blob: 0c4b9e9898ed4439513d11fa8c0852b9e55b08e1 [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 "
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 Hallc2e41222013-08-08 13:40:22 -0700428// Turn linear formats into corresponding sRGB formats when colorspace is
429// EGL_GL_COLORSPACE_SRGB_KHR, or turn sRGB formats into corresponding linear
430// formats when colorspace is EGL_GL_COLORSPACE_LINEAR_KHR. In any cases where
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800431// the modification isn't possible, the original dataSpace is returned.
432static android_dataspace modifyBufferDataspace( android_dataspace dataSpace,
433 EGLint colorspace) {
Jesse Hallc2e41222013-08-08 13:40:22 -0700434 if (colorspace == EGL_GL_COLORSPACE_LINEAR_KHR) {
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800435 return HAL_DATASPACE_SRGB_LINEAR;
Jesse Hallc2e41222013-08-08 13:40:22 -0700436 } else if (colorspace == EGL_GL_COLORSPACE_SRGB_KHR) {
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800437 return HAL_DATASPACE_SRGB;
Jesse Hallc2e41222013-08-08 13:40:22 -0700438 }
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800439 return dataSpace;
Jesse Hallc2e41222013-08-08 13:40:22 -0700440}
441
Mathias Agopian518ec112011-05-13 16:21:08 -0700442EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config,
443 NativeWindowType window,
444 const EGLint *attrib_list)
445{
446 clearError();
447
Jesse Hallb29e5e82012-04-04 16:53:42 -0700448 egl_connection_t* cnx = NULL;
449 egl_display_ptr dp = validate_display_connection(dpy, cnx);
450 if (dp) {
Mathias Agopianada798b2012-02-13 17:09:30 -0800451 EGLDisplay iDpy = dp->disp.dpy;
Mathias Agopian518ec112011-05-13 16:21:08 -0700452
Andy McFaddend566ce32014-01-07 15:54:17 -0800453 int result = native_window_api_connect(window, NATIVE_WINDOW_API_EGL);
454 if (result != OK) {
455 ALOGE("eglCreateWindowSurface: native_window_api_connect (win=%p) "
456 "failed (%#x) (already connected to another API?)",
457 window, result);
Jonathan Hamilton77a9b4a2013-07-17 09:41:42 -0700458 return setError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
Mathias Agopian81a63352011-07-29 17:55:48 -0700459 }
460
Mathias Agopian0f288fc2013-08-21 16:36:34 -0700461 // Set the native window's buffers format to match what this config requests.
Jesse Hallc2e41222013-08-08 13:40:22 -0700462 // Whether to use sRGB gamma is not part of the EGLconfig, but is part
463 // of our native format. So if sRGB gamma is requested, we have to
464 // modify the EGLconfig's format before setting the native window's
465 // format.
Alistair Strachan733a8072015-02-12 12:33:25 -0800466
Mathias Agopian0f288fc2013-08-21 16:36:34 -0700467 // by default, just pick RGBA_8888
468 EGLint format = HAL_PIXEL_FORMAT_RGBA_8888;
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800469 android_dataspace dataSpace = HAL_DATASPACE_UNKNOWN;
Mathias Agopian0f288fc2013-08-21 16:36:34 -0700470
471 EGLint a = 0;
472 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_ALPHA_SIZE, &a);
473 if (a > 0) {
474 // alpha-channel requested, there's really only one suitable format
475 format = HAL_PIXEL_FORMAT_RGBA_8888;
476 } else {
477 EGLint r, g, b;
478 r = g = b = 0;
479 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_RED_SIZE, &r);
480 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_GREEN_SIZE, &g);
481 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_BLUE_SIZE, &b);
482 EGLint colorDepth = r + g + b;
483 if (colorDepth <= 16) {
484 format = HAL_PIXEL_FORMAT_RGB_565;
485 } else {
486 format = HAL_PIXEL_FORMAT_RGBX_8888;
487 }
Jesse Hallc2e41222013-08-08 13:40:22 -0700488 }
Mathias Agopian0f288fc2013-08-21 16:36:34 -0700489
490 // now select a corresponding sRGB format if needed
491 if (attrib_list && dp->haveExtension("EGL_KHR_gl_colorspace")) {
492 for (const EGLint* attr = attrib_list; *attr != EGL_NONE; attr += 2) {
493 if (*attr == EGL_GL_COLORSPACE_KHR) {
Sandeep Shinde9c67bfd2015-02-10 16:04:15 +0530494 dataSpace = modifyBufferDataspace(dataSpace, *(attr+1));
Jamie Gennisbee205f2011-07-01 13:12:07 -0700495 }
Mathias Agopian518ec112011-05-13 16:21:08 -0700496 }
497 }
Alistair Strachan733a8072015-02-12 12:33:25 -0800498
Jesse Hallc2e41222013-08-08 13:40:22 -0700499 if (format != 0) {
500 int err = native_window_set_buffers_format(window, format);
501 if (err != 0) {
502 ALOGE("error setting native window pixel format: %s (%d)",
503 strerror(-err), err);
504 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
505 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
506 }
507 }
Mathias Agopian518ec112011-05-13 16:21:08 -0700508
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800509 if (dataSpace != 0) {
510 int err = native_window_set_buffers_data_space(window, dataSpace);
511 if (err != 0) {
512 ALOGE("error setting native window pixel dataSpace: %s (%d)",
513 strerror(-err), err);
514 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
515 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
516 }
517 }
518
Jamie Gennis59769462011-11-19 18:04:43 -0800519 // the EGL spec requires that a new EGLSurface default to swap interval
520 // 1, so explicitly set that on the window here.
521 ANativeWindow* anw = reinterpret_cast<ANativeWindow*>(window);
522 anw->setSwapInterval(anw, 1);
523
Mathias Agopian518ec112011-05-13 16:21:08 -0700524 EGLSurface surface = cnx->egl.eglCreateWindowSurface(
Mathias Agopian7773c432012-02-13 20:06:08 -0800525 iDpy, config, window, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700526 if (surface != EGL_NO_SURFACE) {
Jesse Hallb29e5e82012-04-04 16:53:42 -0700527 egl_surface_t* s = new egl_surface_t(dp.get(), config, window,
528 surface, cnx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700529 return s;
530 }
Mathias Agopian81a63352011-07-29 17:55:48 -0700531
532 // EGLSurface creation failed
533 native_window_set_buffers_format(window, 0);
534 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
Mathias Agopian518ec112011-05-13 16:21:08 -0700535 }
536 return EGL_NO_SURFACE;
537}
538
539EGLSurface eglCreatePixmapSurface( EGLDisplay dpy, EGLConfig config,
540 NativePixmapType pixmap,
541 const EGLint *attrib_list)
542{
543 clearError();
544
Jesse Hallb29e5e82012-04-04 16:53:42 -0700545 egl_connection_t* cnx = NULL;
546 egl_display_ptr dp = validate_display_connection(dpy, cnx);
547 if (dp) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700548 EGLSurface surface = cnx->egl.eglCreatePixmapSurface(
Mathias Agopian7773c432012-02-13 20:06:08 -0800549 dp->disp.dpy, config, pixmap, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700550 if (surface != EGL_NO_SURFACE) {
Jesse Hallb29e5e82012-04-04 16:53:42 -0700551 egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL,
552 surface, cnx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700553 return s;
554 }
555 }
556 return EGL_NO_SURFACE;
557}
558
559EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config,
560 const EGLint *attrib_list)
561{
562 clearError();
563
Jesse Hallb29e5e82012-04-04 16:53:42 -0700564 egl_connection_t* cnx = NULL;
565 egl_display_ptr dp = validate_display_connection(dpy, cnx);
566 if (dp) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700567 EGLSurface surface = cnx->egl.eglCreatePbufferSurface(
Mathias Agopian7773c432012-02-13 20:06:08 -0800568 dp->disp.dpy, config, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700569 if (surface != EGL_NO_SURFACE) {
Jesse Hallb29e5e82012-04-04 16:53:42 -0700570 egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL,
571 surface, cnx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700572 return s;
573 }
574 }
575 return EGL_NO_SURFACE;
576}
Jesse Hall47743382013-02-08 11:13:46 -0800577
Mathias Agopian518ec112011-05-13 16:21:08 -0700578EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
579{
580 clearError();
581
Jesse Hallb29e5e82012-04-04 16:53:42 -0700582 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700583 if (!dp) return EGL_FALSE;
584
Jesse Hallb29e5e82012-04-04 16:53:42 -0700585 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700586 if (!_s.get())
587 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700588
589 egl_surface_t * const s = get_surface(surface);
Mathias Agopianada798b2012-02-13 17:09:30 -0800590 EGLBoolean result = s->cnx->egl.eglDestroySurface(dp->disp.dpy, s->surface);
Mathias Agopian518ec112011-05-13 16:21:08 -0700591 if (result == EGL_TRUE) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700592 _s.terminate();
593 }
594 return result;
595}
596
597EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface surface,
598 EGLint attribute, EGLint *value)
599{
600 clearError();
601
Jesse Hallb29e5e82012-04-04 16:53:42 -0700602 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700603 if (!dp) return EGL_FALSE;
604
Jesse Hallb29e5e82012-04-04 16:53:42 -0700605 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700606 if (!_s.get())
607 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700608
Mathias Agopian518ec112011-05-13 16:21:08 -0700609 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian7773c432012-02-13 20:06:08 -0800610 return s->cnx->egl.eglQuerySurface(
611 dp->disp.dpy, s->surface, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -0700612}
613
Jamie Gennise8696a42012-01-15 18:54:57 -0800614void EGLAPI eglBeginFrame(EGLDisplay dpy, EGLSurface surface) {
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800615 ATRACE_CALL();
Jamie Gennise8696a42012-01-15 18:54:57 -0800616 clearError();
617
Jesse Hallb29e5e82012-04-04 16:53:42 -0700618 const egl_display_ptr dp = validate_display(dpy);
Jamie Gennise8696a42012-01-15 18:54:57 -0800619 if (!dp) {
620 return;
621 }
622
Jesse Hallb29e5e82012-04-04 16:53:42 -0700623 SurfaceRef _s(dp.get(), surface);
Jamie Gennise8696a42012-01-15 18:54:57 -0800624 if (!_s.get()) {
625 setError(EGL_BAD_SURFACE, EGL_FALSE);
626 return;
627 }
Jamie Gennise8696a42012-01-15 18:54:57 -0800628}
629
Mathias Agopian518ec112011-05-13 16:21:08 -0700630// ----------------------------------------------------------------------------
631// Contexts
632// ----------------------------------------------------------------------------
633
634EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config,
635 EGLContext share_list, const EGLint *attrib_list)
636{
637 clearError();
638
Jesse Hallb29e5e82012-04-04 16:53:42 -0700639 egl_connection_t* cnx = NULL;
640 const egl_display_ptr dp = validate_display_connection(dpy, cnx);
Michael Chock0673e1e2012-06-21 12:53:17 -0700641 if (dp) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700642 if (share_list != EGL_NO_CONTEXT) {
Michael Chock0673e1e2012-06-21 12:53:17 -0700643 if (!ContextRef(dp.get(), share_list).get()) {
644 return setError(EGL_BAD_CONTEXT, EGL_NO_CONTEXT);
645 }
Mathias Agopian518ec112011-05-13 16:21:08 -0700646 egl_context_t* const c = get_context(share_list);
647 share_list = c->context;
648 }
649 EGLContext context = cnx->egl.eglCreateContext(
Mathias Agopian7773c432012-02-13 20:06:08 -0800650 dp->disp.dpy, config, share_list, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700651 if (context != EGL_NO_CONTEXT) {
652 // figure out if it's a GLESv1 or GLESv2
653 int version = 0;
654 if (attrib_list) {
655 while (*attrib_list != EGL_NONE) {
656 GLint attr = *attrib_list++;
657 GLint value = *attrib_list++;
658 if (attr == EGL_CONTEXT_CLIENT_VERSION) {
659 if (value == 1) {
Mathias Agopian7773c432012-02-13 20:06:08 -0800660 version = egl_connection_t::GLESv1_INDEX;
Jesse Hall47743382013-02-08 11:13:46 -0800661 } else if (value == 2 || value == 3) {
Mathias Agopian7773c432012-02-13 20:06:08 -0800662 version = egl_connection_t::GLESv2_INDEX;
Mathias Agopian518ec112011-05-13 16:21:08 -0700663 }
664 }
665 };
666 }
Jesse Hallb29e5e82012-04-04 16:53:42 -0700667 egl_context_t* c = new egl_context_t(dpy, context, config, cnx,
668 version);
Mathias Agopian518ec112011-05-13 16:21:08 -0700669 return c;
670 }
671 }
672 return EGL_NO_CONTEXT;
673}
674
675EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
676{
677 clearError();
678
Jesse Hallb29e5e82012-04-04 16:53:42 -0700679 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700680 if (!dp)
681 return EGL_FALSE;
Mathias Agopian518ec112011-05-13 16:21:08 -0700682
Jesse Hallb29e5e82012-04-04 16:53:42 -0700683 ContextRef _c(dp.get(), ctx);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700684 if (!_c.get())
685 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
Jesse Hall47743382013-02-08 11:13:46 -0800686
Mathias Agopian518ec112011-05-13 16:21:08 -0700687 egl_context_t * const c = get_context(ctx);
Mathias Agopianada798b2012-02-13 17:09:30 -0800688 EGLBoolean result = c->cnx->egl.eglDestroyContext(dp->disp.dpy, c->context);
Mathias Agopian518ec112011-05-13 16:21:08 -0700689 if (result == EGL_TRUE) {
690 _c.terminate();
691 }
692 return result;
693}
694
Mathias Agopian518ec112011-05-13 16:21:08 -0700695EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw,
696 EGLSurface read, EGLContext ctx)
697{
698 clearError();
699
Jesse Hallb29e5e82012-04-04 16:53:42 -0700700 egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700701 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
702
Mathias Agopian5b287a62011-05-16 18:58:55 -0700703 // If ctx is not EGL_NO_CONTEXT, read is not EGL_NO_SURFACE, or draw is not
704 // EGL_NO_SURFACE, then an EGL_NOT_INITIALIZED error is generated if dpy is
705 // a valid but uninitialized display.
Mathias Agopian518ec112011-05-13 16:21:08 -0700706 if ( (ctx != EGL_NO_CONTEXT) || (read != EGL_NO_SURFACE) ||
707 (draw != EGL_NO_SURFACE) ) {
708 if (!dp->isReady()) return setError(EGL_NOT_INITIALIZED, EGL_FALSE);
709 }
710
711 // get a reference to the object passed in
Jesse Hallb29e5e82012-04-04 16:53:42 -0700712 ContextRef _c(dp.get(), ctx);
713 SurfaceRef _d(dp.get(), draw);
714 SurfaceRef _r(dp.get(), read);
Mathias Agopian518ec112011-05-13 16:21:08 -0700715
716 // validate the context (if not EGL_NO_CONTEXT)
Mathias Agopian5b287a62011-05-16 18:58:55 -0700717 if ((ctx != EGL_NO_CONTEXT) && !_c.get()) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700718 // EGL_NO_CONTEXT is valid
Michael Chock0673e1e2012-06-21 12:53:17 -0700719 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700720 }
721
722 // these are the underlying implementation's object
723 EGLContext impl_ctx = EGL_NO_CONTEXT;
724 EGLSurface impl_draw = EGL_NO_SURFACE;
725 EGLSurface impl_read = EGL_NO_SURFACE;
726
727 // these are our objects structs passed in
728 egl_context_t * c = NULL;
729 egl_surface_t const * d = NULL;
730 egl_surface_t const * r = NULL;
731
732 // these are the current objects structs
733 egl_context_t * cur_c = get_context(getContext());
Jesse Hall47743382013-02-08 11:13:46 -0800734
Mathias Agopian518ec112011-05-13 16:21:08 -0700735 if (ctx != EGL_NO_CONTEXT) {
736 c = get_context(ctx);
737 impl_ctx = c->context;
738 } else {
739 // no context given, use the implementation of the current context
Michael Chock0673e1e2012-06-21 12:53:17 -0700740 if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE) {
741 // calling eglMakeCurrent( ..., !=0, !=0, EGL_NO_CONTEXT);
742 return setError(EGL_BAD_MATCH, EGL_FALSE);
743 }
Mathias Agopian518ec112011-05-13 16:21:08 -0700744 if (cur_c == NULL) {
745 // no current context
Mathias Agopian518ec112011-05-13 16:21:08 -0700746 // not an error, there is just no current context.
747 return EGL_TRUE;
748 }
749 }
750
751 // retrieve the underlying implementation's draw EGLSurface
752 if (draw != EGL_NO_SURFACE) {
Michael Chock0673e1e2012-06-21 12:53:17 -0700753 if (!_d.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700754 d = get_surface(draw);
Mathias Agopian518ec112011-05-13 16:21:08 -0700755 impl_draw = d->surface;
756 }
757
758 // retrieve the underlying implementation's read EGLSurface
759 if (read != EGL_NO_SURFACE) {
Michael Chock0673e1e2012-06-21 12:53:17 -0700760 if (!_r.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700761 r = get_surface(read);
Mathias Agopian518ec112011-05-13 16:21:08 -0700762 impl_read = r->surface;
763 }
764
Mathias Agopian518ec112011-05-13 16:21:08 -0700765
Jesse Hallb29e5e82012-04-04 16:53:42 -0700766 EGLBoolean result = dp->makeCurrent(c, cur_c,
Mathias Agopianfb87e542012-01-30 18:20:52 -0800767 draw, read, ctx,
768 impl_draw, impl_read, impl_ctx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700769
770 if (result == EGL_TRUE) {
Mathias Agopianfb87e542012-01-30 18:20:52 -0800771 if (c) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700772 setGLHooksThreadSpecific(c->cnx->hooks[c->version]);
773 egl_tls_t::setContext(ctx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700774 _c.acquire();
775 _r.acquire();
776 _d.acquire();
Mathias Agopian518ec112011-05-13 16:21:08 -0700777 } else {
778 setGLHooksThreadSpecific(&gHooksNoContext);
779 egl_tls_t::setContext(EGL_NO_CONTEXT);
780 }
Mathias Agopian5fecea72011-08-25 18:38:24 -0700781 } else {
Steve Blocke6f43dd2012-01-06 19:20:56 +0000782 // this will ALOGE the error
Mathias Agopian63108c32013-09-06 13:36:49 -0700783 egl_connection_t* const cnx = &gEGLImpl;
784 result = setError(cnx->egl.eglGetError(), EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700785 }
786 return result;
787}
788
789
790EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx,
791 EGLint attribute, EGLint *value)
792{
793 clearError();
794
Jesse Hallb29e5e82012-04-04 16:53:42 -0700795 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700796 if (!dp) return EGL_FALSE;
797
Jesse Hallb29e5e82012-04-04 16:53:42 -0700798 ContextRef _c(dp.get(), ctx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700799 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
800
Mathias Agopian518ec112011-05-13 16:21:08 -0700801 egl_context_t * const c = get_context(ctx);
Mathias Agopian7773c432012-02-13 20:06:08 -0800802 return c->cnx->egl.eglQueryContext(
803 dp->disp.dpy, c->context, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -0700804
Mathias Agopian518ec112011-05-13 16:21:08 -0700805}
806
807EGLContext eglGetCurrentContext(void)
808{
809 // could be called before eglInitialize(), but we wouldn't have a context
810 // then, and this function would correctly return EGL_NO_CONTEXT.
811
812 clearError();
813
814 EGLContext ctx = getContext();
815 return ctx;
816}
817
818EGLSurface eglGetCurrentSurface(EGLint readdraw)
819{
820 // could be called before eglInitialize(), but we wouldn't have a context
821 // then, and this function would correctly return EGL_NO_SURFACE.
822
823 clearError();
824
825 EGLContext ctx = getContext();
826 if (ctx) {
827 egl_context_t const * const c = get_context(ctx);
828 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
829 switch (readdraw) {
830 case EGL_READ: return c->read;
Jesse Hall47743382013-02-08 11:13:46 -0800831 case EGL_DRAW: return c->draw;
Mathias Agopian518ec112011-05-13 16:21:08 -0700832 default: return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
833 }
834 }
835 return EGL_NO_SURFACE;
836}
837
838EGLDisplay eglGetCurrentDisplay(void)
839{
840 // could be called before eglInitialize(), but we wouldn't have a context
841 // then, and this function would correctly return EGL_NO_DISPLAY.
842
843 clearError();
844
845 EGLContext ctx = getContext();
846 if (ctx) {
847 egl_context_t const * const c = get_context(ctx);
848 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
849 return c->dpy;
850 }
851 return EGL_NO_DISPLAY;
852}
853
854EGLBoolean eglWaitGL(void)
855{
Mathias Agopian518ec112011-05-13 16:21:08 -0700856 clearError();
857
Mathias Agopianada798b2012-02-13 17:09:30 -0800858 egl_connection_t* const cnx = &gEGLImpl;
859 if (!cnx->dso)
860 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
861
862 return cnx->egl.eglWaitGL();
Mathias Agopian518ec112011-05-13 16:21:08 -0700863}
864
865EGLBoolean eglWaitNative(EGLint engine)
866{
Mathias Agopian518ec112011-05-13 16:21:08 -0700867 clearError();
868
Mathias Agopianada798b2012-02-13 17:09:30 -0800869 egl_connection_t* const cnx = &gEGLImpl;
870 if (!cnx->dso)
871 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
872
873 return cnx->egl.eglWaitNative(engine);
Mathias Agopian518ec112011-05-13 16:21:08 -0700874}
875
876EGLint eglGetError(void)
877{
Mathias Agopianada798b2012-02-13 17:09:30 -0800878 EGLint err = EGL_SUCCESS;
879 egl_connection_t* const cnx = &gEGLImpl;
880 if (cnx->dso) {
881 err = cnx->egl.eglGetError();
Mathias Agopian518ec112011-05-13 16:21:08 -0700882 }
Mathias Agopianada798b2012-02-13 17:09:30 -0800883 if (err == EGL_SUCCESS) {
884 err = egl_tls_t::getError();
885 }
886 return err;
Mathias Agopian518ec112011-05-13 16:21:08 -0700887}
888
Michael Chockc0ec5e22014-01-27 08:14:33 -0800889static __eglMustCastToProperFunctionPointerType findBuiltinWrapper(
Jesse Hallc07b5202013-07-04 12:08:16 -0700890 const char* procname) {
891 const egl_connection_t* cnx = &gEGLImpl;
892 void* proc = NULL;
893
Michael Chockc0ec5e22014-01-27 08:14:33 -0800894 proc = dlsym(cnx->libEgl, procname);
895 if (proc) return (__eglMustCastToProperFunctionPointerType)proc;
896
Jesse Hallc07b5202013-07-04 12:08:16 -0700897 proc = dlsym(cnx->libGles2, procname);
898 if (proc) return (__eglMustCastToProperFunctionPointerType)proc;
899
900 proc = dlsym(cnx->libGles1, procname);
901 if (proc) return (__eglMustCastToProperFunctionPointerType)proc;
902
903 return NULL;
904}
905
Mathias Agopian518ec112011-05-13 16:21:08 -0700906__eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
907{
908 // eglGetProcAddress() could be the very first function called
909 // in which case we must make sure we've initialized ourselves, this
910 // happens the first time egl_get_display() is called.
911
912 clearError();
913
914 if (egl_init_drivers() == EGL_FALSE) {
915 setError(EGL_BAD_PARAMETER, NULL);
916 return NULL;
917 }
918
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700919 if (FILTER_EXTENSIONS(procname)) {
Jamie Gennisaca51c02011-11-03 17:42:43 -0700920 return NULL;
921 }
922
Mathias Agopian518ec112011-05-13 16:21:08 -0700923 __eglMustCastToProperFunctionPointerType addr;
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700924 addr = findProcAddress(procname, sExtensionMap, NELEM(sExtensionMap));
Mathias Agopian518ec112011-05-13 16:21:08 -0700925 if (addr) return addr;
926
Michael Chockc0ec5e22014-01-27 08:14:33 -0800927 addr = findBuiltinWrapper(procname);
Jesse Hallc07b5202013-07-04 12:08:16 -0700928 if (addr) return addr;
Jamie Gennisaca51c02011-11-03 17:42:43 -0700929
Mathias Agopian518ec112011-05-13 16:21:08 -0700930 // this protects accesses to sGLExtentionMap and sGLExtentionSlot
931 pthread_mutex_lock(&sExtensionMapMutex);
932
933 /*
934 * Since eglGetProcAddress() is not associated to anything, it needs
935 * to return a function pointer that "works" regardless of what
936 * the current context is.
937 *
938 * For this reason, we return a "forwarder", a small stub that takes
939 * care of calling the function associated with the context
940 * currently bound.
941 *
942 * We first look for extensions we've already resolved, if we're seeing
943 * this extension for the first time, we go through all our
944 * implementations and call eglGetProcAddress() and record the
945 * result in the appropriate implementation hooks and return the
946 * address of the forwarder corresponding to that hook set.
947 *
948 */
949
950 const String8 name(procname);
951 addr = sGLExtentionMap.valueFor(name);
952 const int slot = sGLExtentionSlot;
953
Steve Blocke6f43dd2012-01-06 19:20:56 +0000954 ALOGE_IF(slot >= MAX_NUMBER_OF_GL_EXTENSIONS,
Mathias Agopian518ec112011-05-13 16:21:08 -0700955 "no more slots for eglGetProcAddress(\"%s\")",
956 procname);
957
958 if (!addr && (slot < MAX_NUMBER_OF_GL_EXTENSIONS)) {
959 bool found = false;
Mathias Agopianada798b2012-02-13 17:09:30 -0800960
961 egl_connection_t* const cnx = &gEGLImpl;
962 if (cnx->dso && cnx->egl.eglGetProcAddress) {
Mathias Agopianada798b2012-02-13 17:09:30 -0800963 // Extensions are independent of the bound context
luliuhui69d10072012-08-30 11:15:36 +0800964 addr =
Mathias Agopian7773c432012-02-13 20:06:08 -0800965 cnx->hooks[egl_connection_t::GLESv1_INDEX]->ext.extensions[slot] =
966 cnx->hooks[egl_connection_t::GLESv2_INDEX]->ext.extensions[slot] =
Mathias Agopianada798b2012-02-13 17:09:30 -0800967 cnx->egl.eglGetProcAddress(procname);
luliuhui69d10072012-08-30 11:15:36 +0800968 if (addr) found = true;
Mathias Agopian518ec112011-05-13 16:21:08 -0700969 }
Mathias Agopianada798b2012-02-13 17:09:30 -0800970
Mathias Agopian518ec112011-05-13 16:21:08 -0700971 if (found) {
972 addr = gExtensionForwarders[slot];
Mathias Agopian518ec112011-05-13 16:21:08 -0700973 sGLExtentionMap.add(name, addr);
974 sGLExtentionSlot++;
975 }
976 }
977
978 pthread_mutex_unlock(&sExtensionMapMutex);
979 return addr;
980}
981
Jamie Gennis28ef8d72012-04-05 20:34:54 -0700982class FrameCompletionThread : public Thread {
983public:
984
985 static void queueSync(EGLSyncKHR sync) {
986 static sp<FrameCompletionThread> thread(new FrameCompletionThread);
987 static bool running = false;
988 if (!running) {
989 thread->run("GPUFrameCompletion");
990 running = true;
991 }
992 {
993 Mutex::Autolock lock(thread->mMutex);
994 ScopedTrace st(ATRACE_TAG, String8::format("kicked off frame %d",
995 thread->mFramesQueued).string());
996 thread->mQueue.push_back(sync);
997 thread->mCondition.signal();
998 thread->mFramesQueued++;
999 ATRACE_INT("GPU Frames Outstanding", thread->mQueue.size());
1000 }
1001 }
1002
1003private:
1004 FrameCompletionThread() : mFramesQueued(0), mFramesCompleted(0) {}
1005
1006 virtual bool threadLoop() {
1007 EGLSyncKHR sync;
1008 uint32_t frameNum;
1009 {
1010 Mutex::Autolock lock(mMutex);
1011 while (mQueue.isEmpty()) {
1012 mCondition.wait(mMutex);
1013 }
1014 sync = mQueue[0];
1015 frameNum = mFramesCompleted;
1016 }
1017 EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
1018 {
1019 ScopedTrace st(ATRACE_TAG, String8::format("waiting for frame %d",
1020 frameNum).string());
1021 EGLint result = eglClientWaitSyncKHR(dpy, sync, 0, EGL_FOREVER_KHR);
1022 if (result == EGL_FALSE) {
1023 ALOGE("FrameCompletion: error waiting for fence: %#x", eglGetError());
1024 } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
1025 ALOGE("FrameCompletion: timeout waiting for fence");
1026 }
1027 eglDestroySyncKHR(dpy, sync);
1028 }
1029 {
1030 Mutex::Autolock lock(mMutex);
1031 mQueue.removeAt(0);
1032 mFramesCompleted++;
1033 ATRACE_INT("GPU Frames Outstanding", mQueue.size());
1034 }
1035 return true;
1036 }
1037
1038 uint32_t mFramesQueued;
1039 uint32_t mFramesCompleted;
1040 Vector<EGLSyncKHR> mQueue;
1041 Condition mCondition;
1042 Mutex mMutex;
1043};
1044
Dan Stozaa894d082015-02-19 15:27:36 -08001045EGLBoolean eglSwapBuffersWithDamageKHR(EGLDisplay dpy, EGLSurface draw,
1046 EGLint *rects, EGLint n_rects)
Mathias Agopian518ec112011-05-13 16:21:08 -07001047{
Jamie Gennis1c8e95c2012-02-23 19:27:23 -08001048 ATRACE_CALL();
Mathias Agopian518ec112011-05-13 16:21:08 -07001049 clearError();
1050
Jesse Hallb29e5e82012-04-04 16:53:42 -07001051 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001052 if (!dp) return EGL_FALSE;
1053
Jesse Hallb29e5e82012-04-04 16:53:42 -07001054 SurfaceRef _s(dp.get(), draw);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001055 if (!_s.get())
1056 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001057
Mathias Agopian518ec112011-05-13 16:21:08 -07001058 egl_surface_t const * const s = get_surface(draw);
Mathias Agopian7db993a2012-03-25 00:49:46 -07001059
Mathias Agopianed6d08b2013-04-16 16:39:46 -07001060 if (CC_UNLIKELY(dp->traceGpuCompletion)) {
1061 EGLSyncKHR sync = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, NULL);
1062 if (sync != EGL_NO_SYNC_KHR) {
1063 FrameCompletionThread::queueSync(sync);
1064 }
1065 }
1066
Mathias Agopian7db993a2012-03-25 00:49:46 -07001067 if (CC_UNLIKELY(dp->finishOnSwap)) {
1068 uint32_t pixel;
1069 egl_context_t * const c = get_context( egl_tls_t::getContext() );
1070 if (c) {
1071 // glReadPixels() ensures that the frame is complete
1072 s->cnx->hooks[c->version]->gl.glReadPixels(0,0,1,1,
1073 GL_RGBA,GL_UNSIGNED_BYTE,&pixel);
1074 }
1075 }
1076
Dan Stozaa894d082015-02-19 15:27:36 -08001077 if (n_rects == 0) {
1078 return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface);
1079 }
1080
1081 Vector<android_native_rect_t> androidRects;
1082 for (int r = 0; r < n_rects; ++r) {
1083 int offset = r * 4;
1084 int x = rects[offset];
1085 int y = rects[offset + 1];
1086 int width = rects[offset + 2];
1087 int height = rects[offset + 3];
1088 android_native_rect_t androidRect;
1089 androidRect.left = x;
1090 androidRect.top = y + height;
1091 androidRect.right = x + width;
1092 androidRect.bottom = y;
1093 androidRects.push_back(androidRect);
1094 }
1095 native_window_set_surface_damage(s->win.get(), androidRects.array(),
1096 androidRects.size());
1097
1098 if (s->cnx->egl.eglSwapBuffersWithDamageKHR) {
1099 return s->cnx->egl.eglSwapBuffersWithDamageKHR(dp->disp.dpy, s->surface,
1100 rects, n_rects);
1101 } else {
1102 return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface);
1103 }
1104}
1105
1106EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
1107{
1108 return eglSwapBuffersWithDamageKHR(dpy, surface, NULL, 0);
Mathias Agopian518ec112011-05-13 16:21:08 -07001109}
1110
1111EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface,
1112 NativePixmapType target)
1113{
1114 clearError();
1115
Jesse Hallb29e5e82012-04-04 16:53:42 -07001116 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001117 if (!dp) return EGL_FALSE;
1118
Jesse Hallb29e5e82012-04-04 16:53:42 -07001119 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001120 if (!_s.get())
1121 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001122
Mathias Agopian518ec112011-05-13 16:21:08 -07001123 egl_surface_t const * const s = get_surface(surface);
Mathias Agopianada798b2012-02-13 17:09:30 -08001124 return s->cnx->egl.eglCopyBuffers(dp->disp.dpy, s->surface, target);
Mathias Agopian518ec112011-05-13 16:21:08 -07001125}
1126
1127const char* eglQueryString(EGLDisplay dpy, EGLint name)
1128{
1129 clearError();
1130
Jesse Hallb29e5e82012-04-04 16:53:42 -07001131 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001132 if (!dp) return (const char *) NULL;
1133
1134 switch (name) {
1135 case EGL_VENDOR:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001136 return dp->getVendorString();
Mathias Agopian518ec112011-05-13 16:21:08 -07001137 case EGL_VERSION:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001138 return dp->getVersionString();
Mathias Agopian518ec112011-05-13 16:21:08 -07001139 case EGL_EXTENSIONS:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001140 return dp->getExtensionString();
Mathias Agopian518ec112011-05-13 16:21:08 -07001141 case EGL_CLIENT_APIS:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001142 return dp->getClientApiString();
Mathias Agopian518ec112011-05-13 16:21:08 -07001143 }
1144 return setError(EGL_BAD_PARAMETER, (const char *)0);
1145}
1146
Mathias Agopianca088332013-03-28 17:44:13 -07001147EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name)
1148{
1149 clearError();
1150
1151 const egl_display_ptr dp = validate_display(dpy);
1152 if (!dp) return (const char *) NULL;
1153
1154 switch (name) {
1155 case EGL_VENDOR:
1156 return dp->disp.queryString.vendor;
1157 case EGL_VERSION:
1158 return dp->disp.queryString.version;
1159 case EGL_EXTENSIONS:
1160 return dp->disp.queryString.extensions;
1161 case EGL_CLIENT_APIS:
1162 return dp->disp.queryString.clientApi;
1163 }
1164 return setError(EGL_BAD_PARAMETER, (const char *)0);
1165}
Mathias Agopian518ec112011-05-13 16:21:08 -07001166
1167// ----------------------------------------------------------------------------
1168// EGL 1.1
1169// ----------------------------------------------------------------------------
1170
1171EGLBoolean eglSurfaceAttrib(
1172 EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
1173{
1174 clearError();
1175
Jesse Hallb29e5e82012-04-04 16:53:42 -07001176 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001177 if (!dp) return EGL_FALSE;
1178
Jesse Hallb29e5e82012-04-04 16:53:42 -07001179 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001180 if (!_s.get())
1181 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001182
Mathias Agopian518ec112011-05-13 16:21:08 -07001183 egl_surface_t const * const s = get_surface(surface);
Pablo Ceballosccdfd602015-10-07 15:05:45 -07001184
Pablo Ceballos02b05da2016-02-02 17:53:18 -08001185 if (attribute == EGL_FRONT_BUFFER_AUTO_REFRESH_ANDROID) {
Pablo Ceballosf051ade2016-03-15 18:27:20 -07001186 int err = native_window_set_auto_refresh(s->win.get(),
1187 value ? true : false);
1188 return (err == NO_ERROR) ? EGL_TRUE :
1189 setError(EGL_BAD_SURFACE, EGL_FALSE);
Pablo Ceballosccdfd602015-10-07 15:05:45 -07001190 }
1191
Mathias Agopian518ec112011-05-13 16:21:08 -07001192 if (s->cnx->egl.eglSurfaceAttrib) {
1193 return s->cnx->egl.eglSurfaceAttrib(
Mathias Agopianada798b2012-02-13 17:09:30 -08001194 dp->disp.dpy, s->surface, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -07001195 }
1196 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1197}
1198
1199EGLBoolean eglBindTexImage(
1200 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1201{
1202 clearError();
1203
Jesse Hallb29e5e82012-04-04 16:53:42 -07001204 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001205 if (!dp) return EGL_FALSE;
1206
Jesse Hallb29e5e82012-04-04 16:53:42 -07001207 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001208 if (!_s.get())
1209 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001210
Mathias Agopian518ec112011-05-13 16:21:08 -07001211 egl_surface_t const * const s = get_surface(surface);
1212 if (s->cnx->egl.eglBindTexImage) {
1213 return s->cnx->egl.eglBindTexImage(
Mathias Agopianada798b2012-02-13 17:09:30 -08001214 dp->disp.dpy, s->surface, buffer);
Mathias Agopian518ec112011-05-13 16:21:08 -07001215 }
1216 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1217}
1218
1219EGLBoolean eglReleaseTexImage(
1220 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1221{
1222 clearError();
1223
Jesse Hallb29e5e82012-04-04 16:53:42 -07001224 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001225 if (!dp) return EGL_FALSE;
1226
Jesse Hallb29e5e82012-04-04 16:53:42 -07001227 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001228 if (!_s.get())
1229 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001230
Mathias Agopian518ec112011-05-13 16:21:08 -07001231 egl_surface_t const * const s = get_surface(surface);
1232 if (s->cnx->egl.eglReleaseTexImage) {
1233 return s->cnx->egl.eglReleaseTexImage(
Mathias Agopianada798b2012-02-13 17:09:30 -08001234 dp->disp.dpy, s->surface, buffer);
Mathias Agopian518ec112011-05-13 16:21:08 -07001235 }
1236 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1237}
1238
1239EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
1240{
1241 clearError();
1242
Jesse Hallb29e5e82012-04-04 16:53:42 -07001243 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001244 if (!dp) return EGL_FALSE;
1245
1246 EGLBoolean res = EGL_TRUE;
Mathias Agopianada798b2012-02-13 17:09:30 -08001247 egl_connection_t* const cnx = &gEGLImpl;
1248 if (cnx->dso && cnx->egl.eglSwapInterval) {
1249 res = cnx->egl.eglSwapInterval(dp->disp.dpy, interval);
Mathias Agopian518ec112011-05-13 16:21:08 -07001250 }
Mathias Agopianada798b2012-02-13 17:09:30 -08001251
Mathias Agopian518ec112011-05-13 16:21:08 -07001252 return res;
1253}
1254
1255
1256// ----------------------------------------------------------------------------
1257// EGL 1.2
1258// ----------------------------------------------------------------------------
1259
1260EGLBoolean eglWaitClient(void)
1261{
1262 clearError();
1263
Mathias Agopianada798b2012-02-13 17:09:30 -08001264 egl_connection_t* const cnx = &gEGLImpl;
1265 if (!cnx->dso)
1266 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1267
1268 EGLBoolean res;
1269 if (cnx->egl.eglWaitClient) {
1270 res = cnx->egl.eglWaitClient();
1271 } else {
1272 res = cnx->egl.eglWaitGL();
Mathias Agopian518ec112011-05-13 16:21:08 -07001273 }
1274 return res;
1275}
1276
1277EGLBoolean eglBindAPI(EGLenum api)
1278{
1279 clearError();
1280
1281 if (egl_init_drivers() == EGL_FALSE) {
1282 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1283 }
1284
1285 // bind this API on all EGLs
1286 EGLBoolean res = EGL_TRUE;
Mathias Agopianada798b2012-02-13 17:09:30 -08001287 egl_connection_t* const cnx = &gEGLImpl;
1288 if (cnx->dso && cnx->egl.eglBindAPI) {
1289 res = cnx->egl.eglBindAPI(api);
Mathias Agopian518ec112011-05-13 16:21:08 -07001290 }
1291 return res;
1292}
1293
1294EGLenum eglQueryAPI(void)
1295{
1296 clearError();
1297
1298 if (egl_init_drivers() == EGL_FALSE) {
1299 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1300 }
1301
Mathias Agopianada798b2012-02-13 17:09:30 -08001302 egl_connection_t* const cnx = &gEGLImpl;
1303 if (cnx->dso && cnx->egl.eglQueryAPI) {
1304 return cnx->egl.eglQueryAPI();
Mathias Agopian518ec112011-05-13 16:21:08 -07001305 }
Mathias Agopianada798b2012-02-13 17:09:30 -08001306
Mathias Agopian518ec112011-05-13 16:21:08 -07001307 // or, it can only be OpenGL ES
1308 return EGL_OPENGL_ES_API;
1309}
1310
1311EGLBoolean eglReleaseThread(void)
1312{
1313 clearError();
1314
Mathias Agopianada798b2012-02-13 17:09:30 -08001315 egl_connection_t* const cnx = &gEGLImpl;
1316 if (cnx->dso && cnx->egl.eglReleaseThread) {
1317 cnx->egl.eglReleaseThread();
Mathias Agopian518ec112011-05-13 16:21:08 -07001318 }
Sai Kiran Korwar3ac517a2014-01-31 21:15:07 +05301319
1320 // If there is context bound to the thread, release it
1321 egl_display_t::loseCurrent(get_context(getContext()));
1322
Mathias Agopian518ec112011-05-13 16:21:08 -07001323 egl_tls_t::clearTLS();
Mathias Agopian518ec112011-05-13 16:21:08 -07001324 return EGL_TRUE;
1325}
1326
1327EGLSurface eglCreatePbufferFromClientBuffer(
1328 EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer,
1329 EGLConfig config, const EGLint *attrib_list)
1330{
1331 clearError();
1332
Jesse Hallb29e5e82012-04-04 16:53:42 -07001333 egl_connection_t* cnx = NULL;
1334 const egl_display_ptr dp = validate_display_connection(dpy, cnx);
1335 if (!dp) return EGL_FALSE;
Mathias Agopian518ec112011-05-13 16:21:08 -07001336 if (cnx->egl.eglCreatePbufferFromClientBuffer) {
1337 return cnx->egl.eglCreatePbufferFromClientBuffer(
Mathias Agopian7773c432012-02-13 20:06:08 -08001338 dp->disp.dpy, buftype, buffer, config, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001339 }
1340 return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE);
1341}
1342
1343// ----------------------------------------------------------------------------
1344// EGL_EGLEXT_VERSION 3
1345// ----------------------------------------------------------------------------
1346
1347EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface,
1348 const EGLint *attrib_list)
1349{
1350 clearError();
1351
Jesse Hallb29e5e82012-04-04 16:53:42 -07001352 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001353 if (!dp) return EGL_FALSE;
1354
Jesse Hallb29e5e82012-04-04 16:53:42 -07001355 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001356 if (!_s.get())
1357 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001358
1359 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian518ec112011-05-13 16:21:08 -07001360 if (s->cnx->egl.eglLockSurfaceKHR) {
1361 return s->cnx->egl.eglLockSurfaceKHR(
Mathias Agopianada798b2012-02-13 17:09:30 -08001362 dp->disp.dpy, s->surface, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001363 }
1364 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1365}
1366
1367EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface)
1368{
1369 clearError();
1370
Jesse Hallb29e5e82012-04-04 16:53:42 -07001371 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001372 if (!dp) return EGL_FALSE;
1373
Jesse Hallb29e5e82012-04-04 16:53:42 -07001374 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001375 if (!_s.get())
1376 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001377
1378 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian518ec112011-05-13 16:21:08 -07001379 if (s->cnx->egl.eglUnlockSurfaceKHR) {
Mathias Agopianada798b2012-02-13 17:09:30 -08001380 return s->cnx->egl.eglUnlockSurfaceKHR(dp->disp.dpy, s->surface);
Mathias Agopian518ec112011-05-13 16:21:08 -07001381 }
1382 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1383}
1384
1385EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
1386 EGLClientBuffer buffer, const EGLint *attrib_list)
1387{
1388 clearError();
1389
Jesse Hallb29e5e82012-04-04 16:53:42 -07001390 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001391 if (!dp) return EGL_NO_IMAGE_KHR;
1392
Jesse Hallb29e5e82012-04-04 16:53:42 -07001393 ContextRef _c(dp.get(), ctx);
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001394 egl_context_t * const c = _c.get();
Mathias Agopian518ec112011-05-13 16:21:08 -07001395
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001396 EGLImageKHR result = EGL_NO_IMAGE_KHR;
1397 egl_connection_t* const cnx = &gEGLImpl;
1398 if (cnx->dso && cnx->egl.eglCreateImageKHR) {
1399 result = cnx->egl.eglCreateImageKHR(
1400 dp->disp.dpy,
1401 c ? c->context : EGL_NO_CONTEXT,
1402 target, buffer, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001403 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001404 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001405}
1406
1407EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
1408{
1409 clearError();
1410
Jesse Hallb29e5e82012-04-04 16:53:42 -07001411 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001412 if (!dp) return EGL_FALSE;
1413
Steven Holte646a5c52012-06-04 20:02:11 -07001414 EGLBoolean result = EGL_FALSE;
Mathias Agopianada798b2012-02-13 17:09:30 -08001415 egl_connection_t* const cnx = &gEGLImpl;
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001416 if (cnx->dso && cnx->egl.eglDestroyImageKHR) {
Steven Holte646a5c52012-06-04 20:02:11 -07001417 result = cnx->egl.eglDestroyImageKHR(dp->disp.dpy, img);
Mathias Agopian518ec112011-05-13 16:21:08 -07001418 }
Steven Holte646a5c52012-06-04 20:02:11 -07001419 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001420}
1421
1422// ----------------------------------------------------------------------------
1423// EGL_EGLEXT_VERSION 5
1424// ----------------------------------------------------------------------------
1425
1426
1427EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
1428{
1429 clearError();
1430
Jesse Hallb29e5e82012-04-04 16:53:42 -07001431 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001432 if (!dp) return EGL_NO_SYNC_KHR;
1433
Mathias Agopian518ec112011-05-13 16:21:08 -07001434 EGLSyncKHR result = EGL_NO_SYNC_KHR;
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001435 egl_connection_t* const cnx = &gEGLImpl;
1436 if (cnx->dso && cnx->egl.eglCreateSyncKHR) {
1437 result = cnx->egl.eglCreateSyncKHR(dp->disp.dpy, type, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001438 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001439 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001440}
1441
1442EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
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_FALSE;
1448
Mathias Agopian518ec112011-05-13 16:21:08 -07001449 EGLBoolean result = EGL_FALSE;
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001450 egl_connection_t* const cnx = &gEGLImpl;
1451 if (cnx->dso && cnx->egl.eglDestroySyncKHR) {
1452 result = cnx->egl.eglDestroySyncKHR(dp->disp.dpy, sync);
Mathias Agopian518ec112011-05-13 16:21:08 -07001453 }
1454 return result;
1455}
1456
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -07001457EGLBoolean eglSignalSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode) {
1458 clearError();
1459
1460 const egl_display_ptr dp = validate_display(dpy);
1461 if (!dp) return EGL_FALSE;
1462
1463 EGLBoolean result = EGL_FALSE;
1464 egl_connection_t* const cnx = &gEGLImpl;
1465 if (cnx->dso && cnx->egl.eglSignalSyncKHR) {
1466 result = cnx->egl.eglSignalSyncKHR(
1467 dp->disp.dpy, sync, mode);
1468 }
1469 return result;
1470}
1471
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001472EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync,
1473 EGLint flags, EGLTimeKHR timeout)
Mathias Agopian518ec112011-05-13 16:21:08 -07001474{
1475 clearError();
1476
Jesse Hallb29e5e82012-04-04 16:53:42 -07001477 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001478 if (!dp) return EGL_FALSE;
1479
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001480 EGLBoolean result = EGL_FALSE;
1481 egl_connection_t* const cnx = &gEGLImpl;
1482 if (cnx->dso && cnx->egl.eglClientWaitSyncKHR) {
1483 result = cnx->egl.eglClientWaitSyncKHR(
1484 dp->disp.dpy, sync, flags, timeout);
Mathias Agopian518ec112011-05-13 16:21:08 -07001485 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001486 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001487}
1488
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001489EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync,
1490 EGLint attribute, EGLint *value)
Mathias Agopian518ec112011-05-13 16:21:08 -07001491{
1492 clearError();
1493
Jesse Hallb29e5e82012-04-04 16:53:42 -07001494 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001495 if (!dp) return EGL_FALSE;
1496
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001497 EGLBoolean result = EGL_FALSE;
1498 egl_connection_t* const cnx = &gEGLImpl;
1499 if (cnx->dso && cnx->egl.eglGetSyncAttribKHR) {
1500 result = cnx->egl.eglGetSyncAttribKHR(
1501 dp->disp.dpy, sync, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -07001502 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001503 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001504}
1505
Season Li000d88f2015-07-01 11:39:40 -07001506EGLStreamKHR eglCreateStreamKHR(EGLDisplay dpy, const EGLint *attrib_list)
1507{
1508 clearError();
1509
1510 const egl_display_ptr dp = validate_display(dpy);
1511 if (!dp) return EGL_NO_STREAM_KHR;
1512
1513 EGLStreamKHR result = EGL_NO_STREAM_KHR;
1514 egl_connection_t* const cnx = &gEGLImpl;
1515 if (cnx->dso && cnx->egl.eglCreateStreamKHR) {
1516 result = cnx->egl.eglCreateStreamKHR(
1517 dp->disp.dpy, attrib_list);
1518 }
1519 return result;
1520}
1521
1522EGLBoolean eglDestroyStreamKHR(EGLDisplay dpy, EGLStreamKHR stream)
1523{
1524 clearError();
1525
1526 const egl_display_ptr dp = validate_display(dpy);
1527 if (!dp) return EGL_FALSE;
1528
1529 EGLBoolean result = EGL_FALSE;
1530 egl_connection_t* const cnx = &gEGLImpl;
1531 if (cnx->dso && cnx->egl.eglDestroyStreamKHR) {
1532 result = cnx->egl.eglDestroyStreamKHR(
1533 dp->disp.dpy, stream);
1534 }
1535 return result;
1536}
1537
1538EGLBoolean eglStreamAttribKHR(EGLDisplay dpy, EGLStreamKHR stream,
1539 EGLenum attribute, EGLint value)
1540{
1541 clearError();
1542
1543 const egl_display_ptr dp = validate_display(dpy);
1544 if (!dp) return EGL_FALSE;
1545
1546 EGLBoolean result = EGL_FALSE;
1547 egl_connection_t* const cnx = &gEGLImpl;
1548 if (cnx->dso && cnx->egl.eglStreamAttribKHR) {
1549 result = cnx->egl.eglStreamAttribKHR(
1550 dp->disp.dpy, stream, attribute, value);
1551 }
1552 return result;
1553}
1554
1555EGLBoolean eglQueryStreamKHR(EGLDisplay dpy, EGLStreamKHR stream,
1556 EGLenum attribute, EGLint *value)
1557{
1558 clearError();
1559
1560 const egl_display_ptr dp = validate_display(dpy);
1561 if (!dp) return EGL_FALSE;
1562
1563 EGLBoolean result = EGL_FALSE;
1564 egl_connection_t* const cnx = &gEGLImpl;
1565 if (cnx->dso && cnx->egl.eglQueryStreamKHR) {
1566 result = cnx->egl.eglQueryStreamKHR(
1567 dp->disp.dpy, stream, attribute, value);
1568 }
1569 return result;
1570}
1571
1572EGLBoolean eglQueryStreamu64KHR(EGLDisplay dpy, EGLStreamKHR stream,
1573 EGLenum attribute, EGLuint64KHR *value)
1574{
1575 clearError();
1576
1577 const egl_display_ptr dp = validate_display(dpy);
1578 if (!dp) return EGL_FALSE;
1579
1580 EGLBoolean result = EGL_FALSE;
1581 egl_connection_t* const cnx = &gEGLImpl;
1582 if (cnx->dso && cnx->egl.eglQueryStreamu64KHR) {
1583 result = cnx->egl.eglQueryStreamu64KHR(
1584 dp->disp.dpy, stream, attribute, value);
1585 }
1586 return result;
1587}
1588
1589EGLBoolean eglQueryStreamTimeKHR(EGLDisplay dpy, EGLStreamKHR stream,
1590 EGLenum attribute, EGLTimeKHR *value)
1591{
1592 clearError();
1593
1594 const egl_display_ptr dp = validate_display(dpy);
1595 if (!dp) return EGL_FALSE;
1596
1597 EGLBoolean result = EGL_FALSE;
1598 egl_connection_t* const cnx = &gEGLImpl;
1599 if (cnx->dso && cnx->egl.eglQueryStreamTimeKHR) {
1600 result = cnx->egl.eglQueryStreamTimeKHR(
1601 dp->disp.dpy, stream, attribute, value);
1602 }
1603 return result;
1604}
1605
1606EGLSurface eglCreateStreamProducerSurfaceKHR(EGLDisplay dpy, EGLConfig config,
1607 EGLStreamKHR stream, const EGLint *attrib_list)
1608{
1609 clearError();
1610
1611 egl_display_ptr dp = validate_display(dpy);
1612 if (!dp) return EGL_NO_SURFACE;
1613
1614 egl_connection_t* const cnx = &gEGLImpl;
1615 if (cnx->dso && cnx->egl.eglCreateStreamProducerSurfaceKHR) {
1616 EGLSurface surface = cnx->egl.eglCreateStreamProducerSurfaceKHR(
1617 dp->disp.dpy, config, stream, attrib_list);
1618 if (surface != EGL_NO_SURFACE) {
1619 egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL,
1620 surface, cnx);
1621 return s;
1622 }
1623 }
1624 return EGL_NO_SURFACE;
1625}
1626
1627EGLBoolean eglStreamConsumerGLTextureExternalKHR(EGLDisplay dpy,
1628 EGLStreamKHR stream)
1629{
1630 clearError();
1631
1632 const egl_display_ptr dp = validate_display(dpy);
1633 if (!dp) return EGL_FALSE;
1634
1635 EGLBoolean result = EGL_FALSE;
1636 egl_connection_t* const cnx = &gEGLImpl;
1637 if (cnx->dso && cnx->egl.eglStreamConsumerGLTextureExternalKHR) {
1638 result = cnx->egl.eglStreamConsumerGLTextureExternalKHR(
1639 dp->disp.dpy, stream);
1640 }
1641 return result;
1642}
1643
1644EGLBoolean eglStreamConsumerAcquireKHR(EGLDisplay dpy,
1645 EGLStreamKHR stream)
1646{
1647 clearError();
1648
1649 const egl_display_ptr dp = validate_display(dpy);
1650 if (!dp) return EGL_FALSE;
1651
1652 EGLBoolean result = EGL_FALSE;
1653 egl_connection_t* const cnx = &gEGLImpl;
1654 if (cnx->dso && cnx->egl.eglStreamConsumerAcquireKHR) {
1655 result = cnx->egl.eglStreamConsumerAcquireKHR(
1656 dp->disp.dpy, stream);
1657 }
1658 return result;
1659}
1660
1661EGLBoolean eglStreamConsumerReleaseKHR(EGLDisplay dpy,
1662 EGLStreamKHR stream)
1663{
1664 clearError();
1665
1666 const egl_display_ptr dp = validate_display(dpy);
1667 if (!dp) return EGL_FALSE;
1668
1669 EGLBoolean result = EGL_FALSE;
1670 egl_connection_t* const cnx = &gEGLImpl;
1671 if (cnx->dso && cnx->egl.eglStreamConsumerReleaseKHR) {
1672 result = cnx->egl.eglStreamConsumerReleaseKHR(
1673 dp->disp.dpy, stream);
1674 }
1675 return result;
1676}
1677
1678EGLNativeFileDescriptorKHR eglGetStreamFileDescriptorKHR(
1679 EGLDisplay dpy, EGLStreamKHR stream)
1680{
1681 clearError();
1682
1683 const egl_display_ptr dp = validate_display(dpy);
1684 if (!dp) return EGL_NO_FILE_DESCRIPTOR_KHR;
1685
1686 EGLNativeFileDescriptorKHR result = EGL_NO_FILE_DESCRIPTOR_KHR;
1687 egl_connection_t* const cnx = &gEGLImpl;
1688 if (cnx->dso && cnx->egl.eglGetStreamFileDescriptorKHR) {
1689 result = cnx->egl.eglGetStreamFileDescriptorKHR(
1690 dp->disp.dpy, stream);
1691 }
1692 return result;
1693}
1694
1695EGLStreamKHR eglCreateStreamFromFileDescriptorKHR(
1696 EGLDisplay dpy, EGLNativeFileDescriptorKHR file_descriptor)
1697{
1698 clearError();
1699
1700 const egl_display_ptr dp = validate_display(dpy);
1701 if (!dp) return EGL_NO_STREAM_KHR;
1702
1703 EGLStreamKHR result = EGL_NO_STREAM_KHR;
1704 egl_connection_t* const cnx = &gEGLImpl;
1705 if (cnx->dso && cnx->egl.eglCreateStreamFromFileDescriptorKHR) {
1706 result = cnx->egl.eglCreateStreamFromFileDescriptorKHR(
1707 dp->disp.dpy, file_descriptor);
1708 }
1709 return result;
1710}
1711
Mathias Agopian518ec112011-05-13 16:21:08 -07001712// ----------------------------------------------------------------------------
Mathias Agopian2bb71682013-03-27 17:32:41 -07001713// EGL_EGLEXT_VERSION 15
1714// ----------------------------------------------------------------------------
1715
1716EGLint eglWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags) {
1717 clearError();
1718 const egl_display_ptr dp = validate_display(dpy);
1719 if (!dp) return EGL_FALSE;
1720 EGLint result = EGL_FALSE;
1721 egl_connection_t* const cnx = &gEGLImpl;
1722 if (cnx->dso && cnx->egl.eglWaitSyncKHR) {
1723 result = cnx->egl.eglWaitSyncKHR(dp->disp.dpy, sync, flags);
1724 }
1725 return result;
1726}
1727
1728// ----------------------------------------------------------------------------
Mathias Agopian518ec112011-05-13 16:21:08 -07001729// ANDROID extensions
1730// ----------------------------------------------------------------------------
1731
Jamie Gennis331841b2012-09-06 14:52:00 -07001732EGLint eglDupNativeFenceFDANDROID(EGLDisplay dpy, EGLSyncKHR sync)
1733{
1734 clearError();
1735
1736 const egl_display_ptr dp = validate_display(dpy);
1737 if (!dp) return EGL_NO_NATIVE_FENCE_FD_ANDROID;
1738
1739 EGLint result = EGL_NO_NATIVE_FENCE_FD_ANDROID;
1740 egl_connection_t* const cnx = &gEGLImpl;
1741 if (cnx->dso && cnx->egl.eglDupNativeFenceFDANDROID) {
1742 result = cnx->egl.eglDupNativeFenceFDANDROID(dp->disp.dpy, sync);
1743 }
1744 return result;
1745}
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001746
Andy McFadden72841452013-03-01 16:25:32 -08001747EGLBoolean eglPresentationTimeANDROID(EGLDisplay dpy, EGLSurface surface,
1748 EGLnsecsANDROID time)
1749{
1750 clearError();
1751
1752 const egl_display_ptr dp = validate_display(dpy);
1753 if (!dp) {
1754 return EGL_FALSE;
1755 }
1756
1757 SurfaceRef _s(dp.get(), surface);
1758 if (!_s.get()) {
1759 setError(EGL_BAD_SURFACE, EGL_FALSE);
1760 return EGL_FALSE;
1761 }
1762
1763 egl_surface_t const * const s = get_surface(surface);
1764 native_window_set_buffers_timestamp(s->win.get(), time);
1765
1766 return EGL_TRUE;
1767}
1768
Craig Donner05249fc2016-01-15 19:33:55 -08001769EGLClientBuffer eglCreateNativeClientBufferANDROID(const EGLint *attrib_list)
1770{
1771 clearError();
1772
1773 int usage = 0;
1774 uint32_t width = 0;
1775 uint32_t height = 0;
1776 uint32_t format = 0;
1777 uint32_t red_size = 0;
1778 uint32_t green_size = 0;
1779 uint32_t blue_size = 0;
1780 uint32_t alpha_size = 0;
1781
Craig Donnerb40504a2016-06-03 17:54:25 -07001782#define GET_NONNEGATIVE_VALUE(case_name, target) \
Craig Donner05249fc2016-01-15 19:33:55 -08001783 case case_name: \
Craig Donnerb40504a2016-06-03 17:54:25 -07001784 if (value >= 0) { \
Craig Donner05249fc2016-01-15 19:33:55 -08001785 target = value; \
1786 } else { \
1787 return setError(EGL_BAD_PARAMETER, (EGLClientBuffer)0); \
1788 } \
1789 break
1790
1791 if (attrib_list) {
1792 while (*attrib_list != EGL_NONE) {
1793 GLint attr = *attrib_list++;
1794 GLint value = *attrib_list++;
1795 switch (attr) {
Craig Donnerb40504a2016-06-03 17:54:25 -07001796 GET_NONNEGATIVE_VALUE(EGL_WIDTH, width);
1797 GET_NONNEGATIVE_VALUE(EGL_HEIGHT, height);
1798 GET_NONNEGATIVE_VALUE(EGL_RED_SIZE, red_size);
1799 GET_NONNEGATIVE_VALUE(EGL_GREEN_SIZE, green_size);
1800 GET_NONNEGATIVE_VALUE(EGL_BLUE_SIZE, blue_size);
1801 GET_NONNEGATIVE_VALUE(EGL_ALPHA_SIZE, alpha_size);
Craig Donner05249fc2016-01-15 19:33:55 -08001802 case EGL_NATIVE_BUFFER_USAGE_ANDROID:
1803 if (value & EGL_NATIVE_BUFFER_USAGE_PROTECTED_BIT_ANDROID) {
1804 usage |= GRALLOC_USAGE_PROTECTED;
Craig Donner05249fc2016-01-15 19:33:55 -08001805 }
Craig Donner8cfae6d2016-04-12 16:54:03 -07001806 if (value & EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_BIT_ANDROID) {
Craig Donner05249fc2016-01-15 19:33:55 -08001807 usage |= GRALLOC_USAGE_HW_RENDER;
1808 }
Craig Donner8cfae6d2016-04-12 16:54:03 -07001809 if (value & EGL_NATIVE_BUFFER_USAGE_TEXTURE_BIT_ANDROID) {
Craig Donner05249fc2016-01-15 19:33:55 -08001810 usage |= GRALLOC_USAGE_HW_TEXTURE;
1811 }
1812 // The buffer must be used for either a texture or a
1813 // renderbuffer.
Craig Donner8cfae6d2016-04-12 16:54:03 -07001814 if ((value & EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_BIT_ANDROID) &&
1815 (value & EGL_NATIVE_BUFFER_USAGE_TEXTURE_BIT_ANDROID)) {
Craig Donner05249fc2016-01-15 19:33:55 -08001816 return setError(EGL_BAD_PARAMETER, (EGLClientBuffer)0);
1817 }
1818 break;
1819 default:
1820 return setError(EGL_BAD_PARAMETER, (EGLClientBuffer)0);
1821 }
1822 }
1823 }
Craig Donnerb40504a2016-06-03 17:54:25 -07001824#undef GET_NONNEGATIVE_VALUE
Craig Donner05249fc2016-01-15 19:33:55 -08001825
1826 // Validate format.
1827 if (red_size == 8 && green_size == 8 && blue_size == 8) {
1828 if (alpha_size == 8) {
1829 format = HAL_PIXEL_FORMAT_RGBA_8888;
1830 } else {
1831 format = HAL_PIXEL_FORMAT_RGB_888;
1832 }
1833 } else if (red_size == 5 && green_size == 6 && blue_size == 5 &&
1834 alpha_size == 0) {
Craig Donner478f7db2016-06-10 17:20:15 -07001835 format = HAL_PIXEL_FORMAT_RGB_565;
Craig Donner05249fc2016-01-15 19:33:55 -08001836 } else {
1837 ALOGE("Invalid native pixel format { r=%d, g=%d, b=%d, a=%d }",
1838 red_size, green_size, blue_size, alpha_size);
1839 return setError(EGL_BAD_PARAMETER, (EGLClientBuffer)0);
1840 }
1841
Dan Stozaf62eaf52016-06-01 18:21:44 -07001842#define CHECK_ERROR_CONDITION(message) \
1843 if (err != NO_ERROR) { \
1844 ALOGE(message); \
1845 goto error_condition; \
1846 }
1847
1848 // The holder is used to destroy the buffer if an error occurs.
1849 GraphicBuffer* gBuffer = new GraphicBuffer();
1850 sp<IServiceManager> sm = defaultServiceManager();
1851 sp<IBinder> surfaceFlinger = sm->getService(String16("SurfaceFlinger"));
1852 sp<IBinder> allocator;
1853 Parcel sc_data, sc_reply, data, reply;
1854 status_t err = NO_ERROR;
1855 if (sm == NULL) {
1856 ALOGE("Unable to connect to ServiceManager");
1857 goto error_condition;
1858 }
1859
1860 // Obtain an allocator.
1861 if (surfaceFlinger == NULL) {
1862 ALOGE("Unable to connect to SurfaceFlinger");
1863 goto error_condition;
1864 }
1865 sc_data.writeInterfaceToken(String16("android.ui.ISurfaceComposer"));
1866 err = surfaceFlinger->transact(
1867 BnSurfaceComposer::CREATE_GRAPHIC_BUFFER_ALLOC, sc_data, &sc_reply);
1868 CHECK_ERROR_CONDITION("Unable to obtain allocator from SurfaceFlinger");
1869 allocator = sc_reply.readStrongBinder();
1870
1871 if (allocator == NULL) {
1872 ALOGE("Unable to obtain an ISurfaceComposer");
1873 goto error_condition;
1874 }
1875 data.writeInterfaceToken(String16("android.ui.IGraphicBufferAlloc"));
1876 err = data.writeUint32(width);
1877 CHECK_ERROR_CONDITION("Unable to write width");
1878 err = data.writeUint32(height);
1879 CHECK_ERROR_CONDITION("Unable to write height");
1880 err = data.writeInt32(static_cast<int32_t>(format));
1881 CHECK_ERROR_CONDITION("Unable to write format");
1882 err = data.writeUint32(usage);
1883 CHECK_ERROR_CONDITION("Unable to write usage");
1884 err = data.writeUtf8AsUtf16(
1885 std::string("[eglCreateNativeClientBufferANDROID pid ") +
1886 std::to_string(getpid()) + ']');
1887 CHECK_ERROR_CONDITION("Unable to write requestor name");
1888 err = allocator->transact(IBinder::FIRST_CALL_TRANSACTION, data,
1889 &reply);
1890 CHECK_ERROR_CONDITION(
1891 "Unable to request buffer allocation from surface composer");
1892 err = reply.readInt32();
1893 CHECK_ERROR_CONDITION("Unable to obtain buffer from surface composer");
1894 err = reply.read(*gBuffer);
1895 CHECK_ERROR_CONDITION("Unable to read buffer from surface composer");
1896
1897 err = gBuffer->initCheck();
Craig Donner05249fc2016-01-15 19:33:55 -08001898 if (err != NO_ERROR) {
1899 ALOGE("Unable to create native buffer { w=%d, h=%d, f=%d, u=%#x }: %#x",
1900 width, height, format, usage, err);
Dan Stozaf62eaf52016-06-01 18:21:44 -07001901 goto error_condition;
Craig Donner05249fc2016-01-15 19:33:55 -08001902 }
1903 ALOGD("Created new native buffer %p { w=%d, h=%d, f=%d, u=%#x }",
1904 gBuffer, width, height, format, usage);
1905 return static_cast<EGLClientBuffer>(gBuffer->getNativeBuffer());
Dan Stozaf62eaf52016-06-01 18:21:44 -07001906
1907#undef CHECK_ERROR_CONDITION
1908
1909error_condition:
1910 // Delete the buffer.
1911 sp<GraphicBuffer> holder(gBuffer);
1912 return setError(EGL_BAD_ALLOC, (EGLClientBuffer)0);
Craig Donner05249fc2016-01-15 19:33:55 -08001913}
1914
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001915// ----------------------------------------------------------------------------
1916// NVIDIA extensions
1917// ----------------------------------------------------------------------------
1918EGLuint64NV eglGetSystemTimeFrequencyNV()
1919{
1920 clearError();
1921
1922 if (egl_init_drivers() == EGL_FALSE) {
1923 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1924 }
1925
1926 EGLuint64NV ret = 0;
Mathias Agopianada798b2012-02-13 17:09:30 -08001927 egl_connection_t* const cnx = &gEGLImpl;
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001928
Mathias Agopianada798b2012-02-13 17:09:30 -08001929 if (cnx->dso && cnx->egl.eglGetSystemTimeFrequencyNV) {
1930 return cnx->egl.eglGetSystemTimeFrequencyNV();
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001931 }
1932
Mathias Agopian0e8bbee2011-10-05 19:15:05 -07001933 return setErrorQuiet(EGL_BAD_DISPLAY, 0);
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001934}
1935
1936EGLuint64NV eglGetSystemTimeNV()
1937{
1938 clearError();
1939
1940 if (egl_init_drivers() == EGL_FALSE) {
1941 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1942 }
1943
1944 EGLuint64NV ret = 0;
Mathias Agopianada798b2012-02-13 17:09:30 -08001945 egl_connection_t* const cnx = &gEGLImpl;
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001946
Mathias Agopianada798b2012-02-13 17:09:30 -08001947 if (cnx->dso && cnx->egl.eglGetSystemTimeNV) {
1948 return cnx->egl.eglGetSystemTimeNV();
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001949 }
1950
Mathias Agopian0e8bbee2011-10-05 19:15:05 -07001951 return setErrorQuiet(EGL_BAD_DISPLAY, 0);
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001952}
Dan Stozaa894d082015-02-19 15:27:36 -08001953
1954// ----------------------------------------------------------------------------
1955// Partial update extension
1956// ----------------------------------------------------------------------------
1957EGLBoolean eglSetDamageRegionKHR(EGLDisplay dpy, EGLSurface surface,
1958 EGLint *rects, EGLint n_rects)
1959{
1960 clearError();
1961
1962 const egl_display_ptr dp = validate_display(dpy);
1963 if (!dp) {
1964 setError(EGL_BAD_DISPLAY, EGL_FALSE);
1965 return EGL_FALSE;
1966 }
1967
1968 SurfaceRef _s(dp.get(), surface);
1969 if (!_s.get()) {
1970 setError(EGL_BAD_SURFACE, EGL_FALSE);
1971 return EGL_FALSE;
1972 }
1973
1974 egl_surface_t const * const s = get_surface(surface);
1975 if (s->cnx->egl.eglSetDamageRegionKHR) {
1976 return s->cnx->egl.eglSetDamageRegionKHR(dp->disp.dpy, s->surface,
1977 rects, n_rects);
1978 }
1979
1980 return EGL_FALSE;
1981}