diff options
author | Benjamin Otte <otte@redhat.com> | 2010-05-16 03:29:04 +0200 |
---|---|---|
committer | Benjamin Otte <otte@redhat.com> | 2010-05-17 01:13:46 +0200 |
commit | 4144488f516214b675d25d48add8cbd83fd17025 (patch) | |
tree | 4300b724a54db29fb31a22eedf3388152b435111 | |
parent | 6e81d85e3682f14e1c5dbe97dda2cc1fcd32df3a (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.c | 72 | ||||
-rw-r--r-- | src/cairo-gl-private.h | 10 | ||||
-rw-r--r-- | src/cairo-gl-surface.c | 247 |
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; |