[dali_1.2.15] 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::Initialize(Context& context)
637 {
638   if( mNativeImage )
639   {
640     if( mNativeImage->GlExtensionCreate() )
641     {
642       context.GenTextures( 1, &mId );
643       context.Bind2dTexture( mId );
644       context.PixelStorei( GL_UNPACK_ALIGNMENT, 1 ); // We always use tightly packed data
645
646       //Apply default sampling parameters
647       context.TexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, DALI_MINIFY_DEFAULT );
648       context.TexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, DALI_MAGNIFY_DEFAULT );
649       context.TexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_WRAP_DEFAULT );
650       context.TexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_WRAP_DEFAULT );
651
652       // platform specific implementation decides on what GL extension to use
653       if( mNativeImage->TargetTexture() != 0u )
654       {
655         context.DeleteTextures( 1, &mId );
656         mNativeImage->GlExtensionDestroy();
657         mId = 0u;
658       }
659     }
660   }
661   else
662   {
663     context.GenTextures( 1, &mId );
664
665     if( mType == TextureType::TEXTURE_2D )
666     {
667       //Creates the texture and reserves memory for the first mipmap level.
668       context.Bind2dTexture( mId );
669
670       if( !mIsCompressed )
671       {
672         context.TexImage2D(GL_TEXTURE_2D, 0, mInternalFormat, mWidth, mHeight, 0, mInternalFormat, mPixelDataType, 0 );
673       }
674       else
675       {
676         context.CompressedTexImage2D(GL_TEXTURE_2D, 0, mInternalFormat, mWidth, mHeight, 0, 0, 0 );
677       }
678
679       //Apply default sampling parameters
680       context.TexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, DALI_MINIFY_DEFAULT );
681       context.TexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, DALI_MAGNIFY_DEFAULT );
682       context.TexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_WRAP_DEFAULT );
683       context.TexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_WRAP_DEFAULT );
684     }
685     else if( mType == TextureType::TEXTURE_CUBE )
686     {
687       //Creates the texture and reserves memory for the first mipmap level.
688       context.BindCubeMapTexture( mId );
689
690       if( !mIsCompressed )
691       {
692         for( unsigned int i(0); i<6; ++i )
693         {
694           context.TexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, mInternalFormat, mWidth, mHeight, 0, mInternalFormat, mPixelDataType, 0 );
695         }
696       }
697       else
698       {
699         for( unsigned int i(0); i<6; ++i )
700         {
701           context.CompressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, mInternalFormat, mWidth, mHeight, 0, 0, 0 );
702         }
703       }
704
705       //Apply default sampling parameters
706       context.TexParameteri( GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, DALI_MINIFY_DEFAULT );
707       context.TexParameteri( GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, DALI_MAGNIFY_DEFAULT );
708       context.TexParameteri( GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_WRAP_DEFAULT );
709       context.TexParameteri( GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_WRAP_DEFAULT );
710       context.TexParameteri( GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_WRAP_DEFAULT );
711     }
712   }
713 }
714
715 void NewTexture::Upload( Context& context, PixelDataPtr pixelData, const Internal::NewTexture::UploadParams& params  )
716 {
717   DALI_ASSERT_ALWAYS( mNativeImage == NULL );
718
719   //Get pointer to the data of the PixelData object
720   unsigned char* buffer( pixelData->GetBuffer() );
721
722   //This buffer is only used if manually converting from RGB to RGBA
723   unsigned char* tempBuffer(0);
724
725   //Get pixel format and data type of the data contained in the PixelData object
726   GLenum pixelDataFormat, pixelDataElementType;
727   PixelFormatToGl( pixelData->GetPixelFormat(), pixelDataElementType, pixelDataFormat );
728
729 #if DALI_GLES_VERSION < 30
730   if( pixelDataFormat == GL_RGB && mInternalFormat == GL_RGBA )
731   {
732     //Convert manually from RGB to RGBA if GLES < 3 ( GLES 3 can do the conversion automatically when uploading )
733     size_t dataSize = static_cast< size_t >( params.width ) * params.height;
734     tempBuffer = new unsigned char[dataSize*4u];
735     for( size_t i(0u); i<dataSize; i++ )
736     {
737       tempBuffer[i*4u]   = buffer[i*3u];
738       tempBuffer[i*4u+1] = buffer[i*3u+1];
739       tempBuffer[i*4u+2] = buffer[i*3u+2];
740       tempBuffer[i*4u+3] = 0xFF;
741     }
742
743     buffer = tempBuffer;
744     pixelDataFormat = mInternalFormat;
745   }
746 #endif
747
748   //Upload data to the texture
749   GLenum target( GL_NONE );
750   if( mType == TextureType::TEXTURE_2D )
751   {
752     context.Bind2dTexture( mId );
753     target = GL_TEXTURE_2D;
754   }
755   else if( mType == TextureType::TEXTURE_CUBE )
756   {
757     context.BindCubeMapTexture( mId );
758     target = GL_TEXTURE_CUBE_MAP_POSITIVE_X + params.layer;
759   }
760
761   context.PixelStorei( GL_UNPACK_ALIGNMENT, 1 );
762
763   if( params.xOffset == 0 && params.yOffset == 0 &&
764       params.width  == ( mWidth  / (1<<params.mipmap) ) &&
765       params.height == ( mHeight / (1<<params.mipmap) ) )
766   {
767     //Specifying the whole image for the mipmap. We cannot assume that storage for that mipmap has been created so we need to use TexImage2D
768     if( !mIsCompressed )
769     {
770       context.TexImage2D( target, params.mipmap, mInternalFormat, params.width, params.height, 0, pixelDataFormat, pixelDataElementType, buffer );
771     }
772     else
773     {
774       context.CompressedTexImage2D( target, params.mipmap, mInternalFormat, params.width, params.height, 0, pixelData->GetBufferSize(), buffer );
775     }
776   }
777   else
778   {
779     //Specifying part of the image for the mipmap
780     if( !mIsCompressed )
781     {
782       context.TexSubImage2D( target, params.mipmap,
783                              params.xOffset, params.yOffset, params.width, params.height,
784                              pixelDataFormat, pixelDataElementType, buffer );
785     }
786     else
787     {
788       context.CompressedTexSubImage2D( target, params.mipmap,
789                                        params.xOffset, params.yOffset, params.width, params.height,
790                                        pixelDataFormat, pixelData->GetBufferSize(), buffer );
791     }
792   }
793
794
795   //Destroy temp buffer used for conversion RGB->RGBA
796   delete[] tempBuffer;
797 }
798
799 bool NewTexture::Bind( Context& context, unsigned int textureUnit, Render::Sampler* sampler )
800 {
801   if( mId != 0 )
802   {
803     context.ActiveTexture( static_cast<TextureUnit>(textureUnit) );
804
805     if( mType == TextureType::TEXTURE_2D )
806     {
807       context.Bind2dTexture( mId );
808     }
809     else if( mType == TextureType::TEXTURE_CUBE )
810     {
811       context.BindCubeMapTexture( mId );
812     }
813
814     ApplySampler( context, sampler );
815
816     if( mNativeImage )
817     {
818       //Allow implementation specific operations after binding the texture
819       mNativeImage->PrepareTexture();
820     }
821
822     return true;
823   }
824
825   return false;
826 }
827
828 void NewTexture::ApplySampler( Context& context, Render::Sampler* sampler )
829 {
830   Render::Sampler oldSampler = mSampler;
831   mSampler = sampler ? *sampler : Sampler();
832
833   if( mSampler.mBitfield != oldSampler.mBitfield )
834   {
835     if( mSampler.mMinificationFilter != oldSampler.mMinificationFilter )
836     {
837       GLint glFilterMode = FilterModeToGL( mSampler.mMinificationFilter, DALI_MINIFY_DEFAULT, GL_MINIFY_DEFAULT );
838       context.TexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, glFilterMode );
839     }
840
841     if( mSampler.mMagnificationFilter != oldSampler.mMagnificationFilter )
842     {
843       GLint glFilterMode = FilterModeToGL( mSampler.mMagnificationFilter, DALI_MAGNIFY_DEFAULT, GL_MAGNIFY_DEFAULT );
844       context.TexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, glFilterMode );
845     }
846
847     if( mSampler.mSWrapMode != oldSampler.mSWrapMode )
848     {
849       GLint glWrapMode = WrapModeToGL( mSampler.mSWrapMode, GL_WRAP_DEFAULT );
850       context.TexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, glWrapMode );
851     }
852
853     if( mSampler.mTWrapMode != oldSampler.mTWrapMode )
854     {
855       GLint glWrapMode = WrapModeToGL( mSampler.mTWrapMode, GL_WRAP_DEFAULT );
856       context.TexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, glWrapMode );
857     }
858
859     if( mType == TextureType::TEXTURE_CUBE && mSampler.mRWrapMode != oldSampler.mRWrapMode )
860     {
861       GLint glWrapMode = WrapModeToGL( mSampler.mRWrapMode, GL_WRAP_DEFAULT );
862       context.TexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, glWrapMode );
863     }
864   }
865 }
866
867 bool NewTexture::HasAlphaChannel()
868 {
869   return mHasAlpha;
870 }
871
872 void NewTexture::GenerateMipmaps( Context& context )
873 {
874   if( mType == TextureType::TEXTURE_2D )
875   {
876     context.Bind2dTexture( mId );
877     context.GenerateMipmap( GL_TEXTURE_2D );
878   }
879   else if( mType == TextureType::TEXTURE_CUBE )
880   {
881     context.BindCubeMapTexture( mId );
882     context.GenerateMipmap( GL_TEXTURE_CUBE_MAP );
883   }
884 }
885
886 } //Render
887
888 } //Internal
889
890 } //Dali