2 * Copyright (c) 2024 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <dali/integration-api/bitmap.h>
22 #include <dali/integration-api/debug.h>
23 #include <dali/integration-api/gl-defines.h>
24 #include <dali/integration-api/platform-abstraction.h>
25 #include <dali/internal/event/common/thread-local-storage.h>
26 #include <dali/internal/event/images/bitmap-compressed.h>
27 #include <dali/internal/event/images/bitmap-packed-pixel.h>
33 using namespace Dali::Pixel;
35 void ConvertToGlFormat(Format pixelformat, unsigned& pixelDataType, unsigned& internalFormat)
37 // Compressed textures have no pixelDataType, so init to an invalid value:
38 pixelDataType = GL_INVALID_VALUE;
44 pixelDataType = GL_UNSIGNED_BYTE;
45 internalFormat = GL_ALPHA;
51 pixelDataType = GL_UNSIGNED_BYTE;
52 internalFormat = GL_LUMINANCE;
58 pixelDataType = GL_UNSIGNED_BYTE;
59 internalFormat = GL_LUMINANCE_ALPHA;
65 pixelDataType = GL_UNSIGNED_SHORT_5_6_5;
66 internalFormat = GL_RGB;
72 DALI_LOG_ERROR("Pixel format BGR565 is not supported by GLES.\n");
73 pixelDataType = GL_UNSIGNED_SHORT_5_6_5;
75 internalFormat = GL_BGRA_EXT; // alpha is reserved but not used
77 internalFormat = GL_RGBA; // alpha is reserved but not used
84 pixelDataType = GL_UNSIGNED_SHORT_4_4_4_4;
85 internalFormat = GL_RGBA;
91 DALI_LOG_ERROR("Pixel format BGRA4444 is not supported by GLES.\n");
92 pixelDataType = GL_UNSIGNED_SHORT_4_4_4_4;
94 internalFormat = GL_BGRA_EXT; // alpha is reserved but not used
96 internalFormat = GL_RGBA; // alpha is reserved but not used
103 pixelDataType = GL_UNSIGNED_SHORT_5_5_5_1;
104 internalFormat = GL_RGBA;
110 DALI_LOG_ERROR("Pixel format BGRA5551 is not supported by GLES.\n");
111 pixelDataType = GL_UNSIGNED_SHORT_5_5_5_1;
113 internalFormat = GL_BGRA_EXT; // alpha is reserved but not used
115 internalFormat = GL_RGBA; // alpha is reserved but not used
122 pixelDataType = GL_UNSIGNED_BYTE;
123 internalFormat = GL_RGB;
129 pixelDataType = GL_UNSIGNED_BYTE;
130 internalFormat = GL_RGBA; // alpha is reserved but not used
136 pixelDataType = GL_UNSIGNED_BYTE;
138 internalFormat = GL_BGRA_EXT; // alpha is reserved but not used
140 internalFormat = GL_RGBA; // alpha is reserved but not used
147 pixelDataType = GL_UNSIGNED_BYTE;
148 internalFormat = GL_RGBA;
154 pixelDataType = GL_UNSIGNED_BYTE;
156 internalFormat = GL_BGRA_EXT; // alpha is reserved but not used
158 internalFormat = GL_RGBA; // alpha is reserved but not used
163 // GLES 2 extension compressed formats:
164 case COMPRESSED_RGB8_ETC1:
166 DALI_LOG_INFO(Debug::Filter::gImage, Debug::Verbose, "Using non-standard GLES 2.0 extension compressed pixel format COMPRESSED_RGB8_ETC1.\n");
167 internalFormat = 0x8D64; ///! < Hardcoded so we can test before we move to GLES 3.0 or greater.
170 case COMPRESSED_RGB_PVRTC_4BPPV1:
172 DALI_LOG_INFO(Debug::Filter::gImage, Debug::Verbose, "Using non-standard GLES 2.0 extension compressed pixel format COMPRESSED_RGB_PVRTC_4BPPV1.\n");
173 internalFormat = 0x8C00; ///! < Hardcoded so we can test before we move to GLES 3.0 or greater.
177 // GLES 3.0 standard compressed formats:
178 case COMPRESSED_R11_EAC:
180 DALI_LOG_INFO(Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.0 standard compressed pixel format COMPRESSED_R11_EAC.\n");
181 internalFormat = GL_COMPRESSED_R11_EAC;
184 case COMPRESSED_SIGNED_R11_EAC:
186 DALI_LOG_INFO(Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.0 standard compressed pixel format COMPRESSED_SIGNED_R11_EAC.\n");
187 internalFormat = GL_COMPRESSED_SIGNED_R11_EAC;
190 case COMPRESSED_RG11_EAC:
192 DALI_LOG_INFO(Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.0 standard compressed pixel format COMPRESSED_RG11_EAC.\n");
193 internalFormat = GL_COMPRESSED_RG11_EAC;
196 case COMPRESSED_SIGNED_RG11_EAC:
198 DALI_LOG_INFO(Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.0 standard compressed pixel format COMPRESSED_SIGNED_RG11_EAC.\n");
199 internalFormat = GL_COMPRESSED_SIGNED_RG11_EAC;
202 case COMPRESSED_RGB8_ETC2:
204 DALI_LOG_INFO(Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.0 standard compressed pixel format COMPRESSED_RGB8_ETC2.\n");
205 internalFormat = GL_COMPRESSED_RGB8_ETC2;
208 case COMPRESSED_SRGB8_ETC2:
210 DALI_LOG_INFO(Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.0 standard compressed pixel format COMPRESSED_SRGB8_ETC2.\n");
211 internalFormat = GL_COMPRESSED_SRGB8_ETC2;
214 case COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
216 DALI_LOG_INFO(Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.0 standard compressed pixel format COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2.\n");
217 internalFormat = GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2;
220 case COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
222 DALI_LOG_INFO(Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.0 standard compressed pixel format COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2.\n");
223 internalFormat = GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2;
226 case COMPRESSED_RGBA8_ETC2_EAC:
228 DALI_LOG_INFO(Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.0 standard compressed pixel format COMPRESSED_RGBA8_ETC2_EAC.\n");
229 internalFormat = GL_COMPRESSED_RGBA8_ETC2_EAC;
232 case COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
234 DALI_LOG_INFO(Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.0 standard compressed pixel format COMPRESSED_SRGB8_ALPHA8_ETC2_EAC.\n");
235 internalFormat = GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC;
239 // GLES 3.1 extension compressed formats:
240 case COMPRESSED_RGBA_ASTC_4x4_KHR:
242 DALI_LOG_INFO(Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.1 standard compressed pixel format COMPRESSED_RGBA_ASTC_4x4_KHR.\n");
243 internalFormat = GL_COMPRESSED_RGBA_ASTC_4x4_KHR;
246 case COMPRESSED_RGBA_ASTC_5x4_KHR:
248 DALI_LOG_INFO(Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.1 standard compressed pixel format COMPRESSED_RGBA_ASTC_5x4_KHR.\n");
249 internalFormat = GL_COMPRESSED_RGBA_ASTC_5x4_KHR;
252 case COMPRESSED_RGBA_ASTC_5x5_KHR:
254 DALI_LOG_INFO(Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.1 standard compressed pixel format COMPRESSED_RGBA_ASTC_5x5_KHR.\n");
255 internalFormat = GL_COMPRESSED_RGBA_ASTC_5x5_KHR;
258 case COMPRESSED_RGBA_ASTC_6x5_KHR:
260 DALI_LOG_INFO(Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.1 standard compressed pixel format COMPRESSED_RGBA_ASTC_6x5_KHR.\n");
261 internalFormat = GL_COMPRESSED_RGBA_ASTC_6x5_KHR;
264 case COMPRESSED_RGBA_ASTC_6x6_KHR:
266 DALI_LOG_INFO(Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.1 standard compressed pixel format COMPRESSED_RGBA_ASTC_6x6_KHR.\n");
267 internalFormat = GL_COMPRESSED_RGBA_ASTC_6x6_KHR;
270 case COMPRESSED_RGBA_ASTC_8x5_KHR:
272 DALI_LOG_INFO(Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.1 standard compressed pixel format COMPRESSED_RGBA_ASTC_8x5_KHR.\n");
273 internalFormat = GL_COMPRESSED_RGBA_ASTC_8x5_KHR;
276 case COMPRESSED_RGBA_ASTC_8x6_KHR:
278 DALI_LOG_INFO(Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.1 standard compressed pixel format COMPRESSED_RGBA_ASTC_8x6_KHR.\n");
279 internalFormat = GL_COMPRESSED_RGBA_ASTC_8x6_KHR;
282 case COMPRESSED_RGBA_ASTC_8x8_KHR:
284 DALI_LOG_INFO(Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.1 standard compressed pixel format COMPRESSED_RGBA_ASTC_8x8_KHR.\n");
285 internalFormat = GL_COMPRESSED_RGBA_ASTC_8x8_KHR;
288 case COMPRESSED_RGBA_ASTC_10x5_KHR:
290 DALI_LOG_INFO(Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.1 standard compressed pixel format COMPRESSED_RGBA_ASTC_10x5_KHR.\n");
291 internalFormat = GL_COMPRESSED_RGBA_ASTC_10x5_KHR;
294 case COMPRESSED_RGBA_ASTC_10x6_KHR:
296 DALI_LOG_INFO(Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.1 standard compressed pixel format COMPRESSED_RGBA_ASTC_10x6_KHR.\n");
297 internalFormat = GL_COMPRESSED_RGBA_ASTC_10x6_KHR;
300 case COMPRESSED_RGBA_ASTC_10x8_KHR:
302 DALI_LOG_INFO(Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.1 standard compressed pixel format COMPRESSED_RGBA_ASTC_10x8_KHR.\n");
303 internalFormat = GL_COMPRESSED_RGBA_ASTC_10x8_KHR;
306 case COMPRESSED_RGBA_ASTC_10x10_KHR:
308 DALI_LOG_INFO(Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.1 standard compressed pixel format COMPRESSED_RGBA_ASTC_10x10_KHR.\n");
309 internalFormat = GL_COMPRESSED_RGBA_ASTC_10x10_KHR;
312 case COMPRESSED_RGBA_ASTC_12x10_KHR:
314 DALI_LOG_INFO(Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.1 standard compressed pixel format COMPRESSED_RGBA_ASTC_12x10_KHR.\n");
315 internalFormat = GL_COMPRESSED_RGBA_ASTC_12x10_KHR;
318 case COMPRESSED_RGBA_ASTC_12x12_KHR:
320 DALI_LOG_INFO(Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.1 standard compressed pixel format COMPRESSED_RGBA_ASTC_12x12_KHR.\n");
321 internalFormat = GL_COMPRESSED_RGBA_ASTC_12x12_KHR;
324 case COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR:
326 DALI_LOG_INFO(Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.1 standard compressed pixel format COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR.\n");
327 internalFormat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR;
330 case COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR:
332 DALI_LOG_INFO(Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.1 standard compressed pixel format COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR.\n");
333 internalFormat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR;
336 case COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR:
338 DALI_LOG_INFO(Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.1 standard compressed pixel format COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR.\n");
339 internalFormat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR;
342 case COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR:
344 DALI_LOG_INFO(Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.1 standard compressed pixel format COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR.\n");
345 internalFormat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR;
348 case COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR:
350 DALI_LOG_INFO(Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.1 standard compressed pixel format COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR.\n");
351 internalFormat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR;
354 case COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR:
356 DALI_LOG_INFO(Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.1 standard compressed pixel format COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR.\n");
357 internalFormat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR;
360 case COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR:
362 DALI_LOG_INFO(Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.1 standard compressed pixel format COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR.\n");
363 internalFormat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR;
366 case COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR:
368 DALI_LOG_INFO(Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.1 standard compressed pixel format COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR.\n");
369 internalFormat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR;
372 case COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR:
374 DALI_LOG_INFO(Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.1 standard compressed pixel format COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR.\n");
375 internalFormat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR;
378 case COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR:
380 DALI_LOG_INFO(Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.1 standard compressed pixel format COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR.\n");
381 internalFormat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR;
384 case COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR:
386 DALI_LOG_INFO(Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.1 standard compressed pixel format COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR.\n");
387 internalFormat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR;
390 case COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR:
392 DALI_LOG_INFO(Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.1 standard compressed pixel format COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR.\n");
393 internalFormat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR;
396 case COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR:
398 DALI_LOG_INFO(Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.1 standard compressed pixel format COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR.\n");
399 internalFormat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR;
402 case COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR:
404 DALI_LOG_INFO(Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.1 standard compressed pixel format COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR.\n");
405 internalFormat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR;
409 // GLES 3.0 floating point formats.
412 DALI_LOG_INFO(Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.0 GLES 3.0 floating point format.\n");
413 pixelDataType = GL_HALF_FLOAT;
414 internalFormat = GL_RGB;
419 DALI_LOG_INFO(Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.0 GLES 3.0 floating point format.\n");
420 pixelDataType = GL_FLOAT;
421 internalFormat = GL_RGB;
426 DALI_LOG_INFO(Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.0 GLES 3.0 floating point format.\n");
427 pixelDataType = GL_FLOAT;
428 internalFormat = GL_R11F_G11F_B10F;
432 // GLES 3.0 depth and stencil formats
433 case Pixel::DEPTH_UNSIGNED_INT:
435 pixelDataType = GL_UNSIGNED_INT;
436 internalFormat = GL_DEPTH_COMPONENT;
439 case Pixel::DEPTH_FLOAT:
441 pixelDataType = GL_FLOAT;
442 internalFormat = GL_DEPTH_COMPONENT;
445 case Pixel::DEPTH_STENCIL:
447 pixelDataType = GL_UNSIGNED_INT_24_8;
448 internalFormat = GL_DEPTH_STENCIL;
452 // Chrominance formats
453 case Pixel::CHROMINANCE_U:
455 pixelDataType = GL_UNSIGNED_BYTE;
456 internalFormat = GL_LUMINANCE; // GL doesn't support chrominance format. We should convert it in the shader.
459 case Pixel::CHROMINANCE_V:
461 pixelDataType = GL_UNSIGNED_BYTE;
462 internalFormat = GL_LUMINANCE; // GL doesn't support chrominance format. We should convert it in the shader.
468 DALI_LOG_ERROR("Invalid pixel format for bitmap\n");
475 Bitmap* Bitmap::New(const Profile profile = BITMAP_2D_PACKED_PIXELS,
476 ResourcePolicy::Discardable discardable = ResourcePolicy::OWNED_DISCARD)
478 DALI_ASSERT_DEBUG(profile == BITMAP_2D_PACKED_PIXELS || profile == BITMAP_COMPRESSED);
482 /** A 2D array of pixels where each pixel is a whole number of bytes
483 * and each scanline of the backing memory buffer may have additional
484 * bytes off the right edge if requested, and there may be additional
485 * scanlines past the bottom of the image in the buffer if requested.*/
486 case BITMAP_2D_PACKED_PIXELS:
488 Bitmap* const bitmap = new Dali::Internal::BitmapPackedPixel(discardable);
492 /** The data for the bitmap is buffered in an opaque form.*/
493 case BITMAP_COMPRESSED:
495 return new Dali::Internal::BitmapCompressed(discardable);
501 Bitmap::Bitmap(ResourcePolicy::Discardable discardable, Dali::Integration::PixelBuffer* pixBuf)
504 mPixelFormat(Pixel::RGBA8888),
505 mHasAlphaChannel(true),
506 mAlphaChannelUsed(true),
508 mDiscardable(discardable)
512 PixelBuffer* Bitmap::GetBufferOwnership()
514 PixelBuffer* buffer = mData;
519 void Bitmap::DiscardBuffer()
521 if(mDiscardable == ResourcePolicy::OWNED_DISCARD)
529 DALI_LOG_TRACE_METHOD(Debug::Filter::gImage);
535 void Bitmap::DeletePixelBuffer()
545 void Bitmap::Initialize(Pixel::Format pixelFormat,
549 DALI_ASSERT_DEBUG(width * height < (32 * 1024) * (32 * 1024) && "The total area of the bitmap is too great.\n");
551 mImageHeight = height;
552 mPixelFormat = pixelFormat;
554 mHasAlphaChannel = Pixel::HasAlpha(pixelFormat);
557 } //namespace Integration