blob: f6bc06901dd527d176a80e839702fa4f870cb460 [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
963 if (CC_UNLIKELY(dp->finishOnSwap)) {
964 uint32_t pixel;
965 egl_context_t * const c = get_context( egl_tls_t::getContext() );
966 if (c) {
967 // glReadPixels() ensures that the frame is complete
968 s->cnx->hooks[c->version]->gl.glReadPixels(0,0,1,1,
969 GL_RGBA,GL_UNSIGNED_BYTE,&pixel);
970 }
971 }
972
Jamie Gennis28ef8d72012-04-05 20:34:54 -0700973 EGLBoolean result = s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface);
974
975 if (CC_UNLIKELY(dp->traceGpuCompletion)) {
976 EGLSyncKHR sync = EGL_NO_SYNC_KHR;
977 {
978 sync = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, NULL);
979 }
980 if (sync != EGL_NO_SYNC_KHR) {
981 FrameCompletionThread::queueSync(sync);
982 }
983 }
984
985 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -0700986}
987
988EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface,
989 NativePixmapType target)
990{
991 clearError();
992
Jesse Hallb29e5e82012-04-04 16:53:42 -0700993 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700994 if (!dp) return EGL_FALSE;
995
Jesse Hallb29e5e82012-04-04 16:53:42 -0700996 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700997 if (!_s.get())
998 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700999
Mathias Agopian518ec112011-05-13 16:21:08 -07001000 egl_surface_t const * const s = get_surface(surface);
Mathias Agopianada798b2012-02-13 17:09:30 -08001001 return s->cnx->egl.eglCopyBuffers(dp->disp.dpy, s->surface, target);
Mathias Agopian518ec112011-05-13 16:21:08 -07001002}
1003
1004const char* eglQueryString(EGLDisplay dpy, EGLint name)
1005{
1006 clearError();
1007
Jesse Hallb29e5e82012-04-04 16:53:42 -07001008 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001009 if (!dp) return (const char *) NULL;
1010
1011 switch (name) {
1012 case EGL_VENDOR:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001013 return dp->getVendorString();
Mathias Agopian518ec112011-05-13 16:21:08 -07001014 case EGL_VERSION:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001015 return dp->getVersionString();
Mathias Agopian518ec112011-05-13 16:21:08 -07001016 case EGL_EXTENSIONS:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001017 return dp->getExtensionString();
Mathias Agopian518ec112011-05-13 16:21:08 -07001018 case EGL_CLIENT_APIS:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001019 return dp->getClientApiString();
Mathias Agopian518ec112011-05-13 16:21:08 -07001020 }
1021 return setError(EGL_BAD_PARAMETER, (const char *)0);
1022}
1023
Mathias Agopianca088332013-03-28 17:44:13 -07001024EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name)
1025{
1026 clearError();
1027
1028 const egl_display_ptr dp = validate_display(dpy);
1029 if (!dp) return (const char *) NULL;
1030
1031 switch (name) {
1032 case EGL_VENDOR:
1033 return dp->disp.queryString.vendor;
1034 case EGL_VERSION:
1035 return dp->disp.queryString.version;
1036 case EGL_EXTENSIONS:
1037 return dp->disp.queryString.extensions;
1038 case EGL_CLIENT_APIS:
1039 return dp->disp.queryString.clientApi;
1040 }
1041 return setError(EGL_BAD_PARAMETER, (const char *)0);
1042}
Mathias Agopian518ec112011-05-13 16:21:08 -07001043
1044// ----------------------------------------------------------------------------
1045// EGL 1.1
1046// ----------------------------------------------------------------------------
1047
1048EGLBoolean eglSurfaceAttrib(
1049 EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
1050{
1051 clearError();
1052
Jesse Hallb29e5e82012-04-04 16:53:42 -07001053 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001054 if (!dp) return EGL_FALSE;
1055
Jesse Hallb29e5e82012-04-04 16:53:42 -07001056 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001057 if (!_s.get())
1058 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001059
Mathias Agopian518ec112011-05-13 16:21:08 -07001060 egl_surface_t const * const s = get_surface(surface);
1061 if (s->cnx->egl.eglSurfaceAttrib) {
1062 return s->cnx->egl.eglSurfaceAttrib(
Mathias Agopianada798b2012-02-13 17:09:30 -08001063 dp->disp.dpy, s->surface, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -07001064 }
1065 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1066}
1067
1068EGLBoolean eglBindTexImage(
1069 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1070{
1071 clearError();
1072
Jesse Hallb29e5e82012-04-04 16:53:42 -07001073 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001074 if (!dp) return EGL_FALSE;
1075
Jesse Hallb29e5e82012-04-04 16:53:42 -07001076 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001077 if (!_s.get())
1078 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001079
Mathias Agopian518ec112011-05-13 16:21:08 -07001080 egl_surface_t const * const s = get_surface(surface);
1081 if (s->cnx->egl.eglBindTexImage) {
1082 return s->cnx->egl.eglBindTexImage(
Mathias Agopianada798b2012-02-13 17:09:30 -08001083 dp->disp.dpy, s->surface, buffer);
Mathias Agopian518ec112011-05-13 16:21:08 -07001084 }
1085 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1086}
1087
1088EGLBoolean eglReleaseTexImage(
1089 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1090{
1091 clearError();
1092
Jesse Hallb29e5e82012-04-04 16:53:42 -07001093 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001094 if (!dp) return EGL_FALSE;
1095
Jesse Hallb29e5e82012-04-04 16:53:42 -07001096 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001097 if (!_s.get())
1098 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001099
Mathias Agopian518ec112011-05-13 16:21:08 -07001100 egl_surface_t const * const s = get_surface(surface);
1101 if (s->cnx->egl.eglReleaseTexImage) {
1102 return s->cnx->egl.eglReleaseTexImage(
Mathias Agopianada798b2012-02-13 17:09:30 -08001103 dp->disp.dpy, s->surface, buffer);
Mathias Agopian518ec112011-05-13 16:21:08 -07001104 }
1105 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1106}
1107
1108EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
1109{
1110 clearError();
1111
Jesse Hallb29e5e82012-04-04 16:53:42 -07001112 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001113 if (!dp) return EGL_FALSE;
1114
1115 EGLBoolean res = EGL_TRUE;
Mathias Agopianada798b2012-02-13 17:09:30 -08001116 egl_connection_t* const cnx = &gEGLImpl;
1117 if (cnx->dso && cnx->egl.eglSwapInterval) {
1118 res = cnx->egl.eglSwapInterval(dp->disp.dpy, interval);
Mathias Agopian518ec112011-05-13 16:21:08 -07001119 }
Mathias Agopianada798b2012-02-13 17:09:30 -08001120
Mathias Agopian518ec112011-05-13 16:21:08 -07001121 return res;
1122}
1123
1124
1125// ----------------------------------------------------------------------------
1126// EGL 1.2
1127// ----------------------------------------------------------------------------
1128
1129EGLBoolean eglWaitClient(void)
1130{
1131 clearError();
1132
Mathias Agopianada798b2012-02-13 17:09:30 -08001133 egl_connection_t* const cnx = &gEGLImpl;
1134 if (!cnx->dso)
1135 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1136
1137 EGLBoolean res;
1138 if (cnx->egl.eglWaitClient) {
1139 res = cnx->egl.eglWaitClient();
1140 } else {
1141 res = cnx->egl.eglWaitGL();
Mathias Agopian518ec112011-05-13 16:21:08 -07001142 }
1143 return res;
1144}
1145
1146EGLBoolean eglBindAPI(EGLenum api)
1147{
1148 clearError();
1149
1150 if (egl_init_drivers() == EGL_FALSE) {
1151 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1152 }
1153
1154 // bind this API on all EGLs
1155 EGLBoolean res = EGL_TRUE;
Mathias Agopianada798b2012-02-13 17:09:30 -08001156 egl_connection_t* const cnx = &gEGLImpl;
1157 if (cnx->dso && cnx->egl.eglBindAPI) {
1158 res = cnx->egl.eglBindAPI(api);
Mathias Agopian518ec112011-05-13 16:21:08 -07001159 }
1160 return res;
1161}
1162
1163EGLenum eglQueryAPI(void)
1164{
1165 clearError();
1166
1167 if (egl_init_drivers() == EGL_FALSE) {
1168 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1169 }
1170
Mathias Agopianada798b2012-02-13 17:09:30 -08001171 egl_connection_t* const cnx = &gEGLImpl;
1172 if (cnx->dso && cnx->egl.eglQueryAPI) {
1173 return cnx->egl.eglQueryAPI();
Mathias Agopian518ec112011-05-13 16:21:08 -07001174 }
Mathias Agopianada798b2012-02-13 17:09:30 -08001175
Mathias Agopian518ec112011-05-13 16:21:08 -07001176 // or, it can only be OpenGL ES
1177 return EGL_OPENGL_ES_API;
1178}
1179
1180EGLBoolean eglReleaseThread(void)
1181{
1182 clearError();
1183
1184 // If there is context bound to the thread, release it
Mathias Agopianfb87e542012-01-30 18:20:52 -08001185 egl_display_t::loseCurrent(get_context(getContext()));
Mathias Agopian518ec112011-05-13 16:21:08 -07001186
Mathias Agopianada798b2012-02-13 17:09:30 -08001187 egl_connection_t* const cnx = &gEGLImpl;
1188 if (cnx->dso && cnx->egl.eglReleaseThread) {
1189 cnx->egl.eglReleaseThread();
Mathias Agopian518ec112011-05-13 16:21:08 -07001190 }
Mathias Agopianada798b2012-02-13 17:09:30 -08001191
Mathias Agopian518ec112011-05-13 16:21:08 -07001192 egl_tls_t::clearTLS();
Siva Velusamy0469dd62011-11-30 15:05:37 -08001193#if EGL_TRACE
Siva Velusamya73a9772012-12-18 14:56:55 -08001194 if (getEGLDebugLevel() > 0)
Siva Velusamy0469dd62011-11-30 15:05:37 -08001195 GLTrace_eglReleaseThread();
1196#endif
Mathias Agopian518ec112011-05-13 16:21:08 -07001197 return EGL_TRUE;
1198}
1199
1200EGLSurface eglCreatePbufferFromClientBuffer(
1201 EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer,
1202 EGLConfig config, const EGLint *attrib_list)
1203{
1204 clearError();
1205
Jesse Hallb29e5e82012-04-04 16:53:42 -07001206 egl_connection_t* cnx = NULL;
1207 const egl_display_ptr dp = validate_display_connection(dpy, cnx);
1208 if (!dp) return EGL_FALSE;
Mathias Agopian518ec112011-05-13 16:21:08 -07001209 if (cnx->egl.eglCreatePbufferFromClientBuffer) {
1210 return cnx->egl.eglCreatePbufferFromClientBuffer(
Mathias Agopian7773c432012-02-13 20:06:08 -08001211 dp->disp.dpy, buftype, buffer, config, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001212 }
1213 return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE);
1214}
1215
1216// ----------------------------------------------------------------------------
1217// EGL_EGLEXT_VERSION 3
1218// ----------------------------------------------------------------------------
1219
1220EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface,
1221 const EGLint *attrib_list)
1222{
1223 clearError();
1224
Jesse Hallb29e5e82012-04-04 16:53:42 -07001225 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001226 if (!dp) return EGL_FALSE;
1227
Jesse Hallb29e5e82012-04-04 16:53:42 -07001228 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001229 if (!_s.get())
1230 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001231
1232 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian518ec112011-05-13 16:21:08 -07001233 if (s->cnx->egl.eglLockSurfaceKHR) {
1234 return s->cnx->egl.eglLockSurfaceKHR(
Mathias Agopianada798b2012-02-13 17:09:30 -08001235 dp->disp.dpy, s->surface, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001236 }
1237 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1238}
1239
1240EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface)
1241{
1242 clearError();
1243
Jesse Hallb29e5e82012-04-04 16:53:42 -07001244 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001245 if (!dp) return EGL_FALSE;
1246
Jesse Hallb29e5e82012-04-04 16:53:42 -07001247 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001248 if (!_s.get())
1249 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001250
1251 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian518ec112011-05-13 16:21:08 -07001252 if (s->cnx->egl.eglUnlockSurfaceKHR) {
Mathias Agopianada798b2012-02-13 17:09:30 -08001253 return s->cnx->egl.eglUnlockSurfaceKHR(dp->disp.dpy, s->surface);
Mathias Agopian518ec112011-05-13 16:21:08 -07001254 }
1255 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1256}
1257
1258EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
1259 EGLClientBuffer buffer, const EGLint *attrib_list)
1260{
1261 clearError();
1262
Jesse Hallb29e5e82012-04-04 16:53:42 -07001263 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001264 if (!dp) return EGL_NO_IMAGE_KHR;
1265
Jesse Hallb29e5e82012-04-04 16:53:42 -07001266 ContextRef _c(dp.get(), ctx);
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001267 egl_context_t * const c = _c.get();
Mathias Agopian518ec112011-05-13 16:21:08 -07001268
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001269 EGLImageKHR result = EGL_NO_IMAGE_KHR;
1270 egl_connection_t* const cnx = &gEGLImpl;
1271 if (cnx->dso && cnx->egl.eglCreateImageKHR) {
1272 result = cnx->egl.eglCreateImageKHR(
1273 dp->disp.dpy,
1274 c ? c->context : EGL_NO_CONTEXT,
1275 target, buffer, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001276 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001277 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001278}
1279
1280EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
1281{
1282 clearError();
1283
Jesse Hallb29e5e82012-04-04 16:53:42 -07001284 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001285 if (!dp) return EGL_FALSE;
1286
Steven Holte646a5c52012-06-04 20:02:11 -07001287 EGLBoolean result = EGL_FALSE;
Mathias Agopianada798b2012-02-13 17:09:30 -08001288 egl_connection_t* const cnx = &gEGLImpl;
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001289 if (cnx->dso && cnx->egl.eglDestroyImageKHR) {
Steven Holte646a5c52012-06-04 20:02:11 -07001290 result = cnx->egl.eglDestroyImageKHR(dp->disp.dpy, img);
Mathias Agopian518ec112011-05-13 16:21:08 -07001291 }
Steven Holte646a5c52012-06-04 20:02:11 -07001292 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001293}
1294
1295// ----------------------------------------------------------------------------
1296// EGL_EGLEXT_VERSION 5
1297// ----------------------------------------------------------------------------
1298
1299
1300EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
1301{
1302 clearError();
1303
Jesse Hallb29e5e82012-04-04 16:53:42 -07001304 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001305 if (!dp) return EGL_NO_SYNC_KHR;
1306
Mathias Agopian518ec112011-05-13 16:21:08 -07001307 EGLSyncKHR result = EGL_NO_SYNC_KHR;
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001308 egl_connection_t* const cnx = &gEGLImpl;
1309 if (cnx->dso && cnx->egl.eglCreateSyncKHR) {
1310 result = cnx->egl.eglCreateSyncKHR(dp->disp.dpy, type, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001311 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001312 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001313}
1314
1315EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
1316{
1317 clearError();
1318
Jesse Hallb29e5e82012-04-04 16:53:42 -07001319 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001320 if (!dp) return EGL_FALSE;
1321
Mathias Agopian518ec112011-05-13 16:21:08 -07001322 EGLBoolean result = EGL_FALSE;
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001323 egl_connection_t* const cnx = &gEGLImpl;
1324 if (cnx->dso && cnx->egl.eglDestroySyncKHR) {
1325 result = cnx->egl.eglDestroySyncKHR(dp->disp.dpy, sync);
Mathias Agopian518ec112011-05-13 16:21:08 -07001326 }
1327 return result;
1328}
1329
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -07001330EGLBoolean eglSignalSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode) {
1331 clearError();
1332
1333 const egl_display_ptr dp = validate_display(dpy);
1334 if (!dp) return EGL_FALSE;
1335
1336 EGLBoolean result = EGL_FALSE;
1337 egl_connection_t* const cnx = &gEGLImpl;
1338 if (cnx->dso && cnx->egl.eglSignalSyncKHR) {
1339 result = cnx->egl.eglSignalSyncKHR(
1340 dp->disp.dpy, sync, mode);
1341 }
1342 return result;
1343}
1344
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001345EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync,
1346 EGLint flags, EGLTimeKHR timeout)
Mathias Agopian518ec112011-05-13 16:21:08 -07001347{
1348 clearError();
1349
Jesse Hallb29e5e82012-04-04 16:53:42 -07001350 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001351 if (!dp) return EGL_FALSE;
1352
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001353 EGLBoolean result = EGL_FALSE;
1354 egl_connection_t* const cnx = &gEGLImpl;
1355 if (cnx->dso && cnx->egl.eglClientWaitSyncKHR) {
1356 result = cnx->egl.eglClientWaitSyncKHR(
1357 dp->disp.dpy, sync, flags, timeout);
Mathias Agopian518ec112011-05-13 16:21:08 -07001358 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001359 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001360}
1361
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001362EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync,
1363 EGLint attribute, EGLint *value)
Mathias Agopian518ec112011-05-13 16:21:08 -07001364{
1365 clearError();
1366
Jesse Hallb29e5e82012-04-04 16:53:42 -07001367 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001368 if (!dp) return EGL_FALSE;
1369
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001370 EGLBoolean result = EGL_FALSE;
1371 egl_connection_t* const cnx = &gEGLImpl;
1372 if (cnx->dso && cnx->egl.eglGetSyncAttribKHR) {
1373 result = cnx->egl.eglGetSyncAttribKHR(
1374 dp->disp.dpy, sync, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -07001375 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001376 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001377}
1378
1379// ----------------------------------------------------------------------------
Mathias Agopian2bb71682013-03-27 17:32:41 -07001380// EGL_EGLEXT_VERSION 15
1381// ----------------------------------------------------------------------------
1382
1383EGLint eglWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags) {
1384 clearError();
1385 const egl_display_ptr dp = validate_display(dpy);
1386 if (!dp) return EGL_FALSE;
1387 EGLint result = EGL_FALSE;
1388 egl_connection_t* const cnx = &gEGLImpl;
1389 if (cnx->dso && cnx->egl.eglWaitSyncKHR) {
1390 result = cnx->egl.eglWaitSyncKHR(dp->disp.dpy, sync, flags);
1391 }
1392 return result;
1393}
1394
1395// ----------------------------------------------------------------------------
Mathias Agopian518ec112011-05-13 16:21:08 -07001396// ANDROID extensions
1397// ----------------------------------------------------------------------------
1398
Jamie Gennis331841b2012-09-06 14:52:00 -07001399EGLint eglDupNativeFenceFDANDROID(EGLDisplay dpy, EGLSyncKHR sync)
1400{
1401 clearError();
1402
1403 const egl_display_ptr dp = validate_display(dpy);
1404 if (!dp) return EGL_NO_NATIVE_FENCE_FD_ANDROID;
1405
1406 EGLint result = EGL_NO_NATIVE_FENCE_FD_ANDROID;
1407 egl_connection_t* const cnx = &gEGLImpl;
1408 if (cnx->dso && cnx->egl.eglDupNativeFenceFDANDROID) {
1409 result = cnx->egl.eglDupNativeFenceFDANDROID(dp->disp.dpy, sync);
1410 }
1411 return result;
1412}
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001413
Andy McFadden72841452013-03-01 16:25:32 -08001414EGLBoolean eglPresentationTimeANDROID(EGLDisplay dpy, EGLSurface surface,
1415 EGLnsecsANDROID time)
1416{
1417 clearError();
1418
1419 const egl_display_ptr dp = validate_display(dpy);
1420 if (!dp) {
1421 return EGL_FALSE;
1422 }
1423
1424 SurfaceRef _s(dp.get(), surface);
1425 if (!_s.get()) {
1426 setError(EGL_BAD_SURFACE, EGL_FALSE);
1427 return EGL_FALSE;
1428 }
1429
1430 egl_surface_t const * const s = get_surface(surface);
1431 native_window_set_buffers_timestamp(s->win.get(), time);
1432
1433 return EGL_TRUE;
1434}
1435
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001436// ----------------------------------------------------------------------------
1437// NVIDIA extensions
1438// ----------------------------------------------------------------------------
1439EGLuint64NV eglGetSystemTimeFrequencyNV()
1440{
1441 clearError();
1442
1443 if (egl_init_drivers() == EGL_FALSE) {
1444 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1445 }
1446
1447 EGLuint64NV ret = 0;
Mathias Agopianada798b2012-02-13 17:09:30 -08001448 egl_connection_t* const cnx = &gEGLImpl;
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001449
Mathias Agopianada798b2012-02-13 17:09:30 -08001450 if (cnx->dso && cnx->egl.eglGetSystemTimeFrequencyNV) {
1451 return cnx->egl.eglGetSystemTimeFrequencyNV();
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001452 }
1453
Mathias Agopian0e8bbee2011-10-05 19:15:05 -07001454 return setErrorQuiet(EGL_BAD_DISPLAY, 0);
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001455}
1456
1457EGLuint64NV eglGetSystemTimeNV()
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.eglGetSystemTimeNV) {
1469 return cnx->egl.eglGetSystemTimeNV();
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}