diff --git a/cogl/Makefile.am b/cogl/Makefile.am index 02ab16601..995453832 100644 --- a/cogl/Makefile.am +++ b/cogl/Makefile.am @@ -124,10 +124,12 @@ libclutter_cogl_la_SOURCES = \ $(srcdir)/cogl-debug.c \ $(srcdir)/cogl-sub-texture-private.h \ $(srcdir)/cogl-texture-private.h \ + $(srcdir)/cogl-texture-2d-private.h \ $(srcdir)/cogl-texture-2d-sliced-private.h \ $(srcdir)/cogl-texture-driver.h \ $(srcdir)/cogl-sub-texture.c \ $(srcdir)/cogl-texture.c \ + $(srcdir)/cogl-texture-2d.c \ $(srcdir)/cogl-texture-2d-sliced.c \ $(srcdir)/cogl-spans.h \ $(srcdir)/cogl-spans.c \ diff --git a/cogl/cogl-texture-2d-private.h b/cogl/cogl-texture-2d-private.h new file mode 100644 index 000000000..69910db66 --- /dev/null +++ b/cogl/cogl-texture-2d-private.h @@ -0,0 +1,69 @@ +/* + * Cogl + * + * An object oriented GL/GLES Abstraction/Utility Layer + * + * Copyright (C) 2009 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __COGL_TEXTURE_2D_H +#define __COGL_TEXTURE_2D_H + +#include "cogl-handle.h" +#include "cogl-material-private.h" +#include "cogl-texture-private.h" + +#define COGL_TEXTURE_2D(tex) ((CoglTexture2D *) tex) + +typedef struct _CoglTexture2D CoglTexture2D; + +struct _CoglTexture2D +{ + CoglTexture _parent; + + /* The internal format of the GL texture represented as a + CoglPixelFormat */ + CoglPixelFormat format; + /* The internal format of the GL texture represented as a GL enum */ + GLenum gl_format; + /* The texture object number */ + GLuint gl_texture; + gint width; + gint height; + GLenum min_filter; + GLenum mag_filter; + GLint wrap_mode; + gboolean auto_mipmap; + gboolean mipmaps_dirty; +}; + +GQuark +_cogl_handle_texture_2d_get_type (void); + +CoglHandle +_cogl_texture_2d_new_with_size (unsigned int width, + unsigned int height, + CoglTextureFlags flags, + CoglPixelFormat internal_format); + +CoglHandle +_cogl_texture_2d_new_from_bitmap (CoglHandle bmp_handle, + CoglTextureFlags flags, + CoglPixelFormat internal_format); + +#endif /* __COGL_TEXTURE_2D_H */ diff --git a/cogl/cogl-texture-2d.c b/cogl/cogl-texture-2d.c new file mode 100644 index 000000000..e605bb73e --- /dev/null +++ b/cogl/cogl-texture-2d.c @@ -0,0 +1,623 @@ +/* + * Cogl + * + * An object oriented GL/GLES Abstraction/Utility Layer + * + * Copyright (C) 2009 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Authors: + * Neil Roberts + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "cogl.h" +#include "cogl-internal.h" +#include "cogl-util.h" +#include "cogl-texture-private.h" +#include "cogl-texture-2d-private.h" +#include "cogl-texture-driver.h" +#include "cogl-context.h" +#include "cogl-handle.h" + +#include +#include + +static void _cogl_texture_2d_free (CoglTexture2D *tex_2d); + +COGL_HANDLE_DEFINE (Texture2D, texture_2d); + +static const CoglTextureVtable cogl_texture_2d_vtable; + +typedef struct _CoglTexture2DManualRepeatData +{ + CoglTexture2D *tex_2d; + CoglTextureSliceCallback callback; + void *user_data; +} CoglTexture2DManualRepeatData; + +static void +_cogl_texture_2d_wrap_coords (float t_1, float t_2, + float *out_t_1, float *out_t_2) +{ + float int_part; + + /* Wrap t_1 and t_2 to the range [0,1] */ + + modff (t_1 < t_2 ? t_1 : t_2, &int_part); + t_1 -= int_part; + t_2 -= int_part; + if (signbit (int_part)) + { + *out_t_1 = 1.0f - t_1; + *out_t_2 = 1.0f - t_2; + } + else + { + *out_t_1 = t_1; + *out_t_2 = t_2; + } +} + +static void +_cogl_texture_2d_manual_repeat_cb (const float *coords, + void *user_data) +{ + CoglTexture2DManualRepeatData *data = user_data; + float slice_coords[4]; + + _cogl_texture_2d_wrap_coords (coords[0], coords[2], + slice_coords + 0, slice_coords + 2); + _cogl_texture_2d_wrap_coords (coords[1], coords[3], + slice_coords + 1, slice_coords + 3); + + data->callback (COGL_TEXTURE (data->tex_2d), + data->tex_2d->gl_texture, + GL_TEXTURE_2D, + slice_coords, + coords, + data->user_data); +} + +static void +_cogl_texture_2d_foreach_sub_texture_in_region ( + CoglTexture *tex, + float virtual_tx_1, + float virtual_ty_1, + float virtual_tx_2, + float virtual_ty_2, + CoglTextureSliceCallback callback, + void *user_data) +{ + CoglTexture2D *tex_2d = COGL_TEXTURE_2D (tex); + CoglTexture2DManualRepeatData data; + + data.tex_2d = tex_2d; + data.callback = callback; + data.user_data = user_data; + + /* We need to implement manual repeating because if Cogl is calling + this function then it will set the wrap mode to GL_CLAMP_TO_EDGE + and hardware repeating can't be done */ + _cogl_texture_iterate_manual_repeats (_cogl_texture_2d_manual_repeat_cb, + virtual_tx_1, virtual_ty_1, + virtual_tx_2, virtual_ty_2, + &data); +} + +static void +_cogl_texture_2d_set_wrap_mode_parameter (CoglTexture *tex, + GLenum wrap_mode) +{ + CoglTexture2D *tex_2d = COGL_TEXTURE_2D (tex); + + /* Only set the wrap mode if it's different from the current + value to avoid too many GL calls */ + if (tex_2d->wrap_mode != wrap_mode) + { + /* Any queued texture rectangles may be depending on the + * previous wrap mode... */ + _cogl_journal_flush (); + + GE( glBindTexture (GL_TEXTURE_2D, tex_2d->gl_texture) ); + GE( glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_mode) ); + GE( glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_mode) ); + + tex_2d->wrap_mode = wrap_mode; + } +} + +static void +_cogl_texture_2d_free (CoglTexture2D *tex_2d) +{ + GE( glDeleteTextures (1, &tex_2d->gl_texture) ); + g_free (tex_2d); +} + +static gboolean +_cogl_texture_2d_is_pot (unsigned int num) +{ + gboolean have_bit = FALSE; + + /* Make sure there is only one bit set */ + while (num) + { + if (num & 1) + { + if (have_bit) + return FALSE; + have_bit = TRUE; + } + num >>= 1; + } + + return TRUE; +} + +static gboolean +_cogl_texture_2d_can_create (unsigned int width, + unsigned int height, + CoglPixelFormat internal_format) +{ + GLenum gl_intformat; + GLenum gl_type; + + /* If the driver doesn't support glGenerateMipmap then we need to + store a copy of the first pixels to cause an update. Instead of + duplicating the code here we'll just make it fallback to + CoglTexture2DSliced */ + if (!cogl_features_available (COGL_FEATURE_OFFSCREEN)) + return FALSE; + + /* If NPOT textures aren't supported then the size must be a power + of two */ + if (!cogl_features_available (COGL_FEATURE_TEXTURE_NPOT) && + (!_cogl_texture_2d_is_pot (width) || + !_cogl_texture_2d_is_pot (height))) + return FALSE; + + _cogl_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, + gl_intformat, + gl_type, + width, + height)) + return FALSE; + + return TRUE; +} + +static CoglTexture2D * +_cogl_texture_2d_create_base (unsigned int width, + unsigned int height, + CoglTextureFlags flags, + CoglPixelFormat internal_format) +{ + CoglTexture2D *tex_2d = g_new (CoglTexture2D, 1); + CoglTexture *tex = COGL_TEXTURE (tex_2d); + + tex->vtable = &cogl_texture_2d_vtable; + + tex_2d->width = width; + tex_2d->height = height; + tex_2d->mipmaps_dirty = TRUE; + tex_2d->auto_mipmap = (flags & COGL_TEXTURE_NO_AUTO_MIPMAP) == 0; + + /* Unknown filter */ + tex_2d->min_filter = GL_FALSE; + tex_2d->mag_filter = GL_FALSE; + + /* Wrap mode not yet set */ + tex_2d->wrap_mode = GL_FALSE; + + tex_2d->format = internal_format; + + return tex_2d; +} + +CoglHandle +_cogl_texture_2d_new_with_size (unsigned int width, + unsigned int height, + CoglTextureFlags flags, + CoglPixelFormat internal_format) +{ + CoglTexture2D *tex_2d; + GLenum gl_intformat; + GLenum gl_format; + GLenum gl_type; + + /* Since no data, we need some internal format */ + if (internal_format == COGL_PIXEL_FORMAT_ANY) + internal_format = COGL_PIXEL_FORMAT_RGBA_8888_PRE; + + if (!_cogl_texture_2d_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); + + tex_2d = _cogl_texture_2d_create_base (width, height, flags, internal_format); + + GE( glGenTextures (1, &tex_2d->gl_texture) ); + GE( glBindTexture (GL_TEXTURE_2D, tex_2d->gl_texture) ); + GE( glTexImage2D (GL_TEXTURE_2D, 0, gl_intformat, + width, height, 0, gl_format, gl_type, NULL) ); + + return _cogl_texture_2d_handle_new (tex_2d); +} + +CoglHandle +_cogl_texture_2d_new_from_bitmap (CoglHandle bmp_handle, + CoglTextureFlags flags, + CoglPixelFormat internal_format) +{ + CoglTexture2D *tex_2d; + CoglBitmap *bmp = (CoglBitmap *)bmp_handle; + CoglTextureUploadData upload_data; + + g_return_val_if_fail (bmp_handle != COGL_INVALID_HANDLE, COGL_INVALID_HANDLE); + + upload_data.bitmap = *bmp; + upload_data.bitmap_owner = FALSE; + + if (!_cogl_texture_upload_data_prepare_format (&upload_data, + &internal_format) || + !_cogl_texture_2d_can_create (upload_data.bitmap.width, + upload_data.bitmap.height, + internal_format) || + !_cogl_texture_upload_data_convert (&upload_data, internal_format)) + { + _cogl_texture_upload_data_free (&upload_data); + return COGL_INVALID_HANDLE; + } + + tex_2d = _cogl_texture_2d_create_base (upload_data.bitmap.width, + upload_data.bitmap.height, + flags, + upload_data.bitmap.format); + + GE( glGenTextures (1, &tex_2d->gl_texture) ); + _cogl_texture_driver_upload_to_gl (GL_TEXTURE_2D, + tex_2d->gl_texture, + &upload_data.bitmap, + upload_data.gl_intformat, + upload_data.gl_format, + upload_data.gl_type); + + tex_2d->gl_format = upload_data.gl_intformat; + + _cogl_texture_upload_data_free (&upload_data); + + return _cogl_texture_2d_handle_new (tex_2d); +} + +static gint +_cogl_texture_2d_get_max_waste (CoglTexture *tex) +{ + return -1; +} + +static gboolean +_cogl_texture_2d_is_sliced (CoglTexture *tex) +{ + return FALSE; +} + +static gboolean +_cogl_texture_2d_can_hardware_repeat (CoglTexture *tex) +{ + return TRUE; +} + +static void +_cogl_texture_2d_transform_coords_to_gl (CoglTexture *tex, + float *s, + float *t) +{ + /* The texture coordinates map directly so we don't need to do + anything */ +} + +static gboolean +_cogl_texture_2d_get_gl_texture (CoglTexture *tex, + GLuint *out_gl_handle, + GLenum *out_gl_target) +{ + CoglTexture2D *tex_2d = COGL_TEXTURE_2D (tex); + + if (out_gl_handle) + *out_gl_handle = tex_2d->gl_texture; + + if (out_gl_target) + *out_gl_target = GL_TEXTURE_2D; + + return TRUE; +} + +static void +_cogl_texture_2d_set_filters (CoglTexture *tex, + GLenum min_filter, + GLenum mag_filter) +{ + CoglTexture2D *tex_2d = COGL_TEXTURE_2D (tex); + + if (min_filter == tex_2d->min_filter + && mag_filter == tex_2d->mag_filter) + return; + + /* Store new values */ + tex_2d->min_filter = min_filter; + tex_2d->mag_filter = mag_filter; + + /* Apply new filters to the texture */ + GE( glBindTexture (GL_TEXTURE_2D, tex_2d->gl_texture) ); + GE( glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter) ); + GE( glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter) ); +} + +static void +_cogl_texture_2d_ensure_mipmaps (CoglTexture *tex) +{ + CoglTexture2D *tex_2d = COGL_TEXTURE_2D (tex); + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + /* Only update if the mipmaps are dirty */ + if (!tex_2d->auto_mipmap || !tex_2d->mipmaps_dirty) + return; + + GE( glBindTexture (GL_TEXTURE_2D, tex_2d->gl_texture) ); + /* glGenerateMipmap is defined in the FBO extension. We only allow + CoglTexture2D instances to be created if this feature is + available so we don't need to check for the extension */ + _cogl_texture_driver_gl_generate_mipmaps (GL_TEXTURE_2D); + + tex_2d->mipmaps_dirty = FALSE; +} + +static gboolean +_cogl_texture_2d_set_region (CoglTexture *tex, + int src_x, + int src_y, + int dst_x, + int dst_y, + unsigned int dst_width, + unsigned int dst_height, + int width, + int height, + CoglPixelFormat format, + unsigned int rowstride, + const guint8 *data) +{ + CoglTexture2D *tex_2d = COGL_TEXTURE_2D (tex); + gint bpp; + CoglBitmap source_bmp; + CoglBitmap temp_bmp; + gboolean source_bmp_owner = FALSE; + CoglPixelFormat closest_format; + GLenum closest_gl_format; + GLenum closest_gl_type; + gboolean success; + + /* Check for valid format */ + if (format == COGL_PIXEL_FORMAT_ANY) + return FALSE; + + /* Shortcut out early if the image is empty */ + if (width == 0 || height == 0) + return TRUE; + + /* Init source bitmap */ + source_bmp.width = width; + source_bmp.height = height; + source_bmp.format = format; + source_bmp.data = (guchar*) data; + + /* Rowstride from width if none specified */ + bpp = _cogl_get_format_bpp (format); + source_bmp.rowstride = (rowstride == 0) ? width * bpp : rowstride; + + /* Find closest format to internal that's supported by GL */ + closest_format = _cogl_pixel_format_to_gl (tex_2d->format, + NULL, /* don't need */ + &closest_gl_format, + &closest_gl_type); + + /* If no direct match, convert */ + if (closest_format != format) + { + /* Convert to required format */ + success = _cogl_bitmap_convert_and_premult (&source_bmp, + &temp_bmp, + closest_format); + + /* Swap bitmaps if succeeded */ + if (!success) return FALSE; + source_bmp = temp_bmp; + source_bmp_owner = TRUE; + } + + /* Send data to GL */ + _cogl_texture_driver_upload_subregion_to_gl (GL_TEXTURE_2D, + tex_2d->gl_texture, + src_x, src_y, + dst_x, dst_y, + dst_width, dst_height, + &source_bmp, + closest_gl_format, + closest_gl_type); + + /* Free data if owner */ + if (source_bmp_owner) + g_free (source_bmp.data); + + return TRUE; +} + +static int +_cogl_texture_2d_get_data (CoglTexture *tex, + CoglPixelFormat format, + unsigned int rowstride, + guint8 *data) +{ + CoglTexture2D *tex_2d = COGL_TEXTURE_2D (tex); + gint bpp; + gint byte_size; + CoglPixelFormat closest_format; + gint closest_bpp; + GLenum closest_gl_format; + GLenum closest_gl_type; + CoglBitmap target_bmp; + CoglBitmap new_bmp; + gboolean success; + guchar *src; + guchar *dst; + gint y; + + /* Default to internal format if none specified */ + if (format == COGL_PIXEL_FORMAT_ANY) + format = tex_2d->format; + + /* Rowstride from texture width if none specified */ + bpp = _cogl_get_format_bpp (format); + if (rowstride == 0) rowstride = tex_2d->width * bpp; + + /* Return byte size if only that requested */ + byte_size = tex_2d->height * rowstride; + if (data == NULL) return byte_size; + + closest_format = + _cogl_texture_driver_find_best_gl_get_data_format (format, + &closest_gl_format, + &closest_gl_type); + closest_bpp = _cogl_get_format_bpp (closest_format); + + target_bmp.width = tex_2d->width; + target_bmp.height = tex_2d->height; + + /* Is the requested format supported? */ + if (closest_format == format) + { + /* Target user data directly */ + target_bmp.format = format; + target_bmp.rowstride = rowstride; + target_bmp.data = data; + } + else + { + /* Target intermediate buffer */ + target_bmp.format = closest_format; + target_bmp.rowstride = target_bmp.width * closest_bpp; + target_bmp.data = (guchar*) g_malloc (target_bmp.height + * target_bmp.rowstride); + } + + GE( glBindTexture (GL_TEXTURE_2D, tex_2d->gl_texture) ); + if (!_cogl_texture_driver_gl_get_tex_image (GL_TEXTURE_2D, + closest_gl_format, + closest_gl_type, + target_bmp.data)) + { + /* XXX: In some cases _cogl_texture_2d_download_from_gl may + * fail to read back the texture data; such as for GLES which doesn't + * support glGetTexImage, so here we fallback to drawing the texture + * and reading the pixels from the framebuffer. */ + _cogl_texture_draw_and_read (tex, &target_bmp, + closest_gl_format, + closest_gl_type); + } + + /* Was intermediate used? */ + if (closest_format != format) + { + /* Convert to requested format */ + success = _cogl_bitmap_convert_and_premult (&target_bmp, + &new_bmp, + format); + + /* Free intermediate data and return if failed */ + g_free (target_bmp.data); + if (!success) return 0; + + /* Copy to user buffer */ + for (y = 0; y < new_bmp.height; ++y) + { + src = new_bmp.data + y * new_bmp.rowstride; + dst = data + y * rowstride; + memcpy (dst, src, new_bmp.width); + } + + /* Free converted data */ + g_free (new_bmp.data); + } + + return byte_size; +} + +static CoglPixelFormat +_cogl_texture_2d_get_format (CoglTexture *tex) +{ + return COGL_TEXTURE_2D (tex)->format; +} + +static GLenum +_cogl_texture_2d_get_gl_format (CoglTexture *tex) +{ + return COGL_TEXTURE_2D (tex)->gl_format; +} + +static gint +_cogl_texture_2d_get_width (CoglTexture *tex) +{ + return COGL_TEXTURE_2D (tex)->width; +} + +static gint +_cogl_texture_2d_get_height (CoglTexture *tex) +{ + return COGL_TEXTURE_2D (tex)->height; +} + +static const CoglTextureVtable +cogl_texture_2d_vtable = + { + _cogl_texture_2d_set_region, + _cogl_texture_2d_get_data, + _cogl_texture_2d_foreach_sub_texture_in_region, + _cogl_texture_2d_get_max_waste, + _cogl_texture_2d_is_sliced, + _cogl_texture_2d_can_hardware_repeat, + _cogl_texture_2d_transform_coords_to_gl, + _cogl_texture_2d_get_gl_texture, + _cogl_texture_2d_set_filters, + _cogl_texture_2d_ensure_mipmaps, + _cogl_texture_2d_set_wrap_mode_parameter, + _cogl_texture_2d_get_format, + _cogl_texture_2d_get_gl_format, + _cogl_texture_2d_get_width, + _cogl_texture_2d_get_height + }; diff --git a/cogl/cogl-texture-private.h b/cogl/cogl-texture-private.h index ee018faf4..ad6449d6d 100644 --- a/cogl/cogl-texture-private.h +++ b/cogl/cogl-texture-private.h @@ -162,6 +162,15 @@ void _cogl_texture_upload_data_swap_bitmap (CoglTextureUploadData *data, CoglBitmap *new_bitmap); +gboolean +_cogl_texture_upload_data_prepare_format + (CoglTextureUploadData *data, + CoglPixelFormat *internal_format); + +gboolean +_cogl_texture_upload_data_convert (CoglTextureUploadData *data, + CoglPixelFormat internal_format); + gboolean _cogl_texture_upload_data_prepare (CoglTextureUploadData *data, CoglPixelFormat internal_format); diff --git a/cogl/cogl-texture.c b/cogl/cogl-texture.c index 516b23002..5b94b1dbe 100644 --- a/cogl/cogl-texture.c +++ b/cogl/cogl-texture.c @@ -38,6 +38,7 @@ #include "cogl-texture-private.h" #include "cogl-texture-driver.h" #include "cogl-texture-2d-sliced-private.h" +#include "cogl-texture-2d-private.h" #include "cogl-sub-texture-private.h" #include "cogl-material.h" #include "cogl-context.h" @@ -63,7 +64,8 @@ cogl_is_texture (CoglHandle handle) if (handle == COGL_INVALID_HANDLE) return FALSE; - return (obj->klass->type == _cogl_handle_texture_2d_sliced_get_type () || + return (obj->klass->type == _cogl_handle_texture_2d_get_type () || + obj->klass->type == _cogl_handle_texture_2d_sliced_get_type () || obj->klass->type == _cogl_handle_sub_texture_get_type ()); } @@ -154,37 +156,44 @@ _cogl_texture_set_wrap_mode_parameter (CoglHandle handle, } gboolean -_cogl_texture_upload_data_prepare (CoglTextureUploadData *data, - CoglPixelFormat internal_format) +_cogl_texture_upload_data_prepare_format + (CoglTextureUploadData *data, + CoglPixelFormat *internal_format) { - CoglBitmap new_bitmap; - CoglPixelFormat new_data_format; - gboolean success; - /* Was there any internal conversion requested? * By default Cogl will use a premultiplied internal format. Later we will * add control over this. */ - if (internal_format == COGL_PIXEL_FORMAT_ANY) + if (*internal_format == COGL_PIXEL_FORMAT_ANY) { if ((data->bitmap.format & COGL_A_BIT) && data->bitmap.format != COGL_PIXEL_FORMAT_A_8) - internal_format = data->bitmap.format | COGL_PREMULT_BIT; + *internal_format = data->bitmap.format | COGL_PREMULT_BIT; else - internal_format = data->bitmap.format; + *internal_format = data->bitmap.format; } /* Find closest format accepted by GL */ - new_data_format = _cogl_pixel_format_to_gl (internal_format, - &data->gl_intformat, - &data->gl_format, - &data->gl_type); + *internal_format = _cogl_pixel_format_to_gl (*internal_format, + &data->gl_intformat, + &data->gl_format, + &data->gl_type); + + return TRUE; +} + +gboolean +_cogl_texture_upload_data_convert (CoglTextureUploadData *data, + CoglPixelFormat internal_format) +{ + CoglBitmap new_bitmap; + gboolean success; /* Convert to internal format */ - if (new_data_format != data->bitmap.format) + if (internal_format != data->bitmap.format) { success = _cogl_bitmap_convert_and_premult (&data->bitmap, &new_bitmap, - new_data_format); + internal_format); if (!success) return FALSE; @@ -304,10 +313,19 @@ cogl_texture_new_with_size (guint width, CoglTextureFlags flags, CoglPixelFormat internal_format) { - return _cogl_texture_2d_sliced_new_with_size (width, - height, - flags, - internal_format); + CoglHandle tex; + + /* First try creating a fast-path non-sliced texture */ + tex = _cogl_texture_2d_new_with_size (width, height, flags, internal_format); + + /* If it fails resort to sliced textures */ + if (tex == COGL_INVALID_HANDLE) + tex = _cogl_texture_2d_sliced_new_with_size (width, + height, + flags, + internal_format); + + return tex; } CoglHandle @@ -346,9 +364,20 @@ cogl_texture_new_from_bitmap (CoglHandle bmp_handle, CoglTextureFlags flags, CoglPixelFormat internal_format) { - return _cogl_texture_2d_sliced_new_from_bitmap (bmp_handle, - flags, - internal_format); + CoglHandle tex; + + /* First try creating a fast-path non-sliced texture */ + tex = _cogl_texture_2d_new_from_bitmap (bmp_handle, + flags, + internal_format); + + /* If it fails resort to sliced textures */ + if (tex == COGL_INVALID_HANDLE) + tex = _cogl_texture_2d_sliced_new_from_bitmap (bmp_handle, + flags, + internal_format); + + return tex; } CoglHandle