diff options
43 files changed, 1 insertions, 14014 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 699fdbf1f..e7479889e 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -16,9 +16,6 @@ variables: DEFAULT_MESON_ARGS: > --default-library=both - -Dgl-backend=auto - -Dglesv2=auto - -Dglesv3=auto stages: - prep @@ -78,12 +75,6 @@ fedora image: pixman-devel systemd-devel systemd-udev - mesa-libEGL - mesa-libGL - mesa-libGL-devel - mesa-libgbm - mesa-libgbm-devel - mesa-libglapi expat-devel autoconf automake @@ -229,7 +220,6 @@ fedora meson build: variables: MESON_ARGS: > ${DEFAULT_MESON_ARGS} - -Dgl-backend=gl script: - export CFLAGS="-Werror -Wno-error=deprecated-declarations" - meson builddir ${MESON_ARGS} diff --git a/boilerplate/cairo-boilerplate-egl.c b/boilerplate/cairo-boilerplate-egl.c deleted file mode 100644 index 8196b1ffd..000000000 --- a/boilerplate/cairo-boilerplate-egl.c +++ /dev/null @@ -1,192 +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 <cairo-gl.h> -#if CAIRO_HAS_GLESV3_SURFACE -#include <GLES3/gl3.h> -#include <EGL/eglext.h> -#elif CAIRO_HAS_GLESV2_SURFACE -#include <GLES2/gl2.h> -#elif CAIRO_HAS_GL_SURFACE -#include <GL/gl.h> -#endif - -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, - void **closure) -{ - egl_target_closure_t *gltc; - cairo_surface_t *surface; - int major, minor; - EGLConfig config; - EGLint numConfigs; - EGLint config_attribs[] = { - EGL_RED_SIZE, 8, - EGL_GREEN_SIZE, 8, - EGL_BLUE_SIZE, 8, - EGL_ALPHA_SIZE, 8, - EGL_SURFACE_TYPE, EGL_PBUFFER_BIT, -#if CAIRO_HAS_GLESV3_SURFACE - EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT_KHR, -#elif CAIRO_HAS_GLESV2_SURFACE - EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, -#elif CAIRO_HAS_GL_SURFACE - EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT, -#endif - EGL_NONE - }; - const EGLint ctx_attribs[] = { -#if CAIRO_HAS_GLESV3_SURFACE - EGL_CONTEXT_CLIENT_VERSION, 3, -#elif CAIRO_HAS_GLESV2_SURFACE - EGL_CONTEXT_CLIENT_VERSION, 2, -#endif - EGL_NONE - }; - - 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; - } - - eglChooseConfig (gltc->dpy, config_attribs, &config, 1, &numConfigs); -#if CAIRO_HAS_GLESV3_SURFACE && CAIRO_HAS_GLESV2_SURFACE - if (numConfigs == 0) { - /* retry with ES2_BIT */ - config_attribs[11] = ES2_BIT; /* FIXME: Ick */ - eglChooseConfig (gltc->dpy, config_attribs, &config, 1, &numConfigs); - } -#endif - if (numConfigs == 0) { - free (gltc); - return NULL; - } - -#if CAIRO_HAS_GLESV3_SURFACE || CAIRO_HAS_GLESV2_SURFACE - eglBindAPI (EGL_OPENGL_ES_API); -#elif CAIRO_HAS_GL_SURFACE - eglBindAPI (EGL_OPENGL_API); -#endif - - gltc->ctx = eglCreateContext (gltc->dpy, config, EGL_NO_CONTEXT, - ctx_attribs); - if (gltc->ctx == EGL_NO_CONTEXT) { - eglTerminate (gltc->dpy); - free (gltc); - return NULL; - } - - gltc->device = cairo_egl_device_create (gltc->dpy, gltc->ctx); - if (mode == CAIRO_BOILERPLATE_MODE_PERF) - cairo_gl_device_set_thread_aware(gltc->device, FALSE); - - if (width < 1) - width = 1; - if (height < 1) - height = 1; - - 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, - cairo_surface_create_similar, - NULL, NULL, - _cairo_boilerplate_get_image_surface, - cairo_surface_write_to_png, - _cairo_boilerplate_egl_cleanup, - _cairo_boilerplate_egl_synchronize, - NULL, - TRUE, FALSE, FALSE - } -}; -CAIRO_BOILERPLATE (egl, targets) diff --git a/boilerplate/cairo-boilerplate-glx.c b/boilerplate/cairo-boilerplate-glx.c deleted file mode 100644 index 7701d908f..000000000 --- a/boilerplate/cairo-boilerplate-glx.c +++ /dev/null @@ -1,457 +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 <cairo-gl.h> - -#include <X11/X.h> -#include <X11/Xutil.h> /* 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, - 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; - - width = ceil (width); - height = ceil (height); - - 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); - - if (mode == CAIRO_BOILERPLATE_MODE_PERF) - cairo_gl_device_set_thread_aware(gltc->device, FALSE); - - gltc->surface = surface = cairo_gl_surface_create (gltc->device, - content, width, height); - if (cairo_surface_status (surface)) - _cairo_boilerplate_gl_cleanup (gltc); - - return surface; -} - -static cairo_surface_t * -_cairo_boilerplate_gl_create_window_common (int rgba_attribs[], - cairo_content_t content, - double width, - double height, - double max_width, - double max_height, - cairo_boilerplate_mode_t mode, - gl_target_closure_t *gltc) -{ - XVisualInfo *vi; - GLXContext ctx; - cairo_surface_t *surface; - Display *dpy; - XSetWindowAttributes attr; - - width = ceil (width); - height = ceil (height); - - 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, - width, height); - if (cairo_surface_status (surface)) { - _cairo_boilerplate_gl_cleanup (gltc); - return NULL; - } - 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, - void **closure) -{ - gl_target_closure_t *gltc; - - int rgba_attribs[] = { GLX_RGBA, - GLX_RED_SIZE, 1, - GLX_GREEN_SIZE, 1, - GLX_BLUE_SIZE, 1, - GLX_ALPHA_SIZE, 1, - GLX_DOUBLEBUFFER, - GLX_NONE }; - - gltc = calloc (1, sizeof (gl_target_closure_t)); - *closure = gltc; - - return _cairo_boilerplate_gl_create_window_common (rgba_attribs, content, - width, height, - max_width, max_height, - mode, gltc); -} - -static cairo_surface_t * -_cairo_boilerplate_gl_create_window_msaa (const char *name, - cairo_content_t content, - double width, - double height, - double max_width, - double max_height, - cairo_boilerplate_mode_t mode, - void **closure) -{ - gl_target_closure_t *gltc; - - int rgba_attribs[] = { GLX_RGBA, - GLX_RED_SIZE, 1, - GLX_GREEN_SIZE, 1, - GLX_BLUE_SIZE, 1, - GLX_ALPHA_SIZE, 1, - GLX_STENCIL_SIZE, 1, - GLX_SAMPLES, 4, - GLX_SAMPLE_BUFFERS, 1, - GLX_DOUBLEBUFFER, - GLX_NONE }; - - gltc = calloc (1, sizeof (gl_target_closure_t)); - *closure = gltc; - return _cairo_boilerplate_gl_create_window_common (rgba_attribs, content, - width, height, - max_width, max_height, - mode, gltc); - -} - -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, - void **closure) -{ - cairo_status_t status; - cairo_surface_t *surface; - gl_target_closure_t *gltc; - - int rgba_attribs[] = { GLX_RGBA, - GLX_RED_SIZE, 1, - GLX_GREEN_SIZE, 1, - GLX_BLUE_SIZE, 1, - GLX_ALPHA_SIZE, 1, - GLX_DOUBLEBUFFER, - GLX_NONE }; - - gltc = calloc (1, sizeof (gl_target_closure_t)); - *closure = gltc; - - surface = _cairo_boilerplate_gl_create_window_common (rgba_attribs, content, - width, height, - max_width, max_height, - mode, gltc); - - if (! surface) - return NULL; - - 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 char * -_cairo_boilerplate_gl_describe (void *closure) -{ - gl_target_closure_t *gltc = closure; - char *s; - const GLubyte *vendor, *renderer, *version; - - if (cairo_device_acquire (gltc->device)) - return NULL; - - vendor = glGetString (GL_VENDOR); - renderer = glGetString (GL_RENDERER); - version = glGetString (GL_VERSION); - - xasprintf (&s, "%s %s %s", vendor, renderer, version); - - cairo_device_release (gltc->device); - - return s; -} - -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, - cairo_surface_create_similar, - NULL, NULL, - _cairo_boilerplate_get_image_surface, - cairo_surface_write_to_png, - _cairo_boilerplate_gl_cleanup, - _cairo_boilerplate_gl_synchronize, - _cairo_boilerplate_gl_describe, - TRUE, FALSE, FALSE - }, - { - "gl", "gl", NULL, NULL, - CAIRO_SURFACE_TYPE_GL, CAIRO_CONTENT_COLOR, 1, - "cairo_gl_surface_create", - _cairo_boilerplate_gl_create_surface, - cairo_surface_create_similar, - NULL, NULL, - _cairo_boilerplate_get_image_surface, - cairo_surface_write_to_png, - _cairo_boilerplate_gl_cleanup, - _cairo_boilerplate_gl_synchronize, - _cairo_boilerplate_gl_describe, - 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, - cairo_surface_create_similar, - NULL, - _cairo_boilerplate_gl_finish_window, - _cairo_boilerplate_get_image_surface, - cairo_surface_write_to_png, - _cairo_boilerplate_gl_cleanup, - _cairo_boilerplate_gl_synchronize, - _cairo_boilerplate_gl_describe, - FALSE, FALSE, FALSE - }, - { - "gl-window-msaa", "gl", NULL, NULL, - CAIRO_SURFACE_TYPE_GL, CAIRO_CONTENT_COLOR_ALPHA, 1, - "cairo_gl_surface_create_for_window", - _cairo_boilerplate_gl_create_window_msaa, - cairo_surface_create_similar, - NULL, - _cairo_boilerplate_gl_finish_window, - _cairo_boilerplate_get_image_surface, - cairo_surface_write_to_png, - _cairo_boilerplate_gl_cleanup, - _cairo_boilerplate_gl_synchronize, - _cairo_boilerplate_gl_describe, - 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, - cairo_surface_create_similar, - NULL, - _cairo_boilerplate_gl_finish_window, - _cairo_boilerplate_get_image_surface, - cairo_surface_write_to_png, - _cairo_boilerplate_gl_cleanup, - _cairo_boilerplate_gl_synchronize, - _cairo_boilerplate_gl_describe, - FALSE, FALSE, FALSE - }, -}; -CAIRO_BOILERPLATE (gl, targets) diff --git a/boilerplate/cairo-boilerplate-wgl.c b/boilerplate/cairo-boilerplate-wgl.c deleted file mode 100644 index 908817788..000000000 --- a/boilerplate/cairo-boilerplate-wgl.c +++ /dev/null @@ -1,239 +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. - * - * Contributor(s): - * Zoxc <zoxc32@gmail.com> - */ - -#include "cairo-boilerplate-private.h" - -#include <cairo-gl.h> - -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, - 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, - 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, - cairo_surface_create_similar, - NULL, NULL, - _cairo_boilerplate_get_image_surface, - cairo_surface_write_to_png, - _cairo_boilerplate_wgl_cleanup, - _cairo_boilerplate_wgl_synchronize, - NULL, - 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, - NULL, - FALSE, FALSE, FALSE - }, -}; - -CAIRO_BOILERPLATE (wgl, targets) diff --git a/boilerplate/meson.build b/boilerplate/meson.build index 7f663c273..450eabf3e 100644 --- a/boilerplate/meson.build +++ b/boilerplate/meson.build @@ -13,10 +13,6 @@ cairo_boilerplate_feature_sources = { 'cairo-ps': ['cairo-boilerplate-ps.c'], 'cairo-svg': ['cairo-boilerplate-svg.c'], 'cairo-script': ['cairo-boilerplate-script.c'], - # All tests crash with FPE - # 'cairo-egl': ['cairo-boilerplate-egl.c'], - # cairo-glx: ['cairo-boilerplate-glx.c'], - 'cairo-wgl': ['cairo-boilerplate-wgl.c'], } foreach feature: built_features diff --git a/meson.build b/meson.build index 0faf8638e..34679304e 100644 --- a/meson.build +++ b/meson.build @@ -551,135 +551,6 @@ if host_machine.system() == 'windows' endif endif -# GL / GLESV2 / GLESV3 are mutually exclusive -gl_backend = get_option('gl-backend') -need_egl_functions = false -need_wgl_functions = false -need_glx_functions = false - -if gl_backend in ['auto', 'gl'] - gl_dep = dependency('gl', required: false) - if not gl_dep.found() - gl_dep = cc.find_library('GL', required: gl_backend == 'gl') - endif - if gl_dep.found() and \ - cc.has_header('GL/gl.h', required: gl_backend == 'gl', dependencies: gl_dep) and \ - cc.has_header('GL/glext.h', required: gl_backend == 'gl', dependencies: gl_dep) - deps += [gl_dep] - - need_egl_functions = true - need_wgl_functions = true - need_glx_functions = true - - feature_conf.set('CAIRO_HAS_GL_SURFACE', 1) - built_features += [{ - 'name': 'cairo-gl', - 'description': 'OpenGL surface backend', - 'deps': [gl_dep], - }] - endif -endif - -if feature_conf.get('CAIRO_HAS_GL_SURFACE', 0) == 0 and ['auto', 'glesv2'].contains(gl_backend) - glesv2_dep = dependency('glesv2', required: false) - if not glesv2_dep.found() - glesv2_dep = cc.find_library('GLESv2', required: gl_backend == 'glesv2') - endif - if glesv2_dep.found() and \ - cc.has_header('GLES2/gl2.h', required: gl_backend == 'glesv2', dependencies: glesv2_dep) and \ - cc.has_header('GLES2/gl2ext.h', required: gl_backend == 'glesv2', dependencies: glesv2_dep) - deps += [glesv2_dep] - need_egl_functions = true - - feature_conf.set('CAIRO_HAS_GLESV2_SURFACE', 1) - built_features += [{ - 'name': 'cairo-glesv2', - 'source-key': 'cairo-gl', - 'description': 'OpenGLESv2 surface backend', - 'deps': [glesv2_dep], - }] - endif -endif - -if feature_conf.get('CAIRO_HAS_GL_SURFACE', 0) == 0 and feature_conf.get('CAIRO_HAS_GLESV2_SURFACE', 0) == 0 and ['auto', 'glesv3'].contains(gl_backend) - # glesv3 is provided via libGLESv2.so (there is no libGLESv3, nor glesv3.pc) - glesv3_dep = dependency('glesv2', required: false) - if not glesv3_dep.found() - glesv3_dep = cc.find_library('GLESv2', required: gl_backend == 'glesv3') - endif - - if glesv3_dep.found() and \ - cc.has_header('GLES3/gl3.h', required: gl_backend == 'glesv3', dependencies: glesv3_dep) and \ - cc.has_header('GLES3/gl3ext.h', required: gl_backend == 'glesv3', dependencies: glesv3_dep) - deps += [glesv3_dep] - need_egl_functions = true - - feature_conf.set('CAIRO_HAS_GLESV3_SURFACE', 1) - built_features += [{ - 'name': 'cairo-glesv3', - 'source-key': 'cairo-gl', - 'description': 'OpenGLESv3 surface backend', - 'deps': [glesv3_dep], - }] - endif -endif - -if need_egl_functions - # FIXME: automagic - egl_extra_deps = [] - egl_dep = dependency('egl', required: false) - if not egl_dep.found() - if cc.has_header('EGL/egl.h') - csi_dep = cc.find_library('csi', required: false) - if csi_dep.found() and cc.has_function('csi_stream_attachresource', dependencies: [csi_dep]) - egl_extra_deps += csi_dep - endif - - foreach libname : ['EGL', 'egl13', 'egl12', 'egl11'] - dep = cc.find_library(libname, required: false) - if dep.found() and cc.has_function('eglGetError', dependencies: [dep]) - egl_dep = dep - break - endif - endforeach - endif - endif - - if egl_dep.found() - deps += egl_dep - feature_conf.set('CAIRO_HAS_EGL_FUNCTIONS', 1) - built_features += [{ - 'name': 'cairo-egl', - 'description': 'EGL functions', - 'deps': [egl_dep] + egl_extra_deps, - }] - endif -endif - -if need_glx_functions - # FIXME: automagic - if cc.has_header('GL/glx.h') - feature_conf.set('CAIRO_HAS_GLX_FUNCTIONS', 1) - built_features += [{ - 'name': 'cairo-glx', - 'description': 'GLX functions', - 'deps': [cc.find_library('GL')], - }] - endif -endif - -# Untested -if need_wgl_functions - # FIXME: automagic - if cc.has_header('windows.h') - feature_conf.set('CAIRO_HAS_WGL_FUNCTIONS', 1) - built_features += [{ - 'name': 'cairo-wgl', - 'description': 'WGL functions', - }] - endif -endif - gobject_dep = dependency('gobject-2.0', required: get_option('glib'), fallback: ['glib', 'libgobject_dep'] @@ -979,9 +850,6 @@ summary({ 'PostScript': feature_conf.get('CAIRO_HAS_PS_SURFACE', 0) == 1, 'PDF': feature_conf.get('CAIRO_HAS_PDF_SURFACE', 0) == 1, 'SVG': feature_conf.get('CAIRO_HAS_SVG_SURFACE', 0) == 1, - 'OpenGL': feature_conf.get('CAIRO_HAS_GL_SURFACE', 0) == 1, - 'OpenGL ES 2.0': feature_conf.get('CAIRO_HAS_GLESV2_SURFACE', 0) == 1, - 'OpenGL ES 3.0': feature_conf.get('CAIRO_HAS_GLESV3_SURFACE', 0) == 1, }, section: 'Surface Backends', bool_yn: true) summary({ @@ -995,9 +863,6 @@ summary({ summary({ 'PNG functions': feature_conf.get('CAIRO_HAS_PNG_FUNCTIONS', 0) == 1, - 'GLX functions': feature_conf.get('CAIRO_HAS_GLX_FUNCTIONS', 0) == 1, - 'WGL functions': feature_conf.get('CAIRO_HAS_WGL_FUNCTIONS', 0) == 1, - 'EGL functions': feature_conf.get('CAIRO_HAS_EGL_FUNCTIONS', 0) == 1, 'X11-xcb': feature_conf.get('CAIRO_HAS_XLIB_XCB_FUNCTIONS', 0) == 1, 'XCB-shm': feature_conf.get('CAIRO_HAS_XCB_SHM_FUNCTIONS', 0) == 1, }, section: 'Functions', bool_yn: true) diff --git a/meson_options.txt b/meson_options.txt index 1d4d018c4..4bdfe8a13 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -4,11 +4,6 @@ option('fontconfig', type : 'feature', value : 'auto') option('freetype', type : 'feature', value : 'auto') # Cairo surface backends -option('gl-backend', type : 'combo', value : 'disabled', - # FIXME: https://github.com/mesonbuild/meson/issues/4566 - choices : ['auto', 'gl', 'glesv2', 'glesv3', 'disabled']) -option('glesv2', type : 'feature', value : 'disabled') -option('glesv3', type : 'feature', value : 'disabled') option('png', type : 'feature', value : 'auto') # png and svg surfaces option('quartz', type : 'feature', value : 'auto') option('tee', type : 'feature', value : 'disabled') @@ -33,8 +28,3 @@ option('symbol-lookup', type: 'feature', value : 'auto', # Documentation option('gtk_doc', type : 'boolean', value : false, description: 'Build the Cairo API reference (depends on gtk-doc)') - -# FIXME: implement these to avoid automagic -#option('egl', type : 'feature', value : 'auto') -#option('glx', type : 'feature', value : 'auto') -#option('wgl', type : 'feature', value : 'auto') diff --git a/src/cairo-egl-context.c b/src/cairo-egl-context.c deleted file mode 100644 index bf704c630..000000000 --- a/src/cairo-egl-context.c +++ /dev/null @@ -1,317 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2009 Eric Anholt - * Copyright © 2009 Chris Wilson - * 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., 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 Red Hat, Inc. - * - * Contributor(s): - * Carl Worth <cworth@cworth.org> - * Chris Wilson <chris@chris-wilson.co.uk> - */ - -#include "cairoint.h" - -#include "cairo-gl-private.h" - -#include "cairo-error-private.h" - -typedef struct _cairo_egl_context { - cairo_gl_context_t base; - - EGLDisplay display; - EGLContext context; - - EGLSurface dummy_surface; - - EGLContext previous_context; - EGLSurface previous_surface; -} cairo_egl_context_t; - -typedef struct _cairo_egl_surface { - cairo_gl_surface_t base; - - EGLSurface egl; -} cairo_egl_surface_t; - - -static cairo_bool_t -_context_acquisition_changed_egl_state (cairo_egl_context_t *ctx, - EGLSurface current_surface) -{ - return ctx->previous_context != ctx->context || - ctx->previous_surface != current_surface; -} - -static EGLSurface -_egl_get_current_surface (cairo_egl_context_t *ctx) -{ - if (ctx->base.current_target == NULL || - _cairo_gl_surface_is_texture (ctx->base.current_target)) { - return ctx->dummy_surface; - } - - return ((cairo_egl_surface_t *) ctx->base.current_target)->egl; -} - -static void -_egl_query_current_state (cairo_egl_context_t *ctx) -{ - ctx->previous_surface = eglGetCurrentSurface (EGL_DRAW); - ctx->previous_context = eglGetCurrentContext (); - - /* If any of the values were none, assume they are all none. Not all - drivers seem well behaved when it comes to using these values across - multiple threads. */ - if (ctx->previous_surface == EGL_NO_SURFACE || - ctx->previous_context == EGL_NO_CONTEXT) { - ctx->previous_surface = EGL_NO_SURFACE; - ctx->previous_context = EGL_NO_CONTEXT; - } -} - -static void -_egl_acquire (void *abstract_ctx) -{ - cairo_egl_context_t *ctx = abstract_ctx; - EGLSurface current_surface = _egl_get_current_surface (ctx); - - _egl_query_current_state (ctx); - if (!_context_acquisition_changed_egl_state (ctx, current_surface)) - return; - - eglMakeCurrent (ctx->display, - current_surface, current_surface, ctx->context); -} - -static void -_egl_release (void *abstract_ctx) -{ - cairo_egl_context_t *ctx = abstract_ctx; - if (!ctx->base.thread_aware || - !_context_acquisition_changed_egl_state (ctx, - _egl_get_current_surface (ctx))) { - return; - } - - eglMakeCurrent (ctx->display, - EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); -} - -static void -_egl_make_current (void *abstract_ctx, - cairo_gl_surface_t *abstract_surface) -{ - cairo_egl_context_t *ctx = abstract_ctx; - cairo_egl_surface_t *surface = (cairo_egl_surface_t *) abstract_surface; - - eglMakeCurrent(ctx->display, surface->egl, surface->egl, ctx->context); -} - -static void -_egl_swap_buffers (void *abstract_ctx, - cairo_gl_surface_t *abstract_surface) -{ - cairo_egl_context_t *ctx = abstract_ctx; - cairo_egl_surface_t *surface = (cairo_egl_surface_t *) abstract_surface; - - eglSwapBuffers (ctx->display, surface->egl); -} - -static void -_egl_destroy (void *abstract_ctx) -{ - cairo_egl_context_t *ctx = abstract_ctx; - - eglMakeCurrent (ctx->display, - EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); - if (ctx->dummy_surface != EGL_NO_SURFACE) - eglDestroySurface (ctx->display, ctx->dummy_surface); -} - -static cairo_bool_t -_egl_make_current_surfaceless(cairo_egl_context_t *ctx) -{ - const char *extensions; - - extensions = eglQueryString(ctx->display, EGL_EXTENSIONS); - if (strstr(extensions, "EGL_KHR_surfaceless_context") == NULL && - strstr(extensions, "EGL_KHR_surfaceless_opengl") == NULL) - return FALSE; - - if (!eglMakeCurrent(ctx->display, - EGL_NO_SURFACE, EGL_NO_SURFACE, ctx->context)) - return FALSE; - - return TRUE; -} - -cairo_device_t * -cairo_egl_device_create (EGLDisplay dpy, EGLContext egl) -{ - cairo_egl_context_t *ctx; - cairo_status_t status; - int attribs[] = { - EGL_WIDTH, 1, - EGL_HEIGHT, 1, - EGL_NONE, - }; - EGLConfig config; - EGLint numConfigs; - - ctx = calloc (1, sizeof (cairo_egl_context_t)); - if (unlikely (ctx == NULL)) - return _cairo_gl_context_create_in_error (CAIRO_STATUS_NO_MEMORY); - - ctx->display = dpy; - ctx->context = egl; - - ctx->base.acquire = _egl_acquire; - ctx->base.release = _egl_release; - ctx->base.make_current = _egl_make_current; - ctx->base.swap_buffers = _egl_swap_buffers; - ctx->base.destroy = _egl_destroy; - - /* We are about the change the current state of EGL, so we should - * query the pre-existing surface now instead of later. */ - _egl_query_current_state (ctx); - - if (!_egl_make_current_surfaceless (ctx)) { - /* Fall back to dummy surface, meh. */ - EGLint config_attribs[] = { - EGL_CONFIG_ID, 0, - EGL_NONE - }; - - /* - * In order to be able to make an egl context current when using a - * pbuffer surface, that surface must have been created with a config - * that is compatible with the context config. For Mesa, this means - * that the configs must be the same. - */ - eglQueryContext (dpy, egl, EGL_CONFIG_ID, &config_attribs[1]); - eglChooseConfig (dpy, config_attribs, &config, 1, &numConfigs); - - ctx->dummy_surface = eglCreatePbufferSurface (dpy, config, attribs); - if (ctx->dummy_surface == NULL) { - free (ctx); - return _cairo_gl_context_create_in_error (CAIRO_STATUS_NO_MEMORY); - } - - if (!eglMakeCurrent (dpy, ctx->dummy_surface, ctx->dummy_surface, egl)) { - free (ctx); - return _cairo_gl_context_create_in_error (CAIRO_STATUS_NO_MEMORY); - } - } - - status = _cairo_gl_dispatch_init (&ctx->base.dispatch, eglGetProcAddress); - if (unlikely (status)) { - free (ctx); - return _cairo_gl_context_create_in_error (status); - } - - status = _cairo_gl_context_init (&ctx->base); - if (unlikely (status)) { - if (ctx->dummy_surface != EGL_NO_SURFACE) - eglDestroySurface (dpy, ctx->dummy_surface); - free (ctx); - return _cairo_gl_context_create_in_error (status); - } - - /* Tune the default VBO size to reduce overhead on embedded devices. - * This smaller size means that flushing needs to be done more often, - * but it is less demanding of scarce memory on embedded devices. - */ - ctx->base.vbo_size = 16*1024; - - eglMakeCurrent (dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); - - return &ctx->base.base; -} - -cairo_surface_t * -cairo_gl_surface_create_for_egl (cairo_device_t *device, - EGLSurface egl, - int width, - int height) -{ - cairo_egl_surface_t *surface; - - if (unlikely (device->status)) - return _cairo_surface_create_in_error (device->status); - - if (device->backend->type != CAIRO_DEVICE_TYPE_GL) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH)); - - if (width <= 0 || height <= 0) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE)); - - surface = calloc (1, sizeof (cairo_egl_surface_t)); - if (unlikely (surface == NULL)) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - - _cairo_gl_surface_init (device, &surface->base, - CAIRO_CONTENT_COLOR_ALPHA, width, height); - surface->egl = egl; - - return &surface->base.base; -} - -static cairo_bool_t is_egl_device (cairo_device_t *device) -{ - return (device->backend != NULL && - device->backend->type == CAIRO_DEVICE_TYPE_GL); -} - -static cairo_egl_context_t *to_egl_context (cairo_device_t *device) -{ - return (cairo_egl_context_t *) device; -} - -EGLDisplay -cairo_egl_device_get_display (cairo_device_t *device) -{ - if (! is_egl_device (device)) { - _cairo_error_throw (CAIRO_STATUS_DEVICE_TYPE_MISMATCH); - return EGL_NO_DISPLAY; - } - - return to_egl_context (device)->display; -} - -cairo_public EGLContext -cairo_egl_device_get_context (cairo_device_t *device) -{ - if (! is_egl_device (device)) { - _cairo_error_throw (CAIRO_STATUS_DEVICE_TYPE_MISMATCH); - return EGL_NO_CONTEXT; - } - - return to_egl_context (device)->context; -} diff --git a/src/cairo-gl-composite.c b/src/cairo-gl-composite.c deleted file mode 100644 index 5477ef0d8..000000000 --- a/src/cairo-gl-composite.c +++ /dev/null @@ -1,1364 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2009 Eric Anholt - * Copyright © 2009 Chris Wilson - * Copyright © 2005,2010 Red Hat, Inc - * Copyright © 2011 Linaro Limited - * Copyright © 2011 Samsung Electronics - * - * 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 Red Hat, Inc. - * - * Contributor(s): - * Benjamin Otte <otte@gnome.org> - * Carl Worth <cworth@cworth.org> - * Chris Wilson <chris@chris-wilson.co.uk> - * Eric Anholt <eric@anholt.net> - * Alexandros Frantzis <alexandros.frantzis@linaro.org> - * Henry Song <hsong@sisa.samsung.com> - * Martin Robinson <mrobinson@igalia.com> - */ - -#include "cairoint.h" - -#include "cairo-gl-private.h" - -#include "cairo-composite-rectangles-private.h" -#include "cairo-clip-private.h" -#include "cairo-error-private.h" -#include "cairo-image-surface-private.h" - -/* FIXME: Copy of same routine in cairo-gl-msaa-compositor.c */ -static cairo_int_status_t -_draw_int_rect (cairo_gl_context_t *ctx, - cairo_gl_composite_t *setup, - cairo_rectangle_int_t *rect) -{ - cairo_box_t box; - cairo_point_t quad[4]; - - _cairo_box_from_rectangle (&box, rect); - quad[0].x = box.p1.x; - quad[0].y = box.p1.y; - quad[1].x = box.p1.x; - quad[1].y = box.p2.y; - quad[2].x = box.p2.x; - quad[2].y = box.p2.y; - quad[3].x = box.p2.x; - quad[3].y = box.p1.y; - - return _cairo_gl_composite_emit_quad_as_tristrip (ctx, setup, quad); -} - -static cairo_int_status_t -_blit_texture_to_renderbuffer (cairo_gl_surface_t *surface) -{ - cairo_gl_context_t *ctx = NULL; - cairo_gl_composite_t setup; - cairo_surface_pattern_t pattern; - cairo_rectangle_int_t extents; - cairo_int_status_t status; - - /* FIXME: This only permits blit when glesv3 is enabled. But note that - glesv2 with the ANGLE extension should also be able to support this feature, - so once the ANGLE support code is in place this check can be relaxed. */ - if (((cairo_gl_context_t *)surface->base.device)->gl_flavor != CAIRO_GL_FLAVOR_ES3) - return CAIRO_INT_STATUS_SUCCESS; - - if (! surface->content_in_texture) - return CAIRO_INT_STATUS_SUCCESS; - - memset (&setup, 0, sizeof (cairo_gl_composite_t)); - - status = _cairo_gl_composite_set_operator (&setup, - CAIRO_OPERATOR_SOURCE, - FALSE); - - if (status) - return status; - - setup.dst = surface; - setup.clip_region = surface->clip_region; - - _cairo_pattern_init_for_surface (&pattern, &surface->base); - status = _cairo_gl_composite_set_source (&setup, &pattern.base, - NULL, NULL, FALSE); - _cairo_pattern_fini (&pattern.base); - - if (unlikely (status)) - goto FAIL; - - _cairo_gl_composite_set_multisample (&setup); - - status = _cairo_gl_composite_begin (&setup, &ctx); - - if (unlikely (status)) - goto FAIL; - - extents.x = extents.y = 0; - extents.width = surface->width; - extents.height = surface->height; - - status = _draw_int_rect (ctx, &setup, &extents); - - if (status == CAIRO_INT_STATUS_SUCCESS) - surface->content_in_texture = FALSE; - -FAIL: - _cairo_gl_composite_fini (&setup); - - if (ctx) { - _cairo_gl_composite_flush (ctx); - status = _cairo_gl_context_release (ctx, status); - } - - return status; -} - -cairo_int_status_t -_cairo_gl_composite_set_source (cairo_gl_composite_t *setup, - const cairo_pattern_t *pattern, - const cairo_rectangle_int_t *sample, - const cairo_rectangle_int_t *extents, - cairo_bool_t use_texgen) -{ - _cairo_gl_operand_destroy (&setup->src); - return _cairo_gl_operand_init (&setup->src, pattern, setup->dst, - sample, extents, use_texgen); -} - -void -_cairo_gl_composite_set_source_operand (cairo_gl_composite_t *setup, - const cairo_gl_operand_t *source) -{ - cairo_int_status_t status; - - _cairo_gl_operand_destroy (&setup->src); - _cairo_gl_operand_copy (&setup->src, source); - - if (source->type == CAIRO_GL_OPERAND_TEXTURE) - status = _cairo_gl_surface_resolve_multisampling (source->texture.surface); -} - -void -_cairo_gl_composite_set_solid_source (cairo_gl_composite_t *setup, - const cairo_color_t *color) -{ - _cairo_gl_operand_destroy (&setup->src); - _cairo_gl_solid_operand_init (&setup->src, color); -} - -cairo_int_status_t -_cairo_gl_composite_set_mask (cairo_gl_composite_t *setup, - const cairo_pattern_t *pattern, - const cairo_rectangle_int_t *sample, - const cairo_rectangle_int_t *extents, - cairo_bool_t use_texgen) -{ - _cairo_gl_operand_destroy (&setup->mask); - if (pattern == NULL) - return CAIRO_STATUS_SUCCESS; - - return _cairo_gl_operand_init (&setup->mask, pattern, setup->dst, - sample, extents, use_texgen); -} - -void -_cairo_gl_composite_set_mask_operand (cairo_gl_composite_t *setup, - const cairo_gl_operand_t *mask) -{ - cairo_int_status_t status; - _cairo_gl_operand_destroy (&setup->mask); - if (mask) { - _cairo_gl_operand_copy (&setup->mask, mask); - if (mask->type == CAIRO_GL_OPERAND_TEXTURE) - status = _cairo_gl_surface_resolve_multisampling (mask->texture.surface); - } -} - -void -_cairo_gl_composite_set_spans (cairo_gl_composite_t *setup) -{ - setup->spans = TRUE; -} - -void -_cairo_gl_composite_set_multisample (cairo_gl_composite_t *setup) -{ - setup->multisample = TRUE; -} - -void -_cairo_gl_composite_set_clip_region (cairo_gl_composite_t *setup, - cairo_region_t *clip_region) -{ - setup->clip_region = clip_region; -} - -void -_cairo_gl_composite_set_clip (cairo_gl_composite_t *setup, - cairo_clip_t *clip) -{ - setup->clip = clip; -} - -static void -_cairo_gl_composite_bind_to_shader (cairo_gl_context_t *ctx, - cairo_gl_composite_t *setup) -{ - _cairo_gl_shader_bind_matrix4f(ctx, ctx->current_shader->mvp_location, - ctx->modelviewprojection_matrix); - _cairo_gl_operand_bind_to_shader (ctx, &setup->src, CAIRO_GL_TEX_SOURCE); - _cairo_gl_operand_bind_to_shader (ctx, &setup->mask, CAIRO_GL_TEX_MASK); -} - -static void -_cairo_gl_texture_set_filter (cairo_gl_context_t *ctx, - GLuint target, - cairo_filter_t filter) -{ - switch (filter) { - case CAIRO_FILTER_FAST: - case CAIRO_FILTER_NEAREST: - glTexParameteri (target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri (target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - break; - case CAIRO_FILTER_GOOD: - case CAIRO_FILTER_BEST: - case CAIRO_FILTER_BILINEAR: - glTexParameteri (target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri (target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - break; - default: - case CAIRO_FILTER_GAUSSIAN: - ASSERT_NOT_REACHED; - } -} - -static void -_cairo_gl_texture_set_extend (cairo_gl_context_t *ctx, - GLuint target, - cairo_extend_t extend) -{ - GLint wrap_mode; - assert (! _cairo_gl_device_requires_power_of_two_textures (&ctx->base) || - (extend != CAIRO_EXTEND_REPEAT && extend != CAIRO_EXTEND_REFLECT)); - - switch (extend) { - case CAIRO_EXTEND_NONE: - if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3 || - ctx->gl_flavor == CAIRO_GL_FLAVOR_ES2) - wrap_mode = GL_CLAMP_TO_EDGE; - else - wrap_mode = GL_CLAMP_TO_BORDER; - break; - case CAIRO_EXTEND_PAD: - wrap_mode = GL_CLAMP_TO_EDGE; - break; - case CAIRO_EXTEND_REPEAT: - if (ctx->has_npot_repeat) - wrap_mode = GL_REPEAT; - else - wrap_mode = GL_CLAMP_TO_EDGE; - break; - case CAIRO_EXTEND_REFLECT: - if (ctx->has_npot_repeat) - wrap_mode = GL_MIRRORED_REPEAT; - else - wrap_mode = GL_CLAMP_TO_EDGE; - break; - default: - wrap_mode = 0; - } - - if (likely (wrap_mode)) { - glTexParameteri (target, GL_TEXTURE_WRAP_S, wrap_mode); - glTexParameteri (target, GL_TEXTURE_WRAP_T, wrap_mode); - } -} - - -static void -_cairo_gl_context_setup_operand (cairo_gl_context_t *ctx, - cairo_gl_tex_t tex_unit, - cairo_gl_operand_t *operand, - unsigned int vertex_offset, - cairo_bool_t vertex_size_changed) -{ - cairo_gl_dispatch_t *dispatch = &ctx->dispatch; - cairo_bool_t needs_setup; - - /* XXX: we need to do setup when switching from shaders - * to no shaders (or back) */ - needs_setup = vertex_size_changed; - needs_setup |= _cairo_gl_operand_needs_setup (&ctx->operands[tex_unit], - operand, - vertex_offset); - - if (needs_setup) { - _cairo_gl_composite_flush (ctx); - _cairo_gl_context_destroy_operand (ctx, tex_unit); - } - - memcpy (&ctx->operands[tex_unit], operand, sizeof (cairo_gl_operand_t)); - ctx->operands[tex_unit].vertex_offset = vertex_offset; - - if (! needs_setup) - return; - - switch (operand->type) { - default: - case CAIRO_GL_OPERAND_COUNT: - ASSERT_NOT_REACHED; - case CAIRO_GL_OPERAND_NONE: - break; - /* fall through */ - case CAIRO_GL_OPERAND_CONSTANT: - break; - case CAIRO_GL_OPERAND_TEXTURE: - glActiveTexture (GL_TEXTURE0 + tex_unit); - glBindTexture (ctx->tex_target, operand->texture.tex); - _cairo_gl_texture_set_extend (ctx, ctx->tex_target, - operand->texture.attributes.extend); - _cairo_gl_texture_set_filter (ctx, ctx->tex_target, - operand->texture.attributes.filter); - - if (! operand->texture.texgen) { - dispatch->VertexAttribPointer (CAIRO_GL_TEXCOORD0_ATTRIB_INDEX + tex_unit, 2, - GL_FLOAT, GL_FALSE, ctx->vertex_size, - ctx->vb + vertex_offset); - dispatch->EnableVertexAttribArray (CAIRO_GL_TEXCOORD0_ATTRIB_INDEX + tex_unit); - } - break; - case CAIRO_GL_OPERAND_LINEAR_GRADIENT: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT: - glActiveTexture (GL_TEXTURE0 + tex_unit); - glBindTexture (ctx->tex_target, operand->gradient.gradient->tex); - _cairo_gl_texture_set_extend (ctx, ctx->tex_target, operand->gradient.extend); - _cairo_gl_texture_set_filter (ctx, ctx->tex_target, CAIRO_FILTER_BILINEAR); - - if (! operand->gradient.texgen) { - dispatch->VertexAttribPointer (CAIRO_GL_TEXCOORD0_ATTRIB_INDEX + tex_unit, 2, - GL_FLOAT, GL_FALSE, ctx->vertex_size, - ctx->vb + vertex_offset); - dispatch->EnableVertexAttribArray (CAIRO_GL_TEXCOORD0_ATTRIB_INDEX + tex_unit); - } - break; - } -} - -static void -_cairo_gl_context_setup_spans (cairo_gl_context_t *ctx, - cairo_bool_t spans_enabled, - unsigned int vertex_size, - unsigned int vertex_offset) -{ - cairo_gl_dispatch_t *dispatch = &ctx->dispatch; - - if (! spans_enabled) { - dispatch->DisableVertexAttribArray (CAIRO_GL_COLOR_ATTRIB_INDEX); - ctx->spans = FALSE; - return; - } - - dispatch->VertexAttribPointer (CAIRO_GL_COLOR_ATTRIB_INDEX, 4, - GL_UNSIGNED_BYTE, GL_TRUE, vertex_size, - ctx->vb + vertex_offset); - dispatch->EnableVertexAttribArray (CAIRO_GL_COLOR_ATTRIB_INDEX); - ctx->spans = TRUE; -} - -void -_cairo_gl_context_destroy_operand (cairo_gl_context_t *ctx, - cairo_gl_tex_t tex_unit) -{ - cairo_gl_dispatch_t *dispatch = &ctx->dispatch; - - if (!_cairo_gl_context_is_flushed (ctx)) - _cairo_gl_composite_flush (ctx); - - switch (ctx->operands[tex_unit].type) { - default: - case CAIRO_GL_OPERAND_COUNT: - ASSERT_NOT_REACHED; - case CAIRO_GL_OPERAND_NONE: - break; - /* fall through */ - case CAIRO_GL_OPERAND_CONSTANT: - break; - case CAIRO_GL_OPERAND_TEXTURE: - dispatch->DisableVertexAttribArray (CAIRO_GL_TEXCOORD0_ATTRIB_INDEX + tex_unit); - break; - case CAIRO_GL_OPERAND_LINEAR_GRADIENT: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT: - dispatch->DisableVertexAttribArray (CAIRO_GL_TEXCOORD0_ATTRIB_INDEX + tex_unit); - break; - } - - memset (&ctx->operands[tex_unit], 0, sizeof (cairo_gl_operand_t)); -} - -static void -_cairo_gl_set_operator (cairo_gl_context_t *ctx, - cairo_operator_t op, - cairo_bool_t component_alpha) -{ - struct { - GLenum src; - GLenum dst; - } blend_factors[] = { - { GL_ZERO, GL_ZERO }, /* Clear */ - { GL_ONE, GL_ZERO }, /* Source */ - { GL_ONE, GL_ONE_MINUS_SRC_ALPHA }, /* Over */ - { GL_DST_ALPHA, GL_ZERO }, /* In */ - { GL_ONE_MINUS_DST_ALPHA, GL_ZERO }, /* Out */ - { GL_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA }, /* Atop */ - - { GL_ZERO, GL_ONE }, /* Dest */ - { GL_ONE_MINUS_DST_ALPHA, GL_ONE }, /* DestOver */ - { GL_ZERO, GL_SRC_ALPHA }, /* DestIn */ - { GL_ZERO, GL_ONE_MINUS_SRC_ALPHA }, /* DestOut */ - { GL_ONE_MINUS_DST_ALPHA, GL_SRC_ALPHA }, /* DestAtop */ - - { GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA }, /* Xor */ - { GL_ONE, GL_ONE }, /* Add */ - }; - GLenum src_factor, dst_factor; - - assert (op < ARRAY_LENGTH (blend_factors)); - /* different dst and component_alpha changes cause flushes elsewhere */ - if (ctx->current_operator != op) - _cairo_gl_composite_flush (ctx); - ctx->current_operator = op; - - src_factor = blend_factors[op].src; - dst_factor = blend_factors[op].dst; - - /* Even when the user requests CAIRO_CONTENT_COLOR, we use GL_RGBA - * due to texture filtering of GL_CLAMP_TO_BORDER. So fix those - * bits in that case. - */ - if (ctx->current_target->base.content == CAIRO_CONTENT_COLOR) { - if (src_factor == GL_ONE_MINUS_DST_ALPHA) - src_factor = GL_ZERO; - if (src_factor == GL_DST_ALPHA) - src_factor = GL_ONE; - } - - if (component_alpha) { - if (dst_factor == GL_ONE_MINUS_SRC_ALPHA) - dst_factor = GL_ONE_MINUS_SRC_COLOR; - if (dst_factor == GL_SRC_ALPHA) - dst_factor = GL_SRC_COLOR; - } - - if (ctx->current_target->base.content == CAIRO_CONTENT_ALPHA) { - glBlendFuncSeparate (GL_ZERO, GL_ZERO, src_factor, dst_factor); - } else if (ctx->current_target->base.content == CAIRO_CONTENT_COLOR) { - glBlendFuncSeparate (src_factor, dst_factor, GL_ONE, GL_ONE); - } else { - glBlendFunc (src_factor, dst_factor); - } -} - -static cairo_status_t -_cairo_gl_composite_begin_component_alpha (cairo_gl_context_t *ctx, - cairo_gl_composite_t *setup) -{ - cairo_gl_shader_t *pre_shader = NULL; - cairo_status_t status; - - /* For CLEAR, cairo's rendering equation (quoting Owen's description in: - * https://lists.cairographics.org/archives/cairo/2005-August/004992.html) - * is: - * mask IN clip ? src OP dest : dest - * or more simply: - * mask IN CLIP ? 0 : dest - * - * where the ternary operator A ? B : C is (A * B) + ((1 - A) * C). - * - * The model we use in _cairo_gl_set_operator() is Render's: - * src IN mask IN clip OP dest - * which would boil down to: - * 0 (bounded by the extents of the drawing). - * - * However, we can do a Render operation using an opaque source - * and DEST_OUT to produce: - * 1 IN mask IN clip DEST_OUT dest - * which is - * mask IN clip ? 0 : dest - */ - if (setup->op == CAIRO_OPERATOR_CLEAR) { - _cairo_gl_solid_operand_init (&setup->src, CAIRO_COLOR_WHITE); - setup->op = CAIRO_OPERATOR_DEST_OUT; - } - - /* - * implements component-alpha %CAIRO_OPERATOR_OVER using two passes of - * the simpler operations %CAIRO_OPERATOR_DEST_OUT and %CAIRO_OPERATOR_ADD. - * - * From http://anholt.livejournal.com/32058.html: - * - * The trouble is that component-alpha rendering requires two different sources - * for blending: one for the source value to the blender, which is the - * per-channel multiplication of source and mask, and one for the source alpha - * for multiplying with the destination channels, which is the multiplication - * of the source channels by the mask alpha. So the equation for Over is: - * - * dst.A = src.A * mask.A + (1 - (src.A * mask.A)) * dst.A - * dst.R = src.R * mask.R + (1 - (src.A * mask.R)) * dst.R - * dst.G = src.G * mask.G + (1 - (src.A * mask.G)) * dst.G - * dst.B = src.B * mask.B + (1 - (src.A * mask.B)) * dst.B - * - * But we can do some simpler operations, right? How about PictOpOutReverse, - * which has a source factor of 0 and dest factor of (1 - source alpha). We - * can get the source alpha value (srca.X = src.A * mask.X) out of the texture - * blenders pretty easily. So we can do a component-alpha OutReverse, which - * gets us: - * - * dst.A = 0 + (1 - (src.A * mask.A)) * dst.A - * dst.R = 0 + (1 - (src.A * mask.R)) * dst.R - * dst.G = 0 + (1 - (src.A * mask.G)) * dst.G - * dst.B = 0 + (1 - (src.A * mask.B)) * dst.B - * - * OK. And if an op doesn't use the source alpha value for the destination - * factor, then we can do the channel multiplication in the texture blenders - * to get the source value, and ignore the source alpha that we wouldn't use. - * We've supported this in the Radeon driver for a long time. An example would - * be PictOpAdd, which does: - * - * dst.A = src.A * mask.A + dst.A - * dst.R = src.R * mask.R + dst.R - * dst.G = src.G * mask.G + dst.G - * dst.B = src.B * mask.B + dst.B - * - * Hey, this looks good! If we do a PictOpOutReverse and then a PictOpAdd right - * after it, we get: - * - * dst.A = src.A * mask.A + ((1 - (src.A * mask.A)) * dst.A) - * dst.R = src.R * mask.R + ((1 - (src.A * mask.R)) * dst.R) - * dst.G = src.G * mask.G + ((1 - (src.A * mask.G)) * dst.G) - * dst.B = src.B * mask.B + ((1 - (src.A * mask.B)) * dst.B) - * - * This two-pass trickery could be avoided using a new GL extension that - * lets two values come out of the shader and into the blend unit. - */ - if (setup->op == CAIRO_OPERATOR_OVER) { - setup->op = CAIRO_OPERATOR_ADD; - status = _cairo_gl_get_shader_by_type (ctx, - &setup->src, - &setup->mask, - setup->spans, - CAIRO_GL_SHADER_IN_CA_SOURCE_ALPHA, - &pre_shader); - if (unlikely (status)) - return status; - } - - if (ctx->pre_shader != pre_shader) - _cairo_gl_composite_flush (ctx); - ctx->pre_shader = pre_shader; - - return CAIRO_STATUS_SUCCESS; -} - -static void -_scissor_to_doubles (cairo_gl_surface_t *surface, - double x1, double y1, - double x2, double y2) -{ - double height; - - height = y2 - y1; - if (_cairo_gl_surface_is_texture (surface) == FALSE) - y1 = surface->height - (y1 + height); - glScissor (x1, y1, x2 - x1, height); - glEnable (GL_SCISSOR_TEST); -} - -void -_cairo_gl_scissor_to_rectangle (cairo_gl_surface_t *surface, - const cairo_rectangle_int_t *r) -{ - _scissor_to_doubles (surface, r->x, r->y, r->x+r->width, r->y+r->height); -} - -static void -_scissor_to_box (cairo_gl_surface_t *surface, - const cairo_box_t *box) -{ - double x1, y1, x2, y2; - _cairo_box_to_doubles (box, &x1, &y1, &x2, &y2); - _scissor_to_doubles (surface, x1, y1, x2, y2); -} - -static cairo_bool_t -_cairo_gl_composite_setup_vbo (cairo_gl_context_t *ctx, - unsigned int size_per_vertex) -{ - cairo_bool_t vertex_size_changed = ctx->vertex_size != size_per_vertex; - if (vertex_size_changed) { - ctx->vertex_size = size_per_vertex; - _cairo_gl_composite_flush (ctx); - } - - if (_cairo_gl_context_is_flushed (ctx)) { - ctx->dispatch.VertexAttribPointer (CAIRO_GL_VERTEX_ATTRIB_INDEX, 2, - GL_FLOAT, GL_FALSE, size_per_vertex, - ctx->vb); - ctx->dispatch.EnableVertexAttribArray (CAIRO_GL_VERTEX_ATTRIB_INDEX); - } - - return vertex_size_changed; -} - -static void -_disable_stencil_buffer (void) -{ - glDisable (GL_STENCIL_TEST); - glDepthMask (GL_FALSE); -} - -static cairo_int_status_t -_cairo_gl_composite_setup_painted_clipping (cairo_gl_composite_t *setup, - cairo_gl_context_t *ctx, - int vertex_size) -{ - cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS; - - cairo_gl_surface_t *dst = setup->dst; - cairo_clip_t *clip = setup->clip; - - if (clip->num_boxes == 1 && clip->path == NULL) { - _scissor_to_box (dst, &clip->boxes[0]); - goto disable_stencil_buffer_and_return; - } - - if (! _cairo_gl_ensure_stencil (ctx, setup->dst)) { - status = CAIRO_INT_STATUS_UNSUPPORTED; - goto disable_stencil_buffer_and_return; - } - - /* We only want to clear the part of the stencil buffer - * that we are about to use. It also does not hurt to - * scissor around the painted clip. */ - _cairo_gl_scissor_to_rectangle (dst, _cairo_clip_get_extents (clip)); - - /* The clip is not rectangular, so use the stencil buffer. */ - glDepthMask (GL_TRUE); - glEnable (GL_STENCIL_TEST); - - /* Texture surfaces have private depth/stencil buffers, so we can - * rely on any previous clip being cached there. */ - if (_cairo_gl_surface_is_texture (setup->dst)) { - cairo_clip_t *old_clip = setup->dst->clip_on_stencil_buffer; - if (_cairo_clip_equal (old_clip, setup->clip)) - goto activate_stencil_buffer_and_return; - - if (old_clip) { - _cairo_clip_destroy (setup->dst->clip_on_stencil_buffer); - } - - setup->dst->clip_on_stencil_buffer = _cairo_clip_copy (setup->clip); - } - - glClearStencil (0); - glClear (GL_STENCIL_BUFFER_BIT); - - glStencilOp (GL_REPLACE, GL_REPLACE, GL_REPLACE); - glStencilFunc (GL_EQUAL, 1, 0xffffffff); - glColorMask (0, 0, 0, 0); - - status = _cairo_gl_msaa_compositor_draw_clip (ctx, setup, clip); - - if (unlikely (status)) { - glColorMask (1, 1, 1, 1); - goto disable_stencil_buffer_and_return; - } - - /* We want to only render to the stencil buffer, so draw everything now. - Flushing also unbinds the VBO, which we want to rebind for regular - drawing. */ - _cairo_gl_composite_flush (ctx); - _cairo_gl_composite_setup_vbo (ctx, vertex_size); - -activate_stencil_buffer_and_return: - glColorMask (1, 1, 1, 1); - glStencilOp (GL_KEEP, GL_KEEP, GL_KEEP); - glStencilFunc (GL_EQUAL, 1, 0xffffffff); - return CAIRO_INT_STATUS_SUCCESS; - -disable_stencil_buffer_and_return: - _disable_stencil_buffer (); - return status; -} - -static cairo_int_status_t -_cairo_gl_composite_setup_clipping (cairo_gl_composite_t *setup, - cairo_gl_context_t *ctx, - int vertex_size) -{ - cairo_bool_t clip_changing = TRUE; - cairo_bool_t clip_region_changing = TRUE; - - if (! ctx->clip && ! setup->clip && ! setup->clip_region && ! ctx->clip_region) - goto disable_all_clipping; - - clip_changing = ! _cairo_clip_equal (ctx->clip, setup->clip); - clip_region_changing = ! cairo_region_equal (ctx->clip_region, setup->clip_region); - if (! _cairo_gl_context_is_flushed (ctx) && - (clip_region_changing || clip_changing)) - _cairo_gl_composite_flush (ctx); - - assert (!setup->clip_region || !setup->clip); - - /* setup->clip is only used by the msaa compositor and setup->clip_region - * only by the other compositors, so it's safe to wait to clean up obsolete - * clips. */ - if (clip_region_changing) { - cairo_region_destroy (ctx->clip_region); - ctx->clip_region = cairo_region_reference (setup->clip_region); - } - if (clip_changing) { - _cairo_clip_destroy (ctx->clip); - ctx->clip = _cairo_clip_copy (setup->clip); - } - - /* For clip regions, we scissor right before drawing. */ - if (setup->clip_region) - goto disable_all_clipping; - - if (setup->clip) - return _cairo_gl_composite_setup_painted_clipping (setup, ctx, - vertex_size); -disable_all_clipping: - _disable_stencil_buffer (); - glDisable (GL_SCISSOR_TEST); - return CAIRO_INT_STATUS_SUCCESS; -} - -cairo_status_t -_cairo_gl_set_operands_and_operator (cairo_gl_composite_t *setup, - cairo_gl_context_t *ctx) -{ - unsigned int dst_size, src_size, mask_size, vertex_size; - cairo_status_t status; - cairo_gl_shader_t *shader; - cairo_bool_t component_alpha; - cairo_bool_t vertex_size_changed; - - component_alpha = - setup->mask.type == CAIRO_GL_OPERAND_TEXTURE && - setup->mask.texture.attributes.has_component_alpha; - - /* Do various magic for component alpha */ - if (component_alpha) { - status = _cairo_gl_composite_begin_component_alpha (ctx, setup); - if (unlikely (status)) - return status; - } else { - if (ctx->pre_shader) { - _cairo_gl_composite_flush (ctx); - ctx->pre_shader = NULL; - } - } - - status = _cairo_gl_get_shader_by_type (ctx, - &setup->src, - &setup->mask, - setup->spans, - component_alpha ? - CAIRO_GL_SHADER_IN_CA_SOURCE : - CAIRO_GL_SHADER_IN_NORMAL, - &shader); - if (unlikely (status)) { - ctx->pre_shader = NULL; - return status; - } - if (ctx->current_shader != shader) - _cairo_gl_composite_flush (ctx); - - status = CAIRO_STATUS_SUCCESS; - - dst_size = 2 * sizeof (GLfloat); - src_size = _cairo_gl_operand_get_vertex_size (&setup->src); - mask_size = _cairo_gl_operand_get_vertex_size (&setup->mask); - vertex_size = dst_size + src_size + mask_size; - - if (setup->spans) - vertex_size += sizeof (GLfloat); - - vertex_size_changed = _cairo_gl_composite_setup_vbo (ctx, vertex_size); - - _cairo_gl_context_setup_operand (ctx, CAIRO_GL_TEX_SOURCE, &setup->src, dst_size, vertex_size_changed); - _cairo_gl_context_setup_operand (ctx, CAIRO_GL_TEX_MASK, &setup->mask, dst_size + src_size, vertex_size_changed); - - _cairo_gl_context_setup_spans (ctx, setup->spans, vertex_size, - dst_size + src_size + mask_size); - - _cairo_gl_set_operator (ctx, setup->op, component_alpha); - - if (_cairo_gl_context_is_flushed (ctx)) { - if (ctx->pre_shader) { - _cairo_gl_set_shader (ctx, ctx->pre_shader); - _cairo_gl_composite_bind_to_shader (ctx, setup); - } - _cairo_gl_set_shader (ctx, shader); - _cairo_gl_composite_bind_to_shader (ctx, setup); - } - - return status; -} - -cairo_status_t -_cairo_gl_composite_begin (cairo_gl_composite_t *setup, - cairo_gl_context_t **ctx_out) -{ - cairo_gl_context_t *ctx; - cairo_status_t status; - - assert (setup->dst); - - status = _cairo_gl_context_acquire (setup->dst->base.device, &ctx); - if (unlikely (status)) - return status; - - _cairo_gl_context_set_destination (ctx, setup->dst, setup->multisample); - glEnable (GL_BLEND); - - status = _cairo_gl_set_operands_and_operator (setup, ctx); - if (unlikely (status)) - goto FAIL; - - status = _cairo_gl_composite_setup_clipping (setup, ctx, ctx->vertex_size); - if (unlikely (status)) - goto FAIL; - - *ctx_out = ctx; - -FAIL: - if (unlikely (status)) - status = _cairo_gl_context_release (ctx, status); - - return status; -} - -static inline void -_cairo_gl_composite_draw_tristrip (cairo_gl_context_t *ctx) -{ - cairo_array_t* indices = &ctx->tristrip_indices; - const unsigned short *indices_array = _cairo_array_index_const (indices, 0); - - if (ctx->pre_shader) { - cairo_gl_shader_t *prev_shader = ctx->current_shader; - - _cairo_gl_set_shader (ctx, ctx->pre_shader); - _cairo_gl_set_operator (ctx, CAIRO_OPERATOR_DEST_OUT, TRUE); - glDrawElements (GL_TRIANGLE_STRIP, _cairo_array_num_elements (indices), GL_UNSIGNED_SHORT, indices_array); - - _cairo_gl_set_shader (ctx, prev_shader); - _cairo_gl_set_operator (ctx, CAIRO_OPERATOR_ADD, TRUE); - } - - glDrawElements (GL_TRIANGLE_STRIP, _cairo_array_num_elements (indices), GL_UNSIGNED_SHORT, indices_array); - _cairo_array_truncate (indices, 0); -} - -static inline void -_cairo_gl_composite_draw_triangles (cairo_gl_context_t *ctx, - unsigned int count) -{ - if (! ctx->pre_shader) { - glDrawArrays (GL_TRIANGLES, 0, count); - } else { - cairo_gl_shader_t *prev_shader = ctx->current_shader; - - _cairo_gl_set_shader (ctx, ctx->pre_shader); - _cairo_gl_set_operator (ctx, CAIRO_OPERATOR_DEST_OUT, TRUE); - glDrawArrays (GL_TRIANGLES, 0, count); - - _cairo_gl_set_shader (ctx, prev_shader); - _cairo_gl_set_operator (ctx, CAIRO_OPERATOR_ADD, TRUE); - glDrawArrays (GL_TRIANGLES, 0, count); - } -} - -static void -_cairo_gl_composite_draw_triangles_with_clip_region (cairo_gl_context_t *ctx, - unsigned int count) -{ - int i, num_rectangles; - - if (!ctx->clip_region) { - _cairo_gl_composite_draw_triangles (ctx, count); - return; - } - - num_rectangles = cairo_region_num_rectangles (ctx->clip_region); - for (i = 0; i < num_rectangles; i++) { - cairo_rectangle_int_t rect; - - cairo_region_get_rectangle (ctx->clip_region, i, &rect); - - _cairo_gl_scissor_to_rectangle (ctx->current_target, &rect); - _cairo_gl_composite_draw_triangles (ctx, count); - } -} - -static void -_cairo_gl_composite_unmap_vertex_buffer (cairo_gl_context_t *ctx) -{ - ctx->vb_offset = 0; -} - -void -_cairo_gl_composite_flush (cairo_gl_context_t *ctx) -{ - unsigned int count; - int i; - - if (_cairo_gl_context_is_flushed (ctx)) - return; - - count = ctx->vb_offset / ctx->vertex_size; - _cairo_gl_composite_unmap_vertex_buffer (ctx); - - if (ctx->primitive_type == CAIRO_GL_PRIMITIVE_TYPE_TRISTRIPS) { - _cairo_gl_composite_draw_tristrip (ctx); - } else { - assert (ctx->primitive_type == CAIRO_GL_PRIMITIVE_TYPE_TRIANGLES); - _cairo_gl_composite_draw_triangles_with_clip_region (ctx, count); - } - - for (i = 0; i < ARRAY_LENGTH (ctx->glyph_cache); i++) - _cairo_gl_glyph_cache_unlock (&ctx->glyph_cache[i]); -} - -static void -_cairo_gl_composite_prepare_buffer (cairo_gl_context_t *ctx, - unsigned int n_vertices, - cairo_gl_primitive_type_t primitive_type) -{ - if (ctx->primitive_type != primitive_type) { - _cairo_gl_composite_flush (ctx); - ctx->primitive_type = primitive_type; - } - - assert(ctx->vbo_size > 0); - if (ctx->vb_offset + n_vertices * ctx->vertex_size > ctx->vbo_size) - _cairo_gl_composite_flush (ctx); -} - -static inline void -_cairo_gl_composite_emit_vertex (cairo_gl_context_t *ctx, - GLfloat x, GLfloat y) -{ - GLfloat *vb = (GLfloat *) (void *) &ctx->vb[ctx->vb_offset]; - - *vb++ = x; - *vb++ = y; - - _cairo_gl_operand_emit (&ctx->operands[CAIRO_GL_TEX_SOURCE], &vb, x, y); - _cairo_gl_operand_emit (&ctx->operands[CAIRO_GL_TEX_MASK ], &vb, x, y); - - ctx->vb_offset += ctx->vertex_size; -} - -static inline void -_cairo_gl_composite_emit_alpha_vertex (cairo_gl_context_t *ctx, - GLfloat x, GLfloat y, uint8_t alpha) -{ - GLfloat *vb = (GLfloat *) (void *) &ctx->vb[ctx->vb_offset]; - union fi { - float f; - GLbyte bytes[4]; - } fi; - - *vb++ = x; - *vb++ = y; - - _cairo_gl_operand_emit (&ctx->operands[CAIRO_GL_TEX_SOURCE], &vb, x, y); - _cairo_gl_operand_emit (&ctx->operands[CAIRO_GL_TEX_MASK ], &vb, x, y); - - fi.bytes[0] = 0; - fi.bytes[1] = 0; - fi.bytes[2] = 0; - fi.bytes[3] = alpha; - *vb++ = fi.f; - - ctx->vb_offset += ctx->vertex_size; -} - -static void -_cairo_gl_composite_emit_point (cairo_gl_context_t *ctx, - const cairo_point_t *point) -{ - _cairo_gl_composite_emit_vertex (ctx, - _cairo_fixed_to_double (point->x), - _cairo_fixed_to_double (point->y)); -} - -static void -_cairo_gl_composite_emit_rect (cairo_gl_context_t *ctx, - GLfloat x1, GLfloat y1, - GLfloat x2, GLfloat y2) -{ - _cairo_gl_composite_prepare_buffer (ctx, 6, - CAIRO_GL_PRIMITIVE_TYPE_TRIANGLES); - - _cairo_gl_composite_emit_vertex (ctx, x1, y1); - _cairo_gl_composite_emit_vertex (ctx, x2, y1); - _cairo_gl_composite_emit_vertex (ctx, x1, y2); - - _cairo_gl_composite_emit_vertex (ctx, x2, y1); - _cairo_gl_composite_emit_vertex (ctx, x2, y2); - _cairo_gl_composite_emit_vertex (ctx, x1, y2); -} - -cairo_gl_emit_rect_t -_cairo_gl_context_choose_emit_rect (cairo_gl_context_t *ctx) -{ - return _cairo_gl_composite_emit_rect; -} - -void -_cairo_gl_context_emit_rect (cairo_gl_context_t *ctx, - GLfloat x1, GLfloat y1, - GLfloat x2, GLfloat y2) -{ - _cairo_gl_composite_emit_rect (ctx, x1, y1, x2, y2); -} - -static void -_cairo_gl_composite_emit_span (cairo_gl_context_t *ctx, - GLfloat x1, GLfloat y1, - GLfloat x2, GLfloat y2, - uint8_t alpha) -{ - _cairo_gl_composite_prepare_buffer (ctx, 6, - CAIRO_GL_PRIMITIVE_TYPE_TRIANGLES); - - _cairo_gl_composite_emit_alpha_vertex (ctx, x1, y1, alpha); - _cairo_gl_composite_emit_alpha_vertex (ctx, x2, y1, alpha); - _cairo_gl_composite_emit_alpha_vertex (ctx, x1, y2, alpha); - - _cairo_gl_composite_emit_alpha_vertex (ctx, x2, y1, alpha); - _cairo_gl_composite_emit_alpha_vertex (ctx, x2, y2, alpha); - _cairo_gl_composite_emit_alpha_vertex (ctx, x1, y2, alpha); -} - -static void -_cairo_gl_composite_emit_solid_span (cairo_gl_context_t *ctx, - GLfloat x1, GLfloat y1, - GLfloat x2, GLfloat y2, - uint8_t alpha) -{ - GLfloat *v; - union fi { - float f; - GLbyte bytes[4]; - } fi; - - _cairo_gl_composite_prepare_buffer (ctx, 6, - CAIRO_GL_PRIMITIVE_TYPE_TRIANGLES); - v = (GLfloat *) (void *) &ctx->vb[ctx->vb_offset]; - - v[15] = v[ 6] = v[0] = x1; - v[10] = v[ 4] = v[1] = y1; - v[12] = v[ 9] = v[3] = x2; - v[16] = v[13] = v[7] = y2; - - fi.bytes[0] = 0; - fi.bytes[1] = 0; - fi.bytes[2] = 0; - fi.bytes[3] = alpha; - v[17] =v[14] = v[11] = v[8] = v[5] = v[2] = fi.f; - - ctx->vb_offset += 6*3 * sizeof(GLfloat); -} - -cairo_gl_emit_span_t -_cairo_gl_context_choose_emit_span (cairo_gl_context_t *ctx) -{ - if (ctx->operands[CAIRO_GL_TEX_MASK].type != CAIRO_GL_OPERAND_NONE) { - switch (ctx->operands[CAIRO_GL_TEX_MASK].type) { - default: - case CAIRO_GL_OPERAND_COUNT: - ASSERT_NOT_REACHED; - case CAIRO_GL_OPERAND_NONE: - case CAIRO_GL_OPERAND_CONSTANT: - break; - - case CAIRO_GL_OPERAND_LINEAR_GRADIENT: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT: - if (!ctx->operands[CAIRO_GL_TEX_MASK].gradient.texgen) - return _cairo_gl_composite_emit_span; - break; - - case CAIRO_GL_OPERAND_TEXTURE: - if (!ctx->operands[CAIRO_GL_TEX_MASK].texture.texgen) - return _cairo_gl_composite_emit_span; - break; - } - } - - switch (ctx->operands[CAIRO_GL_TEX_SOURCE].type) { - default: - case CAIRO_GL_OPERAND_COUNT: - ASSERT_NOT_REACHED; - case CAIRO_GL_OPERAND_NONE: - case CAIRO_GL_OPERAND_CONSTANT: - break; - - case CAIRO_GL_OPERAND_LINEAR_GRADIENT: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT: - if (!ctx->operands[CAIRO_GL_TEX_SOURCE].gradient.texgen) - return _cairo_gl_composite_emit_span; - break; - - case CAIRO_GL_OPERAND_TEXTURE: - if (!ctx->operands[CAIRO_GL_TEX_SOURCE].texture.texgen) - return _cairo_gl_composite_emit_span; - } - - return _cairo_gl_composite_emit_solid_span; -} - -static inline void -_cairo_gl_composite_emit_glyph_vertex (cairo_gl_context_t *ctx, - GLfloat x, GLfloat y, - GLfloat glyph_x, GLfloat glyph_y) -{ - GLfloat *vb = (GLfloat *) (void *) &ctx->vb[ctx->vb_offset]; - - *vb++ = x; - *vb++ = y; - - _cairo_gl_operand_emit (&ctx->operands[CAIRO_GL_TEX_SOURCE], &vb, x, y); - - *vb++ = glyph_x; - *vb++ = glyph_y; - - ctx->vb_offset += ctx->vertex_size; -} - -static void -_cairo_gl_composite_emit_glyph (cairo_gl_context_t *ctx, - GLfloat x1, GLfloat y1, - GLfloat x2, GLfloat y2, - GLfloat glyph_x1, GLfloat glyph_y1, - GLfloat glyph_x2, GLfloat glyph_y2) -{ - _cairo_gl_composite_prepare_buffer (ctx, 6, - CAIRO_GL_PRIMITIVE_TYPE_TRIANGLES); - - _cairo_gl_composite_emit_glyph_vertex (ctx, x1, y1, glyph_x1, glyph_y1); - _cairo_gl_composite_emit_glyph_vertex (ctx, x2, y1, glyph_x2, glyph_y1); - _cairo_gl_composite_emit_glyph_vertex (ctx, x1, y2, glyph_x1, glyph_y2); - - _cairo_gl_composite_emit_glyph_vertex (ctx, x2, y1, glyph_x2, glyph_y1); - _cairo_gl_composite_emit_glyph_vertex (ctx, x2, y2, glyph_x2, glyph_y2); - _cairo_gl_composite_emit_glyph_vertex (ctx, x1, y2, glyph_x1, glyph_y2); -} - -static void -_cairo_gl_composite_emit_solid_glyph (cairo_gl_context_t *ctx, - GLfloat x1, GLfloat y1, - GLfloat x2, GLfloat y2, - GLfloat glyph_x1, GLfloat glyph_y1, - GLfloat glyph_x2, GLfloat glyph_y2) -{ - GLfloat *v; - - _cairo_gl_composite_prepare_buffer (ctx, 6, - CAIRO_GL_PRIMITIVE_TYPE_TRIANGLES); - - v = (GLfloat *) (void *) &ctx->vb[ctx->vb_offset]; - - v[20] = v[ 8] = v[0] = x1; - v[13] = v[ 5] = v[1] = y1; - v[22] = v[10] = v[2] = glyph_x1; - v[15] = v[ 7] = v[3] = glyph_y1; - - v[16] = v[12] = v[4] = x2; - v[18] = v[14] = v[6] = glyph_x2; - - v[21] = v[17] = v[ 9] = y2; - v[23] = v[19] = v[11] = glyph_y2; - - ctx->vb_offset += 4 * 6 * sizeof (GLfloat); -} - -cairo_gl_emit_glyph_t -_cairo_gl_context_choose_emit_glyph (cairo_gl_context_t *ctx) -{ - switch (ctx->operands[CAIRO_GL_TEX_SOURCE].type) { - default: - case CAIRO_GL_OPERAND_COUNT: - ASSERT_NOT_REACHED; - case CAIRO_GL_OPERAND_NONE: - case CAIRO_GL_OPERAND_CONSTANT: - return _cairo_gl_composite_emit_solid_glyph; - - case CAIRO_GL_OPERAND_LINEAR_GRADIENT: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT: - case CAIRO_GL_OPERAND_TEXTURE: - return _cairo_gl_composite_emit_glyph; - } -} - -void -_cairo_gl_composite_fini (cairo_gl_composite_t *setup) -{ - _cairo_gl_operand_destroy (&setup->src); - _cairo_gl_operand_destroy (&setup->mask); -} - -cairo_status_t -_cairo_gl_composite_set_operator (cairo_gl_composite_t *setup, - cairo_operator_t op, - cairo_bool_t assume_component_alpha) -{ - if (assume_component_alpha) { - if (op != CAIRO_OPERATOR_CLEAR && - op != CAIRO_OPERATOR_OVER && - op != CAIRO_OPERATOR_ADD) - return UNSUPPORTED ("unsupported component alpha operator"); - } else { - if (! _cairo_gl_operator_is_supported (op)) - return UNSUPPORTED ("unsupported operator"); - } - - setup->op = op; - return CAIRO_STATUS_SUCCESS; -} - -cairo_status_t -_cairo_gl_composite_init (cairo_gl_composite_t *setup, - cairo_operator_t op, - cairo_gl_surface_t *dst, - cairo_bool_t assume_component_alpha) -{ - cairo_status_t status; - - status = _blit_texture_to_renderbuffer (dst); - - memset (setup, 0, sizeof (cairo_gl_composite_t)); - - status = _cairo_gl_composite_set_operator (setup, op, - assume_component_alpha); - if (status) - return status; - - setup->dst = dst; - setup->clip_region = dst->clip_region; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -_cairo_gl_composite_append_vertex_indices (cairo_gl_context_t *ctx, - int number_of_new_indices) -{ - cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS; - cairo_array_t *indices = &ctx->tristrip_indices; - int number_of_indices = _cairo_array_num_elements (indices); - unsigned short current_vertex_index = 0; - int i; - - assert (number_of_new_indices > 0); - - /* If any preexisting triangle triangle strip indices exist on this - context, we insert a set of degenerate triangles from the last - preexisting vertex to our first one. */ - if (number_of_indices > 0) { - const unsigned short *indices_array = _cairo_array_index_const (indices, 0); - current_vertex_index = indices_array[number_of_indices - 1]; - - status = _cairo_array_append (indices, ¤t_vertex_index); - if (unlikely (status)) - return status; - - current_vertex_index++; - status =_cairo_array_append (indices, ¤t_vertex_index); - if (unlikely (status)) - return status; - } - - for (i = 0; i < number_of_new_indices; i++) { - status = _cairo_array_append (indices, ¤t_vertex_index); - current_vertex_index++; - if (unlikely (status)) - return status; - } - - return CAIRO_STATUS_SUCCESS; -} - -cairo_int_status_t -_cairo_gl_composite_emit_quad_as_tristrip (cairo_gl_context_t *ctx, - cairo_gl_composite_t *setup, - const cairo_point_t quad[4]) -{ - _cairo_gl_composite_prepare_buffer (ctx, 4, - CAIRO_GL_PRIMITIVE_TYPE_TRISTRIPS); - - _cairo_gl_composite_emit_point (ctx, &quad[0]); - _cairo_gl_composite_emit_point (ctx, &quad[1]); - - /* Cairo stores quad vertices in counter-clockwise order, but we need to - emit them from top to bottom in the triangle strip, so we need to reverse - the order of the last two vertices. */ - _cairo_gl_composite_emit_point (ctx, &quad[3]); - _cairo_gl_composite_emit_point (ctx, &quad[2]); - - return _cairo_gl_composite_append_vertex_indices (ctx, 4); -} - -cairo_int_status_t -_cairo_gl_composite_emit_triangle_as_tristrip (cairo_gl_context_t *ctx, - cairo_gl_composite_t *setup, - const cairo_point_t triangle[3]) -{ - _cairo_gl_composite_prepare_buffer (ctx, 3, - CAIRO_GL_PRIMITIVE_TYPE_TRISTRIPS); - - _cairo_gl_composite_emit_point (ctx, &triangle[0]); - _cairo_gl_composite_emit_point (ctx, &triangle[1]); - _cairo_gl_composite_emit_point (ctx, &triangle[2]); - return _cairo_gl_composite_append_vertex_indices (ctx, 3); -} diff --git a/src/cairo-gl-device.c b/src/cairo-gl-device.c deleted file mode 100644 index 6f4c852a4..000000000 --- a/src/cairo-gl-device.c +++ /dev/null @@ -1,851 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2009 Eric Anholt - * Copyright © 2009 Chris Wilson - * Copyright © 2005,2010 Red Hat, Inc - * 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. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Red Hat, Inc. - * - * Contributor(s): - * Benjamin Otte <otte@gnome.org> - * Carl Worth <cworth@cworth.org> - * Chris Wilson <chris@chris-wilson.co.uk> - * Eric Anholt <eric@anholt.net> - * Alexandros Frantzis <alexandros.frantzis@linaro.org> - */ - -#include "cairoint.h" - -#include "cairo-error-private.h" -#include "cairo-gl-private.h" - -#define MAX_MSAA_SAMPLES 4 - -static void -_gl_lock (void *device) -{ - cairo_gl_context_t *ctx = (cairo_gl_context_t *) device; - - ctx->acquire (ctx); -} - -static void -_gl_unlock (void *device) -{ - cairo_gl_context_t *ctx = (cairo_gl_context_t *) device; - - ctx->release (ctx); -} - -static cairo_status_t -_gl_flush (void *device) -{ - cairo_gl_context_t *ctx; - cairo_status_t status; - - status = _cairo_gl_context_acquire (device, &ctx); - if (unlikely (status)) - return status; - - _cairo_gl_composite_flush (ctx); - - _cairo_gl_context_destroy_operand (ctx, CAIRO_GL_TEX_SOURCE); - _cairo_gl_context_destroy_operand (ctx, CAIRO_GL_TEX_MASK); - - if (ctx->clip_region) { - cairo_region_destroy (ctx->clip_region); - ctx->clip_region = NULL; - } - - ctx->current_target = NULL; - ctx->current_operator = -1; - ctx->vertex_size = 0; - ctx->pre_shader = NULL; - _cairo_gl_set_shader (ctx, NULL); - - ctx->dispatch.BindBuffer (GL_ARRAY_BUFFER, 0); - - glDisable (GL_SCISSOR_TEST); - glDisable (GL_BLEND); - - return _cairo_gl_context_release (ctx, status); -} - -static void -_gl_finish (void *device) -{ - cairo_gl_context_t *ctx = device; - int n; - - _gl_lock (device); - - _cairo_cache_fini (&ctx->gradients); - - _cairo_gl_context_fini_shaders (ctx); - - for (n = 0; n < ARRAY_LENGTH (ctx->glyph_cache); n++) - _cairo_gl_glyph_cache_fini (ctx, &ctx->glyph_cache[n]); - - _gl_unlock (device); -} - -static void -_gl_destroy (void *device) -{ - cairo_gl_context_t *ctx = device; - - ctx->acquire (ctx); - - while (! cairo_list_is_empty (&ctx->fonts)) { - cairo_gl_font_t *font; - - font = cairo_list_first_entry (&ctx->fonts, - cairo_gl_font_t, - link); - - cairo_list_del (&font->base.link); - cairo_list_del (&font->link); - free (font); - } - - _cairo_array_fini (&ctx->tristrip_indices); - - cairo_region_destroy (ctx->clip_region); - _cairo_clip_destroy (ctx->clip); - - free (ctx->vb); - - ctx->destroy (ctx); - - free (ctx); -} - -static const cairo_device_backend_t _cairo_gl_device_backend = { - CAIRO_DEVICE_TYPE_GL, - - _gl_lock, - _gl_unlock, - - _gl_flush, /* flush */ - _gl_finish, - _gl_destroy, -}; - -static cairo_bool_t -_cairo_gl_msaa_compositor_enabled (void) -{ - const char *env = getenv ("CAIRO_GL_COMPOSITOR"); - return env && strcmp(env, "msaa") == 0; -} - -static cairo_bool_t -test_can_read_bgra (cairo_gl_flavor_t gl_flavor) -{ - /* Desktop GL always supports BGRA formats. */ - if (gl_flavor == CAIRO_GL_FLAVOR_DESKTOP) - return TRUE; - - assert (gl_flavor == CAIRO_GL_FLAVOR_ES3 || - gl_flavor == CAIRO_GL_FLAVOR_ES2); - - /* For OpenGL ES we have to look for the specific extension and BGRA only - * matches cairo's integer packed bytes on little-endian machines. */ - if (!_cairo_is_little_endian()) - return FALSE; - return _cairo_gl_has_extension ("EXT_read_format_bgra"); -} - -cairo_status_t -_cairo_gl_context_init (cairo_gl_context_t *ctx) -{ - cairo_status_t status; - cairo_gl_dispatch_t *dispatch = &ctx->dispatch; - int gl_version = _cairo_gl_get_version (); - cairo_gl_flavor_t gl_flavor = _cairo_gl_get_flavor (); - int n; - - cairo_bool_t is_desktop = gl_flavor == CAIRO_GL_FLAVOR_DESKTOP; - cairo_bool_t is_gles = (gl_flavor == CAIRO_GL_FLAVOR_ES3 || - gl_flavor == CAIRO_GL_FLAVOR_ES2); - - _cairo_device_init (&ctx->base, &_cairo_gl_device_backend); - - /* XXX The choice of compositor should be made automatically at runtime. - * However, it is useful to force one particular compositor whilst - * testing. - */ - if (_cairo_gl_msaa_compositor_enabled ()) - ctx->compositor = _cairo_gl_msaa_compositor_get (); - else - ctx->compositor = _cairo_gl_span_compositor_get (); - - - ctx->thread_aware = TRUE; - - memset (ctx->glyph_cache, 0, sizeof (ctx->glyph_cache)); - cairo_list_init (&ctx->fonts); - - /* Support only GL version >= 1.3 */ - if (gl_version < CAIRO_GL_VERSION_ENCODE (1, 3)) - return _cairo_error (CAIRO_STATUS_DEVICE_ERROR); - - /* Check for required extensions */ - if (is_desktop) { - if (_cairo_gl_has_extension ("GL_ARB_texture_non_power_of_two")) { - ctx->tex_target = GL_TEXTURE_2D; - ctx->has_npot_repeat = TRUE; - } else if (_cairo_gl_has_extension ("GL_ARB_texture_rectangle")) { - ctx->tex_target = GL_TEXTURE_RECTANGLE; - ctx->has_npot_repeat = FALSE; - } else - return _cairo_error (CAIRO_STATUS_DEVICE_ERROR); - } else { - ctx->tex_target = GL_TEXTURE_2D; - if (_cairo_gl_has_extension ("GL_OES_texture_npot") || - _cairo_gl_has_extension ("GL_IMG_texture_npot")) - ctx->has_npot_repeat = TRUE; - else - ctx->has_npot_repeat = FALSE; - } - - if (is_desktop && gl_version < CAIRO_GL_VERSION_ENCODE (2, 1) && - ! _cairo_gl_has_extension ("GL_ARB_pixel_buffer_object")) - return _cairo_error (CAIRO_STATUS_DEVICE_ERROR); - - if (is_gles && ! _cairo_gl_has_extension ("GL_EXT_texture_format_BGRA8888")) - return _cairo_error (CAIRO_STATUS_DEVICE_ERROR); - - ctx->has_map_buffer = - is_desktop || (is_gles && _cairo_gl_has_extension ("GL_OES_mapbuffer")); - - ctx->can_read_bgra = test_can_read_bgra (gl_flavor); - - ctx->has_mesa_pack_invert = - _cairo_gl_has_extension ("GL_MESA_pack_invert"); - - ctx->has_packed_depth_stencil = - (is_desktop && _cairo_gl_has_extension ("GL_EXT_packed_depth_stencil")) || - (is_gles && _cairo_gl_has_extension ("GL_OES_packed_depth_stencil")); - - ctx->num_samples = 1; - -#if CAIRO_HAS_GL_SURFACE - if (is_desktop && ctx->has_packed_depth_stencil && - (gl_version >= CAIRO_GL_VERSION_ENCODE (3, 0) || - _cairo_gl_has_extension ("GL_ARB_framebuffer_object") || - (_cairo_gl_has_extension ("GL_EXT_framebuffer_blit") && - _cairo_gl_has_extension ("GL_EXT_framebuffer_multisample")))) { - glGetIntegerv(GL_MAX_SAMPLES_EXT, &ctx->num_samples); - } -#endif - -#if CAIRO_HAS_GLESV3_SURFACE - if (is_gles && ctx->has_packed_depth_stencil) { - glGetIntegerv(GL_MAX_SAMPLES, &ctx->num_samples); - } - -#elif CAIRO_HAS_GLESV2_SURFACE && defined(GL_MAX_SAMPLES_EXT) - if (is_gles && ctx->has_packed_depth_stencil && - _cairo_gl_has_extension ("GL_EXT_multisampled_render_to_texture")) { - glGetIntegerv(GL_MAX_SAMPLES_EXT, &ctx->num_samples); - } - - if (is_gles && ctx->has_packed_depth_stencil && - _cairo_gl_has_extension ("GL_IMG_multisampled_render_to_texture")) { - glGetIntegerv(GL_MAX_SAMPLES_IMG, &ctx->num_samples); - } -#endif - - /* we always use renderbuffer for rendering in glesv3 */ - if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3) - ctx->supports_msaa = TRUE; - else - ctx->supports_msaa = ctx->num_samples > 1; - if (ctx->num_samples > MAX_MSAA_SAMPLES) - ctx->num_samples = MAX_MSAA_SAMPLES; - - ctx->current_operator = -1; - ctx->gl_flavor = gl_flavor; - - status = _cairo_gl_context_init_shaders (ctx); - if (unlikely (status)) - return status; - - status = _cairo_cache_init (&ctx->gradients, - _cairo_gl_gradient_equal, - NULL, - (cairo_destroy_func_t) _cairo_gl_gradient_destroy, - CAIRO_GL_GRADIENT_CACHE_SIZE); - if (unlikely (status)) - return status; - - ctx->vbo_size = _cairo_gl_get_vbo_size(); - - ctx->vb = _cairo_malloc (ctx->vbo_size); - if (unlikely (ctx->vb == NULL)) { - _cairo_cache_fini (&ctx->gradients); - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - ctx->primitive_type = CAIRO_GL_PRIMITIVE_TYPE_TRIANGLES; - _cairo_array_init (&ctx->tristrip_indices, sizeof (unsigned short)); - - /* PBO for any sort of texture upload */ - dispatch->GenBuffers (1, &ctx->texture_load_pbo); - - ctx->max_framebuffer_size = 0; - glGetIntegerv (GL_MAX_RENDERBUFFER_SIZE, &ctx->max_framebuffer_size); - ctx->max_texture_size = 0; - glGetIntegerv (GL_MAX_TEXTURE_SIZE, &ctx->max_texture_size); - ctx->max_textures = 0; - glGetIntegerv (GL_MAX_TEXTURE_IMAGE_UNITS, &ctx->max_textures); - - for (n = 0; n < ARRAY_LENGTH (ctx->glyph_cache); n++) - _cairo_gl_glyph_cache_init (&ctx->glyph_cache[n]); - - return CAIRO_STATUS_SUCCESS; -} - -void -_cairo_gl_context_activate (cairo_gl_context_t *ctx, - cairo_gl_tex_t tex_unit) -{ - if (ctx->max_textures <= (GLint) tex_unit) { - if (tex_unit < 2) { - _cairo_gl_composite_flush (ctx); - _cairo_gl_context_destroy_operand (ctx, ctx->max_textures - 1); - } - glActiveTexture (ctx->max_textures - 1); - } else { - glActiveTexture (GL_TEXTURE0 + tex_unit); - } -} - -static GLenum -_get_depth_stencil_format (cairo_gl_context_t *ctx) -{ - /* This is necessary to properly handle the situation where both - OpenGL and OpenGLES are active and returning a sane default. */ -#if CAIRO_HAS_GL_SURFACE - if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP) - return GL_DEPTH_STENCIL; -#endif - -#if CAIRO_HAS_GLESV2_SURFACE && !CAIRO_HAS_GLESV3_SURFACE - if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP) - return GL_DEPTH24_STENCIL8_OES; -#endif - -#if CAIRO_HAS_GL_SURFACE - return GL_DEPTH_STENCIL; -#elif CAIRO_HAS_GLESV3_SURFACE - return GL_DEPTH24_STENCIL8; -#elif CAIRO_HAS_GLESV2_SURFACE - return GL_DEPTH24_STENCIL8_OES; -#endif -} - -#if CAIRO_HAS_GLESV2_SURFACE -static void -_cairo_gl_ensure_msaa_gles_framebuffer (cairo_gl_context_t *ctx, - cairo_gl_surface_t *surface) -{ - if (surface->msaa_active) - return; - - ctx->dispatch.FramebufferTexture2DMultisample(GL_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0, - ctx->tex_target, - surface->tex, - 0, - ctx->num_samples); - - /* From now on MSAA will always be active on this surface. */ - surface->msaa_active = TRUE; -} -#endif - -void -_cairo_gl_ensure_framebuffer (cairo_gl_context_t *ctx, - cairo_gl_surface_t *surface) -{ - GLenum status; - cairo_gl_dispatch_t *dispatch = &ctx->dispatch; - - if (likely (surface->fb)) - return; - - /* Create a framebuffer object wrapping the texture so that we can render - * to it. - */ - dispatch->GenFramebuffers (1, &surface->fb); - dispatch->BindFramebuffer (GL_FRAMEBUFFER, surface->fb); - - /* Unlike for desktop GL we only maintain one multisampling framebuffer - for OpenGLES since the EXT_multisampled_render_to_texture extension - does not require an explicit multisample resolution. */ -#if CAIRO_HAS_GLESV2_SURFACE - if (surface->supports_msaa && _cairo_gl_msaa_compositor_enabled () && - ctx->gl_flavor == CAIRO_GL_FLAVOR_ES2) { - _cairo_gl_ensure_msaa_gles_framebuffer (ctx, surface); - } else -#endif - dispatch->FramebufferTexture2D (GL_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0, - ctx->tex_target, - surface->tex, - 0); - -#if CAIRO_HAS_GL_SURFACE - glDrawBuffer (GL_COLOR_ATTACHMENT0); - glReadBuffer (GL_COLOR_ATTACHMENT0); -#endif - - status = dispatch->CheckFramebufferStatus (GL_FRAMEBUFFER); - if (status != GL_FRAMEBUFFER_COMPLETE) { - const char *str; - switch (status) { - //case GL_FRAMEBUFFER_UNDEFINED: str= "undefined"; break; - case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: str= "incomplete attachment"; break; - case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: str= "incomplete/missing attachment"; break; - case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER: str= "incomplete draw buffer"; break; - case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER: str= "incomplete read buffer"; break; - case GL_FRAMEBUFFER_UNSUPPORTED: str= "unsupported"; break; - case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: str= "incomplete multiple"; break; - default: str = "unknown error"; break; - } - - fprintf (stderr, - "destination is framebuffer incomplete: %s [%#x]\n", - str, status); - } -} -#if CAIRO_HAS_GL_SURFACE || CAIRO_HAS_GLESV3_SURFACE -static void -_cairo_gl_ensure_multisampling (cairo_gl_context_t *ctx, - cairo_gl_surface_t *surface) -{ - assert (surface->supports_msaa); - assert (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP || - ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3); - - if (surface->msaa_fb) - return; - - /* We maintain a separate framebuffer for multisampling operations. - This allows us to do a fast paint to the non-multisampling framebuffer - when mulitsampling is disabled. */ - ctx->dispatch.GenFramebuffers (1, &surface->msaa_fb); - ctx->dispatch.BindFramebuffer (GL_FRAMEBUFFER, surface->msaa_fb); - ctx->dispatch.GenRenderbuffers (1, &surface->msaa_rb); - ctx->dispatch.BindRenderbuffer (GL_RENDERBUFFER, surface->msaa_rb); - - /* FIXME: For now we assume that textures passed from the outside have GL_RGBA - format, but eventually we need to expose a way for the API consumer to pass - this information. */ - ctx->dispatch.RenderbufferStorageMultisample (GL_RENDERBUFFER, - ctx->num_samples, -#if CAIRO_HAS_GLESV3_SURFACE - GL_RGBA8, -#else - GL_RGBA, -#endif - surface->width, - surface->height); - ctx->dispatch.FramebufferRenderbuffer (GL_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0, - GL_RENDERBUFFER, - surface->msaa_rb); - - /* Cairo surfaces start out initialized to transparent (black) */ - glDisable (GL_SCISSOR_TEST); - glClearColor (0, 0, 0, 0); - glClear (GL_COLOR_BUFFER_BIT); - - /* for glesv3 with multisample renderbuffer, we always render to - this renderbuffer */ - if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3) - surface->msaa_active = TRUE; -} -#endif - -static cairo_bool_t -_cairo_gl_ensure_msaa_depth_stencil_buffer (cairo_gl_context_t *ctx, - cairo_gl_surface_t *surface) -{ - cairo_gl_dispatch_t *dispatch = &ctx->dispatch; - if (surface->msaa_depth_stencil) - return TRUE; - - _cairo_gl_ensure_framebuffer (ctx, surface); -#if CAIRO_HAS_GL_SURFACE || CAIRO_HAS_GLESV3_SURFACE - if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP || - ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3) - _cairo_gl_ensure_multisampling (ctx, surface); -#endif - - dispatch->GenRenderbuffers (1, &surface->msaa_depth_stencil); - dispatch->BindRenderbuffer (GL_RENDERBUFFER, - surface->msaa_depth_stencil); - - dispatch->RenderbufferStorageMultisample (GL_RENDERBUFFER, - ctx->num_samples, - _get_depth_stencil_format (ctx), - surface->width, - surface->height); - -#if CAIRO_HAS_GL_SURFACE || CAIRO_HAS_GLESV3_SURFACE - if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP || - ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3) { - dispatch->FramebufferRenderbuffer (GL_FRAMEBUFFER, - GL_DEPTH_STENCIL_ATTACHMENT, - GL_RENDERBUFFER, - surface->msaa_depth_stencil); - } -#endif - -#if CAIRO_HAS_GLESV2_SURFACE - if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES2) { - dispatch->FramebufferRenderbuffer (GL_FRAMEBUFFER, - GL_DEPTH_ATTACHMENT, - GL_RENDERBUFFER, - surface->msaa_depth_stencil); - dispatch->FramebufferRenderbuffer (GL_FRAMEBUFFER, - GL_STENCIL_ATTACHMENT, - GL_RENDERBUFFER, - surface->msaa_depth_stencil); - } -#endif - - if (dispatch->CheckFramebufferStatus (GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { - dispatch->DeleteRenderbuffers (1, &surface->msaa_depth_stencil); - surface->msaa_depth_stencil = 0; - return FALSE; - } - - return TRUE; -} - -static cairo_bool_t -_cairo_gl_ensure_depth_stencil_buffer (cairo_gl_context_t *ctx, - cairo_gl_surface_t *surface) -{ - cairo_gl_dispatch_t *dispatch = &ctx->dispatch; - - if (surface->depth_stencil) - return TRUE; - - _cairo_gl_ensure_framebuffer (ctx, surface); - - dispatch->GenRenderbuffers (1, &surface->depth_stencil); - dispatch->BindRenderbuffer (GL_RENDERBUFFER, surface->depth_stencil); - dispatch->RenderbufferStorage (GL_RENDERBUFFER, - _get_depth_stencil_format (ctx), - surface->width, surface->height); - - dispatch->FramebufferRenderbuffer (GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, - GL_RENDERBUFFER, surface->depth_stencil); - dispatch->FramebufferRenderbuffer (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, - GL_RENDERBUFFER, surface->depth_stencil); - if (dispatch->CheckFramebufferStatus (GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { - dispatch->DeleteRenderbuffers (1, &surface->depth_stencil); - surface->depth_stencil = 0; - return FALSE; - } - - return TRUE; -} - -cairo_bool_t -_cairo_gl_ensure_stencil (cairo_gl_context_t *ctx, - cairo_gl_surface_t *surface) -{ - if (! _cairo_gl_surface_is_texture (surface)) - return TRUE; /* best guess for now, will check later */ - if (! ctx->has_packed_depth_stencil) - return FALSE; - - if (surface->msaa_active) - return _cairo_gl_ensure_msaa_depth_stencil_buffer (ctx, surface); - else - return _cairo_gl_ensure_depth_stencil_buffer (ctx, surface); -} - -/* - * Stores a parallel projection transformation in matrix 'm', - * using column-major order. - * - * This is equivalent to: - * - * glLoadIdentity() - * gluOrtho2D() - * - * The calculation for the ortho transformation was taken from the - * mesa source code. - */ -static void -_gl_identity_ortho (GLfloat *m, - GLfloat left, GLfloat right, - GLfloat bottom, GLfloat top) -{ -#define M(row,col) m[col*4+row] - M(0,0) = 2.f / (right - left); - M(0,1) = 0.f; - M(0,2) = 0.f; - M(0,3) = -(right + left) / (right - left); - - M(1,0) = 0.f; - M(1,1) = 2.f / (top - bottom); - M(1,2) = 0.f; - M(1,3) = -(top + bottom) / (top - bottom); - - M(2,0) = 0.f; - M(2,1) = 0.f; - M(2,2) = -1.f; - M(2,3) = 0.f; - - M(3,0) = 0.f; - M(3,1) = 0.f; - M(3,2) = 0.f; - M(3,3) = 1.f; -#undef M -} - -#if CAIRO_HAS_GL_SURFACE || CAIRO_HAS_GLESV3_SURFACE -static void -bind_multisample_framebuffer (cairo_gl_context_t *ctx, - cairo_gl_surface_t *surface) -{ - cairo_bool_t stencil_test_enabled; - cairo_bool_t scissor_test_enabled; - - assert (surface->supports_msaa); - assert (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP || - ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3); - - _cairo_gl_ensure_framebuffer (ctx, surface); - _cairo_gl_ensure_multisampling (ctx, surface); - - if (surface->msaa_active) { -#if CAIRO_HAS_GL_SURFACE - glEnable (GL_MULTISAMPLE); -#endif - ctx->dispatch.BindFramebuffer (GL_FRAMEBUFFER, surface->msaa_fb); - if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3) - surface->content_in_texture = FALSE; - return; - } - - _cairo_gl_composite_flush (ctx); - - stencil_test_enabled = glIsEnabled (GL_STENCIL_TEST); - scissor_test_enabled = glIsEnabled (GL_SCISSOR_TEST); - glDisable (GL_STENCIL_TEST); - glDisable (GL_SCISSOR_TEST); - -#if CAIRO_HAS_GL_SURFACE - glEnable (GL_MULTISAMPLE); -#endif - - /* The last time we drew to the surface, we were not using multisampling, - so we need to blit from the non-multisampling framebuffer into the - multisampling framebuffer. */ - ctx->dispatch.BindFramebuffer (GL_DRAW_FRAMEBUFFER, surface->msaa_fb); - ctx->dispatch.BindFramebuffer (GL_READ_FRAMEBUFFER, surface->fb); - ctx->dispatch.BlitFramebuffer (0, 0, surface->width, surface->height, - 0, 0, surface->width, surface->height, - GL_COLOR_BUFFER_BIT -#if CAIRO_HAS_GL_SURFACE - | GL_STENCIL_BUFFER_BIT -#endif - , - GL_NEAREST); - ctx->dispatch.BindFramebuffer (GL_FRAMEBUFFER, surface->msaa_fb); - - if (stencil_test_enabled) - glEnable (GL_STENCIL_TEST); - if (scissor_test_enabled) - glEnable (GL_SCISSOR_TEST); - if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3) - surface->content_in_texture = FALSE; -} -#endif - -#if CAIRO_HAS_GL_SURFACE || CAIRO_HAS_GLESV3_SURFACE -static void -bind_singlesample_framebuffer (cairo_gl_context_t *ctx, - cairo_gl_surface_t *surface) -{ - cairo_bool_t stencil_test_enabled; - cairo_bool_t scissor_test_enabled; - - assert (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP || - ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3); - _cairo_gl_ensure_framebuffer (ctx, surface); - - if (! surface->msaa_active) { -#if CAIRO_HAS_GL_SURFACE - glDisable (GL_MULTISAMPLE); -#endif - - ctx->dispatch.BindFramebuffer (GL_FRAMEBUFFER, surface->fb); - return; - } - - _cairo_gl_composite_flush (ctx); - - stencil_test_enabled = glIsEnabled (GL_STENCIL_TEST); - scissor_test_enabled = glIsEnabled (GL_SCISSOR_TEST); - glDisable (GL_STENCIL_TEST); - glDisable (GL_SCISSOR_TEST); - -#if CAIRO_HAS_GL_SURFACE - glDisable (GL_MULTISAMPLE); -#endif - - /* The last time we drew to the surface, we were using multisampling, - so we need to blit from the multisampling framebuffer into the - non-multisampling framebuffer. */ - ctx->dispatch.BindFramebuffer (GL_DRAW_FRAMEBUFFER, surface->fb); - ctx->dispatch.BindFramebuffer (GL_READ_FRAMEBUFFER, surface->msaa_fb); - ctx->dispatch.BlitFramebuffer (0, 0, surface->width, surface->height, - 0, 0, surface->width, surface->height, - GL_COLOR_BUFFER_BIT, GL_NEAREST); - ctx->dispatch.BindFramebuffer (GL_FRAMEBUFFER, surface->fb); - - if (stencil_test_enabled) - glEnable (GL_STENCIL_TEST); - if (scissor_test_enabled) - glEnable (GL_SCISSOR_TEST); -} -#endif - -void -_cairo_gl_context_bind_framebuffer (cairo_gl_context_t *ctx, - cairo_gl_surface_t *surface, - cairo_bool_t multisampling) -{ - if (_cairo_gl_surface_is_texture (surface)) { - /* OpenGL ES surfaces only have either a multisample framebuffer or a - * singlesample framebuffer, so we cannot switch back and forth. */ - if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES2) { - _cairo_gl_ensure_framebuffer (ctx, surface); - ctx->dispatch.BindFramebuffer (GL_FRAMEBUFFER, surface->fb); - return; - } - -#if CAIRO_HAS_GL_SURFACE || CAIRO_HAS_GLESV3_SURFACE - if (multisampling) - bind_multisample_framebuffer (ctx, surface); - else - bind_singlesample_framebuffer (ctx, surface); -#endif - } else { - ctx->dispatch.BindFramebuffer (GL_FRAMEBUFFER, 0); - -#if CAIRO_HAS_GL_SURFACE - if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP) { - if (multisampling) - glEnable (GL_MULTISAMPLE); - else - glDisable (GL_MULTISAMPLE); - } -#endif - } - - if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP) - surface->msaa_active = multisampling; -} - -void -_cairo_gl_context_set_destination (cairo_gl_context_t *ctx, - cairo_gl_surface_t *surface, - cairo_bool_t multisampling) -{ - cairo_bool_t changing_surface, changing_sampling; - - /* The decision whether or not to use multisampling happens when - * we create an OpenGL ES surface, so we can never switch modes. */ - if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES2) - multisampling = surface->msaa_active; - /* For GLESV3, we always use renderbuffer for drawing */ - else if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3) - multisampling = TRUE; - - changing_surface = ctx->current_target != surface || surface->needs_update; - changing_sampling = (surface->msaa_active != multisampling || - surface->content_in_texture); - if (! changing_surface && ! changing_sampling) - return; - - if (! changing_surface) { - _cairo_gl_composite_flush (ctx); - _cairo_gl_context_bind_framebuffer (ctx, surface, multisampling); - return; - } - - _cairo_gl_composite_flush (ctx); - - ctx->current_target = surface; - surface->needs_update = FALSE; - - if (! _cairo_gl_surface_is_texture (surface)) { - ctx->make_current (ctx, surface); - } - - _cairo_gl_context_bind_framebuffer (ctx, surface, multisampling); - - if (! _cairo_gl_surface_is_texture (surface)) { -#if CAIRO_HAS_GL_SURFACE - glDrawBuffer (GL_BACK_LEFT); - glReadBuffer (GL_BACK_LEFT); -#endif - } - - glDisable (GL_DITHER); - glViewport (0, 0, surface->width, surface->height); - - if (_cairo_gl_surface_is_texture (surface)) - _gl_identity_ortho (ctx->modelviewprojection_matrix, - 0, surface->width, 0, surface->height); - else - _gl_identity_ortho (ctx->modelviewprojection_matrix, - 0, surface->width, surface->height, 0); -} - -void -cairo_gl_device_set_thread_aware (cairo_device_t *device, - cairo_bool_t thread_aware) -{ - if (device->backend->type != CAIRO_DEVICE_TYPE_GL) { - _cairo_error_throw (CAIRO_STATUS_DEVICE_TYPE_MISMATCH); - return; - } - ((cairo_gl_context_t *) device)->thread_aware = thread_aware; -} diff --git a/src/cairo-gl-dispatch-private.h b/src/cairo-gl-dispatch-private.h deleted file mode 100644 index cabf76f0d..000000000 --- a/src/cairo-gl-dispatch-private.h +++ /dev/null @@ -1,129 +0,0 @@ -/* 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 "cairo-gl-private.h" -#include <stddef.h> - -typedef enum _cairo_gl_dispatch_name { - CAIRO_GL_DISPATCH_NAME_CORE, - CAIRO_GL_DISPATCH_NAME_EXT, - CAIRO_GL_DISPATCH_NAME_ES, - CAIRO_GL_DISPATCH_NAME_COUNT -} cairo_gl_dispatch_name_t; - -typedef struct _cairo_gl_dispatch_entry { - const char *name[CAIRO_GL_DISPATCH_NAME_COUNT]; - size_t offset; -} cairo_gl_dispatch_entry_t; - -#define DISPATCH_ENTRY_ARB(name) { { "gl"#name, "gl"#name"ARB", "gl"#name }, \ - offsetof(cairo_gl_dispatch_t, name) } -#define DISPATCH_ENTRY_EXT(name) { { "gl"#name, "gl"#name"EXT", "gl"#name }, \ - offsetof(cairo_gl_dispatch_t, name) } -#define DISPATCH_ENTRY_ARB_OES(name) { { "gl"#name, "gl"#name"ARB", "gl"#name"OES" }, \ - offsetof(cairo_gl_dispatch_t, name) } -#define DISPATCH_ENTRY_EXT_IMG(name) { { "gl"#name, "gl"#name"EXT", "gl"#name"IMG" }, \ - offsetof(cairo_gl_dispatch_t, name) } -#define DISPATCH_ENTRY_CUSTOM(name, name2) { { "gl"#name, "gl"#name2, "gl"#name }, \ - offsetof(cairo_gl_dispatch_t, name)} -#define DISPATCH_ENTRY_LAST { { NULL, NULL, NULL }, 0 } - -cairo_private cairo_gl_dispatch_entry_t dispatch_buffers_entries[] = { - DISPATCH_ENTRY_ARB (GenBuffers), - DISPATCH_ENTRY_ARB (BindBuffer), - DISPATCH_ENTRY_ARB (BufferData), - DISPATCH_ENTRY_ARB_OES (MapBuffer), - DISPATCH_ENTRY_ARB_OES (UnmapBuffer), - DISPATCH_ENTRY_LAST -}; - -cairo_private 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 (UniformMatrix4fv), - DISPATCH_ENTRY_ARB (Uniform1i), - - /* Attributes */ - DISPATCH_ENTRY_ARB (BindAttribLocation), - DISPATCH_ENTRY_ARB (VertexAttribPointer), - DISPATCH_ENTRY_ARB (EnableVertexAttribArray), - DISPATCH_ENTRY_ARB (DisableVertexAttribArray), - - DISPATCH_ENTRY_LAST -}; - -cairo_private 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_EXT (GenRenderbuffers), - DISPATCH_ENTRY_EXT (BindRenderbuffer), - DISPATCH_ENTRY_EXT (RenderbufferStorage), - DISPATCH_ENTRY_EXT (FramebufferRenderbuffer), - DISPATCH_ENTRY_EXT (DeleteRenderbuffers), - DISPATCH_ENTRY_EXT (BlitFramebuffer), - DISPATCH_ENTRY_LAST -}; - -cairo_private cairo_gl_dispatch_entry_t dispatch_multisampling_entries[] = { - DISPATCH_ENTRY_EXT_IMG (RenderbufferStorageMultisample), - DISPATCH_ENTRY_EXT_IMG (FramebufferTexture2DMultisample), - DISPATCH_ENTRY_LAST -}; - -#endif /* CAIRO_GL_DISPATCH_PRIVATE_H */ diff --git a/src/cairo-gl-dispatch.c b/src/cairo-gl-dispatch.c deleted file mode 100644 index a49199dbb..000000000 --- a/src/cairo-gl-dispatch.c +++ /dev/null @@ -1,273 +0,0 @@ -/* 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 "cairoint.h" -#include "cairo-gl-private.h" -#include "cairo-gl-dispatch-private.h" -#if CAIRO_HAS_DLSYM -#include <dlfcn.h> -#endif - -#if CAIRO_HAS_DLSYM -static void * -_cairo_gl_dispatch_open_lib (void) -{ - return dlopen (NULL, RTLD_LAZY); -} - -static void -_cairo_gl_dispatch_close_lib (void *handle) -{ - dlclose (handle); -} - -static cairo_gl_generic_func_t -_cairo_gl_dispatch_get_proc_addr (void *handle, const char *name) -{ - return (cairo_gl_generic_func_t) dlsym (handle, name); -} -#else -static void * -_cairo_gl_dispatch_open_lib (void) -{ - return NULL; -} - -static void -_cairo_gl_dispatch_close_lib (void *handle) -{ - return; -} - -static cairo_gl_generic_func_t -_cairo_gl_dispatch_get_proc_addr (void *handle, const char *name) -{ - return NULL; -} -#endif /* CAIRO_HAS_DLSYM */ - - -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_gl_dispatch_name_t dispatch_name) -{ - cairo_gl_dispatch_entry_t *entry = entries; - void *handle = _cairo_gl_dispatch_open_lib (); - - while (entry->name[CAIRO_GL_DISPATCH_NAME_CORE] != NULL) { - void *dispatch_ptr = &((char *) dispatch)[entry->offset]; - const char *name = entry->name[dispatch_name]; - - /* - * In strictly conforming EGL implementations, eglGetProcAddress() can - * be used only to get extension functions, but some of the functions - * we want belong to core GL(ES). If the *GetProcAddress function - * provided by the context fails, try to get the address of the wanted - * GL function using standard system facilities (eg dlsym() in *nix - * systems). - */ - cairo_gl_generic_func_t func = get_proc_addr (name); - if (func == NULL) - func = _cairo_gl_dispatch_get_proc_addr (handle, name); - - *((cairo_gl_generic_func_t *) dispatch_ptr) = func; - - ++entry; - } - - _cairo_gl_dispatch_close_lib (handle); -} - -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_gl_flavor_t gl_flavor) -{ - cairo_gl_dispatch_name_t dispatch_name; - - if (gl_flavor == CAIRO_GL_FLAVOR_DESKTOP) - { - if (gl_version >= CAIRO_GL_VERSION_ENCODE (1, 5)) - dispatch_name = CAIRO_GL_DISPATCH_NAME_CORE; - else if (_cairo_gl_has_extension ("GL_ARB_vertex_buffer_object")) - dispatch_name = CAIRO_GL_DISPATCH_NAME_EXT; - else - return CAIRO_STATUS_DEVICE_ERROR; - } - else if (gl_flavor == CAIRO_GL_FLAVOR_ES3) - { - dispatch_name = CAIRO_GL_DISPATCH_NAME_CORE; - } - else if (gl_flavor == CAIRO_GL_FLAVOR_ES2 && - gl_version >= CAIRO_GL_VERSION_ENCODE (2, 0)) - { - dispatch_name = CAIRO_GL_DISPATCH_NAME_ES; - } - else - { - return CAIRO_STATUS_DEVICE_ERROR; - } - - _cairo_gl_dispatch_init_entries (dispatch, get_proc_addr, - dispatch_buffers_entries, dispatch_name); - - 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_gl_flavor_t gl_flavor) -{ - cairo_gl_dispatch_name_t dispatch_name; - - if (gl_flavor == CAIRO_GL_FLAVOR_DESKTOP) - { - if (gl_version >= CAIRO_GL_VERSION_ENCODE (2, 0)) - dispatch_name = CAIRO_GL_DISPATCH_NAME_CORE; - else if (_cairo_gl_has_extension ("GL_ARB_shader_objects")) - dispatch_name = CAIRO_GL_DISPATCH_NAME_EXT; - else - return CAIRO_STATUS_DEVICE_ERROR; - } - else if (gl_flavor == CAIRO_GL_FLAVOR_ES3) - { - dispatch_name = CAIRO_GL_DISPATCH_NAME_CORE; - } - else if (gl_flavor == CAIRO_GL_FLAVOR_ES2 && - gl_version >= CAIRO_GL_VERSION_ENCODE (2, 0)) - { - dispatch_name = CAIRO_GL_DISPATCH_NAME_ES; - } - else - { - return CAIRO_STATUS_DEVICE_ERROR; - } - - _cairo_gl_dispatch_init_entries (dispatch, get_proc_addr, - dispatch_shaders_entries, dispatch_name); - - 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_gl_flavor_t gl_flavor) -{ - cairo_gl_dispatch_name_t dispatch_name; - - if (gl_flavor == CAIRO_GL_FLAVOR_DESKTOP) - { - if (gl_version >= CAIRO_GL_VERSION_ENCODE (3, 0) || - _cairo_gl_has_extension ("GL_ARB_framebuffer_object")) - dispatch_name = CAIRO_GL_DISPATCH_NAME_CORE; - else if (_cairo_gl_has_extension ("GL_EXT_framebuffer_object")) - dispatch_name = CAIRO_GL_DISPATCH_NAME_EXT; - else - return CAIRO_STATUS_DEVICE_ERROR; - } - else if (gl_flavor == CAIRO_GL_FLAVOR_ES3) - { - dispatch_name = CAIRO_GL_DISPATCH_NAME_CORE; - } - else if (gl_flavor == CAIRO_GL_FLAVOR_ES2 && - gl_version >= CAIRO_GL_VERSION_ENCODE (2, 0)) - { - dispatch_name = CAIRO_GL_DISPATCH_NAME_ES; - } - else - { - return CAIRO_STATUS_DEVICE_ERROR; - } - - _cairo_gl_dispatch_init_entries (dispatch, get_proc_addr, - dispatch_fbo_entries, dispatch_name); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_gl_dispatch_init_multisampling (cairo_gl_dispatch_t *dispatch, - cairo_gl_get_proc_addr_func_t get_proc_addr, - int gl_version, - cairo_gl_flavor_t gl_flavor) -{ - /* For the multisampling table, there are two GLES versions of the - * extension, so we put one in the EXT slot and one in the real ES slot.*/ - cairo_gl_dispatch_name_t dispatch_name = CAIRO_GL_DISPATCH_NAME_CORE; - if (gl_flavor == CAIRO_GL_FLAVOR_ES2) { - if (_cairo_gl_has_extension ("GL_EXT_multisampled_render_to_texture")) - dispatch_name = CAIRO_GL_DISPATCH_NAME_EXT; - else if (_cairo_gl_has_extension ("GL_IMG_multisampled_render_to_texture")) - dispatch_name = CAIRO_GL_DISPATCH_NAME_ES; - } - _cairo_gl_dispatch_init_entries (dispatch, get_proc_addr, - dispatch_multisampling_entries, - dispatch_name); - 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; - cairo_gl_flavor_t gl_flavor; - - gl_version = _cairo_gl_get_version (); - gl_flavor = _cairo_gl_get_flavor (); - - status = _cairo_gl_dispatch_init_buffers (dispatch, get_proc_addr, - gl_version, gl_flavor); - if (status != CAIRO_STATUS_SUCCESS) - return status; - - status = _cairo_gl_dispatch_init_shaders (dispatch, get_proc_addr, - gl_version, gl_flavor); - if (status != CAIRO_STATUS_SUCCESS) - return status; - - status = _cairo_gl_dispatch_init_fbo (dispatch, get_proc_addr, - gl_version, gl_flavor); - if (status != CAIRO_STATUS_SUCCESS) - return status; - - status = _cairo_gl_dispatch_init_multisampling (dispatch, get_proc_addr, - gl_version, gl_flavor); - if (status != CAIRO_STATUS_SUCCESS) - return status; - - return CAIRO_STATUS_SUCCESS; -} diff --git a/src/cairo-gl-ext-def-private.h b/src/cairo-gl-ext-def-private.h deleted file mode 100644 index a261947be..000000000 --- a/src/cairo-gl-ext-def-private.h +++ /dev/null @@ -1,143 +0,0 @@ -/* 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_EXT_DEF_PRIVATE_H -#define CAIRO_GL_EXT_DEF_PRIVATE_H - -#ifndef GL_TEXTURE_RECTANGLE -#define GL_TEXTURE_RECTANGLE 0x84F5 -#endif - -#ifndef GL_ARRAY_BUFFER -#define GL_ARRAY_BUFFER 0x8892 -#endif - -#ifndef GL_STREAM_DRAW -#define GL_STREAM_DRAW 0x88E0 -#endif - -#ifndef GL_WRITE_ONLY -#define GL_WRITE_ONLY 0x88B9 -#endif - -#ifndef GL_PIXEL_UNPACK_BUFFER -#define GL_PIXEL_UNPACK_BUFFER 0x88EC -#endif - -#ifndef GL_FRAMEBUFFER -#define GL_FRAMEBUFFER 0x8D40 -#endif - -#ifndef GL_COLOR_ATTACHMENT0 -#define GL_COLOR_ATTACHMENT0 0x8CE0 -#endif - -#ifndef GL_FRAMEBUFFER_COMPLETE -#define GL_FRAMEBUFFER_COMPLETE 0x8CD5 -#endif - -#ifndef GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT -#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6 -#endif - -#ifndef GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT -#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7 -#endif - -#ifndef GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS -#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS 0x8CD9 -#endif - -#ifndef GL_FRAMEBUFFER_INCOMPLETE_FORMATS -#define GL_FRAMEBUFFER_INCOMPLETE_FORMATS 0x8CDA -#endif - -#ifndef GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER -#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER 0x8CDB -#endif - -#ifndef GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER -#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER 0x8CDC -#endif - -#ifndef GL_FRAMEBUFFER_UNSUPPORTED -#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD -#endif - -#ifndef GL_PACK_INVERT_MESA -#define GL_PACK_INVERT_MESA 0x8758 -#endif - -#ifndef GL_CLAMP_TO_BORDER -#define GL_CLAMP_TO_BORDER 0x812D -#endif - -#ifndef GL_BGR -#define GL_BGR 0x80E0 -#endif - -#ifndef GL_BGRA -#define GL_BGRA 0x80E1 -#endif - -#ifndef GL_RGBA8 -#define GL_RGBA8 0x8058 -#endif - -#ifndef GL_UNSIGNED_INT_8_8_8_8 -#define GL_UNSIGNED_INT_8_8_8_8 0x8035 -#endif - -#ifndef GL_UNSIGNED_SHORT_5_6_5_REV -#define GL_UNSIGNED_SHORT_5_6_5_REV 0x8364 -#endif - -#ifndef GL_UNSIGNED_SHORT_1_5_5_5_REV -#define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366 -#endif - -#ifndef GL_UNSIGNED_INT_8_8_8_8_REV -#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367 -#endif - -#ifndef GL_PACK_ROW_LENGTH -#define GL_PACK_ROW_LENGTH 0x0D02 -#endif - -#ifndef GL_UNPACK_ROW_LENGTH -#define GL_UNPACK_ROW_LENGTH 0x0CF2 -#endif - -#ifndef GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE -#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56 -#endif - -#endif /* CAIRO_GL_EXT_DEF_PRIVATE_H */ diff --git a/src/cairo-gl-glyphs.c b/src/cairo-gl-glyphs.c deleted file mode 100644 index f6f5ec096..000000000 --- a/src/cairo-gl-glyphs.c +++ /dev/null @@ -1,507 +0,0 @@ -/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */ -/* Cairo - a vector graphics library with display and print output - * - * Copyright © 2009 Chris Wilson - * Copyright © 2010 Intel Corporation - * Copyright © 2010 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., 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. - * - * Contributors: - * Benjamin Otte <otte@gnome.org> - * Chris Wilson <chris@chris-wilson.co.uk> - */ - -#include "cairoint.h" - -#include "cairo-gl-private.h" - -#include "cairo-compositor-private.h" -#include "cairo-composite-rectangles-private.h" -#include "cairo-error-private.h" -#include "cairo-image-surface-private.h" -#include "cairo-rtree-private.h" - -#define GLYPH_CACHE_WIDTH 1024 -#define GLYPH_CACHE_HEIGHT 1024 -#define GLYPH_CACHE_MIN_SIZE 4 -#define GLYPH_CACHE_MAX_SIZE 128 - -typedef struct _cairo_gl_glyph { - cairo_rtree_node_t node; - cairo_scaled_glyph_private_t base; - cairo_scaled_glyph_t *glyph; - cairo_gl_glyph_cache_t *cache; - struct { float x, y; } p1, p2; -} cairo_gl_glyph_t; - -static void -_cairo_gl_node_destroy (cairo_rtree_node_t *node) -{ - cairo_gl_glyph_t *priv = cairo_container_of (node, cairo_gl_glyph_t, node); - cairo_scaled_glyph_t *glyph; - - glyph = priv->glyph; - if (glyph == NULL) - return; - - if (glyph->dev_private_key == priv->cache) { - glyph->dev_private = NULL; - glyph->dev_private_key = NULL; - } - cairo_list_del (&priv->base.link); - priv->glyph = NULL; -} - -static void -_cairo_gl_glyph_fini (cairo_scaled_glyph_private_t *glyph_private, - cairo_scaled_glyph_t *scaled_glyph, - cairo_scaled_font_t *scaled_font) -{ - cairo_gl_glyph_t *priv = cairo_container_of (glyph_private, - cairo_gl_glyph_t, - base); - - assert (priv->glyph); - - _cairo_gl_node_destroy (&priv->node); - - /* XXX thread-safety? Probably ok due to the frozen scaled-font. */ - if (! priv->node.pinned) - _cairo_rtree_node_remove (&priv->cache->rtree, &priv->node); - - assert (priv->glyph == NULL); -} - -static cairo_int_status_t -_cairo_gl_glyph_cache_add_glyph (cairo_gl_context_t *ctx, - cairo_gl_glyph_cache_t *cache, - cairo_scaled_glyph_t *scaled_glyph) -{ - cairo_image_surface_t *glyph_surface = scaled_glyph->surface; - cairo_gl_glyph_t *glyph_private; - cairo_rtree_node_t *node = NULL; - cairo_int_status_t status; - int width, height; - - width = glyph_surface->width; - if (width < GLYPH_CACHE_MIN_SIZE) - width = GLYPH_CACHE_MIN_SIZE; - height = glyph_surface->height; - if (height < GLYPH_CACHE_MIN_SIZE) - height = GLYPH_CACHE_MIN_SIZE; - - /* search for an available slot */ - status = _cairo_rtree_insert (&cache->rtree, width, height, &node); - /* search for an unlocked slot */ - if (status == CAIRO_INT_STATUS_UNSUPPORTED) { - status = _cairo_rtree_evict_random (&cache->rtree, - width, height, &node); - if (status == CAIRO_INT_STATUS_SUCCESS) { - status = _cairo_rtree_node_insert (&cache->rtree, - node, width, height, &node); - } - } - if (status) - return status; - - /* XXX: Make sure we use the mask texture. This should work automagically somehow */ - glActiveTexture (GL_TEXTURE1); - status = _cairo_gl_surface_draw_image (cache->surface, glyph_surface, - 0, 0, - glyph_surface->width, glyph_surface->height, - node->x, node->y, FALSE); - if (unlikely (status)) - return status; - - glyph_private = (cairo_gl_glyph_t *) node; - glyph_private->cache = cache; - glyph_private->glyph = scaled_glyph; - _cairo_scaled_glyph_attach_private (scaled_glyph, - &glyph_private->base, - cache, - _cairo_gl_glyph_fini); - - scaled_glyph->dev_private = glyph_private; - scaled_glyph->dev_private_key = cache; - - /* compute tex coords */ - glyph_private->p1.x = node->x; - glyph_private->p1.y = node->y; - glyph_private->p2.x = node->x + glyph_surface->width; - glyph_private->p2.y = node->y + glyph_surface->height; - if (! _cairo_gl_device_requires_power_of_two_textures (&ctx->base)) { - glyph_private->p1.x /= GLYPH_CACHE_WIDTH; - glyph_private->p2.x /= GLYPH_CACHE_WIDTH; - glyph_private->p1.y /= GLYPH_CACHE_HEIGHT; - glyph_private->p2.y /= GLYPH_CACHE_HEIGHT; - } - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_gl_glyph_t * -_cairo_gl_glyph_cache_lock (cairo_gl_glyph_cache_t *cache, - cairo_scaled_glyph_t *scaled_glyph) -{ - return _cairo_rtree_pin (&cache->rtree, scaled_glyph->dev_private); -} - -static cairo_status_t -cairo_gl_context_get_glyph_cache (cairo_gl_context_t *ctx, - cairo_format_t format, - cairo_gl_glyph_cache_t **cache_out) -{ - cairo_gl_glyph_cache_t *cache; - cairo_content_t content; - - switch (format) { - case CAIRO_FORMAT_RGBA128F: - case CAIRO_FORMAT_RGB96F: - case CAIRO_FORMAT_RGB30: - case CAIRO_FORMAT_RGB16_565: - case CAIRO_FORMAT_ARGB32: - case CAIRO_FORMAT_RGB24: - cache = &ctx->glyph_cache[0]; - content = CAIRO_CONTENT_COLOR_ALPHA; - break; - case CAIRO_FORMAT_A8: - case CAIRO_FORMAT_A1: - cache = &ctx->glyph_cache[1]; - content = CAIRO_CONTENT_ALPHA; - break; - default: - case CAIRO_FORMAT_INVALID: - ASSERT_NOT_REACHED; - return _cairo_error (CAIRO_STATUS_INVALID_FORMAT); - } - - if (unlikely (cache->surface == NULL)) { - cairo_surface_t *surface; - - surface = _cairo_gl_surface_create_scratch_for_caching (ctx, - content, - GLYPH_CACHE_WIDTH, - GLYPH_CACHE_HEIGHT); - if (unlikely (surface->status)) - return surface->status; - - _cairo_surface_release_device_reference (surface); - - cache->surface = (cairo_gl_surface_t *)surface; - cache->surface->operand.texture.attributes.has_component_alpha = - content == CAIRO_CONTENT_COLOR_ALPHA; - } - - *cache_out = cache; - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -render_glyphs (cairo_gl_surface_t *dst, - int dst_x, int dst_y, - cairo_operator_t op, - cairo_surface_t *source, - cairo_composite_glyphs_info_t *info, - cairo_bool_t *has_component_alpha, - cairo_clip_t *clip) -{ - cairo_format_t last_format = CAIRO_FORMAT_INVALID; - cairo_gl_glyph_cache_t *cache = NULL; - cairo_gl_context_t *ctx; - cairo_gl_emit_glyph_t emit = NULL; - cairo_gl_composite_t setup; - cairo_int_status_t status; - int i = 0; - - TRACE ((stderr, "%s (%d, %d)x(%d, %d)\n", __FUNCTION__, - info->extents.x, info->extents.y, - info->extents.width, info->extents.height)); - - *has_component_alpha = FALSE; - - status = _cairo_gl_context_acquire (dst->base.device, &ctx); - if (unlikely (status)) - return status; - - status = _cairo_gl_composite_init (&setup, op, dst, TRUE); - if (unlikely (status)) - goto FINISH; - - if (source == NULL) { - _cairo_gl_composite_set_solid_source (&setup, CAIRO_COLOR_WHITE); - } else { - _cairo_gl_composite_set_source_operand (&setup, - source_to_operand (source)); - - } - - _cairo_gl_composite_set_clip (&setup, clip); - - for (i = 0; i < info->num_glyphs; i++) { - cairo_scaled_glyph_t *scaled_glyph; - cairo_gl_glyph_t *glyph; - double x_offset, y_offset; - double x1, x2, y1, y2; - - status = _cairo_scaled_glyph_lookup (info->font, - info->glyphs[i].index, - CAIRO_SCALED_GLYPH_INFO_SURFACE, - NULL, /* foreground color */ - &scaled_glyph); - if (unlikely (status)) - goto FINISH; - - if (scaled_glyph->surface->width == 0 || - scaled_glyph->surface->height == 0) - { - continue; - } - if (scaled_glyph->surface->format != last_format) { - status = cairo_gl_context_get_glyph_cache (ctx, - scaled_glyph->surface->format, - &cache); - if (unlikely (status)) - goto FINISH; - - last_format = scaled_glyph->surface->format; - - _cairo_gl_composite_set_mask_operand (&setup, &cache->surface->operand); - *has_component_alpha |= cache->surface->operand.texture.attributes.has_component_alpha; - - /* XXX Shoot me. */ - status = _cairo_gl_composite_begin (&setup, &ctx); - status = _cairo_gl_context_release (ctx, status); - if (unlikely (status)) - goto FINISH; - - emit = _cairo_gl_context_choose_emit_glyph (ctx); - } - - if (scaled_glyph->dev_private_key != cache) { - cairo_scaled_glyph_private_t *priv; - - priv = _cairo_scaled_glyph_find_private (scaled_glyph, cache); - if (priv) { - scaled_glyph->dev_private_key = cache; - scaled_glyph->dev_private = cairo_container_of (priv, - cairo_gl_glyph_t, - base); - } else { - status = _cairo_gl_glyph_cache_add_glyph (ctx, cache, scaled_glyph); - - if (status == CAIRO_INT_STATUS_UNSUPPORTED) { - /* Cache is full, so flush existing prims and try again. */ - _cairo_gl_composite_flush (ctx); - _cairo_gl_glyph_cache_unlock (cache); - status = _cairo_gl_glyph_cache_add_glyph (ctx, cache, scaled_glyph); - } - - if (unlikely (_cairo_int_status_is_error (status))) - goto FINISH; - } - } - - x_offset = scaled_glyph->surface->base.device_transform.x0; - y_offset = scaled_glyph->surface->base.device_transform.y0; - - x1 = _cairo_lround (info->glyphs[i].x - x_offset - dst_x); - y1 = _cairo_lround (info->glyphs[i].y - y_offset - dst_y); - x2 = x1 + scaled_glyph->surface->width; - y2 = y1 + scaled_glyph->surface->height; - - glyph = _cairo_gl_glyph_cache_lock (cache, scaled_glyph); - assert (emit); - emit (ctx, - x1, y1, x2, y2, - glyph->p1.x, glyph->p1.y, - glyph->p2.x, glyph->p2.y); - } - - status = CAIRO_STATUS_SUCCESS; - FINISH: - status = _cairo_gl_context_release (ctx, status); - - _cairo_gl_composite_fini (&setup); - return status; -} - -static cairo_int_status_t -render_glyphs_via_mask (cairo_gl_surface_t *dst, - int dst_x, int dst_y, - cairo_operator_t op, - cairo_surface_t *source, - cairo_composite_glyphs_info_t *info, - cairo_clip_t *clip) -{ - cairo_surface_t *mask; - cairo_status_t status; - cairo_bool_t has_component_alpha; - - TRACE ((stderr, "%s\n", __FUNCTION__)); - - /* XXX: For non-CA, this should be CAIRO_CONTENT_ALPHA to save memory */ - mask = cairo_gl_surface_create (dst->base.device, - CAIRO_CONTENT_COLOR_ALPHA, - info->extents.width, - info->extents.height); - if (unlikely (mask->status)) - return mask->status; - - status = render_glyphs ((cairo_gl_surface_t *) mask, - info->extents.x, info->extents.y, - CAIRO_OPERATOR_ADD, NULL, - info, &has_component_alpha, NULL); - if (likely (status == CAIRO_STATUS_SUCCESS)) { - cairo_surface_pattern_t mask_pattern; - cairo_surface_pattern_t source_pattern; - cairo_rectangle_int_t clip_extents; - - mask->is_clear = FALSE; - _cairo_pattern_init_for_surface (&mask_pattern, mask); - mask_pattern.base.has_component_alpha = has_component_alpha; - mask_pattern.base.filter = CAIRO_FILTER_NEAREST; - mask_pattern.base.extend = CAIRO_EXTEND_NONE; - - cairo_matrix_init_translate (&mask_pattern.base.matrix, - dst_x-info->extents.x, dst_y-info->extents.y); - - _cairo_pattern_init_for_surface (&source_pattern, source); - cairo_matrix_init_translate (&source_pattern.base.matrix, - dst_x-info->extents.x, dst_y-info->extents.y); - - clip = _cairo_clip_copy (clip); - clip_extents.x = info->extents.x - dst_x; - clip_extents.y = info->extents.y - dst_y; - clip_extents.width = info->extents.width; - clip_extents.height = info->extents.height; - clip = _cairo_clip_intersect_rectangle (clip, &clip_extents); - - status = _cairo_surface_mask (&dst->base, op, - &source_pattern.base, - &mask_pattern.base, - clip); - - _cairo_clip_destroy (clip); - - _cairo_pattern_fini (&mask_pattern.base); - _cairo_pattern_fini (&source_pattern.base); - } - - cairo_surface_destroy (mask); - - return status; -} - -cairo_int_status_t -_cairo_gl_check_composite_glyphs (const cairo_composite_rectangles_t *extents, - cairo_scaled_font_t *scaled_font, - cairo_glyph_t *glyphs, - int *num_glyphs) -{ - if (! _cairo_gl_operator_is_supported (extents->op)) - return UNSUPPORTED ("unsupported operator"); - - /* XXX use individual masks for large glyphs? */ - if (ceil (scaled_font->max_scale) >= GLYPH_CACHE_MAX_SIZE) - return UNSUPPORTED ("glyphs too large"); - - return CAIRO_STATUS_SUCCESS; -} - -cairo_int_status_t -_cairo_gl_composite_glyphs_with_clip (void *_dst, - cairo_operator_t op, - cairo_surface_t *_src, - int src_x, - int src_y, - int dst_x, - int dst_y, - cairo_composite_glyphs_info_t *info, - cairo_clip_t *clip) -{ - cairo_gl_surface_t *dst = _dst; - cairo_bool_t has_component_alpha; - - TRACE ((stderr, "%s\n", __FUNCTION__)); - - /* If any of the glyphs require component alpha, we have to go through - * a mask, since only _cairo_gl_surface_composite() currently supports - * component alpha. - */ - if (!dst->base.is_clear && ! info->use_mask && op != CAIRO_OPERATOR_OVER && - (info->font->options.antialias == CAIRO_ANTIALIAS_SUBPIXEL || - info->font->options.antialias == CAIRO_ANTIALIAS_BEST)) - { - info->use_mask = TRUE; - } - - if (info->use_mask) { - return render_glyphs_via_mask (dst, dst_x, dst_y, - op, _src, info, clip); - } else { - return render_glyphs (dst, dst_x, dst_y, - op, _src, info, - &has_component_alpha, - clip); - } - -} - -cairo_int_status_t -_cairo_gl_composite_glyphs (void *_dst, - cairo_operator_t op, - cairo_surface_t *_src, - int src_x, - int src_y, - int dst_x, - int dst_y, - cairo_composite_glyphs_info_t *info) -{ - return _cairo_gl_composite_glyphs_with_clip (_dst, op, _src, src_x, src_y, - dst_x, dst_y, info, NULL); -} - -void -_cairo_gl_glyph_cache_init (cairo_gl_glyph_cache_t *cache) -{ - _cairo_rtree_init (&cache->rtree, - GLYPH_CACHE_WIDTH, - GLYPH_CACHE_HEIGHT, - GLYPH_CACHE_MIN_SIZE, - sizeof (cairo_gl_glyph_t), - _cairo_gl_node_destroy); -} - -void -_cairo_gl_glyph_cache_fini (cairo_gl_context_t *ctx, - cairo_gl_glyph_cache_t *cache) -{ - _cairo_rtree_fini (&cache->rtree); - cairo_surface_destroy (&cache->surface->base); -} diff --git a/src/cairo-gl-gradient-private.h b/src/cairo-gl-gradient-private.h deleted file mode 100644 index 0d9f41f54..000000000 --- a/src/cairo-gl-gradient-private.h +++ /dev/null @@ -1,96 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2009 Eric Anholt - * Copyright © 2009 Chris Wilson - * Copyright © 2005,2010 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., 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 Red Hat, Inc. - * - * Contributor(s): - * Benjamin Otte <otte@gnome.org> - * Carl Worth <cworth@cworth.org> - * Chris Wilson <chris@chris-wilson.co.uk> - * Eric Anholt <eric@anholt.net> - */ - -#ifndef CAIRO_GL_GRADIENT_PRIVATE_H -#define CAIRO_GL_GRADIENT_PRIVATE_H - -#define GL_GLEXT_PROTOTYPES - -#include "cairo-cache-private.h" -#include "cairo-device-private.h" -#include "cairo-reference-count-private.h" -#include "cairo-pattern-private.h" -#include "cairo-types-private.h" - -#include "cairo-gl.h" - -#if CAIRO_HAS_GLESV3_SURFACE -#include <GLES3/gl3.h> -#include <GLES3/gl3ext.h> -#elif CAIRO_HAS_GLESV2_SURFACE -#include <GLES2/gl2.h> -#include <GLES2/gl2ext.h> -#elif CAIRO_HAS_GL_SURFACE -#include <GL/gl.h> -#include <GL/glext.h> -#endif - -#define CAIRO_GL_GRADIENT_CACHE_SIZE 4096 - -/* XXX: Declare in a better place */ -typedef struct _cairo_gl_context cairo_gl_context_t; - -typedef struct _cairo_gl_gradient { - cairo_cache_entry_t cache_entry; - cairo_reference_count_t ref_count; - cairo_device_t *device; /* NB: we don't hold a reference */ - GLuint tex; - unsigned int n_stops; - const cairo_gradient_stop_t *stops; - cairo_gradient_stop_t stops_embedded[1]; -} cairo_gl_gradient_t; - -cairo_private cairo_int_status_t -_cairo_gl_gradient_create (cairo_gl_context_t *ctx, - unsigned int n_stops, - const cairo_gradient_stop_t *stops, - cairo_gl_gradient_t **gradient_out); - -cairo_private_no_warn cairo_gl_gradient_t * -_cairo_gl_gradient_reference (cairo_gl_gradient_t *gradient); - -cairo_private void -_cairo_gl_gradient_destroy (cairo_gl_gradient_t *gradient); - -cairo_private cairo_bool_t -_cairo_gl_gradient_equal (const void *key_a, const void *key_b); - - -#endif /* CAIRO_GL_GRADIENT_PRIVATE_H */ diff --git a/src/cairo-gl-gradient.c b/src/cairo-gl-gradient.c deleted file mode 100644 index 293d4e30e..000000000 --- a/src/cairo-gl-gradient.c +++ /dev/null @@ -1,339 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2009 Eric Anholt - * Copyright © 2009 Chris Wilson - * Copyright © 2005,2010 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., 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 Red Hat, Inc. - * - * Contributor(s): - * Benjamin Otte <otte@gnome.org> - * Carl Worth <cworth@cworth.org> - * Chris Wilson <chris@chris-wilson.co.uk> - * Eric Anholt <eric@anholt.net> - */ - -#include "cairoint.h" -#include <stdint.h> -#include "cairo-error-private.h" -#include "cairo-gl-gradient-private.h" -#include "cairo-gl-private.h" - - -static int -_cairo_gl_gradient_sample_width (unsigned int n_stops, - const cairo_gradient_stop_t *stops) -{ - unsigned int n; - int width; - - width = 8; - for (n = 1; n < n_stops; n++) { - double dx = stops[n].offset - stops[n-1].offset; - double delta, max; - int ramp; - - if (dx == 0) - return 1024; /* we need to emulate an infinitely sharp step */ - - max = fabs (stops[n].color.red - stops[n-1].color.red); - - delta = fabs (stops[n].color.green - stops[n-1].color.green); - if (delta > max) - max = delta; - - delta = fabs (stops[n].color.blue - stops[n-1].color.blue); - if (delta > max) - max = delta; - - delta = fabs (stops[n].color.alpha - stops[n-1].color.alpha); - if (delta > max) - max = delta; - - ramp = 128 * max / dx; - if (ramp > width) - width = ramp; - } - - return (width + 7) & -8; -} - -static uint8_t premultiply(double c, double a) -{ - int v = c * a * 256; - return v - (v >> 8); -} - -static uint32_t color_stop_to_pixel(const cairo_gradient_stop_t *stop) -{ - uint8_t a, r, g, b; - - a = stop->color.alpha_short >> 8; - r = premultiply(stop->color.red, stop->color.alpha); - g = premultiply(stop->color.green, stop->color.alpha); - b = premultiply(stop->color.blue, stop->color.alpha); - - if (_cairo_is_little_endian ()) - return (uint32_t)a << 24 | r << 16 | g << 8 | b << 0; - else - return a << 0 | r << 8 | g << 16 | (uint32_t)b << 24; -} - -static cairo_status_t -_cairo_gl_gradient_render (const cairo_gl_context_t *ctx, - unsigned int n_stops, - const cairo_gradient_stop_t *stops, - void *bytes, - int width) -{ - pixman_image_t *gradient, *image; - pixman_gradient_stop_t pixman_stops_stack[32]; - pixman_gradient_stop_t *pixman_stops; - pixman_point_fixed_t p1, p2; - unsigned int i; - pixman_format_code_t gradient_pixman_format; - - /* - * Ensure that the order of the gradient's components in memory is BGRA. - * This is done so that the gradient's pixel data is always suitable for - * texture upload using format=GL_BGRA and type=GL_UNSIGNED_BYTE. - */ - if (_cairo_is_little_endian ()) - gradient_pixman_format = PIXMAN_a8r8g8b8; - else - gradient_pixman_format = PIXMAN_b8g8r8a8; - - pixman_stops = pixman_stops_stack; - if (unlikely (n_stops > ARRAY_LENGTH (pixman_stops_stack))) { - pixman_stops = _cairo_malloc_ab (n_stops, - sizeof (pixman_gradient_stop_t)); - if (unlikely (pixman_stops == NULL)) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - for (i = 0; i < n_stops; i++) { - pixman_stops[i].x = _cairo_fixed_16_16_from_double (stops[i].offset); - pixman_stops[i].color.red = stops[i].color.red_short; - pixman_stops[i].color.green = stops[i].color.green_short; - pixman_stops[i].color.blue = stops[i].color.blue_short; - pixman_stops[i].color.alpha = stops[i].color.alpha_short; - } - - p1.x = _cairo_fixed_16_16_from_double (0.5); - p1.y = 0; - p2.x = _cairo_fixed_16_16_from_double (width - 0.5); - p2.y = 0; - - gradient = pixman_image_create_linear_gradient (&p1, &p2, - pixman_stops, - n_stops); - if (pixman_stops != pixman_stops_stack) - free (pixman_stops); - - if (unlikely (gradient == NULL)) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - pixman_image_set_filter (gradient, PIXMAN_FILTER_BILINEAR, NULL, 0); - pixman_image_set_repeat (gradient, PIXMAN_REPEAT_PAD); - - image = pixman_image_create_bits (gradient_pixman_format, width, 1, - bytes, sizeof(uint32_t)*width); - if (unlikely (image == NULL)) { - pixman_image_unref (gradient); - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - pixman_image_composite32 (PIXMAN_OP_SRC, - gradient, NULL, image, - 0, 0, - 0, 0, - 0, 0, - width, 1); - - pixman_image_unref (gradient); - pixman_image_unref (image); - - /* We need to fudge pixel 0 to hold the left-most color stop and not - * the neareset stop to the zeroth pixel centre in order to correctly - * populate the border color. For completeness, do both edges. - */ - ((uint32_t*)bytes)[0] = color_stop_to_pixel(&stops[0]); - ((uint32_t*)bytes)[width-1] = color_stop_to_pixel(&stops[n_stops-1]); - - return CAIRO_STATUS_SUCCESS; -} - -static uintptr_t -_cairo_gl_gradient_hash (unsigned int n_stops, - const cairo_gradient_stop_t *stops) -{ - return _cairo_hash_bytes (n_stops, - stops, - sizeof (cairo_gradient_stop_t) * n_stops); -} - -static cairo_gl_gradient_t * -_cairo_gl_gradient_lookup (cairo_gl_context_t *ctx, - uintptr_t hash, - unsigned int n_stops, - const cairo_gradient_stop_t *stops) -{ - cairo_gl_gradient_t lookup; - - lookup.cache_entry.hash = hash, - lookup.n_stops = n_stops; - lookup.stops = stops; - - return _cairo_cache_lookup (&ctx->gradients, &lookup.cache_entry); -} - -cairo_bool_t -_cairo_gl_gradient_equal (const void *key_a, const void *key_b) -{ - const cairo_gl_gradient_t *a = key_a; - const cairo_gl_gradient_t *b = key_b; - - if (a->n_stops != b->n_stops) - return FALSE; - - return memcmp (a->stops, b->stops, a->n_stops * sizeof (cairo_gradient_stop_t)) == 0; -} - -cairo_int_status_t -_cairo_gl_gradient_create (cairo_gl_context_t *ctx, - unsigned int n_stops, - const cairo_gradient_stop_t *stops, - cairo_gl_gradient_t **gradient_out) -{ - uintptr_t hash; - cairo_gl_gradient_t *gradient; - cairo_status_t status; - int tex_width; - GLint internal_format; - void *data; - - if ((unsigned int) ctx->max_texture_size / 2 <= n_stops) - return CAIRO_INT_STATUS_UNSUPPORTED; - - hash = _cairo_gl_gradient_hash (n_stops, stops); - - gradient = _cairo_gl_gradient_lookup (ctx, hash, n_stops, stops); - if (gradient) { - *gradient_out = _cairo_gl_gradient_reference (gradient); - return CAIRO_STATUS_SUCCESS; - } - - gradient = _cairo_malloc (sizeof (cairo_gl_gradient_t) + sizeof (cairo_gradient_stop_t) * (n_stops - 1)); - if (gradient == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - tex_width = _cairo_gl_gradient_sample_width (n_stops, stops); - if (tex_width > ctx->max_texture_size) - tex_width = ctx->max_texture_size; - - CAIRO_REFERENCE_COUNT_INIT (&gradient->ref_count, 2); - gradient->cache_entry.hash = hash; - gradient->cache_entry.size = tex_width; - gradient->device = &ctx->base; - gradient->n_stops = n_stops; - gradient->stops = gradient->stops_embedded; - memcpy (gradient->stops_embedded, stops, n_stops * sizeof (cairo_gradient_stop_t)); - - glGenTextures (1, &gradient->tex); - _cairo_gl_context_activate (ctx, CAIRO_GL_TEX_TEMP); - glBindTexture (ctx->tex_target, gradient->tex); - - data = _cairo_malloc_ab (tex_width, sizeof (uint32_t)); - if (unlikely (data == NULL)) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto cleanup_gradient; - } - - status = _cairo_gl_gradient_render (ctx, n_stops, stops, data, tex_width); - if (unlikely (status)) - goto cleanup_data; - - /* - * In OpenGL ES 2.0 no format conversion is allowed i.e. 'internalFormat' - * must match 'format' in glTexImage2D. - */ - if (_cairo_gl_get_flavor () == CAIRO_GL_FLAVOR_ES3 || - _cairo_gl_get_flavor () == CAIRO_GL_FLAVOR_ES2) - internal_format = GL_BGRA; - else - internal_format = GL_RGBA; - - glTexImage2D (ctx->tex_target, 0, internal_format, tex_width, 1, 0, - GL_BGRA, GL_UNSIGNED_BYTE, data); - - free (data); - - /* we ignore errors here and just return an uncached gradient */ - if (unlikely (_cairo_cache_insert (&ctx->gradients, &gradient->cache_entry))) - CAIRO_REFERENCE_COUNT_INIT (&gradient->ref_count, 1); - - *gradient_out = gradient; - return CAIRO_STATUS_SUCCESS; - -cleanup_data: - free (data); -cleanup_gradient: - free (gradient); - return status; -} - -cairo_gl_gradient_t * -_cairo_gl_gradient_reference (cairo_gl_gradient_t *gradient) -{ - assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&gradient->ref_count)); - - _cairo_reference_count_inc (&gradient->ref_count); - - return gradient; -} - -void -_cairo_gl_gradient_destroy (cairo_gl_gradient_t *gradient) -{ - cairo_gl_context_t *ctx; - cairo_status_t ignore; - - assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&gradient->ref_count)); - - if (! _cairo_reference_count_dec_and_test (&gradient->ref_count)) - return; - - if (_cairo_gl_context_acquire (gradient->device, &ctx) == CAIRO_STATUS_SUCCESS) { - /* The gradient my still be active in the last operation, so flush */ - _cairo_gl_composite_flush (ctx); - glDeleteTextures (1, &gradient->tex); - ignore = _cairo_gl_context_release (ctx, CAIRO_STATUS_SUCCESS); - } - - free (gradient); -} diff --git a/src/cairo-gl-info.c b/src/cairo-gl-info.c deleted file mode 100644 index c655b962e..000000000 --- a/src/cairo-gl-info.c +++ /dev/null @@ -1,147 +0,0 @@ -/* 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> - * Heiko Lewin <heiko.lewin@gmx.de> - */ - -#include "cairoint.h" -#include "cairo-gl-private.h" - -#include <errno.h> - -int -_cairo_gl_get_version (void) -{ - int major, minor; - const char *version = (const char *) glGetString (GL_VERSION); - const char *dot = version == NULL ? NULL : strchr (version, '.'); - const char *major_start = dot; - - /* Sanity check */ - if (dot == NULL || dot == version || *(dot + 1) == '\0') { - major = 0; - minor = 0; - } else { - /* Find the start of the major version in the string */ - while (major_start > version && *major_start != ' ') - --major_start; - major = strtol (major_start, NULL, 10); - minor = strtol (dot + 1, NULL, 10); - } - - return CAIRO_GL_VERSION_ENCODE (major, minor); -} - - -static cairo_gl_flavor_t -_cairo_gl_degrade_flavor_by_build_features (cairo_gl_flavor_t flavor) -{ - switch(flavor) { - case CAIRO_GL_FLAVOR_DESKTOP: -#if CAIRO_HAS_GL_SURFACE - return CAIRO_GL_FLAVOR_DESKTOP; -#else - return CAIRO_GL_FLAVOR_NONE; -#endif - - case CAIRO_GL_FLAVOR_ES3: -#if CAIRO_HAS_GLESV3_SURFACE - return CAIRO_GL_FLAVOR_ES3; -#else - /* intentional fall through: degrade to GLESv2 if GLESv3-surfaces are not available */ -#endif - - case CAIRO_GL_FLAVOR_ES2: -#if CAIRO_HAS_GLESV2_SURFACE - return CAIRO_GL_FLAVOR_ES2; -#else - /* intentional fall through: no OpenGL in first place or no surfaces for it's version */ -#endif - - case CAIRO_GL_FLAVOR_NONE: - default: - return CAIRO_GL_FLAVOR_NONE; - } -} - -cairo_gl_flavor_t -_cairo_gl_get_flavor (void) -{ - const char *version = (const char *) glGetString (GL_VERSION); - cairo_gl_flavor_t flavor; - - if (version == NULL) { - flavor = CAIRO_GL_FLAVOR_NONE; - } else if (strstr (version, "OpenGL ES 3") != NULL) { - flavor = CAIRO_GL_FLAVOR_ES3; - } else if (strstr (version, "OpenGL ES 2") != NULL) { - flavor = CAIRO_GL_FLAVOR_ES2; - } else { - flavor = CAIRO_GL_FLAVOR_DESKTOP; - } - - return _cairo_gl_degrade_flavor_by_build_features(flavor); -} - -unsigned long -_cairo_gl_get_vbo_size (void) -{ - unsigned long vbo_size; - - const char *env = getenv ("CAIRO_GL_VBO_SIZE"); - if (env == NULL) { - vbo_size = CAIRO_GL_VBO_SIZE_DEFAULT; - } else { - errno = 0; - vbo_size = strtol (env, NULL, 10); - assert (errno == 0); - assert (vbo_size > 0); - } - - return vbo_size; -} - -cairo_bool_t -_cairo_gl_has_extension (const char *ext) -{ - const char *extensions = (const char *) glGetString (GL_EXTENSIONS); - size_t len = strlen (ext); - const char *ext_ptr = extensions; - - if (unlikely (ext_ptr == NULL)) - return 0; - - while ((ext_ptr = strstr (ext_ptr, ext)) != NULL) { - if (ext_ptr[len] == ' ' || ext_ptr[len] == '\0') - break; - ext_ptr += len; - } - - return (ext_ptr != NULL); -} diff --git a/src/cairo-gl-msaa-compositor.c b/src/cairo-gl-msaa-compositor.c deleted file mode 100644 index 7a83dd219..000000000 --- a/src/cairo-gl-msaa-compositor.c +++ /dev/null @@ -1,956 +0,0 @@ -/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2002 University of Southern California - * Copyright © 2005 Red Hat, Inc. - * Copyright © 2011 Intel Corporation - * Copyright © 2011 Samsung Electronics - * - * 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 University of Southern - * California. - * - * Contributor(s): - * Henry Song <hsong@sisa.samsung.com> - * Martin Robinson <mrobinson@igalia.com> - */ - -#include "cairoint.h" - -#include "cairo-clip-inline.h" -#include "cairo-composite-rectangles-private.h" -#include "cairo-compositor-private.h" -#include "cairo-gl-private.h" -#include "cairo-path-private.h" -#include "cairo-traps-private.h" - -static cairo_bool_t -can_use_msaa_compositor (cairo_gl_surface_t *surface, - cairo_antialias_t antialias); - -static void -query_surface_capabilities (cairo_gl_surface_t *surface); - -struct _tristrip_composite_info { - cairo_gl_composite_t setup; - cairo_gl_context_t *ctx; -}; - -static cairo_int_status_t -_draw_trap (cairo_gl_context_t *ctx, - cairo_gl_composite_t *setup, - cairo_trapezoid_t *trap) -{ - cairo_point_t quad[4]; - - quad[0].x = _cairo_edge_compute_intersection_x_for_y (&trap->left.p1, - &trap->left.p2, - trap->top); - quad[0].y = trap->top; - - quad[1].x = _cairo_edge_compute_intersection_x_for_y (&trap->left.p1, - &trap->left.p2, - trap->bottom); - quad[1].y = trap->bottom; - - quad[2].x = _cairo_edge_compute_intersection_x_for_y (&trap->right.p1, - &trap->right.p2, - trap->bottom); - quad[2].y = trap->bottom; - - quad[3].x = _cairo_edge_compute_intersection_x_for_y (&trap->right.p1, - &trap->right.p2, - trap->top); - quad[3].y = trap->top; - return _cairo_gl_composite_emit_quad_as_tristrip (ctx, setup, quad); -} - -static cairo_int_status_t -_draw_traps (cairo_gl_context_t *ctx, - cairo_gl_composite_t *setup, - cairo_traps_t *traps) -{ - cairo_int_status_t status = CAIRO_STATUS_SUCCESS; - int i; - - for (i = 0; i < traps->num_traps; i++) { - cairo_trapezoid_t *trap = traps->traps + i; - if (unlikely ((status = _draw_trap (ctx, setup, trap)))) - return status; - } - - return status; -} - -static cairo_int_status_t -_draw_int_rect (cairo_gl_context_t *ctx, - cairo_gl_composite_t *setup, - cairo_rectangle_int_t *rect) -{ - cairo_box_t box; - cairo_point_t quad[4]; - - _cairo_box_from_rectangle (&box, rect); - quad[0].x = box.p1.x; - quad[0].y = box.p1.y; - quad[1].x = box.p1.x; - quad[1].y = box.p2.y; - quad[2].x = box.p2.x; - quad[2].y = box.p2.y; - quad[3].x = box.p2.x; - quad[3].y = box.p1.y; - - return _cairo_gl_composite_emit_quad_as_tristrip (ctx, setup, quad); -} - -static cairo_int_status_t -_draw_triangle_fan (cairo_gl_context_t *ctx, - cairo_gl_composite_t *setup, - const cairo_point_t *midpt, - const cairo_point_t *points, - int npoints) -{ - int i; - - /* Our strategy here is to not even try to build a triangle fan, but to - draw each triangle as if it was an unconnected member of a triangle strip. */ - for (i = 1; i < npoints; i++) { - cairo_int_status_t status; - cairo_point_t triangle[3]; - - triangle[0] = *midpt; - triangle[1] = points[i - 1]; - triangle[2] = points[i]; - - status = _cairo_gl_composite_emit_triangle_as_tristrip (ctx, setup, triangle); - if (unlikely (status)) - return status; - } - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -_clip_to_traps (cairo_clip_t *clip, - cairo_traps_t *traps) -{ - cairo_int_status_t status; - cairo_polygon_t polygon; - cairo_antialias_t antialias; - cairo_fill_rule_t fill_rule; - - _cairo_traps_init (traps); - - if (clip->num_boxes == 1 && clip->path == NULL) { - cairo_boxes_t boxes; - _cairo_boxes_init_for_array (&boxes, clip->boxes, clip->num_boxes); - return _cairo_traps_init_boxes (traps, &boxes); - } - - status = _cairo_clip_get_polygon (clip, &polygon, &fill_rule, &antialias); - if (unlikely (status)) - return status; - - /* We ignore the antialias mode of the clip here, since the user requested - * unantialiased rendering of their path and we expect that this stencil - * based rendering of the clip to be a reasonable approximation to - * the intersection between that clip and the path. - * - * In other words, what the user expects when they try to perform - * a geometric intersection between an unantialiased polygon and an - * antialiased polygon is open to interpretation. And we choose the fast - * option. - */ - - _cairo_traps_init (traps); - status = _cairo_bentley_ottmann_tessellate_polygon (traps, - &polygon, - fill_rule); - _cairo_polygon_fini (&polygon); - - return status; -} - -cairo_int_status_t -_cairo_gl_msaa_compositor_draw_clip (cairo_gl_context_t *ctx, - cairo_gl_composite_t *setup, - cairo_clip_t *clip) -{ - cairo_int_status_t status; - cairo_traps_t traps; - - status = _clip_to_traps (clip, &traps); - if (unlikely (status)) - return status; - status = _draw_traps (ctx, setup, &traps); - - _cairo_traps_fini (&traps); - return status; -} - -static cairo_bool_t -_should_use_unbounded_surface (cairo_composite_rectangles_t *composite) -{ - cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface; - cairo_rectangle_int_t *source = &composite->source; - - if (composite->is_bounded) - return FALSE; - - /* This isn't just an optimization. It also detects when painting is used - to paint back the unbounded surface, preventing infinite recursion. */ - return ! (source->x <= 0 && source->y <= 0 && - source->height + source->y >= dst->height && - source->width + source->x >= dst->width); -} - -static cairo_surface_t* -_prepare_unbounded_surface (cairo_gl_surface_t *dst) -{ - - cairo_surface_t* surface = cairo_gl_surface_create (dst->base.device, - dst->base.content, - dst->width, - dst->height); - if (surface == NULL) - return NULL; - if (unlikely (surface->status)) { - cairo_surface_destroy (surface); - return NULL; - } - return surface; -} - -static cairo_int_status_t -_paint_back_unbounded_surface (const cairo_compositor_t *compositor, - cairo_composite_rectangles_t *composite, - cairo_surface_t *surface) -{ - cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface; - cairo_int_status_t status; - - cairo_pattern_t *pattern = cairo_pattern_create_for_surface (surface); - if (unlikely (pattern->status)) { - status = pattern->status; - goto finish; - } - - status = _cairo_compositor_paint (compositor, &dst->base, - composite->op, pattern, - composite->clip); - -finish: - cairo_pattern_destroy (pattern); - cairo_surface_destroy (surface); - return status; -} - -static cairo_bool_t -can_use_msaa_compositor (cairo_gl_surface_t *surface, - cairo_antialias_t antialias) -{ - cairo_gl_flavor_t gl_flavor = ((cairo_gl_context_t *) surface->base.device)->gl_flavor; - - query_surface_capabilities (surface); - if (! surface->supports_stencil) - return FALSE; - - /* Multisampling OpenGL ES surfaces only maintain one multisampling - framebuffer and thus must use the spans compositor to do non-antialiased - rendering. */ - if ((gl_flavor == CAIRO_GL_FLAVOR_ES3 || - gl_flavor == CAIRO_GL_FLAVOR_ES2) - && surface->supports_msaa - && surface->num_samples > 1 - && antialias == CAIRO_ANTIALIAS_NONE) - return FALSE; - - /* The MSAA compositor has a single-sample mode, so we can - support non-antialiased rendering. */ - if (antialias == CAIRO_ANTIALIAS_NONE) - return TRUE; - - if (antialias == CAIRO_ANTIALIAS_FAST || antialias == CAIRO_ANTIALIAS_DEFAULT) - return surface->supports_msaa; - return FALSE; -} - -static void -_cairo_gl_msaa_compositor_set_clip (cairo_composite_rectangles_t *composite, - cairo_gl_composite_t *setup) -{ - if (_cairo_composite_rectangles_can_reduce_clip (composite, composite->clip)) - return; - _cairo_gl_composite_set_clip (setup, composite->clip); -} - -/* Masking with the SOURCE operator requires two passes. In the first - * pass we use the mask as the source to get: - * result = (1 - ma) * dst - * In the second pass we use the add operator to achieve: - * result = (src * ma) + dst - * Combined this produces: - * result = (src * ma) + (1 - ma) * dst - */ -static cairo_int_status_t -_cairo_gl_msaa_compositor_mask_source_operator (const cairo_compositor_t *compositor, - cairo_composite_rectangles_t *composite) -{ - cairo_gl_composite_t setup; - cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface; - cairo_gl_context_t *ctx = NULL; - cairo_int_status_t status; - - cairo_clip_t *clip = composite->clip; - cairo_traps_t traps; - - /* If we have a non-rectangular clip, we can avoid using the stencil buffer - * for clipping and just draw the clip polygon. */ - if (clip) { - status = _clip_to_traps (clip, &traps); - if (unlikely (status)) { - _cairo_traps_fini (&traps); - return status; - } - } - - status = _cairo_gl_composite_init (&setup, - CAIRO_OPERATOR_DEST_OUT, - dst, - FALSE /* assume_component_alpha */); - if (unlikely (status)) - return status; - status = _cairo_gl_composite_set_source (&setup, - &composite->mask_pattern.base, - &composite->mask_sample_area, - &composite->bounded, - FALSE); - if (unlikely (status)) - goto finish; - _cairo_gl_composite_set_multisample (&setup); - status = _cairo_gl_composite_begin (&setup, &ctx); - if (unlikely (status)) - goto finish; - - if (! clip) - status = _draw_int_rect (ctx, &setup, &composite->bounded); - else - status = _draw_traps (ctx, &setup, &traps); - if (unlikely (status)) - goto finish; - - /* Now draw the second pass. */ - status = _cairo_gl_composite_set_operator (&setup, CAIRO_OPERATOR_ADD, - FALSE /* assume_component_alpha */); - if (unlikely (status)) - goto finish; - status = _cairo_gl_composite_set_source (&setup, - &composite->source_pattern.base, - &composite->source_sample_area, - &composite->bounded, - FALSE); - if (unlikely (status)) - goto finish; - status = _cairo_gl_composite_set_mask (&setup, - &composite->mask_pattern.base, - &composite->source_sample_area, - &composite->bounded, - FALSE); - if (unlikely (status)) - goto finish; - - _cairo_gl_context_set_destination (ctx, dst, setup.multisample); - - status = _cairo_gl_set_operands_and_operator (&setup, ctx); - if (unlikely (status)) - goto finish; - - if (! clip) - status = _draw_int_rect (ctx, &setup, &composite->bounded); - else - status = _draw_traps (ctx, &setup, &traps); - -finish: - _cairo_gl_composite_fini (&setup); - if (ctx) - status = _cairo_gl_context_release (ctx, status); - if (clip) - _cairo_traps_fini (&traps); - - return status; -} - -static cairo_int_status_t -_cairo_gl_msaa_compositor_mask (const cairo_compositor_t *compositor, - cairo_composite_rectangles_t *composite) -{ - cairo_gl_composite_t setup; - cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface; - cairo_gl_context_t *ctx = NULL; - cairo_int_status_t status; - cairo_operator_t op = composite->op; - cairo_clip_t *clip = composite->clip; - - if (! can_use_msaa_compositor (dst, CAIRO_ANTIALIAS_DEFAULT)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - if (composite->op == CAIRO_OPERATOR_CLEAR && - composite->original_mask_pattern != NULL) - return CAIRO_INT_STATUS_UNSUPPORTED; - - /* GL compositing operators cannot properly represent a mask operation - using the SOURCE compositing operator in one pass. This only matters if - there actually is a mask (there isn't in a paint operation) and if the - mask isn't totally opaque. */ - if (op == CAIRO_OPERATOR_SOURCE && - composite->original_mask_pattern != NULL && - ! _cairo_pattern_is_opaque (&composite->mask_pattern.base, - &composite->mask_sample_area)) { - - if (! _cairo_pattern_is_opaque (&composite->source_pattern.base, - &composite->source_sample_area)) { - return _cairo_gl_msaa_compositor_mask_source_operator (compositor, composite); - } - - /* If the source is opaque the operation reduces to OVER. */ - op = CAIRO_OPERATOR_OVER; - } - - if (_should_use_unbounded_surface (composite)) { - cairo_surface_t* surface = _prepare_unbounded_surface (dst); - - if (unlikely (surface == NULL)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - /* This may be a paint operation. */ - if (composite->original_mask_pattern == NULL) { - status = _cairo_compositor_paint (compositor, surface, - CAIRO_OPERATOR_SOURCE, - &composite->source_pattern.base, - NULL); - } else { - status = _cairo_compositor_mask (compositor, surface, - CAIRO_OPERATOR_SOURCE, - &composite->source_pattern.base, - &composite->mask_pattern.base, - NULL); - } - - if (unlikely (status)) { - cairo_surface_destroy (surface); - return status; - } - - return _paint_back_unbounded_surface (compositor, composite, surface); - } - - status = _cairo_gl_composite_init (&setup, - op, - dst, - FALSE /* assume_component_alpha */); - if (unlikely (status)) - return status; - - status = _cairo_gl_composite_set_source (&setup, - &composite->source_pattern.base, - &composite->source_sample_area, - &composite->bounded, - FALSE); - if (unlikely (status)) - goto finish; - - if (composite->original_mask_pattern != NULL) { - status = _cairo_gl_composite_set_mask (&setup, - &composite->mask_pattern.base, - &composite->mask_sample_area, - &composite->bounded, - FALSE); - } - if (unlikely (status)) - goto finish; - - /* We always use multisampling here, because we do not yet have the smarts - to calculate when the clip or the source requires it. */ - _cairo_gl_composite_set_multisample (&setup); - - status = _cairo_gl_composite_begin (&setup, &ctx); - if (unlikely (status)) - goto finish; - - if (! clip) - status = _draw_int_rect (ctx, &setup, &composite->bounded); - else - status = _cairo_gl_msaa_compositor_draw_clip (ctx, &setup, clip); - -finish: - _cairo_gl_composite_fini (&setup); - - if (ctx) - status = _cairo_gl_context_release (ctx, status); - - return status; -} - -static cairo_int_status_t -_cairo_gl_msaa_compositor_paint (const cairo_compositor_t *compositor, - cairo_composite_rectangles_t *composite) -{ - return _cairo_gl_msaa_compositor_mask (compositor, composite); -} - -static cairo_status_t -_stroke_shaper_add_triangle (void *closure, - const cairo_point_t triangle[3]) -{ - struct _tristrip_composite_info *info = closure; - return _cairo_gl_composite_emit_triangle_as_tristrip (info->ctx, - &info->setup, - triangle); -} - -static cairo_status_t -_stroke_shaper_add_triangle_fan (void *closure, - const cairo_point_t *midpoint, - const cairo_point_t *points, - int npoints) -{ - struct _tristrip_composite_info *info = closure; - return _draw_triangle_fan (info->ctx, &info->setup, - midpoint, points, npoints); -} - -static cairo_status_t -_stroke_shaper_add_quad (void *closure, - const cairo_point_t quad[4]) -{ - struct _tristrip_composite_info *info = closure; - return _cairo_gl_composite_emit_quad_as_tristrip (info->ctx, &info->setup, - quad); -} - -static cairo_int_status_t -_prevent_overlapping_strokes (cairo_gl_context_t *ctx, - cairo_gl_composite_t *setup, - cairo_composite_rectangles_t *composite, - const cairo_path_fixed_t *path, - const cairo_stroke_style_t *style, - const cairo_matrix_t *ctm) -{ - cairo_rectangle_int_t stroke_extents; - - if (! _cairo_gl_ensure_stencil (ctx, setup->dst)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - if (_cairo_pattern_is_opaque (&composite->source_pattern.base, - &composite->source_sample_area)) - return CAIRO_INT_STATUS_SUCCESS; - - if (glIsEnabled (GL_STENCIL_TEST) == FALSE) { - cairo_bool_t scissor_was_enabled; - - /* In case we have pending operations we have to flush before - adding the stencil buffer. */ - _cairo_gl_composite_flush (ctx); - - /* Enable the stencil buffer, even if we are not using it for clipping, - so we can use it below to prevent overlapping shapes. We initialize - it all to one here which represents infinite clip. */ - glDepthMask (GL_TRUE); - glEnable (GL_STENCIL_TEST); - - /* We scissor here so that we don't have to clear the entire stencil - * buffer. If the scissor test is already enabled, it was enabled - * for clipping. In that case, instead of calculating an intersection, - * we just reuse it, and risk clearing too much. */ - scissor_was_enabled = glIsEnabled (GL_SCISSOR_TEST); - if (! scissor_was_enabled) { - _cairo_path_fixed_approximate_stroke_extents (path, style, ctm, - FALSE, /* is_vector */ - &stroke_extents); - _cairo_gl_scissor_to_rectangle (setup->dst, &stroke_extents); - } - glClearStencil (1); - glClear (GL_STENCIL_BUFFER_BIT); - if (! scissor_was_enabled) - glDisable (GL_SCISSOR_TEST); - - glStencilFunc (GL_EQUAL, 1, 1); - } - - /* This means that once we draw to a particular pixel nothing else can - be drawn there until the stencil buffer is reset or the stencil test - is disabled. */ - glStencilOp (GL_ZERO, GL_ZERO, GL_ZERO); - - _cairo_clip_destroy (setup->dst->clip_on_stencil_buffer); - setup->dst->clip_on_stencil_buffer = NULL; - - return CAIRO_INT_STATUS_SUCCESS; -} - -static void -query_surface_capabilities (cairo_gl_surface_t *surface) -{ - GLint samples, stencil_bits; - cairo_gl_context_t *ctx; - cairo_int_status_t status; - - /* Texture surfaces are create in such a way that they always - have stencil and multisample bits if possible, so we don't - need to query their capabilities lazily. */ - if (_cairo_gl_surface_is_texture (surface)) - return; - if (surface->stencil_and_msaa_caps_initialized) - return; - - surface->stencil_and_msaa_caps_initialized = TRUE; - surface->supports_stencil = FALSE; - surface->supports_msaa = FALSE; - - status = _cairo_gl_context_acquire (surface->base.device, &ctx); - if (unlikely (status)) - return; - - _cairo_gl_context_set_destination (ctx, surface, FALSE); - - glGetIntegerv(GL_SAMPLES, &samples); - glGetIntegerv(GL_STENCIL_BITS, &stencil_bits); - surface->supports_stencil = stencil_bits > 0; - surface->supports_msaa = samples > 1; - surface->num_samples = samples; - - status = _cairo_gl_context_release (ctx, status); -} - -static cairo_int_status_t -_cairo_gl_msaa_compositor_stroke (const cairo_compositor_t *compositor, - cairo_composite_rectangles_t *composite, - const cairo_path_fixed_t *path, - const cairo_stroke_style_t *style, - const cairo_matrix_t *ctm, - const cairo_matrix_t *ctm_inverse, - double tolerance, - cairo_antialias_t antialias) -{ - cairo_int_status_t status; - cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface; - struct _tristrip_composite_info info; - - if (! can_use_msaa_compositor (dst, antialias)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - if (composite->is_bounded == FALSE) { - cairo_surface_t* surface = _prepare_unbounded_surface (dst); - - if (unlikely (surface == NULL)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - status = _cairo_compositor_stroke (compositor, surface, - CAIRO_OPERATOR_SOURCE, - &composite->source_pattern.base, - path, style, ctm, ctm_inverse, - tolerance, antialias, NULL); - if (unlikely (status)) { - cairo_surface_destroy (surface); - return status; - } - - return _paint_back_unbounded_surface (compositor, composite, surface); - } - - status = _cairo_gl_composite_init (&info.setup, - composite->op, - dst, - FALSE /* assume_component_alpha */); - if (unlikely (status)) - return status; - - info.ctx = NULL; - - status = _cairo_gl_composite_set_source (&info.setup, - &composite->source_pattern.base, - &composite->source_sample_area, - &composite->bounded, - FALSE); - if (unlikely (status)) - goto finish; - - _cairo_gl_msaa_compositor_set_clip (composite, &info.setup); - if (antialias != CAIRO_ANTIALIAS_NONE) - _cairo_gl_composite_set_multisample (&info.setup); - - status = _cairo_gl_composite_begin (&info.setup, &info.ctx); - if (unlikely (status)) - goto finish; - - status = _prevent_overlapping_strokes (info.ctx, &info.setup, - composite, path, style, ctm); - if (unlikely (status)) - goto finish; - - status = _cairo_path_fixed_stroke_to_shaper ((cairo_path_fixed_t *) path, - style, - ctm, - ctm_inverse, - tolerance, - _stroke_shaper_add_triangle, - _stroke_shaper_add_triangle_fan, - _stroke_shaper_add_quad, - &info); - if (unlikely (status)) - goto finish; - -finish: - _cairo_gl_composite_fini (&info.setup); - - if (info.ctx) - status = _cairo_gl_context_release (info.ctx, status); - - return status; -} - -static cairo_int_status_t -_draw_simple_quad_path (cairo_gl_context_t *ctx, - cairo_gl_composite_t *setup, - const cairo_path_fixed_t *path) -{ - cairo_point_t triangle[3]; - cairo_int_status_t status; - const cairo_point_t *points; - - points = cairo_path_head (path)->points; - triangle[0] = points[0]; - triangle[1] = points[1]; - triangle[2] = points[2]; - status = _cairo_gl_composite_emit_triangle_as_tristrip (ctx, setup, triangle); - if (status) - return status; - - triangle[0] = points[2]; - triangle[1] = points[3]; - triangle[2] = points[0]; - return _cairo_gl_composite_emit_triangle_as_tristrip (ctx, setup, triangle); -} - -static cairo_int_status_t -_cairo_gl_msaa_compositor_fill (const cairo_compositor_t *compositor, - cairo_composite_rectangles_t *composite, - const cairo_path_fixed_t *path, - cairo_fill_rule_t fill_rule, - double tolerance, - cairo_antialias_t antialias) -{ - cairo_gl_composite_t setup; - cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface; - cairo_gl_context_t *ctx = NULL; - cairo_int_status_t status; - cairo_traps_t traps; - cairo_bool_t draw_path_with_traps; - - if (! can_use_msaa_compositor (dst, antialias)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - if (composite->is_bounded == FALSE) { - cairo_surface_t* surface = _prepare_unbounded_surface (dst); - - if (unlikely (surface == NULL)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - - status = _cairo_compositor_fill (compositor, surface, - CAIRO_OPERATOR_SOURCE, - &composite->source_pattern.base, - path, fill_rule, tolerance, - antialias, NULL); - - if (unlikely (status)) { - cairo_surface_destroy (surface); - return status; - } - - return _paint_back_unbounded_surface (compositor, composite, surface); - } - - draw_path_with_traps = ! _cairo_path_fixed_is_simple_quad (path); - - if (draw_path_with_traps) { - _cairo_traps_init (&traps); - status = _cairo_path_fixed_fill_to_traps (path, fill_rule, tolerance, &traps); - if (unlikely (status)) - goto cleanup_traps; - } - - status = _cairo_gl_composite_init (&setup, - composite->op, - dst, - FALSE /* assume_component_alpha */); - if (unlikely (status)) - goto cleanup_traps; - - status = _cairo_gl_composite_set_source (&setup, - &composite->source_pattern.base, - &composite->source_sample_area, - &composite->bounded, - FALSE); - if (unlikely (status)) - goto cleanup_setup; - - _cairo_gl_msaa_compositor_set_clip (composite, &setup); - if (antialias != CAIRO_ANTIALIAS_NONE) - _cairo_gl_composite_set_multisample (&setup); - - status = _cairo_gl_composite_begin (&setup, &ctx); - if (unlikely (status)) - goto cleanup_setup; - - if (! draw_path_with_traps) - status = _draw_simple_quad_path (ctx, &setup, path); - else - status = _draw_traps (ctx, &setup, &traps); - if (unlikely (status)) - goto cleanup_setup; - -cleanup_setup: - _cairo_gl_composite_fini (&setup); - - if (ctx) - status = _cairo_gl_context_release (ctx, status); - -cleanup_traps: - if (draw_path_with_traps) - _cairo_traps_fini (&traps); - - return status; -} - -static cairo_int_status_t -_cairo_gl_msaa_compositor_glyphs (const cairo_compositor_t *compositor, - cairo_composite_rectangles_t *composite, - cairo_scaled_font_t *scaled_font, - cairo_glyph_t *glyphs, - int num_glyphs, - cairo_bool_t overlap) -{ - cairo_int_status_t status; - cairo_surface_t *src = NULL; - int src_x, src_y; - cairo_composite_glyphs_info_t info; - - cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface; - - query_surface_capabilities (dst); - if (! dst->supports_stencil) - return CAIRO_INT_STATUS_UNSUPPORTED; - - if (composite->op == CAIRO_OPERATOR_CLEAR) - return CAIRO_INT_STATUS_UNSUPPORTED; - - if (composite->is_bounded == FALSE) { - cairo_surface_t* surface = _prepare_unbounded_surface (dst); - - if (unlikely (surface == NULL)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - status = _cairo_compositor_glyphs (compositor, surface, - CAIRO_OPERATOR_SOURCE, - &composite->source_pattern.base, - glyphs, num_glyphs, - scaled_font, composite->clip); - - if (unlikely (status)) { - cairo_surface_destroy (surface); - return status; - } - - return _paint_back_unbounded_surface (compositor, composite, surface); - } - - src = _cairo_gl_pattern_to_source (&dst->base, - &composite->source_pattern.base, - FALSE, - &composite->bounded, - &composite->source_sample_area, - &src_x, &src_y); - if (unlikely (src->status)) { - status = src->status; - goto finish; - } - - status = _cairo_gl_check_composite_glyphs (composite, - scaled_font, glyphs, - &num_glyphs); - if (unlikely (status != CAIRO_INT_STATUS_SUCCESS)) - goto finish; - - info.font = scaled_font; - info.glyphs = glyphs; - info.num_glyphs = num_glyphs; - info.use_mask = overlap || ! composite->is_bounded || - composite->op == CAIRO_OPERATOR_SOURCE; - info.extents = composite->bounded; - - _cairo_scaled_font_freeze_cache (scaled_font); - status = _cairo_gl_composite_glyphs_with_clip (dst, composite->op, - src, src_x, src_y, - 0, 0, &info, - composite->clip); - - _cairo_scaled_font_thaw_cache (scaled_font); - -finish: - if (src) - cairo_surface_destroy (src); - - return status; -} - -static void -_cairo_gl_msaa_compositor_init (cairo_compositor_t *compositor, - const cairo_compositor_t *delegate) -{ - compositor->delegate = delegate; - - compositor->paint = _cairo_gl_msaa_compositor_paint; - compositor->mask = _cairo_gl_msaa_compositor_mask; - compositor->fill = _cairo_gl_msaa_compositor_fill; - compositor->stroke = _cairo_gl_msaa_compositor_stroke; - compositor->glyphs = _cairo_gl_msaa_compositor_glyphs; -} - -const cairo_compositor_t * -_cairo_gl_msaa_compositor_get (void) -{ - static cairo_atomic_once_t once = CAIRO_ATOMIC_ONCE_INIT; - static cairo_compositor_t compositor; - if (_cairo_atomic_init_once_enter(&once)) { - _cairo_gl_msaa_compositor_init (&compositor, - _cairo_gl_span_compositor_get ()); - _cairo_atomic_init_once_leave(&once); - } - - return &compositor; -} diff --git a/src/cairo-gl-operand.c b/src/cairo-gl-operand.c deleted file mode 100644 index a754bde2f..000000000 --- a/src/cairo-gl-operand.c +++ /dev/null @@ -1,793 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2009 Eric Anholt - * Copyright © 2009 Chris Wilson - * Copyright © 2005,2010 Red Hat, Inc - * Copyright © 2011 Intel Corporation - * - * 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 Red Hat, Inc. - * - * Contributor(s): - * Benjamin Otte <otte@gnome.org> - * Carl Worth <cworth@cworth.org> - * Chris Wilson <chris@chris-wilson.co.uk> - * Eric Anholt <eric@anholt.net> - */ - -#include "cairoint.h" - -#include "cairo-gl-private.h" - -#include "cairo-composite-rectangles-private.h" -#include "cairo-compositor-private.h" -#include "cairo-default-context-private.h" -#include "cairo-error-private.h" -#include "cairo-image-surface-private.h" -#include "cairo-surface-backend-private.h" -#include "cairo-surface-offset-private.h" -#include "cairo-surface-subsurface-inline.h" - -static cairo_int_status_t -_cairo_gl_create_gradient_texture (cairo_gl_surface_t *dst, - const cairo_gradient_pattern_t *pattern, - cairo_gl_gradient_t **gradient) -{ - cairo_gl_context_t *ctx; - cairo_status_t status; - - status = _cairo_gl_context_acquire (dst->base.device, &ctx); - if (unlikely (status)) - return status; - - status = _cairo_gl_gradient_create (ctx, pattern->n_stops, pattern->stops, gradient); - - return _cairo_gl_context_release (ctx, status); -} - -static cairo_status_t -_cairo_gl_subsurface_clone_operand_init (cairo_gl_operand_t *operand, - const cairo_pattern_t *_src, - cairo_gl_surface_t *dst, - const cairo_rectangle_int_t *sample, - const cairo_rectangle_int_t *extents, - cairo_bool_t use_texgen) -{ - const cairo_surface_pattern_t *src = (cairo_surface_pattern_t *)_src; - cairo_surface_pattern_t local_pattern; - cairo_surface_subsurface_t *sub; - cairo_gl_surface_t *surface; - cairo_gl_context_t *ctx; - cairo_surface_attributes_t *attributes; - cairo_status_t status; - - sub = (cairo_surface_subsurface_t *) src->surface; - - if (sub->snapshot && - sub->snapshot->type == CAIRO_SURFACE_TYPE_GL && - sub->snapshot->device == dst->base.device) - { - surface = (cairo_gl_surface_t *) - cairo_surface_reference (sub->snapshot); - } - else - { - status = _cairo_gl_context_acquire (dst->base.device, &ctx); - if (unlikely (status)) - return status; - - /* XXX Trim surface to the sample area within the subsurface? */ - surface = (cairo_gl_surface_t *) - _cairo_gl_surface_create_scratch (ctx, - sub->target->content, - sub->extents.width, - sub->extents.height); - if (surface->base.status) - return _cairo_gl_context_release (ctx, surface->base.status); - - _cairo_pattern_init_for_surface (&local_pattern, sub->target); - cairo_matrix_init_translate (&local_pattern.base.matrix, - sub->extents.x, sub->extents.y); - local_pattern.base.filter = CAIRO_FILTER_NEAREST; - status = _cairo_surface_paint (&surface->base, - CAIRO_OPERATOR_SOURCE, - &local_pattern.base, - NULL); - _cairo_pattern_fini (&local_pattern.base); - - status = _cairo_gl_context_release (ctx, status); - if (unlikely (status)) { - cairo_surface_destroy (&surface->base); - return status; - } - - _cairo_surface_subsurface_set_snapshot (&sub->base, &surface->base); - } - - status = _cairo_gl_surface_resolve_multisampling (surface); - if (unlikely (status)) - return status; - - attributes = &operand->texture.attributes; - - operand->type = CAIRO_GL_OPERAND_TEXTURE; - operand->texture.surface = surface; - operand->texture.owns_surface = surface; - operand->texture.tex = surface->tex; - - if (_cairo_gl_device_requires_power_of_two_textures (dst->base.device)) { - attributes->matrix = src->base.matrix; - } else { - cairo_matrix_t m; - - cairo_matrix_init_scale (&m, - 1.0 / surface->width, - 1.0 / surface->height); - cairo_matrix_multiply (&attributes->matrix, &src->base.matrix, &m); - } - - attributes->extend = src->base.extend; - attributes->filter = src->base.filter; - attributes->has_component_alpha = src->base.has_component_alpha; - - operand->texture.texgen = use_texgen; - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_gl_subsurface_operand_init (cairo_gl_operand_t *operand, - const cairo_pattern_t *_src, - cairo_gl_surface_t *dst, - const cairo_rectangle_int_t *sample, - const cairo_rectangle_int_t *extents, - cairo_bool_t use_texgen) -{ - const cairo_surface_pattern_t *src = (cairo_surface_pattern_t *)_src; - cairo_surface_subsurface_t *sub; - cairo_gl_surface_t *surface; - cairo_surface_attributes_t *attributes; - cairo_int_status_t status; - - sub = (cairo_surface_subsurface_t *) src->surface; - - if (sample->x < 0 || sample->y < 0 || - sample->x + sample->width > sub->extents.width || - sample->y + sample->height > sub->extents.height) - { - return _cairo_gl_subsurface_clone_operand_init (operand, _src, - dst, sample, extents, - use_texgen); - } - - surface = (cairo_gl_surface_t *) sub->target; - if (surface->base.device && surface->base.device != dst->base.device) - return CAIRO_INT_STATUS_UNSUPPORTED; - - if (! _cairo_gl_surface_is_texture (surface)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - status = _cairo_gl_surface_resolve_multisampling (surface); - if (unlikely (status)) - return status; - - /* Translate the matrix from - * (unnormalized src -> unnormalized src) to - * (unnormalized dst -> unnormalized src) - */ - _cairo_gl_operand_copy(operand, &surface->operand); - - attributes = &operand->texture.attributes; - attributes->matrix = src->base.matrix; - attributes->matrix.x0 += sub->extents.x; - attributes->matrix.y0 += sub->extents.y; - cairo_matrix_multiply (&attributes->matrix, - &attributes->matrix, - &surface->operand.texture.attributes.matrix); - - attributes->extend = src->base.extend; - attributes->filter = src->base.filter; - attributes->has_component_alpha = src->base.has_component_alpha; - - operand->texture.texgen = use_texgen; - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_gl_surface_operand_init (cairo_gl_operand_t *operand, - const cairo_pattern_t *_src, - cairo_gl_surface_t *dst, - const cairo_rectangle_int_t *sample, - const cairo_rectangle_int_t *extents, - cairo_bool_t use_texgen) -{ - const cairo_surface_pattern_t *src = (cairo_surface_pattern_t *)_src; - cairo_gl_surface_t *surface; - cairo_surface_attributes_t *attributes; - cairo_int_status_t status; - - surface = (cairo_gl_surface_t *) src->surface; - if (surface->base.type != CAIRO_SURFACE_TYPE_GL) - return CAIRO_INT_STATUS_UNSUPPORTED; - - if (surface->base.backend->type != CAIRO_SURFACE_TYPE_GL) { - if (_cairo_surface_is_subsurface (&surface->base)) - return _cairo_gl_subsurface_operand_init (operand, _src, dst, - sample, extents, - use_texgen); - - return CAIRO_INT_STATUS_UNSUPPORTED; - } - - if (surface->base.device && surface->base.device != dst->base.device) - return CAIRO_INT_STATUS_UNSUPPORTED; - - if (surface->base.device && ! _cairo_gl_surface_is_texture (surface)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - status = _cairo_gl_surface_resolve_multisampling (surface); - if (unlikely (status)) - return status; - - _cairo_gl_operand_copy(operand, &surface->operand); - - attributes = &operand->texture.attributes; - cairo_matrix_multiply (&attributes->matrix, - &src->base.matrix, - &attributes->matrix); - - attributes->extend = src->base.extend; - attributes->filter = src->base.filter; - attributes->has_component_alpha = src->base.has_component_alpha; - - operand->texture.texgen = use_texgen; - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_gl_pattern_texture_setup (cairo_gl_operand_t *operand, - const cairo_pattern_t *_src, - cairo_gl_surface_t *dst, - const cairo_rectangle_int_t *extents) -{ - cairo_status_t status; - cairo_gl_surface_t *surface; - cairo_gl_context_t *ctx; - cairo_image_surface_t *image; - cairo_bool_t src_is_gl_surface = FALSE; - cairo_rectangle_int_t map_extents; - - if (_src->type == CAIRO_PATTERN_TYPE_SURFACE) { - cairo_surface_t* src_surface = ((cairo_surface_pattern_t *) _src)->surface; - src_is_gl_surface = src_surface->type == CAIRO_SURFACE_TYPE_GL; - } - - status = _cairo_gl_context_acquire (dst->base.device, &ctx); - if (unlikely (status)) - return status; - - surface = (cairo_gl_surface_t *) - _cairo_gl_surface_create_scratch (ctx, - CAIRO_CONTENT_COLOR_ALPHA, - extents->width, extents->height); - map_extents = *extents; - map_extents.x = map_extents.y = 0; - image = _cairo_surface_map_to_image (&surface->base, &map_extents); - - /* If the pattern is a GL surface, it belongs to some other GL context, - so we need to release this device while we paint it to the image. */ - if (src_is_gl_surface) { - status = _cairo_gl_context_release (ctx, status); - if (unlikely (status)) { - _cairo_surface_unmap_image (&surface->base, image); - goto fail; - } - } - - status = _cairo_surface_offset_paint (&image->base, extents->x, extents->y, - CAIRO_OPERATOR_SOURCE, _src, NULL); - - if (src_is_gl_surface) { - status = _cairo_gl_context_acquire (dst->base.device, &ctx); - if (unlikely (status)) { - _cairo_surface_unmap_image (&surface->base, image); - goto fail; - } - } - - status = _cairo_surface_unmap_image (&surface->base, image); - status = _cairo_gl_context_release (ctx, status); - if (unlikely (status)) - goto fail; - - *operand = surface->operand; - operand->texture.owns_surface = surface; - operand->texture.attributes.matrix.x0 -= extents->x * operand->texture.attributes.matrix.xx; - operand->texture.attributes.matrix.y0 -= extents->y * operand->texture.attributes.matrix.yy; - return CAIRO_STATUS_SUCCESS; - -fail: - cairo_surface_destroy (&surface->base); - return status; -} - -void -_cairo_gl_solid_operand_init (cairo_gl_operand_t *operand, - const cairo_color_t *color) -{ - operand->type = CAIRO_GL_OPERAND_CONSTANT; - operand->constant.color[0] = color->red * color->alpha; - operand->constant.color[1] = color->green * color->alpha; - operand->constant.color[2] = color->blue * color->alpha; - operand->constant.color[3] = color->alpha; -} - -void -_cairo_gl_operand_translate (cairo_gl_operand_t *operand, - double tx, double ty) -{ - switch (operand->type) { - case CAIRO_GL_OPERAND_TEXTURE: - operand->texture.attributes.matrix.x0 -= tx * operand->texture.attributes.matrix.xx; - operand->texture.attributes.matrix.y0 -= ty * operand->texture.attributes.matrix.yy; - break; - - case CAIRO_GL_OPERAND_LINEAR_GRADIENT: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT: - operand->gradient.m.x0 -= tx * operand->gradient.m.xx; - operand->gradient.m.y0 -= ty * operand->gradient.m.yy; - break; - - case CAIRO_GL_OPERAND_NONE: - case CAIRO_GL_OPERAND_CONSTANT: - case CAIRO_GL_OPERAND_COUNT: - default: - break; - } -} - -static cairo_status_t -_cairo_gl_gradient_operand_init (cairo_gl_operand_t *operand, - const cairo_pattern_t *pattern, - cairo_gl_surface_t *dst, - cairo_bool_t use_texgen) -{ - const cairo_gradient_pattern_t *gradient = (const cairo_gradient_pattern_t *)pattern; - cairo_status_t status; - - assert (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR || - gradient->base.type == CAIRO_PATTERN_TYPE_RADIAL); - - if (! _cairo_gl_device_has_glsl (dst->base.device)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - status = _cairo_gl_create_gradient_texture (dst, - gradient, - &operand->gradient.gradient); - if (unlikely (status)) - return status; - - if (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR) { - cairo_linear_pattern_t *linear = (cairo_linear_pattern_t *) gradient; - double x0, y0, dx, dy, sf, offset; - - dx = linear->pd2.x - linear->pd1.x; - dy = linear->pd2.y - linear->pd1.y; - sf = 1.0 / (dx * dx + dy * dy); - dx *= sf; - dy *= sf; - - x0 = linear->pd1.x; - y0 = linear->pd1.y; - offset = dx * x0 + dy * y0; - - operand->type = CAIRO_GL_OPERAND_LINEAR_GRADIENT; - - cairo_matrix_init (&operand->gradient.m, dx, 0, dy, 1, -offset, 0); - if (! _cairo_matrix_is_identity (&pattern->matrix)) { - cairo_matrix_multiply (&operand->gradient.m, - &pattern->matrix, - &operand->gradient.m); - } - } else { - cairo_matrix_t m; - cairo_circle_double_t circles[2]; - double x0, y0, r0, dx, dy, dr; - - /* - * Some fragment shader implementations use half-floats to - * represent numbers, so the maximum number they can represent - * is about 2^14. Some intermediate computations used in the - * radial gradient shaders can produce results of up to 2*k^4. - * Setting k=8 makes the maximum result about 8192 (assuming - * that the extreme circles are not much smaller than the - * destination image). - */ - _cairo_gradient_pattern_fit_to_range (gradient, 8., - &operand->gradient.m, circles); - - x0 = circles[0].center.x; - y0 = circles[0].center.y; - r0 = circles[0].radius; - dx = circles[1].center.x - x0; - dy = circles[1].center.y - y0; - dr = circles[1].radius - r0; - - operand->gradient.a = dx * dx + dy * dy - dr * dr; - operand->gradient.radius_0 = r0; - operand->gradient.circle_d.center.x = dx; - operand->gradient.circle_d.center.y = dy; - operand->gradient.circle_d.radius = dr; - - if (operand->gradient.a == 0) - operand->type = CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0; - else if (pattern->extend == CAIRO_EXTEND_NONE) - operand->type = CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE; - else - operand->type = CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT; - - cairo_matrix_init_translate (&m, -x0, -y0); - cairo_matrix_multiply (&operand->gradient.m, - &operand->gradient.m, - &m); - } - - operand->gradient.extend = pattern->extend; - operand->gradient.texgen = use_texgen; - - return CAIRO_STATUS_SUCCESS; -} - -void -_cairo_gl_operand_copy (cairo_gl_operand_t *dst, - const cairo_gl_operand_t *src) -{ - *dst = *src; - switch (dst->type) { - case CAIRO_GL_OPERAND_CONSTANT: - break; - case CAIRO_GL_OPERAND_LINEAR_GRADIENT: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT: - _cairo_gl_gradient_reference (dst->gradient.gradient); - break; - case CAIRO_GL_OPERAND_TEXTURE: - cairo_surface_reference (&dst->texture.owns_surface->base); - break; - default: - case CAIRO_GL_OPERAND_COUNT: - ASSERT_NOT_REACHED; - case CAIRO_GL_OPERAND_NONE: - break; - } -} - -void -_cairo_gl_operand_destroy (cairo_gl_operand_t *operand) -{ - switch (operand->type) { - case CAIRO_GL_OPERAND_CONSTANT: - break; - case CAIRO_GL_OPERAND_LINEAR_GRADIENT: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT: - _cairo_gl_gradient_destroy (operand->gradient.gradient); - break; - case CAIRO_GL_OPERAND_TEXTURE: - cairo_surface_destroy (&operand->texture.owns_surface->base); - break; - default: - case CAIRO_GL_OPERAND_COUNT: - ASSERT_NOT_REACHED; - case CAIRO_GL_OPERAND_NONE: - break; - } - - operand->type = CAIRO_GL_OPERAND_NONE; -} - -cairo_int_status_t -_cairo_gl_operand_init (cairo_gl_operand_t *operand, - const cairo_pattern_t *pattern, - cairo_gl_surface_t *dst, - const cairo_rectangle_int_t *sample, - const cairo_rectangle_int_t *extents, - cairo_bool_t use_texgen) -{ - cairo_int_status_t status; - - TRACE ((stderr, "%s: type=%d\n", __FUNCTION__, pattern->type)); - switch (pattern->type) { - case CAIRO_PATTERN_TYPE_SOLID: - _cairo_gl_solid_operand_init (operand, - &((cairo_solid_pattern_t *) pattern)->color); - return CAIRO_STATUS_SUCCESS; - case CAIRO_PATTERN_TYPE_SURFACE: - status = _cairo_gl_surface_operand_init (operand, pattern, dst, - sample, extents, use_texgen); - if (status == CAIRO_INT_STATUS_UNSUPPORTED) - break; - - return status; - - case CAIRO_PATTERN_TYPE_LINEAR: - case CAIRO_PATTERN_TYPE_RADIAL: - status = _cairo_gl_gradient_operand_init (operand, pattern, dst, - use_texgen); - if (status == CAIRO_INT_STATUS_UNSUPPORTED) - break; - - return status; - - default: - case CAIRO_PATTERN_TYPE_MESH: - case CAIRO_PATTERN_TYPE_RASTER_SOURCE: - break; - } - - return _cairo_gl_pattern_texture_setup (operand, pattern, dst, extents); -} - -cairo_filter_t -_cairo_gl_operand_get_filter (cairo_gl_operand_t *operand) -{ - cairo_filter_t filter; - - switch ((int) operand->type) { - case CAIRO_GL_OPERAND_TEXTURE: - filter = operand->texture.attributes.filter; - break; - case CAIRO_GL_OPERAND_LINEAR_GRADIENT: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT: - filter = CAIRO_FILTER_BILINEAR; - break; - default: - filter = CAIRO_FILTER_DEFAULT; - break; - } - - return filter; -} - -GLint -_cairo_gl_operand_get_gl_filter (cairo_gl_operand_t *operand) -{ - cairo_filter_t filter = _cairo_gl_operand_get_filter (operand); - - return filter != CAIRO_FILTER_FAST && filter != CAIRO_FILTER_NEAREST ? - GL_LINEAR : - GL_NEAREST; -} - -cairo_extend_t -_cairo_gl_operand_get_extend (cairo_gl_operand_t *operand) -{ - cairo_extend_t extend; - - switch ((int) operand->type) { - case CAIRO_GL_OPERAND_TEXTURE: - extend = operand->texture.attributes.extend; - break; - case CAIRO_GL_OPERAND_LINEAR_GRADIENT: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT: - extend = operand->gradient.extend; - break; - default: - extend = CAIRO_EXTEND_NONE; - break; - } - - return extend; -} - - -void -_cairo_gl_operand_bind_to_shader (cairo_gl_context_t *ctx, - cairo_gl_operand_t *operand, - cairo_gl_tex_t tex_unit) -{ - const cairo_matrix_t *texgen = NULL; - - switch (operand->type) { - default: - case CAIRO_GL_OPERAND_COUNT: - ASSERT_NOT_REACHED; - case CAIRO_GL_OPERAND_NONE: - return; - - case CAIRO_GL_OPERAND_CONSTANT: - _cairo_gl_shader_bind_vec4 (ctx, - ctx->current_shader->constant_location[tex_unit], - operand->constant.color[0], - operand->constant.color[1], - operand->constant.color[2], - operand->constant.color[3]); - return; - - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT: - _cairo_gl_shader_bind_float (ctx, - ctx->current_shader->a_location[tex_unit], - operand->gradient.a); - /* fall through */ - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0: - _cairo_gl_shader_bind_vec3 (ctx, - ctx->current_shader->circle_d_location[tex_unit], - operand->gradient.circle_d.center.x, - operand->gradient.circle_d.center.y, - operand->gradient.circle_d.radius); - _cairo_gl_shader_bind_float (ctx, - ctx->current_shader->radius_0_location[tex_unit], - operand->gradient.radius_0); - /* fall through */ - case CAIRO_GL_OPERAND_LINEAR_GRADIENT: - case CAIRO_GL_OPERAND_TEXTURE: - /* - * For GLES2 we use shaders to implement GL_CLAMP_TO_BORDER (used - * with CAIRO_EXTEND_NONE). When bilinear filtering is enabled, - * these shaders need the texture dimensions for their calculations. - */ - if ((ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3 || - ctx->gl_flavor == CAIRO_GL_FLAVOR_ES2) && - _cairo_gl_operand_get_extend (operand) == CAIRO_EXTEND_NONE && - _cairo_gl_operand_get_gl_filter (operand) == GL_LINEAR) - { - float width, height; - if (operand->type == CAIRO_GL_OPERAND_TEXTURE) { - width = operand->texture.surface->width; - height = operand->texture.surface->height; - } - else { - width = operand->gradient.gradient->cache_entry.size, - height = 1; - } - _cairo_gl_shader_bind_vec2 (ctx, - ctx->current_shader->texdims_location[tex_unit], - width, height); - } - break; - } - - if (operand->type == CAIRO_GL_OPERAND_TEXTURE) { - if (operand->texture.texgen) - texgen = &operand->texture.attributes.matrix; - } else { - if (operand->gradient.texgen) - texgen = &operand->gradient.m; - } - if (texgen) { - _cairo_gl_shader_bind_matrix(ctx, - ctx->current_shader->texgen_location[tex_unit], - texgen); - } -} - - -cairo_bool_t -_cairo_gl_operand_needs_setup (cairo_gl_operand_t *dest, - cairo_gl_operand_t *source, - unsigned int vertex_offset) -{ - if (dest->type != source->type) - return TRUE; - if (dest->vertex_offset != vertex_offset) - return TRUE; - - switch (source->type) { - case CAIRO_GL_OPERAND_NONE: - return FALSE; - case CAIRO_GL_OPERAND_CONSTANT: - return dest->constant.color[0] != source->constant.color[0] || - dest->constant.color[1] != source->constant.color[1] || - dest->constant.color[2] != source->constant.color[2] || - dest->constant.color[3] != source->constant.color[3]; - case CAIRO_GL_OPERAND_TEXTURE: - return dest->texture.surface != source->texture.surface || - dest->texture.attributes.extend != source->texture.attributes.extend || - dest->texture.attributes.filter != source->texture.attributes.filter || - dest->texture.attributes.has_component_alpha != source->texture.attributes.has_component_alpha; - case CAIRO_GL_OPERAND_LINEAR_GRADIENT: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT: - /* XXX: improve this */ - return TRUE; - default: - case CAIRO_GL_OPERAND_COUNT: - ASSERT_NOT_REACHED; - break; - } - return TRUE; -} - -unsigned int -_cairo_gl_operand_get_vertex_size (const cairo_gl_operand_t *operand) -{ - switch (operand->type) { - default: - case CAIRO_GL_OPERAND_COUNT: - ASSERT_NOT_REACHED; - case CAIRO_GL_OPERAND_NONE: - case CAIRO_GL_OPERAND_CONSTANT: - return 0; - case CAIRO_GL_OPERAND_TEXTURE: - return operand->texture.texgen ? 0 : 2 * sizeof (GLfloat); - case CAIRO_GL_OPERAND_LINEAR_GRADIENT: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT: - return operand->gradient.texgen ? 0 : 2 * sizeof (GLfloat); - } -} - -void -_cairo_gl_operand_emit (cairo_gl_operand_t *operand, - GLfloat ** vb, - GLfloat x, - GLfloat y) -{ - switch (operand->type) { - default: - case CAIRO_GL_OPERAND_COUNT: - ASSERT_NOT_REACHED; - case CAIRO_GL_OPERAND_NONE: - case CAIRO_GL_OPERAND_CONSTANT: - break; - case CAIRO_GL_OPERAND_LINEAR_GRADIENT: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT: - if (! operand->gradient.texgen) { - double s = x; - double t = y; - - cairo_matrix_transform_point (&operand->gradient.m, &s, &t); - - *(*vb)++ = s; - *(*vb)++ = t; - } - break; - case CAIRO_GL_OPERAND_TEXTURE: - if (! operand->texture.texgen) { - cairo_surface_attributes_t *src_attributes = &operand->texture.attributes; - double s = x; - double t = y; - - cairo_matrix_transform_point (&src_attributes->matrix, &s, &t); - *(*vb)++ = s; - *(*vb)++ = t; - } - break; - } -} diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h deleted file mode 100644 index f02a58763..000000000 --- a/src/cairo-gl-private.h +++ /dev/null @@ -1,865 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2009 Eric Anholt - * Copyright © 2009 Chris Wilson - * Copyright © 2005,2010 Red Hat, Inc - * Copyright © 2011 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. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Red Hat, Inc. - * - * Contributor(s): - * Benjamin Otte <otte@gnome.org> - * Carl Worth <cworth@cworth.org> - * Chris Wilson <chris@chris-wilson.co.uk> - * Eric Anholt <eric@anholt.net> - * T. Zachary Laine <whatwasthataddress@gmail.com> - * Alexandros Frantzis <alexandros.frantzis@linaro.org> - */ - -#ifndef CAIRO_GL_PRIVATE_H -#define CAIRO_GL_PRIVATE_H - -#define GL_GLEXT_PROTOTYPES - -#include "cairoint.h" - -#include "cairo-gl.h" -#include "cairo-gl-gradient-private.h" - -#include "cairo-device-private.h" -#include "cairo-error-private.h" -#include "cairo-rtree-private.h" -#include "cairo-scaled-font-private.h" -#include "cairo-spans-compositor-private.h" -#include "cairo-array-private.h" - -#include <assert.h> - -#if CAIRO_HAS_GLESV3_SURFACE -#include <GLES3/gl3.h> -#include <GLES3/gl3ext.h> -#elif CAIRO_HAS_GLESV2_SURFACE -#include <GLES2/gl2.h> -#include <GLES2/gl2ext.h> -#elif CAIRO_HAS_GL_SURFACE -#include <GL/gl.h> -#include <GL/glext.h> -#endif - -#include "cairo-gl-ext-def-private.h" - -#define DEBUG_GL 0 - -#if DEBUG_GL && __GNUC__ -#define UNSUPPORTED(reason) ({ \ - fprintf (stderr, \ - "cairo-gl: hit unsupported operation in %s(), line %d: %s\n", \ - __FUNCTION__, __LINE__, reason); \ - CAIRO_INT_STATUS_UNSUPPORTED; \ -}) -#else -#define UNSUPPORTED(reason) CAIRO_INT_STATUS_UNSUPPORTED -#endif - -#define CAIRO_GL_VERSION_ENCODE(major, minor) ( \ - ((major) * 256) \ - + ((minor) * 1)) - -/* maximal number of shaders we keep in the cache. - * Random number that is hopefully big enough to not cause many cache evictions. */ -#define CAIRO_GL_MAX_SHADERS_PER_CONTEXT 64 - -/* VBO size that we allocate, smaller size means we gotta flush more often, - * but larger means hogging more memory and can cause trouble for drivers - * (especially on embedded devices). Use the CAIRO_GL_VBO_SIZE environment - * variable to set this to a different size. */ -#define CAIRO_GL_VBO_SIZE_DEFAULT (1024*1024) - -typedef struct _cairo_gl_surface cairo_gl_surface_t; - -/* GL flavor is the type of GL supported by the underlying platform. */ -typedef enum cairo_gl_flavor { - CAIRO_GL_FLAVOR_NONE = 0, - CAIRO_GL_FLAVOR_DESKTOP = 1, - CAIRO_GL_FLAVOR_ES2 = 2, - CAIRO_GL_FLAVOR_ES3 = 3 -} cairo_gl_flavor_t; - -/* Indices for vertex attributes used by BindAttribLocation, etc. */ -enum { - CAIRO_GL_VERTEX_ATTRIB_INDEX = 0, - CAIRO_GL_COLOR_ATTRIB_INDEX = 1, - CAIRO_GL_TEXCOORD0_ATTRIB_INDEX = 2, - CAIRO_GL_TEXCOORD1_ATTRIB_INDEX = CAIRO_GL_TEXCOORD0_ATTRIB_INDEX + 1 -}; - -typedef enum cairo_gl_operand_type { - CAIRO_GL_OPERAND_NONE, - CAIRO_GL_OPERAND_CONSTANT, - CAIRO_GL_OPERAND_TEXTURE, - CAIRO_GL_OPERAND_LINEAR_GRADIENT, - CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0, - CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE, - CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT, - - CAIRO_GL_OPERAND_COUNT -} cairo_gl_operand_type_t; - -/* This union structure describes a potential source or mask operand to the - * compositing equation. - */ -typedef struct cairo_gl_operand { - cairo_gl_operand_type_t type; - union { - struct { - GLuint tex; - cairo_gl_surface_t *surface; - cairo_gl_surface_t *owns_surface; - cairo_surface_attributes_t attributes; - int texgen; - } texture; - struct { - GLfloat color[4]; - } constant; - struct { - cairo_gl_gradient_t *gradient; - cairo_matrix_t m; - cairo_circle_double_t circle_d; - double radius_0, a; - cairo_extend_t extend; - int texgen; - } gradient; - }; - unsigned int vertex_offset; -} cairo_gl_operand_t; - -typedef struct cairo_gl_source { - cairo_surface_t base; - cairo_gl_operand_t operand; -} cairo_gl_source_t; - -struct _cairo_gl_surface { - cairo_surface_t base; - cairo_gl_operand_t operand; - - int width, height; - - GLuint tex; /* GL texture object containing our data. */ - GLuint fb; /* GL framebuffer object wrapping our data. */ - GLuint depth_stencil; /* GL renderbuffer object for holding stencil buffer clip. */ - -#if CAIRO_HAS_GL_SURFACE || CAIRO_HAS_GLESV3_SURFACE - GLuint msaa_rb; /* The ARB MSAA path uses a renderbuffer. */ - GLuint msaa_fb; -#endif - GLuint msaa_depth_stencil; - - cairo_bool_t stencil_and_msaa_caps_initialized; - cairo_bool_t supports_stencil; /* Stencil support for for non-texture surfaces. */ - cairo_bool_t supports_msaa; - GLint num_samples; - cairo_bool_t msaa_active; /* Whether the multisampling - framebuffer is active or not. */ - cairo_bool_t content_in_texture; /* whether we just uploaded image - to texture, used for certain - gles2 extensions and glesv3 */ - cairo_clip_t *clip_on_stencil_buffer; - - int owns_tex; - cairo_bool_t needs_update; - - cairo_region_t *clip_region; -}; - -typedef struct cairo_gl_glyph_cache { - cairo_rtree_t rtree; - cairo_gl_surface_t *surface; -} cairo_gl_glyph_cache_t; - -typedef enum cairo_gl_tex { - CAIRO_GL_TEX_SOURCE = 0, - CAIRO_GL_TEX_MASK = 1, - CAIRO_GL_TEX_TEMP = 2 -} cairo_gl_tex_t; - -typedef struct cairo_gl_shader { - GLuint fragment_shader; - GLuint program; - GLint mvp_location; - GLint constant_location[2]; - GLint a_location[2]; - GLint circle_d_location[2]; - GLint radius_0_location[2]; - GLint texdims_location[2]; - GLint texgen_location[2]; -} cairo_gl_shader_t; - -typedef enum cairo_gl_shader_in { - CAIRO_GL_SHADER_IN_NORMAL, - CAIRO_GL_SHADER_IN_CA_SOURCE, - CAIRO_GL_SHADER_IN_CA_SOURCE_ALPHA, - - CAIRO_GL_SHADER_IN_COUNT -} cairo_gl_shader_in_t; - -typedef enum cairo_gl_var_type { - CAIRO_GL_VAR_NONE, - CAIRO_GL_VAR_TEXCOORDS, - CAIRO_GL_VAR_TEXGEN, -} cairo_gl_var_type_t; - -typedef enum cairo_gl_primitive_type { - CAIRO_GL_PRIMITIVE_TYPE_TRIANGLES, - CAIRO_GL_PRIMITIVE_TYPE_TRISTRIPS -} cairo_gl_primitive_type_t; - -typedef void (*cairo_gl_emit_rect_t) (cairo_gl_context_t *ctx, - GLfloat x1, GLfloat y1, - GLfloat x2, GLfloat y2); - -typedef void (*cairo_gl_emit_span_t) (cairo_gl_context_t *ctx, - GLfloat x1, GLfloat y1, - GLfloat x2, GLfloat y2, - uint8_t alpha); - -typedef void (*cairo_gl_emit_glyph_t) (cairo_gl_context_t *ctx, - GLfloat x1, GLfloat y1, - GLfloat x2, GLfloat y2, - GLfloat glyph_x1, GLfloat glyph_y1, - GLfloat glyph_x2, GLfloat glyph_y2); - -#define cairo_gl_var_type_hash(src,mask,spans,dest) ((spans) << 5) | ((mask) << 3 | (src << 1) | (dest)) -#define CAIRO_GL_VAR_TYPE_MAX (1 << 6) - -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 (*UniformMatrix4fv) (GLint location, GLsizei count, - GLboolean transpose, const GLfloat *value); - void (*Uniform1i) (GLint location, GLint x); - - /* Attributes */ - void (*BindAttribLocation) (GLuint program, GLuint index, - const GLchar *name); - void (*VertexAttribPointer) (GLuint index, GLint size, GLenum type, - GLboolean normalized, GLsizei stride, - const GLvoid *pointer); - void (*EnableVertexAttribArray) (GLuint index); - void (*DisableVertexAttribArray) (GLuint index); - - /* 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); - void (*GenRenderbuffers) (GLsizei n, GLuint *renderbuffers); - void (*BindRenderbuffer) (GLenum target, GLuint renderbuffer); - void (*RenderbufferStorage) (GLenum target, GLenum internal_format, - GLsizei width, GLsizei height); - void (*FramebufferRenderbuffer) (GLenum target, GLenum attachment, - GLenum renderbuffer_ttarget, GLuint renderbuffer); - void (*DeleteRenderbuffers) (GLsizei n, GLuint *renderbuffers); - void (*BlitFramebuffer) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, - GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, - GLbitfield mask, GLenum filter); - void (*RenderbufferStorageMultisample) (GLenum target, GLsizei samples, - GLenum internalformat, - GLsizei width, GLsizei height); - void (*FramebufferTexture2DMultisample) (GLenum target, GLenum attachment, - GLenum textarget, GLuint texture, - GLint level, GLsizei samples); -} cairo_gl_dispatch_t; - -struct _cairo_gl_context { - cairo_device_t base; - - const cairo_compositor_t *compositor; - - GLuint texture_load_pbo; - GLint max_framebuffer_size; - GLint max_texture_size; - GLint max_textures; - GLenum tex_target; - - GLint num_samples; - cairo_bool_t supports_msaa; - char *vb; - - cairo_bool_t has_shader_support; - - GLuint vertex_shaders[CAIRO_GL_VAR_TYPE_MAX]; - cairo_gl_shader_t fill_rectangles_shader; - cairo_cache_t shaders; - - cairo_cache_t gradients; - - cairo_gl_glyph_cache_t glyph_cache[2]; - cairo_list_t fonts; - - cairo_gl_surface_t *current_target; - cairo_operator_t current_operator; - cairo_gl_shader_t *pre_shader; /* for component alpha */ - cairo_gl_shader_t *current_shader; - - cairo_gl_operand_t operands[2]; - cairo_bool_t spans; - - unsigned int vbo_size; - unsigned int vb_offset; - unsigned int vertex_size; - cairo_region_t *clip_region; - cairo_clip_t *clip; - - cairo_gl_primitive_type_t primitive_type; - cairo_array_t tristrip_indices; - - cairo_bool_t has_mesa_pack_invert; - cairo_gl_dispatch_t dispatch; - GLfloat modelviewprojection_matrix[16]; - cairo_gl_flavor_t gl_flavor; - cairo_bool_t has_map_buffer; - cairo_bool_t has_packed_depth_stencil; - cairo_bool_t has_npot_repeat; - cairo_bool_t can_read_bgra; - - cairo_bool_t thread_aware; - - void (*acquire) (void *ctx); - void (*release) (void *ctx); - - void (*make_current) (void *ctx, cairo_gl_surface_t *surface); - void (*swap_buffers)(void *ctx, cairo_gl_surface_t *surface); - void (*destroy) (void *ctx); -}; - -typedef struct _cairo_gl_composite { - cairo_gl_surface_t *dst; - cairo_operator_t op; - cairo_region_t *clip_region; - - cairo_gl_operand_t src; - cairo_gl_operand_t mask; - cairo_bool_t spans; - - cairo_clip_t *clip; - cairo_bool_t multisample; -} cairo_gl_composite_t; - -typedef struct _cairo_gl_font { - cairo_scaled_font_private_t base; - cairo_device_t *device; - cairo_list_t link; -} cairo_gl_font_t; - -static cairo_always_inline GLenum -_cairo_gl_get_error (void) -{ - GLenum err = glGetError(); - - if (unlikely (err)) - while (glGetError ()); - - return err; -} - -static inline cairo_device_t * -_cairo_gl_context_create_in_error (cairo_status_t status) -{ - return (cairo_device_t *) _cairo_device_create_in_error (status); -} - -cairo_private cairo_status_t -_cairo_gl_context_init (cairo_gl_context_t *ctx); - -cairo_private void -_cairo_gl_surface_init (cairo_device_t *device, - cairo_gl_surface_t *surface, - cairo_content_t content, - int width, int height); - -static cairo_always_inline cairo_bool_t cairo_warn -_cairo_gl_surface_is_texture (cairo_gl_surface_t *surface) -{ - return surface->tex != 0; -} - -cairo_private cairo_status_t -_cairo_gl_surface_draw_image (cairo_gl_surface_t *dst, - cairo_image_surface_t *src, - int src_x, int src_y, - int width, int height, - int dst_x, int dst_y, - cairo_bool_t force_flush); - -cairo_private cairo_int_status_t -_cairo_gl_surface_resolve_multisampling (cairo_gl_surface_t *surface); - -static cairo_always_inline cairo_bool_t -_cairo_gl_device_has_glsl (cairo_device_t *device) -{ - return ((cairo_gl_context_t *) device)->has_shader_support; -} - -static cairo_always_inline cairo_bool_t -_cairo_gl_device_requires_power_of_two_textures (cairo_device_t *device) -{ - return ((cairo_gl_context_t *) device)->tex_target == GL_TEXTURE_RECTANGLE; -} - -static cairo_always_inline cairo_status_t cairo_warn -_cairo_gl_context_acquire (cairo_device_t *device, - cairo_gl_context_t **ctx) -{ - cairo_status_t status; - - status = cairo_device_acquire (device); - if (unlikely (status)) - return status; - - /* clear potential previous GL errors */ - _cairo_gl_get_error (); - - *ctx = (cairo_gl_context_t *) device; - return CAIRO_STATUS_SUCCESS; -} - -static cairo_always_inline cairo_warn cairo_status_t -_cairo_gl_context_release (cairo_gl_context_t *ctx, cairo_status_t status) -{ - GLenum err; - - err = _cairo_gl_get_error (); - - if (unlikely (err)) { - cairo_status_t new_status; - new_status = _cairo_error (CAIRO_STATUS_DEVICE_ERROR); - if (status == CAIRO_STATUS_SUCCESS) - status = new_status; - } - - cairo_device_release (&(ctx)->base); - - return status; -} - -cairo_private void -_cairo_gl_context_set_destination (cairo_gl_context_t *ctx, - cairo_gl_surface_t *surface, - cairo_bool_t multisampling); - -cairo_private void -_cairo_gl_context_bind_framebuffer (cairo_gl_context_t *ctx, - cairo_gl_surface_t *surface, - cairo_bool_t multisampling); - -cairo_private cairo_gl_emit_rect_t -_cairo_gl_context_choose_emit_rect (cairo_gl_context_t *ctx); - -cairo_private void -_cairo_gl_context_emit_rect (cairo_gl_context_t *ctx, - GLfloat x1, GLfloat y1, - GLfloat x2, GLfloat y2); - -cairo_private cairo_gl_emit_span_t -_cairo_gl_context_choose_emit_span (cairo_gl_context_t *ctx); - -cairo_private cairo_gl_emit_glyph_t -_cairo_gl_context_choose_emit_glyph (cairo_gl_context_t *ctx); - -cairo_private void -_cairo_gl_context_activate (cairo_gl_context_t *ctx, - cairo_gl_tex_t tex_unit); - -cairo_private cairo_bool_t -_cairo_gl_operator_is_supported (cairo_operator_t op); - -cairo_private cairo_bool_t -_cairo_gl_ensure_stencil (cairo_gl_context_t *ctx, - cairo_gl_surface_t *surface); - -cairo_private cairo_status_t -_cairo_gl_composite_init (cairo_gl_composite_t *setup, - cairo_operator_t op, - cairo_gl_surface_t *dst, - cairo_bool_t has_component_alpha); - -cairo_private void -_cairo_gl_composite_fini (cairo_gl_composite_t *setup); - -cairo_private cairo_status_t -_cairo_gl_composite_set_operator (cairo_gl_composite_t *setup, - cairo_operator_t op, - cairo_bool_t assume_component_alpha); - -cairo_private void -_cairo_gl_composite_set_clip_region (cairo_gl_composite_t *setup, - cairo_region_t *clip_region); - -cairo_private void -_cairo_gl_composite_set_clip(cairo_gl_composite_t *setup, - cairo_clip_t *clip); - -cairo_private cairo_int_status_t -_cairo_gl_composite_set_source (cairo_gl_composite_t *setup, - const cairo_pattern_t *pattern, - const cairo_rectangle_int_t *sample, - const cairo_rectangle_int_t *extents, - cairo_bool_t use_texgen); - -cairo_private void -_cairo_gl_composite_set_solid_source (cairo_gl_composite_t *setup, - const cairo_color_t *color); - -cairo_private void -_cairo_gl_composite_set_source_operand (cairo_gl_composite_t *setup, - const cairo_gl_operand_t *source); - -cairo_private cairo_int_status_t -_cairo_gl_composite_set_mask (cairo_gl_composite_t *setup, - const cairo_pattern_t *pattern, - const cairo_rectangle_int_t *sample, - const cairo_rectangle_int_t *extents, - cairo_bool_t use_texgen); - -cairo_private void -_cairo_gl_composite_set_mask_operand (cairo_gl_composite_t *setup, - const cairo_gl_operand_t *mask); - -cairo_private void -_cairo_gl_composite_set_spans (cairo_gl_composite_t *setup); - -cairo_private void -_cairo_gl_composite_set_multisample (cairo_gl_composite_t *setup); - -cairo_private cairo_status_t -_cairo_gl_composite_begin (cairo_gl_composite_t *setup, - cairo_gl_context_t **ctx); - -cairo_private cairo_status_t -_cairo_gl_set_operands_and_operator (cairo_gl_composite_t *setup, - cairo_gl_context_t *ctx); - -cairo_private void -_cairo_gl_composite_flush (cairo_gl_context_t *ctx); - -cairo_private cairo_int_status_t -_cairo_gl_composite_emit_quad_as_tristrip (cairo_gl_context_t *ctx, - cairo_gl_composite_t *setup, - const cairo_point_t quad[4]); - -cairo_private cairo_int_status_t -_cairo_gl_composite_emit_triangle_as_tristrip (cairo_gl_context_t *ctx, - cairo_gl_composite_t *setup, - const cairo_point_t triangle[3]); - -cairo_private void -_cairo_gl_context_destroy_operand (cairo_gl_context_t *ctx, - cairo_gl_tex_t tex_unit); - -cairo_private cairo_bool_t -_cairo_gl_get_image_format_and_type (cairo_gl_flavor_t flavor, - pixman_format_code_t pixman_format, - GLenum *internal_format, GLenum *format, - GLenum *type, cairo_bool_t *has_alpha, - cairo_bool_t *needs_swap); - -cairo_private void -_cairo_gl_glyph_cache_init (cairo_gl_glyph_cache_t *cache); - -cairo_private void -_cairo_gl_glyph_cache_fini (cairo_gl_context_t *ctx, - cairo_gl_glyph_cache_t *cache); - -cairo_private cairo_int_status_t -_cairo_gl_surface_show_glyphs (void *abstract_dst, - cairo_operator_t op, - const cairo_pattern_t *source, - cairo_glyph_t *glyphs, - int num_glyphs, - cairo_scaled_font_t *scaled_font, - const cairo_clip_t *clip, - int *remaining_glyphs); - -cairo_private cairo_status_t -_cairo_gl_context_init_shaders (cairo_gl_context_t *ctx); - -cairo_private void -_cairo_gl_context_fini_shaders (cairo_gl_context_t *ctx); - -static cairo_always_inline cairo_bool_t -_cairo_gl_context_is_flushed (cairo_gl_context_t *ctx) -{ - return ctx->vb_offset == 0; -} - -cairo_private cairo_status_t -_cairo_gl_get_shader_by_type (cairo_gl_context_t *ctx, - cairo_gl_operand_t *source, - cairo_gl_operand_t *mask, - cairo_bool_t use_coverage, - cairo_gl_shader_in_t in, - cairo_gl_shader_t **shader); - -cairo_private void -_cairo_gl_shader_bind_float (cairo_gl_context_t *ctx, - GLint location, - float value); - -cairo_private void -_cairo_gl_shader_bind_vec2 (cairo_gl_context_t *ctx, - GLint location, - float value0, float value1); - -cairo_private void -_cairo_gl_shader_bind_vec3 (cairo_gl_context_t *ctx, - GLint location, - float value0, - float value1, - float value2); - -cairo_private void -_cairo_gl_shader_bind_vec4 (cairo_gl_context_t *ctx, - GLint location, - float value0, float value1, - float value2, float value3); - -cairo_private void -_cairo_gl_shader_bind_matrix (cairo_gl_context_t *ctx, - GLint location, - const cairo_matrix_t* m); - -cairo_private void -_cairo_gl_shader_bind_matrix4f (cairo_gl_context_t *ctx, - GLint location, - GLfloat* gl_m); - -cairo_private void -_cairo_gl_set_shader (cairo_gl_context_t *ctx, - cairo_gl_shader_t *shader); - -cairo_private void -_cairo_gl_shader_fini (cairo_gl_context_t *ctx, cairo_gl_shader_t *shader); - -cairo_private int -_cairo_gl_get_version (void); - -cairo_private cairo_gl_flavor_t -_cairo_gl_get_flavor (void); - -cairo_private unsigned long -_cairo_gl_get_vbo_size (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); - -cairo_private cairo_int_status_t -_cairo_gl_operand_init (cairo_gl_operand_t *operand, - const cairo_pattern_t *pattern, - cairo_gl_surface_t *dst, - const cairo_rectangle_int_t *sample, - const cairo_rectangle_int_t *extents, - cairo_bool_t use_texgen); - -cairo_private void -_cairo_gl_solid_operand_init (cairo_gl_operand_t *operand, - const cairo_color_t *color); - -cairo_private cairo_filter_t -_cairo_gl_operand_get_filter (cairo_gl_operand_t *operand); - -cairo_private GLint -_cairo_gl_operand_get_gl_filter (cairo_gl_operand_t *operand); - -cairo_private cairo_extend_t -_cairo_gl_operand_get_extend (cairo_gl_operand_t *operand); - -cairo_private unsigned int -_cairo_gl_operand_get_vertex_size (const cairo_gl_operand_t *operand); - -cairo_private cairo_bool_t -_cairo_gl_operand_needs_setup (cairo_gl_operand_t *dest, - cairo_gl_operand_t *source, - unsigned int vertex_offset); - -cairo_private void -_cairo_gl_operand_bind_to_shader (cairo_gl_context_t *ctx, - cairo_gl_operand_t *operand, - cairo_gl_tex_t tex_unit); - -cairo_private void -_cairo_gl_operand_emit (cairo_gl_operand_t *operand, - GLfloat ** vb, - GLfloat x, - GLfloat y); - -cairo_private void -_cairo_gl_operand_copy (cairo_gl_operand_t *dst, - const cairo_gl_operand_t *src); - -cairo_private void -_cairo_gl_operand_translate (cairo_gl_operand_t *operand, - double tx, double ty); - -cairo_private void -_cairo_gl_operand_destroy (cairo_gl_operand_t *operand); - -cairo_private const cairo_compositor_t * -_cairo_gl_msaa_compositor_get (void); - -cairo_private const cairo_compositor_t * -_cairo_gl_span_compositor_get (void); - -cairo_private const cairo_compositor_t * -_cairo_gl_traps_compositor_get (void); - -cairo_private cairo_int_status_t -_cairo_gl_check_composite_glyphs (const cairo_composite_rectangles_t *extents, - cairo_scaled_font_t *scaled_font, - cairo_glyph_t *glyphs, - int *num_glyphs); - -cairo_private cairo_int_status_t -_cairo_gl_composite_glyphs (void *_dst, - cairo_operator_t op, - cairo_surface_t *_src, - int src_x, - int src_y, - int dst_x, - int dst_y, - cairo_composite_glyphs_info_t *info); - -cairo_private cairo_int_status_t -_cairo_gl_composite_glyphs_with_clip (void *_dst, - cairo_operator_t op, - cairo_surface_t *_src, - int src_x, - int src_y, - int dst_x, - int dst_y, - cairo_composite_glyphs_info_t *info, - cairo_clip_t *clip); - -cairo_private void -_cairo_gl_ensure_framebuffer (cairo_gl_context_t *ctx, - cairo_gl_surface_t *surface); - -cairo_private cairo_surface_t * -_cairo_gl_surface_create_scratch (cairo_gl_context_t *ctx, - cairo_content_t content, - int width, - int height); - -cairo_private cairo_surface_t * -_cairo_gl_surface_create_scratch_for_caching (cairo_gl_context_t *ctx, - cairo_content_t content, - int width, - int height); - -cairo_private cairo_surface_t * -_cairo_gl_pattern_to_source (cairo_surface_t *dst, - const cairo_pattern_t *pattern, - cairo_bool_t is_mask, - const cairo_rectangle_int_t *extents, - const cairo_rectangle_int_t *sample, - int *src_x, int *src_y); - -cairo_private cairo_int_status_t -_cairo_gl_msaa_compositor_draw_clip (cairo_gl_context_t *ctx, - cairo_gl_composite_t *setup, - cairo_clip_t *clip); - -cairo_private cairo_surface_t * -_cairo_gl_white_source (void); - -cairo_private void -_cairo_gl_scissor_to_rectangle (cairo_gl_surface_t *surface, - const cairo_rectangle_int_t *r); - -static inline cairo_gl_operand_t * -source_to_operand (cairo_surface_t *surface) -{ - cairo_gl_source_t *source = (cairo_gl_source_t *)surface; - return source ? &source->operand : NULL; -} - -static inline void -_cairo_gl_glyph_cache_unlock (cairo_gl_glyph_cache_t *cache) -{ - _cairo_rtree_unpin (&cache->rtree); -} - - -slim_hidden_proto (cairo_gl_surface_create); -slim_hidden_proto (cairo_gl_surface_create_for_texture); - -#endif /* CAIRO_GL_PRIVATE_H */ diff --git a/src/cairo-gl-shaders.c b/src/cairo-gl-shaders.c deleted file mode 100644 index b70c177f2..000000000 --- a/src/cairo-gl-shaders.c +++ /dev/null @@ -1,1111 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2009 T. Zachary Laine - * Copyright © 2010 Eric Anholt - * Copyright © 2010 Red Hat, Inc - * 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. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is T. Zachary Laine. - * - * Contributor(s): - * Benjamin Otte <otte@gnome.org> - * Eric Anholt <eric@anholt.net> - * T. Zachary Laine <whatwasthataddress@gmail.com> - * Alexandros Frantzis <alexandros.frantzis@linaro.org> - * H. Lewin <heiko.lewin@gmx.de> - */ - -#include "cairoint.h" -#include "cairo-gl-private.h" -#include "cairo-error-private.h" -#include "cairo-output-stream-private.h" - -static cairo_status_t -_cairo_gl_shader_compile_and_link (cairo_gl_context_t *ctx, - cairo_gl_shader_t *shader, - cairo_gl_var_type_t src, - cairo_gl_var_type_t mask, - cairo_bool_t use_coverage, - const char *fragment_text); - -typedef struct _cairo_shader_cache_entry { - cairo_cache_entry_t base; - - unsigned vertex; - - cairo_gl_operand_type_t src; - cairo_gl_operand_type_t mask; - cairo_gl_operand_type_t dest; - cairo_bool_t use_coverage; - - cairo_gl_shader_in_t in; - GLint src_gl_filter; - cairo_bool_t src_border_fade; - cairo_extend_t src_extend; - GLint mask_gl_filter; - cairo_bool_t mask_border_fade; - cairo_extend_t mask_extend; - - cairo_gl_context_t *ctx; /* XXX: needed to destroy the program */ - cairo_gl_shader_t shader; -} cairo_shader_cache_entry_t; - -static cairo_bool_t -_cairo_gl_shader_cache_equal_desktop (const void *key_a, const void *key_b) -{ - const cairo_shader_cache_entry_t *a = key_a; - const cairo_shader_cache_entry_t *b = key_b; - cairo_bool_t both_have_npot_repeat = - a->ctx->has_npot_repeat && b->ctx->has_npot_repeat; - - return (a->vertex == b->vertex && - a->src == b->src && - a->mask == b->mask && - a->dest == b->dest && - a->use_coverage == b->use_coverage && - a->in == b->in && - (both_have_npot_repeat || a->src_extend == b->src_extend) && - (both_have_npot_repeat || a->mask_extend == b->mask_extend)); -} - -/* - * For GLES2 we use more complicated shaders to implement missing GL - * features. In this case we need more parameters to uniquely identify - * a shader (vs _cairo_gl_shader_cache_equal_desktop()). - */ -static cairo_bool_t -_cairo_gl_shader_cache_equal_gles2 (const void *key_a, const void *key_b) -{ - const cairo_shader_cache_entry_t *a = key_a; - const cairo_shader_cache_entry_t *b = key_b; - cairo_bool_t both_have_npot_repeat = - a->ctx->has_npot_repeat && b->ctx->has_npot_repeat; - - return (a->vertex == b->vertex && - a->src == b->src && - a->mask == b->mask && - a->dest == b->dest && - a->use_coverage == b->use_coverage && - a->in == b->in && - a->src_gl_filter == b->src_gl_filter && - a->src_border_fade == b->src_border_fade && - (both_have_npot_repeat || a->src_extend == b->src_extend) && - a->mask_gl_filter == b->mask_gl_filter && - a->mask_border_fade == b->mask_border_fade && - (both_have_npot_repeat || a->mask_extend == b->mask_extend)); -} - -static unsigned long -_cairo_gl_shader_cache_hash (const cairo_shader_cache_entry_t *entry) -{ - return (((uint32_t)entry->src << 24) | (entry->mask << 16) | (entry->dest << 8) | (entry->in << 1) | entry->use_coverage) ^ entry->vertex; -} - -static void -_cairo_gl_shader_cache_destroy (void *data) -{ - cairo_shader_cache_entry_t *entry = data; - - _cairo_gl_shader_fini (entry->ctx, &entry->shader); - if (entry->ctx->current_shader == &entry->shader) - entry->ctx->current_shader = NULL; - free (entry); -} - -static void -_cairo_gl_shader_init (cairo_gl_shader_t *shader) -{ - shader->fragment_shader = 0; - shader->program = 0; -} - -cairo_status_t -_cairo_gl_context_init_shaders (cairo_gl_context_t *ctx) -{ - static const char *fill_fs_source = - "#ifdef GL_ES\n" - "precision mediump float;\n" - "#endif\n" - "uniform vec4 color;\n" - "void main()\n" - "{\n" - " gl_FragColor = color;\n" - "}\n"; - cairo_status_t status; - - if (_cairo_gl_get_version () >= CAIRO_GL_VERSION_ENCODE (2, 0) || - (_cairo_gl_has_extension ("GL_ARB_shader_objects") && - _cairo_gl_has_extension ("GL_ARB_fragment_shader") && - _cairo_gl_has_extension ("GL_ARB_vertex_shader"))) { - ctx->has_shader_support = TRUE; - } else { - ctx->has_shader_support = FALSE; - fprintf (stderr, "Error: The cairo gl backend requires shader support!\n"); - return CAIRO_STATUS_DEVICE_ERROR; - } - - memset (ctx->vertex_shaders, 0, sizeof (ctx->vertex_shaders)); - - status = _cairo_cache_init (&ctx->shaders, - ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP ? - _cairo_gl_shader_cache_equal_desktop : - _cairo_gl_shader_cache_equal_gles2, - NULL, - _cairo_gl_shader_cache_destroy, - CAIRO_GL_MAX_SHADERS_PER_CONTEXT); - if (unlikely (status)) - return status; - - _cairo_gl_shader_init (&ctx->fill_rectangles_shader); - status = _cairo_gl_shader_compile_and_link (ctx, - &ctx->fill_rectangles_shader, - CAIRO_GL_VAR_NONE, - CAIRO_GL_VAR_NONE, - FALSE, - fill_fs_source); - if (unlikely (status)) - return status; - - return CAIRO_STATUS_SUCCESS; -} - -void -_cairo_gl_context_fini_shaders (cairo_gl_context_t *ctx) -{ - int i; - - for (i = 0; i < CAIRO_GL_VAR_TYPE_MAX; i++) { - if (ctx->vertex_shaders[i]) - ctx->dispatch.DeleteShader (ctx->vertex_shaders[i]); - } - - _cairo_gl_shader_fini(ctx, &ctx->fill_rectangles_shader); - _cairo_cache_fini (&ctx->shaders); -} - -void -_cairo_gl_shader_fini (cairo_gl_context_t *ctx, - cairo_gl_shader_t *shader) -{ - if (shader->fragment_shader) - ctx->dispatch.DeleteShader (shader->fragment_shader); - - if (shader->program) - ctx->dispatch.DeleteProgram (shader->program); -} - -static const char *operand_names[] = { "source", "mask", "dest" }; - -static cairo_gl_var_type_t -cairo_gl_operand_get_var_type (cairo_gl_operand_t *operand) -{ - switch (operand->type) { - default: - case CAIRO_GL_OPERAND_COUNT: - ASSERT_NOT_REACHED; - case CAIRO_GL_OPERAND_NONE: - case CAIRO_GL_OPERAND_CONSTANT: - return CAIRO_GL_VAR_NONE; - case CAIRO_GL_OPERAND_LINEAR_GRADIENT: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE: - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT: - return operand->gradient.texgen ? CAIRO_GL_VAR_TEXGEN : CAIRO_GL_VAR_TEXCOORDS; - case CAIRO_GL_OPERAND_TEXTURE: - return operand->texture.texgen ? CAIRO_GL_VAR_TEXGEN : CAIRO_GL_VAR_TEXCOORDS; - } -} - -static void -cairo_gl_shader_emit_variable (cairo_output_stream_t *stream, - cairo_gl_var_type_t type, - cairo_gl_tex_t name) -{ - switch (type) { - default: - ASSERT_NOT_REACHED; - case CAIRO_GL_VAR_NONE: - break; - case CAIRO_GL_VAR_TEXCOORDS: - _cairo_output_stream_printf (stream, - "attribute vec4 MultiTexCoord%d;\n" - "varying vec2 %s_texcoords;\n", - name, - operand_names[name]); - break; - case CAIRO_GL_VAR_TEXGEN: - _cairo_output_stream_printf (stream, - "uniform mat3 %s_texgen;\n" - "varying vec2 %s_texcoords;\n", - operand_names[name], - operand_names[name]); - break; - } -} - -static void -cairo_gl_shader_emit_vertex (cairo_output_stream_t *stream, - cairo_gl_var_type_t type, - cairo_gl_tex_t name) -{ - switch (type) { - default: - ASSERT_NOT_REACHED; - case CAIRO_GL_VAR_NONE: - break; - case CAIRO_GL_VAR_TEXCOORDS: - _cairo_output_stream_printf (stream, - " %s_texcoords = MultiTexCoord%d.xy;\n", - operand_names[name], name); - break; - - case CAIRO_GL_VAR_TEXGEN: - _cairo_output_stream_printf (stream, - " %s_texcoords = (%s_texgen * Vertex.xyw).xy;\n", - operand_names[name], operand_names[name]); - break; - } -} - -static void -cairo_gl_shader_dcl_coverage (cairo_output_stream_t *stream) -{ - _cairo_output_stream_printf (stream, "varying float coverage;\n"); -} - -static void -cairo_gl_shader_def_coverage (cairo_output_stream_t *stream) -{ - _cairo_output_stream_printf (stream, " coverage = Color.a;\n"); -} - -static cairo_status_t -cairo_gl_shader_get_vertex_source (cairo_gl_var_type_t src, - cairo_gl_var_type_t mask, - cairo_bool_t use_coverage, - cairo_gl_var_type_t dest, - char **out) -{ - cairo_output_stream_t *stream = _cairo_memory_stream_create (); - unsigned char *source; - unsigned long length; - cairo_status_t status; - - cairo_gl_shader_emit_variable (stream, src, CAIRO_GL_TEX_SOURCE); - cairo_gl_shader_emit_variable (stream, mask, CAIRO_GL_TEX_MASK); - if (use_coverage) - cairo_gl_shader_dcl_coverage (stream); - - _cairo_output_stream_printf (stream, - "attribute vec4 Vertex;\n" - "attribute vec4 Color;\n" - "uniform mat4 ModelViewProjectionMatrix;\n" - "void main()\n" - "{\n" - " gl_Position = ModelViewProjectionMatrix * Vertex;\n"); - - cairo_gl_shader_emit_vertex (stream, src, CAIRO_GL_TEX_SOURCE); - cairo_gl_shader_emit_vertex (stream, mask, CAIRO_GL_TEX_MASK); - if (use_coverage) - cairo_gl_shader_def_coverage (stream); - - _cairo_output_stream_write (stream, - "}\n\0", 3); - - status = _cairo_memory_stream_destroy (stream, &source, &length); - if (unlikely (status)) - return status; - - *out = (char *) source; - return CAIRO_STATUS_SUCCESS; -} - -/* - * Returns whether an operand needs a special border fade fragment shader - * to simulate the GL_CLAMP_TO_BORDER wrapping method that is missing in GLES2. - */ -static cairo_bool_t -_cairo_gl_shader_needs_border_fade (cairo_gl_operand_t *operand) -{ - cairo_extend_t extend =_cairo_gl_operand_get_extend (operand); - - return extend == CAIRO_EXTEND_NONE && - (operand->type == CAIRO_GL_OPERAND_TEXTURE || - operand->type == CAIRO_GL_OPERAND_LINEAR_GRADIENT || - operand->type == CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE || - operand->type == CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0); -} - -static void -cairo_gl_shader_emit_color (cairo_output_stream_t *stream, - cairo_gl_context_t *ctx, - cairo_gl_operand_t *op, - cairo_gl_tex_t name) -{ - const char *namestr = operand_names[name]; - const char *rectstr = (ctx->tex_target == GL_TEXTURE_RECTANGLE ? "Rect" : ""); - - switch (op->type) { - case CAIRO_GL_OPERAND_COUNT: - default: - ASSERT_NOT_REACHED; - break; - case CAIRO_GL_OPERAND_NONE: - _cairo_output_stream_printf (stream, - "vec4 get_%s()\n" - "{\n" - " return vec4 (0, 0, 0, 1);\n" - "}\n", - namestr); - break; - case CAIRO_GL_OPERAND_CONSTANT: - _cairo_output_stream_printf (stream, - "uniform vec4 %s_constant;\n" - "vec4 get_%s()\n" - "{\n" - " return %s_constant;\n" - "}\n", - namestr, namestr, namestr); - break; - case CAIRO_GL_OPERAND_TEXTURE: - _cairo_output_stream_printf (stream, - "uniform sampler2D%s %s_sampler;\n" - "uniform vec2 %s_texdims;\n" - "varying vec2 %s_texcoords;\n" - "vec4 get_%s()\n" - "{\n", - rectstr, namestr, namestr, namestr, namestr); - if ((ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3 || - ctx->gl_flavor == CAIRO_GL_FLAVOR_ES2) && - _cairo_gl_shader_needs_border_fade (op)) - { - _cairo_output_stream_printf (stream, - " vec2 border_fade = %s_border_fade (%s_texcoords, %s_texdims);\n" - " vec4 texel = texture2D%s (%s_sampler, %s_texcoords);\n" - " return texel * border_fade.x * border_fade.y;\n" - "}\n", - namestr, namestr, namestr, rectstr, namestr, namestr); - } - else - { - _cairo_output_stream_printf (stream, - " return texture2D%s (%s_sampler, %s_wrap (%s_texcoords));\n" - "}\n", - rectstr, namestr, namestr, namestr); - } - break; - case CAIRO_GL_OPERAND_LINEAR_GRADIENT: - _cairo_output_stream_printf (stream, - "varying vec2 %s_texcoords;\n" - "uniform vec2 %s_texdims;\n" - "uniform sampler2D%s %s_sampler;\n" - "\n" - "vec4 get_%s()\n" - "{\n", - namestr, namestr, rectstr, namestr, namestr); - if ((ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3 || - ctx->gl_flavor == CAIRO_GL_FLAVOR_ES2) && - _cairo_gl_shader_needs_border_fade (op)) - { - _cairo_output_stream_printf (stream, - " float border_fade = %s_border_fade (%s_texcoords.x, %s_texdims.x);\n" - " vec4 texel = texture2D%s (%s_sampler, vec2 (%s_texcoords.x, 0.5));\n" - " return texel * border_fade;\n" - "}\n", - namestr, namestr, namestr, rectstr, namestr, namestr); - } - else - { - _cairo_output_stream_printf (stream, - " return texture2D%s (%s_sampler, %s_wrap (vec2 (%s_texcoords.x, 0.5)));\n" - "}\n", - rectstr, namestr, namestr, namestr); - } - break; - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0: - _cairo_output_stream_printf (stream, - "varying vec2 %s_texcoords;\n" - "uniform vec2 %s_texdims;\n" - "uniform sampler2D%s %s_sampler;\n" - "uniform vec3 %s_circle_d;\n" - "uniform float %s_radius_0;\n" - "\n" - "vec4 get_%s()\n" - "{\n" - " vec3 pos = vec3 (%s_texcoords, %s_radius_0);\n" - " \n" - " float B = dot (pos, %s_circle_d);\n" - " float C = dot (pos, vec3 (pos.xy, -pos.z));\n" - " \n" - " float t = 0.5 * C / B;\n" - " float is_valid = step (-%s_radius_0, t * %s_circle_d.z);\n", - namestr, namestr, rectstr, namestr, namestr, namestr, namestr, - namestr, namestr, namestr, namestr, namestr); - if ((ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3 || - ctx->gl_flavor == CAIRO_GL_FLAVOR_ES2) && - _cairo_gl_shader_needs_border_fade (op)) - { - _cairo_output_stream_printf (stream, - " float border_fade = %s_border_fade (t, %s_texdims.x);\n" - " vec4 texel = texture2D%s (%s_sampler, vec2 (t, 0.5));\n" - " return mix (vec4 (0.0), texel * border_fade, is_valid);\n" - "}\n", - namestr, namestr, rectstr, namestr); - } - else - { - _cairo_output_stream_printf (stream, - " vec4 texel = texture2D%s (%s_sampler, %s_wrap (vec2 (t, 0.5)));\n" - " return mix (vec4 (0.0), texel, is_valid);\n" - "}\n", - rectstr, namestr, namestr); - } - break; - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE: - _cairo_output_stream_printf (stream, - "varying vec2 %s_texcoords;\n" - "uniform vec2 %s_texdims;\n" - "uniform sampler2D%s %s_sampler;\n" - "uniform vec3 %s_circle_d;\n" - "uniform float %s_a;\n" - "uniform float %s_radius_0;\n" - "\n" - "vec4 get_%s()\n" - "{\n" - " vec3 pos = vec3 (%s_texcoords, %s_radius_0);\n" - " \n" - " float B = dot (pos, %s_circle_d);\n" - " float C = dot (pos, vec3 (pos.xy, -pos.z));\n" - " \n" - " float det = dot (vec2 (B, %s_a), vec2 (B, -C));\n" - " float sqrtdet = sqrt (abs (det));\n" - " vec2 t = (B + vec2 (sqrtdet, -sqrtdet)) / %s_a;\n" - " \n" - " vec2 is_valid = step (vec2 (0.0), t) * step (t, vec2(1.0));\n" - " float has_color = step (0., det) * max (is_valid.x, is_valid.y);\n" - " \n" - " float upper_t = mix (t.y, t.x, is_valid.x);\n", - namestr, namestr, rectstr, namestr, namestr, namestr, namestr, - namestr, namestr, namestr, namestr, namestr, namestr); - if ((ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3 || - ctx->gl_flavor == CAIRO_GL_FLAVOR_ES2) && - _cairo_gl_shader_needs_border_fade (op)) - { - _cairo_output_stream_printf (stream, - " float border_fade = %s_border_fade (upper_t, %s_texdims.x);\n" - " vec4 texel = texture2D%s (%s_sampler, vec2 (upper_t, 0.5));\n" - " return mix (vec4 (0.0), texel * border_fade, has_color);\n" - "}\n", - namestr, namestr, rectstr, namestr); - } - else - { - _cairo_output_stream_printf (stream, - " vec4 texel = texture2D%s (%s_sampler, %s_wrap (vec2(upper_t, 0.5)));\n" - " return mix (vec4 (0.0), texel, has_color);\n" - "}\n", - rectstr, namestr, namestr); - } - break; - case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT: - _cairo_output_stream_printf (stream, - "varying vec2 %s_texcoords;\n" - "uniform sampler2D%s %s_sampler;\n" - "uniform vec3 %s_circle_d;\n" - "uniform float %s_a;\n" - "uniform float %s_radius_0;\n" - "\n" - "vec4 get_%s()\n" - "{\n" - " vec3 pos = vec3 (%s_texcoords, %s_radius_0);\n" - " \n" - " float B = dot (pos, %s_circle_d);\n" - " float C = dot (pos, vec3 (pos.xy, -pos.z));\n" - " \n" - " float det = dot (vec2 (B, %s_a), vec2 (B, -C));\n" - " float sqrtdet = sqrt (abs (det));\n" - " vec2 t = (B + vec2 (sqrtdet, -sqrtdet)) / %s_a;\n" - " \n" - " vec2 is_valid = step (vec2 (-%s_radius_0), t * %s_circle_d.z);\n" - " float has_color = step (0., det) * max (is_valid.x, is_valid.y);\n" - " \n" - " float upper_t = mix (t.y, t.x, is_valid.x);\n" - " vec4 texel = texture2D%s (%s_sampler, %s_wrap (vec2(upper_t, 0.5)));\n" - " return mix (vec4 (0.0), texel, has_color);\n" - "}\n", - namestr, rectstr, namestr, namestr, namestr, namestr, - namestr, namestr, namestr, namestr, namestr, - namestr, namestr, namestr, rectstr, namestr, namestr); - break; - } -} - -/* - * Emits the border fade functions used by an operand. - * - * If bilinear filtering is used, the emitted function performs a linear - * fade to transparency effect in the intervals [-1/2n, 1/2n] and - * [1 - 1/2n, 1 + 1/2n] (n: texture size). - * - * If nearest filtering is used, the emitted function just returns - * 0.0 for all values outside [0, 1). - */ -static void -_cairo_gl_shader_emit_border_fade (cairo_output_stream_t *stream, - cairo_gl_operand_t *operand, - cairo_gl_tex_t name) -{ - const char *namestr = operand_names[name]; - GLint gl_filter = _cairo_gl_operand_get_gl_filter (operand); - - /* 2D version */ - _cairo_output_stream_printf (stream, - "vec2 %s_border_fade (vec2 coords, vec2 dims)\n" - "{\n", - namestr); - - if (gl_filter == GL_LINEAR) - _cairo_output_stream_printf (stream, - " return clamp(-abs(dims * (coords - 0.5)) + (dims + vec2(1.0)) * 0.5, 0.0, 1.0);\n"); - else - _cairo_output_stream_printf (stream, - " bvec2 in_tex1 = greaterThanEqual (coords, vec2 (0.0));\n" - " bvec2 in_tex2 = lessThan (coords, vec2 (1.0));\n" - " return vec2 (float (all (in_tex1) && all (in_tex2)));\n"); - - _cairo_output_stream_printf (stream, "}\n"); - - /* 1D version */ - _cairo_output_stream_printf (stream, - "float %s_border_fade (float x, float dim)\n" - "{\n", - namestr); - if (gl_filter == GL_LINEAR) - _cairo_output_stream_printf (stream, - " return clamp(-abs(dim * (x - 0.5)) + (dim + 1.0) * 0.5, 0.0, 1.0);\n"); - else - _cairo_output_stream_printf (stream, - " bool in_tex = x >= 0.0 && x < 1.0;\n" - " return float (in_tex);\n"); - - _cairo_output_stream_printf (stream, "}\n"); -} - -/* - * Emits the wrap function used by an operand. - * - * In OpenGL ES 2.0, repeat wrap modes (GL_REPEAT and GL_MIRRORED REPEAT) are - * only available for NPOT textures if the GL_OES_texture_npot is supported. - * If GL_OES_texture_npot is not supported, we need to implement the wrapping - * functionality in the shader. - */ -static void -_cairo_gl_shader_emit_wrap (cairo_gl_context_t *ctx, - cairo_output_stream_t *stream, - cairo_gl_operand_t *operand, - cairo_gl_tex_t name) -{ - const char *namestr = operand_names[name]; - cairo_extend_t extend = _cairo_gl_operand_get_extend (operand); - - _cairo_output_stream_printf (stream, - "vec2 %s_wrap(vec2 coords)\n" - "{\n", - namestr); - - if (! ctx->has_npot_repeat && - (extend == CAIRO_EXTEND_REPEAT || extend == CAIRO_EXTEND_REFLECT)) - { - if (extend == CAIRO_EXTEND_REPEAT) { - _cairo_output_stream_printf (stream, - " return fract(coords);\n"); - } else { /* CAIRO_EXTEND_REFLECT */ - _cairo_output_stream_printf (stream, - " return mix(fract(coords), 1.0 - fract(coords), floor(mod(coords, 2.0)));\n"); - } - } - else - { - _cairo_output_stream_printf (stream, " return coords;\n"); - } - - _cairo_output_stream_printf (stream, "}\n"); -} - -static cairo_status_t -cairo_gl_shader_get_fragment_source (cairo_gl_context_t *ctx, - cairo_gl_shader_in_t in, - cairo_gl_operand_t *src, - cairo_gl_operand_t *mask, - cairo_bool_t use_coverage, - cairo_gl_operand_type_t dest_type, - char **out) -{ - cairo_output_stream_t *stream = _cairo_memory_stream_create (); - unsigned char *source; - unsigned long length; - cairo_status_t status; - const char *coverage_str; - - _cairo_output_stream_printf (stream, - "#ifdef GL_ES\n" - "precision mediump float;\n" - "#endif\n"); - - _cairo_gl_shader_emit_wrap (ctx, stream, src, CAIRO_GL_TEX_SOURCE); - _cairo_gl_shader_emit_wrap (ctx, stream, mask, CAIRO_GL_TEX_MASK); - - if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3 || - ctx->gl_flavor == CAIRO_GL_FLAVOR_ES2) { - if (_cairo_gl_shader_needs_border_fade (src)) - _cairo_gl_shader_emit_border_fade (stream, src, CAIRO_GL_TEX_SOURCE); - if (_cairo_gl_shader_needs_border_fade (mask)) - _cairo_gl_shader_emit_border_fade (stream, mask, CAIRO_GL_TEX_MASK); - } - - cairo_gl_shader_emit_color (stream, ctx, src, CAIRO_GL_TEX_SOURCE); - cairo_gl_shader_emit_color (stream, ctx, mask, CAIRO_GL_TEX_MASK); - - coverage_str = ""; - if (use_coverage) { - _cairo_output_stream_printf (stream, "varying float coverage;\n"); - coverage_str = " * coverage"; - } - - _cairo_output_stream_printf (stream, - "void main()\n" - "{\n"); - switch (in) { - case CAIRO_GL_SHADER_IN_COUNT: - default: - ASSERT_NOT_REACHED; - case CAIRO_GL_SHADER_IN_NORMAL: - _cairo_output_stream_printf (stream, - " gl_FragColor = get_source() * get_mask().a%s;\n", - coverage_str); - break; - case CAIRO_GL_SHADER_IN_CA_SOURCE: - _cairo_output_stream_printf (stream, - " gl_FragColor = get_source() * get_mask()%s;\n", - coverage_str); - break; - case CAIRO_GL_SHADER_IN_CA_SOURCE_ALPHA: - _cairo_output_stream_printf (stream, - " gl_FragColor = get_source().a * get_mask()%s;\n", - coverage_str); - break; - } - - _cairo_output_stream_write (stream, - "}\n\0", 3); - - status = _cairo_memory_stream_destroy (stream, &source, &length); - if (unlikely (status)) - return status; - - *out = (char *) source; - return CAIRO_STATUS_SUCCESS; -} - -static void -compile_shader (cairo_gl_context_t *ctx, - GLuint *shader, - GLenum type, - const char *source) -{ - cairo_gl_dispatch_t *dispatch = &ctx->dispatch; - GLint success, log_size, num_chars; - char *log; - - *shader = dispatch->CreateShader (type); - dispatch->ShaderSource (*shader, 1, &source, 0); - dispatch->CompileShader (*shader); - dispatch->GetShaderiv (*shader, GL_COMPILE_STATUS, &success); - - if (success) - return; - - dispatch->GetShaderiv (*shader, GL_INFO_LOG_LENGTH, &log_size); - if (log_size < 0) { - printf ("OpenGL shader compilation failed.\n"); - ASSERT_NOT_REACHED; - return; - } - - log = _cairo_malloc (log_size + 1); - dispatch->GetShaderInfoLog (*shader, log_size, &num_chars, log); - log[num_chars] = '\0'; - - printf ("OpenGL shader compilation failed. Shader:\n%s\n", source); - printf ("OpenGL compilation log:\n%s\n", log); - - free (log); - ASSERT_NOT_REACHED; -} - -static void -link_shader_program (cairo_gl_context_t *ctx, - GLuint *program, - GLuint vert, - GLuint frag) -{ - cairo_gl_dispatch_t *dispatch = &ctx->dispatch; - GLint success, log_size, num_chars; - char *log; - - *program = dispatch->CreateProgram (); - dispatch->AttachShader (*program, vert); - dispatch->AttachShader (*program, frag); - - dispatch->BindAttribLocation (*program, CAIRO_GL_VERTEX_ATTRIB_INDEX, - "Vertex"); - dispatch->BindAttribLocation (*program, CAIRO_GL_COLOR_ATTRIB_INDEX, - "Color"); - dispatch->BindAttribLocation (*program, CAIRO_GL_TEXCOORD0_ATTRIB_INDEX, - "MultiTexCoord0"); - dispatch->BindAttribLocation (*program, CAIRO_GL_TEXCOORD1_ATTRIB_INDEX, - "MultiTexCoord1"); - - dispatch->LinkProgram (*program); - dispatch->GetProgramiv (*program, GL_LINK_STATUS, &success); - if (success) - return; - - dispatch->GetProgramiv (*program, GL_INFO_LOG_LENGTH, &log_size); - if (log_size < 0) { - printf ("OpenGL shader link failed.\n"); - ASSERT_NOT_REACHED; - return; - } - - log = _cairo_malloc (log_size + 1); - dispatch->GetProgramInfoLog (*program, log_size, &num_chars, log); - log[num_chars] = '\0'; - - printf ("OpenGL shader link failed:\n%s\n", log); - free (log); - ASSERT_NOT_REACHED; -} - -static GLint -_cairo_gl_get_op_uniform_location(cairo_gl_context_t *ctx, - cairo_gl_shader_t *shader, - cairo_gl_tex_t tex_unit, - const char *suffix) -{ - cairo_gl_dispatch_t *dispatch = &ctx->dispatch; - char uniform_name[100]; - const char *unit_name[2] = { "source", "mask" }; - - snprintf (uniform_name, sizeof (uniform_name), "%s_%s", - unit_name[tex_unit], suffix); - - return dispatch->GetUniformLocation (shader->program, uniform_name); -} - -static cairo_status_t -_cairo_gl_shader_compile_and_link (cairo_gl_context_t *ctx, - cairo_gl_shader_t *shader, - cairo_gl_var_type_t src, - cairo_gl_var_type_t mask, - cairo_bool_t use_coverage, - const char *fragment_text) -{ - cairo_gl_dispatch_t *dispatch = &ctx->dispatch; - unsigned int vertex_shader; - cairo_status_t status; - int i; - - assert (shader->program == 0); - - vertex_shader = cairo_gl_var_type_hash (src, mask, use_coverage, - CAIRO_GL_VAR_NONE); - if (ctx->vertex_shaders[vertex_shader] == 0) { - char *source; - - status = cairo_gl_shader_get_vertex_source (src, - mask, - use_coverage, - CAIRO_GL_VAR_NONE, - &source); - if (unlikely (status)) - goto FAILURE; - - compile_shader (ctx, &ctx->vertex_shaders[vertex_shader], - GL_VERTEX_SHADER, source); - free (source); - } - - compile_shader (ctx, &shader->fragment_shader, - GL_FRAGMENT_SHADER, fragment_text); - - link_shader_program (ctx, &shader->program, - ctx->vertex_shaders[vertex_shader], - shader->fragment_shader); - - shader->mvp_location = - dispatch->GetUniformLocation (shader->program, - "ModelViewProjectionMatrix"); - - for (i = 0; i < 2; i++) { - shader->constant_location[i] = - _cairo_gl_get_op_uniform_location (ctx, shader, i, "constant"); - shader->a_location[i] = - _cairo_gl_get_op_uniform_location (ctx, shader, i, "a"); - shader->circle_d_location[i] = - _cairo_gl_get_op_uniform_location (ctx, shader, i, "circle_d"); - shader->radius_0_location[i] = - _cairo_gl_get_op_uniform_location (ctx, shader, i, "radius_0"); - shader->texdims_location[i] = - _cairo_gl_get_op_uniform_location (ctx, shader, i, "texdims"); - shader->texgen_location[i] = - _cairo_gl_get_op_uniform_location (ctx, shader, i, "texgen"); - } - - return CAIRO_STATUS_SUCCESS; - - FAILURE: - _cairo_gl_shader_fini (ctx, shader); - shader->fragment_shader = 0; - shader->program = 0; - - return status; -} - -/* We always bind the source to texture unit 0 if present, and mask to - * texture unit 1 if present, so we can just initialize these once at - * compile time. - */ -static cairo_status_t -_cairo_gl_shader_set_samplers (cairo_gl_context_t *ctx, - cairo_gl_shader_t *shader) -{ - cairo_gl_dispatch_t *dispatch = &ctx->dispatch; - GLint location; - GLint saved_program; - - /* We have to save/restore the current program because we might be - * asked for a different program while a shader is bound. This shouldn't - * be a performance issue, since this is only called once per compile. - */ - glGetIntegerv (GL_CURRENT_PROGRAM, &saved_program); - dispatch->UseProgram (shader->program); - - location = dispatch->GetUniformLocation (shader->program, "source_sampler"); - if (location != -1) { - dispatch->Uniform1i (location, CAIRO_GL_TEX_SOURCE); - } - - location = dispatch->GetUniformLocation (shader->program, "mask_sampler"); - if (location != -1) { - dispatch->Uniform1i (location, CAIRO_GL_TEX_MASK); - } - if(_cairo_gl_get_error()) return CAIRO_STATUS_DEVICE_ERROR; - dispatch->UseProgram (saved_program); - /* Pop and ignore a possible gl-error when restoring the previous program. - * It may be that being selected in the gl-context was the last reference - * to the shader. - */ - _cairo_gl_get_error(); - return CAIRO_STATUS_SUCCESS; -} - -void -_cairo_gl_shader_bind_float (cairo_gl_context_t *ctx, - GLint location, - float value) -{ - cairo_gl_dispatch_t *dispatch = &ctx->dispatch; - assert (location != -1); - dispatch->Uniform1f (location, value); -} - -void -_cairo_gl_shader_bind_vec2 (cairo_gl_context_t *ctx, - GLint location, - float value0, - float value1) -{ - cairo_gl_dispatch_t *dispatch = &ctx->dispatch; - assert (location != -1); - dispatch->Uniform2f (location, value0, value1); -} - -void -_cairo_gl_shader_bind_vec3 (cairo_gl_context_t *ctx, - GLint location, - float value0, - float value1, - float value2) -{ - cairo_gl_dispatch_t *dispatch = &ctx->dispatch; - assert (location != -1); - dispatch->Uniform3f (location, value0, value1, value2); -} - -void -_cairo_gl_shader_bind_vec4 (cairo_gl_context_t *ctx, - GLint location, - float value0, float value1, - float value2, float value3) -{ - cairo_gl_dispatch_t *dispatch = &ctx->dispatch; - assert (location != -1); - dispatch->Uniform4f (location, value0, value1, value2, value3); -} - -void -_cairo_gl_shader_bind_matrix (cairo_gl_context_t *ctx, - GLint location, - const cairo_matrix_t* m) -{ - cairo_gl_dispatch_t *dispatch = &ctx->dispatch; - float gl_m[9] = { - m->xx, m->yx, 0, - m->xy, m->yy, 0, - m->x0, m->y0, 1 - }; - assert (location != -1); - dispatch->UniformMatrix3fv (location, 1, GL_FALSE, gl_m); -} - -void -_cairo_gl_shader_bind_matrix4f (cairo_gl_context_t *ctx, - GLint location, GLfloat* gl_m) -{ - cairo_gl_dispatch_t *dispatch = &ctx->dispatch; - assert (location != -1); - dispatch->UniformMatrix4fv (location, 1, GL_FALSE, gl_m); -} - -void -_cairo_gl_set_shader (cairo_gl_context_t *ctx, - cairo_gl_shader_t *shader) -{ - if (ctx->current_shader == shader) - return; - - if (shader) - ctx->dispatch.UseProgram (shader->program); - else - ctx->dispatch.UseProgram (0); - - ctx->current_shader = shader; -} - -cairo_status_t -_cairo_gl_get_shader_by_type (cairo_gl_context_t *ctx, - cairo_gl_operand_t *source, - cairo_gl_operand_t *mask, - cairo_bool_t use_coverage, - cairo_gl_shader_in_t in, - cairo_gl_shader_t **shader) -{ - cairo_shader_cache_entry_t lookup, *entry; - char *fs_source; - cairo_status_t status; - - lookup.ctx = ctx; - - lookup.vertex = cairo_gl_var_type_hash (cairo_gl_operand_get_var_type (source), - cairo_gl_operand_get_var_type (mask), - use_coverage, - CAIRO_GL_VAR_NONE); - - lookup.src = source->type; - lookup.mask = mask->type; - lookup.dest = CAIRO_GL_OPERAND_NONE; - lookup.use_coverage = use_coverage; - lookup.in = in; - lookup.src_gl_filter = _cairo_gl_operand_get_gl_filter (source); - lookup.src_border_fade = _cairo_gl_shader_needs_border_fade (source); - lookup.src_extend = _cairo_gl_operand_get_extend (source); - lookup.mask_gl_filter = _cairo_gl_operand_get_gl_filter (mask); - lookup.mask_border_fade = _cairo_gl_shader_needs_border_fade (mask); - lookup.mask_extend = _cairo_gl_operand_get_extend (mask); - lookup.base.hash = _cairo_gl_shader_cache_hash (&lookup); - lookup.base.size = 1; - - entry = _cairo_cache_lookup (&ctx->shaders, &lookup.base); - if (entry) { - assert (entry->shader.program); - *shader = &entry->shader; - return CAIRO_STATUS_SUCCESS; - } - - status = cairo_gl_shader_get_fragment_source (ctx, - in, - source, - mask, - use_coverage, - CAIRO_GL_OPERAND_NONE, - &fs_source); - if (unlikely (status)) - return status; - - entry = _cairo_malloc (sizeof (cairo_shader_cache_entry_t)); - if (unlikely (entry == NULL)) { - free (fs_source); - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - memcpy (entry, &lookup, sizeof (cairo_shader_cache_entry_t)); - - entry->ctx = ctx; - _cairo_gl_shader_init (&entry->shader); - status = _cairo_gl_shader_compile_and_link (ctx, - &entry->shader, - cairo_gl_operand_get_var_type (source), - cairo_gl_operand_get_var_type (mask), - use_coverage, - fs_source); - free (fs_source); - - if (unlikely (status)) { - free (entry); - return status; - } - - status = _cairo_gl_shader_set_samplers (ctx, &entry->shader); - if (unlikely (status)) { - _cairo_gl_shader_fini (ctx, &entry->shader); - free (entry); - return status; - } - - status = _cairo_cache_insert (&ctx->shaders, &entry->base); - if (unlikely (status)) { - _cairo_gl_shader_fini (ctx, &entry->shader); - free (entry); - return status; - } - - *shader = &entry->shader; - - return CAIRO_STATUS_SUCCESS; -} diff --git a/src/cairo-gl-source.c b/src/cairo-gl-source.c deleted file mode 100644 index 7e0ee4a82..000000000 --- a/src/cairo-gl-source.c +++ /dev/null @@ -1,113 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2011 Intel Corporation - * - * 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 Red Hat, Inc. - * - * Contributor(s): - * Chris Wilson <chris@chris-wilson.co.uk> - */ - -#include "cairoint.h" - -#include "cairo-gl-private.h" - -#include "cairo-surface-backend-private.h" - -static cairo_status_t -_cairo_gl_source_finish (void *abstract_surface) -{ - cairo_gl_source_t *source = abstract_surface; - - _cairo_gl_operand_destroy (&source->operand); - return CAIRO_STATUS_SUCCESS; -} - -static const cairo_surface_backend_t cairo_gl_source_backend = { - CAIRO_SURFACE_TYPE_GL, - _cairo_gl_source_finish, - NULL, /* read-only wrapper */ -}; - -cairo_surface_t * -_cairo_gl_pattern_to_source (cairo_surface_t *dst, - const cairo_pattern_t *pattern, - cairo_bool_t is_mask, - const cairo_rectangle_int_t *extents, - const cairo_rectangle_int_t *sample, - int *src_x, int *src_y) -{ - cairo_gl_source_t *source; - cairo_int_status_t status; - - TRACE ((stderr, "%s\n", __FUNCTION__)); - if (pattern == NULL) - return _cairo_gl_white_source (); - - source = _cairo_malloc (sizeof (*source)); - if (unlikely (source == NULL)) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - - _cairo_surface_init (&source->base, - &cairo_gl_source_backend, - NULL, /* device */ - CAIRO_CONTENT_COLOR_ALPHA, - FALSE); /* is_vector */ - - *src_x = *src_y = 0; - status = _cairo_gl_operand_init (&source->operand, pattern, - (cairo_gl_surface_t *)dst, - sample, extents, - FALSE); - if (unlikely (status)) { - cairo_surface_destroy (&source->base); - return _cairo_surface_create_in_error (status); - } - - return &source->base; -} - -cairo_surface_t * -_cairo_gl_white_source (void) -{ - cairo_gl_source_t *source; - - source = _cairo_malloc (sizeof (*source)); - if (unlikely (source == NULL)) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - - _cairo_surface_init (&source->base, - &cairo_gl_source_backend, - NULL, /* device */ - CAIRO_CONTENT_COLOR_ALPHA, - FALSE); /* is_vector */ - - _cairo_gl_solid_operand_init (&source->operand, CAIRO_COLOR_WHITE); - - return &source->base; -} diff --git a/src/cairo-gl-spans-compositor.c b/src/cairo-gl-spans-compositor.c deleted file mode 100644 index 0a4538a04..000000000 --- a/src/cairo-gl-spans-compositor.c +++ /dev/null @@ -1,556 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2009 Eric Anholt - * Copyright © 2009 Chris Wilson - * Copyright © 2005,2010 Red Hat, Inc - * Copyright © 2011 Intel Corporation - * - * 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 Red Hat, Inc. - * - * Contributor(s): - * Benjamin Otte <otte@gnome.org> - * Carl Worth <cworth@cworth.org> - * Chris Wilson <chris@chris-wilson.co.uk> - * Eric Anholt <eric@anholt.net> - */ - -#include "cairoint.h" - -#include "cairo-gl-private.h" - -#include "cairo-composite-rectangles-private.h" -#include "cairo-compositor-private.h" -#include "cairo-default-context-private.h" -#include "cairo-error-private.h" -#include "cairo-image-surface-private.h" -#include "cairo-spans-compositor-private.h" -#include "cairo-surface-backend-private.h" - -typedef struct _cairo_gl_span_renderer { - cairo_span_renderer_t base; - - cairo_gl_composite_t setup; - double opacity; - - cairo_gl_emit_span_t emit; - - int xmin, xmax; - int ymin, ymax; - - cairo_gl_context_t *ctx; -} cairo_gl_span_renderer_t; - -static cairo_status_t -_cairo_gl_bounded_opaque_spans (void *abstract_renderer, - int y, int height, - const cairo_half_open_span_t *spans, - unsigned num_spans) -{ - cairo_gl_span_renderer_t *r = abstract_renderer; - cairo_gl_emit_span_t emit = r->emit; - - if (num_spans == 0) - return CAIRO_STATUS_SUCCESS; - - do { - if (spans[0].coverage) { - emit (r->ctx, - spans[0].x, y, - spans[1].x, y + height, - spans[0].coverage); - } - - spans++; - } while (--num_spans > 1); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_gl_bounded_spans (void *abstract_renderer, - int y, int height, - const cairo_half_open_span_t *spans, - unsigned num_spans) -{ - cairo_gl_span_renderer_t *r = abstract_renderer; - cairo_gl_emit_span_t emit = r->emit; - - if (num_spans == 0) - return CAIRO_STATUS_SUCCESS; - - do { - if (spans[0].coverage) { - emit (r->ctx, - spans[0].x, y, - spans[1].x, y + height, - r->opacity * spans[0].coverage); - } - - spans++; - } while (--num_spans > 1); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_gl_unbounded_spans (void *abstract_renderer, - int y, int height, - const cairo_half_open_span_t *spans, - unsigned num_spans) -{ - cairo_gl_span_renderer_t *r = abstract_renderer; - cairo_gl_emit_span_t emit = r->emit; - - if (y > r->ymin) { - emit (r->ctx, - r->xmin, r->ymin, - r->xmax, y, - 0); - } - - if (num_spans == 0) { - emit (r->ctx, - r->xmin, y, - r->xmax, y + height, - 0); - } else { - if (spans[0].x != r->xmin) { - emit (r->ctx, - r->xmin, y, - spans[0].x, y + height, - 0); - } - - do { - emit (r->ctx, - spans[0].x, y, - spans[1].x, y + height, - r->opacity * spans[0].coverage); - spans++; - } while (--num_spans > 1); - - if (spans[0].x != r->xmax) { - emit (r->ctx, - spans[0].x, y, - r->xmax, y + height, - 0); - } - } - - r->ymin = y + height; - return CAIRO_STATUS_SUCCESS; -} - -/* XXX */ -static cairo_status_t -_cairo_gl_clipped_spans (void *abstract_renderer, - int y, int height, - const cairo_half_open_span_t *spans, - unsigned num_spans) -{ - cairo_gl_span_renderer_t *r = abstract_renderer; - cairo_gl_emit_span_t emit = r->emit; - - if (y > r->ymin) { - emit (r->ctx, - r->xmin, r->ymin, - r->xmax, y, - 0); - } - - if (num_spans == 0) { - emit (r->ctx, - r->xmin, y, - r->xmax, y + height, - 0); - } else { - if (spans[0].x != r->xmin) { - emit (r->ctx, - r->xmin, y, - spans[0].x, y + height, - 0); - } - - do { - emit (r->ctx, - spans[0].x, y, - spans[1].x, y + height, - r->opacity * spans[0].coverage); - spans++; - } while (--num_spans > 1); - - if (spans[0].x != r->xmax) { - emit (r->ctx, - spans[0].x, y, - r->xmax, y + height, - 0); - } - } - - r->ymin = y + height; - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_gl_finish_unbounded_spans (void *abstract_renderer) -{ - cairo_gl_span_renderer_t *r = abstract_renderer; - cairo_gl_emit_span_t emit = r->emit; - - if (r->ymax > r->ymin) { - emit (r->ctx, - r->xmin, r->ymin, - r->xmax, r->ymax, - 0); - } - - return _cairo_gl_context_release (r->ctx, CAIRO_STATUS_SUCCESS); -} - -static cairo_status_t -_cairo_gl_finish_bounded_spans (void *abstract_renderer) -{ - cairo_gl_span_renderer_t *r = abstract_renderer; - - return _cairo_gl_context_release (r->ctx, CAIRO_STATUS_SUCCESS); -} - -static void -emit_aligned_boxes (cairo_gl_context_t *ctx, - const cairo_boxes_t *boxes) -{ - const struct _cairo_boxes_chunk *chunk; - cairo_gl_emit_rect_t emit = _cairo_gl_context_choose_emit_rect (ctx); - int i; - - TRACE ((stderr, "%s: num_boxes=%d\n", __FUNCTION__, boxes->num_boxes)); - for (chunk = &boxes->chunks; chunk; chunk = chunk->next) { - for (i = 0; i < chunk->count; i++) { - int x1 = _cairo_fixed_integer_part (chunk->base[i].p1.x); - int y1 = _cairo_fixed_integer_part (chunk->base[i].p1.y); - int x2 = _cairo_fixed_integer_part (chunk->base[i].p2.x); - int y2 = _cairo_fixed_integer_part (chunk->base[i].p2.y); - emit (ctx, x1, y1, x2, y2); - } - } -} - -static cairo_int_status_t -fill_boxes (void *_dst, - cairo_operator_t op, - const cairo_color_t *color, - cairo_boxes_t *boxes) -{ - cairo_gl_composite_t setup; - cairo_gl_context_t *ctx; - cairo_int_status_t status; - - TRACE ((stderr, "%s\n", __FUNCTION__)); - status = _cairo_gl_composite_init (&setup, op, _dst, FALSE); - if (unlikely (status)) - goto FAIL; - - _cairo_gl_composite_set_solid_source (&setup, color); - - status = _cairo_gl_composite_begin (&setup, &ctx); - if (unlikely (status)) - goto FAIL; - - emit_aligned_boxes (ctx, boxes); - status = _cairo_gl_context_release (ctx, CAIRO_STATUS_SUCCESS); - -FAIL: - _cairo_gl_composite_fini (&setup); - return status; -} - -static cairo_int_status_t -draw_image_boxes (void *_dst, - cairo_image_surface_t *image, - cairo_boxes_t *boxes, - int dx, int dy) -{ - cairo_gl_surface_t *dst = _dst; - struct _cairo_boxes_chunk *chunk; - int i; - - for (chunk = &boxes->chunks; chunk; chunk = chunk->next) { - for (i = 0; i < chunk->count; i++) { - cairo_box_t *b = &chunk->base[i]; - int x = _cairo_fixed_integer_part (b->p1.x); - int y = _cairo_fixed_integer_part (b->p1.y); - int w = _cairo_fixed_integer_part (b->p2.x) - x; - int h = _cairo_fixed_integer_part (b->p2.y) - y; - cairo_status_t status; - - status = _cairo_gl_surface_draw_image (dst, image, - x + dx, y + dy, - w, h, - x, y, TRUE); - if (unlikely (status)) - return status; - } - } - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t copy_boxes (void *_dst, - cairo_surface_t *_src, - cairo_boxes_t *boxes, - const cairo_rectangle_int_t *extents, - int dx, int dy) -{ - cairo_gl_surface_t *dst = _dst; - cairo_gl_surface_t *src = (cairo_gl_surface_t *)_src; - cairo_gl_composite_t setup; - cairo_gl_context_t *ctx; - cairo_int_status_t status; - - TRACE ((stderr, "%s\n", __FUNCTION__)); - if (! _cairo_gl_surface_is_texture (src)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - if (src->base.device != dst->base.device) - return CAIRO_INT_STATUS_UNSUPPORTED; - - status = _cairo_gl_composite_init (&setup, CAIRO_OPERATOR_SOURCE, _dst, FALSE); - if (unlikely (status)) - goto FAIL; - - _cairo_gl_composite_set_source_operand (&setup, &src->operand); - _cairo_gl_operand_translate (&setup.src, -dx, -dy); - - status = _cairo_gl_composite_begin (&setup, &ctx); - if (unlikely (status)) - goto FAIL; - - emit_aligned_boxes (ctx, boxes); - status = _cairo_gl_context_release (ctx, CAIRO_STATUS_SUCCESS); - -FAIL: - _cairo_gl_composite_fini (&setup); - return status; -} - -static cairo_int_status_t -composite_boxes (void *_dst, - cairo_operator_t op, - cairo_surface_t *abstract_src, - cairo_surface_t *abstract_mask, - int src_x, - int src_y, - int mask_x, - int mask_y, - int dst_x, - int dst_y, - cairo_boxes_t *boxes, - const cairo_rectangle_int_t *extents) -{ - cairo_gl_composite_t setup; - cairo_gl_context_t *ctx; - cairo_int_status_t status; - cairo_gl_operand_t tmp_operand; - cairo_gl_operand_t *src_operand; - - TRACE ((stderr, "%s mask=(%d,%d), dst=(%d, %d)\n", __FUNCTION__, - mask_x, mask_y, dst_x, dst_y)); - - if (abstract_mask) { - if (op == CAIRO_OPERATOR_CLEAR) { - _cairo_gl_solid_operand_init (&tmp_operand, CAIRO_COLOR_WHITE); - src_operand = &tmp_operand; - op = CAIRO_OPERATOR_DEST_OUT; - } else if (op == CAIRO_OPERATOR_SOURCE) { - /* requires a LERP in the shader between dest and source */ - return CAIRO_INT_STATUS_UNSUPPORTED; - } else - src_operand = source_to_operand (abstract_src); - } else - src_operand = source_to_operand (abstract_src); - - status = _cairo_gl_composite_init (&setup, op, _dst, FALSE); - if (unlikely (status)) - goto FAIL; - - _cairo_gl_composite_set_source_operand (&setup, - src_operand); - _cairo_gl_operand_translate (&setup.src, -src_x, -src_y); - - _cairo_gl_composite_set_mask_operand (&setup, - source_to_operand (abstract_mask)); - _cairo_gl_operand_translate (&setup.mask, -mask_x, -mask_y); - - status = _cairo_gl_composite_begin (&setup, &ctx); - if (unlikely (status)) - goto FAIL; - - emit_aligned_boxes (ctx, boxes); - status = _cairo_gl_context_release (ctx, CAIRO_STATUS_SUCCESS); - -FAIL: - _cairo_gl_composite_fini (&setup); - if (src_operand == &tmp_operand) - _cairo_gl_operand_destroy (&tmp_operand); - return status; -} - -static cairo_int_status_t -_cairo_gl_span_renderer_init (cairo_abstract_span_renderer_t *_r, - const cairo_composite_rectangles_t *composite, - cairo_antialias_t antialias, - cairo_bool_t needs_clip) -{ - cairo_gl_span_renderer_t *r = (cairo_gl_span_renderer_t *)_r; - const cairo_pattern_t *source = &composite->source_pattern.base; - cairo_operator_t op = composite->op; - cairo_int_status_t status; - - if (op == CAIRO_OPERATOR_SOURCE) { - if (! _cairo_pattern_is_opaque (&composite->source_pattern.base, - &composite->source_sample_area)) - return CAIRO_INT_STATUS_UNSUPPORTED; - op = CAIRO_OPERATOR_OVER; - } - - /* XXX earlier! */ - if (op == CAIRO_OPERATOR_CLEAR) { - source = &_cairo_pattern_white.base; - op = CAIRO_OPERATOR_DEST_OUT; - } else if (composite->surface->is_clear && - (op == CAIRO_OPERATOR_SOURCE || - op == CAIRO_OPERATOR_OVER || - op == CAIRO_OPERATOR_ADD)) { - op = CAIRO_OPERATOR_SOURCE; - } else if (op == CAIRO_OPERATOR_SOURCE) { - /* no lerp equivalent without some major PITA */ - return CAIRO_INT_STATUS_UNSUPPORTED; - } else if (! _cairo_gl_operator_is_supported (op)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - status = _cairo_gl_composite_init (&r->setup, - op, (cairo_gl_surface_t *)composite->surface, - FALSE); - if (unlikely (status)) - goto FAIL; - - status = _cairo_gl_composite_set_source (&r->setup, source, - &composite->source_sample_area, - &composite->unbounded, - TRUE); - if (unlikely (status)) - goto FAIL; - - r->opacity = 1.0; - if (composite->mask_pattern.base.type == CAIRO_PATTERN_TYPE_SOLID) { - r->opacity = composite->mask_pattern.solid.color.alpha; - } else { - status = _cairo_gl_composite_set_mask (&r->setup, - &composite->mask_pattern.base, - &composite->mask_sample_area, - &composite->unbounded, - TRUE); - if (unlikely (status)) - goto FAIL; - } - - _cairo_gl_composite_set_spans (&r->setup); - - status = _cairo_gl_composite_begin (&r->setup, &r->ctx); - if (unlikely (status)) - goto FAIL; - - r->emit = _cairo_gl_context_choose_emit_span (r->ctx); - if (composite->is_bounded) { - if (r->opacity == 1.) - r->base.render_rows = _cairo_gl_bounded_opaque_spans; - else - r->base.render_rows = _cairo_gl_bounded_spans; - r->base.finish = _cairo_gl_finish_bounded_spans; - } else { - if (needs_clip) - r->base.render_rows = _cairo_gl_clipped_spans; - else - r->base.render_rows = _cairo_gl_unbounded_spans; - r->base.finish = _cairo_gl_finish_unbounded_spans; - r->xmin = composite->unbounded.x; - r->xmax = composite->unbounded.x + composite->unbounded.width; - r->ymin = composite->unbounded.y; - r->ymax = composite->unbounded.y + composite->unbounded.height; - } - - return CAIRO_STATUS_SUCCESS; - -FAIL: - return status; -} - -static void -_cairo_gl_span_renderer_fini (cairo_abstract_span_renderer_t *_r, - cairo_int_status_t status) -{ - cairo_gl_span_renderer_t *r = (cairo_gl_span_renderer_t *) _r; - - if (status == CAIRO_INT_STATUS_UNSUPPORTED) - return; - - if (status == CAIRO_INT_STATUS_SUCCESS) - r->base.finish (r); - - _cairo_gl_composite_fini (&r->setup); -} - -const cairo_compositor_t * -_cairo_gl_span_compositor_get (void) -{ - static cairo_atomic_once_t once = CAIRO_ATOMIC_ONCE_INIT; - static cairo_spans_compositor_t spans; - static cairo_compositor_t shape; - - if (_cairo_atomic_init_once_enter(&once)) { - /* The fallback to traps here is essentially just for glyphs... */ - _cairo_shape_mask_compositor_init (&shape, - _cairo_gl_traps_compositor_get()); - shape.glyphs = NULL; - - _cairo_spans_compositor_init (&spans, &shape); - spans.fill_boxes = fill_boxes; - spans.draw_image_boxes = draw_image_boxes; - spans.copy_boxes = copy_boxes; - //spans.check_composite_boxes = check_composite_boxes; - spans.pattern_to_surface = _cairo_gl_pattern_to_source; - spans.composite_boxes = composite_boxes; - //spans.check_span_renderer = check_span_renderer; - spans.renderer_init = _cairo_gl_span_renderer_init; - spans.renderer_fini = _cairo_gl_span_renderer_fini; - - _cairo_atomic_init_once_leave(&once); - } - - return &spans.base; -} diff --git a/src/cairo-gl-surface-legacy.c b/src/cairo-gl-surface-legacy.c deleted file mode 100644 index 87dca2f03..000000000 --- a/src/cairo-gl-surface-legacy.c +++ /dev/null @@ -1,602 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2009 Eric Anholt - * Copyright © 2009 Chris Wilson - * Copyright © 2005,2010 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., 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 Red Hat, Inc. - * - * Contributor(s): - * Benjamin Otte <otte@gnome.org> - * Carl Worth <cworth@cworth.org> - * Chris Wilson <chris@chris-wilson.co.uk> - * Eric Anholt <eric@anholt.net> - */ - -#include "cairoint.h" - -#include "cairo-composite-rectangles-private.h" -#include "cairo-default-context-private.h" -#include "cairo-error-private.h" -#include "cairo-gl-private.h" -#include "cairo-image-surface-inline.h" - -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; - cairo_int_status_t status; - - status = _cairo_gl_surface_deferred_clear (surface); - if (unlikely (status)) - return status; - - *image_extra = NULL; - return _cairo_gl_surface_get_image (surface, interest_rect, image_out, - image_rect_out); -} - -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_status_t status; - - status = _cairo_gl_surface_draw_image (abstract_surface, image, - 0, 0, - image->width, image->height, - image_rect->x, image_rect->y, - TRUE); - /* as we created the image, its format should be directly applicable */ - assert (status == CAIRO_STATUS_SUCCESS); - - cairo_surface_destroy (&image->base); -} - -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; - cairo_int_status_t status; - - /* XXX: Use GLCopyTexImage2D to clone non-texture-surfaces */ - if (src->device == surface->base.device && - _cairo_gl_surface_is_texture ((cairo_gl_surface_t *) src)) { - status = _cairo_gl_surface_deferred_clear ((cairo_gl_surface_t *)src); - if (unlikely (status)) - return status; - - *clone_offset_x = 0; - *clone_offset_y = 0; - *clone_out = cairo_surface_reference (src); - - return CAIRO_STATUS_SUCCESS; - } else if (_cairo_surface_is_image (src)) { - cairo_image_surface_t *image_src = (cairo_image_surface_t *)src; - cairo_gl_surface_t *clone; - - clone = (cairo_gl_surface_t *) - _cairo_gl_surface_create_similar (&surface->base, - src->content, - width, height); - if (clone == NULL) - return UNSUPPORTED ("create_similar failed"); - if (clone->base.status) - return clone->base.status; - - status = _cairo_gl_surface_draw_image (clone, image_src, - src_x, src_y, - width, height, - 0, 0, TRUE); - if (status) { - cairo_surface_destroy (&clone->base); - return status; - } - - *clone_out = &clone->base; - *clone_offset_x = src_x; - *clone_offset_y = src_y; - - return CAIRO_STATUS_SUCCESS; - } - - return UNSUPPORTED ("unknown src surface type in clone_similar"); -} - -/* Creates a cairo-gl pattern surface for the given trapezoids */ -static cairo_status_t -_cairo_gl_get_traps_pattern (cairo_gl_surface_t *dst, - int dst_x, int dst_y, - int width, int height, - cairo_trapezoid_t *traps, - int num_traps, - cairo_antialias_t antialias, - cairo_surface_pattern_t *pattern) -{ - pixman_format_code_t pixman_format; - pixman_image_t *image; - cairo_surface_t *surface; - int i; - - pixman_format = antialias != CAIRO_ANTIALIAS_NONE ? PIXMAN_a8 : PIXMAN_a1, - image = pixman_image_create_bits (pixman_format, width, height, NULL, 0); - if (unlikely (image == NULL)) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - for (i = 0; i < num_traps; i++) { - pixman_trapezoid_t trap; - - trap.top = _cairo_fixed_to_16_16 (traps[i].top); - trap.bottom = _cairo_fixed_to_16_16 (traps[i].bottom); - - trap.left.p1.x = _cairo_fixed_to_16_16 (traps[i].left.p1.x); - trap.left.p1.y = _cairo_fixed_to_16_16 (traps[i].left.p1.y); - trap.left.p2.x = _cairo_fixed_to_16_16 (traps[i].left.p2.x); - trap.left.p2.y = _cairo_fixed_to_16_16 (traps[i].left.p2.y); - - trap.right.p1.x = _cairo_fixed_to_16_16 (traps[i].right.p1.x); - trap.right.p1.y = _cairo_fixed_to_16_16 (traps[i].right.p1.y); - trap.right.p2.x = _cairo_fixed_to_16_16 (traps[i].right.p2.x); - trap.right.p2.y = _cairo_fixed_to_16_16 (traps[i].right.p2.y); - - pixman_rasterize_trapezoid (image, &trap, -dst_x, -dst_y); - } - - surface = _cairo_image_surface_create_for_pixman_image (image, - pixman_format); - if (unlikely (surface->status)) { - pixman_image_unref (image); - return surface->status; - } - - _cairo_pattern_init_for_surface (pattern, surface); - cairo_surface_destroy (surface); - - return CAIRO_STATUS_SUCCESS; -} - -cairo_int_status_t -_cairo_gl_surface_composite (cairo_operator_t op, - const cairo_pattern_t *src, - const cairo_pattern_t *mask, - void *abstract_dst, - int src_x, - int src_y, - int mask_x, - int mask_y, - int dst_x, - int dst_y, - unsigned int width, - unsigned int height, - cairo_region_t *clip_region) -{ - cairo_gl_surface_t *dst = abstract_dst; - cairo_gl_context_t *ctx; - cairo_status_t status; - cairo_gl_composite_t setup; - cairo_rectangle_int_t rect = { dst_x, dst_y, width, height }; - int dx, dy; - - status = _cairo_gl_surface_deferred_clear (dst); - if (unlikely (status)) - return status; - - if (op == CAIRO_OPERATOR_SOURCE && - mask == NULL && - src->type == CAIRO_PATTERN_TYPE_SURFACE && - _cairo_surface_is_image (((cairo_surface_pattern_t *) src)->surface) && - _cairo_matrix_is_integer_translation (&src->matrix, &dx, &dy)) { - cairo_image_surface_t *image = (cairo_image_surface_t *) - ((cairo_surface_pattern_t *) src)->surface; - dx += src_x; - dy += src_y; - if (dx >= 0 && - dy >= 0 && - dx + width <= (unsigned int) image->width && - dy + height <= (unsigned int) image->height) { - status = _cairo_gl_surface_draw_image (dst, image, - dx, dy, - width, height, - dst_x, dst_y, TRUE); - if (status != CAIRO_INT_STATUS_UNSUPPORTED) - return status; - } - } - - status = _cairo_gl_composite_init (&setup, op, dst, - mask && mask->has_component_alpha, - &rect); - if (unlikely (status)) - goto CLEANUP; - - status = _cairo_gl_composite_set_source (&setup, src, - src_x, src_y, - dst_x, dst_y, - width, height); - if (unlikely (status)) - goto CLEANUP; - - status = _cairo_gl_composite_set_mask (&setup, mask, - mask_x, mask_y, - dst_x, dst_y, - width, height); - if (unlikely (status)) - goto CLEANUP; - - status = _cairo_gl_composite_begin (&setup, &ctx); - if (unlikely (status)) - goto CLEANUP; - - if (clip_region != NULL) { - int i, num_rectangles; - - num_rectangles = cairo_region_num_rectangles (clip_region); - - for (i = 0; i < num_rectangles; i++) { - cairo_rectangle_int_t rect; - - cairo_region_get_rectangle (clip_region, i, &rect); - _cairo_gl_composite_emit_rect (ctx, - rect.x, rect.y, - rect.x + rect.width, rect.y + rect.height, - 0); - } - } else { - _cairo_gl_composite_emit_rect (ctx, - dst_x, dst_y, - dst_x + width, dst_y + height, - 0); - } - - status = _cairo_gl_context_release (ctx, status); - - CLEANUP: - _cairo_gl_composite_fini (&setup); - - return status; -} - -cairo_int_status_t -_cairo_gl_surface_composite_trapezoids (cairo_operator_t op, - const cairo_pattern_t *pattern, - void *abstract_dst, - cairo_antialias_t antialias, - int src_x, int src_y, - int dst_x, int dst_y, - unsigned int width, - unsigned int height, - cairo_trapezoid_t *traps, - int num_traps, - cairo_region_t *clip_region) -{ - cairo_gl_surface_t *dst = abstract_dst; - cairo_surface_pattern_t traps_pattern; - cairo_int_status_t status; - - if (! _cairo_gl_operator_is_supported (op)) - return UNSUPPORTED ("unsupported operator"); - - status = _cairo_gl_surface_deferred_clear (dst); - if (unlikely (status)) - return status; - - status = _cairo_gl_get_traps_pattern (dst, - dst_x, dst_y, width, height, - traps, num_traps, antialias, - &traps_pattern); - if (unlikely (status)) - return status; - - status = _cairo_gl_surface_composite (op, - pattern, &traps_pattern.base, dst, - src_x, src_y, - 0, 0, - dst_x, dst_y, - width, height, - clip_region); - - _cairo_pattern_fini (&traps_pattern.base); - - assert (status != CAIRO_INT_STATUS_UNSUPPORTED); - return status; -} - -cairo_int_status_t -_cairo_gl_surface_fill_rectangles (void *abstract_dst, - cairo_operator_t op, - const cairo_color_t *color, - cairo_rectangle_int_t *rects, - int num_rects) -{ - cairo_gl_surface_t *dst = abstract_dst; - cairo_solid_pattern_t solid; - cairo_gl_context_t *ctx; - cairo_status_t status; - cairo_gl_composite_t setup; - int i; - - status = _cairo_gl_surface_deferred_clear (dst); - if (unlikely (status)) - return status; - - status = _cairo_gl_composite_init (&setup, op, dst, - FALSE, - /* XXX */ NULL); - if (unlikely (status)) - goto CLEANUP; - - _cairo_pattern_init_solid (&solid, color); - status = _cairo_gl_composite_set_source (&setup, &solid.base, - 0, 0, - 0, 0, - 0, 0); - if (unlikely (status)) - goto CLEANUP; - - status = _cairo_gl_composite_set_mask (&setup, NULL, - 0, 0, - 0, 0, - 0, 0); - if (unlikely (status)) - goto CLEANUP; - - status = _cairo_gl_composite_begin (&setup, &ctx); - if (unlikely (status)) - goto CLEANUP; - - for (i = 0; i < num_rects; i++) { - _cairo_gl_composite_emit_rect (ctx, - rects[i].x, - rects[i].y, - rects[i].x + rects[i].width, - rects[i].y + rects[i].height, - 0); - } - - status = _cairo_gl_context_release (ctx, status); - - CLEANUP: - _cairo_gl_composite_fini (&setup); - - return status; -} - -typedef struct _cairo_gl_surface_span_renderer { - cairo_span_renderer_t base; - - cairo_gl_composite_t setup; - - int xmin, xmax; - int ymin, ymax; - - cairo_gl_context_t *ctx; -} cairo_gl_surface_span_renderer_t; - -static cairo_status_t -_cairo_gl_render_bounded_spans (void *abstract_renderer, - int y, int height, - const cairo_half_open_span_t *spans, - unsigned num_spans) -{ - cairo_gl_surface_span_renderer_t *renderer = abstract_renderer; - - if (num_spans == 0) - return CAIRO_STATUS_SUCCESS; - - do { - if (spans[0].coverage) { - _cairo_gl_composite_emit_rect (renderer->ctx, - spans[0].x, y, - spans[1].x, y + height, - spans[0].coverage); - } - - spans++; - } while (--num_spans > 1); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_gl_render_unbounded_spans (void *abstract_renderer, - int y, int height, - const cairo_half_open_span_t *spans, - unsigned num_spans) -{ - cairo_gl_surface_span_renderer_t *renderer = abstract_renderer; - - if (y > renderer->ymin) { - _cairo_gl_composite_emit_rect (renderer->ctx, - renderer->xmin, renderer->ymin, - renderer->xmax, y, - 0); - } - - if (num_spans == 0) { - _cairo_gl_composite_emit_rect (renderer->ctx, - renderer->xmin, y, - renderer->xmax, y + height, - 0); - } else { - if (spans[0].x != renderer->xmin) { - _cairo_gl_composite_emit_rect (renderer->ctx, - renderer->xmin, y, - spans[0].x, y + height, - 0); - } - - do { - _cairo_gl_composite_emit_rect (renderer->ctx, - spans[0].x, y, - spans[1].x, y + height, - spans[0].coverage); - spans++; - } while (--num_spans > 1); - - if (spans[0].x != renderer->xmax) { - _cairo_gl_composite_emit_rect (renderer->ctx, - spans[0].x, y, - renderer->xmax, y + height, - 0); - } - } - - renderer->ymin = y + height; - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_gl_finish_unbounded_spans (void *abstract_renderer) -{ - cairo_gl_surface_span_renderer_t *renderer = abstract_renderer; - - if (renderer->ymax > renderer->ymin) { - _cairo_gl_composite_emit_rect (renderer->ctx, - renderer->xmin, renderer->ymin, - renderer->xmax, renderer->ymax, - 0); - } - - return _cairo_gl_context_release (renderer->ctx, CAIRO_STATUS_SUCCESS); -} - -static cairo_status_t -_cairo_gl_finish_bounded_spans (void *abstract_renderer) -{ - cairo_gl_surface_span_renderer_t *renderer = abstract_renderer; - - return _cairo_gl_context_release (renderer->ctx, CAIRO_STATUS_SUCCESS); -} - -static void -_cairo_gl_surface_span_renderer_destroy (void *abstract_renderer) -{ - cairo_gl_surface_span_renderer_t *renderer = abstract_renderer; - - if (!renderer) - return; - - _cairo_gl_composite_fini (&renderer->setup); - - free (renderer); -} - -cairo_bool_t -_cairo_gl_surface_check_span_renderer (cairo_operator_t op, - const cairo_pattern_t *pattern, - void *abstract_dst, - cairo_antialias_t antialias) -{ - if (! _cairo_gl_operator_is_supported (op)) - return FALSE; - - return TRUE; - - (void) pattern; - (void) abstract_dst; - (void) antialias; -} - -cairo_span_renderer_t * -_cairo_gl_surface_create_span_renderer (cairo_operator_t op, - const cairo_pattern_t *src, - void *abstract_dst, - cairo_antialias_t antialias, - const cairo_composite_rectangles_t *rects) -{ - cairo_gl_surface_t *dst = abstract_dst; - cairo_gl_surface_span_renderer_t *renderer; - cairo_status_t status; - const cairo_rectangle_int_t *extents; - - status = _cairo_gl_surface_deferred_clear (dst); - if (unlikely (status)) - return _cairo_span_renderer_create_in_error (status); - - renderer = calloc (1, sizeof (*renderer)); - if (unlikely (renderer == NULL)) - return _cairo_span_renderer_create_in_error (CAIRO_STATUS_NO_MEMORY); - - renderer->base.destroy = _cairo_gl_surface_span_renderer_destroy; - if (rects->is_bounded) { - renderer->base.render_rows = _cairo_gl_render_bounded_spans; - renderer->base.finish = _cairo_gl_finish_bounded_spans; - extents = &rects->bounded; - } else { - renderer->base.render_rows = _cairo_gl_render_unbounded_spans; - renderer->base.finish = _cairo_gl_finish_unbounded_spans; - extents = &rects->unbounded; - } - renderer->xmin = extents->x; - renderer->xmax = extents->x + extents->width; - renderer->ymin = extents->y; - renderer->ymax = extents->y + extents->height; - - status = _cairo_gl_composite_init (&renderer->setup, - op, dst, - FALSE, extents); - if (unlikely (status)) - goto FAIL; - - status = _cairo_gl_composite_set_source (&renderer->setup, src, - extents->x, extents->y, - extents->x, extents->y, - extents->width, extents->height); - if (unlikely (status)) - goto FAIL; - - _cairo_gl_composite_set_spans (&renderer->setup); - _cairo_gl_composite_set_clip_region (&renderer->setup, - _cairo_clip_get_region (rects->clip)); - - status = _cairo_gl_composite_begin (&renderer->setup, &renderer->ctx); - if (unlikely (status)) - goto FAIL; - - return &renderer->base; - -FAIL: - _cairo_gl_composite_fini (&renderer->setup); - free (renderer); - return _cairo_span_renderer_create_in_error (status); -} diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c deleted file mode 100644 index e48244dd4..000000000 --- a/src/cairo-gl-surface.c +++ /dev/null @@ -1,1552 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2009 Eric Anholt - * Copyright © 2009 Chris Wilson - * Copyright © 2005,2010 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., 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 Red Hat, Inc. - * - * Contributor(s): - * Benjamin Otte <otte@gnome.org> - * Carl Worth <cworth@cworth.org> - * Chris Wilson <chris@chris-wilson.co.uk> - * Eric Anholt <eric@anholt.net> - */ - -#include "cairoint.h" - -#include "cairo-gl-private.h" - -#include "cairo-composite-rectangles-private.h" -#include "cairo-compositor-private.h" -#include "cairo-default-context-private.h" -#include "cairo-error-private.h" -#include "cairo-image-surface-inline.h" -#include "cairo-surface-backend-private.h" - -static const cairo_surface_backend_t _cairo_gl_surface_backend; - -static cairo_status_t -_cairo_gl_surface_flush (void *abstract_surface, unsigned flags); - -static cairo_bool_t _cairo_surface_is_gl (cairo_surface_t *surface) -{ - return surface->backend == &_cairo_gl_surface_backend; -} - -static cairo_bool_t -_cairo_gl_get_image_format_and_type_gles2 (pixman_format_code_t pixman_format, - GLenum *internal_format, GLenum *format, - GLenum *type, cairo_bool_t *has_alpha, - cairo_bool_t *needs_swap) -{ - cairo_bool_t is_little_endian = _cairo_is_little_endian (); - - *has_alpha = TRUE; - - switch ((int) pixman_format) { - case PIXMAN_a8r8g8b8: - *internal_format = GL_BGRA; - *format = GL_BGRA; - *type = GL_UNSIGNED_BYTE; - *needs_swap = !is_little_endian; - return TRUE; - - case PIXMAN_x8r8g8b8: - *internal_format = GL_BGRA; - *format = GL_BGRA; - *type = GL_UNSIGNED_BYTE; - *has_alpha = FALSE; - *needs_swap = !is_little_endian; - return TRUE; - - case PIXMAN_a8b8g8r8: - *internal_format = GL_RGBA; - *format = GL_RGBA; - *type = GL_UNSIGNED_BYTE; - *needs_swap = !is_little_endian; - return TRUE; - - case PIXMAN_x8b8g8r8: - *internal_format = GL_RGBA; - *format = GL_RGBA; - *type = GL_UNSIGNED_BYTE; - *has_alpha = FALSE; - *needs_swap = !is_little_endian; - return TRUE; - - case PIXMAN_b8g8r8a8: - *internal_format = GL_BGRA; - *format = GL_BGRA; - *type = GL_UNSIGNED_BYTE; - *needs_swap = is_little_endian; - return TRUE; - - case PIXMAN_b8g8r8x8: - *internal_format = GL_BGRA; - *format = GL_BGRA; - *type = GL_UNSIGNED_BYTE; - *has_alpha = FALSE; - *needs_swap = is_little_endian; - return TRUE; - - case PIXMAN_r8g8b8: - *internal_format = GL_RGB; - *format = GL_RGB; - *type = GL_UNSIGNED_BYTE; - *needs_swap = is_little_endian; - return TRUE; - - case PIXMAN_b8g8r8: - *internal_format = GL_RGB; - *format = GL_RGB; - *type = GL_UNSIGNED_BYTE; - *needs_swap = !is_little_endian; - return TRUE; - - case PIXMAN_r5g6b5: - *internal_format = GL_RGB; - *format = GL_RGB; - *type = GL_UNSIGNED_SHORT_5_6_5; - *needs_swap = FALSE; - return TRUE; - - case PIXMAN_b5g6r5: - *internal_format = GL_RGB; - *format = GL_RGB; - *type = GL_UNSIGNED_SHORT_5_6_5; - *needs_swap = TRUE; - return TRUE; - - case PIXMAN_a1b5g5r5: - *internal_format = GL_RGBA; - *format = GL_RGBA; - *type = GL_UNSIGNED_SHORT_5_5_5_1; - *needs_swap = TRUE; - return TRUE; - - case PIXMAN_x1b5g5r5: - *internal_format = GL_RGBA; - *format = GL_RGBA; - *type = GL_UNSIGNED_SHORT_5_5_5_1; - *has_alpha = FALSE; - *needs_swap = TRUE; - return TRUE; - - case PIXMAN_a8: - *internal_format = GL_ALPHA; - *format = GL_ALPHA; - *type = GL_UNSIGNED_BYTE; - *needs_swap = FALSE; - return TRUE; - - default: - return FALSE; - } -} - -static cairo_bool_t -_cairo_gl_get_image_format_and_type_gl (pixman_format_code_t pixman_format, - GLenum *internal_format, GLenum *format, - GLenum *type, cairo_bool_t *has_alpha, - cairo_bool_t *needs_swap) -{ - *has_alpha = TRUE; - *needs_swap = FALSE; - - switch (pixman_format) { - case PIXMAN_a8r8g8b8: - *internal_format = GL_RGBA; - *format = GL_BGRA; - *type = GL_UNSIGNED_INT_8_8_8_8_REV; - return TRUE; - case PIXMAN_x8r8g8b8: - *internal_format = GL_RGB; - *format = GL_BGRA; - *type = GL_UNSIGNED_INT_8_8_8_8_REV; - *has_alpha = FALSE; - return TRUE; - case PIXMAN_a8b8g8r8: - *internal_format = GL_RGBA; - *format = GL_RGBA; - *type = GL_UNSIGNED_INT_8_8_8_8_REV; - return TRUE; - case PIXMAN_x8b8g8r8: - *internal_format = GL_RGB; - *format = GL_RGBA; - *type = GL_UNSIGNED_INT_8_8_8_8_REV; - *has_alpha = FALSE; - return TRUE; - case PIXMAN_b8g8r8a8: - *internal_format = GL_RGBA; - *format = GL_BGRA; - *type = GL_UNSIGNED_INT_8_8_8_8; - return TRUE; - case PIXMAN_b8g8r8x8: - *internal_format = GL_RGB; - *format = GL_BGRA; - *type = GL_UNSIGNED_INT_8_8_8_8; - *has_alpha = FALSE; - return TRUE; - case PIXMAN_r8g8b8: - *internal_format = GL_RGB; - *format = GL_RGB; - *type = GL_UNSIGNED_BYTE; - return TRUE; - case PIXMAN_b8g8r8: - *internal_format = GL_RGB; - *format = GL_BGR; - *type = GL_UNSIGNED_BYTE; - return TRUE; - case PIXMAN_r5g6b5: - *internal_format = GL_RGB; - *format = GL_RGB; - *type = GL_UNSIGNED_SHORT_5_6_5; - return TRUE; - case PIXMAN_b5g6r5: - *internal_format = GL_RGB; - *format = GL_RGB; - *type = GL_UNSIGNED_SHORT_5_6_5_REV; - return TRUE; - case PIXMAN_a1r5g5b5: - *internal_format = GL_RGBA; - *format = GL_BGRA; - *type = GL_UNSIGNED_SHORT_1_5_5_5_REV; - return TRUE; - case PIXMAN_x1r5g5b5: - *internal_format = GL_RGB; - *format = GL_BGRA; - *type = GL_UNSIGNED_SHORT_1_5_5_5_REV; - *has_alpha = FALSE; - return TRUE; - case PIXMAN_a1b5g5r5: - *internal_format = GL_RGBA; - *format = GL_RGBA; - *type = GL_UNSIGNED_SHORT_1_5_5_5_REV; - return TRUE; - case PIXMAN_x1b5g5r5: - *internal_format = GL_RGB; - *format = GL_RGBA; - *type = GL_UNSIGNED_SHORT_1_5_5_5_REV; - *has_alpha = FALSE; - return TRUE; - case PIXMAN_a8: - *internal_format = GL_ALPHA; - *format = GL_ALPHA; - *type = GL_UNSIGNED_BYTE; - return TRUE; - -#if PIXMAN_VERSION >= PIXMAN_VERSION_ENCODE(0,27,2) - case PIXMAN_a8r8g8b8_sRGB: -#endif - case PIXMAN_a2b10g10r10: - case PIXMAN_x2b10g10r10: - case PIXMAN_a4r4g4b4: - case PIXMAN_x4r4g4b4: - case PIXMAN_a4b4g4r4: - case PIXMAN_x4b4g4r4: - case PIXMAN_r3g3b2: - case PIXMAN_b2g3r3: - case PIXMAN_a2r2g2b2: - case PIXMAN_a2b2g2r2: - case PIXMAN_c8: - case PIXMAN_x4a4: - /* case PIXMAN_x4c4: */ - case PIXMAN_x4g4: - case PIXMAN_a4: - case PIXMAN_r1g2b1: - case PIXMAN_b1g2r1: - case PIXMAN_a1r1g1b1: - case PIXMAN_a1b1g1r1: - case PIXMAN_c4: - case PIXMAN_g4: - case PIXMAN_a1: - case PIXMAN_g1: - case PIXMAN_yuy2: - case PIXMAN_yv12: - case PIXMAN_x2r10g10b10: - case PIXMAN_a2r10g10b10: - case PIXMAN_r8g8b8x8: - case PIXMAN_r8g8b8a8: - case PIXMAN_x14r6g6b6: - case PIXMAN_rgb_float: - case PIXMAN_rgba_float: - default: - return FALSE; - } -} - -/* - * Extracts pixel data from an image surface. - */ -static cairo_status_t -_cairo_gl_surface_extract_image_data (cairo_image_surface_t *image, - int x, int y, - int width, int height, - void **output) -{ - int cpp = PIXMAN_FORMAT_BPP (image->pixman_format) / 8; - char *data = _cairo_malloc_ab (width * height, cpp); - char *dst = data; - unsigned char *src = image->data + y * image->stride + x * cpp; - int i; - - if (unlikely (data == NULL)) - return CAIRO_STATUS_NO_MEMORY; - - for (i = 0; i < height; i++) { - memcpy (dst, src, width * cpp); - src += image->stride; - dst += width * cpp; - } - - *output = data; - - return CAIRO_STATUS_SUCCESS; -} - -cairo_bool_t -_cairo_gl_get_image_format_and_type (cairo_gl_flavor_t flavor, - pixman_format_code_t pixman_format, - GLenum *internal_format, GLenum *format, - GLenum *type, cairo_bool_t *has_alpha, - cairo_bool_t *needs_swap) -{ - if (flavor == CAIRO_GL_FLAVOR_DESKTOP) - return _cairo_gl_get_image_format_and_type_gl (pixman_format, - internal_format, format, - type, has_alpha, - needs_swap); - else - return _cairo_gl_get_image_format_and_type_gles2 (pixman_format, - internal_format, format, - type, has_alpha, - needs_swap); - -} - -cairo_bool_t -_cairo_gl_operator_is_supported (cairo_operator_t op) -{ - return op < CAIRO_OPERATOR_SATURATE; -} - -static void -_cairo_gl_surface_embedded_operand_init (cairo_gl_surface_t *surface) -{ - cairo_gl_operand_t *operand = &surface->operand; - cairo_surface_attributes_t *attributes = &operand->texture.attributes; - - memset (operand, 0, sizeof (cairo_gl_operand_t)); - - operand->type = CAIRO_GL_OPERAND_TEXTURE; - operand->texture.surface = surface; - operand->texture.tex = surface->tex; - - if (_cairo_gl_device_requires_power_of_two_textures (surface->base.device)) { - cairo_matrix_init_identity (&attributes->matrix); - } else { - cairo_matrix_init_scale (&attributes->matrix, - 1.0 / surface->width, - 1.0 / surface->height); - } - - attributes->extend = CAIRO_EXTEND_NONE; - attributes->filter = CAIRO_FILTER_NEAREST; -} - -void -_cairo_gl_surface_init (cairo_device_t *device, - cairo_gl_surface_t *surface, - cairo_content_t content, - int width, int height) -{ - assert (width > 0 && height > 0); - - _cairo_surface_init (&surface->base, - &_cairo_gl_surface_backend, - device, - content, - FALSE); /* is_vector */ - - surface->width = width; - surface->height = height; - surface->needs_update = FALSE; - surface->content_in_texture = FALSE; - - _cairo_gl_surface_embedded_operand_init (surface); -} - -static cairo_bool_t -_cairo_gl_surface_size_valid_for_context (cairo_gl_context_t *ctx, - int width, int height) -{ - return width > 0 && height > 0 && - width <= ctx->max_framebuffer_size && - height <= ctx->max_framebuffer_size; -} - -static cairo_bool_t -_cairo_gl_surface_size_valid (cairo_gl_surface_t *surface, - int width, int height) -{ - cairo_gl_context_t *ctx = (cairo_gl_context_t *)surface->base.device; - return _cairo_gl_surface_size_valid_for_context (ctx, width, height); -} - -static cairo_surface_t * -_cairo_gl_surface_create_scratch_for_texture (cairo_gl_context_t *ctx, - cairo_content_t content, - GLuint tex, - int width, - int height) -{ - cairo_gl_surface_t *surface; - - surface = calloc (1, sizeof (cairo_gl_surface_t)); - if (unlikely (surface == NULL)) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - - surface->tex = tex; - _cairo_gl_surface_init (&ctx->base, surface, content, width, height); - - surface->supports_msaa = ctx->supports_msaa; - surface->num_samples = ctx->num_samples; - surface->supports_stencil = TRUE; - - /* Create the texture used to store the surface's data. */ - _cairo_gl_context_activate (ctx, CAIRO_GL_TEX_TEMP); - glBindTexture (ctx->tex_target, surface->tex); - glTexParameteri (ctx->tex_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri (ctx->tex_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - - return &surface->base; -} - -static cairo_surface_t * -_create_scratch_internal (cairo_gl_context_t *ctx, - cairo_content_t content, - int width, - int height, - cairo_bool_t for_caching) -{ - cairo_gl_surface_t *surface; - GLenum format; - GLuint tex; - - glGenTextures (1, &tex); - surface = (cairo_gl_surface_t *) - _cairo_gl_surface_create_scratch_for_texture (ctx, content, - tex, width, height); - if (unlikely (surface->base.status)) - return &surface->base; - - surface->owns_tex = TRUE; - - /* adjust the texture size after setting our real extents */ - if (width < 1) - width = 1; - if (height < 1) - height = 1; - - switch (content) { - default: - ASSERT_NOT_REACHED; - case CAIRO_CONTENT_COLOR_ALPHA: - format = GL_RGBA; - break; - case CAIRO_CONTENT_ALPHA: - /* When using GL_ALPHA, compositing doesn't work properly, but for - * caching surfaces, we are just uploading pixel data, so it isn't - * an issue. */ - if (for_caching) - format = GL_ALPHA; - else - format = GL_RGBA; - break; - case CAIRO_CONTENT_COLOR: - /* GL_RGB is almost what we want here -- sampling 1 alpha when - * texturing, using 1 as destination alpha factor in blending, - * etc. However, when filtering with GL_CLAMP_TO_BORDER, the - * alpha channel of the border color will also be clamped to - * 1, when we actually want the border color we explicitly - * specified. So, we have to store RGBA, and fill the alpha - * channel with 1 when blending. - */ - format = GL_RGBA; - break; - } - - glTexImage2D (ctx->tex_target, 0, format, width, height, 0, - format, GL_UNSIGNED_BYTE, NULL); - - return &surface->base; -} - -cairo_surface_t * -_cairo_gl_surface_create_scratch (cairo_gl_context_t *ctx, - cairo_content_t content, - int width, - int height) -{ - return _create_scratch_internal (ctx, content, width, height, FALSE); -} - -cairo_surface_t * -_cairo_gl_surface_create_scratch_for_caching (cairo_gl_context_t *ctx, - cairo_content_t content, - int width, - int height) -{ - return _create_scratch_internal (ctx, content, width, height, TRUE); -} - -static cairo_status_t -_cairo_gl_surface_clear (cairo_gl_surface_t *surface, - const cairo_color_t *color) -{ - cairo_gl_context_t *ctx; - cairo_status_t status; - double r, g, b, a; - - status = _cairo_gl_context_acquire (surface->base.device, &ctx); - if (unlikely (status)) - return status; - - _cairo_gl_context_set_destination (ctx, surface, surface->msaa_active); - if (surface->base.content & CAIRO_CONTENT_COLOR) { - r = color->red * color->alpha; - g = color->green * color->alpha; - b = color->blue * color->alpha; - } else { - r = g = b = 0; - } - if (surface->base.content & CAIRO_CONTENT_ALPHA) { - a = color->alpha; - } else { - a = 1.0; - } - - glDisable (GL_SCISSOR_TEST); - glClearColor (r, g, b, a); - glClear (GL_COLOR_BUFFER_BIT); - - if (a == 0) - surface->base.is_clear = TRUE; - - return _cairo_gl_context_release (ctx, status); -} - -static cairo_surface_t * -_cairo_gl_surface_create_and_clear_scratch (cairo_gl_context_t *ctx, - cairo_content_t content, - int width, - int height) -{ - cairo_gl_surface_t *surface; - cairo_int_status_t status; - - surface = (cairo_gl_surface_t *) - _cairo_gl_surface_create_scratch (ctx, content, width, height); - if (unlikely (surface->base.status)) - return &surface->base; - - /* Cairo surfaces start out initialized to transparent (black) */ - status = _cairo_gl_surface_clear (surface, CAIRO_COLOR_TRANSPARENT); - if (unlikely (status)) { - cairo_surface_destroy (&surface->base); - return _cairo_surface_create_in_error (status); - } - - return &surface->base; -} - -cairo_surface_t * -cairo_gl_surface_create (cairo_device_t *abstract_device, - cairo_content_t content, - int width, - int height) -{ - cairo_gl_context_t *ctx; - cairo_gl_surface_t *surface; - cairo_status_t status; - - if (! CAIRO_CONTENT_VALID (content)) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_CONTENT)); - - if (abstract_device == NULL) - return _cairo_image_surface_create_with_content (content, width, height); - - if (abstract_device->status) - return _cairo_surface_create_in_error (abstract_device->status); - - if (abstract_device->backend->type != CAIRO_DEVICE_TYPE_GL) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH)); - - status = _cairo_gl_context_acquire (abstract_device, &ctx); - if (unlikely (status)) - return _cairo_surface_create_in_error (status); - - if (! _cairo_gl_surface_size_valid_for_context (ctx, width, height)) { - status = _cairo_gl_context_release (ctx, status); - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE)); - } - - surface = (cairo_gl_surface_t *) - _cairo_gl_surface_create_and_clear_scratch (ctx, content, width, height); - if (unlikely (surface->base.status)) { - status = _cairo_gl_context_release (ctx, surface->base.status); - cairo_surface_destroy (&surface->base); - return _cairo_surface_create_in_error (status); - } - - status = _cairo_gl_context_release (ctx, status); - if (unlikely (status)) { - cairo_surface_destroy (&surface->base); - return _cairo_surface_create_in_error (status); - } - - return &surface->base; -} -slim_hidden_def (cairo_gl_surface_create); - -/** - * cairo_gl_surface_create_for_texture: - * @content: type of content in the surface - * @tex: name of texture to use for storage of surface pixels - * @width: width of the surface, in pixels - * @height: height of the surface, in pixels - * - * Creates a GL surface for the specified texture with the specified - * content and dimensions. The texture must be kept around until the - * #cairo_surface_t is destroyed or cairo_surface_finish() is called - * on the surface. The initial contents of @tex will be used as the - * initial image contents; you must explicitly clear the buffer, - * using, for example, cairo_rectangle() and cairo_fill() if you want - * it cleared. The format of @tex should be compatible with @content, - * in the sense that it must have the color components required by - * @content. - * - * Return value: a pointer to the newly created surface. The caller - * owns the surface and should call cairo_surface_destroy() when done - * with it. - * - * This function always returns a valid pointer, but it will return a - * pointer to a "nil" surface if an error such as out of memory - * occurs. You can use cairo_surface_status() to check for this. - * - * Since: TBD - **/ -cairo_surface_t * -cairo_gl_surface_create_for_texture (cairo_device_t *abstract_device, - cairo_content_t content, - unsigned int tex, - int width, - int height) -{ - cairo_gl_context_t *ctx; - cairo_gl_surface_t *surface; - cairo_status_t status; - - if (! CAIRO_CONTENT_VALID (content)) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_CONTENT)); - - if (abstract_device == NULL) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NULL_POINTER)); - - if (abstract_device->status) - return _cairo_surface_create_in_error (abstract_device->status); - - if (abstract_device->backend->type != CAIRO_DEVICE_TYPE_GL) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_DEVICE_TYPE_MISMATCH)); - - status = _cairo_gl_context_acquire (abstract_device, &ctx); - if (unlikely (status)) - return _cairo_surface_create_in_error (status); - - if (! _cairo_gl_surface_size_valid_for_context (ctx, width, height)) { - status = _cairo_gl_context_release (ctx, status); - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE)); - } - - surface = (cairo_gl_surface_t *) - _cairo_gl_surface_create_scratch_for_texture (ctx, content, - tex, width, height); - status = _cairo_gl_context_release (ctx, status); - - return &surface->base; -} -slim_hidden_def (cairo_gl_surface_create_for_texture); - - -void -cairo_gl_surface_set_size (cairo_surface_t *abstract_surface, - int width, - int height) -{ - cairo_gl_surface_t *surface = (cairo_gl_surface_t *) abstract_surface; - - if (unlikely (abstract_surface->status)) - return; - if (unlikely (abstract_surface->finished)) { - _cairo_surface_set_error (abstract_surface, - _cairo_error (CAIRO_STATUS_SURFACE_FINISHED)); - return; - } - - if (! _cairo_surface_is_gl (abstract_surface) || - _cairo_gl_surface_is_texture (surface)) { - _cairo_surface_set_error (abstract_surface, - _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH)); - return; - } - - if (surface->width != width || surface->height != height) { - surface->needs_update = TRUE; - surface->width = width; - surface->height = height; - } -} - -int -cairo_gl_surface_get_width (cairo_surface_t *abstract_surface) -{ - cairo_gl_surface_t *surface = (cairo_gl_surface_t *) abstract_surface; - - if (! _cairo_surface_is_gl (abstract_surface)) - return 0; - - return surface->width; -} - -int -cairo_gl_surface_get_height (cairo_surface_t *abstract_surface) -{ - cairo_gl_surface_t *surface = (cairo_gl_surface_t *) abstract_surface; - - if (! _cairo_surface_is_gl (abstract_surface)) - return 0; - - return surface->height; -} - -void -cairo_gl_surface_swapbuffers (cairo_surface_t *abstract_surface) -{ - cairo_gl_surface_t *surface = (cairo_gl_surface_t *) abstract_surface; - - if (unlikely (abstract_surface->status)) - return; - if (unlikely (abstract_surface->finished)) { - _cairo_surface_set_error (abstract_surface, - _cairo_error (CAIRO_STATUS_SURFACE_FINISHED)); - return; - } - - if (! _cairo_surface_is_gl (abstract_surface)) { - _cairo_surface_set_error (abstract_surface, - CAIRO_STATUS_SURFACE_TYPE_MISMATCH); - return; - } - - if (! _cairo_gl_surface_is_texture (surface)) { - cairo_gl_context_t *ctx; - cairo_status_t status; - - status = _cairo_gl_context_acquire (surface->base.device, &ctx); - if (unlikely (status)) - return; - - /* For swapping on EGL, at least, we need a valid context/target. */ - _cairo_gl_context_set_destination (ctx, surface, FALSE); - /* And in any case we should flush any pending operations. */ - _cairo_gl_composite_flush (ctx); - - ctx->swap_buffers (ctx, surface); - - status = _cairo_gl_context_release (ctx, status); - if (status) - status = _cairo_surface_set_error (abstract_surface, status); - } -} - -static cairo_surface_t * -_cairo_gl_surface_create_similar (void *abstract_surface, - cairo_content_t content, - int width, - int height) -{ - cairo_surface_t *surface = abstract_surface; - cairo_gl_context_t *ctx; - cairo_status_t status; - - if (! _cairo_gl_surface_size_valid (abstract_surface, width, height)) - return _cairo_image_surface_create_with_content (content, width, height); - - status = _cairo_gl_context_acquire (surface->device, &ctx); - if (unlikely (status)) - return _cairo_surface_create_in_error (status); - - surface = _cairo_gl_surface_create_and_clear_scratch (ctx, content, width, height); - - status = _cairo_gl_context_release (ctx, status); - if (unlikely (status)) { - cairo_surface_destroy (surface); - return _cairo_surface_create_in_error (status); - } - - return surface; -} - -static cairo_int_status_t -_cairo_gl_surface_fill_alpha_channel (cairo_gl_surface_t *dst, - cairo_gl_context_t *ctx, - int x, int y, - int width, int height) -{ - cairo_gl_composite_t setup; - cairo_status_t status; - - _cairo_gl_composite_flush (ctx); - glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE); - - status = _cairo_gl_composite_init (&setup, CAIRO_OPERATOR_SOURCE, - dst, FALSE); - if (unlikely (status)) - goto CLEANUP; - - _cairo_gl_composite_set_solid_source (&setup, CAIRO_COLOR_BLACK); - - status = _cairo_gl_composite_begin (&setup, &ctx); - if (unlikely (status)) - goto CLEANUP; - - _cairo_gl_context_emit_rect (ctx, x, y, x + width, y + height); - - status = _cairo_gl_context_release (ctx, status); - - CLEANUP: - _cairo_gl_composite_fini (&setup); - - _cairo_gl_composite_flush (ctx); - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - - return status; -} - -cairo_status_t -_cairo_gl_surface_draw_image (cairo_gl_surface_t *dst, - cairo_image_surface_t *src, - int src_x, int src_y, - int width, int height, - int dst_x, int dst_y, - cairo_bool_t force_flush) -{ - GLenum internal_format, format, type; - cairo_bool_t has_alpha, needs_swap; - cairo_image_surface_t *clone = NULL; - cairo_gl_context_t *ctx; - int cpp; - cairo_image_surface_t *rgba_clone = NULL; - cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS; - - status = _cairo_gl_context_acquire (dst->base.device, &ctx); - if (unlikely (status)) - return status; - - if (_cairo_gl_get_flavor () == CAIRO_GL_FLAVOR_ES3 || - _cairo_gl_get_flavor () == CAIRO_GL_FLAVOR_ES2) { - pixman_format_code_t pixman_format; - cairo_surface_pattern_t pattern; - cairo_bool_t require_conversion = FALSE; - pixman_format = _cairo_is_little_endian () ? PIXMAN_a8b8g8r8 : PIXMAN_r8g8b8a8; - - if (src->base.content != CAIRO_CONTENT_ALPHA) { - if (src->pixman_format != pixman_format) - require_conversion = TRUE; - } - else if (dst->base.content != CAIRO_CONTENT_ALPHA) { - require_conversion = TRUE; - } - else if (src->pixman_format != PIXMAN_a8) { - pixman_format = PIXMAN_a8; - require_conversion = TRUE; - } - - if (require_conversion) { - rgba_clone = (cairo_image_surface_t *) - _cairo_image_surface_create_with_pixman_format (NULL, - pixman_format, - src->width, - src->height, - 0); - if (unlikely (rgba_clone->base.status)) - goto FAIL; - - _cairo_pattern_init_for_surface (&pattern, &src->base); - status = _cairo_surface_paint (&rgba_clone->base, - CAIRO_OPERATOR_SOURCE, - &pattern.base, NULL); - _cairo_pattern_fini (&pattern.base); - if (unlikely (status)) - goto FAIL; - - src = rgba_clone; - } - } - - if (! _cairo_gl_get_image_format_and_type (ctx->gl_flavor, - src->pixman_format, - &internal_format, - &format, - &type, - &has_alpha, - &needs_swap)) - { - cairo_bool_t is_supported; - - clone = _cairo_image_surface_coerce (src); - if (unlikely (status = clone->base.status)) - goto FAIL; - - is_supported = - _cairo_gl_get_image_format_and_type (ctx->gl_flavor, - clone->pixman_format, - &internal_format, - &format, - &type, - &has_alpha, - &needs_swap); - assert (is_supported); - assert (!needs_swap); - src = clone; - } - - cpp = PIXMAN_FORMAT_BPP (src->pixman_format) / 8; - - if (force_flush) { - status = _cairo_gl_surface_flush (&dst->base, 0); - if (unlikely (status)) - goto FAIL; - } - - if (_cairo_gl_surface_is_texture (dst)) { - void *data_start = src->data + src_y * src->stride + src_x * cpp; - void *data_start_gles2 = NULL; - - /* - * Due to GL_UNPACK_ROW_LENGTH missing in GLES2 we have to extract the - * image data ourselves in some cases. In particular, we must extract - * the pixels if: - * a. we don't want full-length lines or - * b. the row stride cannot be handled by GL itself using a 4 byte - * alignment constraint - */ - if (src->stride < 0 || - (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES2 && - (src->width * cpp < src->stride - 3 || - width != src->width))) - { - glPixelStorei (GL_UNPACK_ALIGNMENT, 1); - status = _cairo_gl_surface_extract_image_data (src, src_x, src_y, - width, height, - &data_start_gles2); - if (unlikely (status)) - goto FAIL; - - data_start = data_start_gles2; - } - else - { - glPixelStorei (GL_UNPACK_ALIGNMENT, 4); - if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP || - ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3) - glPixelStorei (GL_UNPACK_ROW_LENGTH, src->stride / cpp); - } - - /* we must resolve the renderbuffer to texture before we - upload image */ - status = _cairo_gl_surface_resolve_multisampling (dst); - if (unlikely (status)) { - free (data_start_gles2); - goto FAIL; - } - - _cairo_gl_context_activate (ctx, CAIRO_GL_TEX_TEMP); - glBindTexture (ctx->tex_target, dst->tex); - glTexParameteri (ctx->tex_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri (ctx->tex_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexSubImage2D (ctx->tex_target, 0, - dst_x, dst_y, width, height, - format, type, data_start); - - free (data_start_gles2); - - /* If we just treated some rgb-only data as rgba, then we have to - * go back and fix up the alpha channel where we filled in this - * texture data. - */ - if (!has_alpha) { - _cairo_gl_surface_fill_alpha_channel (dst, ctx, - dst_x, dst_y, - width, height); - } - if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3) - dst->content_in_texture = TRUE; - } else { - cairo_surface_t *tmp; - - tmp = _cairo_gl_surface_create_scratch (ctx, - dst->base.content, - width, height); - if (unlikely (tmp->status)) - goto FAIL; - - status = _cairo_gl_surface_draw_image ((cairo_gl_surface_t *) tmp, - src, - src_x, src_y, - width, height, - 0, 0, force_flush); - if (status == CAIRO_INT_STATUS_SUCCESS) { - cairo_surface_pattern_t tmp_pattern; - cairo_rectangle_int_t r; - cairo_clip_t *clip; - - _cairo_pattern_init_for_surface (&tmp_pattern, tmp); - cairo_matrix_init_translate (&tmp_pattern.base.matrix, - -dst_x, -dst_y); - tmp_pattern.base.filter = CAIRO_FILTER_NEAREST; - tmp_pattern.base.extend = CAIRO_EXTEND_NONE; - - r.x = dst_x; - r.y = dst_y; - r.width = width; - r.height = height; - clip = _cairo_clip_intersect_rectangle (NULL, &r); - status = _cairo_surface_paint (&dst->base, - CAIRO_OPERATOR_SOURCE, - &tmp_pattern.base, - clip); - _cairo_clip_destroy (clip); - _cairo_pattern_fini (&tmp_pattern.base); - } - - cairo_surface_destroy (tmp); - if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3) - dst->content_in_texture = TRUE; - } - -FAIL: - status = _cairo_gl_context_release (ctx, status); - - if (clone) - cairo_surface_destroy (&clone->base); - - if (rgba_clone) - cairo_surface_destroy (&rgba_clone->base); - - return status; -} - -static int _cairo_gl_surface_flavor (cairo_gl_surface_t *surface) -{ - cairo_gl_context_t *ctx = (cairo_gl_context_t *)surface->base.device; - return ctx->gl_flavor; -} - -static cairo_status_t -_cairo_gl_surface_finish (void *abstract_surface) -{ - cairo_gl_surface_t *surface = abstract_surface; - cairo_status_t status; - cairo_gl_context_t *ctx; - - status = _cairo_gl_context_acquire (surface->base.device, &ctx); - if (unlikely (status)) - return status; - - if (ctx->operands[CAIRO_GL_TEX_SOURCE].type == CAIRO_GL_OPERAND_TEXTURE && - ctx->operands[CAIRO_GL_TEX_SOURCE].texture.surface == surface) - _cairo_gl_context_destroy_operand (ctx, CAIRO_GL_TEX_SOURCE); - if (ctx->operands[CAIRO_GL_TEX_MASK].type == CAIRO_GL_OPERAND_TEXTURE && - ctx->operands[CAIRO_GL_TEX_MASK].texture.surface == surface) - _cairo_gl_context_destroy_operand (ctx, CAIRO_GL_TEX_MASK); - if (ctx->current_target == surface) - ctx->current_target = NULL; - - if (surface->fb) - ctx->dispatch.DeleteFramebuffers (1, &surface->fb); - if (surface->depth_stencil) - ctx->dispatch.DeleteRenderbuffers (1, &surface->depth_stencil); - if (surface->owns_tex) - glDeleteTextures (1, &surface->tex); - - if (surface->msaa_depth_stencil) - ctx->dispatch.DeleteRenderbuffers (1, &surface->msaa_depth_stencil); - -#if CAIRO_HAS_GL_SURFACE || CAIRO_HAS_GLESV3_SURFACE - if (surface->msaa_fb) - ctx->dispatch.DeleteFramebuffers (1, &surface->msaa_fb); - if (surface->msaa_rb) - ctx->dispatch.DeleteRenderbuffers (1, &surface->msaa_rb); -#endif - - _cairo_clip_destroy (surface->clip_on_stencil_buffer); - - return _cairo_gl_context_release (ctx, status); -} - -static cairo_image_surface_t * -_cairo_gl_surface_map_to_image (void *abstract_surface, - const cairo_rectangle_int_t *extents) -{ - cairo_gl_surface_t *surface = abstract_surface; - cairo_image_surface_t *image; - cairo_gl_context_t *ctx; - GLenum format, type; - pixman_format_code_t pixman_format; - unsigned int cpp; - cairo_bool_t flipped, mesa_invert; - cairo_status_t status; - int y; - - status = _cairo_gl_context_acquire (surface->base.device, &ctx); - if (unlikely (status)) { - return _cairo_image_surface_create_in_error (status); - } - - /* Want to use a switch statement here but the compiler gets whiny. */ - if (surface->base.content == CAIRO_CONTENT_COLOR_ALPHA) { - format = GL_BGRA; - pixman_format = PIXMAN_a8r8g8b8; - type = GL_UNSIGNED_INT_8_8_8_8_REV; - cpp = 4; - } else if (surface->base.content == CAIRO_CONTENT_COLOR) { - format = GL_BGRA; - pixman_format = PIXMAN_x8r8g8b8; - type = GL_UNSIGNED_INT_8_8_8_8_REV; - cpp = 4; - } else if (surface->base.content == CAIRO_CONTENT_ALPHA) { - format = GL_ALPHA; - pixman_format = PIXMAN_a8; - type = GL_UNSIGNED_BYTE; - cpp = 1; - } else { - ASSERT_NOT_REACHED; - return NULL; - } - - if (_cairo_gl_surface_flavor (surface) == CAIRO_GL_FLAVOR_ES3 || - _cairo_gl_surface_flavor (surface) == CAIRO_GL_FLAVOR_ES2) { - /* If only RGBA is supported, we must download data in a compatible - * format. This means that pixman will convert the data on the CPU when - * interacting with other image surfaces. For ALPHA, GLES2 does not - * support GL_PACK_ROW_LENGTH anyway, and this makes sure that the - * pixman image that is created has row_stride = row_width * bpp. */ - if (surface->base.content == CAIRO_CONTENT_ALPHA || !ctx->can_read_bgra) { - cairo_bool_t little_endian = _cairo_is_little_endian (); - format = GL_RGBA; - - if (surface->base.content == CAIRO_CONTENT_COLOR) { - pixman_format = little_endian ? - PIXMAN_x8b8g8r8 : PIXMAN_r8g8b8x8; - } else { - pixman_format = little_endian ? - PIXMAN_a8b8g8r8 : PIXMAN_r8g8b8a8; - } - } - - /* GLES2 only supports GL_UNSIGNED_BYTE. */ - type = GL_UNSIGNED_BYTE; - cpp = 4; - } - - image = (cairo_image_surface_t*) - _cairo_image_surface_create_with_pixman_format (NULL, - pixman_format, - extents->width, - extents->height, - -1); - if (unlikely (image->base.status)) { - status = _cairo_gl_context_release (ctx, status); - return image; - } - - cairo_surface_set_device_offset (&image->base, -extents->x, -extents->y); - - /* If the original surface has not been modified or - * is clear, we can avoid downloading data. */ - if (surface->base.is_clear || surface->base.serial == 0) { - status = _cairo_gl_context_release (ctx, status); - return image; - } - - /* This is inefficient, as we'd rather just read the thing without making - * it the destination. But then, this is the fallback path, so let's not - * fall back instead. - */ - _cairo_gl_composite_flush (ctx); - - if (ctx->gl_flavor != CAIRO_GL_FLAVOR_ES3) { - _cairo_gl_context_set_destination (ctx, surface, FALSE); - } else { - if (surface->content_in_texture) { - _cairo_gl_ensure_framebuffer (ctx, surface); - ctx->dispatch.BindFramebuffer (GL_FRAMEBUFFER, surface->fb); - } else { - status = _cairo_gl_surface_resolve_multisampling (surface); - if (unlikely (status)) { - status = _cairo_gl_context_release (ctx, status); - cairo_surface_destroy (&image->base); - return _cairo_image_surface_create_in_error (status); - } - } - } - - flipped = ! _cairo_gl_surface_is_texture (surface); - mesa_invert = flipped && ctx->has_mesa_pack_invert; - - glPixelStorei (GL_PACK_ALIGNMENT, 4); - if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP || - ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3) - glPixelStorei (GL_PACK_ROW_LENGTH, image->stride / cpp); - if (mesa_invert) - glPixelStorei (GL_PACK_INVERT_MESA, 1); - - y = extents->y; - if (flipped) - y = surface->height - extents->y - extents->height; - - glReadPixels (extents->x, y, - extents->width, extents->height, - format, type, image->data); - if (mesa_invert) - glPixelStorei (GL_PACK_INVERT_MESA, 0); - - status = _cairo_gl_context_release (ctx, status); - if (unlikely (status)) { - cairo_surface_destroy (&image->base); - return _cairo_image_surface_create_in_error (status); - } - - /* We must invert the image manually if we lack GL_MESA_pack_invert */ - if (flipped && ! mesa_invert) { - uint8_t stack[1024], *row = stack; - uint8_t *top = image->data; - uint8_t *bot = image->data + (image->height-1)*image->stride; - - if (image->stride > (int)sizeof(stack)) { - row = _cairo_malloc (image->stride); - if (unlikely (row == NULL)) { - cairo_surface_destroy (&image->base); - return _cairo_image_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - } - } - - while (top < bot) { - memcpy (row, top, image->stride); - memcpy (top, bot, image->stride); - memcpy (bot, row, image->stride); - top += image->stride; - bot -= image->stride; - } - - if (row != stack) - free(row); - } - - image->base.is_clear = FALSE; - return image; -} - -static cairo_surface_t * -_cairo_gl_surface_source (void *abstract_surface, - cairo_rectangle_int_t *extents) -{ - cairo_gl_surface_t *surface = abstract_surface; - - if (extents) { - extents->x = extents->y = 0; - extents->width = surface->width; - extents->height = surface->height; - } - - return &surface->base; -} - -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; - cairo_rectangle_int_t extents; - - *image_extra = NULL; - - extents.x = extents.y = 0; - extents.width = surface->width; - extents.height = surface->height; - - *image_out = (cairo_image_surface_t *) - _cairo_gl_surface_map_to_image (surface, &extents); - return (*image_out)->base.status; -} - -static void -_cairo_gl_surface_release_source_image (void *abstract_surface, - cairo_image_surface_t *image, - void *image_extra) -{ - cairo_surface_destroy (&image->base); -} - -static cairo_int_status_t -_cairo_gl_surface_unmap_image (void *abstract_surface, - cairo_image_surface_t *image) -{ - cairo_int_status_t status; - - status = _cairo_gl_surface_draw_image (abstract_surface, image, - 0, 0, - image->width, image->height, - image->base.device_transform_inverse.x0, - image->base.device_transform_inverse.y0, - TRUE); - - cairo_surface_finish (&image->base); - cairo_surface_destroy (&image->base); - - return status; -} - -static cairo_bool_t -_cairo_gl_surface_get_extents (void *abstract_surface, - cairo_rectangle_int_t *rectangle) -{ - cairo_gl_surface_t *surface = abstract_surface; - - rectangle->x = 0; - rectangle->y = 0; - rectangle->width = surface->width; - rectangle->height = surface->height; - - return TRUE; -} - -static cairo_status_t -_cairo_gl_surface_flush (void *abstract_surface, unsigned flags) -{ - cairo_gl_surface_t *surface = abstract_surface; - cairo_status_t status; - cairo_gl_context_t *ctx; - - if (flags) - return CAIRO_STATUS_SUCCESS; - - status = _cairo_gl_context_acquire (surface->base.device, &ctx); - if (unlikely (status)) - return status; - - if ((ctx->operands[CAIRO_GL_TEX_SOURCE].type == CAIRO_GL_OPERAND_TEXTURE && - ctx->operands[CAIRO_GL_TEX_SOURCE].texture.surface == surface) || - (ctx->operands[CAIRO_GL_TEX_MASK].type == CAIRO_GL_OPERAND_TEXTURE && - ctx->operands[CAIRO_GL_TEX_MASK].texture.surface == surface) || - (ctx->current_target == surface)) - _cairo_gl_composite_flush (ctx); - - status = _cairo_gl_surface_resolve_multisampling (surface); - - return _cairo_gl_context_release (ctx, status); -} - -cairo_int_status_t -_cairo_gl_surface_resolve_multisampling (cairo_gl_surface_t *surface) -{ - cairo_gl_context_t *ctx; - cairo_int_status_t status; - - if (! surface->msaa_active) - return CAIRO_INT_STATUS_SUCCESS; - - if (surface->base.device == NULL) - return CAIRO_INT_STATUS_SUCCESS; - - /* GLES surfaces do not need explicit resolution. */ - if (((cairo_gl_context_t *) surface->base.device)->gl_flavor == CAIRO_GL_FLAVOR_ES2) - return CAIRO_INT_STATUS_SUCCESS; - else if (((cairo_gl_context_t *) surface->base.device)->gl_flavor == CAIRO_GL_FLAVOR_ES3 && - surface->content_in_texture) - return CAIRO_INT_STATUS_SUCCESS; - - if (! _cairo_gl_surface_is_texture (surface)) - return CAIRO_INT_STATUS_SUCCESS; - - status = _cairo_gl_context_acquire (surface->base.device, &ctx); - if (unlikely (status)) - return status; - -#if CAIRO_HAS_GLESV3_SURFACE - _cairo_gl_composite_flush (ctx); - ctx->current_target = NULL; - _cairo_gl_context_bind_framebuffer (ctx, surface, FALSE); - if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3) - surface->content_in_texture = TRUE; - -#elif CAIRO_HAS_GL_SURFACE - ctx->current_target = surface; - _cairo_gl_context_bind_framebuffer (ctx, surface, FALSE); - -#else - ctx->current_target = surface; - -#endif - - status = _cairo_gl_context_release (ctx, status); - return status; -} - -static const cairo_compositor_t * -get_compositor (cairo_gl_surface_t *surface) -{ - cairo_gl_context_t *ctx = (cairo_gl_context_t *)surface->base.device; - return ctx->compositor; -} - -static cairo_int_status_t -_cairo_gl_surface_paint (void *surface, - cairo_operator_t op, - const cairo_pattern_t *source, - const cairo_clip_t *clip) -{ - /* simplify the common case of clearing the surface */ - if (clip == NULL) { - if (op == CAIRO_OPERATOR_CLEAR) - return _cairo_gl_surface_clear (surface, CAIRO_COLOR_TRANSPARENT); - else if (source->type == CAIRO_PATTERN_TYPE_SOLID && - (op == CAIRO_OPERATOR_SOURCE || - (op == CAIRO_OPERATOR_OVER && _cairo_pattern_is_opaque_solid (source)))) { - return _cairo_gl_surface_clear (surface, - &((cairo_solid_pattern_t *) source)->color); - } - } - - return _cairo_compositor_paint (get_compositor (surface), surface, - op, source, clip); -} - -static cairo_int_status_t -_cairo_gl_surface_mask (void *surface, - cairo_operator_t op, - const cairo_pattern_t *source, - const cairo_pattern_t *mask, - const cairo_clip_t *clip) -{ - return _cairo_compositor_mask (get_compositor (surface), surface, - op, source, mask, clip); -} - -static cairo_int_status_t -_cairo_gl_surface_stroke (void *surface, - cairo_operator_t op, - const cairo_pattern_t *source, - const cairo_path_fixed_t *path, - const cairo_stroke_style_t *style, - const cairo_matrix_t *ctm, - const cairo_matrix_t *ctm_inverse, - double tolerance, - cairo_antialias_t antialias, - const cairo_clip_t *clip) -{ - return _cairo_compositor_stroke (get_compositor (surface), surface, - op, source, path, style, - ctm, ctm_inverse, tolerance, antialias, - clip); -} - -static cairo_int_status_t -_cairo_gl_surface_fill (void *surface, - cairo_operator_t op, - const cairo_pattern_t *source, - const cairo_path_fixed_t*path, - cairo_fill_rule_t fill_rule, - double tolerance, - cairo_antialias_t antialias, - const cairo_clip_t *clip) -{ - return _cairo_compositor_fill (get_compositor (surface), surface, - op, source, path, - fill_rule, tolerance, antialias, - clip); -} - -static cairo_int_status_t -_cairo_gl_surface_glyphs (void *surface, - cairo_operator_t op, - const cairo_pattern_t *source, - cairo_glyph_t *glyphs, - int num_glyphs, - cairo_scaled_font_t *font, - const cairo_clip_t *clip) -{ - return _cairo_compositor_glyphs (get_compositor (surface), surface, - op, source, glyphs, num_glyphs, font, - clip); -} - -static const cairo_surface_backend_t _cairo_gl_surface_backend = { - CAIRO_SURFACE_TYPE_GL, - _cairo_gl_surface_finish, - _cairo_default_context_create, - - _cairo_gl_surface_create_similar, - NULL, /* similar image */ - _cairo_gl_surface_map_to_image, - _cairo_gl_surface_unmap_image, - - _cairo_gl_surface_source, - _cairo_gl_surface_acquire_source_image, - _cairo_gl_surface_release_source_image, - NULL, /* snapshot */ - - NULL, /* copy_page */ - NULL, /* show_page */ - - _cairo_gl_surface_get_extents, - _cairo_image_surface_get_font_options, - - _cairo_gl_surface_flush, - NULL, /* mark_dirty_rectangle */ - - _cairo_gl_surface_paint, - _cairo_gl_surface_mask, - _cairo_gl_surface_stroke, - _cairo_gl_surface_fill, - NULL, /* fill/stroke */ - _cairo_gl_surface_glyphs, -}; diff --git a/src/cairo-gl-traps-compositor.c b/src/cairo-gl-traps-compositor.c deleted file mode 100644 index 7938c5b20..000000000 --- a/src/cairo-gl-traps-compositor.c +++ /dev/null @@ -1,531 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2009 Eric Anholt - * Copyright © 2009 Chris Wilson - * Copyright © 2005,2010 Red Hat, Inc - * Copyright © 2011 Intel Corporation - * - * 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 Red Hat, Inc. - * - * Contributor(s): - * Benjamin Otte <otte@gnome.org> - * Carl Worth <cworth@cworth.org> - * Chris Wilson <chris@chris-wilson.co.uk> - * Eric Anholt <eric@anholt.net> - */ - -#include "cairoint.h" - -#include "cairo-gl-private.h" - -#include "cairo-composite-rectangles-private.h" -#include "cairo-compositor-private.h" -#include "cairo-default-context-private.h" -#include "cairo-error-private.h" -#include "cairo-image-surface-private.h" -#include "cairo-spans-compositor-private.h" -#include "cairo-surface-backend-private.h" -#include "cairo-surface-offset-private.h" - -static cairo_int_status_t -acquire (void *abstract_dst) -{ - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -release (void *abstract_dst) -{ - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -set_clip_region (void *_surface, - cairo_region_t *region) -{ - cairo_gl_surface_t *surface = _surface; - - surface->clip_region = region; - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -draw_image_boxes (void *_dst, - cairo_image_surface_t *image, - cairo_boxes_t *boxes, - int dx, int dy) -{ - cairo_gl_surface_t *dst = _dst; - struct _cairo_boxes_chunk *chunk; - int i; - - for (chunk = &boxes->chunks; chunk; chunk = chunk->next) { - for (i = 0; i < chunk->count; i++) { - cairo_box_t *b = &chunk->base[i]; - int x = _cairo_fixed_integer_part (b->p1.x); - int y = _cairo_fixed_integer_part (b->p1.y); - int w = _cairo_fixed_integer_part (b->p2.x) - x; - int h = _cairo_fixed_integer_part (b->p2.y) - y; - cairo_status_t status; - - status = _cairo_gl_surface_draw_image (dst, image, - x + dx, y + dy, - w, h, - x, y, - TRUE); - if (unlikely (status)) - return status; - } - } - - return CAIRO_STATUS_SUCCESS; -} - -static void -emit_aligned_boxes (cairo_gl_context_t *ctx, - const cairo_boxes_t *boxes) -{ - const struct _cairo_boxes_chunk *chunk; - cairo_gl_emit_rect_t emit = _cairo_gl_context_choose_emit_rect (ctx); - int i; - - for (chunk = &boxes->chunks; chunk; chunk = chunk->next) { - for (i = 0; i < chunk->count; i++) { - int x1 = _cairo_fixed_integer_part (chunk->base[i].p1.x); - int y1 = _cairo_fixed_integer_part (chunk->base[i].p1.y); - int x2 = _cairo_fixed_integer_part (chunk->base[i].p2.x); - int y2 = _cairo_fixed_integer_part (chunk->base[i].p2.y); - emit (ctx, x1, y1, x2, y2); - } - } -} - -static cairo_int_status_t -fill_boxes (void *_dst, - cairo_operator_t op, - const cairo_color_t *color, - cairo_boxes_t *boxes) -{ - cairo_gl_composite_t setup; - cairo_gl_context_t *ctx; - cairo_int_status_t status; - - status = _cairo_gl_composite_init (&setup, op, _dst, FALSE); - if (unlikely (status)) - goto FAIL; - - _cairo_gl_composite_set_solid_source (&setup, color); - - status = _cairo_gl_composite_begin (&setup, &ctx); - if (unlikely (status)) - goto FAIL; - - emit_aligned_boxes (ctx, boxes); - status = _cairo_gl_context_release (ctx, CAIRO_STATUS_SUCCESS); - -FAIL: - _cairo_gl_composite_fini (&setup); - return status; -} - -static cairo_int_status_t -composite_boxes (void *_dst, - cairo_operator_t op, - cairo_surface_t *abstract_src, - cairo_surface_t *abstract_mask, - int src_x, - int src_y, - int mask_x, - int mask_y, - int dst_x, - int dst_y, - cairo_boxes_t *boxes, - const cairo_rectangle_int_t *extents) -{ - cairo_gl_composite_t setup; - cairo_gl_context_t *ctx; - cairo_int_status_t status; - - status = _cairo_gl_composite_init (&setup, op, _dst, FALSE); - if (unlikely (status)) - goto FAIL; - - _cairo_gl_composite_set_source_operand (&setup, - source_to_operand (abstract_src)); - _cairo_gl_operand_translate (&setup.src, dst_x-src_x, dst_y-src_y); - - _cairo_gl_composite_set_mask_operand (&setup, - source_to_operand (abstract_mask)); - _cairo_gl_operand_translate (&setup.mask, dst_x-mask_x, dst_y-mask_y); - - status = _cairo_gl_composite_begin (&setup, &ctx); - if (unlikely (status)) - goto FAIL; - - emit_aligned_boxes (ctx, boxes); - status = _cairo_gl_context_release (ctx, CAIRO_STATUS_SUCCESS); - -FAIL: - _cairo_gl_composite_fini (&setup); - return status; -} - -static cairo_int_status_t -composite (void *_dst, - cairo_operator_t op, - cairo_surface_t *abstract_src, - cairo_surface_t *abstract_mask, - int src_x, - int src_y, - int mask_x, - int mask_y, - int dst_x, - int dst_y, - unsigned int width, - unsigned int height) -{ - cairo_gl_composite_t setup; - cairo_gl_context_t *ctx; - cairo_int_status_t status; - - status = _cairo_gl_composite_init (&setup, op, _dst, FALSE); - if (unlikely (status)) - goto FAIL; - - _cairo_gl_composite_set_source_operand (&setup, - source_to_operand (abstract_src)); - _cairo_gl_operand_translate (&setup.src, dst_x-src_x, dst_y-src_y); - - _cairo_gl_composite_set_mask_operand (&setup, - source_to_operand (abstract_mask)); - _cairo_gl_operand_translate (&setup.mask, dst_x-mask_x, dst_y-mask_y); - - status = _cairo_gl_composite_begin (&setup, &ctx); - if (unlikely (status)) - goto FAIL; - - /* XXX clip */ - _cairo_gl_context_emit_rect (ctx, dst_x, dst_y, dst_x+width, dst_y+height); - status = _cairo_gl_context_release (ctx, CAIRO_STATUS_SUCCESS); - -FAIL: - _cairo_gl_composite_fini (&setup); - return status; -} - -static cairo_int_status_t -lerp (void *dst, - cairo_surface_t *src, - cairo_surface_t *mask, - int src_x, - int src_y, - int mask_x, - int mask_y, - int dst_x, - int dst_y, - unsigned int width, - unsigned int height) -{ - cairo_int_status_t status; - - /* we could avoid some repetition... */ - status = composite (dst, CAIRO_OPERATOR_DEST_OUT, mask, NULL, - mask_x, mask_y, - 0, 0, - dst_x, dst_y, - width, height); - if (unlikely (status)) - return status; - - status = composite (dst, CAIRO_OPERATOR_ADD, src, mask, - src_x, src_y, - mask_x, mask_y, - dst_x, dst_y, - width, height); - if (unlikely (status)) - return status; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -traps_to_operand (void *_dst, - const cairo_rectangle_int_t *extents, - cairo_antialias_t antialias, - cairo_traps_t *traps, - cairo_gl_operand_t *operand, - int dst_x, int dst_y) -{ - pixman_format_code_t pixman_format; - pixman_image_t *pixman_image; - cairo_surface_t *image, *mask; - cairo_surface_pattern_t pattern; - cairo_status_t status; - - pixman_format = antialias != CAIRO_ANTIALIAS_NONE ? PIXMAN_a8 : PIXMAN_a1; - pixman_image = pixman_image_create_bits (pixman_format, - extents->width, - extents->height, - NULL, 0); - if (unlikely (pixman_image == NULL)) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - _pixman_image_add_traps (pixman_image, extents->x, extents->y, traps); - image = _cairo_image_surface_create_for_pixman_image (pixman_image, - pixman_format); - if (unlikely (image->status)) { - pixman_image_unref (pixman_image); - return image->status; - } - - mask = _cairo_surface_create_scratch (_dst, - CAIRO_CONTENT_COLOR_ALPHA, - extents->width, - extents->height, - NULL); - if (unlikely (mask->status)) { - cairo_surface_destroy (image); - return mask->status; - } - - status = _cairo_gl_surface_draw_image ((cairo_gl_surface_t *)mask, - (cairo_image_surface_t *)image, - 0, 0, - extents->width, extents->height, - 0, 0, - TRUE); - cairo_surface_destroy (image); - - if (unlikely (status)) - goto error; - - _cairo_pattern_init_for_surface (&pattern, mask); - cairo_matrix_init_translate (&pattern.base.matrix, - -extents->x+dst_x, -extents->y+dst_y); - pattern.base.filter = CAIRO_FILTER_NEAREST; - pattern.base.extend = CAIRO_EXTEND_NONE; - status = _cairo_gl_operand_init (operand, &pattern.base, _dst, - &_cairo_unbounded_rectangle, - &_cairo_unbounded_rectangle, - FALSE); - _cairo_pattern_fini (&pattern.base); - - if (unlikely (status)) - goto error; - - operand->texture.owns_surface = (cairo_gl_surface_t *)mask; - return CAIRO_STATUS_SUCCESS; - -error: - cairo_surface_destroy (mask); - return status; -} - -static cairo_int_status_t -composite_traps (void *_dst, - cairo_operator_t op, - cairo_surface_t *abstract_src, - int src_x, - int src_y, - int dst_x, - int dst_y, - const cairo_rectangle_int_t *extents, - cairo_antialias_t antialias, - cairo_traps_t *traps) -{ - cairo_gl_composite_t setup; - cairo_gl_context_t *ctx; - cairo_int_status_t status; - - status = _cairo_gl_composite_init (&setup, op, _dst, FALSE); - if (unlikely (status)) - goto FAIL; - - _cairo_gl_composite_set_source_operand (&setup, - source_to_operand (abstract_src)); - _cairo_gl_operand_translate (&setup.src, -src_x-dst_x, -src_y-dst_y); - status = traps_to_operand (_dst, extents, antialias, traps, &setup.mask, dst_x, dst_y); - if (unlikely (status)) - goto FAIL; - - status = _cairo_gl_composite_begin (&setup, &ctx); - if (unlikely (status)) - goto FAIL; - - /* XXX clip */ - _cairo_gl_context_emit_rect (ctx, - extents->x-dst_x, extents->y-dst_y, - extents->x-dst_x+extents->width, - extents->y-dst_y+extents->height); - status = _cairo_gl_context_release (ctx, CAIRO_STATUS_SUCCESS); - -FAIL: - _cairo_gl_composite_fini (&setup); - return status; -} - -static cairo_gl_surface_t * -tristrip_to_surface (void *_dst, - const cairo_rectangle_int_t *extents, - cairo_antialias_t antialias, - cairo_tristrip_t *strip) -{ - pixman_format_code_t pixman_format; - pixman_image_t *pixman_image; - cairo_surface_t *image, *mask; - cairo_status_t status; - - pixman_format = antialias != CAIRO_ANTIALIAS_NONE ? PIXMAN_a8 : PIXMAN_a1, - pixman_image = pixman_image_create_bits (pixman_format, - extents->width, - extents->height, - NULL, 0); - if (unlikely (pixman_image == NULL)) - return (cairo_gl_surface_t *)_cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - - _pixman_image_add_tristrip (pixman_image, extents->x, extents->y, strip); - image = _cairo_image_surface_create_for_pixman_image (pixman_image, - pixman_format); - if (unlikely (image->status)) { - pixman_image_unref (pixman_image); - return (cairo_gl_surface_t *)image; - } - - mask = _cairo_surface_create_scratch (_dst, - CAIRO_CONTENT_COLOR_ALPHA, - extents->width, - extents->height, - NULL); - if (unlikely (mask->status)) { - cairo_surface_destroy (image); - return (cairo_gl_surface_t *)mask; - } - - status = _cairo_gl_surface_draw_image ((cairo_gl_surface_t *)mask, - (cairo_image_surface_t *)image, - 0, 0, - extents->width, extents->height, - 0, 0, - TRUE); - cairo_surface_destroy (image); - if (unlikely (status)) { - cairo_surface_destroy (mask); - return (cairo_gl_surface_t*)_cairo_surface_create_in_error (status); - } - - return (cairo_gl_surface_t*)mask; -} - -static cairo_int_status_t -composite_tristrip (void *_dst, - cairo_operator_t op, - cairo_surface_t *abstract_src, - int src_x, - int src_y, - int dst_x, - int dst_y, - const cairo_rectangle_int_t *extents, - cairo_antialias_t antialias, - cairo_tristrip_t *strip) -{ - cairo_gl_composite_t setup; - cairo_gl_context_t *ctx; - cairo_gl_surface_t *mask; - cairo_int_status_t status; - - mask = tristrip_to_surface (_dst, extents, antialias, strip); - if (unlikely (mask->base.status)) - return mask->base.status; - - status = _cairo_gl_composite_init (&setup, op, _dst, FALSE); - if (unlikely (status)) - goto FAIL; - - _cairo_gl_composite_set_source_operand (&setup, - source_to_operand (abstract_src)); - - //_cairo_gl_composite_set_mask_surface (&setup, mask, 0, 0); - - status = _cairo_gl_composite_begin (&setup, &ctx); - if (unlikely (status)) - goto FAIL; - - /* XXX clip */ - _cairo_gl_context_emit_rect (ctx, - dst_x, dst_y, - dst_x+extents->width, - dst_y+extents->height); - status = _cairo_gl_context_release (ctx, CAIRO_STATUS_SUCCESS); - -FAIL: - _cairo_gl_composite_fini (&setup); - cairo_surface_destroy (&mask->base); - return status; -} - -static cairo_int_status_t -check_composite (const cairo_composite_rectangles_t *extents) -{ - if (! _cairo_gl_operator_is_supported (extents->op)) - return UNSUPPORTED ("unsupported operator"); - - return CAIRO_STATUS_SUCCESS; -} - -const cairo_compositor_t * -_cairo_gl_traps_compositor_get (void) -{ - static cairo_atomic_once_t once = CAIRO_ATOMIC_ONCE_INIT; - static cairo_traps_compositor_t compositor; - - if (_cairo_atomic_init_once_enter(&once)) { - _cairo_traps_compositor_init (&compositor, &_cairo_fallback_compositor); - compositor.acquire = acquire; - compositor.release = release; - compositor.set_clip_region = set_clip_region; - compositor.pattern_to_surface = _cairo_gl_pattern_to_source; - compositor.draw_image_boxes = draw_image_boxes; - //compositor.copy_boxes = copy_boxes; - compositor.fill_boxes = fill_boxes; - compositor.check_composite = check_composite; - compositor.composite = composite; - compositor.lerp = lerp; - //compositor.check_composite_boxes = check_composite_boxes; - compositor.composite_boxes = composite_boxes; - //compositor.check_composite_traps = check_composite_traps; - compositor.composite_traps = composite_traps; - //compositor.check_composite_tristrip = check_composite_traps; - compositor.composite_tristrip = composite_tristrip; - compositor.check_composite_glyphs = _cairo_gl_check_composite_glyphs; - compositor.composite_glyphs = _cairo_gl_composite_glyphs; - - _cairo_atomic_init_once_leave(&once); - } - - return &compositor.base; -} diff --git a/src/cairo-gl.h b/src/cairo-gl.h deleted file mode 100644 index 7cd869c76..000000000 --- a/src/cairo-gl.h +++ /dev/null @@ -1,155 +0,0 @@ -/* 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., 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 Eric Anholt. - */ - -/* - * cairo-gl.h: - * - * The cairo-gl backend provides an implementation of possibly - * hardware-accelerated cairo rendering by targeting the OpenGL API. - * The goal of the cairo-gl backend is to provide better performance - * with equal functionality to cairo-image where possible. It does - * not directly provide for applying additional OpenGL effects to - * cairo surfaces. - * - * Cairo-gl allows interoperability with other GL rendering through GL - * context sharing. Cairo-gl surfaces are created in reference to a - * #cairo_device_t, which represents a GL context created by the user. - * When that GL context is created with its sharePtr set to another - * context (or vice versa), its objects (textures backing cairo-gl - * surfaces) can be accessed in the other OpenGL context. This allows - * cairo-gl to maintain its drawing state in one context while the - * user's 3D rendering occurs in the user's other context. - * - * However, as only one context can be current to a thread at a time, - * cairo-gl may make its context current to the thread on any cairo - * call which interacts with a cairo-gl surface or the cairo-gl - * device. As a result, the user must make their own context current - * between any cairo calls and their own OpenGL rendering. - **/ - -#ifndef CAIRO_GL_H -#define CAIRO_GL_H - -#include "cairo.h" - -#if CAIRO_HAS_GL_SURFACE || CAIRO_HAS_GLESV2_SURFACE || CAIRO_HAS_GLESV3_SURFACE - -CAIRO_BEGIN_DECLS - -cairo_public cairo_surface_t * -cairo_gl_surface_create (cairo_device_t *device, - cairo_content_t content, - int width, int height); - -cairo_public cairo_surface_t * -cairo_gl_surface_create_for_texture (cairo_device_t *abstract_device, - cairo_content_t content, - unsigned int tex, - int width, int height); -cairo_public void -cairo_gl_surface_set_size (cairo_surface_t *surface, int width, int height); - -cairo_public int -cairo_gl_surface_get_width (cairo_surface_t *abstract_surface); - -cairo_public int -cairo_gl_surface_get_height (cairo_surface_t *abstract_surface); - -cairo_public void -cairo_gl_surface_swapbuffers (cairo_surface_t *surface); - -cairo_public void -cairo_gl_device_set_thread_aware (cairo_device_t *device, - cairo_bool_t thread_aware); - -#if CAIRO_HAS_GLX_FUNCTIONS -#include <GL/glx.h> - -cairo_public cairo_device_t * -cairo_glx_device_create (Display *dpy, GLXContext gl_ctx); - -cairo_public Display * -cairo_glx_device_get_display (cairo_device_t *device); - -cairo_public GLXContext -cairo_glx_device_get_context (cairo_device_t *device); - -cairo_public cairo_surface_t * -cairo_gl_surface_create_for_window (cairo_device_t *device, - Window win, - int width, int height); -#endif - -#if CAIRO_HAS_WGL_FUNCTIONS -#include <windows.h> - -cairo_public cairo_device_t * -cairo_wgl_device_create (HGLRC rc); - -cairo_public HGLRC -cairo_wgl_device_get_context (cairo_device_t *device); - -cairo_public cairo_surface_t * -cairo_gl_surface_create_for_dc (cairo_device_t *device, - HDC dc, - int width, - int height); -#endif - -#if CAIRO_HAS_EGL_FUNCTIONS -#include <EGL/egl.h> - -cairo_public cairo_device_t * -cairo_egl_device_create (EGLDisplay dpy, EGLContext egl); - -cairo_public cairo_surface_t * -cairo_gl_surface_create_for_egl (cairo_device_t *device, - EGLSurface egl, - int width, - int height); - -cairo_public EGLDisplay -cairo_egl_device_get_display (cairo_device_t *device); - -cairo_public EGLSurface -cairo_egl_device_get_context (cairo_device_t *device); - -#endif - -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-glx-context.c b/src/cairo-glx-context.c deleted file mode 100644 index 66f5a0d1b..000000000 --- a/src/cairo-glx-context.c +++ /dev/null @@ -1,324 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2009 Eric Anholt - * Copyright © 2009 Chris Wilson - * 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., 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 Red Hat, Inc. - * - * Contributor(s): - * Carl Worth <cworth@cworth.org> - * Chris Wilson <chris@chris-wilson.co.uk> - */ - -#include "cairoint.h" - -#include "cairo-gl-private.h" - -#include "cairo-error-private.h" - -#include <X11/Xutil.h> - -/* XXX needs hooking into XCloseDisplay() */ - -typedef struct _cairo_glx_context { - cairo_gl_context_t base; - - Display *display; - Window dummy_window; - GLXContext context; - - GLXDrawable previous_drawable; - GLXContext previous_context; - - cairo_bool_t has_multithread_makecurrent; -} cairo_glx_context_t; - -typedef struct _cairo_glx_surface { - cairo_gl_surface_t base; - - Window win; -} cairo_glx_surface_t; - -static cairo_bool_t -_context_acquisition_changed_glx_state (cairo_glx_context_t *ctx, - GLXDrawable current_drawable) -{ - return ctx->previous_drawable != current_drawable || - ctx->previous_context != ctx->context; -} - -static GLXDrawable -_glx_get_current_drawable (cairo_glx_context_t *ctx) -{ - if (ctx->base.current_target == NULL || - _cairo_gl_surface_is_texture (ctx->base.current_target)) { - return ctx->dummy_window; - } - - return ((cairo_glx_surface_t *) ctx->base.current_target)->win; -} - -static void -_glx_query_current_state (cairo_glx_context_t * ctx) -{ - ctx->previous_drawable = glXGetCurrentDrawable (); - ctx->previous_context = glXGetCurrentContext (); - - /* If any of the values were none, assume they are all none. Not all - drivers seem well behaved when it comes to using these values across - multiple threads. */ - if (ctx->previous_drawable == None || - ctx->previous_context == None) { - ctx->previous_drawable = None; - ctx->previous_context = None; - } -} - -static void -_glx_acquire (void *abstract_ctx) -{ - cairo_glx_context_t *ctx = abstract_ctx; - GLXDrawable current_drawable = _glx_get_current_drawable (ctx); - - _glx_query_current_state (ctx); - if (!_context_acquisition_changed_glx_state (ctx, current_drawable)) - return; - - glXMakeCurrent (ctx->display, current_drawable, ctx->context); -} - -static void -_glx_make_current (void *abstract_ctx, cairo_gl_surface_t *abstract_surface) -{ - cairo_glx_context_t *ctx = abstract_ctx; - cairo_glx_surface_t *surface = (cairo_glx_surface_t *) abstract_surface; - - /* Set the window as the target of our context. */ - glXMakeCurrent (ctx->display, surface->win, ctx->context); -} - -static void -_glx_release (void *abstract_ctx) -{ - cairo_glx_context_t *ctx = abstract_ctx; - - if (ctx->has_multithread_makecurrent || !ctx->base.thread_aware || - !_context_acquisition_changed_glx_state (ctx, - _glx_get_current_drawable (ctx))) { - return; - } - - glXMakeCurrent (ctx->display, None, None); -} - -static void -_glx_swap_buffers (void *abstract_ctx, - cairo_gl_surface_t *abstract_surface) -{ - cairo_glx_context_t *ctx = abstract_ctx; - cairo_glx_surface_t *surface = (cairo_glx_surface_t *) abstract_surface; - - glXSwapBuffers (ctx->display, surface->win); -} - -static void -_glx_destroy (void *abstract_ctx) -{ - cairo_glx_context_t *ctx = abstract_ctx; - - if (ctx->dummy_window != None) - XDestroyWindow (ctx->display, ctx->dummy_window); - - glXMakeCurrent (ctx->display, None, None); -} - -static cairo_status_t -_glx_dummy_window (Display *dpy, GLXContext gl_ctx, Window *dummy) -{ - int attr[3] = { GLX_FBCONFIG_ID, 0, None }; - GLXFBConfig *config; - XVisualInfo *vi; - Colormap cmap; - XSetWindowAttributes swa; - Window win = None; - int cnt; - - /* Create a dummy window created for the target GLX context that we can - * use to query the available GL/GLX extensions. - */ - glXQueryContext (dpy, gl_ctx, GLX_FBCONFIG_ID, &attr[1]); - - cnt = 0; - config = glXChooseFBConfig (dpy, DefaultScreen (dpy), attr, &cnt); - if (unlikely (cnt == 0)) - return _cairo_error (CAIRO_STATUS_INVALID_FORMAT); - - vi = glXGetVisualFromFBConfig (dpy, config[0]); - XFree (config); - - if (unlikely (vi == NULL)) - return _cairo_error (CAIRO_STATUS_INVALID_FORMAT); - - cmap = XCreateColormap (dpy, - RootWindow (dpy, vi->screen), - vi->visual, - AllocNone); - swa.colormap = cmap; - swa.border_pixel = 0; - win = XCreateWindow (dpy, RootWindow (dpy, vi->screen), - -1, -1, 1, 1, 0, - vi->depth, - InputOutput, - vi->visual, - CWBorderPixel | CWColormap, &swa); - XFreeColormap (dpy, cmap); - XFree (vi); - - XFlush (dpy); - if (unlikely (! glXMakeCurrent (dpy, win, gl_ctx))) { - XDestroyWindow (dpy, win); - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } - - *dummy = win; - return CAIRO_STATUS_SUCCESS; -} - -cairo_device_t * -cairo_glx_device_create (Display *dpy, GLXContext gl_ctx) -{ - cairo_glx_context_t *ctx; - cairo_status_t status; - Window dummy = None; - const char *glx_extensions; - - ctx = calloc (1, sizeof (cairo_glx_context_t)); - if (unlikely (ctx == NULL)) - return _cairo_gl_context_create_in_error (CAIRO_STATUS_NO_MEMORY); - - /* glx_dummy_window will call glXMakeCurrent, so we need to - * query the current state of the context now. */ - _glx_query_current_state (ctx); - - status = _glx_dummy_window (dpy, gl_ctx, &dummy); - if (unlikely (status)) { - free (ctx); - return _cairo_gl_context_create_in_error (status); - } - - ctx->display = dpy; - ctx->dummy_window = dummy; - ctx->context = gl_ctx; - - ctx->base.acquire = _glx_acquire; - ctx->base.release = _glx_release; - ctx->base.make_current = _glx_make_current; - ctx->base.swap_buffers = _glx_swap_buffers; - ctx->base.destroy = _glx_destroy; - - status = _cairo_gl_dispatch_init (&ctx->base.dispatch, - (cairo_gl_get_proc_addr_func_t) glXGetProcAddress); - if (unlikely (status)) { - free (ctx); - return _cairo_gl_context_create_in_error (status); - } - - status = _cairo_gl_context_init (&ctx->base); - if (unlikely (status)) { - free (ctx); - return _cairo_gl_context_create_in_error (status); - } - - glx_extensions = glXQueryExtensionsString (dpy, DefaultScreen (dpy)); - if (strstr(glx_extensions, "GLX_MESA_multithread_makecurrent")) { - ctx->has_multithread_makecurrent = TRUE; - } - - ctx->base.release (ctx); - - return &ctx->base.base; -} - -Display * -cairo_glx_device_get_display (cairo_device_t *device) -{ - cairo_glx_context_t *ctx; - - if (device->backend->type != CAIRO_DEVICE_TYPE_GL) { - _cairo_error_throw (CAIRO_STATUS_DEVICE_TYPE_MISMATCH); - return NULL; - } - - ctx = (cairo_glx_context_t *) device; - - return ctx->display; -} - -GLXContext -cairo_glx_device_get_context (cairo_device_t *device) -{ - cairo_glx_context_t *ctx; - - if (device->backend->type != CAIRO_DEVICE_TYPE_GL) { - _cairo_error_throw (CAIRO_STATUS_DEVICE_TYPE_MISMATCH); - return NULL; - } - - ctx = (cairo_glx_context_t *) device; - - return ctx->context; -} - -cairo_surface_t * -cairo_gl_surface_create_for_window (cairo_device_t *device, - Window win, - int width, - int height) -{ - cairo_glx_surface_t *surface; - - if (unlikely (device->status)) - return _cairo_surface_create_in_error (device->status); - - if (device->backend->type != CAIRO_DEVICE_TYPE_GL) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH)); - - if (width <= 0 || height <= 0) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE)); - - surface = calloc (1, sizeof (cairo_glx_surface_t)); - if (unlikely (surface == NULL)) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - - _cairo_gl_surface_init (device, &surface->base, - CAIRO_CONTENT_COLOR_ALPHA, width, height); - surface->win = win; - - return &surface->base.base; -} diff --git a/src/cairo-mutex-list-private.h b/src/cairo-mutex-list-private.h index 70d566ebb..af5cc0517 100644 --- a/src/cairo-mutex-list-private.h +++ b/src/cairo-mutex-list-private.h @@ -64,10 +64,6 @@ CAIRO_MUTEX_DECLARE (_cairo_xlib_display_mutex) CAIRO_MUTEX_DECLARE (_cairo_xcb_connections_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-wgl-context.c b/src/cairo-wgl-context.c deleted file mode 100644 index b6cd803a0..000000000 --- a/src/cairo-wgl-context.c +++ /dev/null @@ -1,260 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2009 Eric Anholt - * Copyright © 2009 Chris Wilson - * 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., 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 Red Hat, Inc. - * - * Contributor(s): - * Carl Worth <cworth@cworth.org> - * Chris Wilson <chris@chris-wilson.co.uk> - * Zoxc <zoxc32@gmail.com> - */ - -#include "cairoint.h" - -#include "cairo-gl-private.h" - -#include "cairo-error-private.h" - -#include <windows.h> - -typedef struct _cairo_wgl_context { - cairo_gl_context_t base; - - HDC dummy_dc; - HWND dummy_wnd; - HGLRC rc; - - HDC prev_dc; - HGLRC prev_rc; -} cairo_wgl_context_t; - -typedef struct _cairo_wgl_surface { - cairo_gl_surface_t base; - - HDC dc; -} cairo_wgl_surface_t; - -static void -_wgl_acquire (void *abstract_ctx) -{ - cairo_wgl_context_t *ctx = abstract_ctx; - - HDC current_dc; - - ctx->prev_dc = wglGetCurrentDC (); - ctx->prev_rc = wglGetCurrentContext (); - - if (ctx->base.current_target == NULL || - _cairo_gl_surface_is_texture (ctx->base.current_target)) - { - current_dc = ctx->dummy_dc; - } - else - { - cairo_wgl_surface_t *surface = (cairo_wgl_surface_t *) ctx->base.current_target; - current_dc = surface->dc; - } - - if (ctx->prev_dc != current_dc || - (ctx->prev_rc != ctx->rc && - current_dc != ctx->dummy_dc)) - { - wglMakeCurrent (current_dc, ctx->rc); - } -} - -static void -_wgl_make_current (void *abstract_ctx, cairo_gl_surface_t *abstract_surface) -{ - cairo_wgl_context_t *ctx = abstract_ctx; - cairo_wgl_surface_t *surface = (cairo_wgl_surface_t *) abstract_surface; - - /* Set the window as the target of our context. */ - wglMakeCurrent (surface->dc, ctx->rc); -} - -static void -_wgl_release (void *abstract_ctx) -{ - cairo_wgl_context_t *ctx = abstract_ctx; - - if (ctx->prev_dc != wglGetCurrentDC () || - ctx->prev_rc != wglGetCurrentContext ()) - { - wglMakeCurrent (ctx->prev_dc, - ctx->prev_rc); - } -} - -static void -_wgl_swap_buffers (void *abstract_ctx, - cairo_gl_surface_t *abstract_surface) -{ - cairo_wgl_surface_t *surface = (cairo_wgl_surface_t *) abstract_surface; - - SwapBuffers (surface->dc); -} - -static void -_wgl_destroy (void *abstract_ctx) -{ - cairo_wgl_context_t *ctx = abstract_ctx; - - if (ctx->dummy_dc != 0) { - wglMakeCurrent (ctx->dummy_dc, 0); - ReleaseDC (ctx->dummy_wnd, ctx->dummy_dc); - DestroyWindow (ctx->dummy_wnd); - } -} - -static cairo_status_t -_wgl_dummy_ctx (cairo_wgl_context_t *ctx) -{ - WNDCLASSEXA wincl; - PIXELFORMATDESCRIPTOR pfd; - int format; - HDC dc; - - ZeroMemory (&wincl, sizeof (WNDCLASSEXA)); - wincl.cbSize = sizeof (WNDCLASSEXA); - wincl.hInstance = GetModuleHandle (0); - wincl.lpszClassName = "cairo_wgl_context_dummy"; - wincl.lpfnWndProc = DefWindowProcA; - wincl.style = CS_OWNDC; - - RegisterClassExA (&wincl); - - ctx->dummy_wnd = CreateWindowA ("cairo_wgl_context_dummy", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); - ctx->dummy_dc = GetDC (ctx->dummy_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 (ctx->dummy_dc, &pfd); - SetPixelFormat (ctx->dummy_dc, format, &pfd); - - wglMakeCurrent(ctx->dummy_dc, ctx->rc); - - return CAIRO_STATUS_SUCCESS; -} - -cairo_device_t * -cairo_wgl_device_create (HGLRC rc) -{ - cairo_wgl_context_t *ctx; - cairo_status_t status; - - ctx = calloc (1, sizeof (cairo_wgl_context_t)); - if (unlikely (ctx == NULL)) - return _cairo_gl_context_create_in_error (CAIRO_STATUS_NO_MEMORY); - - ctx->rc = rc; - ctx->prev_dc = 0; - ctx->prev_rc = 0; - - status = _wgl_dummy_ctx (ctx); - if (unlikely (status)) { - free (ctx); - return _cairo_gl_context_create_in_error (status); - } - - ctx->base.acquire = _wgl_acquire; - ctx->base.release = _wgl_release; - ctx->base.make_current = _wgl_make_current; - ctx->base.swap_buffers = _wgl_swap_buffers; - ctx->base.destroy = _wgl_destroy; - - status = _cairo_gl_dispatch_init (&ctx->base.dispatch, - (cairo_gl_get_proc_addr_func_t) wglGetProcAddress); - if (unlikely (status)) { - free (ctx); - return _cairo_gl_context_create_in_error (status); - } - - status = _cairo_gl_context_init (&ctx->base); - if (unlikely (status)) { - free (ctx); - return _cairo_gl_context_create_in_error (status); - } - - ctx->base.release (ctx); - - return &ctx->base.base; -} - -HGLRC -cairo_wgl_device_get_context (cairo_device_t *device) -{ - cairo_wgl_context_t *ctx; - - if (device->backend->type != CAIRO_DEVICE_TYPE_GL) { - _cairo_error_throw (CAIRO_STATUS_DEVICE_TYPE_MISMATCH); - return NULL; - } - - ctx = (cairo_wgl_context_t *) device; - - return ctx->rc; -} - -cairo_surface_t * -cairo_gl_surface_create_for_dc (cairo_device_t *device, - HDC dc, - int width, - int height) -{ - cairo_wgl_surface_t *surface; - - if (unlikely (device->status)) - return _cairo_surface_create_in_error (device->status); - - if (device->backend->type != CAIRO_DEVICE_TYPE_GL) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH)); - - if (width <= 0 || height <= 0) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE)); - - surface = calloc (1, sizeof (cairo_wgl_surface_t)); - if (unlikely (surface == NULL)) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - - _cairo_gl_surface_init (device, &surface->base, - CAIRO_CONTENT_COLOR_ALPHA, width, height); - surface->dc = dc; - - return &surface->base.base; -} diff --git a/src/cairo-xcb-surface-render.c b/src/cairo-xcb-surface-render.c index c58821a48..a4441dc46 100644 --- a/src/cairo-xcb-surface-render.c +++ b/src/cairo-xcb-surface-render.c @@ -1243,12 +1243,6 @@ _cairo_xcb_surface_picture (cairo_xcb_surface_t *target, } } #endif -#if CAIRO_HAS_GL_FUNCTIONS - else if (source->type == CAIRO_SURFACE_TYPE_GL) - { - /* pixmap from texture */ - } -#endif else if (source->type == CAIRO_SURFACE_TYPE_RECORDING) { /* We have to skip the call to attach_snapshot() because we possibly diff --git a/src/cairo.h b/src/cairo.h index a9b423b28..ca7d67836 100644 --- a/src/cairo.h +++ b/src/cairo.h @@ -157,9 +157,7 @@ typedef struct _cairo_surface cairo_surface_t; * * A #cairo_device_t represents the driver interface for drawing * operations to a #cairo_surface_t. There are different subtypes of - * #cairo_device_t for different drawing backends; for example, - * cairo_egl_device_create() creates a device that wraps an EGL display and - * context. + * #cairo_device_t for different drawing backends. * * The type of a device can be queried with cairo_device_get_type(). * diff --git a/src/meson.build b/src/meson.build index 768dba143..db9bf41e4 100644 --- a/src/meson.build +++ b/src/meson.build @@ -182,21 +182,6 @@ cairo_feature_sources = { 'cairo-win32-dwrite-font': [ 'win32/cairo-dwrite-font.cpp', ], - 'cairo-gl': [ - 'cairo-gl-composite.c', - 'cairo-gl-device.c', - 'cairo-gl-dispatch.c', - 'cairo-gl-glyphs.c', - 'cairo-gl-gradient.c', - 'cairo-gl-info.c', - 'cairo-gl-msaa-compositor.c', - 'cairo-gl-operand.c', - 'cairo-gl-shaders.c', - 'cairo-gl-source.c', - 'cairo-gl-spans-compositor.c', - 'cairo-gl-surface.c', - 'cairo-gl-traps-compositor.c', - ], 'cairo-script': [ 'cairo-script-surface.c', ], @@ -210,15 +195,6 @@ cairo_feature_sources = { 'cairo-svg': [ 'cairo-svg-surface.c', ], - 'cairo-egl': [ - 'cairo-egl-context.c', - ], - 'cairo-glx': [ - 'cairo-glx-context.c', - ], - 'cairo-wgl': [ - 'cairo-wgl-context.c', - ], 'cairo-xml': [ 'cairo-xml-surface.c', ], diff --git a/test/api-special-cases.c b/test/api-special-cases.c index ce54200b7..d926aa652 100644 --- a/test/api-special-cases.c +++ b/test/api-special-cases.c @@ -63,9 +63,6 @@ #include "cairo-test.h" -#if CAIRO_HAS_GL_SURFACE -#include <cairo-gl.h> -#endif #if CAIRO_HAS_PDF_SURFACE #include <cairo-pdf.h> #endif @@ -1312,38 +1309,6 @@ test_cairo_tee_surface_index (cairo_surface_t *surface) #endif /* CAIRO_HAS_TEE_SURFACE */ -#if CAIRO_HAS_GL_SURFACE - -static cairo_test_status_t -test_cairo_gl_surface_set_size (cairo_surface_t *surface) -{ - cairo_gl_surface_set_size (surface, 5, 5); - return CAIRO_TEST_SUCCESS; -} - -static cairo_test_status_t -test_cairo_gl_surface_get_width (cairo_surface_t *surface) -{ - unsigned int width = cairo_gl_surface_get_width (surface); - return width == 0 || surface_has_type (surface, CAIRO_SURFACE_TYPE_GL) ? CAIRO_TEST_SUCCESS : CAIRO_TEST_ERROR; -} - -static cairo_test_status_t -test_cairo_gl_surface_get_height (cairo_surface_t *surface) -{ - unsigned int height = cairo_gl_surface_get_height (surface); - return height == 0 || surface_has_type (surface, CAIRO_SURFACE_TYPE_GL) ? CAIRO_TEST_SUCCESS : CAIRO_TEST_ERROR; -} - -static cairo_test_status_t -test_cairo_gl_surface_swapbuffers (cairo_surface_t *surface) -{ - cairo_gl_surface_swapbuffers (surface); - return CAIRO_TEST_SUCCESS; -} - -#endif /* CAIRO_HAS_GL_SURFACE */ - #if CAIRO_HAS_PDF_SURFACE static cairo_test_status_t @@ -1675,12 +1640,6 @@ struct { TEST (cairo_tee_surface_remove, CAIRO_SURFACE_TYPE_TEE, TRUE), TEST (cairo_tee_surface_index, CAIRO_SURFACE_TYPE_TEE, FALSE), #endif -#if CAIRO_HAS_GL_SURFACE - TEST (cairo_gl_surface_set_size, CAIRO_SURFACE_TYPE_GL, TRUE), - TEST (cairo_gl_surface_get_width, CAIRO_SURFACE_TYPE_GL, FALSE), - TEST (cairo_gl_surface_get_height, CAIRO_SURFACE_TYPE_GL, FALSE), - TEST (cairo_gl_surface_swapbuffers, CAIRO_SURFACE_TYPE_GL, TRUE), -#endif #if CAIRO_HAS_PDF_SURFACE TEST (cairo_pdf_surface_restrict_to_version, CAIRO_SURFACE_TYPE_PDF, TRUE), TEST (cairo_pdf_surface_set_size, CAIRO_SURFACE_TYPE_PDF, TRUE), diff --git a/test/egl-oversized-surface.c b/test/egl-oversized-surface.c deleted file mode 100644 index cb85a628d..000000000 --- a/test/egl-oversized-surface.c +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright © 2014 Samsung Electronics - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * Author: Ravi Nanjundappa <nravi.n@samsung.com> - */ - -/* - * This test exercises error scenario for over sized egl surface - * - */ - -#include "cairo-test.h" -#include <cairo-gl.h> -#include <assert.h> -#include <limits.h> - -static cairo_test_status_t -preamble (cairo_test_context_t *test_ctx) -{ - EGLint rgba_attribs[] = { - EGL_RED_SIZE, 8, - EGL_GREEN_SIZE, 8, - EGL_BLUE_SIZE, 8, - EGL_ALPHA_SIZE, 8, - EGL_SURFACE_TYPE, EGL_PBUFFER_BIT, -#if CAIRO_HAS_GL_SURFACE - EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT, -#elif CAIRO_HAS_GLESV2_SURFACE - EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, -#endif - EGL_NONE - }; - const EGLint ctx_attribs[] = { -#if CAIRO_HAS_GLESV2_SURFACE - EGL_CONTEXT_CLIENT_VERSION, 2, -#endif - EGL_NONE - }; - - EGLDisplay dpy; - EGLContext ctx; - EGLConfig config; - EGLint numConfigs; - int major, minor; - cairo_device_t *device; - cairo_surface_t *oversized_surface; - cairo_test_status_t test_status = CAIRO_TEST_SUCCESS; - - dpy = eglGetDisplay (EGL_DEFAULT_DISPLAY); - if (! eglInitialize (dpy, &major, &minor)) { - test_status = CAIRO_TEST_UNTESTED; - goto CLEANUP_1; - } - - eglChooseConfig (dpy, rgba_attribs, &config, 1, &numConfigs); - if (numConfigs == 0) { - test_status = CAIRO_TEST_UNTESTED; - goto CLEANUP_1; - } - -#if CAIRO_HAS_GL_SURFACE - eglBindAPI (EGL_OPENGL_API); -#elif CAIRO_HAS_GLESV2_SURFACE - eglBindAPI (EGL_OPENGL_ES_API); -#endif - - ctx = eglCreateContext (dpy, config, EGL_NO_CONTEXT, - ctx_attribs); - if (ctx == EGL_NO_CONTEXT) { - test_status = CAIRO_TEST_UNTESTED; - goto CLEANUP_2; - } - - device = cairo_egl_device_create (dpy, ctx); - - oversized_surface = cairo_gl_surface_create (device, CAIRO_CONTENT_COLOR_ALPHA, INT_MAX, INT_MAX); - if (cairo_surface_status (oversized_surface) != CAIRO_STATUS_INVALID_SIZE) - test_status = CAIRO_TEST_FAILURE; - - cairo_device_destroy (device); - eglDestroyContext (dpy, ctx); - eglMakeCurrent (dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); - ctx = EGL_NO_CONTEXT; - -CLEANUP_2: - eglTerminate (dpy); - -CLEANUP_1: - return test_status; -} - -CAIRO_TEST (egl_oversized_surface, - "Test that creating a surface beyond texture limits results in an error surface", - "egl", /* keywords */ - NULL, /* requirements */ - 0, 0, - preamble, NULL) diff --git a/test/egl-surface-source.c b/test/egl-surface-source.c deleted file mode 100644 index 4a84d7042..000000000 --- a/test/egl-surface-source.c +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright © 2014 Samsung Electronics - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * Author: Ravi Nanjundappa <nravi.n@samsung.com> - */ - -/* - * This case tests using a EGL surface as the source - * - */ - -#include "cairo-test.h" -#include <cairo-gl.h> - -#include "surface-source.c" - -struct closure { - EGLDisplay dpy; - EGLContext ctx; -}; - -static void -cleanup (void *data) -{ - struct closure *arg = data; - - eglDestroyContext (arg->dpy, arg->ctx); - eglMakeCurrent (arg->dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); - eglTerminate (arg->dpy); - - free (arg); -} - -static cairo_surface_t * -create_source_surface (int size) -{ - EGLint config_attribs[] = { - EGL_RED_SIZE, 8, - EGL_GREEN_SIZE, 8, - EGL_BLUE_SIZE, 8, - EGL_ALPHA_SIZE, 8, - EGL_SURFACE_TYPE, EGL_PBUFFER_BIT, -#if CAIRO_HAS_GL_SURFACE - EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT, -#elif CAIRO_HAS_GLESV2_SURFACE - EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, -#endif - EGL_NONE - }; - const EGLint ctx_attribs[] = { -#if CAIRO_HAS_GLESV2_SURFACE - EGL_CONTEXT_CLIENT_VERSION, 2, -#endif - EGL_NONE - }; - - struct closure *arg; - cairo_device_t *device; - cairo_surface_t *surface; - EGLConfig config; - EGLint numConfigs; - EGLDisplay dpy; - EGLContext ctx; - int major, minor; - - dpy = eglGetDisplay (EGL_DEFAULT_DISPLAY); - if (! eglInitialize (dpy, &major, &minor)) { - return NULL; - } - - eglChooseConfig (dpy, config_attribs, &config, 1, &numConfigs); - if (numConfigs == 0) { - return NULL; - } - -#if CAIRO_HAS_GL_SURFACE - eglBindAPI (EGL_OPENGL_API); -#elif CAIRO_HAS_GLESV2_SURFACE - eglBindAPI (EGL_OPENGL_ES_API); -#endif - - ctx = eglCreateContext (dpy, config, EGL_NO_CONTEXT, - ctx_attribs); - if (ctx == EGL_NO_CONTEXT) { - eglTerminate (dpy); - return NULL; - } - - arg = xmalloc (sizeof (struct closure)); - arg->dpy = dpy; - arg->ctx = ctx; - device = cairo_egl_device_create (dpy, ctx); - if (cairo_device_set_user_data (device, - (cairo_user_data_key_t *) cleanup, - arg, - cleanup)) - { - cleanup (arg); - return NULL; - } - - surface = cairo_gl_surface_create (device, - CAIRO_CONTENT_COLOR_ALPHA, - size, size); - cairo_device_destroy (device); - - return surface; -} - -CAIRO_TEST (egl_surface_source, - "Test using a EGL surface as the source", - "source", /* keywords */ - NULL, /* requirements */ - SIZE, SIZE, - preamble, draw) diff --git a/test/error-setters.c b/test/error-setters.c index c69a6d89b..ecbb78fde 100644 --- a/test/error-setters.c +++ b/test/error-setters.c @@ -29,9 +29,6 @@ #include "cairo-test.h" -#if CAIRO_HAS_GL_SURFACE -#include <cairo-gl.h> -#endif #if CAIRO_HAS_PDF_SURFACE #include <cairo-pdf.h> #endif @@ -53,11 +50,6 @@ preamble (cairo_test_context_t *ctx) /* get the error surface */ surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, INT_MAX, INT_MAX); -#if CAIRO_HAS_GL_SURFACE - cairo_gl_surface_set_size (surface, 0, 0); - cairo_gl_surface_swapbuffers (surface); -#endif - #if CAIRO_HAS_PDF_SURFACE cairo_pdf_surface_restrict_to_version (surface, CAIRO_PDF_VERSION_1_4); cairo_pdf_surface_set_size (surface, 0, 0); diff --git a/test/gl-device-release.c b/test/gl-device-release.c deleted file mode 100644 index 7f554be30..000000000 --- a/test/gl-device-release.c +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Copyright © 2012 Igalia S.L. - * Copyright © 2009 Eric Anholt - * Copyright © 2009 Chris Wilson - * Copyright © 2005 Red Hat, Inc - * - * Permission to use, copy, modify, distribute, and sell this software - * and its documentation for any purpose is hereby granted without - * fee, provided that the above copyright notice appear in all copies - * and that both that copyright notice and this permission notice - * appear in supporting documentation, and that the name of - * Chris Wilson not be used in advertising or publicity pertaining to - * distribution of the software without specific, written prior - * permission. Chris Wilson makes no representations about the - * suitability of this software for any purpose. It is provided "as - * is" without express or implied warranty. - * - * IGALIA S.L. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS - * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS, IN NO EVENT SHALL CHRIS WILSON BE LIABLE FOR ANY SPECIAL, - * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER - * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION - * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR - * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Author: Martin Robinson <mrobinson@igalia.com> - */ - -#include "cairo-test.h" -#include <cairo-gl.h> -#include <assert.h> - -static Window -create_test_window (Display *display, - GLXContext glx_context, - XVisualInfo *visual_info) -{ - Colormap colormap; - XSetWindowAttributes window_attributes; - Window window = None; - - colormap = XCreateColormap (display, - RootWindow (display, visual_info->screen), - visual_info->visual, - AllocNone); - window_attributes.colormap = colormap; - window_attributes.border_pixel = 0; - window = XCreateWindow (display, RootWindow (display, visual_info->screen), - -1, -1, 1, 1, 0, - visual_info->depth, - InputOutput, - visual_info->visual, - CWBorderPixel | CWColormap, &window_attributes); - XFreeColormap (display, colormap); - - XFlush (display); - return window; -} - -static cairo_bool_t -multithread_makecurrent_available (Display *display) -{ - const char *extensions = glXQueryExtensionsString (display, - DefaultScreen (display)); - return !! strstr(extensions, "GLX_MESA_multithread_makecurrent"); -} - -static void -draw_to_surface (cairo_surface_t *surface) -{ - cairo_t *cr = cairo_create (surface); - cairo_paint (cr); - cairo_destroy (cr); -} - -static cairo_test_status_t -preamble (cairo_test_context_t *test_ctx) -{ - 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 *visual_info; - GLXContext glx_context; - cairo_device_t *device; - Display *display; - Window test_window; - cairo_surface_t *window_surface; - cairo_bool_t has_multithread_makecurrent; - - display = XOpenDisplay (NULL); - if (display == NULL) - return CAIRO_TEST_UNTESTED; - - visual_info = glXChooseVisual (display, DefaultScreen (display), rgba_attribs); - if (visual_info == NULL) { - XCloseDisplay (display); - return CAIRO_TEST_UNTESTED; - } - - glx_context = glXCreateContext (display, visual_info, NULL, True); - if (glx_context == NULL) { - XCloseDisplay (display); - return CAIRO_TEST_UNTESTED; - } - - test_window = create_test_window (display, glx_context, visual_info); - XFree (visual_info); - if (test_window == None) { - XCloseDisplay (display); - return CAIRO_TEST_UNTESTED; - } - - has_multithread_makecurrent = multithread_makecurrent_available (display); - - glXMakeCurrent (display, None, None); - - /* Creating the device should actually change the GL context, because of - * the creation/activation of a dummy window used for texture surfaces. */ - device = cairo_glx_device_create (display, glx_context); - - /* It's important that when multithread_makecurrent isn't available the - * Cairo backend clears the current context, so that the dummy texture - * window is not active while the device is unlocked. */ - if (has_multithread_makecurrent) { - assert (None != glXGetCurrentDrawable ()); - assert (display == glXGetCurrentDisplay ()); - assert (glx_context == glXGetCurrentContext ()); - } else { - assert (None == glXGetCurrentDrawable ()); - assert (None == glXGetCurrentDisplay ()); - assert (None == glXGetCurrentContext ()); - } - - window_surface = cairo_gl_surface_create_for_window (device, test_window, - 1, 1); - assert (cairo_surface_status (window_surface) == CAIRO_STATUS_SUCCESS); - - draw_to_surface (window_surface); - if (has_multithread_makecurrent) { - assert (test_window == glXGetCurrentDrawable ()); - assert (display == glXGetCurrentDisplay ()); - assert (glx_context == glXGetCurrentContext ()); - } else { - assert (None == glXGetCurrentDrawable ()); - assert (None == glXGetCurrentDisplay ()); - assert (None == glXGetCurrentContext ()); - } - - /* In this case, drawing to the window surface will not change the current - * GL context, so Cairo setting the current surface and context to none. */ - glXMakeCurrent (display, test_window, glx_context); - draw_to_surface (window_surface); - assert (test_window == glXGetCurrentDrawable ()); - assert (display == glXGetCurrentDisplay ()); - assert (glx_context == glXGetCurrentContext ()); - - /* There should be no context change when destroying the device. */ - cairo_device_destroy (device); - assert (test_window == glXGetCurrentDrawable ()); - assert (display == glXGetCurrentDisplay ()); - assert (glx_context == glXGetCurrentContext ()); - - glXDestroyContext(display, glx_context); - XDestroyWindow (display, test_window); - XCloseDisplay (display); - - return CAIRO_TEST_SUCCESS; -} - -CAIRO_TEST (gl_device_creation_changes_context, - "Test that using the Cairo GL backend leaves the current GL context in the appropriate state", - "gl", /* keywords */ - NULL, /* requirements */ - 0, 0, - preamble, NULL) diff --git a/test/gl-oversized-surface.c b/test/gl-oversized-surface.c deleted file mode 100644 index 4c46efd80..000000000 --- a/test/gl-oversized-surface.c +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright © 2012 Igalia S.L. - * Copyright © 2009 Eric Anholt - * Copyright © 2009 Chris Wilson - * Copyright © 2005 Red Hat, Inc - * - * Permission to use, copy, modify, distribute, and sell this software - * and its documentation for any purpose is hereby granted without - * fee, provided that the above copyright notice appear in all copies - * and that both that copyright notice and this permission notice - * appear in supporting documentation, and that the name of - * Chris Wilson not be used in advertising or publicity pertaining to - * distribution of the software without specific, written prior - * permission. Chris Wilson makes no representations about the - * suitability of this software for any purpose. It is provided "as - * is" without express or implied warranty. - * - * IGALIA S.L. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS - * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS, IN NO EVENT SHALL CHRIS WILSON BE LIABLE FOR ANY SPECIAL, - * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER - * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION - * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR - * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Author: Martin Robinson <mrobinson@igalia.com> - */ - -#include "cairo-test.h" -#include <cairo-gl.h> -#include <assert.h> -#include <limits.h> - -static cairo_test_status_t -preamble (cairo_test_context_t *test_ctx) -{ - int rgba_attribs[] = { - GLX_RGBA, - GLX_RED_SIZE, 1, - GLX_GREEN_SIZE, 1, - GLX_BLUE_SIZE, 1, - GLX_ALPHA_SIZE, 1, - GLX_DOUBLEBUFFER, - None - }; - - Display *display; - XVisualInfo *visual_info; - GLXContext glx_context; - cairo_device_t *device; - cairo_surface_t *oversized_surface; - cairo_test_status_t test_status = CAIRO_TEST_SUCCESS; - - display = XOpenDisplay (NULL); - if (display == NULL) - return CAIRO_TEST_UNTESTED; - - visual_info = glXChooseVisual (display, DefaultScreen (display), rgba_attribs); - if (visual_info == NULL) { - XCloseDisplay (display); - return CAIRO_TEST_UNTESTED; - } - - glx_context = glXCreateContext (display, visual_info, NULL, True); - if (glx_context == NULL) { - XCloseDisplay (display); - return CAIRO_TEST_UNTESTED; - } - - device = cairo_glx_device_create (display, glx_context); - - oversized_surface = cairo_gl_surface_create (device, CAIRO_CONTENT_COLOR_ALPHA, INT_MAX, INT_MAX); - if (cairo_surface_status (oversized_surface) != CAIRO_STATUS_INVALID_SIZE) - test_status = CAIRO_TEST_FAILURE; - - cairo_device_destroy (device); - glXDestroyContext(display, glx_context); - XCloseDisplay (display); - - return test_status; -} - -CAIRO_TEST (gl_oversized_surface, - "Test that creating a surface beyond texture limits results in an error surface", - "gl", /* keywords */ - NULL, /* requirements */ - 0, 0, - preamble, NULL) diff --git a/test/gl-surface-source.c b/test/gl-surface-source.c deleted file mode 100644 index 09d4d9c47..000000000 --- a/test/gl-surface-source.c +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright © 2008 Chris Wilson - * Copyright © 2010 Intel Corporation - * - * Permission to use, copy, modify, distribute, and sell this software - * and its documentation for any purpose is hereby granted without - * fee, provided that the above copyright notice appear in all copies - * and that both that copyright notice and this permission notice - * appear in supporting documentation, and that the name of - * Chris Wilson not be used in advertising or publicity pertaining to - * distribution of the software without specific, written prior - * permission. Chris Wilson makes no representations about the - * suitability of this software for any purpose. It is provided "as - * is" without express or implied warranty. - * - * CHRIS WILSON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS - * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS, IN NO EVENT SHALL CHRIS WILSON BE LIABLE FOR ANY SPECIAL, - * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER - * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION - * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR - * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Author: Chris Wilson <chris@chris-wilson.co.uk> - */ - -#include "cairo-test.h" -#include <cairo-gl.h> - -#include "surface-source.c" - -struct closure { - Display *dpy; - GLXContext ctx; -}; - -static void -cleanup (void *data) -{ - struct closure *arg = data; - - glXDestroyContext (arg->dpy, arg->ctx); - XCloseDisplay (arg->dpy); - - free (arg); -} - -static cairo_surface_t * -create_source_surface (int size) -{ - 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 *visinfo; - GLXContext ctx; - struct closure *arg; - cairo_device_t *device; - cairo_surface_t *surface; - Display *dpy; - - dpy = XOpenDisplay (NULL); - if (dpy == NULL) - return NULL; - - visinfo = glXChooseVisual (dpy, DefaultScreen (dpy), rgba_attribs); - if (visinfo == NULL) { - XCloseDisplay (dpy); - return NULL; - } - - ctx = glXCreateContext (dpy, visinfo, NULL, True); - XFree (visinfo); - - if (ctx == NULL) { - XCloseDisplay (dpy); - return NULL; - } - - arg = xmalloc (sizeof (struct closure)); - arg->dpy = dpy; - arg->ctx = ctx; - device = cairo_glx_device_create (dpy, ctx); - if (cairo_device_set_user_data (device, - (cairo_user_data_key_t *) cleanup, - arg, - cleanup)) - { - cleanup (arg); - return NULL; - } - - surface = cairo_gl_surface_create (device, - CAIRO_CONTENT_COLOR_ALPHA, - size, size); - cairo_device_destroy (device); - - return surface; -} - -CAIRO_TEST (gl_surface_source, - "Test using a GL surface as the source", - "source", /* keywords */ - NULL, /* requirements */ - SIZE, SIZE, - preamble, draw) diff --git a/test/meson.build b/test/meson.build index e5b4f89d5..b18a23f48 100644 --- a/test/meson.build +++ b/test/meson.build @@ -439,17 +439,6 @@ test_ft_svg_ttx_font_sources = [ 'ft-svg-render-color.c' ] -test_gl_sources = [ - 'gl-device-release.c', - 'gl-oversized-surface.c', - 'gl-surface-source.c', -] - -test_egl_sources = [ - 'egl-oversized-surface.c', - 'egl-surface-source.c', -] - test_quartz_sources = [ 'quartz-surface-source.c', 'quartz-color-font.c', @@ -596,10 +585,6 @@ if feature_conf.get('CAIRO_HAS_XLIB_XRENDER_SURFACE', 0) == 1 test_sources += test_xlib_xrender_sources endif -if feature_conf.get('CAIRO_HAS_EGL_FUNCTIONS', 0) == 1 - test_sources += test_egl_sources -endif - if has_multipage_surfaces test_sources += test_multi_page_sources endif diff --git a/util/cairo-script/csi-replay.c b/util/cairo-script/csi-replay.c index 9d9be72c2..4460d6414 100644 --- a/util/cairo-script/csi-replay.c +++ b/util/cairo-script/csi-replay.c @@ -206,64 +206,6 @@ _xrender_surface_create (void *closure, #endif #endif -#if CAIRO_HAS_GL_GLX_SURFACE -#include <cairo-gl.h> -static cairo_gl_context_t * -_glx_get_context (cairo_content_t content) -{ - static cairo_gl_context_t *context; - - if (context == NULL) { - 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 *visinfo; - GLXContext gl_ctx; - Display *dpy; - - dpy = XOpenDisplay (NULL); - if (dpy == NULL) { - fprintf (stderr, "Failed to open display.\n"); - exit (1); - } - - visinfo = glXChooseVisual (dpy, DefaultScreen (dpy), rgba_attribs); - if (visinfo == NULL) { - fprintf (stderr, "Failed to create RGBA, double-buffered visual\n"); - exit (1); - } - - gl_ctx = glXCreateContext (dpy, visinfo, NULL, True); - XFree (visinfo); - - context = cairo_glx_context_create (dpy, gl_ctx); - } - - return context; -} - -static cairo_surface_t * -_glx_surface_create (void *closure, - cairo_content_t content, - double width, double height, - long uid) -{ - if (width == 0) - width = 1; - if (height == 0) - height = 1; - - return cairo_gl_surface_create (_glx_get_context (content), - content, width, height); -} -#endif - #if CAIRO_HAS_PDF_SURFACE #include <cairo-pdf.h> static cairo_surface_t * @@ -341,9 +283,6 @@ main (int argc, char **argv) #if CAIRO_HAS_XLIB_XRENDER_SURFACE { "--xrender", _xrender_surface_create }, #endif -#if CAIRO_HAS_GL_GLX_SURFACE - { "--glx", _glx_surface_create }, -#endif #if CAIRO_HAS_XLIB_SURFACE { "--xlib", _xlib_surface_create }, #endif diff --git a/util/cairo-trace/trace.c b/util/cairo-trace/trace.c index a9181ce24..7ccdc41dc 100644 --- a/util/cairo-trace/trace.c +++ b/util/cairo-trace/trace.c @@ -5323,191 +5323,3 @@ cairo_recording_surface_create (cairo_content_t content, _exit_trace (); return ret; } - -#if CAIRO_HAS_GL_SURFACE || CAIRO_HAS_GLESV2_SURFACE -#include <cairo-gl.h> -cairo_surface_t * -cairo_gl_surface_create (cairo_device_t *abstract_device, - cairo_content_t content, - int width, - int height) -{ - cairo_surface_t *ret; - - _enter_trace (); - - ret = DLCALL (cairo_gl_surface_create, abstract_device, content, width, height); - - _emit_line_info (); - if (_write_lock ()) { - Object *obj = _create_surface (ret); - - _trace_printf ("dict\n" - " /type /gl set\n" - " /content //%s set\n" - " /width %d set\n" - " /height %d set\n" - " surface dup /s%ld exch def\n", - _content_to_string (content), - width, height, - obj->token); - obj->width = width; - obj->height = height; - obj->defined = TRUE; - _push_object (obj); - dump_stack(__func__); - _write_unlock (); - } - - _exit_trace (); - return ret; -} - -cairo_surface_t * -cairo_gl_surface_create_for_texture (cairo_device_t *abstract_device, - cairo_content_t content, - unsigned int tex, - int width, - int height) -{ - cairo_surface_t *ret; - - _enter_trace (); - - ret = DLCALL (cairo_gl_surface_create_for_texture, abstract_device, content, tex, width, height); - - _emit_line_info (); - if (_write_lock ()) { - Object *obj = _create_surface (ret); - - _trace_printf ("dict\n" - " /type /gl set\n" - " /content //%s set\n" - " /width %d set\n" - " /height %d set\n" - " surface dup /s%ld exch def\n", - _content_to_string (content), - width, height, - obj->token); - obj->width = width; - obj->height = height; - obj->defined = TRUE; - _push_object (obj); - dump_stack(__func__); - _write_unlock (); - } - - _exit_trace (); - return ret; -} - -#if CAIRO_HAS_GLX_FUNCTIONS -cairo_surface_t * -cairo_gl_surface_create_for_window (cairo_device_t *device, - Window win, - int width, int height) -{ - cairo_surface_t *ret; - - _enter_trace (); - - ret = DLCALL (cairo_gl_surface_create_for_window, device, win, width, height); - - _emit_line_info (); - if (_write_lock ()) { - Object *obj = _create_surface (ret); - - _trace_printf ("dict\n" - " /type /gl set\n" - " /width %d set\n" - " /height %d set\n" - " surface dup /s%ld exch def\n", - width, height, - obj->token); - obj->width = width; - obj->height = height; - obj->defined = TRUE; - _push_object (obj); - dump_stack(__func__); - _write_unlock (); - } - - _exit_trace (); - return ret; -} -#endif - -#if CAIRO_HAS_WGL_FUNCTIONS -cairo_surface_t * -cairo_gl_surface_create_for_dc (cairo_device_t *device, - HDC dc, - int width, - int height) -{ - cairo_surface_t *ret; - - _enter_trace (); - - ret = DLCALL (cairo_gl_surface_create_for_dc, device, dc, width, height); - - _emit_line_info (); - if (_write_lock ()) { - Object *obj = _create_surface (ret); - - _trace_printf ("dict\n" - " /type /gl set\n" - " /width %d set\n" - " /height %d set\n" - " surface dup /s%ld exch def\n", - width, height, - obj->token); - obj->width = width; - obj->height = height; - obj->defined = TRUE; - _push_object (obj); - dump_stack(__func__); - _write_unlock (); - } - - _exit_trace (); - return ret; -} -#endif - -#if CAIRO_HAS_EGL_FUNCTIONS -cairo_surface_t * -cairo_gl_surface_create_for_egl (cairo_device_t *device, - EGLSurface egl, - int width, - int height) -{ - cairo_surface_t *ret; - - _enter_trace (); - - ret = DLCALL (cairo_gl_surface_create_for_egl, device, egl, width, height); - - _emit_line_info (); - if (_write_lock ()) { - Object *obj = _create_surface (ret); - - _trace_printf ("dict\n" - " /type /gl set\n" - " /width %d set\n" - " /height %d set\n" - " surface dup /s%ld exch def\n", - width, height, - obj->token); - obj->width = width; - obj->height = height; - obj->defined = TRUE; - _push_object (obj); - dump_stack(__func__); - _write_unlock (); - } - - _exit_trace (); - return ret; -} -#endif -#endif |