Bitmap core patch 2 of 4 - Replace all uses of the Bitmap class with new simpler...
[platform/core/uifw/dali-core.git] / dali / integration-api / bitmap.cpp
1 //
2 // Copyright (c) 2014 Samsung Electronics Co., Ltd.
3 //
4 // Licensed under the Flora License, Version 1.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://floralicense.org/license/
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/integration-api/bitmap.h>
19
20 // EXTERNAL INCLUDES
21 #include <cstring>
22
23 // INTERNAL INCLUDES
24 #include <dali/integration-api/debug.h>
25 #include <dali/integration-api/image-data.h>
26 #include <dali/internal/event/images/bitmap-packed-pixel.h>
27 #include <dali/internal/event/images/bitmap-compressed.h>
28 #include <dali/internal/event/images/bitmap-external.h>
29 #include <dali/integration-api/gl-abstraction.h>
30 #include <dali/public-api/images/pixel-extras.h>
31
32 namespace Dali
33 {
34
35 namespace Integration
36 {
37 using namespace Dali::Pixel;
38
39 void ConvertToGlFormat( Format pixelformat, unsigned& pixelDataType, unsigned& internalFormat )
40 {
41   // Compressed textures have no pixelDataType, so init to an invalid value:
42   pixelDataType  = -1;
43
44   switch( pixelformat )
45   {
46     case A8:
47     {
48       pixelDataType = GL_UNSIGNED_BYTE;
49       internalFormat= GL_ALPHA;
50       break;
51     }
52
53     case L8:
54     {
55       pixelDataType = GL_UNSIGNED_BYTE;
56       internalFormat= GL_LUMINANCE;
57       break;
58     }
59
60     case LA88:
61     {
62       pixelDataType = GL_UNSIGNED_BYTE;
63       internalFormat= GL_LUMINANCE_ALPHA;
64       break;
65     }
66
67     case RGB565:
68     {
69       pixelDataType = GL_UNSIGNED_SHORT_5_6_5;
70       internalFormat= GL_RGB;
71       break;
72     }
73
74     case BGR565:
75     {
76       DALI_LOG_ERROR("Pixel format BGR565 is not supported by GLES.\n");
77       pixelDataType  = GL_UNSIGNED_SHORT_5_6_5;
78 #ifdef _ARCH_ARM_
79       internalFormat= GL_BGRA_EXT; // alpha is reserved but not used
80 #else
81       internalFormat= GL_RGBA;     // alpha is reserved but not used
82 #endif
83       break;
84     }
85
86     case RGBA4444:
87     {
88       pixelDataType = GL_UNSIGNED_SHORT_4_4_4_4;
89       internalFormat= GL_RGBA;
90       break;
91     }
92
93     case BGRA4444:
94     {
95       DALI_LOG_ERROR("Pixel format BGRA4444 is not supported by GLES.\n");
96       pixelDataType  = GL_UNSIGNED_SHORT_4_4_4_4;
97 #ifdef _ARCH_ARM_
98       internalFormat= GL_BGRA_EXT; // alpha is reserved but not used
99 #else
100       internalFormat= GL_RGBA;     // alpha is reserved but not used
101 #endif
102       break;
103     }
104
105     case RGBA5551:
106     {
107       pixelDataType = GL_UNSIGNED_SHORT_5_5_5_1;
108       internalFormat= GL_RGBA;
109       break;
110     }
111
112     case BGRA5551:
113     {
114       DALI_LOG_ERROR("Pixel format BGRA5551 is not supported by GLES.\n");
115       pixelDataType  = GL_UNSIGNED_SHORT_5_5_5_1;
116 #ifdef _ARCH_ARM_
117       internalFormat= GL_BGRA_EXT; // alpha is reserved but not used
118 #else
119       internalFormat= GL_RGBA;     // alpha is reserved but not used
120 #endif
121       break;
122     }
123
124     case RGB888:
125     {
126       pixelDataType = GL_UNSIGNED_BYTE;
127       internalFormat= GL_RGB;
128       break;
129     }
130
131     case RGB8888:
132     {
133       pixelDataType = GL_UNSIGNED_BYTE;
134       internalFormat= GL_RGBA;     // alpha is reserved but not used
135       break;
136     }
137
138     case BGR8888:
139     {
140       pixelDataType = GL_UNSIGNED_BYTE;
141 #ifdef GL_BGRA_EXT
142       internalFormat= GL_BGRA_EXT; // alpha is reserved but not used
143 #else
144       internalFormat= GL_RGBA;     // alpha is reserved but not used
145 #endif
146     break;
147     }
148
149     case RGBA8888:
150     {
151       pixelDataType = GL_UNSIGNED_BYTE;
152       internalFormat= GL_RGBA;
153       break;
154     }
155
156     case BGRA8888:
157     {
158       pixelDataType = GL_UNSIGNED_BYTE;
159 #ifdef GL_BGRA_EXT
160       internalFormat= GL_BGRA_EXT; // alpha is reserved but not used
161 #else
162       internalFormat= GL_RGBA;     // alpha is reserved but not used
163 #endif
164       break;
165     }
166
167     // GLES 3.0 standard compressed formats:
168     case COMPRESSED_R11_EAC:
169     {
170       DALI_LOG_INFO(Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.0 standard compressed pixel format COMPRESSED_R11_EAC.\n");
171       internalFormat = 0x9270; ///! < Hardcoded until we move to GLES 3.0 or greater.
172       break;
173     }
174     case COMPRESSED_SIGNED_R11_EAC:
175     {
176       DALI_LOG_INFO( Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.0 standard compressed pixel format COMPRESSED_SIGNED_R11_EAC.\n" );
177       internalFormat = 0x9271; ///! < Hardcoded until we move to GLES 3.0 or greater.
178       ;
179       break;
180     }
181     case COMPRESSED_RG11_EAC:
182     {
183       DALI_LOG_INFO( Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.0 standard compressed pixel format COMPRESSED_RG11_EAC.\n" );
184       internalFormat = 0x9272; ///! < Hardcoded until we move to GLES 3.0 or greater.
185       break;
186     }
187     case COMPRESSED_SIGNED_RG11_EAC:
188     {
189       DALI_LOG_INFO( Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.0 standard compressed pixel format COMPRESSED_SIGNED_RG11_EAC.\n" );
190       internalFormat = 0x9273; ///! < Hardcoded until we move to GLES 3.0 or greater.
191       break;
192     }
193     case COMPRESSED_RGB8_ETC2:
194     {
195       DALI_LOG_INFO( Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.0 standard compressed pixel format COMPRESSED_RGB8_ETC2.\n" );
196       internalFormat = 0x9274; ///! < Hardcoded until we move to GLES 3.0 or greater.
197       break;
198     }
199     case COMPRESSED_SRGB8_ETC2:
200     {
201       DALI_LOG_INFO( Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.0 standard compressed pixel format COMPRESSED_SRGB8_ETC2.\n" );
202       internalFormat = 0x9275; ///! < Hardcoded until we move to GLES 3.0 or greater.
203       break;
204     }
205     case COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
206     {
207       DALI_LOG_INFO( Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.0 standard compressed pixel format COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2.\n" );
208       internalFormat = 0x9276; ///! < Hardcoded until we move to GLES 3.0 or greater.
209       break;
210     }
211     case COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
212     {
213       DALI_LOG_INFO( Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.0 standard compressed pixel format COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2.\n" );
214       internalFormat = 0x9277; ///! < Hardcoded until we move to GLES 3.0 or greater.
215       break;
216     }
217     case COMPRESSED_RGBA8_ETC2_EAC:
218     {
219       DALI_LOG_INFO( Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.0 standard compressed pixel format COMPRESSED_RGBA8_ETC2_EAC.\n" );
220       internalFormat = 0x9278; ///! < Hardcoded until we move to GLES 3.0 or greater.
221       break;
222     }
223     case COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
224     {
225       DALI_LOG_INFO( Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.0 standard compressed pixel format COMPRESSED_SRGB8_ALPHA8_ETC2_EAC.\n" );
226       internalFormat = 0x9279; ///! < Hardcoded until we move to GLES 3.0 or greater.
227       break;
228     }
229
230     // GLES 2 extension compressed formats:
231     case COMPRESSED_RGB8_ETC1:
232     {
233       DALI_LOG_INFO( Debug::Filter::gImage, Debug::Verbose, "Using non-standard GLES 2.0 extension compressed pixel format COMPRESSED_RGB8_ETC1.\n" );
234       internalFormat = 0x8D64; ///! < Hardcoded so we can test before we move to GLES 3.0 or greater.
235       break;
236     }
237     case COMPRESSED_RGB_PVRTC_4BPPV1:
238     {
239       DALI_LOG_INFO( Debug::Filter::gImage, Debug::Verbose, "Using non-standard GLES 2.0 extension compressed pixel format COMPRESSED_RGB_PVRTC_4BPPV1.\n" );
240       internalFormat = 0x8C00; ///! < Hardcoded so we can test before we move to GLES 3.0 or greater.
241       break;
242     }
243   }
244 }
245
246 Bitmap* Bitmap::New(const Profile profile = BITMAP_2D_PACKED_PIXELS, const bool managePixelBuffer = true)
247 {
248   DALI_ASSERT_DEBUG(profile == BITMAP_2D_PACKED_PIXELS || profile == BITMAP_COMPRESSED);
249
250   switch( profile )
251   {
252     /** A 2D array of pixels where each pixel is a whole number of bytes
253      * and each scanline of the backing memory buffer may have additional
254      * bytes off the right edge if requested, and there may be additional
255      * scanlines past the bottom of the image in the buffer if requested.*/
256     case BITMAP_2D_PACKED_PIXELS:
257     {
258       return new Dali::Internal::BitmapPackedPixel(managePixelBuffer);
259     }
260
261     /** The data for the bitmap is buffered in an opaque form.*/
262     case BITMAP_COMPRESSED:
263     {
264       return new Dali::Internal::BitmapCompressed(managePixelBuffer);
265     }
266   }
267   return 0;
268 }
269
270 Bitmap* Bitmap::New(const Pixel::Format format)
271 {
272   if( Pixel::IsEncoded( format ) )
273   {
274     return new Dali::Internal::BitmapCompressed(true);
275   }
276   else
277   {
278     return new Dali::Internal::BitmapPackedPixel(true);
279   }
280 }
281
282 Bitmap::Bitmap( bool discardable, Dali::Integration::PixelBuffer* pixBuf)
283 : mImageWidth(0),
284   mImageHeight(0),
285   mPixelFormat(Pixel::RGBA8888),
286   mHasAlphaChannel(true),
287   mAlphaChannelUsed(true),
288   mData(pixBuf),
289   mDiscardable(discardable)
290 {
291 }
292
293 void Bitmap::DiscardBuffer()
294 {
295   if ( mDiscardable )
296   {
297     DeletePixelBuffer();
298   }
299 }
300
301 PixelBuffer* Bitmap::ReleaseBuffer()
302 {
303   PixelBuffer* const data = mData;
304
305   // Ownership of mData has been transferred, so indicate that mData pointer is no longer valid:
306   mData = NULL;
307
308   return data;
309 }
310
311 Bitmap::~Bitmap()
312 {
313   DALI_LOG_TRACE_METHOD(Debug::Filter::gImage);
314   DeletePixelBuffer();
315 }
316
317 /**
318  * */
319 void Bitmap::DeletePixelBuffer()
320 {
321   if( !mData )
322   {
323     return;
324   }
325   delete [] mData;
326   mData = NULL;
327 }
328
329
330 void Bitmap::Initialize( Pixel::Format pixelFormat,
331                           unsigned int width,
332                           unsigned int height )
333 {
334   DALI_ASSERT_DEBUG(width * height < (32 * 1024) * (32 * 1024) && "The total area of the bitmap is too great.\n");
335   mImageWidth   = width;
336   mImageHeight  = height;
337   mPixelFormat  = pixelFormat;
338
339   mHasAlphaChannel = Pixel::HasAlpha(pixelFormat);
340 }
341
342 BitmapPtr ConvertToBitmap( ImageData& imageData )
343 {
344   BitmapPtr bitmap = Bitmap::New( imageData.pixelFormat );
345   Bitmap::PackedPixelsProfile* packedBitmap = bitmap->GetPackedPixelsProfile();
346   if( packedBitmap )
347   {
348     // Pass the buffer of pixels into the new Bitmap:
349     packedBitmap->AssignBuffer( imageData.pixelFormat, imageData.ReleaseImageBuffer(), imageData.dataSize, imageData.imageWidth, imageData.imageHeight, imageData.imageWidth, imageData.imageHeight );
350
351     // Convert the info about the alpha channel:
352     bitmap->SetAlphaChannelUsed( imageData.GetAlphaUsage() == ImageData::ALPHA_USAGE_SOME_TRANSLUCENT );
353   }
354   else
355   {
356     ///@Todo: In one of the follow-on patches, the copy here will be replaced with a buffer ownership assignment, after the Bitmap classes are refactored, rather than enhancing BitmapCompressed in this one.
357     Bitmap::CompressedProfile * compressedBitmap = bitmap->GetCompressedProfile();
358     if( compressedBitmap )
359     {
360       compressedBitmap->ReserveBufferOfSize( imageData.pixelFormat, imageData.imageWidth, imageData.imageHeight, imageData.dataSize );
361       memcpy( bitmap->GetBuffer(), imageData.GetBuffer(), imageData.dataSize );
362     }
363     else
364     {
365       DALI_ASSERT_DEBUG( 0 == "Unknown bitmap profile." );
366     }
367   }
368   return bitmap;
369 }
370
371 } //namespace Integration
372
373 } //namespace Dali
374