blob: f9229adf4dabb05b83f7b975bb06e67edff8fbf5 [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
Courtney Goeltzenleuchter21b33cb2017-04-17 17:31:29 -060082// clang-format off
Mathias Agopian311b4792017-02-28 15:00:49 -080083char const * const gBuiltinExtensionString =
Jesse Hall21558da2013-08-06 15:31:22 -070084 "EGL_KHR_get_all_proc_addresses "
85 "EGL_ANDROID_presentation_time "
Dan Stozaa894d082015-02-19 15:27:36 -080086 "EGL_KHR_swap_buffers_with_damage "
Craig Donner60761072017-01-27 12:30:44 -080087 "EGL_ANDROID_get_native_client_buffer "
Pablo Ceballos02b05da2016-02-02 17:53:18 -080088 "EGL_ANDROID_front_buffer_auto_refresh "
Pablo Ceballosc18be292016-05-31 14:55:42 -070089 "EGL_ANDROID_get_frame_timestamps "
Courtney Goeltzenleuchter21b33cb2017-04-17 17:31:29 -060090 "EGL_EXT_gl_colorspace_scrgb_linear "
91 "EGL_EXT_gl_colorspace_display_p3_linear "
92 "EGL_EXT_gl_colorspace_display_p3 "
Jesse Hall21558da2013-08-06 15:31:22 -070093 ;
Mathias Agopian311b4792017-02-28 15:00:49 -080094
95char const * const gExtensionString =
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070096 "EGL_KHR_image " // mandatory
97 "EGL_KHR_image_base " // mandatory
98 "EGL_KHR_image_pixmap "
99 "EGL_KHR_lock_surface "
Jesse Hallc2e41222013-08-08 13:40:22 -0700100 "EGL_KHR_gl_colorspace "
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700101 "EGL_KHR_gl_texture_2D_image "
Season Li000d88f2015-07-01 11:39:40 -0700102 "EGL_KHR_gl_texture_3D_image "
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700103 "EGL_KHR_gl_texture_cubemap_image "
104 "EGL_KHR_gl_renderbuffer_image "
105 "EGL_KHR_reusable_sync "
106 "EGL_KHR_fence_sync "
Jamie Gennisf6d1c392013-04-25 18:48:41 -0700107 "EGL_KHR_create_context "
Season Li000d88f2015-07-01 11:39:40 -0700108 "EGL_KHR_config_attribs "
109 "EGL_KHR_surfaceless_context "
110 "EGL_KHR_stream "
111 "EGL_KHR_stream_fifo "
112 "EGL_KHR_stream_producer_eglsurface "
113 "EGL_KHR_stream_consumer_gltexture "
114 "EGL_KHR_stream_cross_process_fd "
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700115 "EGL_EXT_create_context_robustness "
116 "EGL_NV_system_time "
117 "EGL_ANDROID_image_native_buffer " // mandatory
Mathias Agopian2bb71682013-03-27 17:32:41 -0700118 "EGL_KHR_wait_sync " // strongly recommended
Jamie Gennisdbe92452013-09-23 17:22:10 -0700119 "EGL_ANDROID_recordable " // mandatory
Dan Stozaa894d082015-02-19 15:27:36 -0800120 "EGL_KHR_partial_update " // strongly recommended
Courtney Goeltzenleuchter0e4e3952016-11-16 13:53:40 -0700121 "EGL_EXT_pixel_format_float "
Dan Stozaa894d082015-02-19 15:27:36 -0800122 "EGL_EXT_buffer_age " // strongly recommended with partial_update
Jesse Hall408e59f2015-04-24 01:40:42 -0700123 "EGL_KHR_create_context_no_error "
Pablo Ceballosceb9ee72016-04-13 11:17:32 -0700124 "EGL_KHR_mutable_render_buffer "
Mika Isojärvif37864b2016-04-15 11:58:56 -0700125 "EGL_EXT_yuv_surface "
Craig Donneraec86972016-04-28 18:09:40 -0700126 "EGL_EXT_protected_content "
Christian Poetzscha7805f62016-12-01 16:34:39 +0000127 "EGL_IMG_context_priority "
Pyry Haulos51d53c42017-03-06 09:39:09 -0800128 "EGL_KHR_no_config_context "
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700129 ;
Courtney Goeltzenleuchter21b33cb2017-04-17 17:31:29 -0600130// clang-format on
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700131
132// extensions not exposed to applications but used by the ANDROID system
133// "EGL_ANDROID_blob_cache " // strongly recommended
134// "EGL_IMG_hibernate_process " // optional
135// "EGL_ANDROID_native_fence_sync " // strongly recommended
136// "EGL_ANDROID_framebuffer_target " // mandatory for HWC 1.1
Jamie Gennisdbe92452013-09-23 17:22:10 -0700137// "EGL_ANDROID_image_crop " // optional
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700138
139/*
140 * EGL Extensions entry-points exposed to 3rd party applications
141 * (keep in sync with gExtensionString above)
142 *
143 */
144static const extention_map_t sExtensionMap[] = {
145 // EGL_KHR_lock_surface
Mathias Agopian518ec112011-05-13 16:21:08 -0700146 { "eglLockSurfaceKHR",
147 (__eglMustCastToProperFunctionPointerType)&eglLockSurfaceKHR },
148 { "eglUnlockSurfaceKHR",
149 (__eglMustCastToProperFunctionPointerType)&eglUnlockSurfaceKHR },
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700150
151 // EGL_KHR_image, EGL_KHR_image_base
Mathias Agopian518ec112011-05-13 16:21:08 -0700152 { "eglCreateImageKHR",
153 (__eglMustCastToProperFunctionPointerType)&eglCreateImageKHR },
154 { "eglDestroyImageKHR",
155 (__eglMustCastToProperFunctionPointerType)&eglDestroyImageKHR },
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700156
157 // EGL_KHR_reusable_sync, EGL_KHR_fence_sync
158 { "eglCreateSyncKHR",
159 (__eglMustCastToProperFunctionPointerType)&eglCreateSyncKHR },
160 { "eglDestroySyncKHR",
161 (__eglMustCastToProperFunctionPointerType)&eglDestroySyncKHR },
162 { "eglClientWaitSyncKHR",
163 (__eglMustCastToProperFunctionPointerType)&eglClientWaitSyncKHR },
164 { "eglSignalSyncKHR",
165 (__eglMustCastToProperFunctionPointerType)&eglSignalSyncKHR },
166 { "eglGetSyncAttribKHR",
167 (__eglMustCastToProperFunctionPointerType)&eglGetSyncAttribKHR },
168
169 // EGL_NV_system_time
Jonas Yang1c3d72a2011-08-26 20:04:39 +0800170 { "eglGetSystemTimeFrequencyNV",
171 (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeFrequencyNV },
172 { "eglGetSystemTimeNV",
173 (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeNV },
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700174
Mathias Agopian2bb71682013-03-27 17:32:41 -0700175 // EGL_KHR_wait_sync
176 { "eglWaitSyncKHR",
177 (__eglMustCastToProperFunctionPointerType)&eglWaitSyncKHR },
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700178
179 // EGL_ANDROID_presentation_time
180 { "eglPresentationTimeANDROID",
181 (__eglMustCastToProperFunctionPointerType)&eglPresentationTimeANDROID },
Dan Stozaa894d082015-02-19 15:27:36 -0800182
183 // EGL_KHR_swap_buffers_with_damage
184 { "eglSwapBuffersWithDamageKHR",
185 (__eglMustCastToProperFunctionPointerType)&eglSwapBuffersWithDamageKHR },
186
Craig Donner60761072017-01-27 12:30:44 -0800187 // EGL_ANDROID_get_native_client_buffer
188 { "eglGetNativeClientBufferANDROID",
189 (__eglMustCastToProperFunctionPointerType)&eglGetNativeClientBufferANDROID },
190
Dan Stozaa894d082015-02-19 15:27:36 -0800191 // EGL_KHR_partial_update
192 { "eglSetDamageRegionKHR",
193 (__eglMustCastToProperFunctionPointerType)&eglSetDamageRegionKHR },
Season Li000d88f2015-07-01 11:39:40 -0700194
195 { "eglCreateStreamKHR",
196 (__eglMustCastToProperFunctionPointerType)&eglCreateStreamKHR },
197 { "eglDestroyStreamKHR",
198 (__eglMustCastToProperFunctionPointerType)&eglDestroyStreamKHR },
199 { "eglStreamAttribKHR",
200 (__eglMustCastToProperFunctionPointerType)&eglStreamAttribKHR },
201 { "eglQueryStreamKHR",
202 (__eglMustCastToProperFunctionPointerType)&eglQueryStreamKHR },
203 { "eglQueryStreamu64KHR",
204 (__eglMustCastToProperFunctionPointerType)&eglQueryStreamu64KHR },
205 { "eglQueryStreamTimeKHR",
206 (__eglMustCastToProperFunctionPointerType)&eglQueryStreamTimeKHR },
207 { "eglCreateStreamProducerSurfaceKHR",
208 (__eglMustCastToProperFunctionPointerType)&eglCreateStreamProducerSurfaceKHR },
209 { "eglStreamConsumerGLTextureExternalKHR",
210 (__eglMustCastToProperFunctionPointerType)&eglStreamConsumerGLTextureExternalKHR },
211 { "eglStreamConsumerAcquireKHR",
212 (__eglMustCastToProperFunctionPointerType)&eglStreamConsumerAcquireKHR },
213 { "eglStreamConsumerReleaseKHR",
214 (__eglMustCastToProperFunctionPointerType)&eglStreamConsumerReleaseKHR },
215 { "eglGetStreamFileDescriptorKHR",
216 (__eglMustCastToProperFunctionPointerType)&eglGetStreamFileDescriptorKHR },
217 { "eglCreateStreamFromFileDescriptorKHR",
218 (__eglMustCastToProperFunctionPointerType)&eglCreateStreamFromFileDescriptorKHR },
Pablo Ceballosc18be292016-05-31 14:55:42 -0700219
220 // EGL_ANDROID_get_frame_timestamps
Brian Anderson1049d1d2016-12-16 17:25:57 -0800221 { "eglGetNextFrameIdANDROID",
222 (__eglMustCastToProperFunctionPointerType)&eglGetNextFrameIdANDROID },
Brian Anderson0a61b0c2016-12-07 14:55:56 -0800223 { "eglGetCompositorTimingANDROID",
224 (__eglMustCastToProperFunctionPointerType)&eglGetCompositorTimingANDROID },
225 { "eglGetCompositorTimingSupportedANDROID",
226 (__eglMustCastToProperFunctionPointerType)&eglGetCompositorTimingSupportedANDROID },
Pablo Ceballosc18be292016-05-31 14:55:42 -0700227 { "eglGetFrameTimestampsANDROID",
228 (__eglMustCastToProperFunctionPointerType)&eglGetFrameTimestampsANDROID },
Brian Anderson0a61b0c2016-12-07 14:55:56 -0800229 { "eglGetFrameTimestampSupportedANDROID",
230 (__eglMustCastToProperFunctionPointerType)&eglGetFrameTimestampSupportedANDROID },
Craig Donner55901a22017-04-17 15:31:06 -0700231
232 // EGL_ANDROID_native_fence_sync
233 { "eglDupNativeFenceFDANDROID",
234 (__eglMustCastToProperFunctionPointerType)&eglDupNativeFenceFDANDROID },
Mathias Agopian518ec112011-05-13 16:21:08 -0700235};
236
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700237/*
238 * These extensions entry-points should not be exposed to applications.
239 * They're used internally by the Android EGL layer.
240 */
241#define FILTER_EXTENSIONS(procname) \
242 (!strcmp((procname), "eglSetBlobCacheFuncsANDROID") || \
243 !strcmp((procname), "eglHibernateProcessIMG") || \
Craig Donner55901a22017-04-17 15:31:06 -0700244 !strcmp((procname), "eglAwakenProcessIMG"))
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700245
246
247
Mathias Agopian518ec112011-05-13 16:21:08 -0700248// accesses protected by sExtensionMapMutex
Mathias Agopian65421432017-03-08 11:49:05 -0800249static std::unordered_map<std::string, __eglMustCastToProperFunctionPointerType> sGLExtentionMap;
250
Mathias Agopian518ec112011-05-13 16:21:08 -0700251static int sGLExtentionSlot = 0;
252static pthread_mutex_t sExtensionMapMutex = PTHREAD_MUTEX_INITIALIZER;
253
254static void(*findProcAddress(const char* name,
255 const extention_map_t* map, size_t n))() {
256 for (uint32_t i=0 ; i<n ; i++) {
257 if (!strcmp(name, map[i].name)) {
258 return map[i].address;
259 }
260 }
261 return NULL;
262}
263
264// ----------------------------------------------------------------------------
265
Mathias Agopian518ec112011-05-13 16:21:08 -0700266extern void setGLHooksThreadSpecific(gl_hooks_t const *value);
267extern EGLBoolean egl_init_drivers();
268extern const __eglMustCastToProperFunctionPointerType gExtensionForwarders[MAX_NUMBER_OF_GL_EXTENSIONS];
Mathias Agopian518ec112011-05-13 16:21:08 -0700269extern gl_hooks_t gHooksTrace;
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700270
Mathias Agopian518ec112011-05-13 16:21:08 -0700271} // namespace android;
272
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700273
Mathias Agopian518ec112011-05-13 16:21:08 -0700274// ----------------------------------------------------------------------------
275
276static inline void clearError() { egl_tls_t::clearError(); }
277static inline EGLContext getContext() { return egl_tls_t::getContext(); }
278
279// ----------------------------------------------------------------------------
280
281EGLDisplay eglGetDisplay(EGLNativeDisplayType display)
282{
Jesse Hall1508ae62017-01-19 17:43:26 -0800283 ATRACE_CALL();
Mathias Agopian518ec112011-05-13 16:21:08 -0700284 clearError();
285
Dan Stozac3289c42014-01-17 11:38:34 -0800286 uintptr_t index = reinterpret_cast<uintptr_t>(display);
Mathias Agopian518ec112011-05-13 16:21:08 -0700287 if (index >= NUM_DISPLAYS) {
288 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
289 }
290
291 if (egl_init_drivers() == EGL_FALSE) {
292 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
293 }
294
295 EGLDisplay dpy = egl_display_t::getFromNativeDisplay(display);
296 return dpy;
297}
298
299// ----------------------------------------------------------------------------
300// Initialization
301// ----------------------------------------------------------------------------
302
303EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
304{
305 clearError();
306
Jesse Hallb29e5e82012-04-04 16:53:42 -0700307 egl_display_ptr dp = get_display(dpy);
Mathias Agopian737b8962017-02-24 14:32:05 -0800308 if (!dp) return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700309
310 EGLBoolean res = dp->initialize(major, minor);
311
312 return res;
313}
314
315EGLBoolean eglTerminate(EGLDisplay dpy)
316{
317 // NOTE: don't unload the drivers b/c some APIs can be called
318 // after eglTerminate() has been called. eglTerminate() only
319 // terminates an EGLDisplay, not a EGL itself.
320
321 clearError();
322
Jesse Hallb29e5e82012-04-04 16:53:42 -0700323 egl_display_ptr dp = get_display(dpy);
Mathias Agopian737b8962017-02-24 14:32:05 -0800324 if (!dp) return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700325
326 EGLBoolean res = dp->terminate();
Jesse Hall47743382013-02-08 11:13:46 -0800327
Mathias Agopian518ec112011-05-13 16:21:08 -0700328 return res;
329}
330
331// ----------------------------------------------------------------------------
332// configuration
333// ----------------------------------------------------------------------------
334
335EGLBoolean eglGetConfigs( EGLDisplay dpy,
336 EGLConfig *configs,
337 EGLint config_size, EGLint *num_config)
338{
339 clearError();
340
Jesse Hallb29e5e82012-04-04 16:53:42 -0700341 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700342 if (!dp) return EGL_FALSE;
343
Mathias Agopian7773c432012-02-13 20:06:08 -0800344 if (num_config==0) {
Mathias Agopian737b8962017-02-24 14:32:05 -0800345 return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700346 }
347
Mathias Agopian7773c432012-02-13 20:06:08 -0800348 EGLBoolean res = EGL_FALSE;
349 *num_config = 0;
350
351 egl_connection_t* const cnx = &gEGLImpl;
352 if (cnx->dso) {
353 res = cnx->egl.eglGetConfigs(
354 dp->disp.dpy, configs, config_size, num_config);
Mathias Agopian518ec112011-05-13 16:21:08 -0700355 }
Mathias Agopian7773c432012-02-13 20:06:08 -0800356
357 return res;
Mathias Agopian518ec112011-05-13 16:21:08 -0700358}
359
360EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list,
361 EGLConfig *configs, EGLint config_size,
362 EGLint *num_config)
363{
364 clearError();
365
Jesse Hallb29e5e82012-04-04 16:53:42 -0700366 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700367 if (!dp) return EGL_FALSE;
368
369 if (num_config==0) {
Mathias Agopian737b8962017-02-24 14:32:05 -0800370 return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700371 }
372
Mathias Agopian518ec112011-05-13 16:21:08 -0700373 EGLBoolean res = EGL_FALSE;
374 *num_config = 0;
375
Mathias Agopianada798b2012-02-13 17:09:30 -0800376 egl_connection_t* const cnx = &gEGLImpl;
377 if (cnx->dso) {
Romain Guy1cffc802012-10-15 18:13:05 -0700378 if (attrib_list) {
379 char value[PROPERTY_VALUE_MAX];
380 property_get("debug.egl.force_msaa", value, "false");
381
382 if (!strcmp(value, "true")) {
383 size_t attribCount = 0;
384 EGLint attrib = attrib_list[0];
385
386 // Only enable MSAA if the context is OpenGL ES 2.0 and
Romain Guybe3c3e42012-10-15 19:25:18 -0700387 // if no caveat is requested
Romain Guy1cffc802012-10-15 18:13:05 -0700388 const EGLint *attribRendererable = NULL;
389 const EGLint *attribCaveat = NULL;
390
391 // Count the number of attributes and look for
Romain Guybe3c3e42012-10-15 19:25:18 -0700392 // EGL_RENDERABLE_TYPE and EGL_CONFIG_CAVEAT
Romain Guy1cffc802012-10-15 18:13:05 -0700393 while (attrib != EGL_NONE) {
394 attrib = attrib_list[attribCount];
395 switch (attrib) {
396 case EGL_RENDERABLE_TYPE:
397 attribRendererable = &attrib_list[attribCount];
398 break;
399 case EGL_CONFIG_CAVEAT:
400 attribCaveat = &attrib_list[attribCount];
401 break;
Mathias Agopian737b8962017-02-24 14:32:05 -0800402 default:
403 break;
Romain Guy1cffc802012-10-15 18:13:05 -0700404 }
405 attribCount++;
406 }
407
408 if (attribRendererable && attribRendererable[1] == EGL_OPENGL_ES2_BIT &&
409 (!attribCaveat || attribCaveat[1] != EGL_NONE)) {
Jesse Hall47743382013-02-08 11:13:46 -0800410
Romain Guy1cffc802012-10-15 18:13:05 -0700411 // Insert 2 extra attributes to force-enable MSAA 4x
412 EGLint aaAttribs[attribCount + 4];
413 aaAttribs[0] = EGL_SAMPLE_BUFFERS;
414 aaAttribs[1] = 1;
415 aaAttribs[2] = EGL_SAMPLES;
416 aaAttribs[3] = 4;
417
418 memcpy(&aaAttribs[4], attrib_list, attribCount * sizeof(EGLint));
419
420 EGLint numConfigAA;
421 EGLBoolean resAA = cnx->egl.eglChooseConfig(
422 dp->disp.dpy, aaAttribs, configs, config_size, &numConfigAA);
423
424 if (resAA == EGL_TRUE && numConfigAA > 0) {
425 ALOGD("Enabling MSAA 4x");
426 *num_config = numConfigAA;
427 return resAA;
428 }
429 }
430 }
431 }
432
Mathias Agopian7773c432012-02-13 20:06:08 -0800433 res = cnx->egl.eglChooseConfig(
434 dp->disp.dpy, attrib_list, configs, config_size, num_config);
Mathias Agopian518ec112011-05-13 16:21:08 -0700435 }
436 return res;
437}
438
439EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
440 EGLint attribute, EGLint *value)
441{
442 clearError();
443
Jesse Hallb29e5e82012-04-04 16:53:42 -0700444 egl_connection_t* cnx = NULL;
445 const egl_display_ptr dp = validate_display_connection(dpy, cnx);
446 if (!dp) return EGL_FALSE;
Jesse Hall47743382013-02-08 11:13:46 -0800447
Mathias Agopian518ec112011-05-13 16:21:08 -0700448 return cnx->egl.eglGetConfigAttrib(
Mathias Agopian7773c432012-02-13 20:06:08 -0800449 dp->disp.dpy, config, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -0700450}
451
452// ----------------------------------------------------------------------------
453// surfaces
454// ----------------------------------------------------------------------------
455
Jesse Hallc2e41222013-08-08 13:40:22 -0700456// Turn linear formats into corresponding sRGB formats when colorspace is
457// EGL_GL_COLORSPACE_SRGB_KHR, or turn sRGB formats into corresponding linear
458// formats when colorspace is EGL_GL_COLORSPACE_LINEAR_KHR. In any cases where
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800459// the modification isn't possible, the original dataSpace is returned.
460static android_dataspace modifyBufferDataspace( android_dataspace dataSpace,
461 EGLint colorspace) {
Jesse Hallc2e41222013-08-08 13:40:22 -0700462 if (colorspace == EGL_GL_COLORSPACE_LINEAR_KHR) {
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800463 return HAL_DATASPACE_SRGB_LINEAR;
Jesse Hallc2e41222013-08-08 13:40:22 -0700464 } else if (colorspace == EGL_GL_COLORSPACE_SRGB_KHR) {
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800465 return HAL_DATASPACE_SRGB;
Courtney Goeltzenleuchter21b33cb2017-04-17 17:31:29 -0600466 } else if (colorspace == EGL_GL_COLORSPACE_DISPLAY_P3_EXT) {
467 return HAL_DATASPACE_DISPLAY_P3;
468 } else if (colorspace == EGL_GL_COLORSPACE_DISPLAY_P3_LINEAR_EXT) {
469 return HAL_DATASPACE_DISPLAY_P3_LINEAR;
470 } else if (colorspace == EGL_GL_COLORSPACE_SCRGB_LINEAR_EXT) {
471 return HAL_DATASPACE_V0_SCRGB_LINEAR;
Jesse Hallc2e41222013-08-08 13:40:22 -0700472 }
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800473 return dataSpace;
Jesse Hallc2e41222013-08-08 13:40:22 -0700474}
475
Mathias Agopian518ec112011-05-13 16:21:08 -0700476EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config,
477 NativeWindowType window,
478 const EGLint *attrib_list)
479{
480 clearError();
481
Jesse Hallb29e5e82012-04-04 16:53:42 -0700482 egl_connection_t* cnx = NULL;
483 egl_display_ptr dp = validate_display_connection(dpy, cnx);
484 if (dp) {
Mathias Agopianada798b2012-02-13 17:09:30 -0800485 EGLDisplay iDpy = dp->disp.dpy;
Mathias Agopian518ec112011-05-13 16:21:08 -0700486
Mathias Agopian10e9ab52017-03-08 15:02:55 -0800487 if (!window) {
488 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
489 }
490
491 int value = 0;
492 window->query(window, NATIVE_WINDOW_IS_VALID, &value);
493 if (!value) {
494 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
495 }
496
Andy McFaddend566ce32014-01-07 15:54:17 -0800497 int result = native_window_api_connect(window, NATIVE_WINDOW_API_EGL);
Mathias Agopian65421432017-03-08 11:49:05 -0800498 if (result < 0) {
Andy McFaddend566ce32014-01-07 15:54:17 -0800499 ALOGE("eglCreateWindowSurface: native_window_api_connect (win=%p) "
500 "failed (%#x) (already connected to another API?)",
501 window, result);
Jonathan Hamilton77a9b4a2013-07-17 09:41:42 -0700502 return setError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
Mathias Agopian81a63352011-07-29 17:55:48 -0700503 }
504
Mathias Agopian0f288fc2013-08-21 16:36:34 -0700505 // Set the native window's buffers format to match what this config requests.
Jesse Hallc2e41222013-08-08 13:40:22 -0700506 // Whether to use sRGB gamma is not part of the EGLconfig, but is part
507 // of our native format. So if sRGB gamma is requested, we have to
508 // modify the EGLconfig's format before setting the native window's
509 // format.
Alistair Strachan733a8072015-02-12 12:33:25 -0800510
Courtney Goeltzenleuchter0e4e3952016-11-16 13:53:40 -0700511 EGLint componentType = EGL_COLOR_COMPONENT_TYPE_FIXED_EXT;
512 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_COLOR_COMPONENT_TYPE_EXT,
513 &componentType);
514
Mathias Agopian95921562017-02-24 14:31:31 -0800515 EGLint format;
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800516 android_dataspace dataSpace = HAL_DATASPACE_UNKNOWN;
Mathias Agopian0f288fc2013-08-21 16:36:34 -0700517 EGLint a = 0;
Courtney Goeltzenleuchter0e4e3952016-11-16 13:53:40 -0700518 EGLint r, g, b;
519 r = g = b = 0;
520 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_RED_SIZE, &r);
521 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_GREEN_SIZE, &g);
522 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_BLUE_SIZE, &b);
Mathias Agopian0f288fc2013-08-21 16:36:34 -0700523 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_ALPHA_SIZE, &a);
Courtney Goeltzenleuchter0e4e3952016-11-16 13:53:40 -0700524 EGLint colorDepth = r + g + b;
525
526 if (a == 0) {
Mathias Agopian0f288fc2013-08-21 16:36:34 -0700527 if (colorDepth <= 16) {
528 format = HAL_PIXEL_FORMAT_RGB_565;
529 } else {
Courtney Goeltzenleuchter0e4e3952016-11-16 13:53:40 -0700530 if (componentType == EGL_COLOR_COMPONENT_TYPE_FIXED_EXT) {
531 if (colorDepth > 24) {
532 format = HAL_PIXEL_FORMAT_RGBA_1010102;
533 } else {
534 format = HAL_PIXEL_FORMAT_RGBX_8888;
535 }
536 } else {
537 format = HAL_PIXEL_FORMAT_RGBA_FP16;
538 }
539 }
540 } else {
541 if (componentType == EGL_COLOR_COMPONENT_TYPE_FIXED_EXT) {
542 if (colorDepth > 24) {
543 format = HAL_PIXEL_FORMAT_RGBA_1010102;
544 } else {
545 format = HAL_PIXEL_FORMAT_RGBA_8888;
546 }
547 } else {
548 format = HAL_PIXEL_FORMAT_RGBA_FP16;
Mathias Agopian0f288fc2013-08-21 16:36:34 -0700549 }
Jesse Hallc2e41222013-08-08 13:40:22 -0700550 }
Mathias Agopian0f288fc2013-08-21 16:36:34 -0700551
552 // now select a corresponding sRGB format if needed
553 if (attrib_list && dp->haveExtension("EGL_KHR_gl_colorspace")) {
554 for (const EGLint* attr = attrib_list; *attr != EGL_NONE; attr += 2) {
555 if (*attr == EGL_GL_COLORSPACE_KHR) {
Sandeep Shinde9c67bfd2015-02-10 16:04:15 +0530556 dataSpace = modifyBufferDataspace(dataSpace, *(attr+1));
Jamie Gennisbee205f2011-07-01 13:12:07 -0700557 }
Mathias Agopian518ec112011-05-13 16:21:08 -0700558 }
559 }
Alistair Strachan733a8072015-02-12 12:33:25 -0800560
Jesse Hallc2e41222013-08-08 13:40:22 -0700561 if (format != 0) {
562 int err = native_window_set_buffers_format(window, format);
563 if (err != 0) {
564 ALOGE("error setting native window pixel format: %s (%d)",
565 strerror(-err), err);
566 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
567 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
568 }
569 }
Mathias Agopian518ec112011-05-13 16:21:08 -0700570
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800571 if (dataSpace != 0) {
572 int err = native_window_set_buffers_data_space(window, dataSpace);
573 if (err != 0) {
574 ALOGE("error setting native window pixel dataSpace: %s (%d)",
575 strerror(-err), err);
576 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
577 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
578 }
579 }
580
Jamie Gennis59769462011-11-19 18:04:43 -0800581 // the EGL spec requires that a new EGLSurface default to swap interval
582 // 1, so explicitly set that on the window here.
583 ANativeWindow* anw = reinterpret_cast<ANativeWindow*>(window);
584 anw->setSwapInterval(anw, 1);
585
Mathias Agopian518ec112011-05-13 16:21:08 -0700586 EGLSurface surface = cnx->egl.eglCreateWindowSurface(
Mathias Agopian7773c432012-02-13 20:06:08 -0800587 iDpy, config, window, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700588 if (surface != EGL_NO_SURFACE) {
Jesse Hallb29e5e82012-04-04 16:53:42 -0700589 egl_surface_t* s = new egl_surface_t(dp.get(), config, window,
590 surface, cnx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700591 return s;
592 }
Mathias Agopian81a63352011-07-29 17:55:48 -0700593
594 // EGLSurface creation failed
595 native_window_set_buffers_format(window, 0);
596 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
Mathias Agopian518ec112011-05-13 16:21:08 -0700597 }
598 return EGL_NO_SURFACE;
599}
600
601EGLSurface eglCreatePixmapSurface( EGLDisplay dpy, EGLConfig config,
602 NativePixmapType pixmap,
603 const EGLint *attrib_list)
604{
605 clearError();
606
Jesse Hallb29e5e82012-04-04 16:53:42 -0700607 egl_connection_t* cnx = NULL;
608 egl_display_ptr dp = validate_display_connection(dpy, cnx);
609 if (dp) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700610 EGLSurface surface = cnx->egl.eglCreatePixmapSurface(
Mathias Agopian7773c432012-02-13 20:06:08 -0800611 dp->disp.dpy, config, pixmap, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700612 if (surface != EGL_NO_SURFACE) {
Jesse Hallb29e5e82012-04-04 16:53:42 -0700613 egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL,
614 surface, cnx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700615 return s;
616 }
617 }
618 return EGL_NO_SURFACE;
619}
620
621EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config,
622 const EGLint *attrib_list)
623{
624 clearError();
625
Jesse Hallb29e5e82012-04-04 16:53:42 -0700626 egl_connection_t* cnx = NULL;
627 egl_display_ptr dp = validate_display_connection(dpy, cnx);
628 if (dp) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700629 EGLSurface surface = cnx->egl.eglCreatePbufferSurface(
Mathias Agopian7773c432012-02-13 20:06:08 -0800630 dp->disp.dpy, config, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700631 if (surface != EGL_NO_SURFACE) {
Jesse Hallb29e5e82012-04-04 16:53:42 -0700632 egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL,
633 surface, cnx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700634 return s;
635 }
636 }
637 return EGL_NO_SURFACE;
638}
Jesse Hall47743382013-02-08 11:13:46 -0800639
Mathias Agopian518ec112011-05-13 16:21:08 -0700640EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
641{
642 clearError();
643
Jesse Hallb29e5e82012-04-04 16:53:42 -0700644 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700645 if (!dp) return EGL_FALSE;
646
Jesse Hallb29e5e82012-04-04 16:53:42 -0700647 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700648 if (!_s.get())
Mathias Agopian737b8962017-02-24 14:32:05 -0800649 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700650
651 egl_surface_t * const s = get_surface(surface);
Mathias Agopianada798b2012-02-13 17:09:30 -0800652 EGLBoolean result = s->cnx->egl.eglDestroySurface(dp->disp.dpy, s->surface);
Mathias Agopian518ec112011-05-13 16:21:08 -0700653 if (result == EGL_TRUE) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700654 _s.terminate();
655 }
656 return result;
657}
658
659EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface surface,
660 EGLint attribute, EGLint *value)
661{
662 clearError();
663
Jesse Hallb29e5e82012-04-04 16:53:42 -0700664 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700665 if (!dp) return EGL_FALSE;
666
Jesse Hallb29e5e82012-04-04 16:53:42 -0700667 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700668 if (!_s.get())
Mathias Agopian737b8962017-02-24 14:32:05 -0800669 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700670
Mathias Agopian518ec112011-05-13 16:21:08 -0700671 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian7773c432012-02-13 20:06:08 -0800672 return s->cnx->egl.eglQuerySurface(
673 dp->disp.dpy, s->surface, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -0700674}
675
Jamie Gennise8696a42012-01-15 18:54:57 -0800676void EGLAPI eglBeginFrame(EGLDisplay dpy, EGLSurface surface) {
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800677 ATRACE_CALL();
Jamie Gennise8696a42012-01-15 18:54:57 -0800678 clearError();
679
Jesse Hallb29e5e82012-04-04 16:53:42 -0700680 const egl_display_ptr dp = validate_display(dpy);
Jamie Gennise8696a42012-01-15 18:54:57 -0800681 if (!dp) {
682 return;
683 }
684
Jesse Hallb29e5e82012-04-04 16:53:42 -0700685 SurfaceRef _s(dp.get(), surface);
Jamie Gennise8696a42012-01-15 18:54:57 -0800686 if (!_s.get()) {
687 setError(EGL_BAD_SURFACE, EGL_FALSE);
Jamie Gennise8696a42012-01-15 18:54:57 -0800688 }
Jamie Gennise8696a42012-01-15 18:54:57 -0800689}
690
Mathias Agopian518ec112011-05-13 16:21:08 -0700691// ----------------------------------------------------------------------------
692// Contexts
693// ----------------------------------------------------------------------------
694
695EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config,
696 EGLContext share_list, const EGLint *attrib_list)
697{
698 clearError();
699
Jesse Hallb29e5e82012-04-04 16:53:42 -0700700 egl_connection_t* cnx = NULL;
701 const egl_display_ptr dp = validate_display_connection(dpy, cnx);
Michael Chock0673e1e2012-06-21 12:53:17 -0700702 if (dp) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700703 if (share_list != EGL_NO_CONTEXT) {
Michael Chock0673e1e2012-06-21 12:53:17 -0700704 if (!ContextRef(dp.get(), share_list).get()) {
705 return setError(EGL_BAD_CONTEXT, EGL_NO_CONTEXT);
706 }
Mathias Agopian518ec112011-05-13 16:21:08 -0700707 egl_context_t* const c = get_context(share_list);
708 share_list = c->context;
709 }
710 EGLContext context = cnx->egl.eglCreateContext(
Mathias Agopian7773c432012-02-13 20:06:08 -0800711 dp->disp.dpy, config, share_list, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700712 if (context != EGL_NO_CONTEXT) {
713 // figure out if it's a GLESv1 or GLESv2
714 int version = 0;
715 if (attrib_list) {
716 while (*attrib_list != EGL_NONE) {
717 GLint attr = *attrib_list++;
718 GLint value = *attrib_list++;
719 if (attr == EGL_CONTEXT_CLIENT_VERSION) {
720 if (value == 1) {
Mathias Agopian7773c432012-02-13 20:06:08 -0800721 version = egl_connection_t::GLESv1_INDEX;
Jesse Hall47743382013-02-08 11:13:46 -0800722 } else if (value == 2 || value == 3) {
Mathias Agopian7773c432012-02-13 20:06:08 -0800723 version = egl_connection_t::GLESv2_INDEX;
Mathias Agopian518ec112011-05-13 16:21:08 -0700724 }
725 }
726 };
727 }
Jesse Hallb29e5e82012-04-04 16:53:42 -0700728 egl_context_t* c = new egl_context_t(dpy, context, config, cnx,
729 version);
Mathias Agopian518ec112011-05-13 16:21:08 -0700730 return c;
731 }
732 }
733 return EGL_NO_CONTEXT;
734}
735
736EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
737{
738 clearError();
739
Jesse Hallb29e5e82012-04-04 16:53:42 -0700740 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700741 if (!dp)
742 return EGL_FALSE;
Mathias Agopian518ec112011-05-13 16:21:08 -0700743
Jesse Hallb29e5e82012-04-04 16:53:42 -0700744 ContextRef _c(dp.get(), ctx);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700745 if (!_c.get())
Mathias Agopian737b8962017-02-24 14:32:05 -0800746 return setError(EGL_BAD_CONTEXT, (EGLBoolean)EGL_FALSE);
Jesse Hall47743382013-02-08 11:13:46 -0800747
Mathias Agopian518ec112011-05-13 16:21:08 -0700748 egl_context_t * const c = get_context(ctx);
Mathias Agopianada798b2012-02-13 17:09:30 -0800749 EGLBoolean result = c->cnx->egl.eglDestroyContext(dp->disp.dpy, c->context);
Mathias Agopian518ec112011-05-13 16:21:08 -0700750 if (result == EGL_TRUE) {
751 _c.terminate();
752 }
753 return result;
754}
755
Mathias Agopian518ec112011-05-13 16:21:08 -0700756EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw,
757 EGLSurface read, EGLContext ctx)
758{
759 clearError();
760
Jesse Hallb29e5e82012-04-04 16:53:42 -0700761 egl_display_ptr dp = validate_display(dpy);
Mathias Agopian737b8962017-02-24 14:32:05 -0800762 if (!dp) return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700763
Mathias Agopian5b287a62011-05-16 18:58:55 -0700764 // If ctx is not EGL_NO_CONTEXT, read is not EGL_NO_SURFACE, or draw is not
765 // EGL_NO_SURFACE, then an EGL_NOT_INITIALIZED error is generated if dpy is
766 // a valid but uninitialized display.
Mathias Agopian518ec112011-05-13 16:21:08 -0700767 if ( (ctx != EGL_NO_CONTEXT) || (read != EGL_NO_SURFACE) ||
768 (draw != EGL_NO_SURFACE) ) {
Mathias Agopian737b8962017-02-24 14:32:05 -0800769 if (!dp->isReady()) return setError(EGL_NOT_INITIALIZED, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700770 }
771
772 // get a reference to the object passed in
Jesse Hallb29e5e82012-04-04 16:53:42 -0700773 ContextRef _c(dp.get(), ctx);
774 SurfaceRef _d(dp.get(), draw);
775 SurfaceRef _r(dp.get(), read);
Mathias Agopian518ec112011-05-13 16:21:08 -0700776
777 // validate the context (if not EGL_NO_CONTEXT)
Mathias Agopian5b287a62011-05-16 18:58:55 -0700778 if ((ctx != EGL_NO_CONTEXT) && !_c.get()) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700779 // EGL_NO_CONTEXT is valid
Mathias Agopian737b8962017-02-24 14:32:05 -0800780 return setError(EGL_BAD_CONTEXT, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700781 }
782
783 // these are the underlying implementation's object
784 EGLContext impl_ctx = EGL_NO_CONTEXT;
785 EGLSurface impl_draw = EGL_NO_SURFACE;
786 EGLSurface impl_read = EGL_NO_SURFACE;
787
788 // these are our objects structs passed in
789 egl_context_t * c = NULL;
790 egl_surface_t const * d = NULL;
791 egl_surface_t const * r = NULL;
792
793 // these are the current objects structs
794 egl_context_t * cur_c = get_context(getContext());
Jesse Hall47743382013-02-08 11:13:46 -0800795
Mathias Agopian518ec112011-05-13 16:21:08 -0700796 if (ctx != EGL_NO_CONTEXT) {
797 c = get_context(ctx);
798 impl_ctx = c->context;
799 } else {
800 // no context given, use the implementation of the current context
Michael Chock0673e1e2012-06-21 12:53:17 -0700801 if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE) {
802 // calling eglMakeCurrent( ..., !=0, !=0, EGL_NO_CONTEXT);
Mathias Agopian737b8962017-02-24 14:32:05 -0800803 return setError(EGL_BAD_MATCH, (EGLBoolean)EGL_FALSE);
Michael Chock0673e1e2012-06-21 12:53:17 -0700804 }
Mathias Agopian518ec112011-05-13 16:21:08 -0700805 if (cur_c == NULL) {
806 // no current context
Mathias Agopian518ec112011-05-13 16:21:08 -0700807 // not an error, there is just no current context.
808 return EGL_TRUE;
809 }
810 }
811
812 // retrieve the underlying implementation's draw EGLSurface
813 if (draw != EGL_NO_SURFACE) {
Mathias Agopian737b8962017-02-24 14:32:05 -0800814 if (!_d.get()) return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700815 d = get_surface(draw);
Mathias Agopian518ec112011-05-13 16:21:08 -0700816 impl_draw = d->surface;
817 }
818
819 // retrieve the underlying implementation's read EGLSurface
820 if (read != EGL_NO_SURFACE) {
Mathias Agopian737b8962017-02-24 14:32:05 -0800821 if (!_r.get()) return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700822 r = get_surface(read);
Mathias Agopian518ec112011-05-13 16:21:08 -0700823 impl_read = r->surface;
824 }
825
Mathias Agopian518ec112011-05-13 16:21:08 -0700826
Jesse Hallb29e5e82012-04-04 16:53:42 -0700827 EGLBoolean result = dp->makeCurrent(c, cur_c,
Mathias Agopianfb87e542012-01-30 18:20:52 -0800828 draw, read, ctx,
829 impl_draw, impl_read, impl_ctx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700830
831 if (result == EGL_TRUE) {
Mathias Agopianfb87e542012-01-30 18:20:52 -0800832 if (c) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700833 setGLHooksThreadSpecific(c->cnx->hooks[c->version]);
834 egl_tls_t::setContext(ctx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700835 _c.acquire();
836 _r.acquire();
837 _d.acquire();
Mathias Agopian518ec112011-05-13 16:21:08 -0700838 } else {
839 setGLHooksThreadSpecific(&gHooksNoContext);
840 egl_tls_t::setContext(EGL_NO_CONTEXT);
841 }
Mathias Agopian5fecea72011-08-25 18:38:24 -0700842 } else {
Steve Blocke6f43dd2012-01-06 19:20:56 +0000843 // this will ALOGE the error
Mathias Agopian63108c32013-09-06 13:36:49 -0700844 egl_connection_t* const cnx = &gEGLImpl;
Mathias Agopian737b8962017-02-24 14:32:05 -0800845 result = setError(cnx->egl.eglGetError(), (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700846 }
847 return result;
848}
849
850
851EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx,
852 EGLint attribute, EGLint *value)
853{
854 clearError();
855
Jesse Hallb29e5e82012-04-04 16:53:42 -0700856 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700857 if (!dp) return EGL_FALSE;
858
Jesse Hallb29e5e82012-04-04 16:53:42 -0700859 ContextRef _c(dp.get(), ctx);
Mathias Agopian737b8962017-02-24 14:32:05 -0800860 if (!_c.get()) return setError(EGL_BAD_CONTEXT, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700861
Mathias Agopian518ec112011-05-13 16:21:08 -0700862 egl_context_t * const c = get_context(ctx);
Mathias Agopian7773c432012-02-13 20:06:08 -0800863 return c->cnx->egl.eglQueryContext(
864 dp->disp.dpy, c->context, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -0700865
Mathias Agopian518ec112011-05-13 16:21:08 -0700866}
867
868EGLContext eglGetCurrentContext(void)
869{
870 // could be called before eglInitialize(), but we wouldn't have a context
871 // then, and this function would correctly return EGL_NO_CONTEXT.
872
873 clearError();
874
875 EGLContext ctx = getContext();
876 return ctx;
877}
878
879EGLSurface eglGetCurrentSurface(EGLint readdraw)
880{
881 // could be called before eglInitialize(), but we wouldn't have a context
882 // then, and this function would correctly return EGL_NO_SURFACE.
883
884 clearError();
885
886 EGLContext ctx = getContext();
887 if (ctx) {
888 egl_context_t const * const c = get_context(ctx);
889 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
890 switch (readdraw) {
891 case EGL_READ: return c->read;
Jesse Hall47743382013-02-08 11:13:46 -0800892 case EGL_DRAW: return c->draw;
Mathias Agopian518ec112011-05-13 16:21:08 -0700893 default: return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
894 }
895 }
896 return EGL_NO_SURFACE;
897}
898
899EGLDisplay eglGetCurrentDisplay(void)
900{
901 // could be called before eglInitialize(), but we wouldn't have a context
902 // then, and this function would correctly return EGL_NO_DISPLAY.
903
904 clearError();
905
906 EGLContext ctx = getContext();
907 if (ctx) {
908 egl_context_t const * const c = get_context(ctx);
909 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
910 return c->dpy;
911 }
912 return EGL_NO_DISPLAY;
913}
914
915EGLBoolean eglWaitGL(void)
916{
Mathias Agopian518ec112011-05-13 16:21:08 -0700917 clearError();
918
Mathias Agopianada798b2012-02-13 17:09:30 -0800919 egl_connection_t* const cnx = &gEGLImpl;
920 if (!cnx->dso)
Mathias Agopian737b8962017-02-24 14:32:05 -0800921 return setError(EGL_BAD_CONTEXT, (EGLBoolean)EGL_FALSE);
Mathias Agopianada798b2012-02-13 17:09:30 -0800922
923 return cnx->egl.eglWaitGL();
Mathias Agopian518ec112011-05-13 16:21:08 -0700924}
925
926EGLBoolean eglWaitNative(EGLint engine)
927{
Mathias Agopian518ec112011-05-13 16:21:08 -0700928 clearError();
929
Mathias Agopianada798b2012-02-13 17:09:30 -0800930 egl_connection_t* const cnx = &gEGLImpl;
931 if (!cnx->dso)
Mathias Agopian737b8962017-02-24 14:32:05 -0800932 return setError(EGL_BAD_CONTEXT, (EGLBoolean)EGL_FALSE);
Mathias Agopianada798b2012-02-13 17:09:30 -0800933
934 return cnx->egl.eglWaitNative(engine);
Mathias Agopian518ec112011-05-13 16:21:08 -0700935}
936
937EGLint eglGetError(void)
938{
Mathias Agopianada798b2012-02-13 17:09:30 -0800939 EGLint err = EGL_SUCCESS;
940 egl_connection_t* const cnx = &gEGLImpl;
941 if (cnx->dso) {
942 err = cnx->egl.eglGetError();
Mathias Agopian518ec112011-05-13 16:21:08 -0700943 }
Mathias Agopianada798b2012-02-13 17:09:30 -0800944 if (err == EGL_SUCCESS) {
945 err = egl_tls_t::getError();
946 }
947 return err;
Mathias Agopian518ec112011-05-13 16:21:08 -0700948}
949
Michael Chockc0ec5e22014-01-27 08:14:33 -0800950static __eglMustCastToProperFunctionPointerType findBuiltinWrapper(
Jesse Hallc07b5202013-07-04 12:08:16 -0700951 const char* procname) {
952 const egl_connection_t* cnx = &gEGLImpl;
953 void* proc = NULL;
954
Michael Chockc0ec5e22014-01-27 08:14:33 -0800955 proc = dlsym(cnx->libEgl, procname);
956 if (proc) return (__eglMustCastToProperFunctionPointerType)proc;
957
Jesse Hallc07b5202013-07-04 12:08:16 -0700958 proc = dlsym(cnx->libGles2, procname);
959 if (proc) return (__eglMustCastToProperFunctionPointerType)proc;
960
961 proc = dlsym(cnx->libGles1, procname);
962 if (proc) return (__eglMustCastToProperFunctionPointerType)proc;
963
964 return NULL;
965}
966
Mathias Agopian518ec112011-05-13 16:21:08 -0700967__eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
968{
969 // eglGetProcAddress() could be the very first function called
970 // in which case we must make sure we've initialized ourselves, this
971 // happens the first time egl_get_display() is called.
972
973 clearError();
974
975 if (egl_init_drivers() == EGL_FALSE) {
976 setError(EGL_BAD_PARAMETER, NULL);
977 return NULL;
978 }
979
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700980 if (FILTER_EXTENSIONS(procname)) {
Jamie Gennisaca51c02011-11-03 17:42:43 -0700981 return NULL;
982 }
983
Mathias Agopian518ec112011-05-13 16:21:08 -0700984 __eglMustCastToProperFunctionPointerType addr;
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700985 addr = findProcAddress(procname, sExtensionMap, NELEM(sExtensionMap));
Mathias Agopian518ec112011-05-13 16:21:08 -0700986 if (addr) return addr;
987
Michael Chockc0ec5e22014-01-27 08:14:33 -0800988 addr = findBuiltinWrapper(procname);
Jesse Hallc07b5202013-07-04 12:08:16 -0700989 if (addr) return addr;
Jamie Gennisaca51c02011-11-03 17:42:43 -0700990
Mathias Agopian518ec112011-05-13 16:21:08 -0700991 // this protects accesses to sGLExtentionMap and sGLExtentionSlot
992 pthread_mutex_lock(&sExtensionMapMutex);
993
994 /*
995 * Since eglGetProcAddress() is not associated to anything, it needs
996 * to return a function pointer that "works" regardless of what
997 * the current context is.
998 *
999 * For this reason, we return a "forwarder", a small stub that takes
1000 * care of calling the function associated with the context
1001 * currently bound.
1002 *
1003 * We first look for extensions we've already resolved, if we're seeing
1004 * this extension for the first time, we go through all our
1005 * implementations and call eglGetProcAddress() and record the
1006 * result in the appropriate implementation hooks and return the
1007 * address of the forwarder corresponding to that hook set.
1008 *
1009 */
1010
Mathias Agopian65421432017-03-08 11:49:05 -08001011 const std::string name(procname);
1012
1013 auto& extentionMap = sGLExtentionMap;
1014 auto pos = extentionMap.find(name);
1015 addr = (pos != extentionMap.end()) ? pos->second : nullptr;
Mathias Agopian518ec112011-05-13 16:21:08 -07001016 const int slot = sGLExtentionSlot;
1017
Steve Blocke6f43dd2012-01-06 19:20:56 +00001018 ALOGE_IF(slot >= MAX_NUMBER_OF_GL_EXTENSIONS,
Mathias Agopian518ec112011-05-13 16:21:08 -07001019 "no more slots for eglGetProcAddress(\"%s\")",
1020 procname);
1021
1022 if (!addr && (slot < MAX_NUMBER_OF_GL_EXTENSIONS)) {
1023 bool found = false;
Mathias Agopianada798b2012-02-13 17:09:30 -08001024
1025 egl_connection_t* const cnx = &gEGLImpl;
1026 if (cnx->dso && cnx->egl.eglGetProcAddress) {
Mathias Agopianada798b2012-02-13 17:09:30 -08001027 // Extensions are independent of the bound context
luliuhui69d10072012-08-30 11:15:36 +08001028 addr =
Mathias Agopian7773c432012-02-13 20:06:08 -08001029 cnx->hooks[egl_connection_t::GLESv1_INDEX]->ext.extensions[slot] =
1030 cnx->hooks[egl_connection_t::GLESv2_INDEX]->ext.extensions[slot] =
Mathias Agopianada798b2012-02-13 17:09:30 -08001031 cnx->egl.eglGetProcAddress(procname);
luliuhui69d10072012-08-30 11:15:36 +08001032 if (addr) found = true;
Mathias Agopian518ec112011-05-13 16:21:08 -07001033 }
Mathias Agopianada798b2012-02-13 17:09:30 -08001034
Mathias Agopian518ec112011-05-13 16:21:08 -07001035 if (found) {
1036 addr = gExtensionForwarders[slot];
Mathias Agopian65421432017-03-08 11:49:05 -08001037 extentionMap[name] = addr;
Mathias Agopian518ec112011-05-13 16:21:08 -07001038 sGLExtentionSlot++;
1039 }
1040 }
1041
1042 pthread_mutex_unlock(&sExtensionMapMutex);
1043 return addr;
1044}
1045
Mathias Agopian65421432017-03-08 11:49:05 -08001046class FrameCompletionThread {
Jamie Gennis28ef8d72012-04-05 20:34:54 -07001047public:
1048
1049 static void queueSync(EGLSyncKHR sync) {
Mathias Agopian65421432017-03-08 11:49:05 -08001050 static FrameCompletionThread thread;
1051
1052 char name[64];
1053
1054 std::lock_guard<std::mutex> lock(thread.mMutex);
1055 snprintf(name, sizeof(name), "kicked off frame %u", (unsigned int)thread.mFramesQueued);
1056 ATRACE_NAME(name);
1057
1058 thread.mQueue.push_back(sync);
1059 thread.mCondition.notify_one();
1060 thread.mFramesQueued++;
1061 ATRACE_INT("GPU Frames Outstanding", int32_t(thread.mQueue.size()));
Jamie Gennis28ef8d72012-04-05 20:34:54 -07001062 }
1063
1064private:
Jamie Gennis28ef8d72012-04-05 20:34:54 -07001065
Mathias Agopian65421432017-03-08 11:49:05 -08001066 FrameCompletionThread() : mFramesQueued(0), mFramesCompleted(0) {
1067 std::thread thread(&FrameCompletionThread::loop, this);
1068 thread.detach();
1069 }
1070
1071#pragma clang diagnostic push
1072#pragma clang diagnostic ignored "-Wmissing-noreturn"
1073 void loop() {
1074 while (true) {
1075 threadLoop();
1076 }
1077 }
1078#pragma clang diagnostic pop
1079
1080 void threadLoop() {
Jamie Gennis28ef8d72012-04-05 20:34:54 -07001081 EGLSyncKHR sync;
1082 uint32_t frameNum;
1083 {
Mathias Agopian65421432017-03-08 11:49:05 -08001084 std::unique_lock<std::mutex> lock(mMutex);
1085 while (mQueue.empty()) {
1086 mCondition.wait(lock);
Jamie Gennis28ef8d72012-04-05 20:34:54 -07001087 }
1088 sync = mQueue[0];
1089 frameNum = mFramesCompleted;
1090 }
1091 EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
1092 {
Mathias Agopian65421432017-03-08 11:49:05 -08001093 char name[64];
1094 snprintf(name, sizeof(name), "waiting for frame %u", (unsigned int)frameNum);
1095 ATRACE_NAME(name);
1096
Jamie Gennis28ef8d72012-04-05 20:34:54 -07001097 EGLint result = eglClientWaitSyncKHR(dpy, sync, 0, EGL_FOREVER_KHR);
1098 if (result == EGL_FALSE) {
1099 ALOGE("FrameCompletion: error waiting for fence: %#x", eglGetError());
1100 } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
1101 ALOGE("FrameCompletion: timeout waiting for fence");
1102 }
1103 eglDestroySyncKHR(dpy, sync);
1104 }
1105 {
Mathias Agopian65421432017-03-08 11:49:05 -08001106 std::lock_guard<std::mutex> lock(mMutex);
1107 mQueue.pop_front();
Jamie Gennis28ef8d72012-04-05 20:34:54 -07001108 mFramesCompleted++;
Mathias Agopian737b8962017-02-24 14:32:05 -08001109 ATRACE_INT("GPU Frames Outstanding", int32_t(mQueue.size()));
Jamie Gennis28ef8d72012-04-05 20:34:54 -07001110 }
Jamie Gennis28ef8d72012-04-05 20:34:54 -07001111 }
1112
1113 uint32_t mFramesQueued;
1114 uint32_t mFramesCompleted;
Mathias Agopian65421432017-03-08 11:49:05 -08001115 std::deque<EGLSyncKHR> mQueue;
1116 std::condition_variable mCondition;
1117 std::mutex mMutex;
Jamie Gennis28ef8d72012-04-05 20:34:54 -07001118};
1119
Dan Stozaa894d082015-02-19 15:27:36 -08001120EGLBoolean eglSwapBuffersWithDamageKHR(EGLDisplay dpy, EGLSurface draw,
1121 EGLint *rects, EGLint n_rects)
Mathias Agopian518ec112011-05-13 16:21:08 -07001122{
Jamie Gennis1c8e95c2012-02-23 19:27:23 -08001123 ATRACE_CALL();
Mathias Agopian518ec112011-05-13 16:21:08 -07001124 clearError();
1125
Jesse Hallb29e5e82012-04-04 16:53:42 -07001126 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001127 if (!dp) return EGL_FALSE;
1128
Jesse Hallb29e5e82012-04-04 16:53:42 -07001129 SurfaceRef _s(dp.get(), draw);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001130 if (!_s.get())
Mathias Agopian737b8962017-02-24 14:32:05 -08001131 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001132
Mathias Agopian518ec112011-05-13 16:21:08 -07001133 egl_surface_t const * const s = get_surface(draw);
Mathias Agopian7db993a2012-03-25 00:49:46 -07001134
Mathias Agopianed6d08b2013-04-16 16:39:46 -07001135 if (CC_UNLIKELY(dp->traceGpuCompletion)) {
1136 EGLSyncKHR sync = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, NULL);
1137 if (sync != EGL_NO_SYNC_KHR) {
1138 FrameCompletionThread::queueSync(sync);
1139 }
1140 }
1141
Mathias Agopian7db993a2012-03-25 00:49:46 -07001142 if (CC_UNLIKELY(dp->finishOnSwap)) {
1143 uint32_t pixel;
1144 egl_context_t * const c = get_context( egl_tls_t::getContext() );
1145 if (c) {
1146 // glReadPixels() ensures that the frame is complete
1147 s->cnx->hooks[c->version]->gl.glReadPixels(0,0,1,1,
1148 GL_RGBA,GL_UNSIGNED_BYTE,&pixel);
1149 }
1150 }
1151
Dan Stozaa894d082015-02-19 15:27:36 -08001152 if (n_rects == 0) {
1153 return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface);
1154 }
1155
Mathias Agopian65421432017-03-08 11:49:05 -08001156 std::vector<android_native_rect_t> androidRects((size_t)n_rects);
Dan Stozaa894d082015-02-19 15:27:36 -08001157 for (int r = 0; r < n_rects; ++r) {
1158 int offset = r * 4;
1159 int x = rects[offset];
1160 int y = rects[offset + 1];
1161 int width = rects[offset + 2];
1162 int height = rects[offset + 3];
1163 android_native_rect_t androidRect;
1164 androidRect.left = x;
1165 androidRect.top = y + height;
1166 androidRect.right = x + width;
1167 androidRect.bottom = y;
1168 androidRects.push_back(androidRect);
1169 }
Mathias Agopian65421432017-03-08 11:49:05 -08001170 native_window_set_surface_damage(s->getNativeWindow(), androidRects.data(), androidRects.size());
Dan Stozaa894d082015-02-19 15:27:36 -08001171
1172 if (s->cnx->egl.eglSwapBuffersWithDamageKHR) {
1173 return s->cnx->egl.eglSwapBuffersWithDamageKHR(dp->disp.dpy, s->surface,
1174 rects, n_rects);
1175 } else {
1176 return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface);
1177 }
1178}
1179
1180EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
1181{
1182 return eglSwapBuffersWithDamageKHR(dpy, surface, NULL, 0);
Mathias Agopian518ec112011-05-13 16:21:08 -07001183}
1184
1185EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface,
1186 NativePixmapType target)
1187{
1188 clearError();
1189
Jesse Hallb29e5e82012-04-04 16:53:42 -07001190 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001191 if (!dp) return EGL_FALSE;
1192
Jesse Hallb29e5e82012-04-04 16:53:42 -07001193 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001194 if (!_s.get())
Mathias Agopian737b8962017-02-24 14:32:05 -08001195 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001196
Mathias Agopian518ec112011-05-13 16:21:08 -07001197 egl_surface_t const * const s = get_surface(surface);
Mathias Agopianada798b2012-02-13 17:09:30 -08001198 return s->cnx->egl.eglCopyBuffers(dp->disp.dpy, s->surface, target);
Mathias Agopian518ec112011-05-13 16:21:08 -07001199}
1200
1201const char* eglQueryString(EGLDisplay dpy, EGLint name)
1202{
1203 clearError();
1204
Chia-I Wue57d1352016-08-15 16:10:02 +08001205 // Generate an error quietly when client extensions (as defined by
1206 // EGL_EXT_client_extensions) are queried. We do not want to rely on
1207 // validate_display to generate the error as validate_display would log
1208 // the error, which can be misleading.
1209 //
1210 // If we want to support EGL_EXT_client_extensions later, we can return
1211 // the client extension string here instead.
1212 if (dpy == EGL_NO_DISPLAY && name == EGL_EXTENSIONS)
Mathias Agopian737b8962017-02-24 14:32:05 -08001213 return setErrorQuiet(EGL_BAD_DISPLAY, (const char*)0);
Chia-I Wue57d1352016-08-15 16:10:02 +08001214
Jesse Hallb29e5e82012-04-04 16:53:42 -07001215 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001216 if (!dp) return (const char *) NULL;
1217
1218 switch (name) {
1219 case EGL_VENDOR:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001220 return dp->getVendorString();
Mathias Agopian518ec112011-05-13 16:21:08 -07001221 case EGL_VERSION:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001222 return dp->getVersionString();
Mathias Agopian518ec112011-05-13 16:21:08 -07001223 case EGL_EXTENSIONS:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001224 return dp->getExtensionString();
Mathias Agopian518ec112011-05-13 16:21:08 -07001225 case EGL_CLIENT_APIS:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001226 return dp->getClientApiString();
Mathias Agopian737b8962017-02-24 14:32:05 -08001227 default:
1228 break;
Mathias Agopian518ec112011-05-13 16:21:08 -07001229 }
1230 return setError(EGL_BAD_PARAMETER, (const char *)0);
1231}
1232
Mathias Agopianca088332013-03-28 17:44:13 -07001233EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name)
1234{
1235 clearError();
1236
1237 const egl_display_ptr dp = validate_display(dpy);
1238 if (!dp) return (const char *) NULL;
1239
1240 switch (name) {
1241 case EGL_VENDOR:
1242 return dp->disp.queryString.vendor;
1243 case EGL_VERSION:
1244 return dp->disp.queryString.version;
1245 case EGL_EXTENSIONS:
1246 return dp->disp.queryString.extensions;
1247 case EGL_CLIENT_APIS:
1248 return dp->disp.queryString.clientApi;
Mathias Agopian737b8962017-02-24 14:32:05 -08001249 default:
1250 break;
Mathias Agopianca088332013-03-28 17:44:13 -07001251 }
1252 return setError(EGL_BAD_PARAMETER, (const char *)0);
1253}
Mathias Agopian518ec112011-05-13 16:21:08 -07001254
1255// ----------------------------------------------------------------------------
1256// EGL 1.1
1257// ----------------------------------------------------------------------------
1258
1259EGLBoolean eglSurfaceAttrib(
1260 EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
1261{
1262 clearError();
1263
Jesse Hallb29e5e82012-04-04 16:53:42 -07001264 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001265 if (!dp) return EGL_FALSE;
1266
Jesse Hallb29e5e82012-04-04 16:53:42 -07001267 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001268 if (!_s.get())
Mathias Agopian737b8962017-02-24 14:32:05 -08001269 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001270
Pablo Ceballosc18be292016-05-31 14:55:42 -07001271 egl_surface_t * const s = get_surface(surface);
Pablo Ceballosccdfd602015-10-07 15:05:45 -07001272
Pablo Ceballos02b05da2016-02-02 17:53:18 -08001273 if (attribute == EGL_FRONT_BUFFER_AUTO_REFRESH_ANDROID) {
Mathias Agopian65421432017-03-08 11:49:05 -08001274 if (!s->getNativeWindow()) {
Brian Anderson069b3652016-07-22 10:32:47 -07001275 setError(EGL_BAD_SURFACE, EGL_FALSE);
1276 }
Mathias Agopian65421432017-03-08 11:49:05 -08001277 int err = native_window_set_auto_refresh(s->getNativeWindow(), value != 0);
1278 return (err == 0) ? EGL_TRUE : setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Pablo Ceballosccdfd602015-10-07 15:05:45 -07001279 }
1280
Pablo Ceballosc18be292016-05-31 14:55:42 -07001281 if (attribute == EGL_TIMESTAMPS_ANDROID) {
Mathias Agopian65421432017-03-08 11:49:05 -08001282 if (!s->getNativeWindow()) {
Mathias Agopian737b8962017-02-24 14:32:05 -08001283 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Brian Anderson069b3652016-07-22 10:32:47 -07001284 }
Mathias Agopian65421432017-03-08 11:49:05 -08001285 int err = native_window_enable_frame_timestamps(s->getNativeWindow(), value != 0);
1286 return (err == 0) ? EGL_TRUE : setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Pablo Ceballosc18be292016-05-31 14:55:42 -07001287 }
1288
Mathias Agopian518ec112011-05-13 16:21:08 -07001289 if (s->cnx->egl.eglSurfaceAttrib) {
1290 return s->cnx->egl.eglSurfaceAttrib(
Mathias Agopianada798b2012-02-13 17:09:30 -08001291 dp->disp.dpy, s->surface, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -07001292 }
Mathias Agopian737b8962017-02-24 14:32:05 -08001293 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001294}
1295
1296EGLBoolean eglBindTexImage(
1297 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1298{
1299 clearError();
1300
Jesse Hallb29e5e82012-04-04 16:53:42 -07001301 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001302 if (!dp) return EGL_FALSE;
1303
Jesse Hallb29e5e82012-04-04 16:53:42 -07001304 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001305 if (!_s.get())
Mathias Agopian737b8962017-02-24 14:32:05 -08001306 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001307
Mathias Agopian518ec112011-05-13 16:21:08 -07001308 egl_surface_t const * const s = get_surface(surface);
1309 if (s->cnx->egl.eglBindTexImage) {
1310 return s->cnx->egl.eglBindTexImage(
Mathias Agopianada798b2012-02-13 17:09:30 -08001311 dp->disp.dpy, s->surface, buffer);
Mathias Agopian518ec112011-05-13 16:21:08 -07001312 }
Mathias Agopian737b8962017-02-24 14:32:05 -08001313 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001314}
1315
1316EGLBoolean eglReleaseTexImage(
1317 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1318{
1319 clearError();
1320
Jesse Hallb29e5e82012-04-04 16:53:42 -07001321 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001322 if (!dp) return EGL_FALSE;
1323
Jesse Hallb29e5e82012-04-04 16:53:42 -07001324 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001325 if (!_s.get())
Mathias Agopian737b8962017-02-24 14:32:05 -08001326 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001327
Mathias Agopian518ec112011-05-13 16:21:08 -07001328 egl_surface_t const * const s = get_surface(surface);
1329 if (s->cnx->egl.eglReleaseTexImage) {
1330 return s->cnx->egl.eglReleaseTexImage(
Mathias Agopianada798b2012-02-13 17:09:30 -08001331 dp->disp.dpy, s->surface, buffer);
Mathias Agopian518ec112011-05-13 16:21:08 -07001332 }
Mathias Agopian737b8962017-02-24 14:32:05 -08001333 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001334}
1335
1336EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
1337{
1338 clearError();
1339
Jesse Hallb29e5e82012-04-04 16:53:42 -07001340 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001341 if (!dp) return EGL_FALSE;
1342
1343 EGLBoolean res = EGL_TRUE;
Mathias Agopianada798b2012-02-13 17:09:30 -08001344 egl_connection_t* const cnx = &gEGLImpl;
1345 if (cnx->dso && cnx->egl.eglSwapInterval) {
1346 res = cnx->egl.eglSwapInterval(dp->disp.dpy, interval);
Mathias Agopian518ec112011-05-13 16:21:08 -07001347 }
Mathias Agopianada798b2012-02-13 17:09:30 -08001348
Mathias Agopian518ec112011-05-13 16:21:08 -07001349 return res;
1350}
1351
1352
1353// ----------------------------------------------------------------------------
1354// EGL 1.2
1355// ----------------------------------------------------------------------------
1356
1357EGLBoolean eglWaitClient(void)
1358{
1359 clearError();
1360
Mathias Agopianada798b2012-02-13 17:09:30 -08001361 egl_connection_t* const cnx = &gEGLImpl;
1362 if (!cnx->dso)
Mathias Agopian737b8962017-02-24 14:32:05 -08001363 return setError(EGL_BAD_CONTEXT, (EGLBoolean)EGL_FALSE);
Mathias Agopianada798b2012-02-13 17:09:30 -08001364
1365 EGLBoolean res;
1366 if (cnx->egl.eglWaitClient) {
1367 res = cnx->egl.eglWaitClient();
1368 } else {
1369 res = cnx->egl.eglWaitGL();
Mathias Agopian518ec112011-05-13 16:21:08 -07001370 }
1371 return res;
1372}
1373
1374EGLBoolean eglBindAPI(EGLenum api)
1375{
1376 clearError();
1377
1378 if (egl_init_drivers() == EGL_FALSE) {
Mathias Agopian737b8962017-02-24 14:32:05 -08001379 return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001380 }
1381
1382 // bind this API on all EGLs
1383 EGLBoolean res = EGL_TRUE;
Mathias Agopianada798b2012-02-13 17:09:30 -08001384 egl_connection_t* const cnx = &gEGLImpl;
1385 if (cnx->dso && cnx->egl.eglBindAPI) {
1386 res = cnx->egl.eglBindAPI(api);
Mathias Agopian518ec112011-05-13 16:21:08 -07001387 }
1388 return res;
1389}
1390
1391EGLenum eglQueryAPI(void)
1392{
1393 clearError();
1394
1395 if (egl_init_drivers() == EGL_FALSE) {
Mathias Agopian737b8962017-02-24 14:32:05 -08001396 return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001397 }
1398
Mathias Agopianada798b2012-02-13 17:09:30 -08001399 egl_connection_t* const cnx = &gEGLImpl;
1400 if (cnx->dso && cnx->egl.eglQueryAPI) {
1401 return cnx->egl.eglQueryAPI();
Mathias Agopian518ec112011-05-13 16:21:08 -07001402 }
Mathias Agopianada798b2012-02-13 17:09:30 -08001403
Mathias Agopian518ec112011-05-13 16:21:08 -07001404 // or, it can only be OpenGL ES
1405 return EGL_OPENGL_ES_API;
1406}
1407
1408EGLBoolean eglReleaseThread(void)
1409{
1410 clearError();
1411
Mathias Agopianada798b2012-02-13 17:09:30 -08001412 egl_connection_t* const cnx = &gEGLImpl;
1413 if (cnx->dso && cnx->egl.eglReleaseThread) {
1414 cnx->egl.eglReleaseThread();
Mathias Agopian518ec112011-05-13 16:21:08 -07001415 }
Sai Kiran Korwar3ac517a2014-01-31 21:15:07 +05301416
1417 // If there is context bound to the thread, release it
1418 egl_display_t::loseCurrent(get_context(getContext()));
1419
Mathias Agopian518ec112011-05-13 16:21:08 -07001420 egl_tls_t::clearTLS();
Mathias Agopian518ec112011-05-13 16:21:08 -07001421 return EGL_TRUE;
1422}
1423
1424EGLSurface eglCreatePbufferFromClientBuffer(
1425 EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer,
1426 EGLConfig config, const EGLint *attrib_list)
1427{
1428 clearError();
1429
Jesse Hallb29e5e82012-04-04 16:53:42 -07001430 egl_connection_t* cnx = NULL;
1431 const egl_display_ptr dp = validate_display_connection(dpy, cnx);
1432 if (!dp) return EGL_FALSE;
Mathias Agopian518ec112011-05-13 16:21:08 -07001433 if (cnx->egl.eglCreatePbufferFromClientBuffer) {
1434 return cnx->egl.eglCreatePbufferFromClientBuffer(
Mathias Agopian7773c432012-02-13 20:06:08 -08001435 dp->disp.dpy, buftype, buffer, config, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001436 }
1437 return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE);
1438}
1439
1440// ----------------------------------------------------------------------------
1441// EGL_EGLEXT_VERSION 3
1442// ----------------------------------------------------------------------------
1443
1444EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface,
1445 const EGLint *attrib_list)
1446{
1447 clearError();
1448
Jesse Hallb29e5e82012-04-04 16:53:42 -07001449 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001450 if (!dp) return EGL_FALSE;
1451
Jesse Hallb29e5e82012-04-04 16:53:42 -07001452 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001453 if (!_s.get())
Mathias Agopian737b8962017-02-24 14:32:05 -08001454 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001455
1456 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian518ec112011-05-13 16:21:08 -07001457 if (s->cnx->egl.eglLockSurfaceKHR) {
1458 return s->cnx->egl.eglLockSurfaceKHR(
Mathias Agopianada798b2012-02-13 17:09:30 -08001459 dp->disp.dpy, s->surface, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001460 }
Mathias Agopian737b8962017-02-24 14:32:05 -08001461 return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001462}
1463
1464EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface)
1465{
1466 clearError();
1467
Jesse Hallb29e5e82012-04-04 16:53:42 -07001468 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001469 if (!dp) return EGL_FALSE;
1470
Jesse Hallb29e5e82012-04-04 16:53:42 -07001471 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001472 if (!_s.get())
Mathias Agopian737b8962017-02-24 14:32:05 -08001473 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001474
1475 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian518ec112011-05-13 16:21:08 -07001476 if (s->cnx->egl.eglUnlockSurfaceKHR) {
Mathias Agopianada798b2012-02-13 17:09:30 -08001477 return s->cnx->egl.eglUnlockSurfaceKHR(dp->disp.dpy, s->surface);
Mathias Agopian518ec112011-05-13 16:21:08 -07001478 }
Mathias Agopian737b8962017-02-24 14:32:05 -08001479 return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001480}
1481
1482EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
1483 EGLClientBuffer buffer, const EGLint *attrib_list)
1484{
1485 clearError();
1486
Jesse Hallb29e5e82012-04-04 16:53:42 -07001487 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001488 if (!dp) return EGL_NO_IMAGE_KHR;
1489
Jesse Hallb29e5e82012-04-04 16:53:42 -07001490 ContextRef _c(dp.get(), ctx);
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001491 egl_context_t * const c = _c.get();
Mathias Agopian518ec112011-05-13 16:21:08 -07001492
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001493 EGLImageKHR result = EGL_NO_IMAGE_KHR;
1494 egl_connection_t* const cnx = &gEGLImpl;
1495 if (cnx->dso && cnx->egl.eglCreateImageKHR) {
1496 result = cnx->egl.eglCreateImageKHR(
1497 dp->disp.dpy,
1498 c ? c->context : EGL_NO_CONTEXT,
1499 target, buffer, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001500 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001501 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001502}
1503
1504EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
1505{
1506 clearError();
1507
Jesse Hallb29e5e82012-04-04 16:53:42 -07001508 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001509 if (!dp) return EGL_FALSE;
1510
Steven Holte646a5c52012-06-04 20:02:11 -07001511 EGLBoolean result = EGL_FALSE;
Mathias Agopianada798b2012-02-13 17:09:30 -08001512 egl_connection_t* const cnx = &gEGLImpl;
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001513 if (cnx->dso && cnx->egl.eglDestroyImageKHR) {
Steven Holte646a5c52012-06-04 20:02:11 -07001514 result = cnx->egl.eglDestroyImageKHR(dp->disp.dpy, img);
Mathias Agopian518ec112011-05-13 16:21:08 -07001515 }
Steven Holte646a5c52012-06-04 20:02:11 -07001516 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001517}
1518
1519// ----------------------------------------------------------------------------
1520// EGL_EGLEXT_VERSION 5
1521// ----------------------------------------------------------------------------
1522
1523
1524EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
1525{
1526 clearError();
1527
Jesse Hallb29e5e82012-04-04 16:53:42 -07001528 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001529 if (!dp) return EGL_NO_SYNC_KHR;
1530
Mathias Agopian518ec112011-05-13 16:21:08 -07001531 EGLSyncKHR result = EGL_NO_SYNC_KHR;
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001532 egl_connection_t* const cnx = &gEGLImpl;
1533 if (cnx->dso && cnx->egl.eglCreateSyncKHR) {
1534 result = cnx->egl.eglCreateSyncKHR(dp->disp.dpy, type, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001535 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001536 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001537}
1538
1539EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
1540{
1541 clearError();
1542
Jesse Hallb29e5e82012-04-04 16:53:42 -07001543 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001544 if (!dp) return EGL_FALSE;
1545
Mathias Agopian518ec112011-05-13 16:21:08 -07001546 EGLBoolean result = EGL_FALSE;
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001547 egl_connection_t* const cnx = &gEGLImpl;
1548 if (cnx->dso && cnx->egl.eglDestroySyncKHR) {
1549 result = cnx->egl.eglDestroySyncKHR(dp->disp.dpy, sync);
Mathias Agopian518ec112011-05-13 16:21:08 -07001550 }
1551 return result;
1552}
1553
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -07001554EGLBoolean eglSignalSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode) {
1555 clearError();
1556
1557 const egl_display_ptr dp = validate_display(dpy);
1558 if (!dp) return EGL_FALSE;
1559
1560 EGLBoolean result = EGL_FALSE;
1561 egl_connection_t* const cnx = &gEGLImpl;
1562 if (cnx->dso && cnx->egl.eglSignalSyncKHR) {
1563 result = cnx->egl.eglSignalSyncKHR(
1564 dp->disp.dpy, sync, mode);
1565 }
1566 return result;
1567}
1568
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001569EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync,
1570 EGLint flags, EGLTimeKHR timeout)
Mathias Agopian518ec112011-05-13 16:21:08 -07001571{
1572 clearError();
1573
Jesse Hallb29e5e82012-04-04 16:53:42 -07001574 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001575 if (!dp) return EGL_FALSE;
1576
Mathias Agopian737b8962017-02-24 14:32:05 -08001577 EGLint result = EGL_FALSE;
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001578 egl_connection_t* const cnx = &gEGLImpl;
1579 if (cnx->dso && cnx->egl.eglClientWaitSyncKHR) {
1580 result = cnx->egl.eglClientWaitSyncKHR(
1581 dp->disp.dpy, sync, flags, timeout);
Mathias Agopian518ec112011-05-13 16:21:08 -07001582 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001583 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001584}
1585
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001586EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync,
1587 EGLint attribute, EGLint *value)
Mathias Agopian518ec112011-05-13 16:21:08 -07001588{
1589 clearError();
1590
Jesse Hallb29e5e82012-04-04 16:53:42 -07001591 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001592 if (!dp) return EGL_FALSE;
1593
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001594 EGLBoolean result = EGL_FALSE;
1595 egl_connection_t* const cnx = &gEGLImpl;
1596 if (cnx->dso && cnx->egl.eglGetSyncAttribKHR) {
1597 result = cnx->egl.eglGetSyncAttribKHR(
1598 dp->disp.dpy, sync, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -07001599 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001600 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001601}
1602
Season Li000d88f2015-07-01 11:39:40 -07001603EGLStreamKHR eglCreateStreamKHR(EGLDisplay dpy, const EGLint *attrib_list)
1604{
1605 clearError();
1606
1607 const egl_display_ptr dp = validate_display(dpy);
1608 if (!dp) return EGL_NO_STREAM_KHR;
1609
1610 EGLStreamKHR result = EGL_NO_STREAM_KHR;
1611 egl_connection_t* const cnx = &gEGLImpl;
1612 if (cnx->dso && cnx->egl.eglCreateStreamKHR) {
1613 result = cnx->egl.eglCreateStreamKHR(
1614 dp->disp.dpy, attrib_list);
1615 }
1616 return result;
1617}
1618
1619EGLBoolean eglDestroyStreamKHR(EGLDisplay dpy, EGLStreamKHR stream)
1620{
1621 clearError();
1622
1623 const egl_display_ptr dp = validate_display(dpy);
1624 if (!dp) return EGL_FALSE;
1625
1626 EGLBoolean result = EGL_FALSE;
1627 egl_connection_t* const cnx = &gEGLImpl;
1628 if (cnx->dso && cnx->egl.eglDestroyStreamKHR) {
1629 result = cnx->egl.eglDestroyStreamKHR(
1630 dp->disp.dpy, stream);
1631 }
1632 return result;
1633}
1634
1635EGLBoolean eglStreamAttribKHR(EGLDisplay dpy, EGLStreamKHR stream,
1636 EGLenum attribute, EGLint value)
1637{
1638 clearError();
1639
1640 const egl_display_ptr dp = validate_display(dpy);
1641 if (!dp) return EGL_FALSE;
1642
1643 EGLBoolean result = EGL_FALSE;
1644 egl_connection_t* const cnx = &gEGLImpl;
1645 if (cnx->dso && cnx->egl.eglStreamAttribKHR) {
1646 result = cnx->egl.eglStreamAttribKHR(
1647 dp->disp.dpy, stream, attribute, value);
1648 }
1649 return result;
1650}
1651
1652EGLBoolean eglQueryStreamKHR(EGLDisplay dpy, EGLStreamKHR stream,
1653 EGLenum attribute, EGLint *value)
1654{
1655 clearError();
1656
1657 const egl_display_ptr dp = validate_display(dpy);
1658 if (!dp) return EGL_FALSE;
1659
1660 EGLBoolean result = EGL_FALSE;
1661 egl_connection_t* const cnx = &gEGLImpl;
1662 if (cnx->dso && cnx->egl.eglQueryStreamKHR) {
1663 result = cnx->egl.eglQueryStreamKHR(
1664 dp->disp.dpy, stream, attribute, value);
1665 }
1666 return result;
1667}
1668
1669EGLBoolean eglQueryStreamu64KHR(EGLDisplay dpy, EGLStreamKHR stream,
1670 EGLenum attribute, EGLuint64KHR *value)
1671{
1672 clearError();
1673
1674 const egl_display_ptr dp = validate_display(dpy);
1675 if (!dp) return EGL_FALSE;
1676
1677 EGLBoolean result = EGL_FALSE;
1678 egl_connection_t* const cnx = &gEGLImpl;
1679 if (cnx->dso && cnx->egl.eglQueryStreamu64KHR) {
1680 result = cnx->egl.eglQueryStreamu64KHR(
1681 dp->disp.dpy, stream, attribute, value);
1682 }
1683 return result;
1684}
1685
1686EGLBoolean eglQueryStreamTimeKHR(EGLDisplay dpy, EGLStreamKHR stream,
1687 EGLenum attribute, EGLTimeKHR *value)
1688{
1689 clearError();
1690
1691 const egl_display_ptr dp = validate_display(dpy);
1692 if (!dp) return EGL_FALSE;
1693
1694 EGLBoolean result = EGL_FALSE;
1695 egl_connection_t* const cnx = &gEGLImpl;
1696 if (cnx->dso && cnx->egl.eglQueryStreamTimeKHR) {
1697 result = cnx->egl.eglQueryStreamTimeKHR(
1698 dp->disp.dpy, stream, attribute, value);
1699 }
1700 return result;
1701}
1702
1703EGLSurface eglCreateStreamProducerSurfaceKHR(EGLDisplay dpy, EGLConfig config,
1704 EGLStreamKHR stream, const EGLint *attrib_list)
1705{
1706 clearError();
1707
1708 egl_display_ptr dp = validate_display(dpy);
1709 if (!dp) return EGL_NO_SURFACE;
1710
1711 egl_connection_t* const cnx = &gEGLImpl;
1712 if (cnx->dso && cnx->egl.eglCreateStreamProducerSurfaceKHR) {
1713 EGLSurface surface = cnx->egl.eglCreateStreamProducerSurfaceKHR(
1714 dp->disp.dpy, config, stream, attrib_list);
1715 if (surface != EGL_NO_SURFACE) {
1716 egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL,
1717 surface, cnx);
1718 return s;
1719 }
1720 }
1721 return EGL_NO_SURFACE;
1722}
1723
1724EGLBoolean eglStreamConsumerGLTextureExternalKHR(EGLDisplay dpy,
1725 EGLStreamKHR stream)
1726{
1727 clearError();
1728
1729 const egl_display_ptr dp = validate_display(dpy);
1730 if (!dp) return EGL_FALSE;
1731
1732 EGLBoolean result = EGL_FALSE;
1733 egl_connection_t* const cnx = &gEGLImpl;
1734 if (cnx->dso && cnx->egl.eglStreamConsumerGLTextureExternalKHR) {
1735 result = cnx->egl.eglStreamConsumerGLTextureExternalKHR(
1736 dp->disp.dpy, stream);
1737 }
1738 return result;
1739}
1740
1741EGLBoolean eglStreamConsumerAcquireKHR(EGLDisplay dpy,
1742 EGLStreamKHR stream)
1743{
1744 clearError();
1745
1746 const egl_display_ptr dp = validate_display(dpy);
1747 if (!dp) return EGL_FALSE;
1748
1749 EGLBoolean result = EGL_FALSE;
1750 egl_connection_t* const cnx = &gEGLImpl;
1751 if (cnx->dso && cnx->egl.eglStreamConsumerAcquireKHR) {
1752 result = cnx->egl.eglStreamConsumerAcquireKHR(
1753 dp->disp.dpy, stream);
1754 }
1755 return result;
1756}
1757
1758EGLBoolean eglStreamConsumerReleaseKHR(EGLDisplay dpy,
1759 EGLStreamKHR stream)
1760{
1761 clearError();
1762
1763 const egl_display_ptr dp = validate_display(dpy);
1764 if (!dp) return EGL_FALSE;
1765
1766 EGLBoolean result = EGL_FALSE;
1767 egl_connection_t* const cnx = &gEGLImpl;
1768 if (cnx->dso && cnx->egl.eglStreamConsumerReleaseKHR) {
1769 result = cnx->egl.eglStreamConsumerReleaseKHR(
1770 dp->disp.dpy, stream);
1771 }
1772 return result;
1773}
1774
1775EGLNativeFileDescriptorKHR eglGetStreamFileDescriptorKHR(
1776 EGLDisplay dpy, EGLStreamKHR stream)
1777{
1778 clearError();
1779
1780 const egl_display_ptr dp = validate_display(dpy);
1781 if (!dp) return EGL_NO_FILE_DESCRIPTOR_KHR;
1782
1783 EGLNativeFileDescriptorKHR result = EGL_NO_FILE_DESCRIPTOR_KHR;
1784 egl_connection_t* const cnx = &gEGLImpl;
1785 if (cnx->dso && cnx->egl.eglGetStreamFileDescriptorKHR) {
1786 result = cnx->egl.eglGetStreamFileDescriptorKHR(
1787 dp->disp.dpy, stream);
1788 }
1789 return result;
1790}
1791
1792EGLStreamKHR eglCreateStreamFromFileDescriptorKHR(
1793 EGLDisplay dpy, EGLNativeFileDescriptorKHR file_descriptor)
1794{
1795 clearError();
1796
1797 const egl_display_ptr dp = validate_display(dpy);
1798 if (!dp) return EGL_NO_STREAM_KHR;
1799
1800 EGLStreamKHR result = EGL_NO_STREAM_KHR;
1801 egl_connection_t* const cnx = &gEGLImpl;
1802 if (cnx->dso && cnx->egl.eglCreateStreamFromFileDescriptorKHR) {
1803 result = cnx->egl.eglCreateStreamFromFileDescriptorKHR(
1804 dp->disp.dpy, file_descriptor);
1805 }
1806 return result;
1807}
1808
Mathias Agopian518ec112011-05-13 16:21:08 -07001809// ----------------------------------------------------------------------------
Mathias Agopian2bb71682013-03-27 17:32:41 -07001810// EGL_EGLEXT_VERSION 15
1811// ----------------------------------------------------------------------------
1812
1813EGLint eglWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags) {
1814 clearError();
1815 const egl_display_ptr dp = validate_display(dpy);
1816 if (!dp) return EGL_FALSE;
1817 EGLint result = EGL_FALSE;
1818 egl_connection_t* const cnx = &gEGLImpl;
1819 if (cnx->dso && cnx->egl.eglWaitSyncKHR) {
1820 result = cnx->egl.eglWaitSyncKHR(dp->disp.dpy, sync, flags);
1821 }
1822 return result;
1823}
1824
1825// ----------------------------------------------------------------------------
Mathias Agopian518ec112011-05-13 16:21:08 -07001826// ANDROID extensions
1827// ----------------------------------------------------------------------------
1828
Jamie Gennis331841b2012-09-06 14:52:00 -07001829EGLint eglDupNativeFenceFDANDROID(EGLDisplay dpy, EGLSyncKHR sync)
1830{
1831 clearError();
1832
1833 const egl_display_ptr dp = validate_display(dpy);
1834 if (!dp) return EGL_NO_NATIVE_FENCE_FD_ANDROID;
1835
1836 EGLint result = EGL_NO_NATIVE_FENCE_FD_ANDROID;
1837 egl_connection_t* const cnx = &gEGLImpl;
1838 if (cnx->dso && cnx->egl.eglDupNativeFenceFDANDROID) {
1839 result = cnx->egl.eglDupNativeFenceFDANDROID(dp->disp.dpy, sync);
1840 }
1841 return result;
1842}
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001843
Andy McFadden72841452013-03-01 16:25:32 -08001844EGLBoolean eglPresentationTimeANDROID(EGLDisplay dpy, EGLSurface surface,
1845 EGLnsecsANDROID time)
1846{
1847 clearError();
1848
1849 const egl_display_ptr dp = validate_display(dpy);
1850 if (!dp) {
1851 return EGL_FALSE;
1852 }
1853
1854 SurfaceRef _s(dp.get(), surface);
1855 if (!_s.get()) {
1856 setError(EGL_BAD_SURFACE, EGL_FALSE);
1857 return EGL_FALSE;
1858 }
1859
1860 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian65421432017-03-08 11:49:05 -08001861 native_window_set_buffers_timestamp(s->getNativeWindow(), time);
Andy McFadden72841452013-03-01 16:25:32 -08001862
1863 return EGL_TRUE;
1864}
1865
Craig Donner60761072017-01-27 12:30:44 -08001866EGLClientBuffer eglGetNativeClientBufferANDROID(const AHardwareBuffer *buffer) {
1867 clearError();
Craig Donner60761072017-01-27 12:30:44 -08001868 if (!buffer) return setError(EGL_BAD_PARAMETER, (EGLClientBuffer)0);
Mathias Agopian61963402017-02-24 16:38:15 -08001869 return const_cast<ANativeWindowBuffer *>(AHardwareBuffer_to_ANativeWindowBuffer(buffer));
Craig Donner60761072017-01-27 12:30:44 -08001870}
1871
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001872// ----------------------------------------------------------------------------
1873// NVIDIA extensions
1874// ----------------------------------------------------------------------------
1875EGLuint64NV eglGetSystemTimeFrequencyNV()
1876{
1877 clearError();
1878
1879 if (egl_init_drivers() == EGL_FALSE) {
Mathias Agopian737b8962017-02-24 14:32:05 -08001880 return setError(EGL_BAD_PARAMETER, (EGLuint64NV)EGL_FALSE);
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001881 }
1882
1883 EGLuint64NV ret = 0;
Mathias Agopianada798b2012-02-13 17:09:30 -08001884 egl_connection_t* const cnx = &gEGLImpl;
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001885
Mathias Agopianada798b2012-02-13 17:09:30 -08001886 if (cnx->dso && cnx->egl.eglGetSystemTimeFrequencyNV) {
1887 return cnx->egl.eglGetSystemTimeFrequencyNV();
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001888 }
1889
Mathias Agopian737b8962017-02-24 14:32:05 -08001890 return setErrorQuiet(EGL_BAD_DISPLAY, (EGLuint64NV)0);
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001891}
1892
1893EGLuint64NV eglGetSystemTimeNV()
1894{
1895 clearError();
1896
1897 if (egl_init_drivers() == EGL_FALSE) {
Mathias Agopian737b8962017-02-24 14:32:05 -08001898 return setError(EGL_BAD_PARAMETER, (EGLuint64NV)EGL_FALSE);
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001899 }
1900
1901 EGLuint64NV ret = 0;
Mathias Agopianada798b2012-02-13 17:09:30 -08001902 egl_connection_t* const cnx = &gEGLImpl;
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001903
Mathias Agopianada798b2012-02-13 17:09:30 -08001904 if (cnx->dso && cnx->egl.eglGetSystemTimeNV) {
1905 return cnx->egl.eglGetSystemTimeNV();
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001906 }
1907
Mathias Agopian737b8962017-02-24 14:32:05 -08001908 return setErrorQuiet(EGL_BAD_DISPLAY, (EGLuint64NV)0);
Jonas Yang1c3d72a2011-08-26 20:04:39 +08001909}
Dan Stozaa894d082015-02-19 15:27:36 -08001910
1911// ----------------------------------------------------------------------------
1912// Partial update extension
1913// ----------------------------------------------------------------------------
1914EGLBoolean eglSetDamageRegionKHR(EGLDisplay dpy, EGLSurface surface,
1915 EGLint *rects, EGLint n_rects)
1916{
1917 clearError();
1918
1919 const egl_display_ptr dp = validate_display(dpy);
1920 if (!dp) {
1921 setError(EGL_BAD_DISPLAY, EGL_FALSE);
1922 return EGL_FALSE;
1923 }
1924
1925 SurfaceRef _s(dp.get(), surface);
1926 if (!_s.get()) {
1927 setError(EGL_BAD_SURFACE, EGL_FALSE);
1928 return EGL_FALSE;
1929 }
1930
1931 egl_surface_t const * const s = get_surface(surface);
1932 if (s->cnx->egl.eglSetDamageRegionKHR) {
1933 return s->cnx->egl.eglSetDamageRegionKHR(dp->disp.dpy, s->surface,
1934 rects, n_rects);
1935 }
1936
1937 return EGL_FALSE;
1938}
Pablo Ceballosc18be292016-05-31 14:55:42 -07001939
Brian Anderson1049d1d2016-12-16 17:25:57 -08001940EGLBoolean eglGetNextFrameIdANDROID(EGLDisplay dpy, EGLSurface surface,
1941 EGLuint64KHR *frameId) {
1942 clearError();
1943
1944 const egl_display_ptr dp = validate_display(dpy);
1945 if (!dp) {
Mathias Agopian737b8962017-02-24 14:32:05 -08001946 return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
Brian Anderson1049d1d2016-12-16 17:25:57 -08001947 }
1948
1949 SurfaceRef _s(dp.get(), surface);
1950 if (!_s.get()) {
Mathias Agopian737b8962017-02-24 14:32:05 -08001951 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Brian Anderson1049d1d2016-12-16 17:25:57 -08001952 }
1953
1954 egl_surface_t const * const s = get_surface(surface);
1955
Mathias Agopian65421432017-03-08 11:49:05 -08001956 if (!s->getNativeWindow()) {
Mathias Agopian737b8962017-02-24 14:32:05 -08001957 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Brian Anderson1049d1d2016-12-16 17:25:57 -08001958 }
1959
1960 uint64_t nextFrameId = 0;
Mathias Agopian65421432017-03-08 11:49:05 -08001961 int ret = native_window_get_next_frame_id(s->getNativeWindow(), &nextFrameId);
Brian Anderson1049d1d2016-12-16 17:25:57 -08001962
Mathias Agopian65421432017-03-08 11:49:05 -08001963 if (ret != 0) {
Brian Anderson1049d1d2016-12-16 17:25:57 -08001964 // This should not happen. Return an error that is not in the spec
1965 // so it's obvious something is very wrong.
1966 ALOGE("eglGetNextFrameId: Unexpected error.");
Mathias Agopian737b8962017-02-24 14:32:05 -08001967 return setError(EGL_NOT_INITIALIZED, (EGLBoolean)EGL_FALSE);
Brian Anderson1049d1d2016-12-16 17:25:57 -08001968 }
1969
1970 *frameId = nextFrameId;
1971 return EGL_TRUE;
1972}
1973
Brian Anderson0a61b0c2016-12-07 14:55:56 -08001974EGLBoolean eglGetCompositorTimingANDROID(EGLDisplay dpy, EGLSurface surface,
1975 EGLint numTimestamps, const EGLint *names, EGLnsecsANDROID *values)
1976{
1977 clearError();
1978
1979 const egl_display_ptr dp = validate_display(dpy);
1980 if (!dp) {
Mathias Agopian737b8962017-02-24 14:32:05 -08001981 return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
Brian Anderson0a61b0c2016-12-07 14:55:56 -08001982 }
1983
1984 SurfaceRef _s(dp.get(), surface);
1985 if (!_s.get()) {
Mathias Agopian737b8962017-02-24 14:32:05 -08001986 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Brian Anderson0a61b0c2016-12-07 14:55:56 -08001987 }
1988
1989 egl_surface_t const * const s = get_surface(surface);
1990
Mathias Agopian65421432017-03-08 11:49:05 -08001991 if (!s->getNativeWindow()) {
Mathias Agopian737b8962017-02-24 14:32:05 -08001992 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Brian Anderson0a61b0c2016-12-07 14:55:56 -08001993 }
1994
1995 nsecs_t* compositeDeadline = nullptr;
1996 nsecs_t* compositeInterval = nullptr;
1997 nsecs_t* compositeToPresentLatency = nullptr;
1998
1999 for (int i = 0; i < numTimestamps; i++) {
2000 switch (names[i]) {
2001 case EGL_COMPOSITE_DEADLINE_ANDROID:
2002 compositeDeadline = &values[i];
2003 break;
2004 case EGL_COMPOSITE_INTERVAL_ANDROID:
2005 compositeInterval = &values[i];
2006 break;
2007 case EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID:
2008 compositeToPresentLatency = &values[i];
2009 break;
2010 default:
Mathias Agopian737b8962017-02-24 14:32:05 -08002011 return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE);
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002012 }
2013 }
2014
Mathias Agopian65421432017-03-08 11:49:05 -08002015 int ret = native_window_get_compositor_timing(s->getNativeWindow(),
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002016 compositeDeadline, compositeInterval, compositeToPresentLatency);
2017
2018 switch (ret) {
Mathias Agopian65421432017-03-08 11:49:05 -08002019 case 0:
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002020 return EGL_TRUE;
Mathias Agopian65421432017-03-08 11:49:05 -08002021 case -ENOSYS:
Mathias Agopian737b8962017-02-24 14:32:05 -08002022 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002023 default:
2024 // This should not happen. Return an error that is not in the spec
2025 // so it's obvious something is very wrong.
2026 ALOGE("eglGetCompositorTiming: Unexpected error.");
Mathias Agopian737b8962017-02-24 14:32:05 -08002027 return setError(EGL_NOT_INITIALIZED, (EGLBoolean)EGL_FALSE);
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002028 }
2029}
2030
2031EGLBoolean eglGetCompositorTimingSupportedANDROID(
2032 EGLDisplay dpy, EGLSurface surface, EGLint name)
2033{
2034 clearError();
2035
2036 const egl_display_ptr dp = validate_display(dpy);
2037 if (!dp) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002038 return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002039 }
2040
2041 SurfaceRef _s(dp.get(), surface);
2042 if (!_s.get()) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002043 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002044 }
2045
2046 egl_surface_t const * const s = get_surface(surface);
2047
Mathias Agopian65421432017-03-08 11:49:05 -08002048 ANativeWindow* window = s->getNativeWindow();
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002049 if (!window) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002050 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002051 }
2052
2053 switch (name) {
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002054 case EGL_COMPOSITE_DEADLINE_ANDROID:
2055 case EGL_COMPOSITE_INTERVAL_ANDROID:
2056 case EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID:
2057 return EGL_TRUE;
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002058 default:
2059 return EGL_FALSE;
2060 }
2061}
2062
Pablo Ceballosc18be292016-05-31 14:55:42 -07002063EGLBoolean eglGetFrameTimestampsANDROID(EGLDisplay dpy, EGLSurface surface,
Brian Anderson1049d1d2016-12-16 17:25:57 -08002064 EGLuint64KHR frameId, EGLint numTimestamps, const EGLint *timestamps,
Pablo Ceballosc18be292016-05-31 14:55:42 -07002065 EGLnsecsANDROID *values)
2066{
2067 clearError();
2068
2069 const egl_display_ptr dp = validate_display(dpy);
2070 if (!dp) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002071 return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
Pablo Ceballosc18be292016-05-31 14:55:42 -07002072 }
2073
2074 SurfaceRef _s(dp.get(), surface);
2075 if (!_s.get()) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002076 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Pablo Ceballosc18be292016-05-31 14:55:42 -07002077 }
2078
2079 egl_surface_t const * const s = get_surface(surface);
2080
Mathias Agopian65421432017-03-08 11:49:05 -08002081 if (!s->getNativeWindow()) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002082 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Pablo Ceballosc18be292016-05-31 14:55:42 -07002083 }
2084
Brian Andersondbd0ea82016-07-22 09:38:59 -07002085 nsecs_t* requestedPresentTime = nullptr;
Pablo Ceballosc18be292016-05-31 14:55:42 -07002086 nsecs_t* acquireTime = nullptr;
Brian Andersonf7fd56a2016-09-02 10:10:04 -07002087 nsecs_t* latchTime = nullptr;
2088 nsecs_t* firstRefreshStartTime = nullptr;
Brian Andersonb04c6f02016-10-21 12:57:46 -07002089 nsecs_t* gpuCompositionDoneTime = nullptr;
Brian Andersonf7fd56a2016-09-02 10:10:04 -07002090 nsecs_t* lastRefreshStartTime = nullptr;
Brian Anderson069b3652016-07-22 10:32:47 -07002091 nsecs_t* displayPresentTime = nullptr;
Brian Andersonf7fd56a2016-09-02 10:10:04 -07002092 nsecs_t* dequeueReadyTime = nullptr;
Pablo Ceballosc18be292016-05-31 14:55:42 -07002093 nsecs_t* releaseTime = nullptr;
2094
2095 for (int i = 0; i < numTimestamps; i++) {
2096 switch (timestamps[i]) {
Brian Andersondbd0ea82016-07-22 09:38:59 -07002097 case EGL_REQUESTED_PRESENT_TIME_ANDROID:
2098 requestedPresentTime = &values[i];
Pablo Ceballosc18be292016-05-31 14:55:42 -07002099 break;
2100 case EGL_RENDERING_COMPLETE_TIME_ANDROID:
2101 acquireTime = &values[i];
2102 break;
Brian Andersonf7fd56a2016-09-02 10:10:04 -07002103 case EGL_COMPOSITION_LATCH_TIME_ANDROID:
2104 latchTime = &values[i];
Pablo Ceballosc18be292016-05-31 14:55:42 -07002105 break;
Brian Andersonf7fd56a2016-09-02 10:10:04 -07002106 case EGL_FIRST_COMPOSITION_START_TIME_ANDROID:
2107 firstRefreshStartTime = &values[i];
2108 break;
2109 case EGL_LAST_COMPOSITION_START_TIME_ANDROID:
2110 lastRefreshStartTime = &values[i];
2111 break;
Brian Andersonb04c6f02016-10-21 12:57:46 -07002112 case EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID:
2113 gpuCompositionDoneTime = &values[i];
Pablo Ceballosc18be292016-05-31 14:55:42 -07002114 break;
Brian Anderson069b3652016-07-22 10:32:47 -07002115 case EGL_DISPLAY_PRESENT_TIME_ANDROID:
2116 displayPresentTime = &values[i];
2117 break;
Brian Andersonf7fd56a2016-09-02 10:10:04 -07002118 case EGL_DEQUEUE_READY_TIME_ANDROID:
2119 dequeueReadyTime = &values[i];
2120 break;
Pablo Ceballosc18be292016-05-31 14:55:42 -07002121 case EGL_READS_DONE_TIME_ANDROID:
2122 releaseTime = &values[i];
2123 break;
2124 default:
Mathias Agopian737b8962017-02-24 14:32:05 -08002125 return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE);
Pablo Ceballosc18be292016-05-31 14:55:42 -07002126 }
2127 }
2128
Mathias Agopian65421432017-03-08 11:49:05 -08002129 int ret = native_window_get_frame_timestamps(s->getNativeWindow(), frameId,
Brian Andersonf7fd56a2016-09-02 10:10:04 -07002130 requestedPresentTime, acquireTime, latchTime, firstRefreshStartTime,
Brian Andersonb04c6f02016-10-21 12:57:46 -07002131 lastRefreshStartTime, gpuCompositionDoneTime, displayPresentTime,
Brian Anderson4e606e32017-03-16 15:34:57 -07002132 dequeueReadyTime, releaseTime);
Pablo Ceballosc18be292016-05-31 14:55:42 -07002133
Brian Anderson069b3652016-07-22 10:32:47 -07002134 switch (ret) {
Mathias Agopian65421432017-03-08 11:49:05 -08002135 case 0:
Mathias Agopian737b8962017-02-24 14:32:05 -08002136 return EGL_TRUE;
Mathias Agopian65421432017-03-08 11:49:05 -08002137 case -ENOENT:
Mathias Agopian737b8962017-02-24 14:32:05 -08002138 return setError(EGL_BAD_ACCESS, (EGLBoolean)EGL_FALSE);
Mathias Agopian65421432017-03-08 11:49:05 -08002139 case -ENOSYS:
Mathias Agopian737b8962017-02-24 14:32:05 -08002140 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian65421432017-03-08 11:49:05 -08002141 case -EINVAL:
Mathias Agopian737b8962017-02-24 14:32:05 -08002142 return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE);
2143 default:
2144 // This should not happen. Return an error that is not in the spec
2145 // so it's obvious something is very wrong.
2146 ALOGE("eglGetFrameTimestamps: Unexpected error.");
2147 return setError(EGL_NOT_INITIALIZED, (EGLBoolean)EGL_FALSE);
Pablo Ceballosc18be292016-05-31 14:55:42 -07002148 }
Pablo Ceballosc18be292016-05-31 14:55:42 -07002149}
2150
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002151EGLBoolean eglGetFrameTimestampSupportedANDROID(
2152 EGLDisplay dpy, EGLSurface surface, EGLint timestamp)
Pablo Ceballosc18be292016-05-31 14:55:42 -07002153{
2154 clearError();
2155
2156 const egl_display_ptr dp = validate_display(dpy);
2157 if (!dp) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002158 return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
Pablo Ceballosc18be292016-05-31 14:55:42 -07002159 }
2160
2161 SurfaceRef _s(dp.get(), surface);
2162 if (!_s.get()) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002163 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Brian Anderson069b3652016-07-22 10:32:47 -07002164 }
2165
2166 egl_surface_t const * const s = get_surface(surface);
2167
Mathias Agopian65421432017-03-08 11:49:05 -08002168 ANativeWindow* window = s->getNativeWindow();
Brian Anderson069b3652016-07-22 10:32:47 -07002169 if (!window) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002170 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Pablo Ceballosc18be292016-05-31 14:55:42 -07002171 }
2172
2173 switch (timestamp) {
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002174 case EGL_COMPOSITE_DEADLINE_ANDROID:
2175 case EGL_COMPOSITE_INTERVAL_ANDROID:
2176 case EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID:
Brian Andersondbd0ea82016-07-22 09:38:59 -07002177 case EGL_REQUESTED_PRESENT_TIME_ANDROID:
Pablo Ceballosc18be292016-05-31 14:55:42 -07002178 case EGL_RENDERING_COMPLETE_TIME_ANDROID:
Brian Andersonf7fd56a2016-09-02 10:10:04 -07002179 case EGL_COMPOSITION_LATCH_TIME_ANDROID:
2180 case EGL_FIRST_COMPOSITION_START_TIME_ANDROID:
2181 case EGL_LAST_COMPOSITION_START_TIME_ANDROID:
Brian Andersonb04c6f02016-10-21 12:57:46 -07002182 case EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID:
Brian Andersonf7fd56a2016-09-02 10:10:04 -07002183 case EGL_DEQUEUE_READY_TIME_ANDROID:
Pablo Ceballosc18be292016-05-31 14:55:42 -07002184 case EGL_READS_DONE_TIME_ANDROID:
2185 return EGL_TRUE;
Brian Anderson6b376712017-04-04 10:51:39 -07002186 case EGL_DISPLAY_PRESENT_TIME_ANDROID: {
2187 int value = 0;
2188 window->query(window,
2189 NATIVE_WINDOW_FRAME_TIMESTAMPS_SUPPORTS_PRESENT, &value);
2190 return value == 0 ? EGL_FALSE : EGL_TRUE;
2191 }
Pablo Ceballosc18be292016-05-31 14:55:42 -07002192 default:
2193 return EGL_FALSE;
2194 }
2195}