blob: 24394a98155dfaf316e5a75710a142e35c1e81bc [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
Craig Donner05249fc2016-01-15 19:33:55 -080036#include <ui/GraphicBuffer.h>
37
Mathias Agopian518ec112011-05-13 16:21:08 -070038#include <utils/KeyedVector.h>
39#include <utils/SortedVector.h>
40#include <utils/String8.h>
Jamie Gennis1c8e95c2012-02-23 19:27:23 -080041#include <utils/Trace.h>
Mathias Agopian518ec112011-05-13 16:21:08 -070042
Mathias Agopian39c24a22013-04-04 23:17:56 -070043#include "../egl_impl.h"
Mathias Agopian39c24a22013-04-04 23:17:56 -070044#include "../hooks.h"
Mathias Agopian518ec112011-05-13 16:21:08 -070045
46#include "egl_display.h"
Mathias Agopian518ec112011-05-13 16:21:08 -070047#include "egl_object.h"
48#include "egl_tls.h"
Mathias Agopianada798b2012-02-13 17:09:30 -080049#include "egldefs.h"
Mathias Agopian518ec112011-05-13 16:21:08 -070050
51using namespace android;
52
Jesse Halla2ba4282013-09-14 21:00:14 -070053// This extension has not been ratified yet, so can't be shipped.
54// Implementation is incomplete and untested.
55#define ENABLE_EGL_KHR_GL_COLORSPACE 0
56
Mathias Agopian518ec112011-05-13 16:21:08 -070057// ----------------------------------------------------------------------------
58
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070059namespace android {
60
Mathias Agopian518ec112011-05-13 16:21:08 -070061struct extention_map_t {
62 const char* name;
63 __eglMustCastToProperFunctionPointerType address;
64};
65
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070066/*
Jesse Hall21558da2013-08-06 15:31:22 -070067 * This is the list of EGL extensions exposed to applications.
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070068 *
Jesse Hall21558da2013-08-06 15:31:22 -070069 * Some of them (gBuiltinExtensionString) are implemented entirely in this EGL
70 * wrapper and are always available.
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070071 *
Jesse Hall21558da2013-08-06 15:31:22 -070072 * The rest (gExtensionString) depend on support in the EGL driver, and are
73 * only available if the driver supports them. However, some of these must be
74 * supported because they are used by the Android system itself; these are
Pablo Ceballos02b05da2016-02-02 17:53:18 -080075 * listed as mandatory below and are required by the CDD. The system *assumes*
Jesse Hall21558da2013-08-06 15:31:22 -070076 * the mandatory extensions are present and may not function properly if some
77 * are missing.
78 *
79 * NOTE: Both strings MUST have a single space as the last character.
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070080 */
Jesse Hall21558da2013-08-06 15:31:22 -070081extern char const * const gBuiltinExtensionString =
82 "EGL_KHR_get_all_proc_addresses "
83 "EGL_ANDROID_presentation_time "
Dan Stozaa894d082015-02-19 15:27:36 -080084 "EGL_KHR_swap_buffers_with_damage "
Craig Donner05249fc2016-01-15 19:33:55 -080085 "EGL_ANDROID_create_native_client_buffer "
Pablo Ceballos02b05da2016-02-02 17:53:18 -080086 "EGL_ANDROID_front_buffer_auto_refresh "
Jesse Hall21558da2013-08-06 15:31:22 -070087 ;
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070088extern char const * const gExtensionString =
89 "EGL_KHR_image " // mandatory
90 "EGL_KHR_image_base " // mandatory
91 "EGL_KHR_image_pixmap "
92 "EGL_KHR_lock_surface "
Jesse Halla2ba4282013-09-14 21:00:14 -070093#if (ENABLE_EGL_KHR_GL_COLORSPACE != 0)
Jesse Hallc2e41222013-08-08 13:40:22 -070094 "EGL_KHR_gl_colorspace "
Jesse Halla2ba4282013-09-14 21:00:14 -070095#endif
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070096 "EGL_KHR_gl_texture_2D_image "
Season Li000d88f2015-07-01 11:39:40 -070097 "EGL_KHR_gl_texture_3D_image "
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070098 "EGL_KHR_gl_texture_cubemap_image "
99 "EGL_KHR_gl_renderbuffer_image "
100 "EGL_KHR_reusable_sync "
101 "EGL_KHR_fence_sync "
Jamie Gennisf6d1c392013-04-25 18:48:41 -0700102 "EGL_KHR_create_context "
Season Li000d88f2015-07-01 11:39:40 -0700103 "EGL_KHR_config_attribs "
104 "EGL_KHR_surfaceless_context "
105 "EGL_KHR_stream "
106 "EGL_KHR_stream_fifo "
107 "EGL_KHR_stream_producer_eglsurface "
108 "EGL_KHR_stream_consumer_gltexture "
109 "EGL_KHR_stream_cross_process_fd "
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700110 "EGL_EXT_create_context_robustness "
111 "EGL_NV_system_time "
112 "EGL_ANDROID_image_native_buffer " // mandatory
Mathias Agopian2bb71682013-03-27 17:32:41 -0700113 "EGL_KHR_wait_sync " // strongly recommended
Jamie Gennisdbe92452013-09-23 17:22:10 -0700114 "EGL_ANDROID_recordable " // mandatory
Dan Stozaa894d082015-02-19 15:27:36 -0800115 "EGL_KHR_partial_update " // strongly recommended
116 "EGL_EXT_buffer_age " // strongly recommended with partial_update
Jesse Hall408e59f2015-04-24 01:40:42 -0700117 "EGL_KHR_create_context_no_error "
Pablo Ceballosceb9ee72016-04-13 11:17:32 -0700118 "EGL_KHR_mutable_render_buffer "
Mika Isojärvif37864b2016-04-15 11:58:56 -0700119 "EGL_EXT_yuv_surface "
Craig Donneraec86972016-04-28 18:09:40 -0700120 "EGL_EXT_protected_content "
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700121 ;
122
123// extensions not exposed to applications but used by the ANDROID system
124// "EGL_ANDROID_blob_cache " // strongly recommended
125// "EGL_IMG_hibernate_process " // optional
126// "EGL_ANDROID_native_fence_sync " // strongly recommended
127// "EGL_ANDROID_framebuffer_target " // mandatory for HWC 1.1
Jamie Gennisdbe92452013-09-23 17:22:10 -0700128// "EGL_ANDROID_image_crop " // optional
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700129
130/*
131 * EGL Extensions entry-points exposed to 3rd party applications
132 * (keep in sync with gExtensionString above)
133 *
134 */
135static const extention_map_t sExtensionMap[] = {
136 // EGL_KHR_lock_surface
Mathias Agopian518ec112011-05-13 16:21:08 -0700137 { "eglLockSurfaceKHR",
138 (__eglMustCastToProperFunctionPointerType)&eglLockSurfaceKHR },
139 { "eglUnlockSurfaceKHR",
140 (__eglMustCastToProperFunctionPointerType)&eglUnlockSurfaceKHR },
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700141
142 // EGL_KHR_image, EGL_KHR_image_base
Mathias Agopian518ec112011-05-13 16:21:08 -0700143 { "eglCreateImageKHR",
144 (__eglMustCastToProperFunctionPointerType)&eglCreateImageKHR },
145 { "eglDestroyImageKHR",
146 (__eglMustCastToProperFunctionPointerType)&eglDestroyImageKHR },
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700147
148 // EGL_KHR_reusable_sync, EGL_KHR_fence_sync
149 { "eglCreateSyncKHR",
150 (__eglMustCastToProperFunctionPointerType)&eglCreateSyncKHR },
151 { "eglDestroySyncKHR",
152 (__eglMustCastToProperFunctionPointerType)&eglDestroySyncKHR },
153 { "eglClientWaitSyncKHR",
154 (__eglMustCastToProperFunctionPointerType)&eglClientWaitSyncKHR },
155 { "eglSignalSyncKHR",
156 (__eglMustCastToProperFunctionPointerType)&eglSignalSyncKHR },
157 { "eglGetSyncAttribKHR",
158 (__eglMustCastToProperFunctionPointerType)&eglGetSyncAttribKHR },
159
160 // EGL_NV_system_time
Jonas Yang1c3d72a2011-08-26 20:04:39 +0800161 { "eglGetSystemTimeFrequencyNV",
162 (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeFrequencyNV },
163 { "eglGetSystemTimeNV",
164 (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeNV },
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700165
Mathias Agopian2bb71682013-03-27 17:32:41 -0700166 // EGL_KHR_wait_sync
167 { "eglWaitSyncKHR",
168 (__eglMustCastToProperFunctionPointerType)&eglWaitSyncKHR },
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700169
170 // EGL_ANDROID_presentation_time
171 { "eglPresentationTimeANDROID",
172 (__eglMustCastToProperFunctionPointerType)&eglPresentationTimeANDROID },
Dan Stozaa894d082015-02-19 15:27:36 -0800173
174 // EGL_KHR_swap_buffers_with_damage
175 { "eglSwapBuffersWithDamageKHR",
176 (__eglMustCastToProperFunctionPointerType)&eglSwapBuffersWithDamageKHR },
177
Craig Donner05249fc2016-01-15 19:33:55 -0800178 // EGL_ANDROID_native_client_buffer
179 { "eglCreateNativeClientBufferANDROID",
180 (__eglMustCastToProperFunctionPointerType)&eglCreateNativeClientBufferANDROID },
181
Dan Stozaa894d082015-02-19 15:27:36 -0800182 // EGL_KHR_partial_update
183 { "eglSetDamageRegionKHR",
184 (__eglMustCastToProperFunctionPointerType)&eglSetDamageRegionKHR },
Season Li000d88f2015-07-01 11:39:40 -0700185
186 { "eglCreateStreamKHR",
187 (__eglMustCastToProperFunctionPointerType)&eglCreateStreamKHR },
188 { "eglDestroyStreamKHR",
189 (__eglMustCastToProperFunctionPointerType)&eglDestroyStreamKHR },
190 { "eglStreamAttribKHR",
191 (__eglMustCastToProperFunctionPointerType)&eglStreamAttribKHR },
192 { "eglQueryStreamKHR",
193 (__eglMustCastToProperFunctionPointerType)&eglQueryStreamKHR },
194 { "eglQueryStreamu64KHR",
195 (__eglMustCastToProperFunctionPointerType)&eglQueryStreamu64KHR },
196 { "eglQueryStreamTimeKHR",
197 (__eglMustCastToProperFunctionPointerType)&eglQueryStreamTimeKHR },
198 { "eglCreateStreamProducerSurfaceKHR",
199 (__eglMustCastToProperFunctionPointerType)&eglCreateStreamProducerSurfaceKHR },
200 { "eglStreamConsumerGLTextureExternalKHR",
201 (__eglMustCastToProperFunctionPointerType)&eglStreamConsumerGLTextureExternalKHR },
202 { "eglStreamConsumerAcquireKHR",
203 (__eglMustCastToProperFunctionPointerType)&eglStreamConsumerAcquireKHR },
204 { "eglStreamConsumerReleaseKHR",
205 (__eglMustCastToProperFunctionPointerType)&eglStreamConsumerReleaseKHR },
206 { "eglGetStreamFileDescriptorKHR",
207 (__eglMustCastToProperFunctionPointerType)&eglGetStreamFileDescriptorKHR },
208 { "eglCreateStreamFromFileDescriptorKHR",
209 (__eglMustCastToProperFunctionPointerType)&eglCreateStreamFromFileDescriptorKHR },
Mathias Agopian518ec112011-05-13 16:21:08 -0700210};
211
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700212/*
213 * These extensions entry-points should not be exposed to applications.
214 * They're used internally by the Android EGL layer.
215 */
216#define FILTER_EXTENSIONS(procname) \
217 (!strcmp((procname), "eglSetBlobCacheFuncsANDROID") || \
218 !strcmp((procname), "eglHibernateProcessIMG") || \
219 !strcmp((procname), "eglAwakenProcessIMG") || \
220 !strcmp((procname), "eglDupNativeFenceFDANDROID"))
221
222
223
Mathias Agopian518ec112011-05-13 16:21:08 -0700224// accesses protected by sExtensionMapMutex
225static DefaultKeyedVector<String8, __eglMustCastToProperFunctionPointerType> sGLExtentionMap;
226static int sGLExtentionSlot = 0;
227static pthread_mutex_t sExtensionMapMutex = PTHREAD_MUTEX_INITIALIZER;
228
229static void(*findProcAddress(const char* name,
230 const extention_map_t* map, size_t n))() {
231 for (uint32_t i=0 ; i<n ; i++) {
232 if (!strcmp(name, map[i].name)) {
233 return map[i].address;
234 }
235 }
236 return NULL;
237}
238
239// ----------------------------------------------------------------------------
240
Mathias Agopian518ec112011-05-13 16:21:08 -0700241extern void setGLHooksThreadSpecific(gl_hooks_t const *value);
242extern EGLBoolean egl_init_drivers();
243extern const __eglMustCastToProperFunctionPointerType gExtensionForwarders[MAX_NUMBER_OF_GL_EXTENSIONS];
Mathias Agopian518ec112011-05-13 16:21:08 -0700244extern gl_hooks_t gHooksTrace;
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700245
Mathias Agopian518ec112011-05-13 16:21:08 -0700246} // namespace android;
247
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700248
Mathias Agopian518ec112011-05-13 16:21:08 -0700249// ----------------------------------------------------------------------------
250
251static inline void clearError() { egl_tls_t::clearError(); }
252static inline EGLContext getContext() { return egl_tls_t::getContext(); }
253
254// ----------------------------------------------------------------------------
255
256EGLDisplay eglGetDisplay(EGLNativeDisplayType display)
257{
258 clearError();
259
Dan Stozac3289c42014-01-17 11:38:34 -0800260 uintptr_t index = reinterpret_cast<uintptr_t>(display);
Mathias Agopian518ec112011-05-13 16:21:08 -0700261 if (index >= NUM_DISPLAYS) {
262 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
263 }
264
265 if (egl_init_drivers() == EGL_FALSE) {
266 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
267 }
268
269 EGLDisplay dpy = egl_display_t::getFromNativeDisplay(display);
270 return dpy;
271}
272
273// ----------------------------------------------------------------------------
274// Initialization
275// ----------------------------------------------------------------------------
276
277EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
278{
279 clearError();
280
Jesse Hallb29e5e82012-04-04 16:53:42 -0700281 egl_display_ptr dp = get_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700282 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
283
284 EGLBoolean res = dp->initialize(major, minor);
285
286 return res;
287}
288
289EGLBoolean eglTerminate(EGLDisplay dpy)
290{
291 // NOTE: don't unload the drivers b/c some APIs can be called
292 // after eglTerminate() has been called. eglTerminate() only
293 // terminates an EGLDisplay, not a EGL itself.
294
295 clearError();
296
Jesse Hallb29e5e82012-04-04 16:53:42 -0700297 egl_display_ptr dp = get_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700298 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
299
300 EGLBoolean res = dp->terminate();
Jesse Hall47743382013-02-08 11:13:46 -0800301
Mathias Agopian518ec112011-05-13 16:21:08 -0700302 return res;
303}
304
305// ----------------------------------------------------------------------------
306// configuration
307// ----------------------------------------------------------------------------
308
309EGLBoolean eglGetConfigs( EGLDisplay dpy,
310 EGLConfig *configs,
311 EGLint config_size, EGLint *num_config)
312{
313 clearError();
314
Jesse Hallb29e5e82012-04-04 16:53:42 -0700315 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700316 if (!dp) return EGL_FALSE;
317
Mathias Agopian7773c432012-02-13 20:06:08 -0800318 if (num_config==0) {
319 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700320 }
321
Mathias Agopian7773c432012-02-13 20:06:08 -0800322 EGLBoolean res = EGL_FALSE;
323 *num_config = 0;
324
325 egl_connection_t* const cnx = &gEGLImpl;
326 if (cnx->dso) {
327 res = cnx->egl.eglGetConfigs(
328 dp->disp.dpy, configs, config_size, num_config);
Mathias Agopian518ec112011-05-13 16:21:08 -0700329 }
Mathias Agopian7773c432012-02-13 20:06:08 -0800330
331 return res;
Mathias Agopian518ec112011-05-13 16:21:08 -0700332}
333
334EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list,
335 EGLConfig *configs, EGLint config_size,
336 EGLint *num_config)
337{
338 clearError();
339
Jesse Hallb29e5e82012-04-04 16:53:42 -0700340 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700341 if (!dp) return EGL_FALSE;
342
343 if (num_config==0) {
344 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
345 }
346
Mathias Agopian518ec112011-05-13 16:21:08 -0700347 EGLBoolean res = EGL_FALSE;
348 *num_config = 0;
349
Mathias Agopianada798b2012-02-13 17:09:30 -0800350 egl_connection_t* const cnx = &gEGLImpl;
351 if (cnx->dso) {
Romain Guy1cffc802012-10-15 18:13:05 -0700352 if (attrib_list) {
353 char value[PROPERTY_VALUE_MAX];
354 property_get("debug.egl.force_msaa", value, "false");
355
356 if (!strcmp(value, "true")) {
357 size_t attribCount = 0;
358 EGLint attrib = attrib_list[0];
359
360 // Only enable MSAA if the context is OpenGL ES 2.0 and
Romain Guybe3c3e42012-10-15 19:25:18 -0700361 // if no caveat is requested
Romain Guy1cffc802012-10-15 18:13:05 -0700362 const EGLint *attribRendererable = NULL;
363 const EGLint *attribCaveat = NULL;
364
365 // Count the number of attributes and look for
Romain Guybe3c3e42012-10-15 19:25:18 -0700366 // EGL_RENDERABLE_TYPE and EGL_CONFIG_CAVEAT
Romain Guy1cffc802012-10-15 18:13:05 -0700367 while (attrib != EGL_NONE) {
368 attrib = attrib_list[attribCount];
369 switch (attrib) {
370 case EGL_RENDERABLE_TYPE:
371 attribRendererable = &attrib_list[attribCount];
372 break;
373 case EGL_CONFIG_CAVEAT:
374 attribCaveat = &attrib_list[attribCount];
375 break;
376 }
377 attribCount++;
378 }
379
380 if (attribRendererable && attribRendererable[1] == EGL_OPENGL_ES2_BIT &&
381 (!attribCaveat || attribCaveat[1] != EGL_NONE)) {
Jesse Hall47743382013-02-08 11:13:46 -0800382
Romain Guy1cffc802012-10-15 18:13:05 -0700383 // Insert 2 extra attributes to force-enable MSAA 4x
384 EGLint aaAttribs[attribCount + 4];
385 aaAttribs[0] = EGL_SAMPLE_BUFFERS;
386 aaAttribs[1] = 1;
387 aaAttribs[2] = EGL_SAMPLES;
388 aaAttribs[3] = 4;
389
390 memcpy(&aaAttribs[4], attrib_list, attribCount * sizeof(EGLint));
391
392 EGLint numConfigAA;
393 EGLBoolean resAA = cnx->egl.eglChooseConfig(
394 dp->disp.dpy, aaAttribs, configs, config_size, &numConfigAA);
395
396 if (resAA == EGL_TRUE && numConfigAA > 0) {
397 ALOGD("Enabling MSAA 4x");
398 *num_config = numConfigAA;
399 return resAA;
400 }
401 }
402 }
403 }
404
Mathias Agopian7773c432012-02-13 20:06:08 -0800405 res = cnx->egl.eglChooseConfig(
406 dp->disp.dpy, attrib_list, configs, config_size, num_config);
Mathias Agopian518ec112011-05-13 16:21:08 -0700407 }
408 return res;
409}
410
411EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
412 EGLint attribute, EGLint *value)
413{
414 clearError();
415
Jesse Hallb29e5e82012-04-04 16:53:42 -0700416 egl_connection_t* cnx = NULL;
417 const egl_display_ptr dp = validate_display_connection(dpy, cnx);
418 if (!dp) return EGL_FALSE;
Jesse Hall47743382013-02-08 11:13:46 -0800419
Mathias Agopian518ec112011-05-13 16:21:08 -0700420 return cnx->egl.eglGetConfigAttrib(
Mathias Agopian7773c432012-02-13 20:06:08 -0800421 dp->disp.dpy, config, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -0700422}
423
424// ----------------------------------------------------------------------------
425// surfaces
426// ----------------------------------------------------------------------------
427
Jesse Halla2ba4282013-09-14 21:00:14 -0700428// The EGL_KHR_gl_colorspace spec hasn't been ratified yet, so these haven't
Jesse Hallc2e41222013-08-08 13:40:22 -0700429// been added to the Khronos egl.h.
430#define EGL_GL_COLORSPACE_KHR EGL_VG_COLORSPACE
431#define EGL_GL_COLORSPACE_SRGB_KHR EGL_VG_COLORSPACE_sRGB
432#define EGL_GL_COLORSPACE_LINEAR_KHR EGL_VG_COLORSPACE_LINEAR
433
434// Turn linear formats into corresponding sRGB formats when colorspace is
435// EGL_GL_COLORSPACE_SRGB_KHR, or turn sRGB formats into corresponding linear
436// formats when colorspace is EGL_GL_COLORSPACE_LINEAR_KHR. In any cases where
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800437// the modification isn't possible, the original dataSpace is returned.
438static android_dataspace modifyBufferDataspace( android_dataspace dataSpace,
439 EGLint colorspace) {
Jesse Hallc2e41222013-08-08 13:40:22 -0700440 if (colorspace == EGL_GL_COLORSPACE_LINEAR_KHR) {
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800441 return HAL_DATASPACE_SRGB_LINEAR;
Jesse Hallc2e41222013-08-08 13:40:22 -0700442 } else if (colorspace == EGL_GL_COLORSPACE_SRGB_KHR) {
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800443 return HAL_DATASPACE_SRGB;
Jesse Hallc2e41222013-08-08 13:40:22 -0700444 }
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800445 return dataSpace;
Jesse Hallc2e41222013-08-08 13:40:22 -0700446}
447
Mathias Agopian518ec112011-05-13 16:21:08 -0700448EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config,
449 NativeWindowType window,
450 const EGLint *attrib_list)
451{
452 clearError();
453
Jesse Hallb29e5e82012-04-04 16:53:42 -0700454 egl_connection_t* cnx = NULL;
455 egl_display_ptr dp = validate_display_connection(dpy, cnx);
456 if (dp) {
Mathias Agopianada798b2012-02-13 17:09:30 -0800457 EGLDisplay iDpy = dp->disp.dpy;
Mathias Agopian518ec112011-05-13 16:21:08 -0700458
Andy McFaddend566ce32014-01-07 15:54:17 -0800459 int result = native_window_api_connect(window, NATIVE_WINDOW_API_EGL);
460 if (result != OK) {
461 ALOGE("eglCreateWindowSurface: native_window_api_connect (win=%p) "
462 "failed (%#x) (already connected to another API?)",
463 window, result);
Jonathan Hamilton77a9b4a2013-07-17 09:41:42 -0700464 return setError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
Mathias Agopian81a63352011-07-29 17:55:48 -0700465 }
466
Mathias Agopian0f288fc2013-08-21 16:36:34 -0700467 // Set the native window's buffers format to match what this config requests.
Jesse Hallc2e41222013-08-08 13:40:22 -0700468 // Whether to use sRGB gamma is not part of the EGLconfig, but is part
469 // of our native format. So if sRGB gamma is requested, we have to
470 // modify the EGLconfig's format before setting the native window's
471 // format.
Alistair Strachan733a8072015-02-12 12:33:25 -0800472
Mathias Agopian0f288fc2013-08-21 16:36:34 -0700473 // by default, just pick RGBA_8888
474 EGLint format = HAL_PIXEL_FORMAT_RGBA_8888;
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800475 android_dataspace dataSpace = HAL_DATASPACE_UNKNOWN;
Mathias Agopian0f288fc2013-08-21 16:36:34 -0700476
477 EGLint a = 0;
478 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_ALPHA_SIZE, &a);
479 if (a > 0) {
480 // alpha-channel requested, there's really only one suitable format
481 format = HAL_PIXEL_FORMAT_RGBA_8888;
482 } else {
483 EGLint r, g, b;
484 r = g = b = 0;
485 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_RED_SIZE, &r);
486 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_GREEN_SIZE, &g);
487 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_BLUE_SIZE, &b);
488 EGLint colorDepth = r + g + b;
489 if (colorDepth <= 16) {
490 format = HAL_PIXEL_FORMAT_RGB_565;
491 } else {
492 format = HAL_PIXEL_FORMAT_RGBX_8888;
493 }
Jesse Hallc2e41222013-08-08 13:40:22 -0700494 }
Mathias Agopian0f288fc2013-08-21 16:36:34 -0700495
496 // now select a corresponding sRGB format if needed
497 if (attrib_list && dp->haveExtension("EGL_KHR_gl_colorspace")) {
498 for (const EGLint* attr = attrib_list; *attr != EGL_NONE; attr += 2) {
499 if (*attr == EGL_GL_COLORSPACE_KHR) {
Jesse Halla2ba4282013-09-14 21:00:14 -0700500 if (ENABLE_EGL_KHR_GL_COLORSPACE) {
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800501 dataSpace = modifyBufferDataspace(dataSpace, *(attr+1));
Jesse Halla2ba4282013-09-14 21:00:14 -0700502 } else {
503 // Normally we'd pass through unhandled attributes to
504 // the driver. But in case the driver implements this
505 // extension but we're disabling it, we want to prevent
506 // it getting through -- support will be broken without
507 // our help.
508 ALOGE("sRGB window surfaces not supported");
509 return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
510 }
Jamie Gennisbee205f2011-07-01 13:12:07 -0700511 }
Mathias Agopian518ec112011-05-13 16:21:08 -0700512 }
513 }
Alistair Strachan733a8072015-02-12 12:33:25 -0800514
Jesse Hallc2e41222013-08-08 13:40:22 -0700515 if (format != 0) {
516 int err = native_window_set_buffers_format(window, format);
517 if (err != 0) {
518 ALOGE("error setting native window pixel format: %s (%d)",
519 strerror(-err), err);
520 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
521 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
522 }
523 }
Mathias Agopian518ec112011-05-13 16:21:08 -0700524
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800525 if (dataSpace != 0) {
526 int err = native_window_set_buffers_data_space(window, dataSpace);
527 if (err != 0) {
528 ALOGE("error setting native window pixel dataSpace: %s (%d)",
529 strerror(-err), err);
530 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
531 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
532 }
533 }
534
Jamie Gennis59769462011-11-19 18:04:43 -0800535 // the EGL spec requires that a new EGLSurface default to swap interval
536 // 1, so explicitly set that on the window here.
537 ANativeWindow* anw = reinterpret_cast<ANativeWindow*>(window);
538 anw->setSwapInterval(anw, 1);
539
Mathias Agopian518ec112011-05-13 16:21:08 -0700540 EGLSurface surface = cnx->egl.eglCreateWindowSurface(
Mathias Agopian7773c432012-02-13 20:06:08 -0800541 iDpy, config, window, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700542 if (surface != EGL_NO_SURFACE) {
Jesse Hallb29e5e82012-04-04 16:53:42 -0700543 egl_surface_t* s = new egl_surface_t(dp.get(), config, window,
544 surface, cnx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700545 return s;
546 }
Mathias Agopian81a63352011-07-29 17:55:48 -0700547
548 // EGLSurface creation failed
549 native_window_set_buffers_format(window, 0);
550 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
Mathias Agopian518ec112011-05-13 16:21:08 -0700551 }
552 return EGL_NO_SURFACE;
553}
554
555EGLSurface eglCreatePixmapSurface( EGLDisplay dpy, EGLConfig config,
556 NativePixmapType pixmap,
557 const EGLint *attrib_list)
558{
559 clearError();
560
Jesse Hallb29e5e82012-04-04 16:53:42 -0700561 egl_connection_t* cnx = NULL;
562 egl_display_ptr dp = validate_display_connection(dpy, cnx);
563 if (dp) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700564 EGLSurface surface = cnx->egl.eglCreatePixmapSurface(
Mathias Agopian7773c432012-02-13 20:06:08 -0800565 dp->disp.dpy, config, pixmap, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700566 if (surface != EGL_NO_SURFACE) {
Jesse Hallb29e5e82012-04-04 16:53:42 -0700567 egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL,
568 surface, cnx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700569 return s;
570 }
571 }
572 return EGL_NO_SURFACE;
573}
574
575EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config,
576 const EGLint *attrib_list)
577{
578 clearError();
579
Jesse Hallb29e5e82012-04-04 16:53:42 -0700580 egl_connection_t* cnx = NULL;
581 egl_display_ptr dp = validate_display_connection(dpy, cnx);
582 if (dp) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700583 EGLSurface surface = cnx->egl.eglCreatePbufferSurface(
Mathias Agopian7773c432012-02-13 20:06:08 -0800584 dp->disp.dpy, config, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700585 if (surface != EGL_NO_SURFACE) {
Jesse Hallb29e5e82012-04-04 16:53:42 -0700586 egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL,
587 surface, cnx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700588 return s;
589 }
590 }
591 return EGL_NO_SURFACE;
592}
Jesse Hall47743382013-02-08 11:13:46 -0800593
Mathias Agopian518ec112011-05-13 16:21:08 -0700594EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
595{
596 clearError();
597
Jesse Hallb29e5e82012-04-04 16:53:42 -0700598 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700599 if (!dp) return EGL_FALSE;
600
Jesse Hallb29e5e82012-04-04 16:53:42 -0700601 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700602 if (!_s.get())
603 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700604
605 egl_surface_t * const s = get_surface(surface);
Mathias Agopianada798b2012-02-13 17:09:30 -0800606 EGLBoolean result = s->cnx->egl.eglDestroySurface(dp->disp.dpy, s->surface);
Mathias Agopian518ec112011-05-13 16:21:08 -0700607 if (result == EGL_TRUE) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700608 _s.terminate();
609 }
610 return result;
611}
612
613EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface surface,
614 EGLint attribute, EGLint *value)
615{
616 clearError();
617
Jesse Hallb29e5e82012-04-04 16:53:42 -0700618 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700619 if (!dp) return EGL_FALSE;
620
Jesse Hallb29e5e82012-04-04 16:53:42 -0700621 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700622 if (!_s.get())
623 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700624
Mathias Agopian518ec112011-05-13 16:21:08 -0700625 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian7773c432012-02-13 20:06:08 -0800626 return s->cnx->egl.eglQuerySurface(
627 dp->disp.dpy, s->surface, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -0700628}
629
Jamie Gennise8696a42012-01-15 18:54:57 -0800630void EGLAPI eglBeginFrame(EGLDisplay dpy, EGLSurface surface) {
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800631 ATRACE_CALL();
Jamie Gennise8696a42012-01-15 18:54:57 -0800632 clearError();
633
Jesse Hallb29e5e82012-04-04 16:53:42 -0700634 const egl_display_ptr dp = validate_display(dpy);
Jamie Gennise8696a42012-01-15 18:54:57 -0800635 if (!dp) {
636 return;
637 }
638
Jesse Hallb29e5e82012-04-04 16:53:42 -0700639 SurfaceRef _s(dp.get(), surface);
Jamie Gennise8696a42012-01-15 18:54:57 -0800640 if (!_s.get()) {
641 setError(EGL_BAD_SURFACE, EGL_FALSE);
642 return;
643 }
Jamie Gennise8696a42012-01-15 18:54:57 -0800644}
645
Mathias Agopian518ec112011-05-13 16:21:08 -0700646// ----------------------------------------------------------------------------
647// Contexts
648// ----------------------------------------------------------------------------
649
650EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config,
651 EGLContext share_list, const EGLint *attrib_list)
652{
653 clearError();
654
Jesse Hallb29e5e82012-04-04 16:53:42 -0700655 egl_connection_t* cnx = NULL;
656 const egl_display_ptr dp = validate_display_connection(dpy, cnx);
Michael Chock0673e1e2012-06-21 12:53:17 -0700657 if (dp) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700658 if (share_list != EGL_NO_CONTEXT) {
Michael Chock0673e1e2012-06-21 12:53:17 -0700659 if (!ContextRef(dp.get(), share_list).get()) {
660 return setError(EGL_BAD_CONTEXT, EGL_NO_CONTEXT);
661 }
Mathias Agopian518ec112011-05-13 16:21:08 -0700662 egl_context_t* const c = get_context(share_list);
663 share_list = c->context;
664 }
665 EGLContext context = cnx->egl.eglCreateContext(
Mathias Agopian7773c432012-02-13 20:06:08 -0800666 dp->disp.dpy, config, share_list, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700667 if (context != EGL_NO_CONTEXT) {
668 // figure out if it's a GLESv1 or GLESv2
669 int version = 0;
670 if (attrib_list) {
671 while (*attrib_list != EGL_NONE) {
672 GLint attr = *attrib_list++;
673 GLint value = *attrib_list++;
674 if (attr == EGL_CONTEXT_CLIENT_VERSION) {
675 if (value == 1) {
Mathias Agopian7773c432012-02-13 20:06:08 -0800676 version = egl_connection_t::GLESv1_INDEX;
Jesse Hall47743382013-02-08 11:13:46 -0800677 } else if (value == 2 || value == 3) {
Mathias Agopian7773c432012-02-13 20:06:08 -0800678 version = egl_connection_t::GLESv2_INDEX;
Mathias Agopian518ec112011-05-13 16:21:08 -0700679 }
680 }
681 };
682 }
Jesse Hallb29e5e82012-04-04 16:53:42 -0700683 egl_context_t* c = new egl_context_t(dpy, context, config, cnx,
684 version);
Mathias Agopian518ec112011-05-13 16:21:08 -0700685 return c;
686 }
687 }
688 return EGL_NO_CONTEXT;
689}
690
691EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
692{
693 clearError();
694
Jesse Hallb29e5e82012-04-04 16:53:42 -0700695 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700696 if (!dp)
697 return EGL_FALSE;
Mathias Agopian518ec112011-05-13 16:21:08 -0700698
Jesse Hallb29e5e82012-04-04 16:53:42 -0700699 ContextRef _c(dp.get(), ctx);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700700 if (!_c.get())
701 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
Jesse Hall47743382013-02-08 11:13:46 -0800702
Mathias Agopian518ec112011-05-13 16:21:08 -0700703 egl_context_t * const c = get_context(ctx);
Mathias Agopianada798b2012-02-13 17:09:30 -0800704 EGLBoolean result = c->cnx->egl.eglDestroyContext(dp->disp.dpy, c->context);
Mathias Agopian518ec112011-05-13 16:21:08 -0700705 if (result == EGL_TRUE) {
706 _c.terminate();
707 }
708 return result;
709}
710
Mathias Agopian518ec112011-05-13 16:21:08 -0700711EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw,
712 EGLSurface read, EGLContext ctx)
713{
714 clearError();
715
Jesse Hallb29e5e82012-04-04 16:53:42 -0700716 egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700717 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
718
Mathias Agopian5b287a62011-05-16 18:58:55 -0700719 // If ctx is not EGL_NO_CONTEXT, read is not EGL_NO_SURFACE, or draw is not
720 // EGL_NO_SURFACE, then an EGL_NOT_INITIALIZED error is generated if dpy is
721 // a valid but uninitialized display.
Mathias Agopian518ec112011-05-13 16:21:08 -0700722 if ( (ctx != EGL_NO_CONTEXT) || (read != EGL_NO_SURFACE) ||
723 (draw != EGL_NO_SURFACE) ) {
724 if (!dp->isReady()) return setError(EGL_NOT_INITIALIZED, EGL_FALSE);
725 }
726
727 // get a reference to the object passed in
Jesse Hallb29e5e82012-04-04 16:53:42 -0700728 ContextRef _c(dp.get(), ctx);
729 SurfaceRef _d(dp.get(), draw);
730 SurfaceRef _r(dp.get(), read);
Mathias Agopian518ec112011-05-13 16:21:08 -0700731
732 // validate the context (if not EGL_NO_CONTEXT)
Mathias Agopian5b287a62011-05-16 18:58:55 -0700733 if ((ctx != EGL_NO_CONTEXT) && !_c.get()) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700734 // EGL_NO_CONTEXT is valid
Michael Chock0673e1e2012-06-21 12:53:17 -0700735 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700736 }
737
738 // these are the underlying implementation's object
739 EGLContext impl_ctx = EGL_NO_CONTEXT;
740 EGLSurface impl_draw = EGL_NO_SURFACE;
741 EGLSurface impl_read = EGL_NO_SURFACE;
742
743 // these are our objects structs passed in
744 egl_context_t * c = NULL;
745 egl_surface_t const * d = NULL;
746 egl_surface_t const * r = NULL;
747
748 // these are the current objects structs
749 egl_context_t * cur_c = get_context(getContext());
Jesse Hall47743382013-02-08 11:13:46 -0800750
Mathias Agopian518ec112011-05-13 16:21:08 -0700751 if (ctx != EGL_NO_CONTEXT) {
752 c = get_context(ctx);
753 impl_ctx = c->context;
754 } else {
755 // no context given, use the implementation of the current context
Michael Chock0673e1e2012-06-21 12:53:17 -0700756 if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE) {
757 // calling eglMakeCurrent( ..., !=0, !=0, EGL_NO_CONTEXT);
758 return setError(EGL_BAD_MATCH, EGL_FALSE);
759 }
Mathias Agopian518ec112011-05-13 16:21:08 -0700760 if (cur_c == NULL) {
761 // no current context
Mathias Agopian518ec112011-05-13 16:21:08 -0700762 // not an error, there is just no current context.
763 return EGL_TRUE;
764 }
765 }
766
767 // retrieve the underlying implementation's draw EGLSurface
768 if (draw != EGL_NO_SURFACE) {
Michael Chock0673e1e2012-06-21 12:53:17 -0700769 if (!_d.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700770 d = get_surface(draw);
Mathias Agopian518ec112011-05-13 16:21:08 -0700771 impl_draw = d->surface;
772 }
773
774 // retrieve the underlying implementation's read EGLSurface
775 if (read != EGL_NO_SURFACE) {
Michael Chock0673e1e2012-06-21 12:53:17 -0700776 if (!_r.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700777 r = get_surface(read);
Mathias Agopian518ec112011-05-13 16:21:08 -0700778 impl_read = r->surface;
779 }
780
Mathias Agopian518ec112011-05-13 16:21:08 -0700781
Jesse Hallb29e5e82012-04-04 16:53:42 -0700782 EGLBoolean result = dp->makeCurrent(c, cur_c,
Mathias Agopianfb87e542012-01-30 18:20:52 -0800783 draw, read, ctx,
784 impl_draw, impl_read, impl_ctx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700785
786 if (result == EGL_TRUE) {
Mathias Agopianfb87e542012-01-30 18:20:52 -0800787 if (c) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700788 setGLHooksThreadSpecific(c->cnx->hooks[c->version]);
789 egl_tls_t::setContext(ctx);
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
974 if (!addr && (slot < MAX_NUMBER_OF_GL_EXTENSIONS)) {
975 bool found = false;
Mathias Agopianada798b2012-02-13 17:09:30 -0800976
977 egl_connection_t* const cnx = &gEGLImpl;
978 if (cnx->dso && cnx->egl.eglGetProcAddress) {
Mathias Agopianada798b2012-02-13 17:09:30 -0800979 // Extensions are independent of the bound context
luliuhui69d10072012-08-30 11:15:36 +0800980 addr =
Mathias Agopian7773c432012-02-13 20:06:08 -0800981 cnx->hooks[egl_connection_t::GLESv1_INDEX]->ext.extensions[slot] =
982 cnx->hooks[egl_connection_t::GLESv2_INDEX]->ext.extensions[slot] =
Mathias Agopianada798b2012-02-13 17:09:30 -0800983 cnx->egl.eglGetProcAddress(procname);
luliuhui69d10072012-08-30 11:15:36 +0800984 if (addr) found = true;
Mathias Agopian518ec112011-05-13 16:21:08 -0700985 }
Mathias Agopianada798b2012-02-13 17:09:30 -0800986
Mathias Agopian518ec112011-05-13 16:21:08 -0700987 if (found) {
988 addr = gExtensionForwarders[slot];
Mathias Agopian518ec112011-05-13 16:21:08 -0700989 sGLExtentionMap.add(name, addr);
990 sGLExtentionSlot++;
991 }
992 }
993
994 pthread_mutex_unlock(&sExtensionMapMutex);
995 return addr;
996}
997
Jamie Gennis28ef8d72012-04-05 20:34:54 -0700998class FrameCompletionThread : public Thread {
999public:
1000
1001 static void queueSync(EGLSyncKHR sync) {
1002 static sp<FrameCompletionThread> thread(new FrameCompletionThread);
1003 static bool running = false;
1004 if (!running) {
1005 thread->run("GPUFrameCompletion");
1006 running = true;
1007 }
1008 {
1009 Mutex::Autolock lock(thread->mMutex);
1010 ScopedTrace st(ATRACE_TAG, String8::format("kicked off frame %d",
1011 thread->mFramesQueued).string());
1012 thread->mQueue.push_back(sync);
1013 thread->mCondition.signal();
1014 thread->mFramesQueued++;
1015 ATRACE_INT("GPU Frames Outstanding", thread->mQueue.size());
1016 }
1017 }
1018
1019private:
1020 FrameCompletionThread() : mFramesQueued(0), mFramesCompleted(0) {}
1021
1022 virtual bool threadLoop() {
1023 EGLSyncKHR sync;
1024 uint32_t frameNum;
1025 {
1026 Mutex::Autolock lock(mMutex);
1027 while (mQueue.isEmpty()) {
1028 mCondition.wait(mMutex);
1029 }
1030 sync = mQueue[0];
1031 frameNum = mFramesCompleted;
1032 }
1033 EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
1034 {
1035 ScopedTrace st(ATRACE_TAG, String8::format("waiting for frame %d",
1036 frameNum).string());
1037 EGLint result = eglClientWaitSyncKHR(dpy, sync, 0, EGL_FOREVER_KHR);
1038 if (result == EGL_FALSE) {
1039 ALOGE("FrameCompletion: error waiting for fence: %#x", eglGetError());
1040 } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
1041 ALOGE("FrameCompletion: timeout waiting for fence");
1042 }
1043 eglDestroySyncKHR(dpy, sync);
1044 }
1045 {
1046 Mutex::Autolock lock(mMutex);
1047 mQueue.removeAt(0);
1048 mFramesCompleted++;
1049 ATRACE_INT("GPU Frames Outstanding", mQueue.size());
1050 }
1051 return true;
1052 }
1053
1054 uint32_t mFramesQueued;
1055 uint32_t mFramesCompleted;
1056 Vector<EGLSyncKHR> mQueue;
1057 Condition mCondition;
1058 Mutex mMutex;
1059};
1060
Dan Stozaa894d082015-02-19 15:27:36 -08001061EGLBoolean eglSwapBuffersWithDamageKHR(EGLDisplay dpy, EGLSurface draw,
1062 EGLint *rects, EGLint n_rects)
Mathias Agopian518ec112011-05-13 16:21:08 -07001063{
Jamie Gennis1c8e95c2012-02-23 19:27:23 -08001064 ATRACE_CALL();
Mathias Agopian518ec112011-05-13 16:21:08 -07001065 clearError();
1066
Jesse Hallb29e5e82012-04-04 16:53:42 -07001067 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001068 if (!dp) return EGL_FALSE;
1069
Jesse Hallb29e5e82012-04-04 16:53:42 -07001070 SurfaceRef _s(dp.get(), draw);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001071 if (!_s.get())
1072 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001073
Mathias Agopian518ec112011-05-13 16:21:08 -07001074 egl_surface_t const * const s = get_surface(draw);
Mathias Agopian7db993a2012-03-25 00:49:46 -07001075
Mathias Agopianed6d08b2013-04-16 16:39:46 -07001076 if (CC_UNLIKELY(dp->traceGpuCompletion)) {
1077 EGLSyncKHR sync = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, NULL);
1078 if (sync != EGL_NO_SYNC_KHR) {
1079 FrameCompletionThread::queueSync(sync);
1080 }
1081 }
1082
Mathias Agopian7db993a2012-03-25 00:49:46 -07001083 if (CC_UNLIKELY(dp->finishOnSwap)) {
1084 uint32_t pixel;
1085 egl_context_t * const c = get_context( egl_tls_t::getContext() );
1086 if (c) {
1087 // glReadPixels() ensures that the frame is complete
1088 s->cnx->hooks[c->version]->gl.glReadPixels(0,0,1,1,
1089 GL_RGBA,GL_UNSIGNED_BYTE,&pixel);
1090 }
1091 }
1092
Dan Stozaa894d082015-02-19 15:27:36 -08001093 if (n_rects == 0) {
1094 return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface);
1095 }
1096
1097 Vector<android_native_rect_t> androidRects;
1098 for (int r = 0; r < n_rects; ++r) {
1099 int offset = r * 4;
1100 int x = rects[offset];
1101 int y = rects[offset + 1];
1102 int width = rects[offset + 2];
1103 int height = rects[offset + 3];
1104 android_native_rect_t androidRect;
1105 androidRect.left = x;
1106 androidRect.top = y + height;
1107 androidRect.right = x + width;
1108 androidRect.bottom = y;
1109 androidRects.push_back(androidRect);
1110 }
1111 native_window_set_surface_damage(s->win.get(), androidRects.array(),
1112 androidRects.size());
1113
1114 if (s->cnx->egl.eglSwapBuffersWithDamageKHR) {
1115 return s->cnx->egl.eglSwapBuffersWithDamageKHR(dp->disp.dpy, s->surface,
1116 rects, n_rects);
1117 } else {
1118 return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface);
1119 }
1120}
1121
1122EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
1123{
1124 return eglSwapBuffersWithDamageKHR(dpy, surface, NULL, 0);
Mathias Agopian518ec112011-05-13 16:21:08 -07001125}
1126
1127EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface,
1128 NativePixmapType target)
1129{
1130 clearError();
1131
Jesse Hallb29e5e82012-04-04 16:53:42 -07001132 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001133 if (!dp) return EGL_FALSE;
1134
Jesse Hallb29e5e82012-04-04 16:53:42 -07001135 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001136 if (!_s.get())
1137 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001138
Mathias Agopian518ec112011-05-13 16:21:08 -07001139 egl_surface_t const * const s = get_surface(surface);
Mathias Agopianada798b2012-02-13 17:09:30 -08001140 return s->cnx->egl.eglCopyBuffers(dp->disp.dpy, s->surface, target);
Mathias Agopian518ec112011-05-13 16:21:08 -07001141}
1142
1143const char* eglQueryString(EGLDisplay dpy, EGLint name)
1144{
1145 clearError();
1146
Jesse Hallb29e5e82012-04-04 16:53:42 -07001147 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001148 if (!dp) return (const char *) NULL;
1149
1150 switch (name) {
1151 case EGL_VENDOR:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001152 return dp->getVendorString();
Mathias Agopian518ec112011-05-13 16:21:08 -07001153 case EGL_VERSION:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001154 return dp->getVersionString();
Mathias Agopian518ec112011-05-13 16:21:08 -07001155 case EGL_EXTENSIONS:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001156 return dp->getExtensionString();
Mathias Agopian518ec112011-05-13 16:21:08 -07001157 case EGL_CLIENT_APIS:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001158 return dp->getClientApiString();
Mathias Agopian518ec112011-05-13 16:21:08 -07001159 }
1160 return setError(EGL_BAD_PARAMETER, (const char *)0);
1161}
1162
Mathias Agopianca088332013-03-28 17:44:13 -07001163EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name)
1164{
1165 clearError();
1166
1167 const egl_display_ptr dp = validate_display(dpy);
1168 if (!dp) return (const char *) NULL;
1169
1170 switch (name) {
1171 case EGL_VENDOR:
1172 return dp->disp.queryString.vendor;
1173 case EGL_VERSION:
1174 return dp->disp.queryString.version;
1175 case EGL_EXTENSIONS:
1176 return dp->disp.queryString.extensions;
1177 case EGL_CLIENT_APIS:
1178 return dp->disp.queryString.clientApi;
1179 }
1180 return setError(EGL_BAD_PARAMETER, (const char *)0);
1181}
Mathias Agopian518ec112011-05-13 16:21:08 -07001182
1183// ----------------------------------------------------------------------------
1184// EGL 1.1
1185// ----------------------------------------------------------------------------
1186
1187EGLBoolean eglSurfaceAttrib(
1188 EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
1189{
1190 clearError();
1191
Jesse Hallb29e5e82012-04-04 16:53:42 -07001192 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001193 if (!dp) return EGL_FALSE;
1194
Jesse Hallb29e5e82012-04-04 16:53:42 -07001195 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001196 if (!_s.get())
1197 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001198
Mathias Agopian518ec112011-05-13 16:21:08 -07001199 egl_surface_t const * const s = get_surface(surface);
Pablo Ceballosccdfd602015-10-07 15:05:45 -07001200
Pablo Ceballos02b05da2016-02-02 17:53:18 -08001201 if (attribute == EGL_FRONT_BUFFER_AUTO_REFRESH_ANDROID) {
Pablo Ceballosf051ade2016-03-15 18:27:20 -07001202 int err = native_window_set_auto_refresh(s->win.get(),
1203 value ? true : false);
1204 return (err == NO_ERROR) ? EGL_TRUE :
1205 setError(EGL_BAD_SURFACE, EGL_FALSE);
Pablo Ceballosccdfd602015-10-07 15:05:45 -07001206 }
1207
Mathias Agopian518ec112011-05-13 16:21:08 -07001208 if (s->cnx->egl.eglSurfaceAttrib) {
1209 return s->cnx->egl.eglSurfaceAttrib(
Mathias Agopianada798b2012-02-13 17:09:30 -08001210 dp->disp.dpy, s->surface, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -07001211 }
1212 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1213}
1214
1215EGLBoolean eglBindTexImage(
1216 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1217{
1218 clearError();
1219
Jesse Hallb29e5e82012-04-04 16:53:42 -07001220 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001221 if (!dp) return EGL_FALSE;
1222
Jesse Hallb29e5e82012-04-04 16:53:42 -07001223 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001224 if (!_s.get())
1225 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001226
Mathias Agopian518ec112011-05-13 16:21:08 -07001227 egl_surface_t const * const s = get_surface(surface);
1228 if (s->cnx->egl.eglBindTexImage) {
1229 return s->cnx->egl.eglBindTexImage(
Mathias Agopianada798b2012-02-13 17:09:30 -08001230 dp->disp.dpy, s->surface, buffer);
Mathias Agopian518ec112011-05-13 16:21:08 -07001231 }
1232 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1233}
1234
1235EGLBoolean eglReleaseTexImage(
1236 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1237{
1238 clearError();
1239
Jesse Hallb29e5e82012-04-04 16:53:42 -07001240 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001241 if (!dp) return EGL_FALSE;
1242
Jesse Hallb29e5e82012-04-04 16:53:42 -07001243 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001244 if (!_s.get())
1245 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001246
Mathias Agopian518ec112011-05-13 16:21:08 -07001247 egl_surface_t const * const s = get_surface(surface);
1248 if (s->cnx->egl.eglReleaseTexImage) {
1249 return s->cnx->egl.eglReleaseTexImage(
Mathias Agopianada798b2012-02-13 17:09:30 -08001250 dp->disp.dpy, s->surface, buffer);
Mathias Agopian518ec112011-05-13 16:21:08 -07001251 }
1252 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1253}
1254
1255EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
1256{
1257 clearError();
1258
Jesse Hallb29e5e82012-04-04 16:53:42 -07001259 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001260 if (!dp) return EGL_FALSE;
1261
1262 EGLBoolean res = EGL_TRUE;
Mathias Agopianada798b2012-02-13 17:09:30 -08001263 egl_connection_t* const cnx = &gEGLImpl;
1264 if (cnx->dso && cnx->egl.eglSwapInterval) {
1265 res = cnx->egl.eglSwapInterval(dp->disp.dpy, interval);
Mathias Agopian518ec112011-05-13 16:21:08 -07001266 }
Mathias Agopianada798b2012-02-13 17:09:30 -08001267
Mathias Agopian518ec112011-05-13 16:21:08 -07001268 return res;
1269}
1270
1271
1272// ----------------------------------------------------------------------------
1273// EGL 1.2
1274// ----------------------------------------------------------------------------
1275
1276EGLBoolean eglWaitClient(void)
1277{
1278 clearError();
1279
Mathias Agopianada798b2012-02-13 17:09:30 -08001280 egl_connection_t* const cnx = &gEGLImpl;
1281 if (!cnx->dso)
1282 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1283
1284 EGLBoolean res;
1285 if (cnx->egl.eglWaitClient) {
1286 res = cnx->egl.eglWaitClient();
1287 } else {
1288 res = cnx->egl.eglWaitGL();
Mathias Agopian518ec112011-05-13 16:21:08 -07001289 }
1290 return res;
1291}
1292
1293EGLBoolean eglBindAPI(EGLenum api)
1294{
1295 clearError();
1296
1297 if (egl_init_drivers() == EGL_FALSE) {
1298 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1299 }
1300
1301 // bind this API on all EGLs
1302 EGLBoolean res = EGL_TRUE;
Mathias Agopianada798b2012-02-13 17:09:30 -08001303 egl_connection_t* const cnx = &gEGLImpl;
1304 if (cnx->dso && cnx->egl.eglBindAPI) {
1305 res = cnx->egl.eglBindAPI(api);
Mathias Agopian518ec112011-05-13 16:21:08 -07001306 }
1307 return res;
1308}
1309
1310EGLenum eglQueryAPI(void)
1311{
1312 clearError();
1313
1314 if (egl_init_drivers() == EGL_FALSE) {
1315 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1316 }
1317
Mathias Agopianada798b2012-02-13 17:09:30 -08001318 egl_connection_t* const cnx = &gEGLImpl;
1319 if (cnx->dso && cnx->egl.eglQueryAPI) {
1320 return cnx->egl.eglQueryAPI();
Mathias Agopian518ec112011-05-13 16:21:08 -07001321 }
Mathias Agopianada798b2012-02-13 17:09:30 -08001322
Mathias Agopian518ec112011-05-13 16:21:08 -07001323 // or, it can only be OpenGL ES
1324 return EGL_OPENGL_ES_API;
1325}
1326
1327EGLBoolean eglReleaseThread(void)
1328{
1329 clearError();
1330
1331 // If there is context bound to the thread, release it
Mathias Agopianfb87e542012-01-30 18:20:52 -08001332 egl_display_t::loseCurrent(get_context(getContext()));
Mathias Agopian518ec112011-05-13 16:21:08 -07001333
Mathias Agopianada798b2012-02-13 17:09:30 -08001334 egl_connection_t* const cnx = &gEGLImpl;
1335 if (cnx->dso && cnx->egl.eglReleaseThread) {
1336 cnx->egl.eglReleaseThread();
Mathias Agopian518ec112011-05-13 16:21:08 -07001337 }
1338 egl_tls_t::clearTLS();
Mathias Agopian518ec112011-05-13 16:21:08 -07001339 return EGL_TRUE;
1340}
1341
1342EGLSurface eglCreatePbufferFromClientBuffer(
1343 EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer,
1344 EGLConfig config, const EGLint *attrib_list)
1345{
1346 clearError();
1347
Jesse Hallb29e5e82012-04-04 16:53:42 -07001348 egl_connection_t* cnx = NULL;
1349 const egl_display_ptr dp = validate_display_connection(dpy, cnx);
1350 if (!dp) return EGL_FALSE;
Mathias Agopian518ec112011-05-13 16:21:08 -07001351 if (cnx->egl.eglCreatePbufferFromClientBuffer) {
1352 return cnx->egl.eglCreatePbufferFromClientBuffer(
Mathias Agopian7773c432012-02-13 20:06:08 -08001353 dp->disp.dpy, buftype, buffer, config, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001354 }
1355 return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE);
1356}
1357
1358// ----------------------------------------------------------------------------
1359// EGL_EGLEXT_VERSION 3
1360// ----------------------------------------------------------------------------
1361
1362EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface,
1363 const EGLint *attrib_list)
1364{
1365 clearError();
1366
Jesse Hallb29e5e82012-04-04 16:53:42 -07001367 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001368 if (!dp) return EGL_FALSE;
1369
Jesse Hallb29e5e82012-04-04 16:53:42 -07001370 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001371 if (!_s.get())
1372 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001373
1374 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian518ec112011-05-13 16:21:08 -07001375 if (s->cnx->egl.eglLockSurfaceKHR) {
1376 return s->cnx->egl.eglLockSurfaceKHR(
Mathias Agopianada798b2012-02-13 17:09:30 -08001377 dp->disp.dpy, s->surface, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001378 }
1379 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1380}
1381
1382EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface)
1383{
1384 clearError();
1385
Jesse Hallb29e5e82012-04-04 16:53:42 -07001386 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001387 if (!dp) return EGL_FALSE;
1388
Jesse Hallb29e5e82012-04-04 16:53:42 -07001389 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001390 if (!_s.get())
1391 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001392
1393 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian518ec112011-05-13 16:21:08 -07001394 if (s->cnx->egl.eglUnlockSurfaceKHR) {
Mathias Agopianada798b2012-02-13 17:09:30 -08001395 return s->cnx->egl.eglUnlockSurfaceKHR(dp->disp.dpy, s->surface);
Mathias Agopian518ec112011-05-13 16:21:08 -07001396 }
1397 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1398}
1399
1400EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
1401 EGLClientBuffer buffer, const EGLint *attrib_list)
1402{
1403 clearError();
1404
Jesse Hallb29e5e82012-04-04 16:53:42 -07001405 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001406 if (!dp) return EGL_NO_IMAGE_KHR;
1407
Jesse Hallb29e5e82012-04-04 16:53:42 -07001408 ContextRef _c(dp.get(), ctx);
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001409 egl_context_t * const c = _c.get();
Mathias Agopian518ec112011-05-13 16:21:08 -07001410
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001411 EGLImageKHR result = EGL_NO_IMAGE_KHR;
1412 egl_connection_t* const cnx = &gEGLImpl;
1413 if (cnx->dso && cnx->egl.eglCreateImageKHR) {
1414 result = cnx->egl.eglCreateImageKHR(
1415 dp->disp.dpy,
1416 c ? c->context : EGL_NO_CONTEXT,
1417 target, buffer, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001418 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001419 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001420}
1421
1422EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
1423{
1424 clearError();
1425
Jesse Hallb29e5e82012-04-04 16:53:42 -07001426 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001427 if (!dp) return EGL_FALSE;
1428
Steven Holte646a5c52012-06-04 20:02:11 -07001429 EGLBoolean result = EGL_FALSE;
Mathias Agopianada798b2012-02-13 17:09:30 -08001430 egl_connection_t* const cnx = &gEGLImpl;
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001431 if (cnx->dso && cnx->egl.eglDestroyImageKHR) {
Steven Holte646a5c52012-06-04 20:02:11 -07001432 result = cnx->egl.eglDestroyImageKHR(dp->disp.dpy, img);
Mathias Agopian518ec112011-05-13 16:21:08 -07001433 }
Steven Holte646a5c52012-06-04 20:02:11 -07001434 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001435}
1436
1437// ----------------------------------------------------------------------------
1438// EGL_EGLEXT_VERSION 5
1439// ----------------------------------------------------------------------------
1440
1441
1442EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
1443{
1444 clearError();
1445
Jesse Hallb29e5e82012-04-04 16:53:42 -07001446 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001447 if (!dp) return EGL_NO_SYNC_KHR;
1448
Mathias Agopian518ec112011-05-13 16:21:08 -07001449 EGLSyncKHR result = EGL_NO_SYNC_KHR;
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001450 egl_connection_t* const cnx = &gEGLImpl;
1451 if (cnx->dso && cnx->egl.eglCreateSyncKHR) {
1452 result = cnx->egl.eglCreateSyncKHR(dp->disp.dpy, type, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001453 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001454 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001455}
1456
1457EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
1458{
1459 clearError();
1460
Jesse Hallb29e5e82012-04-04 16:53:42 -07001461 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001462 if (!dp) return EGL_FALSE;
1463
Mathias Agopian518ec112011-05-13 16:21:08 -07001464 EGLBoolean result = EGL_FALSE;
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001465 egl_connection_t* const cnx = &gEGLImpl;
1466 if (cnx->dso && cnx->egl.eglDestroySyncKHR) {
1467 result = cnx->egl.eglDestroySyncKHR(dp->disp.dpy, sync);
Mathias Agopian518ec112011-05-13 16:21:08 -07001468 }
1469 return result;
1470}
1471
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -07001472EGLBoolean eglSignalSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode) {
1473 clearError();
1474
1475 const egl_display_ptr dp = validate_display(dpy);
1476 if (!dp) return EGL_FALSE;
1477
1478 EGLBoolean result = EGL_FALSE;
1479 egl_connection_t* const cnx = &gEGLImpl;
1480 if (cnx->dso && cnx->egl.eglSignalSyncKHR) {
1481 result = cnx->egl.eglSignalSyncKHR(
1482 dp->disp.dpy, sync, mode);
1483 }
1484 return result;
1485}
1486
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001487EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync,
1488 EGLint flags, EGLTimeKHR timeout)
Mathias Agopian518ec112011-05-13 16:21:08 -07001489{
1490 clearError();
1491
Jesse Hallb29e5e82012-04-04 16:53:42 -07001492 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001493 if (!dp) return EGL_FALSE;
1494
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001495 EGLBoolean result = EGL_FALSE;
1496 egl_connection_t* const cnx = &gEGLImpl;
1497 if (cnx->dso && cnx->egl.eglClientWaitSyncKHR) {
1498 result = cnx->egl.eglClientWaitSyncKHR(
1499 dp->disp.dpy, sync, flags, timeout);
Mathias Agopian518ec112011-05-13 16:21:08 -07001500 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001501 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001502}
1503
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001504EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync,
1505 EGLint attribute, EGLint *value)
Mathias Agopian518ec112011-05-13 16:21:08 -07001506{
1507 clearError();
1508
Jesse Hallb29e5e82012-04-04 16:53:42 -07001509 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001510 if (!dp) return EGL_FALSE;
1511
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001512 EGLBoolean result = EGL_FALSE;
1513 egl_connection_t* const cnx = &gEGLImpl;
1514 if (cnx->dso && cnx->egl.eglGetSyncAttribKHR) {
1515 result = cnx->egl.eglGetSyncAttribKHR(
1516 dp->disp.dpy, sync, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -07001517 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001518 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001519}
1520
Season Li000d88f2015-07-01 11:39:40 -07001521EGLStreamKHR eglCreateStreamKHR(EGLDisplay dpy, const EGLint *attrib_list)
1522{
1523 clearError();
1524
1525 const egl_display_ptr dp = validate_display(dpy);
1526 if (!dp) return EGL_NO_STREAM_KHR;
1527
1528 EGLStreamKHR result = EGL_NO_STREAM_KHR;
1529 egl_connection_t* const cnx = &gEGLImpl;
1530 if (cnx->dso && cnx->egl.eglCreateStreamKHR) {
1531 result = cnx->egl.eglCreateStreamKHR(
1532 dp->disp.dpy, attrib_list);
1533 }
1534 return result;
1535}
1536
1537EGLBoolean eglDestroyStreamKHR(EGLDisplay dpy, EGLStreamKHR stream)
1538{
1539 clearError();
1540
1541 const egl_display_ptr dp = validate_display(dpy);
1542 if (!dp) return EGL_FALSE;
1543
1544 EGLBoolean result = EGL_FALSE;
1545 egl_connection_t* const cnx = &gEGLImpl;
1546 if (cnx->dso && cnx->egl.eglDestroyStreamKHR) {
1547 result = cnx->egl.eglDestroyStreamKHR(
1548 dp->disp.dpy, stream);
1549 }
1550 return result;
1551}
1552
1553EGLBoolean eglStreamAttribKHR(EGLDisplay dpy, EGLStreamKHR stream,
1554 EGLenum attribute, EGLint value)
1555{
1556 clearError();
1557
1558 const egl_display_ptr dp = validate_display(dpy);
1559 if (!dp) return EGL_FALSE;
1560
1561 EGLBoolean result = EGL_FALSE;
1562 egl_connection_t* const cnx = &gEGLImpl;
1563 if (cnx->dso && cnx->egl.eglStreamAttribKHR) {
1564 result = cnx->egl.eglStreamAttribKHR(
1565 dp->disp.dpy, stream, attribute, value);
1566 }
1567 return result;
1568}
1569
1570EGLBoolean eglQueryStreamKHR(EGLDisplay dpy, EGLStreamKHR stream,
1571 EGLenum attribute, EGLint *value)
1572{
1573 clearError();
1574
1575 const egl_display_ptr dp = validate_display(dpy);
1576 if (!dp) return EGL_FALSE;
1577
1578 EGLBoolean result = EGL_FALSE;
1579 egl_connection_t* const cnx = &gEGLImpl;
1580 if (cnx->dso && cnx->egl.eglQueryStreamKHR) {
1581 result = cnx->egl.eglQueryStreamKHR(
1582 dp->disp.dpy, stream, attribute, value);
1583 }
1584 return result;
1585}
1586
1587EGLBoolean eglQueryStreamu64KHR(EGLDisplay dpy, EGLStreamKHR stream,
1588 EGLenum attribute, EGLuint64KHR *value)
1589{
1590 clearError();
1591
1592 const egl_display_ptr dp = validate_display(dpy);
1593 if (!dp) return EGL_FALSE;
1594
1595 EGLBoolean result = EGL_FALSE;
1596 egl_connection_t* const cnx = &gEGLImpl;
1597 if (cnx->dso && cnx->egl.eglQueryStreamu64KHR) {
1598 result = cnx->egl.eglQueryStreamu64KHR(
1599 dp->disp.dpy, stream, attribute, value);
1600 }
1601 return result;
1602}
1603
1604EGLBoolean eglQueryStreamTimeKHR(EGLDisplay dpy, EGLStreamKHR stream,
1605 EGLenum attribute, EGLTimeKHR *value)
1606{
1607 clearError();
1608
1609 const egl_display_ptr dp = validate_display(dpy);
1610 if (!dp) return EGL_FALSE;
1611
1612 EGLBoolean result = EGL_FALSE;
1613 egl_connection_t* const cnx = &gEGLImpl;
1614 if (cnx->dso && cnx->egl.eglQueryStreamTimeKHR) {
1615 result = cnx->egl.eglQueryStreamTimeKHR(
1616 dp->disp.dpy, stream, attribute, value);
1617 }
1618 return result;
1619}
1620
1621EGLSurface eglCreateStreamProducerSurfaceKHR(EGLDisplay dpy, EGLConfig config,
1622 EGLStreamKHR stream, const EGLint *attrib_list)
1623{
1624 clearError();
1625
1626 egl_display_ptr dp = validate_display(dpy);
1627 if (!dp) return EGL_NO_SURFACE;
1628
1629 egl_connection_t* const cnx = &gEGLImpl;
1630 if (cnx->dso && cnx->egl.eglCreateStreamProducerSurfaceKHR) {
1631 EGLSurface surface = cnx->egl.eglCreateStreamProducerSurfaceKHR(
1632 dp->disp.dpy, config, stream, attrib_list);
1633 if (surface != EGL_NO_SURFACE) {
1634 egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL,
1635 surface, cnx);
1636 return s;
1637 }
1638 }
1639 return EGL_NO_SURFACE;
1640}
1641
1642EGLBoolean eglStreamConsumerGLTextureExternalKHR(EGLDisplay dpy,
1643 EGLStreamKHR stream)
1644{
1645 clearError();
1646
1647 const egl_display_ptr dp = validate_display(dpy);
1648 if (!dp) return EGL_FALSE;
1649
1650 EGLBoolean result = EGL_FALSE;
1651 egl_connection_t* const cnx = &gEGLImpl;
1652 if (cnx->dso && cnx->egl.eglStreamConsumerGLTextureExternalKHR) {
1653 result = cnx->egl.eglStreamConsumerGLTextureExternalKHR(
1654 dp->disp.dpy, stream);
1655 }
1656 return result;
1657}
1658
1659EGLBoolean eglStreamConsumerAcquireKHR(EGLDisplay dpy,
1660 EGLStreamKHR stream)
1661{
1662 clearError();
1663
1664 const egl_display_ptr dp = validate_display(dpy);
1665 if (!dp) return EGL_FALSE;
1666
1667 EGLBoolean result = EGL_FALSE;
1668 egl_connection_t* const cnx = &gEGLImpl;
1669 if (cnx->dso && cnx->egl.eglStreamConsumerAcquireKHR) {
1670 result = cnx->egl.eglStreamConsumerAcquireKHR(
1671 dp->disp.dpy, stream);
1672 }
1673 return result;
1674}
1675
1676EGLBoolean eglStreamConsumerReleaseKHR(EGLDisplay dpy,
1677 EGLStreamKHR stream)
1678{
1679 clearError();
1680
1681 const egl_display_ptr dp = validate_display(dpy);
1682 if (!dp) return EGL_FALSE;
1683
1684 EGLBoolean result = EGL_FALSE;
1685 egl_connection_t* const cnx = &gEGLImpl;
1686 if (cnx->dso && cnx->egl.eglStreamConsumerReleaseKHR) {
1687 result = cnx->egl.eglStreamConsumerReleaseKHR(
1688 dp->disp.dpy, stream);
1689 }
1690 return result;
1691}
1692
1693EGLNativeFileDescriptorKHR eglGetStreamFileDescriptorKHR(
1694 EGLDisplay dpy, EGLStreamKHR stream)
1695{
1696 clearError();
1697
1698 const egl_display_ptr dp = validate_display(dpy);
1699 if (!dp) return EGL_NO_FILE_DESCRIPTOR_KHR;
1700
1701 EGLNativeFileDescriptorKHR result = EGL_NO_FILE_DESCRIPTOR_KHR;
1702 egl_connection_t* const cnx = &gEGLImpl;
1703 if (cnx->dso && cnx->egl.eglGetStreamFileDescriptorKHR) {
1704 result = cnx->egl.eglGetStreamFileDescriptorKHR(
1705 dp->disp.dpy, stream);
1706 }
1707 return result;
1708}
1709
1710EGLStreamKHR eglCreateStreamFromFileDescriptorKHR(
1711 EGLDisplay dpy, EGLNativeFileDescriptorKHR file_descriptor)
1712{
1713 clearError();
1714
1715 const egl_display_ptr dp = validate_display(dpy);
1716 if (!dp) return EGL_NO_STREAM_KHR;
1717
1718 EGLStreamKHR result = EGL_NO_STREAM_KHR;
1719 egl_connection_t* const cnx = &gEGLImpl;
1720 if (cnx->dso && cnx->egl.eglCreateStreamFromFileDescriptorKHR) {
1721 result = cnx->egl.eglCreateStreamFromFileDescriptorKHR(
1722 dp->disp.dpy, file_descriptor);
1723 }
1724 return result;
1725}
1726
Mathias Agopian518ec112011-05-13 16:21:08 -07001727// ----------------------------------------------------------------------------
Mathias Agopian2bb71682013-03-27 17:32:41 -07001728// EGL_EGLEXT_VERSION 15
1729// ----------------------------------------------------------------------------
1730
1731EGLint eglWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags) {
1732 clearError();
1733 const egl_display_ptr dp = validate_display(dpy);
1734 if (!dp) return EGL_FALSE;
1735 EGLint result = EGL_FALSE;
1736 egl_connection_t* const cnx = &gEGLImpl;
1737 if (cnx->dso && cnx->egl.eglWaitSyncKHR) {
1738 result = cnx->egl.eglWaitSyncKHR(dp->disp.dpy, sync, flags);
1739 }
1740 return result;
1741}
1742
1743// ----------------------------------------------------------------------------
Mathias Agopian518ec112011-05-13 16:21:08 -07001744// ANDROID extensions
1745// ----------------------------------------------------------------------------
1746
Jamie Gennis331841b2012-09-06 14:52:00 -07001747EGLint eglDupNativeFenceFDANDROID(EGLDisplay dpy, EGLSyncKHR sync)
1748{
1749 clearError();
1750
1751 const egl_display_ptr dp = validate_display(dpy);
1752 if (!dp) return EGL_NO_NATIVE_FENCE_FD_ANDROID;
1753
1754 EGLint result = EGL_NO_NATIVE_FENCE_FD_ANDROID;
1755 egl_connection_t* const cnx = &gEGLImpl;
1756 if (cnx->dso && cnx->egl.eglDupNativeFenceFDANDROID) {
1757 result = cnx->egl.eglDupNativeFenceFDANDROID(dp->disp.dpy, sync);
1758 }
1759 return result;
1760}
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001761
Andy McFadden72841452013-03-01 16:25:32 -08001762EGLBoolean eglPresentationTimeANDROID(EGLDisplay dpy, EGLSurface surface,
1763 EGLnsecsANDROID time)
1764{
1765 clearError();
1766
1767 const egl_display_ptr dp = validate_display(dpy);
1768 if (!dp) {
1769 return EGL_FALSE;
1770 }
1771
1772 SurfaceRef _s(dp.get(), surface);
1773 if (!_s.get()) {
1774 setError(EGL_BAD_SURFACE, EGL_FALSE);
1775 return EGL_FALSE;
1776 }
1777
1778 egl_surface_t const * const s = get_surface(surface);
1779 native_window_set_buffers_timestamp(s->win.get(), time);
1780
1781 return EGL_TRUE;
1782}
1783
Craig Donner05249fc2016-01-15 19:33:55 -08001784EGLClientBuffer eglCreateNativeClientBufferANDROID(const EGLint *attrib_list)
1785{
1786 clearError();
1787
1788 int usage = 0;
1789 uint32_t width = 0;
1790 uint32_t height = 0;
1791 uint32_t format = 0;
1792 uint32_t red_size = 0;
1793 uint32_t green_size = 0;
1794 uint32_t blue_size = 0;
1795 uint32_t alpha_size = 0;
1796
Craig Donnerb40504a2016-06-03 17:54:25 -07001797#define GET_NONNEGATIVE_VALUE(case_name, target) \
Craig Donner05249fc2016-01-15 19:33:55 -08001798 case case_name: \
Craig Donnerb40504a2016-06-03 17:54:25 -07001799 if (value >= 0) { \
Craig Donner05249fc2016-01-15 19:33:55 -08001800 target = value; \
1801 } else { \
1802 return setError(EGL_BAD_PARAMETER, (EGLClientBuffer)0); \
1803 } \
1804 break
1805
1806 if (attrib_list) {
1807 while (*attrib_list != EGL_NONE) {
1808 GLint attr = *attrib_list++;
1809 GLint value = *attrib_list++;
1810 switch (attr) {
Craig Donnerb40504a2016-06-03 17:54:25 -07001811 GET_NONNEGATIVE_VALUE(EGL_WIDTH, width);
1812 GET_NONNEGATIVE_VALUE(EGL_HEIGHT, height);
1813 GET_NONNEGATIVE_VALUE(EGL_RED_SIZE, red_size);
1814 GET_NONNEGATIVE_VALUE(EGL_GREEN_SIZE, green_size);
1815 GET_NONNEGATIVE_VALUE(EGL_BLUE_SIZE, blue_size);
1816 GET_NONNEGATIVE_VALUE(EGL_ALPHA_SIZE, alpha_size);
Craig Donner05249fc2016-01-15 19:33:55 -08001817 case EGL_NATIVE_BUFFER_USAGE_ANDROID:
1818 if (value & EGL_NATIVE_BUFFER_USAGE_PROTECTED_BIT_ANDROID) {
1819 usage |= GRALLOC_USAGE_PROTECTED;
Craig Donner05249fc2016-01-15 19:33:55 -08001820 }
Craig Donner8cfae6d2016-04-12 16:54:03 -07001821 if (value & EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_BIT_ANDROID) {
Craig Donner05249fc2016-01-15 19:33:55 -08001822 usage |= GRALLOC_USAGE_HW_RENDER;
1823 }
Craig Donner8cfae6d2016-04-12 16:54:03 -07001824 if (value & EGL_NATIVE_BUFFER_USAGE_TEXTURE_BIT_ANDROID) {
Craig Donner05249fc2016-01-15 19:33:55 -08001825 usage |= GRALLOC_USAGE_HW_TEXTURE;
1826 }
1827 // The buffer must be used for either a texture or a
1828 // renderbuffer.
Craig Donner8cfae6d2016-04-12 16:54:03 -07001829 if ((value & EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_BIT_ANDROID) &&
1830 (value & EGL_NATIVE_BUFFER_USAGE_TEXTURE_BIT_ANDROID)) {
Craig Donner05249fc2016-01-15 19:33:55 -08001831 return setError(EGL_BAD_PARAMETER, (EGLClientBuffer)0);
1832 }
1833 break;
1834 default:
1835 return setError(EGL_BAD_PARAMETER, (EGLClientBuffer)0);
1836 }
1837 }
1838 }
Craig Donnerb40504a2016-06-03 17:54:25 -07001839#undef GET_NONNEGATIVE_VALUE
Craig Donner05249fc2016-01-15 19:33:55 -08001840
1841 // Validate format.
1842 if (red_size == 8 && green_size == 8 && blue_size == 8) {
1843 if (alpha_size == 8) {
1844 format = HAL_PIXEL_FORMAT_RGBA_8888;
1845 } else {
1846 format = HAL_PIXEL_FORMAT_RGB_888;
1847 }
1848 } else if (red_size == 5 && green_size == 6 && blue_size == 5 &&
1849 alpha_size == 0) {
1850 format == HAL_PIXEL_FORMAT_RGB_565;
1851 } else {
1852 ALOGE("Invalid native pixel format { r=%d, g=%d, b=%d, a=%d }",
1853 red_size, green_size, blue_size, alpha_size);
1854 return setError(EGL_BAD_PARAMETER, (EGLClientBuffer)0);
1855 }
1856
1857 GraphicBuffer* gBuffer = new GraphicBuffer(width, height, format, usage);
1858 const status_t err = gBuffer->initCheck();
1859 if (err != NO_ERROR) {
1860 ALOGE("Unable to create native buffer { w=%d, h=%d, f=%d, u=%#x }: %#x",
1861 width, height, format, usage, err);
1862 // Destroy the buffer.
1863 sp<GraphicBuffer> holder(gBuffer);
1864 return setError(EGL_BAD_ALLOC, (EGLClientBuffer)0);
1865 }
1866 ALOGD("Created new native buffer %p { w=%d, h=%d, f=%d, u=%#x }",
1867 gBuffer, width, height, format, usage);
1868 return static_cast<EGLClientBuffer>(gBuffer->getNativeBuffer());
1869}
1870
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001871// ----------------------------------------------------------------------------
1872// NVIDIA extensions
1873// ----------------------------------------------------------------------------
1874EGLuint64NV eglGetSystemTimeFrequencyNV()
1875{
1876 clearError();
1877
1878 if (egl_init_drivers() == EGL_FALSE) {
1879 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1880 }
1881
1882 EGLuint64NV ret = 0;
Mathias Agopianada798b2012-02-13 17:09:30 -08001883 egl_connection_t* const cnx = &gEGLImpl;
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001884
Mathias Agopianada798b2012-02-13 17:09:30 -08001885 if (cnx->dso && cnx->egl.eglGetSystemTimeFrequencyNV) {
1886 return cnx->egl.eglGetSystemTimeFrequencyNV();
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001887 }
1888
Mathias Agopian0e8bbee2011-10-05 19:15:05 -07001889 return setErrorQuiet(EGL_BAD_DISPLAY, 0);
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001890}
1891
1892EGLuint64NV eglGetSystemTimeNV()
1893{
1894 clearError();
1895
1896 if (egl_init_drivers() == EGL_FALSE) {
1897 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1898 }
1899
1900 EGLuint64NV ret = 0;
Mathias Agopianada798b2012-02-13 17:09:30 -08001901 egl_connection_t* const cnx = &gEGLImpl;
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001902
Mathias Agopianada798b2012-02-13 17:09:30 -08001903 if (cnx->dso && cnx->egl.eglGetSystemTimeNV) {
1904 return cnx->egl.eglGetSystemTimeNV();
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001905 }
1906
Mathias Agopian0e8bbee2011-10-05 19:15:05 -07001907 return setErrorQuiet(EGL_BAD_DISPLAY, 0);
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001908}
Dan Stozaa894d082015-02-19 15:27:36 -08001909
1910// ----------------------------------------------------------------------------
1911// Partial update extension
1912// ----------------------------------------------------------------------------
1913EGLBoolean eglSetDamageRegionKHR(EGLDisplay dpy, EGLSurface surface,
1914 EGLint *rects, EGLint n_rects)
1915{
1916 clearError();
1917
1918 const egl_display_ptr dp = validate_display(dpy);
1919 if (!dp) {
1920 setError(EGL_BAD_DISPLAY, EGL_FALSE);
1921 return EGL_FALSE;
1922 }
1923
1924 SurfaceRef _s(dp.get(), surface);
1925 if (!_s.get()) {
1926 setError(EGL_BAD_SURFACE, EGL_FALSE);
1927 return EGL_FALSE;
1928 }
1929
1930 egl_surface_t const * const s = get_surface(surface);
1931 if (s->cnx->egl.eglSetDamageRegionKHR) {
1932 return s->cnx->egl.eglSetDamageRegionKHR(dp->disp.dpy, s->surface,
1933 rects, n_rects);
1934 }
1935
1936 return EGL_FALSE;
1937}