7e0af70b1305777fd1b9819255ab5705b742a83b
[platform/core/uifw/dali-core.git] / dali / internal / render / renderers / render-texture.cpp
1 /*
2  * Copyright (c) 2017 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/devel-api/images/native-image-interface-extension.h>
25
26 namespace Dali
27 {
28 namespace Internal
29 {
30 namespace Render
31 {
32
33 namespace
34 {
35
36 // These match the GL specification
37 const GLint GL_MINIFY_DEFAULT  = GL_NEAREST_MIPMAP_LINEAR;
38 const GLint GL_MAGNIFY_DEFAULT = GL_LINEAR;
39 const GLint GL_WRAP_DEFAULT  = GL_CLAMP_TO_EDGE;
40
41 // These are the Dali defaults
42 const GLint DALI_MINIFY_DEFAULT  = GL_LINEAR;
43 const GLint DALI_MAGNIFY_DEFAULT = GL_LINEAR;
44
45 /**
46  * @brief Convert a FilterMode to its corresponding GL type.
47  *
48  * @param[in] filterMode The FilterMode type.
49  * @param[in] daliDefault The filter mode to use if filterMode is DEFAULT.
50  * @param[in] glDefault The filter mode to use if filterMode is NONE.
51  * @return the equivalent GL filter mode.
52  */
53 GLint FilterModeToGL( FilterMode::Type filterMode, GLint daliDefault, GLint glDefault )
54 {
55   switch( filterMode )
56   {
57     case FilterMode::NEAREST:
58     {
59       return GL_NEAREST;
60     }
61     case FilterMode::LINEAR:
62     {
63       return GL_LINEAR;
64     }
65     case FilterMode::NONE:
66     {
67       return glDefault;
68     }
69     case FilterMode::NEAREST_MIPMAP_NEAREST:
70     {
71       return GL_NEAREST_MIPMAP_NEAREST;
72     }
73     case FilterMode::LINEAR_MIPMAP_NEAREST:
74     {
75       return GL_LINEAR_MIPMAP_NEAREST;
76     }
77     case FilterMode::NEAREST_MIPMAP_LINEAR:
78     {
79       return GL_NEAREST_MIPMAP_LINEAR;
80     }
81     case FilterMode::LINEAR_MIPMAP_LINEAR:
82     {
83       return GL_LINEAR_MIPMAP_LINEAR;
84     }
85     case FilterMode::DEFAULT:
86     {
87       return daliDefault;
88     }
89   }
90
91   return daliDefault;
92 }
93
94 /**
95  * @brief Convert from a WrapMode to its corresponding GL enumeration
96  * @param[in] wrapMode The wrap mode
97  * @param[in] defaultWrapMode The mode to use if WrapMode is Default
98  * @return The equivalent GL wrap mode
99  */
100 GLint WrapModeToGL( WrapMode::Type wrapMode, GLint defaultWrapMode )
101 {
102   switch( wrapMode )
103   {
104     case WrapMode::CLAMP_TO_EDGE:
105     {
106       return GL_CLAMP_TO_EDGE;
107     }
108     case WrapMode::REPEAT:
109     {
110       return GL_REPEAT;
111     }
112     case WrapMode::MIRRORED_REPEAT:
113     {
114       return GL_MIRRORED_REPEAT;
115     }
116     case WrapMode::DEFAULT:
117     {
118       return defaultWrapMode;
119     }
120   }
121
122   return defaultWrapMode;
123 }
124
125 /**
126  * @brief Retrives the GL format, GL internal format and pixel data type from a Pixel::Format
127  * @param[in] pixelFormat The pixel format.
128  * @param[out] glFormat The gl format.
129  * @param[out] glInternalFormat The gl internal format.
130  * @param[out] pixelDataType The data type of the pixel data.
131  */
132 void PixelFormatToGl( Pixel::Format pixelFormat, GLenum& glFormat, GLint& glInternalFormat, GLenum& pixelDataType )
133 {
134   // Compressed textures have no pixelDataType, so init to an invalid value:
135   pixelDataType  = -1;
136
137   switch( pixelFormat )
138   {
139     case Pixel::A8:
140     {
141       pixelDataType = GL_UNSIGNED_BYTE;
142       glFormat= GL_ALPHA;
143       break;
144     }
145
146     case Pixel::L8:
147     {
148       pixelDataType = GL_UNSIGNED_BYTE;
149       glFormat= GL_LUMINANCE;
150       break;
151     }
152
153     case Pixel::LA88:
154     {
155       pixelDataType = GL_UNSIGNED_BYTE;
156       glFormat= GL_LUMINANCE_ALPHA;
157       break;
158     }
159
160     case Pixel::RGB565:
161     {
162       pixelDataType = GL_UNSIGNED_SHORT_5_6_5;
163       glFormat= GL_RGB;
164       break;
165     }
166
167     case Pixel::BGR565:
168     {
169       DALI_LOG_ERROR("Pixel format BGR565 is not supported by GLES.\n");
170       pixelDataType  = GL_UNSIGNED_SHORT_5_6_5;
171 #ifdef _ARCH_ARM_
172       glFormat= GL_BGRA_EXT; // alpha is reserved but not used
173 #else
174       glFormat= GL_RGBA;     // alpha is reserved but not used
175 #endif
176       break;
177     }
178
179     case Pixel::RGBA4444:
180     {
181       pixelDataType = GL_UNSIGNED_SHORT_4_4_4_4;
182       glFormat= GL_RGBA;
183       break;
184     }
185
186     case Pixel::BGRA4444:
187     {
188       DALI_LOG_ERROR("Pixel format BGRA4444 is not supported by GLES.\n");
189       pixelDataType  = GL_UNSIGNED_SHORT_4_4_4_4;
190 #ifdef _ARCH_ARM_
191       glFormat= GL_BGRA_EXT; // alpha is reserved but not used
192 #else
193       glFormat= GL_RGBA;     // alpha is reserved but not used
194 #endif
195       break;
196     }
197
198     case Pixel::RGBA5551:
199     {
200       pixelDataType = GL_UNSIGNED_SHORT_5_5_5_1;
201       glFormat= GL_RGBA;
202       break;
203     }
204
205     case Pixel::BGRA5551:
206     {
207       DALI_LOG_ERROR("Pixel format BGRA5551 is not supported by GLES.\n");
208       pixelDataType  = GL_UNSIGNED_SHORT_5_5_5_1;
209 #ifdef _ARCH_ARM_
210       glFormat= GL_BGRA_EXT; // alpha is reserved but not used
211 #else
212       glFormat= GL_RGBA;     // alpha is reserved but not used
213 #endif
214       break;
215     }
216
217     case Pixel::RGB888:
218     {
219       pixelDataType = GL_UNSIGNED_BYTE;
220       glFormat= GL_RGB;
221       break;
222     }
223
224     case Pixel::RGB8888:
225     {
226       pixelDataType = GL_UNSIGNED_BYTE;
227       glFormat= GL_RGBA;     // alpha is reserved but not used
228       break;
229     }
230
231     case Pixel::BGR8888:
232     {
233       pixelDataType = GL_UNSIGNED_BYTE;
234 #ifdef GL_BGRA_EXT
235       glFormat= GL_BGRA_EXT; // alpha is reserved but not used
236 #else
237       glFormat= GL_RGBA;     // alpha is reserved but not used
238 #endif
239     break;
240     }
241
242     case Pixel::RGBA8888:
243     {
244       pixelDataType = GL_UNSIGNED_BYTE;
245       glFormat= GL_RGBA;
246       break;
247     }
248
249     case Pixel::BGRA8888:
250     {
251       pixelDataType = GL_UNSIGNED_BYTE;
252 #ifdef GL_BGRA_EXT
253       glFormat= GL_BGRA_EXT; // alpha is reserved but not used
254 #else
255       glFormat= GL_RGBA;     // alpha is reserved but not used
256 #endif
257       break;
258     }
259
260     // GLES 2 extension compressed formats:
261     case Pixel::COMPRESSED_RGB8_ETC1:
262     {
263       DALI_LOG_INFO( Debug::Filter::gImage, Debug::Verbose, "Using non-standard GLES 2.0 extension compressed pixel format COMPRESSED_RGB8_ETC1.\n" );
264       glFormat = 0x8D64; ///! < Hardcoded so we can test before we move to GLES 3.0 or greater.
265       break;
266     }
267     case Pixel::COMPRESSED_RGB_PVRTC_4BPPV1:
268     {
269       DALI_LOG_INFO( Debug::Filter::gImage, Debug::Verbose, "Using non-standard GLES 2.0 extension compressed pixel format COMPRESSED_RGB_PVRTC_4BPPV1.\n" );
270       glFormat = 0x8C00; ///! < Hardcoded so we can test before we move to GLES 3.0 or greater.
271       break;
272     }
273
274     // GLES 3.0 standard compressed formats:
275     case Pixel::COMPRESSED_R11_EAC:
276     {
277       DALI_LOG_INFO(Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.0 standard compressed pixel format COMPRESSED_R11_EAC.\n");
278       glFormat = GL_COMPRESSED_R11_EAC;
279       break;
280     }
281     case Pixel::COMPRESSED_SIGNED_R11_EAC:
282     {
283       DALI_LOG_INFO( Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.0 standard compressed pixel format COMPRESSED_SIGNED_R11_EAC.\n" );
284       glFormat = GL_COMPRESSED_SIGNED_R11_EAC;
285       break;
286     }
287     case Pixel::COMPRESSED_RG11_EAC:
288     {
289       DALI_LOG_INFO( Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.0 standard compressed pixel format COMPRESSED_RG11_EAC.\n" );
290       glFormat = GL_COMPRESSED_RG11_EAC;
291       break;
292     }
293     case Pixel::COMPRESSED_SIGNED_RG11_EAC:
294     {
295       DALI_LOG_INFO( Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.0 standard compressed pixel format COMPRESSED_SIGNED_RG11_EAC.\n" );
296       glFormat = GL_COMPRESSED_SIGNED_RG11_EAC;
297       break;
298     }
299     case Pixel::COMPRESSED_RGB8_ETC2:
300     {
301       DALI_LOG_INFO( Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.0 standard compressed pixel format COMPRESSED_RGB8_ETC2.\n" );
302       glFormat = GL_COMPRESSED_RGB8_ETC2;
303       break;
304     }
305     case Pixel::COMPRESSED_SRGB8_ETC2:
306     {
307       DALI_LOG_INFO( Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.0 standard compressed pixel format COMPRESSED_SRGB8_ETC2.\n" );
308       glFormat = GL_COMPRESSED_SRGB8_ETC2;
309       break;
310     }
311     case Pixel::COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
312     {
313       DALI_LOG_INFO( Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.0 standard compressed pixel format COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2.\n" );
314       glFormat = GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2;
315       break;
316     }
317     case Pixel::COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
318     {
319       DALI_LOG_INFO( Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.0 standard compressed pixel format COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2.\n" );
320       glFormat = GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2;
321       break;
322     }
323     case Pixel::COMPRESSED_RGBA8_ETC2_EAC:
324     {
325       DALI_LOG_INFO( Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.0 standard compressed pixel format COMPRESSED_RGBA8_ETC2_EAC.\n" );
326       glFormat = GL_COMPRESSED_RGBA8_ETC2_EAC;
327       break;
328     }
329     case Pixel::COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
330     {
331       DALI_LOG_INFO( Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.0 standard compressed pixel format COMPRESSED_SRGB8_ALPHA8_ETC2_EAC.\n" );
332       glFormat = GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC;
333       break;
334     }
335
336     // GLES 3.1 extension compressed formats:
337     case Pixel::COMPRESSED_RGBA_ASTC_4x4_KHR:
338     {
339       DALI_LOG_INFO( Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.1 standard compressed pixel format COMPRESSED_RGBA_ASTC_4x4_KHR.\n" );
340       glFormat = GL_COMPRESSED_RGBA_ASTC_4x4_KHR;
341       break;
342     }
343     case Pixel::COMPRESSED_RGBA_ASTC_5x4_KHR:
344     {
345       DALI_LOG_INFO( Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.1 standard compressed pixel format COMPRESSED_RGBA_ASTC_5x4_KHR.\n" );
346       glFormat = GL_COMPRESSED_RGBA_ASTC_5x4_KHR;
347       break;
348     }
349     case Pixel::COMPRESSED_RGBA_ASTC_5x5_KHR:
350     {
351       DALI_LOG_INFO( Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.1 standard compressed pixel format COMPRESSED_RGBA_ASTC_5x5_KHR.\n" );
352       glFormat = GL_COMPRESSED_RGBA_ASTC_5x5_KHR;
353       break;
354     }
355     case Pixel::COMPRESSED_RGBA_ASTC_6x5_KHR:
356     {
357       DALI_LOG_INFO( Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.1 standard compressed pixel format COMPRESSED_RGBA_ASTC_6x5_KHR.\n" );
358       glFormat = GL_COMPRESSED_RGBA_ASTC_6x5_KHR;
359       break;
360     }
361     case Pixel::COMPRESSED_RGBA_ASTC_6x6_KHR:
362     {
363       DALI_LOG_INFO( Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.1 standard compressed pixel format COMPRESSED_RGBA_ASTC_6x6_KHR.\n" );
364       glFormat = GL_COMPRESSED_RGBA_ASTC_6x6_KHR;
365       break;
366     }
367     case Pixel::COMPRESSED_RGBA_ASTC_8x5_KHR:
368     {
369       DALI_LOG_INFO( Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.1 standard compressed pixel format COMPRESSED_RGBA_ASTC_8x5_KHR.\n" );
370       glFormat = GL_COMPRESSED_RGBA_ASTC_8x5_KHR;
371       break;
372     }
373     case Pixel::COMPRESSED_RGBA_ASTC_8x6_KHR:
374     {
375       DALI_LOG_INFO( Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.1 standard compressed pixel format COMPRESSED_RGBA_ASTC_8x6_KHR.\n" );
376       glFormat = GL_COMPRESSED_RGBA_ASTC_8x6_KHR;
377       break;
378     }
379     case Pixel::COMPRESSED_RGBA_ASTC_8x8_KHR:
380     {
381       DALI_LOG_INFO( Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.1 standard compressed pixel format COMPRESSED_RGBA_ASTC_8x8_KHR.\n" );
382       glFormat = GL_COMPRESSED_RGBA_ASTC_8x8_KHR;
383       break;
384     }
385     case Pixel::COMPRESSED_RGBA_ASTC_10x5_KHR:
386     {
387       DALI_LOG_INFO( Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.1 standard compressed pixel format COMPRESSED_RGBA_ASTC_10x5_KHR.\n" );
388       glFormat = GL_COMPRESSED_RGBA_ASTC_10x5_KHR;
389       break;
390     }
391     case Pixel::COMPRESSED_RGBA_ASTC_10x6_KHR:
392     {
393       DALI_LOG_INFO( Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.1 standard compressed pixel format COMPRESSED_RGBA_ASTC_10x6_KHR.\n" );
394       glFormat = GL_COMPRESSED_RGBA_ASTC_10x6_KHR;
395       break;
396     }
397     case Pixel::COMPRESSED_RGBA_ASTC_10x8_KHR:
398     {
399       DALI_LOG_INFO( Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.1 standard compressed pixel format COMPRESSED_RGBA_ASTC_10x8_KHR.\n" );
400       glFormat = GL_COMPRESSED_RGBA_ASTC_10x8_KHR;
401       break;
402     }
403     case Pixel::COMPRESSED_RGBA_ASTC_10x10_KHR:
404     {
405       DALI_LOG_INFO( Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.1 standard compressed pixel format COMPRESSED_RGBA_ASTC_10x10_KHR.\n" );
406       glFormat = GL_COMPRESSED_RGBA_ASTC_10x10_KHR;
407       break;
408     }
409     case Pixel::COMPRESSED_RGBA_ASTC_12x10_KHR:
410     {
411       DALI_LOG_INFO( Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.1 standard compressed pixel format COMPRESSED_RGBA_ASTC_12x10_KHR.\n" );
412       glFormat = GL_COMPRESSED_RGBA_ASTC_12x10_KHR;
413       break;
414     }
415     case Pixel::COMPRESSED_RGBA_ASTC_12x12_KHR:
416     {
417       DALI_LOG_INFO( Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.1 standard compressed pixel format COMPRESSED_RGBA_ASTC_12x12_KHR.\n" );
418       glFormat = GL_COMPRESSED_RGBA_ASTC_12x12_KHR;
419       break;
420     }
421     case Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR:
422     {
423       DALI_LOG_INFO( Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.1 standard compressed pixel format COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR.\n" );
424       glFormat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR;
425       break;
426     }
427     case Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR:
428     {
429       DALI_LOG_INFO( Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.1 standard compressed pixel format COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR.\n" );
430       glFormat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR;
431       break;
432     }
433     case Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR:
434     {
435       DALI_LOG_INFO( Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.1 standard compressed pixel format COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR.\n" );
436       glFormat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR;
437       break;
438     }
439     case Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR:
440     {
441       DALI_LOG_INFO( Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.1 standard compressed pixel format COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR.\n" );
442       glFormat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR;
443       break;
444     }
445     case Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR:
446     {
447       DALI_LOG_INFO( Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.1 standard compressed pixel format COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR.\n" );
448       glFormat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR;
449       break;
450     }
451     case Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR:
452     {
453       DALI_LOG_INFO( Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.1 standard compressed pixel format COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR.\n" );
454       glFormat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR;
455       break;
456     }
457     case Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR:
458     {
459       DALI_LOG_INFO( Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.1 standard compressed pixel format COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR.\n" );
460       glFormat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR;
461       break;
462     }
463     case Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR:
464     {
465       DALI_LOG_INFO( Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.1 standard compressed pixel format COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR.\n" );
466       glFormat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR;
467       break;
468     }
469     case Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR:
470     {
471       DALI_LOG_INFO( Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.1 standard compressed pixel format COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR.\n" );
472       glFormat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR;
473       break;
474     }
475     case Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR:
476     {
477       DALI_LOG_INFO( Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.1 standard compressed pixel format COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR.\n" );
478       glFormat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR;
479       break;
480     }
481     case Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR:
482     {
483       DALI_LOG_INFO( Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.1 standard compressed pixel format COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR.\n" );
484       glFormat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR;
485       break;
486     }
487     case Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR:
488     {
489       DALI_LOG_INFO( Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.1 standard compressed pixel format COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR.\n" );
490       glFormat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR;
491       break;
492     }
493     case Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR:
494     {
495       DALI_LOG_INFO( Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.1 standard compressed pixel format COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR.\n" );
496       glFormat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR;
497       break;
498     }
499     case Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR:
500     {
501       DALI_LOG_INFO( Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.1 standard compressed pixel format COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR.\n" );
502       glFormat = GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR;
503       break;
504     }
505
506     // GLES 3.0 floating point formats.
507     case Pixel::RGB16F:
508     {
509       glFormat = GL_RGB;
510       pixelDataType = GL_HALF_FLOAT;
511       break;
512     }
513     case Pixel::RGB32F:
514     {
515       glFormat = GL_RGB;
516       pixelDataType = GL_FLOAT;
517       break;
518     }
519
520     case Pixel::INVALID:
521     {
522       DALI_LOG_ERROR( "Invalid pixel format for bitmap\n" );
523       glFormat = 0;
524       break;
525     }
526   }
527
528   switch( pixelFormat )
529   {
530     case Pixel::RGB16F:
531     case Pixel::RGB32F: // FALL THROUGH
532     {
533       glInternalFormat = GL_R11F_G11F_B10F;
534       break;
535     }
536     default:
537     {
538       glInternalFormat = glFormat;
539     }
540   }
541
542 }
543
544
545 /**
546  * @brief Whether specified pixel format is compressed.
547  *
548  * @param [in] pixelformat Pixel format
549  * @return true if format is compressed, false otherwise
550  */
551 bool IsCompressedFormat(Pixel::Format pixelFormat)
552 {
553   switch (pixelFormat)
554   {
555     case Pixel::L8:
556     case Pixel::A8:
557     case Pixel::LA88:
558     case Pixel::RGB565:
559     case Pixel::RGBA4444:
560     case Pixel::RGBA5551:
561     case Pixel::BGR565:
562     case Pixel::BGRA4444:
563     case Pixel::BGRA5551:
564     case Pixel::RGB888:
565     case Pixel::RGB8888:
566     case Pixel::BGR8888:
567     case Pixel::RGBA8888:
568     case Pixel::BGRA8888:
569     case Pixel::RGB16F:
570     case Pixel::RGB32F:
571     case Pixel::INVALID:
572     {
573       return false;
574     }
575
576     case Pixel::COMPRESSED_R11_EAC:
577     case Pixel::COMPRESSED_SIGNED_R11_EAC:
578     case Pixel::COMPRESSED_RG11_EAC:
579     case Pixel::COMPRESSED_SIGNED_RG11_EAC:
580     case Pixel::COMPRESSED_RGB8_ETC2:
581     case Pixel::COMPRESSED_SRGB8_ETC2:
582     case Pixel::COMPRESSED_RGB8_ETC1:
583     case Pixel::COMPRESSED_RGB_PVRTC_4BPPV1:
584     case Pixel::COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
585     case Pixel::COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
586     case Pixel::COMPRESSED_RGBA8_ETC2_EAC:
587     case Pixel::COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
588     case Pixel::COMPRESSED_RGBA_ASTC_4x4_KHR:
589     case Pixel::COMPRESSED_RGBA_ASTC_5x4_KHR:
590     case Pixel::COMPRESSED_RGBA_ASTC_5x5_KHR:
591     case Pixel::COMPRESSED_RGBA_ASTC_6x5_KHR:
592     case Pixel::COMPRESSED_RGBA_ASTC_6x6_KHR:
593     case Pixel::COMPRESSED_RGBA_ASTC_8x5_KHR:
594     case Pixel::COMPRESSED_RGBA_ASTC_8x6_KHR:
595     case Pixel::COMPRESSED_RGBA_ASTC_8x8_KHR:
596     case Pixel::COMPRESSED_RGBA_ASTC_10x5_KHR:
597     case Pixel::COMPRESSED_RGBA_ASTC_10x6_KHR:
598     case Pixel::COMPRESSED_RGBA_ASTC_10x8_KHR:
599     case Pixel::COMPRESSED_RGBA_ASTC_10x10_KHR:
600     case Pixel::COMPRESSED_RGBA_ASTC_12x10_KHR:
601     case Pixel::COMPRESSED_RGBA_ASTC_12x12_KHR:
602     case Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR:
603     case Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR:
604     case Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR:
605     case Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR:
606     case Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR:
607     case Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR:
608     case Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR:
609     case Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR:
610     case Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR:
611     case Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR:
612     case Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR:
613     case Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR:
614     case Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR:
615     case Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR:
616     {
617       return true;
618     }
619   }
620
621   return false;
622 }
623
624 } //Unnamed namespace
625
626
627 Texture::Texture( Type type, Pixel::Format format, ImageDimensions size )
628 : mNativeImage(),
629   mSampler(),
630   mId( 0 ),
631   mTarget( ( type == TextureType::TEXTURE_2D ) ? GL_TEXTURE_2D : GL_TEXTURE_CUBE_MAP ),
632   mGlInternalFormat( GL_RGB ),
633   mGlFormat( GL_RGB ),
634   mPixelDataType( GL_UNSIGNED_BYTE ),
635   mWidth( size.GetWidth() ),
636   mHeight( size.GetHeight() ),
637   mMaxMipMapLevel( 0 ),
638   mType( type ),
639   mHasAlpha( HasAlpha( format ) ),
640   mIsCompressed( IsCompressedFormat( format ) )
641 {
642   PixelFormatToGl( format,
643                    mGlFormat,
644                    mGlInternalFormat,
645                    mPixelDataType );
646 }
647
648 Texture::Texture( NativeImageInterfacePtr nativeImageInterface )
649 : mNativeImage( nativeImageInterface ),
650   mSampler(),
651   mId( 0 ),
652   mTarget( GL_TEXTURE_2D ),
653   mGlInternalFormat( GL_RGB ),
654   mGlFormat( GL_RGB ),
655   mPixelDataType( GL_UNSIGNED_BYTE ),
656   mWidth( nativeImageInterface->GetWidth() ),
657   mHeight( nativeImageInterface->GetHeight() ),
658   mMaxMipMapLevel( 0 ),
659   mType( TextureType::TEXTURE_2D ),
660   mHasAlpha( nativeImageInterface->RequiresBlending() ),
661   mIsCompressed( false )
662 {
663 }
664
665 Texture::~Texture()
666 {}
667
668 void Texture::Destroy( Context& context )
669 {
670   if( mId )
671   {
672     context.DeleteTextures( 1, &mId );
673
674     if( mNativeImage )
675     {
676       mNativeImage->GlExtensionDestroy();
677     }
678   }
679 }
680
681 void Texture::GlContextDestroyed()
682 {
683   mId = 0u;
684 }
685
686 void Texture::Initialize(Context& context)
687 {
688   if( mNativeImage )
689   {
690     if( mNativeImage->GlExtensionCreate() )
691     {
692       NativeImageInterface::Extension* extension = mNativeImage->GetExtension();
693       if( extension )
694       {
695         mTarget = extension->GetEglImageTextureTarget();
696       }
697
698       context.GenTextures( 1, &mId );
699       context.BindTexture( mTarget, mId );
700       context.PixelStorei( GL_UNPACK_ALIGNMENT, 1 ); // We always use tightly packed data
701
702       //Apply default sampling parameters
703       context.TexParameteri( mTarget, GL_TEXTURE_MIN_FILTER, DALI_MINIFY_DEFAULT );
704       context.TexParameteri( mTarget, GL_TEXTURE_MAG_FILTER, DALI_MAGNIFY_DEFAULT );
705       context.TexParameteri( mTarget, GL_TEXTURE_WRAP_S, GL_WRAP_DEFAULT );
706       context.TexParameteri( mTarget, GL_TEXTURE_WRAP_T, GL_WRAP_DEFAULT );
707
708       // platform specific implementation decides on what GL extension to use
709       if( mNativeImage->TargetTexture() != 0u )
710       {
711         context.DeleteTextures( 1, &mId );
712         mNativeImage->GlExtensionDestroy();
713         mId = 0u;
714       }
715     }
716   }
717   else
718   {
719     //Create the texture and reserve memory for the first mipmap level.
720     context.GenTextures( 1, &mId );
721     context.BindTexture( mTarget, mId );
722     context.PixelStorei( GL_UNPACK_ALIGNMENT, 1 ); // We always use tightly packed data
723
724     //Apply default sampling parameters
725     context.TexParameteri( mTarget, GL_TEXTURE_MIN_FILTER, DALI_MINIFY_DEFAULT );
726     context.TexParameteri( mTarget, GL_TEXTURE_MAG_FILTER, DALI_MAGNIFY_DEFAULT );
727     context.TexParameteri( mTarget, GL_TEXTURE_WRAP_S, GL_WRAP_DEFAULT );
728     context.TexParameteri( mTarget, GL_TEXTURE_WRAP_T, GL_WRAP_DEFAULT );
729
730     if( mType == TextureType::TEXTURE_2D )
731     {
732       if( !mIsCompressed )
733       {
734         context.TexImage2D(GL_TEXTURE_2D, 0, mGlInternalFormat, mWidth, mHeight, 0, mGlFormat, mPixelDataType, 0 );
735       }
736       else
737       {
738         context.CompressedTexImage2D(GL_TEXTURE_2D, 0, mGlInternalFormat, mWidth, mHeight, 0, 0, 0 );
739       }
740     }
741     else if( mType == TextureType::TEXTURE_CUBE )
742     {
743       if( !mIsCompressed )
744       {
745         for( unsigned int i(0); i<6; ++i )
746         {
747           context.TexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, mGlInternalFormat, mWidth, mHeight, 0, mGlFormat, mPixelDataType, 0 );
748         }
749       }
750       else
751       {
752         for( unsigned int i(0); i<6; ++i )
753         {
754           context.CompressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, mGlInternalFormat, mWidth, mHeight, 0, 0, 0 );
755         }
756       }
757       context.TexParameteri( mTarget, GL_TEXTURE_WRAP_R, GL_WRAP_DEFAULT );
758     }
759   }
760 }
761
762 void Texture::Upload( Context& context, PixelDataPtr pixelData, const Internal::Texture::UploadParams& params  )
763 {
764   DALI_ASSERT_ALWAYS( mNativeImage == NULL );
765
766   //Get pointer to the data of the PixelData object
767   unsigned char* buffer( pixelData->GetBuffer() );
768
769   //This buffer is only used if manually converting from RGB to RGBA
770   unsigned char* tempBuffer(0);
771
772   //Retrieves the pixel data element type, the gl format and gl internal format of the data contained in the PixelData object.
773   GLenum glFormat;
774   GLint glInternalFormat;
775   GLenum pixelDataElementType;
776   PixelFormatToGl( pixelData->GetPixelFormat(), glFormat, glInternalFormat, pixelDataElementType );
777
778   //Get the maximum mipmap level to set GL_TEXTURE_MAX_LEVEL parameter in GLES3x because is not
779   //necessary to upload all the mipmap levels
780   mMaxMipMapLevel = ( mMaxMipMapLevel > params.mipmap ) ? mMaxMipMapLevel : params.mipmap;
781
782   const bool isSubImage = ( ( params.xOffset != 0 ) ||
783                             ( params.yOffset != 0 ) ||
784                             ( params.width  != ( mWidth  / ( 1 << params.mipmap ) ) ) ||
785                             ( params.height != ( mHeight / ( 1 << params.mipmap ) ) ) );
786
787   bool convert = ( ( glFormat == GL_RGB ) && ( mGlFormat == GL_RGBA ) );
788 #if DALI_GLES_VERSION >= 30
789   // Don't convert manually from RGB to RGBA if GLES >= 3.0 and a sub-image is uploaded.
790   convert = convert && !isSubImage;
791 #endif
792
793   if( convert )
794   {
795     size_t dataSize = static_cast< size_t >( params.width ) * params.height;
796     tempBuffer = new unsigned char[dataSize*4u];
797     for( size_t i(0u); i<dataSize; i++ )
798     {
799       tempBuffer[i*4u]   = buffer[i*3u];
800       tempBuffer[i*4u+1] = buffer[i*3u+1];
801       tempBuffer[i*4u+2] = buffer[i*3u+2];
802       tempBuffer[i*4u+3] = 0xFF;
803     }
804
805     buffer = tempBuffer;
806     glFormat = mGlFormat; // Set the glFormat to GL_RGBA
807   }
808
809   //Upload data to the texture
810
811   context.BindTexture( mTarget, mId );
812   GLenum target( mTarget );
813   if( mType == TextureType::TEXTURE_CUBE )
814   {
815     target = GL_TEXTURE_CUBE_MAP_POSITIVE_X + params.layer;
816   }
817
818   context.PixelStorei( GL_UNPACK_ALIGNMENT, 1 );
819
820   if( !isSubImage )
821   {
822     //Specifying the whole image for the mipmap. We cannot assume that storage for that mipmap has been created so we need to use TexImage2D
823     if( !mIsCompressed )
824     {
825       context.TexImage2D( target, params.mipmap, mGlInternalFormat, params.width, params.height, 0, glFormat, pixelDataElementType, buffer );
826     }
827     else
828     {
829       context.CompressedTexImage2D( target, params.mipmap, mGlInternalFormat, params.width, params.height, 0, pixelData->GetBufferSize(), buffer );
830     }
831   }
832   else
833   {
834     //Specifying part of the image for the mipmap
835     if( !mIsCompressed )
836     {
837       context.TexSubImage2D( target, params.mipmap,
838                              params.xOffset, params.yOffset, params.width, params.height,
839                              glFormat, pixelDataElementType, buffer );
840     }
841     else
842     {
843       context.CompressedTexSubImage2D( target, params.mipmap,
844                                        params.xOffset, params.yOffset, params.width, params.height,
845                                        glFormat, pixelData->GetBufferSize(), buffer );
846     }
847   }
848
849
850   //Destroy temp buffer used for conversion RGB->RGBA
851   delete[] tempBuffer;
852 }
853
854 bool Texture::Bind( Context& context, unsigned int textureUnit, Render::Sampler* sampler )
855 {
856   if( mNativeImage && mId == 0 )
857   {
858     Initialize( context );
859   }
860
861   if( mId != 0 )
862   {
863     context.ActiveTexture( static_cast<TextureUnit>(textureUnit) );
864     context.BindTexture( mTarget, mId );
865     ApplySampler( context, sampler );
866
867     if( mNativeImage )
868     {
869       mNativeImage->PrepareTexture();
870     }
871
872     return true;
873   }
874
875   return false;
876 }
877
878 void Texture::ApplySampler( Context& context, Render::Sampler* sampler )
879 {
880   Render::Sampler oldSampler = mSampler;
881   mSampler = sampler ? *sampler : Sampler();
882
883   if( mSampler != oldSampler )
884   {
885     GLint mode = FilterModeToGL( mSampler.mMinificationFilter, DALI_MINIFY_DEFAULT, GL_MINIFY_DEFAULT );
886     if( mode != FilterModeToGL( oldSampler.mMinificationFilter, DALI_MINIFY_DEFAULT, GL_MINIFY_DEFAULT ) )
887     {
888       context.TexParameteri( mTarget, GL_TEXTURE_MIN_FILTER, mode );
889     }
890
891     mode = FilterModeToGL( mSampler.mMagnificationFilter, DALI_MAGNIFY_DEFAULT, GL_MAGNIFY_DEFAULT );
892     if( mode != FilterModeToGL( oldSampler.mMagnificationFilter, DALI_MAGNIFY_DEFAULT, GL_MAGNIFY_DEFAULT ) )
893     {
894       context.TexParameteri( mTarget, GL_TEXTURE_MAG_FILTER, mode );
895     }
896
897     mode = WrapModeToGL( mSampler.mSWrapMode, GL_WRAP_DEFAULT );
898     if( mode != WrapModeToGL( oldSampler.mSWrapMode, GL_WRAP_DEFAULT ) )
899     {
900       context.TexParameteri( mTarget, GL_TEXTURE_WRAP_S, mode );
901     }
902
903     mode = WrapModeToGL( mSampler.mTWrapMode, GL_WRAP_DEFAULT );
904     if( mode != WrapModeToGL( oldSampler.mTWrapMode, GL_WRAP_DEFAULT ) )
905     {
906       context.TexParameteri( mTarget, GL_TEXTURE_WRAP_T, mode );
907     }
908
909     if( mType == TextureType::TEXTURE_CUBE )
910     {
911       mode = WrapModeToGL( mSampler.mRWrapMode, GL_WRAP_DEFAULT );
912       if( mode != WrapModeToGL( oldSampler.mRWrapMode, GL_WRAP_DEFAULT ) )
913       {
914         context.TexParameteri( mTarget, GL_TEXTURE_WRAP_R, mode );
915       }
916     }
917
918 #if DALI_GLES_VERSION >= 30
919     //In GLES 3.0 we do not need to upload all of the mipmap levels, but GL_TEXTURE_MAX_LEVEL must be set
920     if(mMaxMipMapLevel)
921     {
922       context.TexParameteri( mTarget, GL_TEXTURE_MAX_LEVEL, mMaxMipMapLevel );
923     }
924 #endif
925
926   }
927 }
928
929 bool Texture::HasAlphaChannel()
930 {
931   return mHasAlpha;
932 }
933
934 void Texture::GenerateMipmaps( Context& context )
935 {
936   //GL_TEXTURE_MAX_LEVEL does not need to be set when mipmaps are generated by GL
937   mMaxMipMapLevel = 0;
938   context.BindTexture( mTarget, mId );
939   context.GenerateMipmap( mTarget );
940 }
941
942 } //Render
943
944 } //Internal
945
946 } //Dali