mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2025-12-30 20:10:13 +01:00
Drop cairo-gl
The GL support in Cairo has always been a prototype, and nothing happened in the past 10+ years to make it work as it was meant to. GL support is not enabled by any downstream packagers of Cairo, so nobody should notice its absence.
This commit is contained in:
parent
407bb0a478
commit
b5793081d0
43 changed files with 1 additions and 14014 deletions
|
|
@ -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}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
@ -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)
|
||||
|
|
@ -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)
|
||||
|
|
@ -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
|
||||
|
|
|
|||
135
meson.build
135
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)
|
||||
|
|
|
|||
|
|
@ -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')
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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 */
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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 */
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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 */
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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 */
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -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;
|
||||
}
|
||||
155
src/cairo-gl.h
155
src/cairo-gl.h
|
|
@ -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 */
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -1242,12 +1242,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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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().
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
],
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
@ -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)
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
@ -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)
|
||||
|
|
@ -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)
|
||||
|
|
@ -439,17 +439,6 @@ test_ft_svg_ttx_font_sources = [
|
|||
'ft-svg-render-palette.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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue