blob: b00d4013bcb31c5119f812f6ad761d61ddbaaae2 [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
Mathias Agopian65421432017-03-08 11:49:05 -080036#include <condition_variable>
37#include <deque>
38#include <mutex>
39#include <unordered_map>
40#include <string>
41#include <thread>
Mathias Agopian518ec112011-05-13 16:21:08 -070042
Mathias Agopian39c24a22013-04-04 23:17:56 -070043#include "../egl_impl.h"
Mathias Agopian518ec112011-05-13 16:21:08 -070044
45#include "egl_display.h"
Mathias Agopian518ec112011-05-13 16:21:08 -070046#include "egl_object.h"
47#include "egl_tls.h"
Mathias Agopian65421432017-03-08 11:49:05 -080048#include "egl_trace.h"
Mathias Agopian518ec112011-05-13 16:21:08 -070049
50using namespace android;
51
52// ----------------------------------------------------------------------------
53
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070054namespace android {
55
Mathias Agopian65421432017-03-08 11:49:05 -080056using nsecs_t = int64_t;
57
Mathias Agopian518ec112011-05-13 16:21:08 -070058struct extention_map_t {
59 const char* name;
60 __eglMustCastToProperFunctionPointerType address;
61};
62
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070063/*
Jesse Hall21558da2013-08-06 15:31:22 -070064 * This is the list of EGL extensions exposed to applications.
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070065 *
Jesse Hall21558da2013-08-06 15:31:22 -070066 * Some of them (gBuiltinExtensionString) are implemented entirely in this EGL
67 * wrapper and are always available.
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070068 *
Jesse Hall21558da2013-08-06 15:31:22 -070069 * The rest (gExtensionString) depend on support in the EGL driver, and are
70 * only available if the driver supports them. However, some of these must be
71 * supported because they are used by the Android system itself; these are
Pablo Ceballos02b05da2016-02-02 17:53:18 -080072 * listed as mandatory below and are required by the CDD. The system *assumes*
Jesse Hall21558da2013-08-06 15:31:22 -070073 * the mandatory extensions are present and may not function properly if some
74 * are missing.
75 *
76 * NOTE: Both strings MUST have a single space as the last character.
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070077 */
Mathias Agopian737b8962017-02-24 14:32:05 -080078
Mathias Agopian311b4792017-02-28 15:00:49 -080079extern char const * const gBuiltinExtensionString;
80extern char const * const gExtensionString;
Mathias Agopian737b8962017-02-24 14:32:05 -080081
Mathias Agopian311b4792017-02-28 15:00:49 -080082char const * const gBuiltinExtensionString =
Jesse Hall21558da2013-08-06 15:31:22 -070083 "EGL_KHR_get_all_proc_addresses "
84 "EGL_ANDROID_presentation_time "
Dan Stozaa894d082015-02-19 15:27:36 -080085 "EGL_KHR_swap_buffers_with_damage "
Craig Donner60761072017-01-27 12:30:44 -080086 "EGL_ANDROID_get_native_client_buffer "
Pablo Ceballos02b05da2016-02-02 17:53:18 -080087 "EGL_ANDROID_front_buffer_auto_refresh "
Pablo Ceballosc18be292016-05-31 14:55:42 -070088 "EGL_ANDROID_get_frame_timestamps "
Jesse Hall21558da2013-08-06 15:31:22 -070089 ;
Mathias Agopian311b4792017-02-28 15:00:49 -080090
91char const * const gExtensionString =
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070092 "EGL_KHR_image " // mandatory
93 "EGL_KHR_image_base " // mandatory
94 "EGL_KHR_image_pixmap "
95 "EGL_KHR_lock_surface "
Jesse Hallc2e41222013-08-08 13:40:22 -070096 "EGL_KHR_gl_colorspace "
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070097 "EGL_KHR_gl_texture_2D_image "
Season Li000d88f2015-07-01 11:39:40 -070098 "EGL_KHR_gl_texture_3D_image "
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070099 "EGL_KHR_gl_texture_cubemap_image "
100 "EGL_KHR_gl_renderbuffer_image "
101 "EGL_KHR_reusable_sync "
102 "EGL_KHR_fence_sync "
Jamie Gennisf6d1c392013-04-25 18:48:41 -0700103 "EGL_KHR_create_context "
Season Li000d88f2015-07-01 11:39:40 -0700104 "EGL_KHR_config_attribs "
105 "EGL_KHR_surfaceless_context "
106 "EGL_KHR_stream "
107 "EGL_KHR_stream_fifo "
108 "EGL_KHR_stream_producer_eglsurface "
109 "EGL_KHR_stream_consumer_gltexture "
110 "EGL_KHR_stream_cross_process_fd "
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700111 "EGL_EXT_create_context_robustness "
112 "EGL_NV_system_time "
113 "EGL_ANDROID_image_native_buffer " // mandatory
Mathias Agopian2bb71682013-03-27 17:32:41 -0700114 "EGL_KHR_wait_sync " // strongly recommended
Jamie Gennisdbe92452013-09-23 17:22:10 -0700115 "EGL_ANDROID_recordable " // mandatory
Dan Stozaa894d082015-02-19 15:27:36 -0800116 "EGL_KHR_partial_update " // strongly recommended
Courtney Goeltzenleuchter0e4e3952016-11-16 13:53:40 -0700117 "EGL_EXT_pixel_format_float "
Dan Stozaa894d082015-02-19 15:27:36 -0800118 "EGL_EXT_buffer_age " // strongly recommended with partial_update
Jesse Hall408e59f2015-04-24 01:40:42 -0700119 "EGL_KHR_create_context_no_error "
Pablo Ceballosceb9ee72016-04-13 11:17:32 -0700120 "EGL_KHR_mutable_render_buffer "
Mika Isojärvif37864b2016-04-15 11:58:56 -0700121 "EGL_EXT_yuv_surface "
Craig Donneraec86972016-04-28 18:09:40 -0700122 "EGL_EXT_protected_content "
Christian Poetzscha7805f62016-12-01 16:34:39 +0000123 "EGL_IMG_context_priority "
Pyry Haulos51d53c42017-03-06 09:39:09 -0800124 "EGL_KHR_no_config_context "
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700125 ;
126
127// extensions not exposed to applications but used by the ANDROID system
128// "EGL_ANDROID_blob_cache " // strongly recommended
129// "EGL_IMG_hibernate_process " // optional
130// "EGL_ANDROID_native_fence_sync " // strongly recommended
131// "EGL_ANDROID_framebuffer_target " // mandatory for HWC 1.1
Jamie Gennisdbe92452013-09-23 17:22:10 -0700132// "EGL_ANDROID_image_crop " // optional
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700133
134/*
135 * EGL Extensions entry-points exposed to 3rd party applications
136 * (keep in sync with gExtensionString above)
137 *
138 */
139static const extention_map_t sExtensionMap[] = {
140 // EGL_KHR_lock_surface
Mathias Agopian518ec112011-05-13 16:21:08 -0700141 { "eglLockSurfaceKHR",
142 (__eglMustCastToProperFunctionPointerType)&eglLockSurfaceKHR },
143 { "eglUnlockSurfaceKHR",
144 (__eglMustCastToProperFunctionPointerType)&eglUnlockSurfaceKHR },
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700145
146 // EGL_KHR_image, EGL_KHR_image_base
Mathias Agopian518ec112011-05-13 16:21:08 -0700147 { "eglCreateImageKHR",
148 (__eglMustCastToProperFunctionPointerType)&eglCreateImageKHR },
149 { "eglDestroyImageKHR",
150 (__eglMustCastToProperFunctionPointerType)&eglDestroyImageKHR },
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700151
152 // EGL_KHR_reusable_sync, EGL_KHR_fence_sync
153 { "eglCreateSyncKHR",
154 (__eglMustCastToProperFunctionPointerType)&eglCreateSyncKHR },
155 { "eglDestroySyncKHR",
156 (__eglMustCastToProperFunctionPointerType)&eglDestroySyncKHR },
157 { "eglClientWaitSyncKHR",
158 (__eglMustCastToProperFunctionPointerType)&eglClientWaitSyncKHR },
159 { "eglSignalSyncKHR",
160 (__eglMustCastToProperFunctionPointerType)&eglSignalSyncKHR },
161 { "eglGetSyncAttribKHR",
162 (__eglMustCastToProperFunctionPointerType)&eglGetSyncAttribKHR },
163
164 // EGL_NV_system_time
Jonas Yang1c3d72a2011-08-26 20:04:39 +0800165 { "eglGetSystemTimeFrequencyNV",
166 (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeFrequencyNV },
167 { "eglGetSystemTimeNV",
168 (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeNV },
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700169
Mathias Agopian2bb71682013-03-27 17:32:41 -0700170 // EGL_KHR_wait_sync
171 { "eglWaitSyncKHR",
172 (__eglMustCastToProperFunctionPointerType)&eglWaitSyncKHR },
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700173
174 // EGL_ANDROID_presentation_time
175 { "eglPresentationTimeANDROID",
176 (__eglMustCastToProperFunctionPointerType)&eglPresentationTimeANDROID },
Dan Stozaa894d082015-02-19 15:27:36 -0800177
178 // EGL_KHR_swap_buffers_with_damage
179 { "eglSwapBuffersWithDamageKHR",
180 (__eglMustCastToProperFunctionPointerType)&eglSwapBuffersWithDamageKHR },
181
Craig Donner60761072017-01-27 12:30:44 -0800182 // EGL_ANDROID_get_native_client_buffer
183 { "eglGetNativeClientBufferANDROID",
184 (__eglMustCastToProperFunctionPointerType)&eglGetNativeClientBufferANDROID },
185
Dan Stozaa894d082015-02-19 15:27:36 -0800186 // EGL_KHR_partial_update
187 { "eglSetDamageRegionKHR",
188 (__eglMustCastToProperFunctionPointerType)&eglSetDamageRegionKHR },
Season Li000d88f2015-07-01 11:39:40 -0700189
190 { "eglCreateStreamKHR",
191 (__eglMustCastToProperFunctionPointerType)&eglCreateStreamKHR },
192 { "eglDestroyStreamKHR",
193 (__eglMustCastToProperFunctionPointerType)&eglDestroyStreamKHR },
194 { "eglStreamAttribKHR",
195 (__eglMustCastToProperFunctionPointerType)&eglStreamAttribKHR },
196 { "eglQueryStreamKHR",
197 (__eglMustCastToProperFunctionPointerType)&eglQueryStreamKHR },
198 { "eglQueryStreamu64KHR",
199 (__eglMustCastToProperFunctionPointerType)&eglQueryStreamu64KHR },
200 { "eglQueryStreamTimeKHR",
201 (__eglMustCastToProperFunctionPointerType)&eglQueryStreamTimeKHR },
202 { "eglCreateStreamProducerSurfaceKHR",
203 (__eglMustCastToProperFunctionPointerType)&eglCreateStreamProducerSurfaceKHR },
204 { "eglStreamConsumerGLTextureExternalKHR",
205 (__eglMustCastToProperFunctionPointerType)&eglStreamConsumerGLTextureExternalKHR },
206 { "eglStreamConsumerAcquireKHR",
207 (__eglMustCastToProperFunctionPointerType)&eglStreamConsumerAcquireKHR },
208 { "eglStreamConsumerReleaseKHR",
209 (__eglMustCastToProperFunctionPointerType)&eglStreamConsumerReleaseKHR },
210 { "eglGetStreamFileDescriptorKHR",
211 (__eglMustCastToProperFunctionPointerType)&eglGetStreamFileDescriptorKHR },
212 { "eglCreateStreamFromFileDescriptorKHR",
213 (__eglMustCastToProperFunctionPointerType)&eglCreateStreamFromFileDescriptorKHR },
Pablo Ceballosc18be292016-05-31 14:55:42 -0700214
215 // EGL_ANDROID_get_frame_timestamps
Brian Anderson1049d1d2016-12-16 17:25:57 -0800216 { "eglGetNextFrameIdANDROID",
217 (__eglMustCastToProperFunctionPointerType)&eglGetNextFrameIdANDROID },
Brian Anderson0a61b0c2016-12-07 14:55:56 -0800218 { "eglGetCompositorTimingANDROID",
219 (__eglMustCastToProperFunctionPointerType)&eglGetCompositorTimingANDROID },
220 { "eglGetCompositorTimingSupportedANDROID",
221 (__eglMustCastToProperFunctionPointerType)&eglGetCompositorTimingSupportedANDROID },
Pablo Ceballosc18be292016-05-31 14:55:42 -0700222 { "eglGetFrameTimestampsANDROID",
223 (__eglMustCastToProperFunctionPointerType)&eglGetFrameTimestampsANDROID },
Brian Anderson0a61b0c2016-12-07 14:55:56 -0800224 { "eglGetFrameTimestampSupportedANDROID",
225 (__eglMustCastToProperFunctionPointerType)&eglGetFrameTimestampSupportedANDROID },
Mathias Agopian518ec112011-05-13 16:21:08 -0700226};
227
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700228/*
229 * These extensions entry-points should not be exposed to applications.
230 * They're used internally by the Android EGL layer.
231 */
232#define FILTER_EXTENSIONS(procname) \
233 (!strcmp((procname), "eglSetBlobCacheFuncsANDROID") || \
234 !strcmp((procname), "eglHibernateProcessIMG") || \
235 !strcmp((procname), "eglAwakenProcessIMG") || \
236 !strcmp((procname), "eglDupNativeFenceFDANDROID"))
237
238
239
Mathias Agopian518ec112011-05-13 16:21:08 -0700240// accesses protected by sExtensionMapMutex
Mathias Agopian65421432017-03-08 11:49:05 -0800241static std::unordered_map<std::string, __eglMustCastToProperFunctionPointerType> sGLExtentionMap;
242
Mathias Agopian518ec112011-05-13 16:21:08 -0700243static int sGLExtentionSlot = 0;
244static pthread_mutex_t sExtensionMapMutex = PTHREAD_MUTEX_INITIALIZER;
245
246static void(*findProcAddress(const char* name,
247 const extention_map_t* map, size_t n))() {
248 for (uint32_t i=0 ; i<n ; i++) {
249 if (!strcmp(name, map[i].name)) {
250 return map[i].address;
251 }
252 }
253 return NULL;
254}
255
256// ----------------------------------------------------------------------------
257
Mathias Agopian518ec112011-05-13 16:21:08 -0700258extern void setGLHooksThreadSpecific(gl_hooks_t const *value);
259extern EGLBoolean egl_init_drivers();
260extern const __eglMustCastToProperFunctionPointerType gExtensionForwarders[MAX_NUMBER_OF_GL_EXTENSIONS];
Mathias Agopian518ec112011-05-13 16:21:08 -0700261extern gl_hooks_t gHooksTrace;
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700262
Mathias Agopian518ec112011-05-13 16:21:08 -0700263} // namespace android;
264
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700265
Mathias Agopian518ec112011-05-13 16:21:08 -0700266// ----------------------------------------------------------------------------
267
268static inline void clearError() { egl_tls_t::clearError(); }
269static inline EGLContext getContext() { return egl_tls_t::getContext(); }
270
271// ----------------------------------------------------------------------------
272
273EGLDisplay eglGetDisplay(EGLNativeDisplayType display)
274{
Jesse Hall1508ae62017-01-19 17:43:26 -0800275 ATRACE_CALL();
Mathias Agopian518ec112011-05-13 16:21:08 -0700276 clearError();
277
Dan Stozac3289c42014-01-17 11:38:34 -0800278 uintptr_t index = reinterpret_cast<uintptr_t>(display);
Mathias Agopian518ec112011-05-13 16:21:08 -0700279 if (index >= NUM_DISPLAYS) {
280 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
281 }
282
283 if (egl_init_drivers() == EGL_FALSE) {
284 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
285 }
286
287 EGLDisplay dpy = egl_display_t::getFromNativeDisplay(display);
288 return dpy;
289}
290
291// ----------------------------------------------------------------------------
292// Initialization
293// ----------------------------------------------------------------------------
294
295EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
296{
297 clearError();
298
Jesse Hallb29e5e82012-04-04 16:53:42 -0700299 egl_display_ptr dp = get_display(dpy);
Mathias Agopian737b8962017-02-24 14:32:05 -0800300 if (!dp) return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700301
302 EGLBoolean res = dp->initialize(major, minor);
303
304 return res;
305}
306
307EGLBoolean eglTerminate(EGLDisplay dpy)
308{
309 // NOTE: don't unload the drivers b/c some APIs can be called
310 // after eglTerminate() has been called. eglTerminate() only
311 // terminates an EGLDisplay, not a EGL itself.
312
313 clearError();
314
Jesse Hallb29e5e82012-04-04 16:53:42 -0700315 egl_display_ptr dp = get_display(dpy);
Mathias Agopian737b8962017-02-24 14:32:05 -0800316 if (!dp) return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700317
318 EGLBoolean res = dp->terminate();
Jesse Hall47743382013-02-08 11:13:46 -0800319
Mathias Agopian518ec112011-05-13 16:21:08 -0700320 return res;
321}
322
323// ----------------------------------------------------------------------------
324// configuration
325// ----------------------------------------------------------------------------
326
327EGLBoolean eglGetConfigs( EGLDisplay dpy,
328 EGLConfig *configs,
329 EGLint config_size, EGLint *num_config)
330{
331 clearError();
332
Jesse Hallb29e5e82012-04-04 16:53:42 -0700333 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700334 if (!dp) return EGL_FALSE;
335
Mathias Agopian7773c432012-02-13 20:06:08 -0800336 if (num_config==0) {
Mathias Agopian737b8962017-02-24 14:32:05 -0800337 return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700338 }
339
Mathias Agopian7773c432012-02-13 20:06:08 -0800340 EGLBoolean res = EGL_FALSE;
341 *num_config = 0;
342
343 egl_connection_t* const cnx = &gEGLImpl;
344 if (cnx->dso) {
345 res = cnx->egl.eglGetConfigs(
346 dp->disp.dpy, configs, config_size, num_config);
Mathias Agopian518ec112011-05-13 16:21:08 -0700347 }
Mathias Agopian7773c432012-02-13 20:06:08 -0800348
349 return res;
Mathias Agopian518ec112011-05-13 16:21:08 -0700350}
351
352EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list,
353 EGLConfig *configs, EGLint config_size,
354 EGLint *num_config)
355{
356 clearError();
357
Jesse Hallb29e5e82012-04-04 16:53:42 -0700358 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700359 if (!dp) return EGL_FALSE;
360
361 if (num_config==0) {
Mathias Agopian737b8962017-02-24 14:32:05 -0800362 return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700363 }
364
Mathias Agopian518ec112011-05-13 16:21:08 -0700365 EGLBoolean res = EGL_FALSE;
366 *num_config = 0;
367
Mathias Agopianada798b2012-02-13 17:09:30 -0800368 egl_connection_t* const cnx = &gEGLImpl;
369 if (cnx->dso) {
Romain Guy1cffc802012-10-15 18:13:05 -0700370 if (attrib_list) {
371 char value[PROPERTY_VALUE_MAX];
372 property_get("debug.egl.force_msaa", value, "false");
373
374 if (!strcmp(value, "true")) {
375 size_t attribCount = 0;
376 EGLint attrib = attrib_list[0];
377
378 // Only enable MSAA if the context is OpenGL ES 2.0 and
Romain Guybe3c3e42012-10-15 19:25:18 -0700379 // if no caveat is requested
Romain Guy1cffc802012-10-15 18:13:05 -0700380 const EGLint *attribRendererable = NULL;
381 const EGLint *attribCaveat = NULL;
382
383 // Count the number of attributes and look for
Romain Guybe3c3e42012-10-15 19:25:18 -0700384 // EGL_RENDERABLE_TYPE and EGL_CONFIG_CAVEAT
Romain Guy1cffc802012-10-15 18:13:05 -0700385 while (attrib != EGL_NONE) {
386 attrib = attrib_list[attribCount];
387 switch (attrib) {
388 case EGL_RENDERABLE_TYPE:
389 attribRendererable = &attrib_list[attribCount];
390 break;
391 case EGL_CONFIG_CAVEAT:
392 attribCaveat = &attrib_list[attribCount];
393 break;
Mathias Agopian737b8962017-02-24 14:32:05 -0800394 default:
395 break;
Romain Guy1cffc802012-10-15 18:13:05 -0700396 }
397 attribCount++;
398 }
399
400 if (attribRendererable && attribRendererable[1] == EGL_OPENGL_ES2_BIT &&
401 (!attribCaveat || attribCaveat[1] != EGL_NONE)) {
Jesse Hall47743382013-02-08 11:13:46 -0800402
Romain Guy1cffc802012-10-15 18:13:05 -0700403 // Insert 2 extra attributes to force-enable MSAA 4x
404 EGLint aaAttribs[attribCount + 4];
405 aaAttribs[0] = EGL_SAMPLE_BUFFERS;
406 aaAttribs[1] = 1;
407 aaAttribs[2] = EGL_SAMPLES;
408 aaAttribs[3] = 4;
409
410 memcpy(&aaAttribs[4], attrib_list, attribCount * sizeof(EGLint));
411
412 EGLint numConfigAA;
413 EGLBoolean resAA = cnx->egl.eglChooseConfig(
414 dp->disp.dpy, aaAttribs, configs, config_size, &numConfigAA);
415
416 if (resAA == EGL_TRUE && numConfigAA > 0) {
417 ALOGD("Enabling MSAA 4x");
418 *num_config = numConfigAA;
419 return resAA;
420 }
421 }
422 }
423 }
424
Mathias Agopian7773c432012-02-13 20:06:08 -0800425 res = cnx->egl.eglChooseConfig(
426 dp->disp.dpy, attrib_list, configs, config_size, num_config);
Mathias Agopian518ec112011-05-13 16:21:08 -0700427 }
428 return res;
429}
430
431EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
432 EGLint attribute, EGLint *value)
433{
434 clearError();
435
Jesse Hallb29e5e82012-04-04 16:53:42 -0700436 egl_connection_t* cnx = NULL;
437 const egl_display_ptr dp = validate_display_connection(dpy, cnx);
438 if (!dp) return EGL_FALSE;
Jesse Hall47743382013-02-08 11:13:46 -0800439
Mathias Agopian518ec112011-05-13 16:21:08 -0700440 return cnx->egl.eglGetConfigAttrib(
Mathias Agopian7773c432012-02-13 20:06:08 -0800441 dp->disp.dpy, config, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -0700442}
443
444// ----------------------------------------------------------------------------
445// surfaces
446// ----------------------------------------------------------------------------
447
Jesse Hallc2e41222013-08-08 13:40:22 -0700448// Turn linear formats into corresponding sRGB formats when colorspace is
449// EGL_GL_COLORSPACE_SRGB_KHR, or turn sRGB formats into corresponding linear
450// formats when colorspace is EGL_GL_COLORSPACE_LINEAR_KHR. In any cases where
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800451// the modification isn't possible, the original dataSpace is returned.
452static android_dataspace modifyBufferDataspace( android_dataspace dataSpace,
453 EGLint colorspace) {
Jesse Hallc2e41222013-08-08 13:40:22 -0700454 if (colorspace == EGL_GL_COLORSPACE_LINEAR_KHR) {
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800455 return HAL_DATASPACE_SRGB_LINEAR;
Jesse Hallc2e41222013-08-08 13:40:22 -0700456 } else if (colorspace == EGL_GL_COLORSPACE_SRGB_KHR) {
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800457 return HAL_DATASPACE_SRGB;
Jesse Hallc2e41222013-08-08 13:40:22 -0700458 }
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800459 return dataSpace;
Jesse Hallc2e41222013-08-08 13:40:22 -0700460}
461
Mathias Agopian518ec112011-05-13 16:21:08 -0700462EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config,
463 NativeWindowType window,
464 const EGLint *attrib_list)
465{
466 clearError();
467
Jesse Hallb29e5e82012-04-04 16:53:42 -0700468 egl_connection_t* cnx = NULL;
469 egl_display_ptr dp = validate_display_connection(dpy, cnx);
470 if (dp) {
Mathias Agopianada798b2012-02-13 17:09:30 -0800471 EGLDisplay iDpy = dp->disp.dpy;
Mathias Agopian518ec112011-05-13 16:21:08 -0700472
Mathias Agopian10e9ab52017-03-08 15:02:55 -0800473 if (!window) {
474 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
475 }
476
477 int value = 0;
478 window->query(window, NATIVE_WINDOW_IS_VALID, &value);
479 if (!value) {
480 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
481 }
482
Andy McFaddend566ce32014-01-07 15:54:17 -0800483 int result = native_window_api_connect(window, NATIVE_WINDOW_API_EGL);
Mathias Agopian65421432017-03-08 11:49:05 -0800484 if (result < 0) {
Andy McFaddend566ce32014-01-07 15:54:17 -0800485 ALOGE("eglCreateWindowSurface: native_window_api_connect (win=%p) "
486 "failed (%#x) (already connected to another API?)",
487 window, result);
Jonathan Hamilton77a9b4a2013-07-17 09:41:42 -0700488 return setError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
Mathias Agopian81a63352011-07-29 17:55:48 -0700489 }
490
Mathias Agopian0f288fc2013-08-21 16:36:34 -0700491 // Set the native window's buffers format to match what this config requests.
Jesse Hallc2e41222013-08-08 13:40:22 -0700492 // Whether to use sRGB gamma is not part of the EGLconfig, but is part
493 // of our native format. So if sRGB gamma is requested, we have to
494 // modify the EGLconfig's format before setting the native window's
495 // format.
Alistair Strachan733a8072015-02-12 12:33:25 -0800496
Courtney Goeltzenleuchter0e4e3952016-11-16 13:53:40 -0700497 EGLint componentType = EGL_COLOR_COMPONENT_TYPE_FIXED_EXT;
498 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_COLOR_COMPONENT_TYPE_EXT,
499 &componentType);
500
Mathias Agopian95921562017-02-24 14:31:31 -0800501 EGLint format;
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800502 android_dataspace dataSpace = HAL_DATASPACE_UNKNOWN;
Mathias Agopian0f288fc2013-08-21 16:36:34 -0700503 EGLint a = 0;
Courtney Goeltzenleuchter0e4e3952016-11-16 13:53:40 -0700504 EGLint r, g, b;
505 r = g = b = 0;
506 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_RED_SIZE, &r);
507 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_GREEN_SIZE, &g);
508 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_BLUE_SIZE, &b);
Mathias Agopian0f288fc2013-08-21 16:36:34 -0700509 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_ALPHA_SIZE, &a);
Courtney Goeltzenleuchter0e4e3952016-11-16 13:53:40 -0700510 EGLint colorDepth = r + g + b;
511
512 if (a == 0) {
Mathias Agopian0f288fc2013-08-21 16:36:34 -0700513 if (colorDepth <= 16) {
514 format = HAL_PIXEL_FORMAT_RGB_565;
515 } else {
Courtney Goeltzenleuchter0e4e3952016-11-16 13:53:40 -0700516 if (componentType == EGL_COLOR_COMPONENT_TYPE_FIXED_EXT) {
517 if (colorDepth > 24) {
518 format = HAL_PIXEL_FORMAT_RGBA_1010102;
519 } else {
520 format = HAL_PIXEL_FORMAT_RGBX_8888;
521 }
522 } else {
523 format = HAL_PIXEL_FORMAT_RGBA_FP16;
524 }
525 }
526 } else {
527 if (componentType == EGL_COLOR_COMPONENT_TYPE_FIXED_EXT) {
528 if (colorDepth > 24) {
529 format = HAL_PIXEL_FORMAT_RGBA_1010102;
530 } else {
531 format = HAL_PIXEL_FORMAT_RGBA_8888;
532 }
533 } else {
534 format = HAL_PIXEL_FORMAT_RGBA_FP16;
Mathias Agopian0f288fc2013-08-21 16:36:34 -0700535 }
Jesse Hallc2e41222013-08-08 13:40:22 -0700536 }
Mathias Agopian0f288fc2013-08-21 16:36:34 -0700537
538 // now select a corresponding sRGB format if needed
539 if (attrib_list && dp->haveExtension("EGL_KHR_gl_colorspace")) {
540 for (const EGLint* attr = attrib_list; *attr != EGL_NONE; attr += 2) {
541 if (*attr == EGL_GL_COLORSPACE_KHR) {
Sandeep Shinde9c67bfd2015-02-10 16:04:15 +0530542 dataSpace = modifyBufferDataspace(dataSpace, *(attr+1));
Jamie Gennisbee205f2011-07-01 13:12:07 -0700543 }
Mathias Agopian518ec112011-05-13 16:21:08 -0700544 }
545 }
Alistair Strachan733a8072015-02-12 12:33:25 -0800546
Jesse Hallc2e41222013-08-08 13:40:22 -0700547 if (format != 0) {
548 int err = native_window_set_buffers_format(window, format);
549 if (err != 0) {
550 ALOGE("error setting native window pixel format: %s (%d)",
551 strerror(-err), err);
552 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
553 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
554 }
555 }
Mathias Agopian518ec112011-05-13 16:21:08 -0700556
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800557 if (dataSpace != 0) {
558 int err = native_window_set_buffers_data_space(window, dataSpace);
559 if (err != 0) {
560 ALOGE("error setting native window pixel dataSpace: %s (%d)",
561 strerror(-err), err);
562 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
563 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
564 }
565 }
566
Jamie Gennis59769462011-11-19 18:04:43 -0800567 // the EGL spec requires that a new EGLSurface default to swap interval
568 // 1, so explicitly set that on the window here.
569 ANativeWindow* anw = reinterpret_cast<ANativeWindow*>(window);
570 anw->setSwapInterval(anw, 1);
571
Mathias Agopian518ec112011-05-13 16:21:08 -0700572 EGLSurface surface = cnx->egl.eglCreateWindowSurface(
Mathias Agopian7773c432012-02-13 20:06:08 -0800573 iDpy, config, window, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700574 if (surface != EGL_NO_SURFACE) {
Jesse Hallb29e5e82012-04-04 16:53:42 -0700575 egl_surface_t* s = new egl_surface_t(dp.get(), config, window,
576 surface, cnx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700577 return s;
578 }
Mathias Agopian81a63352011-07-29 17:55:48 -0700579
580 // EGLSurface creation failed
581 native_window_set_buffers_format(window, 0);
582 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
Mathias Agopian518ec112011-05-13 16:21:08 -0700583 }
584 return EGL_NO_SURFACE;
585}
586
587EGLSurface eglCreatePixmapSurface( EGLDisplay dpy, EGLConfig config,
588 NativePixmapType pixmap,
589 const EGLint *attrib_list)
590{
591 clearError();
592
Jesse Hallb29e5e82012-04-04 16:53:42 -0700593 egl_connection_t* cnx = NULL;
594 egl_display_ptr dp = validate_display_connection(dpy, cnx);
595 if (dp) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700596 EGLSurface surface = cnx->egl.eglCreatePixmapSurface(
Mathias Agopian7773c432012-02-13 20:06:08 -0800597 dp->disp.dpy, config, pixmap, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700598 if (surface != EGL_NO_SURFACE) {
Jesse Hallb29e5e82012-04-04 16:53:42 -0700599 egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL,
600 surface, cnx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700601 return s;
602 }
603 }
604 return EGL_NO_SURFACE;
605}
606
607EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config,
608 const EGLint *attrib_list)
609{
610 clearError();
611
Jesse Hallb29e5e82012-04-04 16:53:42 -0700612 egl_connection_t* cnx = NULL;
613 egl_display_ptr dp = validate_display_connection(dpy, cnx);
614 if (dp) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700615 EGLSurface surface = cnx->egl.eglCreatePbufferSurface(
Mathias Agopian7773c432012-02-13 20:06:08 -0800616 dp->disp.dpy, config, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700617 if (surface != EGL_NO_SURFACE) {
Jesse Hallb29e5e82012-04-04 16:53:42 -0700618 egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL,
619 surface, cnx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700620 return s;
621 }
622 }
623 return EGL_NO_SURFACE;
624}
Jesse Hall47743382013-02-08 11:13:46 -0800625
Mathias Agopian518ec112011-05-13 16:21:08 -0700626EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
627{
628 clearError();
629
Jesse Hallb29e5e82012-04-04 16:53:42 -0700630 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700631 if (!dp) return EGL_FALSE;
632
Jesse Hallb29e5e82012-04-04 16:53:42 -0700633 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700634 if (!_s.get())
Mathias Agopian737b8962017-02-24 14:32:05 -0800635 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700636
637 egl_surface_t * const s = get_surface(surface);
Mathias Agopianada798b2012-02-13 17:09:30 -0800638 EGLBoolean result = s->cnx->egl.eglDestroySurface(dp->disp.dpy, s->surface);
Mathias Agopian518ec112011-05-13 16:21:08 -0700639 if (result == EGL_TRUE) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700640 _s.terminate();
641 }
642 return result;
643}
644
645EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface surface,
646 EGLint attribute, EGLint *value)
647{
648 clearError();
649
Jesse Hallb29e5e82012-04-04 16:53:42 -0700650 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700651 if (!dp) return EGL_FALSE;
652
Jesse Hallb29e5e82012-04-04 16:53:42 -0700653 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700654 if (!_s.get())
Mathias Agopian737b8962017-02-24 14:32:05 -0800655 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700656
Mathias Agopian518ec112011-05-13 16:21:08 -0700657 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian7773c432012-02-13 20:06:08 -0800658 return s->cnx->egl.eglQuerySurface(
659 dp->disp.dpy, s->surface, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -0700660}
661
Jamie Gennise8696a42012-01-15 18:54:57 -0800662void EGLAPI eglBeginFrame(EGLDisplay dpy, EGLSurface surface) {
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800663 ATRACE_CALL();
Jamie Gennise8696a42012-01-15 18:54:57 -0800664 clearError();
665
Jesse Hallb29e5e82012-04-04 16:53:42 -0700666 const egl_display_ptr dp = validate_display(dpy);
Jamie Gennise8696a42012-01-15 18:54:57 -0800667 if (!dp) {
668 return;
669 }
670
Jesse Hallb29e5e82012-04-04 16:53:42 -0700671 SurfaceRef _s(dp.get(), surface);
Jamie Gennise8696a42012-01-15 18:54:57 -0800672 if (!_s.get()) {
673 setError(EGL_BAD_SURFACE, EGL_FALSE);
Jamie Gennise8696a42012-01-15 18:54:57 -0800674 }
Jamie Gennise8696a42012-01-15 18:54:57 -0800675}
676
Mathias Agopian518ec112011-05-13 16:21:08 -0700677// ----------------------------------------------------------------------------
678// Contexts
679// ----------------------------------------------------------------------------
680
681EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config,
682 EGLContext share_list, const EGLint *attrib_list)
683{
684 clearError();
685
Jesse Hallb29e5e82012-04-04 16:53:42 -0700686 egl_connection_t* cnx = NULL;
687 const egl_display_ptr dp = validate_display_connection(dpy, cnx);
Michael Chock0673e1e2012-06-21 12:53:17 -0700688 if (dp) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700689 if (share_list != EGL_NO_CONTEXT) {
Michael Chock0673e1e2012-06-21 12:53:17 -0700690 if (!ContextRef(dp.get(), share_list).get()) {
691 return setError(EGL_BAD_CONTEXT, EGL_NO_CONTEXT);
692 }
Mathias Agopian518ec112011-05-13 16:21:08 -0700693 egl_context_t* const c = get_context(share_list);
694 share_list = c->context;
695 }
696 EGLContext context = cnx->egl.eglCreateContext(
Mathias Agopian7773c432012-02-13 20:06:08 -0800697 dp->disp.dpy, config, share_list, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700698 if (context != EGL_NO_CONTEXT) {
699 // figure out if it's a GLESv1 or GLESv2
700 int version = 0;
701 if (attrib_list) {
702 while (*attrib_list != EGL_NONE) {
703 GLint attr = *attrib_list++;
704 GLint value = *attrib_list++;
705 if (attr == EGL_CONTEXT_CLIENT_VERSION) {
706 if (value == 1) {
Mathias Agopian7773c432012-02-13 20:06:08 -0800707 version = egl_connection_t::GLESv1_INDEX;
Jesse Hall47743382013-02-08 11:13:46 -0800708 } else if (value == 2 || value == 3) {
Mathias Agopian7773c432012-02-13 20:06:08 -0800709 version = egl_connection_t::GLESv2_INDEX;
Mathias Agopian518ec112011-05-13 16:21:08 -0700710 }
711 }
712 };
713 }
Jesse Hallb29e5e82012-04-04 16:53:42 -0700714 egl_context_t* c = new egl_context_t(dpy, context, config, cnx,
715 version);
Mathias Agopian518ec112011-05-13 16:21:08 -0700716 return c;
717 }
718 }
719 return EGL_NO_CONTEXT;
720}
721
722EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
723{
724 clearError();
725
Jesse Hallb29e5e82012-04-04 16:53:42 -0700726 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700727 if (!dp)
728 return EGL_FALSE;
Mathias Agopian518ec112011-05-13 16:21:08 -0700729
Jesse Hallb29e5e82012-04-04 16:53:42 -0700730 ContextRef _c(dp.get(), ctx);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700731 if (!_c.get())
Mathias Agopian737b8962017-02-24 14:32:05 -0800732 return setError(EGL_BAD_CONTEXT, (EGLBoolean)EGL_FALSE);
Jesse Hall47743382013-02-08 11:13:46 -0800733
Mathias Agopian518ec112011-05-13 16:21:08 -0700734 egl_context_t * const c = get_context(ctx);
Mathias Agopianada798b2012-02-13 17:09:30 -0800735 EGLBoolean result = c->cnx->egl.eglDestroyContext(dp->disp.dpy, c->context);
Mathias Agopian518ec112011-05-13 16:21:08 -0700736 if (result == EGL_TRUE) {
737 _c.terminate();
738 }
739 return result;
740}
741
Mathias Agopian518ec112011-05-13 16:21:08 -0700742EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw,
743 EGLSurface read, EGLContext ctx)
744{
745 clearError();
746
Jesse Hallb29e5e82012-04-04 16:53:42 -0700747 egl_display_ptr dp = validate_display(dpy);
Mathias Agopian737b8962017-02-24 14:32:05 -0800748 if (!dp) return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700749
Mathias Agopian5b287a62011-05-16 18:58:55 -0700750 // If ctx is not EGL_NO_CONTEXT, read is not EGL_NO_SURFACE, or draw is not
751 // EGL_NO_SURFACE, then an EGL_NOT_INITIALIZED error is generated if dpy is
752 // a valid but uninitialized display.
Mathias Agopian518ec112011-05-13 16:21:08 -0700753 if ( (ctx != EGL_NO_CONTEXT) || (read != EGL_NO_SURFACE) ||
754 (draw != EGL_NO_SURFACE) ) {
Mathias Agopian737b8962017-02-24 14:32:05 -0800755 if (!dp->isReady()) return setError(EGL_NOT_INITIALIZED, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700756 }
757
758 // get a reference to the object passed in
Jesse Hallb29e5e82012-04-04 16:53:42 -0700759 ContextRef _c(dp.get(), ctx);
760 SurfaceRef _d(dp.get(), draw);
761 SurfaceRef _r(dp.get(), read);
Mathias Agopian518ec112011-05-13 16:21:08 -0700762
763 // validate the context (if not EGL_NO_CONTEXT)
Mathias Agopian5b287a62011-05-16 18:58:55 -0700764 if ((ctx != EGL_NO_CONTEXT) && !_c.get()) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700765 // EGL_NO_CONTEXT is valid
Mathias Agopian737b8962017-02-24 14:32:05 -0800766 return setError(EGL_BAD_CONTEXT, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700767 }
768
769 // these are the underlying implementation's object
770 EGLContext impl_ctx = EGL_NO_CONTEXT;
771 EGLSurface impl_draw = EGL_NO_SURFACE;
772 EGLSurface impl_read = EGL_NO_SURFACE;
773
774 // these are our objects structs passed in
775 egl_context_t * c = NULL;
776 egl_surface_t const * d = NULL;
777 egl_surface_t const * r = NULL;
778
779 // these are the current objects structs
780 egl_context_t * cur_c = get_context(getContext());
Jesse Hall47743382013-02-08 11:13:46 -0800781
Mathias Agopian518ec112011-05-13 16:21:08 -0700782 if (ctx != EGL_NO_CONTEXT) {
783 c = get_context(ctx);
784 impl_ctx = c->context;
785 } else {
786 // no context given, use the implementation of the current context
Michael Chock0673e1e2012-06-21 12:53:17 -0700787 if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE) {
788 // calling eglMakeCurrent( ..., !=0, !=0, EGL_NO_CONTEXT);
Mathias Agopian737b8962017-02-24 14:32:05 -0800789 return setError(EGL_BAD_MATCH, (EGLBoolean)EGL_FALSE);
Michael Chock0673e1e2012-06-21 12:53:17 -0700790 }
Mathias Agopian518ec112011-05-13 16:21:08 -0700791 if (cur_c == NULL) {
792 // no current context
Mathias Agopian518ec112011-05-13 16:21:08 -0700793 // not an error, there is just no current context.
794 return EGL_TRUE;
795 }
796 }
797
798 // retrieve the underlying implementation's draw EGLSurface
799 if (draw != EGL_NO_SURFACE) {
Mathias Agopian737b8962017-02-24 14:32:05 -0800800 if (!_d.get()) return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700801 d = get_surface(draw);
Mathias Agopian518ec112011-05-13 16:21:08 -0700802 impl_draw = d->surface;
803 }
804
805 // retrieve the underlying implementation's read EGLSurface
806 if (read != EGL_NO_SURFACE) {
Mathias Agopian737b8962017-02-24 14:32:05 -0800807 if (!_r.get()) return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700808 r = get_surface(read);
Mathias Agopian518ec112011-05-13 16:21:08 -0700809 impl_read = r->surface;
810 }
811
Mathias Agopian518ec112011-05-13 16:21:08 -0700812
Jesse Hallb29e5e82012-04-04 16:53:42 -0700813 EGLBoolean result = dp->makeCurrent(c, cur_c,
Mathias Agopianfb87e542012-01-30 18:20:52 -0800814 draw, read, ctx,
815 impl_draw, impl_read, impl_ctx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700816
817 if (result == EGL_TRUE) {
Mathias Agopianfb87e542012-01-30 18:20:52 -0800818 if (c) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700819 setGLHooksThreadSpecific(c->cnx->hooks[c->version]);
820 egl_tls_t::setContext(ctx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700821 _c.acquire();
822 _r.acquire();
823 _d.acquire();
Mathias Agopian518ec112011-05-13 16:21:08 -0700824 } else {
825 setGLHooksThreadSpecific(&gHooksNoContext);
826 egl_tls_t::setContext(EGL_NO_CONTEXT);
827 }
Mathias Agopian5fecea72011-08-25 18:38:24 -0700828 } else {
Steve Blocke6f43dd2012-01-06 19:20:56 +0000829 // this will ALOGE the error
Mathias Agopian63108c32013-09-06 13:36:49 -0700830 egl_connection_t* const cnx = &gEGLImpl;
Mathias Agopian737b8962017-02-24 14:32:05 -0800831 result = setError(cnx->egl.eglGetError(), (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700832 }
833 return result;
834}
835
836
837EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx,
838 EGLint attribute, EGLint *value)
839{
840 clearError();
841
Jesse Hallb29e5e82012-04-04 16:53:42 -0700842 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700843 if (!dp) return EGL_FALSE;
844
Jesse Hallb29e5e82012-04-04 16:53:42 -0700845 ContextRef _c(dp.get(), ctx);
Mathias Agopian737b8962017-02-24 14:32:05 -0800846 if (!_c.get()) return setError(EGL_BAD_CONTEXT, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700847
Mathias Agopian518ec112011-05-13 16:21:08 -0700848 egl_context_t * const c = get_context(ctx);
Mathias Agopian7773c432012-02-13 20:06:08 -0800849 return c->cnx->egl.eglQueryContext(
850 dp->disp.dpy, c->context, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -0700851
Mathias Agopian518ec112011-05-13 16:21:08 -0700852}
853
854EGLContext eglGetCurrentContext(void)
855{
856 // could be called before eglInitialize(), but we wouldn't have a context
857 // then, and this function would correctly return EGL_NO_CONTEXT.
858
859 clearError();
860
861 EGLContext ctx = getContext();
862 return ctx;
863}
864
865EGLSurface eglGetCurrentSurface(EGLint readdraw)
866{
867 // could be called before eglInitialize(), but we wouldn't have a context
868 // then, and this function would correctly return EGL_NO_SURFACE.
869
870 clearError();
871
872 EGLContext ctx = getContext();
873 if (ctx) {
874 egl_context_t const * const c = get_context(ctx);
875 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
876 switch (readdraw) {
877 case EGL_READ: return c->read;
Jesse Hall47743382013-02-08 11:13:46 -0800878 case EGL_DRAW: return c->draw;
Mathias Agopian518ec112011-05-13 16:21:08 -0700879 default: return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
880 }
881 }
882 return EGL_NO_SURFACE;
883}
884
885EGLDisplay eglGetCurrentDisplay(void)
886{
887 // could be called before eglInitialize(), but we wouldn't have a context
888 // then, and this function would correctly return EGL_NO_DISPLAY.
889
890 clearError();
891
892 EGLContext ctx = getContext();
893 if (ctx) {
894 egl_context_t const * const c = get_context(ctx);
895 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
896 return c->dpy;
897 }
898 return EGL_NO_DISPLAY;
899}
900
901EGLBoolean eglWaitGL(void)
902{
Mathias Agopian518ec112011-05-13 16:21:08 -0700903 clearError();
904
Mathias Agopianada798b2012-02-13 17:09:30 -0800905 egl_connection_t* const cnx = &gEGLImpl;
906 if (!cnx->dso)
Mathias Agopian737b8962017-02-24 14:32:05 -0800907 return setError(EGL_BAD_CONTEXT, (EGLBoolean)EGL_FALSE);
Mathias Agopianada798b2012-02-13 17:09:30 -0800908
909 return cnx->egl.eglWaitGL();
Mathias Agopian518ec112011-05-13 16:21:08 -0700910}
911
912EGLBoolean eglWaitNative(EGLint engine)
913{
Mathias Agopian518ec112011-05-13 16:21:08 -0700914 clearError();
915
Mathias Agopianada798b2012-02-13 17:09:30 -0800916 egl_connection_t* const cnx = &gEGLImpl;
917 if (!cnx->dso)
Mathias Agopian737b8962017-02-24 14:32:05 -0800918 return setError(EGL_BAD_CONTEXT, (EGLBoolean)EGL_FALSE);
Mathias Agopianada798b2012-02-13 17:09:30 -0800919
920 return cnx->egl.eglWaitNative(engine);
Mathias Agopian518ec112011-05-13 16:21:08 -0700921}
922
923EGLint eglGetError(void)
924{
Mathias Agopianada798b2012-02-13 17:09:30 -0800925 EGLint err = EGL_SUCCESS;
926 egl_connection_t* const cnx = &gEGLImpl;
927 if (cnx->dso) {
928 err = cnx->egl.eglGetError();
Mathias Agopian518ec112011-05-13 16:21:08 -0700929 }
Mathias Agopianada798b2012-02-13 17:09:30 -0800930 if (err == EGL_SUCCESS) {
931 err = egl_tls_t::getError();
932 }
933 return err;
Mathias Agopian518ec112011-05-13 16:21:08 -0700934}
935
Michael Chockc0ec5e22014-01-27 08:14:33 -0800936static __eglMustCastToProperFunctionPointerType findBuiltinWrapper(
Jesse Hallc07b5202013-07-04 12:08:16 -0700937 const char* procname) {
938 const egl_connection_t* cnx = &gEGLImpl;
939 void* proc = NULL;
940
Michael Chockc0ec5e22014-01-27 08:14:33 -0800941 proc = dlsym(cnx->libEgl, procname);
942 if (proc) return (__eglMustCastToProperFunctionPointerType)proc;
943
Jesse Hallc07b5202013-07-04 12:08:16 -0700944 proc = dlsym(cnx->libGles2, procname);
945 if (proc) return (__eglMustCastToProperFunctionPointerType)proc;
946
947 proc = dlsym(cnx->libGles1, procname);
948 if (proc) return (__eglMustCastToProperFunctionPointerType)proc;
949
950 return NULL;
951}
952
Mathias Agopian518ec112011-05-13 16:21:08 -0700953__eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
954{
955 // eglGetProcAddress() could be the very first function called
956 // in which case we must make sure we've initialized ourselves, this
957 // happens the first time egl_get_display() is called.
958
959 clearError();
960
961 if (egl_init_drivers() == EGL_FALSE) {
962 setError(EGL_BAD_PARAMETER, NULL);
963 return NULL;
964 }
965
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700966 if (FILTER_EXTENSIONS(procname)) {
Jamie Gennisaca51c02011-11-03 17:42:43 -0700967 return NULL;
968 }
969
Mathias Agopian518ec112011-05-13 16:21:08 -0700970 __eglMustCastToProperFunctionPointerType addr;
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700971 addr = findProcAddress(procname, sExtensionMap, NELEM(sExtensionMap));
Mathias Agopian518ec112011-05-13 16:21:08 -0700972 if (addr) return addr;
973
Michael Chockc0ec5e22014-01-27 08:14:33 -0800974 addr = findBuiltinWrapper(procname);
Jesse Hallc07b5202013-07-04 12:08:16 -0700975 if (addr) return addr;
Jamie Gennisaca51c02011-11-03 17:42:43 -0700976
Mathias Agopian518ec112011-05-13 16:21:08 -0700977 // this protects accesses to sGLExtentionMap and sGLExtentionSlot
978 pthread_mutex_lock(&sExtensionMapMutex);
979
980 /*
981 * Since eglGetProcAddress() is not associated to anything, it needs
982 * to return a function pointer that "works" regardless of what
983 * the current context is.
984 *
985 * For this reason, we return a "forwarder", a small stub that takes
986 * care of calling the function associated with the context
987 * currently bound.
988 *
989 * We first look for extensions we've already resolved, if we're seeing
990 * this extension for the first time, we go through all our
991 * implementations and call eglGetProcAddress() and record the
992 * result in the appropriate implementation hooks and return the
993 * address of the forwarder corresponding to that hook set.
994 *
995 */
996
Mathias Agopian65421432017-03-08 11:49:05 -0800997 const std::string name(procname);
998
999 auto& extentionMap = sGLExtentionMap;
1000 auto pos = extentionMap.find(name);
1001 addr = (pos != extentionMap.end()) ? pos->second : nullptr;
Mathias Agopian518ec112011-05-13 16:21:08 -07001002 const int slot = sGLExtentionSlot;
1003
Steve Blocke6f43dd2012-01-06 19:20:56 +00001004 ALOGE_IF(slot >= MAX_NUMBER_OF_GL_EXTENSIONS,
Mathias Agopian518ec112011-05-13 16:21:08 -07001005 "no more slots for eglGetProcAddress(\"%s\")",
1006 procname);
1007
1008 if (!addr && (slot < MAX_NUMBER_OF_GL_EXTENSIONS)) {
1009 bool found = false;
Mathias Agopianada798b2012-02-13 17:09:30 -08001010
1011 egl_connection_t* const cnx = &gEGLImpl;
1012 if (cnx->dso && cnx->egl.eglGetProcAddress) {
Mathias Agopianada798b2012-02-13 17:09:30 -08001013 // Extensions are independent of the bound context
luliuhui69d10072012-08-30 11:15:36 +08001014 addr =
Mathias Agopian7773c432012-02-13 20:06:08 -08001015 cnx->hooks[egl_connection_t::GLESv1_INDEX]->ext.extensions[slot] =
1016 cnx->hooks[egl_connection_t::GLESv2_INDEX]->ext.extensions[slot] =
Mathias Agopianada798b2012-02-13 17:09:30 -08001017 cnx->egl.eglGetProcAddress(procname);
luliuhui69d10072012-08-30 11:15:36 +08001018 if (addr) found = true;
Mathias Agopian518ec112011-05-13 16:21:08 -07001019 }
Mathias Agopianada798b2012-02-13 17:09:30 -08001020
Mathias Agopian518ec112011-05-13 16:21:08 -07001021 if (found) {
1022 addr = gExtensionForwarders[slot];
Mathias Agopian65421432017-03-08 11:49:05 -08001023 extentionMap[name] = addr;
Mathias Agopian518ec112011-05-13 16:21:08 -07001024 sGLExtentionSlot++;
1025 }
1026 }
1027
1028 pthread_mutex_unlock(&sExtensionMapMutex);
1029 return addr;
1030}
1031
Mathias Agopian65421432017-03-08 11:49:05 -08001032class FrameCompletionThread {
Jamie Gennis28ef8d72012-04-05 20:34:54 -07001033public:
1034
1035 static void queueSync(EGLSyncKHR sync) {
Mathias Agopian65421432017-03-08 11:49:05 -08001036 static FrameCompletionThread thread;
1037
1038 char name[64];
1039
1040 std::lock_guard<std::mutex> lock(thread.mMutex);
1041 snprintf(name, sizeof(name), "kicked off frame %u", (unsigned int)thread.mFramesQueued);
1042 ATRACE_NAME(name);
1043
1044 thread.mQueue.push_back(sync);
1045 thread.mCondition.notify_one();
1046 thread.mFramesQueued++;
1047 ATRACE_INT("GPU Frames Outstanding", int32_t(thread.mQueue.size()));
Jamie Gennis28ef8d72012-04-05 20:34:54 -07001048 }
1049
1050private:
Jamie Gennis28ef8d72012-04-05 20:34:54 -07001051
Mathias Agopian65421432017-03-08 11:49:05 -08001052 FrameCompletionThread() : mFramesQueued(0), mFramesCompleted(0) {
1053 std::thread thread(&FrameCompletionThread::loop, this);
1054 thread.detach();
1055 }
1056
1057#pragma clang diagnostic push
1058#pragma clang diagnostic ignored "-Wmissing-noreturn"
1059 void loop() {
1060 while (true) {
1061 threadLoop();
1062 }
1063 }
1064#pragma clang diagnostic pop
1065
1066 void threadLoop() {
Jamie Gennis28ef8d72012-04-05 20:34:54 -07001067 EGLSyncKHR sync;
1068 uint32_t frameNum;
1069 {
Mathias Agopian65421432017-03-08 11:49:05 -08001070 std::unique_lock<std::mutex> lock(mMutex);
1071 while (mQueue.empty()) {
1072 mCondition.wait(lock);
Jamie Gennis28ef8d72012-04-05 20:34:54 -07001073 }
1074 sync = mQueue[0];
1075 frameNum = mFramesCompleted;
1076 }
1077 EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
1078 {
Mathias Agopian65421432017-03-08 11:49:05 -08001079 char name[64];
1080 snprintf(name, sizeof(name), "waiting for frame %u", (unsigned int)frameNum);
1081 ATRACE_NAME(name);
1082
Jamie Gennis28ef8d72012-04-05 20:34:54 -07001083 EGLint result = eglClientWaitSyncKHR(dpy, sync, 0, EGL_FOREVER_KHR);
1084 if (result == EGL_FALSE) {
1085 ALOGE("FrameCompletion: error waiting for fence: %#x", eglGetError());
1086 } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
1087 ALOGE("FrameCompletion: timeout waiting for fence");
1088 }
1089 eglDestroySyncKHR(dpy, sync);
1090 }
1091 {
Mathias Agopian65421432017-03-08 11:49:05 -08001092 std::lock_guard<std::mutex> lock(mMutex);
1093 mQueue.pop_front();
Jamie Gennis28ef8d72012-04-05 20:34:54 -07001094 mFramesCompleted++;
Mathias Agopian737b8962017-02-24 14:32:05 -08001095 ATRACE_INT("GPU Frames Outstanding", int32_t(mQueue.size()));
Jamie Gennis28ef8d72012-04-05 20:34:54 -07001096 }
Jamie Gennis28ef8d72012-04-05 20:34:54 -07001097 }
1098
1099 uint32_t mFramesQueued;
1100 uint32_t mFramesCompleted;
Mathias Agopian65421432017-03-08 11:49:05 -08001101 std::deque<EGLSyncKHR> mQueue;
1102 std::condition_variable mCondition;
1103 std::mutex mMutex;
Jamie Gennis28ef8d72012-04-05 20:34:54 -07001104};
1105
Dan Stozaa894d082015-02-19 15:27:36 -08001106EGLBoolean eglSwapBuffersWithDamageKHR(EGLDisplay dpy, EGLSurface draw,
1107 EGLint *rects, EGLint n_rects)
Mathias Agopian518ec112011-05-13 16:21:08 -07001108{
Jamie Gennis1c8e95c2012-02-23 19:27:23 -08001109 ATRACE_CALL();
Mathias Agopian518ec112011-05-13 16:21:08 -07001110 clearError();
1111
Jesse Hallb29e5e82012-04-04 16:53:42 -07001112 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001113 if (!dp) return EGL_FALSE;
1114
Jesse Hallb29e5e82012-04-04 16:53:42 -07001115 SurfaceRef _s(dp.get(), draw);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001116 if (!_s.get())
Mathias Agopian737b8962017-02-24 14:32:05 -08001117 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001118
Mathias Agopian518ec112011-05-13 16:21:08 -07001119 egl_surface_t const * const s = get_surface(draw);
Mathias Agopian7db993a2012-03-25 00:49:46 -07001120
Mathias Agopianed6d08b2013-04-16 16:39:46 -07001121 if (CC_UNLIKELY(dp->traceGpuCompletion)) {
1122 EGLSyncKHR sync = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, NULL);
1123 if (sync != EGL_NO_SYNC_KHR) {
1124 FrameCompletionThread::queueSync(sync);
1125 }
1126 }
1127
Mathias Agopian7db993a2012-03-25 00:49:46 -07001128 if (CC_UNLIKELY(dp->finishOnSwap)) {
1129 uint32_t pixel;
1130 egl_context_t * const c = get_context( egl_tls_t::getContext() );
1131 if (c) {
1132 // glReadPixels() ensures that the frame is complete
1133 s->cnx->hooks[c->version]->gl.glReadPixels(0,0,1,1,
1134 GL_RGBA,GL_UNSIGNED_BYTE,&pixel);
1135 }
1136 }
1137
Dan Stozaa894d082015-02-19 15:27:36 -08001138 if (n_rects == 0) {
1139 return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface);
1140 }
1141
Mathias Agopian65421432017-03-08 11:49:05 -08001142 std::vector<android_native_rect_t> androidRects((size_t)n_rects);
Dan Stozaa894d082015-02-19 15:27:36 -08001143 for (int r = 0; r < n_rects; ++r) {
1144 int offset = r * 4;
1145 int x = rects[offset];
1146 int y = rects[offset + 1];
1147 int width = rects[offset + 2];
1148 int height = rects[offset + 3];
1149 android_native_rect_t androidRect;
1150 androidRect.left = x;
1151 androidRect.top = y + height;
1152 androidRect.right = x + width;
1153 androidRect.bottom = y;
1154 androidRects.push_back(androidRect);
1155 }
Mathias Agopian65421432017-03-08 11:49:05 -08001156 native_window_set_surface_damage(s->getNativeWindow(), androidRects.data(), androidRects.size());
Dan Stozaa894d082015-02-19 15:27:36 -08001157
1158 if (s->cnx->egl.eglSwapBuffersWithDamageKHR) {
1159 return s->cnx->egl.eglSwapBuffersWithDamageKHR(dp->disp.dpy, s->surface,
1160 rects, n_rects);
1161 } else {
1162 return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface);
1163 }
1164}
1165
1166EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
1167{
1168 return eglSwapBuffersWithDamageKHR(dpy, surface, NULL, 0);
Mathias Agopian518ec112011-05-13 16:21:08 -07001169}
1170
1171EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface,
1172 NativePixmapType target)
1173{
1174 clearError();
1175
Jesse Hallb29e5e82012-04-04 16:53:42 -07001176 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001177 if (!dp) return EGL_FALSE;
1178
Jesse Hallb29e5e82012-04-04 16:53:42 -07001179 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001180 if (!_s.get())
Mathias Agopian737b8962017-02-24 14:32:05 -08001181 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001182
Mathias Agopian518ec112011-05-13 16:21:08 -07001183 egl_surface_t const * const s = get_surface(surface);
Mathias Agopianada798b2012-02-13 17:09:30 -08001184 return s->cnx->egl.eglCopyBuffers(dp->disp.dpy, s->surface, target);
Mathias Agopian518ec112011-05-13 16:21:08 -07001185}
1186
1187const char* eglQueryString(EGLDisplay dpy, EGLint name)
1188{
1189 clearError();
1190
Chia-I Wue57d1352016-08-15 16:10:02 +08001191 // Generate an error quietly when client extensions (as defined by
1192 // EGL_EXT_client_extensions) are queried. We do not want to rely on
1193 // validate_display to generate the error as validate_display would log
1194 // the error, which can be misleading.
1195 //
1196 // If we want to support EGL_EXT_client_extensions later, we can return
1197 // the client extension string here instead.
1198 if (dpy == EGL_NO_DISPLAY && name == EGL_EXTENSIONS)
Mathias Agopian737b8962017-02-24 14:32:05 -08001199 return setErrorQuiet(EGL_BAD_DISPLAY, (const char*)0);
Chia-I Wue57d1352016-08-15 16:10:02 +08001200
Jesse Hallb29e5e82012-04-04 16:53:42 -07001201 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001202 if (!dp) return (const char *) NULL;
1203
1204 switch (name) {
1205 case EGL_VENDOR:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001206 return dp->getVendorString();
Mathias Agopian518ec112011-05-13 16:21:08 -07001207 case EGL_VERSION:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001208 return dp->getVersionString();
Mathias Agopian518ec112011-05-13 16:21:08 -07001209 case EGL_EXTENSIONS:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001210 return dp->getExtensionString();
Mathias Agopian518ec112011-05-13 16:21:08 -07001211 case EGL_CLIENT_APIS:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001212 return dp->getClientApiString();
Mathias Agopian737b8962017-02-24 14:32:05 -08001213 default:
1214 break;
Mathias Agopian518ec112011-05-13 16:21:08 -07001215 }
1216 return setError(EGL_BAD_PARAMETER, (const char *)0);
1217}
1218
Mathias Agopianca088332013-03-28 17:44:13 -07001219EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name)
1220{
1221 clearError();
1222
1223 const egl_display_ptr dp = validate_display(dpy);
1224 if (!dp) return (const char *) NULL;
1225
1226 switch (name) {
1227 case EGL_VENDOR:
1228 return dp->disp.queryString.vendor;
1229 case EGL_VERSION:
1230 return dp->disp.queryString.version;
1231 case EGL_EXTENSIONS:
1232 return dp->disp.queryString.extensions;
1233 case EGL_CLIENT_APIS:
1234 return dp->disp.queryString.clientApi;
Mathias Agopian737b8962017-02-24 14:32:05 -08001235 default:
1236 break;
Mathias Agopianca088332013-03-28 17:44:13 -07001237 }
1238 return setError(EGL_BAD_PARAMETER, (const char *)0);
1239}
Mathias Agopian518ec112011-05-13 16:21:08 -07001240
1241// ----------------------------------------------------------------------------
1242// EGL 1.1
1243// ----------------------------------------------------------------------------
1244
1245EGLBoolean eglSurfaceAttrib(
1246 EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
1247{
1248 clearError();
1249
Jesse Hallb29e5e82012-04-04 16:53:42 -07001250 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001251 if (!dp) return EGL_FALSE;
1252
Jesse Hallb29e5e82012-04-04 16:53:42 -07001253 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001254 if (!_s.get())
Mathias Agopian737b8962017-02-24 14:32:05 -08001255 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001256
Pablo Ceballosc18be292016-05-31 14:55:42 -07001257 egl_surface_t * const s = get_surface(surface);
Pablo Ceballosccdfd602015-10-07 15:05:45 -07001258
Pablo Ceballos02b05da2016-02-02 17:53:18 -08001259 if (attribute == EGL_FRONT_BUFFER_AUTO_REFRESH_ANDROID) {
Mathias Agopian65421432017-03-08 11:49:05 -08001260 if (!s->getNativeWindow()) {
Brian Anderson069b3652016-07-22 10:32:47 -07001261 setError(EGL_BAD_SURFACE, EGL_FALSE);
1262 }
Mathias Agopian65421432017-03-08 11:49:05 -08001263 int err = native_window_set_auto_refresh(s->getNativeWindow(), value != 0);
1264 return (err == 0) ? EGL_TRUE : setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Pablo Ceballosccdfd602015-10-07 15:05:45 -07001265 }
1266
Pablo Ceballosc18be292016-05-31 14:55:42 -07001267 if (attribute == EGL_TIMESTAMPS_ANDROID) {
Mathias Agopian65421432017-03-08 11:49:05 -08001268 if (!s->getNativeWindow()) {
Mathias Agopian737b8962017-02-24 14:32:05 -08001269 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Brian Anderson069b3652016-07-22 10:32:47 -07001270 }
Mathias Agopian65421432017-03-08 11:49:05 -08001271 int err = native_window_enable_frame_timestamps(s->getNativeWindow(), value != 0);
1272 return (err == 0) ? EGL_TRUE : setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Pablo Ceballosc18be292016-05-31 14:55:42 -07001273 }
1274
Mathias Agopian518ec112011-05-13 16:21:08 -07001275 if (s->cnx->egl.eglSurfaceAttrib) {
1276 return s->cnx->egl.eglSurfaceAttrib(
Mathias Agopianada798b2012-02-13 17:09:30 -08001277 dp->disp.dpy, s->surface, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -07001278 }
Mathias Agopian737b8962017-02-24 14:32:05 -08001279 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001280}
1281
1282EGLBoolean eglBindTexImage(
1283 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1284{
1285 clearError();
1286
Jesse Hallb29e5e82012-04-04 16:53:42 -07001287 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001288 if (!dp) return EGL_FALSE;
1289
Jesse Hallb29e5e82012-04-04 16:53:42 -07001290 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001291 if (!_s.get())
Mathias Agopian737b8962017-02-24 14:32:05 -08001292 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001293
Mathias Agopian518ec112011-05-13 16:21:08 -07001294 egl_surface_t const * const s = get_surface(surface);
1295 if (s->cnx->egl.eglBindTexImage) {
1296 return s->cnx->egl.eglBindTexImage(
Mathias Agopianada798b2012-02-13 17:09:30 -08001297 dp->disp.dpy, s->surface, buffer);
Mathias Agopian518ec112011-05-13 16:21:08 -07001298 }
Mathias Agopian737b8962017-02-24 14:32:05 -08001299 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001300}
1301
1302EGLBoolean eglReleaseTexImage(
1303 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
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
Jesse Hallb29e5e82012-04-04 16:53:42 -07001310 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001311 if (!_s.get())
Mathias Agopian737b8962017-02-24 14:32:05 -08001312 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001313
Mathias Agopian518ec112011-05-13 16:21:08 -07001314 egl_surface_t const * const s = get_surface(surface);
1315 if (s->cnx->egl.eglReleaseTexImage) {
1316 return s->cnx->egl.eglReleaseTexImage(
Mathias Agopianada798b2012-02-13 17:09:30 -08001317 dp->disp.dpy, s->surface, buffer);
Mathias Agopian518ec112011-05-13 16:21:08 -07001318 }
Mathias Agopian737b8962017-02-24 14:32:05 -08001319 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001320}
1321
1322EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
1323{
1324 clearError();
1325
Jesse Hallb29e5e82012-04-04 16:53:42 -07001326 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001327 if (!dp) return EGL_FALSE;
1328
1329 EGLBoolean res = EGL_TRUE;
Mathias Agopianada798b2012-02-13 17:09:30 -08001330 egl_connection_t* const cnx = &gEGLImpl;
1331 if (cnx->dso && cnx->egl.eglSwapInterval) {
1332 res = cnx->egl.eglSwapInterval(dp->disp.dpy, interval);
Mathias Agopian518ec112011-05-13 16:21:08 -07001333 }
Mathias Agopianada798b2012-02-13 17:09:30 -08001334
Mathias Agopian518ec112011-05-13 16:21:08 -07001335 return res;
1336}
1337
1338
1339// ----------------------------------------------------------------------------
1340// EGL 1.2
1341// ----------------------------------------------------------------------------
1342
1343EGLBoolean eglWaitClient(void)
1344{
1345 clearError();
1346
Mathias Agopianada798b2012-02-13 17:09:30 -08001347 egl_connection_t* const cnx = &gEGLImpl;
1348 if (!cnx->dso)
Mathias Agopian737b8962017-02-24 14:32:05 -08001349 return setError(EGL_BAD_CONTEXT, (EGLBoolean)EGL_FALSE);
Mathias Agopianada798b2012-02-13 17:09:30 -08001350
1351 EGLBoolean res;
1352 if (cnx->egl.eglWaitClient) {
1353 res = cnx->egl.eglWaitClient();
1354 } else {
1355 res = cnx->egl.eglWaitGL();
Mathias Agopian518ec112011-05-13 16:21:08 -07001356 }
1357 return res;
1358}
1359
1360EGLBoolean eglBindAPI(EGLenum api)
1361{
1362 clearError();
1363
1364 if (egl_init_drivers() == EGL_FALSE) {
Mathias Agopian737b8962017-02-24 14:32:05 -08001365 return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001366 }
1367
1368 // bind this API on all EGLs
1369 EGLBoolean res = EGL_TRUE;
Mathias Agopianada798b2012-02-13 17:09:30 -08001370 egl_connection_t* const cnx = &gEGLImpl;
1371 if (cnx->dso && cnx->egl.eglBindAPI) {
1372 res = cnx->egl.eglBindAPI(api);
Mathias Agopian518ec112011-05-13 16:21:08 -07001373 }
1374 return res;
1375}
1376
1377EGLenum eglQueryAPI(void)
1378{
1379 clearError();
1380
1381 if (egl_init_drivers() == EGL_FALSE) {
Mathias Agopian737b8962017-02-24 14:32:05 -08001382 return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001383 }
1384
Mathias Agopianada798b2012-02-13 17:09:30 -08001385 egl_connection_t* const cnx = &gEGLImpl;
1386 if (cnx->dso && cnx->egl.eglQueryAPI) {
1387 return cnx->egl.eglQueryAPI();
Mathias Agopian518ec112011-05-13 16:21:08 -07001388 }
Mathias Agopianada798b2012-02-13 17:09:30 -08001389
Mathias Agopian518ec112011-05-13 16:21:08 -07001390 // or, it can only be OpenGL ES
1391 return EGL_OPENGL_ES_API;
1392}
1393
1394EGLBoolean eglReleaseThread(void)
1395{
1396 clearError();
1397
Mathias Agopianada798b2012-02-13 17:09:30 -08001398 egl_connection_t* const cnx = &gEGLImpl;
1399 if (cnx->dso && cnx->egl.eglReleaseThread) {
1400 cnx->egl.eglReleaseThread();
Mathias Agopian518ec112011-05-13 16:21:08 -07001401 }
Sai Kiran Korwar3ac517a2014-01-31 21:15:07 +05301402
1403 // If there is context bound to the thread, release it
1404 egl_display_t::loseCurrent(get_context(getContext()));
1405
Mathias Agopian518ec112011-05-13 16:21:08 -07001406 egl_tls_t::clearTLS();
Mathias Agopian518ec112011-05-13 16:21:08 -07001407 return EGL_TRUE;
1408}
1409
1410EGLSurface eglCreatePbufferFromClientBuffer(
1411 EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer,
1412 EGLConfig config, const EGLint *attrib_list)
1413{
1414 clearError();
1415
Jesse Hallb29e5e82012-04-04 16:53:42 -07001416 egl_connection_t* cnx = NULL;
1417 const egl_display_ptr dp = validate_display_connection(dpy, cnx);
1418 if (!dp) return EGL_FALSE;
Mathias Agopian518ec112011-05-13 16:21:08 -07001419 if (cnx->egl.eglCreatePbufferFromClientBuffer) {
1420 return cnx->egl.eglCreatePbufferFromClientBuffer(
Mathias Agopian7773c432012-02-13 20:06:08 -08001421 dp->disp.dpy, buftype, buffer, config, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001422 }
1423 return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE);
1424}
1425
1426// ----------------------------------------------------------------------------
1427// EGL_EGLEXT_VERSION 3
1428// ----------------------------------------------------------------------------
1429
1430EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface,
1431 const EGLint *attrib_list)
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.eglLockSurfaceKHR) {
1444 return s->cnx->egl.eglLockSurfaceKHR(
Mathias Agopianada798b2012-02-13 17:09:30 -08001445 dp->disp.dpy, s->surface, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001446 }
Mathias Agopian737b8962017-02-24 14:32:05 -08001447 return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001448}
1449
1450EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface)
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_FALSE;
1456
Jesse Hallb29e5e82012-04-04 16:53:42 -07001457 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001458 if (!_s.get())
Mathias Agopian737b8962017-02-24 14:32:05 -08001459 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001460
1461 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian518ec112011-05-13 16:21:08 -07001462 if (s->cnx->egl.eglUnlockSurfaceKHR) {
Mathias Agopianada798b2012-02-13 17:09:30 -08001463 return s->cnx->egl.eglUnlockSurfaceKHR(dp->disp.dpy, s->surface);
Mathias Agopian518ec112011-05-13 16:21:08 -07001464 }
Mathias Agopian737b8962017-02-24 14:32:05 -08001465 return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001466}
1467
1468EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
1469 EGLClientBuffer buffer, const EGLint *attrib_list)
1470{
1471 clearError();
1472
Jesse Hallb29e5e82012-04-04 16:53:42 -07001473 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001474 if (!dp) return EGL_NO_IMAGE_KHR;
1475
Jesse Hallb29e5e82012-04-04 16:53:42 -07001476 ContextRef _c(dp.get(), ctx);
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001477 egl_context_t * const c = _c.get();
Mathias Agopian518ec112011-05-13 16:21:08 -07001478
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001479 EGLImageKHR result = EGL_NO_IMAGE_KHR;
1480 egl_connection_t* const cnx = &gEGLImpl;
1481 if (cnx->dso && cnx->egl.eglCreateImageKHR) {
1482 result = cnx->egl.eglCreateImageKHR(
1483 dp->disp.dpy,
1484 c ? c->context : EGL_NO_CONTEXT,
1485 target, buffer, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001486 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001487 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001488}
1489
1490EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
1491{
1492 clearError();
1493
Jesse Hallb29e5e82012-04-04 16:53:42 -07001494 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001495 if (!dp) return EGL_FALSE;
1496
Steven Holte646a5c52012-06-04 20:02:11 -07001497 EGLBoolean result = EGL_FALSE;
Mathias Agopianada798b2012-02-13 17:09:30 -08001498 egl_connection_t* const cnx = &gEGLImpl;
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001499 if (cnx->dso && cnx->egl.eglDestroyImageKHR) {
Steven Holte646a5c52012-06-04 20:02:11 -07001500 result = cnx->egl.eglDestroyImageKHR(dp->disp.dpy, img);
Mathias Agopian518ec112011-05-13 16:21:08 -07001501 }
Steven Holte646a5c52012-06-04 20:02:11 -07001502 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001503}
1504
1505// ----------------------------------------------------------------------------
1506// EGL_EGLEXT_VERSION 5
1507// ----------------------------------------------------------------------------
1508
1509
1510EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
1511{
1512 clearError();
1513
Jesse Hallb29e5e82012-04-04 16:53:42 -07001514 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001515 if (!dp) return EGL_NO_SYNC_KHR;
1516
Mathias Agopian518ec112011-05-13 16:21:08 -07001517 EGLSyncKHR result = EGL_NO_SYNC_KHR;
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001518 egl_connection_t* const cnx = &gEGLImpl;
1519 if (cnx->dso && cnx->egl.eglCreateSyncKHR) {
1520 result = cnx->egl.eglCreateSyncKHR(dp->disp.dpy, type, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001521 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001522 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001523}
1524
1525EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
1526{
1527 clearError();
1528
Jesse Hallb29e5e82012-04-04 16:53:42 -07001529 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001530 if (!dp) return EGL_FALSE;
1531
Mathias Agopian518ec112011-05-13 16:21:08 -07001532 EGLBoolean result = EGL_FALSE;
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001533 egl_connection_t* const cnx = &gEGLImpl;
1534 if (cnx->dso && cnx->egl.eglDestroySyncKHR) {
1535 result = cnx->egl.eglDestroySyncKHR(dp->disp.dpy, sync);
Mathias Agopian518ec112011-05-13 16:21:08 -07001536 }
1537 return result;
1538}
1539
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -07001540EGLBoolean eglSignalSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode) {
1541 clearError();
1542
1543 const egl_display_ptr dp = validate_display(dpy);
1544 if (!dp) return EGL_FALSE;
1545
1546 EGLBoolean result = EGL_FALSE;
1547 egl_connection_t* const cnx = &gEGLImpl;
1548 if (cnx->dso && cnx->egl.eglSignalSyncKHR) {
1549 result = cnx->egl.eglSignalSyncKHR(
1550 dp->disp.dpy, sync, mode);
1551 }
1552 return result;
1553}
1554
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001555EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync,
1556 EGLint flags, EGLTimeKHR timeout)
Mathias Agopian518ec112011-05-13 16:21:08 -07001557{
1558 clearError();
1559
Jesse Hallb29e5e82012-04-04 16:53:42 -07001560 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001561 if (!dp) return EGL_FALSE;
1562
Mathias Agopian737b8962017-02-24 14:32:05 -08001563 EGLint result = EGL_FALSE;
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001564 egl_connection_t* const cnx = &gEGLImpl;
1565 if (cnx->dso && cnx->egl.eglClientWaitSyncKHR) {
1566 result = cnx->egl.eglClientWaitSyncKHR(
1567 dp->disp.dpy, sync, flags, timeout);
Mathias Agopian518ec112011-05-13 16:21:08 -07001568 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001569 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001570}
1571
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001572EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync,
1573 EGLint attribute, EGLint *value)
Mathias Agopian518ec112011-05-13 16:21:08 -07001574{
1575 clearError();
1576
Jesse Hallb29e5e82012-04-04 16:53:42 -07001577 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001578 if (!dp) return EGL_FALSE;
1579
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001580 EGLBoolean result = EGL_FALSE;
1581 egl_connection_t* const cnx = &gEGLImpl;
1582 if (cnx->dso && cnx->egl.eglGetSyncAttribKHR) {
1583 result = cnx->egl.eglGetSyncAttribKHR(
1584 dp->disp.dpy, sync, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -07001585 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001586 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001587}
1588
Season Li000d88f2015-07-01 11:39:40 -07001589EGLStreamKHR eglCreateStreamKHR(EGLDisplay dpy, const EGLint *attrib_list)
1590{
1591 clearError();
1592
1593 const egl_display_ptr dp = validate_display(dpy);
1594 if (!dp) return EGL_NO_STREAM_KHR;
1595
1596 EGLStreamKHR result = EGL_NO_STREAM_KHR;
1597 egl_connection_t* const cnx = &gEGLImpl;
1598 if (cnx->dso && cnx->egl.eglCreateStreamKHR) {
1599 result = cnx->egl.eglCreateStreamKHR(
1600 dp->disp.dpy, attrib_list);
1601 }
1602 return result;
1603}
1604
1605EGLBoolean eglDestroyStreamKHR(EGLDisplay dpy, EGLStreamKHR stream)
1606{
1607 clearError();
1608
1609 const egl_display_ptr dp = validate_display(dpy);
1610 if (!dp) return EGL_FALSE;
1611
1612 EGLBoolean result = EGL_FALSE;
1613 egl_connection_t* const cnx = &gEGLImpl;
1614 if (cnx->dso && cnx->egl.eglDestroyStreamKHR) {
1615 result = cnx->egl.eglDestroyStreamKHR(
1616 dp->disp.dpy, stream);
1617 }
1618 return result;
1619}
1620
1621EGLBoolean eglStreamAttribKHR(EGLDisplay dpy, EGLStreamKHR stream,
1622 EGLenum attribute, EGLint value)
1623{
1624 clearError();
1625
1626 const egl_display_ptr dp = validate_display(dpy);
1627 if (!dp) return EGL_FALSE;
1628
1629 EGLBoolean result = EGL_FALSE;
1630 egl_connection_t* const cnx = &gEGLImpl;
1631 if (cnx->dso && cnx->egl.eglStreamAttribKHR) {
1632 result = cnx->egl.eglStreamAttribKHR(
1633 dp->disp.dpy, stream, attribute, value);
1634 }
1635 return result;
1636}
1637
1638EGLBoolean eglQueryStreamKHR(EGLDisplay dpy, EGLStreamKHR stream,
1639 EGLenum attribute, EGLint *value)
1640{
1641 clearError();
1642
1643 const egl_display_ptr dp = validate_display(dpy);
1644 if (!dp) return EGL_FALSE;
1645
1646 EGLBoolean result = EGL_FALSE;
1647 egl_connection_t* const cnx = &gEGLImpl;
1648 if (cnx->dso && cnx->egl.eglQueryStreamKHR) {
1649 result = cnx->egl.eglQueryStreamKHR(
1650 dp->disp.dpy, stream, attribute, value);
1651 }
1652 return result;
1653}
1654
1655EGLBoolean eglQueryStreamu64KHR(EGLDisplay dpy, EGLStreamKHR stream,
1656 EGLenum attribute, EGLuint64KHR *value)
1657{
1658 clearError();
1659
1660 const egl_display_ptr dp = validate_display(dpy);
1661 if (!dp) return EGL_FALSE;
1662
1663 EGLBoolean result = EGL_FALSE;
1664 egl_connection_t* const cnx = &gEGLImpl;
1665 if (cnx->dso && cnx->egl.eglQueryStreamu64KHR) {
1666 result = cnx->egl.eglQueryStreamu64KHR(
1667 dp->disp.dpy, stream, attribute, value);
1668 }
1669 return result;
1670}
1671
1672EGLBoolean eglQueryStreamTimeKHR(EGLDisplay dpy, EGLStreamKHR stream,
1673 EGLenum attribute, EGLTimeKHR *value)
1674{
1675 clearError();
1676
1677 const egl_display_ptr dp = validate_display(dpy);
1678 if (!dp) return EGL_FALSE;
1679
1680 EGLBoolean result = EGL_FALSE;
1681 egl_connection_t* const cnx = &gEGLImpl;
1682 if (cnx->dso && cnx->egl.eglQueryStreamTimeKHR) {
1683 result = cnx->egl.eglQueryStreamTimeKHR(
1684 dp->disp.dpy, stream, attribute, value);
1685 }
1686 return result;
1687}
1688
1689EGLSurface eglCreateStreamProducerSurfaceKHR(EGLDisplay dpy, EGLConfig config,
1690 EGLStreamKHR stream, const EGLint *attrib_list)
1691{
1692 clearError();
1693
1694 egl_display_ptr dp = validate_display(dpy);
1695 if (!dp) return EGL_NO_SURFACE;
1696
1697 egl_connection_t* const cnx = &gEGLImpl;
1698 if (cnx->dso && cnx->egl.eglCreateStreamProducerSurfaceKHR) {
1699 EGLSurface surface = cnx->egl.eglCreateStreamProducerSurfaceKHR(
1700 dp->disp.dpy, config, stream, attrib_list);
1701 if (surface != EGL_NO_SURFACE) {
1702 egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL,
1703 surface, cnx);
1704 return s;
1705 }
1706 }
1707 return EGL_NO_SURFACE;
1708}
1709
1710EGLBoolean eglStreamConsumerGLTextureExternalKHR(EGLDisplay dpy,
1711 EGLStreamKHR stream)
1712{
1713 clearError();
1714
1715 const egl_display_ptr dp = validate_display(dpy);
1716 if (!dp) return EGL_FALSE;
1717
1718 EGLBoolean result = EGL_FALSE;
1719 egl_connection_t* const cnx = &gEGLImpl;
1720 if (cnx->dso && cnx->egl.eglStreamConsumerGLTextureExternalKHR) {
1721 result = cnx->egl.eglStreamConsumerGLTextureExternalKHR(
1722 dp->disp.dpy, stream);
1723 }
1724 return result;
1725}
1726
1727EGLBoolean eglStreamConsumerAcquireKHR(EGLDisplay dpy,
1728 EGLStreamKHR stream)
1729{
1730 clearError();
1731
1732 const egl_display_ptr dp = validate_display(dpy);
1733 if (!dp) return EGL_FALSE;
1734
1735 EGLBoolean result = EGL_FALSE;
1736 egl_connection_t* const cnx = &gEGLImpl;
1737 if (cnx->dso && cnx->egl.eglStreamConsumerAcquireKHR) {
1738 result = cnx->egl.eglStreamConsumerAcquireKHR(
1739 dp->disp.dpy, stream);
1740 }
1741 return result;
1742}
1743
1744EGLBoolean eglStreamConsumerReleaseKHR(EGLDisplay dpy,
1745 EGLStreamKHR stream)
1746{
1747 clearError();
1748
1749 const egl_display_ptr dp = validate_display(dpy);
1750 if (!dp) return EGL_FALSE;
1751
1752 EGLBoolean result = EGL_FALSE;
1753 egl_connection_t* const cnx = &gEGLImpl;
1754 if (cnx->dso && cnx->egl.eglStreamConsumerReleaseKHR) {
1755 result = cnx->egl.eglStreamConsumerReleaseKHR(
1756 dp->disp.dpy, stream);
1757 }
1758 return result;
1759}
1760
1761EGLNativeFileDescriptorKHR eglGetStreamFileDescriptorKHR(
1762 EGLDisplay dpy, EGLStreamKHR stream)
1763{
1764 clearError();
1765
1766 const egl_display_ptr dp = validate_display(dpy);
1767 if (!dp) return EGL_NO_FILE_DESCRIPTOR_KHR;
1768
1769 EGLNativeFileDescriptorKHR result = EGL_NO_FILE_DESCRIPTOR_KHR;
1770 egl_connection_t* const cnx = &gEGLImpl;
1771 if (cnx->dso && cnx->egl.eglGetStreamFileDescriptorKHR) {
1772 result = cnx->egl.eglGetStreamFileDescriptorKHR(
1773 dp->disp.dpy, stream);
1774 }
1775 return result;
1776}
1777
1778EGLStreamKHR eglCreateStreamFromFileDescriptorKHR(
1779 EGLDisplay dpy, EGLNativeFileDescriptorKHR file_descriptor)
1780{
1781 clearError();
1782
1783 const egl_display_ptr dp = validate_display(dpy);
1784 if (!dp) return EGL_NO_STREAM_KHR;
1785
1786 EGLStreamKHR result = EGL_NO_STREAM_KHR;
1787 egl_connection_t* const cnx = &gEGLImpl;
1788 if (cnx->dso && cnx->egl.eglCreateStreamFromFileDescriptorKHR) {
1789 result = cnx->egl.eglCreateStreamFromFileDescriptorKHR(
1790 dp->disp.dpy, file_descriptor);
1791 }
1792 return result;
1793}
1794
Mathias Agopian518ec112011-05-13 16:21:08 -07001795// ----------------------------------------------------------------------------
Mathias Agopian2bb71682013-03-27 17:32:41 -07001796// EGL_EGLEXT_VERSION 15
1797// ----------------------------------------------------------------------------
1798
1799EGLint eglWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags) {
1800 clearError();
1801 const egl_display_ptr dp = validate_display(dpy);
1802 if (!dp) return EGL_FALSE;
1803 EGLint result = EGL_FALSE;
1804 egl_connection_t* const cnx = &gEGLImpl;
1805 if (cnx->dso && cnx->egl.eglWaitSyncKHR) {
1806 result = cnx->egl.eglWaitSyncKHR(dp->disp.dpy, sync, flags);
1807 }
1808 return result;
1809}
1810
1811// ----------------------------------------------------------------------------
Mathias Agopian518ec112011-05-13 16:21:08 -07001812// ANDROID extensions
1813// ----------------------------------------------------------------------------
1814
Jamie Gennis331841b2012-09-06 14:52:00 -07001815EGLint eglDupNativeFenceFDANDROID(EGLDisplay dpy, EGLSyncKHR sync)
1816{
1817 clearError();
1818
1819 const egl_display_ptr dp = validate_display(dpy);
1820 if (!dp) return EGL_NO_NATIVE_FENCE_FD_ANDROID;
1821
1822 EGLint result = EGL_NO_NATIVE_FENCE_FD_ANDROID;
1823 egl_connection_t* const cnx = &gEGLImpl;
1824 if (cnx->dso && cnx->egl.eglDupNativeFenceFDANDROID) {
1825 result = cnx->egl.eglDupNativeFenceFDANDROID(dp->disp.dpy, sync);
1826 }
1827 return result;
1828}
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001829
Andy McFadden72841452013-03-01 16:25:32 -08001830EGLBoolean eglPresentationTimeANDROID(EGLDisplay dpy, EGLSurface surface,
1831 EGLnsecsANDROID time)
1832{
1833 clearError();
1834
1835 const egl_display_ptr dp = validate_display(dpy);
1836 if (!dp) {
1837 return EGL_FALSE;
1838 }
1839
1840 SurfaceRef _s(dp.get(), surface);
1841 if (!_s.get()) {
1842 setError(EGL_BAD_SURFACE, EGL_FALSE);
1843 return EGL_FALSE;
1844 }
1845
1846 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian65421432017-03-08 11:49:05 -08001847 native_window_set_buffers_timestamp(s->getNativeWindow(), time);
Andy McFadden72841452013-03-01 16:25:32 -08001848
1849 return EGL_TRUE;
1850}
1851
Craig Donner60761072017-01-27 12:30:44 -08001852EGLClientBuffer eglGetNativeClientBufferANDROID(const AHardwareBuffer *buffer) {
1853 clearError();
Craig Donner60761072017-01-27 12:30:44 -08001854 if (!buffer) return setError(EGL_BAD_PARAMETER, (EGLClientBuffer)0);
Mathias Agopian61963402017-02-24 16:38:15 -08001855 return const_cast<ANativeWindowBuffer *>(AHardwareBuffer_to_ANativeWindowBuffer(buffer));
Craig Donner60761072017-01-27 12:30:44 -08001856}
1857
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001858// ----------------------------------------------------------------------------
1859// NVIDIA extensions
1860// ----------------------------------------------------------------------------
1861EGLuint64NV eglGetSystemTimeFrequencyNV()
1862{
1863 clearError();
1864
1865 if (egl_init_drivers() == EGL_FALSE) {
Mathias Agopian737b8962017-02-24 14:32:05 -08001866 return setError(EGL_BAD_PARAMETER, (EGLuint64NV)EGL_FALSE);
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001867 }
1868
1869 EGLuint64NV ret = 0;
Mathias Agopianada798b2012-02-13 17:09:30 -08001870 egl_connection_t* const cnx = &gEGLImpl;
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001871
Mathias Agopianada798b2012-02-13 17:09:30 -08001872 if (cnx->dso && cnx->egl.eglGetSystemTimeFrequencyNV) {
1873 return cnx->egl.eglGetSystemTimeFrequencyNV();
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001874 }
1875
Mathias Agopian737b8962017-02-24 14:32:05 -08001876 return setErrorQuiet(EGL_BAD_DISPLAY, (EGLuint64NV)0);
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001877}
1878
1879EGLuint64NV eglGetSystemTimeNV()
1880{
1881 clearError();
1882
1883 if (egl_init_drivers() == EGL_FALSE) {
Mathias Agopian737b8962017-02-24 14:32:05 -08001884 return setError(EGL_BAD_PARAMETER, (EGLuint64NV)EGL_FALSE);
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001885 }
1886
1887 EGLuint64NV ret = 0;
Mathias Agopianada798b2012-02-13 17:09:30 -08001888 egl_connection_t* const cnx = &gEGLImpl;
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001889
Mathias Agopianada798b2012-02-13 17:09:30 -08001890 if (cnx->dso && cnx->egl.eglGetSystemTimeNV) {
1891 return cnx->egl.eglGetSystemTimeNV();
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001892 }
1893
Mathias Agopian737b8962017-02-24 14:32:05 -08001894 return setErrorQuiet(EGL_BAD_DISPLAY, (EGLuint64NV)0);
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001895}
Dan Stozaa894d082015-02-19 15:27:36 -08001896
1897// ----------------------------------------------------------------------------
1898// Partial update extension
1899// ----------------------------------------------------------------------------
1900EGLBoolean eglSetDamageRegionKHR(EGLDisplay dpy, EGLSurface surface,
1901 EGLint *rects, EGLint n_rects)
1902{
1903 clearError();
1904
1905 const egl_display_ptr dp = validate_display(dpy);
1906 if (!dp) {
1907 setError(EGL_BAD_DISPLAY, EGL_FALSE);
1908 return EGL_FALSE;
1909 }
1910
1911 SurfaceRef _s(dp.get(), surface);
1912 if (!_s.get()) {
1913 setError(EGL_BAD_SURFACE, EGL_FALSE);
1914 return EGL_FALSE;
1915 }
1916
1917 egl_surface_t const * const s = get_surface(surface);
1918 if (s->cnx->egl.eglSetDamageRegionKHR) {
1919 return s->cnx->egl.eglSetDamageRegionKHR(dp->disp.dpy, s->surface,
1920 rects, n_rects);
1921 }
1922
1923 return EGL_FALSE;
1924}
Pablo Ceballosc18be292016-05-31 14:55:42 -07001925
Brian Anderson1049d1d2016-12-16 17:25:57 -08001926EGLBoolean eglGetNextFrameIdANDROID(EGLDisplay dpy, EGLSurface surface,
1927 EGLuint64KHR *frameId) {
1928 clearError();
1929
1930 const egl_display_ptr dp = validate_display(dpy);
1931 if (!dp) {
Mathias Agopian737b8962017-02-24 14:32:05 -08001932 return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
Brian Anderson1049d1d2016-12-16 17:25:57 -08001933 }
1934
1935 SurfaceRef _s(dp.get(), surface);
1936 if (!_s.get()) {
Mathias Agopian737b8962017-02-24 14:32:05 -08001937 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Brian Anderson1049d1d2016-12-16 17:25:57 -08001938 }
1939
1940 egl_surface_t const * const s = get_surface(surface);
1941
Mathias Agopian65421432017-03-08 11:49:05 -08001942 if (!s->getNativeWindow()) {
Mathias Agopian737b8962017-02-24 14:32:05 -08001943 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Brian Anderson1049d1d2016-12-16 17:25:57 -08001944 }
1945
1946 uint64_t nextFrameId = 0;
Mathias Agopian65421432017-03-08 11:49:05 -08001947 int ret = native_window_get_next_frame_id(s->getNativeWindow(), &nextFrameId);
Brian Anderson1049d1d2016-12-16 17:25:57 -08001948
Mathias Agopian65421432017-03-08 11:49:05 -08001949 if (ret != 0) {
Brian Anderson1049d1d2016-12-16 17:25:57 -08001950 // This should not happen. Return an error that is not in the spec
1951 // so it's obvious something is very wrong.
1952 ALOGE("eglGetNextFrameId: Unexpected error.");
Mathias Agopian737b8962017-02-24 14:32:05 -08001953 return setError(EGL_NOT_INITIALIZED, (EGLBoolean)EGL_FALSE);
Brian Anderson1049d1d2016-12-16 17:25:57 -08001954 }
1955
1956 *frameId = nextFrameId;
1957 return EGL_TRUE;
1958}
1959
Brian Anderson0a61b0c2016-12-07 14:55:56 -08001960EGLBoolean eglGetCompositorTimingANDROID(EGLDisplay dpy, EGLSurface surface,
1961 EGLint numTimestamps, const EGLint *names, EGLnsecsANDROID *values)
1962{
1963 clearError();
1964
1965 const egl_display_ptr dp = validate_display(dpy);
1966 if (!dp) {
Mathias Agopian737b8962017-02-24 14:32:05 -08001967 return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
Brian Anderson0a61b0c2016-12-07 14:55:56 -08001968 }
1969
1970 SurfaceRef _s(dp.get(), surface);
1971 if (!_s.get()) {
Mathias Agopian737b8962017-02-24 14:32:05 -08001972 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Brian Anderson0a61b0c2016-12-07 14:55:56 -08001973 }
1974
1975 egl_surface_t const * const s = get_surface(surface);
1976
Mathias Agopian65421432017-03-08 11:49:05 -08001977 if (!s->getNativeWindow()) {
Mathias Agopian737b8962017-02-24 14:32:05 -08001978 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Brian Anderson0a61b0c2016-12-07 14:55:56 -08001979 }
1980
1981 nsecs_t* compositeDeadline = nullptr;
1982 nsecs_t* compositeInterval = nullptr;
1983 nsecs_t* compositeToPresentLatency = nullptr;
1984
1985 for (int i = 0; i < numTimestamps; i++) {
1986 switch (names[i]) {
1987 case EGL_COMPOSITE_DEADLINE_ANDROID:
1988 compositeDeadline = &values[i];
1989 break;
1990 case EGL_COMPOSITE_INTERVAL_ANDROID:
1991 compositeInterval = &values[i];
1992 break;
1993 case EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID:
1994 compositeToPresentLatency = &values[i];
1995 break;
1996 default:
Mathias Agopian737b8962017-02-24 14:32:05 -08001997 return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE);
Brian Anderson0a61b0c2016-12-07 14:55:56 -08001998 }
1999 }
2000
Mathias Agopian65421432017-03-08 11:49:05 -08002001 int ret = native_window_get_compositor_timing(s->getNativeWindow(),
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002002 compositeDeadline, compositeInterval, compositeToPresentLatency);
2003
2004 switch (ret) {
Mathias Agopian65421432017-03-08 11:49:05 -08002005 case 0:
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002006 return EGL_TRUE;
Mathias Agopian65421432017-03-08 11:49:05 -08002007 case -ENOSYS:
Mathias Agopian737b8962017-02-24 14:32:05 -08002008 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002009 default:
2010 // This should not happen. Return an error that is not in the spec
2011 // so it's obvious something is very wrong.
2012 ALOGE("eglGetCompositorTiming: Unexpected error.");
Mathias Agopian737b8962017-02-24 14:32:05 -08002013 return setError(EGL_NOT_INITIALIZED, (EGLBoolean)EGL_FALSE);
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002014 }
2015}
2016
2017EGLBoolean eglGetCompositorTimingSupportedANDROID(
2018 EGLDisplay dpy, EGLSurface surface, EGLint name)
2019{
2020 clearError();
2021
2022 const egl_display_ptr dp = validate_display(dpy);
2023 if (!dp) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002024 return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002025 }
2026
2027 SurfaceRef _s(dp.get(), surface);
2028 if (!_s.get()) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002029 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002030 }
2031
2032 egl_surface_t const * const s = get_surface(surface);
2033
Mathias Agopian65421432017-03-08 11:49:05 -08002034 ANativeWindow* window = s->getNativeWindow();
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002035 if (!window) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002036 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002037 }
2038
2039 switch (name) {
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002040 case EGL_COMPOSITE_DEADLINE_ANDROID:
2041 case EGL_COMPOSITE_INTERVAL_ANDROID:
2042 case EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID:
2043 return EGL_TRUE;
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002044 default:
2045 return EGL_FALSE;
2046 }
2047}
2048
Pablo Ceballosc18be292016-05-31 14:55:42 -07002049EGLBoolean eglGetFrameTimestampsANDROID(EGLDisplay dpy, EGLSurface surface,
Brian Anderson1049d1d2016-12-16 17:25:57 -08002050 EGLuint64KHR frameId, EGLint numTimestamps, const EGLint *timestamps,
Pablo Ceballosc18be292016-05-31 14:55:42 -07002051 EGLnsecsANDROID *values)
2052{
2053 clearError();
2054
2055 const egl_display_ptr dp = validate_display(dpy);
2056 if (!dp) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002057 return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
Pablo Ceballosc18be292016-05-31 14:55:42 -07002058 }
2059
2060 SurfaceRef _s(dp.get(), surface);
2061 if (!_s.get()) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002062 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Pablo Ceballosc18be292016-05-31 14:55:42 -07002063 }
2064
2065 egl_surface_t const * const s = get_surface(surface);
2066
Mathias Agopian65421432017-03-08 11:49:05 -08002067 if (!s->getNativeWindow()) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002068 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Pablo Ceballosc18be292016-05-31 14:55:42 -07002069 }
2070
Brian Andersondbd0ea82016-07-22 09:38:59 -07002071 nsecs_t* requestedPresentTime = nullptr;
Pablo Ceballosc18be292016-05-31 14:55:42 -07002072 nsecs_t* acquireTime = nullptr;
Brian Andersonf7fd56a2016-09-02 10:10:04 -07002073 nsecs_t* latchTime = nullptr;
2074 nsecs_t* firstRefreshStartTime = nullptr;
Brian Andersonb04c6f02016-10-21 12:57:46 -07002075 nsecs_t* gpuCompositionDoneTime = nullptr;
Brian Andersonf7fd56a2016-09-02 10:10:04 -07002076 nsecs_t* lastRefreshStartTime = nullptr;
Brian Anderson069b3652016-07-22 10:32:47 -07002077 nsecs_t* displayPresentTime = nullptr;
Brian Andersonf7fd56a2016-09-02 10:10:04 -07002078 nsecs_t* dequeueReadyTime = nullptr;
Pablo Ceballosc18be292016-05-31 14:55:42 -07002079 nsecs_t* releaseTime = nullptr;
2080
2081 for (int i = 0; i < numTimestamps; i++) {
2082 switch (timestamps[i]) {
Brian Andersondbd0ea82016-07-22 09:38:59 -07002083 case EGL_REQUESTED_PRESENT_TIME_ANDROID:
2084 requestedPresentTime = &values[i];
Pablo Ceballosc18be292016-05-31 14:55:42 -07002085 break;
2086 case EGL_RENDERING_COMPLETE_TIME_ANDROID:
2087 acquireTime = &values[i];
2088 break;
Brian Andersonf7fd56a2016-09-02 10:10:04 -07002089 case EGL_COMPOSITION_LATCH_TIME_ANDROID:
2090 latchTime = &values[i];
Pablo Ceballosc18be292016-05-31 14:55:42 -07002091 break;
Brian Andersonf7fd56a2016-09-02 10:10:04 -07002092 case EGL_FIRST_COMPOSITION_START_TIME_ANDROID:
2093 firstRefreshStartTime = &values[i];
2094 break;
2095 case EGL_LAST_COMPOSITION_START_TIME_ANDROID:
2096 lastRefreshStartTime = &values[i];
2097 break;
Brian Andersonb04c6f02016-10-21 12:57:46 -07002098 case EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID:
2099 gpuCompositionDoneTime = &values[i];
Pablo Ceballosc18be292016-05-31 14:55:42 -07002100 break;
Brian Anderson069b3652016-07-22 10:32:47 -07002101 case EGL_DISPLAY_PRESENT_TIME_ANDROID:
2102 displayPresentTime = &values[i];
2103 break;
Brian Andersonf7fd56a2016-09-02 10:10:04 -07002104 case EGL_DEQUEUE_READY_TIME_ANDROID:
2105 dequeueReadyTime = &values[i];
2106 break;
Pablo Ceballosc18be292016-05-31 14:55:42 -07002107 case EGL_READS_DONE_TIME_ANDROID:
2108 releaseTime = &values[i];
2109 break;
2110 default:
Mathias Agopian737b8962017-02-24 14:32:05 -08002111 return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE);
Pablo Ceballosc18be292016-05-31 14:55:42 -07002112 }
2113 }
2114
Mathias Agopian65421432017-03-08 11:49:05 -08002115 int ret = native_window_get_frame_timestamps(s->getNativeWindow(), frameId,
Brian Andersonf7fd56a2016-09-02 10:10:04 -07002116 requestedPresentTime, acquireTime, latchTime, firstRefreshStartTime,
Brian Andersonb04c6f02016-10-21 12:57:46 -07002117 lastRefreshStartTime, gpuCompositionDoneTime, displayPresentTime,
Brian Anderson4e606e32017-03-16 15:34:57 -07002118 dequeueReadyTime, releaseTime);
Pablo Ceballosc18be292016-05-31 14:55:42 -07002119
Brian Anderson069b3652016-07-22 10:32:47 -07002120 switch (ret) {
Mathias Agopian65421432017-03-08 11:49:05 -08002121 case 0:
Mathias Agopian737b8962017-02-24 14:32:05 -08002122 return EGL_TRUE;
Mathias Agopian65421432017-03-08 11:49:05 -08002123 case -ENOENT:
Mathias Agopian737b8962017-02-24 14:32:05 -08002124 return setError(EGL_BAD_ACCESS, (EGLBoolean)EGL_FALSE);
Mathias Agopian65421432017-03-08 11:49:05 -08002125 case -ENOSYS:
Mathias Agopian737b8962017-02-24 14:32:05 -08002126 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian65421432017-03-08 11:49:05 -08002127 case -EINVAL:
Mathias Agopian737b8962017-02-24 14:32:05 -08002128 return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE);
2129 default:
2130 // This should not happen. Return an error that is not in the spec
2131 // so it's obvious something is very wrong.
2132 ALOGE("eglGetFrameTimestamps: Unexpected error.");
2133 return setError(EGL_NOT_INITIALIZED, (EGLBoolean)EGL_FALSE);
Pablo Ceballosc18be292016-05-31 14:55:42 -07002134 }
Pablo Ceballosc18be292016-05-31 14:55:42 -07002135}
2136
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002137EGLBoolean eglGetFrameTimestampSupportedANDROID(
2138 EGLDisplay dpy, EGLSurface surface, EGLint timestamp)
Pablo Ceballosc18be292016-05-31 14:55:42 -07002139{
2140 clearError();
2141
2142 const egl_display_ptr dp = validate_display(dpy);
2143 if (!dp) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002144 return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
Pablo Ceballosc18be292016-05-31 14:55:42 -07002145 }
2146
2147 SurfaceRef _s(dp.get(), surface);
2148 if (!_s.get()) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002149 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Brian Anderson069b3652016-07-22 10:32:47 -07002150 }
2151
2152 egl_surface_t const * const s = get_surface(surface);
2153
Mathias Agopian65421432017-03-08 11:49:05 -08002154 ANativeWindow* window = s->getNativeWindow();
Brian Anderson069b3652016-07-22 10:32:47 -07002155 if (!window) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002156 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Pablo Ceballosc18be292016-05-31 14:55:42 -07002157 }
2158
2159 switch (timestamp) {
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002160 case EGL_COMPOSITE_DEADLINE_ANDROID:
2161 case EGL_COMPOSITE_INTERVAL_ANDROID:
2162 case EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID:
Brian Andersondbd0ea82016-07-22 09:38:59 -07002163 case EGL_REQUESTED_PRESENT_TIME_ANDROID:
Pablo Ceballosc18be292016-05-31 14:55:42 -07002164 case EGL_RENDERING_COMPLETE_TIME_ANDROID:
Brian Andersonf7fd56a2016-09-02 10:10:04 -07002165 case EGL_COMPOSITION_LATCH_TIME_ANDROID:
2166 case EGL_FIRST_COMPOSITION_START_TIME_ANDROID:
2167 case EGL_LAST_COMPOSITION_START_TIME_ANDROID:
Brian Andersonb04c6f02016-10-21 12:57:46 -07002168 case EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID:
Brian Anderson4e606e32017-03-16 15:34:57 -07002169 case EGL_DISPLAY_PRESENT_TIME_ANDROID:
Brian Andersonf7fd56a2016-09-02 10:10:04 -07002170 case EGL_DEQUEUE_READY_TIME_ANDROID:
Pablo Ceballosc18be292016-05-31 14:55:42 -07002171 case EGL_READS_DONE_TIME_ANDROID:
2172 return EGL_TRUE;
2173 default:
2174 return EGL_FALSE;
2175 }
2176}