cally: Do not use deprecated functions
[profile/ivi/clutter.git] / clutter / cogl / cogl / driver / gles / cogl-texture-driver-gles.c
1 /*
2  * Cogl
3  *
4  * An object oriented GL/GLES Abstraction/Utility Layer
5  *
6  * Copyright (C) 2007,2008,2009 Intel Corporation.
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library. If not, see <http://www.gnu.org/licenses/>.
20  *
21  *
22  *
23  * Authors:
24  *  Matthew Allum  <mallum@openedhand.com>
25  *  Neil Roberts   <neil@linux.intel.com>
26  *  Robert Bragg   <robert@linux.intel.com>
27  */
28
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
32
33 #include "cogl.h"
34 #include "cogl-internal.h"
35 #include "cogl-util.h"
36 #include "cogl-bitmap.h"
37 #include "cogl-bitmap-private.h"
38 #include "cogl-texture-private.h"
39 #include "cogl-material.h"
40 #include "cogl-material-opengl-private.h"
41 #include "cogl-context.h"
42 #include "cogl-handle.h"
43 #include "cogl-primitives.h"
44
45 #include <string.h>
46 #include <stdlib.h>
47 #include <math.h>
48
49 #include "cogl-gles2-wrapper.h"
50
51 #define glTexImage3D ctx->drv.pf_glTexImage3D
52 #define glTexSubImage3D ctx->drv.pf_glTexSubImage3D
53
54 #ifndef GL_TEXTURE_3D
55 #define GL_TEXTURE_3D 0x806F
56 #endif
57 #ifndef GL_MAX_3D_TEXTURE_SIZE_OES
58 #define GL_MAX_3D_TEXTURE_SIZE_OES 0x8073
59 #endif
60
61 void
62 _cogl_texture_driver_gen (GLenum   gl_target,
63                           GLsizei  n,
64                           GLuint  *textures)
65 {
66   unsigned int i;
67
68   GE (glGenTextures (n, textures));
69
70   for (i = 0; i < n; i++)
71     {
72       _cogl_bind_gl_texture_transient (gl_target, textures[i], FALSE);
73
74       switch (gl_target)
75         {
76         case GL_TEXTURE_2D:
77         case GL_TEXTURE_3D:
78           /* GL_TEXTURE_MAG_FILTER defaults to GL_LINEAR, no need to set it */
79           GE( glTexParameteri (gl_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR) );
80           break;
81
82         default:
83           g_assert_not_reached();
84         }
85     }
86 }
87
88 void
89 _cogl_texture_driver_prep_gl_for_pixels_upload (int pixels_rowstride,
90                                                 int pixels_bpp)
91 {
92   _cogl_texture_prep_gl_alignment_for_pixels_upload (pixels_rowstride);
93 }
94
95 void
96 _cogl_texture_driver_prep_gl_for_pixels_download (int pixels_rowstride,
97                                                   int pixels_bpp)
98 {
99   _cogl_texture_prep_gl_alignment_for_pixels_download (pixels_rowstride);
100 }
101
102 void
103 _cogl_texture_driver_upload_subregion_to_gl (GLenum       gl_target,
104                                              GLuint       gl_handle,
105                                              gboolean     is_foreign,
106                                              int          src_x,
107                                              int          src_y,
108                                              int          dst_x,
109                                              int          dst_y,
110                                              int          width,
111                                              int          height,
112                                              CoglBitmap  *source_bmp,
113                                              GLuint       source_gl_format,
114                                              GLuint       source_gl_type)
115 {
116   guint8 *data;
117   CoglPixelFormat source_format = _cogl_bitmap_get_format (source_bmp);
118   int bpp = _cogl_get_format_bpp (source_format);
119   CoglBitmap *slice_bmp;
120   int rowstride;
121
122   /* NB: GLES doesn't support the GL_UNPACK_ROW_LENGTH,
123    * GL_UNPACK_SKIP_PIXELS or GL_UNPACK_SKIP_ROWS pixel store options
124    * so we can't directly source a sub-region from source_bmp, we need
125    * to use a transient bitmap instead. */
126
127   /* FIXME: optimize by not copying to intermediate slice bitmap when
128    * source rowstride = bpp * width and the texture image is not
129    * sliced */
130
131   /* Setup temp bitmap for slice subregion */
132   rowstride = bpp * width;
133   slice_bmp = _cogl_bitmap_new_from_data (g_malloc (rowstride * height),
134                                           source_format,
135                                           width,
136                                           height,
137                                           rowstride,
138                                           (CoglBitmapDestroyNotify)
139                                           g_free,
140                                           NULL);
141
142   /* Setup gl alignment to match rowstride and top-left corner */
143   _cogl_texture_driver_prep_gl_for_pixels_upload (rowstride, bpp);
144
145   /* Copy subregion data */
146   _cogl_bitmap_copy_subregion (source_bmp,
147                                slice_bmp,
148                                src_x,
149                                src_y,
150                                0, 0,
151                                width, height);
152
153   data = _cogl_bitmap_bind (slice_bmp, COGL_BUFFER_ACCESS_READ, 0);
154
155   _cogl_bind_gl_texture_transient (gl_target, gl_handle, is_foreign);
156
157   GE( glTexSubImage2D (gl_target, 0,
158                        dst_x, dst_y,
159                        width, height,
160                        source_gl_format,
161                        source_gl_type,
162                        data) );
163
164   _cogl_bitmap_unbind (slice_bmp);
165
166   cogl_object_unref (slice_bmp);
167 }
168
169 void
170 _cogl_texture_driver_upload_to_gl (GLenum       gl_target,
171                                    GLuint       gl_handle,
172                                    gboolean     is_foreign,
173                                    CoglBitmap  *source_bmp,
174                                    GLint        internal_gl_format,
175                                    GLuint       source_gl_format,
176                                    GLuint       source_gl_type)
177 {
178   int bpp = _cogl_get_format_bpp (_cogl_bitmap_get_format (source_bmp));
179   int rowstride = _cogl_bitmap_get_rowstride (source_bmp);
180   int bmp_width = _cogl_bitmap_get_width (source_bmp);
181   int bmp_height = _cogl_bitmap_get_height (source_bmp);
182   CoglBitmap *bmp;
183   guint8 *data;
184
185   /* If the rowstride can't be specified with just GL_ALIGNMENT alone
186      then we need to copy the bitmap because there is no GL_ROW_LENGTH */
187   if (rowstride / bpp != bmp_width)
188     {
189       bmp = _cogl_bitmap_new_from_data (g_malloc (rowstride * bmp_height),
190                                         _cogl_bitmap_get_format (source_bmp),
191                                         bmp_width,
192                                         bmp_height,
193                                         rowstride,
194                                         (CoglBitmapDestroyNotify) g_free,
195                                         NULL);
196
197       _cogl_bitmap_copy_subregion (source_bmp,
198                                    bmp,
199                                    0, 0, 0, 0,
200                                    bmp_width,
201                                    bmp_height);
202     }
203   else
204     bmp = cogl_object_ref (source_bmp);
205
206   /* Setup gl alignment to match rowstride and top-left corner */
207   _cogl_texture_driver_prep_gl_for_pixels_upload (rowstride, bpp);
208
209   _cogl_bind_gl_texture_transient (gl_target, gl_handle, is_foreign);
210
211   data = _cogl_bitmap_bind (bmp, COGL_BUFFER_ACCESS_READ, 0);
212
213   GE( glTexImage2D (gl_target, 0,
214                     internal_gl_format,
215                     bmp_width, bmp_height,
216                     0,
217                     source_gl_format,
218                     source_gl_type,
219                     data) );
220
221   _cogl_bitmap_unbind (bmp);
222
223   cogl_object_unref (bmp);
224 }
225
226 void
227 _cogl_texture_driver_upload_to_gl_3d (GLenum       gl_target,
228                                       GLuint       gl_handle,
229                                       gboolean     is_foreign,
230                                       GLint        height,
231                                       GLint        depth,
232                                       CoglBitmap  *source_bmp,
233                                       GLint        internal_gl_format,
234                                       GLuint       source_gl_format,
235                                       GLuint       source_gl_type)
236 {
237   int bpp = _cogl_get_format_bpp (_cogl_bitmap_get_format (source_bmp));
238   int rowstride = _cogl_bitmap_get_rowstride (source_bmp);
239   int bmp_width = _cogl_bitmap_get_width (source_bmp);
240   int bmp_height = _cogl_bitmap_get_height (source_bmp);
241   guint8 *data;
242
243   _COGL_GET_CONTEXT (ctx, NO_RETVAL);
244
245   _cogl_bind_gl_texture_transient (gl_target, gl_handle, is_foreign);
246
247   /* If the rowstride or image height can't be specified with just
248      GL_ALIGNMENT alone then we need to copy the bitmap because there
249      is no GL_ROW_LENGTH */
250   if (rowstride / bpp != bmp_width ||
251       height != bmp_height / depth)
252     {
253       CoglBitmap *bmp;
254       int image_height = bmp_height / depth;
255       int i;
256
257       _cogl_texture_driver_prep_gl_for_pixels_upload (bmp_width * bpp, bpp);
258
259       /* Initialize the texture with empty data and then upload each
260          image with a sub-region update */
261
262       GE( glTexImage3D (gl_target,
263                         0, /* level */
264                         internal_gl_format,
265                         bmp_width,
266                         height,
267                         depth,
268                         0,
269                         source_gl_format,
270                         source_gl_type,
271                         NULL) );
272
273       bmp = _cogl_bitmap_new_from_data (g_malloc (bpp * bmp_width * height),
274                                         _cogl_bitmap_get_format (source_bmp),
275                                         bmp_width,
276                                         height,
277                                         bpp * bmp_width,
278                                         (CoglBitmapDestroyNotify) g_free,
279                                         NULL);
280
281       for (i = 0; i < depth; i++)
282         {
283           _cogl_bitmap_copy_subregion (source_bmp,
284                                        bmp,
285                                        0, image_height * i,
286                                        0, 0,
287                                        bmp_width,
288                                        bmp_height);
289
290           data = _cogl_bitmap_bind (bmp,
291                                     COGL_BUFFER_ACCESS_READ, 0);
292
293           GE( glTexSubImage3D (gl_target,
294                                0, /* level */
295                                0, /* xoffset */
296                                0, /* yoffset */
297                                i, /* zoffset */
298                                bmp_width, /* width */
299                                height, /* height */
300                                1, /* depth */
301                                source_gl_format,
302                                source_gl_type,
303                                data) );
304
305           _cogl_bitmap_unbind (bmp);
306         }
307
308       cogl_object_unref (bmp);
309     }
310   else
311     {
312       data = _cogl_bitmap_bind (source_bmp, COGL_BUFFER_ACCESS_READ, 0);
313
314       _cogl_texture_driver_prep_gl_for_pixels_upload (rowstride, bpp);
315
316       GE( glTexImage3D (gl_target,
317                         0, /* level */
318                         internal_gl_format,
319                         bmp_width,
320                         height,
321                         depth,
322                         0,
323                         source_gl_format,
324                         source_gl_type,
325                         data) );
326
327       _cogl_bitmap_unbind (source_bmp);
328     }
329 }
330
331 /* NB: GLES doesn't support glGetTexImage2D, so cogl-texture will instead
332  * fallback to a generic render + readpixels approach to downloading
333  * texture data. (See _cogl_texture_draw_and_read() ) */
334 gboolean
335 _cogl_texture_driver_gl_get_tex_image (GLenum  gl_target,
336                                        GLenum  dest_gl_format,
337                                        GLenum  dest_gl_type,
338                                        guint8 *dest)
339 {
340   return FALSE;
341 }
342
343 gboolean
344 _cogl_texture_driver_size_supported_3d (GLenum gl_target,
345                                         GLenum gl_format,
346                                         GLenum gl_type,
347                                         int    width,
348                                         int    height,
349                                         int    depth)
350 {
351   GLint max_size;
352
353   /* GLES doesn't support a proxy texture target so let's at least
354      check whether the size is greater than
355      GL_MAX_3D_TEXTURE_SIZE_OES */
356   GE( glGetIntegerv (GL_MAX_3D_TEXTURE_SIZE_OES, &max_size) );
357
358   return width <= max_size && height <= max_size && depth <= max_size;
359 }
360
361 gboolean
362 _cogl_texture_driver_size_supported (GLenum gl_target,
363                                      GLenum gl_format,
364                                      GLenum gl_type,
365                                      int    width,
366                                      int    height)
367 {
368   GLint max_size;
369
370   /* GLES doesn't support a proxy texture target so let's at least
371      check whether the size is greater than GL_MAX_TEXTURE_SIZE */
372   GE( glGetIntegerv (GL_MAX_TEXTURE_SIZE, &max_size) );
373
374   return width <= max_size && height <= max_size;
375 }
376
377 void
378 _cogl_texture_driver_try_setting_gl_border_color (
379                                               GLuint   gl_target,
380                                               const GLfloat *transparent_color)
381 {
382   /* FAIL! */
383 }
384
385 gboolean
386 _cogl_pixel_format_from_gl_internal (GLenum            gl_int_format,
387                                      CoglPixelFormat  *out_format)
388 {
389   return TRUE;
390 }
391
392 CoglPixelFormat
393 _cogl_pixel_format_to_gl (CoglPixelFormat  format,
394                           GLenum          *out_glintformat,
395                           GLenum          *out_glformat,
396                           GLenum          *out_gltype)
397 {
398   CoglPixelFormat required_format;
399   GLenum          glintformat = 0;
400   GLenum          glformat = 0;
401   GLenum          gltype = 0;
402
403   /* FIXME: check YUV support */
404
405   required_format = format;
406
407   /* Find GL equivalents */
408   switch (format & COGL_UNPREMULT_MASK)
409     {
410     case COGL_PIXEL_FORMAT_A_8:
411       glintformat = GL_ALPHA;
412       glformat = GL_ALPHA;
413       gltype = GL_UNSIGNED_BYTE;
414       break;
415     case COGL_PIXEL_FORMAT_G_8:
416       glintformat = GL_LUMINANCE;
417       glformat = GL_LUMINANCE;
418       gltype = GL_UNSIGNED_BYTE;
419       break;
420
421       /* Just one 24-bit ordering supported */
422     case COGL_PIXEL_FORMAT_RGB_888:
423     case COGL_PIXEL_FORMAT_BGR_888:
424       glintformat = GL_RGB;
425       glformat = GL_RGB;
426       gltype = GL_UNSIGNED_BYTE;
427       required_format = COGL_PIXEL_FORMAT_RGB_888;
428       break;
429
430       /* Just one 32-bit ordering supported */
431     case COGL_PIXEL_FORMAT_RGBA_8888:
432     case COGL_PIXEL_FORMAT_BGRA_8888:
433     case COGL_PIXEL_FORMAT_ARGB_8888:
434     case COGL_PIXEL_FORMAT_ABGR_8888:
435       glintformat = GL_RGBA;
436       glformat = GL_RGBA;
437       gltype = GL_UNSIGNED_BYTE;
438       required_format = COGL_PIXEL_FORMAT_RGBA_8888;
439       required_format |= (format & COGL_PREMULT_BIT);
440       break;
441
442       /* The following three types of channel ordering
443        * are always defined using system word byte
444        * ordering (even according to GLES spec) */
445     case COGL_PIXEL_FORMAT_RGB_565:
446       glintformat = GL_RGB;
447       glformat = GL_RGB;
448       gltype = GL_UNSIGNED_SHORT_5_6_5;
449       break;
450     case COGL_PIXEL_FORMAT_RGBA_4444:
451       glintformat = GL_RGBA;
452       glformat = GL_RGBA;
453       gltype = GL_UNSIGNED_SHORT_4_4_4_4;
454       break;
455     case COGL_PIXEL_FORMAT_RGBA_5551:
456       glintformat = GL_RGBA;
457       glformat = GL_RGBA;
458       gltype = GL_UNSIGNED_SHORT_5_5_5_1;
459       break;
460
461       /* FIXME: check extensions for YUV support */
462     default:
463       break;
464     }
465
466   if (out_glintformat != NULL)
467     *out_glintformat = glintformat;
468   if (out_glformat != NULL)
469     *out_glformat = glformat;
470   if (out_gltype != NULL)
471     *out_gltype = gltype;
472
473   return required_format;
474 }
475
476 gboolean
477 _cogl_texture_driver_allows_foreign_gl_target (GLenum gl_target)
478 {
479   /* Allow 2-dimensional textures only */
480   if (gl_target != GL_TEXTURE_2D)
481     return FALSE;
482   return TRUE;
483 }
484
485 void
486 _cogl_texture_driver_gl_generate_mipmaps (GLenum gl_target)
487 {
488   GE( _cogl_wrap_glGenerateMipmap (gl_target) );
489 }
490
491 CoglPixelFormat
492 _cogl_texture_driver_find_best_gl_get_data_format (
493                                              CoglPixelFormat  format,
494                                              GLenum          *closest_gl_format,
495                                              GLenum          *closest_gl_type)
496 {
497   /* Find closest format that's supported by GL
498      (Can't use _cogl_pixel_format_to_gl since available formats
499       when reading pixels on GLES are severely limited) */
500   *closest_gl_format = GL_RGBA;
501   *closest_gl_type = GL_UNSIGNED_BYTE;
502   return COGL_PIXEL_FORMAT_RGBA_8888;
503 }
504