diff --git a/cogl/Makefile.am b/cogl/Makefile.am index c3b19c424..02ab16601 100644 --- a/cogl/Makefile.am +++ b/cogl/Makefile.am @@ -122,9 +122,11 @@ libclutter_cogl_la_SOURCES = \ $(srcdir)/cogl-blend-string.c \ $(srcdir)/cogl-blend-string.h \ $(srcdir)/cogl-debug.c \ + $(srcdir)/cogl-sub-texture-private.h \ $(srcdir)/cogl-texture-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-sliced.c \ $(srcdir)/cogl-spans.h \ diff --git a/cogl/cogl-sub-texture-private.h b/cogl/cogl-sub-texture-private.h new file mode 100644 index 000000000..899f61e8c --- /dev/null +++ b/cogl/cogl-sub-texture-private.h @@ -0,0 +1,56 @@ +/* + * 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_SUB_TEXTURE_H +#define __COGL_SUB_TEXTURE_H + +#include "cogl-handle.h" +#include "cogl-texture-private.h" + +#define COGL_SUB_TEXTURE(tex) ((CoglSubTexture *) tex) + +typedef struct _CoglSubTexture CoglSubTexture; + +struct _CoglSubTexture +{ + CoglTexture _parent; + + CoglHandle full_texture; + + /* The texture coordinates of the subregion of full_texture */ + gfloat tx1, ty1; + gfloat tx2, ty2; + + /* Are all of the texture coordinates a multiple of one? */ + gboolean tex_coords_are_a_multiple; +}; + +GQuark +_cogl_handle_sub_texture_get_type (void); + +CoglHandle +_cogl_sub_texture_new (CoglHandle full_texture, + gfloat tx1, gfloat ty1, + gfloat tx2, gfloat ty2); + +#endif /* __COGL_SUB_TEXTURE_H */ diff --git a/cogl/cogl-sub-texture.c b/cogl/cogl-sub-texture.c new file mode 100644 index 000000000..a8e164160 --- /dev/null +++ b/cogl/cogl-sub-texture.c @@ -0,0 +1,699 @@ +/* + * 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-sub-texture-private.h" +#include "cogl-context.h" +#include "cogl-handle.h" +#include "cogl-texture-driver.h" + +#include +#include + +static void _cogl_sub_texture_free (CoglSubTexture *sub_tex); + +COGL_HANDLE_DEFINE (SubTexture, sub_texture); + +static const CoglTextureVtable cogl_sub_texture_vtable; + +/* Maps from the texture coordinates of this texture to the texture + coordinates of the full texture */ + +static void +_cogl_sub_texture_map_coordinate_pair (CoglSubTexture *sub_tex, + gfloat *tx, gfloat *ty) +{ + *tx = *tx * (sub_tex->tx2 - sub_tex->tx1) + sub_tex->tx1; + *ty = *ty * (sub_tex->ty2 - sub_tex->ty1) + sub_tex->ty1; +} + +static void +_cogl_sub_texture_map_coordinate_set (CoglSubTexture *sub_tex, + gfloat *tx1, gfloat *ty1, + gfloat *tx2, gfloat *ty2) +{ + _cogl_sub_texture_map_coordinate_pair (sub_tex, tx1, ty1); + _cogl_sub_texture_map_coordinate_pair (sub_tex, tx2, ty2); +} + +/* Maps from the texture coordinates of the full texture to the + texture coordinates of the sub texture */ +static void +_cogl_sub_texture_unmap_coordinate_pair (CoglSubTexture *sub_tex, + gfloat *coords) +{ + if (sub_tex->tx1 == sub_tex->tx2) + coords[0] = sub_tex->tx1; + else + coords[0] = (coords[0] - sub_tex->tx1) / (sub_tex->tx2 - sub_tex->tx1); + + if (sub_tex->ty1 == sub_tex->ty2) + coords[0] = sub_tex->ty1; + else + coords[1] = (coords[1] - sub_tex->ty1) / (sub_tex->ty2 - sub_tex->ty1); +} + +static void +_cogl_sub_texture_unmap_coordinate_set (CoglSubTexture *sub_tex, + gfloat *coords) +{ + _cogl_sub_texture_unmap_coordinate_pair (sub_tex, coords); + _cogl_sub_texture_unmap_coordinate_pair (sub_tex, coords + 2); +} + +static gboolean +_cogl_sub_texture_same_int_part (float t1, float t2) +{ + float int_part1, int_part2; + float frac_part1, frac_part2; + + frac_part1 = modff (t1, &int_part1); + frac_part2 = modff (t2, &int_part2); + + return (int_part1 == int_part2 || + ((frac_part1 == 0.0f || frac_part2 == 0.0f) && + ABS (int_part1 - int_part2) == 1.0f)); +} + +typedef struct _CoglSubTextureForeachData +{ + CoglSubTexture *sub_tex; + CoglTextureSliceCallback callback; + void *user_data; +} CoglSubTextureForeachData; + +static void +_cogl_sub_texture_foreach_cb (CoglHandle handle, + GLuint gl_handle, + GLenum gl_target, + const float *slice_coords, + const float *full_virtual_coords, + void *user_data) +{ + CoglSubTextureForeachData *data = user_data; + float virtual_coords[4]; + + memcpy (virtual_coords, full_virtual_coords, sizeof (virtual_coords)); + /* Convert the virtual coords from the full-texture space to the sub + texture space */ + _cogl_sub_texture_unmap_coordinate_set (data->sub_tex, virtual_coords); + + data->callback (handle, gl_handle, gl_target, + slice_coords, virtual_coords, + data->user_data); +} + +static void +_cogl_sub_texture_manual_repeat_cb (const float *coords, + void *user_data) +{ + CoglSubTextureForeachData *data = user_data; + float mapped_coords[4]; + + memcpy (mapped_coords, coords, sizeof (mapped_coords)); + + _cogl_sub_texture_map_coordinate_set (data->sub_tex, + &mapped_coords[0], + &mapped_coords[1], + &mapped_coords[2], + &mapped_coords[3]); + + _cogl_texture_foreach_sub_texture_in_region (data->sub_tex->full_texture, + mapped_coords[0], + mapped_coords[1], + mapped_coords[2], + mapped_coords[3], + _cogl_sub_texture_foreach_cb, + user_data); +} + +static void +_cogl_sub_texture_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) +{ + CoglSubTexture *sub_tex = COGL_SUB_TEXTURE (tex); + CoglSubTextureForeachData data; + + data.sub_tex = sub_tex; + data.callback = callback; + data.user_data = user_data; + + /* If there is no repeating or the sub texture coordinates are a + multiple of the whole texture then we can just directly map the + texture coordinates */ + if (sub_tex->tex_coords_are_a_multiple || + (_cogl_sub_texture_same_int_part (virtual_tx_1, virtual_tx_2) && + _cogl_sub_texture_same_int_part (virtual_ty_1, virtual_ty_2))) + { + _cogl_sub_texture_map_coordinate_set (sub_tex, + &virtual_tx_1, + &virtual_ty_1, + &virtual_tx_2, + &virtual_ty_2); + + _cogl_texture_foreach_sub_texture_in_region + (sub_tex->full_texture, + virtual_tx_1, virtual_ty_1, + virtual_tx_2, virtual_ty_2, + _cogl_sub_texture_foreach_cb, &data); + } + else + _cogl_texture_iterate_manual_repeats (_cogl_sub_texture_manual_repeat_cb, + virtual_tx_1, virtual_ty_1, + virtual_tx_2, virtual_ty_2, + &data); +} + +static void +_cogl_sub_texture_set_wrap_mode_parameter (CoglTexture *tex, + GLenum wrap_mode) +{ + CoglSubTexture *sub_tex = COGL_SUB_TEXTURE (tex); + + _cogl_texture_set_wrap_mode_parameter (sub_tex->full_texture, wrap_mode); +} + +static void +_cogl_sub_texture_free (CoglSubTexture *sub_tex) +{ + cogl_handle_unref (sub_tex->full_texture); + + g_free (sub_tex); +} + +CoglHandle +_cogl_sub_texture_new (CoglHandle full_texture, + gfloat tx1, gfloat ty1, + gfloat tx2, gfloat ty2) +{ + CoglSubTexture *sub_tex; + CoglTexture *tex; + gfloat integer_part; + + sub_tex = g_new (CoglSubTexture, 1); + + tex = COGL_TEXTURE (sub_tex); + tex->vtable = &cogl_sub_texture_vtable; + + sub_tex->full_texture = cogl_handle_ref (full_texture); + + sub_tex->tx1 = tx1; + sub_tex->ty1 = ty1; + sub_tex->tx2 = tx2; + sub_tex->ty2 = ty2; + + /* Track whether the texture coords are a multiple of one because in + that case we can use hardware repeating */ + sub_tex->tex_coords_are_a_multiple + = (modff (tx1, &integer_part) == 0.0f && + modff (ty1, &integer_part) == 0.0f && + modff (tx2, &integer_part) == 0.0f && + modff (ty2, &integer_part) == 0.0f); + + return _cogl_sub_texture_handle_new (sub_tex); +} + +static gint +_cogl_sub_texture_get_max_waste (CoglTexture *tex) +{ + CoglSubTexture *sub_tex = COGL_SUB_TEXTURE (tex); + + return cogl_texture_get_max_waste (sub_tex->full_texture); +} + +static gboolean +_cogl_sub_texture_is_sliced (CoglTexture *tex) +{ + CoglSubTexture *sub_tex = COGL_SUB_TEXTURE (tex); + + return cogl_texture_is_sliced (sub_tex->full_texture); +} + +static gboolean +_cogl_sub_texture_can_hardware_repeat (CoglTexture *tex) +{ + CoglSubTexture *sub_tex = COGL_SUB_TEXTURE (tex); + + /* We can hardware repeat if the full texture can hardware repeat + and the coordinates for the subregion are all a multiple of the + full size of the texture (ie, they have no fractional part) */ + + return (sub_tex->tex_coords_are_a_multiple && + _cogl_texture_can_hardware_repeat (sub_tex->full_texture)); +} + +static void +_cogl_sub_texture_transform_coords_to_gl (CoglTexture *tex, + float *s, + float *t) +{ + CoglSubTexture *sub_tex = COGL_SUB_TEXTURE (tex); + + _cogl_sub_texture_map_coordinate_pair (sub_tex, s, t); + _cogl_texture_transform_coords_to_gl (sub_tex->full_texture, s, t); +} + +static gboolean +_cogl_sub_texture_get_gl_texture (CoglTexture *tex, + GLuint *out_gl_handle, + GLenum *out_gl_target) +{ + CoglSubTexture *sub_tex = COGL_SUB_TEXTURE (tex); + + return cogl_texture_get_gl_texture (sub_tex->full_texture, + out_gl_handle, + out_gl_target); +} + +static void +_cogl_sub_texture_set_filters (CoglTexture *tex, + GLenum min_filter, + GLenum mag_filter) +{ + CoglSubTexture *sub_tex = COGL_SUB_TEXTURE (tex); + + _cogl_texture_set_filters (sub_tex->full_texture, min_filter, mag_filter); +} + +static void +_cogl_sub_texture_ensure_mipmaps (CoglTexture *tex) +{ + CoglSubTexture *sub_tex = COGL_SUB_TEXTURE (tex); + + _cogl_texture_ensure_mipmaps (sub_tex->full_texture); +} + +static void +_cogl_sub_texture_get_next_chunk (int pos, int end, + int tex_size, + int *chunk_start, int *chunk_end) +{ + /* pos and end may be negative or greater than the size of the + texture. We want to calculate the next largest range we can copy + in one chunk */ + + if (pos < 0) + /* The behaviour of % for negative numbers is implementation + dependant in C89 so we have to do this */ + *chunk_start = (tex_size - pos) % tex_size; + else + *chunk_start = pos % tex_size; + + /* If the region is larger than the remaining size of the texture + then we need to crop it */ + if (end - pos > tex_size - *chunk_start) + end = pos + tex_size - *chunk_start; + + if (end < 0) + *chunk_end = (tex_size - end) % tex_size; + else + *chunk_end = end % tex_size; + + if (*chunk_end == 0) + *chunk_end = tex_size; +} + +static void +_cogl_sub_texture_get_x_pixel_pos (CoglSubTexture *sub_tex, + gint *px1, gint *px2) +{ + gint full_width = cogl_texture_get_width (sub_tex->full_texture); + + *px1 = full_width * sub_tex->tx1; + *px2 = full_width * sub_tex->tx2; + + if (*px1 > *px2) + { + gint temp = *px1; + *px1 = *px2; + *px2 = temp; + } +} + +static void +_cogl_sub_texture_get_y_pixel_pos (CoglSubTexture *sub_tex, + gint *py1, gint *py2) +{ + gint full_width = cogl_texture_get_width (sub_tex->full_texture); + + *py1 = full_width * sub_tex->ty1; + *py2 = full_width * sub_tex->ty2; + + if (*py1 > *py2) + { + gint temp = *py1; + *py1 = *py2; + *py2 = temp; + } +} + +static gboolean +_cogl_sub_texture_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) +{ + CoglSubTexture *sub_tex = COGL_SUB_TEXTURE (tex); + gint full_tex_width, full_tex_height; + gint bpp; + gint px1, py1, px2, py2; + gint it_x, it_y; + gint src_x1, src_y1, src_x2, src_y2; + CoglBitmap source_bmp; + CoglBitmap temp_bmp; + gboolean source_bmp_owner = FALSE; + CoglPixelFormat closest_format; + GLenum closest_gl_format; + GLenum closest_gl_type; + gboolean success; + CoglPixelFormat tex_format; + + /* 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; + + /* FIXME: If the sub texture coordinates are swapped around then we + should flip the bitmap */ + + _cogl_sub_texture_get_x_pixel_pos (sub_tex, &px1, &px2); + _cogl_sub_texture_get_y_pixel_pos (sub_tex, &py1, &py2); + + full_tex_width = cogl_texture_get_width (sub_tex->full_texture); + full_tex_height = cogl_texture_get_height (sub_tex->full_texture); + + /* Init source bitmap */ + source_bmp.width = width; + source_bmp.height = height; + source_bmp.format = format; + source_bmp.data = (guchar*) data; + + /* Rowstride from texture 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 */ + tex_format = cogl_texture_get_format (sub_tex->full_texture); + closest_format = _cogl_pixel_format_to_gl (tex_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; + } + + for (it_y = py1; it_y < py2; it_y += src_y2 - src_y1) + { + _cogl_sub_texture_get_next_chunk (it_y, py2, full_tex_width, + &src_y1, &src_y2); + + for (it_x = px1; it_x < px2; it_x += src_x2 - src_x1) + { + gint virt_x_1, virt_y_1, virt_width, virt_height; + gint copy_dst_x, copy_dst_y, copy_dst_width, copy_dst_height; + + _cogl_sub_texture_get_next_chunk (it_x, px2, full_tex_height, + &src_x1, &src_x2); + + /* Offset of the chunk from the left edge in the virtual sub + texture coordinates */ + virt_x_1 = it_x - px1; + /* Pixel width covered by this chunk */ + virt_width = src_x2 - src_x1; + /* Offset of the chunk from the top edge in the virtual sub + texture coordinates */ + virt_y_1 = it_y - py1; + /* Pixel height covered by this chunk */ + virt_height = src_y2 - src_y1; + + /* Check if this chunk intersects with the update region */ + if (dst_x + dst_width <= virt_x_1 || + dst_x >= virt_x_1 + virt_width || + dst_y + dst_height <= it_y - py1 || + dst_y >= virt_y_1 + virt_height) + continue; + + /* Calculate the intersection in virtual coordinates */ + copy_dst_width = dst_width; + if (dst_x < virt_x_1) + { + copy_dst_width -= virt_x_1 - dst_x; + copy_dst_x = virt_x_1; + } + else + copy_dst_x = dst_x; + if (copy_dst_width + copy_dst_x > virt_x_1 + virt_width) + copy_dst_width = virt_x_1 + virt_width - copy_dst_x; + + copy_dst_height = dst_height; + if (dst_y < virt_y_1) + { + copy_dst_height -= virt_y_1 - dst_y; + copy_dst_y = virt_y_1; + } + else + copy_dst_y = dst_y; + if (copy_dst_height + copy_dst_y > virt_y_1 + virt_height) + copy_dst_height = virt_y_1 + virt_height - copy_dst_y; + + /* Update the region in the full texture */ + cogl_texture_set_region (sub_tex->full_texture, + src_x + copy_dst_x - dst_x, + src_y + copy_dst_y - dst_y, + src_x1 + copy_dst_x - virt_x_1, + src_y1 + copy_dst_y - virt_y_1, + copy_dst_width, + copy_dst_height, + width, + height, + format, + rowstride, + data); + } + } + + /* Free data if owner */ + if (source_bmp_owner) + g_free (source_bmp.data); + + return TRUE; +} + +static void +_cogl_sub_texture_copy_region (guchar *dst, + const guchar *src, + gint dst_x, gint dst_y, + gint src_x, gint src_y, + gint width, gint height, + gint dst_rowstride, + gint src_rowstride, + gint bpp) +{ + int y; + + dst += dst_x * bpp + dst_y * dst_rowstride; + src += src_x * bpp + src_y * src_rowstride; + + for (y = 0; y < height; y++) + { + memcpy (dst, src, bpp * width); + dst += dst_rowstride; + src += src_rowstride; + } +} + +static int +_cogl_sub_texture_get_data (CoglTexture *tex, + CoglPixelFormat format, + unsigned int rowstride, + guint8 *data) +{ + CoglSubTexture *sub_tex = COGL_SUB_TEXTURE (tex); + unsigned int full_rowstride; + guint8 *full_data; + int byte_size, full_size; + gint bpp; + gint px1, py1, px2, py2; + gint full_tex_width, full_tex_height; + + /* FIXME: This gets the full data from the full texture and then + copies a subregion of that. It would be better if there was a + texture_get_sub_data virtual and it can just munge the texture + coordinates */ + + /* Default to internal format if none specified */ + if (format == COGL_PIXEL_FORMAT_ANY) + format = cogl_texture_get_format (sub_tex->full_texture); + + _cogl_sub_texture_get_x_pixel_pos (sub_tex, &px1, &px2); + _cogl_sub_texture_get_y_pixel_pos (sub_tex, &py1, &py2); + + full_tex_width = cogl_texture_get_width (sub_tex->full_texture); + full_tex_height = cogl_texture_get_height (sub_tex->full_texture); + + /* Rowstride from texture width if none specified */ + bpp = _cogl_get_format_bpp (format); + if (rowstride == 0) + rowstride = px2 - px1; + + /* Return byte size if only that requested */ + byte_size = (py2 - py1) * rowstride; + if (data == NULL) + return byte_size; + + full_rowstride = _cogl_get_format_bpp (format) * full_tex_width; + full_data = g_malloc (full_rowstride * full_tex_height); + + full_size = cogl_texture_get_data (sub_tex->full_texture, format, + full_rowstride, full_data); + + if (full_size) + { + int dst_x, dst_y; + int src_x1, src_y1; + int src_x2, src_y2; + + for (dst_y = py1; dst_y < py2; dst_y += src_y2 - src_y1) + { + _cogl_sub_texture_get_next_chunk (dst_y, py2, full_tex_width, + &src_y1, &src_y2); + + for (dst_x = px1; dst_x < px2; dst_x += src_x2 - src_x1) + { + _cogl_sub_texture_get_next_chunk (dst_x, px2, full_tex_height, + &src_x1, &src_x2); + + _cogl_sub_texture_copy_region (data, full_data, + dst_x - px1, dst_y - py1, + src_x1, src_y1, + src_x2 - src_x1, + src_y2 - src_y1, + rowstride, + full_rowstride, + bpp); + } + } + } + else + byte_size = 0; + + g_free (full_data); + + return byte_size; +} + +static CoglPixelFormat +_cogl_sub_texture_get_format (CoglTexture *tex) +{ + CoglSubTexture *sub_tex = COGL_SUB_TEXTURE (tex); + + return cogl_texture_get_format (sub_tex->full_texture); +} + +static GLenum +_cogl_sub_texture_get_gl_format (CoglTexture *tex) +{ + CoglSubTexture *sub_tex = COGL_SUB_TEXTURE (tex); + + return _cogl_texture_get_gl_format (sub_tex->full_texture); +} + +static gint +_cogl_sub_texture_get_width (CoglTexture *tex) +{ + CoglSubTexture *sub_tex = COGL_SUB_TEXTURE (tex); + gint px1, px2; + + _cogl_sub_texture_get_x_pixel_pos (sub_tex, &px1, &px2); + + return px2 - px1; +} + +static gint +_cogl_sub_texture_get_height (CoglTexture *tex) +{ + CoglSubTexture *sub_tex = COGL_SUB_TEXTURE (tex); + gint py1, py2; + + _cogl_sub_texture_get_y_pixel_pos (sub_tex, &py1, &py2); + + return py2 - py1; +} + +static const CoglTextureVtable +cogl_sub_texture_vtable = + { + _cogl_sub_texture_set_region, + _cogl_sub_texture_get_data, + _cogl_sub_texture_foreach_sub_texture_in_region, + _cogl_sub_texture_get_max_waste, + _cogl_sub_texture_is_sliced, + _cogl_sub_texture_can_hardware_repeat, + _cogl_sub_texture_transform_coords_to_gl, + _cogl_sub_texture_get_gl_texture, + _cogl_sub_texture_set_filters, + _cogl_sub_texture_ensure_mipmaps, + _cogl_sub_texture_set_wrap_mode_parameter, + _cogl_sub_texture_get_format, + _cogl_sub_texture_get_gl_format, + _cogl_sub_texture_get_width, + _cogl_sub_texture_get_height + }; diff --git a/cogl/cogl-texture.c b/cogl/cogl-texture.c index e4eff2e06..5fc0892cb 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-sub-texture-private.h" #include "cogl-material.h" #include "cogl-context.h" #include "cogl-handle.h" @@ -62,8 +63,8 @@ cogl_is_texture (CoglHandle handle) if (handle == COGL_INVALID_HANDLE) return FALSE; - return obj->klass->type == _cogl_handle_texture_2d_sliced_get_type (); - //|| obj->klass->type == _cogl_handle_texture_3d_get_type (); + return (obj->klass->type == _cogl_handle_texture_2d_sliced_get_type () || + obj->klass->type == _cogl_handle_sub_texture_get_type ()); } CoglHandle @@ -367,6 +368,16 @@ cogl_texture_new_from_foreign (GLuint gl_handle, format); } +CoglHandle +cogl_texture_new_from_sub_texture (CoglHandle full_texture, + gfloat tx1, + gfloat ty1, + gfloat tx2, + gfloat ty2) +{ + return _cogl_sub_texture_new (full_texture, tx1, ty1, tx2, ty2); +} + guint cogl_texture_get_width (CoglHandle handle) { diff --git a/cogl/cogl-texture.h b/cogl/cogl-texture.h index b831d1ae1..5e4910f31 100644 --- a/cogl/cogl-texture.h +++ b/cogl/cogl-texture.h @@ -316,6 +316,33 @@ gboolean cogl_texture_set_region (CoglHandle handle, guint rowstride, const guchar *data); +/** + * cogl_texture_new_from_sub_texture: + * @full_texture: a #CoglHandle to an existing texture + * @tx1: X coordinate of the top-left of the subregion + * @ty1: Y coordinate of the top-left of the subregion + * @tx2: X coordinate of the bottom-right of the subregion + * @ty2: Y coordinate of the bottom-right of the subregion + * + * Creates a new texture which represents a subregion of another + * texture. The GL resources will be shared so that no new texture + * data is actually allocated. + * + * You can also specify texture coordinates outside the range of [0,1] + * to make a texture that represents a repeated version of another + * texture. + * + * Return value: a #CoglHandle to the new texture. + * + * Since: 1.2 + */ +CoglHandle cogl_texture_new_from_sub_texture + (CoglHandle full_texture, + gfloat tx1, + gfloat ty1, + gfloat tx2, + gfloat ty2); + #ifndef COGL_DISABLE_DEPRECATED /** diff --git a/doc/reference/cogl/cogl-sections.txt b/doc/reference/cogl/cogl-sections.txt index 336f9ad03..eda10b462 100644 --- a/doc/reference/cogl/cogl-sections.txt +++ b/doc/reference/cogl/cogl-sections.txt @@ -192,6 +192,7 @@ cogl_texture_new_from_file cogl_texture_new_from_data cogl_texture_new_from_foreign cogl_texture_new_from_bitmap +cogl_texture_new_from_sub_texture cogl_is_texture cogl_texture_ref cogl_texture_unref