blob: c1f2b2e14697c33b9c279fdeaf4d28f4652ac6bb [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
40#include "egl_impl.h"
41#include "egl_tls.h"
Siva Velusamy0469dd62011-11-30 15:05:37 -080042#include "glestrace.h"
Mathias Agopian518ec112011-05-13 16:21:08 -070043#include "hooks.h"
44
45#include "egl_display.h"
46#include "egl_impl.h"
47#include "egl_object.h"
48#include "egl_tls.h"
Mathias Agopianada798b2012-02-13 17:09:30 -080049#include "egldefs.h"
Mathias Agopian518ec112011-05-13 16:21:08 -070050
51using namespace android;
52
53// ----------------------------------------------------------------------------
54
Mathias Agopianbc2d79e2011-11-29 17:55:46 -080055#define EGL_VERSION_HW_ANDROID 0x3143
56
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070057namespace android {
58
Mathias Agopian518ec112011-05-13 16:21:08 -070059struct extention_map_t {
60 const char* name;
61 __eglMustCastToProperFunctionPointerType address;
62};
63
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070064/*
65 * This is the list of EGL extensions exposed to applications,
66 * some of them are mandatory because used by the ANDROID system.
67 *
68 * Mandatory extensions are required per the CDD and not explicitly
69 * checked during EGL initialization. the system *assumes* these extensions
70 * are present. the system may not function properly if some mandatory
71 * extensions are missing.
72 *
73 * NOTE: gExtensionString MUST have a single space as the last character.
74 */
75extern char const * const gExtensionString =
76 "EGL_KHR_image " // mandatory
77 "EGL_KHR_image_base " // mandatory
78 "EGL_KHR_image_pixmap "
79 "EGL_KHR_lock_surface "
80 "EGL_KHR_gl_texture_2D_image "
81 "EGL_KHR_gl_texture_cubemap_image "
82 "EGL_KHR_gl_renderbuffer_image "
83 "EGL_KHR_reusable_sync "
84 "EGL_KHR_fence_sync "
85 "EGL_EXT_create_context_robustness "
86 "EGL_NV_system_time "
87 "EGL_ANDROID_image_native_buffer " // mandatory
88 "EGL_ANDROID_wait_sync " // strongly recommended
89 "EGL_ANDROID_presentation_time "
90 ;
91
92// extensions not exposed to applications but used by the ANDROID system
93// "EGL_ANDROID_blob_cache " // strongly recommended
94// "EGL_IMG_hibernate_process " // optional
95// "EGL_ANDROID_native_fence_sync " // strongly recommended
96// "EGL_ANDROID_framebuffer_target " // mandatory for HWC 1.1
97// "EGL_ANDROID_recordable " // mandatory
98
99
100/*
101 * EGL Extensions entry-points exposed to 3rd party applications
102 * (keep in sync with gExtensionString above)
103 *
104 */
105static const extention_map_t sExtensionMap[] = {
106 // EGL_KHR_lock_surface
Mathias Agopian518ec112011-05-13 16:21:08 -0700107 { "eglLockSurfaceKHR",
108 (__eglMustCastToProperFunctionPointerType)&eglLockSurfaceKHR },
109 { "eglUnlockSurfaceKHR",
110 (__eglMustCastToProperFunctionPointerType)&eglUnlockSurfaceKHR },
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700111
112 // EGL_KHR_image, EGL_KHR_image_base
Mathias Agopian518ec112011-05-13 16:21:08 -0700113 { "eglCreateImageKHR",
114 (__eglMustCastToProperFunctionPointerType)&eglCreateImageKHR },
115 { "eglDestroyImageKHR",
116 (__eglMustCastToProperFunctionPointerType)&eglDestroyImageKHR },
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700117
118 // EGL_KHR_reusable_sync, EGL_KHR_fence_sync
119 { "eglCreateSyncKHR",
120 (__eglMustCastToProperFunctionPointerType)&eglCreateSyncKHR },
121 { "eglDestroySyncKHR",
122 (__eglMustCastToProperFunctionPointerType)&eglDestroySyncKHR },
123 { "eglClientWaitSyncKHR",
124 (__eglMustCastToProperFunctionPointerType)&eglClientWaitSyncKHR },
125 { "eglSignalSyncKHR",
126 (__eglMustCastToProperFunctionPointerType)&eglSignalSyncKHR },
127 { "eglGetSyncAttribKHR",
128 (__eglMustCastToProperFunctionPointerType)&eglGetSyncAttribKHR },
129
130 // EGL_NV_system_time
Jonas Yang1c3d72a2011-08-26 20:04:39 +0800131 { "eglGetSystemTimeFrequencyNV",
132 (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeFrequencyNV },
133 { "eglGetSystemTimeNV",
134 (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeNV },
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700135
136 // EGL_ANDROID_wait_sync
137 { "eglWaitSyncANDROID",
138 (__eglMustCastToProperFunctionPointerType)&eglWaitSyncANDROID },
139
140 // EGL_ANDROID_presentation_time
141 { "eglPresentationTimeANDROID",
142 (__eglMustCastToProperFunctionPointerType)&eglPresentationTimeANDROID },
Mathias Agopian518ec112011-05-13 16:21:08 -0700143};
144
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700145/*
146 * These extensions entry-points should not be exposed to applications.
147 * They're used internally by the Android EGL layer.
148 */
149#define FILTER_EXTENSIONS(procname) \
150 (!strcmp((procname), "eglSetBlobCacheFuncsANDROID") || \
151 !strcmp((procname), "eglHibernateProcessIMG") || \
152 !strcmp((procname), "eglAwakenProcessIMG") || \
153 !strcmp((procname), "eglDupNativeFenceFDANDROID"))
154
155
156
Mathias Agopian518ec112011-05-13 16:21:08 -0700157// accesses protected by sExtensionMapMutex
158static DefaultKeyedVector<String8, __eglMustCastToProperFunctionPointerType> sGLExtentionMap;
159static int sGLExtentionSlot = 0;
160static pthread_mutex_t sExtensionMapMutex = PTHREAD_MUTEX_INITIALIZER;
161
162static void(*findProcAddress(const char* name,
163 const extention_map_t* map, size_t n))() {
164 for (uint32_t i=0 ; i<n ; i++) {
165 if (!strcmp(name, map[i].name)) {
166 return map[i].address;
167 }
168 }
169 return NULL;
170}
171
172// ----------------------------------------------------------------------------
173
Mathias Agopian518ec112011-05-13 16:21:08 -0700174extern void setGLHooksThreadSpecific(gl_hooks_t const *value);
175extern EGLBoolean egl_init_drivers();
176extern const __eglMustCastToProperFunctionPointerType gExtensionForwarders[MAX_NUMBER_OF_GL_EXTENSIONS];
Siva Velusamya73a9772012-12-18 14:56:55 -0800177extern int getEGLDebugLevel();
178extern void setEGLDebugLevel(int level);
Mathias Agopian518ec112011-05-13 16:21:08 -0700179extern gl_hooks_t gHooksTrace;
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700180
Mathias Agopian518ec112011-05-13 16:21:08 -0700181} // namespace android;
182
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700183
Mathias Agopian518ec112011-05-13 16:21:08 -0700184// ----------------------------------------------------------------------------
185
186static inline void clearError() { egl_tls_t::clearError(); }
187static inline EGLContext getContext() { return egl_tls_t::getContext(); }
188
189// ----------------------------------------------------------------------------
190
191EGLDisplay eglGetDisplay(EGLNativeDisplayType display)
192{
193 clearError();
194
195 uint32_t index = uint32_t(display);
196 if (index >= NUM_DISPLAYS) {
197 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
198 }
199
200 if (egl_init_drivers() == EGL_FALSE) {
201 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
202 }
203
204 EGLDisplay dpy = egl_display_t::getFromNativeDisplay(display);
205 return dpy;
206}
207
208// ----------------------------------------------------------------------------
209// Initialization
210// ----------------------------------------------------------------------------
211
212EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
213{
214 clearError();
215
Jesse Hallb29e5e82012-04-04 16:53:42 -0700216 egl_display_ptr dp = get_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700217 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
218
219 EGLBoolean res = dp->initialize(major, minor);
220
221 return res;
222}
223
224EGLBoolean eglTerminate(EGLDisplay dpy)
225{
226 // NOTE: don't unload the drivers b/c some APIs can be called
227 // after eglTerminate() has been called. eglTerminate() only
228 // terminates an EGLDisplay, not a EGL itself.
229
230 clearError();
231
Jesse Hallb29e5e82012-04-04 16:53:42 -0700232 egl_display_ptr dp = get_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700233 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
234
235 EGLBoolean res = dp->terminate();
Jesse Hall47743382013-02-08 11:13:46 -0800236
Mathias Agopian518ec112011-05-13 16:21:08 -0700237 return res;
238}
239
240// ----------------------------------------------------------------------------
241// configuration
242// ----------------------------------------------------------------------------
243
244EGLBoolean eglGetConfigs( EGLDisplay dpy,
245 EGLConfig *configs,
246 EGLint config_size, EGLint *num_config)
247{
248 clearError();
249
Jesse Hallb29e5e82012-04-04 16:53:42 -0700250 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700251 if (!dp) return EGL_FALSE;
252
Mathias Agopian7773c432012-02-13 20:06:08 -0800253 if (num_config==0) {
254 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700255 }
256
Mathias Agopian7773c432012-02-13 20:06:08 -0800257 EGLBoolean res = EGL_FALSE;
258 *num_config = 0;
259
260 egl_connection_t* const cnx = &gEGLImpl;
261 if (cnx->dso) {
262 res = cnx->egl.eglGetConfigs(
263 dp->disp.dpy, configs, config_size, num_config);
Mathias Agopian518ec112011-05-13 16:21:08 -0700264 }
Mathias Agopian7773c432012-02-13 20:06:08 -0800265
266 return res;
Mathias Agopian518ec112011-05-13 16:21:08 -0700267}
268
269EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list,
270 EGLConfig *configs, EGLint config_size,
271 EGLint *num_config)
272{
273 clearError();
274
Jesse Hallb29e5e82012-04-04 16:53:42 -0700275 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700276 if (!dp) return EGL_FALSE;
277
278 if (num_config==0) {
279 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
280 }
281
Mathias Agopian518ec112011-05-13 16:21:08 -0700282 EGLBoolean res = EGL_FALSE;
283 *num_config = 0;
284
Mathias Agopianada798b2012-02-13 17:09:30 -0800285 egl_connection_t* const cnx = &gEGLImpl;
286 if (cnx->dso) {
Romain Guy1cffc802012-10-15 18:13:05 -0700287 if (attrib_list) {
288 char value[PROPERTY_VALUE_MAX];
289 property_get("debug.egl.force_msaa", value, "false");
290
291 if (!strcmp(value, "true")) {
292 size_t attribCount = 0;
293 EGLint attrib = attrib_list[0];
294
295 // Only enable MSAA if the context is OpenGL ES 2.0 and
Romain Guybe3c3e42012-10-15 19:25:18 -0700296 // if no caveat is requested
Romain Guy1cffc802012-10-15 18:13:05 -0700297 const EGLint *attribRendererable = NULL;
298 const EGLint *attribCaveat = NULL;
299
300 // Count the number of attributes and look for
Romain Guybe3c3e42012-10-15 19:25:18 -0700301 // EGL_RENDERABLE_TYPE and EGL_CONFIG_CAVEAT
Romain Guy1cffc802012-10-15 18:13:05 -0700302 while (attrib != EGL_NONE) {
303 attrib = attrib_list[attribCount];
304 switch (attrib) {
305 case EGL_RENDERABLE_TYPE:
306 attribRendererable = &attrib_list[attribCount];
307 break;
308 case EGL_CONFIG_CAVEAT:
309 attribCaveat = &attrib_list[attribCount];
310 break;
311 }
312 attribCount++;
313 }
314
315 if (attribRendererable && attribRendererable[1] == EGL_OPENGL_ES2_BIT &&
316 (!attribCaveat || attribCaveat[1] != EGL_NONE)) {
Jesse Hall47743382013-02-08 11:13:46 -0800317
Romain Guy1cffc802012-10-15 18:13:05 -0700318 // Insert 2 extra attributes to force-enable MSAA 4x
319 EGLint aaAttribs[attribCount + 4];
320 aaAttribs[0] = EGL_SAMPLE_BUFFERS;
321 aaAttribs[1] = 1;
322 aaAttribs[2] = EGL_SAMPLES;
323 aaAttribs[3] = 4;
324
325 memcpy(&aaAttribs[4], attrib_list, attribCount * sizeof(EGLint));
326
327 EGLint numConfigAA;
328 EGLBoolean resAA = cnx->egl.eglChooseConfig(
329 dp->disp.dpy, aaAttribs, configs, config_size, &numConfigAA);
330
331 if (resAA == EGL_TRUE && numConfigAA > 0) {
332 ALOGD("Enabling MSAA 4x");
333 *num_config = numConfigAA;
334 return resAA;
335 }
336 }
337 }
338 }
339
Mathias Agopian7773c432012-02-13 20:06:08 -0800340 res = cnx->egl.eglChooseConfig(
341 dp->disp.dpy, attrib_list, configs, config_size, num_config);
Mathias Agopian518ec112011-05-13 16:21:08 -0700342 }
343 return res;
344}
345
346EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
347 EGLint attribute, EGLint *value)
348{
349 clearError();
350
Jesse Hallb29e5e82012-04-04 16:53:42 -0700351 egl_connection_t* cnx = NULL;
352 const egl_display_ptr dp = validate_display_connection(dpy, cnx);
353 if (!dp) return EGL_FALSE;
Jesse Hall47743382013-02-08 11:13:46 -0800354
Mathias Agopian518ec112011-05-13 16:21:08 -0700355 return cnx->egl.eglGetConfigAttrib(
Mathias Agopian7773c432012-02-13 20:06:08 -0800356 dp->disp.dpy, config, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -0700357}
358
359// ----------------------------------------------------------------------------
360// surfaces
361// ----------------------------------------------------------------------------
362
363EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config,
364 NativeWindowType window,
365 const EGLint *attrib_list)
366{
367 clearError();
368
Jesse Hallb29e5e82012-04-04 16:53:42 -0700369 egl_connection_t* cnx = NULL;
370 egl_display_ptr dp = validate_display_connection(dpy, cnx);
371 if (dp) {
Mathias Agopianada798b2012-02-13 17:09:30 -0800372 EGLDisplay iDpy = dp->disp.dpy;
Mathias Agopian518ec112011-05-13 16:21:08 -0700373 EGLint format;
374
Mathias Agopian81a63352011-07-29 17:55:48 -0700375 if (native_window_api_connect(window, NATIVE_WINDOW_API_EGL) != OK) {
Steve Blocke6f43dd2012-01-06 19:20:56 +0000376 ALOGE("EGLNativeWindowType %p already connected to another API",
Mathias Agopian81a63352011-07-29 17:55:48 -0700377 window);
378 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
379 }
380
Mathias Agopian518ec112011-05-13 16:21:08 -0700381 // set the native window's buffers format to match this config
382 if (cnx->egl.eglGetConfigAttrib(iDpy,
Mathias Agopian7773c432012-02-13 20:06:08 -0800383 config, EGL_NATIVE_VISUAL_ID, &format)) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700384 if (format != 0) {
Jamie Gennisbee205f2011-07-01 13:12:07 -0700385 int err = native_window_set_buffers_format(window, format);
386 if (err != 0) {
Steve Blocke6f43dd2012-01-06 19:20:56 +0000387 ALOGE("error setting native window pixel format: %s (%d)",
Jamie Gennisbee205f2011-07-01 13:12:07 -0700388 strerror(-err), err);
Mathias Agopian81a63352011-07-29 17:55:48 -0700389 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
Jamie Gennisbee205f2011-07-01 13:12:07 -0700390 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
391 }
Mathias Agopian518ec112011-05-13 16:21:08 -0700392 }
393 }
394
Jamie Gennis59769462011-11-19 18:04:43 -0800395 // the EGL spec requires that a new EGLSurface default to swap interval
396 // 1, so explicitly set that on the window here.
397 ANativeWindow* anw = reinterpret_cast<ANativeWindow*>(window);
398 anw->setSwapInterval(anw, 1);
399
Mathias Agopian518ec112011-05-13 16:21:08 -0700400 EGLSurface surface = cnx->egl.eglCreateWindowSurface(
Mathias Agopian7773c432012-02-13 20:06:08 -0800401 iDpy, config, window, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700402 if (surface != EGL_NO_SURFACE) {
Jesse Hallb29e5e82012-04-04 16:53:42 -0700403 egl_surface_t* s = new egl_surface_t(dp.get(), config, window,
404 surface, cnx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700405 return s;
406 }
Mathias Agopian81a63352011-07-29 17:55:48 -0700407
408 // EGLSurface creation failed
409 native_window_set_buffers_format(window, 0);
410 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
Mathias Agopian518ec112011-05-13 16:21:08 -0700411 }
412 return EGL_NO_SURFACE;
413}
414
415EGLSurface eglCreatePixmapSurface( EGLDisplay dpy, EGLConfig config,
416 NativePixmapType pixmap,
417 const EGLint *attrib_list)
418{
419 clearError();
420
Jesse Hallb29e5e82012-04-04 16:53:42 -0700421 egl_connection_t* cnx = NULL;
422 egl_display_ptr dp = validate_display_connection(dpy, cnx);
423 if (dp) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700424 EGLSurface surface = cnx->egl.eglCreatePixmapSurface(
Mathias Agopian7773c432012-02-13 20:06:08 -0800425 dp->disp.dpy, config, pixmap, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700426 if (surface != EGL_NO_SURFACE) {
Jesse Hallb29e5e82012-04-04 16:53:42 -0700427 egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL,
428 surface, cnx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700429 return s;
430 }
431 }
432 return EGL_NO_SURFACE;
433}
434
435EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config,
436 const EGLint *attrib_list)
437{
438 clearError();
439
Jesse Hallb29e5e82012-04-04 16:53:42 -0700440 egl_connection_t* cnx = NULL;
441 egl_display_ptr dp = validate_display_connection(dpy, cnx);
442 if (dp) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700443 EGLSurface surface = cnx->egl.eglCreatePbufferSurface(
Mathias Agopian7773c432012-02-13 20:06:08 -0800444 dp->disp.dpy, config, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700445 if (surface != EGL_NO_SURFACE) {
Jesse Hallb29e5e82012-04-04 16:53:42 -0700446 egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL,
447 surface, cnx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700448 return s;
449 }
450 }
451 return EGL_NO_SURFACE;
452}
Jesse Hall47743382013-02-08 11:13:46 -0800453
Mathias Agopian518ec112011-05-13 16:21:08 -0700454EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
455{
456 clearError();
457
Jesse Hallb29e5e82012-04-04 16:53:42 -0700458 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700459 if (!dp) return EGL_FALSE;
460
Jesse Hallb29e5e82012-04-04 16:53:42 -0700461 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700462 if (!_s.get())
463 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700464
465 egl_surface_t * const s = get_surface(surface);
Mathias Agopianada798b2012-02-13 17:09:30 -0800466 EGLBoolean result = s->cnx->egl.eglDestroySurface(dp->disp.dpy, s->surface);
Mathias Agopian518ec112011-05-13 16:21:08 -0700467 if (result == EGL_TRUE) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700468 _s.terminate();
469 }
470 return result;
471}
472
473EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface surface,
474 EGLint attribute, EGLint *value)
475{
476 clearError();
477
Jesse Hallb29e5e82012-04-04 16:53:42 -0700478 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700479 if (!dp) return EGL_FALSE;
480
Jesse Hallb29e5e82012-04-04 16:53:42 -0700481 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700482 if (!_s.get())
483 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700484
Mathias Agopian518ec112011-05-13 16:21:08 -0700485 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian7773c432012-02-13 20:06:08 -0800486 return s->cnx->egl.eglQuerySurface(
487 dp->disp.dpy, s->surface, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -0700488}
489
Jamie Gennise8696a42012-01-15 18:54:57 -0800490void EGLAPI eglBeginFrame(EGLDisplay dpy, EGLSurface surface) {
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800491 ATRACE_CALL();
Jamie Gennise8696a42012-01-15 18:54:57 -0800492 clearError();
493
Jesse Hallb29e5e82012-04-04 16:53:42 -0700494 const egl_display_ptr dp = validate_display(dpy);
Jamie Gennise8696a42012-01-15 18:54:57 -0800495 if (!dp) {
496 return;
497 }
498
Jesse Hallb29e5e82012-04-04 16:53:42 -0700499 SurfaceRef _s(dp.get(), surface);
Jamie Gennise8696a42012-01-15 18:54:57 -0800500 if (!_s.get()) {
501 setError(EGL_BAD_SURFACE, EGL_FALSE);
502 return;
503 }
504
505 int64_t timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
506
507 egl_surface_t const * const s = get_surface(surface);
508 native_window_set_buffers_timestamp(s->win.get(), timestamp);
509}
510
Mathias Agopian518ec112011-05-13 16:21:08 -0700511// ----------------------------------------------------------------------------
512// Contexts
513// ----------------------------------------------------------------------------
514
515EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config,
516 EGLContext share_list, const EGLint *attrib_list)
517{
518 clearError();
519
Jesse Hallb29e5e82012-04-04 16:53:42 -0700520 egl_connection_t* cnx = NULL;
521 const egl_display_ptr dp = validate_display_connection(dpy, cnx);
522 if (dpy) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700523 if (share_list != EGL_NO_CONTEXT) {
524 egl_context_t* const c = get_context(share_list);
525 share_list = c->context;
526 }
527 EGLContext context = cnx->egl.eglCreateContext(
Mathias Agopian7773c432012-02-13 20:06:08 -0800528 dp->disp.dpy, config, share_list, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700529 if (context != EGL_NO_CONTEXT) {
530 // figure out if it's a GLESv1 or GLESv2
531 int version = 0;
532 if (attrib_list) {
533 while (*attrib_list != EGL_NONE) {
534 GLint attr = *attrib_list++;
535 GLint value = *attrib_list++;
536 if (attr == EGL_CONTEXT_CLIENT_VERSION) {
537 if (value == 1) {
Mathias Agopian7773c432012-02-13 20:06:08 -0800538 version = egl_connection_t::GLESv1_INDEX;
Jesse Hall47743382013-02-08 11:13:46 -0800539 } else if (value == 2 || value == 3) {
Mathias Agopian7773c432012-02-13 20:06:08 -0800540 version = egl_connection_t::GLESv2_INDEX;
Mathias Agopian518ec112011-05-13 16:21:08 -0700541 }
542 }
543 };
544 }
Jesse Hallb29e5e82012-04-04 16:53:42 -0700545 egl_context_t* c = new egl_context_t(dpy, context, config, cnx,
546 version);
Siva Velusamy0469dd62011-11-30 15:05:37 -0800547#if EGL_TRACE
Siva Velusamya73a9772012-12-18 14:56:55 -0800548 if (getEGLDebugLevel() > 0)
Siva Velusamy0469dd62011-11-30 15:05:37 -0800549 GLTrace_eglCreateContext(version, c);
550#endif
Mathias Agopian518ec112011-05-13 16:21:08 -0700551 return c;
Mathias Agopian500407a2012-09-24 17:57:48 -0700552 } else {
553 EGLint error = eglGetError();
554 ALOGE_IF(error == EGL_SUCCESS,
555 "eglCreateContext(%p, %p, %p, %p) returned EGL_NO_CONTEXT "
556 "but no EGL error!",
557 dpy, config, share_list, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700558 }
559 }
560 return EGL_NO_CONTEXT;
561}
562
563EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
564{
565 clearError();
566
Jesse Hallb29e5e82012-04-04 16:53:42 -0700567 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700568 if (!dp)
569 return EGL_FALSE;
Mathias Agopian518ec112011-05-13 16:21:08 -0700570
Jesse Hallb29e5e82012-04-04 16:53:42 -0700571 ContextRef _c(dp.get(), ctx);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700572 if (!_c.get())
573 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
Jesse Hall47743382013-02-08 11:13:46 -0800574
Mathias Agopian518ec112011-05-13 16:21:08 -0700575 egl_context_t * const c = get_context(ctx);
Mathias Agopianada798b2012-02-13 17:09:30 -0800576 EGLBoolean result = c->cnx->egl.eglDestroyContext(dp->disp.dpy, c->context);
Mathias Agopian518ec112011-05-13 16:21:08 -0700577 if (result == EGL_TRUE) {
578 _c.terminate();
579 }
580 return result;
581}
582
Mathias Agopian518ec112011-05-13 16:21:08 -0700583EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw,
584 EGLSurface read, EGLContext ctx)
585{
586 clearError();
587
Jesse Hallb29e5e82012-04-04 16:53:42 -0700588 egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700589 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
590
Mathias Agopian5b287a62011-05-16 18:58:55 -0700591 // If ctx is not EGL_NO_CONTEXT, read is not EGL_NO_SURFACE, or draw is not
592 // EGL_NO_SURFACE, then an EGL_NOT_INITIALIZED error is generated if dpy is
593 // a valid but uninitialized display.
Mathias Agopian518ec112011-05-13 16:21:08 -0700594 if ( (ctx != EGL_NO_CONTEXT) || (read != EGL_NO_SURFACE) ||
595 (draw != EGL_NO_SURFACE) ) {
596 if (!dp->isReady()) return setError(EGL_NOT_INITIALIZED, EGL_FALSE);
597 }
598
599 // get a reference to the object passed in
Jesse Hallb29e5e82012-04-04 16:53:42 -0700600 ContextRef _c(dp.get(), ctx);
601 SurfaceRef _d(dp.get(), draw);
602 SurfaceRef _r(dp.get(), read);
Mathias Agopian518ec112011-05-13 16:21:08 -0700603
604 // validate the context (if not EGL_NO_CONTEXT)
Mathias Agopian5b287a62011-05-16 18:58:55 -0700605 if ((ctx != EGL_NO_CONTEXT) && !_c.get()) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700606 // EGL_NO_CONTEXT is valid
607 return EGL_FALSE;
608 }
609
610 // these are the underlying implementation's object
611 EGLContext impl_ctx = EGL_NO_CONTEXT;
612 EGLSurface impl_draw = EGL_NO_SURFACE;
613 EGLSurface impl_read = EGL_NO_SURFACE;
614
615 // these are our objects structs passed in
616 egl_context_t * c = NULL;
617 egl_surface_t const * d = NULL;
618 egl_surface_t const * r = NULL;
619
620 // these are the current objects structs
621 egl_context_t * cur_c = get_context(getContext());
Jesse Hall47743382013-02-08 11:13:46 -0800622
Mathias Agopian518ec112011-05-13 16:21:08 -0700623 if (ctx != EGL_NO_CONTEXT) {
624 c = get_context(ctx);
625 impl_ctx = c->context;
626 } else {
627 // no context given, use the implementation of the current context
628 if (cur_c == NULL) {
629 // no current context
630 if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE) {
631 // calling eglMakeCurrent( ..., !=0, !=0, EGL_NO_CONTEXT);
632 return setError(EGL_BAD_MATCH, EGL_FALSE);
633 }
634 // not an error, there is just no current context.
635 return EGL_TRUE;
636 }
637 }
638
639 // retrieve the underlying implementation's draw EGLSurface
640 if (draw != EGL_NO_SURFACE) {
641 d = get_surface(draw);
Mathias Agopian518ec112011-05-13 16:21:08 -0700642 impl_draw = d->surface;
643 }
644
645 // retrieve the underlying implementation's read EGLSurface
646 if (read != EGL_NO_SURFACE) {
647 r = get_surface(read);
Mathias Agopian518ec112011-05-13 16:21:08 -0700648 impl_read = r->surface;
649 }
650
Mathias Agopian518ec112011-05-13 16:21:08 -0700651
Jesse Hallb29e5e82012-04-04 16:53:42 -0700652 EGLBoolean result = dp->makeCurrent(c, cur_c,
Mathias Agopianfb87e542012-01-30 18:20:52 -0800653 draw, read, ctx,
654 impl_draw, impl_read, impl_ctx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700655
656 if (result == EGL_TRUE) {
Mathias Agopianfb87e542012-01-30 18:20:52 -0800657 if (c) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700658 setGLHooksThreadSpecific(c->cnx->hooks[c->version]);
659 egl_tls_t::setContext(ctx);
Siva Velusamy0469dd62011-11-30 15:05:37 -0800660#if EGL_TRACE
Siva Velusamya73a9772012-12-18 14:56:55 -0800661 if (getEGLDebugLevel() > 0)
Siva Velusamy93a826f2011-12-14 12:19:56 -0800662 GLTrace_eglMakeCurrent(c->version, c->cnx->hooks[c->version], ctx);
Siva Velusamy0469dd62011-11-30 15:05:37 -0800663#endif
Mathias Agopian518ec112011-05-13 16:21:08 -0700664 _c.acquire();
665 _r.acquire();
666 _d.acquire();
Mathias Agopian518ec112011-05-13 16:21:08 -0700667 } else {
668 setGLHooksThreadSpecific(&gHooksNoContext);
669 egl_tls_t::setContext(EGL_NO_CONTEXT);
670 }
Mathias Agopian5fecea72011-08-25 18:38:24 -0700671 } else {
Steve Blocke6f43dd2012-01-06 19:20:56 +0000672 // this will ALOGE the error
Mathias Agopian5fecea72011-08-25 18:38:24 -0700673 result = setError(c->cnx->egl.eglGetError(), EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700674 }
675 return result;
676}
677
678
679EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx,
680 EGLint attribute, EGLint *value)
681{
682 clearError();
683
Jesse Hallb29e5e82012-04-04 16:53:42 -0700684 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700685 if (!dp) return EGL_FALSE;
686
Jesse Hallb29e5e82012-04-04 16:53:42 -0700687 ContextRef _c(dp.get(), ctx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700688 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
689
Mathias Agopian518ec112011-05-13 16:21:08 -0700690 egl_context_t * const c = get_context(ctx);
Mathias Agopian7773c432012-02-13 20:06:08 -0800691 return c->cnx->egl.eglQueryContext(
692 dp->disp.dpy, c->context, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -0700693
Mathias Agopian518ec112011-05-13 16:21:08 -0700694}
695
696EGLContext eglGetCurrentContext(void)
697{
698 // could be called before eglInitialize(), but we wouldn't have a context
699 // then, and this function would correctly return EGL_NO_CONTEXT.
700
701 clearError();
702
703 EGLContext ctx = getContext();
704 return ctx;
705}
706
707EGLSurface eglGetCurrentSurface(EGLint readdraw)
708{
709 // could be called before eglInitialize(), but we wouldn't have a context
710 // then, and this function would correctly return EGL_NO_SURFACE.
711
712 clearError();
713
714 EGLContext ctx = getContext();
715 if (ctx) {
716 egl_context_t const * const c = get_context(ctx);
717 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
718 switch (readdraw) {
719 case EGL_READ: return c->read;
Jesse Hall47743382013-02-08 11:13:46 -0800720 case EGL_DRAW: return c->draw;
Mathias Agopian518ec112011-05-13 16:21:08 -0700721 default: return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
722 }
723 }
724 return EGL_NO_SURFACE;
725}
726
727EGLDisplay eglGetCurrentDisplay(void)
728{
729 // could be called before eglInitialize(), but we wouldn't have a context
730 // then, and this function would correctly return EGL_NO_DISPLAY.
731
732 clearError();
733
734 EGLContext ctx = getContext();
735 if (ctx) {
736 egl_context_t const * const c = get_context(ctx);
737 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
738 return c->dpy;
739 }
740 return EGL_NO_DISPLAY;
741}
742
743EGLBoolean eglWaitGL(void)
744{
Mathias Agopian518ec112011-05-13 16:21:08 -0700745 clearError();
746
Mathias Agopianada798b2012-02-13 17:09:30 -0800747 egl_connection_t* const cnx = &gEGLImpl;
748 if (!cnx->dso)
749 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
750
751 return cnx->egl.eglWaitGL();
Mathias Agopian518ec112011-05-13 16:21:08 -0700752}
753
754EGLBoolean eglWaitNative(EGLint engine)
755{
Mathias Agopian518ec112011-05-13 16:21:08 -0700756 clearError();
757
Mathias Agopianada798b2012-02-13 17:09:30 -0800758 egl_connection_t* const cnx = &gEGLImpl;
759 if (!cnx->dso)
760 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
761
762 return cnx->egl.eglWaitNative(engine);
Mathias Agopian518ec112011-05-13 16:21:08 -0700763}
764
765EGLint eglGetError(void)
766{
Mathias Agopianada798b2012-02-13 17:09:30 -0800767 EGLint err = EGL_SUCCESS;
768 egl_connection_t* const cnx = &gEGLImpl;
769 if (cnx->dso) {
770 err = cnx->egl.eglGetError();
Mathias Agopian518ec112011-05-13 16:21:08 -0700771 }
Mathias Agopianada798b2012-02-13 17:09:30 -0800772 if (err == EGL_SUCCESS) {
773 err = egl_tls_t::getError();
774 }
775 return err;
Mathias Agopian518ec112011-05-13 16:21:08 -0700776}
777
Mathias Agopian518ec112011-05-13 16:21:08 -0700778__eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
779{
780 // eglGetProcAddress() could be the very first function called
781 // in which case we must make sure we've initialized ourselves, this
782 // happens the first time egl_get_display() is called.
783
784 clearError();
785
786 if (egl_init_drivers() == EGL_FALSE) {
787 setError(EGL_BAD_PARAMETER, NULL);
788 return NULL;
789 }
790
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700791 if (FILTER_EXTENSIONS(procname)) {
Jamie Gennisaca51c02011-11-03 17:42:43 -0700792 return NULL;
793 }
794
Mathias Agopian518ec112011-05-13 16:21:08 -0700795 __eglMustCastToProperFunctionPointerType addr;
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700796 addr = findProcAddress(procname, sExtensionMap, NELEM(sExtensionMap));
Mathias Agopian518ec112011-05-13 16:21:08 -0700797 if (addr) return addr;
798
Jamie Gennisaca51c02011-11-03 17:42:43 -0700799
Mathias Agopian518ec112011-05-13 16:21:08 -0700800 // this protects accesses to sGLExtentionMap and sGLExtentionSlot
801 pthread_mutex_lock(&sExtensionMapMutex);
802
803 /*
804 * Since eglGetProcAddress() is not associated to anything, it needs
805 * to return a function pointer that "works" regardless of what
806 * the current context is.
807 *
808 * For this reason, we return a "forwarder", a small stub that takes
809 * care of calling the function associated with the context
810 * currently bound.
811 *
812 * We first look for extensions we've already resolved, if we're seeing
813 * this extension for the first time, we go through all our
814 * implementations and call eglGetProcAddress() and record the
815 * result in the appropriate implementation hooks and return the
816 * address of the forwarder corresponding to that hook set.
817 *
818 */
819
820 const String8 name(procname);
821 addr = sGLExtentionMap.valueFor(name);
822 const int slot = sGLExtentionSlot;
823
Steve Blocke6f43dd2012-01-06 19:20:56 +0000824 ALOGE_IF(slot >= MAX_NUMBER_OF_GL_EXTENSIONS,
Mathias Agopian518ec112011-05-13 16:21:08 -0700825 "no more slots for eglGetProcAddress(\"%s\")",
826 procname);
827
Siva Velusamy0469dd62011-11-30 15:05:37 -0800828#if EGL_TRACE
829 gl_hooks_t *debugHooks = GLTrace_getGLHooks();
830#endif
831
Mathias Agopian518ec112011-05-13 16:21:08 -0700832 if (!addr && (slot < MAX_NUMBER_OF_GL_EXTENSIONS)) {
833 bool found = false;
Mathias Agopianada798b2012-02-13 17:09:30 -0800834
835 egl_connection_t* const cnx = &gEGLImpl;
836 if (cnx->dso && cnx->egl.eglGetProcAddress) {
Mathias Agopianada798b2012-02-13 17:09:30 -0800837 // Extensions are independent of the bound context
luliuhui69d10072012-08-30 11:15:36 +0800838 addr =
Mathias Agopian7773c432012-02-13 20:06:08 -0800839 cnx->hooks[egl_connection_t::GLESv1_INDEX]->ext.extensions[slot] =
840 cnx->hooks[egl_connection_t::GLESv2_INDEX]->ext.extensions[slot] =
Mathias Agopian518ec112011-05-13 16:21:08 -0700841#if EGL_TRACE
Mathias Agopianada798b2012-02-13 17:09:30 -0800842 debugHooks->ext.extensions[slot] =
843 gHooksTrace.ext.extensions[slot] =
Mathias Agopian518ec112011-05-13 16:21:08 -0700844#endif
Mathias Agopianada798b2012-02-13 17:09:30 -0800845 cnx->egl.eglGetProcAddress(procname);
luliuhui69d10072012-08-30 11:15:36 +0800846 if (addr) found = true;
Mathias Agopian518ec112011-05-13 16:21:08 -0700847 }
Mathias Agopianada798b2012-02-13 17:09:30 -0800848
Mathias Agopian518ec112011-05-13 16:21:08 -0700849 if (found) {
luliuhui69d10072012-08-30 11:15:36 +0800850#if USE_FAST_TLS_KEY
Mathias Agopian518ec112011-05-13 16:21:08 -0700851 addr = gExtensionForwarders[slot];
luliuhui69d10072012-08-30 11:15:36 +0800852#endif
Mathias Agopian518ec112011-05-13 16:21:08 -0700853 sGLExtentionMap.add(name, addr);
854 sGLExtentionSlot++;
855 }
856 }
857
858 pthread_mutex_unlock(&sExtensionMapMutex);
859 return addr;
860}
861
Jamie Gennis28ef8d72012-04-05 20:34:54 -0700862class FrameCompletionThread : public Thread {
863public:
864
865 static void queueSync(EGLSyncKHR sync) {
866 static sp<FrameCompletionThread> thread(new FrameCompletionThread);
867 static bool running = false;
868 if (!running) {
869 thread->run("GPUFrameCompletion");
870 running = true;
871 }
872 {
873 Mutex::Autolock lock(thread->mMutex);
874 ScopedTrace st(ATRACE_TAG, String8::format("kicked off frame %d",
875 thread->mFramesQueued).string());
876 thread->mQueue.push_back(sync);
877 thread->mCondition.signal();
878 thread->mFramesQueued++;
879 ATRACE_INT("GPU Frames Outstanding", thread->mQueue.size());
880 }
881 }
882
883private:
884 FrameCompletionThread() : mFramesQueued(0), mFramesCompleted(0) {}
885
886 virtual bool threadLoop() {
887 EGLSyncKHR sync;
888 uint32_t frameNum;
889 {
890 Mutex::Autolock lock(mMutex);
891 while (mQueue.isEmpty()) {
892 mCondition.wait(mMutex);
893 }
894 sync = mQueue[0];
895 frameNum = mFramesCompleted;
896 }
897 EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
898 {
899 ScopedTrace st(ATRACE_TAG, String8::format("waiting for frame %d",
900 frameNum).string());
901 EGLint result = eglClientWaitSyncKHR(dpy, sync, 0, EGL_FOREVER_KHR);
902 if (result == EGL_FALSE) {
903 ALOGE("FrameCompletion: error waiting for fence: %#x", eglGetError());
904 } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
905 ALOGE("FrameCompletion: timeout waiting for fence");
906 }
907 eglDestroySyncKHR(dpy, sync);
908 }
909 {
910 Mutex::Autolock lock(mMutex);
911 mQueue.removeAt(0);
912 mFramesCompleted++;
913 ATRACE_INT("GPU Frames Outstanding", mQueue.size());
914 }
915 return true;
916 }
917
918 uint32_t mFramesQueued;
919 uint32_t mFramesCompleted;
920 Vector<EGLSyncKHR> mQueue;
921 Condition mCondition;
922 Mutex mMutex;
923};
924
Mathias Agopian518ec112011-05-13 16:21:08 -0700925EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw)
926{
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800927 ATRACE_CALL();
Mathias Agopian518ec112011-05-13 16:21:08 -0700928 clearError();
929
Jesse Hallb29e5e82012-04-04 16:53:42 -0700930 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700931 if (!dp) return EGL_FALSE;
932
Jesse Hallb29e5e82012-04-04 16:53:42 -0700933 SurfaceRef _s(dp.get(), draw);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700934 if (!_s.get())
935 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700936
Siva Velusamy0469dd62011-11-30 15:05:37 -0800937#if EGL_TRACE
Siva Velusamya73a9772012-12-18 14:56:55 -0800938 gl_hooks_t const *trace_hooks = getGLTraceThreadSpecific();
939 if (getEGLDebugLevel() > 0) {
940 if (trace_hooks == NULL) {
941 if (GLTrace_start() < 0) {
942 ALOGE("Disabling Tracer for OpenGL ES");
943 setEGLDebugLevel(0);
944 } else {
945 // switch over to the trace version of hooks
946 EGLContext ctx = egl_tls_t::getContext();
947 egl_context_t * const c = get_context(ctx);
948 if (c) {
949 setGLHooksThreadSpecific(c->cnx->hooks[c->version]);
950 GLTrace_eglMakeCurrent(c->version, c->cnx->hooks[c->version], ctx);
951 }
952 }
953 }
954
Siva Velusamy0469dd62011-11-30 15:05:37 -0800955 GLTrace_eglSwapBuffers(dpy, draw);
Siva Velusamya73a9772012-12-18 14:56:55 -0800956 } else if (trace_hooks != NULL) {
957 // tracing is now disabled, so switch back to the non trace version
958 EGLContext ctx = egl_tls_t::getContext();
959 egl_context_t * const c = get_context(ctx);
960 if (c) setGLHooksThreadSpecific(c->cnx->hooks[c->version]);
961 GLTrace_stop();
962 }
Siva Velusamy0469dd62011-11-30 15:05:37 -0800963#endif
964
Mathias Agopian518ec112011-05-13 16:21:08 -0700965 egl_surface_t const * const s = get_surface(draw);
Mathias Agopian7db993a2012-03-25 00:49:46 -0700966
967 if (CC_UNLIKELY(dp->finishOnSwap)) {
968 uint32_t pixel;
969 egl_context_t * const c = get_context( egl_tls_t::getContext() );
970 if (c) {
971 // glReadPixels() ensures that the frame is complete
972 s->cnx->hooks[c->version]->gl.glReadPixels(0,0,1,1,
973 GL_RGBA,GL_UNSIGNED_BYTE,&pixel);
974 }
975 }
976
Jamie Gennis28ef8d72012-04-05 20:34:54 -0700977 EGLBoolean result = s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface);
978
979 if (CC_UNLIKELY(dp->traceGpuCompletion)) {
980 EGLSyncKHR sync = EGL_NO_SYNC_KHR;
981 {
982 sync = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, NULL);
983 }
984 if (sync != EGL_NO_SYNC_KHR) {
985 FrameCompletionThread::queueSync(sync);
986 }
987 }
988
989 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -0700990}
991
992EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface,
993 NativePixmapType target)
994{
995 clearError();
996
Jesse Hallb29e5e82012-04-04 16:53:42 -0700997 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700998 if (!dp) return EGL_FALSE;
999
Jesse Hallb29e5e82012-04-04 16:53:42 -07001000 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001001 if (!_s.get())
1002 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001003
Mathias Agopian518ec112011-05-13 16:21:08 -07001004 egl_surface_t const * const s = get_surface(surface);
Mathias Agopianada798b2012-02-13 17:09:30 -08001005 return s->cnx->egl.eglCopyBuffers(dp->disp.dpy, s->surface, target);
Mathias Agopian518ec112011-05-13 16:21:08 -07001006}
1007
1008const char* eglQueryString(EGLDisplay dpy, EGLint name)
1009{
1010 clearError();
1011
Jesse Hallb29e5e82012-04-04 16:53:42 -07001012 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001013 if (!dp) return (const char *) NULL;
1014
1015 switch (name) {
1016 case EGL_VENDOR:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001017 return dp->getVendorString();
Mathias Agopian518ec112011-05-13 16:21:08 -07001018 case EGL_VERSION:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001019 return dp->getVersionString();
Mathias Agopian518ec112011-05-13 16:21:08 -07001020 case EGL_EXTENSIONS:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001021 return dp->getExtensionString();
Mathias Agopian518ec112011-05-13 16:21:08 -07001022 case EGL_CLIENT_APIS:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001023 return dp->getClientApiString();
Mathias Agopianada798b2012-02-13 17:09:30 -08001024 case EGL_VERSION_HW_ANDROID:
1025 return dp->disp.queryString.version;
Mathias Agopian518ec112011-05-13 16:21:08 -07001026 }
1027 return setError(EGL_BAD_PARAMETER, (const char *)0);
1028}
1029
1030
1031// ----------------------------------------------------------------------------
1032// EGL 1.1
1033// ----------------------------------------------------------------------------
1034
1035EGLBoolean eglSurfaceAttrib(
1036 EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
1037{
1038 clearError();
1039
Jesse Hallb29e5e82012-04-04 16:53:42 -07001040 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001041 if (!dp) return EGL_FALSE;
1042
Jesse Hallb29e5e82012-04-04 16:53:42 -07001043 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001044 if (!_s.get())
1045 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001046
Mathias Agopian518ec112011-05-13 16:21:08 -07001047 egl_surface_t const * const s = get_surface(surface);
1048 if (s->cnx->egl.eglSurfaceAttrib) {
1049 return s->cnx->egl.eglSurfaceAttrib(
Mathias Agopianada798b2012-02-13 17:09:30 -08001050 dp->disp.dpy, s->surface, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -07001051 }
1052 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1053}
1054
1055EGLBoolean eglBindTexImage(
1056 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1057{
1058 clearError();
1059
Jesse Hallb29e5e82012-04-04 16:53:42 -07001060 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001061 if (!dp) return EGL_FALSE;
1062
Jesse Hallb29e5e82012-04-04 16:53:42 -07001063 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001064 if (!_s.get())
1065 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001066
Mathias Agopian518ec112011-05-13 16:21:08 -07001067 egl_surface_t const * const s = get_surface(surface);
1068 if (s->cnx->egl.eglBindTexImage) {
1069 return s->cnx->egl.eglBindTexImage(
Mathias Agopianada798b2012-02-13 17:09:30 -08001070 dp->disp.dpy, s->surface, buffer);
Mathias Agopian518ec112011-05-13 16:21:08 -07001071 }
1072 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1073}
1074
1075EGLBoolean eglReleaseTexImage(
1076 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1077{
1078 clearError();
1079
Jesse Hallb29e5e82012-04-04 16:53:42 -07001080 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001081 if (!dp) return EGL_FALSE;
1082
Jesse Hallb29e5e82012-04-04 16:53:42 -07001083 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001084 if (!_s.get())
1085 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001086
Mathias Agopian518ec112011-05-13 16:21:08 -07001087 egl_surface_t const * const s = get_surface(surface);
1088 if (s->cnx->egl.eglReleaseTexImage) {
1089 return s->cnx->egl.eglReleaseTexImage(
Mathias Agopianada798b2012-02-13 17:09:30 -08001090 dp->disp.dpy, s->surface, buffer);
Mathias Agopian518ec112011-05-13 16:21:08 -07001091 }
1092 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1093}
1094
1095EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
1096{
1097 clearError();
1098
Jesse Hallb29e5e82012-04-04 16:53:42 -07001099 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001100 if (!dp) return EGL_FALSE;
1101
1102 EGLBoolean res = EGL_TRUE;
Mathias Agopianada798b2012-02-13 17:09:30 -08001103 egl_connection_t* const cnx = &gEGLImpl;
1104 if (cnx->dso && cnx->egl.eglSwapInterval) {
1105 res = cnx->egl.eglSwapInterval(dp->disp.dpy, interval);
Mathias Agopian518ec112011-05-13 16:21:08 -07001106 }
Mathias Agopianada798b2012-02-13 17:09:30 -08001107
Mathias Agopian518ec112011-05-13 16:21:08 -07001108 return res;
1109}
1110
1111
1112// ----------------------------------------------------------------------------
1113// EGL 1.2
1114// ----------------------------------------------------------------------------
1115
1116EGLBoolean eglWaitClient(void)
1117{
1118 clearError();
1119
Mathias Agopianada798b2012-02-13 17:09:30 -08001120 egl_connection_t* const cnx = &gEGLImpl;
1121 if (!cnx->dso)
1122 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1123
1124 EGLBoolean res;
1125 if (cnx->egl.eglWaitClient) {
1126 res = cnx->egl.eglWaitClient();
1127 } else {
1128 res = cnx->egl.eglWaitGL();
Mathias Agopian518ec112011-05-13 16:21:08 -07001129 }
1130 return res;
1131}
1132
1133EGLBoolean eglBindAPI(EGLenum api)
1134{
1135 clearError();
1136
1137 if (egl_init_drivers() == EGL_FALSE) {
1138 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1139 }
1140
1141 // bind this API on all EGLs
1142 EGLBoolean res = EGL_TRUE;
Mathias Agopianada798b2012-02-13 17:09:30 -08001143 egl_connection_t* const cnx = &gEGLImpl;
1144 if (cnx->dso && cnx->egl.eglBindAPI) {
1145 res = cnx->egl.eglBindAPI(api);
Mathias Agopian518ec112011-05-13 16:21:08 -07001146 }
1147 return res;
1148}
1149
1150EGLenum eglQueryAPI(void)
1151{
1152 clearError();
1153
1154 if (egl_init_drivers() == EGL_FALSE) {
1155 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1156 }
1157
Mathias Agopianada798b2012-02-13 17:09:30 -08001158 egl_connection_t* const cnx = &gEGLImpl;
1159 if (cnx->dso && cnx->egl.eglQueryAPI) {
1160 return cnx->egl.eglQueryAPI();
Mathias Agopian518ec112011-05-13 16:21:08 -07001161 }
Mathias Agopianada798b2012-02-13 17:09:30 -08001162
Mathias Agopian518ec112011-05-13 16:21:08 -07001163 // or, it can only be OpenGL ES
1164 return EGL_OPENGL_ES_API;
1165}
1166
1167EGLBoolean eglReleaseThread(void)
1168{
1169 clearError();
1170
1171 // If there is context bound to the thread, release it
Mathias Agopianfb87e542012-01-30 18:20:52 -08001172 egl_display_t::loseCurrent(get_context(getContext()));
Mathias Agopian518ec112011-05-13 16:21:08 -07001173
Mathias Agopianada798b2012-02-13 17:09:30 -08001174 egl_connection_t* const cnx = &gEGLImpl;
1175 if (cnx->dso && cnx->egl.eglReleaseThread) {
1176 cnx->egl.eglReleaseThread();
Mathias Agopian518ec112011-05-13 16:21:08 -07001177 }
Mathias Agopianada798b2012-02-13 17:09:30 -08001178
Mathias Agopian518ec112011-05-13 16:21:08 -07001179 egl_tls_t::clearTLS();
Siva Velusamy0469dd62011-11-30 15:05:37 -08001180#if EGL_TRACE
Siva Velusamya73a9772012-12-18 14:56:55 -08001181 if (getEGLDebugLevel() > 0)
Siva Velusamy0469dd62011-11-30 15:05:37 -08001182 GLTrace_eglReleaseThread();
1183#endif
Mathias Agopian518ec112011-05-13 16:21:08 -07001184 return EGL_TRUE;
1185}
1186
1187EGLSurface eglCreatePbufferFromClientBuffer(
1188 EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer,
1189 EGLConfig config, const EGLint *attrib_list)
1190{
1191 clearError();
1192
Jesse Hallb29e5e82012-04-04 16:53:42 -07001193 egl_connection_t* cnx = NULL;
1194 const egl_display_ptr dp = validate_display_connection(dpy, cnx);
1195 if (!dp) return EGL_FALSE;
Mathias Agopian518ec112011-05-13 16:21:08 -07001196 if (cnx->egl.eglCreatePbufferFromClientBuffer) {
1197 return cnx->egl.eglCreatePbufferFromClientBuffer(
Mathias Agopian7773c432012-02-13 20:06:08 -08001198 dp->disp.dpy, buftype, buffer, config, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001199 }
1200 return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE);
1201}
1202
1203// ----------------------------------------------------------------------------
1204// EGL_EGLEXT_VERSION 3
1205// ----------------------------------------------------------------------------
1206
1207EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface,
1208 const EGLint *attrib_list)
1209{
1210 clearError();
1211
Jesse Hallb29e5e82012-04-04 16:53:42 -07001212 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001213 if (!dp) return EGL_FALSE;
1214
Jesse Hallb29e5e82012-04-04 16:53:42 -07001215 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001216 if (!_s.get())
1217 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001218
1219 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian518ec112011-05-13 16:21:08 -07001220 if (s->cnx->egl.eglLockSurfaceKHR) {
1221 return s->cnx->egl.eglLockSurfaceKHR(
Mathias Agopianada798b2012-02-13 17:09:30 -08001222 dp->disp.dpy, s->surface, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001223 }
1224 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1225}
1226
1227EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface)
1228{
1229 clearError();
1230
Jesse Hallb29e5e82012-04-04 16:53:42 -07001231 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001232 if (!dp) return EGL_FALSE;
1233
Jesse Hallb29e5e82012-04-04 16:53:42 -07001234 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001235 if (!_s.get())
1236 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001237
1238 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian518ec112011-05-13 16:21:08 -07001239 if (s->cnx->egl.eglUnlockSurfaceKHR) {
Mathias Agopianada798b2012-02-13 17:09:30 -08001240 return s->cnx->egl.eglUnlockSurfaceKHR(dp->disp.dpy, s->surface);
Mathias Agopian518ec112011-05-13 16:21:08 -07001241 }
1242 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1243}
1244
1245EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
1246 EGLClientBuffer buffer, const EGLint *attrib_list)
1247{
1248 clearError();
1249
Jesse Hallb29e5e82012-04-04 16:53:42 -07001250 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001251 if (!dp) return EGL_NO_IMAGE_KHR;
1252
Jesse Hallb29e5e82012-04-04 16:53:42 -07001253 ContextRef _c(dp.get(), ctx);
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001254 egl_context_t * const c = _c.get();
Mathias Agopian518ec112011-05-13 16:21:08 -07001255
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001256 EGLImageKHR result = EGL_NO_IMAGE_KHR;
1257 egl_connection_t* const cnx = &gEGLImpl;
1258 if (cnx->dso && cnx->egl.eglCreateImageKHR) {
1259 result = cnx->egl.eglCreateImageKHR(
1260 dp->disp.dpy,
1261 c ? c->context : EGL_NO_CONTEXT,
1262 target, buffer, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001263 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001264 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001265}
1266
1267EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
1268{
1269 clearError();
1270
Jesse Hallb29e5e82012-04-04 16:53:42 -07001271 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001272 if (!dp) return EGL_FALSE;
1273
Steven Holte646a5c52012-06-04 20:02:11 -07001274 EGLBoolean result = EGL_FALSE;
Mathias Agopianada798b2012-02-13 17:09:30 -08001275 egl_connection_t* const cnx = &gEGLImpl;
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001276 if (cnx->dso && cnx->egl.eglDestroyImageKHR) {
Steven Holte646a5c52012-06-04 20:02:11 -07001277 result = cnx->egl.eglDestroyImageKHR(dp->disp.dpy, img);
Mathias Agopian518ec112011-05-13 16:21:08 -07001278 }
Steven Holte646a5c52012-06-04 20:02:11 -07001279 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001280}
1281
1282// ----------------------------------------------------------------------------
1283// EGL_EGLEXT_VERSION 5
1284// ----------------------------------------------------------------------------
1285
1286
1287EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
1288{
1289 clearError();
1290
Jesse Hallb29e5e82012-04-04 16:53:42 -07001291 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001292 if (!dp) return EGL_NO_SYNC_KHR;
1293
Mathias Agopian518ec112011-05-13 16:21:08 -07001294 EGLSyncKHR result = EGL_NO_SYNC_KHR;
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001295 egl_connection_t* const cnx = &gEGLImpl;
1296 if (cnx->dso && cnx->egl.eglCreateSyncKHR) {
1297 result = cnx->egl.eglCreateSyncKHR(dp->disp.dpy, type, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001298 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001299 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001300}
1301
1302EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
1303{
1304 clearError();
1305
Jesse Hallb29e5e82012-04-04 16:53:42 -07001306 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001307 if (!dp) return EGL_FALSE;
1308
Mathias Agopian518ec112011-05-13 16:21:08 -07001309 EGLBoolean result = EGL_FALSE;
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001310 egl_connection_t* const cnx = &gEGLImpl;
1311 if (cnx->dso && cnx->egl.eglDestroySyncKHR) {
1312 result = cnx->egl.eglDestroySyncKHR(dp->disp.dpy, sync);
Mathias Agopian518ec112011-05-13 16:21:08 -07001313 }
1314 return result;
1315}
1316
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -07001317EGLBoolean eglSignalSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode) {
1318 clearError();
1319
1320 const egl_display_ptr dp = validate_display(dpy);
1321 if (!dp) return EGL_FALSE;
1322
1323 EGLBoolean result = EGL_FALSE;
1324 egl_connection_t* const cnx = &gEGLImpl;
1325 if (cnx->dso && cnx->egl.eglSignalSyncKHR) {
1326 result = cnx->egl.eglSignalSyncKHR(
1327 dp->disp.dpy, sync, mode);
1328 }
1329 return result;
1330}
1331
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001332EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync,
1333 EGLint flags, EGLTimeKHR timeout)
Mathias Agopian518ec112011-05-13 16:21:08 -07001334{
1335 clearError();
1336
Jesse Hallb29e5e82012-04-04 16:53:42 -07001337 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001338 if (!dp) return EGL_FALSE;
1339
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001340 EGLBoolean result = EGL_FALSE;
1341 egl_connection_t* const cnx = &gEGLImpl;
1342 if (cnx->dso && cnx->egl.eglClientWaitSyncKHR) {
1343 result = cnx->egl.eglClientWaitSyncKHR(
1344 dp->disp.dpy, sync, flags, timeout);
Mathias Agopian518ec112011-05-13 16:21:08 -07001345 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001346 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001347}
1348
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001349EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync,
1350 EGLint attribute, EGLint *value)
Mathias Agopian518ec112011-05-13 16:21:08 -07001351{
1352 clearError();
1353
Jesse Hallb29e5e82012-04-04 16:53:42 -07001354 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001355 if (!dp) return EGL_FALSE;
1356
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001357 EGLBoolean result = EGL_FALSE;
1358 egl_connection_t* const cnx = &gEGLImpl;
1359 if (cnx->dso && cnx->egl.eglGetSyncAttribKHR) {
1360 result = cnx->egl.eglGetSyncAttribKHR(
1361 dp->disp.dpy, sync, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -07001362 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001363 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001364}
1365
1366// ----------------------------------------------------------------------------
1367// ANDROID extensions
1368// ----------------------------------------------------------------------------
1369
Jamie Gennis331841b2012-09-06 14:52:00 -07001370EGLint eglDupNativeFenceFDANDROID(EGLDisplay dpy, EGLSyncKHR sync)
1371{
1372 clearError();
1373
1374 const egl_display_ptr dp = validate_display(dpy);
1375 if (!dp) return EGL_NO_NATIVE_FENCE_FD_ANDROID;
1376
1377 EGLint result = EGL_NO_NATIVE_FENCE_FD_ANDROID;
1378 egl_connection_t* const cnx = &gEGLImpl;
1379 if (cnx->dso && cnx->egl.eglDupNativeFenceFDANDROID) {
1380 result = cnx->egl.eglDupNativeFenceFDANDROID(dp->disp.dpy, sync);
1381 }
1382 return result;
1383}
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001384
Jamie Gennis010dd4f2012-09-09 17:46:17 -07001385EGLint eglWaitSyncANDROID(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags)
1386{
1387 clearError();
1388
1389 const egl_display_ptr dp = validate_display(dpy);
1390 if (!dp) return EGL_NO_NATIVE_FENCE_FD_ANDROID;
1391
1392 EGLint result = EGL_FALSE;
1393 egl_connection_t* const cnx = &gEGLImpl;
1394 if (cnx->dso && cnx->egl.eglWaitSyncANDROID) {
1395 result = cnx->egl.eglWaitSyncANDROID(dp->disp.dpy, sync, flags);
1396 }
1397 return result;
1398}
1399
Andy McFadden72841452013-03-01 16:25:32 -08001400EGLBoolean eglPresentationTimeANDROID(EGLDisplay dpy, EGLSurface surface,
1401 EGLnsecsANDROID time)
1402{
1403 clearError();
1404
1405 const egl_display_ptr dp = validate_display(dpy);
1406 if (!dp) {
1407 return EGL_FALSE;
1408 }
1409
1410 SurfaceRef _s(dp.get(), surface);
1411 if (!_s.get()) {
1412 setError(EGL_BAD_SURFACE, EGL_FALSE);
1413 return EGL_FALSE;
1414 }
1415
1416 egl_surface_t const * const s = get_surface(surface);
1417 native_window_set_buffers_timestamp(s->win.get(), time);
1418
1419 return EGL_TRUE;
1420}
1421
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001422// ----------------------------------------------------------------------------
1423// NVIDIA extensions
1424// ----------------------------------------------------------------------------
1425EGLuint64NV eglGetSystemTimeFrequencyNV()
1426{
1427 clearError();
1428
1429 if (egl_init_drivers() == EGL_FALSE) {
1430 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1431 }
1432
1433 EGLuint64NV ret = 0;
Mathias Agopianada798b2012-02-13 17:09:30 -08001434 egl_connection_t* const cnx = &gEGLImpl;
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001435
Mathias Agopianada798b2012-02-13 17:09:30 -08001436 if (cnx->dso && cnx->egl.eglGetSystemTimeFrequencyNV) {
1437 return cnx->egl.eglGetSystemTimeFrequencyNV();
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001438 }
1439
Mathias Agopian0e8bbee2011-10-05 19:15:05 -07001440 return setErrorQuiet(EGL_BAD_DISPLAY, 0);
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001441}
1442
1443EGLuint64NV eglGetSystemTimeNV()
1444{
1445 clearError();
1446
1447 if (egl_init_drivers() == EGL_FALSE) {
1448 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1449 }
1450
1451 EGLuint64NV ret = 0;
Mathias Agopianada798b2012-02-13 17:09:30 -08001452 egl_connection_t* const cnx = &gEGLImpl;
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001453
Mathias Agopianada798b2012-02-13 17:09:30 -08001454 if (cnx->dso && cnx->egl.eglGetSystemTimeNV) {
1455 return cnx->egl.eglGetSystemTimeNV();
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001456 }
1457
Mathias Agopian0e8bbee2011-10-05 19:15:05 -07001458 return setErrorQuiet(EGL_BAD_DISPLAY, 0);
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001459}