mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-06-07 01:48:20 +02:00
[gl] Add shader support code for GL versions < 3.0.
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.
This commit is contained in:
parent
a6897ad386
commit
25ccc5dcb0
2 changed files with 671 additions and 1 deletions
|
|
@ -34,6 +34,7 @@
|
|||
* Contributor(s):
|
||||
* Carl Worth <cworth@cworth.org>
|
||||
* Chris Wilson <chris@chris-wilson.co.uk>
|
||||
* T. Zachary Laine <whatwasthataddress@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;
|
||||
|
||||
typedef struct _cairo_gl_context {
|
||||
cairo_device_t base;
|
||||
|
||||
|
|
@ -241,6 +249,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 */
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
/* cairo - a vector graphics library with display and print output
|
||||
*
|
||||
* Copyright © 2010 Eric Anholt
|
||||
* 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
|
||||
|
|
@ -27,7 +28,7 @@
|
|||
*
|
||||
* The Original Code is the cairo graphics library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Eric Anholt.
|
||||
* The Initial Developer of the Original Code is T. Zachary Laine.
|
||||
*/
|
||||
|
||||
#include "cairoint.h"
|
||||
|
|
@ -116,3 +117,623 @@ fail:
|
|||
glDeleteObjectARB (shader);
|
||||
return status;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue