blob: ef6e9d0f9c6d6419bcf6727518c17a2b726183c2 [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 {
Mike Stroyan02ba5c72017-05-08 10:47:24 -06001115
Mike Stroyan47e741b2017-06-01 13:56:18 -06001116 if (cur_c != NULL) {
1117 // Force return to current context for drivers that cannot handle errors
1118 EGLBoolean restore_result = EGL_FALSE;
1119 // get a reference to the old current objects
1120 ContextRef _c2(dp.get(), cur_c);
1121 SurfaceRef _d2(dp.get(), cur_c->draw);
1122 SurfaceRef _r2(dp.get(), cur_c->read);
Mike Stroyan02ba5c72017-05-08 10:47:24 -06001123
Mike Stroyan02ba5c72017-05-08 10:47:24 -06001124 c = cur_c;
1125 impl_ctx = c->context;
1126 impl_draw = EGL_NO_SURFACE;
1127 if (cur_c->draw != EGL_NO_SURFACE) {
1128 d = get_surface(cur_c->draw);
1129 impl_draw = d->surface;
1130 }
1131 impl_read = EGL_NO_SURFACE;
1132 if (cur_c->read != EGL_NO_SURFACE) {
1133 r = get_surface(cur_c->read);
1134 impl_read = r->surface;
1135 }
1136 restore_result = dp->makeCurrent(c, cur_c,
1137 cur_c->draw, cur_c->read, cur_c->context,
1138 impl_draw, impl_read, impl_ctx);
Mike Stroyan47e741b2017-06-01 13:56:18 -06001139 if (restore_result == EGL_TRUE) {
1140 _c2.acquire();
1141 _r2.acquire();
1142 _d2.acquire();
1143 } else {
1144 ALOGE("Could not restore original EGL context");
1145 }
Mike Stroyan02ba5c72017-05-08 10:47:24 -06001146 }
Steve Blocke6f43dd2012-01-06 19:20:56 +00001147 // this will ALOGE the error
Mathias Agopian63108c32013-09-06 13:36:49 -07001148 egl_connection_t* const cnx = &gEGLImpl;
Mathias Agopian737b8962017-02-24 14:32:05 -08001149 result = setError(cnx->egl.eglGetError(), (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001150 }
1151 return result;
1152}
1153
1154
1155EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx,
1156 EGLint attribute, EGLint *value)
1157{
1158 clearError();
1159
Jesse Hallb29e5e82012-04-04 16:53:42 -07001160 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001161 if (!dp) return EGL_FALSE;
1162
Jesse Hallb29e5e82012-04-04 16:53:42 -07001163 ContextRef _c(dp.get(), ctx);
Mathias Agopian737b8962017-02-24 14:32:05 -08001164 if (!_c.get()) return setError(EGL_BAD_CONTEXT, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001165
Mathias Agopian518ec112011-05-13 16:21:08 -07001166 egl_context_t * const c = get_context(ctx);
Mathias Agopian7773c432012-02-13 20:06:08 -08001167 return c->cnx->egl.eglQueryContext(
1168 dp->disp.dpy, c->context, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -07001169
Mathias Agopian518ec112011-05-13 16:21:08 -07001170}
1171
1172EGLContext eglGetCurrentContext(void)
1173{
1174 // could be called before eglInitialize(), but we wouldn't have a context
1175 // then, and this function would correctly return EGL_NO_CONTEXT.
1176
1177 clearError();
1178
1179 EGLContext ctx = getContext();
1180 return ctx;
1181}
1182
1183EGLSurface eglGetCurrentSurface(EGLint readdraw)
1184{
1185 // could be called before eglInitialize(), but we wouldn't have a context
1186 // then, and this function would correctly return EGL_NO_SURFACE.
1187
1188 clearError();
1189
1190 EGLContext ctx = getContext();
1191 if (ctx) {
1192 egl_context_t const * const c = get_context(ctx);
1193 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
1194 switch (readdraw) {
1195 case EGL_READ: return c->read;
Jesse Hall47743382013-02-08 11:13:46 -08001196 case EGL_DRAW: return c->draw;
Mathias Agopian518ec112011-05-13 16:21:08 -07001197 default: return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
1198 }
1199 }
1200 return EGL_NO_SURFACE;
1201}
1202
1203EGLDisplay eglGetCurrentDisplay(void)
1204{
1205 // could be called before eglInitialize(), but we wouldn't have a context
1206 // then, and this function would correctly return EGL_NO_DISPLAY.
1207
1208 clearError();
1209
1210 EGLContext ctx = getContext();
1211 if (ctx) {
1212 egl_context_t const * const c = get_context(ctx);
1213 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
1214 return c->dpy;
1215 }
1216 return EGL_NO_DISPLAY;
1217}
1218
1219EGLBoolean eglWaitGL(void)
1220{
Mathias Agopian518ec112011-05-13 16:21:08 -07001221 clearError();
1222
Mathias Agopianada798b2012-02-13 17:09:30 -08001223 egl_connection_t* const cnx = &gEGLImpl;
1224 if (!cnx->dso)
Mathias Agopian737b8962017-02-24 14:32:05 -08001225 return setError(EGL_BAD_CONTEXT, (EGLBoolean)EGL_FALSE);
Mathias Agopianada798b2012-02-13 17:09:30 -08001226
1227 return cnx->egl.eglWaitGL();
Mathias Agopian518ec112011-05-13 16:21:08 -07001228}
1229
1230EGLBoolean eglWaitNative(EGLint engine)
1231{
Mathias Agopian518ec112011-05-13 16:21:08 -07001232 clearError();
1233
Mathias Agopianada798b2012-02-13 17:09:30 -08001234 egl_connection_t* const cnx = &gEGLImpl;
1235 if (!cnx->dso)
Mathias Agopian737b8962017-02-24 14:32:05 -08001236 return setError(EGL_BAD_CONTEXT, (EGLBoolean)EGL_FALSE);
Mathias Agopianada798b2012-02-13 17:09:30 -08001237
1238 return cnx->egl.eglWaitNative(engine);
Mathias Agopian518ec112011-05-13 16:21:08 -07001239}
1240
1241EGLint eglGetError(void)
1242{
Mathias Agopianada798b2012-02-13 17:09:30 -08001243 EGLint err = EGL_SUCCESS;
1244 egl_connection_t* const cnx = &gEGLImpl;
1245 if (cnx->dso) {
1246 err = cnx->egl.eglGetError();
Mathias Agopian518ec112011-05-13 16:21:08 -07001247 }
Mathias Agopianada798b2012-02-13 17:09:30 -08001248 if (err == EGL_SUCCESS) {
1249 err = egl_tls_t::getError();
1250 }
1251 return err;
Mathias Agopian518ec112011-05-13 16:21:08 -07001252}
1253
Michael Chockc0ec5e22014-01-27 08:14:33 -08001254static __eglMustCastToProperFunctionPointerType findBuiltinWrapper(
Jesse Hallc07b5202013-07-04 12:08:16 -07001255 const char* procname) {
1256 const egl_connection_t* cnx = &gEGLImpl;
1257 void* proc = NULL;
1258
Michael Chockc0ec5e22014-01-27 08:14:33 -08001259 proc = dlsym(cnx->libEgl, procname);
1260 if (proc) return (__eglMustCastToProperFunctionPointerType)proc;
1261
Jesse Hallc07b5202013-07-04 12:08:16 -07001262 proc = dlsym(cnx->libGles2, procname);
1263 if (proc) return (__eglMustCastToProperFunctionPointerType)proc;
1264
1265 proc = dlsym(cnx->libGles1, procname);
1266 if (proc) return (__eglMustCastToProperFunctionPointerType)proc;
1267
1268 return NULL;
1269}
1270
Mathias Agopian518ec112011-05-13 16:21:08 -07001271__eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
1272{
1273 // eglGetProcAddress() could be the very first function called
1274 // in which case we must make sure we've initialized ourselves, this
1275 // happens the first time egl_get_display() is called.
1276
1277 clearError();
1278
1279 if (egl_init_drivers() == EGL_FALSE) {
1280 setError(EGL_BAD_PARAMETER, NULL);
1281 return NULL;
1282 }
1283
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -07001284 if (FILTER_EXTENSIONS(procname)) {
Jamie Gennisaca51c02011-11-03 17:42:43 -07001285 return NULL;
1286 }
1287
Mathias Agopian518ec112011-05-13 16:21:08 -07001288 __eglMustCastToProperFunctionPointerType addr;
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -07001289 addr = findProcAddress(procname, sExtensionMap, NELEM(sExtensionMap));
Mathias Agopian518ec112011-05-13 16:21:08 -07001290 if (addr) return addr;
1291
Michael Chockc0ec5e22014-01-27 08:14:33 -08001292 addr = findBuiltinWrapper(procname);
Jesse Hallc07b5202013-07-04 12:08:16 -07001293 if (addr) return addr;
Jamie Gennisaca51c02011-11-03 17:42:43 -07001294
Mathias Agopian518ec112011-05-13 16:21:08 -07001295 // this protects accesses to sGLExtentionMap and sGLExtentionSlot
1296 pthread_mutex_lock(&sExtensionMapMutex);
1297
1298 /*
1299 * Since eglGetProcAddress() is not associated to anything, it needs
1300 * to return a function pointer that "works" regardless of what
1301 * the current context is.
1302 *
1303 * For this reason, we return a "forwarder", a small stub that takes
1304 * care of calling the function associated with the context
1305 * currently bound.
1306 *
1307 * We first look for extensions we've already resolved, if we're seeing
1308 * this extension for the first time, we go through all our
1309 * implementations and call eglGetProcAddress() and record the
1310 * result in the appropriate implementation hooks and return the
1311 * address of the forwarder corresponding to that hook set.
1312 *
1313 */
1314
Mathias Agopian65421432017-03-08 11:49:05 -08001315 const std::string name(procname);
1316
1317 auto& extentionMap = sGLExtentionMap;
1318 auto pos = extentionMap.find(name);
1319 addr = (pos != extentionMap.end()) ? pos->second : nullptr;
Mathias Agopian518ec112011-05-13 16:21:08 -07001320 const int slot = sGLExtentionSlot;
1321
Steve Blocke6f43dd2012-01-06 19:20:56 +00001322 ALOGE_IF(slot >= MAX_NUMBER_OF_GL_EXTENSIONS,
Mathias Agopian518ec112011-05-13 16:21:08 -07001323 "no more slots for eglGetProcAddress(\"%s\")",
1324 procname);
1325
1326 if (!addr && (slot < MAX_NUMBER_OF_GL_EXTENSIONS)) {
1327 bool found = false;
Mathias Agopianada798b2012-02-13 17:09:30 -08001328
1329 egl_connection_t* const cnx = &gEGLImpl;
1330 if (cnx->dso && cnx->egl.eglGetProcAddress) {
Mathias Agopianada798b2012-02-13 17:09:30 -08001331 // Extensions are independent of the bound context
luliuhui69d10072012-08-30 11:15:36 +08001332 addr =
Mathias Agopian7773c432012-02-13 20:06:08 -08001333 cnx->hooks[egl_connection_t::GLESv1_INDEX]->ext.extensions[slot] =
1334 cnx->hooks[egl_connection_t::GLESv2_INDEX]->ext.extensions[slot] =
Mathias Agopianada798b2012-02-13 17:09:30 -08001335 cnx->egl.eglGetProcAddress(procname);
luliuhui69d10072012-08-30 11:15:36 +08001336 if (addr) found = true;
Mathias Agopian518ec112011-05-13 16:21:08 -07001337 }
Mathias Agopianada798b2012-02-13 17:09:30 -08001338
Mathias Agopian518ec112011-05-13 16:21:08 -07001339 if (found) {
1340 addr = gExtensionForwarders[slot];
Mathias Agopian65421432017-03-08 11:49:05 -08001341 extentionMap[name] = addr;
Mathias Agopian518ec112011-05-13 16:21:08 -07001342 sGLExtentionSlot++;
1343 }
1344 }
1345
1346 pthread_mutex_unlock(&sExtensionMapMutex);
1347 return addr;
1348}
1349
Mathias Agopian65421432017-03-08 11:49:05 -08001350class FrameCompletionThread {
Jamie Gennis28ef8d72012-04-05 20:34:54 -07001351public:
1352
1353 static void queueSync(EGLSyncKHR sync) {
Mathias Agopian65421432017-03-08 11:49:05 -08001354 static FrameCompletionThread thread;
1355
1356 char name[64];
1357
1358 std::lock_guard<std::mutex> lock(thread.mMutex);
1359 snprintf(name, sizeof(name), "kicked off frame %u", (unsigned int)thread.mFramesQueued);
1360 ATRACE_NAME(name);
1361
1362 thread.mQueue.push_back(sync);
1363 thread.mCondition.notify_one();
1364 thread.mFramesQueued++;
1365 ATRACE_INT("GPU Frames Outstanding", int32_t(thread.mQueue.size()));
Jamie Gennis28ef8d72012-04-05 20:34:54 -07001366 }
1367
1368private:
Jamie Gennis28ef8d72012-04-05 20:34:54 -07001369
Mathias Agopian65421432017-03-08 11:49:05 -08001370 FrameCompletionThread() : mFramesQueued(0), mFramesCompleted(0) {
1371 std::thread thread(&FrameCompletionThread::loop, this);
1372 thread.detach();
1373 }
1374
1375#pragma clang diagnostic push
1376#pragma clang diagnostic ignored "-Wmissing-noreturn"
1377 void loop() {
1378 while (true) {
1379 threadLoop();
1380 }
1381 }
1382#pragma clang diagnostic pop
1383
1384 void threadLoop() {
Jamie Gennis28ef8d72012-04-05 20:34:54 -07001385 EGLSyncKHR sync;
1386 uint32_t frameNum;
1387 {
Mathias Agopian65421432017-03-08 11:49:05 -08001388 std::unique_lock<std::mutex> lock(mMutex);
1389 while (mQueue.empty()) {
1390 mCondition.wait(lock);
Jamie Gennis28ef8d72012-04-05 20:34:54 -07001391 }
1392 sync = mQueue[0];
1393 frameNum = mFramesCompleted;
1394 }
1395 EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
1396 {
Mathias Agopian65421432017-03-08 11:49:05 -08001397 char name[64];
1398 snprintf(name, sizeof(name), "waiting for frame %u", (unsigned int)frameNum);
1399 ATRACE_NAME(name);
1400
Jamie Gennis28ef8d72012-04-05 20:34:54 -07001401 EGLint result = eglClientWaitSyncKHR(dpy, sync, 0, EGL_FOREVER_KHR);
1402 if (result == EGL_FALSE) {
1403 ALOGE("FrameCompletion: error waiting for fence: %#x", eglGetError());
1404 } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
1405 ALOGE("FrameCompletion: timeout waiting for fence");
1406 }
1407 eglDestroySyncKHR(dpy, sync);
1408 }
1409 {
Mathias Agopian65421432017-03-08 11:49:05 -08001410 std::lock_guard<std::mutex> lock(mMutex);
1411 mQueue.pop_front();
Jamie Gennis28ef8d72012-04-05 20:34:54 -07001412 mFramesCompleted++;
Mathias Agopian737b8962017-02-24 14:32:05 -08001413 ATRACE_INT("GPU Frames Outstanding", int32_t(mQueue.size()));
Jamie Gennis28ef8d72012-04-05 20:34:54 -07001414 }
Jamie Gennis28ef8d72012-04-05 20:34:54 -07001415 }
1416
1417 uint32_t mFramesQueued;
1418 uint32_t mFramesCompleted;
Mathias Agopian65421432017-03-08 11:49:05 -08001419 std::deque<EGLSyncKHR> mQueue;
1420 std::condition_variable mCondition;
1421 std::mutex mMutex;
Jamie Gennis28ef8d72012-04-05 20:34:54 -07001422};
1423
Dan Stozaa894d082015-02-19 15:27:36 -08001424EGLBoolean eglSwapBuffersWithDamageKHR(EGLDisplay dpy, EGLSurface draw,
1425 EGLint *rects, EGLint n_rects)
Mathias Agopian518ec112011-05-13 16:21:08 -07001426{
Jamie Gennis1c8e95c2012-02-23 19:27:23 -08001427 ATRACE_CALL();
Mathias Agopian518ec112011-05-13 16:21:08 -07001428 clearError();
1429
Jesse Hallb29e5e82012-04-04 16:53:42 -07001430 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001431 if (!dp) return EGL_FALSE;
1432
Jesse Hallb29e5e82012-04-04 16:53:42 -07001433 SurfaceRef _s(dp.get(), draw);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001434 if (!_s.get())
Mathias Agopian737b8962017-02-24 14:32:05 -08001435 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001436
Courtney Goeltzenleuchter936799c2018-03-02 16:47:08 -07001437 egl_surface_t* const s = get_surface(draw);
Mathias Agopian7db993a2012-03-25 00:49:46 -07001438
Mathias Agopianed6d08b2013-04-16 16:39:46 -07001439 if (CC_UNLIKELY(dp->traceGpuCompletion)) {
1440 EGLSyncKHR sync = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, NULL);
1441 if (sync != EGL_NO_SYNC_KHR) {
1442 FrameCompletionThread::queueSync(sync);
1443 }
1444 }
1445
Mathias Agopian7db993a2012-03-25 00:49:46 -07001446 if (CC_UNLIKELY(dp->finishOnSwap)) {
1447 uint32_t pixel;
1448 egl_context_t * const c = get_context( egl_tls_t::getContext() );
1449 if (c) {
1450 // glReadPixels() ensures that the frame is complete
1451 s->cnx->hooks[c->version]->gl.glReadPixels(0,0,1,1,
1452 GL_RGBA,GL_UNSIGNED_BYTE,&pixel);
1453 }
1454 }
1455
Courtney Goeltzenleuchter936799c2018-03-02 16:47:08 -07001456 if (!sendSurfaceMetadata(s)) {
1457 native_window_api_disconnect(s->getNativeWindow(), NATIVE_WINDOW_API_EGL);
1458 return setError(EGL_BAD_NATIVE_WINDOW, (EGLBoolean)EGL_FALSE);
1459 }
1460
Dan Stozaa894d082015-02-19 15:27:36 -08001461 if (n_rects == 0) {
1462 return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface);
1463 }
1464
Mathias Agopian65421432017-03-08 11:49:05 -08001465 std::vector<android_native_rect_t> androidRects((size_t)n_rects);
Dan Stozaa894d082015-02-19 15:27:36 -08001466 for (int r = 0; r < n_rects; ++r) {
1467 int offset = r * 4;
1468 int x = rects[offset];
1469 int y = rects[offset + 1];
1470 int width = rects[offset + 2];
1471 int height = rects[offset + 3];
1472 android_native_rect_t androidRect;
1473 androidRect.left = x;
1474 androidRect.top = y + height;
1475 androidRect.right = x + width;
1476 androidRect.bottom = y;
1477 androidRects.push_back(androidRect);
1478 }
Mathias Agopian65421432017-03-08 11:49:05 -08001479 native_window_set_surface_damage(s->getNativeWindow(), androidRects.data(), androidRects.size());
Dan Stozaa894d082015-02-19 15:27:36 -08001480
1481 if (s->cnx->egl.eglSwapBuffersWithDamageKHR) {
1482 return s->cnx->egl.eglSwapBuffersWithDamageKHR(dp->disp.dpy, s->surface,
1483 rects, n_rects);
1484 } else {
1485 return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface);
1486 }
1487}
1488
1489EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
1490{
1491 return eglSwapBuffersWithDamageKHR(dpy, surface, NULL, 0);
Mathias Agopian518ec112011-05-13 16:21:08 -07001492}
1493
1494EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface,
1495 NativePixmapType target)
1496{
1497 clearError();
1498
Jesse Hallb29e5e82012-04-04 16:53:42 -07001499 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001500 if (!dp) return EGL_FALSE;
1501
Jesse Hallb29e5e82012-04-04 16:53:42 -07001502 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001503 if (!_s.get())
Mathias Agopian737b8962017-02-24 14:32:05 -08001504 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001505
Mathias Agopian518ec112011-05-13 16:21:08 -07001506 egl_surface_t const * const s = get_surface(surface);
Mathias Agopianada798b2012-02-13 17:09:30 -08001507 return s->cnx->egl.eglCopyBuffers(dp->disp.dpy, s->surface, target);
Mathias Agopian518ec112011-05-13 16:21:08 -07001508}
1509
1510const char* eglQueryString(EGLDisplay dpy, EGLint name)
1511{
1512 clearError();
1513
Chia-I Wue57d1352016-08-15 16:10:02 +08001514 // Generate an error quietly when client extensions (as defined by
1515 // EGL_EXT_client_extensions) are queried. We do not want to rely on
1516 // validate_display to generate the error as validate_display would log
1517 // the error, which can be misleading.
1518 //
1519 // If we want to support EGL_EXT_client_extensions later, we can return
1520 // the client extension string here instead.
1521 if (dpy == EGL_NO_DISPLAY && name == EGL_EXTENSIONS)
Mathias Agopian737b8962017-02-24 14:32:05 -08001522 return setErrorQuiet(EGL_BAD_DISPLAY, (const char*)0);
Chia-I Wue57d1352016-08-15 16:10:02 +08001523
Jesse Hallb29e5e82012-04-04 16:53:42 -07001524 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001525 if (!dp) return (const char *) NULL;
1526
1527 switch (name) {
1528 case EGL_VENDOR:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001529 return dp->getVendorString();
Mathias Agopian518ec112011-05-13 16:21:08 -07001530 case EGL_VERSION:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001531 return dp->getVersionString();
Mathias Agopian518ec112011-05-13 16:21:08 -07001532 case EGL_EXTENSIONS:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001533 return dp->getExtensionString();
Mathias Agopian518ec112011-05-13 16:21:08 -07001534 case EGL_CLIENT_APIS:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001535 return dp->getClientApiString();
Mathias Agopian737b8962017-02-24 14:32:05 -08001536 default:
1537 break;
Mathias Agopian518ec112011-05-13 16:21:08 -07001538 }
1539 return setError(EGL_BAD_PARAMETER, (const char *)0);
1540}
1541
Jiyong Park00b15b82017-08-10 20:30:56 +09001542extern "C" EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name)
Mathias Agopianca088332013-03-28 17:44:13 -07001543{
1544 clearError();
1545
1546 const egl_display_ptr dp = validate_display(dpy);
1547 if (!dp) return (const char *) NULL;
1548
1549 switch (name) {
1550 case EGL_VENDOR:
1551 return dp->disp.queryString.vendor;
1552 case EGL_VERSION:
1553 return dp->disp.queryString.version;
1554 case EGL_EXTENSIONS:
1555 return dp->disp.queryString.extensions;
1556 case EGL_CLIENT_APIS:
1557 return dp->disp.queryString.clientApi;
Mathias Agopian737b8962017-02-24 14:32:05 -08001558 default:
1559 break;
Mathias Agopianca088332013-03-28 17:44:13 -07001560 }
1561 return setError(EGL_BAD_PARAMETER, (const char *)0);
1562}
Mathias Agopian518ec112011-05-13 16:21:08 -07001563
1564// ----------------------------------------------------------------------------
1565// EGL 1.1
1566// ----------------------------------------------------------------------------
1567
1568EGLBoolean eglSurfaceAttrib(
1569 EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
1570{
1571 clearError();
1572
Jesse Hallb29e5e82012-04-04 16:53:42 -07001573 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001574 if (!dp) return EGL_FALSE;
1575
Jesse Hallb29e5e82012-04-04 16:53:42 -07001576 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001577 if (!_s.get())
Mathias Agopian737b8962017-02-24 14:32:05 -08001578 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001579
Pablo Ceballosc18be292016-05-31 14:55:42 -07001580 egl_surface_t * const s = get_surface(surface);
Pablo Ceballosccdfd602015-10-07 15:05:45 -07001581
Pablo Ceballos02b05da2016-02-02 17:53:18 -08001582 if (attribute == EGL_FRONT_BUFFER_AUTO_REFRESH_ANDROID) {
Mathias Agopian65421432017-03-08 11:49:05 -08001583 if (!s->getNativeWindow()) {
Brian Anderson069b3652016-07-22 10:32:47 -07001584 setError(EGL_BAD_SURFACE, EGL_FALSE);
1585 }
Mathias Agopian65421432017-03-08 11:49:05 -08001586 int err = native_window_set_auto_refresh(s->getNativeWindow(), value != 0);
1587 return (err == 0) ? EGL_TRUE : setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Pablo Ceballosccdfd602015-10-07 15:05:45 -07001588 }
1589
Pablo Ceballosc18be292016-05-31 14:55:42 -07001590 if (attribute == EGL_TIMESTAMPS_ANDROID) {
Mathias Agopian65421432017-03-08 11:49:05 -08001591 if (!s->getNativeWindow()) {
Mathias Agopian737b8962017-02-24 14:32:05 -08001592 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Brian Anderson069b3652016-07-22 10:32:47 -07001593 }
Mathias Agopian65421432017-03-08 11:49:05 -08001594 int err = native_window_enable_frame_timestamps(s->getNativeWindow(), value != 0);
1595 return (err == 0) ? EGL_TRUE : setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Pablo Ceballosc18be292016-05-31 14:55:42 -07001596 }
1597
Courtney Goeltzenleuchter786ab882018-01-26 13:37:33 -08001598 if (s->setSmpte2086Attribute(attribute, value)) {
1599 return EGL_TRUE;
1600 } else if (s->setCta8613Attribute(attribute, value)) {
1601 return EGL_TRUE;
1602 } else if (s->cnx->egl.eglSurfaceAttrib) {
Mathias Agopian518ec112011-05-13 16:21:08 -07001603 return s->cnx->egl.eglSurfaceAttrib(
Mathias Agopianada798b2012-02-13 17:09:30 -08001604 dp->disp.dpy, s->surface, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -07001605 }
Mathias Agopian737b8962017-02-24 14:32:05 -08001606 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001607}
1608
1609EGLBoolean eglBindTexImage(
1610 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1611{
1612 clearError();
1613
Jesse Hallb29e5e82012-04-04 16:53:42 -07001614 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001615 if (!dp) return EGL_FALSE;
1616
Jesse Hallb29e5e82012-04-04 16:53:42 -07001617 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001618 if (!_s.get())
Mathias Agopian737b8962017-02-24 14:32:05 -08001619 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001620
Mathias Agopian518ec112011-05-13 16:21:08 -07001621 egl_surface_t const * const s = get_surface(surface);
1622 if (s->cnx->egl.eglBindTexImage) {
1623 return s->cnx->egl.eglBindTexImage(
Mathias Agopianada798b2012-02-13 17:09:30 -08001624 dp->disp.dpy, s->surface, buffer);
Mathias Agopian518ec112011-05-13 16:21:08 -07001625 }
Mathias Agopian737b8962017-02-24 14:32:05 -08001626 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001627}
1628
1629EGLBoolean eglReleaseTexImage(
1630 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1631{
1632 clearError();
1633
Jesse Hallb29e5e82012-04-04 16:53:42 -07001634 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001635 if (!dp) return EGL_FALSE;
1636
Jesse Hallb29e5e82012-04-04 16:53:42 -07001637 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001638 if (!_s.get())
Mathias Agopian737b8962017-02-24 14:32:05 -08001639 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001640
Mathias Agopian518ec112011-05-13 16:21:08 -07001641 egl_surface_t const * const s = get_surface(surface);
1642 if (s->cnx->egl.eglReleaseTexImage) {
1643 return s->cnx->egl.eglReleaseTexImage(
Mathias Agopianada798b2012-02-13 17:09:30 -08001644 dp->disp.dpy, s->surface, buffer);
Mathias Agopian518ec112011-05-13 16:21:08 -07001645 }
Mathias Agopian737b8962017-02-24 14:32:05 -08001646 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001647}
1648
1649EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
1650{
1651 clearError();
1652
Jesse Hallb29e5e82012-04-04 16:53:42 -07001653 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001654 if (!dp) return EGL_FALSE;
1655
1656 EGLBoolean res = EGL_TRUE;
Mathias Agopianada798b2012-02-13 17:09:30 -08001657 egl_connection_t* const cnx = &gEGLImpl;
1658 if (cnx->dso && cnx->egl.eglSwapInterval) {
1659 res = cnx->egl.eglSwapInterval(dp->disp.dpy, interval);
Mathias Agopian518ec112011-05-13 16:21:08 -07001660 }
Mathias Agopianada798b2012-02-13 17:09:30 -08001661
Mathias Agopian518ec112011-05-13 16:21:08 -07001662 return res;
1663}
1664
1665
1666// ----------------------------------------------------------------------------
1667// EGL 1.2
1668// ----------------------------------------------------------------------------
1669
1670EGLBoolean eglWaitClient(void)
1671{
1672 clearError();
1673
Mathias Agopianada798b2012-02-13 17:09:30 -08001674 egl_connection_t* const cnx = &gEGLImpl;
1675 if (!cnx->dso)
Mathias Agopian737b8962017-02-24 14:32:05 -08001676 return setError(EGL_BAD_CONTEXT, (EGLBoolean)EGL_FALSE);
Mathias Agopianada798b2012-02-13 17:09:30 -08001677
1678 EGLBoolean res;
1679 if (cnx->egl.eglWaitClient) {
1680 res = cnx->egl.eglWaitClient();
1681 } else {
1682 res = cnx->egl.eglWaitGL();
Mathias Agopian518ec112011-05-13 16:21:08 -07001683 }
1684 return res;
1685}
1686
1687EGLBoolean eglBindAPI(EGLenum api)
1688{
1689 clearError();
1690
1691 if (egl_init_drivers() == EGL_FALSE) {
Mathias Agopian737b8962017-02-24 14:32:05 -08001692 return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001693 }
1694
1695 // bind this API on all EGLs
1696 EGLBoolean res = EGL_TRUE;
Mathias Agopianada798b2012-02-13 17:09:30 -08001697 egl_connection_t* const cnx = &gEGLImpl;
1698 if (cnx->dso && cnx->egl.eglBindAPI) {
1699 res = cnx->egl.eglBindAPI(api);
Mathias Agopian518ec112011-05-13 16:21:08 -07001700 }
1701 return res;
1702}
1703
1704EGLenum eglQueryAPI(void)
1705{
1706 clearError();
1707
1708 if (egl_init_drivers() == EGL_FALSE) {
Mathias Agopian737b8962017-02-24 14:32:05 -08001709 return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001710 }
1711
Mathias Agopianada798b2012-02-13 17:09:30 -08001712 egl_connection_t* const cnx = &gEGLImpl;
1713 if (cnx->dso && cnx->egl.eglQueryAPI) {
1714 return cnx->egl.eglQueryAPI();
Mathias Agopian518ec112011-05-13 16:21:08 -07001715 }
Mathias Agopianada798b2012-02-13 17:09:30 -08001716
Mathias Agopian518ec112011-05-13 16:21:08 -07001717 // or, it can only be OpenGL ES
1718 return EGL_OPENGL_ES_API;
1719}
1720
1721EGLBoolean eglReleaseThread(void)
1722{
1723 clearError();
1724
Mathias Agopianada798b2012-02-13 17:09:30 -08001725 egl_connection_t* const cnx = &gEGLImpl;
1726 if (cnx->dso && cnx->egl.eglReleaseThread) {
1727 cnx->egl.eglReleaseThread();
Mathias Agopian518ec112011-05-13 16:21:08 -07001728 }
Sai Kiran Korwar3ac517a2014-01-31 21:15:07 +05301729
1730 // If there is context bound to the thread, release it
1731 egl_display_t::loseCurrent(get_context(getContext()));
1732
Mathias Agopian518ec112011-05-13 16:21:08 -07001733 egl_tls_t::clearTLS();
Mathias Agopian518ec112011-05-13 16:21:08 -07001734 return EGL_TRUE;
1735}
1736
1737EGLSurface eglCreatePbufferFromClientBuffer(
1738 EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer,
1739 EGLConfig config, const EGLint *attrib_list)
1740{
1741 clearError();
1742
Jesse Hallb29e5e82012-04-04 16:53:42 -07001743 egl_connection_t* cnx = NULL;
1744 const egl_display_ptr dp = validate_display_connection(dpy, cnx);
1745 if (!dp) return EGL_FALSE;
Mathias Agopian518ec112011-05-13 16:21:08 -07001746 if (cnx->egl.eglCreatePbufferFromClientBuffer) {
1747 return cnx->egl.eglCreatePbufferFromClientBuffer(
Mathias Agopian7773c432012-02-13 20:06:08 -08001748 dp->disp.dpy, buftype, buffer, config, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001749 }
1750 return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE);
1751}
1752
1753// ----------------------------------------------------------------------------
1754// EGL_EGLEXT_VERSION 3
1755// ----------------------------------------------------------------------------
1756
1757EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface,
1758 const EGLint *attrib_list)
1759{
1760 clearError();
1761
Jesse Hallb29e5e82012-04-04 16:53:42 -07001762 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001763 if (!dp) return EGL_FALSE;
1764
Jesse Hallb29e5e82012-04-04 16:53:42 -07001765 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001766 if (!_s.get())
Mathias Agopian737b8962017-02-24 14:32:05 -08001767 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001768
1769 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian518ec112011-05-13 16:21:08 -07001770 if (s->cnx->egl.eglLockSurfaceKHR) {
1771 return s->cnx->egl.eglLockSurfaceKHR(
Mathias Agopianada798b2012-02-13 17:09:30 -08001772 dp->disp.dpy, s->surface, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001773 }
Mathias Agopian737b8962017-02-24 14:32:05 -08001774 return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001775}
1776
1777EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface)
1778{
1779 clearError();
1780
Jesse Hallb29e5e82012-04-04 16:53:42 -07001781 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001782 if (!dp) return EGL_FALSE;
1783
Jesse Hallb29e5e82012-04-04 16:53:42 -07001784 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001785 if (!_s.get())
Mathias Agopian737b8962017-02-24 14:32:05 -08001786 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001787
1788 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian518ec112011-05-13 16:21:08 -07001789 if (s->cnx->egl.eglUnlockSurfaceKHR) {
Mathias Agopianada798b2012-02-13 17:09:30 -08001790 return s->cnx->egl.eglUnlockSurfaceKHR(dp->disp.dpy, s->surface);
Mathias Agopian518ec112011-05-13 16:21:08 -07001791 }
Mathias Agopian737b8962017-02-24 14:32:05 -08001792 return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001793}
1794
1795EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
1796 EGLClientBuffer buffer, const EGLint *attrib_list)
1797{
1798 clearError();
1799
Jesse Hallb29e5e82012-04-04 16:53:42 -07001800 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001801 if (!dp) return EGL_NO_IMAGE_KHR;
1802
Jesse Hallb29e5e82012-04-04 16:53:42 -07001803 ContextRef _c(dp.get(), ctx);
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001804 egl_context_t * const c = _c.get();
Mathias Agopian518ec112011-05-13 16:21:08 -07001805
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001806 EGLImageKHR result = EGL_NO_IMAGE_KHR;
1807 egl_connection_t* const cnx = &gEGLImpl;
1808 if (cnx->dso && cnx->egl.eglCreateImageKHR) {
1809 result = cnx->egl.eglCreateImageKHR(
1810 dp->disp.dpy,
1811 c ? c->context : EGL_NO_CONTEXT,
1812 target, buffer, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001813 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001814 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001815}
1816
1817EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
1818{
1819 clearError();
1820
Jesse Hallb29e5e82012-04-04 16:53:42 -07001821 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001822 if (!dp) return EGL_FALSE;
1823
Steven Holte646a5c52012-06-04 20:02:11 -07001824 EGLBoolean result = EGL_FALSE;
Mathias Agopianada798b2012-02-13 17:09:30 -08001825 egl_connection_t* const cnx = &gEGLImpl;
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001826 if (cnx->dso && cnx->egl.eglDestroyImageKHR) {
Steven Holte646a5c52012-06-04 20:02:11 -07001827 result = cnx->egl.eglDestroyImageKHR(dp->disp.dpy, img);
Mathias Agopian518ec112011-05-13 16:21:08 -07001828 }
Steven Holte646a5c52012-06-04 20:02:11 -07001829 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001830}
1831
1832// ----------------------------------------------------------------------------
1833// EGL_EGLEXT_VERSION 5
1834// ----------------------------------------------------------------------------
1835
1836
1837EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
1838{
1839 clearError();
1840
Jesse Hallb29e5e82012-04-04 16:53:42 -07001841 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001842 if (!dp) return EGL_NO_SYNC_KHR;
1843
Mathias Agopian518ec112011-05-13 16:21:08 -07001844 EGLSyncKHR result = EGL_NO_SYNC_KHR;
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001845 egl_connection_t* const cnx = &gEGLImpl;
1846 if (cnx->dso && cnx->egl.eglCreateSyncKHR) {
1847 result = cnx->egl.eglCreateSyncKHR(dp->disp.dpy, type, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001848 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001849 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001850}
1851
1852EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
1853{
1854 clearError();
1855
Jesse Hallb29e5e82012-04-04 16:53:42 -07001856 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001857 if (!dp) return EGL_FALSE;
1858
Mathias Agopian518ec112011-05-13 16:21:08 -07001859 EGLBoolean result = EGL_FALSE;
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001860 egl_connection_t* const cnx = &gEGLImpl;
1861 if (cnx->dso && cnx->egl.eglDestroySyncKHR) {
1862 result = cnx->egl.eglDestroySyncKHR(dp->disp.dpy, sync);
Mathias Agopian518ec112011-05-13 16:21:08 -07001863 }
1864 return result;
1865}
1866
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -07001867EGLBoolean eglSignalSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode) {
1868 clearError();
1869
1870 const egl_display_ptr dp = validate_display(dpy);
1871 if (!dp) return EGL_FALSE;
1872
1873 EGLBoolean result = EGL_FALSE;
1874 egl_connection_t* const cnx = &gEGLImpl;
1875 if (cnx->dso && cnx->egl.eglSignalSyncKHR) {
1876 result = cnx->egl.eglSignalSyncKHR(
1877 dp->disp.dpy, sync, mode);
1878 }
1879 return result;
1880}
1881
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001882EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync,
1883 EGLint flags, EGLTimeKHR timeout)
Mathias Agopian518ec112011-05-13 16:21:08 -07001884{
1885 clearError();
1886
Jesse Hallb29e5e82012-04-04 16:53:42 -07001887 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001888 if (!dp) return EGL_FALSE;
1889
Mathias Agopian737b8962017-02-24 14:32:05 -08001890 EGLint result = EGL_FALSE;
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001891 egl_connection_t* const cnx = &gEGLImpl;
1892 if (cnx->dso && cnx->egl.eglClientWaitSyncKHR) {
1893 result = cnx->egl.eglClientWaitSyncKHR(
1894 dp->disp.dpy, sync, flags, timeout);
Mathias Agopian518ec112011-05-13 16:21:08 -07001895 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001896 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001897}
1898
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001899EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync,
1900 EGLint attribute, EGLint *value)
Mathias Agopian518ec112011-05-13 16:21:08 -07001901{
1902 clearError();
1903
Jesse Hallb29e5e82012-04-04 16:53:42 -07001904 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001905 if (!dp) return EGL_FALSE;
1906
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001907 EGLBoolean result = EGL_FALSE;
1908 egl_connection_t* const cnx = &gEGLImpl;
1909 if (cnx->dso && cnx->egl.eglGetSyncAttribKHR) {
1910 result = cnx->egl.eglGetSyncAttribKHR(
1911 dp->disp.dpy, sync, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -07001912 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001913 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001914}
1915
Season Li000d88f2015-07-01 11:39:40 -07001916EGLStreamKHR eglCreateStreamKHR(EGLDisplay dpy, const EGLint *attrib_list)
1917{
1918 clearError();
1919
1920 const egl_display_ptr dp = validate_display(dpy);
1921 if (!dp) return EGL_NO_STREAM_KHR;
1922
1923 EGLStreamKHR result = EGL_NO_STREAM_KHR;
1924 egl_connection_t* const cnx = &gEGLImpl;
1925 if (cnx->dso && cnx->egl.eglCreateStreamKHR) {
1926 result = cnx->egl.eglCreateStreamKHR(
1927 dp->disp.dpy, attrib_list);
1928 }
1929 return result;
1930}
1931
1932EGLBoolean eglDestroyStreamKHR(EGLDisplay dpy, EGLStreamKHR stream)
1933{
1934 clearError();
1935
1936 const egl_display_ptr dp = validate_display(dpy);
1937 if (!dp) return EGL_FALSE;
1938
1939 EGLBoolean result = EGL_FALSE;
1940 egl_connection_t* const cnx = &gEGLImpl;
1941 if (cnx->dso && cnx->egl.eglDestroyStreamKHR) {
1942 result = cnx->egl.eglDestroyStreamKHR(
1943 dp->disp.dpy, stream);
1944 }
1945 return result;
1946}
1947
1948EGLBoolean eglStreamAttribKHR(EGLDisplay dpy, EGLStreamKHR stream,
1949 EGLenum attribute, EGLint value)
1950{
1951 clearError();
1952
1953 const egl_display_ptr dp = validate_display(dpy);
1954 if (!dp) return EGL_FALSE;
1955
1956 EGLBoolean result = EGL_FALSE;
1957 egl_connection_t* const cnx = &gEGLImpl;
1958 if (cnx->dso && cnx->egl.eglStreamAttribKHR) {
1959 result = cnx->egl.eglStreamAttribKHR(
1960 dp->disp.dpy, stream, attribute, value);
1961 }
1962 return result;
1963}
1964
1965EGLBoolean eglQueryStreamKHR(EGLDisplay dpy, EGLStreamKHR stream,
1966 EGLenum attribute, EGLint *value)
1967{
1968 clearError();
1969
1970 const egl_display_ptr dp = validate_display(dpy);
1971 if (!dp) return EGL_FALSE;
1972
1973 EGLBoolean result = EGL_FALSE;
1974 egl_connection_t* const cnx = &gEGLImpl;
1975 if (cnx->dso && cnx->egl.eglQueryStreamKHR) {
1976 result = cnx->egl.eglQueryStreamKHR(
1977 dp->disp.dpy, stream, attribute, value);
1978 }
1979 return result;
1980}
1981
1982EGLBoolean eglQueryStreamu64KHR(EGLDisplay dpy, EGLStreamKHR stream,
1983 EGLenum attribute, EGLuint64KHR *value)
1984{
1985 clearError();
1986
1987 const egl_display_ptr dp = validate_display(dpy);
1988 if (!dp) return EGL_FALSE;
1989
1990 EGLBoolean result = EGL_FALSE;
1991 egl_connection_t* const cnx = &gEGLImpl;
1992 if (cnx->dso && cnx->egl.eglQueryStreamu64KHR) {
1993 result = cnx->egl.eglQueryStreamu64KHR(
1994 dp->disp.dpy, stream, attribute, value);
1995 }
1996 return result;
1997}
1998
1999EGLBoolean eglQueryStreamTimeKHR(EGLDisplay dpy, EGLStreamKHR stream,
2000 EGLenum attribute, EGLTimeKHR *value)
2001{
2002 clearError();
2003
2004 const egl_display_ptr dp = validate_display(dpy);
2005 if (!dp) return EGL_FALSE;
2006
2007 EGLBoolean result = EGL_FALSE;
2008 egl_connection_t* const cnx = &gEGLImpl;
2009 if (cnx->dso && cnx->egl.eglQueryStreamTimeKHR) {
2010 result = cnx->egl.eglQueryStreamTimeKHR(
2011 dp->disp.dpy, stream, attribute, value);
2012 }
2013 return result;
2014}
2015
2016EGLSurface eglCreateStreamProducerSurfaceKHR(EGLDisplay dpy, EGLConfig config,
2017 EGLStreamKHR stream, const EGLint *attrib_list)
2018{
2019 clearError();
2020
2021 egl_display_ptr dp = validate_display(dpy);
2022 if (!dp) return EGL_NO_SURFACE;
2023
2024 egl_connection_t* const cnx = &gEGLImpl;
2025 if (cnx->dso && cnx->egl.eglCreateStreamProducerSurfaceKHR) {
2026 EGLSurface surface = cnx->egl.eglCreateStreamProducerSurfaceKHR(
2027 dp->disp.dpy, config, stream, attrib_list);
2028 if (surface != EGL_NO_SURFACE) {
Courtney Goeltzenleuchterb1d70ec2018-02-08 18:09:33 -07002029 egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL, surface,
2030 EGL_GL_COLORSPACE_LINEAR_KHR, cnx);
Season Li000d88f2015-07-01 11:39:40 -07002031 return s;
2032 }
2033 }
2034 return EGL_NO_SURFACE;
2035}
2036
2037EGLBoolean eglStreamConsumerGLTextureExternalKHR(EGLDisplay dpy,
2038 EGLStreamKHR stream)
2039{
2040 clearError();
2041
2042 const egl_display_ptr dp = validate_display(dpy);
2043 if (!dp) return EGL_FALSE;
2044
2045 EGLBoolean result = EGL_FALSE;
2046 egl_connection_t* const cnx = &gEGLImpl;
2047 if (cnx->dso && cnx->egl.eglStreamConsumerGLTextureExternalKHR) {
2048 result = cnx->egl.eglStreamConsumerGLTextureExternalKHR(
2049 dp->disp.dpy, stream);
2050 }
2051 return result;
2052}
2053
2054EGLBoolean eglStreamConsumerAcquireKHR(EGLDisplay dpy,
2055 EGLStreamKHR stream)
2056{
2057 clearError();
2058
2059 const egl_display_ptr dp = validate_display(dpy);
2060 if (!dp) return EGL_FALSE;
2061
2062 EGLBoolean result = EGL_FALSE;
2063 egl_connection_t* const cnx = &gEGLImpl;
2064 if (cnx->dso && cnx->egl.eglStreamConsumerAcquireKHR) {
2065 result = cnx->egl.eglStreamConsumerAcquireKHR(
2066 dp->disp.dpy, stream);
2067 }
2068 return result;
2069}
2070
2071EGLBoolean eglStreamConsumerReleaseKHR(EGLDisplay dpy,
2072 EGLStreamKHR stream)
2073{
2074 clearError();
2075
2076 const egl_display_ptr dp = validate_display(dpy);
2077 if (!dp) return EGL_FALSE;
2078
2079 EGLBoolean result = EGL_FALSE;
2080 egl_connection_t* const cnx = &gEGLImpl;
2081 if (cnx->dso && cnx->egl.eglStreamConsumerReleaseKHR) {
2082 result = cnx->egl.eglStreamConsumerReleaseKHR(
2083 dp->disp.dpy, stream);
2084 }
2085 return result;
2086}
2087
2088EGLNativeFileDescriptorKHR eglGetStreamFileDescriptorKHR(
2089 EGLDisplay dpy, EGLStreamKHR stream)
2090{
2091 clearError();
2092
2093 const egl_display_ptr dp = validate_display(dpy);
2094 if (!dp) return EGL_NO_FILE_DESCRIPTOR_KHR;
2095
2096 EGLNativeFileDescriptorKHR result = EGL_NO_FILE_DESCRIPTOR_KHR;
2097 egl_connection_t* const cnx = &gEGLImpl;
2098 if (cnx->dso && cnx->egl.eglGetStreamFileDescriptorKHR) {
2099 result = cnx->egl.eglGetStreamFileDescriptorKHR(
2100 dp->disp.dpy, stream);
2101 }
2102 return result;
2103}
2104
2105EGLStreamKHR eglCreateStreamFromFileDescriptorKHR(
2106 EGLDisplay dpy, EGLNativeFileDescriptorKHR file_descriptor)
2107{
2108 clearError();
2109
2110 const egl_display_ptr dp = validate_display(dpy);
2111 if (!dp) return EGL_NO_STREAM_KHR;
2112
2113 EGLStreamKHR result = EGL_NO_STREAM_KHR;
2114 egl_connection_t* const cnx = &gEGLImpl;
2115 if (cnx->dso && cnx->egl.eglCreateStreamFromFileDescriptorKHR) {
2116 result = cnx->egl.eglCreateStreamFromFileDescriptorKHR(
2117 dp->disp.dpy, file_descriptor);
2118 }
2119 return result;
2120}
2121
Mathias Agopian518ec112011-05-13 16:21:08 -07002122// ----------------------------------------------------------------------------
Mathias Agopian2bb71682013-03-27 17:32:41 -07002123// EGL_EGLEXT_VERSION 15
2124// ----------------------------------------------------------------------------
2125
2126EGLint eglWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags) {
2127 clearError();
2128 const egl_display_ptr dp = validate_display(dpy);
2129 if (!dp) return EGL_FALSE;
2130 EGLint result = EGL_FALSE;
2131 egl_connection_t* const cnx = &gEGLImpl;
2132 if (cnx->dso && cnx->egl.eglWaitSyncKHR) {
2133 result = cnx->egl.eglWaitSyncKHR(dp->disp.dpy, sync, flags);
2134 }
2135 return result;
2136}
2137
2138// ----------------------------------------------------------------------------
Mathias Agopian518ec112011-05-13 16:21:08 -07002139// ANDROID extensions
2140// ----------------------------------------------------------------------------
2141
Jamie Gennis331841b2012-09-06 14:52:00 -07002142EGLint eglDupNativeFenceFDANDROID(EGLDisplay dpy, EGLSyncKHR sync)
2143{
2144 clearError();
2145
2146 const egl_display_ptr dp = validate_display(dpy);
2147 if (!dp) return EGL_NO_NATIVE_FENCE_FD_ANDROID;
2148
2149 EGLint result = EGL_NO_NATIVE_FENCE_FD_ANDROID;
2150 egl_connection_t* const cnx = &gEGLImpl;
2151 if (cnx->dso && cnx->egl.eglDupNativeFenceFDANDROID) {
2152 result = cnx->egl.eglDupNativeFenceFDANDROID(dp->disp.dpy, sync);
2153 }
2154 return result;
2155}
Jonas Yang1c3d72a2011-08-26 20:04:39 +08002156
Andy McFadden72841452013-03-01 16:25:32 -08002157EGLBoolean eglPresentationTimeANDROID(EGLDisplay dpy, EGLSurface surface,
2158 EGLnsecsANDROID time)
2159{
2160 clearError();
2161
2162 const egl_display_ptr dp = validate_display(dpy);
2163 if (!dp) {
2164 return EGL_FALSE;
2165 }
2166
2167 SurfaceRef _s(dp.get(), surface);
2168 if (!_s.get()) {
2169 setError(EGL_BAD_SURFACE, EGL_FALSE);
2170 return EGL_FALSE;
2171 }
2172
2173 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian65421432017-03-08 11:49:05 -08002174 native_window_set_buffers_timestamp(s->getNativeWindow(), time);
Andy McFadden72841452013-03-01 16:25:32 -08002175
2176 return EGL_TRUE;
2177}
2178
Craig Donner60761072017-01-27 12:30:44 -08002179EGLClientBuffer eglGetNativeClientBufferANDROID(const AHardwareBuffer *buffer) {
2180 clearError();
Jiyong Parka243e5d2017-06-21 12:26:51 +09002181 // AHardwareBuffer_to_ANativeWindowBuffer is a platform-only symbol and thus
2182 // this function cannot be implemented when this libEGL is built for
2183 // vendors.
2184#ifndef __ANDROID_VNDK__
Craig Donner60761072017-01-27 12:30:44 -08002185 if (!buffer) return setError(EGL_BAD_PARAMETER, (EGLClientBuffer)0);
Mathias Agopian61963402017-02-24 16:38:15 -08002186 return const_cast<ANativeWindowBuffer *>(AHardwareBuffer_to_ANativeWindowBuffer(buffer));
Jiyong Parka243e5d2017-06-21 12:26:51 +09002187#else
2188 return setError(EGL_BAD_PARAMETER, (EGLClientBuffer)0);
2189#endif
Craig Donner60761072017-01-27 12:30:44 -08002190}
2191
Jonas Yang1c3d72a2011-08-26 20:04:39 +08002192// ----------------------------------------------------------------------------
2193// NVIDIA extensions
2194// ----------------------------------------------------------------------------
2195EGLuint64NV eglGetSystemTimeFrequencyNV()
2196{
2197 clearError();
2198
2199 if (egl_init_drivers() == EGL_FALSE) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002200 return setError(EGL_BAD_PARAMETER, (EGLuint64NV)EGL_FALSE);
Jonas Yang1c3d72a2011-08-26 20:04:39 +08002201 }
2202
2203 EGLuint64NV ret = 0;
Mathias Agopianada798b2012-02-13 17:09:30 -08002204 egl_connection_t* const cnx = &gEGLImpl;
Jonas Yang1c3d72a2011-08-26 20:04:39 +08002205
Mathias Agopianada798b2012-02-13 17:09:30 -08002206 if (cnx->dso && cnx->egl.eglGetSystemTimeFrequencyNV) {
2207 return cnx->egl.eglGetSystemTimeFrequencyNV();
Jonas Yang1c3d72a2011-08-26 20:04:39 +08002208 }
2209
Mathias Agopian737b8962017-02-24 14:32:05 -08002210 return setErrorQuiet(EGL_BAD_DISPLAY, (EGLuint64NV)0);
Jonas Yang1c3d72a2011-08-26 20:04:39 +08002211}
2212
2213EGLuint64NV eglGetSystemTimeNV()
2214{
2215 clearError();
2216
2217 if (egl_init_drivers() == EGL_FALSE) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002218 return setError(EGL_BAD_PARAMETER, (EGLuint64NV)EGL_FALSE);
Jonas Yang1c3d72a2011-08-26 20:04:39 +08002219 }
2220
2221 EGLuint64NV ret = 0;
Mathias Agopianada798b2012-02-13 17:09:30 -08002222 egl_connection_t* const cnx = &gEGLImpl;
Jonas Yang1c3d72a2011-08-26 20:04:39 +08002223
Mathias Agopianada798b2012-02-13 17:09:30 -08002224 if (cnx->dso && cnx->egl.eglGetSystemTimeNV) {
2225 return cnx->egl.eglGetSystemTimeNV();
Jonas Yang1c3d72a2011-08-26 20:04:39 +08002226 }
2227
Mathias Agopian737b8962017-02-24 14:32:05 -08002228 return setErrorQuiet(EGL_BAD_DISPLAY, (EGLuint64NV)0);
Jonas Yang1c3d72a2011-08-26 20:04:39 +08002229}
Dan Stozaa894d082015-02-19 15:27:36 -08002230
2231// ----------------------------------------------------------------------------
2232// Partial update extension
2233// ----------------------------------------------------------------------------
2234EGLBoolean eglSetDamageRegionKHR(EGLDisplay dpy, EGLSurface surface,
2235 EGLint *rects, EGLint n_rects)
2236{
2237 clearError();
2238
2239 const egl_display_ptr dp = validate_display(dpy);
2240 if (!dp) {
2241 setError(EGL_BAD_DISPLAY, EGL_FALSE);
2242 return EGL_FALSE;
2243 }
2244
2245 SurfaceRef _s(dp.get(), surface);
2246 if (!_s.get()) {
2247 setError(EGL_BAD_SURFACE, EGL_FALSE);
2248 return EGL_FALSE;
2249 }
2250
2251 egl_surface_t const * const s = get_surface(surface);
2252 if (s->cnx->egl.eglSetDamageRegionKHR) {
2253 return s->cnx->egl.eglSetDamageRegionKHR(dp->disp.dpy, s->surface,
2254 rects, n_rects);
2255 }
2256
2257 return EGL_FALSE;
2258}
Pablo Ceballosc18be292016-05-31 14:55:42 -07002259
Brian Anderson1049d1d2016-12-16 17:25:57 -08002260EGLBoolean eglGetNextFrameIdANDROID(EGLDisplay dpy, EGLSurface surface,
2261 EGLuint64KHR *frameId) {
2262 clearError();
2263
2264 const egl_display_ptr dp = validate_display(dpy);
2265 if (!dp) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002266 return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
Brian Anderson1049d1d2016-12-16 17:25:57 -08002267 }
2268
2269 SurfaceRef _s(dp.get(), surface);
2270 if (!_s.get()) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002271 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Brian Anderson1049d1d2016-12-16 17:25:57 -08002272 }
2273
2274 egl_surface_t const * const s = get_surface(surface);
2275
Mathias Agopian65421432017-03-08 11:49:05 -08002276 if (!s->getNativeWindow()) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002277 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Brian Anderson1049d1d2016-12-16 17:25:57 -08002278 }
2279
2280 uint64_t nextFrameId = 0;
Mathias Agopian65421432017-03-08 11:49:05 -08002281 int ret = native_window_get_next_frame_id(s->getNativeWindow(), &nextFrameId);
Brian Anderson1049d1d2016-12-16 17:25:57 -08002282
Mathias Agopian65421432017-03-08 11:49:05 -08002283 if (ret != 0) {
Brian Anderson1049d1d2016-12-16 17:25:57 -08002284 // This should not happen. Return an error that is not in the spec
2285 // so it's obvious something is very wrong.
2286 ALOGE("eglGetNextFrameId: Unexpected error.");
Mathias Agopian737b8962017-02-24 14:32:05 -08002287 return setError(EGL_NOT_INITIALIZED, (EGLBoolean)EGL_FALSE);
Brian Anderson1049d1d2016-12-16 17:25:57 -08002288 }
2289
2290 *frameId = nextFrameId;
2291 return EGL_TRUE;
2292}
2293
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002294EGLBoolean eglGetCompositorTimingANDROID(EGLDisplay dpy, EGLSurface surface,
2295 EGLint numTimestamps, const EGLint *names, EGLnsecsANDROID *values)
2296{
2297 clearError();
2298
2299 const egl_display_ptr dp = validate_display(dpy);
2300 if (!dp) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002301 return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002302 }
2303
2304 SurfaceRef _s(dp.get(), surface);
2305 if (!_s.get()) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002306 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002307 }
2308
2309 egl_surface_t const * const s = get_surface(surface);
2310
Mathias Agopian65421432017-03-08 11:49:05 -08002311 if (!s->getNativeWindow()) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002312 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002313 }
2314
2315 nsecs_t* compositeDeadline = nullptr;
2316 nsecs_t* compositeInterval = nullptr;
2317 nsecs_t* compositeToPresentLatency = nullptr;
2318
2319 for (int i = 0; i < numTimestamps; i++) {
2320 switch (names[i]) {
2321 case EGL_COMPOSITE_DEADLINE_ANDROID:
2322 compositeDeadline = &values[i];
2323 break;
2324 case EGL_COMPOSITE_INTERVAL_ANDROID:
2325 compositeInterval = &values[i];
2326 break;
2327 case EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID:
2328 compositeToPresentLatency = &values[i];
2329 break;
2330 default:
Mathias Agopian737b8962017-02-24 14:32:05 -08002331 return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE);
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002332 }
2333 }
2334
Mathias Agopian65421432017-03-08 11:49:05 -08002335 int ret = native_window_get_compositor_timing(s->getNativeWindow(),
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002336 compositeDeadline, compositeInterval, compositeToPresentLatency);
2337
2338 switch (ret) {
Mathias Agopian65421432017-03-08 11:49:05 -08002339 case 0:
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002340 return EGL_TRUE;
Mathias Agopian65421432017-03-08 11:49:05 -08002341 case -ENOSYS:
Mathias Agopian737b8962017-02-24 14:32:05 -08002342 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002343 default:
2344 // This should not happen. Return an error that is not in the spec
2345 // so it's obvious something is very wrong.
2346 ALOGE("eglGetCompositorTiming: Unexpected error.");
Mathias Agopian737b8962017-02-24 14:32:05 -08002347 return setError(EGL_NOT_INITIALIZED, (EGLBoolean)EGL_FALSE);
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002348 }
2349}
2350
2351EGLBoolean eglGetCompositorTimingSupportedANDROID(
2352 EGLDisplay dpy, EGLSurface surface, EGLint name)
2353{
2354 clearError();
2355
2356 const egl_display_ptr dp = validate_display(dpy);
2357 if (!dp) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002358 return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002359 }
2360
2361 SurfaceRef _s(dp.get(), surface);
2362 if (!_s.get()) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002363 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002364 }
2365
2366 egl_surface_t const * const s = get_surface(surface);
2367
Mathias Agopian65421432017-03-08 11:49:05 -08002368 ANativeWindow* window = s->getNativeWindow();
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002369 if (!window) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002370 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002371 }
2372
2373 switch (name) {
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002374 case EGL_COMPOSITE_DEADLINE_ANDROID:
2375 case EGL_COMPOSITE_INTERVAL_ANDROID:
2376 case EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID:
2377 return EGL_TRUE;
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002378 default:
2379 return EGL_FALSE;
2380 }
2381}
2382
Pablo Ceballosc18be292016-05-31 14:55:42 -07002383EGLBoolean eglGetFrameTimestampsANDROID(EGLDisplay dpy, EGLSurface surface,
Brian Anderson1049d1d2016-12-16 17:25:57 -08002384 EGLuint64KHR frameId, EGLint numTimestamps, const EGLint *timestamps,
Pablo Ceballosc18be292016-05-31 14:55:42 -07002385 EGLnsecsANDROID *values)
2386{
2387 clearError();
2388
2389 const egl_display_ptr dp = validate_display(dpy);
2390 if (!dp) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002391 return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
Pablo Ceballosc18be292016-05-31 14:55:42 -07002392 }
2393
2394 SurfaceRef _s(dp.get(), surface);
2395 if (!_s.get()) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002396 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Pablo Ceballosc18be292016-05-31 14:55:42 -07002397 }
2398
2399 egl_surface_t const * const s = get_surface(surface);
2400
Mathias Agopian65421432017-03-08 11:49:05 -08002401 if (!s->getNativeWindow()) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002402 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Pablo Ceballosc18be292016-05-31 14:55:42 -07002403 }
2404
Brian Andersondbd0ea82016-07-22 09:38:59 -07002405 nsecs_t* requestedPresentTime = nullptr;
Pablo Ceballosc18be292016-05-31 14:55:42 -07002406 nsecs_t* acquireTime = nullptr;
Brian Andersonf7fd56a2016-09-02 10:10:04 -07002407 nsecs_t* latchTime = nullptr;
2408 nsecs_t* firstRefreshStartTime = nullptr;
Brian Andersonb04c6f02016-10-21 12:57:46 -07002409 nsecs_t* gpuCompositionDoneTime = nullptr;
Brian Andersonf7fd56a2016-09-02 10:10:04 -07002410 nsecs_t* lastRefreshStartTime = nullptr;
Brian Anderson069b3652016-07-22 10:32:47 -07002411 nsecs_t* displayPresentTime = nullptr;
Brian Andersonf7fd56a2016-09-02 10:10:04 -07002412 nsecs_t* dequeueReadyTime = nullptr;
Pablo Ceballosc18be292016-05-31 14:55:42 -07002413 nsecs_t* releaseTime = nullptr;
2414
2415 for (int i = 0; i < numTimestamps; i++) {
2416 switch (timestamps[i]) {
Brian Andersondbd0ea82016-07-22 09:38:59 -07002417 case EGL_REQUESTED_PRESENT_TIME_ANDROID:
2418 requestedPresentTime = &values[i];
Pablo Ceballosc18be292016-05-31 14:55:42 -07002419 break;
2420 case EGL_RENDERING_COMPLETE_TIME_ANDROID:
2421 acquireTime = &values[i];
2422 break;
Brian Andersonf7fd56a2016-09-02 10:10:04 -07002423 case EGL_COMPOSITION_LATCH_TIME_ANDROID:
2424 latchTime = &values[i];
Pablo Ceballosc18be292016-05-31 14:55:42 -07002425 break;
Brian Andersonf7fd56a2016-09-02 10:10:04 -07002426 case EGL_FIRST_COMPOSITION_START_TIME_ANDROID:
2427 firstRefreshStartTime = &values[i];
2428 break;
2429 case EGL_LAST_COMPOSITION_START_TIME_ANDROID:
2430 lastRefreshStartTime = &values[i];
2431 break;
Brian Andersonb04c6f02016-10-21 12:57:46 -07002432 case EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID:
2433 gpuCompositionDoneTime = &values[i];
Pablo Ceballosc18be292016-05-31 14:55:42 -07002434 break;
Brian Anderson069b3652016-07-22 10:32:47 -07002435 case EGL_DISPLAY_PRESENT_TIME_ANDROID:
2436 displayPresentTime = &values[i];
2437 break;
Brian Andersonf7fd56a2016-09-02 10:10:04 -07002438 case EGL_DEQUEUE_READY_TIME_ANDROID:
2439 dequeueReadyTime = &values[i];
2440 break;
Pablo Ceballosc18be292016-05-31 14:55:42 -07002441 case EGL_READS_DONE_TIME_ANDROID:
2442 releaseTime = &values[i];
2443 break;
2444 default:
Mathias Agopian737b8962017-02-24 14:32:05 -08002445 return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE);
Pablo Ceballosc18be292016-05-31 14:55:42 -07002446 }
2447 }
2448
Mathias Agopian65421432017-03-08 11:49:05 -08002449 int ret = native_window_get_frame_timestamps(s->getNativeWindow(), frameId,
Brian Andersonf7fd56a2016-09-02 10:10:04 -07002450 requestedPresentTime, acquireTime, latchTime, firstRefreshStartTime,
Brian Andersonb04c6f02016-10-21 12:57:46 -07002451 lastRefreshStartTime, gpuCompositionDoneTime, displayPresentTime,
Brian Anderson4e606e32017-03-16 15:34:57 -07002452 dequeueReadyTime, releaseTime);
Pablo Ceballosc18be292016-05-31 14:55:42 -07002453
Brian Anderson069b3652016-07-22 10:32:47 -07002454 switch (ret) {
Mathias Agopian65421432017-03-08 11:49:05 -08002455 case 0:
Mathias Agopian737b8962017-02-24 14:32:05 -08002456 return EGL_TRUE;
Mathias Agopian65421432017-03-08 11:49:05 -08002457 case -ENOENT:
Mathias Agopian737b8962017-02-24 14:32:05 -08002458 return setError(EGL_BAD_ACCESS, (EGLBoolean)EGL_FALSE);
Mathias Agopian65421432017-03-08 11:49:05 -08002459 case -ENOSYS:
Mathias Agopian737b8962017-02-24 14:32:05 -08002460 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian65421432017-03-08 11:49:05 -08002461 case -EINVAL:
Mathias Agopian737b8962017-02-24 14:32:05 -08002462 return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE);
2463 default:
2464 // This should not happen. Return an error that is not in the spec
2465 // so it's obvious something is very wrong.
2466 ALOGE("eglGetFrameTimestamps: Unexpected error.");
2467 return setError(EGL_NOT_INITIALIZED, (EGLBoolean)EGL_FALSE);
Pablo Ceballosc18be292016-05-31 14:55:42 -07002468 }
Pablo Ceballosc18be292016-05-31 14:55:42 -07002469}
2470
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002471EGLBoolean eglGetFrameTimestampSupportedANDROID(
2472 EGLDisplay dpy, EGLSurface surface, EGLint timestamp)
Pablo Ceballosc18be292016-05-31 14:55:42 -07002473{
2474 clearError();
2475
2476 const egl_display_ptr dp = validate_display(dpy);
2477 if (!dp) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002478 return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
Pablo Ceballosc18be292016-05-31 14:55:42 -07002479 }
2480
2481 SurfaceRef _s(dp.get(), surface);
2482 if (!_s.get()) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002483 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Brian Anderson069b3652016-07-22 10:32:47 -07002484 }
2485
2486 egl_surface_t const * const s = get_surface(surface);
2487
Mathias Agopian65421432017-03-08 11:49:05 -08002488 ANativeWindow* window = s->getNativeWindow();
Brian Anderson069b3652016-07-22 10:32:47 -07002489 if (!window) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002490 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Pablo Ceballosc18be292016-05-31 14:55:42 -07002491 }
2492
2493 switch (timestamp) {
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002494 case EGL_COMPOSITE_DEADLINE_ANDROID:
2495 case EGL_COMPOSITE_INTERVAL_ANDROID:
2496 case EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID:
Brian Andersondbd0ea82016-07-22 09:38:59 -07002497 case EGL_REQUESTED_PRESENT_TIME_ANDROID:
Pablo Ceballosc18be292016-05-31 14:55:42 -07002498 case EGL_RENDERING_COMPLETE_TIME_ANDROID:
Brian Andersonf7fd56a2016-09-02 10:10:04 -07002499 case EGL_COMPOSITION_LATCH_TIME_ANDROID:
2500 case EGL_FIRST_COMPOSITION_START_TIME_ANDROID:
2501 case EGL_LAST_COMPOSITION_START_TIME_ANDROID:
Brian Andersonb04c6f02016-10-21 12:57:46 -07002502 case EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID:
Brian Andersonf7fd56a2016-09-02 10:10:04 -07002503 case EGL_DEQUEUE_READY_TIME_ANDROID:
Pablo Ceballosc18be292016-05-31 14:55:42 -07002504 case EGL_READS_DONE_TIME_ANDROID:
2505 return EGL_TRUE;
Brian Anderson6b376712017-04-04 10:51:39 -07002506 case EGL_DISPLAY_PRESENT_TIME_ANDROID: {
2507 int value = 0;
2508 window->query(window,
2509 NATIVE_WINDOW_FRAME_TIMESTAMPS_SUPPORTS_PRESENT, &value);
2510 return value == 0 ? EGL_FALSE : EGL_TRUE;
2511 }
Pablo Ceballosc18be292016-05-31 14:55:42 -07002512 default:
2513 return EGL_FALSE;
2514 }
2515}