4 * An object oriented GL/GLES Abstraction/Utility Layer
6 * Copyright (C) 2010 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 * Neil Roberts <neil@linux.intel.com>
31 #include "cogl-private.h"
32 #include "cogl-util.h"
33 #include "cogl-texture-private.h"
34 #include "cogl-texture-rectangle-private.h"
35 #include "cogl-texture-driver.h"
36 #include "cogl-context-private.h"
37 #include "cogl-handle.h"
38 #include "cogl-journal-private.h"
39 #include "cogl-pipeline-opengl-private.h"
44 /* These aren't defined under GLES */
45 #ifndef GL_TEXTURE_RECTANGLE_ARB
46 #define GL_TEXTURE_RECTANGLE_ARB 0x84F5
49 #define GL_CLAMP 0x2900
51 #ifndef GL_CLAMP_TO_BORDER
52 #define GL_CLAMP_TO_BORDER 0x812D
55 static void _cogl_texture_rectangle_free (CoglTextureRectangle *tex_rect);
57 COGL_TEXTURE_DEFINE (TextureRectangle, texture_rectangle);
59 static const CoglTextureVtable cogl_texture_rectangle_vtable;
62 can_use_wrap_mode (GLenum wrap_mode)
64 return (wrap_mode == GL_CLAMP ||
65 wrap_mode == GL_CLAMP_TO_EDGE ||
66 wrap_mode == GL_CLAMP_TO_BORDER);
70 _cogl_texture_rectangle_set_wrap_mode_parameters (CoglTexture *tex,
75 CoglTextureRectangle *tex_rect = COGL_TEXTURE_RECTANGLE (tex);
77 _COGL_GET_CONTEXT (ctx, NO_RETVAL);
79 /* Only set the wrap mode if it's different from the current value
80 to avoid too many GL calls. Texture rectangle doesn't make use of
81 the r coordinate so we can ignore its wrap mode */
82 if (tex_rect->wrap_mode_s != wrap_mode_s ||
83 tex_rect->wrap_mode_t != wrap_mode_t)
85 g_assert (can_use_wrap_mode (wrap_mode_s));
86 g_assert (can_use_wrap_mode (wrap_mode_t));
88 _cogl_bind_gl_texture_transient (GL_TEXTURE_RECTANGLE_ARB,
90 tex_rect->is_foreign);
91 GE( ctx, glTexParameteri (GL_TEXTURE_RECTANGLE_ARB,
92 GL_TEXTURE_WRAP_S, wrap_mode_s) );
93 GE( ctx, glTexParameteri (GL_TEXTURE_RECTANGLE_ARB,
94 GL_TEXTURE_WRAP_T, wrap_mode_t) );
96 tex_rect->wrap_mode_s = wrap_mode_s;
97 tex_rect->wrap_mode_t = wrap_mode_t;
102 _cogl_texture_rectangle_free (CoglTextureRectangle *tex_rect)
104 if (!tex_rect->is_foreign)
105 _cogl_delete_gl_texture (tex_rect->gl_texture);
108 _cogl_texture_free (COGL_TEXTURE (tex_rect));
112 _cogl_texture_rectangle_can_create (unsigned int width,
114 CoglPixelFormat internal_format,
120 _COGL_GET_CONTEXT (ctx, FALSE);
122 if (!cogl_has_feature (ctx, COGL_FEATURE_ID_TEXTURE_RECTANGLE))
126 COGL_TEXTURE_ERROR_TYPE,
127 "The CoglTextureRectangle feature isn't available");
131 ctx->texture_driver->pixel_format_to_gl (internal_format,
136 /* Check that the driver can create a texture with that size */
137 if (!ctx->texture_driver->size_supported (GL_TEXTURE_RECTANGLE_ARB,
145 COGL_TEXTURE_ERROR_SIZE,
146 "The requested texture size + format is unsupported");
153 static CoglTextureRectangle *
154 _cogl_texture_rectangle_create_base (unsigned int width,
156 CoglPixelFormat internal_format)
158 CoglTextureRectangle *tex_rect = g_new (CoglTextureRectangle, 1);
159 CoglTexture *tex = COGL_TEXTURE (tex_rect);
161 _cogl_texture_init (tex, &cogl_texture_rectangle_vtable);
163 tex_rect->width = width;
164 tex_rect->height = height;
166 /* We default to GL_LINEAR for both filters */
167 tex_rect->min_filter = GL_LINEAR;
168 tex_rect->mag_filter = GL_LINEAR;
170 /* Wrap mode not yet set */
171 tex_rect->wrap_mode_s = GL_FALSE;
172 tex_rect->wrap_mode_t = GL_FALSE;
174 tex_rect->format = internal_format;
179 CoglTextureRectangle *
180 cogl_texture_rectangle_new_with_size (CoglContext *ctx,
183 CoglPixelFormat internal_format,
186 CoglTextureRectangle *tex_rect;
191 /* Since no data, we need some internal format */
192 if (internal_format == COGL_PIXEL_FORMAT_ANY)
193 internal_format = COGL_PIXEL_FORMAT_RGBA_8888_PRE;
195 if (!_cogl_texture_rectangle_can_create (width, height,
196 internal_format, error))
199 internal_format = ctx->texture_driver->pixel_format_to_gl (internal_format,
204 tex_rect = _cogl_texture_rectangle_create_base (width, height,
207 ctx->texture_driver->gen (GL_TEXTURE_RECTANGLE_ARB, 1, &tex_rect->gl_texture);
208 _cogl_bind_gl_texture_transient (GL_TEXTURE_RECTANGLE_ARB,
209 tex_rect->gl_texture,
210 tex_rect->is_foreign);
211 GE( ctx, glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, gl_intformat,
212 width, height, 0, gl_format, gl_type, NULL) );
214 return _cogl_texture_rectangle_object_new (tex_rect);
217 CoglTextureRectangle *
218 _cogl_texture_rectangle_new_from_bitmap (CoglBitmap *bmp,
219 CoglTextureFlags flags,
220 CoglPixelFormat internal_format)
222 CoglTextureRectangle *tex_rect;
228 _COGL_GET_CONTEXT (ctx, NULL);
230 _COGL_RETURN_VAL_IF_FAIL (cogl_is_bitmap (bmp), NULL);
233 _cogl_texture_determine_internal_format (cogl_bitmap_get_format (bmp),
236 if (!_cogl_texture_rectangle_can_create (cogl_bitmap_get_width (bmp),
237 cogl_bitmap_get_height (bmp),
242 dst_bmp = _cogl_texture_prepare_for_upload (bmp,
252 tex_rect = _cogl_texture_rectangle_create_base (cogl_bitmap_get_width (bmp),
253 cogl_bitmap_get_height (bmp),
256 ctx->texture_driver->gen (GL_TEXTURE_RECTANGLE_ARB, 1, &tex_rect->gl_texture);
257 ctx->texture_driver->upload_to_gl (GL_TEXTURE_RECTANGLE_ARB,
258 tex_rect->gl_texture,
265 tex_rect->gl_format = gl_intformat;
267 cogl_object_unref (dst_bmp);
269 return _cogl_texture_rectangle_object_new (tex_rect);
272 CoglTextureRectangle *
273 _cogl_texture_rectangle_new_from_foreign (GLuint gl_handle,
276 CoglPixelFormat format)
278 /* NOTE: width, height and internal format are not queriable
279 * in GLES, hence such a function prototype.
283 GLint gl_compressed = GL_FALSE;
284 GLenum gl_int_format = 0;
285 CoglTextureRectangle *tex_rect;
287 _COGL_GET_CONTEXT (ctx, NULL);
289 if (!ctx->texture_driver->allows_foreign_gl_target (GL_TEXTURE_RECTANGLE_ARB))
292 /* Make sure it is a valid GL texture object */
293 if (!ctx->glIsTexture (gl_handle))
296 /* Make sure binding succeeds */
297 while ((gl_error = ctx->glGetError ()) != GL_NO_ERROR)
300 _cogl_bind_gl_texture_transient (GL_TEXTURE_RECTANGLE_ARB, gl_handle, TRUE);
301 if (ctx->glGetError () != GL_NO_ERROR)
304 /* Obtain texture parameters */
307 if (ctx->driver == COGL_DRIVER_GL)
311 GE( ctx, glGetTexLevelParameteriv (GL_TEXTURE_RECTANGLE_ARB, 0,
312 GL_TEXTURE_COMPRESSED,
315 GE( ctx, glGetTexLevelParameteriv (GL_TEXTURE_RECTANGLE_ARB, 0,
316 GL_TEXTURE_INTERNAL_FORMAT,
321 /* If we can query GL for the actual pixel format then we'll ignore
322 the passed in format and use that. */
323 if (!ctx->texture_driver->pixel_format_from_gl_internal (gl_int_format,
330 /* Otherwise we'll assume we can derive the GL format from the
332 ctx->texture_driver->pixel_format_to_gl (format,
338 /* Note: We always trust the given width and height without querying
339 * the texture object because the user may be creating a Cogl
340 * texture for a texture_from_pixmap object where glTexImage2D may
341 * not have been called and the texture_from_pixmap spec doesn't
342 * clarify that it is reliable to query back the size from OpenGL.
345 /* Validate width and height */
346 if (width <= 0 || height <= 0)
349 /* Compressed texture images not supported */
350 if (gl_compressed == GL_TRUE)
353 /* Create new texture */
354 tex_rect = _cogl_texture_rectangle_create_base (width, height, format);
356 /* Setup bitmap info */
357 tex_rect->is_foreign = TRUE;
359 tex_rect->format = format;
361 tex_rect->gl_texture = gl_handle;
362 tex_rect->gl_format = gl_int_format;
365 tex_rect->min_filter = GL_FALSE;
366 tex_rect->mag_filter = GL_FALSE;
368 return _cogl_texture_rectangle_handle_new (tex_rect);
372 _cogl_texture_rectangle_get_max_waste (CoglTexture *tex)
378 _cogl_texture_rectangle_is_sliced (CoglTexture *tex)
384 _cogl_texture_rectangle_can_hardware_repeat (CoglTexture *tex)
390 _cogl_texture_rectangle_transform_coords_to_gl (CoglTexture *tex,
394 CoglTextureRectangle *tex_rect = COGL_TEXTURE_RECTANGLE (tex);
396 *s *= tex_rect->width;
397 *t *= tex_rect->height;
400 static CoglTransformResult
401 _cogl_texture_rectangle_transform_quad_coords_to_gl (CoglTexture *tex,
404 CoglTextureRectangle *tex_rect = COGL_TEXTURE_RECTANGLE (tex);
405 gboolean need_repeat = FALSE;
408 for (i = 0; i < 4; i++)
410 if (coords[i] < 0.0f || coords[i] > 1.0f)
412 coords[i] *= (i & 1) ? tex_rect->height : tex_rect->width;
415 return (need_repeat ? COGL_TRANSFORM_SOFTWARE_REPEAT
416 : COGL_TRANSFORM_NO_REPEAT);
420 _cogl_texture_rectangle_get_gl_texture (CoglTexture *tex,
421 GLuint *out_gl_handle,
422 GLenum *out_gl_target)
424 CoglTextureRectangle *tex_rect = COGL_TEXTURE_RECTANGLE (tex);
427 *out_gl_handle = tex_rect->gl_texture;
430 *out_gl_target = GL_TEXTURE_RECTANGLE_ARB;
436 _cogl_texture_rectangle_set_filters (CoglTexture *tex,
440 CoglTextureRectangle *tex_rect = COGL_TEXTURE_RECTANGLE (tex);
442 _COGL_GET_CONTEXT (ctx, NO_RETVAL);
444 if (min_filter == tex_rect->min_filter
445 && mag_filter == tex_rect->mag_filter)
448 /* Rectangle textures don't support mipmapping */
449 g_assert (min_filter == GL_LINEAR || min_filter == GL_NEAREST);
451 /* Store new values */
452 tex_rect->min_filter = min_filter;
453 tex_rect->mag_filter = mag_filter;
455 /* Apply new filters to the texture */
456 _cogl_bind_gl_texture_transient (GL_TEXTURE_RECTANGLE_ARB,
457 tex_rect->gl_texture,
458 tex_rect->is_foreign);
459 GE( ctx, glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER,
461 GE( ctx, glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER,
466 _cogl_texture_rectangle_pre_paint (CoglTexture *tex,
467 CoglTexturePrePaintFlags flags)
469 _COGL_GET_CONTEXT (ctx, NO_RETVAL);
471 /* Rectangle textures don't support mipmaps */
472 g_assert ((flags & COGL_TEXTURE_NEEDS_MIPMAP) == 0);
476 _cogl_texture_rectangle_ensure_non_quad_rendering (CoglTexture *tex)
478 /* Nothing needs to be done */
482 _cogl_texture_rectangle_set_region (CoglTexture *tex,
487 unsigned int dst_width,
488 unsigned int dst_height,
491 CoglTextureRectangle *tex_rect = COGL_TEXTURE_RECTANGLE (tex);
495 _COGL_GET_CONTEXT (ctx, FALSE);
497 bmp = _cogl_texture_prepare_for_upload (bmp,
498 cogl_texture_get_format (tex),
504 /* Send data to GL */
505 ctx->texture_driver->upload_subregion_to_gl (GL_TEXTURE_RECTANGLE_ARB,
506 tex_rect->gl_texture,
510 dst_width, dst_height,
515 cogl_object_unref (bmp);
521 _cogl_texture_rectangle_get_data (CoglTexture *tex,
522 CoglPixelFormat format,
523 unsigned int rowstride,
526 CoglTextureRectangle *tex_rect = COGL_TEXTURE_RECTANGLE (tex);
531 _COGL_GET_CONTEXT (ctx, FALSE);
533 bpp = _cogl_pixel_format_get_bytes_per_pixel (format);
535 ctx->texture_driver->pixel_format_to_gl (format,
536 NULL, /* internal format */
540 ctx->texture_driver->prep_gl_for_pixels_download (rowstride, bpp);
542 _cogl_bind_gl_texture_transient (GL_TEXTURE_RECTANGLE_ARB,
543 tex_rect->gl_texture,
544 tex_rect->is_foreign);
545 return ctx->texture_driver->gl_get_tex_image (GL_TEXTURE_RECTANGLE_ARB,
551 static CoglPixelFormat
552 _cogl_texture_rectangle_get_format (CoglTexture *tex)
554 return COGL_TEXTURE_RECTANGLE (tex)->format;
558 _cogl_texture_rectangle_get_gl_format (CoglTexture *tex)
560 return COGL_TEXTURE_RECTANGLE (tex)->gl_format;
564 _cogl_texture_rectangle_get_width (CoglTexture *tex)
566 return COGL_TEXTURE_RECTANGLE (tex)->width;
570 _cogl_texture_rectangle_get_height (CoglTexture *tex)
572 return COGL_TEXTURE_RECTANGLE (tex)->height;
576 _cogl_texture_rectangle_is_foreign (CoglTexture *tex)
578 return COGL_TEXTURE_RECTANGLE (tex)->is_foreign;
581 static CoglTextureType
582 _cogl_texture_rectangle_get_type (CoglTexture *tex)
584 return COGL_TEXTURE_TYPE_RECTANGLE;
587 static const CoglTextureVtable
588 cogl_texture_rectangle_vtable =
590 _cogl_texture_rectangle_set_region,
591 _cogl_texture_rectangle_get_data,
592 NULL, /* foreach_sub_texture_in_region */
593 _cogl_texture_rectangle_get_max_waste,
594 _cogl_texture_rectangle_is_sliced,
595 _cogl_texture_rectangle_can_hardware_repeat,
596 _cogl_texture_rectangle_transform_coords_to_gl,
597 _cogl_texture_rectangle_transform_quad_coords_to_gl,
598 _cogl_texture_rectangle_get_gl_texture,
599 _cogl_texture_rectangle_set_filters,
600 _cogl_texture_rectangle_pre_paint,
601 _cogl_texture_rectangle_ensure_non_quad_rendering,
602 _cogl_texture_rectangle_set_wrap_mode_parameters,
603 _cogl_texture_rectangle_get_format,
604 _cogl_texture_rectangle_get_gl_format,
605 _cogl_texture_rectangle_get_width,
606 _cogl_texture_rectangle_get_height,
607 _cogl_texture_rectangle_get_type,
608 _cogl_texture_rectangle_is_foreign