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