blob: cdec565e4e97613bd5ac5e4ca8b7db255d4c40f5 [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
Jesse Halla2ba4282013-09-14 21:00:14 -070052// This extension has not been ratified yet, so can't be shipped.
53// Implementation is incomplete and untested.
54#define ENABLE_EGL_KHR_GL_COLORSPACE 0
55
Mathias Agopian518ec112011-05-13 16:21:08 -070056// ----------------------------------------------------------------------------
57
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070058namespace android {
59
Mathias Agopian518ec112011-05-13 16:21:08 -070060struct extention_map_t {
61 const char* name;
62 __eglMustCastToProperFunctionPointerType address;
63};
64
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070065/*
Jesse Hall21558da2013-08-06 15:31:22 -070066 * This is the list of EGL extensions exposed to applications.
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070067 *
Jesse Hall21558da2013-08-06 15:31:22 -070068 * Some of them (gBuiltinExtensionString) are implemented entirely in this EGL
69 * wrapper and are always available.
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070070 *
Jesse Hall21558da2013-08-06 15:31:22 -070071 * The rest (gExtensionString) depend on support in the EGL driver, and are
72 * only available if the driver supports them. However, some of these must be
73 * supported because they are used by the Android system itself; these are
74 * listd as mandatory below and are required by the CDD. The system *assumes*
75 * the mandatory extensions are present and may not function properly if some
76 * are missing.
77 *
78 * NOTE: Both strings MUST have a single space as the last character.
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070079 */
Jesse Hall21558da2013-08-06 15:31:22 -070080extern char const * const gBuiltinExtensionString =
81 "EGL_KHR_get_all_proc_addresses "
82 "EGL_ANDROID_presentation_time "
Dan Stozaa894d082015-02-19 15:27:36 -080083 "EGL_KHR_swap_buffers_with_damage "
Jesse Hall21558da2013-08-06 15:31:22 -070084 ;
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070085extern char const * const gExtensionString =
86 "EGL_KHR_image " // mandatory
87 "EGL_KHR_image_base " // mandatory
88 "EGL_KHR_image_pixmap "
89 "EGL_KHR_lock_surface "
Jesse Halla2ba4282013-09-14 21:00:14 -070090#if (ENABLE_EGL_KHR_GL_COLORSPACE != 0)
Jesse Hallc2e41222013-08-08 13:40:22 -070091 "EGL_KHR_gl_colorspace "
Jesse Halla2ba4282013-09-14 21:00:14 -070092#endif
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070093 "EGL_KHR_gl_texture_2D_image "
Season Li000d88f2015-07-01 11:39:40 -070094 "EGL_KHR_gl_texture_3D_image "
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070095 "EGL_KHR_gl_texture_cubemap_image "
96 "EGL_KHR_gl_renderbuffer_image "
97 "EGL_KHR_reusable_sync "
98 "EGL_KHR_fence_sync "
Jamie Gennisf6d1c392013-04-25 18:48:41 -070099 "EGL_KHR_create_context "
Season Li000d88f2015-07-01 11:39:40 -0700100 "EGL_KHR_config_attribs "
101 "EGL_KHR_surfaceless_context "
102 "EGL_KHR_stream "
103 "EGL_KHR_stream_fifo "
104 "EGL_KHR_stream_producer_eglsurface "
105 "EGL_KHR_stream_consumer_gltexture "
106 "EGL_KHR_stream_cross_process_fd "
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700107 "EGL_EXT_create_context_robustness "
108 "EGL_NV_system_time "
109 "EGL_ANDROID_image_native_buffer " // mandatory
Mathias Agopian2bb71682013-03-27 17:32:41 -0700110 "EGL_KHR_wait_sync " // strongly recommended
Jamie Gennisdbe92452013-09-23 17:22:10 -0700111 "EGL_ANDROID_recordable " // mandatory
Dan Stozaa894d082015-02-19 15:27:36 -0800112 "EGL_KHR_partial_update " // strongly recommended
113 "EGL_EXT_buffer_age " // strongly recommended with partial_update
Jesse Hall408e59f2015-04-24 01:40:42 -0700114 "EGL_KHR_create_context_no_error "
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700115 ;
116
117// extensions not exposed to applications but used by the ANDROID system
118// "EGL_ANDROID_blob_cache " // strongly recommended
119// "EGL_IMG_hibernate_process " // optional
120// "EGL_ANDROID_native_fence_sync " // strongly recommended
121// "EGL_ANDROID_framebuffer_target " // mandatory for HWC 1.1
Jamie Gennisdbe92452013-09-23 17:22:10 -0700122// "EGL_ANDROID_image_crop " // optional
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700123
124/*
125 * EGL Extensions entry-points exposed to 3rd party applications
126 * (keep in sync with gExtensionString above)
127 *
128 */
129static const extention_map_t sExtensionMap[] = {
130 // EGL_KHR_lock_surface
Mathias Agopian518ec112011-05-13 16:21:08 -0700131 { "eglLockSurfaceKHR",
132 (__eglMustCastToProperFunctionPointerType)&eglLockSurfaceKHR },
133 { "eglUnlockSurfaceKHR",
134 (__eglMustCastToProperFunctionPointerType)&eglUnlockSurfaceKHR },
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700135
136 // EGL_KHR_image, EGL_KHR_image_base
Mathias Agopian518ec112011-05-13 16:21:08 -0700137 { "eglCreateImageKHR",
138 (__eglMustCastToProperFunctionPointerType)&eglCreateImageKHR },
139 { "eglDestroyImageKHR",
140 (__eglMustCastToProperFunctionPointerType)&eglDestroyImageKHR },
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700141
142 // EGL_KHR_reusable_sync, EGL_KHR_fence_sync
143 { "eglCreateSyncKHR",
144 (__eglMustCastToProperFunctionPointerType)&eglCreateSyncKHR },
145 { "eglDestroySyncKHR",
146 (__eglMustCastToProperFunctionPointerType)&eglDestroySyncKHR },
147 { "eglClientWaitSyncKHR",
148 (__eglMustCastToProperFunctionPointerType)&eglClientWaitSyncKHR },
149 { "eglSignalSyncKHR",
150 (__eglMustCastToProperFunctionPointerType)&eglSignalSyncKHR },
151 { "eglGetSyncAttribKHR",
152 (__eglMustCastToProperFunctionPointerType)&eglGetSyncAttribKHR },
153
154 // EGL_NV_system_time
Jonas Yang1c3d72a2011-08-26 20:04:39 +0800155 { "eglGetSystemTimeFrequencyNV",
156 (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeFrequencyNV },
157 { "eglGetSystemTimeNV",
158 (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeNV },
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700159
Mathias Agopian2bb71682013-03-27 17:32:41 -0700160 // EGL_KHR_wait_sync
161 { "eglWaitSyncKHR",
162 (__eglMustCastToProperFunctionPointerType)&eglWaitSyncKHR },
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700163
164 // EGL_ANDROID_presentation_time
165 { "eglPresentationTimeANDROID",
166 (__eglMustCastToProperFunctionPointerType)&eglPresentationTimeANDROID },
Dan Stozaa894d082015-02-19 15:27:36 -0800167
168 // EGL_KHR_swap_buffers_with_damage
169 { "eglSwapBuffersWithDamageKHR",
170 (__eglMustCastToProperFunctionPointerType)&eglSwapBuffersWithDamageKHR },
171
172 // EGL_KHR_partial_update
173 { "eglSetDamageRegionKHR",
174 (__eglMustCastToProperFunctionPointerType)&eglSetDamageRegionKHR },
Season Li000d88f2015-07-01 11:39:40 -0700175
176 { "eglCreateStreamKHR",
177 (__eglMustCastToProperFunctionPointerType)&eglCreateStreamKHR },
178 { "eglDestroyStreamKHR",
179 (__eglMustCastToProperFunctionPointerType)&eglDestroyStreamKHR },
180 { "eglStreamAttribKHR",
181 (__eglMustCastToProperFunctionPointerType)&eglStreamAttribKHR },
182 { "eglQueryStreamKHR",
183 (__eglMustCastToProperFunctionPointerType)&eglQueryStreamKHR },
184 { "eglQueryStreamu64KHR",
185 (__eglMustCastToProperFunctionPointerType)&eglQueryStreamu64KHR },
186 { "eglQueryStreamTimeKHR",
187 (__eglMustCastToProperFunctionPointerType)&eglQueryStreamTimeKHR },
188 { "eglCreateStreamProducerSurfaceKHR",
189 (__eglMustCastToProperFunctionPointerType)&eglCreateStreamProducerSurfaceKHR },
190 { "eglStreamConsumerGLTextureExternalKHR",
191 (__eglMustCastToProperFunctionPointerType)&eglStreamConsumerGLTextureExternalKHR },
192 { "eglStreamConsumerAcquireKHR",
193 (__eglMustCastToProperFunctionPointerType)&eglStreamConsumerAcquireKHR },
194 { "eglStreamConsumerReleaseKHR",
195 (__eglMustCastToProperFunctionPointerType)&eglStreamConsumerReleaseKHR },
196 { "eglGetStreamFileDescriptorKHR",
197 (__eglMustCastToProperFunctionPointerType)&eglGetStreamFileDescriptorKHR },
198 { "eglCreateStreamFromFileDescriptorKHR",
199 (__eglMustCastToProperFunctionPointerType)&eglCreateStreamFromFileDescriptorKHR },
Mathias Agopian518ec112011-05-13 16:21:08 -0700200};
201
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700202/*
203 * These extensions entry-points should not be exposed to applications.
204 * They're used internally by the Android EGL layer.
205 */
206#define FILTER_EXTENSIONS(procname) \
207 (!strcmp((procname), "eglSetBlobCacheFuncsANDROID") || \
208 !strcmp((procname), "eglHibernateProcessIMG") || \
209 !strcmp((procname), "eglAwakenProcessIMG") || \
210 !strcmp((procname), "eglDupNativeFenceFDANDROID"))
211
212
213
Mathias Agopian518ec112011-05-13 16:21:08 -0700214// accesses protected by sExtensionMapMutex
215static DefaultKeyedVector<String8, __eglMustCastToProperFunctionPointerType> sGLExtentionMap;
216static int sGLExtentionSlot = 0;
217static pthread_mutex_t sExtensionMapMutex = PTHREAD_MUTEX_INITIALIZER;
218
219static void(*findProcAddress(const char* name,
220 const extention_map_t* map, size_t n))() {
221 for (uint32_t i=0 ; i<n ; i++) {
222 if (!strcmp(name, map[i].name)) {
223 return map[i].address;
224 }
225 }
226 return NULL;
227}
228
229// ----------------------------------------------------------------------------
230
Mathias Agopian518ec112011-05-13 16:21:08 -0700231extern void setGLHooksThreadSpecific(gl_hooks_t const *value);
232extern EGLBoolean egl_init_drivers();
233extern const __eglMustCastToProperFunctionPointerType gExtensionForwarders[MAX_NUMBER_OF_GL_EXTENSIONS];
Siva Velusamya73a9772012-12-18 14:56:55 -0800234extern int getEGLDebugLevel();
235extern void setEGLDebugLevel(int level);
Mathias Agopian518ec112011-05-13 16:21:08 -0700236extern gl_hooks_t gHooksTrace;
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700237
Mathias Agopian518ec112011-05-13 16:21:08 -0700238} // namespace android;
239
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700240
Mathias Agopian518ec112011-05-13 16:21:08 -0700241// ----------------------------------------------------------------------------
242
243static inline void clearError() { egl_tls_t::clearError(); }
244static inline EGLContext getContext() { return egl_tls_t::getContext(); }
245
246// ----------------------------------------------------------------------------
247
248EGLDisplay eglGetDisplay(EGLNativeDisplayType display)
249{
250 clearError();
251
Dan Stozac3289c42014-01-17 11:38:34 -0800252 uintptr_t index = reinterpret_cast<uintptr_t>(display);
Mathias Agopian518ec112011-05-13 16:21:08 -0700253 if (index >= NUM_DISPLAYS) {
254 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
255 }
256
257 if (egl_init_drivers() == EGL_FALSE) {
258 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
259 }
260
261 EGLDisplay dpy = egl_display_t::getFromNativeDisplay(display);
262 return dpy;
263}
264
265// ----------------------------------------------------------------------------
266// Initialization
267// ----------------------------------------------------------------------------
268
269EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
270{
271 clearError();
272
Jesse Hallb29e5e82012-04-04 16:53:42 -0700273 egl_display_ptr dp = get_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700274 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
275
276 EGLBoolean res = dp->initialize(major, minor);
277
278 return res;
279}
280
281EGLBoolean eglTerminate(EGLDisplay dpy)
282{
283 // NOTE: don't unload the drivers b/c some APIs can be called
284 // after eglTerminate() has been called. eglTerminate() only
285 // terminates an EGLDisplay, not a EGL itself.
286
287 clearError();
288
Jesse Hallb29e5e82012-04-04 16:53:42 -0700289 egl_display_ptr dp = get_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700290 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
291
292 EGLBoolean res = dp->terminate();
Jesse Hall47743382013-02-08 11:13:46 -0800293
Mathias Agopian518ec112011-05-13 16:21:08 -0700294 return res;
295}
296
297// ----------------------------------------------------------------------------
298// configuration
299// ----------------------------------------------------------------------------
300
301EGLBoolean eglGetConfigs( EGLDisplay dpy,
302 EGLConfig *configs,
303 EGLint config_size, EGLint *num_config)
304{
305 clearError();
306
Jesse Hallb29e5e82012-04-04 16:53:42 -0700307 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700308 if (!dp) return EGL_FALSE;
309
Mathias Agopian7773c432012-02-13 20:06:08 -0800310 if (num_config==0) {
311 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700312 }
313
Mathias Agopian7773c432012-02-13 20:06:08 -0800314 EGLBoolean res = EGL_FALSE;
315 *num_config = 0;
316
317 egl_connection_t* const cnx = &gEGLImpl;
318 if (cnx->dso) {
319 res = cnx->egl.eglGetConfigs(
320 dp->disp.dpy, configs, config_size, num_config);
Mathias Agopian518ec112011-05-13 16:21:08 -0700321 }
Mathias Agopian7773c432012-02-13 20:06:08 -0800322
323 return res;
Mathias Agopian518ec112011-05-13 16:21:08 -0700324}
325
326EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list,
327 EGLConfig *configs, EGLint config_size,
328 EGLint *num_config)
329{
330 clearError();
331
Jesse Hallb29e5e82012-04-04 16:53:42 -0700332 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700333 if (!dp) return EGL_FALSE;
334
335 if (num_config==0) {
336 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
337 }
338
Mathias Agopian518ec112011-05-13 16:21:08 -0700339 EGLBoolean res = EGL_FALSE;
340 *num_config = 0;
341
Mathias Agopianada798b2012-02-13 17:09:30 -0800342 egl_connection_t* const cnx = &gEGLImpl;
343 if (cnx->dso) {
Romain Guy1cffc802012-10-15 18:13:05 -0700344 if (attrib_list) {
345 char value[PROPERTY_VALUE_MAX];
346 property_get("debug.egl.force_msaa", value, "false");
347
348 if (!strcmp(value, "true")) {
349 size_t attribCount = 0;
350 EGLint attrib = attrib_list[0];
351
352 // Only enable MSAA if the context is OpenGL ES 2.0 and
Romain Guybe3c3e42012-10-15 19:25:18 -0700353 // if no caveat is requested
Romain Guy1cffc802012-10-15 18:13:05 -0700354 const EGLint *attribRendererable = NULL;
355 const EGLint *attribCaveat = NULL;
356
357 // Count the number of attributes and look for
Romain Guybe3c3e42012-10-15 19:25:18 -0700358 // EGL_RENDERABLE_TYPE and EGL_CONFIG_CAVEAT
Romain Guy1cffc802012-10-15 18:13:05 -0700359 while (attrib != EGL_NONE) {
360 attrib = attrib_list[attribCount];
361 switch (attrib) {
362 case EGL_RENDERABLE_TYPE:
363 attribRendererable = &attrib_list[attribCount];
364 break;
365 case EGL_CONFIG_CAVEAT:
366 attribCaveat = &attrib_list[attribCount];
367 break;
368 }
369 attribCount++;
370 }
371
372 if (attribRendererable && attribRendererable[1] == EGL_OPENGL_ES2_BIT &&
373 (!attribCaveat || attribCaveat[1] != EGL_NONE)) {
Jesse Hall47743382013-02-08 11:13:46 -0800374
Romain Guy1cffc802012-10-15 18:13:05 -0700375 // Insert 2 extra attributes to force-enable MSAA 4x
376 EGLint aaAttribs[attribCount + 4];
377 aaAttribs[0] = EGL_SAMPLE_BUFFERS;
378 aaAttribs[1] = 1;
379 aaAttribs[2] = EGL_SAMPLES;
380 aaAttribs[3] = 4;
381
382 memcpy(&aaAttribs[4], attrib_list, attribCount * sizeof(EGLint));
383
384 EGLint numConfigAA;
385 EGLBoolean resAA = cnx->egl.eglChooseConfig(
386 dp->disp.dpy, aaAttribs, configs, config_size, &numConfigAA);
387
388 if (resAA == EGL_TRUE && numConfigAA > 0) {
389 ALOGD("Enabling MSAA 4x");
390 *num_config = numConfigAA;
391 return resAA;
392 }
393 }
394 }
395 }
396
Mathias Agopian7773c432012-02-13 20:06:08 -0800397 res = cnx->egl.eglChooseConfig(
398 dp->disp.dpy, attrib_list, configs, config_size, num_config);
Mathias Agopian518ec112011-05-13 16:21:08 -0700399 }
400 return res;
401}
402
403EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
404 EGLint attribute, EGLint *value)
405{
406 clearError();
407
Jesse Hallb29e5e82012-04-04 16:53:42 -0700408 egl_connection_t* cnx = NULL;
409 const egl_display_ptr dp = validate_display_connection(dpy, cnx);
410 if (!dp) return EGL_FALSE;
Jesse Hall47743382013-02-08 11:13:46 -0800411
Mathias Agopian518ec112011-05-13 16:21:08 -0700412 return cnx->egl.eglGetConfigAttrib(
Mathias Agopian7773c432012-02-13 20:06:08 -0800413 dp->disp.dpy, config, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -0700414}
415
416// ----------------------------------------------------------------------------
417// surfaces
418// ----------------------------------------------------------------------------
419
Jesse Halla2ba4282013-09-14 21:00:14 -0700420// The EGL_KHR_gl_colorspace spec hasn't been ratified yet, so these haven't
Jesse Hallc2e41222013-08-08 13:40:22 -0700421// been added to the Khronos egl.h.
422#define EGL_GL_COLORSPACE_KHR EGL_VG_COLORSPACE
423#define EGL_GL_COLORSPACE_SRGB_KHR EGL_VG_COLORSPACE_sRGB
424#define EGL_GL_COLORSPACE_LINEAR_KHR EGL_VG_COLORSPACE_LINEAR
425
426// Turn linear formats into corresponding sRGB formats when colorspace is
427// EGL_GL_COLORSPACE_SRGB_KHR, or turn sRGB formats into corresponding linear
428// formats when colorspace is EGL_GL_COLORSPACE_LINEAR_KHR. In any cases where
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800429// the modification isn't possible, the original dataSpace is returned.
430static android_dataspace modifyBufferDataspace( android_dataspace dataSpace,
431 EGLint colorspace) {
Jesse Hallc2e41222013-08-08 13:40:22 -0700432 if (colorspace == EGL_GL_COLORSPACE_LINEAR_KHR) {
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800433 return HAL_DATASPACE_SRGB_LINEAR;
Jesse Hallc2e41222013-08-08 13:40:22 -0700434 } else if (colorspace == EGL_GL_COLORSPACE_SRGB_KHR) {
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800435 return HAL_DATASPACE_SRGB;
Jesse Hallc2e41222013-08-08 13:40:22 -0700436 }
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800437 return dataSpace;
Jesse Hallc2e41222013-08-08 13:40:22 -0700438}
439
Mathias Agopian518ec112011-05-13 16:21:08 -0700440EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config,
441 NativeWindowType window,
442 const EGLint *attrib_list)
443{
444 clearError();
445
Jesse Hallb29e5e82012-04-04 16:53:42 -0700446 egl_connection_t* cnx = NULL;
447 egl_display_ptr dp = validate_display_connection(dpy, cnx);
448 if (dp) {
Mathias Agopianada798b2012-02-13 17:09:30 -0800449 EGLDisplay iDpy = dp->disp.dpy;
Mathias Agopian518ec112011-05-13 16:21:08 -0700450
Andy McFaddend566ce32014-01-07 15:54:17 -0800451 int result = native_window_api_connect(window, NATIVE_WINDOW_API_EGL);
452 if (result != OK) {
453 ALOGE("eglCreateWindowSurface: native_window_api_connect (win=%p) "
454 "failed (%#x) (already connected to another API?)",
455 window, result);
Jonathan Hamilton77a9b4a2013-07-17 09:41:42 -0700456 return setError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
Mathias Agopian81a63352011-07-29 17:55:48 -0700457 }
458
Mathias Agopian0f288fc2013-08-21 16:36:34 -0700459 // Set the native window's buffers format to match what this config requests.
Jesse Hallc2e41222013-08-08 13:40:22 -0700460 // Whether to use sRGB gamma is not part of the EGLconfig, but is part
461 // of our native format. So if sRGB gamma is requested, we have to
462 // modify the EGLconfig's format before setting the native window's
463 // format.
Alistair Strachan733a8072015-02-12 12:33:25 -0800464
Mathias Agopian0f288fc2013-08-21 16:36:34 -0700465 // by default, just pick RGBA_8888
466 EGLint format = HAL_PIXEL_FORMAT_RGBA_8888;
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800467 android_dataspace dataSpace = HAL_DATASPACE_UNKNOWN;
Mathias Agopian0f288fc2013-08-21 16:36:34 -0700468
469 EGLint a = 0;
470 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_ALPHA_SIZE, &a);
471 if (a > 0) {
472 // alpha-channel requested, there's really only one suitable format
473 format = HAL_PIXEL_FORMAT_RGBA_8888;
474 } else {
475 EGLint r, g, b;
476 r = g = b = 0;
477 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_RED_SIZE, &r);
478 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_GREEN_SIZE, &g);
479 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_BLUE_SIZE, &b);
480 EGLint colorDepth = r + g + b;
481 if (colorDepth <= 16) {
482 format = HAL_PIXEL_FORMAT_RGB_565;
483 } else {
484 format = HAL_PIXEL_FORMAT_RGBX_8888;
485 }
Jesse Hallc2e41222013-08-08 13:40:22 -0700486 }
Mathias Agopian0f288fc2013-08-21 16:36:34 -0700487
488 // now select a corresponding sRGB format if needed
489 if (attrib_list && dp->haveExtension("EGL_KHR_gl_colorspace")) {
490 for (const EGLint* attr = attrib_list; *attr != EGL_NONE; attr += 2) {
491 if (*attr == EGL_GL_COLORSPACE_KHR) {
Jesse Halla2ba4282013-09-14 21:00:14 -0700492 if (ENABLE_EGL_KHR_GL_COLORSPACE) {
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800493 dataSpace = modifyBufferDataspace(dataSpace, *(attr+1));
Jesse Halla2ba4282013-09-14 21:00:14 -0700494 } else {
495 // Normally we'd pass through unhandled attributes to
496 // the driver. But in case the driver implements this
497 // extension but we're disabling it, we want to prevent
498 // it getting through -- support will be broken without
499 // our help.
500 ALOGE("sRGB window surfaces not supported");
501 return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
502 }
Jamie Gennisbee205f2011-07-01 13:12:07 -0700503 }
Mathias Agopian518ec112011-05-13 16:21:08 -0700504 }
505 }
Alistair Strachan733a8072015-02-12 12:33:25 -0800506
Jesse Hallc2e41222013-08-08 13:40:22 -0700507 if (format != 0) {
508 int err = native_window_set_buffers_format(window, format);
509 if (err != 0) {
510 ALOGE("error setting native window pixel format: %s (%d)",
511 strerror(-err), err);
512 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
513 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
514 }
515 }
Mathias Agopian518ec112011-05-13 16:21:08 -0700516
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800517 if (dataSpace != 0) {
518 int err = native_window_set_buffers_data_space(window, dataSpace);
519 if (err != 0) {
520 ALOGE("error setting native window pixel dataSpace: %s (%d)",
521 strerror(-err), err);
522 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
523 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
524 }
525 }
526
Jamie Gennis59769462011-11-19 18:04:43 -0800527 // the EGL spec requires that a new EGLSurface default to swap interval
528 // 1, so explicitly set that on the window here.
529 ANativeWindow* anw = reinterpret_cast<ANativeWindow*>(window);
530 anw->setSwapInterval(anw, 1);
531
Mathias Agopian518ec112011-05-13 16:21:08 -0700532 EGLSurface surface = cnx->egl.eglCreateWindowSurface(
Mathias Agopian7773c432012-02-13 20:06:08 -0800533 iDpy, config, window, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700534 if (surface != EGL_NO_SURFACE) {
Jesse Hallb29e5e82012-04-04 16:53:42 -0700535 egl_surface_t* s = new egl_surface_t(dp.get(), config, window,
536 surface, cnx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700537 return s;
538 }
Mathias Agopian81a63352011-07-29 17:55:48 -0700539
540 // EGLSurface creation failed
541 native_window_set_buffers_format(window, 0);
542 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
Mathias Agopian518ec112011-05-13 16:21:08 -0700543 }
544 return EGL_NO_SURFACE;
545}
546
547EGLSurface eglCreatePixmapSurface( EGLDisplay dpy, EGLConfig config,
548 NativePixmapType pixmap,
549 const EGLint *attrib_list)
550{
551 clearError();
552
Jesse Hallb29e5e82012-04-04 16:53:42 -0700553 egl_connection_t* cnx = NULL;
554 egl_display_ptr dp = validate_display_connection(dpy, cnx);
555 if (dp) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700556 EGLSurface surface = cnx->egl.eglCreatePixmapSurface(
Mathias Agopian7773c432012-02-13 20:06:08 -0800557 dp->disp.dpy, config, pixmap, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700558 if (surface != EGL_NO_SURFACE) {
Jesse Hallb29e5e82012-04-04 16:53:42 -0700559 egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL,
560 surface, cnx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700561 return s;
562 }
563 }
564 return EGL_NO_SURFACE;
565}
566
567EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config,
568 const EGLint *attrib_list)
569{
570 clearError();
571
Jesse Hallb29e5e82012-04-04 16:53:42 -0700572 egl_connection_t* cnx = NULL;
573 egl_display_ptr dp = validate_display_connection(dpy, cnx);
574 if (dp) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700575 EGLSurface surface = cnx->egl.eglCreatePbufferSurface(
Mathias Agopian7773c432012-02-13 20:06:08 -0800576 dp->disp.dpy, config, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700577 if (surface != EGL_NO_SURFACE) {
Jesse Hallb29e5e82012-04-04 16:53:42 -0700578 egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL,
579 surface, cnx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700580 return s;
581 }
582 }
583 return EGL_NO_SURFACE;
584}
Jesse Hall47743382013-02-08 11:13:46 -0800585
Mathias Agopian518ec112011-05-13 16:21:08 -0700586EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
587{
588 clearError();
589
Jesse Hallb29e5e82012-04-04 16:53:42 -0700590 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700591 if (!dp) return EGL_FALSE;
592
Jesse Hallb29e5e82012-04-04 16:53:42 -0700593 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700594 if (!_s.get())
595 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700596
597 egl_surface_t * const s = get_surface(surface);
Mathias Agopianada798b2012-02-13 17:09:30 -0800598 EGLBoolean result = s->cnx->egl.eglDestroySurface(dp->disp.dpy, s->surface);
Mathias Agopian518ec112011-05-13 16:21:08 -0700599 if (result == EGL_TRUE) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700600 _s.terminate();
601 }
602 return result;
603}
604
605EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface surface,
606 EGLint attribute, EGLint *value)
607{
608 clearError();
609
Jesse Hallb29e5e82012-04-04 16:53:42 -0700610 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700611 if (!dp) return EGL_FALSE;
612
Jesse Hallb29e5e82012-04-04 16:53:42 -0700613 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700614 if (!_s.get())
615 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700616
Mathias Agopian518ec112011-05-13 16:21:08 -0700617 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian7773c432012-02-13 20:06:08 -0800618 return s->cnx->egl.eglQuerySurface(
619 dp->disp.dpy, s->surface, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -0700620}
621
Jamie Gennise8696a42012-01-15 18:54:57 -0800622void EGLAPI eglBeginFrame(EGLDisplay dpy, EGLSurface surface) {
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800623 ATRACE_CALL();
Jamie Gennise8696a42012-01-15 18:54:57 -0800624 clearError();
625
Jesse Hallb29e5e82012-04-04 16:53:42 -0700626 const egl_display_ptr dp = validate_display(dpy);
Jamie Gennise8696a42012-01-15 18:54:57 -0800627 if (!dp) {
628 return;
629 }
630
Jesse Hallb29e5e82012-04-04 16:53:42 -0700631 SurfaceRef _s(dp.get(), surface);
Jamie Gennise8696a42012-01-15 18:54:57 -0800632 if (!_s.get()) {
633 setError(EGL_BAD_SURFACE, EGL_FALSE);
634 return;
635 }
Jamie Gennise8696a42012-01-15 18:54:57 -0800636}
637
Mathias Agopian518ec112011-05-13 16:21:08 -0700638// ----------------------------------------------------------------------------
639// Contexts
640// ----------------------------------------------------------------------------
641
642EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config,
643 EGLContext share_list, const EGLint *attrib_list)
644{
645 clearError();
646
Jesse Hallb29e5e82012-04-04 16:53:42 -0700647 egl_connection_t* cnx = NULL;
648 const egl_display_ptr dp = validate_display_connection(dpy, cnx);
Michael Chock0673e1e2012-06-21 12:53:17 -0700649 if (dp) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700650 if (share_list != EGL_NO_CONTEXT) {
Michael Chock0673e1e2012-06-21 12:53:17 -0700651 if (!ContextRef(dp.get(), share_list).get()) {
652 return setError(EGL_BAD_CONTEXT, EGL_NO_CONTEXT);
653 }
Mathias Agopian518ec112011-05-13 16:21:08 -0700654 egl_context_t* const c = get_context(share_list);
655 share_list = c->context;
656 }
657 EGLContext context = cnx->egl.eglCreateContext(
Mathias Agopian7773c432012-02-13 20:06:08 -0800658 dp->disp.dpy, config, share_list, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700659 if (context != EGL_NO_CONTEXT) {
660 // figure out if it's a GLESv1 or GLESv2
661 int version = 0;
662 if (attrib_list) {
663 while (*attrib_list != EGL_NONE) {
664 GLint attr = *attrib_list++;
665 GLint value = *attrib_list++;
666 if (attr == EGL_CONTEXT_CLIENT_VERSION) {
667 if (value == 1) {
Mathias Agopian7773c432012-02-13 20:06:08 -0800668 version = egl_connection_t::GLESv1_INDEX;
Jesse Hall47743382013-02-08 11:13:46 -0800669 } else if (value == 2 || value == 3) {
Mathias Agopian7773c432012-02-13 20:06:08 -0800670 version = egl_connection_t::GLESv2_INDEX;
Mathias Agopian518ec112011-05-13 16:21:08 -0700671 }
672 }
673 };
674 }
Jesse Hallb29e5e82012-04-04 16:53:42 -0700675 egl_context_t* c = new egl_context_t(dpy, context, config, cnx,
676 version);
Siva Velusamy0469dd62011-11-30 15:05:37 -0800677#if EGL_TRACE
Siva Velusamya73a9772012-12-18 14:56:55 -0800678 if (getEGLDebugLevel() > 0)
Siva Velusamy0469dd62011-11-30 15:05:37 -0800679 GLTrace_eglCreateContext(version, c);
680#endif
Mathias Agopian518ec112011-05-13 16:21:08 -0700681 return c;
682 }
683 }
684 return EGL_NO_CONTEXT;
685}
686
687EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
688{
689 clearError();
690
Jesse Hallb29e5e82012-04-04 16:53:42 -0700691 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700692 if (!dp)
693 return EGL_FALSE;
Mathias Agopian518ec112011-05-13 16:21:08 -0700694
Jesse Hallb29e5e82012-04-04 16:53:42 -0700695 ContextRef _c(dp.get(), ctx);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700696 if (!_c.get())
697 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
Jesse Hall47743382013-02-08 11:13:46 -0800698
Mathias Agopian518ec112011-05-13 16:21:08 -0700699 egl_context_t * const c = get_context(ctx);
Mathias Agopianada798b2012-02-13 17:09:30 -0800700 EGLBoolean result = c->cnx->egl.eglDestroyContext(dp->disp.dpy, c->context);
Mathias Agopian518ec112011-05-13 16:21:08 -0700701 if (result == EGL_TRUE) {
702 _c.terminate();
703 }
704 return result;
705}
706
Mathias Agopian518ec112011-05-13 16:21:08 -0700707EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw,
708 EGLSurface read, EGLContext ctx)
709{
710 clearError();
711
Jesse Hallb29e5e82012-04-04 16:53:42 -0700712 egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700713 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
714
Mathias Agopian5b287a62011-05-16 18:58:55 -0700715 // If ctx is not EGL_NO_CONTEXT, read is not EGL_NO_SURFACE, or draw is not
716 // EGL_NO_SURFACE, then an EGL_NOT_INITIALIZED error is generated if dpy is
717 // a valid but uninitialized display.
Mathias Agopian518ec112011-05-13 16:21:08 -0700718 if ( (ctx != EGL_NO_CONTEXT) || (read != EGL_NO_SURFACE) ||
719 (draw != EGL_NO_SURFACE) ) {
720 if (!dp->isReady()) return setError(EGL_NOT_INITIALIZED, EGL_FALSE);
721 }
722
723 // get a reference to the object passed in
Jesse Hallb29e5e82012-04-04 16:53:42 -0700724 ContextRef _c(dp.get(), ctx);
725 SurfaceRef _d(dp.get(), draw);
726 SurfaceRef _r(dp.get(), read);
Mathias Agopian518ec112011-05-13 16:21:08 -0700727
728 // validate the context (if not EGL_NO_CONTEXT)
Mathias Agopian5b287a62011-05-16 18:58:55 -0700729 if ((ctx != EGL_NO_CONTEXT) && !_c.get()) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700730 // EGL_NO_CONTEXT is valid
Michael Chock0673e1e2012-06-21 12:53:17 -0700731 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700732 }
733
734 // these are the underlying implementation's object
735 EGLContext impl_ctx = EGL_NO_CONTEXT;
736 EGLSurface impl_draw = EGL_NO_SURFACE;
737 EGLSurface impl_read = EGL_NO_SURFACE;
738
739 // these are our objects structs passed in
740 egl_context_t * c = NULL;
741 egl_surface_t const * d = NULL;
742 egl_surface_t const * r = NULL;
743
744 // these are the current objects structs
745 egl_context_t * cur_c = get_context(getContext());
Jesse Hall47743382013-02-08 11:13:46 -0800746
Mathias Agopian518ec112011-05-13 16:21:08 -0700747 if (ctx != EGL_NO_CONTEXT) {
748 c = get_context(ctx);
749 impl_ctx = c->context;
750 } else {
751 // no context given, use the implementation of the current context
Michael Chock0673e1e2012-06-21 12:53:17 -0700752 if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE) {
753 // calling eglMakeCurrent( ..., !=0, !=0, EGL_NO_CONTEXT);
754 return setError(EGL_BAD_MATCH, EGL_FALSE);
755 }
Mathias Agopian518ec112011-05-13 16:21:08 -0700756 if (cur_c == NULL) {
757 // no current context
Mathias Agopian518ec112011-05-13 16:21:08 -0700758 // not an error, there is just no current context.
759 return EGL_TRUE;
760 }
761 }
762
763 // retrieve the underlying implementation's draw EGLSurface
764 if (draw != EGL_NO_SURFACE) {
Michael Chock0673e1e2012-06-21 12:53:17 -0700765 if (!_d.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700766 d = get_surface(draw);
Mathias Agopian518ec112011-05-13 16:21:08 -0700767 impl_draw = d->surface;
768 }
769
770 // retrieve the underlying implementation's read EGLSurface
771 if (read != EGL_NO_SURFACE) {
Michael Chock0673e1e2012-06-21 12:53:17 -0700772 if (!_r.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700773 r = get_surface(read);
Mathias Agopian518ec112011-05-13 16:21:08 -0700774 impl_read = r->surface;
775 }
776
Mathias Agopian518ec112011-05-13 16:21:08 -0700777
Jesse Hallb29e5e82012-04-04 16:53:42 -0700778 EGLBoolean result = dp->makeCurrent(c, cur_c,
Mathias Agopianfb87e542012-01-30 18:20:52 -0800779 draw, read, ctx,
780 impl_draw, impl_read, impl_ctx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700781
782 if (result == EGL_TRUE) {
Mathias Agopianfb87e542012-01-30 18:20:52 -0800783 if (c) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700784 setGLHooksThreadSpecific(c->cnx->hooks[c->version]);
785 egl_tls_t::setContext(ctx);
Siva Velusamy0469dd62011-11-30 15:05:37 -0800786#if EGL_TRACE
Siva Velusamya73a9772012-12-18 14:56:55 -0800787 if (getEGLDebugLevel() > 0)
Siva Velusamy93a826f2011-12-14 12:19:56 -0800788 GLTrace_eglMakeCurrent(c->version, c->cnx->hooks[c->version], ctx);
Siva Velusamy0469dd62011-11-30 15:05:37 -0800789#endif
Mathias Agopian518ec112011-05-13 16:21:08 -0700790 _c.acquire();
791 _r.acquire();
792 _d.acquire();
Mathias Agopian518ec112011-05-13 16:21:08 -0700793 } else {
794 setGLHooksThreadSpecific(&gHooksNoContext);
795 egl_tls_t::setContext(EGL_NO_CONTEXT);
796 }
Mathias Agopian5fecea72011-08-25 18:38:24 -0700797 } else {
Steve Blocke6f43dd2012-01-06 19:20:56 +0000798 // this will ALOGE the error
Mathias Agopian63108c32013-09-06 13:36:49 -0700799 egl_connection_t* const cnx = &gEGLImpl;
800 result = setError(cnx->egl.eglGetError(), EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700801 }
802 return result;
803}
804
805
806EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx,
807 EGLint attribute, EGLint *value)
808{
809 clearError();
810
Jesse Hallb29e5e82012-04-04 16:53:42 -0700811 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700812 if (!dp) return EGL_FALSE;
813
Jesse Hallb29e5e82012-04-04 16:53:42 -0700814 ContextRef _c(dp.get(), ctx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700815 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
816
Mathias Agopian518ec112011-05-13 16:21:08 -0700817 egl_context_t * const c = get_context(ctx);
Mathias Agopian7773c432012-02-13 20:06:08 -0800818 return c->cnx->egl.eglQueryContext(
819 dp->disp.dpy, c->context, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -0700820
Mathias Agopian518ec112011-05-13 16:21:08 -0700821}
822
823EGLContext eglGetCurrentContext(void)
824{
825 // could be called before eglInitialize(), but we wouldn't have a context
826 // then, and this function would correctly return EGL_NO_CONTEXT.
827
828 clearError();
829
830 EGLContext ctx = getContext();
831 return ctx;
832}
833
834EGLSurface eglGetCurrentSurface(EGLint readdraw)
835{
836 // could be called before eglInitialize(), but we wouldn't have a context
837 // then, and this function would correctly return EGL_NO_SURFACE.
838
839 clearError();
840
841 EGLContext ctx = getContext();
842 if (ctx) {
843 egl_context_t const * const c = get_context(ctx);
844 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
845 switch (readdraw) {
846 case EGL_READ: return c->read;
Jesse Hall47743382013-02-08 11:13:46 -0800847 case EGL_DRAW: return c->draw;
Mathias Agopian518ec112011-05-13 16:21:08 -0700848 default: return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
849 }
850 }
851 return EGL_NO_SURFACE;
852}
853
854EGLDisplay eglGetCurrentDisplay(void)
855{
856 // could be called before eglInitialize(), but we wouldn't have a context
857 // then, and this function would correctly return EGL_NO_DISPLAY.
858
859 clearError();
860
861 EGLContext ctx = getContext();
862 if (ctx) {
863 egl_context_t const * const c = get_context(ctx);
864 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
865 return c->dpy;
866 }
867 return EGL_NO_DISPLAY;
868}
869
870EGLBoolean eglWaitGL(void)
871{
Mathias Agopian518ec112011-05-13 16:21:08 -0700872 clearError();
873
Mathias Agopianada798b2012-02-13 17:09:30 -0800874 egl_connection_t* const cnx = &gEGLImpl;
875 if (!cnx->dso)
876 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
877
878 return cnx->egl.eglWaitGL();
Mathias Agopian518ec112011-05-13 16:21:08 -0700879}
880
881EGLBoolean eglWaitNative(EGLint engine)
882{
Mathias Agopian518ec112011-05-13 16:21:08 -0700883 clearError();
884
Mathias Agopianada798b2012-02-13 17:09:30 -0800885 egl_connection_t* const cnx = &gEGLImpl;
886 if (!cnx->dso)
887 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
888
889 return cnx->egl.eglWaitNative(engine);
Mathias Agopian518ec112011-05-13 16:21:08 -0700890}
891
892EGLint eglGetError(void)
893{
Mathias Agopianada798b2012-02-13 17:09:30 -0800894 EGLint err = EGL_SUCCESS;
895 egl_connection_t* const cnx = &gEGLImpl;
896 if (cnx->dso) {
897 err = cnx->egl.eglGetError();
Mathias Agopian518ec112011-05-13 16:21:08 -0700898 }
Mathias Agopianada798b2012-02-13 17:09:30 -0800899 if (err == EGL_SUCCESS) {
900 err = egl_tls_t::getError();
901 }
902 return err;
Mathias Agopian518ec112011-05-13 16:21:08 -0700903}
904
Michael Chockc0ec5e22014-01-27 08:14:33 -0800905static __eglMustCastToProperFunctionPointerType findBuiltinWrapper(
Jesse Hallc07b5202013-07-04 12:08:16 -0700906 const char* procname) {
907 const egl_connection_t* cnx = &gEGLImpl;
908 void* proc = NULL;
909
Michael Chockc0ec5e22014-01-27 08:14:33 -0800910 proc = dlsym(cnx->libEgl, procname);
911 if (proc) return (__eglMustCastToProperFunctionPointerType)proc;
912
Jesse Hallc07b5202013-07-04 12:08:16 -0700913 proc = dlsym(cnx->libGles2, procname);
914 if (proc) return (__eglMustCastToProperFunctionPointerType)proc;
915
916 proc = dlsym(cnx->libGles1, procname);
917 if (proc) return (__eglMustCastToProperFunctionPointerType)proc;
918
919 return NULL;
920}
921
Mathias Agopian518ec112011-05-13 16:21:08 -0700922__eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
923{
924 // eglGetProcAddress() could be the very first function called
925 // in which case we must make sure we've initialized ourselves, this
926 // happens the first time egl_get_display() is called.
927
928 clearError();
929
930 if (egl_init_drivers() == EGL_FALSE) {
931 setError(EGL_BAD_PARAMETER, NULL);
932 return NULL;
933 }
934
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700935 if (FILTER_EXTENSIONS(procname)) {
Jamie Gennisaca51c02011-11-03 17:42:43 -0700936 return NULL;
937 }
938
Mathias Agopian518ec112011-05-13 16:21:08 -0700939 __eglMustCastToProperFunctionPointerType addr;
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700940 addr = findProcAddress(procname, sExtensionMap, NELEM(sExtensionMap));
Mathias Agopian518ec112011-05-13 16:21:08 -0700941 if (addr) return addr;
942
Michael Chockc0ec5e22014-01-27 08:14:33 -0800943 addr = findBuiltinWrapper(procname);
Jesse Hallc07b5202013-07-04 12:08:16 -0700944 if (addr) return addr;
Jamie Gennisaca51c02011-11-03 17:42:43 -0700945
Mathias Agopian518ec112011-05-13 16:21:08 -0700946 // this protects accesses to sGLExtentionMap and sGLExtentionSlot
947 pthread_mutex_lock(&sExtensionMapMutex);
948
949 /*
950 * Since eglGetProcAddress() is not associated to anything, it needs
951 * to return a function pointer that "works" regardless of what
952 * the current context is.
953 *
954 * For this reason, we return a "forwarder", a small stub that takes
955 * care of calling the function associated with the context
956 * currently bound.
957 *
958 * We first look for extensions we've already resolved, if we're seeing
959 * this extension for the first time, we go through all our
960 * implementations and call eglGetProcAddress() and record the
961 * result in the appropriate implementation hooks and return the
962 * address of the forwarder corresponding to that hook set.
963 *
964 */
965
966 const String8 name(procname);
967 addr = sGLExtentionMap.valueFor(name);
968 const int slot = sGLExtentionSlot;
969
Steve Blocke6f43dd2012-01-06 19:20:56 +0000970 ALOGE_IF(slot >= MAX_NUMBER_OF_GL_EXTENSIONS,
Mathias Agopian518ec112011-05-13 16:21:08 -0700971 "no more slots for eglGetProcAddress(\"%s\")",
972 procname);
973
Siva Velusamy0469dd62011-11-30 15:05:37 -0800974#if EGL_TRACE
975 gl_hooks_t *debugHooks = GLTrace_getGLHooks();
976#endif
977
Mathias Agopian518ec112011-05-13 16:21:08 -0700978 if (!addr && (slot < MAX_NUMBER_OF_GL_EXTENSIONS)) {
979 bool found = false;
Mathias Agopianada798b2012-02-13 17:09:30 -0800980
981 egl_connection_t* const cnx = &gEGLImpl;
982 if (cnx->dso && cnx->egl.eglGetProcAddress) {
Mathias Agopianada798b2012-02-13 17:09:30 -0800983 // Extensions are independent of the bound context
luliuhui69d10072012-08-30 11:15:36 +0800984 addr =
Mathias Agopian7773c432012-02-13 20:06:08 -0800985 cnx->hooks[egl_connection_t::GLESv1_INDEX]->ext.extensions[slot] =
986 cnx->hooks[egl_connection_t::GLESv2_INDEX]->ext.extensions[slot] =
Mathias Agopian518ec112011-05-13 16:21:08 -0700987#if EGL_TRACE
Mathias Agopianada798b2012-02-13 17:09:30 -0800988 debugHooks->ext.extensions[slot] =
989 gHooksTrace.ext.extensions[slot] =
Mathias Agopian518ec112011-05-13 16:21:08 -0700990#endif
Mathias Agopianada798b2012-02-13 17:09:30 -0800991 cnx->egl.eglGetProcAddress(procname);
luliuhui69d10072012-08-30 11:15:36 +0800992 if (addr) found = true;
Mathias Agopian518ec112011-05-13 16:21:08 -0700993 }
Mathias Agopianada798b2012-02-13 17:09:30 -0800994
Mathias Agopian518ec112011-05-13 16:21:08 -0700995 if (found) {
996 addr = gExtensionForwarders[slot];
Mathias Agopian518ec112011-05-13 16:21:08 -0700997 sGLExtentionMap.add(name, addr);
998 sGLExtentionSlot++;
999 }
1000 }
1001
1002 pthread_mutex_unlock(&sExtensionMapMutex);
1003 return addr;
1004}
1005
Jamie Gennis28ef8d72012-04-05 20:34:54 -07001006class FrameCompletionThread : public Thread {
1007public:
1008
1009 static void queueSync(EGLSyncKHR sync) {
1010 static sp<FrameCompletionThread> thread(new FrameCompletionThread);
1011 static bool running = false;
1012 if (!running) {
1013 thread->run("GPUFrameCompletion");
1014 running = true;
1015 }
1016 {
1017 Mutex::Autolock lock(thread->mMutex);
1018 ScopedTrace st(ATRACE_TAG, String8::format("kicked off frame %d",
1019 thread->mFramesQueued).string());
1020 thread->mQueue.push_back(sync);
1021 thread->mCondition.signal();
1022 thread->mFramesQueued++;
1023 ATRACE_INT("GPU Frames Outstanding", thread->mQueue.size());
1024 }
1025 }
1026
1027private:
1028 FrameCompletionThread() : mFramesQueued(0), mFramesCompleted(0) {}
1029
1030 virtual bool threadLoop() {
1031 EGLSyncKHR sync;
1032 uint32_t frameNum;
1033 {
1034 Mutex::Autolock lock(mMutex);
1035 while (mQueue.isEmpty()) {
1036 mCondition.wait(mMutex);
1037 }
1038 sync = mQueue[0];
1039 frameNum = mFramesCompleted;
1040 }
1041 EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
1042 {
1043 ScopedTrace st(ATRACE_TAG, String8::format("waiting for frame %d",
1044 frameNum).string());
1045 EGLint result = eglClientWaitSyncKHR(dpy, sync, 0, EGL_FOREVER_KHR);
1046 if (result == EGL_FALSE) {
1047 ALOGE("FrameCompletion: error waiting for fence: %#x", eglGetError());
1048 } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
1049 ALOGE("FrameCompletion: timeout waiting for fence");
1050 }
1051 eglDestroySyncKHR(dpy, sync);
1052 }
1053 {
1054 Mutex::Autolock lock(mMutex);
1055 mQueue.removeAt(0);
1056 mFramesCompleted++;
1057 ATRACE_INT("GPU Frames Outstanding", mQueue.size());
1058 }
1059 return true;
1060 }
1061
1062 uint32_t mFramesQueued;
1063 uint32_t mFramesCompleted;
1064 Vector<EGLSyncKHR> mQueue;
1065 Condition mCondition;
1066 Mutex mMutex;
1067};
1068
Dan Stozaa894d082015-02-19 15:27:36 -08001069EGLBoolean eglSwapBuffersWithDamageKHR(EGLDisplay dpy, EGLSurface draw,
1070 EGLint *rects, EGLint n_rects)
Mathias Agopian518ec112011-05-13 16:21:08 -07001071{
Jamie Gennis1c8e95c2012-02-23 19:27:23 -08001072 ATRACE_CALL();
Mathias Agopian518ec112011-05-13 16:21:08 -07001073 clearError();
1074
Jesse Hallb29e5e82012-04-04 16:53:42 -07001075 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001076 if (!dp) return EGL_FALSE;
1077
Jesse Hallb29e5e82012-04-04 16:53:42 -07001078 SurfaceRef _s(dp.get(), draw);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001079 if (!_s.get())
1080 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001081
Siva Velusamy0469dd62011-11-30 15:05:37 -08001082#if EGL_TRACE
Siva Velusamya73a9772012-12-18 14:56:55 -08001083 gl_hooks_t const *trace_hooks = getGLTraceThreadSpecific();
1084 if (getEGLDebugLevel() > 0) {
1085 if (trace_hooks == NULL) {
1086 if (GLTrace_start() < 0) {
1087 ALOGE("Disabling Tracer for OpenGL ES");
1088 setEGLDebugLevel(0);
1089 } else {
1090 // switch over to the trace version of hooks
1091 EGLContext ctx = egl_tls_t::getContext();
1092 egl_context_t * const c = get_context(ctx);
1093 if (c) {
1094 setGLHooksThreadSpecific(c->cnx->hooks[c->version]);
1095 GLTrace_eglMakeCurrent(c->version, c->cnx->hooks[c->version], ctx);
1096 }
1097 }
1098 }
1099
Siva Velusamy0469dd62011-11-30 15:05:37 -08001100 GLTrace_eglSwapBuffers(dpy, draw);
Siva Velusamya73a9772012-12-18 14:56:55 -08001101 } else if (trace_hooks != NULL) {
1102 // tracing is now disabled, so switch back to the non trace version
1103 EGLContext ctx = egl_tls_t::getContext();
1104 egl_context_t * const c = get_context(ctx);
1105 if (c) setGLHooksThreadSpecific(c->cnx->hooks[c->version]);
1106 GLTrace_stop();
1107 }
Siva Velusamy0469dd62011-11-30 15:05:37 -08001108#endif
1109
Mathias Agopian518ec112011-05-13 16:21:08 -07001110 egl_surface_t const * const s = get_surface(draw);
Mathias Agopian7db993a2012-03-25 00:49:46 -07001111
Mathias Agopianed6d08b2013-04-16 16:39:46 -07001112 if (CC_UNLIKELY(dp->traceGpuCompletion)) {
1113 EGLSyncKHR sync = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, NULL);
1114 if (sync != EGL_NO_SYNC_KHR) {
1115 FrameCompletionThread::queueSync(sync);
1116 }
1117 }
1118
Mathias Agopian7db993a2012-03-25 00:49:46 -07001119 if (CC_UNLIKELY(dp->finishOnSwap)) {
1120 uint32_t pixel;
1121 egl_context_t * const c = get_context( egl_tls_t::getContext() );
1122 if (c) {
1123 // glReadPixels() ensures that the frame is complete
1124 s->cnx->hooks[c->version]->gl.glReadPixels(0,0,1,1,
1125 GL_RGBA,GL_UNSIGNED_BYTE,&pixel);
1126 }
1127 }
1128
Dan Stozaa894d082015-02-19 15:27:36 -08001129 if (n_rects == 0) {
1130 return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface);
1131 }
1132
1133 Vector<android_native_rect_t> androidRects;
1134 for (int r = 0; r < n_rects; ++r) {
1135 int offset = r * 4;
1136 int x = rects[offset];
1137 int y = rects[offset + 1];
1138 int width = rects[offset + 2];
1139 int height = rects[offset + 3];
1140 android_native_rect_t androidRect;
1141 androidRect.left = x;
1142 androidRect.top = y + height;
1143 androidRect.right = x + width;
1144 androidRect.bottom = y;
1145 androidRects.push_back(androidRect);
1146 }
1147 native_window_set_surface_damage(s->win.get(), androidRects.array(),
1148 androidRects.size());
1149
1150 if (s->cnx->egl.eglSwapBuffersWithDamageKHR) {
1151 return s->cnx->egl.eglSwapBuffersWithDamageKHR(dp->disp.dpy, s->surface,
1152 rects, n_rects);
1153 } else {
1154 return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface);
1155 }
1156}
1157
1158EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
1159{
1160 return eglSwapBuffersWithDamageKHR(dpy, surface, NULL, 0);
Mathias Agopian518ec112011-05-13 16:21:08 -07001161}
1162
1163EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface,
1164 NativePixmapType target)
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
Jesse Hallb29e5e82012-04-04 16:53:42 -07001171 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001172 if (!_s.get())
1173 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001174
Mathias Agopian518ec112011-05-13 16:21:08 -07001175 egl_surface_t const * const s = get_surface(surface);
Mathias Agopianada798b2012-02-13 17:09:30 -08001176 return s->cnx->egl.eglCopyBuffers(dp->disp.dpy, s->surface, target);
Mathias Agopian518ec112011-05-13 16:21:08 -07001177}
1178
1179const char* eglQueryString(EGLDisplay dpy, EGLint name)
1180{
1181 clearError();
1182
Jesse Hallb29e5e82012-04-04 16:53:42 -07001183 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001184 if (!dp) return (const char *) NULL;
1185
1186 switch (name) {
1187 case EGL_VENDOR:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001188 return dp->getVendorString();
Mathias Agopian518ec112011-05-13 16:21:08 -07001189 case EGL_VERSION:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001190 return dp->getVersionString();
Mathias Agopian518ec112011-05-13 16:21:08 -07001191 case EGL_EXTENSIONS:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001192 return dp->getExtensionString();
Mathias Agopian518ec112011-05-13 16:21:08 -07001193 case EGL_CLIENT_APIS:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001194 return dp->getClientApiString();
Mathias Agopian518ec112011-05-13 16:21:08 -07001195 }
1196 return setError(EGL_BAD_PARAMETER, (const char *)0);
1197}
1198
Mathias Agopianca088332013-03-28 17:44:13 -07001199EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name)
1200{
1201 clearError();
1202
1203 const egl_display_ptr dp = validate_display(dpy);
1204 if (!dp) return (const char *) NULL;
1205
1206 switch (name) {
1207 case EGL_VENDOR:
1208 return dp->disp.queryString.vendor;
1209 case EGL_VERSION:
1210 return dp->disp.queryString.version;
1211 case EGL_EXTENSIONS:
1212 return dp->disp.queryString.extensions;
1213 case EGL_CLIENT_APIS:
1214 return dp->disp.queryString.clientApi;
1215 }
1216 return setError(EGL_BAD_PARAMETER, (const char *)0);
1217}
Mathias Agopian518ec112011-05-13 16:21:08 -07001218
1219// ----------------------------------------------------------------------------
1220// EGL 1.1
1221// ----------------------------------------------------------------------------
1222
1223EGLBoolean eglSurfaceAttrib(
1224 EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
1225{
1226 clearError();
1227
Jesse Hallb29e5e82012-04-04 16:53:42 -07001228 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001229 if (!dp) return EGL_FALSE;
1230
Jesse Hallb29e5e82012-04-04 16:53:42 -07001231 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001232 if (!_s.get())
1233 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001234
Mathias Agopian518ec112011-05-13 16:21:08 -07001235 egl_surface_t const * const s = get_surface(surface);
1236 if (s->cnx->egl.eglSurfaceAttrib) {
1237 return s->cnx->egl.eglSurfaceAttrib(
Mathias Agopianada798b2012-02-13 17:09:30 -08001238 dp->disp.dpy, s->surface, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -07001239 }
1240 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1241}
1242
1243EGLBoolean eglBindTexImage(
1244 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1245{
1246 clearError();
1247
Jesse Hallb29e5e82012-04-04 16:53:42 -07001248 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001249 if (!dp) return EGL_FALSE;
1250
Jesse Hallb29e5e82012-04-04 16:53:42 -07001251 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001252 if (!_s.get())
1253 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001254
Mathias Agopian518ec112011-05-13 16:21:08 -07001255 egl_surface_t const * const s = get_surface(surface);
1256 if (s->cnx->egl.eglBindTexImage) {
1257 return s->cnx->egl.eglBindTexImage(
Mathias Agopianada798b2012-02-13 17:09:30 -08001258 dp->disp.dpy, s->surface, buffer);
Mathias Agopian518ec112011-05-13 16:21:08 -07001259 }
1260 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1261}
1262
1263EGLBoolean eglReleaseTexImage(
1264 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1265{
1266 clearError();
1267
Jesse Hallb29e5e82012-04-04 16:53:42 -07001268 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001269 if (!dp) return EGL_FALSE;
1270
Jesse Hallb29e5e82012-04-04 16:53:42 -07001271 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001272 if (!_s.get())
1273 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001274
Mathias Agopian518ec112011-05-13 16:21:08 -07001275 egl_surface_t const * const s = get_surface(surface);
1276 if (s->cnx->egl.eglReleaseTexImage) {
1277 return s->cnx->egl.eglReleaseTexImage(
Mathias Agopianada798b2012-02-13 17:09:30 -08001278 dp->disp.dpy, s->surface, buffer);
Mathias Agopian518ec112011-05-13 16:21:08 -07001279 }
1280 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1281}
1282
1283EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
1284{
1285 clearError();
1286
Jesse Hallb29e5e82012-04-04 16:53:42 -07001287 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001288 if (!dp) return EGL_FALSE;
1289
1290 EGLBoolean res = EGL_TRUE;
Mathias Agopianada798b2012-02-13 17:09:30 -08001291 egl_connection_t* const cnx = &gEGLImpl;
1292 if (cnx->dso && cnx->egl.eglSwapInterval) {
1293 res = cnx->egl.eglSwapInterval(dp->disp.dpy, interval);
Mathias Agopian518ec112011-05-13 16:21:08 -07001294 }
Mathias Agopianada798b2012-02-13 17:09:30 -08001295
Mathias Agopian518ec112011-05-13 16:21:08 -07001296 return res;
1297}
1298
1299
1300// ----------------------------------------------------------------------------
1301// EGL 1.2
1302// ----------------------------------------------------------------------------
1303
1304EGLBoolean eglWaitClient(void)
1305{
1306 clearError();
1307
Mathias Agopianada798b2012-02-13 17:09:30 -08001308 egl_connection_t* const cnx = &gEGLImpl;
1309 if (!cnx->dso)
1310 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1311
1312 EGLBoolean res;
1313 if (cnx->egl.eglWaitClient) {
1314 res = cnx->egl.eglWaitClient();
1315 } else {
1316 res = cnx->egl.eglWaitGL();
Mathias Agopian518ec112011-05-13 16:21:08 -07001317 }
1318 return res;
1319}
1320
1321EGLBoolean eglBindAPI(EGLenum api)
1322{
1323 clearError();
1324
1325 if (egl_init_drivers() == EGL_FALSE) {
1326 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1327 }
1328
1329 // bind this API on all EGLs
1330 EGLBoolean res = EGL_TRUE;
Mathias Agopianada798b2012-02-13 17:09:30 -08001331 egl_connection_t* const cnx = &gEGLImpl;
1332 if (cnx->dso && cnx->egl.eglBindAPI) {
1333 res = cnx->egl.eglBindAPI(api);
Mathias Agopian518ec112011-05-13 16:21:08 -07001334 }
1335 return res;
1336}
1337
1338EGLenum eglQueryAPI(void)
1339{
1340 clearError();
1341
1342 if (egl_init_drivers() == EGL_FALSE) {
1343 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1344 }
1345
Mathias Agopianada798b2012-02-13 17:09:30 -08001346 egl_connection_t* const cnx = &gEGLImpl;
1347 if (cnx->dso && cnx->egl.eglQueryAPI) {
1348 return cnx->egl.eglQueryAPI();
Mathias Agopian518ec112011-05-13 16:21:08 -07001349 }
Mathias Agopianada798b2012-02-13 17:09:30 -08001350
Mathias Agopian518ec112011-05-13 16:21:08 -07001351 // or, it can only be OpenGL ES
1352 return EGL_OPENGL_ES_API;
1353}
1354
1355EGLBoolean eglReleaseThread(void)
1356{
1357 clearError();
1358
Mathias Agopian4e620dd2013-05-30 16:07:36 -07001359#if EGL_TRACE
1360 if (getEGLDebugLevel() > 0)
1361 GLTrace_eglReleaseThread();
1362#endif
1363
Mathias Agopian518ec112011-05-13 16:21:08 -07001364 // If there is context bound to the thread, release it
Mathias Agopianfb87e542012-01-30 18:20:52 -08001365 egl_display_t::loseCurrent(get_context(getContext()));
Mathias Agopian518ec112011-05-13 16:21:08 -07001366
Mathias Agopianada798b2012-02-13 17:09:30 -08001367 egl_connection_t* const cnx = &gEGLImpl;
1368 if (cnx->dso && cnx->egl.eglReleaseThread) {
1369 cnx->egl.eglReleaseThread();
Mathias Agopian518ec112011-05-13 16:21:08 -07001370 }
1371 egl_tls_t::clearTLS();
Mathias Agopian518ec112011-05-13 16:21:08 -07001372 return EGL_TRUE;
1373}
1374
1375EGLSurface eglCreatePbufferFromClientBuffer(
1376 EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer,
1377 EGLConfig config, const EGLint *attrib_list)
1378{
1379 clearError();
1380
Jesse Hallb29e5e82012-04-04 16:53:42 -07001381 egl_connection_t* cnx = NULL;
1382 const egl_display_ptr dp = validate_display_connection(dpy, cnx);
1383 if (!dp) return EGL_FALSE;
Mathias Agopian518ec112011-05-13 16:21:08 -07001384 if (cnx->egl.eglCreatePbufferFromClientBuffer) {
1385 return cnx->egl.eglCreatePbufferFromClientBuffer(
Mathias Agopian7773c432012-02-13 20:06:08 -08001386 dp->disp.dpy, buftype, buffer, config, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001387 }
1388 return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE);
1389}
1390
1391// ----------------------------------------------------------------------------
1392// EGL_EGLEXT_VERSION 3
1393// ----------------------------------------------------------------------------
1394
1395EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface,
1396 const EGLint *attrib_list)
1397{
1398 clearError();
1399
Jesse Hallb29e5e82012-04-04 16:53:42 -07001400 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001401 if (!dp) return EGL_FALSE;
1402
Jesse Hallb29e5e82012-04-04 16:53:42 -07001403 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001404 if (!_s.get())
1405 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001406
1407 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian518ec112011-05-13 16:21:08 -07001408 if (s->cnx->egl.eglLockSurfaceKHR) {
1409 return s->cnx->egl.eglLockSurfaceKHR(
Mathias Agopianada798b2012-02-13 17:09:30 -08001410 dp->disp.dpy, s->surface, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001411 }
1412 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1413}
1414
1415EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface)
1416{
1417 clearError();
1418
Jesse Hallb29e5e82012-04-04 16:53:42 -07001419 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001420 if (!dp) return EGL_FALSE;
1421
Jesse Hallb29e5e82012-04-04 16:53:42 -07001422 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001423 if (!_s.get())
1424 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001425
1426 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian518ec112011-05-13 16:21:08 -07001427 if (s->cnx->egl.eglUnlockSurfaceKHR) {
Mathias Agopianada798b2012-02-13 17:09:30 -08001428 return s->cnx->egl.eglUnlockSurfaceKHR(dp->disp.dpy, s->surface);
Mathias Agopian518ec112011-05-13 16:21:08 -07001429 }
1430 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1431}
1432
1433EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
1434 EGLClientBuffer buffer, const EGLint *attrib_list)
1435{
1436 clearError();
1437
Jesse Hallb29e5e82012-04-04 16:53:42 -07001438 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001439 if (!dp) return EGL_NO_IMAGE_KHR;
1440
Jesse Hallb29e5e82012-04-04 16:53:42 -07001441 ContextRef _c(dp.get(), ctx);
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001442 egl_context_t * const c = _c.get();
Mathias Agopian518ec112011-05-13 16:21:08 -07001443
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001444 EGLImageKHR result = EGL_NO_IMAGE_KHR;
1445 egl_connection_t* const cnx = &gEGLImpl;
1446 if (cnx->dso && cnx->egl.eglCreateImageKHR) {
1447 result = cnx->egl.eglCreateImageKHR(
1448 dp->disp.dpy,
1449 c ? c->context : EGL_NO_CONTEXT,
1450 target, buffer, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001451 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001452 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001453}
1454
1455EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
1456{
1457 clearError();
1458
Jesse Hallb29e5e82012-04-04 16:53:42 -07001459 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001460 if (!dp) return EGL_FALSE;
1461
Steven Holte646a5c52012-06-04 20:02:11 -07001462 EGLBoolean result = EGL_FALSE;
Mathias Agopianada798b2012-02-13 17:09:30 -08001463 egl_connection_t* const cnx = &gEGLImpl;
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001464 if (cnx->dso && cnx->egl.eglDestroyImageKHR) {
Steven Holte646a5c52012-06-04 20:02:11 -07001465 result = cnx->egl.eglDestroyImageKHR(dp->disp.dpy, img);
Mathias Agopian518ec112011-05-13 16:21:08 -07001466 }
Steven Holte646a5c52012-06-04 20:02:11 -07001467 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001468}
1469
1470// ----------------------------------------------------------------------------
1471// EGL_EGLEXT_VERSION 5
1472// ----------------------------------------------------------------------------
1473
1474
1475EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
1476{
1477 clearError();
1478
Jesse Hallb29e5e82012-04-04 16:53:42 -07001479 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001480 if (!dp) return EGL_NO_SYNC_KHR;
1481
Mathias Agopian518ec112011-05-13 16:21:08 -07001482 EGLSyncKHR result = EGL_NO_SYNC_KHR;
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001483 egl_connection_t* const cnx = &gEGLImpl;
1484 if (cnx->dso && cnx->egl.eglCreateSyncKHR) {
1485 result = cnx->egl.eglCreateSyncKHR(dp->disp.dpy, type, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001486 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001487 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001488}
1489
1490EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
1491{
1492 clearError();
1493
Jesse Hallb29e5e82012-04-04 16:53:42 -07001494 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001495 if (!dp) return EGL_FALSE;
1496
Mathias Agopian518ec112011-05-13 16:21:08 -07001497 EGLBoolean result = EGL_FALSE;
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001498 egl_connection_t* const cnx = &gEGLImpl;
1499 if (cnx->dso && cnx->egl.eglDestroySyncKHR) {
1500 result = cnx->egl.eglDestroySyncKHR(dp->disp.dpy, sync);
Mathias Agopian518ec112011-05-13 16:21:08 -07001501 }
1502 return result;
1503}
1504
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -07001505EGLBoolean eglSignalSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode) {
1506 clearError();
1507
1508 const egl_display_ptr dp = validate_display(dpy);
1509 if (!dp) return EGL_FALSE;
1510
1511 EGLBoolean result = EGL_FALSE;
1512 egl_connection_t* const cnx = &gEGLImpl;
1513 if (cnx->dso && cnx->egl.eglSignalSyncKHR) {
1514 result = cnx->egl.eglSignalSyncKHR(
1515 dp->disp.dpy, sync, mode);
1516 }
1517 return result;
1518}
1519
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001520EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync,
1521 EGLint flags, EGLTimeKHR timeout)
Mathias Agopian518ec112011-05-13 16:21:08 -07001522{
1523 clearError();
1524
Jesse Hallb29e5e82012-04-04 16:53:42 -07001525 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001526 if (!dp) return EGL_FALSE;
1527
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001528 EGLBoolean result = EGL_FALSE;
1529 egl_connection_t* const cnx = &gEGLImpl;
1530 if (cnx->dso && cnx->egl.eglClientWaitSyncKHR) {
1531 result = cnx->egl.eglClientWaitSyncKHR(
1532 dp->disp.dpy, sync, flags, timeout);
Mathias Agopian518ec112011-05-13 16:21:08 -07001533 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001534 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001535}
1536
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001537EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync,
1538 EGLint attribute, EGLint *value)
Mathias Agopian518ec112011-05-13 16:21:08 -07001539{
1540 clearError();
1541
Jesse Hallb29e5e82012-04-04 16:53:42 -07001542 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001543 if (!dp) return EGL_FALSE;
1544
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001545 EGLBoolean result = EGL_FALSE;
1546 egl_connection_t* const cnx = &gEGLImpl;
1547 if (cnx->dso && cnx->egl.eglGetSyncAttribKHR) {
1548 result = cnx->egl.eglGetSyncAttribKHR(
1549 dp->disp.dpy, sync, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -07001550 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001551 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001552}
1553
Season Li000d88f2015-07-01 11:39:40 -07001554EGLStreamKHR eglCreateStreamKHR(EGLDisplay dpy, const EGLint *attrib_list)
1555{
1556 clearError();
1557
1558 const egl_display_ptr dp = validate_display(dpy);
1559 if (!dp) return EGL_NO_STREAM_KHR;
1560
1561 EGLStreamKHR result = EGL_NO_STREAM_KHR;
1562 egl_connection_t* const cnx = &gEGLImpl;
1563 if (cnx->dso && cnx->egl.eglCreateStreamKHR) {
1564 result = cnx->egl.eglCreateStreamKHR(
1565 dp->disp.dpy, attrib_list);
1566 }
1567 return result;
1568}
1569
1570EGLBoolean eglDestroyStreamKHR(EGLDisplay dpy, EGLStreamKHR stream)
1571{
1572 clearError();
1573
1574 const egl_display_ptr dp = validate_display(dpy);
1575 if (!dp) return EGL_FALSE;
1576
1577 EGLBoolean result = EGL_FALSE;
1578 egl_connection_t* const cnx = &gEGLImpl;
1579 if (cnx->dso && cnx->egl.eglDestroyStreamKHR) {
1580 result = cnx->egl.eglDestroyStreamKHR(
1581 dp->disp.dpy, stream);
1582 }
1583 return result;
1584}
1585
1586EGLBoolean eglStreamAttribKHR(EGLDisplay dpy, EGLStreamKHR stream,
1587 EGLenum attribute, EGLint value)
1588{
1589 clearError();
1590
1591 const egl_display_ptr dp = validate_display(dpy);
1592 if (!dp) return EGL_FALSE;
1593
1594 EGLBoolean result = EGL_FALSE;
1595 egl_connection_t* const cnx = &gEGLImpl;
1596 if (cnx->dso && cnx->egl.eglStreamAttribKHR) {
1597 result = cnx->egl.eglStreamAttribKHR(
1598 dp->disp.dpy, stream, attribute, value);
1599 }
1600 return result;
1601}
1602
1603EGLBoolean eglQueryStreamKHR(EGLDisplay dpy, EGLStreamKHR stream,
1604 EGLenum attribute, EGLint *value)
1605{
1606 clearError();
1607
1608 const egl_display_ptr dp = validate_display(dpy);
1609 if (!dp) return EGL_FALSE;
1610
1611 EGLBoolean result = EGL_FALSE;
1612 egl_connection_t* const cnx = &gEGLImpl;
1613 if (cnx->dso && cnx->egl.eglQueryStreamKHR) {
1614 result = cnx->egl.eglQueryStreamKHR(
1615 dp->disp.dpy, stream, attribute, value);
1616 }
1617 return result;
1618}
1619
1620EGLBoolean eglQueryStreamu64KHR(EGLDisplay dpy, EGLStreamKHR stream,
1621 EGLenum attribute, EGLuint64KHR *value)
1622{
1623 clearError();
1624
1625 const egl_display_ptr dp = validate_display(dpy);
1626 if (!dp) return EGL_FALSE;
1627
1628 EGLBoolean result = EGL_FALSE;
1629 egl_connection_t* const cnx = &gEGLImpl;
1630 if (cnx->dso && cnx->egl.eglQueryStreamu64KHR) {
1631 result = cnx->egl.eglQueryStreamu64KHR(
1632 dp->disp.dpy, stream, attribute, value);
1633 }
1634 return result;
1635}
1636
1637EGLBoolean eglQueryStreamTimeKHR(EGLDisplay dpy, EGLStreamKHR stream,
1638 EGLenum attribute, EGLTimeKHR *value)
1639{
1640 clearError();
1641
1642 const egl_display_ptr dp = validate_display(dpy);
1643 if (!dp) return EGL_FALSE;
1644
1645 EGLBoolean result = EGL_FALSE;
1646 egl_connection_t* const cnx = &gEGLImpl;
1647 if (cnx->dso && cnx->egl.eglQueryStreamTimeKHR) {
1648 result = cnx->egl.eglQueryStreamTimeKHR(
1649 dp->disp.dpy, stream, attribute, value);
1650 }
1651 return result;
1652}
1653
1654EGLSurface eglCreateStreamProducerSurfaceKHR(EGLDisplay dpy, EGLConfig config,
1655 EGLStreamKHR stream, const EGLint *attrib_list)
1656{
1657 clearError();
1658
1659 egl_display_ptr dp = validate_display(dpy);
1660 if (!dp) return EGL_NO_SURFACE;
1661
1662 egl_connection_t* const cnx = &gEGLImpl;
1663 if (cnx->dso && cnx->egl.eglCreateStreamProducerSurfaceKHR) {
1664 EGLSurface surface = cnx->egl.eglCreateStreamProducerSurfaceKHR(
1665 dp->disp.dpy, config, stream, attrib_list);
1666 if (surface != EGL_NO_SURFACE) {
1667 egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL,
1668 surface, cnx);
1669 return s;
1670 }
1671 }
1672 return EGL_NO_SURFACE;
1673}
1674
1675EGLBoolean eglStreamConsumerGLTextureExternalKHR(EGLDisplay dpy,
1676 EGLStreamKHR stream)
1677{
1678 clearError();
1679
1680 const egl_display_ptr dp = validate_display(dpy);
1681 if (!dp) return EGL_FALSE;
1682
1683 EGLBoolean result = EGL_FALSE;
1684 egl_connection_t* const cnx = &gEGLImpl;
1685 if (cnx->dso && cnx->egl.eglStreamConsumerGLTextureExternalKHR) {
1686 result = cnx->egl.eglStreamConsumerGLTextureExternalKHR(
1687 dp->disp.dpy, stream);
1688 }
1689 return result;
1690}
1691
1692EGLBoolean eglStreamConsumerAcquireKHR(EGLDisplay dpy,
1693 EGLStreamKHR stream)
1694{
1695 clearError();
1696
1697 const egl_display_ptr dp = validate_display(dpy);
1698 if (!dp) return EGL_FALSE;
1699
1700 EGLBoolean result = EGL_FALSE;
1701 egl_connection_t* const cnx = &gEGLImpl;
1702 if (cnx->dso && cnx->egl.eglStreamConsumerAcquireKHR) {
1703 result = cnx->egl.eglStreamConsumerAcquireKHR(
1704 dp->disp.dpy, stream);
1705 }
1706 return result;
1707}
1708
1709EGLBoolean eglStreamConsumerReleaseKHR(EGLDisplay dpy,
1710 EGLStreamKHR stream)
1711{
1712 clearError();
1713
1714 const egl_display_ptr dp = validate_display(dpy);
1715 if (!dp) return EGL_FALSE;
1716
1717 EGLBoolean result = EGL_FALSE;
1718 egl_connection_t* const cnx = &gEGLImpl;
1719 if (cnx->dso && cnx->egl.eglStreamConsumerReleaseKHR) {
1720 result = cnx->egl.eglStreamConsumerReleaseKHR(
1721 dp->disp.dpy, stream);
1722 }
1723 return result;
1724}
1725
1726EGLNativeFileDescriptorKHR eglGetStreamFileDescriptorKHR(
1727 EGLDisplay dpy, EGLStreamKHR stream)
1728{
1729 clearError();
1730
1731 const egl_display_ptr dp = validate_display(dpy);
1732 if (!dp) return EGL_NO_FILE_DESCRIPTOR_KHR;
1733
1734 EGLNativeFileDescriptorKHR result = EGL_NO_FILE_DESCRIPTOR_KHR;
1735 egl_connection_t* const cnx = &gEGLImpl;
1736 if (cnx->dso && cnx->egl.eglGetStreamFileDescriptorKHR) {
1737 result = cnx->egl.eglGetStreamFileDescriptorKHR(
1738 dp->disp.dpy, stream);
1739 }
1740 return result;
1741}
1742
1743EGLStreamKHR eglCreateStreamFromFileDescriptorKHR(
1744 EGLDisplay dpy, EGLNativeFileDescriptorKHR file_descriptor)
1745{
1746 clearError();
1747
1748 const egl_display_ptr dp = validate_display(dpy);
1749 if (!dp) return EGL_NO_STREAM_KHR;
1750
1751 EGLStreamKHR result = EGL_NO_STREAM_KHR;
1752 egl_connection_t* const cnx = &gEGLImpl;
1753 if (cnx->dso && cnx->egl.eglCreateStreamFromFileDescriptorKHR) {
1754 result = cnx->egl.eglCreateStreamFromFileDescriptorKHR(
1755 dp->disp.dpy, file_descriptor);
1756 }
1757 return result;
1758}
1759
Mathias Agopian518ec112011-05-13 16:21:08 -07001760// ----------------------------------------------------------------------------
Mathias Agopian2bb71682013-03-27 17:32:41 -07001761// EGL_EGLEXT_VERSION 15
1762// ----------------------------------------------------------------------------
1763
1764EGLint eglWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags) {
1765 clearError();
1766 const egl_display_ptr dp = validate_display(dpy);
1767 if (!dp) return EGL_FALSE;
1768 EGLint result = EGL_FALSE;
1769 egl_connection_t* const cnx = &gEGLImpl;
1770 if (cnx->dso && cnx->egl.eglWaitSyncKHR) {
1771 result = cnx->egl.eglWaitSyncKHR(dp->disp.dpy, sync, flags);
1772 }
1773 return result;
1774}
1775
1776// ----------------------------------------------------------------------------
Mathias Agopian518ec112011-05-13 16:21:08 -07001777// ANDROID extensions
1778// ----------------------------------------------------------------------------
1779
Jamie Gennis331841b2012-09-06 14:52:00 -07001780EGLint eglDupNativeFenceFDANDROID(EGLDisplay dpy, EGLSyncKHR sync)
1781{
1782 clearError();
1783
1784 const egl_display_ptr dp = validate_display(dpy);
1785 if (!dp) return EGL_NO_NATIVE_FENCE_FD_ANDROID;
1786
1787 EGLint result = EGL_NO_NATIVE_FENCE_FD_ANDROID;
1788 egl_connection_t* const cnx = &gEGLImpl;
1789 if (cnx->dso && cnx->egl.eglDupNativeFenceFDANDROID) {
1790 result = cnx->egl.eglDupNativeFenceFDANDROID(dp->disp.dpy, sync);
1791 }
1792 return result;
1793}
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001794
Andy McFadden72841452013-03-01 16:25:32 -08001795EGLBoolean eglPresentationTimeANDROID(EGLDisplay dpy, EGLSurface surface,
1796 EGLnsecsANDROID time)
1797{
1798 clearError();
1799
1800 const egl_display_ptr dp = validate_display(dpy);
1801 if (!dp) {
1802 return EGL_FALSE;
1803 }
1804
1805 SurfaceRef _s(dp.get(), surface);
1806 if (!_s.get()) {
1807 setError(EGL_BAD_SURFACE, EGL_FALSE);
1808 return EGL_FALSE;
1809 }
1810
1811 egl_surface_t const * const s = get_surface(surface);
1812 native_window_set_buffers_timestamp(s->win.get(), time);
1813
1814 return EGL_TRUE;
1815}
1816
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001817// ----------------------------------------------------------------------------
1818// NVIDIA extensions
1819// ----------------------------------------------------------------------------
1820EGLuint64NV eglGetSystemTimeFrequencyNV()
1821{
1822 clearError();
1823
1824 if (egl_init_drivers() == EGL_FALSE) {
1825 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1826 }
1827
1828 EGLuint64NV ret = 0;
Mathias Agopianada798b2012-02-13 17:09:30 -08001829 egl_connection_t* const cnx = &gEGLImpl;
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001830
Mathias Agopianada798b2012-02-13 17:09:30 -08001831 if (cnx->dso && cnx->egl.eglGetSystemTimeFrequencyNV) {
1832 return cnx->egl.eglGetSystemTimeFrequencyNV();
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001833 }
1834
Mathias Agopian0e8bbee2011-10-05 19:15:05 -07001835 return setErrorQuiet(EGL_BAD_DISPLAY, 0);
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001836}
1837
1838EGLuint64NV eglGetSystemTimeNV()
1839{
1840 clearError();
1841
1842 if (egl_init_drivers() == EGL_FALSE) {
1843 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1844 }
1845
1846 EGLuint64NV ret = 0;
Mathias Agopianada798b2012-02-13 17:09:30 -08001847 egl_connection_t* const cnx = &gEGLImpl;
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001848
Mathias Agopianada798b2012-02-13 17:09:30 -08001849 if (cnx->dso && cnx->egl.eglGetSystemTimeNV) {
1850 return cnx->egl.eglGetSystemTimeNV();
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001851 }
1852
Mathias Agopian0e8bbee2011-10-05 19:15:05 -07001853 return setErrorQuiet(EGL_BAD_DISPLAY, 0);
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001854}
Dan Stozaa894d082015-02-19 15:27:36 -08001855
1856// ----------------------------------------------------------------------------
1857// Partial update extension
1858// ----------------------------------------------------------------------------
1859EGLBoolean eglSetDamageRegionKHR(EGLDisplay dpy, EGLSurface surface,
1860 EGLint *rects, EGLint n_rects)
1861{
1862 clearError();
1863
1864 const egl_display_ptr dp = validate_display(dpy);
1865 if (!dp) {
1866 setError(EGL_BAD_DISPLAY, EGL_FALSE);
1867 return EGL_FALSE;
1868 }
1869
1870 SurfaceRef _s(dp.get(), surface);
1871 if (!_s.get()) {
1872 setError(EGL_BAD_SURFACE, EGL_FALSE);
1873 return EGL_FALSE;
1874 }
1875
1876 egl_surface_t const * const s = get_surface(surface);
1877 if (s->cnx->egl.eglSetDamageRegionKHR) {
1878 return s->cnx->egl.eglSetDamageRegionKHR(dp->disp.dpy, s->surface,
1879 rects, n_rects);
1880 }
1881
1882 return EGL_FALSE;
1883}