blob: ed58cdcf10a68c83b7c62e5082ea2db4752a94fa [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
Dan Stozaf62eaf52016-06-01 18:21:44 -070036#include <gui/ISurfaceComposer.h>
37
Craig Donner05249fc2016-01-15 19:33:55 -080038#include <ui/GraphicBuffer.h>
39
Mathias Agopian518ec112011-05-13 16:21:08 -070040#include <utils/KeyedVector.h>
41#include <utils/SortedVector.h>
42#include <utils/String8.h>
Jamie Gennis1c8e95c2012-02-23 19:27:23 -080043#include <utils/Trace.h>
Mathias Agopian518ec112011-05-13 16:21:08 -070044
Dan Stozaf62eaf52016-06-01 18:21:44 -070045#include "binder/Binder.h"
46#include "binder/Parcel.h"
47#include "binder/IServiceManager.h"
48
Mathias Agopian39c24a22013-04-04 23:17:56 -070049#include "../egl_impl.h"
Mathias Agopian39c24a22013-04-04 23:17:56 -070050#include "../hooks.h"
Mathias Agopian518ec112011-05-13 16:21:08 -070051
52#include "egl_display.h"
Mathias Agopian518ec112011-05-13 16:21:08 -070053#include "egl_object.h"
54#include "egl_tls.h"
Mathias Agopianada798b2012-02-13 17:09:30 -080055#include "egldefs.h"
Mathias Agopian518ec112011-05-13 16:21:08 -070056
57using namespace android;
58
59// ----------------------------------------------------------------------------
60
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070061namespace android {
62
Mathias Agopian518ec112011-05-13 16:21:08 -070063struct extention_map_t {
64 const char* name;
65 __eglMustCastToProperFunctionPointerType address;
66};
67
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070068/*
Jesse Hall21558da2013-08-06 15:31:22 -070069 * This is the list of EGL extensions exposed to applications.
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070070 *
Jesse Hall21558da2013-08-06 15:31:22 -070071 * Some of them (gBuiltinExtensionString) are implemented entirely in this EGL
72 * wrapper and are always available.
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070073 *
Jesse Hall21558da2013-08-06 15:31:22 -070074 * The rest (gExtensionString) depend on support in the EGL driver, and are
75 * only available if the driver supports them. However, some of these must be
76 * supported because they are used by the Android system itself; these are
Pablo Ceballos02b05da2016-02-02 17:53:18 -080077 * listed as mandatory below and are required by the CDD. The system *assumes*
Jesse Hall21558da2013-08-06 15:31:22 -070078 * the mandatory extensions are present and may not function properly if some
79 * are missing.
80 *
81 * NOTE: Both strings MUST have a single space as the last character.
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070082 */
Jesse Hall21558da2013-08-06 15:31:22 -070083extern char const * const gBuiltinExtensionString =
84 "EGL_KHR_get_all_proc_addresses "
85 "EGL_ANDROID_presentation_time "
Dan Stozaa894d082015-02-19 15:27:36 -080086 "EGL_KHR_swap_buffers_with_damage "
Craig Donner05249fc2016-01-15 19:33:55 -080087 "EGL_ANDROID_create_native_client_buffer "
Pablo Ceballos02b05da2016-02-02 17:53:18 -080088 "EGL_ANDROID_front_buffer_auto_refresh "
Jesse Hall21558da2013-08-06 15:31:22 -070089 ;
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070090extern char const * const gExtensionString =
91 "EGL_KHR_image " // mandatory
92 "EGL_KHR_image_base " // mandatory
93 "EGL_KHR_image_pixmap "
94 "EGL_KHR_lock_surface "
Jesse Hallc2e41222013-08-08 13:40:22 -070095 "EGL_KHR_gl_colorspace "
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 "
Christian Poetzscha7805f62016-12-01 16:34:39 +0000121 "EGL_IMG_context_priority "
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700122 ;
123
124// extensions not exposed to applications but used by the ANDROID system
125// "EGL_ANDROID_blob_cache " // strongly recommended
126// "EGL_IMG_hibernate_process " // optional
127// "EGL_ANDROID_native_fence_sync " // strongly recommended
128// "EGL_ANDROID_framebuffer_target " // mandatory for HWC 1.1
Jamie Gennisdbe92452013-09-23 17:22:10 -0700129// "EGL_ANDROID_image_crop " // optional
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700130
131/*
132 * EGL Extensions entry-points exposed to 3rd party applications
133 * (keep in sync with gExtensionString above)
134 *
135 */
136static const extention_map_t sExtensionMap[] = {
137 // EGL_KHR_lock_surface
Mathias Agopian518ec112011-05-13 16:21:08 -0700138 { "eglLockSurfaceKHR",
139 (__eglMustCastToProperFunctionPointerType)&eglLockSurfaceKHR },
140 { "eglUnlockSurfaceKHR",
141 (__eglMustCastToProperFunctionPointerType)&eglUnlockSurfaceKHR },
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700142
143 // EGL_KHR_image, EGL_KHR_image_base
Mathias Agopian518ec112011-05-13 16:21:08 -0700144 { "eglCreateImageKHR",
145 (__eglMustCastToProperFunctionPointerType)&eglCreateImageKHR },
146 { "eglDestroyImageKHR",
147 (__eglMustCastToProperFunctionPointerType)&eglDestroyImageKHR },
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700148
149 // EGL_KHR_reusable_sync, EGL_KHR_fence_sync
150 { "eglCreateSyncKHR",
151 (__eglMustCastToProperFunctionPointerType)&eglCreateSyncKHR },
152 { "eglDestroySyncKHR",
153 (__eglMustCastToProperFunctionPointerType)&eglDestroySyncKHR },
154 { "eglClientWaitSyncKHR",
155 (__eglMustCastToProperFunctionPointerType)&eglClientWaitSyncKHR },
156 { "eglSignalSyncKHR",
157 (__eglMustCastToProperFunctionPointerType)&eglSignalSyncKHR },
158 { "eglGetSyncAttribKHR",
159 (__eglMustCastToProperFunctionPointerType)&eglGetSyncAttribKHR },
160
161 // EGL_NV_system_time
Jonas Yang1c3d72a2011-08-26 20:04:39 +0800162 { "eglGetSystemTimeFrequencyNV",
163 (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeFrequencyNV },
164 { "eglGetSystemTimeNV",
165 (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeNV },
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700166
Mathias Agopian2bb71682013-03-27 17:32:41 -0700167 // EGL_KHR_wait_sync
168 { "eglWaitSyncKHR",
169 (__eglMustCastToProperFunctionPointerType)&eglWaitSyncKHR },
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700170
171 // EGL_ANDROID_presentation_time
172 { "eglPresentationTimeANDROID",
173 (__eglMustCastToProperFunctionPointerType)&eglPresentationTimeANDROID },
Dan Stozaa894d082015-02-19 15:27:36 -0800174
175 // EGL_KHR_swap_buffers_with_damage
176 { "eglSwapBuffersWithDamageKHR",
177 (__eglMustCastToProperFunctionPointerType)&eglSwapBuffersWithDamageKHR },
178
Craig Donner05249fc2016-01-15 19:33:55 -0800179 // EGL_ANDROID_native_client_buffer
180 { "eglCreateNativeClientBufferANDROID",
181 (__eglMustCastToProperFunctionPointerType)&eglCreateNativeClientBufferANDROID },
182
Dan Stozaa894d082015-02-19 15:27:36 -0800183 // EGL_KHR_partial_update
184 { "eglSetDamageRegionKHR",
185 (__eglMustCastToProperFunctionPointerType)&eglSetDamageRegionKHR },
Season Li000d88f2015-07-01 11:39:40 -0700186
187 { "eglCreateStreamKHR",
188 (__eglMustCastToProperFunctionPointerType)&eglCreateStreamKHR },
189 { "eglDestroyStreamKHR",
190 (__eglMustCastToProperFunctionPointerType)&eglDestroyStreamKHR },
191 { "eglStreamAttribKHR",
192 (__eglMustCastToProperFunctionPointerType)&eglStreamAttribKHR },
193 { "eglQueryStreamKHR",
194 (__eglMustCastToProperFunctionPointerType)&eglQueryStreamKHR },
195 { "eglQueryStreamu64KHR",
196 (__eglMustCastToProperFunctionPointerType)&eglQueryStreamu64KHR },
197 { "eglQueryStreamTimeKHR",
198 (__eglMustCastToProperFunctionPointerType)&eglQueryStreamTimeKHR },
199 { "eglCreateStreamProducerSurfaceKHR",
200 (__eglMustCastToProperFunctionPointerType)&eglCreateStreamProducerSurfaceKHR },
201 { "eglStreamConsumerGLTextureExternalKHR",
202 (__eglMustCastToProperFunctionPointerType)&eglStreamConsumerGLTextureExternalKHR },
203 { "eglStreamConsumerAcquireKHR",
204 (__eglMustCastToProperFunctionPointerType)&eglStreamConsumerAcquireKHR },
205 { "eglStreamConsumerReleaseKHR",
206 (__eglMustCastToProperFunctionPointerType)&eglStreamConsumerReleaseKHR },
207 { "eglGetStreamFileDescriptorKHR",
208 (__eglMustCastToProperFunctionPointerType)&eglGetStreamFileDescriptorKHR },
209 { "eglCreateStreamFromFileDescriptorKHR",
210 (__eglMustCastToProperFunctionPointerType)&eglCreateStreamFromFileDescriptorKHR },
Mathias Agopian518ec112011-05-13 16:21:08 -0700211};
212
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700213/*
214 * These extensions entry-points should not be exposed to applications.
215 * They're used internally by the Android EGL layer.
216 */
217#define FILTER_EXTENSIONS(procname) \
218 (!strcmp((procname), "eglSetBlobCacheFuncsANDROID") || \
219 !strcmp((procname), "eglHibernateProcessIMG") || \
220 !strcmp((procname), "eglAwakenProcessIMG") || \
221 !strcmp((procname), "eglDupNativeFenceFDANDROID"))
222
223
224
Mathias Agopian518ec112011-05-13 16:21:08 -0700225// accesses protected by sExtensionMapMutex
226static DefaultKeyedVector<String8, __eglMustCastToProperFunctionPointerType> sGLExtentionMap;
227static int sGLExtentionSlot = 0;
228static pthread_mutex_t sExtensionMapMutex = PTHREAD_MUTEX_INITIALIZER;
229
230static void(*findProcAddress(const char* name,
231 const extention_map_t* map, size_t n))() {
232 for (uint32_t i=0 ; i<n ; i++) {
233 if (!strcmp(name, map[i].name)) {
234 return map[i].address;
235 }
236 }
237 return NULL;
238}
239
240// ----------------------------------------------------------------------------
241
Mathias Agopian518ec112011-05-13 16:21:08 -0700242extern void setGLHooksThreadSpecific(gl_hooks_t const *value);
243extern EGLBoolean egl_init_drivers();
244extern const __eglMustCastToProperFunctionPointerType gExtensionForwarders[MAX_NUMBER_OF_GL_EXTENSIONS];
Mathias Agopian518ec112011-05-13 16:21:08 -0700245extern gl_hooks_t gHooksTrace;
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700246
Mathias Agopian518ec112011-05-13 16:21:08 -0700247} // namespace android;
248
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700249
Mathias Agopian518ec112011-05-13 16:21:08 -0700250// ----------------------------------------------------------------------------
251
252static inline void clearError() { egl_tls_t::clearError(); }
253static inline EGLContext getContext() { return egl_tls_t::getContext(); }
254
255// ----------------------------------------------------------------------------
256
257EGLDisplay eglGetDisplay(EGLNativeDisplayType display)
258{
259 clearError();
260
Dan Stozac3289c42014-01-17 11:38:34 -0800261 uintptr_t index = reinterpret_cast<uintptr_t>(display);
Mathias Agopian518ec112011-05-13 16:21:08 -0700262 if (index >= NUM_DISPLAYS) {
263 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
264 }
265
266 if (egl_init_drivers() == EGL_FALSE) {
267 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
268 }
269
270 EGLDisplay dpy = egl_display_t::getFromNativeDisplay(display);
271 return dpy;
272}
273
274// ----------------------------------------------------------------------------
275// Initialization
276// ----------------------------------------------------------------------------
277
278EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
279{
280 clearError();
281
Jesse Hallb29e5e82012-04-04 16:53:42 -0700282 egl_display_ptr dp = get_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700283 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
284
285 EGLBoolean res = dp->initialize(major, minor);
286
287 return res;
288}
289
290EGLBoolean eglTerminate(EGLDisplay dpy)
291{
292 // NOTE: don't unload the drivers b/c some APIs can be called
293 // after eglTerminate() has been called. eglTerminate() only
294 // terminates an EGLDisplay, not a EGL itself.
295
296 clearError();
297
Jesse Hallb29e5e82012-04-04 16:53:42 -0700298 egl_display_ptr dp = get_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700299 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
300
301 EGLBoolean res = dp->terminate();
Jesse Hall47743382013-02-08 11:13:46 -0800302
Mathias Agopian518ec112011-05-13 16:21:08 -0700303 return res;
304}
305
306// ----------------------------------------------------------------------------
307// configuration
308// ----------------------------------------------------------------------------
309
310EGLBoolean eglGetConfigs( EGLDisplay dpy,
311 EGLConfig *configs,
312 EGLint config_size, EGLint *num_config)
313{
314 clearError();
315
Jesse Hallb29e5e82012-04-04 16:53:42 -0700316 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700317 if (!dp) return EGL_FALSE;
318
Mathias Agopian7773c432012-02-13 20:06:08 -0800319 if (num_config==0) {
320 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700321 }
322
Mathias Agopian7773c432012-02-13 20:06:08 -0800323 EGLBoolean res = EGL_FALSE;
324 *num_config = 0;
325
326 egl_connection_t* const cnx = &gEGLImpl;
327 if (cnx->dso) {
328 res = cnx->egl.eglGetConfigs(
329 dp->disp.dpy, configs, config_size, num_config);
Mathias Agopian518ec112011-05-13 16:21:08 -0700330 }
Mathias Agopian7773c432012-02-13 20:06:08 -0800331
332 return res;
Mathias Agopian518ec112011-05-13 16:21:08 -0700333}
334
335EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list,
336 EGLConfig *configs, EGLint config_size,
337 EGLint *num_config)
338{
339 clearError();
340
Jesse Hallb29e5e82012-04-04 16:53:42 -0700341 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700342 if (!dp) return EGL_FALSE;
343
344 if (num_config==0) {
345 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
346 }
347
Mathias Agopian518ec112011-05-13 16:21:08 -0700348 EGLBoolean res = EGL_FALSE;
349 *num_config = 0;
350
Mathias Agopianada798b2012-02-13 17:09:30 -0800351 egl_connection_t* const cnx = &gEGLImpl;
352 if (cnx->dso) {
Romain Guy1cffc802012-10-15 18:13:05 -0700353 if (attrib_list) {
354 char value[PROPERTY_VALUE_MAX];
355 property_get("debug.egl.force_msaa", value, "false");
356
357 if (!strcmp(value, "true")) {
358 size_t attribCount = 0;
359 EGLint attrib = attrib_list[0];
360
361 // Only enable MSAA if the context is OpenGL ES 2.0 and
Romain Guybe3c3e42012-10-15 19:25:18 -0700362 // if no caveat is requested
Romain Guy1cffc802012-10-15 18:13:05 -0700363 const EGLint *attribRendererable = NULL;
364 const EGLint *attribCaveat = NULL;
365
366 // Count the number of attributes and look for
Romain Guybe3c3e42012-10-15 19:25:18 -0700367 // EGL_RENDERABLE_TYPE and EGL_CONFIG_CAVEAT
Romain Guy1cffc802012-10-15 18:13:05 -0700368 while (attrib != EGL_NONE) {
369 attrib = attrib_list[attribCount];
370 switch (attrib) {
371 case EGL_RENDERABLE_TYPE:
372 attribRendererable = &attrib_list[attribCount];
373 break;
374 case EGL_CONFIG_CAVEAT:
375 attribCaveat = &attrib_list[attribCount];
376 break;
377 }
378 attribCount++;
379 }
380
381 if (attribRendererable && attribRendererable[1] == EGL_OPENGL_ES2_BIT &&
382 (!attribCaveat || attribCaveat[1] != EGL_NONE)) {
Jesse Hall47743382013-02-08 11:13:46 -0800383
Romain Guy1cffc802012-10-15 18:13:05 -0700384 // Insert 2 extra attributes to force-enable MSAA 4x
385 EGLint aaAttribs[attribCount + 4];
386 aaAttribs[0] = EGL_SAMPLE_BUFFERS;
387 aaAttribs[1] = 1;
388 aaAttribs[2] = EGL_SAMPLES;
389 aaAttribs[3] = 4;
390
391 memcpy(&aaAttribs[4], attrib_list, attribCount * sizeof(EGLint));
392
393 EGLint numConfigAA;
394 EGLBoolean resAA = cnx->egl.eglChooseConfig(
395 dp->disp.dpy, aaAttribs, configs, config_size, &numConfigAA);
396
397 if (resAA == EGL_TRUE && numConfigAA > 0) {
398 ALOGD("Enabling MSAA 4x");
399 *num_config = numConfigAA;
400 return resAA;
401 }
402 }
403 }
404 }
405
Mathias Agopian7773c432012-02-13 20:06:08 -0800406 res = cnx->egl.eglChooseConfig(
407 dp->disp.dpy, attrib_list, configs, config_size, num_config);
Mathias Agopian518ec112011-05-13 16:21:08 -0700408 }
409 return res;
410}
411
412EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
413 EGLint attribute, EGLint *value)
414{
415 clearError();
416
Jesse Hallb29e5e82012-04-04 16:53:42 -0700417 egl_connection_t* cnx = NULL;
418 const egl_display_ptr dp = validate_display_connection(dpy, cnx);
419 if (!dp) return EGL_FALSE;
Jesse Hall47743382013-02-08 11:13:46 -0800420
Mathias Agopian518ec112011-05-13 16:21:08 -0700421 return cnx->egl.eglGetConfigAttrib(
Mathias Agopian7773c432012-02-13 20:06:08 -0800422 dp->disp.dpy, config, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -0700423}
424
425// ----------------------------------------------------------------------------
426// surfaces
427// ----------------------------------------------------------------------------
428
Jesse Hallc2e41222013-08-08 13:40:22 -0700429// Turn linear formats into corresponding sRGB formats when colorspace is
430// EGL_GL_COLORSPACE_SRGB_KHR, or turn sRGB formats into corresponding linear
431// formats when colorspace is EGL_GL_COLORSPACE_LINEAR_KHR. In any cases where
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800432// the modification isn't possible, the original dataSpace is returned.
433static android_dataspace modifyBufferDataspace( android_dataspace dataSpace,
434 EGLint colorspace) {
Jesse Hallc2e41222013-08-08 13:40:22 -0700435 if (colorspace == EGL_GL_COLORSPACE_LINEAR_KHR) {
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800436 return HAL_DATASPACE_SRGB_LINEAR;
Jesse Hallc2e41222013-08-08 13:40:22 -0700437 } else if (colorspace == EGL_GL_COLORSPACE_SRGB_KHR) {
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800438 return HAL_DATASPACE_SRGB;
Jesse Hallc2e41222013-08-08 13:40:22 -0700439 }
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800440 return dataSpace;
Jesse Hallc2e41222013-08-08 13:40:22 -0700441}
442
Mathias Agopian518ec112011-05-13 16:21:08 -0700443EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config,
444 NativeWindowType window,
445 const EGLint *attrib_list)
446{
447 clearError();
448
Jesse Hallb29e5e82012-04-04 16:53:42 -0700449 egl_connection_t* cnx = NULL;
450 egl_display_ptr dp = validate_display_connection(dpy, cnx);
451 if (dp) {
Mathias Agopianada798b2012-02-13 17:09:30 -0800452 EGLDisplay iDpy = dp->disp.dpy;
Mathias Agopian518ec112011-05-13 16:21:08 -0700453
Andy McFaddend566ce32014-01-07 15:54:17 -0800454 int result = native_window_api_connect(window, NATIVE_WINDOW_API_EGL);
455 if (result != OK) {
456 ALOGE("eglCreateWindowSurface: native_window_api_connect (win=%p) "
457 "failed (%#x) (already connected to another API?)",
458 window, result);
Jonathan Hamilton77a9b4a2013-07-17 09:41:42 -0700459 return setError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
Mathias Agopian81a63352011-07-29 17:55:48 -0700460 }
461
Mathias Agopian0f288fc2013-08-21 16:36:34 -0700462 // Set the native window's buffers format to match what this config requests.
Jesse Hallc2e41222013-08-08 13:40:22 -0700463 // Whether to use sRGB gamma is not part of the EGLconfig, but is part
464 // of our native format. So if sRGB gamma is requested, we have to
465 // modify the EGLconfig's format before setting the native window's
466 // format.
Alistair Strachan733a8072015-02-12 12:33:25 -0800467
Mathias Agopian0f288fc2013-08-21 16:36:34 -0700468 // by default, just pick RGBA_8888
469 EGLint format = HAL_PIXEL_FORMAT_RGBA_8888;
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800470 android_dataspace dataSpace = HAL_DATASPACE_UNKNOWN;
Mathias Agopian0f288fc2013-08-21 16:36:34 -0700471
472 EGLint a = 0;
473 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_ALPHA_SIZE, &a);
474 if (a > 0) {
475 // alpha-channel requested, there's really only one suitable format
476 format = HAL_PIXEL_FORMAT_RGBA_8888;
477 } else {
478 EGLint r, g, b;
479 r = g = b = 0;
480 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_RED_SIZE, &r);
481 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_GREEN_SIZE, &g);
482 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_BLUE_SIZE, &b);
483 EGLint colorDepth = r + g + b;
484 if (colorDepth <= 16) {
485 format = HAL_PIXEL_FORMAT_RGB_565;
486 } else {
487 format = HAL_PIXEL_FORMAT_RGBX_8888;
488 }
Jesse Hallc2e41222013-08-08 13:40:22 -0700489 }
Mathias Agopian0f288fc2013-08-21 16:36:34 -0700490
491 // now select a corresponding sRGB format if needed
492 if (attrib_list && dp->haveExtension("EGL_KHR_gl_colorspace")) {
493 for (const EGLint* attr = attrib_list; *attr != EGL_NONE; attr += 2) {
494 if (*attr == EGL_GL_COLORSPACE_KHR) {
Sandeep Shinde9c67bfd2015-02-10 16:04:15 +0530495 dataSpace = modifyBufferDataspace(dataSpace, *(attr+1));
Jamie Gennisbee205f2011-07-01 13:12:07 -0700496 }
Mathias Agopian518ec112011-05-13 16:21:08 -0700497 }
498 }
Alistair Strachan733a8072015-02-12 12:33:25 -0800499
Jesse Hallc2e41222013-08-08 13:40:22 -0700500 if (format != 0) {
501 int err = native_window_set_buffers_format(window, format);
502 if (err != 0) {
503 ALOGE("error setting native window pixel format: %s (%d)",
504 strerror(-err), err);
505 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
506 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
507 }
508 }
Mathias Agopian518ec112011-05-13 16:21:08 -0700509
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800510 if (dataSpace != 0) {
511 int err = native_window_set_buffers_data_space(window, dataSpace);
512 if (err != 0) {
513 ALOGE("error setting native window pixel dataSpace: %s (%d)",
514 strerror(-err), err);
515 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
516 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
517 }
518 }
519
Jamie Gennis59769462011-11-19 18:04:43 -0800520 // the EGL spec requires that a new EGLSurface default to swap interval
521 // 1, so explicitly set that on the window here.
522 ANativeWindow* anw = reinterpret_cast<ANativeWindow*>(window);
523 anw->setSwapInterval(anw, 1);
524
Mathias Agopian518ec112011-05-13 16:21:08 -0700525 EGLSurface surface = cnx->egl.eglCreateWindowSurface(
Mathias Agopian7773c432012-02-13 20:06:08 -0800526 iDpy, config, window, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700527 if (surface != EGL_NO_SURFACE) {
Jesse Hallb29e5e82012-04-04 16:53:42 -0700528 egl_surface_t* s = new egl_surface_t(dp.get(), config, window,
529 surface, cnx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700530 return s;
531 }
Mathias Agopian81a63352011-07-29 17:55:48 -0700532
533 // EGLSurface creation failed
534 native_window_set_buffers_format(window, 0);
535 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
Mathias Agopian518ec112011-05-13 16:21:08 -0700536 }
537 return EGL_NO_SURFACE;
538}
539
540EGLSurface eglCreatePixmapSurface( EGLDisplay dpy, EGLConfig config,
541 NativePixmapType pixmap,
542 const EGLint *attrib_list)
543{
544 clearError();
545
Jesse Hallb29e5e82012-04-04 16:53:42 -0700546 egl_connection_t* cnx = NULL;
547 egl_display_ptr dp = validate_display_connection(dpy, cnx);
548 if (dp) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700549 EGLSurface surface = cnx->egl.eglCreatePixmapSurface(
Mathias Agopian7773c432012-02-13 20:06:08 -0800550 dp->disp.dpy, config, pixmap, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700551 if (surface != EGL_NO_SURFACE) {
Jesse Hallb29e5e82012-04-04 16:53:42 -0700552 egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL,
553 surface, cnx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700554 return s;
555 }
556 }
557 return EGL_NO_SURFACE;
558}
559
560EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config,
561 const EGLint *attrib_list)
562{
563 clearError();
564
Jesse Hallb29e5e82012-04-04 16:53:42 -0700565 egl_connection_t* cnx = NULL;
566 egl_display_ptr dp = validate_display_connection(dpy, cnx);
567 if (dp) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700568 EGLSurface surface = cnx->egl.eglCreatePbufferSurface(
Mathias Agopian7773c432012-02-13 20:06:08 -0800569 dp->disp.dpy, config, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700570 if (surface != EGL_NO_SURFACE) {
Jesse Hallb29e5e82012-04-04 16:53:42 -0700571 egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL,
572 surface, cnx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700573 return s;
574 }
575 }
576 return EGL_NO_SURFACE;
577}
Jesse Hall47743382013-02-08 11:13:46 -0800578
Mathias Agopian518ec112011-05-13 16:21:08 -0700579EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
580{
581 clearError();
582
Jesse Hallb29e5e82012-04-04 16:53:42 -0700583 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700584 if (!dp) return EGL_FALSE;
585
Jesse Hallb29e5e82012-04-04 16:53:42 -0700586 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700587 if (!_s.get())
588 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700589
590 egl_surface_t * const s = get_surface(surface);
Mathias Agopianada798b2012-02-13 17:09:30 -0800591 EGLBoolean result = s->cnx->egl.eglDestroySurface(dp->disp.dpy, s->surface);
Mathias Agopian518ec112011-05-13 16:21:08 -0700592 if (result == EGL_TRUE) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700593 _s.terminate();
594 }
595 return result;
596}
597
598EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface surface,
599 EGLint attribute, EGLint *value)
600{
601 clearError();
602
Jesse Hallb29e5e82012-04-04 16:53:42 -0700603 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700604 if (!dp) return EGL_FALSE;
605
Jesse Hallb29e5e82012-04-04 16:53:42 -0700606 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700607 if (!_s.get())
608 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700609
Mathias Agopian518ec112011-05-13 16:21:08 -0700610 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian7773c432012-02-13 20:06:08 -0800611 return s->cnx->egl.eglQuerySurface(
612 dp->disp.dpy, s->surface, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -0700613}
614
Jamie Gennise8696a42012-01-15 18:54:57 -0800615void EGLAPI eglBeginFrame(EGLDisplay dpy, EGLSurface surface) {
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800616 ATRACE_CALL();
Jamie Gennise8696a42012-01-15 18:54:57 -0800617 clearError();
618
Jesse Hallb29e5e82012-04-04 16:53:42 -0700619 const egl_display_ptr dp = validate_display(dpy);
Jamie Gennise8696a42012-01-15 18:54:57 -0800620 if (!dp) {
621 return;
622 }
623
Jesse Hallb29e5e82012-04-04 16:53:42 -0700624 SurfaceRef _s(dp.get(), surface);
Jamie Gennise8696a42012-01-15 18:54:57 -0800625 if (!_s.get()) {
626 setError(EGL_BAD_SURFACE, EGL_FALSE);
627 return;
628 }
Jamie Gennise8696a42012-01-15 18:54:57 -0800629}
630
Mathias Agopian518ec112011-05-13 16:21:08 -0700631// ----------------------------------------------------------------------------
632// Contexts
633// ----------------------------------------------------------------------------
634
635EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config,
636 EGLContext share_list, const EGLint *attrib_list)
637{
638 clearError();
639
Jesse Hallb29e5e82012-04-04 16:53:42 -0700640 egl_connection_t* cnx = NULL;
641 const egl_display_ptr dp = validate_display_connection(dpy, cnx);
Michael Chock0673e1e2012-06-21 12:53:17 -0700642 if (dp) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700643 if (share_list != EGL_NO_CONTEXT) {
Michael Chock0673e1e2012-06-21 12:53:17 -0700644 if (!ContextRef(dp.get(), share_list).get()) {
645 return setError(EGL_BAD_CONTEXT, EGL_NO_CONTEXT);
646 }
Mathias Agopian518ec112011-05-13 16:21:08 -0700647 egl_context_t* const c = get_context(share_list);
648 share_list = c->context;
649 }
650 EGLContext context = cnx->egl.eglCreateContext(
Mathias Agopian7773c432012-02-13 20:06:08 -0800651 dp->disp.dpy, config, share_list, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700652 if (context != EGL_NO_CONTEXT) {
653 // figure out if it's a GLESv1 or GLESv2
654 int version = 0;
655 if (attrib_list) {
656 while (*attrib_list != EGL_NONE) {
657 GLint attr = *attrib_list++;
658 GLint value = *attrib_list++;
659 if (attr == EGL_CONTEXT_CLIENT_VERSION) {
660 if (value == 1) {
Mathias Agopian7773c432012-02-13 20:06:08 -0800661 version = egl_connection_t::GLESv1_INDEX;
Jesse Hall47743382013-02-08 11:13:46 -0800662 } else if (value == 2 || value == 3) {
Mathias Agopian7773c432012-02-13 20:06:08 -0800663 version = egl_connection_t::GLESv2_INDEX;
Mathias Agopian518ec112011-05-13 16:21:08 -0700664 }
665 }
666 };
667 }
Jesse Hallb29e5e82012-04-04 16:53:42 -0700668 egl_context_t* c = new egl_context_t(dpy, context, config, cnx,
669 version);
Mathias Agopian518ec112011-05-13 16:21:08 -0700670 return c;
671 }
672 }
673 return EGL_NO_CONTEXT;
674}
675
676EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
677{
678 clearError();
679
Jesse Hallb29e5e82012-04-04 16:53:42 -0700680 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700681 if (!dp)
682 return EGL_FALSE;
Mathias Agopian518ec112011-05-13 16:21:08 -0700683
Jesse Hallb29e5e82012-04-04 16:53:42 -0700684 ContextRef _c(dp.get(), ctx);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700685 if (!_c.get())
686 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
Jesse Hall47743382013-02-08 11:13:46 -0800687
Mathias Agopian518ec112011-05-13 16:21:08 -0700688 egl_context_t * const c = get_context(ctx);
Mathias Agopianada798b2012-02-13 17:09:30 -0800689 EGLBoolean result = c->cnx->egl.eglDestroyContext(dp->disp.dpy, c->context);
Mathias Agopian518ec112011-05-13 16:21:08 -0700690 if (result == EGL_TRUE) {
691 _c.terminate();
692 }
693 return result;
694}
695
Mathias Agopian518ec112011-05-13 16:21:08 -0700696EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw,
697 EGLSurface read, EGLContext ctx)
698{
699 clearError();
700
Jesse Hallb29e5e82012-04-04 16:53:42 -0700701 egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700702 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
703
Mathias Agopian5b287a62011-05-16 18:58:55 -0700704 // If ctx is not EGL_NO_CONTEXT, read is not EGL_NO_SURFACE, or draw is not
705 // EGL_NO_SURFACE, then an EGL_NOT_INITIALIZED error is generated if dpy is
706 // a valid but uninitialized display.
Mathias Agopian518ec112011-05-13 16:21:08 -0700707 if ( (ctx != EGL_NO_CONTEXT) || (read != EGL_NO_SURFACE) ||
708 (draw != EGL_NO_SURFACE) ) {
709 if (!dp->isReady()) return setError(EGL_NOT_INITIALIZED, EGL_FALSE);
710 }
711
712 // get a reference to the object passed in
Jesse Hallb29e5e82012-04-04 16:53:42 -0700713 ContextRef _c(dp.get(), ctx);
714 SurfaceRef _d(dp.get(), draw);
715 SurfaceRef _r(dp.get(), read);
Mathias Agopian518ec112011-05-13 16:21:08 -0700716
717 // validate the context (if not EGL_NO_CONTEXT)
Mathias Agopian5b287a62011-05-16 18:58:55 -0700718 if ((ctx != EGL_NO_CONTEXT) && !_c.get()) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700719 // EGL_NO_CONTEXT is valid
Michael Chock0673e1e2012-06-21 12:53:17 -0700720 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700721 }
722
723 // these are the underlying implementation's object
724 EGLContext impl_ctx = EGL_NO_CONTEXT;
725 EGLSurface impl_draw = EGL_NO_SURFACE;
726 EGLSurface impl_read = EGL_NO_SURFACE;
727
728 // these are our objects structs passed in
729 egl_context_t * c = NULL;
730 egl_surface_t const * d = NULL;
731 egl_surface_t const * r = NULL;
732
733 // these are the current objects structs
734 egl_context_t * cur_c = get_context(getContext());
Jesse Hall47743382013-02-08 11:13:46 -0800735
Mathias Agopian518ec112011-05-13 16:21:08 -0700736 if (ctx != EGL_NO_CONTEXT) {
737 c = get_context(ctx);
738 impl_ctx = c->context;
739 } else {
740 // no context given, use the implementation of the current context
Michael Chock0673e1e2012-06-21 12:53:17 -0700741 if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE) {
742 // calling eglMakeCurrent( ..., !=0, !=0, EGL_NO_CONTEXT);
743 return setError(EGL_BAD_MATCH, EGL_FALSE);
744 }
Mathias Agopian518ec112011-05-13 16:21:08 -0700745 if (cur_c == NULL) {
746 // no current context
Mathias Agopian518ec112011-05-13 16:21:08 -0700747 // not an error, there is just no current context.
748 return EGL_TRUE;
749 }
750 }
751
752 // retrieve the underlying implementation's draw EGLSurface
753 if (draw != EGL_NO_SURFACE) {
Michael Chock0673e1e2012-06-21 12:53:17 -0700754 if (!_d.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700755 d = get_surface(draw);
Mathias Agopian518ec112011-05-13 16:21:08 -0700756 impl_draw = d->surface;
757 }
758
759 // retrieve the underlying implementation's read EGLSurface
760 if (read != EGL_NO_SURFACE) {
Michael Chock0673e1e2012-06-21 12:53:17 -0700761 if (!_r.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700762 r = get_surface(read);
Mathias Agopian518ec112011-05-13 16:21:08 -0700763 impl_read = r->surface;
764 }
765
Mathias Agopian518ec112011-05-13 16:21:08 -0700766
Jesse Hallb29e5e82012-04-04 16:53:42 -0700767 EGLBoolean result = dp->makeCurrent(c, cur_c,
Mathias Agopianfb87e542012-01-30 18:20:52 -0800768 draw, read, ctx,
769 impl_draw, impl_read, impl_ctx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700770
771 if (result == EGL_TRUE) {
Mathias Agopianfb87e542012-01-30 18:20:52 -0800772 if (c) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700773 setGLHooksThreadSpecific(c->cnx->hooks[c->version]);
774 egl_tls_t::setContext(ctx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700775 _c.acquire();
776 _r.acquire();
777 _d.acquire();
Mathias Agopian518ec112011-05-13 16:21:08 -0700778 } else {
779 setGLHooksThreadSpecific(&gHooksNoContext);
780 egl_tls_t::setContext(EGL_NO_CONTEXT);
781 }
Mathias Agopian5fecea72011-08-25 18:38:24 -0700782 } else {
Steve Blocke6f43dd2012-01-06 19:20:56 +0000783 // this will ALOGE the error
Mathias Agopian63108c32013-09-06 13:36:49 -0700784 egl_connection_t* const cnx = &gEGLImpl;
785 result = setError(cnx->egl.eglGetError(), EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700786 }
787 return result;
788}
789
790
791EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx,
792 EGLint attribute, EGLint *value)
793{
794 clearError();
795
Jesse Hallb29e5e82012-04-04 16:53:42 -0700796 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700797 if (!dp) return EGL_FALSE;
798
Jesse Hallb29e5e82012-04-04 16:53:42 -0700799 ContextRef _c(dp.get(), ctx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700800 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
801
Mathias Agopian518ec112011-05-13 16:21:08 -0700802 egl_context_t * const c = get_context(ctx);
Mathias Agopian7773c432012-02-13 20:06:08 -0800803 return c->cnx->egl.eglQueryContext(
804 dp->disp.dpy, c->context, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -0700805
Mathias Agopian518ec112011-05-13 16:21:08 -0700806}
807
808EGLContext eglGetCurrentContext(void)
809{
810 // could be called before eglInitialize(), but we wouldn't have a context
811 // then, and this function would correctly return EGL_NO_CONTEXT.
812
813 clearError();
814
815 EGLContext ctx = getContext();
816 return ctx;
817}
818
819EGLSurface eglGetCurrentSurface(EGLint readdraw)
820{
821 // could be called before eglInitialize(), but we wouldn't have a context
822 // then, and this function would correctly return EGL_NO_SURFACE.
823
824 clearError();
825
826 EGLContext ctx = getContext();
827 if (ctx) {
828 egl_context_t const * const c = get_context(ctx);
829 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
830 switch (readdraw) {
831 case EGL_READ: return c->read;
Jesse Hall47743382013-02-08 11:13:46 -0800832 case EGL_DRAW: return c->draw;
Mathias Agopian518ec112011-05-13 16:21:08 -0700833 default: return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
834 }
835 }
836 return EGL_NO_SURFACE;
837}
838
839EGLDisplay eglGetCurrentDisplay(void)
840{
841 // could be called before eglInitialize(), but we wouldn't have a context
842 // then, and this function would correctly return EGL_NO_DISPLAY.
843
844 clearError();
845
846 EGLContext ctx = getContext();
847 if (ctx) {
848 egl_context_t const * const c = get_context(ctx);
849 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
850 return c->dpy;
851 }
852 return EGL_NO_DISPLAY;
853}
854
855EGLBoolean eglWaitGL(void)
856{
Mathias Agopian518ec112011-05-13 16:21:08 -0700857 clearError();
858
Mathias Agopianada798b2012-02-13 17:09:30 -0800859 egl_connection_t* const cnx = &gEGLImpl;
860 if (!cnx->dso)
861 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
862
863 return cnx->egl.eglWaitGL();
Mathias Agopian518ec112011-05-13 16:21:08 -0700864}
865
866EGLBoolean eglWaitNative(EGLint engine)
867{
Mathias Agopian518ec112011-05-13 16:21:08 -0700868 clearError();
869
Mathias Agopianada798b2012-02-13 17:09:30 -0800870 egl_connection_t* const cnx = &gEGLImpl;
871 if (!cnx->dso)
872 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
873
874 return cnx->egl.eglWaitNative(engine);
Mathias Agopian518ec112011-05-13 16:21:08 -0700875}
876
877EGLint eglGetError(void)
878{
Mathias Agopianada798b2012-02-13 17:09:30 -0800879 EGLint err = EGL_SUCCESS;
880 egl_connection_t* const cnx = &gEGLImpl;
881 if (cnx->dso) {
882 err = cnx->egl.eglGetError();
Mathias Agopian518ec112011-05-13 16:21:08 -0700883 }
Mathias Agopianada798b2012-02-13 17:09:30 -0800884 if (err == EGL_SUCCESS) {
885 err = egl_tls_t::getError();
886 }
887 return err;
Mathias Agopian518ec112011-05-13 16:21:08 -0700888}
889
Michael Chockc0ec5e22014-01-27 08:14:33 -0800890static __eglMustCastToProperFunctionPointerType findBuiltinWrapper(
Jesse Hallc07b5202013-07-04 12:08:16 -0700891 const char* procname) {
892 const egl_connection_t* cnx = &gEGLImpl;
893 void* proc = NULL;
894
Michael Chockc0ec5e22014-01-27 08:14:33 -0800895 proc = dlsym(cnx->libEgl, procname);
896 if (proc) return (__eglMustCastToProperFunctionPointerType)proc;
897
Jesse Hallc07b5202013-07-04 12:08:16 -0700898 proc = dlsym(cnx->libGles2, procname);
899 if (proc) return (__eglMustCastToProperFunctionPointerType)proc;
900
901 proc = dlsym(cnx->libGles1, procname);
902 if (proc) return (__eglMustCastToProperFunctionPointerType)proc;
903
904 return NULL;
905}
906
Mathias Agopian518ec112011-05-13 16:21:08 -0700907__eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
908{
909 // eglGetProcAddress() could be the very first function called
910 // in which case we must make sure we've initialized ourselves, this
911 // happens the first time egl_get_display() is called.
912
913 clearError();
914
915 if (egl_init_drivers() == EGL_FALSE) {
916 setError(EGL_BAD_PARAMETER, NULL);
917 return NULL;
918 }
919
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700920 if (FILTER_EXTENSIONS(procname)) {
Jamie Gennisaca51c02011-11-03 17:42:43 -0700921 return NULL;
922 }
923
Mathias Agopian518ec112011-05-13 16:21:08 -0700924 __eglMustCastToProperFunctionPointerType addr;
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700925 addr = findProcAddress(procname, sExtensionMap, NELEM(sExtensionMap));
Mathias Agopian518ec112011-05-13 16:21:08 -0700926 if (addr) return addr;
927
Michael Chockc0ec5e22014-01-27 08:14:33 -0800928 addr = findBuiltinWrapper(procname);
Jesse Hallc07b5202013-07-04 12:08:16 -0700929 if (addr) return addr;
Jamie Gennisaca51c02011-11-03 17:42:43 -0700930
Mathias Agopian518ec112011-05-13 16:21:08 -0700931 // this protects accesses to sGLExtentionMap and sGLExtentionSlot
932 pthread_mutex_lock(&sExtensionMapMutex);
933
934 /*
935 * Since eglGetProcAddress() is not associated to anything, it needs
936 * to return a function pointer that "works" regardless of what
937 * the current context is.
938 *
939 * For this reason, we return a "forwarder", a small stub that takes
940 * care of calling the function associated with the context
941 * currently bound.
942 *
943 * We first look for extensions we've already resolved, if we're seeing
944 * this extension for the first time, we go through all our
945 * implementations and call eglGetProcAddress() and record the
946 * result in the appropriate implementation hooks and return the
947 * address of the forwarder corresponding to that hook set.
948 *
949 */
950
951 const String8 name(procname);
952 addr = sGLExtentionMap.valueFor(name);
953 const int slot = sGLExtentionSlot;
954
Steve Blocke6f43dd2012-01-06 19:20:56 +0000955 ALOGE_IF(slot >= MAX_NUMBER_OF_GL_EXTENSIONS,
Mathias Agopian518ec112011-05-13 16:21:08 -0700956 "no more slots for eglGetProcAddress(\"%s\")",
957 procname);
958
959 if (!addr && (slot < MAX_NUMBER_OF_GL_EXTENSIONS)) {
960 bool found = false;
Mathias Agopianada798b2012-02-13 17:09:30 -0800961
962 egl_connection_t* const cnx = &gEGLImpl;
963 if (cnx->dso && cnx->egl.eglGetProcAddress) {
Mathias Agopianada798b2012-02-13 17:09:30 -0800964 // Extensions are independent of the bound context
luliuhui69d10072012-08-30 11:15:36 +0800965 addr =
Mathias Agopian7773c432012-02-13 20:06:08 -0800966 cnx->hooks[egl_connection_t::GLESv1_INDEX]->ext.extensions[slot] =
967 cnx->hooks[egl_connection_t::GLESv2_INDEX]->ext.extensions[slot] =
Mathias Agopianada798b2012-02-13 17:09:30 -0800968 cnx->egl.eglGetProcAddress(procname);
luliuhui69d10072012-08-30 11:15:36 +0800969 if (addr) found = true;
Mathias Agopian518ec112011-05-13 16:21:08 -0700970 }
Mathias Agopianada798b2012-02-13 17:09:30 -0800971
Mathias Agopian518ec112011-05-13 16:21:08 -0700972 if (found) {
973 addr = gExtensionForwarders[slot];
Mathias Agopian518ec112011-05-13 16:21:08 -0700974 sGLExtentionMap.add(name, addr);
975 sGLExtentionSlot++;
976 }
977 }
978
979 pthread_mutex_unlock(&sExtensionMapMutex);
980 return addr;
981}
982
Jamie Gennis28ef8d72012-04-05 20:34:54 -0700983class FrameCompletionThread : public Thread {
984public:
985
986 static void queueSync(EGLSyncKHR sync) {
987 static sp<FrameCompletionThread> thread(new FrameCompletionThread);
988 static bool running = false;
989 if (!running) {
990 thread->run("GPUFrameCompletion");
991 running = true;
992 }
993 {
994 Mutex::Autolock lock(thread->mMutex);
995 ScopedTrace st(ATRACE_TAG, String8::format("kicked off frame %d",
996 thread->mFramesQueued).string());
997 thread->mQueue.push_back(sync);
998 thread->mCondition.signal();
999 thread->mFramesQueued++;
1000 ATRACE_INT("GPU Frames Outstanding", thread->mQueue.size());
1001 }
1002 }
1003
1004private:
1005 FrameCompletionThread() : mFramesQueued(0), mFramesCompleted(0) {}
1006
1007 virtual bool threadLoop() {
1008 EGLSyncKHR sync;
1009 uint32_t frameNum;
1010 {
1011 Mutex::Autolock lock(mMutex);
1012 while (mQueue.isEmpty()) {
1013 mCondition.wait(mMutex);
1014 }
1015 sync = mQueue[0];
1016 frameNum = mFramesCompleted;
1017 }
1018 EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
1019 {
1020 ScopedTrace st(ATRACE_TAG, String8::format("waiting for frame %d",
1021 frameNum).string());
1022 EGLint result = eglClientWaitSyncKHR(dpy, sync, 0, EGL_FOREVER_KHR);
1023 if (result == EGL_FALSE) {
1024 ALOGE("FrameCompletion: error waiting for fence: %#x", eglGetError());
1025 } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
1026 ALOGE("FrameCompletion: timeout waiting for fence");
1027 }
1028 eglDestroySyncKHR(dpy, sync);
1029 }
1030 {
1031 Mutex::Autolock lock(mMutex);
1032 mQueue.removeAt(0);
1033 mFramesCompleted++;
1034 ATRACE_INT("GPU Frames Outstanding", mQueue.size());
1035 }
1036 return true;
1037 }
1038
1039 uint32_t mFramesQueued;
1040 uint32_t mFramesCompleted;
1041 Vector<EGLSyncKHR> mQueue;
1042 Condition mCondition;
1043 Mutex mMutex;
1044};
1045
Dan Stozaa894d082015-02-19 15:27:36 -08001046EGLBoolean eglSwapBuffersWithDamageKHR(EGLDisplay dpy, EGLSurface draw,
1047 EGLint *rects, EGLint n_rects)
Mathias Agopian518ec112011-05-13 16:21:08 -07001048{
Jamie Gennis1c8e95c2012-02-23 19:27:23 -08001049 ATRACE_CALL();
Mathias Agopian518ec112011-05-13 16:21:08 -07001050 clearError();
1051
Jesse Hallb29e5e82012-04-04 16:53:42 -07001052 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001053 if (!dp) return EGL_FALSE;
1054
Jesse Hallb29e5e82012-04-04 16:53:42 -07001055 SurfaceRef _s(dp.get(), draw);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001056 if (!_s.get())
1057 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001058
Mathias Agopian518ec112011-05-13 16:21:08 -07001059 egl_surface_t const * const s = get_surface(draw);
Mathias Agopian7db993a2012-03-25 00:49:46 -07001060
Mathias Agopianed6d08b2013-04-16 16:39:46 -07001061 if (CC_UNLIKELY(dp->traceGpuCompletion)) {
1062 EGLSyncKHR sync = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, NULL);
1063 if (sync != EGL_NO_SYNC_KHR) {
1064 FrameCompletionThread::queueSync(sync);
1065 }
1066 }
1067
Mathias Agopian7db993a2012-03-25 00:49:46 -07001068 if (CC_UNLIKELY(dp->finishOnSwap)) {
1069 uint32_t pixel;
1070 egl_context_t * const c = get_context( egl_tls_t::getContext() );
1071 if (c) {
1072 // glReadPixels() ensures that the frame is complete
1073 s->cnx->hooks[c->version]->gl.glReadPixels(0,0,1,1,
1074 GL_RGBA,GL_UNSIGNED_BYTE,&pixel);
1075 }
1076 }
1077
Dan Stozaa894d082015-02-19 15:27:36 -08001078 if (n_rects == 0) {
1079 return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface);
1080 }
1081
1082 Vector<android_native_rect_t> androidRects;
1083 for (int r = 0; r < n_rects; ++r) {
1084 int offset = r * 4;
1085 int x = rects[offset];
1086 int y = rects[offset + 1];
1087 int width = rects[offset + 2];
1088 int height = rects[offset + 3];
1089 android_native_rect_t androidRect;
1090 androidRect.left = x;
1091 androidRect.top = y + height;
1092 androidRect.right = x + width;
1093 androidRect.bottom = y;
1094 androidRects.push_back(androidRect);
1095 }
1096 native_window_set_surface_damage(s->win.get(), androidRects.array(),
1097 androidRects.size());
1098
1099 if (s->cnx->egl.eglSwapBuffersWithDamageKHR) {
1100 return s->cnx->egl.eglSwapBuffersWithDamageKHR(dp->disp.dpy, s->surface,
1101 rects, n_rects);
1102 } else {
1103 return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface);
1104 }
1105}
1106
1107EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
1108{
1109 return eglSwapBuffersWithDamageKHR(dpy, surface, NULL, 0);
Mathias Agopian518ec112011-05-13 16:21:08 -07001110}
1111
1112EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface,
1113 NativePixmapType target)
1114{
1115 clearError();
1116
Jesse Hallb29e5e82012-04-04 16:53:42 -07001117 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001118 if (!dp) return EGL_FALSE;
1119
Jesse Hallb29e5e82012-04-04 16:53:42 -07001120 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001121 if (!_s.get())
1122 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001123
Mathias Agopian518ec112011-05-13 16:21:08 -07001124 egl_surface_t const * const s = get_surface(surface);
Mathias Agopianada798b2012-02-13 17:09:30 -08001125 return s->cnx->egl.eglCopyBuffers(dp->disp.dpy, s->surface, target);
Mathias Agopian518ec112011-05-13 16:21:08 -07001126}
1127
1128const char* eglQueryString(EGLDisplay dpy, EGLint name)
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 (const char *) NULL;
1134
1135 switch (name) {
1136 case EGL_VENDOR:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001137 return dp->getVendorString();
Mathias Agopian518ec112011-05-13 16:21:08 -07001138 case EGL_VERSION:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001139 return dp->getVersionString();
Mathias Agopian518ec112011-05-13 16:21:08 -07001140 case EGL_EXTENSIONS:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001141 return dp->getExtensionString();
Mathias Agopian518ec112011-05-13 16:21:08 -07001142 case EGL_CLIENT_APIS:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001143 return dp->getClientApiString();
Mathias Agopian518ec112011-05-13 16:21:08 -07001144 }
1145 return setError(EGL_BAD_PARAMETER, (const char *)0);
1146}
1147
Mathias Agopianca088332013-03-28 17:44:13 -07001148EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name)
1149{
1150 clearError();
1151
1152 const egl_display_ptr dp = validate_display(dpy);
1153 if (!dp) return (const char *) NULL;
1154
1155 switch (name) {
1156 case EGL_VENDOR:
1157 return dp->disp.queryString.vendor;
1158 case EGL_VERSION:
1159 return dp->disp.queryString.version;
1160 case EGL_EXTENSIONS:
1161 return dp->disp.queryString.extensions;
1162 case EGL_CLIENT_APIS:
1163 return dp->disp.queryString.clientApi;
1164 }
1165 return setError(EGL_BAD_PARAMETER, (const char *)0);
1166}
Mathias Agopian518ec112011-05-13 16:21:08 -07001167
1168// ----------------------------------------------------------------------------
1169// EGL 1.1
1170// ----------------------------------------------------------------------------
1171
1172EGLBoolean eglSurfaceAttrib(
1173 EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
1174{
1175 clearError();
1176
Jesse Hallb29e5e82012-04-04 16:53:42 -07001177 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001178 if (!dp) return EGL_FALSE;
1179
Jesse Hallb29e5e82012-04-04 16:53:42 -07001180 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001181 if (!_s.get())
1182 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001183
Mathias Agopian518ec112011-05-13 16:21:08 -07001184 egl_surface_t const * const s = get_surface(surface);
Pablo Ceballosccdfd602015-10-07 15:05:45 -07001185
Pablo Ceballos02b05da2016-02-02 17:53:18 -08001186 if (attribute == EGL_FRONT_BUFFER_AUTO_REFRESH_ANDROID) {
Pablo Ceballosf051ade2016-03-15 18:27:20 -07001187 int err = native_window_set_auto_refresh(s->win.get(),
1188 value ? true : false);
1189 return (err == NO_ERROR) ? EGL_TRUE :
1190 setError(EGL_BAD_SURFACE, EGL_FALSE);
Pablo Ceballosccdfd602015-10-07 15:05:45 -07001191 }
1192
Mathias Agopian518ec112011-05-13 16:21:08 -07001193 if (s->cnx->egl.eglSurfaceAttrib) {
1194 return s->cnx->egl.eglSurfaceAttrib(
Mathias Agopianada798b2012-02-13 17:09:30 -08001195 dp->disp.dpy, s->surface, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -07001196 }
1197 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1198}
1199
1200EGLBoolean eglBindTexImage(
1201 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1202{
1203 clearError();
1204
Jesse Hallb29e5e82012-04-04 16:53:42 -07001205 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001206 if (!dp) return EGL_FALSE;
1207
Jesse Hallb29e5e82012-04-04 16:53:42 -07001208 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001209 if (!_s.get())
1210 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001211
Mathias Agopian518ec112011-05-13 16:21:08 -07001212 egl_surface_t const * const s = get_surface(surface);
1213 if (s->cnx->egl.eglBindTexImage) {
1214 return s->cnx->egl.eglBindTexImage(
Mathias Agopianada798b2012-02-13 17:09:30 -08001215 dp->disp.dpy, s->surface, buffer);
Mathias Agopian518ec112011-05-13 16:21:08 -07001216 }
1217 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1218}
1219
1220EGLBoolean eglReleaseTexImage(
1221 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1222{
1223 clearError();
1224
Jesse Hallb29e5e82012-04-04 16:53:42 -07001225 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001226 if (!dp) return EGL_FALSE;
1227
Jesse Hallb29e5e82012-04-04 16:53:42 -07001228 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001229 if (!_s.get())
1230 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001231
Mathias Agopian518ec112011-05-13 16:21:08 -07001232 egl_surface_t const * const s = get_surface(surface);
1233 if (s->cnx->egl.eglReleaseTexImage) {
1234 return s->cnx->egl.eglReleaseTexImage(
Mathias Agopianada798b2012-02-13 17:09:30 -08001235 dp->disp.dpy, s->surface, buffer);
Mathias Agopian518ec112011-05-13 16:21:08 -07001236 }
1237 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1238}
1239
1240EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
1241{
1242 clearError();
1243
Jesse Hallb29e5e82012-04-04 16:53:42 -07001244 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001245 if (!dp) return EGL_FALSE;
1246
1247 EGLBoolean res = EGL_TRUE;
Mathias Agopianada798b2012-02-13 17:09:30 -08001248 egl_connection_t* const cnx = &gEGLImpl;
1249 if (cnx->dso && cnx->egl.eglSwapInterval) {
1250 res = cnx->egl.eglSwapInterval(dp->disp.dpy, interval);
Mathias Agopian518ec112011-05-13 16:21:08 -07001251 }
Mathias Agopianada798b2012-02-13 17:09:30 -08001252
Mathias Agopian518ec112011-05-13 16:21:08 -07001253 return res;
1254}
1255
1256
1257// ----------------------------------------------------------------------------
1258// EGL 1.2
1259// ----------------------------------------------------------------------------
1260
1261EGLBoolean eglWaitClient(void)
1262{
1263 clearError();
1264
Mathias Agopianada798b2012-02-13 17:09:30 -08001265 egl_connection_t* const cnx = &gEGLImpl;
1266 if (!cnx->dso)
1267 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1268
1269 EGLBoolean res;
1270 if (cnx->egl.eglWaitClient) {
1271 res = cnx->egl.eglWaitClient();
1272 } else {
1273 res = cnx->egl.eglWaitGL();
Mathias Agopian518ec112011-05-13 16:21:08 -07001274 }
1275 return res;
1276}
1277
1278EGLBoolean eglBindAPI(EGLenum api)
1279{
1280 clearError();
1281
1282 if (egl_init_drivers() == EGL_FALSE) {
1283 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1284 }
1285
1286 // bind this API on all EGLs
1287 EGLBoolean res = EGL_TRUE;
Mathias Agopianada798b2012-02-13 17:09:30 -08001288 egl_connection_t* const cnx = &gEGLImpl;
1289 if (cnx->dso && cnx->egl.eglBindAPI) {
1290 res = cnx->egl.eglBindAPI(api);
Mathias Agopian518ec112011-05-13 16:21:08 -07001291 }
1292 return res;
1293}
1294
1295EGLenum eglQueryAPI(void)
1296{
1297 clearError();
1298
1299 if (egl_init_drivers() == EGL_FALSE) {
1300 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1301 }
1302
Mathias Agopianada798b2012-02-13 17:09:30 -08001303 egl_connection_t* const cnx = &gEGLImpl;
1304 if (cnx->dso && cnx->egl.eglQueryAPI) {
1305 return cnx->egl.eglQueryAPI();
Mathias Agopian518ec112011-05-13 16:21:08 -07001306 }
Mathias Agopianada798b2012-02-13 17:09:30 -08001307
Mathias Agopian518ec112011-05-13 16:21:08 -07001308 // or, it can only be OpenGL ES
1309 return EGL_OPENGL_ES_API;
1310}
1311
1312EGLBoolean eglReleaseThread(void)
1313{
1314 clearError();
1315
Mathias Agopianada798b2012-02-13 17:09:30 -08001316 egl_connection_t* const cnx = &gEGLImpl;
1317 if (cnx->dso && cnx->egl.eglReleaseThread) {
1318 cnx->egl.eglReleaseThread();
Mathias Agopian518ec112011-05-13 16:21:08 -07001319 }
Sai Kiran Korwar3ac517a2014-01-31 21:15:07 +05301320
1321 // If there is context bound to the thread, release it
1322 egl_display_t::loseCurrent(get_context(getContext()));
1323
Mathias Agopian518ec112011-05-13 16:21:08 -07001324 egl_tls_t::clearTLS();
Mathias Agopian518ec112011-05-13 16:21:08 -07001325 return EGL_TRUE;
1326}
1327
1328EGLSurface eglCreatePbufferFromClientBuffer(
1329 EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer,
1330 EGLConfig config, const EGLint *attrib_list)
1331{
1332 clearError();
1333
Jesse Hallb29e5e82012-04-04 16:53:42 -07001334 egl_connection_t* cnx = NULL;
1335 const egl_display_ptr dp = validate_display_connection(dpy, cnx);
1336 if (!dp) return EGL_FALSE;
Mathias Agopian518ec112011-05-13 16:21:08 -07001337 if (cnx->egl.eglCreatePbufferFromClientBuffer) {
1338 return cnx->egl.eglCreatePbufferFromClientBuffer(
Mathias Agopian7773c432012-02-13 20:06:08 -08001339 dp->disp.dpy, buftype, buffer, config, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001340 }
1341 return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE);
1342}
1343
1344// ----------------------------------------------------------------------------
1345// EGL_EGLEXT_VERSION 3
1346// ----------------------------------------------------------------------------
1347
1348EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface,
1349 const EGLint *attrib_list)
1350{
1351 clearError();
1352
Jesse Hallb29e5e82012-04-04 16:53:42 -07001353 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001354 if (!dp) return EGL_FALSE;
1355
Jesse Hallb29e5e82012-04-04 16:53:42 -07001356 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001357 if (!_s.get())
1358 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001359
1360 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian518ec112011-05-13 16:21:08 -07001361 if (s->cnx->egl.eglLockSurfaceKHR) {
1362 return s->cnx->egl.eglLockSurfaceKHR(
Mathias Agopianada798b2012-02-13 17:09:30 -08001363 dp->disp.dpy, s->surface, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001364 }
1365 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1366}
1367
1368EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface)
1369{
1370 clearError();
1371
Jesse Hallb29e5e82012-04-04 16:53:42 -07001372 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001373 if (!dp) return EGL_FALSE;
1374
Jesse Hallb29e5e82012-04-04 16:53:42 -07001375 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001376 if (!_s.get())
1377 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001378
1379 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian518ec112011-05-13 16:21:08 -07001380 if (s->cnx->egl.eglUnlockSurfaceKHR) {
Mathias Agopianada798b2012-02-13 17:09:30 -08001381 return s->cnx->egl.eglUnlockSurfaceKHR(dp->disp.dpy, s->surface);
Mathias Agopian518ec112011-05-13 16:21:08 -07001382 }
1383 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1384}
1385
1386EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
1387 EGLClientBuffer buffer, const EGLint *attrib_list)
1388{
1389 clearError();
1390
Jesse Hallb29e5e82012-04-04 16:53:42 -07001391 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001392 if (!dp) return EGL_NO_IMAGE_KHR;
1393
Jesse Hallb29e5e82012-04-04 16:53:42 -07001394 ContextRef _c(dp.get(), ctx);
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001395 egl_context_t * const c = _c.get();
Mathias Agopian518ec112011-05-13 16:21:08 -07001396
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001397 EGLImageKHR result = EGL_NO_IMAGE_KHR;
1398 egl_connection_t* const cnx = &gEGLImpl;
1399 if (cnx->dso && cnx->egl.eglCreateImageKHR) {
1400 result = cnx->egl.eglCreateImageKHR(
1401 dp->disp.dpy,
1402 c ? c->context : EGL_NO_CONTEXT,
1403 target, buffer, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001404 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001405 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001406}
1407
1408EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
1409{
1410 clearError();
1411
Jesse Hallb29e5e82012-04-04 16:53:42 -07001412 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001413 if (!dp) return EGL_FALSE;
1414
Steven Holte646a5c52012-06-04 20:02:11 -07001415 EGLBoolean result = EGL_FALSE;
Mathias Agopianada798b2012-02-13 17:09:30 -08001416 egl_connection_t* const cnx = &gEGLImpl;
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001417 if (cnx->dso && cnx->egl.eglDestroyImageKHR) {
Steven Holte646a5c52012-06-04 20:02:11 -07001418 result = cnx->egl.eglDestroyImageKHR(dp->disp.dpy, img);
Mathias Agopian518ec112011-05-13 16:21:08 -07001419 }
Steven Holte646a5c52012-06-04 20:02:11 -07001420 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001421}
1422
1423// ----------------------------------------------------------------------------
1424// EGL_EGLEXT_VERSION 5
1425// ----------------------------------------------------------------------------
1426
1427
1428EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
1429{
1430 clearError();
1431
Jesse Hallb29e5e82012-04-04 16:53:42 -07001432 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001433 if (!dp) return EGL_NO_SYNC_KHR;
1434
Mathias Agopian518ec112011-05-13 16:21:08 -07001435 EGLSyncKHR result = EGL_NO_SYNC_KHR;
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001436 egl_connection_t* const cnx = &gEGLImpl;
1437 if (cnx->dso && cnx->egl.eglCreateSyncKHR) {
1438 result = cnx->egl.eglCreateSyncKHR(dp->disp.dpy, type, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001439 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001440 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001441}
1442
1443EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
1444{
1445 clearError();
1446
Jesse Hallb29e5e82012-04-04 16:53:42 -07001447 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001448 if (!dp) return EGL_FALSE;
1449
Mathias Agopian518ec112011-05-13 16:21:08 -07001450 EGLBoolean result = EGL_FALSE;
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001451 egl_connection_t* const cnx = &gEGLImpl;
1452 if (cnx->dso && cnx->egl.eglDestroySyncKHR) {
1453 result = cnx->egl.eglDestroySyncKHR(dp->disp.dpy, sync);
Mathias Agopian518ec112011-05-13 16:21:08 -07001454 }
1455 return result;
1456}
1457
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -07001458EGLBoolean eglSignalSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode) {
1459 clearError();
1460
1461 const egl_display_ptr dp = validate_display(dpy);
1462 if (!dp) return EGL_FALSE;
1463
1464 EGLBoolean result = EGL_FALSE;
1465 egl_connection_t* const cnx = &gEGLImpl;
1466 if (cnx->dso && cnx->egl.eglSignalSyncKHR) {
1467 result = cnx->egl.eglSignalSyncKHR(
1468 dp->disp.dpy, sync, mode);
1469 }
1470 return result;
1471}
1472
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001473EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync,
1474 EGLint flags, EGLTimeKHR timeout)
Mathias Agopian518ec112011-05-13 16:21:08 -07001475{
1476 clearError();
1477
Jesse Hallb29e5e82012-04-04 16:53:42 -07001478 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001479 if (!dp) return EGL_FALSE;
1480
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001481 EGLBoolean result = EGL_FALSE;
1482 egl_connection_t* const cnx = &gEGLImpl;
1483 if (cnx->dso && cnx->egl.eglClientWaitSyncKHR) {
1484 result = cnx->egl.eglClientWaitSyncKHR(
1485 dp->disp.dpy, sync, flags, timeout);
Mathias Agopian518ec112011-05-13 16:21:08 -07001486 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001487 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001488}
1489
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001490EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync,
1491 EGLint attribute, EGLint *value)
Mathias Agopian518ec112011-05-13 16:21:08 -07001492{
1493 clearError();
1494
Jesse Hallb29e5e82012-04-04 16:53:42 -07001495 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001496 if (!dp) return EGL_FALSE;
1497
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001498 EGLBoolean result = EGL_FALSE;
1499 egl_connection_t* const cnx = &gEGLImpl;
1500 if (cnx->dso && cnx->egl.eglGetSyncAttribKHR) {
1501 result = cnx->egl.eglGetSyncAttribKHR(
1502 dp->disp.dpy, sync, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -07001503 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001504 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001505}
1506
Season Li000d88f2015-07-01 11:39:40 -07001507EGLStreamKHR eglCreateStreamKHR(EGLDisplay dpy, const EGLint *attrib_list)
1508{
1509 clearError();
1510
1511 const egl_display_ptr dp = validate_display(dpy);
1512 if (!dp) return EGL_NO_STREAM_KHR;
1513
1514 EGLStreamKHR result = EGL_NO_STREAM_KHR;
1515 egl_connection_t* const cnx = &gEGLImpl;
1516 if (cnx->dso && cnx->egl.eglCreateStreamKHR) {
1517 result = cnx->egl.eglCreateStreamKHR(
1518 dp->disp.dpy, attrib_list);
1519 }
1520 return result;
1521}
1522
1523EGLBoolean eglDestroyStreamKHR(EGLDisplay dpy, EGLStreamKHR stream)
1524{
1525 clearError();
1526
1527 const egl_display_ptr dp = validate_display(dpy);
1528 if (!dp) return EGL_FALSE;
1529
1530 EGLBoolean result = EGL_FALSE;
1531 egl_connection_t* const cnx = &gEGLImpl;
1532 if (cnx->dso && cnx->egl.eglDestroyStreamKHR) {
1533 result = cnx->egl.eglDestroyStreamKHR(
1534 dp->disp.dpy, stream);
1535 }
1536 return result;
1537}
1538
1539EGLBoolean eglStreamAttribKHR(EGLDisplay dpy, EGLStreamKHR stream,
1540 EGLenum attribute, EGLint value)
1541{
1542 clearError();
1543
1544 const egl_display_ptr dp = validate_display(dpy);
1545 if (!dp) return EGL_FALSE;
1546
1547 EGLBoolean result = EGL_FALSE;
1548 egl_connection_t* const cnx = &gEGLImpl;
1549 if (cnx->dso && cnx->egl.eglStreamAttribKHR) {
1550 result = cnx->egl.eglStreamAttribKHR(
1551 dp->disp.dpy, stream, attribute, value);
1552 }
1553 return result;
1554}
1555
1556EGLBoolean eglQueryStreamKHR(EGLDisplay dpy, EGLStreamKHR stream,
1557 EGLenum attribute, EGLint *value)
1558{
1559 clearError();
1560
1561 const egl_display_ptr dp = validate_display(dpy);
1562 if (!dp) return EGL_FALSE;
1563
1564 EGLBoolean result = EGL_FALSE;
1565 egl_connection_t* const cnx = &gEGLImpl;
1566 if (cnx->dso && cnx->egl.eglQueryStreamKHR) {
1567 result = cnx->egl.eglQueryStreamKHR(
1568 dp->disp.dpy, stream, attribute, value);
1569 }
1570 return result;
1571}
1572
1573EGLBoolean eglQueryStreamu64KHR(EGLDisplay dpy, EGLStreamKHR stream,
1574 EGLenum attribute, EGLuint64KHR *value)
1575{
1576 clearError();
1577
1578 const egl_display_ptr dp = validate_display(dpy);
1579 if (!dp) return EGL_FALSE;
1580
1581 EGLBoolean result = EGL_FALSE;
1582 egl_connection_t* const cnx = &gEGLImpl;
1583 if (cnx->dso && cnx->egl.eglQueryStreamu64KHR) {
1584 result = cnx->egl.eglQueryStreamu64KHR(
1585 dp->disp.dpy, stream, attribute, value);
1586 }
1587 return result;
1588}
1589
1590EGLBoolean eglQueryStreamTimeKHR(EGLDisplay dpy, EGLStreamKHR stream,
1591 EGLenum attribute, EGLTimeKHR *value)
1592{
1593 clearError();
1594
1595 const egl_display_ptr dp = validate_display(dpy);
1596 if (!dp) return EGL_FALSE;
1597
1598 EGLBoolean result = EGL_FALSE;
1599 egl_connection_t* const cnx = &gEGLImpl;
1600 if (cnx->dso && cnx->egl.eglQueryStreamTimeKHR) {
1601 result = cnx->egl.eglQueryStreamTimeKHR(
1602 dp->disp.dpy, stream, attribute, value);
1603 }
1604 return result;
1605}
1606
1607EGLSurface eglCreateStreamProducerSurfaceKHR(EGLDisplay dpy, EGLConfig config,
1608 EGLStreamKHR stream, const EGLint *attrib_list)
1609{
1610 clearError();
1611
1612 egl_display_ptr dp = validate_display(dpy);
1613 if (!dp) return EGL_NO_SURFACE;
1614
1615 egl_connection_t* const cnx = &gEGLImpl;
1616 if (cnx->dso && cnx->egl.eglCreateStreamProducerSurfaceKHR) {
1617 EGLSurface surface = cnx->egl.eglCreateStreamProducerSurfaceKHR(
1618 dp->disp.dpy, config, stream, attrib_list);
1619 if (surface != EGL_NO_SURFACE) {
1620 egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL,
1621 surface, cnx);
1622 return s;
1623 }
1624 }
1625 return EGL_NO_SURFACE;
1626}
1627
1628EGLBoolean eglStreamConsumerGLTextureExternalKHR(EGLDisplay dpy,
1629 EGLStreamKHR stream)
1630{
1631 clearError();
1632
1633 const egl_display_ptr dp = validate_display(dpy);
1634 if (!dp) return EGL_FALSE;
1635
1636 EGLBoolean result = EGL_FALSE;
1637 egl_connection_t* const cnx = &gEGLImpl;
1638 if (cnx->dso && cnx->egl.eglStreamConsumerGLTextureExternalKHR) {
1639 result = cnx->egl.eglStreamConsumerGLTextureExternalKHR(
1640 dp->disp.dpy, stream);
1641 }
1642 return result;
1643}
1644
1645EGLBoolean eglStreamConsumerAcquireKHR(EGLDisplay dpy,
1646 EGLStreamKHR stream)
1647{
1648 clearError();
1649
1650 const egl_display_ptr dp = validate_display(dpy);
1651 if (!dp) return EGL_FALSE;
1652
1653 EGLBoolean result = EGL_FALSE;
1654 egl_connection_t* const cnx = &gEGLImpl;
1655 if (cnx->dso && cnx->egl.eglStreamConsumerAcquireKHR) {
1656 result = cnx->egl.eglStreamConsumerAcquireKHR(
1657 dp->disp.dpy, stream);
1658 }
1659 return result;
1660}
1661
1662EGLBoolean eglStreamConsumerReleaseKHR(EGLDisplay dpy,
1663 EGLStreamKHR stream)
1664{
1665 clearError();
1666
1667 const egl_display_ptr dp = validate_display(dpy);
1668 if (!dp) return EGL_FALSE;
1669
1670 EGLBoolean result = EGL_FALSE;
1671 egl_connection_t* const cnx = &gEGLImpl;
1672 if (cnx->dso && cnx->egl.eglStreamConsumerReleaseKHR) {
1673 result = cnx->egl.eglStreamConsumerReleaseKHR(
1674 dp->disp.dpy, stream);
1675 }
1676 return result;
1677}
1678
1679EGLNativeFileDescriptorKHR eglGetStreamFileDescriptorKHR(
1680 EGLDisplay dpy, EGLStreamKHR stream)
1681{
1682 clearError();
1683
1684 const egl_display_ptr dp = validate_display(dpy);
1685 if (!dp) return EGL_NO_FILE_DESCRIPTOR_KHR;
1686
1687 EGLNativeFileDescriptorKHR result = EGL_NO_FILE_DESCRIPTOR_KHR;
1688 egl_connection_t* const cnx = &gEGLImpl;
1689 if (cnx->dso && cnx->egl.eglGetStreamFileDescriptorKHR) {
1690 result = cnx->egl.eglGetStreamFileDescriptorKHR(
1691 dp->disp.dpy, stream);
1692 }
1693 return result;
1694}
1695
1696EGLStreamKHR eglCreateStreamFromFileDescriptorKHR(
1697 EGLDisplay dpy, EGLNativeFileDescriptorKHR file_descriptor)
1698{
1699 clearError();
1700
1701 const egl_display_ptr dp = validate_display(dpy);
1702 if (!dp) return EGL_NO_STREAM_KHR;
1703
1704 EGLStreamKHR result = EGL_NO_STREAM_KHR;
1705 egl_connection_t* const cnx = &gEGLImpl;
1706 if (cnx->dso && cnx->egl.eglCreateStreamFromFileDescriptorKHR) {
1707 result = cnx->egl.eglCreateStreamFromFileDescriptorKHR(
1708 dp->disp.dpy, file_descriptor);
1709 }
1710 return result;
1711}
1712
Mathias Agopian518ec112011-05-13 16:21:08 -07001713// ----------------------------------------------------------------------------
Mathias Agopian2bb71682013-03-27 17:32:41 -07001714// EGL_EGLEXT_VERSION 15
1715// ----------------------------------------------------------------------------
1716
1717EGLint eglWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags) {
1718 clearError();
1719 const egl_display_ptr dp = validate_display(dpy);
1720 if (!dp) return EGL_FALSE;
1721 EGLint result = EGL_FALSE;
1722 egl_connection_t* const cnx = &gEGLImpl;
1723 if (cnx->dso && cnx->egl.eglWaitSyncKHR) {
1724 result = cnx->egl.eglWaitSyncKHR(dp->disp.dpy, sync, flags);
1725 }
1726 return result;
1727}
1728
1729// ----------------------------------------------------------------------------
Mathias Agopian518ec112011-05-13 16:21:08 -07001730// ANDROID extensions
1731// ----------------------------------------------------------------------------
1732
Jamie Gennis331841b2012-09-06 14:52:00 -07001733EGLint eglDupNativeFenceFDANDROID(EGLDisplay dpy, EGLSyncKHR sync)
1734{
1735 clearError();
1736
1737 const egl_display_ptr dp = validate_display(dpy);
1738 if (!dp) return EGL_NO_NATIVE_FENCE_FD_ANDROID;
1739
1740 EGLint result = EGL_NO_NATIVE_FENCE_FD_ANDROID;
1741 egl_connection_t* const cnx = &gEGLImpl;
1742 if (cnx->dso && cnx->egl.eglDupNativeFenceFDANDROID) {
1743 result = cnx->egl.eglDupNativeFenceFDANDROID(dp->disp.dpy, sync);
1744 }
1745 return result;
1746}
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001747
Andy McFadden72841452013-03-01 16:25:32 -08001748EGLBoolean eglPresentationTimeANDROID(EGLDisplay dpy, EGLSurface surface,
1749 EGLnsecsANDROID time)
1750{
1751 clearError();
1752
1753 const egl_display_ptr dp = validate_display(dpy);
1754 if (!dp) {
1755 return EGL_FALSE;
1756 }
1757
1758 SurfaceRef _s(dp.get(), surface);
1759 if (!_s.get()) {
1760 setError(EGL_BAD_SURFACE, EGL_FALSE);
1761 return EGL_FALSE;
1762 }
1763
1764 egl_surface_t const * const s = get_surface(surface);
1765 native_window_set_buffers_timestamp(s->win.get(), time);
1766
1767 return EGL_TRUE;
1768}
1769
Craig Donner05249fc2016-01-15 19:33:55 -08001770EGLClientBuffer eglCreateNativeClientBufferANDROID(const EGLint *attrib_list)
1771{
1772 clearError();
1773
1774 int usage = 0;
1775 uint32_t width = 0;
1776 uint32_t height = 0;
1777 uint32_t format = 0;
1778 uint32_t red_size = 0;
1779 uint32_t green_size = 0;
1780 uint32_t blue_size = 0;
1781 uint32_t alpha_size = 0;
1782
Craig Donnerb40504a2016-06-03 17:54:25 -07001783#define GET_NONNEGATIVE_VALUE(case_name, target) \
Craig Donner05249fc2016-01-15 19:33:55 -08001784 case case_name: \
Craig Donnerb40504a2016-06-03 17:54:25 -07001785 if (value >= 0) { \
Craig Donner05249fc2016-01-15 19:33:55 -08001786 target = value; \
1787 } else { \
1788 return setError(EGL_BAD_PARAMETER, (EGLClientBuffer)0); \
1789 } \
1790 break
1791
1792 if (attrib_list) {
1793 while (*attrib_list != EGL_NONE) {
1794 GLint attr = *attrib_list++;
1795 GLint value = *attrib_list++;
1796 switch (attr) {
Craig Donnerb40504a2016-06-03 17:54:25 -07001797 GET_NONNEGATIVE_VALUE(EGL_WIDTH, width);
1798 GET_NONNEGATIVE_VALUE(EGL_HEIGHT, height);
1799 GET_NONNEGATIVE_VALUE(EGL_RED_SIZE, red_size);
1800 GET_NONNEGATIVE_VALUE(EGL_GREEN_SIZE, green_size);
1801 GET_NONNEGATIVE_VALUE(EGL_BLUE_SIZE, blue_size);
1802 GET_NONNEGATIVE_VALUE(EGL_ALPHA_SIZE, alpha_size);
Craig Donner05249fc2016-01-15 19:33:55 -08001803 case EGL_NATIVE_BUFFER_USAGE_ANDROID:
1804 if (value & EGL_NATIVE_BUFFER_USAGE_PROTECTED_BIT_ANDROID) {
1805 usage |= GRALLOC_USAGE_PROTECTED;
Craig Donner05249fc2016-01-15 19:33:55 -08001806 }
Craig Donner8cfae6d2016-04-12 16:54:03 -07001807 if (value & EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_BIT_ANDROID) {
Craig Donner05249fc2016-01-15 19:33:55 -08001808 usage |= GRALLOC_USAGE_HW_RENDER;
1809 }
Craig Donner8cfae6d2016-04-12 16:54:03 -07001810 if (value & EGL_NATIVE_BUFFER_USAGE_TEXTURE_BIT_ANDROID) {
Craig Donner05249fc2016-01-15 19:33:55 -08001811 usage |= GRALLOC_USAGE_HW_TEXTURE;
1812 }
1813 // The buffer must be used for either a texture or a
1814 // renderbuffer.
Craig Donner8cfae6d2016-04-12 16:54:03 -07001815 if ((value & EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_BIT_ANDROID) &&
1816 (value & EGL_NATIVE_BUFFER_USAGE_TEXTURE_BIT_ANDROID)) {
Craig Donner05249fc2016-01-15 19:33:55 -08001817 return setError(EGL_BAD_PARAMETER, (EGLClientBuffer)0);
1818 }
1819 break;
1820 default:
1821 return setError(EGL_BAD_PARAMETER, (EGLClientBuffer)0);
1822 }
1823 }
1824 }
Craig Donnerb40504a2016-06-03 17:54:25 -07001825#undef GET_NONNEGATIVE_VALUE
Craig Donner05249fc2016-01-15 19:33:55 -08001826
1827 // Validate format.
1828 if (red_size == 8 && green_size == 8 && blue_size == 8) {
1829 if (alpha_size == 8) {
1830 format = HAL_PIXEL_FORMAT_RGBA_8888;
1831 } else {
1832 format = HAL_PIXEL_FORMAT_RGB_888;
1833 }
1834 } else if (red_size == 5 && green_size == 6 && blue_size == 5 &&
1835 alpha_size == 0) {
Craig Donner478f7db2016-06-10 17:20:15 -07001836 format = HAL_PIXEL_FORMAT_RGB_565;
Craig Donner05249fc2016-01-15 19:33:55 -08001837 } else {
1838 ALOGE("Invalid native pixel format { r=%d, g=%d, b=%d, a=%d }",
1839 red_size, green_size, blue_size, alpha_size);
1840 return setError(EGL_BAD_PARAMETER, (EGLClientBuffer)0);
1841 }
1842
Dan Stozaf62eaf52016-06-01 18:21:44 -07001843#define CHECK_ERROR_CONDITION(message) \
1844 if (err != NO_ERROR) { \
1845 ALOGE(message); \
1846 goto error_condition; \
1847 }
1848
1849 // The holder is used to destroy the buffer if an error occurs.
1850 GraphicBuffer* gBuffer = new GraphicBuffer();
1851 sp<IServiceManager> sm = defaultServiceManager();
1852 sp<IBinder> surfaceFlinger = sm->getService(String16("SurfaceFlinger"));
1853 sp<IBinder> allocator;
1854 Parcel sc_data, sc_reply, data, reply;
1855 status_t err = NO_ERROR;
1856 if (sm == NULL) {
1857 ALOGE("Unable to connect to ServiceManager");
1858 goto error_condition;
1859 }
1860
1861 // Obtain an allocator.
1862 if (surfaceFlinger == NULL) {
1863 ALOGE("Unable to connect to SurfaceFlinger");
1864 goto error_condition;
1865 }
1866 sc_data.writeInterfaceToken(String16("android.ui.ISurfaceComposer"));
1867 err = surfaceFlinger->transact(
1868 BnSurfaceComposer::CREATE_GRAPHIC_BUFFER_ALLOC, sc_data, &sc_reply);
1869 CHECK_ERROR_CONDITION("Unable to obtain allocator from SurfaceFlinger");
1870 allocator = sc_reply.readStrongBinder();
1871
1872 if (allocator == NULL) {
1873 ALOGE("Unable to obtain an ISurfaceComposer");
1874 goto error_condition;
1875 }
1876 data.writeInterfaceToken(String16("android.ui.IGraphicBufferAlloc"));
1877 err = data.writeUint32(width);
1878 CHECK_ERROR_CONDITION("Unable to write width");
1879 err = data.writeUint32(height);
1880 CHECK_ERROR_CONDITION("Unable to write height");
1881 err = data.writeInt32(static_cast<int32_t>(format));
1882 CHECK_ERROR_CONDITION("Unable to write format");
1883 err = data.writeUint32(usage);
1884 CHECK_ERROR_CONDITION("Unable to write usage");
1885 err = data.writeUtf8AsUtf16(
1886 std::string("[eglCreateNativeClientBufferANDROID pid ") +
1887 std::to_string(getpid()) + ']');
1888 CHECK_ERROR_CONDITION("Unable to write requestor name");
1889 err = allocator->transact(IBinder::FIRST_CALL_TRANSACTION, data,
1890 &reply);
1891 CHECK_ERROR_CONDITION(
1892 "Unable to request buffer allocation from surface composer");
1893 err = reply.readInt32();
1894 CHECK_ERROR_CONDITION("Unable to obtain buffer from surface composer");
1895 err = reply.read(*gBuffer);
1896 CHECK_ERROR_CONDITION("Unable to read buffer from surface composer");
1897
1898 err = gBuffer->initCheck();
Craig Donner05249fc2016-01-15 19:33:55 -08001899 if (err != NO_ERROR) {
1900 ALOGE("Unable to create native buffer { w=%d, h=%d, f=%d, u=%#x }: %#x",
1901 width, height, format, usage, err);
Dan Stozaf62eaf52016-06-01 18:21:44 -07001902 goto error_condition;
Craig Donner05249fc2016-01-15 19:33:55 -08001903 }
1904 ALOGD("Created new native buffer %p { w=%d, h=%d, f=%d, u=%#x }",
1905 gBuffer, width, height, format, usage);
1906 return static_cast<EGLClientBuffer>(gBuffer->getNativeBuffer());
Dan Stozaf62eaf52016-06-01 18:21:44 -07001907
1908#undef CHECK_ERROR_CONDITION
1909
1910error_condition:
1911 // Delete the buffer.
1912 sp<GraphicBuffer> holder(gBuffer);
1913 return setError(EGL_BAD_ALLOC, (EGLClientBuffer)0);
Craig Donner05249fc2016-01-15 19:33:55 -08001914}
1915
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001916// ----------------------------------------------------------------------------
1917// NVIDIA extensions
1918// ----------------------------------------------------------------------------
1919EGLuint64NV eglGetSystemTimeFrequencyNV()
1920{
1921 clearError();
1922
1923 if (egl_init_drivers() == EGL_FALSE) {
1924 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1925 }
1926
1927 EGLuint64NV ret = 0;
Mathias Agopianada798b2012-02-13 17:09:30 -08001928 egl_connection_t* const cnx = &gEGLImpl;
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001929
Mathias Agopianada798b2012-02-13 17:09:30 -08001930 if (cnx->dso && cnx->egl.eglGetSystemTimeFrequencyNV) {
1931 return cnx->egl.eglGetSystemTimeFrequencyNV();
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001932 }
1933
Mathias Agopian0e8bbee2011-10-05 19:15:05 -07001934 return setErrorQuiet(EGL_BAD_DISPLAY, 0);
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001935}
1936
1937EGLuint64NV eglGetSystemTimeNV()
1938{
1939 clearError();
1940
1941 if (egl_init_drivers() == EGL_FALSE) {
1942 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1943 }
1944
1945 EGLuint64NV ret = 0;
Mathias Agopianada798b2012-02-13 17:09:30 -08001946 egl_connection_t* const cnx = &gEGLImpl;
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001947
Mathias Agopianada798b2012-02-13 17:09:30 -08001948 if (cnx->dso && cnx->egl.eglGetSystemTimeNV) {
1949 return cnx->egl.eglGetSystemTimeNV();
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001950 }
1951
Mathias Agopian0e8bbee2011-10-05 19:15:05 -07001952 return setErrorQuiet(EGL_BAD_DISPLAY, 0);
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001953}
Dan Stozaa894d082015-02-19 15:27:36 -08001954
1955// ----------------------------------------------------------------------------
1956// Partial update extension
1957// ----------------------------------------------------------------------------
1958EGLBoolean eglSetDamageRegionKHR(EGLDisplay dpy, EGLSurface surface,
1959 EGLint *rects, EGLint n_rects)
1960{
1961 clearError();
1962
1963 const egl_display_ptr dp = validate_display(dpy);
1964 if (!dp) {
1965 setError(EGL_BAD_DISPLAY, EGL_FALSE);
1966 return EGL_FALSE;
1967 }
1968
1969 SurfaceRef _s(dp.get(), surface);
1970 if (!_s.get()) {
1971 setError(EGL_BAD_SURFACE, EGL_FALSE);
1972 return EGL_FALSE;
1973 }
1974
1975 egl_surface_t const * const s = get_surface(surface);
1976 if (s->cnx->egl.eglSetDamageRegionKHR) {
1977 return s->cnx->egl.eglSetDamageRegionKHR(dp->disp.dpy, s->surface,
1978 rects, n_rects);
1979 }
1980
1981 return EGL_FALSE;
1982}