summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMartin Robinson <mrobinson@webkit.org>2011-09-26 14:45:23 -0700
committerChris Wilson <chris@chris-wilson.co.uk>2011-10-13 14:42:15 +0100
commit13d9d07ccd92454f8eb0a1f2d59c8829ac471cb4 (patch)
tree64cc704b3a91f3c2162bbff4715bc455b7f40dea /src
parent9f85eb52d834200802a05ac1dd5fa045217adf5f (diff)
downloadcairo-13d9d07ccd92454f8eb0a1f2d59c8829ac471cb4.tar.gz
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.
Diffstat (limited to 'src')
-rw-r--r--src/cairo-gl-composite.c167
-rw-r--r--src/cairo-gl-device.c7
-rw-r--r--src/cairo-gl-msaa-compositor.c101
-rw-r--r--src/cairo-gl-private.h11
4 files changed, 274 insertions, 12 deletions
diff --git a/src/cairo-gl-composite.c b/src/cairo-gl-composite.c
index 5bce04d58..f260c1d97 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, &current_vertex_index);
+ if (unlikely (status))
+ return status;
+
+ current_vertex_index++;
+ status =_cairo_array_append (indices, &current_vertex_index);
+ if (unlikely (status))
+ return status;
+ }
+
+ for (i = 0; i < number_of_new_indices; i++) {
+ status = _cairo_array_append (indices, &current_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 f20850e74..33af08e7e 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 8e2c2ed5c..ab5501db0 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 52492741a..d1208709e 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);