From d5634e37a262012f66022071d862ad9e5a8fbe53 Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Mon, 4 Oct 2010 14:34:24 +0100 Subject: [PATCH] cogl-texture-2d-sliced: Use the other backends for the slices Instead of directly manipulating GL textures itself, CoglTexture2DSliced now works in terms of CoglHandles. It creates the texture slices using cogl_texture_new_with_size which should always end up creating a CoglTexture2D because the size should fit. This allows us to avoid replicating some code such as the first pixel mipmap tracking and it better enforces the separation that each texture backend is the only place that contains code dealing with each texture target. --- .../cogl/cogl-texture-2d-sliced-private.h | 20 +- clutter/cogl/cogl/cogl-texture-2d-sliced.c | 1087 +++++++---------- 2 files changed, 454 insertions(+), 653 deletions(-) diff --git a/clutter/cogl/cogl/cogl-texture-2d-sliced-private.h b/clutter/cogl/cogl/cogl-texture-2d-sliced-private.h index 462c4055d..039f77e0b 100644 --- a/clutter/cogl/cogl/cogl-texture-2d-sliced-private.h +++ b/clutter/cogl/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/clutter/cogl/cogl/cogl-texture-2d-sliced.c b/clutter/cogl/cogl/cogl-texture-2d-sliced.c index f6fd3bf1a..4e8958871 100644 --- a/clutter/cogl/cogl/cogl-texture-2d-sliced.c +++ b/clutter/cogl/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