From ca35e09ece5107c3ebc9f111d4a3d96d69aa3d03 Mon Sep 17 00:00:00 2001 From: Zoxc Date: Mon, 14 Jun 2010 20:34:52 +0200 Subject: gl: Added wgl boilerplate and moved the glx and egl boilerplates into their own files. --- boilerplate/Makefile.sources | 4 +- boilerplate/Makefile.win32.features | 8 + boilerplate/cairo-boilerplate-egl.c | 141 +++++++++++ boilerplate/cairo-boilerplate-gl.c | 492 ------------------------------------ boilerplate/cairo-boilerplate-glx.c | 401 +++++++++++++++++++++++++++++ boilerplate/cairo-boilerplate-wgl.c | 236 +++++++++++++++++ build/Makefile.win32.features-h | 1 + src/Makefile.win32.features | 8 + 8 files changed, 798 insertions(+), 493 deletions(-) create mode 100644 boilerplate/cairo-boilerplate-egl.c delete mode 100644 boilerplate/cairo-boilerplate-gl.c create mode 100644 boilerplate/cairo-boilerplate-glx.c create mode 100644 boilerplate/cairo-boilerplate-wgl.c diff --git a/boilerplate/Makefile.sources b/boilerplate/Makefile.sources index b590b7f1..d247510f 100644 --- a/boilerplate/Makefile.sources +++ b/boilerplate/Makefile.sources @@ -25,7 +25,9 @@ cairo_boilerplate_private = \ cairo_boilerplate_directfb_sources = cairo-boilerplate-directfb.c cairo_boilerplate_drm_sources = cairo-boilerplate-drm.c -cairo_boilerplate_gl_sources = cairo-boilerplate-gl.c +cairo_boilerplate_glx_sources = cairo-boilerplate-glx.c +cairo_boilerplate_wgl_sources = cairo-boilerplate-wgl.c +cairo_boilerplate_egl_sources = cairo-boilerplate-egl.c cairo_boilerplate_pdf_sources = cairo-boilerplate-pdf.c cairo_boilerplate_ps_sources = cairo-boilerplate-ps.c cairo_boilerplate_qt_sources = cairo-boilerplate-qt.cpp diff --git a/boilerplate/Makefile.win32.features b/boilerplate/Makefile.win32.features index fd0e9c73..d79fe2f2 100644 --- a/boilerplate/Makefile.win32.features +++ b/boilerplate/Makefile.win32.features @@ -209,6 +209,14 @@ enabled_cairo_boilerplate_private += $(cairo_boilerplate_png_private) enabled_cairo_boilerplate_sources += $(cairo_boilerplate_png_sources) endif +supported_cairo_boilerplate_headers += $(cairo_boilerplate_glew_headers) +all_cairo_boilerplate_headers += $(cairo_boilerplate_glew_headers) +all_cairo_boilerplate_private += $(cairo_boilerplate_glew_private) +all_cairo_boilerplate_sources += $(cairo_boilerplate_glew_sources) +enabled_cairo_boilerplate_headers += $(cairo_boilerplate_glew_headers) +enabled_cairo_boilerplate_private += $(cairo_boilerplate_glew_private) +enabled_cairo_boilerplate_sources += $(cairo_boilerplate_glew_sources) + unsupported_cairo_boilerplate_headers += $(cairo_boilerplate_gl_headers) all_cairo_boilerplate_headers += $(cairo_boilerplate_gl_headers) all_cairo_boilerplate_private += $(cairo_boilerplate_gl_private) diff --git a/boilerplate/cairo-boilerplate-egl.c b/boilerplate/cairo-boilerplate-egl.c new file mode 100644 index 00000000..413c7ed6 --- /dev/null +++ b/boilerplate/cairo-boilerplate-egl.c @@ -0,0 +1,141 @@ +/* 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., 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 Chris Wilson. + */ + +#include "cairo-boilerplate-private.h" + +#include + +static const cairo_user_data_key_t gl_closure_key; + +typedef struct _egl_target_closure { + EGLDisplay dpy; + EGLContext ctx; + + cairo_device_t *device; + cairo_surface_t *surface; +} egl_target_closure_t; + +static void +_cairo_boilerplate_egl_cleanup (void *closure) +{ + egl_target_closure_t *gltc = closure; + + cairo_device_finish (gltc->device); + cairo_device_destroy (gltc->device); + + eglDestroyContext (gltc->dpy, gltc->ctx); + eglMakeCurrent (gltc->dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + eglTerminate (gltc->dpy); + + free (gltc); +} + +static cairo_surface_t * +_cairo_boilerplate_egl_create_surface (const char *name, + cairo_content_t content, + double width, + double height, + double max_width, + double max_height, + cairo_boilerplate_mode_t mode, + int id, + void **closure) +{ + egl_target_closure_t *gltc; + cairo_surface_t *surface; + int major, minor; + EGLConfig *configs; + EGLint numConfigs; + + gltc = xcalloc (1, sizeof (egl_target_closure_t)); + *closure = gltc; + + gltc->dpy = eglGetDisplay (EGL_DEFAULT_DISPLAY); + + if (! eglInitialize (gltc->dpy, &major, &minor)) { + free (gltc); + return NULL; + } + + eglGetConfigs (gltc->dpy, NULL, 0, &numConfigs); + configs = xmalloc(sizeof(*configs) *numConfigs); + eglGetConfigs (gltc->dpy, configs, numConfigs, &numConfigs); + + eglBindAPI (EGL_OPENGL_API); + + gltc->ctx = eglCreateContext (gltc->dpy, configs[0], EGL_NO_CONTEXT, NULL); + if (gltc->ctx == EGL_NO_CONTEXT) { + eglTerminate (gltc->dpy); + free (gltc); + return NULL; + } + + gltc->device = cairo_egl_device_create (gltc->dpy, gltc->ctx); + + gltc->surface = surface = cairo_gl_surface_create (gltc->device, + content, + ceil (width), + ceil (height)); + if (cairo_surface_status (surface)) + _cairo_boilerplate_egl_cleanup (gltc); + + return surface; +} + +static void +_cairo_boilerplate_egl_synchronize (void *closure) +{ + egl_target_closure_t *gltc = closure; + + if (cairo_device_acquire (gltc->device)) + return; + + glFinish (); + + cairo_device_release (gltc->device); +} + +static const cairo_boilerplate_target_t targets[] = { + { + "egl", "gl", NULL, NULL, + CAIRO_SURFACE_TYPE_GL, CAIRO_CONTENT_COLOR_ALPHA, 1, + "cairo_egl_device_create", + _cairo_boilerplate_egl_create_surface, + NULL, NULL, + _cairo_boilerplate_get_image_surface, + cairo_surface_write_to_png, + _cairo_boilerplate_egl_cleanup, + _cairo_boilerplate_egl_synchronize, + TRUE, FALSE, FALSE + } +}; +CAIRO_BOILERPLATE (egl, targets) diff --git a/boilerplate/cairo-boilerplate-gl.c b/boilerplate/cairo-boilerplate-gl.c deleted file mode 100644 index 965beaac..00000000 --- a/boilerplate/cairo-boilerplate-gl.c +++ /dev/null @@ -1,492 +0,0 @@ -/* 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., 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 Chris Wilson. - */ - -#include "cairo-boilerplate-private.h" - -#include - -#include -#include /* for XDestroyImage */ - -static const cairo_user_data_key_t gl_closure_key; - -typedef struct _gl_target_closure { - Display *dpy; - int screen; - Window drawable; - - GLXContext ctx; - cairo_device_t *device; - cairo_surface_t *surface; -} gl_target_closure_t; - -static void -_cairo_boilerplate_gl_cleanup (void *closure) -{ - gl_target_closure_t *gltc = closure; - - cairo_device_finish (gltc->device); - cairo_device_destroy (gltc->device); - - glXDestroyContext (gltc->dpy, gltc->ctx); - - if (gltc->drawable) - XDestroyWindow (gltc->dpy, gltc->drawable); - XCloseDisplay (gltc->dpy); - - free (gltc); -} - -static cairo_surface_t * -_cairo_boilerplate_gl_create_surface (const char *name, - cairo_content_t content, - double width, - double height, - double max_width, - double max_height, - cairo_boilerplate_mode_t mode, - int id, - void **closure) -{ - int rgba_attribs[] = { GLX_RGBA, - GLX_RED_SIZE, 1, - GLX_GREEN_SIZE, 1, - GLX_BLUE_SIZE, 1, - GLX_ALPHA_SIZE, 1, - GLX_DOUBLEBUFFER, - None }; - int rgb_attribs[] = { GLX_RGBA, - GLX_RED_SIZE, 1, - GLX_GREEN_SIZE, 1, - GLX_BLUE_SIZE, 1, - GLX_DOUBLEBUFFER, - None }; - XVisualInfo *visinfo; - GLXContext ctx; - gl_target_closure_t *gltc; - cairo_surface_t *surface; - Display *dpy; - - gltc = calloc (1, 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); - - if (content == CAIRO_CONTENT_COLOR) - visinfo = glXChooseVisual (dpy, DefaultScreen (dpy), rgb_attribs); - else - visinfo = glXChooseVisual (dpy, DefaultScreen (dpy), rgba_attribs); - - if (visinfo == NULL) { - fprintf (stderr, "Failed to create RGB, double-buffered visual\n"); - XCloseDisplay (dpy); - free (gltc); - return NULL; - } - - ctx = glXCreateContext (dpy, visinfo, NULL, True); - XFree (visinfo); - - gltc->ctx = ctx; - gltc->device = cairo_glx_device_create (dpy, ctx); - - gltc->surface = surface = cairo_gl_surface_create (gltc->device, - content, - ceil (width), - ceil (height)); - if (cairo_surface_status (surface)) - _cairo_boilerplate_gl_cleanup (gltc); - - return surface; -} - -static cairo_surface_t * -_cairo_boilerplate_gl_create_window (const char *name, - cairo_content_t content, - double width, - double height, - double max_width, - double max_height, - cairo_boilerplate_mode_t mode, - int id, - void **closure) -{ - int rgba_attribs[] = { GLX_RGBA, - GLX_RED_SIZE, 1, - GLX_GREEN_SIZE, 1, - GLX_BLUE_SIZE, 1, - GLX_ALPHA_SIZE, 1, - GLX_DOUBLEBUFFER, - None }; - XVisualInfo *vi; - GLXContext ctx; - gl_target_closure_t *gltc; - cairo_surface_t *surface; - Display *dpy; - XSetWindowAttributes attr; - - gltc = calloc (1, 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); - - vi = glXChooseVisual (dpy, DefaultScreen (dpy), rgba_attribs); - if (vi == NULL) { - fprintf (stderr, "Failed to create RGBA, double-buffered visual\n"); - XCloseDisplay (dpy); - free (gltc); - return NULL; - } - - attr.colormap = XCreateColormap (dpy, - RootWindow (dpy, vi->screen), - vi->visual, - AllocNone); - attr.border_pixel = 0; - attr.override_redirect = True; - gltc->drawable = XCreateWindow (dpy, DefaultRootWindow (dpy), 0, 0, - width, height, 0, vi->depth, - InputOutput, vi->visual, - CWOverrideRedirect | CWBorderPixel | CWColormap, - &attr); - XMapWindow (dpy, gltc->drawable); - - ctx = glXCreateContext (dpy, vi, NULL, True); - XFree (vi); - - gltc->ctx = ctx; - gltc->device = cairo_glx_device_create (dpy, ctx); - - gltc->surface = surface = cairo_gl_surface_create_for_window (gltc->device, - gltc->drawable, - ceil (width), - ceil (height)); - if (cairo_surface_status (surface)) - _cairo_boilerplate_gl_cleanup (gltc); - - return surface; -} - -static cairo_surface_t * -_cairo_boilerplate_gl_create_window_db (const char *name, - cairo_content_t content, - double width, - double height, - double max_width, - double max_height, - cairo_boilerplate_mode_t mode, - int id, - void **closure) -{ - int rgba_attribs[] = { GLX_RGBA, - GLX_RED_SIZE, 1, - GLX_GREEN_SIZE, 1, - GLX_BLUE_SIZE, 1, - GLX_ALPHA_SIZE, 1, - GLX_DOUBLEBUFFER, - None }; - XVisualInfo *vi; - GLXContext ctx; - gl_target_closure_t *gltc; - cairo_surface_t *surface; - Display *dpy; - XSetWindowAttributes attr; - cairo_status_t status; - - gltc = calloc (1, 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); - - vi = glXChooseVisual (dpy, DefaultScreen (dpy), rgba_attribs); - if (vi == NULL) { - fprintf (stderr, "Failed to create RGBA, double-buffered visual\n"); - XCloseDisplay (dpy); - free (gltc); - return NULL; - } - - attr.colormap = XCreateColormap (dpy, - RootWindow (dpy, vi->screen), - vi->visual, - AllocNone); - attr.border_pixel = 0; - attr.override_redirect = True; - gltc->drawable = XCreateWindow (dpy, DefaultRootWindow (dpy), 0, 0, - width, height, 0, vi->depth, - InputOutput, vi->visual, - CWOverrideRedirect | CWBorderPixel | CWColormap, - &attr); - XMapWindow (dpy, gltc->drawable); - - ctx = glXCreateContext (dpy, vi, NULL, True); - XFree (vi); - - gltc->ctx = ctx; - gltc->device = cairo_glx_device_create (dpy, ctx); - - gltc->surface = cairo_gl_surface_create_for_window (gltc->device, - gltc->drawable, - ceil (width), - ceil (height)); - surface = cairo_surface_create_similar (gltc->surface, content, width, height); - status = cairo_surface_set_user_data (surface, &gl_closure_key, gltc, NULL); - if (status == CAIRO_STATUS_SUCCESS) - return surface; - - cairo_surface_destroy (surface); - _cairo_boilerplate_gl_cleanup (gltc); - return cairo_boilerplate_surface_create_in_error (status); -} - -static cairo_status_t -_cairo_boilerplate_gl_finish_window (cairo_surface_t *surface) -{ - gl_target_closure_t *gltc = cairo_surface_get_user_data (surface, - &gl_closure_key); - - if (gltc != NULL && gltc->surface != NULL) { - cairo_t *cr; - - cr = cairo_create (gltc->surface); - cairo_surface_set_device_offset (surface, 0, 0); - cairo_set_source_surface (cr, surface, 0, 0); - cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); - cairo_paint (cr); - cairo_destroy (cr); - - surface = gltc->surface; - } - - cairo_gl_surface_swapbuffers (surface); - return CAIRO_STATUS_SUCCESS; -} - -static void -_cairo_boilerplate_gl_synchronize (void *closure) -{ - gl_target_closure_t *gltc = closure; - - if (cairo_device_acquire (gltc->device)) - return; - - glFinish (); - - cairo_device_release (gltc->device); -} - -#if CAIRO_HAS_EGL_FUNCTIONS -typedef struct _egl_target_closure { - EGLDisplay dpy; - EGLContext ctx; - - cairo_device_t *device; - cairo_surface_t *surface; -} egl_target_closure_t; - -static void -_cairo_boilerplate_egl_cleanup (void *closure) -{ - egl_target_closure_t *gltc = closure; - - cairo_device_finish (gltc->device); - cairo_device_destroy (gltc->device); - - eglDestroyContext (gltc->dpy, gltc->ctx); - eglMakeCurrent (gltc->dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); - eglTerminate (gltc->dpy); - - free (gltc); -} - -static cairo_surface_t * -_cairo_boilerplate_egl_create_surface (const char *name, - cairo_content_t content, - double width, - double height, - double max_width, - double max_height, - cairo_boilerplate_mode_t mode, - int id, - void **closure) -{ - egl_target_closure_t *gltc; - cairo_surface_t *surface; - int major, minor; - EGLConfig *configs; - EGLint numConfigs; - - gltc = xcalloc (1, sizeof (gl_target_closure_t)); - *closure = gltc; - - gltc->dpy = eglGetDisplay (EGL_DEFAULT_DISPLAY); - - if (! eglInitialize (gltc->dpy, &major, &minor)) { - free (gltc); - return NULL; - } - - eglGetConfigs (gltc->dpy, NULL, 0, &numConfigs); - configs = xmalloc(sizeof(*configs) *numConfigs); - eglGetConfigs (gltc->dpy, configs, numConfigs, &numConfigs); - - eglBindAPI (EGL_OPENGL_API); - - gltc->ctx = eglCreateContext (gltc->dpy, configs[0], EGL_NO_CONTEXT, NULL); - if (gltc->ctx == EGL_NO_CONTEXT) { - eglTerminate (gltc->dpy); - free (gltc); - return NULL; - } - - gltc->device = cairo_egl_device_create (gltc->dpy, gltc->ctx); - - gltc->surface = surface = cairo_gl_surface_create (gltc->device, - content, - ceil (width), - ceil (height)); - if (cairo_surface_status (surface)) - _cairo_boilerplate_egl_cleanup (gltc); - - return surface; -} -#endif - -static const cairo_boilerplate_target_t targets[] = { - { - "gl", "gl", NULL, NULL, - CAIRO_SURFACE_TYPE_GL, CAIRO_CONTENT_COLOR_ALPHA, 1, - "cairo_gl_surface_create", - _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, - TRUE, FALSE, FALSE - }, - { - "gl", "gl", NULL, NULL, - CAIRO_SURFACE_TYPE_GL, CAIRO_CONTENT_COLOR, 1, - "cairo_gl_surface_create", - _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, - FALSE, FALSE, FALSE - }, - { - "gl-window", "gl", NULL, NULL, - CAIRO_SURFACE_TYPE_GL, CAIRO_CONTENT_COLOR_ALPHA, 1, - "cairo_gl_surface_create_for_window", - _cairo_boilerplate_gl_create_window, - NULL, - _cairo_boilerplate_gl_finish_window, - _cairo_boilerplate_get_image_surface, - cairo_surface_write_to_png, - _cairo_boilerplate_gl_cleanup, - _cairo_boilerplate_gl_synchronize, - FALSE, FALSE, FALSE - }, - { - "gl-window&", "gl", NULL, NULL, - CAIRO_SURFACE_TYPE_GL, CAIRO_CONTENT_COLOR_ALPHA, 1, - "cairo_gl_surface_create_for_window", - _cairo_boilerplate_gl_create_window_db, - NULL, - _cairo_boilerplate_gl_finish_window, - _cairo_boilerplate_get_image_surface, - cairo_surface_write_to_png, - _cairo_boilerplate_gl_cleanup, - _cairo_boilerplate_gl_synchronize, - FALSE, FALSE, FALSE - }, -#if CAIRO_HAS_EGL_FUNCTIONS - { - "egl", "gl", NULL, NULL, - CAIRO_SURFACE_TYPE_GL, CAIRO_CONTENT_COLOR_ALPHA, 1, - "cairo_egl_device_create", - _cairo_boilerplate_egl_create_surface, - NULL, NULL, - _cairo_boilerplate_get_image_surface, - cairo_surface_write_to_png, - _cairo_boilerplate_egl_cleanup, - _cairo_boilerplate_gl_synchronize, - TRUE, FALSE, FALSE - }, -#endif -}; -CAIRO_BOILERPLATE (gl, targets) diff --git a/boilerplate/cairo-boilerplate-glx.c b/boilerplate/cairo-boilerplate-glx.c new file mode 100644 index 00000000..66a031b1 --- /dev/null +++ b/boilerplate/cairo-boilerplate-glx.c @@ -0,0 +1,401 @@ +/* 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., 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 Chris Wilson. + */ + +#include "cairo-boilerplate-private.h" + +#include + +#include +#include /* for XDestroyImage */ + +static const cairo_user_data_key_t gl_closure_key; + +typedef struct _gl_target_closure { + Display *dpy; + int screen; + Window drawable; + + GLXContext ctx; + cairo_device_t *device; + cairo_surface_t *surface; +} gl_target_closure_t; + +static void +_cairo_boilerplate_gl_cleanup (void *closure) +{ + gl_target_closure_t *gltc = closure; + + cairo_device_finish (gltc->device); + cairo_device_destroy (gltc->device); + + glXDestroyContext (gltc->dpy, gltc->ctx); + + if (gltc->drawable) + XDestroyWindow (gltc->dpy, gltc->drawable); + XCloseDisplay (gltc->dpy); + + free (gltc); +} + +static cairo_surface_t * +_cairo_boilerplate_gl_create_surface (const char *name, + cairo_content_t content, + double width, + double height, + double max_width, + double max_height, + cairo_boilerplate_mode_t mode, + int id, + void **closure) +{ + int rgba_attribs[] = { GLX_RGBA, + GLX_RED_SIZE, 1, + GLX_GREEN_SIZE, 1, + GLX_BLUE_SIZE, 1, + GLX_ALPHA_SIZE, 1, + GLX_DOUBLEBUFFER, + None }; + int rgb_attribs[] = { GLX_RGBA, + GLX_RED_SIZE, 1, + GLX_GREEN_SIZE, 1, + GLX_BLUE_SIZE, 1, + GLX_DOUBLEBUFFER, + None }; + XVisualInfo *visinfo; + GLXContext ctx; + gl_target_closure_t *gltc; + cairo_surface_t *surface; + Display *dpy; + + gltc = calloc (1, 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); + + if (content == CAIRO_CONTENT_COLOR) + visinfo = glXChooseVisual (dpy, DefaultScreen (dpy), rgb_attribs); + else + visinfo = glXChooseVisual (dpy, DefaultScreen (dpy), rgba_attribs); + + if (visinfo == NULL) { + fprintf (stderr, "Failed to create RGB, double-buffered visual\n"); + XCloseDisplay (dpy); + free (gltc); + return NULL; + } + + ctx = glXCreateContext (dpy, visinfo, NULL, True); + XFree (visinfo); + + gltc->ctx = ctx; + gltc->device = cairo_glx_device_create (dpy, ctx); + + gltc->surface = surface = cairo_gl_surface_create (gltc->device, + content, + ceil (width), + ceil (height)); + if (cairo_surface_status (surface)) + _cairo_boilerplate_gl_cleanup (gltc); + + return surface; +} + +static cairo_surface_t * +_cairo_boilerplate_gl_create_window (const char *name, + cairo_content_t content, + double width, + double height, + double max_width, + double max_height, + cairo_boilerplate_mode_t mode, + int id, + void **closure) +{ + int rgba_attribs[] = { GLX_RGBA, + GLX_RED_SIZE, 1, + GLX_GREEN_SIZE, 1, + GLX_BLUE_SIZE, 1, + GLX_ALPHA_SIZE, 1, + GLX_DOUBLEBUFFER, + None }; + XVisualInfo *vi; + GLXContext ctx; + gl_target_closure_t *gltc; + cairo_surface_t *surface; + Display *dpy; + XSetWindowAttributes attr; + + gltc = calloc (1, 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); + + vi = glXChooseVisual (dpy, DefaultScreen (dpy), rgba_attribs); + if (vi == NULL) { + fprintf (stderr, "Failed to create RGBA, double-buffered visual\n"); + XCloseDisplay (dpy); + free (gltc); + return NULL; + } + + attr.colormap = XCreateColormap (dpy, + RootWindow (dpy, vi->screen), + vi->visual, + AllocNone); + attr.border_pixel = 0; + attr.override_redirect = True; + gltc->drawable = XCreateWindow (dpy, DefaultRootWindow (dpy), 0, 0, + width, height, 0, vi->depth, + InputOutput, vi->visual, + CWOverrideRedirect | CWBorderPixel | CWColormap, + &attr); + XMapWindow (dpy, gltc->drawable); + + ctx = glXCreateContext (dpy, vi, NULL, True); + XFree (vi); + + gltc->ctx = ctx; + gltc->device = cairo_glx_device_create (dpy, ctx); + + gltc->surface = surface = cairo_gl_surface_create_for_window (gltc->device, + gltc->drawable, + ceil (width), + ceil (height)); + if (cairo_surface_status (surface)) + _cairo_boilerplate_gl_cleanup (gltc); + + return surface; +} + +static cairo_surface_t * +_cairo_boilerplate_gl_create_window_db (const char *name, + cairo_content_t content, + double width, + double height, + double max_width, + double max_height, + cairo_boilerplate_mode_t mode, + int id, + void **closure) +{ + int rgba_attribs[] = { GLX_RGBA, + GLX_RED_SIZE, 1, + GLX_GREEN_SIZE, 1, + GLX_BLUE_SIZE, 1, + GLX_ALPHA_SIZE, 1, + GLX_DOUBLEBUFFER, + None }; + XVisualInfo *vi; + GLXContext ctx; + gl_target_closure_t *gltc; + cairo_surface_t *surface; + Display *dpy; + XSetWindowAttributes attr; + cairo_status_t status; + + gltc = calloc (1, 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); + + vi = glXChooseVisual (dpy, DefaultScreen (dpy), rgba_attribs); + if (vi == NULL) { + fprintf (stderr, "Failed to create RGBA, double-buffered visual\n"); + XCloseDisplay (dpy); + free (gltc); + return NULL; + } + + attr.colormap = XCreateColormap (dpy, + RootWindow (dpy, vi->screen), + vi->visual, + AllocNone); + attr.border_pixel = 0; + attr.override_redirect = True; + gltc->drawable = XCreateWindow (dpy, DefaultRootWindow (dpy), 0, 0, + width, height, 0, vi->depth, + InputOutput, vi->visual, + CWOverrideRedirect | CWBorderPixel | CWColormap, + &attr); + XMapWindow (dpy, gltc->drawable); + + ctx = glXCreateContext (dpy, vi, NULL, True); + XFree (vi); + + gltc->ctx = ctx; + gltc->device = cairo_glx_device_create (dpy, ctx); + + gltc->surface = cairo_gl_surface_create_for_window (gltc->device, + gltc->drawable, + ceil (width), + ceil (height)); + surface = cairo_surface_create_similar (gltc->surface, content, width, height); + status = cairo_surface_set_user_data (surface, &gl_closure_key, gltc, NULL); + if (status == CAIRO_STATUS_SUCCESS) + return surface; + + cairo_surface_destroy (surface); + _cairo_boilerplate_gl_cleanup (gltc); + return cairo_boilerplate_surface_create_in_error (status); +} + +static cairo_status_t +_cairo_boilerplate_gl_finish_window (cairo_surface_t *surface) +{ + gl_target_closure_t *gltc = cairo_surface_get_user_data (surface, + &gl_closure_key); + + if (gltc != NULL && gltc->surface != NULL) { + cairo_t *cr; + + cr = cairo_create (gltc->surface); + cairo_surface_set_device_offset (surface, 0, 0); + cairo_set_source_surface (cr, surface, 0, 0); + cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); + cairo_paint (cr); + cairo_destroy (cr); + + surface = gltc->surface; + } + + cairo_gl_surface_swapbuffers (surface); + return CAIRO_STATUS_SUCCESS; +} + +static void +_cairo_boilerplate_gl_synchronize (void *closure) +{ + gl_target_closure_t *gltc = closure; + + if (cairo_device_acquire (gltc->device)) + return; + + glFinish (); + + cairo_device_release (gltc->device); +} + +static const cairo_boilerplate_target_t targets[] = { + { + "gl", "gl", NULL, NULL, + CAIRO_SURFACE_TYPE_GL, CAIRO_CONTENT_COLOR_ALPHA, 1, + "cairo_gl_surface_create", + _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, + TRUE, FALSE, FALSE + }, + { + "gl", "gl", NULL, NULL, + CAIRO_SURFACE_TYPE_GL, CAIRO_CONTENT_COLOR, 1, + "cairo_gl_surface_create", + _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, + FALSE, FALSE, FALSE + }, + { + "gl-window", "gl", NULL, NULL, + CAIRO_SURFACE_TYPE_GL, CAIRO_CONTENT_COLOR_ALPHA, 1, + "cairo_gl_surface_create_for_window", + _cairo_boilerplate_gl_create_window, + NULL, + _cairo_boilerplate_gl_finish_window, + _cairo_boilerplate_get_image_surface, + cairo_surface_write_to_png, + _cairo_boilerplate_gl_cleanup, + _cairo_boilerplate_gl_synchronize, + FALSE, FALSE, FALSE + }, + { + "gl-window&", "gl", NULL, NULL, + CAIRO_SURFACE_TYPE_GL, CAIRO_CONTENT_COLOR_ALPHA, 1, + "cairo_gl_surface_create_for_window", + _cairo_boilerplate_gl_create_window_db, + NULL, + _cairo_boilerplate_gl_finish_window, + _cairo_boilerplate_get_image_surface, + cairo_surface_write_to_png, + _cairo_boilerplate_gl_cleanup, + _cairo_boilerplate_gl_synchronize, + FALSE, FALSE, FALSE + }, +}; +CAIRO_BOILERPLATE (gl, targets) diff --git a/boilerplate/cairo-boilerplate-wgl.c b/boilerplate/cairo-boilerplate-wgl.c new file mode 100644 index 00000000..559cc11b --- /dev/null +++ b/boilerplate/cairo-boilerplate-wgl.c @@ -0,0 +1,236 @@ +/* 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., 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 Chris Wilson. + * + * Contributor(s): + * Zoxc + */ + +#include "cairo-boilerplate-private.h" + +#include + +static const cairo_user_data_key_t gl_closure_key; + +typedef struct _wgl_target_closure { + HWND wnd; + HDC dc; + HGLRC rc; + cairo_device_t *device; + cairo_surface_t *surface; +} wgl_target_closure_t; + +static void +_cairo_boilerplate_wgl_cleanup (void *closure) +{ + wgl_target_closure_t *wgltc = closure; + + cairo_device_finish (wgltc->device); + cairo_device_destroy (wgltc->device); + + wglDeleteContext(wgltc->rc); + + ReleaseDC(wgltc->wnd, wgltc->dc); + DestroyWindow (wgltc->wnd); + + free (wgltc); +} + +static void +_cairo_boilerplate_wgl_create_window (int width, int height, wgl_target_closure_t *wgltc) +{ + WNDCLASSEXA wincl; + PIXELFORMATDESCRIPTOR pfd; + int format; + cairo_surface_t *surface; + + ZeroMemory (&wincl, sizeof (WNDCLASSEXA)); + wincl.cbSize = sizeof (WNDCLASSEXA); + wincl.hInstance = GetModuleHandle (0); + wincl.lpszClassName = "cairo_boilerplate_wgl_dummy"; + wincl.lpfnWndProc = DefWindowProcA; + wincl.style = CS_OWNDC; + + RegisterClassExA (&wincl); + + wgltc->wnd = CreateWindow ("cairo_boilerplate_wgl_dummy", 0, WS_POPUP, 0, 0, width, height, 0, 0, 0, 0); + wgltc->dc = GetDC (wgltc->wnd); + + ZeroMemory (&pfd, sizeof (PIXELFORMATDESCRIPTOR)); + pfd.nSize = sizeof (PIXELFORMATDESCRIPTOR); + pfd.nVersion = 1; + pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; + pfd.iPixelType = PFD_TYPE_RGBA; + pfd.cColorBits = 24; + pfd.cDepthBits = 16; + pfd.iLayerType = PFD_MAIN_PLANE; + + format = ChoosePixelFormat (wgltc->dc, &pfd); + SetPixelFormat (wgltc->dc, format, &pfd); + + wgltc->rc = wglCreateContext (wgltc->dc); + wgltc->device = cairo_wgl_device_create (wgltc->rc); +} + +static cairo_surface_t * +_cairo_boilerplate_wgl_create_surface (const char *name, + cairo_content_t content, + double width, + double height, + double max_width, + double max_height, + cairo_boilerplate_mode_t mode, + int id, + void **closure) +{ + wgl_target_closure_t *wgltc; + cairo_surface_t *surface; + + wgltc = calloc (1, sizeof (wgl_target_closure_t)); + + *closure = wgltc; + + _cairo_boilerplate_wgl_create_window(0, 0, wgltc); + + if (width == 0) + width = 1; + if (height == 0) + height = 1; + + wgltc->surface = surface = cairo_gl_surface_create (wgltc->device, + content, + ceil (width), + ceil (height)); + if (cairo_surface_status (surface)) { + _cairo_boilerplate_wgl_cleanup (wgltc); + return NULL; + } + + return surface; +} + +static cairo_surface_t * +_cairo_boilerplate_wgl_for_create_window (const char *name, + cairo_content_t content, + double width, + double height, + double max_width, + double max_height, + cairo_boilerplate_mode_t mode, + int id, + void **closure) +{ + wgl_target_closure_t *wgltc; + cairo_surface_t *surface; + + wgltc = calloc (1, sizeof (wgl_target_closure_t)); + + *closure = wgltc; + + _cairo_boilerplate_wgl_create_window(width, height, wgltc); + + wgltc->surface = surface = cairo_gl_surface_create_for_dc (wgltc->device, + wgltc->dc, + ceil (width), + ceil (height)); + + if (cairo_surface_status (surface)) { + _cairo_boilerplate_wgl_cleanup (wgltc); + return NULL; + } + + return surface; +} + +static cairo_status_t +_cairo_boilerplate_wgl_finish_window (cairo_surface_t *surface) +{ + wgl_target_closure_t *wgltc = cairo_surface_get_user_data (surface, + &gl_closure_key); + + if (wgltc != NULL && wgltc->surface != NULL) { + cairo_t *cr; + + cr = cairo_create (wgltc->surface); + cairo_surface_set_device_offset (surface, 0, 0); + cairo_set_source_surface (cr, surface, 0, 0); + cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); + cairo_paint (cr); + cairo_destroy (cr); + + surface = wgltc->surface; + } + + cairo_gl_surface_swapbuffers (surface); + return CAIRO_STATUS_SUCCESS; +} + +static void +_cairo_boilerplate_wgl_synchronize (void *closure) +{ + wgl_target_closure_t *wgltc = closure; + + if (cairo_device_acquire (wgltc->device)) + return; + + //glFinish (); + + cairo_device_release (wgltc->device); +} + +static const cairo_boilerplate_target_t targets[] = { + { + "gl", "gl", NULL, NULL, + CAIRO_SURFACE_TYPE_GL, CAIRO_CONTENT_COLOR_ALPHA, 1, + "cairo_gl_surface_create", + _cairo_boilerplate_wgl_create_surface, + NULL, NULL, + _cairo_boilerplate_get_image_surface, + cairo_surface_write_to_png, + _cairo_boilerplate_wgl_cleanup, + _cairo_boilerplate_wgl_synchronize, + TRUE, FALSE, FALSE + }, + { + "gl-dc", "gl", NULL, NULL, + CAIRO_SURFACE_TYPE_GL, CAIRO_CONTENT_COLOR_ALPHA, 1, + "cairo_gl_surface_create_for_dc", + _cairo_boilerplate_wgl_for_create_window, + NULL, + _cairo_boilerplate_wgl_finish_window, + _cairo_boilerplate_get_image_surface, + cairo_surface_write_to_png, + _cairo_boilerplate_wgl_cleanup, + _cairo_boilerplate_wgl_synchronize, + FALSE, FALSE, FALSE + }, +}; + +CAIRO_BOILERPLATE (wgl, targets) diff --git a/build/Makefile.win32.features-h b/build/Makefile.win32.features-h index 9d9468cd..9aec98ce 100644 --- a/build/Makefile.win32.features-h +++ b/build/Makefile.win32.features-h @@ -62,6 +62,7 @@ endif ifeq ($(CAIRO_HAS_PNG_FUNCTIONS),1) @echo "#define CAIRO_HAS_PNG_FUNCTIONS 1" >> src/cairo-features.h endif + @echo "#define CAIRO_HAS_GLEW_FUNCTIONS 1" >> src/cairo-features.h ifeq ($(CAIRO_HAS_GL_SURFACE),1) @echo "#define CAIRO_HAS_GL_SURFACE 1" >> src/cairo-features.h endif diff --git a/src/Makefile.win32.features b/src/Makefile.win32.features index 3cbdd2e3..f99cb661 100644 --- a/src/Makefile.win32.features +++ b/src/Makefile.win32.features @@ -287,6 +287,14 @@ ifeq ($(CAIRO_HAS_PNG_FUNCTIONS),1) enabled_cairo_pkgconf += cairo-png.pc endif +supported_cairo_headers += $(cairo_glew_headers) +all_cairo_headers += $(cairo_glew_headers) +all_cairo_private += $(cairo_glew_private) +all_cairo_sources += $(cairo_glew_sources) +enabled_cairo_headers += $(cairo_glew_headers) +enabled_cairo_private += $(cairo_glew_private) +enabled_cairo_sources += $(cairo_glew_sources) + unsupported_cairo_headers += $(cairo_gl_headers) all_cairo_headers += $(cairo_gl_headers) all_cairo_private += $(cairo_gl_private) -- cgit v1.2.3