blob: e5e2dc05d41a866902799af59369637dc87918ce [file] [log] [blame]
Jesse Hall47743382013-02-08 11:13:46 -08001/*
Mathias Agopian518ec112011-05-13 16:21:08 -07002 ** Copyright 2007, The Android Open Source Project
3 **
Jesse Hall47743382013-02-08 11:13:46 -08004 ** Licensed under the Apache License, Version 2.0 (the "License");
5 ** you may not use this file except in compliance with the License.
6 ** You may obtain a copy of the License at
Mathias Agopian518ec112011-05-13 16:21:08 -07007 **
Jesse Hall47743382013-02-08 11:13:46 -08008 ** http://www.apache.org/licenses/LICENSE-2.0
Mathias Agopian518ec112011-05-13 16:21:08 -07009 **
Jesse Hall47743382013-02-08 11:13:46 -080010 ** Unless required by applicable law or agreed to in writing, software
11 ** distributed under the License is distributed on an "AS IS" BASIS,
12 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 ** See the License for the specific language governing permissions and
Mathias Agopian518ec112011-05-13 16:21:08 -070014 ** limitations under the License.
15 */
16
Jamie Gennis1c8e95c2012-02-23 19:27:23 -080017#define ATRACE_TAG ATRACE_TAG_GRAPHICS
18
Jesse Hallc07b5202013-07-04 12:08:16 -070019#include <dlfcn.h>
Mathias Agopian518ec112011-05-13 16:21:08 -070020#include <ctype.h>
21#include <stdlib.h>
22#include <string.h>
23
24#include <hardware/gralloc.h>
25#include <system/window.h>
26
27#include <EGL/egl.h>
28#include <EGL/eglext.h>
Mathias Agopian518ec112011-05-13 16:21:08 -070029
30#include <cutils/log.h>
31#include <cutils/atomic.h>
Mathias Agopian7db993a2012-03-25 00:49:46 -070032#include <cutils/compiler.h>
Mathias Agopian518ec112011-05-13 16:21:08 -070033#include <cutils/properties.h>
34#include <cutils/memory.h>
35
36#include <utils/KeyedVector.h>
37#include <utils/SortedVector.h>
38#include <utils/String8.h>
Jamie Gennis1c8e95c2012-02-23 19:27:23 -080039#include <utils/Trace.h>
Mathias Agopian518ec112011-05-13 16:21:08 -070040
Mathias Agopian39c24a22013-04-04 23:17:56 -070041#include "../egl_impl.h"
42#include "../glestrace.h"
43#include "../hooks.h"
Mathias Agopian518ec112011-05-13 16:21:08 -070044
45#include "egl_display.h"
Mathias Agopian518ec112011-05-13 16:21:08 -070046#include "egl_object.h"
47#include "egl_tls.h"
Mathias Agopianada798b2012-02-13 17:09:30 -080048#include "egldefs.h"
Mathias Agopian518ec112011-05-13 16:21:08 -070049
50using namespace android;
51
52// ----------------------------------------------------------------------------
53
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070054namespace android {
55
Mathias Agopian518ec112011-05-13 16:21:08 -070056struct extention_map_t {
57 const char* name;
58 __eglMustCastToProperFunctionPointerType address;
59};
60
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070061/*
Jesse Hall21558da2013-08-06 15:31:22 -070062 * This is the list of EGL extensions exposed to applications.
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070063 *
Jesse Hall21558da2013-08-06 15:31:22 -070064 * Some of them (gBuiltinExtensionString) are implemented entirely in this EGL
65 * wrapper and are always available.
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070066 *
Jesse Hall21558da2013-08-06 15:31:22 -070067 * The rest (gExtensionString) depend on support in the EGL driver, and are
68 * only available if the driver supports them. However, some of these must be
69 * supported because they are used by the Android system itself; these are
70 * listd as mandatory below and are required by the CDD. The system *assumes*
71 * the mandatory extensions are present and may not function properly if some
72 * are missing.
73 *
74 * NOTE: Both strings MUST have a single space as the last character.
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070075 */
Jesse Hall21558da2013-08-06 15:31:22 -070076extern char const * const gBuiltinExtensionString =
77 "EGL_KHR_get_all_proc_addresses "
78 "EGL_ANDROID_presentation_time "
79 ;
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070080extern char const * const gExtensionString =
81 "EGL_KHR_image " // mandatory
82 "EGL_KHR_image_base " // mandatory
83 "EGL_KHR_image_pixmap "
84 "EGL_KHR_lock_surface "
85 "EGL_KHR_gl_texture_2D_image "
86 "EGL_KHR_gl_texture_cubemap_image "
87 "EGL_KHR_gl_renderbuffer_image "
88 "EGL_KHR_reusable_sync "
89 "EGL_KHR_fence_sync "
Jamie Gennisf6d1c392013-04-25 18:48:41 -070090 "EGL_KHR_create_context "
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070091 "EGL_EXT_create_context_robustness "
92 "EGL_NV_system_time "
93 "EGL_ANDROID_image_native_buffer " // mandatory
Mathias Agopian2bb71682013-03-27 17:32:41 -070094 "EGL_KHR_wait_sync " // strongly recommended
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070095 ;
96
97// extensions not exposed to applications but used by the ANDROID system
98// "EGL_ANDROID_blob_cache " // strongly recommended
99// "EGL_IMG_hibernate_process " // optional
100// "EGL_ANDROID_native_fence_sync " // strongly recommended
101// "EGL_ANDROID_framebuffer_target " // mandatory for HWC 1.1
102// "EGL_ANDROID_recordable " // mandatory
103
104
105/*
106 * EGL Extensions entry-points exposed to 3rd party applications
107 * (keep in sync with gExtensionString above)
108 *
109 */
110static const extention_map_t sExtensionMap[] = {
111 // EGL_KHR_lock_surface
Mathias Agopian518ec112011-05-13 16:21:08 -0700112 { "eglLockSurfaceKHR",
113 (__eglMustCastToProperFunctionPointerType)&eglLockSurfaceKHR },
114 { "eglUnlockSurfaceKHR",
115 (__eglMustCastToProperFunctionPointerType)&eglUnlockSurfaceKHR },
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700116
117 // EGL_KHR_image, EGL_KHR_image_base
Mathias Agopian518ec112011-05-13 16:21:08 -0700118 { "eglCreateImageKHR",
119 (__eglMustCastToProperFunctionPointerType)&eglCreateImageKHR },
120 { "eglDestroyImageKHR",
121 (__eglMustCastToProperFunctionPointerType)&eglDestroyImageKHR },
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700122
123 // EGL_KHR_reusable_sync, EGL_KHR_fence_sync
124 { "eglCreateSyncKHR",
125 (__eglMustCastToProperFunctionPointerType)&eglCreateSyncKHR },
126 { "eglDestroySyncKHR",
127 (__eglMustCastToProperFunctionPointerType)&eglDestroySyncKHR },
128 { "eglClientWaitSyncKHR",
129 (__eglMustCastToProperFunctionPointerType)&eglClientWaitSyncKHR },
130 { "eglSignalSyncKHR",
131 (__eglMustCastToProperFunctionPointerType)&eglSignalSyncKHR },
132 { "eglGetSyncAttribKHR",
133 (__eglMustCastToProperFunctionPointerType)&eglGetSyncAttribKHR },
134
135 // EGL_NV_system_time
Jonas Yang1c3d72a2011-08-26 20:04:39 +0800136 { "eglGetSystemTimeFrequencyNV",
137 (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeFrequencyNV },
138 { "eglGetSystemTimeNV",
139 (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeNV },
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700140
Mathias Agopian2bb71682013-03-27 17:32:41 -0700141 // EGL_KHR_wait_sync
142 { "eglWaitSyncKHR",
143 (__eglMustCastToProperFunctionPointerType)&eglWaitSyncKHR },
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700144
145 // EGL_ANDROID_presentation_time
146 { "eglPresentationTimeANDROID",
147 (__eglMustCastToProperFunctionPointerType)&eglPresentationTimeANDROID },
Mathias Agopian518ec112011-05-13 16:21:08 -0700148};
149
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700150/*
151 * These extensions entry-points should not be exposed to applications.
152 * They're used internally by the Android EGL layer.
153 */
154#define FILTER_EXTENSIONS(procname) \
155 (!strcmp((procname), "eglSetBlobCacheFuncsANDROID") || \
156 !strcmp((procname), "eglHibernateProcessIMG") || \
157 !strcmp((procname), "eglAwakenProcessIMG") || \
158 !strcmp((procname), "eglDupNativeFenceFDANDROID"))
159
160
161
Mathias Agopian518ec112011-05-13 16:21:08 -0700162// accesses protected by sExtensionMapMutex
163static DefaultKeyedVector<String8, __eglMustCastToProperFunctionPointerType> sGLExtentionMap;
164static int sGLExtentionSlot = 0;
165static pthread_mutex_t sExtensionMapMutex = PTHREAD_MUTEX_INITIALIZER;
166
167static void(*findProcAddress(const char* name,
168 const extention_map_t* map, size_t n))() {
169 for (uint32_t i=0 ; i<n ; i++) {
170 if (!strcmp(name, map[i].name)) {
171 return map[i].address;
172 }
173 }
174 return NULL;
175}
176
177// ----------------------------------------------------------------------------
178
Mathias Agopian518ec112011-05-13 16:21:08 -0700179extern void setGLHooksThreadSpecific(gl_hooks_t const *value);
180extern EGLBoolean egl_init_drivers();
181extern const __eglMustCastToProperFunctionPointerType gExtensionForwarders[MAX_NUMBER_OF_GL_EXTENSIONS];
Siva Velusamya73a9772012-12-18 14:56:55 -0800182extern int getEGLDebugLevel();
183extern void setEGLDebugLevel(int level);
Mathias Agopian518ec112011-05-13 16:21:08 -0700184extern gl_hooks_t gHooksTrace;
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700185
Mathias Agopian518ec112011-05-13 16:21:08 -0700186} // namespace android;
187
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700188
Mathias Agopian518ec112011-05-13 16:21:08 -0700189// ----------------------------------------------------------------------------
190
191static inline void clearError() { egl_tls_t::clearError(); }
192static inline EGLContext getContext() { return egl_tls_t::getContext(); }
193
194// ----------------------------------------------------------------------------
195
196EGLDisplay eglGetDisplay(EGLNativeDisplayType display)
197{
198 clearError();
199
200 uint32_t index = uint32_t(display);
201 if (index >= NUM_DISPLAYS) {
202 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
203 }
204
205 if (egl_init_drivers() == EGL_FALSE) {
206 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
207 }
208
209 EGLDisplay dpy = egl_display_t::getFromNativeDisplay(display);
210 return dpy;
211}
212
213// ----------------------------------------------------------------------------
214// Initialization
215// ----------------------------------------------------------------------------
216
217EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
218{
219 clearError();
220
Jesse Hallb29e5e82012-04-04 16:53:42 -0700221 egl_display_ptr dp = get_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700222 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
223
224 EGLBoolean res = dp->initialize(major, minor);
225
226 return res;
227}
228
229EGLBoolean eglTerminate(EGLDisplay dpy)
230{
231 // NOTE: don't unload the drivers b/c some APIs can be called
232 // after eglTerminate() has been called. eglTerminate() only
233 // terminates an EGLDisplay, not a EGL itself.
234
235 clearError();
236
Jesse Hallb29e5e82012-04-04 16:53:42 -0700237 egl_display_ptr dp = get_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700238 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
239
240 EGLBoolean res = dp->terminate();
Jesse Hall47743382013-02-08 11:13:46 -0800241
Mathias Agopian518ec112011-05-13 16:21:08 -0700242 return res;
243}
244
245// ----------------------------------------------------------------------------
246// configuration
247// ----------------------------------------------------------------------------
248
249EGLBoolean eglGetConfigs( EGLDisplay dpy,
250 EGLConfig *configs,
251 EGLint config_size, EGLint *num_config)
252{
253 clearError();
254
Jesse Hallb29e5e82012-04-04 16:53:42 -0700255 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700256 if (!dp) return EGL_FALSE;
257
Mathias Agopian7773c432012-02-13 20:06:08 -0800258 if (num_config==0) {
259 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700260 }
261
Mathias Agopian7773c432012-02-13 20:06:08 -0800262 EGLBoolean res = EGL_FALSE;
263 *num_config = 0;
264
265 egl_connection_t* const cnx = &gEGLImpl;
266 if (cnx->dso) {
267 res = cnx->egl.eglGetConfigs(
268 dp->disp.dpy, configs, config_size, num_config);
Mathias Agopian518ec112011-05-13 16:21:08 -0700269 }
Mathias Agopian7773c432012-02-13 20:06:08 -0800270
271 return res;
Mathias Agopian518ec112011-05-13 16:21:08 -0700272}
273
274EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list,
275 EGLConfig *configs, EGLint config_size,
276 EGLint *num_config)
277{
278 clearError();
279
Jesse Hallb29e5e82012-04-04 16:53:42 -0700280 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700281 if (!dp) return EGL_FALSE;
282
283 if (num_config==0) {
284 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
285 }
286
Mathias Agopian518ec112011-05-13 16:21:08 -0700287 EGLBoolean res = EGL_FALSE;
288 *num_config = 0;
289
Mathias Agopianada798b2012-02-13 17:09:30 -0800290 egl_connection_t* const cnx = &gEGLImpl;
291 if (cnx->dso) {
Romain Guy1cffc802012-10-15 18:13:05 -0700292 if (attrib_list) {
293 char value[PROPERTY_VALUE_MAX];
294 property_get("debug.egl.force_msaa", value, "false");
295
296 if (!strcmp(value, "true")) {
297 size_t attribCount = 0;
298 EGLint attrib = attrib_list[0];
299
300 // Only enable MSAA if the context is OpenGL ES 2.0 and
Romain Guybe3c3e42012-10-15 19:25:18 -0700301 // if no caveat is requested
Romain Guy1cffc802012-10-15 18:13:05 -0700302 const EGLint *attribRendererable = NULL;
303 const EGLint *attribCaveat = NULL;
304
305 // Count the number of attributes and look for
Romain Guybe3c3e42012-10-15 19:25:18 -0700306 // EGL_RENDERABLE_TYPE and EGL_CONFIG_CAVEAT
Romain Guy1cffc802012-10-15 18:13:05 -0700307 while (attrib != EGL_NONE) {
308 attrib = attrib_list[attribCount];
309 switch (attrib) {
310 case EGL_RENDERABLE_TYPE:
311 attribRendererable = &attrib_list[attribCount];
312 break;
313 case EGL_CONFIG_CAVEAT:
314 attribCaveat = &attrib_list[attribCount];
315 break;
316 }
317 attribCount++;
318 }
319
320 if (attribRendererable && attribRendererable[1] == EGL_OPENGL_ES2_BIT &&
321 (!attribCaveat || attribCaveat[1] != EGL_NONE)) {
Jesse Hall47743382013-02-08 11:13:46 -0800322
Romain Guy1cffc802012-10-15 18:13:05 -0700323 // Insert 2 extra attributes to force-enable MSAA 4x
324 EGLint aaAttribs[attribCount + 4];
325 aaAttribs[0] = EGL_SAMPLE_BUFFERS;
326 aaAttribs[1] = 1;
327 aaAttribs[2] = EGL_SAMPLES;
328 aaAttribs[3] = 4;
329
330 memcpy(&aaAttribs[4], attrib_list, attribCount * sizeof(EGLint));
331
332 EGLint numConfigAA;
333 EGLBoolean resAA = cnx->egl.eglChooseConfig(
334 dp->disp.dpy, aaAttribs, configs, config_size, &numConfigAA);
335
336 if (resAA == EGL_TRUE && numConfigAA > 0) {
337 ALOGD("Enabling MSAA 4x");
338 *num_config = numConfigAA;
339 return resAA;
340 }
341 }
342 }
343 }
344
Mathias Agopian7773c432012-02-13 20:06:08 -0800345 res = cnx->egl.eglChooseConfig(
346 dp->disp.dpy, attrib_list, configs, config_size, num_config);
Mathias Agopian518ec112011-05-13 16:21:08 -0700347 }
348 return res;
349}
350
351EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
352 EGLint attribute, EGLint *value)
353{
354 clearError();
355
Jesse Hallb29e5e82012-04-04 16:53:42 -0700356 egl_connection_t* cnx = NULL;
357 const egl_display_ptr dp = validate_display_connection(dpy, cnx);
358 if (!dp) return EGL_FALSE;
Jesse Hall47743382013-02-08 11:13:46 -0800359
Mathias Agopian518ec112011-05-13 16:21:08 -0700360 return cnx->egl.eglGetConfigAttrib(
Mathias Agopian7773c432012-02-13 20:06:08 -0800361 dp->disp.dpy, config, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -0700362}
363
364// ----------------------------------------------------------------------------
365// surfaces
366// ----------------------------------------------------------------------------
367
368EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config,
369 NativeWindowType window,
370 const EGLint *attrib_list)
371{
372 clearError();
373
Jesse Hallb29e5e82012-04-04 16:53:42 -0700374 egl_connection_t* cnx = NULL;
375 egl_display_ptr dp = validate_display_connection(dpy, cnx);
376 if (dp) {
Mathias Agopianada798b2012-02-13 17:09:30 -0800377 EGLDisplay iDpy = dp->disp.dpy;
Mathias Agopian518ec112011-05-13 16:21:08 -0700378 EGLint format;
379
Mathias Agopian81a63352011-07-29 17:55:48 -0700380 if (native_window_api_connect(window, NATIVE_WINDOW_API_EGL) != OK) {
Steve Blocke6f43dd2012-01-06 19:20:56 +0000381 ALOGE("EGLNativeWindowType %p already connected to another API",
Mathias Agopian81a63352011-07-29 17:55:48 -0700382 window);
Jonathan Hamilton77a9b4a2013-07-17 09:41:42 -0700383 return setError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
Mathias Agopian81a63352011-07-29 17:55:48 -0700384 }
385
Mathias Agopian518ec112011-05-13 16:21:08 -0700386 // set the native window's buffers format to match this config
387 if (cnx->egl.eglGetConfigAttrib(iDpy,
Mathias Agopian7773c432012-02-13 20:06:08 -0800388 config, EGL_NATIVE_VISUAL_ID, &format)) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700389 if (format != 0) {
Jamie Gennisbee205f2011-07-01 13:12:07 -0700390 int err = native_window_set_buffers_format(window, format);
391 if (err != 0) {
Steve Blocke6f43dd2012-01-06 19:20:56 +0000392 ALOGE("error setting native window pixel format: %s (%d)",
Jamie Gennisbee205f2011-07-01 13:12:07 -0700393 strerror(-err), err);
Mathias Agopian81a63352011-07-29 17:55:48 -0700394 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
Jamie Gennisbee205f2011-07-01 13:12:07 -0700395 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
396 }
Mathias Agopian518ec112011-05-13 16:21:08 -0700397 }
398 }
399
Jamie Gennis59769462011-11-19 18:04:43 -0800400 // the EGL spec requires that a new EGLSurface default to swap interval
401 // 1, so explicitly set that on the window here.
402 ANativeWindow* anw = reinterpret_cast<ANativeWindow*>(window);
403 anw->setSwapInterval(anw, 1);
404
Mathias Agopian518ec112011-05-13 16:21:08 -0700405 EGLSurface surface = cnx->egl.eglCreateWindowSurface(
Mathias Agopian7773c432012-02-13 20:06:08 -0800406 iDpy, config, window, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700407 if (surface != EGL_NO_SURFACE) {
Jesse Hallb29e5e82012-04-04 16:53:42 -0700408 egl_surface_t* s = new egl_surface_t(dp.get(), config, window,
409 surface, cnx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700410 return s;
411 }
Mathias Agopian81a63352011-07-29 17:55:48 -0700412
413 // EGLSurface creation failed
414 native_window_set_buffers_format(window, 0);
415 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
Mathias Agopian518ec112011-05-13 16:21:08 -0700416 }
417 return EGL_NO_SURFACE;
418}
419
420EGLSurface eglCreatePixmapSurface( EGLDisplay dpy, EGLConfig config,
421 NativePixmapType pixmap,
422 const EGLint *attrib_list)
423{
424 clearError();
425
Jesse Hallb29e5e82012-04-04 16:53:42 -0700426 egl_connection_t* cnx = NULL;
427 egl_display_ptr dp = validate_display_connection(dpy, cnx);
428 if (dp) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700429 EGLSurface surface = cnx->egl.eglCreatePixmapSurface(
Mathias Agopian7773c432012-02-13 20:06:08 -0800430 dp->disp.dpy, config, pixmap, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700431 if (surface != EGL_NO_SURFACE) {
Jesse Hallb29e5e82012-04-04 16:53:42 -0700432 egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL,
433 surface, cnx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700434 return s;
435 }
436 }
437 return EGL_NO_SURFACE;
438}
439
440EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config,
441 const EGLint *attrib_list)
442{
443 clearError();
444
Jesse Hallb29e5e82012-04-04 16:53:42 -0700445 egl_connection_t* cnx = NULL;
446 egl_display_ptr dp = validate_display_connection(dpy, cnx);
447 if (dp) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700448 EGLSurface surface = cnx->egl.eglCreatePbufferSurface(
Mathias Agopian7773c432012-02-13 20:06:08 -0800449 dp->disp.dpy, config, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700450 if (surface != EGL_NO_SURFACE) {
Jesse Hallb29e5e82012-04-04 16:53:42 -0700451 egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL,
452 surface, cnx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700453 return s;
454 }
455 }
456 return EGL_NO_SURFACE;
457}
Jesse Hall47743382013-02-08 11:13:46 -0800458
Mathias Agopian518ec112011-05-13 16:21:08 -0700459EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
460{
461 clearError();
462
Jesse Hallb29e5e82012-04-04 16:53:42 -0700463 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700464 if (!dp) return EGL_FALSE;
465
Jesse Hallb29e5e82012-04-04 16:53:42 -0700466 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700467 if (!_s.get())
468 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700469
470 egl_surface_t * const s = get_surface(surface);
Mathias Agopianada798b2012-02-13 17:09:30 -0800471 EGLBoolean result = s->cnx->egl.eglDestroySurface(dp->disp.dpy, s->surface);
Mathias Agopian518ec112011-05-13 16:21:08 -0700472 if (result == EGL_TRUE) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700473 _s.terminate();
474 }
475 return result;
476}
477
478EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface surface,
479 EGLint attribute, EGLint *value)
480{
481 clearError();
482
Jesse Hallb29e5e82012-04-04 16:53:42 -0700483 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700484 if (!dp) return EGL_FALSE;
485
Jesse Hallb29e5e82012-04-04 16:53:42 -0700486 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700487 if (!_s.get())
488 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700489
Mathias Agopian518ec112011-05-13 16:21:08 -0700490 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian7773c432012-02-13 20:06:08 -0800491 return s->cnx->egl.eglQuerySurface(
492 dp->disp.dpy, s->surface, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -0700493}
494
Jamie Gennise8696a42012-01-15 18:54:57 -0800495void EGLAPI eglBeginFrame(EGLDisplay dpy, EGLSurface surface) {
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800496 ATRACE_CALL();
Jamie Gennise8696a42012-01-15 18:54:57 -0800497 clearError();
498
Jesse Hallb29e5e82012-04-04 16:53:42 -0700499 const egl_display_ptr dp = validate_display(dpy);
Jamie Gennise8696a42012-01-15 18:54:57 -0800500 if (!dp) {
501 return;
502 }
503
Jesse Hallb29e5e82012-04-04 16:53:42 -0700504 SurfaceRef _s(dp.get(), surface);
Jamie Gennise8696a42012-01-15 18:54:57 -0800505 if (!_s.get()) {
506 setError(EGL_BAD_SURFACE, EGL_FALSE);
507 return;
508 }
Jamie Gennise8696a42012-01-15 18:54:57 -0800509}
510
Mathias Agopian518ec112011-05-13 16:21:08 -0700511// ----------------------------------------------------------------------------
512// Contexts
513// ----------------------------------------------------------------------------
514
515EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config,
516 EGLContext share_list, const EGLint *attrib_list)
517{
518 clearError();
519
Jesse Hallb29e5e82012-04-04 16:53:42 -0700520 egl_connection_t* cnx = NULL;
521 const egl_display_ptr dp = validate_display_connection(dpy, cnx);
Michael Chock0673e1e2012-06-21 12:53:17 -0700522 if (dp) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700523 if (share_list != EGL_NO_CONTEXT) {
Michael Chock0673e1e2012-06-21 12:53:17 -0700524 if (!ContextRef(dp.get(), share_list).get()) {
525 return setError(EGL_BAD_CONTEXT, EGL_NO_CONTEXT);
526 }
Mathias Agopian518ec112011-05-13 16:21:08 -0700527 egl_context_t* const c = get_context(share_list);
528 share_list = c->context;
529 }
530 EGLContext context = cnx->egl.eglCreateContext(
Mathias Agopian7773c432012-02-13 20:06:08 -0800531 dp->disp.dpy, config, share_list, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700532 if (context != EGL_NO_CONTEXT) {
533 // figure out if it's a GLESv1 or GLESv2
534 int version = 0;
535 if (attrib_list) {
536 while (*attrib_list != EGL_NONE) {
537 GLint attr = *attrib_list++;
538 GLint value = *attrib_list++;
539 if (attr == EGL_CONTEXT_CLIENT_VERSION) {
540 if (value == 1) {
Mathias Agopian7773c432012-02-13 20:06:08 -0800541 version = egl_connection_t::GLESv1_INDEX;
Jesse Hall47743382013-02-08 11:13:46 -0800542 } else if (value == 2 || value == 3) {
Mathias Agopian7773c432012-02-13 20:06:08 -0800543 version = egl_connection_t::GLESv2_INDEX;
Mathias Agopian518ec112011-05-13 16:21:08 -0700544 }
545 }
546 };
547 }
Jesse Hallb29e5e82012-04-04 16:53:42 -0700548 egl_context_t* c = new egl_context_t(dpy, context, config, cnx,
549 version);
Siva Velusamy0469dd62011-11-30 15:05:37 -0800550#if EGL_TRACE
Siva Velusamya73a9772012-12-18 14:56:55 -0800551 if (getEGLDebugLevel() > 0)
Siva Velusamy0469dd62011-11-30 15:05:37 -0800552 GLTrace_eglCreateContext(version, c);
553#endif
Mathias Agopian518ec112011-05-13 16:21:08 -0700554 return c;
555 }
556 }
557 return EGL_NO_CONTEXT;
558}
559
560EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
561{
562 clearError();
563
Jesse Hallb29e5e82012-04-04 16:53:42 -0700564 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700565 if (!dp)
566 return EGL_FALSE;
Mathias Agopian518ec112011-05-13 16:21:08 -0700567
Jesse Hallb29e5e82012-04-04 16:53:42 -0700568 ContextRef _c(dp.get(), ctx);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700569 if (!_c.get())
570 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
Jesse Hall47743382013-02-08 11:13:46 -0800571
Mathias Agopian518ec112011-05-13 16:21:08 -0700572 egl_context_t * const c = get_context(ctx);
Mathias Agopianada798b2012-02-13 17:09:30 -0800573 EGLBoolean result = c->cnx->egl.eglDestroyContext(dp->disp.dpy, c->context);
Mathias Agopian518ec112011-05-13 16:21:08 -0700574 if (result == EGL_TRUE) {
575 _c.terminate();
576 }
577 return result;
578}
579
Mathias Agopian518ec112011-05-13 16:21:08 -0700580EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw,
581 EGLSurface read, EGLContext ctx)
582{
583 clearError();
584
Jesse Hallb29e5e82012-04-04 16:53:42 -0700585 egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700586 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
587
Mathias Agopian5b287a62011-05-16 18:58:55 -0700588 // If ctx is not EGL_NO_CONTEXT, read is not EGL_NO_SURFACE, or draw is not
589 // EGL_NO_SURFACE, then an EGL_NOT_INITIALIZED error is generated if dpy is
590 // a valid but uninitialized display.
Mathias Agopian518ec112011-05-13 16:21:08 -0700591 if ( (ctx != EGL_NO_CONTEXT) || (read != EGL_NO_SURFACE) ||
592 (draw != EGL_NO_SURFACE) ) {
593 if (!dp->isReady()) return setError(EGL_NOT_INITIALIZED, EGL_FALSE);
594 }
595
596 // get a reference to the object passed in
Jesse Hallb29e5e82012-04-04 16:53:42 -0700597 ContextRef _c(dp.get(), ctx);
598 SurfaceRef _d(dp.get(), draw);
599 SurfaceRef _r(dp.get(), read);
Mathias Agopian518ec112011-05-13 16:21:08 -0700600
601 // validate the context (if not EGL_NO_CONTEXT)
Mathias Agopian5b287a62011-05-16 18:58:55 -0700602 if ((ctx != EGL_NO_CONTEXT) && !_c.get()) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700603 // EGL_NO_CONTEXT is valid
Michael Chock0673e1e2012-06-21 12:53:17 -0700604 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700605 }
606
607 // these are the underlying implementation's object
608 EGLContext impl_ctx = EGL_NO_CONTEXT;
609 EGLSurface impl_draw = EGL_NO_SURFACE;
610 EGLSurface impl_read = EGL_NO_SURFACE;
611
612 // these are our objects structs passed in
613 egl_context_t * c = NULL;
614 egl_surface_t const * d = NULL;
615 egl_surface_t const * r = NULL;
616
617 // these are the current objects structs
618 egl_context_t * cur_c = get_context(getContext());
Jesse Hall47743382013-02-08 11:13:46 -0800619
Mathias Agopian518ec112011-05-13 16:21:08 -0700620 if (ctx != EGL_NO_CONTEXT) {
621 c = get_context(ctx);
622 impl_ctx = c->context;
623 } else {
624 // no context given, use the implementation of the current context
Michael Chock0673e1e2012-06-21 12:53:17 -0700625 if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE) {
626 // calling eglMakeCurrent( ..., !=0, !=0, EGL_NO_CONTEXT);
627 return setError(EGL_BAD_MATCH, EGL_FALSE);
628 }
Mathias Agopian518ec112011-05-13 16:21:08 -0700629 if (cur_c == NULL) {
630 // no current context
Mathias Agopian518ec112011-05-13 16:21:08 -0700631 // not an error, there is just no current context.
632 return EGL_TRUE;
633 }
634 }
635
636 // retrieve the underlying implementation's draw EGLSurface
637 if (draw != EGL_NO_SURFACE) {
Michael Chock0673e1e2012-06-21 12:53:17 -0700638 if (!_d.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700639 d = get_surface(draw);
Mathias Agopian518ec112011-05-13 16:21:08 -0700640 impl_draw = d->surface;
641 }
642
643 // retrieve the underlying implementation's read EGLSurface
644 if (read != EGL_NO_SURFACE) {
Michael Chock0673e1e2012-06-21 12:53:17 -0700645 if (!_r.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700646 r = get_surface(read);
Mathias Agopian518ec112011-05-13 16:21:08 -0700647 impl_read = r->surface;
648 }
649
Mathias Agopian518ec112011-05-13 16:21:08 -0700650
Jesse Hallb29e5e82012-04-04 16:53:42 -0700651 EGLBoolean result = dp->makeCurrent(c, cur_c,
Mathias Agopianfb87e542012-01-30 18:20:52 -0800652 draw, read, ctx,
653 impl_draw, impl_read, impl_ctx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700654
655 if (result == EGL_TRUE) {
Mathias Agopianfb87e542012-01-30 18:20:52 -0800656 if (c) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700657 setGLHooksThreadSpecific(c->cnx->hooks[c->version]);
658 egl_tls_t::setContext(ctx);
Siva Velusamy0469dd62011-11-30 15:05:37 -0800659#if EGL_TRACE
Siva Velusamya73a9772012-12-18 14:56:55 -0800660 if (getEGLDebugLevel() > 0)
Siva Velusamy93a826f2011-12-14 12:19:56 -0800661 GLTrace_eglMakeCurrent(c->version, c->cnx->hooks[c->version], ctx);
Siva Velusamy0469dd62011-11-30 15:05:37 -0800662#endif
Mathias Agopian518ec112011-05-13 16:21:08 -0700663 _c.acquire();
664 _r.acquire();
665 _d.acquire();
Mathias Agopian518ec112011-05-13 16:21:08 -0700666 } else {
667 setGLHooksThreadSpecific(&gHooksNoContext);
668 egl_tls_t::setContext(EGL_NO_CONTEXT);
669 }
Mathias Agopian5fecea72011-08-25 18:38:24 -0700670 } else {
Steve Blocke6f43dd2012-01-06 19:20:56 +0000671 // this will ALOGE the error
Mathias Agopian5fecea72011-08-25 18:38:24 -0700672 result = setError(c->cnx->egl.eglGetError(), EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700673 }
674 return result;
675}
676
677
678EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx,
679 EGLint attribute, EGLint *value)
680{
681 clearError();
682
Jesse Hallb29e5e82012-04-04 16:53:42 -0700683 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700684 if (!dp) return EGL_FALSE;
685
Jesse Hallb29e5e82012-04-04 16:53:42 -0700686 ContextRef _c(dp.get(), ctx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700687 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
688
Mathias Agopian518ec112011-05-13 16:21:08 -0700689 egl_context_t * const c = get_context(ctx);
Mathias Agopian7773c432012-02-13 20:06:08 -0800690 return c->cnx->egl.eglQueryContext(
691 dp->disp.dpy, c->context, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -0700692
Mathias Agopian518ec112011-05-13 16:21:08 -0700693}
694
695EGLContext eglGetCurrentContext(void)
696{
697 // could be called before eglInitialize(), but we wouldn't have a context
698 // then, and this function would correctly return EGL_NO_CONTEXT.
699
700 clearError();
701
702 EGLContext ctx = getContext();
703 return ctx;
704}
705
706EGLSurface eglGetCurrentSurface(EGLint readdraw)
707{
708 // could be called before eglInitialize(), but we wouldn't have a context
709 // then, and this function would correctly return EGL_NO_SURFACE.
710
711 clearError();
712
713 EGLContext ctx = getContext();
714 if (ctx) {
715 egl_context_t const * const c = get_context(ctx);
716 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
717 switch (readdraw) {
718 case EGL_READ: return c->read;
Jesse Hall47743382013-02-08 11:13:46 -0800719 case EGL_DRAW: return c->draw;
Mathias Agopian518ec112011-05-13 16:21:08 -0700720 default: return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
721 }
722 }
723 return EGL_NO_SURFACE;
724}
725
726EGLDisplay eglGetCurrentDisplay(void)
727{
728 // could be called before eglInitialize(), but we wouldn't have a context
729 // then, and this function would correctly return EGL_NO_DISPLAY.
730
731 clearError();
732
733 EGLContext ctx = getContext();
734 if (ctx) {
735 egl_context_t const * const c = get_context(ctx);
736 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
737 return c->dpy;
738 }
739 return EGL_NO_DISPLAY;
740}
741
742EGLBoolean eglWaitGL(void)
743{
Mathias Agopian518ec112011-05-13 16:21:08 -0700744 clearError();
745
Mathias Agopianada798b2012-02-13 17:09:30 -0800746 egl_connection_t* const cnx = &gEGLImpl;
747 if (!cnx->dso)
748 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
749
750 return cnx->egl.eglWaitGL();
Mathias Agopian518ec112011-05-13 16:21:08 -0700751}
752
753EGLBoolean eglWaitNative(EGLint engine)
754{
Mathias Agopian518ec112011-05-13 16:21:08 -0700755 clearError();
756
Mathias Agopianada798b2012-02-13 17:09:30 -0800757 egl_connection_t* const cnx = &gEGLImpl;
758 if (!cnx->dso)
759 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
760
761 return cnx->egl.eglWaitNative(engine);
Mathias Agopian518ec112011-05-13 16:21:08 -0700762}
763
764EGLint eglGetError(void)
765{
Mathias Agopianada798b2012-02-13 17:09:30 -0800766 EGLint err = EGL_SUCCESS;
767 egl_connection_t* const cnx = &gEGLImpl;
768 if (cnx->dso) {
769 err = cnx->egl.eglGetError();
Mathias Agopian518ec112011-05-13 16:21:08 -0700770 }
Mathias Agopianada798b2012-02-13 17:09:30 -0800771 if (err == EGL_SUCCESS) {
772 err = egl_tls_t::getError();
773 }
774 return err;
Mathias Agopian518ec112011-05-13 16:21:08 -0700775}
776
Jesse Hallc07b5202013-07-04 12:08:16 -0700777static __eglMustCastToProperFunctionPointerType findBuiltinGLWrapper(
778 const char* procname) {
779 const egl_connection_t* cnx = &gEGLImpl;
780 void* proc = NULL;
781
782 proc = dlsym(cnx->libGles2, procname);
783 if (proc) return (__eglMustCastToProperFunctionPointerType)proc;
784
785 proc = dlsym(cnx->libGles1, procname);
786 if (proc) return (__eglMustCastToProperFunctionPointerType)proc;
787
788 return NULL;
789}
790
Mathias Agopian518ec112011-05-13 16:21:08 -0700791__eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
792{
793 // eglGetProcAddress() could be the very first function called
794 // in which case we must make sure we've initialized ourselves, this
795 // happens the first time egl_get_display() is called.
796
797 clearError();
798
799 if (egl_init_drivers() == EGL_FALSE) {
800 setError(EGL_BAD_PARAMETER, NULL);
801 return NULL;
802 }
803
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700804 if (FILTER_EXTENSIONS(procname)) {
Jamie Gennisaca51c02011-11-03 17:42:43 -0700805 return NULL;
806 }
807
Mathias Agopian518ec112011-05-13 16:21:08 -0700808 __eglMustCastToProperFunctionPointerType addr;
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700809 addr = findProcAddress(procname, sExtensionMap, NELEM(sExtensionMap));
Mathias Agopian518ec112011-05-13 16:21:08 -0700810 if (addr) return addr;
811
Jesse Hallc07b5202013-07-04 12:08:16 -0700812 addr = findBuiltinGLWrapper(procname);
813 if (addr) return addr;
Jamie Gennisaca51c02011-11-03 17:42:43 -0700814
Mathias Agopian518ec112011-05-13 16:21:08 -0700815 // this protects accesses to sGLExtentionMap and sGLExtentionSlot
816 pthread_mutex_lock(&sExtensionMapMutex);
817
818 /*
819 * Since eglGetProcAddress() is not associated to anything, it needs
820 * to return a function pointer that "works" regardless of what
821 * the current context is.
822 *
823 * For this reason, we return a "forwarder", a small stub that takes
824 * care of calling the function associated with the context
825 * currently bound.
826 *
827 * We first look for extensions we've already resolved, if we're seeing
828 * this extension for the first time, we go through all our
829 * implementations and call eglGetProcAddress() and record the
830 * result in the appropriate implementation hooks and return the
831 * address of the forwarder corresponding to that hook set.
832 *
833 */
834
835 const String8 name(procname);
836 addr = sGLExtentionMap.valueFor(name);
837 const int slot = sGLExtentionSlot;
838
Steve Blocke6f43dd2012-01-06 19:20:56 +0000839 ALOGE_IF(slot >= MAX_NUMBER_OF_GL_EXTENSIONS,
Mathias Agopian518ec112011-05-13 16:21:08 -0700840 "no more slots for eglGetProcAddress(\"%s\")",
841 procname);
842
Siva Velusamy0469dd62011-11-30 15:05:37 -0800843#if EGL_TRACE
844 gl_hooks_t *debugHooks = GLTrace_getGLHooks();
845#endif
846
Mathias Agopian518ec112011-05-13 16:21:08 -0700847 if (!addr && (slot < MAX_NUMBER_OF_GL_EXTENSIONS)) {
848 bool found = false;
Mathias Agopianada798b2012-02-13 17:09:30 -0800849
850 egl_connection_t* const cnx = &gEGLImpl;
851 if (cnx->dso && cnx->egl.eglGetProcAddress) {
Mathias Agopianada798b2012-02-13 17:09:30 -0800852 // Extensions are independent of the bound context
luliuhui69d10072012-08-30 11:15:36 +0800853 addr =
Mathias Agopian7773c432012-02-13 20:06:08 -0800854 cnx->hooks[egl_connection_t::GLESv1_INDEX]->ext.extensions[slot] =
855 cnx->hooks[egl_connection_t::GLESv2_INDEX]->ext.extensions[slot] =
Mathias Agopian518ec112011-05-13 16:21:08 -0700856#if EGL_TRACE
Mathias Agopianada798b2012-02-13 17:09:30 -0800857 debugHooks->ext.extensions[slot] =
858 gHooksTrace.ext.extensions[slot] =
Mathias Agopian518ec112011-05-13 16:21:08 -0700859#endif
Mathias Agopianada798b2012-02-13 17:09:30 -0800860 cnx->egl.eglGetProcAddress(procname);
luliuhui69d10072012-08-30 11:15:36 +0800861 if (addr) found = true;
Mathias Agopian518ec112011-05-13 16:21:08 -0700862 }
Mathias Agopianada798b2012-02-13 17:09:30 -0800863
Mathias Agopian518ec112011-05-13 16:21:08 -0700864 if (found) {
865 addr = gExtensionForwarders[slot];
Mathias Agopian518ec112011-05-13 16:21:08 -0700866 sGLExtentionMap.add(name, addr);
867 sGLExtentionSlot++;
868 }
869 }
870
871 pthread_mutex_unlock(&sExtensionMapMutex);
872 return addr;
873}
874
Jamie Gennis28ef8d72012-04-05 20:34:54 -0700875class FrameCompletionThread : public Thread {
876public:
877
878 static void queueSync(EGLSyncKHR sync) {
879 static sp<FrameCompletionThread> thread(new FrameCompletionThread);
880 static bool running = false;
881 if (!running) {
882 thread->run("GPUFrameCompletion");
883 running = true;
884 }
885 {
886 Mutex::Autolock lock(thread->mMutex);
887 ScopedTrace st(ATRACE_TAG, String8::format("kicked off frame %d",
888 thread->mFramesQueued).string());
889 thread->mQueue.push_back(sync);
890 thread->mCondition.signal();
891 thread->mFramesQueued++;
892 ATRACE_INT("GPU Frames Outstanding", thread->mQueue.size());
893 }
894 }
895
896private:
897 FrameCompletionThread() : mFramesQueued(0), mFramesCompleted(0) {}
898
899 virtual bool threadLoop() {
900 EGLSyncKHR sync;
901 uint32_t frameNum;
902 {
903 Mutex::Autolock lock(mMutex);
904 while (mQueue.isEmpty()) {
905 mCondition.wait(mMutex);
906 }
907 sync = mQueue[0];
908 frameNum = mFramesCompleted;
909 }
910 EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
911 {
912 ScopedTrace st(ATRACE_TAG, String8::format("waiting for frame %d",
913 frameNum).string());
914 EGLint result = eglClientWaitSyncKHR(dpy, sync, 0, EGL_FOREVER_KHR);
915 if (result == EGL_FALSE) {
916 ALOGE("FrameCompletion: error waiting for fence: %#x", eglGetError());
917 } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
918 ALOGE("FrameCompletion: timeout waiting for fence");
919 }
920 eglDestroySyncKHR(dpy, sync);
921 }
922 {
923 Mutex::Autolock lock(mMutex);
924 mQueue.removeAt(0);
925 mFramesCompleted++;
926 ATRACE_INT("GPU Frames Outstanding", mQueue.size());
927 }
928 return true;
929 }
930
931 uint32_t mFramesQueued;
932 uint32_t mFramesCompleted;
933 Vector<EGLSyncKHR> mQueue;
934 Condition mCondition;
935 Mutex mMutex;
936};
937
Mathias Agopian518ec112011-05-13 16:21:08 -0700938EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw)
939{
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800940 ATRACE_CALL();
Mathias Agopian518ec112011-05-13 16:21:08 -0700941 clearError();
942
Jesse Hallb29e5e82012-04-04 16:53:42 -0700943 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700944 if (!dp) return EGL_FALSE;
945
Jesse Hallb29e5e82012-04-04 16:53:42 -0700946 SurfaceRef _s(dp.get(), draw);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700947 if (!_s.get())
948 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700949
Siva Velusamy0469dd62011-11-30 15:05:37 -0800950#if EGL_TRACE
Siva Velusamya73a9772012-12-18 14:56:55 -0800951 gl_hooks_t const *trace_hooks = getGLTraceThreadSpecific();
952 if (getEGLDebugLevel() > 0) {
953 if (trace_hooks == NULL) {
954 if (GLTrace_start() < 0) {
955 ALOGE("Disabling Tracer for OpenGL ES");
956 setEGLDebugLevel(0);
957 } else {
958 // switch over to the trace version of hooks
959 EGLContext ctx = egl_tls_t::getContext();
960 egl_context_t * const c = get_context(ctx);
961 if (c) {
962 setGLHooksThreadSpecific(c->cnx->hooks[c->version]);
963 GLTrace_eglMakeCurrent(c->version, c->cnx->hooks[c->version], ctx);
964 }
965 }
966 }
967
Siva Velusamy0469dd62011-11-30 15:05:37 -0800968 GLTrace_eglSwapBuffers(dpy, draw);
Siva Velusamya73a9772012-12-18 14:56:55 -0800969 } else if (trace_hooks != NULL) {
970 // tracing is now disabled, so switch back to the non trace version
971 EGLContext ctx = egl_tls_t::getContext();
972 egl_context_t * const c = get_context(ctx);
973 if (c) setGLHooksThreadSpecific(c->cnx->hooks[c->version]);
974 GLTrace_stop();
975 }
Siva Velusamy0469dd62011-11-30 15:05:37 -0800976#endif
977
Mathias Agopian518ec112011-05-13 16:21:08 -0700978 egl_surface_t const * const s = get_surface(draw);
Mathias Agopian7db993a2012-03-25 00:49:46 -0700979
Mathias Agopianed6d08b2013-04-16 16:39:46 -0700980 if (CC_UNLIKELY(dp->traceGpuCompletion)) {
981 EGLSyncKHR sync = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, NULL);
982 if (sync != EGL_NO_SYNC_KHR) {
983 FrameCompletionThread::queueSync(sync);
984 }
985 }
986
Mathias Agopian7db993a2012-03-25 00:49:46 -0700987 if (CC_UNLIKELY(dp->finishOnSwap)) {
988 uint32_t pixel;
989 egl_context_t * const c = get_context( egl_tls_t::getContext() );
990 if (c) {
991 // glReadPixels() ensures that the frame is complete
992 s->cnx->hooks[c->version]->gl.glReadPixels(0,0,1,1,
993 GL_RGBA,GL_UNSIGNED_BYTE,&pixel);
994 }
995 }
996
Mathias Agopianed6d08b2013-04-16 16:39:46 -0700997 return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface);
Mathias Agopian518ec112011-05-13 16:21:08 -0700998}
999
1000EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface,
1001 NativePixmapType target)
1002{
1003 clearError();
1004
Jesse Hallb29e5e82012-04-04 16:53:42 -07001005 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001006 if (!dp) return EGL_FALSE;
1007
Jesse Hallb29e5e82012-04-04 16:53:42 -07001008 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001009 if (!_s.get())
1010 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001011
Mathias Agopian518ec112011-05-13 16:21:08 -07001012 egl_surface_t const * const s = get_surface(surface);
Mathias Agopianada798b2012-02-13 17:09:30 -08001013 return s->cnx->egl.eglCopyBuffers(dp->disp.dpy, s->surface, target);
Mathias Agopian518ec112011-05-13 16:21:08 -07001014}
1015
1016const char* eglQueryString(EGLDisplay dpy, EGLint name)
1017{
1018 clearError();
1019
Jesse Hallb29e5e82012-04-04 16:53:42 -07001020 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001021 if (!dp) return (const char *) NULL;
1022
1023 switch (name) {
1024 case EGL_VENDOR:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001025 return dp->getVendorString();
Mathias Agopian518ec112011-05-13 16:21:08 -07001026 case EGL_VERSION:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001027 return dp->getVersionString();
Mathias Agopian518ec112011-05-13 16:21:08 -07001028 case EGL_EXTENSIONS:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001029 return dp->getExtensionString();
Mathias Agopian518ec112011-05-13 16:21:08 -07001030 case EGL_CLIENT_APIS:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001031 return dp->getClientApiString();
Mathias Agopian518ec112011-05-13 16:21:08 -07001032 }
1033 return setError(EGL_BAD_PARAMETER, (const char *)0);
1034}
1035
Mathias Agopianca088332013-03-28 17:44:13 -07001036EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name)
1037{
1038 clearError();
1039
1040 const egl_display_ptr dp = validate_display(dpy);
1041 if (!dp) return (const char *) NULL;
1042
1043 switch (name) {
1044 case EGL_VENDOR:
1045 return dp->disp.queryString.vendor;
1046 case EGL_VERSION:
1047 return dp->disp.queryString.version;
1048 case EGL_EXTENSIONS:
1049 return dp->disp.queryString.extensions;
1050 case EGL_CLIENT_APIS:
1051 return dp->disp.queryString.clientApi;
1052 }
1053 return setError(EGL_BAD_PARAMETER, (const char *)0);
1054}
Mathias Agopian518ec112011-05-13 16:21:08 -07001055
1056// ----------------------------------------------------------------------------
1057// EGL 1.1
1058// ----------------------------------------------------------------------------
1059
1060EGLBoolean eglSurfaceAttrib(
1061 EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
1062{
1063 clearError();
1064
Jesse Hallb29e5e82012-04-04 16:53:42 -07001065 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001066 if (!dp) return EGL_FALSE;
1067
Jesse Hallb29e5e82012-04-04 16:53:42 -07001068 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001069 if (!_s.get())
1070 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001071
Mathias Agopian518ec112011-05-13 16:21:08 -07001072 egl_surface_t const * const s = get_surface(surface);
1073 if (s->cnx->egl.eglSurfaceAttrib) {
1074 return s->cnx->egl.eglSurfaceAttrib(
Mathias Agopianada798b2012-02-13 17:09:30 -08001075 dp->disp.dpy, s->surface, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -07001076 }
1077 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1078}
1079
1080EGLBoolean eglBindTexImage(
1081 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1082{
1083 clearError();
1084
Jesse Hallb29e5e82012-04-04 16:53:42 -07001085 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001086 if (!dp) return EGL_FALSE;
1087
Jesse Hallb29e5e82012-04-04 16:53:42 -07001088 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001089 if (!_s.get())
1090 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001091
Mathias Agopian518ec112011-05-13 16:21:08 -07001092 egl_surface_t const * const s = get_surface(surface);
1093 if (s->cnx->egl.eglBindTexImage) {
1094 return s->cnx->egl.eglBindTexImage(
Mathias Agopianada798b2012-02-13 17:09:30 -08001095 dp->disp.dpy, s->surface, buffer);
Mathias Agopian518ec112011-05-13 16:21:08 -07001096 }
1097 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1098}
1099
1100EGLBoolean eglReleaseTexImage(
1101 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1102{
1103 clearError();
1104
Jesse Hallb29e5e82012-04-04 16:53:42 -07001105 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001106 if (!dp) return EGL_FALSE;
1107
Jesse Hallb29e5e82012-04-04 16:53:42 -07001108 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001109 if (!_s.get())
1110 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001111
Mathias Agopian518ec112011-05-13 16:21:08 -07001112 egl_surface_t const * const s = get_surface(surface);
1113 if (s->cnx->egl.eglReleaseTexImage) {
1114 return s->cnx->egl.eglReleaseTexImage(
Mathias Agopianada798b2012-02-13 17:09:30 -08001115 dp->disp.dpy, s->surface, buffer);
Mathias Agopian518ec112011-05-13 16:21:08 -07001116 }
1117 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1118}
1119
1120EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
1121{
1122 clearError();
1123
Jesse Hallb29e5e82012-04-04 16:53:42 -07001124 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001125 if (!dp) return EGL_FALSE;
1126
1127 EGLBoolean res = EGL_TRUE;
Mathias Agopianada798b2012-02-13 17:09:30 -08001128 egl_connection_t* const cnx = &gEGLImpl;
1129 if (cnx->dso && cnx->egl.eglSwapInterval) {
1130 res = cnx->egl.eglSwapInterval(dp->disp.dpy, interval);
Mathias Agopian518ec112011-05-13 16:21:08 -07001131 }
Mathias Agopianada798b2012-02-13 17:09:30 -08001132
Mathias Agopian518ec112011-05-13 16:21:08 -07001133 return res;
1134}
1135
1136
1137// ----------------------------------------------------------------------------
1138// EGL 1.2
1139// ----------------------------------------------------------------------------
1140
1141EGLBoolean eglWaitClient(void)
1142{
1143 clearError();
1144
Mathias Agopianada798b2012-02-13 17:09:30 -08001145 egl_connection_t* const cnx = &gEGLImpl;
1146 if (!cnx->dso)
1147 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1148
1149 EGLBoolean res;
1150 if (cnx->egl.eglWaitClient) {
1151 res = cnx->egl.eglWaitClient();
1152 } else {
1153 res = cnx->egl.eglWaitGL();
Mathias Agopian518ec112011-05-13 16:21:08 -07001154 }
1155 return res;
1156}
1157
1158EGLBoolean eglBindAPI(EGLenum api)
1159{
1160 clearError();
1161
1162 if (egl_init_drivers() == EGL_FALSE) {
1163 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1164 }
1165
1166 // bind this API on all EGLs
1167 EGLBoolean res = EGL_TRUE;
Mathias Agopianada798b2012-02-13 17:09:30 -08001168 egl_connection_t* const cnx = &gEGLImpl;
1169 if (cnx->dso && cnx->egl.eglBindAPI) {
1170 res = cnx->egl.eglBindAPI(api);
Mathias Agopian518ec112011-05-13 16:21:08 -07001171 }
1172 return res;
1173}
1174
1175EGLenum eglQueryAPI(void)
1176{
1177 clearError();
1178
1179 if (egl_init_drivers() == EGL_FALSE) {
1180 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1181 }
1182
Mathias Agopianada798b2012-02-13 17:09:30 -08001183 egl_connection_t* const cnx = &gEGLImpl;
1184 if (cnx->dso && cnx->egl.eglQueryAPI) {
1185 return cnx->egl.eglQueryAPI();
Mathias Agopian518ec112011-05-13 16:21:08 -07001186 }
Mathias Agopianada798b2012-02-13 17:09:30 -08001187
Mathias Agopian518ec112011-05-13 16:21:08 -07001188 // or, it can only be OpenGL ES
1189 return EGL_OPENGL_ES_API;
1190}
1191
1192EGLBoolean eglReleaseThread(void)
1193{
1194 clearError();
1195
Mathias Agopian4e620dd2013-05-30 16:07:36 -07001196#if EGL_TRACE
1197 if (getEGLDebugLevel() > 0)
1198 GLTrace_eglReleaseThread();
1199#endif
1200
Mathias Agopian518ec112011-05-13 16:21:08 -07001201 // If there is context bound to the thread, release it
Mathias Agopianfb87e542012-01-30 18:20:52 -08001202 egl_display_t::loseCurrent(get_context(getContext()));
Mathias Agopian518ec112011-05-13 16:21:08 -07001203
Mathias Agopianada798b2012-02-13 17:09:30 -08001204 egl_connection_t* const cnx = &gEGLImpl;
1205 if (cnx->dso && cnx->egl.eglReleaseThread) {
1206 cnx->egl.eglReleaseThread();
Mathias Agopian518ec112011-05-13 16:21:08 -07001207 }
1208 egl_tls_t::clearTLS();
Mathias Agopian518ec112011-05-13 16:21:08 -07001209 return EGL_TRUE;
1210}
1211
1212EGLSurface eglCreatePbufferFromClientBuffer(
1213 EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer,
1214 EGLConfig config, const EGLint *attrib_list)
1215{
1216 clearError();
1217
Jesse Hallb29e5e82012-04-04 16:53:42 -07001218 egl_connection_t* cnx = NULL;
1219 const egl_display_ptr dp = validate_display_connection(dpy, cnx);
1220 if (!dp) return EGL_FALSE;
Mathias Agopian518ec112011-05-13 16:21:08 -07001221 if (cnx->egl.eglCreatePbufferFromClientBuffer) {
1222 return cnx->egl.eglCreatePbufferFromClientBuffer(
Mathias Agopian7773c432012-02-13 20:06:08 -08001223 dp->disp.dpy, buftype, buffer, config, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001224 }
1225 return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE);
1226}
1227
1228// ----------------------------------------------------------------------------
1229// EGL_EGLEXT_VERSION 3
1230// ----------------------------------------------------------------------------
1231
1232EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface,
1233 const EGLint *attrib_list)
1234{
1235 clearError();
1236
Jesse Hallb29e5e82012-04-04 16:53:42 -07001237 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001238 if (!dp) return EGL_FALSE;
1239
Jesse Hallb29e5e82012-04-04 16:53:42 -07001240 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001241 if (!_s.get())
1242 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001243
1244 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian518ec112011-05-13 16:21:08 -07001245 if (s->cnx->egl.eglLockSurfaceKHR) {
1246 return s->cnx->egl.eglLockSurfaceKHR(
Mathias Agopianada798b2012-02-13 17:09:30 -08001247 dp->disp.dpy, s->surface, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001248 }
1249 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1250}
1251
1252EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface)
1253{
1254 clearError();
1255
Jesse Hallb29e5e82012-04-04 16:53:42 -07001256 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001257 if (!dp) return EGL_FALSE;
1258
Jesse Hallb29e5e82012-04-04 16:53:42 -07001259 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001260 if (!_s.get())
1261 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001262
1263 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian518ec112011-05-13 16:21:08 -07001264 if (s->cnx->egl.eglUnlockSurfaceKHR) {
Mathias Agopianada798b2012-02-13 17:09:30 -08001265 return s->cnx->egl.eglUnlockSurfaceKHR(dp->disp.dpy, s->surface);
Mathias Agopian518ec112011-05-13 16:21:08 -07001266 }
1267 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1268}
1269
1270EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
1271 EGLClientBuffer buffer, const EGLint *attrib_list)
1272{
1273 clearError();
1274
Jesse Hallb29e5e82012-04-04 16:53:42 -07001275 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001276 if (!dp) return EGL_NO_IMAGE_KHR;
1277
Jesse Hallb29e5e82012-04-04 16:53:42 -07001278 ContextRef _c(dp.get(), ctx);
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001279 egl_context_t * const c = _c.get();
Mathias Agopian518ec112011-05-13 16:21:08 -07001280
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001281 EGLImageKHR result = EGL_NO_IMAGE_KHR;
1282 egl_connection_t* const cnx = &gEGLImpl;
1283 if (cnx->dso && cnx->egl.eglCreateImageKHR) {
1284 result = cnx->egl.eglCreateImageKHR(
1285 dp->disp.dpy,
1286 c ? c->context : EGL_NO_CONTEXT,
1287 target, buffer, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001288 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001289 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001290}
1291
1292EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
1293{
1294 clearError();
1295
Jesse Hallb29e5e82012-04-04 16:53:42 -07001296 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001297 if (!dp) return EGL_FALSE;
1298
Steven Holte646a5c52012-06-04 20:02:11 -07001299 EGLBoolean result = EGL_FALSE;
Mathias Agopianada798b2012-02-13 17:09:30 -08001300 egl_connection_t* const cnx = &gEGLImpl;
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001301 if (cnx->dso && cnx->egl.eglDestroyImageKHR) {
Steven Holte646a5c52012-06-04 20:02:11 -07001302 result = cnx->egl.eglDestroyImageKHR(dp->disp.dpy, img);
Mathias Agopian518ec112011-05-13 16:21:08 -07001303 }
Steven Holte646a5c52012-06-04 20:02:11 -07001304 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001305}
1306
1307// ----------------------------------------------------------------------------
1308// EGL_EGLEXT_VERSION 5
1309// ----------------------------------------------------------------------------
1310
1311
1312EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
1313{
1314 clearError();
1315
Jesse Hallb29e5e82012-04-04 16:53:42 -07001316 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001317 if (!dp) return EGL_NO_SYNC_KHR;
1318
Mathias Agopian518ec112011-05-13 16:21:08 -07001319 EGLSyncKHR result = EGL_NO_SYNC_KHR;
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001320 egl_connection_t* const cnx = &gEGLImpl;
1321 if (cnx->dso && cnx->egl.eglCreateSyncKHR) {
1322 result = cnx->egl.eglCreateSyncKHR(dp->disp.dpy, type, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001323 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001324 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001325}
1326
1327EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
1328{
1329 clearError();
1330
Jesse Hallb29e5e82012-04-04 16:53:42 -07001331 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001332 if (!dp) return EGL_FALSE;
1333
Mathias Agopian518ec112011-05-13 16:21:08 -07001334 EGLBoolean result = EGL_FALSE;
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001335 egl_connection_t* const cnx = &gEGLImpl;
1336 if (cnx->dso && cnx->egl.eglDestroySyncKHR) {
1337 result = cnx->egl.eglDestroySyncKHR(dp->disp.dpy, sync);
Mathias Agopian518ec112011-05-13 16:21:08 -07001338 }
1339 return result;
1340}
1341
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -07001342EGLBoolean eglSignalSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode) {
1343 clearError();
1344
1345 const egl_display_ptr dp = validate_display(dpy);
1346 if (!dp) return EGL_FALSE;
1347
1348 EGLBoolean result = EGL_FALSE;
1349 egl_connection_t* const cnx = &gEGLImpl;
1350 if (cnx->dso && cnx->egl.eglSignalSyncKHR) {
1351 result = cnx->egl.eglSignalSyncKHR(
1352 dp->disp.dpy, sync, mode);
1353 }
1354 return result;
1355}
1356
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001357EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync,
1358 EGLint flags, EGLTimeKHR timeout)
Mathias Agopian518ec112011-05-13 16:21:08 -07001359{
1360 clearError();
1361
Jesse Hallb29e5e82012-04-04 16:53:42 -07001362 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001363 if (!dp) return EGL_FALSE;
1364
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001365 EGLBoolean result = EGL_FALSE;
1366 egl_connection_t* const cnx = &gEGLImpl;
1367 if (cnx->dso && cnx->egl.eglClientWaitSyncKHR) {
1368 result = cnx->egl.eglClientWaitSyncKHR(
1369 dp->disp.dpy, sync, flags, timeout);
Mathias Agopian518ec112011-05-13 16:21:08 -07001370 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001371 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001372}
1373
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001374EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync,
1375 EGLint attribute, EGLint *value)
Mathias Agopian518ec112011-05-13 16:21:08 -07001376{
1377 clearError();
1378
Jesse Hallb29e5e82012-04-04 16:53:42 -07001379 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001380 if (!dp) return EGL_FALSE;
1381
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001382 EGLBoolean result = EGL_FALSE;
1383 egl_connection_t* const cnx = &gEGLImpl;
1384 if (cnx->dso && cnx->egl.eglGetSyncAttribKHR) {
1385 result = cnx->egl.eglGetSyncAttribKHR(
1386 dp->disp.dpy, sync, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -07001387 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001388 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001389}
1390
1391// ----------------------------------------------------------------------------
Mathias Agopian2bb71682013-03-27 17:32:41 -07001392// EGL_EGLEXT_VERSION 15
1393// ----------------------------------------------------------------------------
1394
1395EGLint eglWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags) {
1396 clearError();
1397 const egl_display_ptr dp = validate_display(dpy);
1398 if (!dp) return EGL_FALSE;
1399 EGLint result = EGL_FALSE;
1400 egl_connection_t* const cnx = &gEGLImpl;
1401 if (cnx->dso && cnx->egl.eglWaitSyncKHR) {
1402 result = cnx->egl.eglWaitSyncKHR(dp->disp.dpy, sync, flags);
1403 }
1404 return result;
1405}
1406
1407// ----------------------------------------------------------------------------
Mathias Agopian518ec112011-05-13 16:21:08 -07001408// ANDROID extensions
1409// ----------------------------------------------------------------------------
1410
Jamie Gennis331841b2012-09-06 14:52:00 -07001411EGLint eglDupNativeFenceFDANDROID(EGLDisplay dpy, EGLSyncKHR sync)
1412{
1413 clearError();
1414
1415 const egl_display_ptr dp = validate_display(dpy);
1416 if (!dp) return EGL_NO_NATIVE_FENCE_FD_ANDROID;
1417
1418 EGLint result = EGL_NO_NATIVE_FENCE_FD_ANDROID;
1419 egl_connection_t* const cnx = &gEGLImpl;
1420 if (cnx->dso && cnx->egl.eglDupNativeFenceFDANDROID) {
1421 result = cnx->egl.eglDupNativeFenceFDANDROID(dp->disp.dpy, sync);
1422 }
1423 return result;
1424}
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001425
Andy McFadden72841452013-03-01 16:25:32 -08001426EGLBoolean eglPresentationTimeANDROID(EGLDisplay dpy, EGLSurface surface,
1427 EGLnsecsANDROID time)
1428{
1429 clearError();
1430
1431 const egl_display_ptr dp = validate_display(dpy);
1432 if (!dp) {
1433 return EGL_FALSE;
1434 }
1435
1436 SurfaceRef _s(dp.get(), surface);
1437 if (!_s.get()) {
1438 setError(EGL_BAD_SURFACE, EGL_FALSE);
1439 return EGL_FALSE;
1440 }
1441
1442 egl_surface_t const * const s = get_surface(surface);
1443 native_window_set_buffers_timestamp(s->win.get(), time);
1444
1445 return EGL_TRUE;
1446}
1447
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001448// ----------------------------------------------------------------------------
1449// NVIDIA extensions
1450// ----------------------------------------------------------------------------
1451EGLuint64NV eglGetSystemTimeFrequencyNV()
1452{
1453 clearError();
1454
1455 if (egl_init_drivers() == EGL_FALSE) {
1456 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1457 }
1458
1459 EGLuint64NV ret = 0;
Mathias Agopianada798b2012-02-13 17:09:30 -08001460 egl_connection_t* const cnx = &gEGLImpl;
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001461
Mathias Agopianada798b2012-02-13 17:09:30 -08001462 if (cnx->dso && cnx->egl.eglGetSystemTimeFrequencyNV) {
1463 return cnx->egl.eglGetSystemTimeFrequencyNV();
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001464 }
1465
Mathias Agopian0e8bbee2011-10-05 19:15:05 -07001466 return setErrorQuiet(EGL_BAD_DISPLAY, 0);
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001467}
1468
1469EGLuint64NV eglGetSystemTimeNV()
1470{
1471 clearError();
1472
1473 if (egl_init_drivers() == EGL_FALSE) {
1474 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1475 }
1476
1477 EGLuint64NV ret = 0;
Mathias Agopianada798b2012-02-13 17:09:30 -08001478 egl_connection_t* const cnx = &gEGLImpl;
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001479
Mathias Agopianada798b2012-02-13 17:09:30 -08001480 if (cnx->dso && cnx->egl.eglGetSystemTimeNV) {
1481 return cnx->egl.eglGetSystemTimeNV();
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001482 }
1483
Mathias Agopian0e8bbee2011-10-05 19:15:05 -07001484 return setErrorQuiet(EGL_BAD_DISPLAY, 0);
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001485}