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