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 #include <scene_plugin/api/material_uid.h>
16 
17 #include <meta/ext/concrete_base_object.h>
18 
19 #include "bind_templates.inl"
20 #include "node_impl.h"
21 
22 namespace {
23 class GraphicsStateImpl : public META_NS::ObjectFwd<GraphicsStateImpl, SCENE_NS::ClassId::GraphicsState,
24                               META_NS::ClassId::Object, SCENE_NS::IGraphicsState, ISceneHolderRef> {
25     META_IMPLEMENT_INTERFACE_PROPERTY(SCENE_NS::IGraphicsState, BASE_NS::string, Uri, "")
26     META_IMPLEMENT_INTERFACE_PROPERTY(SCENE_NS::IGraphicsState, BASE_NS::string, Variant, "")
27 
28     bool Build(const IMetadata::Ptr& data) override
29     {
30         return true;
31     }
32 
GetRenderHandleReference(RENDER_NS::IShaderManager & shaderManager)33     RENDER_NS::RenderHandleReference GetRenderHandleReference(RENDER_NS::IShaderManager& shaderManager) override
34     {
35         if (RENDER_NS::RenderHandleUtil::IsValid(renderHandleReference_.GetHandle())) {
36             return renderHandleReference_;
37         }
38 
39         auto uri = GetValue(META_ACCESS_PROPERTY(Uri));
40         auto variant = GetValue(META_ACCESS_PROPERTY(Variant));
41 
42         renderHandleReference_ = shaderManager.GetGraphicsStateHandle(uri, variant);
43         if (!renderHandleReference_) {
44             // presumably we should resolve the state from shader instead trying to create a default our self
45             // the problem is, we don't actually know to which shader we are attached to
46             // basically the shader should have set its default during the material component set-up, though
47             shaderManager.CreateGraphicsState({ uri, {} }, { variant, {} });
48             renderHandleReference_ = shaderManager.GetGraphicsStateHandle(uri, variant);
49         }
50 
51         return renderHandleReference_;
52     }
53 
SetGraphicsState(const RENDER_NS::GraphicsState & state,SCENE_NS::IMaterial::Ptr mat)54     void SetGraphicsState(const RENDER_NS::GraphicsState& state, SCENE_NS::IMaterial::Ptr mat) override
55     {
56         if (auto sh = SceneHolder()) {
57             sh->QueueApplicationTask(META_NS::MakeCallback<META_NS::ITaskQueueTask>(
58                                          [st = state, sh = sh_, material = BASE_NS::weak_ptr(mat), type = ix_]() {
59                                              if (auto sceneHolder = sh.lock()) {
60                                                  if (auto mat = interface_cast<SCENE_NS::IEcsObject>(material.lock())) {
61                                                      sceneHolder->SetGraphicsState(
62                                                          mat->GetEntity(), (SceneHolder::ShaderType)type, st);
63                                                  }
64                                              }
65                                              return false;
66                                          }),
67                 false);
68         }
69     }
70 
GetGraphicsState(SCENE_NS::IMaterial::Ptr mat)71     SCENE_NS::IShaderGraphicsState::Ptr GetGraphicsState(SCENE_NS::IMaterial::Ptr mat) override
72     {
73         auto ret =
74             META_NS::GetObjectRegistry().Create<SCENE_NS::IShaderGraphicsState>(SCENE_NS::ClassId::GraphicsState);
75         if (auto sh = SceneHolder()) {
76             sh->QueueApplicationTask(
77                 META_NS::MakeCallback<META_NS::ITaskQueueTask>([sh = sh_, material = BASE_NS::weak_ptr(mat), type = ix_,
78                                                                ret_w = BASE_NS::weak_ptr(ret)]() {
79                     if (auto sceneHolder = sh.lock()) {
80                         if (auto mat = interface_cast<SCENE_NS::IEcsObject>(material.lock())) {
81                             if (auto ret = ret_w.lock()) {
82                                 sceneHolder->GetGraphicsState(mat->GetEntity(), (SceneHolder::ShaderType)type, ret);
83                                 if (auto typedRet =
84                                         interface_cast<SCENE_NS::IPendingRequestData<RENDER_NS::GraphicsState>>(ret)) {
85                                     typedRet->MarkReady();
86                                 }
87                             }
88                         }
89                     }
90                     return false;
91                 }),
92                 false);
93         }
94 
95         return ret;
96     }
97 
SetSceneHolder(const SceneHolder::WeakPtr & sh)98     void SetSceneHolder(const SceneHolder::WeakPtr& sh) override
99     {
100         sh_ = sh;
101     }
102 
SceneHolder()103     SceneHolder::Ptr SceneHolder() override
104     {
105         return sh_.lock();
106     }
107 
SetIndex(size_t ix)108     void SetIndex(size_t ix) override
109     {
110         ix_ = ix;
111     }
112 
113 private:
114     RENDER_NS::RenderHandleReference renderHandleReference_;
115     SceneHolder::WeakPtr sh_;
116     size_t ix_ { 0 };
117 };
118 } // namespace
119 
SCENE_BEGIN_NAMESPACE()120 SCENE_BEGIN_NAMESPACE()
121 void RegisterGraphicsStateImpl()
122 {
123     META_NS::GetObjectRegistry().RegisterObjectType<GraphicsStateImpl>();
124 }
UnregisterGraphicsStateImpl()125 void UnregisterGraphicsStateImpl()
126 {
127     META_NS::GetObjectRegistry().UnregisterObjectType<GraphicsStateImpl>();
128 }
129 SCENE_END_NAMESPACE()