summaryrefslogtreecommitdiff
path: root/src/cairo-gl-composite.c
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/cairo-gl-composite.c
parent9f85eb52d834200802a05ac1dd5fa045217adf5f (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.
Diffstat (limited to 'src/cairo-gl-composite.c')
-rw-r--r--src/cairo-gl-composite.c167
1 files changed, 157 insertions, 10 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, &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;
+}