diff --git a/cogl/cogl-texture-2d-sliced-private.h b/cogl/cogl-texture-2d-sliced-private.h index 462c4055d..039f77e0b 100644 --- a/cogl/cogl-texture-2d-sliced-private.h +++ b/cogl/cogl-texture-2d-sliced-private.h @@ -38,29 +38,11 @@ struct _CoglTexture2DSliced CoglTexture _parent; GArray *slice_x_spans; GArray *slice_y_spans; - GArray *slice_gl_handles; + GArray *slice_textures; int max_waste; - /* 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; - GLenum gl_target; int width; int height; - GLenum min_filter; - GLenum mag_filter; - gboolean is_foreign; - GLenum wrap_mode_s; - GLenum wrap_mode_t; - gboolean auto_mipmap; - gboolean mipmaps_dirty; - - /* This holds a copy of the first pixel in each slice. It is only - used to force an automatic update of the mipmaps when - glGenerateMipmap is not available. */ - CoglTexturePixel *first_pixels; }; GQuark diff --git a/cogl/cogl-texture-2d-sliced.c b/cogl/cogl-texture-2d-sliced.c index f6fd3bf1a..4e8958871 100644 --- a/cogl/cogl-texture-2d-sliced.c +++ b/cogl/cogl-texture-2d-sliced.c @@ -3,7 +3,7 @@ * * An object oriented GL/GLES Abstraction/Utility Layer * - * Copyright (C) 2007,2008,2009 Intel Corporation. + * Copyright (C) 2007,2008,2009,2010 Intel Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -37,6 +37,7 @@ #include "cogl-bitmap.h" #include "cogl-bitmap-private.h" #include "cogl-texture-private.h" +#include "cogl-texture-2d-private.h" #include "cogl-texture-2d-sliced-private.h" #include "cogl-texture-driver.h" #include "cogl-context.h" @@ -55,6 +56,52 @@ COGL_TEXTURE_INTERNAL_DEFINE (Texture2DSliced, texture_2d_sliced); static const CoglTextureVtable cogl_texture_2d_sliced_vtable; +typedef struct +{ + CoglTexture2DSliced *tex; + float x_intersect_start; + float x_intersect_end; + float y_intersect_start; + float y_intersect_end; + + CoglTextureSliceCallback callback; + void *user_data; +} ForeachData; + +static void +_cogl_texture_2d_sliced_foreach_cb (CoglHandle handle, + GLuint gl_handle, + GLenum gl_target, + const float *slice_coords, + const float *virtual_coords_in, + void *user_data) +{ + float virtual_coords_out[4]; + ForeachData *data = user_data; + + /* Convert the virtual coordinates of the texture slice back to + coordinates in the space of the outer texture */ + virtual_coords_out[0] = (virtual_coords_in[0] * + (data->x_intersect_end - data->x_intersect_start) + + data->x_intersect_start) / data->tex->width; + virtual_coords_out[1] = (virtual_coords_in[1] * + (data->y_intersect_end - data->y_intersect_start) + + data->y_intersect_start) / data->tex->height; + virtual_coords_out[2] = (virtual_coords_in[2] * + (data->x_intersect_end - data->x_intersect_start) + + data->x_intersect_start) / data->tex->width; + virtual_coords_out[3] = (virtual_coords_in[3] * + (data->y_intersect_end - data->y_intersect_start) + + data->y_intersect_start) / data->tex->height; + + data->callback (data->tex, + gl_handle, + gl_target, + slice_coords, + virtual_coords_out, + data->user_data); +} + /* To differentiate between texture coordinates of a specific, real, slice * texture and the texture coordinates of the composite, sliced texture, the * coordinates of the sliced texture are called "virtual" coordinates and the @@ -78,6 +125,11 @@ _cogl_texture_2d_sliced_foreach_sub_texture_in_region ( float height = tex_2ds->height; CoglSpanIter iter_x; CoglSpanIter iter_y; + ForeachData data; + + data.tex = COGL_TEXTURE_2D_SLICED (tex); + data.callback = callback; + data.user_data = user_data; /* Slice spans are stored in denormalized coordinates, and this is what * the _cogl_span_iter_* funcs expect to be given, so we scale the given @@ -99,31 +151,29 @@ _cogl_texture_2d_sliced_foreach_sub_texture_in_region ( !_cogl_span_iter_end (&iter_y); _cogl_span_iter_next (&iter_y)) { - float y_intersect_start = iter_y.intersect_start; - float y_intersect_end = iter_y.intersect_end; float slice_ty1; float slice_ty2; + data.y_intersect_start = iter_y.intersect_start; + data.y_intersect_end = iter_y.intersect_end; + /* Discard slices out of rectangle early */ if (!iter_y.intersects) continue; if (iter_y.flipped) { - y_intersect_start = iter_y.intersect_end; - y_intersect_end = iter_y.intersect_start; + data.y_intersect_start = iter_y.intersect_end; + data.y_intersect_end = iter_y.intersect_start; } /* Localize slice texture coordinates */ - slice_ty1 = y_intersect_start - iter_y.pos; - slice_ty2 = y_intersect_end - iter_y.pos; + slice_ty1 = data.y_intersect_start - iter_y.pos; + slice_ty2 = data.y_intersect_end - iter_y.pos; - if (tex_2ds->gl_target == GL_TEXTURE_2D) - { - /* Normalize slice texture coordinates */ - slice_ty1 /= iter_y.span->size; - slice_ty2 /= iter_y.span->size; - } + /* Normalize slice texture coordinates */ + slice_ty1 /= iter_y.span->size; + slice_ty2 /= iter_y.span->size; /* Iterate the x axis of the virtual rectangle */ for (_cogl_span_iter_begin (&iter_x, @@ -134,13 +184,12 @@ _cogl_texture_2d_sliced_foreach_sub_texture_in_region ( !_cogl_span_iter_end (&iter_x); _cogl_span_iter_next (&iter_x)) { - float slice_coords[4]; - float virtual_coords[4]; - float x_intersect_start = iter_x.intersect_start; - float x_intersect_end = iter_x.intersect_end; float slice_tx1; float slice_tx2; - GLuint gl_handle; + CoglHandle slice_tex; + + data.x_intersect_start = iter_x.intersect_start; + data.x_intersect_end = iter_x.intersect_end; /* Discard slices out of rectangle early */ if (!iter_x.intersects) @@ -148,42 +197,28 @@ _cogl_texture_2d_sliced_foreach_sub_texture_in_region ( if (iter_x.flipped) { - x_intersect_start = iter_x.intersect_end; - x_intersect_end = iter_x.intersect_start; + data.x_intersect_start = iter_x.intersect_end; + data.x_intersect_end = iter_x.intersect_start; } /* Localize slice texture coordinates */ - slice_tx1 = x_intersect_start - iter_x.pos; - slice_tx2 = x_intersect_end - iter_x.pos; + slice_tx1 = data.x_intersect_start - iter_x.pos; + slice_tx2 = data.x_intersect_end - iter_x.pos; - /* Pluck out opengl texture object for this slice */ - gl_handle = g_array_index (tex_2ds->slice_gl_handles, GLuint, + /* Normalize slice texture coordinates */ + slice_tx1 /= iter_x.span->size; + slice_tx2 /= iter_x.span->size; + + /* Pluck out the cogl texture for this slice */ + slice_tex = g_array_index (tex_2ds->slice_textures, CoglHandle, iter_y.index * iter_x.array->len + iter_x.index); - if (tex_2ds->gl_target == GL_TEXTURE_2D) - { - /* Normalize slice texture coordinates */ - slice_tx1 /= iter_x.span->size; - slice_tx2 /= iter_x.span->size; - } - - slice_coords[0] = slice_tx1; - slice_coords[1] = slice_ty1; - slice_coords[2] = slice_tx2; - slice_coords[3] = slice_ty2; - - virtual_coords[0] = x_intersect_start / width; - virtual_coords[1] = y_intersect_start / height; - virtual_coords[2] = x_intersect_end / width; - virtual_coords[3] = y_intersect_end / height; - - callback (tex, - gl_handle, - tex_2ds->gl_target, - slice_coords, - virtual_coords, - user_data); + _cogl_texture_foreach_sub_texture_in_region + (slice_tex, + slice_tx1, slice_ty1, slice_tx2, slice_ty2, + _cogl_texture_2d_sliced_foreach_cb, + &data); } } } @@ -218,16 +253,161 @@ _cogl_texture_2d_sliced_allocate_waste_buffer (CoglTexture2DSliced *tex_2ds, return waste_buf; } +static void +_cogl_texture_2d_sliced_set_waste (CoglTexture2DSliced *tex_2ds, + CoglBitmap *source_bmp, + CoglHandle slice_tex, + guint8 *waste_buf, + CoglSpan *x_span, + CoglSpan *y_span, + CoglSpanIter *x_iter, + CoglSpanIter *y_iter, + int src_x, + int src_y, + int dst_x, + int dst_y) +{ + gboolean need_x, need_y; + + /* If the x_span is sliced and the upload touches the + rightmost pixels then fill the waste with copies of the + pixels */ + need_x = x_span->waste > 0 && + x_iter->intersect_end - x_iter->pos >= x_span->size - x_span->waste; + + /* same for the bottom-most pixels */ + need_y = y_span->waste > 0 && + y_iter->intersect_end - y_iter->pos >= y_span->size - y_span->waste; + + if (need_x || need_y) + { + int bmp_rowstride = _cogl_bitmap_get_rowstride (source_bmp); + CoglPixelFormat source_format = _cogl_bitmap_get_format (source_bmp); + int bpp = _cogl_get_format_bpp (source_format); + guint8 *bmp_data; + const guint8 *src; + guint8 *dst; + unsigned int wy, wx; + CoglBitmap *waste_bmp; + + bmp_data = _cogl_bitmap_map (source_bmp, COGL_BUFFER_ACCESS_READ, 0); + + if (bmp_data == NULL) + return; + + if (need_x) + { + src = (bmp_data + ((src_y + (int) y_iter->intersect_start - dst_y) * + bmp_rowstride) + + (src_x + x_span->start + x_span->size - + x_span->waste - dst_x - 1) * bpp); + + dst = waste_buf; + + for (wy = 0; + wy < y_iter->intersect_end - y_iter->intersect_start; + wy++) + { + for (wx = 0; wx < x_span->waste; wx++) + { + memcpy (dst, src, bpp); + dst += bpp; + } + src += bmp_rowstride; + } + + waste_bmp = + _cogl_bitmap_new_from_data (waste_buf, + source_format, + x_span->waste, + y_iter->intersect_end - + y_iter->intersect_start, + x_span->waste * bpp, + NULL, + NULL); + + _cogl_texture_set_region_from_bitmap (slice_tex, + 0, /* src_x */ + 0, /* src_y */ + /* dst_x */ + x_span->size - x_span->waste, + y_iter->intersect_start - + y_span->start, /* dst_y */ + x_span->waste, /* dst_width */ + /* dst_height */ + y_iter->intersect_end - + y_iter->intersect_start, + waste_bmp); + + cogl_object_unref (waste_bmp); + } + + if (need_y) + { + unsigned int copy_width, intersect_width; + + src = (bmp_data + ((src_x + (int) x_iter->intersect_start - dst_x) * + bpp) + + (src_y + y_span->start + y_span->size - y_span->waste + - dst_y - 1) * bmp_rowstride); + + dst = waste_buf; + + if (x_iter->intersect_end - x_iter->pos + >= x_span->size - x_span->waste) + copy_width = x_span->size + x_iter->pos - x_iter->intersect_start; + else + copy_width = x_iter->intersect_end - x_iter->intersect_start; + + intersect_width = x_iter->intersect_end - x_iter->intersect_start; + + for (wy = 0; wy < y_span->waste; wy++) + { + memcpy (dst, src, intersect_width * bpp); + dst += intersect_width * bpp; + + for (wx = intersect_width; wx < copy_width; wx++) + { + memcpy (dst, dst - bpp, bpp); + dst += bpp; + } + } + + waste_bmp = + _cogl_bitmap_new_from_data (waste_buf, + source_format, + copy_width, + y_span->waste, + copy_width * bpp, + NULL, + NULL); + + _cogl_texture_set_region_from_bitmap (slice_tex, + 0, /* src_x */ + 0, /* src_y */ + /* dst_x */ + x_iter->intersect_start - + x_iter->pos, + /* dst_y */ + y_span->size - y_span->waste, + copy_width, /* dst_width */ + y_span->waste, /* dst_height */ + waste_bmp); + + cogl_object_unref (waste_bmp); + } + + _cogl_bitmap_unmap (source_bmp); + } +} + static gboolean _cogl_texture_2d_sliced_upload_to_gl (CoglTexture2DSliced *tex_2ds, - CoglBitmap *bmp, - GLenum gl_intformat, - GLenum gl_format, - GLenum gl_type) + CoglBitmap *bmp) { CoglSpan *x_span; CoglSpan *y_span; - GLuint gl_handle; + CoglHandle slice_tex; int bpp; int x, y; guint8 *waste_buf; @@ -248,135 +428,54 @@ _cogl_texture_2d_sliced_upload_to_gl (CoglTexture2DSliced *tex_2ds, for (x = 0; x < tex_2ds->slice_x_spans->len; ++x) { int slice_num = y * tex_2ds->slice_x_spans->len + x; + CoglSpanIter x_iter, y_iter; x_span = &g_array_index (tex_2ds->slice_x_spans, CoglSpan, x); /* Pick the gl texture object handle */ - gl_handle = g_array_index (tex_2ds->slice_gl_handles, GLuint, slice_num); + slice_tex = g_array_index (tex_2ds->slice_textures, + CoglHandle, slice_num); - _cogl_texture_driver_upload_subregion_to_gl ( - tex_2ds->gl_target, - gl_handle, - tex_2ds->is_foreign, - x_span->start, /* src x */ - y_span->start, /* src y */ - 0, /* dst x */ - 0, /* dst y */ - x_span->size - x_span->waste, /* width */ - y_span->size - y_span->waste, /* height */ - bmp, - gl_format, - gl_type); + _cogl_texture_set_region_from_bitmap (slice_tex, + x_span->start, /* src x */ + y_span->start, /* src y */ + 0, /* dst x */ + 0, /* dst y */ + x_span->size - + x_span->waste, /* width */ + y_span->size - + y_span->waste, /* height */ + bmp); - /* Keep a copy of the first pixel if needed */ - if (tex_2ds->first_pixels) - { - guint8 *data; + /* Set up a fake iterator that covers the whole slice */ + x_iter.intersect_start = x_span->start; + x_iter.intersect_end = (x_span->start + + x_span->size - + x_span->waste); + x_iter.pos = x_span->start; - if ((data = _cogl_bitmap_map (bmp, COGL_BUFFER_ACCESS_READ, 0))) - { - memcpy (tex_2ds->first_pixels[slice_num].data, - data + x_span->start * bpp - + y_span->start * _cogl_bitmap_get_rowstride (bmp), - bpp); - _cogl_bitmap_unmap (bmp); - } + y_iter.intersect_start = y_span->start; + y_iter.intersect_end = (y_span->start + + y_span->size - + y_span->waste); + y_iter.pos = y_span->start; - tex_2ds->first_pixels[slice_num].gl_format = gl_format; - tex_2ds->first_pixels[slice_num].gl_type = gl_type; - } - - /* Fill the waste with a copies of the rightmost pixels */ - if (x_span->waste > 0) - { - int bmp_rowstride = _cogl_bitmap_get_rowstride (bmp); - guint8 *bmp_data = _cogl_bitmap_map (bmp, - COGL_BUFFER_ACCESS_READ, 0); - - if (bmp_data) - { - const guint8 *src = bmp_data - + y_span->start * bmp_rowstride - + (x_span->start + x_span->size - x_span->waste - 1) * bpp; - guint8 *dst = waste_buf; - unsigned int wx, wy; - - for (wy = 0; wy < y_span->size - y_span->waste; wy++) - { - for (wx = 0; wx < x_span->waste; wx++) - { - memcpy (dst, src, bpp); - dst += bpp; - } - src += bmp_rowstride; - } - - _cogl_bitmap_unmap (bmp); - - _cogl_texture_driver_prep_gl_for_pixels_upload ( - x_span->waste * bpp, - bpp); - - GE( glTexSubImage2D (tex_2ds->gl_target, 0, - x_span->size - x_span->waste, - 0, - x_span->waste, - y_span->size - y_span->waste, - gl_format, gl_type, - waste_buf) ); - } - } - - if (y_span->waste > 0) - { - int bmp_rowstride = _cogl_bitmap_get_rowstride (bmp); - guint8 *bmp_data = _cogl_bitmap_map (bmp, - COGL_BUFFER_ACCESS_READ, 0); - - if (bmp_data) - { - const guint8 *src = bmp_data - + ((y_span->start + y_span->size - y_span->waste - 1) - * bmp_rowstride) - + x_span->start * bpp; - guint8 *dst = waste_buf; - unsigned int wy, wx; - - for (wy = 0; wy < y_span->waste; wy++) - { - memcpy (dst, src, (x_span->size - x_span->waste) * bpp); - dst += (x_span->size - x_span->waste) * bpp; - - for (wx = 0; wx < x_span->waste; wx++) - { - memcpy (dst, dst - bpp, bpp); - dst += bpp; - } - } - - _cogl_bitmap_unmap (bmp); - - _cogl_texture_driver_prep_gl_for_pixels_upload ( - x_span->size * bpp, - bpp); - - GE( glTexSubImage2D (tex_2ds->gl_target, 0, - 0, - y_span->size - y_span->waste, - x_span->size, - y_span->waste, - gl_format, gl_type, - waste_buf) ); - } - } + _cogl_texture_2d_sliced_set_waste (tex_2ds, + bmp, + slice_tex, + waste_buf, + x_span, y_span, + &x_iter, &y_iter, + 0, /* src_x */ + 0, /* src_y */ + 0, /* dst_x */ + 0); /* dst_y */ } } if (waste_buf) g_free (waste_buf); - tex_2ds->mipmaps_dirty = TRUE; - return TRUE; } @@ -397,7 +496,7 @@ _cogl_texture_2d_sliced_upload_subregion_to_gl (CoglTexture2DSliced *tex_2ds, int bpp; CoglSpanIter x_iter; CoglSpanIter y_iter; - GLuint gl_handle; + CoglHandle slice_tex; int source_x = 0, source_y = 0; int inter_w = 0, inter_h = 0; int local_x = 0, local_y = 0; @@ -468,161 +567,31 @@ _cogl_texture_2d_sliced_upload_subregion_to_gl (CoglTexture2DSliced *tex_2ds, slice_num = y_iter.index * tex_2ds->slice_x_spans->len + x_iter.index; - /* Pick slice GL handle */ - gl_handle = g_array_index (tex_2ds->slice_gl_handles, GLuint, slice_num); + /* Pick slice texture */ + slice_tex = g_array_index (tex_2ds->slice_textures, + CoglHandle, slice_num); - _cogl_texture_driver_upload_subregion_to_gl (tex_2ds->gl_target, - gl_handle, - tex_2ds->is_foreign, - source_x, - source_y, - local_x, /* dst x */ - local_y, /* dst x */ - inter_w, /* width */ - inter_h, /* height */ - source_bmp, - source_gl_format, - source_gl_type); + _cogl_texture_set_region_from_bitmap (slice_tex, + source_x, + source_y, + local_x, /* dst x */ + local_y, /* dst y */ + inter_w, /* width */ + inter_h, /* height */ + source_bmp); - /* Keep a copy of the first pixel if needed */ - if (tex_2ds->first_pixels && local_x == 0 && local_y == 0) - { - guint8 *data; - - if ((data = _cogl_bitmap_map (source_bmp, - COGL_BUFFER_ACCESS_READ, 0))) - { - memcpy (tex_2ds->first_pixels[slice_num].data, - data + source_x * bpp - + source_y * _cogl_bitmap_get_rowstride (source_bmp), - bpp); - _cogl_bitmap_unmap (source_bmp); - } - - tex_2ds->first_pixels[slice_num].gl_format = source_gl_format; - tex_2ds->first_pixels[slice_num].gl_type = source_gl_type; - } - - /* If the x_span is sliced and the upload touches the - rightmost pixels then fill the waste with copies of the - pixels */ - if (x_span->waste > 0 - && local_x < x_span->size - x_span->waste - && local_x + inter_w >= x_span->size - x_span->waste) - { - int bmp_rowstride = _cogl_bitmap_get_rowstride (source_bmp); - guint8 *bmp_data = _cogl_bitmap_map (source_bmp, - COGL_BUFFER_ACCESS_READ, 0); - - if (bmp_data) - { - const guint8 *src; - guint8 *dst; - unsigned int wx, wy; - - src = bmp_data - + (src_y + ((int)y_iter.intersect_start) - - dst_y) - * bmp_rowstride - + (src_x + x_span->start + x_span->size - x_span->waste - - dst_x - 1) - * bpp; - - dst = waste_buf; - - for (wy = 0; wy < inter_h; wy++) - { - for (wx = 0; wx < x_span->waste; wx++) - { - memcpy (dst, src, bpp); - dst += bpp; - } - src += bmp_rowstride; - } - - _cogl_bitmap_unmap (source_bmp); - - _cogl_texture_driver_prep_gl_for_pixels_upload ( - x_span->waste * bpp, - bpp); - - GE( glTexSubImage2D (tex_2ds->gl_target, 0, - x_span->size - x_span->waste, - local_y, - x_span->waste, - inter_h, - source_gl_format, - source_gl_type, - waste_buf) ); - } - } - - /* same for the bottom-most pixels */ - if (y_span->waste > 0 - && local_y < y_span->size - y_span->waste - && local_y + inter_h >= y_span->size - y_span->waste) - { - int bmp_rowstride = _cogl_bitmap_get_rowstride (source_bmp); - guint8 *bmp_data = _cogl_bitmap_map (source_bmp, - COGL_BUFFER_ACCESS_READ, 0); - - if (bmp_data) - { - const guint8 *src; - guint8 *dst; - unsigned int wy, wx; - unsigned int copy_width; - - src = bmp_data - + (src_x + ((int)x_iter.intersect_start) - - dst_x) - * bpp - + (src_y + y_span->start + y_span->size - y_span->waste - - dst_y - 1) - * bmp_rowstride; - - dst = waste_buf; - - if (local_x + inter_w >= x_span->size - x_span->waste) - copy_width = x_span->size - local_x; - else - copy_width = inter_w; - - for (wy = 0; wy < y_span->waste; wy++) - { - memcpy (dst, src, inter_w * bpp); - dst += inter_w * bpp; - - for (wx = inter_w; wx < copy_width; wx++) - { - memcpy (dst, dst - bpp, bpp); - dst += bpp; - } - } - - _cogl_bitmap_unmap (source_bmp); - - _cogl_texture_driver_prep_gl_for_pixels_upload ( - copy_width * bpp, - bpp); - - GE( glTexSubImage2D (tex_2ds->gl_target, 0, - local_x, - y_span->size - y_span->waste, - copy_width, - y_span->waste, - source_gl_format, - source_gl_type, - waste_buf) ); - } - } + _cogl_texture_2d_sliced_set_waste (tex_2ds, + source_bmp, + slice_tex, + waste_buf, + x_span, y_span, + &x_iter, &y_iter, + src_x, src_y, + dst_x, dst_y); } } - if (waste_buf) - g_free (waste_buf); - - tex_2ds->mipmaps_dirty = TRUE; + g_free (waste_buf); return TRUE; } @@ -730,50 +699,39 @@ _cogl_texture_2d_sliced_set_wrap_mode_parameters (CoglTexture *tex, GLenum wrap_mode_p) { CoglTexture2DSliced *tex_2ds = COGL_TEXTURE_2D_SLICED (tex); + int i; - /* Only set the wrap mode if it's different from the current value - to avoid too many GL calls. Texture 2D doesn't make use of the r - coordinate so we can ignore its wrap mode */ - if (tex_2ds->wrap_mode_s != wrap_mode_s || - tex_2ds->wrap_mode_t != wrap_mode_t) + /* Pass the set wrap mode on to all of the child textures */ + for (i = 0; i < tex_2ds->slice_textures->len; i++) { - int i; + CoglHandle slice_tex = g_array_index (tex_2ds->slice_textures, + CoglHandle, + i); - for (i = 0; i < tex_2ds->slice_gl_handles->len; i++) - { - GLuint texnum = g_array_index (tex_2ds->slice_gl_handles, GLuint, i); - - _cogl_bind_gl_texture_transient (tex_2ds->gl_target, - texnum, - tex_2ds->is_foreign); - GE( glTexParameteri (tex_2ds->gl_target, - GL_TEXTURE_WRAP_S, wrap_mode_s) ); - GE( glTexParameteri (tex_2ds->gl_target, - GL_TEXTURE_WRAP_T, wrap_mode_t) ); - } - - tex_2ds->wrap_mode_s = wrap_mode_s; - tex_2ds->wrap_mode_t = wrap_mode_t; + _cogl_texture_set_wrap_mode_parameters (slice_tex, + wrap_mode_s, + wrap_mode_t, + wrap_mode_p); } } static gboolean _cogl_texture_2d_sliced_slices_create (CoglTexture2DSliced *tex_2ds, int width, int height, - GLenum gl_intformat, - GLenum gl_format, - GLenum gl_type) + CoglPixelFormat format, + CoglTextureFlags flags) { - int max_width; - int max_height; - GLuint *gl_handles; - int n_x_slices; - int n_y_slices; - int n_slices; - int x, y; - CoglSpan *x_span; - CoglSpan *y_span; - const GLfloat transparent_color[4] = { 0x00, 0x00, 0x00, 0x00 }; + int max_width; + int max_height; + CoglHandle *slice_textures; + int n_x_slices; + int n_y_slices; + int n_slices; + int x, y; + CoglSpan *x_span; + CoglSpan *y_span; + GLenum gl_intformat; + GLenum gl_type; int (*slices_for_size) (int, int, int, GArray*); @@ -782,24 +740,24 @@ _cogl_texture_2d_sliced_slices_create (CoglTexture2DSliced *tex_2ds, { max_width = width; max_height = height; - tex_2ds->gl_target = GL_TEXTURE_2D; slices_for_size = _cogl_rect_slices_for_size; } else { max_width = _cogl_util_next_p2 (width); max_height = _cogl_util_next_p2 (height); - tex_2ds->gl_target = GL_TEXTURE_2D; slices_for_size = _cogl_pot_slices_for_size; } + _cogl_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) { CoglSpan span; /* Check if size supported else bail out */ - if (!_cogl_texture_driver_size_supported (tex_2ds->gl_target, + if (!_cogl_texture_driver_size_supported (GL_TEXTURE_2D, gl_intformat, gl_type, max_width, @@ -833,7 +791,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 (tex_2ds->gl_target, + while (!_cogl_texture_driver_size_supported (GL_TEXTURE_2D, gl_intformat, gl_type, max_width, @@ -880,30 +838,16 @@ _cogl_texture_2d_sliced_slices_create (CoglTexture2DSliced *tex_2ds, /* Init and resize GL handle array */ n_slices = n_x_slices * n_y_slices; - tex_2ds->slice_gl_handles = g_array_sized_new (FALSE, FALSE, - sizeof (GLuint), - n_slices); + tex_2ds->slice_textures = g_array_sized_new (FALSE, FALSE, + sizeof (CoglHandle), + n_slices); - g_array_set_size (tex_2ds->slice_gl_handles, n_slices); - - /* Allocate some space to store a copy of the first pixel of each - slice. This is only needed if glGenerateMipmap (which is part of - the FBO extension) is not available */ - if (cogl_features_available (COGL_FEATURE_OFFSCREEN)) - tex_2ds->first_pixels = NULL; - else - tex_2ds->first_pixels = g_new (CoglTexturePixel, n_slices); - - /* Wrap mode not yet set */ - tex_2ds->wrap_mode_s = GL_FALSE; - tex_2ds->wrap_mode_t = GL_FALSE; + g_array_set_size (tex_2ds->slice_textures, n_slices); /* Generate a "working set" of GL texture objects * (some implementations might supported faster * re-binding between textures inside a set) */ - gl_handles = (GLuint*) tex_2ds->slice_gl_handles->data; - - _cogl_texture_driver_gen (GL_TEXTURE_2D, n_slices, gl_handles); + slice_textures = (CoglHandle *) tex_2ds->slice_textures->data; /* Init each GL texture object */ for (y = 0; y < n_y_slices; ++y) @@ -919,18 +863,10 @@ _cogl_texture_2d_sliced_slices_create (CoglTexture2DSliced *tex_2ds, x_span->size - x_span->waste, y_span->size - y_span->waste); - /* Setup texture parameters */ - _cogl_bind_gl_texture_transient (tex_2ds->gl_target, - gl_handles[y * n_x_slices + x], - FALSE); - - _cogl_texture_driver_try_setting_gl_border_color (tex_2ds->gl_target, - transparent_color); - - /* Pass NULL data to init size and internal format */ - GE( glTexImage2D (tex_2ds->gl_target, 0, gl_intformat, - x_span->size, y_span->size, 0, - gl_format, gl_type, NULL) ); + slice_textures[y * n_x_slices + x] = + cogl_texture_new_with_size (x_span->size, y_span->size, + COGL_TEXTURE_NO_ATLAS | flags, + format); } } @@ -946,22 +882,19 @@ _cogl_texture_2d_sliced_slices_free (CoglTexture2DSliced *tex_2ds) if (tex_2ds->slice_y_spans != NULL) g_array_free (tex_2ds->slice_y_spans, TRUE); - if (tex_2ds->slice_gl_handles != NULL) + if (tex_2ds->slice_textures != NULL) { int i; - if (tex_2ds->is_foreign == FALSE) - for (i = 0; i < tex_2ds->slice_gl_handles->len; i++) - { - GLuint texture = - g_array_index (tex_2ds->slice_gl_handles, GLuint, i); - _cogl_delete_gl_texture (texture); - } - g_array_free (tex_2ds->slice_gl_handles, TRUE); + for (i = 0; i < tex_2ds->slice_textures->len; i++) + { + CoglHandle slice_tex = + g_array_index (tex_2ds->slice_textures, CoglHandle, i); + cogl_handle_unref (slice_tex); + } + + g_array_free (tex_2ds->slice_textures, TRUE); } - - if (tex_2ds->first_pixels != NULL) - g_free (tex_2ds->first_pixels); } static void @@ -977,41 +910,27 @@ static gboolean _cogl_texture_2d_sliced_init_base (CoglTexture2DSliced *tex_2ds, int width, int height, - GLenum gl_intformat, - GLenum gl_format, - GLenum gl_type, - CoglPixelFormat internal_format) + CoglPixelFormat internal_format, + CoglTextureFlags flags) { CoglTexture *tex = COGL_TEXTURE (tex_2ds); tex->vtable = &cogl_texture_2d_sliced_vtable; - tex_2ds->is_foreign = FALSE; - tex_2ds->auto_mipmap = FALSE; - tex_2ds->mipmaps_dirty = TRUE; - tex_2ds->first_pixels = NULL; - tex_2ds->slice_x_spans = NULL; tex_2ds->slice_y_spans = NULL; - tex_2ds->slice_gl_handles = NULL; - - /* We default to GL_LINEAR for both filters */ - tex_2ds->min_filter = GL_LINEAR; - tex_2ds->mag_filter = GL_LINEAR; + tex_2ds->slice_textures = NULL; /* Create slices for the given format and size */ if (!_cogl_texture_2d_sliced_slices_create (tex_2ds, width, height, - gl_intformat, - gl_format, - gl_type)) + internal_format, + flags)) return FALSE; - tex_2ds->gl_format = gl_intformat; tex_2ds->width = width; tex_2ds->height = height; - tex_2ds->format = internal_format; return TRUE; } @@ -1023,9 +942,6 @@ _cogl_texture_2d_sliced_new_with_size (unsigned int width, CoglPixelFormat internal_format) { CoglTexture2DSliced *tex_2ds; - GLenum gl_intformat; - GLenum gl_format; - GLenum gl_type; /* Since no data, we need some internal format */ if (internal_format == COGL_PIXEL_FORMAT_ANY) @@ -1039,25 +955,15 @@ _cogl_texture_2d_sliced_new_with_size (unsigned int width, else tex_2ds->max_waste = COGL_TEXTURE_MAX_WASTE; - /* Find closest GL format match */ - internal_format = _cogl_pixel_format_to_gl (internal_format, - &gl_intformat, - &gl_format, - &gl_type); - if (!_cogl_texture_2d_sliced_init_base (tex_2ds, width, height, - gl_intformat, - gl_format, - gl_type, - internal_format)) + internal_format, + flags)) { _cogl_texture_2d_sliced_free (tex_2ds); return COGL_INVALID_HANDLE; } - tex_2ds->auto_mipmap = (flags & COGL_TEXTURE_NO_AUTO_MIPMAP) == 0; - return _cogl_texture_2d_sliced_handle_new (tex_2ds); } @@ -1108,23 +1014,16 @@ _cogl_texture_2d_sliced_new_from_bitmap (CoglBitmap *bmp, if (!_cogl_texture_2d_sliced_init_base (tex_2ds, width, height, - gl_intformat, - gl_format, - gl_type, - internal_format)) + internal_format, + flags)) goto error; if (!_cogl_texture_2d_sliced_upload_to_gl (tex_2ds, - dst_bmp, - gl_intformat, - gl_format, - gl_type)) + dst_bmp)) goto error; cogl_object_unref (dst_bmp); - tex_2ds->auto_mipmap = (flags & COGL_TEXTURE_NO_AUTO_MIPMAP) == 0; - return _cogl_texture_2d_sliced_handle_new (tex_2ds); error: @@ -1146,88 +1045,39 @@ _cogl_texture_2d_sliced_new_from_foreign (GLuint gl_handle, * in GLES, hence such a function prototype. */ - GLenum gl_error = 0; - GLboolean gl_istexture; - GLint gl_compressed = GL_FALSE; - GLint gl_int_format = 0; GLint gl_width = 0; GLint gl_height = 0; - GLint gl_gen_mipmap; CoglTexture2DSliced *tex_2ds; CoglTexture *tex; CoglSpan x_span; CoglSpan y_span; + CoglHandle tex_2d; - if (!_cogl_texture_driver_allows_foreign_gl_target (gl_target)) - return COGL_INVALID_HANDLE; + /* This should only be called when the texture target is 2D. If a + rectangle texture is used then _cogl_texture_new_from_foreign + will create a cogl_texture_rectangle instead */ + g_assert (gl_target == GL_TEXTURE_2D); -#if HAVE_COGL_GL - /* It shouldn't be necissary to have waste in this case since - * the texture isn't limited to power of two sizes. */ - if (gl_target == GL_TEXTURE_RECTANGLE_ARB && - (x_pot_waste != 0 || y_pot_waste != 0)) - { - g_warning ("You can't create a foreign GL_TEXTURE_RECTANGLE cogl " - "texture with waste\n"); - return COGL_INVALID_HANDLE; - } -#endif - - /* Make sure it is a valid GL texture object */ - gl_istexture = glIsTexture (gl_handle); - if (gl_istexture == GL_FALSE) - return COGL_INVALID_HANDLE; - - /* Make sure binding succeeds */ - while ((gl_error = glGetError ()) != GL_NO_ERROR) - ; - - _cogl_bind_gl_texture_transient (gl_target, gl_handle, TRUE); - if (glGetError () != GL_NO_ERROR) - return COGL_INVALID_HANDLE; - - /* Obtain texture parameters - (only level 0 we are interested in) */ - -#if HAVE_COGL_GL - GE( glGetTexLevelParameteriv (gl_target, 0, - GL_TEXTURE_COMPRESSED, - &gl_compressed) ); - - GE( glGetTexLevelParameteriv (gl_target, 0, - GL_TEXTURE_INTERNAL_FORMAT, - &gl_int_format) ); -#endif - - /* Note: We always trust the given width and height without querying - * the texture object because the user may be creating a Cogl - * texture for a texture_from_pixmap object where glTexImage2D may - * not have been called and the texture_from_pixmap spec doesn't - * clarify that it is reliable to query back the size from OpenGL. - */ gl_width = width + x_pot_waste; gl_height = height + y_pot_waste; - GE( glGetTexParameteriv (gl_target, - GL_GENERATE_MIPMAP, - &gl_gen_mipmap) ); - - /* Validate width and height */ - if (gl_width <= 0 || gl_height <= 0) - return COGL_INVALID_HANDLE; - /* Validate pot waste */ - if (x_pot_waste < 0 || x_pot_waste >= gl_width || - y_pot_waste < 0 || y_pot_waste >= gl_height) + if (x_pot_waste < 0 || x_pot_waste >= width || + y_pot_waste < 0 || y_pot_waste >= height) return COGL_INVALID_HANDLE; - /* Compressed texture images not supported */ - if (gl_compressed == GL_TRUE) + tex_2d = _cogl_texture_2d_new_from_foreign (gl_target, + gl_width, + gl_height, + format); + + if (!tex_2d) return COGL_INVALID_HANDLE; - /* Try and match to a cogl format */ - if (!_cogl_pixel_format_from_gl_internal (gl_int_format, &format)) - return COGL_INVALID_HANDLE; + /* The texture 2d backend may use a different pixel format if it + queries the actual texture so we'll refetch the format it + actually used */ + format = cogl_texture_get_format (tex_2d); /* Create new texture */ tex_2ds = g_new0 (CoglTexture2DSliced, 1); @@ -1235,27 +1085,10 @@ _cogl_texture_2d_sliced_new_from_foreign (GLuint gl_handle, tex = COGL_TEXTURE (tex_2ds); tex->vtable = &cogl_texture_2d_sliced_vtable; - /* Setup bitmap info */ - tex_2ds->is_foreign = TRUE; - tex_2ds->auto_mipmap = (gl_gen_mipmap == GL_TRUE) ? TRUE : FALSE; - tex_2ds->mipmaps_dirty = TRUE; - tex_2ds->first_pixels = NULL; - - tex_2ds->format = format; tex_2ds->width = gl_width - x_pot_waste; tex_2ds->height = gl_height - y_pot_waste; - tex_2ds->gl_target = gl_target; - tex_2ds->gl_format = gl_int_format; - - /* Unknown filter */ - tex_2ds->min_filter = GL_FALSE; - tex_2ds->mag_filter = GL_FALSE; tex_2ds->max_waste = 0; - /* Wrap mode not yet set */ - tex_2ds->wrap_mode_s = GL_FALSE; - tex_2ds->wrap_mode_t = GL_FALSE; - /* Create slice arrays */ tex_2ds->slice_x_spans = g_array_sized_new (FALSE, FALSE, @@ -1265,9 +1098,9 @@ _cogl_texture_2d_sliced_new_from_foreign (GLuint gl_handle, g_array_sized_new (FALSE, FALSE, sizeof (CoglSpan), 1); - tex_2ds->slice_gl_handles = + tex_2ds->slice_textures = g_array_sized_new (FALSE, FALSE, - sizeof (GLuint), 1); + sizeof (CoglHandle), 1); /* Store info for a single slice */ x_span.start = 0; @@ -1280,9 +1113,7 @@ _cogl_texture_2d_sliced_new_from_foreign (GLuint gl_handle, y_span.waste = y_pot_waste; g_array_append_val (tex_2ds->slice_y_spans, y_span); - g_array_append_val (tex_2ds->slice_gl_handles, gl_handle); - - tex_2ds->first_pixels = NULL; + g_array_append_val (tex_2ds->slice_textures, tex_2d); return _cogl_texture_2d_sliced_handle_new (tex_2ds); } @@ -1290,7 +1121,16 @@ _cogl_texture_2d_sliced_new_from_foreign (GLuint gl_handle, static gboolean _cogl_texture_2d_sliced_is_foreign (CoglTexture *tex) { - return COGL_TEXTURE_2D_SLICED (tex)->is_foreign; + CoglTexture2DSliced *tex_2ds = COGL_TEXTURE_2D_SLICED (tex); + CoglHandle slice_tex; + + /* Make sure slices were created */ + if (tex_2ds->slice_textures == NULL) + return FALSE; + + /* Pass the call on to the first slice */ + slice_tex = g_array_index (tex_2ds->slice_textures, CoglHandle, 0); + return _cogl_texture_is_foreign (slice_tex); } static int @@ -1306,10 +1146,10 @@ _cogl_texture_2d_sliced_is_sliced (CoglTexture *tex) { CoglTexture2DSliced *tex_2ds = COGL_TEXTURE_2D_SLICED (tex); - if (tex_2ds->slice_gl_handles == NULL) + if (tex_2ds->slice_textures == NULL) return FALSE; - if (tex_2ds->slice_gl_handles->len <= 1) + if (tex_2ds->slice_textures->len <= 1) return FALSE; return TRUE; @@ -1319,19 +1159,23 @@ static gboolean _cogl_texture_2d_sliced_can_hardware_repeat (CoglTexture *tex) { CoglTexture2DSliced *tex_2ds = COGL_TEXTURE_2D_SLICED (tex); + CoglHandle slice_tex; CoglSpan *x_span; CoglSpan *y_span; + /* If there's more than one texture then we can't hardware repeat */ + if (tex_2ds->slice_textures->len != 1) + return FALSE; + + /* If there's any waste then we can't hardware repeat */ x_span = &g_array_index (tex_2ds->slice_x_spans, CoglSpan, 0); y_span = &g_array_index (tex_2ds->slice_y_spans, CoglSpan, 0); - -#if HAVE_COGL_GL - /* TODO: COGL_TEXTURE_TYPE_2D_RECTANGLE */ - if (tex_2ds->gl_target == GL_TEXTURE_RECTANGLE_ARB) + if (x_span->waste > 0 || y_span->waste > 0) return FALSE; -#endif - return (x_span->waste || y_span->waste) ? FALSE : TRUE; + /* Otherwise pass the query on to the single slice texture */ + slice_tex = g_array_index (tex_2ds->slice_textures, CoglHandle, 0); + return _cogl_texture_can_hardware_repeat (slice_tex); } static void @@ -1342,6 +1186,7 @@ _cogl_texture_2d_sliced_transform_coords_to_gl (CoglTexture *tex, CoglTexture2DSliced *tex_2ds = COGL_TEXTURE_2D_SLICED (tex); CoglSpan *x_span; CoglSpan *y_span; + CoglHandle slice_tex; g_assert (!_cogl_texture_2d_sliced_is_sliced (tex)); @@ -1352,14 +1197,9 @@ _cogl_texture_2d_sliced_transform_coords_to_gl (CoglTexture *tex, *s *= tex_2ds->width / (float)x_span->size; *t *= tex_2ds->height / (float)y_span->size; -#if HAVE_COGL_GL - /* Denormalize texture coordinates for rectangle textures */ - if (tex_2ds->gl_target == GL_TEXTURE_RECTANGLE_ARB) - { - *s *= x_span->size; - *t *= y_span->size; - } -#endif + /* Let the child texture further transform the coords */ + slice_tex = g_array_index (tex_2ds->slice_textures, CoglHandle, 0); + _cogl_texture_transform_coords_to_gl (slice_tex, s, t); } static CoglTransformResult @@ -1397,20 +1237,17 @@ _cogl_texture_2d_sliced_get_gl_texture (CoglTexture *tex, GLenum *out_gl_target) { CoglTexture2DSliced *tex_2ds = COGL_TEXTURE_2D_SLICED (tex); + CoglHandle slice_tex; - if (tex_2ds->slice_gl_handles == NULL) + if (tex_2ds->slice_textures == NULL) return FALSE; - if (tex_2ds->slice_gl_handles->len < 1) + if (tex_2ds->slice_textures->len < 1) return FALSE; - if (out_gl_handle != NULL) - *out_gl_handle = g_array_index (tex_2ds->slice_gl_handles, GLuint, 0); + slice_tex = g_array_index (tex_2ds->slice_textures, CoglHandle, 0); - if (out_gl_target != NULL) - *out_gl_target = tex_2ds->gl_target; - - return TRUE; + return cogl_texture_get_gl_texture (slice_tex, out_gl_handle, out_gl_target); } static void @@ -1419,32 +1256,20 @@ _cogl_texture_2d_sliced_set_filters (CoglTexture *tex, GLenum mag_filter) { CoglTexture2DSliced *tex_2ds = COGL_TEXTURE_2D_SLICED (tex); - GLuint gl_handle; + CoglHandle slice_tex; int i; /* Make sure slices were created */ - if (tex_2ds->slice_gl_handles == NULL) + if (tex_2ds->slice_textures == NULL) return; - if (min_filter == tex_2ds->min_filter - && mag_filter == tex_2ds->mag_filter) - return; - - /* Store new values */ - tex_2ds->min_filter = min_filter; - tex_2ds->mag_filter = mag_filter; - - /* Apply new filters to every slice */ - for (i=0; islice_gl_handles->len; ++i) + /* Apply new filters to every slice. The slice texture itself should + cache the value and avoid resubmitting the same filter value to + GL */ + for (i = 0; i < tex_2ds->slice_textures->len; i++) { - gl_handle = g_array_index (tex_2ds->slice_gl_handles, GLuint, i); - _cogl_bind_gl_texture_transient (tex_2ds->gl_target, - gl_handle, - tex_2ds->is_foreign); - GE( glTexParameteri (tex_2ds->gl_target, GL_TEXTURE_MAG_FILTER, - tex_2ds->mag_filter) ); - GE( glTexParameteri (tex_2ds->gl_target, GL_TEXTURE_MIN_FILTER, - tex_2ds->min_filter) ); + slice_tex = g_array_index (tex_2ds->slice_textures, CoglHandle, i); + _cogl_texture_set_filters (slice_tex, min_filter, mag_filter); } } @@ -1455,51 +1280,36 @@ _cogl_texture_2d_sliced_pre_paint (CoglTexture *tex, CoglTexture2DSliced *tex_2ds = COGL_TEXTURE_2D_SLICED (tex); int i; - _COGL_GET_CONTEXT (ctx, NO_RETVAL); - - /* We only care about the mipmap flag */ - if ((flags & COGL_TEXTURE_NEEDS_MIPMAP) == 0) - return; - - /* Only update if the mipmaps are dirty */ - if (!tex_2ds->auto_mipmap || !tex_2ds->mipmaps_dirty) - return; - /* Make sure slices were created */ - if (tex_2ds->slice_gl_handles == NULL) + if (tex_2ds->slice_textures == NULL) return; - /* Regenerate the mipmaps on every slice */ - for (i = 0; i < tex_2ds->slice_gl_handles->len; i++) + /* Pass the pre-paint on to every slice */ + for (i = 0; i < tex_2ds->slice_textures->len; i++) { - GLuint gl_handle = g_array_index (tex_2ds->slice_gl_handles, GLuint, i); - _cogl_bind_gl_texture_transient (tex_2ds->gl_target, - gl_handle, - tex_2ds->is_foreign); - - /* glGenerateMipmap is defined in the FBO extension */ - if (cogl_features_available (COGL_FEATURE_OFFSCREEN)) - _cogl_texture_driver_gl_generate_mipmaps (tex_2ds->gl_target); - else if (tex_2ds->first_pixels) - { - CoglTexturePixel *pixel = tex_2ds->first_pixels + i; - /* Temporarily enable automatic mipmap generation and - re-upload the first pixel to cause a regeneration */ - GE( glTexParameteri (tex_2ds->gl_target, GL_GENERATE_MIPMAP, GL_TRUE) ); - GE( glTexSubImage2D (tex_2ds->gl_target, 0, 0, 0, 1, 1, - pixel->gl_format, pixel->gl_type, - pixel->data) ); - GE( glTexParameteri (tex_2ds->gl_target, GL_GENERATE_MIPMAP, GL_FALSE) ); - } + CoglHandle slice_tex = g_array_index (tex_2ds->slice_textures, + CoglHandle, i); + _cogl_texture_pre_paint (slice_tex, flags); } - - tex_2ds->mipmaps_dirty = FALSE; } static void _cogl_texture_2d_sliced_ensure_non_quad_rendering (CoglTexture *tex) { - /* Nothing needs to be done */ + CoglTexture2DSliced *tex_2ds = COGL_TEXTURE_2D_SLICED (tex); + int i; + + /* Make sure slices were created */ + if (tex_2ds->slice_textures == NULL) + return; + + /* Pass the call on to every slice */ + for (i = 0; i < tex_2ds->slice_textures->len; i++) + { + CoglHandle slice_tex = g_array_index (tex_2ds->slice_textures, + CoglHandle, i); + _cogl_texture_ensure_non_quad_rendering (slice_tex); + } } static gboolean @@ -1542,7 +1352,7 @@ _cogl_texture_2d_sliced_download_from_gl ( { CoglSpan *x_span; CoglSpan *y_span; - GLuint gl_handle; + CoglHandle slice_tex; int bpp; int x, y; CoglBitmap *slice_bmp; @@ -1561,9 +1371,9 @@ _cogl_texture_2d_sliced_download_from_gl ( /*if (x != 0 || y != 1) continue;*/ x_span = &g_array_index (tex_2ds->slice_x_spans, CoglSpan, x); - /* Pick the gl texture object handle */ - gl_handle = g_array_index (tex_2ds->slice_gl_handles, GLuint, - y * tex_2ds->slice_x_spans->len + x); + /* Pick the sliced texture */ + slice_tex = g_array_index (tex_2ds->slice_textures, CoglHandle, + y * tex_2ds->slice_x_spans->len + x); /* If there's any waste we need to copy manually (no glGetTexSubImage) */ @@ -1586,15 +1396,10 @@ _cogl_texture_2d_sliced_download_from_gl ( /* Setup gl alignment to 0,0 top-left corner */ _cogl_texture_driver_prep_gl_for_pixels_download (rowstride, bpp); - /* Download slice image data into temp bmp */ - _cogl_bind_gl_texture_transient (tex_2ds->gl_target, - gl_handle, - tex_2ds->is_foreign); - - if (!_cogl_texture_driver_gl_get_tex_image (tex_2ds->gl_target, - target_gl_format, - target_gl_type, - data)) + if (!cogl_texture_get_data (slice_tex, + target_format, + rowstride, + data)) { /* Free temp bitmap */ cogl_object_unref (slice_bmp); @@ -1630,14 +1435,10 @@ _cogl_texture_2d_sliced_download_from_gl ( _cogl_texture_driver_prep_gl_for_pixels_download (rowstride, bpp); /* Download slice image data */ - _cogl_bind_gl_texture_transient (tex_2ds->gl_target, - gl_handle, - tex_2ds->is_foreign); - - ret = _cogl_texture_driver_gl_get_tex_image (tex_2ds->gl_target, - target_gl_format, - target_gl_type, - dst); + ret = cogl_texture_get_data (slice_tex, + target_format, + rowstride, + dst); _cogl_bitmap_unmap (target_bmp); @@ -1692,13 +1493,31 @@ _cogl_texture_2d_sliced_get_data (CoglTexture *tex, static CoglPixelFormat _cogl_texture_2d_sliced_get_format (CoglTexture *tex) { - return COGL_TEXTURE_2D_SLICED (tex)->format; + CoglTexture2DSliced *tex_2ds = COGL_TEXTURE_2D_SLICED (tex); + CoglHandle slice_tex; + + /* Make sure slices were created */ + if (tex_2ds->slice_textures == NULL) + return 0; + + /* Pass the call on to the first slice */ + slice_tex = g_array_index (tex_2ds->slice_textures, CoglHandle, 0); + return cogl_texture_get_format (slice_tex); } static GLenum _cogl_texture_2d_sliced_get_gl_format (CoglTexture *tex) { - return COGL_TEXTURE_2D_SLICED (tex)->gl_format; + CoglTexture2DSliced *tex_2ds = COGL_TEXTURE_2D_SLICED (tex); + CoglHandle slice_tex; + + /* Make sure slices were created */ + if (tex_2ds->slice_textures == NULL) + return 0; + + /* Pass the call on to the first slice */ + slice_tex = g_array_index (tex_2ds->slice_textures, CoglHandle, 0); + return _cogl_texture_get_gl_format (slice_tex); } static int