• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "texture_layer.h"
17 
18 #ifdef USE_M133_SKIA
19 #include "include/gpu/ganesh/GrBackendSurface.h"
20 #include "include/gpu/ganesh/gl/GrGLInterface.h"
21 #else
22 #include "include/gpu/GrBackendSurface.h"
23 #include "include/gpu/gl/GrGLInterface.h"
24 #endif
25 #include <native_buffer.h>
26 #include <render_service_base/include/pipeline/rs_recording_canvas.h>
27 #include <render_service_base/include/property/rs_properties_def.h>
28 #include <render_service_client/core/pipeline/rs_node_map.h>
29 #include <render_service_client/core/transaction/rs_interfaces.h>
30 #include <render_service_client/core/ui/rs_canvas_node.h>
31 #include <render_service_client/core/ui/rs_root_node.h>
32 #include <render_service_client/core/ui/rs_surface_node.h>
33 #include <render_service_client/core/ui/rs_ui_director.h>
34 
35 #include <surface_buffer.h>
36 #include <surface_utils.h>
37 #include <window.h>
38 
39 #include "data_type/constants.h"
40 #include "3d_widget_adapter_log.h"
41 #include "graphics_manager.h"
42 #include "offscreen_context_helper.h"
43 #include "widget_trace.h"
44 
45 struct OH_NativeBuffer;
46 struct NativeWindowBuffer;
47 
48 namespace OHOS {
49 namespace Render3D {
50 
51 struct TextureImage {
TextureImageOHOS::Render3D::TextureImage52     explicit TextureImage(const TextureInfo& textureInfo) : textureInfo_(textureInfo) {}
53     TextureImage() = default;
54     TextureInfo textureInfo_;
55 };
56 
57 class TextureLayerImpl : public TextureLayer {
58 public:
59     explicit TextureLayerImpl(int32_t key);
60     ~TextureLayerImpl();
61 
62     void DestroyRenderTarget() override;
63     TextureInfo GetTextureInfo() override;
64 
65     void SetParent(std::shared_ptr<Rosen::RSNode>& parent) override;
66     TextureInfo OnWindowChange(float offsetX, float offsetY, float width, float height, float scale,
67         bool recreateWindow, SurfaceType surfaceType = SurfaceType::SURFACE_WINDOW) override;
68     TextureInfo OnWindowChange(const WindowChangeInfo& windowChangeInfo) override;
69 
70 private:
71     void CreateNatviceWindowNode(const Rosen::RSSurfaceNodeConfig &surfaceNodeConfig);
72     void* CreateNativeWindow(uint32_t width, uint32_t height);
73     void ConfigWindow(float offsetX, float offsetY, float width, float height, float scale, bool recreateWindow);
74     void ConfigTexture(float width, float height);
75     void RemoveChild();
76 
77     int32_t offsetX_ = 0u;
78     int32_t offsetY_ = 0u;
79     uint32_t width_ = 0u;
80     uint32_t height_ = 0u;
81     int32_t key_ = INT32_MAX;
82     uint32_t transform_ = 0U;
83 
84     std::shared_ptr<Rosen::RSNode> rsNode_ = nullptr;
85     std::shared_ptr<Rosen::RSNode> parent_ = nullptr;
86     sptr<OHOS::Surface> producerSurface_ = nullptr;
87     std::shared_ptr<OHOS::Rosen::RSUIDirector> rsUIDirector_;
88     SurfaceType surface_ = SurfaceType::UNDEFINE;
89     TextureImage image_;
90 };
91 
GetTextureInfo()92 TextureInfo TextureLayerImpl::GetTextureInfo()
93 {
94     return image_.textureInfo_;
95 }
96 
SetParent(std::shared_ptr<Rosen::RSNode> & parent)97 void TextureLayerImpl::SetParent(std::shared_ptr<Rosen::RSNode>& parent)
98 {
99     parent_ = parent;
100     // delete previous rs node reference
101     RemoveChild();
102 
103     if (parent_ && rsNode_) {
104         rsNode_->SetRSUIContext(parent->GetRSUIContext());
105         parent_->AddChild(rsNode_, 0); // second paramenter is added child at the index of parent's children;
106     }
107 }
108 
RemoveChild()109 void TextureLayerImpl::RemoveChild()
110 {
111     if (parent_ && rsNode_) {
112         parent_->RemoveChild(rsNode_);
113     }
114 }
115 
RotationToTransform(uint32_t rotation)116 GraphicTransformType RotationToTransform(uint32_t rotation)
117 {
118     GraphicTransformType transform = GraphicTransformType::GRAPHIC_ROTATE_BUTT;
119     switch (rotation) {
120         case 0: // rotation angle 0 degree
121             transform = GraphicTransformType::GRAPHIC_ROTATE_NONE;
122             break;
123         case 90: // rotation angle 90 degree
124             transform = GraphicTransformType::GRAPHIC_ROTATE_90;
125             break;
126         case 180: // rotation angle 180 degree
127             transform = GraphicTransformType::GRAPHIC_ROTATE_180;
128             break;
129         case 270: // rotation angle 270 degree
130             transform = GraphicTransformType::GRAPHIC_ROTATE_270;
131             break;
132         default:
133             transform = GraphicTransformType::GRAPHIC_ROTATE_NONE;
134             break;
135     }
136     return transform;
137 }
138 
CreateNatviceWindowNode(const Rosen::RSSurfaceNodeConfig & surfaceNodeConfig)139 void TextureLayerImpl::CreateNatviceWindowNode(const Rosen::RSSurfaceNodeConfig &surfaceNodeConfig)
140 {
141     rsUIDirector_ = OHOS::Rosen::RSUIDirector::Create();
142     // Init: The first true indicates that RenderThread is created, and the second true indicates that multiple
143     // instances are used. When multi-instance is not used, each process has a global RSUIDirector. When multi-instance
144     // is used, each instance corresponds to one RSUIDirector.
145     rsUIDirector_->Init(true, false); // the second params need to be true for adapting multi-instances
146     auto rsUIContext = rsUIDirector_->GetRSUIContext();
147     rsNode_ = Rosen::RSSurfaceNode::Create(surfaceNodeConfig, false, rsUIContext);
148 }
149 
CreateNativeWindow(uint32_t width,uint32_t height)150 void* TextureLayerImpl::CreateNativeWindow(uint32_t width, uint32_t height)
151 {
152     std::string bundleName = GraphicsManager::GetInstance().GetHapInfo().bundleName_;
153     struct Rosen::RSSurfaceNodeConfig surfaceNodeConfig;
154     if (bundleName.find("totemweather") != std::string::npos) {
155         surfaceNodeConfig = { .SurfaceNodeName = std::string("SceneViewer Model totemweather") + std::to_string(key_) };
156     } else {
157         surfaceNodeConfig = { .SurfaceNodeName = std::string("SceneViewer Model") + std::to_string(key_) };
158     }
159     CreateNatviceWindowNode(surfaceNodeConfig);
160     if (!rsNode_) {
161         WIDGET_LOGE("Create rs node fail");
162         return nullptr;
163     }
164 
165     auto surfaceNode = OHOS::Rosen::RSBaseNode::ReinterpretCast<OHOS::Rosen::RSSurfaceNode>(rsNode_);
166     surfaceNode->SetFrameGravity(Rosen::Gravity::RESIZE);
167     if (surface_ == SurfaceType::SURFACE_WINDOW) {
168         surfaceNode->SetHardwareEnabled(true);
169     }
170     if (surface_ == SurfaceType::SURFACE_TEXTURE) {
171         surfaceNode->SetHardwareEnabled(false);
172     }
173 
174     if (bundleName.find("sceneboard") != std::string::npos) {
175         surfaceNode->SetHardwareEnabled(true); // SetHardwareEnabled as a flag enable gpu bilinear interpolation
176     } else if (bundleName.find("totemweather") != std::string::npos) {
177         surfaceNode->SetHardwareEnabled(true);
178         uint32_t argbWhite = 0xFFFFFFFF;  // set a white background color for dss
179         surfaceNode->SetBackgroundColor(argbWhite);
180     }
181 
182     producerSurface_ = surfaceNode->GetSurface();
183     if (!producerSurface_) {
184         WIDGET_LOGE("Get producer surface fail");
185         return nullptr;
186     }
187 
188     auto transform = RotationToTransform(transform_);
189     producerSurface_->SetTransformHint(transform);
190 
191     auto ret = SurfaceUtils::GetInstance()->Add(producerSurface_->GetUniqueId(), producerSurface_);
192     if (ret != SurfaceError::SURFACE_ERROR_OK) {
193         WIDGET_LOGE("add surface error");
194         return nullptr;
195     }
196 
197     producerSurface_->SetQueueSize(5); // 5 seems ok
198     producerSurface_->SetUserData("SURFACE_STRIDE_ALIGNMENT", "8");
199     producerSurface_->SetUserData("SURFACE_FORMAT", std::to_string(GRAPHIC_PIXEL_FMT_RGBA_8888));
200     producerSurface_->SetUserData("SURFACE_WIDTH", std::to_string(width));
201     producerSurface_->SetUserData("SURFACE_HEIGHT", std::to_string(height));
202     auto window = CreateNativeWindowFromSurface(&producerSurface_);
203     if (!window) {
204         WIDGET_LOGE("CreateNativeWindowFromSurface failed");
205     }
206 
207     return reinterpret_cast<void *>(window);
208 }
209 
ConfigWindow(float offsetX,float offsetY,float width,float height,float scale,bool recreateWindow)210 void TextureLayerImpl::ConfigWindow(float offsetX, float offsetY, float width, float height, float scale,
211     bool recreateWindow)
212 {
213     float widthScale = image_.textureInfo_.widthScale_;
214     float heightScale = image_.textureInfo_.heightScale_;
215     if (surface_ == SurfaceType::SURFACE_WINDOW || surface_ == SurfaceType::SURFACE_TEXTURE) {
216         image_.textureInfo_.recreateWindow_ = recreateWindow;
217 
218         if (!image_.textureInfo_.nativeWindow_) {
219             image_.textureInfo_.nativeWindow_ = reinterpret_cast<void *>(CreateNativeWindow(
220                 static_cast<uint32_t>(width * widthScale), static_cast<uint32_t>(height * heightScale)));
221         }
222         // need check recreate window flag
223         NativeWindowHandleOpt(reinterpret_cast<OHNativeWindow *>(image_.textureInfo_.nativeWindow_),
224             SET_BUFFER_GEOMETRY, static_cast<uint32_t>(width * scale * widthScale),
225             static_cast<uint32_t>(height * scale * heightScale));
226         if (rsNode_ == nullptr) {
227             WIDGET_LOGE("TextureLayer ConfigWindow rsNode_ is nullptr.");
228             return;
229         }
230         rsNode_->SetBounds(offsetX, offsetY, width, height);
231     }
232 }
233 
OnWindowChange(float offsetX,float offsetY,float width,float height,float scale,bool recreateWindow,SurfaceType surfaceType)234 TextureInfo TextureLayerImpl::OnWindowChange(float offsetX, float offsetY, float width, float height, float scale,
235     bool recreateWindow, SurfaceType surfaceType)
236 {
237     // no DestroyRenderTarget will not cause memory leak / render issue
238     surface_ = surfaceType;
239     offsetX_ = offsetX;
240     offsetY_ = offsetY;
241 
242     image_.textureInfo_.width_ = static_cast<uint32_t>(width);
243     image_.textureInfo_.height_ = static_cast<uint32_t>(height);
244 
245     ConfigWindow(offsetX, offsetY, width, height, scale, recreateWindow);
246 
247     WIDGET_LOGD("TextureLayer OnWindowChange offsetX %f, offsetY %f, width %d, height %d, float scale %f,"
248         "recreateWindow %d window empty %d", offsetX, offsetY, image_.textureInfo_.width_, image_.textureInfo_.height_,
249         scale, recreateWindow, image_.textureInfo_.nativeWindow_ == nullptr);
250     return image_.textureInfo_;
251 }
252 
OnWindowChange(const WindowChangeInfo & windowChangeInfo)253 TextureInfo TextureLayerImpl::OnWindowChange(const WindowChangeInfo& windowChangeInfo)
254 {
255     // no DestroyRenderTarget will not cause memory leak / render issue
256     surface_ = windowChangeInfo.surfaceType;
257     offsetX_ = (int)windowChangeInfo.offsetX;
258     offsetY_ = (int)windowChangeInfo.offsetY;
259     transform_ = windowChangeInfo.transformType;
260 
261     image_.textureInfo_.width_ = static_cast<uint32_t>(windowChangeInfo.width);
262     image_.textureInfo_.height_ = static_cast<uint32_t>(windowChangeInfo.height);
263 
264     image_.textureInfo_.widthScale_ = static_cast<float>(windowChangeInfo.widthScale);
265     image_.textureInfo_.heightScale_ = static_cast<float>(windowChangeInfo.heightScale);
266 
267     ConfigWindow(windowChangeInfo.offsetX, windowChangeInfo.offsetY, windowChangeInfo.width,
268         windowChangeInfo.height, windowChangeInfo.scale, windowChangeInfo.recreateWindow);
269 
270     return image_.textureInfo_;
271 }
272 
DestroyRenderTarget()273 void TextureLayerImpl::DestroyRenderTarget()
274 {
275     // window release
276     RemoveChild();
277     // clean cache routine should be in rs node deconstruct
278     auto rsSurfaceNode = OHOS::Rosen::RSBaseNode::ReinterpretCast<OHOS::Rosen::RSSurfaceNode>(rsNode_);
279     if (rsSurfaceNode && rsSurfaceNode->GetSurface()) {
280         rsSurfaceNode->GetSurface()->CleanCache(true);
281     }
282 
283     rsNode_ = nullptr;
284     parent_ = nullptr;
285     image_.textureInfo_ = {};
286 }
287 
TextureLayerImpl(int32_t key)288 TextureLayerImpl::TextureLayerImpl(int32_t key) : key_(key)
289 {
290 }
291 
~TextureLayerImpl()292 TextureLayerImpl::~TextureLayerImpl()
293 {
294     // explicit release resource before destructor
295 }
296 
297 // old implement
GetTextureInfo()298 TextureInfo TextureLayer::GetTextureInfo()
299 {
300     return textureLayer_->GetTextureInfo();
301 }
302 
SetParent(std::shared_ptr<Rosen::RSNode> & parent)303 void TextureLayer::SetParent(std::shared_ptr<Rosen::RSNode>& parent)
304 {
305     textureLayer_->SetParent(parent);
306 }
307 
OnWindowChange(float offsetX,float offsetY,float width,float height,float scale,bool recreateWindow,SurfaceType surfaceType)308 TextureInfo TextureLayer::OnWindowChange(float offsetX, float offsetY, float width, float height, float scale,
309     bool recreateWindow, SurfaceType surfaceType)
310 {
311     return textureLayer_->OnWindowChange(offsetX, offsetY, width, height, scale, recreateWindow, surfaceType);
312 }
313 
OnWindowChange(const WindowChangeInfo & windowChangeInfo)314 TextureInfo TextureLayer::OnWindowChange(const WindowChangeInfo& windowChangeInfo)
315 {
316     return textureLayer_->OnWindowChange(windowChangeInfo);
317 }
318 
DestroyRenderTarget()319 void TextureLayer::DestroyRenderTarget()
320 {
321     textureLayer_->DestroyRenderTarget();
322 }
323 
TextureLayer(int32_t key)324 TextureLayer::TextureLayer(int32_t key)
325 {
326     textureLayer_ = std::make_shared<TextureLayerImpl>(key);
327 }
328 
~TextureLayer()329 TextureLayer::~TextureLayer()
330 {
331     // explicit release resource before destructor
332 }
333 
334 } // Render3D
335 } // OHOS
336