1 /* cairo - a vector graphics library with display and print output
3 * Copyright © 2010 Linaro Limited
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.
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
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/
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.
29 * Alexandros Frantzis <alexandros.frantzis@linaro.org>
33 #include "cairo-gl-private.h"
34 #include "cairo-gl-dispatch-private.h"
41 _cairo_gl_dispatch_open_lib (void)
43 return dlopen (NULL
, RTLD_LAZY
);
47 _cairo_gl_dispatch_close_lib (void *handle
)
52 static cairo_gl_generic_func_t
53 _cairo_gl_dispatch_get_proc_addr (void *handle
, const char *name
)
55 return (cairo_gl_generic_func_t
) dlsym (handle
, name
);
59 _cairo_gl_dispatch_open_lib (void)
65 _cairo_gl_dispatch_close_lib (void *handle
)
70 static cairo_gl_generic_func_t
71 _cairo_gl_dispatch_get_proc_addr (void *handle
, const char *name
)
75 #endif /* CAIRO_HAS_DLSYM */
79 _cairo_gl_dispatch_init_entries (cairo_gl_dispatch_t
*dispatch
,
80 cairo_gl_get_proc_addr_func_t get_proc_addr
,
81 cairo_gl_dispatch_entry_t
*entries
,
82 cairo_gl_dispatch_name_t dispatch_name
)
84 cairo_gl_dispatch_entry_t
*entry
= entries
;
85 void *handle
= _cairo_gl_dispatch_open_lib ();
87 while (entry
->name
[CAIRO_GL_DISPATCH_NAME_CORE
] != NULL
) {
88 void *dispatch_ptr
= &((char *) dispatch
)[entry
->offset
];
89 const char *name
= entry
->name
[dispatch_name
];
92 * In strictly conforming EGL implementations, eglGetProcAddress() can
93 * be used only to get extension functions, but some of the functions
94 * we want belong to core GL(ES). If the *GetProcAddress function
95 * provided by the context fails, try to get the address of the wanted
96 * GL function using standard system facilities (eg dlsym() in *nix
99 cairo_gl_generic_func_t func
= get_proc_addr (name
);
101 func
= _cairo_gl_dispatch_get_proc_addr (handle
, name
);
103 *((cairo_gl_generic_func_t
*) dispatch_ptr
) = func
;
108 _cairo_gl_dispatch_close_lib (handle
);
111 static cairo_status_t
112 _cairo_gl_dispatch_init_buffers (cairo_gl_dispatch_t
*dispatch
,
113 cairo_gl_get_proc_addr_func_t get_proc_addr
,
114 int gl_version
, cairo_gl_flavor_t gl_flavor
)
116 cairo_gl_dispatch_name_t dispatch_name
;
118 if (gl_flavor
== CAIRO_GL_FLAVOR_DESKTOP
)
120 if (gl_version
>= CAIRO_GL_VERSION_ENCODE (1, 5))
121 dispatch_name
= CAIRO_GL_DISPATCH_NAME_CORE
;
122 else if (_cairo_gl_has_extension ("GL_ARB_vertex_buffer_object"))
123 dispatch_name
= CAIRO_GL_DISPATCH_NAME_EXT
;
125 return CAIRO_STATUS_DEVICE_ERROR
;
127 else if (gl_flavor
== CAIRO_GL_FLAVOR_ES
&&
128 gl_version
>= CAIRO_GL_VERSION_ENCODE (2, 0))
130 dispatch_name
= CAIRO_GL_DISPATCH_NAME_ES
;
134 return CAIRO_STATUS_DEVICE_ERROR
;
137 _cairo_gl_dispatch_init_entries (dispatch
, get_proc_addr
,
138 dispatch_buffers_entries
, dispatch_name
);
140 return CAIRO_STATUS_SUCCESS
;
143 static cairo_status_t
144 _cairo_gl_dispatch_init_shaders (cairo_gl_dispatch_t
*dispatch
,
145 cairo_gl_get_proc_addr_func_t get_proc_addr
,
146 int gl_version
, cairo_gl_flavor_t gl_flavor
)
148 cairo_gl_dispatch_name_t dispatch_name
;
150 if (gl_flavor
== CAIRO_GL_FLAVOR_DESKTOP
)
152 if (gl_version
>= CAIRO_GL_VERSION_ENCODE (2, 0))
153 dispatch_name
= CAIRO_GL_DISPATCH_NAME_CORE
;
154 else if (_cairo_gl_has_extension ("GL_ARB_shader_objects"))
155 dispatch_name
= CAIRO_GL_DISPATCH_NAME_EXT
;
157 return CAIRO_STATUS_DEVICE_ERROR
;
159 else if (gl_flavor
== CAIRO_GL_FLAVOR_ES
&&
160 gl_version
>= CAIRO_GL_VERSION_ENCODE (2, 0))
162 dispatch_name
= CAIRO_GL_DISPATCH_NAME_ES
;
166 return CAIRO_STATUS_DEVICE_ERROR
;
169 _cairo_gl_dispatch_init_entries (dispatch
, get_proc_addr
,
170 dispatch_shaders_entries
, dispatch_name
);
172 return CAIRO_STATUS_SUCCESS
;
175 static cairo_status_t
176 _cairo_gl_dispatch_init_fbo (cairo_gl_dispatch_t
*dispatch
,
177 cairo_gl_get_proc_addr_func_t get_proc_addr
,
178 int gl_version
, cairo_gl_flavor_t gl_flavor
)
180 cairo_gl_dispatch_name_t dispatch_name
;
182 if (gl_flavor
== CAIRO_GL_FLAVOR_DESKTOP
)
184 if (gl_version
>= CAIRO_GL_VERSION_ENCODE (3, 0) ||
185 _cairo_gl_has_extension ("GL_ARB_framebuffer_object"))
186 dispatch_name
= CAIRO_GL_DISPATCH_NAME_CORE
;
187 else if (_cairo_gl_has_extension ("GL_EXT_framebuffer_object"))
188 dispatch_name
= CAIRO_GL_DISPATCH_NAME_EXT
;
190 return CAIRO_STATUS_DEVICE_ERROR
;
192 else if (gl_flavor
== CAIRO_GL_FLAVOR_ES
&&
193 gl_version
>= CAIRO_GL_VERSION_ENCODE (2, 0))
195 dispatch_name
= CAIRO_GL_DISPATCH_NAME_ES
;
199 return CAIRO_STATUS_DEVICE_ERROR
;
202 _cairo_gl_dispatch_init_entries (dispatch
, get_proc_addr
,
203 dispatch_fbo_entries
, dispatch_name
);
205 return CAIRO_STATUS_SUCCESS
;
208 static cairo_status_t
209 _cairo_gl_dispatch_init_multisampling (cairo_gl_dispatch_t
*dispatch
,
210 cairo_gl_get_proc_addr_func_t get_proc_addr
,
212 cairo_gl_flavor_t gl_flavor
)
214 /* For the multisampling table, there are two GLES versions of the
215 * extension, so we put one in the EXT slot and one in the real ES slot.*/
216 cairo_gl_dispatch_name_t dispatch_name
= CAIRO_GL_DISPATCH_NAME_CORE
;
217 if (gl_flavor
== CAIRO_GL_FLAVOR_ES
) {
218 if (_cairo_gl_has_extension ("GL_EXT_multisampled_render_to_texture"))
219 dispatch_name
= CAIRO_GL_DISPATCH_NAME_EXT
;
220 else if (_cairo_gl_has_extension ("GL_IMG_multisampled_render_to_texture"))
221 dispatch_name
= CAIRO_GL_DISPATCH_NAME_ES
;
223 _cairo_gl_dispatch_init_entries (dispatch
, get_proc_addr
,
224 dispatch_multisampling_entries
,
226 return CAIRO_STATUS_SUCCESS
;
230 _cairo_gl_dispatch_init (cairo_gl_dispatch_t
*dispatch
,
231 cairo_gl_get_proc_addr_func_t get_proc_addr
)
233 cairo_status_t status
;
235 cairo_gl_flavor_t gl_flavor
;
237 gl_version
= _cairo_gl_get_version ();
238 gl_flavor
= _cairo_gl_get_flavor ();
240 status
= _cairo_gl_dispatch_init_buffers (dispatch
, get_proc_addr
,
241 gl_version
, gl_flavor
);
242 if (status
!= CAIRO_STATUS_SUCCESS
)
245 status
= _cairo_gl_dispatch_init_shaders (dispatch
, get_proc_addr
,
246 gl_version
, gl_flavor
);
247 if (status
!= CAIRO_STATUS_SUCCESS
)
250 status
= _cairo_gl_dispatch_init_fbo (dispatch
, get_proc_addr
,
251 gl_version
, gl_flavor
);
252 if (status
!= CAIRO_STATUS_SUCCESS
)
255 status
= _cairo_gl_dispatch_init_multisampling (dispatch
, get_proc_addr
,
256 gl_version
, gl_flavor
);
257 if (status
!= CAIRO_STATUS_SUCCESS
)
260 return CAIRO_STATUS_SUCCESS
;