diff options
author | Alexandros Frantzis <alexandros.frantzis@linaro.org> | 2010-12-03 19:35:05 +0200 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2010-12-15 15:32:20 +0000 |
commit | 357c2f46a77aebd8caac8ac0c6491b0db68351c7 (patch) | |
tree | 8d4f5fe910194b8a36845aa6ebf0441c93e147ac | |
parent | cd7c0df2bb036fddca4b874f12171121ae740a50 (diff) | |
download | cairo-357c2f46a77aebd8caac8ac0c6491b0db68351c7.tar.gz |
gl: Add infrastructure for calling GL functions using a dispatch table
Some GL functions can be called using different names depending on the
GL version and available extensions (ARB, EXT). The dispatch table
abstracts these differences and provides a uniform API for dealing with
these functions.
-rw-r--r-- | src/Makefile.sources | 2 | ||||
-rw-r--r-- | src/cairo-gl-dispatch-private.h | 99 | ||||
-rw-r--r-- | src/cairo-gl-dispatch.c | 144 | ||||
-rw-r--r-- | src/cairo-gl-private.h | 58 |
4 files changed, 303 insertions, 0 deletions
diff --git a/src/Makefile.sources b/src/Makefile.sources index ae19e7f15..168429fac 100644 --- a/src/Makefile.sources +++ b/src/Makefile.sources @@ -313,12 +313,14 @@ cairo_beos_cxx_sources = cairo-beos-surface.cpp cairo_gl_headers = cairo-gl.h cairo_gl_private = cairo-gl-private.h \ + cairo-gl-dispatch-private.h \ cairo-gl-gradient-private.h \ glew/GL/glew.h \ glew/GL/glxew.h cairo_gl_sources = cairo-gl-composite.c \ cairo-gl-device.c \ + cairo-gl-dispatch.c \ cairo-gl-glyphs.c \ cairo-gl-gradient.c \ cairo-gl-info.c \ diff --git a/src/cairo-gl-dispatch-private.h b/src/cairo-gl-dispatch-private.h new file mode 100644 index 000000000..cfe737c7f --- /dev/null +++ b/src/cairo-gl-dispatch-private.h @@ -0,0 +1,99 @@ +/* cairo - a vector graphics library with display and print output + * + * Copyright © 2010 Linaro Limited + * + * 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. + * + * Contributor(s): + * Alexandros Frantzis <alexandros.frantzis@linaro.org> + */ + +#ifndef CAIRO_GL_DISPATCH_PRIVATE_H +#define CAIRO_GL_DISPATCH_PRIVATE_H + +#include <stddef.h> +#include "cairo-gl-private.h" + +typedef struct _cairo_gl_dispatch_entry { + const char *name_core; + const char *name_ext; + size_t offset; +} cairo_gl_dispatch_entry_t; + +#define DISPATCH_ENTRY_ARB(name) { "gl"#name, "gl"#name"ARB", \ + offsetof(cairo_gl_dispatch_t, name) } +#define DISPATCH_ENTRY_EXT(name) { "gl"#name, "gl"#name"EXT", \ + offsetof(cairo_gl_dispatch_t, name) } +#define DISPATCH_ENTRY_CUSTOM(name, name2) { "gl"#name, "gl"#name2, \ + offsetof(cairo_gl_dispatch_t, name)} +#define DISPATCH_ENTRY_LAST { NULL, NULL, 0 } + +cairo_gl_dispatch_entry_t dispatch_buffers_entries[] = { + DISPATCH_ENTRY_ARB (GenBuffers), + DISPATCH_ENTRY_ARB (BindBuffer), + DISPATCH_ENTRY_ARB (BufferData), + DISPATCH_ENTRY_ARB (MapBuffer), + DISPATCH_ENTRY_ARB (UnmapBuffer), + DISPATCH_ENTRY_LAST +}; + +cairo_gl_dispatch_entry_t dispatch_shaders_entries[] = { + /* Shaders */ + DISPATCH_ENTRY_CUSTOM (CreateShader, CreateShaderObjectARB), + DISPATCH_ENTRY_ARB (ShaderSource), + DISPATCH_ENTRY_ARB (CompileShader), + DISPATCH_ENTRY_CUSTOM (GetShaderiv, GetObjectParameterivARB), + DISPATCH_ENTRY_CUSTOM (GetShaderInfoLog, GetInfoLogARB), + DISPATCH_ENTRY_CUSTOM (DeleteShader, DeleteObjectARB), + + /* Programs */ + DISPATCH_ENTRY_CUSTOM (CreateProgram, CreateProgramObjectARB), + DISPATCH_ENTRY_CUSTOM (AttachShader, AttachObjectARB), + DISPATCH_ENTRY_CUSTOM (DeleteProgram, DeleteObjectARB), + DISPATCH_ENTRY_ARB (LinkProgram), + DISPATCH_ENTRY_CUSTOM (UseProgram, UseProgramObjectARB), + DISPATCH_ENTRY_CUSTOM (GetProgramiv, GetObjectParameterivARB), + DISPATCH_ENTRY_CUSTOM (GetProgramInfoLog, GetInfoLogARB), + + /* Uniforms */ + DISPATCH_ENTRY_ARB (GetUniformLocation), + DISPATCH_ENTRY_ARB (Uniform1f), + DISPATCH_ENTRY_ARB (Uniform2f), + DISPATCH_ENTRY_ARB (Uniform3f), + DISPATCH_ENTRY_ARB (Uniform4f), + DISPATCH_ENTRY_ARB (UniformMatrix3fv), + DISPATCH_ENTRY_ARB (Uniform1i), + DISPATCH_ENTRY_LAST +}; + +cairo_gl_dispatch_entry_t dispatch_fbo_entries[] = { + DISPATCH_ENTRY_EXT (GenFramebuffers), + DISPATCH_ENTRY_EXT (BindFramebuffer), + DISPATCH_ENTRY_EXT (FramebufferTexture2D), + DISPATCH_ENTRY_EXT (CheckFramebufferStatus), + DISPATCH_ENTRY_EXT (DeleteFramebuffers), + DISPATCH_ENTRY_LAST +}; + +#endif /* CAIRO_GL_DISPATCH_PRIVATE_H */ diff --git a/src/cairo-gl-dispatch.c b/src/cairo-gl-dispatch.c new file mode 100644 index 000000000..f44d3b855 --- /dev/null +++ b/src/cairo-gl-dispatch.c @@ -0,0 +1,144 @@ +/* cairo - a vector graphics library with display and print output + * + * Copyright © 2010 Linaro Limited + * + * 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. + * + * Contributor(s): + * Alexandros Frantzis <alexandros.frantzis@linaro.org> + */ + +#include "cairo-gl-private.h" +#include "cairo-gl-dispatch-private.h" + +static void +_cairo_gl_dispatch_init_entries (cairo_gl_dispatch_t *dispatch, + cairo_gl_get_proc_addr_func_t get_proc_addr, + cairo_gl_dispatch_entry_t *entries, + cairo_bool_t use_ext) +{ + cairo_gl_dispatch_entry_t *entry = entries; + + while (entry->name_core != NULL) { + void *dispatch_ptr = &((char *) dispatch)[entry->offset]; + const char *name = use_ext ? entry->name_ext : + entry->name_core; + + cairo_gl_generic_func_t func = get_proc_addr (name); + + *((cairo_gl_generic_func_t *) dispatch_ptr) = func; + + ++entry; + } + +} + +static cairo_status_t +_cairo_gl_dispatch_init_buffers (cairo_gl_dispatch_t *dispatch, + cairo_gl_get_proc_addr_func_t get_proc_addr, + int gl_version) +{ + cairo_bool_t use_ext; + + if (gl_version >= CAIRO_GL_VERSION_ENCODE (1, 5)) + use_ext = 0; + else if (_cairo_gl_has_extension ("GL_ARB_vertex_buffer_object")) + use_ext = 1; + else + return CAIRO_STATUS_DEVICE_ERROR; + + _cairo_gl_dispatch_init_entries (dispatch, get_proc_addr, + dispatch_buffers_entries, use_ext); + + return CAIRO_STATUS_SUCCESS; +} + +static cairo_status_t +_cairo_gl_dispatch_init_shaders (cairo_gl_dispatch_t *dispatch, + cairo_gl_get_proc_addr_func_t get_proc_addr, + int gl_version) +{ + cairo_bool_t use_ext; + + /* Note: shader support is not necessary at the moment */ + if (gl_version >= CAIRO_GL_VERSION_ENCODE (2, 0)) + use_ext = 0; + else if (_cairo_gl_has_extension ("GL_ARB_shader_objects")) + use_ext = 1; + else + return CAIRO_STATUS_SUCCESS; + + _cairo_gl_dispatch_init_entries (dispatch, get_proc_addr, + dispatch_shaders_entries, use_ext); + + return CAIRO_STATUS_SUCCESS; +} + +static cairo_status_t +_cairo_gl_dispatch_init_fbo (cairo_gl_dispatch_t *dispatch, + cairo_gl_get_proc_addr_func_t get_proc_addr, + int gl_version) +{ + cairo_bool_t use_ext; + + if (gl_version >= CAIRO_GL_VERSION_ENCODE (3, 0) || + _cairo_gl_has_extension ("GL_ARB_framebuffer_object")) + use_ext = 0; + else if (_cairo_gl_has_extension ("GL_EXT_framebuffer_object")) + use_ext = 1; + else + return CAIRO_STATUS_DEVICE_ERROR; + + _cairo_gl_dispatch_init_entries (dispatch, get_proc_addr, + dispatch_fbo_entries, use_ext); + + return CAIRO_STATUS_SUCCESS; +} + +cairo_status_t +_cairo_gl_dispatch_init (cairo_gl_dispatch_t *dispatch, + cairo_gl_get_proc_addr_func_t get_proc_addr) +{ + cairo_status_t status; + int gl_version; + + gl_version = _cairo_gl_get_version (); + + status = _cairo_gl_dispatch_init_buffers (dispatch, get_proc_addr, + gl_version); + if (status != CAIRO_STATUS_SUCCESS) + return status; + + status = _cairo_gl_dispatch_init_shaders (dispatch, get_proc_addr, + gl_version); + if (status != CAIRO_STATUS_SUCCESS) + return status; + + status = _cairo_gl_dispatch_init_fbo (dispatch, get_proc_addr, + gl_version); + if (status != CAIRO_STATUS_SUCCESS) + return status; + + return CAIRO_STATUS_SUCCESS; +} diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h index 2a818aa32..a050e189b 100644 --- a/src/cairo-gl-private.h +++ b/src/cairo-gl-private.h @@ -175,6 +175,59 @@ typedef struct cairo_gl_operand { unsigned int vertex_offset; } cairo_gl_operand_t; +typedef void (*cairo_gl_generic_func_t)(void); +typedef cairo_gl_generic_func_t (*cairo_gl_get_proc_addr_func_t)(const char *procname); + +typedef struct _cairo_gl_dispatch { + /* Buffers */ + void (*GenBuffers) (GLsizei n, GLuint *buffers); + void (*BindBuffer) (GLenum target, GLuint buffer); + void (*BufferData) (GLenum target, GLsizeiptr size, + const GLvoid* data, GLenum usage); + GLvoid *(*MapBuffer) (GLenum target, GLenum access); + GLboolean (*UnmapBuffer) (GLenum target); + + /* Shaders */ + GLuint (*CreateShader) (GLenum type); + void (*ShaderSource) (GLuint shader, GLsizei count, + const GLchar** string, const GLint* length); + void (*CompileShader) (GLuint shader); + void (*GetShaderiv) (GLuint shader, GLenum pname, GLint *params); + void (*GetShaderInfoLog) (GLuint shader, GLsizei bufSize, + GLsizei *length, GLchar *infoLog); + void (*DeleteShader) (GLuint shader); + + /* Programs */ + GLuint (*CreateProgram) (void); + void (*AttachShader) (GLuint program, GLuint shader); + void (*DeleteProgram) (GLuint program); + void (*LinkProgram) (GLuint program); + void (*UseProgram) (GLuint program); + void (*GetProgramiv) (GLuint program, GLenum pname, GLint *params); + void (*GetProgramInfoLog) (GLuint program, GLsizei bufSize, + GLsizei *length, GLchar *infoLog); + + /* Uniforms */ + GLint (*GetUniformLocation) (GLuint program, const GLchar* name); + void (*Uniform1f) (GLint location, GLfloat x); + void (*Uniform2f) (GLint location, GLfloat x, GLfloat y); + void (*Uniform3f) (GLint location, GLfloat x, GLfloat y, GLfloat z); + void (*Uniform4f) (GLint location, GLfloat x, GLfloat y, GLfloat z, + GLfloat w); + void (*UniformMatrix3fv) (GLint location, GLsizei count, + GLboolean transpose, const GLfloat *value); + void (*Uniform1i) (GLint location, GLint x); + + /* Framebuffer objects */ + void (*GenFramebuffers) (GLsizei n, GLuint* framebuffers); + void (*BindFramebuffer) (GLenum target, GLuint framebuffer); + void (*FramebufferTexture2D) (GLenum target, GLenum attachment, + GLenum textarget, GLuint texture, + GLint level); + GLenum (*CheckFramebufferStatus) (GLenum target); + void (*DeleteFramebuffers) (GLsizei n, const GLuint* framebuffers); +} cairo_gl_dispatch_t; + struct _cairo_gl_context { cairo_device_t base; @@ -489,6 +542,11 @@ _cairo_gl_get_version (void); cairo_private cairo_bool_t _cairo_gl_has_extension (const char *ext); +cairo_private cairo_status_t +_cairo_gl_dispatch_init(cairo_gl_dispatch_t *dispatch, + cairo_gl_get_proc_addr_func_t get_proc_addr); + + slim_hidden_proto (cairo_gl_surface_create); slim_hidden_proto (cairo_gl_surface_create_for_texture); |