4 * An object oriented GL/GLES Abstraction/Utility Layer
6 * Copyright (C) 2007,2008,2009 Intel Corporation.
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.
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.
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/>.
24 * Matthew Allum <mallum@openedhand.com>
25 * Neil Roberts <neil@linux.intel.com>
26 * Robert Bragg <robert@linux.intel.com>
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"
49 #include "cogl-gles2-wrapper.h"
51 #define glTexImage3D ctx->drv.pf_glTexImage3D
52 #define glTexSubImage3D ctx->drv.pf_glTexSubImage3D
55 #define GL_TEXTURE_3D 0x806F
57 #ifndef GL_MAX_3D_TEXTURE_SIZE_OES
58 #define GL_MAX_3D_TEXTURE_SIZE_OES 0x8073
62 _cogl_texture_driver_gen (GLenum gl_target,
68 GE (glGenTextures (n, textures));
70 for (i = 0; i < n; i++)
72 _cogl_bind_gl_texture_transient (gl_target, textures[i], FALSE);
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) );
83 g_assert_not_reached();
89 _cogl_texture_driver_prep_gl_for_pixels_upload (int pixels_rowstride,
92 _cogl_texture_prep_gl_alignment_for_pixels_upload (pixels_rowstride);
96 _cogl_texture_driver_prep_gl_for_pixels_download (int pixels_rowstride,
99 _cogl_texture_prep_gl_alignment_for_pixels_download (pixels_rowstride);
103 _cogl_texture_driver_upload_subregion_to_gl (GLenum gl_target,
112 CoglBitmap *source_bmp,
113 GLuint source_gl_format,
114 GLuint source_gl_type)
117 CoglPixelFormat source_format = _cogl_bitmap_get_format (source_bmp);
118 int bpp = _cogl_get_format_bpp (source_format);
119 CoglBitmap *slice_bmp;
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. */
127 /* FIXME: optimize by not copying to intermediate slice bitmap when
128 * source rowstride = bpp * width and the texture image is not
131 /* Setup temp bitmap for slice subregion */
132 rowstride = bpp * width;
133 slice_bmp = _cogl_bitmap_new_from_data (g_malloc (rowstride * height),
138 (CoglBitmapDestroyNotify)
142 /* Setup gl alignment to match rowstride and top-left corner */
143 _cogl_texture_driver_prep_gl_for_pixels_upload (rowstride, bpp);
145 /* Copy subregion data */
146 _cogl_bitmap_copy_subregion (source_bmp,
153 data = _cogl_bitmap_bind (slice_bmp, COGL_BUFFER_ACCESS_READ, 0);
155 _cogl_bind_gl_texture_transient (gl_target, gl_handle, is_foreign);
157 GE( glTexSubImage2D (gl_target, 0,
164 _cogl_bitmap_unbind (slice_bmp);
166 cogl_object_unref (slice_bmp);
170 _cogl_texture_driver_upload_to_gl (GLenum gl_target,
173 CoglBitmap *source_bmp,
174 GLint internal_gl_format,
175 GLuint source_gl_format,
176 GLuint source_gl_type)
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);
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)
189 bmp = _cogl_bitmap_new_from_data (g_malloc (rowstride * bmp_height),
190 _cogl_bitmap_get_format (source_bmp),
194 (CoglBitmapDestroyNotify) g_free,
197 _cogl_bitmap_copy_subregion (source_bmp,
204 bmp = cogl_object_ref (source_bmp);
206 /* Setup gl alignment to match rowstride and top-left corner */
207 _cogl_texture_driver_prep_gl_for_pixels_upload (rowstride, bpp);
209 _cogl_bind_gl_texture_transient (gl_target, gl_handle, is_foreign);
211 data = _cogl_bitmap_bind (bmp, COGL_BUFFER_ACCESS_READ, 0);
213 GE( glTexImage2D (gl_target, 0,
215 bmp_width, bmp_height,
221 _cogl_bitmap_unbind (bmp);
223 cogl_object_unref (bmp);
227 _cogl_texture_driver_upload_to_gl_3d (GLenum gl_target,
232 CoglBitmap *source_bmp,
233 GLint internal_gl_format,
234 GLuint source_gl_format,
235 GLuint source_gl_type)
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);
243 _COGL_GET_CONTEXT (ctx, NO_RETVAL);
245 _cogl_bind_gl_texture_transient (gl_target, gl_handle, is_foreign);
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)
254 int image_height = bmp_height / depth;
257 _cogl_texture_driver_prep_gl_for_pixels_upload (bmp_width * bpp, bpp);
259 /* Initialize the texture with empty data and then upload each
260 image with a sub-region update */
262 GE( glTexImage3D (gl_target,
273 bmp = _cogl_bitmap_new_from_data (g_malloc (bpp * bmp_width * height),
274 _cogl_bitmap_get_format (source_bmp),
278 (CoglBitmapDestroyNotify) g_free,
281 for (i = 0; i < depth; i++)
283 _cogl_bitmap_copy_subregion (source_bmp,
290 data = _cogl_bitmap_bind (bmp,
291 COGL_BUFFER_ACCESS_READ, 0);
293 GE( glTexSubImage3D (gl_target,
298 bmp_width, /* width */
305 _cogl_bitmap_unbind (bmp);
308 cogl_object_unref (bmp);
312 data = _cogl_bitmap_bind (source_bmp, COGL_BUFFER_ACCESS_READ, 0);
314 _cogl_texture_driver_prep_gl_for_pixels_upload (rowstride, bpp);
316 GE( glTexImage3D (gl_target,
327 _cogl_bitmap_unbind (source_bmp);
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() ) */
335 _cogl_texture_driver_gl_get_tex_image (GLenum gl_target,
336 GLenum dest_gl_format,
344 _cogl_texture_driver_size_supported_3d (GLenum gl_target,
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) );
358 return width <= max_size && height <= max_size && depth <= max_size;
362 _cogl_texture_driver_size_supported (GLenum gl_target,
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) );
374 return width <= max_size && height <= max_size;
378 _cogl_texture_driver_try_setting_gl_border_color (
380 const GLfloat *transparent_color)
386 _cogl_pixel_format_from_gl_internal (GLenum gl_int_format,
387 CoglPixelFormat *out_format)
393 _cogl_pixel_format_to_gl (CoglPixelFormat format,
394 GLenum *out_glintformat,
395 GLenum *out_glformat,
398 CoglPixelFormat required_format;
399 GLenum glintformat = 0;
403 /* FIXME: check YUV support */
405 required_format = format;
407 /* Find GL equivalents */
408 switch (format & COGL_UNPREMULT_MASK)
410 case COGL_PIXEL_FORMAT_A_8:
411 glintformat = GL_ALPHA;
413 gltype = GL_UNSIGNED_BYTE;
415 case COGL_PIXEL_FORMAT_G_8:
416 glintformat = GL_LUMINANCE;
417 glformat = GL_LUMINANCE;
418 gltype = GL_UNSIGNED_BYTE;
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;
426 gltype = GL_UNSIGNED_BYTE;
427 required_format = COGL_PIXEL_FORMAT_RGB_888;
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;
437 gltype = GL_UNSIGNED_BYTE;
438 required_format = COGL_PIXEL_FORMAT_RGBA_8888;
439 required_format |= (format & COGL_PREMULT_BIT);
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;
448 gltype = GL_UNSIGNED_SHORT_5_6_5;
450 case COGL_PIXEL_FORMAT_RGBA_4444:
451 glintformat = GL_RGBA;
453 gltype = GL_UNSIGNED_SHORT_4_4_4_4;
455 case COGL_PIXEL_FORMAT_RGBA_5551:
456 glintformat = GL_RGBA;
458 gltype = GL_UNSIGNED_SHORT_5_5_5_1;
461 /* FIXME: check extensions for YUV support */
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;
473 return required_format;
477 _cogl_texture_driver_allows_foreign_gl_target (GLenum gl_target)
479 /* Allow 2-dimensional textures only */
480 if (gl_target != GL_TEXTURE_2D)
486 _cogl_texture_driver_gl_generate_mipmaps (GLenum gl_target)
488 GE( _cogl_wrap_glGenerateMipmap (gl_target) );
492 _cogl_texture_driver_find_best_gl_get_data_format (
493 CoglPixelFormat format,
494 GLenum *closest_gl_format,
495 GLenum *closest_gl_type)
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;