blob: 8a0522ef6ba81def1b4693d0d090b517bcbb6862 [file] [log] [blame]
Jesse Hall47743382013-02-08 11:13:46 -08001/*
Mathias Agopian518ec112011-05-13 16:21:08 -07002 ** Copyright 2007, The Android Open Source Project
3 **
Jesse Hall47743382013-02-08 11:13:46 -08004 ** Licensed under the Apache License, Version 2.0 (the "License");
5 ** you may not use this file except in compliance with the License.
6 ** You may obtain a copy of the License at
Mathias Agopian518ec112011-05-13 16:21:08 -07007 **
Jesse Hall47743382013-02-08 11:13:46 -08008 ** http://www.apache.org/licenses/LICENSE-2.0
Mathias Agopian518ec112011-05-13 16:21:08 -07009 **
Jesse Hall47743382013-02-08 11:13:46 -080010 ** Unless required by applicable law or agreed to in writing, software
11 ** distributed under the License is distributed on an "AS IS" BASIS,
12 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 ** See the License for the specific language governing permissions and
Mathias Agopian518ec112011-05-13 16:21:08 -070014 ** limitations under the License.
15 */
16
Jamie Gennis1c8e95c2012-02-23 19:27:23 -080017#define ATRACE_TAG ATRACE_TAG_GRAPHICS
18
Jesse Hallc07b5202013-07-04 12:08:16 -070019#include <dlfcn.h>
Mathias Agopian518ec112011-05-13 16:21:08 -070020#include <ctype.h>
21#include <stdlib.h>
22#include <string.h>
23
24#include <hardware/gralloc.h>
25#include <system/window.h>
26
27#include <EGL/egl.h>
28#include <EGL/eglext.h>
Mathias Agopian518ec112011-05-13 16:21:08 -070029
30#include <cutils/log.h>
31#include <cutils/atomic.h>
Mathias Agopian7db993a2012-03-25 00:49:46 -070032#include <cutils/compiler.h>
Mathias Agopian518ec112011-05-13 16:21:08 -070033#include <cutils/properties.h>
34#include <cutils/memory.h>
35
36#include <utils/KeyedVector.h>
37#include <utils/SortedVector.h>
38#include <utils/String8.h>
Jamie Gennis1c8e95c2012-02-23 19:27:23 -080039#include <utils/Trace.h>
Mathias Agopian518ec112011-05-13 16:21:08 -070040
Mathias Agopian39c24a22013-04-04 23:17:56 -070041#include "../egl_impl.h"
42#include "../glestrace.h"
43#include "../hooks.h"
Mathias Agopian518ec112011-05-13 16:21:08 -070044
45#include "egl_display.h"
Mathias Agopian518ec112011-05-13 16:21:08 -070046#include "egl_object.h"
47#include "egl_tls.h"
Mathias Agopianada798b2012-02-13 17:09:30 -080048#include "egldefs.h"
Mathias Agopian518ec112011-05-13 16:21:08 -070049
50using namespace android;
51
52// ----------------------------------------------------------------------------
53
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070054namespace android {
55
Mathias Agopian518ec112011-05-13 16:21:08 -070056struct extention_map_t {
57 const char* name;
58 __eglMustCastToProperFunctionPointerType address;
59};
60
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070061/*
Jesse Hall21558da2013-08-06 15:31:22 -070062 * This is the list of EGL extensions exposed to applications.
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070063 *
Jesse Hall21558da2013-08-06 15:31:22 -070064 * Some of them (gBuiltinExtensionString) are implemented entirely in this EGL
65 * wrapper and are always available.
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070066 *
Jesse Hall21558da2013-08-06 15:31:22 -070067 * The rest (gExtensionString) depend on support in the EGL driver, and are
68 * only available if the driver supports them. However, some of these must be
69 * supported because they are used by the Android system itself; these are
70 * listd as mandatory below and are required by the CDD. The system *assumes*
71 * the mandatory extensions are present and may not function properly if some
72 * are missing.
73 *
74 * NOTE: Both strings MUST have a single space as the last character.
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070075 */
Jesse Hall21558da2013-08-06 15:31:22 -070076extern char const * const gBuiltinExtensionString =
77 "EGL_KHR_get_all_proc_addresses "
78 "EGL_ANDROID_presentation_time "
79 ;
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070080extern char const * const gExtensionString =
81 "EGL_KHR_image " // mandatory
82 "EGL_KHR_image_base " // mandatory
83 "EGL_KHR_image_pixmap "
84 "EGL_KHR_lock_surface "
85 "EGL_KHR_gl_texture_2D_image "
86 "EGL_KHR_gl_texture_cubemap_image "
87 "EGL_KHR_gl_renderbuffer_image "
88 "EGL_KHR_reusable_sync "
89 "EGL_KHR_fence_sync "
Jamie Gennisf6d1c392013-04-25 18:48:41 -070090 "EGL_KHR_create_context "
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070091 "EGL_EXT_create_context_robustness "
92 "EGL_NV_system_time "
93 "EGL_ANDROID_image_native_buffer " // mandatory
Mathias Agopian2bb71682013-03-27 17:32:41 -070094 "EGL_KHR_wait_sync " // strongly recommended
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070095 ;
96
97// extensions not exposed to applications but used by the ANDROID system
98// "EGL_ANDROID_blob_cache " // strongly recommended
99// "EGL_IMG_hibernate_process " // optional
100// "EGL_ANDROID_native_fence_sync " // strongly recommended
101// "EGL_ANDROID_framebuffer_target " // mandatory for HWC 1.1
102// "EGL_ANDROID_recordable " // mandatory
103
104
105/*
106 * EGL Extensions entry-points exposed to 3rd party applications
107 * (keep in sync with gExtensionString above)
108 *
109 */
110static const extention_map_t sExtensionMap[] = {
111 // EGL_KHR_lock_surface
Mathias Agopian518ec112011-05-13 16:21:08 -0700112 { "eglLockSurfaceKHR",
113 (__eglMustCastToProperFunctionPointerType)&eglLockSurfaceKHR },
114 { "eglUnlockSurfaceKHR",
115 (__eglMustCastToProperFunctionPointerType)&eglUnlockSurfaceKHR },
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700116
117 // EGL_KHR_image, EGL_KHR_image_base
Mathias Agopian518ec112011-05-13 16:21:08 -0700118 { "eglCreateImageKHR",
119 (__eglMustCastToProperFunctionPointerType)&eglCreateImageKHR },
120 { "eglDestroyImageKHR",
121 (__eglMustCastToProperFunctionPointerType)&eglDestroyImageKHR },
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700122
123 // EGL_KHR_reusable_sync, EGL_KHR_fence_sync
124 { "eglCreateSyncKHR",
125 (__eglMustCastToProperFunctionPointerType)&eglCreateSyncKHR },
126 { "eglDestroySyncKHR",
127 (__eglMustCastToProperFunctionPointerType)&eglDestroySyncKHR },
128 { "eglClientWaitSyncKHR",
129 (__eglMustCastToProperFunctionPointerType)&eglClientWaitSyncKHR },
130 { "eglSignalSyncKHR",
131 (__eglMustCastToProperFunctionPointerType)&eglSignalSyncKHR },
132 { "eglGetSyncAttribKHR",
133 (__eglMustCastToProperFunctionPointerType)&eglGetSyncAttribKHR },
134
135 // EGL_NV_system_time
Jonas Yang1c3d72a2011-08-26 20:04:39 +0800136 { "eglGetSystemTimeFrequencyNV",
137 (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeFrequencyNV },
138 { "eglGetSystemTimeNV",
139 (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeNV },
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700140
Mathias Agopian2bb71682013-03-27 17:32:41 -0700141 // EGL_KHR_wait_sync
142 { "eglWaitSyncKHR",
143 (__eglMustCastToProperFunctionPointerType)&eglWaitSyncKHR },
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700144
145 // EGL_ANDROID_presentation_time
146 { "eglPresentationTimeANDROID",
147 (__eglMustCastToProperFunctionPointerType)&eglPresentationTimeANDROID },
Mathias Agopian518ec112011-05-13 16:21:08 -0700148};
149
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700150/*
151 * These extensions entry-points should not be exposed to applications.
152 * They're used internally by the Android EGL layer.
153 */
154#define FILTER_EXTENSIONS(procname) \
155 (!strcmp((procname), "eglSetBlobCacheFuncsANDROID") || \
156 !strcmp((procname), "eglHibernateProcessIMG") || \
157 !strcmp((procname), "eglAwakenProcessIMG") || \
158 !strcmp((procname), "eglDupNativeFenceFDANDROID"))
159
160
161
Mathias Agopian518ec112011-05-13 16:21:08 -0700162// accesses protected by sExtensionMapMutex
163static DefaultKeyedVector<String8, __eglMustCastToProperFunctionPointerType> sGLExtentionMap;
164static int sGLExtentionSlot = 0;
165static pthread_mutex_t sExtensionMapMutex = PTHREAD_MUTEX_INITIALIZER;
166
167static void(*findProcAddress(const char* name,
168 const extention_map_t* map, size_t n))() {
169 for (uint32_t i=0 ; i<n ; i++) {
170 if (!strcmp(name, map[i].name)) {
171 return map[i].address;
172 }
173 }
174 return NULL;
175}
176
177// ----------------------------------------------------------------------------
178
Mathias Agopian518ec112011-05-13 16:21:08 -0700179extern void setGLHooksThreadSpecific(gl_hooks_t const *value);
180extern EGLBoolean egl_init_drivers();
181extern const __eglMustCastToProperFunctionPointerType gExtensionForwarders[MAX_NUMBER_OF_GL_EXTENSIONS];
Siva Velusamya73a9772012-12-18 14:56:55 -0800182extern int getEGLDebugLevel();
183extern void setEGLDebugLevel(int level);
Mathias Agopian518ec112011-05-13 16:21:08 -0700184extern gl_hooks_t gHooksTrace;
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700185
Mathias Agopian518ec112011-05-13 16:21:08 -0700186} // namespace android;
187
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700188
Mathias Agopian518ec112011-05-13 16:21:08 -0700189// ----------------------------------------------------------------------------
190
191static inline void clearError() { egl_tls_t::clearError(); }
192static inline EGLContext getContext() { return egl_tls_t::getContext(); }
193
194// ----------------------------------------------------------------------------
195
196EGLDisplay eglGetDisplay(EGLNativeDisplayType display)
197{
198 clearError();
199
200 uint32_t index = uint32_t(display);
201 if (index >= NUM_DISPLAYS) {
202 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
203 }
204
205 if (egl_init_drivers() == EGL_FALSE) {
206 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
207 }
208
209 EGLDisplay dpy = egl_display_t::getFromNativeDisplay(display);
210 return dpy;
211}
212
213// ----------------------------------------------------------------------------
214// Initialization
215// ----------------------------------------------------------------------------
216
217EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
218{
219 clearError();
220
Jesse Hallb29e5e82012-04-04 16:53:42 -0700221 egl_display_ptr dp = get_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700222 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
223
224 EGLBoolean res = dp->initialize(major, minor);
225
226 return res;
227}
228
229EGLBoolean eglTerminate(EGLDisplay dpy)
230{
231 // NOTE: don't unload the drivers b/c some APIs can be called
232 // after eglTerminate() has been called. eglTerminate() only
233 // terminates an EGLDisplay, not a EGL itself.
234
235 clearError();
236
Jesse Hallb29e5e82012-04-04 16:53:42 -0700237 egl_display_ptr dp = get_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700238 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
239
240 EGLBoolean res = dp->terminate();
Jesse Hall47743382013-02-08 11:13:46 -0800241
Mathias Agopian518ec112011-05-13 16:21:08 -0700242 return res;
243}
244
245// ----------------------------------------------------------------------------
246// configuration
247// ----------------------------------------------------------------------------
248
249EGLBoolean eglGetConfigs( EGLDisplay dpy,
250 EGLConfig *configs,
251 EGLint config_size, EGLint *num_config)
252{
253 clearError();
254
Jesse Hallb29e5e82012-04-04 16:53:42 -0700255 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700256 if (!dp) return EGL_FALSE;
257
Mathias Agopian7773c432012-02-13 20:06:08 -0800258 if (num_config==0) {
259 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700260 }
261
Mathias Agopian7773c432012-02-13 20:06:08 -0800262 EGLBoolean res = EGL_FALSE;
263 *num_config = 0;
264
265 egl_connection_t* const cnx = &gEGLImpl;
266 if (cnx->dso) {
267 res = cnx->egl.eglGetConfigs(
268 dp->disp.dpy, configs, config_size, num_config);
Mathias Agopian518ec112011-05-13 16:21:08 -0700269 }
Mathias Agopian7773c432012-02-13 20:06:08 -0800270
271 return res;
Mathias Agopian518ec112011-05-13 16:21:08 -0700272}
273
274EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list,
275 EGLConfig *configs, EGLint config_size,
276 EGLint *num_config)
277{
278 clearError();
279
Jesse Hallb29e5e82012-04-04 16:53:42 -0700280 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700281 if (!dp) return EGL_FALSE;
282
283 if (num_config==0) {
284 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
285 }
286
Mathias Agopian518ec112011-05-13 16:21:08 -0700287 EGLBoolean res = EGL_FALSE;
288 *num_config = 0;
289
Mathias Agopianada798b2012-02-13 17:09:30 -0800290 egl_connection_t* const cnx = &gEGLImpl;
291 if (cnx->dso) {
Romain Guy1cffc802012-10-15 18:13:05 -0700292 if (attrib_list) {
293 char value[PROPERTY_VALUE_MAX];
294 property_get("debug.egl.force_msaa", value, "false");
295
296 if (!strcmp(value, "true")) {
297 size_t attribCount = 0;
298 EGLint attrib = attrib_list[0];
299
300 // Only enable MSAA if the context is OpenGL ES 2.0 and
Romain Guybe3c3e42012-10-15 19:25:18 -0700301 // if no caveat is requested
Romain Guy1cffc802012-10-15 18:13:05 -0700302 const EGLint *attribRendererable = NULL;
303 const EGLint *attribCaveat = NULL;
304
305 // Count the number of attributes and look for
Romain Guybe3c3e42012-10-15 19:25:18 -0700306 // EGL_RENDERABLE_TYPE and EGL_CONFIG_CAVEAT
Romain Guy1cffc802012-10-15 18:13:05 -0700307 while (attrib != EGL_NONE) {
308 attrib = attrib_list[attribCount];
309 switch (attrib) {
310 case EGL_RENDERABLE_TYPE:
311 attribRendererable = &attrib_list[attribCount];
312 break;
313 case EGL_CONFIG_CAVEAT:
314 attribCaveat = &attrib_list[attribCount];
315 break;
316 }
317 attribCount++;
318 }
319
320 if (attribRendererable && attribRendererable[1] == EGL_OPENGL_ES2_BIT &&
321 (!attribCaveat || attribCaveat[1] != EGL_NONE)) {
Jesse Hall47743382013-02-08 11:13:46 -0800322
Romain Guy1cffc802012-10-15 18:13:05 -0700323 // Insert 2 extra attributes to force-enable MSAA 4x
324 EGLint aaAttribs[attribCount + 4];
325 aaAttribs[0] = EGL_SAMPLE_BUFFERS;
326 aaAttribs[1] = 1;
327 aaAttribs[2] = EGL_SAMPLES;
328 aaAttribs[3] = 4;
329
330 memcpy(&aaAttribs[4], attrib_list, attribCount * sizeof(EGLint));
331
332 EGLint numConfigAA;
333 EGLBoolean resAA = cnx->egl.eglChooseConfig(
334 dp->disp.dpy, aaAttribs, configs, config_size, &numConfigAA);
335
336 if (resAA == EGL_TRUE && numConfigAA > 0) {
337 ALOGD("Enabling MSAA 4x");
338 *num_config = numConfigAA;
339 return resAA;
340 }
341 }
342 }
343 }
344
Mathias Agopian7773c432012-02-13 20:06:08 -0800345 res = cnx->egl.eglChooseConfig(
346 dp->disp.dpy, attrib_list, configs, config_size, num_config);
Mathias Agopian518ec112011-05-13 16:21:08 -0700347 }
348 return res;
349}
350
351EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
352 EGLint attribute, EGLint *value)
353{
354 clearError();
355
Jesse Hallb29e5e82012-04-04 16:53:42 -0700356 egl_connection_t* cnx = NULL;
357 const egl_display_ptr dp = validate_display_connection(dpy, cnx);
358 if (!dp) return EGL_FALSE;
Jesse Hall47743382013-02-08 11:13:46 -0800359
Mathias Agopian518ec112011-05-13 16:21:08 -0700360 return cnx->egl.eglGetConfigAttrib(
Mathias Agopian7773c432012-02-13 20:06:08 -0800361 dp->disp.dpy, config, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -0700362}
363
364// ----------------------------------------------------------------------------
365// surfaces
366// ----------------------------------------------------------------------------
367
368EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config,
369 NativeWindowType window,
370 const EGLint *attrib_list)
371{
372 clearError();
373
Jesse Hallb29e5e82012-04-04 16:53:42 -0700374 egl_connection_t* cnx = NULL;
375 egl_display_ptr dp = validate_display_connection(dpy, cnx);
376 if (dp) {
Mathias Agopianada798b2012-02-13 17:09:30 -0800377 EGLDisplay iDpy = dp->disp.dpy;
Mathias Agopian518ec112011-05-13 16:21:08 -0700378 EGLint format;
379
Mathias Agopian81a63352011-07-29 17:55:48 -0700380 if (native_window_api_connect(window, NATIVE_WINDOW_API_EGL) != OK) {
Steve Blocke6f43dd2012-01-06 19:20:56 +0000381 ALOGE("EGLNativeWindowType %p already connected to another API",
Mathias Agopian81a63352011-07-29 17:55:48 -0700382 window);
Jonathan Hamilton77a9b4a2013-07-17 09:41:42 -0700383 return setError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
Mathias Agopian81a63352011-07-29 17:55:48 -0700384 }
385
Mathias Agopian518ec112011-05-13 16:21:08 -0700386 // set the native window's buffers format to match this config
387 if (cnx->egl.eglGetConfigAttrib(iDpy,
Mathias Agopian7773c432012-02-13 20:06:08 -0800388 config, EGL_NATIVE_VISUAL_ID, &format)) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700389 if (format != 0) {
Jamie Gennisbee205f2011-07-01 13:12:07 -0700390 int err = native_window_set_buffers_format(window, format);
391 if (err != 0) {
Steve Blocke6f43dd2012-01-06 19:20:56 +0000392 ALOGE("error setting native window pixel format: %s (%d)",
Jamie Gennisbee205f2011-07-01 13:12:07 -0700393 strerror(-err), err);
Mathias Agopian81a63352011-07-29 17:55:48 -0700394 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
Jamie Gennisbee205f2011-07-01 13:12:07 -0700395 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
396 }
Mathias Agopian518ec112011-05-13 16:21:08 -0700397 }
398 }
399
Jamie Gennis59769462011-11-19 18:04:43 -0800400 // the EGL spec requires that a new EGLSurface default to swap interval
401 // 1, so explicitly set that on the window here.
402 ANativeWindow* anw = reinterpret_cast<ANativeWindow*>(window);
403 anw->setSwapInterval(anw, 1);
404
Mathias Agopian518ec112011-05-13 16:21:08 -0700405 EGLSurface surface = cnx->egl.eglCreateWindowSurface(
Mathias Agopian7773c432012-02-13 20:06:08 -0800406 iDpy, config, window, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700407 if (surface != EGL_NO_SURFACE) {
Jesse Hallb29e5e82012-04-04 16:53:42 -0700408 egl_surface_t* s = new egl_surface_t(dp.get(), config, window,
409 surface, cnx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700410 return s;
411 }
Mathias Agopian81a63352011-07-29 17:55:48 -0700412
413 // EGLSurface creation failed
414 native_window_set_buffers_format(window, 0);
415 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
Mathias Agopian518ec112011-05-13 16:21:08 -0700416 }
417 return EGL_NO_SURFACE;
418}
419
420EGLSurface eglCreatePixmapSurface( EGLDisplay dpy, EGLConfig config,
421 NativePixmapType pixmap,
422 const EGLint *attrib_list)
423{
424 clearError();
425
Jesse Hallb29e5e82012-04-04 16:53:42 -0700426 egl_connection_t* cnx = NULL;
427 egl_display_ptr dp = validate_display_connection(dpy, cnx);
428 if (dp) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700429 EGLSurface surface = cnx->egl.eglCreatePixmapSurface(
Mathias Agopian7773c432012-02-13 20:06:08 -0800430 dp->disp.dpy, config, pixmap, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700431 if (surface != EGL_NO_SURFACE) {
Jesse Hallb29e5e82012-04-04 16:53:42 -0700432 egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL,
433 surface, cnx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700434 return s;
435 }
436 }
437 return EGL_NO_SURFACE;
438}
439
440EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config,
441 const EGLint *attrib_list)
442{
443 clearError();
444
Jesse Hallb29e5e82012-04-04 16:53:42 -0700445 egl_connection_t* cnx = NULL;
446 egl_display_ptr dp = validate_display_connection(dpy, cnx);
447 if (dp) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700448 EGLSurface surface = cnx->egl.eglCreatePbufferSurface(
Mathias Agopian7773c432012-02-13 20:06:08 -0800449 dp->disp.dpy, config, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700450 if (surface != EGL_NO_SURFACE) {
Jesse Hallb29e5e82012-04-04 16:53:42 -0700451 egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL,
452 surface, cnx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700453 return s;
454 }
455 }
456 return EGL_NO_SURFACE;
457}
Jesse Hall47743382013-02-08 11:13:46 -0800458
Mathias Agopian518ec112011-05-13 16:21:08 -0700459EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
460{
461 clearError();
462
Jesse Hallb29e5e82012-04-04 16:53:42 -0700463 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700464 if (!dp) return EGL_FALSE;
465
Jesse Hallb29e5e82012-04-04 16:53:42 -0700466 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700467 if (!_s.get())
468 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700469
470 egl_surface_t * const s = get_surface(surface);
Mathias Agopianada798b2012-02-13 17:09:30 -0800471 EGLBoolean result = s->cnx->egl.eglDestroySurface(dp->disp.dpy, s->surface);
Mathias Agopian518ec112011-05-13 16:21:08 -0700472 if (result == EGL_TRUE) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700473 _s.terminate();
474 }
475 return result;
476}
477
478EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface surface,
479 EGLint attribute, EGLint *value)
480{
481 clearError();
482
Jesse Hallb29e5e82012-04-04 16:53:42 -0700483 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700484 if (!dp) return EGL_FALSE;
485
Jesse Hallb29e5e82012-04-04 16:53:42 -0700486 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700487 if (!_s.get())
488 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700489
Mathias Agopian518ec112011-05-13 16:21:08 -0700490 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian7773c432012-02-13 20:06:08 -0800491 return s->cnx->egl.eglQuerySurface(
492 dp->disp.dpy, s->surface, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -0700493}
494
Jamie Gennise8696a42012-01-15 18:54:57 -0800495void EGLAPI eglBeginFrame(EGLDisplay dpy, EGLSurface surface) {
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800496 ATRACE_CALL();
Jamie Gennise8696a42012-01-15 18:54:57 -0800497 clearError();
498
Jesse Hallb29e5e82012-04-04 16:53:42 -0700499 const egl_display_ptr dp = validate_display(dpy);
Jamie Gennise8696a42012-01-15 18:54:57 -0800500 if (!dp) {
501 return;
502 }
503
Jesse Hallb29e5e82012-04-04 16:53:42 -0700504 SurfaceRef _s(dp.get(), surface);
Jamie Gennise8696a42012-01-15 18:54:57 -0800505 if (!_s.get()) {
506 setError(EGL_BAD_SURFACE, EGL_FALSE);
507 return;
508 }
Jamie Gennise8696a42012-01-15 18:54:57 -0800509}
510
Mathias Agopian518ec112011-05-13 16:21:08 -0700511// ----------------------------------------------------------------------------
512// Contexts
513// ----------------------------------------------------------------------------
514
515EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config,
516 EGLContext share_list, const EGLint *attrib_list)
517{
518 clearError();
519
Jesse Hallb29e5e82012-04-04 16:53:42 -0700520 egl_connection_t* cnx = NULL;
521 const egl_display_ptr dp = validate_display_connection(dpy, cnx);
Michael Chock0673e1e2012-06-21 12:53:17 -0700522 if (dp) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700523 if (share_list != EGL_NO_CONTEXT) {
Michael Chock0673e1e2012-06-21 12:53:17 -0700524 if (!ContextRef(dp.get(), share_list).get()) {
525 return setError(EGL_BAD_CONTEXT, EGL_NO_CONTEXT);
526 }
Mathias Agopian518ec112011-05-13 16:21:08 -0700527 egl_context_t* const c = get_context(share_list);
528 share_list = c->context;
529 }
530 EGLContext context = cnx->egl.eglCreateContext(
Mathias Agopian7773c432012-02-13 20:06:08 -0800531 dp->disp.dpy, config, share_list, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700532 if (context != EGL_NO_CONTEXT) {
533 // figure out if it's a GLESv1 or GLESv2
534 int version = 0;
535 if (attrib_list) {
536 while (*attrib_list != EGL_NONE) {
537 GLint attr = *attrib_list++;
538 GLint value = *attrib_list++;
539 if (attr == EGL_CONTEXT_CLIENT_VERSION) {
540 if (value == 1) {
Mathias Agopian7773c432012-02-13 20:06:08 -0800541 version = egl_connection_t::GLESv1_INDEX;
Jesse Hall47743382013-02-08 11:13:46 -0800542 } else if (value == 2 || value == 3) {
Mathias Agopian7773c432012-02-13 20:06:08 -0800543 version = egl_connection_t::GLESv2_INDEX;
Mathias Agopian518ec112011-05-13 16:21:08 -0700544 }
545 }
546 };
547 }
Jesse Hallb29e5e82012-04-04 16:53:42 -0700548 egl_context_t* c = new egl_context_t(dpy, context, config, cnx,
549 version);
Siva Velusamy0469dd62011-11-30 15:05:37 -0800550#if EGL_TRACE
Siva Velusamya73a9772012-12-18 14:56:55 -0800551 if (getEGLDebugLevel() > 0)
Siva Velusamy0469dd62011-11-30 15:05:37 -0800552 GLTrace_eglCreateContext(version, c);
553#endif
Mathias Agopian518ec112011-05-13 16:21:08 -0700554 return c;
Mathias Agopian500407a2012-09-24 17:57:48 -0700555 } else {
556 EGLint error = eglGetError();
557 ALOGE_IF(error == EGL_SUCCESS,
558 "eglCreateContext(%p, %p, %p, %p) returned EGL_NO_CONTEXT "
559 "but no EGL error!",
560 dpy, config, share_list, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700561 }
562 }
563 return EGL_NO_CONTEXT;
564}
565
566EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
567{
568 clearError();
569
Jesse Hallb29e5e82012-04-04 16:53:42 -0700570 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700571 if (!dp)
572 return EGL_FALSE;
Mathias Agopian518ec112011-05-13 16:21:08 -0700573
Jesse Hallb29e5e82012-04-04 16:53:42 -0700574 ContextRef _c(dp.get(), ctx);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700575 if (!_c.get())
576 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
Jesse Hall47743382013-02-08 11:13:46 -0800577
Mathias Agopian518ec112011-05-13 16:21:08 -0700578 egl_context_t * const c = get_context(ctx);
Mathias Agopianada798b2012-02-13 17:09:30 -0800579 EGLBoolean result = c->cnx->egl.eglDestroyContext(dp->disp.dpy, c->context);
Mathias Agopian518ec112011-05-13 16:21:08 -0700580 if (result == EGL_TRUE) {
581 _c.terminate();
582 }
583 return result;
584}
585
Mathias Agopian518ec112011-05-13 16:21:08 -0700586EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw,
587 EGLSurface read, EGLContext ctx)
588{
589 clearError();
590
Jesse Hallb29e5e82012-04-04 16:53:42 -0700591 egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700592 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
593
Mathias Agopian5b287a62011-05-16 18:58:55 -0700594 // If ctx is not EGL_NO_CONTEXT, read is not EGL_NO_SURFACE, or draw is not
595 // EGL_NO_SURFACE, then an EGL_NOT_INITIALIZED error is generated if dpy is
596 // a valid but uninitialized display.
Mathias Agopian518ec112011-05-13 16:21:08 -0700597 if ( (ctx != EGL_NO_CONTEXT) || (read != EGL_NO_SURFACE) ||
598 (draw != EGL_NO_SURFACE) ) {
599 if (!dp->isReady()) return setError(EGL_NOT_INITIALIZED, EGL_FALSE);
600 }
601
602 // get a reference to the object passed in
Jesse Hallb29e5e82012-04-04 16:53:42 -0700603 ContextRef _c(dp.get(), ctx);
604 SurfaceRef _d(dp.get(), draw);
605 SurfaceRef _r(dp.get(), read);
Mathias Agopian518ec112011-05-13 16:21:08 -0700606
607 // validate the context (if not EGL_NO_CONTEXT)
Mathias Agopian5b287a62011-05-16 18:58:55 -0700608 if ((ctx != EGL_NO_CONTEXT) && !_c.get()) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700609 // EGL_NO_CONTEXT is valid
Michael Chock0673e1e2012-06-21 12:53:17 -0700610 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700611 }
612
613 // these are the underlying implementation's object
614 EGLContext impl_ctx = EGL_NO_CONTEXT;
615 EGLSurface impl_draw = EGL_NO_SURFACE;
616 EGLSurface impl_read = EGL_NO_SURFACE;
617
618 // these are our objects structs passed in
619 egl_context_t * c = NULL;
620 egl_surface_t const * d = NULL;
621 egl_surface_t const * r = NULL;
622
623 // these are the current objects structs
624 egl_context_t * cur_c = get_context(getContext());
Jesse Hall47743382013-02-08 11:13:46 -0800625
Mathias Agopian518ec112011-05-13 16:21:08 -0700626 if (ctx != EGL_NO_CONTEXT) {
627 c = get_context(ctx);
628 impl_ctx = c->context;
629 } else {
630 // no context given, use the implementation of the current context
Michael Chock0673e1e2012-06-21 12:53:17 -0700631 if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE) {
632 // calling eglMakeCurrent( ..., !=0, !=0, EGL_NO_CONTEXT);
633 return setError(EGL_BAD_MATCH, EGL_FALSE);
634 }
Mathias Agopian518ec112011-05-13 16:21:08 -0700635 if (cur_c == NULL) {
636 // no current context
Mathias Agopian518ec112011-05-13 16:21:08 -0700637 // not an error, there is just no current context.
638 return EGL_TRUE;
639 }
640 }
641
642 // retrieve the underlying implementation's draw EGLSurface
643 if (draw != EGL_NO_SURFACE) {
Michael Chock0673e1e2012-06-21 12:53:17 -0700644 if (!_d.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700645 d = get_surface(draw);
Mathias Agopian518ec112011-05-13 16:21:08 -0700646 impl_draw = d->surface;
647 }
648
649 // retrieve the underlying implementation's read EGLSurface
650 if (read != EGL_NO_SURFACE) {
Michael Chock0673e1e2012-06-21 12:53:17 -0700651 if (!_r.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700652 r = get_surface(read);
Mathias Agopian518ec112011-05-13 16:21:08 -0700653 impl_read = r->surface;
654 }
655
Mathias Agopian518ec112011-05-13 16:21:08 -0700656
Jesse Hallb29e5e82012-04-04 16:53:42 -0700657 EGLBoolean result = dp->makeCurrent(c, cur_c,
Mathias Agopianfb87e542012-01-30 18:20:52 -0800658 draw, read, ctx,
659 impl_draw, impl_read, impl_ctx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700660
661 if (result == EGL_TRUE) {
Mathias Agopianfb87e542012-01-30 18:20:52 -0800662 if (c) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700663 setGLHooksThreadSpecific(c->cnx->hooks[c->version]);
664 egl_tls_t::setContext(ctx);
Siva Velusamy0469dd62011-11-30 15:05:37 -0800665#if EGL_TRACE
Siva Velusamya73a9772012-12-18 14:56:55 -0800666 if (getEGLDebugLevel() > 0)
Siva Velusamy93a826f2011-12-14 12:19:56 -0800667 GLTrace_eglMakeCurrent(c->version, c->cnx->hooks[c->version], ctx);
Siva Velusamy0469dd62011-11-30 15:05:37 -0800668#endif
Mathias Agopian518ec112011-05-13 16:21:08 -0700669 _c.acquire();
670 _r.acquire();
671 _d.acquire();
Mathias Agopian518ec112011-05-13 16:21:08 -0700672 } else {
673 setGLHooksThreadSpecific(&gHooksNoContext);
674 egl_tls_t::setContext(EGL_NO_CONTEXT);
675 }
Mathias Agopian5fecea72011-08-25 18:38:24 -0700676 } else {
Steve Blocke6f43dd2012-01-06 19:20:56 +0000677 // this will ALOGE the error
Mathias Agopian5fecea72011-08-25 18:38:24 -0700678 result = setError(c->cnx->egl.eglGetError(), EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700679 }
680 return result;
681}
682
683
684EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx,
685 EGLint attribute, EGLint *value)
686{
687 clearError();
688
Jesse Hallb29e5e82012-04-04 16:53:42 -0700689 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700690 if (!dp) return EGL_FALSE;
691
Jesse Hallb29e5e82012-04-04 16:53:42 -0700692 ContextRef _c(dp.get(), ctx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700693 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
694
Mathias Agopian518ec112011-05-13 16:21:08 -0700695 egl_context_t * const c = get_context(ctx);
Mathias Agopian7773c432012-02-13 20:06:08 -0800696 return c->cnx->egl.eglQueryContext(
697 dp->disp.dpy, c->context, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -0700698
Mathias Agopian518ec112011-05-13 16:21:08 -0700699}
700
701EGLContext eglGetCurrentContext(void)
702{
703 // could be called before eglInitialize(), but we wouldn't have a context
704 // then, and this function would correctly return EGL_NO_CONTEXT.
705
706 clearError();
707
708 EGLContext ctx = getContext();
709 return ctx;
710}
711
712EGLSurface eglGetCurrentSurface(EGLint readdraw)
713{
714 // could be called before eglInitialize(), but we wouldn't have a context
715 // then, and this function would correctly return EGL_NO_SURFACE.
716
717 clearError();
718
719 EGLContext ctx = getContext();
720 if (ctx) {
721 egl_context_t const * const c = get_context(ctx);
722 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
723 switch (readdraw) {
724 case EGL_READ: return c->read;
Jesse Hall47743382013-02-08 11:13:46 -0800725 case EGL_DRAW: return c->draw;
Mathias Agopian518ec112011-05-13 16:21:08 -0700726 default: return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
727 }
728 }
729 return EGL_NO_SURFACE;
730}
731
732EGLDisplay eglGetCurrentDisplay(void)
733{
734 // could be called before eglInitialize(), but we wouldn't have a context
735 // then, and this function would correctly return EGL_NO_DISPLAY.
736
737 clearError();
738
739 EGLContext ctx = getContext();
740 if (ctx) {
741 egl_context_t const * const c = get_context(ctx);
742 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
743 return c->dpy;
744 }
745 return EGL_NO_DISPLAY;
746}
747
748EGLBoolean eglWaitGL(void)
749{
Mathias Agopian518ec112011-05-13 16:21:08 -0700750 clearError();
751
Mathias Agopianada798b2012-02-13 17:09:30 -0800752 egl_connection_t* const cnx = &gEGLImpl;
753 if (!cnx->dso)
754 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
755
756 return cnx->egl.eglWaitGL();
Mathias Agopian518ec112011-05-13 16:21:08 -0700757}
758
759EGLBoolean eglWaitNative(EGLint engine)
760{
Mathias Agopian518ec112011-05-13 16:21:08 -0700761 clearError();
762
Mathias Agopianada798b2012-02-13 17:09:30 -0800763 egl_connection_t* const cnx = &gEGLImpl;
764 if (!cnx->dso)
765 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
766
767 return cnx->egl.eglWaitNative(engine);
Mathias Agopian518ec112011-05-13 16:21:08 -0700768}
769
770EGLint eglGetError(void)
771{
Mathias Agopianada798b2012-02-13 17:09:30 -0800772 EGLint err = EGL_SUCCESS;
773 egl_connection_t* const cnx = &gEGLImpl;
774 if (cnx->dso) {
775 err = cnx->egl.eglGetError();
Mathias Agopian518ec112011-05-13 16:21:08 -0700776 }
Mathias Agopianada798b2012-02-13 17:09:30 -0800777 if (err == EGL_SUCCESS) {
778 err = egl_tls_t::getError();
779 }
780 return err;
Mathias Agopian518ec112011-05-13 16:21:08 -0700781}
782
Jesse Hallc07b5202013-07-04 12:08:16 -0700783static __eglMustCastToProperFunctionPointerType findBuiltinGLWrapper(
784 const char* procname) {
785 const egl_connection_t* cnx = &gEGLImpl;
786 void* proc = NULL;
787
788 proc = dlsym(cnx->libGles2, procname);
789 if (proc) return (__eglMustCastToProperFunctionPointerType)proc;
790
791 proc = dlsym(cnx->libGles1, procname);
792 if (proc) return (__eglMustCastToProperFunctionPointerType)proc;
793
794 return NULL;
795}
796
Mathias Agopian518ec112011-05-13 16:21:08 -0700797__eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
798{
799 // eglGetProcAddress() could be the very first function called
800 // in which case we must make sure we've initialized ourselves, this
801 // happens the first time egl_get_display() is called.
802
803 clearError();
804
805 if (egl_init_drivers() == EGL_FALSE) {
806 setError(EGL_BAD_PARAMETER, NULL);
807 return NULL;
808 }
809
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700810 if (FILTER_EXTENSIONS(procname)) {
Jamie Gennisaca51c02011-11-03 17:42:43 -0700811 return NULL;
812 }
813
Mathias Agopian518ec112011-05-13 16:21:08 -0700814 __eglMustCastToProperFunctionPointerType addr;
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700815 addr = findProcAddress(procname, sExtensionMap, NELEM(sExtensionMap));
Mathias Agopian518ec112011-05-13 16:21:08 -0700816 if (addr) return addr;
817
Jesse Hallc07b5202013-07-04 12:08:16 -0700818 addr = findBuiltinGLWrapper(procname);
819 if (addr) return addr;
Jamie Gennisaca51c02011-11-03 17:42:43 -0700820
Mathias Agopian518ec112011-05-13 16:21:08 -0700821 // this protects accesses to sGLExtentionMap and sGLExtentionSlot
822 pthread_mutex_lock(&sExtensionMapMutex);
823
824 /*
825 * Since eglGetProcAddress() is not associated to anything, it needs
826 * to return a function pointer that "works" regardless of what
827 * the current context is.
828 *
829 * For this reason, we return a "forwarder", a small stub that takes
830 * care of calling the function associated with the context
831 * currently bound.
832 *
833 * We first look for extensions we've already resolved, if we're seeing
834 * this extension for the first time, we go through all our
835 * implementations and call eglGetProcAddress() and record the
836 * result in the appropriate implementation hooks and return the
837 * address of the forwarder corresponding to that hook set.
838 *
839 */
840
841 const String8 name(procname);
842 addr = sGLExtentionMap.valueFor(name);
843 const int slot = sGLExtentionSlot;
844
Steve Blocke6f43dd2012-01-06 19:20:56 +0000845 ALOGE_IF(slot >= MAX_NUMBER_OF_GL_EXTENSIONS,
Mathias Agopian518ec112011-05-13 16:21:08 -0700846 "no more slots for eglGetProcAddress(\"%s\")",
847 procname);
848
Siva Velusamy0469dd62011-11-30 15:05:37 -0800849#if EGL_TRACE
850 gl_hooks_t *debugHooks = GLTrace_getGLHooks();
851#endif
852
Mathias Agopian518ec112011-05-13 16:21:08 -0700853 if (!addr && (slot < MAX_NUMBER_OF_GL_EXTENSIONS)) {
854 bool found = false;
Mathias Agopianada798b2012-02-13 17:09:30 -0800855
856 egl_connection_t* const cnx = &gEGLImpl;
857 if (cnx->dso && cnx->egl.eglGetProcAddress) {
Mathias Agopianada798b2012-02-13 17:09:30 -0800858 // Extensions are independent of the bound context
luliuhui69d10072012-08-30 11:15:36 +0800859 addr =
Mathias Agopian7773c432012-02-13 20:06:08 -0800860 cnx->hooks[egl_connection_t::GLESv1_INDEX]->ext.extensions[slot] =
861 cnx->hooks[egl_connection_t::GLESv2_INDEX]->ext.extensions[slot] =
Mathias Agopian518ec112011-05-13 16:21:08 -0700862#if EGL_TRACE
Mathias Agopianada798b2012-02-13 17:09:30 -0800863 debugHooks->ext.extensions[slot] =
864 gHooksTrace.ext.extensions[slot] =
Mathias Agopian518ec112011-05-13 16:21:08 -0700865#endif
Mathias Agopianada798b2012-02-13 17:09:30 -0800866 cnx->egl.eglGetProcAddress(procname);
luliuhui69d10072012-08-30 11:15:36 +0800867 if (addr) found = true;
Mathias Agopian518ec112011-05-13 16:21:08 -0700868 }
Mathias Agopianada798b2012-02-13 17:09:30 -0800869
Mathias Agopian518ec112011-05-13 16:21:08 -0700870 if (found) {
871 addr = gExtensionForwarders[slot];
Mathias Agopian518ec112011-05-13 16:21:08 -0700872 sGLExtentionMap.add(name, addr);
873 sGLExtentionSlot++;
874 }
875 }
876
877 pthread_mutex_unlock(&sExtensionMapMutex);
878 return addr;
879}
880
Jamie Gennis28ef8d72012-04-05 20:34:54 -0700881class FrameCompletionThread : public Thread {
882public:
883
884 static void queueSync(EGLSyncKHR sync) {
885 static sp<FrameCompletionThread> thread(new FrameCompletionThread);
886 static bool running = false;
887 if (!running) {
888 thread->run("GPUFrameCompletion");
889 running = true;
890 }
891 {
892 Mutex::Autolock lock(thread->mMutex);
893 ScopedTrace st(ATRACE_TAG, String8::format("kicked off frame %d",
894 thread->mFramesQueued).string());
895 thread->mQueue.push_back(sync);
896 thread->mCondition.signal();
897 thread->mFramesQueued++;
898 ATRACE_INT("GPU Frames Outstanding", thread->mQueue.size());
899 }
900 }
901
902private:
903 FrameCompletionThread() : mFramesQueued(0), mFramesCompleted(0) {}
904
905 virtual bool threadLoop() {
906 EGLSyncKHR sync;
907 uint32_t frameNum;
908 {
909 Mutex::Autolock lock(mMutex);
910 while (mQueue.isEmpty()) {
911 mCondition.wait(mMutex);
912 }
913 sync = mQueue[0];
914 frameNum = mFramesCompleted;
915 }
916 EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
917 {
918 ScopedTrace st(ATRACE_TAG, String8::format("waiting for frame %d",
919 frameNum).string());
920 EGLint result = eglClientWaitSyncKHR(dpy, sync, 0, EGL_FOREVER_KHR);
921 if (result == EGL_FALSE) {
922 ALOGE("FrameCompletion: error waiting for fence: %#x", eglGetError());
923 } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
924 ALOGE("FrameCompletion: timeout waiting for fence");
925 }
926 eglDestroySyncKHR(dpy, sync);
927 }
928 {
929 Mutex::Autolock lock(mMutex);
930 mQueue.removeAt(0);
931 mFramesCompleted++;
932 ATRACE_INT("GPU Frames Outstanding", mQueue.size());
933 }
934 return true;
935 }
936
937 uint32_t mFramesQueued;
938 uint32_t mFramesCompleted;
939 Vector<EGLSyncKHR> mQueue;
940 Condition mCondition;
941 Mutex mMutex;
942};
943
Mathias Agopian518ec112011-05-13 16:21:08 -0700944EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw)
945{
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800946 ATRACE_CALL();
Mathias Agopian518ec112011-05-13 16:21:08 -0700947 clearError();
948
Jesse Hallb29e5e82012-04-04 16:53:42 -0700949 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700950 if (!dp) return EGL_FALSE;
951
Jesse Hallb29e5e82012-04-04 16:53:42 -0700952 SurfaceRef _s(dp.get(), draw);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700953 if (!_s.get())
954 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700955
Siva Velusamy0469dd62011-11-30 15:05:37 -0800956#if EGL_TRACE
Siva Velusamya73a9772012-12-18 14:56:55 -0800957 gl_hooks_t const *trace_hooks = getGLTraceThreadSpecific();
958 if (getEGLDebugLevel() > 0) {
959 if (trace_hooks == NULL) {
960 if (GLTrace_start() < 0) {
961 ALOGE("Disabling Tracer for OpenGL ES");
962 setEGLDebugLevel(0);
963 } else {
964 // switch over to the trace version of hooks
965 EGLContext ctx = egl_tls_t::getContext();
966 egl_context_t * const c = get_context(ctx);
967 if (c) {
968 setGLHooksThreadSpecific(c->cnx->hooks[c->version]);
969 GLTrace_eglMakeCurrent(c->version, c->cnx->hooks[c->version], ctx);
970 }
971 }
972 }
973
Siva Velusamy0469dd62011-11-30 15:05:37 -0800974 GLTrace_eglSwapBuffers(dpy, draw);
Siva Velusamya73a9772012-12-18 14:56:55 -0800975 } else if (trace_hooks != NULL) {
976 // tracing is now disabled, so switch back to the non trace version
977 EGLContext ctx = egl_tls_t::getContext();
978 egl_context_t * const c = get_context(ctx);
979 if (c) setGLHooksThreadSpecific(c->cnx->hooks[c->version]);
980 GLTrace_stop();
981 }
Siva Velusamy0469dd62011-11-30 15:05:37 -0800982#endif
983
Mathias Agopian518ec112011-05-13 16:21:08 -0700984 egl_surface_t const * const s = get_surface(draw);
Mathias Agopian7db993a2012-03-25 00:49:46 -0700985
Mathias Agopianed6d08b2013-04-16 16:39:46 -0700986 if (CC_UNLIKELY(dp->traceGpuCompletion)) {
987 EGLSyncKHR sync = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, NULL);
988 if (sync != EGL_NO_SYNC_KHR) {
989 FrameCompletionThread::queueSync(sync);
990 }
991 }
992
Mathias Agopian7db993a2012-03-25 00:49:46 -0700993 if (CC_UNLIKELY(dp->finishOnSwap)) {
994 uint32_t pixel;
995 egl_context_t * const c = get_context( egl_tls_t::getContext() );
996 if (c) {
997 // glReadPixels() ensures that the frame is complete
998 s->cnx->hooks[c->version]->gl.glReadPixels(0,0,1,1,
999 GL_RGBA,GL_UNSIGNED_BYTE,&pixel);
1000 }
1001 }
1002
Mathias Agopianed6d08b2013-04-16 16:39:46 -07001003 return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface);
Mathias Agopian518ec112011-05-13 16:21:08 -07001004}
1005
1006EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface,
1007 NativePixmapType target)
1008{
1009 clearError();
1010
Jesse Hallb29e5e82012-04-04 16:53:42 -07001011 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001012 if (!dp) return EGL_FALSE;
1013
Jesse Hallb29e5e82012-04-04 16:53:42 -07001014 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001015 if (!_s.get())
1016 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001017
Mathias Agopian518ec112011-05-13 16:21:08 -07001018 egl_surface_t const * const s = get_surface(surface);
Mathias Agopianada798b2012-02-13 17:09:30 -08001019 return s->cnx->egl.eglCopyBuffers(dp->disp.dpy, s->surface, target);
Mathias Agopian518ec112011-05-13 16:21:08 -07001020}
1021
1022const char* eglQueryString(EGLDisplay dpy, EGLint name)
1023{
1024 clearError();
1025
Jesse Hallb29e5e82012-04-04 16:53:42 -07001026 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001027 if (!dp) return (const char *) NULL;
1028
1029 switch (name) {
1030 case EGL_VENDOR:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001031 return dp->getVendorString();
Mathias Agopian518ec112011-05-13 16:21:08 -07001032 case EGL_VERSION:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001033 return dp->getVersionString();
Mathias Agopian518ec112011-05-13 16:21:08 -07001034 case EGL_EXTENSIONS:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001035 return dp->getExtensionString();
Mathias Agopian518ec112011-05-13 16:21:08 -07001036 case EGL_CLIENT_APIS:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001037 return dp->getClientApiString();
Mathias Agopian518ec112011-05-13 16:21:08 -07001038 }
1039 return setError(EGL_BAD_PARAMETER, (const char *)0);
1040}
1041
Mathias Agopianca088332013-03-28 17:44:13 -07001042EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name)
1043{
1044 clearError();
1045
1046 const egl_display_ptr dp = validate_display(dpy);
1047 if (!dp) return (const char *) NULL;
1048
1049 switch (name) {
1050 case EGL_VENDOR:
1051 return dp->disp.queryString.vendor;
1052 case EGL_VERSION:
1053 return dp->disp.queryString.version;
1054 case EGL_EXTENSIONS:
1055 return dp->disp.queryString.extensions;
1056 case EGL_CLIENT_APIS:
1057 return dp->disp.queryString.clientApi;
1058 }
1059 return setError(EGL_BAD_PARAMETER, (const char *)0);
1060}
Mathias Agopian518ec112011-05-13 16:21:08 -07001061
1062// ----------------------------------------------------------------------------
1063// EGL 1.1
1064// ----------------------------------------------------------------------------
1065
1066EGLBoolean eglSurfaceAttrib(
1067 EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
1068{
1069 clearError();
1070
Jesse Hallb29e5e82012-04-04 16:53:42 -07001071 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001072 if (!dp) return EGL_FALSE;
1073
Jesse Hallb29e5e82012-04-04 16:53:42 -07001074 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001075 if (!_s.get())
1076 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001077
Mathias Agopian518ec112011-05-13 16:21:08 -07001078 egl_surface_t const * const s = get_surface(surface);
1079 if (s->cnx->egl.eglSurfaceAttrib) {
1080 return s->cnx->egl.eglSurfaceAttrib(
Mathias Agopianada798b2012-02-13 17:09:30 -08001081 dp->disp.dpy, s->surface, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -07001082 }
1083 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1084}
1085
1086EGLBoolean eglBindTexImage(
1087 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1088{
1089 clearError();
1090
Jesse Hallb29e5e82012-04-04 16:53:42 -07001091 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001092 if (!dp) return EGL_FALSE;
1093
Jesse Hallb29e5e82012-04-04 16:53:42 -07001094 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001095 if (!_s.get())
1096 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001097
Mathias Agopian518ec112011-05-13 16:21:08 -07001098 egl_surface_t const * const s = get_surface(surface);
1099 if (s->cnx->egl.eglBindTexImage) {
1100 return s->cnx->egl.eglBindTexImage(
Mathias Agopianada798b2012-02-13 17:09:30 -08001101 dp->disp.dpy, s->surface, buffer);
Mathias Agopian518ec112011-05-13 16:21:08 -07001102 }
1103 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1104}
1105
1106EGLBoolean eglReleaseTexImage(
1107 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1108{
1109 clearError();
1110
Jesse Hallb29e5e82012-04-04 16:53:42 -07001111 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001112 if (!dp) return EGL_FALSE;
1113
Jesse Hallb29e5e82012-04-04 16:53:42 -07001114 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001115 if (!_s.get())
1116 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001117
Mathias Agopian518ec112011-05-13 16:21:08 -07001118 egl_surface_t const * const s = get_surface(surface);
1119 if (s->cnx->egl.eglReleaseTexImage) {
1120 return s->cnx->egl.eglReleaseTexImage(
Mathias Agopianada798b2012-02-13 17:09:30 -08001121 dp->disp.dpy, s->surface, buffer);
Mathias Agopian518ec112011-05-13 16:21:08 -07001122 }
1123 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1124}
1125
1126EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
1127{
1128 clearError();
1129
Jesse Hallb29e5e82012-04-04 16:53:42 -07001130 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001131 if (!dp) return EGL_FALSE;
1132
1133 EGLBoolean res = EGL_TRUE;
Mathias Agopianada798b2012-02-13 17:09:30 -08001134 egl_connection_t* const cnx = &gEGLImpl;
1135 if (cnx->dso && cnx->egl.eglSwapInterval) {
1136 res = cnx->egl.eglSwapInterval(dp->disp.dpy, interval);
Mathias Agopian518ec112011-05-13 16:21:08 -07001137 }
Mathias Agopianada798b2012-02-13 17:09:30 -08001138
Mathias Agopian518ec112011-05-13 16:21:08 -07001139 return res;
1140}
1141
1142
1143// ----------------------------------------------------------------------------
1144// EGL 1.2
1145// ----------------------------------------------------------------------------
1146
1147EGLBoolean eglWaitClient(void)
1148{
1149 clearError();
1150
Mathias Agopianada798b2012-02-13 17:09:30 -08001151 egl_connection_t* const cnx = &gEGLImpl;
1152 if (!cnx->dso)
1153 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1154
1155 EGLBoolean res;
1156 if (cnx->egl.eglWaitClient) {
1157 res = cnx->egl.eglWaitClient();
1158 } else {
1159 res = cnx->egl.eglWaitGL();
Mathias Agopian518ec112011-05-13 16:21:08 -07001160 }
1161 return res;
1162}
1163
1164EGLBoolean eglBindAPI(EGLenum api)
1165{
1166 clearError();
1167
1168 if (egl_init_drivers() == EGL_FALSE) {
1169 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1170 }
1171
1172 // bind this API on all EGLs
1173 EGLBoolean res = EGL_TRUE;
Mathias Agopianada798b2012-02-13 17:09:30 -08001174 egl_connection_t* const cnx = &gEGLImpl;
1175 if (cnx->dso && cnx->egl.eglBindAPI) {
1176 res = cnx->egl.eglBindAPI(api);
Mathias Agopian518ec112011-05-13 16:21:08 -07001177 }
1178 return res;
1179}
1180
1181EGLenum eglQueryAPI(void)
1182{
1183 clearError();
1184
1185 if (egl_init_drivers() == EGL_FALSE) {
1186 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1187 }
1188
Mathias Agopianada798b2012-02-13 17:09:30 -08001189 egl_connection_t* const cnx = &gEGLImpl;
1190 if (cnx->dso && cnx->egl.eglQueryAPI) {
1191 return cnx->egl.eglQueryAPI();
Mathias Agopian518ec112011-05-13 16:21:08 -07001192 }
Mathias Agopianada798b2012-02-13 17:09:30 -08001193
Mathias Agopian518ec112011-05-13 16:21:08 -07001194 // or, it can only be OpenGL ES
1195 return EGL_OPENGL_ES_API;
1196}
1197
1198EGLBoolean eglReleaseThread(void)
1199{
1200 clearError();
1201
Mathias Agopian4e620dd2013-05-30 16:07:36 -07001202#if EGL_TRACE
1203 if (getEGLDebugLevel() > 0)
1204 GLTrace_eglReleaseThread();
1205#endif
1206
Mathias Agopian518ec112011-05-13 16:21:08 -07001207 // If there is context bound to the thread, release it
Mathias Agopianfb87e542012-01-30 18:20:52 -08001208 egl_display_t::loseCurrent(get_context(getContext()));
Mathias Agopian518ec112011-05-13 16:21:08 -07001209
Mathias Agopianada798b2012-02-13 17:09:30 -08001210 egl_connection_t* const cnx = &gEGLImpl;
1211 if (cnx->dso && cnx->egl.eglReleaseThread) {
1212 cnx->egl.eglReleaseThread();
Mathias Agopian518ec112011-05-13 16:21:08 -07001213 }
1214 egl_tls_t::clearTLS();
Mathias Agopian518ec112011-05-13 16:21:08 -07001215 return EGL_TRUE;
1216}
1217
1218EGLSurface eglCreatePbufferFromClientBuffer(
1219 EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer,
1220 EGLConfig config, const EGLint *attrib_list)
1221{
1222 clearError();
1223
Jesse Hallb29e5e82012-04-04 16:53:42 -07001224 egl_connection_t* cnx = NULL;
1225 const egl_display_ptr dp = validate_display_connection(dpy, cnx);
1226 if (!dp) return EGL_FALSE;
Mathias Agopian518ec112011-05-13 16:21:08 -07001227 if (cnx->egl.eglCreatePbufferFromClientBuffer) {
1228 return cnx->egl.eglCreatePbufferFromClientBuffer(
Mathias Agopian7773c432012-02-13 20:06:08 -08001229 dp->disp.dpy, buftype, buffer, config, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001230 }
1231 return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE);
1232}
1233
1234// ----------------------------------------------------------------------------
1235// EGL_EGLEXT_VERSION 3
1236// ----------------------------------------------------------------------------
1237
1238EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface,
1239 const EGLint *attrib_list)
1240{
1241 clearError();
1242
Jesse Hallb29e5e82012-04-04 16:53:42 -07001243 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001244 if (!dp) return EGL_FALSE;
1245
Jesse Hallb29e5e82012-04-04 16:53:42 -07001246 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001247 if (!_s.get())
1248 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001249
1250 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian518ec112011-05-13 16:21:08 -07001251 if (s->cnx->egl.eglLockSurfaceKHR) {
1252 return s->cnx->egl.eglLockSurfaceKHR(
Mathias Agopianada798b2012-02-13 17:09:30 -08001253 dp->disp.dpy, s->surface, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001254 }
1255 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1256}
1257
1258EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface)
1259{
1260 clearError();
1261
Jesse Hallb29e5e82012-04-04 16:53:42 -07001262 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001263 if (!dp) return EGL_FALSE;
1264
Jesse Hallb29e5e82012-04-04 16:53:42 -07001265 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001266 if (!_s.get())
1267 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001268
1269 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian518ec112011-05-13 16:21:08 -07001270 if (s->cnx->egl.eglUnlockSurfaceKHR) {
Mathias Agopianada798b2012-02-13 17:09:30 -08001271 return s->cnx->egl.eglUnlockSurfaceKHR(dp->disp.dpy, s->surface);
Mathias Agopian518ec112011-05-13 16:21:08 -07001272 }
1273 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1274}
1275
1276EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
1277 EGLClientBuffer buffer, const EGLint *attrib_list)
1278{
1279 clearError();
1280
Jesse Hallb29e5e82012-04-04 16:53:42 -07001281 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001282 if (!dp) return EGL_NO_IMAGE_KHR;
1283
Jesse Hallb29e5e82012-04-04 16:53:42 -07001284 ContextRef _c(dp.get(), ctx);
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001285 egl_context_t * const c = _c.get();
Mathias Agopian518ec112011-05-13 16:21:08 -07001286
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001287 EGLImageKHR result = EGL_NO_IMAGE_KHR;
1288 egl_connection_t* const cnx = &gEGLImpl;
1289 if (cnx->dso && cnx->egl.eglCreateImageKHR) {
1290 result = cnx->egl.eglCreateImageKHR(
1291 dp->disp.dpy,
1292 c ? c->context : EGL_NO_CONTEXT,
1293 target, buffer, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001294 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001295 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001296}
1297
1298EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
1299{
1300 clearError();
1301
Jesse Hallb29e5e82012-04-04 16:53:42 -07001302 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001303 if (!dp) return EGL_FALSE;
1304
Steven Holte646a5c52012-06-04 20:02:11 -07001305 EGLBoolean result = EGL_FALSE;
Mathias Agopianada798b2012-02-13 17:09:30 -08001306 egl_connection_t* const cnx = &gEGLImpl;
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001307 if (cnx->dso && cnx->egl.eglDestroyImageKHR) {
Steven Holte646a5c52012-06-04 20:02:11 -07001308 result = cnx->egl.eglDestroyImageKHR(dp->disp.dpy, img);
Mathias Agopian518ec112011-05-13 16:21:08 -07001309 }
Steven Holte646a5c52012-06-04 20:02:11 -07001310 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001311}
1312
1313// ----------------------------------------------------------------------------
1314// EGL_EGLEXT_VERSION 5
1315// ----------------------------------------------------------------------------
1316
1317
1318EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
1319{
1320 clearError();
1321
Jesse Hallb29e5e82012-04-04 16:53:42 -07001322 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001323 if (!dp) return EGL_NO_SYNC_KHR;
1324
Mathias Agopian518ec112011-05-13 16:21:08 -07001325 EGLSyncKHR result = EGL_NO_SYNC_KHR;
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001326 egl_connection_t* const cnx = &gEGLImpl;
1327 if (cnx->dso && cnx->egl.eglCreateSyncKHR) {
1328 result = cnx->egl.eglCreateSyncKHR(dp->disp.dpy, type, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001329 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001330 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001331}
1332
1333EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
1334{
1335 clearError();
1336
Jesse Hallb29e5e82012-04-04 16:53:42 -07001337 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001338 if (!dp) return EGL_FALSE;
1339
Mathias Agopian518ec112011-05-13 16:21:08 -07001340 EGLBoolean result = EGL_FALSE;
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001341 egl_connection_t* const cnx = &gEGLImpl;
1342 if (cnx->dso && cnx->egl.eglDestroySyncKHR) {
1343 result = cnx->egl.eglDestroySyncKHR(dp->disp.dpy, sync);
Mathias Agopian518ec112011-05-13 16:21:08 -07001344 }
1345 return result;
1346}
1347
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -07001348EGLBoolean eglSignalSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode) {
1349 clearError();
1350
1351 const egl_display_ptr dp = validate_display(dpy);
1352 if (!dp) return EGL_FALSE;
1353
1354 EGLBoolean result = EGL_FALSE;
1355 egl_connection_t* const cnx = &gEGLImpl;
1356 if (cnx->dso && cnx->egl.eglSignalSyncKHR) {
1357 result = cnx->egl.eglSignalSyncKHR(
1358 dp->disp.dpy, sync, mode);
1359 }
1360 return result;
1361}
1362
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001363EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync,
1364 EGLint flags, EGLTimeKHR timeout)
Mathias Agopian518ec112011-05-13 16:21:08 -07001365{
1366 clearError();
1367
Jesse Hallb29e5e82012-04-04 16:53:42 -07001368 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001369 if (!dp) return EGL_FALSE;
1370
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001371 EGLBoolean result = EGL_FALSE;
1372 egl_connection_t* const cnx = &gEGLImpl;
1373 if (cnx->dso && cnx->egl.eglClientWaitSyncKHR) {
1374 result = cnx->egl.eglClientWaitSyncKHR(
1375 dp->disp.dpy, sync, flags, timeout);
Mathias Agopian518ec112011-05-13 16:21:08 -07001376 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001377 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001378}
1379
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001380EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync,
1381 EGLint attribute, EGLint *value)
Mathias Agopian518ec112011-05-13 16:21:08 -07001382{
1383 clearError();
1384
Jesse Hallb29e5e82012-04-04 16:53:42 -07001385 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001386 if (!dp) return EGL_FALSE;
1387
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001388 EGLBoolean result = EGL_FALSE;
1389 egl_connection_t* const cnx = &gEGLImpl;
1390 if (cnx->dso && cnx->egl.eglGetSyncAttribKHR) {
1391 result = cnx->egl.eglGetSyncAttribKHR(
1392 dp->disp.dpy, sync, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -07001393 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001394 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001395}
1396
1397// ----------------------------------------------------------------------------
Mathias Agopian2bb71682013-03-27 17:32:41 -07001398// EGL_EGLEXT_VERSION 15
1399// ----------------------------------------------------------------------------
1400
1401EGLint eglWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags) {
1402 clearError();
1403 const egl_display_ptr dp = validate_display(dpy);
1404 if (!dp) return EGL_FALSE;
1405 EGLint result = EGL_FALSE;
1406 egl_connection_t* const cnx = &gEGLImpl;
1407 if (cnx->dso && cnx->egl.eglWaitSyncKHR) {
1408 result = cnx->egl.eglWaitSyncKHR(dp->disp.dpy, sync, flags);
1409 }
1410 return result;
1411}
1412
1413// ----------------------------------------------------------------------------
Mathias Agopian518ec112011-05-13 16:21:08 -07001414// ANDROID extensions
1415// ----------------------------------------------------------------------------
1416
Jamie Gennis331841b2012-09-06 14:52:00 -07001417EGLint eglDupNativeFenceFDANDROID(EGLDisplay dpy, EGLSyncKHR sync)
1418{
1419 clearError();
1420
1421 const egl_display_ptr dp = validate_display(dpy);
1422 if (!dp) return EGL_NO_NATIVE_FENCE_FD_ANDROID;
1423
1424 EGLint result = EGL_NO_NATIVE_FENCE_FD_ANDROID;
1425 egl_connection_t* const cnx = &gEGLImpl;
1426 if (cnx->dso && cnx->egl.eglDupNativeFenceFDANDROID) {
1427 result = cnx->egl.eglDupNativeFenceFDANDROID(dp->disp.dpy, sync);
1428 }
1429 return result;
1430}
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001431
Andy McFadden72841452013-03-01 16:25:32 -08001432EGLBoolean eglPresentationTimeANDROID(EGLDisplay dpy, EGLSurface surface,
1433 EGLnsecsANDROID time)
1434{
1435 clearError();
1436
1437 const egl_display_ptr dp = validate_display(dpy);
1438 if (!dp) {
1439 return EGL_FALSE;
1440 }
1441
1442 SurfaceRef _s(dp.get(), surface);
1443 if (!_s.get()) {
1444 setError(EGL_BAD_SURFACE, EGL_FALSE);
1445 return EGL_FALSE;
1446 }
1447
1448 egl_surface_t const * const s = get_surface(surface);
1449 native_window_set_buffers_timestamp(s->win.get(), time);
1450
1451 return EGL_TRUE;
1452}
1453
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001454// ----------------------------------------------------------------------------
1455// NVIDIA extensions
1456// ----------------------------------------------------------------------------
1457EGLuint64NV eglGetSystemTimeFrequencyNV()
1458{
1459 clearError();
1460
1461 if (egl_init_drivers() == EGL_FALSE) {
1462 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1463 }
1464
1465 EGLuint64NV ret = 0;
Mathias Agopianada798b2012-02-13 17:09:30 -08001466 egl_connection_t* const cnx = &gEGLImpl;
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001467
Mathias Agopianada798b2012-02-13 17:09:30 -08001468 if (cnx->dso && cnx->egl.eglGetSystemTimeFrequencyNV) {
1469 return cnx->egl.eglGetSystemTimeFrequencyNV();
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001470 }
1471
Mathias Agopian0e8bbee2011-10-05 19:15:05 -07001472 return setErrorQuiet(EGL_BAD_DISPLAY, 0);
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001473}
1474
1475EGLuint64NV eglGetSystemTimeNV()
1476{
1477 clearError();
1478
1479 if (egl_init_drivers() == EGL_FALSE) {
1480 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1481 }
1482
1483 EGLuint64NV ret = 0;
Mathias Agopianada798b2012-02-13 17:09:30 -08001484 egl_connection_t* const cnx = &gEGLImpl;
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001485
Mathias Agopianada798b2012-02-13 17:09:30 -08001486 if (cnx->dso && cnx->egl.eglGetSystemTimeNV) {
1487 return cnx->egl.eglGetSystemTimeNV();
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001488 }
1489
Mathias Agopian0e8bbee2011-10-05 19:15:05 -07001490 return setErrorQuiet(EGL_BAD_DISPLAY, 0);
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001491}