blob: c37582390f66909495d6b86f4a2415e03ba488ba [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
Mathias Agopian518ec112011-05-13 16:21:08 -070019#include <ctype.h>
Mark Salyzyna5e161b2016-09-29 08:08:05 -070020#include <dlfcn.h>
Mathias Agopian518ec112011-05-13 16:21:08 -070021#include <stdlib.h>
22#include <string.h>
23
Craig Donnere96a3252017-02-02 12:13:34 -080024#include <hardware/gralloc1.h>
Mathias Agopian518ec112011-05-13 16:21:08 -070025#include <system/window.h>
26
27#include <EGL/egl.h>
28#include <EGL/eglext.h>
Mathias Agopian518ec112011-05-13 16:21:08 -070029
Craig Donner60761072017-01-27 12:30:44 -080030#include <android/hardware_buffer.h>
Mathias Agopian89ed4c82017-02-09 18:48:34 -080031#include <private/android/AHardwareBufferHelpers.h>
32
Mathias Agopian518ec112011-05-13 16:21:08 -070033#include <cutils/atomic.h>
Mathias Agopian7db993a2012-03-25 00:49:46 -070034#include <cutils/compiler.h>
Mathias Agopian518ec112011-05-13 16:21:08 -070035#include <cutils/memory.h>
Mark Salyzyna5e161b2016-09-29 08:08:05 -070036#include <cutils/properties.h>
Mark Salyzyn7823e122016-09-29 08:08:05 -070037#include <log/log.h>
Mathias Agopian518ec112011-05-13 16:21:08 -070038
Craig Donner68671532016-07-18 10:19:54 -070039#include <gui/ISurfaceComposer.h>
40
Craig Donner05249fc2016-01-15 19:33:55 -080041#include <ui/GraphicBuffer.h>
42
Mathias Agopian89ed4c82017-02-09 18:48:34 -080043
Mathias Agopian518ec112011-05-13 16:21:08 -070044#include <utils/KeyedVector.h>
45#include <utils/SortedVector.h>
46#include <utils/String8.h>
Jamie Gennis1c8e95c2012-02-23 19:27:23 -080047#include <utils/Trace.h>
Mathias Agopian518ec112011-05-13 16:21:08 -070048
Craig Donner68671532016-07-18 10:19:54 -070049#include "binder/Binder.h"
50#include "binder/Parcel.h"
51#include "binder/IServiceManager.h"
52
Mathias Agopian39c24a22013-04-04 23:17:56 -070053#include "../egl_impl.h"
Mathias Agopian39c24a22013-04-04 23:17:56 -070054#include "../hooks.h"
Mathias Agopian518ec112011-05-13 16:21:08 -070055
56#include "egl_display.h"
Mathias Agopian518ec112011-05-13 16:21:08 -070057#include "egl_object.h"
58#include "egl_tls.h"
Mathias Agopianada798b2012-02-13 17:09:30 -080059#include "egldefs.h"
Mathias Agopian518ec112011-05-13 16:21:08 -070060
61using namespace android;
62
63// ----------------------------------------------------------------------------
64
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070065namespace android {
66
Mathias Agopian518ec112011-05-13 16:21:08 -070067struct extention_map_t {
68 const char* name;
69 __eglMustCastToProperFunctionPointerType address;
70};
71
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070072/*
Jesse Hall21558da2013-08-06 15:31:22 -070073 * This is the list of EGL extensions exposed to applications.
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070074 *
Jesse Hall21558da2013-08-06 15:31:22 -070075 * Some of them (gBuiltinExtensionString) are implemented entirely in this EGL
76 * wrapper and are always available.
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070077 *
Jesse Hall21558da2013-08-06 15:31:22 -070078 * The rest (gExtensionString) depend on support in the EGL driver, and are
79 * only available if the driver supports them. However, some of these must be
80 * supported because they are used by the Android system itself; these are
Pablo Ceballos02b05da2016-02-02 17:53:18 -080081 * listed as mandatory below and are required by the CDD. The system *assumes*
Jesse Hall21558da2013-08-06 15:31:22 -070082 * the mandatory extensions are present and may not function properly if some
83 * are missing.
84 *
85 * NOTE: Both strings MUST have a single space as the last character.
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070086 */
Jesse Hall21558da2013-08-06 15:31:22 -070087extern char const * const gBuiltinExtensionString =
88 "EGL_KHR_get_all_proc_addresses "
89 "EGL_ANDROID_presentation_time "
Dan Stozaa894d082015-02-19 15:27:36 -080090 "EGL_KHR_swap_buffers_with_damage "
Craig Donner05249fc2016-01-15 19:33:55 -080091 "EGL_ANDROID_create_native_client_buffer "
Craig Donner60761072017-01-27 12:30:44 -080092 "EGL_ANDROID_get_native_client_buffer "
Pablo Ceballos02b05da2016-02-02 17:53:18 -080093 "EGL_ANDROID_front_buffer_auto_refresh "
Pablo Ceballosc18be292016-05-31 14:55:42 -070094 "EGL_ANDROID_get_frame_timestamps "
Jesse Hall21558da2013-08-06 15:31:22 -070095 ;
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070096extern char const * const gExtensionString =
97 "EGL_KHR_image " // mandatory
98 "EGL_KHR_image_base " // mandatory
99 "EGL_KHR_image_pixmap "
100 "EGL_KHR_lock_surface "
Jesse Hallc2e41222013-08-08 13:40:22 -0700101 "EGL_KHR_gl_colorspace "
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700102 "EGL_KHR_gl_texture_2D_image "
Season Li000d88f2015-07-01 11:39:40 -0700103 "EGL_KHR_gl_texture_3D_image "
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700104 "EGL_KHR_gl_texture_cubemap_image "
105 "EGL_KHR_gl_renderbuffer_image "
106 "EGL_KHR_reusable_sync "
107 "EGL_KHR_fence_sync "
Jamie Gennisf6d1c392013-04-25 18:48:41 -0700108 "EGL_KHR_create_context "
Season Li000d88f2015-07-01 11:39:40 -0700109 "EGL_KHR_config_attribs "
110 "EGL_KHR_surfaceless_context "
111 "EGL_KHR_stream "
112 "EGL_KHR_stream_fifo "
113 "EGL_KHR_stream_producer_eglsurface "
114 "EGL_KHR_stream_consumer_gltexture "
115 "EGL_KHR_stream_cross_process_fd "
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700116 "EGL_EXT_create_context_robustness "
117 "EGL_NV_system_time "
118 "EGL_ANDROID_image_native_buffer " // mandatory
Mathias Agopian2bb71682013-03-27 17:32:41 -0700119 "EGL_KHR_wait_sync " // strongly recommended
Jamie Gennisdbe92452013-09-23 17:22:10 -0700120 "EGL_ANDROID_recordable " // mandatory
Dan Stozaa894d082015-02-19 15:27:36 -0800121 "EGL_KHR_partial_update " // strongly recommended
Courtney Goeltzenleuchter0e4e3952016-11-16 13:53:40 -0700122 "EGL_EXT_pixel_format_float "
Dan Stozaa894d082015-02-19 15:27:36 -0800123 "EGL_EXT_buffer_age " // strongly recommended with partial_update
Jesse Hall408e59f2015-04-24 01:40:42 -0700124 "EGL_KHR_create_context_no_error "
Pablo Ceballosceb9ee72016-04-13 11:17:32 -0700125 "EGL_KHR_mutable_render_buffer "
Mika Isojärvif37864b2016-04-15 11:58:56 -0700126 "EGL_EXT_yuv_surface "
Craig Donneraec86972016-04-28 18:09:40 -0700127 "EGL_EXT_protected_content "
Christian Poetzscha7805f62016-12-01 16:34:39 +0000128 "EGL_IMG_context_priority "
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700129 ;
130
131// extensions not exposed to applications but used by the ANDROID system
132// "EGL_ANDROID_blob_cache " // strongly recommended
133// "EGL_IMG_hibernate_process " // optional
134// "EGL_ANDROID_native_fence_sync " // strongly recommended
135// "EGL_ANDROID_framebuffer_target " // mandatory for HWC 1.1
Jamie Gennisdbe92452013-09-23 17:22:10 -0700136// "EGL_ANDROID_image_crop " // optional
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700137
138/*
139 * EGL Extensions entry-points exposed to 3rd party applications
140 * (keep in sync with gExtensionString above)
141 *
142 */
143static const extention_map_t sExtensionMap[] = {
144 // EGL_KHR_lock_surface
Mathias Agopian518ec112011-05-13 16:21:08 -0700145 { "eglLockSurfaceKHR",
146 (__eglMustCastToProperFunctionPointerType)&eglLockSurfaceKHR },
147 { "eglUnlockSurfaceKHR",
148 (__eglMustCastToProperFunctionPointerType)&eglUnlockSurfaceKHR },
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700149
150 // EGL_KHR_image, EGL_KHR_image_base
Mathias Agopian518ec112011-05-13 16:21:08 -0700151 { "eglCreateImageKHR",
152 (__eglMustCastToProperFunctionPointerType)&eglCreateImageKHR },
153 { "eglDestroyImageKHR",
154 (__eglMustCastToProperFunctionPointerType)&eglDestroyImageKHR },
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700155
156 // EGL_KHR_reusable_sync, EGL_KHR_fence_sync
157 { "eglCreateSyncKHR",
158 (__eglMustCastToProperFunctionPointerType)&eglCreateSyncKHR },
159 { "eglDestroySyncKHR",
160 (__eglMustCastToProperFunctionPointerType)&eglDestroySyncKHR },
161 { "eglClientWaitSyncKHR",
162 (__eglMustCastToProperFunctionPointerType)&eglClientWaitSyncKHR },
163 { "eglSignalSyncKHR",
164 (__eglMustCastToProperFunctionPointerType)&eglSignalSyncKHR },
165 { "eglGetSyncAttribKHR",
166 (__eglMustCastToProperFunctionPointerType)&eglGetSyncAttribKHR },
167
168 // EGL_NV_system_time
Jonas Yang1c3d72a2011-08-26 20:04:39 +0800169 { "eglGetSystemTimeFrequencyNV",
170 (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeFrequencyNV },
171 { "eglGetSystemTimeNV",
172 (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeNV },
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700173
Mathias Agopian2bb71682013-03-27 17:32:41 -0700174 // EGL_KHR_wait_sync
175 { "eglWaitSyncKHR",
176 (__eglMustCastToProperFunctionPointerType)&eglWaitSyncKHR },
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700177
178 // EGL_ANDROID_presentation_time
179 { "eglPresentationTimeANDROID",
180 (__eglMustCastToProperFunctionPointerType)&eglPresentationTimeANDROID },
Dan Stozaa894d082015-02-19 15:27:36 -0800181
182 // EGL_KHR_swap_buffers_with_damage
183 { "eglSwapBuffersWithDamageKHR",
184 (__eglMustCastToProperFunctionPointerType)&eglSwapBuffersWithDamageKHR },
185
Craig Donner60761072017-01-27 12:30:44 -0800186 // EGL_ANDROID_create_native_client_buffer
Craig Donner05249fc2016-01-15 19:33:55 -0800187 { "eglCreateNativeClientBufferANDROID",
188 (__eglMustCastToProperFunctionPointerType)&eglCreateNativeClientBufferANDROID },
189
Craig Donner60761072017-01-27 12:30:44 -0800190 // EGL_ANDROID_get_native_client_buffer
191 { "eglGetNativeClientBufferANDROID",
192 (__eglMustCastToProperFunctionPointerType)&eglGetNativeClientBufferANDROID },
193
Dan Stozaa894d082015-02-19 15:27:36 -0800194 // EGL_KHR_partial_update
195 { "eglSetDamageRegionKHR",
196 (__eglMustCastToProperFunctionPointerType)&eglSetDamageRegionKHR },
Season Li000d88f2015-07-01 11:39:40 -0700197
198 { "eglCreateStreamKHR",
199 (__eglMustCastToProperFunctionPointerType)&eglCreateStreamKHR },
200 { "eglDestroyStreamKHR",
201 (__eglMustCastToProperFunctionPointerType)&eglDestroyStreamKHR },
202 { "eglStreamAttribKHR",
203 (__eglMustCastToProperFunctionPointerType)&eglStreamAttribKHR },
204 { "eglQueryStreamKHR",
205 (__eglMustCastToProperFunctionPointerType)&eglQueryStreamKHR },
206 { "eglQueryStreamu64KHR",
207 (__eglMustCastToProperFunctionPointerType)&eglQueryStreamu64KHR },
208 { "eglQueryStreamTimeKHR",
209 (__eglMustCastToProperFunctionPointerType)&eglQueryStreamTimeKHR },
210 { "eglCreateStreamProducerSurfaceKHR",
211 (__eglMustCastToProperFunctionPointerType)&eglCreateStreamProducerSurfaceKHR },
212 { "eglStreamConsumerGLTextureExternalKHR",
213 (__eglMustCastToProperFunctionPointerType)&eglStreamConsumerGLTextureExternalKHR },
214 { "eglStreamConsumerAcquireKHR",
215 (__eglMustCastToProperFunctionPointerType)&eglStreamConsumerAcquireKHR },
216 { "eglStreamConsumerReleaseKHR",
217 (__eglMustCastToProperFunctionPointerType)&eglStreamConsumerReleaseKHR },
218 { "eglGetStreamFileDescriptorKHR",
219 (__eglMustCastToProperFunctionPointerType)&eglGetStreamFileDescriptorKHR },
220 { "eglCreateStreamFromFileDescriptorKHR",
221 (__eglMustCastToProperFunctionPointerType)&eglCreateStreamFromFileDescriptorKHR },
Pablo Ceballosc18be292016-05-31 14:55:42 -0700222
223 // EGL_ANDROID_get_frame_timestamps
Brian Anderson1049d1d2016-12-16 17:25:57 -0800224 { "eglGetNextFrameIdANDROID",
225 (__eglMustCastToProperFunctionPointerType)&eglGetNextFrameIdANDROID },
Brian Anderson0a61b0c2016-12-07 14:55:56 -0800226 { "eglGetCompositorTimingANDROID",
227 (__eglMustCastToProperFunctionPointerType)&eglGetCompositorTimingANDROID },
228 { "eglGetCompositorTimingSupportedANDROID",
229 (__eglMustCastToProperFunctionPointerType)&eglGetCompositorTimingSupportedANDROID },
Pablo Ceballosc18be292016-05-31 14:55:42 -0700230 { "eglGetFrameTimestampsANDROID",
231 (__eglMustCastToProperFunctionPointerType)&eglGetFrameTimestampsANDROID },
Brian Anderson0a61b0c2016-12-07 14:55:56 -0800232 { "eglGetFrameTimestampSupportedANDROID",
233 (__eglMustCastToProperFunctionPointerType)&eglGetFrameTimestampSupportedANDROID },
Mathias Agopian518ec112011-05-13 16:21:08 -0700234};
235
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700236/*
237 * These extensions entry-points should not be exposed to applications.
238 * They're used internally by the Android EGL layer.
239 */
240#define FILTER_EXTENSIONS(procname) \
241 (!strcmp((procname), "eglSetBlobCacheFuncsANDROID") || \
242 !strcmp((procname), "eglHibernateProcessIMG") || \
243 !strcmp((procname), "eglAwakenProcessIMG") || \
244 !strcmp((procname), "eglDupNativeFenceFDANDROID"))
245
246
247
Mathias Agopian518ec112011-05-13 16:21:08 -0700248// accesses protected by sExtensionMapMutex
249static DefaultKeyedVector<String8, __eglMustCastToProperFunctionPointerType> sGLExtentionMap;
250static int sGLExtentionSlot = 0;
251static pthread_mutex_t sExtensionMapMutex = PTHREAD_MUTEX_INITIALIZER;
252
253static void(*findProcAddress(const char* name,
254 const extention_map_t* map, size_t n))() {
255 for (uint32_t i=0 ; i<n ; i++) {
256 if (!strcmp(name, map[i].name)) {
257 return map[i].address;
258 }
259 }
260 return NULL;
261}
262
263// ----------------------------------------------------------------------------
264
Mathias Agopian518ec112011-05-13 16:21:08 -0700265extern void setGLHooksThreadSpecific(gl_hooks_t const *value);
266extern EGLBoolean egl_init_drivers();
267extern const __eglMustCastToProperFunctionPointerType gExtensionForwarders[MAX_NUMBER_OF_GL_EXTENSIONS];
Mathias Agopian518ec112011-05-13 16:21:08 -0700268extern gl_hooks_t gHooksTrace;
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700269
Mathias Agopian518ec112011-05-13 16:21:08 -0700270} // namespace android;
271
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700272
Mathias Agopian518ec112011-05-13 16:21:08 -0700273// ----------------------------------------------------------------------------
274
275static inline void clearError() { egl_tls_t::clearError(); }
276static inline EGLContext getContext() { return egl_tls_t::getContext(); }
277
278// ----------------------------------------------------------------------------
279
280EGLDisplay eglGetDisplay(EGLNativeDisplayType display)
281{
Jesse Hall1508ae62017-01-19 17:43:26 -0800282 ATRACE_CALL();
Mathias Agopian518ec112011-05-13 16:21:08 -0700283 clearError();
284
Dan Stozac3289c42014-01-17 11:38:34 -0800285 uintptr_t index = reinterpret_cast<uintptr_t>(display);
Mathias Agopian518ec112011-05-13 16:21:08 -0700286 if (index >= NUM_DISPLAYS) {
287 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
288 }
289
290 if (egl_init_drivers() == EGL_FALSE) {
291 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
292 }
293
294 EGLDisplay dpy = egl_display_t::getFromNativeDisplay(display);
295 return dpy;
296}
297
298// ----------------------------------------------------------------------------
299// Initialization
300// ----------------------------------------------------------------------------
301
302EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
303{
304 clearError();
305
Jesse Hallb29e5e82012-04-04 16:53:42 -0700306 egl_display_ptr dp = get_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700307 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
308
309 EGLBoolean res = dp->initialize(major, minor);
310
311 return res;
312}
313
314EGLBoolean eglTerminate(EGLDisplay dpy)
315{
316 // NOTE: don't unload the drivers b/c some APIs can be called
317 // after eglTerminate() has been called. eglTerminate() only
318 // terminates an EGLDisplay, not a EGL itself.
319
320 clearError();
321
Jesse Hallb29e5e82012-04-04 16:53:42 -0700322 egl_display_ptr dp = get_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700323 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
324
325 EGLBoolean res = dp->terminate();
Jesse Hall47743382013-02-08 11:13:46 -0800326
Mathias Agopian518ec112011-05-13 16:21:08 -0700327 return res;
328}
329
330// ----------------------------------------------------------------------------
331// configuration
332// ----------------------------------------------------------------------------
333
334EGLBoolean eglGetConfigs( EGLDisplay dpy,
335 EGLConfig *configs,
336 EGLint config_size, EGLint *num_config)
337{
338 clearError();
339
Jesse Hallb29e5e82012-04-04 16:53:42 -0700340 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700341 if (!dp) return EGL_FALSE;
342
Mathias Agopian7773c432012-02-13 20:06:08 -0800343 if (num_config==0) {
344 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700345 }
346
Mathias Agopian7773c432012-02-13 20:06:08 -0800347 EGLBoolean res = EGL_FALSE;
348 *num_config = 0;
349
350 egl_connection_t* const cnx = &gEGLImpl;
351 if (cnx->dso) {
352 res = cnx->egl.eglGetConfigs(
353 dp->disp.dpy, configs, config_size, num_config);
Mathias Agopian518ec112011-05-13 16:21:08 -0700354 }
Mathias Agopian7773c432012-02-13 20:06:08 -0800355
356 return res;
Mathias Agopian518ec112011-05-13 16:21:08 -0700357}
358
359EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list,
360 EGLConfig *configs, EGLint config_size,
361 EGLint *num_config)
362{
363 clearError();
364
Jesse Hallb29e5e82012-04-04 16:53:42 -0700365 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700366 if (!dp) return EGL_FALSE;
367
368 if (num_config==0) {
369 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
370 }
371
Mathias Agopian518ec112011-05-13 16:21:08 -0700372 EGLBoolean res = EGL_FALSE;
373 *num_config = 0;
374
Mathias Agopianada798b2012-02-13 17:09:30 -0800375 egl_connection_t* const cnx = &gEGLImpl;
376 if (cnx->dso) {
Romain Guy1cffc802012-10-15 18:13:05 -0700377 if (attrib_list) {
378 char value[PROPERTY_VALUE_MAX];
379 property_get("debug.egl.force_msaa", value, "false");
380
381 if (!strcmp(value, "true")) {
382 size_t attribCount = 0;
383 EGLint attrib = attrib_list[0];
384
385 // Only enable MSAA if the context is OpenGL ES 2.0 and
Romain Guybe3c3e42012-10-15 19:25:18 -0700386 // if no caveat is requested
Romain Guy1cffc802012-10-15 18:13:05 -0700387 const EGLint *attribRendererable = NULL;
388 const EGLint *attribCaveat = NULL;
389
390 // Count the number of attributes and look for
Romain Guybe3c3e42012-10-15 19:25:18 -0700391 // EGL_RENDERABLE_TYPE and EGL_CONFIG_CAVEAT
Romain Guy1cffc802012-10-15 18:13:05 -0700392 while (attrib != EGL_NONE) {
393 attrib = attrib_list[attribCount];
394 switch (attrib) {
395 case EGL_RENDERABLE_TYPE:
396 attribRendererable = &attrib_list[attribCount];
397 break;
398 case EGL_CONFIG_CAVEAT:
399 attribCaveat = &attrib_list[attribCount];
400 break;
401 }
402 attribCount++;
403 }
404
405 if (attribRendererable && attribRendererable[1] == EGL_OPENGL_ES2_BIT &&
406 (!attribCaveat || attribCaveat[1] != EGL_NONE)) {
Jesse Hall47743382013-02-08 11:13:46 -0800407
Romain Guy1cffc802012-10-15 18:13:05 -0700408 // Insert 2 extra attributes to force-enable MSAA 4x
409 EGLint aaAttribs[attribCount + 4];
410 aaAttribs[0] = EGL_SAMPLE_BUFFERS;
411 aaAttribs[1] = 1;
412 aaAttribs[2] = EGL_SAMPLES;
413 aaAttribs[3] = 4;
414
415 memcpy(&aaAttribs[4], attrib_list, attribCount * sizeof(EGLint));
416
417 EGLint numConfigAA;
418 EGLBoolean resAA = cnx->egl.eglChooseConfig(
419 dp->disp.dpy, aaAttribs, configs, config_size, &numConfigAA);
420
421 if (resAA == EGL_TRUE && numConfigAA > 0) {
422 ALOGD("Enabling MSAA 4x");
423 *num_config = numConfigAA;
424 return resAA;
425 }
426 }
427 }
428 }
429
Mathias Agopian7773c432012-02-13 20:06:08 -0800430 res = cnx->egl.eglChooseConfig(
431 dp->disp.dpy, attrib_list, configs, config_size, num_config);
Mathias Agopian518ec112011-05-13 16:21:08 -0700432 }
433 return res;
434}
435
436EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
437 EGLint attribute, EGLint *value)
438{
439 clearError();
440
Jesse Hallb29e5e82012-04-04 16:53:42 -0700441 egl_connection_t* cnx = NULL;
442 const egl_display_ptr dp = validate_display_connection(dpy, cnx);
443 if (!dp) return EGL_FALSE;
Jesse Hall47743382013-02-08 11:13:46 -0800444
Mathias Agopian518ec112011-05-13 16:21:08 -0700445 return cnx->egl.eglGetConfigAttrib(
Mathias Agopian7773c432012-02-13 20:06:08 -0800446 dp->disp.dpy, config, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -0700447}
448
449// ----------------------------------------------------------------------------
450// surfaces
451// ----------------------------------------------------------------------------
452
Jesse Hallc2e41222013-08-08 13:40:22 -0700453// Turn linear formats into corresponding sRGB formats when colorspace is
454// EGL_GL_COLORSPACE_SRGB_KHR, or turn sRGB formats into corresponding linear
455// formats when colorspace is EGL_GL_COLORSPACE_LINEAR_KHR. In any cases where
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800456// the modification isn't possible, the original dataSpace is returned.
457static android_dataspace modifyBufferDataspace( android_dataspace dataSpace,
458 EGLint colorspace) {
Jesse Hallc2e41222013-08-08 13:40:22 -0700459 if (colorspace == EGL_GL_COLORSPACE_LINEAR_KHR) {
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800460 return HAL_DATASPACE_SRGB_LINEAR;
Jesse Hallc2e41222013-08-08 13:40:22 -0700461 } else if (colorspace == EGL_GL_COLORSPACE_SRGB_KHR) {
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800462 return HAL_DATASPACE_SRGB;
Jesse Hallc2e41222013-08-08 13:40:22 -0700463 }
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800464 return dataSpace;
Jesse Hallc2e41222013-08-08 13:40:22 -0700465}
466
Mathias Agopian518ec112011-05-13 16:21:08 -0700467EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config,
468 NativeWindowType window,
469 const EGLint *attrib_list)
470{
471 clearError();
472
Jesse Hallb29e5e82012-04-04 16:53:42 -0700473 egl_connection_t* cnx = NULL;
474 egl_display_ptr dp = validate_display_connection(dpy, cnx);
475 if (dp) {
Mathias Agopianada798b2012-02-13 17:09:30 -0800476 EGLDisplay iDpy = dp->disp.dpy;
Mathias Agopian518ec112011-05-13 16:21:08 -0700477
Andy McFaddend566ce32014-01-07 15:54:17 -0800478 int result = native_window_api_connect(window, NATIVE_WINDOW_API_EGL);
479 if (result != OK) {
480 ALOGE("eglCreateWindowSurface: native_window_api_connect (win=%p) "
481 "failed (%#x) (already connected to another API?)",
482 window, result);
Jonathan Hamilton77a9b4a2013-07-17 09:41:42 -0700483 return setError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
Mathias Agopian81a63352011-07-29 17:55:48 -0700484 }
485
Mathias Agopian0f288fc2013-08-21 16:36:34 -0700486 // Set the native window's buffers format to match what this config requests.
Jesse Hallc2e41222013-08-08 13:40:22 -0700487 // Whether to use sRGB gamma is not part of the EGLconfig, but is part
488 // of our native format. So if sRGB gamma is requested, we have to
489 // modify the EGLconfig's format before setting the native window's
490 // format.
Alistair Strachan733a8072015-02-12 12:33:25 -0800491
Courtney Goeltzenleuchter0e4e3952016-11-16 13:53:40 -0700492 EGLint componentType = EGL_COLOR_COMPONENT_TYPE_FIXED_EXT;
493 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_COLOR_COMPONENT_TYPE_EXT,
494 &componentType);
495
Mathias Agopian95921562017-02-24 14:31:31 -0800496 EGLint format;
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800497 android_dataspace dataSpace = HAL_DATASPACE_UNKNOWN;
Mathias Agopian0f288fc2013-08-21 16:36:34 -0700498 EGLint a = 0;
Courtney Goeltzenleuchter0e4e3952016-11-16 13:53:40 -0700499 EGLint r, g, b;
500 r = g = b = 0;
501 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_RED_SIZE, &r);
502 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_GREEN_SIZE, &g);
503 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_BLUE_SIZE, &b);
Mathias Agopian0f288fc2013-08-21 16:36:34 -0700504 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_ALPHA_SIZE, &a);
Courtney Goeltzenleuchter0e4e3952016-11-16 13:53:40 -0700505 EGLint colorDepth = r + g + b;
506
507 if (a == 0) {
Mathias Agopian0f288fc2013-08-21 16:36:34 -0700508 if (colorDepth <= 16) {
509 format = HAL_PIXEL_FORMAT_RGB_565;
510 } else {
Courtney Goeltzenleuchter0e4e3952016-11-16 13:53:40 -0700511 if (componentType == EGL_COLOR_COMPONENT_TYPE_FIXED_EXT) {
512 if (colorDepth > 24) {
513 format = HAL_PIXEL_FORMAT_RGBA_1010102;
514 } else {
515 format = HAL_PIXEL_FORMAT_RGBX_8888;
516 }
517 } else {
518 format = HAL_PIXEL_FORMAT_RGBA_FP16;
519 }
520 }
521 } else {
522 if (componentType == EGL_COLOR_COMPONENT_TYPE_FIXED_EXT) {
523 if (colorDepth > 24) {
524 format = HAL_PIXEL_FORMAT_RGBA_1010102;
525 } else {
526 format = HAL_PIXEL_FORMAT_RGBA_8888;
527 }
528 } else {
529 format = HAL_PIXEL_FORMAT_RGBA_FP16;
Mathias Agopian0f288fc2013-08-21 16:36:34 -0700530 }
Jesse Hallc2e41222013-08-08 13:40:22 -0700531 }
Mathias Agopian0f288fc2013-08-21 16:36:34 -0700532
533 // now select a corresponding sRGB format if needed
534 if (attrib_list && dp->haveExtension("EGL_KHR_gl_colorspace")) {
535 for (const EGLint* attr = attrib_list; *attr != EGL_NONE; attr += 2) {
536 if (*attr == EGL_GL_COLORSPACE_KHR) {
Sandeep Shinde9c67bfd2015-02-10 16:04:15 +0530537 dataSpace = modifyBufferDataspace(dataSpace, *(attr+1));
Jamie Gennisbee205f2011-07-01 13:12:07 -0700538 }
Mathias Agopian518ec112011-05-13 16:21:08 -0700539 }
540 }
Alistair Strachan733a8072015-02-12 12:33:25 -0800541
Jesse Hallc2e41222013-08-08 13:40:22 -0700542 if (format != 0) {
543 int err = native_window_set_buffers_format(window, format);
544 if (err != 0) {
545 ALOGE("error setting native window pixel format: %s (%d)",
546 strerror(-err), err);
547 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
548 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
549 }
550 }
Mathias Agopian518ec112011-05-13 16:21:08 -0700551
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800552 if (dataSpace != 0) {
553 int err = native_window_set_buffers_data_space(window, dataSpace);
554 if (err != 0) {
555 ALOGE("error setting native window pixel dataSpace: %s (%d)",
556 strerror(-err), err);
557 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
558 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
559 }
560 }
561
Jamie Gennis59769462011-11-19 18:04:43 -0800562 // the EGL spec requires that a new EGLSurface default to swap interval
563 // 1, so explicitly set that on the window here.
564 ANativeWindow* anw = reinterpret_cast<ANativeWindow*>(window);
565 anw->setSwapInterval(anw, 1);
566
Mathias Agopian518ec112011-05-13 16:21:08 -0700567 EGLSurface surface = cnx->egl.eglCreateWindowSurface(
Mathias Agopian7773c432012-02-13 20:06:08 -0800568 iDpy, config, window, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700569 if (surface != EGL_NO_SURFACE) {
Jesse Hallb29e5e82012-04-04 16:53:42 -0700570 egl_surface_t* s = new egl_surface_t(dp.get(), config, window,
571 surface, cnx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700572 return s;
573 }
Mathias Agopian81a63352011-07-29 17:55:48 -0700574
575 // EGLSurface creation failed
576 native_window_set_buffers_format(window, 0);
577 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
Mathias Agopian518ec112011-05-13 16:21:08 -0700578 }
579 return EGL_NO_SURFACE;
580}
581
582EGLSurface eglCreatePixmapSurface( EGLDisplay dpy, EGLConfig config,
583 NativePixmapType pixmap,
584 const EGLint *attrib_list)
585{
586 clearError();
587
Jesse Hallb29e5e82012-04-04 16:53:42 -0700588 egl_connection_t* cnx = NULL;
589 egl_display_ptr dp = validate_display_connection(dpy, cnx);
590 if (dp) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700591 EGLSurface surface = cnx->egl.eglCreatePixmapSurface(
Mathias Agopian7773c432012-02-13 20:06:08 -0800592 dp->disp.dpy, config, pixmap, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700593 if (surface != EGL_NO_SURFACE) {
Jesse Hallb29e5e82012-04-04 16:53:42 -0700594 egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL,
595 surface, cnx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700596 return s;
597 }
598 }
599 return EGL_NO_SURFACE;
600}
601
602EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config,
603 const EGLint *attrib_list)
604{
605 clearError();
606
Jesse Hallb29e5e82012-04-04 16:53:42 -0700607 egl_connection_t* cnx = NULL;
608 egl_display_ptr dp = validate_display_connection(dpy, cnx);
609 if (dp) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700610 EGLSurface surface = cnx->egl.eglCreatePbufferSurface(
Mathias Agopian7773c432012-02-13 20:06:08 -0800611 dp->disp.dpy, config, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700612 if (surface != EGL_NO_SURFACE) {
Jesse Hallb29e5e82012-04-04 16:53:42 -0700613 egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL,
614 surface, cnx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700615 return s;
616 }
617 }
618 return EGL_NO_SURFACE;
619}
Jesse Hall47743382013-02-08 11:13:46 -0800620
Mathias Agopian518ec112011-05-13 16:21:08 -0700621EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
622{
623 clearError();
624
Jesse Hallb29e5e82012-04-04 16:53:42 -0700625 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700626 if (!dp) return EGL_FALSE;
627
Jesse Hallb29e5e82012-04-04 16:53:42 -0700628 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700629 if (!_s.get())
630 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700631
632 egl_surface_t * const s = get_surface(surface);
Mathias Agopianada798b2012-02-13 17:09:30 -0800633 EGLBoolean result = s->cnx->egl.eglDestroySurface(dp->disp.dpy, s->surface);
Mathias Agopian518ec112011-05-13 16:21:08 -0700634 if (result == EGL_TRUE) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700635 _s.terminate();
636 }
637 return result;
638}
639
640EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface surface,
641 EGLint attribute, EGLint *value)
642{
643 clearError();
644
Jesse Hallb29e5e82012-04-04 16:53:42 -0700645 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700646 if (!dp) return EGL_FALSE;
647
Jesse Hallb29e5e82012-04-04 16:53:42 -0700648 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700649 if (!_s.get())
650 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700651
Mathias Agopian518ec112011-05-13 16:21:08 -0700652 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian7773c432012-02-13 20:06:08 -0800653 return s->cnx->egl.eglQuerySurface(
654 dp->disp.dpy, s->surface, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -0700655}
656
Jamie Gennise8696a42012-01-15 18:54:57 -0800657void EGLAPI eglBeginFrame(EGLDisplay dpy, EGLSurface surface) {
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800658 ATRACE_CALL();
Jamie Gennise8696a42012-01-15 18:54:57 -0800659 clearError();
660
Jesse Hallb29e5e82012-04-04 16:53:42 -0700661 const egl_display_ptr dp = validate_display(dpy);
Jamie Gennise8696a42012-01-15 18:54:57 -0800662 if (!dp) {
663 return;
664 }
665
Jesse Hallb29e5e82012-04-04 16:53:42 -0700666 SurfaceRef _s(dp.get(), surface);
Jamie Gennise8696a42012-01-15 18:54:57 -0800667 if (!_s.get()) {
668 setError(EGL_BAD_SURFACE, EGL_FALSE);
669 return;
670 }
Jamie Gennise8696a42012-01-15 18:54:57 -0800671}
672
Mathias Agopian518ec112011-05-13 16:21:08 -0700673// ----------------------------------------------------------------------------
674// Contexts
675// ----------------------------------------------------------------------------
676
677EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config,
678 EGLContext share_list, const EGLint *attrib_list)
679{
680 clearError();
681
Jesse Hallb29e5e82012-04-04 16:53:42 -0700682 egl_connection_t* cnx = NULL;
683 const egl_display_ptr dp = validate_display_connection(dpy, cnx);
Michael Chock0673e1e2012-06-21 12:53:17 -0700684 if (dp) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700685 if (share_list != EGL_NO_CONTEXT) {
Michael Chock0673e1e2012-06-21 12:53:17 -0700686 if (!ContextRef(dp.get(), share_list).get()) {
687 return setError(EGL_BAD_CONTEXT, EGL_NO_CONTEXT);
688 }
Mathias Agopian518ec112011-05-13 16:21:08 -0700689 egl_context_t* const c = get_context(share_list);
690 share_list = c->context;
691 }
692 EGLContext context = cnx->egl.eglCreateContext(
Mathias Agopian7773c432012-02-13 20:06:08 -0800693 dp->disp.dpy, config, share_list, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700694 if (context != EGL_NO_CONTEXT) {
695 // figure out if it's a GLESv1 or GLESv2
696 int version = 0;
697 if (attrib_list) {
698 while (*attrib_list != EGL_NONE) {
699 GLint attr = *attrib_list++;
700 GLint value = *attrib_list++;
701 if (attr == EGL_CONTEXT_CLIENT_VERSION) {
702 if (value == 1) {
Mathias Agopian7773c432012-02-13 20:06:08 -0800703 version = egl_connection_t::GLESv1_INDEX;
Jesse Hall47743382013-02-08 11:13:46 -0800704 } else if (value == 2 || value == 3) {
Mathias Agopian7773c432012-02-13 20:06:08 -0800705 version = egl_connection_t::GLESv2_INDEX;
Mathias Agopian518ec112011-05-13 16:21:08 -0700706 }
707 }
708 };
709 }
Jesse Hallb29e5e82012-04-04 16:53:42 -0700710 egl_context_t* c = new egl_context_t(dpy, context, config, cnx,
711 version);
Mathias Agopian518ec112011-05-13 16:21:08 -0700712 return c;
713 }
714 }
715 return EGL_NO_CONTEXT;
716}
717
718EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
719{
720 clearError();
721
Jesse Hallb29e5e82012-04-04 16:53:42 -0700722 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700723 if (!dp)
724 return EGL_FALSE;
Mathias Agopian518ec112011-05-13 16:21:08 -0700725
Jesse Hallb29e5e82012-04-04 16:53:42 -0700726 ContextRef _c(dp.get(), ctx);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700727 if (!_c.get())
728 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
Jesse Hall47743382013-02-08 11:13:46 -0800729
Mathias Agopian518ec112011-05-13 16:21:08 -0700730 egl_context_t * const c = get_context(ctx);
Mathias Agopianada798b2012-02-13 17:09:30 -0800731 EGLBoolean result = c->cnx->egl.eglDestroyContext(dp->disp.dpy, c->context);
Mathias Agopian518ec112011-05-13 16:21:08 -0700732 if (result == EGL_TRUE) {
733 _c.terminate();
734 }
735 return result;
736}
737
Mathias Agopian518ec112011-05-13 16:21:08 -0700738EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw,
739 EGLSurface read, EGLContext ctx)
740{
741 clearError();
742
Jesse Hallb29e5e82012-04-04 16:53:42 -0700743 egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700744 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
745
Mathias Agopian5b287a62011-05-16 18:58:55 -0700746 // If ctx is not EGL_NO_CONTEXT, read is not EGL_NO_SURFACE, or draw is not
747 // EGL_NO_SURFACE, then an EGL_NOT_INITIALIZED error is generated if dpy is
748 // a valid but uninitialized display.
Mathias Agopian518ec112011-05-13 16:21:08 -0700749 if ( (ctx != EGL_NO_CONTEXT) || (read != EGL_NO_SURFACE) ||
750 (draw != EGL_NO_SURFACE) ) {
751 if (!dp->isReady()) return setError(EGL_NOT_INITIALIZED, EGL_FALSE);
752 }
753
754 // get a reference to the object passed in
Jesse Hallb29e5e82012-04-04 16:53:42 -0700755 ContextRef _c(dp.get(), ctx);
756 SurfaceRef _d(dp.get(), draw);
757 SurfaceRef _r(dp.get(), read);
Mathias Agopian518ec112011-05-13 16:21:08 -0700758
759 // validate the context (if not EGL_NO_CONTEXT)
Mathias Agopian5b287a62011-05-16 18:58:55 -0700760 if ((ctx != EGL_NO_CONTEXT) && !_c.get()) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700761 // EGL_NO_CONTEXT is valid
Michael Chock0673e1e2012-06-21 12:53:17 -0700762 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700763 }
764
765 // these are the underlying implementation's object
766 EGLContext impl_ctx = EGL_NO_CONTEXT;
767 EGLSurface impl_draw = EGL_NO_SURFACE;
768 EGLSurface impl_read = EGL_NO_SURFACE;
769
770 // these are our objects structs passed in
771 egl_context_t * c = NULL;
772 egl_surface_t const * d = NULL;
773 egl_surface_t const * r = NULL;
774
775 // these are the current objects structs
776 egl_context_t * cur_c = get_context(getContext());
Jesse Hall47743382013-02-08 11:13:46 -0800777
Mathias Agopian518ec112011-05-13 16:21:08 -0700778 if (ctx != EGL_NO_CONTEXT) {
779 c = get_context(ctx);
780 impl_ctx = c->context;
781 } else {
782 // no context given, use the implementation of the current context
Michael Chock0673e1e2012-06-21 12:53:17 -0700783 if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE) {
784 // calling eglMakeCurrent( ..., !=0, !=0, EGL_NO_CONTEXT);
785 return setError(EGL_BAD_MATCH, EGL_FALSE);
786 }
Mathias Agopian518ec112011-05-13 16:21:08 -0700787 if (cur_c == NULL) {
788 // no current context
Mathias Agopian518ec112011-05-13 16:21:08 -0700789 // not an error, there is just no current context.
790 return EGL_TRUE;
791 }
792 }
793
794 // retrieve the underlying implementation's draw EGLSurface
795 if (draw != EGL_NO_SURFACE) {
Michael Chock0673e1e2012-06-21 12:53:17 -0700796 if (!_d.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700797 d = get_surface(draw);
Mathias Agopian518ec112011-05-13 16:21:08 -0700798 impl_draw = d->surface;
799 }
800
801 // retrieve the underlying implementation's read EGLSurface
802 if (read != EGL_NO_SURFACE) {
Michael Chock0673e1e2012-06-21 12:53:17 -0700803 if (!_r.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700804 r = get_surface(read);
Mathias Agopian518ec112011-05-13 16:21:08 -0700805 impl_read = r->surface;
806 }
807
Mathias Agopian518ec112011-05-13 16:21:08 -0700808
Jesse Hallb29e5e82012-04-04 16:53:42 -0700809 EGLBoolean result = dp->makeCurrent(c, cur_c,
Mathias Agopianfb87e542012-01-30 18:20:52 -0800810 draw, read, ctx,
811 impl_draw, impl_read, impl_ctx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700812
813 if (result == EGL_TRUE) {
Mathias Agopianfb87e542012-01-30 18:20:52 -0800814 if (c) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700815 setGLHooksThreadSpecific(c->cnx->hooks[c->version]);
816 egl_tls_t::setContext(ctx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700817 _c.acquire();
818 _r.acquire();
819 _d.acquire();
Mathias Agopian518ec112011-05-13 16:21:08 -0700820 } else {
821 setGLHooksThreadSpecific(&gHooksNoContext);
822 egl_tls_t::setContext(EGL_NO_CONTEXT);
823 }
Mathias Agopian5fecea72011-08-25 18:38:24 -0700824 } else {
Steve Blocke6f43dd2012-01-06 19:20:56 +0000825 // this will ALOGE the error
Mathias Agopian63108c32013-09-06 13:36:49 -0700826 egl_connection_t* const cnx = &gEGLImpl;
827 result = setError(cnx->egl.eglGetError(), EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700828 }
829 return result;
830}
831
832
833EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx,
834 EGLint attribute, EGLint *value)
835{
836 clearError();
837
Jesse Hallb29e5e82012-04-04 16:53:42 -0700838 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700839 if (!dp) return EGL_FALSE;
840
Jesse Hallb29e5e82012-04-04 16:53:42 -0700841 ContextRef _c(dp.get(), ctx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700842 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
843
Mathias Agopian518ec112011-05-13 16:21:08 -0700844 egl_context_t * const c = get_context(ctx);
Mathias Agopian7773c432012-02-13 20:06:08 -0800845 return c->cnx->egl.eglQueryContext(
846 dp->disp.dpy, c->context, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -0700847
Mathias Agopian518ec112011-05-13 16:21:08 -0700848}
849
850EGLContext eglGetCurrentContext(void)
851{
852 // could be called before eglInitialize(), but we wouldn't have a context
853 // then, and this function would correctly return EGL_NO_CONTEXT.
854
855 clearError();
856
857 EGLContext ctx = getContext();
858 return ctx;
859}
860
861EGLSurface eglGetCurrentSurface(EGLint readdraw)
862{
863 // could be called before eglInitialize(), but we wouldn't have a context
864 // then, and this function would correctly return EGL_NO_SURFACE.
865
866 clearError();
867
868 EGLContext ctx = getContext();
869 if (ctx) {
870 egl_context_t const * const c = get_context(ctx);
871 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
872 switch (readdraw) {
873 case EGL_READ: return c->read;
Jesse Hall47743382013-02-08 11:13:46 -0800874 case EGL_DRAW: return c->draw;
Mathias Agopian518ec112011-05-13 16:21:08 -0700875 default: return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
876 }
877 }
878 return EGL_NO_SURFACE;
879}
880
881EGLDisplay eglGetCurrentDisplay(void)
882{
883 // could be called before eglInitialize(), but we wouldn't have a context
884 // then, and this function would correctly return EGL_NO_DISPLAY.
885
886 clearError();
887
888 EGLContext ctx = getContext();
889 if (ctx) {
890 egl_context_t const * const c = get_context(ctx);
891 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
892 return c->dpy;
893 }
894 return EGL_NO_DISPLAY;
895}
896
897EGLBoolean eglWaitGL(void)
898{
Mathias Agopian518ec112011-05-13 16:21:08 -0700899 clearError();
900
Mathias Agopianada798b2012-02-13 17:09:30 -0800901 egl_connection_t* const cnx = &gEGLImpl;
902 if (!cnx->dso)
903 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
904
905 return cnx->egl.eglWaitGL();
Mathias Agopian518ec112011-05-13 16:21:08 -0700906}
907
908EGLBoolean eglWaitNative(EGLint engine)
909{
Mathias Agopian518ec112011-05-13 16:21:08 -0700910 clearError();
911
Mathias Agopianada798b2012-02-13 17:09:30 -0800912 egl_connection_t* const cnx = &gEGLImpl;
913 if (!cnx->dso)
914 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
915
916 return cnx->egl.eglWaitNative(engine);
Mathias Agopian518ec112011-05-13 16:21:08 -0700917}
918
919EGLint eglGetError(void)
920{
Mathias Agopianada798b2012-02-13 17:09:30 -0800921 EGLint err = EGL_SUCCESS;
922 egl_connection_t* const cnx = &gEGLImpl;
923 if (cnx->dso) {
924 err = cnx->egl.eglGetError();
Mathias Agopian518ec112011-05-13 16:21:08 -0700925 }
Mathias Agopianada798b2012-02-13 17:09:30 -0800926 if (err == EGL_SUCCESS) {
927 err = egl_tls_t::getError();
928 }
929 return err;
Mathias Agopian518ec112011-05-13 16:21:08 -0700930}
931
Michael Chockc0ec5e22014-01-27 08:14:33 -0800932static __eglMustCastToProperFunctionPointerType findBuiltinWrapper(
Jesse Hallc07b5202013-07-04 12:08:16 -0700933 const char* procname) {
934 const egl_connection_t* cnx = &gEGLImpl;
935 void* proc = NULL;
936
Michael Chockc0ec5e22014-01-27 08:14:33 -0800937 proc = dlsym(cnx->libEgl, procname);
938 if (proc) return (__eglMustCastToProperFunctionPointerType)proc;
939
Jesse Hallc07b5202013-07-04 12:08:16 -0700940 proc = dlsym(cnx->libGles2, procname);
941 if (proc) return (__eglMustCastToProperFunctionPointerType)proc;
942
943 proc = dlsym(cnx->libGles1, procname);
944 if (proc) return (__eglMustCastToProperFunctionPointerType)proc;
945
946 return NULL;
947}
948
Mathias Agopian518ec112011-05-13 16:21:08 -0700949__eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
950{
951 // eglGetProcAddress() could be the very first function called
952 // in which case we must make sure we've initialized ourselves, this
953 // happens the first time egl_get_display() is called.
954
955 clearError();
956
957 if (egl_init_drivers() == EGL_FALSE) {
958 setError(EGL_BAD_PARAMETER, NULL);
959 return NULL;
960 }
961
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700962 if (FILTER_EXTENSIONS(procname)) {
Jamie Gennisaca51c02011-11-03 17:42:43 -0700963 return NULL;
964 }
965
Mathias Agopian518ec112011-05-13 16:21:08 -0700966 __eglMustCastToProperFunctionPointerType addr;
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700967 addr = findProcAddress(procname, sExtensionMap, NELEM(sExtensionMap));
Mathias Agopian518ec112011-05-13 16:21:08 -0700968 if (addr) return addr;
969
Michael Chockc0ec5e22014-01-27 08:14:33 -0800970 addr = findBuiltinWrapper(procname);
Jesse Hallc07b5202013-07-04 12:08:16 -0700971 if (addr) return addr;
Jamie Gennisaca51c02011-11-03 17:42:43 -0700972
Mathias Agopian518ec112011-05-13 16:21:08 -0700973 // this protects accesses to sGLExtentionMap and sGLExtentionSlot
974 pthread_mutex_lock(&sExtensionMapMutex);
975
976 /*
977 * Since eglGetProcAddress() is not associated to anything, it needs
978 * to return a function pointer that "works" regardless of what
979 * the current context is.
980 *
981 * For this reason, we return a "forwarder", a small stub that takes
982 * care of calling the function associated with the context
983 * currently bound.
984 *
985 * We first look for extensions we've already resolved, if we're seeing
986 * this extension for the first time, we go through all our
987 * implementations and call eglGetProcAddress() and record the
988 * result in the appropriate implementation hooks and return the
989 * address of the forwarder corresponding to that hook set.
990 *
991 */
992
993 const String8 name(procname);
994 addr = sGLExtentionMap.valueFor(name);
995 const int slot = sGLExtentionSlot;
996
Steve Blocke6f43dd2012-01-06 19:20:56 +0000997 ALOGE_IF(slot >= MAX_NUMBER_OF_GL_EXTENSIONS,
Mathias Agopian518ec112011-05-13 16:21:08 -0700998 "no more slots for eglGetProcAddress(\"%s\")",
999 procname);
1000
1001 if (!addr && (slot < MAX_NUMBER_OF_GL_EXTENSIONS)) {
1002 bool found = false;
Mathias Agopianada798b2012-02-13 17:09:30 -08001003
1004 egl_connection_t* const cnx = &gEGLImpl;
1005 if (cnx->dso && cnx->egl.eglGetProcAddress) {
Mathias Agopianada798b2012-02-13 17:09:30 -08001006 // Extensions are independent of the bound context
luliuhui69d10072012-08-30 11:15:36 +08001007 addr =
Mathias Agopian7773c432012-02-13 20:06:08 -08001008 cnx->hooks[egl_connection_t::GLESv1_INDEX]->ext.extensions[slot] =
1009 cnx->hooks[egl_connection_t::GLESv2_INDEX]->ext.extensions[slot] =
Mathias Agopianada798b2012-02-13 17:09:30 -08001010 cnx->egl.eglGetProcAddress(procname);
luliuhui69d10072012-08-30 11:15:36 +08001011 if (addr) found = true;
Mathias Agopian518ec112011-05-13 16:21:08 -07001012 }
Mathias Agopianada798b2012-02-13 17:09:30 -08001013
Mathias Agopian518ec112011-05-13 16:21:08 -07001014 if (found) {
1015 addr = gExtensionForwarders[slot];
Mathias Agopian518ec112011-05-13 16:21:08 -07001016 sGLExtentionMap.add(name, addr);
1017 sGLExtentionSlot++;
1018 }
1019 }
1020
1021 pthread_mutex_unlock(&sExtensionMapMutex);
1022 return addr;
1023}
1024
Jamie Gennis28ef8d72012-04-05 20:34:54 -07001025class FrameCompletionThread : public Thread {
1026public:
1027
1028 static void queueSync(EGLSyncKHR sync) {
1029 static sp<FrameCompletionThread> thread(new FrameCompletionThread);
1030 static bool running = false;
1031 if (!running) {
1032 thread->run("GPUFrameCompletion");
1033 running = true;
1034 }
1035 {
1036 Mutex::Autolock lock(thread->mMutex);
1037 ScopedTrace st(ATRACE_TAG, String8::format("kicked off frame %d",
1038 thread->mFramesQueued).string());
1039 thread->mQueue.push_back(sync);
1040 thread->mCondition.signal();
1041 thread->mFramesQueued++;
1042 ATRACE_INT("GPU Frames Outstanding", thread->mQueue.size());
1043 }
1044 }
1045
1046private:
1047 FrameCompletionThread() : mFramesQueued(0), mFramesCompleted(0) {}
1048
1049 virtual bool threadLoop() {
1050 EGLSyncKHR sync;
1051 uint32_t frameNum;
1052 {
1053 Mutex::Autolock lock(mMutex);
1054 while (mQueue.isEmpty()) {
1055 mCondition.wait(mMutex);
1056 }
1057 sync = mQueue[0];
1058 frameNum = mFramesCompleted;
1059 }
1060 EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
1061 {
1062 ScopedTrace st(ATRACE_TAG, String8::format("waiting for frame %d",
1063 frameNum).string());
1064 EGLint result = eglClientWaitSyncKHR(dpy, sync, 0, EGL_FOREVER_KHR);
1065 if (result == EGL_FALSE) {
1066 ALOGE("FrameCompletion: error waiting for fence: %#x", eglGetError());
1067 } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
1068 ALOGE("FrameCompletion: timeout waiting for fence");
1069 }
1070 eglDestroySyncKHR(dpy, sync);
1071 }
1072 {
1073 Mutex::Autolock lock(mMutex);
1074 mQueue.removeAt(0);
1075 mFramesCompleted++;
1076 ATRACE_INT("GPU Frames Outstanding", mQueue.size());
1077 }
1078 return true;
1079 }
1080
1081 uint32_t mFramesQueued;
1082 uint32_t mFramesCompleted;
1083 Vector<EGLSyncKHR> mQueue;
1084 Condition mCondition;
1085 Mutex mMutex;
1086};
1087
Dan Stozaa894d082015-02-19 15:27:36 -08001088EGLBoolean eglSwapBuffersWithDamageKHR(EGLDisplay dpy, EGLSurface draw,
1089 EGLint *rects, EGLint n_rects)
Mathias Agopian518ec112011-05-13 16:21:08 -07001090{
Jamie Gennis1c8e95c2012-02-23 19:27:23 -08001091 ATRACE_CALL();
Mathias Agopian518ec112011-05-13 16:21:08 -07001092 clearError();
1093
Jesse Hallb29e5e82012-04-04 16:53:42 -07001094 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001095 if (!dp) return EGL_FALSE;
1096
Jesse Hallb29e5e82012-04-04 16:53:42 -07001097 SurfaceRef _s(dp.get(), draw);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001098 if (!_s.get())
1099 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001100
Mathias Agopian518ec112011-05-13 16:21:08 -07001101 egl_surface_t const * const s = get_surface(draw);
Mathias Agopian7db993a2012-03-25 00:49:46 -07001102
Mathias Agopianed6d08b2013-04-16 16:39:46 -07001103 if (CC_UNLIKELY(dp->traceGpuCompletion)) {
1104 EGLSyncKHR sync = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, NULL);
1105 if (sync != EGL_NO_SYNC_KHR) {
1106 FrameCompletionThread::queueSync(sync);
1107 }
1108 }
1109
Mathias Agopian7db993a2012-03-25 00:49:46 -07001110 if (CC_UNLIKELY(dp->finishOnSwap)) {
1111 uint32_t pixel;
1112 egl_context_t * const c = get_context( egl_tls_t::getContext() );
1113 if (c) {
1114 // glReadPixels() ensures that the frame is complete
1115 s->cnx->hooks[c->version]->gl.glReadPixels(0,0,1,1,
1116 GL_RGBA,GL_UNSIGNED_BYTE,&pixel);
1117 }
1118 }
1119
Dan Stozaa894d082015-02-19 15:27:36 -08001120 if (n_rects == 0) {
1121 return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface);
1122 }
1123
1124 Vector<android_native_rect_t> androidRects;
1125 for (int r = 0; r < n_rects; ++r) {
1126 int offset = r * 4;
1127 int x = rects[offset];
1128 int y = rects[offset + 1];
1129 int width = rects[offset + 2];
1130 int height = rects[offset + 3];
1131 android_native_rect_t androidRect;
1132 androidRect.left = x;
1133 androidRect.top = y + height;
1134 androidRect.right = x + width;
1135 androidRect.bottom = y;
1136 androidRects.push_back(androidRect);
1137 }
1138 native_window_set_surface_damage(s->win.get(), androidRects.array(),
1139 androidRects.size());
1140
1141 if (s->cnx->egl.eglSwapBuffersWithDamageKHR) {
1142 return s->cnx->egl.eglSwapBuffersWithDamageKHR(dp->disp.dpy, s->surface,
1143 rects, n_rects);
1144 } else {
1145 return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface);
1146 }
1147}
1148
1149EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
1150{
1151 return eglSwapBuffersWithDamageKHR(dpy, surface, NULL, 0);
Mathias Agopian518ec112011-05-13 16:21:08 -07001152}
1153
1154EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface,
1155 NativePixmapType target)
1156{
1157 clearError();
1158
Jesse Hallb29e5e82012-04-04 16:53:42 -07001159 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001160 if (!dp) return EGL_FALSE;
1161
Jesse Hallb29e5e82012-04-04 16:53:42 -07001162 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001163 if (!_s.get())
1164 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001165
Mathias Agopian518ec112011-05-13 16:21:08 -07001166 egl_surface_t const * const s = get_surface(surface);
Mathias Agopianada798b2012-02-13 17:09:30 -08001167 return s->cnx->egl.eglCopyBuffers(dp->disp.dpy, s->surface, target);
Mathias Agopian518ec112011-05-13 16:21:08 -07001168}
1169
1170const char* eglQueryString(EGLDisplay dpy, EGLint name)
1171{
1172 clearError();
1173
Chia-I Wue57d1352016-08-15 16:10:02 +08001174 // Generate an error quietly when client extensions (as defined by
1175 // EGL_EXT_client_extensions) are queried. We do not want to rely on
1176 // validate_display to generate the error as validate_display would log
1177 // the error, which can be misleading.
1178 //
1179 // If we want to support EGL_EXT_client_extensions later, we can return
1180 // the client extension string here instead.
1181 if (dpy == EGL_NO_DISPLAY && name == EGL_EXTENSIONS)
1182 return setErrorQuiet(EGL_BAD_DISPLAY, nullptr);
1183
Jesse Hallb29e5e82012-04-04 16:53:42 -07001184 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001185 if (!dp) return (const char *) NULL;
1186
1187 switch (name) {
1188 case EGL_VENDOR:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001189 return dp->getVendorString();
Mathias Agopian518ec112011-05-13 16:21:08 -07001190 case EGL_VERSION:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001191 return dp->getVersionString();
Mathias Agopian518ec112011-05-13 16:21:08 -07001192 case EGL_EXTENSIONS:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001193 return dp->getExtensionString();
Mathias Agopian518ec112011-05-13 16:21:08 -07001194 case EGL_CLIENT_APIS:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001195 return dp->getClientApiString();
Mathias Agopian518ec112011-05-13 16:21:08 -07001196 }
1197 return setError(EGL_BAD_PARAMETER, (const char *)0);
1198}
1199
Mathias Agopianca088332013-03-28 17:44:13 -07001200EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name)
1201{
1202 clearError();
1203
1204 const egl_display_ptr dp = validate_display(dpy);
1205 if (!dp) return (const char *) NULL;
1206
1207 switch (name) {
1208 case EGL_VENDOR:
1209 return dp->disp.queryString.vendor;
1210 case EGL_VERSION:
1211 return dp->disp.queryString.version;
1212 case EGL_EXTENSIONS:
1213 return dp->disp.queryString.extensions;
1214 case EGL_CLIENT_APIS:
1215 return dp->disp.queryString.clientApi;
1216 }
1217 return setError(EGL_BAD_PARAMETER, (const char *)0);
1218}
Mathias Agopian518ec112011-05-13 16:21:08 -07001219
1220// ----------------------------------------------------------------------------
1221// EGL 1.1
1222// ----------------------------------------------------------------------------
1223
1224EGLBoolean eglSurfaceAttrib(
1225 EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
1226{
1227 clearError();
1228
Jesse Hallb29e5e82012-04-04 16:53:42 -07001229 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001230 if (!dp) return EGL_FALSE;
1231
Jesse Hallb29e5e82012-04-04 16:53:42 -07001232 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001233 if (!_s.get())
1234 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001235
Pablo Ceballosc18be292016-05-31 14:55:42 -07001236 egl_surface_t * const s = get_surface(surface);
Pablo Ceballosccdfd602015-10-07 15:05:45 -07001237
Pablo Ceballos02b05da2016-02-02 17:53:18 -08001238 if (attribute == EGL_FRONT_BUFFER_AUTO_REFRESH_ANDROID) {
Brian Anderson069b3652016-07-22 10:32:47 -07001239 if (!s->win.get()) {
1240 setError(EGL_BAD_SURFACE, EGL_FALSE);
1241 }
Pablo Ceballosf051ade2016-03-15 18:27:20 -07001242 int err = native_window_set_auto_refresh(s->win.get(),
1243 value ? true : false);
1244 return (err == NO_ERROR) ? EGL_TRUE :
1245 setError(EGL_BAD_SURFACE, EGL_FALSE);
Pablo Ceballosccdfd602015-10-07 15:05:45 -07001246 }
1247
Pablo Ceballosc18be292016-05-31 14:55:42 -07001248 if (attribute == EGL_TIMESTAMPS_ANDROID) {
Brian Anderson069b3652016-07-22 10:32:47 -07001249 if (!s->win.get()) {
1250 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1251 }
Brian Anderson069b3652016-07-22 10:32:47 -07001252 int err = native_window_enable_frame_timestamps(
1253 s->win.get(), value ? true : false);
1254 return (err == NO_ERROR) ? EGL_TRUE :
1255 setError(EGL_BAD_SURFACE, EGL_FALSE);
Pablo Ceballosc18be292016-05-31 14:55:42 -07001256 }
1257
Mathias Agopian518ec112011-05-13 16:21:08 -07001258 if (s->cnx->egl.eglSurfaceAttrib) {
1259 return s->cnx->egl.eglSurfaceAttrib(
Mathias Agopianada798b2012-02-13 17:09:30 -08001260 dp->disp.dpy, s->surface, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -07001261 }
1262 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1263}
1264
1265EGLBoolean eglBindTexImage(
1266 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1267{
1268 clearError();
1269
Jesse Hallb29e5e82012-04-04 16:53:42 -07001270 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001271 if (!dp) return EGL_FALSE;
1272
Jesse Hallb29e5e82012-04-04 16:53:42 -07001273 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001274 if (!_s.get())
1275 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001276
Mathias Agopian518ec112011-05-13 16:21:08 -07001277 egl_surface_t const * const s = get_surface(surface);
1278 if (s->cnx->egl.eglBindTexImage) {
1279 return s->cnx->egl.eglBindTexImage(
Mathias Agopianada798b2012-02-13 17:09:30 -08001280 dp->disp.dpy, s->surface, buffer);
Mathias Agopian518ec112011-05-13 16:21:08 -07001281 }
1282 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1283}
1284
1285EGLBoolean eglReleaseTexImage(
1286 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1287{
1288 clearError();
1289
Jesse Hallb29e5e82012-04-04 16:53:42 -07001290 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001291 if (!dp) return EGL_FALSE;
1292
Jesse Hallb29e5e82012-04-04 16:53:42 -07001293 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001294 if (!_s.get())
1295 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001296
Mathias Agopian518ec112011-05-13 16:21:08 -07001297 egl_surface_t const * const s = get_surface(surface);
1298 if (s->cnx->egl.eglReleaseTexImage) {
1299 return s->cnx->egl.eglReleaseTexImage(
Mathias Agopianada798b2012-02-13 17:09:30 -08001300 dp->disp.dpy, s->surface, buffer);
Mathias Agopian518ec112011-05-13 16:21:08 -07001301 }
1302 return setError(EGL_BAD_SURFACE, EGL_FALSE);
1303}
1304
1305EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
1306{
1307 clearError();
1308
Jesse Hallb29e5e82012-04-04 16:53:42 -07001309 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001310 if (!dp) return EGL_FALSE;
1311
1312 EGLBoolean res = EGL_TRUE;
Mathias Agopianada798b2012-02-13 17:09:30 -08001313 egl_connection_t* const cnx = &gEGLImpl;
1314 if (cnx->dso && cnx->egl.eglSwapInterval) {
1315 res = cnx->egl.eglSwapInterval(dp->disp.dpy, interval);
Mathias Agopian518ec112011-05-13 16:21:08 -07001316 }
Mathias Agopianada798b2012-02-13 17:09:30 -08001317
Mathias Agopian518ec112011-05-13 16:21:08 -07001318 return res;
1319}
1320
1321
1322// ----------------------------------------------------------------------------
1323// EGL 1.2
1324// ----------------------------------------------------------------------------
1325
1326EGLBoolean eglWaitClient(void)
1327{
1328 clearError();
1329
Mathias Agopianada798b2012-02-13 17:09:30 -08001330 egl_connection_t* const cnx = &gEGLImpl;
1331 if (!cnx->dso)
1332 return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1333
1334 EGLBoolean res;
1335 if (cnx->egl.eglWaitClient) {
1336 res = cnx->egl.eglWaitClient();
1337 } else {
1338 res = cnx->egl.eglWaitGL();
Mathias Agopian518ec112011-05-13 16:21:08 -07001339 }
1340 return res;
1341}
1342
1343EGLBoolean eglBindAPI(EGLenum api)
1344{
1345 clearError();
1346
1347 if (egl_init_drivers() == EGL_FALSE) {
1348 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1349 }
1350
1351 // bind this API on all EGLs
1352 EGLBoolean res = EGL_TRUE;
Mathias Agopianada798b2012-02-13 17:09:30 -08001353 egl_connection_t* const cnx = &gEGLImpl;
1354 if (cnx->dso && cnx->egl.eglBindAPI) {
1355 res = cnx->egl.eglBindAPI(api);
Mathias Agopian518ec112011-05-13 16:21:08 -07001356 }
1357 return res;
1358}
1359
1360EGLenum eglQueryAPI(void)
1361{
1362 clearError();
1363
1364 if (egl_init_drivers() == EGL_FALSE) {
1365 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1366 }
1367
Mathias Agopianada798b2012-02-13 17:09:30 -08001368 egl_connection_t* const cnx = &gEGLImpl;
1369 if (cnx->dso && cnx->egl.eglQueryAPI) {
1370 return cnx->egl.eglQueryAPI();
Mathias Agopian518ec112011-05-13 16:21:08 -07001371 }
Mathias Agopianada798b2012-02-13 17:09:30 -08001372
Mathias Agopian518ec112011-05-13 16:21:08 -07001373 // or, it can only be OpenGL ES
1374 return EGL_OPENGL_ES_API;
1375}
1376
1377EGLBoolean eglReleaseThread(void)
1378{
1379 clearError();
1380
Mathias Agopianada798b2012-02-13 17:09:30 -08001381 egl_connection_t* const cnx = &gEGLImpl;
1382 if (cnx->dso && cnx->egl.eglReleaseThread) {
1383 cnx->egl.eglReleaseThread();
Mathias Agopian518ec112011-05-13 16:21:08 -07001384 }
Sai Kiran Korwar3ac517a2014-01-31 21:15:07 +05301385
1386 // If there is context bound to the thread, release it
1387 egl_display_t::loseCurrent(get_context(getContext()));
1388
Mathias Agopian518ec112011-05-13 16:21:08 -07001389 egl_tls_t::clearTLS();
Mathias Agopian518ec112011-05-13 16:21:08 -07001390 return EGL_TRUE;
1391}
1392
1393EGLSurface eglCreatePbufferFromClientBuffer(
1394 EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer,
1395 EGLConfig config, const EGLint *attrib_list)
1396{
1397 clearError();
1398
Jesse Hallb29e5e82012-04-04 16:53:42 -07001399 egl_connection_t* cnx = NULL;
1400 const egl_display_ptr dp = validate_display_connection(dpy, cnx);
1401 if (!dp) return EGL_FALSE;
Mathias Agopian518ec112011-05-13 16:21:08 -07001402 if (cnx->egl.eglCreatePbufferFromClientBuffer) {
1403 return cnx->egl.eglCreatePbufferFromClientBuffer(
Mathias Agopian7773c432012-02-13 20:06:08 -08001404 dp->disp.dpy, buftype, buffer, config, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001405 }
1406 return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE);
1407}
1408
1409// ----------------------------------------------------------------------------
1410// EGL_EGLEXT_VERSION 3
1411// ----------------------------------------------------------------------------
1412
1413EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface,
1414 const EGLint *attrib_list)
1415{
1416 clearError();
1417
Jesse Hallb29e5e82012-04-04 16:53:42 -07001418 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001419 if (!dp) return EGL_FALSE;
1420
Jesse Hallb29e5e82012-04-04 16:53:42 -07001421 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001422 if (!_s.get())
1423 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001424
1425 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian518ec112011-05-13 16:21:08 -07001426 if (s->cnx->egl.eglLockSurfaceKHR) {
1427 return s->cnx->egl.eglLockSurfaceKHR(
Mathias Agopianada798b2012-02-13 17:09:30 -08001428 dp->disp.dpy, s->surface, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001429 }
1430 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1431}
1432
1433EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface)
1434{
1435 clearError();
1436
Jesse Hallb29e5e82012-04-04 16:53:42 -07001437 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001438 if (!dp) return EGL_FALSE;
1439
Jesse Hallb29e5e82012-04-04 16:53:42 -07001440 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001441 if (!_s.get())
1442 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001443
1444 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian518ec112011-05-13 16:21:08 -07001445 if (s->cnx->egl.eglUnlockSurfaceKHR) {
Mathias Agopianada798b2012-02-13 17:09:30 -08001446 return s->cnx->egl.eglUnlockSurfaceKHR(dp->disp.dpy, s->surface);
Mathias Agopian518ec112011-05-13 16:21:08 -07001447 }
1448 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1449}
1450
1451EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
1452 EGLClientBuffer buffer, const EGLint *attrib_list)
1453{
1454 clearError();
1455
Jesse Hallb29e5e82012-04-04 16:53:42 -07001456 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001457 if (!dp) return EGL_NO_IMAGE_KHR;
1458
Jesse Hallb29e5e82012-04-04 16:53:42 -07001459 ContextRef _c(dp.get(), ctx);
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001460 egl_context_t * const c = _c.get();
Mathias Agopian518ec112011-05-13 16:21:08 -07001461
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001462 EGLImageKHR result = EGL_NO_IMAGE_KHR;
1463 egl_connection_t* const cnx = &gEGLImpl;
1464 if (cnx->dso && cnx->egl.eglCreateImageKHR) {
1465 result = cnx->egl.eglCreateImageKHR(
1466 dp->disp.dpy,
1467 c ? c->context : EGL_NO_CONTEXT,
1468 target, buffer, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001469 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001470 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001471}
1472
1473EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
1474{
1475 clearError();
1476
Jesse Hallb29e5e82012-04-04 16:53:42 -07001477 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001478 if (!dp) return EGL_FALSE;
1479
Steven Holte646a5c52012-06-04 20:02:11 -07001480 EGLBoolean result = EGL_FALSE;
Mathias Agopianada798b2012-02-13 17:09:30 -08001481 egl_connection_t* const cnx = &gEGLImpl;
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001482 if (cnx->dso && cnx->egl.eglDestroyImageKHR) {
Steven Holte646a5c52012-06-04 20:02:11 -07001483 result = cnx->egl.eglDestroyImageKHR(dp->disp.dpy, img);
Mathias Agopian518ec112011-05-13 16:21:08 -07001484 }
Steven Holte646a5c52012-06-04 20:02:11 -07001485 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001486}
1487
1488// ----------------------------------------------------------------------------
1489// EGL_EGLEXT_VERSION 5
1490// ----------------------------------------------------------------------------
1491
1492
1493EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
1494{
1495 clearError();
1496
Jesse Hallb29e5e82012-04-04 16:53:42 -07001497 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001498 if (!dp) return EGL_NO_SYNC_KHR;
1499
Mathias Agopian518ec112011-05-13 16:21:08 -07001500 EGLSyncKHR result = EGL_NO_SYNC_KHR;
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001501 egl_connection_t* const cnx = &gEGLImpl;
1502 if (cnx->dso && cnx->egl.eglCreateSyncKHR) {
1503 result = cnx->egl.eglCreateSyncKHR(dp->disp.dpy, type, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001504 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001505 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001506}
1507
1508EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
1509{
1510 clearError();
1511
Jesse Hallb29e5e82012-04-04 16:53:42 -07001512 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001513 if (!dp) return EGL_FALSE;
1514
Mathias Agopian518ec112011-05-13 16:21:08 -07001515 EGLBoolean result = EGL_FALSE;
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001516 egl_connection_t* const cnx = &gEGLImpl;
1517 if (cnx->dso && cnx->egl.eglDestroySyncKHR) {
1518 result = cnx->egl.eglDestroySyncKHR(dp->disp.dpy, sync);
Mathias Agopian518ec112011-05-13 16:21:08 -07001519 }
1520 return result;
1521}
1522
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -07001523EGLBoolean eglSignalSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode) {
1524 clearError();
1525
1526 const egl_display_ptr dp = validate_display(dpy);
1527 if (!dp) return EGL_FALSE;
1528
1529 EGLBoolean result = EGL_FALSE;
1530 egl_connection_t* const cnx = &gEGLImpl;
1531 if (cnx->dso && cnx->egl.eglSignalSyncKHR) {
1532 result = cnx->egl.eglSignalSyncKHR(
1533 dp->disp.dpy, sync, mode);
1534 }
1535 return result;
1536}
1537
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001538EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync,
1539 EGLint flags, EGLTimeKHR timeout)
Mathias Agopian518ec112011-05-13 16:21:08 -07001540{
1541 clearError();
1542
Jesse Hallb29e5e82012-04-04 16:53:42 -07001543 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001544 if (!dp) return EGL_FALSE;
1545
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001546 EGLBoolean result = EGL_FALSE;
1547 egl_connection_t* const cnx = &gEGLImpl;
1548 if (cnx->dso && cnx->egl.eglClientWaitSyncKHR) {
1549 result = cnx->egl.eglClientWaitSyncKHR(
1550 dp->disp.dpy, sync, flags, timeout);
Mathias Agopian518ec112011-05-13 16:21:08 -07001551 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001552 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001553}
1554
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001555EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync,
1556 EGLint attribute, EGLint *value)
Mathias Agopian518ec112011-05-13 16:21:08 -07001557{
1558 clearError();
1559
Jesse Hallb29e5e82012-04-04 16:53:42 -07001560 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001561 if (!dp) return EGL_FALSE;
1562
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001563 EGLBoolean result = EGL_FALSE;
1564 egl_connection_t* const cnx = &gEGLImpl;
1565 if (cnx->dso && cnx->egl.eglGetSyncAttribKHR) {
1566 result = cnx->egl.eglGetSyncAttribKHR(
1567 dp->disp.dpy, sync, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -07001568 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001569 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001570}
1571
Season Li000d88f2015-07-01 11:39:40 -07001572EGLStreamKHR eglCreateStreamKHR(EGLDisplay dpy, const EGLint *attrib_list)
1573{
1574 clearError();
1575
1576 const egl_display_ptr dp = validate_display(dpy);
1577 if (!dp) return EGL_NO_STREAM_KHR;
1578
1579 EGLStreamKHR result = EGL_NO_STREAM_KHR;
1580 egl_connection_t* const cnx = &gEGLImpl;
1581 if (cnx->dso && cnx->egl.eglCreateStreamKHR) {
1582 result = cnx->egl.eglCreateStreamKHR(
1583 dp->disp.dpy, attrib_list);
1584 }
1585 return result;
1586}
1587
1588EGLBoolean eglDestroyStreamKHR(EGLDisplay dpy, EGLStreamKHR stream)
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.eglDestroyStreamKHR) {
1598 result = cnx->egl.eglDestroyStreamKHR(
1599 dp->disp.dpy, stream);
1600 }
1601 return result;
1602}
1603
1604EGLBoolean eglStreamAttribKHR(EGLDisplay dpy, EGLStreamKHR stream,
1605 EGLenum attribute, EGLint 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.eglStreamAttribKHR) {
1615 result = cnx->egl.eglStreamAttribKHR(
1616 dp->disp.dpy, stream, attribute, value);
1617 }
1618 return result;
1619}
1620
1621EGLBoolean eglQueryStreamKHR(EGLDisplay dpy, EGLStreamKHR stream,
1622 EGLenum attribute, EGLint *value)
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.eglQueryStreamKHR) {
1632 result = cnx->egl.eglQueryStreamKHR(
1633 dp->disp.dpy, stream, attribute, value);
1634 }
1635 return result;
1636}
1637
1638EGLBoolean eglQueryStreamu64KHR(EGLDisplay dpy, EGLStreamKHR stream,
1639 EGLenum attribute, EGLuint64KHR *value)
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.eglQueryStreamu64KHR) {
1649 result = cnx->egl.eglQueryStreamu64KHR(
1650 dp->disp.dpy, stream, attribute, value);
1651 }
1652 return result;
1653}
1654
1655EGLBoolean eglQueryStreamTimeKHR(EGLDisplay dpy, EGLStreamKHR stream,
1656 EGLenum attribute, EGLTimeKHR *value)
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.eglQueryStreamTimeKHR) {
1666 result = cnx->egl.eglQueryStreamTimeKHR(
1667 dp->disp.dpy, stream, attribute, value);
1668 }
1669 return result;
1670}
1671
1672EGLSurface eglCreateStreamProducerSurfaceKHR(EGLDisplay dpy, EGLConfig config,
1673 EGLStreamKHR stream, const EGLint *attrib_list)
1674{
1675 clearError();
1676
1677 egl_display_ptr dp = validate_display(dpy);
1678 if (!dp) return EGL_NO_SURFACE;
1679
1680 egl_connection_t* const cnx = &gEGLImpl;
1681 if (cnx->dso && cnx->egl.eglCreateStreamProducerSurfaceKHR) {
1682 EGLSurface surface = cnx->egl.eglCreateStreamProducerSurfaceKHR(
1683 dp->disp.dpy, config, stream, attrib_list);
1684 if (surface != EGL_NO_SURFACE) {
1685 egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL,
1686 surface, cnx);
1687 return s;
1688 }
1689 }
1690 return EGL_NO_SURFACE;
1691}
1692
1693EGLBoolean eglStreamConsumerGLTextureExternalKHR(EGLDisplay dpy,
1694 EGLStreamKHR stream)
1695{
1696 clearError();
1697
1698 const egl_display_ptr dp = validate_display(dpy);
1699 if (!dp) return EGL_FALSE;
1700
1701 EGLBoolean result = EGL_FALSE;
1702 egl_connection_t* const cnx = &gEGLImpl;
1703 if (cnx->dso && cnx->egl.eglStreamConsumerGLTextureExternalKHR) {
1704 result = cnx->egl.eglStreamConsumerGLTextureExternalKHR(
1705 dp->disp.dpy, stream);
1706 }
1707 return result;
1708}
1709
1710EGLBoolean eglStreamConsumerAcquireKHR(EGLDisplay dpy,
1711 EGLStreamKHR stream)
1712{
1713 clearError();
1714
1715 const egl_display_ptr dp = validate_display(dpy);
1716 if (!dp) return EGL_FALSE;
1717
1718 EGLBoolean result = EGL_FALSE;
1719 egl_connection_t* const cnx = &gEGLImpl;
1720 if (cnx->dso && cnx->egl.eglStreamConsumerAcquireKHR) {
1721 result = cnx->egl.eglStreamConsumerAcquireKHR(
1722 dp->disp.dpy, stream);
1723 }
1724 return result;
1725}
1726
1727EGLBoolean eglStreamConsumerReleaseKHR(EGLDisplay dpy,
1728 EGLStreamKHR stream)
1729{
1730 clearError();
1731
1732 const egl_display_ptr dp = validate_display(dpy);
1733 if (!dp) return EGL_FALSE;
1734
1735 EGLBoolean result = EGL_FALSE;
1736 egl_connection_t* const cnx = &gEGLImpl;
1737 if (cnx->dso && cnx->egl.eglStreamConsumerReleaseKHR) {
1738 result = cnx->egl.eglStreamConsumerReleaseKHR(
1739 dp->disp.dpy, stream);
1740 }
1741 return result;
1742}
1743
1744EGLNativeFileDescriptorKHR eglGetStreamFileDescriptorKHR(
1745 EGLDisplay dpy, EGLStreamKHR stream)
1746{
1747 clearError();
1748
1749 const egl_display_ptr dp = validate_display(dpy);
1750 if (!dp) return EGL_NO_FILE_DESCRIPTOR_KHR;
1751
1752 EGLNativeFileDescriptorKHR result = EGL_NO_FILE_DESCRIPTOR_KHR;
1753 egl_connection_t* const cnx = &gEGLImpl;
1754 if (cnx->dso && cnx->egl.eglGetStreamFileDescriptorKHR) {
1755 result = cnx->egl.eglGetStreamFileDescriptorKHR(
1756 dp->disp.dpy, stream);
1757 }
1758 return result;
1759}
1760
1761EGLStreamKHR eglCreateStreamFromFileDescriptorKHR(
1762 EGLDisplay dpy, EGLNativeFileDescriptorKHR file_descriptor)
1763{
1764 clearError();
1765
1766 const egl_display_ptr dp = validate_display(dpy);
1767 if (!dp) return EGL_NO_STREAM_KHR;
1768
1769 EGLStreamKHR result = EGL_NO_STREAM_KHR;
1770 egl_connection_t* const cnx = &gEGLImpl;
1771 if (cnx->dso && cnx->egl.eglCreateStreamFromFileDescriptorKHR) {
1772 result = cnx->egl.eglCreateStreamFromFileDescriptorKHR(
1773 dp->disp.dpy, file_descriptor);
1774 }
1775 return result;
1776}
1777
Mathias Agopian518ec112011-05-13 16:21:08 -07001778// ----------------------------------------------------------------------------
Mathias Agopian2bb71682013-03-27 17:32:41 -07001779// EGL_EGLEXT_VERSION 15
1780// ----------------------------------------------------------------------------
1781
1782EGLint eglWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags) {
1783 clearError();
1784 const egl_display_ptr dp = validate_display(dpy);
1785 if (!dp) return EGL_FALSE;
1786 EGLint result = EGL_FALSE;
1787 egl_connection_t* const cnx = &gEGLImpl;
1788 if (cnx->dso && cnx->egl.eglWaitSyncKHR) {
1789 result = cnx->egl.eglWaitSyncKHR(dp->disp.dpy, sync, flags);
1790 }
1791 return result;
1792}
1793
1794// ----------------------------------------------------------------------------
Mathias Agopian518ec112011-05-13 16:21:08 -07001795// ANDROID extensions
1796// ----------------------------------------------------------------------------
1797
Jamie Gennis331841b2012-09-06 14:52:00 -07001798EGLint eglDupNativeFenceFDANDROID(EGLDisplay dpy, EGLSyncKHR sync)
1799{
1800 clearError();
1801
1802 const egl_display_ptr dp = validate_display(dpy);
1803 if (!dp) return EGL_NO_NATIVE_FENCE_FD_ANDROID;
1804
1805 EGLint result = EGL_NO_NATIVE_FENCE_FD_ANDROID;
1806 egl_connection_t* const cnx = &gEGLImpl;
1807 if (cnx->dso && cnx->egl.eglDupNativeFenceFDANDROID) {
1808 result = cnx->egl.eglDupNativeFenceFDANDROID(dp->disp.dpy, sync);
1809 }
1810 return result;
1811}
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001812
Andy McFadden72841452013-03-01 16:25:32 -08001813EGLBoolean eglPresentationTimeANDROID(EGLDisplay dpy, EGLSurface surface,
1814 EGLnsecsANDROID time)
1815{
1816 clearError();
1817
1818 const egl_display_ptr dp = validate_display(dpy);
1819 if (!dp) {
1820 return EGL_FALSE;
1821 }
1822
1823 SurfaceRef _s(dp.get(), surface);
1824 if (!_s.get()) {
1825 setError(EGL_BAD_SURFACE, EGL_FALSE);
1826 return EGL_FALSE;
1827 }
1828
1829 egl_surface_t const * const s = get_surface(surface);
1830 native_window_set_buffers_timestamp(s->win.get(), time);
1831
1832 return EGL_TRUE;
1833}
1834
Craig Donner05249fc2016-01-15 19:33:55 -08001835EGLClientBuffer eglCreateNativeClientBufferANDROID(const EGLint *attrib_list)
1836{
1837 clearError();
1838
Craig Donnere96a3252017-02-02 12:13:34 -08001839 uint64_t producerUsage = 0;
1840 uint64_t consumerUsage = 0;
Craig Donner05249fc2016-01-15 19:33:55 -08001841 uint32_t width = 0;
1842 uint32_t height = 0;
1843 uint32_t format = 0;
Craig Donner6ebc46a2016-10-21 15:23:44 -07001844 uint32_t layer_count = 1;
Craig Donner05249fc2016-01-15 19:33:55 -08001845 uint32_t red_size = 0;
1846 uint32_t green_size = 0;
1847 uint32_t blue_size = 0;
1848 uint32_t alpha_size = 0;
1849
Craig Donnerb40504a2016-06-03 17:54:25 -07001850#define GET_NONNEGATIVE_VALUE(case_name, target) \
Craig Donner05249fc2016-01-15 19:33:55 -08001851 case case_name: \
Craig Donnerb40504a2016-06-03 17:54:25 -07001852 if (value >= 0) { \
Craig Donner05249fc2016-01-15 19:33:55 -08001853 target = value; \
1854 } else { \
1855 return setError(EGL_BAD_PARAMETER, (EGLClientBuffer)0); \
1856 } \
1857 break
1858
1859 if (attrib_list) {
1860 while (*attrib_list != EGL_NONE) {
1861 GLint attr = *attrib_list++;
1862 GLint value = *attrib_list++;
1863 switch (attr) {
Craig Donnerb40504a2016-06-03 17:54:25 -07001864 GET_NONNEGATIVE_VALUE(EGL_WIDTH, width);
1865 GET_NONNEGATIVE_VALUE(EGL_HEIGHT, height);
1866 GET_NONNEGATIVE_VALUE(EGL_RED_SIZE, red_size);
1867 GET_NONNEGATIVE_VALUE(EGL_GREEN_SIZE, green_size);
1868 GET_NONNEGATIVE_VALUE(EGL_BLUE_SIZE, blue_size);
1869 GET_NONNEGATIVE_VALUE(EGL_ALPHA_SIZE, alpha_size);
Craig Donner6ebc46a2016-10-21 15:23:44 -07001870 GET_NONNEGATIVE_VALUE(EGL_LAYER_COUNT_ANDROID, layer_count);
Craig Donner05249fc2016-01-15 19:33:55 -08001871 case EGL_NATIVE_BUFFER_USAGE_ANDROID:
1872 if (value & EGL_NATIVE_BUFFER_USAGE_PROTECTED_BIT_ANDROID) {
Craig Donnere96a3252017-02-02 12:13:34 -08001873 producerUsage |= GRALLOC1_PRODUCER_USAGE_PROTECTED;
Craig Donner05249fc2016-01-15 19:33:55 -08001874 }
Craig Donner8cfae6d2016-04-12 16:54:03 -07001875 if (value & EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_BIT_ANDROID) {
Craig Donnere96a3252017-02-02 12:13:34 -08001876 producerUsage |= GRALLOC1_PRODUCER_USAGE_GPU_RENDER_TARGET;
Craig Donner05249fc2016-01-15 19:33:55 -08001877 }
Craig Donner8cfae6d2016-04-12 16:54:03 -07001878 if (value & EGL_NATIVE_BUFFER_USAGE_TEXTURE_BIT_ANDROID) {
Craig Donnere96a3252017-02-02 12:13:34 -08001879 consumerUsage |= GRALLOC1_CONSUMER_USAGE_GPU_TEXTURE;
Craig Donner05249fc2016-01-15 19:33:55 -08001880 }
Craig Donner05249fc2016-01-15 19:33:55 -08001881 break;
1882 default:
1883 return setError(EGL_BAD_PARAMETER, (EGLClientBuffer)0);
1884 }
1885 }
1886 }
Craig Donnerb40504a2016-06-03 17:54:25 -07001887#undef GET_NONNEGATIVE_VALUE
Craig Donner05249fc2016-01-15 19:33:55 -08001888
1889 // Validate format.
1890 if (red_size == 8 && green_size == 8 && blue_size == 8) {
1891 if (alpha_size == 8) {
1892 format = HAL_PIXEL_FORMAT_RGBA_8888;
1893 } else {
1894 format = HAL_PIXEL_FORMAT_RGB_888;
1895 }
1896 } else if (red_size == 5 && green_size == 6 && blue_size == 5 &&
1897 alpha_size == 0) {
Craig Donner478f7db2016-06-10 17:20:15 -07001898 format = HAL_PIXEL_FORMAT_RGB_565;
Craig Donner05249fc2016-01-15 19:33:55 -08001899 } else {
Craig Donner6ebc46a2016-10-21 15:23:44 -07001900 ALOGE("Invalid native pixel format { r=%u, g=%u, b=%u, a=%u }",
Craig Donner05249fc2016-01-15 19:33:55 -08001901 red_size, green_size, blue_size, alpha_size);
1902 return setError(EGL_BAD_PARAMETER, (EGLClientBuffer)0);
1903 }
1904
Craig Donner68671532016-07-18 10:19:54 -07001905#define CHECK_ERROR_CONDITION(message) \
1906 if (err != NO_ERROR) { \
1907 ALOGE(message); \
1908 goto error_condition; \
1909 }
1910
1911 // The holder is used to destroy the buffer if an error occurs.
1912 GraphicBuffer* gBuffer = new GraphicBuffer();
1913 sp<IServiceManager> sm = defaultServiceManager();
1914 sp<IBinder> surfaceFlinger = sm->getService(String16("SurfaceFlinger"));
1915 sp<IBinder> allocator;
1916 Parcel sc_data, sc_reply, data, reply;
1917 status_t err = NO_ERROR;
1918 if (sm == NULL) {
1919 ALOGE("Unable to connect to ServiceManager");
1920 goto error_condition;
1921 }
1922
1923 // Obtain an allocator.
1924 if (surfaceFlinger == NULL) {
1925 ALOGE("Unable to connect to SurfaceFlinger");
1926 goto error_condition;
1927 }
1928 sc_data.writeInterfaceToken(String16("android.ui.ISurfaceComposer"));
1929 err = surfaceFlinger->transact(
1930 BnSurfaceComposer::CREATE_GRAPHIC_BUFFER_ALLOC, sc_data, &sc_reply);
1931 CHECK_ERROR_CONDITION("Unable to obtain allocator from SurfaceFlinger");
1932 allocator = sc_reply.readStrongBinder();
1933
1934 if (allocator == NULL) {
1935 ALOGE("Unable to obtain an ISurfaceComposer");
1936 goto error_condition;
1937 }
1938 data.writeInterfaceToken(String16("android.ui.IGraphicBufferAlloc"));
1939 err = data.writeUint32(width);
1940 CHECK_ERROR_CONDITION("Unable to write width");
1941 err = data.writeUint32(height);
1942 CHECK_ERROR_CONDITION("Unable to write height");
1943 err = data.writeInt32(static_cast<int32_t>(format));
1944 CHECK_ERROR_CONDITION("Unable to write format");
Craig Donner6ebc46a2016-10-21 15:23:44 -07001945 err = data.writeUint32(layer_count);
1946 CHECK_ERROR_CONDITION("Unable to write layer count");
Craig Donnere96a3252017-02-02 12:13:34 -08001947 err = data.writeUint64(producerUsage);
1948 CHECK_ERROR_CONDITION("Unable to write producer usage");
1949 err = data.writeUint64(consumerUsage);
1950 CHECK_ERROR_CONDITION("Unable to write consumer usage");
Dan Stoza024e9312016-08-24 12:17:29 -07001951 err = data.writeUtf8AsUtf16(
1952 std::string("[eglCreateNativeClientBufferANDROID pid ") +
1953 std::to_string(getpid()) + ']');
1954 CHECK_ERROR_CONDITION("Unable to write requestor name");
Craig Donner68671532016-07-18 10:19:54 -07001955 err = allocator->transact(IBinder::FIRST_CALL_TRANSACTION, data,
1956 &reply);
1957 CHECK_ERROR_CONDITION(
1958 "Unable to request buffer allocation from surface composer");
1959 err = reply.readInt32();
1960 CHECK_ERROR_CONDITION("Unable to obtain buffer from surface composer");
1961 err = reply.read(*gBuffer);
1962 CHECK_ERROR_CONDITION("Unable to read buffer from surface composer");
1963
1964 err = gBuffer->initCheck();
Craig Donner05249fc2016-01-15 19:33:55 -08001965 if (err != NO_ERROR) {
Craig Donner6ebc46a2016-10-21 15:23:44 -07001966 ALOGE("Unable to create native buffer "
Craig Donnere96a3252017-02-02 12:13:34 -08001967 "{ w=%u, h=%u, f=%u, pu=%" PRIx64 " cu=%" PRIx64 ", lc=%u} %#x",
1968 width, height, format, producerUsage, consumerUsage,
1969 layer_count, err);
Craig Donner68671532016-07-18 10:19:54 -07001970 goto error_condition;
Craig Donner05249fc2016-01-15 19:33:55 -08001971 }
Craig Donnere96a3252017-02-02 12:13:34 -08001972 ALOGV("Created new native buffer %p { w=%u, h=%u, f=%u, pu=%" PRIx64
1973 " cu=%" PRIx64 ", lc=%u}",
1974 gBuffer, width, height, format, producerUsage, consumerUsage,
1975 layer_count);
Craig Donner05249fc2016-01-15 19:33:55 -08001976 return static_cast<EGLClientBuffer>(gBuffer->getNativeBuffer());
Craig Donner68671532016-07-18 10:19:54 -07001977
1978#undef CHECK_ERROR_CONDITION
1979
1980error_condition:
1981 // Delete the buffer.
1982 sp<GraphicBuffer> holder(gBuffer);
1983 return setError(EGL_BAD_ALLOC, (EGLClientBuffer)0);
Craig Donner05249fc2016-01-15 19:33:55 -08001984}
1985
Craig Donner60761072017-01-27 12:30:44 -08001986EGLClientBuffer eglGetNativeClientBufferANDROID(const AHardwareBuffer *buffer) {
1987 clearError();
1988
1989 if (!buffer) return setError(EGL_BAD_PARAMETER, (EGLClientBuffer)0);
1990
Mathias Agopian89ed4c82017-02-09 18:48:34 -08001991 const GraphicBuffer* graphicBuffer = AHardwareBuffer_to_GraphicBuffer(buffer);
Craig Donner60761072017-01-27 12:30:44 -08001992 return static_cast<EGLClientBuffer>(graphicBuffer->getNativeBuffer());
1993}
1994
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001995// ----------------------------------------------------------------------------
1996// NVIDIA extensions
1997// ----------------------------------------------------------------------------
1998EGLuint64NV eglGetSystemTimeFrequencyNV()
1999{
2000 clearError();
2001
2002 if (egl_init_drivers() == EGL_FALSE) {
2003 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
2004 }
2005
2006 EGLuint64NV ret = 0;
Mathias Agopianada798b2012-02-13 17:09:30 -08002007 egl_connection_t* const cnx = &gEGLImpl;
Jonas Yang1c3d72a2011-08-26 20:04:39 +08002008
Mathias Agopianada798b2012-02-13 17:09:30 -08002009 if (cnx->dso && cnx->egl.eglGetSystemTimeFrequencyNV) {
2010 return cnx->egl.eglGetSystemTimeFrequencyNV();
Jonas Yang1c3d72a2011-08-26 20:04:39 +08002011 }
2012
Mathias Agopian0e8bbee2011-10-05 19:15:05 -07002013 return setErrorQuiet(EGL_BAD_DISPLAY, 0);
Jonas Yang1c3d72a2011-08-26 20:04:39 +08002014}
2015
2016EGLuint64NV eglGetSystemTimeNV()
2017{
2018 clearError();
2019
2020 if (egl_init_drivers() == EGL_FALSE) {
2021 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
2022 }
2023
2024 EGLuint64NV ret = 0;
Mathias Agopianada798b2012-02-13 17:09:30 -08002025 egl_connection_t* const cnx = &gEGLImpl;
Jonas Yang1c3d72a2011-08-26 20:04:39 +08002026
Mathias Agopianada798b2012-02-13 17:09:30 -08002027 if (cnx->dso && cnx->egl.eglGetSystemTimeNV) {
2028 return cnx->egl.eglGetSystemTimeNV();
Jonas Yang1c3d72a2011-08-26 20:04:39 +08002029 }
2030
Mathias Agopian0e8bbee2011-10-05 19:15:05 -07002031 return setErrorQuiet(EGL_BAD_DISPLAY, 0);
Jonas Yang1c3d72a2011-08-26 20:04:39 +08002032}
Dan Stozaa894d082015-02-19 15:27:36 -08002033
2034// ----------------------------------------------------------------------------
2035// Partial update extension
2036// ----------------------------------------------------------------------------
2037EGLBoolean eglSetDamageRegionKHR(EGLDisplay dpy, EGLSurface surface,
2038 EGLint *rects, EGLint n_rects)
2039{
2040 clearError();
2041
2042 const egl_display_ptr dp = validate_display(dpy);
2043 if (!dp) {
2044 setError(EGL_BAD_DISPLAY, EGL_FALSE);
2045 return EGL_FALSE;
2046 }
2047
2048 SurfaceRef _s(dp.get(), surface);
2049 if (!_s.get()) {
2050 setError(EGL_BAD_SURFACE, EGL_FALSE);
2051 return EGL_FALSE;
2052 }
2053
2054 egl_surface_t const * const s = get_surface(surface);
2055 if (s->cnx->egl.eglSetDamageRegionKHR) {
2056 return s->cnx->egl.eglSetDamageRegionKHR(dp->disp.dpy, s->surface,
2057 rects, n_rects);
2058 }
2059
2060 return EGL_FALSE;
2061}
Pablo Ceballosc18be292016-05-31 14:55:42 -07002062
Brian Anderson1049d1d2016-12-16 17:25:57 -08002063EGLBoolean eglGetNextFrameIdANDROID(EGLDisplay dpy, EGLSurface surface,
2064 EGLuint64KHR *frameId) {
2065 clearError();
2066
2067 const egl_display_ptr dp = validate_display(dpy);
2068 if (!dp) {
2069 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
2070 }
2071
2072 SurfaceRef _s(dp.get(), surface);
2073 if (!_s.get()) {
2074 return setError(EGL_BAD_SURFACE, EGL_FALSE);
2075 }
2076
2077 egl_surface_t const * const s = get_surface(surface);
2078
2079 if (!s->win.get()) {
2080 return setError(EGL_BAD_SURFACE, EGL_FALSE);
2081 }
2082
2083 uint64_t nextFrameId = 0;
2084 status_t ret = native_window_get_next_frame_id(s->win.get(), &nextFrameId);
2085
2086 if (ret != NO_ERROR) {
2087 // This should not happen. Return an error that is not in the spec
2088 // so it's obvious something is very wrong.
2089 ALOGE("eglGetNextFrameId: Unexpected error.");
2090 return setError(EGL_NOT_INITIALIZED, EGL_FALSE);
2091 }
2092
2093 *frameId = nextFrameId;
2094 return EGL_TRUE;
2095}
2096
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002097EGLBoolean eglGetCompositorTimingANDROID(EGLDisplay dpy, EGLSurface surface,
2098 EGLint numTimestamps, const EGLint *names, EGLnsecsANDROID *values)
2099{
2100 clearError();
2101
2102 const egl_display_ptr dp = validate_display(dpy);
2103 if (!dp) {
2104 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
2105 }
2106
2107 SurfaceRef _s(dp.get(), surface);
2108 if (!_s.get()) {
2109 return setError(EGL_BAD_SURFACE, EGL_FALSE);
2110 }
2111
2112 egl_surface_t const * const s = get_surface(surface);
2113
2114 if (!s->win.get()) {
2115 return setError(EGL_BAD_SURFACE, EGL_FALSE);
2116 }
2117
2118 nsecs_t* compositeDeadline = nullptr;
2119 nsecs_t* compositeInterval = nullptr;
2120 nsecs_t* compositeToPresentLatency = nullptr;
2121
2122 for (int i = 0; i < numTimestamps; i++) {
2123 switch (names[i]) {
2124 case EGL_COMPOSITE_DEADLINE_ANDROID:
2125 compositeDeadline = &values[i];
2126 break;
2127 case EGL_COMPOSITE_INTERVAL_ANDROID:
2128 compositeInterval = &values[i];
2129 break;
2130 case EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID:
2131 compositeToPresentLatency = &values[i];
2132 break;
2133 default:
2134 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
2135 }
2136 }
2137
2138 status_t ret = native_window_get_compositor_timing(s->win.get(),
2139 compositeDeadline, compositeInterval, compositeToPresentLatency);
2140
2141 switch (ret) {
2142 case NO_ERROR:
2143 return EGL_TRUE;
2144 case INVALID_OPERATION:
2145 return setError(EGL_BAD_SURFACE, EGL_FALSE);
2146 default:
2147 // This should not happen. Return an error that is not in the spec
2148 // so it's obvious something is very wrong.
2149 ALOGE("eglGetCompositorTiming: Unexpected error.");
2150 return setError(EGL_NOT_INITIALIZED, EGL_FALSE);
2151 }
2152}
2153
2154EGLBoolean eglGetCompositorTimingSupportedANDROID(
2155 EGLDisplay dpy, EGLSurface surface, EGLint name)
2156{
2157 clearError();
2158
2159 const egl_display_ptr dp = validate_display(dpy);
2160 if (!dp) {
2161 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
2162 }
2163
2164 SurfaceRef _s(dp.get(), surface);
2165 if (!_s.get()) {
2166 return setError(EGL_BAD_SURFACE, EGL_FALSE);
2167 }
2168
2169 egl_surface_t const * const s = get_surface(surface);
2170
2171 ANativeWindow* window = s->win.get();
2172 if (!window) {
2173 return setError(EGL_BAD_SURFACE, EGL_FALSE);
2174 }
2175
2176 switch (name) {
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002177 case EGL_COMPOSITE_DEADLINE_ANDROID:
2178 case EGL_COMPOSITE_INTERVAL_ANDROID:
2179 case EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID:
2180 return EGL_TRUE;
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002181 default:
2182 return EGL_FALSE;
2183 }
2184}
2185
Pablo Ceballosc18be292016-05-31 14:55:42 -07002186EGLBoolean eglGetFrameTimestampsANDROID(EGLDisplay dpy, EGLSurface surface,
Brian Anderson1049d1d2016-12-16 17:25:57 -08002187 EGLuint64KHR frameId, EGLint numTimestamps, const EGLint *timestamps,
Pablo Ceballosc18be292016-05-31 14:55:42 -07002188 EGLnsecsANDROID *values)
2189{
2190 clearError();
2191
2192 const egl_display_ptr dp = validate_display(dpy);
2193 if (!dp) {
Brian Anderson069b3652016-07-22 10:32:47 -07002194 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
Pablo Ceballosc18be292016-05-31 14:55:42 -07002195 }
2196
2197 SurfaceRef _s(dp.get(), surface);
2198 if (!_s.get()) {
Brian Anderson069b3652016-07-22 10:32:47 -07002199 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Pablo Ceballosc18be292016-05-31 14:55:42 -07002200 }
2201
2202 egl_surface_t const * const s = get_surface(surface);
2203
Brian Anderson7c3ba8a2016-07-25 12:48:08 -07002204 if (!s->win.get()) {
Brian Anderson069b3652016-07-22 10:32:47 -07002205 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Pablo Ceballosc18be292016-05-31 14:55:42 -07002206 }
2207
Brian Andersondbd0ea82016-07-22 09:38:59 -07002208 nsecs_t* requestedPresentTime = nullptr;
Pablo Ceballosc18be292016-05-31 14:55:42 -07002209 nsecs_t* acquireTime = nullptr;
Brian Andersonf7fd56a2016-09-02 10:10:04 -07002210 nsecs_t* latchTime = nullptr;
2211 nsecs_t* firstRefreshStartTime = nullptr;
Brian Andersonb04c6f02016-10-21 12:57:46 -07002212 nsecs_t* gpuCompositionDoneTime = nullptr;
Brian Andersonf7fd56a2016-09-02 10:10:04 -07002213 nsecs_t* lastRefreshStartTime = nullptr;
Brian Anderson069b3652016-07-22 10:32:47 -07002214 nsecs_t* displayPresentTime = nullptr;
Pablo Ceballosc18be292016-05-31 14:55:42 -07002215 nsecs_t* displayRetireTime = nullptr;
Brian Andersonf7fd56a2016-09-02 10:10:04 -07002216 nsecs_t* dequeueReadyTime = nullptr;
Pablo Ceballosc18be292016-05-31 14:55:42 -07002217 nsecs_t* releaseTime = nullptr;
2218
2219 for (int i = 0; i < numTimestamps; i++) {
2220 switch (timestamps[i]) {
Brian Andersondbd0ea82016-07-22 09:38:59 -07002221 case EGL_REQUESTED_PRESENT_TIME_ANDROID:
2222 requestedPresentTime = &values[i];
Pablo Ceballosc18be292016-05-31 14:55:42 -07002223 break;
2224 case EGL_RENDERING_COMPLETE_TIME_ANDROID:
2225 acquireTime = &values[i];
2226 break;
Brian Andersonf7fd56a2016-09-02 10:10:04 -07002227 case EGL_COMPOSITION_LATCH_TIME_ANDROID:
2228 latchTime = &values[i];
Pablo Ceballosc18be292016-05-31 14:55:42 -07002229 break;
Brian Andersonf7fd56a2016-09-02 10:10:04 -07002230 case EGL_FIRST_COMPOSITION_START_TIME_ANDROID:
2231 firstRefreshStartTime = &values[i];
2232 break;
2233 case EGL_LAST_COMPOSITION_START_TIME_ANDROID:
2234 lastRefreshStartTime = &values[i];
2235 break;
Brian Andersonb04c6f02016-10-21 12:57:46 -07002236 case EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID:
2237 gpuCompositionDoneTime = &values[i];
Pablo Ceballosc18be292016-05-31 14:55:42 -07002238 break;
Brian Anderson069b3652016-07-22 10:32:47 -07002239 case EGL_DISPLAY_PRESENT_TIME_ANDROID:
2240 displayPresentTime = &values[i];
2241 break;
Pablo Ceballosc18be292016-05-31 14:55:42 -07002242 case EGL_DISPLAY_RETIRE_TIME_ANDROID:
2243 displayRetireTime = &values[i];
2244 break;
Brian Andersonf7fd56a2016-09-02 10:10:04 -07002245 case EGL_DEQUEUE_READY_TIME_ANDROID:
2246 dequeueReadyTime = &values[i];
2247 break;
Pablo Ceballosc18be292016-05-31 14:55:42 -07002248 case EGL_READS_DONE_TIME_ANDROID:
2249 releaseTime = &values[i];
2250 break;
2251 default:
Brian Anderson069b3652016-07-22 10:32:47 -07002252 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
Pablo Ceballosc18be292016-05-31 14:55:42 -07002253 }
2254 }
2255
Brian Anderson1049d1d2016-12-16 17:25:57 -08002256 status_t ret = native_window_get_frame_timestamps(s->win.get(), frameId,
Brian Andersonf7fd56a2016-09-02 10:10:04 -07002257 requestedPresentTime, acquireTime, latchTime, firstRefreshStartTime,
Brian Andersonb04c6f02016-10-21 12:57:46 -07002258 lastRefreshStartTime, gpuCompositionDoneTime, displayPresentTime,
Brian Andersonf7fd56a2016-09-02 10:10:04 -07002259 displayRetireTime, dequeueReadyTime, releaseTime);
Pablo Ceballosc18be292016-05-31 14:55:42 -07002260
Brian Anderson069b3652016-07-22 10:32:47 -07002261 switch (ret) {
2262 case NO_ERROR:
2263 return EGL_TRUE;
2264 case NAME_NOT_FOUND:
2265 return setError(EGL_BAD_ACCESS, EGL_FALSE);
Brian Anderson7c3ba8a2016-07-25 12:48:08 -07002266 case INVALID_OPERATION:
2267 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Brian Anderson069b3652016-07-22 10:32:47 -07002268 case BAD_VALUE:
2269 return setError(EGL_BAD_PARAMETER, EGL_FALSE);
2270 default:
2271 // This should not happen. Return an error that is not in the spec
2272 // so it's obvious something is very wrong.
Brian Anderson1049d1d2016-12-16 17:25:57 -08002273 ALOGE("eglGetFrameTimestamps: Unexpected error.");
Brian Anderson069b3652016-07-22 10:32:47 -07002274 return setError(EGL_NOT_INITIALIZED, EGL_FALSE);
Pablo Ceballosc18be292016-05-31 14:55:42 -07002275 }
Pablo Ceballosc18be292016-05-31 14:55:42 -07002276}
2277
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002278EGLBoolean eglGetFrameTimestampSupportedANDROID(
2279 EGLDisplay dpy, EGLSurface surface, EGLint timestamp)
Pablo Ceballosc18be292016-05-31 14:55:42 -07002280{
2281 clearError();
2282
2283 const egl_display_ptr dp = validate_display(dpy);
2284 if (!dp) {
Brian Anderson069b3652016-07-22 10:32:47 -07002285 return setError(EGL_BAD_DISPLAY, EGL_FALSE);
Pablo Ceballosc18be292016-05-31 14:55:42 -07002286 }
2287
2288 SurfaceRef _s(dp.get(), surface);
2289 if (!_s.get()) {
Brian Anderson069b3652016-07-22 10:32:47 -07002290 return setError(EGL_BAD_SURFACE, EGL_FALSE);
2291 }
2292
2293 egl_surface_t const * const s = get_surface(surface);
2294
2295 ANativeWindow* window = s->win.get();
2296 if (!window) {
2297 return setError(EGL_BAD_SURFACE, EGL_FALSE);
Pablo Ceballosc18be292016-05-31 14:55:42 -07002298 }
2299
2300 switch (timestamp) {
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002301 case EGL_COMPOSITE_DEADLINE_ANDROID:
2302 case EGL_COMPOSITE_INTERVAL_ANDROID:
2303 case EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID:
Brian Andersondbd0ea82016-07-22 09:38:59 -07002304 case EGL_REQUESTED_PRESENT_TIME_ANDROID:
Pablo Ceballosc18be292016-05-31 14:55:42 -07002305 case EGL_RENDERING_COMPLETE_TIME_ANDROID:
Brian Andersonf7fd56a2016-09-02 10:10:04 -07002306 case EGL_COMPOSITION_LATCH_TIME_ANDROID:
2307 case EGL_FIRST_COMPOSITION_START_TIME_ANDROID:
2308 case EGL_LAST_COMPOSITION_START_TIME_ANDROID:
Brian Andersonb04c6f02016-10-21 12:57:46 -07002309 case EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID:
Brian Andersonf7fd56a2016-09-02 10:10:04 -07002310 case EGL_DEQUEUE_READY_TIME_ANDROID:
Pablo Ceballosc18be292016-05-31 14:55:42 -07002311 case EGL_READS_DONE_TIME_ANDROID:
2312 return EGL_TRUE;
Brian Anderson069b3652016-07-22 10:32:47 -07002313 case EGL_DISPLAY_PRESENT_TIME_ANDROID: {
2314 int value = 0;
2315 window->query(window,
2316 NATIVE_WINDOW_FRAME_TIMESTAMPS_SUPPORTS_PRESENT, &value);
2317 return value == 0 ? EGL_FALSE : EGL_TRUE;
2318 }
2319 case EGL_DISPLAY_RETIRE_TIME_ANDROID: {
2320 int value = 0;
2321 window->query(window,
2322 NATIVE_WINDOW_FRAME_TIMESTAMPS_SUPPORTS_RETIRE, &value);
2323 return value == 0 ? EGL_FALSE : EGL_TRUE;
2324 }
Pablo Ceballosc18be292016-05-31 14:55:42 -07002325 default:
2326 return EGL_FALSE;
2327 }
2328}