blob: b453d19d8372f61bb483c132e19e3a200addcd3d [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
97 "EGL_KHR_image_pixmap "
98 "EGL_KHR_lock_surface "
Jesse Hallc2e41222013-08-08 13:40:22 -070099 "EGL_KHR_gl_colorspace "
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700100 "EGL_KHR_gl_texture_2D_image "
Season Li000d88f2015-07-01 11:39:40 -0700101 "EGL_KHR_gl_texture_3D_image "
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700102 "EGL_KHR_gl_texture_cubemap_image "
103 "EGL_KHR_gl_renderbuffer_image "
104 "EGL_KHR_reusable_sync "
105 "EGL_KHR_fence_sync "
Jamie Gennisf6d1c392013-04-25 18:48:41 -0700106 "EGL_KHR_create_context "
Season Li000d88f2015-07-01 11:39:40 -0700107 "EGL_KHR_config_attribs "
108 "EGL_KHR_surfaceless_context "
109 "EGL_KHR_stream "
110 "EGL_KHR_stream_fifo "
111 "EGL_KHR_stream_producer_eglsurface "
112 "EGL_KHR_stream_consumer_gltexture "
113 "EGL_KHR_stream_cross_process_fd "
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700114 "EGL_EXT_create_context_robustness "
115 "EGL_NV_system_time "
116 "EGL_ANDROID_image_native_buffer " // mandatory
Mathias Agopian2bb71682013-03-27 17:32:41 -0700117 "EGL_KHR_wait_sync " // strongly recommended
Jamie Gennisdbe92452013-09-23 17:22:10 -0700118 "EGL_ANDROID_recordable " // mandatory
Dan Stozaa894d082015-02-19 15:27:36 -0800119 "EGL_KHR_partial_update " // strongly recommended
Courtney Goeltzenleuchter0e4e3952016-11-16 13:53:40 -0700120 "EGL_EXT_pixel_format_float "
Dan Stozaa894d082015-02-19 15:27:36 -0800121 "EGL_EXT_buffer_age " // strongly recommended with partial_update
Jesse Hall408e59f2015-04-24 01:40:42 -0700122 "EGL_KHR_create_context_no_error "
Pablo Ceballosceb9ee72016-04-13 11:17:32 -0700123 "EGL_KHR_mutable_render_buffer "
Mika Isojärvif37864b2016-04-15 11:58:56 -0700124 "EGL_EXT_yuv_surface "
Craig Donneraec86972016-04-28 18:09:40 -0700125 "EGL_EXT_protected_content "
Christian Poetzscha7805f62016-12-01 16:34:39 +0000126 "EGL_IMG_context_priority "
Pyry Haulos51d53c42017-03-06 09:39:09 -0800127 "EGL_KHR_no_config_context "
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700128 ;
Courtney Goeltzenleuchter21b33cb2017-04-17 17:31:29 -0600129// clang-format on
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700130
131// extensions not exposed to applications but used by the ANDROID system
132// "EGL_ANDROID_blob_cache " // strongly recommended
133// "EGL_IMG_hibernate_process " // optional
134// "EGL_ANDROID_native_fence_sync " // strongly recommended
135// "EGL_ANDROID_framebuffer_target " // mandatory for HWC 1.1
Jamie Gennisdbe92452013-09-23 17:22:10 -0700136// "EGL_ANDROID_image_crop " // optional
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700137
138/*
139 * EGL Extensions entry-points exposed to 3rd party applications
140 * (keep in sync with gExtensionString above)
141 *
142 */
143static const extention_map_t sExtensionMap[] = {
144 // EGL_KHR_lock_surface
Mathias Agopian518ec112011-05-13 16:21:08 -0700145 { "eglLockSurfaceKHR",
146 (__eglMustCastToProperFunctionPointerType)&eglLockSurfaceKHR },
147 { "eglUnlockSurfaceKHR",
148 (__eglMustCastToProperFunctionPointerType)&eglUnlockSurfaceKHR },
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700149
150 // EGL_KHR_image, EGL_KHR_image_base
Mathias Agopian518ec112011-05-13 16:21:08 -0700151 { "eglCreateImageKHR",
152 (__eglMustCastToProperFunctionPointerType)&eglCreateImageKHR },
153 { "eglDestroyImageKHR",
154 (__eglMustCastToProperFunctionPointerType)&eglDestroyImageKHR },
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700155
156 // EGL_KHR_reusable_sync, EGL_KHR_fence_sync
157 { "eglCreateSyncKHR",
158 (__eglMustCastToProperFunctionPointerType)&eglCreateSyncKHR },
159 { "eglDestroySyncKHR",
160 (__eglMustCastToProperFunctionPointerType)&eglDestroySyncKHR },
161 { "eglClientWaitSyncKHR",
162 (__eglMustCastToProperFunctionPointerType)&eglClientWaitSyncKHR },
163 { "eglSignalSyncKHR",
164 (__eglMustCastToProperFunctionPointerType)&eglSignalSyncKHR },
165 { "eglGetSyncAttribKHR",
166 (__eglMustCastToProperFunctionPointerType)&eglGetSyncAttribKHR },
167
168 // EGL_NV_system_time
Jonas Yang1c3d72a2011-08-26 20:04:39 +0800169 { "eglGetSystemTimeFrequencyNV",
170 (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeFrequencyNV },
171 { "eglGetSystemTimeNV",
172 (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeNV },
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700173
Mathias Agopian2bb71682013-03-27 17:32:41 -0700174 // EGL_KHR_wait_sync
175 { "eglWaitSyncKHR",
176 (__eglMustCastToProperFunctionPointerType)&eglWaitSyncKHR },
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700177
178 // EGL_ANDROID_presentation_time
179 { "eglPresentationTimeANDROID",
180 (__eglMustCastToProperFunctionPointerType)&eglPresentationTimeANDROID },
Dan Stozaa894d082015-02-19 15:27:36 -0800181
182 // EGL_KHR_swap_buffers_with_damage
183 { "eglSwapBuffersWithDamageKHR",
184 (__eglMustCastToProperFunctionPointerType)&eglSwapBuffersWithDamageKHR },
185
Craig Donner60761072017-01-27 12:30:44 -0800186 // EGL_ANDROID_get_native_client_buffer
187 { "eglGetNativeClientBufferANDROID",
188 (__eglMustCastToProperFunctionPointerType)&eglGetNativeClientBufferANDROID },
189
Dan Stozaa894d082015-02-19 15:27:36 -0800190 // EGL_KHR_partial_update
191 { "eglSetDamageRegionKHR",
192 (__eglMustCastToProperFunctionPointerType)&eglSetDamageRegionKHR },
Season Li000d88f2015-07-01 11:39:40 -0700193
194 { "eglCreateStreamKHR",
195 (__eglMustCastToProperFunctionPointerType)&eglCreateStreamKHR },
196 { "eglDestroyStreamKHR",
197 (__eglMustCastToProperFunctionPointerType)&eglDestroyStreamKHR },
198 { "eglStreamAttribKHR",
199 (__eglMustCastToProperFunctionPointerType)&eglStreamAttribKHR },
200 { "eglQueryStreamKHR",
201 (__eglMustCastToProperFunctionPointerType)&eglQueryStreamKHR },
202 { "eglQueryStreamu64KHR",
203 (__eglMustCastToProperFunctionPointerType)&eglQueryStreamu64KHR },
204 { "eglQueryStreamTimeKHR",
205 (__eglMustCastToProperFunctionPointerType)&eglQueryStreamTimeKHR },
206 { "eglCreateStreamProducerSurfaceKHR",
207 (__eglMustCastToProperFunctionPointerType)&eglCreateStreamProducerSurfaceKHR },
208 { "eglStreamConsumerGLTextureExternalKHR",
209 (__eglMustCastToProperFunctionPointerType)&eglStreamConsumerGLTextureExternalKHR },
210 { "eglStreamConsumerAcquireKHR",
211 (__eglMustCastToProperFunctionPointerType)&eglStreamConsumerAcquireKHR },
212 { "eglStreamConsumerReleaseKHR",
213 (__eglMustCastToProperFunctionPointerType)&eglStreamConsumerReleaseKHR },
214 { "eglGetStreamFileDescriptorKHR",
215 (__eglMustCastToProperFunctionPointerType)&eglGetStreamFileDescriptorKHR },
216 { "eglCreateStreamFromFileDescriptorKHR",
217 (__eglMustCastToProperFunctionPointerType)&eglCreateStreamFromFileDescriptorKHR },
Pablo Ceballosc18be292016-05-31 14:55:42 -0700218
219 // EGL_ANDROID_get_frame_timestamps
Brian Anderson1049d1d2016-12-16 17:25:57 -0800220 { "eglGetNextFrameIdANDROID",
221 (__eglMustCastToProperFunctionPointerType)&eglGetNextFrameIdANDROID },
Brian Anderson0a61b0c2016-12-07 14:55:56 -0800222 { "eglGetCompositorTimingANDROID",
223 (__eglMustCastToProperFunctionPointerType)&eglGetCompositorTimingANDROID },
224 { "eglGetCompositorTimingSupportedANDROID",
225 (__eglMustCastToProperFunctionPointerType)&eglGetCompositorTimingSupportedANDROID },
Pablo Ceballosc18be292016-05-31 14:55:42 -0700226 { "eglGetFrameTimestampsANDROID",
227 (__eglMustCastToProperFunctionPointerType)&eglGetFrameTimestampsANDROID },
Brian Anderson0a61b0c2016-12-07 14:55:56 -0800228 { "eglGetFrameTimestampSupportedANDROID",
229 (__eglMustCastToProperFunctionPointerType)&eglGetFrameTimestampSupportedANDROID },
Craig Donner55901a22017-04-17 15:31:06 -0700230
231 // EGL_ANDROID_native_fence_sync
232 { "eglDupNativeFenceFDANDROID",
233 (__eglMustCastToProperFunctionPointerType)&eglDupNativeFenceFDANDROID },
Mathias Agopian518ec112011-05-13 16:21:08 -0700234};
235
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700236/*
237 * These extensions entry-points should not be exposed to applications.
238 * They're used internally by the Android EGL layer.
239 */
240#define FILTER_EXTENSIONS(procname) \
241 (!strcmp((procname), "eglSetBlobCacheFuncsANDROID") || \
242 !strcmp((procname), "eglHibernateProcessIMG") || \
Craig Donner55901a22017-04-17 15:31:06 -0700243 !strcmp((procname), "eglAwakenProcessIMG"))
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700244
Mathias Agopian518ec112011-05-13 16:21:08 -0700245// accesses protected by sExtensionMapMutex
Mathias Agopian65421432017-03-08 11:49:05 -0800246static std::unordered_map<std::string, __eglMustCastToProperFunctionPointerType> sGLExtentionMap;
247
Mathias Agopian518ec112011-05-13 16:21:08 -0700248static int sGLExtentionSlot = 0;
249static pthread_mutex_t sExtensionMapMutex = PTHREAD_MUTEX_INITIALIZER;
250
251static void(*findProcAddress(const char* name,
252 const extention_map_t* map, size_t n))() {
253 for (uint32_t i=0 ; i<n ; i++) {
254 if (!strcmp(name, map[i].name)) {
255 return map[i].address;
256 }
257 }
258 return NULL;
259}
260
261// ----------------------------------------------------------------------------
262
Mathias Agopian518ec112011-05-13 16:21:08 -0700263extern void setGLHooksThreadSpecific(gl_hooks_t const *value);
264extern EGLBoolean egl_init_drivers();
265extern const __eglMustCastToProperFunctionPointerType gExtensionForwarders[MAX_NUMBER_OF_GL_EXTENSIONS];
Mathias Agopian518ec112011-05-13 16:21:08 -0700266extern gl_hooks_t gHooksTrace;
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700267
Mathias Agopian518ec112011-05-13 16:21:08 -0700268} // namespace android;
269
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -0700270
Mathias Agopian518ec112011-05-13 16:21:08 -0700271// ----------------------------------------------------------------------------
272
273static inline void clearError() { egl_tls_t::clearError(); }
274static inline EGLContext getContext() { return egl_tls_t::getContext(); }
275
276// ----------------------------------------------------------------------------
277
278EGLDisplay eglGetDisplay(EGLNativeDisplayType display)
279{
Jesse Hall1508ae62017-01-19 17:43:26 -0800280 ATRACE_CALL();
Mathias Agopian518ec112011-05-13 16:21:08 -0700281 clearError();
282
Dan Stozac3289c42014-01-17 11:38:34 -0800283 uintptr_t index = reinterpret_cast<uintptr_t>(display);
Mathias Agopian518ec112011-05-13 16:21:08 -0700284 if (index >= NUM_DISPLAYS) {
285 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
286 }
287
288 if (egl_init_drivers() == EGL_FALSE) {
289 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
290 }
291
292 EGLDisplay dpy = egl_display_t::getFromNativeDisplay(display);
293 return dpy;
294}
295
296// ----------------------------------------------------------------------------
297// Initialization
298// ----------------------------------------------------------------------------
299
300EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
301{
302 clearError();
303
Jesse Hallb29e5e82012-04-04 16:53:42 -0700304 egl_display_ptr dp = get_display(dpy);
Mathias Agopian737b8962017-02-24 14:32:05 -0800305 if (!dp) return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700306
307 EGLBoolean res = dp->initialize(major, minor);
308
309 return res;
310}
311
312EGLBoolean eglTerminate(EGLDisplay dpy)
313{
314 // NOTE: don't unload the drivers b/c some APIs can be called
315 // after eglTerminate() has been called. eglTerminate() only
316 // terminates an EGLDisplay, not a EGL itself.
317
318 clearError();
319
Jesse Hallb29e5e82012-04-04 16:53:42 -0700320 egl_display_ptr dp = get_display(dpy);
Mathias Agopian737b8962017-02-24 14:32:05 -0800321 if (!dp) return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700322
323 EGLBoolean res = dp->terminate();
Jesse Hall47743382013-02-08 11:13:46 -0800324
Mathias Agopian518ec112011-05-13 16:21:08 -0700325 return res;
326}
327
328// ----------------------------------------------------------------------------
329// configuration
330// ----------------------------------------------------------------------------
331
332EGLBoolean eglGetConfigs( EGLDisplay dpy,
333 EGLConfig *configs,
334 EGLint config_size, EGLint *num_config)
335{
336 clearError();
337
Jesse Hallb29e5e82012-04-04 16:53:42 -0700338 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700339 if (!dp) return EGL_FALSE;
340
Mathias Agopian7773c432012-02-13 20:06:08 -0800341 if (num_config==0) {
Mathias Agopian737b8962017-02-24 14:32:05 -0800342 return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700343 }
344
Mathias Agopian7773c432012-02-13 20:06:08 -0800345 EGLBoolean res = EGL_FALSE;
346 *num_config = 0;
347
348 egl_connection_t* const cnx = &gEGLImpl;
349 if (cnx->dso) {
350 res = cnx->egl.eglGetConfigs(
351 dp->disp.dpy, configs, config_size, num_config);
Mathias Agopian518ec112011-05-13 16:21:08 -0700352 }
Mathias Agopian7773c432012-02-13 20:06:08 -0800353
354 return res;
Mathias Agopian518ec112011-05-13 16:21:08 -0700355}
356
357EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list,
358 EGLConfig *configs, EGLint config_size,
359 EGLint *num_config)
360{
361 clearError();
362
Jesse Hallb29e5e82012-04-04 16:53:42 -0700363 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700364 if (!dp) return EGL_FALSE;
365
366 if (num_config==0) {
Mathias Agopian737b8962017-02-24 14:32:05 -0800367 return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700368 }
369
Mathias Agopian518ec112011-05-13 16:21:08 -0700370 EGLBoolean res = EGL_FALSE;
371 *num_config = 0;
372
Mathias Agopianada798b2012-02-13 17:09:30 -0800373 egl_connection_t* const cnx = &gEGLImpl;
374 if (cnx->dso) {
Romain Guy1cffc802012-10-15 18:13:05 -0700375 if (attrib_list) {
376 char value[PROPERTY_VALUE_MAX];
377 property_get("debug.egl.force_msaa", value, "false");
378
379 if (!strcmp(value, "true")) {
380 size_t attribCount = 0;
381 EGLint attrib = attrib_list[0];
382
383 // Only enable MSAA if the context is OpenGL ES 2.0 and
Romain Guybe3c3e42012-10-15 19:25:18 -0700384 // if no caveat is requested
Romain Guy1cffc802012-10-15 18:13:05 -0700385 const EGLint *attribRendererable = NULL;
386 const EGLint *attribCaveat = NULL;
387
388 // Count the number of attributes and look for
Romain Guybe3c3e42012-10-15 19:25:18 -0700389 // EGL_RENDERABLE_TYPE and EGL_CONFIG_CAVEAT
Romain Guy1cffc802012-10-15 18:13:05 -0700390 while (attrib != EGL_NONE) {
391 attrib = attrib_list[attribCount];
392 switch (attrib) {
393 case EGL_RENDERABLE_TYPE:
394 attribRendererable = &attrib_list[attribCount];
395 break;
396 case EGL_CONFIG_CAVEAT:
397 attribCaveat = &attrib_list[attribCount];
398 break;
Mathias Agopian737b8962017-02-24 14:32:05 -0800399 default:
400 break;
Romain Guy1cffc802012-10-15 18:13:05 -0700401 }
402 attribCount++;
403 }
404
405 if (attribRendererable && attribRendererable[1] == EGL_OPENGL_ES2_BIT &&
406 (!attribCaveat || attribCaveat[1] != EGL_NONE)) {
Jesse Hall47743382013-02-08 11:13:46 -0800407
Romain Guy1cffc802012-10-15 18:13:05 -0700408 // Insert 2 extra attributes to force-enable MSAA 4x
409 EGLint aaAttribs[attribCount + 4];
410 aaAttribs[0] = EGL_SAMPLE_BUFFERS;
411 aaAttribs[1] = 1;
412 aaAttribs[2] = EGL_SAMPLES;
413 aaAttribs[3] = 4;
414
415 memcpy(&aaAttribs[4], attrib_list, attribCount * sizeof(EGLint));
416
417 EGLint numConfigAA;
418 EGLBoolean resAA = cnx->egl.eglChooseConfig(
419 dp->disp.dpy, aaAttribs, configs, config_size, &numConfigAA);
420
421 if (resAA == EGL_TRUE && numConfigAA > 0) {
422 ALOGD("Enabling MSAA 4x");
423 *num_config = numConfigAA;
424 return resAA;
425 }
426 }
427 }
428 }
429
Mathias Agopian7773c432012-02-13 20:06:08 -0800430 res = cnx->egl.eglChooseConfig(
431 dp->disp.dpy, attrib_list, configs, config_size, num_config);
Mathias Agopian518ec112011-05-13 16:21:08 -0700432 }
433 return res;
434}
435
436EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
437 EGLint attribute, EGLint *value)
438{
439 clearError();
440
Jesse Hallb29e5e82012-04-04 16:53:42 -0700441 egl_connection_t* cnx = NULL;
442 const egl_display_ptr dp = validate_display_connection(dpy, cnx);
443 if (!dp) return EGL_FALSE;
Jesse Hall47743382013-02-08 11:13:46 -0800444
Mathias Agopian518ec112011-05-13 16:21:08 -0700445 return cnx->egl.eglGetConfigAttrib(
Mathias Agopian7773c432012-02-13 20:06:08 -0800446 dp->disp.dpy, config, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -0700447}
448
449// ----------------------------------------------------------------------------
450// surfaces
451// ----------------------------------------------------------------------------
452
Jesse Hallc2e41222013-08-08 13:40:22 -0700453// Turn linear formats into corresponding sRGB formats when colorspace is
454// EGL_GL_COLORSPACE_SRGB_KHR, or turn sRGB formats into corresponding linear
455// formats when colorspace is EGL_GL_COLORSPACE_LINEAR_KHR. In any cases where
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800456// the modification isn't possible, the original dataSpace is returned.
Courtney Goeltzenleuchtereeaa52b2017-06-20 08:12:54 -0600457static android_dataspace modifyBufferDataspace(android_dataspace dataSpace,
458 EGLint colorspace) {
Jesse Hallc2e41222013-08-08 13:40:22 -0700459 if (colorspace == EGL_GL_COLORSPACE_LINEAR_KHR) {
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800460 return HAL_DATASPACE_SRGB_LINEAR;
Jesse Hallc2e41222013-08-08 13:40:22 -0700461 } else if (colorspace == EGL_GL_COLORSPACE_SRGB_KHR) {
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800462 return HAL_DATASPACE_SRGB;
Courtney Goeltzenleuchter21b33cb2017-04-17 17:31:29 -0600463 } else if (colorspace == EGL_GL_COLORSPACE_DISPLAY_P3_EXT) {
464 return HAL_DATASPACE_DISPLAY_P3;
465 } else if (colorspace == EGL_GL_COLORSPACE_DISPLAY_P3_LINEAR_EXT) {
466 return HAL_DATASPACE_DISPLAY_P3_LINEAR;
Courtney Goeltzenleuchter33e2b782017-06-23 09:06:52 -0600467 } else if (colorspace == EGL_GL_COLORSPACE_SCRGB_EXT) {
468 return HAL_DATASPACE_V0_SCRGB;
Courtney Goeltzenleuchter21b33cb2017-04-17 17:31:29 -0600469 } else if (colorspace == EGL_GL_COLORSPACE_SCRGB_LINEAR_EXT) {
470 return HAL_DATASPACE_V0_SCRGB_LINEAR;
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700471 } else if (colorspace == EGL_GL_COLORSPACE_BT2020_LINEAR_EXT) {
472 return HAL_DATASPACE_BT2020_LINEAR;
473 } else if (colorspace == EGL_GL_COLORSPACE_BT2020_PQ_EXT) {
474 return HAL_DATASPACE_BT2020_PQ;
Jesse Hallc2e41222013-08-08 13:40:22 -0700475 }
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800476 return dataSpace;
Jesse Hallc2e41222013-08-08 13:40:22 -0700477}
478
Courtney Goeltzenleuchtera1e59f12018-03-05 08:19:25 -0700479// stripAttributes is used by eglCreateWindowSurface, eglCreatePbufferSurface
480// and eglCreatePixmapSurface to clean up color space related Window parameters
481// that a driver does not advertise support for.
482// Return true if stripped_attrib_list has stripped contents.
483
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700484static EGLBoolean stripAttributes(egl_display_ptr dp, const EGLint* attrib_list,
Courtney Goeltzenleuchter786ab882018-01-26 13:37:33 -0800485 EGLint format,
486 std::vector<EGLint>& stripped_attrib_list) {
Courtney Goeltzenleuchtereeaa52b2017-06-20 08:12:54 -0600487 std::vector<EGLint> allowedColorSpaces;
Courtney Goeltzenleuchtera1e59f12018-03-05 08:19:25 -0700488 bool haveColorSpaceSupport = dp->haveExtension("EGL_KHR_gl_colorspace");
Courtney Goeltzenleuchtereeaa52b2017-06-20 08:12:54 -0600489 switch (format) {
490 case HAL_PIXEL_FORMAT_RGBA_8888:
Courtney Goeltzenleuchtera1e59f12018-03-05 08:19:25 -0700491 if (haveColorSpaceSupport) {
492 // Spec says:
493 // [fn1] Only OpenGL and OpenGL ES contexts which support sRGB
494 // rendering must respect requests for EGL_GL_COLORSPACE_SRGB_KHR, and
495 // only to sRGB formats supported by the context (normally just SRGB8)
496 // Older versions not supporting sRGB rendering will ignore this
497 // surface attribute.
498 //
499 // We support sRGB and pixel format is SRGB8, so allow
500 // the EGL_GL_COLORSPACE_SRGB_KHR and
501 // EGL_GL_COLORSPACE_LINEAR_KHR
502 // colorspaces to be specified.
503
504 allowedColorSpaces.push_back(EGL_GL_COLORSPACE_SRGB_KHR);
505 allowedColorSpaces.push_back(EGL_GL_COLORSPACE_LINEAR_KHR);
506 }
507 if (findExtension(dp->disp.queryString.extensions,
508 "EGL_EXT_gl_colorspace_display_p3_linear")) {
509 allowedColorSpaces.push_back(EGL_GL_COLORSPACE_DISPLAY_P3_LINEAR_EXT);
510 }
511 if (findExtension(dp->disp.queryString.extensions,
512 "EGL_EXT_gl_colorspace_display_p3")) {
513 allowedColorSpaces.push_back(EGL_GL_COLORSPACE_DISPLAY_P3_EXT);
514 }
515 if (findExtension(dp->disp.queryString.extensions,
516 "EGL_EXT_gl_colorspace_bt2020_linear")) {
517 allowedColorSpaces.push_back(EGL_GL_COLORSPACE_BT2020_LINEAR_EXT);
518 }
519 if (findExtension(dp->disp.queryString.extensions,
520 "EGL_EXT_gl_colorspace_bt2020_pq")) {
521 allowedColorSpaces.push_back(EGL_GL_COLORSPACE_BT2020_PQ_EXT);
522 }
523 if (findExtension(dp->disp.queryString.extensions,
524 "EGL_EXT_gl_colorspace_scrgb_linear")) {
525 allowedColorSpaces.push_back(EGL_GL_COLORSPACE_SCRGB_LINEAR_EXT);
526 }
Courtney Goeltzenleuchtereeaa52b2017-06-20 08:12:54 -0600527 break;
528
529 case HAL_PIXEL_FORMAT_RGBA_FP16:
530 case HAL_PIXEL_FORMAT_RGBA_1010102:
Courtney Goeltzenleuchtera1e59f12018-03-05 08:19:25 -0700531 case HAL_PIXEL_FORMAT_RGB_565:
Courtney Goeltzenleuchtereeaa52b2017-06-20 08:12:54 -0600532 // Future: if driver supports XXXX extension, we can pass down that colorspace
Courtney Goeltzenleuchtera1e59f12018-03-05 08:19:25 -0700533 default:
Courtney Goeltzenleuchtereeaa52b2017-06-20 08:12:54 -0600534 break;
535 }
536
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700537 if (!attrib_list) return false;
538
Courtney Goeltzenleuchtereeaa52b2017-06-20 08:12:54 -0600539 bool stripped = false;
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700540 for (const EGLint* attr = attrib_list; attr[0] != EGL_NONE; attr += 2) {
541 switch (attr[0]) {
542 case EGL_GL_COLORSPACE_KHR: {
543 EGLint colorSpace = attr[1];
544 bool found = false;
545 // Verify that color space is allowed
546 for (auto it : allowedColorSpaces) {
547 if (colorSpace == it) {
548 found = true;
549 }
550 }
Courtney Goeltzenleuchtera1e59f12018-03-05 08:19:25 -0700551 if (found) {
552 // Found supported attribute
553 stripped_attrib_list.push_back(attr[0]);
554 stripped_attrib_list.push_back(attr[1]);
555 } else if (!haveColorSpaceSupport) {
556 // Device does not support colorspace extension
557 // pass on the attribute and let downstream
558 // components validate like normal
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700559 stripped_attrib_list.push_back(attr[0]);
560 stripped_attrib_list.push_back(attr[1]);
Courtney Goeltzenleuchter52de2fd2018-02-01 09:51:58 -0700561 } else {
Courtney Goeltzenleuchtera1e59f12018-03-05 08:19:25 -0700562 // Found supported attribute that driver does not
563 // support, strip it.
Courtney Goeltzenleuchter52de2fd2018-02-01 09:51:58 -0700564 stripped = true;
Courtney Goeltzenleuchtereeaa52b2017-06-20 08:12:54 -0600565 }
566 }
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700567 break;
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700568 default:
Courtney Goeltzenleuchtereeaa52b2017-06-20 08:12:54 -0600569 stripped_attrib_list.push_back(attr[0]);
570 stripped_attrib_list.push_back(attr[1]);
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700571 break;
Courtney Goeltzenleuchtereeaa52b2017-06-20 08:12:54 -0600572 }
573 }
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700574
575 // Make sure there is at least one attribute
Courtney Goeltzenleuchtereeaa52b2017-06-20 08:12:54 -0600576 if (stripped) {
577 stripped_attrib_list.push_back(EGL_NONE);
Courtney Goeltzenleuchtereeaa52b2017-06-20 08:12:54 -0600578 }
579 return stripped;
580}
581
Courtney Goeltzenleuchtere5d6f992017-07-07 14:55:40 -0600582static EGLBoolean getColorSpaceAttribute(egl_display_ptr dp, NativeWindowType window,
583 const EGLint* attrib_list, EGLint& colorSpace,
584 android_dataspace& dataSpace) {
Courtney Goeltzenleuchter37836572017-04-26 15:07:51 -0600585 colorSpace = EGL_GL_COLORSPACE_LINEAR_KHR;
586 dataSpace = HAL_DATASPACE_UNKNOWN;
Courtney Goeltzenleuchtere5d6f992017-07-07 14:55:40 -0600587
Courtney Goeltzenleuchter37836572017-04-26 15:07:51 -0600588 if (attrib_list && dp->haveExtension("EGL_KHR_gl_colorspace")) {
589 for (const EGLint* attr = attrib_list; *attr != EGL_NONE; attr += 2) {
590 if (*attr == EGL_GL_COLORSPACE_KHR) {
591 colorSpace = attr[1];
592 bool found = false;
Courtney Goeltzenleuchtere5d6f992017-07-07 14:55:40 -0600593 bool verify = true;
Courtney Goeltzenleuchter37836572017-04-26 15:07:51 -0600594 // Verify that color space is allowed
595 if (colorSpace == EGL_GL_COLORSPACE_SRGB_KHR ||
596 colorSpace == EGL_GL_COLORSPACE_LINEAR_KHR) {
Courtney Goeltzenleuchtere5d6f992017-07-07 14:55:40 -0600597 // SRGB and LINEAR are always supported when EGL_KHR_gl_colorspace
598 // is available, so no need to verify.
Courtney Goeltzenleuchter37836572017-04-26 15:07:51 -0600599 found = true;
Courtney Goeltzenleuchtere5d6f992017-07-07 14:55:40 -0600600 verify = false;
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700601 } else if (colorSpace == EGL_GL_COLORSPACE_BT2020_LINEAR_EXT &&
Courtney Goeltzenleuchter37836572017-04-26 15:07:51 -0600602 dp->haveExtension("EGL_EXT_gl_colorspace_bt2020_linear")) {
603 found = true;
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700604 } else if (colorSpace == EGL_GL_COLORSPACE_BT2020_PQ_EXT &&
Courtney Goeltzenleuchter37836572017-04-26 15:07:51 -0600605 dp->haveExtension("EGL_EXT_gl_colorspace_bt2020_pq")) {
606 found = true;
Courtney Goeltzenleuchter33e2b782017-06-23 09:06:52 -0600607 } else if (colorSpace == EGL_GL_COLORSPACE_SCRGB_EXT &&
608 dp->haveExtension("EGL_EXT_gl_colorspace_scrgb")) {
609 found = true;
Courtney Goeltzenleuchter37836572017-04-26 15:07:51 -0600610 } else if (colorSpace == EGL_GL_COLORSPACE_SCRGB_LINEAR_EXT &&
611 dp->haveExtension("EGL_EXT_gl_colorspace_scrgb_linear")) {
612 found = true;
613 } else if (colorSpace == EGL_GL_COLORSPACE_DISPLAY_P3_LINEAR_EXT &&
614 dp->haveExtension("EGL_EXT_gl_colorspace_display_p3_linear")) {
615 found = true;
616 } else if (colorSpace == EGL_GL_COLORSPACE_DISPLAY_P3_EXT &&
617 dp->haveExtension("EGL_EXT_gl_colorspace_display_p3")) {
618 found = true;
619 }
620 if (!found) {
621 return false;
622 }
Courtney Goeltzenleuchtere5d6f992017-07-07 14:55:40 -0600623 if (verify && window) {
624 bool wide_color_support = true;
625 // Ordinarily we'd put a call to native_window_get_wide_color_support
626 // at the beginning of the function so that we'll have the
627 // result when needed elsewhere in the function.
628 // However, because eglCreateWindowSurface is called by SurfaceFlinger and
629 // SurfaceFlinger is required to answer the call below we would
630 // end up in a deadlock situation. By moving the call to only happen
631 // if the application has specifically asked for wide-color we avoid
632 // the deadlock with SurfaceFlinger since it will not ask for a
633 // wide-color surface.
634 int err = native_window_get_wide_color_support(window, &wide_color_support);
635
636 if (err) {
637 ALOGE("getColorSpaceAttribute: invalid window (win=%p) "
638 "failed (%#x) (already connected to another API?)",
639 window, err);
640 return false;
641 }
642 if (!wide_color_support) {
643 // Application has asked for a wide-color colorspace but
644 // wide-color support isn't available on the display the window is on.
645 return false;
646 }
647 }
Courtney Goeltzenleuchter1d4f7a22017-05-05 13:30:25 -0600648 // Only change the dataSpace from default if the application
649 // has explicitly set the color space with a EGL_GL_COLORSPACE_KHR attribute.
650 dataSpace = modifyBufferDataspace(dataSpace, colorSpace);
Courtney Goeltzenleuchter37836572017-04-26 15:07:51 -0600651 }
652 }
Courtney Goeltzenleuchter37836572017-04-26 15:07:51 -0600653 }
654 return true;
655}
656
Courtney Goeltzenleuchtere5d6f992017-07-07 14:55:40 -0600657static EGLBoolean getColorSpaceAttribute(egl_display_ptr dp, const EGLint* attrib_list,
658 EGLint& colorSpace, android_dataspace& dataSpace) {
659 return getColorSpaceAttribute(dp, NULL, attrib_list, colorSpace, dataSpace);
660}
661
Courtney Goeltzenleuchtereeaa52b2017-06-20 08:12:54 -0600662void getNativePixelFormat(EGLDisplay dpy, egl_connection_t* cnx, EGLConfig config, EGLint& format) {
663 // Set the native window's buffers format to match what this config requests.
664 // Whether to use sRGB gamma is not part of the EGLconfig, but is part
665 // of our native format. So if sRGB gamma is requested, we have to
666 // modify the EGLconfig's format before setting the native window's
667 // format.
668
669 EGLint componentType = EGL_COLOR_COMPONENT_TYPE_FIXED_EXT;
670 cnx->egl.eglGetConfigAttrib(dpy, config, EGL_COLOR_COMPONENT_TYPE_EXT, &componentType);
671
672 EGLint a = 0;
673 EGLint r, g, b;
674 r = g = b = 0;
675 cnx->egl.eglGetConfigAttrib(dpy, config, EGL_RED_SIZE, &r);
676 cnx->egl.eglGetConfigAttrib(dpy, config, EGL_GREEN_SIZE, &g);
677 cnx->egl.eglGetConfigAttrib(dpy, config, EGL_BLUE_SIZE, &b);
678 cnx->egl.eglGetConfigAttrib(dpy, config, EGL_ALPHA_SIZE, &a);
679 EGLint colorDepth = r + g + b;
680
681 // Today, the driver only understands sRGB and linear on 888X
682 // formats. Strip other colorspaces from the attribute list and
683 // only use them to set the dataspace via
684 // native_window_set_buffers_dataspace
685 // if pixel format is RGBX 8888
686 // TBD: Can test for future extensions that indicate that driver
687 // handles requested color space and we can let it through.
688 // allow SRGB and LINEAR. All others need to be stripped.
689 // else if 565, 4444
690 // TBD: Can we assume these are supported if 8888 is?
691 // else if FP16 or 1010102
692 // strip colorspace from attribs.
693 // endif
694 if (a == 0) {
695 if (colorDepth <= 16) {
696 format = HAL_PIXEL_FORMAT_RGB_565;
697 } else {
698 if (componentType == EGL_COLOR_COMPONENT_TYPE_FIXED_EXT) {
699 if (colorDepth > 24) {
700 format = HAL_PIXEL_FORMAT_RGBA_1010102;
701 } else {
702 format = HAL_PIXEL_FORMAT_RGBX_8888;
703 }
704 } else {
705 format = HAL_PIXEL_FORMAT_RGBA_FP16;
706 }
707 }
708 } else {
709 if (componentType == EGL_COLOR_COMPONENT_TYPE_FIXED_EXT) {
710 if (colorDepth > 24) {
711 format = HAL_PIXEL_FORMAT_RGBA_1010102;
712 } else {
713 format = HAL_PIXEL_FORMAT_RGBA_8888;
714 }
715 } else {
716 format = HAL_PIXEL_FORMAT_RGBA_FP16;
717 }
718 }
719}
720
Courtney Goeltzenleuchter936799c2018-03-02 16:47:08 -0700721EGLBoolean sendSurfaceMetadata(egl_surface_t* s) {
722 android_smpte2086_metadata smpteMetadata;
723 if (s->getSmpte2086Metadata(smpteMetadata)) {
724 int err =
725 native_window_set_buffers_smpte2086_metadata(s->getNativeWindow(), &smpteMetadata);
726 s->resetSmpte2086Metadata();
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700727 if (err != 0) {
728 ALOGE("error setting native window smpte2086 metadata: %s (%d)",
729 strerror(-err), err);
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700730 return EGL_FALSE;
731 }
732 }
Courtney Goeltzenleuchter936799c2018-03-02 16:47:08 -0700733 android_cta861_3_metadata cta8613Metadata;
734 if (s->getCta8613Metadata(cta8613Metadata)) {
735 int err =
736 native_window_set_buffers_cta861_3_metadata(s->getNativeWindow(), &cta8613Metadata);
737 s->resetCta8613Metadata();
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700738 if (err != 0) {
739 ALOGE("error setting native window CTS 861.3 metadata: %s (%d)",
740 strerror(-err), err);
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700741 return EGL_FALSE;
742 }
743 }
744 return EGL_TRUE;
745}
746
Mathias Agopian518ec112011-05-13 16:21:08 -0700747EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config,
748 NativeWindowType window,
749 const EGLint *attrib_list)
750{
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700751 const EGLint *origAttribList = attrib_list;
Mathias Agopian518ec112011-05-13 16:21:08 -0700752 clearError();
753
Jesse Hallb29e5e82012-04-04 16:53:42 -0700754 egl_connection_t* cnx = NULL;
755 egl_display_ptr dp = validate_display_connection(dpy, cnx);
756 if (dp) {
Mathias Agopianada798b2012-02-13 17:09:30 -0800757 EGLDisplay iDpy = dp->disp.dpy;
Mathias Agopian518ec112011-05-13 16:21:08 -0700758
Mathias Agopian10e9ab52017-03-08 15:02:55 -0800759 if (!window) {
760 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
761 }
762
763 int value = 0;
764 window->query(window, NATIVE_WINDOW_IS_VALID, &value);
765 if (!value) {
766 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
767 }
768
Andy McFaddend566ce32014-01-07 15:54:17 -0800769 int result = native_window_api_connect(window, NATIVE_WINDOW_API_EGL);
Mathias Agopian65421432017-03-08 11:49:05 -0800770 if (result < 0) {
Andy McFaddend566ce32014-01-07 15:54:17 -0800771 ALOGE("eglCreateWindowSurface: native_window_api_connect (win=%p) "
772 "failed (%#x) (already connected to another API?)",
773 window, result);
Jonathan Hamilton77a9b4a2013-07-17 09:41:42 -0700774 return setError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
Mathias Agopian81a63352011-07-29 17:55:48 -0700775 }
776
Mathias Agopian95921562017-02-24 14:31:31 -0800777 EGLint format;
Courtney Goeltzenleuchtereeaa52b2017-06-20 08:12:54 -0600778 getNativePixelFormat(iDpy, cnx, config, format);
779
780 // now select correct colorspace and dataspace based on user's attribute list
Courtney Goeltzenleuchter37836572017-04-26 15:07:51 -0600781 EGLint colorSpace;
782 android_dataspace dataSpace;
Courtney Goeltzenleuchtere5d6f992017-07-07 14:55:40 -0600783 if (!getColorSpaceAttribute(dp, window, attrib_list, colorSpace, dataSpace)) {
Courtney Goeltzenleuchter37836572017-04-26 15:07:51 -0600784 ALOGE("error invalid colorspace: %d", colorSpace);
785 return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700786 }
Alistair Strachan733a8072015-02-12 12:33:25 -0800787
Courtney Goeltzenleuchtereeaa52b2017-06-20 08:12:54 -0600788 std::vector<EGLint> strippedAttribList;
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700789 if (stripAttributes(dp, attrib_list, format, strippedAttribList)) {
Courtney Goeltzenleuchtereeaa52b2017-06-20 08:12:54 -0600790 // Had to modify the attribute list due to use of color space.
791 // Use modified list from here on.
792 attrib_list = strippedAttribList.data();
793 }
794
Jesse Hallc2e41222013-08-08 13:40:22 -0700795 if (format != 0) {
796 int err = native_window_set_buffers_format(window, format);
797 if (err != 0) {
798 ALOGE("error setting native window pixel format: %s (%d)",
799 strerror(-err), err);
800 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
801 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
802 }
803 }
Mathias Agopian518ec112011-05-13 16:21:08 -0700804
Eino-Ville Talvala82c6bcc2015-02-19 16:10:43 -0800805 if (dataSpace != 0) {
806 int err = native_window_set_buffers_data_space(window, dataSpace);
807 if (err != 0) {
808 ALOGE("error setting native window pixel dataSpace: %s (%d)",
809 strerror(-err), err);
810 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
811 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
812 }
813 }
814
Jamie Gennis59769462011-11-19 18:04:43 -0800815 // the EGL spec requires that a new EGLSurface default to swap interval
816 // 1, so explicitly set that on the window here.
817 ANativeWindow* anw = reinterpret_cast<ANativeWindow*>(window);
818 anw->setSwapInterval(anw, 1);
819
Mathias Agopian518ec112011-05-13 16:21:08 -0700820 EGLSurface surface = cnx->egl.eglCreateWindowSurface(
Mathias Agopian7773c432012-02-13 20:06:08 -0800821 iDpy, config, window, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700822 if (surface != EGL_NO_SURFACE) {
Courtney Goeltzenleuchter37836572017-04-26 15:07:51 -0600823 egl_surface_t* s =
824 new egl_surface_t(dp.get(), config, window, surface, colorSpace, cnx);
Courtney Goeltzenleuchtera1e59f12018-03-05 08:19:25 -0700825 return s;
Mathias Agopian518ec112011-05-13 16:21:08 -0700826 }
Mathias Agopian81a63352011-07-29 17:55:48 -0700827
828 // EGLSurface creation failed
829 native_window_set_buffers_format(window, 0);
830 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
Mathias Agopian518ec112011-05-13 16:21:08 -0700831 }
832 return EGL_NO_SURFACE;
833}
834
835EGLSurface eglCreatePixmapSurface( EGLDisplay dpy, EGLConfig config,
836 NativePixmapType pixmap,
837 const EGLint *attrib_list)
838{
839 clearError();
840
Jesse Hallb29e5e82012-04-04 16:53:42 -0700841 egl_connection_t* cnx = NULL;
842 egl_display_ptr dp = validate_display_connection(dpy, cnx);
Courtney Goeltzenleuchter37836572017-04-26 15:07:51 -0600843 EGLint colorSpace;
844 android_dataspace dataSpace;
Jesse Hallb29e5e82012-04-04 16:53:42 -0700845 if (dp) {
Courtney Goeltzenleuchter37836572017-04-26 15:07:51 -0600846 // now select a corresponding sRGB format if needed
847 if (!getColorSpaceAttribute(dp, attrib_list, colorSpace, dataSpace)) {
848 ALOGE("error invalid colorspace: %d", colorSpace);
849 return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
850 }
851
Mathias Agopian518ec112011-05-13 16:21:08 -0700852 EGLSurface surface = cnx->egl.eglCreatePixmapSurface(
Mathias Agopian7773c432012-02-13 20:06:08 -0800853 dp->disp.dpy, config, pixmap, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700854 if (surface != EGL_NO_SURFACE) {
Courtney Goeltzenleuchter37836572017-04-26 15:07:51 -0600855 egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL, surface, colorSpace, cnx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700856 return s;
857 }
858 }
859 return EGL_NO_SURFACE;
860}
861
862EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config,
863 const EGLint *attrib_list)
864{
865 clearError();
866
Jesse Hallb29e5e82012-04-04 16:53:42 -0700867 egl_connection_t* cnx = NULL;
868 egl_display_ptr dp = validate_display_connection(dpy, cnx);
869 if (dp) {
Courtney Goeltzenleuchtereeaa52b2017-06-20 08:12:54 -0600870 EGLDisplay iDpy = dp->disp.dpy;
871 EGLint format;
872 getNativePixelFormat(iDpy, cnx, config, format);
873
874 // now select correct colorspace and dataspace based on user's attribute list
875 EGLint colorSpace;
876 android_dataspace dataSpace;
Courtney Goeltzenleuchter37836572017-04-26 15:07:51 -0600877 if (!getColorSpaceAttribute(dp, attrib_list, colorSpace, dataSpace)) {
878 ALOGE("error invalid colorspace: %d", colorSpace);
879 return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
880 }
881
Courtney Goeltzenleuchtereeaa52b2017-06-20 08:12:54 -0600882 // Pbuffers are not displayed so we don't need to store the
883 // colorspace. We do need to filter out color spaces the
884 // driver doesn't know how to process.
885 std::vector<EGLint> strippedAttribList;
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700886 if (stripAttributes(dp, attrib_list, format, strippedAttribList)) {
Courtney Goeltzenleuchtereeaa52b2017-06-20 08:12:54 -0600887 // Had to modify the attribute list due to use of color space.
888 // Use modified list from here on.
889 attrib_list = strippedAttribList.data();
890 }
891
Mathias Agopian518ec112011-05-13 16:21:08 -0700892 EGLSurface surface = cnx->egl.eglCreatePbufferSurface(
Mathias Agopian7773c432012-02-13 20:06:08 -0800893 dp->disp.dpy, config, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700894 if (surface != EGL_NO_SURFACE) {
Courtney Goeltzenleuchter37836572017-04-26 15:07:51 -0600895 egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL, surface, colorSpace, cnx);
Mathias Agopian518ec112011-05-13 16:21:08 -0700896 return s;
897 }
898 }
899 return EGL_NO_SURFACE;
900}
Jesse Hall47743382013-02-08 11:13:46 -0800901
Mathias Agopian518ec112011-05-13 16:21:08 -0700902EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
903{
904 clearError();
905
Jesse Hallb29e5e82012-04-04 16:53:42 -0700906 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700907 if (!dp) return EGL_FALSE;
908
Jesse Hallb29e5e82012-04-04 16:53:42 -0700909 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700910 if (!_s.get())
Mathias Agopian737b8962017-02-24 14:32:05 -0800911 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700912
913 egl_surface_t * const s = get_surface(surface);
Mathias Agopianada798b2012-02-13 17:09:30 -0800914 EGLBoolean result = s->cnx->egl.eglDestroySurface(dp->disp.dpy, s->surface);
Mathias Agopian518ec112011-05-13 16:21:08 -0700915 if (result == EGL_TRUE) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700916 _s.terminate();
917 }
918 return result;
919}
920
921EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface surface,
922 EGLint attribute, EGLint *value)
923{
924 clearError();
925
Jesse Hallb29e5e82012-04-04 16:53:42 -0700926 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -0700927 if (!dp) return EGL_FALSE;
928
Jesse Hallb29e5e82012-04-04 16:53:42 -0700929 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -0700930 if (!_s.get())
Mathias Agopian737b8962017-02-24 14:32:05 -0800931 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -0700932
Mathias Agopian518ec112011-05-13 16:21:08 -0700933 egl_surface_t const * const s = get_surface(surface);
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700934 if (s->getColorSpaceAttribute(attribute, value)) {
935 return EGL_TRUE;
936 } else if (s->getSmpte2086Attribute(attribute, value)) {
937 return EGL_TRUE;
938 } else if (s->getCta8613Attribute(attribute, value)) {
Courtney Goeltzenleuchter37836572017-04-26 15:07:51 -0600939 return EGL_TRUE;
940 }
Courtney Goeltzenleuchter12ffe092017-11-16 14:27:48 -0700941 return s->cnx->egl.eglQuerySurface(dp->disp.dpy, s->surface, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -0700942}
943
Jamie Gennise8696a42012-01-15 18:54:57 -0800944void EGLAPI eglBeginFrame(EGLDisplay dpy, EGLSurface surface) {
Jamie Gennis1c8e95c2012-02-23 19:27:23 -0800945 ATRACE_CALL();
Jamie Gennise8696a42012-01-15 18:54:57 -0800946 clearError();
947
Jesse Hallb29e5e82012-04-04 16:53:42 -0700948 const egl_display_ptr dp = validate_display(dpy);
Jamie Gennise8696a42012-01-15 18:54:57 -0800949 if (!dp) {
950 return;
951 }
952
Jesse Hallb29e5e82012-04-04 16:53:42 -0700953 SurfaceRef _s(dp.get(), surface);
Jamie Gennise8696a42012-01-15 18:54:57 -0800954 if (!_s.get()) {
955 setError(EGL_BAD_SURFACE, EGL_FALSE);
Jamie Gennise8696a42012-01-15 18:54:57 -0800956 }
Jamie Gennise8696a42012-01-15 18:54:57 -0800957}
958
Mathias Agopian518ec112011-05-13 16:21:08 -0700959// ----------------------------------------------------------------------------
960// Contexts
961// ----------------------------------------------------------------------------
962
963EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config,
964 EGLContext share_list, const EGLint *attrib_list)
965{
966 clearError();
967
Jesse Hallb29e5e82012-04-04 16:53:42 -0700968 egl_connection_t* cnx = NULL;
969 const egl_display_ptr dp = validate_display_connection(dpy, cnx);
Michael Chock0673e1e2012-06-21 12:53:17 -0700970 if (dp) {
Mathias Agopian518ec112011-05-13 16:21:08 -0700971 if (share_list != EGL_NO_CONTEXT) {
Michael Chock0673e1e2012-06-21 12:53:17 -0700972 if (!ContextRef(dp.get(), share_list).get()) {
973 return setError(EGL_BAD_CONTEXT, EGL_NO_CONTEXT);
974 }
Mathias Agopian518ec112011-05-13 16:21:08 -0700975 egl_context_t* const c = get_context(share_list);
976 share_list = c->context;
977 }
978 EGLContext context = cnx->egl.eglCreateContext(
Mathias Agopian7773c432012-02-13 20:06:08 -0800979 dp->disp.dpy, config, share_list, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -0700980 if (context != EGL_NO_CONTEXT) {
981 // figure out if it's a GLESv1 or GLESv2
982 int version = 0;
983 if (attrib_list) {
984 while (*attrib_list != EGL_NONE) {
985 GLint attr = *attrib_list++;
986 GLint value = *attrib_list++;
987 if (attr == EGL_CONTEXT_CLIENT_VERSION) {
988 if (value == 1) {
Mathias Agopian7773c432012-02-13 20:06:08 -0800989 version = egl_connection_t::GLESv1_INDEX;
Jesse Hall47743382013-02-08 11:13:46 -0800990 } else if (value == 2 || value == 3) {
Mathias Agopian7773c432012-02-13 20:06:08 -0800991 version = egl_connection_t::GLESv2_INDEX;
Mathias Agopian518ec112011-05-13 16:21:08 -0700992 }
993 }
994 };
995 }
Jesse Hallb29e5e82012-04-04 16:53:42 -0700996 egl_context_t* c = new egl_context_t(dpy, context, config, cnx,
997 version);
Mathias Agopian518ec112011-05-13 16:21:08 -0700998 return c;
999 }
1000 }
1001 return EGL_NO_CONTEXT;
1002}
1003
1004EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
1005{
1006 clearError();
1007
Jesse Hallb29e5e82012-04-04 16:53:42 -07001008 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001009 if (!dp)
1010 return EGL_FALSE;
Mathias Agopian518ec112011-05-13 16:21:08 -07001011
Jesse Hallb29e5e82012-04-04 16:53:42 -07001012 ContextRef _c(dp.get(), ctx);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001013 if (!_c.get())
Mathias Agopian737b8962017-02-24 14:32:05 -08001014 return setError(EGL_BAD_CONTEXT, (EGLBoolean)EGL_FALSE);
Jesse Hall47743382013-02-08 11:13:46 -08001015
Mathias Agopian518ec112011-05-13 16:21:08 -07001016 egl_context_t * const c = get_context(ctx);
Mathias Agopianada798b2012-02-13 17:09:30 -08001017 EGLBoolean result = c->cnx->egl.eglDestroyContext(dp->disp.dpy, c->context);
Mathias Agopian518ec112011-05-13 16:21:08 -07001018 if (result == EGL_TRUE) {
1019 _c.terminate();
1020 }
1021 return result;
1022}
1023
Mathias Agopian518ec112011-05-13 16:21:08 -07001024EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw,
1025 EGLSurface read, EGLContext ctx)
1026{
1027 clearError();
1028
Jesse Hallb29e5e82012-04-04 16:53:42 -07001029 egl_display_ptr dp = validate_display(dpy);
Mathias Agopian737b8962017-02-24 14:32:05 -08001030 if (!dp) return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001031
Mathias Agopian5b287a62011-05-16 18:58:55 -07001032 // If ctx is not EGL_NO_CONTEXT, read is not EGL_NO_SURFACE, or draw is not
1033 // EGL_NO_SURFACE, then an EGL_NOT_INITIALIZED error is generated if dpy is
1034 // a valid but uninitialized display.
Mathias Agopian518ec112011-05-13 16:21:08 -07001035 if ( (ctx != EGL_NO_CONTEXT) || (read != EGL_NO_SURFACE) ||
1036 (draw != EGL_NO_SURFACE) ) {
Mathias Agopian737b8962017-02-24 14:32:05 -08001037 if (!dp->isReady()) return setError(EGL_NOT_INITIALIZED, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001038 }
1039
1040 // get a reference to the object passed in
Jesse Hallb29e5e82012-04-04 16:53:42 -07001041 ContextRef _c(dp.get(), ctx);
1042 SurfaceRef _d(dp.get(), draw);
1043 SurfaceRef _r(dp.get(), read);
Mathias Agopian518ec112011-05-13 16:21:08 -07001044
1045 // validate the context (if not EGL_NO_CONTEXT)
Mathias Agopian5b287a62011-05-16 18:58:55 -07001046 if ((ctx != EGL_NO_CONTEXT) && !_c.get()) {
Mathias Agopian518ec112011-05-13 16:21:08 -07001047 // EGL_NO_CONTEXT is valid
Mathias Agopian737b8962017-02-24 14:32:05 -08001048 return setError(EGL_BAD_CONTEXT, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001049 }
1050
1051 // these are the underlying implementation's object
1052 EGLContext impl_ctx = EGL_NO_CONTEXT;
1053 EGLSurface impl_draw = EGL_NO_SURFACE;
1054 EGLSurface impl_read = EGL_NO_SURFACE;
1055
1056 // these are our objects structs passed in
1057 egl_context_t * c = NULL;
1058 egl_surface_t const * d = NULL;
1059 egl_surface_t const * r = NULL;
1060
1061 // these are the current objects structs
1062 egl_context_t * cur_c = get_context(getContext());
Jesse Hall47743382013-02-08 11:13:46 -08001063
Mathias Agopian518ec112011-05-13 16:21:08 -07001064 if (ctx != EGL_NO_CONTEXT) {
1065 c = get_context(ctx);
1066 impl_ctx = c->context;
1067 } else {
1068 // no context given, use the implementation of the current context
Michael Chock0673e1e2012-06-21 12:53:17 -07001069 if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE) {
1070 // calling eglMakeCurrent( ..., !=0, !=0, EGL_NO_CONTEXT);
Mathias Agopian737b8962017-02-24 14:32:05 -08001071 return setError(EGL_BAD_MATCH, (EGLBoolean)EGL_FALSE);
Michael Chock0673e1e2012-06-21 12:53:17 -07001072 }
Mathias Agopian518ec112011-05-13 16:21:08 -07001073 if (cur_c == NULL) {
1074 // no current context
Mathias Agopian518ec112011-05-13 16:21:08 -07001075 // not an error, there is just no current context.
1076 return EGL_TRUE;
1077 }
1078 }
1079
1080 // retrieve the underlying implementation's draw EGLSurface
1081 if (draw != EGL_NO_SURFACE) {
Mathias Agopian737b8962017-02-24 14:32:05 -08001082 if (!_d.get()) return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001083 d = get_surface(draw);
Mathias Agopian518ec112011-05-13 16:21:08 -07001084 impl_draw = d->surface;
1085 }
1086
1087 // retrieve the underlying implementation's read EGLSurface
1088 if (read != EGL_NO_SURFACE) {
Mathias Agopian737b8962017-02-24 14:32:05 -08001089 if (!_r.get()) return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001090 r = get_surface(read);
Mathias Agopian518ec112011-05-13 16:21:08 -07001091 impl_read = r->surface;
1092 }
1093
Mathias Agopian518ec112011-05-13 16:21:08 -07001094
Jesse Hallb29e5e82012-04-04 16:53:42 -07001095 EGLBoolean result = dp->makeCurrent(c, cur_c,
Mathias Agopianfb87e542012-01-30 18:20:52 -08001096 draw, read, ctx,
1097 impl_draw, impl_read, impl_ctx);
Mathias Agopian518ec112011-05-13 16:21:08 -07001098
1099 if (result == EGL_TRUE) {
Mathias Agopianfb87e542012-01-30 18:20:52 -08001100 if (c) {
Mathias Agopian518ec112011-05-13 16:21:08 -07001101 setGLHooksThreadSpecific(c->cnx->hooks[c->version]);
1102 egl_tls_t::setContext(ctx);
Mathias Agopian518ec112011-05-13 16:21:08 -07001103 _c.acquire();
1104 _r.acquire();
1105 _d.acquire();
Mathias Agopian518ec112011-05-13 16:21:08 -07001106 } else {
1107 setGLHooksThreadSpecific(&gHooksNoContext);
1108 egl_tls_t::setContext(EGL_NO_CONTEXT);
1109 }
Mathias Agopian5fecea72011-08-25 18:38:24 -07001110 } else {
Mike Stroyan02ba5c72017-05-08 10:47:24 -06001111
Mike Stroyan47e741b2017-06-01 13:56:18 -06001112 if (cur_c != NULL) {
1113 // Force return to current context for drivers that cannot handle errors
1114 EGLBoolean restore_result = EGL_FALSE;
1115 // get a reference to the old current objects
1116 ContextRef _c2(dp.get(), cur_c);
1117 SurfaceRef _d2(dp.get(), cur_c->draw);
1118 SurfaceRef _r2(dp.get(), cur_c->read);
Mike Stroyan02ba5c72017-05-08 10:47:24 -06001119
Mike Stroyan02ba5c72017-05-08 10:47:24 -06001120 c = cur_c;
1121 impl_ctx = c->context;
1122 impl_draw = EGL_NO_SURFACE;
1123 if (cur_c->draw != EGL_NO_SURFACE) {
1124 d = get_surface(cur_c->draw);
1125 impl_draw = d->surface;
1126 }
1127 impl_read = EGL_NO_SURFACE;
1128 if (cur_c->read != EGL_NO_SURFACE) {
1129 r = get_surface(cur_c->read);
1130 impl_read = r->surface;
1131 }
1132 restore_result = dp->makeCurrent(c, cur_c,
1133 cur_c->draw, cur_c->read, cur_c->context,
1134 impl_draw, impl_read, impl_ctx);
Mike Stroyan47e741b2017-06-01 13:56:18 -06001135 if (restore_result == EGL_TRUE) {
1136 _c2.acquire();
1137 _r2.acquire();
1138 _d2.acquire();
1139 } else {
1140 ALOGE("Could not restore original EGL context");
1141 }
Mike Stroyan02ba5c72017-05-08 10:47:24 -06001142 }
Steve Blocke6f43dd2012-01-06 19:20:56 +00001143 // this will ALOGE the error
Mathias Agopian63108c32013-09-06 13:36:49 -07001144 egl_connection_t* const cnx = &gEGLImpl;
Mathias Agopian737b8962017-02-24 14:32:05 -08001145 result = setError(cnx->egl.eglGetError(), (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001146 }
1147 return result;
1148}
1149
1150
1151EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx,
1152 EGLint attribute, EGLint *value)
1153{
1154 clearError();
1155
Jesse Hallb29e5e82012-04-04 16:53:42 -07001156 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001157 if (!dp) return EGL_FALSE;
1158
Jesse Hallb29e5e82012-04-04 16:53:42 -07001159 ContextRef _c(dp.get(), ctx);
Mathias Agopian737b8962017-02-24 14:32:05 -08001160 if (!_c.get()) return setError(EGL_BAD_CONTEXT, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001161
Mathias Agopian518ec112011-05-13 16:21:08 -07001162 egl_context_t * const c = get_context(ctx);
Mathias Agopian7773c432012-02-13 20:06:08 -08001163 return c->cnx->egl.eglQueryContext(
1164 dp->disp.dpy, c->context, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -07001165
Mathias Agopian518ec112011-05-13 16:21:08 -07001166}
1167
1168EGLContext eglGetCurrentContext(void)
1169{
1170 // could be called before eglInitialize(), but we wouldn't have a context
1171 // then, and this function would correctly return EGL_NO_CONTEXT.
1172
1173 clearError();
1174
1175 EGLContext ctx = getContext();
1176 return ctx;
1177}
1178
1179EGLSurface eglGetCurrentSurface(EGLint readdraw)
1180{
1181 // could be called before eglInitialize(), but we wouldn't have a context
1182 // then, and this function would correctly return EGL_NO_SURFACE.
1183
1184 clearError();
1185
1186 EGLContext ctx = getContext();
1187 if (ctx) {
1188 egl_context_t const * const c = get_context(ctx);
1189 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
1190 switch (readdraw) {
1191 case EGL_READ: return c->read;
Jesse Hall47743382013-02-08 11:13:46 -08001192 case EGL_DRAW: return c->draw;
Mathias Agopian518ec112011-05-13 16:21:08 -07001193 default: return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
1194 }
1195 }
1196 return EGL_NO_SURFACE;
1197}
1198
1199EGLDisplay eglGetCurrentDisplay(void)
1200{
1201 // could be called before eglInitialize(), but we wouldn't have a context
1202 // then, and this function would correctly return EGL_NO_DISPLAY.
1203
1204 clearError();
1205
1206 EGLContext ctx = getContext();
1207 if (ctx) {
1208 egl_context_t const * const c = get_context(ctx);
1209 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
1210 return c->dpy;
1211 }
1212 return EGL_NO_DISPLAY;
1213}
1214
1215EGLBoolean eglWaitGL(void)
1216{
Mathias Agopian518ec112011-05-13 16:21:08 -07001217 clearError();
1218
Mathias Agopianada798b2012-02-13 17:09:30 -08001219 egl_connection_t* const cnx = &gEGLImpl;
1220 if (!cnx->dso)
Mathias Agopian737b8962017-02-24 14:32:05 -08001221 return setError(EGL_BAD_CONTEXT, (EGLBoolean)EGL_FALSE);
Mathias Agopianada798b2012-02-13 17:09:30 -08001222
1223 return cnx->egl.eglWaitGL();
Mathias Agopian518ec112011-05-13 16:21:08 -07001224}
1225
1226EGLBoolean eglWaitNative(EGLint engine)
1227{
Mathias Agopian518ec112011-05-13 16:21:08 -07001228 clearError();
1229
Mathias Agopianada798b2012-02-13 17:09:30 -08001230 egl_connection_t* const cnx = &gEGLImpl;
1231 if (!cnx->dso)
Mathias Agopian737b8962017-02-24 14:32:05 -08001232 return setError(EGL_BAD_CONTEXT, (EGLBoolean)EGL_FALSE);
Mathias Agopianada798b2012-02-13 17:09:30 -08001233
1234 return cnx->egl.eglWaitNative(engine);
Mathias Agopian518ec112011-05-13 16:21:08 -07001235}
1236
1237EGLint eglGetError(void)
1238{
Mathias Agopianada798b2012-02-13 17:09:30 -08001239 EGLint err = EGL_SUCCESS;
1240 egl_connection_t* const cnx = &gEGLImpl;
1241 if (cnx->dso) {
1242 err = cnx->egl.eglGetError();
Mathias Agopian518ec112011-05-13 16:21:08 -07001243 }
Mathias Agopianada798b2012-02-13 17:09:30 -08001244 if (err == EGL_SUCCESS) {
1245 err = egl_tls_t::getError();
1246 }
1247 return err;
Mathias Agopian518ec112011-05-13 16:21:08 -07001248}
1249
Michael Chockc0ec5e22014-01-27 08:14:33 -08001250static __eglMustCastToProperFunctionPointerType findBuiltinWrapper(
Jesse Hallc07b5202013-07-04 12:08:16 -07001251 const char* procname) {
1252 const egl_connection_t* cnx = &gEGLImpl;
1253 void* proc = NULL;
1254
Michael Chockc0ec5e22014-01-27 08:14:33 -08001255 proc = dlsym(cnx->libEgl, procname);
1256 if (proc) return (__eglMustCastToProperFunctionPointerType)proc;
1257
Jesse Hallc07b5202013-07-04 12:08:16 -07001258 proc = dlsym(cnx->libGles2, procname);
1259 if (proc) return (__eglMustCastToProperFunctionPointerType)proc;
1260
1261 proc = dlsym(cnx->libGles1, procname);
1262 if (proc) return (__eglMustCastToProperFunctionPointerType)proc;
1263
1264 return NULL;
1265}
1266
Mathias Agopian518ec112011-05-13 16:21:08 -07001267__eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
1268{
1269 // eglGetProcAddress() could be the very first function called
1270 // in which case we must make sure we've initialized ourselves, this
1271 // happens the first time egl_get_display() is called.
1272
1273 clearError();
1274
1275 if (egl_init_drivers() == EGL_FALSE) {
1276 setError(EGL_BAD_PARAMETER, NULL);
1277 return NULL;
1278 }
1279
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -07001280 if (FILTER_EXTENSIONS(procname)) {
Jamie Gennisaca51c02011-11-03 17:42:43 -07001281 return NULL;
1282 }
1283
Mathias Agopian518ec112011-05-13 16:21:08 -07001284 __eglMustCastToProperFunctionPointerType addr;
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -07001285 addr = findProcAddress(procname, sExtensionMap, NELEM(sExtensionMap));
Mathias Agopian518ec112011-05-13 16:21:08 -07001286 if (addr) return addr;
1287
Michael Chockc0ec5e22014-01-27 08:14:33 -08001288 addr = findBuiltinWrapper(procname);
Jesse Hallc07b5202013-07-04 12:08:16 -07001289 if (addr) return addr;
Jamie Gennisaca51c02011-11-03 17:42:43 -07001290
Mathias Agopian518ec112011-05-13 16:21:08 -07001291 // this protects accesses to sGLExtentionMap and sGLExtentionSlot
1292 pthread_mutex_lock(&sExtensionMapMutex);
1293
1294 /*
1295 * Since eglGetProcAddress() is not associated to anything, it needs
1296 * to return a function pointer that "works" regardless of what
1297 * the current context is.
1298 *
1299 * For this reason, we return a "forwarder", a small stub that takes
1300 * care of calling the function associated with the context
1301 * currently bound.
1302 *
1303 * We first look for extensions we've already resolved, if we're seeing
1304 * this extension for the first time, we go through all our
1305 * implementations and call eglGetProcAddress() and record the
1306 * result in the appropriate implementation hooks and return the
1307 * address of the forwarder corresponding to that hook set.
1308 *
1309 */
1310
Mathias Agopian65421432017-03-08 11:49:05 -08001311 const std::string name(procname);
1312
1313 auto& extentionMap = sGLExtentionMap;
1314 auto pos = extentionMap.find(name);
1315 addr = (pos != extentionMap.end()) ? pos->second : nullptr;
Mathias Agopian518ec112011-05-13 16:21:08 -07001316 const int slot = sGLExtentionSlot;
1317
Steve Blocke6f43dd2012-01-06 19:20:56 +00001318 ALOGE_IF(slot >= MAX_NUMBER_OF_GL_EXTENSIONS,
Mathias Agopian518ec112011-05-13 16:21:08 -07001319 "no more slots for eglGetProcAddress(\"%s\")",
1320 procname);
1321
1322 if (!addr && (slot < MAX_NUMBER_OF_GL_EXTENSIONS)) {
1323 bool found = false;
Mathias Agopianada798b2012-02-13 17:09:30 -08001324
1325 egl_connection_t* const cnx = &gEGLImpl;
1326 if (cnx->dso && cnx->egl.eglGetProcAddress) {
Mathias Agopianada798b2012-02-13 17:09:30 -08001327 // Extensions are independent of the bound context
luliuhui69d10072012-08-30 11:15:36 +08001328 addr =
Mathias Agopian7773c432012-02-13 20:06:08 -08001329 cnx->hooks[egl_connection_t::GLESv1_INDEX]->ext.extensions[slot] =
1330 cnx->hooks[egl_connection_t::GLESv2_INDEX]->ext.extensions[slot] =
Mathias Agopianada798b2012-02-13 17:09:30 -08001331 cnx->egl.eglGetProcAddress(procname);
luliuhui69d10072012-08-30 11:15:36 +08001332 if (addr) found = true;
Mathias Agopian518ec112011-05-13 16:21:08 -07001333 }
Mathias Agopianada798b2012-02-13 17:09:30 -08001334
Mathias Agopian518ec112011-05-13 16:21:08 -07001335 if (found) {
1336 addr = gExtensionForwarders[slot];
Mathias Agopian65421432017-03-08 11:49:05 -08001337 extentionMap[name] = addr;
Mathias Agopian518ec112011-05-13 16:21:08 -07001338 sGLExtentionSlot++;
1339 }
1340 }
1341
1342 pthread_mutex_unlock(&sExtensionMapMutex);
1343 return addr;
1344}
1345
Mathias Agopian65421432017-03-08 11:49:05 -08001346class FrameCompletionThread {
Jamie Gennis28ef8d72012-04-05 20:34:54 -07001347public:
1348
1349 static void queueSync(EGLSyncKHR sync) {
Mathias Agopian65421432017-03-08 11:49:05 -08001350 static FrameCompletionThread thread;
1351
1352 char name[64];
1353
1354 std::lock_guard<std::mutex> lock(thread.mMutex);
1355 snprintf(name, sizeof(name), "kicked off frame %u", (unsigned int)thread.mFramesQueued);
1356 ATRACE_NAME(name);
1357
1358 thread.mQueue.push_back(sync);
1359 thread.mCondition.notify_one();
1360 thread.mFramesQueued++;
1361 ATRACE_INT("GPU Frames Outstanding", int32_t(thread.mQueue.size()));
Jamie Gennis28ef8d72012-04-05 20:34:54 -07001362 }
1363
1364private:
Jamie Gennis28ef8d72012-04-05 20:34:54 -07001365
Mathias Agopian65421432017-03-08 11:49:05 -08001366 FrameCompletionThread() : mFramesQueued(0), mFramesCompleted(0) {
1367 std::thread thread(&FrameCompletionThread::loop, this);
1368 thread.detach();
1369 }
1370
1371#pragma clang diagnostic push
1372#pragma clang diagnostic ignored "-Wmissing-noreturn"
1373 void loop() {
1374 while (true) {
1375 threadLoop();
1376 }
1377 }
1378#pragma clang diagnostic pop
1379
1380 void threadLoop() {
Jamie Gennis28ef8d72012-04-05 20:34:54 -07001381 EGLSyncKHR sync;
1382 uint32_t frameNum;
1383 {
Mathias Agopian65421432017-03-08 11:49:05 -08001384 std::unique_lock<std::mutex> lock(mMutex);
1385 while (mQueue.empty()) {
1386 mCondition.wait(lock);
Jamie Gennis28ef8d72012-04-05 20:34:54 -07001387 }
1388 sync = mQueue[0];
1389 frameNum = mFramesCompleted;
1390 }
1391 EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
1392 {
Mathias Agopian65421432017-03-08 11:49:05 -08001393 char name[64];
1394 snprintf(name, sizeof(name), "waiting for frame %u", (unsigned int)frameNum);
1395 ATRACE_NAME(name);
1396
Jamie Gennis28ef8d72012-04-05 20:34:54 -07001397 EGLint result = eglClientWaitSyncKHR(dpy, sync, 0, EGL_FOREVER_KHR);
1398 if (result == EGL_FALSE) {
1399 ALOGE("FrameCompletion: error waiting for fence: %#x", eglGetError());
1400 } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
1401 ALOGE("FrameCompletion: timeout waiting for fence");
1402 }
1403 eglDestroySyncKHR(dpy, sync);
1404 }
1405 {
Mathias Agopian65421432017-03-08 11:49:05 -08001406 std::lock_guard<std::mutex> lock(mMutex);
1407 mQueue.pop_front();
Jamie Gennis28ef8d72012-04-05 20:34:54 -07001408 mFramesCompleted++;
Mathias Agopian737b8962017-02-24 14:32:05 -08001409 ATRACE_INT("GPU Frames Outstanding", int32_t(mQueue.size()));
Jamie Gennis28ef8d72012-04-05 20:34:54 -07001410 }
Jamie Gennis28ef8d72012-04-05 20:34:54 -07001411 }
1412
1413 uint32_t mFramesQueued;
1414 uint32_t mFramesCompleted;
Mathias Agopian65421432017-03-08 11:49:05 -08001415 std::deque<EGLSyncKHR> mQueue;
1416 std::condition_variable mCondition;
1417 std::mutex mMutex;
Jamie Gennis28ef8d72012-04-05 20:34:54 -07001418};
1419
Dan Stozaa894d082015-02-19 15:27:36 -08001420EGLBoolean eglSwapBuffersWithDamageKHR(EGLDisplay dpy, EGLSurface draw,
1421 EGLint *rects, EGLint n_rects)
Mathias Agopian518ec112011-05-13 16:21:08 -07001422{
Jamie Gennis1c8e95c2012-02-23 19:27:23 -08001423 ATRACE_CALL();
Mathias Agopian518ec112011-05-13 16:21:08 -07001424 clearError();
1425
Jesse Hallb29e5e82012-04-04 16:53:42 -07001426 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001427 if (!dp) return EGL_FALSE;
1428
Jesse Hallb29e5e82012-04-04 16:53:42 -07001429 SurfaceRef _s(dp.get(), draw);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001430 if (!_s.get())
Mathias Agopian737b8962017-02-24 14:32:05 -08001431 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001432
Courtney Goeltzenleuchter936799c2018-03-02 16:47:08 -07001433 egl_surface_t* const s = get_surface(draw);
Mathias Agopian7db993a2012-03-25 00:49:46 -07001434
Mathias Agopianed6d08b2013-04-16 16:39:46 -07001435 if (CC_UNLIKELY(dp->traceGpuCompletion)) {
1436 EGLSyncKHR sync = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, NULL);
1437 if (sync != EGL_NO_SYNC_KHR) {
1438 FrameCompletionThread::queueSync(sync);
1439 }
1440 }
1441
Mathias Agopian7db993a2012-03-25 00:49:46 -07001442 if (CC_UNLIKELY(dp->finishOnSwap)) {
1443 uint32_t pixel;
1444 egl_context_t * const c = get_context( egl_tls_t::getContext() );
1445 if (c) {
1446 // glReadPixels() ensures that the frame is complete
1447 s->cnx->hooks[c->version]->gl.glReadPixels(0,0,1,1,
1448 GL_RGBA,GL_UNSIGNED_BYTE,&pixel);
1449 }
1450 }
1451
Courtney Goeltzenleuchter936799c2018-03-02 16:47:08 -07001452 if (!sendSurfaceMetadata(s)) {
1453 native_window_api_disconnect(s->getNativeWindow(), NATIVE_WINDOW_API_EGL);
1454 return setError(EGL_BAD_NATIVE_WINDOW, (EGLBoolean)EGL_FALSE);
1455 }
1456
Dan Stozaa894d082015-02-19 15:27:36 -08001457 if (n_rects == 0) {
1458 return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface);
1459 }
1460
Mathias Agopian65421432017-03-08 11:49:05 -08001461 std::vector<android_native_rect_t> androidRects((size_t)n_rects);
Dan Stozaa894d082015-02-19 15:27:36 -08001462 for (int r = 0; r < n_rects; ++r) {
1463 int offset = r * 4;
1464 int x = rects[offset];
1465 int y = rects[offset + 1];
1466 int width = rects[offset + 2];
1467 int height = rects[offset + 3];
1468 android_native_rect_t androidRect;
1469 androidRect.left = x;
1470 androidRect.top = y + height;
1471 androidRect.right = x + width;
1472 androidRect.bottom = y;
1473 androidRects.push_back(androidRect);
1474 }
Mathias Agopian65421432017-03-08 11:49:05 -08001475 native_window_set_surface_damage(s->getNativeWindow(), androidRects.data(), androidRects.size());
Dan Stozaa894d082015-02-19 15:27:36 -08001476
1477 if (s->cnx->egl.eglSwapBuffersWithDamageKHR) {
1478 return s->cnx->egl.eglSwapBuffersWithDamageKHR(dp->disp.dpy, s->surface,
1479 rects, n_rects);
1480 } else {
1481 return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface);
1482 }
1483}
1484
1485EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
1486{
1487 return eglSwapBuffersWithDamageKHR(dpy, surface, NULL, 0);
Mathias Agopian518ec112011-05-13 16:21:08 -07001488}
1489
1490EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface,
1491 NativePixmapType target)
1492{
1493 clearError();
1494
Jesse Hallb29e5e82012-04-04 16:53:42 -07001495 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001496 if (!dp) return EGL_FALSE;
1497
Jesse Hallb29e5e82012-04-04 16:53:42 -07001498 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001499 if (!_s.get())
Mathias Agopian737b8962017-02-24 14:32:05 -08001500 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001501
Mathias Agopian518ec112011-05-13 16:21:08 -07001502 egl_surface_t const * const s = get_surface(surface);
Mathias Agopianada798b2012-02-13 17:09:30 -08001503 return s->cnx->egl.eglCopyBuffers(dp->disp.dpy, s->surface, target);
Mathias Agopian518ec112011-05-13 16:21:08 -07001504}
1505
1506const char* eglQueryString(EGLDisplay dpy, EGLint name)
1507{
1508 clearError();
1509
Chia-I Wue57d1352016-08-15 16:10:02 +08001510 // Generate an error quietly when client extensions (as defined by
1511 // EGL_EXT_client_extensions) are queried. We do not want to rely on
1512 // validate_display to generate the error as validate_display would log
1513 // the error, which can be misleading.
1514 //
1515 // If we want to support EGL_EXT_client_extensions later, we can return
1516 // the client extension string here instead.
1517 if (dpy == EGL_NO_DISPLAY && name == EGL_EXTENSIONS)
Mathias Agopian737b8962017-02-24 14:32:05 -08001518 return setErrorQuiet(EGL_BAD_DISPLAY, (const char*)0);
Chia-I Wue57d1352016-08-15 16:10:02 +08001519
Jesse Hallb29e5e82012-04-04 16:53:42 -07001520 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001521 if (!dp) return (const char *) NULL;
1522
1523 switch (name) {
1524 case EGL_VENDOR:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001525 return dp->getVendorString();
Mathias Agopian518ec112011-05-13 16:21:08 -07001526 case EGL_VERSION:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001527 return dp->getVersionString();
Mathias Agopian518ec112011-05-13 16:21:08 -07001528 case EGL_EXTENSIONS:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001529 return dp->getExtensionString();
Mathias Agopian518ec112011-05-13 16:21:08 -07001530 case EGL_CLIENT_APIS:
Mathias Agopian4b9511c2011-11-13 23:52:47 -08001531 return dp->getClientApiString();
Mathias Agopian737b8962017-02-24 14:32:05 -08001532 default:
1533 break;
Mathias Agopian518ec112011-05-13 16:21:08 -07001534 }
1535 return setError(EGL_BAD_PARAMETER, (const char *)0);
1536}
1537
Jiyong Park00b15b82017-08-10 20:30:56 +09001538extern "C" EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name)
Mathias Agopianca088332013-03-28 17:44:13 -07001539{
1540 clearError();
1541
1542 const egl_display_ptr dp = validate_display(dpy);
1543 if (!dp) return (const char *) NULL;
1544
1545 switch (name) {
1546 case EGL_VENDOR:
1547 return dp->disp.queryString.vendor;
1548 case EGL_VERSION:
1549 return dp->disp.queryString.version;
1550 case EGL_EXTENSIONS:
1551 return dp->disp.queryString.extensions;
1552 case EGL_CLIENT_APIS:
1553 return dp->disp.queryString.clientApi;
Mathias Agopian737b8962017-02-24 14:32:05 -08001554 default:
1555 break;
Mathias Agopianca088332013-03-28 17:44:13 -07001556 }
1557 return setError(EGL_BAD_PARAMETER, (const char *)0);
1558}
Mathias Agopian518ec112011-05-13 16:21:08 -07001559
1560// ----------------------------------------------------------------------------
1561// EGL 1.1
1562// ----------------------------------------------------------------------------
1563
1564EGLBoolean eglSurfaceAttrib(
1565 EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
1566{
1567 clearError();
1568
Jesse Hallb29e5e82012-04-04 16:53:42 -07001569 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001570 if (!dp) return EGL_FALSE;
1571
Jesse Hallb29e5e82012-04-04 16:53:42 -07001572 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001573 if (!_s.get())
Mathias Agopian737b8962017-02-24 14:32:05 -08001574 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001575
Pablo Ceballosc18be292016-05-31 14:55:42 -07001576 egl_surface_t * const s = get_surface(surface);
Pablo Ceballosccdfd602015-10-07 15:05:45 -07001577
Pablo Ceballos02b05da2016-02-02 17:53:18 -08001578 if (attribute == EGL_FRONT_BUFFER_AUTO_REFRESH_ANDROID) {
Mathias Agopian65421432017-03-08 11:49:05 -08001579 if (!s->getNativeWindow()) {
Brian Anderson069b3652016-07-22 10:32:47 -07001580 setError(EGL_BAD_SURFACE, EGL_FALSE);
1581 }
Mathias Agopian65421432017-03-08 11:49:05 -08001582 int err = native_window_set_auto_refresh(s->getNativeWindow(), value != 0);
1583 return (err == 0) ? EGL_TRUE : setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Pablo Ceballosccdfd602015-10-07 15:05:45 -07001584 }
1585
Pablo Ceballosc18be292016-05-31 14:55:42 -07001586 if (attribute == EGL_TIMESTAMPS_ANDROID) {
Mathias Agopian65421432017-03-08 11:49:05 -08001587 if (!s->getNativeWindow()) {
Mathias Agopian737b8962017-02-24 14:32:05 -08001588 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Brian Anderson069b3652016-07-22 10:32:47 -07001589 }
Mathias Agopian65421432017-03-08 11:49:05 -08001590 int err = native_window_enable_frame_timestamps(s->getNativeWindow(), value != 0);
1591 return (err == 0) ? EGL_TRUE : setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Pablo Ceballosc18be292016-05-31 14:55:42 -07001592 }
1593
Courtney Goeltzenleuchter786ab882018-01-26 13:37:33 -08001594 if (s->setSmpte2086Attribute(attribute, value)) {
1595 return EGL_TRUE;
1596 } else if (s->setCta8613Attribute(attribute, value)) {
1597 return EGL_TRUE;
1598 } else if (s->cnx->egl.eglSurfaceAttrib) {
Mathias Agopian518ec112011-05-13 16:21:08 -07001599 return s->cnx->egl.eglSurfaceAttrib(
Mathias Agopianada798b2012-02-13 17:09:30 -08001600 dp->disp.dpy, s->surface, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -07001601 }
Mathias Agopian737b8962017-02-24 14:32:05 -08001602 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001603}
1604
1605EGLBoolean eglBindTexImage(
1606 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1607{
1608 clearError();
1609
Jesse Hallb29e5e82012-04-04 16:53:42 -07001610 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001611 if (!dp) return EGL_FALSE;
1612
Jesse Hallb29e5e82012-04-04 16:53:42 -07001613 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001614 if (!_s.get())
Mathias Agopian737b8962017-02-24 14:32:05 -08001615 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001616
Mathias Agopian518ec112011-05-13 16:21:08 -07001617 egl_surface_t const * const s = get_surface(surface);
1618 if (s->cnx->egl.eglBindTexImage) {
1619 return s->cnx->egl.eglBindTexImage(
Mathias Agopianada798b2012-02-13 17:09:30 -08001620 dp->disp.dpy, s->surface, buffer);
Mathias Agopian518ec112011-05-13 16:21:08 -07001621 }
Mathias Agopian737b8962017-02-24 14:32:05 -08001622 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001623}
1624
1625EGLBoolean eglReleaseTexImage(
1626 EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1627{
1628 clearError();
1629
Jesse Hallb29e5e82012-04-04 16:53:42 -07001630 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001631 if (!dp) return EGL_FALSE;
1632
Jesse Hallb29e5e82012-04-04 16:53:42 -07001633 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001634 if (!_s.get())
Mathias Agopian737b8962017-02-24 14:32:05 -08001635 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001636
Mathias Agopian518ec112011-05-13 16:21:08 -07001637 egl_surface_t const * const s = get_surface(surface);
1638 if (s->cnx->egl.eglReleaseTexImage) {
1639 return s->cnx->egl.eglReleaseTexImage(
Mathias Agopianada798b2012-02-13 17:09:30 -08001640 dp->disp.dpy, s->surface, buffer);
Mathias Agopian518ec112011-05-13 16:21:08 -07001641 }
Mathias Agopian737b8962017-02-24 14:32:05 -08001642 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001643}
1644
1645EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
1646{
1647 clearError();
1648
Jesse Hallb29e5e82012-04-04 16:53:42 -07001649 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001650 if (!dp) return EGL_FALSE;
1651
1652 EGLBoolean res = EGL_TRUE;
Mathias Agopianada798b2012-02-13 17:09:30 -08001653 egl_connection_t* const cnx = &gEGLImpl;
1654 if (cnx->dso && cnx->egl.eglSwapInterval) {
1655 res = cnx->egl.eglSwapInterval(dp->disp.dpy, interval);
Mathias Agopian518ec112011-05-13 16:21:08 -07001656 }
Mathias Agopianada798b2012-02-13 17:09:30 -08001657
Mathias Agopian518ec112011-05-13 16:21:08 -07001658 return res;
1659}
1660
1661
1662// ----------------------------------------------------------------------------
1663// EGL 1.2
1664// ----------------------------------------------------------------------------
1665
1666EGLBoolean eglWaitClient(void)
1667{
1668 clearError();
1669
Mathias Agopianada798b2012-02-13 17:09:30 -08001670 egl_connection_t* const cnx = &gEGLImpl;
1671 if (!cnx->dso)
Mathias Agopian737b8962017-02-24 14:32:05 -08001672 return setError(EGL_BAD_CONTEXT, (EGLBoolean)EGL_FALSE);
Mathias Agopianada798b2012-02-13 17:09:30 -08001673
1674 EGLBoolean res;
1675 if (cnx->egl.eglWaitClient) {
1676 res = cnx->egl.eglWaitClient();
1677 } else {
1678 res = cnx->egl.eglWaitGL();
Mathias Agopian518ec112011-05-13 16:21:08 -07001679 }
1680 return res;
1681}
1682
1683EGLBoolean eglBindAPI(EGLenum api)
1684{
1685 clearError();
1686
1687 if (egl_init_drivers() == EGL_FALSE) {
Mathias Agopian737b8962017-02-24 14:32:05 -08001688 return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001689 }
1690
1691 // bind this API on all EGLs
1692 EGLBoolean res = EGL_TRUE;
Mathias Agopianada798b2012-02-13 17:09:30 -08001693 egl_connection_t* const cnx = &gEGLImpl;
1694 if (cnx->dso && cnx->egl.eglBindAPI) {
1695 res = cnx->egl.eglBindAPI(api);
Mathias Agopian518ec112011-05-13 16:21:08 -07001696 }
1697 return res;
1698}
1699
1700EGLenum eglQueryAPI(void)
1701{
1702 clearError();
1703
1704 if (egl_init_drivers() == EGL_FALSE) {
Mathias Agopian737b8962017-02-24 14:32:05 -08001705 return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001706 }
1707
Mathias Agopianada798b2012-02-13 17:09:30 -08001708 egl_connection_t* const cnx = &gEGLImpl;
1709 if (cnx->dso && cnx->egl.eglQueryAPI) {
1710 return cnx->egl.eglQueryAPI();
Mathias Agopian518ec112011-05-13 16:21:08 -07001711 }
Mathias Agopianada798b2012-02-13 17:09:30 -08001712
Mathias Agopian518ec112011-05-13 16:21:08 -07001713 // or, it can only be OpenGL ES
1714 return EGL_OPENGL_ES_API;
1715}
1716
1717EGLBoolean eglReleaseThread(void)
1718{
1719 clearError();
1720
Mathias Agopianada798b2012-02-13 17:09:30 -08001721 egl_connection_t* const cnx = &gEGLImpl;
1722 if (cnx->dso && cnx->egl.eglReleaseThread) {
1723 cnx->egl.eglReleaseThread();
Mathias Agopian518ec112011-05-13 16:21:08 -07001724 }
Sai Kiran Korwar3ac517a2014-01-31 21:15:07 +05301725
1726 // If there is context bound to the thread, release it
1727 egl_display_t::loseCurrent(get_context(getContext()));
1728
Mathias Agopian518ec112011-05-13 16:21:08 -07001729 egl_tls_t::clearTLS();
Mathias Agopian518ec112011-05-13 16:21:08 -07001730 return EGL_TRUE;
1731}
1732
1733EGLSurface eglCreatePbufferFromClientBuffer(
1734 EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer,
1735 EGLConfig config, const EGLint *attrib_list)
1736{
1737 clearError();
1738
Jesse Hallb29e5e82012-04-04 16:53:42 -07001739 egl_connection_t* cnx = NULL;
1740 const egl_display_ptr dp = validate_display_connection(dpy, cnx);
1741 if (!dp) return EGL_FALSE;
Mathias Agopian518ec112011-05-13 16:21:08 -07001742 if (cnx->egl.eglCreatePbufferFromClientBuffer) {
1743 return cnx->egl.eglCreatePbufferFromClientBuffer(
Mathias Agopian7773c432012-02-13 20:06:08 -08001744 dp->disp.dpy, buftype, buffer, config, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001745 }
1746 return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE);
1747}
1748
1749// ----------------------------------------------------------------------------
1750// EGL_EGLEXT_VERSION 3
1751// ----------------------------------------------------------------------------
1752
1753EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface,
1754 const EGLint *attrib_list)
1755{
1756 clearError();
1757
Jesse Hallb29e5e82012-04-04 16:53:42 -07001758 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001759 if (!dp) return EGL_FALSE;
1760
Jesse Hallb29e5e82012-04-04 16:53:42 -07001761 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001762 if (!_s.get())
Mathias Agopian737b8962017-02-24 14:32:05 -08001763 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001764
1765 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian518ec112011-05-13 16:21:08 -07001766 if (s->cnx->egl.eglLockSurfaceKHR) {
1767 return s->cnx->egl.eglLockSurfaceKHR(
Mathias Agopianada798b2012-02-13 17:09:30 -08001768 dp->disp.dpy, s->surface, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001769 }
Mathias Agopian737b8962017-02-24 14:32:05 -08001770 return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001771}
1772
1773EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface)
1774{
1775 clearError();
1776
Jesse Hallb29e5e82012-04-04 16:53:42 -07001777 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001778 if (!dp) return EGL_FALSE;
1779
Jesse Hallb29e5e82012-04-04 16:53:42 -07001780 SurfaceRef _s(dp.get(), surface);
Mathias Agopian5b287a62011-05-16 18:58:55 -07001781 if (!_s.get())
Mathias Agopian737b8962017-02-24 14:32:05 -08001782 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001783
1784 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian518ec112011-05-13 16:21:08 -07001785 if (s->cnx->egl.eglUnlockSurfaceKHR) {
Mathias Agopianada798b2012-02-13 17:09:30 -08001786 return s->cnx->egl.eglUnlockSurfaceKHR(dp->disp.dpy, s->surface);
Mathias Agopian518ec112011-05-13 16:21:08 -07001787 }
Mathias Agopian737b8962017-02-24 14:32:05 -08001788 return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
Mathias Agopian518ec112011-05-13 16:21:08 -07001789}
1790
1791EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
1792 EGLClientBuffer buffer, const EGLint *attrib_list)
1793{
1794 clearError();
1795
Jesse Hallb29e5e82012-04-04 16:53:42 -07001796 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001797 if (!dp) return EGL_NO_IMAGE_KHR;
1798
Jesse Hallb29e5e82012-04-04 16:53:42 -07001799 ContextRef _c(dp.get(), ctx);
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001800 egl_context_t * const c = _c.get();
Mathias Agopian518ec112011-05-13 16:21:08 -07001801
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001802 EGLImageKHR result = EGL_NO_IMAGE_KHR;
1803 egl_connection_t* const cnx = &gEGLImpl;
1804 if (cnx->dso && cnx->egl.eglCreateImageKHR) {
1805 result = cnx->egl.eglCreateImageKHR(
1806 dp->disp.dpy,
1807 c ? c->context : EGL_NO_CONTEXT,
1808 target, buffer, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001809 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001810 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001811}
1812
1813EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
1814{
1815 clearError();
1816
Jesse Hallb29e5e82012-04-04 16:53:42 -07001817 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001818 if (!dp) return EGL_FALSE;
1819
Steven Holte646a5c52012-06-04 20:02:11 -07001820 EGLBoolean result = EGL_FALSE;
Mathias Agopianada798b2012-02-13 17:09:30 -08001821 egl_connection_t* const cnx = &gEGLImpl;
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001822 if (cnx->dso && cnx->egl.eglDestroyImageKHR) {
Steven Holte646a5c52012-06-04 20:02:11 -07001823 result = cnx->egl.eglDestroyImageKHR(dp->disp.dpy, img);
Mathias Agopian518ec112011-05-13 16:21:08 -07001824 }
Steven Holte646a5c52012-06-04 20:02:11 -07001825 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001826}
1827
1828// ----------------------------------------------------------------------------
1829// EGL_EGLEXT_VERSION 5
1830// ----------------------------------------------------------------------------
1831
1832
1833EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
1834{
1835 clearError();
1836
Jesse Hallb29e5e82012-04-04 16:53:42 -07001837 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001838 if (!dp) return EGL_NO_SYNC_KHR;
1839
Mathias Agopian518ec112011-05-13 16:21:08 -07001840 EGLSyncKHR result = EGL_NO_SYNC_KHR;
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001841 egl_connection_t* const cnx = &gEGLImpl;
1842 if (cnx->dso && cnx->egl.eglCreateSyncKHR) {
1843 result = cnx->egl.eglCreateSyncKHR(dp->disp.dpy, type, attrib_list);
Mathias Agopian518ec112011-05-13 16:21:08 -07001844 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001845 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001846}
1847
1848EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
1849{
1850 clearError();
1851
Jesse Hallb29e5e82012-04-04 16:53:42 -07001852 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001853 if (!dp) return EGL_FALSE;
1854
Mathias Agopian518ec112011-05-13 16:21:08 -07001855 EGLBoolean result = EGL_FALSE;
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001856 egl_connection_t* const cnx = &gEGLImpl;
1857 if (cnx->dso && cnx->egl.eglDestroySyncKHR) {
1858 result = cnx->egl.eglDestroySyncKHR(dp->disp.dpy, sync);
Mathias Agopian518ec112011-05-13 16:21:08 -07001859 }
1860 return result;
1861}
1862
Mathias Agopiane9b3dfb2013-03-27 14:30:19 -07001863EGLBoolean eglSignalSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode) {
1864 clearError();
1865
1866 const egl_display_ptr dp = validate_display(dpy);
1867 if (!dp) return EGL_FALSE;
1868
1869 EGLBoolean result = EGL_FALSE;
1870 egl_connection_t* const cnx = &gEGLImpl;
1871 if (cnx->dso && cnx->egl.eglSignalSyncKHR) {
1872 result = cnx->egl.eglSignalSyncKHR(
1873 dp->disp.dpy, sync, mode);
1874 }
1875 return result;
1876}
1877
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001878EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync,
1879 EGLint flags, EGLTimeKHR timeout)
Mathias Agopian518ec112011-05-13 16:21:08 -07001880{
1881 clearError();
1882
Jesse Hallb29e5e82012-04-04 16:53:42 -07001883 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001884 if (!dp) return EGL_FALSE;
1885
Mathias Agopian737b8962017-02-24 14:32:05 -08001886 EGLint result = EGL_FALSE;
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001887 egl_connection_t* const cnx = &gEGLImpl;
1888 if (cnx->dso && cnx->egl.eglClientWaitSyncKHR) {
1889 result = cnx->egl.eglClientWaitSyncKHR(
1890 dp->disp.dpy, sync, flags, timeout);
Mathias Agopian518ec112011-05-13 16:21:08 -07001891 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001892 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001893}
1894
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001895EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync,
1896 EGLint attribute, EGLint *value)
Mathias Agopian518ec112011-05-13 16:21:08 -07001897{
1898 clearError();
1899
Jesse Hallb29e5e82012-04-04 16:53:42 -07001900 const egl_display_ptr dp = validate_display(dpy);
Mathias Agopian518ec112011-05-13 16:21:08 -07001901 if (!dp) return EGL_FALSE;
1902
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001903 EGLBoolean result = EGL_FALSE;
1904 egl_connection_t* const cnx = &gEGLImpl;
1905 if (cnx->dso && cnx->egl.eglGetSyncAttribKHR) {
1906 result = cnx->egl.eglGetSyncAttribKHR(
1907 dp->disp.dpy, sync, attribute, value);
Mathias Agopian518ec112011-05-13 16:21:08 -07001908 }
Mathias Agopian7c0441a2012-02-14 17:14:36 -08001909 return result;
Mathias Agopian518ec112011-05-13 16:21:08 -07001910}
1911
Season Li000d88f2015-07-01 11:39:40 -07001912EGLStreamKHR eglCreateStreamKHR(EGLDisplay dpy, const EGLint *attrib_list)
1913{
1914 clearError();
1915
1916 const egl_display_ptr dp = validate_display(dpy);
1917 if (!dp) return EGL_NO_STREAM_KHR;
1918
1919 EGLStreamKHR result = EGL_NO_STREAM_KHR;
1920 egl_connection_t* const cnx = &gEGLImpl;
1921 if (cnx->dso && cnx->egl.eglCreateStreamKHR) {
1922 result = cnx->egl.eglCreateStreamKHR(
1923 dp->disp.dpy, attrib_list);
1924 }
1925 return result;
1926}
1927
1928EGLBoolean eglDestroyStreamKHR(EGLDisplay dpy, EGLStreamKHR stream)
1929{
1930 clearError();
1931
1932 const egl_display_ptr dp = validate_display(dpy);
1933 if (!dp) return EGL_FALSE;
1934
1935 EGLBoolean result = EGL_FALSE;
1936 egl_connection_t* const cnx = &gEGLImpl;
1937 if (cnx->dso && cnx->egl.eglDestroyStreamKHR) {
1938 result = cnx->egl.eglDestroyStreamKHR(
1939 dp->disp.dpy, stream);
1940 }
1941 return result;
1942}
1943
1944EGLBoolean eglStreamAttribKHR(EGLDisplay dpy, EGLStreamKHR stream,
1945 EGLenum attribute, EGLint value)
1946{
1947 clearError();
1948
1949 const egl_display_ptr dp = validate_display(dpy);
1950 if (!dp) return EGL_FALSE;
1951
1952 EGLBoolean result = EGL_FALSE;
1953 egl_connection_t* const cnx = &gEGLImpl;
1954 if (cnx->dso && cnx->egl.eglStreamAttribKHR) {
1955 result = cnx->egl.eglStreamAttribKHR(
1956 dp->disp.dpy, stream, attribute, value);
1957 }
1958 return result;
1959}
1960
1961EGLBoolean eglQueryStreamKHR(EGLDisplay dpy, EGLStreamKHR stream,
1962 EGLenum attribute, EGLint *value)
1963{
1964 clearError();
1965
1966 const egl_display_ptr dp = validate_display(dpy);
1967 if (!dp) return EGL_FALSE;
1968
1969 EGLBoolean result = EGL_FALSE;
1970 egl_connection_t* const cnx = &gEGLImpl;
1971 if (cnx->dso && cnx->egl.eglQueryStreamKHR) {
1972 result = cnx->egl.eglQueryStreamKHR(
1973 dp->disp.dpy, stream, attribute, value);
1974 }
1975 return result;
1976}
1977
1978EGLBoolean eglQueryStreamu64KHR(EGLDisplay dpy, EGLStreamKHR stream,
1979 EGLenum attribute, EGLuint64KHR *value)
1980{
1981 clearError();
1982
1983 const egl_display_ptr dp = validate_display(dpy);
1984 if (!dp) return EGL_FALSE;
1985
1986 EGLBoolean result = EGL_FALSE;
1987 egl_connection_t* const cnx = &gEGLImpl;
1988 if (cnx->dso && cnx->egl.eglQueryStreamu64KHR) {
1989 result = cnx->egl.eglQueryStreamu64KHR(
1990 dp->disp.dpy, stream, attribute, value);
1991 }
1992 return result;
1993}
1994
1995EGLBoolean eglQueryStreamTimeKHR(EGLDisplay dpy, EGLStreamKHR stream,
1996 EGLenum attribute, EGLTimeKHR *value)
1997{
1998 clearError();
1999
2000 const egl_display_ptr dp = validate_display(dpy);
2001 if (!dp) return EGL_FALSE;
2002
2003 EGLBoolean result = EGL_FALSE;
2004 egl_connection_t* const cnx = &gEGLImpl;
2005 if (cnx->dso && cnx->egl.eglQueryStreamTimeKHR) {
2006 result = cnx->egl.eglQueryStreamTimeKHR(
2007 dp->disp.dpy, stream, attribute, value);
2008 }
2009 return result;
2010}
2011
2012EGLSurface eglCreateStreamProducerSurfaceKHR(EGLDisplay dpy, EGLConfig config,
2013 EGLStreamKHR stream, const EGLint *attrib_list)
2014{
2015 clearError();
2016
2017 egl_display_ptr dp = validate_display(dpy);
2018 if (!dp) return EGL_NO_SURFACE;
2019
2020 egl_connection_t* const cnx = &gEGLImpl;
2021 if (cnx->dso && cnx->egl.eglCreateStreamProducerSurfaceKHR) {
2022 EGLSurface surface = cnx->egl.eglCreateStreamProducerSurfaceKHR(
2023 dp->disp.dpy, config, stream, attrib_list);
2024 if (surface != EGL_NO_SURFACE) {
Courtney Goeltzenleuchterb1d70ec2018-02-08 18:09:33 -07002025 egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL, surface,
2026 EGL_GL_COLORSPACE_LINEAR_KHR, cnx);
Season Li000d88f2015-07-01 11:39:40 -07002027 return s;
2028 }
2029 }
2030 return EGL_NO_SURFACE;
2031}
2032
2033EGLBoolean eglStreamConsumerGLTextureExternalKHR(EGLDisplay dpy,
2034 EGLStreamKHR stream)
2035{
2036 clearError();
2037
2038 const egl_display_ptr dp = validate_display(dpy);
2039 if (!dp) return EGL_FALSE;
2040
2041 EGLBoolean result = EGL_FALSE;
2042 egl_connection_t* const cnx = &gEGLImpl;
2043 if (cnx->dso && cnx->egl.eglStreamConsumerGLTextureExternalKHR) {
2044 result = cnx->egl.eglStreamConsumerGLTextureExternalKHR(
2045 dp->disp.dpy, stream);
2046 }
2047 return result;
2048}
2049
2050EGLBoolean eglStreamConsumerAcquireKHR(EGLDisplay dpy,
2051 EGLStreamKHR stream)
2052{
2053 clearError();
2054
2055 const egl_display_ptr dp = validate_display(dpy);
2056 if (!dp) return EGL_FALSE;
2057
2058 EGLBoolean result = EGL_FALSE;
2059 egl_connection_t* const cnx = &gEGLImpl;
2060 if (cnx->dso && cnx->egl.eglStreamConsumerAcquireKHR) {
2061 result = cnx->egl.eglStreamConsumerAcquireKHR(
2062 dp->disp.dpy, stream);
2063 }
2064 return result;
2065}
2066
2067EGLBoolean eglStreamConsumerReleaseKHR(EGLDisplay dpy,
2068 EGLStreamKHR stream)
2069{
2070 clearError();
2071
2072 const egl_display_ptr dp = validate_display(dpy);
2073 if (!dp) return EGL_FALSE;
2074
2075 EGLBoolean result = EGL_FALSE;
2076 egl_connection_t* const cnx = &gEGLImpl;
2077 if (cnx->dso && cnx->egl.eglStreamConsumerReleaseKHR) {
2078 result = cnx->egl.eglStreamConsumerReleaseKHR(
2079 dp->disp.dpy, stream);
2080 }
2081 return result;
2082}
2083
2084EGLNativeFileDescriptorKHR eglGetStreamFileDescriptorKHR(
2085 EGLDisplay dpy, EGLStreamKHR stream)
2086{
2087 clearError();
2088
2089 const egl_display_ptr dp = validate_display(dpy);
2090 if (!dp) return EGL_NO_FILE_DESCRIPTOR_KHR;
2091
2092 EGLNativeFileDescriptorKHR result = EGL_NO_FILE_DESCRIPTOR_KHR;
2093 egl_connection_t* const cnx = &gEGLImpl;
2094 if (cnx->dso && cnx->egl.eglGetStreamFileDescriptorKHR) {
2095 result = cnx->egl.eglGetStreamFileDescriptorKHR(
2096 dp->disp.dpy, stream);
2097 }
2098 return result;
2099}
2100
2101EGLStreamKHR eglCreateStreamFromFileDescriptorKHR(
2102 EGLDisplay dpy, EGLNativeFileDescriptorKHR file_descriptor)
2103{
2104 clearError();
2105
2106 const egl_display_ptr dp = validate_display(dpy);
2107 if (!dp) return EGL_NO_STREAM_KHR;
2108
2109 EGLStreamKHR result = EGL_NO_STREAM_KHR;
2110 egl_connection_t* const cnx = &gEGLImpl;
2111 if (cnx->dso && cnx->egl.eglCreateStreamFromFileDescriptorKHR) {
2112 result = cnx->egl.eglCreateStreamFromFileDescriptorKHR(
2113 dp->disp.dpy, file_descriptor);
2114 }
2115 return result;
2116}
2117
Mathias Agopian518ec112011-05-13 16:21:08 -07002118// ----------------------------------------------------------------------------
Mathias Agopian2bb71682013-03-27 17:32:41 -07002119// EGL_EGLEXT_VERSION 15
2120// ----------------------------------------------------------------------------
2121
2122EGLint eglWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags) {
2123 clearError();
2124 const egl_display_ptr dp = validate_display(dpy);
2125 if (!dp) return EGL_FALSE;
2126 EGLint result = EGL_FALSE;
2127 egl_connection_t* const cnx = &gEGLImpl;
2128 if (cnx->dso && cnx->egl.eglWaitSyncKHR) {
2129 result = cnx->egl.eglWaitSyncKHR(dp->disp.dpy, sync, flags);
2130 }
2131 return result;
2132}
2133
2134// ----------------------------------------------------------------------------
Mathias Agopian518ec112011-05-13 16:21:08 -07002135// ANDROID extensions
2136// ----------------------------------------------------------------------------
2137
Jamie Gennis331841b2012-09-06 14:52:00 -07002138EGLint eglDupNativeFenceFDANDROID(EGLDisplay dpy, EGLSyncKHR sync)
2139{
2140 clearError();
2141
2142 const egl_display_ptr dp = validate_display(dpy);
2143 if (!dp) return EGL_NO_NATIVE_FENCE_FD_ANDROID;
2144
2145 EGLint result = EGL_NO_NATIVE_FENCE_FD_ANDROID;
2146 egl_connection_t* const cnx = &gEGLImpl;
2147 if (cnx->dso && cnx->egl.eglDupNativeFenceFDANDROID) {
2148 result = cnx->egl.eglDupNativeFenceFDANDROID(dp->disp.dpy, sync);
2149 }
2150 return result;
2151}
Jonas Yang1c3d72a2011-08-26 20:04:39 +08002152
Andy McFadden72841452013-03-01 16:25:32 -08002153EGLBoolean eglPresentationTimeANDROID(EGLDisplay dpy, EGLSurface surface,
2154 EGLnsecsANDROID time)
2155{
2156 clearError();
2157
2158 const egl_display_ptr dp = validate_display(dpy);
2159 if (!dp) {
2160 return EGL_FALSE;
2161 }
2162
2163 SurfaceRef _s(dp.get(), surface);
2164 if (!_s.get()) {
2165 setError(EGL_BAD_SURFACE, EGL_FALSE);
2166 return EGL_FALSE;
2167 }
2168
2169 egl_surface_t const * const s = get_surface(surface);
Mathias Agopian65421432017-03-08 11:49:05 -08002170 native_window_set_buffers_timestamp(s->getNativeWindow(), time);
Andy McFadden72841452013-03-01 16:25:32 -08002171
2172 return EGL_TRUE;
2173}
2174
Craig Donner60761072017-01-27 12:30:44 -08002175EGLClientBuffer eglGetNativeClientBufferANDROID(const AHardwareBuffer *buffer) {
2176 clearError();
Jiyong Parka243e5d2017-06-21 12:26:51 +09002177 // AHardwareBuffer_to_ANativeWindowBuffer is a platform-only symbol and thus
2178 // this function cannot be implemented when this libEGL is built for
2179 // vendors.
2180#ifndef __ANDROID_VNDK__
Craig Donner60761072017-01-27 12:30:44 -08002181 if (!buffer) return setError(EGL_BAD_PARAMETER, (EGLClientBuffer)0);
Mathias Agopian61963402017-02-24 16:38:15 -08002182 return const_cast<ANativeWindowBuffer *>(AHardwareBuffer_to_ANativeWindowBuffer(buffer));
Jiyong Parka243e5d2017-06-21 12:26:51 +09002183#else
2184 return setError(EGL_BAD_PARAMETER, (EGLClientBuffer)0);
2185#endif
Craig Donner60761072017-01-27 12:30:44 -08002186}
2187
Jonas Yang1c3d72a2011-08-26 20:04:39 +08002188// ----------------------------------------------------------------------------
2189// NVIDIA extensions
2190// ----------------------------------------------------------------------------
2191EGLuint64NV eglGetSystemTimeFrequencyNV()
2192{
2193 clearError();
2194
2195 if (egl_init_drivers() == EGL_FALSE) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002196 return setError(EGL_BAD_PARAMETER, (EGLuint64NV)EGL_FALSE);
Jonas Yang1c3d72a2011-08-26 20:04:39 +08002197 }
2198
2199 EGLuint64NV ret = 0;
Mathias Agopianada798b2012-02-13 17:09:30 -08002200 egl_connection_t* const cnx = &gEGLImpl;
Jonas Yang1c3d72a2011-08-26 20:04:39 +08002201
Mathias Agopianada798b2012-02-13 17:09:30 -08002202 if (cnx->dso && cnx->egl.eglGetSystemTimeFrequencyNV) {
2203 return cnx->egl.eglGetSystemTimeFrequencyNV();
Jonas Yang1c3d72a2011-08-26 20:04:39 +08002204 }
2205
Mathias Agopian737b8962017-02-24 14:32:05 -08002206 return setErrorQuiet(EGL_BAD_DISPLAY, (EGLuint64NV)0);
Jonas Yang1c3d72a2011-08-26 20:04:39 +08002207}
2208
2209EGLuint64NV eglGetSystemTimeNV()
2210{
2211 clearError();
2212
2213 if (egl_init_drivers() == EGL_FALSE) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002214 return setError(EGL_BAD_PARAMETER, (EGLuint64NV)EGL_FALSE);
Jonas Yang1c3d72a2011-08-26 20:04:39 +08002215 }
2216
2217 EGLuint64NV ret = 0;
Mathias Agopianada798b2012-02-13 17:09:30 -08002218 egl_connection_t* const cnx = &gEGLImpl;
Jonas Yang1c3d72a2011-08-26 20:04:39 +08002219
Mathias Agopianada798b2012-02-13 17:09:30 -08002220 if (cnx->dso && cnx->egl.eglGetSystemTimeNV) {
2221 return cnx->egl.eglGetSystemTimeNV();
Jonas Yang1c3d72a2011-08-26 20:04:39 +08002222 }
2223
Mathias Agopian737b8962017-02-24 14:32:05 -08002224 return setErrorQuiet(EGL_BAD_DISPLAY, (EGLuint64NV)0);
Jonas Yang1c3d72a2011-08-26 20:04:39 +08002225}
Dan Stozaa894d082015-02-19 15:27:36 -08002226
2227// ----------------------------------------------------------------------------
2228// Partial update extension
2229// ----------------------------------------------------------------------------
2230EGLBoolean eglSetDamageRegionKHR(EGLDisplay dpy, EGLSurface surface,
2231 EGLint *rects, EGLint n_rects)
2232{
2233 clearError();
2234
2235 const egl_display_ptr dp = validate_display(dpy);
2236 if (!dp) {
2237 setError(EGL_BAD_DISPLAY, EGL_FALSE);
2238 return EGL_FALSE;
2239 }
2240
2241 SurfaceRef _s(dp.get(), surface);
2242 if (!_s.get()) {
2243 setError(EGL_BAD_SURFACE, EGL_FALSE);
2244 return EGL_FALSE;
2245 }
2246
2247 egl_surface_t const * const s = get_surface(surface);
2248 if (s->cnx->egl.eglSetDamageRegionKHR) {
2249 return s->cnx->egl.eglSetDamageRegionKHR(dp->disp.dpy, s->surface,
2250 rects, n_rects);
2251 }
2252
2253 return EGL_FALSE;
2254}
Pablo Ceballosc18be292016-05-31 14:55:42 -07002255
Brian Anderson1049d1d2016-12-16 17:25:57 -08002256EGLBoolean eglGetNextFrameIdANDROID(EGLDisplay dpy, EGLSurface surface,
2257 EGLuint64KHR *frameId) {
2258 clearError();
2259
2260 const egl_display_ptr dp = validate_display(dpy);
2261 if (!dp) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002262 return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
Brian Anderson1049d1d2016-12-16 17:25:57 -08002263 }
2264
2265 SurfaceRef _s(dp.get(), surface);
2266 if (!_s.get()) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002267 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Brian Anderson1049d1d2016-12-16 17:25:57 -08002268 }
2269
2270 egl_surface_t const * const s = get_surface(surface);
2271
Mathias Agopian65421432017-03-08 11:49:05 -08002272 if (!s->getNativeWindow()) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002273 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Brian Anderson1049d1d2016-12-16 17:25:57 -08002274 }
2275
2276 uint64_t nextFrameId = 0;
Mathias Agopian65421432017-03-08 11:49:05 -08002277 int ret = native_window_get_next_frame_id(s->getNativeWindow(), &nextFrameId);
Brian Anderson1049d1d2016-12-16 17:25:57 -08002278
Mathias Agopian65421432017-03-08 11:49:05 -08002279 if (ret != 0) {
Brian Anderson1049d1d2016-12-16 17:25:57 -08002280 // This should not happen. Return an error that is not in the spec
2281 // so it's obvious something is very wrong.
2282 ALOGE("eglGetNextFrameId: Unexpected error.");
Mathias Agopian737b8962017-02-24 14:32:05 -08002283 return setError(EGL_NOT_INITIALIZED, (EGLBoolean)EGL_FALSE);
Brian Anderson1049d1d2016-12-16 17:25:57 -08002284 }
2285
2286 *frameId = nextFrameId;
2287 return EGL_TRUE;
2288}
2289
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002290EGLBoolean eglGetCompositorTimingANDROID(EGLDisplay dpy, EGLSurface surface,
2291 EGLint numTimestamps, const EGLint *names, EGLnsecsANDROID *values)
2292{
2293 clearError();
2294
2295 const egl_display_ptr dp = validate_display(dpy);
2296 if (!dp) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002297 return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002298 }
2299
2300 SurfaceRef _s(dp.get(), surface);
2301 if (!_s.get()) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002302 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002303 }
2304
2305 egl_surface_t const * const s = get_surface(surface);
2306
Mathias Agopian65421432017-03-08 11:49:05 -08002307 if (!s->getNativeWindow()) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002308 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002309 }
2310
2311 nsecs_t* compositeDeadline = nullptr;
2312 nsecs_t* compositeInterval = nullptr;
2313 nsecs_t* compositeToPresentLatency = nullptr;
2314
2315 for (int i = 0; i < numTimestamps; i++) {
2316 switch (names[i]) {
2317 case EGL_COMPOSITE_DEADLINE_ANDROID:
2318 compositeDeadline = &values[i];
2319 break;
2320 case EGL_COMPOSITE_INTERVAL_ANDROID:
2321 compositeInterval = &values[i];
2322 break;
2323 case EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID:
2324 compositeToPresentLatency = &values[i];
2325 break;
2326 default:
Mathias Agopian737b8962017-02-24 14:32:05 -08002327 return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE);
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002328 }
2329 }
2330
Mathias Agopian65421432017-03-08 11:49:05 -08002331 int ret = native_window_get_compositor_timing(s->getNativeWindow(),
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002332 compositeDeadline, compositeInterval, compositeToPresentLatency);
2333
2334 switch (ret) {
Mathias Agopian65421432017-03-08 11:49:05 -08002335 case 0:
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002336 return EGL_TRUE;
Mathias Agopian65421432017-03-08 11:49:05 -08002337 case -ENOSYS:
Mathias Agopian737b8962017-02-24 14:32:05 -08002338 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002339 default:
2340 // This should not happen. Return an error that is not in the spec
2341 // so it's obvious something is very wrong.
2342 ALOGE("eglGetCompositorTiming: Unexpected error.");
Mathias Agopian737b8962017-02-24 14:32:05 -08002343 return setError(EGL_NOT_INITIALIZED, (EGLBoolean)EGL_FALSE);
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002344 }
2345}
2346
2347EGLBoolean eglGetCompositorTimingSupportedANDROID(
2348 EGLDisplay dpy, EGLSurface surface, EGLint name)
2349{
2350 clearError();
2351
2352 const egl_display_ptr dp = validate_display(dpy);
2353 if (!dp) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002354 return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002355 }
2356
2357 SurfaceRef _s(dp.get(), surface);
2358 if (!_s.get()) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002359 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002360 }
2361
2362 egl_surface_t const * const s = get_surface(surface);
2363
Mathias Agopian65421432017-03-08 11:49:05 -08002364 ANativeWindow* window = s->getNativeWindow();
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002365 if (!window) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002366 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002367 }
2368
2369 switch (name) {
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002370 case EGL_COMPOSITE_DEADLINE_ANDROID:
2371 case EGL_COMPOSITE_INTERVAL_ANDROID:
2372 case EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID:
2373 return EGL_TRUE;
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002374 default:
2375 return EGL_FALSE;
2376 }
2377}
2378
Pablo Ceballosc18be292016-05-31 14:55:42 -07002379EGLBoolean eglGetFrameTimestampsANDROID(EGLDisplay dpy, EGLSurface surface,
Brian Anderson1049d1d2016-12-16 17:25:57 -08002380 EGLuint64KHR frameId, EGLint numTimestamps, const EGLint *timestamps,
Pablo Ceballosc18be292016-05-31 14:55:42 -07002381 EGLnsecsANDROID *values)
2382{
2383 clearError();
2384
2385 const egl_display_ptr dp = validate_display(dpy);
2386 if (!dp) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002387 return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
Pablo Ceballosc18be292016-05-31 14:55:42 -07002388 }
2389
2390 SurfaceRef _s(dp.get(), surface);
2391 if (!_s.get()) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002392 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Pablo Ceballosc18be292016-05-31 14:55:42 -07002393 }
2394
2395 egl_surface_t const * const s = get_surface(surface);
2396
Mathias Agopian65421432017-03-08 11:49:05 -08002397 if (!s->getNativeWindow()) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002398 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Pablo Ceballosc18be292016-05-31 14:55:42 -07002399 }
2400
Brian Andersondbd0ea82016-07-22 09:38:59 -07002401 nsecs_t* requestedPresentTime = nullptr;
Pablo Ceballosc18be292016-05-31 14:55:42 -07002402 nsecs_t* acquireTime = nullptr;
Brian Andersonf7fd56a2016-09-02 10:10:04 -07002403 nsecs_t* latchTime = nullptr;
2404 nsecs_t* firstRefreshStartTime = nullptr;
Brian Andersonb04c6f02016-10-21 12:57:46 -07002405 nsecs_t* gpuCompositionDoneTime = nullptr;
Brian Andersonf7fd56a2016-09-02 10:10:04 -07002406 nsecs_t* lastRefreshStartTime = nullptr;
Brian Anderson069b3652016-07-22 10:32:47 -07002407 nsecs_t* displayPresentTime = nullptr;
Brian Andersonf7fd56a2016-09-02 10:10:04 -07002408 nsecs_t* dequeueReadyTime = nullptr;
Pablo Ceballosc18be292016-05-31 14:55:42 -07002409 nsecs_t* releaseTime = nullptr;
2410
2411 for (int i = 0; i < numTimestamps; i++) {
2412 switch (timestamps[i]) {
Brian Andersondbd0ea82016-07-22 09:38:59 -07002413 case EGL_REQUESTED_PRESENT_TIME_ANDROID:
2414 requestedPresentTime = &values[i];
Pablo Ceballosc18be292016-05-31 14:55:42 -07002415 break;
2416 case EGL_RENDERING_COMPLETE_TIME_ANDROID:
2417 acquireTime = &values[i];
2418 break;
Brian Andersonf7fd56a2016-09-02 10:10:04 -07002419 case EGL_COMPOSITION_LATCH_TIME_ANDROID:
2420 latchTime = &values[i];
Pablo Ceballosc18be292016-05-31 14:55:42 -07002421 break;
Brian Andersonf7fd56a2016-09-02 10:10:04 -07002422 case EGL_FIRST_COMPOSITION_START_TIME_ANDROID:
2423 firstRefreshStartTime = &values[i];
2424 break;
2425 case EGL_LAST_COMPOSITION_START_TIME_ANDROID:
2426 lastRefreshStartTime = &values[i];
2427 break;
Brian Andersonb04c6f02016-10-21 12:57:46 -07002428 case EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID:
2429 gpuCompositionDoneTime = &values[i];
Pablo Ceballosc18be292016-05-31 14:55:42 -07002430 break;
Brian Anderson069b3652016-07-22 10:32:47 -07002431 case EGL_DISPLAY_PRESENT_TIME_ANDROID:
2432 displayPresentTime = &values[i];
2433 break;
Brian Andersonf7fd56a2016-09-02 10:10:04 -07002434 case EGL_DEQUEUE_READY_TIME_ANDROID:
2435 dequeueReadyTime = &values[i];
2436 break;
Pablo Ceballosc18be292016-05-31 14:55:42 -07002437 case EGL_READS_DONE_TIME_ANDROID:
2438 releaseTime = &values[i];
2439 break;
2440 default:
Mathias Agopian737b8962017-02-24 14:32:05 -08002441 return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE);
Pablo Ceballosc18be292016-05-31 14:55:42 -07002442 }
2443 }
2444
Mathias Agopian65421432017-03-08 11:49:05 -08002445 int ret = native_window_get_frame_timestamps(s->getNativeWindow(), frameId,
Brian Andersonf7fd56a2016-09-02 10:10:04 -07002446 requestedPresentTime, acquireTime, latchTime, firstRefreshStartTime,
Brian Andersonb04c6f02016-10-21 12:57:46 -07002447 lastRefreshStartTime, gpuCompositionDoneTime, displayPresentTime,
Brian Anderson4e606e32017-03-16 15:34:57 -07002448 dequeueReadyTime, releaseTime);
Pablo Ceballosc18be292016-05-31 14:55:42 -07002449
Brian Anderson069b3652016-07-22 10:32:47 -07002450 switch (ret) {
Mathias Agopian65421432017-03-08 11:49:05 -08002451 case 0:
Mathias Agopian737b8962017-02-24 14:32:05 -08002452 return EGL_TRUE;
Mathias Agopian65421432017-03-08 11:49:05 -08002453 case -ENOENT:
Mathias Agopian737b8962017-02-24 14:32:05 -08002454 return setError(EGL_BAD_ACCESS, (EGLBoolean)EGL_FALSE);
Mathias Agopian65421432017-03-08 11:49:05 -08002455 case -ENOSYS:
Mathias Agopian737b8962017-02-24 14:32:05 -08002456 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Mathias Agopian65421432017-03-08 11:49:05 -08002457 case -EINVAL:
Mathias Agopian737b8962017-02-24 14:32:05 -08002458 return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE);
2459 default:
2460 // This should not happen. Return an error that is not in the spec
2461 // so it's obvious something is very wrong.
2462 ALOGE("eglGetFrameTimestamps: Unexpected error.");
2463 return setError(EGL_NOT_INITIALIZED, (EGLBoolean)EGL_FALSE);
Pablo Ceballosc18be292016-05-31 14:55:42 -07002464 }
Pablo Ceballosc18be292016-05-31 14:55:42 -07002465}
2466
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002467EGLBoolean eglGetFrameTimestampSupportedANDROID(
2468 EGLDisplay dpy, EGLSurface surface, EGLint timestamp)
Pablo Ceballosc18be292016-05-31 14:55:42 -07002469{
2470 clearError();
2471
2472 const egl_display_ptr dp = validate_display(dpy);
2473 if (!dp) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002474 return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE);
Pablo Ceballosc18be292016-05-31 14:55:42 -07002475 }
2476
2477 SurfaceRef _s(dp.get(), surface);
2478 if (!_s.get()) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002479 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Brian Anderson069b3652016-07-22 10:32:47 -07002480 }
2481
2482 egl_surface_t const * const s = get_surface(surface);
2483
Mathias Agopian65421432017-03-08 11:49:05 -08002484 ANativeWindow* window = s->getNativeWindow();
Brian Anderson069b3652016-07-22 10:32:47 -07002485 if (!window) {
Mathias Agopian737b8962017-02-24 14:32:05 -08002486 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE);
Pablo Ceballosc18be292016-05-31 14:55:42 -07002487 }
2488
2489 switch (timestamp) {
Brian Anderson0a61b0c2016-12-07 14:55:56 -08002490 case EGL_COMPOSITE_DEADLINE_ANDROID:
2491 case EGL_COMPOSITE_INTERVAL_ANDROID:
2492 case EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID:
Brian Andersondbd0ea82016-07-22 09:38:59 -07002493 case EGL_REQUESTED_PRESENT_TIME_ANDROID:
Pablo Ceballosc18be292016-05-31 14:55:42 -07002494 case EGL_RENDERING_COMPLETE_TIME_ANDROID:
Brian Andersonf7fd56a2016-09-02 10:10:04 -07002495 case EGL_COMPOSITION_LATCH_TIME_ANDROID:
2496 case EGL_FIRST_COMPOSITION_START_TIME_ANDROID:
2497 case EGL_LAST_COMPOSITION_START_TIME_ANDROID:
Brian Andersonb04c6f02016-10-21 12:57:46 -07002498 case EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID:
Brian Andersonf7fd56a2016-09-02 10:10:04 -07002499 case EGL_DEQUEUE_READY_TIME_ANDROID:
Pablo Ceballosc18be292016-05-31 14:55:42 -07002500 case EGL_READS_DONE_TIME_ANDROID:
2501 return EGL_TRUE;
Brian Anderson6b376712017-04-04 10:51:39 -07002502 case EGL_DISPLAY_PRESENT_TIME_ANDROID: {
2503 int value = 0;
2504 window->query(window,
2505 NATIVE_WINDOW_FRAME_TIMESTAMPS_SUPPORTS_PRESENT, &value);
2506 return value == 0 ? EGL_FALSE : EGL_TRUE;
2507 }
Pablo Ceballosc18be292016-05-31 14:55:42 -07002508 default:
2509 return EGL_FALSE;
2510 }
2511}