From 3251590a05dc23e805a86c3497cf896d3387373a Mon Sep 17 00:00:00 2001 From: Henry Song Date: Mon, 26 Sep 2011 14:45:23 -0700 Subject: [PATCH 2/4] cairo-gl-msaa-compositor: 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. --- src/cairo-gl-composite.c | 160 +++++++++++++++++++++++++++++++++++++--- src/cairo-gl-device.c | 7 ++- src/cairo-gl-msaa-compositor.c | 98 ++++++++++++++++++++++++- src/cairo-gl-private.h | 14 ++++ 4 files changed, 267 insertions(+), 12 deletions(-) diff --git a/src/cairo-gl-composite.c b/src/cairo-gl-composite.c index c59501e..10d2e4a 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 * Eric Anholt * Alexandros Frantzis + * Henry Song + * Martin Robinson */ #include "cairoint.h" @@ -573,6 +576,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) { @@ -591,16 +603,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 @@ -609,8 +614,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++) { @@ -769,3 +788,124 @@ _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; + + 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); + + ctx->vertex_size = 2 * sizeof (GLfloat); + + 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); + + return status; +} diff --git a/src/cairo-gl-device.c b/src/cairo-gl-device.c index f20850e..33af08e 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); @@ -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 afbf85c..3565658 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 *extents) { @@ -82,7 +128,57 @@ _cairo_gl_msaa_compositor_fill (const cairo_compositor_t *compositor, double tolerance, cairo_antialias_t antialias) { - return CAIRO_INT_STATUS_UNSUPPORTED; + cairo_status_t status; + cairo_traps_t traps; + + cairo_gl_composite_t setup; + cairo_gl_surface_t *dst = (cairo_gl_surface_t *) extents->surface; + cairo_gl_context_t *ctx = NULL; + + if (antialias != CAIRO_ANTIALIAS_NONE) + 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 FINISH; + + status = _cairo_gl_composite_init (&setup, + extents->op, + dst, + FALSE, /* assume_component_alpha */ + &extents->bounded); + if (unlikely (status)) + return status; + + status = _cairo_gl_composite_set_source (&setup, + &extents->source_pattern.base, + extents->bounded.x, + extents->bounded.y, + extents->bounded.x, + extents->bounded.y, + extents->bounded.width, + extents->bounded.height); + if (unlikely (status)) + goto FINISH; + + status = _cairo_gl_composite_begin_tristrip (&setup, &ctx); + if (unlikely (status)) + goto FINISH; + + status = _draw_traps (ctx, &setup, &traps); + if (unlikely (status)) + goto FINISH; + + _cairo_gl_composite_flush (ctx); + +FINISH: + _cairo_traps_fini (&traps); + _cairo_gl_composite_fini (&setup); + if (ctx) + status = _cairo_gl_context_release (ctx, status); + + return status; } static cairo_int_status_t diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h index e1005ba..1bb59b3 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 @@ -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); @@ -648,6 +659,9 @@ _cairo_gl_span_compositor_get (void); cairo_private const cairo_compositor_t * _cairo_gl_traps_compositor_get (void); +cairo_private cairo_compositor_t * +_cairo_gl_msaa_compositor_get (void); + cairo_private cairo_int_status_t _cairo_gl_check_composite_glyphs (const cairo_composite_rectangles_t *extents, cairo_scaled_font_t *scaled_font, -- 1.7.4.1