blob: 9cc96c771ac7afc8463f41ee32077a54851833ca [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
26#include <EGL/egl.h>
27#include <EGL/eglext.h>
Mathias Agopian518ec112011-05-13 16:21:08 -070028
Craig Donner60761072017-01-27 12:30:44 -080029#include <android/hardware_buffer.h>
Mathias Agopian89ed4c82017-02-09 18:48:34 -080030#include <private/android/AHardwareBufferHelpers.h>
31
Mathias Agopian7db993a2012-03-25 00:49:46 -070032#include <cutils/compiler.h>
Mark Salyzyna5e161b2016-09-29 08:08:05 -070033#include <cutils/properties.h>
Mark Salyzyn7823e122016-09-29 08:08:05 -070034#include <log/log.h>
Mathias Agopian518ec112011-05-13 16:21:08 -070035
36#include <utils/KeyedVector.h>
Mathias Agopian518ec112011-05-13 16:21:08 -070037#include <utils/String8.h>
Jamie Gennis1c8e95c2012-02-23 19:27:23 -080038#include <utils/Trace.h>
Mathias Agopian311b4792017-02-28 15:00:49 -080039#include <utils/Thread.h>
Mathias Agopian518ec112011-05-13 16:21:08 -070040
Mathias Agopian39c24a22013-04-04 23:17:56 -070041#include "../egl_impl.h"
Mathias Agopian518ec112011-05-13 16:21:08 -070042
43#include "egl_display.h"
Mathias Agopian518ec112011-05-13 16:21:08 -070044#include "egl_object.h"
45#include "egl_tls.h"
46
47using namespace android;
48
49// ----------------------------------------------------------------------------
50
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070051namespace android {
52
Mathias Agopian518ec112011-05-13 16:21:08 -070053struct extention_map_t {
54 const char* name;
55 __eglMustCastToProperFunctionPointerType address;
56};
57
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070058/*
Jesse Hall21558da2013-08-06 15:31:22 -070059 * This is the list of EGL extensions exposed to applications.
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070060 *
Jesse Hall21558da2013-08-06 15:31:22 -070061 * Some of them (gBuiltinExtensionString) are implemented entirely in this EGL
62 * wrapper and are always available.
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070063 *
Jesse Hall21558da2013-08-06 15:31:22 -070064 * The rest (gExtensionString) depend on support in the EGL driver, and are
65 * only available if the driver supports them. However, some of these must be
66 * supported because they are used by the Android system itself; these are
Pablo Ceballos02b05da2016-02-02 17:53:18 -080067 * listed as mandatory below and are required by the CDD. The system *assumes*
Jesse Hall21558da2013-08-06 15:31:22 -070068 * the mandatory extensions are present and may not function properly if some
69 * are missing.
70 *
71 * NOTE: Both strings MUST have a single space as the last character.
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070072 */
Mathias Agopian737b8962017-02-24 14:32:05 -080073
Mathias Agopian311b4792017-02-28 15:00:49 -080074extern char const * const gBuiltinExtensionString;
75extern char const * const gExtensionString;
Mathias Agopian737b8962017-02-24 14:32:05 -080076
Mathias Agopian311b4792017-02-28 15:00:49 -080077char const * const gBuiltinExtensionString =
Jesse Hall21558da2013-08-06 15:31:22 -070078 "EGL_KHR_get_all_proc_addresses "
79 "EGL_ANDROID_presentation_time "
Dan Stozaa894d082015-02-19 15:27:36 -080080 "EGL_KHR_swap_buffers_with_damage "
Craig Donner60761072017-01-27 12:30:44 -080081 "EGL_ANDROID_get_native_client_buffer "
Pablo Ceballos02b05da2016-02-02 17:53:18 -080082 "EGL_ANDROID_front_buffer_auto_refresh "
Pablo Ceballosc18be292016-05-31 14:55:42 -070083 "EGL_ANDROID_get_frame_timestamps "
Jesse Hall21558da2013-08-06 15:31:22 -070084 ;
Mathias Agopian311b4792017-02-28 15:00:49 -080085
86char const * const gExtensionString =
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070087 "EGL_KHR_image " // mandatory
88 "EGL_KHR_image_base " // mandatory
89 "EGL_KHR_image_pixmap "
90 "EGL_KHR_lock_surface "
Jesse Hallc2e41222013-08-08 13:40:22 -070091 "EGL_KHR_gl_colorspace "
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070092 "EGL_KHR_gl_texture_2D_image "
Season Li000d88f2015-07-01 11:39:40 -070093 "EGL_KHR_gl_texture_3D_image "
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070094 "EGL_KHR_gl_texture_cubemap_image "
95 "EGL_KHR_gl_renderbuffer_image "
96 "EGL_KHR_reusable_sync "
97 "EGL_KHR_fence_sync "
Jamie Gennisf6d1c392013-04-25 18:48:41 -070098 "EGL_KHR_create_context "
Season Li000d88f2015-07-01 11:39:40 -070099 "EGL_KHR_config_attribs "
100 "EGL_KHR_surfaceless_context "
101 "EGL_KHR_stream "
102 "EGL_KHR_stream_fifo "
103 "EGL_KHR_stream_producer_eglsurface "
104 "EGL_KHR_stream_consumer_gltexture "
105 "EGL_KHR_stream_cross_process_fd "
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700106 "EGL_EXT_create_context_robustness "
107 "EGL_NV_system_time "
108 "EGL_ANDROID_image_native_buffer " // mandatory
Mathias Agopian2bb71682013-03-27 17:32:41 -0700109 "EGL_KHR_wait_sync " // strongly recommended
Jamie Gennisdbe92452013-09-23 17:22:10 -0700110 "EGL_ANDROID_recordable " // mandatory
Dan Stozaa894d082015-02-19 15:27:36 -0800111 "EGL_KHR_partial_update " // strongly recommended
Courtney Goeltzenleuchter0e4e3952016-11-16 13:53:40 -0700112 "EGL_EXT_pixel_format_float "
Dan Stozaa894d082015-02-19 15:27:36 -0800113 "EGL_EXT_buffer_age " // strongly recommended with partial_update
Jesse Hall408e59f2015-04-24 01:40:42 -0700114 "EGL_KHR_create_context_no_error "
Pablo Ceballosceb9ee72016-04-13 11:17:32 -0700115 "EGL_KHR_mutable_render_buffer "
Mika Isojärvif37864b2016-04-15 11:58:56 -0700116 "EGL_EXT_yuv_surface "
Craig Donneraec86972016-04-28 18:09:40 -0700117 "EGL_EXT_protected_content "
Christian Poetzscha7805f62016-12-01 16:34:39 +0000118 "EGL_IMG_context_priority "
Pyry Haulos51d53c42017-03-06 09:39:09 -0800119 "EGL_KHR_no_config_context "
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700120 ;
121
122// extensions not exposed to applications but used by the ANDROID system
123// "EGL_ANDROID_blob_cache " // strongly recommended
124// "EGL_IMG_hibernate_process " // optional
125// "EGL_ANDROID_native_fence_sync " // strongly recommended
126// "EGL_ANDROID_framebuffer_target " // mandatory for HWC 1.1
Jamie Gennisdbe92452013-09-23 17:22:10 -0700127// "EGL_ANDROID_image_crop " // optional
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700128
129/*
130 * EGL Extensions entry-points exposed to 3rd party applications
131 * (keep in sync with gExtensionString above)
132 *
133 */
134static const extention_map_t sExtensionMap[] = {
135 // EGL_KHR_lock_surface
Mathias Agopian518ec112011-05-13 16:21:08 -0700136 { "eglLockSurfaceKHR",
137 (__eglMustCastToProperFunctionPointerType)&eglLockSurfaceKHR },
138 { "eglUnlockSurfaceKHR",
139 (__eglMustCastToProperFunctionPointerType)&eglUnlockSurfaceKHR },
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700140
141 // EGL_KHR_image, EGL_KHR_image_base
Mathias Agopian518ec112011-05-13 16:21:08 -0700142 { "eglCreateImageKHR",
143 (__eglMustCastToProperFunctionPointerType)&eglCreateImageKHR },
144 { "eglDestroyImageKHR",
145 (__eglMustCastToProperFunctionPointerType)&eglDestroyImageKHR },
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700146
147 // EGL_KHR_reusable_sync, EGL_KHR_fence_sync
148 { "eglCreateSyncKHR",
149 (__eglMustCastToProperFunctionPointerType)&eglCreateSyncKHR },
150 { "eglDestroySyncKHR",
151 (__eglMustCastToProperFunctionPointerType)&eglDestroySyncKHR },
152 { "eglClientWaitSyncKHR",
153 (__eglMustCastToProperFunctionPointerType)&eglClientWaitSyncKHR },
154 { "eglSignalSyncKHR",
155 (__eglMustCastToProperFunctionPointerType)&eglSignalSyncKHR },
156 { "eglGetSyncAttribKHR",
157 (__eglMustCastToProperFunctionPointerType)&eglGetSyncAttribKHR },
158
159 // EGL_NV_system_time
Jonas Yang1c3d72a2011-08-26 20:04:39 +0800160 { "eglGetSystemTimeFrequencyNV",
161 (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeFrequencyNV },
162 { "eglGetSystemTimeNV",
163 (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeNV },
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700164
Mathias Agopian2bb71682013-03-27 17:32:41 -0700165 // EGL_KHR_wait_sync
166 { "eglWaitSyncKHR",
167 (__eglMustCastToProperFunctionPointerType)&eglWaitSyncKHR },
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700168
169 // EGL_ANDROID_presentation_time
170 { "eglPresentationTimeANDROID",
171 (__eglMustCastToProperFunctionPointerType)&eglPresentationTimeANDROID },
Dan Stozaa894d082015-02-19 15:27:36 -0800172
173 // EGL_KHR_swap_buffers_with_damage
174 { "eglSwapBuffersWithDamageKHR",
175 (__eglMustCastToProperFunctionPointerType)&eglSwapBuffersWithDamageKHR },
176
Craig Donner60761072017-01-27 12:30:44 -0800177 // EGL_ANDROID_get_native_client_buffer
178 { "eglGetNativeClientBufferANDROID",
179 (__eglMustCastToProperFunctionPointerType)&eglGetNativeClientBufferANDROID },
180
Dan Stozaa894d082015-02-19 15:27:36 -0800181 // EGL_KHR_partial_update
182 { "eglSetDamageRegionKHR",
183 (__eglMustCastToProperFunctionPointerType)&eglSetDamageRegionKHR },
Season Li000d88f2015-07-01 11:39:40 -0700184
185 { "eglCreateStreamKHR",
186 (__eglMustCastToProperFunctionPointerType)&eglCreateStreamKHR },
187 { "eglDestroyStreamKHR",
188 (__eglMustCastToProperFunctionPointerType)&eglDestroyStreamKHR },
189 { "eglStreamAttribKHR",
190 (__eglMustCastToProperFunctionPointerType)&eglStreamAttribKHR },
191 { "eglQueryStreamKHR",
192 (__eglMustCastToProperFunctionPointerType)&eglQueryStreamKHR },
193 { "eglQueryStreamu64KHR",
194 (__eglMustCastToProperFunctionPointerType)&eglQueryStreamu64KHR },
195 { "eglQueryStreamTimeKHR",
196 (__eglMustCastToProperFunctionPointerType)&eglQueryStreamTimeKHR },
197 { "eglCreateStreamProducerSurfaceKHR",
198 (__eglMustCastToProperFunctionPointerType)&eglCreateStreamProducerSurfaceKHR },
199 { "eglStreamConsumerGLTextureExternalKHR",
200 (__eglMustCastToProperFunctionPointerType)&eglStreamConsumerGLTextureExternalKHR },
201 { "eglStreamConsumerAcquireKHR",
202 (__eglMustCastToProperFunctionPointerType)&eglStreamConsumerAcquireKHR },
203 { "eglStreamConsumerReleaseKHR",
204 (__eglMustCastToProperFunctionPointerType)&eglStreamConsumerReleaseKHR },
205 { "eglGetStreamFileDescriptorKHR",
206 (__eglMustCastToProperFunctionPointerType)&eglGetStreamFileDescriptorKHR },
207 { "eglCreateStreamFromFileDescriptorKHR",
208 (__eglMustCastToProperFunctionPointerType)&eglCreateStreamFromFileDescriptorKHR },
Pablo Ceballosc18be292016-05-31 14:55:42 -0700209
210 // EGL_ANDROID_get_frame_timestamps
Brian Anderson1049d1d2016-12-16 17:25:57 -0800211 { "eglGetNextFrameIdANDROID",
212 (__eglMustCastToProperFunctionPointerType)&eglGetNextFrameIdANDROID },
Brian Anderson0a61b0c2016-12-07 14:55:56 -0800213 { "eglGetCompositorTimingANDROID",
214 (__eglMustCastToProperFunctionPointerType)&eglGetCompositorTimingANDROID },
215 { "eglGetCompositorTimingSupportedANDROID",
216 (__eglMustCastToProperFunctionPointerType)&eglGetCompositorTimingSupportedANDROID },
Pablo Ceballosc18be292016-05-31 14:55:42 -0700217 { "eglGetFrameTimestampsANDROID",
218 (__eglMustCastToProperFunctionPointerType)&eglGetFrameTimestampsANDROID },
Brian Anderson0a61b0c2016-12-07 14:55:56 -0800219 { "eglGetFrameTimestampSupportedANDROID",
220 (__eglMustCastToProperFunctionPointerType)&eglGetFrameTimestampSupportedANDROID },
Mathias Agopian518ec112011-05-13 16:21:08 -0700221};
222
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700223/*
224 * These extensions entry-points should not be exposed to applications.
225 * They're used internally by the Android EGL layer.
226 */
227#define FILTER_EXTENSIONS(procname) \
228 (!strcmp((procname), "eglSetBlobCacheFuncsANDROID") || \
229 !strcmp((procname), "eglHibernateProcessIMG") || \
230 !strcmp((procname), "eglAwakenProcessIMG") || \
231 !strcmp((procname), "eglDupNativeFenceFDANDROID"))
232
233
234
Mathias Agopian518ec112011-05-13 16:21:08 -0700235// accesses protected by sExtensionMapMutex
236static DefaultKeyedVector<String8, __eglMustCastToProperFunctionPointerType> sGLExtentionMap;
237static int sGLExtentionSlot = 0;
238static pthread_mutex_t sExtensionMapMutex = PTHREAD_MUTEX_INITIALIZER;
239
240static void(*findProcAddress(const char* name,
241 const extention_map_t* map, size_t n))() {
242 for (uint32_t i=0 ; i<n ; i++) {
243 if (!strcmp(name, map[i].name)) {
244 return map[i].address;
245 }
246 }
247 return NULL;
248}
249
250// ----------------------------------------------------------------------------
251
Mathias Agopian518ec112011-05-13 16:21:08 -0700252extern void setGLHooksThreadSpecific(gl_hooks_t const *value);
253extern EGLBoolean egl_init_drivers();
254extern const __eglMustCastToProperFunctionPointerType gExtensionForwarders[MAX_NUMBER_OF_GL_EXTENSIONS];
Mathias Agopian518ec112011-05-13 16:21:08 -0700255extern gl_hooks_t gHooksTrace;
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700256
Mathias Agopian518ec112011-05-13 16:21:08 -0700257} // namespace android;
258
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700259
Mathias Agopian518ec112011-05-13 16:21:08 -0700260// ----------------------------------------------------------------------------
261
262static inline void clearError() { egl_tls_t::clearError(); }
263static inline EGLContext getContext() { return egl_tls_t::getContext(); }
264
265// ----------------------------------------------------------------------------
266
267EGLDisplay eglGetDisplay(EGLNativeDisplayType display)
268{
Jesse Hall1508ae62017-01-19 17:43:26 -0800269 ATRACE_CALL();
Mathias Agopian518ec112011-05-13 16:21:08 -0700270 clearError();
271
Dan Stozac3289c42014-01-17 11:38:34 -0800272 uintptr_t index = reinterpret_cast<uintptr_t>(display);
Mathias Agopian518ec112011-05-13 16:21:08 -0700273 if (index >= NUM_DISPLAYS) {
274 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
275 }
276
277 if (egl_init_drivers() == EGL_FALSE) {
278 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
279 }
280
281 EGLDisplay dpy = egl_display_t::getFromNativeDisplay(display);
282 return dpy;
283}
284
285// ----------------------------------------------------------------------------
286// Initialization
287// ----------------------------------------------------------------------------
288
289EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
290{
291 clearError();
292
Jesse Hallb29e5e82012-04-04 16:53:42 -0700293 egl_display_ptr dp = get_display(dpy);
Mathias Agopian737b8962017-02-24 14:32:05 -0800294 if (!dp) return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700295
296 EGLBoolean res = dp->initialize(major, minor);
297
298 return res;
299}
300
301EGLBoolean eglTerminate(EGLDisplay dpy)
302{
303 // NOTE: don't unload the drivers b/c some APIs can be called
304 // after eglTerminate() has been called. eglTerminate() only
305 // terminates an EGLDisplay, not a EGL itself.
306
307 clearError();
308
Jesse Hallb29e5e82012-04-04 16:53:42 -0700309 egl_display_ptr dp = get_display(dpy);
Mathias Agopian737b8962017-02-24 14:32:05 -0800310 if (!dp) return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700311
312 EGLBoolean res = dp->terminate();
Jesse Hall47743382013-02-08 11:13:46 -0800313
Mathias Agopian518ec112011-05-13 16:21:08 -0700314 return res;
315}
316
317// ----------------------------------------------------------------------------
318// configuration
319// ----------------------------------------------------------------------------
320
321EGLBoolean eglGetConfigs( EGLDisplay dpy,
322 EGLConfig *configs,
323 EGLint config_size, EGLint *num_config)
324{
325 clearError();
326
Jesse Hallb29e5e82012-04-04 16:53:42 -0700327 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700328 if (!dp) return EGL_FALSE;
329
Mathias Agopian7773c432012-02-13 20:06:08 -0800330 if (num_config==0) {
Mathias Agopian737b8962017-02-24 14:32:05 -0800331 return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700332 }
333
Mathias Agopian7773c432012-02-13 20:06:08 -0800334 EGLBoolean res = EGL_FALSE;
335 *num_config = 0;
336
337 egl_connection_t* const cnx = &gEGLImpl;
338 if (cnx->dso) {
339 res = cnx->egl.eglGetConfigs(
340 dp->disp.dpy, configs, config_size, num_config);
Mathias Agopian518ec112011-05-13 16:21:08 -0700341 }
Mathias Agopian7773c432012-02-13 20:06:08 -0800342
343 return res;
Mathias Agopian518ec112011-05-13 16:21:08 -0700344}
345
346EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list,
347 EGLConfig *configs, EGLint config_size,
348 EGLint *num_config)
349{
350 clearError();
351
Jesse Hallb29e5e82012-04-04 16:53:42 -0700352 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700353 if (!dp) return EGL_FALSE;
354
355 if (num_config==0) {
Mathias Agopian737b8962017-02-24 14:32:05 -0800356 return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700357 }
358
Mathias Agopian518ec112011-05-13 16:21:08 -0700359 EGLBoolean res = EGL_FALSE;
360 *num_config = 0;
361
Mathias Agopianada798b2012-02-13 17:09:30 -0800362 egl_connection_t* const cnx = &gEGLImpl;
363 if (cnx->dso) {
Romain Guy1cffc802012-10-15 18:13:05 -0700364 if (attrib_list) {
365 char value[PROPERTY_VALUE_MAX];
366 property_get("debug.egl.force_msaa", value, "false");
367
368 if (!strcmp(value, "true")) {
369 size_t attribCount = 0;
370 EGLint attrib = attrib_list[0];
371
372 // Only enable MSAA if the context is OpenGL ES 2.0 and
Romain Guybe3c3e42012-10-15 19:25:18 -0700373 // if no caveat is requested
Romain Guy1cffc802012-10-15 18:13:05 -0700374 const EGLint *attribRendererable = NULL;
375 const EGLint *attribCaveat = NULL;
376
377 // Count the number of attributes and look for
Romain Guybe3c3e42012-10-15 19:25:18 -0700378 // EGL_RENDERABLE_TYPE and EGL_CONFIG_CAVEAT
Romain Guy1cffc802012-10-15 18:13:05 -0700379 while (attrib != EGL_NONE) {
380 attrib = attrib_list[attribCount];
381 switch (attrib) {
382 case EGL_RENDERABLE_TYPE:
383 attribRendererable = &attrib_list[attribCount];
384 break;
385 case EGL_CONFIG_CAVEAT:
386 attribCaveat = &attrib_list[attribCount];
387 break;
Mathias Agopian737b8962017-02-24 14:32:05 -0800388 default:
389 break;
Romain Guy1cffc802012-10-15 18:13:05 -0700390 }
391 attribCount++;
392 }
393
394 if (attribRendererable && attribRendererable[1] == EGL_OPENGL_ES2_BIT &&
395 (!attribCaveat || attribCaveat[1] != EGL_NONE)) {
Jesse Hall47743382013-02-08 11:13:46 -0800396
Romain Guy1cffc802012-10-15 18:13:05 -0700397 // Insert 2 extra attributes to force-enable MSAA 4x
398 EGLint aaAttribs[attribCount + 4];
399 aaAttribs[0] = EGL_SAMPLE_BUFFERS;
400 aaAttribs[1] = 1;
401 aaAttribs[2] = EGL_SAMPLES;
402 aaAttribs[3] = 4;
403
404 memcpy(&aaAttribs[4], attrib_list, attribCount * sizeof(EGLint));
405
406 EGLint numConfigAA;
407 EGLBoolean resAA = cnx->egl.eglChooseConfig(
408 dp->disp.dpy, aaAttribs, configs, config_size, &numConfigAA);
409
410 if (resAA == EGL_TRUE && numConfigAA > 0) {
411 ALOGD("Enabling MSAA 4x");
412 *num_config = numConfigAA;
413 return resAA;
414 }
415 }
416 }
417 }
418
Mathias Agopian7773c432012-02-13 20:06:08 -0800419 res = cnx->egl.eglChooseConfig(
420 dp->disp.dpy, attrib_list, configs, config_size, num_config);
Mathias Agopian518ec112011-05-13 16:21:08 -0700421 }
422 return res;
423}
424
425EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
426 EGLint attribute, EGLint *value)
427{
428 clearError();
429
Jesse Hallb29e5e82012-04-04 16:53:42 -0700430 egl_connection_t* cnx = NULL;
431 const egl_display_ptr dp = validate_display_connection(dpy, cnx);
432 if (!dp) return EGL_FALSE;
Jesse Hall47743382013-02-08 11:13:46 -0800433
Mathias Agopian518ec112011-05-13 16:21:08 -0700434 return cnx->egl.eglGetConfigAttrib(
Mathias Agopian7773c432012-02-13 20:06:08 -0800435 dp->disp.dpy, config, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -0700436}
437
438// ----------------------------------------------------------------------------
439// surfaces
440// ----------------------------------------------------------------------------
441
Jesse Hallc2e41222013-08-08 13:40:22 -0700442// Turn linear formats into corresponding sRGB formats when colorspace is
443// EGL_GL_COLORSPACE_SRGB_KHR, or turn sRGB formats into corresponding linear
444// formats when colorspace is EGL_GL_COLORSPACE_LINEAR_KHR. In any cases where
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800445// the modification isn't possible, the original dataSpace is returned.
446static android_dataspace modifyBufferDataspace( android_dataspace dataSpace,
447 EGLint colorspace) {
Jesse Hallc2e41222013-08-08 13:40:22 -0700448 if (colorspace == EGL_GL_COLORSPACE_LINEAR_KHR) {
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800449 return HAL_DATASPACE_SRGB_LINEAR;
Jesse Hallc2e41222013-08-08 13:40:22 -0700450 } else if (colorspace == EGL_GL_COLORSPACE_SRGB_KHR) {
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800451 return HAL_DATASPACE_SRGB;
Jesse Hallc2e41222013-08-08 13:40:22 -0700452 }
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800453 return dataSpace;
Jesse Hallc2e41222013-08-08 13:40:22 -0700454}
455
Mathias Agopian518ec112011-05-13 16:21:08 -0700456EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config,
457 NativeWindowType window,
458 const EGLint *attrib_list)
459{
460 clearError();
461
Jesse Hallb29e5e82012-04-04 16:53:42 -0700462 egl_connection_t* cnx = NULL;
463 egl_display_ptr dp = validate_display_connection(dpy, cnx);
464 if (dp) {
Mathias Agopianada798b2012-02-13 17:09:30 -0800465 EGLDisplay iDpy = dp->disp.dpy;
Mathias Agopian518ec112011-05-13 16:21:08 -0700466
Mathias Agopian10e9ab52017-03-08 15:02:55 -0800467 if (!window) {
468 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
469 }
470
471 int value = 0;
472 window->query(window, NATIVE_WINDOW_IS_VALID, &value);
473 if (!value) {
474 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
475 }
476
Andy McFaddend566ce32014-01-07 15:54:17 -0800477 int result = native_window_api_connect(window, NATIVE_WINDOW_API_EGL);
478 if (result != OK) {
479 ALOGE("eglCreateWindowSurface: native_window_api_connect (win=%p) "
480 "failed (%#x) (already connected to another API?)",
481 window, result);
Jonathan Hamilton77a9b4a2013-07-17 09:41:42 -0700482 return setError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
Mathias Agopian81a63352011-07-29 17:55:48 -0700483 }
484
Mathias Agopian0f288fc2013-08-21 16:36:34 -0700485 // Set the native window's buffers format to match what this config requests.
Jesse Hallc2e41222013-08-08 13:40:22 -0700486 // Whether to use sRGB gamma is not part of the EGLconfig, but is part
487 // of our native format. So if sRGB gamma is requested, we have to
488 // modify the EGLconfig's format before setting the native window's
489 // format.
Alistair Strachan733a8072015-02-12 12:33:25 -0800490
Courtney Goeltzenleuchter0e4e3952016-11-16 13:53:40 -0700491 EGLint componentType = EGL_COLOR_COMPONENT_TYPE_FIXED_EXT;
492 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_COLOR_COMPONENT_TYPE_EXT,
493 &componentType);
494
Mathias Agopian95921562017-02-24 14:31:31 -0800495 EGLint format;
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800496 android_dataspace dataSpace = HAL_DATASPACE_UNKNOWN;
Mathias Agopian0f288fc2013-08-21 16:36:34 -0700497 EGLint a = 0;
Courtney Goeltzenleuchter0e4e3952016-11-16 13:53:40 -0700498 EGLint r, g, b;
499 r = g = b = 0;
500 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_RED_SIZE, &r);
501 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_GREEN_SIZE, &g);
502 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_BLUE_SIZE, &b);
Mathias Agopian0f288fc2013-08-21 16:36:34 -0700503 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_ALPHA_SIZE, &a);
Courtney Goeltzenleuchter0e4e3952016-11-16 13:53:40 -0700504 EGLint colorDepth = r + g + b;
505
506 if (a == 0) {
Mathias Agopian0f288fc2013-08-21 16:36:34 -0700507 if (colorDepth <= 16) {
508 format = HAL_PIXEL_FORMAT_RGB_565;
509 } else {
Courtney Goeltzenleuchter0e4e3952016-11-16 13:53:40 -0700510 if (componentType == EGL_COLOR_COMPONENT_TYPE_FIXED_EXT) {
511 if (colorDepth > 24) {
512 format = HAL_PIXEL_FORMAT_RGBA_1010102;
513 } else {
514 format = HAL_PIXEL_FORMAT_RGBX_8888;
515 }
516 } else {
517 format = HAL_PIXEL_FORMAT_RGBA_FP16;
518 }
519 }
520 } else {
521 if (componentType == EGL_COLOR_COMPONENT_TYPE_FIXED_EXT) {
522 if (colorDepth > 24) {
523 format = HAL_PIXEL_FORMAT_RGBA_1010102;
524 } else {
525 format = HAL_PIXEL_FORMAT_RGBA_8888;
526 }
527 } else {
528 format = HAL_PIXEL_FORMAT_RGBA_FP16;
Mathias Agopian0f288fc2013-08-21 16:36:34 -0700529 }
Jesse Hallc2e41222013-08-08 13:40:22 -0700530 }
Mathias Agopian0f288fc2013-08-21 16:36:34 -0700531
532 // now select a corresponding sRGB format if needed
533 if (attrib_list && dp->haveExtension("EGL_KHR_gl_colorspace")) {
534 for (const EGLint* attr = attrib_list; *attr != EGL_NONE; attr += 2) {
535 if (*attr == EGL_GL_COLORSPACE_KHR) {
Sandeep Shinde9c67bfd2015-02-10 16:04:15 +0530536 dataSpace = modifyBufferDataspace(dataSpace, *(attr+1));
Jamie Gennisbee205f2011-07-01 13:12:07 -0700537 }
Mathias Agopian518ec112011-05-13 16:21:08 -0700538 }
539 }
Alistair Strachan733a8072015-02-12 12:33:25 -0800540
Jesse Hallc2e41222013-08-08 13:40:22 -0700541 if (format != 0) {
542 int err = native_window_set_buffers_format(window, format);
543 if (err != 0) {
544 ALOGE("error setting native window pixel format: %s (%d)",
545 strerror(-err), err);
546 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
547 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
548 }
549 }
Mathias Agopian518ec112011-05-13 16:21:08 -0700550
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800551 if (dataSpace != 0) {
552 int err = native_window_set_buffers_data_space(window, dataSpace);
553 if (err != 0) {
554 ALOGE("error setting native window pixel dataSpace: %s (%d)",
555 strerror(-err), err);
556 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
557 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
558 }
559 }
560
Jamie Gennis59769462011-11-19 18:04:43 -0800561 // the EGL spec requires that a new EGLSurface default to swap interval
562 // 1, so explicitly set that on the window here.
563 ANativeWindow* anw = reinterpret_cast<ANativeWindow*>(window);
564 anw->setSwapInterval(anw, 1);
565
Mathias Agopian518ec112011-05-13 16:21:08 -0700566 EGLSurface surface = cnx->egl.eglCreateWindowSurface(
Mathias Agopian7773c432012-02-13 20:06:08 -0800567 iDpy, config, window, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700568 if (surface != EGL_NO_SURFACE) {
Jesse Hallb29e5e82012-04-04 16:53:42 -0700569 egl_surface_t* s = new egl_surface_t(dp.get(), config, window,
570 surface, cnx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700571 return s;
572 }
Mathias Agopian81a63352011-07-29 17:55:48 -0700573
574 // EGLSurface creation failed
575 native_window_set_buffers_format(window, 0);
576 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
Mathias Agopian518ec112011-05-13 16:21:08 -0700577 }
578 return EGL_NO_SURFACE;
579}
580
581EGLSurface eglCreatePixmapSurface( EGLDisplay dpy, EGLConfig config,
582 NativePixmapType pixmap,
583 const EGLint *attrib_list)
584{
585 clearError();
586
Jesse Hallb29e5e82012-04-04 16:53:42 -0700587 egl_connection_t* cnx = NULL;
588 egl_display_ptr dp = validate_display_connection(dpy, cnx);
589 if (dp) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700590 EGLSurface surface = cnx->egl.eglCreatePixmapSurface(
Mathias Agopian7773c432012-02-13 20:06:08 -0800591 dp->disp.dpy, config, pixmap, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700592 if (surface != EGL_NO_SURFACE) {
Jesse Hallb29e5e82012-04-04 16:53:42 -0700593 egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL,
594 surface, cnx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700595 return s;
596 }
597 }
598 return EGL_NO_SURFACE;
599}
600
601EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config,
602 const EGLint *attrib_list)
603{
604 clearError();
605
Jesse Hallb29e5e82012-04-04 16:53:42 -0700606 egl_connection_t* cnx = NULL;
607 egl_display_ptr dp = validate_display_connection(dpy, cnx);
608 if (dp) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700609 EGLSurface surface = cnx->egl.eglCreatePbufferSurface(
Mathias Agopian7773c432012-02-13 20:06:08 -0800610 dp->disp.dpy, config, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700611 if (surface != EGL_NO_SURFACE) {
Jesse Hallb29e5e82012-04-04 16:53:42 -0700612 egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL,
613 surface, cnx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700614 return s;
615 }
616 }
617 return EGL_NO_SURFACE;
618}
Jesse Hall47743382013-02-08 11:13:46 -0800619
Mathias Agopian518ec112011-05-13 16:21:08 -0700620EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
621{
622 clearError();
623
Jesse Hallb29e5e82012-04-04 16:53:42 -0700624 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700625 if (!dp) return EGL_FALSE;
626
Jesse Hallb29e5e82012-04-04 16:53:42 -0700627 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700628 if (!_s.get())
Mathias Agopian737b8962017-02-24 14:32:05 -0800629 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700630
631 egl_surface_t * const s = get_surface(surface);
Mathias Agopianada798b2012-02-13 17:09:30 -0800632 EGLBoolean result = s->cnx->egl.eglDestroySurface(dp->disp.dpy, s->surface);
Mathias Agopian518ec112011-05-13 16:21:08 -0700633 if (result == EGL_TRUE) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700634 _s.terminate();
635 }
636 return result;
637}
638
639EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface surface,
640 EGLint attribute, EGLint *value)
641{
642 clearError();
643
Jesse Hallb29e5e82012-04-04 16:53:42 -0700644 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700645 if (!dp) return EGL_FALSE;
646
Jesse Hallb29e5e82012-04-04 16:53:42 -0700647 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700648 if (!_s.get())
Mathias Agopian737b8962017-02-24 14:32:05 -0800649 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700650
Mathias Agopian518ec112011-05-13 16:21:08 -0700651 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian7773c432012-02-13 20:06:08 -0800652 return s->cnx->egl.eglQuerySurface(
653 dp->disp.dpy, s->surface, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -0700654}
655
Jamie Gennise8696a42012-01-15 18:54:57 -0800656void EGLAPI eglBeginFrame(EGLDisplay dpy, EGLSurface surface) {
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800657 ATRACE_CALL();
Jamie Gennise8696a42012-01-15 18:54:57 -0800658 clearError();
659
Jesse Hallb29e5e82012-04-04 16:53:42 -0700660 const egl_display_ptr dp = validate_display(dpy);
Jamie Gennise8696a42012-01-15 18:54:57 -0800661 if (!dp) {
662 return;
663 }
664
Jesse Hallb29e5e82012-04-04 16:53:42 -0700665 SurfaceRef _s(dp.get(), surface);
Jamie Gennise8696a42012-01-15 18:54:57 -0800666 if (!_s.get()) {
667 setError(EGL_BAD_SURFACE, EGL_FALSE);
Jamie Gennise8696a42012-01-15 18:54:57 -0800668 }
Jamie Gennise8696a42012-01-15 18:54:57 -0800669}
670
Mathias Agopian518ec112011-05-13 16:21:08 -0700671// ----------------------------------------------------------------------------
672// Contexts
673// ----------------------------------------------------------------------------
674
675EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config,
676 EGLContext share_list, const EGLint *attrib_list)
677{
678 clearError();
679
Jesse Hallb29e5e82012-04-04 16:53:42 -0700680 egl_connection_t* cnx = NULL;
681 const egl_display_ptr dp = validate_display_connection(dpy, cnx);
Michael Chock0673e1e2012-06-21 12:53:17 -0700682 if (dp) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700683 if (share_list != EGL_NO_CONTEXT) {
Michael Chock0673e1e2012-06-21 12:53:17 -0700684 if (!ContextRef(dp.get(), share_list).get()) {
685 return setError(EGL_BAD_CONTEXT, EGL_NO_CONTEXT);
686 }
Mathias Agopian518ec112011-05-13 16:21:08 -0700687 egl_context_t* const c = get_context(share_list);
688 share_list = c->context;
689 }
690 EGLContext context = cnx->egl.eglCreateContext(
Mathias Agopian7773c432012-02-13 20:06:08 -0800691 dp->disp.dpy, config, share_list, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700692 if (context != EGL_NO_CONTEXT) {
693 // figure out if it's a GLESv1 or GLESv2
694 int version = 0;
695 if (attrib_list) {
696 while (*attrib_list != EGL_NONE) {
697 GLint attr = *attrib_list++;
698 GLint value = *attrib_list++;
699 if (attr == EGL_CONTEXT_CLIENT_VERSION) {
700 if (value == 1) {
Mathias Agopian7773c432012-02-13 20:06:08 -0800701 version = egl_connection_t::GLESv1_INDEX;
Jesse Hall47743382013-02-08 11:13:46 -0800702 } else if (value == 2 || value == 3) {
Mathias Agopian7773c432012-02-13 20:06:08 -0800703 version = egl_connection_t::GLESv2_INDEX;
Mathias Agopian518ec112011-05-13 16:21:08 -0700704 }
705 }
706 };
707 }
Jesse Hallb29e5e82012-04-04 16:53:42 -0700708 egl_context_t* c = new egl_context_t(dpy, context, config, cnx,
709 version);
Mathias Agopian518ec112011-05-13 16:21:08 -0700710 return c;
711 }
712 }
713 return EGL_NO_CONTEXT;
714}
715
716EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
717{
718 clearError();
719
Jesse Hallb29e5e82012-04-04 16:53:42 -0700720 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700721 if (!dp)
722 return EGL_FALSE;
Mathias Agopian518ec112011-05-13 16:21:08 -0700723
Jesse Hallb29e5e82012-04-04 16:53:42 -0700724 ContextRef _c(dp.get(), ctx);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700725 if (!_c.get())
Mathias Agopian737b8962017-02-24 14:32:05 -0800726 return setError(EGL_BAD_CONTEXT, (EGLBoolean)EGL_FALSE);
Jesse Hall47743382013-02-08 11:13:46 -0800727
Mathias Agopian518ec112011-05-13 16:21:08 -0700728 egl_context_t * const c = get_context(ctx);
Mathias Agopianada798b2012-02-13 17:09:30 -0800729 EGLBoolean result = c->cnx->egl.eglDestroyContext(dp->disp.dpy, c->context);
Mathias Agopian518ec112011-05-13 16:21:08 -0700730 if (result == EGL_TRUE) {
731 _c.terminate();
732 }
733 return result;
734}
735
Mathias Agopian518ec112011-05-13 16:21:08 -0700736EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw,
737 EGLSurface read, EGLContext ctx)
738{
739 clearError();
740
Jesse Hallb29e5e82012-04-04 16:53:42 -0700741 egl_display_ptr dp = validate_display(dpy);
Mathias Agopian737b8962017-02-24 14:32:05 -0800742 if (!dp) return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700743
Mathias Agopian5b287a62011-05-16 18:58:55 -0700744 // If ctx is not EGL_NO_CONTEXT, read is not EGL_NO_SURFACE, or draw is not
745 // EGL_NO_SURFACE, then an EGL_NOT_INITIALIZED error is generated if dpy is
746 // a valid but uninitialized display.
Mathias Agopian518ec112011-05-13 16:21:08 -0700747 if ( (ctx != EGL_NO_CONTEXT) || (read != EGL_NO_SURFACE) ||
748 (draw != EGL_NO_SURFACE) ) {
Mathias Agopian737b8962017-02-24 14:32:05 -0800749 if (!dp->isReady()) return setError(EGL_NOT_INITIALIZED, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700750 }
751
752 // get a reference to the object passed in
Jesse Hallb29e5e82012-04-04 16:53:42 -0700753 ContextRef _c(dp.get(), ctx);
754 SurfaceRef _d(dp.get(), draw);
755 SurfaceRef _r(dp.get(), read);
Mathias Agopian518ec112011-05-13 16:21:08 -0700756
757 // validate the context (if not EGL_NO_CONTEXT)
Mathias Agopian5b287a62011-05-16 18:58:55 -0700758 if ((ctx != EGL_NO_CONTEXT) && !_c.get()) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700759 // EGL_NO_CONTEXT is valid
Mathias Agopian737b8962017-02-24 14:32:05 -0800760 return setError(EGL_BAD_CONTEXT, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700761 }
762
763 // these are the underlying implementation's object
764 EGLContext impl_ctx = EGL_NO_CONTEXT;
765 EGLSurface impl_draw = EGL_NO_SURFACE;
766 EGLSurface impl_read = EGL_NO_SURFACE;
767
768 // these are our objects structs passed in
769 egl_context_t * c = NULL;
770 egl_surface_t const * d = NULL;
771 egl_surface_t const * r = NULL;
772
773 // these are the current objects structs
774 egl_context_t * cur_c = get_context(getContext());
Jesse Hall47743382013-02-08 11:13:46 -0800775
Mathias Agopian518ec112011-05-13 16:21:08 -0700776 if (ctx != EGL_NO_CONTEXT) {
777 c = get_context(ctx);
778 impl_ctx = c->context;
779 } else {
780 // no context given, use the implementation of the current context
Michael Chock0673e1e2012-06-21 12:53:17 -0700781 if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE) {
782 // calling eglMakeCurrent( ..., !=0, !=0, EGL_NO_CONTEXT);
Mathias Agopian737b8962017-02-24 14:32:05 -0800783 return setError(EGL_BAD_MATCH, (EGLBoolean)EGL_FALSE);
Michael Chock0673e1e2012-06-21 12:53:17 -0700784 }
Mathias Agopian518ec112011-05-13 16:21:08 -0700785 if (cur_c == NULL) {
786 // no current context
Mathias Agopian518ec112011-05-13 16:21:08 -0700787 // not an error, there is just no current context.
788 return EGL_TRUE;
789 }
790 }
791
792 // retrieve the underlying implementation's draw EGLSurface
793 if (draw != EGL_NO_SURFACE) {
Mathias Agopian737b8962017-02-24 14:32:05 -0800794 if (!_d.get()) return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700795 d = get_surface(draw);
Mathias Agopian518ec112011-05-13 16:21:08 -0700796 impl_draw = d->surface;
797 }
798
799 // retrieve the underlying implementation's read EGLSurface
800 if (read != EGL_NO_SURFACE) {
Mathias Agopian737b8962017-02-24 14:32:05 -0800801 if (!_r.get()) return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700802 r = get_surface(read);
Mathias Agopian518ec112011-05-13 16:21:08 -0700803 impl_read = r->surface;
804 }
805
Mathias Agopian518ec112011-05-13 16:21:08 -0700806
Jesse Hallb29e5e82012-04-04 16:53:42 -0700807 EGLBoolean result = dp->makeCurrent(c, cur_c,
Mathias Agopianfb87e542012-01-30 18:20:52 -0800808 draw, read, ctx,
809 impl_draw, impl_read, impl_ctx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700810
811 if (result == EGL_TRUE) {
Mathias Agopianfb87e542012-01-30 18:20:52 -0800812 if (c) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700813 setGLHooksThreadSpecific(c->cnx->hooks[c->version]);
814 egl_tls_t::setContext(ctx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700815 _c.acquire();
816 _r.acquire();
817 _d.acquire();
Mathias Agopian518ec112011-05-13 16:21:08 -0700818 } else {
819 setGLHooksThreadSpecific(&gHooksNoContext);
820 egl_tls_t::setContext(EGL_NO_CONTEXT);
821 }
Mathias Agopian5fecea72011-08-25 18:38:24 -0700822 } else {
Steve Blocke6f43dd2012-01-06 19:20:56 +0000823 // this will ALOGE the error
Mathias Agopian63108c32013-09-06 13:36:49 -0700824 egl_connection_t* const cnx = &gEGLImpl;
Mathias Agopian737b8962017-02-24 14:32:05 -0800825 result = setError(cnx->egl.eglGetError(), (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700826 }
827 return result;
828}
829
830
831EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx,
832 EGLint attribute, EGLint *value)
833{
834 clearError();
835
Jesse Hallb29e5e82012-04-04 16:53:42 -0700836 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700837 if (!dp) return EGL_FALSE;
838
Jesse Hallb29e5e82012-04-04 16:53:42 -0700839 ContextRef _c(dp.get(), ctx);
Mathias Agopian737b8962017-02-24 14:32:05 -0800840 if (!_c.get()) return setError(EGL_BAD_CONTEXT, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700841
Mathias Agopian518ec112011-05-13 16:21:08 -0700842 egl_context_t * const c = get_context(ctx);
Mathias Agopian7773c432012-02-13 20:06:08 -0800843 return c->cnx->egl.eglQueryContext(
844 dp->disp.dpy, c->context, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -0700845
Mathias Agopian518ec112011-05-13 16:21:08 -0700846}
847
848EGLContext eglGetCurrentContext(void)
849{
850 // could be called before eglInitialize(), but we wouldn't have a context
851 // then, and this function would correctly return EGL_NO_CONTEXT.
852
853 clearError();
854
855 EGLContext ctx = getContext();
856 return ctx;
857}
858
859EGLSurface eglGetCurrentSurface(EGLint readdraw)
860{
861 // could be called before eglInitialize(), but we wouldn't have a context
862 // then, and this function would correctly return EGL_NO_SURFACE.
863
864 clearError();
865
866 EGLContext ctx = getContext();
867 if (ctx) {
868 egl_context_t const * const c = get_context(ctx);
869 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
870 switch (readdraw) {
871 case EGL_READ: return c->read;
Jesse Hall47743382013-02-08 11:13:46 -0800872 case EGL_DRAW: return c->draw;
Mathias Agopian518ec112011-05-13 16:21:08 -0700873 default: return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
874 }
875 }
876 return EGL_NO_SURFACE;
877}
878
879EGLDisplay eglGetCurrentDisplay(void)
880{
881 // could be called before eglInitialize(), but we wouldn't have a context
882 // then, and this function would correctly return EGL_NO_DISPLAY.
883
884 clearError();
885
886 EGLContext ctx = getContext();
887 if (ctx) {
888 egl_context_t const * const c = get_context(ctx);
889 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
890 return c->dpy;
891 }
892 return EGL_NO_DISPLAY;
893}
894
895EGLBoolean eglWaitGL(void)
896{
Mathias Agopian518ec112011-05-13 16:21:08 -0700897 clearError();
898
Mathias Agopianada798b2012-02-13 17:09:30 -0800899 egl_connection_t* const cnx = &gEGLImpl;
900 if (!cnx->dso)
Mathias Agopian737b8962017-02-24 14:32:05 -0800901 return setError(EGL_BAD_CONTEXT, (EGLBoolean)EGL_FALSE);
Mathias Agopianada798b2012-02-13 17:09:30 -0800902
903 return cnx->egl.eglWaitGL();
Mathias Agopian518ec112011-05-13 16:21:08 -0700904}
905
906EGLBoolean eglWaitNative(EGLint engine)
907{
Mathias Agopian518ec112011-05-13 16:21:08 -0700908 clearError();
909
Mathias Agopianada798b2012-02-13 17:09:30 -0800910 egl_connection_t* const cnx = &gEGLImpl;
911 if (!cnx->dso)
Mathias Agopian737b8962017-02-24 14:32:05 -0800912 return setError(EGL_BAD_CONTEXT, (EGLBoolean)EGL_FALSE);
Mathias Agopianada798b2012-02-13 17:09:30 -0800913
914 return cnx->egl.eglWaitNative(engine);
Mathias Agopian518ec112011-05-13 16:21:08 -0700915}
916
917EGLint eglGetError(void)
918{
Mathias Agopianada798b2012-02-13 17:09:30 -0800919 EGLint err = EGL_SUCCESS;
920 egl_connection_t* const cnx = &gEGLImpl;
921 if (cnx->dso) {
922 err = cnx->egl.eglGetError();
Mathias Agopian518ec112011-05-13 16:21:08 -0700923 }
Mathias Agopianada798b2012-02-13 17:09:30 -0800924 if (err == EGL_SUCCESS) {
925 err = egl_tls_t::getError();
926 }
927 return err;
Mathias Agopian518ec112011-05-13 16:21:08 -0700928}
929
Michael Chockc0ec5e22014-01-27 08:14:33 -0800930static __eglMustCastToProperFunctionPointerType findBuiltinWrapper(
Jesse Hallc07b5202013-07-04 12:08:16 -0700931 const char* procname) {
932 const egl_connection_t* cnx = &gEGLImpl;
933 void* proc = NULL;
934
Michael Chockc0ec5e22014-01-27 08:14:33 -0800935 proc = dlsym(cnx->libEgl, procname);
936 if (proc) return (__eglMustCastToProperFunctionPointerType)proc;
937
Jesse Hallc07b5202013-07-04 12:08:16 -0700938 proc = dlsym(cnx->libGles2, procname);
939 if (proc) return (__eglMustCastToProperFunctionPointerType)proc;
940
941 proc = dlsym(cnx->libGles1, procname);
942 if (proc) return (__eglMustCastToProperFunctionPointerType)proc;
943
944 return NULL;
945}
946
Mathias Agopian518ec112011-05-13 16:21:08 -0700947__eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
948{
949 // eglGetProcAddress() could be the very first function called
950 // in which case we must make sure we've initialized ourselves, this
951 // happens the first time egl_get_display() is called.
952
953 clearError();
954
955 if (egl_init_drivers() == EGL_FALSE) {
956 setError(EGL_BAD_PARAMETER, NULL);
957 return NULL;
958 }
959
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700960 if (FILTER_EXTENSIONS(procname)) {
Jamie Gennisaca51c02011-11-03 17:42:43 -0700961 return NULL;
962 }
963
Mathias Agopian518ec112011-05-13 16:21:08 -0700964 __eglMustCastToProperFunctionPointerType addr;
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700965 addr = findProcAddress(procname, sExtensionMap, NELEM(sExtensionMap));
Mathias Agopian518ec112011-05-13 16:21:08 -0700966 if (addr) return addr;
967
Michael Chockc0ec5e22014-01-27 08:14:33 -0800968 addr = findBuiltinWrapper(procname);
Jesse Hallc07b5202013-07-04 12:08:16 -0700969 if (addr) return addr;
Jamie Gennisaca51c02011-11-03 17:42:43 -0700970
Mathias Agopian518ec112011-05-13 16:21:08 -0700971 // this protects accesses to sGLExtentionMap and sGLExtentionSlot
972 pthread_mutex_lock(&sExtensionMapMutex);
973
974 /*
975 * Since eglGetProcAddress() is not associated to anything, it needs
976 * to return a function pointer that "works" regardless of what
977 * the current context is.
978 *
979 * For this reason, we return a "forwarder", a small stub that takes
980 * care of calling the function associated with the context
981 * currently bound.
982 *
983 * We first look for extensions we've already resolved, if we're seeing
984 * this extension for the first time, we go through all our
985 * implementations and call eglGetProcAddress() and record the
986 * result in the appropriate implementation hooks and return the
987 * address of the forwarder corresponding to that hook set.
988 *
989 */
990
991 const String8 name(procname);
992 addr = sGLExtentionMap.valueFor(name);
993 const int slot = sGLExtentionSlot;
994
Steve Blocke6f43dd2012-01-06 19:20:56 +0000995 ALOGE_IF(slot >= MAX_NUMBER_OF_GL_EXTENSIONS,
Mathias Agopian518ec112011-05-13 16:21:08 -0700996 "no more slots for eglGetProcAddress(\"%s\")",
997 procname);
998
999 if (!addr && (slot < MAX_NUMBER_OF_GL_EXTENSIONS)) {
1000 bool found = false;
Mathias Agopianada798b2012-02-13 17:09:30 -08001001
1002 egl_connection_t* const cnx = &gEGLImpl;
1003 if (cnx->dso && cnx->egl.eglGetProcAddress) {
Mathias Agopianada798b2012-02-13 17:09:30 -08001004 // Extensions are independent of the bound context
luliuhui69d10072012-08-30 11:15:36 +08001005 addr =
Mathias Agopian7773c432012-02-13 20:06:08 -08001006 cnx->hooks[egl_connection_t::GLESv1_INDEX]->ext.extensions[slot] =
1007 cnx->hooks[egl_connection_t::GLESv2_INDEX]->ext.extensions[slot] =
Mathias Agopianada798b2012-02-13 17:09:30 -08001008 cnx->egl.eglGetProcAddress(procname);
luliuhui69d10072012-08-30 11:15:36 +08001009 if (addr) found = true;
Mathias Agopian518ec112011-05-13 16:21:08 -07001010 }
Mathias Agopianada798b2012-02-13 17:09:30 -08001011
Mathias Agopian518ec112011-05-13 16:21:08 -07001012 if (found) {
1013 addr = gExtensionForwarders[slot];
Mathias Agopian518ec112011-05-13 16:21:08 -07001014 sGLExtentionMap.add(name, addr);
1015 sGLExtentionSlot++;
1016 }
1017 }
1018
1019 pthread_mutex_unlock(&sExtensionMapMutex);
1020 return addr;
1021}
1022
Jamie Gennis28ef8d72012-04-05 20:34:54 -07001023class FrameCompletionThread : public Thread {
1024public:
1025
1026 static void queueSync(EGLSyncKHR sync) {
1027 static sp<FrameCompletionThread> thread(new FrameCompletionThread);
1028 static bool running = false;
1029 if (!running) {
1030 thread->run("GPUFrameCompletion");
1031 running = true;
1032 }
1033 {
1034 Mutex::Autolock lock(thread->mMutex);
1035 ScopedTrace st(ATRACE_TAG, String8::format("kicked off frame %d",
1036 thread->mFramesQueued).string());
1037 thread->mQueue.push_back(sync);
1038 thread->mCondition.signal();
1039 thread->mFramesQueued++;
Mathias Agopian737b8962017-02-24 14:32:05 -08001040 ATRACE_INT("GPU Frames Outstanding", int32_t(thread->mQueue.size()));
Jamie Gennis28ef8d72012-04-05 20:34:54 -07001041 }
1042 }
1043
1044private:
1045 FrameCompletionThread() : mFramesQueued(0), mFramesCompleted(0) {}
1046
1047 virtual bool threadLoop() {
1048 EGLSyncKHR sync;
1049 uint32_t frameNum;
1050 {
1051 Mutex::Autolock lock(mMutex);
1052 while (mQueue.isEmpty()) {
1053 mCondition.wait(mMutex);
1054 }
1055 sync = mQueue[0];
1056 frameNum = mFramesCompleted;
1057 }
1058 EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
1059 {
1060 ScopedTrace st(ATRACE_TAG, String8::format("waiting for frame %d",
1061 frameNum).string());
1062 EGLint result = eglClientWaitSyncKHR(dpy, sync, 0, EGL_FOREVER_KHR);
1063 if (result == EGL_FALSE) {
1064 ALOGE("FrameCompletion: error waiting for fence: %#x", eglGetError());
1065 } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
1066 ALOGE("FrameCompletion: timeout waiting for fence");
1067 }
1068 eglDestroySyncKHR(dpy, sync);
1069 }
1070 {
1071 Mutex::Autolock lock(mMutex);
1072 mQueue.removeAt(0);
1073 mFramesCompleted++;
Mathias Agopian737b8962017-02-24 14:32:05 -08001074 ATRACE_INT("GPU Frames Outstanding", int32_t(mQueue.size()));
Jamie Gennis28ef8d72012-04-05 20:34:54 -07001075 }
1076 return true;
1077 }
1078
1079 uint32_t mFramesQueued;
1080 uint32_t mFramesCompleted;
1081 Vector<EGLSyncKHR> mQueue;
1082 Condition mCondition;
1083 Mutex mMutex;
1084};
1085
Dan Stozaa894d082015-02-19 15:27:36 -08001086EGLBoolean eglSwapBuffersWithDamageKHR(EGLDisplay dpy, EGLSurface draw,
1087 EGLint *rects, EGLint n_rects)
Mathias Agopian518ec112011-05-13 16:21:08 -07001088{
Jamie Gennis1c8e95c2012-02-23 19:27:23 -08001089 ATRACE_CALL();
Mathias Agopian518ec112011-05-13 16:21:08 -07001090 clearError();
1091
Jesse Hallb29e5e82012-04-04 16:53:42 -07001092 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001093 if (!dp) return EGL_FALSE;
1094
Jesse Hallb29e5e82012-04-04 16:53:42 -07001095 SurfaceRef _s(dp.get(), draw);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001096 if (!_s.get())
Mathias Agopian737b8962017-02-24 14:32:05 -08001097 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001098
Mathias Agopian518ec112011-05-13 16:21:08 -07001099 egl_surface_t const * const s = get_surface(draw);
Mathias Agopian7db993a2012-03-25 00:49:46 -07001100
Mathias Agopianed6d08b2013-04-16 16:39:46 -07001101 if (CC_UNLIKELY(dp->traceGpuCompletion)) {
1102 EGLSyncKHR sync = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, NULL);
1103 if (sync != EGL_NO_SYNC_KHR) {
1104 FrameCompletionThread::queueSync(sync);
1105 }
1106 }
1107
Mathias Agopian7db993a2012-03-25 00:49:46 -07001108 if (CC_UNLIKELY(dp->finishOnSwap)) {
1109 uint32_t pixel;
1110 egl_context_t * const c = get_context( egl_tls_t::getContext() );
1111 if (c) {
1112 // glReadPixels() ensures that the frame is complete
1113 s->cnx->hooks[c->version]->gl.glReadPixels(0,0,1,1,
1114 GL_RGBA,GL_UNSIGNED_BYTE,&pixel);
1115 }
1116 }
1117
Dan Stozaa894d082015-02-19 15:27:36 -08001118 if (n_rects == 0) {
1119 return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface);
1120 }
1121
1122 Vector<android_native_rect_t> androidRects;
1123 for (int r = 0; r < n_rects; ++r) {
1124 int offset = r * 4;
1125 int x = rects[offset];
1126 int y = rects[offset + 1];
1127 int width = rects[offset + 2];
1128 int height = rects[offset + 3];
1129 android_native_rect_t androidRect;
1130 androidRect.left = x;
1131 androidRect.top = y + height;
1132 androidRect.right = x + width;
1133 androidRect.bottom = y;
1134 androidRects.push_back(androidRect);
1135 }
1136 native_window_set_surface_damage(s->win.get(), androidRects.array(),
1137 androidRects.size());
1138
1139 if (s->cnx->egl.eglSwapBuffersWithDamageKHR) {
1140 return s->cnx->egl.eglSwapBuffersWithDamageKHR(dp->disp.dpy, s->surface,
1141 rects, n_rects);
1142 } else {
1143 return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface);
1144 }
1145}
1146
1147EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
1148{
1149 return eglSwapBuffersWithDamageKHR(dpy, surface, NULL, 0);
Mathias Agopian518ec112011-05-13 16:21:08 -07001150}
1151
1152EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface,
1153 NativePixmapType target)
1154{
1155 clearError();
1156
Jesse Hallb29e5e82012-04-04 16:53:42 -07001157 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001158 if (!dp) return EGL_FALSE;
1159
Jesse Hallb29e5e82012-04-04 16:53:42 -07001160 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001161 if (!_s.get())
Mathias Agopian737b8962017-02-24 14:32:05 -08001162 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001163
Mathias Agopian518ec112011-05-13 16:21:08 -07001164 egl_surface_t const * const s = get_surface(surface);
Mathias Agopianada798b2012-02-13 17:09:30 -08001165 return s->cnx->egl.eglCopyBuffers(dp->disp.dpy, s->surface, target);
Mathias Agopian518ec112011-05-13 16:21:08 -07001166}
1167
1168const char* eglQueryString(EGLDisplay dpy, EGLint name)
1169{
1170 clearError();
1171
Chia-I Wue57d1352016-08-15 16:10:02 +08001172 // Generate an error quietly when client extensions (as defined by
1173 // EGL_EXT_client_extensions) are queried. We do not want to rely on
1174 // validate_display to generate the error as validate_display would log
1175 // the error, which can be misleading.
1176 //
1177 // If we want to support EGL_EXT_client_extensions later, we can return
1178 // the client extension string here instead.
1179 if (dpy == EGL_NO_DISPLAY && name == EGL_EXTENSIONS)
Mathias Agopian737b8962017-02-24 14:32:05 -08001180 return setErrorQuiet(EGL_BAD_DISPLAY, (const char*)0);
Chia-I Wue57d1352016-08-15 16:10:02 +08001181
Jesse Hallb29e5e82012-04-04 16:53:42 -07001182 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001183 if (!dp) return (const char *) NULL;
1184
1185 switch (name) {
1186 case EGL_VENDOR:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001187 return dp->getVendorString();
Mathias Agopian518ec112011-05-13 16:21:08 -07001188 case EGL_VERSION:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001189 return dp->getVersionString();
Mathias Agopian518ec112011-05-13 16:21:08 -07001190 case EGL_EXTENSIONS:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001191 return dp->getExtensionString();
Mathias Agopian518ec112011-05-13 16:21:08 -07001192 case EGL_CLIENT_APIS:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001193 return dp->getClientApiString();
Mathias Agopian737b8962017-02-24 14:32:05 -08001194 default:
1195 break;
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;
Mathias Agopian737b8962017-02-24 14:32:05 -08001216 default:
1217 break;
Mathias Agopianca088332013-03-28 17:44:13 -07001218 }
1219 return setError(EGL_BAD_PARAMETER, (const char *)0);
1220}
Mathias Agopian518ec112011-05-13 16:21:08 -07001221
1222// ----------------------------------------------------------------------------
1223// EGL 1.1
1224// ----------------------------------------------------------------------------
1225
1226EGLBoolean eglSurfaceAttrib(
1227 EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
1228{
1229 clearError();
1230
Jesse Hallb29e5e82012-04-04 16:53:42 -07001231 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001232 if (!dp) return EGL_FALSE;
1233
Jesse Hallb29e5e82012-04-04 16:53:42 -07001234 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001235 if (!_s.get())
Mathias Agopian737b8962017-02-24 14:32:05 -08001236 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001237
Pablo Ceballosc18be292016-05-31 14:55:42 -07001238 egl_surface_t * const s = get_surface(surface);
Pablo Ceballosccdfd602015-10-07 15:05:45 -07001239
Pablo Ceballos02b05da2016-02-02 17:53:18 -08001240 if (attribute == EGL_FRONT_BUFFER_AUTO_REFRESH_ANDROID) {
Brian Anderson069b3652016-07-22 10:32:47 -07001241 if (!s->win.get()) {
1242 setError(EGL_BAD_SURFACE, EGL_FALSE);
1243 }
Mathias Agopian737b8962017-02-24 14:32:05 -08001244 int err = native_window_set_auto_refresh(s->win.get(), value ? true : false);
1245 return (err == NO_ERROR) ? EGL_TRUE : setError(EGL_BAD_SURFACE, (EGLBoolean)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()) {
Mathias Agopian737b8962017-02-24 14:32:05 -08001250 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Brian Anderson069b3652016-07-22 10:32:47 -07001251 }
Mathias Agopian737b8962017-02-24 14:32:05 -08001252 int err = native_window_enable_frame_timestamps(s->win.get(), value ? true : false);
1253 return (err == NO_ERROR) ? EGL_TRUE : setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Pablo Ceballosc18be292016-05-31 14:55:42 -07001254 }
1255
Mathias Agopian518ec112011-05-13 16:21:08 -07001256 if (s->cnx->egl.eglSurfaceAttrib) {
1257 return s->cnx->egl.eglSurfaceAttrib(
Mathias Agopianada798b2012-02-13 17:09:30 -08001258 dp->disp.dpy, s->surface, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -07001259 }
Mathias Agopian737b8962017-02-24 14:32:05 -08001260 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001261}
1262
1263EGLBoolean eglBindTexImage(
1264 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1265{
1266 clearError();
1267
Jesse Hallb29e5e82012-04-04 16:53:42 -07001268 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001269 if (!dp) return EGL_FALSE;
1270
Jesse Hallb29e5e82012-04-04 16:53:42 -07001271 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001272 if (!_s.get())
Mathias Agopian737b8962017-02-24 14:32:05 -08001273 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001274
Mathias Agopian518ec112011-05-13 16:21:08 -07001275 egl_surface_t const * const s = get_surface(surface);
1276 if (s->cnx->egl.eglBindTexImage) {
1277 return s->cnx->egl.eglBindTexImage(
Mathias Agopianada798b2012-02-13 17:09:30 -08001278 dp->disp.dpy, s->surface, buffer);
Mathias Agopian518ec112011-05-13 16:21:08 -07001279 }
Mathias Agopian737b8962017-02-24 14:32:05 -08001280 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001281}
1282
1283EGLBoolean eglReleaseTexImage(
1284 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1285{
1286 clearError();
1287
Jesse Hallb29e5e82012-04-04 16:53:42 -07001288 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001289 if (!dp) return EGL_FALSE;
1290
Jesse Hallb29e5e82012-04-04 16:53:42 -07001291 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001292 if (!_s.get())
Mathias Agopian737b8962017-02-24 14:32:05 -08001293 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001294
Mathias Agopian518ec112011-05-13 16:21:08 -07001295 egl_surface_t const * const s = get_surface(surface);
1296 if (s->cnx->egl.eglReleaseTexImage) {
1297 return s->cnx->egl.eglReleaseTexImage(
Mathias Agopianada798b2012-02-13 17:09:30 -08001298 dp->disp.dpy, s->surface, buffer);
Mathias Agopian518ec112011-05-13 16:21:08 -07001299 }
Mathias Agopian737b8962017-02-24 14:32:05 -08001300 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001301}
1302
1303EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
1304{
1305 clearError();
1306
Jesse Hallb29e5e82012-04-04 16:53:42 -07001307 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001308 if (!dp) return EGL_FALSE;
1309
1310 EGLBoolean res = EGL_TRUE;
Mathias Agopianada798b2012-02-13 17:09:30 -08001311 egl_connection_t* const cnx = &gEGLImpl;
1312 if (cnx->dso && cnx->egl.eglSwapInterval) {
1313 res = cnx->egl.eglSwapInterval(dp->disp.dpy, interval);
Mathias Agopian518ec112011-05-13 16:21:08 -07001314 }
Mathias Agopianada798b2012-02-13 17:09:30 -08001315
Mathias Agopian518ec112011-05-13 16:21:08 -07001316 return res;
1317}
1318
1319
1320// ----------------------------------------------------------------------------
1321// EGL 1.2
1322// ----------------------------------------------------------------------------
1323
1324EGLBoolean eglWaitClient(void)
1325{
1326 clearError();
1327
Mathias Agopianada798b2012-02-13 17:09:30 -08001328 egl_connection_t* const cnx = &gEGLImpl;
1329 if (!cnx->dso)
Mathias Agopian737b8962017-02-24 14:32:05 -08001330 return setError(EGL_BAD_CONTEXT, (EGLBoolean)EGL_FALSE);
Mathias Agopianada798b2012-02-13 17:09:30 -08001331
1332 EGLBoolean res;
1333 if (cnx->egl.eglWaitClient) {
1334 res = cnx->egl.eglWaitClient();
1335 } else {
1336 res = cnx->egl.eglWaitGL();
Mathias Agopian518ec112011-05-13 16:21:08 -07001337 }
1338 return res;
1339}
1340
1341EGLBoolean eglBindAPI(EGLenum api)
1342{
1343 clearError();
1344
1345 if (egl_init_drivers() == EGL_FALSE) {
Mathias Agopian737b8962017-02-24 14:32:05 -08001346 return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001347 }
1348
1349 // bind this API on all EGLs
1350 EGLBoolean res = EGL_TRUE;
Mathias Agopianada798b2012-02-13 17:09:30 -08001351 egl_connection_t* const cnx = &gEGLImpl;
1352 if (cnx->dso && cnx->egl.eglBindAPI) {
1353 res = cnx->egl.eglBindAPI(api);
Mathias Agopian518ec112011-05-13 16:21:08 -07001354 }
1355 return res;
1356}
1357
1358EGLenum eglQueryAPI(void)
1359{
1360 clearError();
1361
1362 if (egl_init_drivers() == EGL_FALSE) {
Mathias Agopian737b8962017-02-24 14:32:05 -08001363 return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001364 }
1365
Mathias Agopianada798b2012-02-13 17:09:30 -08001366 egl_connection_t* const cnx = &gEGLImpl;
1367 if (cnx->dso && cnx->egl.eglQueryAPI) {
1368 return cnx->egl.eglQueryAPI();
Mathias Agopian518ec112011-05-13 16:21:08 -07001369 }
Mathias Agopianada798b2012-02-13 17:09:30 -08001370
Mathias Agopian518ec112011-05-13 16:21:08 -07001371 // or, it can only be OpenGL ES
1372 return EGL_OPENGL_ES_API;
1373}
1374
1375EGLBoolean eglReleaseThread(void)
1376{
1377 clearError();
1378
Mathias Agopianada798b2012-02-13 17:09:30 -08001379 egl_connection_t* const cnx = &gEGLImpl;
1380 if (cnx->dso && cnx->egl.eglReleaseThread) {
1381 cnx->egl.eglReleaseThread();
Mathias Agopian518ec112011-05-13 16:21:08 -07001382 }
Sai Kiran Korwar3ac517a2014-01-31 21:15:07 +05301383
1384 // If there is context bound to the thread, release it
1385 egl_display_t::loseCurrent(get_context(getContext()));
1386
Mathias Agopian518ec112011-05-13 16:21:08 -07001387 egl_tls_t::clearTLS();
Mathias Agopian518ec112011-05-13 16:21:08 -07001388 return EGL_TRUE;
1389}
1390
1391EGLSurface eglCreatePbufferFromClientBuffer(
1392 EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer,
1393 EGLConfig config, const EGLint *attrib_list)
1394{
1395 clearError();
1396
Jesse Hallb29e5e82012-04-04 16:53:42 -07001397 egl_connection_t* cnx = NULL;
1398 const egl_display_ptr dp = validate_display_connection(dpy, cnx);
1399 if (!dp) return EGL_FALSE;
Mathias Agopian518ec112011-05-13 16:21:08 -07001400 if (cnx->egl.eglCreatePbufferFromClientBuffer) {
1401 return cnx->egl.eglCreatePbufferFromClientBuffer(
Mathias Agopian7773c432012-02-13 20:06:08 -08001402 dp->disp.dpy, buftype, buffer, config, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001403 }
1404 return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE);
1405}
1406
1407// ----------------------------------------------------------------------------
1408// EGL_EGLEXT_VERSION 3
1409// ----------------------------------------------------------------------------
1410
1411EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface,
1412 const EGLint *attrib_list)
1413{
1414 clearError();
1415
Jesse Hallb29e5e82012-04-04 16:53:42 -07001416 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001417 if (!dp) return EGL_FALSE;
1418
Jesse Hallb29e5e82012-04-04 16:53:42 -07001419 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001420 if (!_s.get())
Mathias Agopian737b8962017-02-24 14:32:05 -08001421 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001422
1423 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian518ec112011-05-13 16:21:08 -07001424 if (s->cnx->egl.eglLockSurfaceKHR) {
1425 return s->cnx->egl.eglLockSurfaceKHR(
Mathias Agopianada798b2012-02-13 17:09:30 -08001426 dp->disp.dpy, s->surface, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001427 }
Mathias Agopian737b8962017-02-24 14:32:05 -08001428 return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001429}
1430
1431EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface)
1432{
1433 clearError();
1434
Jesse Hallb29e5e82012-04-04 16:53:42 -07001435 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001436 if (!dp) return EGL_FALSE;
1437
Jesse Hallb29e5e82012-04-04 16:53:42 -07001438 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001439 if (!_s.get())
Mathias Agopian737b8962017-02-24 14:32:05 -08001440 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001441
1442 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian518ec112011-05-13 16:21:08 -07001443 if (s->cnx->egl.eglUnlockSurfaceKHR) {
Mathias Agopianada798b2012-02-13 17:09:30 -08001444 return s->cnx->egl.eglUnlockSurfaceKHR(dp->disp.dpy, s->surface);
Mathias Agopian518ec112011-05-13 16:21:08 -07001445 }
Mathias Agopian737b8962017-02-24 14:32:05 -08001446 return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001447}
1448
1449EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
1450 EGLClientBuffer buffer, const EGLint *attrib_list)
1451{
1452 clearError();
1453
Jesse Hallb29e5e82012-04-04 16:53:42 -07001454 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001455 if (!dp) return EGL_NO_IMAGE_KHR;
1456
Jesse Hallb29e5e82012-04-04 16:53:42 -07001457 ContextRef _c(dp.get(), ctx);
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001458 egl_context_t * const c = _c.get();
Mathias Agopian518ec112011-05-13 16:21:08 -07001459
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001460 EGLImageKHR result = EGL_NO_IMAGE_KHR;
1461 egl_connection_t* const cnx = &gEGLImpl;
1462 if (cnx->dso && cnx->egl.eglCreateImageKHR) {
1463 result = cnx->egl.eglCreateImageKHR(
1464 dp->disp.dpy,
1465 c ? c->context : EGL_NO_CONTEXT,
1466 target, buffer, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001467 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001468 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001469}
1470
1471EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
1472{
1473 clearError();
1474
Jesse Hallb29e5e82012-04-04 16:53:42 -07001475 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001476 if (!dp) return EGL_FALSE;
1477
Steven Holte646a5c52012-06-04 20:02:11 -07001478 EGLBoolean result = EGL_FALSE;
Mathias Agopianada798b2012-02-13 17:09:30 -08001479 egl_connection_t* const cnx = &gEGLImpl;
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001480 if (cnx->dso && cnx->egl.eglDestroyImageKHR) {
Steven Holte646a5c52012-06-04 20:02:11 -07001481 result = cnx->egl.eglDestroyImageKHR(dp->disp.dpy, img);
Mathias Agopian518ec112011-05-13 16:21:08 -07001482 }
Steven Holte646a5c52012-06-04 20:02:11 -07001483 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001484}
1485
1486// ----------------------------------------------------------------------------
1487// EGL_EGLEXT_VERSION 5
1488// ----------------------------------------------------------------------------
1489
1490
1491EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
1492{
1493 clearError();
1494
Jesse Hallb29e5e82012-04-04 16:53:42 -07001495 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001496 if (!dp) return EGL_NO_SYNC_KHR;
1497
Mathias Agopian518ec112011-05-13 16:21:08 -07001498 EGLSyncKHR result = EGL_NO_SYNC_KHR;
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001499 egl_connection_t* const cnx = &gEGLImpl;
1500 if (cnx->dso && cnx->egl.eglCreateSyncKHR) {
1501 result = cnx->egl.eglCreateSyncKHR(dp->disp.dpy, type, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001502 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001503 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001504}
1505
1506EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
1507{
1508 clearError();
1509
Jesse Hallb29e5e82012-04-04 16:53:42 -07001510 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001511 if (!dp) return EGL_FALSE;
1512
Mathias Agopian518ec112011-05-13 16:21:08 -07001513 EGLBoolean result = EGL_FALSE;
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001514 egl_connection_t* const cnx = &gEGLImpl;
1515 if (cnx->dso && cnx->egl.eglDestroySyncKHR) {
1516 result = cnx->egl.eglDestroySyncKHR(dp->disp.dpy, sync);
Mathias Agopian518ec112011-05-13 16:21:08 -07001517 }
1518 return result;
1519}
1520
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -07001521EGLBoolean eglSignalSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode) {
1522 clearError();
1523
1524 const egl_display_ptr dp = validate_display(dpy);
1525 if (!dp) return EGL_FALSE;
1526
1527 EGLBoolean result = EGL_FALSE;
1528 egl_connection_t* const cnx = &gEGLImpl;
1529 if (cnx->dso && cnx->egl.eglSignalSyncKHR) {
1530 result = cnx->egl.eglSignalSyncKHR(
1531 dp->disp.dpy, sync, mode);
1532 }
1533 return result;
1534}
1535
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001536EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync,
1537 EGLint flags, EGLTimeKHR timeout)
Mathias Agopian518ec112011-05-13 16:21:08 -07001538{
1539 clearError();
1540
Jesse Hallb29e5e82012-04-04 16:53:42 -07001541 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001542 if (!dp) return EGL_FALSE;
1543
Mathias Agopian737b8962017-02-24 14:32:05 -08001544 EGLint result = EGL_FALSE;
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001545 egl_connection_t* const cnx = &gEGLImpl;
1546 if (cnx->dso && cnx->egl.eglClientWaitSyncKHR) {
1547 result = cnx->egl.eglClientWaitSyncKHR(
1548 dp->disp.dpy, sync, flags, timeout);
Mathias Agopian518ec112011-05-13 16:21:08 -07001549 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001550 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001551}
1552
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001553EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync,
1554 EGLint attribute, EGLint *value)
Mathias Agopian518ec112011-05-13 16:21:08 -07001555{
1556 clearError();
1557
Jesse Hallb29e5e82012-04-04 16:53:42 -07001558 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001559 if (!dp) return EGL_FALSE;
1560
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001561 EGLBoolean result = EGL_FALSE;
1562 egl_connection_t* const cnx = &gEGLImpl;
1563 if (cnx->dso && cnx->egl.eglGetSyncAttribKHR) {
1564 result = cnx->egl.eglGetSyncAttribKHR(
1565 dp->disp.dpy, sync, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -07001566 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001567 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001568}
1569
Season Li000d88f2015-07-01 11:39:40 -07001570EGLStreamKHR eglCreateStreamKHR(EGLDisplay dpy, const EGLint *attrib_list)
1571{
1572 clearError();
1573
1574 const egl_display_ptr dp = validate_display(dpy);
1575 if (!dp) return EGL_NO_STREAM_KHR;
1576
1577 EGLStreamKHR result = EGL_NO_STREAM_KHR;
1578 egl_connection_t* const cnx = &gEGLImpl;
1579 if (cnx->dso && cnx->egl.eglCreateStreamKHR) {
1580 result = cnx->egl.eglCreateStreamKHR(
1581 dp->disp.dpy, attrib_list);
1582 }
1583 return result;
1584}
1585
1586EGLBoolean eglDestroyStreamKHR(EGLDisplay dpy, EGLStreamKHR stream)
1587{
1588 clearError();
1589
1590 const egl_display_ptr dp = validate_display(dpy);
1591 if (!dp) return EGL_FALSE;
1592
1593 EGLBoolean result = EGL_FALSE;
1594 egl_connection_t* const cnx = &gEGLImpl;
1595 if (cnx->dso && cnx->egl.eglDestroyStreamKHR) {
1596 result = cnx->egl.eglDestroyStreamKHR(
1597 dp->disp.dpy, stream);
1598 }
1599 return result;
1600}
1601
1602EGLBoolean eglStreamAttribKHR(EGLDisplay dpy, EGLStreamKHR stream,
1603 EGLenum attribute, EGLint value)
1604{
1605 clearError();
1606
1607 const egl_display_ptr dp = validate_display(dpy);
1608 if (!dp) return EGL_FALSE;
1609
1610 EGLBoolean result = EGL_FALSE;
1611 egl_connection_t* const cnx = &gEGLImpl;
1612 if (cnx->dso && cnx->egl.eglStreamAttribKHR) {
1613 result = cnx->egl.eglStreamAttribKHR(
1614 dp->disp.dpy, stream, attribute, value);
1615 }
1616 return result;
1617}
1618
1619EGLBoolean eglQueryStreamKHR(EGLDisplay dpy, EGLStreamKHR stream,
1620 EGLenum attribute, EGLint *value)
1621{
1622 clearError();
1623
1624 const egl_display_ptr dp = validate_display(dpy);
1625 if (!dp) return EGL_FALSE;
1626
1627 EGLBoolean result = EGL_FALSE;
1628 egl_connection_t* const cnx = &gEGLImpl;
1629 if (cnx->dso && cnx->egl.eglQueryStreamKHR) {
1630 result = cnx->egl.eglQueryStreamKHR(
1631 dp->disp.dpy, stream, attribute, value);
1632 }
1633 return result;
1634}
1635
1636EGLBoolean eglQueryStreamu64KHR(EGLDisplay dpy, EGLStreamKHR stream,
1637 EGLenum attribute, EGLuint64KHR *value)
1638{
1639 clearError();
1640
1641 const egl_display_ptr dp = validate_display(dpy);
1642 if (!dp) return EGL_FALSE;
1643
1644 EGLBoolean result = EGL_FALSE;
1645 egl_connection_t* const cnx = &gEGLImpl;
1646 if (cnx->dso && cnx->egl.eglQueryStreamu64KHR) {
1647 result = cnx->egl.eglQueryStreamu64KHR(
1648 dp->disp.dpy, stream, attribute, value);
1649 }
1650 return result;
1651}
1652
1653EGLBoolean eglQueryStreamTimeKHR(EGLDisplay dpy, EGLStreamKHR stream,
1654 EGLenum attribute, EGLTimeKHR *value)
1655{
1656 clearError();
1657
1658 const egl_display_ptr dp = validate_display(dpy);
1659 if (!dp) return EGL_FALSE;
1660
1661 EGLBoolean result = EGL_FALSE;
1662 egl_connection_t* const cnx = &gEGLImpl;
1663 if (cnx->dso && cnx->egl.eglQueryStreamTimeKHR) {
1664 result = cnx->egl.eglQueryStreamTimeKHR(
1665 dp->disp.dpy, stream, attribute, value);
1666 }
1667 return result;
1668}
1669
1670EGLSurface eglCreateStreamProducerSurfaceKHR(EGLDisplay dpy, EGLConfig config,
1671 EGLStreamKHR stream, const EGLint *attrib_list)
1672{
1673 clearError();
1674
1675 egl_display_ptr dp = validate_display(dpy);
1676 if (!dp) return EGL_NO_SURFACE;
1677
1678 egl_connection_t* const cnx = &gEGLImpl;
1679 if (cnx->dso && cnx->egl.eglCreateStreamProducerSurfaceKHR) {
1680 EGLSurface surface = cnx->egl.eglCreateStreamProducerSurfaceKHR(
1681 dp->disp.dpy, config, stream, attrib_list);
1682 if (surface != EGL_NO_SURFACE) {
1683 egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL,
1684 surface, cnx);
1685 return s;
1686 }
1687 }
1688 return EGL_NO_SURFACE;
1689}
1690
1691EGLBoolean eglStreamConsumerGLTextureExternalKHR(EGLDisplay dpy,
1692 EGLStreamKHR stream)
1693{
1694 clearError();
1695
1696 const egl_display_ptr dp = validate_display(dpy);
1697 if (!dp) return EGL_FALSE;
1698
1699 EGLBoolean result = EGL_FALSE;
1700 egl_connection_t* const cnx = &gEGLImpl;
1701 if (cnx->dso && cnx->egl.eglStreamConsumerGLTextureExternalKHR) {
1702 result = cnx->egl.eglStreamConsumerGLTextureExternalKHR(
1703 dp->disp.dpy, stream);
1704 }
1705 return result;
1706}
1707
1708EGLBoolean eglStreamConsumerAcquireKHR(EGLDisplay dpy,
1709 EGLStreamKHR stream)
1710{
1711 clearError();
1712
1713 const egl_display_ptr dp = validate_display(dpy);
1714 if (!dp) return EGL_FALSE;
1715
1716 EGLBoolean result = EGL_FALSE;
1717 egl_connection_t* const cnx = &gEGLImpl;
1718 if (cnx->dso && cnx->egl.eglStreamConsumerAcquireKHR) {
1719 result = cnx->egl.eglStreamConsumerAcquireKHR(
1720 dp->disp.dpy, stream);
1721 }
1722 return result;
1723}
1724
1725EGLBoolean eglStreamConsumerReleaseKHR(EGLDisplay dpy,
1726 EGLStreamKHR stream)
1727{
1728 clearError();
1729
1730 const egl_display_ptr dp = validate_display(dpy);
1731 if (!dp) return EGL_FALSE;
1732
1733 EGLBoolean result = EGL_FALSE;
1734 egl_connection_t* const cnx = &gEGLImpl;
1735 if (cnx->dso && cnx->egl.eglStreamConsumerReleaseKHR) {
1736 result = cnx->egl.eglStreamConsumerReleaseKHR(
1737 dp->disp.dpy, stream);
1738 }
1739 return result;
1740}
1741
1742EGLNativeFileDescriptorKHR eglGetStreamFileDescriptorKHR(
1743 EGLDisplay dpy, EGLStreamKHR stream)
1744{
1745 clearError();
1746
1747 const egl_display_ptr dp = validate_display(dpy);
1748 if (!dp) return EGL_NO_FILE_DESCRIPTOR_KHR;
1749
1750 EGLNativeFileDescriptorKHR result = EGL_NO_FILE_DESCRIPTOR_KHR;
1751 egl_connection_t* const cnx = &gEGLImpl;
1752 if (cnx->dso && cnx->egl.eglGetStreamFileDescriptorKHR) {
1753 result = cnx->egl.eglGetStreamFileDescriptorKHR(
1754 dp->disp.dpy, stream);
1755 }
1756 return result;
1757}
1758
1759EGLStreamKHR eglCreateStreamFromFileDescriptorKHR(
1760 EGLDisplay dpy, EGLNativeFileDescriptorKHR file_descriptor)
1761{
1762 clearError();
1763
1764 const egl_display_ptr dp = validate_display(dpy);
1765 if (!dp) return EGL_NO_STREAM_KHR;
1766
1767 EGLStreamKHR result = EGL_NO_STREAM_KHR;
1768 egl_connection_t* const cnx = &gEGLImpl;
1769 if (cnx->dso && cnx->egl.eglCreateStreamFromFileDescriptorKHR) {
1770 result = cnx->egl.eglCreateStreamFromFileDescriptorKHR(
1771 dp->disp.dpy, file_descriptor);
1772 }
1773 return result;
1774}
1775
Mathias Agopian518ec112011-05-13 16:21:08 -07001776// ----------------------------------------------------------------------------
Mathias Agopian2bb71682013-03-27 17:32:41 -07001777// EGL_EGLEXT_VERSION 15
1778// ----------------------------------------------------------------------------
1779
1780EGLint eglWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags) {
1781 clearError();
1782 const egl_display_ptr dp = validate_display(dpy);
1783 if (!dp) return EGL_FALSE;
1784 EGLint result = EGL_FALSE;
1785 egl_connection_t* const cnx = &gEGLImpl;
1786 if (cnx->dso && cnx->egl.eglWaitSyncKHR) {
1787 result = cnx->egl.eglWaitSyncKHR(dp->disp.dpy, sync, flags);
1788 }
1789 return result;
1790}
1791
1792// ----------------------------------------------------------------------------
Mathias Agopian518ec112011-05-13 16:21:08 -07001793// ANDROID extensions
1794// ----------------------------------------------------------------------------
1795
Jamie Gennis331841b2012-09-06 14:52:00 -07001796EGLint eglDupNativeFenceFDANDROID(EGLDisplay dpy, EGLSyncKHR sync)
1797{
1798 clearError();
1799
1800 const egl_display_ptr dp = validate_display(dpy);
1801 if (!dp) return EGL_NO_NATIVE_FENCE_FD_ANDROID;
1802
1803 EGLint result = EGL_NO_NATIVE_FENCE_FD_ANDROID;
1804 egl_connection_t* const cnx = &gEGLImpl;
1805 if (cnx->dso && cnx->egl.eglDupNativeFenceFDANDROID) {
1806 result = cnx->egl.eglDupNativeFenceFDANDROID(dp->disp.dpy, sync);
1807 }
1808 return result;
1809}
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001810
Andy McFadden72841452013-03-01 16:25:32 -08001811EGLBoolean eglPresentationTimeANDROID(EGLDisplay dpy, EGLSurface surface,
1812 EGLnsecsANDROID time)
1813{
1814 clearError();
1815
1816 const egl_display_ptr dp = validate_display(dpy);
1817 if (!dp) {
1818 return EGL_FALSE;
1819 }
1820
1821 SurfaceRef _s(dp.get(), surface);
1822 if (!_s.get()) {
1823 setError(EGL_BAD_SURFACE, EGL_FALSE);
1824 return EGL_FALSE;
1825 }
1826
1827 egl_surface_t const * const s = get_surface(surface);
1828 native_window_set_buffers_timestamp(s->win.get(), time);
1829
1830 return EGL_TRUE;
1831}
1832
Craig Donner60761072017-01-27 12:30:44 -08001833EGLClientBuffer eglGetNativeClientBufferANDROID(const AHardwareBuffer *buffer) {
1834 clearError();
Craig Donner60761072017-01-27 12:30:44 -08001835 if (!buffer) return setError(EGL_BAD_PARAMETER, (EGLClientBuffer)0);
Mathias Agopian61963402017-02-24 16:38:15 -08001836 return const_cast<ANativeWindowBuffer *>(AHardwareBuffer_to_ANativeWindowBuffer(buffer));
Craig Donner60761072017-01-27 12:30:44 -08001837}
1838
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001839// ----------------------------------------------------------------------------
1840// NVIDIA extensions
1841// ----------------------------------------------------------------------------
1842EGLuint64NV eglGetSystemTimeFrequencyNV()
1843{
1844 clearError();
1845
1846 if (egl_init_drivers() == EGL_FALSE) {
Mathias Agopian737b8962017-02-24 14:32:05 -08001847 return setError(EGL_BAD_PARAMETER, (EGLuint64NV)EGL_FALSE);
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001848 }
1849
1850 EGLuint64NV ret = 0;
Mathias Agopianada798b2012-02-13 17:09:30 -08001851 egl_connection_t* const cnx = &gEGLImpl;
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001852
Mathias Agopianada798b2012-02-13 17:09:30 -08001853 if (cnx->dso && cnx->egl.eglGetSystemTimeFrequencyNV) {
1854 return cnx->egl.eglGetSystemTimeFrequencyNV();
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001855 }
1856
Mathias Agopian737b8962017-02-24 14:32:05 -08001857 return setErrorQuiet(EGL_BAD_DISPLAY, (EGLuint64NV)0);
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001858}
1859
1860EGLuint64NV eglGetSystemTimeNV()
1861{
1862 clearError();
1863
1864 if (egl_init_drivers() == EGL_FALSE) {
Mathias Agopian737b8962017-02-24 14:32:05 -08001865 return setError(EGL_BAD_PARAMETER, (EGLuint64NV)EGL_FALSE);
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001866 }
1867
1868 EGLuint64NV ret = 0;
Mathias Agopianada798b2012-02-13 17:09:30 -08001869 egl_connection_t* const cnx = &gEGLImpl;
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001870
Mathias Agopianada798b2012-02-13 17:09:30 -08001871 if (cnx->dso && cnx->egl.eglGetSystemTimeNV) {
1872 return cnx->egl.eglGetSystemTimeNV();
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001873 }
1874
Mathias Agopian737b8962017-02-24 14:32:05 -08001875 return setErrorQuiet(EGL_BAD_DISPLAY, (EGLuint64NV)0);
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001876}
Dan Stozaa894d082015-02-19 15:27:36 -08001877
1878// ----------------------------------------------------------------------------
1879// Partial update extension
1880// ----------------------------------------------------------------------------
1881EGLBoolean eglSetDamageRegionKHR(EGLDisplay dpy, EGLSurface surface,
1882 EGLint *rects, EGLint n_rects)
1883{
1884 clearError();
1885
1886 const egl_display_ptr dp = validate_display(dpy);
1887 if (!dp) {
1888 setError(EGL_BAD_DISPLAY, EGL_FALSE);
1889 return EGL_FALSE;
1890 }
1891
1892 SurfaceRef _s(dp.get(), surface);
1893 if (!_s.get()) {
1894 setError(EGL_BAD_SURFACE, EGL_FALSE);
1895 return EGL_FALSE;
1896 }
1897
1898 egl_surface_t const * const s = get_surface(surface);
1899 if (s->cnx->egl.eglSetDamageRegionKHR) {
1900 return s->cnx->egl.eglSetDamageRegionKHR(dp->disp.dpy, s->surface,
1901 rects, n_rects);
1902 }
1903
1904 return EGL_FALSE;
1905}
Pablo Ceballosc18be292016-05-31 14:55:42 -07001906
Brian Anderson1049d1d2016-12-16 17:25:57 -08001907EGLBoolean eglGetNextFrameIdANDROID(EGLDisplay dpy, EGLSurface surface,
1908 EGLuint64KHR *frameId) {
1909 clearError();
1910
1911 const egl_display_ptr dp = validate_display(dpy);
1912 if (!dp) {
Mathias Agopian737b8962017-02-24 14:32:05 -08001913 return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
Brian Anderson1049d1d2016-12-16 17:25:57 -08001914 }
1915
1916 SurfaceRef _s(dp.get(), surface);
1917 if (!_s.get()) {
Mathias Agopian737b8962017-02-24 14:32:05 -08001918 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Brian Anderson1049d1d2016-12-16 17:25:57 -08001919 }
1920
1921 egl_surface_t const * const s = get_surface(surface);
1922
1923 if (!s->win.get()) {
Mathias Agopian737b8962017-02-24 14:32:05 -08001924 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Brian Anderson1049d1d2016-12-16 17:25:57 -08001925 }
1926
1927 uint64_t nextFrameId = 0;
1928 status_t ret = native_window_get_next_frame_id(s->win.get(), &nextFrameId);
1929
1930 if (ret != NO_ERROR) {
1931 // This should not happen. Return an error that is not in the spec
1932 // so it's obvious something is very wrong.
1933 ALOGE("eglGetNextFrameId: Unexpected error.");
Mathias Agopian737b8962017-02-24 14:32:05 -08001934 return setError(EGL_NOT_INITIALIZED, (EGLBoolean)EGL_FALSE);
Brian Anderson1049d1d2016-12-16 17:25:57 -08001935 }
1936
1937 *frameId = nextFrameId;
1938 return EGL_TRUE;
1939}
1940
Brian Anderson0a61b0c2016-12-07 14:55:56 -08001941EGLBoolean eglGetCompositorTimingANDROID(EGLDisplay dpy, EGLSurface surface,
1942 EGLint numTimestamps, const EGLint *names, EGLnsecsANDROID *values)
1943{
1944 clearError();
1945
1946 const egl_display_ptr dp = validate_display(dpy);
1947 if (!dp) {
Mathias Agopian737b8962017-02-24 14:32:05 -08001948 return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
Brian Anderson0a61b0c2016-12-07 14:55:56 -08001949 }
1950
1951 SurfaceRef _s(dp.get(), surface);
1952 if (!_s.get()) {
Mathias Agopian737b8962017-02-24 14:32:05 -08001953 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Brian Anderson0a61b0c2016-12-07 14:55:56 -08001954 }
1955
1956 egl_surface_t const * const s = get_surface(surface);
1957
1958 if (!s->win.get()) {
Mathias Agopian737b8962017-02-24 14:32:05 -08001959 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Brian Anderson0a61b0c2016-12-07 14:55:56 -08001960 }
1961
1962 nsecs_t* compositeDeadline = nullptr;
1963 nsecs_t* compositeInterval = nullptr;
1964 nsecs_t* compositeToPresentLatency = nullptr;
1965
1966 for (int i = 0; i < numTimestamps; i++) {
1967 switch (names[i]) {
1968 case EGL_COMPOSITE_DEADLINE_ANDROID:
1969 compositeDeadline = &values[i];
1970 break;
1971 case EGL_COMPOSITE_INTERVAL_ANDROID:
1972 compositeInterval = &values[i];
1973 break;
1974 case EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID:
1975 compositeToPresentLatency = &values[i];
1976 break;
1977 default:
Mathias Agopian737b8962017-02-24 14:32:05 -08001978 return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE);
Brian Anderson0a61b0c2016-12-07 14:55:56 -08001979 }
1980 }
1981
1982 status_t ret = native_window_get_compositor_timing(s->win.get(),
1983 compositeDeadline, compositeInterval, compositeToPresentLatency);
1984
1985 switch (ret) {
1986 case NO_ERROR:
1987 return EGL_TRUE;
1988 case INVALID_OPERATION:
Mathias Agopian737b8962017-02-24 14:32:05 -08001989 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Brian Anderson0a61b0c2016-12-07 14:55:56 -08001990 default:
1991 // This should not happen. Return an error that is not in the spec
1992 // so it's obvious something is very wrong.
1993 ALOGE("eglGetCompositorTiming: Unexpected error.");
Mathias Agopian737b8962017-02-24 14:32:05 -08001994 return setError(EGL_NOT_INITIALIZED, (EGLBoolean)EGL_FALSE);
Brian Anderson0a61b0c2016-12-07 14:55:56 -08001995 }
1996}
1997
1998EGLBoolean eglGetCompositorTimingSupportedANDROID(
1999 EGLDisplay dpy, EGLSurface surface, EGLint name)
2000{
2001 clearError();
2002
2003 const egl_display_ptr dp = validate_display(dpy);
2004 if (!dp) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002005 return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002006 }
2007
2008 SurfaceRef _s(dp.get(), surface);
2009 if (!_s.get()) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002010 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002011 }
2012
2013 egl_surface_t const * const s = get_surface(surface);
2014
2015 ANativeWindow* window = s->win.get();
2016 if (!window) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002017 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002018 }
2019
2020 switch (name) {
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002021 case EGL_COMPOSITE_DEADLINE_ANDROID:
2022 case EGL_COMPOSITE_INTERVAL_ANDROID:
2023 case EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID:
2024 return EGL_TRUE;
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002025 default:
2026 return EGL_FALSE;
2027 }
2028}
2029
Pablo Ceballosc18be292016-05-31 14:55:42 -07002030EGLBoolean eglGetFrameTimestampsANDROID(EGLDisplay dpy, EGLSurface surface,
Brian Anderson1049d1d2016-12-16 17:25:57 -08002031 EGLuint64KHR frameId, EGLint numTimestamps, const EGLint *timestamps,
Pablo Ceballosc18be292016-05-31 14:55:42 -07002032 EGLnsecsANDROID *values)
2033{
2034 clearError();
2035
2036 const egl_display_ptr dp = validate_display(dpy);
2037 if (!dp) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002038 return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
Pablo Ceballosc18be292016-05-31 14:55:42 -07002039 }
2040
2041 SurfaceRef _s(dp.get(), surface);
2042 if (!_s.get()) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002043 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Pablo Ceballosc18be292016-05-31 14:55:42 -07002044 }
2045
2046 egl_surface_t const * const s = get_surface(surface);
2047
Brian Anderson7c3ba8a2016-07-25 12:48:08 -07002048 if (!s->win.get()) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002049 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Pablo Ceballosc18be292016-05-31 14:55:42 -07002050 }
2051
Brian Andersondbd0ea82016-07-22 09:38:59 -07002052 nsecs_t* requestedPresentTime = nullptr;
Pablo Ceballosc18be292016-05-31 14:55:42 -07002053 nsecs_t* acquireTime = nullptr;
Brian Andersonf7fd56a2016-09-02 10:10:04 -07002054 nsecs_t* latchTime = nullptr;
2055 nsecs_t* firstRefreshStartTime = nullptr;
Brian Andersonb04c6f02016-10-21 12:57:46 -07002056 nsecs_t* gpuCompositionDoneTime = nullptr;
Brian Andersonf7fd56a2016-09-02 10:10:04 -07002057 nsecs_t* lastRefreshStartTime = nullptr;
Brian Anderson069b3652016-07-22 10:32:47 -07002058 nsecs_t* displayPresentTime = nullptr;
Pablo Ceballosc18be292016-05-31 14:55:42 -07002059 nsecs_t* displayRetireTime = nullptr;
Brian Andersonf7fd56a2016-09-02 10:10:04 -07002060 nsecs_t* dequeueReadyTime = nullptr;
Pablo Ceballosc18be292016-05-31 14:55:42 -07002061 nsecs_t* releaseTime = nullptr;
2062
2063 for (int i = 0; i < numTimestamps; i++) {
2064 switch (timestamps[i]) {
Brian Andersondbd0ea82016-07-22 09:38:59 -07002065 case EGL_REQUESTED_PRESENT_TIME_ANDROID:
2066 requestedPresentTime = &values[i];
Pablo Ceballosc18be292016-05-31 14:55:42 -07002067 break;
2068 case EGL_RENDERING_COMPLETE_TIME_ANDROID:
2069 acquireTime = &values[i];
2070 break;
Brian Andersonf7fd56a2016-09-02 10:10:04 -07002071 case EGL_COMPOSITION_LATCH_TIME_ANDROID:
2072 latchTime = &values[i];
Pablo Ceballosc18be292016-05-31 14:55:42 -07002073 break;
Brian Andersonf7fd56a2016-09-02 10:10:04 -07002074 case EGL_FIRST_COMPOSITION_START_TIME_ANDROID:
2075 firstRefreshStartTime = &values[i];
2076 break;
2077 case EGL_LAST_COMPOSITION_START_TIME_ANDROID:
2078 lastRefreshStartTime = &values[i];
2079 break;
Brian Andersonb04c6f02016-10-21 12:57:46 -07002080 case EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID:
2081 gpuCompositionDoneTime = &values[i];
Pablo Ceballosc18be292016-05-31 14:55:42 -07002082 break;
Brian Anderson069b3652016-07-22 10:32:47 -07002083 case EGL_DISPLAY_PRESENT_TIME_ANDROID:
2084 displayPresentTime = &values[i];
2085 break;
Pablo Ceballosc18be292016-05-31 14:55:42 -07002086 case EGL_DISPLAY_RETIRE_TIME_ANDROID:
2087 displayRetireTime = &values[i];
2088 break;
Brian Andersonf7fd56a2016-09-02 10:10:04 -07002089 case EGL_DEQUEUE_READY_TIME_ANDROID:
2090 dequeueReadyTime = &values[i];
2091 break;
Pablo Ceballosc18be292016-05-31 14:55:42 -07002092 case EGL_READS_DONE_TIME_ANDROID:
2093 releaseTime = &values[i];
2094 break;
2095 default:
Mathias Agopian737b8962017-02-24 14:32:05 -08002096 return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE);
Pablo Ceballosc18be292016-05-31 14:55:42 -07002097 }
2098 }
2099
Brian Anderson1049d1d2016-12-16 17:25:57 -08002100 status_t ret = native_window_get_frame_timestamps(s->win.get(), frameId,
Brian Andersonf7fd56a2016-09-02 10:10:04 -07002101 requestedPresentTime, acquireTime, latchTime, firstRefreshStartTime,
Brian Andersonb04c6f02016-10-21 12:57:46 -07002102 lastRefreshStartTime, gpuCompositionDoneTime, displayPresentTime,
Brian Andersonf7fd56a2016-09-02 10:10:04 -07002103 displayRetireTime, dequeueReadyTime, releaseTime);
Pablo Ceballosc18be292016-05-31 14:55:42 -07002104
Brian Anderson069b3652016-07-22 10:32:47 -07002105 switch (ret) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002106 case NO_ERROR:
2107 return EGL_TRUE;
2108 case NAME_NOT_FOUND:
2109 return setError(EGL_BAD_ACCESS, (EGLBoolean)EGL_FALSE);
2110 case INVALID_OPERATION:
2111 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
2112 case BAD_VALUE:
2113 return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE);
2114 default:
2115 // This should not happen. Return an error that is not in the spec
2116 // so it's obvious something is very wrong.
2117 ALOGE("eglGetFrameTimestamps: Unexpected error.");
2118 return setError(EGL_NOT_INITIALIZED, (EGLBoolean)EGL_FALSE);
Pablo Ceballosc18be292016-05-31 14:55:42 -07002119 }
Pablo Ceballosc18be292016-05-31 14:55:42 -07002120}
2121
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002122EGLBoolean eglGetFrameTimestampSupportedANDROID(
2123 EGLDisplay dpy, EGLSurface surface, EGLint timestamp)
Pablo Ceballosc18be292016-05-31 14:55:42 -07002124{
2125 clearError();
2126
2127 const egl_display_ptr dp = validate_display(dpy);
2128 if (!dp) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002129 return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
Pablo Ceballosc18be292016-05-31 14:55:42 -07002130 }
2131
2132 SurfaceRef _s(dp.get(), surface);
2133 if (!_s.get()) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002134 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Brian Anderson069b3652016-07-22 10:32:47 -07002135 }
2136
2137 egl_surface_t const * const s = get_surface(surface);
2138
2139 ANativeWindow* window = s->win.get();
2140 if (!window) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002141 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Pablo Ceballosc18be292016-05-31 14:55:42 -07002142 }
2143
2144 switch (timestamp) {
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002145 case EGL_COMPOSITE_DEADLINE_ANDROID:
2146 case EGL_COMPOSITE_INTERVAL_ANDROID:
2147 case EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID:
Brian Andersondbd0ea82016-07-22 09:38:59 -07002148 case EGL_REQUESTED_PRESENT_TIME_ANDROID:
Pablo Ceballosc18be292016-05-31 14:55:42 -07002149 case EGL_RENDERING_COMPLETE_TIME_ANDROID:
Brian Andersonf7fd56a2016-09-02 10:10:04 -07002150 case EGL_COMPOSITION_LATCH_TIME_ANDROID:
2151 case EGL_FIRST_COMPOSITION_START_TIME_ANDROID:
2152 case EGL_LAST_COMPOSITION_START_TIME_ANDROID:
Brian Andersonb04c6f02016-10-21 12:57:46 -07002153 case EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID:
Brian Andersonf7fd56a2016-09-02 10:10:04 -07002154 case EGL_DEQUEUE_READY_TIME_ANDROID:
Pablo Ceballosc18be292016-05-31 14:55:42 -07002155 case EGL_READS_DONE_TIME_ANDROID:
2156 return EGL_TRUE;
Brian Anderson069b3652016-07-22 10:32:47 -07002157 case EGL_DISPLAY_PRESENT_TIME_ANDROID: {
2158 int value = 0;
Mathias Agopian737b8962017-02-24 14:32:05 -08002159 window->query(window, NATIVE_WINDOW_FRAME_TIMESTAMPS_SUPPORTS_PRESENT, &value);
Brian Anderson069b3652016-07-22 10:32:47 -07002160 return value == 0 ? EGL_FALSE : EGL_TRUE;
2161 }
2162 case EGL_DISPLAY_RETIRE_TIME_ANDROID: {
2163 int value = 0;
Mathias Agopian737b8962017-02-24 14:32:05 -08002164 window->query(window, NATIVE_WINDOW_FRAME_TIMESTAMPS_SUPPORTS_RETIRE, &value);
Brian Anderson069b3652016-07-22 10:32:47 -07002165 return value == 0 ? EGL_FALSE : EGL_TRUE;
2166 }
Pablo Ceballosc18be292016-05-31 14:55:42 -07002167 default:
2168 return EGL_FALSE;
2169 }
2170}