Update change log.
[platform/upstream/cairo.git] / boilerplate / cairo-boilerplate-egl.c
1 /* Cairo - a vector graphics library with display and print output
2  *
3  * Copyright © 2009 Chris Wilson
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it either under the terms of the GNU Lesser General Public
7  * License version 2.1 as published by the Free Software Foundation
8  * (the "LGPL") or, at your option, under the terms of the Mozilla
9  * Public License Version 1.1 (the "MPL"). If you do not alter this
10  * notice, a recipient may use your version of this file under either
11  * the MPL or the LGPL.
12  *
13  * You should have received a copy of the LGPL along with this library
14  * in the file COPYING-LGPL-2.1; if not, write to the Free Software
15  * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
16  * You should have received a copy of the MPL along with this library
17  * in the file COPYING-MPL-1.1
18  *
19  * The contents of this file are subject to the Mozilla Public License
20  * Version 1.1 (the "License"); you may not use this file except in
21  * compliance with the License. You may obtain a copy of the License at
22  * http://www.mozilla.org/MPL/
23  *
24  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
25  * OF ANY KIND, either express or implied. See the LGPL or the MPL for
26  * the specific language governing rights and limitations.
27  *
28  * The Original Code is the cairo graphics library.
29  *
30  * The Initial Developer of the Original Code is Chris Wilson.
31  */
32
33 #include "cairo-boilerplate-private.h"
34
35 #include <cairo-gl.h>
36 #if CAIRO_HAS_GL_SURFACE
37 #include <GL/gl.h>
38 #elif CAIRO_HAS_GLESV2_SURFACE
39 #include <GLES2/gl2.h>
40 #endif
41
42 static const cairo_user_data_key_t gl_closure_key;
43
44 typedef struct _egl_target_closure {
45     EGLDisplay dpy;
46     EGLContext ctx;
47
48     cairo_device_t *device;
49     cairo_surface_t *surface;
50 } egl_target_closure_t;
51
52 static void
53 _cairo_boilerplate_egl_cleanup (void *closure)
54 {
55     egl_target_closure_t *gltc = closure;
56
57     cairo_device_finish (gltc->device);
58     cairo_device_destroy (gltc->device);
59
60     eglDestroyContext (gltc->dpy, gltc->ctx);
61     eglMakeCurrent (gltc->dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
62     eglTerminate (gltc->dpy);
63
64     free (gltc);
65 }
66
67 static cairo_surface_t *
68 _cairo_boilerplate_egl_create_surface (const char                *name,
69                                        cairo_content_t            content,
70                                        double                     width,
71                                        double                     height,
72                                        double                     max_width,
73                                        double                     max_height,
74                                        cairo_boilerplate_mode_t   mode,
75                                        void                     **closure)
76 {
77     egl_target_closure_t *gltc;
78     cairo_surface_t *surface;
79     int major, minor;
80     EGLConfig config;
81     EGLint numConfigs;
82     EGLint config_attribs[] = {
83         EGL_RED_SIZE, 8,
84         EGL_GREEN_SIZE, 8,
85         EGL_BLUE_SIZE, 8,
86         EGL_ALPHA_SIZE, 8,
87         EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
88 #if CAIRO_HAS_GL_SURFACE
89         EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
90 #elif CAIRO_HAS_GLESV2_SURFACE
91         EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
92 #endif
93         EGL_NONE
94     };
95     const EGLint ctx_attribs[] = {
96 #if CAIRO_HAS_GLESV2_SURFACE
97         EGL_CONTEXT_CLIENT_VERSION, 2,
98 #endif
99         EGL_NONE
100     };
101
102     gltc = xcalloc (1, sizeof (egl_target_closure_t));
103     *closure = gltc;
104
105     gltc->dpy = eglGetDisplay (EGL_DEFAULT_DISPLAY);
106
107     if (! eglInitialize (gltc->dpy, &major, &minor)) {
108         free (gltc);
109         return NULL;
110     }
111
112     eglChooseConfig (gltc->dpy, config_attribs, &config, 1, &numConfigs);
113     if (numConfigs == 0) {
114         free (gltc);
115         return NULL;
116     }
117
118 #if CAIRO_HAS_GL_SURFACE
119     eglBindAPI (EGL_OPENGL_API);
120 #elif CAIRO_HAS_GLESV2_SURFACE
121     eglBindAPI (EGL_OPENGL_ES_API);
122 #endif
123
124     gltc->ctx = eglCreateContext (gltc->dpy, config, EGL_NO_CONTEXT,
125                                   ctx_attribs);
126     if (gltc->ctx == EGL_NO_CONTEXT) {
127         eglTerminate (gltc->dpy);
128         free (gltc);
129         return NULL;
130     }
131
132     gltc->device = cairo_egl_device_create (gltc->dpy, gltc->ctx);
133     if (mode == CAIRO_BOILERPLATE_MODE_PERF)
134         cairo_gl_device_set_thread_aware(gltc->device, FALSE);
135
136     if (width < 1)
137         width = 1;
138     if (height < 1)
139         height = 1;
140
141     gltc->surface = surface = cairo_gl_surface_create (gltc->device,
142                                                        content,
143                                                        ceil (width),
144                                                        ceil (height));
145     if (cairo_surface_status (surface))
146         _cairo_boilerplate_egl_cleanup (gltc);
147
148     return surface;
149 }
150
151 static void
152 _cairo_boilerplate_egl_synchronize (void *closure)
153 {
154     egl_target_closure_t *gltc = closure;
155
156     if (cairo_device_acquire (gltc->device))
157         return;
158
159     glFinish ();
160
161     cairo_device_release (gltc->device);
162 }
163
164 static const cairo_boilerplate_target_t targets[] = {
165     {
166         "egl", "gl", NULL, NULL,
167         CAIRO_SURFACE_TYPE_GL, CAIRO_CONTENT_COLOR_ALPHA, 1,
168         "cairo_egl_device_create",
169         _cairo_boilerplate_egl_create_surface,
170         cairo_surface_create_similar,
171         NULL, NULL,
172         _cairo_boilerplate_get_image_surface,
173         cairo_surface_write_to_png,
174         _cairo_boilerplate_egl_cleanup,
175         _cairo_boilerplate_egl_synchronize,
176         NULL,
177         TRUE, FALSE, FALSE
178     }
179 };
180 CAIRO_BOILERPLATE (egl, targets)