/* * Copyright (C) 2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "texture_layer.h" #include #include #include #include #include #include #include #include #include #include #include #include "data_type/constants.h" #include "3d_widget_adapter_log.h" #include "graphics_manager.h" #include "offscreen_context_helper.h" #include "widget_trace.h" namespace OHOS { namespace Render3D { struct TextureImage { explicit TextureImage(const TextureInfo& textureInfo): textureInfo_(textureInfo) {} TextureImage() = default; TextureInfo textureInfo_; }; class TextureLayerImpl : public TextureLayer { public: explicit TextureLayerImpl(int32_t key); virtual ~TextureLayerImpl(); void DestroyRenderTarget() override; TextureInfo GetTextureInfo() override; void SetParent(std::shared_ptr& parent) override; TextureInfo OnWindowChange(float offsetX, float offsetY, float width, float height, float scale, bool recreateWindow, SurfaceType surfaceType = SurfaceType::SURFACE_WINDOW) override; TextureInfo OnWindowChange(const WindowChangeInfo& windowChangeInfo) override; private: void* CreateNativeWindow(uint32_t width, uint32_t height); void ConfigWindow(float offsetX, float offsetY, float width, float height, float scale, bool recreateWindow); void ConfigTexture(float width, float height); void RemoveChild(); int32_t offsetX_ = 0u; int32_t offsetY_ = 0u; int32_t width_ = 0u; int32_t height_ = 0u; int32_t key_ = INT32_MAX; uint32_t transform_ = 0U; std::shared_ptr rsNode_ = nullptr; std::shared_ptr parent_ = nullptr; sptr producerSurface_ = nullptr; SurfaceType surface_ = SurfaceType::UNDEFINE; TextureImage image_; }; TextureInfo TextureLayerImpl::GetTextureInfo() { return image_.textureInfo_; } void TextureLayerImpl::SetParent(std::shared_ptr& parent) { parent_ = parent; // delete previous rs node reference RemoveChild(); if (parent_ && rsNode_) { parent_->AddChild(rsNode_, 0); // second paramenter is added child at the index of parent's children; } } void TextureLayerImpl::RemoveChild() { if (parent_ && rsNode_) { parent_->RemoveChild(rsNode_); } } GraphicTransformType RotationToTransform(uint32_t rotation) { GraphicTransformType transform = GraphicTransformType::GRAPHIC_ROTATE_BUTT; switch (rotation) { case 0: transform = GraphicTransformType::GRAPHIC_ROTATE_NONE; break; case 90: transform = GraphicTransformType::GRAPHIC_ROTATE_90; break; case 180: transform = GraphicTransformType::GRAPHIC_ROTATE_180; break; case 270: transform = GraphicTransformType::GRAPHIC_ROTATE_270; break; default: transform = GraphicTransformType::GRAPHIC_ROTATE_NONE; break; } return transform; } void* TextureLayerImpl::CreateNativeWindow(uint32_t width, uint32_t height) { std::string bundleName = GraphicsManager::GetInstance().GetHapInfo().bundleName_; struct Rosen::RSSurfaceNodeConfig surfaceNodeConfig; if (bundleName.find("totemweather") != std::string::npos) { surfaceNodeConfig = {.SurfaceNodeName = std::string("SceneViewer Model totemweather") + std::to_string(key_)}; } else { surfaceNodeConfig = {.SurfaceNodeName = std::string("SceneViewer Model") + std::to_string(key_)}; } rsNode_ = Rosen::RSSurfaceNode::Create(surfaceNodeConfig, false); if (!rsNode_) { WIDGET_LOGE("Create rs node fail"); return nullptr; } auto surfaceNode = OHOS::Rosen::RSBaseNode::ReinterpretCast(rsNode_); surfaceNode->SetFrameGravity(Rosen::Gravity::RESIZE); if (surface_ == SurfaceType::SURFACE_WINDOW) { surfaceNode->SetHardwareEnabled(true); } if (surface_ == SurfaceType::SURFACE_TEXTURE) { surfaceNode->SetHardwareEnabled(false); } std::string hapPath = GraphicsManager::GetInstance().GetHapInfo().hapPath_; if (hapPath.find("SceneBoard_MetaBallsTurbo") != std::string::npos) { surfaceNode->SetHardwareEnabled(true); } else if (hapPath.find("HwWeather") != std::string::npos) { surfaceNode->SetHardwareEnabled(true); uint32_t argbWhite = 0xFFFFFFFF; // set a white background color for dss surfaceNode->SetBackgroundColor(argbWhite); } producerSurface_ = surfaceNode->GetSurface(); if (!producerSurface_) { WIDGET_LOGE("Get producer surface fail"); return nullptr; } auto transform = RotationToTransform(transform_); producerSurface_->SetTransformHint(transform); auto ret = SurfaceUtils::GetInstance()->Add(producerSurface_->GetUniqueId(), producerSurface_); if (ret != SurfaceError::SURFACE_ERROR_OK) { WIDGET_LOGE("add surface error"); return nullptr; } producerSurface_->SetQueueSize(3); // 3 seems ok producerSurface_->SetUserData("SURFACE_STRIDE_ALIGNMENT", "8"); producerSurface_->SetUserData("SURFACE_FORMAT", std::to_string(GRAPHIC_PIXEL_FMT_RGBA_8888)); producerSurface_->SetUserData("SURFACE_WIDTH", std::to_string(width)); producerSurface_->SetUserData("SURFACE_HEIGHT", std::to_string(height)); auto window = CreateNativeWindowFromSurface(&producerSurface_); return reinterpret_cast(window); } void TextureLayerImpl::ConfigWindow(float offsetX, float offsetY, float width, float height, float scale, bool recreateWindow) { float widthScale = image_.textureInfo_.widthScale_; float heightScale = image_.textureInfo_.heightScale_; if (surface_ == SurfaceType::SURFACE_WINDOW || surface_ == SurfaceType::SURFACE_TEXTURE) { image_.textureInfo_.recreateWindow_ = recreateWindow; if (!image_.textureInfo_.nativeWindow_) { image_.textureInfo_.nativeWindow_ = reinterpret_cast(CreateNativeWindow( static_cast(width * widthScale), static_cast(height * heightScale))); } // need check recreate window flag NativeWindowHandleOpt(reinterpret_cast(image_.textureInfo_.nativeWindow_), SET_BUFFER_GEOMETRY, static_cast(width * scale * widthScale), static_cast(height * scale * heightScale)); rsNode_->SetBounds(offsetX, offsetY, width, height); } } TextureInfo TextureLayerImpl::OnWindowChange(float offsetX, float offsetY, float width, float height, float scale, bool recreateWindow, SurfaceType surfaceType) { DestroyRenderTarget(); surface_ = surfaceType; offsetX_ = offsetX; offsetY_ = offsetY; image_.textureInfo_.width_ = static_cast(width); image_.textureInfo_.height_ = static_cast(height); image_.textureInfo_.widthScale_ = scale; image_.textureInfo_.heightScale_ = scale; ConfigWindow(offsetX, offsetY, width, height, scale, recreateWindow); WIDGET_LOGD("TextureLayer OnWindowChange offsetX %f, offsetY %f, width %d, height %d, float scale %f," "recreateWindow %d window empty %d", offsetX, offsetY, image_.textureInfo_.width_, image_.textureInfo_.height_, scale, recreateWindow, image_.textureInfo_.nativeWindow_ == nullptr); return image_.textureInfo_; } TextureInfo TextureLayerImpl::OnWindowChange(const WindowChangeInfo& windowChangeInfo) { DestroyRenderTarget(); surface_ = windowChangeInfo.surfaceType; offsetX_ = (int)windowChangeInfo.offsetX; offsetY_ = (int)windowChangeInfo.offsetY; transform_ = windowChangeInfo.transformType; image_.textureInfo_.width_ = static_cast(windowChangeInfo.width); image_.textureInfo_.height_ = static_cast(windowChangeInfo.height); image_.textureInfo_.widthScale_ = static_cast(windowChangeInfo.widthScale); image_.textureInfo_.heightScale_ = static_cast(windowChangeInfo.heightScale); ConfigWindow(windowChangeInfo.offsetX, windowChangeInfo.offsetY, windowChangeInfo.width, windowChangeInfo.height, windowChangeInfo.scale, windowChangeInfo.recreateWindow); return image_.textureInfo_; } void TextureLayerImpl::DestroyRenderTarget() { // window release RemoveChild(); rsNode_ = nullptr; parent_ = nullptr; image_.textureInfo_ = {}; } TextureLayerImpl::TextureLayerImpl(int32_t key): key_(key) { } TextureLayerImpl::~TextureLayerImpl() { // explicity release resource before destructor } TextureInfo TextureLayer::GetTextureInfo() { return textureLayer_->GetTextureInfo(); } void TextureLayer::SetParent(std::shared_ptr& parent) { return textureLayer_->SetParent(parent); } TextureInfo TextureLayer::OnWindowChange(float offsetX, float offsetY, float width, float height, float scale, bool recreateWindow, SurfaceType surfaceType) { return textureLayer_->OnWindowChange(offsetX, offsetY, width, height, scale, recreateWindow, surfaceType); } TextureInfo TextureLayer::OnWindowChange(const WindowChangeInfo& windowChangeInfo) { return textureLayer_->OnWindowChange(windowChangeInfo); } void TextureLayer::DestroyRenderTarget() { textureLayer_->DestroyRenderTarget(); } TextureLayer::TextureLayer(int32_t key) { textureLayer_ = std::make_shared(key); } TextureLayer::~TextureLayer() { // explicit release resource before destructor } } // Render3D } // OHOS