summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Otte <otte@redhat.com>2010-05-16 03:29:04 +0200
committerBenjamin Otte <otte@redhat.com>2010-05-17 01:13:46 +0200
commit4144488f516214b675d25d48add8cbd83fd17025 (patch)
tree4300b724a54db29fb31a22eedf3388152b435111
parent6e81d85e3682f14e1c5dbe97dda2cc1fcd32df3a (diff)
gl: Convert span renderer to use cairo_gl_composite_begin/end()
Adds two new APIs to the composite API: - _cairo_gl_composite_set_mask_spans() Tells the composite renderer to use the color values for spans. - _cairo_gl_composite_set_clip_region() Tells the composite renderer to use GL_SCISSORS_TEST to clip when drawing. This function is very unperformant, so if it can be avoided, it probably shouldn't be used.
-rw-r--r--src/cairo-gl-composite.c72
-rw-r--r--src/cairo-gl-private.h10
-rw-r--r--src/cairo-gl-surface.c247
3 files changed, 110 insertions, 219 deletions
diff --git a/src/cairo-gl-composite.c b/src/cairo-gl-composite.c
index c32c89bc..a93267ca 100644
--- a/src/cairo-gl-composite.c
+++ b/src/cairo-gl-composite.c
@@ -450,6 +450,21 @@ _cairo_gl_operand_init (cairo_gl_context_t *ctx,
}
}
+void
+_cairo_gl_composite_set_mask_spans (cairo_gl_context_t *ctx,
+ cairo_gl_composite_t *setup)
+{
+ setup->mask.type = CAIRO_GL_OPERAND_SPANS;
+}
+
+void
+_cairo_gl_composite_set_clip_region (cairo_gl_context_t *ctx,
+ cairo_gl_composite_t *setup,
+ cairo_region_t *clip_region)
+{
+ setup->clip_region = clip_region;
+}
+
static void
_cairo_gl_operand_destroy (cairo_gl_operand_t *operand)
{
@@ -864,6 +879,27 @@ _cairo_gl_set_mask_operand (cairo_gl_context_t *ctx,
case CAIRO_GL_OPERAND_NONE:
break;
case CAIRO_GL_OPERAND_SPANS:
+ if (! setup->shader) {
+ /* Set up the mask to source from the incoming vertex color. */
+ glActiveTexture (GL_TEXTURE1);
+ /* Have to have a dummy texture bound in order to use the combiner unit. */
+ glBindTexture (ctx->tex_target, ctx->dummy_tex);
+ glEnable (ctx->tex_target);
+ glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
+ glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE);
+ glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE);
+
+ glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS);
+ glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_PREVIOUS);
+ glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
+ glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
+
+ glTexEnvi (GL_TEXTURE_ENV, GL_SRC1_RGB, GL_PRIMARY_COLOR);
+ glTexEnvi (GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_PRIMARY_COLOR);
+ glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_ALPHA);
+ glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
+ }
+ break;
case CAIRO_GL_OPERAND_COUNT:
default:
ASSERT_NOT_REACHED;
@@ -1050,8 +1086,15 @@ _cairo_gl_composite_begin (cairo_gl_context_t *ctx,
glTexCoordPointer (2, GL_FLOAT, setup->vertex_size,
(void *) (uintptr_t) (dst_size + src_size));
glEnableClientState (GL_TEXTURE_COORD_ARRAY);
+ } else if (setup->mask.type == CAIRO_GL_OPERAND_SPANS) {
+ glColorPointer (4, GL_UNSIGNED_BYTE, setup->vertex_size,
+ (void *) (uintptr_t) (dst_size + src_size));
+ glEnableClientState (GL_COLOR_ARRAY);
}
+ if (setup->clip_region)
+ glEnable (GL_SCISSOR_TEST);
+
return status;
}
@@ -1085,7 +1128,20 @@ _cairo_gl_composite_flush (cairo_gl_context_t *ctx,
if (setup->vb_offset == 0)
return;
- _cairo_gl_composite_draw (ctx, setup);
+ if (setup->clip_region) {
+ int i, num_rectangles = cairo_region_num_rectangles (setup->clip_region);
+
+ for (i = 0; i < num_rectangles; i++) {
+ cairo_rectangle_int_t rect;
+
+ cairo_region_get_rectangle (setup->clip_region, i, &rect);
+
+ glScissor (rect.x, rect.y, rect.width, rect.height);
+ _cairo_gl_composite_draw (ctx, setup);
+ }
+ } else {
+ _cairo_gl_composite_draw (ctx, setup);
+ }
glUnmapBufferARB (GL_ARRAY_BUFFER_ARB);
setup->vb = NULL;
@@ -1124,7 +1180,15 @@ _cairo_gl_operand_emit (cairo_gl_operand_t *operand,
case CAIRO_GL_OPERAND_RADIAL_GRADIENT:
break;
case CAIRO_GL_OPERAND_SPANS:
- ASSERT_NOT_REACHED;
+ {
+ union fi {
+ float f;
+ uint32_t u;
+ } fi;
+
+ fi.u = color;
+ *(*vb)++ = fi.f;
+ }
break;
case CAIRO_GL_OPERAND_TEXTURE:
{
@@ -1181,12 +1245,16 @@ _cairo_gl_composite_end (cairo_gl_context_t *ctx,
{
_cairo_gl_composite_flush (ctx, setup);
+ if (setup->clip_region)
+ glDisable (GL_SCISSOR_TEST);
+
glBindBufferARB (GL_ARRAY_BUFFER_ARB, 0);
_cairo_gl_use_program (ctx, NULL);
glDisable (GL_BLEND);
glDisableClientState (GL_VERTEX_ARRAY);
+ glDisableClientState (GL_COLOR_ARRAY);
glClientActiveTexture (GL_TEXTURE0);
glDisableClientState (GL_TEXTURE_COORD_ARRAY);
diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h
index 870d80c5..aad11a09 100644
--- a/src/cairo-gl-private.h
+++ b/src/cairo-gl-private.h
@@ -189,6 +189,7 @@ typedef struct _cairo_gl_composite {
cairo_gl_surface_t *dst;
cairo_operator_t op;
cairo_bool_t has_component_alpha;
+ cairo_region_t *clip_region;
cairo_gl_operand_t src;
cairo_gl_operand_t mask;
@@ -297,6 +298,15 @@ cairo_private void
_cairo_gl_composite_fini (cairo_gl_context_t *ctx,
cairo_gl_composite_t *setup);
+cairo_private void
+_cairo_gl_composite_set_clip_region (cairo_gl_context_t *ctx,
+ cairo_gl_composite_t *setup,
+ cairo_region_t *clip_region);
+
+cairo_private void
+_cairo_gl_composite_set_mask_spans (cairo_gl_context_t *ctx,
+ cairo_gl_composite_t *setup);
+
cairo_private cairo_status_t
_cairo_gl_composite_begin (cairo_gl_context_t *ctx,
cairo_gl_composite_t *setup);
diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c
index 6f91dbd7..4e6976b4 100644
--- a/src/cairo-gl-surface.c
+++ b/src/cairo-gl-surface.c
@@ -50,18 +50,6 @@ _cairo_gl_surface_fill_rectangles (void *abstract_surface,
#define BIAS .375
-static inline float
-int_as_float (uint32_t val)
-{
- union fi {
- float f;
- uint32_t u;
- } fi;
-
- fi.u = val;
- return fi.f;
-}
-
static cairo_bool_t _cairo_surface_is_gl (cairo_surface_t *surface)
{
return surface->backend == &_cairo_gl_surface_backend;
@@ -1287,138 +1275,8 @@ typedef struct _cairo_gl_surface_span_renderer {
int xmin, xmax;
cairo_gl_context_t *ctx;
- cairo_region_t *clip;
-
- void *vbo_base;
- unsigned int vbo_size;
- unsigned int vbo_offset;
- unsigned int vertex_size;
} cairo_gl_surface_span_renderer_t;
-static void
-_cairo_gl_span_renderer_flush (cairo_gl_surface_span_renderer_t *renderer)
-{
- int count;
-
- if (renderer->vbo_offset == 0)
- return;
-
- glUnmapBufferARB (GL_ARRAY_BUFFER_ARB);
-
- count = renderer->vbo_offset / renderer->vertex_size;
- renderer->vbo_offset = 0;
-
- if (renderer->clip) {
- int i, num_rectangles = cairo_region_num_rectangles (renderer->clip);
-
- glEnable (GL_SCISSOR_TEST);
- for (i = 0; i < num_rectangles; i++) {
- cairo_rectangle_int_t rect;
-
- cairo_region_get_rectangle (renderer->clip, i, &rect);
-
- glScissor (rect.x, rect.y, rect.width, rect.height);
- glDrawArrays (GL_QUADS, 0, count);
- }
- glDisable (GL_SCISSOR_TEST);
- } else {
- glDrawArrays (GL_QUADS, 0, count);
- }
-}
-
-static void *
-_cairo_gl_span_renderer_get_vbo (cairo_gl_surface_span_renderer_t *renderer,
- unsigned int num_vertices)
-{
- unsigned int offset;
-
- if (renderer->vbo_size == 0) {
- renderer->vbo_size = 16384;
- glBindBufferARB (GL_ARRAY_BUFFER_ARB, renderer->ctx->vbo);
-
- if (renderer->setup.src.type == CAIRO_GL_OPERAND_TEXTURE)
- renderer->vertex_size = 4 * sizeof (float) + sizeof (uint32_t);
- else
- renderer->vertex_size = 2 * sizeof (float) + sizeof (uint32_t);
-
- glVertexPointer (2, GL_FLOAT, renderer->vertex_size, 0);
- glEnableClientState (GL_VERTEX_ARRAY);
-
- glColorPointer (4, GL_UNSIGNED_BYTE, renderer->vertex_size,
- (void *) (uintptr_t) (2 * sizeof (float)));
- glEnableClientState (GL_COLOR_ARRAY);
-
- if (renderer->setup.src.type == CAIRO_GL_OPERAND_TEXTURE) {
- glClientActiveTexture (GL_TEXTURE0);
- glTexCoordPointer (2, GL_FLOAT, renderer->vertex_size,
- (void *) (uintptr_t) (2 * sizeof (float) +
- sizeof (uint32_t)));
- glEnableClientState (GL_TEXTURE_COORD_ARRAY);
- }
- }
-
- if (renderer->vbo_offset + num_vertices * renderer->vertex_size >
- renderer->vbo_size) {
- _cairo_gl_span_renderer_flush (renderer);
- }
-
- if (renderer->vbo_offset == 0) {
- /* We'll only be using these vertices once. */
- glBufferDataARB (GL_ARRAY_BUFFER_ARB, renderer->vbo_size, NULL,
- GL_STREAM_DRAW_ARB);
- renderer->vbo_base = glMapBufferARB (GL_ARRAY_BUFFER_ARB,
- GL_WRITE_ONLY_ARB);
- }
-
- offset = renderer->vbo_offset;
- renderer->vbo_offset += num_vertices * renderer->vertex_size;
-
- return (char *) renderer->vbo_base + offset;
-}
-
-static void
-_cairo_gl_emit_span_vertex (cairo_gl_surface_span_renderer_t *renderer,
- int dst_x, int dst_y, uint8_t alpha,
- float *vertices)
-{
- cairo_surface_attributes_t *src_attributes;
- int v = 0;
-
- src_attributes = &renderer->setup.src.operand.texture.attributes;
-
- vertices[v++] = dst_x + BIAS;
- vertices[v++] = dst_y + BIAS;
- vertices[v++] = int_as_float (alpha << 24);
- if (renderer->setup.src.type == CAIRO_GL_OPERAND_TEXTURE) {
- double s, t;
-
- s = dst_x + BIAS;
- t = dst_y + BIAS;
- cairo_matrix_transform_point (&src_attributes->matrix, &s, &t);
- vertices[v++] = s;
- vertices[v++] = t;
- }
-}
-
-static void
-_cairo_gl_emit_rectangle (cairo_gl_surface_span_renderer_t *renderer,
- int x1, int y1,
- int x2, int y2,
- int coverage)
-{
- float *vertices = _cairo_gl_span_renderer_get_vbo (renderer, 4);
- int vsize = renderer->vertex_size / 4;
-
- _cairo_gl_emit_span_vertex (renderer, x1, y1, coverage,
- vertices + vsize * 0);
- _cairo_gl_emit_span_vertex (renderer, x1, y2, coverage,
- vertices + vsize * 1);
- _cairo_gl_emit_span_vertex (renderer, x2, y2, coverage,
- vertices + vsize * 2);
- _cairo_gl_emit_span_vertex (renderer, x2, y1, coverage,
- vertices + vsize * 3);
-}
-
static cairo_status_t
_cairo_gl_render_bounded_spans (void *abstract_renderer,
int y, int height,
@@ -1432,10 +1290,11 @@ _cairo_gl_render_bounded_spans (void *abstract_renderer,
do {
if (spans[0].coverage) {
- _cairo_gl_emit_rectangle (renderer,
- spans[0].x, y,
- spans[1].x, y + height,
- spans[0].coverage);
+ _cairo_gl_composite_emit_rect (renderer->ctx,
+ &renderer->setup,
+ spans[0].x, y,
+ spans[1].x, y + height,
+ spans[0].coverage << 24);
}
spans++;
@@ -1453,33 +1312,37 @@ _cairo_gl_render_unbounded_spans (void *abstract_renderer,
cairo_gl_surface_span_renderer_t *renderer = abstract_renderer;
if (num_spans == 0) {
- _cairo_gl_emit_rectangle (renderer,
- renderer->xmin, y,
- renderer->xmax, y + height,
- 0);
+ _cairo_gl_composite_emit_rect (renderer->ctx,
+ &renderer->setup,
+ renderer->xmin, y,
+ renderer->xmax, y + height,
+ 0);
return CAIRO_STATUS_SUCCESS;
}
if (spans[0].x != renderer->xmin) {
- _cairo_gl_emit_rectangle (renderer,
- renderer->xmin, y,
- spans[0].x, y + height,
- 0);
+ _cairo_gl_composite_emit_rect (renderer->ctx,
+ &renderer->setup,
+ renderer->xmin, y,
+ spans[0].x, y + height,
+ 0);
}
do {
- _cairo_gl_emit_rectangle (renderer,
- spans[0].x, y,
- spans[1].x, y + height,
- spans[0].coverage);
+ _cairo_gl_composite_emit_rect (renderer->ctx,
+ &renderer->setup,
+ spans[0].x, y,
+ spans[1].x, y + height,
+ spans[0].coverage << 24);
spans++;
} while (--num_spans > 1);
if (spans[0].x != renderer->xmax) {
- _cairo_gl_emit_rectangle (renderer,
- spans[0].x, y,
- renderer->xmax, y + height,
- 0);
+ _cairo_gl_composite_emit_rect (renderer->ctx,
+ &renderer->setup,
+ spans[0].x, y,
+ renderer->xmax, y + height,
+ 0);
}
return CAIRO_STATUS_SUCCESS;
@@ -1505,25 +1368,7 @@ _cairo_gl_surface_span_renderer_finish (void *abstract_renderer)
{
cairo_gl_surface_span_renderer_t *renderer = abstract_renderer;
- _cairo_gl_span_renderer_flush (renderer);
-
- glBindBufferARB (GL_ARRAY_BUFFER_ARB, 0);
- glDisableClientState (GL_VERTEX_ARRAY);
- glDisableClientState (GL_COLOR_ARRAY);
-
- glClientActiveTexture (GL_TEXTURE0);
- glDisableClientState (GL_TEXTURE_COORD_ARRAY);
- glActiveTexture (GL_TEXTURE0);
- glDisable (GL_TEXTURE_1D);
- glDisable (renderer->ctx->tex_target);
-
- if (!renderer->setup.shader) {
- glActiveTexture (GL_TEXTURE1);
- glDisable (renderer->ctx->tex_target);
- }
-
- glDisable (GL_BLEND);
- _cairo_gl_use_program (renderer->ctx, NULL);
+ _cairo_gl_composite_end (renderer->ctx, &renderer->setup);
return CAIRO_STATUS_SUCCESS;
}
@@ -1559,7 +1404,6 @@ _cairo_gl_surface_create_span_renderer (cairo_operator_t op,
cairo_gl_surface_t *dst = abstract_dst;
cairo_gl_surface_span_renderer_t *renderer;
cairo_status_t status;
- cairo_surface_attributes_t *src_attributes;
const cairo_rectangle_int_t *extents;
renderer = calloc (1, sizeof (*renderer));
@@ -1577,7 +1421,6 @@ _cairo_gl_surface_create_span_renderer (cairo_operator_t op,
}
renderer->xmin = extents->x;
renderer->xmax = extents->x + extents->width;
- renderer->clip = clip_region;
status = _cairo_gl_context_acquire (dst->base.device, &renderer->ctx);
if (unlikely (status)) {
@@ -1600,43 +1443,13 @@ _cairo_gl_surface_create_span_renderer (cairo_operator_t op,
if (unlikely (status))
goto FAIL;
- _cairo_gl_context_set_destination (renderer->ctx, dst);
+ _cairo_gl_composite_set_mask_spans (renderer->ctx, &renderer->setup);
+ _cairo_gl_composite_set_clip_region (renderer->ctx, &renderer->setup, clip_region);
- status = _cairo_gl_get_program (renderer->ctx,
- renderer->setup.src.type,
- CAIRO_GL_OPERAND_SPANS,
- CAIRO_GL_SHADER_IN_NORMAL,
- &renderer->setup.shader);
- if (_cairo_status_is_error (status))
+ status = _cairo_gl_composite_begin (renderer->ctx, &renderer->setup);
+ if (unlikely (status))
goto FAIL;
- src_attributes = &renderer->setup.src.operand.texture.attributes;
-
- _cairo_gl_use_program (renderer->ctx, renderer->setup.shader);
- _cairo_gl_set_operator (dst, op, FALSE);
- _cairo_gl_set_src_operand (renderer->ctx, &renderer->setup);
-
- if (!renderer->setup.shader) {
- /* Set up the mask to source from the incoming vertex color. */
- glActiveTexture (GL_TEXTURE1);
- /* Have to have a dummy texture bound in order to use the combiner unit. */
- glBindTexture (renderer->ctx->tex_target, renderer->ctx->dummy_tex);
- glEnable (renderer->ctx->tex_target);
- glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
- glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE);
- glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE);
-
- glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS);
- glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_PREVIOUS);
- glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
- glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
-
- glTexEnvi (GL_TEXTURE_ENV, GL_SRC1_RGB, GL_PRIMARY_COLOR);
- glTexEnvi (GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_PRIMARY_COLOR);
- glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_ALPHA);
- glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
- }
-
return &renderer->base;