summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Anholt <eric@anholt.net>2009-01-29 09:19:01 -0800
committerEric Anholt <eric@anholt.net>2009-02-05 09:38:43 -0800
commit235de8d7a492ccd132fb83f78d33b408bd76aec1 (patch)
treebf37af0a65105aee5cb4f2b83f8bea535a9c7f02
parent83ec4b16b7b9a27439fee2d84c50e30a1ec2d68c (diff)
[gl] Add basics for GL surface backend using test-fallback as base.
-rw-r--r--boilerplate/Makefile.sources3
-rw-r--r--boilerplate/Makefile.win32.features10
-rw-r--r--boilerplate/cairo-boilerplate-gl-private.h59
-rw-r--r--boilerplate/cairo-boilerplate-gl.c124
-rw-r--r--boilerplate/cairo-boilerplate.c25
-rw-r--r--build/Makefile.win32.features1
-rw-r--r--build/Makefile.win32.features-h3
-rw-r--r--build/configure.ac.features1
-rw-r--r--configure.ac7
-rw-r--r--perf/cairo-perf.c1
-rw-r--r--src/Makefile.sources4
-rw-r--r--src/Makefile.win32.features14
-rw-r--r--src/cairo-gl-surface.c287
-rw-r--r--src/cairo-gl.h89
-rw-r--r--src/cairo-mutex-list-private.h4
-rw-r--r--src/cairo.h4
16 files changed, 635 insertions, 1 deletions
diff --git a/boilerplate/Makefile.sources b/boilerplate/Makefile.sources
index b3cea817..d3c0fa15 100644
--- a/boilerplate/Makefile.sources
+++ b/boilerplate/Makefile.sources
@@ -24,6 +24,9 @@ cairo_boilerplate_beos_private = cairo-boilerplate-beos-private.h
cairo_boilerplate_directfb_private = cairo-boilerplate-directfb-private.h
cairo_boilerplate_directfb_sources = cairo-boilerplate-directfb.c
+cairo_boilerplate_gl_private = cairo-boilerplate-gl-private.h
+cairo_boilerplate_gl_sources = cairo-boilerplate-gl.c
+
cairo_boilerplate_glitz_private = cairo-boilerplate-glitz-private.h
cairo_boilerplate_glitz_sources = \
cairo-boilerplate-glitz-agl.c \
diff --git a/boilerplate/Makefile.win32.features b/boilerplate/Makefile.win32.features
index 74f1ec1e..3d55ced7 100644
--- a/boilerplate/Makefile.win32.features
+++ b/boilerplate/Makefile.win32.features
@@ -139,6 +139,16 @@ enabled_cairo_boilerplate_private += $(cairo_boilerplate_png_private)
enabled_cairo_boilerplate_sources += $(cairo_boilerplate_png_sources)
endif
+unsupported_cairo_boilerplate_headers += $(cairo_boilerplate_gl_headers)
+all_cairo_boilerplate_headers += $(cairo_boilerplate_gl_headers)
+all_cairo_boilerplate_private += $(cairo_boilerplate_gl_private)
+all_cairo_boilerplate_sources += $(cairo_boilerplate_gl_sources)
+ifeq ($(CAIRO_HAS_GL_SURFACE),1)
+enabled_cairo_boilerplate_headers += $(cairo_boilerplate_gl_headers)
+enabled_cairo_boilerplate_private += $(cairo_boilerplate_gl_private)
+enabled_cairo_boilerplate_sources += $(cairo_boilerplate_gl_sources)
+endif
+
unsupported_cairo_boilerplate_headers += $(cairo_boilerplate_glitz_headers)
all_cairo_boilerplate_headers += $(cairo_boilerplate_glitz_headers)
all_cairo_boilerplate_private += $(cairo_boilerplate_glitz_private)
diff --git a/boilerplate/cairo-boilerplate-gl-private.h b/boilerplate/cairo-boilerplate-gl-private.h
new file mode 100644
index 00000000..2d256c34
--- /dev/null
+++ b/boilerplate/cairo-boilerplate-gl-private.h
@@ -0,0 +1,59 @@
+/* Cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2009 Chris Wilson
+ *
+ * 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 Chris Wilson.
+ */
+
+#ifndef CAIRO_BOILERPLATE_GL_PRIVATE_H
+#define CAIRO_BOILERPLATE_GL_PRIVATE_H
+
+#include <cairo.h>
+
+CAIRO_BEGIN_DECLS
+
+extern cairo_surface_t *
+_cairo_boilerplate_gl_create_surface (const char *name,
+ cairo_content_t content,
+ int width,
+ int height,
+ int max_width,
+ int max_height,
+ cairo_boilerplate_mode_t mode,
+ int id,
+ void **closure);
+
+extern void
+_cairo_boilerplate_gl_cleanup (void* closure);
+
+extern void
+_cairo_boilerplate_gl_synchronize (void *closure);
+
+CAIRO_END_DECLS
+
+#endif /* CAIRO_BOILERPLATE_GL_PRIVATE_H */
diff --git a/boilerplate/cairo-boilerplate-gl.c b/boilerplate/cairo-boilerplate-gl.c
new file mode 100644
index 00000000..8a0422c4
--- /dev/null
+++ b/boilerplate/cairo-boilerplate-gl.c
@@ -0,0 +1,124 @@
+/* Cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2009 Chris Wilson
+ *
+ * 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 Chris Wilson.
+ */
+
+#include "cairo-boilerplate.h"
+#include "cairo-boilerplate-gl-private.h"
+
+#include <cairo-gl.h>
+
+typedef struct _gl_target_closure {
+ Display *dpy;
+ int screen;
+
+ cairo_gl_context_t *ctx;
+ cairo_surface_t *surface;
+} gl_target_closure_t;
+
+void
+_cairo_boilerplate_gl_cleanup (void *closure)
+{
+ gl_target_closure_t *gltc = closure;
+
+ cairo_gl_context_destroy (gltc->ctx);
+ XCloseDisplay (gltc->dpy);
+ free (gltc);
+}
+
+cairo_surface_t *
+_cairo_boilerplate_gl_create_surface (const char *name,
+ cairo_content_t content,
+ int width,
+ int height,
+ int max_width,
+ int max_height,
+ cairo_boilerplate_mode_t mode,
+ int id,
+ void **closure)
+{
+ int attribs[] = { GLX_RGBA,
+ GLX_RED_SIZE, 1,
+ GLX_GREEN_SIZE, 1,
+ GLX_BLUE_SIZE, 1,
+ GLX_DOUBLEBUFFER,
+ None };
+ XVisualInfo *visinfo;
+ GLXContext gl_ctx;
+ gl_target_closure_t *gltc;
+ Display *dpy;
+
+ gltc = malloc (sizeof (gl_target_closure_t));
+ *closure = gltc;
+
+ if (width == 0)
+ width = 1;
+ if (height == 0)
+ height = 1;
+
+ dpy = XOpenDisplay (NULL);
+ gltc->dpy = dpy;
+ if (!gltc->dpy) {
+ fprintf (stderr, "Failed to open display: %s\n", XDisplayName(0));
+ free (gltc);
+ return NULL;
+ }
+
+ if (mode == CAIRO_BOILERPLATE_MODE_TEST)
+ XSynchronize (gltc->dpy, 1);
+
+ visinfo = glXChooseVisual (dpy, DefaultScreen (dpy), attribs);
+ if (visinfo == NULL) {
+ fprintf (stderr, "Failed to create RGB, double-buffered visual\n");
+ XCloseDisplay (dpy);
+ free (gltc);
+ return NULL;
+ }
+
+ gl_ctx = glXCreateContext (dpy, visinfo, NULL, True);
+
+ gltc->ctx = cairo_gl_glx_context_create (dpy, gl_ctx);
+
+ gltc->surface = cairo_gl_surface_create (gltc->ctx, content,
+ width, height);
+
+ if (gltc->surface == NULL || cairo_surface_status (gltc->surface))
+ _cairo_boilerplate_gl_cleanup (gltc);
+
+ return gltc->surface;
+}
+
+void
+_cairo_boilerplate_gl_synchronize (void *closure)
+{
+ gl_target_closure_t *gltc = closure;
+
+ cairo_gl_surface_glfinish (gltc->surface);
+}
diff --git a/boilerplate/cairo-boilerplate.c b/boilerplate/cairo-boilerplate.c
index dd34110c..09859bab 100644
--- a/boilerplate/cairo-boilerplate.c
+++ b/boilerplate/cairo-boilerplate.c
@@ -35,6 +35,9 @@
#if CAIRO_HAS_DIRECTFB_SURFACE
#include "cairo-boilerplate-directfb-private.h"
#endif
+#if CAIRO_HAS_GL_SURFACE
+#include "cairo-boilerplate-gl-private.h"
+#endif
#if CAIRO_HAS_GLITZ_SURFACE
#include "cairo-boilerplate-glitz-private.h"
#endif
@@ -356,6 +359,28 @@ static cairo_boilerplate_target_t targets[] =
FALSE, TRUE
},
#endif
+#ifdef CAIRO_HAS_GL_SURFACE
+ {
+ "gl", "gl", NULL,
+ CAIRO_SURFACE_TYPE_GL,CAIRO_CONTENT_COLOR_ALPHA, 0,
+ _cairo_boilerplate_gl_create_surface, NULL,
+ NULL,
+ _cairo_boilerplate_get_image_surface,
+ cairo_surface_write_to_png,
+ _cairo_boilerplate_gl_cleanup,
+ _cairo_boilerplate_gl_synchronize,
+ },
+ {
+ "gl", "gl", NULL,
+ CAIRO_SURFACE_TYPE_GL, CAIRO_CONTENT_COLOR, 0,
+ _cairo_boilerplate_gl_create_surface, NULL,
+ NULL,
+ _cairo_boilerplate_get_image_surface,
+ cairo_surface_write_to_png,
+ _cairo_boilerplate_gl_cleanup,
+ _cairo_boilerplate_gl_synchronize,
+ },
+#endif
#ifdef CAIRO_HAS_GLITZ_SURFACE
#if CAIRO_CAN_TEST_GLITZ_GLX_SURFACE
{
diff --git a/build/Makefile.win32.features b/build/Makefile.win32.features
index aa7e56e1..69b3b39e 100644
--- a/build/Makefile.win32.features
+++ b/build/Makefile.win32.features
@@ -12,6 +12,7 @@ CAIRO_HAS_OS2_SURFACE=0
CAIRO_HAS_BEOS_SURFACE=0
CAIRO_HAS_SDL_SURFACE=0
CAIRO_HAS_PNG_FUNCTIONS=1
+CAIRO_HAS_GL_SURFACE=0
CAIRO_HAS_GLITZ_SURFACE=0
CAIRO_HAS_DIRECTFB_SURFACE=0
CAIRO_HAS_SCRIPT_SURFACE=0
diff --git a/build/Makefile.win32.features-h b/build/Makefile.win32.features-h
index 82f6121b..cae81357 100644
--- a/build/Makefile.win32.features-h
+++ b/build/Makefile.win32.features-h
@@ -41,6 +41,9 @@ endif
ifeq ($(CAIRO_HAS_PNG_FUNCTIONS),1)
@echo "#define CAIRO_HAS_PNG_FUNCTIONS 1" >> src/cairo-features.h
endif
+ifeq ($(CAIRO_HAS_GL_SURFACE),1)
+ @echo "#define CAIRO_HAS_GL_SURFACE 1" >> src/cairo-features.h
+endif
ifeq ($(CAIRO_HAS_GLITZ_SURFACE),1)
@echo "#define CAIRO_HAS_GLITZ_SURFACE 1" >> src/cairo-features.h
endif
diff --git a/build/configure.ac.features b/build/configure.ac.features
index a7311c18..06ed7f3e 100644
--- a/build/configure.ac.features
+++ b/build/configure.ac.features
@@ -372,6 +372,7 @@ AC_DEFUN([CAIRO_REPORT],
echo " PostScript: $use_ps"
echo " PDF: $use_pdf"
echo " SVG: $use_svg"
+ echo " GL: $use_gl"
echo " glitz: $use_glitz"
echo " BeOS: $use_beos"
echo " DirectFB: $use_directfb"
diff --git a/configure.ac b/configure.ac
index d3ed7031..2cbd713c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -192,6 +192,13 @@ CAIRO_ENABLE_FUNCTIONS(png, PNG, yes, [
])
dnl ===========================================================================
+CAIRO_ENABLE_SURFACE_BACKEND(gl, gl, no, [
+ gl_REQUIRES="gl"
+ PKG_CHECK_MODULES(gl, $gl_REQUIRES, , [AC_MSG_RESULT(no)
+ use_gl="no (requires gl.pc)"])
+])
+
+dnl ===========================================================================
GLITZ_MIN_VERSION=0.5.1
CAIRO_ENABLE_SURFACE_BACKEND(glitz, glitz, no, [
diff --git a/perf/cairo-perf.c b/perf/cairo-perf.c
index 6bb48f13..6d93eb42 100644
--- a/perf/cairo-perf.c
+++ b/perf/cairo-perf.c
@@ -91,6 +91,7 @@ target_is_measurable (cairo_boilerplate_target_t *target)
return TRUE;
}
case CAIRO_SURFACE_TYPE_XCB:
+ case CAIRO_SURFACE_TYPE_GL:
case CAIRO_SURFACE_TYPE_GLITZ:
case CAIRO_SURFACE_TYPE_QUARTZ:
case CAIRO_SURFACE_TYPE_WIN32:
diff --git a/src/Makefile.sources b/src/Makefile.sources
index 174bb993..6407271e 100644
--- a/src/Makefile.sources
+++ b/src/Makefile.sources
@@ -244,6 +244,10 @@ cairo_os2_sources = cairo-os2-surface.c
cairo_beos_headers = cairo-beos.h
#cairo_beos_sources = cairo-beos-surface.cpp
+cairo_gl_headers = cairo-gl.h
+cairo_gl_private =
+cairo_gl_sources = cairo-gl-surface.c
+
cairo_glitz_headers = cairo-glitz.h
cairo_glitz_private = cairo-glitz-private.h
cairo_glitz_sources = cairo-glitz-surface.c
diff --git a/src/Makefile.win32.features b/src/Makefile.win32.features
index 921ab2d0..9e7bffe5 100644
--- a/src/Makefile.win32.features
+++ b/src/Makefile.win32.features
@@ -189,6 +189,20 @@ ifeq ($(CAIRO_HAS_PNG_FUNCTIONS),1)
enabled_cairo_pkgconf += cairo-png.pc
endif
+unsupported_cairo_headers += $(cairo_gl_headers)
+all_cairo_headers += $(cairo_gl_headers)
+all_cairo_private += $(cairo_gl_private)
+all_cairo_sources += $(cairo_gl_sources)
+ifeq ($(CAIRO_HAS_GL_SURFACE),1)
+enabled_cairo_headers += $(cairo_gl_headers)
+enabled_cairo_private += $(cairo_gl_private)
+enabled_cairo_sources += $(cairo_gl_sources)
+endif
+all_cairo_pkgconf += cairo-gl.pc
+ifeq ($(CAIRO_HAS_GL_SURFACE),1)
+enabled_cairo_pkgconf += cairo-gl.pc
+endif
+
unsupported_cairo_headers += $(cairo_glitz_headers)
all_cairo_headers += $(cairo_glitz_headers)
all_cairo_private += $(cairo_glitz_private)
diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c
new file mode 100644
index 00000000..2f1b153e
--- /dev/null
+++ b/src/cairo-gl-surface.c
@@ -0,0 +1,287 @@
+/* cairo - a vector graphics library with display and print output
+ *
+ * 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., 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 Red Hat, Inc.
+ *
+ * Contributor(s):
+ * Carl Worth <cworth@cworth.org>
+ */
+
+#include "cairoint.h"
+
+#include "cairo-gl.h"
+
+typedef struct _cairo_gl_surface {
+ cairo_surface_t base;
+
+ /* This is a cairo_image_surface to hold the actual contents. */
+ cairo_surface_t *backing;
+} cairo_gl_surface_t;
+
+struct _cairo_gl_context {
+ cairo_reference_count_t ref_count;
+ cairo_status_t status;
+
+ Display *dpy;
+ GLXContext gl_ctx;
+ cairo_mutex_t mutex; /* needed? */
+ cairo_gl_surface_t *current_target;
+};
+
+static const cairo_surface_backend_t cairo_gl_surface_backend;
+
+const cairo_gl_context_t _nil_context = {
+ CAIRO_REFERENCE_COUNT_INVALID,
+ CAIRO_STATUS_NO_MEMORY
+};
+
+static cairo_gl_context_t *
+_cairo_gl_context_create_in_error (cairo_status_t status)
+{
+ if (status == CAIRO_STATUS_NO_MEMORY)
+ return (cairo_gl_context_t *) &_nil_context;
+
+ ASSERT_NOT_REACHED;
+}
+
+cairo_gl_context_t *
+cairo_gl_glx_context_create (Display *dpy, GLXContext gl_ctx)
+{
+ cairo_gl_context_t *ctx;
+
+ ctx = calloc (1, sizeof(cairo_gl_context_t));
+ if (ctx == NULL)
+ return _cairo_gl_context_create_in_error (CAIRO_STATUS_NO_MEMORY);
+
+ CAIRO_REFERENCE_COUNT_INIT (&ctx->ref_count, 1);
+ ctx->dpy = dpy;
+ ctx->gl_ctx = gl_ctx;
+
+ /* Make our GL context active. While we'll be setting the destination
+ * drawable with each rendering operation, in order to set the context
+ * we have to choose a drawable. The root window happens to be convenient
+ * for this.
+ */
+ glXMakeCurrent(dpy, RootWindow (dpy, DefaultScreen (dpy)), gl_ctx);
+
+ return ctx;
+}
+
+void
+cairo_gl_context_destroy (cairo_gl_context_t *context)
+{
+ if (context == NULL ||
+ CAIRO_REFERENCE_COUNT_IS_INVALID (&context->ref_count))
+ {
+ return;
+ }
+
+ assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&context->ref_count));
+ if (! _cairo_reference_count_dec_and_test (&context->ref_count))
+ return;
+
+ free (context);
+}
+
+cairo_surface_t *
+cairo_gl_surface_create (cairo_gl_context_t *ctx,
+ cairo_content_t content,
+ int width,
+ int height)
+{
+ cairo_gl_surface_t *surface;
+ cairo_surface_t *backing;
+
+ backing = _cairo_image_surface_create_with_content (content, width, height);
+ if (cairo_surface_status (backing))
+ return backing;
+
+ surface = malloc (sizeof (cairo_gl_surface_t));
+ if (unlikely (surface == NULL)) {
+ cairo_surface_destroy (backing);
+ return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
+ }
+
+ _cairo_surface_init (&surface->base, &cairo_gl_surface_backend,
+ content);
+
+ surface->backing = backing;
+
+ return &surface->base;
+}
+
+static cairo_surface_t *
+_cairo_gl_surface_create_similar (void *abstract_surface,
+ cairo_content_t content,
+ int width,
+ int height)
+{
+ assert (CAIRO_CONTENT_VALID (content));
+
+ return cairo_gl_surface_create (NULL, content, width, height);
+}
+
+static cairo_status_t
+_cairo_gl_surface_finish (void *abstract_surface)
+{
+ cairo_gl_surface_t *surface = abstract_surface;
+
+ cairo_surface_destroy (surface->backing);
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cairo_gl_surface_acquire_source_image (void *abstract_surface,
+ cairo_image_surface_t **image_out,
+ void **image_extra)
+{
+ cairo_gl_surface_t *surface = abstract_surface;
+
+ return _cairo_surface_acquire_source_image (surface->backing,
+ image_out, image_extra);
+}
+
+static void
+_cairo_gl_surface_release_source_image (void *abstract_surface,
+ cairo_image_surface_t *image,
+ void *image_extra)
+{
+ cairo_gl_surface_t *surface = abstract_surface;
+
+ _cairo_surface_release_source_image (surface->backing,
+ image, image_extra);
+}
+
+static cairo_status_t
+_cairo_gl_surface_acquire_dest_image (void *abstract_surface,
+ cairo_rectangle_int_t *interest_rect,
+ cairo_image_surface_t **image_out,
+ cairo_rectangle_int_t *image_rect_out,
+ void **image_extra)
+{
+ cairo_gl_surface_t *surface = abstract_surface;
+
+ return _cairo_surface_acquire_dest_image (surface->backing,
+ interest_rect,
+ image_out,
+ image_rect_out,
+ image_extra);
+}
+
+static void
+_cairo_gl_surface_release_dest_image (void *abstract_surface,
+ cairo_rectangle_int_t *interest_rect,
+ cairo_image_surface_t *image,
+ cairo_rectangle_int_t *image_rect,
+ void *image_extra)
+{
+ cairo_gl_surface_t *surface = abstract_surface;
+
+ _cairo_surface_release_dest_image (surface->backing,
+ interest_rect,
+ image,
+ image_rect,
+ image_extra);
+}
+
+static cairo_status_t
+_cairo_gl_surface_clone_similar (void *abstract_surface,
+ cairo_surface_t *src,
+ int src_x,
+ int src_y,
+ int width,
+ int height,
+ int *clone_offset_x,
+ int *clone_offset_y,
+ cairo_surface_t **clone_out)
+{
+ cairo_gl_surface_t *surface = abstract_surface;
+
+ if (src->backend == surface->base.backend) {
+ *clone_offset_x = 0;
+ *clone_offset_y = 0;
+ *clone_out = cairo_surface_reference (src);
+
+ return CAIRO_STATUS_SUCCESS;
+ }
+
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+}
+
+static cairo_int_status_t
+_cairo_gl_surface_get_extents (void *abstract_surface,
+ cairo_rectangle_int_t *rectangle)
+{
+ cairo_gl_surface_t *surface = abstract_surface;
+
+ return _cairo_surface_get_extents (surface->backing, rectangle);
+}
+
+static const cairo_surface_backend_t cairo_gl_surface_backend = {
+ CAIRO_SURFACE_TYPE_GL,
+ _cairo_gl_surface_create_similar,
+ _cairo_gl_surface_finish,
+ _cairo_gl_surface_acquire_source_image,
+ _cairo_gl_surface_release_source_image,
+ _cairo_gl_surface_acquire_dest_image,
+ _cairo_gl_surface_release_dest_image,
+ _cairo_gl_surface_clone_similar,
+ NULL, /* composite */
+ NULL, /* fill_rectangles */
+ NULL, /* composite_trapezoids */
+ NULL, /* create_span_renderer */
+ NULL, /* check_span_renderer */
+ NULL, /* copy_page */
+ NULL, /* show_page */
+ NULL, /* set_clip_region */
+ NULL, /* intersect_clip_path */
+ _cairo_gl_surface_get_extents,
+ NULL, /* old_show_glyphs */
+ NULL, /* get_font_options */
+ NULL, /* flush */
+ NULL, /* mark_dirty_rectangle */
+ NULL, /* scaled_font_fini */
+ NULL, /* scaled_glyph_fini */
+ NULL, /* paint */
+ NULL, /* mask */
+ NULL, /* stroke */
+ NULL, /* fill */
+ NULL, /* show_glyphs */
+ NULL /* snapshot */
+};
+
+/** Call glFinish(), used for accurate performance testing. */
+cairo_status_t
+cairo_gl_surface_glfinish (cairo_surface_t *surface)
+{
+ glFinish();
+
+ return CAIRO_STATUS_SUCCESS;
+}
diff --git a/src/cairo-gl.h b/src/cairo-gl.h
new file mode 100644
index 00000000..ffe5879b
--- /dev/null
+++ b/src/cairo-gl.h
@@ -0,0 +1,89 @@
+/* Cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2009 Eric Anholt
+ * Copyright © 2009 Chris Wilson
+ *
+ * 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 Eric Anholt.
+ */
+
+#ifndef CAIRO_GL_H
+#define CAIRO_GL_H
+
+#include <GL/glx.h>
+
+#include "cairo.h"
+
+#if CAIRO_HAS_GL_SURFACE
+
+CAIRO_BEGIN_DECLS
+
+typedef struct _cairo_gl_context cairo_gl_context_t;
+
+cairo_public cairo_gl_context_t *
+cairo_gl_glx_context_create (Display *dpy, GLXContext gl_ctx);
+
+cairo_public cairo_gl_context_t *
+cairo_gl_context_reference (cairo_gl_context_t *context);
+
+cairo_public cairo_status_t
+cairo_gl_context_status (cairo_gl_context_t *context);
+
+cairo_public void
+cairo_gl_context_destroy (cairo_gl_context_t *context);
+
+cairo_public cairo_surface_t *
+cairo_gl_surface_create (cairo_gl_context_t *ctx,
+ cairo_content_t content,
+ int width, int height);
+
+cairo_public cairo_surface_t *
+cairo_gl_surface_create_for_window (cairo_gl_context_t *ctx,
+ Window win,
+ cairo_content_t content,
+ int width, int height);
+
+cairo_public cairo_gl_context_t *
+cairo_gl_surface_get_context (cairo_surface_t *abstract_surface);
+
+cairo_public int
+cairo_gl_surface_get_width (cairo_surface_t *surface);
+
+cairo_public int
+cairo_gl_surface_get_height (cairo_surface_t *surface);
+
+cairo_public cairo_status_t
+cairo_gl_surface_glfinish (cairo_surface_t *surface);
+
+CAIRO_END_DECLS
+
+#else /* CAIRO_HAS_GL_SURFACE */
+# error Cairo was not compiled with support for the GL backend
+#endif /* CAIRO_HAS_GL_SURFACE */
+
+#endif /* CAIRO_GL_H */
+
diff --git a/src/cairo-mutex-list-private.h b/src/cairo-mutex-list-private.h
index 8f62cb9f..97f1f35e 100644
--- a/src/cairo-mutex-list-private.h
+++ b/src/cairo-mutex-list-private.h
@@ -53,6 +53,10 @@ CAIRO_MUTEX_DECLARE (_cairo_ft_unscaled_font_map_mutex)
CAIRO_MUTEX_DECLARE (_cairo_xlib_display_mutex)
#endif
+#if CAIRO_HAS_GL_SURFACE
+CAIRO_MUTEX_DECLARE (_cairo_gl_context_mutex)
+#endif
+
#if !defined (HAS_ATOMIC_OPS) || defined (ATOMIC_OP_NEEDS_MEMORY_BARRIER)
CAIRO_MUTEX_DECLARE (_cairo_atomic_mutex)
#endif
diff --git a/src/cairo.h b/src/cairo.h
index 856f7afc..e35c9ca8 100644
--- a/src/cairo.h
+++ b/src/cairo.h
@@ -1879,6 +1879,7 @@ cairo_surface_status (cairo_surface_t *surface);
* @CAIRO_SURFACE_TYPE_QUARTZ_IMAGE: The surface is of type quartz_image
* @CAIRO_SURFACE_TYPE_SDL: The surface is of type SDL, since 1.10
* @CAIRO_SURFACE_TYPE_SCRIPT: The surface is of type script, since 1.10
+ * @CAIRO_SURFACE_TYPE_GL: The surface is of type OpenGL, since 1.10
*
* #cairo_surface_type_t is used to describe the type of a given
* surface. The surface types are also known as "backends" or "surface
@@ -1919,7 +1920,8 @@ typedef enum _cairo_surface_type {
CAIRO_SURFACE_TYPE_WIN32_PRINTING,
CAIRO_SURFACE_TYPE_QUARTZ_IMAGE,
CAIRO_SURFACE_TYPE_SDL,
- CAIRO_SURFACE_TYPE_SCRIPT
+ CAIRO_SURFACE_TYPE_SCRIPT,
+ CAIRO_SURFACE_TYPE_GL,
} cairo_surface_type_t;
cairo_public cairo_surface_type_t