blob: df639cdbbe02e353dba23a274b948e6d543b953f [file] [log] [blame]
Jesse Hall47743382013-02-08 11:13:46 -08001/*
Mathias Agopian518ec112011-05-13 16:21:08 -07002 ** Copyright 2007, The Android Open Source Project
3 **
Jesse Hall47743382013-02-08 11:13:46 -08004 ** Licensed under the Apache License, Version 2.0 (the "License");
5 ** you may not use this file except in compliance with the License.
6 ** You may obtain a copy of the License at
Mathias Agopian518ec112011-05-13 16:21:08 -07007 **
Jesse Hall47743382013-02-08 11:13:46 -08008 ** http://www.apache.org/licenses/LICENSE-2.0
Mathias Agopian518ec112011-05-13 16:21:08 -07009 **
Jesse Hall47743382013-02-08 11:13:46 -080010 ** Unless required by applicable law or agreed to in writing, software
11 ** distributed under the License is distributed on an "AS IS" BASIS,
12 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 ** See the License for the specific language governing permissions and
Mathias Agopian518ec112011-05-13 16:21:08 -070014 ** limitations under the License.
15 */
16
Jamie Gennis1c8e95c2012-02-23 19:27:23 -080017#define ATRACE_TAG ATRACE_TAG_GRAPHICS
18
Jesse Hallc07b5202013-07-04 12:08:16 -070019#include <dlfcn.h>
Mathias Agopian518ec112011-05-13 16:21:08 -070020#include <ctype.h>
21#include <stdlib.h>
22#include <string.h>
23
24#include <hardware/gralloc.h>
25#include <system/window.h>
26
27#include <EGL/egl.h>
28#include <EGL/eglext.h>
Mathias Agopian518ec112011-05-13 16:21:08 -070029
30#include <cutils/log.h>
31#include <cutils/atomic.h>
Mathias Agopian7db993a2012-03-25 00:49:46 -070032#include <cutils/compiler.h>
Mathias Agopian518ec112011-05-13 16:21:08 -070033#include <cutils/properties.h>
34#include <cutils/memory.h>
35
Craig Donner05249fc2016-01-15 19:33:55 -080036#include <ui/GraphicBuffer.h>
37
Mathias Agopian518ec112011-05-13 16:21:08 -070038#include <utils/KeyedVector.h>
39#include <utils/SortedVector.h>
40#include <utils/String8.h>
Jamie Gennis1c8e95c2012-02-23 19:27:23 -080041#include <utils/Trace.h>
Mathias Agopian518ec112011-05-13 16:21:08 -070042
Mathias Agopian39c24a22013-04-04 23:17:56 -070043#include "../egl_impl.h"
Mathias Agopian39c24a22013-04-04 23:17:56 -070044#include "../hooks.h"
Mathias Agopian518ec112011-05-13 16:21:08 -070045
46#include "egl_display.h"
Mathias Agopian518ec112011-05-13 16:21:08 -070047#include "egl_object.h"
48#include "egl_tls.h"
Mathias Agopianada798b2012-02-13 17:09:30 -080049#include "egldefs.h"
Mathias Agopian518ec112011-05-13 16:21:08 -070050
51using namespace android;
52
Jesse Halla2ba4282013-09-14 21:00:14 -070053// This extension has not been ratified yet, so can't be shipped.
54// Implementation is incomplete and untested.
55#define ENABLE_EGL_KHR_GL_COLORSPACE 0
56
Mathias Agopian518ec112011-05-13 16:21:08 -070057// ----------------------------------------------------------------------------
58
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070059namespace android {
60
Mathias Agopian518ec112011-05-13 16:21:08 -070061struct extention_map_t {
62 const char* name;
63 __eglMustCastToProperFunctionPointerType address;
64};
65
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070066/*
Jesse Hall21558da2013-08-06 15:31:22 -070067 * This is the list of EGL extensions exposed to applications.
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070068 *
Jesse Hall21558da2013-08-06 15:31:22 -070069 * Some of them (gBuiltinExtensionString) are implemented entirely in this EGL
70 * wrapper and are always available.
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070071 *
Jesse Hall21558da2013-08-06 15:31:22 -070072 * The rest (gExtensionString) depend on support in the EGL driver, and are
73 * only available if the driver supports them. However, some of these must be
74 * supported because they are used by the Android system itself; these are
Pablo Ceballos02b05da2016-02-02 17:53:18 -080075 * listed as mandatory below and are required by the CDD. The system *assumes*
Jesse Hall21558da2013-08-06 15:31:22 -070076 * the mandatory extensions are present and may not function properly if some
77 * are missing.
78 *
79 * NOTE: Both strings MUST have a single space as the last character.
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070080 */
Jesse Hall21558da2013-08-06 15:31:22 -070081extern char const * const gBuiltinExtensionString =
82 "EGL_KHR_get_all_proc_addresses "
83 "EGL_ANDROID_presentation_time "
Dan Stozaa894d082015-02-19 15:27:36 -080084 "EGL_KHR_swap_buffers_with_damage "
Craig Donner05249fc2016-01-15 19:33:55 -080085 "EGL_ANDROID_create_native_client_buffer "
Pablo Ceballos02b05da2016-02-02 17:53:18 -080086 "EGL_ANDROID_front_buffer_auto_refresh "
Jesse Hall21558da2013-08-06 15:31:22 -070087 ;
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070088extern char const * const gExtensionString =
89 "EGL_KHR_image " // mandatory
90 "EGL_KHR_image_base " // mandatory
91 "EGL_KHR_image_pixmap "
92 "EGL_KHR_lock_surface "
Jesse Halla2ba4282013-09-14 21:00:14 -070093#if (ENABLE_EGL_KHR_GL_COLORSPACE != 0)
Jesse Hallc2e41222013-08-08 13:40:22 -070094 "EGL_KHR_gl_colorspace "
Jesse Halla2ba4282013-09-14 21:00:14 -070095#endif
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070096 "EGL_KHR_gl_texture_2D_image "
Season Li000d88f2015-07-01 11:39:40 -070097 "EGL_KHR_gl_texture_3D_image "
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070098 "EGL_KHR_gl_texture_cubemap_image "
99 "EGL_KHR_gl_renderbuffer_image "
100 "EGL_KHR_reusable_sync "
101 "EGL_KHR_fence_sync "
Jamie Gennisf6d1c392013-04-25 18:48:41 -0700102 "EGL_KHR_create_context "
Season Li000d88f2015-07-01 11:39:40 -0700103 "EGL_KHR_config_attribs "
104 "EGL_KHR_surfaceless_context "
105 "EGL_KHR_stream "
106 "EGL_KHR_stream_fifo "
107 "EGL_KHR_stream_producer_eglsurface "
108 "EGL_KHR_stream_consumer_gltexture "
109 "EGL_KHR_stream_cross_process_fd "
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700110 "EGL_EXT_create_context_robustness "
111 "EGL_NV_system_time "
112 "EGL_ANDROID_image_native_buffer " // mandatory
Mathias Agopian2bb71682013-03-27 17:32:41 -0700113 "EGL_KHR_wait_sync " // strongly recommended
Jamie Gennisdbe92452013-09-23 17:22:10 -0700114 "EGL_ANDROID_recordable " // mandatory
Dan Stozaa894d082015-02-19 15:27:36 -0800115 "EGL_KHR_partial_update " // strongly recommended
116 "EGL_EXT_buffer_age " // strongly recommended with partial_update
Jesse Hall408e59f2015-04-24 01:40:42 -0700117 "EGL_KHR_create_context_no_error "
Pablo Ceballosceb9ee72016-04-13 11:17:32 -0700118 "EGL_KHR_mutable_render_buffer "
Mika Isojärvif37864b2016-04-15 11:58:56 -0700119 "EGL_EXT_yuv_surface "
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700120 ;
121
122// extensions not exposed to applications but used by the ANDROID system
123// "EGL_ANDROID_blob_cache " // strongly recommended
124// "EGL_IMG_hibernate_process " // optional
125// "EGL_ANDROID_native_fence_sync " // strongly recommended
126// "EGL_ANDROID_framebuffer_target " // mandatory for HWC 1.1
Jamie Gennisdbe92452013-09-23 17:22:10 -0700127// "EGL_ANDROID_image_crop " // optional
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700128
129/*
130 * EGL Extensions entry-points exposed to 3rd party applications
131 * (keep in sync with gExtensionString above)
132 *
133 */
134static const extention_map_t sExtensionMap[] = {
135 // EGL_KHR_lock_surface
Mathias Agopian518ec112011-05-13 16:21:08 -0700136 { "eglLockSurfaceKHR",
137 (__eglMustCastToProperFunctionPointerType)&eglLockSurfaceKHR },
138 { "eglUnlockSurfaceKHR",
139 (__eglMustCastToProperFunctionPointerType)&eglUnlockSurfaceKHR },
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700140
141 // EGL_KHR_image, EGL_KHR_image_base
Mathias Agopian518ec112011-05-13 16:21:08 -0700142 { "eglCreateImageKHR",
143 (__eglMustCastToProperFunctionPointerType)&eglCreateImageKHR },
144 { "eglDestroyImageKHR",
145 (__eglMustCastToProperFunctionPointerType)&eglDestroyImageKHR },
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700146
147 // EGL_KHR_reusable_sync, EGL_KHR_fence_sync
148 { "eglCreateSyncKHR",
149 (__eglMustCastToProperFunctionPointerType)&eglCreateSyncKHR },
150 { "eglDestroySyncKHR",
151 (__eglMustCastToProperFunctionPointerType)&eglDestroySyncKHR },
152 { "eglClientWaitSyncKHR",
153 (__eglMustCastToProperFunctionPointerType)&eglClientWaitSyncKHR },
154 { "eglSignalSyncKHR",
155 (__eglMustCastToProperFunctionPointerType)&eglSignalSyncKHR },
156 { "eglGetSyncAttribKHR",
157 (__eglMustCastToProperFunctionPointerType)&eglGetSyncAttribKHR },
158
159 // EGL_NV_system_time
Jonas Yang1c3d72a2011-08-26 20:04:39 +0800160 { "eglGetSystemTimeFrequencyNV",
161 (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeFrequencyNV },
162 { "eglGetSystemTimeNV",
163 (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeNV },
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700164
Mathias Agopian2bb71682013-03-27 17:32:41 -0700165 // EGL_KHR_wait_sync
166 { "eglWaitSyncKHR",
167 (__eglMustCastToProperFunctionPointerType)&eglWaitSyncKHR },
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700168
169 // EGL_ANDROID_presentation_time
170 { "eglPresentationTimeANDROID",
171 (__eglMustCastToProperFunctionPointerType)&eglPresentationTimeANDROID },
Dan Stozaa894d082015-02-19 15:27:36 -0800172
173 // EGL_KHR_swap_buffers_with_damage
174 { "eglSwapBuffersWithDamageKHR",
175 (__eglMustCastToProperFunctionPointerType)&eglSwapBuffersWithDamageKHR },
176
Craig Donner05249fc2016-01-15 19:33:55 -0800177 // EGL_ANDROID_native_client_buffer
178 { "eglCreateNativeClientBufferANDROID",
179 (__eglMustCastToProperFunctionPointerType)&eglCreateNativeClientBufferANDROID },
180
Dan Stozaa894d082015-02-19 15:27:36 -0800181 // EGL_KHR_partial_update
182 { "eglSetDamageRegionKHR",
183 (__eglMustCastToProperFunctionPointerType)&eglSetDamageRegionKHR },
Season Li000d88f2015-07-01 11:39:40 -0700184
185 { "eglCreateStreamKHR",
186 (__eglMustCastToProperFunctionPointerType)&eglCreateStreamKHR },
187 { "eglDestroyStreamKHR",
188 (__eglMustCastToProperFunctionPointerType)&eglDestroyStreamKHR },
189 { "eglStreamAttribKHR",
190 (__eglMustCastToProperFunctionPointerType)&eglStreamAttribKHR },
191 { "eglQueryStreamKHR",
192 (__eglMustCastToProperFunctionPointerType)&eglQueryStreamKHR },
193 { "eglQueryStreamu64KHR",
194 (__eglMustCastToProperFunctionPointerType)&eglQueryStreamu64KHR },
195 { "eglQueryStreamTimeKHR",
196 (__eglMustCastToProperFunctionPointerType)&eglQueryStreamTimeKHR },
197 { "eglCreateStreamProducerSurfaceKHR",
198 (__eglMustCastToProperFunctionPointerType)&eglCreateStreamProducerSurfaceKHR },
199 { "eglStreamConsumerGLTextureExternalKHR",
200 (__eglMustCastToProperFunctionPointerType)&eglStreamConsumerGLTextureExternalKHR },
201 { "eglStreamConsumerAcquireKHR",
202 (__eglMustCastToProperFunctionPointerType)&eglStreamConsumerAcquireKHR },
203 { "eglStreamConsumerReleaseKHR",
204 (__eglMustCastToProperFunctionPointerType)&eglStreamConsumerReleaseKHR },
205 { "eglGetStreamFileDescriptorKHR",
206 (__eglMustCastToProperFunctionPointerType)&eglGetStreamFileDescriptorKHR },
207 { "eglCreateStreamFromFileDescriptorKHR",
208 (__eglMustCastToProperFunctionPointerType)&eglCreateStreamFromFileDescriptorKHR },
Mathias Agopian518ec112011-05-13 16:21:08 -0700209};
210
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700211/*
212 * These extensions entry-points should not be exposed to applications.
213 * They're used internally by the Android EGL layer.
214 */
215#define FILTER_EXTENSIONS(procname) \
216 (!strcmp((procname), "eglSetBlobCacheFuncsANDROID") || \
217 !strcmp((procname), "eglHibernateProcessIMG") || \
218 !strcmp((procname), "eglAwakenProcessIMG") || \
219 !strcmp((procname), "eglDupNativeFenceFDANDROID"))
220
221
222
Mathias Agopian518ec112011-05-13 16:21:08 -0700223// accesses protected by sExtensionMapMutex
224static DefaultKeyedVector<String8, __eglMustCastToProperFunctionPointerType> sGLExtentionMap;
225static int sGLExtentionSlot = 0;
226static pthread_mutex_t sExtensionMapMutex = PTHREAD_MUTEX_INITIALIZER;
227
228static void(*findProcAddress(const char* name,
229 const extention_map_t* map, size_t n))() {
230 for (uint32_t i=0 ; i<n ; i++) {
231 if (!strcmp(name, map[i].name)) {
232 return map[i].address;
233 }
234 }
235 return NULL;
236}
237
238// ----------------------------------------------------------------------------
239
Mathias Agopian518ec112011-05-13 16:21:08 -0700240extern void setGLHooksThreadSpecific(gl_hooks_t const *value);
241extern EGLBoolean egl_init_drivers();
242extern const __eglMustCastToProperFunctionPointerType gExtensionForwarders[MAX_NUMBER_OF_GL_EXTENSIONS];
Mathias Agopian518ec112011-05-13 16:21:08 -0700243extern gl_hooks_t gHooksTrace;
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700244
Mathias Agopian518ec112011-05-13 16:21:08 -0700245} // namespace android;
246
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700247
Mathias Agopian518ec112011-05-13 16:21:08 -0700248// ----------------------------------------------------------------------------
249
250static inline void clearError() { egl_tls_t::clearError(); }
251static inline EGLContext getContext() { return egl_tls_t::getContext(); }
252
253// ----------------------------------------------------------------------------
254
255EGLDisplay eglGetDisplay(EGLNativeDisplayType display)
256{
257 clearError();
258
Dan Stozac3289c42014-01-17 11:38:34 -0800259 uintptr_t index = reinterpret_cast<uintptr_t>(display);
Mathias Agopian518ec112011-05-13 16:21:08 -0700260 if (index >= NUM_DISPLAYS) {
261 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
262 }
263
264 if (egl_init_drivers() == EGL_FALSE) {
265 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
266 }
267
268 EGLDisplay dpy = egl_display_t::getFromNativeDisplay(display);
269 return dpy;
270}
271
272// ----------------------------------------------------------------------------
273// Initialization
274// ----------------------------------------------------------------------------
275
276EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
277{
278 clearError();
279
Jesse Hallb29e5e82012-04-04 16:53:42 -0700280 egl_display_ptr dp = get_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700281 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
282
283 EGLBoolean res = dp->initialize(major, minor);
284
285 return res;
286}
287
288EGLBoolean eglTerminate(EGLDisplay dpy)
289{
290 // NOTE: don't unload the drivers b/c some APIs can be called
291 // after eglTerminate() has been called. eglTerminate() only
292 // terminates an EGLDisplay, not a EGL itself.
293
294 clearError();
295
Jesse Hallb29e5e82012-04-04 16:53:42 -0700296 egl_display_ptr dp = get_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700297 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
298
299 EGLBoolean res = dp->terminate();
Jesse Hall47743382013-02-08 11:13:46 -0800300
Mathias Agopian518ec112011-05-13 16:21:08 -0700301 return res;
302}
303
304// ----------------------------------------------------------------------------
305// configuration
306// ----------------------------------------------------------------------------
307
308EGLBoolean eglGetConfigs( EGLDisplay dpy,
309 EGLConfig *configs,
310 EGLint config_size, EGLint *num_config)
311{
312 clearError();
313
Jesse Hallb29e5e82012-04-04 16:53:42 -0700314 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700315 if (!dp) return EGL_FALSE;
316
Mathias Agopian7773c432012-02-13 20:06:08 -0800317 if (num_config==0) {
318 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700319 }
320
Mathias Agopian7773c432012-02-13 20:06:08 -0800321 EGLBoolean res = EGL_FALSE;
322 *num_config = 0;
323
324 egl_connection_t* const cnx = &gEGLImpl;
325 if (cnx->dso) {
326 res = cnx->egl.eglGetConfigs(
327 dp->disp.dpy, configs, config_size, num_config);
Mathias Agopian518ec112011-05-13 16:21:08 -0700328 }
Mathias Agopian7773c432012-02-13 20:06:08 -0800329
330 return res;
Mathias Agopian518ec112011-05-13 16:21:08 -0700331}
332
333EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list,
334 EGLConfig *configs, EGLint config_size,
335 EGLint *num_config)
336{
337 clearError();
338
Jesse Hallb29e5e82012-04-04 16:53:42 -0700339 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700340 if (!dp) return EGL_FALSE;
341
342 if (num_config==0) {
343 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
344 }
345
Mathias Agopian518ec112011-05-13 16:21:08 -0700346 EGLBoolean res = EGL_FALSE;
347 *num_config = 0;
348
Mathias Agopianada798b2012-02-13 17:09:30 -0800349 egl_connection_t* const cnx = &gEGLImpl;
350 if (cnx->dso) {
Romain Guy1cffc802012-10-15 18:13:05 -0700351 if (attrib_list) {
352 char value[PROPERTY_VALUE_MAX];
353 property_get("debug.egl.force_msaa", value, "false");
354
355 if (!strcmp(value, "true")) {
356 size_t attribCount = 0;
357 EGLint attrib = attrib_list[0];
358
359 // Only enable MSAA if the context is OpenGL ES 2.0 and
Romain Guybe3c3e42012-10-15 19:25:18 -0700360 // if no caveat is requested
Romain Guy1cffc802012-10-15 18:13:05 -0700361 const EGLint *attribRendererable = NULL;
362 const EGLint *attribCaveat = NULL;
363
364 // Count the number of attributes and look for
Romain Guybe3c3e42012-10-15 19:25:18 -0700365 // EGL_RENDERABLE_TYPE and EGL_CONFIG_CAVEAT
Romain Guy1cffc802012-10-15 18:13:05 -0700366 while (attrib != EGL_NONE) {
367 attrib = attrib_list[attribCount];
368 switch (attrib) {
369 case EGL_RENDERABLE_TYPE:
370 attribRendererable = &attrib_list[attribCount];
371 break;
372 case EGL_CONFIG_CAVEAT:
373 attribCaveat = &attrib_list[attribCount];
374 break;
375 }
376 attribCount++;
377 }
378
379 if (attribRendererable && attribRendererable[1] == EGL_OPENGL_ES2_BIT &&
380 (!attribCaveat || attribCaveat[1] != EGL_NONE)) {
Jesse Hall47743382013-02-08 11:13:46 -0800381
Romain Guy1cffc802012-10-15 18:13:05 -0700382 // Insert 2 extra attributes to force-enable MSAA 4x
383 EGLint aaAttribs[attribCount + 4];
384 aaAttribs[0] = EGL_SAMPLE_BUFFERS;
385 aaAttribs[1] = 1;
386 aaAttribs[2] = EGL_SAMPLES;
387 aaAttribs[3] = 4;
388
389 memcpy(&aaAttribs[4], attrib_list, attribCount * sizeof(EGLint));
390
391 EGLint numConfigAA;
392 EGLBoolean resAA = cnx->egl.eglChooseConfig(
393 dp->disp.dpy, aaAttribs, configs, config_size, &numConfigAA);
394
395 if (resAA == EGL_TRUE && numConfigAA > 0) {
396 ALOGD("Enabling MSAA 4x");
397 *num_config = numConfigAA;
398 return resAA;
399 }
400 }
401 }
402 }
403
Mathias Agopian7773c432012-02-13 20:06:08 -0800404 res = cnx->egl.eglChooseConfig(
405 dp->disp.dpy, attrib_list, configs, config_size, num_config);
Mathias Agopian518ec112011-05-13 16:21:08 -0700406 }
407 return res;
408}
409
410EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
411 EGLint attribute, EGLint *value)
412{
413 clearError();
414
Jesse Hallb29e5e82012-04-04 16:53:42 -0700415 egl_connection_t* cnx = NULL;
416 const egl_display_ptr dp = validate_display_connection(dpy, cnx);
417 if (!dp) return EGL_FALSE;
Jesse Hall47743382013-02-08 11:13:46 -0800418
Mathias Agopian518ec112011-05-13 16:21:08 -0700419 return cnx->egl.eglGetConfigAttrib(
Mathias Agopian7773c432012-02-13 20:06:08 -0800420 dp->disp.dpy, config, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -0700421}
422
423// ----------------------------------------------------------------------------
424// surfaces
425// ----------------------------------------------------------------------------
426
Jesse Halla2ba4282013-09-14 21:00:14 -0700427// The EGL_KHR_gl_colorspace spec hasn't been ratified yet, so these haven't
Jesse Hallc2e41222013-08-08 13:40:22 -0700428// been added to the Khronos egl.h.
429#define EGL_GL_COLORSPACE_KHR EGL_VG_COLORSPACE
430#define EGL_GL_COLORSPACE_SRGB_KHR EGL_VG_COLORSPACE_sRGB
431#define EGL_GL_COLORSPACE_LINEAR_KHR EGL_VG_COLORSPACE_LINEAR
432
433// Turn linear formats into corresponding sRGB formats when colorspace is
434// EGL_GL_COLORSPACE_SRGB_KHR, or turn sRGB formats into corresponding linear
435// formats when colorspace is EGL_GL_COLORSPACE_LINEAR_KHR. In any cases where
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800436// the modification isn't possible, the original dataSpace is returned.
437static android_dataspace modifyBufferDataspace( android_dataspace dataSpace,
438 EGLint colorspace) {
Jesse Hallc2e41222013-08-08 13:40:22 -0700439 if (colorspace == EGL_GL_COLORSPACE_LINEAR_KHR) {
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800440 return HAL_DATASPACE_SRGB_LINEAR;
Jesse Hallc2e41222013-08-08 13:40:22 -0700441 } else if (colorspace == EGL_GL_COLORSPACE_SRGB_KHR) {
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800442 return HAL_DATASPACE_SRGB;
Jesse Hallc2e41222013-08-08 13:40:22 -0700443 }
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800444 return dataSpace;
Jesse Hallc2e41222013-08-08 13:40:22 -0700445}
446
Mathias Agopian518ec112011-05-13 16:21:08 -0700447EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config,
448 NativeWindowType window,
449 const EGLint *attrib_list)
450{
451 clearError();
452
Jesse Hallb29e5e82012-04-04 16:53:42 -0700453 egl_connection_t* cnx = NULL;
454 egl_display_ptr dp = validate_display_connection(dpy, cnx);
455 if (dp) {
Mathias Agopianada798b2012-02-13 17:09:30 -0800456 EGLDisplay iDpy = dp->disp.dpy;
Mathias Agopian518ec112011-05-13 16:21:08 -0700457
Andy McFaddend566ce32014-01-07 15:54:17 -0800458 int result = native_window_api_connect(window, NATIVE_WINDOW_API_EGL);
459 if (result != OK) {
460 ALOGE("eglCreateWindowSurface: native_window_api_connect (win=%p) "
461 "failed (%#x) (already connected to another API?)",
462 window, result);
Jonathan Hamilton77a9b4a2013-07-17 09:41:42 -0700463 return setError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
Mathias Agopian81a63352011-07-29 17:55:48 -0700464 }
465
Mathias Agopian0f288fc2013-08-21 16:36:34 -0700466 // Set the native window's buffers format to match what this config requests.
Jesse Hallc2e41222013-08-08 13:40:22 -0700467 // Whether to use sRGB gamma is not part of the EGLconfig, but is part
468 // of our native format. So if sRGB gamma is requested, we have to
469 // modify the EGLconfig's format before setting the native window's
470 // format.
Alistair Strachan733a8072015-02-12 12:33:25 -0800471
Mathias Agopian0f288fc2013-08-21 16:36:34 -0700472 // by default, just pick RGBA_8888
473 EGLint format = HAL_PIXEL_FORMAT_RGBA_8888;
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800474 android_dataspace dataSpace = HAL_DATASPACE_UNKNOWN;
Mathias Agopian0f288fc2013-08-21 16:36:34 -0700475
476 EGLint a = 0;
477 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_ALPHA_SIZE, &a);
478 if (a > 0) {
479 // alpha-channel requested, there's really only one suitable format
480 format = HAL_PIXEL_FORMAT_RGBA_8888;
481 } else {
482 EGLint r, g, b;
483 r = g = b = 0;
484 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_RED_SIZE, &r);
485 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_GREEN_SIZE, &g);
486 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_BLUE_SIZE, &b);
487 EGLint colorDepth = r + g + b;
488 if (colorDepth <= 16) {
489 format = HAL_PIXEL_FORMAT_RGB_565;
490 } else {
491 format = HAL_PIXEL_FORMAT_RGBX_8888;
492 }
Jesse Hallc2e41222013-08-08 13:40:22 -0700493 }
Mathias Agopian0f288fc2013-08-21 16:36:34 -0700494
495 // now select a corresponding sRGB format if needed
496 if (attrib_list && dp->haveExtension("EGL_KHR_gl_colorspace")) {
497 for (const EGLint* attr = attrib_list; *attr != EGL_NONE; attr += 2) {
498 if (*attr == EGL_GL_COLORSPACE_KHR) {
Jesse Halla2ba4282013-09-14 21:00:14 -0700499 if (ENABLE_EGL_KHR_GL_COLORSPACE) {
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800500 dataSpace = modifyBufferDataspace(dataSpace, *(attr+1));
Jesse Halla2ba4282013-09-14 21:00:14 -0700501 } else {
502 // Normally we'd pass through unhandled attributes to
503 // the driver. But in case the driver implements this
504 // extension but we're disabling it, we want to prevent
505 // it getting through -- support will be broken without
506 // our help.
507 ALOGE("sRGB window surfaces not supported");
508 return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
509 }
Jamie Gennisbee205f2011-07-01 13:12:07 -0700510 }
Mathias Agopian518ec112011-05-13 16:21:08 -0700511 }
512 }
Alistair Strachan733a8072015-02-12 12:33:25 -0800513
Jesse Hallc2e41222013-08-08 13:40:22 -0700514 if (format != 0) {
515 int err = native_window_set_buffers_format(window, format);
516 if (err != 0) {
517 ALOGE("error setting native window pixel format: %s (%d)",
518 strerror(-err), err);
519 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
520 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
521 }
522 }
Mathias Agopian518ec112011-05-13 16:21:08 -0700523
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800524 if (dataSpace != 0) {
525 int err = native_window_set_buffers_data_space(window, dataSpace);
526 if (err != 0) {
527 ALOGE("error setting native window pixel dataSpace: %s (%d)",
528 strerror(-err), err);
529 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
530 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
531 }
532 }
533
Jamie Gennis59769462011-11-19 18:04:43 -0800534 // the EGL spec requires that a new EGLSurface default to swap interval
535 // 1, so explicitly set that on the window here.
536 ANativeWindow* anw = reinterpret_cast<ANativeWindow*>(window);
537 anw->setSwapInterval(anw, 1);
538
Mathias Agopian518ec112011-05-13 16:21:08 -0700539 EGLSurface surface = cnx->egl.eglCreateWindowSurface(
Mathias Agopian7773c432012-02-13 20:06:08 -0800540 iDpy, config, window, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700541 if (surface != EGL_NO_SURFACE) {
Jesse Hallb29e5e82012-04-04 16:53:42 -0700542 egl_surface_t* s = new egl_surface_t(dp.get(), config, window,
543 surface, cnx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700544 return s;
545 }
Mathias Agopian81a63352011-07-29 17:55:48 -0700546
547 // EGLSurface creation failed
548 native_window_set_buffers_format(window, 0);
549 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
Mathias Agopian518ec112011-05-13 16:21:08 -0700550 }
551 return EGL_NO_SURFACE;
552}
553
554EGLSurface eglCreatePixmapSurface( EGLDisplay dpy, EGLConfig config,
555 NativePixmapType pixmap,
556 const EGLint *attrib_list)
557{
558 clearError();
559
Jesse Hallb29e5e82012-04-04 16:53:42 -0700560 egl_connection_t* cnx = NULL;
561 egl_display_ptr dp = validate_display_connection(dpy, cnx);
562 if (dp) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700563 EGLSurface surface = cnx->egl.eglCreatePixmapSurface(
Mathias Agopian7773c432012-02-13 20:06:08 -0800564 dp->disp.dpy, config, pixmap, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700565 if (surface != EGL_NO_SURFACE) {
Jesse Hallb29e5e82012-04-04 16:53:42 -0700566 egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL,
567 surface, cnx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700568 return s;
569 }
570 }
571 return EGL_NO_SURFACE;
572}
573
574EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config,
575 const EGLint *attrib_list)
576{
577 clearError();
578
Jesse Hallb29e5e82012-04-04 16:53:42 -0700579 egl_connection_t* cnx = NULL;
580 egl_display_ptr dp = validate_display_connection(dpy, cnx);
581 if (dp) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700582 EGLSurface surface = cnx->egl.eglCreatePbufferSurface(
Mathias Agopian7773c432012-02-13 20:06:08 -0800583 dp->disp.dpy, config, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700584 if (surface != EGL_NO_SURFACE) {
Jesse Hallb29e5e82012-04-04 16:53:42 -0700585 egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL,
586 surface, cnx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700587 return s;
588 }
589 }
590 return EGL_NO_SURFACE;
591}
Jesse Hall47743382013-02-08 11:13:46 -0800592
Mathias Agopian518ec112011-05-13 16:21:08 -0700593EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
594{
595 clearError();
596
Jesse Hallb29e5e82012-04-04 16:53:42 -0700597 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700598 if (!dp) return EGL_FALSE;
599
Jesse Hallb29e5e82012-04-04 16:53:42 -0700600 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700601 if (!_s.get())
602 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700603
604 egl_surface_t * const s = get_surface(surface);
Mathias Agopianada798b2012-02-13 17:09:30 -0800605 EGLBoolean result = s->cnx->egl.eglDestroySurface(dp->disp.dpy, s->surface);
Mathias Agopian518ec112011-05-13 16:21:08 -0700606 if (result == EGL_TRUE) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700607 _s.terminate();
Pablo Ceballos541de492016-04-09 15:56:12 -0700608 dp->removeSurface(surface);
Mathias Agopian518ec112011-05-13 16:21:08 -0700609 }
610 return result;
611}
612
613EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface surface,
614 EGLint attribute, EGLint *value)
615{
616 clearError();
617
Jesse Hallb29e5e82012-04-04 16:53:42 -0700618 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700619 if (!dp) return EGL_FALSE;
620
Jesse Hallb29e5e82012-04-04 16:53:42 -0700621 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700622 if (!_s.get())
623 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700624
Mathias Agopian518ec112011-05-13 16:21:08 -0700625 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian7773c432012-02-13 20:06:08 -0800626 return s->cnx->egl.eglQuerySurface(
627 dp->disp.dpy, s->surface, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -0700628}
629
Jamie Gennise8696a42012-01-15 18:54:57 -0800630void EGLAPI eglBeginFrame(EGLDisplay dpy, EGLSurface surface) {
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800631 ATRACE_CALL();
Jamie Gennise8696a42012-01-15 18:54:57 -0800632 clearError();
633
Jesse Hallb29e5e82012-04-04 16:53:42 -0700634 const egl_display_ptr dp = validate_display(dpy);
Jamie Gennise8696a42012-01-15 18:54:57 -0800635 if (!dp) {
636 return;
637 }
638
Jesse Hallb29e5e82012-04-04 16:53:42 -0700639 SurfaceRef _s(dp.get(), surface);
Jamie Gennise8696a42012-01-15 18:54:57 -0800640 if (!_s.get()) {
641 setError(EGL_BAD_SURFACE, EGL_FALSE);
642 return;
643 }
Jamie Gennise8696a42012-01-15 18:54:57 -0800644}
645
Mathias Agopian518ec112011-05-13 16:21:08 -0700646// ----------------------------------------------------------------------------
647// Contexts
648// ----------------------------------------------------------------------------
649
650EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config,
651 EGLContext share_list, const EGLint *attrib_list)
652{
653 clearError();
654
Jesse Hallb29e5e82012-04-04 16:53:42 -0700655 egl_connection_t* cnx = NULL;
656 const egl_display_ptr dp = validate_display_connection(dpy, cnx);
Michael Chock0673e1e2012-06-21 12:53:17 -0700657 if (dp) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700658 if (share_list != EGL_NO_CONTEXT) {
Michael Chock0673e1e2012-06-21 12:53:17 -0700659 if (!ContextRef(dp.get(), share_list).get()) {
660 return setError(EGL_BAD_CONTEXT, EGL_NO_CONTEXT);
661 }
Mathias Agopian518ec112011-05-13 16:21:08 -0700662 egl_context_t* const c = get_context(share_list);
663 share_list = c->context;
664 }
665 EGLContext context = cnx->egl.eglCreateContext(
Mathias Agopian7773c432012-02-13 20:06:08 -0800666 dp->disp.dpy, config, share_list, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700667 if (context != EGL_NO_CONTEXT) {
668 // figure out if it's a GLESv1 or GLESv2
669 int version = 0;
670 if (attrib_list) {
671 while (*attrib_list != EGL_NONE) {
672 GLint attr = *attrib_list++;
673 GLint value = *attrib_list++;
674 if (attr == EGL_CONTEXT_CLIENT_VERSION) {
675 if (value == 1) {
Mathias Agopian7773c432012-02-13 20:06:08 -0800676 version = egl_connection_t::GLESv1_INDEX;
Jesse Hall47743382013-02-08 11:13:46 -0800677 } else if (value == 2 || value == 3) {
Mathias Agopian7773c432012-02-13 20:06:08 -0800678 version = egl_connection_t::GLESv2_INDEX;
Mathias Agopian518ec112011-05-13 16:21:08 -0700679 }
680 }
681 };
682 }
Jesse Hallb29e5e82012-04-04 16:53:42 -0700683 egl_context_t* c = new egl_context_t(dpy, context, config, cnx,
684 version);
Mathias Agopian518ec112011-05-13 16:21:08 -0700685 return c;
686 }
687 }
688 return EGL_NO_CONTEXT;
689}
690
691EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
692{
693 clearError();
694
Jesse Hallb29e5e82012-04-04 16:53:42 -0700695 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700696 if (!dp)
697 return EGL_FALSE;
Mathias Agopian518ec112011-05-13 16:21:08 -0700698
Jesse Hallb29e5e82012-04-04 16:53:42 -0700699 ContextRef _c(dp.get(), ctx);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700700 if (!_c.get())
701 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
Jesse Hall47743382013-02-08 11:13:46 -0800702
Mathias Agopian518ec112011-05-13 16:21:08 -0700703 egl_context_t * const c = get_context(ctx);
Mathias Agopianada798b2012-02-13 17:09:30 -0800704 EGLBoolean result = c->cnx->egl.eglDestroyContext(dp->disp.dpy, c->context);
Mathias Agopian518ec112011-05-13 16:21:08 -0700705 if (result == EGL_TRUE) {
706 _c.terminate();
707 }
708 return result;
709}
710
Mathias Agopian518ec112011-05-13 16:21:08 -0700711EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw,
712 EGLSurface read, EGLContext ctx)
713{
714 clearError();
715
Jesse Hallb29e5e82012-04-04 16:53:42 -0700716 egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700717 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
718
Mathias Agopian5b287a62011-05-16 18:58:55 -0700719 // If ctx is not EGL_NO_CONTEXT, read is not EGL_NO_SURFACE, or draw is not
720 // EGL_NO_SURFACE, then an EGL_NOT_INITIALIZED error is generated if dpy is
721 // a valid but uninitialized display.
Mathias Agopian518ec112011-05-13 16:21:08 -0700722 if ( (ctx != EGL_NO_CONTEXT) || (read != EGL_NO_SURFACE) ||
723 (draw != EGL_NO_SURFACE) ) {
724 if (!dp->isReady()) return setError(EGL_NOT_INITIALIZED, EGL_FALSE);
725 }
726
727 // get a reference to the object passed in
Jesse Hallb29e5e82012-04-04 16:53:42 -0700728 ContextRef _c(dp.get(), ctx);
729 SurfaceRef _d(dp.get(), draw);
730 SurfaceRef _r(dp.get(), read);
Mathias Agopian518ec112011-05-13 16:21:08 -0700731
732 // validate the context (if not EGL_NO_CONTEXT)
Mathias Agopian5b287a62011-05-16 18:58:55 -0700733 if ((ctx != EGL_NO_CONTEXT) && !_c.get()) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700734 // EGL_NO_CONTEXT is valid
Michael Chock0673e1e2012-06-21 12:53:17 -0700735 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700736 }
737
738 // these are the underlying implementation's object
739 EGLContext impl_ctx = EGL_NO_CONTEXT;
740 EGLSurface impl_draw = EGL_NO_SURFACE;
741 EGLSurface impl_read = EGL_NO_SURFACE;
742
743 // these are our objects structs passed in
744 egl_context_t * c = NULL;
745 egl_surface_t const * d = NULL;
746 egl_surface_t const * r = NULL;
747
748 // these are the current objects structs
749 egl_context_t * cur_c = get_context(getContext());
Jesse Hall47743382013-02-08 11:13:46 -0800750
Mathias Agopian518ec112011-05-13 16:21:08 -0700751 if (ctx != EGL_NO_CONTEXT) {
752 c = get_context(ctx);
753 impl_ctx = c->context;
754 } else {
755 // no context given, use the implementation of the current context
Michael Chock0673e1e2012-06-21 12:53:17 -0700756 if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE) {
757 // calling eglMakeCurrent( ..., !=0, !=0, EGL_NO_CONTEXT);
758 return setError(EGL_BAD_MATCH, EGL_FALSE);
759 }
Mathias Agopian518ec112011-05-13 16:21:08 -0700760 if (cur_c == NULL) {
761 // no current context
Mathias Agopian518ec112011-05-13 16:21:08 -0700762 // not an error, there is just no current context.
763 return EGL_TRUE;
764 }
765 }
766
767 // retrieve the underlying implementation's draw EGLSurface
768 if (draw != EGL_NO_SURFACE) {
Michael Chock0673e1e2012-06-21 12:53:17 -0700769 if (!_d.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700770 d = get_surface(draw);
Mathias Agopian518ec112011-05-13 16:21:08 -0700771 impl_draw = d->surface;
772 }
773
774 // retrieve the underlying implementation's read EGLSurface
775 if (read != EGL_NO_SURFACE) {
Michael Chock0673e1e2012-06-21 12:53:17 -0700776 if (!_r.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700777 r = get_surface(read);
Mathias Agopian518ec112011-05-13 16:21:08 -0700778 impl_read = r->surface;
779 }
780
Mathias Agopian518ec112011-05-13 16:21:08 -0700781
Jesse Hallb29e5e82012-04-04 16:53:42 -0700782 EGLBoolean result = dp->makeCurrent(c, cur_c,
Mathias Agopianfb87e542012-01-30 18:20:52 -0800783 draw, read, ctx,
784 impl_draw, impl_read, impl_ctx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700785
786 if (result == EGL_TRUE) {
Mathias Agopianfb87e542012-01-30 18:20:52 -0800787 if (c) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700788 setGLHooksThreadSpecific(c->cnx->hooks[c->version]);
789 egl_tls_t::setContext(ctx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700790 _c.acquire();
791 _r.acquire();
792 _d.acquire();
Mathias Agopian518ec112011-05-13 16:21:08 -0700793 } else {
794 setGLHooksThreadSpecific(&gHooksNoContext);
795 egl_tls_t::setContext(EGL_NO_CONTEXT);
796 }
Mathias Agopian5fecea72011-08-25 18:38:24 -0700797 } else {
Steve Blocke6f43dd2012-01-06 19:20:56 +0000798 // this will ALOGE the error
Mathias Agopian63108c32013-09-06 13:36:49 -0700799 egl_connection_t* const cnx = &gEGLImpl;
800 result = setError(cnx->egl.eglGetError(), EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700801 }
802 return result;
803}
804
805
806EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx,
807 EGLint attribute, EGLint *value)
808{
809 clearError();
810
Jesse Hallb29e5e82012-04-04 16:53:42 -0700811 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700812 if (!dp) return EGL_FALSE;
813
Jesse Hallb29e5e82012-04-04 16:53:42 -0700814 ContextRef _c(dp.get(), ctx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700815 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
816
Mathias Agopian518ec112011-05-13 16:21:08 -0700817 egl_context_t * const c = get_context(ctx);
Mathias Agopian7773c432012-02-13 20:06:08 -0800818 return c->cnx->egl.eglQueryContext(
819 dp->disp.dpy, c->context, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -0700820
Mathias Agopian518ec112011-05-13 16:21:08 -0700821}
822
823EGLContext eglGetCurrentContext(void)
824{
825 // could be called before eglInitialize(), but we wouldn't have a context
826 // then, and this function would correctly return EGL_NO_CONTEXT.
827
828 clearError();
829
830 EGLContext ctx = getContext();
831 return ctx;
832}
833
834EGLSurface eglGetCurrentSurface(EGLint readdraw)
835{
836 // could be called before eglInitialize(), but we wouldn't have a context
837 // then, and this function would correctly return EGL_NO_SURFACE.
838
839 clearError();
840
841 EGLContext ctx = getContext();
842 if (ctx) {
843 egl_context_t const * const c = get_context(ctx);
844 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
845 switch (readdraw) {
846 case EGL_READ: return c->read;
Jesse Hall47743382013-02-08 11:13:46 -0800847 case EGL_DRAW: return c->draw;
Mathias Agopian518ec112011-05-13 16:21:08 -0700848 default: return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
849 }
850 }
851 return EGL_NO_SURFACE;
852}
853
854EGLDisplay eglGetCurrentDisplay(void)
855{
856 // could be called before eglInitialize(), but we wouldn't have a context
857 // then, and this function would correctly return EGL_NO_DISPLAY.
858
859 clearError();
860
861 EGLContext ctx = getContext();
862 if (ctx) {
863 egl_context_t const * const c = get_context(ctx);
864 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
865 return c->dpy;
866 }
867 return EGL_NO_DISPLAY;
868}
869
870EGLBoolean eglWaitGL(void)
871{
Mathias Agopian518ec112011-05-13 16:21:08 -0700872 clearError();
873
Mathias Agopianada798b2012-02-13 17:09:30 -0800874 egl_connection_t* const cnx = &gEGLImpl;
875 if (!cnx->dso)
876 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
877
878 return cnx->egl.eglWaitGL();
Mathias Agopian518ec112011-05-13 16:21:08 -0700879}
880
881EGLBoolean eglWaitNative(EGLint engine)
882{
Mathias Agopian518ec112011-05-13 16:21:08 -0700883 clearError();
884
Mathias Agopianada798b2012-02-13 17:09:30 -0800885 egl_connection_t* const cnx = &gEGLImpl;
886 if (!cnx->dso)
887 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
888
889 return cnx->egl.eglWaitNative(engine);
Mathias Agopian518ec112011-05-13 16:21:08 -0700890}
891
892EGLint eglGetError(void)
893{
Mathias Agopianada798b2012-02-13 17:09:30 -0800894 EGLint err = EGL_SUCCESS;
895 egl_connection_t* const cnx = &gEGLImpl;
896 if (cnx->dso) {
897 err = cnx->egl.eglGetError();
Mathias Agopian518ec112011-05-13 16:21:08 -0700898 }
Mathias Agopianada798b2012-02-13 17:09:30 -0800899 if (err == EGL_SUCCESS) {
900 err = egl_tls_t::getError();
901 }
902 return err;
Mathias Agopian518ec112011-05-13 16:21:08 -0700903}
904
Michael Chockc0ec5e22014-01-27 08:14:33 -0800905static __eglMustCastToProperFunctionPointerType findBuiltinWrapper(
Jesse Hallc07b5202013-07-04 12:08:16 -0700906 const char* procname) {
907 const egl_connection_t* cnx = &gEGLImpl;
908 void* proc = NULL;
909
Michael Chockc0ec5e22014-01-27 08:14:33 -0800910 proc = dlsym(cnx->libEgl, procname);
911 if (proc) return (__eglMustCastToProperFunctionPointerType)proc;
912
Jesse Hallc07b5202013-07-04 12:08:16 -0700913 proc = dlsym(cnx->libGles2, procname);
914 if (proc) return (__eglMustCastToProperFunctionPointerType)proc;
915
916 proc = dlsym(cnx->libGles1, procname);
917 if (proc) return (__eglMustCastToProperFunctionPointerType)proc;
918
919 return NULL;
920}
921
Mathias Agopian518ec112011-05-13 16:21:08 -0700922__eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
923{
924 // eglGetProcAddress() could be the very first function called
925 // in which case we must make sure we've initialized ourselves, this
926 // happens the first time egl_get_display() is called.
927
928 clearError();
929
930 if (egl_init_drivers() == EGL_FALSE) {
931 setError(EGL_BAD_PARAMETER, NULL);
932 return NULL;
933 }
934
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700935 if (FILTER_EXTENSIONS(procname)) {
Jamie Gennisaca51c02011-11-03 17:42:43 -0700936 return NULL;
937 }
938
Mathias Agopian518ec112011-05-13 16:21:08 -0700939 __eglMustCastToProperFunctionPointerType addr;
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700940 addr = findProcAddress(procname, sExtensionMap, NELEM(sExtensionMap));
Mathias Agopian518ec112011-05-13 16:21:08 -0700941 if (addr) return addr;
942
Michael Chockc0ec5e22014-01-27 08:14:33 -0800943 addr = findBuiltinWrapper(procname);
Jesse Hallc07b5202013-07-04 12:08:16 -0700944 if (addr) return addr;
Jamie Gennisaca51c02011-11-03 17:42:43 -0700945
Mathias Agopian518ec112011-05-13 16:21:08 -0700946 // this protects accesses to sGLExtentionMap and sGLExtentionSlot
947 pthread_mutex_lock(&sExtensionMapMutex);
948
949 /*
950 * Since eglGetProcAddress() is not associated to anything, it needs
951 * to return a function pointer that "works" regardless of what
952 * the current context is.
953 *
954 * For this reason, we return a "forwarder", a small stub that takes
955 * care of calling the function associated with the context
956 * currently bound.
957 *
958 * We first look for extensions we've already resolved, if we're seeing
959 * this extension for the first time, we go through all our
960 * implementations and call eglGetProcAddress() and record the
961 * result in the appropriate implementation hooks and return the
962 * address of the forwarder corresponding to that hook set.
963 *
964 */
965
966 const String8 name(procname);
967 addr = sGLExtentionMap.valueFor(name);
968 const int slot = sGLExtentionSlot;
969
Steve Blocke6f43dd2012-01-06 19:20:56 +0000970 ALOGE_IF(slot >= MAX_NUMBER_OF_GL_EXTENSIONS,
Mathias Agopian518ec112011-05-13 16:21:08 -0700971 "no more slots for eglGetProcAddress(\"%s\")",
972 procname);
973
974 if (!addr && (slot < MAX_NUMBER_OF_GL_EXTENSIONS)) {
975 bool found = false;
Mathias Agopianada798b2012-02-13 17:09:30 -0800976
977 egl_connection_t* const cnx = &gEGLImpl;
978 if (cnx->dso && cnx->egl.eglGetProcAddress) {
Mathias Agopianada798b2012-02-13 17:09:30 -0800979 // Extensions are independent of the bound context
luliuhui69d10072012-08-30 11:15:36 +0800980 addr =
Mathias Agopian7773c432012-02-13 20:06:08 -0800981 cnx->hooks[egl_connection_t::GLESv1_INDEX]->ext.extensions[slot] =
982 cnx->hooks[egl_connection_t::GLESv2_INDEX]->ext.extensions[slot] =
Mathias Agopianada798b2012-02-13 17:09:30 -0800983 cnx->egl.eglGetProcAddress(procname);
luliuhui69d10072012-08-30 11:15:36 +0800984 if (addr) found = true;
Mathias Agopian518ec112011-05-13 16:21:08 -0700985 }
Mathias Agopianada798b2012-02-13 17:09:30 -0800986
Mathias Agopian518ec112011-05-13 16:21:08 -0700987 if (found) {
988 addr = gExtensionForwarders[slot];
Mathias Agopian518ec112011-05-13 16:21:08 -0700989 sGLExtentionMap.add(name, addr);
990 sGLExtentionSlot++;
991 }
992 }
993
994 pthread_mutex_unlock(&sExtensionMapMutex);
995 return addr;
996}
997
Jamie Gennis28ef8d72012-04-05 20:34:54 -0700998class FrameCompletionThread : public Thread {
999public:
1000
1001 static void queueSync(EGLSyncKHR sync) {
1002 static sp<FrameCompletionThread> thread(new FrameCompletionThread);
1003 static bool running = false;
1004 if (!running) {
1005 thread->run("GPUFrameCompletion");
1006 running = true;
1007 }
1008 {
1009 Mutex::Autolock lock(thread->mMutex);
1010 ScopedTrace st(ATRACE_TAG, String8::format("kicked off frame %d",
1011 thread->mFramesQueued).string());
1012 thread->mQueue.push_back(sync);
1013 thread->mCondition.signal();
1014 thread->mFramesQueued++;
1015 ATRACE_INT("GPU Frames Outstanding", thread->mQueue.size());
1016 }
1017 }
1018
1019private:
1020 FrameCompletionThread() : mFramesQueued(0), mFramesCompleted(0) {}
1021
1022 virtual bool threadLoop() {
1023 EGLSyncKHR sync;
1024 uint32_t frameNum;
1025 {
1026 Mutex::Autolock lock(mMutex);
1027 while (mQueue.isEmpty()) {
1028 mCondition.wait(mMutex);
1029 }
1030 sync = mQueue[0];
1031 frameNum = mFramesCompleted;
1032 }
1033 EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
1034 {
1035 ScopedTrace st(ATRACE_TAG, String8::format("waiting for frame %d",
1036 frameNum).string());
1037 EGLint result = eglClientWaitSyncKHR(dpy, sync, 0, EGL_FOREVER_KHR);
1038 if (result == EGL_FALSE) {
1039 ALOGE("FrameCompletion: error waiting for fence: %#x", eglGetError());
1040 } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
1041 ALOGE("FrameCompletion: timeout waiting for fence");
1042 }
1043 eglDestroySyncKHR(dpy, sync);
1044 }
1045 {
1046 Mutex::Autolock lock(mMutex);
1047 mQueue.removeAt(0);
1048 mFramesCompleted++;
1049 ATRACE_INT("GPU Frames Outstanding", mQueue.size());
1050 }
1051 return true;
1052 }
1053
1054 uint32_t mFramesQueued;
1055 uint32_t mFramesCompleted;
1056 Vector<EGLSyncKHR> mQueue;
1057 Condition mCondition;
1058 Mutex mMutex;
1059};
1060
Dan Stozaa894d082015-02-19 15:27:36 -08001061EGLBoolean eglSwapBuffersWithDamageKHR(EGLDisplay dpy, EGLSurface draw,
1062 EGLint *rects, EGLint n_rects)
Mathias Agopian518ec112011-05-13 16:21:08 -07001063{
Jamie Gennis1c8e95c2012-02-23 19:27:23 -08001064 ATRACE_CALL();
Mathias Agopian518ec112011-05-13 16:21:08 -07001065 clearError();
1066
Jesse Hallb29e5e82012-04-04 16:53:42 -07001067 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001068 if (!dp) return EGL_FALSE;
1069
Jesse Hallb29e5e82012-04-04 16:53:42 -07001070 SurfaceRef _s(dp.get(), draw);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001071 if (!_s.get())
1072 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001073
Mathias Agopian518ec112011-05-13 16:21:08 -07001074 egl_surface_t const * const s = get_surface(draw);
Mathias Agopian7db993a2012-03-25 00:49:46 -07001075
Mathias Agopianed6d08b2013-04-16 16:39:46 -07001076 if (CC_UNLIKELY(dp->traceGpuCompletion)) {
1077 EGLSyncKHR sync = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, NULL);
1078 if (sync != EGL_NO_SYNC_KHR) {
1079 FrameCompletionThread::queueSync(sync);
1080 }
1081 }
1082
Mathias Agopian7db993a2012-03-25 00:49:46 -07001083 if (CC_UNLIKELY(dp->finishOnSwap)) {
1084 uint32_t pixel;
1085 egl_context_t * const c = get_context( egl_tls_t::getContext() );
1086 if (c) {
1087 // glReadPixels() ensures that the frame is complete
1088 s->cnx->hooks[c->version]->gl.glReadPixels(0,0,1,1,
1089 GL_RGBA,GL_UNSIGNED_BYTE,&pixel);
1090 }
1091 }
1092
Dan Stozaa894d082015-02-19 15:27:36 -08001093 if (n_rects == 0) {
1094 return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface);
1095 }
1096
1097 Vector<android_native_rect_t> androidRects;
1098 for (int r = 0; r < n_rects; ++r) {
1099 int offset = r * 4;
1100 int x = rects[offset];
1101 int y = rects[offset + 1];
1102 int width = rects[offset + 2];
1103 int height = rects[offset + 3];
1104 android_native_rect_t androidRect;
1105 androidRect.left = x;
1106 androidRect.top = y + height;
1107 androidRect.right = x + width;
1108 androidRect.bottom = y;
1109 androidRects.push_back(androidRect);
1110 }
1111 native_window_set_surface_damage(s->win.get(), androidRects.array(),
1112 androidRects.size());
1113
1114 if (s->cnx->egl.eglSwapBuffersWithDamageKHR) {
1115 return s->cnx->egl.eglSwapBuffersWithDamageKHR(dp->disp.dpy, s->surface,
1116 rects, n_rects);
1117 } else {
1118 return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface);
1119 }
1120}
1121
1122EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
1123{
1124 return eglSwapBuffersWithDamageKHR(dpy, surface, NULL, 0);
Mathias Agopian518ec112011-05-13 16:21:08 -07001125}
1126
1127EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface,
1128 NativePixmapType target)
1129{
1130 clearError();
1131
Jesse Hallb29e5e82012-04-04 16:53:42 -07001132 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001133 if (!dp) return EGL_FALSE;
1134
Jesse Hallb29e5e82012-04-04 16:53:42 -07001135 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001136 if (!_s.get())
1137 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001138
Mathias Agopian518ec112011-05-13 16:21:08 -07001139 egl_surface_t const * const s = get_surface(surface);
Mathias Agopianada798b2012-02-13 17:09:30 -08001140 return s->cnx->egl.eglCopyBuffers(dp->disp.dpy, s->surface, target);
Mathias Agopian518ec112011-05-13 16:21:08 -07001141}
1142
1143const char* eglQueryString(EGLDisplay dpy, EGLint name)
1144{
1145 clearError();
1146
Jesse Hallb29e5e82012-04-04 16:53:42 -07001147 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001148 if (!dp) return (const char *) NULL;
1149
1150 switch (name) {
1151 case EGL_VENDOR:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001152 return dp->getVendorString();
Mathias Agopian518ec112011-05-13 16:21:08 -07001153 case EGL_VERSION:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001154 return dp->getVersionString();
Mathias Agopian518ec112011-05-13 16:21:08 -07001155 case EGL_EXTENSIONS:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001156 return dp->getExtensionString();
Mathias Agopian518ec112011-05-13 16:21:08 -07001157 case EGL_CLIENT_APIS:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001158 return dp->getClientApiString();
Mathias Agopian518ec112011-05-13 16:21:08 -07001159 }
1160 return setError(EGL_BAD_PARAMETER, (const char *)0);
1161}
1162
Mathias Agopianca088332013-03-28 17:44:13 -07001163EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name)
1164{
1165 clearError();
1166
1167 const egl_display_ptr dp = validate_display(dpy);
1168 if (!dp) return (const char *) NULL;
1169
1170 switch (name) {
1171 case EGL_VENDOR:
1172 return dp->disp.queryString.vendor;
1173 case EGL_VERSION:
1174 return dp->disp.queryString.version;
1175 case EGL_EXTENSIONS:
1176 return dp->disp.queryString.extensions;
1177 case EGL_CLIENT_APIS:
1178 return dp->disp.queryString.clientApi;
1179 }
1180 return setError(EGL_BAD_PARAMETER, (const char *)0);
1181}
Mathias Agopian518ec112011-05-13 16:21:08 -07001182
1183// ----------------------------------------------------------------------------
1184// EGL 1.1
1185// ----------------------------------------------------------------------------
1186
1187EGLBoolean eglSurfaceAttrib(
1188 EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
1189{
1190 clearError();
1191
Jesse Hallb29e5e82012-04-04 16:53:42 -07001192 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001193 if (!dp) return EGL_FALSE;
1194
Jesse Hallb29e5e82012-04-04 16:53:42 -07001195 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001196 if (!_s.get())
1197 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001198
Mathias Agopian518ec112011-05-13 16:21:08 -07001199 egl_surface_t const * const s = get_surface(surface);
Pablo Ceballosccdfd602015-10-07 15:05:45 -07001200
Pablo Ceballos02b05da2016-02-02 17:53:18 -08001201 if (attribute == EGL_FRONT_BUFFER_AUTO_REFRESH_ANDROID) {
Pablo Ceballosf051ade2016-03-15 18:27:20 -07001202 int err = native_window_set_auto_refresh(s->win.get(),
1203 value ? true : false);
1204 return (err == NO_ERROR) ? EGL_TRUE :
1205 setError(EGL_BAD_SURFACE, EGL_FALSE);
Pablo Ceballosccdfd602015-10-07 15:05:45 -07001206 }
1207
Mathias Agopian518ec112011-05-13 16:21:08 -07001208 if (s->cnx->egl.eglSurfaceAttrib) {
1209 return s->cnx->egl.eglSurfaceAttrib(
Mathias Agopianada798b2012-02-13 17:09:30 -08001210 dp->disp.dpy, s->surface, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -07001211 }
1212 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1213}
1214
1215EGLBoolean eglBindTexImage(
1216 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1217{
1218 clearError();
1219
Jesse Hallb29e5e82012-04-04 16:53:42 -07001220 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001221 if (!dp) return EGL_FALSE;
1222
Jesse Hallb29e5e82012-04-04 16:53:42 -07001223 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001224 if (!_s.get())
1225 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001226
Mathias Agopian518ec112011-05-13 16:21:08 -07001227 egl_surface_t const * const s = get_surface(surface);
1228 if (s->cnx->egl.eglBindTexImage) {
1229 return s->cnx->egl.eglBindTexImage(
Mathias Agopianada798b2012-02-13 17:09:30 -08001230 dp->disp.dpy, s->surface, buffer);
Mathias Agopian518ec112011-05-13 16:21:08 -07001231 }
1232 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1233}
1234
1235EGLBoolean eglReleaseTexImage(
1236 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1237{
1238 clearError();
1239
Jesse Hallb29e5e82012-04-04 16:53:42 -07001240 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001241 if (!dp) return EGL_FALSE;
1242
Jesse Hallb29e5e82012-04-04 16:53:42 -07001243 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001244 if (!_s.get())
1245 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001246
Mathias Agopian518ec112011-05-13 16:21:08 -07001247 egl_surface_t const * const s = get_surface(surface);
1248 if (s->cnx->egl.eglReleaseTexImage) {
1249 return s->cnx->egl.eglReleaseTexImage(
Mathias Agopianada798b2012-02-13 17:09:30 -08001250 dp->disp.dpy, s->surface, buffer);
Mathias Agopian518ec112011-05-13 16:21:08 -07001251 }
1252 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1253}
1254
1255EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
1256{
1257 clearError();
1258
Jesse Hallb29e5e82012-04-04 16:53:42 -07001259 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001260 if (!dp) return EGL_FALSE;
1261
1262 EGLBoolean res = EGL_TRUE;
Mathias Agopianada798b2012-02-13 17:09:30 -08001263 egl_connection_t* const cnx = &gEGLImpl;
1264 if (cnx->dso && cnx->egl.eglSwapInterval) {
1265 res = cnx->egl.eglSwapInterval(dp->disp.dpy, interval);
Mathias Agopian518ec112011-05-13 16:21:08 -07001266 }
Mathias Agopianada798b2012-02-13 17:09:30 -08001267
Mathias Agopian518ec112011-05-13 16:21:08 -07001268 return res;
1269}
1270
1271
1272// ----------------------------------------------------------------------------
1273// EGL 1.2
1274// ----------------------------------------------------------------------------
1275
1276EGLBoolean eglWaitClient(void)
1277{
1278 clearError();
1279
Mathias Agopianada798b2012-02-13 17:09:30 -08001280 egl_connection_t* const cnx = &gEGLImpl;
1281 if (!cnx->dso)
1282 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1283
1284 EGLBoolean res;
1285 if (cnx->egl.eglWaitClient) {
1286 res = cnx->egl.eglWaitClient();
1287 } else {
1288 res = cnx->egl.eglWaitGL();
Mathias Agopian518ec112011-05-13 16:21:08 -07001289 }
1290 return res;
1291}
1292
1293EGLBoolean eglBindAPI(EGLenum api)
1294{
1295 clearError();
1296
1297 if (egl_init_drivers() == EGL_FALSE) {
1298 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1299 }
1300
1301 // bind this API on all EGLs
1302 EGLBoolean res = EGL_TRUE;
Mathias Agopianada798b2012-02-13 17:09:30 -08001303 egl_connection_t* const cnx = &gEGLImpl;
1304 if (cnx->dso && cnx->egl.eglBindAPI) {
1305 res = cnx->egl.eglBindAPI(api);
Mathias Agopian518ec112011-05-13 16:21:08 -07001306 }
1307 return res;
1308}
1309
1310EGLenum eglQueryAPI(void)
1311{
1312 clearError();
1313
1314 if (egl_init_drivers() == EGL_FALSE) {
1315 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1316 }
1317
Mathias Agopianada798b2012-02-13 17:09:30 -08001318 egl_connection_t* const cnx = &gEGLImpl;
1319 if (cnx->dso && cnx->egl.eglQueryAPI) {
1320 return cnx->egl.eglQueryAPI();
Mathias Agopian518ec112011-05-13 16:21:08 -07001321 }
Mathias Agopianada798b2012-02-13 17:09:30 -08001322
Mathias Agopian518ec112011-05-13 16:21:08 -07001323 // or, it can only be OpenGL ES
1324 return EGL_OPENGL_ES_API;
1325}
1326
1327EGLBoolean eglReleaseThread(void)
1328{
1329 clearError();
1330
1331 // If there is context bound to the thread, release it
Mathias Agopianfb87e542012-01-30 18:20:52 -08001332 egl_display_t::loseCurrent(get_context(getContext()));
Mathias Agopian518ec112011-05-13 16:21:08 -07001333
Mathias Agopianada798b2012-02-13 17:09:30 -08001334 egl_connection_t* const cnx = &gEGLImpl;
1335 if (cnx->dso && cnx->egl.eglReleaseThread) {
1336 cnx->egl.eglReleaseThread();
Mathias Agopian518ec112011-05-13 16:21:08 -07001337 }
1338 egl_tls_t::clearTLS();
Mathias Agopian518ec112011-05-13 16:21:08 -07001339 return EGL_TRUE;
1340}
1341
1342EGLSurface eglCreatePbufferFromClientBuffer(
1343 EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer,
1344 EGLConfig config, const EGLint *attrib_list)
1345{
1346 clearError();
1347
Jesse Hallb29e5e82012-04-04 16:53:42 -07001348 egl_connection_t* cnx = NULL;
1349 const egl_display_ptr dp = validate_display_connection(dpy, cnx);
1350 if (!dp) return EGL_FALSE;
Mathias Agopian518ec112011-05-13 16:21:08 -07001351 if (cnx->egl.eglCreatePbufferFromClientBuffer) {
1352 return cnx->egl.eglCreatePbufferFromClientBuffer(
Mathias Agopian7773c432012-02-13 20:06:08 -08001353 dp->disp.dpy, buftype, buffer, config, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001354 }
1355 return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE);
1356}
1357
1358// ----------------------------------------------------------------------------
1359// EGL_EGLEXT_VERSION 3
1360// ----------------------------------------------------------------------------
1361
1362EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface,
1363 const EGLint *attrib_list)
1364{
1365 clearError();
1366
Jesse Hallb29e5e82012-04-04 16:53:42 -07001367 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001368 if (!dp) return EGL_FALSE;
1369
Jesse Hallb29e5e82012-04-04 16:53:42 -07001370 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001371 if (!_s.get())
1372 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001373
1374 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian518ec112011-05-13 16:21:08 -07001375 if (s->cnx->egl.eglLockSurfaceKHR) {
1376 return s->cnx->egl.eglLockSurfaceKHR(
Mathias Agopianada798b2012-02-13 17:09:30 -08001377 dp->disp.dpy, s->surface, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001378 }
1379 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1380}
1381
1382EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface)
1383{
1384 clearError();
1385
Jesse Hallb29e5e82012-04-04 16:53:42 -07001386 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001387 if (!dp) return EGL_FALSE;
1388
Jesse Hallb29e5e82012-04-04 16:53:42 -07001389 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001390 if (!_s.get())
1391 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001392
1393 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian518ec112011-05-13 16:21:08 -07001394 if (s->cnx->egl.eglUnlockSurfaceKHR) {
Mathias Agopianada798b2012-02-13 17:09:30 -08001395 return s->cnx->egl.eglUnlockSurfaceKHR(dp->disp.dpy, s->surface);
Mathias Agopian518ec112011-05-13 16:21:08 -07001396 }
1397 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1398}
1399
1400EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
1401 EGLClientBuffer buffer, const EGLint *attrib_list)
1402{
1403 clearError();
1404
Jesse Hallb29e5e82012-04-04 16:53:42 -07001405 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001406 if (!dp) return EGL_NO_IMAGE_KHR;
1407
Jesse Hallb29e5e82012-04-04 16:53:42 -07001408 ContextRef _c(dp.get(), ctx);
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001409 egl_context_t * const c = _c.get();
Mathias Agopian518ec112011-05-13 16:21:08 -07001410
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001411 EGLImageKHR result = EGL_NO_IMAGE_KHR;
1412 egl_connection_t* const cnx = &gEGLImpl;
1413 if (cnx->dso && cnx->egl.eglCreateImageKHR) {
1414 result = cnx->egl.eglCreateImageKHR(
1415 dp->disp.dpy,
1416 c ? c->context : EGL_NO_CONTEXT,
1417 target, buffer, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001418 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001419 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001420}
1421
1422EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
1423{
1424 clearError();
1425
Jesse Hallb29e5e82012-04-04 16:53:42 -07001426 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001427 if (!dp) return EGL_FALSE;
1428
Steven Holte646a5c52012-06-04 20:02:11 -07001429 EGLBoolean result = EGL_FALSE;
Mathias Agopianada798b2012-02-13 17:09:30 -08001430 egl_connection_t* const cnx = &gEGLImpl;
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001431 if (cnx->dso && cnx->egl.eglDestroyImageKHR) {
Steven Holte646a5c52012-06-04 20:02:11 -07001432 result = cnx->egl.eglDestroyImageKHR(dp->disp.dpy, img);
Mathias Agopian518ec112011-05-13 16:21:08 -07001433 }
Steven Holte646a5c52012-06-04 20:02:11 -07001434 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001435}
1436
1437// ----------------------------------------------------------------------------
1438// EGL_EGLEXT_VERSION 5
1439// ----------------------------------------------------------------------------
1440
1441
1442EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
1443{
1444 clearError();
1445
Jesse Hallb29e5e82012-04-04 16:53:42 -07001446 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001447 if (!dp) return EGL_NO_SYNC_KHR;
1448
Mathias Agopian518ec112011-05-13 16:21:08 -07001449 EGLSyncKHR result = EGL_NO_SYNC_KHR;
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001450 egl_connection_t* const cnx = &gEGLImpl;
1451 if (cnx->dso && cnx->egl.eglCreateSyncKHR) {
1452 result = cnx->egl.eglCreateSyncKHR(dp->disp.dpy, type, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001453 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001454 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001455}
1456
1457EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
1458{
1459 clearError();
1460
Jesse Hallb29e5e82012-04-04 16:53:42 -07001461 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001462 if (!dp) return EGL_FALSE;
1463
Mathias Agopian518ec112011-05-13 16:21:08 -07001464 EGLBoolean result = EGL_FALSE;
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001465 egl_connection_t* const cnx = &gEGLImpl;
1466 if (cnx->dso && cnx->egl.eglDestroySyncKHR) {
1467 result = cnx->egl.eglDestroySyncKHR(dp->disp.dpy, sync);
Mathias Agopian518ec112011-05-13 16:21:08 -07001468 }
1469 return result;
1470}
1471
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -07001472EGLBoolean eglSignalSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode) {
1473 clearError();
1474
1475 const egl_display_ptr dp = validate_display(dpy);
1476 if (!dp) return EGL_FALSE;
1477
1478 EGLBoolean result = EGL_FALSE;
1479 egl_connection_t* const cnx = &gEGLImpl;
1480 if (cnx->dso && cnx->egl.eglSignalSyncKHR) {
1481 result = cnx->egl.eglSignalSyncKHR(
1482 dp->disp.dpy, sync, mode);
1483 }
1484 return result;
1485}
1486
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001487EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync,
1488 EGLint flags, EGLTimeKHR timeout)
Mathias Agopian518ec112011-05-13 16:21:08 -07001489{
1490 clearError();
1491
Jesse Hallb29e5e82012-04-04 16:53:42 -07001492 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001493 if (!dp) return EGL_FALSE;
1494
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001495 EGLBoolean result = EGL_FALSE;
1496 egl_connection_t* const cnx = &gEGLImpl;
1497 if (cnx->dso && cnx->egl.eglClientWaitSyncKHR) {
1498 result = cnx->egl.eglClientWaitSyncKHR(
1499 dp->disp.dpy, sync, flags, timeout);
Mathias Agopian518ec112011-05-13 16:21:08 -07001500 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001501 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001502}
1503
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001504EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync,
1505 EGLint attribute, EGLint *value)
Mathias Agopian518ec112011-05-13 16:21:08 -07001506{
1507 clearError();
1508
Jesse Hallb29e5e82012-04-04 16:53:42 -07001509 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001510 if (!dp) return EGL_FALSE;
1511
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001512 EGLBoolean result = EGL_FALSE;
1513 egl_connection_t* const cnx = &gEGLImpl;
1514 if (cnx->dso && cnx->egl.eglGetSyncAttribKHR) {
1515 result = cnx->egl.eglGetSyncAttribKHR(
1516 dp->disp.dpy, sync, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -07001517 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001518 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001519}
1520
Season Li000d88f2015-07-01 11:39:40 -07001521EGLStreamKHR eglCreateStreamKHR(EGLDisplay dpy, const EGLint *attrib_list)
1522{
1523 clearError();
1524
1525 const egl_display_ptr dp = validate_display(dpy);
1526 if (!dp) return EGL_NO_STREAM_KHR;
1527
1528 EGLStreamKHR result = EGL_NO_STREAM_KHR;
1529 egl_connection_t* const cnx = &gEGLImpl;
1530 if (cnx->dso && cnx->egl.eglCreateStreamKHR) {
1531 result = cnx->egl.eglCreateStreamKHR(
1532 dp->disp.dpy, attrib_list);
1533 }
1534 return result;
1535}
1536
1537EGLBoolean eglDestroyStreamKHR(EGLDisplay dpy, EGLStreamKHR stream)
1538{
1539 clearError();
1540
1541 const egl_display_ptr dp = validate_display(dpy);
1542 if (!dp) return EGL_FALSE;
1543
1544 EGLBoolean result = EGL_FALSE;
1545 egl_connection_t* const cnx = &gEGLImpl;
1546 if (cnx->dso && cnx->egl.eglDestroyStreamKHR) {
1547 result = cnx->egl.eglDestroyStreamKHR(
1548 dp->disp.dpy, stream);
1549 }
1550 return result;
1551}
1552
1553EGLBoolean eglStreamAttribKHR(EGLDisplay dpy, EGLStreamKHR stream,
1554 EGLenum attribute, EGLint value)
1555{
1556 clearError();
1557
1558 const egl_display_ptr dp = validate_display(dpy);
1559 if (!dp) return EGL_FALSE;
1560
1561 EGLBoolean result = EGL_FALSE;
1562 egl_connection_t* const cnx = &gEGLImpl;
1563 if (cnx->dso && cnx->egl.eglStreamAttribKHR) {
1564 result = cnx->egl.eglStreamAttribKHR(
1565 dp->disp.dpy, stream, attribute, value);
1566 }
1567 return result;
1568}
1569
1570EGLBoolean eglQueryStreamKHR(EGLDisplay dpy, EGLStreamKHR stream,
1571 EGLenum attribute, EGLint *value)
1572{
1573 clearError();
1574
1575 const egl_display_ptr dp = validate_display(dpy);
1576 if (!dp) return EGL_FALSE;
1577
1578 EGLBoolean result = EGL_FALSE;
1579 egl_connection_t* const cnx = &gEGLImpl;
1580 if (cnx->dso && cnx->egl.eglQueryStreamKHR) {
1581 result = cnx->egl.eglQueryStreamKHR(
1582 dp->disp.dpy, stream, attribute, value);
1583 }
1584 return result;
1585}
1586
1587EGLBoolean eglQueryStreamu64KHR(EGLDisplay dpy, EGLStreamKHR stream,
1588 EGLenum attribute, EGLuint64KHR *value)
1589{
1590 clearError();
1591
1592 const egl_display_ptr dp = validate_display(dpy);
1593 if (!dp) return EGL_FALSE;
1594
1595 EGLBoolean result = EGL_FALSE;
1596 egl_connection_t* const cnx = &gEGLImpl;
1597 if (cnx->dso && cnx->egl.eglQueryStreamu64KHR) {
1598 result = cnx->egl.eglQueryStreamu64KHR(
1599 dp->disp.dpy, stream, attribute, value);
1600 }
1601 return result;
1602}
1603
1604EGLBoolean eglQueryStreamTimeKHR(EGLDisplay dpy, EGLStreamKHR stream,
1605 EGLenum attribute, EGLTimeKHR *value)
1606{
1607 clearError();
1608
1609 const egl_display_ptr dp = validate_display(dpy);
1610 if (!dp) return EGL_FALSE;
1611
1612 EGLBoolean result = EGL_FALSE;
1613 egl_connection_t* const cnx = &gEGLImpl;
1614 if (cnx->dso && cnx->egl.eglQueryStreamTimeKHR) {
1615 result = cnx->egl.eglQueryStreamTimeKHR(
1616 dp->disp.dpy, stream, attribute, value);
1617 }
1618 return result;
1619}
1620
1621EGLSurface eglCreateStreamProducerSurfaceKHR(EGLDisplay dpy, EGLConfig config,
1622 EGLStreamKHR stream, const EGLint *attrib_list)
1623{
1624 clearError();
1625
1626 egl_display_ptr dp = validate_display(dpy);
1627 if (!dp) return EGL_NO_SURFACE;
1628
1629 egl_connection_t* const cnx = &gEGLImpl;
1630 if (cnx->dso && cnx->egl.eglCreateStreamProducerSurfaceKHR) {
1631 EGLSurface surface = cnx->egl.eglCreateStreamProducerSurfaceKHR(
1632 dp->disp.dpy, config, stream, attrib_list);
1633 if (surface != EGL_NO_SURFACE) {
1634 egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL,
1635 surface, cnx);
1636 return s;
1637 }
1638 }
1639 return EGL_NO_SURFACE;
1640}
1641
1642EGLBoolean eglStreamConsumerGLTextureExternalKHR(EGLDisplay dpy,
1643 EGLStreamKHR stream)
1644{
1645 clearError();
1646
1647 const egl_display_ptr dp = validate_display(dpy);
1648 if (!dp) return EGL_FALSE;
1649
1650 EGLBoolean result = EGL_FALSE;
1651 egl_connection_t* const cnx = &gEGLImpl;
1652 if (cnx->dso && cnx->egl.eglStreamConsumerGLTextureExternalKHR) {
1653 result = cnx->egl.eglStreamConsumerGLTextureExternalKHR(
1654 dp->disp.dpy, stream);
1655 }
1656 return result;
1657}
1658
1659EGLBoolean eglStreamConsumerAcquireKHR(EGLDisplay dpy,
1660 EGLStreamKHR stream)
1661{
1662 clearError();
1663
1664 const egl_display_ptr dp = validate_display(dpy);
1665 if (!dp) return EGL_FALSE;
1666
1667 EGLBoolean result = EGL_FALSE;
1668 egl_connection_t* const cnx = &gEGLImpl;
1669 if (cnx->dso && cnx->egl.eglStreamConsumerAcquireKHR) {
1670 result = cnx->egl.eglStreamConsumerAcquireKHR(
1671 dp->disp.dpy, stream);
1672 }
1673 return result;
1674}
1675
1676EGLBoolean eglStreamConsumerReleaseKHR(EGLDisplay dpy,
1677 EGLStreamKHR stream)
1678{
1679 clearError();
1680
1681 const egl_display_ptr dp = validate_display(dpy);
1682 if (!dp) return EGL_FALSE;
1683
1684 EGLBoolean result = EGL_FALSE;
1685 egl_connection_t* const cnx = &gEGLImpl;
1686 if (cnx->dso && cnx->egl.eglStreamConsumerReleaseKHR) {
1687 result = cnx->egl.eglStreamConsumerReleaseKHR(
1688 dp->disp.dpy, stream);
1689 }
1690 return result;
1691}
1692
1693EGLNativeFileDescriptorKHR eglGetStreamFileDescriptorKHR(
1694 EGLDisplay dpy, EGLStreamKHR stream)
1695{
1696 clearError();
1697
1698 const egl_display_ptr dp = validate_display(dpy);
1699 if (!dp) return EGL_NO_FILE_DESCRIPTOR_KHR;
1700
1701 EGLNativeFileDescriptorKHR result = EGL_NO_FILE_DESCRIPTOR_KHR;
1702 egl_connection_t* const cnx = &gEGLImpl;
1703 if (cnx->dso && cnx->egl.eglGetStreamFileDescriptorKHR) {
1704 result = cnx->egl.eglGetStreamFileDescriptorKHR(
1705 dp->disp.dpy, stream);
1706 }
1707 return result;
1708}
1709
1710EGLStreamKHR eglCreateStreamFromFileDescriptorKHR(
1711 EGLDisplay dpy, EGLNativeFileDescriptorKHR file_descriptor)
1712{
1713 clearError();
1714
1715 const egl_display_ptr dp = validate_display(dpy);
1716 if (!dp) return EGL_NO_STREAM_KHR;
1717
1718 EGLStreamKHR result = EGL_NO_STREAM_KHR;
1719 egl_connection_t* const cnx = &gEGLImpl;
1720 if (cnx->dso && cnx->egl.eglCreateStreamFromFileDescriptorKHR) {
1721 result = cnx->egl.eglCreateStreamFromFileDescriptorKHR(
1722 dp->disp.dpy, file_descriptor);
1723 }
1724 return result;
1725}
1726
Mathias Agopian518ec112011-05-13 16:21:08 -07001727// ----------------------------------------------------------------------------
Mathias Agopian2bb71682013-03-27 17:32:41 -07001728// EGL_EGLEXT_VERSION 15
1729// ----------------------------------------------------------------------------
1730
1731EGLint eglWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags) {
1732 clearError();
1733 const egl_display_ptr dp = validate_display(dpy);
1734 if (!dp) return EGL_FALSE;
1735 EGLint result = EGL_FALSE;
1736 egl_connection_t* const cnx = &gEGLImpl;
1737 if (cnx->dso && cnx->egl.eglWaitSyncKHR) {
1738 result = cnx->egl.eglWaitSyncKHR(dp->disp.dpy, sync, flags);
1739 }
1740 return result;
1741}
1742
1743// ----------------------------------------------------------------------------
Mathias Agopian518ec112011-05-13 16:21:08 -07001744// ANDROID extensions
1745// ----------------------------------------------------------------------------
1746
Jamie Gennis331841b2012-09-06 14:52:00 -07001747EGLint eglDupNativeFenceFDANDROID(EGLDisplay dpy, EGLSyncKHR sync)
1748{
1749 clearError();
1750
1751 const egl_display_ptr dp = validate_display(dpy);
1752 if (!dp) return EGL_NO_NATIVE_FENCE_FD_ANDROID;
1753
1754 EGLint result = EGL_NO_NATIVE_FENCE_FD_ANDROID;
1755 egl_connection_t* const cnx = &gEGLImpl;
1756 if (cnx->dso && cnx->egl.eglDupNativeFenceFDANDROID) {
1757 result = cnx->egl.eglDupNativeFenceFDANDROID(dp->disp.dpy, sync);
1758 }
1759 return result;
1760}
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001761
Andy McFadden72841452013-03-01 16:25:32 -08001762EGLBoolean eglPresentationTimeANDROID(EGLDisplay dpy, EGLSurface surface,
1763 EGLnsecsANDROID time)
1764{
1765 clearError();
1766
1767 const egl_display_ptr dp = validate_display(dpy);
1768 if (!dp) {
1769 return EGL_FALSE;
1770 }
1771
1772 SurfaceRef _s(dp.get(), surface);
1773 if (!_s.get()) {
1774 setError(EGL_BAD_SURFACE, EGL_FALSE);
1775 return EGL_FALSE;
1776 }
1777
1778 egl_surface_t const * const s = get_surface(surface);
1779 native_window_set_buffers_timestamp(s->win.get(), time);
1780
1781 return EGL_TRUE;
1782}
1783
Craig Donner05249fc2016-01-15 19:33:55 -08001784EGLClientBuffer eglCreateNativeClientBufferANDROID(const EGLint *attrib_list)
1785{
1786 clearError();
1787
1788 int usage = 0;
1789 uint32_t width = 0;
1790 uint32_t height = 0;
1791 uint32_t format = 0;
1792 uint32_t red_size = 0;
1793 uint32_t green_size = 0;
1794 uint32_t blue_size = 0;
1795 uint32_t alpha_size = 0;
1796
1797#define GET_POSITIVE_VALUE(case_name, target) \
1798 case case_name: \
1799 if (value > 0) { \
1800 target = value; \
1801 } else { \
1802 return setError(EGL_BAD_PARAMETER, (EGLClientBuffer)0); \
1803 } \
1804 break
1805
1806 if (attrib_list) {
1807 while (*attrib_list != EGL_NONE) {
1808 GLint attr = *attrib_list++;
1809 GLint value = *attrib_list++;
1810 switch (attr) {
1811 GET_POSITIVE_VALUE(EGL_WIDTH, width);
1812 GET_POSITIVE_VALUE(EGL_HEIGHT, height);
1813 GET_POSITIVE_VALUE(EGL_RED_SIZE, red_size);
1814 GET_POSITIVE_VALUE(EGL_GREEN_SIZE, green_size);
1815 GET_POSITIVE_VALUE(EGL_BLUE_SIZE, blue_size);
1816 GET_POSITIVE_VALUE(EGL_ALPHA_SIZE, alpha_size);
1817 case EGL_NATIVE_BUFFER_USAGE_ANDROID:
1818 if (value & EGL_NATIVE_BUFFER_USAGE_PROTECTED_BIT_ANDROID) {
1819 usage |= GRALLOC_USAGE_PROTECTED;
Craig Donner05249fc2016-01-15 19:33:55 -08001820 }
Craig Donner8cfae6d2016-04-12 16:54:03 -07001821 if (value & EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_BIT_ANDROID) {
Craig Donner05249fc2016-01-15 19:33:55 -08001822 usage |= GRALLOC_USAGE_HW_RENDER;
1823 }
Craig Donner8cfae6d2016-04-12 16:54:03 -07001824 if (value & EGL_NATIVE_BUFFER_USAGE_TEXTURE_BIT_ANDROID) {
Craig Donner05249fc2016-01-15 19:33:55 -08001825 usage |= GRALLOC_USAGE_HW_TEXTURE;
1826 }
1827 // The buffer must be used for either a texture or a
1828 // renderbuffer.
Craig Donner8cfae6d2016-04-12 16:54:03 -07001829 if ((value & EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_BIT_ANDROID) &&
1830 (value & EGL_NATIVE_BUFFER_USAGE_TEXTURE_BIT_ANDROID)) {
Craig Donner05249fc2016-01-15 19:33:55 -08001831 return setError(EGL_BAD_PARAMETER, (EGLClientBuffer)0);
1832 }
1833 break;
1834 default:
1835 return setError(EGL_BAD_PARAMETER, (EGLClientBuffer)0);
1836 }
1837 }
1838 }
1839#undef GET_POSITIVE_VALUE
1840
1841 // Validate format.
1842 if (red_size == 8 && green_size == 8 && blue_size == 8) {
1843 if (alpha_size == 8) {
1844 format = HAL_PIXEL_FORMAT_RGBA_8888;
1845 } else {
1846 format = HAL_PIXEL_FORMAT_RGB_888;
1847 }
1848 } else if (red_size == 5 && green_size == 6 && blue_size == 5 &&
1849 alpha_size == 0) {
1850 format == HAL_PIXEL_FORMAT_RGB_565;
1851 } else {
1852 ALOGE("Invalid native pixel format { r=%d, g=%d, b=%d, a=%d }",
1853 red_size, green_size, blue_size, alpha_size);
1854 return setError(EGL_BAD_PARAMETER, (EGLClientBuffer)0);
1855 }
1856
1857 GraphicBuffer* gBuffer = new GraphicBuffer(width, height, format, usage);
1858 const status_t err = gBuffer->initCheck();
1859 if (err != NO_ERROR) {
1860 ALOGE("Unable to create native buffer { w=%d, h=%d, f=%d, u=%#x }: %#x",
1861 width, height, format, usage, err);
1862 // Destroy the buffer.
1863 sp<GraphicBuffer> holder(gBuffer);
1864 return setError(EGL_BAD_ALLOC, (EGLClientBuffer)0);
1865 }
1866 ALOGD("Created new native buffer %p { w=%d, h=%d, f=%d, u=%#x }",
1867 gBuffer, width, height, format, usage);
1868 return static_cast<EGLClientBuffer>(gBuffer->getNativeBuffer());
1869}
1870
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001871// ----------------------------------------------------------------------------
1872// NVIDIA extensions
1873// ----------------------------------------------------------------------------
1874EGLuint64NV eglGetSystemTimeFrequencyNV()
1875{
1876 clearError();
1877
1878 if (egl_init_drivers() == EGL_FALSE) {
1879 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1880 }
1881
1882 EGLuint64NV ret = 0;
Mathias Agopianada798b2012-02-13 17:09:30 -08001883 egl_connection_t* const cnx = &gEGLImpl;
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001884
Mathias Agopianada798b2012-02-13 17:09:30 -08001885 if (cnx->dso && cnx->egl.eglGetSystemTimeFrequencyNV) {
1886 return cnx->egl.eglGetSystemTimeFrequencyNV();
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001887 }
1888
Mathias Agopian0e8bbee2011-10-05 19:15:05 -07001889 return setErrorQuiet(EGL_BAD_DISPLAY, 0);
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001890}
1891
1892EGLuint64NV eglGetSystemTimeNV()
1893{
1894 clearError();
1895
1896 if (egl_init_drivers() == EGL_FALSE) {
1897 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1898 }
1899
1900 EGLuint64NV ret = 0;
Mathias Agopianada798b2012-02-13 17:09:30 -08001901 egl_connection_t* const cnx = &gEGLImpl;
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001902
Mathias Agopianada798b2012-02-13 17:09:30 -08001903 if (cnx->dso && cnx->egl.eglGetSystemTimeNV) {
1904 return cnx->egl.eglGetSystemTimeNV();
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001905 }
1906
Mathias Agopian0e8bbee2011-10-05 19:15:05 -07001907 return setErrorQuiet(EGL_BAD_DISPLAY, 0);
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001908}
Dan Stozaa894d082015-02-19 15:27:36 -08001909
1910// ----------------------------------------------------------------------------
1911// Partial update extension
1912// ----------------------------------------------------------------------------
1913EGLBoolean eglSetDamageRegionKHR(EGLDisplay dpy, EGLSurface surface,
1914 EGLint *rects, EGLint n_rects)
1915{
1916 clearError();
1917
1918 const egl_display_ptr dp = validate_display(dpy);
1919 if (!dp) {
1920 setError(EGL_BAD_DISPLAY, EGL_FALSE);
1921 return EGL_FALSE;
1922 }
1923
1924 SurfaceRef _s(dp.get(), surface);
1925 if (!_s.get()) {
1926 setError(EGL_BAD_SURFACE, EGL_FALSE);
1927 return EGL_FALSE;
1928 }
1929
1930 egl_surface_t const * const s = get_surface(surface);
1931 if (s->cnx->egl.eglSetDamageRegionKHR) {
1932 return s->cnx->egl.eglSetDamageRegionKHR(dp->disp.dpy, s->surface,
1933 rects, n_rects);
1934 }
1935
1936 return EGL_FALSE;
1937}