blob: 5de559985f39803d7cb036babed40a3563dfebab [file] [log] [blame]
Jesse Hall47743382013-02-08 11:13:46 -08001/*
Mathias Agopian518ec112011-05-13 16:21:08 -07002 ** Copyright 2007, The Android Open Source Project
3 **
Jesse Hall47743382013-02-08 11:13:46 -08004 ** Licensed under the Apache License, Version 2.0 (the "License");
5 ** you may not use this file except in compliance with the License.
6 ** You may obtain a copy of the License at
Mathias Agopian518ec112011-05-13 16:21:08 -07007 **
Jesse Hall47743382013-02-08 11:13:46 -08008 ** http://www.apache.org/licenses/LICENSE-2.0
Mathias Agopian518ec112011-05-13 16:21:08 -07009 **
Jesse Hall47743382013-02-08 11:13:46 -080010 ** Unless required by applicable law or agreed to in writing, software
11 ** distributed under the License is distributed on an "AS IS" BASIS,
12 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 ** See the License for the specific language governing permissions and
Mathias Agopian518ec112011-05-13 16:21:08 -070014 ** limitations under the License.
15 */
16
Jamie Gennis1c8e95c2012-02-23 19:27:23 -080017#define ATRACE_TAG ATRACE_TAG_GRAPHICS
18
Jesse Hallc07b5202013-07-04 12:08:16 -070019#include <dlfcn.h>
Mathias Agopian518ec112011-05-13 16:21:08 -070020#include <ctype.h>
21#include <stdlib.h>
22#include <string.h>
23
24#include <hardware/gralloc.h>
25#include <system/window.h>
26
27#include <EGL/egl.h>
28#include <EGL/eglext.h>
Mathias Agopian518ec112011-05-13 16:21:08 -070029
30#include <cutils/log.h>
31#include <cutils/atomic.h>
Mathias Agopian7db993a2012-03-25 00:49:46 -070032#include <cutils/compiler.h>
Mathias Agopian518ec112011-05-13 16:21:08 -070033#include <cutils/properties.h>
34#include <cutils/memory.h>
35
Craig Donner05249fc2016-01-15 19:33:55 -080036#include <ui/GraphicBuffer.h>
37
Mathias Agopian518ec112011-05-13 16:21:08 -070038#include <utils/KeyedVector.h>
39#include <utils/SortedVector.h>
40#include <utils/String8.h>
Jamie Gennis1c8e95c2012-02-23 19:27:23 -080041#include <utils/Trace.h>
Mathias Agopian518ec112011-05-13 16:21:08 -070042
Mathias Agopian39c24a22013-04-04 23:17:56 -070043#include "../egl_impl.h"
Mathias Agopian39c24a22013-04-04 23:17:56 -070044#include "../hooks.h"
Mathias Agopian518ec112011-05-13 16:21:08 -070045
46#include "egl_display.h"
Mathias Agopian518ec112011-05-13 16:21:08 -070047#include "egl_object.h"
48#include "egl_tls.h"
Mathias Agopianada798b2012-02-13 17:09:30 -080049#include "egldefs.h"
Mathias Agopian518ec112011-05-13 16:21:08 -070050
51using namespace android;
52
53// ----------------------------------------------------------------------------
54
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070055namespace android {
56
Mathias Agopian518ec112011-05-13 16:21:08 -070057struct extention_map_t {
58 const char* name;
59 __eglMustCastToProperFunctionPointerType address;
60};
61
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070062/*
Jesse Hall21558da2013-08-06 15:31:22 -070063 * This is the list of EGL extensions exposed to applications.
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070064 *
Jesse Hall21558da2013-08-06 15:31:22 -070065 * Some of them (gBuiltinExtensionString) are implemented entirely in this EGL
66 * wrapper and are always available.
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070067 *
Jesse Hall21558da2013-08-06 15:31:22 -070068 * The rest (gExtensionString) depend on support in the EGL driver, and are
69 * only available if the driver supports them. However, some of these must be
70 * supported because they are used by the Android system itself; these are
Pablo Ceballos02b05da2016-02-02 17:53:18 -080071 * listed as mandatory below and are required by the CDD. The system *assumes*
Jesse Hall21558da2013-08-06 15:31:22 -070072 * the mandatory extensions are present and may not function properly if some
73 * are missing.
74 *
75 * NOTE: Both strings MUST have a single space as the last character.
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070076 */
Jesse Hall21558da2013-08-06 15:31:22 -070077extern char const * const gBuiltinExtensionString =
78 "EGL_KHR_get_all_proc_addresses "
79 "EGL_ANDROID_presentation_time "
Dan Stozaa894d082015-02-19 15:27:36 -080080 "EGL_KHR_swap_buffers_with_damage "
Craig Donner05249fc2016-01-15 19:33:55 -080081 "EGL_ANDROID_create_native_client_buffer "
Pablo Ceballos02b05da2016-02-02 17:53:18 -080082 "EGL_ANDROID_front_buffer_auto_refresh "
Jesse Hall21558da2013-08-06 15:31:22 -070083 ;
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070084extern char const * const gExtensionString =
85 "EGL_KHR_image " // mandatory
86 "EGL_KHR_image_base " // mandatory
87 "EGL_KHR_image_pixmap "
88 "EGL_KHR_lock_surface "
Jesse Hallc2e41222013-08-08 13:40:22 -070089 "EGL_KHR_gl_colorspace "
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070090 "EGL_KHR_gl_texture_2D_image "
Season Li000d88f2015-07-01 11:39:40 -070091 "EGL_KHR_gl_texture_3D_image "
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070092 "EGL_KHR_gl_texture_cubemap_image "
93 "EGL_KHR_gl_renderbuffer_image "
94 "EGL_KHR_reusable_sync "
95 "EGL_KHR_fence_sync "
Jamie Gennisf6d1c392013-04-25 18:48:41 -070096 "EGL_KHR_create_context "
Season Li000d88f2015-07-01 11:39:40 -070097 "EGL_KHR_config_attribs "
98 "EGL_KHR_surfaceless_context "
99 "EGL_KHR_stream "
100 "EGL_KHR_stream_fifo "
101 "EGL_KHR_stream_producer_eglsurface "
102 "EGL_KHR_stream_consumer_gltexture "
103 "EGL_KHR_stream_cross_process_fd "
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700104 "EGL_EXT_create_context_robustness "
105 "EGL_NV_system_time "
106 "EGL_ANDROID_image_native_buffer " // mandatory
Mathias Agopian2bb71682013-03-27 17:32:41 -0700107 "EGL_KHR_wait_sync " // strongly recommended
Jamie Gennisdbe92452013-09-23 17:22:10 -0700108 "EGL_ANDROID_recordable " // mandatory
Dan Stozaa894d082015-02-19 15:27:36 -0800109 "EGL_KHR_partial_update " // strongly recommended
110 "EGL_EXT_buffer_age " // strongly recommended with partial_update
Jesse Hall408e59f2015-04-24 01:40:42 -0700111 "EGL_KHR_create_context_no_error "
Pablo Ceballosceb9ee72016-04-13 11:17:32 -0700112 "EGL_KHR_mutable_render_buffer "
Mika Isojärvif37864b2016-04-15 11:58:56 -0700113 "EGL_EXT_yuv_surface "
Craig Donneraec86972016-04-28 18:09:40 -0700114 "EGL_EXT_protected_content "
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700115 ;
116
117// extensions not exposed to applications but used by the ANDROID system
118// "EGL_ANDROID_blob_cache " // strongly recommended
119// "EGL_IMG_hibernate_process " // optional
120// "EGL_ANDROID_native_fence_sync " // strongly recommended
121// "EGL_ANDROID_framebuffer_target " // mandatory for HWC 1.1
Jamie Gennisdbe92452013-09-23 17:22:10 -0700122// "EGL_ANDROID_image_crop " // optional
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700123
124/*
125 * EGL Extensions entry-points exposed to 3rd party applications
126 * (keep in sync with gExtensionString above)
127 *
128 */
129static const extention_map_t sExtensionMap[] = {
130 // EGL_KHR_lock_surface
Mathias Agopian518ec112011-05-13 16:21:08 -0700131 { "eglLockSurfaceKHR",
132 (__eglMustCastToProperFunctionPointerType)&eglLockSurfaceKHR },
133 { "eglUnlockSurfaceKHR",
134 (__eglMustCastToProperFunctionPointerType)&eglUnlockSurfaceKHR },
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700135
136 // EGL_KHR_image, EGL_KHR_image_base
Mathias Agopian518ec112011-05-13 16:21:08 -0700137 { "eglCreateImageKHR",
138 (__eglMustCastToProperFunctionPointerType)&eglCreateImageKHR },
139 { "eglDestroyImageKHR",
140 (__eglMustCastToProperFunctionPointerType)&eglDestroyImageKHR },
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700141
142 // EGL_KHR_reusable_sync, EGL_KHR_fence_sync
143 { "eglCreateSyncKHR",
144 (__eglMustCastToProperFunctionPointerType)&eglCreateSyncKHR },
145 { "eglDestroySyncKHR",
146 (__eglMustCastToProperFunctionPointerType)&eglDestroySyncKHR },
147 { "eglClientWaitSyncKHR",
148 (__eglMustCastToProperFunctionPointerType)&eglClientWaitSyncKHR },
149 { "eglSignalSyncKHR",
150 (__eglMustCastToProperFunctionPointerType)&eglSignalSyncKHR },
151 { "eglGetSyncAttribKHR",
152 (__eglMustCastToProperFunctionPointerType)&eglGetSyncAttribKHR },
153
154 // EGL_NV_system_time
Jonas Yang1c3d72a2011-08-26 20:04:39 +0800155 { "eglGetSystemTimeFrequencyNV",
156 (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeFrequencyNV },
157 { "eglGetSystemTimeNV",
158 (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeNV },
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700159
Mathias Agopian2bb71682013-03-27 17:32:41 -0700160 // EGL_KHR_wait_sync
161 { "eglWaitSyncKHR",
162 (__eglMustCastToProperFunctionPointerType)&eglWaitSyncKHR },
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700163
164 // EGL_ANDROID_presentation_time
165 { "eglPresentationTimeANDROID",
166 (__eglMustCastToProperFunctionPointerType)&eglPresentationTimeANDROID },
Dan Stozaa894d082015-02-19 15:27:36 -0800167
168 // EGL_KHR_swap_buffers_with_damage
169 { "eglSwapBuffersWithDamageKHR",
170 (__eglMustCastToProperFunctionPointerType)&eglSwapBuffersWithDamageKHR },
171
Craig Donner05249fc2016-01-15 19:33:55 -0800172 // EGL_ANDROID_native_client_buffer
173 { "eglCreateNativeClientBufferANDROID",
174 (__eglMustCastToProperFunctionPointerType)&eglCreateNativeClientBufferANDROID },
175
Dan Stozaa894d082015-02-19 15:27:36 -0800176 // EGL_KHR_partial_update
177 { "eglSetDamageRegionKHR",
178 (__eglMustCastToProperFunctionPointerType)&eglSetDamageRegionKHR },
Season Li000d88f2015-07-01 11:39:40 -0700179
180 { "eglCreateStreamKHR",
181 (__eglMustCastToProperFunctionPointerType)&eglCreateStreamKHR },
182 { "eglDestroyStreamKHR",
183 (__eglMustCastToProperFunctionPointerType)&eglDestroyStreamKHR },
184 { "eglStreamAttribKHR",
185 (__eglMustCastToProperFunctionPointerType)&eglStreamAttribKHR },
186 { "eglQueryStreamKHR",
187 (__eglMustCastToProperFunctionPointerType)&eglQueryStreamKHR },
188 { "eglQueryStreamu64KHR",
189 (__eglMustCastToProperFunctionPointerType)&eglQueryStreamu64KHR },
190 { "eglQueryStreamTimeKHR",
191 (__eglMustCastToProperFunctionPointerType)&eglQueryStreamTimeKHR },
192 { "eglCreateStreamProducerSurfaceKHR",
193 (__eglMustCastToProperFunctionPointerType)&eglCreateStreamProducerSurfaceKHR },
194 { "eglStreamConsumerGLTextureExternalKHR",
195 (__eglMustCastToProperFunctionPointerType)&eglStreamConsumerGLTextureExternalKHR },
196 { "eglStreamConsumerAcquireKHR",
197 (__eglMustCastToProperFunctionPointerType)&eglStreamConsumerAcquireKHR },
198 { "eglStreamConsumerReleaseKHR",
199 (__eglMustCastToProperFunctionPointerType)&eglStreamConsumerReleaseKHR },
200 { "eglGetStreamFileDescriptorKHR",
201 (__eglMustCastToProperFunctionPointerType)&eglGetStreamFileDescriptorKHR },
202 { "eglCreateStreamFromFileDescriptorKHR",
203 (__eglMustCastToProperFunctionPointerType)&eglCreateStreamFromFileDescriptorKHR },
Mathias Agopian518ec112011-05-13 16:21:08 -0700204};
205
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700206/*
207 * These extensions entry-points should not be exposed to applications.
208 * They're used internally by the Android EGL layer.
209 */
210#define FILTER_EXTENSIONS(procname) \
211 (!strcmp((procname), "eglSetBlobCacheFuncsANDROID") || \
212 !strcmp((procname), "eglHibernateProcessIMG") || \
213 !strcmp((procname), "eglAwakenProcessIMG") || \
214 !strcmp((procname), "eglDupNativeFenceFDANDROID"))
215
216
217
Mathias Agopian518ec112011-05-13 16:21:08 -0700218// accesses protected by sExtensionMapMutex
219static DefaultKeyedVector<String8, __eglMustCastToProperFunctionPointerType> sGLExtentionMap;
220static int sGLExtentionSlot = 0;
221static pthread_mutex_t sExtensionMapMutex = PTHREAD_MUTEX_INITIALIZER;
222
223static void(*findProcAddress(const char* name,
224 const extention_map_t* map, size_t n))() {
225 for (uint32_t i=0 ; i<n ; i++) {
226 if (!strcmp(name, map[i].name)) {
227 return map[i].address;
228 }
229 }
230 return NULL;
231}
232
233// ----------------------------------------------------------------------------
234
Mathias Agopian518ec112011-05-13 16:21:08 -0700235extern void setGLHooksThreadSpecific(gl_hooks_t const *value);
236extern EGLBoolean egl_init_drivers();
237extern const __eglMustCastToProperFunctionPointerType gExtensionForwarders[MAX_NUMBER_OF_GL_EXTENSIONS];
Mathias Agopian518ec112011-05-13 16:21:08 -0700238extern gl_hooks_t gHooksTrace;
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700239
Mathias Agopian518ec112011-05-13 16:21:08 -0700240} // namespace android;
241
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700242
Mathias Agopian518ec112011-05-13 16:21:08 -0700243// ----------------------------------------------------------------------------
244
245static inline void clearError() { egl_tls_t::clearError(); }
246static inline EGLContext getContext() { return egl_tls_t::getContext(); }
247
248// ----------------------------------------------------------------------------
249
250EGLDisplay eglGetDisplay(EGLNativeDisplayType display)
251{
252 clearError();
253
Dan Stozac3289c42014-01-17 11:38:34 -0800254 uintptr_t index = reinterpret_cast<uintptr_t>(display);
Mathias Agopian518ec112011-05-13 16:21:08 -0700255 if (index >= NUM_DISPLAYS) {
256 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
257 }
258
259 if (egl_init_drivers() == EGL_FALSE) {
260 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
261 }
262
263 EGLDisplay dpy = egl_display_t::getFromNativeDisplay(display);
264 return dpy;
265}
266
267// ----------------------------------------------------------------------------
268// Initialization
269// ----------------------------------------------------------------------------
270
271EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
272{
273 clearError();
274
Jesse Hallb29e5e82012-04-04 16:53:42 -0700275 egl_display_ptr dp = get_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700276 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
277
278 EGLBoolean res = dp->initialize(major, minor);
279
280 return res;
281}
282
283EGLBoolean eglTerminate(EGLDisplay dpy)
284{
285 // NOTE: don't unload the drivers b/c some APIs can be called
286 // after eglTerminate() has been called. eglTerminate() only
287 // terminates an EGLDisplay, not a EGL itself.
288
289 clearError();
290
Jesse Hallb29e5e82012-04-04 16:53:42 -0700291 egl_display_ptr dp = get_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700292 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
293
294 EGLBoolean res = dp->terminate();
Jesse Hall47743382013-02-08 11:13:46 -0800295
Mathias Agopian518ec112011-05-13 16:21:08 -0700296 return res;
297}
298
299// ----------------------------------------------------------------------------
300// configuration
301// ----------------------------------------------------------------------------
302
303EGLBoolean eglGetConfigs( EGLDisplay dpy,
304 EGLConfig *configs,
305 EGLint config_size, EGLint *num_config)
306{
307 clearError();
308
Jesse Hallb29e5e82012-04-04 16:53:42 -0700309 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700310 if (!dp) return EGL_FALSE;
311
Mathias Agopian7773c432012-02-13 20:06:08 -0800312 if (num_config==0) {
313 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700314 }
315
Mathias Agopian7773c432012-02-13 20:06:08 -0800316 EGLBoolean res = EGL_FALSE;
317 *num_config = 0;
318
319 egl_connection_t* const cnx = &gEGLImpl;
320 if (cnx->dso) {
321 res = cnx->egl.eglGetConfigs(
322 dp->disp.dpy, configs, config_size, num_config);
Mathias Agopian518ec112011-05-13 16:21:08 -0700323 }
Mathias Agopian7773c432012-02-13 20:06:08 -0800324
325 return res;
Mathias Agopian518ec112011-05-13 16:21:08 -0700326}
327
328EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list,
329 EGLConfig *configs, EGLint config_size,
330 EGLint *num_config)
331{
332 clearError();
333
Jesse Hallb29e5e82012-04-04 16:53:42 -0700334 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700335 if (!dp) return EGL_FALSE;
336
337 if (num_config==0) {
338 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
339 }
340
Mathias Agopian518ec112011-05-13 16:21:08 -0700341 EGLBoolean res = EGL_FALSE;
342 *num_config = 0;
343
Mathias Agopianada798b2012-02-13 17:09:30 -0800344 egl_connection_t* const cnx = &gEGLImpl;
345 if (cnx->dso) {
Romain Guy1cffc802012-10-15 18:13:05 -0700346 if (attrib_list) {
347 char value[PROPERTY_VALUE_MAX];
348 property_get("debug.egl.force_msaa", value, "false");
349
350 if (!strcmp(value, "true")) {
351 size_t attribCount = 0;
352 EGLint attrib = attrib_list[0];
353
354 // Only enable MSAA if the context is OpenGL ES 2.0 and
Romain Guybe3c3e42012-10-15 19:25:18 -0700355 // if no caveat is requested
Romain Guy1cffc802012-10-15 18:13:05 -0700356 const EGLint *attribRendererable = NULL;
357 const EGLint *attribCaveat = NULL;
358
359 // Count the number of attributes and look for
Romain Guybe3c3e42012-10-15 19:25:18 -0700360 // EGL_RENDERABLE_TYPE and EGL_CONFIG_CAVEAT
Romain Guy1cffc802012-10-15 18:13:05 -0700361 while (attrib != EGL_NONE) {
362 attrib = attrib_list[attribCount];
363 switch (attrib) {
364 case EGL_RENDERABLE_TYPE:
365 attribRendererable = &attrib_list[attribCount];
366 break;
367 case EGL_CONFIG_CAVEAT:
368 attribCaveat = &attrib_list[attribCount];
369 break;
370 }
371 attribCount++;
372 }
373
374 if (attribRendererable && attribRendererable[1] == EGL_OPENGL_ES2_BIT &&
375 (!attribCaveat || attribCaveat[1] != EGL_NONE)) {
Jesse Hall47743382013-02-08 11:13:46 -0800376
Romain Guy1cffc802012-10-15 18:13:05 -0700377 // Insert 2 extra attributes to force-enable MSAA 4x
378 EGLint aaAttribs[attribCount + 4];
379 aaAttribs[0] = EGL_SAMPLE_BUFFERS;
380 aaAttribs[1] = 1;
381 aaAttribs[2] = EGL_SAMPLES;
382 aaAttribs[3] = 4;
383
384 memcpy(&aaAttribs[4], attrib_list, attribCount * sizeof(EGLint));
385
386 EGLint numConfigAA;
387 EGLBoolean resAA = cnx->egl.eglChooseConfig(
388 dp->disp.dpy, aaAttribs, configs, config_size, &numConfigAA);
389
390 if (resAA == EGL_TRUE && numConfigAA > 0) {
391 ALOGD("Enabling MSAA 4x");
392 *num_config = numConfigAA;
393 return resAA;
394 }
395 }
396 }
397 }
398
Mathias Agopian7773c432012-02-13 20:06:08 -0800399 res = cnx->egl.eglChooseConfig(
400 dp->disp.dpy, attrib_list, configs, config_size, num_config);
Mathias Agopian518ec112011-05-13 16:21:08 -0700401 }
402 return res;
403}
404
405EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
406 EGLint attribute, EGLint *value)
407{
408 clearError();
409
Jesse Hallb29e5e82012-04-04 16:53:42 -0700410 egl_connection_t* cnx = NULL;
411 const egl_display_ptr dp = validate_display_connection(dpy, cnx);
412 if (!dp) return EGL_FALSE;
Jesse Hall47743382013-02-08 11:13:46 -0800413
Mathias Agopian518ec112011-05-13 16:21:08 -0700414 return cnx->egl.eglGetConfigAttrib(
Mathias Agopian7773c432012-02-13 20:06:08 -0800415 dp->disp.dpy, config, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -0700416}
417
418// ----------------------------------------------------------------------------
419// surfaces
420// ----------------------------------------------------------------------------
421
Jesse Hallc2e41222013-08-08 13:40:22 -0700422// Turn linear formats into corresponding sRGB formats when colorspace is
423// EGL_GL_COLORSPACE_SRGB_KHR, or turn sRGB formats into corresponding linear
424// formats when colorspace is EGL_GL_COLORSPACE_LINEAR_KHR. In any cases where
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800425// the modification isn't possible, the original dataSpace is returned.
426static android_dataspace modifyBufferDataspace( android_dataspace dataSpace,
427 EGLint colorspace) {
Jesse Hallc2e41222013-08-08 13:40:22 -0700428 if (colorspace == EGL_GL_COLORSPACE_LINEAR_KHR) {
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800429 return HAL_DATASPACE_SRGB_LINEAR;
Jesse Hallc2e41222013-08-08 13:40:22 -0700430 } else if (colorspace == EGL_GL_COLORSPACE_SRGB_KHR) {
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800431 return HAL_DATASPACE_SRGB;
Jesse Hallc2e41222013-08-08 13:40:22 -0700432 }
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800433 return dataSpace;
Jesse Hallc2e41222013-08-08 13:40:22 -0700434}
435
Mathias Agopian518ec112011-05-13 16:21:08 -0700436EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config,
437 NativeWindowType window,
438 const EGLint *attrib_list)
439{
440 clearError();
441
Jesse Hallb29e5e82012-04-04 16:53:42 -0700442 egl_connection_t* cnx = NULL;
443 egl_display_ptr dp = validate_display_connection(dpy, cnx);
444 if (dp) {
Mathias Agopianada798b2012-02-13 17:09:30 -0800445 EGLDisplay iDpy = dp->disp.dpy;
Mathias Agopian518ec112011-05-13 16:21:08 -0700446
Andy McFaddend566ce32014-01-07 15:54:17 -0800447 int result = native_window_api_connect(window, NATIVE_WINDOW_API_EGL);
448 if (result != OK) {
449 ALOGE("eglCreateWindowSurface: native_window_api_connect (win=%p) "
450 "failed (%#x) (already connected to another API?)",
451 window, result);
Jonathan Hamilton77a9b4a2013-07-17 09:41:42 -0700452 return setError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
Mathias Agopian81a63352011-07-29 17:55:48 -0700453 }
454
Mathias Agopian0f288fc2013-08-21 16:36:34 -0700455 // Set the native window's buffers format to match what this config requests.
Jesse Hallc2e41222013-08-08 13:40:22 -0700456 // Whether to use sRGB gamma is not part of the EGLconfig, but is part
457 // of our native format. So if sRGB gamma is requested, we have to
458 // modify the EGLconfig's format before setting the native window's
459 // format.
Alistair Strachan733a8072015-02-12 12:33:25 -0800460
Mathias Agopian0f288fc2013-08-21 16:36:34 -0700461 // by default, just pick RGBA_8888
462 EGLint format = HAL_PIXEL_FORMAT_RGBA_8888;
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800463 android_dataspace dataSpace = HAL_DATASPACE_UNKNOWN;
Mathias Agopian0f288fc2013-08-21 16:36:34 -0700464
465 EGLint a = 0;
466 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_ALPHA_SIZE, &a);
467 if (a > 0) {
468 // alpha-channel requested, there's really only one suitable format
469 format = HAL_PIXEL_FORMAT_RGBA_8888;
470 } else {
471 EGLint r, g, b;
472 r = g = b = 0;
473 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_RED_SIZE, &r);
474 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_GREEN_SIZE, &g);
475 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_BLUE_SIZE, &b);
476 EGLint colorDepth = r + g + b;
477 if (colorDepth <= 16) {
478 format = HAL_PIXEL_FORMAT_RGB_565;
479 } else {
480 format = HAL_PIXEL_FORMAT_RGBX_8888;
481 }
Jesse Hallc2e41222013-08-08 13:40:22 -0700482 }
Mathias Agopian0f288fc2013-08-21 16:36:34 -0700483
484 // now select a corresponding sRGB format if needed
485 if (attrib_list && dp->haveExtension("EGL_KHR_gl_colorspace")) {
486 for (const EGLint* attr = attrib_list; *attr != EGL_NONE; attr += 2) {
487 if (*attr == EGL_GL_COLORSPACE_KHR) {
Sandeep Shinde9c67bfd2015-02-10 16:04:15 +0530488 dataSpace = modifyBufferDataspace(dataSpace, *(attr+1));
Jamie Gennisbee205f2011-07-01 13:12:07 -0700489 }
Mathias Agopian518ec112011-05-13 16:21:08 -0700490 }
491 }
Alistair Strachan733a8072015-02-12 12:33:25 -0800492
Jesse Hallc2e41222013-08-08 13:40:22 -0700493 if (format != 0) {
494 int err = native_window_set_buffers_format(window, format);
495 if (err != 0) {
496 ALOGE("error setting native window pixel format: %s (%d)",
497 strerror(-err), err);
498 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
499 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
500 }
501 }
Mathias Agopian518ec112011-05-13 16:21:08 -0700502
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800503 if (dataSpace != 0) {
504 int err = native_window_set_buffers_data_space(window, dataSpace);
505 if (err != 0) {
506 ALOGE("error setting native window pixel dataSpace: %s (%d)",
507 strerror(-err), err);
508 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
509 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
510 }
511 }
512
Jamie Gennis59769462011-11-19 18:04:43 -0800513 // the EGL spec requires that a new EGLSurface default to swap interval
514 // 1, so explicitly set that on the window here.
515 ANativeWindow* anw = reinterpret_cast<ANativeWindow*>(window);
516 anw->setSwapInterval(anw, 1);
517
Mathias Agopian518ec112011-05-13 16:21:08 -0700518 EGLSurface surface = cnx->egl.eglCreateWindowSurface(
Mathias Agopian7773c432012-02-13 20:06:08 -0800519 iDpy, config, window, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700520 if (surface != EGL_NO_SURFACE) {
Jesse Hallb29e5e82012-04-04 16:53:42 -0700521 egl_surface_t* s = new egl_surface_t(dp.get(), config, window,
522 surface, cnx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700523 return s;
524 }
Mathias Agopian81a63352011-07-29 17:55:48 -0700525
526 // EGLSurface creation failed
527 native_window_set_buffers_format(window, 0);
528 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
Mathias Agopian518ec112011-05-13 16:21:08 -0700529 }
530 return EGL_NO_SURFACE;
531}
532
533EGLSurface eglCreatePixmapSurface( EGLDisplay dpy, EGLConfig config,
534 NativePixmapType pixmap,
535 const EGLint *attrib_list)
536{
537 clearError();
538
Jesse Hallb29e5e82012-04-04 16:53:42 -0700539 egl_connection_t* cnx = NULL;
540 egl_display_ptr dp = validate_display_connection(dpy, cnx);
541 if (dp) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700542 EGLSurface surface = cnx->egl.eglCreatePixmapSurface(
Mathias Agopian7773c432012-02-13 20:06:08 -0800543 dp->disp.dpy, config, pixmap, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700544 if (surface != EGL_NO_SURFACE) {
Jesse Hallb29e5e82012-04-04 16:53:42 -0700545 egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL,
546 surface, cnx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700547 return s;
548 }
549 }
550 return EGL_NO_SURFACE;
551}
552
553EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config,
554 const EGLint *attrib_list)
555{
556 clearError();
557
Jesse Hallb29e5e82012-04-04 16:53:42 -0700558 egl_connection_t* cnx = NULL;
559 egl_display_ptr dp = validate_display_connection(dpy, cnx);
560 if (dp) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700561 EGLSurface surface = cnx->egl.eglCreatePbufferSurface(
Mathias Agopian7773c432012-02-13 20:06:08 -0800562 dp->disp.dpy, config, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700563 if (surface != EGL_NO_SURFACE) {
Jesse Hallb29e5e82012-04-04 16:53:42 -0700564 egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL,
565 surface, cnx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700566 return s;
567 }
568 }
569 return EGL_NO_SURFACE;
570}
Jesse Hall47743382013-02-08 11:13:46 -0800571
Mathias Agopian518ec112011-05-13 16:21:08 -0700572EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
573{
574 clearError();
575
Jesse Hallb29e5e82012-04-04 16:53:42 -0700576 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700577 if (!dp) return EGL_FALSE;
578
Jesse Hallb29e5e82012-04-04 16:53:42 -0700579 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700580 if (!_s.get())
581 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700582
583 egl_surface_t * const s = get_surface(surface);
Mathias Agopianada798b2012-02-13 17:09:30 -0800584 EGLBoolean result = s->cnx->egl.eglDestroySurface(dp->disp.dpy, s->surface);
Mathias Agopian518ec112011-05-13 16:21:08 -0700585 if (result == EGL_TRUE) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700586 _s.terminate();
587 }
588 return result;
589}
590
591EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface surface,
592 EGLint attribute, EGLint *value)
593{
594 clearError();
595
Jesse Hallb29e5e82012-04-04 16:53:42 -0700596 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700597 if (!dp) return EGL_FALSE;
598
Jesse Hallb29e5e82012-04-04 16:53:42 -0700599 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700600 if (!_s.get())
601 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700602
Mathias Agopian518ec112011-05-13 16:21:08 -0700603 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian7773c432012-02-13 20:06:08 -0800604 return s->cnx->egl.eglQuerySurface(
605 dp->disp.dpy, s->surface, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -0700606}
607
Jamie Gennise8696a42012-01-15 18:54:57 -0800608void EGLAPI eglBeginFrame(EGLDisplay dpy, EGLSurface surface) {
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800609 ATRACE_CALL();
Jamie Gennise8696a42012-01-15 18:54:57 -0800610 clearError();
611
Jesse Hallb29e5e82012-04-04 16:53:42 -0700612 const egl_display_ptr dp = validate_display(dpy);
Jamie Gennise8696a42012-01-15 18:54:57 -0800613 if (!dp) {
614 return;
615 }
616
Jesse Hallb29e5e82012-04-04 16:53:42 -0700617 SurfaceRef _s(dp.get(), surface);
Jamie Gennise8696a42012-01-15 18:54:57 -0800618 if (!_s.get()) {
619 setError(EGL_BAD_SURFACE, EGL_FALSE);
620 return;
621 }
Jamie Gennise8696a42012-01-15 18:54:57 -0800622}
623
Mathias Agopian518ec112011-05-13 16:21:08 -0700624// ----------------------------------------------------------------------------
625// Contexts
626// ----------------------------------------------------------------------------
627
628EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config,
629 EGLContext share_list, const EGLint *attrib_list)
630{
631 clearError();
632
Jesse Hallb29e5e82012-04-04 16:53:42 -0700633 egl_connection_t* cnx = NULL;
634 const egl_display_ptr dp = validate_display_connection(dpy, cnx);
Michael Chock0673e1e2012-06-21 12:53:17 -0700635 if (dp) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700636 if (share_list != EGL_NO_CONTEXT) {
Michael Chock0673e1e2012-06-21 12:53:17 -0700637 if (!ContextRef(dp.get(), share_list).get()) {
638 return setError(EGL_BAD_CONTEXT, EGL_NO_CONTEXT);
639 }
Mathias Agopian518ec112011-05-13 16:21:08 -0700640 egl_context_t* const c = get_context(share_list);
641 share_list = c->context;
642 }
643 EGLContext context = cnx->egl.eglCreateContext(
Mathias Agopian7773c432012-02-13 20:06:08 -0800644 dp->disp.dpy, config, share_list, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700645 if (context != EGL_NO_CONTEXT) {
646 // figure out if it's a GLESv1 or GLESv2
647 int version = 0;
648 if (attrib_list) {
649 while (*attrib_list != EGL_NONE) {
650 GLint attr = *attrib_list++;
651 GLint value = *attrib_list++;
652 if (attr == EGL_CONTEXT_CLIENT_VERSION) {
653 if (value == 1) {
Mathias Agopian7773c432012-02-13 20:06:08 -0800654 version = egl_connection_t::GLESv1_INDEX;
Jesse Hall47743382013-02-08 11:13:46 -0800655 } else if (value == 2 || value == 3) {
Mathias Agopian7773c432012-02-13 20:06:08 -0800656 version = egl_connection_t::GLESv2_INDEX;
Mathias Agopian518ec112011-05-13 16:21:08 -0700657 }
658 }
659 };
660 }
Jesse Hallb29e5e82012-04-04 16:53:42 -0700661 egl_context_t* c = new egl_context_t(dpy, context, config, cnx,
662 version);
Mathias Agopian518ec112011-05-13 16:21:08 -0700663 return c;
664 }
665 }
666 return EGL_NO_CONTEXT;
667}
668
669EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
670{
671 clearError();
672
Jesse Hallb29e5e82012-04-04 16:53:42 -0700673 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700674 if (!dp)
675 return EGL_FALSE;
Mathias Agopian518ec112011-05-13 16:21:08 -0700676
Jesse Hallb29e5e82012-04-04 16:53:42 -0700677 ContextRef _c(dp.get(), ctx);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700678 if (!_c.get())
679 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
Jesse Hall47743382013-02-08 11:13:46 -0800680
Mathias Agopian518ec112011-05-13 16:21:08 -0700681 egl_context_t * const c = get_context(ctx);
Mathias Agopianada798b2012-02-13 17:09:30 -0800682 EGLBoolean result = c->cnx->egl.eglDestroyContext(dp->disp.dpy, c->context);
Mathias Agopian518ec112011-05-13 16:21:08 -0700683 if (result == EGL_TRUE) {
684 _c.terminate();
685 }
686 return result;
687}
688
Mathias Agopian518ec112011-05-13 16:21:08 -0700689EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw,
690 EGLSurface read, EGLContext ctx)
691{
692 clearError();
693
Jesse Hallb29e5e82012-04-04 16:53:42 -0700694 egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700695 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
696
Mathias Agopian5b287a62011-05-16 18:58:55 -0700697 // If ctx is not EGL_NO_CONTEXT, read is not EGL_NO_SURFACE, or draw is not
698 // EGL_NO_SURFACE, then an EGL_NOT_INITIALIZED error is generated if dpy is
699 // a valid but uninitialized display.
Mathias Agopian518ec112011-05-13 16:21:08 -0700700 if ( (ctx != EGL_NO_CONTEXT) || (read != EGL_NO_SURFACE) ||
701 (draw != EGL_NO_SURFACE) ) {
702 if (!dp->isReady()) return setError(EGL_NOT_INITIALIZED, EGL_FALSE);
703 }
704
705 // get a reference to the object passed in
Jesse Hallb29e5e82012-04-04 16:53:42 -0700706 ContextRef _c(dp.get(), ctx);
707 SurfaceRef _d(dp.get(), draw);
708 SurfaceRef _r(dp.get(), read);
Mathias Agopian518ec112011-05-13 16:21:08 -0700709
710 // validate the context (if not EGL_NO_CONTEXT)
Mathias Agopian5b287a62011-05-16 18:58:55 -0700711 if ((ctx != EGL_NO_CONTEXT) && !_c.get()) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700712 // EGL_NO_CONTEXT is valid
Michael Chock0673e1e2012-06-21 12:53:17 -0700713 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700714 }
715
716 // these are the underlying implementation's object
717 EGLContext impl_ctx = EGL_NO_CONTEXT;
718 EGLSurface impl_draw = EGL_NO_SURFACE;
719 EGLSurface impl_read = EGL_NO_SURFACE;
720
721 // these are our objects structs passed in
722 egl_context_t * c = NULL;
723 egl_surface_t const * d = NULL;
724 egl_surface_t const * r = NULL;
725
726 // these are the current objects structs
727 egl_context_t * cur_c = get_context(getContext());
Jesse Hall47743382013-02-08 11:13:46 -0800728
Mathias Agopian518ec112011-05-13 16:21:08 -0700729 if (ctx != EGL_NO_CONTEXT) {
730 c = get_context(ctx);
731 impl_ctx = c->context;
732 } else {
733 // no context given, use the implementation of the current context
Michael Chock0673e1e2012-06-21 12:53:17 -0700734 if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE) {
735 // calling eglMakeCurrent( ..., !=0, !=0, EGL_NO_CONTEXT);
736 return setError(EGL_BAD_MATCH, EGL_FALSE);
737 }
Mathias Agopian518ec112011-05-13 16:21:08 -0700738 if (cur_c == NULL) {
739 // no current context
Mathias Agopian518ec112011-05-13 16:21:08 -0700740 // not an error, there is just no current context.
741 return EGL_TRUE;
742 }
743 }
744
745 // retrieve the underlying implementation's draw EGLSurface
746 if (draw != EGL_NO_SURFACE) {
Michael Chock0673e1e2012-06-21 12:53:17 -0700747 if (!_d.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700748 d = get_surface(draw);
Mathias Agopian518ec112011-05-13 16:21:08 -0700749 impl_draw = d->surface;
750 }
751
752 // retrieve the underlying implementation's read EGLSurface
753 if (read != EGL_NO_SURFACE) {
Michael Chock0673e1e2012-06-21 12:53:17 -0700754 if (!_r.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700755 r = get_surface(read);
Mathias Agopian518ec112011-05-13 16:21:08 -0700756 impl_read = r->surface;
757 }
758
Mathias Agopian518ec112011-05-13 16:21:08 -0700759
Jesse Hallb29e5e82012-04-04 16:53:42 -0700760 EGLBoolean result = dp->makeCurrent(c, cur_c,
Mathias Agopianfb87e542012-01-30 18:20:52 -0800761 draw, read, ctx,
762 impl_draw, impl_read, impl_ctx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700763
764 if (result == EGL_TRUE) {
Mathias Agopianfb87e542012-01-30 18:20:52 -0800765 if (c) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700766 setGLHooksThreadSpecific(c->cnx->hooks[c->version]);
767 egl_tls_t::setContext(ctx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700768 _c.acquire();
769 _r.acquire();
770 _d.acquire();
Mathias Agopian518ec112011-05-13 16:21:08 -0700771 } else {
772 setGLHooksThreadSpecific(&gHooksNoContext);
773 egl_tls_t::setContext(EGL_NO_CONTEXT);
774 }
Mathias Agopian5fecea72011-08-25 18:38:24 -0700775 } else {
Steve Blocke6f43dd2012-01-06 19:20:56 +0000776 // this will ALOGE the error
Mathias Agopian63108c32013-09-06 13:36:49 -0700777 egl_connection_t* const cnx = &gEGLImpl;
778 result = setError(cnx->egl.eglGetError(), EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700779 }
780 return result;
781}
782
783
784EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx,
785 EGLint attribute, EGLint *value)
786{
787 clearError();
788
Jesse Hallb29e5e82012-04-04 16:53:42 -0700789 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700790 if (!dp) return EGL_FALSE;
791
Jesse Hallb29e5e82012-04-04 16:53:42 -0700792 ContextRef _c(dp.get(), ctx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700793 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
794
Mathias Agopian518ec112011-05-13 16:21:08 -0700795 egl_context_t * const c = get_context(ctx);
Mathias Agopian7773c432012-02-13 20:06:08 -0800796 return c->cnx->egl.eglQueryContext(
797 dp->disp.dpy, c->context, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -0700798
Mathias Agopian518ec112011-05-13 16:21:08 -0700799}
800
801EGLContext eglGetCurrentContext(void)
802{
803 // could be called before eglInitialize(), but we wouldn't have a context
804 // then, and this function would correctly return EGL_NO_CONTEXT.
805
806 clearError();
807
808 EGLContext ctx = getContext();
809 return ctx;
810}
811
812EGLSurface eglGetCurrentSurface(EGLint readdraw)
813{
814 // could be called before eglInitialize(), but we wouldn't have a context
815 // then, and this function would correctly return EGL_NO_SURFACE.
816
817 clearError();
818
819 EGLContext ctx = getContext();
820 if (ctx) {
821 egl_context_t const * const c = get_context(ctx);
822 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
823 switch (readdraw) {
824 case EGL_READ: return c->read;
Jesse Hall47743382013-02-08 11:13:46 -0800825 case EGL_DRAW: return c->draw;
Mathias Agopian518ec112011-05-13 16:21:08 -0700826 default: return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
827 }
828 }
829 return EGL_NO_SURFACE;
830}
831
832EGLDisplay eglGetCurrentDisplay(void)
833{
834 // could be called before eglInitialize(), but we wouldn't have a context
835 // then, and this function would correctly return EGL_NO_DISPLAY.
836
837 clearError();
838
839 EGLContext ctx = getContext();
840 if (ctx) {
841 egl_context_t const * const c = get_context(ctx);
842 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
843 return c->dpy;
844 }
845 return EGL_NO_DISPLAY;
846}
847
848EGLBoolean eglWaitGL(void)
849{
Mathias Agopian518ec112011-05-13 16:21:08 -0700850 clearError();
851
Mathias Agopianada798b2012-02-13 17:09:30 -0800852 egl_connection_t* const cnx = &gEGLImpl;
853 if (!cnx->dso)
854 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
855
856 return cnx->egl.eglWaitGL();
Mathias Agopian518ec112011-05-13 16:21:08 -0700857}
858
859EGLBoolean eglWaitNative(EGLint engine)
860{
Mathias Agopian518ec112011-05-13 16:21:08 -0700861 clearError();
862
Mathias Agopianada798b2012-02-13 17:09:30 -0800863 egl_connection_t* const cnx = &gEGLImpl;
864 if (!cnx->dso)
865 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
866
867 return cnx->egl.eglWaitNative(engine);
Mathias Agopian518ec112011-05-13 16:21:08 -0700868}
869
870EGLint eglGetError(void)
871{
Mathias Agopianada798b2012-02-13 17:09:30 -0800872 EGLint err = EGL_SUCCESS;
873 egl_connection_t* const cnx = &gEGLImpl;
874 if (cnx->dso) {
875 err = cnx->egl.eglGetError();
Mathias Agopian518ec112011-05-13 16:21:08 -0700876 }
Mathias Agopianada798b2012-02-13 17:09:30 -0800877 if (err == EGL_SUCCESS) {
878 err = egl_tls_t::getError();
879 }
880 return err;
Mathias Agopian518ec112011-05-13 16:21:08 -0700881}
882
Michael Chockc0ec5e22014-01-27 08:14:33 -0800883static __eglMustCastToProperFunctionPointerType findBuiltinWrapper(
Jesse Hallc07b5202013-07-04 12:08:16 -0700884 const char* procname) {
885 const egl_connection_t* cnx = &gEGLImpl;
886 void* proc = NULL;
887
Michael Chockc0ec5e22014-01-27 08:14:33 -0800888 proc = dlsym(cnx->libEgl, procname);
889 if (proc) return (__eglMustCastToProperFunctionPointerType)proc;
890
Jesse Hallc07b5202013-07-04 12:08:16 -0700891 proc = dlsym(cnx->libGles2, procname);
892 if (proc) return (__eglMustCastToProperFunctionPointerType)proc;
893
894 proc = dlsym(cnx->libGles1, procname);
895 if (proc) return (__eglMustCastToProperFunctionPointerType)proc;
896
897 return NULL;
898}
899
Mathias Agopian518ec112011-05-13 16:21:08 -0700900__eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
901{
902 // eglGetProcAddress() could be the very first function called
903 // in which case we must make sure we've initialized ourselves, this
904 // happens the first time egl_get_display() is called.
905
906 clearError();
907
908 if (egl_init_drivers() == EGL_FALSE) {
909 setError(EGL_BAD_PARAMETER, NULL);
910 return NULL;
911 }
912
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700913 if (FILTER_EXTENSIONS(procname)) {
Jamie Gennisaca51c02011-11-03 17:42:43 -0700914 return NULL;
915 }
916
Mathias Agopian518ec112011-05-13 16:21:08 -0700917 __eglMustCastToProperFunctionPointerType addr;
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700918 addr = findProcAddress(procname, sExtensionMap, NELEM(sExtensionMap));
Mathias Agopian518ec112011-05-13 16:21:08 -0700919 if (addr) return addr;
920
Michael Chockc0ec5e22014-01-27 08:14:33 -0800921 addr = findBuiltinWrapper(procname);
Jesse Hallc07b5202013-07-04 12:08:16 -0700922 if (addr) return addr;
Jamie Gennisaca51c02011-11-03 17:42:43 -0700923
Mathias Agopian518ec112011-05-13 16:21:08 -0700924 // this protects accesses to sGLExtentionMap and sGLExtentionSlot
925 pthread_mutex_lock(&sExtensionMapMutex);
926
927 /*
928 * Since eglGetProcAddress() is not associated to anything, it needs
929 * to return a function pointer that "works" regardless of what
930 * the current context is.
931 *
932 * For this reason, we return a "forwarder", a small stub that takes
933 * care of calling the function associated with the context
934 * currently bound.
935 *
936 * We first look for extensions we've already resolved, if we're seeing
937 * this extension for the first time, we go through all our
938 * implementations and call eglGetProcAddress() and record the
939 * result in the appropriate implementation hooks and return the
940 * address of the forwarder corresponding to that hook set.
941 *
942 */
943
944 const String8 name(procname);
945 addr = sGLExtentionMap.valueFor(name);
946 const int slot = sGLExtentionSlot;
947
Steve Blocke6f43dd2012-01-06 19:20:56 +0000948 ALOGE_IF(slot >= MAX_NUMBER_OF_GL_EXTENSIONS,
Mathias Agopian518ec112011-05-13 16:21:08 -0700949 "no more slots for eglGetProcAddress(\"%s\")",
950 procname);
951
952 if (!addr && (slot < MAX_NUMBER_OF_GL_EXTENSIONS)) {
953 bool found = false;
Mathias Agopianada798b2012-02-13 17:09:30 -0800954
955 egl_connection_t* const cnx = &gEGLImpl;
956 if (cnx->dso && cnx->egl.eglGetProcAddress) {
Mathias Agopianada798b2012-02-13 17:09:30 -0800957 // Extensions are independent of the bound context
luliuhui69d10072012-08-30 11:15:36 +0800958 addr =
Mathias Agopian7773c432012-02-13 20:06:08 -0800959 cnx->hooks[egl_connection_t::GLESv1_INDEX]->ext.extensions[slot] =
960 cnx->hooks[egl_connection_t::GLESv2_INDEX]->ext.extensions[slot] =
Mathias Agopianada798b2012-02-13 17:09:30 -0800961 cnx->egl.eglGetProcAddress(procname);
luliuhui69d10072012-08-30 11:15:36 +0800962 if (addr) found = true;
Mathias Agopian518ec112011-05-13 16:21:08 -0700963 }
Mathias Agopianada798b2012-02-13 17:09:30 -0800964
Mathias Agopian518ec112011-05-13 16:21:08 -0700965 if (found) {
966 addr = gExtensionForwarders[slot];
Mathias Agopian518ec112011-05-13 16:21:08 -0700967 sGLExtentionMap.add(name, addr);
968 sGLExtentionSlot++;
969 }
970 }
971
972 pthread_mutex_unlock(&sExtensionMapMutex);
973 return addr;
974}
975
Jamie Gennis28ef8d72012-04-05 20:34:54 -0700976class FrameCompletionThread : public Thread {
977public:
978
979 static void queueSync(EGLSyncKHR sync) {
980 static sp<FrameCompletionThread> thread(new FrameCompletionThread);
981 static bool running = false;
982 if (!running) {
983 thread->run("GPUFrameCompletion");
984 running = true;
985 }
986 {
987 Mutex::Autolock lock(thread->mMutex);
988 ScopedTrace st(ATRACE_TAG, String8::format("kicked off frame %d",
989 thread->mFramesQueued).string());
990 thread->mQueue.push_back(sync);
991 thread->mCondition.signal();
992 thread->mFramesQueued++;
993 ATRACE_INT("GPU Frames Outstanding", thread->mQueue.size());
994 }
995 }
996
997private:
998 FrameCompletionThread() : mFramesQueued(0), mFramesCompleted(0) {}
999
1000 virtual bool threadLoop() {
1001 EGLSyncKHR sync;
1002 uint32_t frameNum;
1003 {
1004 Mutex::Autolock lock(mMutex);
1005 while (mQueue.isEmpty()) {
1006 mCondition.wait(mMutex);
1007 }
1008 sync = mQueue[0];
1009 frameNum = mFramesCompleted;
1010 }
1011 EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
1012 {
1013 ScopedTrace st(ATRACE_TAG, String8::format("waiting for frame %d",
1014 frameNum).string());
1015 EGLint result = eglClientWaitSyncKHR(dpy, sync, 0, EGL_FOREVER_KHR);
1016 if (result == EGL_FALSE) {
1017 ALOGE("FrameCompletion: error waiting for fence: %#x", eglGetError());
1018 } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
1019 ALOGE("FrameCompletion: timeout waiting for fence");
1020 }
1021 eglDestroySyncKHR(dpy, sync);
1022 }
1023 {
1024 Mutex::Autolock lock(mMutex);
1025 mQueue.removeAt(0);
1026 mFramesCompleted++;
1027 ATRACE_INT("GPU Frames Outstanding", mQueue.size());
1028 }
1029 return true;
1030 }
1031
1032 uint32_t mFramesQueued;
1033 uint32_t mFramesCompleted;
1034 Vector<EGLSyncKHR> mQueue;
1035 Condition mCondition;
1036 Mutex mMutex;
1037};
1038
Dan Stozaa894d082015-02-19 15:27:36 -08001039EGLBoolean eglSwapBuffersWithDamageKHR(EGLDisplay dpy, EGLSurface draw,
1040 EGLint *rects, EGLint n_rects)
Mathias Agopian518ec112011-05-13 16:21:08 -07001041{
Jamie Gennis1c8e95c2012-02-23 19:27:23 -08001042 ATRACE_CALL();
Mathias Agopian518ec112011-05-13 16:21:08 -07001043 clearError();
1044
Jesse Hallb29e5e82012-04-04 16:53:42 -07001045 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001046 if (!dp) return EGL_FALSE;
1047
Jesse Hallb29e5e82012-04-04 16:53:42 -07001048 SurfaceRef _s(dp.get(), draw);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001049 if (!_s.get())
1050 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001051
Mathias Agopian518ec112011-05-13 16:21:08 -07001052 egl_surface_t const * const s = get_surface(draw);
Mathias Agopian7db993a2012-03-25 00:49:46 -07001053
Mathias Agopianed6d08b2013-04-16 16:39:46 -07001054 if (CC_UNLIKELY(dp->traceGpuCompletion)) {
1055 EGLSyncKHR sync = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, NULL);
1056 if (sync != EGL_NO_SYNC_KHR) {
1057 FrameCompletionThread::queueSync(sync);
1058 }
1059 }
1060
Mathias Agopian7db993a2012-03-25 00:49:46 -07001061 if (CC_UNLIKELY(dp->finishOnSwap)) {
1062 uint32_t pixel;
1063 egl_context_t * const c = get_context( egl_tls_t::getContext() );
1064 if (c) {
1065 // glReadPixels() ensures that the frame is complete
1066 s->cnx->hooks[c->version]->gl.glReadPixels(0,0,1,1,
1067 GL_RGBA,GL_UNSIGNED_BYTE,&pixel);
1068 }
1069 }
1070
Dan Stozaa894d082015-02-19 15:27:36 -08001071 if (n_rects == 0) {
1072 return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface);
1073 }
1074
1075 Vector<android_native_rect_t> androidRects;
1076 for (int r = 0; r < n_rects; ++r) {
1077 int offset = r * 4;
1078 int x = rects[offset];
1079 int y = rects[offset + 1];
1080 int width = rects[offset + 2];
1081 int height = rects[offset + 3];
1082 android_native_rect_t androidRect;
1083 androidRect.left = x;
1084 androidRect.top = y + height;
1085 androidRect.right = x + width;
1086 androidRect.bottom = y;
1087 androidRects.push_back(androidRect);
1088 }
1089 native_window_set_surface_damage(s->win.get(), androidRects.array(),
1090 androidRects.size());
1091
1092 if (s->cnx->egl.eglSwapBuffersWithDamageKHR) {
1093 return s->cnx->egl.eglSwapBuffersWithDamageKHR(dp->disp.dpy, s->surface,
1094 rects, n_rects);
1095 } else {
1096 return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface);
1097 }
1098}
1099
1100EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
1101{
1102 return eglSwapBuffersWithDamageKHR(dpy, surface, NULL, 0);
Mathias Agopian518ec112011-05-13 16:21:08 -07001103}
1104
1105EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface,
1106 NativePixmapType target)
1107{
1108 clearError();
1109
Jesse Hallb29e5e82012-04-04 16:53:42 -07001110 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001111 if (!dp) return EGL_FALSE;
1112
Jesse Hallb29e5e82012-04-04 16:53:42 -07001113 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001114 if (!_s.get())
1115 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001116
Mathias Agopian518ec112011-05-13 16:21:08 -07001117 egl_surface_t const * const s = get_surface(surface);
Mathias Agopianada798b2012-02-13 17:09:30 -08001118 return s->cnx->egl.eglCopyBuffers(dp->disp.dpy, s->surface, target);
Mathias Agopian518ec112011-05-13 16:21:08 -07001119}
1120
1121const char* eglQueryString(EGLDisplay dpy, EGLint name)
1122{
1123 clearError();
1124
Jesse Hallb29e5e82012-04-04 16:53:42 -07001125 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001126 if (!dp) return (const char *) NULL;
1127
1128 switch (name) {
1129 case EGL_VENDOR:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001130 return dp->getVendorString();
Mathias Agopian518ec112011-05-13 16:21:08 -07001131 case EGL_VERSION:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001132 return dp->getVersionString();
Mathias Agopian518ec112011-05-13 16:21:08 -07001133 case EGL_EXTENSIONS:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001134 return dp->getExtensionString();
Mathias Agopian518ec112011-05-13 16:21:08 -07001135 case EGL_CLIENT_APIS:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001136 return dp->getClientApiString();
Mathias Agopian518ec112011-05-13 16:21:08 -07001137 }
1138 return setError(EGL_BAD_PARAMETER, (const char *)0);
1139}
1140
Mathias Agopianca088332013-03-28 17:44:13 -07001141EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name)
1142{
1143 clearError();
1144
1145 const egl_display_ptr dp = validate_display(dpy);
1146 if (!dp) return (const char *) NULL;
1147
1148 switch (name) {
1149 case EGL_VENDOR:
1150 return dp->disp.queryString.vendor;
1151 case EGL_VERSION:
1152 return dp->disp.queryString.version;
1153 case EGL_EXTENSIONS:
1154 return dp->disp.queryString.extensions;
1155 case EGL_CLIENT_APIS:
1156 return dp->disp.queryString.clientApi;
1157 }
1158 return setError(EGL_BAD_PARAMETER, (const char *)0);
1159}
Mathias Agopian518ec112011-05-13 16:21:08 -07001160
1161// ----------------------------------------------------------------------------
1162// EGL 1.1
1163// ----------------------------------------------------------------------------
1164
1165EGLBoolean eglSurfaceAttrib(
1166 EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
1167{
1168 clearError();
1169
Jesse Hallb29e5e82012-04-04 16:53:42 -07001170 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001171 if (!dp) return EGL_FALSE;
1172
Jesse Hallb29e5e82012-04-04 16:53:42 -07001173 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001174 if (!_s.get())
1175 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001176
Mathias Agopian518ec112011-05-13 16:21:08 -07001177 egl_surface_t const * const s = get_surface(surface);
Pablo Ceballosccdfd602015-10-07 15:05:45 -07001178
Pablo Ceballos02b05da2016-02-02 17:53:18 -08001179 if (attribute == EGL_FRONT_BUFFER_AUTO_REFRESH_ANDROID) {
Pablo Ceballosf051ade2016-03-15 18:27:20 -07001180 int err = native_window_set_auto_refresh(s->win.get(),
1181 value ? true : false);
1182 return (err == NO_ERROR) ? EGL_TRUE :
1183 setError(EGL_BAD_SURFACE, EGL_FALSE);
Pablo Ceballosccdfd602015-10-07 15:05:45 -07001184 }
1185
Mathias Agopian518ec112011-05-13 16:21:08 -07001186 if (s->cnx->egl.eglSurfaceAttrib) {
1187 return s->cnx->egl.eglSurfaceAttrib(
Mathias Agopianada798b2012-02-13 17:09:30 -08001188 dp->disp.dpy, s->surface, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -07001189 }
1190 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1191}
1192
1193EGLBoolean eglBindTexImage(
1194 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1195{
1196 clearError();
1197
Jesse Hallb29e5e82012-04-04 16:53:42 -07001198 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001199 if (!dp) return EGL_FALSE;
1200
Jesse Hallb29e5e82012-04-04 16:53:42 -07001201 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001202 if (!_s.get())
1203 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001204
Mathias Agopian518ec112011-05-13 16:21:08 -07001205 egl_surface_t const * const s = get_surface(surface);
1206 if (s->cnx->egl.eglBindTexImage) {
1207 return s->cnx->egl.eglBindTexImage(
Mathias Agopianada798b2012-02-13 17:09:30 -08001208 dp->disp.dpy, s->surface, buffer);
Mathias Agopian518ec112011-05-13 16:21:08 -07001209 }
1210 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1211}
1212
1213EGLBoolean eglReleaseTexImage(
1214 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1215{
1216 clearError();
1217
Jesse Hallb29e5e82012-04-04 16:53:42 -07001218 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001219 if (!dp) return EGL_FALSE;
1220
Jesse Hallb29e5e82012-04-04 16:53:42 -07001221 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001222 if (!_s.get())
1223 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001224
Mathias Agopian518ec112011-05-13 16:21:08 -07001225 egl_surface_t const * const s = get_surface(surface);
1226 if (s->cnx->egl.eglReleaseTexImage) {
1227 return s->cnx->egl.eglReleaseTexImage(
Mathias Agopianada798b2012-02-13 17:09:30 -08001228 dp->disp.dpy, s->surface, buffer);
Mathias Agopian518ec112011-05-13 16:21:08 -07001229 }
1230 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1231}
1232
1233EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
1234{
1235 clearError();
1236
Jesse Hallb29e5e82012-04-04 16:53:42 -07001237 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001238 if (!dp) return EGL_FALSE;
1239
1240 EGLBoolean res = EGL_TRUE;
Mathias Agopianada798b2012-02-13 17:09:30 -08001241 egl_connection_t* const cnx = &gEGLImpl;
1242 if (cnx->dso && cnx->egl.eglSwapInterval) {
1243 res = cnx->egl.eglSwapInterval(dp->disp.dpy, interval);
Mathias Agopian518ec112011-05-13 16:21:08 -07001244 }
Mathias Agopianada798b2012-02-13 17:09:30 -08001245
Mathias Agopian518ec112011-05-13 16:21:08 -07001246 return res;
1247}
1248
1249
1250// ----------------------------------------------------------------------------
1251// EGL 1.2
1252// ----------------------------------------------------------------------------
1253
1254EGLBoolean eglWaitClient(void)
1255{
1256 clearError();
1257
Mathias Agopianada798b2012-02-13 17:09:30 -08001258 egl_connection_t* const cnx = &gEGLImpl;
1259 if (!cnx->dso)
1260 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1261
1262 EGLBoolean res;
1263 if (cnx->egl.eglWaitClient) {
1264 res = cnx->egl.eglWaitClient();
1265 } else {
1266 res = cnx->egl.eglWaitGL();
Mathias Agopian518ec112011-05-13 16:21:08 -07001267 }
1268 return res;
1269}
1270
1271EGLBoolean eglBindAPI(EGLenum api)
1272{
1273 clearError();
1274
1275 if (egl_init_drivers() == EGL_FALSE) {
1276 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1277 }
1278
1279 // bind this API on all EGLs
1280 EGLBoolean res = EGL_TRUE;
Mathias Agopianada798b2012-02-13 17:09:30 -08001281 egl_connection_t* const cnx = &gEGLImpl;
1282 if (cnx->dso && cnx->egl.eglBindAPI) {
1283 res = cnx->egl.eglBindAPI(api);
Mathias Agopian518ec112011-05-13 16:21:08 -07001284 }
1285 return res;
1286}
1287
1288EGLenum eglQueryAPI(void)
1289{
1290 clearError();
1291
1292 if (egl_init_drivers() == EGL_FALSE) {
1293 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1294 }
1295
Mathias Agopianada798b2012-02-13 17:09:30 -08001296 egl_connection_t* const cnx = &gEGLImpl;
1297 if (cnx->dso && cnx->egl.eglQueryAPI) {
1298 return cnx->egl.eglQueryAPI();
Mathias Agopian518ec112011-05-13 16:21:08 -07001299 }
Mathias Agopianada798b2012-02-13 17:09:30 -08001300
Mathias Agopian518ec112011-05-13 16:21:08 -07001301 // or, it can only be OpenGL ES
1302 return EGL_OPENGL_ES_API;
1303}
1304
1305EGLBoolean eglReleaseThread(void)
1306{
1307 clearError();
1308
Mathias Agopianada798b2012-02-13 17:09:30 -08001309 egl_connection_t* const cnx = &gEGLImpl;
1310 if (cnx->dso && cnx->egl.eglReleaseThread) {
1311 cnx->egl.eglReleaseThread();
Mathias Agopian518ec112011-05-13 16:21:08 -07001312 }
Sai Kiran Korwar3ac517a2014-01-31 21:15:07 +05301313
1314 // If there is context bound to the thread, release it
1315 egl_display_t::loseCurrent(get_context(getContext()));
1316
Mathias Agopian518ec112011-05-13 16:21:08 -07001317 egl_tls_t::clearTLS();
Mathias Agopian518ec112011-05-13 16:21:08 -07001318 return EGL_TRUE;
1319}
1320
1321EGLSurface eglCreatePbufferFromClientBuffer(
1322 EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer,
1323 EGLConfig config, const EGLint *attrib_list)
1324{
1325 clearError();
1326
Jesse Hallb29e5e82012-04-04 16:53:42 -07001327 egl_connection_t* cnx = NULL;
1328 const egl_display_ptr dp = validate_display_connection(dpy, cnx);
1329 if (!dp) return EGL_FALSE;
Mathias Agopian518ec112011-05-13 16:21:08 -07001330 if (cnx->egl.eglCreatePbufferFromClientBuffer) {
1331 return cnx->egl.eglCreatePbufferFromClientBuffer(
Mathias Agopian7773c432012-02-13 20:06:08 -08001332 dp->disp.dpy, buftype, buffer, config, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001333 }
1334 return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE);
1335}
1336
1337// ----------------------------------------------------------------------------
1338// EGL_EGLEXT_VERSION 3
1339// ----------------------------------------------------------------------------
1340
1341EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface,
1342 const EGLint *attrib_list)
1343{
1344 clearError();
1345
Jesse Hallb29e5e82012-04-04 16:53:42 -07001346 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001347 if (!dp) return EGL_FALSE;
1348
Jesse Hallb29e5e82012-04-04 16:53:42 -07001349 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001350 if (!_s.get())
1351 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001352
1353 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian518ec112011-05-13 16:21:08 -07001354 if (s->cnx->egl.eglLockSurfaceKHR) {
1355 return s->cnx->egl.eglLockSurfaceKHR(
Mathias Agopianada798b2012-02-13 17:09:30 -08001356 dp->disp.dpy, s->surface, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001357 }
1358 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1359}
1360
1361EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface)
1362{
1363 clearError();
1364
Jesse Hallb29e5e82012-04-04 16:53:42 -07001365 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001366 if (!dp) return EGL_FALSE;
1367
Jesse Hallb29e5e82012-04-04 16:53:42 -07001368 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001369 if (!_s.get())
1370 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001371
1372 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian518ec112011-05-13 16:21:08 -07001373 if (s->cnx->egl.eglUnlockSurfaceKHR) {
Mathias Agopianada798b2012-02-13 17:09:30 -08001374 return s->cnx->egl.eglUnlockSurfaceKHR(dp->disp.dpy, s->surface);
Mathias Agopian518ec112011-05-13 16:21:08 -07001375 }
1376 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1377}
1378
1379EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
1380 EGLClientBuffer buffer, const EGLint *attrib_list)
1381{
1382 clearError();
1383
Jesse Hallb29e5e82012-04-04 16:53:42 -07001384 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001385 if (!dp) return EGL_NO_IMAGE_KHR;
1386
Jesse Hallb29e5e82012-04-04 16:53:42 -07001387 ContextRef _c(dp.get(), ctx);
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001388 egl_context_t * const c = _c.get();
Mathias Agopian518ec112011-05-13 16:21:08 -07001389
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001390 EGLImageKHR result = EGL_NO_IMAGE_KHR;
1391 egl_connection_t* const cnx = &gEGLImpl;
1392 if (cnx->dso && cnx->egl.eglCreateImageKHR) {
1393 result = cnx->egl.eglCreateImageKHR(
1394 dp->disp.dpy,
1395 c ? c->context : EGL_NO_CONTEXT,
1396 target, buffer, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001397 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001398 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001399}
1400
1401EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
1402{
1403 clearError();
1404
Jesse Hallb29e5e82012-04-04 16:53:42 -07001405 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001406 if (!dp) return EGL_FALSE;
1407
Steven Holte646a5c52012-06-04 20:02:11 -07001408 EGLBoolean result = EGL_FALSE;
Mathias Agopianada798b2012-02-13 17:09:30 -08001409 egl_connection_t* const cnx = &gEGLImpl;
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001410 if (cnx->dso && cnx->egl.eglDestroyImageKHR) {
Steven Holte646a5c52012-06-04 20:02:11 -07001411 result = cnx->egl.eglDestroyImageKHR(dp->disp.dpy, img);
Mathias Agopian518ec112011-05-13 16:21:08 -07001412 }
Steven Holte646a5c52012-06-04 20:02:11 -07001413 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001414}
1415
1416// ----------------------------------------------------------------------------
1417// EGL_EGLEXT_VERSION 5
1418// ----------------------------------------------------------------------------
1419
1420
1421EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
1422{
1423 clearError();
1424
Jesse Hallb29e5e82012-04-04 16:53:42 -07001425 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001426 if (!dp) return EGL_NO_SYNC_KHR;
1427
Mathias Agopian518ec112011-05-13 16:21:08 -07001428 EGLSyncKHR result = EGL_NO_SYNC_KHR;
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001429 egl_connection_t* const cnx = &gEGLImpl;
1430 if (cnx->dso && cnx->egl.eglCreateSyncKHR) {
1431 result = cnx->egl.eglCreateSyncKHR(dp->disp.dpy, type, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001432 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001433 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001434}
1435
1436EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
1437{
1438 clearError();
1439
Jesse Hallb29e5e82012-04-04 16:53:42 -07001440 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001441 if (!dp) return EGL_FALSE;
1442
Mathias Agopian518ec112011-05-13 16:21:08 -07001443 EGLBoolean result = EGL_FALSE;
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001444 egl_connection_t* const cnx = &gEGLImpl;
1445 if (cnx->dso && cnx->egl.eglDestroySyncKHR) {
1446 result = cnx->egl.eglDestroySyncKHR(dp->disp.dpy, sync);
Mathias Agopian518ec112011-05-13 16:21:08 -07001447 }
1448 return result;
1449}
1450
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -07001451EGLBoolean eglSignalSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode) {
1452 clearError();
1453
1454 const egl_display_ptr dp = validate_display(dpy);
1455 if (!dp) return EGL_FALSE;
1456
1457 EGLBoolean result = EGL_FALSE;
1458 egl_connection_t* const cnx = &gEGLImpl;
1459 if (cnx->dso && cnx->egl.eglSignalSyncKHR) {
1460 result = cnx->egl.eglSignalSyncKHR(
1461 dp->disp.dpy, sync, mode);
1462 }
1463 return result;
1464}
1465
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001466EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync,
1467 EGLint flags, EGLTimeKHR timeout)
Mathias Agopian518ec112011-05-13 16:21:08 -07001468{
1469 clearError();
1470
Jesse Hallb29e5e82012-04-04 16:53:42 -07001471 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001472 if (!dp) return EGL_FALSE;
1473
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001474 EGLBoolean result = EGL_FALSE;
1475 egl_connection_t* const cnx = &gEGLImpl;
1476 if (cnx->dso && cnx->egl.eglClientWaitSyncKHR) {
1477 result = cnx->egl.eglClientWaitSyncKHR(
1478 dp->disp.dpy, sync, flags, timeout);
Mathias Agopian518ec112011-05-13 16:21:08 -07001479 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001480 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001481}
1482
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001483EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync,
1484 EGLint attribute, EGLint *value)
Mathias Agopian518ec112011-05-13 16:21:08 -07001485{
1486 clearError();
1487
Jesse Hallb29e5e82012-04-04 16:53:42 -07001488 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001489 if (!dp) return EGL_FALSE;
1490
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001491 EGLBoolean result = EGL_FALSE;
1492 egl_connection_t* const cnx = &gEGLImpl;
1493 if (cnx->dso && cnx->egl.eglGetSyncAttribKHR) {
1494 result = cnx->egl.eglGetSyncAttribKHR(
1495 dp->disp.dpy, sync, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -07001496 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001497 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001498}
1499
Season Li000d88f2015-07-01 11:39:40 -07001500EGLStreamKHR eglCreateStreamKHR(EGLDisplay dpy, const EGLint *attrib_list)
1501{
1502 clearError();
1503
1504 const egl_display_ptr dp = validate_display(dpy);
1505 if (!dp) return EGL_NO_STREAM_KHR;
1506
1507 EGLStreamKHR result = EGL_NO_STREAM_KHR;
1508 egl_connection_t* const cnx = &gEGLImpl;
1509 if (cnx->dso && cnx->egl.eglCreateStreamKHR) {
1510 result = cnx->egl.eglCreateStreamKHR(
1511 dp->disp.dpy, attrib_list);
1512 }
1513 return result;
1514}
1515
1516EGLBoolean eglDestroyStreamKHR(EGLDisplay dpy, EGLStreamKHR stream)
1517{
1518 clearError();
1519
1520 const egl_display_ptr dp = validate_display(dpy);
1521 if (!dp) return EGL_FALSE;
1522
1523 EGLBoolean result = EGL_FALSE;
1524 egl_connection_t* const cnx = &gEGLImpl;
1525 if (cnx->dso && cnx->egl.eglDestroyStreamKHR) {
1526 result = cnx->egl.eglDestroyStreamKHR(
1527 dp->disp.dpy, stream);
1528 }
1529 return result;
1530}
1531
1532EGLBoolean eglStreamAttribKHR(EGLDisplay dpy, EGLStreamKHR stream,
1533 EGLenum attribute, EGLint value)
1534{
1535 clearError();
1536
1537 const egl_display_ptr dp = validate_display(dpy);
1538 if (!dp) return EGL_FALSE;
1539
1540 EGLBoolean result = EGL_FALSE;
1541 egl_connection_t* const cnx = &gEGLImpl;
1542 if (cnx->dso && cnx->egl.eglStreamAttribKHR) {
1543 result = cnx->egl.eglStreamAttribKHR(
1544 dp->disp.dpy, stream, attribute, value);
1545 }
1546 return result;
1547}
1548
1549EGLBoolean eglQueryStreamKHR(EGLDisplay dpy, EGLStreamKHR stream,
1550 EGLenum attribute, EGLint *value)
1551{
1552 clearError();
1553
1554 const egl_display_ptr dp = validate_display(dpy);
1555 if (!dp) return EGL_FALSE;
1556
1557 EGLBoolean result = EGL_FALSE;
1558 egl_connection_t* const cnx = &gEGLImpl;
1559 if (cnx->dso && cnx->egl.eglQueryStreamKHR) {
1560 result = cnx->egl.eglQueryStreamKHR(
1561 dp->disp.dpy, stream, attribute, value);
1562 }
1563 return result;
1564}
1565
1566EGLBoolean eglQueryStreamu64KHR(EGLDisplay dpy, EGLStreamKHR stream,
1567 EGLenum attribute, EGLuint64KHR *value)
1568{
1569 clearError();
1570
1571 const egl_display_ptr dp = validate_display(dpy);
1572 if (!dp) return EGL_FALSE;
1573
1574 EGLBoolean result = EGL_FALSE;
1575 egl_connection_t* const cnx = &gEGLImpl;
1576 if (cnx->dso && cnx->egl.eglQueryStreamu64KHR) {
1577 result = cnx->egl.eglQueryStreamu64KHR(
1578 dp->disp.dpy, stream, attribute, value);
1579 }
1580 return result;
1581}
1582
1583EGLBoolean eglQueryStreamTimeKHR(EGLDisplay dpy, EGLStreamKHR stream,
1584 EGLenum attribute, EGLTimeKHR *value)
1585{
1586 clearError();
1587
1588 const egl_display_ptr dp = validate_display(dpy);
1589 if (!dp) return EGL_FALSE;
1590
1591 EGLBoolean result = EGL_FALSE;
1592 egl_connection_t* const cnx = &gEGLImpl;
1593 if (cnx->dso && cnx->egl.eglQueryStreamTimeKHR) {
1594 result = cnx->egl.eglQueryStreamTimeKHR(
1595 dp->disp.dpy, stream, attribute, value);
1596 }
1597 return result;
1598}
1599
1600EGLSurface eglCreateStreamProducerSurfaceKHR(EGLDisplay dpy, EGLConfig config,
1601 EGLStreamKHR stream, const EGLint *attrib_list)
1602{
1603 clearError();
1604
1605 egl_display_ptr dp = validate_display(dpy);
1606 if (!dp) return EGL_NO_SURFACE;
1607
1608 egl_connection_t* const cnx = &gEGLImpl;
1609 if (cnx->dso && cnx->egl.eglCreateStreamProducerSurfaceKHR) {
1610 EGLSurface surface = cnx->egl.eglCreateStreamProducerSurfaceKHR(
1611 dp->disp.dpy, config, stream, attrib_list);
1612 if (surface != EGL_NO_SURFACE) {
1613 egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL,
1614 surface, cnx);
1615 return s;
1616 }
1617 }
1618 return EGL_NO_SURFACE;
1619}
1620
1621EGLBoolean eglStreamConsumerGLTextureExternalKHR(EGLDisplay dpy,
1622 EGLStreamKHR stream)
1623{
1624 clearError();
1625
1626 const egl_display_ptr dp = validate_display(dpy);
1627 if (!dp) return EGL_FALSE;
1628
1629 EGLBoolean result = EGL_FALSE;
1630 egl_connection_t* const cnx = &gEGLImpl;
1631 if (cnx->dso && cnx->egl.eglStreamConsumerGLTextureExternalKHR) {
1632 result = cnx->egl.eglStreamConsumerGLTextureExternalKHR(
1633 dp->disp.dpy, stream);
1634 }
1635 return result;
1636}
1637
1638EGLBoolean eglStreamConsumerAcquireKHR(EGLDisplay dpy,
1639 EGLStreamKHR stream)
1640{
1641 clearError();
1642
1643 const egl_display_ptr dp = validate_display(dpy);
1644 if (!dp) return EGL_FALSE;
1645
1646 EGLBoolean result = EGL_FALSE;
1647 egl_connection_t* const cnx = &gEGLImpl;
1648 if (cnx->dso && cnx->egl.eglStreamConsumerAcquireKHR) {
1649 result = cnx->egl.eglStreamConsumerAcquireKHR(
1650 dp->disp.dpy, stream);
1651 }
1652 return result;
1653}
1654
1655EGLBoolean eglStreamConsumerReleaseKHR(EGLDisplay dpy,
1656 EGLStreamKHR stream)
1657{
1658 clearError();
1659
1660 const egl_display_ptr dp = validate_display(dpy);
1661 if (!dp) return EGL_FALSE;
1662
1663 EGLBoolean result = EGL_FALSE;
1664 egl_connection_t* const cnx = &gEGLImpl;
1665 if (cnx->dso && cnx->egl.eglStreamConsumerReleaseKHR) {
1666 result = cnx->egl.eglStreamConsumerReleaseKHR(
1667 dp->disp.dpy, stream);
1668 }
1669 return result;
1670}
1671
1672EGLNativeFileDescriptorKHR eglGetStreamFileDescriptorKHR(
1673 EGLDisplay dpy, EGLStreamKHR stream)
1674{
1675 clearError();
1676
1677 const egl_display_ptr dp = validate_display(dpy);
1678 if (!dp) return EGL_NO_FILE_DESCRIPTOR_KHR;
1679
1680 EGLNativeFileDescriptorKHR result = EGL_NO_FILE_DESCRIPTOR_KHR;
1681 egl_connection_t* const cnx = &gEGLImpl;
1682 if (cnx->dso && cnx->egl.eglGetStreamFileDescriptorKHR) {
1683 result = cnx->egl.eglGetStreamFileDescriptorKHR(
1684 dp->disp.dpy, stream);
1685 }
1686 return result;
1687}
1688
1689EGLStreamKHR eglCreateStreamFromFileDescriptorKHR(
1690 EGLDisplay dpy, EGLNativeFileDescriptorKHR file_descriptor)
1691{
1692 clearError();
1693
1694 const egl_display_ptr dp = validate_display(dpy);
1695 if (!dp) return EGL_NO_STREAM_KHR;
1696
1697 EGLStreamKHR result = EGL_NO_STREAM_KHR;
1698 egl_connection_t* const cnx = &gEGLImpl;
1699 if (cnx->dso && cnx->egl.eglCreateStreamFromFileDescriptorKHR) {
1700 result = cnx->egl.eglCreateStreamFromFileDescriptorKHR(
1701 dp->disp.dpy, file_descriptor);
1702 }
1703 return result;
1704}
1705
Mathias Agopian518ec112011-05-13 16:21:08 -07001706// ----------------------------------------------------------------------------
Mathias Agopian2bb71682013-03-27 17:32:41 -07001707// EGL_EGLEXT_VERSION 15
1708// ----------------------------------------------------------------------------
1709
1710EGLint eglWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags) {
1711 clearError();
1712 const egl_display_ptr dp = validate_display(dpy);
1713 if (!dp) return EGL_FALSE;
1714 EGLint result = EGL_FALSE;
1715 egl_connection_t* const cnx = &gEGLImpl;
1716 if (cnx->dso && cnx->egl.eglWaitSyncKHR) {
1717 result = cnx->egl.eglWaitSyncKHR(dp->disp.dpy, sync, flags);
1718 }
1719 return result;
1720}
1721
1722// ----------------------------------------------------------------------------
Mathias Agopian518ec112011-05-13 16:21:08 -07001723// ANDROID extensions
1724// ----------------------------------------------------------------------------
1725
Jamie Gennis331841b2012-09-06 14:52:00 -07001726EGLint eglDupNativeFenceFDANDROID(EGLDisplay dpy, EGLSyncKHR sync)
1727{
1728 clearError();
1729
1730 const egl_display_ptr dp = validate_display(dpy);
1731 if (!dp) return EGL_NO_NATIVE_FENCE_FD_ANDROID;
1732
1733 EGLint result = EGL_NO_NATIVE_FENCE_FD_ANDROID;
1734 egl_connection_t* const cnx = &gEGLImpl;
1735 if (cnx->dso && cnx->egl.eglDupNativeFenceFDANDROID) {
1736 result = cnx->egl.eglDupNativeFenceFDANDROID(dp->disp.dpy, sync);
1737 }
1738 return result;
1739}
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001740
Andy McFadden72841452013-03-01 16:25:32 -08001741EGLBoolean eglPresentationTimeANDROID(EGLDisplay dpy, EGLSurface surface,
1742 EGLnsecsANDROID time)
1743{
1744 clearError();
1745
1746 const egl_display_ptr dp = validate_display(dpy);
1747 if (!dp) {
1748 return EGL_FALSE;
1749 }
1750
1751 SurfaceRef _s(dp.get(), surface);
1752 if (!_s.get()) {
1753 setError(EGL_BAD_SURFACE, EGL_FALSE);
1754 return EGL_FALSE;
1755 }
1756
1757 egl_surface_t const * const s = get_surface(surface);
1758 native_window_set_buffers_timestamp(s->win.get(), time);
1759
1760 return EGL_TRUE;
1761}
1762
Craig Donner05249fc2016-01-15 19:33:55 -08001763EGLClientBuffer eglCreateNativeClientBufferANDROID(const EGLint *attrib_list)
1764{
1765 clearError();
1766
1767 int usage = 0;
1768 uint32_t width = 0;
1769 uint32_t height = 0;
1770 uint32_t format = 0;
1771 uint32_t red_size = 0;
1772 uint32_t green_size = 0;
1773 uint32_t blue_size = 0;
1774 uint32_t alpha_size = 0;
1775
Craig Donnerb40504a2016-06-03 17:54:25 -07001776#define GET_NONNEGATIVE_VALUE(case_name, target) \
Craig Donner05249fc2016-01-15 19:33:55 -08001777 case case_name: \
Craig Donnerb40504a2016-06-03 17:54:25 -07001778 if (value >= 0) { \
Craig Donner05249fc2016-01-15 19:33:55 -08001779 target = value; \
1780 } else { \
1781 return setError(EGL_BAD_PARAMETER, (EGLClientBuffer)0); \
1782 } \
1783 break
1784
1785 if (attrib_list) {
1786 while (*attrib_list != EGL_NONE) {
1787 GLint attr = *attrib_list++;
1788 GLint value = *attrib_list++;
1789 switch (attr) {
Craig Donnerb40504a2016-06-03 17:54:25 -07001790 GET_NONNEGATIVE_VALUE(EGL_WIDTH, width);
1791 GET_NONNEGATIVE_VALUE(EGL_HEIGHT, height);
1792 GET_NONNEGATIVE_VALUE(EGL_RED_SIZE, red_size);
1793 GET_NONNEGATIVE_VALUE(EGL_GREEN_SIZE, green_size);
1794 GET_NONNEGATIVE_VALUE(EGL_BLUE_SIZE, blue_size);
1795 GET_NONNEGATIVE_VALUE(EGL_ALPHA_SIZE, alpha_size);
Craig Donner05249fc2016-01-15 19:33:55 -08001796 case EGL_NATIVE_BUFFER_USAGE_ANDROID:
1797 if (value & EGL_NATIVE_BUFFER_USAGE_PROTECTED_BIT_ANDROID) {
1798 usage |= GRALLOC_USAGE_PROTECTED;
Craig Donner05249fc2016-01-15 19:33:55 -08001799 }
Craig Donner8cfae6d2016-04-12 16:54:03 -07001800 if (value & EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_BIT_ANDROID) {
Craig Donner05249fc2016-01-15 19:33:55 -08001801 usage |= GRALLOC_USAGE_HW_RENDER;
1802 }
Craig Donner8cfae6d2016-04-12 16:54:03 -07001803 if (value & EGL_NATIVE_BUFFER_USAGE_TEXTURE_BIT_ANDROID) {
Craig Donner05249fc2016-01-15 19:33:55 -08001804 usage |= GRALLOC_USAGE_HW_TEXTURE;
1805 }
1806 // The buffer must be used for either a texture or a
1807 // renderbuffer.
Craig Donner8cfae6d2016-04-12 16:54:03 -07001808 if ((value & EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_BIT_ANDROID) &&
1809 (value & EGL_NATIVE_BUFFER_USAGE_TEXTURE_BIT_ANDROID)) {
Craig Donner05249fc2016-01-15 19:33:55 -08001810 return setError(EGL_BAD_PARAMETER, (EGLClientBuffer)0);
1811 }
1812 break;
1813 default:
1814 return setError(EGL_BAD_PARAMETER, (EGLClientBuffer)0);
1815 }
1816 }
1817 }
Craig Donnerb40504a2016-06-03 17:54:25 -07001818#undef GET_NONNEGATIVE_VALUE
Craig Donner05249fc2016-01-15 19:33:55 -08001819
1820 // Validate format.
1821 if (red_size == 8 && green_size == 8 && blue_size == 8) {
1822 if (alpha_size == 8) {
1823 format = HAL_PIXEL_FORMAT_RGBA_8888;
1824 } else {
1825 format = HAL_PIXEL_FORMAT_RGB_888;
1826 }
1827 } else if (red_size == 5 && green_size == 6 && blue_size == 5 &&
1828 alpha_size == 0) {
Craig Donner478f7db2016-06-10 17:20:15 -07001829 format = HAL_PIXEL_FORMAT_RGB_565;
Craig Donner05249fc2016-01-15 19:33:55 -08001830 } else {
1831 ALOGE("Invalid native pixel format { r=%d, g=%d, b=%d, a=%d }",
1832 red_size, green_size, blue_size, alpha_size);
1833 return setError(EGL_BAD_PARAMETER, (EGLClientBuffer)0);
1834 }
1835
1836 GraphicBuffer* gBuffer = new GraphicBuffer(width, height, format, usage);
1837 const status_t err = gBuffer->initCheck();
1838 if (err != NO_ERROR) {
1839 ALOGE("Unable to create native buffer { w=%d, h=%d, f=%d, u=%#x }: %#x",
1840 width, height, format, usage, err);
1841 // Destroy the buffer.
1842 sp<GraphicBuffer> holder(gBuffer);
1843 return setError(EGL_BAD_ALLOC, (EGLClientBuffer)0);
1844 }
1845 ALOGD("Created new native buffer %p { w=%d, h=%d, f=%d, u=%#x }",
1846 gBuffer, width, height, format, usage);
1847 return static_cast<EGLClientBuffer>(gBuffer->getNativeBuffer());
1848}
1849
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001850// ----------------------------------------------------------------------------
1851// NVIDIA extensions
1852// ----------------------------------------------------------------------------
1853EGLuint64NV eglGetSystemTimeFrequencyNV()
1854{
1855 clearError();
1856
1857 if (egl_init_drivers() == EGL_FALSE) {
1858 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1859 }
1860
1861 EGLuint64NV ret = 0;
Mathias Agopianada798b2012-02-13 17:09:30 -08001862 egl_connection_t* const cnx = &gEGLImpl;
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001863
Mathias Agopianada798b2012-02-13 17:09:30 -08001864 if (cnx->dso && cnx->egl.eglGetSystemTimeFrequencyNV) {
1865 return cnx->egl.eglGetSystemTimeFrequencyNV();
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001866 }
1867
Mathias Agopian0e8bbee2011-10-05 19:15:05 -07001868 return setErrorQuiet(EGL_BAD_DISPLAY, 0);
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001869}
1870
1871EGLuint64NV eglGetSystemTimeNV()
1872{
1873 clearError();
1874
1875 if (egl_init_drivers() == EGL_FALSE) {
1876 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1877 }
1878
1879 EGLuint64NV ret = 0;
Mathias Agopianada798b2012-02-13 17:09:30 -08001880 egl_connection_t* const cnx = &gEGLImpl;
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001881
Mathias Agopianada798b2012-02-13 17:09:30 -08001882 if (cnx->dso && cnx->egl.eglGetSystemTimeNV) {
1883 return cnx->egl.eglGetSystemTimeNV();
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001884 }
1885
Mathias Agopian0e8bbee2011-10-05 19:15:05 -07001886 return setErrorQuiet(EGL_BAD_DISPLAY, 0);
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001887}
Dan Stozaa894d082015-02-19 15:27:36 -08001888
1889// ----------------------------------------------------------------------------
1890// Partial update extension
1891// ----------------------------------------------------------------------------
1892EGLBoolean eglSetDamageRegionKHR(EGLDisplay dpy, EGLSurface surface,
1893 EGLint *rects, EGLint n_rects)
1894{
1895 clearError();
1896
1897 const egl_display_ptr dp = validate_display(dpy);
1898 if (!dp) {
1899 setError(EGL_BAD_DISPLAY, EGL_FALSE);
1900 return EGL_FALSE;
1901 }
1902
1903 SurfaceRef _s(dp.get(), surface);
1904 if (!_s.get()) {
1905 setError(EGL_BAD_SURFACE, EGL_FALSE);
1906 return EGL_FALSE;
1907 }
1908
1909 egl_surface_t const * const s = get_surface(surface);
1910 if (s->cnx->egl.eglSetDamageRegionKHR) {
1911 return s->cnx->egl.eglSetDamageRegionKHR(dp->disp.dpy, s->surface,
1912 rects, n_rects);
1913 }
1914
1915 return EGL_FALSE;
1916}