diff options
author | Martin Robinson <mrobinson@webkit.org> | 2011-09-26 14:45:23 -0700 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2011-10-13 14:42:15 +0100 |
commit | 13d9d07ccd92454f8eb0a1f2d59c8829ac471cb4 (patch) | |
tree | 64cc704b3a91f3c2162bbff4715bc455b7f40dea | |
parent | 9f85eb52d834200802a05ac1dd5fa045217adf5f (diff) |
gl/msaa: Implement basic solid color fill
Introduce the very basic functionality of an MSAA compositor
for OpenGL. For this first patch only solid fills are supported.
-rw-r--r-- | src/cairo-gl-composite.c | 167 | ||||
-rw-r--r-- | src/cairo-gl-device.c | 7 | ||||
-rw-r--r-- | src/cairo-gl-msaa-compositor.c | 101 | ||||
-rw-r--r-- | src/cairo-gl-private.h | 11 |
4 files changed, 274 insertions, 12 deletions
diff --git a/src/cairo-gl-composite.c b/src/cairo-gl-composite.c index 5bce04d5..f260c1d9 100644 --- a/src/cairo-gl-composite.c +++ b/src/cairo-gl-composite.c @@ -4,6 +4,7 @@ * Copyright © 2009 Chris Wilson * Copyright © 2005,2010 Red Hat, Inc * Copyright © 2011 Linaro Limited + * Copyright © 2011 Samsung Electronics * * This library is free software; you can redistribute it and/or * modify it either under the terms of the GNU Lesser General Public @@ -38,6 +39,8 @@ * Chris Wilson <chris@chris-wilson.co.uk> * Eric Anholt <eric@anholt.net> * Alexandros Frantzis <alexandros.frantzis@linaro.org> + * Henry Song <hsong@sisa.samsung.com> + * Martin Robinson <mrobinson@igalia.com> */ #include "cairoint.h" @@ -571,6 +574,15 @@ FAIL: } static inline void +_cairo_gl_composite_draw_tristrip (cairo_gl_context_t *ctx) +{ + cairo_array_t* indices = &ctx->tristrip_indices; + const int *indices_array = _cairo_array_index_const (indices, 0); + glDrawElements (GL_TRIANGLE_STRIP, _cairo_array_num_elements (indices), GL_UNSIGNED_INT, indices_array); + _cairo_array_truncate (indices, 0); +} + +static inline void _cairo_gl_composite_draw (cairo_gl_context_t *ctx, unsigned int count) { @@ -589,16 +601,9 @@ _cairo_gl_composite_draw (cairo_gl_context_t *ctx, } } -void -_cairo_gl_composite_flush (cairo_gl_context_t *ctx) +static void +_cairo_gl_composite_unmap_vertex_buffer (cairo_gl_context_t *ctx) { - unsigned int count; - - if (_cairo_gl_context_is_flushed (ctx)) - return; - - count = ctx->vb_offset / ctx->vertex_size; - if (ctx->has_map_buffer) ctx->dispatch.UnmapBuffer (GL_ARRAY_BUFFER); else @@ -607,8 +612,22 @@ _cairo_gl_composite_flush (cairo_gl_context_t *ctx) ctx->vb = NULL; ctx->vb_offset = 0; +} + +void +_cairo_gl_composite_flush (cairo_gl_context_t *ctx) +{ + unsigned int count; + + if (_cairo_gl_context_is_flushed (ctx)) + return; + + count = ctx->vb_offset / ctx->vertex_size; + _cairo_gl_composite_unmap_vertex_buffer (ctx); - if (ctx->clip_region) { + if ( _cairo_array_num_elements (&ctx->tristrip_indices) > 0) { + _cairo_gl_composite_draw_tristrip (ctx); + } else if (ctx->clip_region) { int i, num_rectangles = cairo_region_num_rectangles (ctx->clip_region); for (i = 0; i < num_rectangles; i++) { @@ -767,3 +786,131 @@ _cairo_gl_composite_init (cairo_gl_composite_t *setup, return CAIRO_STATUS_SUCCESS; } + +static void +_cairo_gl_composite_emit_tristrip_vertex (cairo_gl_context_t *ctx, + cairo_point_t *point) +{ + GLfloat *vb = (GLfloat *) (void *) &ctx->vb[ctx->vb_offset]; + + *vb++ = _cairo_fixed_to_double (point->x); + *vb++ = _cairo_fixed_to_double (point->y); + + ctx->vb_offset += ctx->vertex_size; +} + +static cairo_int_status_t +_cairo_gl_composite_append_vertex_indices (cairo_gl_context_t *ctx, + int number_of_new_indices) +{ + cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS; + cairo_array_t *indices = &ctx->tristrip_indices; + int number_of_indices = _cairo_array_num_elements (indices); + int current_vertex_index = 0; + int i; + + assert (number_of_new_indices > 0); + + /* If any preexisting triangle triangle strip indices exist on this + context, we insert a set of degenerate triangles from the last + preexisting vertex to our first one. */ + if (number_of_indices > 0) { + const int *indices_array = _cairo_array_index_const (indices, 0); + current_vertex_index = indices_array[number_of_indices - 1]; + + status = _cairo_array_append (indices, ¤t_vertex_index); + if (unlikely (status)) + return status; + + current_vertex_index++; + status =_cairo_array_append (indices, ¤t_vertex_index); + if (unlikely (status)) + return status; + } + + for (i = 0; i < number_of_new_indices; i++) { + status = _cairo_array_append (indices, ¤t_vertex_index); + current_vertex_index++; + if (unlikely (status)) + return status; + } + + return CAIRO_STATUS_SUCCESS; +} + +cairo_int_status_t +_cairo_gl_composite_emit_quad_as_tristrip (cairo_gl_context_t *ctx, + cairo_gl_composite_t *setup, + cairo_point_t quad[4]) +{ + _cairo_gl_composite_prepare_buffer (ctx, 4); + + _cairo_gl_composite_emit_tristrip_vertex (ctx, &quad[0]); + _cairo_gl_composite_emit_tristrip_vertex (ctx, &quad[1]); + + /* Cairo stores quad vertices in counter-clockwise order, but we need to + emit them from top to bottom in the triangle strip, so we need to reverse + the order of the last two vertices. */ + _cairo_gl_composite_emit_tristrip_vertex (ctx, &quad[3]); + _cairo_gl_composite_emit_tristrip_vertex (ctx, &quad[2]); + + return _cairo_gl_composite_append_vertex_indices (ctx, 4); +} + +cairo_status_t +_cairo_gl_composite_begin_tristrip (cairo_gl_composite_t *setup, + cairo_gl_context_t **ctx_out) +{ + cairo_gl_context_t *ctx; + cairo_status_t status; + cairo_gl_shader_t *shader; + int src_size, dst_size; + + cairo_gl_operand_t default_mask; + memset (&default_mask, 0, sizeof (cairo_gl_operand_t)); + + assert (setup->dst); + + status = _cairo_gl_context_acquire (setup->dst->base.device, &ctx); + if (unlikely (status)) + return status; + *ctx_out = ctx; + + /* Finish any pending operations from other GL compositors. */ + if (! _cairo_gl_context_is_flushed (ctx)) + _cairo_gl_composite_flush (ctx); + + glEnable (GL_BLEND); + + status = _cairo_gl_get_shader_by_type (ctx, + &setup->src, + &default_mask, + setup->spans, + CAIRO_GL_SHADER_IN_NORMAL, + &shader); + if (unlikely (status)) { + status = _cairo_gl_context_release (ctx, status); + return status; + } + + _cairo_gl_context_set_destination (ctx, setup->dst); + + _cairo_gl_set_operator (ctx, setup->op, FALSE); + _cairo_gl_set_shader (ctx, shader); + _cairo_gl_composite_bind_to_shader (ctx, setup); + + dst_size = 2 * sizeof (GLfloat); + src_size = _cairo_gl_operand_get_vertex_size (setup->src.type); + + ctx->vertex_size = dst_size + src_size; + + ctx->dispatch.BindBuffer (GL_ARRAY_BUFFER, ctx->vbo); + ctx->dispatch.VertexAttribPointer (CAIRO_GL_VERTEX_ATTRIB_INDEX, 2, + GL_FLOAT, GL_FALSE, ctx->vertex_size, NULL); + ctx->dispatch.EnableVertexAttribArray (CAIRO_GL_VERTEX_ATTRIB_INDEX); + + _cairo_gl_context_setup_operand (ctx, CAIRO_GL_TEX_SOURCE, &setup->src, + ctx->vertex_size, dst_size); + + return status; +} diff --git a/src/cairo-gl-device.c b/src/cairo-gl-device.c index f20850e7..33af08e7 100644 --- a/src/cairo-gl-device.c +++ b/src/cairo-gl-device.c @@ -132,6 +132,8 @@ _gl_destroy (void *device) for (n = 0; n < ARRAY_LENGTH (ctx->glyph_cache); n++) _cairo_gl_glyph_cache_fini (ctx, &ctx->glyph_cache[n]); + _cairo_array_fini (&ctx->tristrip_indices); + cairo_region_destroy (ctx->clip_region); free (ctx->vb_mem); @@ -163,7 +165,8 @@ _cairo_gl_context_init (cairo_gl_context_t *ctx) _cairo_device_init (&ctx->base, &_cairo_gl_device_backend); - ctx->compositor = _cairo_gl_span_compositor_get (); + //ctx->compositor = _cairo_gl_span_compositor_get (); + ctx->compositor = _cairo_gl_msaa_compositor_get (); memset (ctx->glyph_cache, 0, sizeof (ctx->glyph_cache)); cairo_list_init (&ctx->fonts); @@ -227,6 +230,8 @@ _cairo_gl_context_init (cairo_gl_context_t *ctx) } } + _cairo_array_init (&ctx->tristrip_indices, sizeof(int)); + /* PBO for any sort of texture upload */ dispatch->GenBuffers (1, &ctx->texture_load_pbo); dispatch->GenBuffers (1, &ctx->vbo); diff --git a/src/cairo-gl-msaa-compositor.c b/src/cairo-gl-msaa-compositor.c index 8e2c2ed5..ab5501db 100644 --- a/src/cairo-gl-msaa-compositor.c +++ b/src/cairo-gl-msaa-compositor.c @@ -48,6 +48,52 @@ #include "cairo-traps-private.h" static cairo_int_status_t +_draw_trap (cairo_gl_context_t *ctx, + cairo_gl_composite_t *setup, + cairo_trapezoid_t *trap) +{ + cairo_point_t quad[4]; + + quad[0].x = _cairo_edge_compute_intersection_x_for_y (&trap->left.p1, + &trap->left.p2, + trap->top); + quad[0].y = trap->top; + + quad[1].x = _cairo_edge_compute_intersection_x_for_y (&trap->left.p1, + &trap->left.p2, + trap->bottom); + quad[1].y = trap->bottom; + + quad[2].x = _cairo_edge_compute_intersection_x_for_y (&trap->right.p1, + &trap->right.p2, + trap->bottom); + quad[2].y = trap->bottom; + + quad[3].x = _cairo_edge_compute_intersection_x_for_y (&trap->right.p1, + &trap->right.p2, + trap->top); + quad[3].y = trap->top; + return _cairo_gl_composite_emit_quad_as_tristrip (ctx, setup, quad); +} + +static cairo_int_status_t +_draw_traps (cairo_gl_context_t *ctx, + cairo_gl_composite_t *setup, + cairo_traps_t *traps) +{ + int i; + cairo_int_status_t status = CAIRO_STATUS_SUCCESS; + + for (i = 0; i < traps->num_traps; i++) { + cairo_trapezoid_t *trap = traps->traps + i; + if (unlikely ((status = _draw_trap (ctx, setup, trap)))) + return status; + } + + return status; +} + +static cairo_int_status_t _cairo_gl_msaa_compositor_paint (const cairo_compositor_t *compositor, cairo_composite_rectangles_t *composite) { @@ -82,7 +128,60 @@ _cairo_gl_msaa_compositor_fill (const cairo_compositor_t *compositor, double tolerance, cairo_antialias_t antialias) { - return CAIRO_INT_STATUS_UNSUPPORTED; + cairo_gl_composite_t setup; + cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface; + cairo_gl_context_t *ctx = NULL; + cairo_int_status_t status; + cairo_traps_t traps; + + if (antialias != CAIRO_ANTIALIAS_NONE) + return CAIRO_INT_STATUS_UNSUPPORTED; + + if (! _cairo_composite_rectangles_can_reduce_clip (composite, + composite->clip)) + return CAIRO_INT_STATUS_UNSUPPORTED; + + _cairo_traps_init (&traps); + status = _cairo_path_fixed_fill_to_traps (path, fill_rule, tolerance, &traps); + if (unlikely (status)) + goto cleanup_traps; + + status = _cairo_gl_composite_init (&setup, + composite->op, + dst, + FALSE, /* assume_component_alpha */ + &composite->bounded); + if (unlikely (status)) + goto cleanup_traps; + + status = _cairo_gl_composite_set_source (&setup, + &composite->source_pattern.base, + composite->bounded.x, + composite->bounded.y, + composite->bounded.x, + composite->bounded.y, + composite->bounded.width, + composite->bounded.height); + if (unlikely (status)) + goto cleanup_setup; + + status = _cairo_gl_composite_begin_tristrip (&setup, &ctx); + if (unlikely (status)) + goto cleanup_setup; + + status = _draw_traps (ctx, &setup, &traps); + if (unlikely (status)) + goto cleanup_setup; + + _cairo_gl_composite_flush (ctx); +cleanup_setup: + _cairo_gl_composite_fini (&setup); + if (ctx) + status = _cairo_gl_context_release (ctx, status); +cleanup_traps: + _cairo_traps_fini (&traps); + + return status; } static void diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h index 52492741..d1208709 100644 --- a/src/cairo-gl-private.h +++ b/src/cairo-gl-private.h @@ -56,6 +56,7 @@ #include "cairo-rtree-private.h" #include "cairo-scaled-font-private.h" #include "cairo-spans-compositor-private.h" +#include "cairo-array-private.h" #include <assert.h> @@ -291,6 +292,7 @@ struct _cairo_gl_context { unsigned int vb_offset; unsigned int vertex_size; cairo_region_t *clip_region; + cairo_array_t tristrip_indices; cairo_bool_t has_mesa_pack_invert; cairo_gl_dispatch_t dispatch; @@ -489,6 +491,15 @@ _cairo_gl_composite_emit_glyph (cairo_gl_context_t *ctx, cairo_private void _cairo_gl_composite_flush (cairo_gl_context_t *ctx); +cairo_private cairo_status_t +_cairo_gl_composite_begin_tristrip (cairo_gl_composite_t *setup, + cairo_gl_context_t **ctx_out); + +cairo_int_status_t +_cairo_gl_composite_emit_quad_as_tristrip (cairo_gl_context_t *ctx, + cairo_gl_composite_t *setup, + cairo_point_t quad[4]); + cairo_private void _cairo_gl_context_destroy_operand (cairo_gl_context_t *ctx, cairo_gl_tex_t tex_unit); |