[dali_2.3.21] Merge branch 'devel/master'
[platform/core/uifw/dali-toolkit.git] / automated-tests / src / dali-toolkit / dali-toolkit-test-utils / toolkit-texture-upload-manager.cpp
1 /*
2  * Copyright (c) 2023 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // CLASS HEADER
19 #include <toolkit-texture-upload-manager.h>
20
21 // EXTERNAL INCLUDE
22 #include <dali/devel-api/adaptor-framework/texture-upload-manager.h>
23 #include <dali/graphics-api/graphics-controller.h>
24 #include <dali/integration-api/pixel-data-integ.h>
25 #include <dali/integration-api/texture-integ.h>
26
27 // INTERNAL INCLUDE
28 #include <test-graphics-controller.h>
29 #include <toolkit-application.h>
30
31 namespace Dali
32 {
33 namespace Internal
34 {
35 namespace Adaptor
36 {
37 class TextureUploadManager : public Dali::BaseObject
38 {
39 public:
40   using ResourceId = Dali::Devel::TextureUploadManager::ResourceId;
41
42 public:
43   static Dali::Devel::TextureUploadManager Get();
44   TextureUploadManager();
45   ~TextureUploadManager() = default;
46
47   Dali::Texture GenerateTexture2D();
48
49 public: // Update thread called method
50   bool ResourceUpload();
51
52   void InitalizeGraphicsController(Dali::Graphics::Controller& graphicsController);
53
54 private:                                                             // Update thread called method
55   using UploadRequestItem  = std::pair<ResourceId, Dali::PixelData>; ///< TODO : PixelData? PixelBuffer?
56   using RequestUploadQueue = std::vector<UploadRequestItem>;
57
58   bool ProcessUploadQueue(RequestUploadQueue&& queue);
59
60 public: // Worker thread called method
61   /**
62    * @copydoc Dali::Devel::TextureUploadManager::RequestUpload()
63    */
64   void RequestUpload(ResourceId id, Dali::PixelData pixelData);
65
66 private:
67   Dali::Graphics::Controller* mGraphicsController;
68   RequestUploadQueue          mRequestUploadQueue{};
69
70 public:
71   ResourceId gUniqueResourceId{0u};
72 };
73
74 inline Internal::Adaptor::TextureUploadManager& GetImplementation(Dali::Devel::TextureUploadManager& obj)
75 {
76   DALI_ASSERT_ALWAYS(obj && "TextureUploadManager is empty");
77
78   Dali::BaseObject& handle = obj.GetBaseObject();
79
80   return static_cast<Internal::Adaptor::TextureUploadManager&>(handle);
81 }
82
83 inline const Internal::Adaptor::TextureUploadManager& GetImplementation(const Dali::Devel::TextureUploadManager& obj)
84 {
85   DALI_ASSERT_ALWAYS(obj && "TextureUploadManager is empty");
86
87   const Dali::BaseObject& handle = obj.GetBaseObject();
88
89   return static_cast<const Internal::Adaptor::TextureUploadManager&>(handle);
90 }
91
92 /********************************************************************************/
93 /*********************************  INTERNAL CLASS  *****************************/
94 /********************************************************************************/
95
96 namespace
97 {
98 Devel::TextureUploadManager gTextureUploadManager;
99 } // namespace
100
101 Devel::TextureUploadManager TextureUploadManager::Get()
102 {
103   if(!gTextureUploadManager)
104   {
105     gTextureUploadManager = Devel::TextureUploadManager(new TextureUploadManager());
106   }
107   return gTextureUploadManager;
108 }
109
110 TextureUploadManager::TextureUploadManager()
111 : mGraphicsController{nullptr}
112 {
113 }
114
115 Dali::Texture TextureUploadManager::GenerateTexture2D()
116 {
117   ResourceId resourceId = ++gUniqueResourceId;
118
119   Dali::Texture ret = Dali::Integration::NewTextureWithResourceId(Dali::TextureType::TEXTURE_2D, resourceId);
120
121   return ret;
122 }
123
124 // Called by update thread
125
126 bool TextureUploadManager::ResourceUpload()
127 {
128   DALI_ASSERT_DEBUG(mGraphicsController && "GraphicsController is not prepared!");
129
130   // Upload.
131   bool uploaded = ProcessUploadQueue(std::move(mRequestUploadQueue));
132   mRequestUploadQueue.clear();
133
134   return uploaded;
135 }
136
137 void TextureUploadManager::InitalizeGraphicsController(Dali::Graphics::Controller& graphicsController)
138 {
139   mGraphicsController = &graphicsController;
140 }
141
142 bool TextureUploadManager::ProcessUploadQueue(RequestUploadQueue&& queue)
143 {
144   bool uploaded = false;
145
146   if(!queue.empty())
147   {
148     for(auto& requests : queue)
149     {
150       auto& resourceId = requests.first;
151       auto& pixelData  = requests.second;
152
153       Graphics::Texture* graphicsTexture = nullptr;
154
155       // TODO : Could we detect TEXTURE_2D or TEXTURE_CUBE case in future?
156       {
157         // We always need to create new one
158         auto createInfo = Graphics::TextureCreateInfo();
159         createInfo
160           .SetTextureType(Dali::Graphics::ConvertTextureType(Dali::TextureType::TEXTURE_2D))
161           .SetUsageFlags(static_cast<Graphics::TextureUsageFlags>(Graphics::TextureUsageFlagBits::SAMPLE))
162           .SetFormat(Dali::Graphics::ConvertPixelFormat(pixelData.GetPixelFormat()))
163           .SetSize({pixelData.GetWidth(), pixelData.GetHeight()})
164           .SetLayout(Graphics::TextureLayout::LINEAR)
165           .SetData(nullptr)
166           .SetDataSize(0u)
167           .SetNativeImage(nullptr)
168           .SetMipMapFlag(Graphics::TextureMipMapFlag::DISABLED);
169
170         graphicsTexture = mGraphicsController->CreateTextureByResourceId(resourceId, createInfo);
171       }
172
173       if(graphicsTexture)
174       {
175         Graphics::TextureUpdateInfo info{};
176
177         info.dstTexture   = graphicsTexture;
178         info.dstOffset2D  = {0u, 0u};
179         info.layer        = 0u;
180         info.level        = 0u;
181         info.srcReference = 0;
182         info.srcExtent2D  = {pixelData.GetWidth(), pixelData.GetHeight()};
183         info.srcOffset    = 0;
184         info.srcSize      = Dali::Integration::GetPixelDataBuffer(pixelData).bufferSize;
185         info.srcStride    = pixelData.GetStride();
186         info.srcFormat    = Dali::Graphics::ConvertPixelFormat(pixelData.GetPixelFormat());
187
188         Graphics::TextureUpdateSourceInfo updateSourceInfo{};
189         updateSourceInfo.sourceType                = Graphics::TextureUpdateSourceInfo::Type::PIXEL_DATA;
190         updateSourceInfo.pixelDataSource.pixelData = pixelData;
191
192         mGraphicsController->UpdateTextures({info}, {updateSourceInfo});
193
194         uploaded = true;
195       }
196       else
197       {
198         // Invalidate resouce id! ignore.
199       }
200     }
201
202     if(uploaded)
203     {
204       // Flush here
205       Graphics::SubmitInfo submitInfo;
206       submitInfo.cmdBuffer.clear(); // Only flush
207       submitInfo.flags = 0 | Graphics::SubmitFlagBits::FLUSH;
208       mGraphicsController->SubmitCommandBuffers(submitInfo);
209     }
210   }
211
212   return uploaded;
213 }
214
215 // Called by worker thread
216
217 void TextureUploadManager::RequestUpload(Dali::Devel::TextureUploadManager::ResourceId resourceId, Dali::PixelData pixelData)
218 {
219   mRequestUploadQueue.push_back(std::move(UploadRequestItem(resourceId, pixelData)));
220 }
221
222 } // namespace Adaptor
223
224 } // namespace Internal
225
226 /********************************************************************************/
227 /*********************************  PUBLIC CLASS  *******************************/
228 /********************************************************************************/
229
230 namespace Devel
231 {
232 // Called by main thread
233
234 TextureUploadManager::TextureUploadManager() = default;
235
236 TextureUploadManager::~TextureUploadManager() = default;
237
238 TextureUploadManager TextureUploadManager::Get()
239 {
240   return Internal::Adaptor::TextureUploadManager::Get();
241 }
242
243 Dali::Texture TextureUploadManager::GenerateTexture2D()
244 {
245   return Internal::Adaptor::GetImplementation(*this).GenerateTexture2D();
246 }
247
248 TextureUploadManager::TextureUploadManager(Internal::Adaptor::TextureUploadManager* impl)
249 : BaseHandle(impl)
250 {
251 }
252
253 // Called by update thread
254
255 bool TextureUploadManager::ResourceUpload()
256 {
257   return Internal::Adaptor::GetImplementation(*this).ResourceUpload();
258 }
259
260 // Called by worker thread
261
262 void TextureUploadManager::RequestUpload(ResourceId resourceId, PixelData pixelData)
263 {
264   Internal::Adaptor::GetImplementation(*this).RequestUpload(resourceId, pixelData);
265 }
266
267 } // namespace Devel
268
269 } // namespace Dali
270
271 namespace Test
272 {
273 namespace TextureUploadManager
274 {
275 void InitalizeGraphicsController(Dali::Graphics::Controller& graphicsController)
276 {
277   auto textureUploadManager = Dali::Devel::TextureUploadManager::Get();
278   Internal::Adaptor::GetImplementation(textureUploadManager).InitalizeGraphicsController(graphicsController);
279 }
280 } // namespace TextureUploadManager
281 } // namespace Test