blob: 85aa2ae43a47f386d4cc726179b76620659fc1bf [file] [log] [blame]
Nicolas Capens0bac2852016-05-07 06:09:58 -04001// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15// libEGL.cpp: Implements the exported EGL functions.
16
Nicolas Capens45be1bc2021-04-07 12:34:21 -040017#include "Common/Version.h"
18#include "Context.hpp"
Nicolas Capens0bac2852016-05-07 06:09:58 -040019#include "Display.h"
Nicolas Capens31c07a32017-06-13 23:44:13 -040020#include "Surface.hpp"
Nicolas Capens0bac2852016-05-07 06:09:58 -040021#include "Texture.hpp"
Nicolas Capens0bac2852016-05-07 06:09:58 -040022#include "common/Image.hpp"
23#include "common/debug.h"
Nicolas Capens45be1bc2021-04-07 12:34:21 -040024#include "main.h"
Nicolas Capens0bac2852016-05-07 06:09:58 -040025
Stephen Whitee6ab01f2019-04-04 14:31:25 -040026#if defined(__ANDROID__) && !defined(ANDROID_NDK_BUILD)
Yiwei Zhang375fee92020-09-30 12:40:50 -070027#include <vndk/window.h>
Maksim Sisovb6fc49b2021-11-11 12:44:01 +020028#elif defined(SWIFTSHADER_USE_X11)
Nicolas Capens0bac2852016-05-07 06:09:58 -040029#include "Main/libX11.hpp"
30#endif
31
Krzysztof Kosińskif919b862018-01-03 23:17:52 +010032#include <algorithm>
Nicolas Capens0bac2852016-05-07 06:09:58 -040033#include <string.h>
Nicolas Capens45be1bc2021-04-07 12:34:21 -040034#include <vector>
Nicolas Capens0bac2852016-05-07 06:09:58 -040035
Nicolas Capens48908cb2018-01-08 13:07:14 -050036namespace egl
37{
38namespace
39{
Jason Macnakea6a98b2019-10-28 13:10:53 -070040sw::RecursiveLock *getDisplayLock(egl::Display *display) {
41 if (!display) return nullptr;
42 return display->getLock();
43}
44
Nicolas Capens48908cb2018-01-08 13:07:14 -050045bool validateDisplay(egl::Display *display)
Nicolas Capens0bac2852016-05-07 06:09:58 -040046{
47 if(display == EGL_NO_DISPLAY)
48 {
49 return error(EGL_BAD_DISPLAY, false);
50 }
51
52 if(!display->isInitialized())
53 {
54 return error(EGL_NOT_INITIALIZED, false);
55 }
56
57 return true;
58}
59
Nicolas Capens48908cb2018-01-08 13:07:14 -050060bool validateConfig(egl::Display *display, EGLConfig config)
Nicolas Capens0bac2852016-05-07 06:09:58 -040061{
62 if(!validateDisplay(display))
63 {
64 return false;
65 }
66
67 if(!display->isValidConfig(config))
68 {
69 return error(EGL_BAD_CONFIG, false);
70 }
71
72 return true;
73}
74
Nicolas Capens48908cb2018-01-08 13:07:14 -050075bool validateContext(egl::Display *display, egl::Context *context)
Nicolas Capens0bac2852016-05-07 06:09:58 -040076{
77 if(!validateDisplay(display))
78 {
79 return false;
80 }
81
82 if(!display->isValidContext(context))
83 {
84 return error(EGL_BAD_CONTEXT, false);
85 }
86
87 return true;
88}
89
Nicolas Capens48908cb2018-01-08 13:07:14 -050090bool validateSurface(egl::Display *display, egl::Surface *surface)
Nicolas Capens0bac2852016-05-07 06:09:58 -040091{
92 if(!validateDisplay(display))
93 {
94 return false;
95 }
96
97 if(!display->isValidSurface(surface))
98 {
99 return error(EGL_BAD_SURFACE, false);
100 }
101
102 return true;
103}
104
Nicolas Capens48908cb2018-01-08 13:07:14 -0500105// Class to facilitate conversion from EGLint to EGLAttrib lists.
106class EGLAttribs
Nicolas Capens0bac2852016-05-07 06:09:58 -0400107{
Nicolas Capens48908cb2018-01-08 13:07:14 -0500108public:
109 explicit EGLAttribs(const EGLint *attrib_list)
110 {
111 if(attrib_list)
112 {
113 while(*attrib_list != EGL_NONE)
114 {
115 attrib.push_back(static_cast<EGLAttrib>(*attrib_list));
116 attrib_list++;
117 }
118 }
119
120 attrib.push_back(EGL_NONE);
121 }
122
Nicolas Capensd7622ff2018-08-07 12:24:10 -0400123 const EGLAttrib *operator&() const
Nicolas Capens48908cb2018-01-08 13:07:14 -0500124 {
125 return &attrib[0];
126 }
127
128private:
129 std::vector<EGLAttrib> attrib;
130};
131}
132
Nicolas Capens38a9b3c2019-09-10 16:35:24 -0400133EGLint EGLAPIENTRY GetError(void)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400134{
135 TRACE("()");
136
137 EGLint error = egl::getCurrentError();
138
139 if(error != EGL_SUCCESS)
140 {
141 egl::setCurrentError(EGL_SUCCESS);
142 }
143
144 return error;
145}
146
Nicolas Capens38a9b3c2019-09-10 16:35:24 -0400147EGLDisplay EGLAPIENTRY GetDisplay(EGLNativeDisplayType display_id)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400148{
149 TRACE("(EGLNativeDisplayType display_id = %p)", display_id);
150
151 if(display_id != EGL_DEFAULT_DISPLAY)
152 {
153 // FIXME: Check if display_id is the default display
154 }
155
156 #if defined(__linux__) && !defined(__ANDROID__)
Maksim Sisovb6fc49b2021-11-11 12:44:01 +0200157 #if defined(SWIFTSHADER_USE_X11)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400158 if(!libX11)
Alexis Hetu20eea3c2018-06-19 14:50:41 -0400159 #endif // Non X11 linux is headless only
Nicolas Capens0bac2852016-05-07 06:09:58 -0400160 {
161 return success(HEADLESS_DISPLAY);
162 }
163 #endif
164
165 return success(PRIMARY_DISPLAY); // We only support the default display
166}
167
Nicolas Capens38a9b3c2019-09-10 16:35:24 -0400168EGLBoolean EGLAPIENTRY Initialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400169{
170 TRACE("(EGLDisplay dpy = %p, EGLint *major = %p, EGLint *minor = %p)",
171 dpy, major, minor);
172
Alexis Hetu2b6ac182017-05-24 14:06:27 -0400173 egl::Display *display = egl::Display::get(dpy);
174
Jason Macnakea6a98b2019-10-28 13:10:53 -0700175 RecursiveLockGuard lock(egl::getDisplayLock(display));
176
Alexis Hetu2b6ac182017-05-24 14:06:27 -0400177 if(!display)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400178 {
179 return error(EGL_BAD_DISPLAY, EGL_FALSE);
180 }
181
Nicolas Capens0bac2852016-05-07 06:09:58 -0400182 if(!display->initialize())
183 {
184 return error(EGL_NOT_INITIALIZED, EGL_FALSE);
185 }
186
187 if(major) *major = 1;
188 if(minor) *minor = 4;
189
190 return success(EGL_TRUE);
191}
192
Nicolas Capens38a9b3c2019-09-10 16:35:24 -0400193EGLBoolean EGLAPIENTRY Terminate(EGLDisplay dpy)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400194{
195 TRACE("(EGLDisplay dpy = %p)", dpy);
196
197 if(dpy == EGL_NO_DISPLAY)
198 {
199 return error(EGL_BAD_DISPLAY, EGL_FALSE);
200 }
201
202 egl::Display *display = egl::Display::get(dpy);
203
Jason Macnakea6a98b2019-10-28 13:10:53 -0700204 RecursiveLockGuard lock(egl::getDisplayLock(display));
205
Nicolas Capens0bac2852016-05-07 06:09:58 -0400206 display->terminate();
207
208 return success(EGL_TRUE);
209}
210
Nicolas Capens38a9b3c2019-09-10 16:35:24 -0400211const char *EGLAPIENTRY QueryString(EGLDisplay dpy, EGLint name)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400212{
213 TRACE("(EGLDisplay dpy = %p, EGLint name = %d)", dpy, name);
214
Nicolas Capensdf0be382017-06-05 17:43:46 -0400215 if(dpy == EGL_NO_DISPLAY && name == EGL_EXTENSIONS)
216 {
217 return success(
Krzysztof Kosińskif919b862018-01-03 23:17:52 +0100218 "EGL_KHR_client_get_all_proc_addresses "
Nicolas Capensdf0be382017-06-05 17:43:46 -0400219#if defined(__linux__) && !defined(__ANDROID__)
220 "EGL_KHR_platform_gbm "
Alexis Hetu20eea3c2018-06-19 14:50:41 -0400221#endif
Maksim Sisovb6fc49b2021-11-11 12:44:01 +0200222#if defined(SWIFTSHADER_USE_X11)
Nicolas Capensdf0be382017-06-05 17:43:46 -0400223 "EGL_KHR_platform_x11 "
Alexis Hetud415ba12017-06-05 10:29:14 -0400224#endif
Nicolas Capensdf0be382017-06-05 17:43:46 -0400225 "EGL_EXT_client_extensions "
226 "EGL_EXT_platform_base");
227 }
Nicolas Capens0bac2852016-05-07 06:09:58 -0400228
229 egl::Display *display = egl::Display::get(dpy);
230
Jason Macnakea6a98b2019-10-28 13:10:53 -0700231 RecursiveLockGuard lock(egl::getDisplayLock(display));
232
Nicolas Capens0bac2852016-05-07 06:09:58 -0400233 if(!validateDisplay(display))
234 {
235 return nullptr;
236 }
237
238 switch(name)
239 {
240 case EGL_CLIENT_APIS:
241 return success("OpenGL_ES");
242 case EGL_EXTENSIONS:
Alexis Hetub75bb022016-05-18 11:43:43 -0400243 return success("EGL_KHR_create_context "
Krzysztof Kosińskif919b862018-01-03 23:17:52 +0100244 "EGL_KHR_get_all_proc_addresses "
Alexis Hetub75bb022016-05-18 11:43:43 -0400245 "EGL_KHR_gl_texture_2D_image "
Nicolas Capens0bac2852016-05-07 06:09:58 -0400246 "EGL_KHR_gl_texture_cubemap_image "
247 "EGL_KHR_gl_renderbuffer_image "
248 "EGL_KHR_fence_sync "
249 "EGL_KHR_image_base "
Alexis Hetu5cd502b2018-03-22 08:29:31 -0400250 "EGL_KHR_surfaceless_context "
Alexis Hetuc80eada2018-02-13 15:02:40 -0500251 "EGL_ANGLE_iosurface_client_buffer "
Nicolas Capens0bac2852016-05-07 06:09:58 -0400252 "EGL_ANDROID_framebuffer_target "
253 "EGL_ANDROID_recordable");
254 case EGL_VENDOR:
255 return success("Google Inc.");
256 case EGL_VERSION:
257 return success("1.4 SwiftShader " VERSION_STRING);
258 }
259
260 return error(EGL_BAD_PARAMETER, (const char*)nullptr);
261}
262
Nicolas Capens38a9b3c2019-09-10 16:35:24 -0400263EGLBoolean EGLAPIENTRY GetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400264{
265 TRACE("(EGLDisplay dpy = %p, EGLConfig *configs = %p, "
266 "EGLint config_size = %d, EGLint *num_config = %p)",
267 dpy, configs, config_size, num_config);
268
269 egl::Display *display = egl::Display::get(dpy);
270
Jason Macnakea6a98b2019-10-28 13:10:53 -0700271 RecursiveLockGuard lock(egl::getDisplayLock(display));
272
Nicolas Capens0bac2852016-05-07 06:09:58 -0400273 if(!validateDisplay(display))
274 {
275 return EGL_FALSE;
276 }
277
278 if(!num_config)
279 {
280 return error(EGL_BAD_PARAMETER, EGL_FALSE);
281 }
282
283 const EGLint attribList[] = {EGL_NONE};
284
285 if(!display->getConfigs(configs, attribList, config_size, num_config))
286 {
287 return error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
288 }
289
290 return success(EGL_TRUE);
291}
292
Nicolas Capens38a9b3c2019-09-10 16:35:24 -0400293EGLBoolean EGLAPIENTRY ChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400294{
295 TRACE("(EGLDisplay dpy = %p, const EGLint *attrib_list = %p, "
296 "EGLConfig *configs = %p, EGLint config_size = %d, EGLint *num_config = %p)",
297 dpy, attrib_list, configs, config_size, num_config);
298
299 egl::Display *display = egl::Display::get(dpy);
300
Jason Macnakea6a98b2019-10-28 13:10:53 -0700301 RecursiveLockGuard lock(egl::getDisplayLock(display));
302
Nicolas Capens0bac2852016-05-07 06:09:58 -0400303 if(!validateDisplay(display))
304 {
305 return EGL_FALSE;
306 }
307
308 if(!num_config)
309 {
310 return error(EGL_BAD_PARAMETER, EGL_FALSE);
311 }
312
313 const EGLint attribList[] = {EGL_NONE};
314
315 if(!attrib_list)
316 {
317 attrib_list = attribList;
318 }
319
320 if(!display->getConfigs(configs, attrib_list, config_size, num_config))
321 {
322 return error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
323 }
324
325 return success(EGL_TRUE);
326}
327
Nicolas Capens38a9b3c2019-09-10 16:35:24 -0400328EGLBoolean EGLAPIENTRY GetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400329{
330 TRACE("(EGLDisplay dpy = %p, EGLConfig config = %p, EGLint attribute = %d, EGLint *value = %p)",
331 dpy, config, attribute, value);
332
333 egl::Display *display = egl::Display::get(dpy);
334
Jason Macnakea6a98b2019-10-28 13:10:53 -0700335 RecursiveLockGuard lock(egl::getDisplayLock(display));
336
Nicolas Capens0bac2852016-05-07 06:09:58 -0400337 if(!validateConfig(display, config))
338 {
339 return EGL_FALSE;
340 }
341
342 if(!display->getConfigAttrib(config, attribute, value))
343 {
344 return error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
345 }
346
347 return success(EGL_TRUE);
348}
349
Nicolas Capens38a9b3c2019-09-10 16:35:24 -0400350EGLSurface EGLAPIENTRY CreatePlatformWindowSurface(EGLDisplay dpy, EGLConfig config, void *native_window, const EGLAttrib *attrib_list)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400351{
Nicolas Capens48908cb2018-01-08 13:07:14 -0500352 TRACE("(EGLDisplay dpy = %p, EGLConfig config = %p, void *native_window = %p, "
353 "const EGLint *attrib_list = %p)", dpy, config, native_window, attrib_list);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400354
355 egl::Display *display = egl::Display::get(dpy);
356
Jason Macnakea6a98b2019-10-28 13:10:53 -0700357 RecursiveLockGuard lock(egl::getDisplayLock(display));
358
Nicolas Capens0bac2852016-05-07 06:09:58 -0400359 if(!validateConfig(display, config))
360 {
361 return EGL_NO_SURFACE;
362 }
363
Maksim Sisovb6fc49b2021-11-11 12:44:01 +0200364 #if defined(SWIFTSHADER_USE_X11)
Nicolas Capensde0105d2020-09-30 14:32:31 -0400365 native_window = (void *)(*(::Window*)native_window);
366 #endif
Nicolas Caramellib042f4e2020-09-18 11:22:52 +0200367
Nicolas Capens48908cb2018-01-08 13:07:14 -0500368 if(!display->isValidWindow((EGLNativeWindowType)native_window))
Nicolas Capens0bac2852016-05-07 06:09:58 -0400369 {
370 return error(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
371 }
372
Nicolas Capens48908cb2018-01-08 13:07:14 -0500373 return display->createWindowSurface((EGLNativeWindowType)native_window, config, attrib_list);
374}
375
Nicolas Capens38a9b3c2019-09-10 16:35:24 -0400376EGLSurface EGLAPIENTRY CreatePlatformWindowSurfaceEXT(EGLDisplay dpy, EGLConfig config, void *native_window, const EGLint *attrib_list)
Nicolas Capens48908cb2018-01-08 13:07:14 -0500377{
378 TRACE("(EGLDisplay dpy = %p, EGLConfig config = %p, void *native_window = %p, "
379 "const EGLint *attrib_list = %p)", dpy, config, native_window, attrib_list);
380
381 EGLAttribs attribs(attrib_list);
Nicolas Capensd7622ff2018-08-07 12:24:10 -0400382 return CreatePlatformWindowSurface(dpy, config, native_window, &attribs);
Nicolas Capens48908cb2018-01-08 13:07:14 -0500383}
384
Nicolas Capens38a9b3c2019-09-10 16:35:24 -0400385EGLSurface EGLAPIENTRY CreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType window, const EGLint *attrib_list)
Nicolas Capens48908cb2018-01-08 13:07:14 -0500386{
387 TRACE("(EGLDisplay dpy = %p, EGLConfig config = %p, EGLNativeWindowType window = %p, "
388 "const EGLint *attrib_list = %p)", dpy, config, window, attrib_list);
389
390 EGLAttribs attribs(attrib_list);
Nicolas Capensde0105d2020-09-30 14:32:31 -0400391
Maksim Sisovb6fc49b2021-11-11 12:44:01 +0200392 #if defined(SWIFTSHADER_USE_X11)
Nicolas Capensde0105d2020-09-30 14:32:31 -0400393 return CreatePlatformWindowSurface(dpy, config, (void*)&window, &attribs);
394 #else
395 return CreatePlatformWindowSurface(dpy, config, (void*)window, &attribs);
396 #endif
Nicolas Capens0bac2852016-05-07 06:09:58 -0400397}
398
Nicolas Capens38a9b3c2019-09-10 16:35:24 -0400399EGLSurface EGLAPIENTRY CreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400400{
401 TRACE("(EGLDisplay dpy = %p, EGLConfig config = %p, const EGLint *attrib_list = %p)",
402 dpy, config, attrib_list);
403
404 egl::Display *display = egl::Display::get(dpy);
405
Jason Macnakea6a98b2019-10-28 13:10:53 -0700406 RecursiveLockGuard lock(egl::getDisplayLock(display));
407
Nicolas Capens0bac2852016-05-07 06:09:58 -0400408 if(!validateConfig(display, config))
409 {
410 return EGL_NO_SURFACE;
411 }
412
413 return display->createPBufferSurface(config, attrib_list);
414}
415
Nicolas Capens38a9b3c2019-09-10 16:35:24 -0400416EGLSurface EGLAPIENTRY CreatePlatformPixmapSurface(EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLAttrib *attrib_list)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400417{
Nicolas Capens48908cb2018-01-08 13:07:14 -0500418 TRACE("(EGLDisplay dpy = %p, EGLConfig config = %p, void *native_pixmap = %p, "
419 "const EGLint *attrib_list = %p)", dpy, config, native_pixmap, attrib_list);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400420
421 egl::Display *display = egl::Display::get(dpy);
422
Jason Macnakea6a98b2019-10-28 13:10:53 -0700423 RecursiveLockGuard lock(egl::getDisplayLock(display));
424
Nicolas Capens0bac2852016-05-07 06:09:58 -0400425 if(!validateConfig(display, config))
426 {
427 return EGL_NO_SURFACE;
428 }
429
430 UNIMPLEMENTED(); // FIXME
431
432 return success(EGL_NO_SURFACE);
433}
434
Nicolas Capens38a9b3c2019-09-10 16:35:24 -0400435EGLSurface EGLAPIENTRY CreatePlatformPixmapSurfaceEXT(EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLint *attrib_list)
Nicolas Capens48908cb2018-01-08 13:07:14 -0500436{
437 TRACE("(EGLDisplay dpy = %p, EGLConfig config = %p, void *native_pixmap = %p, "
438 "const EGLint *attrib_list = %p)", dpy, config, native_pixmap, attrib_list);
439
440 EGLAttribs attribs(attrib_list);
Nicolas Capensd7622ff2018-08-07 12:24:10 -0400441 return CreatePlatformPixmapSurface(dpy, config, native_pixmap, &attribs);
Nicolas Capens48908cb2018-01-08 13:07:14 -0500442}
443
Nicolas Capens38a9b3c2019-09-10 16:35:24 -0400444EGLSurface EGLAPIENTRY CreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list)
Nicolas Capens48908cb2018-01-08 13:07:14 -0500445{
446 TRACE("(EGLDisplay dpy = %p, EGLConfig config = %p, EGLNativePixmapType pixmap = %p, "
447 "const EGLint *attrib_list = %p)", dpy, config, pixmap, attrib_list);
448
449 EGLAttribs attribs(attrib_list);
Nicolas Capensd7622ff2018-08-07 12:24:10 -0400450 return CreatePlatformPixmapSurface(dpy, config, (void*)pixmap, &attribs);
Nicolas Capens48908cb2018-01-08 13:07:14 -0500451}
452
Nicolas Capens38a9b3c2019-09-10 16:35:24 -0400453EGLBoolean EGLAPIENTRY DestroySurface(EGLDisplay dpy, EGLSurface surface)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400454{
455 TRACE("(EGLDisplay dpy = %p, EGLSurface surface = %p)", dpy, surface);
456
457 egl::Display *display = egl::Display::get(dpy);
458 egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
459
Jason Macnakea6a98b2019-10-28 13:10:53 -0700460 RecursiveLockGuard lock(egl::getDisplayLock(display));
461
Nicolas Capens0bac2852016-05-07 06:09:58 -0400462 if(!validateSurface(display, eglSurface))
463 {
464 return EGL_FALSE;
465 }
466
467 if(surface == EGL_NO_SURFACE)
468 {
469 return error(EGL_BAD_SURFACE, EGL_FALSE);
470 }
471
472 display->destroySurface((egl::Surface*)surface);
473
474 return success(EGL_TRUE);
475}
476
Nicolas Capens38a9b3c2019-09-10 16:35:24 -0400477EGLBoolean EGLAPIENTRY QuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400478{
479 TRACE("(EGLDisplay dpy = %p, EGLSurface surface = %p, EGLint attribute = %d, EGLint *value = %p)",
480 dpy, surface, attribute, value);
481
482 egl::Display *display = egl::Display::get(dpy);
483 egl::Surface *eglSurface = (egl::Surface*)surface;
484
Jason Macnakea6a98b2019-10-28 13:10:53 -0700485 RecursiveLockGuard lock(egl::getDisplayLock(display));
486
Nicolas Capens0bac2852016-05-07 06:09:58 -0400487 if(!validateSurface(display, eglSurface))
488 {
489 return EGL_FALSE;
490 }
491
492 if(surface == EGL_NO_SURFACE)
493 {
494 return error(EGL_BAD_SURFACE, EGL_FALSE);
495 }
496
497 switch(attribute)
498 {
499 case EGL_VG_ALPHA_FORMAT:
Nicolas Capensc8eedeb2018-04-12 12:50:21 -0400500 *value = EGL_VG_ALPHA_FORMAT_NONPRE; // Default
Nicolas Capens0bac2852016-05-07 06:09:58 -0400501 break;
502 case EGL_VG_COLORSPACE:
Nicolas Capensc8eedeb2018-04-12 12:50:21 -0400503 *value = EGL_VG_COLORSPACE_sRGB; // Default
Nicolas Capens0bac2852016-05-07 06:09:58 -0400504 break;
505 case EGL_CONFIG_ID:
506 *value = eglSurface->getConfigID();
507 break;
508 case EGL_HEIGHT:
509 *value = eglSurface->getHeight();
510 break;
511 case EGL_HORIZONTAL_RESOLUTION:
Nicolas Capensc8eedeb2018-04-12 12:50:21 -0400512 *value = EGL_UNKNOWN;
Nicolas Capens0bac2852016-05-07 06:09:58 -0400513 break;
514 case EGL_LARGEST_PBUFFER:
515 if(eglSurface->isPBufferSurface()) // For a window or pixmap surface, the contents of *value are not modified.
516 {
517 *value = eglSurface->getLargestPBuffer();
518 }
519 break;
520 case EGL_MIPMAP_TEXTURE:
Nicolas Capensc8eedeb2018-04-12 12:50:21 -0400521 if(eglSurface->isPBufferSurface()) // For a window or pixmap surface, the contents of *value are not modified.
522 {
523 *value = EGL_FALSE; // UNIMPLEMENTED
524 }
Nicolas Capens0bac2852016-05-07 06:09:58 -0400525 break;
526 case EGL_MIPMAP_LEVEL:
Nicolas Capensc8eedeb2018-04-12 12:50:21 -0400527 if(eglSurface->isPBufferSurface()) // For a window or pixmap surface, the contents of *value are not modified.
528 {
529 *value = eglSurface->getMipmapLevel();
530 }
Nicolas Capens0bac2852016-05-07 06:09:58 -0400531 break;
532 case EGL_MULTISAMPLE_RESOLVE:
Nicolas Capensc8eedeb2018-04-12 12:50:21 -0400533 *value = eglSurface->getMultisampleResolve();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400534 break;
535 case EGL_PIXEL_ASPECT_RATIO:
536 *value = eglSurface->getPixelAspectRatio();
537 break;
538 case EGL_RENDER_BUFFER:
539 *value = eglSurface->getRenderBuffer();
540 break;
541 case EGL_SWAP_BEHAVIOR:
542 *value = eglSurface->getSwapBehavior();
543 break;
544 case EGL_TEXTURE_FORMAT:
Nicolas Capensc8eedeb2018-04-12 12:50:21 -0400545 if(eglSurface->isPBufferSurface()) // For a window or pixmap surface, the contents of *value are not modified.
546 {
547 *value = eglSurface->getTextureFormat();
548 }
Nicolas Capens0bac2852016-05-07 06:09:58 -0400549 break;
550 case EGL_TEXTURE_TARGET:
Nicolas Capensc8eedeb2018-04-12 12:50:21 -0400551 if(eglSurface->isPBufferSurface()) // For a window or pixmap surface, the contents of *value are not modified.
552 {
553 *value = eglSurface->getTextureTarget();
554 }
Nicolas Capens0bac2852016-05-07 06:09:58 -0400555 break;
556 case EGL_VERTICAL_RESOLUTION:
Nicolas Capensc8eedeb2018-04-12 12:50:21 -0400557 *value = EGL_UNKNOWN;
Nicolas Capens0bac2852016-05-07 06:09:58 -0400558 break;
559 case EGL_WIDTH:
560 *value = eglSurface->getWidth();
561 break;
562 default:
563 return error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
564 }
565
566 return success(EGL_TRUE);
567}
568
Nicolas Capens38a9b3c2019-09-10 16:35:24 -0400569EGLBoolean EGLAPIENTRY BindAPI(EGLenum api)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400570{
571 TRACE("(EGLenum api = 0x%X)", api);
572
573 switch(api)
574 {
575 case EGL_OPENGL_API:
576 case EGL_OPENVG_API:
577 return error(EGL_BAD_PARAMETER, EGL_FALSE); // Not supported by this implementation
578 case EGL_OPENGL_ES_API:
579 break;
580 default:
581 return error(EGL_BAD_PARAMETER, EGL_FALSE);
582 }
583
584 egl::setCurrentAPI(api);
585
586 return success(EGL_TRUE);
587}
588
Nicolas Capens38a9b3c2019-09-10 16:35:24 -0400589EGLenum EGLAPIENTRY QueryAPI(void)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400590{
591 TRACE("()");
592
593 EGLenum API = egl::getCurrentAPI();
594
595 return success(API);
596}
597
Nicolas Capens38a9b3c2019-09-10 16:35:24 -0400598EGLBoolean EGLAPIENTRY WaitClient(void)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400599{
600 TRACE("()");
601
Alexis Hetuf3a124f2018-01-15 15:49:42 -0500602 // eglWaitClient is ignored if there is no current EGL rendering context for the current rendering API.
603 egl::Context *context = egl::getCurrentContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400604
Alexis Hetuf3a124f2018-01-15 15:49:42 -0500605 if(context)
606 {
607 context->finish();
608 }
609
610 return success(EGL_TRUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400611}
612
Nicolas Capens38a9b3c2019-09-10 16:35:24 -0400613EGLBoolean EGLAPIENTRY ReleaseThread(void)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400614{
615 TRACE("()");
616
Nicolas Capenscc5c7d92016-06-13 14:35:11 -0400617 detachThread();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400618
Nicolas Capens660eba92017-09-05 14:06:06 -0400619 return EGL_TRUE; // success() is not called here because it would re-allocate thread-local storage.
Nicolas Capens0bac2852016-05-07 06:09:58 -0400620}
621
Nicolas Capens38a9b3c2019-09-10 16:35:24 -0400622EGLSurface EGLAPIENTRY CreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400623{
624 TRACE("(EGLDisplay dpy = %p, EGLenum buftype = 0x%X, EGLClientBuffer buffer = %p, "
625 "EGLConfig config = %p, const EGLint *attrib_list = %p)",
626 dpy, buftype, buffer, config, attrib_list);
627
Alexis Hetuc80eada2018-02-13 15:02:40 -0500628 switch(buftype)
629 {
630 case EGL_IOSURFACE_ANGLE:
631 {
632 egl::Display *display = egl::Display::get(dpy);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400633
Jason Macnakea6a98b2019-10-28 13:10:53 -0700634 RecursiveLockGuard lock(egl::getDisplayLock(display));
635
Alexis Hetuc80eada2018-02-13 15:02:40 -0500636 if(!validateConfig(display, config))
637 {
638 return EGL_NO_SURFACE;
639 }
640
641 return display->createPBufferSurface(config, attrib_list, buffer);
642 }
643 case EGL_OPENVG_IMAGE:
644 UNIMPLEMENTED();
645 return error(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
646 default:
647 return error(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
648 };
Nicolas Capens0bac2852016-05-07 06:09:58 -0400649}
650
Nicolas Capens38a9b3c2019-09-10 16:35:24 -0400651EGLBoolean EGLAPIENTRY SurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400652{
653 TRACE("(EGLDisplay dpy = %p, EGLSurface surface = %p, EGLint attribute = %d, EGLint value = %d)",
654 dpy, surface, attribute, value);
655
656 egl::Display *display = egl::Display::get(dpy);
657 egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
658
Jason Macnakea6a98b2019-10-28 13:10:53 -0700659 RecursiveLockGuard lock(egl::getDisplayLock(display));
660
Nicolas Capens0bac2852016-05-07 06:09:58 -0400661 if(!validateSurface(display, eglSurface))
662 {
663 return EGL_FALSE;
664 }
665
666 switch(attribute)
667 {
Nicolas Capensc8eedeb2018-04-12 12:50:21 -0400668 case EGL_MIPMAP_LEVEL:
669 eglSurface->setMipmapLevel(value);
670 break;
671 case EGL_MULTISAMPLE_RESOLVE:
672 switch(value)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400673 {
Nicolas Capensc8eedeb2018-04-12 12:50:21 -0400674 case EGL_MULTISAMPLE_RESOLVE_DEFAULT:
675 break;
676 case EGL_MULTISAMPLE_RESOLVE_BOX:
677 if(!(eglSurface->getSurfaceType() & EGL_MULTISAMPLE_RESOLVE_BOX_BIT))
678 {
679 return error(EGL_BAD_MATCH, EGL_FALSE);
680 }
681 break;
682 default:
683 return error(EGL_BAD_PARAMETER, EGL_FALSE);
684 }
685 eglSurface->setMultisampleResolve(value);
686 break;
687 case EGL_SWAP_BEHAVIOR:
688 switch(value)
689 {
690 case EGL_BUFFER_DESTROYED:
691 break;
692 case EGL_BUFFER_PRESERVED:
Nicolas Capens0bac2852016-05-07 06:09:58 -0400693 if(!(eglSurface->getSurfaceType() & EGL_SWAP_BEHAVIOR_PRESERVED_BIT))
694 {
695 return error(EGL_BAD_MATCH, EGL_FALSE);
696 }
Nicolas Capensc8eedeb2018-04-12 12:50:21 -0400697 break;
698 default:
Nicolas Capens0bac2852016-05-07 06:09:58 -0400699 return error(EGL_BAD_PARAMETER, EGL_FALSE);
700 }
701 eglSurface->setSwapBehavior(value);
702 break;
703 default:
Nicolas Capensc8eedeb2018-04-12 12:50:21 -0400704 return error(EGL_BAD_PARAMETER, EGL_FALSE);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400705 }
706
707 return success(EGL_TRUE);
708}
709
Nicolas Capens38a9b3c2019-09-10 16:35:24 -0400710EGLBoolean EGLAPIENTRY BindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400711{
712 TRACE("(EGLDisplay dpy = %p, EGLSurface surface = %p, EGLint buffer = %d)", dpy, surface, buffer);
713
714 egl::Display *display = egl::Display::get(dpy);
715 egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
716
Jason Macnakea6a98b2019-10-28 13:10:53 -0700717 RecursiveLockGuard lock(egl::getDisplayLock(display));
718
Nicolas Capens0bac2852016-05-07 06:09:58 -0400719 if(!validateSurface(display, eglSurface))
720 {
721 return EGL_FALSE;
722 }
723
724 if(buffer != EGL_BACK_BUFFER)
725 {
726 return error(EGL_BAD_PARAMETER, EGL_FALSE);
727 }
728
729 if(surface == EGL_NO_SURFACE || eglSurface->isWindowSurface())
730 {
731 return error(EGL_BAD_SURFACE, EGL_FALSE);
732 }
733
734 if(eglSurface->getBoundTexture())
735 {
736 return error(EGL_BAD_ACCESS, EGL_FALSE);
737 }
738
739 if(eglSurface->getTextureFormat() == EGL_NO_TEXTURE)
740 {
741 return error(EGL_BAD_MATCH, EGL_FALSE);
742 }
743
744 egl::Context *context = egl::getCurrentContext();
745
746 if(context)
747 {
748 context->bindTexImage(eglSurface);
749 }
750
751 return success(EGL_TRUE);
752}
753
Nicolas Capens38a9b3c2019-09-10 16:35:24 -0400754EGLBoolean EGLAPIENTRY ReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400755{
756 TRACE("(EGLDisplay dpy = %p, EGLSurface surface = %p, EGLint buffer = %d)", dpy, surface, buffer);
757
758 egl::Display *display = egl::Display::get(dpy);
759 egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
760
Jason Macnakea6a98b2019-10-28 13:10:53 -0700761 RecursiveLockGuard lock(egl::getDisplayLock(display));
762
Nicolas Capens0bac2852016-05-07 06:09:58 -0400763 if(!validateSurface(display, eglSurface))
764 {
765 return EGL_FALSE;
766 }
767
768 if(buffer != EGL_BACK_BUFFER)
769 {
770 return error(EGL_BAD_PARAMETER, EGL_FALSE);
771 }
772
773 if(surface == EGL_NO_SURFACE || eglSurface->isWindowSurface())
774 {
775 return error(EGL_BAD_SURFACE, EGL_FALSE);
776 }
777
778 if(eglSurface->getTextureFormat() == EGL_NO_TEXTURE)
779 {
780 return error(EGL_BAD_MATCH, EGL_FALSE);
781 }
782
783 egl::Texture *texture = eglSurface->getBoundTexture();
784
785 if(texture)
786 {
787 texture->releaseTexImage();
788 }
789
790 return success(EGL_TRUE);
791}
792
Nicolas Capens38a9b3c2019-09-10 16:35:24 -0400793EGLBoolean EGLAPIENTRY SwapInterval(EGLDisplay dpy, EGLint interval)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400794{
795 TRACE("(EGLDisplay dpy = %p, EGLint interval = %d)", dpy, interval);
796
797 egl::Display *display = egl::Display::get(dpy);
798 egl::Context *context = egl::getCurrentContext();
799
Jason Macnakea6a98b2019-10-28 13:10:53 -0700800 RecursiveLockGuard lock(egl::getDisplayLock(display));
801
Nicolas Capens0bac2852016-05-07 06:09:58 -0400802 if(!validateContext(display, context))
803 {
804 return EGL_FALSE;
805 }
806
807 egl::Surface *draw_surface = static_cast<egl::Surface*>(egl::getCurrentDrawSurface());
808
809 if(!draw_surface)
810 {
811 return error(EGL_BAD_SURFACE, EGL_FALSE);
812 }
813
814 draw_surface->setSwapInterval(interval);
815
816 return success(EGL_TRUE);
817}
818
Nicolas Capens38a9b3c2019-09-10 16:35:24 -0400819EGLContext EGLAPIENTRY CreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400820{
821 TRACE("(EGLDisplay dpy = %p, EGLConfig config = %p, EGLContext share_context = %p, "
822 "const EGLint *attrib_list = %p)", dpy, config, share_context, attrib_list);
823
Alexis Hetub75bb022016-05-18 11:43:43 -0400824 EGLint majorVersion = 1;
825 EGLint minorVersion = 0;
826
Nicolas Capens0bac2852016-05-07 06:09:58 -0400827 if(attrib_list)
828 {
829 for(const EGLint* attribute = attrib_list; attribute[0] != EGL_NONE; attribute += 2)
830 {
Alexis Hetub75bb022016-05-18 11:43:43 -0400831 switch(attribute[0])
Nicolas Capens0bac2852016-05-07 06:09:58 -0400832 {
Alexis Hetub75bb022016-05-18 11:43:43 -0400833 case EGL_CONTEXT_MAJOR_VERSION_KHR: // This token is an alias for EGL_CONTEXT_CLIENT_VERSION
834 majorVersion = attribute[1];
835 break;
836 case EGL_CONTEXT_MINOR_VERSION_KHR:
837 minorVersion = attribute[1];
838 break;
839 case EGL_CONTEXT_FLAGS_KHR:
840 switch(attribute[1])
841 {
842 case EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR:
843 // According to the EGL_KHR_create_context spec:
844 // "Khronos is still defining the expected and required features of debug contexts, so
845 // implementations are currently free to implement "debug contexts" with little or no debug
846 // functionality. However, OpenGL and OpenGL ES implementations supporting the GL_KHR_debug
847 // extension should enable it when this bit is set."
848 break;
849 case EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR:
850 case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR:
851 // These bits are for OpenGL contexts only, not OpenGL ES contexts
852 return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
853 default:
854 return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
855 }
856 break;
857 case EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR:
858 switch(attribute[1])
859 {
860 case EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR:
861 case EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR:
862 // These bits are for OpenGL contexts only, not OpenGL ES contexts
863 return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
864 default:
865 return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
866 }
867 break;
868 case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR:
869 switch(attribute[1])
870 {
871 case EGL_NO_RESET_NOTIFICATION_KHR:
872 case EGL_LOSE_CONTEXT_ON_RESET_KHR:
873 // These bits are for OpenGL contexts only, not OpenGL ES contexts
874 return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
875 default:
876 return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
877 }
878 break;
879 default:
Nicolas Capens0bac2852016-05-07 06:09:58 -0400880 return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
881 }
882 }
883 }
884
Alexis Hetub75bb022016-05-18 11:43:43 -0400885 switch(majorVersion)
886 {
887 case 1:
888 if(minorVersion != 0 && minorVersion != 1)
889 {
890 // 1.X: Only OpenGL ES 1.0 and 1.1 contexts are supported
891 return error(EGL_BAD_MATCH, EGL_NO_CONTEXT);
892 }
893 break;
894 case 2:
895 case 3:
896 if(minorVersion != 0)
897 {
898 // 2.X and 3.X: Only OpenGL ES 2.0 and 3.0 contexts are currently supported
899 return error(EGL_BAD_MATCH, EGL_NO_CONTEXT);
900 }
901 break;
902 default:
903 return error(EGL_BAD_MATCH, EGL_NO_CONTEXT);
904 }
905
Nicolas Capens0bac2852016-05-07 06:09:58 -0400906 egl::Display *display = egl::Display::get(dpy);
907 egl::Context *shareContext = static_cast<egl::Context*>(share_context);
908
Jason Macnakea6a98b2019-10-28 13:10:53 -0700909 RecursiveLockGuard lock(egl::getDisplayLock(display));
910
Nicolas Capens0bac2852016-05-07 06:09:58 -0400911 if(!validateConfig(display, config))
912 {
913 return EGL_NO_CONTEXT;
914 }
915
Chris Forbes5fb5e812018-08-30 17:28:59 -0700916 // Allow sharing between different context versions >= 2.0, but isolate 1.x
917 // contexts from 2.0+. Strict matching between context versions >= 2.0 is
918 // confusing for apps to navigate because of version promotion.
919 if(shareContext && ((shareContext->getClientVersion() >= 2) ^ (majorVersion >= 2)))
Nicolas Capens0bac2852016-05-07 06:09:58 -0400920 {
921 return error(EGL_BAD_CONTEXT, EGL_NO_CONTEXT);
922 }
923
Alexis Hetub75bb022016-05-18 11:43:43 -0400924 return display->createContext(config, shareContext, majorVersion);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400925}
926
Nicolas Capens38a9b3c2019-09-10 16:35:24 -0400927EGLBoolean EGLAPIENTRY DestroyContext(EGLDisplay dpy, EGLContext ctx)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400928{
929 TRACE("(EGLDisplay dpy = %p, EGLContext ctx = %p)", dpy, ctx);
930
931 egl::Display *display = egl::Display::get(dpy);
932 egl::Context *context = static_cast<egl::Context*>(ctx);
933
Jason Macnakea6a98b2019-10-28 13:10:53 -0700934 RecursiveLockGuard lock(egl::getDisplayLock(display));
935
Nicolas Capens0bac2852016-05-07 06:09:58 -0400936 if(!validateContext(display, context))
937 {
938 return EGL_FALSE;
939 }
940
941 if(ctx == EGL_NO_CONTEXT)
942 {
943 return error(EGL_BAD_CONTEXT, EGL_FALSE);
944 }
945
946 display->destroyContext(context);
947
948 return success(EGL_TRUE);
949}
950
Nicolas Capens38a9b3c2019-09-10 16:35:24 -0400951EGLBoolean EGLAPIENTRY MakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400952{
953 TRACE("(EGLDisplay dpy = %p, EGLSurface draw = %p, EGLSurface read = %p, EGLContext ctx = %p)",
954 dpy, draw, read, ctx);
955
956 egl::Display *display = egl::Display::get(dpy);
957 egl::Context *context = static_cast<egl::Context*>(ctx);
958 egl::Surface *drawSurface = static_cast<egl::Surface*>(draw);
959 egl::Surface *readSurface = static_cast<egl::Surface*>(read);
960
Jason Macnakea6a98b2019-10-28 13:10:53 -0700961 RecursiveLockGuard lock(egl::getDisplayLock(display));
962
Nicolas Capens0bac2852016-05-07 06:09:58 -0400963 if(ctx != EGL_NO_CONTEXT || draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE)
964 {
965 if(!validateDisplay(display))
966 {
967 return EGL_FALSE;
968 }
969 }
970
971 if(ctx == EGL_NO_CONTEXT && (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE))
972 {
973 return error(EGL_BAD_MATCH, EGL_FALSE);
974 }
975
976 if(ctx != EGL_NO_CONTEXT && !validateContext(display, context))
977 {
978 return EGL_FALSE;
979 }
980
981 if((draw != EGL_NO_SURFACE && !validateSurface(display, drawSurface)) ||
982 (read != EGL_NO_SURFACE && !validateSurface(display, readSurface)))
983 {
984 return EGL_FALSE;
985 }
986
987 if((draw != EGL_NO_SURFACE) ^ (read != EGL_NO_SURFACE))
988 {
989 return error(EGL_BAD_MATCH, EGL_FALSE);
990 }
991
992 if(draw != read)
993 {
994 UNIMPLEMENTED(); // FIXME
995 }
996
Nicolas Capens0bac2852016-05-07 06:09:58 -0400997 egl::setCurrentDrawSurface(drawSurface);
998 egl::setCurrentReadSurface(readSurface);
999 egl::setCurrentContext(context);
1000
1001 if(context)
1002 {
1003 context->makeCurrent(drawSurface);
1004 }
1005
1006 return success(EGL_TRUE);
1007}
1008
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04001009EGLContext EGLAPIENTRY GetCurrentContext(void)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001010{
1011 TRACE("()");
1012
1013 EGLContext context = egl::getCurrentContext();
1014
1015 return success(context);
1016}
1017
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04001018EGLSurface EGLAPIENTRY GetCurrentSurface(EGLint readdraw)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001019{
1020 TRACE("(EGLint readdraw = %d)", readdraw);
1021
1022 if(readdraw == EGL_READ)
1023 {
1024 EGLSurface read = egl::getCurrentReadSurface();
1025 return success(read);
1026 }
1027 else if(readdraw == EGL_DRAW)
1028 {
1029 EGLSurface draw = egl::getCurrentDrawSurface();
1030 return success(draw);
1031 }
1032 else
1033 {
1034 return error(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
1035 }
1036}
1037
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04001038EGLDisplay EGLAPIENTRY GetCurrentDisplay(void)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001039{
1040 TRACE("()");
1041
Nicolas Capens8aca1df2017-06-15 14:15:30 -07001042 egl::Context *context = egl::getCurrentContext();
1043
1044 if(!context)
1045 {
1046 return success(EGL_NO_DISPLAY);
1047 }
1048
Nicolas Capense88da312017-07-10 14:26:17 -04001049 egl::Display *display = context->getDisplay();
1050
1051 if(!display)
1052 {
1053 return error(EGL_BAD_ACCESS, EGL_NO_DISPLAY);
1054 }
1055
1056 return success(display->getEGLDisplay());
Nicolas Capens0bac2852016-05-07 06:09:58 -04001057}
1058
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04001059EGLBoolean EGLAPIENTRY QueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001060{
1061 TRACE("(EGLDisplay dpy = %p, EGLContext ctx = %p, EGLint attribute = %d, EGLint *value = %p)",
1062 dpy, ctx, attribute, value);
1063
1064 egl::Display *display = egl::Display::get(dpy);
1065 egl::Context *context = static_cast<egl::Context*>(ctx);
1066
Jason Macnakea6a98b2019-10-28 13:10:53 -07001067 RecursiveLockGuard lock(egl::getDisplayLock(display));
1068
Nicolas Capens0bac2852016-05-07 06:09:58 -04001069 if(!validateContext(display, context))
1070 {
1071 return EGL_FALSE;
1072 }
1073
Nicolas Capensf6a377b2017-05-19 09:31:35 -04001074 switch(attribute)
1075 {
Nicolas Capensdf0be382017-06-05 17:43:46 -04001076 case EGL_CONFIG_ID:
1077 *value = context->getConfigID();
1078 break;
1079 case EGL_CONTEXT_CLIENT_TYPE:
1080 *value = egl::getCurrentAPI();
1081 break;
Nicolas Capensf6a377b2017-05-19 09:31:35 -04001082 case EGL_CONTEXT_CLIENT_VERSION:
1083 *value = context->getClientVersion();
1084 break;
1085 case EGL_RENDER_BUFFER:
Nicolas Capensdf0be382017-06-05 17:43:46 -04001086 *value = EGL_BACK_BUFFER;
Nicolas Capensf6a377b2017-05-19 09:31:35 -04001087 break;
1088 default:
1089 return error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
1090 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04001091
Nicolas Capensf6a377b2017-05-19 09:31:35 -04001092 return success(EGL_TRUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001093}
1094
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04001095EGLBoolean EGLAPIENTRY WaitGL(void)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001096{
1097 TRACE("()");
1098
Alexis Hetuf3a124f2018-01-15 15:49:42 -05001099 // glWaitGL is ignored if there is no current EGL rendering context for OpenGL ES.
1100 egl::Context *context = egl::getCurrentContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001101
Alexis Hetuf3a124f2018-01-15 15:49:42 -05001102 if(context)
1103 {
1104 context->finish();
1105 }
1106
1107 return success(EGL_TRUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001108}
1109
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04001110EGLBoolean EGLAPIENTRY WaitNative(EGLint engine)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001111{
1112 TRACE("(EGLint engine = %d)", engine);
1113
Alexis Hetuf3a124f2018-01-15 15:49:42 -05001114 if(engine != EGL_CORE_NATIVE_ENGINE)
1115 {
1116 return error(EGL_BAD_PARAMETER, EGL_FALSE);
1117 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04001118
Alexis Hetuf3a124f2018-01-15 15:49:42 -05001119 // eglWaitNative is ignored if there is no current EGL rendering context.
1120 egl::Context *context = egl::getCurrentContext();
1121
1122 if(context)
1123 {
Maksim Sisovb6fc49b2021-11-11 12:44:01 +02001124 #if defined(SWIFTSHADER_USE_X11)
Alexis Hetuf3a124f2018-01-15 15:49:42 -05001125 egl::Display *display = context->getDisplay();
1126
1127 if(!display)
1128 {
1129 return error(EGL_BAD_DISPLAY, EGL_FALSE);
1130 }
1131
1132 libX11->XSync((::Display*)display->getNativeDisplay(), False);
1133 #else
1134 UNIMPLEMENTED();
1135 #endif
1136 }
1137
1138 return success(EGL_TRUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001139}
1140
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04001141EGLBoolean EGLAPIENTRY SwapBuffers(EGLDisplay dpy, EGLSurface surface)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001142{
1143 TRACE("(EGLDisplay dpy = %p, EGLSurface surface = %p)", dpy, surface);
1144
1145 egl::Display *display = egl::Display::get(dpy);
1146 egl::Surface *eglSurface = (egl::Surface*)surface;
1147
Nicolas Capens0bac2852016-05-07 06:09:58 -04001148 {
Jason Macnak855e8b12019-10-28 16:17:18 -07001149 RecursiveLockGuard lock(egl::getDisplayLock(display));
1150
1151 if(!validateSurface(display, eglSurface))
1152 {
1153 return EGL_FALSE;
1154 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04001155 }
1156
1157 if(surface == EGL_NO_SURFACE)
1158 {
1159 return error(EGL_BAD_SURFACE, EGL_FALSE);
1160 }
1161
1162 eglSurface->swap();
1163
1164 return success(EGL_TRUE);
1165}
1166
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04001167EGLBoolean EGLAPIENTRY CopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001168{
1169 TRACE("(EGLDisplay dpy = %p, EGLSurface surface = %p, EGLNativePixmapType target = %p)", dpy, surface, target);
1170
1171 egl::Display *display = egl::Display::get(dpy);
1172 egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
1173
Jason Macnakea6a98b2019-10-28 13:10:53 -07001174 RecursiveLockGuard lock(egl::getDisplayLock(display));
1175
Nicolas Capens0bac2852016-05-07 06:09:58 -04001176 if(!validateSurface(display, eglSurface))
1177 {
1178 return EGL_FALSE;
1179 }
1180
1181 UNIMPLEMENTED(); // FIXME
1182
1183 return success(EGL_FALSE);
1184}
1185
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04001186EGLImage EGLAPIENTRY CreateImage(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLAttrib *attrib_list)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001187{
Nicolas Capens48908cb2018-01-08 13:07:14 -05001188 TRACE("(EGLDisplay dpy = %p, EGLContext ctx = %p, EGLenum target = 0x%X, buffer = %p, const EGLAttrib *attrib_list = %p)", dpy, ctx, target, buffer, attrib_list);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001189
1190 egl::Display *display = egl::Display::get(dpy);
1191 egl::Context *context = static_cast<egl::Context*>(ctx);
1192
Jason Macnakea6a98b2019-10-28 13:10:53 -07001193 RecursiveLockGuard lock(egl::getDisplayLock(display));
1194
Nicolas Capens0bac2852016-05-07 06:09:58 -04001195 if(!validateDisplay(display))
1196 {
1197 return error(EGL_BAD_DISPLAY, EGL_NO_IMAGE_KHR);
1198 }
1199
1200 if(context != EGL_NO_CONTEXT && !display->isValidContext(context))
1201 {
1202 return error(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
1203 }
1204
1205 EGLenum imagePreserved = EGL_FALSE;
Ben Claytonf4b99b62019-02-19 16:50:48 +00001206 (void)imagePreserved; // currently unused
1207
Nicolas Capens0bac2852016-05-07 06:09:58 -04001208 GLuint textureLevel = 0;
1209 if(attrib_list)
1210 {
Nicolas Capens48908cb2018-01-08 13:07:14 -05001211 for(const EGLAttrib *attribute = attrib_list; attribute[0] != EGL_NONE; attribute += 2)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001212 {
1213 if(attribute[0] == EGL_IMAGE_PRESERVED_KHR)
1214 {
Nicolas Capens48908cb2018-01-08 13:07:14 -05001215 imagePreserved = static_cast<EGLenum>(attribute[1]);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001216 }
1217 else if(attribute[0] == EGL_GL_TEXTURE_LEVEL_KHR)
1218 {
Nicolas Capens48908cb2018-01-08 13:07:14 -05001219 textureLevel = static_cast<GLuint>(attribute[1]);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001220 }
1221 else
1222 {
1223 return error(EGL_BAD_ATTRIBUTE, EGL_NO_IMAGE_KHR);
1224 }
1225 }
1226 }
1227
Stephen Whitee6ab01f2019-04-04 14:31:25 -04001228 #if defined(__ANDROID__) && !defined(ANDROID_NDK_BUILD)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001229 if(target == EGL_NATIVE_BUFFER_ANDROID)
1230 {
1231 ANativeWindowBuffer *nativeBuffer = reinterpret_cast<ANativeWindowBuffer*>(buffer);
1232
1233 if(!nativeBuffer || GLPixelFormatFromAndroid(nativeBuffer->format) == GL_NONE)
1234 {
Alistair Strachanc28d28a2018-03-24 12:24:00 -07001235 ERR("%s badness unsupported HAL format=%x", __FUNCTION__, nativeBuffer ? nativeBuffer->format : 0);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001236 return error(EGL_BAD_ATTRIBUTE, EGL_NO_IMAGE_KHR);
1237 }
1238
Nicolas Capens58df2f62016-06-07 14:48:56 -04001239 Image *image = new AndroidNativeImage(nativeBuffer);
1240 EGLImageKHR eglImage = display->createSharedImage(image);
1241
1242 return success(eglImage);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001243 }
1244 #endif
1245
Nicolas Capens3a795c62016-06-30 10:38:12 -04001246 GLuint name = static_cast<GLuint>(reinterpret_cast<uintptr_t>(buffer));
Nicolas Capens0bac2852016-05-07 06:09:58 -04001247
1248 if(name == 0)
1249 {
1250 return error(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
1251 }
1252
1253 EGLenum validationResult = context->validateSharedImage(target, name, textureLevel);
1254
1255 if(validationResult != EGL_SUCCESS)
1256 {
1257 return error(validationResult, EGL_NO_IMAGE_KHR);
1258 }
1259
Nicolas Capens58df2f62016-06-07 14:48:56 -04001260 Image *image = context->createSharedImage(target, name, textureLevel);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001261
1262 if(!image)
1263 {
1264 return error(EGL_BAD_MATCH, EGL_NO_IMAGE_KHR);
1265 }
1266
1267 if(image->getDepth() > 1)
1268 {
1269 return error(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
1270 }
1271
Nicolas Capens48908cb2018-01-08 13:07:14 -05001272 EGLImage eglImage = display->createSharedImage(image);
Nicolas Capens58df2f62016-06-07 14:48:56 -04001273
1274 return success(eglImage);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001275}
1276
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04001277EGLImageKHR EGLAPIENTRY CreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list)
Nicolas Capens48908cb2018-01-08 13:07:14 -05001278{
1279 TRACE("(EGLDisplay dpy = %p, EGLContext ctx = %p, EGLenum target = 0x%X, buffer = %p, const EGLint attrib_list = %p)", dpy, ctx, target, buffer, attrib_list);
1280
1281 EGLAttribs attribs(attrib_list);
Nicolas Capensd7622ff2018-08-07 12:24:10 -04001282 return CreateImage(dpy, ctx, target, buffer, &attribs);
Nicolas Capens48908cb2018-01-08 13:07:14 -05001283}
1284
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04001285EGLBoolean EGLAPIENTRY DestroyImageKHR(EGLDisplay dpy, EGLImageKHR image)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001286{
1287 TRACE("(EGLDisplay dpy = %p, EGLImageKHR image = %p)", dpy, image);
1288
1289 egl::Display *display = egl::Display::get(dpy);
1290
Jason Macnakea6a98b2019-10-28 13:10:53 -07001291 RecursiveLockGuard lock(egl::getDisplayLock(display));
1292
Nicolas Capens0bac2852016-05-07 06:09:58 -04001293 if(!validateDisplay(display))
1294 {
1295 return error(EGL_BAD_DISPLAY, EGL_FALSE);
1296 }
1297
Nicolas Capens58df2f62016-06-07 14:48:56 -04001298 if(!display->destroySharedImage(image))
Nicolas Capens0bac2852016-05-07 06:09:58 -04001299 {
1300 return error(EGL_BAD_PARAMETER, EGL_FALSE);
1301 }
1302
Nicolas Capens0bac2852016-05-07 06:09:58 -04001303 return success(EGL_TRUE);
1304}
1305
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04001306EGLDisplay EGLAPIENTRY GetPlatformDisplay(EGLenum platform, void *native_display, const EGLAttrib *attrib_list)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001307{
Nicolas Capens48908cb2018-01-08 13:07:14 -05001308 TRACE("(EGLenum platform = 0x%X, void *native_display = %p, const EGLAttrib *attrib_list = %p)", platform, native_display, attrib_list);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001309
Nicolas Capens0bac2852016-05-07 06:09:58 -04001310 #if defined(__linux__) && !defined(__ANDROID__)
Alexis Hetu1d672442016-06-23 11:24:00 -04001311 switch(platform)
1312 {
Maksim Sisovb6fc49b2021-11-11 12:44:01 +02001313 #if defined(SWIFTSHADER_USE_X11)
Alexis Hetuc47cd432018-08-10 11:48:33 -04001314 case EGL_PLATFORM_X11_EXT: break;
1315 #endif
1316 case EGL_PLATFORM_GBM_KHR: break;
Alexis Hetu1d672442016-06-23 11:24:00 -04001317 default:
1318 return error(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
1319 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04001320
Alexis Hetuc47cd432018-08-10 11:48:33 -04001321 if(platform == EGL_PLATFORM_GBM_KHR)
1322 {
1323 if(native_display != (void*)EGL_DEFAULT_DISPLAY)
1324 {
1325 return error(EGL_BAD_PARAMETER, EGL_NO_DISPLAY); // Unimplemented
1326 }
1327
1328 if(attrib_list && attrib_list[0] != EGL_NONE)
1329 {
1330 return error(EGL_BAD_ATTRIBUTE, EGL_NO_DISPLAY); // Unimplemented
1331 }
1332
1333 return success(HEADLESS_DISPLAY);
1334 }
Maksim Sisovb6fc49b2021-11-11 12:44:01 +02001335 #if defined(SWIFTSHADER_USE_X11)
Alexis Hetuc47cd432018-08-10 11:48:33 -04001336 else if(platform == EGL_PLATFORM_X11_EXT)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001337 {
1338 if(!libX11)
1339 {
Nicolas Capensd7622ff2018-08-07 12:24:10 -04001340 return error(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001341 }
1342
Nicolas Capensd7622ff2018-08-07 12:24:10 -04001343 if(native_display != (void*)EGL_DEFAULT_DISPLAY)
1344 {
1345 return error(EGL_BAD_PARAMETER, EGL_NO_DISPLAY); // Unimplemented
1346 }
1347
1348 if(attrib_list && attrib_list[0] != EGL_NONE)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001349 {
1350 return error(EGL_BAD_ATTRIBUTE, EGL_NO_DISPLAY); // Unimplemented
1351 }
1352 }
Alexis Hetuc47cd432018-08-10 11:48:33 -04001353 #endif
Nicolas Capens0bac2852016-05-07 06:09:58 -04001354
Alexis Hetu1d672442016-06-23 11:24:00 -04001355 return success(PRIMARY_DISPLAY); // We only support the default display
1356 #else
1357 return error(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
1358 #endif
Nicolas Capens0bac2852016-05-07 06:09:58 -04001359}
1360
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04001361EGLDisplay EGLAPIENTRY GetPlatformDisplayEXT(EGLenum platform, void *native_display, const EGLint *attrib_list)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001362{
Nicolas Capens48908cb2018-01-08 13:07:14 -05001363 TRACE("(EGLenum platform = 0x%X, void *native_display = %p, const EGLint *attrib_list = %p)", platform, native_display, attrib_list);
1364
1365 EGLAttribs attribs(attrib_list);
Nicolas Capensd7622ff2018-08-07 12:24:10 -04001366 return GetPlatformDisplay(platform, native_display, &attribs);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001367}
1368
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04001369EGLSync EGLAPIENTRY CreateSync(EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001370{
Nicolas Capens48908cb2018-01-08 13:07:14 -05001371 TRACE("(EGLDisplay dpy = %p, EGLunum type = %x, EGLAttrib *attrib_list=%p)", dpy, type, attrib_list);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001372
1373 egl::Display *display = egl::Display::get(dpy);
1374
Jason Macnakea6a98b2019-10-28 13:10:53 -07001375 RecursiveLockGuard lock(egl::getDisplayLock(display));
1376
Nicolas Capens0bac2852016-05-07 06:09:58 -04001377 if(!validateDisplay(display))
1378 {
1379 return error(EGL_BAD_DISPLAY, EGL_NO_SYNC_KHR);
1380 }
1381
1382 if(type != EGL_SYNC_FENCE_KHR)
1383 {
1384 return error(EGL_BAD_ATTRIBUTE, EGL_NO_SYNC_KHR);
1385 }
1386
1387 if(attrib_list && attrib_list[0] != EGL_NONE)
1388 {
1389 return error(EGL_BAD_ATTRIBUTE, EGL_NO_SYNC_KHR);
1390 }
1391
1392 egl::Context *context = egl::getCurrentContext();
1393
1394 if(!validateContext(display, context))
1395 {
1396 return error(EGL_BAD_MATCH, EGL_NO_SYNC_KHR);
1397 }
1398
1399 EGLSyncKHR sync = display->createSync(context);
1400
1401 return success(sync);
1402}
1403
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04001404EGLSyncKHR EGLAPIENTRY CreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
Nicolas Capens48908cb2018-01-08 13:07:14 -05001405{
1406 TRACE("(EGLDisplay dpy = %p, EGLunum type = %x, EGLint *attrib_list=%p)", dpy, type, attrib_list);
1407
1408 EGLAttribs attribs(attrib_list);
Nicolas Capensd7622ff2018-08-07 12:24:10 -04001409 return CreateSync(dpy, type, &attribs);
Nicolas Capens48908cb2018-01-08 13:07:14 -05001410}
1411
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04001412EGLBoolean EGLAPIENTRY DestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001413{
1414 TRACE("(EGLDisplay dpy = %p, EGLSyncKHR sync = %p)", dpy, sync);
1415
1416 egl::Display *display = egl::Display::get(dpy);
1417 FenceSync *eglSync = static_cast<FenceSync*>(sync);
1418
Jason Macnakea6a98b2019-10-28 13:10:53 -07001419 RecursiveLockGuard lock(egl::getDisplayLock(display));
1420
Nicolas Capens0bac2852016-05-07 06:09:58 -04001421 if(!validateDisplay(display))
1422 {
1423 return error(EGL_BAD_DISPLAY, EGL_FALSE);
1424 }
1425
1426 if(!display->isValidSync(eglSync))
1427 {
1428 return error(EGL_BAD_PARAMETER, EGL_FALSE);
1429 }
1430
1431 display->destroySync(eglSync);
1432
1433 return success(EGL_TRUE);
1434}
1435
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04001436EGLint EGLAPIENTRY ClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001437{
1438 TRACE("(EGLDisplay dpy = %p, EGLSyncKHR sync = %p, EGLint flags = %x, EGLTimeKHR value = %llx)", dpy, sync, flags, timeout);
1439
1440 egl::Display *display = egl::Display::get(dpy);
1441 FenceSync *eglSync = static_cast<FenceSync*>(sync);
1442
Jason Macnakea6a98b2019-10-28 13:10:53 -07001443 RecursiveLockGuard lock(egl::getDisplayLock(display));
1444
Nicolas Capens0bac2852016-05-07 06:09:58 -04001445 if(!validateDisplay(display))
1446 {
1447 return error(EGL_BAD_DISPLAY, EGL_FALSE);
1448 }
1449
1450 if(!display->isValidSync(eglSync))
1451 {
1452 return error(EGL_BAD_PARAMETER, EGL_FALSE);
1453 }
1454
1455 (void)flags;
1456 (void)timeout;
1457
1458 if(!eglSync->isSignaled())
1459 {
1460 eglSync->wait();
1461 }
1462
1463 return success(EGL_CONDITION_SATISFIED_KHR);
1464}
1465
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04001466EGLBoolean EGLAPIENTRY GetSyncAttrib(EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLAttrib *value)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001467{
Nicolas Capens48908cb2018-01-08 13:07:14 -05001468 TRACE("(EGLDisplay dpy = %p, EGLSyncKHR sync = %p, EGLint attribute = %x, EGLAttrib *value = %p)", dpy, sync, attribute, value);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001469
1470 egl::Display *display = egl::Display::get(dpy);
1471 FenceSync *eglSync = static_cast<FenceSync*>(sync);
1472
Jason Macnakea6a98b2019-10-28 13:10:53 -07001473 RecursiveLockGuard lock(egl::getDisplayLock(display));
1474
Nicolas Capens0bac2852016-05-07 06:09:58 -04001475 if(!validateDisplay(display))
1476 {
1477 return error(EGL_BAD_DISPLAY, EGL_FALSE);
1478 }
1479
1480 if(!display->isValidSync(eglSync))
1481 {
1482 return error(EGL_BAD_PARAMETER, EGL_FALSE);
1483 }
1484
Alistair Strachan179c9322019-03-27 17:54:12 +09001485 if(!value)
1486 {
1487 return error(EGL_BAD_PARAMETER, EGL_FALSE);
1488 }
1489
Nicolas Capens0bac2852016-05-07 06:09:58 -04001490 switch(attribute)
1491 {
1492 case EGL_SYNC_TYPE_KHR:
1493 *value = EGL_SYNC_FENCE_KHR;
1494 return success(EGL_TRUE);
1495 case EGL_SYNC_STATUS_KHR:
1496 eglSync->wait(); // TODO: Don't block. Just poll based on sw::Query.
1497 *value = eglSync->isSignaled() ? EGL_SIGNALED_KHR : EGL_UNSIGNALED_KHR;
1498 return success(EGL_TRUE);
1499 case EGL_SYNC_CONDITION_KHR:
1500 *value = EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR;
1501 return success(EGL_TRUE);
1502 default:
1503 return error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
1504 }
1505}
1506
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04001507EGLBoolean EGLAPIENTRY GetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value)
Nicolas Capens48908cb2018-01-08 13:07:14 -05001508{
1509 EGLAttrib attrib_value;
1510 EGLBoolean result = GetSyncAttrib(dpy, sync, attribute, &attrib_value);
1511 *value = static_cast<EGLint>(attrib_value);
1512 return result;
1513}
1514
Nicolas Capens38a9b3c2019-09-10 16:35:24 -04001515__eglMustCastToProperFunctionPointerType EGLAPIENTRY GetProcAddress(const char *procname)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001516{
1517 TRACE("(const char *procname = \"%s\")", procname);
1518
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01001519 struct Function
Nicolas Capens0bac2852016-05-07 06:09:58 -04001520 {
1521 const char *name;
1522 __eglMustCastToProperFunctionPointerType address;
1523 };
1524
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01001525 struct CompareFunctor
Nicolas Capens0bac2852016-05-07 06:09:58 -04001526 {
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01001527 bool operator()(const Function &a, const Function &b) const
1528 {
1529 return strcmp(a.name, b.name) < 0;
1530 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04001531 };
1532
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01001533 // This array must be kept sorted with respect to strcmp(), so that binary search works correctly.
1534 // The Unix command "LC_COLLATE=C sort" will generate the correct order.
1535 static const Function eglFunctions[] =
Nicolas Capens0bac2852016-05-07 06:09:58 -04001536 {
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01001537 #define FUNCTION(name) {#name, (__eglMustCastToProperFunctionPointerType)name}
1538
1539 FUNCTION(eglBindAPI),
1540 FUNCTION(eglBindTexImage),
1541 FUNCTION(eglChooseConfig),
Nicolas Capens48908cb2018-01-08 13:07:14 -05001542 FUNCTION(eglClientWaitSync),
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01001543 FUNCTION(eglClientWaitSyncKHR),
1544 FUNCTION(eglCopyBuffers),
1545 FUNCTION(eglCreateContext),
Nicolas Capens48908cb2018-01-08 13:07:14 -05001546 FUNCTION(eglCreateImage),
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01001547 FUNCTION(eglCreateImageKHR),
1548 FUNCTION(eglCreatePbufferFromClientBuffer),
1549 FUNCTION(eglCreatePbufferSurface),
1550 FUNCTION(eglCreatePixmapSurface),
Nicolas Capens48908cb2018-01-08 13:07:14 -05001551 FUNCTION(eglCreatePlatformPixmapSurface),
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01001552 FUNCTION(eglCreatePlatformPixmapSurfaceEXT),
Nicolas Capens48908cb2018-01-08 13:07:14 -05001553 FUNCTION(eglCreatePlatformWindowSurface),
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01001554 FUNCTION(eglCreatePlatformWindowSurfaceEXT),
Nicolas Capens48908cb2018-01-08 13:07:14 -05001555 FUNCTION(eglCreateSync),
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01001556 FUNCTION(eglCreateSyncKHR),
1557 FUNCTION(eglCreateWindowSurface),
1558 FUNCTION(eglDestroyContext),
Nicolas Capens48908cb2018-01-08 13:07:14 -05001559 FUNCTION(eglDestroyImage),
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01001560 FUNCTION(eglDestroyImageKHR),
1561 FUNCTION(eglDestroySurface),
Nicolas Capens48908cb2018-01-08 13:07:14 -05001562 FUNCTION(eglDestroySync),
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01001563 FUNCTION(eglDestroySyncKHR),
1564 FUNCTION(eglGetConfigAttrib),
1565 FUNCTION(eglGetConfigs),
1566 FUNCTION(eglGetCurrentContext),
1567 FUNCTION(eglGetCurrentDisplay),
1568 FUNCTION(eglGetCurrentSurface),
1569 FUNCTION(eglGetDisplay),
1570 FUNCTION(eglGetError),
Nicolas Capens48908cb2018-01-08 13:07:14 -05001571 FUNCTION(eglGetPlatformDisplay),
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01001572 FUNCTION(eglGetPlatformDisplayEXT),
1573 FUNCTION(eglGetProcAddress),
Nicolas Capens48908cb2018-01-08 13:07:14 -05001574 FUNCTION(eglGetSyncAttrib),
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01001575 FUNCTION(eglGetSyncAttribKHR),
1576 FUNCTION(eglInitialize),
1577 FUNCTION(eglMakeCurrent),
1578 FUNCTION(eglQueryAPI),
1579 FUNCTION(eglQueryContext),
1580 FUNCTION(eglQueryString),
1581 FUNCTION(eglQuerySurface),
1582 FUNCTION(eglReleaseTexImage),
1583 FUNCTION(eglReleaseThread),
1584 FUNCTION(eglSurfaceAttrib),
1585 FUNCTION(eglSwapBuffers),
1586 FUNCTION(eglSwapInterval),
1587 FUNCTION(eglTerminate),
1588 FUNCTION(eglWaitClient),
1589 FUNCTION(eglWaitGL),
1590 FUNCTION(eglWaitNative),
Nicolas Capens48908cb2018-01-08 13:07:14 -05001591 FUNCTION(eglWaitSync),
1592 FUNCTION(eglWaitSyncKHR),
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01001593
1594 #undef FUNCTION
1595 };
1596
1597 static const size_t numFunctions = sizeof eglFunctions / sizeof(Function);
1598 static const Function *const eglFunctionsEnd = eglFunctions + numFunctions;
1599
1600 Function needle;
1601 needle.name = procname;
1602
1603 if(procname && strncmp("egl", procname, 3) == 0)
1604 {
1605 const Function *result = std::lower_bound(eglFunctions, eglFunctionsEnd, needle, CompareFunctor());
1606 if (result != eglFunctionsEnd && strcmp(procname, result->name) == 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001607 {
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01001608 return success((__eglMustCastToProperFunctionPointerType)result->address);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001609 }
1610 }
1611
1612 if(libGLESv2)
1613 {
1614 __eglMustCastToProperFunctionPointerType proc = libGLESv2->es2GetProcAddress(procname);
1615 if(proc) return success(proc);
1616 }
1617
Nicolas Capens0bac2852016-05-07 06:09:58 -04001618 return success((__eglMustCastToProperFunctionPointerType)NULL);
1619}
1620}