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