blob: 9a214c2677b0627e46daa92bf348d166b6a3effb [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
Mathias Agopian518ec112011-05-13 16:21:08 -070019#include <ctype.h>
20#include <stdlib.h>
21#include <string.h>
22
23#include <hardware/gralloc.h>
24#include <system/window.h>
25
26#include <EGL/egl.h>
27#include <EGL/eglext.h>
Mathias Agopian518ec112011-05-13 16:21:08 -070028
29#include <cutils/log.h>
30#include <cutils/atomic.h>
Mathias Agopian7db993a2012-03-25 00:49:46 -070031#include <cutils/compiler.h>
Mathias Agopian518ec112011-05-13 16:21:08 -070032#include <cutils/properties.h>
33#include <cutils/memory.h>
34
35#include <utils/KeyedVector.h>
36#include <utils/SortedVector.h>
37#include <utils/String8.h>
Jamie Gennis1c8e95c2012-02-23 19:27:23 -080038#include <utils/Trace.h>
Mathias Agopian518ec112011-05-13 16:21:08 -070039
Mathias Agopian39c24a22013-04-04 23:17:56 -070040#include "../egl_impl.h"
41#include "../glestrace.h"
42#include "../hooks.h"
Mathias Agopian518ec112011-05-13 16:21:08 -070043
44#include "egl_display.h"
Mathias Agopian518ec112011-05-13 16:21:08 -070045#include "egl_object.h"
46#include "egl_tls.h"
Mathias Agopianada798b2012-02-13 17:09:30 -080047#include "egldefs.h"
Mathias Agopian518ec112011-05-13 16:21:08 -070048
49using namespace android;
50
51// ----------------------------------------------------------------------------
52
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070053namespace android {
54
Mathias Agopian518ec112011-05-13 16:21:08 -070055struct extention_map_t {
56 const char* name;
57 __eglMustCastToProperFunctionPointerType address;
58};
59
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070060/*
61 * This is the list of EGL extensions exposed to applications,
62 * some of them are mandatory because used by the ANDROID system.
63 *
64 * Mandatory extensions are required per the CDD and not explicitly
65 * checked during EGL initialization. the system *assumes* these extensions
66 * are present. the system may not function properly if some mandatory
67 * extensions are missing.
68 *
69 * NOTE: gExtensionString MUST have a single space as the last character.
70 */
71extern char const * const gExtensionString =
72 "EGL_KHR_image " // mandatory
73 "EGL_KHR_image_base " // mandatory
74 "EGL_KHR_image_pixmap "
75 "EGL_KHR_lock_surface "
76 "EGL_KHR_gl_texture_2D_image "
77 "EGL_KHR_gl_texture_cubemap_image "
78 "EGL_KHR_gl_renderbuffer_image "
79 "EGL_KHR_reusable_sync "
80 "EGL_KHR_fence_sync "
81 "EGL_EXT_create_context_robustness "
82 "EGL_NV_system_time "
83 "EGL_ANDROID_image_native_buffer " // mandatory
Mathias Agopian2bb71682013-03-27 17:32:41 -070084 "EGL_KHR_wait_sync " // strongly recommended
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070085 "EGL_ANDROID_presentation_time "
86 ;
87
88// extensions not exposed to applications but used by the ANDROID system
89// "EGL_ANDROID_blob_cache " // strongly recommended
90// "EGL_IMG_hibernate_process " // optional
91// "EGL_ANDROID_native_fence_sync " // strongly recommended
92// "EGL_ANDROID_framebuffer_target " // mandatory for HWC 1.1
93// "EGL_ANDROID_recordable " // mandatory
94
95
96/*
97 * EGL Extensions entry-points exposed to 3rd party applications
98 * (keep in sync with gExtensionString above)
99 *
100 */
101static const extention_map_t sExtensionMap[] = {
102 // EGL_KHR_lock_surface
Mathias Agopian518ec112011-05-13 16:21:08 -0700103 { "eglLockSurfaceKHR",
104 (__eglMustCastToProperFunctionPointerType)&eglLockSurfaceKHR },
105 { "eglUnlockSurfaceKHR",
106 (__eglMustCastToProperFunctionPointerType)&eglUnlockSurfaceKHR },
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700107
108 // EGL_KHR_image, EGL_KHR_image_base
Mathias Agopian518ec112011-05-13 16:21:08 -0700109 { "eglCreateImageKHR",
110 (__eglMustCastToProperFunctionPointerType)&eglCreateImageKHR },
111 { "eglDestroyImageKHR",
112 (__eglMustCastToProperFunctionPointerType)&eglDestroyImageKHR },
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700113
114 // EGL_KHR_reusable_sync, EGL_KHR_fence_sync
115 { "eglCreateSyncKHR",
116 (__eglMustCastToProperFunctionPointerType)&eglCreateSyncKHR },
117 { "eglDestroySyncKHR",
118 (__eglMustCastToProperFunctionPointerType)&eglDestroySyncKHR },
119 { "eglClientWaitSyncKHR",
120 (__eglMustCastToProperFunctionPointerType)&eglClientWaitSyncKHR },
121 { "eglSignalSyncKHR",
122 (__eglMustCastToProperFunctionPointerType)&eglSignalSyncKHR },
123 { "eglGetSyncAttribKHR",
124 (__eglMustCastToProperFunctionPointerType)&eglGetSyncAttribKHR },
125
126 // EGL_NV_system_time
Jonas Yang1c3d72a2011-08-26 20:04:39 +0800127 { "eglGetSystemTimeFrequencyNV",
128 (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeFrequencyNV },
129 { "eglGetSystemTimeNV",
130 (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeNV },
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700131
Mathias Agopian2bb71682013-03-27 17:32:41 -0700132 // EGL_KHR_wait_sync
133 { "eglWaitSyncKHR",
134 (__eglMustCastToProperFunctionPointerType)&eglWaitSyncKHR },
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700135
136 // EGL_ANDROID_presentation_time
137 { "eglPresentationTimeANDROID",
138 (__eglMustCastToProperFunctionPointerType)&eglPresentationTimeANDROID },
Mathias Agopian518ec112011-05-13 16:21:08 -0700139};
140
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700141/*
142 * These extensions entry-points should not be exposed to applications.
143 * They're used internally by the Android EGL layer.
144 */
145#define FILTER_EXTENSIONS(procname) \
146 (!strcmp((procname), "eglSetBlobCacheFuncsANDROID") || \
147 !strcmp((procname), "eglHibernateProcessIMG") || \
148 !strcmp((procname), "eglAwakenProcessIMG") || \
149 !strcmp((procname), "eglDupNativeFenceFDANDROID"))
150
151
152
Mathias Agopian518ec112011-05-13 16:21:08 -0700153// accesses protected by sExtensionMapMutex
154static DefaultKeyedVector<String8, __eglMustCastToProperFunctionPointerType> sGLExtentionMap;
155static int sGLExtentionSlot = 0;
156static pthread_mutex_t sExtensionMapMutex = PTHREAD_MUTEX_INITIALIZER;
157
158static void(*findProcAddress(const char* name,
159 const extention_map_t* map, size_t n))() {
160 for (uint32_t i=0 ; i<n ; i++) {
161 if (!strcmp(name, map[i].name)) {
162 return map[i].address;
163 }
164 }
165 return NULL;
166}
167
168// ----------------------------------------------------------------------------
169
Mathias Agopian518ec112011-05-13 16:21:08 -0700170extern void setGLHooksThreadSpecific(gl_hooks_t const *value);
171extern EGLBoolean egl_init_drivers();
172extern const __eglMustCastToProperFunctionPointerType gExtensionForwarders[MAX_NUMBER_OF_GL_EXTENSIONS];
Siva Velusamya73a9772012-12-18 14:56:55 -0800173extern int getEGLDebugLevel();
174extern void setEGLDebugLevel(int level);
Mathias Agopian518ec112011-05-13 16:21:08 -0700175extern gl_hooks_t gHooksTrace;
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700176
Mathias Agopian518ec112011-05-13 16:21:08 -0700177} // namespace android;
178
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700179
Mathias Agopian518ec112011-05-13 16:21:08 -0700180// ----------------------------------------------------------------------------
181
182static inline void clearError() { egl_tls_t::clearError(); }
183static inline EGLContext getContext() { return egl_tls_t::getContext(); }
184
185// ----------------------------------------------------------------------------
186
187EGLDisplay eglGetDisplay(EGLNativeDisplayType display)
188{
189 clearError();
190
191 uint32_t index = uint32_t(display);
192 if (index >= NUM_DISPLAYS) {
193 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
194 }
195
196 if (egl_init_drivers() == EGL_FALSE) {
197 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
198 }
199
200 EGLDisplay dpy = egl_display_t::getFromNativeDisplay(display);
201 return dpy;
202}
203
204// ----------------------------------------------------------------------------
205// Initialization
206// ----------------------------------------------------------------------------
207
208EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
209{
210 clearError();
211
Jesse Hallb29e5e82012-04-04 16:53:42 -0700212 egl_display_ptr dp = get_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700213 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
214
215 EGLBoolean res = dp->initialize(major, minor);
216
217 return res;
218}
219
220EGLBoolean eglTerminate(EGLDisplay dpy)
221{
222 // NOTE: don't unload the drivers b/c some APIs can be called
223 // after eglTerminate() has been called. eglTerminate() only
224 // terminates an EGLDisplay, not a EGL itself.
225
226 clearError();
227
Jesse Hallb29e5e82012-04-04 16:53:42 -0700228 egl_display_ptr dp = get_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700229 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
230
231 EGLBoolean res = dp->terminate();
Jesse Hall47743382013-02-08 11:13:46 -0800232
Mathias Agopian518ec112011-05-13 16:21:08 -0700233 return res;
234}
235
236// ----------------------------------------------------------------------------
237// configuration
238// ----------------------------------------------------------------------------
239
240EGLBoolean eglGetConfigs( EGLDisplay dpy,
241 EGLConfig *configs,
242 EGLint config_size, EGLint *num_config)
243{
244 clearError();
245
Jesse Hallb29e5e82012-04-04 16:53:42 -0700246 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700247 if (!dp) return EGL_FALSE;
248
Mathias Agopian7773c432012-02-13 20:06:08 -0800249 if (num_config==0) {
250 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700251 }
252
Mathias Agopian7773c432012-02-13 20:06:08 -0800253 EGLBoolean res = EGL_FALSE;
254 *num_config = 0;
255
256 egl_connection_t* const cnx = &gEGLImpl;
257 if (cnx->dso) {
258 res = cnx->egl.eglGetConfigs(
259 dp->disp.dpy, configs, config_size, num_config);
Mathias Agopian518ec112011-05-13 16:21:08 -0700260 }
Mathias Agopian7773c432012-02-13 20:06:08 -0800261
262 return res;
Mathias Agopian518ec112011-05-13 16:21:08 -0700263}
264
265EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list,
266 EGLConfig *configs, EGLint config_size,
267 EGLint *num_config)
268{
269 clearError();
270
Jesse Hallb29e5e82012-04-04 16:53:42 -0700271 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700272 if (!dp) return EGL_FALSE;
273
274 if (num_config==0) {
275 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
276 }
277
Mathias Agopian518ec112011-05-13 16:21:08 -0700278 EGLBoolean res = EGL_FALSE;
279 *num_config = 0;
280
Mathias Agopianada798b2012-02-13 17:09:30 -0800281 egl_connection_t* const cnx = &gEGLImpl;
282 if (cnx->dso) {
Romain Guy1cffc802012-10-15 18:13:05 -0700283 if (attrib_list) {
284 char value[PROPERTY_VALUE_MAX];
285 property_get("debug.egl.force_msaa", value, "false");
286
287 if (!strcmp(value, "true")) {
288 size_t attribCount = 0;
289 EGLint attrib = attrib_list[0];
290
291 // Only enable MSAA if the context is OpenGL ES 2.0 and
Romain Guybe3c3e42012-10-15 19:25:18 -0700292 // if no caveat is requested
Romain Guy1cffc802012-10-15 18:13:05 -0700293 const EGLint *attribRendererable = NULL;
294 const EGLint *attribCaveat = NULL;
295
296 // Count the number of attributes and look for
Romain Guybe3c3e42012-10-15 19:25:18 -0700297 // EGL_RENDERABLE_TYPE and EGL_CONFIG_CAVEAT
Romain Guy1cffc802012-10-15 18:13:05 -0700298 while (attrib != EGL_NONE) {
299 attrib = attrib_list[attribCount];
300 switch (attrib) {
301 case EGL_RENDERABLE_TYPE:
302 attribRendererable = &attrib_list[attribCount];
303 break;
304 case EGL_CONFIG_CAVEAT:
305 attribCaveat = &attrib_list[attribCount];
306 break;
307 }
308 attribCount++;
309 }
310
311 if (attribRendererable && attribRendererable[1] == EGL_OPENGL_ES2_BIT &&
312 (!attribCaveat || attribCaveat[1] != EGL_NONE)) {
Jesse Hall47743382013-02-08 11:13:46 -0800313
Romain Guy1cffc802012-10-15 18:13:05 -0700314 // Insert 2 extra attributes to force-enable MSAA 4x
315 EGLint aaAttribs[attribCount + 4];
316 aaAttribs[0] = EGL_SAMPLE_BUFFERS;
317 aaAttribs[1] = 1;
318 aaAttribs[2] = EGL_SAMPLES;
319 aaAttribs[3] = 4;
320
321 memcpy(&aaAttribs[4], attrib_list, attribCount * sizeof(EGLint));
322
323 EGLint numConfigAA;
324 EGLBoolean resAA = cnx->egl.eglChooseConfig(
325 dp->disp.dpy, aaAttribs, configs, config_size, &numConfigAA);
326
327 if (resAA == EGL_TRUE && numConfigAA > 0) {
328 ALOGD("Enabling MSAA 4x");
329 *num_config = numConfigAA;
330 return resAA;
331 }
332 }
333 }
334 }
335
Mathias Agopian7773c432012-02-13 20:06:08 -0800336 res = cnx->egl.eglChooseConfig(
337 dp->disp.dpy, attrib_list, configs, config_size, num_config);
Mathias Agopian518ec112011-05-13 16:21:08 -0700338 }
339 return res;
340}
341
342EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
343 EGLint attribute, EGLint *value)
344{
345 clearError();
346
Jesse Hallb29e5e82012-04-04 16:53:42 -0700347 egl_connection_t* cnx = NULL;
348 const egl_display_ptr dp = validate_display_connection(dpy, cnx);
349 if (!dp) return EGL_FALSE;
Jesse Hall47743382013-02-08 11:13:46 -0800350
Mathias Agopian518ec112011-05-13 16:21:08 -0700351 return cnx->egl.eglGetConfigAttrib(
Mathias Agopian7773c432012-02-13 20:06:08 -0800352 dp->disp.dpy, config, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -0700353}
354
355// ----------------------------------------------------------------------------
356// surfaces
357// ----------------------------------------------------------------------------
358
359EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config,
360 NativeWindowType window,
361 const EGLint *attrib_list)
362{
363 clearError();
364
Jesse Hallb29e5e82012-04-04 16:53:42 -0700365 egl_connection_t* cnx = NULL;
366 egl_display_ptr dp = validate_display_connection(dpy, cnx);
367 if (dp) {
Mathias Agopianada798b2012-02-13 17:09:30 -0800368 EGLDisplay iDpy = dp->disp.dpy;
Mathias Agopian518ec112011-05-13 16:21:08 -0700369 EGLint format;
370
Mathias Agopian81a63352011-07-29 17:55:48 -0700371 if (native_window_api_connect(window, NATIVE_WINDOW_API_EGL) != OK) {
Steve Blocke6f43dd2012-01-06 19:20:56 +0000372 ALOGE("EGLNativeWindowType %p already connected to another API",
Mathias Agopian81a63352011-07-29 17:55:48 -0700373 window);
374 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
375 }
376
Mathias Agopian518ec112011-05-13 16:21:08 -0700377 // set the native window's buffers format to match this config
378 if (cnx->egl.eglGetConfigAttrib(iDpy,
Mathias Agopian7773c432012-02-13 20:06:08 -0800379 config, EGL_NATIVE_VISUAL_ID, &format)) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700380 if (format != 0) {
Jamie Gennisbee205f2011-07-01 13:12:07 -0700381 int err = native_window_set_buffers_format(window, format);
382 if (err != 0) {
Steve Blocke6f43dd2012-01-06 19:20:56 +0000383 ALOGE("error setting native window pixel format: %s (%d)",
Jamie Gennisbee205f2011-07-01 13:12:07 -0700384 strerror(-err), err);
Mathias Agopian81a63352011-07-29 17:55:48 -0700385 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
Jamie Gennisbee205f2011-07-01 13:12:07 -0700386 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
387 }
Mathias Agopian518ec112011-05-13 16:21:08 -0700388 }
389 }
390
Jamie Gennis59769462011-11-19 18:04:43 -0800391 // the EGL spec requires that a new EGLSurface default to swap interval
392 // 1, so explicitly set that on the window here.
393 ANativeWindow* anw = reinterpret_cast<ANativeWindow*>(window);
394 anw->setSwapInterval(anw, 1);
395
Mathias Agopian518ec112011-05-13 16:21:08 -0700396 EGLSurface surface = cnx->egl.eglCreateWindowSurface(
Mathias Agopian7773c432012-02-13 20:06:08 -0800397 iDpy, config, window, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700398 if (surface != EGL_NO_SURFACE) {
Jesse Hallb29e5e82012-04-04 16:53:42 -0700399 egl_surface_t* s = new egl_surface_t(dp.get(), config, window,
400 surface, cnx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700401 return s;
402 }
Mathias Agopian81a63352011-07-29 17:55:48 -0700403
404 // EGLSurface creation failed
405 native_window_set_buffers_format(window, 0);
406 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
Mathias Agopian518ec112011-05-13 16:21:08 -0700407 }
408 return EGL_NO_SURFACE;
409}
410
411EGLSurface eglCreatePixmapSurface( EGLDisplay dpy, EGLConfig config,
412 NativePixmapType pixmap,
413 const EGLint *attrib_list)
414{
415 clearError();
416
Jesse Hallb29e5e82012-04-04 16:53:42 -0700417 egl_connection_t* cnx = NULL;
418 egl_display_ptr dp = validate_display_connection(dpy, cnx);
419 if (dp) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700420 EGLSurface surface = cnx->egl.eglCreatePixmapSurface(
Mathias Agopian7773c432012-02-13 20:06:08 -0800421 dp->disp.dpy, config, pixmap, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700422 if (surface != EGL_NO_SURFACE) {
Jesse Hallb29e5e82012-04-04 16:53:42 -0700423 egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL,
424 surface, cnx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700425 return s;
426 }
427 }
428 return EGL_NO_SURFACE;
429}
430
431EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config,
432 const EGLint *attrib_list)
433{
434 clearError();
435
Jesse Hallb29e5e82012-04-04 16:53:42 -0700436 egl_connection_t* cnx = NULL;
437 egl_display_ptr dp = validate_display_connection(dpy, cnx);
438 if (dp) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700439 EGLSurface surface = cnx->egl.eglCreatePbufferSurface(
Mathias Agopian7773c432012-02-13 20:06:08 -0800440 dp->disp.dpy, config, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700441 if (surface != EGL_NO_SURFACE) {
Jesse Hallb29e5e82012-04-04 16:53:42 -0700442 egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL,
443 surface, cnx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700444 return s;
445 }
446 }
447 return EGL_NO_SURFACE;
448}
Jesse Hall47743382013-02-08 11:13:46 -0800449
Mathias Agopian518ec112011-05-13 16:21:08 -0700450EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
451{
452 clearError();
453
Jesse Hallb29e5e82012-04-04 16:53:42 -0700454 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700455 if (!dp) return EGL_FALSE;
456
Jesse Hallb29e5e82012-04-04 16:53:42 -0700457 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700458 if (!_s.get())
459 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700460
461 egl_surface_t * const s = get_surface(surface);
Mathias Agopianada798b2012-02-13 17:09:30 -0800462 EGLBoolean result = s->cnx->egl.eglDestroySurface(dp->disp.dpy, s->surface);
Mathias Agopian518ec112011-05-13 16:21:08 -0700463 if (result == EGL_TRUE) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700464 _s.terminate();
465 }
466 return result;
467}
468
469EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface surface,
470 EGLint attribute, EGLint *value)
471{
472 clearError();
473
Jesse Hallb29e5e82012-04-04 16:53:42 -0700474 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700475 if (!dp) return EGL_FALSE;
476
Jesse Hallb29e5e82012-04-04 16:53:42 -0700477 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700478 if (!_s.get())
479 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700480
Mathias Agopian518ec112011-05-13 16:21:08 -0700481 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian7773c432012-02-13 20:06:08 -0800482 return s->cnx->egl.eglQuerySurface(
483 dp->disp.dpy, s->surface, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -0700484}
485
Jamie Gennise8696a42012-01-15 18:54:57 -0800486void EGLAPI eglBeginFrame(EGLDisplay dpy, EGLSurface surface) {
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800487 ATRACE_CALL();
Jamie Gennise8696a42012-01-15 18:54:57 -0800488 clearError();
489
Jesse Hallb29e5e82012-04-04 16:53:42 -0700490 const egl_display_ptr dp = validate_display(dpy);
Jamie Gennise8696a42012-01-15 18:54:57 -0800491 if (!dp) {
492 return;
493 }
494
Jesse Hallb29e5e82012-04-04 16:53:42 -0700495 SurfaceRef _s(dp.get(), surface);
Jamie Gennise8696a42012-01-15 18:54:57 -0800496 if (!_s.get()) {
497 setError(EGL_BAD_SURFACE, EGL_FALSE);
498 return;
499 }
500
501 int64_t timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
502
503 egl_surface_t const * const s = get_surface(surface);
504 native_window_set_buffers_timestamp(s->win.get(), timestamp);
505}
506
Mathias Agopian518ec112011-05-13 16:21:08 -0700507// ----------------------------------------------------------------------------
508// Contexts
509// ----------------------------------------------------------------------------
510
511EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config,
512 EGLContext share_list, const EGLint *attrib_list)
513{
514 clearError();
515
Jesse Hallb29e5e82012-04-04 16:53:42 -0700516 egl_connection_t* cnx = NULL;
517 const egl_display_ptr dp = validate_display_connection(dpy, cnx);
518 if (dpy) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700519 if (share_list != EGL_NO_CONTEXT) {
520 egl_context_t* const c = get_context(share_list);
521 share_list = c->context;
522 }
523 EGLContext context = cnx->egl.eglCreateContext(
Mathias Agopian7773c432012-02-13 20:06:08 -0800524 dp->disp.dpy, config, share_list, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700525 if (context != EGL_NO_CONTEXT) {
526 // figure out if it's a GLESv1 or GLESv2
527 int version = 0;
528 if (attrib_list) {
529 while (*attrib_list != EGL_NONE) {
530 GLint attr = *attrib_list++;
531 GLint value = *attrib_list++;
532 if (attr == EGL_CONTEXT_CLIENT_VERSION) {
533 if (value == 1) {
Mathias Agopian7773c432012-02-13 20:06:08 -0800534 version = egl_connection_t::GLESv1_INDEX;
Jesse Hall47743382013-02-08 11:13:46 -0800535 } else if (value == 2 || value == 3) {
Mathias Agopian7773c432012-02-13 20:06:08 -0800536 version = egl_connection_t::GLESv2_INDEX;
Mathias Agopian518ec112011-05-13 16:21:08 -0700537 }
538 }
539 };
540 }
Jesse Hallb29e5e82012-04-04 16:53:42 -0700541 egl_context_t* c = new egl_context_t(dpy, context, config, cnx,
542 version);
Siva Velusamy0469dd62011-11-30 15:05:37 -0800543#if EGL_TRACE
Siva Velusamya73a9772012-12-18 14:56:55 -0800544 if (getEGLDebugLevel() > 0)
Siva Velusamy0469dd62011-11-30 15:05:37 -0800545 GLTrace_eglCreateContext(version, c);
546#endif
Mathias Agopian518ec112011-05-13 16:21:08 -0700547 return c;
Mathias Agopian500407a2012-09-24 17:57:48 -0700548 } else {
549 EGLint error = eglGetError();
550 ALOGE_IF(error == EGL_SUCCESS,
551 "eglCreateContext(%p, %p, %p, %p) returned EGL_NO_CONTEXT "
552 "but no EGL error!",
553 dpy, config, share_list, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700554 }
555 }
556 return EGL_NO_CONTEXT;
557}
558
559EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
560{
561 clearError();
562
Jesse Hallb29e5e82012-04-04 16:53:42 -0700563 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700564 if (!dp)
565 return EGL_FALSE;
Mathias Agopian518ec112011-05-13 16:21:08 -0700566
Jesse Hallb29e5e82012-04-04 16:53:42 -0700567 ContextRef _c(dp.get(), ctx);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700568 if (!_c.get())
569 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
Jesse Hall47743382013-02-08 11:13:46 -0800570
Mathias Agopian518ec112011-05-13 16:21:08 -0700571 egl_context_t * const c = get_context(ctx);
Mathias Agopianada798b2012-02-13 17:09:30 -0800572 EGLBoolean result = c->cnx->egl.eglDestroyContext(dp->disp.dpy, c->context);
Mathias Agopian518ec112011-05-13 16:21:08 -0700573 if (result == EGL_TRUE) {
574 _c.terminate();
575 }
576 return result;
577}
578
Mathias Agopian518ec112011-05-13 16:21:08 -0700579EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw,
580 EGLSurface read, EGLContext ctx)
581{
582 clearError();
583
Jesse Hallb29e5e82012-04-04 16:53:42 -0700584 egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700585 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
586
Mathias Agopian5b287a62011-05-16 18:58:55 -0700587 // If ctx is not EGL_NO_CONTEXT, read is not EGL_NO_SURFACE, or draw is not
588 // EGL_NO_SURFACE, then an EGL_NOT_INITIALIZED error is generated if dpy is
589 // a valid but uninitialized display.
Mathias Agopian518ec112011-05-13 16:21:08 -0700590 if ( (ctx != EGL_NO_CONTEXT) || (read != EGL_NO_SURFACE) ||
591 (draw != EGL_NO_SURFACE) ) {
592 if (!dp->isReady()) return setError(EGL_NOT_INITIALIZED, EGL_FALSE);
593 }
594
595 // get a reference to the object passed in
Jesse Hallb29e5e82012-04-04 16:53:42 -0700596 ContextRef _c(dp.get(), ctx);
597 SurfaceRef _d(dp.get(), draw);
598 SurfaceRef _r(dp.get(), read);
Mathias Agopian518ec112011-05-13 16:21:08 -0700599
600 // validate the context (if not EGL_NO_CONTEXT)
Mathias Agopian5b287a62011-05-16 18:58:55 -0700601 if ((ctx != EGL_NO_CONTEXT) && !_c.get()) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700602 // EGL_NO_CONTEXT is valid
603 return EGL_FALSE;
604 }
605
606 // these are the underlying implementation's object
607 EGLContext impl_ctx = EGL_NO_CONTEXT;
608 EGLSurface impl_draw = EGL_NO_SURFACE;
609 EGLSurface impl_read = EGL_NO_SURFACE;
610
611 // these are our objects structs passed in
612 egl_context_t * c = NULL;
613 egl_surface_t const * d = NULL;
614 egl_surface_t const * r = NULL;
615
616 // these are the current objects structs
617 egl_context_t * cur_c = get_context(getContext());
Jesse Hall47743382013-02-08 11:13:46 -0800618
Mathias Agopian518ec112011-05-13 16:21:08 -0700619 if (ctx != EGL_NO_CONTEXT) {
620 c = get_context(ctx);
621 impl_ctx = c->context;
622 } else {
623 // no context given, use the implementation of the current context
624 if (cur_c == NULL) {
625 // no current context
626 if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE) {
627 // calling eglMakeCurrent( ..., !=0, !=0, EGL_NO_CONTEXT);
628 return setError(EGL_BAD_MATCH, EGL_FALSE);
629 }
630 // not an error, there is just no current context.
631 return EGL_TRUE;
632 }
633 }
634
635 // retrieve the underlying implementation's draw EGLSurface
636 if (draw != EGL_NO_SURFACE) {
637 d = get_surface(draw);
Mathias Agopian518ec112011-05-13 16:21:08 -0700638 impl_draw = d->surface;
639 }
640
641 // retrieve the underlying implementation's read EGLSurface
642 if (read != EGL_NO_SURFACE) {
643 r = get_surface(read);
Mathias Agopian518ec112011-05-13 16:21:08 -0700644 impl_read = r->surface;
645 }
646
Mathias Agopian518ec112011-05-13 16:21:08 -0700647
Jesse Hallb29e5e82012-04-04 16:53:42 -0700648 EGLBoolean result = dp->makeCurrent(c, cur_c,
Mathias Agopianfb87e542012-01-30 18:20:52 -0800649 draw, read, ctx,
650 impl_draw, impl_read, impl_ctx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700651
652 if (result == EGL_TRUE) {
Mathias Agopianfb87e542012-01-30 18:20:52 -0800653 if (c) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700654 setGLHooksThreadSpecific(c->cnx->hooks[c->version]);
655 egl_tls_t::setContext(ctx);
Siva Velusamy0469dd62011-11-30 15:05:37 -0800656#if EGL_TRACE
Siva Velusamya73a9772012-12-18 14:56:55 -0800657 if (getEGLDebugLevel() > 0)
Siva Velusamy93a826f2011-12-14 12:19:56 -0800658 GLTrace_eglMakeCurrent(c->version, c->cnx->hooks[c->version], ctx);
Siva Velusamy0469dd62011-11-30 15:05:37 -0800659#endif
Mathias Agopian518ec112011-05-13 16:21:08 -0700660 _c.acquire();
661 _r.acquire();
662 _d.acquire();
Mathias Agopian518ec112011-05-13 16:21:08 -0700663 } else {
664 setGLHooksThreadSpecific(&gHooksNoContext);
665 egl_tls_t::setContext(EGL_NO_CONTEXT);
666 }
Mathias Agopian5fecea72011-08-25 18:38:24 -0700667 } else {
Steve Blocke6f43dd2012-01-06 19:20:56 +0000668 // this will ALOGE the error
Mathias Agopian5fecea72011-08-25 18:38:24 -0700669 result = setError(c->cnx->egl.eglGetError(), EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700670 }
671 return result;
672}
673
674
675EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx,
676 EGLint attribute, EGLint *value)
677{
678 clearError();
679
Jesse Hallb29e5e82012-04-04 16:53:42 -0700680 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700681 if (!dp) return EGL_FALSE;
682
Jesse Hallb29e5e82012-04-04 16:53:42 -0700683 ContextRef _c(dp.get(), ctx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700684 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
685
Mathias Agopian518ec112011-05-13 16:21:08 -0700686 egl_context_t * const c = get_context(ctx);
Mathias Agopian7773c432012-02-13 20:06:08 -0800687 return c->cnx->egl.eglQueryContext(
688 dp->disp.dpy, c->context, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -0700689
Mathias Agopian518ec112011-05-13 16:21:08 -0700690}
691
692EGLContext eglGetCurrentContext(void)
693{
694 // could be called before eglInitialize(), but we wouldn't have a context
695 // then, and this function would correctly return EGL_NO_CONTEXT.
696
697 clearError();
698
699 EGLContext ctx = getContext();
700 return ctx;
701}
702
703EGLSurface eglGetCurrentSurface(EGLint readdraw)
704{
705 // could be called before eglInitialize(), but we wouldn't have a context
706 // then, and this function would correctly return EGL_NO_SURFACE.
707
708 clearError();
709
710 EGLContext ctx = getContext();
711 if (ctx) {
712 egl_context_t const * const c = get_context(ctx);
713 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
714 switch (readdraw) {
715 case EGL_READ: return c->read;
Jesse Hall47743382013-02-08 11:13:46 -0800716 case EGL_DRAW: return c->draw;
Mathias Agopian518ec112011-05-13 16:21:08 -0700717 default: return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
718 }
719 }
720 return EGL_NO_SURFACE;
721}
722
723EGLDisplay eglGetCurrentDisplay(void)
724{
725 // could be called before eglInitialize(), but we wouldn't have a context
726 // then, and this function would correctly return EGL_NO_DISPLAY.
727
728 clearError();
729
730 EGLContext ctx = getContext();
731 if (ctx) {
732 egl_context_t const * const c = get_context(ctx);
733 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
734 return c->dpy;
735 }
736 return EGL_NO_DISPLAY;
737}
738
739EGLBoolean eglWaitGL(void)
740{
Mathias Agopian518ec112011-05-13 16:21:08 -0700741 clearError();
742
Mathias Agopianada798b2012-02-13 17:09:30 -0800743 egl_connection_t* const cnx = &gEGLImpl;
744 if (!cnx->dso)
745 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
746
747 return cnx->egl.eglWaitGL();
Mathias Agopian518ec112011-05-13 16:21:08 -0700748}
749
750EGLBoolean eglWaitNative(EGLint engine)
751{
Mathias Agopian518ec112011-05-13 16:21:08 -0700752 clearError();
753
Mathias Agopianada798b2012-02-13 17:09:30 -0800754 egl_connection_t* const cnx = &gEGLImpl;
755 if (!cnx->dso)
756 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
757
758 return cnx->egl.eglWaitNative(engine);
Mathias Agopian518ec112011-05-13 16:21:08 -0700759}
760
761EGLint eglGetError(void)
762{
Mathias Agopianada798b2012-02-13 17:09:30 -0800763 EGLint err = EGL_SUCCESS;
764 egl_connection_t* const cnx = &gEGLImpl;
765 if (cnx->dso) {
766 err = cnx->egl.eglGetError();
Mathias Agopian518ec112011-05-13 16:21:08 -0700767 }
Mathias Agopianada798b2012-02-13 17:09:30 -0800768 if (err == EGL_SUCCESS) {
769 err = egl_tls_t::getError();
770 }
771 return err;
Mathias Agopian518ec112011-05-13 16:21:08 -0700772}
773
Mathias Agopian518ec112011-05-13 16:21:08 -0700774__eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
775{
776 // eglGetProcAddress() could be the very first function called
777 // in which case we must make sure we've initialized ourselves, this
778 // happens the first time egl_get_display() is called.
779
780 clearError();
781
782 if (egl_init_drivers() == EGL_FALSE) {
783 setError(EGL_BAD_PARAMETER, NULL);
784 return NULL;
785 }
786
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700787 if (FILTER_EXTENSIONS(procname)) {
Jamie Gennisaca51c02011-11-03 17:42:43 -0700788 return NULL;
789 }
790
Mathias Agopian518ec112011-05-13 16:21:08 -0700791 __eglMustCastToProperFunctionPointerType addr;
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700792 addr = findProcAddress(procname, sExtensionMap, NELEM(sExtensionMap));
Mathias Agopian518ec112011-05-13 16:21:08 -0700793 if (addr) return addr;
794
Jamie Gennisaca51c02011-11-03 17:42:43 -0700795
Mathias Agopian518ec112011-05-13 16:21:08 -0700796 // this protects accesses to sGLExtentionMap and sGLExtentionSlot
797 pthread_mutex_lock(&sExtensionMapMutex);
798
799 /*
800 * Since eglGetProcAddress() is not associated to anything, it needs
801 * to return a function pointer that "works" regardless of what
802 * the current context is.
803 *
804 * For this reason, we return a "forwarder", a small stub that takes
805 * care of calling the function associated with the context
806 * currently bound.
807 *
808 * We first look for extensions we've already resolved, if we're seeing
809 * this extension for the first time, we go through all our
810 * implementations and call eglGetProcAddress() and record the
811 * result in the appropriate implementation hooks and return the
812 * address of the forwarder corresponding to that hook set.
813 *
814 */
815
816 const String8 name(procname);
817 addr = sGLExtentionMap.valueFor(name);
818 const int slot = sGLExtentionSlot;
819
Steve Blocke6f43dd2012-01-06 19:20:56 +0000820 ALOGE_IF(slot >= MAX_NUMBER_OF_GL_EXTENSIONS,
Mathias Agopian518ec112011-05-13 16:21:08 -0700821 "no more slots for eglGetProcAddress(\"%s\")",
822 procname);
823
Siva Velusamy0469dd62011-11-30 15:05:37 -0800824#if EGL_TRACE
825 gl_hooks_t *debugHooks = GLTrace_getGLHooks();
826#endif
827
Mathias Agopian518ec112011-05-13 16:21:08 -0700828 if (!addr && (slot < MAX_NUMBER_OF_GL_EXTENSIONS)) {
829 bool found = false;
Mathias Agopianada798b2012-02-13 17:09:30 -0800830
831 egl_connection_t* const cnx = &gEGLImpl;
832 if (cnx->dso && cnx->egl.eglGetProcAddress) {
Mathias Agopianada798b2012-02-13 17:09:30 -0800833 // Extensions are independent of the bound context
luliuhui69d10072012-08-30 11:15:36 +0800834 addr =
Mathias Agopian7773c432012-02-13 20:06:08 -0800835 cnx->hooks[egl_connection_t::GLESv1_INDEX]->ext.extensions[slot] =
836 cnx->hooks[egl_connection_t::GLESv2_INDEX]->ext.extensions[slot] =
Mathias Agopian518ec112011-05-13 16:21:08 -0700837#if EGL_TRACE
Mathias Agopianada798b2012-02-13 17:09:30 -0800838 debugHooks->ext.extensions[slot] =
839 gHooksTrace.ext.extensions[slot] =
Mathias Agopian518ec112011-05-13 16:21:08 -0700840#endif
Mathias Agopianada798b2012-02-13 17:09:30 -0800841 cnx->egl.eglGetProcAddress(procname);
luliuhui69d10072012-08-30 11:15:36 +0800842 if (addr) found = true;
Mathias Agopian518ec112011-05-13 16:21:08 -0700843 }
Mathias Agopianada798b2012-02-13 17:09:30 -0800844
Mathias Agopian518ec112011-05-13 16:21:08 -0700845 if (found) {
luliuhui69d10072012-08-30 11:15:36 +0800846#if USE_FAST_TLS_KEY
Mathias Agopian518ec112011-05-13 16:21:08 -0700847 addr = gExtensionForwarders[slot];
luliuhui69d10072012-08-30 11:15:36 +0800848#endif
Mathias Agopian518ec112011-05-13 16:21:08 -0700849 sGLExtentionMap.add(name, addr);
850 sGLExtentionSlot++;
851 }
852 }
853
854 pthread_mutex_unlock(&sExtensionMapMutex);
855 return addr;
856}
857
Jamie Gennis28ef8d72012-04-05 20:34:54 -0700858class FrameCompletionThread : public Thread {
859public:
860
861 static void queueSync(EGLSyncKHR sync) {
862 static sp<FrameCompletionThread> thread(new FrameCompletionThread);
863 static bool running = false;
864 if (!running) {
865 thread->run("GPUFrameCompletion");
866 running = true;
867 }
868 {
869 Mutex::Autolock lock(thread->mMutex);
870 ScopedTrace st(ATRACE_TAG, String8::format("kicked off frame %d",
871 thread->mFramesQueued).string());
872 thread->mQueue.push_back(sync);
873 thread->mCondition.signal();
874 thread->mFramesQueued++;
875 ATRACE_INT("GPU Frames Outstanding", thread->mQueue.size());
876 }
877 }
878
879private:
880 FrameCompletionThread() : mFramesQueued(0), mFramesCompleted(0) {}
881
882 virtual bool threadLoop() {
883 EGLSyncKHR sync;
884 uint32_t frameNum;
885 {
886 Mutex::Autolock lock(mMutex);
887 while (mQueue.isEmpty()) {
888 mCondition.wait(mMutex);
889 }
890 sync = mQueue[0];
891 frameNum = mFramesCompleted;
892 }
893 EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
894 {
895 ScopedTrace st(ATRACE_TAG, String8::format("waiting for frame %d",
896 frameNum).string());
897 EGLint result = eglClientWaitSyncKHR(dpy, sync, 0, EGL_FOREVER_KHR);
898 if (result == EGL_FALSE) {
899 ALOGE("FrameCompletion: error waiting for fence: %#x", eglGetError());
900 } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
901 ALOGE("FrameCompletion: timeout waiting for fence");
902 }
903 eglDestroySyncKHR(dpy, sync);
904 }
905 {
906 Mutex::Autolock lock(mMutex);
907 mQueue.removeAt(0);
908 mFramesCompleted++;
909 ATRACE_INT("GPU Frames Outstanding", mQueue.size());
910 }
911 return true;
912 }
913
914 uint32_t mFramesQueued;
915 uint32_t mFramesCompleted;
916 Vector<EGLSyncKHR> mQueue;
917 Condition mCondition;
918 Mutex mMutex;
919};
920
Mathias Agopian518ec112011-05-13 16:21:08 -0700921EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw)
922{
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800923 ATRACE_CALL();
Mathias Agopian518ec112011-05-13 16:21:08 -0700924 clearError();
925
Jesse Hallb29e5e82012-04-04 16:53:42 -0700926 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700927 if (!dp) return EGL_FALSE;
928
Jesse Hallb29e5e82012-04-04 16:53:42 -0700929 SurfaceRef _s(dp.get(), draw);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700930 if (!_s.get())
931 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700932
Siva Velusamy0469dd62011-11-30 15:05:37 -0800933#if EGL_TRACE
Siva Velusamya73a9772012-12-18 14:56:55 -0800934 gl_hooks_t const *trace_hooks = getGLTraceThreadSpecific();
935 if (getEGLDebugLevel() > 0) {
936 if (trace_hooks == NULL) {
937 if (GLTrace_start() < 0) {
938 ALOGE("Disabling Tracer for OpenGL ES");
939 setEGLDebugLevel(0);
940 } else {
941 // switch over to the trace version of hooks
942 EGLContext ctx = egl_tls_t::getContext();
943 egl_context_t * const c = get_context(ctx);
944 if (c) {
945 setGLHooksThreadSpecific(c->cnx->hooks[c->version]);
946 GLTrace_eglMakeCurrent(c->version, c->cnx->hooks[c->version], ctx);
947 }
948 }
949 }
950
Siva Velusamy0469dd62011-11-30 15:05:37 -0800951 GLTrace_eglSwapBuffers(dpy, draw);
Siva Velusamya73a9772012-12-18 14:56:55 -0800952 } else if (trace_hooks != NULL) {
953 // tracing is now disabled, so switch back to the non trace version
954 EGLContext ctx = egl_tls_t::getContext();
955 egl_context_t * const c = get_context(ctx);
956 if (c) setGLHooksThreadSpecific(c->cnx->hooks[c->version]);
957 GLTrace_stop();
958 }
Siva Velusamy0469dd62011-11-30 15:05:37 -0800959#endif
960
Mathias Agopian518ec112011-05-13 16:21:08 -0700961 egl_surface_t const * const s = get_surface(draw);
Mathias Agopian7db993a2012-03-25 00:49:46 -0700962
Mathias Agopianed6d08b2013-04-16 16:39:46 -0700963 if (CC_UNLIKELY(dp->traceGpuCompletion)) {
964 EGLSyncKHR sync = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, NULL);
965 if (sync != EGL_NO_SYNC_KHR) {
966 FrameCompletionThread::queueSync(sync);
967 }
968 }
969
Mathias Agopian7db993a2012-03-25 00:49:46 -0700970 if (CC_UNLIKELY(dp->finishOnSwap)) {
971 uint32_t pixel;
972 egl_context_t * const c = get_context( egl_tls_t::getContext() );
973 if (c) {
974 // glReadPixels() ensures that the frame is complete
975 s->cnx->hooks[c->version]->gl.glReadPixels(0,0,1,1,
976 GL_RGBA,GL_UNSIGNED_BYTE,&pixel);
977 }
978 }
979
Mathias Agopianed6d08b2013-04-16 16:39:46 -0700980 return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface);
Mathias Agopian518ec112011-05-13 16:21:08 -0700981}
982
983EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface,
984 NativePixmapType target)
985{
986 clearError();
987
Jesse Hallb29e5e82012-04-04 16:53:42 -0700988 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700989 if (!dp) return EGL_FALSE;
990
Jesse Hallb29e5e82012-04-04 16:53:42 -0700991 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700992 if (!_s.get())
993 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700994
Mathias Agopian518ec112011-05-13 16:21:08 -0700995 egl_surface_t const * const s = get_surface(surface);
Mathias Agopianada798b2012-02-13 17:09:30 -0800996 return s->cnx->egl.eglCopyBuffers(dp->disp.dpy, s->surface, target);
Mathias Agopian518ec112011-05-13 16:21:08 -0700997}
998
999const char* eglQueryString(EGLDisplay dpy, EGLint name)
1000{
1001 clearError();
1002
Jesse Hallb29e5e82012-04-04 16:53:42 -07001003 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001004 if (!dp) return (const char *) NULL;
1005
1006 switch (name) {
1007 case EGL_VENDOR:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001008 return dp->getVendorString();
Mathias Agopian518ec112011-05-13 16:21:08 -07001009 case EGL_VERSION:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001010 return dp->getVersionString();
Mathias Agopian518ec112011-05-13 16:21:08 -07001011 case EGL_EXTENSIONS:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001012 return dp->getExtensionString();
Mathias Agopian518ec112011-05-13 16:21:08 -07001013 case EGL_CLIENT_APIS:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001014 return dp->getClientApiString();
Mathias Agopian518ec112011-05-13 16:21:08 -07001015 }
1016 return setError(EGL_BAD_PARAMETER, (const char *)0);
1017}
1018
Mathias Agopianca088332013-03-28 17:44:13 -07001019EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name)
1020{
1021 clearError();
1022
1023 const egl_display_ptr dp = validate_display(dpy);
1024 if (!dp) return (const char *) NULL;
1025
1026 switch (name) {
1027 case EGL_VENDOR:
1028 return dp->disp.queryString.vendor;
1029 case EGL_VERSION:
1030 return dp->disp.queryString.version;
1031 case EGL_EXTENSIONS:
1032 return dp->disp.queryString.extensions;
1033 case EGL_CLIENT_APIS:
1034 return dp->disp.queryString.clientApi;
1035 }
1036 return setError(EGL_BAD_PARAMETER, (const char *)0);
1037}
Mathias Agopian518ec112011-05-13 16:21:08 -07001038
1039// ----------------------------------------------------------------------------
1040// EGL 1.1
1041// ----------------------------------------------------------------------------
1042
1043EGLBoolean eglSurfaceAttrib(
1044 EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
1045{
1046 clearError();
1047
Jesse Hallb29e5e82012-04-04 16:53:42 -07001048 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001049 if (!dp) return EGL_FALSE;
1050
Jesse Hallb29e5e82012-04-04 16:53:42 -07001051 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001052 if (!_s.get())
1053 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001054
Mathias Agopian518ec112011-05-13 16:21:08 -07001055 egl_surface_t const * const s = get_surface(surface);
1056 if (s->cnx->egl.eglSurfaceAttrib) {
1057 return s->cnx->egl.eglSurfaceAttrib(
Mathias Agopianada798b2012-02-13 17:09:30 -08001058 dp->disp.dpy, s->surface, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -07001059 }
1060 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1061}
1062
1063EGLBoolean eglBindTexImage(
1064 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1065{
1066 clearError();
1067
Jesse Hallb29e5e82012-04-04 16:53:42 -07001068 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001069 if (!dp) return EGL_FALSE;
1070
Jesse Hallb29e5e82012-04-04 16:53:42 -07001071 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001072 if (!_s.get())
1073 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001074
Mathias Agopian518ec112011-05-13 16:21:08 -07001075 egl_surface_t const * const s = get_surface(surface);
1076 if (s->cnx->egl.eglBindTexImage) {
1077 return s->cnx->egl.eglBindTexImage(
Mathias Agopianada798b2012-02-13 17:09:30 -08001078 dp->disp.dpy, s->surface, buffer);
Mathias Agopian518ec112011-05-13 16:21:08 -07001079 }
1080 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1081}
1082
1083EGLBoolean eglReleaseTexImage(
1084 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1085{
1086 clearError();
1087
Jesse Hallb29e5e82012-04-04 16:53:42 -07001088 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001089 if (!dp) return EGL_FALSE;
1090
Jesse Hallb29e5e82012-04-04 16:53:42 -07001091 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001092 if (!_s.get())
1093 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001094
Mathias Agopian518ec112011-05-13 16:21:08 -07001095 egl_surface_t const * const s = get_surface(surface);
1096 if (s->cnx->egl.eglReleaseTexImage) {
1097 return s->cnx->egl.eglReleaseTexImage(
Mathias Agopianada798b2012-02-13 17:09:30 -08001098 dp->disp.dpy, s->surface, buffer);
Mathias Agopian518ec112011-05-13 16:21:08 -07001099 }
1100 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1101}
1102
1103EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
1104{
1105 clearError();
1106
Jesse Hallb29e5e82012-04-04 16:53:42 -07001107 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001108 if (!dp) return EGL_FALSE;
1109
1110 EGLBoolean res = EGL_TRUE;
Mathias Agopianada798b2012-02-13 17:09:30 -08001111 egl_connection_t* const cnx = &gEGLImpl;
1112 if (cnx->dso && cnx->egl.eglSwapInterval) {
1113 res = cnx->egl.eglSwapInterval(dp->disp.dpy, interval);
Mathias Agopian518ec112011-05-13 16:21:08 -07001114 }
Mathias Agopianada798b2012-02-13 17:09:30 -08001115
Mathias Agopian518ec112011-05-13 16:21:08 -07001116 return res;
1117}
1118
1119
1120// ----------------------------------------------------------------------------
1121// EGL 1.2
1122// ----------------------------------------------------------------------------
1123
1124EGLBoolean eglWaitClient(void)
1125{
1126 clearError();
1127
Mathias Agopianada798b2012-02-13 17:09:30 -08001128 egl_connection_t* const cnx = &gEGLImpl;
1129 if (!cnx->dso)
1130 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1131
1132 EGLBoolean res;
1133 if (cnx->egl.eglWaitClient) {
1134 res = cnx->egl.eglWaitClient();
1135 } else {
1136 res = cnx->egl.eglWaitGL();
Mathias Agopian518ec112011-05-13 16:21:08 -07001137 }
1138 return res;
1139}
1140
1141EGLBoolean eglBindAPI(EGLenum api)
1142{
1143 clearError();
1144
1145 if (egl_init_drivers() == EGL_FALSE) {
1146 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1147 }
1148
1149 // bind this API on all EGLs
1150 EGLBoolean res = EGL_TRUE;
Mathias Agopianada798b2012-02-13 17:09:30 -08001151 egl_connection_t* const cnx = &gEGLImpl;
1152 if (cnx->dso && cnx->egl.eglBindAPI) {
1153 res = cnx->egl.eglBindAPI(api);
Mathias Agopian518ec112011-05-13 16:21:08 -07001154 }
1155 return res;
1156}
1157
1158EGLenum eglQueryAPI(void)
1159{
1160 clearError();
1161
1162 if (egl_init_drivers() == EGL_FALSE) {
1163 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1164 }
1165
Mathias Agopianada798b2012-02-13 17:09:30 -08001166 egl_connection_t* const cnx = &gEGLImpl;
1167 if (cnx->dso && cnx->egl.eglQueryAPI) {
1168 return cnx->egl.eglQueryAPI();
Mathias Agopian518ec112011-05-13 16:21:08 -07001169 }
Mathias Agopianada798b2012-02-13 17:09:30 -08001170
Mathias Agopian518ec112011-05-13 16:21:08 -07001171 // or, it can only be OpenGL ES
1172 return EGL_OPENGL_ES_API;
1173}
1174
1175EGLBoolean eglReleaseThread(void)
1176{
1177 clearError();
1178
1179 // If there is context bound to the thread, release it
Mathias Agopianfb87e542012-01-30 18:20:52 -08001180 egl_display_t::loseCurrent(get_context(getContext()));
Mathias Agopian518ec112011-05-13 16:21:08 -07001181
Mathias Agopianada798b2012-02-13 17:09:30 -08001182 egl_connection_t* const cnx = &gEGLImpl;
1183 if (cnx->dso && cnx->egl.eglReleaseThread) {
1184 cnx->egl.eglReleaseThread();
Mathias Agopian518ec112011-05-13 16:21:08 -07001185 }
Mathias Agopianada798b2012-02-13 17:09:30 -08001186
Mathias Agopian518ec112011-05-13 16:21:08 -07001187 egl_tls_t::clearTLS();
Siva Velusamy0469dd62011-11-30 15:05:37 -08001188#if EGL_TRACE
Siva Velusamya73a9772012-12-18 14:56:55 -08001189 if (getEGLDebugLevel() > 0)
Siva Velusamy0469dd62011-11-30 15:05:37 -08001190 GLTrace_eglReleaseThread();
1191#endif
Mathias Agopian518ec112011-05-13 16:21:08 -07001192 return EGL_TRUE;
1193}
1194
1195EGLSurface eglCreatePbufferFromClientBuffer(
1196 EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer,
1197 EGLConfig config, const EGLint *attrib_list)
1198{
1199 clearError();
1200
Jesse Hallb29e5e82012-04-04 16:53:42 -07001201 egl_connection_t* cnx = NULL;
1202 const egl_display_ptr dp = validate_display_connection(dpy, cnx);
1203 if (!dp) return EGL_FALSE;
Mathias Agopian518ec112011-05-13 16:21:08 -07001204 if (cnx->egl.eglCreatePbufferFromClientBuffer) {
1205 return cnx->egl.eglCreatePbufferFromClientBuffer(
Mathias Agopian7773c432012-02-13 20:06:08 -08001206 dp->disp.dpy, buftype, buffer, config, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001207 }
1208 return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE);
1209}
1210
1211// ----------------------------------------------------------------------------
1212// EGL_EGLEXT_VERSION 3
1213// ----------------------------------------------------------------------------
1214
1215EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface,
1216 const EGLint *attrib_list)
1217{
1218 clearError();
1219
Jesse Hallb29e5e82012-04-04 16:53:42 -07001220 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001221 if (!dp) return EGL_FALSE;
1222
Jesse Hallb29e5e82012-04-04 16:53:42 -07001223 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001224 if (!_s.get())
1225 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001226
1227 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian518ec112011-05-13 16:21:08 -07001228 if (s->cnx->egl.eglLockSurfaceKHR) {
1229 return s->cnx->egl.eglLockSurfaceKHR(
Mathias Agopianada798b2012-02-13 17:09:30 -08001230 dp->disp.dpy, s->surface, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001231 }
1232 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1233}
1234
1235EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface)
1236{
1237 clearError();
1238
Jesse Hallb29e5e82012-04-04 16:53:42 -07001239 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001240 if (!dp) return EGL_FALSE;
1241
Jesse Hallb29e5e82012-04-04 16:53:42 -07001242 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001243 if (!_s.get())
1244 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001245
1246 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian518ec112011-05-13 16:21:08 -07001247 if (s->cnx->egl.eglUnlockSurfaceKHR) {
Mathias Agopianada798b2012-02-13 17:09:30 -08001248 return s->cnx->egl.eglUnlockSurfaceKHR(dp->disp.dpy, s->surface);
Mathias Agopian518ec112011-05-13 16:21:08 -07001249 }
1250 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1251}
1252
1253EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
1254 EGLClientBuffer buffer, const EGLint *attrib_list)
1255{
1256 clearError();
1257
Jesse Hallb29e5e82012-04-04 16:53:42 -07001258 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001259 if (!dp) return EGL_NO_IMAGE_KHR;
1260
Jesse Hallb29e5e82012-04-04 16:53:42 -07001261 ContextRef _c(dp.get(), ctx);
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001262 egl_context_t * const c = _c.get();
Mathias Agopian518ec112011-05-13 16:21:08 -07001263
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001264 EGLImageKHR result = EGL_NO_IMAGE_KHR;
1265 egl_connection_t* const cnx = &gEGLImpl;
1266 if (cnx->dso && cnx->egl.eglCreateImageKHR) {
1267 result = cnx->egl.eglCreateImageKHR(
1268 dp->disp.dpy,
1269 c ? c->context : EGL_NO_CONTEXT,
1270 target, buffer, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001271 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001272 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001273}
1274
1275EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
1276{
1277 clearError();
1278
Jesse Hallb29e5e82012-04-04 16:53:42 -07001279 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001280 if (!dp) return EGL_FALSE;
1281
Steven Holte646a5c52012-06-04 20:02:11 -07001282 EGLBoolean result = EGL_FALSE;
Mathias Agopianada798b2012-02-13 17:09:30 -08001283 egl_connection_t* const cnx = &gEGLImpl;
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001284 if (cnx->dso && cnx->egl.eglDestroyImageKHR) {
Steven Holte646a5c52012-06-04 20:02:11 -07001285 result = cnx->egl.eglDestroyImageKHR(dp->disp.dpy, img);
Mathias Agopian518ec112011-05-13 16:21:08 -07001286 }
Steven Holte646a5c52012-06-04 20:02:11 -07001287 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001288}
1289
1290// ----------------------------------------------------------------------------
1291// EGL_EGLEXT_VERSION 5
1292// ----------------------------------------------------------------------------
1293
1294
1295EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
1296{
1297 clearError();
1298
Jesse Hallb29e5e82012-04-04 16:53:42 -07001299 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001300 if (!dp) return EGL_NO_SYNC_KHR;
1301
Mathias Agopian518ec112011-05-13 16:21:08 -07001302 EGLSyncKHR result = EGL_NO_SYNC_KHR;
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001303 egl_connection_t* const cnx = &gEGLImpl;
1304 if (cnx->dso && cnx->egl.eglCreateSyncKHR) {
1305 result = cnx->egl.eglCreateSyncKHR(dp->disp.dpy, type, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001306 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001307 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001308}
1309
1310EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
1311{
1312 clearError();
1313
Jesse Hallb29e5e82012-04-04 16:53:42 -07001314 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001315 if (!dp) return EGL_FALSE;
1316
Mathias Agopian518ec112011-05-13 16:21:08 -07001317 EGLBoolean result = EGL_FALSE;
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001318 egl_connection_t* const cnx = &gEGLImpl;
1319 if (cnx->dso && cnx->egl.eglDestroySyncKHR) {
1320 result = cnx->egl.eglDestroySyncKHR(dp->disp.dpy, sync);
Mathias Agopian518ec112011-05-13 16:21:08 -07001321 }
1322 return result;
1323}
1324
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -07001325EGLBoolean eglSignalSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode) {
1326 clearError();
1327
1328 const egl_display_ptr dp = validate_display(dpy);
1329 if (!dp) return EGL_FALSE;
1330
1331 EGLBoolean result = EGL_FALSE;
1332 egl_connection_t* const cnx = &gEGLImpl;
1333 if (cnx->dso && cnx->egl.eglSignalSyncKHR) {
1334 result = cnx->egl.eglSignalSyncKHR(
1335 dp->disp.dpy, sync, mode);
1336 }
1337 return result;
1338}
1339
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001340EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync,
1341 EGLint flags, EGLTimeKHR timeout)
Mathias Agopian518ec112011-05-13 16:21:08 -07001342{
1343 clearError();
1344
Jesse Hallb29e5e82012-04-04 16:53:42 -07001345 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001346 if (!dp) return EGL_FALSE;
1347
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001348 EGLBoolean result = EGL_FALSE;
1349 egl_connection_t* const cnx = &gEGLImpl;
1350 if (cnx->dso && cnx->egl.eglClientWaitSyncKHR) {
1351 result = cnx->egl.eglClientWaitSyncKHR(
1352 dp->disp.dpy, sync, flags, timeout);
Mathias Agopian518ec112011-05-13 16:21:08 -07001353 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001354 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001355}
1356
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001357EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync,
1358 EGLint attribute, EGLint *value)
Mathias Agopian518ec112011-05-13 16:21:08 -07001359{
1360 clearError();
1361
Jesse Hallb29e5e82012-04-04 16:53:42 -07001362 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001363 if (!dp) return EGL_FALSE;
1364
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001365 EGLBoolean result = EGL_FALSE;
1366 egl_connection_t* const cnx = &gEGLImpl;
1367 if (cnx->dso && cnx->egl.eglGetSyncAttribKHR) {
1368 result = cnx->egl.eglGetSyncAttribKHR(
1369 dp->disp.dpy, sync, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -07001370 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001371 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001372}
1373
1374// ----------------------------------------------------------------------------
Mathias Agopian2bb71682013-03-27 17:32:41 -07001375// EGL_EGLEXT_VERSION 15
1376// ----------------------------------------------------------------------------
1377
1378EGLint eglWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags) {
1379 clearError();
1380 const egl_display_ptr dp = validate_display(dpy);
1381 if (!dp) return EGL_FALSE;
1382 EGLint result = EGL_FALSE;
1383 egl_connection_t* const cnx = &gEGLImpl;
1384 if (cnx->dso && cnx->egl.eglWaitSyncKHR) {
1385 result = cnx->egl.eglWaitSyncKHR(dp->disp.dpy, sync, flags);
1386 }
1387 return result;
1388}
1389
1390// ----------------------------------------------------------------------------
Mathias Agopian518ec112011-05-13 16:21:08 -07001391// ANDROID extensions
1392// ----------------------------------------------------------------------------
1393
Jamie Gennis331841b2012-09-06 14:52:00 -07001394EGLint eglDupNativeFenceFDANDROID(EGLDisplay dpy, EGLSyncKHR sync)
1395{
1396 clearError();
1397
1398 const egl_display_ptr dp = validate_display(dpy);
1399 if (!dp) return EGL_NO_NATIVE_FENCE_FD_ANDROID;
1400
1401 EGLint result = EGL_NO_NATIVE_FENCE_FD_ANDROID;
1402 egl_connection_t* const cnx = &gEGLImpl;
1403 if (cnx->dso && cnx->egl.eglDupNativeFenceFDANDROID) {
1404 result = cnx->egl.eglDupNativeFenceFDANDROID(dp->disp.dpy, sync);
1405 }
1406 return result;
1407}
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001408
Andy McFadden72841452013-03-01 16:25:32 -08001409EGLBoolean eglPresentationTimeANDROID(EGLDisplay dpy, EGLSurface surface,
1410 EGLnsecsANDROID time)
1411{
1412 clearError();
1413
1414 const egl_display_ptr dp = validate_display(dpy);
1415 if (!dp) {
1416 return EGL_FALSE;
1417 }
1418
1419 SurfaceRef _s(dp.get(), surface);
1420 if (!_s.get()) {
1421 setError(EGL_BAD_SURFACE, EGL_FALSE);
1422 return EGL_FALSE;
1423 }
1424
1425 egl_surface_t const * const s = get_surface(surface);
1426 native_window_set_buffers_timestamp(s->win.get(), time);
1427
1428 return EGL_TRUE;
1429}
1430
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001431// ----------------------------------------------------------------------------
1432// NVIDIA extensions
1433// ----------------------------------------------------------------------------
1434EGLuint64NV eglGetSystemTimeFrequencyNV()
1435{
1436 clearError();
1437
1438 if (egl_init_drivers() == EGL_FALSE) {
1439 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1440 }
1441
1442 EGLuint64NV ret = 0;
Mathias Agopianada798b2012-02-13 17:09:30 -08001443 egl_connection_t* const cnx = &gEGLImpl;
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001444
Mathias Agopianada798b2012-02-13 17:09:30 -08001445 if (cnx->dso && cnx->egl.eglGetSystemTimeFrequencyNV) {
1446 return cnx->egl.eglGetSystemTimeFrequencyNV();
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001447 }
1448
Mathias Agopian0e8bbee2011-10-05 19:15:05 -07001449 return setErrorQuiet(EGL_BAD_DISPLAY, 0);
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001450}
1451
1452EGLuint64NV eglGetSystemTimeNV()
1453{
1454 clearError();
1455
1456 if (egl_init_drivers() == EGL_FALSE) {
1457 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1458 }
1459
1460 EGLuint64NV ret = 0;
Mathias Agopianada798b2012-02-13 17:09:30 -08001461 egl_connection_t* const cnx = &gEGLImpl;
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001462
Mathias Agopianada798b2012-02-13 17:09:30 -08001463 if (cnx->dso && cnx->egl.eglGetSystemTimeNV) {
1464 return cnx->egl.eglGetSystemTimeNV();
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001465 }
1466
Mathias Agopian0e8bbee2011-10-05 19:15:05 -07001467 return setErrorQuiet(EGL_BAD_DISPLAY, 0);
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001468}