blob: efef4721f51f0fbd48cd5736f07870ceb9e62edd [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 Goeltzenleuchtera1e59f12018-03-05 08:19:25 -070090 "EGL_EXT_surface_SMPTE2086_metadata "
91 "EGL_EXT_surface_CTA861_3_metadata "
Jesse Hall21558da2013-08-06 15:31:22 -070092 ;
Mathias Agopian311b4792017-02-28 15:00:49 -080093
94char const * const gExtensionString =
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070095 "EGL_KHR_image " // mandatory
96 "EGL_KHR_image_base " // mandatory
Krzysztof KosiƄski41171c52018-04-19 21:38:54 -070097 "EGL_EXT_image_gl_colorspace "
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -070098 "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
Mathias Agopian518ec112011-05-13 16:21:08 -0700246// accesses protected by sExtensionMapMutex
Mathias Agopian65421432017-03-08 11:49:05 -0800247static std::unordered_map<std::string, __eglMustCastToProperFunctionPointerType> sGLExtentionMap;
248
Mathias Agopian518ec112011-05-13 16:21:08 -0700249static int sGLExtentionSlot = 0;
250static pthread_mutex_t sExtensionMapMutex = PTHREAD_MUTEX_INITIALIZER;
251
252static void(*findProcAddress(const char* name,
253 const extention_map_t* map, size_t n))() {
254 for (uint32_t i=0 ; i<n ; i++) {
255 if (!strcmp(name, map[i].name)) {
256 return map[i].address;
257 }
258 }
259 return NULL;
260}
261
262// ----------------------------------------------------------------------------
263
Mathias Agopian518ec112011-05-13 16:21:08 -0700264extern void setGLHooksThreadSpecific(gl_hooks_t const *value);
265extern EGLBoolean egl_init_drivers();
266extern const __eglMustCastToProperFunctionPointerType gExtensionForwarders[MAX_NUMBER_OF_GL_EXTENSIONS];
Mathias Agopian518ec112011-05-13 16:21:08 -0700267extern gl_hooks_t gHooksTrace;
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700268
Mathias Agopian518ec112011-05-13 16:21:08 -0700269} // namespace android;
270
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700271
Mathias Agopian518ec112011-05-13 16:21:08 -0700272// ----------------------------------------------------------------------------
273
274static inline void clearError() { egl_tls_t::clearError(); }
275static inline EGLContext getContext() { return egl_tls_t::getContext(); }
276
277// ----------------------------------------------------------------------------
278
279EGLDisplay eglGetDisplay(EGLNativeDisplayType display)
280{
Jesse Hall1508ae62017-01-19 17:43:26 -0800281 ATRACE_CALL();
Mathias Agopian518ec112011-05-13 16:21:08 -0700282 clearError();
283
Dan Stozac3289c42014-01-17 11:38:34 -0800284 uintptr_t index = reinterpret_cast<uintptr_t>(display);
Mathias Agopian518ec112011-05-13 16:21:08 -0700285 if (index >= NUM_DISPLAYS) {
286 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
287 }
288
289 if (egl_init_drivers() == EGL_FALSE) {
290 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
291 }
292
293 EGLDisplay dpy = egl_display_t::getFromNativeDisplay(display);
294 return dpy;
295}
296
297// ----------------------------------------------------------------------------
298// Initialization
299// ----------------------------------------------------------------------------
300
301EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
302{
303 clearError();
304
Jesse Hallb29e5e82012-04-04 16:53:42 -0700305 egl_display_ptr dp = get_display(dpy);
Mathias Agopian737b8962017-02-24 14:32:05 -0800306 if (!dp) return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700307
308 EGLBoolean res = dp->initialize(major, minor);
309
310 return res;
311}
312
313EGLBoolean eglTerminate(EGLDisplay dpy)
314{
315 // NOTE: don't unload the drivers b/c some APIs can be called
316 // after eglTerminate() has been called. eglTerminate() only
317 // terminates an EGLDisplay, not a EGL itself.
318
319 clearError();
320
Jesse Hallb29e5e82012-04-04 16:53:42 -0700321 egl_display_ptr dp = get_display(dpy);
Mathias Agopian737b8962017-02-24 14:32:05 -0800322 if (!dp) return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700323
324 EGLBoolean res = dp->terminate();
Jesse Hall47743382013-02-08 11:13:46 -0800325
Mathias Agopian518ec112011-05-13 16:21:08 -0700326 return res;
327}
328
329// ----------------------------------------------------------------------------
330// configuration
331// ----------------------------------------------------------------------------
332
333EGLBoolean eglGetConfigs( EGLDisplay dpy,
334 EGLConfig *configs,
335 EGLint config_size, EGLint *num_config)
336{
337 clearError();
338
Jesse Hallb29e5e82012-04-04 16:53:42 -0700339 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700340 if (!dp) return EGL_FALSE;
341
Mathias Agopian7773c432012-02-13 20:06:08 -0800342 if (num_config==0) {
Mathias Agopian737b8962017-02-24 14:32:05 -0800343 return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700344 }
345
Mathias Agopian7773c432012-02-13 20:06:08 -0800346 EGLBoolean res = EGL_FALSE;
347 *num_config = 0;
348
349 egl_connection_t* const cnx = &gEGLImpl;
350 if (cnx->dso) {
351 res = cnx->egl.eglGetConfigs(
352 dp->disp.dpy, configs, config_size, num_config);
Mathias Agopian518ec112011-05-13 16:21:08 -0700353 }
Mathias Agopian7773c432012-02-13 20:06:08 -0800354
355 return res;
Mathias Agopian518ec112011-05-13 16:21:08 -0700356}
357
358EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list,
359 EGLConfig *configs, EGLint config_size,
360 EGLint *num_config)
361{
362 clearError();
363
Jesse Hallb29e5e82012-04-04 16:53:42 -0700364 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700365 if (!dp) return EGL_FALSE;
366
367 if (num_config==0) {
Mathias Agopian737b8962017-02-24 14:32:05 -0800368 return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700369 }
370
Mathias Agopian518ec112011-05-13 16:21:08 -0700371 EGLBoolean res = EGL_FALSE;
372 *num_config = 0;
373
Mathias Agopianada798b2012-02-13 17:09:30 -0800374 egl_connection_t* const cnx = &gEGLImpl;
375 if (cnx->dso) {
Romain Guy1cffc802012-10-15 18:13:05 -0700376 if (attrib_list) {
377 char value[PROPERTY_VALUE_MAX];
378 property_get("debug.egl.force_msaa", value, "false");
379
380 if (!strcmp(value, "true")) {
381 size_t attribCount = 0;
382 EGLint attrib = attrib_list[0];
383
384 // Only enable MSAA if the context is OpenGL ES 2.0 and
Romain Guybe3c3e42012-10-15 19:25:18 -0700385 // if no caveat is requested
Romain Guy1cffc802012-10-15 18:13:05 -0700386 const EGLint *attribRendererable = NULL;
387 const EGLint *attribCaveat = NULL;
388
389 // Count the number of attributes and look for
Romain Guybe3c3e42012-10-15 19:25:18 -0700390 // EGL_RENDERABLE_TYPE and EGL_CONFIG_CAVEAT
Romain Guy1cffc802012-10-15 18:13:05 -0700391 while (attrib != EGL_NONE) {
392 attrib = attrib_list[attribCount];
393 switch (attrib) {
394 case EGL_RENDERABLE_TYPE:
395 attribRendererable = &attrib_list[attribCount];
396 break;
397 case EGL_CONFIG_CAVEAT:
398 attribCaveat = &attrib_list[attribCount];
399 break;
Mathias Agopian737b8962017-02-24 14:32:05 -0800400 default:
401 break;
Romain Guy1cffc802012-10-15 18:13:05 -0700402 }
403 attribCount++;
404 }
405
406 if (attribRendererable && attribRendererable[1] == EGL_OPENGL_ES2_BIT &&
407 (!attribCaveat || attribCaveat[1] != EGL_NONE)) {
Jesse Hall47743382013-02-08 11:13:46 -0800408
Romain Guy1cffc802012-10-15 18:13:05 -0700409 // Insert 2 extra attributes to force-enable MSAA 4x
410 EGLint aaAttribs[attribCount + 4];
411 aaAttribs[0] = EGL_SAMPLE_BUFFERS;
412 aaAttribs[1] = 1;
413 aaAttribs[2] = EGL_SAMPLES;
414 aaAttribs[3] = 4;
415
416 memcpy(&aaAttribs[4], attrib_list, attribCount * sizeof(EGLint));
417
418 EGLint numConfigAA;
419 EGLBoolean resAA = cnx->egl.eglChooseConfig(
420 dp->disp.dpy, aaAttribs, configs, config_size, &numConfigAA);
421
422 if (resAA == EGL_TRUE && numConfigAA > 0) {
423 ALOGD("Enabling MSAA 4x");
424 *num_config = numConfigAA;
425 return resAA;
426 }
427 }
428 }
429 }
430
Mathias Agopian7773c432012-02-13 20:06:08 -0800431 res = cnx->egl.eglChooseConfig(
432 dp->disp.dpy, attrib_list, configs, config_size, num_config);
Mathias Agopian518ec112011-05-13 16:21:08 -0700433 }
434 return res;
435}
436
437EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
438 EGLint attribute, EGLint *value)
439{
440 clearError();
441
Jesse Hallb29e5e82012-04-04 16:53:42 -0700442 egl_connection_t* cnx = NULL;
443 const egl_display_ptr dp = validate_display_connection(dpy, cnx);
444 if (!dp) return EGL_FALSE;
Jesse Hall47743382013-02-08 11:13:46 -0800445
Mathias Agopian518ec112011-05-13 16:21:08 -0700446 return cnx->egl.eglGetConfigAttrib(
Mathias Agopian7773c432012-02-13 20:06:08 -0800447 dp->disp.dpy, config, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -0700448}
449
450// ----------------------------------------------------------------------------
451// surfaces
452// ----------------------------------------------------------------------------
453
Jesse Hallc2e41222013-08-08 13:40:22 -0700454// Turn linear formats into corresponding sRGB formats when colorspace is
455// EGL_GL_COLORSPACE_SRGB_KHR, or turn sRGB formats into corresponding linear
456// formats when colorspace is EGL_GL_COLORSPACE_LINEAR_KHR. In any cases where
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800457// the modification isn't possible, the original dataSpace is returned.
Courtney Goeltzenleuchtereeaa52b2017-06-20 08:12:54 -0600458static android_dataspace modifyBufferDataspace(android_dataspace dataSpace,
459 EGLint colorspace) {
Jesse Hallc2e41222013-08-08 13:40:22 -0700460 if (colorspace == EGL_GL_COLORSPACE_LINEAR_KHR) {
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800461 return HAL_DATASPACE_SRGB_LINEAR;
Jesse Hallc2e41222013-08-08 13:40:22 -0700462 } else if (colorspace == EGL_GL_COLORSPACE_SRGB_KHR) {
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800463 return HAL_DATASPACE_SRGB;
Courtney Goeltzenleuchter21b33cb2017-04-17 17:31:29 -0600464 } else if (colorspace == EGL_GL_COLORSPACE_DISPLAY_P3_EXT) {
465 return HAL_DATASPACE_DISPLAY_P3;
466 } else if (colorspace == EGL_GL_COLORSPACE_DISPLAY_P3_LINEAR_EXT) {
467 return HAL_DATASPACE_DISPLAY_P3_LINEAR;
Courtney Goeltzenleuchter33e2b782017-06-23 09:06:52 -0600468 } else if (colorspace == EGL_GL_COLORSPACE_SCRGB_EXT) {
469 return HAL_DATASPACE_V0_SCRGB;
Courtney Goeltzenleuchter21b33cb2017-04-17 17:31:29 -0600470 } else if (colorspace == EGL_GL_COLORSPACE_SCRGB_LINEAR_EXT) {
471 return HAL_DATASPACE_V0_SCRGB_LINEAR;
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700472 } else if (colorspace == EGL_GL_COLORSPACE_BT2020_LINEAR_EXT) {
473 return HAL_DATASPACE_BT2020_LINEAR;
474 } else if (colorspace == EGL_GL_COLORSPACE_BT2020_PQ_EXT) {
475 return HAL_DATASPACE_BT2020_PQ;
Jesse Hallc2e41222013-08-08 13:40:22 -0700476 }
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800477 return dataSpace;
Jesse Hallc2e41222013-08-08 13:40:22 -0700478}
479
Courtney Goeltzenleuchtera1e59f12018-03-05 08:19:25 -0700480// stripAttributes is used by eglCreateWindowSurface, eglCreatePbufferSurface
481// and eglCreatePixmapSurface to clean up color space related Window parameters
482// that a driver does not advertise support for.
483// Return true if stripped_attrib_list has stripped contents.
484
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700485static EGLBoolean stripAttributes(egl_display_ptr dp, const EGLint* attrib_list,
Courtney Goeltzenleuchter786ab882018-01-26 13:37:33 -0800486 EGLint format,
487 std::vector<EGLint>& stripped_attrib_list) {
Courtney Goeltzenleuchtereeaa52b2017-06-20 08:12:54 -0600488 std::vector<EGLint> allowedColorSpaces;
Courtney Goeltzenleuchtera1e59f12018-03-05 08:19:25 -0700489 bool haveColorSpaceSupport = dp->haveExtension("EGL_KHR_gl_colorspace");
Courtney Goeltzenleuchtereeaa52b2017-06-20 08:12:54 -0600490 switch (format) {
491 case HAL_PIXEL_FORMAT_RGBA_8888:
Krzysztof KosiƄskif2102172018-04-16 10:11:31 -0700492 case HAL_PIXEL_FORMAT_RGBX_8888:
493 // RGB_888 is never returned by getNativePixelFormat, but is included here for completeness.
494 case HAL_PIXEL_FORMAT_RGB_888:
Courtney Goeltzenleuchtera1e59f12018-03-05 08:19:25 -0700495 if (haveColorSpaceSupport) {
496 // Spec says:
497 // [fn1] Only OpenGL and OpenGL ES contexts which support sRGB
498 // rendering must respect requests for EGL_GL_COLORSPACE_SRGB_KHR, and
499 // only to sRGB formats supported by the context (normally just SRGB8)
500 // Older versions not supporting sRGB rendering will ignore this
501 // surface attribute.
502 //
503 // We support sRGB and pixel format is SRGB8, so allow
504 // the EGL_GL_COLORSPACE_SRGB_KHR and
505 // EGL_GL_COLORSPACE_LINEAR_KHR
506 // colorspaces to be specified.
507
508 allowedColorSpaces.push_back(EGL_GL_COLORSPACE_SRGB_KHR);
509 allowedColorSpaces.push_back(EGL_GL_COLORSPACE_LINEAR_KHR);
510 }
511 if (findExtension(dp->disp.queryString.extensions,
512 "EGL_EXT_gl_colorspace_display_p3_linear")) {
513 allowedColorSpaces.push_back(EGL_GL_COLORSPACE_DISPLAY_P3_LINEAR_EXT);
514 }
515 if (findExtension(dp->disp.queryString.extensions,
516 "EGL_EXT_gl_colorspace_display_p3")) {
517 allowedColorSpaces.push_back(EGL_GL_COLORSPACE_DISPLAY_P3_EXT);
518 }
519 if (findExtension(dp->disp.queryString.extensions,
520 "EGL_EXT_gl_colorspace_bt2020_linear")) {
521 allowedColorSpaces.push_back(EGL_GL_COLORSPACE_BT2020_LINEAR_EXT);
522 }
523 if (findExtension(dp->disp.queryString.extensions,
524 "EGL_EXT_gl_colorspace_bt2020_pq")) {
525 allowedColorSpaces.push_back(EGL_GL_COLORSPACE_BT2020_PQ_EXT);
526 }
527 if (findExtension(dp->disp.queryString.extensions,
528 "EGL_EXT_gl_colorspace_scrgb_linear")) {
529 allowedColorSpaces.push_back(EGL_GL_COLORSPACE_SCRGB_LINEAR_EXT);
530 }
Courtney Goeltzenleuchtereeaa52b2017-06-20 08:12:54 -0600531 break;
532
533 case HAL_PIXEL_FORMAT_RGBA_FP16:
534 case HAL_PIXEL_FORMAT_RGBA_1010102:
Courtney Goeltzenleuchtera1e59f12018-03-05 08:19:25 -0700535 case HAL_PIXEL_FORMAT_RGB_565:
Courtney Goeltzenleuchtereeaa52b2017-06-20 08:12:54 -0600536 // Future: if driver supports XXXX extension, we can pass down that colorspace
Courtney Goeltzenleuchtera1e59f12018-03-05 08:19:25 -0700537 default:
Courtney Goeltzenleuchtereeaa52b2017-06-20 08:12:54 -0600538 break;
539 }
540
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700541 if (!attrib_list) return false;
542
Courtney Goeltzenleuchtereeaa52b2017-06-20 08:12:54 -0600543 bool stripped = false;
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700544 for (const EGLint* attr = attrib_list; attr[0] != EGL_NONE; attr += 2) {
545 switch (attr[0]) {
546 case EGL_GL_COLORSPACE_KHR: {
547 EGLint colorSpace = attr[1];
548 bool found = false;
549 // Verify that color space is allowed
550 for (auto it : allowedColorSpaces) {
551 if (colorSpace == it) {
552 found = true;
553 }
554 }
Courtney Goeltzenleuchtera1e59f12018-03-05 08:19:25 -0700555 if (found) {
556 // Found supported attribute
557 stripped_attrib_list.push_back(attr[0]);
558 stripped_attrib_list.push_back(attr[1]);
559 } else if (!haveColorSpaceSupport) {
560 // Device does not support colorspace extension
561 // pass on the attribute and let downstream
562 // components validate like normal
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700563 stripped_attrib_list.push_back(attr[0]);
564 stripped_attrib_list.push_back(attr[1]);
Courtney Goeltzenleuchter52de2fd2018-02-01 09:51:58 -0700565 } else {
Courtney Goeltzenleuchtera1e59f12018-03-05 08:19:25 -0700566 // Found supported attribute that driver does not
567 // support, strip it.
Courtney Goeltzenleuchter52de2fd2018-02-01 09:51:58 -0700568 stripped = true;
Courtney Goeltzenleuchtereeaa52b2017-06-20 08:12:54 -0600569 }
570 }
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700571 break;
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700572 default:
Courtney Goeltzenleuchtereeaa52b2017-06-20 08:12:54 -0600573 stripped_attrib_list.push_back(attr[0]);
574 stripped_attrib_list.push_back(attr[1]);
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700575 break;
Courtney Goeltzenleuchtereeaa52b2017-06-20 08:12:54 -0600576 }
577 }
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700578
579 // Make sure there is at least one attribute
Courtney Goeltzenleuchtereeaa52b2017-06-20 08:12:54 -0600580 if (stripped) {
581 stripped_attrib_list.push_back(EGL_NONE);
Courtney Goeltzenleuchtereeaa52b2017-06-20 08:12:54 -0600582 }
583 return stripped;
584}
585
Courtney Goeltzenleuchtere5d6f992017-07-07 14:55:40 -0600586static EGLBoolean getColorSpaceAttribute(egl_display_ptr dp, NativeWindowType window,
587 const EGLint* attrib_list, EGLint& colorSpace,
588 android_dataspace& dataSpace) {
Courtney Goeltzenleuchter37836572017-04-26 15:07:51 -0600589 colorSpace = EGL_GL_COLORSPACE_LINEAR_KHR;
590 dataSpace = HAL_DATASPACE_UNKNOWN;
Courtney Goeltzenleuchtere5d6f992017-07-07 14:55:40 -0600591
Courtney Goeltzenleuchter37836572017-04-26 15:07:51 -0600592 if (attrib_list && dp->haveExtension("EGL_KHR_gl_colorspace")) {
593 for (const EGLint* attr = attrib_list; *attr != EGL_NONE; attr += 2) {
594 if (*attr == EGL_GL_COLORSPACE_KHR) {
595 colorSpace = attr[1];
596 bool found = false;
Courtney Goeltzenleuchtere5d6f992017-07-07 14:55:40 -0600597 bool verify = true;
Courtney Goeltzenleuchter37836572017-04-26 15:07:51 -0600598 // Verify that color space is allowed
599 if (colorSpace == EGL_GL_COLORSPACE_SRGB_KHR ||
600 colorSpace == EGL_GL_COLORSPACE_LINEAR_KHR) {
Courtney Goeltzenleuchtere5d6f992017-07-07 14:55:40 -0600601 // SRGB and LINEAR are always supported when EGL_KHR_gl_colorspace
602 // is available, so no need to verify.
Courtney Goeltzenleuchter37836572017-04-26 15:07:51 -0600603 found = true;
Courtney Goeltzenleuchtere5d6f992017-07-07 14:55:40 -0600604 verify = false;
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700605 } else if (colorSpace == EGL_GL_COLORSPACE_BT2020_LINEAR_EXT &&
Courtney Goeltzenleuchter37836572017-04-26 15:07:51 -0600606 dp->haveExtension("EGL_EXT_gl_colorspace_bt2020_linear")) {
607 found = true;
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700608 } else if (colorSpace == EGL_GL_COLORSPACE_BT2020_PQ_EXT &&
Courtney Goeltzenleuchter37836572017-04-26 15:07:51 -0600609 dp->haveExtension("EGL_EXT_gl_colorspace_bt2020_pq")) {
610 found = true;
Courtney Goeltzenleuchter33e2b782017-06-23 09:06:52 -0600611 } else if (colorSpace == EGL_GL_COLORSPACE_SCRGB_EXT &&
612 dp->haveExtension("EGL_EXT_gl_colorspace_scrgb")) {
613 found = true;
Courtney Goeltzenleuchter37836572017-04-26 15:07:51 -0600614 } else if (colorSpace == EGL_GL_COLORSPACE_SCRGB_LINEAR_EXT &&
615 dp->haveExtension("EGL_EXT_gl_colorspace_scrgb_linear")) {
616 found = true;
617 } else if (colorSpace == EGL_GL_COLORSPACE_DISPLAY_P3_LINEAR_EXT &&
618 dp->haveExtension("EGL_EXT_gl_colorspace_display_p3_linear")) {
619 found = true;
620 } else if (colorSpace == EGL_GL_COLORSPACE_DISPLAY_P3_EXT &&
621 dp->haveExtension("EGL_EXT_gl_colorspace_display_p3")) {
622 found = true;
623 }
624 if (!found) {
625 return false;
626 }
Courtney Goeltzenleuchtere5d6f992017-07-07 14:55:40 -0600627 if (verify && window) {
628 bool wide_color_support = true;
629 // Ordinarily we'd put a call to native_window_get_wide_color_support
630 // at the beginning of the function so that we'll have the
631 // result when needed elsewhere in the function.
632 // However, because eglCreateWindowSurface is called by SurfaceFlinger and
633 // SurfaceFlinger is required to answer the call below we would
634 // end up in a deadlock situation. By moving the call to only happen
635 // if the application has specifically asked for wide-color we avoid
636 // the deadlock with SurfaceFlinger since it will not ask for a
637 // wide-color surface.
638 int err = native_window_get_wide_color_support(window, &wide_color_support);
639
640 if (err) {
641 ALOGE("getColorSpaceAttribute: invalid window (win=%p) "
642 "failed (%#x) (already connected to another API?)",
643 window, err);
644 return false;
645 }
646 if (!wide_color_support) {
647 // Application has asked for a wide-color colorspace but
648 // wide-color support isn't available on the display the window is on.
649 return false;
650 }
651 }
Courtney Goeltzenleuchter1d4f7a22017-05-05 13:30:25 -0600652 // Only change the dataSpace from default if the application
653 // has explicitly set the color space with a EGL_GL_COLORSPACE_KHR attribute.
654 dataSpace = modifyBufferDataspace(dataSpace, colorSpace);
Courtney Goeltzenleuchter37836572017-04-26 15:07:51 -0600655 }
656 }
Courtney Goeltzenleuchter37836572017-04-26 15:07:51 -0600657 }
658 return true;
659}
660
Courtney Goeltzenleuchtere5d6f992017-07-07 14:55:40 -0600661static EGLBoolean getColorSpaceAttribute(egl_display_ptr dp, const EGLint* attrib_list,
662 EGLint& colorSpace, android_dataspace& dataSpace) {
663 return getColorSpaceAttribute(dp, NULL, attrib_list, colorSpace, dataSpace);
664}
665
Courtney Goeltzenleuchtereeaa52b2017-06-20 08:12:54 -0600666void getNativePixelFormat(EGLDisplay dpy, egl_connection_t* cnx, EGLConfig config, EGLint& format) {
667 // Set the native window's buffers format to match what this config requests.
668 // Whether to use sRGB gamma is not part of the EGLconfig, but is part
669 // of our native format. So if sRGB gamma is requested, we have to
670 // modify the EGLconfig's format before setting the native window's
671 // format.
672
673 EGLint componentType = EGL_COLOR_COMPONENT_TYPE_FIXED_EXT;
674 cnx->egl.eglGetConfigAttrib(dpy, config, EGL_COLOR_COMPONENT_TYPE_EXT, &componentType);
675
676 EGLint a = 0;
677 EGLint r, g, b;
678 r = g = b = 0;
679 cnx->egl.eglGetConfigAttrib(dpy, config, EGL_RED_SIZE, &r);
680 cnx->egl.eglGetConfigAttrib(dpy, config, EGL_GREEN_SIZE, &g);
681 cnx->egl.eglGetConfigAttrib(dpy, config, EGL_BLUE_SIZE, &b);
682 cnx->egl.eglGetConfigAttrib(dpy, config, EGL_ALPHA_SIZE, &a);
683 EGLint colorDepth = r + g + b;
684
685 // Today, the driver only understands sRGB and linear on 888X
686 // formats. Strip other colorspaces from the attribute list and
687 // only use them to set the dataspace via
688 // native_window_set_buffers_dataspace
689 // if pixel format is RGBX 8888
690 // TBD: Can test for future extensions that indicate that driver
691 // handles requested color space and we can let it through.
692 // allow SRGB and LINEAR. All others need to be stripped.
693 // else if 565, 4444
694 // TBD: Can we assume these are supported if 8888 is?
695 // else if FP16 or 1010102
696 // strip colorspace from attribs.
697 // endif
698 if (a == 0) {
699 if (colorDepth <= 16) {
700 format = HAL_PIXEL_FORMAT_RGB_565;
701 } else {
702 if (componentType == EGL_COLOR_COMPONENT_TYPE_FIXED_EXT) {
703 if (colorDepth > 24) {
704 format = HAL_PIXEL_FORMAT_RGBA_1010102;
705 } else {
706 format = HAL_PIXEL_FORMAT_RGBX_8888;
707 }
708 } else {
709 format = HAL_PIXEL_FORMAT_RGBA_FP16;
710 }
711 }
712 } else {
713 if (componentType == EGL_COLOR_COMPONENT_TYPE_FIXED_EXT) {
714 if (colorDepth > 24) {
715 format = HAL_PIXEL_FORMAT_RGBA_1010102;
716 } else {
717 format = HAL_PIXEL_FORMAT_RGBA_8888;
718 }
719 } else {
720 format = HAL_PIXEL_FORMAT_RGBA_FP16;
721 }
722 }
723}
724
Courtney Goeltzenleuchter936799c2018-03-02 16:47:08 -0700725EGLBoolean sendSurfaceMetadata(egl_surface_t* s) {
726 android_smpte2086_metadata smpteMetadata;
727 if (s->getSmpte2086Metadata(smpteMetadata)) {
728 int err =
729 native_window_set_buffers_smpte2086_metadata(s->getNativeWindow(), &smpteMetadata);
730 s->resetSmpte2086Metadata();
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700731 if (err != 0) {
732 ALOGE("error setting native window smpte2086 metadata: %s (%d)",
733 strerror(-err), err);
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700734 return EGL_FALSE;
735 }
736 }
Courtney Goeltzenleuchter936799c2018-03-02 16:47:08 -0700737 android_cta861_3_metadata cta8613Metadata;
738 if (s->getCta8613Metadata(cta8613Metadata)) {
739 int err =
740 native_window_set_buffers_cta861_3_metadata(s->getNativeWindow(), &cta8613Metadata);
741 s->resetCta8613Metadata();
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700742 if (err != 0) {
743 ALOGE("error setting native window CTS 861.3 metadata: %s (%d)",
744 strerror(-err), err);
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700745 return EGL_FALSE;
746 }
747 }
748 return EGL_TRUE;
749}
750
Mathias Agopian518ec112011-05-13 16:21:08 -0700751EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config,
752 NativeWindowType window,
753 const EGLint *attrib_list)
754{
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700755 const EGLint *origAttribList = attrib_list;
Mathias Agopian518ec112011-05-13 16:21:08 -0700756 clearError();
757
Jesse Hallb29e5e82012-04-04 16:53:42 -0700758 egl_connection_t* cnx = NULL;
759 egl_display_ptr dp = validate_display_connection(dpy, cnx);
760 if (dp) {
Mathias Agopianada798b2012-02-13 17:09:30 -0800761 EGLDisplay iDpy = dp->disp.dpy;
Mathias Agopian518ec112011-05-13 16:21:08 -0700762
Mathias Agopian10e9ab52017-03-08 15:02:55 -0800763 if (!window) {
764 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
765 }
766
767 int value = 0;
768 window->query(window, NATIVE_WINDOW_IS_VALID, &value);
769 if (!value) {
770 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
771 }
772
Andy McFaddend566ce32014-01-07 15:54:17 -0800773 int result = native_window_api_connect(window, NATIVE_WINDOW_API_EGL);
Mathias Agopian65421432017-03-08 11:49:05 -0800774 if (result < 0) {
Andy McFaddend566ce32014-01-07 15:54:17 -0800775 ALOGE("eglCreateWindowSurface: native_window_api_connect (win=%p) "
776 "failed (%#x) (already connected to another API?)",
777 window, result);
Jonathan Hamilton77a9b4a2013-07-17 09:41:42 -0700778 return setError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
Mathias Agopian81a63352011-07-29 17:55:48 -0700779 }
780
Mathias Agopian95921562017-02-24 14:31:31 -0800781 EGLint format;
Courtney Goeltzenleuchtereeaa52b2017-06-20 08:12:54 -0600782 getNativePixelFormat(iDpy, cnx, config, format);
783
784 // now select correct colorspace and dataspace based on user's attribute list
Courtney Goeltzenleuchter37836572017-04-26 15:07:51 -0600785 EGLint colorSpace;
786 android_dataspace dataSpace;
Courtney Goeltzenleuchtere5d6f992017-07-07 14:55:40 -0600787 if (!getColorSpaceAttribute(dp, window, attrib_list, colorSpace, dataSpace)) {
Courtney Goeltzenleuchter37836572017-04-26 15:07:51 -0600788 ALOGE("error invalid colorspace: %d", colorSpace);
789 return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700790 }
Alistair Strachan733a8072015-02-12 12:33:25 -0800791
Courtney Goeltzenleuchtereeaa52b2017-06-20 08:12:54 -0600792 std::vector<EGLint> strippedAttribList;
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700793 if (stripAttributes(dp, attrib_list, format, strippedAttribList)) {
Courtney Goeltzenleuchtereeaa52b2017-06-20 08:12:54 -0600794 // Had to modify the attribute list due to use of color space.
795 // Use modified list from here on.
796 attrib_list = strippedAttribList.data();
797 }
798
Jesse Hallc2e41222013-08-08 13:40:22 -0700799 if (format != 0) {
800 int err = native_window_set_buffers_format(window, format);
801 if (err != 0) {
802 ALOGE("error setting native window pixel format: %s (%d)",
803 strerror(-err), err);
804 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
805 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
806 }
807 }
Mathias Agopian518ec112011-05-13 16:21:08 -0700808
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800809 if (dataSpace != 0) {
810 int err = native_window_set_buffers_data_space(window, dataSpace);
811 if (err != 0) {
812 ALOGE("error setting native window pixel dataSpace: %s (%d)",
813 strerror(-err), err);
814 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
815 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
816 }
817 }
818
Jamie Gennis59769462011-11-19 18:04:43 -0800819 // the EGL spec requires that a new EGLSurface default to swap interval
820 // 1, so explicitly set that on the window here.
821 ANativeWindow* anw = reinterpret_cast<ANativeWindow*>(window);
822 anw->setSwapInterval(anw, 1);
823
Mathias Agopian518ec112011-05-13 16:21:08 -0700824 EGLSurface surface = cnx->egl.eglCreateWindowSurface(
Mathias Agopian7773c432012-02-13 20:06:08 -0800825 iDpy, config, window, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700826 if (surface != EGL_NO_SURFACE) {
Courtney Goeltzenleuchter37836572017-04-26 15:07:51 -0600827 egl_surface_t* s =
828 new egl_surface_t(dp.get(), config, window, surface, colorSpace, cnx);
Courtney Goeltzenleuchtera1e59f12018-03-05 08:19:25 -0700829 return s;
Mathias Agopian518ec112011-05-13 16:21:08 -0700830 }
Mathias Agopian81a63352011-07-29 17:55:48 -0700831
832 // EGLSurface creation failed
833 native_window_set_buffers_format(window, 0);
834 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
Mathias Agopian518ec112011-05-13 16:21:08 -0700835 }
836 return EGL_NO_SURFACE;
837}
838
839EGLSurface eglCreatePixmapSurface( EGLDisplay dpy, EGLConfig config,
840 NativePixmapType pixmap,
841 const EGLint *attrib_list)
842{
843 clearError();
844
Jesse Hallb29e5e82012-04-04 16:53:42 -0700845 egl_connection_t* cnx = NULL;
846 egl_display_ptr dp = validate_display_connection(dpy, cnx);
Courtney Goeltzenleuchter37836572017-04-26 15:07:51 -0600847 EGLint colorSpace;
848 android_dataspace dataSpace;
Jesse Hallb29e5e82012-04-04 16:53:42 -0700849 if (dp) {
Courtney Goeltzenleuchter37836572017-04-26 15:07:51 -0600850 // now select a corresponding sRGB format if needed
851 if (!getColorSpaceAttribute(dp, attrib_list, colorSpace, dataSpace)) {
852 ALOGE("error invalid colorspace: %d", colorSpace);
853 return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
854 }
855
Mathias Agopian518ec112011-05-13 16:21:08 -0700856 EGLSurface surface = cnx->egl.eglCreatePixmapSurface(
Mathias Agopian7773c432012-02-13 20:06:08 -0800857 dp->disp.dpy, config, pixmap, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700858 if (surface != EGL_NO_SURFACE) {
Courtney Goeltzenleuchter37836572017-04-26 15:07:51 -0600859 egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL, surface, colorSpace, cnx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700860 return s;
861 }
862 }
863 return EGL_NO_SURFACE;
864}
865
866EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config,
867 const EGLint *attrib_list)
868{
869 clearError();
870
Jesse Hallb29e5e82012-04-04 16:53:42 -0700871 egl_connection_t* cnx = NULL;
872 egl_display_ptr dp = validate_display_connection(dpy, cnx);
873 if (dp) {
Courtney Goeltzenleuchtereeaa52b2017-06-20 08:12:54 -0600874 EGLDisplay iDpy = dp->disp.dpy;
875 EGLint format;
876 getNativePixelFormat(iDpy, cnx, config, format);
877
878 // now select correct colorspace and dataspace based on user's attribute list
879 EGLint colorSpace;
880 android_dataspace dataSpace;
Courtney Goeltzenleuchter37836572017-04-26 15:07:51 -0600881 if (!getColorSpaceAttribute(dp, attrib_list, colorSpace, dataSpace)) {
882 ALOGE("error invalid colorspace: %d", colorSpace);
883 return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
884 }
885
Courtney Goeltzenleuchtereeaa52b2017-06-20 08:12:54 -0600886 // Pbuffers are not displayed so we don't need to store the
887 // colorspace. We do need to filter out color spaces the
888 // driver doesn't know how to process.
889 std::vector<EGLint> strippedAttribList;
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700890 if (stripAttributes(dp, attrib_list, format, strippedAttribList)) {
Courtney Goeltzenleuchtereeaa52b2017-06-20 08:12:54 -0600891 // Had to modify the attribute list due to use of color space.
892 // Use modified list from here on.
893 attrib_list = strippedAttribList.data();
894 }
895
Mathias Agopian518ec112011-05-13 16:21:08 -0700896 EGLSurface surface = cnx->egl.eglCreatePbufferSurface(
Mathias Agopian7773c432012-02-13 20:06:08 -0800897 dp->disp.dpy, config, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700898 if (surface != EGL_NO_SURFACE) {
Courtney Goeltzenleuchter37836572017-04-26 15:07:51 -0600899 egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL, surface, colorSpace, cnx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700900 return s;
901 }
902 }
903 return EGL_NO_SURFACE;
904}
Jesse Hall47743382013-02-08 11:13:46 -0800905
Mathias Agopian518ec112011-05-13 16:21:08 -0700906EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
907{
908 clearError();
909
Jesse Hallb29e5e82012-04-04 16:53:42 -0700910 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700911 if (!dp) return EGL_FALSE;
912
Jesse Hallb29e5e82012-04-04 16:53:42 -0700913 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700914 if (!_s.get())
Mathias Agopian737b8962017-02-24 14:32:05 -0800915 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700916
917 egl_surface_t * const s = get_surface(surface);
Mathias Agopianada798b2012-02-13 17:09:30 -0800918 EGLBoolean result = s->cnx->egl.eglDestroySurface(dp->disp.dpy, s->surface);
Mathias Agopian518ec112011-05-13 16:21:08 -0700919 if (result == EGL_TRUE) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700920 _s.terminate();
921 }
922 return result;
923}
924
925EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface surface,
926 EGLint attribute, EGLint *value)
927{
928 clearError();
929
Jesse Hallb29e5e82012-04-04 16:53:42 -0700930 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700931 if (!dp) return EGL_FALSE;
932
Jesse Hallb29e5e82012-04-04 16:53:42 -0700933 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700934 if (!_s.get())
Mathias Agopian737b8962017-02-24 14:32:05 -0800935 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700936
Mathias Agopian518ec112011-05-13 16:21:08 -0700937 egl_surface_t const * const s = get_surface(surface);
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700938 if (s->getColorSpaceAttribute(attribute, value)) {
939 return EGL_TRUE;
940 } else if (s->getSmpte2086Attribute(attribute, value)) {
941 return EGL_TRUE;
942 } else if (s->getCta8613Attribute(attribute, value)) {
Courtney Goeltzenleuchter37836572017-04-26 15:07:51 -0600943 return EGL_TRUE;
944 }
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700945 return s->cnx->egl.eglQuerySurface(dp->disp.dpy, s->surface, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -0700946}
947
Jamie Gennise8696a42012-01-15 18:54:57 -0800948void EGLAPI eglBeginFrame(EGLDisplay dpy, EGLSurface surface) {
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800949 ATRACE_CALL();
Jamie Gennise8696a42012-01-15 18:54:57 -0800950 clearError();
951
Jesse Hallb29e5e82012-04-04 16:53:42 -0700952 const egl_display_ptr dp = validate_display(dpy);
Jamie Gennise8696a42012-01-15 18:54:57 -0800953 if (!dp) {
954 return;
955 }
956
Jesse Hallb29e5e82012-04-04 16:53:42 -0700957 SurfaceRef _s(dp.get(), surface);
Jamie Gennise8696a42012-01-15 18:54:57 -0800958 if (!_s.get()) {
959 setError(EGL_BAD_SURFACE, EGL_FALSE);
Jamie Gennise8696a42012-01-15 18:54:57 -0800960 }
Jamie Gennise8696a42012-01-15 18:54:57 -0800961}
962
Mathias Agopian518ec112011-05-13 16:21:08 -0700963// ----------------------------------------------------------------------------
964// Contexts
965// ----------------------------------------------------------------------------
966
967EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config,
968 EGLContext share_list, const EGLint *attrib_list)
969{
970 clearError();
971
Jesse Hallb29e5e82012-04-04 16:53:42 -0700972 egl_connection_t* cnx = NULL;
973 const egl_display_ptr dp = validate_display_connection(dpy, cnx);
Michael Chock0673e1e2012-06-21 12:53:17 -0700974 if (dp) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700975 if (share_list != EGL_NO_CONTEXT) {
Michael Chock0673e1e2012-06-21 12:53:17 -0700976 if (!ContextRef(dp.get(), share_list).get()) {
977 return setError(EGL_BAD_CONTEXT, EGL_NO_CONTEXT);
978 }
Mathias Agopian518ec112011-05-13 16:21:08 -0700979 egl_context_t* const c = get_context(share_list);
980 share_list = c->context;
981 }
982 EGLContext context = cnx->egl.eglCreateContext(
Mathias Agopian7773c432012-02-13 20:06:08 -0800983 dp->disp.dpy, config, share_list, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700984 if (context != EGL_NO_CONTEXT) {
985 // figure out if it's a GLESv1 or GLESv2
986 int version = 0;
987 if (attrib_list) {
988 while (*attrib_list != EGL_NONE) {
989 GLint attr = *attrib_list++;
990 GLint value = *attrib_list++;
991 if (attr == EGL_CONTEXT_CLIENT_VERSION) {
992 if (value == 1) {
Mathias Agopian7773c432012-02-13 20:06:08 -0800993 version = egl_connection_t::GLESv1_INDEX;
Jesse Hall47743382013-02-08 11:13:46 -0800994 } else if (value == 2 || value == 3) {
Mathias Agopian7773c432012-02-13 20:06:08 -0800995 version = egl_connection_t::GLESv2_INDEX;
Mathias Agopian518ec112011-05-13 16:21:08 -0700996 }
997 }
998 };
999 }
Jesse Hallb29e5e82012-04-04 16:53:42 -07001000 egl_context_t* c = new egl_context_t(dpy, context, config, cnx,
1001 version);
Mathias Agopian518ec112011-05-13 16:21:08 -07001002 return c;
1003 }
1004 }
1005 return EGL_NO_CONTEXT;
1006}
1007
1008EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
1009{
1010 clearError();
1011
Jesse Hallb29e5e82012-04-04 16:53:42 -07001012 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001013 if (!dp)
1014 return EGL_FALSE;
Mathias Agopian518ec112011-05-13 16:21:08 -07001015
Jesse Hallb29e5e82012-04-04 16:53:42 -07001016 ContextRef _c(dp.get(), ctx);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001017 if (!_c.get())
Mathias Agopian737b8962017-02-24 14:32:05 -08001018 return setError(EGL_BAD_CONTEXT, (EGLBoolean)EGL_FALSE);
Jesse Hall47743382013-02-08 11:13:46 -08001019
Mathias Agopian518ec112011-05-13 16:21:08 -07001020 egl_context_t * const c = get_context(ctx);
Mathias Agopianada798b2012-02-13 17:09:30 -08001021 EGLBoolean result = c->cnx->egl.eglDestroyContext(dp->disp.dpy, c->context);
Mathias Agopian518ec112011-05-13 16:21:08 -07001022 if (result == EGL_TRUE) {
1023 _c.terminate();
1024 }
1025 return result;
1026}
1027
Mathias Agopian518ec112011-05-13 16:21:08 -07001028EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw,
1029 EGLSurface read, EGLContext ctx)
1030{
1031 clearError();
1032
Jesse Hallb29e5e82012-04-04 16:53:42 -07001033 egl_display_ptr dp = validate_display(dpy);
Mathias Agopian737b8962017-02-24 14:32:05 -08001034 if (!dp) return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001035
Mathias Agopian5b287a62011-05-16 18:58:55 -07001036 // If ctx is not EGL_NO_CONTEXT, read is not EGL_NO_SURFACE, or draw is not
1037 // EGL_NO_SURFACE, then an EGL_NOT_INITIALIZED error is generated if dpy is
1038 // a valid but uninitialized display.
Mathias Agopian518ec112011-05-13 16:21:08 -07001039 if ( (ctx != EGL_NO_CONTEXT) || (read != EGL_NO_SURFACE) ||
1040 (draw != EGL_NO_SURFACE) ) {
Mathias Agopian737b8962017-02-24 14:32:05 -08001041 if (!dp->isReady()) return setError(EGL_NOT_INITIALIZED, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001042 }
1043
1044 // get a reference to the object passed in
Jesse Hallb29e5e82012-04-04 16:53:42 -07001045 ContextRef _c(dp.get(), ctx);
1046 SurfaceRef _d(dp.get(), draw);
1047 SurfaceRef _r(dp.get(), read);
Mathias Agopian518ec112011-05-13 16:21:08 -07001048
1049 // validate the context (if not EGL_NO_CONTEXT)
Mathias Agopian5b287a62011-05-16 18:58:55 -07001050 if ((ctx != EGL_NO_CONTEXT) && !_c.get()) {
Mathias Agopian518ec112011-05-13 16:21:08 -07001051 // EGL_NO_CONTEXT is valid
Mathias Agopian737b8962017-02-24 14:32:05 -08001052 return setError(EGL_BAD_CONTEXT, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001053 }
1054
1055 // these are the underlying implementation's object
1056 EGLContext impl_ctx = EGL_NO_CONTEXT;
1057 EGLSurface impl_draw = EGL_NO_SURFACE;
1058 EGLSurface impl_read = EGL_NO_SURFACE;
1059
1060 // these are our objects structs passed in
1061 egl_context_t * c = NULL;
1062 egl_surface_t const * d = NULL;
1063 egl_surface_t const * r = NULL;
1064
1065 // these are the current objects structs
1066 egl_context_t * cur_c = get_context(getContext());
Jesse Hall47743382013-02-08 11:13:46 -08001067
Mathias Agopian518ec112011-05-13 16:21:08 -07001068 if (ctx != EGL_NO_CONTEXT) {
1069 c = get_context(ctx);
1070 impl_ctx = c->context;
1071 } else {
1072 // no context given, use the implementation of the current context
Michael Chock0673e1e2012-06-21 12:53:17 -07001073 if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE) {
1074 // calling eglMakeCurrent( ..., !=0, !=0, EGL_NO_CONTEXT);
Mathias Agopian737b8962017-02-24 14:32:05 -08001075 return setError(EGL_BAD_MATCH, (EGLBoolean)EGL_FALSE);
Michael Chock0673e1e2012-06-21 12:53:17 -07001076 }
Mathias Agopian518ec112011-05-13 16:21:08 -07001077 if (cur_c == NULL) {
1078 // no current context
Mathias Agopian518ec112011-05-13 16:21:08 -07001079 // not an error, there is just no current context.
1080 return EGL_TRUE;
1081 }
1082 }
1083
1084 // retrieve the underlying implementation's draw EGLSurface
1085 if (draw != EGL_NO_SURFACE) {
Mathias Agopian737b8962017-02-24 14:32:05 -08001086 if (!_d.get()) return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001087 d = get_surface(draw);
Mathias Agopian518ec112011-05-13 16:21:08 -07001088 impl_draw = d->surface;
1089 }
1090
1091 // retrieve the underlying implementation's read EGLSurface
1092 if (read != EGL_NO_SURFACE) {
Mathias Agopian737b8962017-02-24 14:32:05 -08001093 if (!_r.get()) return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001094 r = get_surface(read);
Mathias Agopian518ec112011-05-13 16:21:08 -07001095 impl_read = r->surface;
1096 }
1097
Mathias Agopian518ec112011-05-13 16:21:08 -07001098
Jesse Hallb29e5e82012-04-04 16:53:42 -07001099 EGLBoolean result = dp->makeCurrent(c, cur_c,
Mathias Agopianfb87e542012-01-30 18:20:52 -08001100 draw, read, ctx,
1101 impl_draw, impl_read, impl_ctx);
Mathias Agopian518ec112011-05-13 16:21:08 -07001102
1103 if (result == EGL_TRUE) {
Mathias Agopianfb87e542012-01-30 18:20:52 -08001104 if (c) {
Mathias Agopian518ec112011-05-13 16:21:08 -07001105 setGLHooksThreadSpecific(c->cnx->hooks[c->version]);
1106 egl_tls_t::setContext(ctx);
Mathias Agopian518ec112011-05-13 16:21:08 -07001107 _c.acquire();
1108 _r.acquire();
1109 _d.acquire();
Mathias Agopian518ec112011-05-13 16:21:08 -07001110 } else {
1111 setGLHooksThreadSpecific(&gHooksNoContext);
1112 egl_tls_t::setContext(EGL_NO_CONTEXT);
1113 }
Mathias Agopian5fecea72011-08-25 18:38:24 -07001114 } else {
Steve Blocke6f43dd2012-01-06 19:20:56 +00001115 // this will ALOGE the error
Mathias Agopian63108c32013-09-06 13:36:49 -07001116 egl_connection_t* const cnx = &gEGLImpl;
Mathias Agopian737b8962017-02-24 14:32:05 -08001117 result = setError(cnx->egl.eglGetError(), (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001118 }
1119 return result;
1120}
1121
1122
1123EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx,
1124 EGLint attribute, EGLint *value)
1125{
1126 clearError();
1127
Jesse Hallb29e5e82012-04-04 16:53:42 -07001128 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001129 if (!dp) return EGL_FALSE;
1130
Jesse Hallb29e5e82012-04-04 16:53:42 -07001131 ContextRef _c(dp.get(), ctx);
Mathias Agopian737b8962017-02-24 14:32:05 -08001132 if (!_c.get()) return setError(EGL_BAD_CONTEXT, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001133
Mathias Agopian518ec112011-05-13 16:21:08 -07001134 egl_context_t * const c = get_context(ctx);
Mathias Agopian7773c432012-02-13 20:06:08 -08001135 return c->cnx->egl.eglQueryContext(
1136 dp->disp.dpy, c->context, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -07001137
Mathias Agopian518ec112011-05-13 16:21:08 -07001138}
1139
1140EGLContext eglGetCurrentContext(void)
1141{
1142 // could be called before eglInitialize(), but we wouldn't have a context
1143 // then, and this function would correctly return EGL_NO_CONTEXT.
1144
1145 clearError();
1146
1147 EGLContext ctx = getContext();
1148 return ctx;
1149}
1150
1151EGLSurface eglGetCurrentSurface(EGLint readdraw)
1152{
1153 // could be called before eglInitialize(), but we wouldn't have a context
1154 // then, and this function would correctly return EGL_NO_SURFACE.
1155
1156 clearError();
1157
1158 EGLContext ctx = getContext();
1159 if (ctx) {
1160 egl_context_t const * const c = get_context(ctx);
1161 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
1162 switch (readdraw) {
1163 case EGL_READ: return c->read;
Jesse Hall47743382013-02-08 11:13:46 -08001164 case EGL_DRAW: return c->draw;
Mathias Agopian518ec112011-05-13 16:21:08 -07001165 default: return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
1166 }
1167 }
1168 return EGL_NO_SURFACE;
1169}
1170
1171EGLDisplay eglGetCurrentDisplay(void)
1172{
1173 // could be called before eglInitialize(), but we wouldn't have a context
1174 // then, and this function would correctly return EGL_NO_DISPLAY.
1175
1176 clearError();
1177
1178 EGLContext ctx = getContext();
1179 if (ctx) {
1180 egl_context_t const * const c = get_context(ctx);
1181 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
1182 return c->dpy;
1183 }
1184 return EGL_NO_DISPLAY;
1185}
1186
1187EGLBoolean eglWaitGL(void)
1188{
Mathias Agopian518ec112011-05-13 16:21:08 -07001189 clearError();
1190
Mathias Agopianada798b2012-02-13 17:09:30 -08001191 egl_connection_t* const cnx = &gEGLImpl;
1192 if (!cnx->dso)
Mathias Agopian737b8962017-02-24 14:32:05 -08001193 return setError(EGL_BAD_CONTEXT, (EGLBoolean)EGL_FALSE);
Mathias Agopianada798b2012-02-13 17:09:30 -08001194
1195 return cnx->egl.eglWaitGL();
Mathias Agopian518ec112011-05-13 16:21:08 -07001196}
1197
1198EGLBoolean eglWaitNative(EGLint engine)
1199{
Mathias Agopian518ec112011-05-13 16:21:08 -07001200 clearError();
1201
Mathias Agopianada798b2012-02-13 17:09:30 -08001202 egl_connection_t* const cnx = &gEGLImpl;
1203 if (!cnx->dso)
Mathias Agopian737b8962017-02-24 14:32:05 -08001204 return setError(EGL_BAD_CONTEXT, (EGLBoolean)EGL_FALSE);
Mathias Agopianada798b2012-02-13 17:09:30 -08001205
1206 return cnx->egl.eglWaitNative(engine);
Mathias Agopian518ec112011-05-13 16:21:08 -07001207}
1208
1209EGLint eglGetError(void)
1210{
Mathias Agopianada798b2012-02-13 17:09:30 -08001211 EGLint err = EGL_SUCCESS;
1212 egl_connection_t* const cnx = &gEGLImpl;
1213 if (cnx->dso) {
1214 err = cnx->egl.eglGetError();
Mathias Agopian518ec112011-05-13 16:21:08 -07001215 }
Mathias Agopianada798b2012-02-13 17:09:30 -08001216 if (err == EGL_SUCCESS) {
1217 err = egl_tls_t::getError();
1218 }
1219 return err;
Mathias Agopian518ec112011-05-13 16:21:08 -07001220}
1221
Michael Chockc0ec5e22014-01-27 08:14:33 -08001222static __eglMustCastToProperFunctionPointerType findBuiltinWrapper(
Jesse Hallc07b5202013-07-04 12:08:16 -07001223 const char* procname) {
1224 const egl_connection_t* cnx = &gEGLImpl;
1225 void* proc = NULL;
1226
Michael Chockc0ec5e22014-01-27 08:14:33 -08001227 proc = dlsym(cnx->libEgl, procname);
1228 if (proc) return (__eglMustCastToProperFunctionPointerType)proc;
1229
Jesse Hallc07b5202013-07-04 12:08:16 -07001230 proc = dlsym(cnx->libGles2, procname);
1231 if (proc) return (__eglMustCastToProperFunctionPointerType)proc;
1232
1233 proc = dlsym(cnx->libGles1, procname);
1234 if (proc) return (__eglMustCastToProperFunctionPointerType)proc;
1235
1236 return NULL;
1237}
1238
Mathias Agopian518ec112011-05-13 16:21:08 -07001239__eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
1240{
1241 // eglGetProcAddress() could be the very first function called
1242 // in which case we must make sure we've initialized ourselves, this
1243 // happens the first time egl_get_display() is called.
1244
1245 clearError();
1246
1247 if (egl_init_drivers() == EGL_FALSE) {
1248 setError(EGL_BAD_PARAMETER, NULL);
1249 return NULL;
1250 }
1251
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -07001252 if (FILTER_EXTENSIONS(procname)) {
Jamie Gennisaca51c02011-11-03 17:42:43 -07001253 return NULL;
1254 }
1255
Mathias Agopian518ec112011-05-13 16:21:08 -07001256 __eglMustCastToProperFunctionPointerType addr;
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -07001257 addr = findProcAddress(procname, sExtensionMap, NELEM(sExtensionMap));
Mathias Agopian518ec112011-05-13 16:21:08 -07001258 if (addr) return addr;
1259
Michael Chockc0ec5e22014-01-27 08:14:33 -08001260 addr = findBuiltinWrapper(procname);
Jesse Hallc07b5202013-07-04 12:08:16 -07001261 if (addr) return addr;
Jamie Gennisaca51c02011-11-03 17:42:43 -07001262
Mathias Agopian518ec112011-05-13 16:21:08 -07001263 // this protects accesses to sGLExtentionMap and sGLExtentionSlot
1264 pthread_mutex_lock(&sExtensionMapMutex);
1265
1266 /*
1267 * Since eglGetProcAddress() is not associated to anything, it needs
1268 * to return a function pointer that "works" regardless of what
1269 * the current context is.
1270 *
1271 * For this reason, we return a "forwarder", a small stub that takes
1272 * care of calling the function associated with the context
1273 * currently bound.
1274 *
1275 * We first look for extensions we've already resolved, if we're seeing
1276 * this extension for the first time, we go through all our
1277 * implementations and call eglGetProcAddress() and record the
1278 * result in the appropriate implementation hooks and return the
1279 * address of the forwarder corresponding to that hook set.
1280 *
1281 */
1282
Mathias Agopian65421432017-03-08 11:49:05 -08001283 const std::string name(procname);
1284
1285 auto& extentionMap = sGLExtentionMap;
1286 auto pos = extentionMap.find(name);
1287 addr = (pos != extentionMap.end()) ? pos->second : nullptr;
Mathias Agopian518ec112011-05-13 16:21:08 -07001288 const int slot = sGLExtentionSlot;
1289
Steve Blocke6f43dd2012-01-06 19:20:56 +00001290 ALOGE_IF(slot >= MAX_NUMBER_OF_GL_EXTENSIONS,
Mathias Agopian518ec112011-05-13 16:21:08 -07001291 "no more slots for eglGetProcAddress(\"%s\")",
1292 procname);
1293
1294 if (!addr && (slot < MAX_NUMBER_OF_GL_EXTENSIONS)) {
1295 bool found = false;
Mathias Agopianada798b2012-02-13 17:09:30 -08001296
1297 egl_connection_t* const cnx = &gEGLImpl;
1298 if (cnx->dso && cnx->egl.eglGetProcAddress) {
Mathias Agopianada798b2012-02-13 17:09:30 -08001299 // Extensions are independent of the bound context
luliuhui69d10072012-08-30 11:15:36 +08001300 addr =
Mathias Agopian7773c432012-02-13 20:06:08 -08001301 cnx->hooks[egl_connection_t::GLESv1_INDEX]->ext.extensions[slot] =
1302 cnx->hooks[egl_connection_t::GLESv2_INDEX]->ext.extensions[slot] =
Mathias Agopianada798b2012-02-13 17:09:30 -08001303 cnx->egl.eglGetProcAddress(procname);
luliuhui69d10072012-08-30 11:15:36 +08001304 if (addr) found = true;
Mathias Agopian518ec112011-05-13 16:21:08 -07001305 }
Mathias Agopianada798b2012-02-13 17:09:30 -08001306
Mathias Agopian518ec112011-05-13 16:21:08 -07001307 if (found) {
1308 addr = gExtensionForwarders[slot];
Mathias Agopian65421432017-03-08 11:49:05 -08001309 extentionMap[name] = addr;
Mathias Agopian518ec112011-05-13 16:21:08 -07001310 sGLExtentionSlot++;
1311 }
1312 }
1313
1314 pthread_mutex_unlock(&sExtensionMapMutex);
1315 return addr;
1316}
1317
Mathias Agopian65421432017-03-08 11:49:05 -08001318class FrameCompletionThread {
Jamie Gennis28ef8d72012-04-05 20:34:54 -07001319public:
1320
1321 static void queueSync(EGLSyncKHR sync) {
Mathias Agopian65421432017-03-08 11:49:05 -08001322 static FrameCompletionThread thread;
1323
1324 char name[64];
1325
1326 std::lock_guard<std::mutex> lock(thread.mMutex);
1327 snprintf(name, sizeof(name), "kicked off frame %u", (unsigned int)thread.mFramesQueued);
1328 ATRACE_NAME(name);
1329
1330 thread.mQueue.push_back(sync);
1331 thread.mCondition.notify_one();
1332 thread.mFramesQueued++;
1333 ATRACE_INT("GPU Frames Outstanding", int32_t(thread.mQueue.size()));
Jamie Gennis28ef8d72012-04-05 20:34:54 -07001334 }
1335
1336private:
Jamie Gennis28ef8d72012-04-05 20:34:54 -07001337
Mathias Agopian65421432017-03-08 11:49:05 -08001338 FrameCompletionThread() : mFramesQueued(0), mFramesCompleted(0) {
1339 std::thread thread(&FrameCompletionThread::loop, this);
1340 thread.detach();
1341 }
1342
1343#pragma clang diagnostic push
1344#pragma clang diagnostic ignored "-Wmissing-noreturn"
1345 void loop() {
1346 while (true) {
1347 threadLoop();
1348 }
1349 }
1350#pragma clang diagnostic pop
1351
1352 void threadLoop() {
Jamie Gennis28ef8d72012-04-05 20:34:54 -07001353 EGLSyncKHR sync;
1354 uint32_t frameNum;
1355 {
Mathias Agopian65421432017-03-08 11:49:05 -08001356 std::unique_lock<std::mutex> lock(mMutex);
1357 while (mQueue.empty()) {
1358 mCondition.wait(lock);
Jamie Gennis28ef8d72012-04-05 20:34:54 -07001359 }
1360 sync = mQueue[0];
1361 frameNum = mFramesCompleted;
1362 }
1363 EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
1364 {
Mathias Agopian65421432017-03-08 11:49:05 -08001365 char name[64];
1366 snprintf(name, sizeof(name), "waiting for frame %u", (unsigned int)frameNum);
1367 ATRACE_NAME(name);
1368
Jamie Gennis28ef8d72012-04-05 20:34:54 -07001369 EGLint result = eglClientWaitSyncKHR(dpy, sync, 0, EGL_FOREVER_KHR);
1370 if (result == EGL_FALSE) {
1371 ALOGE("FrameCompletion: error waiting for fence: %#x", eglGetError());
1372 } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
1373 ALOGE("FrameCompletion: timeout waiting for fence");
1374 }
1375 eglDestroySyncKHR(dpy, sync);
1376 }
1377 {
Mathias Agopian65421432017-03-08 11:49:05 -08001378 std::lock_guard<std::mutex> lock(mMutex);
1379 mQueue.pop_front();
Jamie Gennis28ef8d72012-04-05 20:34:54 -07001380 mFramesCompleted++;
Mathias Agopian737b8962017-02-24 14:32:05 -08001381 ATRACE_INT("GPU Frames Outstanding", int32_t(mQueue.size()));
Jamie Gennis28ef8d72012-04-05 20:34:54 -07001382 }
Jamie Gennis28ef8d72012-04-05 20:34:54 -07001383 }
1384
1385 uint32_t mFramesQueued;
1386 uint32_t mFramesCompleted;
Mathias Agopian65421432017-03-08 11:49:05 -08001387 std::deque<EGLSyncKHR> mQueue;
1388 std::condition_variable mCondition;
1389 std::mutex mMutex;
Jamie Gennis28ef8d72012-04-05 20:34:54 -07001390};
1391
Dan Stozaa894d082015-02-19 15:27:36 -08001392EGLBoolean eglSwapBuffersWithDamageKHR(EGLDisplay dpy, EGLSurface draw,
1393 EGLint *rects, EGLint n_rects)
Mathias Agopian518ec112011-05-13 16:21:08 -07001394{
Jamie Gennis1c8e95c2012-02-23 19:27:23 -08001395 ATRACE_CALL();
Mathias Agopian518ec112011-05-13 16:21:08 -07001396 clearError();
1397
Jesse Hallb29e5e82012-04-04 16:53:42 -07001398 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001399 if (!dp) return EGL_FALSE;
1400
Jesse Hallb29e5e82012-04-04 16:53:42 -07001401 SurfaceRef _s(dp.get(), draw);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001402 if (!_s.get())
Mathias Agopian737b8962017-02-24 14:32:05 -08001403 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001404
Courtney Goeltzenleuchter936799c2018-03-02 16:47:08 -07001405 egl_surface_t* const s = get_surface(draw);
Mathias Agopian7db993a2012-03-25 00:49:46 -07001406
Mathias Agopianed6d08b2013-04-16 16:39:46 -07001407 if (CC_UNLIKELY(dp->traceGpuCompletion)) {
1408 EGLSyncKHR sync = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, NULL);
1409 if (sync != EGL_NO_SYNC_KHR) {
1410 FrameCompletionThread::queueSync(sync);
1411 }
1412 }
1413
Mathias Agopian7db993a2012-03-25 00:49:46 -07001414 if (CC_UNLIKELY(dp->finishOnSwap)) {
1415 uint32_t pixel;
1416 egl_context_t * const c = get_context( egl_tls_t::getContext() );
1417 if (c) {
1418 // glReadPixels() ensures that the frame is complete
1419 s->cnx->hooks[c->version]->gl.glReadPixels(0,0,1,1,
1420 GL_RGBA,GL_UNSIGNED_BYTE,&pixel);
1421 }
1422 }
1423
Courtney Goeltzenleuchter936799c2018-03-02 16:47:08 -07001424 if (!sendSurfaceMetadata(s)) {
1425 native_window_api_disconnect(s->getNativeWindow(), NATIVE_WINDOW_API_EGL);
1426 return setError(EGL_BAD_NATIVE_WINDOW, (EGLBoolean)EGL_FALSE);
1427 }
1428
Dan Stozaa894d082015-02-19 15:27:36 -08001429 if (n_rects == 0) {
1430 return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface);
1431 }
1432
Mathias Agopian65421432017-03-08 11:49:05 -08001433 std::vector<android_native_rect_t> androidRects((size_t)n_rects);
Dan Stozaa894d082015-02-19 15:27:36 -08001434 for (int r = 0; r < n_rects; ++r) {
1435 int offset = r * 4;
1436 int x = rects[offset];
1437 int y = rects[offset + 1];
1438 int width = rects[offset + 2];
1439 int height = rects[offset + 3];
1440 android_native_rect_t androidRect;
1441 androidRect.left = x;
1442 androidRect.top = y + height;
1443 androidRect.right = x + width;
1444 androidRect.bottom = y;
1445 androidRects.push_back(androidRect);
1446 }
Mathias Agopian65421432017-03-08 11:49:05 -08001447 native_window_set_surface_damage(s->getNativeWindow(), androidRects.data(), androidRects.size());
Dan Stozaa894d082015-02-19 15:27:36 -08001448
1449 if (s->cnx->egl.eglSwapBuffersWithDamageKHR) {
1450 return s->cnx->egl.eglSwapBuffersWithDamageKHR(dp->disp.dpy, s->surface,
1451 rects, n_rects);
1452 } else {
1453 return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface);
1454 }
1455}
1456
1457EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
1458{
1459 return eglSwapBuffersWithDamageKHR(dpy, surface, NULL, 0);
Mathias Agopian518ec112011-05-13 16:21:08 -07001460}
1461
1462EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface,
1463 NativePixmapType target)
1464{
1465 clearError();
1466
Jesse Hallb29e5e82012-04-04 16:53:42 -07001467 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001468 if (!dp) return EGL_FALSE;
1469
Jesse Hallb29e5e82012-04-04 16:53:42 -07001470 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001471 if (!_s.get())
Mathias Agopian737b8962017-02-24 14:32:05 -08001472 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001473
Mathias Agopian518ec112011-05-13 16:21:08 -07001474 egl_surface_t const * const s = get_surface(surface);
Mathias Agopianada798b2012-02-13 17:09:30 -08001475 return s->cnx->egl.eglCopyBuffers(dp->disp.dpy, s->surface, target);
Mathias Agopian518ec112011-05-13 16:21:08 -07001476}
1477
1478const char* eglQueryString(EGLDisplay dpy, EGLint name)
1479{
1480 clearError();
1481
Chia-I Wue57d1352016-08-15 16:10:02 +08001482 // Generate an error quietly when client extensions (as defined by
1483 // EGL_EXT_client_extensions) are queried. We do not want to rely on
1484 // validate_display to generate the error as validate_display would log
1485 // the error, which can be misleading.
1486 //
1487 // If we want to support EGL_EXT_client_extensions later, we can return
1488 // the client extension string here instead.
1489 if (dpy == EGL_NO_DISPLAY && name == EGL_EXTENSIONS)
Mathias Agopian737b8962017-02-24 14:32:05 -08001490 return setErrorQuiet(EGL_BAD_DISPLAY, (const char*)0);
Chia-I Wue57d1352016-08-15 16:10:02 +08001491
Jesse Hallb29e5e82012-04-04 16:53:42 -07001492 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001493 if (!dp) return (const char *) NULL;
1494
1495 switch (name) {
1496 case EGL_VENDOR:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001497 return dp->getVendorString();
Mathias Agopian518ec112011-05-13 16:21:08 -07001498 case EGL_VERSION:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001499 return dp->getVersionString();
Mathias Agopian518ec112011-05-13 16:21:08 -07001500 case EGL_EXTENSIONS:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001501 return dp->getExtensionString();
Mathias Agopian518ec112011-05-13 16:21:08 -07001502 case EGL_CLIENT_APIS:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001503 return dp->getClientApiString();
Mathias Agopian737b8962017-02-24 14:32:05 -08001504 default:
1505 break;
Mathias Agopian518ec112011-05-13 16:21:08 -07001506 }
1507 return setError(EGL_BAD_PARAMETER, (const char *)0);
1508}
1509
Jiyong Park00b15b82017-08-10 20:30:56 +09001510extern "C" EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name)
Mathias Agopianca088332013-03-28 17:44:13 -07001511{
1512 clearError();
1513
1514 const egl_display_ptr dp = validate_display(dpy);
1515 if (!dp) return (const char *) NULL;
1516
1517 switch (name) {
1518 case EGL_VENDOR:
1519 return dp->disp.queryString.vendor;
1520 case EGL_VERSION:
1521 return dp->disp.queryString.version;
1522 case EGL_EXTENSIONS:
1523 return dp->disp.queryString.extensions;
1524 case EGL_CLIENT_APIS:
1525 return dp->disp.queryString.clientApi;
Mathias Agopian737b8962017-02-24 14:32:05 -08001526 default:
1527 break;
Mathias Agopianca088332013-03-28 17:44:13 -07001528 }
1529 return setError(EGL_BAD_PARAMETER, (const char *)0);
1530}
Mathias Agopian518ec112011-05-13 16:21:08 -07001531
1532// ----------------------------------------------------------------------------
1533// EGL 1.1
1534// ----------------------------------------------------------------------------
1535
1536EGLBoolean eglSurfaceAttrib(
1537 EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
1538{
1539 clearError();
1540
Jesse Hallb29e5e82012-04-04 16:53:42 -07001541 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001542 if (!dp) return EGL_FALSE;
1543
Jesse Hallb29e5e82012-04-04 16:53:42 -07001544 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001545 if (!_s.get())
Mathias Agopian737b8962017-02-24 14:32:05 -08001546 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001547
Pablo Ceballosc18be292016-05-31 14:55:42 -07001548 egl_surface_t * const s = get_surface(surface);
Pablo Ceballosccdfd602015-10-07 15:05:45 -07001549
Pablo Ceballos02b05da2016-02-02 17:53:18 -08001550 if (attribute == EGL_FRONT_BUFFER_AUTO_REFRESH_ANDROID) {
Mathias Agopian65421432017-03-08 11:49:05 -08001551 if (!s->getNativeWindow()) {
Brian Anderson069b3652016-07-22 10:32:47 -07001552 setError(EGL_BAD_SURFACE, EGL_FALSE);
1553 }
Mathias Agopian65421432017-03-08 11:49:05 -08001554 int err = native_window_set_auto_refresh(s->getNativeWindow(), value != 0);
1555 return (err == 0) ? EGL_TRUE : setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Pablo Ceballosccdfd602015-10-07 15:05:45 -07001556 }
1557
Pablo Ceballosc18be292016-05-31 14:55:42 -07001558 if (attribute == EGL_TIMESTAMPS_ANDROID) {
Mathias Agopian65421432017-03-08 11:49:05 -08001559 if (!s->getNativeWindow()) {
Mathias Agopian737b8962017-02-24 14:32:05 -08001560 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Brian Anderson069b3652016-07-22 10:32:47 -07001561 }
Mathias Agopian65421432017-03-08 11:49:05 -08001562 int err = native_window_enable_frame_timestamps(s->getNativeWindow(), value != 0);
1563 return (err == 0) ? EGL_TRUE : setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Pablo Ceballosc18be292016-05-31 14:55:42 -07001564 }
1565
Courtney Goeltzenleuchter786ab882018-01-26 13:37:33 -08001566 if (s->setSmpte2086Attribute(attribute, value)) {
1567 return EGL_TRUE;
1568 } else if (s->setCta8613Attribute(attribute, value)) {
1569 return EGL_TRUE;
1570 } else if (s->cnx->egl.eglSurfaceAttrib) {
Mathias Agopian518ec112011-05-13 16:21:08 -07001571 return s->cnx->egl.eglSurfaceAttrib(
Mathias Agopianada798b2012-02-13 17:09:30 -08001572 dp->disp.dpy, s->surface, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -07001573 }
Mathias Agopian737b8962017-02-24 14:32:05 -08001574 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001575}
1576
1577EGLBoolean eglBindTexImage(
1578 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1579{
1580 clearError();
1581
Jesse Hallb29e5e82012-04-04 16:53:42 -07001582 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001583 if (!dp) return EGL_FALSE;
1584
Jesse Hallb29e5e82012-04-04 16:53:42 -07001585 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001586 if (!_s.get())
Mathias Agopian737b8962017-02-24 14:32:05 -08001587 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001588
Mathias Agopian518ec112011-05-13 16:21:08 -07001589 egl_surface_t const * const s = get_surface(surface);
1590 if (s->cnx->egl.eglBindTexImage) {
1591 return s->cnx->egl.eglBindTexImage(
Mathias Agopianada798b2012-02-13 17:09:30 -08001592 dp->disp.dpy, s->surface, buffer);
Mathias Agopian518ec112011-05-13 16:21:08 -07001593 }
Mathias Agopian737b8962017-02-24 14:32:05 -08001594 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001595}
1596
1597EGLBoolean eglReleaseTexImage(
1598 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1599{
1600 clearError();
1601
Jesse Hallb29e5e82012-04-04 16:53:42 -07001602 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001603 if (!dp) return EGL_FALSE;
1604
Jesse Hallb29e5e82012-04-04 16:53:42 -07001605 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001606 if (!_s.get())
Mathias Agopian737b8962017-02-24 14:32:05 -08001607 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001608
Mathias Agopian518ec112011-05-13 16:21:08 -07001609 egl_surface_t const * const s = get_surface(surface);
1610 if (s->cnx->egl.eglReleaseTexImage) {
1611 return s->cnx->egl.eglReleaseTexImage(
Mathias Agopianada798b2012-02-13 17:09:30 -08001612 dp->disp.dpy, s->surface, buffer);
Mathias Agopian518ec112011-05-13 16:21:08 -07001613 }
Mathias Agopian737b8962017-02-24 14:32:05 -08001614 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001615}
1616
1617EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
1618{
1619 clearError();
1620
Jesse Hallb29e5e82012-04-04 16:53:42 -07001621 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001622 if (!dp) return EGL_FALSE;
1623
1624 EGLBoolean res = EGL_TRUE;
Mathias Agopianada798b2012-02-13 17:09:30 -08001625 egl_connection_t* const cnx = &gEGLImpl;
1626 if (cnx->dso && cnx->egl.eglSwapInterval) {
1627 res = cnx->egl.eglSwapInterval(dp->disp.dpy, interval);
Mathias Agopian518ec112011-05-13 16:21:08 -07001628 }
Mathias Agopianada798b2012-02-13 17:09:30 -08001629
Mathias Agopian518ec112011-05-13 16:21:08 -07001630 return res;
1631}
1632
1633
1634// ----------------------------------------------------------------------------
1635// EGL 1.2
1636// ----------------------------------------------------------------------------
1637
1638EGLBoolean eglWaitClient(void)
1639{
1640 clearError();
1641
Mathias Agopianada798b2012-02-13 17:09:30 -08001642 egl_connection_t* const cnx = &gEGLImpl;
1643 if (!cnx->dso)
Mathias Agopian737b8962017-02-24 14:32:05 -08001644 return setError(EGL_BAD_CONTEXT, (EGLBoolean)EGL_FALSE);
Mathias Agopianada798b2012-02-13 17:09:30 -08001645
1646 EGLBoolean res;
1647 if (cnx->egl.eglWaitClient) {
1648 res = cnx->egl.eglWaitClient();
1649 } else {
1650 res = cnx->egl.eglWaitGL();
Mathias Agopian518ec112011-05-13 16:21:08 -07001651 }
1652 return res;
1653}
1654
1655EGLBoolean eglBindAPI(EGLenum api)
1656{
1657 clearError();
1658
1659 if (egl_init_drivers() == EGL_FALSE) {
Mathias Agopian737b8962017-02-24 14:32:05 -08001660 return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001661 }
1662
1663 // bind this API on all EGLs
1664 EGLBoolean res = EGL_TRUE;
Mathias Agopianada798b2012-02-13 17:09:30 -08001665 egl_connection_t* const cnx = &gEGLImpl;
1666 if (cnx->dso && cnx->egl.eglBindAPI) {
1667 res = cnx->egl.eglBindAPI(api);
Mathias Agopian518ec112011-05-13 16:21:08 -07001668 }
1669 return res;
1670}
1671
1672EGLenum eglQueryAPI(void)
1673{
1674 clearError();
1675
1676 if (egl_init_drivers() == EGL_FALSE) {
Mathias Agopian737b8962017-02-24 14:32:05 -08001677 return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001678 }
1679
Mathias Agopianada798b2012-02-13 17:09:30 -08001680 egl_connection_t* const cnx = &gEGLImpl;
1681 if (cnx->dso && cnx->egl.eglQueryAPI) {
1682 return cnx->egl.eglQueryAPI();
Mathias Agopian518ec112011-05-13 16:21:08 -07001683 }
Mathias Agopianada798b2012-02-13 17:09:30 -08001684
Mathias Agopian518ec112011-05-13 16:21:08 -07001685 // or, it can only be OpenGL ES
1686 return EGL_OPENGL_ES_API;
1687}
1688
1689EGLBoolean eglReleaseThread(void)
1690{
1691 clearError();
1692
Mathias Agopianada798b2012-02-13 17:09:30 -08001693 egl_connection_t* const cnx = &gEGLImpl;
1694 if (cnx->dso && cnx->egl.eglReleaseThread) {
1695 cnx->egl.eglReleaseThread();
Mathias Agopian518ec112011-05-13 16:21:08 -07001696 }
Sai Kiran Korwar3ac517a2014-01-31 21:15:07 +05301697
1698 // If there is context bound to the thread, release it
1699 egl_display_t::loseCurrent(get_context(getContext()));
1700
Mathias Agopian518ec112011-05-13 16:21:08 -07001701 egl_tls_t::clearTLS();
Mathias Agopian518ec112011-05-13 16:21:08 -07001702 return EGL_TRUE;
1703}
1704
1705EGLSurface eglCreatePbufferFromClientBuffer(
1706 EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer,
1707 EGLConfig config, const EGLint *attrib_list)
1708{
1709 clearError();
1710
Jesse Hallb29e5e82012-04-04 16:53:42 -07001711 egl_connection_t* cnx = NULL;
1712 const egl_display_ptr dp = validate_display_connection(dpy, cnx);
1713 if (!dp) return EGL_FALSE;
Mathias Agopian518ec112011-05-13 16:21:08 -07001714 if (cnx->egl.eglCreatePbufferFromClientBuffer) {
1715 return cnx->egl.eglCreatePbufferFromClientBuffer(
Mathias Agopian7773c432012-02-13 20:06:08 -08001716 dp->disp.dpy, buftype, buffer, config, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001717 }
1718 return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE);
1719}
1720
1721// ----------------------------------------------------------------------------
1722// EGL_EGLEXT_VERSION 3
1723// ----------------------------------------------------------------------------
1724
1725EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface,
1726 const EGLint *attrib_list)
1727{
1728 clearError();
1729
Jesse Hallb29e5e82012-04-04 16:53:42 -07001730 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001731 if (!dp) return EGL_FALSE;
1732
Jesse Hallb29e5e82012-04-04 16:53:42 -07001733 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001734 if (!_s.get())
Mathias Agopian737b8962017-02-24 14:32:05 -08001735 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001736
1737 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian518ec112011-05-13 16:21:08 -07001738 if (s->cnx->egl.eglLockSurfaceKHR) {
1739 return s->cnx->egl.eglLockSurfaceKHR(
Mathias Agopianada798b2012-02-13 17:09:30 -08001740 dp->disp.dpy, s->surface, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001741 }
Mathias Agopian737b8962017-02-24 14:32:05 -08001742 return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001743}
1744
1745EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface)
1746{
1747 clearError();
1748
Jesse Hallb29e5e82012-04-04 16:53:42 -07001749 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001750 if (!dp) return EGL_FALSE;
1751
Jesse Hallb29e5e82012-04-04 16:53:42 -07001752 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001753 if (!_s.get())
Mathias Agopian737b8962017-02-24 14:32:05 -08001754 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001755
1756 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian518ec112011-05-13 16:21:08 -07001757 if (s->cnx->egl.eglUnlockSurfaceKHR) {
Mathias Agopianada798b2012-02-13 17:09:30 -08001758 return s->cnx->egl.eglUnlockSurfaceKHR(dp->disp.dpy, s->surface);
Mathias Agopian518ec112011-05-13 16:21:08 -07001759 }
Mathias Agopian737b8962017-02-24 14:32:05 -08001760 return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001761}
1762
1763EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
1764 EGLClientBuffer buffer, const EGLint *attrib_list)
1765{
1766 clearError();
1767
Jesse Hallb29e5e82012-04-04 16:53:42 -07001768 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001769 if (!dp) return EGL_NO_IMAGE_KHR;
1770
Jesse Hallb29e5e82012-04-04 16:53:42 -07001771 ContextRef _c(dp.get(), ctx);
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001772 egl_context_t * const c = _c.get();
Mathias Agopian518ec112011-05-13 16:21:08 -07001773
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001774 EGLImageKHR result = EGL_NO_IMAGE_KHR;
1775 egl_connection_t* const cnx = &gEGLImpl;
1776 if (cnx->dso && cnx->egl.eglCreateImageKHR) {
1777 result = cnx->egl.eglCreateImageKHR(
1778 dp->disp.dpy,
1779 c ? c->context : EGL_NO_CONTEXT,
1780 target, buffer, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001781 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001782 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001783}
1784
1785EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
1786{
1787 clearError();
1788
Jesse Hallb29e5e82012-04-04 16:53:42 -07001789 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001790 if (!dp) return EGL_FALSE;
1791
Steven Holte646a5c52012-06-04 20:02:11 -07001792 EGLBoolean result = EGL_FALSE;
Mathias Agopianada798b2012-02-13 17:09:30 -08001793 egl_connection_t* const cnx = &gEGLImpl;
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001794 if (cnx->dso && cnx->egl.eglDestroyImageKHR) {
Steven Holte646a5c52012-06-04 20:02:11 -07001795 result = cnx->egl.eglDestroyImageKHR(dp->disp.dpy, img);
Mathias Agopian518ec112011-05-13 16:21:08 -07001796 }
Steven Holte646a5c52012-06-04 20:02:11 -07001797 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001798}
1799
1800// ----------------------------------------------------------------------------
1801// EGL_EGLEXT_VERSION 5
1802// ----------------------------------------------------------------------------
1803
1804
1805EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
1806{
1807 clearError();
1808
Jesse Hallb29e5e82012-04-04 16:53:42 -07001809 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001810 if (!dp) return EGL_NO_SYNC_KHR;
1811
Mathias Agopian518ec112011-05-13 16:21:08 -07001812 EGLSyncKHR result = EGL_NO_SYNC_KHR;
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001813 egl_connection_t* const cnx = &gEGLImpl;
1814 if (cnx->dso && cnx->egl.eglCreateSyncKHR) {
1815 result = cnx->egl.eglCreateSyncKHR(dp->disp.dpy, type, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001816 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001817 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001818}
1819
1820EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
1821{
1822 clearError();
1823
Jesse Hallb29e5e82012-04-04 16:53:42 -07001824 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001825 if (!dp) return EGL_FALSE;
1826
Mathias Agopian518ec112011-05-13 16:21:08 -07001827 EGLBoolean result = EGL_FALSE;
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001828 egl_connection_t* const cnx = &gEGLImpl;
1829 if (cnx->dso && cnx->egl.eglDestroySyncKHR) {
1830 result = cnx->egl.eglDestroySyncKHR(dp->disp.dpy, sync);
Mathias Agopian518ec112011-05-13 16:21:08 -07001831 }
1832 return result;
1833}
1834
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -07001835EGLBoolean eglSignalSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode) {
1836 clearError();
1837
1838 const egl_display_ptr dp = validate_display(dpy);
1839 if (!dp) return EGL_FALSE;
1840
1841 EGLBoolean result = EGL_FALSE;
1842 egl_connection_t* const cnx = &gEGLImpl;
1843 if (cnx->dso && cnx->egl.eglSignalSyncKHR) {
1844 result = cnx->egl.eglSignalSyncKHR(
1845 dp->disp.dpy, sync, mode);
1846 }
1847 return result;
1848}
1849
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001850EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync,
1851 EGLint flags, EGLTimeKHR timeout)
Mathias Agopian518ec112011-05-13 16:21:08 -07001852{
1853 clearError();
1854
Jesse Hallb29e5e82012-04-04 16:53:42 -07001855 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001856 if (!dp) return EGL_FALSE;
1857
Mathias Agopian737b8962017-02-24 14:32:05 -08001858 EGLint result = EGL_FALSE;
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001859 egl_connection_t* const cnx = &gEGLImpl;
1860 if (cnx->dso && cnx->egl.eglClientWaitSyncKHR) {
1861 result = cnx->egl.eglClientWaitSyncKHR(
1862 dp->disp.dpy, sync, flags, timeout);
Mathias Agopian518ec112011-05-13 16:21:08 -07001863 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001864 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001865}
1866
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001867EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync,
1868 EGLint attribute, EGLint *value)
Mathias Agopian518ec112011-05-13 16:21:08 -07001869{
1870 clearError();
1871
Jesse Hallb29e5e82012-04-04 16:53:42 -07001872 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001873 if (!dp) return EGL_FALSE;
1874
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001875 EGLBoolean result = EGL_FALSE;
1876 egl_connection_t* const cnx = &gEGLImpl;
1877 if (cnx->dso && cnx->egl.eglGetSyncAttribKHR) {
1878 result = cnx->egl.eglGetSyncAttribKHR(
1879 dp->disp.dpy, sync, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -07001880 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001881 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001882}
1883
Season Li000d88f2015-07-01 11:39:40 -07001884EGLStreamKHR eglCreateStreamKHR(EGLDisplay dpy, const EGLint *attrib_list)
1885{
1886 clearError();
1887
1888 const egl_display_ptr dp = validate_display(dpy);
1889 if (!dp) return EGL_NO_STREAM_KHR;
1890
1891 EGLStreamKHR result = EGL_NO_STREAM_KHR;
1892 egl_connection_t* const cnx = &gEGLImpl;
1893 if (cnx->dso && cnx->egl.eglCreateStreamKHR) {
1894 result = cnx->egl.eglCreateStreamKHR(
1895 dp->disp.dpy, attrib_list);
1896 }
1897 return result;
1898}
1899
1900EGLBoolean eglDestroyStreamKHR(EGLDisplay dpy, EGLStreamKHR stream)
1901{
1902 clearError();
1903
1904 const egl_display_ptr dp = validate_display(dpy);
1905 if (!dp) return EGL_FALSE;
1906
1907 EGLBoolean result = EGL_FALSE;
1908 egl_connection_t* const cnx = &gEGLImpl;
1909 if (cnx->dso && cnx->egl.eglDestroyStreamKHR) {
1910 result = cnx->egl.eglDestroyStreamKHR(
1911 dp->disp.dpy, stream);
1912 }
1913 return result;
1914}
1915
1916EGLBoolean eglStreamAttribKHR(EGLDisplay dpy, EGLStreamKHR stream,
1917 EGLenum attribute, EGLint value)
1918{
1919 clearError();
1920
1921 const egl_display_ptr dp = validate_display(dpy);
1922 if (!dp) return EGL_FALSE;
1923
1924 EGLBoolean result = EGL_FALSE;
1925 egl_connection_t* const cnx = &gEGLImpl;
1926 if (cnx->dso && cnx->egl.eglStreamAttribKHR) {
1927 result = cnx->egl.eglStreamAttribKHR(
1928 dp->disp.dpy, stream, attribute, value);
1929 }
1930 return result;
1931}
1932
1933EGLBoolean eglQueryStreamKHR(EGLDisplay dpy, EGLStreamKHR stream,
1934 EGLenum attribute, EGLint *value)
1935{
1936 clearError();
1937
1938 const egl_display_ptr dp = validate_display(dpy);
1939 if (!dp) return EGL_FALSE;
1940
1941 EGLBoolean result = EGL_FALSE;
1942 egl_connection_t* const cnx = &gEGLImpl;
1943 if (cnx->dso && cnx->egl.eglQueryStreamKHR) {
1944 result = cnx->egl.eglQueryStreamKHR(
1945 dp->disp.dpy, stream, attribute, value);
1946 }
1947 return result;
1948}
1949
1950EGLBoolean eglQueryStreamu64KHR(EGLDisplay dpy, EGLStreamKHR stream,
1951 EGLenum attribute, EGLuint64KHR *value)
1952{
1953 clearError();
1954
1955 const egl_display_ptr dp = validate_display(dpy);
1956 if (!dp) return EGL_FALSE;
1957
1958 EGLBoolean result = EGL_FALSE;
1959 egl_connection_t* const cnx = &gEGLImpl;
1960 if (cnx->dso && cnx->egl.eglQueryStreamu64KHR) {
1961 result = cnx->egl.eglQueryStreamu64KHR(
1962 dp->disp.dpy, stream, attribute, value);
1963 }
1964 return result;
1965}
1966
1967EGLBoolean eglQueryStreamTimeKHR(EGLDisplay dpy, EGLStreamKHR stream,
1968 EGLenum attribute, EGLTimeKHR *value)
1969{
1970 clearError();
1971
1972 const egl_display_ptr dp = validate_display(dpy);
1973 if (!dp) return EGL_FALSE;
1974
1975 EGLBoolean result = EGL_FALSE;
1976 egl_connection_t* const cnx = &gEGLImpl;
1977 if (cnx->dso && cnx->egl.eglQueryStreamTimeKHR) {
1978 result = cnx->egl.eglQueryStreamTimeKHR(
1979 dp->disp.dpy, stream, attribute, value);
1980 }
1981 return result;
1982}
1983
1984EGLSurface eglCreateStreamProducerSurfaceKHR(EGLDisplay dpy, EGLConfig config,
1985 EGLStreamKHR stream, const EGLint *attrib_list)
1986{
1987 clearError();
1988
1989 egl_display_ptr dp = validate_display(dpy);
1990 if (!dp) return EGL_NO_SURFACE;
1991
1992 egl_connection_t* const cnx = &gEGLImpl;
1993 if (cnx->dso && cnx->egl.eglCreateStreamProducerSurfaceKHR) {
1994 EGLSurface surface = cnx->egl.eglCreateStreamProducerSurfaceKHR(
1995 dp->disp.dpy, config, stream, attrib_list);
1996 if (surface != EGL_NO_SURFACE) {
Courtney Goeltzenleuchterb1d70ec2018-02-08 18:09:33 -07001997 egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL, surface,
1998 EGL_GL_COLORSPACE_LINEAR_KHR, cnx);
Season Li000d88f2015-07-01 11:39:40 -07001999 return s;
2000 }
2001 }
2002 return EGL_NO_SURFACE;
2003}
2004
2005EGLBoolean eglStreamConsumerGLTextureExternalKHR(EGLDisplay dpy,
2006 EGLStreamKHR stream)
2007{
2008 clearError();
2009
2010 const egl_display_ptr dp = validate_display(dpy);
2011 if (!dp) return EGL_FALSE;
2012
2013 EGLBoolean result = EGL_FALSE;
2014 egl_connection_t* const cnx = &gEGLImpl;
2015 if (cnx->dso && cnx->egl.eglStreamConsumerGLTextureExternalKHR) {
2016 result = cnx->egl.eglStreamConsumerGLTextureExternalKHR(
2017 dp->disp.dpy, stream);
2018 }
2019 return result;
2020}
2021
2022EGLBoolean eglStreamConsumerAcquireKHR(EGLDisplay dpy,
2023 EGLStreamKHR stream)
2024{
2025 clearError();
2026
2027 const egl_display_ptr dp = validate_display(dpy);
2028 if (!dp) return EGL_FALSE;
2029
2030 EGLBoolean result = EGL_FALSE;
2031 egl_connection_t* const cnx = &gEGLImpl;
2032 if (cnx->dso && cnx->egl.eglStreamConsumerAcquireKHR) {
2033 result = cnx->egl.eglStreamConsumerAcquireKHR(
2034 dp->disp.dpy, stream);
2035 }
2036 return result;
2037}
2038
2039EGLBoolean eglStreamConsumerReleaseKHR(EGLDisplay dpy,
2040 EGLStreamKHR stream)
2041{
2042 clearError();
2043
2044 const egl_display_ptr dp = validate_display(dpy);
2045 if (!dp) return EGL_FALSE;
2046
2047 EGLBoolean result = EGL_FALSE;
2048 egl_connection_t* const cnx = &gEGLImpl;
2049 if (cnx->dso && cnx->egl.eglStreamConsumerReleaseKHR) {
2050 result = cnx->egl.eglStreamConsumerReleaseKHR(
2051 dp->disp.dpy, stream);
2052 }
2053 return result;
2054}
2055
2056EGLNativeFileDescriptorKHR eglGetStreamFileDescriptorKHR(
2057 EGLDisplay dpy, EGLStreamKHR stream)
2058{
2059 clearError();
2060
2061 const egl_display_ptr dp = validate_display(dpy);
2062 if (!dp) return EGL_NO_FILE_DESCRIPTOR_KHR;
2063
2064 EGLNativeFileDescriptorKHR result = EGL_NO_FILE_DESCRIPTOR_KHR;
2065 egl_connection_t* const cnx = &gEGLImpl;
2066 if (cnx->dso && cnx->egl.eglGetStreamFileDescriptorKHR) {
2067 result = cnx->egl.eglGetStreamFileDescriptorKHR(
2068 dp->disp.dpy, stream);
2069 }
2070 return result;
2071}
2072
2073EGLStreamKHR eglCreateStreamFromFileDescriptorKHR(
2074 EGLDisplay dpy, EGLNativeFileDescriptorKHR file_descriptor)
2075{
2076 clearError();
2077
2078 const egl_display_ptr dp = validate_display(dpy);
2079 if (!dp) return EGL_NO_STREAM_KHR;
2080
2081 EGLStreamKHR result = EGL_NO_STREAM_KHR;
2082 egl_connection_t* const cnx = &gEGLImpl;
2083 if (cnx->dso && cnx->egl.eglCreateStreamFromFileDescriptorKHR) {
2084 result = cnx->egl.eglCreateStreamFromFileDescriptorKHR(
2085 dp->disp.dpy, file_descriptor);
2086 }
2087 return result;
2088}
2089
Mathias Agopian518ec112011-05-13 16:21:08 -07002090// ----------------------------------------------------------------------------
Mathias Agopian2bb71682013-03-27 17:32:41 -07002091// EGL_EGLEXT_VERSION 15
2092// ----------------------------------------------------------------------------
2093
2094EGLint eglWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags) {
2095 clearError();
2096 const egl_display_ptr dp = validate_display(dpy);
2097 if (!dp) return EGL_FALSE;
2098 EGLint result = EGL_FALSE;
2099 egl_connection_t* const cnx = &gEGLImpl;
2100 if (cnx->dso && cnx->egl.eglWaitSyncKHR) {
2101 result = cnx->egl.eglWaitSyncKHR(dp->disp.dpy, sync, flags);
2102 }
2103 return result;
2104}
2105
2106// ----------------------------------------------------------------------------
Mathias Agopian518ec112011-05-13 16:21:08 -07002107// ANDROID extensions
2108// ----------------------------------------------------------------------------
2109
Jamie Gennis331841b2012-09-06 14:52:00 -07002110EGLint eglDupNativeFenceFDANDROID(EGLDisplay dpy, EGLSyncKHR sync)
2111{
2112 clearError();
2113
2114 const egl_display_ptr dp = validate_display(dpy);
2115 if (!dp) return EGL_NO_NATIVE_FENCE_FD_ANDROID;
2116
2117 EGLint result = EGL_NO_NATIVE_FENCE_FD_ANDROID;
2118 egl_connection_t* const cnx = &gEGLImpl;
2119 if (cnx->dso && cnx->egl.eglDupNativeFenceFDANDROID) {
2120 result = cnx->egl.eglDupNativeFenceFDANDROID(dp->disp.dpy, sync);
2121 }
2122 return result;
2123}
Jonas Yang1c3d72a2011-08-26 20:04:39 +08002124
Andy McFadden72841452013-03-01 16:25:32 -08002125EGLBoolean eglPresentationTimeANDROID(EGLDisplay dpy, EGLSurface surface,
2126 EGLnsecsANDROID time)
2127{
2128 clearError();
2129
2130 const egl_display_ptr dp = validate_display(dpy);
2131 if (!dp) {
2132 return EGL_FALSE;
2133 }
2134
2135 SurfaceRef _s(dp.get(), surface);
2136 if (!_s.get()) {
2137 setError(EGL_BAD_SURFACE, EGL_FALSE);
2138 return EGL_FALSE;
2139 }
2140
2141 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian65421432017-03-08 11:49:05 -08002142 native_window_set_buffers_timestamp(s->getNativeWindow(), time);
Andy McFadden72841452013-03-01 16:25:32 -08002143
2144 return EGL_TRUE;
2145}
2146
Craig Donner60761072017-01-27 12:30:44 -08002147EGLClientBuffer eglGetNativeClientBufferANDROID(const AHardwareBuffer *buffer) {
2148 clearError();
Jiyong Parka243e5d2017-06-21 12:26:51 +09002149 // AHardwareBuffer_to_ANativeWindowBuffer is a platform-only symbol and thus
2150 // this function cannot be implemented when this libEGL is built for
2151 // vendors.
2152#ifndef __ANDROID_VNDK__
Craig Donner60761072017-01-27 12:30:44 -08002153 if (!buffer) return setError(EGL_BAD_PARAMETER, (EGLClientBuffer)0);
Mathias Agopian61963402017-02-24 16:38:15 -08002154 return const_cast<ANativeWindowBuffer *>(AHardwareBuffer_to_ANativeWindowBuffer(buffer));
Jiyong Parka243e5d2017-06-21 12:26:51 +09002155#else
2156 return setError(EGL_BAD_PARAMETER, (EGLClientBuffer)0);
2157#endif
Craig Donner60761072017-01-27 12:30:44 -08002158}
2159
Jonas Yang1c3d72a2011-08-26 20:04:39 +08002160// ----------------------------------------------------------------------------
2161// NVIDIA extensions
2162// ----------------------------------------------------------------------------
2163EGLuint64NV eglGetSystemTimeFrequencyNV()
2164{
2165 clearError();
2166
2167 if (egl_init_drivers() == EGL_FALSE) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002168 return setError(EGL_BAD_PARAMETER, (EGLuint64NV)EGL_FALSE);
Jonas Yang1c3d72a2011-08-26 20:04:39 +08002169 }
2170
2171 EGLuint64NV ret = 0;
Mathias Agopianada798b2012-02-13 17:09:30 -08002172 egl_connection_t* const cnx = &gEGLImpl;
Jonas Yang1c3d72a2011-08-26 20:04:39 +08002173
Mathias Agopianada798b2012-02-13 17:09:30 -08002174 if (cnx->dso && cnx->egl.eglGetSystemTimeFrequencyNV) {
2175 return cnx->egl.eglGetSystemTimeFrequencyNV();
Jonas Yang1c3d72a2011-08-26 20:04:39 +08002176 }
2177
Mathias Agopian737b8962017-02-24 14:32:05 -08002178 return setErrorQuiet(EGL_BAD_DISPLAY, (EGLuint64NV)0);
Jonas Yang1c3d72a2011-08-26 20:04:39 +08002179}
2180
2181EGLuint64NV eglGetSystemTimeNV()
2182{
2183 clearError();
2184
2185 if (egl_init_drivers() == EGL_FALSE) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002186 return setError(EGL_BAD_PARAMETER, (EGLuint64NV)EGL_FALSE);
Jonas Yang1c3d72a2011-08-26 20:04:39 +08002187 }
2188
2189 EGLuint64NV ret = 0;
Mathias Agopianada798b2012-02-13 17:09:30 -08002190 egl_connection_t* const cnx = &gEGLImpl;
Jonas Yang1c3d72a2011-08-26 20:04:39 +08002191
Mathias Agopianada798b2012-02-13 17:09:30 -08002192 if (cnx->dso && cnx->egl.eglGetSystemTimeNV) {
2193 return cnx->egl.eglGetSystemTimeNV();
Jonas Yang1c3d72a2011-08-26 20:04:39 +08002194 }
2195
Mathias Agopian737b8962017-02-24 14:32:05 -08002196 return setErrorQuiet(EGL_BAD_DISPLAY, (EGLuint64NV)0);
Jonas Yang1c3d72a2011-08-26 20:04:39 +08002197}
Dan Stozaa894d082015-02-19 15:27:36 -08002198
2199// ----------------------------------------------------------------------------
2200// Partial update extension
2201// ----------------------------------------------------------------------------
2202EGLBoolean eglSetDamageRegionKHR(EGLDisplay dpy, EGLSurface surface,
2203 EGLint *rects, EGLint n_rects)
2204{
2205 clearError();
2206
2207 const egl_display_ptr dp = validate_display(dpy);
2208 if (!dp) {
2209 setError(EGL_BAD_DISPLAY, EGL_FALSE);
2210 return EGL_FALSE;
2211 }
2212
2213 SurfaceRef _s(dp.get(), surface);
2214 if (!_s.get()) {
2215 setError(EGL_BAD_SURFACE, EGL_FALSE);
2216 return EGL_FALSE;
2217 }
2218
2219 egl_surface_t const * const s = get_surface(surface);
2220 if (s->cnx->egl.eglSetDamageRegionKHR) {
2221 return s->cnx->egl.eglSetDamageRegionKHR(dp->disp.dpy, s->surface,
2222 rects, n_rects);
2223 }
2224
2225 return EGL_FALSE;
2226}
Pablo Ceballosc18be292016-05-31 14:55:42 -07002227
Brian Anderson1049d1d2016-12-16 17:25:57 -08002228EGLBoolean eglGetNextFrameIdANDROID(EGLDisplay dpy, EGLSurface surface,
2229 EGLuint64KHR *frameId) {
2230 clearError();
2231
2232 const egl_display_ptr dp = validate_display(dpy);
2233 if (!dp) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002234 return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
Brian Anderson1049d1d2016-12-16 17:25:57 -08002235 }
2236
2237 SurfaceRef _s(dp.get(), surface);
2238 if (!_s.get()) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002239 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Brian Anderson1049d1d2016-12-16 17:25:57 -08002240 }
2241
2242 egl_surface_t const * const s = get_surface(surface);
2243
Mathias Agopian65421432017-03-08 11:49:05 -08002244 if (!s->getNativeWindow()) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002245 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Brian Anderson1049d1d2016-12-16 17:25:57 -08002246 }
2247
2248 uint64_t nextFrameId = 0;
Mathias Agopian65421432017-03-08 11:49:05 -08002249 int ret = native_window_get_next_frame_id(s->getNativeWindow(), &nextFrameId);
Brian Anderson1049d1d2016-12-16 17:25:57 -08002250
Mathias Agopian65421432017-03-08 11:49:05 -08002251 if (ret != 0) {
Brian Anderson1049d1d2016-12-16 17:25:57 -08002252 // This should not happen. Return an error that is not in the spec
2253 // so it's obvious something is very wrong.
2254 ALOGE("eglGetNextFrameId: Unexpected error.");
Mathias Agopian737b8962017-02-24 14:32:05 -08002255 return setError(EGL_NOT_INITIALIZED, (EGLBoolean)EGL_FALSE);
Brian Anderson1049d1d2016-12-16 17:25:57 -08002256 }
2257
2258 *frameId = nextFrameId;
2259 return EGL_TRUE;
2260}
2261
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002262EGLBoolean eglGetCompositorTimingANDROID(EGLDisplay dpy, EGLSurface surface,
2263 EGLint numTimestamps, const EGLint *names, EGLnsecsANDROID *values)
2264{
2265 clearError();
2266
2267 const egl_display_ptr dp = validate_display(dpy);
2268 if (!dp) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002269 return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002270 }
2271
2272 SurfaceRef _s(dp.get(), surface);
2273 if (!_s.get()) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002274 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002275 }
2276
2277 egl_surface_t const * const s = get_surface(surface);
2278
Mathias Agopian65421432017-03-08 11:49:05 -08002279 if (!s->getNativeWindow()) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002280 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002281 }
2282
2283 nsecs_t* compositeDeadline = nullptr;
2284 nsecs_t* compositeInterval = nullptr;
2285 nsecs_t* compositeToPresentLatency = nullptr;
2286
2287 for (int i = 0; i < numTimestamps; i++) {
2288 switch (names[i]) {
2289 case EGL_COMPOSITE_DEADLINE_ANDROID:
2290 compositeDeadline = &values[i];
2291 break;
2292 case EGL_COMPOSITE_INTERVAL_ANDROID:
2293 compositeInterval = &values[i];
2294 break;
2295 case EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID:
2296 compositeToPresentLatency = &values[i];
2297 break;
2298 default:
Mathias Agopian737b8962017-02-24 14:32:05 -08002299 return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE);
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002300 }
2301 }
2302
Mathias Agopian65421432017-03-08 11:49:05 -08002303 int ret = native_window_get_compositor_timing(s->getNativeWindow(),
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002304 compositeDeadline, compositeInterval, compositeToPresentLatency);
2305
2306 switch (ret) {
Mathias Agopian65421432017-03-08 11:49:05 -08002307 case 0:
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002308 return EGL_TRUE;
Mathias Agopian65421432017-03-08 11:49:05 -08002309 case -ENOSYS:
Mathias Agopian737b8962017-02-24 14:32:05 -08002310 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002311 default:
2312 // This should not happen. Return an error that is not in the spec
2313 // so it's obvious something is very wrong.
2314 ALOGE("eglGetCompositorTiming: Unexpected error.");
Mathias Agopian737b8962017-02-24 14:32:05 -08002315 return setError(EGL_NOT_INITIALIZED, (EGLBoolean)EGL_FALSE);
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002316 }
2317}
2318
2319EGLBoolean eglGetCompositorTimingSupportedANDROID(
2320 EGLDisplay dpy, EGLSurface surface, EGLint name)
2321{
2322 clearError();
2323
2324 const egl_display_ptr dp = validate_display(dpy);
2325 if (!dp) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002326 return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002327 }
2328
2329 SurfaceRef _s(dp.get(), surface);
2330 if (!_s.get()) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002331 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002332 }
2333
2334 egl_surface_t const * const s = get_surface(surface);
2335
Mathias Agopian65421432017-03-08 11:49:05 -08002336 ANativeWindow* window = s->getNativeWindow();
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002337 if (!window) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002338 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002339 }
2340
2341 switch (name) {
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002342 case EGL_COMPOSITE_DEADLINE_ANDROID:
2343 case EGL_COMPOSITE_INTERVAL_ANDROID:
2344 case EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID:
2345 return EGL_TRUE;
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002346 default:
2347 return EGL_FALSE;
2348 }
2349}
2350
Pablo Ceballosc18be292016-05-31 14:55:42 -07002351EGLBoolean eglGetFrameTimestampsANDROID(EGLDisplay dpy, EGLSurface surface,
Brian Anderson1049d1d2016-12-16 17:25:57 -08002352 EGLuint64KHR frameId, EGLint numTimestamps, const EGLint *timestamps,
Pablo Ceballosc18be292016-05-31 14:55:42 -07002353 EGLnsecsANDROID *values)
2354{
2355 clearError();
2356
2357 const egl_display_ptr dp = validate_display(dpy);
2358 if (!dp) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002359 return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
Pablo Ceballosc18be292016-05-31 14:55:42 -07002360 }
2361
2362 SurfaceRef _s(dp.get(), surface);
2363 if (!_s.get()) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002364 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Pablo Ceballosc18be292016-05-31 14:55:42 -07002365 }
2366
2367 egl_surface_t const * const s = get_surface(surface);
2368
Mathias Agopian65421432017-03-08 11:49:05 -08002369 if (!s->getNativeWindow()) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002370 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Pablo Ceballosc18be292016-05-31 14:55:42 -07002371 }
2372
Brian Andersondbd0ea82016-07-22 09:38:59 -07002373 nsecs_t* requestedPresentTime = nullptr;
Pablo Ceballosc18be292016-05-31 14:55:42 -07002374 nsecs_t* acquireTime = nullptr;
Brian Andersonf7fd56a2016-09-02 10:10:04 -07002375 nsecs_t* latchTime = nullptr;
2376 nsecs_t* firstRefreshStartTime = nullptr;
Brian Andersonb04c6f02016-10-21 12:57:46 -07002377 nsecs_t* gpuCompositionDoneTime = nullptr;
Brian Andersonf7fd56a2016-09-02 10:10:04 -07002378 nsecs_t* lastRefreshStartTime = nullptr;
Brian Anderson069b3652016-07-22 10:32:47 -07002379 nsecs_t* displayPresentTime = nullptr;
Brian Andersonf7fd56a2016-09-02 10:10:04 -07002380 nsecs_t* dequeueReadyTime = nullptr;
Pablo Ceballosc18be292016-05-31 14:55:42 -07002381 nsecs_t* releaseTime = nullptr;
2382
2383 for (int i = 0; i < numTimestamps; i++) {
2384 switch (timestamps[i]) {
Brian Andersondbd0ea82016-07-22 09:38:59 -07002385 case EGL_REQUESTED_PRESENT_TIME_ANDROID:
2386 requestedPresentTime = &values[i];
Pablo Ceballosc18be292016-05-31 14:55:42 -07002387 break;
2388 case EGL_RENDERING_COMPLETE_TIME_ANDROID:
2389 acquireTime = &values[i];
2390 break;
Brian Andersonf7fd56a2016-09-02 10:10:04 -07002391 case EGL_COMPOSITION_LATCH_TIME_ANDROID:
2392 latchTime = &values[i];
Pablo Ceballosc18be292016-05-31 14:55:42 -07002393 break;
Brian Andersonf7fd56a2016-09-02 10:10:04 -07002394 case EGL_FIRST_COMPOSITION_START_TIME_ANDROID:
2395 firstRefreshStartTime = &values[i];
2396 break;
2397 case EGL_LAST_COMPOSITION_START_TIME_ANDROID:
2398 lastRefreshStartTime = &values[i];
2399 break;
Brian Andersonb04c6f02016-10-21 12:57:46 -07002400 case EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID:
2401 gpuCompositionDoneTime = &values[i];
Pablo Ceballosc18be292016-05-31 14:55:42 -07002402 break;
Brian Anderson069b3652016-07-22 10:32:47 -07002403 case EGL_DISPLAY_PRESENT_TIME_ANDROID:
2404 displayPresentTime = &values[i];
2405 break;
Brian Andersonf7fd56a2016-09-02 10:10:04 -07002406 case EGL_DEQUEUE_READY_TIME_ANDROID:
2407 dequeueReadyTime = &values[i];
2408 break;
Pablo Ceballosc18be292016-05-31 14:55:42 -07002409 case EGL_READS_DONE_TIME_ANDROID:
2410 releaseTime = &values[i];
2411 break;
2412 default:
Mathias Agopian737b8962017-02-24 14:32:05 -08002413 return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE);
Pablo Ceballosc18be292016-05-31 14:55:42 -07002414 }
2415 }
2416
Mathias Agopian65421432017-03-08 11:49:05 -08002417 int ret = native_window_get_frame_timestamps(s->getNativeWindow(), frameId,
Brian Andersonf7fd56a2016-09-02 10:10:04 -07002418 requestedPresentTime, acquireTime, latchTime, firstRefreshStartTime,
Brian Andersonb04c6f02016-10-21 12:57:46 -07002419 lastRefreshStartTime, gpuCompositionDoneTime, displayPresentTime,
Brian Anderson4e606e32017-03-16 15:34:57 -07002420 dequeueReadyTime, releaseTime);
Pablo Ceballosc18be292016-05-31 14:55:42 -07002421
Brian Anderson069b3652016-07-22 10:32:47 -07002422 switch (ret) {
Mathias Agopian65421432017-03-08 11:49:05 -08002423 case 0:
Mathias Agopian737b8962017-02-24 14:32:05 -08002424 return EGL_TRUE;
Mathias Agopian65421432017-03-08 11:49:05 -08002425 case -ENOENT:
Mathias Agopian737b8962017-02-24 14:32:05 -08002426 return setError(EGL_BAD_ACCESS, (EGLBoolean)EGL_FALSE);
Mathias Agopian65421432017-03-08 11:49:05 -08002427 case -ENOSYS:
Mathias Agopian737b8962017-02-24 14:32:05 -08002428 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian65421432017-03-08 11:49:05 -08002429 case -EINVAL:
Mathias Agopian737b8962017-02-24 14:32:05 -08002430 return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE);
2431 default:
2432 // This should not happen. Return an error that is not in the spec
2433 // so it's obvious something is very wrong.
2434 ALOGE("eglGetFrameTimestamps: Unexpected error.");
2435 return setError(EGL_NOT_INITIALIZED, (EGLBoolean)EGL_FALSE);
Pablo Ceballosc18be292016-05-31 14:55:42 -07002436 }
Pablo Ceballosc18be292016-05-31 14:55:42 -07002437}
2438
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002439EGLBoolean eglGetFrameTimestampSupportedANDROID(
2440 EGLDisplay dpy, EGLSurface surface, EGLint timestamp)
Pablo Ceballosc18be292016-05-31 14:55:42 -07002441{
2442 clearError();
2443
2444 const egl_display_ptr dp = validate_display(dpy);
2445 if (!dp) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002446 return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
Pablo Ceballosc18be292016-05-31 14:55:42 -07002447 }
2448
2449 SurfaceRef _s(dp.get(), surface);
2450 if (!_s.get()) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002451 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Brian Anderson069b3652016-07-22 10:32:47 -07002452 }
2453
2454 egl_surface_t const * const s = get_surface(surface);
2455
Mathias Agopian65421432017-03-08 11:49:05 -08002456 ANativeWindow* window = s->getNativeWindow();
Brian Anderson069b3652016-07-22 10:32:47 -07002457 if (!window) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002458 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Pablo Ceballosc18be292016-05-31 14:55:42 -07002459 }
2460
2461 switch (timestamp) {
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002462 case EGL_COMPOSITE_DEADLINE_ANDROID:
2463 case EGL_COMPOSITE_INTERVAL_ANDROID:
2464 case EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID:
Brian Andersondbd0ea82016-07-22 09:38:59 -07002465 case EGL_REQUESTED_PRESENT_TIME_ANDROID:
Pablo Ceballosc18be292016-05-31 14:55:42 -07002466 case EGL_RENDERING_COMPLETE_TIME_ANDROID:
Brian Andersonf7fd56a2016-09-02 10:10:04 -07002467 case EGL_COMPOSITION_LATCH_TIME_ANDROID:
2468 case EGL_FIRST_COMPOSITION_START_TIME_ANDROID:
2469 case EGL_LAST_COMPOSITION_START_TIME_ANDROID:
Brian Andersonb04c6f02016-10-21 12:57:46 -07002470 case EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID:
Brian Andersonf7fd56a2016-09-02 10:10:04 -07002471 case EGL_DEQUEUE_READY_TIME_ANDROID:
Pablo Ceballosc18be292016-05-31 14:55:42 -07002472 case EGL_READS_DONE_TIME_ANDROID:
2473 return EGL_TRUE;
Brian Anderson6b376712017-04-04 10:51:39 -07002474 case EGL_DISPLAY_PRESENT_TIME_ANDROID: {
2475 int value = 0;
2476 window->query(window,
2477 NATIVE_WINDOW_FRAME_TIMESTAMPS_SUPPORTS_PRESENT, &value);
2478 return value == 0 ? EGL_FALSE : EGL_TRUE;
2479 }
Pablo Ceballosc18be292016-05-31 14:55:42 -07002480 default:
2481 return EGL_FALSE;
2482 }
2483}