[cairo] [PATCH] [gl] Add shader support code for GL versions < 3.0.
Zach Laine
whatwasthataddress at gmail.com
Thu Jan 14 09:49:04 PST 2010
On Wed, Jan 13, 2010 at 6:08 PM, Eric Anholt <eric at anholt.net> wrote:
> Ultimately, we want all of our paths to use shaders when they are
> exposed -- it brings us closer to GL 3.0 compatibility and it should
> reduce the work that GL drivers have to do per operation to compute
> the required hardware state.
[snip]
I had just finished working on this before I saw Eric's patch above,
so there are conflicts with it. If people like it in principle, I can
easily modify Eric's patch to work with it.
=============
Adds cairo_gl_shader_program_t, and functions to manipulate same. Multiple GL
entry points for shaders are provided -- one for the pre-GL 2.0 extenstions
entry points, and one for GL 2.0. This code is well tested, but currently
unused in the GL backend.
---
diff --git a/src/Makefile.sources b/src/Makefile.sources
index 1e04ed2..b94516f 100644
--- a/src/Makefile.sources
+++ b/src/Makefile.sources
@@ -279,7 +279,7 @@ cairo_beos_headers = cairo-beos.h
cairo_gl_headers = cairo-gl.h
cairo_gl_private = cairo-gl-private.h
-cairo_gl_sources = cairo-gl-surface.c cairo-gl-glyphs.c
+cairo_gl_sources = cairo-gl-surface.c cairo-gl-glyphs.c cairo-gl-shader.c
cairo_glx_sources += cairo-glx-context.c
cairo_eagle_sources += cairo-eagle-context.c
diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h
index 79145cf..c9fd5cf 100644
--- a/src/cairo-gl-private.h
+++ b/src/cairo-gl-private.h
@@ -34,6 +34,7 @@
* Contributor(s):
* Carl Worth <cworth at cworth.org>
* Chris Wilson <chris at chris-wilson.co.uk>
+ * T. Zachary Laine <whatwasthataddress at gmail.com>
*/
#ifndef CAIRO_GL_PRIVATE_H
@@ -79,6 +80,13 @@ typedef struct cairo_gl_glyph_cache {
unsigned int width, height;
} cairo_gl_glyph_cache_t;
+typedef struct cairo_gl_shader_program {
+ GLuint vertex_shader;
+ GLuint fragment_shader;
+ GLuint program;
+ cairo_bool_t build_failure;
+} cairo_gl_shader_program_t;
+
struct _cairo_gl_context {
cairo_reference_count_t ref_count;
cairo_status_t status;
@@ -211,6 +219,47 @@ _cairo_gl_y_flip (cairo_gl_surface_t *surface, int y)
return (surface->height - 1) - y;
}
+void
+init_shader_program (cairo_gl_shader_program_t *program);
+
+void
+destroy_shader_program (cairo_gl_shader_program_t *program);
+
+cairo_status_t
+create_shader_program (cairo_gl_shader_program_t *program,
+ const char *vertex_text,
+ const char *fragment_text);
+
+cairo_status_t
+create_linear_gradient_shader_program (cairo_gl_shader_program_t *program);
+
+cairo_status_t
+create_radial_gradient_shader_program (cairo_gl_shader_program_t *program);
+
+cairo_status_t
+bind_float_to_shader (GLuint program, const char *name,
+ float value);
+
+cairo_status_t
+bind_vec2_to_shader (GLuint program, const char *name,
+ float value0, float value1);
+
+cairo_status_t
+bind_vec3_to_shader (GLuint program, const char *name,
+ float value0, float value1,
+ float value2);
+
+cairo_status_t
+bind_vec4_to_shader (GLuint program, const char *name,
+ float value0, float value1,
+ float value2, float value3);
+
+cairo_status_t
+bind_matrix_to_shader (GLuint program, const char *name, cairo_matrix_t* m);
+
+cairo_status_t
+bind_texture_to_shader (GLuint program, const char *name, GLuint tex_unit);
+
slim_hidden_proto (cairo_gl_surface_create);
#endif /* CAIRO_GL_PRIVATE_H */
diff --git a/src/cairo-gl-shader.c b/src/cairo-gl-shader.c
new file mode 100644
index 0000000..52f43f3
--- /dev/null
+++ b/src/cairo-gl-shader.c
@@ -0,0 +1,653 @@
+/* cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2009 T. Zachary Laine
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 T. Zachary Laine.
+ */
+
+#include "cairo-gl-private.h"
+
+typedef struct _shader_impl {
+ cairo_status_t
+ (*compile_shader) (GLuint *shader, GLenum type, const char *text);
+
+ cairo_status_t
+ (*link_shader) (GLuint *program, GLuint vert, GLuint frag);
+
+ void
+ (*destroy_shader_program) (cairo_gl_shader_program_t *program);
+
+ cairo_status_t
+ (*create_linear_gradient_shader_program)
(cairo_gl_shader_program_t *program);
+
+ cairo_status_t
+ (*create_radial_gradient_shader_program)
(cairo_gl_shader_program_t *program);
+
+ cairo_status_t
+ (*bind_float_to_shader) (GLuint program, const char *name,
+ float value);
+
+ cairo_status_t
+ (*bind_vec2_to_shader) (GLuint program, const char *name,
+ float value0, float value1);
+
+ cairo_status_t
+ (*bind_vec3_to_shader) (GLuint program, const char *name,
+ float value0, float value1,
+ float value2);
+
+ cairo_status_t
+ (*bind_vec4_to_shader) (GLuint program, const char *name,
+ float value0, float value1,
+ float value2, float value3);
+
+ cairo_status_t
+ (*bind_matrix_to_shader) (GLuint program, const char *name,
cairo_matrix_t* m);
+
+ cairo_status_t
+ (*bind_texture_to_shader) (GLuint program, const char *name,
GLuint tex_unit);
+
+ GLenum
+ (*vertex_enumerator) (void);
+
+ GLenum
+ (*fragment_enumerator) (void);
+} shader_impl_t;
+
+static const shader_impl_t*
+get_impl (void);
+
+static const char * const minimal_vert_text_110 =
+ "#version 110\n"
+ "\n"
+ "void main ()\n"
+ "{ gl_Position = ftransform(); }\n";
+
+/* This fragment shader was adapted from Argiris Kirtzidis' cairo-gral
+ * library, found at git://github.com/akyrtzi/cairo-gral.git. Argiris' shader
+ * was adapted from the original algorithm in pixman.
+ */
+static const char * const radial_gradient_frag_text_110 =
+ "#version 110\n"
+ "\n"
+ "uniform sampler1D tex;\n"
+ "uniform mat4 matrix;\n"
+ "uniform vec2 circle_1;\n"
+ "uniform float radius_0;\n"
+ "uniform float radius_1;\n"
+ "uniform float first_offset;\n"
+ "uniform float last_offset;\n"
+ "\n"
+ "void main ()\n"
+ "{\n"
+ " vec2 pos = (matrix * vec4 (gl_FragCoord.xy, 0.0, 1.0)).xy;\n"
+ " \n"
+ " float dr = radius_1 - radius_0;\n"
+ " float dot_circle_1 = dot (circle_1, circle_1);\n"
+ " float dot_pos_circle_1 = dot (pos, circle_1);\n"
+ " \n"
+ " float A = dot_circle_1 - dr * dr;\n"
+ " float B = -2.0 * (dot_pos_circle_1 + radius_0 * dr);\n"
+ " float C = dot (pos, pos) - radius_0 * 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"
+ " /* This complicated bit of logic acts as\n"
+ " * \"if (A < 0.0) sqrt_det = -sqrt_det\", without the branch.\n"
+ " */\n"
+ " sqrt_det *= 1.0 + 2.0 * sign (min (A, 0.0));\n"
+ " \n"
+ " float t = (-B + sqrt_det) / (2.0 * A);\n"
+ " t = (t - first_offset) / (last_offset - first_offset);\n"
+ " gl_FragColor = texture1D (tex, t);\n"
+ "}\n";
+
+static const char * const linear_gradient_frag_text_110 =
+ "#version 110\n"
+ "\n"
+ "uniform sampler1D tex;\n"
+ "uniform mat4 matrix;\n"
+ "uniform vec2 segment;\n"
+ "uniform float first_offset;\n"
+ "uniform float last_offset;\n"
+ "\n"
+ "void main ()\n"
+ "{\n"
+ " vec2 pos = (matrix * vec4 (gl_FragCoord.xy, 0.0, 1.0)).xy;\n"
+ " float t = dot (pos, segment) / dot (segment, segment);\n"
+ " t = (t - first_offset) / (last_offset - first_offset);\n"
+ " gl_FragColor = texture1D (tex, t);\n"
+ "}\n";
+
+/* ARB_shader_objects / ARB_vertex_shader / ARB_fragment_shader extensions
+ API. */
+static cairo_status_t
+compile_shader_arb (GLuint *shader, GLenum type, const char *text)
+{
+ const char* strings[1] = { text };
+ GLint gl_status;
+
+ *shader = glCreateShaderObjectARB (type);
+ glShaderSourceARB (*shader, 1, strings, 0);
+ glCompileShaderARB (*shader);
+ glGetObjectParameterivARB (*shader, GL_OBJECT_COMPILE_STATUS_ARB,
&gl_status);
+ if (gl_status == GL_FALSE) {
+ GLint log_size;
+ glGetObjectParameterivARB (*shader,
GL_OBJECT_INFO_LOG_LENGTH_ARB, &log_size);
+ if (0 < log_size) {
+ char *log = _cairo_malloc (log_size);
+ GLint chars;
+
+ log[log_size - 1] = '\0';
+ glGetInfoLogARB (*shader, log_size, &chars, log);
+ printf ("OpenGL shader compilation failed. Shader:\n"
+ "%s\n"
+ "OpenGL compilation log:\n"
+ "%s\n",
+ text, log);
+
+ free (log);
+ } else {
+ printf ("OpenGL shader compilation failed.\n");
+ }
+
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+ }
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+link_shader_arb (GLuint *program, GLuint vert, GLuint frag)
+{
+ GLint gl_status;
+
+ *program = glCreateProgramObjectARB ();
+ glAttachObjectARB (*program, vert);
+ glAttachObjectARB (*program, frag);
+ glLinkProgramARB (*program);
+ glGetObjectParameterivARB (*program, GL_OBJECT_LINK_STATUS_ARB,
&gl_status);
+ if (gl_status == GL_FALSE) {
+ GLint log_size;
+ glGetObjectParameterivARB (*program,
GL_OBJECT_INFO_LOG_LENGTH_ARB, &log_size);
+ if (0 < log_size) {
+ char *log = _cairo_malloc (log_size);
+ GLint chars;
+
+ log[log_size - 1] = '\0';
+ glGetInfoLogARB (*program, log_size, &chars, log);
+ printf ("OpenGL shader link failed:\n%s\n", log);
+
+ free (log);
+ } else {
+ printf ("OpenGL shader link failed.\n");
+ }
+
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+ }
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static void
+destroy_shader_program_arb (cairo_gl_shader_program_t *program)
+{
+ if (program->vertex_shader)
+ glDeleteObjectARB (program->vertex_shader);
+ if (program->fragment_shader)
+ glDeleteObjectARB (program->fragment_shader);
+ if (program->program)
+ glDeleteObjectARB (program->program);
+}
+
+static cairo_status_t
+create_linear_gradient_shader_program_arb (cairo_gl_shader_program_t *program)
+{
+ return create_shader_program (program,
+ minimal_vert_text_110,
+ linear_gradient_frag_text_110);
+}
+
+static cairo_status_t
+create_radial_gradient_shader_program_arb (cairo_gl_shader_program_t *program)
+{
+ return create_shader_program (program,
+ minimal_vert_text_110,
+ radial_gradient_frag_text_110);
+}
+
+static cairo_status_t
+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;
+ glUniform1fARB (location, value);
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+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;
+ glUniform2fARB (location, value0, value1);
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+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;
+ glUniform3fARB (location, value0, value1, value2);
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+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;
+ glUniform4fARB (location, value0, value1, value2, value3);
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+bind_matrix_to_shader_arb (GLuint program, const char *name, cairo_matrix_t* m)
+{
+ GLint location = glGetUniformLocationARB (program, name);
+ if (location == -1)
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+ float gl_m[16] = {
+ m->xx, m->xy, 0, m->x0,
+ m->yx, m->yy, 0, m->y0,
+ 0, 0, 1, 0,
+ 0, 0, 0, 1
+ };
+ glUniformMatrix4fvARB (location, 1, GL_TRUE, gl_m);
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+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;
+ glUniform1iARB (location, tex_unit);
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static GLenum
+vertex_enumerator_arb (void)
+{
+ return GL_VERTEX_SHADER_ARB;
+}
+
+static GLenum
+fragment_enumerator_arb (void)
+{
+ return GL_FRAGMENT_SHADER_ARB;
+}
+
+/* OpenGL Core 2.0 API. */
+static cairo_status_t
+compile_shader_core_2_0 (GLuint *shader, GLenum type, const char *text)
+{
+ const char* strings[1] = { text };
+ GLint gl_status;
+
+ *shader = glCreateShader (type);
+ glShaderSource (*shader, 1, strings, 0);
+ glCompileShader (*shader);
+ glGetShaderiv (*shader, GL_COMPILE_STATUS, &gl_status);
+ if (gl_status == GL_FALSE) {
+ GLint log_size;
+ glGetShaderiv (*shader, GL_INFO_LOG_LENGTH, &log_size);
+ if (0 < log_size) {
+ char *log = _cairo_malloc (log_size);
+ GLint chars;
+
+ log[log_size - 1] = '\0';
+ glGetShaderInfoLog (*shader, log_size, &chars, log);
+ printf ("OpenGL shader compilation failed. Shader:\n"
+ "%s\n"
+ "OpenGL compilation log:\n"
+ "%s\n",
+ text, log);
+
+ free (log);
+ } else {
+ printf ("OpenGL shader compilation failed.\n");
+ }
+
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+ }
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+link_shader_core_2_0 (GLuint *program, GLuint vert, GLuint frag)
+{
+ GLint gl_status;
+
+ *program = glCreateProgram ();
+ glAttachShader (*program, vert);
+ glAttachShader (*program, frag);
+ glLinkProgram (*program);
+ glGetProgramiv (*program, GL_LINK_STATUS, &gl_status);
+ if (gl_status == GL_FALSE) {
+ GLint log_size;
+ glGetProgramiv (*program, GL_INFO_LOG_LENGTH, &log_size);
+ if (0 < log_size) {
+ char *log = _cairo_malloc (log_size);
+ GLint chars;
+
+ log[log_size - 1] = '\0';
+ glGetProgramInfoLog (*program, log_size, &chars, log);
+ printf ("OpenGL shader link failed:\n%s\n", log);
+
+ free (log);
+ } else {
+ printf ("OpenGL shader link failed.\n");
+ }
+
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+ }
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static void
+destroy_shader_program_core_2_0 (cairo_gl_shader_program_t *program)
+{
+ glDeleteShader (program->vertex_shader);
+ glDeleteShader (program->fragment_shader);
+ glDeleteProgram (program->program);
+}
+
+static cairo_status_t
+create_linear_gradient_shader_program_core_2_0
(cairo_gl_shader_program_t *program)
+{
+ return create_shader_program (program,
+ minimal_vert_text_110,
+ linear_gradient_frag_text_110);
+}
+
+static cairo_status_t
+create_radial_gradient_shader_program_core_2_0
(cairo_gl_shader_program_t *program)
+{
+ return create_shader_program (program,
+ minimal_vert_text_110,
+ radial_gradient_frag_text_110);
+}
+
+static cairo_status_t
+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;
+ glUniform1f (location, value);
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+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;
+ glUniform2f (location, value0, value1);
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+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;
+ glUniform3f (location, value0, value1, value2);
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+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;
+ glUniform4f (location, value0, value1, value2, value3);
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+bind_matrix_to_shader_core_2_0 (GLuint program, const char *name,
cairo_matrix_t* m)
+{
+ GLint location = glGetUniformLocation (program, name);
+ if (location == -1)
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+ float gl_m[16] = {
+ m->xx, m->xy, 0, m->x0,
+ m->yx, m->yy, 0, m->y0,
+ 0, 0, 1, 0,
+ 0, 0, 0, 1
+ };
+ glUniformMatrix4fv (location, 1, GL_TRUE, gl_m);
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+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;
+ glUniform1i (location, tex_unit);
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static GLenum
+vertex_enumerator_core_2_0 (void)
+{
+ return GL_VERTEX_SHADER;
+}
+
+static GLenum
+fragment_enumerator_core_2_0 (void)
+{
+ return GL_FRAGMENT_SHADER;
+}
+
+#define SHADER_IMPL_DECL(x) \
+ static const shader_impl_t shader_impl_ ## x = { \
+ compile_shader_ ## x, \
+ link_shader_ ## x, \
+ destroy_shader_program_ ## x, \
+ create_linear_gradient_shader_program_ ## x, \
+ create_radial_gradient_shader_program_ ## x, \
+ bind_float_to_shader_ ## x, \
+ bind_vec2_to_shader_ ## x, \
+ bind_vec3_to_shader_ ## x, \
+ bind_vec4_to_shader_ ## x, \
+ bind_matrix_to_shader_ ## x, \
+ bind_texture_to_shader_ ## x, \
+ vertex_enumerator_ ## x, \
+ fragment_enumerator_ ## x \
+ }
+
+SHADER_IMPL_DECL(core_2_0);
+SHADER_IMPL_DECL(arb);
+
+#undef SHADER_IMPL_DECL
+
+static const shader_impl_t*
+get_impl (void)
+{
+ if (GLEW_VERSION_2_0) {
+ return &shader_impl_core_2_0;
+ } else if (GLEW_ARB_shader_objects &&
+ GLEW_ARB_fragment_shader &&
+ GLEW_ARB_vertex_program) {
+ return &shader_impl_arb;
+ }
+
+ ASSERT_NOT_REACHED;
+ return NULL;
+}
+
+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_program (cairo_gl_shader_program_t *program)
+{
+ return get_impl()->destroy_shader_program(program);
+}
+
+cairo_status_t
+create_shader_program (cairo_gl_shader_program_t *program,
+ const char *vertex_text,
+ const char *fragment_text)
+{
+ cairo_status_t status;
+
+ if (program->program != 0)
+ return CAIRO_STATUS_SUCCESS;
+
+ if (program->build_failure)
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+
+ status = get_impl()->compile_shader (&program->vertex_shader,
+ get_impl()->vertex_enumerator(),
+ vertex_text);
+ if (unlikely (status))
+ goto FAILURE;
+
+ status = get_impl()->compile_shader (&program->fragment_shader,
+ get_impl()->fragment_enumerator(),
+ fragment_text);
+ if (unlikely (status))
+ goto FAILURE;
+
+ status = get_impl()->link_shader (&program->program,
+ program->vertex_shader,
+ program->fragment_shader);
+ if (unlikely (status))
+ goto FAILURE;
+
+ return CAIRO_STATUS_SUCCESS;
+
+ FAILURE:
+ destroy_shader_program (program);
+ program->vertex_shader = 0;
+ program->fragment_shader = 0;
+ program->program = 0;
+ program->build_failure = TRUE;
+
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+}
+
+cairo_status_t
+create_linear_gradient_shader_program (cairo_gl_shader_program_t *program)
+{
+ return get_impl()->create_linear_gradient_shader_program(program);
+}
+
+cairo_status_t
+create_radial_gradient_shader_program (cairo_gl_shader_program_t *program)
+{
+ return get_impl()->create_radial_gradient_shader_program(program);
+}
+
+cairo_status_t
+bind_float_to_shader (GLuint program, const char *name,
+ float value)
+{
+ return get_impl()->bind_float_to_shader(program, name, value);
+}
+
+cairo_status_t
+bind_vec2_to_shader (GLuint program, const char *name,
+ float value0, float value1)
+{
+ return get_impl()->bind_vec2_to_shader(program, name, value0, value1);
+}
+
+cairo_status_t
+bind_vec3_to_shader (GLuint program, const char *name,
+ float value0, float value1,
+ float value2)
+{
+ return get_impl()->bind_vec3_to_shader(program, name, value0,
value1, value2);
+}
+
+cairo_status_t
+bind_vec4_to_shader (GLuint program, const char *name,
+ float value0, float value1,
+ float value2, float value3)
+{
+ return get_impl()->bind_vec4_to_shader(program, name, value0,
value1, value2, value3);
+}
+
+cairo_status_t
+bind_matrix_to_shader (GLuint program, const char *name, cairo_matrix_t* m)
+{
+ return get_impl()->bind_matrix_to_shader(program, name, m);
+}
+
+cairo_status_t
+bind_texture_to_shader (GLuint program, const char *name, GLuint tex_unit)
+{
+ return get_impl()->bind_texture_to_shader(program, name, tex_unit);
+}
More information about the cairo
mailing list