diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2011-10-08 11:08:43 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2011-10-09 19:54:15 +0100 |
commit | a6c27b500ba8f910ff2a731eb6989c96e8977339 (patch) | |
tree | b81e6ed42a416e736f127b83b571ed16d2d2f4e2 /src/cairo-gl-operand.c | |
parent | 22c485017df7979c47e9c4ba708279c8c35e5149 (diff) |
gl: Basic fixes to get cairo-gl running again
Let there be textures!
Unbreak the setup of surface operands after my lazy convertion to the
new compositor interface. This is still only the first step, but it gets
the essentials up and running again, enough to keep me happy whilst
sitting in the airport.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'src/cairo-gl-operand.c')
-rw-r--r-- | src/cairo-gl-operand.c | 151 |
1 files changed, 114 insertions, 37 deletions
diff --git a/src/cairo-gl-operand.c b/src/cairo-gl-operand.c index 8b345bbd..86a96df5 100644 --- a/src/cairo-gl-operand.c +++ b/src/cairo-gl-operand.c @@ -49,6 +49,8 @@ #include "cairo-error-private.h" #include "cairo-image-surface-private.h" #include "cairo-surface-backend-private.h" +#include "cairo-surface-offset-private.h" +#include "cairo-surface-subsurface-private.h" static cairo_int_status_t _cairo_gl_create_gradient_texture (cairo_gl_surface_t *dst, @@ -67,60 +69,124 @@ _cairo_gl_create_gradient_texture (cairo_gl_surface_t *dst, return _cairo_gl_context_release (ctx, status); } -/* - * Like cairo_pattern_acquire_surface(), but returns a matrix that transforms - * from dest to src coords. - */ +static cairo_status_t +_cairo_gl_surface_operand_init (cairo_gl_operand_t *operand, + const cairo_pattern_t *_src, + cairo_gl_surface_t *dst, + int src_x, int src_y, + int dst_x, int dst_y, + int width, int height) +{ + const cairo_surface_pattern_t *src = (cairo_surface_pattern_t *)_src; + cairo_gl_surface_t *surface; + cairo_surface_attributes_t *attributes; + cairo_matrix_t m; + + surface = (cairo_gl_surface_t *) src->surface; + if (surface->base.type != CAIRO_SURFACE_TYPE_GL) + return CAIRO_INT_STATUS_UNSUPPORTED; + if (surface->base.backend->type != CAIRO_SURFACE_TYPE_GL) { + if (_cairo_surface_is_subsurface (&surface->base)) { + surface = (cairo_gl_surface_t *) + _cairo_surface_subsurface_get_target_with_offset (&surface->base, &src_x, &src_y); + } + } + + attributes = &operand->texture.attributes; + + operand->type = CAIRO_GL_OPERAND_TEXTURE; + operand->texture.surface = + (cairo_gl_surface_t *) cairo_surface_reference (&surface->base); + operand->texture.tex = surface->tex; + + /* Translate the matrix from + * (unnormalized src -> unnormalized src) to + * (unnormalized dst -> unnormalized src) + */ + cairo_matrix_init_translate (&m, src_x - dst_x, src_y - dst_y); + cairo_matrix_multiply (&attributes->matrix, &m, &src->base.matrix); + + /* Translate the matrix from + * (unnormalized dst -> unnormalized src) to + * (unnormalized dst -> normalized src) + */ + if (_cairo_gl_device_requires_power_of_two_textures (dst->base.device)) { + cairo_matrix_init_scale (&m, + 1.0, + 1.0); + } else { + cairo_matrix_init_scale (&m, + 1.0 / surface->width, + 1.0 / surface->height); + } + cairo_matrix_multiply (&attributes->matrix, + &attributes->matrix, + &m); + + attributes->extend = src->base.extend; + attributes->filter = src->base.filter; + return CAIRO_STATUS_SUCCESS; +} + static cairo_status_t _cairo_gl_pattern_texture_setup (cairo_gl_operand_t *operand, - const cairo_pattern_t *src, + const cairo_pattern_t *_src, cairo_gl_surface_t *dst, int src_x, int src_y, int dst_x, int dst_y, int width, int height) { + const cairo_surface_pattern_t *src = (cairo_surface_pattern_t *)_src; cairo_status_t status; cairo_matrix_t m; cairo_gl_surface_t *surface; + cairo_gl_context_t *ctx; cairo_surface_attributes_t *attributes; attributes = &operand->texture.attributes; -#if 0 - status = _cairo_pattern_acquire_surface (src, &dst->base, - src_x, src_y, - width, height, - CAIRO_PATTERN_ACQUIRE_NONE, - (cairo_surface_t **) - &surface, - attributes); + status = _cairo_gl_context_acquire (dst->base.device, &ctx); if (unlikely (status)) return status; -#endif - if (_cairo_gl_device_requires_power_of_two_textures (dst->base.device) && - (attributes->extend == CAIRO_EXTEND_REPEAT || - attributes->extend == CAIRO_EXTEND_REFLECT)) - { - return UNSUPPORTED ("EXT_texture_rectangle with repeat/reflect"); + surface = (cairo_gl_surface_t *) + _cairo_gl_surface_create_scratch (ctx, + src->surface->content, + width, height); + if (src->surface->backend->type == CAIRO_SURFACE_TYPE_IMAGE) { + status = _cairo_gl_surface_draw_image (surface, + (cairo_image_surface_t *)src->surface, + src_x, src_y, + width, height, + 0, 0); + + attributes->extend = src->base.extend; + attributes->filter = src->base.filter; + } else { + cairo_surface_t *image; + + image = cairo_surface_map_to_image (&surface->base, NULL); + status = _cairo_surface_offset_paint (image, src_x, src_y, + CAIRO_OPERATOR_SOURCE, _src, + NULL); + cairo_surface_unmap_image (&surface->base, image); + + attributes->extend = CAIRO_EXTEND_NONE; + attributes->filter = CAIRO_FILTER_NEAREST; } - assert (_cairo_gl_surface_is_texture (surface)); + status = _cairo_gl_context_release (ctx, status); operand->type = CAIRO_GL_OPERAND_TEXTURE; operand->texture.surface = surface; operand->texture.tex = surface->tex; + /* Translate the matrix from * (unnormalized src -> unnormalized src) to * (unnormalized dst -> unnormalized src) */ - cairo_matrix_init_translate (&m, - src_x - dst_x + attributes->x_offset, - src_y - dst_y + attributes->y_offset); - cairo_matrix_multiply (&attributes->matrix, - &m, - &attributes->matrix); - + cairo_matrix_init_translate (&m, -dst_x, -dst_y); + cairo_matrix_multiply (&attributes->matrix, &m, &src->base.matrix); /* Translate the matrix from * (unnormalized dst -> unnormalized src) to @@ -138,7 +204,6 @@ _cairo_gl_pattern_texture_setup (cairo_gl_operand_t *operand, cairo_matrix_multiply (&attributes->matrix, &attributes->matrix, &m); - return CAIRO_STATUS_SUCCESS; } @@ -286,26 +351,38 @@ _cairo_gl_operand_init (cairo_gl_operand_t *operand, _cairo_gl_solid_operand_init (operand, &((cairo_solid_pattern_t *) pattern)->color); return CAIRO_STATUS_SUCCESS; + case CAIRO_PATTERN_TYPE_SURFACE: + status = _cairo_gl_surface_operand_init (operand, + pattern, dst, + src_x, src_y, + dst_x, dst_y, + width, height); + if (status == CAIRO_INT_STATUS_UNSUPPORTED) + break; + + return status; + case CAIRO_PATTERN_TYPE_LINEAR: case CAIRO_PATTERN_TYPE_RADIAL: status = _cairo_gl_gradient_operand_init (operand, pattern, dst, src_x, src_y, dst_x, dst_y); - if (status != CAIRO_INT_STATUS_UNSUPPORTED) - return status; + if (status == CAIRO_INT_STATUS_UNSUPPORTED) + break; - /* fall through */ + return status; default: case CAIRO_PATTERN_TYPE_MESH: - case CAIRO_PATTERN_TYPE_SURFACE: - return _cairo_gl_pattern_texture_setup (operand, - pattern, dst, - src_x, src_y, - dst_x, dst_y, - width, height); + break; } + + return _cairo_gl_pattern_texture_setup (operand, + pattern, dst, + src_x, src_y, + dst_x, dst_y, + width, height); } cairo_filter_t |