diff --git a/cogl/cogl-atlas.c b/cogl/cogl-atlas.c index 6138d46e6..3b5ddab35 100644 --- a/cogl/cogl-atlas.c +++ b/cogl/cogl-atlas.c @@ -175,10 +175,12 @@ _cogl_atlas_get_initial_size (CoglPixelFormat format, GLenum gl_intformat; GLenum gl_type; - _cogl_pixel_format_to_gl (format, - &gl_intformat, - NULL, /* gl_format */ - &gl_type); + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + ctx->texture_driver->pixel_format_to_gl (format, + &gl_intformat, + NULL, /* gl_format */ + &gl_type); /* At least on Intel hardware, the texture size will be rounded up to at least 1MB so we might as well try to aim for that as an @@ -193,7 +195,7 @@ _cogl_atlas_get_initial_size (CoglPixelFormat format, /* Some platforms might not support this large size so we'll decrease the size until it can */ while (size > 1 && - !_cogl_texture_driver_size_supported (GL_TEXTURE_2D, + !ctx->texture_driver->size_supported (GL_TEXTURE_2D, gl_intformat, gl_type, size, size)) @@ -213,14 +215,16 @@ _cogl_atlas_create_map (CoglPixelFormat format, GLenum gl_intformat; GLenum gl_type; - _cogl_pixel_format_to_gl (format, - &gl_intformat, - NULL, /* gl_format */ - &gl_type); + _COGL_GET_CONTEXT (ctx, NULL); + + ctx->texture_driver->pixel_format_to_gl (format, + &gl_intformat, + NULL, /* gl_format */ + &gl_type); /* Keep trying increasingly larger atlases until we can fit all of the textures */ - while (_cogl_texture_driver_size_supported (GL_TEXTURE_2D, + while (ctx->texture_driver->size_supported (GL_TEXTURE_2D, gl_intformat, gl_type, map_width, map_height)) diff --git a/cogl/cogl-context-private.h b/cogl/cogl-context-private.h index aeefc7d02..87b0d6c3e 100644 --- a/cogl/cogl-context-private.h +++ b/cogl/cogl-context-private.h @@ -41,6 +41,7 @@ #include "cogl-buffer-private.h" #include "cogl-bitmask.h" #include "cogl-atlas.h" +#include "cogl-texture-driver.h" typedef struct { @@ -55,6 +56,9 @@ struct _CoglContext CoglDisplay *display; + /* vtable for the texture driver functions */ + const CoglTextureDriver *texture_driver; + /* Features cache */ CoglFeatureFlags feature_flags; CoglPrivateFeatureFlags private_feature_flags; diff --git a/cogl/cogl-context.c b/cogl/cogl-context.c index 13c9142bf..7a7079731 100644 --- a/cogl/cogl-context.c +++ b/cogl/cogl-context.c @@ -54,6 +54,9 @@ #define GL_POINT_SPRITE 0x8861 #endif +extern const CoglTextureDriver _cogl_texture_driver_gl; +extern const CoglTextureDriver _cogl_texture_driver_gles; + static void _cogl_context_free (CoglContext *context); COGL_OBJECT_DEFINE (Context, context); @@ -173,6 +176,12 @@ cogl_context_new (CoglDisplay *display, return NULL; } +#ifdef HAVE_COGL_GL + context->texture_driver = &_cogl_texture_driver_gl; +#else + context->texture_driver = &_cogl_texture_driver_gles; +#endif + /* Initialise the driver specific state */ _cogl_init_feature_overrides (context); diff --git a/cogl/cogl-texture-2d-sliced.c b/cogl/cogl-texture-2d-sliced.c index 6cda2c349..9f516e4e7 100644 --- a/cogl/cogl-texture-2d-sliced.c +++ b/cogl/cogl-texture-2d-sliced.c @@ -723,6 +723,8 @@ _cogl_texture_2d_sliced_slices_create (CoglTexture2DSliced *tex_2ds, int (*slices_for_size) (int, int, int, GArray*); + _COGL_GET_CONTEXT (ctx, FALSE); + /* Initialize size of largest slice according to supported features */ if (cogl_features_available (COGL_FEATURE_TEXTURE_NPOT)) { @@ -737,7 +739,10 @@ _cogl_texture_2d_sliced_slices_create (CoglTexture2DSliced *tex_2ds, slices_for_size = _cogl_pot_slices_for_size; } - _cogl_pixel_format_to_gl (format, &gl_intformat, NULL, &gl_type); + ctx->texture_driver->pixel_format_to_gl (format, + &gl_intformat, + NULL, + &gl_type); /* Negative number means no slicing forced by the user */ if (tex_2ds->max_waste <= -1) @@ -745,7 +750,7 @@ _cogl_texture_2d_sliced_slices_create (CoglTexture2DSliced *tex_2ds, CoglSpan span; /* Check if size supported else bail out */ - if (!_cogl_texture_driver_size_supported (GL_TEXTURE_2D, + if (!ctx->texture_driver->size_supported (GL_TEXTURE_2D, gl_intformat, gl_type, max_width, @@ -779,7 +784,7 @@ _cogl_texture_2d_sliced_slices_create (CoglTexture2DSliced *tex_2ds, else { /* Decrease the size of largest slice until supported by GL */ - while (!_cogl_texture_driver_size_supported (GL_TEXTURE_2D, + while (!ctx->texture_driver->size_supported (GL_TEXTURE_2D, gl_intformat, gl_type, max_width, @@ -1318,10 +1323,12 @@ _cogl_texture_2d_sliced_set_region (CoglTexture *tex, GLenum gl_format; GLenum gl_type; - _cogl_pixel_format_to_gl (_cogl_bitmap_get_format (bmp), - NULL, /* internal format */ - &gl_format, - &gl_type); + _COGL_GET_CONTEXT (ctx, FALSE); + + ctx->texture_driver->pixel_format_to_gl (_cogl_bitmap_get_format (bmp), + NULL, /* internal format */ + &gl_format, + &gl_type); /* Send data to GL */ _cogl_texture_2d_sliced_upload_subregion_to_gl (tex_2ds, diff --git a/cogl/cogl-texture-2d.c b/cogl/cogl-texture-2d.c index 267ed9ac9..888720440 100644 --- a/cogl/cogl-texture-2d.c +++ b/cogl/cogl-texture-2d.c @@ -177,6 +177,8 @@ _cogl_texture_2d_can_create (unsigned int width, GLenum gl_intformat; GLenum gl_type; + _COGL_GET_CONTEXT (ctx, FALSE); + /* If NPOT textures aren't supported then the size must be a power of two */ if (!cogl_features_available (COGL_FEATURE_TEXTURE_NPOT) && @@ -184,13 +186,13 @@ _cogl_texture_2d_can_create (unsigned int width, !_cogl_util_is_pot (height))) return FALSE; - _cogl_pixel_format_to_gl (internal_format, - &gl_intformat, - NULL, - &gl_type); + ctx->texture_driver->pixel_format_to_gl (internal_format, + &gl_intformat, + NULL, + &gl_type); /* Check that the driver can create a texture with that size */ - if (!_cogl_texture_driver_size_supported (GL_TEXTURE_2D, + if (!ctx->texture_driver->size_supported (GL_TEXTURE_2D, gl_intformat, gl_type, width, @@ -256,15 +258,15 @@ cogl_texture_2d_new_with_size (CoglContext *ctx, return NULL; } - internal_format = _cogl_pixel_format_to_gl (internal_format, - &gl_intformat, - &gl_format, - &gl_type); + internal_format = ctx->texture_driver->pixel_format_to_gl (internal_format, + &gl_intformat, + &gl_format, + &gl_type); tex_2d = _cogl_texture_2d_create_base (width, height, COGL_TEXTURE_NONE, internal_format); - _cogl_texture_driver_gen (GL_TEXTURE_2D, 1, &tex_2d->gl_texture); + ctx->texture_driver->gen (GL_TEXTURE_2D, 1, &tex_2d->gl_texture); _cogl_bind_gl_texture_transient (GL_TEXTURE_2D, tex_2d->gl_texture, tex_2d->is_foreign); @@ -287,6 +289,8 @@ _cogl_texture_2d_new_from_bitmap (CoglBitmap *bmp, GLenum gl_type; guint8 *data; + _COGL_GET_CONTEXT (ctx, COGL_INVALID_HANDLE); + g_return_val_if_fail (bmp != NULL, COGL_INVALID_HANDLE); internal_format = @@ -337,8 +341,8 @@ _cogl_texture_2d_new_from_bitmap (CoglBitmap *bmp, _cogl_bitmap_unmap (dst_bmp); } - _cogl_texture_driver_gen (GL_TEXTURE_2D, 1, &tex_2d->gl_texture); - _cogl_texture_driver_upload_to_gl (GL_TEXTURE_2D, + ctx->texture_driver->gen (GL_TEXTURE_2D, 1, &tex_2d->gl_texture); + ctx->texture_driver->upload_to_gl (GL_TEXTURE_2D, tex_2d->gl_texture, FALSE, dst_bmp, @@ -407,7 +411,7 @@ cogl_texture_2d_new_from_foreign (CoglContext *ctx, GLenum gl_int_format = 0; CoglTexture2D *tex_2d; - if (!_cogl_texture_driver_allows_foreign_gl_target (GL_TEXTURE_2D)) + if (!ctx->texture_driver->allows_foreign_gl_target (GL_TEXTURE_2D)) return COGL_INVALID_HANDLE; /* Make sure it is a valid GL texture object */ @@ -443,17 +447,18 @@ cogl_texture_2d_new_from_foreign (CoglContext *ctx, /* If we can query GL for the actual pixel format then we'll ignore the passed in format and use that. */ - if (!_cogl_pixel_format_from_gl_internal (gl_int_format, &format)) + if (!ctx->texture_driver->pixel_format_from_gl_internal (gl_int_format, + &format)) return COGL_INVALID_HANDLE; #else /* Otherwise we'll assume we can derive the GL format from the passed in format */ - _cogl_pixel_format_to_gl (format, - &gl_int_format, - NULL, - NULL); + ctx->texture_driver->pixel_format_to_gl (format, + &gl_int_format, + NULL, + NULL); #endif @@ -530,7 +535,7 @@ _cogl_egl_texture_2d_new_from_image (CoglContext *ctx, tex_2d = _cogl_texture_2d_create_base (width, height, COGL_TEXTURE_NONE, format); - _cogl_texture_driver_gen (GL_TEXTURE_2D, 1, &tex_2d->gl_texture); + ctx->texture_driver->gen (GL_TEXTURE_2D, 1, &tex_2d->gl_texture); _cogl_bind_gl_texture_transient (GL_TEXTURE_2D, tex_2d->gl_texture, FALSE); @@ -766,7 +771,7 @@ _cogl_texture_2d_pre_paint (CoglTexture *tex, CoglTexturePrePaintFlags flags) available we'll fallback to temporarily enabling GL_GENERATE_MIPMAP and reuploading the first pixel */ if (cogl_features_available (COGL_FEATURE_OFFSCREEN)) - _cogl_texture_driver_gl_generate_mipmaps (GL_TEXTURE_2D); + ctx->texture_driver->gl_generate_mipmaps (GL_TEXTURE_2D); #ifndef HAVE_COGL_GLES2 else { @@ -808,10 +813,12 @@ _cogl_texture_2d_set_region (CoglTexture *tex, GLenum gl_type; guint8 *data; - _cogl_pixel_format_to_gl (_cogl_bitmap_get_format (bmp), - NULL, /* internal format */ - &gl_format, - &gl_type); + _COGL_GET_CONTEXT (ctx, FALSE); + + ctx->texture_driver->pixel_format_to_gl (_cogl_bitmap_get_format (bmp), + NULL, /* internal format */ + &gl_format, + &gl_type); /* If this touches the first pixel then we'll update our copy */ if (dst_x == 0 && dst_y == 0 && @@ -830,7 +837,7 @@ _cogl_texture_2d_set_region (CoglTexture *tex, } /* Send data to GL */ - _cogl_texture_driver_upload_subregion_to_gl (GL_TEXTURE_2D, + ctx->texture_driver->upload_subregion_to_gl (GL_TEXTURE_2D, tex_2d->gl_texture, FALSE, src_x, src_y, @@ -856,19 +863,21 @@ _cogl_texture_2d_get_data (CoglTexture *tex, GLenum gl_format; GLenum gl_type; + _COGL_GET_CONTEXT (ctx, FALSE); + bpp = _cogl_get_format_bpp (format); - _cogl_pixel_format_to_gl (format, - NULL, /* internal format */ - &gl_format, - &gl_type); + ctx->texture_driver->pixel_format_to_gl (format, + NULL, /* internal format */ + &gl_format, + &gl_type); - _cogl_texture_driver_prep_gl_for_pixels_download (rowstride, bpp); + ctx->texture_driver->prep_gl_for_pixels_download (rowstride, bpp); _cogl_bind_gl_texture_transient (GL_TEXTURE_2D, tex_2d->gl_texture, tex_2d->is_foreign); - return _cogl_texture_driver_gl_get_tex_image (GL_TEXTURE_2D, + return ctx->texture_driver->gl_get_tex_image (GL_TEXTURE_2D, gl_format, gl_type, data); diff --git a/cogl/cogl-texture-3d.c b/cogl/cogl-texture-3d.c index 7c1117243..48e2e2d7d 100644 --- a/cogl/cogl-texture-3d.c +++ b/cogl/cogl-texture-3d.c @@ -216,6 +216,8 @@ _cogl_texture_3d_can_create (unsigned int width, GLenum gl_intformat; GLenum gl_type; + _COGL_GET_CONTEXT (ctx, FALSE); + /* This should only happen on GLES */ if (!cogl_features_available (COGL_FEATURE_TEXTURE_3D)) { @@ -241,13 +243,13 @@ _cogl_texture_3d_can_create (unsigned int width, return FALSE; } - _cogl_pixel_format_to_gl (internal_format, - &gl_intformat, - NULL, - &gl_type); + ctx->texture_driver->pixel_format_to_gl (internal_format, + &gl_intformat, + NULL, + &gl_type); /* Check that the driver can create a texture with that size */ - if (!_cogl_texture_driver_size_supported_3d (GL_TEXTURE_3D, + if (!ctx->texture_driver->size_supported_3d (GL_TEXTURE_3D, gl_intformat, gl_type, width, @@ -288,15 +290,15 @@ cogl_texture_3d_new_with_size (unsigned int width, error)) return COGL_INVALID_HANDLE; - internal_format = _cogl_pixel_format_to_gl (internal_format, - &gl_intformat, - &gl_format, - &gl_type); + internal_format = ctx->texture_driver->pixel_format_to_gl (internal_format, + &gl_intformat, + &gl_format, + &gl_type); tex_3d = _cogl_texture_3d_create_base (width, height, depth, flags, internal_format); - _cogl_texture_driver_gen (GL_TEXTURE_3D, 1, &tex_3d->gl_texture); + ctx->texture_driver->gen (GL_TEXTURE_3D, 1, &tex_3d->gl_texture); _cogl_bind_gl_texture_transient (GL_TEXTURE_3D, tex_3d->gl_texture, FALSE); @@ -367,9 +369,9 @@ _cogl_texture_3d_new_from_bitmap (CoglBitmap *bmp, _cogl_bitmap_unmap (dst_bmp); } - _cogl_texture_driver_gen (GL_TEXTURE_3D, 1, &tex_3d->gl_texture); + ctx->texture_driver->gen (GL_TEXTURE_3D, 1, &tex_3d->gl_texture); - _cogl_texture_driver_upload_to_gl_3d (GL_TEXTURE_3D, + ctx->texture_driver->upload_to_gl_3d (GL_TEXTURE_3D, tex_3d->gl_texture, FALSE, /* is_foreign */ height, @@ -577,7 +579,7 @@ _cogl_texture_3d_pre_paint (CoglTexture *tex, CoglTexturePrePaintFlags flags) available we'll fallback to temporarily enabling GL_GENERATE_MIPMAP and reuploading the first pixel */ if (cogl_features_available (COGL_FEATURE_OFFSCREEN)) - _cogl_texture_driver_gl_generate_mipmaps (GL_TEXTURE_3D); + ctx->texture_driver->gl_generate_mipmaps (GL_TEXTURE_3D); #ifndef HAVE_COGL_GLES2 else { diff --git a/cogl/cogl-texture-driver.h b/cogl/cogl-texture-driver.h index bc1ca63bd..6cbc3afd0 100644 --- a/cogl/cogl-texture-driver.h +++ b/cogl/cogl-texture-driver.h @@ -24,190 +24,185 @@ #ifndef __COGL_TEXTURE_DRIVER_H #define __COGL_TEXTURE_DRIVER_H -/* - * A very small wrapper around glGenTextures() that ensures we default to - * non-mipmap filters when creating textures. This is to save some memory as - * the driver will not allocate room for the mipmap tree. - */ -void -_cogl_texture_driver_gen (GLenum gl_target, - GLsizei n, - GLuint *textures); +typedef struct _CoglTextureDriver CoglTextureDriver; -/* - * This sets up the glPixelStore state for an upload to a destination with - * the same size, and with no offset. - */ -/* NB: GLES can't upload a sub region of pixel data from a larger source - * buffer which is why this interface is limited. The GL driver has a more - * flexible version of this function that is uses internally */ -void -_cogl_texture_driver_prep_gl_for_pixels_upload (int pixels_rowstride, - int pixels_bpp); +struct _CoglTextureDriver +{ + /* + * A very small wrapper around glGenTextures() that ensures we default to + * non-mipmap filters when creating textures. This is to save some memory as + * the driver will not allocate room for the mipmap tree. + */ + void + (* gen) (GLenum gl_target, + GLsizei n, + GLuint *textures); -/* - * This uploads a sub-region from source_bmp to a single GL texture handle (i.e - * a single CoglTexture slice) - * - * It also updates the array of tex->first_pixels[slice_index] if - * dst_{x,y} == 0 - * - * The driver abstraction is in place because GLES doesn't support the pixel - * store options required to source from a subregion, so for GLES we have - * to manually create a transient source bitmap. - * - * XXX: sorry for the ridiculous number of arguments :-( - */ -void -_cogl_texture_driver_upload_subregion_to_gl (GLenum gl_target, - GLuint gl_handle, - gboolean is_foreign, - int src_x, - int src_y, - int dst_x, - int dst_y, - int width, - int height, - CoglBitmap *source_bmp, - GLuint source_gl_format, - GLuint source_gl_type); + /* + * This sets up the glPixelStore state for an upload to a destination with + * the same size, and with no offset. + */ + /* NB: GLES can't upload a sub region of pixel data from a larger source + * buffer which is why this interface is limited. The GL driver has a more + * flexible version of this function that is uses internally */ + void + (* prep_gl_for_pixels_upload) (int pixels_rowstride, + int pixels_bpp); -/* - * Replaces the contents of the GL texture with the entire bitmap. On - * GL this just directly calls glTexImage2D, but under GLES it needs - * to copy the bitmap if the rowstride is not a multiple of a possible - * alignment value because there is no GL_UNPACK_ROW_LENGTH - */ -void -_cogl_texture_driver_upload_to_gl (GLenum gl_target, - GLuint gl_handle, - gboolean is_foreign, - CoglBitmap *source_bmp, - GLint internal_gl_format, - GLuint source_gl_format, - GLuint source_gl_type); + /* + * This uploads a sub-region from source_bmp to a single GL texture + * handle (i.e a single CoglTexture slice) + * + * It also updates the array of tex->first_pixels[slice_index] if + * dst_{x,y} == 0 + * + * The driver abstraction is in place because GLES doesn't support the pixel + * store options required to source from a subregion, so for GLES we have + * to manually create a transient source bitmap. + * + * XXX: sorry for the ridiculous number of arguments :-( + */ + void + (* upload_subregion_to_gl) (GLenum gl_target, + GLuint gl_handle, + gboolean is_foreign, + int src_x, + int src_y, + int dst_x, + int dst_y, + int width, + int height, + CoglBitmap *source_bmp, + GLuint source_gl_format, + GLuint source_gl_type); -/* - * Replaces the contents of the GL texture with the entire bitmap. The - * width of the texture is inferred from the bitmap. The height and - * depth of the texture is given directly. The 'image_height' (which - * is the number of rows between images) is inferred by dividing the - * height of the bitmap by the depth. - */ -void -_cogl_texture_driver_upload_to_gl_3d (GLenum gl_target, - GLuint gl_handle, - gboolean is_foreign, - GLint height, - GLint depth, - CoglBitmap *source_bmp, - GLint internal_gl_format, - GLuint source_gl_format, - GLuint source_gl_type); + /* + * Replaces the contents of the GL texture with the entire bitmap. On + * GL this just directly calls glTexImage2D, but under GLES it needs + * to copy the bitmap if the rowstride is not a multiple of a possible + * alignment value because there is no GL_UNPACK_ROW_LENGTH + */ + void + (* upload_to_gl) (GLenum gl_target, + GLuint gl_handle, + gboolean is_foreign, + CoglBitmap *source_bmp, + GLint internal_gl_format, + GLuint source_gl_format, + GLuint source_gl_type); -/* - * This sets up the glPixelStore state for an download to a destination with - * the same size, and with no offset. - */ -/* NB: GLES can't download pixel data into a sub region of a larger destination - * buffer, the GL driver has a more flexible version of this function that it - * uses internally. */ -void -_cogl_texture_driver_prep_gl_for_pixels_download (int pixels_rowstride, - int pixels_bpp); + /* + * Replaces the contents of the GL texture with the entire bitmap. The + * width of the texture is inferred from the bitmap. The height and + * depth of the texture is given directly. The 'image_height' (which + * is the number of rows between images) is inferred by dividing the + * height of the bitmap by the depth. + */ + void + (* upload_to_gl_3d) (GLenum gl_target, + GLuint gl_handle, + gboolean is_foreign, + GLint height, + GLint depth, + CoglBitmap *source_bmp, + GLint internal_gl_format, + GLuint source_gl_format, + GLuint source_gl_type); -/* - * This driver abstraction is in place because GLES doesn't have a sane way to - * download data from a texture so you litterally render the texture to the - * backbuffer, and retrive the data using glReadPixels :-( - */ -gboolean -_cogl_texture_driver_download_from_gl (CoglTexture *tex, - CoglBitmap *target_bmp, - GLuint target_gl_format, - GLuint target_gl_type); + /* + * This sets up the glPixelStore state for an download to a destination with + * the same size, and with no offset. + */ + /* NB: GLES can't download pixel data into a sub region of a larger + * destination buffer, the GL driver has a more flexible version of + * this function that it uses internally. */ + void + (* prep_gl_for_pixels_download) (int pixels_rowstride, + int pixels_bpp); -/* - * This driver abstraction is needed because GLES doesn't support glGetTexImage - * (). On GLES this currently just returns FALSE which will lead to a generic - * fallback path being used that simply renders the texture and reads it back - * from the framebuffer. (See _cogl_texture_draw_and_read () ) - */ -gboolean -_cogl_texture_driver_gl_get_tex_image (GLenum gl_target, - GLenum dest_gl_format, - GLenum dest_gl_type, - guint8 *dest); + /* + * This driver abstraction is needed because GLES doesn't support + * glGetTexImage (). On GLES this currently just returns FALSE which + * will lead to a generic fallback path being used that simply + * renders the texture and reads it back from the framebuffer. (See + * _cogl_texture_draw_and_read () ) + */ + gboolean + (* gl_get_tex_image) (GLenum gl_target, + GLenum dest_gl_format, + GLenum dest_gl_type, + guint8 *dest); -/* - * It may depend on the driver as to what texture sizes are supported... - */ -gboolean -_cogl_texture_driver_size_supported (GLenum gl_target, - GLenum gl_format, - GLenum gl_type, - int width, - int height); + /* + * It may depend on the driver as to what texture sizes are supported... + */ + gboolean + (* size_supported) (GLenum gl_target, + GLenum gl_format, + GLenum gl_type, + int width, + int height); -gboolean -_cogl_texture_driver_size_supported_3d (GLenum gl_target, - GLenum gl_format, - GLenum gl_type, - int width, - int height, - int depth); + gboolean + (* size_supported_3d) (GLenum gl_target, + GLenum gl_format, + GLenum gl_type, + int width, + int height, + int depth); -/* - * This driver abstraction is needed because GLES doesn't support setting - * a texture border color. - */ -void -_cogl_texture_driver_try_setting_gl_border_color ( - GLuint gl_target, - const GLfloat *transparent_color); + /* + * This driver abstraction is needed because GLES doesn't support setting + * a texture border color. + */ + void + (* try_setting_gl_border_color) ( + GLuint gl_target, + const GLfloat *transparent_color); -/* - * XXX: this should live in cogl/{gl,gles}/cogl.c - */ -gboolean -_cogl_pixel_format_from_gl_internal (GLenum gl_int_format, - CoglPixelFormat *out_format); + /* + * XXX: this should live in cogl/{gl,gles}/cogl.c + */ + gboolean + (* pixel_format_from_gl_internal) (GLenum gl_int_format, + CoglPixelFormat *out_format); -/* - * XXX: this should live in cogl/{gl,gles}/cogl.c - */ -CoglPixelFormat -_cogl_pixel_format_to_gl (CoglPixelFormat format, - GLenum *out_glintformat, - GLenum *out_glformat, - GLenum *out_gltype); + /* + * XXX: this should live in cogl/{gl,gles}/cogl.c + */ + CoglPixelFormat + (* pixel_format_to_gl) (CoglPixelFormat format, + GLenum *out_glintformat, + GLenum *out_glformat, + GLenum *out_gltype); -/* - * It may depend on the driver as to what texture targets may be used when - * creating a foreign texture. E.g. OpenGL supports ARB_texture_rectangle - * but GLES doesn't - */ -gboolean -_cogl_texture_driver_allows_foreign_gl_target (GLenum gl_target); + /* + * It may depend on the driver as to what texture targets may be used when + * creating a foreign texture. E.g. OpenGL supports ARB_texture_rectangle + * but GLES doesn't + */ + gboolean + (* allows_foreign_gl_target) (GLenum gl_target); -/* - * glGenerateMipmap semantics may need to be emulated for some drivers. E.g. by - * enabling auto mipmap generation an re-loading a number of known texels. - */ -void -_cogl_texture_driver_gl_generate_mipmaps (GLenum texture_target); + /* + * glGenerateMipmap semantics may need to be emulated for some + * drivers. E.g. by enabling auto mipmap generation an re-loading a + * number of known texels. + */ + void + (* gl_generate_mipmaps) (GLenum texture_target); -/* - * The driver may impose constraints on what formats can be used to store - * texture data read from textures. For example GLES currently only supports - * RGBA_8888, and so we need to manually convert the data if the final - * destination has another format. - */ -CoglPixelFormat -_cogl_texture_driver_find_best_gl_get_data_format ( - CoglPixelFormat format, - GLenum *closest_gl_format, - GLenum *closest_gl_type); + /* + * The driver may impose constraints on what formats can be used to store + * texture data read from textures. For example GLES currently only supports + * RGBA_8888, and so we need to manually convert the data if the final + * destination has another format. + */ + CoglPixelFormat + (* find_best_gl_get_data_format) (CoglPixelFormat format, + GLenum *closest_gl_format, + GLenum *closest_gl_type); +}; #endif /* __COGL_TEXTURE_DRIVER_H */ diff --git a/cogl/cogl-texture-private.h b/cogl/cogl-texture-private.h index 57093cb7b..fa0d57917 100644 --- a/cogl/cogl-texture-private.h +++ b/cogl/cogl-texture-private.h @@ -80,7 +80,7 @@ struct _CoglTextureVtable /* This should copy the image data of the texture into @data. The requested format will have been first passed through - _cogl_texture_driver_find_best_gl_get_data_format so it should + ctx->texture_driver->find_best_gl_get_data_format so it should always be a format that is valid for GL (ie, no conversion should be necessary). */ gboolean (* get_data) (CoglTexture *tex, diff --git a/cogl/cogl-texture-rectangle.c b/cogl/cogl-texture-rectangle.c index dc8bb7734..88cf5bcd4 100644 --- a/cogl/cogl-texture-rectangle.c +++ b/cogl/cogl-texture-rectangle.c @@ -196,16 +196,18 @@ _cogl_texture_rectangle_can_create (unsigned int width, GLenum gl_intformat; GLenum gl_type; + _COGL_GET_CONTEXT (ctx, FALSE); + if (!cogl_features_available (COGL_FEATURE_TEXTURE_RECTANGLE)) return FALSE; - _cogl_pixel_format_to_gl (internal_format, - &gl_intformat, - NULL, - &gl_type); + ctx->texture_driver->pixel_format_to_gl (internal_format, + &gl_intformat, + NULL, + &gl_type); /* Check that the driver can create a texture with that size */ - if (!_cogl_texture_driver_size_supported (GL_TEXTURE_RECTANGLE_ARB, + if (!ctx->texture_driver->size_supported (GL_TEXTURE_RECTANGLE_ARB, gl_intformat, gl_type, width, @@ -262,15 +264,15 @@ _cogl_texture_rectangle_new_with_size (unsigned int width, if (!_cogl_texture_rectangle_can_create (width, height, internal_format)) return COGL_INVALID_HANDLE; - internal_format = _cogl_pixel_format_to_gl (internal_format, - &gl_intformat, - &gl_format, - &gl_type); + internal_format = ctx->texture_driver->pixel_format_to_gl (internal_format, + &gl_intformat, + &gl_format, + &gl_type); tex_rect = _cogl_texture_rectangle_create_base (width, height, flags, internal_format); - _cogl_texture_driver_gen (GL_TEXTURE_RECTANGLE_ARB, 1, &tex_rect->gl_texture); + ctx->texture_driver->gen (GL_TEXTURE_RECTANGLE_ARB, 1, &tex_rect->gl_texture); _cogl_bind_gl_texture_transient (GL_TEXTURE_RECTANGLE_ARB, tex_rect->gl_texture, tex_rect->is_foreign); @@ -291,6 +293,8 @@ _cogl_texture_rectangle_new_from_bitmap (CoglBitmap *bmp, GLenum gl_format; GLenum gl_type; + _COGL_GET_CONTEXT (ctx, COGL_INVALID_HANDLE); + g_return_val_if_fail (cogl_is_bitmap (bmp), COGL_INVALID_HANDLE); internal_format = @@ -317,8 +321,8 @@ _cogl_texture_rectangle_new_from_bitmap (CoglBitmap *bmp, flags, internal_format); - _cogl_texture_driver_gen (GL_TEXTURE_RECTANGLE_ARB, 1, &tex_rect->gl_texture); - _cogl_texture_driver_upload_to_gl (GL_TEXTURE_RECTANGLE_ARB, + ctx->texture_driver->gen (GL_TEXTURE_RECTANGLE_ARB, 1, &tex_rect->gl_texture); + ctx->texture_driver->upload_to_gl (GL_TEXTURE_RECTANGLE_ARB, tex_rect->gl_texture, FALSE, dst_bmp, @@ -350,7 +354,7 @@ _cogl_texture_rectangle_new_from_foreign (GLuint gl_handle, _COGL_GET_CONTEXT (ctx, COGL_INVALID_HANDLE); - if (!_cogl_texture_driver_allows_foreign_gl_target (GL_TEXTURE_RECTANGLE_ARB)) + if (!ctx->texture_driver->allows_foreign_gl_target (GL_TEXTURE_RECTANGLE_ARB)) return COGL_INVALID_HANDLE; /* Make sure it is a valid GL texture object */ @@ -385,17 +389,18 @@ _cogl_texture_rectangle_new_from_foreign (GLuint gl_handle, /* If we can query GL for the actual pixel format then we'll ignore the passed in format and use that. */ - if (!_cogl_pixel_format_from_gl_internal (gl_int_format, &format)) + if (!ctx->texture_driver->pixel_format_from_gl_internal (gl_int_format, + &format)) return COGL_INVALID_HANDLE; #else /* Otherwise we'll assume we can derive the GL format from the passed in format */ - _cogl_pixel_format_to_gl (format, - &gl_int_format, - NULL, - NULL); + ctx->texture_driver->pixel_format_to_gl (format, + &gl_int_format, + NULL, + NULL); #endif @@ -558,13 +563,15 @@ _cogl_texture_rectangle_set_region (CoglTexture *tex, GLenum gl_format; GLenum gl_type; - _cogl_pixel_format_to_gl (_cogl_bitmap_get_format (bmp), - NULL, /* internal format */ - &gl_format, - &gl_type); + _COGL_GET_CONTEXT (ctx, FALSE); + + ctx->texture_driver->pixel_format_to_gl (_cogl_bitmap_get_format (bmp), + NULL, /* internal format */ + &gl_format, + &gl_type); /* Send data to GL */ - _cogl_texture_driver_upload_subregion_to_gl (GL_TEXTURE_RECTANGLE_ARB, + ctx->texture_driver->upload_subregion_to_gl (GL_TEXTURE_RECTANGLE_ARB, tex_rect->gl_texture, FALSE, src_x, src_y, @@ -592,17 +599,17 @@ _cogl_texture_rectangle_get_data (CoglTexture *tex, bpp = _cogl_get_format_bpp (format); - _cogl_pixel_format_to_gl (format, - NULL, /* internal format */ - &gl_format, - &gl_type); + ctx->texture_driver->pixel_format_to_gl (format, + NULL, /* internal format */ + &gl_format, + &gl_type); - _cogl_texture_driver_prep_gl_for_pixels_download (rowstride, bpp); + ctx->texture_driver->prep_gl_for_pixels_download (rowstride, bpp); _cogl_bind_gl_texture_transient (GL_TEXTURE_RECTANGLE_ARB, tex_rect->gl_texture, tex_rect->is_foreign); - return _cogl_texture_driver_gl_get_tex_image (GL_TEXTURE_RECTANGLE_ARB, + return ctx->texture_driver->gl_get_tex_image (GL_TEXTURE_RECTANGLE_ARB, gl_format, gl_type, data); diff --git a/cogl/cogl-texture.c b/cogl/cogl-texture.c index f2f0a3b58..ffd38b7ff 100644 --- a/cogl/cogl-texture.c +++ b/cogl/cogl-texture.c @@ -181,6 +181,8 @@ _cogl_texture_prepare_for_upload (CoglBitmap *src_bmp, CoglPixelFormat src_format = _cogl_bitmap_get_format (src_bmp); CoglBitmap *dst_bmp; + _COGL_GET_CONTEXT (ctx, NULL); + dst_format = _cogl_texture_determine_internal_format (src_format, dst_format); @@ -215,23 +217,23 @@ _cogl_texture_prepare_for_upload (CoglBitmap *src_bmp, /* Use the source format from the src bitmap type and the internal format from the dst format type so that GL can do the conversion */ - _cogl_pixel_format_to_gl (src_format, - NULL, /* internal format */ - out_glformat, - out_gltype); - _cogl_pixel_format_to_gl (dst_format, - out_glintformat, - NULL, - NULL); + ctx->texture_driver->pixel_format_to_gl (src_format, + NULL, /* internal format */ + out_glformat, + out_gltype); + ctx->texture_driver->pixel_format_to_gl (dst_format, + out_glintformat, + NULL, + NULL); #else /* HAVE_COGL_GL */ { CoglPixelFormat closest_format; - closest_format = _cogl_pixel_format_to_gl (dst_format, - out_glintformat, - out_glformat, - out_gltype); + closest_format = ctx->texture_driver->pixel_format_to_gl (dst_format, + out_glintformat, + out_glformat, + out_gltype); if (closest_format != src_format) dst_bmp = _cogl_bitmap_convert_format_and_premult (src_bmp, @@ -1378,6 +1380,8 @@ cogl_texture_get_data (CoglHandle handle, CoglTextureGetData tg_data; + _COGL_GET_CONTEXT (ctx, 0); + if (!cogl_is_texture (handle)) return 0; @@ -1401,7 +1405,7 @@ cogl_texture_get_data (CoglHandle handle, return byte_size; closest_format = - _cogl_texture_driver_find_best_gl_get_data_format (format, + ctx->texture_driver->find_best_gl_get_data_format (format, &closest_gl_format, &closest_gl_type); closest_bpp = _cogl_get_format_bpp (closest_format); diff --git a/cogl/cogl.c b/cogl/cogl.c index ea4d7c8b8..b77a62309 100644 --- a/cogl/cogl.c +++ b/cogl/cogl.c @@ -542,7 +542,10 @@ _cogl_read_pixels_with_rowstride (int x, bmp_format, width, height, rowstride, NULL, NULL); - _cogl_pixel_format_to_gl (format, &gl_intformat, &gl_format, &gl_type); + ctx->texture_driver->pixel_format_to_gl (format, + &gl_intformat, + &gl_format, + &gl_type); /* Under GLES only GL_RGBA with GL_UNSIGNED_BYTE as well as an implementation specific format under @@ -568,7 +571,7 @@ _cogl_read_pixels_with_rowstride (int x, (CoglBitmapDestroyNotify) g_free, NULL); - _cogl_texture_driver_prep_gl_for_pixels_download (4 * width, 4); + ctx->texture_driver->prep_gl_for_pixels_download (4 * width, 4); GE( ctx, glReadPixels (x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, @@ -598,7 +601,7 @@ _cogl_read_pixels_with_rowstride (int x, else #endif { - _cogl_texture_driver_prep_gl_for_pixels_download (rowstride, bpp); + ctx->texture_driver->prep_gl_for_pixels_download (rowstride, bpp); GE( ctx, glReadPixels (x, y, width, height, gl_format, gl_type, pixels) ); diff --git a/cogl/driver/gl/cogl-texture-driver-gl.c b/cogl/driver/gl/cogl-texture-driver-gl.c index fdb938e85..f68a95d59 100644 --- a/cogl/driver/gl/cogl-texture-driver-gl.c +++ b/cogl/driver/gl/cogl-texture-driver-gl.c @@ -46,7 +46,7 @@ #include #include -void +static void _cogl_texture_driver_gen (GLenum gl_target, GLsizei n, GLuint *textures) @@ -107,7 +107,7 @@ prep_gl_for_pixels_upload_full (int pixels_rowstride, _cogl_texture_prep_gl_alignment_for_pixels_upload (pixels_rowstride); } -void +static void _cogl_texture_driver_prep_gl_for_pixels_upload (int pixels_rowstride, int pixels_bpp) { @@ -136,14 +136,14 @@ prep_gl_for_pixels_download_full (int pixels_rowstride, _cogl_texture_prep_gl_alignment_for_pixels_download (pixels_rowstride); } -void +static void _cogl_texture_driver_prep_gl_for_pixels_download (int pixels_rowstride, int pixels_bpp) { prep_gl_for_pixels_download_full (pixels_rowstride, 0, 0, 0, pixels_bpp); } -void +static void _cogl_texture_driver_upload_subregion_to_gl (GLenum gl_target, GLuint gl_handle, gboolean is_foreign, @@ -183,7 +183,7 @@ _cogl_texture_driver_upload_subregion_to_gl (GLenum gl_target, _cogl_bitmap_unbind (source_bmp); } -void +static void _cogl_texture_driver_upload_to_gl (GLenum gl_target, GLuint gl_handle, gboolean is_foreign, @@ -217,7 +217,7 @@ _cogl_texture_driver_upload_to_gl (GLenum gl_target, _cogl_bitmap_unbind (source_bmp); } -void +static void _cogl_texture_driver_upload_to_gl_3d (GLenum gl_target, GLuint gl_handle, gboolean is_foreign, @@ -257,7 +257,7 @@ _cogl_texture_driver_upload_to_gl_3d (GLenum gl_target, _cogl_bitmap_unbind (source_bmp); } -gboolean +static gboolean _cogl_texture_driver_gl_get_tex_image (GLenum gl_target, GLenum dest_gl_format, GLenum dest_gl_type, @@ -273,7 +273,7 @@ _cogl_texture_driver_gl_get_tex_image (GLenum gl_target, return TRUE; } -gboolean +static gboolean _cogl_texture_driver_size_supported_3d (GLenum gl_target, GLenum gl_format, GLenum gl_type, @@ -303,7 +303,7 @@ _cogl_texture_driver_size_supported_3d (GLenum gl_target, return new_width != 0; } -gboolean +static gboolean _cogl_texture_driver_size_supported (GLenum gl_target, GLenum gl_format, GLenum gl_type, @@ -336,7 +336,7 @@ _cogl_texture_driver_size_supported (GLenum gl_target, return new_width != 0; } -void +static void _cogl_texture_driver_try_setting_gl_border_color ( GLuint gl_target, const GLfloat *transparent_color) @@ -350,9 +350,9 @@ _cogl_texture_driver_try_setting_gl_border_color ( transparent_color) ); } -gboolean -_cogl_pixel_format_from_gl_internal (GLenum gl_int_format, - CoglPixelFormat *out_format) +static gboolean +_cogl_texture_driver_pixel_format_from_gl_internal (GLenum gl_int_format, + CoglPixelFormat *out_format) { /* It doesn't really matter we convert to exact same format (some have no cogl match anyway) since format @@ -390,11 +390,11 @@ _cogl_pixel_format_from_gl_internal (GLenum gl_int_format, return FALSE; } -CoglPixelFormat -_cogl_pixel_format_to_gl (CoglPixelFormat format, - GLenum *out_glintformat, - GLenum *out_glformat, - GLenum *out_gltype) +static CoglPixelFormat +_cogl_texture_driver_pixel_format_to_gl (CoglPixelFormat format, + GLenum *out_glintformat, + GLenum *out_glformat, + GLenum *out_gltype) { CoglPixelFormat required_format; GLenum glintformat = 0; @@ -497,7 +497,7 @@ _cogl_pixel_format_to_gl (CoglPixelFormat format, return required_format; } -gboolean +static gboolean _cogl_texture_driver_allows_foreign_gl_target (GLenum gl_target) { /* GL_ARB_texture_rectangle textures are supported if they are @@ -513,7 +513,7 @@ _cogl_texture_driver_allows_foreign_gl_target (GLenum gl_target) return TRUE; } -void +static void _cogl_texture_driver_gl_generate_mipmaps (GLenum gl_target) { _COGL_GET_CONTEXT (ctx, NO_RETVAL); @@ -521,16 +521,35 @@ _cogl_texture_driver_gl_generate_mipmaps (GLenum gl_target) GE( ctx, glGenerateMipmap (gl_target) ); } -CoglPixelFormat +static CoglPixelFormat _cogl_texture_driver_find_best_gl_get_data_format ( CoglPixelFormat format, GLenum *closest_gl_format, GLenum *closest_gl_type) { /* Find closest format that's supported by GL */ - return _cogl_pixel_format_to_gl (format, - NULL, /* don't need */ - closest_gl_format, - closest_gl_type); + return _cogl_texture_driver_pixel_format_to_gl (format, + NULL, /* don't need */ + closest_gl_format, + closest_gl_type); } +const CoglTextureDriver +_cogl_texture_driver_gl = + { + _cogl_texture_driver_gen, + _cogl_texture_driver_prep_gl_for_pixels_upload, + _cogl_texture_driver_upload_subregion_to_gl, + _cogl_texture_driver_upload_to_gl, + _cogl_texture_driver_upload_to_gl_3d, + _cogl_texture_driver_prep_gl_for_pixels_download, + _cogl_texture_driver_gl_get_tex_image, + _cogl_texture_driver_size_supported, + _cogl_texture_driver_size_supported_3d, + _cogl_texture_driver_try_setting_gl_border_color, + _cogl_texture_driver_pixel_format_from_gl_internal, + _cogl_texture_driver_pixel_format_to_gl, + _cogl_texture_driver_allows_foreign_gl_target, + _cogl_texture_driver_gl_generate_mipmaps, + _cogl_texture_driver_find_best_gl_get_data_format + }; diff --git a/cogl/driver/gles/cogl-texture-driver-gles.c b/cogl/driver/gles/cogl-texture-driver-gles.c index 9a3f61bd6..0571848c0 100644 --- a/cogl/driver/gles/cogl-texture-driver-gles.c +++ b/cogl/driver/gles/cogl-texture-driver-gles.c @@ -53,7 +53,7 @@ #define GL_MAX_3D_TEXTURE_SIZE_OES 0x8073 #endif -void +static void _cogl_texture_driver_gen (GLenum gl_target, GLsizei n, GLuint *textures) @@ -84,14 +84,14 @@ _cogl_texture_driver_gen (GLenum gl_target, } } -void +static void _cogl_texture_driver_prep_gl_for_pixels_upload (int pixels_rowstride, int pixels_bpp) { _cogl_texture_prep_gl_alignment_for_pixels_upload (pixels_rowstride); } -void +static void _cogl_texture_driver_prep_gl_for_pixels_download (int pixels_rowstride, int pixels_bpp) { @@ -124,7 +124,7 @@ prepare_bitmap_alignment_for_upload (CoglBitmap *src_bmp) return _cogl_bitmap_copy (src_bmp); } -void +static void _cogl_texture_driver_upload_subregion_to_gl (GLenum gl_target, GLuint gl_handle, gboolean is_foreign, @@ -192,7 +192,7 @@ _cogl_texture_driver_upload_subregion_to_gl (GLenum gl_target, cogl_object_unref (slice_bmp); } -void +static void _cogl_texture_driver_upload_to_gl (GLenum gl_target, GLuint gl_handle, gboolean is_foreign, @@ -233,7 +233,7 @@ _cogl_texture_driver_upload_to_gl (GLenum gl_target, cogl_object_unref (bmp); } -void +static void _cogl_texture_driver_upload_to_gl_3d (GLenum gl_target, GLuint gl_handle, gboolean is_foreign, @@ -341,7 +341,7 @@ _cogl_texture_driver_upload_to_gl_3d (GLenum gl_target, /* NB: GLES doesn't support glGetTexImage2D, so cogl-texture will instead * fallback to a generic render + readpixels approach to downloading * texture data. (See _cogl_texture_draw_and_read() ) */ -gboolean +static gboolean _cogl_texture_driver_gl_get_tex_image (GLenum gl_target, GLenum dest_gl_format, GLenum dest_gl_type, @@ -350,7 +350,7 @@ _cogl_texture_driver_gl_get_tex_image (GLenum gl_target, return FALSE; } -gboolean +static gboolean _cogl_texture_driver_size_supported_3d (GLenum gl_target, GLenum gl_format, GLenum gl_type, @@ -370,7 +370,7 @@ _cogl_texture_driver_size_supported_3d (GLenum gl_target, return width <= max_size && height <= max_size && depth <= max_size; } -gboolean +static gboolean _cogl_texture_driver_size_supported (GLenum gl_target, GLenum gl_format, GLenum gl_type, @@ -388,7 +388,7 @@ _cogl_texture_driver_size_supported (GLenum gl_target, return width <= max_size && height <= max_size; } -void +static void _cogl_texture_driver_try_setting_gl_border_color ( GLuint gl_target, const GLfloat *transparent_color) @@ -396,18 +396,18 @@ _cogl_texture_driver_try_setting_gl_border_color ( /* FAIL! */ } -gboolean -_cogl_pixel_format_from_gl_internal (GLenum gl_int_format, - CoglPixelFormat *out_format) +static gboolean +_cogl_texture_driver_pixel_format_from_gl_internal (GLenum gl_int_format, + CoglPixelFormat *out_format) { return TRUE; } -CoglPixelFormat -_cogl_pixel_format_to_gl (CoglPixelFormat format, - GLenum *out_glintformat, - GLenum *out_glformat, - GLenum *out_gltype) +static CoglPixelFormat +_cogl_texture_driver_pixel_format_to_gl (CoglPixelFormat format, + GLenum *out_glintformat, + GLenum *out_glformat, + GLenum *out_gltype) { CoglPixelFormat required_format; GLenum glintformat = 0; @@ -487,7 +487,7 @@ _cogl_pixel_format_to_gl (CoglPixelFormat format, return required_format; } -gboolean +static gboolean _cogl_texture_driver_allows_foreign_gl_target (GLenum gl_target) { /* Allow 2-dimensional textures only */ @@ -496,7 +496,7 @@ _cogl_texture_driver_allows_foreign_gl_target (GLenum gl_target) return TRUE; } -void +static void _cogl_texture_driver_gl_generate_mipmaps (GLenum gl_target) { #ifdef HAVE_COGL_GLES2 @@ -506,7 +506,7 @@ _cogl_texture_driver_gl_generate_mipmaps (GLenum gl_target) #endif } -CoglPixelFormat +static CoglPixelFormat _cogl_texture_driver_find_best_gl_get_data_format ( CoglPixelFormat format, GLenum *closest_gl_format, @@ -520,3 +520,22 @@ _cogl_texture_driver_find_best_gl_get_data_format ( return COGL_PIXEL_FORMAT_RGBA_8888; } +const CoglTextureDriver +_cogl_texture_driver_gles = + { + _cogl_texture_driver_gen, + _cogl_texture_driver_prep_gl_for_pixels_upload, + _cogl_texture_driver_upload_subregion_to_gl, + _cogl_texture_driver_upload_to_gl, + _cogl_texture_driver_upload_to_gl_3d, + _cogl_texture_driver_prep_gl_for_pixels_download, + _cogl_texture_driver_gl_get_tex_image, + _cogl_texture_driver_size_supported, + _cogl_texture_driver_size_supported_3d, + _cogl_texture_driver_try_setting_gl_border_color, + _cogl_texture_driver_pixel_format_from_gl_internal, + _cogl_texture_driver_pixel_format_to_gl, + _cogl_texture_driver_allows_foreign_gl_target, + _cogl_texture_driver_gl_generate_mipmaps, + _cogl_texture_driver_find_best_gl_get_data_format + };