Migrated Render::Texture to use memory pool
[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
44   // Request event processing and update forcely.
45   texture->mEventThreadServices.GetRenderController().RequestProcessEventsOnIdle(true);
46   texture->mEventThreadServices.ForceNextUpdate();
47   return texture;
48 }
49
50 Render::TextureKey Texture::GetRenderTextureKey() const
51 {
52   return mTextureKey;
53 }
54
55 Texture::Texture(TextureType::Type type, Pixel::Format format, ImageDimensions size)
56 : mEventThreadServices(EventThreadServices::Get()),
57   mTextureKey{},
58   mNativeImage(),
59   mSize(size),
60   mType(type),
61   mFormat(format)
62 {
63 }
64
65 Texture::Texture(NativeImageInterfacePtr nativeImageInterface)
66 : mEventThreadServices(EventThreadServices::Get()),
67   mTextureKey{},
68   mNativeImage(nativeImageInterface),
69   mSize(nativeImageInterface->GetWidth(), nativeImageInterface->GetHeight()),
70   mType(TextureType::TEXTURE_2D),
71   mFormat(Pixel::RGB888)
72 {
73 }
74
75 void Texture::Initialize()
76 {
77   if(EventThreadServices::IsCoreRunning())
78   {
79     if(mNativeImage)
80     {
81       mTextureKey = Render::Texture::NewKey(mNativeImage);
82     }
83     else
84     {
85       mTextureKey = Render::Texture::NewKey(mType, mFormat, mSize);
86     }
87
88     AddTextureMessage(mEventThreadServices.GetUpdateManager(), mTextureKey);
89   }
90 }
91
92 Texture::~Texture()
93 {
94   if(EventThreadServices::IsCoreRunning() && mTextureKey)
95   {
96     RemoveTextureMessage(mEventThreadServices.GetUpdateManager(), mTextureKey);
97   }
98 }
99
100 bool Texture::Upload(PixelDataPtr pixelData)
101 {
102   return UploadSubPixelData(pixelData, 0u, 0u, pixelData->GetWidth(), pixelData->GetHeight(), 0u, 0u, 0u, 0u, pixelData->GetWidth(), pixelData->GetHeight());
103 }
104
105 bool Texture::Upload(PixelDataPtr pixelData,
106                      uint32_t     layer,
107                      uint32_t     mipmap,
108                      uint32_t     xOffset,
109                      uint32_t     yOffset,
110                      uint32_t     width,
111                      uint32_t     height)
112 {
113   return UploadSubPixelData(pixelData, 0u, 0u, pixelData->GetWidth(), pixelData->GetHeight(), layer, mipmap, xOffset, yOffset, width, height);
114 }
115
116 bool Texture::UploadSubPixelData(PixelDataPtr pixelData,
117                                  uint32_t     dataXOffset,
118                                  uint32_t     dataYOffset,
119                                  uint32_t     dataWidth,
120                                  uint32_t     dataHeight)
121 {
122   return UploadSubPixelData(pixelData, dataXOffset, dataYOffset, dataWidth, dataHeight, 0u, 0u, 0u, 0u, dataWidth, dataHeight);
123 }
124
125 bool Texture::UploadSubPixelData(PixelDataPtr pixelData,
126                                  uint32_t     dataXOffset,
127                                  uint32_t     dataYOffset,
128                                  uint32_t     dataWidth,
129                                  uint32_t     dataHeight,
130                                  uint32_t     layer,
131                                  uint32_t     mipmap,
132                                  uint32_t     xOffset,
133                                  uint32_t     yOffset,
134                                  uint32_t     width,
135                                  uint32_t     height)
136 {
137   constexpr auto max_value = std::numeric_limits<uint16_t>::max();
138   DALI_ASSERT_ALWAYS(layer < max_value &&
139                      mipmap < max_value &&
140                      xOffset < max_value &&
141                      yOffset < max_value &&
142                      width < max_value &&
143                      height < max_value &&
144                      dataWidth < max_value &&
145                      dataHeight < max_value &&
146                      "Parameter value out of range");
147
148   bool result(false);
149   if(EventThreadServices::IsCoreRunning() && mTextureKey)
150   {
151     if(mNativeImage)
152     {
153       DALI_LOG_ERROR("OpenGL ES does not support uploading data to native texture\n");
154     }
155     else
156     {
157       uint32_t pixelDataSize = dataWidth * dataHeight;
158       if(pixelData->GetBuffer() == nullptr || pixelDataSize == 0)
159       {
160         DALI_LOG_ERROR("PixelData is empty\n");
161       }
162       else
163       {
164         Pixel::Format pixelDataFormat = pixelData->GetPixelFormat();
165         if((pixelDataFormat == mFormat) || ((pixelDataFormat == Pixel::RGB888) && (mFormat == Pixel::RGBA8888)))
166         {
167           if(pixelDataSize < width * height)
168           {
169             DALI_LOG_ERROR("PixelData of an incorrect size when trying to update texture\n");
170           }
171           else if(Pixel::IsCompressed(mFormat) &&
172                   ((dataXOffset != 0) ||
173                    (dataYOffset != 0) ||
174                    (dataWidth != pixelData->GetWidth()) ||
175                    (dataHeight != pixelData->GetHeight())))
176           {
177             DALI_LOG_ERROR("Compressed pixel format don't support SubPixelData upload\n");
178           }
179           else if((dataXOffset + dataWidth > pixelData->GetWidth()) ||
180                   (dataYOffset + dataHeight > pixelData->GetHeight()))
181           {
182             DALI_LOG_ERROR("PixelData of an incorrect subsize when trying to update texture\n");
183           }
184           else if((xOffset + width > (mSize.GetWidth() / (1u << mipmap))) ||
185                   (yOffset + height > (mSize.GetHeight() / (1u << mipmap))))
186           {
187             DALI_LOG_ERROR("Texture update area out of bounds\n");
188           }
189           else
190           {
191             //Parameters are correct. Send message to upload data to the texture
192             UploadParams params = {static_cast<uint32_t>(dataXOffset),
193                                    static_cast<uint32_t>(dataYOffset),
194                                    static_cast<uint16_t>(dataWidth),
195                                    static_cast<uint16_t>(dataHeight),
196                                    static_cast<uint16_t>(layer),
197                                    static_cast<uint16_t>(mipmap),
198                                    static_cast<uint16_t>(xOffset),
199                                    static_cast<uint16_t>(yOffset),
200                                    static_cast<uint16_t>(width),
201                                    static_cast<uint16_t>(height)};
202             UploadTextureMessage(mEventThreadServices.GetUpdateManager(), mTextureKey, pixelData, params);
203
204             // Request event processing and update forcely
205             mEventThreadServices.GetRenderController().RequestProcessEventsOnIdle(true);
206             mEventThreadServices.ForceNextUpdate();
207
208             result = true;
209           }
210         }
211         else
212         {
213           DALI_LOG_ERROR("Bad format\n");
214         }
215       }
216     }
217   }
218
219   return result;
220 }
221
222 void Texture::GenerateMipmaps()
223 {
224   if(EventThreadServices::IsCoreRunning() && mTextureKey)
225   {
226     GenerateMipmapsMessage(mEventThreadServices.GetUpdateManager(), mTextureKey);
227   }
228 }
229
230 uint32_t Texture::GetWidth() const
231 {
232   return mSize.GetWidth();
233 }
234
235 uint32_t Texture::GetHeight() const
236 {
237   return mSize.GetHeight();
238 }
239
240 Pixel::Format Texture::GetPixelFormat() const
241 {
242   return mFormat;
243 }
244
245 bool Texture::IsNative() const
246 {
247   return static_cast<bool>(mNativeImage);
248 }
249
250 bool Texture::ApplyNativeFragmentShader(std::string& shader)
251 {
252   bool modified = false;
253   if(mNativeImage && !shader.empty())
254   {
255     modified = mNativeImage->ApplyNativeFragmentShader(shader);
256   }
257
258   return modified;
259 }
260
261 } // namespace Internal
262 } // namespace Dali