[dali_2.3.30] Merge branch 'devel/master'
[platform/core/uifw/dali-core.git] / dali / internal / event / rendering / texture-impl.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 <dali/internal/event/rendering/texture-impl.h> // Dali::Internal::Texture
20
21 // INTERNAL INCLUDES
22 #include <dali/integration-api/render-controller.h>
23 #include <dali/internal/event/common/stage-impl.h>
24 #include <dali/internal/update/manager/update-manager.h>
25
26 namespace Dali
27 {
28 namespace Internal
29 {
30 TexturePtr Texture::New(TextureType::Type type, Pixel::Format format, uint32_t width, uint32_t height)
31 {
32   constexpr auto max_value = std::numeric_limits<uint16_t>::max();
33   DALI_ASSERT_ALWAYS((width < max_value) && (height < max_value) && "Size out of range");
34   TexturePtr texture(new Texture(type, format, ImageDimensions(width, height)));
35   texture->Initialize();
36   return texture;
37 }
38
39 TexturePtr Texture::New(NativeImageInterface& nativeImageInterface)
40 {
41   TexturePtr texture(new Texture(&nativeImageInterface));
42   texture->Initialize();
43   return texture;
44 }
45
46 TexturePtr Texture::New(TextureType::Type type, uint32_t resourceId)
47 {
48   TexturePtr texture(new Texture(type, resourceId));
49   texture->Initialize();
50   return texture;
51 }
52
53 Render::TextureKey Texture::GetRenderTextureKey() const
54 {
55   return mTextureKey;
56 }
57
58 Texture::Texture(TextureType::Type type, Pixel::Format format, ImageDimensions size)
59 : mEventThreadServices(EventThreadServices::Get()),
60   mTextureKey{},
61   mNativeImage(),
62   mSize(size),
63   mType(type),
64   mFormat(format),
65   mResourceId(0u),
66   mUseUploadedParameter(mSize.GetWidth() == 0u && mSize.GetHeight() == 0u && mFormat == Pixel::INVALID)
67 {
68 }
69
70 Texture::Texture(NativeImageInterfacePtr nativeImageInterface)
71 : mEventThreadServices(EventThreadServices::Get()),
72   mTextureKey{},
73   mNativeImage(nativeImageInterface),
74   mSize(nativeImageInterface->GetWidth(), nativeImageInterface->GetHeight()),
75   mType(TextureType::TEXTURE_2D),
76   mFormat(Pixel::RGB888),
77   mResourceId(0u),
78   mUseUploadedParameter(false)
79 {
80 }
81
82 Texture::Texture(TextureType::Type type, uint32_t resourceId)
83 : mEventThreadServices(EventThreadServices::Get()),
84   mTextureKey{},
85   mNativeImage(),
86   mSize(),
87   mType(type),
88   mFormat(Pixel::INVALID),
89   mResourceId(resourceId),
90   mUseUploadedParameter(true)
91 {
92 }
93
94 void Texture::Initialize()
95 {
96   if(EventThreadServices::IsCoreRunning())
97   {
98     if(mNativeImage)
99     {
100       mTextureKey = Render::Texture::NewKey(mNativeImage);
101     }
102     else
103     {
104       if(mResourceId != 0u)
105       {
106         mTextureKey = Render::Texture::NewKey(mType, mResourceId);
107       }
108       else
109       {
110         mTextureKey = Render::Texture::NewKey(mType, mFormat, mSize);
111       }
112     }
113
114     AddTextureMessage(mEventThreadServices.GetUpdateManager(), mTextureKey);
115   }
116 }
117
118 Texture::~Texture()
119 {
120   if(EventThreadServices::IsCoreRunning() && mTextureKey)
121   {
122     RemoveTextureMessage(mEventThreadServices.GetUpdateManager(), mTextureKey);
123   }
124 }
125
126 bool Texture::Upload(PixelDataPtr pixelData)
127 {
128   return UploadSubPixelData(pixelData, 0u, 0u, pixelData->GetWidth(), pixelData->GetHeight(), 0u, 0u, 0u, 0u, pixelData->GetWidth(), pixelData->GetHeight());
129 }
130
131 bool Texture::Upload(PixelDataPtr pixelData,
132                      uint32_t     layer,
133                      uint32_t     mipmap,
134                      uint32_t     xOffset,
135                      uint32_t     yOffset,
136                      uint32_t     width,
137                      uint32_t     height)
138 {
139   return UploadSubPixelData(pixelData, 0u, 0u, pixelData->GetWidth(), pixelData->GetHeight(), layer, mipmap, xOffset, yOffset, width, height);
140 }
141
142 bool Texture::UploadSubPixelData(PixelDataPtr pixelData,
143                                  uint32_t     dataXOffset,
144                                  uint32_t     dataYOffset,
145                                  uint32_t     dataWidth,
146                                  uint32_t     dataHeight)
147 {
148   return UploadSubPixelData(pixelData, dataXOffset, dataYOffset, dataWidth, dataHeight, 0u, 0u, 0u, 0u, dataWidth, dataHeight);
149 }
150
151 bool Texture::UploadSubPixelData(PixelDataPtr pixelData,
152                                  uint32_t     dataXOffset,
153                                  uint32_t     dataYOffset,
154                                  uint32_t     dataWidth,
155                                  uint32_t     dataHeight,
156                                  uint32_t     layer,
157                                  uint32_t     mipmap,
158                                  uint32_t     xOffset,
159                                  uint32_t     yOffset,
160                                  uint32_t     width,
161                                  uint32_t     height)
162 {
163   constexpr auto max_value = std::numeric_limits<uint16_t>::max();
164   DALI_ASSERT_ALWAYS(layer < max_value &&
165                      mipmap < max_value &&
166                      xOffset + width < max_value &&
167                      yOffset + height < max_value &&
168                      dataWidth < max_value &&
169                      dataHeight < max_value &&
170                      "Parameter value out of range");
171
172   bool result(false);
173   if(EventThreadServices::IsCoreRunning() && mTextureKey)
174   {
175     if(mNativeImage)
176     {
177       DALI_LOG_ERROR("OpenGL ES does not support uploading data to native texture\n");
178     }
179     else if(mResourceId != 0u)
180     {
181       DALI_LOG_ERROR("ResourceId using case does not support uploading data\n");
182     }
183     else
184     {
185       uint32_t pixelDataSize = dataWidth * dataHeight;
186       if(pixelData->GetBuffer() == nullptr || pixelDataSize == 0)
187       {
188         DALI_LOG_ERROR("PixelData is empty\n");
189       }
190       else
191       {
192         Pixel::Format pixelDataFormat = pixelData->GetPixelFormat();
193         if((mUseUploadedParameter || pixelDataFormat == mFormat) || ((pixelDataFormat == Pixel::RGB888) && (mFormat == Pixel::RGBA8888)))
194         {
195           if(pixelDataSize < width * height)
196           {
197             DALI_LOG_ERROR("PixelData of an incorrect size when trying to update texture\n");
198           }
199           else if(Pixel::IsCompressed(mFormat) &&
200                   ((dataXOffset != 0) ||
201                    (dataYOffset != 0) ||
202                    (dataWidth != pixelData->GetWidth()) ||
203                    (dataHeight != pixelData->GetHeight())))
204           {
205             DALI_LOG_ERROR("Compressed pixel format don't support SubPixelData upload\n");
206           }
207           else if((dataXOffset + dataWidth > pixelData->GetWidth()) ||
208                   (dataYOffset + dataHeight > pixelData->GetHeight()))
209           {
210             DALI_LOG_ERROR("PixelData of an incorrect subsize when trying to update texture\n");
211           }
212           else if(!mUseUploadedParameter &&
213                   ((xOffset + width > (static_cast<uint32_t>(mSize.GetWidth()) >> mipmap)) ||
214                    (yOffset + height > (static_cast<uint32_t>(mSize.GetHeight()) >> mipmap))))
215           {
216             DALI_LOG_ERROR("Texture update area out of bounds\n");
217           }
218           else
219           {
220             if(mUseUploadedParameter)
221             {
222               mSize   = ImageDimensions(xOffset + width, yOffset + height);
223               mFormat = pixelDataFormat;
224             }
225
226             //Parameters are correct. Send message to upload data to the texture
227             Graphics::UploadParams params = {static_cast<uint32_t>(dataXOffset),
228                                              static_cast<uint32_t>(dataYOffset),
229                                              static_cast<uint16_t>(dataWidth),
230                                              static_cast<uint16_t>(dataHeight),
231                                              static_cast<uint16_t>(layer),
232                                              static_cast<uint16_t>(mipmap),
233                                              static_cast<uint16_t>(xOffset),
234                                              static_cast<uint16_t>(yOffset),
235                                              static_cast<uint16_t>(width),
236                                              static_cast<uint16_t>(height)};
237             UploadTextureMessage(mEventThreadServices.GetUpdateManager(), mTextureKey, pixelData, params);
238
239             result = true;
240           }
241         }
242         else
243         {
244           DALI_LOG_ERROR("Bad format\n");
245         }
246       }
247     }
248   }
249
250   return result;
251 }
252
253 void Texture::GenerateMipmaps()
254 {
255   if(EventThreadServices::IsCoreRunning() && mTextureKey)
256   {
257     GenerateMipmapsMessage(mEventThreadServices.GetUpdateManager(), mTextureKey);
258   }
259 }
260
261 uint32_t Texture::GetWidth() const
262 {
263   return mSize.GetWidth();
264 }
265
266 uint32_t Texture::GetHeight() const
267 {
268   return mSize.GetHeight();
269 }
270
271 Pixel::Format Texture::GetPixelFormat() const
272 {
273   return mFormat;
274 }
275
276 uint32_t Texture::GetResourceId() const
277 {
278   return mResourceId;
279 }
280
281 Dali::TextureType::Type Texture::GetTextureType() const
282 {
283   return mType;
284 }
285
286 void Texture::SetSize(const ImageDimensions& size)
287 {
288   mSize = size;
289   if(EventThreadServices::IsCoreRunning() && mTextureKey)
290   {
291     SetTextureSizeMessage(mEventThreadServices.GetUpdateManager(), mTextureKey, mSize);
292   }
293 }
294
295 void Texture::SetPixelFormat(Pixel::Format format)
296 {
297   mFormat = format;
298   if(EventThreadServices::IsCoreRunning() && mTextureKey)
299   {
300     SetTextureFormatMessage(mEventThreadServices.GetUpdateManager(), mTextureKey, mFormat);
301   }
302 }
303
304 bool Texture::IsNative() const
305 {
306   return static_cast<bool>(mNativeImage);
307 }
308
309 bool Texture::ApplyNativeFragmentShader(std::string& shader)
310 {
311   bool modified = false;
312   if(mNativeImage && !shader.empty())
313   {
314     modified = mNativeImage->ApplyNativeFragmentShader(shader);
315   }
316
317   return modified;
318 }
319
320 } // namespace Internal
321 } // namespace Dali