blob: f4e46e2ee575394fcf013ba949226fcfe96d2df0 [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 "
94 "EGL_KHR_gl_texture_cubemap_image "
95 "EGL_KHR_gl_renderbuffer_image "
96 "EGL_KHR_reusable_sync "
97 "EGL_KHR_fence_sync "
Jamie Gennisf6d1c392013-04-25 18:48:41 -070098 "EGL_KHR_create_context "
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070099 "EGL_EXT_create_context_robustness "
100 "EGL_NV_system_time "
101 "EGL_ANDROID_image_native_buffer " // mandatory
Mathias Agopian2bb71682013-03-27 17:32:41 -0700102 "EGL_KHR_wait_sync " // strongly recommended
Jamie Gennisdbe92452013-09-23 17:22:10 -0700103 "EGL_ANDROID_recordable " // mandatory
Dan Stozaa894d082015-02-19 15:27:36 -0800104 "EGL_KHR_partial_update " // strongly recommended
105 "EGL_EXT_buffer_age " // strongly recommended with partial_update
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700106 ;
107
108// extensions not exposed to applications but used by the ANDROID system
109// "EGL_ANDROID_blob_cache " // strongly recommended
110// "EGL_IMG_hibernate_process " // optional
111// "EGL_ANDROID_native_fence_sync " // strongly recommended
112// "EGL_ANDROID_framebuffer_target " // mandatory for HWC 1.1
Jamie Gennisdbe92452013-09-23 17:22:10 -0700113// "EGL_ANDROID_image_crop " // optional
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700114
115/*
116 * EGL Extensions entry-points exposed to 3rd party applications
117 * (keep in sync with gExtensionString above)
118 *
119 */
120static const extention_map_t sExtensionMap[] = {
121 // EGL_KHR_lock_surface
Mathias Agopian518ec112011-05-13 16:21:08 -0700122 { "eglLockSurfaceKHR",
123 (__eglMustCastToProperFunctionPointerType)&eglLockSurfaceKHR },
124 { "eglUnlockSurfaceKHR",
125 (__eglMustCastToProperFunctionPointerType)&eglUnlockSurfaceKHR },
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700126
127 // EGL_KHR_image, EGL_KHR_image_base
Mathias Agopian518ec112011-05-13 16:21:08 -0700128 { "eglCreateImageKHR",
129 (__eglMustCastToProperFunctionPointerType)&eglCreateImageKHR },
130 { "eglDestroyImageKHR",
131 (__eglMustCastToProperFunctionPointerType)&eglDestroyImageKHR },
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700132
133 // EGL_KHR_reusable_sync, EGL_KHR_fence_sync
134 { "eglCreateSyncKHR",
135 (__eglMustCastToProperFunctionPointerType)&eglCreateSyncKHR },
136 { "eglDestroySyncKHR",
137 (__eglMustCastToProperFunctionPointerType)&eglDestroySyncKHR },
138 { "eglClientWaitSyncKHR",
139 (__eglMustCastToProperFunctionPointerType)&eglClientWaitSyncKHR },
140 { "eglSignalSyncKHR",
141 (__eglMustCastToProperFunctionPointerType)&eglSignalSyncKHR },
142 { "eglGetSyncAttribKHR",
143 (__eglMustCastToProperFunctionPointerType)&eglGetSyncAttribKHR },
144
145 // EGL_NV_system_time
Jonas Yang1c3d72a2011-08-26 20:04:39 +0800146 { "eglGetSystemTimeFrequencyNV",
147 (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeFrequencyNV },
148 { "eglGetSystemTimeNV",
149 (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeNV },
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700150
Mathias Agopian2bb71682013-03-27 17:32:41 -0700151 // EGL_KHR_wait_sync
152 { "eglWaitSyncKHR",
153 (__eglMustCastToProperFunctionPointerType)&eglWaitSyncKHR },
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700154
155 // EGL_ANDROID_presentation_time
156 { "eglPresentationTimeANDROID",
157 (__eglMustCastToProperFunctionPointerType)&eglPresentationTimeANDROID },
Dan Stozaa894d082015-02-19 15:27:36 -0800158
159 // EGL_KHR_swap_buffers_with_damage
160 { "eglSwapBuffersWithDamageKHR",
161 (__eglMustCastToProperFunctionPointerType)&eglSwapBuffersWithDamageKHR },
162
163 // EGL_KHR_partial_update
164 { "eglSetDamageRegionKHR",
165 (__eglMustCastToProperFunctionPointerType)&eglSetDamageRegionKHR },
Mathias Agopian518ec112011-05-13 16:21:08 -0700166};
167
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700168/*
169 * These extensions entry-points should not be exposed to applications.
170 * They're used internally by the Android EGL layer.
171 */
172#define FILTER_EXTENSIONS(procname) \
173 (!strcmp((procname), "eglSetBlobCacheFuncsANDROID") || \
174 !strcmp((procname), "eglHibernateProcessIMG") || \
175 !strcmp((procname), "eglAwakenProcessIMG") || \
176 !strcmp((procname), "eglDupNativeFenceFDANDROID"))
177
178
179
Mathias Agopian518ec112011-05-13 16:21:08 -0700180// accesses protected by sExtensionMapMutex
181static DefaultKeyedVector<String8, __eglMustCastToProperFunctionPointerType> sGLExtentionMap;
182static int sGLExtentionSlot = 0;
183static pthread_mutex_t sExtensionMapMutex = PTHREAD_MUTEX_INITIALIZER;
184
185static void(*findProcAddress(const char* name,
186 const extention_map_t* map, size_t n))() {
187 for (uint32_t i=0 ; i<n ; i++) {
188 if (!strcmp(name, map[i].name)) {
189 return map[i].address;
190 }
191 }
192 return NULL;
193}
194
195// ----------------------------------------------------------------------------
196
Mathias Agopian518ec112011-05-13 16:21:08 -0700197extern void setGLHooksThreadSpecific(gl_hooks_t const *value);
198extern EGLBoolean egl_init_drivers();
199extern const __eglMustCastToProperFunctionPointerType gExtensionForwarders[MAX_NUMBER_OF_GL_EXTENSIONS];
Siva Velusamya73a9772012-12-18 14:56:55 -0800200extern int getEGLDebugLevel();
201extern void setEGLDebugLevel(int level);
Mathias Agopian518ec112011-05-13 16:21:08 -0700202extern gl_hooks_t gHooksTrace;
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700203
Mathias Agopian518ec112011-05-13 16:21:08 -0700204} // namespace android;
205
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700206
Mathias Agopian518ec112011-05-13 16:21:08 -0700207// ----------------------------------------------------------------------------
208
209static inline void clearError() { egl_tls_t::clearError(); }
210static inline EGLContext getContext() { return egl_tls_t::getContext(); }
211
212// ----------------------------------------------------------------------------
213
214EGLDisplay eglGetDisplay(EGLNativeDisplayType display)
215{
216 clearError();
217
Dan Stozac3289c42014-01-17 11:38:34 -0800218 uintptr_t index = reinterpret_cast<uintptr_t>(display);
Mathias Agopian518ec112011-05-13 16:21:08 -0700219 if (index >= NUM_DISPLAYS) {
220 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
221 }
222
223 if (egl_init_drivers() == EGL_FALSE) {
224 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
225 }
226
227 EGLDisplay dpy = egl_display_t::getFromNativeDisplay(display);
228 return dpy;
229}
230
231// ----------------------------------------------------------------------------
232// Initialization
233// ----------------------------------------------------------------------------
234
235EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
236{
237 clearError();
238
Jesse Hallb29e5e82012-04-04 16:53:42 -0700239 egl_display_ptr dp = get_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700240 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
241
242 EGLBoolean res = dp->initialize(major, minor);
243
244 return res;
245}
246
247EGLBoolean eglTerminate(EGLDisplay dpy)
248{
249 // NOTE: don't unload the drivers b/c some APIs can be called
250 // after eglTerminate() has been called. eglTerminate() only
251 // terminates an EGLDisplay, not a EGL itself.
252
253 clearError();
254
Jesse Hallb29e5e82012-04-04 16:53:42 -0700255 egl_display_ptr dp = get_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700256 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
257
258 EGLBoolean res = dp->terminate();
Jesse Hall47743382013-02-08 11:13:46 -0800259
Mathias Agopian518ec112011-05-13 16:21:08 -0700260 return res;
261}
262
263// ----------------------------------------------------------------------------
264// configuration
265// ----------------------------------------------------------------------------
266
267EGLBoolean eglGetConfigs( EGLDisplay dpy,
268 EGLConfig *configs,
269 EGLint config_size, EGLint *num_config)
270{
271 clearError();
272
Jesse Hallb29e5e82012-04-04 16:53:42 -0700273 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700274 if (!dp) return EGL_FALSE;
275
Mathias Agopian7773c432012-02-13 20:06:08 -0800276 if (num_config==0) {
277 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700278 }
279
Mathias Agopian7773c432012-02-13 20:06:08 -0800280 EGLBoolean res = EGL_FALSE;
281 *num_config = 0;
282
283 egl_connection_t* const cnx = &gEGLImpl;
284 if (cnx->dso) {
285 res = cnx->egl.eglGetConfigs(
286 dp->disp.dpy, configs, config_size, num_config);
Mathias Agopian518ec112011-05-13 16:21:08 -0700287 }
Mathias Agopian7773c432012-02-13 20:06:08 -0800288
289 return res;
Mathias Agopian518ec112011-05-13 16:21:08 -0700290}
291
292EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list,
293 EGLConfig *configs, EGLint config_size,
294 EGLint *num_config)
295{
296 clearError();
297
Jesse Hallb29e5e82012-04-04 16:53:42 -0700298 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700299 if (!dp) return EGL_FALSE;
300
301 if (num_config==0) {
302 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
303 }
304
Mathias Agopian518ec112011-05-13 16:21:08 -0700305 EGLBoolean res = EGL_FALSE;
306 *num_config = 0;
307
Mathias Agopianada798b2012-02-13 17:09:30 -0800308 egl_connection_t* const cnx = &gEGLImpl;
309 if (cnx->dso) {
Romain Guy1cffc802012-10-15 18:13:05 -0700310 if (attrib_list) {
311 char value[PROPERTY_VALUE_MAX];
312 property_get("debug.egl.force_msaa", value, "false");
313
314 if (!strcmp(value, "true")) {
315 size_t attribCount = 0;
316 EGLint attrib = attrib_list[0];
317
318 // Only enable MSAA if the context is OpenGL ES 2.0 and
Romain Guybe3c3e42012-10-15 19:25:18 -0700319 // if no caveat is requested
Romain Guy1cffc802012-10-15 18:13:05 -0700320 const EGLint *attribRendererable = NULL;
321 const EGLint *attribCaveat = NULL;
322
323 // Count the number of attributes and look for
Romain Guybe3c3e42012-10-15 19:25:18 -0700324 // EGL_RENDERABLE_TYPE and EGL_CONFIG_CAVEAT
Romain Guy1cffc802012-10-15 18:13:05 -0700325 while (attrib != EGL_NONE) {
326 attrib = attrib_list[attribCount];
327 switch (attrib) {
328 case EGL_RENDERABLE_TYPE:
329 attribRendererable = &attrib_list[attribCount];
330 break;
331 case EGL_CONFIG_CAVEAT:
332 attribCaveat = &attrib_list[attribCount];
333 break;
334 }
335 attribCount++;
336 }
337
338 if (attribRendererable && attribRendererable[1] == EGL_OPENGL_ES2_BIT &&
339 (!attribCaveat || attribCaveat[1] != EGL_NONE)) {
Jesse Hall47743382013-02-08 11:13:46 -0800340
Romain Guy1cffc802012-10-15 18:13:05 -0700341 // Insert 2 extra attributes to force-enable MSAA 4x
342 EGLint aaAttribs[attribCount + 4];
343 aaAttribs[0] = EGL_SAMPLE_BUFFERS;
344 aaAttribs[1] = 1;
345 aaAttribs[2] = EGL_SAMPLES;
346 aaAttribs[3] = 4;
347
348 memcpy(&aaAttribs[4], attrib_list, attribCount * sizeof(EGLint));
349
350 EGLint numConfigAA;
351 EGLBoolean resAA = cnx->egl.eglChooseConfig(
352 dp->disp.dpy, aaAttribs, configs, config_size, &numConfigAA);
353
354 if (resAA == EGL_TRUE && numConfigAA > 0) {
355 ALOGD("Enabling MSAA 4x");
356 *num_config = numConfigAA;
357 return resAA;
358 }
359 }
360 }
361 }
362
Mathias Agopian7773c432012-02-13 20:06:08 -0800363 res = cnx->egl.eglChooseConfig(
364 dp->disp.dpy, attrib_list, configs, config_size, num_config);
Mathias Agopian518ec112011-05-13 16:21:08 -0700365 }
366 return res;
367}
368
369EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
370 EGLint attribute, EGLint *value)
371{
372 clearError();
373
Jesse Hallb29e5e82012-04-04 16:53:42 -0700374 egl_connection_t* cnx = NULL;
375 const egl_display_ptr dp = validate_display_connection(dpy, cnx);
376 if (!dp) return EGL_FALSE;
Jesse Hall47743382013-02-08 11:13:46 -0800377
Mathias Agopian518ec112011-05-13 16:21:08 -0700378 return cnx->egl.eglGetConfigAttrib(
Mathias Agopian7773c432012-02-13 20:06:08 -0800379 dp->disp.dpy, config, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -0700380}
381
382// ----------------------------------------------------------------------------
383// surfaces
384// ----------------------------------------------------------------------------
385
Jesse Halla2ba4282013-09-14 21:00:14 -0700386// The EGL_KHR_gl_colorspace spec hasn't been ratified yet, so these haven't
Jesse Hallc2e41222013-08-08 13:40:22 -0700387// been added to the Khronos egl.h.
388#define EGL_GL_COLORSPACE_KHR EGL_VG_COLORSPACE
389#define EGL_GL_COLORSPACE_SRGB_KHR EGL_VG_COLORSPACE_sRGB
390#define EGL_GL_COLORSPACE_LINEAR_KHR EGL_VG_COLORSPACE_LINEAR
391
392// Turn linear formats into corresponding sRGB formats when colorspace is
393// EGL_GL_COLORSPACE_SRGB_KHR, or turn sRGB formats into corresponding linear
394// formats when colorspace is EGL_GL_COLORSPACE_LINEAR_KHR. In any cases where
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800395// the modification isn't possible, the original dataSpace is returned.
396static android_dataspace modifyBufferDataspace( android_dataspace dataSpace,
397 EGLint colorspace) {
Jesse Hallc2e41222013-08-08 13:40:22 -0700398 if (colorspace == EGL_GL_COLORSPACE_LINEAR_KHR) {
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800399 return HAL_DATASPACE_SRGB_LINEAR;
Jesse Hallc2e41222013-08-08 13:40:22 -0700400 } else if (colorspace == EGL_GL_COLORSPACE_SRGB_KHR) {
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800401 return HAL_DATASPACE_SRGB;
Jesse Hallc2e41222013-08-08 13:40:22 -0700402 }
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800403 return dataSpace;
Jesse Hallc2e41222013-08-08 13:40:22 -0700404}
405
Mathias Agopian518ec112011-05-13 16:21:08 -0700406EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config,
407 NativeWindowType window,
408 const EGLint *attrib_list)
409{
410 clearError();
411
Jesse Hallb29e5e82012-04-04 16:53:42 -0700412 egl_connection_t* cnx = NULL;
413 egl_display_ptr dp = validate_display_connection(dpy, cnx);
414 if (dp) {
Mathias Agopianada798b2012-02-13 17:09:30 -0800415 EGLDisplay iDpy = dp->disp.dpy;
Mathias Agopian518ec112011-05-13 16:21:08 -0700416
Andy McFaddend566ce32014-01-07 15:54:17 -0800417 int result = native_window_api_connect(window, NATIVE_WINDOW_API_EGL);
418 if (result != OK) {
419 ALOGE("eglCreateWindowSurface: native_window_api_connect (win=%p) "
420 "failed (%#x) (already connected to another API?)",
421 window, result);
Jonathan Hamilton77a9b4a2013-07-17 09:41:42 -0700422 return setError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
Mathias Agopian81a63352011-07-29 17:55:48 -0700423 }
424
Mathias Agopian0f288fc2013-08-21 16:36:34 -0700425 // Set the native window's buffers format to match what this config requests.
Jesse Hallc2e41222013-08-08 13:40:22 -0700426 // Whether to use sRGB gamma is not part of the EGLconfig, but is part
427 // of our native format. So if sRGB gamma is requested, we have to
428 // modify the EGLconfig's format before setting the native window's
429 // format.
Alistair Strachan733a8072015-02-12 12:33:25 -0800430
Mathias Agopian0f288fc2013-08-21 16:36:34 -0700431 // by default, just pick RGBA_8888
432 EGLint format = HAL_PIXEL_FORMAT_RGBA_8888;
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800433 android_dataspace dataSpace = HAL_DATASPACE_UNKNOWN;
Mathias Agopian0f288fc2013-08-21 16:36:34 -0700434
435 EGLint a = 0;
436 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_ALPHA_SIZE, &a);
437 if (a > 0) {
438 // alpha-channel requested, there's really only one suitable format
439 format = HAL_PIXEL_FORMAT_RGBA_8888;
440 } else {
441 EGLint r, g, b;
442 r = g = b = 0;
443 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_RED_SIZE, &r);
444 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_GREEN_SIZE, &g);
445 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_BLUE_SIZE, &b);
446 EGLint colorDepth = r + g + b;
447 if (colorDepth <= 16) {
448 format = HAL_PIXEL_FORMAT_RGB_565;
449 } else {
450 format = HAL_PIXEL_FORMAT_RGBX_8888;
451 }
Jesse Hallc2e41222013-08-08 13:40:22 -0700452 }
Mathias Agopian0f288fc2013-08-21 16:36:34 -0700453
454 // now select a corresponding sRGB format if needed
455 if (attrib_list && dp->haveExtension("EGL_KHR_gl_colorspace")) {
456 for (const EGLint* attr = attrib_list; *attr != EGL_NONE; attr += 2) {
457 if (*attr == EGL_GL_COLORSPACE_KHR) {
Jesse Halla2ba4282013-09-14 21:00:14 -0700458 if (ENABLE_EGL_KHR_GL_COLORSPACE) {
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800459 dataSpace = modifyBufferDataspace(dataSpace, *(attr+1));
Jesse Halla2ba4282013-09-14 21:00:14 -0700460 } else {
461 // Normally we'd pass through unhandled attributes to
462 // the driver. But in case the driver implements this
463 // extension but we're disabling it, we want to prevent
464 // it getting through -- support will be broken without
465 // our help.
466 ALOGE("sRGB window surfaces not supported");
467 return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
468 }
Jamie Gennisbee205f2011-07-01 13:12:07 -0700469 }
Mathias Agopian518ec112011-05-13 16:21:08 -0700470 }
471 }
Alistair Strachan733a8072015-02-12 12:33:25 -0800472
Jesse Hallc2e41222013-08-08 13:40:22 -0700473 if (format != 0) {
474 int err = native_window_set_buffers_format(window, format);
475 if (err != 0) {
476 ALOGE("error setting native window pixel format: %s (%d)",
477 strerror(-err), err);
478 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
479 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
480 }
481 }
Mathias Agopian518ec112011-05-13 16:21:08 -0700482
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800483 if (dataSpace != 0) {
484 int err = native_window_set_buffers_data_space(window, dataSpace);
485 if (err != 0) {
486 ALOGE("error setting native window pixel dataSpace: %s (%d)",
487 strerror(-err), err);
488 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
489 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
490 }
491 }
492
Jamie Gennis59769462011-11-19 18:04:43 -0800493 // the EGL spec requires that a new EGLSurface default to swap interval
494 // 1, so explicitly set that on the window here.
495 ANativeWindow* anw = reinterpret_cast<ANativeWindow*>(window);
496 anw->setSwapInterval(anw, 1);
497
Mathias Agopian518ec112011-05-13 16:21:08 -0700498 EGLSurface surface = cnx->egl.eglCreateWindowSurface(
Mathias Agopian7773c432012-02-13 20:06:08 -0800499 iDpy, config, window, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700500 if (surface != EGL_NO_SURFACE) {
Jesse Hallb29e5e82012-04-04 16:53:42 -0700501 egl_surface_t* s = new egl_surface_t(dp.get(), config, window,
502 surface, cnx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700503 return s;
504 }
Mathias Agopian81a63352011-07-29 17:55:48 -0700505
506 // EGLSurface creation failed
507 native_window_set_buffers_format(window, 0);
508 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
Mathias Agopian518ec112011-05-13 16:21:08 -0700509 }
510 return EGL_NO_SURFACE;
511}
512
513EGLSurface eglCreatePixmapSurface( EGLDisplay dpy, EGLConfig config,
514 NativePixmapType pixmap,
515 const EGLint *attrib_list)
516{
517 clearError();
518
Jesse Hallb29e5e82012-04-04 16:53:42 -0700519 egl_connection_t* cnx = NULL;
520 egl_display_ptr dp = validate_display_connection(dpy, cnx);
521 if (dp) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700522 EGLSurface surface = cnx->egl.eglCreatePixmapSurface(
Mathias Agopian7773c432012-02-13 20:06:08 -0800523 dp->disp.dpy, config, pixmap, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700524 if (surface != EGL_NO_SURFACE) {
Jesse Hallb29e5e82012-04-04 16:53:42 -0700525 egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL,
526 surface, cnx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700527 return s;
528 }
529 }
530 return EGL_NO_SURFACE;
531}
532
533EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config,
534 const EGLint *attrib_list)
535{
536 clearError();
537
Jesse Hallb29e5e82012-04-04 16:53:42 -0700538 egl_connection_t* cnx = NULL;
539 egl_display_ptr dp = validate_display_connection(dpy, cnx);
540 if (dp) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700541 EGLSurface surface = cnx->egl.eglCreatePbufferSurface(
Mathias Agopian7773c432012-02-13 20:06:08 -0800542 dp->disp.dpy, config, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700543 if (surface != EGL_NO_SURFACE) {
Jesse Hallb29e5e82012-04-04 16:53:42 -0700544 egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL,
545 surface, cnx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700546 return s;
547 }
548 }
549 return EGL_NO_SURFACE;
550}
Jesse Hall47743382013-02-08 11:13:46 -0800551
Mathias Agopian518ec112011-05-13 16:21:08 -0700552EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
553{
554 clearError();
555
Jesse Hallb29e5e82012-04-04 16:53:42 -0700556 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700557 if (!dp) return EGL_FALSE;
558
Jesse Hallb29e5e82012-04-04 16:53:42 -0700559 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700560 if (!_s.get())
561 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700562
563 egl_surface_t * const s = get_surface(surface);
Michael Lentine00699fa2014-07-23 10:19:41 -0700564 ANativeWindow* window = s->win.get();
565 if (window) {
566 int result = native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
567 if (result != OK) {
568 ALOGE("eglDestroySurface: native_window_api_disconnect (win=%p) "
569 "failed (%#x)",
570 window, result);
571 }
572 }
Mathias Agopianada798b2012-02-13 17:09:30 -0800573 EGLBoolean result = s->cnx->egl.eglDestroySurface(dp->disp.dpy, s->surface);
Mathias Agopian518ec112011-05-13 16:21:08 -0700574 if (result == EGL_TRUE) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700575 _s.terminate();
576 }
577 return result;
578}
579
580EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface surface,
581 EGLint attribute, EGLint *value)
582{
583 clearError();
584
Jesse Hallb29e5e82012-04-04 16:53:42 -0700585 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700586 if (!dp) return EGL_FALSE;
587
Jesse Hallb29e5e82012-04-04 16:53:42 -0700588 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700589 if (!_s.get())
590 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700591
Mathias Agopian518ec112011-05-13 16:21:08 -0700592 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian7773c432012-02-13 20:06:08 -0800593 return s->cnx->egl.eglQuerySurface(
594 dp->disp.dpy, s->surface, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -0700595}
596
Jamie Gennise8696a42012-01-15 18:54:57 -0800597void EGLAPI eglBeginFrame(EGLDisplay dpy, EGLSurface surface) {
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800598 ATRACE_CALL();
Jamie Gennise8696a42012-01-15 18:54:57 -0800599 clearError();
600
Jesse Hallb29e5e82012-04-04 16:53:42 -0700601 const egl_display_ptr dp = validate_display(dpy);
Jamie Gennise8696a42012-01-15 18:54:57 -0800602 if (!dp) {
603 return;
604 }
605
Jesse Hallb29e5e82012-04-04 16:53:42 -0700606 SurfaceRef _s(dp.get(), surface);
Jamie Gennise8696a42012-01-15 18:54:57 -0800607 if (!_s.get()) {
608 setError(EGL_BAD_SURFACE, EGL_FALSE);
609 return;
610 }
Jamie Gennise8696a42012-01-15 18:54:57 -0800611}
612
Mathias Agopian518ec112011-05-13 16:21:08 -0700613// ----------------------------------------------------------------------------
614// Contexts
615// ----------------------------------------------------------------------------
616
617EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config,
618 EGLContext share_list, const EGLint *attrib_list)
619{
620 clearError();
621
Jesse Hallb29e5e82012-04-04 16:53:42 -0700622 egl_connection_t* cnx = NULL;
623 const egl_display_ptr dp = validate_display_connection(dpy, cnx);
Michael Chock0673e1e2012-06-21 12:53:17 -0700624 if (dp) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700625 if (share_list != EGL_NO_CONTEXT) {
Michael Chock0673e1e2012-06-21 12:53:17 -0700626 if (!ContextRef(dp.get(), share_list).get()) {
627 return setError(EGL_BAD_CONTEXT, EGL_NO_CONTEXT);
628 }
Mathias Agopian518ec112011-05-13 16:21:08 -0700629 egl_context_t* const c = get_context(share_list);
630 share_list = c->context;
631 }
632 EGLContext context = cnx->egl.eglCreateContext(
Mathias Agopian7773c432012-02-13 20:06:08 -0800633 dp->disp.dpy, config, share_list, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700634 if (context != EGL_NO_CONTEXT) {
635 // figure out if it's a GLESv1 or GLESv2
636 int version = 0;
637 if (attrib_list) {
638 while (*attrib_list != EGL_NONE) {
639 GLint attr = *attrib_list++;
640 GLint value = *attrib_list++;
641 if (attr == EGL_CONTEXT_CLIENT_VERSION) {
642 if (value == 1) {
Mathias Agopian7773c432012-02-13 20:06:08 -0800643 version = egl_connection_t::GLESv1_INDEX;
Jesse Hall47743382013-02-08 11:13:46 -0800644 } else if (value == 2 || value == 3) {
Mathias Agopian7773c432012-02-13 20:06:08 -0800645 version = egl_connection_t::GLESv2_INDEX;
Mathias Agopian518ec112011-05-13 16:21:08 -0700646 }
647 }
648 };
649 }
Jesse Hallb29e5e82012-04-04 16:53:42 -0700650 egl_context_t* c = new egl_context_t(dpy, context, config, cnx,
651 version);
Siva Velusamy0469dd62011-11-30 15:05:37 -0800652#if EGL_TRACE
Siva Velusamya73a9772012-12-18 14:56:55 -0800653 if (getEGLDebugLevel() > 0)
Siva Velusamy0469dd62011-11-30 15:05:37 -0800654 GLTrace_eglCreateContext(version, c);
655#endif
Mathias Agopian518ec112011-05-13 16:21:08 -0700656 return c;
657 }
658 }
659 return EGL_NO_CONTEXT;
660}
661
662EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
663{
664 clearError();
665
Jesse Hallb29e5e82012-04-04 16:53:42 -0700666 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700667 if (!dp)
668 return EGL_FALSE;
Mathias Agopian518ec112011-05-13 16:21:08 -0700669
Jesse Hallb29e5e82012-04-04 16:53:42 -0700670 ContextRef _c(dp.get(), ctx);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700671 if (!_c.get())
672 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
Jesse Hall47743382013-02-08 11:13:46 -0800673
Mathias Agopian518ec112011-05-13 16:21:08 -0700674 egl_context_t * const c = get_context(ctx);
Mathias Agopianada798b2012-02-13 17:09:30 -0800675 EGLBoolean result = c->cnx->egl.eglDestroyContext(dp->disp.dpy, c->context);
Mathias Agopian518ec112011-05-13 16:21:08 -0700676 if (result == EGL_TRUE) {
677 _c.terminate();
678 }
679 return result;
680}
681
Mathias Agopian518ec112011-05-13 16:21:08 -0700682EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw,
683 EGLSurface read, EGLContext ctx)
684{
685 clearError();
686
Jesse Hallb29e5e82012-04-04 16:53:42 -0700687 egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700688 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
689
Mathias Agopian5b287a62011-05-16 18:58:55 -0700690 // If ctx is not EGL_NO_CONTEXT, read is not EGL_NO_SURFACE, or draw is not
691 // EGL_NO_SURFACE, then an EGL_NOT_INITIALIZED error is generated if dpy is
692 // a valid but uninitialized display.
Mathias Agopian518ec112011-05-13 16:21:08 -0700693 if ( (ctx != EGL_NO_CONTEXT) || (read != EGL_NO_SURFACE) ||
694 (draw != EGL_NO_SURFACE) ) {
695 if (!dp->isReady()) return setError(EGL_NOT_INITIALIZED, EGL_FALSE);
696 }
697
698 // get a reference to the object passed in
Jesse Hallb29e5e82012-04-04 16:53:42 -0700699 ContextRef _c(dp.get(), ctx);
700 SurfaceRef _d(dp.get(), draw);
701 SurfaceRef _r(dp.get(), read);
Mathias Agopian518ec112011-05-13 16:21:08 -0700702
703 // validate the context (if not EGL_NO_CONTEXT)
Mathias Agopian5b287a62011-05-16 18:58:55 -0700704 if ((ctx != EGL_NO_CONTEXT) && !_c.get()) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700705 // EGL_NO_CONTEXT is valid
Michael Chock0673e1e2012-06-21 12:53:17 -0700706 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700707 }
708
709 // these are the underlying implementation's object
710 EGLContext impl_ctx = EGL_NO_CONTEXT;
711 EGLSurface impl_draw = EGL_NO_SURFACE;
712 EGLSurface impl_read = EGL_NO_SURFACE;
713
714 // these are our objects structs passed in
715 egl_context_t * c = NULL;
716 egl_surface_t const * d = NULL;
717 egl_surface_t const * r = NULL;
718
719 // these are the current objects structs
720 egl_context_t * cur_c = get_context(getContext());
Jesse Hall47743382013-02-08 11:13:46 -0800721
Mathias Agopian518ec112011-05-13 16:21:08 -0700722 if (ctx != EGL_NO_CONTEXT) {
723 c = get_context(ctx);
724 impl_ctx = c->context;
725 } else {
726 // no context given, use the implementation of the current context
Michael Chock0673e1e2012-06-21 12:53:17 -0700727 if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE) {
728 // calling eglMakeCurrent( ..., !=0, !=0, EGL_NO_CONTEXT);
729 return setError(EGL_BAD_MATCH, EGL_FALSE);
730 }
Mathias Agopian518ec112011-05-13 16:21:08 -0700731 if (cur_c == NULL) {
732 // no current context
Mathias Agopian518ec112011-05-13 16:21:08 -0700733 // not an error, there is just no current context.
734 return EGL_TRUE;
735 }
736 }
737
738 // retrieve the underlying implementation's draw EGLSurface
739 if (draw != EGL_NO_SURFACE) {
Michael Chock0673e1e2012-06-21 12:53:17 -0700740 if (!_d.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700741 d = get_surface(draw);
Mathias Agopian518ec112011-05-13 16:21:08 -0700742 impl_draw = d->surface;
743 }
744
745 // retrieve the underlying implementation's read EGLSurface
746 if (read != EGL_NO_SURFACE) {
Michael Chock0673e1e2012-06-21 12:53:17 -0700747 if (!_r.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700748 r = get_surface(read);
Mathias Agopian518ec112011-05-13 16:21:08 -0700749 impl_read = r->surface;
750 }
751
Mathias Agopian518ec112011-05-13 16:21:08 -0700752
Jesse Hallb29e5e82012-04-04 16:53:42 -0700753 EGLBoolean result = dp->makeCurrent(c, cur_c,
Mathias Agopianfb87e542012-01-30 18:20:52 -0800754 draw, read, ctx,
755 impl_draw, impl_read, impl_ctx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700756
757 if (result == EGL_TRUE) {
Mathias Agopianfb87e542012-01-30 18:20:52 -0800758 if (c) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700759 setGLHooksThreadSpecific(c->cnx->hooks[c->version]);
760 egl_tls_t::setContext(ctx);
Siva Velusamy0469dd62011-11-30 15:05:37 -0800761#if EGL_TRACE
Siva Velusamya73a9772012-12-18 14:56:55 -0800762 if (getEGLDebugLevel() > 0)
Siva Velusamy93a826f2011-12-14 12:19:56 -0800763 GLTrace_eglMakeCurrent(c->version, c->cnx->hooks[c->version], ctx);
Siva Velusamy0469dd62011-11-30 15:05:37 -0800764#endif
Mathias Agopian518ec112011-05-13 16:21:08 -0700765 _c.acquire();
766 _r.acquire();
767 _d.acquire();
Mathias Agopian518ec112011-05-13 16:21:08 -0700768 } else {
769 setGLHooksThreadSpecific(&gHooksNoContext);
770 egl_tls_t::setContext(EGL_NO_CONTEXT);
771 }
Mathias Agopian5fecea72011-08-25 18:38:24 -0700772 } else {
Steve Blocke6f43dd2012-01-06 19:20:56 +0000773 // this will ALOGE the error
Mathias Agopian63108c32013-09-06 13:36:49 -0700774 egl_connection_t* const cnx = &gEGLImpl;
775 result = setError(cnx->egl.eglGetError(), EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700776 }
777 return result;
778}
779
780
781EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx,
782 EGLint attribute, EGLint *value)
783{
784 clearError();
785
Jesse Hallb29e5e82012-04-04 16:53:42 -0700786 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700787 if (!dp) return EGL_FALSE;
788
Jesse Hallb29e5e82012-04-04 16:53:42 -0700789 ContextRef _c(dp.get(), ctx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700790 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
791
Mathias Agopian518ec112011-05-13 16:21:08 -0700792 egl_context_t * const c = get_context(ctx);
Mathias Agopian7773c432012-02-13 20:06:08 -0800793 return c->cnx->egl.eglQueryContext(
794 dp->disp.dpy, c->context, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -0700795
Mathias Agopian518ec112011-05-13 16:21:08 -0700796}
797
798EGLContext eglGetCurrentContext(void)
799{
800 // could be called before eglInitialize(), but we wouldn't have a context
801 // then, and this function would correctly return EGL_NO_CONTEXT.
802
803 clearError();
804
805 EGLContext ctx = getContext();
806 return ctx;
807}
808
809EGLSurface eglGetCurrentSurface(EGLint readdraw)
810{
811 // could be called before eglInitialize(), but we wouldn't have a context
812 // then, and this function would correctly return EGL_NO_SURFACE.
813
814 clearError();
815
816 EGLContext ctx = getContext();
817 if (ctx) {
818 egl_context_t const * const c = get_context(ctx);
819 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
820 switch (readdraw) {
821 case EGL_READ: return c->read;
Jesse Hall47743382013-02-08 11:13:46 -0800822 case EGL_DRAW: return c->draw;
Mathias Agopian518ec112011-05-13 16:21:08 -0700823 default: return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
824 }
825 }
826 return EGL_NO_SURFACE;
827}
828
829EGLDisplay eglGetCurrentDisplay(void)
830{
831 // could be called before eglInitialize(), but we wouldn't have a context
832 // then, and this function would correctly return EGL_NO_DISPLAY.
833
834 clearError();
835
836 EGLContext ctx = getContext();
837 if (ctx) {
838 egl_context_t const * const c = get_context(ctx);
839 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
840 return c->dpy;
841 }
842 return EGL_NO_DISPLAY;
843}
844
845EGLBoolean eglWaitGL(void)
846{
Mathias Agopian518ec112011-05-13 16:21:08 -0700847 clearError();
848
Mathias Agopianada798b2012-02-13 17:09:30 -0800849 egl_connection_t* const cnx = &gEGLImpl;
850 if (!cnx->dso)
851 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
852
853 return cnx->egl.eglWaitGL();
Mathias Agopian518ec112011-05-13 16:21:08 -0700854}
855
856EGLBoolean eglWaitNative(EGLint engine)
857{
Mathias Agopian518ec112011-05-13 16:21:08 -0700858 clearError();
859
Mathias Agopianada798b2012-02-13 17:09:30 -0800860 egl_connection_t* const cnx = &gEGLImpl;
861 if (!cnx->dso)
862 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
863
864 return cnx->egl.eglWaitNative(engine);
Mathias Agopian518ec112011-05-13 16:21:08 -0700865}
866
867EGLint eglGetError(void)
868{
Mathias Agopianada798b2012-02-13 17:09:30 -0800869 EGLint err = EGL_SUCCESS;
870 egl_connection_t* const cnx = &gEGLImpl;
871 if (cnx->dso) {
872 err = cnx->egl.eglGetError();
Mathias Agopian518ec112011-05-13 16:21:08 -0700873 }
Mathias Agopianada798b2012-02-13 17:09:30 -0800874 if (err == EGL_SUCCESS) {
875 err = egl_tls_t::getError();
876 }
877 return err;
Mathias Agopian518ec112011-05-13 16:21:08 -0700878}
879
Michael Chockc0ec5e22014-01-27 08:14:33 -0800880static __eglMustCastToProperFunctionPointerType findBuiltinWrapper(
Jesse Hallc07b5202013-07-04 12:08:16 -0700881 const char* procname) {
882 const egl_connection_t* cnx = &gEGLImpl;
883 void* proc = NULL;
884
Michael Chockc0ec5e22014-01-27 08:14:33 -0800885 proc = dlsym(cnx->libEgl, procname);
886 if (proc) return (__eglMustCastToProperFunctionPointerType)proc;
887
Jesse Hallc07b5202013-07-04 12:08:16 -0700888 proc = dlsym(cnx->libGles2, procname);
889 if (proc) return (__eglMustCastToProperFunctionPointerType)proc;
890
891 proc = dlsym(cnx->libGles1, procname);
892 if (proc) return (__eglMustCastToProperFunctionPointerType)proc;
893
894 return NULL;
895}
896
Mathias Agopian518ec112011-05-13 16:21:08 -0700897__eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
898{
899 // eglGetProcAddress() could be the very first function called
900 // in which case we must make sure we've initialized ourselves, this
901 // happens the first time egl_get_display() is called.
902
903 clearError();
904
905 if (egl_init_drivers() == EGL_FALSE) {
906 setError(EGL_BAD_PARAMETER, NULL);
907 return NULL;
908 }
909
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700910 if (FILTER_EXTENSIONS(procname)) {
Jamie Gennisaca51c02011-11-03 17:42:43 -0700911 return NULL;
912 }
913
Mathias Agopian518ec112011-05-13 16:21:08 -0700914 __eglMustCastToProperFunctionPointerType addr;
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700915 addr = findProcAddress(procname, sExtensionMap, NELEM(sExtensionMap));
Mathias Agopian518ec112011-05-13 16:21:08 -0700916 if (addr) return addr;
917
Michael Chockc0ec5e22014-01-27 08:14:33 -0800918 addr = findBuiltinWrapper(procname);
Jesse Hallc07b5202013-07-04 12:08:16 -0700919 if (addr) return addr;
Jamie Gennisaca51c02011-11-03 17:42:43 -0700920
Mathias Agopian518ec112011-05-13 16:21:08 -0700921 // this protects accesses to sGLExtentionMap and sGLExtentionSlot
922 pthread_mutex_lock(&sExtensionMapMutex);
923
924 /*
925 * Since eglGetProcAddress() is not associated to anything, it needs
926 * to return a function pointer that "works" regardless of what
927 * the current context is.
928 *
929 * For this reason, we return a "forwarder", a small stub that takes
930 * care of calling the function associated with the context
931 * currently bound.
932 *
933 * We first look for extensions we've already resolved, if we're seeing
934 * this extension for the first time, we go through all our
935 * implementations and call eglGetProcAddress() and record the
936 * result in the appropriate implementation hooks and return the
937 * address of the forwarder corresponding to that hook set.
938 *
939 */
940
941 const String8 name(procname);
942 addr = sGLExtentionMap.valueFor(name);
943 const int slot = sGLExtentionSlot;
944
Steve Blocke6f43dd2012-01-06 19:20:56 +0000945 ALOGE_IF(slot >= MAX_NUMBER_OF_GL_EXTENSIONS,
Mathias Agopian518ec112011-05-13 16:21:08 -0700946 "no more slots for eglGetProcAddress(\"%s\")",
947 procname);
948
Siva Velusamy0469dd62011-11-30 15:05:37 -0800949#if EGL_TRACE
950 gl_hooks_t *debugHooks = GLTrace_getGLHooks();
951#endif
952
Mathias Agopian518ec112011-05-13 16:21:08 -0700953 if (!addr && (slot < MAX_NUMBER_OF_GL_EXTENSIONS)) {
954 bool found = false;
Mathias Agopianada798b2012-02-13 17:09:30 -0800955
956 egl_connection_t* const cnx = &gEGLImpl;
957 if (cnx->dso && cnx->egl.eglGetProcAddress) {
Mathias Agopianada798b2012-02-13 17:09:30 -0800958 // Extensions are independent of the bound context
luliuhui69d10072012-08-30 11:15:36 +0800959 addr =
Mathias Agopian7773c432012-02-13 20:06:08 -0800960 cnx->hooks[egl_connection_t::GLESv1_INDEX]->ext.extensions[slot] =
961 cnx->hooks[egl_connection_t::GLESv2_INDEX]->ext.extensions[slot] =
Mathias Agopian518ec112011-05-13 16:21:08 -0700962#if EGL_TRACE
Mathias Agopianada798b2012-02-13 17:09:30 -0800963 debugHooks->ext.extensions[slot] =
964 gHooksTrace.ext.extensions[slot] =
Mathias Agopian518ec112011-05-13 16:21:08 -0700965#endif
Mathias Agopianada798b2012-02-13 17:09:30 -0800966 cnx->egl.eglGetProcAddress(procname);
luliuhui69d10072012-08-30 11:15:36 +0800967 if (addr) found = true;
Mathias Agopian518ec112011-05-13 16:21:08 -0700968 }
Mathias Agopianada798b2012-02-13 17:09:30 -0800969
Mathias Agopian518ec112011-05-13 16:21:08 -0700970 if (found) {
971 addr = gExtensionForwarders[slot];
Mathias Agopian518ec112011-05-13 16:21:08 -0700972 sGLExtentionMap.add(name, addr);
973 sGLExtentionSlot++;
974 }
975 }
976
977 pthread_mutex_unlock(&sExtensionMapMutex);
978 return addr;
979}
980
Jamie Gennis28ef8d72012-04-05 20:34:54 -0700981class FrameCompletionThread : public Thread {
982public:
983
984 static void queueSync(EGLSyncKHR sync) {
985 static sp<FrameCompletionThread> thread(new FrameCompletionThread);
986 static bool running = false;
987 if (!running) {
988 thread->run("GPUFrameCompletion");
989 running = true;
990 }
991 {
992 Mutex::Autolock lock(thread->mMutex);
993 ScopedTrace st(ATRACE_TAG, String8::format("kicked off frame %d",
994 thread->mFramesQueued).string());
995 thread->mQueue.push_back(sync);
996 thread->mCondition.signal();
997 thread->mFramesQueued++;
998 ATRACE_INT("GPU Frames Outstanding", thread->mQueue.size());
999 }
1000 }
1001
1002private:
1003 FrameCompletionThread() : mFramesQueued(0), mFramesCompleted(0) {}
1004
1005 virtual bool threadLoop() {
1006 EGLSyncKHR sync;
1007 uint32_t frameNum;
1008 {
1009 Mutex::Autolock lock(mMutex);
1010 while (mQueue.isEmpty()) {
1011 mCondition.wait(mMutex);
1012 }
1013 sync = mQueue[0];
1014 frameNum = mFramesCompleted;
1015 }
1016 EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
1017 {
1018 ScopedTrace st(ATRACE_TAG, String8::format("waiting for frame %d",
1019 frameNum).string());
1020 EGLint result = eglClientWaitSyncKHR(dpy, sync, 0, EGL_FOREVER_KHR);
1021 if (result == EGL_FALSE) {
1022 ALOGE("FrameCompletion: error waiting for fence: %#x", eglGetError());
1023 } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
1024 ALOGE("FrameCompletion: timeout waiting for fence");
1025 }
1026 eglDestroySyncKHR(dpy, sync);
1027 }
1028 {
1029 Mutex::Autolock lock(mMutex);
1030 mQueue.removeAt(0);
1031 mFramesCompleted++;
1032 ATRACE_INT("GPU Frames Outstanding", mQueue.size());
1033 }
1034 return true;
1035 }
1036
1037 uint32_t mFramesQueued;
1038 uint32_t mFramesCompleted;
1039 Vector<EGLSyncKHR> mQueue;
1040 Condition mCondition;
1041 Mutex mMutex;
1042};
1043
Dan Stozaa894d082015-02-19 15:27:36 -08001044EGLBoolean eglSwapBuffersWithDamageKHR(EGLDisplay dpy, EGLSurface draw,
1045 EGLint *rects, EGLint n_rects)
Mathias Agopian518ec112011-05-13 16:21:08 -07001046{
Jamie Gennis1c8e95c2012-02-23 19:27:23 -08001047 ATRACE_CALL();
Mathias Agopian518ec112011-05-13 16:21:08 -07001048 clearError();
1049
Jesse Hallb29e5e82012-04-04 16:53:42 -07001050 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001051 if (!dp) return EGL_FALSE;
1052
Jesse Hallb29e5e82012-04-04 16:53:42 -07001053 SurfaceRef _s(dp.get(), draw);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001054 if (!_s.get())
1055 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001056
Siva Velusamy0469dd62011-11-30 15:05:37 -08001057#if EGL_TRACE
Siva Velusamya73a9772012-12-18 14:56:55 -08001058 gl_hooks_t const *trace_hooks = getGLTraceThreadSpecific();
1059 if (getEGLDebugLevel() > 0) {
1060 if (trace_hooks == NULL) {
1061 if (GLTrace_start() < 0) {
1062 ALOGE("Disabling Tracer for OpenGL ES");
1063 setEGLDebugLevel(0);
1064 } else {
1065 // switch over to the trace version of hooks
1066 EGLContext ctx = egl_tls_t::getContext();
1067 egl_context_t * const c = get_context(ctx);
1068 if (c) {
1069 setGLHooksThreadSpecific(c->cnx->hooks[c->version]);
1070 GLTrace_eglMakeCurrent(c->version, c->cnx->hooks[c->version], ctx);
1071 }
1072 }
1073 }
1074
Siva Velusamy0469dd62011-11-30 15:05:37 -08001075 GLTrace_eglSwapBuffers(dpy, draw);
Siva Velusamya73a9772012-12-18 14:56:55 -08001076 } else if (trace_hooks != NULL) {
1077 // tracing is now disabled, so switch back to the non trace version
1078 EGLContext ctx = egl_tls_t::getContext();
1079 egl_context_t * const c = get_context(ctx);
1080 if (c) setGLHooksThreadSpecific(c->cnx->hooks[c->version]);
1081 GLTrace_stop();
1082 }
Siva Velusamy0469dd62011-11-30 15:05:37 -08001083#endif
1084
Mathias Agopian518ec112011-05-13 16:21:08 -07001085 egl_surface_t const * const s = get_surface(draw);
Mathias Agopian7db993a2012-03-25 00:49:46 -07001086
Mathias Agopianed6d08b2013-04-16 16:39:46 -07001087 if (CC_UNLIKELY(dp->traceGpuCompletion)) {
1088 EGLSyncKHR sync = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, NULL);
1089 if (sync != EGL_NO_SYNC_KHR) {
1090 FrameCompletionThread::queueSync(sync);
1091 }
1092 }
1093
Mathias Agopian7db993a2012-03-25 00:49:46 -07001094 if (CC_UNLIKELY(dp->finishOnSwap)) {
1095 uint32_t pixel;
1096 egl_context_t * const c = get_context( egl_tls_t::getContext() );
1097 if (c) {
1098 // glReadPixels() ensures that the frame is complete
1099 s->cnx->hooks[c->version]->gl.glReadPixels(0,0,1,1,
1100 GL_RGBA,GL_UNSIGNED_BYTE,&pixel);
1101 }
1102 }
1103
Dan Stozaa894d082015-02-19 15:27:36 -08001104 if (n_rects == 0) {
1105 return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface);
1106 }
1107
1108 Vector<android_native_rect_t> androidRects;
1109 for (int r = 0; r < n_rects; ++r) {
1110 int offset = r * 4;
1111 int x = rects[offset];
1112 int y = rects[offset + 1];
1113 int width = rects[offset + 2];
1114 int height = rects[offset + 3];
1115 android_native_rect_t androidRect;
1116 androidRect.left = x;
1117 androidRect.top = y + height;
1118 androidRect.right = x + width;
1119 androidRect.bottom = y;
1120 androidRects.push_back(androidRect);
1121 }
1122 native_window_set_surface_damage(s->win.get(), androidRects.array(),
1123 androidRects.size());
1124
1125 if (s->cnx->egl.eglSwapBuffersWithDamageKHR) {
1126 return s->cnx->egl.eglSwapBuffersWithDamageKHR(dp->disp.dpy, s->surface,
1127 rects, n_rects);
1128 } else {
1129 return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface);
1130 }
1131}
1132
1133EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
1134{
1135 return eglSwapBuffersWithDamageKHR(dpy, surface, NULL, 0);
Mathias Agopian518ec112011-05-13 16:21:08 -07001136}
1137
1138EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface,
1139 NativePixmapType target)
1140{
1141 clearError();
1142
Jesse Hallb29e5e82012-04-04 16:53:42 -07001143 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001144 if (!dp) return EGL_FALSE;
1145
Jesse Hallb29e5e82012-04-04 16:53:42 -07001146 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001147 if (!_s.get())
1148 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001149
Mathias Agopian518ec112011-05-13 16:21:08 -07001150 egl_surface_t const * const s = get_surface(surface);
Mathias Agopianada798b2012-02-13 17:09:30 -08001151 return s->cnx->egl.eglCopyBuffers(dp->disp.dpy, s->surface, target);
Mathias Agopian518ec112011-05-13 16:21:08 -07001152}
1153
1154const char* eglQueryString(EGLDisplay dpy, EGLint name)
1155{
1156 clearError();
1157
Jesse Hallb29e5e82012-04-04 16:53:42 -07001158 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001159 if (!dp) return (const char *) NULL;
1160
1161 switch (name) {
1162 case EGL_VENDOR:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001163 return dp->getVendorString();
Mathias Agopian518ec112011-05-13 16:21:08 -07001164 case EGL_VERSION:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001165 return dp->getVersionString();
Mathias Agopian518ec112011-05-13 16:21:08 -07001166 case EGL_EXTENSIONS:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001167 return dp->getExtensionString();
Mathias Agopian518ec112011-05-13 16:21:08 -07001168 case EGL_CLIENT_APIS:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001169 return dp->getClientApiString();
Mathias Agopian518ec112011-05-13 16:21:08 -07001170 }
1171 return setError(EGL_BAD_PARAMETER, (const char *)0);
1172}
1173
Mathias Agopianca088332013-03-28 17:44:13 -07001174EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name)
1175{
1176 clearError();
1177
1178 const egl_display_ptr dp = validate_display(dpy);
1179 if (!dp) return (const char *) NULL;
1180
1181 switch (name) {
1182 case EGL_VENDOR:
1183 return dp->disp.queryString.vendor;
1184 case EGL_VERSION:
1185 return dp->disp.queryString.version;
1186 case EGL_EXTENSIONS:
1187 return dp->disp.queryString.extensions;
1188 case EGL_CLIENT_APIS:
1189 return dp->disp.queryString.clientApi;
1190 }
1191 return setError(EGL_BAD_PARAMETER, (const char *)0);
1192}
Mathias Agopian518ec112011-05-13 16:21:08 -07001193
1194// ----------------------------------------------------------------------------
1195// EGL 1.1
1196// ----------------------------------------------------------------------------
1197
1198EGLBoolean eglSurfaceAttrib(
1199 EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
1200{
1201 clearError();
1202
Jesse Hallb29e5e82012-04-04 16:53:42 -07001203 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001204 if (!dp) return EGL_FALSE;
1205
Jesse Hallb29e5e82012-04-04 16:53:42 -07001206 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001207 if (!_s.get())
1208 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001209
Mathias Agopian518ec112011-05-13 16:21:08 -07001210 egl_surface_t const * const s = get_surface(surface);
1211 if (s->cnx->egl.eglSurfaceAttrib) {
1212 return s->cnx->egl.eglSurfaceAttrib(
Mathias Agopianada798b2012-02-13 17:09:30 -08001213 dp->disp.dpy, s->surface, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -07001214 }
1215 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1216}
1217
1218EGLBoolean eglBindTexImage(
1219 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1220{
1221 clearError();
1222
Jesse Hallb29e5e82012-04-04 16:53:42 -07001223 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001224 if (!dp) return EGL_FALSE;
1225
Jesse Hallb29e5e82012-04-04 16:53:42 -07001226 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001227 if (!_s.get())
1228 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001229
Mathias Agopian518ec112011-05-13 16:21:08 -07001230 egl_surface_t const * const s = get_surface(surface);
1231 if (s->cnx->egl.eglBindTexImage) {
1232 return s->cnx->egl.eglBindTexImage(
Mathias Agopianada798b2012-02-13 17:09:30 -08001233 dp->disp.dpy, s->surface, buffer);
Mathias Agopian518ec112011-05-13 16:21:08 -07001234 }
1235 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1236}
1237
1238EGLBoolean eglReleaseTexImage(
1239 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1240{
1241 clearError();
1242
Jesse Hallb29e5e82012-04-04 16:53:42 -07001243 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001244 if (!dp) return EGL_FALSE;
1245
Jesse Hallb29e5e82012-04-04 16:53:42 -07001246 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001247 if (!_s.get())
1248 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001249
Mathias Agopian518ec112011-05-13 16:21:08 -07001250 egl_surface_t const * const s = get_surface(surface);
1251 if (s->cnx->egl.eglReleaseTexImage) {
1252 return s->cnx->egl.eglReleaseTexImage(
Mathias Agopianada798b2012-02-13 17:09:30 -08001253 dp->disp.dpy, s->surface, buffer);
Mathias Agopian518ec112011-05-13 16:21:08 -07001254 }
1255 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1256}
1257
1258EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
1259{
1260 clearError();
1261
Jesse Hallb29e5e82012-04-04 16:53:42 -07001262 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001263 if (!dp) return EGL_FALSE;
1264
1265 EGLBoolean res = EGL_TRUE;
Mathias Agopianada798b2012-02-13 17:09:30 -08001266 egl_connection_t* const cnx = &gEGLImpl;
1267 if (cnx->dso && cnx->egl.eglSwapInterval) {
1268 res = cnx->egl.eglSwapInterval(dp->disp.dpy, interval);
Mathias Agopian518ec112011-05-13 16:21:08 -07001269 }
Mathias Agopianada798b2012-02-13 17:09:30 -08001270
Mathias Agopian518ec112011-05-13 16:21:08 -07001271 return res;
1272}
1273
1274
1275// ----------------------------------------------------------------------------
1276// EGL 1.2
1277// ----------------------------------------------------------------------------
1278
1279EGLBoolean eglWaitClient(void)
1280{
1281 clearError();
1282
Mathias Agopianada798b2012-02-13 17:09:30 -08001283 egl_connection_t* const cnx = &gEGLImpl;
1284 if (!cnx->dso)
1285 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1286
1287 EGLBoolean res;
1288 if (cnx->egl.eglWaitClient) {
1289 res = cnx->egl.eglWaitClient();
1290 } else {
1291 res = cnx->egl.eglWaitGL();
Mathias Agopian518ec112011-05-13 16:21:08 -07001292 }
1293 return res;
1294}
1295
1296EGLBoolean eglBindAPI(EGLenum api)
1297{
1298 clearError();
1299
1300 if (egl_init_drivers() == EGL_FALSE) {
1301 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1302 }
1303
1304 // bind this API on all EGLs
1305 EGLBoolean res = EGL_TRUE;
Mathias Agopianada798b2012-02-13 17:09:30 -08001306 egl_connection_t* const cnx = &gEGLImpl;
1307 if (cnx->dso && cnx->egl.eglBindAPI) {
1308 res = cnx->egl.eglBindAPI(api);
Mathias Agopian518ec112011-05-13 16:21:08 -07001309 }
1310 return res;
1311}
1312
1313EGLenum eglQueryAPI(void)
1314{
1315 clearError();
1316
1317 if (egl_init_drivers() == EGL_FALSE) {
1318 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1319 }
1320
Mathias Agopianada798b2012-02-13 17:09:30 -08001321 egl_connection_t* const cnx = &gEGLImpl;
1322 if (cnx->dso && cnx->egl.eglQueryAPI) {
1323 return cnx->egl.eglQueryAPI();
Mathias Agopian518ec112011-05-13 16:21:08 -07001324 }
Mathias Agopianada798b2012-02-13 17:09:30 -08001325
Mathias Agopian518ec112011-05-13 16:21:08 -07001326 // or, it can only be OpenGL ES
1327 return EGL_OPENGL_ES_API;
1328}
1329
1330EGLBoolean eglReleaseThread(void)
1331{
1332 clearError();
1333
Mathias Agopian4e620dd2013-05-30 16:07:36 -07001334#if EGL_TRACE
1335 if (getEGLDebugLevel() > 0)
1336 GLTrace_eglReleaseThread();
1337#endif
1338
Mathias Agopian518ec112011-05-13 16:21:08 -07001339 // If there is context bound to the thread, release it
Mathias Agopianfb87e542012-01-30 18:20:52 -08001340 egl_display_t::loseCurrent(get_context(getContext()));
Mathias Agopian518ec112011-05-13 16:21:08 -07001341
Mathias Agopianada798b2012-02-13 17:09:30 -08001342 egl_connection_t* const cnx = &gEGLImpl;
1343 if (cnx->dso && cnx->egl.eglReleaseThread) {
1344 cnx->egl.eglReleaseThread();
Mathias Agopian518ec112011-05-13 16:21:08 -07001345 }
1346 egl_tls_t::clearTLS();
Mathias Agopian518ec112011-05-13 16:21:08 -07001347 return EGL_TRUE;
1348}
1349
1350EGLSurface eglCreatePbufferFromClientBuffer(
1351 EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer,
1352 EGLConfig config, const EGLint *attrib_list)
1353{
1354 clearError();
1355
Jesse Hallb29e5e82012-04-04 16:53:42 -07001356 egl_connection_t* cnx = NULL;
1357 const egl_display_ptr dp = validate_display_connection(dpy, cnx);
1358 if (!dp) return EGL_FALSE;
Mathias Agopian518ec112011-05-13 16:21:08 -07001359 if (cnx->egl.eglCreatePbufferFromClientBuffer) {
1360 return cnx->egl.eglCreatePbufferFromClientBuffer(
Mathias Agopian7773c432012-02-13 20:06:08 -08001361 dp->disp.dpy, buftype, buffer, config, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001362 }
1363 return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE);
1364}
1365
1366// ----------------------------------------------------------------------------
1367// EGL_EGLEXT_VERSION 3
1368// ----------------------------------------------------------------------------
1369
1370EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface,
1371 const EGLint *attrib_list)
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
Jesse Hallb29e5e82012-04-04 16:53:42 -07001378 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001379 if (!_s.get())
1380 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001381
1382 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian518ec112011-05-13 16:21:08 -07001383 if (s->cnx->egl.eglLockSurfaceKHR) {
1384 return s->cnx->egl.eglLockSurfaceKHR(
Mathias Agopianada798b2012-02-13 17:09:30 -08001385 dp->disp.dpy, s->surface, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001386 }
1387 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1388}
1389
1390EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface)
1391{
1392 clearError();
1393
Jesse Hallb29e5e82012-04-04 16:53:42 -07001394 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001395 if (!dp) return EGL_FALSE;
1396
Jesse Hallb29e5e82012-04-04 16:53:42 -07001397 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001398 if (!_s.get())
1399 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001400
1401 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian518ec112011-05-13 16:21:08 -07001402 if (s->cnx->egl.eglUnlockSurfaceKHR) {
Mathias Agopianada798b2012-02-13 17:09:30 -08001403 return s->cnx->egl.eglUnlockSurfaceKHR(dp->disp.dpy, s->surface);
Mathias Agopian518ec112011-05-13 16:21:08 -07001404 }
1405 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1406}
1407
1408EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
1409 EGLClientBuffer buffer, const EGLint *attrib_list)
1410{
1411 clearError();
1412
Jesse Hallb29e5e82012-04-04 16:53:42 -07001413 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001414 if (!dp) return EGL_NO_IMAGE_KHR;
1415
Jesse Hallb29e5e82012-04-04 16:53:42 -07001416 ContextRef _c(dp.get(), ctx);
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001417 egl_context_t * const c = _c.get();
Mathias Agopian518ec112011-05-13 16:21:08 -07001418
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001419 EGLImageKHR result = EGL_NO_IMAGE_KHR;
1420 egl_connection_t* const cnx = &gEGLImpl;
1421 if (cnx->dso && cnx->egl.eglCreateImageKHR) {
1422 result = cnx->egl.eglCreateImageKHR(
1423 dp->disp.dpy,
1424 c ? c->context : EGL_NO_CONTEXT,
1425 target, buffer, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001426 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001427 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001428}
1429
1430EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
1431{
1432 clearError();
1433
Jesse Hallb29e5e82012-04-04 16:53:42 -07001434 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001435 if (!dp) return EGL_FALSE;
1436
Steven Holte646a5c52012-06-04 20:02:11 -07001437 EGLBoolean result = EGL_FALSE;
Mathias Agopianada798b2012-02-13 17:09:30 -08001438 egl_connection_t* const cnx = &gEGLImpl;
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001439 if (cnx->dso && cnx->egl.eglDestroyImageKHR) {
Steven Holte646a5c52012-06-04 20:02:11 -07001440 result = cnx->egl.eglDestroyImageKHR(dp->disp.dpy, img);
Mathias Agopian518ec112011-05-13 16:21:08 -07001441 }
Steven Holte646a5c52012-06-04 20:02:11 -07001442 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001443}
1444
1445// ----------------------------------------------------------------------------
1446// EGL_EGLEXT_VERSION 5
1447// ----------------------------------------------------------------------------
1448
1449
1450EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
1451{
1452 clearError();
1453
Jesse Hallb29e5e82012-04-04 16:53:42 -07001454 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001455 if (!dp) return EGL_NO_SYNC_KHR;
1456
Mathias Agopian518ec112011-05-13 16:21:08 -07001457 EGLSyncKHR result = EGL_NO_SYNC_KHR;
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001458 egl_connection_t* const cnx = &gEGLImpl;
1459 if (cnx->dso && cnx->egl.eglCreateSyncKHR) {
1460 result = cnx->egl.eglCreateSyncKHR(dp->disp.dpy, type, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001461 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001462 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001463}
1464
1465EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
1466{
1467 clearError();
1468
Jesse Hallb29e5e82012-04-04 16:53:42 -07001469 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001470 if (!dp) return EGL_FALSE;
1471
Mathias Agopian518ec112011-05-13 16:21:08 -07001472 EGLBoolean result = EGL_FALSE;
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001473 egl_connection_t* const cnx = &gEGLImpl;
1474 if (cnx->dso && cnx->egl.eglDestroySyncKHR) {
1475 result = cnx->egl.eglDestroySyncKHR(dp->disp.dpy, sync);
Mathias Agopian518ec112011-05-13 16:21:08 -07001476 }
1477 return result;
1478}
1479
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -07001480EGLBoolean eglSignalSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode) {
1481 clearError();
1482
1483 const egl_display_ptr dp = validate_display(dpy);
1484 if (!dp) return EGL_FALSE;
1485
1486 EGLBoolean result = EGL_FALSE;
1487 egl_connection_t* const cnx = &gEGLImpl;
1488 if (cnx->dso && cnx->egl.eglSignalSyncKHR) {
1489 result = cnx->egl.eglSignalSyncKHR(
1490 dp->disp.dpy, sync, mode);
1491 }
1492 return result;
1493}
1494
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001495EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync,
1496 EGLint flags, EGLTimeKHR timeout)
Mathias Agopian518ec112011-05-13 16:21:08 -07001497{
1498 clearError();
1499
Jesse Hallb29e5e82012-04-04 16:53:42 -07001500 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001501 if (!dp) return EGL_FALSE;
1502
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001503 EGLBoolean result = EGL_FALSE;
1504 egl_connection_t* const cnx = &gEGLImpl;
1505 if (cnx->dso && cnx->egl.eglClientWaitSyncKHR) {
1506 result = cnx->egl.eglClientWaitSyncKHR(
1507 dp->disp.dpy, sync, flags, timeout);
Mathias Agopian518ec112011-05-13 16:21:08 -07001508 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001509 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001510}
1511
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001512EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync,
1513 EGLint attribute, EGLint *value)
Mathias Agopian518ec112011-05-13 16:21:08 -07001514{
1515 clearError();
1516
Jesse Hallb29e5e82012-04-04 16:53:42 -07001517 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001518 if (!dp) return EGL_FALSE;
1519
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001520 EGLBoolean result = EGL_FALSE;
1521 egl_connection_t* const cnx = &gEGLImpl;
1522 if (cnx->dso && cnx->egl.eglGetSyncAttribKHR) {
1523 result = cnx->egl.eglGetSyncAttribKHR(
1524 dp->disp.dpy, sync, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -07001525 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001526 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001527}
1528
1529// ----------------------------------------------------------------------------
Mathias Agopian2bb71682013-03-27 17:32:41 -07001530// EGL_EGLEXT_VERSION 15
1531// ----------------------------------------------------------------------------
1532
1533EGLint eglWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags) {
1534 clearError();
1535 const egl_display_ptr dp = validate_display(dpy);
1536 if (!dp) return EGL_FALSE;
1537 EGLint result = EGL_FALSE;
1538 egl_connection_t* const cnx = &gEGLImpl;
1539 if (cnx->dso && cnx->egl.eglWaitSyncKHR) {
1540 result = cnx->egl.eglWaitSyncKHR(dp->disp.dpy, sync, flags);
1541 }
1542 return result;
1543}
1544
1545// ----------------------------------------------------------------------------
Mathias Agopian518ec112011-05-13 16:21:08 -07001546// ANDROID extensions
1547// ----------------------------------------------------------------------------
1548
Jamie Gennis331841b2012-09-06 14:52:00 -07001549EGLint eglDupNativeFenceFDANDROID(EGLDisplay dpy, EGLSyncKHR sync)
1550{
1551 clearError();
1552
1553 const egl_display_ptr dp = validate_display(dpy);
1554 if (!dp) return EGL_NO_NATIVE_FENCE_FD_ANDROID;
1555
1556 EGLint result = EGL_NO_NATIVE_FENCE_FD_ANDROID;
1557 egl_connection_t* const cnx = &gEGLImpl;
1558 if (cnx->dso && cnx->egl.eglDupNativeFenceFDANDROID) {
1559 result = cnx->egl.eglDupNativeFenceFDANDROID(dp->disp.dpy, sync);
1560 }
1561 return result;
1562}
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001563
Andy McFadden72841452013-03-01 16:25:32 -08001564EGLBoolean eglPresentationTimeANDROID(EGLDisplay dpy, EGLSurface surface,
1565 EGLnsecsANDROID time)
1566{
1567 clearError();
1568
1569 const egl_display_ptr dp = validate_display(dpy);
1570 if (!dp) {
1571 return EGL_FALSE;
1572 }
1573
1574 SurfaceRef _s(dp.get(), surface);
1575 if (!_s.get()) {
1576 setError(EGL_BAD_SURFACE, EGL_FALSE);
1577 return EGL_FALSE;
1578 }
1579
1580 egl_surface_t const * const s = get_surface(surface);
1581 native_window_set_buffers_timestamp(s->win.get(), time);
1582
1583 return EGL_TRUE;
1584}
1585
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001586// ----------------------------------------------------------------------------
1587// NVIDIA extensions
1588// ----------------------------------------------------------------------------
1589EGLuint64NV eglGetSystemTimeFrequencyNV()
1590{
1591 clearError();
1592
1593 if (egl_init_drivers() == EGL_FALSE) {
1594 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1595 }
1596
1597 EGLuint64NV ret = 0;
Mathias Agopianada798b2012-02-13 17:09:30 -08001598 egl_connection_t* const cnx = &gEGLImpl;
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001599
Mathias Agopianada798b2012-02-13 17:09:30 -08001600 if (cnx->dso && cnx->egl.eglGetSystemTimeFrequencyNV) {
1601 return cnx->egl.eglGetSystemTimeFrequencyNV();
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001602 }
1603
Mathias Agopian0e8bbee2011-10-05 19:15:05 -07001604 return setErrorQuiet(EGL_BAD_DISPLAY, 0);
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001605}
1606
1607EGLuint64NV eglGetSystemTimeNV()
1608{
1609 clearError();
1610
1611 if (egl_init_drivers() == EGL_FALSE) {
1612 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1613 }
1614
1615 EGLuint64NV ret = 0;
Mathias Agopianada798b2012-02-13 17:09:30 -08001616 egl_connection_t* const cnx = &gEGLImpl;
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001617
Mathias Agopianada798b2012-02-13 17:09:30 -08001618 if (cnx->dso && cnx->egl.eglGetSystemTimeNV) {
1619 return cnx->egl.eglGetSystemTimeNV();
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001620 }
1621
Mathias Agopian0e8bbee2011-10-05 19:15:05 -07001622 return setErrorQuiet(EGL_BAD_DISPLAY, 0);
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001623}
Dan Stozaa894d082015-02-19 15:27:36 -08001624
1625// ----------------------------------------------------------------------------
1626// Partial update extension
1627// ----------------------------------------------------------------------------
1628EGLBoolean eglSetDamageRegionKHR(EGLDisplay dpy, EGLSurface surface,
1629 EGLint *rects, EGLint n_rects)
1630{
1631 clearError();
1632
1633 const egl_display_ptr dp = validate_display(dpy);
1634 if (!dp) {
1635 setError(EGL_BAD_DISPLAY, EGL_FALSE);
1636 return EGL_FALSE;
1637 }
1638
1639 SurfaceRef _s(dp.get(), surface);
1640 if (!_s.get()) {
1641 setError(EGL_BAD_SURFACE, EGL_FALSE);
1642 return EGL_FALSE;
1643 }
1644
1645 egl_surface_t const * const s = get_surface(surface);
1646 if (s->cnx->egl.eglSetDamageRegionKHR) {
1647 return s->cnx->egl.eglSetDamageRegionKHR(dp->disp.dpy, s->surface,
1648 rects, n_rects);
1649 }
1650
1651 return EGL_FALSE;
1652}