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