1 /* cairo - a vector graphics library with display and print output
3 * Copyright © 2009 Eric Anholt
4 * Copyright © 2009 Chris Wilson
5 * Copyright © 2005 Red Hat, Inc
7 * This library is free software; you can redistribute it and/or
8 * modify it either under the terms of the GNU Lesser General Public
9 * License version 2.1 as published by the Free Software Foundation
10 * (the "LGPL") or, at your option, under the terms of the Mozilla
11 * Public License Version 1.1 (the "MPL"). If you do not alter this
12 * notice, a recipient may use your version of this file under either
13 * the MPL or the LGPL.
15 * You should have received a copy of the LGPL along with this library
16 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
18 * You should have received a copy of the MPL along with this library
19 * in the file COPYING-MPL-1.1
21 * The contents of this file are subject to the Mozilla Public License
22 * Version 1.1 (the "License"); you may not use this file except in
23 * compliance with the License. You may obtain a copy of the License at
24 * http://www.mozilla.org/MPL/
26 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
27 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
28 * the specific language governing rights and limitations.
30 * The Original Code is the cairo graphics library.
32 * The Initial Developer of the Original Code is Red Hat, Inc.
35 * Carl Worth <cworth@cworth.org>
36 * Chris Wilson <chris@chris-wilson.co.uk>
41 #include "cairo-gl-private.h"
43 #include "cairo-error-private.h"
45 typedef struct _cairo_egl_context {
46 cairo_gl_context_t base;
51 EGLSurface dummy_surface;
52 } cairo_egl_context_t;
54 typedef struct _cairo_egl_surface {
55 cairo_gl_surface_t base;
58 } cairo_egl_surface_t;
62 _egl_acquire (void *abstract_ctx)
64 cairo_egl_context_t *ctx = abstract_ctx;
65 EGLSurface current_surface;
67 if (ctx->base.current_target == NULL ||
68 _cairo_gl_surface_is_texture (ctx->base.current_target)) {
69 current_surface = ctx->dummy_surface;
71 cairo_egl_surface_t *surface = (cairo_egl_surface_t *) ctx->base.current_target;
72 current_surface = surface->egl ;
75 eglMakeCurrent (ctx->display,
76 current_surface, current_surface, ctx->context);
80 _egl_release (void *abstract_ctx)
82 cairo_egl_context_t *ctx = abstract_ctx;
84 eglMakeCurrent (ctx->display,
85 EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
89 _egl_make_current (void *abstract_ctx,
90 cairo_gl_surface_t *abstract_surface)
92 cairo_egl_context_t *ctx = abstract_ctx;
93 cairo_egl_surface_t *surface = (cairo_egl_surface_t *) abstract_surface;
95 eglMakeCurrent(ctx->display, surface->egl, surface->egl, ctx->context);
99 _egl_swap_buffers (void *abstract_ctx,
100 cairo_gl_surface_t *abstract_surface)
102 cairo_egl_context_t *ctx = abstract_ctx;
103 cairo_egl_surface_t *surface = (cairo_egl_surface_t *) abstract_surface;
105 eglSwapBuffers (ctx->display, surface->egl);
109 _egl_destroy (void *abstract_ctx)
111 cairo_egl_context_t *ctx = abstract_ctx;
113 eglMakeCurrent (ctx->display,
114 EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
115 eglDestroySurface (ctx->display, ctx->dummy_surface);
119 _egl_make_current_surfaceless(cairo_egl_context_t *ctx)
121 const char *extensions;
123 extensions = eglQueryString(ctx->display, EGL_EXTENSIONS);
124 if (!strstr(extensions, "EGL_KHR_surfaceless_opengl"))
126 if (!eglMakeCurrent(ctx->display,
127 EGL_NO_SURFACE, EGL_NO_SURFACE, ctx->context))
134 cairo_egl_device_create (EGLDisplay dpy, EGLContext egl)
136 cairo_egl_context_t *ctx;
137 cairo_status_t status;
146 ctx = calloc (1, sizeof (cairo_egl_context_t));
147 if (unlikely (ctx == NULL))
148 return _cairo_gl_context_create_in_error (CAIRO_STATUS_NO_MEMORY);
153 ctx->base.acquire = _egl_acquire;
154 ctx->base.release = _egl_release;
155 ctx->base.make_current = _egl_make_current;
156 ctx->base.swap_buffers = _egl_swap_buffers;
157 ctx->base.destroy = _egl_destroy;
159 if (!_egl_make_current_surfaceless (ctx)) {
160 /* Fall back to dummy surface, meh. */
161 EGLint config_attribs[] = {
167 * In order to be able to make an egl context current when using a
168 * pbuffer surface, that surface must have been created with a config
169 * that is compatible with the context config. For Mesa, this means
170 * that the configs must be the same.
172 eglQueryContext (dpy, egl, EGL_CONFIG_ID, &config_attribs[1]);
173 eglChooseConfig (dpy, config_attribs, &config, 1, &numConfigs);
175 ctx->dummy_surface = eglCreatePbufferSurface (dpy, config, attribs);
177 if (ctx->dummy_surface == NULL) {
179 return _cairo_gl_context_create_in_error (CAIRO_STATUS_NO_MEMORY);
182 if (!eglMakeCurrent (dpy, ctx->dummy_surface, ctx->dummy_surface, egl)) {
184 return _cairo_gl_context_create_in_error (CAIRO_STATUS_NO_MEMORY);
188 status = _cairo_gl_dispatch_init (&ctx->base.dispatch, eglGetProcAddress);
189 if (unlikely (status)) {
191 return _cairo_gl_context_create_in_error (status);
194 status = _cairo_gl_context_init (&ctx->base);
195 if (unlikely (status)) {
196 if (ctx->dummy_surface != EGL_NO_SURFACE)
197 eglDestroySurface (dpy, ctx->dummy_surface);
199 return _cairo_gl_context_create_in_error (status);
202 eglMakeCurrent (dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
204 return &ctx->base.base;
208 cairo_gl_surface_create_for_egl (cairo_device_t *device,
213 cairo_egl_surface_t *surface;
215 if (unlikely (device->status))
216 return _cairo_surface_create_in_error (device->status);
218 if (device->backend->type != CAIRO_DEVICE_TYPE_GL)
219 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH));
221 surface = calloc (1, sizeof (cairo_egl_surface_t));
222 if (unlikely (surface == NULL))
223 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
225 _cairo_gl_surface_init (device, &surface->base,
226 CAIRO_CONTENT_COLOR_ALPHA, width, height);
229 return &surface->base.base;