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 #include <include/gpu/GrBackendSurface.h>
19 #ifndef NEW_SKIA
20 #include <include/gpu/GrContext.h>
21 #else
22 #include <include/gpu/GrDirectContext.h>
23 #endif
24 #include <include/gpu/gl/GrGLInterface.h>
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
34 #include <surface_buffer.h>
35 #include <surface_utils.h>
36 #include <window.h>
37
38 #include "data_type/constants.h"
39 #include "3d_widget_adapter_log.h"
40 #include "graphics_manager.h"
41 #include "offscreen_context_helper.h"
42 #include "widget_trace.h"
43
44 struct OH_NativeBuffer;
45 struct NativeWindowBuffer;
46
47 namespace OHOS {
48 namespace Render3D {
49
50 struct TextureImage {
TextureImageOHOS::Render3D::TextureImage51 explicit TextureImage(const TextureInfo& textureInfo) : textureInfo_(textureInfo) {}
52 TextureImage() = default;
53 TextureInfo textureInfo_;
54 };
55
56 class TextureLayerImpl : public TextureLayer {
57 public:
58 explicit TextureLayerImpl(int32_t key);
59 ~TextureLayerImpl();
60
61 void DestroyRenderTarget() override;
62 TextureInfo GetTextureInfo() override;
63
64 void SetParent(std::shared_ptr<Rosen::RSNode>& parent) override;
65 TextureInfo OnWindowChange(float offsetX, float offsetY, float width, float height, float scale,
66 bool recreateWindow, SurfaceType surfaceType = SurfaceType::SURFACE_WINDOW) override;
67 TextureInfo OnWindowChange(const WindowChangeInfo& windowChangeInfo) override;
68
69 private:
70 void* CreateNativeWindow(uint32_t width, uint32_t height);
71 void ConfigWindow(float offsetX, float offsetY, float width, float height, float scale, bool recreateWindow);
72 void ConfigTexture(float width, float height);
73 void RemoveChild();
74
75 int32_t offsetX_ = 0u;
76 int32_t offsetY_ = 0u;
77 uint32_t width_ = 0u;
78 uint32_t height_ = 0u;
79 int32_t key_ = INT32_MAX;
80 uint32_t transform_ = 0U;
81
82 std::shared_ptr<Rosen::RSNode> rsNode_ = nullptr;
83 std::shared_ptr<Rosen::RSNode> parent_ = nullptr;
84 sptr<OHOS::Surface> producerSurface_ = nullptr;
85 SurfaceType surface_ = SurfaceType::UNDEFINE;
86 TextureImage image_;
87 };
88
GetTextureInfo()89 TextureInfo TextureLayerImpl::GetTextureInfo()
90 {
91 return image_.textureInfo_;
92 }
93
SetParent(std::shared_ptr<Rosen::RSNode> & parent)94 void TextureLayerImpl::SetParent(std::shared_ptr<Rosen::RSNode>& parent)
95 {
96 parent_ = parent;
97 // delete previous rs node reference
98 RemoveChild();
99
100 if (parent_ && rsNode_) {
101 parent_->AddChild(rsNode_, 0); // second paramenter is added child at the index of parent's children;
102 }
103 }
104
RemoveChild()105 void TextureLayerImpl::RemoveChild()
106 {
107 if (parent_ && rsNode_) {
108 parent_->RemoveChild(rsNode_);
109 }
110 }
111
RotationToTransform(uint32_t rotation)112 GraphicTransformType RotationToTransform(uint32_t rotation)
113 {
114 GraphicTransformType transform = GraphicTransformType::GRAPHIC_ROTATE_BUTT;
115 switch (rotation) {
116 case 0: // rotation angle 0 degree
117 transform = GraphicTransformType::GRAPHIC_ROTATE_NONE;
118 break;
119 case 90: // rotation angle 90 degree
120 transform = GraphicTransformType::GRAPHIC_ROTATE_90;
121 break;
122 case 180: // rotation angle 180 degree
123 transform = GraphicTransformType::GRAPHIC_ROTATE_180;
124 break;
125 case 270: // rotation angle 270 degree
126 transform = GraphicTransformType::GRAPHIC_ROTATE_270;
127 break;
128 default:
129 transform = GraphicTransformType::GRAPHIC_ROTATE_NONE;
130 break;
131 }
132 return transform;
133 }
134
CreateNativeWindow(uint32_t width,uint32_t height)135 void* TextureLayerImpl::CreateNativeWindow(uint32_t width, uint32_t height)
136 {
137 std::string bundleName = GraphicsManager::GetInstance().GetHapInfo().bundleName_;
138 struct Rosen::RSSurfaceNodeConfig surfaceNodeConfig;
139 if (bundleName.find("totemweather") != std::string::npos) {
140 surfaceNodeConfig = { .SurfaceNodeName = std::string("SceneViewer Model totemweather") + std::to_string(key_) };
141 } else {
142 surfaceNodeConfig = { .SurfaceNodeName = std::string("SceneViewer Model") + std::to_string(key_) };
143 }
144
145 rsNode_ = Rosen::RSSurfaceNode::Create(surfaceNodeConfig, false);
146 if (!rsNode_) {
147 WIDGET_LOGE("Create rs node fail");
148 return nullptr;
149 }
150
151 auto surfaceNode = OHOS::Rosen::RSBaseNode::ReinterpretCast<OHOS::Rosen::RSSurfaceNode>(rsNode_);
152 surfaceNode->SetFrameGravity(Rosen::Gravity::RESIZE);
153 if (surface_ == SurfaceType::SURFACE_WINDOW) {
154 surfaceNode->SetHardwareEnabled(true);
155 }
156 if (surface_ == SurfaceType::SURFACE_TEXTURE) {
157 surfaceNode->SetHardwareEnabled(false);
158 }
159
160 if (bundleName.find("sceneboard") != std::string::npos) {
161 surfaceNode->SetHardwareEnabled(true); // SetHardwareEnabled as a flag enable gpu bilinear interpolation
162 } else if (bundleName.find("totemweather") != std::string::npos) {
163 surfaceNode->SetHardwareEnabled(true);
164 uint32_t argbWhite = 0xFFFFFFFF; // set a white background color for dss
165 surfaceNode->SetBackgroundColor(argbWhite);
166 }
167
168 producerSurface_ = surfaceNode->GetSurface();
169 if (!producerSurface_) {
170 WIDGET_LOGE("Get producer surface fail");
171 return nullptr;
172 }
173
174 auto transform = RotationToTransform(transform_);
175 producerSurface_->SetTransformHint(transform);
176
177 auto ret = SurfaceUtils::GetInstance()->Add(producerSurface_->GetUniqueId(), producerSurface_);
178 if (ret != SurfaceError::SURFACE_ERROR_OK) {
179 WIDGET_LOGE("add surface error");
180 return nullptr;
181 }
182
183 producerSurface_->SetQueueSize(5); // 5 seems ok
184 producerSurface_->SetUserData("SURFACE_STRIDE_ALIGNMENT", "8");
185 producerSurface_->SetUserData("SURFACE_FORMAT", std::to_string(GRAPHIC_PIXEL_FMT_RGBA_8888));
186 producerSurface_->SetUserData("SURFACE_WIDTH", std::to_string(width));
187 producerSurface_->SetUserData("SURFACE_HEIGHT", std::to_string(height));
188 auto window = CreateNativeWindowFromSurface(&producerSurface_);
189 if (!window) {
190 WIDGET_LOGE("CreateNativeWindowFromSurface failed");
191 }
192
193 return reinterpret_cast<void *>(window);
194 }
195
ConfigWindow(float offsetX,float offsetY,float width,float height,float scale,bool recreateWindow)196 void TextureLayerImpl::ConfigWindow(float offsetX, float offsetY, float width, float height, float scale,
197 bool recreateWindow)
198 {
199 float widthScale = image_.textureInfo_.widthScale_;
200 float heightScale = image_.textureInfo_.heightScale_;
201 if (surface_ == SurfaceType::SURFACE_WINDOW || surface_ == SurfaceType::SURFACE_TEXTURE) {
202 image_.textureInfo_.recreateWindow_ = recreateWindow;
203
204 if (!image_.textureInfo_.nativeWindow_) {
205 image_.textureInfo_.nativeWindow_ = reinterpret_cast<void *>(CreateNativeWindow(
206 static_cast<uint32_t>(width * widthScale), static_cast<uint32_t>(height * heightScale)));
207 }
208 // need check recreate window flag
209 NativeWindowHandleOpt(reinterpret_cast<OHNativeWindow *>(image_.textureInfo_.nativeWindow_),
210 SET_BUFFER_GEOMETRY, static_cast<uint32_t>(width * scale * widthScale),
211 static_cast<uint32_t>(height * scale * heightScale));
212 if (rsNode_ == nullptr) {
213 WIDGET_LOGE("TextureLayer ConfigWindow rsNode_ is nullptr.");
214 return;
215 }
216 rsNode_->SetBounds(offsetX, offsetY, width, height);
217 }
218 }
219
OnWindowChange(float offsetX,float offsetY,float width,float height,float scale,bool recreateWindow,SurfaceType surfaceType)220 TextureInfo TextureLayerImpl::OnWindowChange(float offsetX, float offsetY, float width, float height, float scale,
221 bool recreateWindow, SurfaceType surfaceType)
222 {
223 // no DestroyRenderTarget will not cause memory leak / render issue
224 surface_ = surfaceType;
225 offsetX_ = offsetX;
226 offsetY_ = offsetY;
227
228 image_.textureInfo_.width_ = static_cast<uint32_t>(width);
229 image_.textureInfo_.height_ = static_cast<uint32_t>(height);
230
231 ConfigWindow(offsetX, offsetY, width, height, scale, recreateWindow);
232
233 WIDGET_LOGD("TextureLayer OnWindowChange offsetX %f, offsetY %f, width %d, height %d, float scale %f,"
234 "recreateWindow %d window empty %d", offsetX, offsetY, image_.textureInfo_.width_, image_.textureInfo_.height_,
235 scale, recreateWindow, image_.textureInfo_.nativeWindow_ == nullptr);
236 return image_.textureInfo_;
237 }
238
OnWindowChange(const WindowChangeInfo & windowChangeInfo)239 TextureInfo TextureLayerImpl::OnWindowChange(const WindowChangeInfo& windowChangeInfo)
240 {
241 // no DestroyRenderTarget will not cause memory leak / render issue
242 surface_ = windowChangeInfo.surfaceType;
243 offsetX_ = (int)windowChangeInfo.offsetX;
244 offsetY_ = (int)windowChangeInfo.offsetY;
245 transform_ = windowChangeInfo.transformType;
246
247 image_.textureInfo_.width_ = static_cast<uint32_t>(windowChangeInfo.width);
248 image_.textureInfo_.height_ = static_cast<uint32_t>(windowChangeInfo.height);
249
250 image_.textureInfo_.widthScale_ = static_cast<float>(windowChangeInfo.widthScale);
251 image_.textureInfo_.heightScale_ = static_cast<float>(windowChangeInfo.heightScale);
252
253 ConfigWindow(windowChangeInfo.offsetX, windowChangeInfo.offsetY, windowChangeInfo.width,
254 windowChangeInfo.height, windowChangeInfo.scale, windowChangeInfo.recreateWindow);
255
256 return image_.textureInfo_;
257 }
258
DestroyRenderTarget()259 void TextureLayerImpl::DestroyRenderTarget()
260 {
261 // window release
262 RemoveChild();
263 rsNode_ = nullptr;
264 parent_ = nullptr;
265 image_.textureInfo_ = {};
266 }
267
TextureLayerImpl(int32_t key)268 TextureLayerImpl::TextureLayerImpl(int32_t key) : key_(key)
269 {
270 }
271
~TextureLayerImpl()272 TextureLayerImpl::~TextureLayerImpl()
273 {
274 // explicit release resource before destructor
275 }
276
277 // old implement
GetTextureInfo()278 TextureInfo TextureLayer::GetTextureInfo()
279 {
280 return textureLayer_->GetTextureInfo();
281 }
282
SetParent(std::shared_ptr<Rosen::RSNode> & parent)283 void TextureLayer::SetParent(std::shared_ptr<Rosen::RSNode>& parent)
284 {
285 textureLayer_->SetParent(parent);
286 }
287
OnWindowChange(float offsetX,float offsetY,float width,float height,float scale,bool recreateWindow,SurfaceType surfaceType)288 TextureInfo TextureLayer::OnWindowChange(float offsetX, float offsetY, float width, float height, float scale,
289 bool recreateWindow, SurfaceType surfaceType)
290 {
291 return textureLayer_->OnWindowChange(offsetX, offsetY, width, height, scale, recreateWindow, surfaceType);
292 }
293
OnWindowChange(const WindowChangeInfo & windowChangeInfo)294 TextureInfo TextureLayer::OnWindowChange(const WindowChangeInfo& windowChangeInfo)
295 {
296 return textureLayer_->OnWindowChange(windowChangeInfo);
297 }
298
DestroyRenderTarget()299 void TextureLayer::DestroyRenderTarget()
300 {
301 textureLayer_->DestroyRenderTarget();
302 }
303
TextureLayer(int32_t key)304 TextureLayer::TextureLayer(int32_t key)
305 {
306 textureLayer_ = std::make_shared<TextureLayerImpl>(key);
307 }
308
~TextureLayer()309 TextureLayer::~TextureLayer()
310 {
311 // explicit release resource before destructor
312 }
313
314 } // Render3D
315 } // OHOS
316