[cairo-commit] 30 commits - src/cairo-gl-composite.c src/cairo-gl-device.c src/cairo-gl-glyphs.c src/cairo-gl-private.h src/cairo-gl-shaders.c src/cairo-gl-surface.c src/cairo-xlib-surface.c src/Makefile.sources
Benjamin Otte
company at kemper.freedesktop.org
Sun May 16 16:17:08 PDT 2010
src/Makefile.sources | 3
src/cairo-gl-composite.c | 1392 ++++++++++++++++++++++++++++++++++++++++
src/cairo-gl-device.c | 31
src/cairo-gl-glyphs.c | 344 +--------
src/cairo-gl-private.h | 224 ++++--
src/cairo-gl-shaders.c | 880 +++++++++++++------------
src/cairo-gl-surface.c | 1624 +++--------------------------------------------
src/cairo-xlib-surface.c | 4
8 files changed, 2195 insertions(+), 2307 deletions(-)
New commits:
commit 7ef1bd22ded512f4fad3959796d7f40c4ddc5824
Author: Benjamin Otte <otte at redhat.com>
Date: Mon May 17 01:12:34 2010 +0200
gl: Update copyright statements
- add 2010 Red Hat copyright for my code
- include myself as author
- update contributors list
diff --git a/src/cairo-gl-composite.c b/src/cairo-gl-composite.c
index 02afe2f..91f94f9 100644
--- a/src/cairo-gl-composite.c
+++ b/src/cairo-gl-composite.c
@@ -2,7 +2,7 @@
*
* Copyright © 2009 Eric Anholt
* Copyright © 2009 Chris Wilson
- * Copyright © 2005 Red Hat, Inc
+ * Copyright © 2005,2010 Red Hat, Inc
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
@@ -32,7 +32,10 @@
* The Initial Developer of the Original Code is Red Hat, Inc.
*
* Contributor(s):
+ * Benjamin Otte <otte at gnome.org>
* Carl Worth <cworth at cworth.org>
+ * Chris Wilson <chris at chris-wilson.co.uk>
+ * Eric Anholt <eric at anholt.net>
*/
#include "cairoint.h"
diff --git a/src/cairo-gl-device.c b/src/cairo-gl-device.c
index 99dfa18..e506ca7 100644
--- a/src/cairo-gl-device.c
+++ b/src/cairo-gl-device.c
@@ -2,7 +2,7 @@
*
* Copyright © 2009 Eric Anholt
* Copyright © 2009 Chris Wilson
- * Copyright © 2005 Red Hat, Inc
+ * Copyright © 2005,2010 Red Hat, Inc
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
@@ -32,7 +32,10 @@
* The Initial Developer of the Original Code is Red Hat, Inc.
*
* Contributor(s):
+ * Benjamin Otte <otte at gnome.org>
* Carl Worth <cworth at cworth.org>
+ * Chris Wilson <chris at chris-wilson.co.uk>
+ * Eric Anholt <eric at anholt.net>
*/
#include "cairoint.h"
diff --git a/src/cairo-gl-glyphs.c b/src/cairo-gl-glyphs.c
index d0aae23..d9107bc 100644
--- a/src/cairo-gl-glyphs.c
+++ b/src/cairo-gl-glyphs.c
@@ -2,6 +2,7 @@
*
* Copyright © 2009 Chris Wilson
* Copyright © 2010 Intel Corporation
+ * Copyright © 2010 Red Hat, Inc
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
@@ -29,6 +30,10 @@
* The Original Code is the cairo graphics library.
*
* The Initial Developer of the Original Code is Chris Wilson.
+ *
+ * Contributors:
+ * Benjamin Otte <otte at gnome.org>
+ * Chris Wilson <chris at chris-wilson.co.uk>
*/
#include "cairoint.h"
diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h
index e9aeeb0..77d0ef7 100644
--- a/src/cairo-gl-private.h
+++ b/src/cairo-gl-private.h
@@ -2,7 +2,7 @@
*
* Copyright © 2009 Eric Anholt
* Copyright © 2009 Chris Wilson
- * Copyright © 2005 Red Hat, Inc
+ * Copyright © 2005,2010 Red Hat, Inc
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
@@ -32,9 +32,11 @@
* The Initial Developer of the Original Code is Red Hat, Inc.
*
* Contributor(s):
+ * Benjamin Otte <otte at gnome.org>
* Carl Worth <cworth at cworth.org>
* Chris Wilson <chris at chris-wilson.co.uk>
- * T. Zachary Laine <whatwasthataddress at gmail.com>
+ * Eric Anholt <eric at anholt.net>
+ * T. Zachary Laine <whatwasthataddress at gmail.com>
*/
#ifndef CAIRO_GL_PRIVATE_H
diff --git a/src/cairo-gl-shaders.c b/src/cairo-gl-shaders.c
index c3de05a..403f76f 100644
--- a/src/cairo-gl-shaders.c
+++ b/src/cairo-gl-shaders.c
@@ -1,7 +1,8 @@
/* cairo - a vector graphics library with display and print output
*
- * Copyright © 2010 Eric Anholt
* Copyright © 2009 T. Zachary Laine
+ * Copyright © 2010 Eric Anholt
+ * Copyright © 2010 Red Hat, Inc
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
@@ -29,6 +30,11 @@
* The Original Code is the cairo graphics library.
*
* The Initial Developer of the Original Code is T. Zachary Laine.
+ *
+ * Contributor(s):
+ * Benjamin Otte <otte at gnome.org>
+ * Eric Anholt <eric at anholt.net>
+ * T. Zachary Laine <whatwasthataddress at gmail.com>
*/
#include "cairoint.h"
diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c
index 154b925..f485682 100644
--- a/src/cairo-gl-surface.c
+++ b/src/cairo-gl-surface.c
@@ -2,7 +2,7 @@
*
* Copyright © 2009 Eric Anholt
* Copyright © 2009 Chris Wilson
- * Copyright © 2005 Red Hat, Inc
+ * Copyright © 2005,2010 Red Hat, Inc
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
@@ -32,7 +32,10 @@
* The Initial Developer of the Original Code is Red Hat, Inc.
*
* Contributor(s):
+ * Benjamin Otte <otte at gnome.org>
* Carl Worth <cworth at cworth.org>
+ * Chris Wilson <chris at chris-wilson.co.uk>
+ * Eric Anholt <eric at anholt.net>
*/
#include "cairoint.h"
commit 0b69e51b526a609a2dc5f1d2fb9c49f240feb57b
Author: Benjamin Otte <otte at redhat.com>
Date: Mon May 17 00:56:21 2010 +0200
gl: Assert that binding values to shaders never fails
As that would be a programming error, we can use an assert and get rid
of return values that we weren't checking anyway.
diff --git a/src/cairo-gl-composite.c b/src/cairo-gl-composite.c
index a8ae084..02afe2f 100644
--- a/src/cairo-gl-composite.c
+++ b/src/cairo-gl-composite.c
@@ -556,21 +556,19 @@ _cairo_gl_set_tex_combine_constant_color (cairo_gl_context_t *ctx,
{
if (setup->shader) {
const char *uniform_name;
- cairo_status_t status;
if (tex_unit == 0)
uniform_name = "source_constant";
else
uniform_name = "mask_constant";
- status = bind_vec4_to_shader (ctx,
- setup->shader->program,
- uniform_name,
- color[0],
- color[1],
- color[2],
- color[3]);
- assert (! _cairo_status_is_error (status));
+ bind_vec4_to_shader (ctx,
+ setup->shader->program,
+ uniform_name,
+ color[0],
+ color[1],
+ color[2],
+ color[3]);
return;
}
@@ -612,7 +610,6 @@ _cairo_gl_set_src_operand (cairo_gl_context_t *ctx,
{
cairo_surface_attributes_t *src_attributes;
GLfloat constant_color[4] = {0.0, 0.0, 0.0, 0.0};
- cairo_status_t status;
src_attributes = &setup->src.operand.texture.attributes;
@@ -652,16 +649,14 @@ _cairo_gl_set_src_operand (cairo_gl_context_t *ctx,
glBindTexture (GL_TEXTURE_1D, setup->src.operand.linear.tex);
glEnable (GL_TEXTURE_1D);
- status = bind_matrix_to_shader (ctx, setup->shader->program,
- "source_matrix",
- &setup->src.operand.linear.m);
- assert (!_cairo_status_is_error (status));
+ bind_matrix_to_shader (ctx, setup->shader->program,
+ "source_matrix",
+ &setup->src.operand.linear.m);
- status = bind_vec2_to_shader (ctx, setup->shader->program,
- "source_segment",
- setup->src.operand.linear.segment_x,
- setup->src.operand.linear.segment_y);
- assert (!_cairo_status_is_error (status));
+ bind_vec2_to_shader (ctx, setup->shader->program,
+ "source_segment",
+ setup->src.operand.linear.segment_x,
+ setup->src.operand.linear.segment_y);
break;
case CAIRO_GL_OPERAND_RADIAL_GRADIENT:
@@ -669,26 +664,22 @@ _cairo_gl_set_src_operand (cairo_gl_context_t *ctx,
glBindTexture (GL_TEXTURE_1D, setup->src.operand.linear.tex);
glEnable (GL_TEXTURE_1D);
- status = bind_matrix_to_shader (ctx, setup->shader->program,
- "source_matrix",
- &setup->src.operand.radial.m);
- assert (!_cairo_status_is_error (status));
-
- status = bind_vec2_to_shader (ctx, setup->shader->program,
- "source_circle_1",
- setup->src.operand.radial.circle_1_x,
- setup->src.operand.radial.circle_1_y);
- assert (!_cairo_status_is_error (status));
-
- status = bind_float_to_shader (ctx, setup->shader->program,
- "source_radius_0",
- setup->src.operand.radial.radius_0);
- assert (!_cairo_status_is_error (status));
-
- status = bind_float_to_shader (ctx, setup->shader->program,
- "source_radius_1",
- setup->src.operand.radial.radius_1);
- assert (!_cairo_status_is_error (status));
+ bind_matrix_to_shader (ctx, setup->shader->program,
+ "source_matrix",
+ &setup->src.operand.radial.m);
+
+ bind_vec2_to_shader (ctx, setup->shader->program,
+ "source_circle_1",
+ setup->src.operand.radial.circle_1_x,
+ setup->src.operand.radial.circle_1_y);
+
+ bind_float_to_shader (ctx, setup->shader->program,
+ "source_radius_0",
+ setup->src.operand.radial.radius_0);
+
+ bind_float_to_shader (ctx, setup->shader->program,
+ "source_radius_1",
+ setup->src.operand.radial.radius_1);
break;
default:
case CAIRO_GL_OPERAND_COUNT:
@@ -751,57 +742,47 @@ static void
_cairo_gl_set_linear_gradient_mask_operand (cairo_gl_context_t *ctx,
cairo_gl_composite_t *setup)
{
- cairo_status_t status;
-
assert(setup->shader);
glActiveTexture (GL_TEXTURE1);
glBindTexture (GL_TEXTURE_1D, setup->mask.operand.linear.tex);
glEnable (GL_TEXTURE_1D);
- status = bind_matrix_to_shader (ctx, setup->shader->program,
+ bind_matrix_to_shader (ctx, setup->shader->program,
"mask_matrix", &setup->mask.operand.linear.m);
- assert (!_cairo_status_is_error (status));
- status = bind_vec2_to_shader (ctx, setup->shader->program,
+ bind_vec2_to_shader (ctx, setup->shader->program,
"mask_segment",
setup->mask.operand.linear.segment_x,
setup->mask.operand.linear.segment_y);
- assert (!_cairo_status_is_error (status));
}
static void
_cairo_gl_set_radial_gradient_mask_operand (cairo_gl_context_t *ctx,
cairo_gl_composite_t *setup)
{
- cairo_status_t status;
-
assert(setup->shader);
glActiveTexture (GL_TEXTURE1);
glBindTexture (GL_TEXTURE_1D, setup->mask.operand.radial.tex);
glEnable (GL_TEXTURE_1D);
- status = bind_matrix_to_shader (ctx, setup->shader->program,
- "mask_matrix",
- &setup->mask.operand.radial.m);
- assert (!_cairo_status_is_error (status));
-
- status = bind_vec2_to_shader (ctx, setup->shader->program,
- "mask_circle_1",
- setup->mask.operand.radial.circle_1_x,
- setup->mask.operand.radial.circle_1_y);
- assert (!_cairo_status_is_error (status));
-
- status = bind_float_to_shader (ctx, setup->shader->program,
- "mask_radius_0",
- setup->mask.operand.radial.radius_0);
- assert (!_cairo_status_is_error (status));
-
- status = bind_float_to_shader (ctx, setup->shader->program,
- "mask_radius_1",
- setup->mask.operand.radial.radius_1);
- assert (!_cairo_status_is_error (status));
+ bind_matrix_to_shader (ctx, setup->shader->program,
+ "mask_matrix",
+ &setup->mask.operand.radial.m);
+
+ bind_vec2_to_shader (ctx, setup->shader->program,
+ "mask_circle_1",
+ setup->mask.operand.radial.circle_1_x,
+ setup->mask.operand.radial.circle_1_y);
+
+ bind_float_to_shader (ctx, setup->shader->program,
+ "mask_radius_0",
+ setup->mask.operand.radial.radius_0);
+
+ bind_float_to_shader (ctx, setup->shader->program,
+ "mask_radius_1",
+ setup->mask.operand.radial.radius_1);
}
/* This is like _cairo_gl_set_src_alpha_operand, for component alpha setup
@@ -831,14 +812,12 @@ _cairo_gl_set_component_alpha_mask_operand (cairo_gl_context_t *ctx,
case CAIRO_GL_OPERAND_CONSTANT:
/* Have to have a dummy texture bound in order to use the combiner unit. */
if (setup->shader) {
- cairo_status_t status;
- status = bind_vec4_to_shader (ctx, setup->shader->program,
- "mask_constant",
- setup->src.operand.constant.color[0],
- setup->src.operand.constant.color[1],
- setup->src.operand.constant.color[2],
- setup->src.operand.constant.color[3]);
- assert (! _cairo_status_is_error (status));
+ bind_vec4_to_shader (ctx, setup->shader->program,
+ "mask_constant",
+ setup->src.operand.constant.color[0],
+ setup->src.operand.constant.color[1],
+ setup->src.operand.constant.color[2],
+ setup->src.operand.constant.color[3]);
} else {
glBindTexture (ctx->tex_target, ctx->dummy_tex);
glActiveTexture (GL_TEXTURE1);
diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h
index 3f53220..e9aeeb0 100644
--- a/src/cairo-gl-private.h
+++ b/src/cairo-gl-private.h
@@ -420,33 +420,33 @@ create_shader_program (cairo_gl_context_t *ctx,
cairo_gl_var_type_t mask,
const char *fragment_text);
-cairo_private cairo_status_t
+cairo_private void
bind_float_to_shader (cairo_gl_context_t *ctx,
GLuint program, const char *name,
float value);
-cairo_private cairo_status_t
+cairo_private void
bind_vec2_to_shader (cairo_gl_context_t *ctx,
GLuint program, const char *name,
float value0, float value1);
-cairo_private cairo_status_t
+cairo_private void
bind_vec3_to_shader (cairo_gl_context_t *ctx,
GLuint program, const char *name,
float value0, float value1,
float value2);
-cairo_private cairo_status_t
+cairo_private void
bind_vec4_to_shader (cairo_gl_context_t *ctx,
GLuint program, const char *name,
float value0, float value1,
float value2, float value3);
-cairo_private cairo_status_t
+cairo_private void
bind_matrix_to_shader (cairo_gl_context_t *ctx,
GLuint program, const char *name, cairo_matrix_t* m);
-cairo_private cairo_status_t
+cairo_private void
bind_texture_to_shader (cairo_gl_context_t *ctx,
GLuint program, const char *name, GLuint tex_unit);
diff --git a/src/cairo-gl-shaders.c b/src/cairo-gl-shaders.c
index 7511b4e..c3de05a 100644
--- a/src/cairo-gl-shaders.c
+++ b/src/cairo-gl-shaders.c
@@ -49,28 +49,28 @@ typedef struct cairo_gl_shader_impl {
void
(*destroy_program) (GLuint program);
- cairo_status_t
+ void
(*bind_float_to_shader) (GLuint program, const char *name,
float value);
- cairo_status_t
+ void
(*bind_vec2_to_shader) (GLuint program, const char *name,
float value0, float value1);
- cairo_status_t
+ void
(*bind_vec3_to_shader) (GLuint program, const char *name,
float value0, float value1,
float value2);
- cairo_status_t
+ void
(*bind_vec4_to_shader) (GLuint program, const char *name,
float value0, float value1,
float value2, float value3);
- cairo_status_t
+ void
(*bind_matrix_to_shader) (GLuint program, const char *name, cairo_matrix_t* m);
- cairo_status_t
+ void
(*bind_texture_to_shader) (GLuint program, const char *name, GLuint tex_unit);
void
@@ -159,53 +159,45 @@ destroy_program_arb (GLuint shader)
glDeleteObjectARB (shader);
}
-static cairo_status_t
+static void
bind_float_to_shader_arb (GLuint program, const char *name,
float value)
{
GLint location = glGetUniformLocationARB (program, name);
- if (location == -1)
- return CAIRO_INT_STATUS_UNSUPPORTED;
+ assert (location != -1);
glUniform1fARB (location, value);
- return CAIRO_STATUS_SUCCESS;
}
-static cairo_status_t
+static void
bind_vec2_to_shader_arb (GLuint program, const char *name,
float value0, float value1)
{
GLint location = glGetUniformLocationARB (program, name);
- if (location == -1)
- return CAIRO_INT_STATUS_UNSUPPORTED;
+ assert (location != -1);
glUniform2fARB (location, value0, value1);
- return CAIRO_STATUS_SUCCESS;
}
-static cairo_status_t
+static void
bind_vec3_to_shader_arb (GLuint program, const char *name,
float value0, float value1,
float value2)
{
GLint location = glGetUniformLocationARB (program, name);
- if (location == -1)
- return CAIRO_INT_STATUS_UNSUPPORTED;
+ assert (location != -1);
glUniform3fARB (location, value0, value1, value2);
- return CAIRO_STATUS_SUCCESS;
}
-static cairo_status_t
+static void
bind_vec4_to_shader_arb (GLuint program, const char *name,
float value0, float value1,
float value2, float value3)
{
GLint location = glGetUniformLocationARB (program, name);
- if (location == -1)
- return CAIRO_INT_STATUS_UNSUPPORTED;
+ assert (location != -1);
glUniform4fARB (location, value0, value1, value2, value3);
- return CAIRO_STATUS_SUCCESS;
}
-static cairo_status_t
+static void
bind_matrix_to_shader_arb (GLuint program, const char *name, cairo_matrix_t* m)
{
GLint location = glGetUniformLocationARB (program, name);
@@ -215,20 +207,16 @@ bind_matrix_to_shader_arb (GLuint program, const char *name, cairo_matrix_t* m)
0, 0, 1, 0,
0, 0, 0, 1
};
- if (location == -1)
- return CAIRO_INT_STATUS_UNSUPPORTED;
+ assert (location != -1);
glUniformMatrix4fvARB (location, 1, GL_TRUE, gl_m);
- return CAIRO_STATUS_SUCCESS;
}
-static cairo_status_t
+static void
bind_texture_to_shader_arb (GLuint program, const char *name, GLuint tex_unit)
{
GLint location = glGetUniformLocationARB (program, name);
- if (location == -1)
- return CAIRO_INT_STATUS_UNSUPPORTED;
+ assert (location != -1);
glUniform1iARB (location, tex_unit);
- return CAIRO_STATUS_SUCCESS;
}
static void
@@ -321,53 +309,45 @@ destroy_program_core_2_0 (GLuint shader)
glDeleteProgram (shader);
}
-static cairo_status_t
+static void
bind_float_to_shader_core_2_0 (GLuint program, const char *name,
float value)
{
GLint location = glGetUniformLocation (program, name);
- if (location == -1)
- return CAIRO_INT_STATUS_UNSUPPORTED;
+ assert (location != -1);
glUniform1f (location, value);
- return CAIRO_STATUS_SUCCESS;
}
-static cairo_status_t
+static void
bind_vec2_to_shader_core_2_0 (GLuint program, const char *name,
float value0, float value1)
{
GLint location = glGetUniformLocation (program, name);
- if (location == -1)
- return CAIRO_INT_STATUS_UNSUPPORTED;
+ assert (location != -1);
glUniform2f (location, value0, value1);
- return CAIRO_STATUS_SUCCESS;
}
-static cairo_status_t
+static void
bind_vec3_to_shader_core_2_0 (GLuint program, const char *name,
float value0, float value1,
float value2)
{
GLint location = glGetUniformLocation (program, name);
- if (location == -1)
- return CAIRO_INT_STATUS_UNSUPPORTED;
+ assert (location != -1);
glUniform3f (location, value0, value1, value2);
- return CAIRO_STATUS_SUCCESS;
}
-static cairo_status_t
+static void
bind_vec4_to_shader_core_2_0 (GLuint program, const char *name,
float value0, float value1,
float value2, float value3)
{
GLint location = glGetUniformLocation (program, name);
- if (location == -1)
- return CAIRO_INT_STATUS_UNSUPPORTED;
+ assert (location != -1);
glUniform4f (location, value0, value1, value2, value3);
- return CAIRO_STATUS_SUCCESS;
}
-static cairo_status_t
+static void
bind_matrix_to_shader_core_2_0 (GLuint program, const char *name, cairo_matrix_t* m)
{
GLint location = glGetUniformLocation (program, name);
@@ -377,20 +357,16 @@ bind_matrix_to_shader_core_2_0 (GLuint program, const char *name, cairo_matrix_t
0, 0, 1, 0,
0, 0, 0, 1
};
- if (location == -1)
- return CAIRO_INT_STATUS_UNSUPPORTED;
+ assert (location != -1);
glUniformMatrix4fv (location, 1, GL_TRUE, gl_m);
- return CAIRO_STATUS_SUCCESS;
}
-static cairo_status_t
+static void
bind_texture_to_shader_core_2_0 (GLuint program, const char *name, GLuint tex_unit)
{
GLint location = glGetUniformLocation (program, name);
- if (location == -1)
- return CAIRO_INT_STATUS_UNSUPPORTED;
+ assert (location != -1);
glUniform1i (location, tex_unit);
- return CAIRO_STATUS_SUCCESS;
}
static void
@@ -826,52 +802,52 @@ create_shader_program (cairo_gl_context_t *ctx,
return CAIRO_INT_STATUS_UNSUPPORTED;
}
-cairo_status_t
+void
bind_float_to_shader (cairo_gl_context_t *ctx,
GLuint program, const char *name,
float value)
{
- return ctx->shader_impl->bind_float_to_shader(program, name, value);
+ ctx->shader_impl->bind_float_to_shader(program, name, value);
}
-cairo_status_t
+void
bind_vec2_to_shader (cairo_gl_context_t *ctx,
GLuint program, const char *name,
float value0, float value1)
{
- return ctx->shader_impl->bind_vec2_to_shader(program, name, value0, value1);
+ ctx->shader_impl->bind_vec2_to_shader(program, name, value0, value1);
}
-cairo_status_t
+void
bind_vec3_to_shader (cairo_gl_context_t *ctx,
GLuint program, const char *name,
float value0, float value1,
float value2)
{
- return ctx->shader_impl->bind_vec3_to_shader(program, name, value0, value1, value2);
+ ctx->shader_impl->bind_vec3_to_shader(program, name, value0, value1, value2);
}
-cairo_status_t
+void
bind_vec4_to_shader (cairo_gl_context_t *ctx,
GLuint program, const char *name,
float value0, float value1,
float value2, float value3)
{
- return ctx->shader_impl->bind_vec4_to_shader(program, name, value0, value1, value2, value3);
+ ctx->shader_impl->bind_vec4_to_shader(program, name, value0, value1, value2, value3);
}
-cairo_status_t
+void
bind_matrix_to_shader (cairo_gl_context_t *ctx,
GLuint program, const char *name, cairo_matrix_t* m)
{
- return ctx->shader_impl->bind_matrix_to_shader(program, name, m);
+ ctx->shader_impl->bind_matrix_to_shader(program, name, m);
}
-cairo_status_t
+void
bind_texture_to_shader (cairo_gl_context_t *ctx,
GLuint program, const char *name, GLuint tex_unit)
{
- return ctx->shader_impl->bind_texture_to_shader(program, name, tex_unit);
+ ctx->shader_impl->bind_texture_to_shader(program, name, tex_unit);
}
void
@@ -952,14 +928,12 @@ _cairo_gl_get_program (cairo_gl_context_t *ctx,
_cairo_gl_use_program (ctx, &entry->program);
if (source != CAIRO_GL_OPERAND_CONSTANT) {
- status = bind_texture_to_shader (ctx, entry->program.program, "source_sampler", 0);
- assert (!_cairo_status_is_error (status));
+ bind_texture_to_shader (ctx, entry->program.program, "source_sampler", 0);
}
if (mask != CAIRO_GL_OPERAND_CONSTANT &&
mask != CAIRO_GL_OPERAND_SPANS &&
mask != CAIRO_GL_OPERAND_NONE) {
- status = bind_texture_to_shader (ctx, entry->program.program, "mask_sampler", 1);
- assert (!_cairo_status_is_error (status));
+ bind_texture_to_shader (ctx, entry->program.program, "mask_sampler", 1);
}
status = _cairo_cache_insert (&ctx->shaders, &entry->base);
diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c
index eeeac59..154b925 100644
--- a/src/cairo-gl-surface.c
+++ b/src/cairo-gl-surface.c
@@ -1200,14 +1200,13 @@ _cairo_gl_surface_fill_rectangles_glsl (void *abstract_surface,
_cairo_gl_context_set_destination (ctx, surface);
_cairo_gl_set_operator (surface, op, FALSE);
- status = bind_vec4_to_shader (ctx,
- ctx->fill_rectangles_shader.program,
- "color",
- color->red * color->alpha,
- color->green * color->alpha,
- color->blue * color->alpha,
- color->alpha);
- assert (! _cairo_status_is_error (status));
+ bind_vec4_to_shader (ctx,
+ ctx->fill_rectangles_shader.program,
+ "color",
+ color->red * color->alpha,
+ color->green * color->alpha,
+ color->blue * color->alpha,
+ color->alpha);
for (i = 0; i < num_rects; i++) {
vertices[i * 8 + 0] = rects[i].x;
commit 0bb11e8f5bcdc8a6f8384197b39c2ad48eaab1cd
Author: Benjamin Otte <otte at redhat.com>
Date: Mon May 17 00:49:01 2010 +0200
gl: Use GL_TRIANGLES instead of GL_QUADS
It seems to increase performance by 1-2% on average and up to 30% in
some cases (on i965).
diff --git a/src/cairo-gl-composite.c b/src/cairo-gl-composite.c
index a9c7e25..a8ae084 100644
--- a/src/cairo-gl-composite.c
+++ b/src/cairo-gl-composite.c
@@ -1158,19 +1158,19 @@ _cairo_gl_composite_draw (cairo_gl_context_t *ctx,
unsigned int count = setup->vb_offset / setup->vertex_size;
if (! setup->pre_shader) {
- glDrawArrays (GL_QUADS, 0, count);
+ glDrawArrays (GL_TRIANGLES, 0, count);
} else {
_cairo_gl_use_program (ctx, setup->pre_shader);
_cairo_gl_set_operator (setup->dst, CAIRO_OPERATOR_DEST_OUT, TRUE);
_cairo_gl_set_src_alpha_operand (ctx, setup);
_cairo_gl_set_component_alpha_mask_operand (ctx, setup);
- glDrawArrays (GL_QUADS, 0, count);
+ glDrawArrays (GL_TRIANGLES, 0, count);
_cairo_gl_use_program (ctx, setup->shader);
_cairo_gl_set_operator (setup->dst, setup->op, TRUE);
_cairo_gl_set_src_operand (ctx, setup);
_cairo_gl_set_component_alpha_mask_operand (ctx, setup);
- glDrawArrays (GL_QUADS, 0, count);
+ glDrawArrays (GL_TRIANGLES, 0, count);
}
}
@@ -1284,10 +1284,13 @@ _cairo_gl_composite_emit_rect (cairo_gl_context_t *ctx,
GLfloat y2,
uint32_t color)
{
- _cairo_gl_composite_prepare_buffer (ctx, setup, 4);
+ _cairo_gl_composite_prepare_buffer (ctx, setup, 6);
_cairo_gl_composite_emit_vertex (ctx, setup, x1, y1, color);
_cairo_gl_composite_emit_vertex (ctx, setup, x2, y1, color);
+ _cairo_gl_composite_emit_vertex (ctx, setup, x1, y2, color);
+
+ _cairo_gl_composite_emit_vertex (ctx, setup, x2, y1, color);
_cairo_gl_composite_emit_vertex (ctx, setup, x2, y2, color);
_cairo_gl_composite_emit_vertex (ctx, setup, x1, y2, color);
}
@@ -1325,10 +1328,13 @@ _cairo_gl_composite_emit_glyph (cairo_gl_context_t *ctx,
GLfloat glyph_x2,
GLfloat glyph_y2)
{
- _cairo_gl_composite_prepare_buffer (ctx, setup, 4);
+ _cairo_gl_composite_prepare_buffer (ctx, setup, 6);
_cairo_gl_composite_emit_glyph_vertex (ctx, setup, x1, y1, glyph_x1, glyph_y1);
_cairo_gl_composite_emit_glyph_vertex (ctx, setup, x2, y1, glyph_x2, glyph_y1);
+ _cairo_gl_composite_emit_glyph_vertex (ctx, setup, x1, y2, glyph_x1, glyph_y2);
+
+ _cairo_gl_composite_emit_glyph_vertex (ctx, setup, x2, y1, glyph_x2, glyph_y1);
_cairo_gl_composite_emit_glyph_vertex (ctx, setup, x2, y2, glyph_x2, glyph_y2);
_cairo_gl_composite_emit_glyph_vertex (ctx, setup, x1, y2, glyph_x1, glyph_y2);
}
commit 2b771da47a87f86f378314bfe8033874d9444914
Author: Benjamin Otte <otte at redhat.com>
Date: Sun May 16 23:58:47 2010 +0200
xlib: ensure variable isn't uninitialized
diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index 3b01fde..ebc45b2 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -1067,6 +1067,8 @@ _draw_image_surface (cairo_xlib_surface_t *surface,
ret = _pixman_format_from_masks (&image_masks, &intermediate_format);
assert (ret);
+ own_data = FALSE;
+
pixman_image = pixman_image_create_bits (intermediate_format,
image->width,
image->height,
@@ -1089,7 +1091,6 @@ _draw_image_surface (cairo_xlib_surface_t *surface,
ximage.bits_per_pixel = image_masks.bpp;
ximage.data = (char *) pixman_image_get_data (pixman_image);
ximage.bytes_per_line = pixman_image_get_stride (pixman_image);
- own_data = FALSE;
ret = XInitImage (&ximage);
assert (ret != 0);
@@ -1135,6 +1136,7 @@ _draw_image_surface (cairo_xlib_surface_t *surface,
ximage.bytes_per_line = stride;
ximage.data = _cairo_malloc_ab (stride, ximage.height);
if (unlikely (ximage.data == NULL)) {
+ own_data = FALSE;
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto BAIL;
}
commit b768a33a602942825e5ec651ae7bafd6d5fc33ac
Author: Benjamin Otte <otte at redhat.com>
Date: Sun May 16 21:10:45 2010 +0200
gl: Set composite->has_component_alpha based on mask
Previously it was set when initing the composite structure, but that
doesn't allow resetting it when a new mask is used.
diff --git a/src/cairo-gl-composite.c b/src/cairo-gl-composite.c
index eae83b2..a9c7e25 100644
--- a/src/cairo-gl-composite.c
+++ b/src/cairo-gl-composite.c
@@ -507,6 +507,7 @@ _cairo_gl_composite_set_mask (cairo_gl_context_t *ctx,
int width, int height)
{
_cairo_gl_operand_destroy (&setup->mask);
+ setup->has_component_alpha = pattern && pattern->has_component_alpha;
return _cairo_gl_operand_init (ctx, &setup->mask, pattern,
setup->dst,
src_x, src_y,
@@ -520,6 +521,7 @@ _cairo_gl_composite_set_mask_spans (cairo_gl_context_t *ctx,
{
_cairo_gl_operand_destroy (&setup->mask);
setup->mask.type = CAIRO_GL_OPERAND_SPANS;
+ setup->has_component_alpha = FALSE;
}
void
@@ -1379,12 +1381,12 @@ _cairo_gl_composite_init (cairo_gl_context_t *ctx,
cairo_gl_surface_t *dst,
const cairo_pattern_t *src,
const cairo_pattern_t *mask,
- cairo_bool_t has_component_alpha,
+ cairo_bool_t assume_component_alpha,
const cairo_rectangle_int_t *rect)
{
memset (setup, 0, sizeof (cairo_gl_composite_t));
- if (has_component_alpha) {
+ if (assume_component_alpha) {
if (op != CAIRO_OPERATOR_CLEAR &&
op != CAIRO_OPERATOR_OVER &&
op != CAIRO_OPERATOR_ADD)
@@ -1395,7 +1397,6 @@ _cairo_gl_composite_init (cairo_gl_context_t *ctx,
}
setup->dst = dst;
- setup->has_component_alpha = has_component_alpha;
setup->op = op;
return CAIRO_STATUS_SUCCESS;
commit 1cde4601df8a3689450e2a0e15888c53aff12983
Author: Benjamin Otte <otte at redhat.com>
Date: Sun May 16 21:05:16 2010 +0200
gl: Replace _cairo_gl_operand_init() with setters for src/mask
Now cairo_gl_operand_t is no longer exposed outside of
cairo-gl-composite.c
diff --git a/src/cairo-gl-composite.c b/src/cairo-gl-composite.c
index 99c60bf..eae83b2 100644
--- a/src/cairo-gl-composite.c
+++ b/src/cairo-gl-composite.c
@@ -447,7 +447,7 @@ _cairo_gl_operand_destroy (cairo_gl_operand_t *operand)
operand->type = CAIRO_GL_OPERAND_NONE;
}
-cairo_int_status_t
+static cairo_int_status_t
_cairo_gl_operand_init (cairo_gl_context_t *ctx,
cairo_gl_operand_t *operand,
const cairo_pattern_t *pattern,
@@ -482,6 +482,38 @@ _cairo_gl_operand_init (cairo_gl_context_t *ctx,
}
}
+cairo_int_status_t
+_cairo_gl_composite_set_source (cairo_gl_context_t *ctx,
+ cairo_gl_composite_t *setup,
+ const cairo_pattern_t *pattern,
+ int src_x, int src_y,
+ int dst_x, int dst_y,
+ int width, int height)
+{
+ _cairo_gl_operand_destroy (&setup->src);
+ return _cairo_gl_operand_init (ctx, &setup->src, pattern,
+ setup->dst,
+ src_x, src_y,
+ dst_x, dst_y,
+ width, height);
+}
+
+cairo_int_status_t
+_cairo_gl_composite_set_mask (cairo_gl_context_t *ctx,
+ cairo_gl_composite_t *setup,
+ const cairo_pattern_t *pattern,
+ int src_x, int src_y,
+ int dst_x, int dst_y,
+ int width, int height)
+{
+ _cairo_gl_operand_destroy (&setup->mask);
+ return _cairo_gl_operand_init (ctx, &setup->mask, pattern,
+ setup->dst,
+ src_x, src_y,
+ dst_x, dst_y,
+ width, height);
+}
+
void
_cairo_gl_composite_set_mask_spans (cairo_gl_context_t *ctx,
cairo_gl_composite_t *setup)
diff --git a/src/cairo-gl-glyphs.c b/src/cairo-gl-glyphs.c
index e4c819b..d0aae23 100644
--- a/src/cairo-gl-glyphs.c
+++ b/src/cairo-gl-glyphs.c
@@ -293,11 +293,11 @@ _render_glyphs (cairo_gl_surface_t *dst,
goto FINISH;
}
- status = _cairo_gl_operand_init (ctx, &setup.src, source, dst,
- glyph_extents->x, glyph_extents->y,
- dst_x, dst_y,
- glyph_extents->width,
- glyph_extents->height);
+ status = _cairo_gl_composite_set_source (ctx, &setup, source,
+ glyph_extents->x, glyph_extents->y,
+ dst_x, dst_y,
+ glyph_extents->width,
+ glyph_extents->height);
if (unlikely (status))
goto FINISH;
diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h
index 65ef22a..3f53220 100644
--- a/src/cairo-gl-private.h
+++ b/src/cairo-gl-private.h
@@ -230,15 +230,6 @@ _cairo_gl_surface_draw_image (cairo_gl_surface_t *dst,
int width, int height,
int dst_x, int dst_y);
-cairo_private cairo_int_status_t
-_cairo_gl_operand_init (cairo_gl_context_t *ctx,
- cairo_gl_operand_t *operand,
- const cairo_pattern_t *pattern,
- cairo_gl_surface_t *dst,
- int src_x, int src_y,
- int dst_x, int dst_y,
- int width, int height);
-
static cairo_always_inline cairo_bool_t
_cairo_gl_device_has_glsl (cairo_device_t *device)
{
@@ -296,6 +287,22 @@ _cairo_gl_composite_set_clip_region (cairo_gl_context_t *ctx,
cairo_gl_composite_t *setup,
cairo_region_t *clip_region);
+cairo_private cairo_int_status_t
+_cairo_gl_composite_set_source (cairo_gl_context_t *ctx,
+ cairo_gl_composite_t *setup,
+ const cairo_pattern_t *pattern,
+ int src_x, int src_y,
+ int dst_x, int dst_y,
+ int width, int height);
+
+cairo_private cairo_int_status_t
+_cairo_gl_composite_set_mask (cairo_gl_context_t *ctx,
+ cairo_gl_composite_t *setup,
+ const cairo_pattern_t *pattern,
+ int src_x, int src_y,
+ int dst_x, int dst_y,
+ int width, int height);
+
cairo_private void
_cairo_gl_composite_set_mask_spans (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 ee319db..eeeac59 100644
--- a/src/cairo-gl-surface.c
+++ b/src/cairo-gl-surface.c
@@ -956,18 +956,18 @@ _cairo_gl_surface_composite (cairo_operator_t op,
if (unlikely (status))
goto CLEANUP;
- status = _cairo_gl_operand_init (ctx, &setup.src, src, dst,
- src_x, src_y,
- dst_x, dst_y,
- width, height);
+ status = _cairo_gl_composite_set_source (ctx, &setup, src,
+ src_x, src_y,
+ dst_x, dst_y,
+ width, height);
if (unlikely (status))
goto CLEANUP;
if (mask != NULL) {
- status = _cairo_gl_operand_init (ctx, &setup.mask, mask, dst,
- mask_x, mask_y,
- dst_x, dst_y,
- width, height);
+ status = _cairo_gl_composite_set_mask (ctx, &setup, mask,
+ mask_x, mask_y,
+ dst_x, dst_y,
+ width, height);
if (unlikely (status))
goto CLEANUP;
}
@@ -1426,11 +1426,11 @@ _cairo_gl_surface_create_span_renderer (cairo_operator_t op,
if (unlikely (status))
goto FAIL;
- status = _cairo_gl_operand_init (renderer->ctx,
- &renderer->setup.src, src, dst,
- rects->source.x, rects->source.y,
- extents->x, extents->y,
- extents->width, extents->height);
+ status = _cairo_gl_composite_set_source (renderer->ctx,
+ &renderer->setup, src,
+ rects->source.x, rects->source.y,
+ extents->x, extents->y,
+ extents->width, extents->height);
if (unlikely (status))
goto FAIL;
commit 6575cb7a95e109ab39eda58603ed6a76581a41b0
Author: Benjamin Otte <otte at redhat.com>
Date: Sun May 16 20:39:00 2010 +0200
gl: Convert glyphs path to use cairo_gl_composite_t
diff --git a/src/cairo-gl-composite.c b/src/cairo-gl-composite.c
index fccb989..99c60bf 100644
--- a/src/cairo-gl-composite.c
+++ b/src/cairo-gl-composite.c
@@ -415,6 +415,38 @@ _cairo_gl_gradient_operand_init (cairo_gl_context_t *ctx,
return CAIRO_INT_STATUS_UNSUPPORTED;
}
+static void
+_cairo_gl_operand_destroy (cairo_gl_operand_t *operand)
+{
+ switch (operand->type) {
+ case CAIRO_GL_OPERAND_CONSTANT:
+ break;
+ case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
+ glDeleteTextures (1, &operand->operand.linear.tex);
+ break;
+ case CAIRO_GL_OPERAND_RADIAL_GRADIENT:
+ glDeleteTextures (1, &operand->operand.radial.tex);
+ break;
+ case CAIRO_GL_OPERAND_TEXTURE:
+ if (operand->operand.texture.surface != NULL) {
+ cairo_gl_surface_t *surface = operand->operand.texture.surface;
+
+ _cairo_pattern_release_surface (operand->pattern,
+ &surface->base,
+ &operand->operand.texture.attributes);
+ }
+ break;
+ default:
+ case CAIRO_GL_OPERAND_COUNT:
+ ASSERT_NOT_REACHED;
+ case CAIRO_GL_OPERAND_NONE:
+ case CAIRO_GL_OPERAND_SPANS:
+ break;
+ }
+
+ operand->type = CAIRO_GL_OPERAND_NONE;
+}
+
cairo_int_status_t
_cairo_gl_operand_init (cairo_gl_context_t *ctx,
cairo_gl_operand_t *operand,
@@ -454,10 +486,27 @@ void
_cairo_gl_composite_set_mask_spans (cairo_gl_context_t *ctx,
cairo_gl_composite_t *setup)
{
+ _cairo_gl_operand_destroy (&setup->mask);
setup->mask.type = CAIRO_GL_OPERAND_SPANS;
}
void
+_cairo_gl_composite_set_mask_texture (cairo_gl_context_t *ctx,
+ cairo_gl_composite_t *setup,
+ GLuint tex,
+ cairo_bool_t has_component_alpha)
+{
+ _cairo_gl_operand_destroy (&setup->mask);
+
+ setup->has_component_alpha = has_component_alpha;
+
+ setup->mask.type = CAIRO_GL_OPERAND_TEXTURE;
+ setup->mask.operand.texture.tex = tex;
+ setup->mask.operand.texture.surface = NULL;
+ cairo_matrix_init_identity (&setup->mask.operand.texture.attributes.matrix);
+}
+
+void
_cairo_gl_composite_set_clip_region (cairo_gl_context_t *ctx,
cairo_gl_composite_t *setup,
cairo_region_t *clip_region)
@@ -466,36 +515,6 @@ _cairo_gl_composite_set_clip_region (cairo_gl_context_t *ctx,
}
static void
-_cairo_gl_operand_destroy (cairo_gl_operand_t *operand)
-{
- switch (operand->type) {
- case CAIRO_GL_OPERAND_CONSTANT:
- break;
- case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
- glDeleteTextures (1, &operand->operand.linear.tex);
- break;
- case CAIRO_GL_OPERAND_RADIAL_GRADIENT:
- glDeleteTextures (1, &operand->operand.radial.tex);
- break;
- case CAIRO_GL_OPERAND_TEXTURE:
- if (operand->operand.texture.surface != NULL) {
- cairo_gl_surface_t *surface = operand->operand.texture.surface;
-
- _cairo_pattern_release_surface (operand->pattern,
- &surface->base,
- &operand->operand.texture.attributes);
- }
- break;
- default:
- case CAIRO_GL_OPERAND_COUNT:
- ASSERT_NOT_REACHED;
- case CAIRO_GL_OPERAND_NONE:
- case CAIRO_GL_OPERAND_SPANS:
- break;
- }
-}
-
-static void
_cairo_gl_set_tex_combine_constant_color (cairo_gl_context_t *ctx,
cairo_gl_composite_t *setup,
int tex_unit,
@@ -1121,7 +1140,7 @@ _cairo_gl_composite_draw (cairo_gl_context_t *ctx,
}
}
-static inline void
+void
_cairo_gl_composite_flush (cairo_gl_context_t *ctx,
cairo_gl_composite_t *setup)
{
@@ -1239,6 +1258,47 @@ _cairo_gl_composite_emit_rect (cairo_gl_context_t *ctx,
_cairo_gl_composite_emit_vertex (ctx, setup, x1, y2, color);
}
+static inline void
+_cairo_gl_composite_emit_glyph_vertex (cairo_gl_context_t *ctx,
+ cairo_gl_composite_t *setup,
+ GLfloat x,
+ GLfloat y,
+ GLfloat glyph_x,
+ GLfloat glyph_y)
+{
+ GLfloat *vb = (GLfloat *) (void *) &setup->vb[setup->vb_offset];
+
+ *vb++ = x;
+ *vb++ = y;
+
+ _cairo_gl_operand_emit (&setup->src, &vb, x, y, 0);
+
+ *vb++ = glyph_x;
+ *vb++ = glyph_y;
+
+ setup->vb_offset += setup->vertex_size;
+}
+
+void
+_cairo_gl_composite_emit_glyph (cairo_gl_context_t *ctx,
+ cairo_gl_composite_t *setup,
+ GLfloat x1,
+ GLfloat y1,
+ GLfloat x2,
+ GLfloat y2,
+ GLfloat glyph_x1,
+ GLfloat glyph_y1,
+ GLfloat glyph_x2,
+ GLfloat glyph_y2)
+{
+ _cairo_gl_composite_prepare_buffer (ctx, setup, 4);
+
+ _cairo_gl_composite_emit_glyph_vertex (ctx, setup, x1, y1, glyph_x1, glyph_y1);
+ _cairo_gl_composite_emit_glyph_vertex (ctx, setup, x2, y1, glyph_x2, glyph_y1);
+ _cairo_gl_composite_emit_glyph_vertex (ctx, setup, x2, y2, glyph_x2, glyph_y2);
+ _cairo_gl_composite_emit_glyph_vertex (ctx, setup, x1, y2, glyph_x1, glyph_y2);
+}
+
void
_cairo_gl_composite_end (cairo_gl_context_t *ctx,
cairo_gl_composite_t *setup)
diff --git a/src/cairo-gl-glyphs.c b/src/cairo-gl-glyphs.c
index 23ac40e..e4c819b 100644
--- a/src/cairo-gl-glyphs.c
+++ b/src/cairo-gl-glyphs.c
@@ -106,6 +106,9 @@ _cairo_gl_glyph_cache_add_glyph (cairo_gl_context_t *ctx,
if (status)
return status;
+ glActiveTexture (GL_TEXTURE1);
+ glBindTexture (ctx->tex_target, cache->tex);
+
glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
glPixelStorei (GL_UNPACK_ROW_LENGTH,
glyph_surface->stride /
@@ -250,211 +253,6 @@ _cairo_gl_surface_scaled_glyph_fini (cairo_scaled_glyph_t *scaled_glyph,
}
}
-typedef struct _cairo_gl_glyphs_setup
-{
- unsigned int vbo_size; /* units of floats */
- unsigned int vb_offset; /* units of floats */
- unsigned int vertex_size; /* units of floats */
- unsigned int num_prims;
- float *vb;
- cairo_gl_composite_t *composite;
- cairo_region_t *clip;
- cairo_gl_surface_t *dst;
- cairo_operator_t op;
- cairo_bool_t component_alpha;
- cairo_gl_shader_in_t in;
-} cairo_gl_glyphs_setup_t;
-
-static void
-_cairo_gl_glyphs_set_shader_fixed (cairo_gl_context_t *ctx,
- cairo_gl_glyphs_setup_t *setup,
- cairo_gl_shader_in_t in)
-{
- if (setup->in == in)
- return;
-
- setup->in = in;
-
- if (in != CAIRO_GL_SHADER_IN_CA_SOURCE_ALPHA)
- _cairo_gl_set_src_operand (ctx, setup->composite);
- else
- _cairo_gl_set_src_alpha_operand (ctx, setup->composite);
-
- /* Set up the IN operator for source IN mask.
- *
- * IN (normal, any op): dst.argb = src.argb * mask.aaaa
- * IN (component, ADD): dst.argb = src.argb * mask.argb
- *
- * The mask channel selection for component alpha ADD will be updated in
- * the loop over glyphs below.
- */
- glActiveTexture (GL_TEXTURE1);
- 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_TEXTURE1);
- glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_TEXTURE1);
- if (in == CAIRO_GL_SHADER_IN_NORMAL)
- glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_ALPHA);
- else
- 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_PREVIOUS);
- glTexEnvi (GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_PREVIOUS);
- glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
- glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
-}
-
-static void
-_cairo_gl_glyphs_set_shader (cairo_gl_context_t *ctx,
- cairo_gl_glyphs_setup_t *setup,
- cairo_gl_shader_in_t in)
-{
- if (setup->in == in)
- return;
-
- if (_cairo_gl_device_has_glsl (&ctx->base)) {
- cairo_status_t status;
-
- status = _cairo_gl_get_program (ctx,
- setup->composite->src.type,
- CAIRO_GL_OPERAND_TEXTURE,
- in,
- &setup->composite->shader);
- if (!_cairo_status_is_error (status)) {
- setup->in = in;
- _cairo_gl_use_program (ctx, setup->composite->shader);
- _cairo_gl_set_src_operand (ctx, setup->composite);
- return;
- }
- }
-
- _cairo_gl_glyphs_set_shader_fixed (ctx, setup, in);
-}
-
-static void
-_cairo_gl_glyphs_draw (cairo_gl_context_t *ctx,
- cairo_gl_glyphs_setup_t *setup)
-{
- if (!setup->component_alpha || setup->op != CAIRO_OPERATOR_OVER) {
- glDrawArrays (GL_QUADS, 0, 4 * setup->num_prims);
- } else {
- _cairo_gl_set_operator (setup->dst, CAIRO_OPERATOR_DEST_OUT, TRUE);
- _cairo_gl_glyphs_set_shader(ctx, setup,
- CAIRO_GL_SHADER_IN_CA_SOURCE_ALPHA);
- glDrawArrays (GL_QUADS, 0, 4 * setup->num_prims);
-
- _cairo_gl_set_operator (setup->dst, CAIRO_OPERATOR_ADD, TRUE);
- _cairo_gl_glyphs_set_shader(ctx, setup,
- CAIRO_GL_SHADER_IN_CA_SOURCE);
- glDrawArrays (GL_QUADS, 0, 4 * setup->num_prims);
- }
-}
-
-static void
-_cairo_gl_flush_glyphs (cairo_gl_context_t *ctx,
- cairo_gl_glyphs_setup_t *setup)
-{
- int i;
-
- if (setup->vb == NULL)
- return;
-
- glUnmapBufferARB (GL_ARRAY_BUFFER_ARB);
- setup->vb = NULL;
-
- if (setup->num_prims == 0)
- return;
-
- if (!setup->component_alpha) {
- _cairo_gl_set_operator (setup->dst, setup->op, FALSE);
- _cairo_gl_glyphs_set_shader(ctx, setup, CAIRO_GL_SHADER_IN_NORMAL);
- } else if (setup->op == CAIRO_OPERATOR_ADD) {
- _cairo_gl_set_operator (setup->dst, setup->op, FALSE);
- _cairo_gl_glyphs_set_shader(ctx, setup, CAIRO_GL_SHADER_IN_CA_SOURCE);
- }
-
- if (setup->clip) {
- int num_rectangles = cairo_region_num_rectangles (setup->clip);
-
- glEnable (GL_SCISSOR_TEST);
- for (i = 0; i < num_rectangles; i++) {
- cairo_rectangle_int_t rect;
-
- cairo_region_get_rectangle (setup->clip, i, &rect);
-
- glScissor (rect.x,
- _cairo_gl_y_flip (setup->dst, rect.y),
- rect.x + rect.width,
- _cairo_gl_y_flip (setup->dst,
- rect.y + rect.height));
- _cairo_gl_glyphs_draw (ctx, setup);
- }
- glDisable (GL_SCISSOR_TEST);
- } else {
- _cairo_gl_glyphs_draw (ctx, setup);
- }
- setup->num_prims = 0;
-}
-
-static void
-_cairo_gl_glyphs_emit_vertex (cairo_gl_glyphs_setup_t *setup,
- int x, int y, float glyph_x, float glyph_y)
-{
- int i = 0;
- float *vb = &setup->vb[setup->vb_offset];
- cairo_surface_attributes_t *src_attributes;
-
- src_attributes = &setup->composite->src.operand.texture.attributes;
-
- vb[i++] = x;
- vb[i++] = y;
-
- vb[i++] = glyph_x;
- vb[i++] = glyph_y;
-
- if (setup->composite->src.type == CAIRO_GL_OPERAND_TEXTURE) {
- double s = x;
- double t = y;
- cairo_matrix_transform_point (&src_attributes->matrix, &s, &t);
- vb[i++] = s;
- vb[i++] = t;
- }
-
- setup->vb_offset += setup->vertex_size;
-}
-
-
-static void
-_cairo_gl_emit_glyph_rectangle (cairo_gl_context_t *ctx,
- cairo_gl_glyphs_setup_t *setup,
- int x1, int y1,
- int x2, int y2,
- cairo_gl_glyph_private_t *glyph)
-{
- if (setup->vb != NULL &&
- setup->vb_offset + 4 * setup->vertex_size > setup->vbo_size) {
- _cairo_gl_flush_glyphs (ctx, setup);
- }
-
- if (setup->vb == NULL) {
- glBufferDataARB (GL_ARRAY_BUFFER_ARB,
- setup->vbo_size * sizeof (GLfloat),
- NULL, GL_STREAM_DRAW_ARB);
- setup->vb = glMapBufferARB (GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
- setup->vb_offset = 0;
- }
-
- _cairo_gl_glyphs_emit_vertex (setup, x1, y1, glyph->p1.x, glyph->p1.y);
- _cairo_gl_glyphs_emit_vertex (setup, x2, y1, glyph->p2.x, glyph->p1.y);
- _cairo_gl_glyphs_emit_vertex (setup, x2, y2, glyph->p2.x, glyph->p2.y);
- _cairo_gl_glyphs_emit_vertex (setup, x1, y2, glyph->p1.x, glyph->p2.y);
- setup->num_prims++;
-}
-
static cairo_status_t
_render_glyphs (cairo_gl_surface_t *dst,
int dst_x, int dst_y,
@@ -468,11 +266,10 @@ _render_glyphs (cairo_gl_surface_t *dst,
cairo_region_t *clip_region,
int *remaining_glyphs)
{
- cairo_format_t last_format = (cairo_format_t) -1;
+ cairo_format_t last_format = CAIRO_FORMAT_INVALID;
cairo_gl_glyph_cache_t *cache = NULL;
cairo_gl_context_t *ctx;
- cairo_gl_glyphs_setup_t setup;
- cairo_gl_composite_t composite_setup;
+ cairo_gl_composite_t setup;
cairo_status_t status;
int i = 0;
@@ -482,28 +279,27 @@ _render_glyphs (cairo_gl_surface_t *dst,
if (unlikely (status))
return status;
- status = _cairo_gl_composite_init (ctx, &composite_setup,
+ _cairo_scaled_font_freeze_cache (scaled_font);
+
+ status = _cairo_gl_composite_init (ctx, &setup,
op, dst, source, NULL,
- FALSE, glyph_extents);
+ TRUE, glyph_extents);
if (unlikely (status))
- goto CLEANUP_FONT;
+ goto FINISH;
- status = _cairo_gl_operand_init (ctx, &composite_setup.src, source, dst,
+ if (! _cairo_gl_surface_owns_font (dst, scaled_font)) {
+ status = CAIRO_INT_STATUS_UNSUPPORTED;
+ goto FINISH;
+ }
+
+ status = _cairo_gl_operand_init (ctx, &setup.src, source, dst,
glyph_extents->x, glyph_extents->y,
dst_x, dst_y,
glyph_extents->width,
glyph_extents->height);
if (unlikely (status))
- goto CLEANUP_FONT;
-
- _cairo_gl_context_set_destination (ctx, dst);
-
- _cairo_scaled_font_freeze_cache (scaled_font);
- if (! _cairo_gl_surface_owns_font (dst, scaled_font)) {
- status = CAIRO_INT_STATUS_UNSUPPORTED;
- goto CLEANUP_FONT;
- }
+ goto FINISH;
if (scaled_font->surface_private == NULL) {
scaled_font->surface_private = ctx;
@@ -511,43 +307,11 @@ _render_glyphs (cairo_gl_surface_t *dst,
cairo_list_add (&scaled_font->link, &ctx->fonts);
}
- /* Create our VBO so that we can accumulate a bunch of glyph primitives
- * into one giant DrawArrays.
- */
- memset(&setup, 0, sizeof(setup));
- setup.composite = &composite_setup;
- setup.clip = clip_region;
- setup.dst = dst;
- setup.vertex_size = 4;
- if (composite_setup.src.type == CAIRO_GL_OPERAND_TEXTURE)
- setup.vertex_size += 2;
- setup.vbo_size = num_glyphs * 4 * setup.vertex_size;
- if (setup.vbo_size > 4096)
- setup.vbo_size = 4096;
- setup.op = op;
- setup.in = CAIRO_GL_SHADER_IN_COUNT; /* unset */
-
- glBindBufferARB (GL_ARRAY_BUFFER_ARB, ctx->vbo);
-
- glVertexPointer (2, GL_FLOAT, setup.vertex_size * sizeof (GLfloat),
- (void *)(uintptr_t)(0));
- glEnableClientState (GL_VERTEX_ARRAY);
- if (composite_setup.src.type == CAIRO_GL_OPERAND_TEXTURE) {
- /* Note that we're packing texcoord 0 after texcoord 1, for
- * convenience.
- */
- glClientActiveTexture (GL_TEXTURE0);
- glTexCoordPointer (2, GL_FLOAT, setup.vertex_size * sizeof (GLfloat),
- (void *)(uintptr_t)(4 * sizeof (GLfloat)));
- glEnableClientState (GL_TEXTURE_COORD_ARRAY);
- }
- glClientActiveTexture (GL_TEXTURE1);
- glTexCoordPointer (2, GL_FLOAT, setup.vertex_size * sizeof (GLfloat),
- (void *)(uintptr_t)(2 * sizeof (GLfloat)));
- glEnableClientState (GL_TEXTURE_COORD_ARRAY);
+ _cairo_gl_composite_set_clip_region (ctx, &setup, clip_region);
for (i = 0; i < num_glyphs; i++) {
cairo_scaled_glyph_t *scaled_glyph;
+ cairo_gl_glyph_private_t *glyph;
double x_offset, y_offset;
double x1, x2, y1, y2;
@@ -571,26 +335,23 @@ _render_glyphs (cairo_gl_surface_t *dst,
}
if (scaled_glyph->surface->format != last_format) {
- /* Switching textures, so flush any queued prims. */
- _cairo_gl_flush_glyphs (ctx, &setup);
+ if (last_format != CAIRO_FORMAT_INVALID)
+ _cairo_gl_composite_end (ctx, &setup);
- glActiveTexture (GL_TEXTURE1);
cache = cairo_gl_context_get_glyph_cache (ctx,
scaled_glyph->surface->format);
- glBindTexture (ctx->tex_target, cache->tex);
-
last_format = scaled_glyph->surface->format;
- /* If we're doing component alpha in this function, it should
- * only be in the case of CAIRO_OPERATOR_ADD. In that case, we just
- * need to make sure we send the rgb bits down to the destination.
- */
- if (last_format == CAIRO_FORMAT_ARGB32) {
+
+ _cairo_gl_composite_set_mask_texture (ctx,
+ &setup,
+ cache->tex,
+ last_format == CAIRO_FORMAT_ARGB32);
+
+ if (last_format == CAIRO_FORMAT_ARGB32)
*has_component_alpha = TRUE;
- setup.component_alpha = TRUE;
- } else {
- setup.component_alpha = FALSE;
- }
+
+ status = _cairo_gl_composite_begin (ctx, &setup);
}
if (scaled_glyph->surface_private == NULL) {
@@ -598,7 +359,7 @@ _render_glyphs (cairo_gl_surface_t *dst,
if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
/* Cache is full, so flush existing prims and try again. */
- _cairo_gl_flush_glyphs (ctx, &setup);
+ _cairo_gl_composite_flush (ctx, &setup);
_cairo_gl_glyph_cache_unlock (cache);
status = _cairo_gl_glyph_cache_add_glyph (ctx, cache, scaled_glyph);
}
@@ -615,37 +376,19 @@ _render_glyphs (cairo_gl_surface_t *dst,
x2 = x1 + scaled_glyph->surface->width;
y2 = y1 + scaled_glyph->surface->height;
- _cairo_gl_emit_glyph_rectangle (ctx, &setup,
+ glyph = _cairo_gl_glyph_cache_lock (cache, scaled_glyph);
+ _cairo_gl_composite_emit_glyph (ctx, &setup,
x1, y1, x2, y2,
- _cairo_gl_glyph_cache_lock (cache, scaled_glyph));
+ glyph->p1.x, glyph->p1.y,
+ glyph->p2.x, glyph->p2.y);
}
status = CAIRO_STATUS_SUCCESS;
FINISH:
- _cairo_gl_flush_glyphs (ctx, &setup);
- CLEANUP_FONT:
+ _cairo_gl_composite_end (ctx, &setup);
_cairo_scaled_font_thaw_cache (scaled_font);
- glDisable (GL_BLEND);
- glDisable (GL_SCISSOR_TEST);
-
- glDisableClientState (GL_VERTEX_ARRAY);
-
- glClientActiveTexture (GL_TEXTURE0);
- glDisableClientState (GL_TEXTURE_COORD_ARRAY);
- glActiveTexture (GL_TEXTURE0);
- glDisable (GL_TEXTURE_1D);
- glDisable (ctx->tex_target);
-
- glClientActiveTexture (GL_TEXTURE1);
- glDisableClientState (GL_TEXTURE_COORD_ARRAY);
- glActiveTexture (GL_TEXTURE1);
- glDisable (ctx->tex_target);
- _cairo_gl_use_program (ctx, NULL);
-
- glBindBufferARB (GL_ARRAY_BUFFER_ARB, 0);
-
- _cairo_gl_composite_fini (ctx, &composite_setup);
+ _cairo_gl_composite_fini (ctx, &setup);
_cairo_gl_context_release (ctx);
diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h
index c24dd6f..65ef22a 100644
--- a/src/cairo-gl-private.h
+++ b/src/cairo-gl-private.h
@@ -300,6 +300,12 @@ cairo_private void
_cairo_gl_composite_set_mask_spans (cairo_gl_context_t *ctx,
cairo_gl_composite_t *setup);
+cairo_private void
+_cairo_gl_composite_set_mask_texture (cairo_gl_context_t *ctx,
+ cairo_gl_composite_t *setup,
+ GLuint tex,
+ cairo_bool_t has_component_alpha);
+
cairo_private cairo_status_t
_cairo_gl_composite_begin (cairo_gl_context_t *ctx,
cairo_gl_composite_t *setup);
@@ -314,6 +320,22 @@ _cairo_gl_composite_emit_rect (cairo_gl_context_t *ctx,
uint32_t color);
cairo_private void
+_cairo_gl_composite_emit_glyph (cairo_gl_context_t *ctx,
+ cairo_gl_composite_t *setup,
+ GLfloat x1,
+ GLfloat y1,
+ GLfloat x2,
+ GLfloat y2,
+ GLfloat glyph_x1,
+ GLfloat glyph_y1,
+ GLfloat glyph_x2,
+ GLfloat glyph_y2);
+
+cairo_private void
+_cairo_gl_composite_flush (cairo_gl_context_t *ctx,
+ cairo_gl_composite_t *setup);
+
+cairo_private void
_cairo_gl_composite_end (cairo_gl_context_t *ctx,
cairo_gl_composite_t *setup);
commit 8937f2b4b5e4bcb8ada1e478df6a7329c0b80a5a
Author: Benjamin Otte <otte at redhat.com>
Date: Sun May 16 13:19:48 2010 +0200
gl: Require ARB_vertex_buffer_object extension unconditionally
<anholt> we shouldn't bother with non-vbo support. there's no
justification for a driver not supporting it.
diff --git a/src/cairo-gl-composite.c b/src/cairo-gl-composite.c
index a93267c..fccb989 100644
--- a/src/cairo-gl-composite.c
+++ b/src/cairo-gl-composite.c
@@ -1292,7 +1292,6 @@ _cairo_gl_composite_init (cairo_gl_context_t *ctx,
{
memset (setup, 0, sizeof (cairo_gl_composite_t));
-
if (has_component_alpha) {
if (op != CAIRO_OPERATOR_CLEAR &&
op != CAIRO_OPERATOR_OVER &&
diff --git a/src/cairo-gl-device.c b/src/cairo-gl-device.c
index 2bfeb51..99dfa18 100644
--- a/src/cairo-gl-device.c
+++ b/src/cairo-gl-device.c
@@ -134,6 +134,9 @@ _cairo_gl_context_init (cairo_gl_context_t *ctx)
fprintf (stderr, " GL_EXT_framebuffer_object\n");
if (! GLEW_ARB_texture_env_combine)
fprintf (stderr, " GL_ARB_texture_env_combine\n");
+ if (! GLEW_ARB_vertex_buffer_object)
+ fprintf (stderr, " GL_ARB_vertex_buffer_object\n");
+
/* EXT_bgra is used in two places:
* - draw_image to upload common pixman formats without hand-swizzling.
* - get_image to download common pixman formats without hand-swizzling.
@@ -156,8 +159,6 @@ _cairo_gl_context_init (cairo_gl_context_t *ctx)
else
ctx->tex_target = GL_TEXTURE_2D;
- ctx->has_span_renderer = GLEW_ARB_vertex_buffer_object;
-
_cairo_gl_context_init_shaders (ctx);
init_shader_program (&ctx->fill_rectangles_shader);
diff --git a/src/cairo-gl-glyphs.c b/src/cairo-gl-glyphs.c
index 76ac5aa..23ac40e 100644
--- a/src/cairo-gl-glyphs.c
+++ b/src/cairo-gl-glyphs.c
@@ -740,9 +740,6 @@ _cairo_gl_surface_show_glyphs (void *abstract_dst,
cairo_status_t status;
int i;
- if (! GLEW_ARB_vertex_buffer_object)
- return UNSUPPORTED ("requires ARB_vertex_buffer_object");
-
if (! _cairo_gl_operator_is_supported (op))
return UNSUPPORTED ("unsupported operator");
diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h
index aad11a0..c24dd6f 100644
--- a/src/cairo-gl-private.h
+++ b/src/cairo-gl-private.h
@@ -132,7 +132,6 @@ typedef struct _cairo_gl_context {
GLint max_framebuffer_size;
GLint max_texture_size;
GLenum tex_target;
- cairo_bool_t has_span_renderer;
const cairo_gl_shader_impl_t *shader_impl;
@@ -246,12 +245,6 @@ _cairo_gl_device_has_glsl (cairo_device_t *device)
return ((cairo_gl_context_t *) device)->shader_impl != NULL;
}
-static cairo_always_inline cairo_bool_t
-cairo_gl_device_check_span_renderer (cairo_device_t *device)
-{
- return ((cairo_gl_context_t *) device)->has_span_renderer;
-}
-
static cairo_always_inline cairo_status_t cairo_warn
_cairo_gl_context_acquire (cairo_device_t *device,
cairo_gl_context_t **ctx)
diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c
index e898120..ee319db 100644
--- a/src/cairo-gl-surface.c
+++ b/src/cairo-gl-surface.c
@@ -1369,22 +1369,18 @@ _cairo_gl_surface_span_renderer_finish (void *abstract_renderer)
}
static cairo_bool_t
-_cairo_gl_surface_check_span_renderer (cairo_operator_t op,
+_cairo_gl_surface_check_span_renderer (cairo_operator_t op,
const cairo_pattern_t *pattern,
- void *abstract_dst,
- cairo_antialias_t antialias)
+ void *abstract_dst,
+ cairo_antialias_t antialias)
{
- cairo_surface_t *surface = abstract_dst;
-
if (! _cairo_gl_operator_is_supported (op))
return FALSE;
- if (! cairo_gl_device_check_span_renderer (surface->device))
- return FALSE;
-
return TRUE;
(void) pattern;
+ (void) abstract_dst;
(void) antialias;
}
commit 29dfd5b488e16ec8be879b2415635df93b874afc
Author: Benjamin Otte <otte at redhat.com>
Date: Sun May 16 03:36:05 2010 +0200
gl: Remove unused variables
diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c
index 4e6976b..e898120 100644
--- a/src/cairo-gl-surface.c
+++ b/src/cairo-gl-surface.c
@@ -939,8 +939,7 @@ _cairo_gl_surface_composite (cairo_operator_t op,
unsigned int height,
cairo_region_t *clip_region)
{
- cairo_gl_surface_t *dst = abstract_dst;
- cairo_surface_attributes_t *src_attributes, *mask_attributes = NULL;
+ cairo_gl_surface_t *dst = abstract_dst;
cairo_gl_context_t *ctx;
cairo_status_t status;
cairo_gl_composite_t setup;
@@ -964,8 +963,6 @@ _cairo_gl_surface_composite (cairo_operator_t op,
if (unlikely (status))
goto CLEANUP;
- src_attributes = &setup.src.operand.texture.attributes;
-
if (mask != NULL) {
status = _cairo_gl_operand_init (ctx, &setup.mask, mask, dst,
mask_x, mask_y,
@@ -973,8 +970,6 @@ _cairo_gl_surface_composite (cairo_operator_t op,
width, height);
if (unlikely (status))
goto CLEANUP;
-
- mask_attributes = &setup.mask.operand.texture.attributes;
}
status = _cairo_gl_composite_begin (ctx, &setup);
commit 4144488f516214b675d25d48add8cbd83fd17025
Author: Benjamin Otte <otte at redhat.com>
Date: Sun May 16 03:29:04 2010 +0200
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.
diff --git a/src/cairo-gl-composite.c b/src/cairo-gl-composite.c
index c32c89b..a93267c 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 870d80c..aad11a0 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 6f91dbd..4e6976b 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;
commit 6e81d85e3682f14e1c5dbe97dda2cc1fcd32df3a
Author: Benjamin Otte <otte at redhat.com>
Date: Sun May 16 03:27:28 2010 +0200
gl: Change _cairo_gl_composite_emit_rect()
Two changes:
- The function now takes x1/y1,x2/y2 instead of x,y,width,height
- The function takes a color uint32_t. This will be used by spans.
diff --git a/src/cairo-gl-composite.c b/src/cairo-gl-composite.c
index 272ebe2..c32c89b 100644
--- a/src/cairo-gl-composite.c
+++ b/src/cairo-gl-composite.c
@@ -1111,7 +1111,8 @@ static inline void
_cairo_gl_operand_emit (cairo_gl_operand_t *operand,
GLfloat ** vb,
GLfloat x,
- GLfloat y)
+ GLfloat y,
+ uint32_t color)
{
switch (operand->type) {
default:
@@ -1143,15 +1144,16 @@ static inline void
_cairo_gl_composite_emit_vertex (cairo_gl_context_t *ctx,
cairo_gl_composite_t *setup,
GLfloat x,
- GLfloat y)
+ GLfloat y,
+ uint32_t color)
{
GLfloat *vb = (GLfloat *) (void *) &setup->vb[setup->vb_offset];
*vb++ = x;
*vb++ = y;
- _cairo_gl_operand_emit (&setup->src, &vb, x, y);
- _cairo_gl_operand_emit (&setup->mask, &vb, x, y);
+ _cairo_gl_operand_emit (&setup->src, &vb, x, y, color);
+ _cairo_gl_operand_emit (&setup->mask, &vb, x, y, color);
setup->vb_offset += setup->vertex_size;
}
@@ -1159,17 +1161,18 @@ _cairo_gl_composite_emit_vertex (cairo_gl_context_t *ctx,
void
_cairo_gl_composite_emit_rect (cairo_gl_context_t *ctx,
cairo_gl_composite_t *setup,
- GLfloat x,
- GLfloat y,
- GLfloat width,
- GLfloat height)
+ GLfloat x1,
+ GLfloat y1,
+ GLfloat x2,
+ GLfloat y2,
+ uint32_t color)
{
_cairo_gl_composite_prepare_buffer (ctx, setup, 4);
- _cairo_gl_composite_emit_vertex (ctx, setup, x, y);
- _cairo_gl_composite_emit_vertex (ctx, setup, x + width, y);
- _cairo_gl_composite_emit_vertex (ctx, setup, x + width, y + height);
- _cairo_gl_composite_emit_vertex (ctx, setup, x, y + height);
+ _cairo_gl_composite_emit_vertex (ctx, setup, x1, y1, color);
+ _cairo_gl_composite_emit_vertex (ctx, setup, x2, y1, color);
+ _cairo_gl_composite_emit_vertex (ctx, setup, x2, y2, color);
+ _cairo_gl_composite_emit_vertex (ctx, setup, x1, y2, color);
}
void
diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h
index e926689..870d80c 100644
--- a/src/cairo-gl-private.h
+++ b/src/cairo-gl-private.h
@@ -304,10 +304,11 @@ _cairo_gl_composite_begin (cairo_gl_context_t *ctx,
cairo_private void
_cairo_gl_composite_emit_rect (cairo_gl_context_t *ctx,
cairo_gl_composite_t *setup,
- GLfloat x,
- GLfloat y,
- GLfloat width,
- GLfloat height);
+ GLfloat x1,
+ GLfloat y1,
+ GLfloat x2,
+ GLfloat y2,
+ uint32_t color);
cairo_private void
_cairo_gl_composite_end (cairo_gl_context_t *ctx,
diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c
index 4bec4ee..6f91dbd 100644
--- a/src/cairo-gl-surface.c
+++ b/src/cairo-gl-surface.c
@@ -1001,13 +1001,15 @@ _cairo_gl_surface_composite (cairo_operator_t op,
cairo_region_get_rectangle (clip_region, i, &rect);
_cairo_gl_composite_emit_rect (ctx, &setup,
- rect.x, rect.y,
- rect.width, rect.height);
+ rect.x, rect.y,
+ rect.x + rect.width, rect.y + rect.height,
+ 0);
}
} else {
_cairo_gl_composite_emit_rect (ctx, &setup,
- dst_x, dst_y,
- width, height);
+ dst_x, dst_y,
+ dst_x + width, dst_y + height,
+ 0);
}
_cairo_gl_composite_end (ctx, &setup);
commit f8398cc2d83eb9ac37874f71d4f8805dbf0df412
Author: Benjamin Otte <otte at redhat.com>
Date: Sun May 16 02:34:18 2010 +0200
gl: remove unused variables from span renderer
diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c
index 24abb90..4bec4ee 100644
--- a/src/cairo-gl-surface.c
+++ b/src/cairo-gl-surface.c
@@ -1284,10 +1284,6 @@ typedef struct _cairo_gl_surface_span_renderer {
int xmin, xmax;
- cairo_operator_t op;
- cairo_antialias_t antialias;
-
- cairo_gl_surface_t *dst;
cairo_gl_context_t *ctx;
cairo_region_t *clip;
@@ -1579,9 +1575,6 @@ _cairo_gl_surface_create_span_renderer (cairo_operator_t op,
}
renderer->xmin = extents->x;
renderer->xmax = extents->x + extents->width;
- renderer->op = op;
- renderer->antialias = antialias;
- renderer->dst = dst;
renderer->clip = clip_region;
status = _cairo_gl_context_acquire (dst->base.device, &renderer->ctx);
commit f5c5077def47b91b57dfbc8c2622b4aaf5ca8fbb
Author: Benjamin Otte <otte at redhat.com>
Date: Sun May 16 02:06:43 2010 +0200
gl: Support component alpha in gl_composite_t
Use that to get rid of cairo_gl_surface_composite_component_alpha()
diff --git a/src/cairo-gl-composite.c b/src/cairo-gl-composite.c
index 8be453e..272ebe2 100644
--- a/src/cairo-gl-composite.c
+++ b/src/cairo-gl-composite.c
@@ -890,6 +890,100 @@ _cairo_gl_operand_get_vertex_size (cairo_gl_operand_type_t type)
}
}
+static cairo_status_t
+_cairo_gl_composite_begin_component_alpha (cairo_gl_context_t *ctx,
+ cairo_gl_composite_t *setup)
+{
+ cairo_status_t status;
+
+ /* For CLEAR, cairo's rendering equation (quoting Owen's description in:
+ * http://lists.cairographics.org/archives/cairo/2005-August/004992.html)
+ * is:
+ * mask IN clip ? src OP dest : dest
+ * or more simply:
+ * mask IN CLIP ? 0 : dest
+ *
+ * where the ternary operator A ? B : C is (A * B) + ((1 - A) * C).
+ *
+ * The model we use in _cairo_gl_set_operator() is Render's:
+ * src IN mask IN clip OP dest
+ * which would boil down to:
+ * 0 (bounded by the extents of the drawing).
+ *
+ * However, we can do a Render operation using an opaque source
+ * and DEST_OUT to produce:
+ * 1 IN mask IN clip DEST_OUT dest
+ * which is
+ * mask IN clip ? 0 : dest
+ */
+ if (setup->op == CAIRO_OPERATOR_CLEAR) {
+ _cairo_gl_solid_operand_init (&setup->src, CAIRO_COLOR_WHITE);
+ setup->op = CAIRO_OPERATOR_DEST_OUT;
+ }
+
+ /**
+ * implements component-alpha %CAIRO_OPERATOR_OVER using two passes of
+ * the simpler operations %CAIRO_OPERATOR_DEST_OUT and %CAIRO_OPERATOR_ADD.
+ *
+ * From http://anholt.livejournal.com/32058.html:
+ *
+ * The trouble is that component-alpha rendering requires two different sources
+ * for blending: one for the source value to the blender, which is the
+ * per-channel multiplication of source and mask, and one for the source alpha
+ * for multiplying with the destination channels, which is the multiplication
+ * of the source channels by the mask alpha. So the equation for Over is:
+ *
+ * dst.A = src.A * mask.A + (1 - (src.A * mask.A)) * dst.A
+ * dst.R = src.R * mask.R + (1 - (src.A * mask.R)) * dst.R
+ * dst.G = src.G * mask.G + (1 - (src.A * mask.G)) * dst.G
+ * dst.B = src.B * mask.B + (1 - (src.A * mask.B)) * dst.B
+ *
+ * But we can do some simpler operations, right? How about PictOpOutReverse,
+ * which has a source factor of 0 and dest factor of (1 - source alpha). We
+ * can get the source alpha value (srca.X = src.A * mask.X) out of the texture
+ * blenders pretty easily. So we can do a component-alpha OutReverse, which
+ * gets us:
+ *
+ * dst.A = 0 + (1 - (src.A * mask.A)) * dst.A
+ * dst.R = 0 + (1 - (src.A * mask.R)) * dst.R
+ * dst.G = 0 + (1 - (src.A * mask.G)) * dst.G
+ * dst.B = 0 + (1 - (src.A * mask.B)) * dst.B
+ *
+ * OK. And if an op doesn't use the source alpha value for the destination
+ * factor, then we can do the channel multiplication in the texture blenders
+ * to get the source value, and ignore the source alpha that we wouldn't use.
+ * We've supported this in the Radeon driver for a long time. An example would
+ * be PictOpAdd, which does:
+ *
+ * dst.A = src.A * mask.A + dst.A
+ * dst.R = src.R * mask.R + dst.R
+ * dst.G = src.G * mask.G + dst.G
+ * dst.B = src.B * mask.B + dst.B
+ *
+ * Hey, this looks good! If we do a PictOpOutReverse and then a PictOpAdd right
+ * after it, we get:
+ *
+ * dst.A = src.A * mask.A + ((1 - (src.A * mask.A)) * dst.A)
+ * dst.R = src.R * mask.R + ((1 - (src.A * mask.R)) * dst.R)
+ * dst.G = src.G * mask.G + ((1 - (src.A * mask.G)) * dst.G)
+ * dst.B = src.B * mask.B + ((1 - (src.A * mask.B)) * dst.B)
+ *
+ * This two-pass trickery could be avoided using a new GL extension that
+ * lets two values come out of the shader and into the blend unit.
+ */
+ if (setup->op == CAIRO_OPERATOR_OVER) {
+ setup->op = CAIRO_OPERATOR_ADD;
+ status = _cairo_gl_get_program (ctx,
+ setup->src.type,
+ setup->mask.type,
+ CAIRO_GL_SHADER_IN_CA_SOURCE_ALPHA,
+ &setup->pre_shader);
+ if (unlikely (_cairo_status_is_error (status)))
+ return status;
+ }
+
+ return CAIRO_STATUS_SUCCESS;
+}
cairo_status_t
_cairo_gl_composite_begin (cairo_gl_context_t *ctx,
@@ -898,13 +992,23 @@ _cairo_gl_composite_begin (cairo_gl_context_t *ctx,
unsigned int dst_size, src_size, mask_size;
cairo_status_t status;
+ /* Do various magic for component alpha */
+ if (setup->has_component_alpha) {
+ status = _cairo_gl_composite_begin_component_alpha (ctx, setup);
+ if (unlikely (status))
+ return status;
+ }
+
status = _cairo_gl_get_program (ctx,
setup->src.type,
setup->mask.type,
- CAIRO_GL_SHADER_IN_NORMAL,
+ setup->has_component_alpha ? CAIRO_GL_SHADER_IN_CA_SOURCE
+ : CAIRO_GL_SHADER_IN_NORMAL,
&setup->shader);
- if (_cairo_status_is_error (status))
+ if (_cairo_status_is_error (status)) {
+ setup->pre_shader = NULL;
return status;
+ }
status = CAIRO_STATUS_SUCCESS;
@@ -915,7 +1019,9 @@ _cairo_gl_composite_begin (cairo_gl_context_t *ctx,
setup->vertex_size = dst_size + src_size + mask_size;
_cairo_gl_context_set_destination (ctx, setup->dst);
- _cairo_gl_set_operator (setup->dst, setup->op, FALSE);
+ _cairo_gl_set_operator (setup->dst,
+ setup->op,
+ setup->has_component_alpha);
_cairo_gl_use_program (ctx, setup->shader);
@@ -924,14 +1030,21 @@ _cairo_gl_composite_begin (cairo_gl_context_t *ctx,
glVertexPointer (2, GL_FLOAT, setup->vertex_size, NULL);
glEnableClientState (GL_VERTEX_ARRAY);
- _cairo_gl_set_src_operand (ctx, setup);
+ if (! setup->pre_shader)
+ _cairo_gl_set_src_operand (ctx, setup);
if (setup->src.type == CAIRO_GL_OPERAND_TEXTURE) {
glClientActiveTexture (GL_TEXTURE0);
glTexCoordPointer (2, GL_FLOAT, setup->vertex_size,
(void *) (uintptr_t) dst_size);
glEnableClientState (GL_TEXTURE_COORD_ARRAY);
}
- _cairo_gl_set_mask_operand (ctx, setup);
+ if (! setup->pre_shader) {
+ if (setup->has_component_alpha)
+ _cairo_gl_set_component_alpha_mask_operand (ctx, setup);
+ else
+ _cairo_gl_set_mask_operand (ctx, setup);
+ }
+
if (setup->mask.type == CAIRO_GL_OPERAND_TEXTURE) {
glClientActiveTexture (GL_TEXTURE1);
glTexCoordPointer (2, GL_FLOAT, setup->vertex_size,
@@ -943,13 +1056,36 @@ _cairo_gl_composite_begin (cairo_gl_context_t *ctx,
}
static inline void
+_cairo_gl_composite_draw (cairo_gl_context_t *ctx,
+ cairo_gl_composite_t *setup)
+{
+ unsigned int count = setup->vb_offset / setup->vertex_size;
+
+ if (! setup->pre_shader) {
+ glDrawArrays (GL_QUADS, 0, count);
+ } else {
+ _cairo_gl_use_program (ctx, setup->pre_shader);
+ _cairo_gl_set_operator (setup->dst, CAIRO_OPERATOR_DEST_OUT, TRUE);
+ _cairo_gl_set_src_alpha_operand (ctx, setup);
+ _cairo_gl_set_component_alpha_mask_operand (ctx, setup);
+ glDrawArrays (GL_QUADS, 0, count);
+
+ _cairo_gl_use_program (ctx, setup->shader);
+ _cairo_gl_set_operator (setup->dst, setup->op, TRUE);
+ _cairo_gl_set_src_operand (ctx, setup);
+ _cairo_gl_set_component_alpha_mask_operand (ctx, setup);
+ glDrawArrays (GL_QUADS, 0, count);
+ }
+}
+
+static inline void
_cairo_gl_composite_flush (cairo_gl_context_t *ctx,
cairo_gl_composite_t *setup)
{
if (setup->vb_offset == 0)
return;
- glDrawArrays (GL_QUADS, 0, setup->vb_offset / setup->vertex_size);
+ _cairo_gl_composite_draw (ctx, setup);
glUnmapBufferARB (GL_ARRAY_BUFFER_ARB);
setup->vb = NULL;
@@ -1060,6 +1196,9 @@ _cairo_gl_composite_end (cairo_gl_context_t *ctx,
glActiveTexture (GL_TEXTURE1);
glDisable (GL_TEXTURE_1D);
glDisable (ctx->tex_target);
+
+ setup->shader = NULL;
+ setup->pre_shader = NULL;
}
void
@@ -1077,14 +1216,24 @@ _cairo_gl_composite_init (cairo_gl_context_t *ctx,
cairo_gl_surface_t *dst,
const cairo_pattern_t *src,
const cairo_pattern_t *mask,
+ cairo_bool_t has_component_alpha,
const cairo_rectangle_int_t *rect)
{
memset (setup, 0, sizeof (cairo_gl_composite_t));
- if (! _cairo_gl_operator_is_supported (op))
- return UNSUPPORTED ("unsupported operator");
+ if (has_component_alpha) {
+ if (op != CAIRO_OPERATOR_CLEAR &&
+ op != CAIRO_OPERATOR_OVER &&
+ op != CAIRO_OPERATOR_ADD)
+ return UNSUPPORTED ("unsupported component alpha operator");
+ } else {
+ if (! _cairo_gl_operator_is_supported (op))
+ return UNSUPPORTED ("unsupported operator");
+ }
+
setup->dst = dst;
+ setup->has_component_alpha = has_component_alpha;
setup->op = op;
return CAIRO_STATUS_SUCCESS;
diff --git a/src/cairo-gl-glyphs.c b/src/cairo-gl-glyphs.c
index c3ded41..76ac5aa 100644
--- a/src/cairo-gl-glyphs.c
+++ b/src/cairo-gl-glyphs.c
@@ -484,7 +484,7 @@ _render_glyphs (cairo_gl_surface_t *dst,
status = _cairo_gl_composite_init (ctx, &composite_setup,
op, dst, source, NULL,
- glyph_extents);
+ FALSE, glyph_extents);
if (unlikely (status))
goto CLEANUP_FONT;
diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h
index 0cf0556..e926689 100644
--- a/src/cairo-gl-private.h
+++ b/src/cairo-gl-private.h
@@ -188,9 +188,12 @@ typedef struct cairo_gl_operand {
typedef struct _cairo_gl_composite {
cairo_gl_surface_t *dst;
cairo_operator_t op;
+ cairo_bool_t has_component_alpha;
+
cairo_gl_operand_t src;
cairo_gl_operand_t mask;
cairo_gl_shader_program_t *shader;
+ cairo_gl_shader_program_t *pre_shader; /* for component alpha */
char *vb;
unsigned int vb_offset;
@@ -287,6 +290,7 @@ _cairo_gl_composite_init (cairo_gl_context_t *ctx,
cairo_gl_surface_t *dst,
const cairo_pattern_t *src,
const cairo_pattern_t *mask,
+ cairo_bool_t has_component_alpha,
const cairo_rectangle_int_t *rect);
cairo_private void
diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c
index 3852fba..24abb90 100644
--- a/src/cairo-gl-surface.c
+++ b/src/cairo-gl-surface.c
@@ -936,262 +936,6 @@ _cairo_gl_get_traps_pattern (cairo_gl_surface_t *dst,
return CAIRO_STATUS_SUCCESS;
}
-/**
- * implements component-alpha %CAIRO_OPERATOR_SOURCE using two passes of
- * the simpler operations %CAIRO_OPERATOR_DEST_OUT and %CAIRO_OPERATOR_ADD.
- *
- * From http://anholt.livejournal.com/32058.html:
- *
- * The trouble is that component-alpha rendering requires two different sources
- * for blending: one for the source value to the blender, which is the
- * per-channel multiplication of source and mask, and one for the source alpha
- * for multiplying with the destination channels, which is the multiplication
- * of the source channels by the mask alpha. So the equation for Over is:
- *
- * dst.A = src.A * mask.A + (1 - (src.A * mask.A)) * dst.A
- * dst.R = src.R * mask.R + (1 - (src.A * mask.R)) * dst.R
- * dst.G = src.G * mask.G + (1 - (src.A * mask.G)) * dst.G
- * dst.B = src.B * mask.B + (1 - (src.A * mask.B)) * dst.B
- *
- * But we can do some simpler operations, right? How about PictOpOutReverse,
- * which has a source factor of 0 and dest factor of (1 - source alpha). We
- * can get the source alpha value (srca.X = src.A * mask.X) out of the texture
- * blenders pretty easily. So we can do a component-alpha OutReverse, which
- * gets us:
- *
- * dst.A = 0 + (1 - (src.A * mask.A)) * dst.A
- * dst.R = 0 + (1 - (src.A * mask.R)) * dst.R
- * dst.G = 0 + (1 - (src.A * mask.G)) * dst.G
- * dst.B = 0 + (1 - (src.A * mask.B)) * dst.B
- *
- * OK. And if an op doesn't use the source alpha value for the destination
- * factor, then we can do the channel multiplication in the texture blenders
- * to get the source value, and ignore the source alpha that we wouldn't use.
- * We've supported this in the Radeon driver for a long time. An example would
- * be PictOpAdd, which does:
- *
- * dst.A = src.A * mask.A + dst.A
- * dst.R = src.R * mask.R + dst.R
- * dst.G = src.G * mask.G + dst.G
- * dst.B = src.B * mask.B + dst.B
- *
- * Hey, this looks good! If we do a PictOpOutReverse and then a PictOpAdd right
- * after it, we get:
- *
- * dst.A = src.A * mask.A + ((1 - (src.A * mask.A)) * dst.A)
- * dst.R = src.R * mask.R + ((1 - (src.A * mask.R)) * dst.R)
- * dst.G = src.G * mask.G + ((1 - (src.A * mask.G)) * dst.G)
- * dst.B = src.B * mask.B + ((1 - (src.A * mask.B)) * dst.B)
- *
- * This two-pass trickery could be avoided using a new GL extension that
- * lets two values come out of the shader and into the blend unit.
- */
-static cairo_int_status_t
-_cairo_gl_surface_composite_component_alpha (cairo_operator_t op,
- const cairo_pattern_t *src,
- const cairo_pattern_t *mask,
- void *abstract_dst,
- int src_x,
- int src_y,
- int mask_x,
- int mask_y,
- int dst_x,
- int dst_y,
- unsigned int width,
- unsigned int height,
- cairo_region_t *clip_region)
-{
- cairo_gl_surface_t *dst = abstract_dst;
- cairo_surface_attributes_t *src_attributes, *mask_attributes = NULL;
- cairo_gl_context_t *ctx;
- struct gl_point {
- GLfloat x, y;
- } vertices_stack[8], texcoord_src_stack[8], texcoord_mask_stack[8];
- struct gl_point *vertices = vertices_stack;
- struct gl_point *texcoord_src = texcoord_src_stack;
- struct gl_point *texcoord_mask = texcoord_mask_stack;
- cairo_status_t status;
- int num_vertices, i;
- cairo_gl_composite_t setup;
- cairo_gl_shader_program_t *ca_source_program = NULL;
- cairo_gl_shader_program_t *ca_source_alpha_program = NULL;
- cairo_rectangle_int_t rect = { dst_x, dst_y, width, height };
-
- if (op != CAIRO_OPERATOR_OVER && op != CAIRO_OPERATOR_ADD)
- return UNSUPPORTED ("unsupported component alpha operator");
-
- status = _cairo_gl_context_acquire (dst->base.device, &ctx);
- if (unlikely (status))
- return status;
-
- status = _cairo_gl_composite_init (ctx, &setup, op, dst, src, mask, &rect);
- if (unlikely (status))
- goto CLEANUP;
-
- status = _cairo_gl_operand_init (ctx, &setup.src, src, dst,
- src_x, src_y,
- dst_x, dst_y,
- width, height);
- if (unlikely (status))
- goto CLEANUP;
-
- src_attributes = &setup.src.operand.texture.attributes;
-
- status = _cairo_gl_operand_init (ctx, &setup.mask, mask, dst,
- mask_x, mask_y,
- dst_x, dst_y,
- width, height);
- if (unlikely (status))
- goto CLEANUP;
-
- mask_attributes = &setup.mask.operand.texture.attributes;
-
- /* We'll fall back to fixed function instead. */
- ca_source_program = NULL;
- ca_source_alpha_program = NULL;
-
- status = _cairo_gl_get_program (ctx,
- setup.src.type,
- setup.mask.type,
- CAIRO_GL_SHADER_IN_CA_SOURCE,
- &ca_source_program);
- if (_cairo_status_is_error (status))
- goto CLEANUP;
-
- status = _cairo_gl_get_program (ctx,
- setup.src.type,
- setup.mask.type,
- CAIRO_GL_SHADER_IN_CA_SOURCE_ALPHA,
- &ca_source_alpha_program);
- if (_cairo_status_is_error (status))
- goto CLEANUP;
-
- status = CAIRO_STATUS_SUCCESS;
-
- _cairo_gl_context_set_destination (ctx, dst);
-
- if (clip_region != NULL) {
- int num_rectangles;
-
- num_rectangles = cairo_region_num_rectangles (clip_region);
- if (num_rectangles * 4 > ARRAY_LENGTH (vertices_stack)) {
- vertices = _cairo_malloc_ab (num_rectangles,
- 4*3*sizeof (vertices[0]));
- if (unlikely (vertices == NULL)) {
- status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
- goto CLEANUP;
- }
-
- texcoord_src = vertices + num_rectangles * 4;
- texcoord_mask = texcoord_src + num_rectangles * 4;
- }
-
- for (i = 0; i < num_rectangles; i++) {
- cairo_rectangle_int_t rect;
-
- cairo_region_get_rectangle (clip_region, i, &rect);
- vertices[4*i + 0].x = rect.x;
- vertices[4*i + 0].y = rect.y;
- vertices[4*i + 1].x = rect.x + rect.width;
- vertices[4*i + 1].y = rect.y;
- vertices[4*i + 2].x = rect.x + rect.width;
- vertices[4*i + 2].y = rect.y + rect.height;
- vertices[4*i + 3].x = rect.x;
- vertices[4*i + 3].y = rect.y + rect.height;
- }
-
- num_vertices = 4 * num_rectangles;
- } else {
- vertices[0].x = dst_x;
- vertices[0].y = dst_y;
- vertices[1].x = dst_x + width;
- vertices[1].y = dst_y;
- vertices[2].x = dst_x + width;
- vertices[2].y = dst_y + height;
- vertices[3].x = dst_x;
- vertices[3].y = dst_y + height;
-
- num_vertices = 4;
- }
-
- glVertexPointer (2, GL_FLOAT, sizeof (GLfloat) * 2, vertices);
- glEnableClientState (GL_VERTEX_ARRAY);
-
- if (setup.src.type == CAIRO_GL_OPERAND_TEXTURE) {
- for (i = 0; i < num_vertices; i++) {
- double s, t;
-
- s = vertices[i].x;
- t = vertices[i].y;
- cairo_matrix_transform_point (&src_attributes->matrix, &s, &t);
- texcoord_src[i].x = s;
- texcoord_src[i].y = t;
- }
-
- glClientActiveTexture (GL_TEXTURE0);
- glTexCoordPointer (2, GL_FLOAT, sizeof (GLfloat)*2, texcoord_src);
- glEnableClientState (GL_TEXTURE_COORD_ARRAY);
- }
-
- if (setup.mask.type == CAIRO_GL_OPERAND_TEXTURE) {
- for (i = 0; i < num_vertices; i++) {
- double s, t;
-
- s = vertices[i].x;
- t = vertices[i].y;
- cairo_matrix_transform_point (&mask_attributes->matrix, &s, &t);
- texcoord_mask[i].x = s;
- texcoord_mask[i].y = t;
- }
-
- glClientActiveTexture (GL_TEXTURE1);
- glTexCoordPointer (2, GL_FLOAT, sizeof (GLfloat)*2, texcoord_mask);
- glEnableClientState (GL_TEXTURE_COORD_ARRAY);
- }
-
- if (op == CAIRO_OPERATOR_OVER) {
- setup.shader = ca_source_alpha_program;
- _cairo_gl_use_program (ctx, setup.shader);
- _cairo_gl_set_operator (dst, CAIRO_OPERATOR_DEST_OUT, TRUE);
- _cairo_gl_set_src_alpha_operand (ctx, &setup);
- _cairo_gl_set_component_alpha_mask_operand (ctx, &setup);
- glDrawArrays (GL_QUADS, 0, num_vertices);
- }
-
- setup.shader = ca_source_program;
- _cairo_gl_use_program (ctx, setup.shader);
- _cairo_gl_set_operator (dst, CAIRO_OPERATOR_ADD, TRUE);
- _cairo_gl_set_src_operand (ctx, &setup);
- _cairo_gl_set_component_alpha_mask_operand (ctx, &setup);
- glDrawArrays (GL_QUADS, 0, num_vertices);
-
- glDisable (GL_BLEND);
- _cairo_gl_use_program (ctx, NULL);
-
- glDisableClientState (GL_VERTEX_ARRAY);
-
- glClientActiveTexture (GL_TEXTURE0);
- glDisableClientState (GL_TEXTURE_COORD_ARRAY);
- glActiveTexture (GL_TEXTURE0);
- glDisable (GL_TEXTURE_1D);
- glDisable (ctx->tex_target);
-
- glClientActiveTexture (GL_TEXTURE1);
- glDisableClientState (GL_TEXTURE_COORD_ARRAY);
- glActiveTexture (GL_TEXTURE1);
- glDisable (GL_TEXTURE_1D);
- glDisable (ctx->tex_target);
-
- CLEANUP:
- _cairo_gl_composite_fini (ctx, &setup);
- _cairo_gl_context_release (ctx);
-
- if (vertices != vertices_stack)
- free (vertices);
-
- return status;
-}
-
static cairo_int_status_t
_cairo_gl_surface_composite (cairo_operator_t op,
const cairo_pattern_t *src,
@@ -1214,28 +958,14 @@ _cairo_gl_surface_composite (cairo_operator_t op,
cairo_gl_composite_t setup;
cairo_rectangle_int_t rect = { dst_x, dst_y, width, height };
- if (mask && mask->has_component_alpha) {
- /* Try two-pass component alpha support, or bail. */
- return _cairo_gl_surface_composite_component_alpha(op,
- src,
- mask,
- abstract_dst,
- src_x,
- src_y,
- mask_x,
- mask_y,
- dst_x,
- dst_y,
- width,
- height,
- clip_region);
- }
-
status = _cairo_gl_context_acquire (dst->base.device, &ctx);
if (unlikely (status))
return status;
- status = _cairo_gl_composite_init (ctx, &setup, op, dst, src, mask, &rect);
+ status = _cairo_gl_composite_init (ctx, &setup,
+ op, dst, src, mask,
+ mask && mask->has_component_alpha,
+ &rect);
if (unlikely (status))
goto CLEANUP;
@@ -1863,7 +1593,7 @@ _cairo_gl_surface_create_span_renderer (cairo_operator_t op,
status = _cairo_gl_composite_init (renderer->ctx,
&renderer->setup,
op, dst, src, NULL,
- extents);
+ FALSE, extents);
if (unlikely (status))
goto FAIL;
commit 88c118f891ca9ba472b8acff33829de845bb507c
Author: Benjamin Otte <otte at redhat.com>
Date: Sun May 16 00:24:17 2010 +0200
gl: Implement _composite_emit_rect() and _composite_end()
And use it in cairo_gl_surface_composite()
diff --git a/src/cairo-gl-composite.c b/src/cairo-gl-composite.c
index 4991194..8be453e 100644
--- a/src/cairo-gl-composite.c
+++ b/src/cairo-gl-composite.c
@@ -871,10 +871,31 @@ _cairo_gl_set_mask_operand (cairo_gl_context_t *ctx,
}
}
+static unsigned int
+_cairo_gl_operand_get_vertex_size (cairo_gl_operand_type_t type)
+{
+ switch (type) {
+ default:
+ case CAIRO_GL_OPERAND_COUNT:
+ ASSERT_NOT_REACHED;
+ case CAIRO_GL_OPERAND_NONE:
+ case CAIRO_GL_OPERAND_CONSTANT:
+ case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
+ case CAIRO_GL_OPERAND_RADIAL_GRADIENT:
+ return 0;
+ case CAIRO_GL_OPERAND_SPANS:
+ return 4 * sizeof (GLbyte);
+ case CAIRO_GL_OPERAND_TEXTURE:
+ return 2 * sizeof (GLfloat);
+ }
+}
+
+
cairo_status_t
_cairo_gl_composite_begin (cairo_gl_context_t *ctx,
cairo_gl_composite_t *setup)
{
+ unsigned int dst_size, src_size, mask_size;
cairo_status_t status;
status = _cairo_gl_get_program (ctx,
@@ -887,17 +908,160 @@ _cairo_gl_composite_begin (cairo_gl_context_t *ctx,
status = CAIRO_STATUS_SUCCESS;
+ dst_size = 2 * sizeof (GLfloat);
+ src_size = _cairo_gl_operand_get_vertex_size (setup->src.type);
+ mask_size = _cairo_gl_operand_get_vertex_size (setup->mask.type);
+
+ setup->vertex_size = dst_size + src_size + mask_size;
+
_cairo_gl_context_set_destination (ctx, setup->dst);
_cairo_gl_set_operator (setup->dst, setup->op, FALSE);
_cairo_gl_use_program (ctx, setup->shader);
+ glBindBufferARB (GL_ARRAY_BUFFER_ARB, ctx->vbo);
+
+ glVertexPointer (2, GL_FLOAT, setup->vertex_size, NULL);
+ glEnableClientState (GL_VERTEX_ARRAY);
+
_cairo_gl_set_src_operand (ctx, setup);
+ if (setup->src.type == CAIRO_GL_OPERAND_TEXTURE) {
+ glClientActiveTexture (GL_TEXTURE0);
+ glTexCoordPointer (2, GL_FLOAT, setup->vertex_size,
+ (void *) (uintptr_t) dst_size);
+ glEnableClientState (GL_TEXTURE_COORD_ARRAY);
+ }
_cairo_gl_set_mask_operand (ctx, setup);
+ if (setup->mask.type == CAIRO_GL_OPERAND_TEXTURE) {
+ glClientActiveTexture (GL_TEXTURE1);
+ glTexCoordPointer (2, GL_FLOAT, setup->vertex_size,
+ (void *) (uintptr_t) (dst_size + src_size));
+ glEnableClientState (GL_TEXTURE_COORD_ARRAY);
+ }
return status;
}
+static inline void
+_cairo_gl_composite_flush (cairo_gl_context_t *ctx,
+ cairo_gl_composite_t *setup)
+{
+ if (setup->vb_offset == 0)
+ return;
+
+ glDrawArrays (GL_QUADS, 0, setup->vb_offset / setup->vertex_size);
+
+ glUnmapBufferARB (GL_ARRAY_BUFFER_ARB);
+ setup->vb = NULL;
+}
+
+static void
+_cairo_gl_composite_prepare_buffer (cairo_gl_context_t *ctx,
+ cairo_gl_composite_t *setup,
+ unsigned int n_vertices)
+{
+ if (setup->vb_offset + n_vertices * setup->vertex_size > CAIRO_GL_VBO_SIZE)
+ _cairo_gl_composite_flush (ctx, setup);
+
+ if (setup->vb == NULL) {
+ glBufferDataARB (GL_ARRAY_BUFFER_ARB, CAIRO_GL_VBO_SIZE,
+ NULL, GL_STREAM_DRAW_ARB);
+ setup->vb = glMapBufferARB (GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
+ setup->vb_offset = 0;
+ }
+}
+
+static inline void
+_cairo_gl_operand_emit (cairo_gl_operand_t *operand,
+ GLfloat ** vb,
+ GLfloat x,
+ GLfloat y)
+{
+ switch (operand->type) {
+ default:
+ case CAIRO_GL_OPERAND_COUNT:
+ ASSERT_NOT_REACHED;
+ case CAIRO_GL_OPERAND_NONE:
+ case CAIRO_GL_OPERAND_CONSTANT:
+ case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
+ case CAIRO_GL_OPERAND_RADIAL_GRADIENT:
+ break;
+ case CAIRO_GL_OPERAND_SPANS:
+ ASSERT_NOT_REACHED;
+ break;
+ case CAIRO_GL_OPERAND_TEXTURE:
+ {
+ cairo_surface_attributes_t *src_attributes = &operand->operand.texture.attributes;
+ double s = x;
+ double t = y;
+
+ cairo_matrix_transform_point (&src_attributes->matrix, &s, &t);
+ *(*vb)++ = s;
+ *(*vb)++ = t;
+ }
+ break;
+ }
+}
+
+static inline void
+_cairo_gl_composite_emit_vertex (cairo_gl_context_t *ctx,
+ cairo_gl_composite_t *setup,
+ GLfloat x,
+ GLfloat y)
+{
+ GLfloat *vb = (GLfloat *) (void *) &setup->vb[setup->vb_offset];
+
+ *vb++ = x;
+ *vb++ = y;
+
+ _cairo_gl_operand_emit (&setup->src, &vb, x, y);
+ _cairo_gl_operand_emit (&setup->mask, &vb, x, y);
+
+ setup->vb_offset += setup->vertex_size;
+}
+
+void
+_cairo_gl_composite_emit_rect (cairo_gl_context_t *ctx,
+ cairo_gl_composite_t *setup,
+ GLfloat x,
+ GLfloat y,
+ GLfloat width,
+ GLfloat height)
+{
+ _cairo_gl_composite_prepare_buffer (ctx, setup, 4);
+
+ _cairo_gl_composite_emit_vertex (ctx, setup, x, y);
+ _cairo_gl_composite_emit_vertex (ctx, setup, x + width, y);
+ _cairo_gl_composite_emit_vertex (ctx, setup, x + width, y + height);
+ _cairo_gl_composite_emit_vertex (ctx, setup, x, y + height);
+}
+
+void
+_cairo_gl_composite_end (cairo_gl_context_t *ctx,
+ cairo_gl_composite_t *setup)
+{
+ _cairo_gl_composite_flush (ctx, setup);
+
+ glBindBufferARB (GL_ARRAY_BUFFER_ARB, 0);
+
+ _cairo_gl_use_program (ctx, NULL);
+ glDisable (GL_BLEND);
+
+ glDisableClientState (GL_VERTEX_ARRAY);
+
+ glClientActiveTexture (GL_TEXTURE0);
+ glDisableClientState (GL_TEXTURE_COORD_ARRAY);
+ glActiveTexture (GL_TEXTURE0);
+ glDisable (GL_TEXTURE_1D);
+ glDisable (ctx->tex_target);
+
+ glClientActiveTexture (GL_TEXTURE1);
+ glDisableClientState (GL_TEXTURE_COORD_ARRAY);
+ glActiveTexture (GL_TEXTURE1);
+ glDisable (GL_TEXTURE_1D);
+ glDisable (ctx->tex_target);
+}
+
void
_cairo_gl_composite_fini (cairo_gl_context_t *ctx,
cairo_gl_composite_t *setup)
diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h
index fac4260..0cf0556 100644
--- a/src/cairo-gl-private.h
+++ b/src/cairo-gl-private.h
@@ -69,6 +69,9 @@
* Random number that is hopefully big enough to not cause many cache evictions. */
#define CAIRO_GL_MAX_SHADERS_PER_CONTEXT 64
+/* VBO size that we allocate, smaller size means we gotta flush more often */
+#define CAIRO_GL_VBO_SIZE 16384
+
typedef struct _cairo_gl_surface {
cairo_surface_t base;
@@ -188,6 +191,10 @@ typedef struct _cairo_gl_composite {
cairo_gl_operand_t src;
cairo_gl_operand_t mask;
cairo_gl_shader_program_t *shader;
+
+ char *vb;
+ unsigned int vb_offset;
+ unsigned int vertex_size;
} cairo_gl_composite_t;
cairo_private extern const cairo_surface_backend_t _cairo_gl_surface_backend;
@@ -291,6 +298,18 @@ _cairo_gl_composite_begin (cairo_gl_context_t *ctx,
cairo_gl_composite_t *setup);
cairo_private void
+_cairo_gl_composite_emit_rect (cairo_gl_context_t *ctx,
+ cairo_gl_composite_t *setup,
+ GLfloat x,
+ GLfloat y,
+ GLfloat width,
+ GLfloat height);
+
+cairo_private void
+_cairo_gl_composite_end (cairo_gl_context_t *ctx,
+ cairo_gl_composite_t *setup);
+
+cairo_private void
_cairo_gl_set_src_operand (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 49bc92c..3852fba 100644
--- a/src/cairo-gl-surface.c
+++ b/src/cairo-gl-surface.c
@@ -1210,14 +1210,7 @@ _cairo_gl_surface_composite (cairo_operator_t op,
cairo_gl_surface_t *dst = abstract_dst;
cairo_surface_attributes_t *src_attributes, *mask_attributes = NULL;
cairo_gl_context_t *ctx;
- struct gl_point {
- GLfloat x, y;
- } vertices_stack[8], texcoord_src_stack[8], texcoord_mask_stack[8];
- struct gl_point *vertices = vertices_stack;
- struct gl_point *texcoord_src = texcoord_src_stack;
- struct gl_point *texcoord_mask = texcoord_mask_stack;
cairo_status_t status;
- int num_vertices, i;
cairo_gl_composite_t setup;
cairo_rectangle_int_t rect = { dst_x, dst_y, width, height };
@@ -1269,107 +1262,25 @@ _cairo_gl_surface_composite (cairo_operator_t op,
status = _cairo_gl_composite_begin (ctx, &setup);
if (clip_region != NULL) {
- int num_rectangles;
-
- num_rectangles = cairo_region_num_rectangles (clip_region);
- if (num_rectangles * 4 > ARRAY_LENGTH (vertices_stack)) {
- vertices = _cairo_malloc_ab (num_rectangles,
- 4*3*sizeof (vertices[0]));
- if (unlikely (vertices == NULL)) {
- status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
- goto CLEANUP;
- }
+ int i, num_rectangles;
- texcoord_src = vertices + num_rectangles * 4;
- texcoord_mask = texcoord_src + num_rectangles * 4;
- }
+ num_rectangles = cairo_region_num_rectangles (clip_region);
for (i = 0; i < num_rectangles; i++) {
cairo_rectangle_int_t rect;
cairo_region_get_rectangle (clip_region, i, &rect);
- vertices[4*i + 0].x = rect.x;
- vertices[4*i + 0].y = rect.y;
- vertices[4*i + 1].x = rect.x + rect.width;
- vertices[4*i + 1].y = rect.y;
- vertices[4*i + 2].x = rect.x + rect.width;
- vertices[4*i + 2].y = rect.y + rect.height;
- vertices[4*i + 3].x = rect.x;
- vertices[4*i + 3].y = rect.y + rect.height;
+ _cairo_gl_composite_emit_rect (ctx, &setup,
+ rect.x, rect.y,
+ rect.width, rect.height);
}
-
- num_vertices = 4 * num_rectangles;
} else {
- vertices[0].x = dst_x;
- vertices[0].y = dst_y;
- vertices[1].x = dst_x + width;
- vertices[1].y = dst_y;
- vertices[2].x = dst_x + width;
- vertices[2].y = dst_y + height;
- vertices[3].x = dst_x;
- vertices[3].y = dst_y + height;
-
- num_vertices = 4;
+ _cairo_gl_composite_emit_rect (ctx, &setup,
+ dst_x, dst_y,
+ width, height);
}
- glVertexPointer (2, GL_FLOAT, sizeof (GLfloat) * 2, vertices);
- glEnableClientState (GL_VERTEX_ARRAY);
-
- if (setup.src.type == CAIRO_GL_OPERAND_TEXTURE) {
- for (i = 0; i < num_vertices; i++) {
- double s, t;
-
- s = vertices[i].x;
- t = vertices[i].y;
- cairo_matrix_transform_point (&src_attributes->matrix, &s, &t);
- texcoord_src[i].x = s;
- texcoord_src[i].y = t;
- }
-
- glClientActiveTexture (GL_TEXTURE0);
- glTexCoordPointer (2, GL_FLOAT, sizeof (GLfloat)*2, texcoord_src);
- glEnableClientState (GL_TEXTURE_COORD_ARRAY);
- }
-
- if (mask != NULL) {
- if (setup.mask.type == CAIRO_GL_OPERAND_TEXTURE) {
- for (i = 0; i < num_vertices; i++) {
- double s, t;
-
- s = vertices[i].x;
- t = vertices[i].y;
- cairo_matrix_transform_point (&mask_attributes->matrix, &s, &t);
- texcoord_mask[i].x = s;
- texcoord_mask[i].y = t;
- }
-
- glClientActiveTexture (GL_TEXTURE1);
- glTexCoordPointer (2, GL_FLOAT, sizeof (GLfloat)*2, texcoord_mask);
- glEnableClientState (GL_TEXTURE_COORD_ARRAY);
- }
- }
-
- glDrawArrays (GL_QUADS, 0, num_vertices);
-
- _cairo_gl_use_program (ctx, NULL);
- glDisable (GL_BLEND);
-
- glDisableClientState (GL_VERTEX_ARRAY);
-
- glClientActiveTexture (GL_TEXTURE0);
- glDisableClientState (GL_TEXTURE_COORD_ARRAY);
- glActiveTexture (GL_TEXTURE0);
- glDisable (GL_TEXTURE_1D);
- glDisable (ctx->tex_target);
-
- glClientActiveTexture (GL_TEXTURE1);
- glDisableClientState (GL_TEXTURE_COORD_ARRAY);
- glActiveTexture (GL_TEXTURE1);
- glDisable (GL_TEXTURE_1D);
- glDisable (ctx->tex_target);
-
- if (vertices != vertices_stack)
- free (vertices);
+ _cairo_gl_composite_end (ctx, &setup);
CLEANUP:
_cairo_gl_composite_fini (ctx, &setup);
commit b96735f7b465a16182c4c8555878ba16b947e8f9
Author: Benjamin Otte <otte at redhat.com>
Date: Sat May 15 22:12:12 2010 +0200
gl: Add _cairo_gl_composite_begin() function
This is the first step at adding the following function set:
_cairo_gl_composite_begin()
_cairo_gl_composite_emit_*()
_cairo_gl_composite_end()
which will take care of proiding a unified model for emitting vertexes
using vbos instead of the 5 different methods we currently have.
diff --git a/src/cairo-gl-composite.c b/src/cairo-gl-composite.c
index e12770a..4991194 100644
--- a/src/cairo-gl-composite.c
+++ b/src/cairo-gl-composite.c
@@ -871,6 +871,33 @@ _cairo_gl_set_mask_operand (cairo_gl_context_t *ctx,
}
}
+cairo_status_t
+_cairo_gl_composite_begin (cairo_gl_context_t *ctx,
+ cairo_gl_composite_t *setup)
+{
+ cairo_status_t status;
+
+ status = _cairo_gl_get_program (ctx,
+ setup->src.type,
+ setup->mask.type,
+ CAIRO_GL_SHADER_IN_NORMAL,
+ &setup->shader);
+ if (_cairo_status_is_error (status))
+ return status;
+
+ status = CAIRO_STATUS_SUCCESS;
+
+ _cairo_gl_context_set_destination (ctx, setup->dst);
+ _cairo_gl_set_operator (setup->dst, setup->op, FALSE);
+
+ _cairo_gl_use_program (ctx, setup->shader);
+
+ _cairo_gl_set_src_operand (ctx, setup);
+ _cairo_gl_set_mask_operand (ctx, setup);
+
+ return status;
+}
+
void
_cairo_gl_composite_fini (cairo_gl_context_t *ctx,
cairo_gl_composite_t *setup)
@@ -893,6 +920,9 @@ _cairo_gl_composite_init (cairo_gl_context_t *ctx,
if (! _cairo_gl_operator_is_supported (op))
return UNSUPPORTED ("unsupported operator");
+ setup->dst = dst;
+ setup->op = op;
+
return CAIRO_STATUS_SUCCESS;
}
diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h
index 627bcac..fac4260 100644
--- a/src/cairo-gl-private.h
+++ b/src/cairo-gl-private.h
@@ -183,6 +183,8 @@ typedef struct cairo_gl_operand {
} cairo_gl_operand_t;
typedef struct _cairo_gl_composite {
+ cairo_gl_surface_t *dst;
+ cairo_operator_t op;
cairo_gl_operand_t src;
cairo_gl_operand_t mask;
cairo_gl_shader_program_t *shader;
@@ -284,6 +286,10 @@ cairo_private void
_cairo_gl_composite_fini (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);
+
cairo_private void
_cairo_gl_set_src_operand (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 661f177..49bc92c 100644
--- a/src/cairo-gl-surface.c
+++ b/src/cairo-gl-surface.c
@@ -1266,27 +1266,7 @@ _cairo_gl_surface_composite (cairo_operator_t op,
mask_attributes = &setup.mask.operand.texture.attributes;
}
- /* We'll fall back to fixed function instead. */
- setup.shader = NULL;
- status = _cairo_gl_get_program (ctx,
- setup.src.type,
- setup.mask.type,
- CAIRO_GL_SHADER_IN_NORMAL,
- &setup.shader);
- if (_cairo_status_is_error (status))
- goto CLEANUP;
-
- status = CAIRO_STATUS_SUCCESS;
-
- _cairo_gl_context_set_destination (ctx, dst);
- _cairo_gl_set_operator (dst, op, FALSE);
-
- _cairo_gl_use_program (ctx, setup.shader);
- _cairo_gl_set_src_operand (ctx, &setup);
-
- if (mask != NULL) {
- _cairo_gl_set_mask_operand (ctx, &setup);
- }
+ status = _cairo_gl_composite_begin (ctx, &setup);
if (clip_region != NULL) {
int num_rectangles;
commit 211a8b8234d24dd8e00332cb0b0e625ac1ffef58
Author: Benjamin Otte <otte at redhat.com>
Date: Sat May 15 21:27:58 2010 +0200
gl: make _cairo_operand_destroy private
diff --git a/src/cairo-gl-composite.c b/src/cairo-gl-composite.c
index d61f70f..e12770a 100644
--- a/src/cairo-gl-composite.c
+++ b/src/cairo-gl-composite.c
@@ -450,7 +450,7 @@ _cairo_gl_operand_init (cairo_gl_context_t *ctx,
}
}
-void
+static void
_cairo_gl_operand_destroy (cairo_gl_operand_t *operand)
{
switch (operand->type) {
diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h
index 6da413c..627bcac 100644
--- a/src/cairo-gl-private.h
+++ b/src/cairo-gl-private.h
@@ -300,9 +300,6 @@ cairo_private void
_cairo_gl_set_mask_operand (cairo_gl_context_t *ctx,
cairo_gl_composite_t *setup);
-cairo_private void
-_cairo_gl_operand_destroy (cairo_gl_operand_t *operand);
-
cairo_private cairo_bool_t
_cairo_gl_get_image_format_and_type (pixman_format_code_t pixman_format,
GLenum *internal_format, GLenum *format,
commit bf1060252abaa97eb5ce149f8b99055b42096c67
Author: Benjamin Otte <otte at redhat.com>
Date: Sat May 15 21:26:55 2010 +0200
gl: make show_glyphs use the cairo_composite_t API
diff --git a/src/cairo-gl-glyphs.c b/src/cairo-gl-glyphs.c
index aee9235..c3ded41 100644
--- a/src/cairo-gl-glyphs.c
+++ b/src/cairo-gl-glyphs.c
@@ -478,21 +478,24 @@ _render_glyphs (cairo_gl_surface_t *dst,
*has_component_alpha = FALSE;
- memset (&composite_setup, 0, sizeof(composite_setup));
-
status = _cairo_gl_context_acquire (dst->base.device, &ctx);
if (unlikely (status))
return status;
+ status = _cairo_gl_composite_init (ctx, &composite_setup,
+ op, dst, source, NULL,
+ glyph_extents);
+
+ if (unlikely (status))
+ goto CLEANUP_FONT;
+
status = _cairo_gl_operand_init (ctx, &composite_setup.src, source, dst,
glyph_extents->x, glyph_extents->y,
dst_x, dst_y,
glyph_extents->width,
glyph_extents->height);
- if (unlikely (status)) {
- _cairo_gl_context_release (ctx);
- return status;
- }
+ if (unlikely (status))
+ goto CLEANUP_FONT;
_cairo_gl_context_set_destination (ctx, dst);
@@ -642,7 +645,7 @@ _render_glyphs (cairo_gl_surface_t *dst,
glBindBufferARB (GL_ARRAY_BUFFER_ARB, 0);
- _cairo_gl_operand_destroy (&composite_setup.src);
+ _cairo_gl_composite_fini (ctx, &composite_setup);
_cairo_gl_context_release (ctx);
commit 948290de12c5f451d361903f0f52e0cde5527180
Author: Benjamin Otte <otte at redhat.com>
Date: Sat May 15 20:33:00 2010 +0200
gl: Make the span renderer use the new composite APIs
diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c
index 16deaab..661f177 100644
--- a/src/cairo-gl-surface.c
+++ b/src/cairo-gl-surface.c
@@ -1874,7 +1874,8 @@ _cairo_gl_surface_span_renderer_destroy (void *abstract_renderer)
if (!renderer)
return;
- _cairo_gl_operand_destroy (&renderer->setup.src);
+ _cairo_gl_composite_fini (renderer->ctx, &renderer->setup);
+
_cairo_gl_context_release (renderer->ctx);
free (renderer);
@@ -1968,16 +1969,20 @@ _cairo_gl_surface_create_span_renderer (cairo_operator_t op,
return _cairo_span_renderer_create_in_error (status);
}
+ status = _cairo_gl_composite_init (renderer->ctx,
+ &renderer->setup,
+ op, dst, src, NULL,
+ extents);
+ if (unlikely (status))
+ goto FAIL;
+
status = _cairo_gl_operand_init (renderer->ctx,
&renderer->setup.src, src, dst,
rects->source.x, rects->source.y,
extents->x, extents->y,
extents->width, extents->height);
- if (unlikely (status)) {
- _cairo_gl_context_release (renderer->ctx);
- free (renderer);
- return _cairo_span_renderer_create_in_error (status);
- }
+ if (unlikely (status))
+ goto FAIL;
_cairo_gl_context_set_destination (renderer->ctx, dst);
@@ -1986,12 +1991,8 @@ _cairo_gl_surface_create_span_renderer (cairo_operator_t op,
CAIRO_GL_OPERAND_SPANS,
CAIRO_GL_SHADER_IN_NORMAL,
&renderer->setup.shader);
- if (_cairo_status_is_error (status)) {
- _cairo_gl_operand_destroy (&renderer->setup.src);
- _cairo_gl_context_release (renderer->ctx);
- free (renderer);
- return _cairo_span_renderer_create_in_error (status);
- }
+ if (_cairo_status_is_error (status))
+ goto FAIL;
src_attributes = &renderer->setup.src.operand.texture.attributes;
@@ -2021,6 +2022,13 @@ _cairo_gl_surface_create_span_renderer (cairo_operator_t op,
}
return &renderer->base;
+
+
+FAIL:
+ _cairo_gl_composite_fini (renderer->ctx, &renderer->setup);
+ _cairo_gl_context_release (renderer->ctx);
+ free (renderer);
+ return _cairo_span_renderer_create_in_error (status);
}
static cairo_bool_t
commit 7ad8c3b45691ce0c8a86180bb3c1117b9a9980c0
Author: Benjamin Otte <otte at redhat.com>
Date: Sat May 15 20:07:44 2010 +0200
gl: Move composite code into own file
This allows designing a cleaner interface for cairo_composite_t as there
will not be static functions that get called outside of the "published"
interfaces.
diff --git a/src/Makefile.sources b/src/Makefile.sources
index c45e339..24f15c5 100644
--- a/src/Makefile.sources
+++ b/src/Makefile.sources
@@ -313,7 +313,8 @@ cairo_beos_headers = cairo-beos.h
cairo_gl_headers = cairo-gl.h
cairo_gl_private = cairo-gl-private.h
-cairo_gl_sources = cairo-gl-device.c \
+cairo_gl_sources = cairo-gl-composite.c \
+ cairo-gl-device.c \
cairo-gl-glyphs.c \
cairo-gl-shaders.c \
cairo-gl-surface.c
diff --git a/src/cairo-gl-composite.c b/src/cairo-gl-composite.c
new file mode 100644
index 0000000..d61f70f
--- /dev/null
+++ b/src/cairo-gl-composite.c
@@ -0,0 +1,898 @@
+/* cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2009 Eric Anholt
+ * Copyright © 2009 Chris Wilson
+ * Copyright © 2005 Red Hat, Inc
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ * The Original Code is the cairo graphics library.
+ *
+ * The Initial Developer of the Original Code is Red Hat, Inc.
+ *
+ * Contributor(s):
+ * Carl Worth <cworth at cworth.org>
+ */
+
+#include "cairoint.h"
+
+#include "cairo-error-private.h"
+#include "cairo-gl-private.h"
+
+static void
+_cairo_gl_set_texture_surface (int tex_unit, GLuint tex,
+ cairo_surface_attributes_t *attributes,
+ GLint tex_target)
+{
+
+ if (tex_target == GL_TEXTURE_RECTANGLE_EXT) {
+ assert (attributes->extend != CAIRO_EXTEND_REPEAT &&
+ attributes->extend != CAIRO_EXTEND_REFLECT);
+ }
+
+ glActiveTexture (GL_TEXTURE0 + tex_unit);
+ glBindTexture (tex_target, tex);
+ switch (attributes->extend) {
+ case CAIRO_EXTEND_NONE:
+ glTexParameteri (tex_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
+ glTexParameteri (tex_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
+ break;
+ case CAIRO_EXTEND_PAD:
+ glTexParameteri (tex_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri (tex_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ break;
+ case CAIRO_EXTEND_REPEAT:
+ glTexParameteri (tex_target, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameteri (tex_target, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ break;
+ case CAIRO_EXTEND_REFLECT:
+ glTexParameteri (tex_target, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
+ glTexParameteri (tex_target, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
+ break;
+ }
+ switch (attributes->filter) {
+ case CAIRO_FILTER_FAST:
+ case CAIRO_FILTER_NEAREST:
+ glTexParameteri (tex_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri (tex_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ break;
+ case CAIRO_FILTER_GOOD:
+ case CAIRO_FILTER_BEST:
+ case CAIRO_FILTER_BILINEAR:
+ glTexParameteri (tex_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri (tex_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ break;
+ default:
+ case CAIRO_FILTER_GAUSSIAN:
+ ASSERT_NOT_REACHED;
+ }
+ glEnable (tex_target);
+}
+
+static int
+_cairo_gl_gradient_sample_width (const cairo_gradient_pattern_t *gradient)
+{
+ unsigned int n;
+ int width;
+
+ width = 8;
+ for (n = 1; n < gradient->n_stops; n++) {
+ double dx = gradient->stops[n].offset - gradient->stops[n-1].offset;
+ double delta, max;
+ int ramp;
+
+ if (dx == 0)
+ continue;
+
+ max = gradient->stops[n].color.red -
+ gradient->stops[n-1].color.red;
+
+ delta = gradient->stops[n].color.green -
+ gradient->stops[n-1].color.green;
+ if (delta > max)
+ max = delta;
+
+ delta = gradient->stops[n].color.blue -
+ gradient->stops[n-1].color.blue;
+ if (delta > max)
+ max = delta;
+
+ delta = gradient->stops[n].color.alpha -
+ gradient->stops[n-1].color.alpha;
+ if (delta > max)
+ max = delta;
+
+ ramp = 128 * max / dx;
+ if (ramp > width)
+ width = ramp;
+ }
+
+ width = (width + 7) & -8;
+ return MIN (width, 1024);
+}
+
+static cairo_status_t
+_render_gradient (const cairo_gl_context_t *ctx,
+ cairo_gradient_pattern_t *pattern,
+ void *bytes,
+ int width)
+{
+ pixman_image_t *gradient, *image;
+ pixman_gradient_stop_t pixman_stops_stack[32];
+ pixman_gradient_stop_t *pixman_stops;
+ pixman_point_fixed_t p1, p2;
+ unsigned int i;
+
+ pixman_stops = pixman_stops_stack;
+ if (unlikely (pattern->n_stops > ARRAY_LENGTH (pixman_stops_stack))) {
+ pixman_stops = _cairo_malloc_ab (pattern->n_stops,
+ sizeof (pixman_gradient_stop_t));
+ if (unlikely (pixman_stops == NULL))
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ }
+
+ for (i = 0; i < pattern->n_stops; i++) {
+ pixman_stops[i].x = _cairo_fixed_16_16_from_double (pattern->stops[i].offset);
+ pixman_stops[i].color.red = pattern->stops[i].color.red_short;
+ pixman_stops[i].color.green = pattern->stops[i].color.green_short;
+ pixman_stops[i].color.blue = pattern->stops[i].color.blue_short;
+ pixman_stops[i].color.alpha = pattern->stops[i].color.alpha_short;
+ }
+
+ p1.x = 0;
+ p1.y = 0;
+ p2.x = width << 16;
+ p2.y = 0;
+
+ gradient = pixman_image_create_linear_gradient (&p1, &p2,
+ pixman_stops,
+ pattern->n_stops);
+ if (pixman_stops != pixman_stops_stack)
+ free (pixman_stops);
+
+ if (unlikely (gradient == NULL))
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+ pixman_image_set_filter (gradient, PIXMAN_FILTER_BILINEAR, NULL, 0);
+ pixman_image_set_repeat (gradient, PIXMAN_REPEAT_PAD);
+
+ image = pixman_image_create_bits (PIXMAN_a8r8g8b8, width, 1,
+ bytes, sizeof(uint32_t)*width);
+ if (unlikely (image == NULL)) {
+ pixman_image_unref (gradient);
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ }
+
+ pixman_image_composite32 (PIXMAN_OP_SRC,
+ gradient, NULL, image,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ width, 1);
+
+ pixman_image_unref (gradient);
+ pixman_image_unref (image);
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static void
+_cairo_gl_create_gradient_texture (const cairo_gl_context_t *ctx,
+ cairo_gl_surface_t *surface,
+ cairo_gradient_pattern_t *pattern,
+ GLuint *tex)
+{
+ int tex_width;
+ GLubyte *data;
+
+ assert (pattern->n_stops != 0);
+
+ tex_width = _cairo_gl_gradient_sample_width (pattern);
+
+ glBindBufferARB (GL_PIXEL_UNPACK_BUFFER_ARB, ctx->texture_load_pbo);
+ glBufferDataARB (GL_PIXEL_UNPACK_BUFFER_ARB, tex_width * sizeof (uint32_t), 0, GL_STREAM_DRAW);
+ data = glMapBufferARB (GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY);
+
+ _render_gradient (ctx, pattern, data, tex_width);
+
+ glUnmapBufferARB (GL_PIXEL_UNPACK_BUFFER_ARB);
+
+ glGenTextures (1, tex);
+ glBindTexture (GL_TEXTURE_1D, *tex);
+ glTexImage1D (GL_TEXTURE_1D, 0, GL_RGBA8, tex_width, 0,
+ GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, 0);
+
+ glBindBufferARB (GL_PIXEL_UNPACK_BUFFER_ARB, 0);
+
+ glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+ switch (pattern->base.extend) {
+ case CAIRO_EXTEND_NONE:
+ glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
+ break;
+ case CAIRO_EXTEND_PAD:
+ glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ break;
+ case CAIRO_EXTEND_REPEAT:
+ glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ break;
+ case CAIRO_EXTEND_REFLECT:
+ glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
+ break;
+ }
+}
+
+/**
+ * Like cairo_pattern_acquire_surface(), but returns a matrix that transforms
+ * from dest to src coords.
+ */
+static cairo_status_t
+_cairo_gl_pattern_texture_setup (cairo_gl_context_t *ctx,
+ cairo_gl_operand_t *operand,
+ const cairo_pattern_t *src,
+ cairo_gl_surface_t *dst,
+ int src_x, int src_y,
+ int dst_x, int dst_y,
+ int width, int height)
+{
+ cairo_status_t status;
+ cairo_matrix_t m;
+ cairo_gl_surface_t *surface;
+ cairo_surface_attributes_t *attributes;
+ attributes = &operand->operand.texture.attributes;
+
+ status = _cairo_pattern_acquire_surface (src, &dst->base,
+ src_x, src_y,
+ width, height,
+ CAIRO_PATTERN_ACQUIRE_NONE,
+ (cairo_surface_t **)
+ &surface,
+ attributes);
+ if (unlikely (status))
+ return status;
+
+ if (ctx->tex_target == GL_TEXTURE_RECTANGLE_EXT &&
+ (attributes->extend == CAIRO_EXTEND_REPEAT ||
+ attributes->extend == CAIRO_EXTEND_REFLECT))
+ {
+ _cairo_pattern_release_surface (operand->pattern,
+ &surface->base,
+ attributes);
+ return UNSUPPORTED ("EXT_texture_rectangle with repeat/reflect");
+ }
+
+ assert (surface->base.backend == &_cairo_gl_surface_backend);
+
+ operand->type = CAIRO_GL_OPERAND_TEXTURE;
+ operand->operand.texture.surface = surface;
+ operand->operand.texture.tex = surface->tex;
+ /* Translate the matrix from
+ * (unnormalized src -> unnormalized src) to
+ * (unnormalized dst -> unnormalized src)
+ */
+ cairo_matrix_init_translate (&m,
+ src_x - dst_x + attributes->x_offset,
+ src_y - dst_y + attributes->y_offset);
+ cairo_matrix_multiply (&attributes->matrix,
+ &m,
+ &attributes->matrix);
+
+
+ /* Translate the matrix from
+ * (unnormalized dst -> unnormalized src) to
+ * (unnormalized dst -> normalized src)
+ */
+ if (ctx->tex_target == GL_TEXTURE_RECTANGLE_EXT) {
+ cairo_matrix_init_scale (&m,
+ 1.0,
+ 1.0);
+ } else {
+ cairo_matrix_init_scale (&m,
+ 1.0 / surface->width,
+ 1.0 / surface->height);
+ }
+ cairo_matrix_multiply (&attributes->matrix,
+ &attributes->matrix,
+ &m);
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cairo_gl_solid_operand_init (cairo_gl_operand_t *operand,
+ const cairo_color_t *color)
+{
+ operand->type = CAIRO_GL_OPERAND_CONSTANT;
+ operand->operand.constant.color[0] = color->red * color->alpha;
+ operand->operand.constant.color[1] = color->green * color->alpha;
+ operand->operand.constant.color[2] = color->blue * color->alpha;
+ operand->operand.constant.color[3] = color->alpha;
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cairo_gl_gradient_operand_init (cairo_gl_context_t *ctx,
+ cairo_gl_operand_t *operand,
+ cairo_gl_surface_t *dst)
+{
+ cairo_gradient_pattern_t *gradient = (cairo_gradient_pattern_t *)operand->pattern;
+
+ if (! _cairo_gl_device_has_glsl (&ctx->base))
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+
+ if (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR) {
+ cairo_linear_pattern_t *linear = (cairo_linear_pattern_t *) gradient;
+ double x0, y0, x1, y1;
+
+ x0 = _cairo_fixed_to_double (linear->p1.x);
+ x1 = _cairo_fixed_to_double (linear->p2.x);
+ y0 = _cairo_fixed_to_double (linear->p1.y);
+ y1 = _cairo_fixed_to_double (linear->p2.y);
+
+ if ((unsigned int)ctx->max_texture_size / 2 <= gradient->n_stops) {
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+ }
+
+ _cairo_gl_create_gradient_texture (ctx,
+ dst,
+ gradient,
+ &operand->operand.linear.tex);
+
+ /* Translation matrix from the destination fragment coordinates
+ * (pixels from lower left = 0,0) to the coordinates in the
+ */
+ cairo_matrix_init_translate (&operand->operand.linear.m, -x0, -y0);
+ cairo_matrix_multiply (&operand->operand.linear.m,
+ &operand->pattern->matrix,
+ &operand->operand.linear.m);
+ cairo_matrix_translate (&operand->operand.linear.m, 0, dst->height);
+ cairo_matrix_scale (&operand->operand.linear.m, 1.0, -1.0);
+
+ operand->operand.linear.segment_x = x1 - x0;
+ operand->operand.linear.segment_y = y1 - y0;
+
+ operand->type = CAIRO_GL_OPERAND_LINEAR_GRADIENT;
+ return CAIRO_STATUS_SUCCESS;
+ } else {
+ cairo_radial_pattern_t *radial = (cairo_radial_pattern_t *) gradient;
+ double x0, y0, r0, x1, y1, r1;
+
+ x0 = _cairo_fixed_to_double (radial->c1.x);
+ x1 = _cairo_fixed_to_double (radial->c2.x);
+ y0 = _cairo_fixed_to_double (radial->c1.y);
+ y1 = _cairo_fixed_to_double (radial->c2.y);
+ r0 = _cairo_fixed_to_double (radial->r1);
+ r1 = _cairo_fixed_to_double (radial->r2);
+
+ if ((unsigned int)ctx->max_texture_size / 2 <= gradient->n_stops)
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+
+ _cairo_gl_create_gradient_texture (ctx,
+ dst,
+ gradient,
+ &operand->operand.radial.tex);
+
+ /* Translation matrix from the destination fragment coordinates
+ * (pixels from lower left = 0,0) to the coordinates in the
+ */
+ cairo_matrix_init_translate (&operand->operand.radial.m, -x0, -y0);
+ cairo_matrix_multiply (&operand->operand.radial.m,
+ &operand->pattern->matrix,
+ &operand->operand.radial.m);
+ cairo_matrix_translate (&operand->operand.radial.m, 0, dst->height);
+ cairo_matrix_scale (&operand->operand.radial.m, 1.0, -1.0);
+
+ operand->operand.radial.circle_1_x = x1 - x0;
+ operand->operand.radial.circle_1_y = y1 - y0;
+ operand->operand.radial.radius_0 = r0;
+ operand->operand.radial.radius_1 = r1;
+
+ operand->type = CAIRO_GL_OPERAND_RADIAL_GRADIENT;
+ return CAIRO_STATUS_SUCCESS;
+ }
+
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+}
+
+cairo_int_status_t
+_cairo_gl_operand_init (cairo_gl_context_t *ctx,
+ cairo_gl_operand_t *operand,
+ const cairo_pattern_t *pattern,
+ cairo_gl_surface_t *dst,
+ int src_x, int src_y,
+ int dst_x, int dst_y,
+ int width, int height)
+{
+ cairo_status_t status;
+
+ operand->pattern = pattern;
+
+ switch (pattern->type) {
+ case CAIRO_PATTERN_TYPE_SOLID:
+ return _cairo_gl_solid_operand_init (operand,
+ &((cairo_solid_pattern_t *) pattern)->color);
+ case CAIRO_PATTERN_TYPE_LINEAR:
+ case CAIRO_PATTERN_TYPE_RADIAL:
+ status = _cairo_gl_gradient_operand_init (ctx, operand, dst);
+ if (status != CAIRO_INT_STATUS_UNSUPPORTED)
+ return status;
+
+ /* fall through */
+
+ default:
+ case CAIRO_PATTERN_TYPE_SURFACE:
+ return _cairo_gl_pattern_texture_setup (ctx, operand,
+ pattern, dst,
+ src_x, src_y,
+ dst_x, dst_y,
+ width, height);
+ }
+}
+
+void
+_cairo_gl_operand_destroy (cairo_gl_operand_t *operand)
+{
+ switch (operand->type) {
+ case CAIRO_GL_OPERAND_CONSTANT:
+ break;
+ case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
+ glDeleteTextures (1, &operand->operand.linear.tex);
+ break;
+ case CAIRO_GL_OPERAND_RADIAL_GRADIENT:
+ glDeleteTextures (1, &operand->operand.radial.tex);
+ break;
+ case CAIRO_GL_OPERAND_TEXTURE:
+ if (operand->operand.texture.surface != NULL) {
+ cairo_gl_surface_t *surface = operand->operand.texture.surface;
+
+ _cairo_pattern_release_surface (operand->pattern,
+ &surface->base,
+ &operand->operand.texture.attributes);
+ }
+ break;
+ default:
+ case CAIRO_GL_OPERAND_COUNT:
+ ASSERT_NOT_REACHED;
+ case CAIRO_GL_OPERAND_NONE:
+ case CAIRO_GL_OPERAND_SPANS:
+ break;
+ }
+}
+
+static void
+_cairo_gl_set_tex_combine_constant_color (cairo_gl_context_t *ctx,
+ cairo_gl_composite_t *setup,
+ int tex_unit,
+ GLfloat *color)
+{
+ if (setup->shader) {
+ const char *uniform_name;
+ cairo_status_t status;
+
+ if (tex_unit == 0)
+ uniform_name = "source_constant";
+ else
+ uniform_name = "mask_constant";
+
+ status = bind_vec4_to_shader (ctx,
+ setup->shader->program,
+ uniform_name,
+ color[0],
+ color[1],
+ color[2],
+ color[3]);
+ assert (! _cairo_status_is_error (status));
+
+ return;
+ }
+
+ /* Fall back to fixed function */
+ glActiveTexture (GL_TEXTURE0 + tex_unit);
+ /* 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);
+
+ glTexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);
+ glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
+ if (tex_unit == 0) {
+ glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE);
+ glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
+ } else {
+ 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_CONSTANT);
+ glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_CONSTANT);
+ if (tex_unit == 0) {
+ glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
+ glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
+ } else {
+ glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_ALPHA);
+ glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
+
+ glTexEnvi (GL_TEXTURE_ENV, GL_SRC1_RGB, GL_PREVIOUS);
+ glTexEnvi (GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_PREVIOUS);
+ glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
+ glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
+ }
+}
+
+void
+_cairo_gl_set_src_operand (cairo_gl_context_t *ctx,
+ cairo_gl_composite_t *setup)
+{
+ cairo_surface_attributes_t *src_attributes;
+ GLfloat constant_color[4] = {0.0, 0.0, 0.0, 0.0};
+ cairo_status_t status;
+
+ src_attributes = &setup->src.operand.texture.attributes;
+
+ switch (setup->src.type) {
+ case CAIRO_GL_OPERAND_CONSTANT:
+ _cairo_gl_set_tex_combine_constant_color (ctx, setup, 0,
+ setup->src.operand.constant.color);
+ break;
+ case CAIRO_GL_OPERAND_TEXTURE:
+ _cairo_gl_set_texture_surface (0, setup->src.operand.texture.tex,
+ src_attributes, ctx->tex_target);
+ if (!setup->shader) {
+ /* Set up the constant color we use to set color to 0 if needed. */
+ glTexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, constant_color);
+ /* Set up the combiner to just set color to the sampled texture. */
+ glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
+ glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE);
+ glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
+
+ /* Force the src color to 0 if the surface should be
+ * alpha-only. We may have a teximage with color bits if
+ * the implementation doesn't support GL_ALPHA FBOs.
+ */
+ if (setup->src.operand.texture.surface->base.content !=
+ CAIRO_CONTENT_ALPHA)
+ glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_RGB, GL_TEXTURE0);
+ else
+ glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_RGB, GL_CONSTANT);
+ glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_TEXTURE0);
+ glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
+ glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
+ }
+ break;
+
+ case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
+ glActiveTexture (GL_TEXTURE0);
+ glBindTexture (GL_TEXTURE_1D, setup->src.operand.linear.tex);
+ glEnable (GL_TEXTURE_1D);
+
+ status = bind_matrix_to_shader (ctx, setup->shader->program,
+ "source_matrix",
+ &setup->src.operand.linear.m);
+ assert (!_cairo_status_is_error (status));
+
+ status = bind_vec2_to_shader (ctx, setup->shader->program,
+ "source_segment",
+ setup->src.operand.linear.segment_x,
+ setup->src.operand.linear.segment_y);
+ assert (!_cairo_status_is_error (status));
+ break;
+
+ case CAIRO_GL_OPERAND_RADIAL_GRADIENT:
+ glActiveTexture (GL_TEXTURE0);
+ glBindTexture (GL_TEXTURE_1D, setup->src.operand.linear.tex);
+ glEnable (GL_TEXTURE_1D);
+
+ status = bind_matrix_to_shader (ctx, setup->shader->program,
+ "source_matrix",
+ &setup->src.operand.radial.m);
+ assert (!_cairo_status_is_error (status));
+
+ status = bind_vec2_to_shader (ctx, setup->shader->program,
+ "source_circle_1",
+ setup->src.operand.radial.circle_1_x,
+ setup->src.operand.radial.circle_1_y);
+ assert (!_cairo_status_is_error (status));
+
+ status = bind_float_to_shader (ctx, setup->shader->program,
+ "source_radius_0",
+ setup->src.operand.radial.radius_0);
+ assert (!_cairo_status_is_error (status));
+
+ status = bind_float_to_shader (ctx, setup->shader->program,
+ "source_radius_1",
+ setup->src.operand.radial.radius_1);
+ assert (!_cairo_status_is_error (status));
+ break;
+ default:
+ case CAIRO_GL_OPERAND_COUNT:
+ ASSERT_NOT_REACHED;
+ case CAIRO_GL_OPERAND_NONE:
+ case CAIRO_GL_OPERAND_SPANS:
+ break;
+ }
+}
+
+/* This is like _cairo_gl_set_src_operand, but instead swizzles the source
+ * for creating the "source alpha" value (src.aaaa * mask.argb) required by
+ * component alpha rendering.
+ */
+void
+_cairo_gl_set_src_alpha_operand (cairo_gl_context_t *ctx,
+ cairo_gl_composite_t *setup)
+{
+ GLfloat constant_color[4] = {0.0, 0.0, 0.0, 0.0};
+ cairo_surface_attributes_t *src_attributes;
+
+ src_attributes = &setup->src.operand.texture.attributes;
+
+ switch (setup->src.type) {
+ case CAIRO_GL_OPERAND_CONSTANT:
+ constant_color[0] = setup->src.operand.constant.color[3];
+ constant_color[1] = setup->src.operand.constant.color[3];
+ constant_color[2] = setup->src.operand.constant.color[3];
+ constant_color[3] = setup->src.operand.constant.color[3];
+ _cairo_gl_set_tex_combine_constant_color (ctx, setup, 0,
+ constant_color);
+ break;
+ case CAIRO_GL_OPERAND_TEXTURE:
+ _cairo_gl_set_texture_surface (0, setup->src.operand.texture.tex,
+ src_attributes, ctx->tex_target);
+ if (!setup->shader) {
+ /* Set up the combiner to just set color to the sampled texture. */
+ glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
+ glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE);
+ glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
+
+ glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_RGB, GL_TEXTURE0);
+ glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_TEXTURE0);
+ glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_ALPHA);
+ glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
+ }
+ break;
+ case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
+ case CAIRO_GL_OPERAND_RADIAL_GRADIENT:
+ case CAIRO_GL_OPERAND_NONE:
+ case CAIRO_GL_OPERAND_SPANS:
+ case CAIRO_GL_OPERAND_COUNT:
+ default:
+ ASSERT_NOT_REACHED;
+ break;
+ }
+}
+
+static void
+_cairo_gl_set_linear_gradient_mask_operand (cairo_gl_context_t *ctx,
+ cairo_gl_composite_t *setup)
+{
+ cairo_status_t status;
+
+ assert(setup->shader);
+
+ glActiveTexture (GL_TEXTURE1);
+ glBindTexture (GL_TEXTURE_1D, setup->mask.operand.linear.tex);
+ glEnable (GL_TEXTURE_1D);
+
+ status = bind_matrix_to_shader (ctx, setup->shader->program,
+ "mask_matrix", &setup->mask.operand.linear.m);
+ assert (!_cairo_status_is_error (status));
+
+ status = bind_vec2_to_shader (ctx, setup->shader->program,
+ "mask_segment",
+ setup->mask.operand.linear.segment_x,
+ setup->mask.operand.linear.segment_y);
+ assert (!_cairo_status_is_error (status));
+}
+
+static void
+_cairo_gl_set_radial_gradient_mask_operand (cairo_gl_context_t *ctx,
+ cairo_gl_composite_t *setup)
+{
+ cairo_status_t status;
+
+ assert(setup->shader);
+
+ glActiveTexture (GL_TEXTURE1);
+ glBindTexture (GL_TEXTURE_1D, setup->mask.operand.radial.tex);
+ glEnable (GL_TEXTURE_1D);
+
+ status = bind_matrix_to_shader (ctx, setup->shader->program,
+ "mask_matrix",
+ &setup->mask.operand.radial.m);
+ assert (!_cairo_status_is_error (status));
+
+ status = bind_vec2_to_shader (ctx, setup->shader->program,
+ "mask_circle_1",
+ setup->mask.operand.radial.circle_1_x,
+ setup->mask.operand.radial.circle_1_y);
+ assert (!_cairo_status_is_error (status));
+
+ status = bind_float_to_shader (ctx, setup->shader->program,
+ "mask_radius_0",
+ setup->mask.operand.radial.radius_0);
+ assert (!_cairo_status_is_error (status));
+
+ status = bind_float_to_shader (ctx, setup->shader->program,
+ "mask_radius_1",
+ setup->mask.operand.radial.radius_1);
+ assert (!_cairo_status_is_error (status));
+}
+
+/* This is like _cairo_gl_set_src_alpha_operand, for component alpha setup
+ * of the mask part of IN to produce a "source alpha" value.
+ */
+void
+_cairo_gl_set_component_alpha_mask_operand (cairo_gl_context_t *ctx,
+ cairo_gl_composite_t *setup)
+{
+ cairo_surface_attributes_t *mask_attributes;
+ GLfloat constant_color[4] = {0.0, 0.0, 0.0, 0.0};
+
+ mask_attributes = &setup->mask.operand.texture.attributes;
+
+ if (!setup->shader) {
+ 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_SRC1_RGB, GL_PREVIOUS);
+ glTexEnvi (GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_PREVIOUS);
+ glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
+ glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
+ }
+
+ switch (setup->mask.type) {
+ case CAIRO_GL_OPERAND_CONSTANT:
+ /* Have to have a dummy texture bound in order to use the combiner unit. */
+ if (setup->shader) {
+ cairo_status_t status;
+ status = bind_vec4_to_shader (ctx, setup->shader->program,
+ "mask_constant",
+ setup->src.operand.constant.color[0],
+ setup->src.operand.constant.color[1],
+ setup->src.operand.constant.color[2],
+ setup->src.operand.constant.color[3]);
+ assert (! _cairo_status_is_error (status));
+ } else {
+ glBindTexture (ctx->tex_target, ctx->dummy_tex);
+ glActiveTexture (GL_TEXTURE1);
+ glEnable (ctx->tex_target);
+
+ glTexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR,
+ setup->mask.operand.constant.color);
+
+ glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_RGB, GL_CONSTANT);
+ glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_CONSTANT);
+ glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
+ glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
+ }
+ break;
+ case CAIRO_GL_OPERAND_TEXTURE:
+ _cairo_gl_set_texture_surface (1, setup->mask.operand.texture.tex,
+ mask_attributes, ctx->tex_target);
+ if (!setup->shader) {
+ /* Set up the constant color we use to set color to 0 if needed. */
+ glTexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, constant_color);
+
+ /* Force the mask color to 0 if the surface should be
+ * alpha-only. We may have a teximage with color bits if
+ * the implementation doesn't support GL_ALPHA FBOs.
+ */
+ if (setup->mask.operand.texture.surface->base.content !=
+ CAIRO_CONTENT_ALPHA)
+ glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_RGB, GL_TEXTURE1);
+ else
+ glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_RGB, GL_CONSTANT);
+ glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_TEXTURE1);
+ glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
+ glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
+ }
+ break;
+
+ case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
+ _cairo_gl_set_linear_gradient_mask_operand (ctx, setup);
+ break;
+
+ case CAIRO_GL_OPERAND_RADIAL_GRADIENT:
+ _cairo_gl_set_radial_gradient_mask_operand (ctx, setup);
+ break;
+ case CAIRO_GL_OPERAND_NONE:
+ case CAIRO_GL_OPERAND_SPANS:
+ case CAIRO_GL_OPERAND_COUNT:
+ default:
+ ASSERT_NOT_REACHED;
+ break;
+ }
+}
+
+void
+_cairo_gl_set_mask_operand (cairo_gl_context_t *ctx,
+ cairo_gl_composite_t *setup)
+{
+ switch (setup->mask.type) {
+ case CAIRO_GL_OPERAND_CONSTANT:
+ _cairo_gl_set_tex_combine_constant_color (ctx, setup, 1,
+ setup->mask.operand.constant.color);
+ break;
+
+ case CAIRO_GL_OPERAND_TEXTURE:
+ _cairo_gl_set_texture_surface (1, setup->mask.operand.texture.tex,
+ &setup->mask.operand.texture.attributes,
+ ctx->tex_target);
+
+ if (! setup->shader) {
+ 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);
+
+ /* IN: dst.argb = src.argb * mask.aaaa */
+ glTexEnvi (GL_TEXTURE_ENV, GL_SRC1_RGB, GL_TEXTURE1);
+ glTexEnvi (GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_TEXTURE1);
+ 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_LINEAR_GRADIENT:
+ _cairo_gl_set_linear_gradient_mask_operand (ctx, setup);
+ break;
+ case CAIRO_GL_OPERAND_RADIAL_GRADIENT:
+ _cairo_gl_set_radial_gradient_mask_operand (ctx, setup);
+ break;
+ case CAIRO_GL_OPERAND_NONE:
+ break;
+ case CAIRO_GL_OPERAND_SPANS:
+ case CAIRO_GL_OPERAND_COUNT:
+ default:
+ ASSERT_NOT_REACHED;
+ break;
+ }
+}
+
+void
+_cairo_gl_composite_fini (cairo_gl_context_t *ctx,
+ cairo_gl_composite_t *setup)
+{
+ _cairo_gl_operand_destroy (&setup->src);
+ _cairo_gl_operand_destroy (&setup->mask);
+}
+
+cairo_status_t
+_cairo_gl_composite_init (cairo_gl_context_t *ctx,
+ cairo_gl_composite_t *setup,
+ cairo_operator_t op,
+ cairo_gl_surface_t *dst,
+ const cairo_pattern_t *src,
+ const cairo_pattern_t *mask,
+ const cairo_rectangle_int_t *rect)
+{
+ memset (setup, 0, sizeof (cairo_gl_composite_t));
+
+ if (! _cairo_gl_operator_is_supported (op))
+ return UNSUPPORTED ("unsupported operator");
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h
index c5944e7..6da413c 100644
--- a/src/cairo-gl-private.h
+++ b/src/cairo-gl-private.h
@@ -293,6 +293,14 @@ _cairo_gl_set_src_alpha_operand (cairo_gl_context_t *ctx,
cairo_gl_composite_t *setup);
cairo_private void
+_cairo_gl_set_component_alpha_mask_operand (cairo_gl_context_t *ctx,
+ cairo_gl_composite_t *setup);
+
+cairo_private void
+_cairo_gl_set_mask_operand (cairo_gl_context_t *ctx,
+ cairo_gl_composite_t *setup);
+
+cairo_private void
_cairo_gl_operand_destroy (cairo_gl_operand_t *operand);
cairo_private cairo_bool_t
diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c
index ac8e881..16deaab 100644
--- a/src/cairo-gl-surface.c
+++ b/src/cairo-gl-surface.c
@@ -251,56 +251,6 @@ _cairo_gl_set_operator (cairo_gl_surface_t *dst, cairo_operator_t op,
}
}
-static void
-_cairo_gl_set_texture_surface (int tex_unit, GLuint tex,
- cairo_surface_attributes_t *attributes,
- GLint tex_target)
-{
-
- if (tex_target == GL_TEXTURE_RECTANGLE_EXT) {
- assert (attributes->extend != CAIRO_EXTEND_REPEAT &&
- attributes->extend != CAIRO_EXTEND_REFLECT);
- }
-
- glActiveTexture (GL_TEXTURE0 + tex_unit);
- glBindTexture (tex_target, tex);
- switch (attributes->extend) {
- case CAIRO_EXTEND_NONE:
- glTexParameteri (tex_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
- glTexParameteri (tex_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
- break;
- case CAIRO_EXTEND_PAD:
- glTexParameteri (tex_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri (tex_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- break;
- case CAIRO_EXTEND_REPEAT:
- glTexParameteri (tex_target, GL_TEXTURE_WRAP_S, GL_REPEAT);
- glTexParameteri (tex_target, GL_TEXTURE_WRAP_T, GL_REPEAT);
- break;
- case CAIRO_EXTEND_REFLECT:
- glTexParameteri (tex_target, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
- glTexParameteri (tex_target, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
- break;
- }
- switch (attributes->filter) {
- case CAIRO_FILTER_FAST:
- case CAIRO_FILTER_NEAREST:
- glTexParameteri (tex_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri (tex_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- break;
- case CAIRO_FILTER_GOOD:
- case CAIRO_FILTER_BEST:
- case CAIRO_FILTER_BILINEAR:
- glTexParameteri (tex_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri (tex_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- break;
- default:
- case CAIRO_FILTER_GAUSSIAN:
- ASSERT_NOT_REACHED;
- }
- glEnable (tex_target);
-}
-
void
_cairo_gl_surface_init (cairo_device_t *device,
cairo_gl_surface_t *surface,
@@ -986,764 +936,6 @@ _cairo_gl_get_traps_pattern (cairo_gl_surface_t *dst,
return CAIRO_STATUS_SUCCESS;
}
-static int
-_cairo_gl_gradient_sample_width (const cairo_gradient_pattern_t *gradient)
-{
- unsigned int n;
- int width;
-
- width = 8;
- for (n = 1; n < gradient->n_stops; n++) {
- double dx = gradient->stops[n].offset - gradient->stops[n-1].offset;
- double delta, max;
- int ramp;
-
- if (dx == 0)
- continue;
-
- max = gradient->stops[n].color.red -
- gradient->stops[n-1].color.red;
-
- delta = gradient->stops[n].color.green -
- gradient->stops[n-1].color.green;
- if (delta > max)
- max = delta;
-
- delta = gradient->stops[n].color.blue -
- gradient->stops[n-1].color.blue;
- if (delta > max)
- max = delta;
-
- delta = gradient->stops[n].color.alpha -
- gradient->stops[n-1].color.alpha;
- if (delta > max)
- max = delta;
-
- ramp = 128 * max / dx;
- if (ramp > width)
- width = ramp;
- }
-
- width = (width + 7) & -8;
- return MIN (width, 1024);
-}
-
-static cairo_status_t
-_render_gradient (const cairo_gl_context_t *ctx,
- cairo_gradient_pattern_t *pattern,
- void *bytes,
- int width)
-{
- pixman_image_t *gradient, *image;
- pixman_gradient_stop_t pixman_stops_stack[32];
- pixman_gradient_stop_t *pixman_stops;
- pixman_point_fixed_t p1, p2;
- unsigned int i;
-
- pixman_stops = pixman_stops_stack;
- if (unlikely (pattern->n_stops > ARRAY_LENGTH (pixman_stops_stack))) {
- pixman_stops = _cairo_malloc_ab (pattern->n_stops,
- sizeof (pixman_gradient_stop_t));
- if (unlikely (pixman_stops == NULL))
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
- }
-
- for (i = 0; i < pattern->n_stops; i++) {
- pixman_stops[i].x = _cairo_fixed_16_16_from_double (pattern->stops[i].offset);
- pixman_stops[i].color.red = pattern->stops[i].color.red_short;
- pixman_stops[i].color.green = pattern->stops[i].color.green_short;
- pixman_stops[i].color.blue = pattern->stops[i].color.blue_short;
- pixman_stops[i].color.alpha = pattern->stops[i].color.alpha_short;
- }
-
- p1.x = 0;
- p1.y = 0;
- p2.x = width << 16;
- p2.y = 0;
-
- gradient = pixman_image_create_linear_gradient (&p1, &p2,
- pixman_stops,
- pattern->n_stops);
- if (pixman_stops != pixman_stops_stack)
- free (pixman_stops);
-
- if (unlikely (gradient == NULL))
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
- pixman_image_set_filter (gradient, PIXMAN_FILTER_BILINEAR, NULL, 0);
- pixman_image_set_repeat (gradient, PIXMAN_REPEAT_PAD);
-
- image = pixman_image_create_bits (PIXMAN_a8r8g8b8, width, 1,
- bytes, sizeof(uint32_t)*width);
- if (unlikely (image == NULL)) {
- pixman_image_unref (gradient);
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
- }
-
- pixman_image_composite32 (PIXMAN_OP_SRC,
- gradient, NULL, image,
- 0, 0,
- 0, 0,
- 0, 0,
- width, 1);
-
- pixman_image_unref (gradient);
- pixman_image_unref (image);
- return CAIRO_STATUS_SUCCESS;
-}
-
-static void
-_cairo_gl_create_gradient_texture (const cairo_gl_context_t *ctx,
- cairo_gl_surface_t *surface,
- cairo_gradient_pattern_t *pattern,
- GLuint *tex)
-{
- int tex_width;
- GLubyte *data;
-
- assert (pattern->n_stops != 0);
-
- tex_width = _cairo_gl_gradient_sample_width (pattern);
-
- glBindBufferARB (GL_PIXEL_UNPACK_BUFFER_ARB, ctx->texture_load_pbo);
- glBufferDataARB (GL_PIXEL_UNPACK_BUFFER_ARB, tex_width * sizeof (uint32_t), 0, GL_STREAM_DRAW);
- data = glMapBufferARB (GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY);
-
- _render_gradient (ctx, pattern, data, tex_width);
-
- glUnmapBufferARB (GL_PIXEL_UNPACK_BUFFER_ARB);
-
- glGenTextures (1, tex);
- glBindTexture (GL_TEXTURE_1D, *tex);
- glTexImage1D (GL_TEXTURE_1D, 0, GL_RGBA8, tex_width, 0,
- GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, 0);
-
- glBindBufferARB (GL_PIXEL_UNPACK_BUFFER_ARB, 0);
-
- glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-
- switch (pattern->base.extend) {
- case CAIRO_EXTEND_NONE:
- glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
- break;
- case CAIRO_EXTEND_PAD:
- glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- break;
- case CAIRO_EXTEND_REPEAT:
- glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_REPEAT);
- break;
- case CAIRO_EXTEND_REFLECT:
- glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
- break;
- }
-}
-
-/**
- * Like cairo_pattern_acquire_surface(), but returns a matrix that transforms
- * from dest to src coords.
- */
-static cairo_status_t
-_cairo_gl_pattern_texture_setup (cairo_gl_context_t *ctx,
- cairo_gl_operand_t *operand,
- const cairo_pattern_t *src,
- cairo_gl_surface_t *dst,
- int src_x, int src_y,
- int dst_x, int dst_y,
- int width, int height)
-{
- cairo_status_t status;
- cairo_matrix_t m;
- cairo_gl_surface_t *surface;
- cairo_surface_attributes_t *attributes;
- attributes = &operand->operand.texture.attributes;
-
- status = _cairo_pattern_acquire_surface (src, &dst->base,
- src_x, src_y,
- width, height,
- CAIRO_PATTERN_ACQUIRE_NONE,
- (cairo_surface_t **)
- &surface,
- attributes);
- if (unlikely (status))
- return status;
-
- if (ctx->tex_target == GL_TEXTURE_RECTANGLE_EXT &&
- (attributes->extend == CAIRO_EXTEND_REPEAT ||
- attributes->extend == CAIRO_EXTEND_REFLECT))
- {
- _cairo_pattern_release_surface (operand->pattern,
- &surface->base,
- attributes);
- return UNSUPPORTED ("EXT_texture_rectangle with repeat/reflect");
- }
-
- assert (surface->base.backend == &_cairo_gl_surface_backend);
-
- operand->type = CAIRO_GL_OPERAND_TEXTURE;
- operand->operand.texture.surface = surface;
- operand->operand.texture.tex = surface->tex;
- /* Translate the matrix from
- * (unnormalized src -> unnormalized src) to
- * (unnormalized dst -> unnormalized src)
- */
- cairo_matrix_init_translate (&m,
- src_x - dst_x + attributes->x_offset,
- src_y - dst_y + attributes->y_offset);
- cairo_matrix_multiply (&attributes->matrix,
- &m,
- &attributes->matrix);
-
-
- /* Translate the matrix from
- * (unnormalized dst -> unnormalized src) to
- * (unnormalized dst -> normalized src)
- */
- if (ctx->tex_target == GL_TEXTURE_RECTANGLE_EXT) {
- cairo_matrix_init_scale (&m,
- 1.0,
- 1.0);
- } else {
- cairo_matrix_init_scale (&m,
- 1.0 / surface->width,
- 1.0 / surface->height);
- }
- cairo_matrix_multiply (&attributes->matrix,
- &attributes->matrix,
- &m);
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_cairo_gl_solid_operand_init (cairo_gl_operand_t *operand,
- const cairo_color_t *color)
-{
- operand->type = CAIRO_GL_OPERAND_CONSTANT;
- operand->operand.constant.color[0] = color->red * color->alpha;
- operand->operand.constant.color[1] = color->green * color->alpha;
- operand->operand.constant.color[2] = color->blue * color->alpha;
- operand->operand.constant.color[3] = color->alpha;
- return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_cairo_gl_gradient_operand_init(cairo_gl_context_t *ctx,
- cairo_gl_operand_t *operand,
- cairo_gl_surface_t *dst)
-{
- cairo_gradient_pattern_t *gradient = (cairo_gradient_pattern_t *)operand->pattern;
-
- if (! _cairo_gl_device_has_glsl (&ctx->base))
- return CAIRO_INT_STATUS_UNSUPPORTED;
-
- if (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR) {
- cairo_linear_pattern_t *linear = (cairo_linear_pattern_t *) gradient;
- double x0, y0, x1, y1;
-
- x0 = _cairo_fixed_to_double (linear->p1.x);
- x1 = _cairo_fixed_to_double (linear->p2.x);
- y0 = _cairo_fixed_to_double (linear->p1.y);
- y1 = _cairo_fixed_to_double (linear->p2.y);
-
- if ((unsigned int)ctx->max_texture_size / 2 <= gradient->n_stops) {
- return CAIRO_INT_STATUS_UNSUPPORTED;
- }
-
- _cairo_gl_create_gradient_texture (ctx,
- dst,
- gradient,
- &operand->operand.linear.tex);
-
- /* Translation matrix from the destination fragment coordinates
- * (pixels from lower left = 0,0) to the coordinates in the
- */
- cairo_matrix_init_translate (&operand->operand.linear.m, -x0, -y0);
- cairo_matrix_multiply (&operand->operand.linear.m,
- &operand->pattern->matrix,
- &operand->operand.linear.m);
- cairo_matrix_translate (&operand->operand.linear.m, 0, dst->height);
- cairo_matrix_scale (&operand->operand.linear.m, 1.0, -1.0);
-
- operand->operand.linear.segment_x = x1 - x0;
- operand->operand.linear.segment_y = y1 - y0;
-
- operand->type = CAIRO_GL_OPERAND_LINEAR_GRADIENT;
- return CAIRO_STATUS_SUCCESS;
- } else {
- cairo_radial_pattern_t *radial = (cairo_radial_pattern_t *) gradient;
- double x0, y0, r0, x1, y1, r1;
-
- x0 = _cairo_fixed_to_double (radial->c1.x);
- x1 = _cairo_fixed_to_double (radial->c2.x);
- y0 = _cairo_fixed_to_double (radial->c1.y);
- y1 = _cairo_fixed_to_double (radial->c2.y);
- r0 = _cairo_fixed_to_double (radial->r1);
- r1 = _cairo_fixed_to_double (radial->r2);
-
- if ((unsigned int)ctx->max_texture_size / 2 <= gradient->n_stops)
- return CAIRO_INT_STATUS_UNSUPPORTED;
-
- _cairo_gl_create_gradient_texture (ctx,
- dst,
- gradient,
- &operand->operand.radial.tex);
-
- /* Translation matrix from the destination fragment coordinates
- * (pixels from lower left = 0,0) to the coordinates in the
- */
- cairo_matrix_init_translate (&operand->operand.radial.m, -x0, -y0);
- cairo_matrix_multiply (&operand->operand.radial.m,
- &operand->pattern->matrix,
- &operand->operand.radial.m);
- cairo_matrix_translate (&operand->operand.radial.m, 0, dst->height);
- cairo_matrix_scale (&operand->operand.radial.m, 1.0, -1.0);
-
- operand->operand.radial.circle_1_x = x1 - x0;
- operand->operand.radial.circle_1_y = y1 - y0;
- operand->operand.radial.radius_0 = r0;
- operand->operand.radial.radius_1 = r1;
-
- operand->type = CAIRO_GL_OPERAND_RADIAL_GRADIENT;
- return CAIRO_STATUS_SUCCESS;
- }
-
- return CAIRO_INT_STATUS_UNSUPPORTED;
-}
-
-cairo_int_status_t
-_cairo_gl_operand_init (cairo_gl_context_t *ctx,
- cairo_gl_operand_t *operand,
- const cairo_pattern_t *pattern,
- cairo_gl_surface_t *dst,
- int src_x, int src_y,
- int dst_x, int dst_y,
- int width, int height)
-{
- cairo_status_t status;
-
- operand->pattern = pattern;
-
- switch (pattern->type) {
- case CAIRO_PATTERN_TYPE_SOLID:
- return _cairo_gl_solid_operand_init (operand,
- &((cairo_solid_pattern_t *) pattern)->color);
- case CAIRO_PATTERN_TYPE_LINEAR:
- case CAIRO_PATTERN_TYPE_RADIAL:
- status = _cairo_gl_gradient_operand_init (ctx, operand, dst);
- if (status != CAIRO_INT_STATUS_UNSUPPORTED)
- return status;
-
- /* fall through */
-
- default:
- case CAIRO_PATTERN_TYPE_SURFACE:
- return _cairo_gl_pattern_texture_setup (ctx, operand,
- pattern, dst,
- src_x, src_y,
- dst_x, dst_y,
- width, height);
- }
-}
-
-void
-_cairo_gl_operand_destroy (cairo_gl_operand_t *operand)
-{
- switch (operand->type) {
- case CAIRO_GL_OPERAND_CONSTANT:
- break;
- case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
- glDeleteTextures (1, &operand->operand.linear.tex);
- break;
- case CAIRO_GL_OPERAND_RADIAL_GRADIENT:
- glDeleteTextures (1, &operand->operand.radial.tex);
- break;
- case CAIRO_GL_OPERAND_TEXTURE:
- if (operand->operand.texture.surface != NULL) {
- cairo_gl_surface_t *surface = operand->operand.texture.surface;
-
- _cairo_pattern_release_surface (operand->pattern,
- &surface->base,
- &operand->operand.texture.attributes);
- }
- break;
- default:
- case CAIRO_GL_OPERAND_COUNT:
- ASSERT_NOT_REACHED;
- case CAIRO_GL_OPERAND_NONE:
- case CAIRO_GL_OPERAND_SPANS:
- break;
- }
-}
-
-static void
-_cairo_gl_set_tex_combine_constant_color (cairo_gl_context_t *ctx,
- cairo_gl_composite_t *setup,
- int tex_unit,
- GLfloat *color)
-{
- if (setup->shader) {
- const char *uniform_name;
- cairo_status_t status;
-
- if (tex_unit == 0)
- uniform_name = "source_constant";
- else
- uniform_name = "mask_constant";
-
- status = bind_vec4_to_shader (ctx,
- setup->shader->program,
- uniform_name,
- color[0],
- color[1],
- color[2],
- color[3]);
- assert (! _cairo_status_is_error (status));
-
- return;
- }
-
- /* Fall back to fixed function */
- glActiveTexture (GL_TEXTURE0 + tex_unit);
- /* 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);
-
- glTexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);
- glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
- if (tex_unit == 0) {
- glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE);
- glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
- } else {
- 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_CONSTANT);
- glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_CONSTANT);
- if (tex_unit == 0) {
- glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
- glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
- } else {
- glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_ALPHA);
- glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
-
- glTexEnvi (GL_TEXTURE_ENV, GL_SRC1_RGB, GL_PREVIOUS);
- glTexEnvi (GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_PREVIOUS);
- glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
- glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
- }
-}
-
-void
-_cairo_gl_set_src_operand (cairo_gl_context_t *ctx,
- cairo_gl_composite_t *setup)
-{
- cairo_surface_attributes_t *src_attributes;
- GLfloat constant_color[4] = {0.0, 0.0, 0.0, 0.0};
- cairo_status_t status;
-
- src_attributes = &setup->src.operand.texture.attributes;
-
- switch (setup->src.type) {
- case CAIRO_GL_OPERAND_CONSTANT:
- _cairo_gl_set_tex_combine_constant_color (ctx, setup, 0,
- setup->src.operand.constant.color);
- break;
- case CAIRO_GL_OPERAND_TEXTURE:
- _cairo_gl_set_texture_surface (0, setup->src.operand.texture.tex,
- src_attributes, ctx->tex_target);
- if (!setup->shader) {
- /* Set up the constant color we use to set color to 0 if needed. */
- glTexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, constant_color);
- /* Set up the combiner to just set color to the sampled texture. */
- glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
- glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE);
- glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
-
- /* Force the src color to 0 if the surface should be
- * alpha-only. We may have a teximage with color bits if
- * the implementation doesn't support GL_ALPHA FBOs.
- */
- if (setup->src.operand.texture.surface->base.content !=
- CAIRO_CONTENT_ALPHA)
- glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_RGB, GL_TEXTURE0);
- else
- glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_RGB, GL_CONSTANT);
- glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_TEXTURE0);
- glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
- glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
- }
- break;
-
- case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
- glActiveTexture (GL_TEXTURE0);
- glBindTexture (GL_TEXTURE_1D, setup->src.operand.linear.tex);
- glEnable (GL_TEXTURE_1D);
-
- status = bind_matrix_to_shader (ctx, setup->shader->program,
- "source_matrix",
- &setup->src.operand.linear.m);
- assert (!_cairo_status_is_error (status));
-
- status = bind_vec2_to_shader (ctx, setup->shader->program,
- "source_segment",
- setup->src.operand.linear.segment_x,
- setup->src.operand.linear.segment_y);
- assert (!_cairo_status_is_error (status));
- break;
-
- case CAIRO_GL_OPERAND_RADIAL_GRADIENT:
- glActiveTexture (GL_TEXTURE0);
- glBindTexture (GL_TEXTURE_1D, setup->src.operand.linear.tex);
- glEnable (GL_TEXTURE_1D);
-
- status = bind_matrix_to_shader (ctx, setup->shader->program,
- "source_matrix",
- &setup->src.operand.radial.m);
- assert (!_cairo_status_is_error (status));
-
- status = bind_vec2_to_shader (ctx, setup->shader->program,
- "source_circle_1",
- setup->src.operand.radial.circle_1_x,
- setup->src.operand.radial.circle_1_y);
- assert (!_cairo_status_is_error (status));
-
- status = bind_float_to_shader (ctx, setup->shader->program,
- "source_radius_0",
- setup->src.operand.radial.radius_0);
- assert (!_cairo_status_is_error (status));
-
- status = bind_float_to_shader (ctx, setup->shader->program,
- "source_radius_1",
- setup->src.operand.radial.radius_1);
- assert (!_cairo_status_is_error (status));
- break;
- default:
- case CAIRO_GL_OPERAND_COUNT:
- ASSERT_NOT_REACHED;
- case CAIRO_GL_OPERAND_NONE:
- case CAIRO_GL_OPERAND_SPANS:
- break;
- }
-}
-
-/* This is like _cairo_gl_set_src_operand, but instead swizzles the source
- * for creating the "source alpha" value (src.aaaa * mask.argb) required by
- * component alpha rendering.
- */
-void
-_cairo_gl_set_src_alpha_operand (cairo_gl_context_t *ctx,
- cairo_gl_composite_t *setup)
-{
- GLfloat constant_color[4] = {0.0, 0.0, 0.0, 0.0};
- cairo_surface_attributes_t *src_attributes;
-
- src_attributes = &setup->src.operand.texture.attributes;
-
- switch (setup->src.type) {
- case CAIRO_GL_OPERAND_CONSTANT:
- constant_color[0] = setup->src.operand.constant.color[3];
- constant_color[1] = setup->src.operand.constant.color[3];
- constant_color[2] = setup->src.operand.constant.color[3];
- constant_color[3] = setup->src.operand.constant.color[3];
- _cairo_gl_set_tex_combine_constant_color (ctx, setup, 0,
- constant_color);
- break;
- case CAIRO_GL_OPERAND_TEXTURE:
- _cairo_gl_set_texture_surface (0, setup->src.operand.texture.tex,
- src_attributes, ctx->tex_target);
- if (!setup->shader) {
- /* Set up the combiner to just set color to the sampled texture. */
- glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
- glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE);
- glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
-
- glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_RGB, GL_TEXTURE0);
- glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_TEXTURE0);
- glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_ALPHA);
- glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
- }
- break;
- case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
- case CAIRO_GL_OPERAND_RADIAL_GRADIENT:
- case CAIRO_GL_OPERAND_NONE:
- case CAIRO_GL_OPERAND_SPANS:
- case CAIRO_GL_OPERAND_COUNT:
- default:
- ASSERT_NOT_REACHED;
- break;
- }
-}
-
-static void
-_cairo_gl_set_linear_gradient_mask_operand (cairo_gl_context_t *ctx,
- cairo_gl_composite_t *setup)
-{
- cairo_status_t status;
-
- assert(setup->shader);
-
- glActiveTexture (GL_TEXTURE1);
- glBindTexture (GL_TEXTURE_1D, setup->mask.operand.linear.tex);
- glEnable (GL_TEXTURE_1D);
-
- status = bind_matrix_to_shader (ctx, setup->shader->program,
- "mask_matrix", &setup->mask.operand.linear.m);
- assert (!_cairo_status_is_error (status));
-
- status = bind_vec2_to_shader (ctx, setup->shader->program,
- "mask_segment",
- setup->mask.operand.linear.segment_x,
- setup->mask.operand.linear.segment_y);
- assert (!_cairo_status_is_error (status));
-}
-
-static void
-_cairo_gl_set_radial_gradient_mask_operand (cairo_gl_context_t *ctx,
- cairo_gl_composite_t *setup)
-{
- cairo_status_t status;
-
- assert(setup->shader);
-
- glActiveTexture (GL_TEXTURE1);
- glBindTexture (GL_TEXTURE_1D, setup->mask.operand.radial.tex);
- glEnable (GL_TEXTURE_1D);
-
- status = bind_matrix_to_shader (ctx, setup->shader->program,
- "mask_matrix",
- &setup->mask.operand.radial.m);
- assert (!_cairo_status_is_error (status));
-
- status = bind_vec2_to_shader (ctx, setup->shader->program,
- "mask_circle_1",
- setup->mask.operand.radial.circle_1_x,
- setup->mask.operand.radial.circle_1_y);
- assert (!_cairo_status_is_error (status));
-
- status = bind_float_to_shader (ctx, setup->shader->program,
- "mask_radius_0",
- setup->mask.operand.radial.radius_0);
- assert (!_cairo_status_is_error (status));
-
- status = bind_float_to_shader (ctx, setup->shader->program,
- "mask_radius_1",
- setup->mask.operand.radial.radius_1);
- assert (!_cairo_status_is_error (status));
-}
-
-/* This is like _cairo_gl_set_src_alpha_operand, for component alpha setup
- * of the mask part of IN to produce a "source alpha" value.
- */
-static void
-_cairo_gl_set_component_alpha_mask_operand (cairo_gl_context_t *ctx,
- cairo_gl_composite_t *setup)
-{
- cairo_surface_attributes_t *mask_attributes;
- GLfloat constant_color[4] = {0.0, 0.0, 0.0, 0.0};
-
- mask_attributes = &setup->mask.operand.texture.attributes;
-
- if (!setup->shader) {
- 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_SRC1_RGB, GL_PREVIOUS);
- glTexEnvi (GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_PREVIOUS);
- glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
- glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
- }
-
- switch (setup->mask.type) {
- case CAIRO_GL_OPERAND_CONSTANT:
- /* Have to have a dummy texture bound in order to use the combiner unit. */
- if (setup->shader) {
- cairo_status_t status;
- status = bind_vec4_to_shader (ctx, setup->shader->program,
- "mask_constant",
- setup->src.operand.constant.color[0],
- setup->src.operand.constant.color[1],
- setup->src.operand.constant.color[2],
- setup->src.operand.constant.color[3]);
- assert (! _cairo_status_is_error (status));
- } else {
- glBindTexture (ctx->tex_target, ctx->dummy_tex);
- glActiveTexture (GL_TEXTURE1);
- glEnable (ctx->tex_target);
-
- glTexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR,
- setup->mask.operand.constant.color);
-
- glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_RGB, GL_CONSTANT);
- glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_CONSTANT);
- glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
- glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
- }
- break;
- case CAIRO_GL_OPERAND_TEXTURE:
- _cairo_gl_set_texture_surface (1, setup->mask.operand.texture.tex,
- mask_attributes, ctx->tex_target);
- if (!setup->shader) {
- /* Set up the constant color we use to set color to 0 if needed. */
- glTexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, constant_color);
-
- /* Force the mask color to 0 if the surface should be
- * alpha-only. We may have a teximage with color bits if
- * the implementation doesn't support GL_ALPHA FBOs.
- */
- if (setup->mask.operand.texture.surface->base.content !=
- CAIRO_CONTENT_ALPHA)
- glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_RGB, GL_TEXTURE1);
- else
- glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_RGB, GL_CONSTANT);
- glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_TEXTURE1);
- glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
- glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
- }
- break;
-
- case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
- _cairo_gl_set_linear_gradient_mask_operand (ctx, setup);
- break;
-
- case CAIRO_GL_OPERAND_RADIAL_GRADIENT:
- _cairo_gl_set_radial_gradient_mask_operand (ctx, setup);
- break;
- case CAIRO_GL_OPERAND_NONE:
- case CAIRO_GL_OPERAND_SPANS:
- case CAIRO_GL_OPERAND_COUNT:
- default:
- ASSERT_NOT_REACHED;
- break;
- }
-}
-
-void
-_cairo_gl_composite_fini (cairo_gl_context_t *ctx,
- cairo_gl_composite_t *setup)
-{
- _cairo_gl_operand_destroy (&setup->src);
- _cairo_gl_operand_destroy (&setup->mask);
-}
-
-cairo_status_t
-_cairo_gl_composite_init (cairo_gl_context_t *ctx,
- cairo_gl_composite_t *setup,
- cairo_operator_t op,
- cairo_gl_surface_t *dst,
- const cairo_pattern_t *src,
- const cairo_pattern_t *mask,
- const cairo_rectangle_int_t *rect)
-{
- memset (setup, 0, sizeof (cairo_gl_composite_t));
-
- if (! _cairo_gl_operator_is_supported (op))
- return UNSUPPORTED ("unsupported operator");
-
- return CAIRO_STATUS_SUCCESS;
-}
-
/**
* implements component-alpha %CAIRO_OPERATOR_SOURCE using two passes of
* the simpler operations %CAIRO_OPERATOR_DEST_OUT and %CAIRO_OPERATOR_ADD.
@@ -2093,46 +1285,7 @@ _cairo_gl_surface_composite (cairo_operator_t op,
_cairo_gl_set_src_operand (ctx, &setup);
if (mask != NULL) {
- switch (setup.mask.type) {
- case CAIRO_GL_OPERAND_CONSTANT:
- _cairo_gl_set_tex_combine_constant_color (ctx, &setup, 1,
- setup.mask.operand.constant.color);
- break;
-
- case CAIRO_GL_OPERAND_TEXTURE:
- _cairo_gl_set_texture_surface (1, setup.mask.operand.texture.tex,
- mask_attributes, ctx->tex_target);
-
- if (!setup.shader) {
- 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);
-
- /* IN: dst.argb = src.argb * mask.aaaa */
- glTexEnvi (GL_TEXTURE_ENV, GL_SRC1_RGB, GL_TEXTURE1);
- glTexEnvi (GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_TEXTURE1);
- 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_LINEAR_GRADIENT:
- _cairo_gl_set_linear_gradient_mask_operand (ctx, &setup);
- break;
- case CAIRO_GL_OPERAND_RADIAL_GRADIENT:
- _cairo_gl_set_radial_gradient_mask_operand (ctx, &setup);
- break;
- case CAIRO_GL_OPERAND_NONE:
- case CAIRO_GL_OPERAND_SPANS:
- case CAIRO_GL_OPERAND_COUNT:
- default:
- ASSERT_NOT_REACHED;
- break;
- }
+ _cairo_gl_set_mask_operand (ctx, &setup);
}
if (clip_region != NULL) {
@@ -2838,7 +1991,7 @@ _cairo_gl_surface_create_span_renderer (cairo_operator_t op,
_cairo_gl_context_release (renderer->ctx);
free (renderer);
return _cairo_span_renderer_create_in_error (status);
-}
+ }
src_attributes = &renderer->setup.src.operand.texture.attributes;
commit 3ff32b00f0f85a853163c20b101ac5dd6a07da77
Author: Benjamin Otte <otte at redhat.com>
Date: Sat May 15 18:20:56 2010 +0200
gl: cairo_gl_compsite_setup_t => cairo_gl_composite_t
diff --git a/src/cairo-gl-glyphs.c b/src/cairo-gl-glyphs.c
index cba1dff..aee9235 100644
--- a/src/cairo-gl-glyphs.c
+++ b/src/cairo-gl-glyphs.c
@@ -257,7 +257,7 @@ typedef struct _cairo_gl_glyphs_setup
unsigned int vertex_size; /* units of floats */
unsigned int num_prims;
float *vb;
- cairo_gl_composite_setup_t *composite;
+ cairo_gl_composite_t *composite;
cairo_region_t *clip;
cairo_gl_surface_t *dst;
cairo_operator_t op;
@@ -472,7 +472,7 @@ _render_glyphs (cairo_gl_surface_t *dst,
cairo_gl_glyph_cache_t *cache = NULL;
cairo_gl_context_t *ctx;
cairo_gl_glyphs_setup_t setup;
- cairo_gl_composite_setup_t composite_setup;
+ cairo_gl_composite_t composite_setup;
cairo_status_t status;
int i = 0;
diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h
index bc7ace4..c5944e7 100644
--- a/src/cairo-gl-private.h
+++ b/src/cairo-gl-private.h
@@ -182,11 +182,11 @@ typedef struct cairo_gl_operand {
const cairo_pattern_t *pattern;
} cairo_gl_operand_t;
-typedef struct _cairo_gl_composite_setup {
+typedef struct _cairo_gl_composite {
cairo_gl_operand_t src;
cairo_gl_operand_t mask;
cairo_gl_shader_program_t *shader;
-} cairo_gl_composite_setup_t;
+} cairo_gl_composite_t;
cairo_private extern const cairo_surface_backend_t _cairo_gl_surface_backend;
@@ -272,25 +272,25 @@ _cairo_gl_set_operator (cairo_gl_surface_t *dst, cairo_operator_t op,
cairo_bool_t component_alpha);
cairo_private cairo_status_t
-_cairo_gl_composite_setup_init (cairo_gl_context_t *ctx,
- cairo_gl_composite_setup_t *setup,
- cairo_operator_t op,
- cairo_gl_surface_t *dst,
- const cairo_pattern_t *src,
- const cairo_pattern_t *mask,
- const cairo_rectangle_int_t *rect);
+_cairo_gl_composite_init (cairo_gl_context_t *ctx,
+ cairo_gl_composite_t *setup,
+ cairo_operator_t op,
+ cairo_gl_surface_t *dst,
+ const cairo_pattern_t *src,
+ const cairo_pattern_t *mask,
+ const cairo_rectangle_int_t *rect);
cairo_private void
-_cairo_gl_composite_setup_fini (cairo_gl_context_t *ctx,
- cairo_gl_composite_setup_t *setup);
+_cairo_gl_composite_fini (cairo_gl_context_t *ctx,
+ cairo_gl_composite_t *setup);
cairo_private void
_cairo_gl_set_src_operand (cairo_gl_context_t *ctx,
- cairo_gl_composite_setup_t *setup);
+ cairo_gl_composite_t *setup);
cairo_private void
_cairo_gl_set_src_alpha_operand (cairo_gl_context_t *ctx,
- cairo_gl_composite_setup_t *setup);
+ cairo_gl_composite_t *setup);
cairo_private void
_cairo_gl_operand_destroy (cairo_gl_operand_t *operand);
diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c
index dc70436..ac8e881 100644
--- a/src/cairo-gl-surface.c
+++ b/src/cairo-gl-surface.c
@@ -1378,7 +1378,7 @@ _cairo_gl_operand_destroy (cairo_gl_operand_t *operand)
static void
_cairo_gl_set_tex_combine_constant_color (cairo_gl_context_t *ctx,
- cairo_gl_composite_setup_t *setup,
+ cairo_gl_composite_t *setup,
int tex_unit,
GLfloat *color)
{
@@ -1436,7 +1436,7 @@ _cairo_gl_set_tex_combine_constant_color (cairo_gl_context_t *ctx,
void
_cairo_gl_set_src_operand (cairo_gl_context_t *ctx,
- cairo_gl_composite_setup_t *setup)
+ cairo_gl_composite_t *setup)
{
cairo_surface_attributes_t *src_attributes;
GLfloat constant_color[4] = {0.0, 0.0, 0.0, 0.0};
@@ -1533,7 +1533,7 @@ _cairo_gl_set_src_operand (cairo_gl_context_t *ctx,
*/
void
_cairo_gl_set_src_alpha_operand (cairo_gl_context_t *ctx,
- cairo_gl_composite_setup_t *setup)
+ cairo_gl_composite_t *setup)
{
GLfloat constant_color[4] = {0.0, 0.0, 0.0, 0.0};
cairo_surface_attributes_t *src_attributes;
@@ -1577,7 +1577,7 @@ _cairo_gl_set_src_alpha_operand (cairo_gl_context_t *ctx,
static void
_cairo_gl_set_linear_gradient_mask_operand (cairo_gl_context_t *ctx,
- cairo_gl_composite_setup_t *setup)
+ cairo_gl_composite_t *setup)
{
cairo_status_t status;
@@ -1600,7 +1600,7 @@ _cairo_gl_set_linear_gradient_mask_operand (cairo_gl_context_t *ctx,
static void
_cairo_gl_set_radial_gradient_mask_operand (cairo_gl_context_t *ctx,
- cairo_gl_composite_setup_t *setup)
+ cairo_gl_composite_t *setup)
{
cairo_status_t status;
@@ -1637,7 +1637,7 @@ _cairo_gl_set_radial_gradient_mask_operand (cairo_gl_context_t *ctx,
*/
static void
_cairo_gl_set_component_alpha_mask_operand (cairo_gl_context_t *ctx,
- cairo_gl_composite_setup_t *setup)
+ cairo_gl_composite_t *setup)
{
cairo_surface_attributes_t *mask_attributes;
GLfloat constant_color[4] = {0.0, 0.0, 0.0, 0.0};
@@ -1720,23 +1720,23 @@ _cairo_gl_set_component_alpha_mask_operand (cairo_gl_context_t *ctx,
}
void
-_cairo_gl_composite_setup_fini (cairo_gl_context_t *ctx,
- cairo_gl_composite_setup_t *setup)
+_cairo_gl_composite_fini (cairo_gl_context_t *ctx,
+ cairo_gl_composite_t *setup)
{
_cairo_gl_operand_destroy (&setup->src);
_cairo_gl_operand_destroy (&setup->mask);
}
cairo_status_t
-cairo_gl_composite_setup_init (cairo_gl_context_t *ctx,
- cairo_gl_composite_setup_t *setup,
- cairo_operator_t op,
- cairo_gl_surface_t *dst,
- const cairo_pattern_t *src,
- const cairo_pattern_t *mask,
- const cairo_rectangle_int_t *rect)
+_cairo_gl_composite_init (cairo_gl_context_t *ctx,
+ cairo_gl_composite_t *setup,
+ cairo_operator_t op,
+ cairo_gl_surface_t *dst,
+ const cairo_pattern_t *src,
+ const cairo_pattern_t *mask,
+ const cairo_rectangle_int_t *rect)
{
- memset (setup, 0, sizeof (cairo_gl_composite_setup_t));
+ memset (setup, 0, sizeof (cairo_gl_composite_t));
if (! _cairo_gl_operator_is_supported (op))
return UNSUPPORTED ("unsupported operator");
@@ -1820,7 +1820,7 @@ _cairo_gl_surface_composite_component_alpha (cairo_operator_t op,
struct gl_point *texcoord_mask = texcoord_mask_stack;
cairo_status_t status;
int num_vertices, i;
- cairo_gl_composite_setup_t setup;
+ cairo_gl_composite_t setup;
cairo_gl_shader_program_t *ca_source_program = NULL;
cairo_gl_shader_program_t *ca_source_alpha_program = NULL;
cairo_rectangle_int_t rect = { dst_x, dst_y, width, height };
@@ -1832,7 +1832,7 @@ _cairo_gl_surface_composite_component_alpha (cairo_operator_t op,
if (unlikely (status))
return status;
- status = _cairo_gl_composite_setup_init (ctx, &setup, op, dst, src, mask, &rect);
+ status = _cairo_gl_composite_init (ctx, &setup, op, dst, src, mask, &rect);
if (unlikely (status))
goto CLEANUP;
@@ -1991,7 +1991,7 @@ _cairo_gl_surface_composite_component_alpha (cairo_operator_t op,
glDisable (ctx->tex_target);
CLEANUP:
- _cairo_gl_composite_setup_fini (ctx, &setup);
+ _cairo_gl_composite_fini (ctx, &setup);
_cairo_gl_context_release (ctx);
if (vertices != vertices_stack)
@@ -2026,7 +2026,7 @@ _cairo_gl_surface_composite (cairo_operator_t op,
struct gl_point *texcoord_mask = texcoord_mask_stack;
cairo_status_t status;
int num_vertices, i;
- cairo_gl_composite_setup_t setup;
+ cairo_gl_composite_t setup;
cairo_rectangle_int_t rect = { dst_x, dst_y, width, height };
if (mask && mask->has_component_alpha) {
@@ -2050,7 +2050,7 @@ _cairo_gl_surface_composite (cairo_operator_t op,
if (unlikely (status))
return status;
- status = _cairo_gl_composite_setup_init (ctx, &setup, op, dst, src, mask, &rect);
+ status = _cairo_gl_composite_init (ctx, &setup, op, dst, src, mask, &rect);
if (unlikely (status))
goto CLEANUP;
@@ -2239,7 +2239,7 @@ _cairo_gl_surface_composite (cairo_operator_t op,
free (vertices);
CLEANUP:
- _cairo_gl_composite_setup_fini (ctx, &setup);
+ _cairo_gl_composite_fini (ctx, &setup);
_cairo_gl_context_release (ctx);
return status;
@@ -2506,7 +2506,7 @@ _cairo_gl_surface_fill_rectangles (void *abstract_surface,
typedef struct _cairo_gl_surface_span_renderer {
cairo_span_renderer_t base;
- cairo_gl_composite_setup_t setup;
+ cairo_gl_composite_t setup;
int xmin, xmax;
commit c16edee26fb9f1669ee0ce1a61f0c54d802c6c7b
Author: Benjamin Otte <otte at redhat.com>
Date: Sat May 15 17:33:24 2010 +0200
gl: use glBlendFuncSeparate()
This way we can treat alpha-only textures correctly and don't have to
emit different shaders for it. Also gets rid of
GL_OPERAND_TEXTURE_ALPHA.
diff --git a/src/cairo-gl-glyphs.c b/src/cairo-gl-glyphs.c
index 4f4e865..cba1dff 100644
--- a/src/cairo-gl-glyphs.c
+++ b/src/cairo-gl-glyphs.c
@@ -416,8 +416,7 @@ _cairo_gl_glyphs_emit_vertex (cairo_gl_glyphs_setup_t *setup,
vb[i++] = glyph_x;
vb[i++] = glyph_y;
- if (setup->composite->src.type == CAIRO_GL_OPERAND_TEXTURE ||
- setup->composite->src.type == CAIRO_GL_OPERAND_TEXTURE_ALPHA) {
+ if (setup->composite->src.type == CAIRO_GL_OPERAND_TEXTURE) {
double s = x;
double t = y;
cairo_matrix_transform_point (&src_attributes->matrix, &s, &t);
@@ -517,8 +516,7 @@ _render_glyphs (cairo_gl_surface_t *dst,
setup.clip = clip_region;
setup.dst = dst;
setup.vertex_size = 4;
- if (composite_setup.src.type == CAIRO_GL_OPERAND_TEXTURE ||
- composite_setup.src.type == CAIRO_GL_OPERAND_TEXTURE_ALPHA)
+ if (composite_setup.src.type == CAIRO_GL_OPERAND_TEXTURE)
setup.vertex_size += 2;
setup.vbo_size = num_glyphs * 4 * setup.vertex_size;
if (setup.vbo_size > 4096)
@@ -531,8 +529,7 @@ _render_glyphs (cairo_gl_surface_t *dst,
glVertexPointer (2, GL_FLOAT, setup.vertex_size * sizeof (GLfloat),
(void *)(uintptr_t)(0));
glEnableClientState (GL_VERTEX_ARRAY);
- if (composite_setup.src.type == CAIRO_GL_OPERAND_TEXTURE ||
- composite_setup.src.type == CAIRO_GL_OPERAND_TEXTURE_ALPHA) {
+ if (composite_setup.src.type == CAIRO_GL_OPERAND_TEXTURE) {
/* Note that we're packing texcoord 0 after texcoord 1, for
* convenience.
*/
diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h
index fa8b87b..bc7ace4 100644
--- a/src/cairo-gl-private.h
+++ b/src/cairo-gl-private.h
@@ -88,7 +88,6 @@ typedef enum cairo_gl_operand_type {
CAIRO_GL_OPERAND_NONE,
CAIRO_GL_OPERAND_CONSTANT,
CAIRO_GL_OPERAND_TEXTURE,
- CAIRO_GL_OPERAND_TEXTURE_ALPHA,
CAIRO_GL_OPERAND_LINEAR_GRADIENT,
CAIRO_GL_OPERAND_RADIAL_GRADIENT,
CAIRO_GL_OPERAND_SPANS,
diff --git a/src/cairo-gl-shaders.c b/src/cairo-gl-shaders.c
index f1f0bec..7511b4e 100644
--- a/src/cairo-gl-shaders.c
+++ b/src/cairo-gl-shaders.c
@@ -540,7 +540,6 @@ cairo_gl_operand_get_var_type (cairo_gl_operand_type_t type)
case CAIRO_GL_OPERAND_RADIAL_GRADIENT:
return CAIRO_GL_VAR_NONE;
case CAIRO_GL_OPERAND_TEXTURE:
- case CAIRO_GL_OPERAND_TEXTURE_ALPHA:
return CAIRO_GL_VAR_TEXCOORDS;
case CAIRO_GL_OPERAND_SPANS:
return CAIRO_GL_VAR_COVERAGE;
@@ -665,16 +664,6 @@ cairo_gl_shader_emit_color (cairo_output_stream_t *stream,
"}\n",
rectstr, namestr, namestr, namestr, rectstr, namestr, namestr);
break;
- case CAIRO_GL_OPERAND_TEXTURE_ALPHA:
- _cairo_output_stream_printf (stream,
- "uniform sampler2D%s %s_sampler;\n"
- "varying vec2 %s_texcoords;\n"
- "vec4 get_%s()\n"
- "{\n"
- " return vec4 (0, 0, 0, texture2D%s(%s_sampler, %s_texcoords).a);\n"
- "}\n",
- rectstr, namestr, namestr, namestr, rectstr, namestr, namestr);
- break;
case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
_cairo_output_stream_printf (stream,
"uniform sampler1D %s_sampler;\n"
@@ -895,32 +884,6 @@ _cairo_gl_use_program (cairo_gl_context_t *ctx,
ctx->shader_impl->use_program (program);
}
-#if 0
-/**
- * This function reduces the GLSL program combinations we compile when
- * there are non-functional differences.
- */
-static cairo_gl_shader_program_t *
-_cairo_gl_select_program (cairo_gl_context_t *ctx,
- cairo_gl_operand_type_t source,
- cairo_gl_operand_type_t mask,
- cairo_gl_shader_in_t in)
-{
- if (in == CAIRO_GL_SHADER_IN_NORMAL &&
- mask == CAIRO_GL_OPERAND_TEXTURE_ALPHA)
- {
- mask = CAIRO_GL_OPERAND_TEXTURE;
- }
- if (in == CAIRO_GL_SHADER_IN_CA_SOURCE_ALPHA &&
- source == CAIRO_GL_OPERAND_TEXTURE_ALPHA)
- {
- source = CAIRO_GL_OPERAND_TEXTURE;
- }
-
- return &ctx->shaders[source][mask][in];
-}
-#endif
-
cairo_status_t
_cairo_gl_get_program (cairo_gl_context_t *ctx,
cairo_gl_operand_type_t source,
diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c
index fad0050..dc70436 100644
--- a/src/cairo-gl-surface.c
+++ b/src/cairo-gl-surface.c
@@ -244,7 +244,11 @@ _cairo_gl_set_operator (cairo_gl_surface_t *dst, cairo_operator_t op,
}
glEnable (GL_BLEND);
- glBlendFunc (src_factor, dst_factor);
+ if (dst->base.content == CAIRO_CONTENT_ALPHA) {
+ glBlendFuncSeparate (GL_ZERO, GL_ZERO, src_factor, dst_factor);
+ } else {
+ glBlendFunc (src_factor, dst_factor);
+ }
}
static void
@@ -1176,10 +1180,7 @@ _cairo_gl_pattern_texture_setup (cairo_gl_context_t *ctx,
assert (surface->base.backend == &_cairo_gl_surface_backend);
- if (surface->base.content == CAIRO_CONTENT_ALPHA)
- operand->type = CAIRO_GL_OPERAND_TEXTURE_ALPHA;
- else
- operand->type = CAIRO_GL_OPERAND_TEXTURE;
+ operand->type = CAIRO_GL_OPERAND_TEXTURE;
operand->operand.texture.surface = surface;
operand->operand.texture.tex = surface->tex;
/* Translate the matrix from
@@ -1358,7 +1359,6 @@ _cairo_gl_operand_destroy (cairo_gl_operand_t *operand)
glDeleteTextures (1, &operand->operand.radial.tex);
break;
case CAIRO_GL_OPERAND_TEXTURE:
- case CAIRO_GL_OPERAND_TEXTURE_ALPHA:
if (operand->operand.texture.surface != NULL) {
cairo_gl_surface_t *surface = operand->operand.texture.surface;
@@ -1450,7 +1450,6 @@ _cairo_gl_set_src_operand (cairo_gl_context_t *ctx,
setup->src.operand.constant.color);
break;
case CAIRO_GL_OPERAND_TEXTURE:
- case CAIRO_GL_OPERAND_TEXTURE_ALPHA:
_cairo_gl_set_texture_surface (0, setup->src.operand.texture.tex,
src_attributes, ctx->tex_target);
if (!setup->shader) {
@@ -1551,7 +1550,6 @@ _cairo_gl_set_src_alpha_operand (cairo_gl_context_t *ctx,
constant_color);
break;
case CAIRO_GL_OPERAND_TEXTURE:
- case CAIRO_GL_OPERAND_TEXTURE_ALPHA:
_cairo_gl_set_texture_surface (0, setup->src.operand.texture.tex,
src_attributes, ctx->tex_target);
if (!setup->shader) {
@@ -1684,7 +1682,6 @@ _cairo_gl_set_component_alpha_mask_operand (cairo_gl_context_t *ctx,
}
break;
case CAIRO_GL_OPERAND_TEXTURE:
- case CAIRO_GL_OPERAND_TEXTURE_ALPHA:
_cairo_gl_set_texture_surface (1, setup->mask.operand.texture.tex,
mask_attributes, ctx->tex_target);
if (!setup->shader) {
@@ -1928,8 +1925,7 @@ _cairo_gl_surface_composite_component_alpha (cairo_operator_t op,
glVertexPointer (2, GL_FLOAT, sizeof (GLfloat) * 2, vertices);
glEnableClientState (GL_VERTEX_ARRAY);
- if (setup.src.type == CAIRO_GL_OPERAND_TEXTURE ||
- setup.src.type == CAIRO_GL_OPERAND_TEXTURE_ALPHA) {
+ if (setup.src.type == CAIRO_GL_OPERAND_TEXTURE) {
for (i = 0; i < num_vertices; i++) {
double s, t;
@@ -1945,8 +1941,7 @@ _cairo_gl_surface_composite_component_alpha (cairo_operator_t op,
glEnableClientState (GL_TEXTURE_COORD_ARRAY);
}
- if (setup.mask.type == CAIRO_GL_OPERAND_TEXTURE ||
- setup.mask.type == CAIRO_GL_OPERAND_TEXTURE_ALPHA) {
+ if (setup.mask.type == CAIRO_GL_OPERAND_TEXTURE) {
for (i = 0; i < num_vertices; i++) {
double s, t;
@@ -2105,7 +2100,6 @@ _cairo_gl_surface_composite (cairo_operator_t op,
break;
case CAIRO_GL_OPERAND_TEXTURE:
- case CAIRO_GL_OPERAND_TEXTURE_ALPHA:
_cairo_gl_set_texture_surface (1, setup.mask.operand.texture.tex,
mask_attributes, ctx->tex_target);
@@ -2188,8 +2182,7 @@ _cairo_gl_surface_composite (cairo_operator_t op,
glVertexPointer (2, GL_FLOAT, sizeof (GLfloat) * 2, vertices);
glEnableClientState (GL_VERTEX_ARRAY);
- if (setup.src.type == CAIRO_GL_OPERAND_TEXTURE ||
- setup.src.type == CAIRO_GL_OPERAND_TEXTURE_ALPHA) {
+ if (setup.src.type == CAIRO_GL_OPERAND_TEXTURE) {
for (i = 0; i < num_vertices; i++) {
double s, t;
@@ -2206,8 +2199,7 @@ _cairo_gl_surface_composite (cairo_operator_t op,
}
if (mask != NULL) {
- if (setup.mask.type == CAIRO_GL_OPERAND_TEXTURE ||
- setup.mask.type == CAIRO_GL_OPERAND_TEXTURE_ALPHA) {
+ if (setup.mask.type == CAIRO_GL_OPERAND_TEXTURE) {
for (i = 0; i < num_vertices; i++) {
double s, t;
@@ -2572,8 +2564,7 @@ _cairo_gl_span_renderer_get_vbo (cairo_gl_surface_span_renderer_t *renderer,
renderer->vbo_size = 16384;
glBindBufferARB (GL_ARRAY_BUFFER_ARB, renderer->ctx->vbo);
- if (renderer->setup.src.type == CAIRO_GL_OPERAND_TEXTURE ||
- renderer->setup.src.type == CAIRO_GL_OPERAND_TEXTURE_ALPHA)
+ 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);
@@ -2585,8 +2576,7 @@ _cairo_gl_span_renderer_get_vbo (cairo_gl_surface_span_renderer_t *renderer,
(void *) (uintptr_t) (2 * sizeof (float)));
glEnableClientState (GL_COLOR_ARRAY);
- if (renderer->setup.src.type == CAIRO_GL_OPERAND_TEXTURE ||
- renderer->setup.src.type == CAIRO_GL_OPERAND_TEXTURE_ALPHA) {
+ 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) +
@@ -2627,8 +2617,7 @@ _cairo_gl_emit_span_vertex (cairo_gl_surface_span_renderer_t *renderer,
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 ||
- renderer->setup.src.type == CAIRO_GL_OPERAND_TEXTURE_ALPHA) {
+ if (renderer->setup.src.type == CAIRO_GL_OPERAND_TEXTURE) {
double s, t;
s = dst_x + BIAS;
commit 4f5221a834a883262cce607d247f607d6c200363
Author: Benjamin Otte <otte at redhat.com>
Date: Wed May 12 21:12:37 2010 +0200
gl: acquire device manually in finish, as the default way will error
We'll get CAIRO_STATUS_DEVICE_FINISHED, d'oh
diff --git a/src/cairo-gl-device.c b/src/cairo-gl-device.c
index 7d873dc..2bfeb51 100644
--- a/src/cairo-gl-device.c
+++ b/src/cairo-gl-device.c
@@ -60,18 +60,18 @@ _gl_unlock (void *device)
static void
_gl_finish (void *device)
{
- cairo_gl_context_t *ctx;
+ cairo_gl_context_t *ctx = device;
int i;
- if (_cairo_gl_context_acquire (device, &ctx) == CAIRO_STATUS_SUCCESS) {
- for (i = 0; i <= CAIRO_GL_VAR_TYPE_MAX; i++) {
- destroy_shader (ctx, ctx->vertex_shaders[i]);
- }
-
- _cairo_cache_fini (&ctx->shaders);
+ _gl_lock (device);
- _cairo_gl_context_release (ctx);
+ for (i = 0; i <= CAIRO_GL_VAR_TYPE_MAX; i++) {
+ destroy_shader (ctx, ctx->vertex_shaders[i]);
}
+
+ _cairo_cache_fini (&ctx->shaders);
+
+ _gl_unlock (device);
}
static void
commit 3f6300444928d12bf4a6e2f6f2c5fec1de7dba8e
Author: Benjamin Otte <otte at redhat.com>
Date: Wed May 12 20:53:20 2010 +0200
gl: Put shaders into a cache
This allows to grow the complexity of the shaders without enlarging the
static array to unreasonable sizes.
The cache size of 64 is essentially random.
diff --git a/src/cairo-gl-device.c b/src/cairo-gl-device.c
index ed9b91e..7d873dc 100644
--- a/src/cairo-gl-device.c
+++ b/src/cairo-gl-device.c
@@ -68,6 +68,8 @@ _gl_finish (void *device)
destroy_shader (ctx, ctx->vertex_shaders[i]);
}
+ _cairo_cache_fini (&ctx->shaders);
+
_cairo_gl_context_release (ctx);
}
}
diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h
index 347735c..fa8b87b 100644
--- a/src/cairo-gl-private.h
+++ b/src/cairo-gl-private.h
@@ -65,6 +65,10 @@
#define UNSUPPORTED(reason) CAIRO_INT_STATUS_UNSUPPORTED
#endif
+/* maximal number of shaders we keep in the cache.
+ * Random number that is hopefully big enough to not cause many cache evictions. */
+#define CAIRO_GL_MAX_SHADERS_PER_CONTEXT 64
+
typedef struct _cairo_gl_surface {
cairo_surface_t base;
@@ -132,9 +136,7 @@ typedef struct _cairo_gl_context {
GLuint vertex_shaders[CAIRO_GL_VAR_TYPE_MAX + 1];
cairo_gl_shader_program_t fill_rectangles_shader;
- cairo_gl_shader_program_t shaders[CAIRO_GL_OPERAND_COUNT]
- [CAIRO_GL_OPERAND_COUNT]
- [CAIRO_GL_SHADER_IN_COUNT];
+ cairo_cache_t shaders;
cairo_gl_surface_t *current_target;
cairo_gl_glyph_cache_t glyph_cache[2];
diff --git a/src/cairo-gl-shaders.c b/src/cairo-gl-shaders.c
index 1a4c9a0..f1f0bec 100644
--- a/src/cairo-gl-shaders.c
+++ b/src/cairo-gl-shaders.c
@@ -430,9 +430,50 @@ static const cairo_gl_shader_impl_t shader_impl_arb = {
use_program_arb,
};
+typedef struct _cairo_shader_cache_entry {
+ cairo_cache_entry_t base;
+
+ cairo_gl_operand_type_t src;
+ cairo_gl_operand_type_t mask;
+ cairo_gl_operand_type_t dest;
+ cairo_gl_shader_in_t in;
+
+ cairo_gl_context_t *ctx; /* XXX: needed to destroy the program */
+ cairo_gl_shader_program_t program;
+} cairo_shader_cache_entry_t;
+
+static cairo_bool_t
+_cairo_gl_shader_cache_equal (const void *key_a, const void *key_b)
+{
+ const cairo_shader_cache_entry_t *a = key_a;
+ const cairo_shader_cache_entry_t *b = key_b;
+
+ return a->src == b->src &&
+ a->mask == b->mask &&
+ a->dest == b->dest &&
+ a->in == b->in;
+}
+
+static unsigned long
+_cairo_gl_shader_cache_hash (const cairo_shader_cache_entry_t *entry)
+{
+ return (entry->src << 24) | (entry->mask << 16) | (entry->dest << 8) | (entry->in);
+}
+
+static void
+_cairo_gl_shader_cache_destroy (void *data)
+{
+ cairo_shader_cache_entry_t *entry = data;
+
+ destroy_shader_program (entry->ctx, &entry->program);
+ free (entry);
+}
+
void
_cairo_gl_context_init_shaders (cairo_gl_context_t *ctx)
{
+ cairo_status_t status;
+
/* XXX multiple device support? */
if (GLEW_VERSION_2_0) {
ctx->shader_impl = &shader_impl_core_2_0;
@@ -445,6 +486,12 @@ _cairo_gl_context_init_shaders (cairo_gl_context_t *ctx)
}
memset (ctx->vertex_shaders, 0, sizeof (ctx->vertex_shaders));
+
+ status = _cairo_cache_init (&ctx->shaders,
+ _cairo_gl_shader_cache_equal,
+ NULL,
+ _cairo_gl_shader_cache_destroy,
+ CAIRO_GL_MAX_SHADERS_PER_CONTEXT);
}
void
@@ -848,6 +895,7 @@ _cairo_gl_use_program (cairo_gl_context_t *ctx,
ctx->shader_impl->use_program (program);
}
+#if 0
/**
* This function reduces the GLSL program combinations we compile when
* there are non-functional differences.
@@ -871,6 +919,7 @@ _cairo_gl_select_program (cairo_gl_context_t *ctx,
return &ctx->shaders[source][mask][in];
}
+#endif
cairo_status_t
_cairo_gl_get_program (cairo_gl_context_t *ctx,
@@ -879,22 +928,30 @@ _cairo_gl_get_program (cairo_gl_context_t *ctx,
cairo_gl_shader_in_t in,
cairo_gl_shader_program_t **out_program)
{
- cairo_gl_shader_program_t *program;
+ cairo_shader_cache_entry_t lookup, *entry;
char *fs_source;
cairo_status_t status;
- program = _cairo_gl_select_program(ctx, source, mask, in);
- if (program->program) {
- *out_program = program;
- return CAIRO_STATUS_SUCCESS;
- }
-
- if (program->build_failure)
- return CAIRO_INT_STATUS_UNSUPPORTED;
-
if (ctx->shader_impl == NULL)
return CAIRO_INT_STATUS_UNSUPPORTED;
+ lookup.src = source;
+ lookup.mask = mask;
+ lookup.dest = CAIRO_GL_OPERAND_NONE;
+ lookup.in = in;
+ lookup.base.hash = _cairo_gl_shader_cache_hash (&lookup);
+ lookup.base.size = 1;
+
+ entry = _cairo_cache_lookup (&ctx->shaders, &lookup.base);
+ if (entry) {
+ if (entry->program.build_failure)
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+
+ assert (entry->program.program);
+ *out_program = &entry->program;
+ return CAIRO_STATUS_SUCCESS;
+ }
+
fs_source = cairo_gl_shader_get_fragment_source (ctx->tex_target,
in,
source,
@@ -903,31 +960,49 @@ _cairo_gl_get_program (cairo_gl_context_t *ctx,
if (unlikely (fs_source == NULL))
return CAIRO_STATUS_NO_MEMORY;
- init_shader_program (program);
+ entry = malloc (sizeof (cairo_shader_cache_entry_t));
+ if (unlikely (entry == NULL)) {
+ free (fs_source);
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ }
+
+ memcpy (entry, &lookup, sizeof (cairo_shader_cache_entry_t));
+
+ entry->ctx = ctx;
+ init_shader_program (&entry->program);
status = create_shader_program (ctx,
- program,
+ &entry->program,
cairo_gl_operand_get_var_type (source),
cairo_gl_operand_get_var_type (mask),
fs_source);
free (fs_source);
- if (_cairo_status_is_error (status))
+ if (unlikely (status)) {
+ /* still add to cache, so we know we got a build failure */
+ if (_cairo_status_is_error (status) ||
+ _cairo_cache_insert (&ctx->shaders, &entry->base)) {
+ free (entry);
+ }
+
return status;
+ }
- _cairo_gl_use_program (ctx, program);
+ _cairo_gl_use_program (ctx, &entry->program);
if (source != CAIRO_GL_OPERAND_CONSTANT) {
- status = bind_texture_to_shader (ctx, program->program, "source_sampler", 0);
+ status = bind_texture_to_shader (ctx, entry->program.program, "source_sampler", 0);
assert (!_cairo_status_is_error (status));
}
if (mask != CAIRO_GL_OPERAND_CONSTANT &&
mask != CAIRO_GL_OPERAND_SPANS &&
mask != CAIRO_GL_OPERAND_NONE) {
- status = bind_texture_to_shader (ctx, program->program, "mask_sampler", 1);
+ status = bind_texture_to_shader (ctx, entry->program.program, "mask_sampler", 1);
assert (!_cairo_status_is_error (status));
}
+ status = _cairo_cache_insert (&ctx->shaders, &entry->base);
+
_cairo_gl_use_program (ctx, NULL);
- *out_program = program;
- return CAIRO_STATUS_SUCCESS;
+ *out_program = &entry->program;
+ return status;
}
commit 08b04caf52518f1672694341355b5f5418008e78
Author: Benjamin Otte <otte at redhat.com>
Date: Wed May 12 18:10:04 2010 +0200
gl: Add cairo_gl_composite_setup_init/fini() functions
Simplifies the main code paths, and can be extended to do dest copies.
diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h
index 6ea8fb2..347735c 100644
--- a/src/cairo-gl-private.h
+++ b/src/cairo-gl-private.h
@@ -270,6 +270,19 @@ cairo_private void
_cairo_gl_set_operator (cairo_gl_surface_t *dst, cairo_operator_t op,
cairo_bool_t component_alpha);
+cairo_private cairo_status_t
+_cairo_gl_composite_setup_init (cairo_gl_context_t *ctx,
+ cairo_gl_composite_setup_t *setup,
+ cairo_operator_t op,
+ cairo_gl_surface_t *dst,
+ const cairo_pattern_t *src,
+ const cairo_pattern_t *mask,
+ const cairo_rectangle_int_t *rect);
+
+cairo_private void
+_cairo_gl_composite_setup_fini (cairo_gl_context_t *ctx,
+ cairo_gl_composite_setup_t *setup);
+
cairo_private void
_cairo_gl_set_src_operand (cairo_gl_context_t *ctx,
cairo_gl_composite_setup_t *setup);
diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c
index 69fcc8c..fad0050 100644
--- a/src/cairo-gl-surface.c
+++ b/src/cairo-gl-surface.c
@@ -1722,6 +1722,31 @@ _cairo_gl_set_component_alpha_mask_operand (cairo_gl_context_t *ctx,
}
}
+void
+_cairo_gl_composite_setup_fini (cairo_gl_context_t *ctx,
+ cairo_gl_composite_setup_t *setup)
+{
+ _cairo_gl_operand_destroy (&setup->src);
+ _cairo_gl_operand_destroy (&setup->mask);
+}
+
+cairo_status_t
+cairo_gl_composite_setup_init (cairo_gl_context_t *ctx,
+ cairo_gl_composite_setup_t *setup,
+ cairo_operator_t op,
+ cairo_gl_surface_t *dst,
+ const cairo_pattern_t *src,
+ const cairo_pattern_t *mask,
+ const cairo_rectangle_int_t *rect)
+{
+ memset (setup, 0, sizeof (cairo_gl_composite_setup_t));
+
+ if (! _cairo_gl_operator_is_supported (op))
+ return UNSUPPORTED ("unsupported operator");
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
/**
* implements component-alpha %CAIRO_OPERATOR_SOURCE using two passes of
* the simpler operations %CAIRO_OPERATOR_DEST_OUT and %CAIRO_OPERATOR_ADD.
@@ -1801,35 +1826,35 @@ _cairo_gl_surface_composite_component_alpha (cairo_operator_t op,
cairo_gl_composite_setup_t setup;
cairo_gl_shader_program_t *ca_source_program = NULL;
cairo_gl_shader_program_t *ca_source_alpha_program = NULL;
+ cairo_rectangle_int_t rect = { dst_x, dst_y, width, height };
if (op != CAIRO_OPERATOR_OVER && op != CAIRO_OPERATOR_ADD)
return UNSUPPORTED ("unsupported component alpha operator");
- memset (&setup, 0, sizeof (setup));
-
status = _cairo_gl_context_acquire (dst->base.device, &ctx);
if (unlikely (status))
return status;
+ status = _cairo_gl_composite_setup_init (ctx, &setup, op, dst, src, mask, &rect);
+ if (unlikely (status))
+ goto CLEANUP;
+
status = _cairo_gl_operand_init (ctx, &setup.src, src, dst,
src_x, src_y,
dst_x, dst_y,
width, height);
- if (unlikely (status)) {
- _cairo_gl_context_release (ctx);
- return status;
- }
+ if (unlikely (status))
+ goto CLEANUP;
+
src_attributes = &setup.src.operand.texture.attributes;
status = _cairo_gl_operand_init (ctx, &setup.mask, mask, dst,
mask_x, mask_y,
dst_x, dst_y,
width, height);
- if (unlikely (status)) {
- _cairo_gl_context_release (ctx);
- _cairo_gl_operand_destroy (&setup.src);
- return status;
- }
+ if (unlikely (status))
+ goto CLEANUP;
+
mask_attributes = &setup.mask.operand.texture.attributes;
/* We'll fall back to fixed function instead. */
@@ -1971,10 +1996,7 @@ _cairo_gl_surface_composite_component_alpha (cairo_operator_t op,
glDisable (ctx->tex_target);
CLEANUP:
- _cairo_gl_operand_destroy (&setup.src);
- if (mask != NULL)
- _cairo_gl_operand_destroy (&setup.mask);
-
+ _cairo_gl_composite_setup_fini (ctx, &setup);
_cairo_gl_context_release (ctx);
if (vertices != vertices_stack)
@@ -2010,6 +2032,7 @@ _cairo_gl_surface_composite (cairo_operator_t op,
cairo_status_t status;
int num_vertices, i;
cairo_gl_composite_setup_t setup;
+ cairo_rectangle_int_t rect = { dst_x, dst_y, width, height };
if (mask && mask->has_component_alpha) {
/* Try two-pass component alpha support, or bail. */
@@ -2028,23 +2051,21 @@ _cairo_gl_surface_composite (cairo_operator_t op,
clip_region);
}
- if (! _cairo_gl_operator_is_supported (op))
- return UNSUPPORTED ("unsupported operator");
-
- memset (&setup, 0, sizeof (setup));
-
status = _cairo_gl_context_acquire (dst->base.device, &ctx);
if (unlikely (status))
return status;
+ status = _cairo_gl_composite_setup_init (ctx, &setup, op, dst, src, mask, &rect);
+ if (unlikely (status))
+ goto CLEANUP;
+
status = _cairo_gl_operand_init (ctx, &setup.src, src, dst,
src_x, src_y,
dst_x, dst_y,
width, height);
- if (unlikely (status)) {
- _cairo_gl_context_release (ctx);
- return status;
- }
+ if (unlikely (status))
+ goto CLEANUP;
+
src_attributes = &setup.src.operand.texture.attributes;
if (mask != NULL) {
@@ -2052,14 +2073,10 @@ _cairo_gl_surface_composite (cairo_operator_t op,
mask_x, mask_y,
dst_x, dst_y,
width, height);
- if (unlikely (status)) {
- _cairo_gl_operand_destroy (&setup.src);
- _cairo_gl_context_release (ctx);
- return status;
- }
+ if (unlikely (status))
+ goto CLEANUP;
+
mask_attributes = &setup.mask.operand.texture.attributes;
- } else {
- setup.mask.type = CAIRO_GL_OPERAND_NONE;
}
/* We'll fall back to fixed function instead. */
@@ -2070,7 +2087,7 @@ _cairo_gl_surface_composite (cairo_operator_t op,
CAIRO_GL_SHADER_IN_NORMAL,
&setup.shader);
if (_cairo_status_is_error (status))
- goto CLEANUP_SHADER;
+ goto CLEANUP;
status = CAIRO_STATUS_SUCCESS;
@@ -2133,7 +2150,7 @@ _cairo_gl_surface_composite (cairo_operator_t op,
4*3*sizeof (vertices[0]));
if (unlikely (vertices == NULL)) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
- goto CLEANUP_SHADER;
+ goto CLEANUP;
}
texcoord_src = vertices + num_rectangles * 4;
@@ -2229,14 +2246,10 @@ _cairo_gl_surface_composite (cairo_operator_t op,
if (vertices != vertices_stack)
free (vertices);
- CLEANUP_SHADER:
- _cairo_gl_operand_destroy (&setup.src);
- if (mask != NULL)
- _cairo_gl_operand_destroy (&setup.mask);
-
+ CLEANUP:
+ _cairo_gl_composite_setup_fini (ctx, &setup);
_cairo_gl_context_release (ctx);
- assert (status != CAIRO_INT_STATUS_UNSUPPORTED);
return status;
}
commit aa14df0db5e4f236a9668ceda4e148e7d3ba0e9f
Author: Benjamin Otte <otte at redhat.com>
Date: Wed May 12 17:01:47 2010 +0200
gl: move operator check
component alpha compositing checks the operator itself
diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c
index 889e41d..69fcc8c 100644
--- a/src/cairo-gl-surface.c
+++ b/src/cairo-gl-surface.c
@@ -2011,9 +2011,6 @@ _cairo_gl_surface_composite (cairo_operator_t op,
int num_vertices, i;
cairo_gl_composite_setup_t setup;
- if (! _cairo_gl_operator_is_supported (op))
- return UNSUPPORTED ("unsupported operator");
-
if (mask && mask->has_component_alpha) {
/* Try two-pass component alpha support, or bail. */
return _cairo_gl_surface_composite_component_alpha(op,
@@ -2031,6 +2028,9 @@ _cairo_gl_surface_composite (cairo_operator_t op,
clip_region);
}
+ if (! _cairo_gl_operator_is_supported (op))
+ return UNSUPPORTED ("unsupported operator");
+
memset (&setup, 0, sizeof (setup));
status = _cairo_gl_context_acquire (dst->base.device, &ctx);
commit a3ee0a7f113ed38df66580ff7e38a79759b0c933
Author: Benjamin Otte <otte at redhat.com>
Date: Wed May 12 16:57:32 2010 +0200
gl: Programmatically generate fragment shaders
diff --git a/src/cairo-gl-shaders.c b/src/cairo-gl-shaders.c
index 240054d..1a4c9a0 100644
--- a/src/cairo-gl-shaders.c
+++ b/src/cairo-gl-shaders.c
@@ -551,30 +551,187 @@ cairo_gl_shader_get_vertex_source (cairo_gl_var_type_t src,
cairo_gl_var_type_t mask,
cairo_gl_var_type_t dest)
{
- cairo_output_stream_t *stream = _cairo_memory_stream_create ();
- unsigned char *source;
- unsigned int length;
+ cairo_output_stream_t *stream = _cairo_memory_stream_create ();
+ unsigned char *source;
+ unsigned int length;
- cairo_gl_shader_emit_variable (stream, src, CAIRO_GL_OPERAND_SOURCE);
- cairo_gl_shader_emit_variable (stream, mask, CAIRO_GL_OPERAND_MASK);
- cairo_gl_shader_emit_variable (stream, dest, CAIRO_GL_OPERAND_DEST);
-
- _cairo_output_stream_printf (stream,
- "void main()\n"
- "{\n"
- " gl_Position = ftransform();\n");
+ cairo_gl_shader_emit_variable (stream, src, CAIRO_GL_OPERAND_SOURCE);
+ cairo_gl_shader_emit_variable (stream, mask, CAIRO_GL_OPERAND_MASK);
+ cairo_gl_shader_emit_variable (stream, dest, CAIRO_GL_OPERAND_DEST);
+
+ _cairo_output_stream_printf (stream,
+ "void main()\n"
+ "{\n"
+ " gl_Position = ftransform();\n");
- cairo_gl_shader_emit_vertex (stream, src, CAIRO_GL_OPERAND_SOURCE);
- cairo_gl_shader_emit_vertex (stream, mask, CAIRO_GL_OPERAND_MASK);
- cairo_gl_shader_emit_vertex (stream, dest, CAIRO_GL_OPERAND_DEST);
-
- _cairo_output_stream_write (stream,
- "}\n\0", 3);
+ cairo_gl_shader_emit_vertex (stream, src, CAIRO_GL_OPERAND_SOURCE);
+ cairo_gl_shader_emit_vertex (stream, mask, CAIRO_GL_OPERAND_MASK);
+ cairo_gl_shader_emit_vertex (stream, dest, CAIRO_GL_OPERAND_DEST);
+
+ _cairo_output_stream_write (stream,
+ "}\n\0", 3);
- if (_cairo_memory_stream_destroy (stream, &source, &length))
- return NULL;
+ if (_cairo_memory_stream_destroy (stream, &source, &length))
+ return NULL;
- return (char *) source;
+ return (char *) source;
+}
+
+static void
+cairo_gl_shader_emit_color (cairo_output_stream_t *stream,
+ GLuint tex_target,
+ cairo_gl_operand_type_t type,
+ cairo_gl_operand_name_t name)
+{
+ const char *namestr = operand_names[name];
+ const char *rectstr = (tex_target == GL_TEXTURE_RECTANGLE_EXT ? "Rect" : "");
+
+ switch (type) {
+ case CAIRO_GL_OPERAND_COUNT:
+ default:
+ ASSERT_NOT_REACHED;
+ break;
+ case CAIRO_GL_OPERAND_NONE:
+ _cairo_output_stream_printf (stream,
+ "vec4 get_%s()\n"
+ "{\n"
+ " return vec4 (0, 0, 0, 1);\n"
+ "}\n",
+ namestr);
+ break;
+ case CAIRO_GL_OPERAND_CONSTANT:
+ _cairo_output_stream_printf (stream,
+ "uniform vec4 %s_constant;\n"
+ "vec4 get_%s()\n"
+ "{\n"
+ " return %s_constant;\n"
+ "}\n",
+ namestr, namestr, namestr);
+ break;
+ case CAIRO_GL_OPERAND_TEXTURE:
+ _cairo_output_stream_printf (stream,
+ "uniform sampler2D%s %s_sampler;\n"
+ "varying vec2 %s_texcoords;\n"
+ "vec4 get_%s()\n"
+ "{\n"
+ " return texture2D%s(%s_sampler, %s_texcoords);\n"
+ "}\n",
+ rectstr, namestr, namestr, namestr, rectstr, namestr, namestr);
+ break;
+ case CAIRO_GL_OPERAND_TEXTURE_ALPHA:
+ _cairo_output_stream_printf (stream,
+ "uniform sampler2D%s %s_sampler;\n"
+ "varying vec2 %s_texcoords;\n"
+ "vec4 get_%s()\n"
+ "{\n"
+ " return vec4 (0, 0, 0, texture2D%s(%s_sampler, %s_texcoords).a);\n"
+ "}\n",
+ rectstr, namestr, namestr, namestr, rectstr, namestr, namestr);
+ break;
+ case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
+ _cairo_output_stream_printf (stream,
+ "uniform sampler1D %s_sampler;\n"
+ "uniform mat4 %s_matrix;\n"
+ "uniform vec2 %s_segment;\n"
+ "\n"
+ "vec4 get_%s()\n"
+ "{\n"
+ " vec2 pos = (%s_matrix * vec4 (gl_FragCoord.xy, 0.0, 1.0)).xy;\n"
+ " float t = dot (pos, %s_segment) / dot (%s_segment, %s_segment);\n"
+ " return texture1D (%s_sampler, t);\n"
+ "}\n",
+ namestr, namestr, namestr, namestr, namestr,
+ namestr, namestr, namestr, namestr);
+ break;
+ case CAIRO_GL_OPERAND_RADIAL_GRADIENT:
+ _cairo_output_stream_printf (stream,
+ "uniform sampler1D %s_sampler;\n"
+ "uniform mat4 %s_matrix;\n"
+ "uniform vec2 %s_circle_1;\n"
+ "uniform float %s_radius_0;\n"
+ "uniform float %s_radius_1;\n"
+ "\n"
+ "vec4 get_%s()\n"
+ "{\n"
+ " vec2 pos = (%s_matrix * vec4 (gl_FragCoord.xy, 0.0, 1.0)).xy;\n"
+ " \n"
+ " float dr = %s_radius_1 - %s_radius_0;\n"
+ " float dot_circle_1 = dot (%s_circle_1, %s_circle_1);\n"
+ " float dot_pos_circle_1 = dot (pos, %s_circle_1);\n"
+ " \n"
+ " float A = dot_circle_1 - dr * dr;\n"
+ " float B = -2.0 * (dot_pos_circle_1 + %s_radius_0 * dr);\n"
+ " float C = dot (pos, pos) - %s_radius_0 * %s_radius_0;\n"
+ " float det = B * B - 4.0 * A * C;\n"
+ " det = max (det, 0.0);\n"
+ " \n"
+ " float sqrt_det = sqrt (det);\n"
+ " sqrt_det *= sign(A);\n"
+ " \n"
+ " float t = (-B + sqrt_det) / (2.0 * A);\n"
+ " return texture1D (%s_sampler, t);\n"
+ "}\n",
+ namestr, namestr, namestr, namestr, namestr,
+ namestr, namestr, namestr, namestr, namestr,
+ namestr, namestr, namestr, namestr, namestr,
+ namestr);
+ break;
+ case CAIRO_GL_OPERAND_SPANS:
+ _cairo_output_stream_printf (stream,
+ "varying float %s_coverage;\n"
+ "vec4 get_%s()\n"
+ "{\n"
+ " return vec4(0, 0, 0, %s_coverage);\n"
+ "}\n",
+ namestr, namestr, namestr);
+ break;
+ }
+}
+
+static char *
+cairo_gl_shader_get_fragment_source (GLuint tex_target,
+ cairo_gl_shader_in_t in,
+ cairo_gl_operand_type_t src,
+ cairo_gl_operand_type_t mask,
+ cairo_gl_operand_type_t dest)
+{
+ cairo_output_stream_t *stream = _cairo_memory_stream_create ();
+ unsigned char *source;
+ unsigned int length;
+
+ cairo_gl_shader_emit_color (stream, tex_target, src, CAIRO_GL_OPERAND_SOURCE);
+ cairo_gl_shader_emit_color (stream, tex_target, mask, CAIRO_GL_OPERAND_MASK);
+ if (dest != CAIRO_GL_OPERAND_NONE)
+ cairo_gl_shader_emit_color (stream, tex_target, dest, CAIRO_GL_OPERAND_DEST);
+
+ _cairo_output_stream_printf (stream,
+ "void main()\n"
+ "{\n");
+ switch (in) {
+ case CAIRO_GL_SHADER_IN_COUNT:
+ default:
+ ASSERT_NOT_REACHED;
+ case CAIRO_GL_SHADER_IN_NORMAL:
+ _cairo_output_stream_printf (stream,
+ " gl_FragColor = get_source() * get_mask().a;\n");
+ break;
+ case CAIRO_GL_SHADER_IN_CA_SOURCE:
+ _cairo_output_stream_printf (stream,
+ " gl_FragColor = get_source() * get_mask();\n");
+ break;
+ case CAIRO_GL_SHADER_IN_CA_SOURCE_ALPHA:
+ _cairo_output_stream_printf (stream,
+ " gl_FragColor = get_source().a * get_mask();\n");
+ break;
+ }
+
+ _cairo_output_stream_write (stream,
+ "}\n\0", 3);
+
+ if (_cairo_memory_stream_destroy (stream, &source, &length))
+ return NULL;
+
+ return (char *) source;
}
cairo_status_t
@@ -691,177 +848,6 @@ _cairo_gl_use_program (cairo_gl_context_t *ctx,
ctx->shader_impl->use_program (program);
}
-static const char *fs_source_constant =
- "uniform vec4 constant_source;\n"
- "vec4 get_source()\n"
- "{\n"
- " return constant_source;\n"
- "}\n";
-static const char *fs_source_texture =
- "uniform sampler2D source_sampler;\n"
- "varying vec2 source_texcoords;\n"
- "vec4 get_source()\n"
- "{\n"
- " return texture2D(source_sampler, source_texcoords);\n"
- "}\n";
-static const char *fs_source_texture_rect =
- "uniform sampler2DRect source_sampler;\n"
- "varying vec2 source_texcoords;\n"
- "vec4 get_source()\n"
- "{\n"
- " return texture2DRect(source_sampler, source_texcoords);\n"
- "}\n";
-static const char *fs_source_texture_alpha =
- "uniform sampler2D source_sampler;\n"
- "varying vec2 source_texcoords;\n"
- "vec4 get_source()\n"
- "{\n"
- " return vec4(0, 0, 0, texture2D(source_sampler, source_texcoords).a);\n"
- "}\n";
-static const char *fs_source_texture_alpha_rect =
- "uniform sampler2DRect source_sampler;\n"
- "varying vec2 source_texcoords;\n"
- "vec4 get_source()\n"
- "{\n"
- " return vec4(0, 0, 0, texture2DRect(source_sampler, source_texcoords).a);\n"
- "}\n";
-static const char *fs_source_linear_gradient =
- "uniform sampler1D source_sampler;\n"
- "uniform mat4 source_matrix;\n"
- "uniform vec2 source_segment;\n"
- "\n"
- "vec4 get_source()\n"
- "{\n"
- " vec2 pos = (source_matrix * vec4 (gl_FragCoord.xy, 0.0, 1.0)).xy;\n"
- " float t = dot (pos, source_segment) / dot (source_segment, source_segment);\n"
- " return texture1D (source_sampler, t);\n"
- "}\n";
-static const char *fs_source_radial_gradient =
- "uniform sampler1D source_sampler;\n"
- "uniform mat4 source_matrix;\n"
- "uniform vec2 source_circle_1;\n"
- "uniform float source_radius_0;\n"
- "uniform float source_radius_1;\n"
- "\n"
- "vec4 get_source()\n"
- "{\n"
- " vec2 pos = (source_matrix * vec4 (gl_FragCoord.xy, 0.0, 1.0)).xy;\n"
- " \n"
- " float dr = source_radius_1 - source_radius_0;\n"
- " float dot_circle_1 = dot (source_circle_1, source_circle_1);\n"
- " float dot_pos_circle_1 = dot (pos, source_circle_1);\n"
- " \n"
- " float A = dot_circle_1 - dr * dr;\n"
- " float B = -2.0 * (dot_pos_circle_1 + source_radius_0 * dr);\n"
- " float C = dot (pos, pos) - source_radius_0 * source_radius_0;\n"
- " float det = B * B - 4.0 * A * C;\n"
- " det = max (det, 0.0);\n"
- " \n"
- " float sqrt_det = sqrt (det);\n"
- " sqrt_det *= sign(A);\n"
- " \n"
- " float t = (-B + sqrt_det) / (2.0 * A);\n"
- " return texture1D (source_sampler, t);\n"
- "}\n";
-static const char *fs_mask_constant =
- "uniform vec4 constant_mask;\n"
- "vec4 get_mask()\n"
- "{\n"
- " return constant_mask;\n"
- "}\n";
-static const char *fs_mask_texture =
- "uniform sampler2D mask_sampler;\n"
- "varying vec2 mask_texcoords;\n"
- "vec4 get_mask()\n"
- "{\n"
- " return texture2D(mask_sampler, mask_texcoords);\n"
- "}\n";
-static const char *fs_mask_texture_rect =
- "uniform sampler2DRect mask_sampler;\n"
- "varying vec2 mask_texcoords;\n"
- "vec4 get_mask()\n"
- "{\n"
- " return texture2DRect(mask_sampler, mask_texcoords);\n"
- "}\n";
-static const char *fs_mask_texture_alpha =
- "uniform sampler2D mask_sampler;\n"
- "varying vec2 mask_texcoords;\n"
- "vec4 get_mask()\n"
- "{\n"
- " return vec4(0, 0, 0, texture2D(mask_sampler, mask_texcoords).a);\n"
- "}\n";
-static const char *fs_mask_texture_alpha_rect =
- "uniform sampler2DRect mask_sampler;\n"
- "varying vec2 mask_texcoords;\n"
- "vec4 get_mask()\n"
- "{\n"
- " return vec4(0, 0, 0, texture2DRect(mask_sampler, mask_texcoords).a);\n"
- "}\n";
-static const char *fs_mask_linear_gradient =
- "uniform sampler1D mask_sampler;\n"
- "uniform mat4 mask_matrix;\n"
- "uniform vec2 mask_segment;\n"
- "\n"
- "vec4 get_mask()\n"
- "{\n"
- " vec2 pos = (mask_matrix * vec4 (gl_FragCoord.xy, 0.0, 1.0)).xy;\n"
- " float t = dot (pos, mask_segment) / dot (mask_segment, mask_segment);\n"
- " return texture1D (mask_sampler, t);\n"
- "}\n";
-static const char *fs_mask_radial_gradient =
- "uniform sampler1D mask_sampler;\n"
- "uniform mat4 mask_matrix;\n"
- "uniform vec2 mask_circle_1;\n"
- "uniform float mask_radius_0;\n"
- "uniform float mask_radius_1;\n"
- "\n"
- "vec4 get_mask()\n"
- "{\n"
- " vec2 pos = (mask_matrix * vec4 (gl_FragCoord.xy, 0.0, 1.0)).xy;\n"
- " \n"
- " float dr = mask_radius_1 - mask_radius_0;\n"
- " float dot_circle_1 = dot (mask_circle_1, mask_circle_1);\n"
- " float dot_pos_circle_1 = dot (pos, mask_circle_1);\n"
- " \n"
- " float A = dot_circle_1 - dr * dr;\n"
- " float B = -2.0 * (dot_pos_circle_1 + mask_radius_0 * dr);\n"
- " float C = dot (pos, pos) - mask_radius_0 * mask_radius_0;\n"
- " float det = B * B - 4.0 * A * C;\n"
- " det = max (det, 0.0);\n"
- " \n"
- " float sqrt_det = sqrt (det);\n"
- " sqrt_det *= sign(A);\n"
- " \n"
- " float t = (-B + sqrt_det) / (2.0 * A);\n"
- " return texture1D (mask_sampler, t);\n"
- "}\n";
-static const char *fs_mask_none =
- "vec4 get_mask()\n"
- "{\n"
- " return vec4(0, 0, 0, 1);\n"
- "}\n";
-static const char *fs_mask_spans =
- "varying float mask_coverage;\n"
- "vec4 get_mask()\n"
- "{\n"
- " return vec4(0, 0, 0, mask_coverage);\n"
- "}\n";
-static const char *fs_in_normal =
- "void main()\n"
- "{\n"
- " gl_FragColor = get_source() * get_mask().a;\n"
- "}\n";
-static const char *fs_in_component_alpha_source =
- "void main()\n"
- "{\n"
- " gl_FragColor = get_source() * get_mask();\n"
- "}\n";
-static const char *fs_in_component_alpha_alpha =
- "void main()\n"
- "{\n"
- " gl_FragColor = get_source().a * get_mask();\n"
- "}\n";
-
/**
* This function reduces the GLSL program combinations we compile when
* there are non-functional differences.
@@ -893,38 +879,10 @@ _cairo_gl_get_program (cairo_gl_context_t *ctx,
cairo_gl_shader_in_t in,
cairo_gl_shader_program_t **out_program)
{
- const char *source_sources[CAIRO_GL_OPERAND_COUNT] = {
- NULL,
- fs_source_constant,
- fs_source_texture,
- fs_source_texture_alpha,
- fs_source_linear_gradient,
- fs_source_radial_gradient,
- NULL
- };
- const char *mask_sources[CAIRO_GL_OPERAND_COUNT] = {
- fs_mask_none,
- fs_mask_constant,
- fs_mask_texture,
- fs_mask_texture_alpha,
- fs_mask_linear_gradient,
- fs_mask_radial_gradient,
- fs_mask_spans
- };
- const char *in_sources[CAIRO_GL_SHADER_IN_COUNT] = {
- fs_in_normal,
- fs_in_component_alpha_source,
- fs_in_component_alpha_alpha,
- };
cairo_gl_shader_program_t *program;
- const char *source_source, *mask_source, *in_source;
char *fs_source;
cairo_status_t status;
- assert (source < ARRAY_LENGTH (source_sources));
- assert (source_sources[source] != NULL);
- assert (mask < ARRAY_LENGTH (mask_sources));
-
program = _cairo_gl_select_program(ctx, source, mask, in);
if (program->program) {
*out_program = program;
@@ -937,33 +895,13 @@ _cairo_gl_get_program (cairo_gl_context_t *ctx,
if (ctx->shader_impl == NULL)
return CAIRO_INT_STATUS_UNSUPPORTED;
- source_source = source_sources[source];
- mask_source = mask_sources[mask];
- in_source = in_sources[in];
-
- /* For ARB_texture_rectangle, rewrite sampler2D and texture2D to
- * sampler2DRect and texture2DRect.
- */
- if (ctx->tex_target == GL_TEXTURE_RECTANGLE_EXT) {
- if (source_source == fs_source_texture)
- source_source = fs_source_texture_rect;
- else if (source_source == fs_source_texture_alpha)
- source_source = fs_source_texture_alpha_rect;
-
- if (mask_source == fs_mask_texture)
- mask_source = fs_mask_texture_rect;
- else if (mask_source == fs_mask_texture_alpha)
- mask_source = fs_mask_texture_alpha_rect;
- }
-
- fs_source = _cairo_malloc (strlen(source_source) +
- strlen(mask_source) +
- strlen(in_source) +
- 1);
+ fs_source = cairo_gl_shader_get_fragment_source (ctx->tex_target,
+ in,
+ source,
+ mask,
+ CAIRO_GL_OPERAND_NONE);
if (unlikely (fs_source == NULL))
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
- sprintf(fs_source, "%s%s%s", source_source, mask_source, in_source);
+ return CAIRO_STATUS_NO_MEMORY;
init_shader_program (program);
status = create_shader_program (ctx,
diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c
index 494a16b..889e41d 100644
--- a/src/cairo-gl-surface.c
+++ b/src/cairo-gl-surface.c
@@ -1387,9 +1387,9 @@ _cairo_gl_set_tex_combine_constant_color (cairo_gl_context_t *ctx,
cairo_status_t status;
if (tex_unit == 0)
- uniform_name = "constant_source";
+ uniform_name = "source_constant";
else
- uniform_name = "constant_mask";
+ uniform_name = "mask_constant";
status = bind_vec4_to_shader (ctx,
setup->shader->program,
@@ -1663,7 +1663,7 @@ _cairo_gl_set_component_alpha_mask_operand (cairo_gl_context_t *ctx,
if (setup->shader) {
cairo_status_t status;
status = bind_vec4_to_shader (ctx, setup->shader->program,
- "constant_mask",
+ "mask_constant",
setup->src.operand.constant.color[0],
setup->src.operand.constant.color[1],
setup->src.operand.constant.color[2],
commit fe43b13052f7063f880aeeebda1880a6a2097922
Author: Benjamin Otte <otte at redhat.com>
Date: Wed May 12 13:57:06 2010 +0200
gl: Automatically generate the vertex shader source
The idea is being able to generate shaders from the given input
on-demand. This allows creating more advanced shaders, such as those
that include the destination (for self-painting and
unsupported-by-blending operator) or painting images in weird formats
(extra translation step in shader, think YUV).
diff --git a/src/cairo-gl-device.c b/src/cairo-gl-device.c
index 2dd225b..ed9b91e 100644
--- a/src/cairo-gl-device.c
+++ b/src/cairo-gl-device.c
@@ -64,7 +64,7 @@ _gl_finish (void *device)
int i;
if (_cairo_gl_context_acquire (device, &ctx) == CAIRO_STATUS_SUCCESS) {
- for (i = 0; i < CAIRO_GL_VERTEX_SHADER_COUNT; i++) {
+ for (i = 0; i <= CAIRO_GL_VAR_TYPE_MAX; i++) {
destroy_shader (ctx, ctx->vertex_shaders[i]);
}
diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h
index 0683879..6ea8fb2 100644
--- a/src/cairo-gl-private.h
+++ b/src/cairo-gl-private.h
@@ -108,16 +108,14 @@ typedef enum cairo_gl_shader_in {
CAIRO_GL_SHADER_IN_COUNT
} cairo_gl_shader_in_t;
-typedef enum cairo_gl_vertex_shader {
- CAIRO_GL_VERTEX_SHADER_EMPTY,
- CAIRO_GL_VERTEX_SHADER_SOURCE,
- CAIRO_GL_VERTEX_SHADER_MASK,
- CAIRO_GL_VERTEX_SHADER_SOURCE_MASK,
- CAIRO_GL_VERTEX_SHADER_SPANS,
- CAIRO_GL_VERTEX_SHADER_SOURCE_SPANS,
+typedef enum cairo_gl_var_type {
+ CAIRO_GL_VAR_NONE,
+ CAIRO_GL_VAR_TEXCOORDS,
+ CAIRO_GL_VAR_COVERAGE
+} cairo_gl_var_type_t;
- CAIRO_GL_VERTEX_SHADER_COUNT
-} cairo_gl_vertex_shader_t;
+#define cairo_gl_var_type_hash(src,mask,dest) ((mask) << 2 | (src << 1) | (dest))
+#define CAIRO_GL_VAR_TYPE_MAX ((CAIRO_GL_VAR_COVERAGE << 2) | (CAIRO_GL_VAR_TEXCOORDS << 1) | CAIRO_GL_VAR_TEXCOORDS)
typedef struct _cairo_gl_context {
cairo_device_t base;
@@ -132,7 +130,7 @@ typedef struct _cairo_gl_context {
const cairo_gl_shader_impl_t *shader_impl;
- GLuint vertex_shaders[CAIRO_GL_VERTEX_SHADER_COUNT];
+ GLuint vertex_shaders[CAIRO_GL_VAR_TYPE_MAX + 1];
cairo_gl_shader_program_t fill_rectangles_shader;
cairo_gl_shader_program_t shaders[CAIRO_GL_OPERAND_COUNT]
[CAIRO_GL_OPERAND_COUNT]
@@ -337,7 +335,8 @@ destroy_shader_program (cairo_gl_context_t *ctx,
cairo_private cairo_status_t
create_shader_program (cairo_gl_context_t *ctx,
cairo_gl_shader_program_t *program,
- cairo_gl_vertex_shader_t vertex_shader,
+ cairo_gl_var_type_t src,
+ cairo_gl_var_type_t mask,
const char *fragment_text);
cairo_private cairo_status_t
diff --git a/src/cairo-gl-shaders.c b/src/cairo-gl-shaders.c
index 2e4f732..240054d 100644
--- a/src/cairo-gl-shaders.c
+++ b/src/cairo-gl-shaders.c
@@ -34,6 +34,7 @@
#include "cairoint.h"
#include "cairo-gl-private.h"
#include "cairo-error-private.h"
+#include "cairo-output-stream-private.h"
typedef struct cairo_gl_shader_impl {
cairo_status_t
@@ -471,62 +472,120 @@ destroy_shader_program (cairo_gl_context_t *ctx,
ctx->shader_impl->destroy_program (program->program);
}
-static const char *vs_sources[] = {
-[CAIRO_GL_VERTEX_SHADER_EMPTY] =
- "void main()\n"
- "{\n"
- " gl_Position = ftransform();\n"
- "}\n",
-[CAIRO_GL_VERTEX_SHADER_SOURCE] =
- "varying vec2 source_texcoords;\n"
- "void main()\n"
- "{\n"
- " gl_Position = ftransform();\n"
- " source_texcoords = gl_MultiTexCoord0.xy;\n"
- "}\n",
-[CAIRO_GL_VERTEX_SHADER_MASK] =
- "varying vec2 mask_texcoords;\n"
- "void main()\n"
- "{\n"
- " gl_Position = ftransform();\n"
- " mask_texcoords = gl_MultiTexCoord1.xy;\n"
- "}\n",
-[CAIRO_GL_VERTEX_SHADER_SOURCE_MASK] =
- "varying vec2 source_texcoords;\n"
- "varying vec2 mask_texcoords;\n"
- "void main()\n"
- "{\n"
- " gl_Position = ftransform();\n"
- " source_texcoords = gl_MultiTexCoord0.xy;\n"
- " mask_texcoords = gl_MultiTexCoord1.xy;\n"
- "}\n",
-[CAIRO_GL_VERTEX_SHADER_SPANS] =
- "varying float coverage;\n"
- "void main()\n"
- "{\n"
- " gl_Position = ftransform();\n"
- " coverage = gl_Color.a;\n"
- "}\n",
-[CAIRO_GL_VERTEX_SHADER_SOURCE_SPANS] =
- "varying vec2 source_texcoords;\n"
- "varying float coverage;\n"
- "void main()\n"
- "{\n"
- " gl_Position = ftransform();\n"
- " source_texcoords = gl_MultiTexCoord0.xy;\n"
- " coverage = gl_Color.a;\n"
- "}\n"
-};
+typedef enum cairo_gl_operand_target {
+ CAIRO_GL_OPERAND_SOURCE,
+ CAIRO_GL_OPERAND_MASK,
+ CAIRO_GL_OPERAND_DEST
+} cairo_gl_operand_name_t;
+
+static const char *operand_names[] = { "source", "mask", "dest" };
+
+static cairo_gl_var_type_t
+cairo_gl_operand_get_var_type (cairo_gl_operand_type_t type)
+{
+ switch (type) {
+ default:
+ case CAIRO_GL_OPERAND_COUNT:
+ ASSERT_NOT_REACHED;
+ case CAIRO_GL_OPERAND_NONE:
+ case CAIRO_GL_OPERAND_CONSTANT:
+ case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
+ case CAIRO_GL_OPERAND_RADIAL_GRADIENT:
+ return CAIRO_GL_VAR_NONE;
+ case CAIRO_GL_OPERAND_TEXTURE:
+ case CAIRO_GL_OPERAND_TEXTURE_ALPHA:
+ return CAIRO_GL_VAR_TEXCOORDS;
+ case CAIRO_GL_OPERAND_SPANS:
+ return CAIRO_GL_VAR_COVERAGE;
+ }
+}
+
+static void
+cairo_gl_shader_emit_variable (cairo_output_stream_t *stream,
+ cairo_gl_var_type_t type,
+ cairo_gl_operand_name_t name)
+{
+ switch (type) {
+ default:
+ ASSERT_NOT_REACHED;
+ case CAIRO_GL_VAR_NONE:
+ break;
+ case CAIRO_GL_VAR_TEXCOORDS:
+ _cairo_output_stream_printf (stream,
+ "varying vec2 %s_texcoords;\n",
+ operand_names[name]);
+ break;
+ case CAIRO_GL_VAR_COVERAGE:
+ _cairo_output_stream_printf (stream,
+ "varying float %s_coverage;\n",
+ operand_names[name]);
+ break;
+ }
+}
+
+static void
+cairo_gl_shader_emit_vertex (cairo_output_stream_t *stream,
+ cairo_gl_var_type_t type,
+ cairo_gl_operand_name_t name)
+{
+ switch (type) {
+ default:
+ ASSERT_NOT_REACHED;
+ case CAIRO_GL_VAR_NONE:
+ break;
+ case CAIRO_GL_VAR_TEXCOORDS:
+ _cairo_output_stream_printf (stream,
+ " %s_texcoords = gl_MultiTexCoord%d.xy;\n",
+ operand_names[name], name);
+ break;
+ case CAIRO_GL_VAR_COVERAGE:
+ _cairo_output_stream_printf (stream,
+ " %s_coverage = gl_Color.a;\n",
+ operand_names[name]);
+ break;
+ }
+}
+
+static char *
+cairo_gl_shader_get_vertex_source (cairo_gl_var_type_t src,
+ cairo_gl_var_type_t mask,
+ cairo_gl_var_type_t dest)
+{
+ cairo_output_stream_t *stream = _cairo_memory_stream_create ();
+ unsigned char *source;
+ unsigned int length;
+
+ cairo_gl_shader_emit_variable (stream, src, CAIRO_GL_OPERAND_SOURCE);
+ cairo_gl_shader_emit_variable (stream, mask, CAIRO_GL_OPERAND_MASK);
+ cairo_gl_shader_emit_variable (stream, dest, CAIRO_GL_OPERAND_DEST);
+
+ _cairo_output_stream_printf (stream,
+ "void main()\n"
+ "{\n"
+ " gl_Position = ftransform();\n");
+
+ cairo_gl_shader_emit_vertex (stream, src, CAIRO_GL_OPERAND_SOURCE);
+ cairo_gl_shader_emit_vertex (stream, mask, CAIRO_GL_OPERAND_MASK);
+ cairo_gl_shader_emit_vertex (stream, dest, CAIRO_GL_OPERAND_DEST);
+
+ _cairo_output_stream_write (stream,
+ "}\n\0", 3);
+
+ if (_cairo_memory_stream_destroy (stream, &source, &length))
+ return NULL;
+
+ return (char *) source;
+}
cairo_status_t
create_shader_program (cairo_gl_context_t *ctx,
cairo_gl_shader_program_t *program,
- cairo_gl_vertex_shader_t vertex_shader,
+ cairo_gl_var_type_t src,
+ cairo_gl_var_type_t mask,
const char *fragment_text)
{
cairo_status_t status;
-
- assert (vertex_shader < ARRAY_LENGTH (vs_sources));
+ unsigned int vertex_shader;
if (program->program != 0)
return CAIRO_STATUS_SUCCESS;
@@ -537,10 +596,16 @@ create_shader_program (cairo_gl_context_t *ctx,
if (ctx->shader_impl == NULL)
return CAIRO_INT_STATUS_UNSUPPORTED;
+ vertex_shader = cairo_gl_var_type_hash (src, mask, CAIRO_GL_VAR_NONE);
if (ctx->vertex_shaders[vertex_shader] == 0) {
+ char *source = cairo_gl_shader_get_vertex_source (src, mask, CAIRO_GL_VAR_NONE);
+ if (unlikely (source == NULL))
+ goto FAILURE;
+
status = ctx->shader_impl->compile_shader (&ctx->vertex_shaders[vertex_shader],
GL_VERTEX_SHADER,
- vs_sources[vertex_shader]);
+ source);
+ free (source);
if (unlikely (status))
goto FAILURE;
}
@@ -776,10 +841,10 @@ static const char *fs_mask_none =
" return vec4(0, 0, 0, 1);\n"
"}\n";
static const char *fs_mask_spans =
- "varying float coverage;\n"
+ "varying float mask_coverage;\n"
"vec4 get_mask()\n"
"{\n"
- " return vec4(0, 0, 0, coverage);\n"
+ " return vec4(0, 0, 0, mask_coverage);\n"
"}\n";
static const char *fs_in_normal =
"void main()\n"
@@ -853,7 +918,6 @@ _cairo_gl_get_program (cairo_gl_context_t *ctx,
};
cairo_gl_shader_program_t *program;
const char *source_source, *mask_source, *in_source;
- cairo_gl_vertex_shader_t vs;
char *fs_source;
cairo_status_t status;
@@ -899,34 +963,13 @@ _cairo_gl_get_program (cairo_gl_context_t *ctx,
if (unlikely (fs_source == NULL))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
- if (source == CAIRO_GL_OPERAND_CONSTANT ||
- source == CAIRO_GL_OPERAND_LINEAR_GRADIENT ||
- source == CAIRO_GL_OPERAND_RADIAL_GRADIENT) {
- if (mask == CAIRO_GL_OPERAND_SPANS)
- vs = CAIRO_GL_VERTEX_SHADER_SPANS;
- else if (mask == CAIRO_GL_OPERAND_CONSTANT ||
- mask == CAIRO_GL_OPERAND_LINEAR_GRADIENT ||
- mask == CAIRO_GL_OPERAND_RADIAL_GRADIENT)
- vs = CAIRO_GL_VERTEX_SHADER_EMPTY;
- else
- vs = CAIRO_GL_VERTEX_SHADER_MASK;
- } else {
- if (mask == CAIRO_GL_OPERAND_SPANS)
- vs = CAIRO_GL_VERTEX_SHADER_SOURCE_SPANS;
- else if (mask == CAIRO_GL_OPERAND_CONSTANT ||
- mask == CAIRO_GL_OPERAND_LINEAR_GRADIENT ||
- mask == CAIRO_GL_OPERAND_RADIAL_GRADIENT)
- vs = CAIRO_GL_VERTEX_SHADER_SOURCE;
- else
- vs = CAIRO_GL_VERTEX_SHADER_SOURCE_MASK;
- }
-
sprintf(fs_source, "%s%s%s", source_source, mask_source, in_source);
init_shader_program (program);
status = create_shader_program (ctx,
program,
- vs,
+ cairo_gl_operand_get_var_type (source),
+ cairo_gl_operand_get_var_type (mask),
fs_source);
free (fs_source);
diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c
index ad80632..494a16b 100644
--- a/src/cairo-gl-surface.c
+++ b/src/cairo-gl-surface.c
@@ -2412,7 +2412,8 @@ _cairo_gl_surface_fill_rectangles_glsl (void *abstract_surface,
status = create_shader_program (ctx,
&ctx->fill_rectangles_shader,
- CAIRO_GL_VERTEX_SHADER_EMPTY,
+ CAIRO_GL_VAR_NONE,
+ CAIRO_GL_VAR_NONE,
fill_fs_source);
if (unlikely (status)) {
_cairo_gl_context_release (ctx);
commit 405eee07ad9a5bc325b339b8588facb905fb28f5
Author: Benjamin Otte <otte at redhat.com>
Date: Wed May 12 00:02:28 2010 +0200
gl: Get rid of cairo_gl_shader_source/mask_t
Use the cairo_gl_operand_type_t instead. Those enums are pretty much
identical.
diff --git a/src/cairo-gl-glyphs.c b/src/cairo-gl-glyphs.c
index 07bd698..4f4e865 100644
--- a/src/cairo-gl-glyphs.c
+++ b/src/cairo-gl-glyphs.c
@@ -320,8 +320,8 @@ _cairo_gl_glyphs_set_shader (cairo_gl_context_t *ctx,
cairo_status_t status;
status = _cairo_gl_get_program (ctx,
- setup->composite->src.source,
- CAIRO_GL_SHADER_MASK_TEXTURE,
+ setup->composite->src.type,
+ CAIRO_GL_OPERAND_TEXTURE,
in,
&setup->composite->shader);
if (!_cairo_status_is_error (status)) {
@@ -416,7 +416,8 @@ _cairo_gl_glyphs_emit_vertex (cairo_gl_glyphs_setup_t *setup,
vb[i++] = glyph_x;
vb[i++] = glyph_y;
- if (setup->composite->src.type == OPERAND_TEXTURE) {
+ if (setup->composite->src.type == CAIRO_GL_OPERAND_TEXTURE ||
+ setup->composite->src.type == CAIRO_GL_OPERAND_TEXTURE_ALPHA) {
double s = x;
double t = y;
cairo_matrix_transform_point (&src_attributes->matrix, &s, &t);
@@ -516,7 +517,8 @@ _render_glyphs (cairo_gl_surface_t *dst,
setup.clip = clip_region;
setup.dst = dst;
setup.vertex_size = 4;
- if (composite_setup.src.type == OPERAND_TEXTURE)
+ if (composite_setup.src.type == CAIRO_GL_OPERAND_TEXTURE ||
+ composite_setup.src.type == CAIRO_GL_OPERAND_TEXTURE_ALPHA)
setup.vertex_size += 2;
setup.vbo_size = num_glyphs * 4 * setup.vertex_size;
if (setup.vbo_size > 4096)
@@ -529,7 +531,8 @@ _render_glyphs (cairo_gl_surface_t *dst,
glVertexPointer (2, GL_FLOAT, setup.vertex_size * sizeof (GLfloat),
(void *)(uintptr_t)(0));
glEnableClientState (GL_VERTEX_ARRAY);
- if (composite_setup.src.type == OPERAND_TEXTURE) {
+ if (composite_setup.src.type == CAIRO_GL_OPERAND_TEXTURE ||
+ composite_setup.src.type == CAIRO_GL_OPERAND_TEXTURE_ALPHA) {
/* Note that we're packing texcoord 0 after texcoord 1, for
* convenience.
*/
diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h
index 777f12c..0683879 100644
--- a/src/cairo-gl-private.h
+++ b/src/cairo-gl-private.h
@@ -80,6 +80,18 @@ typedef struct cairo_gl_glyph_cache {
unsigned int width, height;
} cairo_gl_glyph_cache_t;
+typedef enum cairo_gl_operand_type {
+ CAIRO_GL_OPERAND_NONE,
+ CAIRO_GL_OPERAND_CONSTANT,
+ CAIRO_GL_OPERAND_TEXTURE,
+ CAIRO_GL_OPERAND_TEXTURE_ALPHA,
+ CAIRO_GL_OPERAND_LINEAR_GRADIENT,
+ CAIRO_GL_OPERAND_RADIAL_GRADIENT,
+ CAIRO_GL_OPERAND_SPANS,
+
+ CAIRO_GL_OPERAND_COUNT
+} cairo_gl_operand_type_t;
+
typedef struct cairo_gl_shader_impl cairo_gl_shader_impl_t;
typedef struct cairo_gl_shader_program {
@@ -88,28 +100,6 @@ typedef struct cairo_gl_shader_program {
cairo_bool_t build_failure;
} cairo_gl_shader_program_t;
-typedef enum cairo_gl_shader_source {
- CAIRO_GL_SHADER_SOURCE_CONSTANT,
- CAIRO_GL_SHADER_SOURCE_TEXTURE,
- CAIRO_GL_SHADER_SOURCE_TEXTURE_ALPHA,
- CAIRO_GL_SHADER_SOURCE_LINEAR_GRADIENT,
- CAIRO_GL_SHADER_SOURCE_RADIAL_GRADIENT,
-
- CAIRO_GL_SHADER_SOURCE_COUNT
-} cairo_gl_shader_source_t;
-
-typedef enum cairo_gl_shader_mask {
- CAIRO_GL_SHADER_MASK_CONSTANT,
- CAIRO_GL_SHADER_MASK_TEXTURE,
- CAIRO_GL_SHADER_MASK_TEXTURE_ALPHA,
- CAIRO_GL_SHADER_MASK_LINEAR_GRADIENT,
- CAIRO_GL_SHADER_MASK_RADIAL_GRADIENT,
- CAIRO_GL_SHADER_MASK_NONE,
- CAIRO_GL_SHADER_MASK_SPANS,
-
- CAIRO_GL_SHADER_MASK_COUNT
-} cairo_gl_shader_mask_t;
-
typedef enum cairo_gl_shader_in {
CAIRO_GL_SHADER_IN_NORMAL,
CAIRO_GL_SHADER_IN_CA_SOURCE,
@@ -144,9 +134,9 @@ typedef struct _cairo_gl_context {
GLuint vertex_shaders[CAIRO_GL_VERTEX_SHADER_COUNT];
cairo_gl_shader_program_t fill_rectangles_shader;
- cairo_gl_shader_program_t shaders[CAIRO_GL_SHADER_SOURCE_COUNT]
- [CAIRO_GL_SHADER_MASK_COUNT]
- [CAIRO_GL_SHADER_IN_COUNT];
+ cairo_gl_shader_program_t shaders[CAIRO_GL_OPERAND_COUNT]
+ [CAIRO_GL_OPERAND_COUNT]
+ [CAIRO_GL_SHADER_IN_COUNT];
cairo_gl_surface_t *current_target;
cairo_gl_glyph_cache_t glyph_cache[2];
@@ -160,20 +150,11 @@ typedef struct _cairo_gl_context {
void (*destroy) (void *ctx);
} cairo_gl_context_t;
-enum cairo_gl_composite_operand_type {
- OPERAND_CONSTANT,
- OPERAND_TEXTURE,
- OPERAND_LINEAR_GRADIENT,
- OPERAND_RADIAL_GRADIENT,
-};
-
/* This union structure describes a potential source or mask operand to the
* compositing equation.
*/
-typedef struct cairo_gl_composite_operand {
- enum cairo_gl_composite_operand_type type;
- cairo_gl_shader_source_t source;
- cairo_gl_shader_mask_t mask;
+typedef struct cairo_gl_operand {
+ cairo_gl_operand_type_t type;
union {
struct {
GLuint tex;
@@ -200,11 +181,11 @@ typedef struct cairo_gl_composite_operand {
} operand;
const cairo_pattern_t *pattern;
-} cairo_gl_composite_operand_t;
+} cairo_gl_operand_t;
typedef struct _cairo_gl_composite_setup {
- cairo_gl_composite_operand_t src;
- cairo_gl_composite_operand_t mask;
+ cairo_gl_operand_t src;
+ cairo_gl_operand_t mask;
cairo_gl_shader_program_t *shader;
} cairo_gl_composite_setup_t;
@@ -240,7 +221,7 @@ _cairo_gl_surface_draw_image (cairo_gl_surface_t *dst,
cairo_private cairo_int_status_t
_cairo_gl_operand_init (cairo_gl_context_t *ctx,
- cairo_gl_composite_operand_t *operand,
+ cairo_gl_operand_t *operand,
const cairo_pattern_t *pattern,
cairo_gl_surface_t *dst,
int src_x, int src_y,
@@ -300,7 +281,7 @@ _cairo_gl_set_src_alpha_operand (cairo_gl_context_t *ctx,
cairo_gl_composite_setup_t *setup);
cairo_private void
-_cairo_gl_operand_destroy (cairo_gl_composite_operand_t *operand);
+_cairo_gl_operand_destroy (cairo_gl_operand_t *operand);
cairo_private cairo_bool_t
_cairo_gl_get_image_format_and_type (pixman_format_code_t pixman_format,
@@ -395,8 +376,8 @@ _cairo_gl_use_program (cairo_gl_context_t *ctx,
cairo_private cairo_status_t
_cairo_gl_get_program (cairo_gl_context_t *ctx,
- cairo_gl_shader_source_t source,
- cairo_gl_shader_mask_t mask,
+ cairo_gl_operand_type_t source,
+ cairo_gl_operand_type_t mask,
cairo_gl_shader_in_t in,
cairo_gl_shader_program_t **out_program);
diff --git a/src/cairo-gl-shaders.c b/src/cairo-gl-shaders.c
index e454278..2e4f732 100644
--- a/src/cairo-gl-shaders.c
+++ b/src/cairo-gl-shaders.c
@@ -803,19 +803,19 @@ static const char *fs_in_component_alpha_alpha =
*/
static cairo_gl_shader_program_t *
_cairo_gl_select_program (cairo_gl_context_t *ctx,
- cairo_gl_shader_source_t source,
- cairo_gl_shader_mask_t mask,
+ cairo_gl_operand_type_t source,
+ cairo_gl_operand_type_t mask,
cairo_gl_shader_in_t in)
{
if (in == CAIRO_GL_SHADER_IN_NORMAL &&
- mask == CAIRO_GL_SHADER_MASK_TEXTURE_ALPHA)
+ mask == CAIRO_GL_OPERAND_TEXTURE_ALPHA)
{
- mask = CAIRO_GL_SHADER_MASK_TEXTURE;
+ mask = CAIRO_GL_OPERAND_TEXTURE;
}
if (in == CAIRO_GL_SHADER_IN_CA_SOURCE_ALPHA &&
- source == CAIRO_GL_SHADER_SOURCE_TEXTURE_ALPHA)
+ source == CAIRO_GL_OPERAND_TEXTURE_ALPHA)
{
- source = CAIRO_GL_SHADER_SOURCE_TEXTURE;
+ source = CAIRO_GL_OPERAND_TEXTURE;
}
return &ctx->shaders[source][mask][in];
@@ -823,26 +823,28 @@ _cairo_gl_select_program (cairo_gl_context_t *ctx,
cairo_status_t
_cairo_gl_get_program (cairo_gl_context_t *ctx,
- cairo_gl_shader_source_t source,
- cairo_gl_shader_mask_t mask,
+ cairo_gl_operand_type_t source,
+ cairo_gl_operand_type_t mask,
cairo_gl_shader_in_t in,
cairo_gl_shader_program_t **out_program)
{
- const char *source_sources[CAIRO_GL_SHADER_SOURCE_COUNT] = {
+ const char *source_sources[CAIRO_GL_OPERAND_COUNT] = {
+ NULL,
fs_source_constant,
fs_source_texture,
fs_source_texture_alpha,
fs_source_linear_gradient,
fs_source_radial_gradient,
+ NULL
};
- const char *mask_sources[CAIRO_GL_SHADER_MASK_COUNT] = {
+ const char *mask_sources[CAIRO_GL_OPERAND_COUNT] = {
+ fs_mask_none,
fs_mask_constant,
fs_mask_texture,
fs_mask_texture_alpha,
fs_mask_linear_gradient,
fs_mask_radial_gradient,
- fs_mask_none,
- fs_mask_spans,
+ fs_mask_spans
};
const char *in_sources[CAIRO_GL_SHADER_IN_COUNT] = {
fs_in_normal,
@@ -855,6 +857,10 @@ _cairo_gl_get_program (cairo_gl_context_t *ctx,
char *fs_source;
cairo_status_t status;
+ assert (source < ARRAY_LENGTH (source_sources));
+ assert (source_sources[source] != NULL);
+ assert (mask < ARRAY_LENGTH (mask_sources));
+
program = _cairo_gl_select_program(ctx, source, mask, in);
if (program->program) {
*out_program = program;
@@ -893,23 +899,23 @@ _cairo_gl_get_program (cairo_gl_context_t *ctx,
if (unlikely (fs_source == NULL))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
- if (source == CAIRO_GL_SHADER_SOURCE_CONSTANT ||
- source == CAIRO_GL_SHADER_SOURCE_LINEAR_GRADIENT ||
- source == CAIRO_GL_SHADER_SOURCE_RADIAL_GRADIENT) {
- if (mask == CAIRO_GL_SHADER_MASK_SPANS)
+ if (source == CAIRO_GL_OPERAND_CONSTANT ||
+ source == CAIRO_GL_OPERAND_LINEAR_GRADIENT ||
+ source == CAIRO_GL_OPERAND_RADIAL_GRADIENT) {
+ if (mask == CAIRO_GL_OPERAND_SPANS)
vs = CAIRO_GL_VERTEX_SHADER_SPANS;
- else if (mask == CAIRO_GL_SHADER_MASK_CONSTANT ||
- mask == CAIRO_GL_SHADER_MASK_LINEAR_GRADIENT ||
- mask == CAIRO_GL_SHADER_MASK_RADIAL_GRADIENT)
+ else if (mask == CAIRO_GL_OPERAND_CONSTANT ||
+ mask == CAIRO_GL_OPERAND_LINEAR_GRADIENT ||
+ mask == CAIRO_GL_OPERAND_RADIAL_GRADIENT)
vs = CAIRO_GL_VERTEX_SHADER_EMPTY;
else
vs = CAIRO_GL_VERTEX_SHADER_MASK;
} else {
- if (mask == CAIRO_GL_SHADER_MASK_SPANS)
+ if (mask == CAIRO_GL_OPERAND_SPANS)
vs = CAIRO_GL_VERTEX_SHADER_SOURCE_SPANS;
- else if (mask == CAIRO_GL_SHADER_MASK_CONSTANT ||
- mask == CAIRO_GL_SHADER_MASK_LINEAR_GRADIENT ||
- mask == CAIRO_GL_SHADER_MASK_RADIAL_GRADIENT)
+ else if (mask == CAIRO_GL_OPERAND_CONSTANT ||
+ mask == CAIRO_GL_OPERAND_LINEAR_GRADIENT ||
+ mask == CAIRO_GL_OPERAND_RADIAL_GRADIENT)
vs = CAIRO_GL_VERTEX_SHADER_SOURCE;
else
vs = CAIRO_GL_VERTEX_SHADER_SOURCE_MASK;
@@ -928,13 +934,13 @@ _cairo_gl_get_program (cairo_gl_context_t *ctx,
return status;
_cairo_gl_use_program (ctx, program);
- if (source != CAIRO_GL_SHADER_SOURCE_CONSTANT) {
+ if (source != CAIRO_GL_OPERAND_CONSTANT) {
status = bind_texture_to_shader (ctx, program->program, "source_sampler", 0);
assert (!_cairo_status_is_error (status));
}
- if (mask != CAIRO_GL_SHADER_MASK_CONSTANT &&
- mask != CAIRO_GL_SHADER_MASK_SPANS &&
- mask != CAIRO_GL_SHADER_MASK_NONE) {
+ if (mask != CAIRO_GL_OPERAND_CONSTANT &&
+ mask != CAIRO_GL_OPERAND_SPANS &&
+ mask != CAIRO_GL_OPERAND_NONE) {
status = bind_texture_to_shader (ctx, program->program, "mask_sampler", 1);
assert (!_cairo_status_is_error (status));
}
diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c
index 2ea6717..ad80632 100644
--- a/src/cairo-gl-surface.c
+++ b/src/cairo-gl-surface.c
@@ -644,8 +644,8 @@ _cairo_gl_surface_draw_image (cairo_gl_surface_t *dst,
cairo_gl_shader_program_t *program;
status = _cairo_gl_get_program (ctx,
- CAIRO_GL_SHADER_SOURCE_TEXTURE,
- CAIRO_GL_SHADER_MASK_NONE,
+ CAIRO_GL_OPERAND_TEXTURE,
+ CAIRO_GL_OPERAND_NONE,
CAIRO_GL_SHADER_IN_NORMAL,
&program);
if (_cairo_status_is_error (status)) {
@@ -1141,7 +1141,7 @@ _cairo_gl_create_gradient_texture (const cairo_gl_context_t *ctx,
*/
static cairo_status_t
_cairo_gl_pattern_texture_setup (cairo_gl_context_t *ctx,
- cairo_gl_composite_operand_t *operand,
+ cairo_gl_operand_t *operand,
const cairo_pattern_t *src,
cairo_gl_surface_t *dst,
int src_x, int src_y,
@@ -1176,15 +1176,12 @@ _cairo_gl_pattern_texture_setup (cairo_gl_context_t *ctx,
assert (surface->base.backend == &_cairo_gl_surface_backend);
+ if (surface->base.content == CAIRO_CONTENT_ALPHA)
+ operand->type = CAIRO_GL_OPERAND_TEXTURE_ALPHA;
+ else
+ operand->type = CAIRO_GL_OPERAND_TEXTURE;
operand->operand.texture.surface = surface;
operand->operand.texture.tex = surface->tex;
- if (surface->base.content != CAIRO_CONTENT_ALPHA) {
- operand->source = CAIRO_GL_SHADER_SOURCE_TEXTURE;
- operand->mask = CAIRO_GL_SHADER_MASK_TEXTURE;
- } else {
- operand->source = CAIRO_GL_SHADER_SOURCE_TEXTURE_ALPHA;
- operand->mask = CAIRO_GL_SHADER_MASK_TEXTURE_ALPHA;
- }
/* Translate the matrix from
* (unnormalized src -> unnormalized src) to
* (unnormalized dst -> unnormalized src)
@@ -1218,12 +1215,10 @@ _cairo_gl_pattern_texture_setup (cairo_gl_context_t *ctx,
}
static cairo_status_t
-_cairo_gl_solid_operand_init (cairo_gl_composite_operand_t *operand,
+_cairo_gl_solid_operand_init (cairo_gl_operand_t *operand,
const cairo_color_t *color)
{
- operand->type = OPERAND_CONSTANT;
- operand->source = CAIRO_GL_SHADER_SOURCE_CONSTANT;
- operand->mask = CAIRO_GL_SHADER_MASK_CONSTANT;
+ operand->type = CAIRO_GL_OPERAND_CONSTANT;
operand->operand.constant.color[0] = color->red * color->alpha;
operand->operand.constant.color[1] = color->green * color->alpha;
operand->operand.constant.color[2] = color->blue * color->alpha;
@@ -1233,7 +1228,7 @@ _cairo_gl_solid_operand_init (cairo_gl_composite_operand_t *operand,
static cairo_status_t
_cairo_gl_gradient_operand_init(cairo_gl_context_t *ctx,
- cairo_gl_composite_operand_t *operand,
+ cairo_gl_operand_t *operand,
cairo_gl_surface_t *dst)
{
cairo_gradient_pattern_t *gradient = (cairo_gradient_pattern_t *)operand->pattern;
@@ -1272,9 +1267,7 @@ _cairo_gl_gradient_operand_init(cairo_gl_context_t *ctx,
operand->operand.linear.segment_x = x1 - x0;
operand->operand.linear.segment_y = y1 - y0;
- operand->type = OPERAND_LINEAR_GRADIENT;
- operand->source = CAIRO_GL_SHADER_SOURCE_LINEAR_GRADIENT;
- operand->mask = CAIRO_GL_SHADER_MASK_LINEAR_GRADIENT;
+ operand->type = CAIRO_GL_OPERAND_LINEAR_GRADIENT;
return CAIRO_STATUS_SUCCESS;
} else {
cairo_radial_pattern_t *radial = (cairo_radial_pattern_t *) gradient;
@@ -1310,9 +1303,7 @@ _cairo_gl_gradient_operand_init(cairo_gl_context_t *ctx,
operand->operand.radial.radius_0 = r0;
operand->operand.radial.radius_1 = r1;
- operand->type = OPERAND_RADIAL_GRADIENT;
- operand->source = CAIRO_GL_SHADER_SOURCE_RADIAL_GRADIENT;
- operand->mask = CAIRO_GL_SHADER_MASK_RADIAL_GRADIENT;
+ operand->type = CAIRO_GL_OPERAND_RADIAL_GRADIENT;
return CAIRO_STATUS_SUCCESS;
}
@@ -1321,7 +1312,7 @@ _cairo_gl_gradient_operand_init(cairo_gl_context_t *ctx,
cairo_int_status_t
_cairo_gl_operand_init (cairo_gl_context_t *ctx,
- cairo_gl_composite_operand_t *operand,
+ cairo_gl_operand_t *operand,
const cairo_pattern_t *pattern,
cairo_gl_surface_t *dst,
int src_x, int src_y,
@@ -1346,7 +1337,6 @@ _cairo_gl_operand_init (cairo_gl_context_t *ctx,
default:
case CAIRO_PATTERN_TYPE_SURFACE:
- operand->type = OPERAND_TEXTURE;
return _cairo_gl_pattern_texture_setup (ctx, operand,
pattern, dst,
src_x, src_y,
@@ -1356,18 +1346,19 @@ _cairo_gl_operand_init (cairo_gl_context_t *ctx,
}
void
-_cairo_gl_operand_destroy (cairo_gl_composite_operand_t *operand)
+_cairo_gl_operand_destroy (cairo_gl_operand_t *operand)
{
switch (operand->type) {
- case OPERAND_CONSTANT:
+ case CAIRO_GL_OPERAND_CONSTANT:
break;
- case OPERAND_LINEAR_GRADIENT:
+ case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
glDeleteTextures (1, &operand->operand.linear.tex);
break;
- case OPERAND_RADIAL_GRADIENT:
+ case CAIRO_GL_OPERAND_RADIAL_GRADIENT:
glDeleteTextures (1, &operand->operand.radial.tex);
break;
- case OPERAND_TEXTURE:
+ case CAIRO_GL_OPERAND_TEXTURE:
+ case CAIRO_GL_OPERAND_TEXTURE_ALPHA:
if (operand->operand.texture.surface != NULL) {
cairo_gl_surface_t *surface = operand->operand.texture.surface;
@@ -1376,6 +1367,12 @@ _cairo_gl_operand_destroy (cairo_gl_composite_operand_t *operand)
&operand->operand.texture.attributes);
}
break;
+ default:
+ case CAIRO_GL_OPERAND_COUNT:
+ ASSERT_NOT_REACHED;
+ case CAIRO_GL_OPERAND_NONE:
+ case CAIRO_GL_OPERAND_SPANS:
+ break;
}
}
@@ -1448,11 +1445,12 @@ _cairo_gl_set_src_operand (cairo_gl_context_t *ctx,
src_attributes = &setup->src.operand.texture.attributes;
switch (setup->src.type) {
- case OPERAND_CONSTANT:
+ case CAIRO_GL_OPERAND_CONSTANT:
_cairo_gl_set_tex_combine_constant_color (ctx, setup, 0,
setup->src.operand.constant.color);
break;
- case OPERAND_TEXTURE:
+ case CAIRO_GL_OPERAND_TEXTURE:
+ case CAIRO_GL_OPERAND_TEXTURE_ALPHA:
_cairo_gl_set_texture_surface (0, setup->src.operand.texture.tex,
src_attributes, ctx->tex_target);
if (!setup->shader) {
@@ -1478,7 +1476,7 @@ _cairo_gl_set_src_operand (cairo_gl_context_t *ctx,
}
break;
- case OPERAND_LINEAR_GRADIENT:
+ case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
glActiveTexture (GL_TEXTURE0);
glBindTexture (GL_TEXTURE_1D, setup->src.operand.linear.tex);
glEnable (GL_TEXTURE_1D);
@@ -1495,7 +1493,7 @@ _cairo_gl_set_src_operand (cairo_gl_context_t *ctx,
assert (!_cairo_status_is_error (status));
break;
- case OPERAND_RADIAL_GRADIENT:
+ case CAIRO_GL_OPERAND_RADIAL_GRADIENT:
glActiveTexture (GL_TEXTURE0);
glBindTexture (GL_TEXTURE_1D, setup->src.operand.linear.tex);
glEnable (GL_TEXTURE_1D);
@@ -1521,6 +1519,12 @@ _cairo_gl_set_src_operand (cairo_gl_context_t *ctx,
setup->src.operand.radial.radius_1);
assert (!_cairo_status_is_error (status));
break;
+ default:
+ case CAIRO_GL_OPERAND_COUNT:
+ ASSERT_NOT_REACHED;
+ case CAIRO_GL_OPERAND_NONE:
+ case CAIRO_GL_OPERAND_SPANS:
+ break;
}
}
@@ -1538,7 +1542,7 @@ _cairo_gl_set_src_alpha_operand (cairo_gl_context_t *ctx,
src_attributes = &setup->src.operand.texture.attributes;
switch (setup->src.type) {
- case OPERAND_CONSTANT:
+ case CAIRO_GL_OPERAND_CONSTANT:
constant_color[0] = setup->src.operand.constant.color[3];
constant_color[1] = setup->src.operand.constant.color[3];
constant_color[2] = setup->src.operand.constant.color[3];
@@ -1546,7 +1550,8 @@ _cairo_gl_set_src_alpha_operand (cairo_gl_context_t *ctx,
_cairo_gl_set_tex_combine_constant_color (ctx, setup, 0,
constant_color);
break;
- case OPERAND_TEXTURE:
+ case CAIRO_GL_OPERAND_TEXTURE:
+ case CAIRO_GL_OPERAND_TEXTURE_ALPHA:
_cairo_gl_set_texture_surface (0, setup->src.operand.texture.tex,
src_attributes, ctx->tex_target);
if (!setup->shader) {
@@ -1561,9 +1566,14 @@ _cairo_gl_set_src_alpha_operand (cairo_gl_context_t *ctx,
glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
}
break;
- case OPERAND_LINEAR_GRADIENT:
- case OPERAND_RADIAL_GRADIENT:
- assert(0);
+ case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
+ case CAIRO_GL_OPERAND_RADIAL_GRADIENT:
+ case CAIRO_GL_OPERAND_NONE:
+ case CAIRO_GL_OPERAND_SPANS:
+ case CAIRO_GL_OPERAND_COUNT:
+ default:
+ ASSERT_NOT_REACHED;
+ break;
}
}
@@ -1648,7 +1658,7 @@ _cairo_gl_set_component_alpha_mask_operand (cairo_gl_context_t *ctx,
}
switch (setup->mask.type) {
- case OPERAND_CONSTANT:
+ case CAIRO_GL_OPERAND_CONSTANT:
/* Have to have a dummy texture bound in order to use the combiner unit. */
if (setup->shader) {
cairo_status_t status;
@@ -1673,7 +1683,8 @@ _cairo_gl_set_component_alpha_mask_operand (cairo_gl_context_t *ctx,
glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
}
break;
- case OPERAND_TEXTURE:
+ case CAIRO_GL_OPERAND_TEXTURE:
+ case CAIRO_GL_OPERAND_TEXTURE_ALPHA:
_cairo_gl_set_texture_surface (1, setup->mask.operand.texture.tex,
mask_attributes, ctx->tex_target);
if (!setup->shader) {
@@ -1695,13 +1706,19 @@ _cairo_gl_set_component_alpha_mask_operand (cairo_gl_context_t *ctx,
}
break;
- case OPERAND_LINEAR_GRADIENT:
+ case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
_cairo_gl_set_linear_gradient_mask_operand (ctx, setup);
break;
- case OPERAND_RADIAL_GRADIENT:
+ case CAIRO_GL_OPERAND_RADIAL_GRADIENT:
_cairo_gl_set_radial_gradient_mask_operand (ctx, setup);
break;
+ case CAIRO_GL_OPERAND_NONE:
+ case CAIRO_GL_OPERAND_SPANS:
+ case CAIRO_GL_OPERAND_COUNT:
+ default:
+ ASSERT_NOT_REACHED;
+ break;
}
}
@@ -1820,16 +1837,16 @@ _cairo_gl_surface_composite_component_alpha (cairo_operator_t op,
ca_source_alpha_program = NULL;
status = _cairo_gl_get_program (ctx,
- setup.src.source,
- setup.mask.mask,
+ setup.src.type,
+ setup.mask.type,
CAIRO_GL_SHADER_IN_CA_SOURCE,
&ca_source_program);
if (_cairo_status_is_error (status))
goto CLEANUP;
status = _cairo_gl_get_program (ctx,
- setup.src.source,
- setup.mask.mask,
+ setup.src.type,
+ setup.mask.type,
CAIRO_GL_SHADER_IN_CA_SOURCE_ALPHA,
&ca_source_alpha_program);
if (_cairo_status_is_error (status))
@@ -1886,7 +1903,8 @@ _cairo_gl_surface_composite_component_alpha (cairo_operator_t op,
glVertexPointer (2, GL_FLOAT, sizeof (GLfloat) * 2, vertices);
glEnableClientState (GL_VERTEX_ARRAY);
- if (setup.src.type == OPERAND_TEXTURE) {
+ if (setup.src.type == CAIRO_GL_OPERAND_TEXTURE ||
+ setup.src.type == CAIRO_GL_OPERAND_TEXTURE_ALPHA) {
for (i = 0; i < num_vertices; i++) {
double s, t;
@@ -1902,7 +1920,8 @@ _cairo_gl_surface_composite_component_alpha (cairo_operator_t op,
glEnableClientState (GL_TEXTURE_COORD_ARRAY);
}
- if (setup.mask.type == OPERAND_TEXTURE) {
+ if (setup.mask.type == CAIRO_GL_OPERAND_TEXTURE ||
+ setup.mask.type == CAIRO_GL_OPERAND_TEXTURE_ALPHA) {
for (i = 0; i < num_vertices; i++) {
double s, t;
@@ -2040,14 +2059,14 @@ _cairo_gl_surface_composite (cairo_operator_t op,
}
mask_attributes = &setup.mask.operand.texture.attributes;
} else {
- setup.mask.mask = CAIRO_GL_SHADER_MASK_NONE;
+ setup.mask.type = CAIRO_GL_OPERAND_NONE;
}
/* We'll fall back to fixed function instead. */
setup.shader = NULL;
status = _cairo_gl_get_program (ctx,
- setup.src.source,
- setup.mask.mask,
+ setup.src.type,
+ setup.mask.type,
CAIRO_GL_SHADER_IN_NORMAL,
&setup.shader);
if (_cairo_status_is_error (status))
@@ -2063,12 +2082,13 @@ _cairo_gl_surface_composite (cairo_operator_t op,
if (mask != NULL) {
switch (setup.mask.type) {
- case OPERAND_CONSTANT:
+ case CAIRO_GL_OPERAND_CONSTANT:
_cairo_gl_set_tex_combine_constant_color (ctx, &setup, 1,
setup.mask.operand.constant.color);
break;
- case OPERAND_TEXTURE:
+ case CAIRO_GL_OPERAND_TEXTURE:
+ case CAIRO_GL_OPERAND_TEXTURE_ALPHA:
_cairo_gl_set_texture_surface (1, setup.mask.operand.texture.tex,
mask_attributes, ctx->tex_target);
@@ -2089,12 +2109,18 @@ _cairo_gl_surface_composite (cairo_operator_t op,
glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
}
break;
- case OPERAND_LINEAR_GRADIENT:
+ case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
_cairo_gl_set_linear_gradient_mask_operand (ctx, &setup);
break;
- case OPERAND_RADIAL_GRADIENT:
+ case CAIRO_GL_OPERAND_RADIAL_GRADIENT:
_cairo_gl_set_radial_gradient_mask_operand (ctx, &setup);
break;
+ case CAIRO_GL_OPERAND_NONE:
+ case CAIRO_GL_OPERAND_SPANS:
+ case CAIRO_GL_OPERAND_COUNT:
+ default:
+ ASSERT_NOT_REACHED;
+ break;
}
}
@@ -2145,7 +2171,8 @@ _cairo_gl_surface_composite (cairo_operator_t op,
glVertexPointer (2, GL_FLOAT, sizeof (GLfloat) * 2, vertices);
glEnableClientState (GL_VERTEX_ARRAY);
- if (setup.src.type == OPERAND_TEXTURE) {
+ if (setup.src.type == CAIRO_GL_OPERAND_TEXTURE ||
+ setup.src.type == CAIRO_GL_OPERAND_TEXTURE_ALPHA) {
for (i = 0; i < num_vertices; i++) {
double s, t;
@@ -2162,7 +2189,8 @@ _cairo_gl_surface_composite (cairo_operator_t op,
}
if (mask != NULL) {
- if (setup.mask.type == OPERAND_TEXTURE) {
+ if (setup.mask.type == CAIRO_GL_OPERAND_TEXTURE ||
+ setup.mask.type == CAIRO_GL_OPERAND_TEXTURE_ALPHA) {
for (i = 0; i < num_vertices; i++) {
double s, t;
@@ -2530,7 +2558,8 @@ _cairo_gl_span_renderer_get_vbo (cairo_gl_surface_span_renderer_t *renderer,
renderer->vbo_size = 16384;
glBindBufferARB (GL_ARRAY_BUFFER_ARB, renderer->ctx->vbo);
- if (renderer->setup.src.type == OPERAND_TEXTURE)
+ if (renderer->setup.src.type == CAIRO_GL_OPERAND_TEXTURE ||
+ renderer->setup.src.type == CAIRO_GL_OPERAND_TEXTURE_ALPHA)
renderer->vertex_size = 4 * sizeof (float) + sizeof (uint32_t);
else
renderer->vertex_size = 2 * sizeof (float) + sizeof (uint32_t);
@@ -2542,7 +2571,8 @@ _cairo_gl_span_renderer_get_vbo (cairo_gl_surface_span_renderer_t *renderer,
(void *) (uintptr_t) (2 * sizeof (float)));
glEnableClientState (GL_COLOR_ARRAY);
- if (renderer->setup.src.type == OPERAND_TEXTURE) {
+ if (renderer->setup.src.type == CAIRO_GL_OPERAND_TEXTURE ||
+ renderer->setup.src.type == CAIRO_GL_OPERAND_TEXTURE_ALPHA) {
glClientActiveTexture (GL_TEXTURE0);
glTexCoordPointer (2, GL_FLOAT, renderer->vertex_size,
(void *) (uintptr_t) (2 * sizeof (float) +
@@ -2583,7 +2613,8 @@ _cairo_gl_emit_span_vertex (cairo_gl_surface_span_renderer_t *renderer,
vertices[v++] = dst_x + BIAS;
vertices[v++] = dst_y + BIAS;
vertices[v++] = int_as_float (alpha << 24);
- if (renderer->setup.src.type == OPERAND_TEXTURE) {
+ if (renderer->setup.src.type == CAIRO_GL_OPERAND_TEXTURE ||
+ renderer->setup.src.type == CAIRO_GL_OPERAND_TEXTURE_ALPHA) {
double s, t;
s = dst_x + BIAS;
@@ -2795,8 +2826,8 @@ _cairo_gl_surface_create_span_renderer (cairo_operator_t op,
_cairo_gl_context_set_destination (renderer->ctx, dst);
status = _cairo_gl_get_program (renderer->ctx,
- renderer->setup.src.source,
- CAIRO_GL_SHADER_MASK_SPANS,
+ renderer->setup.src.type,
+ CAIRO_GL_OPERAND_SPANS,
CAIRO_GL_SHADER_IN_NORMAL,
&renderer->setup.shader);
if (_cairo_status_is_error (status)) {
commit 5149bb87d7b547766ce6ff4976217454adbab562
Author: Benjamin Otte <otte at redhat.com>
Date: Tue May 11 21:35:13 2010 +0200
gl: s/_cairo_gl_set_destination/_cairo_gl_context_set_destination/
It's an operation on the context, so name it accordingly
diff --git a/src/cairo-gl-device.c b/src/cairo-gl-device.c
index 7455f96..2dd225b 100644
--- a/src/cairo-gl-device.c
+++ b/src/cairo-gl-device.c
@@ -182,7 +182,7 @@ _cairo_gl_context_init (cairo_gl_context_t *ctx)
}
void
-_cairo_gl_set_destination (cairo_gl_context_t *ctx,
+_cairo_gl_context_set_destination (cairo_gl_context_t *ctx,
cairo_gl_surface_t *surface)
{
if (ctx->current_target != surface) {
diff --git a/src/cairo-gl-glyphs.c b/src/cairo-gl-glyphs.c
index 217f4fb..07bd698 100644
--- a/src/cairo-gl-glyphs.c
+++ b/src/cairo-gl-glyphs.c
@@ -494,7 +494,7 @@ _render_glyphs (cairo_gl_surface_t *dst,
return status;
}
- _cairo_gl_set_destination (ctx, dst);
+ _cairo_gl_context_set_destination (ctx, dst);
_cairo_scaled_font_freeze_cache (scaled_font);
if (! _cairo_gl_surface_owns_font (dst, scaled_font)) {
diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h
index 93aa830..777f12c 100644
--- a/src/cairo-gl-private.h
+++ b/src/cairo-gl-private.h
@@ -279,7 +279,7 @@ _cairo_gl_context_acquire (cairo_device_t *device,
} while (0)
cairo_private void
-_cairo_gl_set_destination (cairo_gl_context_t *ctx, cairo_gl_surface_t *surface);
+_cairo_gl_context_set_destination (cairo_gl_context_t *ctx, cairo_gl_surface_t *surface);
cairo_private cairo_bool_t
_cairo_gl_operator_is_supported (cairo_operator_t op);
diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c
index cf9547c..2ea6717 100644
--- a/src/cairo-gl-surface.c
+++ b/src/cairo-gl-surface.c
@@ -396,7 +396,7 @@ _cairo_gl_surface_clear (cairo_gl_surface_t *surface)
if (unlikely (status))
return status;
- _cairo_gl_set_destination (ctx, surface);
+ _cairo_gl_context_set_destination (ctx, surface);
if (surface->base.content == CAIRO_CONTENT_COLOR)
glClearColor (0.0, 0.0, 0.0, 1.0);
else
@@ -660,7 +660,7 @@ _cairo_gl_surface_draw_image (cairo_gl_surface_t *dst,
status = CAIRO_STATUS_SUCCESS;
- _cairo_gl_set_destination (ctx, dst);
+ _cairo_gl_context_set_destination (ctx, dst);
glGenTextures (1, &tex);
glActiveTexture (GL_TEXTURE0);
@@ -779,7 +779,7 @@ _cairo_gl_surface_get_image (cairo_gl_surface_t *surface,
status = _cairo_gl_context_acquire (surface->base.device, &ctx);
if (unlikely (status))
return status;
- _cairo_gl_set_destination (ctx, surface);
+ _cairo_gl_context_set_destination (ctx, surface);
glPixelStorei (GL_PACK_ALIGNMENT, 1);
glPixelStorei (GL_PACK_ROW_LENGTH, image->stride / cpp);
@@ -1837,7 +1837,7 @@ _cairo_gl_surface_composite_component_alpha (cairo_operator_t op,
status = CAIRO_STATUS_SUCCESS;
- _cairo_gl_set_destination (ctx, dst);
+ _cairo_gl_context_set_destination (ctx, dst);
if (clip_region != NULL) {
int num_rectangles;
@@ -2055,7 +2055,7 @@ _cairo_gl_surface_composite (cairo_operator_t op,
status = CAIRO_STATUS_SUCCESS;
- _cairo_gl_set_destination (ctx, dst);
+ _cairo_gl_context_set_destination (ctx, dst);
_cairo_gl_set_operator (dst, op, FALSE);
_cairo_gl_use_program (ctx, setup.shader);
@@ -2291,7 +2291,7 @@ _cairo_gl_surface_fill_rectangles_fixed (void *abstract_surface,
if (unlikely (status))
return status;
- _cairo_gl_set_destination (ctx, surface);
+ _cairo_gl_context_set_destination (ctx, surface);
_cairo_gl_set_operator (surface, op, FALSE);
if (num_rects > N_STACK_RECTS) {
@@ -2404,7 +2404,7 @@ _cairo_gl_surface_fill_rectangles_glsl (void *abstract_surface,
_cairo_gl_use_program (ctx, &ctx->fill_rectangles_shader);
- _cairo_gl_set_destination (ctx, surface);
+ _cairo_gl_context_set_destination (ctx, surface);
_cairo_gl_set_operator (surface, op, FALSE);
status = bind_vec4_to_shader (ctx,
@@ -2792,7 +2792,7 @@ _cairo_gl_surface_create_span_renderer (cairo_operator_t op,
return _cairo_span_renderer_create_in_error (status);
}
- _cairo_gl_set_destination (renderer->ctx, dst);
+ _cairo_gl_context_set_destination (renderer->ctx, dst);
status = _cairo_gl_get_program (renderer->ctx,
renderer->setup.src.source,
commit 9f34e403f38192d711304fbde4dedbaa8e15fd6e
Author: Benjamin Otte <otte at redhat.com>
Date: Tue May 11 13:15:16 2010 +0200
gl: Share vertex shaders
Previously, we created a new vertex shader for every shader program we
used. Now the code shares identical vertex shaders between programs.
diff --git a/src/cairo-gl-device.c b/src/cairo-gl-device.c
index ab1010d..7455f96 100644
--- a/src/cairo-gl-device.c
+++ b/src/cairo-gl-device.c
@@ -58,6 +58,21 @@ _gl_unlock (void *device)
}
static void
+_gl_finish (void *device)
+{
+ cairo_gl_context_t *ctx;
+ int i;
+
+ if (_cairo_gl_context_acquire (device, &ctx) == CAIRO_STATUS_SUCCESS) {
+ for (i = 0; i < CAIRO_GL_VERTEX_SHADER_COUNT; i++) {
+ destroy_shader (ctx, ctx->vertex_shaders[i]);
+ }
+
+ _cairo_gl_context_release (ctx);
+ }
+}
+
+static void
_gl_destroy (void *device)
{
cairo_gl_context_t *ctx = device;
@@ -90,7 +105,7 @@ static const cairo_device_backend_t _cairo_gl_device_backend = {
_gl_unlock,
NULL, /* flush */
- NULL, /* finish */
+ _gl_finish,
_gl_destroy,
};
diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h
index 83836e7..93aa830 100644
--- a/src/cairo-gl-private.h
+++ b/src/cairo-gl-private.h
@@ -83,7 +83,6 @@ typedef struct cairo_gl_glyph_cache {
typedef struct cairo_gl_shader_impl cairo_gl_shader_impl_t;
typedef struct cairo_gl_shader_program {
- GLuint vertex_shader;
GLuint fragment_shader;
GLuint program;
cairo_bool_t build_failure;
@@ -95,7 +94,8 @@ typedef enum cairo_gl_shader_source {
CAIRO_GL_SHADER_SOURCE_TEXTURE_ALPHA,
CAIRO_GL_SHADER_SOURCE_LINEAR_GRADIENT,
CAIRO_GL_SHADER_SOURCE_RADIAL_GRADIENT,
- CAIRO_GL_SHADER_SOURCE_COUNT,
+
+ CAIRO_GL_SHADER_SOURCE_COUNT
} cairo_gl_shader_source_t;
typedef enum cairo_gl_shader_mask {
@@ -106,16 +106,29 @@ typedef enum cairo_gl_shader_mask {
CAIRO_GL_SHADER_MASK_RADIAL_GRADIENT,
CAIRO_GL_SHADER_MASK_NONE,
CAIRO_GL_SHADER_MASK_SPANS,
- CAIRO_GL_SHADER_MASK_COUNT,
+
+ CAIRO_GL_SHADER_MASK_COUNT
} cairo_gl_shader_mask_t;
typedef enum cairo_gl_shader_in {
CAIRO_GL_SHADER_IN_NORMAL,
CAIRO_GL_SHADER_IN_CA_SOURCE,
CAIRO_GL_SHADER_IN_CA_SOURCE_ALPHA,
- CAIRO_GL_SHADER_IN_COUNT,
+
+ CAIRO_GL_SHADER_IN_COUNT
} cairo_gl_shader_in_t;
+typedef enum cairo_gl_vertex_shader {
+ CAIRO_GL_VERTEX_SHADER_EMPTY,
+ CAIRO_GL_VERTEX_SHADER_SOURCE,
+ CAIRO_GL_VERTEX_SHADER_MASK,
+ CAIRO_GL_VERTEX_SHADER_SOURCE_MASK,
+ CAIRO_GL_VERTEX_SHADER_SPANS,
+ CAIRO_GL_VERTEX_SHADER_SOURCE_SPANS,
+
+ CAIRO_GL_VERTEX_SHADER_COUNT
+} cairo_gl_vertex_shader_t;
+
typedef struct _cairo_gl_context {
cairo_device_t base;
@@ -129,6 +142,7 @@ typedef struct _cairo_gl_context {
const cairo_gl_shader_impl_t *shader_impl;
+ GLuint vertex_shaders[CAIRO_GL_VERTEX_SHADER_COUNT];
cairo_gl_shader_program_t fill_rectangles_shader;
cairo_gl_shader_program_t shaders[CAIRO_GL_SHADER_SOURCE_COUNT]
[CAIRO_GL_SHADER_MASK_COUNT]
@@ -330,6 +344,9 @@ cairo_private void
_cairo_gl_context_init_shaders (cairo_gl_context_t *ctx);
cairo_private void
+destroy_shader (cairo_gl_context_t *ctx, GLuint shader);
+
+cairo_private void
init_shader_program (cairo_gl_shader_program_t *program);
cairo_private void
@@ -339,7 +356,7 @@ destroy_shader_program (cairo_gl_context_t *ctx,
cairo_private cairo_status_t
create_shader_program (cairo_gl_context_t *ctx,
cairo_gl_shader_program_t *program,
- const char *vertex_text,
+ cairo_gl_vertex_shader_t vertex_shader,
const char *fragment_text);
cairo_private cairo_status_t
diff --git a/src/cairo-gl-shaders.c b/src/cairo-gl-shaders.c
index 8aa464e..e454278 100644
--- a/src/cairo-gl-shaders.c
+++ b/src/cairo-gl-shaders.c
@@ -43,7 +43,10 @@ typedef struct cairo_gl_shader_impl {
(*link_shader) (GLuint *program, GLuint vert, GLuint frag);
void
- (*destroy_shader_program) (cairo_gl_shader_program_t *program);
+ (*destroy_shader) (GLuint shader);
+
+ void
+ (*destroy_program) (GLuint program);
cairo_status_t
(*bind_float_to_shader) (GLuint program, const char *name,
@@ -144,14 +147,15 @@ link_shader_arb (GLuint *program, GLuint vert, GLuint frag)
}
static void
-destroy_shader_program_arb (cairo_gl_shader_program_t *program)
+destroy_shader_arb (GLuint shader)
{
- if (program->vertex_shader)
- glDeleteObjectARB (program->vertex_shader);
- if (program->fragment_shader)
- glDeleteObjectARB (program->fragment_shader);
- if (program->program)
- glDeleteObjectARB (program->program);
+ glDeleteObjectARB (shader);
+}
+
+static void
+destroy_program_arb (GLuint shader)
+{
+ glDeleteObjectARB (shader);
}
static cairo_status_t
@@ -305,11 +309,15 @@ link_shader_core_2_0 (GLuint *program, GLuint vert, GLuint frag)
}
static void
-destroy_shader_program_core_2_0 (cairo_gl_shader_program_t *program)
+destroy_shader_core_2_0 (GLuint shader)
+{
+ glDeleteShader (shader);
+}
+
+static void
+destroy_program_core_2_0 (GLuint shader)
{
- glDeleteShader (program->vertex_shader);
- glDeleteShader (program->fragment_shader);
- glDeleteProgram (program->program);
+ glDeleteProgram (shader);
}
static cairo_status_t
@@ -396,7 +404,8 @@ use_program_core_2_0 (cairo_gl_shader_program_t *program)
static const cairo_gl_shader_impl_t shader_impl_core_2_0 = {
compile_shader_core_2_0,
link_shader_core_2_0,
- destroy_shader_program_core_2_0,
+ destroy_shader_core_2_0,
+ destroy_program_core_2_0,
bind_float_to_shader_core_2_0,
bind_vec2_to_shader_core_2_0,
bind_vec3_to_shader_core_2_0,
@@ -409,7 +418,8 @@ static const cairo_gl_shader_impl_t shader_impl_core_2_0 = {
static const cairo_gl_shader_impl_t shader_impl_arb = {
compile_shader_arb,
link_shader_arb,
- destroy_shader_program_arb,
+ destroy_shader_arb,
+ destroy_program_arb,
bind_float_to_shader_arb,
bind_vec2_to_shader_arb,
bind_vec3_to_shader_arb,
@@ -432,32 +442,92 @@ _cairo_gl_context_init_shaders (cairo_gl_context_t *ctx)
} else {
ctx->shader_impl = NULL;
}
+
+ memset (ctx->vertex_shaders, 0, sizeof (ctx->vertex_shaders));
}
void
init_shader_program (cairo_gl_shader_program_t *program)
{
- program->vertex_shader = 0;
program->fragment_shader = 0;
program->program = 0;
program->build_failure = FALSE;
}
void
+destroy_shader (cairo_gl_context_t *ctx, GLuint shader)
+{
+ if (shader)
+ ctx->shader_impl->destroy_shader (shader);
+}
+
+void
destroy_shader_program (cairo_gl_context_t *ctx,
cairo_gl_shader_program_t *program)
{
- return ctx->shader_impl->destroy_shader_program (program);
+ destroy_shader (ctx, program->fragment_shader);
+
+ if (program->program)
+ ctx->shader_impl->destroy_program (program->program);
}
+static const char *vs_sources[] = {
+[CAIRO_GL_VERTEX_SHADER_EMPTY] =
+ "void main()\n"
+ "{\n"
+ " gl_Position = ftransform();\n"
+ "}\n",
+[CAIRO_GL_VERTEX_SHADER_SOURCE] =
+ "varying vec2 source_texcoords;\n"
+ "void main()\n"
+ "{\n"
+ " gl_Position = ftransform();\n"
+ " source_texcoords = gl_MultiTexCoord0.xy;\n"
+ "}\n",
+[CAIRO_GL_VERTEX_SHADER_MASK] =
+ "varying vec2 mask_texcoords;\n"
+ "void main()\n"
+ "{\n"
+ " gl_Position = ftransform();\n"
+ " mask_texcoords = gl_MultiTexCoord1.xy;\n"
+ "}\n",
+[CAIRO_GL_VERTEX_SHADER_SOURCE_MASK] =
+ "varying vec2 source_texcoords;\n"
+ "varying vec2 mask_texcoords;\n"
+ "void main()\n"
+ "{\n"
+ " gl_Position = ftransform();\n"
+ " source_texcoords = gl_MultiTexCoord0.xy;\n"
+ " mask_texcoords = gl_MultiTexCoord1.xy;\n"
+ "}\n",
+[CAIRO_GL_VERTEX_SHADER_SPANS] =
+ "varying float coverage;\n"
+ "void main()\n"
+ "{\n"
+ " gl_Position = ftransform();\n"
+ " coverage = gl_Color.a;\n"
+ "}\n",
+[CAIRO_GL_VERTEX_SHADER_SOURCE_SPANS] =
+ "varying vec2 source_texcoords;\n"
+ "varying float coverage;\n"
+ "void main()\n"
+ "{\n"
+ " gl_Position = ftransform();\n"
+ " source_texcoords = gl_MultiTexCoord0.xy;\n"
+ " coverage = gl_Color.a;\n"
+ "}\n"
+};
+
cairo_status_t
create_shader_program (cairo_gl_context_t *ctx,
cairo_gl_shader_program_t *program,
- const char *vertex_text,
+ cairo_gl_vertex_shader_t vertex_shader,
const char *fragment_text)
{
cairo_status_t status;
+ assert (vertex_shader < ARRAY_LENGTH (vs_sources));
+
if (program->program != 0)
return CAIRO_STATUS_SUCCESS;
@@ -467,11 +537,13 @@ create_shader_program (cairo_gl_context_t *ctx,
if (ctx->shader_impl == NULL)
return CAIRO_INT_STATUS_UNSUPPORTED;
- status = ctx->shader_impl->compile_shader (&program->vertex_shader,
- GL_VERTEX_SHADER,
- vertex_text);
- if (unlikely (status))
- goto FAILURE;
+ if (ctx->vertex_shaders[vertex_shader] == 0) {
+ status = ctx->shader_impl->compile_shader (&ctx->vertex_shaders[vertex_shader],
+ GL_VERTEX_SHADER,
+ vs_sources[vertex_shader]);
+ if (unlikely (status))
+ goto FAILURE;
+ }
status = ctx->shader_impl->compile_shader (&program->fragment_shader,
GL_FRAGMENT_SHADER,
@@ -480,7 +552,7 @@ create_shader_program (cairo_gl_context_t *ctx,
goto FAILURE;
status = ctx->shader_impl->link_shader (&program->program,
- program->vertex_shader,
+ ctx->vertex_shaders[vertex_shader],
program->fragment_shader);
if (unlikely (status))
goto FAILURE;
@@ -489,7 +561,6 @@ create_shader_program (cairo_gl_context_t *ctx,
FAILURE:
destroy_shader_program (ctx, program);
- program->vertex_shader = 0;
program->fragment_shader = 0;
program->program = 0;
program->build_failure = TRUE;
@@ -555,50 +626,6 @@ _cairo_gl_use_program (cairo_gl_context_t *ctx,
ctx->shader_impl->use_program (program);
}
-static const char *vs_no_coords =
- "void main()\n"
- "{\n"
- " gl_Position = ftransform();\n"
- "}\n";
-static const char *vs_source_coords =
- "varying vec2 source_texcoords;\n"
- "void main()\n"
- "{\n"
- " gl_Position = ftransform();\n"
- " source_texcoords = gl_MultiTexCoord0.xy;\n"
- "}\n";
-static const char *vs_mask_coords =
- "varying vec2 mask_texcoords;\n"
- "void main()\n"
- "{\n"
- " gl_Position = ftransform();\n"
- " mask_texcoords = gl_MultiTexCoord1.xy;\n"
- "}\n";
-static const char *vs_source_mask_coords =
- "varying vec2 source_texcoords;\n"
- "varying vec2 mask_texcoords;\n"
- "void main()\n"
- "{\n"
- " gl_Position = ftransform();\n"
- " source_texcoords = gl_MultiTexCoord0.xy;\n"
- " mask_texcoords = gl_MultiTexCoord1.xy;\n"
- "}\n";
-static const char *vs_spans_no_coords =
- "varying float coverage;\n"
- "void main()\n"
- "{\n"
- " gl_Position = ftransform();\n"
- " coverage = gl_Color.a;\n"
- "}\n";
-static const char *vs_spans_source_coords =
- "varying vec2 source_texcoords;\n"
- "varying float coverage;\n"
- "void main()\n"
- "{\n"
- " gl_Position = ftransform();\n"
- " source_texcoords = gl_MultiTexCoord0.xy;\n"
- " coverage = gl_Color.a;\n"
- "}\n";
static const char *fs_source_constant =
"uniform vec4 constant_source;\n"
"vec4 get_source()\n"
@@ -824,7 +851,7 @@ _cairo_gl_get_program (cairo_gl_context_t *ctx,
};
cairo_gl_shader_program_t *program;
const char *source_source, *mask_source, *in_source;
- const char *vs_source;
+ cairo_gl_vertex_shader_t vs;
char *fs_source;
cairo_status_t status;
@@ -870,22 +897,22 @@ _cairo_gl_get_program (cairo_gl_context_t *ctx,
source == CAIRO_GL_SHADER_SOURCE_LINEAR_GRADIENT ||
source == CAIRO_GL_SHADER_SOURCE_RADIAL_GRADIENT) {
if (mask == CAIRO_GL_SHADER_MASK_SPANS)
- vs_source = vs_spans_no_coords;
+ vs = CAIRO_GL_VERTEX_SHADER_SPANS;
else if (mask == CAIRO_GL_SHADER_MASK_CONSTANT ||
mask == CAIRO_GL_SHADER_MASK_LINEAR_GRADIENT ||
mask == CAIRO_GL_SHADER_MASK_RADIAL_GRADIENT)
- vs_source = vs_no_coords;
+ vs = CAIRO_GL_VERTEX_SHADER_EMPTY;
else
- vs_source = vs_mask_coords;
+ vs = CAIRO_GL_VERTEX_SHADER_MASK;
} else {
if (mask == CAIRO_GL_SHADER_MASK_SPANS)
- vs_source = vs_spans_source_coords;
+ vs = CAIRO_GL_VERTEX_SHADER_SOURCE_SPANS;
else if (mask == CAIRO_GL_SHADER_MASK_CONSTANT ||
mask == CAIRO_GL_SHADER_MASK_LINEAR_GRADIENT ||
mask == CAIRO_GL_SHADER_MASK_RADIAL_GRADIENT)
- vs_source = vs_source_coords;
+ vs = CAIRO_GL_VERTEX_SHADER_SOURCE;
else
- vs_source = vs_source_mask_coords;
+ vs = CAIRO_GL_VERTEX_SHADER_SOURCE_MASK;
}
sprintf(fs_source, "%s%s%s", source_source, mask_source, in_source);
@@ -893,7 +920,7 @@ _cairo_gl_get_program (cairo_gl_context_t *ctx,
init_shader_program (program);
status = create_shader_program (ctx,
program,
- vs_source,
+ vs,
fs_source);
free (fs_source);
diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c
index 9b17a53..cf9547c 100644
--- a/src/cairo-gl-surface.c
+++ b/src/cairo-gl-surface.c
@@ -2367,11 +2367,6 @@ _cairo_gl_surface_fill_rectangles_glsl (void *abstract_surface,
cairo_gl_context_t *ctx;
int i;
GLfloat *vertices;
- static const char *fill_vs_source =
- "void main()\n"
- "{\n"
- " gl_Position = ftransform();\n"
- "}\n";
static const char *fill_fs_source =
"uniform vec4 color;\n"
"void main()\n"
@@ -2389,7 +2384,7 @@ _cairo_gl_surface_fill_rectangles_glsl (void *abstract_surface,
status = create_shader_program (ctx,
&ctx->fill_rectangles_shader,
- fill_vs_source,
+ CAIRO_GL_VERTEX_SHADER_EMPTY,
fill_fs_source);
if (unlikely (status)) {
_cairo_gl_context_release (ctx);
More information about the cairo-commit
mailing list