mirror of
https://github.com/brl/mutter.git
synced 2024-12-23 11:32:04 +00:00
meta-texture: This publicly exposes CoglMetaTexture
CoglMetaTexture is an interface for dealing with high level textures that may be comprised of one or more low-level textures internally. The interface allows the development of primitive drawing APIs that can draw with high-level textures (such as atlas textures) even though the GPU doesn't natively understand these texture types. There is currently just one function that's part of this interface: cogl_meta_texture_foreach_in_region() which allows an application to resolve the internal, low-level textures of a high-level texture. cogl_rectangle() uses this API for example so that it can easily emulate the _REPEAT wrap mode for textures that the hardware can't natively handle repeating of. Reviewed-by: Neil Roberts <neil@linux.intel.com>
This commit is contained in:
parent
c11036cd13
commit
1d8fd64e1c
@ -140,13 +140,15 @@ cogl_pango_renderer_draw_glyph (CoglPangoRenderer *priv,
|
||||
the neighbouring glyphs are coming from the same atlas and bundle
|
||||
them together into a single VBO */
|
||||
|
||||
_cogl_texture_foreach_sub_texture_in_region (cache_value->texture,
|
||||
cache_value->tx1,
|
||||
cache_value->ty1,
|
||||
cache_value->tx2,
|
||||
cache_value->ty2,
|
||||
cogl_pango_renderer_slice_cb,
|
||||
&data);
|
||||
cogl_meta_texture_foreach_in_region (COGL_META_TEXTURE (cache_value->texture),
|
||||
cache_value->tx1,
|
||||
cache_value->ty1,
|
||||
cache_value->tx2,
|
||||
cache_value->ty2,
|
||||
COGL_PIPELINE_WRAP_MODE_REPEAT,
|
||||
COGL_PIPELINE_WRAP_MODE_REPEAT,
|
||||
cogl_pango_renderer_slice_cb,
|
||||
&data);
|
||||
}
|
||||
|
||||
static void cogl_pango_renderer_finalize (GObject *object);
|
||||
|
@ -78,6 +78,7 @@ cogl_public_h = \
|
||||
$(srcdir)/cogl-texture-3d.h \
|
||||
$(srcdir)/cogl-texture-2d.h \
|
||||
$(srcdir)/cogl-texture-2d-sliced.h \
|
||||
$(srcdir)/cogl-meta-texture.h \
|
||||
$(srcdir)/cogl-types.h \
|
||||
$(srcdir)/cogl-vertex-buffer.h \
|
||||
$(srcdir)/cogl-index-buffer.h \
|
||||
@ -295,6 +296,7 @@ cogl_sources_c = \
|
||||
$(srcdir)/cogl-atlas.c \
|
||||
$(srcdir)/cogl-atlas-texture-private.h \
|
||||
$(srcdir)/cogl-atlas-texture.c \
|
||||
$(srcdir)/cogl-meta-texture.c \
|
||||
$(srcdir)/cogl-blit.h \
|
||||
$(srcdir)/cogl-blit.c \
|
||||
$(srcdir)/cogl-spans.h \
|
||||
|
@ -225,19 +225,21 @@ _cogl_atlas_texture_foreach_sub_texture_in_region (
|
||||
float virtual_ty_1,
|
||||
float virtual_tx_2,
|
||||
float virtual_ty_2,
|
||||
CoglTextureSliceCallback callback,
|
||||
CoglMetaTextureCallback callback,
|
||||
void *user_data)
|
||||
{
|
||||
CoglAtlasTexture *atlas_tex = COGL_ATLAS_TEXTURE (tex);
|
||||
|
||||
/* Forward on to the sub texture */
|
||||
_cogl_texture_foreach_sub_texture_in_region (atlas_tex->sub_texture,
|
||||
virtual_tx_1,
|
||||
virtual_ty_1,
|
||||
virtual_tx_2,
|
||||
virtual_ty_2,
|
||||
callback,
|
||||
user_data);
|
||||
cogl_meta_texture_foreach_in_region (atlas_tex->sub_texture,
|
||||
virtual_tx_1,
|
||||
virtual_ty_1,
|
||||
virtual_tx_2,
|
||||
virtual_ty_2,
|
||||
COGL_PIPELINE_WRAP_MODE_REPEAT,
|
||||
COGL_PIPELINE_WRAP_MODE_REPEAT,
|
||||
callback,
|
||||
user_data);
|
||||
}
|
||||
|
||||
static void
|
||||
|
391
cogl/cogl-meta-texture.c
Normal file
391
cogl/cogl-meta-texture.c
Normal file
@ -0,0 +1,391 @@
|
||||
/*
|
||||
* Cogl
|
||||
*
|
||||
* An object oriented GL/GLES Abstraction/Utility Layer
|
||||
*
|
||||
* Copyright (C) 2011 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, see
|
||||
* <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
* Authors:
|
||||
* Robert Bragg <robert@linux.intel.com>
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "cogl-texture.h"
|
||||
#include "cogl-matrix.h"
|
||||
#include "cogl-spans.h"
|
||||
#include "cogl-meta-texture.h"
|
||||
#include "cogl-texture-rectangle-private.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
typedef struct _ForeachData
|
||||
{
|
||||
float meta_region_coords[4];
|
||||
CoglPipelineWrapMode wrap_s;
|
||||
CoglPipelineWrapMode wrap_t;
|
||||
CoglMetaTextureCallback callback;
|
||||
void *user_data;
|
||||
|
||||
int width;
|
||||
int height;
|
||||
|
||||
CoglTexture *padded_textures[9];
|
||||
const float *grid_slice_texture_coords;
|
||||
float slice_offset_s;
|
||||
float slice_offset_t;
|
||||
float slice_range_s;
|
||||
float slice_range_t;
|
||||
} ForeachData;
|
||||
|
||||
static void
|
||||
padded_grid_repeat_cb (CoglTexture *slice_texture,
|
||||
const float *slice_texture_coords,
|
||||
const float *meta_coords,
|
||||
void *user_data)
|
||||
{
|
||||
ForeachData *data;
|
||||
float mapped_coords[4];
|
||||
|
||||
/* Ignore padding slices for the current grid */
|
||||
if (!slice_texture)
|
||||
return;
|
||||
|
||||
data = user_data;
|
||||
|
||||
/* NB: the slice_texture_coords[] we get here will always be
|
||||
* normalized.
|
||||
*
|
||||
* We now need to map the normalized slice_texture_coords[] we have
|
||||
* here back to the real slice coordinates we saved in the previous
|
||||
* stage...
|
||||
*/
|
||||
mapped_coords[0] =
|
||||
slice_texture_coords[0] * data->slice_range_s + data->slice_offset_s;
|
||||
mapped_coords[1] =
|
||||
slice_texture_coords[1] * data->slice_range_t + data->slice_offset_t;
|
||||
mapped_coords[2] =
|
||||
slice_texture_coords[2] * data->slice_range_s + data->slice_offset_s;
|
||||
mapped_coords[3] =
|
||||
slice_texture_coords[3] * data->slice_range_t + data->slice_offset_t;
|
||||
|
||||
data->callback (slice_texture,
|
||||
mapped_coords, meta_coords, data->user_data);
|
||||
}
|
||||
|
||||
static int
|
||||
setup_padded_spans (CoglSpan *spans,
|
||||
float start,
|
||||
float end,
|
||||
float range,
|
||||
int *real_index)
|
||||
{
|
||||
int span_index = 0;
|
||||
|
||||
if (start > 0)
|
||||
{
|
||||
spans[0].start = 0;
|
||||
spans[0].size = start;
|
||||
spans[0].waste = 0;
|
||||
span_index++;
|
||||
spans[1].start = spans[0].size;
|
||||
}
|
||||
else
|
||||
spans[span_index].start = 0;
|
||||
|
||||
spans[span_index].size = end - start;
|
||||
spans[span_index].waste = 0;
|
||||
*real_index = span_index;
|
||||
span_index++;
|
||||
|
||||
if (end < range)
|
||||
{
|
||||
spans[span_index].start =
|
||||
spans[span_index - 1].start + spans[span_index - 1].size;
|
||||
spans[span_index].size = range - end;
|
||||
spans[span_index].waste = 0;
|
||||
span_index++;
|
||||
}
|
||||
|
||||
return span_index;
|
||||
}
|
||||
|
||||
/* This handles each sub-texture within the range [0,1] of our
|
||||
* original meta texture and repeats each one separately across the
|
||||
* users requested virtual texture coordinates.
|
||||
*
|
||||
* A notable advantage of this approach is that we will batch
|
||||
* together callbacks corresponding to the same underlying slice
|
||||
* together.
|
||||
*/
|
||||
void
|
||||
create_grid_and_repeat_cb (CoglTexture *slice_texture,
|
||||
const float *slice_texture_coords,
|
||||
const float *meta_coords,
|
||||
void *user_data)
|
||||
{
|
||||
ForeachData *data = user_data;
|
||||
CoglSpan x_spans[3];
|
||||
int n_x_spans;
|
||||
int x_real_index;
|
||||
CoglSpan y_spans[3];
|
||||
int n_y_spans;
|
||||
int y_real_index;
|
||||
|
||||
/* NB: This callback is called for each slice of the meta-texture
|
||||
* in the range [0,1].
|
||||
*
|
||||
* We define a "padded grid" for each slice of the meta-texture in
|
||||
* the range [0,1]. The x axis and y axis grid lines are defined
|
||||
* using CoglSpans.
|
||||
*
|
||||
* The padded grid maps over the meta-texture coordinates in the
|
||||
* range [0,1] but only contains one valid cell that corresponds to
|
||||
* current slice being iterated and all the surrounding cells just
|
||||
* provide padding.
|
||||
*
|
||||
* Once we've defined our padded grid we then repeat that across
|
||||
* the user's original region, calling their callback whenever
|
||||
* we see our current slice - ignoring padding.
|
||||
*
|
||||
* NB: we can assume meta_coords[] are normalized at this point
|
||||
* since TextureRectangles aren't iterated with this code-path.
|
||||
*
|
||||
* NB: spans are always defined using non-normalized coordinates
|
||||
*/
|
||||
n_x_spans = setup_padded_spans (x_spans,
|
||||
meta_coords[0] * data->width,
|
||||
meta_coords[2] * data->width,
|
||||
data->width,
|
||||
&x_real_index);
|
||||
n_y_spans = setup_padded_spans (y_spans,
|
||||
meta_coords[1] * data->height,
|
||||
meta_coords[3] * data->height,
|
||||
data->height,
|
||||
&y_real_index);
|
||||
|
||||
data->padded_textures[n_y_spans * y_real_index + x_real_index] =
|
||||
slice_texture;
|
||||
|
||||
/* Our callback is going to be passed normalized slice texture
|
||||
* coordinates, and we will need to map the range [0,1] to the real
|
||||
* slice_texture_coords we have here... */
|
||||
data->grid_slice_texture_coords = slice_texture_coords;
|
||||
data->slice_range_s = fabs (data->grid_slice_texture_coords[2] -
|
||||
data->grid_slice_texture_coords[0]);
|
||||
data->slice_range_t = fabs (data->grid_slice_texture_coords[3] -
|
||||
data->grid_slice_texture_coords[1]);
|
||||
data->slice_offset_s = MIN (data->grid_slice_texture_coords[0],
|
||||
data->grid_slice_texture_coords[2]);
|
||||
data->slice_offset_t = MIN (data->grid_slice_texture_coords[1],
|
||||
data->grid_slice_texture_coords[3]);
|
||||
|
||||
/* Now actually iterate the region the user originally requested
|
||||
* using the current padded grid */
|
||||
_cogl_texture_spans_foreach_in_region (x_spans,
|
||||
n_x_spans,
|
||||
y_spans,
|
||||
n_y_spans,
|
||||
data->padded_textures,
|
||||
data->meta_region_coords,
|
||||
data->width,
|
||||
data->height,
|
||||
data->wrap_s,
|
||||
data->wrap_t,
|
||||
padded_grid_repeat_cb,
|
||||
data);
|
||||
|
||||
/* Clear the padded_textures ready for the next iteration */
|
||||
data->padded_textures[n_y_spans * y_real_index + x_real_index] = NULL;
|
||||
}
|
||||
|
||||
typedef struct _NormalizeData
|
||||
{
|
||||
CoglMetaTextureCallback callback;
|
||||
void *user_data;
|
||||
float s_normalize_factor;
|
||||
float t_normalize_factor;
|
||||
} NormalizeData;
|
||||
|
||||
static void
|
||||
normalize_meta_coords_cb (CoglTexture *slice_texture,
|
||||
const float *slice_coords,
|
||||
const float *meta_coords,
|
||||
void *user_data)
|
||||
{
|
||||
NormalizeData *data = user_data;
|
||||
float normalized_meta_coords[4] = {
|
||||
meta_coords[0] * data->s_normalize_factor,
|
||||
meta_coords[1] * data->t_normalize_factor,
|
||||
meta_coords[2] * data->s_normalize_factor,
|
||||
meta_coords[3] * data->t_normalize_factor
|
||||
};
|
||||
|
||||
data->callback (slice_texture,
|
||||
slice_coords, normalized_meta_coords,
|
||||
data->user_data);
|
||||
}
|
||||
|
||||
typedef struct _UnNormalizeData
|
||||
{
|
||||
CoglMetaTextureCallback callback;
|
||||
void *user_data;
|
||||
float width;
|
||||
float height;
|
||||
} UnNormalizeData;
|
||||
|
||||
static void
|
||||
un_normalize_slice_coords_cb (CoglTexture *slice_texture,
|
||||
const float *slice_coords,
|
||||
const float *meta_coords,
|
||||
void *user_data)
|
||||
{
|
||||
UnNormalizeData *data = user_data;
|
||||
float un_normalized_slice_coords[4] = {
|
||||
slice_coords[0] * data->width,
|
||||
slice_coords[1] * data->height,
|
||||
slice_coords[2] * data->width,
|
||||
slice_coords[3] * data->height
|
||||
};
|
||||
|
||||
data->callback (slice_texture,
|
||||
un_normalized_slice_coords, meta_coords,
|
||||
data->user_data);
|
||||
}
|
||||
|
||||
void
|
||||
cogl_meta_texture_foreach_in_region (CoglMetaTexture *meta_texture,
|
||||
float tx_1,
|
||||
float ty_1,
|
||||
float tx_2,
|
||||
float ty_2,
|
||||
CoglPipelineWrapMode wrap_s,
|
||||
CoglPipelineWrapMode wrap_t,
|
||||
CoglMetaTextureCallback callback,
|
||||
void *user_data)
|
||||
{
|
||||
CoglTexture *texture = COGL_TEXTURE (meta_texture);
|
||||
float width = cogl_texture_get_width (texture);
|
||||
float height = cogl_texture_get_height (texture);
|
||||
NormalizeData normalize_data;
|
||||
|
||||
/* It makes things simpler to deal with non-normalized region
|
||||
* coordinates beyond this point and only re-normalize just before
|
||||
* calling the user's callback... */
|
||||
|
||||
if (!_cogl_is_texture_rectangle (COGL_TEXTURE (meta_texture)))
|
||||
{
|
||||
normalize_data.callback = callback;
|
||||
normalize_data.user_data = user_data;
|
||||
normalize_data.s_normalize_factor = 1.0f / width;
|
||||
normalize_data.t_normalize_factor = 1.0f / height;
|
||||
callback = normalize_meta_coords_cb;
|
||||
user_data = &normalize_data;
|
||||
tx_1 *= width;
|
||||
ty_1 *= height;
|
||||
tx_2 *= width;
|
||||
ty_2 *= height;
|
||||
}
|
||||
|
||||
/* XXX: at some point this wont be routed through the CoglTexture
|
||||
* vtable, instead there will be a separate CoglMetaTexture
|
||||
* interface vtable. */
|
||||
|
||||
if (texture->vtable->foreach_sub_texture_in_region)
|
||||
{
|
||||
ForeachData data;
|
||||
|
||||
data.meta_region_coords[0] = tx_1;
|
||||
data.meta_region_coords[1] = ty_1;
|
||||
data.meta_region_coords[2] = tx_2;
|
||||
data.meta_region_coords[3] = ty_2;
|
||||
data.wrap_s = wrap_s;
|
||||
data.wrap_t = wrap_t;
|
||||
data.callback = callback;
|
||||
data.user_data = user_data;
|
||||
|
||||
data.width = width;
|
||||
data.height = height;
|
||||
|
||||
memset (data.padded_textures, 0, sizeof (data.padded_textures));
|
||||
|
||||
/*
|
||||
* 1) We iterate all the slices of the meta-texture only within
|
||||
* the range [0,1].
|
||||
*
|
||||
* 2) We define a "padded grid" for each slice of the
|
||||
* meta-texture in the range [0,1].
|
||||
*
|
||||
* The padded grid maps over the meta-texture coordinates in
|
||||
* the range [0,1] but only contains one valid cell that
|
||||
* corresponds to current slice being iterated and all the
|
||||
* surrounding cells just provide padding.
|
||||
*
|
||||
* 3) Once we've defined our padded grid we then repeat that
|
||||
* across the user's original region, calling their callback
|
||||
* whenever we see our current slice - ignoring padding.
|
||||
*
|
||||
* A notable benefit of this design is that repeating a texture
|
||||
* made of multiple slices will result in us repeating each
|
||||
* slice in-turn so the user gets repeat callbacks for the same
|
||||
* texture batched together. For manual emulation of texture
|
||||
* repeats done by drawing geometry this makes it more likely
|
||||
* that we can batch geometry.
|
||||
*/
|
||||
|
||||
texture->vtable->foreach_sub_texture_in_region (texture,
|
||||
0, 0, 1, 1,
|
||||
create_grid_and_repeat_cb,
|
||||
&data);
|
||||
}
|
||||
else
|
||||
{
|
||||
CoglSpan x_span = { 0, width, 0 };
|
||||
CoglSpan y_span = { 0, height, 0 };
|
||||
float meta_region_coords[4] = { tx_1, ty_1, tx_2, ty_2 };
|
||||
UnNormalizeData un_normalize_data;
|
||||
|
||||
/* If we are dealing with a CoglTextureRectangle then we need a shim
|
||||
* callback that un_normalizes the slice coordinates we get from
|
||||
* _cogl_texture_spans_foreach_in_region before passing them to
|
||||
* the user's callback. */
|
||||
if (_cogl_is_texture_rectangle (meta_texture))
|
||||
{
|
||||
un_normalize_data.callback = callback;
|
||||
un_normalize_data.user_data = user_data;
|
||||
un_normalize_data.width = width;
|
||||
un_normalize_data.height = height;
|
||||
callback = un_normalize_slice_coords_cb;
|
||||
user_data = &un_normalize_data;
|
||||
}
|
||||
|
||||
_cogl_texture_spans_foreach_in_region (&x_span, 1,
|
||||
&y_span, 1,
|
||||
&texture,
|
||||
meta_region_coords,
|
||||
width,
|
||||
height,
|
||||
wrap_s,
|
||||
wrap_t,
|
||||
callback,
|
||||
user_data);
|
||||
}
|
||||
}
|
190
cogl/cogl-meta-texture.h
Normal file
190
cogl/cogl-meta-texture.h
Normal file
@ -0,0 +1,190 @@
|
||||
/*
|
||||
* Cogl
|
||||
*
|
||||
* An object oriented GL/GLES Abstraction/Utility Layer
|
||||
*
|
||||
* Copyright (C) 2011 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, see
|
||||
* <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#if !defined(__COGL_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
|
||||
#error "Only <cogl/cogl.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#ifndef __COGL_META_TEXTURE_H__
|
||||
#define __COGL_META_TEXTURE_H__
|
||||
|
||||
#include <cogl/cogl-pipeline-layer-state.h>
|
||||
#include <glib.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/**
|
||||
* SECTION:cogl-meta-texture
|
||||
* @short_description: Interface for high-level textures built from
|
||||
* low-level textures like #CoglTexture2D and
|
||||
* #CoglTexture3D.
|
||||
*
|
||||
* Cogl helps to make it easy to deal with high level textures such
|
||||
* as #CoglAtlasTexture<!-- -->s, #CoglSubTexture<!-- -->s,
|
||||
* #CoglTexturePixmapX11 textures and #CoglTexture2DSliced textures
|
||||
* consistently.
|
||||
*
|
||||
* A #CoglMetaTexture is a texture that might internally be
|
||||
* represented by one or more low-level #CoglTexture<!-- -->s
|
||||
* such as #CoglTexture2D or #CoglTexture3D. These low-level textures
|
||||
* are the only ones that a GPU really understands but because
|
||||
* applications often want more high-level texture abstractions
|
||||
* (such as storing multiple textures inside one larger "atlas"
|
||||
* texture) it's desirable to be able to deal with these
|
||||
* using a common interface.
|
||||
*
|
||||
* For example the GPU is not able to automatically handle repeating a
|
||||
* texture that is part of a larger atlas texture but if you use
|
||||
* %COGL_PIPELINE_WRAP_MODE_REPEAT with an atlas texture when drawing
|
||||
* with cogl_rectangle() you should see that it "Just Works™" - at
|
||||
* least if you don't use multi-texturing. The reason this works is
|
||||
* because cogl_rectangle() internally understands the #CoglMetaTexture
|
||||
* interface and is able to manually resolve the low-level textures
|
||||
* using this interface and by making multiple draw calls it can
|
||||
* emulate the texture repeat modes.
|
||||
*
|
||||
* Cogl doesn't aim to pretend that meta-textures are just like real
|
||||
* textures because it would get extremely complex to try and emulate
|
||||
* low-level GPU semantics transparently for these textures. The low
|
||||
* level drawing APIs of Cogl, such as cogl_draw_attributes() don't
|
||||
* actually know anything about the #CoglMetaTexture interface and its
|
||||
* the developer's responsibility to resolve all textures referenced by
|
||||
* a #CoglPipeline to low-level textures before drawing.
|
||||
*
|
||||
* If you want to develop custom primitive APIs like cogl_rectangle()
|
||||
* and you want to support drawing with #CoglAtlasTexture<!-- -->s
|
||||
* or #CoglSubTexture<!-- -->s for example, then you will need to use
|
||||
* this #CoglMetaTexture interface to be able to resolve high-level
|
||||
* textures into low-level textures before drawing with Cogl's
|
||||
* low-level drawing APIs such as cogl_draw_attributes().
|
||||
*
|
||||
* <note>Most developers won't need to use this interface directly
|
||||
* but still it is worth understanding the distinction between
|
||||
* low-level and meta textures because you may find other references
|
||||
* in the documentation that detail limitations of using
|
||||
* meta-textures.</note>
|
||||
*/
|
||||
|
||||
typedef struct _CoglMetaTexture CoglMetaTexture;
|
||||
#define COGL_META_TEXTURE(X) ((CoglMetaTexture *)X)
|
||||
|
||||
/**
|
||||
* CoglMetaTextureCallback:
|
||||
* @sub_texture: A low-level #CoglTexture making up part of a
|
||||
* #CoglMetaTexture.
|
||||
* @sub_texture_coords: A float 4-tuple ordered like
|
||||
* (tx1,ty1,tx2,ty2) defining what region of the
|
||||
* current @sub_texture maps to a sub-region of a
|
||||
* #CoglMetaTexture. (tx1,ty1) is the top-left
|
||||
* sub-region coordinate and (tx2,ty2) is the
|
||||
* bottom-right. These are low-level texture
|
||||
* coordinates.
|
||||
* @meta_coords: A float 4-tuple ordered like (tx1,ty1,tx2,ty2)
|
||||
* defining what sub-region of a #CoglMetaTexture this
|
||||
* low-level @sub_texture maps too. (tx1,ty1) is
|
||||
* the top-left sub-region coordinate and (tx2,ty2) is
|
||||
* the bottom-right. These are high-level meta-texture
|
||||
* coordinates.
|
||||
* @user_data: A private pointer passed to
|
||||
* cogl_meta_texture_foreach_in_region().
|
||||
*
|
||||
* A callback used with cogl_meta_texture_foreach_in_region() to
|
||||
* retrieve details of all the low-level #CoglTexture<!-- -->s that
|
||||
* make up a given #CoglMetaTexture.
|
||||
*
|
||||
* Since: 1.10
|
||||
* Stability: unstable
|
||||
*/
|
||||
typedef void (*CoglMetaTextureCallback) (CoglTexture *sub_texture,
|
||||
const float *sub_texture_coords,
|
||||
const float *meta_coords,
|
||||
void *user_data);
|
||||
|
||||
/**
|
||||
* cogl_meta_texture_foreach_in_region:
|
||||
* @meta_texture: An object implementing the #CoglMetaTexture
|
||||
* interface.
|
||||
* @tx_1: The top-left x coordinate of the region to iterate
|
||||
* @ty_1: The top-left y coordinate of the region to iterate
|
||||
* @tx_2: The bottom-right x coordinate of the region to iterate
|
||||
* @ty_2: The bottom-right y coordinate of the region to iterate
|
||||
* @wrap_x: The wrap mode for the x-axis (Only
|
||||
* %COGL_PIPELINE_WRAP_MODE_REPEAT may be passed here.)
|
||||
* @wrap_y: The wrap mode for the y-axis (Only
|
||||
* %COGL_PIPELINE_WRAP_MODE_REPEAT may be passed here.)
|
||||
* @callback: A #CoglMetaTextureCallback pointer to be called
|
||||
* for each low-level texture within the specified region.
|
||||
* @user_data: A private pointer that is passed to @callback.
|
||||
*
|
||||
* Allows you to manually iterate the low-level textures that define a
|
||||
* given region of a high-level #CoglMetaTexture.
|
||||
*
|
||||
* For example cogl_texture_2d_sliced_new_with_size() can be used to
|
||||
* create a meta texture that may slice a large image into multiple,
|
||||
* smaller power-of-two sized textures. These high level textures are
|
||||
* not directly understood by a GPU and so this API must be used to
|
||||
* manually resolve the underlying textures for drawing.
|
||||
*
|
||||
* All high level textures (#CoglAtlasTexture, #CoglSubTexture,
|
||||
* #CoglTexturePixmapX11, and #CoglTexture2DSliced) can be handled
|
||||
* consistently using this interface which greately simplifies
|
||||
* implementing primitives that support all texture types.
|
||||
*
|
||||
* For example if you use the cogl_rectangle() API then Cogl will
|
||||
* internally use this API to resolve the low level textures of any
|
||||
* meta textures you have associated with CoglPipeline layers.
|
||||
*
|
||||
* <note>The low level drawing APIs such as cogl_draw_attributes()
|
||||
* don't understand the #CoglMetaTexture interface and so it is your
|
||||
* responsibility to use this API to resolve all CoglPipeline
|
||||
* textures into low-level textures before drawing.</note>
|
||||
*
|
||||
* For each low-level texture that makes up part of the given region
|
||||
* of the @meta_texture, @callback is called specifying how the
|
||||
* low-level texture maps to the original region.
|
||||
*
|
||||
* <note>Currently this interface can only be used to iterate in terms
|
||||
* of %COGL_PIPELINE_WRAP_MODE_REPEAT) which means if you want to
|
||||
* support %COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE for a custom
|
||||
* primitive then you need to do that manually by using this interface
|
||||
* to find edge textures and then stretching the edge texels out using
|
||||
* geometry.</note>
|
||||
*
|
||||
* Since: 1.10
|
||||
* Stability: unstable
|
||||
*/
|
||||
void
|
||||
cogl_meta_texture_foreach_in_region (CoglMetaTexture *meta_texture,
|
||||
float tx_1,
|
||||
float ty_1,
|
||||
float tx_2,
|
||||
float ty_2,
|
||||
CoglPipelineWrapMode wrap_s,
|
||||
CoglPipelineWrapMode wrap_t,
|
||||
CoglMetaTextureCallback callback,
|
||||
void *user_data);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __COGL_META_TEXTURE_H__ */
|
@ -37,6 +37,7 @@
|
||||
#include "cogl-framebuffer-private.h"
|
||||
#include "cogl-attribute-private.h"
|
||||
#include "cogl-private.h"
|
||||
#include "cogl-meta-texture.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
@ -139,6 +140,8 @@ validate_first_layer_cb (CoglPipeline *pipeline,
|
||||
ValidateFirstLayerState *state = user_data;
|
||||
CoglPipelineWrapMode clamp_to_edge =
|
||||
COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE;
|
||||
CoglPipelineWrapMode wrap_s;
|
||||
CoglPipelineWrapMode wrap_t;
|
||||
|
||||
/* We can't use hardware repeat so we need to set clamp to edge
|
||||
* otherwise it might pull in edge pixels from the other side. By
|
||||
@ -184,15 +187,16 @@ validate_first_layer_cb (CoglPipeline *pipeline,
|
||||
*/
|
||||
/* TODO: support multitexturing */
|
||||
static void
|
||||
_cogl_texture_quad_multiple_primitives (CoglTexture *texture,
|
||||
_cogl_texture_quad_multiple_primitives (CoglTexture *texture,
|
||||
CoglPipeline *pipeline,
|
||||
gboolean clamp_s,
|
||||
gboolean clamp_t,
|
||||
const float *position,
|
||||
float tx_1,
|
||||
float ty_1,
|
||||
float tx_2,
|
||||
float ty_2)
|
||||
int layer_index,
|
||||
gboolean check_clamp_s,
|
||||
gboolean check_clamp_t,
|
||||
const float *position,
|
||||
float tx_1,
|
||||
float ty_1,
|
||||
float tx_2,
|
||||
float ty_2)
|
||||
{
|
||||
TextureSlicedQuadState state;
|
||||
gboolean tex_virtual_flipped_x;
|
||||
@ -200,12 +204,17 @@ _cogl_texture_quad_multiple_primitives (CoglTexture *texture,
|
||||
gboolean quad_flipped_x;
|
||||
gboolean quad_flipped_y;
|
||||
ValidateFirstLayerState validate_first_layer_state;
|
||||
CoglPipelineWrapMode wrap_s, wrap_t;
|
||||
|
||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||
|
||||
wrap_s = cogl_pipeline_get_layer_wrap_mode_s (pipeline, layer_index);
|
||||
wrap_t = cogl_pipeline_get_layer_wrap_mode_t (pipeline, layer_index);
|
||||
|
||||
/* If the wrap mode is clamp to edge then we'll recursively draw the
|
||||
stretched part and replace the coordinates */
|
||||
if (clamp_s && tx_1 != tx_2)
|
||||
if (check_clamp_s &&
|
||||
wrap_s == COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE && tx_1 != tx_2)
|
||||
{
|
||||
float *replacement_position = g_newa (float, 4);
|
||||
float old_tx_1 = tx_1, old_tx_2 = tx_2;
|
||||
@ -225,7 +234,8 @@ _cogl_texture_quad_multiple_primitives (CoglTexture *texture,
|
||||
(tx_1 - old_tx_1) / (old_tx_2 - old_tx_1)),
|
||||
position[3] };
|
||||
_cogl_texture_quad_multiple_primitives (texture, pipeline,
|
||||
FALSE, clamp_t,
|
||||
layer_index,
|
||||
FALSE, TRUE,
|
||||
tmp_position,
|
||||
tx_1, ty_1, tx_1, ty_2);
|
||||
replacement_position[0] = tmp_position[2];
|
||||
@ -240,7 +250,8 @@ _cogl_texture_quad_multiple_primitives (CoglTexture *texture,
|
||||
(tx_2 - old_tx_1) / (old_tx_2 - old_tx_1)),
|
||||
position[1], position[2], position[3] };
|
||||
_cogl_texture_quad_multiple_primitives (texture, pipeline,
|
||||
FALSE, clamp_t,
|
||||
layer_index,
|
||||
FALSE, TRUE,
|
||||
tmp_position,
|
||||
tx_2, ty_1, tx_2, ty_2);
|
||||
replacement_position[2] = tmp_position[0];
|
||||
@ -253,7 +264,8 @@ _cogl_texture_quad_multiple_primitives (CoglTexture *texture,
|
||||
position = replacement_position;
|
||||
}
|
||||
|
||||
if (clamp_t && ty_1 != ty_2)
|
||||
if (check_clamp_t &&
|
||||
wrap_t == COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE && ty_1 != ty_2)
|
||||
{
|
||||
float *replacement_position = g_newa (float, 4);
|
||||
float old_ty_1 = ty_1, old_ty_2 = ty_2;
|
||||
@ -272,7 +284,8 @@ _cogl_texture_quad_multiple_primitives (CoglTexture *texture,
|
||||
(position[3] - position[1]) *
|
||||
(ty_1 - old_ty_1) / (old_ty_2 - old_ty_1)) };
|
||||
_cogl_texture_quad_multiple_primitives (texture, pipeline,
|
||||
clamp_s, FALSE,
|
||||
layer_index,
|
||||
TRUE, FALSE,
|
||||
tmp_position,
|
||||
tx_1, ty_1, tx_2, ty_1);
|
||||
replacement_position[1] = tmp_position[3];
|
||||
@ -288,7 +301,8 @@ _cogl_texture_quad_multiple_primitives (CoglTexture *texture,
|
||||
(ty_2 - old_ty_1) / (old_ty_2 - old_ty_1)),
|
||||
position[2], position[3] };
|
||||
_cogl_texture_quad_multiple_primitives (texture, pipeline,
|
||||
clamp_s, FALSE,
|
||||
layer_index,
|
||||
TRUE, FALSE,
|
||||
tmp_position,
|
||||
tx_1, ty_2, tx_2, ty_2);
|
||||
replacement_position[3] = tmp_position[1];
|
||||
@ -354,10 +368,23 @@ _cogl_texture_quad_multiple_primitives (CoglTexture *texture,
|
||||
state.v_to_q_scale_x = fabs (state.quad_len_x / (tx_2 - tx_1));
|
||||
state.v_to_q_scale_y = fabs (state.quad_len_y / (ty_2 - ty_1));
|
||||
|
||||
_cogl_texture_foreach_sub_texture_in_region (texture,
|
||||
tx_1, ty_1, tx_2, ty_2,
|
||||
log_quad_sub_textures_cb,
|
||||
&state);
|
||||
/* cogl_meta_texture_foreach_in_region only allows WRAP_MODE_REPEAT.
|
||||
* If CLAMP_TO_EDGE is in use then we have already dealt with
|
||||
* emulation for that and we can just pass WRAP_MODE_REPEAT here...
|
||||
*/
|
||||
if (wrap_s == COGL_PIPELINE_WRAP_MODE_AUTOMATIC ||
|
||||
wrap_s == COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE)
|
||||
wrap_s = COGL_PIPELINE_WRAP_MODE_REPEAT;
|
||||
if (wrap_t == COGL_PIPELINE_WRAP_MODE_AUTOMATIC ||
|
||||
wrap_t == COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE)
|
||||
wrap_t = COGL_PIPELINE_WRAP_MODE_REPEAT;
|
||||
|
||||
cogl_meta_texture_foreach_in_region (COGL_META_TEXTURE (texture),
|
||||
tx_1, ty_1, tx_2, ty_2,
|
||||
wrap_s,
|
||||
wrap_t,
|
||||
log_quad_sub_textures_cb,
|
||||
&state);
|
||||
|
||||
if (validate_first_layer_state.override_pipeline)
|
||||
cogl_object_unref (validate_first_layer_state.override_pipeline);
|
||||
@ -760,7 +787,6 @@ _cogl_rectangles_with_multitexture_coords (
|
||||
CoglTexture *texture;
|
||||
const float default_tex_coords[4] = {0.0, 0.0, 1.0, 1.0};
|
||||
const float *tex_coords;
|
||||
gboolean clamp_s, clamp_t;
|
||||
|
||||
if (!state.all_use_sliced_quad_fallback)
|
||||
{
|
||||
@ -788,18 +814,12 @@ _cogl_rectangles_with_multitexture_coords (
|
||||
else
|
||||
tex_coords = default_tex_coords;
|
||||
|
||||
clamp_s = (cogl_pipeline_get_layer_wrap_mode_s (pipeline,
|
||||
state.first_layer) ==
|
||||
COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
|
||||
clamp_t = (cogl_pipeline_get_layer_wrap_mode_t (pipeline,
|
||||
state.first_layer) ==
|
||||
COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
|
||||
|
||||
COGL_NOTE (DRAW, "Drawing Tex Quad (Multi-Prim Mode)");
|
||||
|
||||
_cogl_texture_quad_multiple_primitives (texture,
|
||||
pipeline,
|
||||
clamp_s, clamp_t,
|
||||
state.first_layer,
|
||||
TRUE, TRUE,
|
||||
rects[i].position,
|
||||
tex_coords[0],
|
||||
tex_coords[1],
|
||||
|
@ -35,7 +35,7 @@ void
|
||||
_cogl_span_iter_update (CoglSpanIter *iter)
|
||||
{
|
||||
/* Pick current span */
|
||||
iter->span = &g_array_index (iter->array, CoglSpan, iter->index);
|
||||
iter->span = &iter->spans[iter->index];
|
||||
|
||||
/* Offset next position by span size */
|
||||
iter->next_pos = iter->pos + iter->span->size - iter->span->waste;
|
||||
@ -66,17 +66,24 @@ _cogl_span_iter_update (CoglSpanIter *iter)
|
||||
|
||||
void
|
||||
_cogl_span_iter_begin (CoglSpanIter *iter,
|
||||
GArray *spans,
|
||||
float normalize_factor,
|
||||
float cover_start,
|
||||
float cover_end)
|
||||
const CoglSpan *spans,
|
||||
int n_spans,
|
||||
float normalize_factor,
|
||||
float cover_start,
|
||||
float cover_end,
|
||||
CoglPipelineWrapMode wrap_mode)
|
||||
{
|
||||
float cover_start_normalized;
|
||||
|
||||
/* XXX: If CLAMP_TO_EDGE needs to be emulated then it needs to be
|
||||
* done at a higher level than here... */
|
||||
g_return_if_fail (wrap_mode == COGL_PIPELINE_WRAP_MODE_REPEAT);
|
||||
|
||||
iter->index = 0;
|
||||
iter->span = NULL;
|
||||
|
||||
iter->array = spans;
|
||||
iter->spans = spans;
|
||||
iter->n_spans = n_spans;
|
||||
|
||||
/* We always iterate in a positive direction from the origin. If
|
||||
* iter->flipped == TRUE that means whoever is using this API should
|
||||
@ -100,6 +107,8 @@ _cogl_span_iter_begin (CoglSpanIter *iter,
|
||||
cover_start_normalized = cover_start / normalize_factor;
|
||||
iter->origin = floorf (cover_start_normalized) * normalize_factor;
|
||||
|
||||
iter->wrap_mode = wrap_mode;
|
||||
|
||||
iter->cover_start = cover_start;
|
||||
iter->cover_end = cover_end;
|
||||
iter->pos = iter->origin;
|
||||
@ -117,8 +126,7 @@ _cogl_span_iter_next (CoglSpanIter *iter)
|
||||
/* Move current position */
|
||||
iter->pos = iter->next_pos;
|
||||
|
||||
/* Pick next slice (wrap when last reached) */
|
||||
iter->index = (iter->index + 1) % iter->array->len;
|
||||
iter->index = (iter->index + 1) % iter->n_spans;
|
||||
|
||||
/* Update intersection */
|
||||
_cogl_span_iter_update (iter);
|
||||
|
@ -25,6 +25,7 @@
|
||||
#define __COGL_SPANS_PRIVATE_H
|
||||
|
||||
#include "cogl-handle.h"
|
||||
#include "cogl-pipeline-layer-state.h"
|
||||
|
||||
typedef struct _CoglSpan
|
||||
{
|
||||
@ -35,18 +36,20 @@ typedef struct _CoglSpan
|
||||
|
||||
typedef struct _CoglSpanIter
|
||||
{
|
||||
int index;
|
||||
GArray *array;
|
||||
CoglSpan *span;
|
||||
float pos;
|
||||
float next_pos;
|
||||
float origin;
|
||||
float cover_start;
|
||||
float cover_end;
|
||||
float intersect_start;
|
||||
float intersect_end;
|
||||
gboolean intersects;
|
||||
gboolean flipped;
|
||||
int index;
|
||||
const CoglSpan *spans;
|
||||
int n_spans;
|
||||
const CoglSpan *span;
|
||||
float pos;
|
||||
float next_pos;
|
||||
float origin;
|
||||
float cover_start;
|
||||
float cover_end;
|
||||
float intersect_start;
|
||||
float intersect_end;
|
||||
gboolean intersects;
|
||||
gboolean flipped;
|
||||
CoglPipelineWrapMode wrap_mode;
|
||||
} CoglSpanIter;
|
||||
|
||||
void
|
||||
@ -54,10 +57,12 @@ _cogl_span_iter_update (CoglSpanIter *iter);
|
||||
|
||||
void
|
||||
_cogl_span_iter_begin (CoglSpanIter *iter,
|
||||
GArray *spans,
|
||||
float normalize_factor,
|
||||
float cover_start,
|
||||
float cover_end);
|
||||
const CoglSpan *spans,
|
||||
int n_spans,
|
||||
float normalize_factor,
|
||||
float cover_start,
|
||||
float cover_end,
|
||||
CoglPipelineWrapMode wrap_mode);
|
||||
|
||||
void
|
||||
_cogl_span_iter_next (CoglSpanIter *iter);
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include "cogl-context-private.h"
|
||||
#include "cogl-handle.h"
|
||||
#include "cogl-texture-driver.h"
|
||||
#include "cogl-texture-rectangle-private.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
@ -47,157 +48,90 @@ COGL_TEXTURE_INTERNAL_DEFINE (SubTexture, sub_texture);
|
||||
static const CoglTextureVtable cogl_sub_texture_vtable;
|
||||
|
||||
static void
|
||||
_cogl_sub_texture_map_range (float *t1, float *t2,
|
||||
int sub_offset,
|
||||
int sub_size,
|
||||
int full_size)
|
||||
_cogl_sub_texture_unmap_quad (CoglSubTexture *sub_tex,
|
||||
float *coords)
|
||||
{
|
||||
float t1_frac, t1_int, t2_frac, t2_int;
|
||||
|
||||
t1_frac = modff (*t1, &t1_int);
|
||||
t2_frac = modff (*t2, &t2_int);
|
||||
|
||||
if (t1_frac < 0.0f)
|
||||
/* NB: coords[] come in as non-normalized if sub_tex->full_texture
|
||||
* is a CoglTextureRectangle otherwhise they are normalized. The
|
||||
* coordinates we write out though must always be normalized.
|
||||
*
|
||||
* NB: sub_tex->sub_x/y/width/height are in non-normalized
|
||||
* coordinates.
|
||||
*/
|
||||
if (_cogl_is_texture_rectangle (sub_tex->full_texture))
|
||||
{
|
||||
t1_frac += 1.0f;
|
||||
t1_int -= 1.0f;
|
||||
}
|
||||
if (t2_frac < 0.0f)
|
||||
{
|
||||
t2_frac += 1.0f;
|
||||
t2_int -= 1.0f;
|
||||
}
|
||||
|
||||
/* If one of the coordinates is zero we need to make sure it is
|
||||
still greater than the other coordinate if it was originally so
|
||||
we'll flip it to the other side */
|
||||
if (*t1 < *t2)
|
||||
{
|
||||
if (t2_frac == 0.0f)
|
||||
{
|
||||
t2_frac = 1.0f;
|
||||
t2_int -= 1.0f;
|
||||
}
|
||||
coords[0] = (coords[0] - sub_tex->sub_x) / sub_tex->sub_width;
|
||||
coords[1] = (coords[1] - sub_tex->sub_y) / sub_tex->sub_height;
|
||||
coords[2] = (coords[2] - sub_tex->sub_x) / sub_tex->sub_width;
|
||||
coords[3] = (coords[3] - sub_tex->sub_y) / sub_tex->sub_height;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (t1_frac == 0.0f)
|
||||
{
|
||||
t1_frac = 1.0f;
|
||||
t1_int -= 1.0f;
|
||||
}
|
||||
float width = cogl_texture_get_width (sub_tex->full_texture);
|
||||
float height = cogl_texture_get_height (sub_tex->full_texture);
|
||||
coords[0] = (coords[0] * width - sub_tex->sub_x) / sub_tex->sub_width;
|
||||
coords[1] = (coords[1] * height - sub_tex->sub_y) / sub_tex->sub_height;
|
||||
coords[2] = (coords[2] * width - sub_tex->sub_x) / sub_tex->sub_width;
|
||||
coords[3] = (coords[3] * height - sub_tex->sub_y) / sub_tex->sub_height;
|
||||
}
|
||||
|
||||
/* Convert the fractional part leaving the integer part intact */
|
||||
t1_frac = (sub_offset + t1_frac * sub_size) / full_size;
|
||||
*t1 = t1_frac + t1_int;
|
||||
|
||||
t2_frac = (sub_offset + t2_frac * sub_size) / full_size;
|
||||
*t2 = t2_frac + t2_int;
|
||||
}
|
||||
|
||||
static void
|
||||
_cogl_sub_texture_map_quad (CoglSubTexture *sub_tex,
|
||||
float *coords)
|
||||
{
|
||||
unsigned int full_width = cogl_texture_get_width (sub_tex->full_texture);
|
||||
unsigned int full_height = cogl_texture_get_height (sub_tex->full_texture);
|
||||
/* NB: coords[] always come in as normalized coordinates but may go
|
||||
* out as non-normalized if sub_tex->full_texture is a
|
||||
* CoglTextureRectangle.
|
||||
*
|
||||
* NB: sub_tex->sub_x/y/width/height are in non-normalized
|
||||
* coordinates.
|
||||
*/
|
||||
|
||||
_cogl_sub_texture_map_range (coords + 0, coords + 2,
|
||||
sub_tex->sub_x, sub_tex->sub_width,
|
||||
full_width);
|
||||
_cogl_sub_texture_map_range (coords + 1, coords + 3,
|
||||
sub_tex->sub_y, sub_tex->sub_height,
|
||||
full_height);
|
||||
}
|
||||
|
||||
/* Maps from the texture coordinates of the full texture to the
|
||||
texture coordinates of the sub texture */
|
||||
static float
|
||||
_cogl_sub_texture_unmap_coord (float t,
|
||||
int sub_offset,
|
||||
int sub_size,
|
||||
int full_size)
|
||||
{
|
||||
float frac_part, int_part;
|
||||
|
||||
/* Convert the fractional part leaving the integer part in tact */
|
||||
frac_part = modff (t, &int_part);
|
||||
|
||||
if (cogl_util_float_signbit (frac_part))
|
||||
frac_part = ((1.0f + frac_part) * full_size -
|
||||
sub_offset - sub_size) / sub_size;
|
||||
if (_cogl_is_texture_rectangle (sub_tex->full_texture))
|
||||
{
|
||||
coords[0] = coords[0] * sub_tex->sub_width + sub_tex->sub_x;
|
||||
coords[1] = coords[1] * sub_tex->sub_height + sub_tex->sub_y;
|
||||
coords[2] = coords[2] * sub_tex->sub_width + sub_tex->sub_x;
|
||||
coords[3] = coords[3] * sub_tex->sub_height + sub_tex->sub_y;
|
||||
}
|
||||
else
|
||||
frac_part = (frac_part * full_size - sub_offset) / sub_size;
|
||||
|
||||
return frac_part + int_part;
|
||||
}
|
||||
|
||||
static void
|
||||
_cogl_sub_texture_unmap_coords (CoglSubTexture *sub_tex,
|
||||
float *s,
|
||||
float *t)
|
||||
{
|
||||
unsigned int full_width = cogl_texture_get_width (sub_tex->full_texture);
|
||||
unsigned int full_height = cogl_texture_get_height (sub_tex->full_texture);
|
||||
|
||||
*s = _cogl_sub_texture_unmap_coord (*s, sub_tex->sub_x, sub_tex->sub_width,
|
||||
full_width);
|
||||
*t = _cogl_sub_texture_unmap_coord (*t, sub_tex->sub_y, sub_tex->sub_height,
|
||||
full_height);
|
||||
{
|
||||
float width = cogl_texture_get_width (sub_tex->full_texture);
|
||||
float height = cogl_texture_get_height (sub_tex->full_texture);
|
||||
coords[0] = (coords[0] * sub_tex->sub_width + sub_tex->sub_x) / width;
|
||||
coords[1] = (coords[1] * sub_tex->sub_height + sub_tex->sub_y) / height;
|
||||
coords[2] = (coords[2] * sub_tex->sub_width + sub_tex->sub_x) / width;
|
||||
coords[3] = (coords[3] * sub_tex->sub_height + sub_tex->sub_y) / height;
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct _CoglSubTextureForeachData
|
||||
{
|
||||
CoglSubTexture *sub_tex;
|
||||
CoglTextureSliceCallback callback;
|
||||
CoglMetaTextureCallback callback;
|
||||
void *user_data;
|
||||
} CoglSubTextureForeachData;
|
||||
|
||||
static void
|
||||
_cogl_sub_texture_foreach_cb (CoglTexture *texture,
|
||||
const float *slice_coords,
|
||||
const float *full_virtual_coords,
|
||||
void *user_data)
|
||||
unmap_coords_cb (CoglTexture *slice_texture,
|
||||
const float *slice_texture_coords,
|
||||
const float *meta_coords,
|
||||
void *user_data)
|
||||
{
|
||||
CoglSubTextureForeachData *data = user_data;
|
||||
float virtual_coords[4];
|
||||
float unmapped_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_coords (data->sub_tex,
|
||||
&virtual_coords[0],
|
||||
&virtual_coords[1]);
|
||||
_cogl_sub_texture_unmap_coords (data->sub_tex,
|
||||
&virtual_coords[2],
|
||||
&virtual_coords[3]);
|
||||
memcpy (unmapped_coords, meta_coords, sizeof (unmapped_coords));
|
||||
|
||||
data->callback (texture,
|
||||
slice_coords, virtual_coords,
|
||||
_cogl_sub_texture_unmap_quad (data->sub_tex, unmapped_coords);
|
||||
|
||||
data->callback (slice_texture,
|
||||
slice_texture_coords,
|
||||
unmapped_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_quad (data->sub_tex, mapped_coords);
|
||||
|
||||
_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,
|
||||
@ -205,20 +139,46 @@ _cogl_sub_texture_foreach_sub_texture_in_region (
|
||||
float virtual_ty_1,
|
||||
float virtual_tx_2,
|
||||
float virtual_ty_2,
|
||||
CoglTextureSliceCallback callback,
|
||||
CoglMetaTextureCallback callback,
|
||||
void *user_data)
|
||||
{
|
||||
CoglSubTexture *sub_tex = COGL_SUB_TEXTURE (tex);
|
||||
CoglSubTextureForeachData data;
|
||||
CoglTexture *full_texture = sub_tex->full_texture;
|
||||
float mapped_coords[4] =
|
||||
{ virtual_tx_1, virtual_ty_1, virtual_tx_2, virtual_ty_2};
|
||||
float virtual_coords[4] =
|
||||
{ virtual_tx_1, virtual_ty_1, virtual_tx_2, virtual_ty_2};
|
||||
|
||||
data.sub_tex = sub_tex;
|
||||
data.callback = callback;
|
||||
data.user_data = user_data;
|
||||
/* map the virtual coordinates to ->full_texture coordinates */
|
||||
_cogl_sub_texture_map_quad (sub_tex, mapped_coords);
|
||||
|
||||
_cogl_texture_iterate_manual_repeats (_cogl_sub_texture_manual_repeat_cb,
|
||||
virtual_tx_1, virtual_ty_1,
|
||||
virtual_tx_2, virtual_ty_2,
|
||||
&data);
|
||||
/* TODO: Add something like cogl_is_low_level_texture() */
|
||||
if (cogl_is_texture_2d (full_texture) ||
|
||||
_cogl_is_texture_rectangle (full_texture))
|
||||
{
|
||||
callback (sub_tex->full_texture,
|
||||
mapped_coords,
|
||||
virtual_coords,
|
||||
user_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
CoglSubTextureForeachData data;
|
||||
|
||||
data.sub_tex = sub_tex;
|
||||
data.callback = callback;
|
||||
data.user_data = user_data;
|
||||
|
||||
cogl_meta_texture_foreach_in_region (COGL_META_TEXTURE (full_texture),
|
||||
mapped_coords[0],
|
||||
mapped_coords[1],
|
||||
mapped_coords[2],
|
||||
mapped_coords[3],
|
||||
COGL_PIPELINE_WRAP_MODE_REPEAT,
|
||||
COGL_PIPELINE_WRAP_MODE_REPEAT,
|
||||
unmap_coords_cb,
|
||||
&data);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -56,14 +56,33 @@ COGL_TEXTURE_DEFINE (Texture2DSliced, texture_2d_sliced);
|
||||
|
||||
static const CoglTextureVtable cogl_texture_2d_sliced_vtable;
|
||||
|
||||
/* 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
|
||||
* coordinates of slices are called "slice" coordinates. */
|
||||
/* This function lets you iterate all the slices that lie within the given
|
||||
* virtual coordinates of the parent sliced texture. */
|
||||
/* Note: no guarantee is given about the order in which the slices will be
|
||||
* visited */
|
||||
typedef struct _ForeachData
|
||||
{
|
||||
CoglMetaTextureCallback callback;
|
||||
void *user_data;
|
||||
float x_normalize_factor;
|
||||
float y_normalize_factor;
|
||||
} ForeachData;
|
||||
|
||||
static void
|
||||
re_normalize_sub_texture_coords_cb (CoglTexture *sub_texture,
|
||||
const float *sub_texture_coords,
|
||||
const float *meta_coords,
|
||||
void *user_data)
|
||||
{
|
||||
ForeachData *data = user_data;
|
||||
float re_normalized_coords[4] =
|
||||
{
|
||||
sub_texture_coords[0] * data->x_normalize_factor,
|
||||
sub_texture_coords[1] * data->y_normalize_factor,
|
||||
sub_texture_coords[2] * data->x_normalize_factor,
|
||||
sub_texture_coords[3] * data->y_normalize_factor
|
||||
};
|
||||
|
||||
data->callback (sub_texture, re_normalized_coords, meta_coords,
|
||||
data->user_data);
|
||||
}
|
||||
|
||||
static void
|
||||
_cogl_texture_2d_sliced_foreach_sub_texture_in_region (
|
||||
CoglTexture *tex,
|
||||
@ -71,103 +90,44 @@ _cogl_texture_2d_sliced_foreach_sub_texture_in_region (
|
||||
float virtual_ty_1,
|
||||
float virtual_tx_2,
|
||||
float virtual_ty_2,
|
||||
CoglTextureSliceCallback callback,
|
||||
CoglMetaTextureCallback callback,
|
||||
void *user_data)
|
||||
{
|
||||
CoglTexture2DSliced *tex_2ds = COGL_TEXTURE_2D_SLICED (tex);
|
||||
float width = tex_2ds->width;
|
||||
float height = tex_2ds->height;
|
||||
CoglSpanIter iter_x;
|
||||
CoglSpanIter iter_y;
|
||||
float slice_coords[4];
|
||||
CoglSpan *x_spans = (CoglSpan *)tex_2ds->slice_x_spans->data;
|
||||
CoglSpan *y_spans = (CoglSpan *)tex_2ds->slice_y_spans->data;
|
||||
CoglTexture **textures = (CoglTexture **)tex_2ds->slice_textures->data;
|
||||
float un_normalized_coords[4];
|
||||
ForeachData 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
|
||||
* virtual coordinates by the texture size to denormalize.
|
||||
/* NB: its convenient for us to store non-normalized coordinates in
|
||||
* our CoglSpans but that means we need to un-normalize the incoming
|
||||
* virtual coordinates and make sure we re-normalize the coordinates
|
||||
* before calling the given callback.
|
||||
*/
|
||||
/* XXX: I wonder if it's worth changing how we store spans so we can avoid
|
||||
* the need to denormalize here */
|
||||
virtual_tx_1 *= width;
|
||||
virtual_ty_1 *= height;
|
||||
virtual_tx_2 *= width;
|
||||
virtual_ty_2 *= height;
|
||||
|
||||
/* Iterate the y axis of the virtual rectangle */
|
||||
for (_cogl_span_iter_begin (&iter_y,
|
||||
tex_2ds->slice_y_spans,
|
||||
height,
|
||||
virtual_ty_1,
|
||||
virtual_ty_2);
|
||||
!_cogl_span_iter_end (&iter_y);
|
||||
_cogl_span_iter_next (&iter_y))
|
||||
{
|
||||
if (iter_y.flipped)
|
||||
{
|
||||
slice_coords[1] = iter_y.intersect_end;
|
||||
slice_coords[3] = iter_y.intersect_start;
|
||||
}
|
||||
else
|
||||
{
|
||||
slice_coords[1] = iter_y.intersect_start;
|
||||
slice_coords[3] = iter_y.intersect_end;
|
||||
}
|
||||
data.callback = callback;
|
||||
data.user_data = user_data;
|
||||
data.x_normalize_factor = 1.0f / tex_2ds->width;
|
||||
data.y_normalize_factor = 1.0f / tex_2ds->height;
|
||||
|
||||
/* Localize slice texture coordinates */
|
||||
slice_coords[1] -= iter_y.pos;
|
||||
slice_coords[3] -= iter_y.pos;
|
||||
un_normalized_coords[0] = virtual_tx_1 * data.x_normalize_factor;
|
||||
un_normalized_coords[1] = virtual_ty_1 * data.y_normalize_factor;
|
||||
un_normalized_coords[2] = virtual_tx_2 * data.x_normalize_factor;
|
||||
un_normalized_coords[3] = virtual_ty_2 * data.y_normalize_factor;
|
||||
|
||||
/* Normalize slice texture coordinates */
|
||||
slice_coords[1] /= iter_y.span->size;
|
||||
slice_coords[3] /= iter_y.span->size;
|
||||
|
||||
/* Iterate the x axis of the virtual rectangle */
|
||||
for (_cogl_span_iter_begin (&iter_x,
|
||||
tex_2ds->slice_x_spans,
|
||||
width,
|
||||
virtual_tx_1,
|
||||
virtual_tx_2);
|
||||
!_cogl_span_iter_end (&iter_x);
|
||||
_cogl_span_iter_next (&iter_x))
|
||||
{
|
||||
CoglTexture2D *slice_tex;
|
||||
float normalized_virtual_coords[4];
|
||||
|
||||
if (iter_x.flipped)
|
||||
{
|
||||
slice_coords[0] = iter_x.intersect_end;
|
||||
slice_coords[2] = iter_x.intersect_start;
|
||||
}
|
||||
else
|
||||
{
|
||||
slice_coords[0] = iter_x.intersect_start;
|
||||
slice_coords[2] = iter_x.intersect_end;
|
||||
}
|
||||
|
||||
/* Localize slice texture coordinates */
|
||||
slice_coords[0] -= iter_x.pos;
|
||||
slice_coords[2] -= iter_x.pos;
|
||||
|
||||
/* Normalize slice texture coordinates */
|
||||
slice_coords[0] /= iter_x.span->size;
|
||||
slice_coords[2] /= iter_x.span->size;
|
||||
|
||||
/* Pluck out the cogl texture for this slice */
|
||||
slice_tex = g_array_index (tex_2ds->slice_textures, CoglTexture2D *,
|
||||
iter_y.index *
|
||||
tex_2ds->slice_x_spans->len +
|
||||
iter_x.index);
|
||||
|
||||
normalized_virtual_coords[0] = iter_x.intersect_start / width;
|
||||
normalized_virtual_coords[1] = iter_y.intersect_start / height;
|
||||
normalized_virtual_coords[2] = iter_x.intersect_end / width;
|
||||
normalized_virtual_coords[3] = iter_y.intersect_end / height;
|
||||
|
||||
callback (COGL_TEXTURE (slice_tex),
|
||||
slice_coords,
|
||||
normalized_virtual_coords,
|
||||
user_data);
|
||||
}
|
||||
}
|
||||
_cogl_texture_spans_foreach_in_region (x_spans,
|
||||
tex_2ds->slice_x_spans->len,
|
||||
y_spans,
|
||||
tex_2ds->slice_y_spans->len,
|
||||
textures,
|
||||
un_normalized_coords,
|
||||
1, /* x_normalize_factor */
|
||||
1, /* y_normalize_factor */
|
||||
COGL_PIPELINE_WRAP_MODE_REPEAT,
|
||||
COGL_PIPELINE_WRAP_MODE_REPEAT,
|
||||
re_normalize_sub_texture_coords_cb,
|
||||
&data);
|
||||
}
|
||||
|
||||
static guint8 *
|
||||
@ -455,10 +415,12 @@ _cogl_texture_2d_sliced_upload_subregion_to_gl (CoglTexture2DSliced *tex_2ds,
|
||||
/* Iterate vertical spans */
|
||||
for (source_y = src_y,
|
||||
_cogl_span_iter_begin (&y_iter,
|
||||
tex_2ds->slice_y_spans,
|
||||
(CoglSpan *)tex_2ds->slice_y_spans->data,
|
||||
tex_2ds->slice_y_spans->len,
|
||||
tex_2ds->height,
|
||||
dst_y,
|
||||
dst_y + height);
|
||||
dst_y + height,
|
||||
COGL_PIPELINE_WRAP_MODE_REPEAT);
|
||||
|
||||
!_cogl_span_iter_end (&y_iter);
|
||||
|
||||
@ -471,10 +433,12 @@ _cogl_texture_2d_sliced_upload_subregion_to_gl (CoglTexture2DSliced *tex_2ds,
|
||||
/* Iterate horizontal spans */
|
||||
for (source_x = src_x,
|
||||
_cogl_span_iter_begin (&x_iter,
|
||||
tex_2ds->slice_x_spans,
|
||||
(CoglSpan *)tex_2ds->slice_x_spans->data,
|
||||
tex_2ds->slice_x_spans->len,
|
||||
tex_2ds->width,
|
||||
dst_x,
|
||||
dst_x + width);
|
||||
dst_x + width,
|
||||
COGL_PIPELINE_WRAP_MODE_REPEAT);
|
||||
|
||||
!_cogl_span_iter_end (&x_iter);
|
||||
|
||||
|
@ -57,77 +57,10 @@ static const CoglTextureVtable cogl_texture_2d_vtable;
|
||||
typedef struct _CoglTexture2DManualRepeatData
|
||||
{
|
||||
CoglTexture2D *tex_2d;
|
||||
CoglTextureSliceCallback callback;
|
||||
CoglMetaTextureCallback callback;
|
||||
void *user_data;
|
||||
} CoglTexture2DManualRepeatData;
|
||||
|
||||
static void
|
||||
_cogl_texture_2d_wrap_coords (float t_1, float t_2,
|
||||
float *out_t_1, float *out_t_2)
|
||||
{
|
||||
float int_part;
|
||||
|
||||
/* Wrap t_1 and t_2 to the range [0,1] */
|
||||
|
||||
modff (t_1 < t_2 ? t_1 : t_2, &int_part);
|
||||
t_1 -= int_part;
|
||||
t_2 -= int_part;
|
||||
if (cogl_util_float_signbit (int_part))
|
||||
{
|
||||
*out_t_1 = 1.0f + t_1;
|
||||
*out_t_2 = 1.0f + t_2;
|
||||
}
|
||||
else
|
||||
{
|
||||
*out_t_1 = t_1;
|
||||
*out_t_2 = t_2;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_cogl_texture_2d_manual_repeat_cb (const float *coords,
|
||||
void *user_data)
|
||||
{
|
||||
CoglTexture2DManualRepeatData *data = user_data;
|
||||
float slice_coords[4];
|
||||
|
||||
_cogl_texture_2d_wrap_coords (coords[0], coords[2],
|
||||
slice_coords + 0, slice_coords + 2);
|
||||
_cogl_texture_2d_wrap_coords (coords[1], coords[3],
|
||||
slice_coords + 1, slice_coords + 3);
|
||||
|
||||
data->callback (COGL_TEXTURE (data->tex_2d),
|
||||
slice_coords,
|
||||
coords,
|
||||
data->user_data);
|
||||
}
|
||||
|
||||
static void
|
||||
_cogl_texture_2d_foreach_sub_texture_in_region (
|
||||
CoglTexture *tex,
|
||||
float virtual_tx_1,
|
||||
float virtual_ty_1,
|
||||
float virtual_tx_2,
|
||||
float virtual_ty_2,
|
||||
CoglTextureSliceCallback callback,
|
||||
void *user_data)
|
||||
{
|
||||
CoglTexture2D *tex_2d = COGL_TEXTURE_2D (tex);
|
||||
CoglTexture2DManualRepeatData data;
|
||||
|
||||
data.tex_2d = tex_2d;
|
||||
data.callback = callback;
|
||||
data.user_data = user_data;
|
||||
|
||||
/* We need to implement manual repeating because if Cogl is calling
|
||||
this function then it will set the wrap mode to GL_CLAMP_TO_EDGE
|
||||
and hardware repeating can't be done */
|
||||
_cogl_texture_iterate_manual_repeats (_cogl_texture_2d_manual_repeat_cb,
|
||||
virtual_tx_1, virtual_ty_1,
|
||||
virtual_tx_2, virtual_ty_2,
|
||||
&data);
|
||||
}
|
||||
|
||||
static void
|
||||
_cogl_texture_2d_set_wrap_mode_parameters (CoglTexture *tex,
|
||||
GLenum wrap_mode_s,
|
||||
@ -923,7 +856,7 @@ cogl_texture_2d_vtable =
|
||||
{
|
||||
_cogl_texture_2d_set_region,
|
||||
_cogl_texture_2d_get_data,
|
||||
_cogl_texture_2d_foreach_sub_texture_in_region,
|
||||
NULL, /* foreach_sub_texture_in_region */
|
||||
_cogl_texture_2d_get_max_waste,
|
||||
_cogl_texture_2d_is_sliced,
|
||||
_cogl_texture_2d_can_hardware_repeat,
|
||||
|
@ -55,80 +55,6 @@ COGL_TEXTURE_DEFINE (Texture3D, texture_3d);
|
||||
|
||||
static const CoglTextureVtable cogl_texture_3d_vtable;
|
||||
|
||||
typedef struct _CoglTexture3DManualRepeatData
|
||||
{
|
||||
CoglTexture3D *tex_3d;
|
||||
CoglTextureSliceCallback callback;
|
||||
void *user_data;
|
||||
} CoglTexture3DManualRepeatData;
|
||||
|
||||
static void
|
||||
_cogl_texture_3d_wrap_coords (float t_1, float t_2,
|
||||
float *out_t_1, float *out_t_2)
|
||||
{
|
||||
float int_part;
|
||||
|
||||
/* Wrap t_1 and t_2 to the range [0,1] */
|
||||
|
||||
modff (t_1 < t_2 ? t_1 : t_2, &int_part);
|
||||
t_1 -= int_part;
|
||||
t_2 -= int_part;
|
||||
if (cogl_util_float_signbit (int_part))
|
||||
{
|
||||
*out_t_1 = 1.0f + t_1;
|
||||
*out_t_2 = 1.0f + t_2;
|
||||
}
|
||||
else
|
||||
{
|
||||
*out_t_1 = t_1;
|
||||
*out_t_2 = t_2;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_cogl_texture_3d_manual_repeat_cb (const float *coords,
|
||||
void *user_data)
|
||||
{
|
||||
CoglTexture3DManualRepeatData *data = user_data;
|
||||
float slice_coords[4];
|
||||
|
||||
_cogl_texture_3d_wrap_coords (coords[0], coords[2],
|
||||
slice_coords + 0, slice_coords + 2);
|
||||
_cogl_texture_3d_wrap_coords (coords[1], coords[3],
|
||||
slice_coords + 1, slice_coords + 3);
|
||||
|
||||
data->callback (COGL_TEXTURE (data->tex_3d),
|
||||
slice_coords,
|
||||
coords,
|
||||
data->user_data);
|
||||
}
|
||||
|
||||
static void
|
||||
_cogl_texture_3d_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)
|
||||
{
|
||||
CoglTexture3D *tex_3d = COGL_TEXTURE_3D (tex);
|
||||
CoglTexture3DManualRepeatData data;
|
||||
|
||||
data.tex_3d = tex_3d;
|
||||
data.callback = callback;
|
||||
data.user_data = user_data;
|
||||
|
||||
/* We need to implement manual repeating because if Cogl is calling
|
||||
this function then it will set the wrap mode to GL_CLAMP_TO_EDGE
|
||||
and hardware repeating can't be done */
|
||||
_cogl_texture_iterate_manual_repeats (_cogl_texture_3d_manual_repeat_cb,
|
||||
virtual_tx_1, virtual_ty_1,
|
||||
virtual_tx_2, virtual_ty_2,
|
||||
&data);
|
||||
}
|
||||
|
||||
static void
|
||||
_cogl_texture_3d_set_wrap_mode_parameters (CoglTexture *tex,
|
||||
GLenum wrap_mode_s,
|
||||
@ -671,7 +597,7 @@ cogl_texture_3d_vtable =
|
||||
{
|
||||
_cogl_texture_3d_set_region,
|
||||
_cogl_texture_3d_get_data,
|
||||
_cogl_texture_3d_foreach_sub_texture_in_region,
|
||||
NULL, /* foreach_sub_texture_in_region */
|
||||
_cogl_texture_3d_get_max_waste,
|
||||
_cogl_texture_3d_is_sliced,
|
||||
_cogl_texture_3d_can_hardware_repeat,
|
||||
|
@ -27,17 +27,10 @@
|
||||
#include "cogl-bitmap-private.h"
|
||||
#include "cogl-handle.h"
|
||||
#include "cogl-pipeline-private.h"
|
||||
#include "cogl-spans.h"
|
||||
|
||||
typedef struct _CoglTextureVtable CoglTextureVtable;
|
||||
|
||||
typedef void (*CoglTextureSliceCallback) (CoglTexture *texture,
|
||||
const float *slice_coords,
|
||||
const float *virtual_coords,
|
||||
void *user_data);
|
||||
|
||||
typedef void (* CoglTextureManualRepeatCallback) (const float *coords,
|
||||
void *user_data);
|
||||
|
||||
/* Encodes three possibiloities result of transforming a quad */
|
||||
typedef enum {
|
||||
/* quad doesn't cross the boundaries of a texture */
|
||||
@ -92,7 +85,7 @@ struct _CoglTextureVtable
|
||||
float virtual_ty_1,
|
||||
float virtual_tx_2,
|
||||
float virtual_ty_2,
|
||||
CoglTextureSliceCallback callback,
|
||||
CoglMetaTextureCallback callback,
|
||||
void *user_data);
|
||||
|
||||
int (* get_max_waste) (CoglTexture *tex);
|
||||
@ -189,15 +182,6 @@ _cogl_texture_register_texture_type (GQuark type);
|
||||
_cogl_texture_register_texture_type (_cogl_handle_ \
|
||||
## type_name ## _get_type ()))
|
||||
|
||||
void
|
||||
_cogl_texture_foreach_sub_texture_in_region (CoglTexture *texture,
|
||||
float virtual_tx_1,
|
||||
float virtual_ty_1,
|
||||
float virtual_tx_2,
|
||||
float virtual_ty_2,
|
||||
CoglTextureSliceCallback callback,
|
||||
void *user_data);
|
||||
|
||||
gboolean
|
||||
_cogl_texture_can_hardware_repeat (CoglTexture *texture);
|
||||
|
||||
@ -256,17 +240,6 @@ _cogl_texture_prep_gl_alignment_for_pixels_upload (int pixels_rowstride);
|
||||
void
|
||||
_cogl_texture_prep_gl_alignment_for_pixels_download (int pixels_rowstride);
|
||||
|
||||
/* Utility function for implementing manual repeating. Even texture
|
||||
backends that always support hardware repeating need this because
|
||||
when foreach_sub_texture_in_region is invoked Cogl will set the
|
||||
wrap mode to GL_CLAMP_TO_EDGE so hardware repeating can't be
|
||||
done */
|
||||
void
|
||||
_cogl_texture_iterate_manual_repeats (CoglTextureManualRepeatCallback callback,
|
||||
float tx_1, float ty_1,
|
||||
float tx_2, float ty_2,
|
||||
void *user_data);
|
||||
|
||||
/* Utility function to use as a fallback for getting the data of any
|
||||
texture via the framebuffer */
|
||||
|
||||
@ -289,4 +262,18 @@ _cogl_texture_get_associated_framebuffers (CoglTexture *texture);
|
||||
void
|
||||
_cogl_texture_flush_journal_rendering (CoglTexture *texture);
|
||||
|
||||
void
|
||||
_cogl_texture_spans_foreach_in_region (CoglSpan *x_spans,
|
||||
int n_x_spans,
|
||||
CoglSpan *y_spans,
|
||||
int n_y_spans,
|
||||
CoglTexture **textures,
|
||||
float *virtual_coords,
|
||||
float x_normalize_factor,
|
||||
float y_normalize_factor,
|
||||
CoglPipelineWrapMode wrap_x,
|
||||
CoglPipelineWrapMode wrap_y,
|
||||
CoglMetaTextureCallback callback,
|
||||
void *user_data);
|
||||
|
||||
#endif /* __COGL_TEXTURE_PRIVATE_H */
|
||||
|
@ -52,6 +52,9 @@ struct _CoglTextureRectangle
|
||||
gboolean is_foreign;
|
||||
};
|
||||
|
||||
gboolean
|
||||
_cogl_is_texture_rectangle (void *object);
|
||||
|
||||
GQuark
|
||||
_cogl_handle_texture_rectangle_get_type (void);
|
||||
|
||||
|
@ -59,85 +59,6 @@ COGL_TEXTURE_INTERNAL_DEFINE (TextureRectangle, texture_rectangle);
|
||||
|
||||
static const CoglTextureVtable cogl_texture_rectangle_vtable;
|
||||
|
||||
typedef struct _CoglTextureRectangleManualRepeatData
|
||||
{
|
||||
CoglTextureRectangle *tex_rect;
|
||||
CoglTextureSliceCallback callback;
|
||||
void *user_data;
|
||||
} CoglTextureRectangleManualRepeatData;
|
||||
|
||||
static void
|
||||
_cogl_texture_rectangle_wrap_coords (float t_1, float t_2,
|
||||
float *out_t_1, float *out_t_2)
|
||||
{
|
||||
float int_part;
|
||||
|
||||
/* Wrap t_1 and t_2 to the range [0,1] */
|
||||
|
||||
modff (t_1 < t_2 ? t_1 : t_2, &int_part);
|
||||
t_1 -= int_part;
|
||||
t_2 -= int_part;
|
||||
if (cogl_util_float_signbit (int_part))
|
||||
{
|
||||
*out_t_1 = 1.0f + t_1;
|
||||
*out_t_2 = 1.0f + t_2;
|
||||
}
|
||||
else
|
||||
{
|
||||
*out_t_1 = t_1;
|
||||
*out_t_2 = t_2;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_cogl_texture_rectangle_manual_repeat_cb (const float *coords,
|
||||
void *user_data)
|
||||
{
|
||||
CoglTextureRectangleManualRepeatData *data = user_data;
|
||||
float slice_coords[4];
|
||||
|
||||
_cogl_texture_rectangle_wrap_coords (coords[0], coords[2],
|
||||
slice_coords + 0, slice_coords + 2);
|
||||
_cogl_texture_rectangle_wrap_coords (coords[1], coords[3],
|
||||
slice_coords + 1, slice_coords + 3);
|
||||
|
||||
slice_coords[0] *= data->tex_rect->width;
|
||||
slice_coords[1] *= data->tex_rect->height;
|
||||
slice_coords[2] *= data->tex_rect->width;
|
||||
slice_coords[3] *= data->tex_rect->height;
|
||||
|
||||
data->callback (COGL_TEXTURE (data->tex_rect),
|
||||
slice_coords,
|
||||
coords,
|
||||
data->user_data);
|
||||
}
|
||||
|
||||
static void
|
||||
_cogl_texture_rectangle_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)
|
||||
{
|
||||
CoglTextureRectangle *tex_rect = COGL_TEXTURE_RECTANGLE (tex);
|
||||
CoglTextureRectangleManualRepeatData data;
|
||||
|
||||
data.tex_rect = tex_rect;
|
||||
data.callback = callback;
|
||||
data.user_data = user_data;
|
||||
|
||||
/* We need to implement manual repeating because if Cogl is calling
|
||||
this function then it will set the wrap mode to GL_CLAMP_TO_EDGE
|
||||
and hardware repeating can't be done */
|
||||
_cogl_texture_iterate_manual_repeats
|
||||
(_cogl_texture_rectangle_manual_repeat_cb,
|
||||
virtual_tx_1, virtual_ty_1, virtual_tx_2, virtual_ty_2,
|
||||
&data);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
can_use_wrap_mode (GLenum wrap_mode)
|
||||
{
|
||||
@ -653,7 +574,7 @@ cogl_texture_rectangle_vtable =
|
||||
{
|
||||
_cogl_texture_rectangle_set_region,
|
||||
_cogl_texture_rectangle_get_data,
|
||||
_cogl_texture_rectangle_foreach_sub_texture_in_region,
|
||||
NULL, /* foreach_sub_texture_in_region */
|
||||
_cogl_texture_rectangle_get_max_waste,
|
||||
_cogl_texture_rectangle_is_sliced,
|
||||
_cogl_texture_rectangle_can_hardware_repeat,
|
||||
|
@ -292,101 +292,6 @@ _cogl_texture_set_wrap_mode_parameters (CoglTexture *texture,
|
||||
wrap_mode_p);
|
||||
}
|
||||
|
||||
/* This is like CoglSpanIter except it deals with floats and it
|
||||
effectively assumes there is only one span from 0.0 to 1.0 */
|
||||
typedef struct _CoglTextureIter
|
||||
{
|
||||
float pos, end, next_pos;
|
||||
gboolean flipped;
|
||||
float t_1, t_2;
|
||||
} CoglTextureIter;
|
||||
|
||||
static void
|
||||
_cogl_texture_iter_update (CoglTextureIter *iter)
|
||||
{
|
||||
float t_2;
|
||||
float frac_part;
|
||||
|
||||
frac_part = modff (iter->pos, &iter->next_pos);
|
||||
|
||||
/* modff rounds the int part towards zero so we need to add one if
|
||||
we're meant to be heading away from zero */
|
||||
if (iter->pos >= 0.0f || frac_part == 0.0f)
|
||||
iter->next_pos += 1.0f;
|
||||
|
||||
if (iter->next_pos > iter->end)
|
||||
t_2 = iter->end;
|
||||
else
|
||||
t_2 = iter->next_pos;
|
||||
|
||||
if (iter->flipped)
|
||||
{
|
||||
iter->t_1 = t_2;
|
||||
iter->t_2 = iter->pos;
|
||||
}
|
||||
else
|
||||
{
|
||||
iter->t_1 = iter->pos;
|
||||
iter->t_2 = t_2;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_cogl_texture_iter_begin (CoglTextureIter *iter,
|
||||
float t_1, float t_2)
|
||||
{
|
||||
if (t_1 <= t_2)
|
||||
{
|
||||
iter->pos = t_1;
|
||||
iter->end = t_2;
|
||||
iter->flipped = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
iter->pos = t_2;
|
||||
iter->end = t_1;
|
||||
iter->flipped = TRUE;
|
||||
}
|
||||
|
||||
_cogl_texture_iter_update (iter);
|
||||
}
|
||||
|
||||
static void
|
||||
_cogl_texture_iter_next (CoglTextureIter *iter)
|
||||
{
|
||||
iter->pos = iter->next_pos;
|
||||
_cogl_texture_iter_update (iter);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_cogl_texture_iter_end (CoglTextureIter *iter)
|
||||
{
|
||||
return iter->pos >= iter->end;
|
||||
}
|
||||
|
||||
/* This invokes the callback with enough quads to cover the manually
|
||||
repeated range specified by the virtual texture coordinates without
|
||||
emitting coordinates outside the range [0,1] */
|
||||
void
|
||||
_cogl_texture_iterate_manual_repeats (CoglTextureManualRepeatCallback callback,
|
||||
float tx_1, float ty_1,
|
||||
float tx_2, float ty_2,
|
||||
void *user_data)
|
||||
{
|
||||
CoglTextureIter x_iter, y_iter;
|
||||
|
||||
for (_cogl_texture_iter_begin (&y_iter, ty_1, ty_2);
|
||||
!_cogl_texture_iter_end (&y_iter);
|
||||
_cogl_texture_iter_next (&y_iter))
|
||||
for (_cogl_texture_iter_begin (&x_iter, tx_1, tx_2);
|
||||
!_cogl_texture_iter_end (&x_iter);
|
||||
_cogl_texture_iter_next (&x_iter))
|
||||
{
|
||||
float coords[4] = { x_iter.t_1, y_iter.t_1, x_iter.t_2, y_iter.t_2 };
|
||||
callback (coords, user_data);
|
||||
}
|
||||
}
|
||||
|
||||
CoglTexture *
|
||||
cogl_texture_new_with_size (unsigned int width,
|
||||
unsigned int height,
|
||||
@ -527,6 +432,11 @@ cogl_texture_new_from_foreign (GLuint gl_handle,
|
||||
#if HAVE_COGL_GL
|
||||
if (gl_target == GL_TEXTURE_RECTANGLE_ARB)
|
||||
{
|
||||
CoglTextureRectangle *texture_rectangle;
|
||||
CoglSubTexture *sub_texture;
|
||||
|
||||
_COGL_GET_CONTEXT (ctx, COGL_INVALID_HANDLE);
|
||||
|
||||
if (x_pot_waste != 0 || y_pot_waste != 0)
|
||||
{
|
||||
/* It shouldn't be necessary to have waste in this case since
|
||||
@ -536,10 +446,17 @@ cogl_texture_new_from_foreign (GLuint gl_handle,
|
||||
return COGL_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
return _cogl_texture_rectangle_new_from_foreign (gl_handle,
|
||||
width,
|
||||
height,
|
||||
format);
|
||||
texture_rectangle = _cogl_texture_rectangle_new_from_foreign (gl_handle,
|
||||
width,
|
||||
height,
|
||||
format);
|
||||
/* CoglTextureRectangle textures work with non-normalized
|
||||
* coordinates, but the semantics for this function that people
|
||||
* depend on are that all returned texture works with normalized
|
||||
* coordinates so we wrap with a CoglSubTexture... */
|
||||
sub_texture = _cogl_sub_texture_new (COGL_TEXTURE (texture_rectangle),
|
||||
0, 0, width, height);
|
||||
return COGL_TEXTURE (sub_texture);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -681,33 +598,6 @@ cogl_texture_is_sliced (CoglTexture *texture)
|
||||
return texture->vtable->is_sliced (texture);
|
||||
}
|
||||
|
||||
/* Some CoglTextures, notably sliced textures or atlas textures when repeating
|
||||
* is used, will need to divide the coordinate space into multiple GL textures
|
||||
* (or rather; in the case of atlases duplicate a single texture in multiple
|
||||
* positions to handle repeating)
|
||||
*
|
||||
* This function helps you implement primitives using such textures by
|
||||
* invoking a callback once for each sub texture that intersects a given
|
||||
* region specified in texture coordinates.
|
||||
*/
|
||||
void
|
||||
_cogl_texture_foreach_sub_texture_in_region (CoglTexture *texture,
|
||||
float virtual_tx_1,
|
||||
float virtual_ty_1,
|
||||
float virtual_tx_2,
|
||||
float virtual_ty_2,
|
||||
CoglTextureSliceCallback callback,
|
||||
void *user_data)
|
||||
{
|
||||
texture->vtable->foreach_sub_texture_in_region (texture,
|
||||
virtual_tx_1,
|
||||
virtual_ty_1,
|
||||
virtual_tx_2,
|
||||
virtual_ty_2,
|
||||
callback,
|
||||
user_data);
|
||||
}
|
||||
|
||||
/* If this returns FALSE, that implies _foreach_sub_texture_in_region
|
||||
* will be needed to iterate over multiple sub textures for regions whos
|
||||
* texture coordinates extend out of the range [0,1]
|
||||
@ -1353,10 +1243,12 @@ cogl_texture_get_data (CoglTexture *texture,
|
||||
* the data for a sliced texture, and allows us to do the
|
||||
* read-from-framebuffer logic here in a simple fashion rather than
|
||||
* passing offsets down through the code. */
|
||||
_cogl_texture_foreach_sub_texture_in_region (texture,
|
||||
0, 0, 1, 1,
|
||||
texture_get_cb,
|
||||
&tg_data);
|
||||
cogl_meta_texture_foreach_in_region (COGL_META_TEXTURE (texture),
|
||||
0, 0, 1, 1,
|
||||
COGL_PIPELINE_WRAP_MODE_REPEAT,
|
||||
COGL_PIPELINE_WRAP_MODE_REPEAT,
|
||||
texture_get_cb,
|
||||
&tg_data);
|
||||
|
||||
_cogl_bitmap_unmap (target_bmp);
|
||||
|
||||
@ -1457,3 +1349,115 @@ _cogl_texture_flush_journal_rendering (CoglTexture *texture)
|
||||
for (l = texture->framebuffers; l; l = l->next)
|
||||
_cogl_framebuffer_flush_journal (l->data);
|
||||
}
|
||||
|
||||
/* This function lets you define a meta texture as a grid of textures
|
||||
* whereby the x and y grid-lines are defined by an array of
|
||||
* CoglSpans. With that grid based description this function can then
|
||||
* iterate all the cells of the grid that lye within a region
|
||||
* specified as virtual, meta-texture, coordinates. This function can
|
||||
* also cope with regions that extend beyond the original meta-texture
|
||||
* grid by iterating cells repeatedly according to the wrap_x/y
|
||||
* arguments.
|
||||
*
|
||||
* To differentiate between texture coordinates of a specific, real,
|
||||
* slice texture and the texture coordinates of a composite, meta
|
||||
* texture, the coordinates of the meta texture are called "virtual"
|
||||
* coordinates and the coordinates of spans are called "slice"
|
||||
* coordinates.
|
||||
*
|
||||
* Note: no guarantee is given about the order in which the slices
|
||||
* will be visited.
|
||||
*
|
||||
* Note: The slice coordinates passed to @callback are always
|
||||
* normalized coordinates even if the span coordinates aren't
|
||||
* normalized.
|
||||
*/
|
||||
void
|
||||
_cogl_texture_spans_foreach_in_region (CoglSpan *x_spans,
|
||||
int n_x_spans,
|
||||
CoglSpan *y_spans,
|
||||
int n_y_spans,
|
||||
CoglTexture **textures,
|
||||
float *virtual_coords,
|
||||
float x_normalize_factor,
|
||||
float y_normalize_factor,
|
||||
CoglPipelineWrapMode wrap_x,
|
||||
CoglPipelineWrapMode wrap_y,
|
||||
CoglMetaTextureCallback callback,
|
||||
void *user_data)
|
||||
{
|
||||
CoglSpanIter iter_x;
|
||||
CoglSpanIter iter_y;
|
||||
float slice_coords[4];
|
||||
|
||||
/* Iterate the y axis of the virtual rectangle */
|
||||
for (_cogl_span_iter_begin (&iter_y,
|
||||
y_spans,
|
||||
n_y_spans,
|
||||
y_normalize_factor,
|
||||
virtual_coords[1],
|
||||
virtual_coords[3],
|
||||
wrap_y);
|
||||
!_cogl_span_iter_end (&iter_y);
|
||||
_cogl_span_iter_next (&iter_y))
|
||||
{
|
||||
if (iter_y.flipped)
|
||||
{
|
||||
slice_coords[1] = iter_y.intersect_end;
|
||||
slice_coords[3] = iter_y.intersect_start;
|
||||
}
|
||||
else
|
||||
{
|
||||
slice_coords[1] = iter_y.intersect_start;
|
||||
slice_coords[3] = iter_y.intersect_end;
|
||||
}
|
||||
|
||||
/* Map the current intersection to normalized slice coordinates */
|
||||
slice_coords[1] = (slice_coords[1] - iter_y.pos) / iter_y.span->size;
|
||||
slice_coords[3] = (slice_coords[3] - iter_y.pos) / iter_y.span->size;
|
||||
|
||||
/* Iterate the x axis of the virtual rectangle */
|
||||
for (_cogl_span_iter_begin (&iter_x,
|
||||
x_spans,
|
||||
n_x_spans,
|
||||
x_normalize_factor,
|
||||
virtual_coords[0],
|
||||
virtual_coords[2],
|
||||
wrap_x);
|
||||
!_cogl_span_iter_end (&iter_x);
|
||||
_cogl_span_iter_next (&iter_x))
|
||||
{
|
||||
CoglTexture *span_tex;
|
||||
float span_virtual_coords[4];
|
||||
|
||||
if (iter_x.flipped)
|
||||
{
|
||||
slice_coords[0] = iter_x.intersect_end;
|
||||
slice_coords[2] = iter_x.intersect_start;
|
||||
}
|
||||
else
|
||||
{
|
||||
slice_coords[0] = iter_x.intersect_start;
|
||||
slice_coords[2] = iter_x.intersect_end;
|
||||
}
|
||||
|
||||
/* Map the current intersection to normalized slice coordinates */
|
||||
slice_coords[0] = (slice_coords[0] - iter_x.pos) / iter_x.span->size;
|
||||
slice_coords[2] = (slice_coords[2] - iter_x.pos) / iter_x.span->size;
|
||||
|
||||
/* Pluck out the cogl texture for this span */
|
||||
span_tex = textures[iter_y.index * n_y_spans + iter_x.index];
|
||||
|
||||
span_virtual_coords[0] = iter_x.intersect_start;
|
||||
span_virtual_coords[1] = iter_y.intersect_start;
|
||||
span_virtual_coords[2] = iter_x.intersect_end;
|
||||
span_virtual_coords[3] = iter_y.intersect_end;
|
||||
|
||||
callback (COGL_TEXTURE (span_tex),
|
||||
slice_coords,
|
||||
span_virtual_coords,
|
||||
user_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -82,6 +82,7 @@ typedef struct _CoglFramebuffer CoglFramebuffer;
|
||||
#include <cogl/cogl-texture-2d.h>
|
||||
#include <cogl/cogl-texture-3d.h>
|
||||
#include <cogl/cogl-texture-2d-sliced.h>
|
||||
#include <cogl/cogl-meta-texture.h>
|
||||
#include <cogl/cogl-index-buffer.h>
|
||||
#include <cogl/cogl-attribute-buffer.h>
|
||||
#include <cogl/cogl-indices.h>
|
||||
|
@ -739,6 +739,33 @@ _cogl_texture_pixmap_x11_get_data (CoglTexture *tex,
|
||||
return cogl_texture_get_data (child_tex, format, rowstride, data);
|
||||
}
|
||||
|
||||
typedef struct _NormalizeCoordsWrapperData
|
||||
{
|
||||
int width;
|
||||
int height;
|
||||
CoglMetaTextureCallback callback;
|
||||
void *user_data;
|
||||
} NormalizeCoordsWrapperData;
|
||||
|
||||
static void
|
||||
normalize_coords_wrapper_cb (CoglTexture *child_texture,
|
||||
const float *child_texture_coords,
|
||||
const float *meta_coords,
|
||||
void *user_data)
|
||||
{
|
||||
NormalizeCoordsWrapperData *data = user_data;
|
||||
float normalized_coords[4];
|
||||
|
||||
normalized_coords[0] = meta_coords[0] / data->width;
|
||||
normalized_coords[1] = meta_coords[1] / data->height;
|
||||
normalized_coords[2] = meta_coords[2] / data->width;
|
||||
normalized_coords[3] = meta_coords[3] / data->height;
|
||||
|
||||
data->callback (child_texture,
|
||||
child_texture_coords, normalized_coords,
|
||||
data->user_data);
|
||||
}
|
||||
|
||||
static void
|
||||
_cogl_texture_pixmap_x11_foreach_sub_texture_in_region
|
||||
(CoglTexture *tex,
|
||||
@ -746,22 +773,54 @@ _cogl_texture_pixmap_x11_foreach_sub_texture_in_region
|
||||
float virtual_ty_1,
|
||||
float virtual_tx_2,
|
||||
float virtual_ty_2,
|
||||
CoglTextureSliceCallback callback,
|
||||
CoglMetaTextureCallback callback,
|
||||
void *user_data)
|
||||
{
|
||||
CoglTexturePixmapX11 *tex_pixmap = COGL_TEXTURE_PIXMAP_X11 (tex);
|
||||
CoglHandle child_tex;
|
||||
|
||||
child_tex = _cogl_texture_pixmap_x11_get_texture (tex_pixmap);
|
||||
CoglHandle child_tex = _cogl_texture_pixmap_x11_get_texture (tex_pixmap);
|
||||
|
||||
/* Forward on to the child texture */
|
||||
_cogl_texture_foreach_sub_texture_in_region (child_tex,
|
||||
virtual_tx_1,
|
||||
virtual_ty_1,
|
||||
virtual_tx_2,
|
||||
virtual_ty_2,
|
||||
callback,
|
||||
user_data);
|
||||
|
||||
/* tfp textures may be implemented in terms of a
|
||||
* CoglTextureRectangle texture which uses un-normalized texture
|
||||
* coordinates but we want to consistently deal with normalized
|
||||
* texture coordinates with CoglTexturePixmapX11... */
|
||||
if (_cogl_is_texture_rectangle (child_tex))
|
||||
{
|
||||
NormalizeCoordsWrapperData data;
|
||||
int width = tex_pixmap->width;
|
||||
int height = tex_pixmap->height;
|
||||
|
||||
virtual_tx_1 *= width;
|
||||
virtual_ty_1 *= height;
|
||||
virtual_tx_2 *= width;
|
||||
virtual_ty_2 *= height;
|
||||
|
||||
data.width = width;
|
||||
data.height = height;
|
||||
data.callback = callback;
|
||||
data.user_data = user_data;
|
||||
|
||||
cogl_meta_texture_foreach_in_region (COGL_META_TEXTURE (tex),
|
||||
virtual_tx_1,
|
||||
virtual_ty_1,
|
||||
virtual_tx_2,
|
||||
virtual_ty_2,
|
||||
COGL_PIPELINE_WRAP_MODE_REPEAT,
|
||||
COGL_PIPELINE_WRAP_MODE_REPEAT,
|
||||
normalize_coords_wrapper_cb,
|
||||
&data);
|
||||
}
|
||||
else
|
||||
cogl_meta_texture_foreach_in_region (COGL_META_TEXTURE (tex),
|
||||
virtual_tx_1,
|
||||
virtual_ty_1,
|
||||
virtual_tx_2,
|
||||
virtual_ty_2,
|
||||
COGL_PIPELINE_WRAP_MODE_REPEAT,
|
||||
COGL_PIPELINE_WRAP_MODE_REPEAT,
|
||||
callback,
|
||||
user_data);
|
||||
}
|
||||
|
||||
static int
|
||||
|
Loading…
Reference in New Issue
Block a user