• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 "core/components_ng/pattern/model/model_adapter_wrapper.h"
17 
18 #include <EGL/egl.h>
19 #include "foundation/graphic/graphic_3d/3d_widget_adapter/include/graphics_task.h"
20 #include "foundation/graphic/graphic_3d/3d_widget_adapter/include/ohos/graphics_manager.h"
21 #include "render_service_client/core/ui/rs_ui_director.h"
22 #include "render_service_client/core/ui/rs_ui_share_context.h"
23 
24 namespace OHOS::Ace::NG {
25 
ModelAdapterWrapper(uint32_t key)26 ModelAdapterWrapper::ModelAdapterWrapper(uint32_t key) : key_(key)
27 {
28     touchHandler_ = MakeRefPtr<ModelTouchHandler>();
29     touchHandler_->SetCameraEventCallback([weak = WeakClaim(this)]
30         (const OHOS::Render3D::SceneViewerTouchEvent& event) {
31         auto adapter = weak.Upgrade();
32         CHECK_NULL_VOID(adapter);
33         adapter->HandleCameraMove(event);
34     });
35 
36 #if MULTI_ECS_UPDATE_AT_ONCE
37     RefPtr<PipelineBase> pipeline = PipelineBase::GetCurrentContext();
38     CHECK_NULL_VOID(pipeline);
39     if (pipeline) {
40         OHOS::Render3D::GraphicsManager::GetInstance().AttachContext(pipeline);
41     } else {
42         LOGE("MODEL_NG: pipeline context is null");
43     }
44 #endif
45 }
46 
OnPaint(const RefPtr<ModelPaintProperty> & modelPaintProperty)47 void ModelAdapterWrapper::OnPaint(const RefPtr<ModelPaintProperty>& modelPaintProperty)
48 {
49     auto properties = ExtractPaintProperties(modelPaintProperty);
50     if (modelPaintProperty->NeedsCameraSetup()) {
51         UpdateCamera(properties);
52     }
53     if (modelPaintProperty->NeedsLightsSetup()) {
54         UpdateLights(properties);
55     }
56     if (modelPaintProperty->NeedsAnimationsSetup()) {
57         UpdateGLTFAnimations(properties);
58     }
59     if (modelPaintProperty->NeedsGeometriesSetup()) {
60         UpdateGeometries(properties);
61     }
62     if (modelPaintProperty->NeedsCustomRendersSetup()) {
63         UpdateCustomRenders(properties);
64     }
65     if (modelPaintProperty->NeedsShaderPathSetup()) {
66         UpdateShaderPath(properties);
67     }
68     if (modelPaintProperty->NeedsImageTexturePathsSetup()) {
69         UpdateImageTexturePaths(properties);
70     }
71     if (modelPaintProperty->NeedsShaderInputBuffersSetup()) {
72         UpdateShaderInputBuffers(properties);
73     }
74     DrawFrame();
75 }
76 
UpdateCamera(const SceneViewerAdapterProperties & properties)77 void ModelAdapterWrapper::UpdateCamera(const SceneViewerAdapterProperties& properties)
78 {
79     LOGD("MODEL_NG: ModelAdapterWrapper::UpdateCamera()");
80 #if MULTI_ECS_UPDATE_AT_ONCE
81     OHOS::Render3D::GraphicsTask::GetInstance().PushSyncMessage([weak = WeakClaim(this), &properties] {
82 #else
83     OHOS::Render3D::GraphicsTask::GetInstance().PushSyncMessage([weak = WeakClaim(this), &properties] {
84 #endif
85         auto adapter = weak.Upgrade();
86         CHECK_NULL_VOID(adapter);
87         adapter->sceneViewerAdapter_->SetUpCameraTransform(properties.cameraPosition_, properties.cameraLookAt_,
88             properties.cameraUp_, properties.cameraRotation_);
89         adapter->sceneViewerAdapter_->SetUpCameraViewProjection(properties.zNear_, properties.zFar_, properties.fov_);
90     });
91 }
92 
93 void ModelAdapterWrapper::UpdateLights(const SceneViewerAdapterProperties& properties)
94 {
95     LOGD("MODEL_NG: ModelAdapterWrapper::UpdateLights()");
96     if (!properties.lights_.empty()) {
97 #if MULTI_ECS_UPDATE_AT_ONCE
98         OHOS::Render3D::GraphicsTask::GetInstance().PushSyncMessage([weak = WeakClaim(this), &properties] {
99 #else
100         OHOS::Render3D::GraphicsTask::GetInstance().PushSyncMessage([weak = WeakClaim(this), &properties] {
101 #endif
102             auto adapter = weak.Upgrade();
103             CHECK_NULL_VOID(adapter);
104             adapter->sceneViewerAdapter_->AddLights(properties.lights_);
105             adapter->sceneViewerAdapter_->CreateLight();
106         });
107     }
108 }
109 
110 void ModelAdapterWrapper::UpdateGLTFAnimations(const SceneViewerAdapterProperties& properties)
111 {
112     LOGD("MODEL_NG: ModelAdapterWrapper::UpdateGLTFAnimations() -> %zu", properties.animations_.size());
113     if (!properties.animations_.empty()) {
114 #if MULTI_ECS_UPDATE_AT_ONCE
115         OHOS::Render3D::GraphicsTask::GetInstance().PushSyncMessage([weak = WeakClaim(this), &properties] {
116 #else
117         OHOS::Render3D::GraphicsTask::GetInstance().PushSyncMessage([weak = WeakClaim(this), &properties] {
118 #endif
119             auto adapter = weak.Upgrade();
120             CHECK_NULL_VOID(adapter);
121             adapter->sceneViewerAdapter_->UpdateGLTFAnimations(properties.animations_);
122         });
123     }
124 }
125 
126 void ModelAdapterWrapper::UpdateGeometries(const SceneViewerAdapterProperties& properties)
127 {
128     LOGD("MODEL_NG: ModelAdapterWrapper::UpdateGeometries() -> %zu", properties.geometries_.size());
129     if (!properties.geometries_.empty()) {
130 #if MULTI_ECS_UPDATE_AT_ONCE
131         OHOS::Render3D::GraphicsTask::GetInstance().PushSyncMessage([weak = WeakClaim(this), &properties] {
132 #else
133         OHOS::Render3D::GraphicsTask::GetInstance().PushSyncMessage([weak = WeakClaim(this), &properties] {
134 #endif
135             auto adapter = weak.Upgrade();
136             CHECK_NULL_VOID(adapter);
137             adapter->sceneViewerAdapter_->UpdateGeometries(properties.geometries_);
138         });
139     }
140 }
141 
142 void ModelAdapterWrapper::DrawFrame()
143 {
144     ACE_FUNCTION_TRACE();
145     // if open MULTI_ECS_UPDATE_AT_ONCE macro  SetGSVsyncCallback is called on current thread
146     // that means all the 3D engine task should be in syncorinize manner.
147 #if MULTI_ECS_UPDATE_AT_ONCE
148     OHOS::Render3D::GraphicsTask::GetInstance().PushSyncMessage([weak = WeakClaim(this)] {
149 #else
150     // Async painting does not seem to work.
151     OHOS::Render3D::GraphicsTask::GetInstance().PushSyncMessage([weak = WeakClaim(this)] {
152 #endif
153         auto adapter = weak.Upgrade();
154         CHECK_NULL_VOID(adapter);
155         adapter->sceneViewerAdapter_->DrawFrame();
156     });
157 }
158 
159 void ModelAdapterWrapper::OnPaintFinish()
160 {
161     if (callback_) {
162         callback_();
163     }
164 }
165 
166 SkDrawable* ModelAdapterWrapper::GetDrawable(OffsetF offset)
167 {
168     /*
169         Async painting does not seem to work.
170     */
171     CHECK_NULL_RETURN(textureLayer_, nullptr);
172     textureLayer_->SetOffset(offset.GetX(), offset.GetY());
173     ACE_FUNCTION_TRACE();
174 
175     return textureLayer_.get();
176 }
177 
178 std::shared_ptr<OHOS::Render3D::TextureLayer> ModelAdapterWrapper::GetTextureLayer(OffsetF offset)
179 {
180     textureLayer_->SetOffset(offset.GetX(), offset.GetY());
181     return textureLayer_;
182 }
183 
184 void ModelAdapterWrapper::OnMeasureContent(const RefPtr<ModelLayoutProperty>& modelLayoutProperty, SizeF size)
185 {
186     LOGD("MODEL_NG: OnMeasureContent");
187     bool sizeChanged = size_.UpdateSizeWithCheck(size);
188     bool sceneChanged = modelLayoutProperty->NeedsSceneSetup();
189     bool needsSetup = !sceneIsSetUp_ || sceneChanged || sizeChanged;
190 
191     if (IsInitialized() && sceneChanged) {
192         UnloadScene();
193     }
194 
195     if (!IsInitialized()) {
196         Initialize();
197     }
198 
199     if (!IsInitialized()) {
200         // Failed to create TextureLayer or Engine, or Cannot obtain EGL context
201         LOGW("MODEL_NG: OnMeasureContent() - Failed to initialize");
202         return;
203     }
204 
205     if (sizeChanged) {
206         UpdateTextureLayer();
207     }
208 
209     if (needsSetup) {
210         modelLayoutProperty->UpdateNeedsSceneSetup(false);
211         auto properties = ExtractLayoutProperties(modelLayoutProperty);
212         UpdateSceneViewerAdapter(properties);
213     }
214 }
215 
216 void ModelAdapterWrapper::Initialize()
217 {
218     // Obtain EGLContext
219     EGLContext eglContext = GetRenderContext();
220 
221     if (eglContext == EGL_NO_CONTEXT) {
222         LOGW("MODEL_NG: Initialize() - No render context. Start unify rendering");
223     }
224 
225     CreateTextureLayer(eglContext);
226     CreateSceneViewerAdapter(eglContext_);
227 }
228 
229 void ModelAdapterWrapper::CreateSceneViewerAdapter(const EGLContext& eglContext)
230 {
231     sceneViewerAdapter_ = std::make_shared<OHOS::Render3D::SceneViewerAdapter>(GetKey());
232 #if MULTI_ECS_UPDATE_AT_ONCE
233     OHOS::Render3D::GraphicsTask::GetInstance().PushSyncMessage([weak = WeakClaim(this), &eglContext] {
234 #else
235     // init engine in async manner sometimes crash on screen rotation
236     OHOS::Render3D::GraphicsTask::GetInstance().PushSyncMessage([weak = WeakClaim(this), &eglContext] {
237 #endif
238         auto adapter = weak.Upgrade();
239         CHECK_NULL_VOID(adapter);
240         auto& gfxManager = OHOS::Render3D::GraphicsManager::GetInstance();
241         auto &&engine = gfxManager.GetEngine(OHOS::Render3D::EngineFactory::EngineType::LUME, eglContext);
242         LOGD("MODEL_NG: ModelAdapterWrapper::CreateSceneViewerAdapter() init Engine key_ = %d", adapter->GetKey());
243         adapter->sceneViewerAdapter_->SetEngine(std::move(engine));
244     });
245 }
246 
247 void ModelAdapterWrapper::UpdateSceneViewerAdapter(const SceneViewerAdapterProperties& properties)
248 {
249 #if MULTI_ECS_UPDATE_AT_ONCE
250     OHOS::Render3D::GraphicsTask::GetInstance().PushSyncMessage([weak = WeakClaim(this), &properties] {
251 #else
252     OHOS::Render3D::GraphicsTask::GetInstance().PushSyncMessage([weak = WeakClaim(this), &properties] {
253 #endif
254         auto adapter = weak.Upgrade();
255         CHECK_NULL_VOID(adapter);
256         const OHOS::Render3D::TextureInfo& obj = *(adapter->textureInfo_);
257         adapter->sceneViewerAdapter_->SetUpSceneViewer(
258             obj, properties.gltfSrc_, properties.backgroundSrc_, properties.bgType_);
259         LOGD("MODEL_NG: ModelAdapterWrapper::UpdateSceneViewerAdapter() glTFSrc_ %s GetKey() %d",
260             properties.gltfSrc_.c_str(), adapter->GetKey());
261         adapter->sceneIsSetUp_ = true;
262     });
263 }
264 
265 void ModelAdapterWrapper::CreateTextureLayer(const EGLContext& eglContext)
266 {
267     // texture create must in sync manner
268     OHOS::Render3D::GraphicsTask::GetInstance().PushSyncMessage([weak = WeakClaim(this), &eglContext] {
269         auto adapter = weak.Upgrade();
270         CHECK_NULL_VOID(adapter);
271         auto& gfxManager = OHOS::Render3D::GraphicsManager::GetInstance();
272         gfxManager.Register(adapter->GetKey());
273 
274         adapter->eglContext_ = gfxManager.CreateOffScreenContext(eglContext);
275         adapter->textureLayer_ = std::make_shared<OHOS::Render3D::TextureLayer>();
276         auto info = adapter->textureLayer_->CreateRenderTarget(adapter->size_.Width(), adapter->size_.Height());
277         adapter->textureInfo_ = std::make_shared<OHOS::Render3D::TextureInfo>(std::move(info));
278         adapter->textureLayer_->SetTextureInfo(info);
279     });
280 }
281 
282 void ModelAdapterWrapper::UpdateTextureLayer()
283 {
284     CHECK_NULL_VOID(textureLayer_);
285     textureLayer_->SetWH(size_.Width(), size_.Height());
286 }
287 
288 void ModelAdapterWrapper::UnloadScene()
289 {
290 #if MULTI_ECS_UPDATE_AT_ONCE
291     OHOS::Render3D::GraphicsTask::GetInstance().PushSyncMessage([weak = WeakClaim(this)] {
292 #else
293     OHOS::Render3D::GraphicsTask::GetInstance().PushSyncMessage([weak = WeakClaim(this)] {
294 #endif
295         auto adapter = weak.Upgrade();
296         CHECK_NULL_VOID(adapter);
297         adapter->sceneViewerAdapter_->UnLoadModel();
298         LOGD("MODEL_NG: UnloadScene -> Unload model GetKey() %d", adapter->GetKey());
299     });
300 }
301 
302 SceneViewerAdapterProperties ModelAdapterWrapper::ExtractLayoutProperties(
303     const RefPtr<ModelLayoutProperty>& modelLayoutProperty)
304 {
305     SceneViewerAdapterProperties properties {};
306     properties.gltfSrc_ = modelLayoutProperty->GetModelSource().value_or(properties.gltfSrc_);
307     properties.backgroundSrc_ = modelLayoutProperty->GetModelBackground().value_or(properties.backgroundSrc_);
308     bool isTransparent = modelLayoutProperty->GetModelTransparent().value_or(false);
309     properties.bgType_ = isTransparent ? OHOS::Render3D::SceneViewerBackgroundType::TRANSPARENT :
310         OHOS::Render3D::SceneViewerBackgroundType::CUBE_MAP;
311 
312     return properties;
313 }
314 
315 SceneViewerAdapterProperties ModelAdapterWrapper::ExtractPaintProperties(
316     const RefPtr<ModelPaintProperty>& modelPaintProperty)
317 {
318     SceneViewerAdapterProperties properties {};
319 
320     auto cameraPosition = modelPaintProperty->GetCameraPosition().value_or(properties.cameraPosition_.GetVec());
321     auto cameraDistance = modelPaintProperty->GetCameraDistance().value_or(properties.cameraPosition_.GetDistance());
322     auto cameraIsAngular = modelPaintProperty->GetCameraIsAngular().value_or(properties.cameraPosition_.GetIsAngular());
323     properties.cameraPosition_.SetVec(cameraPosition);
324     properties.cameraPosition_.SetDistance(cameraDistance);
325     properties.cameraPosition_.SetIsAngular(cameraIsAngular);
326     properties.cameraRotation_ = modelPaintProperty->GetCameraRotation().value_or(properties.cameraRotation_);
327     properties.cameraLookAt_ = modelPaintProperty->GetCameraLookAt().value_or(properties.cameraLookAt_);
328     properties.cameraUp_ = modelPaintProperty->GetCameraUp().value_or(properties.cameraUp_);
329     properties.zNear_ = modelPaintProperty->GetCameraZNear().value_or(properties.zNear_);
330     properties.zFar_ = modelPaintProperty->GetCameraZFar().value_or(properties.zFar_);
331     properties.fov_ = modelPaintProperty->GetCameraFOV().value_or(properties.fov_);
332     properties.lights_ = modelPaintProperty->GetModelLights().value_or(properties.lights_);
333     properties.animations_ = modelPaintProperty->GetModelAnimations().value_or(properties.animations_);
334     properties.geometries_ = modelPaintProperty->GetModelGeometries().value_or(properties.geometries_);
335     properties.customRenders_ = modelPaintProperty->GetModelCustomRenders().value_or(properties.customRenders_);
336     properties.shaderPath_ = modelPaintProperty->GetShaderPath().value_or(properties.shaderPath_);
337     properties.imageTexturePaths_ =
338         modelPaintProperty->GetModelImageTexturePaths().value_or(properties.imageTexturePaths_);
339     properties.shaderInputBuffers_ =
340         modelPaintProperty->GetModelShaderInputBuffers().value_or(properties.shaderInputBuffers_);
341     return properties;
342 }
343 
344 EGLContext ModelAdapterWrapper::GetRenderContext()
345 {
346     auto ret = EGL_NO_CONTEXT;
347     ret = Rosen::RSUIShareContext::GetInstance().GetRsRenderContext();
348     return ret;
349 }
350 
351 bool ModelAdapterWrapper::IsInitialized()
352 {
353     return sceneViewerAdapter_ ? true : false;
354 }
355 
356 bool ModelAdapterWrapper::IsReady()
357 {
358     return IsInitialized() && sceneIsSetUp_;
359 }
360 
361 bool ModelAdapterWrapper::NeedsRepaint()
362 {
363     if (!sceneViewerAdapter_) {
364         return false;
365     }
366 
367     if (sceneViewerAdapter_->IsAnimating() || sceneViewerAdapter_->HandlesNotReady()) {
368         return true;
369     }
370 
371     return needsRepaint_;
372 }
373 
374 uint32_t ModelAdapterWrapper::GetKey()
375 {
376     return key_;
377 }
378 
379 void ModelAdapterWrapper::SetPaintFinishCallback(PaintFinishCallback callback)
380 {
381     callback_ = std::move(callback);
382 }
383 
384 bool ModelAdapterWrapper::HandleTouchEvent(const TouchEventInfo& info)
385 {
386     CHECK_NULL_RETURN(touchHandler_, false);
387     return touchHandler_->HandleTouchEvent(info);
388 }
389 
390 void ModelAdapterWrapper::HandleCameraMove(const OHOS::Render3D::SceneViewerTouchEvent& event)
391 {
392     LOGD("MODEL_NG HandleCameraMove() eventId[%d], eventType[%zu], position[%.2f, %.2f], delta[%.2f, %.2f], key = %d",
393     event.GetFingerId(), event.GetEventType(), event.GetGlobalLocation().GetX(), event.GetGlobalLocation().GetY(),
394     event.GetDeltaChange().GetX(), event.GetDeltaChange().GetY(), GetKey());
395 #if MULTI_ECS_UPDATE_AT_ONCE
396     OHOS::Render3D::GraphicsTask::GetInstance().PushSyncMessage([weak = WeakClaim(this), &event] {
397 #else
398     OHOS::Render3D::GraphicsTask::GetInstance().PushSyncMessage([weak = WeakClaim(this), &event] {
399 #endif
400         auto adapter = weak.Upgrade();
401         CHECK_NULL_VOID(adapter);
402         adapter->sceneViewerAdapter_->OnTouchEvent(event);
403     });
404 }
405 
406 void ModelAdapterWrapper::UpdateCustomRenders(const SceneViewerAdapterProperties& properties)
407 {
408     LOGD("MODEL_NG: ModelAdapterWrapper::UpdateCustomRenders() size: %zu", properties.customRenders_.size());
409     if (!properties.customRenders_.empty()) {
410 #if MULTI_ECS_UPDATE_AT_ONCE
411         OHOS::Render3D::GraphicsTask::GetInstance().PushSyncMessage([weak = WeakClaim(this), &properties] {
412 #else
413         OHOS::Render3D::GraphicsTask::GetInstance().PushSyncMessage([weak = WeakClaim(this), &properties] {
414 #endif
415             auto adapter = weak.Upgrade();
416             CHECK_NULL_VOID(adapter);
417             adapter->sceneViewerAdapter_->AddCustomRenders(properties.customRenders_);
418         });
419     }
420 }
421 
422 void ModelAdapterWrapper::UpdateShaderPath(const SceneViewerAdapterProperties& properties)
423 {
424     LOGD("ModelAdapterWrapper::UpdateShaderPath() %s", properties.shaderPath_.c_str());
425 #if MULTI_ECS_UPDATE_AT_ONCE
426     OHOS::Render3D::GraphicsTask::GetInstance().PushSyncMessage([weak = WeakClaim(this), &properties] {
427 #else
428     OHOS::Render3D::GraphicsTask::GetInstance().PushSyncMessage([weak = WeakClaim(this), &properties] {
429 #endif
430         auto adapter = weak.Upgrade();
431         CHECK_NULL_VOID(adapter);
432         adapter->sceneViewerAdapter_->UpdateShaderPath(properties.shaderPath_);
433     });
434 }
435 
436 void ModelAdapterWrapper::UpdateImageTexturePaths(const SceneViewerAdapterProperties& properties)
437 {
438     LOGD("MODEL_NG: ModelAdapterWrapper::UpdateImageTexturePaths() size: %zu", properties.imageTexturePaths_.size());
439     if (!properties.imageTexturePaths_.empty()) {
440 #if MULTI_ECS_UPDATE_AT_ONCE
441         OHOS::Render3D::GraphicsTask::GetInstance().PushSyncMessage([weak = WeakClaim(this), &properties] {
442 #else
443         OHOS::Render3D::GraphicsTask::GetInstance().PushSyncMessage([weak = WeakClaim(this), &properties] {
444 #endif
445             auto adapter = weak.Upgrade();
446             CHECK_NULL_VOID(adapter);
447             adapter->sceneViewerAdapter_->UpdateImageTexturePaths(properties.imageTexturePaths_);
448         });
449     }
450 }
451 
452 void ModelAdapterWrapper::UpdateShaderInputBuffers(const SceneViewerAdapterProperties& properties)
453 {
454     LOGD("MODEL_NG: ModelAdapterWrapper::UpdateShaderInputBuffers() size: %zu", properties.shaderInputBuffers_.size());
455     if (!properties.shaderInputBuffers_.empty()) {
456 #if MULTI_ECS_UPDATE_AT_ONCE
457         OHOS::Render3D::GraphicsTask::GetInstance().PushSyncMessage([weak = WeakClaim(this), &properties] {
458 #else
459         OHOS::Render3D::GraphicsTask::GetInstance().PushSyncMessage([weak = WeakClaim(this), &properties] {
460 #endif
461             auto adapter = weak.Upgrade();
462             CHECK_NULL_VOID(adapter);
463             adapter->sceneViewerAdapter_->UpdateShaderInputBuffers(properties.shaderInputBuffers_);
464         });
465     }
466 }
467 
468 } // namespace OHOS::Ace::NG
469