Fix partial update issues
[platform/core/uifw/dali-core.git] / dali / internal / render / renderers / render-texture.cpp
1 /*
2  * Copyright (c) 2022 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 // CLASS HEADER
18 #include <dali/internal/render/renderers/render-texture.h>
19
20 // EXTERNAL INCLUDES
21 #include <math.h> //floor, log2
22
23 // INTERNAL INCLUDES
24 #include <dali/integration-api/debug.h>
25
26 namespace Dali
27 {
28 namespace Internal
29 {
30 namespace Render
31 {
32 namespace
33 {
34 #if defined(DEBUG_ENABLED)
35 Debug::Filter* gTextureFilter = Debug::Filter::New(Debug::Concise, false, "LOG_TEXTURE");
36 #endif
37
38 /**
39  * Converts DALi pixel format to Graphics::Format
40  * @param format
41  * @return
42  */
43 constexpr Graphics::Format ConvertPixelFormat(Pixel::Format format)
44 {
45   switch(format)
46   {
47     case Pixel::INVALID:
48       return Graphics::Format::UNDEFINED;
49     case Pixel::A8:
50       return Graphics::Format::R8_UNORM;
51
52     case Pixel::L8:
53       return Graphics::Format::L8;
54     case Pixel::LA88:
55       return Graphics::Format::L8A8;
56     case Pixel::RGB565:
57       return Graphics::Format::R5G6B5_UNORM_PACK16;
58     case Pixel::BGR565:
59       return Graphics::Format::B5G6R5_UNORM_PACK16;
60     case Pixel::RGBA4444:
61       return Graphics::Format::R4G4B4A4_UNORM_PACK16;
62
63     case Pixel::BGRA4444:
64       return Graphics::Format::B4G4R4A4_UNORM_PACK16;
65     case Pixel::RGBA5551:
66       return Graphics::Format::R5G5B5A1_UNORM_PACK16;
67     case Pixel::BGRA5551:
68       return Graphics::Format::B5G5R5A1_UNORM_PACK16;
69     case Pixel::RGB888:
70       return Graphics::Format::R8G8B8_UNORM;
71     case Pixel::RGB8888:
72       return Graphics::Format::R8G8B8A8_UNORM;
73     case Pixel::BGR8888:
74       return Graphics::Format::B8G8R8A8_UNORM;
75     case Pixel::RGBA8888:
76       return Graphics::Format::R8G8B8A8_UNORM;
77     case Pixel::BGRA8888:
78       return Graphics::Format::B8G8R8A8_UNORM;
79
80     case Pixel::DEPTH_UNSIGNED_INT:
81       return Graphics::Format::D16_UNORM;
82     case Pixel::DEPTH_FLOAT:
83       return Graphics::Format::D32_SFLOAT;
84     case Pixel::DEPTH_STENCIL:
85       return Graphics::Format::D24_UNORM_S8_UINT;
86
87     // EAC
88     case Pixel::COMPRESSED_R11_EAC:
89       return Graphics::Format::EAC_R11_UNORM_BLOCK;
90     case Pixel::COMPRESSED_SIGNED_R11_EAC:
91       return Graphics::Format::EAC_R11_SNORM_BLOCK;
92     case Pixel::COMPRESSED_RG11_EAC:
93       return Graphics::Format::EAC_R11G11_UNORM_BLOCK;
94     case Pixel::COMPRESSED_SIGNED_RG11_EAC:
95       return Graphics::Format::EAC_R11G11_SNORM_BLOCK;
96
97     // ETC
98     case Pixel::COMPRESSED_RGB8_ETC2:
99       return Graphics::Format::ETC2_R8G8B8_UNORM_BLOCK;
100     case Pixel::COMPRESSED_SRGB8_ETC2:
101       return Graphics::Format::ETC2_R8G8B8_SRGB_BLOCK;
102
103     case Pixel::COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
104       return Graphics::Format::ETC2_R8G8B8A1_UNORM_BLOCK; // no 'punchthrough' format
105
106     case Pixel::COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
107       return Graphics::Format::ETC2_R8G8B8A1_SRGB_BLOCK; // no 'punchthrough' format
108
109     case Pixel::COMPRESSED_RGBA8_ETC2_EAC:
110       return Graphics::Format::ETC2_R8G8B8A8_UNORM_BLOCK;
111
112     case Pixel::COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
113       return Graphics::Format::ETC2_R8G8B8A8_SRGB_BLOCK;
114
115     case Pixel::COMPRESSED_RGB8_ETC1:
116       return Graphics::Format::ETC2_R8G8B8_UNORM_BLOCK; // doesn't seem to be supported at all
117
118     case Pixel::COMPRESSED_RGB_PVRTC_4BPPV1:
119       return Graphics::Format::PVRTC1_4BPP_UNORM_BLOCK_IMG; // or SRGB?
120
121     // ASTC
122     case Pixel::COMPRESSED_RGBA_ASTC_4x4_KHR:
123       return Graphics::Format::ASTC_4x4_UNORM_BLOCK; // or SRGB?
124     case Pixel::COMPRESSED_RGBA_ASTC_5x4_KHR:
125       return Graphics::Format::ASTC_5x4_UNORM_BLOCK;
126     case Pixel::COMPRESSED_RGBA_ASTC_5x5_KHR:
127       return Graphics::Format::ASTC_5x5_UNORM_BLOCK;
128     case Pixel::COMPRESSED_RGBA_ASTC_6x5_KHR:
129       return Graphics::Format::ASTC_6x5_UNORM_BLOCK;
130     case Pixel::COMPRESSED_RGBA_ASTC_6x6_KHR:
131       return Graphics::Format::ASTC_6x6_UNORM_BLOCK;
132     case Pixel::COMPRESSED_RGBA_ASTC_8x5_KHR:
133       return Graphics::Format::ASTC_8x5_UNORM_BLOCK;
134     case Pixel::COMPRESSED_RGBA_ASTC_8x6_KHR:
135       return Graphics::Format::ASTC_8x6_UNORM_BLOCK;
136     case Pixel::COMPRESSED_RGBA_ASTC_8x8_KHR:
137       return Graphics::Format::ASTC_8x8_UNORM_BLOCK;
138     case Pixel::COMPRESSED_RGBA_ASTC_10x5_KHR:
139       return Graphics::Format::ASTC_10x5_UNORM_BLOCK;
140     case Pixel::COMPRESSED_RGBA_ASTC_10x6_KHR:
141       return Graphics::Format::ASTC_10x6_UNORM_BLOCK;
142     case Pixel::COMPRESSED_RGBA_ASTC_10x8_KHR:
143       return Graphics::Format::ASTC_10x8_UNORM_BLOCK;
144     case Pixel::COMPRESSED_RGBA_ASTC_10x10_KHR:
145       return Graphics::Format::ASTC_10x10_UNORM_BLOCK;
146     case Pixel::COMPRESSED_RGBA_ASTC_12x10_KHR:
147       return Graphics::Format::ASTC_12x10_UNORM_BLOCK;
148     case Pixel::COMPRESSED_RGBA_ASTC_12x12_KHR:
149       return Graphics::Format::ASTC_12x12_UNORM_BLOCK;
150     case Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR:
151       return Graphics::Format::ASTC_4x4_SRGB_BLOCK; // not type with alpha, but likely to use SRGB
152     case Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR:
153       return Graphics::Format::ASTC_5x4_SRGB_BLOCK;
154     case Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR:
155       return Graphics::Format::ASTC_5x5_SRGB_BLOCK;
156     case Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR:
157       return Graphics::Format::ASTC_6x5_SRGB_BLOCK;
158     case Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR:
159       return Graphics::Format::ASTC_6x6_SRGB_BLOCK;
160     case Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR:
161       return Graphics::Format::ASTC_8x5_SRGB_BLOCK;
162     case Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR:
163       return Graphics::Format::ASTC_8x6_UNORM_BLOCK;
164     case Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR:
165       return Graphics::Format::ASTC_8x8_SRGB_BLOCK;
166     case Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR:
167       return Graphics::Format::ASTC_10x5_SRGB_BLOCK;
168     case Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR:
169       return Graphics::Format::ASTC_10x6_SRGB_BLOCK;
170     case Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR:
171       return Graphics::Format::ASTC_10x8_SRGB_BLOCK;
172     case Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR:
173       return Graphics::Format::ASTC_10x10_SRGB_BLOCK;
174     case Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR:
175       return Graphics::Format::ASTC_12x10_SRGB_BLOCK;
176     case Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR:
177       return Graphics::Format::ASTC_12x12_SRGB_BLOCK;
178
179     case Pixel::RGB16F:
180       return Graphics::Format::R16G16B16_SFLOAT;
181     case Pixel::RGB32F:
182       return Graphics::Format::R32G32B32_SFLOAT;
183     case Pixel::R11G11B10F:
184       return Graphics::Format::R11G11B10_UFLOAT_PACK32;
185
186     case Pixel::CHROMINANCE_U:
187       return Graphics::Format::L8;
188     case Pixel::CHROMINANCE_V:
189       return Graphics::Format::L8;
190   }
191   return Graphics::Format::UNDEFINED;
192 }
193
194 constexpr Graphics::TextureType ConvertType(Texture::Type type)
195 {
196   switch(type)
197   {
198     case TextureType::TEXTURE_2D:
199       return Graphics::TextureType::TEXTURE_2D;
200     case TextureType::TEXTURE_CUBE:
201       return Graphics::TextureType::TEXTURE_CUBEMAP;
202   }
203   return Graphics::TextureType::TEXTURE_2D;
204 }
205
206 } //Unnamed namespace
207
208 Texture::Texture(Type type, Pixel::Format format, ImageDimensions size)
209 : mGraphicsController(nullptr),
210   mGraphicsTexture(nullptr),
211   mNativeImage(),
212   mSampler(),
213   mPixelFormat(format),
214   mWidth(size.GetWidth()),
215   mHeight(size.GetHeight()),
216   mType(type),
217   mHasAlpha(HasAlpha(format)),
218   mUpdated(true)
219 {
220 }
221
222 Texture::Texture(NativeImageInterfacePtr nativeImageInterface)
223 : mGraphicsController(nullptr),
224   mGraphicsTexture(nullptr),
225   mNativeImage(nativeImageInterface),
226   mSampler(),
227   mPixelFormat(Pixel::RGBA8888),
228   mWidth(static_cast<uint16_t>(nativeImageInterface->GetWidth())),   // ignoring overflow, not happening in practice
229   mHeight(static_cast<uint16_t>(nativeImageInterface->GetHeight())), // ignoring overflow, not happening in practice
230   mType(TextureType::TEXTURE_2D),
231   mHasAlpha(nativeImageInterface->RequiresBlending()),
232   mUpdated(true)
233 {
234 }
235
236 Texture::~Texture() = default;
237
238 void Texture::Initialize(Graphics::Controller& graphicsController)
239 {
240   mGraphicsController = &graphicsController;
241   if(mNativeImage)
242   {
243     Create(static_cast<uint32_t>(Graphics::TextureUsageFlagBits::SAMPLE));
244   }
245 }
246
247 void Texture::Destroy()
248 {
249   mGraphicsTexture.reset();
250 }
251
252 Graphics::Texture* Texture::GetGraphicsObject() const
253 {
254   DALI_LOG_INFO(gTextureFilter, Debug::General, "SC::Texture(%p)::GetGraphicsObject() = %p\n", this, mGraphicsTexture.get());
255
256   return mGraphicsTexture.get();
257 }
258
259 void Texture::Create(Graphics::TextureUsageFlags usage)
260 {
261   CreateWithData(usage, nullptr, 0u);
262 }
263
264 void Texture::CreateWithData(Graphics::TextureUsageFlags usage, uint8_t* data, uint32_t size)
265 {
266   auto createInfo = Graphics::TextureCreateInfo();
267   createInfo
268     .SetTextureType(ConvertType(mType))
269     .SetUsageFlags(usage)
270     .SetFormat(ConvertPixelFormat(mPixelFormat))
271     .SetSize({mWidth, mHeight})
272     .SetLayout(Graphics::TextureLayout::LINEAR)
273     .SetData(data)
274     .SetDataSize(size)
275     .SetNativeImage(mNativeImage)
276     .SetMipMapFlag(Graphics::TextureMipMapFlag::DISABLED);
277
278   mGraphicsTexture = mGraphicsController->CreateTexture(createInfo, std::move(mGraphicsTexture));
279 }
280
281 void Texture::Upload(PixelDataPtr pixelData, const Internal::Texture::UploadParams& params)
282 {
283   DALI_ASSERT_ALWAYS(!mNativeImage);
284
285   if(!mGraphicsTexture)
286   {
287     Create(static_cast<Graphics::TextureUsageFlags>(Graphics::TextureUsageFlagBits::SAMPLE));
288   }
289
290   Graphics::TextureUpdateInfo info{};
291
292   const uint32_t bytePerPixel = Pixel::GetBytesPerPixel(pixelData->GetPixelFormat());
293   const uint32_t srcStride    = pixelData->GetStride();
294   uint32_t       srcOffset    = 0u;
295   uint32_t       srcSize      = pixelData->GetBufferSize();
296
297   const bool requiredSubPixelData = (!Pixel::IsCompressed(pixelData->GetPixelFormat())) &&
298                                     ((params.dataXOffset != 0) ||
299                                      (params.dataYOffset != 0) ||
300                                      (params.dataWidth != pixelData->GetWidth()) ||
301                                      (params.dataHeight != pixelData->GetHeight()));
302
303   if(requiredSubPixelData)
304   {
305     /**
306      * TextureUpdateInfo use byte scaled offset / size.
307      *
308      * To make we only use sub-data of inputed PixelData, make srcOffset as 'start of SubPixelData.
309      *
310      *   |---- dataStrideByte -----|
311      *   |-----| <-- dataXOffsetByte
312      *   ...........................
313      *   ......A-----------+........
314      *   ......|           |........
315      *   ......|           |........
316      *   ......+-----------+C.......
317      *   ......B....................
318      *
319      * A) Start of SubPixelData. offsetByte = dataStrideByte * dataYOffset + dataXOffsetByte.
320      * B) offsetByte = A).offsetByte + dataStrideByte * dataHeight. Note, It can be out of original PixelData boundary.
321      * C) End of SubPixelData. offsetByte = B).offsetByte - dataStrideByte + dataWidthByte.
322      *
323      * srcOffset = A).offsetByte;
324      * srcSize = ( C).offsetByte - A).offsetByte );
325      */
326     const uint32_t dataStrideByte  = (srcStride ? srcStride : static_cast<uint32_t>(params.dataWidth)) * bytePerPixel;
327     const uint32_t dataXOffsetByte = params.dataXOffset * bytePerPixel;
328     const uint32_t dataWidthByte   = static_cast<uint32_t>(params.dataWidth) * bytePerPixel;
329
330     srcOffset = params.dataYOffset * dataStrideByte + dataXOffsetByte;
331     srcSize   = static_cast<uint32_t>(params.dataHeight) * dataStrideByte - (dataStrideByte - dataWidthByte);
332   }
333
334   info.dstTexture   = mGraphicsTexture.get();
335   info.dstOffset2D  = {params.xOffset, params.yOffset};
336   info.layer        = params.layer;
337   info.level        = params.mipmap;
338   info.srcReference = 0;
339   info.srcExtent2D  = {params.dataWidth, params.dataHeight};
340   info.srcOffset    = srcOffset;
341   info.srcSize      = srcSize;
342   info.srcStride    = srcStride;
343   info.srcFormat    = ConvertPixelFormat(pixelData->GetPixelFormat());
344
345   Graphics::TextureUpdateSourceInfo updateSourceInfo{};
346   updateSourceInfo.sourceType          = Graphics::TextureUpdateSourceInfo::Type::MEMORY;
347   updateSourceInfo.memorySource.memory = pixelData->GetBuffer();
348
349   mGraphicsController->UpdateTextures({info}, {updateSourceInfo});
350
351   SetUpdated(true);
352 }
353
354 bool Texture::HasAlphaChannel() const
355 {
356   bool alpha = mHasAlpha;
357   if(mNativeImage)
358   {
359     alpha = mNativeImage->RequiresBlending();
360   }
361   return alpha;
362 }
363
364 void Texture::GenerateMipmaps()
365 {
366   if(!mGraphicsTexture)
367   {
368     Create(static_cast<Graphics::TextureUsageFlags>(Graphics::TextureUsageFlagBits::SAMPLE));
369   }
370
371   mGraphicsController->GenerateTextureMipmaps(*mGraphicsTexture.get());
372 }
373
374 void Texture::OnRenderFinished()
375 {
376   SetUpdated(false);
377 }
378
379 } // namespace Render
380
381 } // namespace Internal
382
383 } // namespace Dali