blob: a81c450277a51159f58911d6da8bc92076b7788d [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 "
Jesse Hallc2e41222013-08-08 13:40:22 -070085 "EGL_KHR_gl_colorspace "
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070086 "EGL_KHR_gl_texture_2D_image "
87 "EGL_KHR_gl_texture_cubemap_image "
88 "EGL_KHR_gl_renderbuffer_image "
89 "EGL_KHR_reusable_sync "
90 "EGL_KHR_fence_sync "
Jamie Gennisf6d1c392013-04-25 18:48:41 -070091 "EGL_KHR_create_context "
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070092 "EGL_EXT_create_context_robustness "
93 "EGL_NV_system_time "
94 "EGL_ANDROID_image_native_buffer " // mandatory
Mathias Agopian2bb71682013-03-27 17:32:41 -070095 "EGL_KHR_wait_sync " // strongly recommended
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070096 ;
97
98// extensions not exposed to applications but used by the ANDROID system
99// "EGL_ANDROID_blob_cache " // strongly recommended
100// "EGL_IMG_hibernate_process " // optional
101// "EGL_ANDROID_native_fence_sync " // strongly recommended
102// "EGL_ANDROID_framebuffer_target " // mandatory for HWC 1.1
103// "EGL_ANDROID_recordable " // mandatory
104
105
106/*
107 * EGL Extensions entry-points exposed to 3rd party applications
108 * (keep in sync with gExtensionString above)
109 *
110 */
111static const extention_map_t sExtensionMap[] = {
112 // EGL_KHR_lock_surface
Mathias Agopian518ec112011-05-13 16:21:08 -0700113 { "eglLockSurfaceKHR",
114 (__eglMustCastToProperFunctionPointerType)&eglLockSurfaceKHR },
115 { "eglUnlockSurfaceKHR",
116 (__eglMustCastToProperFunctionPointerType)&eglUnlockSurfaceKHR },
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700117
118 // EGL_KHR_image, EGL_KHR_image_base
Mathias Agopian518ec112011-05-13 16:21:08 -0700119 { "eglCreateImageKHR",
120 (__eglMustCastToProperFunctionPointerType)&eglCreateImageKHR },
121 { "eglDestroyImageKHR",
122 (__eglMustCastToProperFunctionPointerType)&eglDestroyImageKHR },
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700123
124 // EGL_KHR_reusable_sync, EGL_KHR_fence_sync
125 { "eglCreateSyncKHR",
126 (__eglMustCastToProperFunctionPointerType)&eglCreateSyncKHR },
127 { "eglDestroySyncKHR",
128 (__eglMustCastToProperFunctionPointerType)&eglDestroySyncKHR },
129 { "eglClientWaitSyncKHR",
130 (__eglMustCastToProperFunctionPointerType)&eglClientWaitSyncKHR },
131 { "eglSignalSyncKHR",
132 (__eglMustCastToProperFunctionPointerType)&eglSignalSyncKHR },
133 { "eglGetSyncAttribKHR",
134 (__eglMustCastToProperFunctionPointerType)&eglGetSyncAttribKHR },
135
136 // EGL_NV_system_time
Jonas Yang1c3d72a2011-08-26 20:04:39 +0800137 { "eglGetSystemTimeFrequencyNV",
138 (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeFrequencyNV },
139 { "eglGetSystemTimeNV",
140 (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeNV },
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700141
Mathias Agopian2bb71682013-03-27 17:32:41 -0700142 // EGL_KHR_wait_sync
143 { "eglWaitSyncKHR",
144 (__eglMustCastToProperFunctionPointerType)&eglWaitSyncKHR },
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700145
146 // EGL_ANDROID_presentation_time
147 { "eglPresentationTimeANDROID",
148 (__eglMustCastToProperFunctionPointerType)&eglPresentationTimeANDROID },
Mathias Agopian518ec112011-05-13 16:21:08 -0700149};
150
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700151/*
152 * These extensions entry-points should not be exposed to applications.
153 * They're used internally by the Android EGL layer.
154 */
155#define FILTER_EXTENSIONS(procname) \
156 (!strcmp((procname), "eglSetBlobCacheFuncsANDROID") || \
157 !strcmp((procname), "eglHibernateProcessIMG") || \
158 !strcmp((procname), "eglAwakenProcessIMG") || \
159 !strcmp((procname), "eglDupNativeFenceFDANDROID"))
160
161
162
Mathias Agopian518ec112011-05-13 16:21:08 -0700163// accesses protected by sExtensionMapMutex
164static DefaultKeyedVector<String8, __eglMustCastToProperFunctionPointerType> sGLExtentionMap;
165static int sGLExtentionSlot = 0;
166static pthread_mutex_t sExtensionMapMutex = PTHREAD_MUTEX_INITIALIZER;
167
168static void(*findProcAddress(const char* name,
169 const extention_map_t* map, size_t n))() {
170 for (uint32_t i=0 ; i<n ; i++) {
171 if (!strcmp(name, map[i].name)) {
172 return map[i].address;
173 }
174 }
175 return NULL;
176}
177
178// ----------------------------------------------------------------------------
179
Mathias Agopian518ec112011-05-13 16:21:08 -0700180extern void setGLHooksThreadSpecific(gl_hooks_t const *value);
181extern EGLBoolean egl_init_drivers();
182extern const __eglMustCastToProperFunctionPointerType gExtensionForwarders[MAX_NUMBER_OF_GL_EXTENSIONS];
Siva Velusamya73a9772012-12-18 14:56:55 -0800183extern int getEGLDebugLevel();
184extern void setEGLDebugLevel(int level);
Mathias Agopian518ec112011-05-13 16:21:08 -0700185extern gl_hooks_t gHooksTrace;
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700186
Mathias Agopian518ec112011-05-13 16:21:08 -0700187} // namespace android;
188
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700189
Mathias Agopian518ec112011-05-13 16:21:08 -0700190// ----------------------------------------------------------------------------
191
192static inline void clearError() { egl_tls_t::clearError(); }
193static inline EGLContext getContext() { return egl_tls_t::getContext(); }
194
195// ----------------------------------------------------------------------------
196
197EGLDisplay eglGetDisplay(EGLNativeDisplayType display)
198{
199 clearError();
200
201 uint32_t index = uint32_t(display);
202 if (index >= NUM_DISPLAYS) {
203 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
204 }
205
206 if (egl_init_drivers() == EGL_FALSE) {
207 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
208 }
209
210 EGLDisplay dpy = egl_display_t::getFromNativeDisplay(display);
211 return dpy;
212}
213
214// ----------------------------------------------------------------------------
215// Initialization
216// ----------------------------------------------------------------------------
217
218EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
219{
220 clearError();
221
Jesse Hallb29e5e82012-04-04 16:53:42 -0700222 egl_display_ptr dp = get_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700223 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
224
225 EGLBoolean res = dp->initialize(major, minor);
226
227 return res;
228}
229
230EGLBoolean eglTerminate(EGLDisplay dpy)
231{
232 // NOTE: don't unload the drivers b/c some APIs can be called
233 // after eglTerminate() has been called. eglTerminate() only
234 // terminates an EGLDisplay, not a EGL itself.
235
236 clearError();
237
Jesse Hallb29e5e82012-04-04 16:53:42 -0700238 egl_display_ptr dp = get_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700239 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
240
241 EGLBoolean res = dp->terminate();
Jesse Hall47743382013-02-08 11:13:46 -0800242
Mathias Agopian518ec112011-05-13 16:21:08 -0700243 return res;
244}
245
246// ----------------------------------------------------------------------------
247// configuration
248// ----------------------------------------------------------------------------
249
250EGLBoolean eglGetConfigs( EGLDisplay dpy,
251 EGLConfig *configs,
252 EGLint config_size, EGLint *num_config)
253{
254 clearError();
255
Jesse Hallb29e5e82012-04-04 16:53:42 -0700256 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700257 if (!dp) return EGL_FALSE;
258
Mathias Agopian7773c432012-02-13 20:06:08 -0800259 if (num_config==0) {
260 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700261 }
262
Mathias Agopian7773c432012-02-13 20:06:08 -0800263 EGLBoolean res = EGL_FALSE;
264 *num_config = 0;
265
266 egl_connection_t* const cnx = &gEGLImpl;
267 if (cnx->dso) {
268 res = cnx->egl.eglGetConfigs(
269 dp->disp.dpy, configs, config_size, num_config);
Mathias Agopian518ec112011-05-13 16:21:08 -0700270 }
Mathias Agopian7773c432012-02-13 20:06:08 -0800271
272 return res;
Mathias Agopian518ec112011-05-13 16:21:08 -0700273}
274
275EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list,
276 EGLConfig *configs, EGLint config_size,
277 EGLint *num_config)
278{
279 clearError();
280
Jesse Hallb29e5e82012-04-04 16:53:42 -0700281 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700282 if (!dp) return EGL_FALSE;
283
284 if (num_config==0) {
285 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
286 }
287
Mathias Agopian518ec112011-05-13 16:21:08 -0700288 EGLBoolean res = EGL_FALSE;
289 *num_config = 0;
290
Mathias Agopianada798b2012-02-13 17:09:30 -0800291 egl_connection_t* const cnx = &gEGLImpl;
292 if (cnx->dso) {
Romain Guy1cffc802012-10-15 18:13:05 -0700293 if (attrib_list) {
294 char value[PROPERTY_VALUE_MAX];
295 property_get("debug.egl.force_msaa", value, "false");
296
297 if (!strcmp(value, "true")) {
298 size_t attribCount = 0;
299 EGLint attrib = attrib_list[0];
300
301 // Only enable MSAA if the context is OpenGL ES 2.0 and
Romain Guybe3c3e42012-10-15 19:25:18 -0700302 // if no caveat is requested
Romain Guy1cffc802012-10-15 18:13:05 -0700303 const EGLint *attribRendererable = NULL;
304 const EGLint *attribCaveat = NULL;
305
306 // Count the number of attributes and look for
Romain Guybe3c3e42012-10-15 19:25:18 -0700307 // EGL_RENDERABLE_TYPE and EGL_CONFIG_CAVEAT
Romain Guy1cffc802012-10-15 18:13:05 -0700308 while (attrib != EGL_NONE) {
309 attrib = attrib_list[attribCount];
310 switch (attrib) {
311 case EGL_RENDERABLE_TYPE:
312 attribRendererable = &attrib_list[attribCount];
313 break;
314 case EGL_CONFIG_CAVEAT:
315 attribCaveat = &attrib_list[attribCount];
316 break;
317 }
318 attribCount++;
319 }
320
321 if (attribRendererable && attribRendererable[1] == EGL_OPENGL_ES2_BIT &&
322 (!attribCaveat || attribCaveat[1] != EGL_NONE)) {
Jesse Hall47743382013-02-08 11:13:46 -0800323
Romain Guy1cffc802012-10-15 18:13:05 -0700324 // Insert 2 extra attributes to force-enable MSAA 4x
325 EGLint aaAttribs[attribCount + 4];
326 aaAttribs[0] = EGL_SAMPLE_BUFFERS;
327 aaAttribs[1] = 1;
328 aaAttribs[2] = EGL_SAMPLES;
329 aaAttribs[3] = 4;
330
331 memcpy(&aaAttribs[4], attrib_list, attribCount * sizeof(EGLint));
332
333 EGLint numConfigAA;
334 EGLBoolean resAA = cnx->egl.eglChooseConfig(
335 dp->disp.dpy, aaAttribs, configs, config_size, &numConfigAA);
336
337 if (resAA == EGL_TRUE && numConfigAA > 0) {
338 ALOGD("Enabling MSAA 4x");
339 *num_config = numConfigAA;
340 return resAA;
341 }
342 }
343 }
344 }
345
Mathias Agopian7773c432012-02-13 20:06:08 -0800346 res = cnx->egl.eglChooseConfig(
347 dp->disp.dpy, attrib_list, configs, config_size, num_config);
Mathias Agopian518ec112011-05-13 16:21:08 -0700348 }
349 return res;
350}
351
352EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
353 EGLint attribute, EGLint *value)
354{
355 clearError();
356
Jesse Hallb29e5e82012-04-04 16:53:42 -0700357 egl_connection_t* cnx = NULL;
358 const egl_display_ptr dp = validate_display_connection(dpy, cnx);
359 if (!dp) return EGL_FALSE;
Jesse Hall47743382013-02-08 11:13:46 -0800360
Mathias Agopian518ec112011-05-13 16:21:08 -0700361 return cnx->egl.eglGetConfigAttrib(
Mathias Agopian7773c432012-02-13 20:06:08 -0800362 dp->disp.dpy, config, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -0700363}
364
365// ----------------------------------------------------------------------------
366// surfaces
367// ----------------------------------------------------------------------------
368
Jesse Hallc2e41222013-08-08 13:40:22 -0700369// The EGL_KHR_gl_colorspace spec hasn't been published yet, so these haven't
370// been added to the Khronos egl.h.
371#define EGL_GL_COLORSPACE_KHR EGL_VG_COLORSPACE
372#define EGL_GL_COLORSPACE_SRGB_KHR EGL_VG_COLORSPACE_sRGB
373#define EGL_GL_COLORSPACE_LINEAR_KHR EGL_VG_COLORSPACE_LINEAR
374
375// Turn linear formats into corresponding sRGB formats when colorspace is
376// EGL_GL_COLORSPACE_SRGB_KHR, or turn sRGB formats into corresponding linear
377// formats when colorspace is EGL_GL_COLORSPACE_LINEAR_KHR. In any cases where
378// the modification isn't possible, the original format is returned.
379static int modifyFormatColorspace(int fmt, EGLint colorspace) {
380 if (colorspace == EGL_GL_COLORSPACE_LINEAR_KHR) {
381 switch (fmt) {
382 case HAL_PIXEL_FORMAT_sRGB_A_8888: return HAL_PIXEL_FORMAT_RGBA_8888;
Jesse Hallbc2a90b2013-08-16 07:50:11 -0700383 case HAL_PIXEL_FORMAT_sRGB_X_8888: return HAL_PIXEL_FORMAT_RGBX_8888;
Jesse Hallc2e41222013-08-08 13:40:22 -0700384 }
385 } else if (colorspace == EGL_GL_COLORSPACE_SRGB_KHR) {
386 switch (fmt) {
387 case HAL_PIXEL_FORMAT_RGBA_8888: return HAL_PIXEL_FORMAT_sRGB_A_8888;
Jesse Hallbc2a90b2013-08-16 07:50:11 -0700388 case HAL_PIXEL_FORMAT_RGBX_8888: return HAL_PIXEL_FORMAT_sRGB_X_8888;
389 // TODO: this should go away once drivers stop using BGRA EGLConfigs
Jesse Hallc2e41222013-08-08 13:40:22 -0700390 case HAL_PIXEL_FORMAT_BGRA_8888: return HAL_PIXEL_FORMAT_sRGB_A_8888;
Jesse Hallc2e41222013-08-08 13:40:22 -0700391 }
392 }
393 return fmt;
394}
395
Mathias Agopian518ec112011-05-13 16:21:08 -0700396EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config,
397 NativeWindowType window,
398 const EGLint *attrib_list)
399{
400 clearError();
401
Jesse Hallb29e5e82012-04-04 16:53:42 -0700402 egl_connection_t* cnx = NULL;
403 egl_display_ptr dp = validate_display_connection(dpy, cnx);
404 if (dp) {
Mathias Agopianada798b2012-02-13 17:09:30 -0800405 EGLDisplay iDpy = dp->disp.dpy;
Mathias Agopian518ec112011-05-13 16:21:08 -0700406
Mathias Agopian81a63352011-07-29 17:55:48 -0700407 if (native_window_api_connect(window, NATIVE_WINDOW_API_EGL) != OK) {
Steve Blocke6f43dd2012-01-06 19:20:56 +0000408 ALOGE("EGLNativeWindowType %p already connected to another API",
Mathias Agopian81a63352011-07-29 17:55:48 -0700409 window);
Jonathan Hamilton77a9b4a2013-07-17 09:41:42 -0700410 return setError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
Mathias Agopian81a63352011-07-29 17:55:48 -0700411 }
412
Jesse Hallc2e41222013-08-08 13:40:22 -0700413 // Set the native window's buffers format to match this config.
414 // Whether to use sRGB gamma is not part of the EGLconfig, but is part
415 // of our native format. So if sRGB gamma is requested, we have to
416 // modify the EGLconfig's format before setting the native window's
417 // format.
418 EGLint format;
419 if (!cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_NATIVE_VISUAL_ID,
420 &format)) {
421 ALOGE("eglGetConfigAttrib(EGL_NATIVE_VISUAL_ID) failed: %#x",
422 eglGetError());
423 format = 0;
424 }
425 if (attrib_list) {
426 for (const EGLint* attr = attrib_list; *attr != EGL_NONE;
427 attr += 2) {
428 if (*attr == EGL_GL_COLORSPACE_KHR &&
429 dp->haveExtension("EGL_KHR_gl_colorspace")) {
430 format = modifyFormatColorspace(format, *(attr+1));
Jamie Gennisbee205f2011-07-01 13:12:07 -0700431 }
Mathias Agopian518ec112011-05-13 16:21:08 -0700432 }
433 }
Jesse Hallc2e41222013-08-08 13:40:22 -0700434 if (format != 0) {
435 int err = native_window_set_buffers_format(window, format);
436 if (err != 0) {
437 ALOGE("error setting native window pixel format: %s (%d)",
438 strerror(-err), err);
439 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
440 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
441 }
442 }
Mathias Agopian518ec112011-05-13 16:21:08 -0700443
Jamie Gennis59769462011-11-19 18:04:43 -0800444 // the EGL spec requires that a new EGLSurface default to swap interval
445 // 1, so explicitly set that on the window here.
446 ANativeWindow* anw = reinterpret_cast<ANativeWindow*>(window);
447 anw->setSwapInterval(anw, 1);
448
Mathias Agopian518ec112011-05-13 16:21:08 -0700449 EGLSurface surface = cnx->egl.eglCreateWindowSurface(
Mathias Agopian7773c432012-02-13 20:06:08 -0800450 iDpy, config, window, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700451 if (surface != EGL_NO_SURFACE) {
Jesse Hallb29e5e82012-04-04 16:53:42 -0700452 egl_surface_t* s = new egl_surface_t(dp.get(), config, window,
453 surface, cnx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700454 return s;
455 }
Mathias Agopian81a63352011-07-29 17:55:48 -0700456
457 // EGLSurface creation failed
458 native_window_set_buffers_format(window, 0);
459 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
Mathias Agopian518ec112011-05-13 16:21:08 -0700460 }
461 return EGL_NO_SURFACE;
462}
463
464EGLSurface eglCreatePixmapSurface( EGLDisplay dpy, EGLConfig config,
465 NativePixmapType pixmap,
466 const EGLint *attrib_list)
467{
468 clearError();
469
Jesse Hallb29e5e82012-04-04 16:53:42 -0700470 egl_connection_t* cnx = NULL;
471 egl_display_ptr dp = validate_display_connection(dpy, cnx);
472 if (dp) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700473 EGLSurface surface = cnx->egl.eglCreatePixmapSurface(
Mathias Agopian7773c432012-02-13 20:06:08 -0800474 dp->disp.dpy, config, pixmap, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700475 if (surface != EGL_NO_SURFACE) {
Jesse Hallb29e5e82012-04-04 16:53:42 -0700476 egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL,
477 surface, cnx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700478 return s;
479 }
480 }
481 return EGL_NO_SURFACE;
482}
483
484EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config,
485 const EGLint *attrib_list)
486{
487 clearError();
488
Jesse Hallb29e5e82012-04-04 16:53:42 -0700489 egl_connection_t* cnx = NULL;
490 egl_display_ptr dp = validate_display_connection(dpy, cnx);
491 if (dp) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700492 EGLSurface surface = cnx->egl.eglCreatePbufferSurface(
Mathias Agopian7773c432012-02-13 20:06:08 -0800493 dp->disp.dpy, config, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700494 if (surface != EGL_NO_SURFACE) {
Jesse Hallb29e5e82012-04-04 16:53:42 -0700495 egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL,
496 surface, cnx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700497 return s;
498 }
499 }
500 return EGL_NO_SURFACE;
501}
Jesse Hall47743382013-02-08 11:13:46 -0800502
Mathias Agopian518ec112011-05-13 16:21:08 -0700503EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
504{
505 clearError();
506
Jesse Hallb29e5e82012-04-04 16:53:42 -0700507 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700508 if (!dp) return EGL_FALSE;
509
Jesse Hallb29e5e82012-04-04 16:53:42 -0700510 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700511 if (!_s.get())
512 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700513
514 egl_surface_t * const s = get_surface(surface);
Mathias Agopianada798b2012-02-13 17:09:30 -0800515 EGLBoolean result = s->cnx->egl.eglDestroySurface(dp->disp.dpy, s->surface);
Mathias Agopian518ec112011-05-13 16:21:08 -0700516 if (result == EGL_TRUE) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700517 _s.terminate();
518 }
519 return result;
520}
521
522EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface surface,
523 EGLint attribute, EGLint *value)
524{
525 clearError();
526
Jesse Hallb29e5e82012-04-04 16:53:42 -0700527 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700528 if (!dp) return EGL_FALSE;
529
Jesse Hallb29e5e82012-04-04 16:53:42 -0700530 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700531 if (!_s.get())
532 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700533
Mathias Agopian518ec112011-05-13 16:21:08 -0700534 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian7773c432012-02-13 20:06:08 -0800535 return s->cnx->egl.eglQuerySurface(
536 dp->disp.dpy, s->surface, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -0700537}
538
Jamie Gennise8696a42012-01-15 18:54:57 -0800539void EGLAPI eglBeginFrame(EGLDisplay dpy, EGLSurface surface) {
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800540 ATRACE_CALL();
Jamie Gennise8696a42012-01-15 18:54:57 -0800541 clearError();
542
Jesse Hallb29e5e82012-04-04 16:53:42 -0700543 const egl_display_ptr dp = validate_display(dpy);
Jamie Gennise8696a42012-01-15 18:54:57 -0800544 if (!dp) {
545 return;
546 }
547
Jesse Hallb29e5e82012-04-04 16:53:42 -0700548 SurfaceRef _s(dp.get(), surface);
Jamie Gennise8696a42012-01-15 18:54:57 -0800549 if (!_s.get()) {
550 setError(EGL_BAD_SURFACE, EGL_FALSE);
551 return;
552 }
Jamie Gennise8696a42012-01-15 18:54:57 -0800553}
554
Mathias Agopian518ec112011-05-13 16:21:08 -0700555// ----------------------------------------------------------------------------
556// Contexts
557// ----------------------------------------------------------------------------
558
559EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config,
560 EGLContext share_list, const EGLint *attrib_list)
561{
562 clearError();
563
Jesse Hallb29e5e82012-04-04 16:53:42 -0700564 egl_connection_t* cnx = NULL;
565 const egl_display_ptr dp = validate_display_connection(dpy, cnx);
Michael Chock0673e1e2012-06-21 12:53:17 -0700566 if (dp) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700567 if (share_list != EGL_NO_CONTEXT) {
Michael Chock0673e1e2012-06-21 12:53:17 -0700568 if (!ContextRef(dp.get(), share_list).get()) {
569 return setError(EGL_BAD_CONTEXT, EGL_NO_CONTEXT);
570 }
Mathias Agopian518ec112011-05-13 16:21:08 -0700571 egl_context_t* const c = get_context(share_list);
572 share_list = c->context;
573 }
574 EGLContext context = cnx->egl.eglCreateContext(
Mathias Agopian7773c432012-02-13 20:06:08 -0800575 dp->disp.dpy, config, share_list, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700576 if (context != EGL_NO_CONTEXT) {
577 // figure out if it's a GLESv1 or GLESv2
578 int version = 0;
579 if (attrib_list) {
580 while (*attrib_list != EGL_NONE) {
581 GLint attr = *attrib_list++;
582 GLint value = *attrib_list++;
583 if (attr == EGL_CONTEXT_CLIENT_VERSION) {
584 if (value == 1) {
Mathias Agopian7773c432012-02-13 20:06:08 -0800585 version = egl_connection_t::GLESv1_INDEX;
Jesse Hall47743382013-02-08 11:13:46 -0800586 } else if (value == 2 || value == 3) {
Mathias Agopian7773c432012-02-13 20:06:08 -0800587 version = egl_connection_t::GLESv2_INDEX;
Mathias Agopian518ec112011-05-13 16:21:08 -0700588 }
589 }
590 };
591 }
Jesse Hallb29e5e82012-04-04 16:53:42 -0700592 egl_context_t* c = new egl_context_t(dpy, context, config, cnx,
593 version);
Siva Velusamy0469dd62011-11-30 15:05:37 -0800594#if EGL_TRACE
Siva Velusamya73a9772012-12-18 14:56:55 -0800595 if (getEGLDebugLevel() > 0)
Siva Velusamy0469dd62011-11-30 15:05:37 -0800596 GLTrace_eglCreateContext(version, c);
597#endif
Mathias Agopian518ec112011-05-13 16:21:08 -0700598 return c;
599 }
600 }
601 return EGL_NO_CONTEXT;
602}
603
604EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
605{
606 clearError();
607
Jesse Hallb29e5e82012-04-04 16:53:42 -0700608 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700609 if (!dp)
610 return EGL_FALSE;
Mathias Agopian518ec112011-05-13 16:21:08 -0700611
Jesse Hallb29e5e82012-04-04 16:53:42 -0700612 ContextRef _c(dp.get(), ctx);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700613 if (!_c.get())
614 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
Jesse Hall47743382013-02-08 11:13:46 -0800615
Mathias Agopian518ec112011-05-13 16:21:08 -0700616 egl_context_t * const c = get_context(ctx);
Mathias Agopianada798b2012-02-13 17:09:30 -0800617 EGLBoolean result = c->cnx->egl.eglDestroyContext(dp->disp.dpy, c->context);
Mathias Agopian518ec112011-05-13 16:21:08 -0700618 if (result == EGL_TRUE) {
619 _c.terminate();
620 }
621 return result;
622}
623
Mathias Agopian518ec112011-05-13 16:21:08 -0700624EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw,
625 EGLSurface read, EGLContext ctx)
626{
627 clearError();
628
Jesse Hallb29e5e82012-04-04 16:53:42 -0700629 egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700630 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
631
Mathias Agopian5b287a62011-05-16 18:58:55 -0700632 // If ctx is not EGL_NO_CONTEXT, read is not EGL_NO_SURFACE, or draw is not
633 // EGL_NO_SURFACE, then an EGL_NOT_INITIALIZED error is generated if dpy is
634 // a valid but uninitialized display.
Mathias Agopian518ec112011-05-13 16:21:08 -0700635 if ( (ctx != EGL_NO_CONTEXT) || (read != EGL_NO_SURFACE) ||
636 (draw != EGL_NO_SURFACE) ) {
637 if (!dp->isReady()) return setError(EGL_NOT_INITIALIZED, EGL_FALSE);
638 }
639
640 // get a reference to the object passed in
Jesse Hallb29e5e82012-04-04 16:53:42 -0700641 ContextRef _c(dp.get(), ctx);
642 SurfaceRef _d(dp.get(), draw);
643 SurfaceRef _r(dp.get(), read);
Mathias Agopian518ec112011-05-13 16:21:08 -0700644
645 // validate the context (if not EGL_NO_CONTEXT)
Mathias Agopian5b287a62011-05-16 18:58:55 -0700646 if ((ctx != EGL_NO_CONTEXT) && !_c.get()) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700647 // EGL_NO_CONTEXT is valid
Michael Chock0673e1e2012-06-21 12:53:17 -0700648 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700649 }
650
651 // these are the underlying implementation's object
652 EGLContext impl_ctx = EGL_NO_CONTEXT;
653 EGLSurface impl_draw = EGL_NO_SURFACE;
654 EGLSurface impl_read = EGL_NO_SURFACE;
655
656 // these are our objects structs passed in
657 egl_context_t * c = NULL;
658 egl_surface_t const * d = NULL;
659 egl_surface_t const * r = NULL;
660
661 // these are the current objects structs
662 egl_context_t * cur_c = get_context(getContext());
Jesse Hall47743382013-02-08 11:13:46 -0800663
Mathias Agopian518ec112011-05-13 16:21:08 -0700664 if (ctx != EGL_NO_CONTEXT) {
665 c = get_context(ctx);
666 impl_ctx = c->context;
667 } else {
668 // no context given, use the implementation of the current context
Michael Chock0673e1e2012-06-21 12:53:17 -0700669 if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE) {
670 // calling eglMakeCurrent( ..., !=0, !=0, EGL_NO_CONTEXT);
671 return setError(EGL_BAD_MATCH, EGL_FALSE);
672 }
Mathias Agopian518ec112011-05-13 16:21:08 -0700673 if (cur_c == NULL) {
674 // no current context
Mathias Agopian518ec112011-05-13 16:21:08 -0700675 // not an error, there is just no current context.
676 return EGL_TRUE;
677 }
678 }
679
680 // retrieve the underlying implementation's draw EGLSurface
681 if (draw != EGL_NO_SURFACE) {
Michael Chock0673e1e2012-06-21 12:53:17 -0700682 if (!_d.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700683 d = get_surface(draw);
Mathias Agopian518ec112011-05-13 16:21:08 -0700684 impl_draw = d->surface;
685 }
686
687 // retrieve the underlying implementation's read EGLSurface
688 if (read != EGL_NO_SURFACE) {
Michael Chock0673e1e2012-06-21 12:53:17 -0700689 if (!_r.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700690 r = get_surface(read);
Mathias Agopian518ec112011-05-13 16:21:08 -0700691 impl_read = r->surface;
692 }
693
Mathias Agopian518ec112011-05-13 16:21:08 -0700694
Jesse Hallb29e5e82012-04-04 16:53:42 -0700695 EGLBoolean result = dp->makeCurrent(c, cur_c,
Mathias Agopianfb87e542012-01-30 18:20:52 -0800696 draw, read, ctx,
697 impl_draw, impl_read, impl_ctx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700698
699 if (result == EGL_TRUE) {
Mathias Agopianfb87e542012-01-30 18:20:52 -0800700 if (c) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700701 setGLHooksThreadSpecific(c->cnx->hooks[c->version]);
702 egl_tls_t::setContext(ctx);
Siva Velusamy0469dd62011-11-30 15:05:37 -0800703#if EGL_TRACE
Siva Velusamya73a9772012-12-18 14:56:55 -0800704 if (getEGLDebugLevel() > 0)
Siva Velusamy93a826f2011-12-14 12:19:56 -0800705 GLTrace_eglMakeCurrent(c->version, c->cnx->hooks[c->version], ctx);
Siva Velusamy0469dd62011-11-30 15:05:37 -0800706#endif
Mathias Agopian518ec112011-05-13 16:21:08 -0700707 _c.acquire();
708 _r.acquire();
709 _d.acquire();
Mathias Agopian518ec112011-05-13 16:21:08 -0700710 } else {
711 setGLHooksThreadSpecific(&gHooksNoContext);
712 egl_tls_t::setContext(EGL_NO_CONTEXT);
713 }
Mathias Agopian5fecea72011-08-25 18:38:24 -0700714 } else {
Steve Blocke6f43dd2012-01-06 19:20:56 +0000715 // this will ALOGE the error
Mathias Agopian5fecea72011-08-25 18:38:24 -0700716 result = setError(c->cnx->egl.eglGetError(), EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700717 }
718 return result;
719}
720
721
722EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx,
723 EGLint attribute, EGLint *value)
724{
725 clearError();
726
Jesse Hallb29e5e82012-04-04 16:53:42 -0700727 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700728 if (!dp) return EGL_FALSE;
729
Jesse Hallb29e5e82012-04-04 16:53:42 -0700730 ContextRef _c(dp.get(), ctx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700731 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
732
Mathias Agopian518ec112011-05-13 16:21:08 -0700733 egl_context_t * const c = get_context(ctx);
Mathias Agopian7773c432012-02-13 20:06:08 -0800734 return c->cnx->egl.eglQueryContext(
735 dp->disp.dpy, c->context, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -0700736
Mathias Agopian518ec112011-05-13 16:21:08 -0700737}
738
739EGLContext eglGetCurrentContext(void)
740{
741 // could be called before eglInitialize(), but we wouldn't have a context
742 // then, and this function would correctly return EGL_NO_CONTEXT.
743
744 clearError();
745
746 EGLContext ctx = getContext();
747 return ctx;
748}
749
750EGLSurface eglGetCurrentSurface(EGLint readdraw)
751{
752 // could be called before eglInitialize(), but we wouldn't have a context
753 // then, and this function would correctly return EGL_NO_SURFACE.
754
755 clearError();
756
757 EGLContext ctx = getContext();
758 if (ctx) {
759 egl_context_t const * const c = get_context(ctx);
760 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
761 switch (readdraw) {
762 case EGL_READ: return c->read;
Jesse Hall47743382013-02-08 11:13:46 -0800763 case EGL_DRAW: return c->draw;
Mathias Agopian518ec112011-05-13 16:21:08 -0700764 default: return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
765 }
766 }
767 return EGL_NO_SURFACE;
768}
769
770EGLDisplay eglGetCurrentDisplay(void)
771{
772 // could be called before eglInitialize(), but we wouldn't have a context
773 // then, and this function would correctly return EGL_NO_DISPLAY.
774
775 clearError();
776
777 EGLContext ctx = getContext();
778 if (ctx) {
779 egl_context_t const * const c = get_context(ctx);
780 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
781 return c->dpy;
782 }
783 return EGL_NO_DISPLAY;
784}
785
786EGLBoolean eglWaitGL(void)
787{
Mathias Agopian518ec112011-05-13 16:21:08 -0700788 clearError();
789
Mathias Agopianada798b2012-02-13 17:09:30 -0800790 egl_connection_t* const cnx = &gEGLImpl;
791 if (!cnx->dso)
792 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
793
794 return cnx->egl.eglWaitGL();
Mathias Agopian518ec112011-05-13 16:21:08 -0700795}
796
797EGLBoolean eglWaitNative(EGLint engine)
798{
Mathias Agopian518ec112011-05-13 16:21:08 -0700799 clearError();
800
Mathias Agopianada798b2012-02-13 17:09:30 -0800801 egl_connection_t* const cnx = &gEGLImpl;
802 if (!cnx->dso)
803 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
804
805 return cnx->egl.eglWaitNative(engine);
Mathias Agopian518ec112011-05-13 16:21:08 -0700806}
807
808EGLint eglGetError(void)
809{
Mathias Agopianada798b2012-02-13 17:09:30 -0800810 EGLint err = EGL_SUCCESS;
811 egl_connection_t* const cnx = &gEGLImpl;
812 if (cnx->dso) {
813 err = cnx->egl.eglGetError();
Mathias Agopian518ec112011-05-13 16:21:08 -0700814 }
Mathias Agopianada798b2012-02-13 17:09:30 -0800815 if (err == EGL_SUCCESS) {
816 err = egl_tls_t::getError();
817 }
818 return err;
Mathias Agopian518ec112011-05-13 16:21:08 -0700819}
820
Jesse Hallc07b5202013-07-04 12:08:16 -0700821static __eglMustCastToProperFunctionPointerType findBuiltinGLWrapper(
822 const char* procname) {
823 const egl_connection_t* cnx = &gEGLImpl;
824 void* proc = NULL;
825
826 proc = dlsym(cnx->libGles2, procname);
827 if (proc) return (__eglMustCastToProperFunctionPointerType)proc;
828
829 proc = dlsym(cnx->libGles1, procname);
830 if (proc) return (__eglMustCastToProperFunctionPointerType)proc;
831
832 return NULL;
833}
834
Mathias Agopian518ec112011-05-13 16:21:08 -0700835__eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
836{
837 // eglGetProcAddress() could be the very first function called
838 // in which case we must make sure we've initialized ourselves, this
839 // happens the first time egl_get_display() is called.
840
841 clearError();
842
843 if (egl_init_drivers() == EGL_FALSE) {
844 setError(EGL_BAD_PARAMETER, NULL);
845 return NULL;
846 }
847
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700848 if (FILTER_EXTENSIONS(procname)) {
Jamie Gennisaca51c02011-11-03 17:42:43 -0700849 return NULL;
850 }
851
Mathias Agopian518ec112011-05-13 16:21:08 -0700852 __eglMustCastToProperFunctionPointerType addr;
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700853 addr = findProcAddress(procname, sExtensionMap, NELEM(sExtensionMap));
Mathias Agopian518ec112011-05-13 16:21:08 -0700854 if (addr) return addr;
855
Jesse Hallc07b5202013-07-04 12:08:16 -0700856 addr = findBuiltinGLWrapper(procname);
857 if (addr) return addr;
Jamie Gennisaca51c02011-11-03 17:42:43 -0700858
Mathias Agopian518ec112011-05-13 16:21:08 -0700859 // this protects accesses to sGLExtentionMap and sGLExtentionSlot
860 pthread_mutex_lock(&sExtensionMapMutex);
861
862 /*
863 * Since eglGetProcAddress() is not associated to anything, it needs
864 * to return a function pointer that "works" regardless of what
865 * the current context is.
866 *
867 * For this reason, we return a "forwarder", a small stub that takes
868 * care of calling the function associated with the context
869 * currently bound.
870 *
871 * We first look for extensions we've already resolved, if we're seeing
872 * this extension for the first time, we go through all our
873 * implementations and call eglGetProcAddress() and record the
874 * result in the appropriate implementation hooks and return the
875 * address of the forwarder corresponding to that hook set.
876 *
877 */
878
879 const String8 name(procname);
880 addr = sGLExtentionMap.valueFor(name);
881 const int slot = sGLExtentionSlot;
882
Steve Blocke6f43dd2012-01-06 19:20:56 +0000883 ALOGE_IF(slot >= MAX_NUMBER_OF_GL_EXTENSIONS,
Mathias Agopian518ec112011-05-13 16:21:08 -0700884 "no more slots for eglGetProcAddress(\"%s\")",
885 procname);
886
Siva Velusamy0469dd62011-11-30 15:05:37 -0800887#if EGL_TRACE
888 gl_hooks_t *debugHooks = GLTrace_getGLHooks();
889#endif
890
Mathias Agopian518ec112011-05-13 16:21:08 -0700891 if (!addr && (slot < MAX_NUMBER_OF_GL_EXTENSIONS)) {
892 bool found = false;
Mathias Agopianada798b2012-02-13 17:09:30 -0800893
894 egl_connection_t* const cnx = &gEGLImpl;
895 if (cnx->dso && cnx->egl.eglGetProcAddress) {
Mathias Agopianada798b2012-02-13 17:09:30 -0800896 // Extensions are independent of the bound context
luliuhui69d10072012-08-30 11:15:36 +0800897 addr =
Mathias Agopian7773c432012-02-13 20:06:08 -0800898 cnx->hooks[egl_connection_t::GLESv1_INDEX]->ext.extensions[slot] =
899 cnx->hooks[egl_connection_t::GLESv2_INDEX]->ext.extensions[slot] =
Mathias Agopian518ec112011-05-13 16:21:08 -0700900#if EGL_TRACE
Mathias Agopianada798b2012-02-13 17:09:30 -0800901 debugHooks->ext.extensions[slot] =
902 gHooksTrace.ext.extensions[slot] =
Mathias Agopian518ec112011-05-13 16:21:08 -0700903#endif
Mathias Agopianada798b2012-02-13 17:09:30 -0800904 cnx->egl.eglGetProcAddress(procname);
luliuhui69d10072012-08-30 11:15:36 +0800905 if (addr) found = true;
Mathias Agopian518ec112011-05-13 16:21:08 -0700906 }
Mathias Agopianada798b2012-02-13 17:09:30 -0800907
Mathias Agopian518ec112011-05-13 16:21:08 -0700908 if (found) {
909 addr = gExtensionForwarders[slot];
Mathias Agopian518ec112011-05-13 16:21:08 -0700910 sGLExtentionMap.add(name, addr);
911 sGLExtentionSlot++;
912 }
913 }
914
915 pthread_mutex_unlock(&sExtensionMapMutex);
916 return addr;
917}
918
Jamie Gennis28ef8d72012-04-05 20:34:54 -0700919class FrameCompletionThread : public Thread {
920public:
921
922 static void queueSync(EGLSyncKHR sync) {
923 static sp<FrameCompletionThread> thread(new FrameCompletionThread);
924 static bool running = false;
925 if (!running) {
926 thread->run("GPUFrameCompletion");
927 running = true;
928 }
929 {
930 Mutex::Autolock lock(thread->mMutex);
931 ScopedTrace st(ATRACE_TAG, String8::format("kicked off frame %d",
932 thread->mFramesQueued).string());
933 thread->mQueue.push_back(sync);
934 thread->mCondition.signal();
935 thread->mFramesQueued++;
936 ATRACE_INT("GPU Frames Outstanding", thread->mQueue.size());
937 }
938 }
939
940private:
941 FrameCompletionThread() : mFramesQueued(0), mFramesCompleted(0) {}
942
943 virtual bool threadLoop() {
944 EGLSyncKHR sync;
945 uint32_t frameNum;
946 {
947 Mutex::Autolock lock(mMutex);
948 while (mQueue.isEmpty()) {
949 mCondition.wait(mMutex);
950 }
951 sync = mQueue[0];
952 frameNum = mFramesCompleted;
953 }
954 EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
955 {
956 ScopedTrace st(ATRACE_TAG, String8::format("waiting for frame %d",
957 frameNum).string());
958 EGLint result = eglClientWaitSyncKHR(dpy, sync, 0, EGL_FOREVER_KHR);
959 if (result == EGL_FALSE) {
960 ALOGE("FrameCompletion: error waiting for fence: %#x", eglGetError());
961 } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
962 ALOGE("FrameCompletion: timeout waiting for fence");
963 }
964 eglDestroySyncKHR(dpy, sync);
965 }
966 {
967 Mutex::Autolock lock(mMutex);
968 mQueue.removeAt(0);
969 mFramesCompleted++;
970 ATRACE_INT("GPU Frames Outstanding", mQueue.size());
971 }
972 return true;
973 }
974
975 uint32_t mFramesQueued;
976 uint32_t mFramesCompleted;
977 Vector<EGLSyncKHR> mQueue;
978 Condition mCondition;
979 Mutex mMutex;
980};
981
Mathias Agopian518ec112011-05-13 16:21:08 -0700982EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw)
983{
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800984 ATRACE_CALL();
Mathias Agopian518ec112011-05-13 16:21:08 -0700985 clearError();
986
Jesse Hallb29e5e82012-04-04 16:53:42 -0700987 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700988 if (!dp) return EGL_FALSE;
989
Jesse Hallb29e5e82012-04-04 16:53:42 -0700990 SurfaceRef _s(dp.get(), draw);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700991 if (!_s.get())
992 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700993
Siva Velusamy0469dd62011-11-30 15:05:37 -0800994#if EGL_TRACE
Siva Velusamya73a9772012-12-18 14:56:55 -0800995 gl_hooks_t const *trace_hooks = getGLTraceThreadSpecific();
996 if (getEGLDebugLevel() > 0) {
997 if (trace_hooks == NULL) {
998 if (GLTrace_start() < 0) {
999 ALOGE("Disabling Tracer for OpenGL ES");
1000 setEGLDebugLevel(0);
1001 } else {
1002 // switch over to the trace version of hooks
1003 EGLContext ctx = egl_tls_t::getContext();
1004 egl_context_t * const c = get_context(ctx);
1005 if (c) {
1006 setGLHooksThreadSpecific(c->cnx->hooks[c->version]);
1007 GLTrace_eglMakeCurrent(c->version, c->cnx->hooks[c->version], ctx);
1008 }
1009 }
1010 }
1011
Siva Velusamy0469dd62011-11-30 15:05:37 -08001012 GLTrace_eglSwapBuffers(dpy, draw);
Siva Velusamya73a9772012-12-18 14:56:55 -08001013 } else if (trace_hooks != NULL) {
1014 // tracing is now disabled, so switch back to the non trace version
1015 EGLContext ctx = egl_tls_t::getContext();
1016 egl_context_t * const c = get_context(ctx);
1017 if (c) setGLHooksThreadSpecific(c->cnx->hooks[c->version]);
1018 GLTrace_stop();
1019 }
Siva Velusamy0469dd62011-11-30 15:05:37 -08001020#endif
1021
Mathias Agopian518ec112011-05-13 16:21:08 -07001022 egl_surface_t const * const s = get_surface(draw);
Mathias Agopian7db993a2012-03-25 00:49:46 -07001023
Mathias Agopianed6d08b2013-04-16 16:39:46 -07001024 if (CC_UNLIKELY(dp->traceGpuCompletion)) {
1025 EGLSyncKHR sync = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, NULL);
1026 if (sync != EGL_NO_SYNC_KHR) {
1027 FrameCompletionThread::queueSync(sync);
1028 }
1029 }
1030
Mathias Agopian7db993a2012-03-25 00:49:46 -07001031 if (CC_UNLIKELY(dp->finishOnSwap)) {
1032 uint32_t pixel;
1033 egl_context_t * const c = get_context( egl_tls_t::getContext() );
1034 if (c) {
1035 // glReadPixels() ensures that the frame is complete
1036 s->cnx->hooks[c->version]->gl.glReadPixels(0,0,1,1,
1037 GL_RGBA,GL_UNSIGNED_BYTE,&pixel);
1038 }
1039 }
1040
Mathias Agopianed6d08b2013-04-16 16:39:46 -07001041 return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface);
Mathias Agopian518ec112011-05-13 16:21:08 -07001042}
1043
1044EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface,
1045 NativePixmapType target)
1046{
1047 clearError();
1048
Jesse Hallb29e5e82012-04-04 16:53:42 -07001049 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001050 if (!dp) return EGL_FALSE;
1051
Jesse Hallb29e5e82012-04-04 16:53:42 -07001052 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001053 if (!_s.get())
1054 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001055
Mathias Agopian518ec112011-05-13 16:21:08 -07001056 egl_surface_t const * const s = get_surface(surface);
Mathias Agopianada798b2012-02-13 17:09:30 -08001057 return s->cnx->egl.eglCopyBuffers(dp->disp.dpy, s->surface, target);
Mathias Agopian518ec112011-05-13 16:21:08 -07001058}
1059
1060const char* eglQueryString(EGLDisplay dpy, EGLint name)
1061{
1062 clearError();
1063
Jesse Hallb29e5e82012-04-04 16:53:42 -07001064 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001065 if (!dp) return (const char *) NULL;
1066
1067 switch (name) {
1068 case EGL_VENDOR:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001069 return dp->getVendorString();
Mathias Agopian518ec112011-05-13 16:21:08 -07001070 case EGL_VERSION:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001071 return dp->getVersionString();
Mathias Agopian518ec112011-05-13 16:21:08 -07001072 case EGL_EXTENSIONS:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001073 return dp->getExtensionString();
Mathias Agopian518ec112011-05-13 16:21:08 -07001074 case EGL_CLIENT_APIS:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001075 return dp->getClientApiString();
Mathias Agopian518ec112011-05-13 16:21:08 -07001076 }
1077 return setError(EGL_BAD_PARAMETER, (const char *)0);
1078}
1079
Mathias Agopianca088332013-03-28 17:44:13 -07001080EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name)
1081{
1082 clearError();
1083
1084 const egl_display_ptr dp = validate_display(dpy);
1085 if (!dp) return (const char *) NULL;
1086
1087 switch (name) {
1088 case EGL_VENDOR:
1089 return dp->disp.queryString.vendor;
1090 case EGL_VERSION:
1091 return dp->disp.queryString.version;
1092 case EGL_EXTENSIONS:
1093 return dp->disp.queryString.extensions;
1094 case EGL_CLIENT_APIS:
1095 return dp->disp.queryString.clientApi;
1096 }
1097 return setError(EGL_BAD_PARAMETER, (const char *)0);
1098}
Mathias Agopian518ec112011-05-13 16:21:08 -07001099
1100// ----------------------------------------------------------------------------
1101// EGL 1.1
1102// ----------------------------------------------------------------------------
1103
1104EGLBoolean eglSurfaceAttrib(
1105 EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
1106{
1107 clearError();
1108
Jesse Hallb29e5e82012-04-04 16:53:42 -07001109 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001110 if (!dp) return EGL_FALSE;
1111
Jesse Hallb29e5e82012-04-04 16:53:42 -07001112 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001113 if (!_s.get())
1114 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001115
Mathias Agopian518ec112011-05-13 16:21:08 -07001116 egl_surface_t const * const s = get_surface(surface);
1117 if (s->cnx->egl.eglSurfaceAttrib) {
1118 return s->cnx->egl.eglSurfaceAttrib(
Mathias Agopianada798b2012-02-13 17:09:30 -08001119 dp->disp.dpy, s->surface, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -07001120 }
1121 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1122}
1123
1124EGLBoolean eglBindTexImage(
1125 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1126{
1127 clearError();
1128
Jesse Hallb29e5e82012-04-04 16:53:42 -07001129 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001130 if (!dp) return EGL_FALSE;
1131
Jesse Hallb29e5e82012-04-04 16:53:42 -07001132 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001133 if (!_s.get())
1134 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001135
Mathias Agopian518ec112011-05-13 16:21:08 -07001136 egl_surface_t const * const s = get_surface(surface);
1137 if (s->cnx->egl.eglBindTexImage) {
1138 return s->cnx->egl.eglBindTexImage(
Mathias Agopianada798b2012-02-13 17:09:30 -08001139 dp->disp.dpy, s->surface, buffer);
Mathias Agopian518ec112011-05-13 16:21:08 -07001140 }
1141 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1142}
1143
1144EGLBoolean eglReleaseTexImage(
1145 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1146{
1147 clearError();
1148
Jesse Hallb29e5e82012-04-04 16:53:42 -07001149 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001150 if (!dp) return EGL_FALSE;
1151
Jesse Hallb29e5e82012-04-04 16:53:42 -07001152 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001153 if (!_s.get())
1154 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001155
Mathias Agopian518ec112011-05-13 16:21:08 -07001156 egl_surface_t const * const s = get_surface(surface);
1157 if (s->cnx->egl.eglReleaseTexImage) {
1158 return s->cnx->egl.eglReleaseTexImage(
Mathias Agopianada798b2012-02-13 17:09:30 -08001159 dp->disp.dpy, s->surface, buffer);
Mathias Agopian518ec112011-05-13 16:21:08 -07001160 }
1161 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1162}
1163
1164EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
1165{
1166 clearError();
1167
Jesse Hallb29e5e82012-04-04 16:53:42 -07001168 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001169 if (!dp) return EGL_FALSE;
1170
1171 EGLBoolean res = EGL_TRUE;
Mathias Agopianada798b2012-02-13 17:09:30 -08001172 egl_connection_t* const cnx = &gEGLImpl;
1173 if (cnx->dso && cnx->egl.eglSwapInterval) {
1174 res = cnx->egl.eglSwapInterval(dp->disp.dpy, interval);
Mathias Agopian518ec112011-05-13 16:21:08 -07001175 }
Mathias Agopianada798b2012-02-13 17:09:30 -08001176
Mathias Agopian518ec112011-05-13 16:21:08 -07001177 return res;
1178}
1179
1180
1181// ----------------------------------------------------------------------------
1182// EGL 1.2
1183// ----------------------------------------------------------------------------
1184
1185EGLBoolean eglWaitClient(void)
1186{
1187 clearError();
1188
Mathias Agopianada798b2012-02-13 17:09:30 -08001189 egl_connection_t* const cnx = &gEGLImpl;
1190 if (!cnx->dso)
1191 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1192
1193 EGLBoolean res;
1194 if (cnx->egl.eglWaitClient) {
1195 res = cnx->egl.eglWaitClient();
1196 } else {
1197 res = cnx->egl.eglWaitGL();
Mathias Agopian518ec112011-05-13 16:21:08 -07001198 }
1199 return res;
1200}
1201
1202EGLBoolean eglBindAPI(EGLenum api)
1203{
1204 clearError();
1205
1206 if (egl_init_drivers() == EGL_FALSE) {
1207 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1208 }
1209
1210 // bind this API on all EGLs
1211 EGLBoolean res = EGL_TRUE;
Mathias Agopianada798b2012-02-13 17:09:30 -08001212 egl_connection_t* const cnx = &gEGLImpl;
1213 if (cnx->dso && cnx->egl.eglBindAPI) {
1214 res = cnx->egl.eglBindAPI(api);
Mathias Agopian518ec112011-05-13 16:21:08 -07001215 }
1216 return res;
1217}
1218
1219EGLenum eglQueryAPI(void)
1220{
1221 clearError();
1222
1223 if (egl_init_drivers() == EGL_FALSE) {
1224 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1225 }
1226
Mathias Agopianada798b2012-02-13 17:09:30 -08001227 egl_connection_t* const cnx = &gEGLImpl;
1228 if (cnx->dso && cnx->egl.eglQueryAPI) {
1229 return cnx->egl.eglQueryAPI();
Mathias Agopian518ec112011-05-13 16:21:08 -07001230 }
Mathias Agopianada798b2012-02-13 17:09:30 -08001231
Mathias Agopian518ec112011-05-13 16:21:08 -07001232 // or, it can only be OpenGL ES
1233 return EGL_OPENGL_ES_API;
1234}
1235
1236EGLBoolean eglReleaseThread(void)
1237{
1238 clearError();
1239
Mathias Agopian4e620dd2013-05-30 16:07:36 -07001240#if EGL_TRACE
1241 if (getEGLDebugLevel() > 0)
1242 GLTrace_eglReleaseThread();
1243#endif
1244
Mathias Agopian518ec112011-05-13 16:21:08 -07001245 // If there is context bound to the thread, release it
Mathias Agopianfb87e542012-01-30 18:20:52 -08001246 egl_display_t::loseCurrent(get_context(getContext()));
Mathias Agopian518ec112011-05-13 16:21:08 -07001247
Mathias Agopianada798b2012-02-13 17:09:30 -08001248 egl_connection_t* const cnx = &gEGLImpl;
1249 if (cnx->dso && cnx->egl.eglReleaseThread) {
1250 cnx->egl.eglReleaseThread();
Mathias Agopian518ec112011-05-13 16:21:08 -07001251 }
1252 egl_tls_t::clearTLS();
Mathias Agopian518ec112011-05-13 16:21:08 -07001253 return EGL_TRUE;
1254}
1255
1256EGLSurface eglCreatePbufferFromClientBuffer(
1257 EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer,
1258 EGLConfig config, const EGLint *attrib_list)
1259{
1260 clearError();
1261
Jesse Hallb29e5e82012-04-04 16:53:42 -07001262 egl_connection_t* cnx = NULL;
1263 const egl_display_ptr dp = validate_display_connection(dpy, cnx);
1264 if (!dp) return EGL_FALSE;
Mathias Agopian518ec112011-05-13 16:21:08 -07001265 if (cnx->egl.eglCreatePbufferFromClientBuffer) {
1266 return cnx->egl.eglCreatePbufferFromClientBuffer(
Mathias Agopian7773c432012-02-13 20:06:08 -08001267 dp->disp.dpy, buftype, buffer, config, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001268 }
1269 return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE);
1270}
1271
1272// ----------------------------------------------------------------------------
1273// EGL_EGLEXT_VERSION 3
1274// ----------------------------------------------------------------------------
1275
1276EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface,
1277 const EGLint *attrib_list)
1278{
1279 clearError();
1280
Jesse Hallb29e5e82012-04-04 16:53:42 -07001281 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001282 if (!dp) return EGL_FALSE;
1283
Jesse Hallb29e5e82012-04-04 16:53:42 -07001284 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001285 if (!_s.get())
1286 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001287
1288 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian518ec112011-05-13 16:21:08 -07001289 if (s->cnx->egl.eglLockSurfaceKHR) {
1290 return s->cnx->egl.eglLockSurfaceKHR(
Mathias Agopianada798b2012-02-13 17:09:30 -08001291 dp->disp.dpy, s->surface, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001292 }
1293 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1294}
1295
1296EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface)
1297{
1298 clearError();
1299
Jesse Hallb29e5e82012-04-04 16:53:42 -07001300 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001301 if (!dp) return EGL_FALSE;
1302
Jesse Hallb29e5e82012-04-04 16:53:42 -07001303 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001304 if (!_s.get())
1305 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001306
1307 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian518ec112011-05-13 16:21:08 -07001308 if (s->cnx->egl.eglUnlockSurfaceKHR) {
Mathias Agopianada798b2012-02-13 17:09:30 -08001309 return s->cnx->egl.eglUnlockSurfaceKHR(dp->disp.dpy, s->surface);
Mathias Agopian518ec112011-05-13 16:21:08 -07001310 }
1311 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1312}
1313
1314EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
1315 EGLClientBuffer buffer, const EGLint *attrib_list)
1316{
1317 clearError();
1318
Jesse Hallb29e5e82012-04-04 16:53:42 -07001319 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001320 if (!dp) return EGL_NO_IMAGE_KHR;
1321
Jesse Hallb29e5e82012-04-04 16:53:42 -07001322 ContextRef _c(dp.get(), ctx);
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001323 egl_context_t * const c = _c.get();
Mathias Agopian518ec112011-05-13 16:21:08 -07001324
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001325 EGLImageKHR result = EGL_NO_IMAGE_KHR;
1326 egl_connection_t* const cnx = &gEGLImpl;
1327 if (cnx->dso && cnx->egl.eglCreateImageKHR) {
1328 result = cnx->egl.eglCreateImageKHR(
1329 dp->disp.dpy,
1330 c ? c->context : EGL_NO_CONTEXT,
1331 target, buffer, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001332 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001333 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001334}
1335
1336EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
1337{
1338 clearError();
1339
Jesse Hallb29e5e82012-04-04 16:53:42 -07001340 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001341 if (!dp) return EGL_FALSE;
1342
Steven Holte646a5c52012-06-04 20:02:11 -07001343 EGLBoolean result = EGL_FALSE;
Mathias Agopianada798b2012-02-13 17:09:30 -08001344 egl_connection_t* const cnx = &gEGLImpl;
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001345 if (cnx->dso && cnx->egl.eglDestroyImageKHR) {
Steven Holte646a5c52012-06-04 20:02:11 -07001346 result = cnx->egl.eglDestroyImageKHR(dp->disp.dpy, img);
Mathias Agopian518ec112011-05-13 16:21:08 -07001347 }
Steven Holte646a5c52012-06-04 20:02:11 -07001348 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001349}
1350
1351// ----------------------------------------------------------------------------
1352// EGL_EGLEXT_VERSION 5
1353// ----------------------------------------------------------------------------
1354
1355
1356EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
1357{
1358 clearError();
1359
Jesse Hallb29e5e82012-04-04 16:53:42 -07001360 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001361 if (!dp) return EGL_NO_SYNC_KHR;
1362
Mathias Agopian518ec112011-05-13 16:21:08 -07001363 EGLSyncKHR result = EGL_NO_SYNC_KHR;
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001364 egl_connection_t* const cnx = &gEGLImpl;
1365 if (cnx->dso && cnx->egl.eglCreateSyncKHR) {
1366 result = cnx->egl.eglCreateSyncKHR(dp->disp.dpy, type, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001367 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001368 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001369}
1370
1371EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
1372{
1373 clearError();
1374
Jesse Hallb29e5e82012-04-04 16:53:42 -07001375 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001376 if (!dp) return EGL_FALSE;
1377
Mathias Agopian518ec112011-05-13 16:21:08 -07001378 EGLBoolean result = EGL_FALSE;
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001379 egl_connection_t* const cnx = &gEGLImpl;
1380 if (cnx->dso && cnx->egl.eglDestroySyncKHR) {
1381 result = cnx->egl.eglDestroySyncKHR(dp->disp.dpy, sync);
Mathias Agopian518ec112011-05-13 16:21:08 -07001382 }
1383 return result;
1384}
1385
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -07001386EGLBoolean eglSignalSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode) {
1387 clearError();
1388
1389 const egl_display_ptr dp = validate_display(dpy);
1390 if (!dp) return EGL_FALSE;
1391
1392 EGLBoolean result = EGL_FALSE;
1393 egl_connection_t* const cnx = &gEGLImpl;
1394 if (cnx->dso && cnx->egl.eglSignalSyncKHR) {
1395 result = cnx->egl.eglSignalSyncKHR(
1396 dp->disp.dpy, sync, mode);
1397 }
1398 return result;
1399}
1400
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001401EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync,
1402 EGLint flags, EGLTimeKHR timeout)
Mathias Agopian518ec112011-05-13 16:21:08 -07001403{
1404 clearError();
1405
Jesse Hallb29e5e82012-04-04 16:53:42 -07001406 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001407 if (!dp) return EGL_FALSE;
1408
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001409 EGLBoolean result = EGL_FALSE;
1410 egl_connection_t* const cnx = &gEGLImpl;
1411 if (cnx->dso && cnx->egl.eglClientWaitSyncKHR) {
1412 result = cnx->egl.eglClientWaitSyncKHR(
1413 dp->disp.dpy, sync, flags, timeout);
Mathias Agopian518ec112011-05-13 16:21:08 -07001414 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001415 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001416}
1417
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001418EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync,
1419 EGLint attribute, EGLint *value)
Mathias Agopian518ec112011-05-13 16:21:08 -07001420{
1421 clearError();
1422
Jesse Hallb29e5e82012-04-04 16:53:42 -07001423 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001424 if (!dp) return EGL_FALSE;
1425
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001426 EGLBoolean result = EGL_FALSE;
1427 egl_connection_t* const cnx = &gEGLImpl;
1428 if (cnx->dso && cnx->egl.eglGetSyncAttribKHR) {
1429 result = cnx->egl.eglGetSyncAttribKHR(
1430 dp->disp.dpy, sync, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -07001431 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001432 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001433}
1434
1435// ----------------------------------------------------------------------------
Mathias Agopian2bb71682013-03-27 17:32:41 -07001436// EGL_EGLEXT_VERSION 15
1437// ----------------------------------------------------------------------------
1438
1439EGLint eglWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags) {
1440 clearError();
1441 const egl_display_ptr dp = validate_display(dpy);
1442 if (!dp) return EGL_FALSE;
1443 EGLint result = EGL_FALSE;
1444 egl_connection_t* const cnx = &gEGLImpl;
1445 if (cnx->dso && cnx->egl.eglWaitSyncKHR) {
1446 result = cnx->egl.eglWaitSyncKHR(dp->disp.dpy, sync, flags);
1447 }
1448 return result;
1449}
1450
1451// ----------------------------------------------------------------------------
Mathias Agopian518ec112011-05-13 16:21:08 -07001452// ANDROID extensions
1453// ----------------------------------------------------------------------------
1454
Jamie Gennis331841b2012-09-06 14:52:00 -07001455EGLint eglDupNativeFenceFDANDROID(EGLDisplay dpy, EGLSyncKHR sync)
1456{
1457 clearError();
1458
1459 const egl_display_ptr dp = validate_display(dpy);
1460 if (!dp) return EGL_NO_NATIVE_FENCE_FD_ANDROID;
1461
1462 EGLint result = EGL_NO_NATIVE_FENCE_FD_ANDROID;
1463 egl_connection_t* const cnx = &gEGLImpl;
1464 if (cnx->dso && cnx->egl.eglDupNativeFenceFDANDROID) {
1465 result = cnx->egl.eglDupNativeFenceFDANDROID(dp->disp.dpy, sync);
1466 }
1467 return result;
1468}
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001469
Andy McFadden72841452013-03-01 16:25:32 -08001470EGLBoolean eglPresentationTimeANDROID(EGLDisplay dpy, EGLSurface surface,
1471 EGLnsecsANDROID time)
1472{
1473 clearError();
1474
1475 const egl_display_ptr dp = validate_display(dpy);
1476 if (!dp) {
1477 return EGL_FALSE;
1478 }
1479
1480 SurfaceRef _s(dp.get(), surface);
1481 if (!_s.get()) {
1482 setError(EGL_BAD_SURFACE, EGL_FALSE);
1483 return EGL_FALSE;
1484 }
1485
1486 egl_surface_t const * const s = get_surface(surface);
1487 native_window_set_buffers_timestamp(s->win.get(), time);
1488
1489 return EGL_TRUE;
1490}
1491
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001492// ----------------------------------------------------------------------------
1493// NVIDIA extensions
1494// ----------------------------------------------------------------------------
1495EGLuint64NV eglGetSystemTimeFrequencyNV()
1496{
1497 clearError();
1498
1499 if (egl_init_drivers() == EGL_FALSE) {
1500 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1501 }
1502
1503 EGLuint64NV ret = 0;
Mathias Agopianada798b2012-02-13 17:09:30 -08001504 egl_connection_t* const cnx = &gEGLImpl;
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001505
Mathias Agopianada798b2012-02-13 17:09:30 -08001506 if (cnx->dso && cnx->egl.eglGetSystemTimeFrequencyNV) {
1507 return cnx->egl.eglGetSystemTimeFrequencyNV();
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001508 }
1509
Mathias Agopian0e8bbee2011-10-05 19:15:05 -07001510 return setErrorQuiet(EGL_BAD_DISPLAY, 0);
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001511}
1512
1513EGLuint64NV eglGetSystemTimeNV()
1514{
1515 clearError();
1516
1517 if (egl_init_drivers() == EGL_FALSE) {
1518 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1519 }
1520
1521 EGLuint64NV ret = 0;
Mathias Agopianada798b2012-02-13 17:09:30 -08001522 egl_connection_t* const cnx = &gEGLImpl;
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001523
Mathias Agopianada798b2012-02-13 17:09:30 -08001524 if (cnx->dso && cnx->egl.eglGetSystemTimeNV) {
1525 return cnx->egl.eglGetSystemTimeNV();
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001526 }
1527
Mathias Agopian0e8bbee2011-10-05 19:15:05 -07001528 return setErrorQuiet(EGL_BAD_DISPLAY, 0);
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001529}