• 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 #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