blob: b2ef237a584f339104ea33484acdca9bfe5e3b08 [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
17#include "main.h"
18#include "Display.h"
Nicolas Capens31c07a32017-06-13 23:44:13 -040019#include "Surface.hpp"
Nicolas Capens0bac2852016-05-07 06:09:58 -040020#include "Texture.hpp"
21#include "Context.hpp"
22#include "common/Image.hpp"
23#include "common/debug.h"
24#include "Common/Version.h"
25
26#if defined(__ANDROID__)
27#include <system/window.h>
Alexis Hetu20eea3c2018-06-19 14:50:41 -040028#elif defined(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 Capens48908cb2018-01-08 13:07:14 -050033#include <vector>
Nicolas Capens0bac2852016-05-07 06:09:58 -040034#include <string.h>
35
Nicolas Capens48908cb2018-01-08 13:07:14 -050036namespace egl
37{
38namespace
39{
40bool validateDisplay(egl::Display *display)
Nicolas Capens0bac2852016-05-07 06:09:58 -040041{
42 if(display == EGL_NO_DISPLAY)
43 {
44 return error(EGL_BAD_DISPLAY, false);
45 }
46
47 if(!display->isInitialized())
48 {
49 return error(EGL_NOT_INITIALIZED, false);
50 }
51
52 return true;
53}
54
Nicolas Capens48908cb2018-01-08 13:07:14 -050055bool validateConfig(egl::Display *display, EGLConfig config)
Nicolas Capens0bac2852016-05-07 06:09:58 -040056{
57 if(!validateDisplay(display))
58 {
59 return false;
60 }
61
62 if(!display->isValidConfig(config))
63 {
64 return error(EGL_BAD_CONFIG, false);
65 }
66
67 return true;
68}
69
Nicolas Capens48908cb2018-01-08 13:07:14 -050070bool validateContext(egl::Display *display, egl::Context *context)
Nicolas Capens0bac2852016-05-07 06:09:58 -040071{
72 if(!validateDisplay(display))
73 {
74 return false;
75 }
76
77 if(!display->isValidContext(context))
78 {
79 return error(EGL_BAD_CONTEXT, false);
80 }
81
82 return true;
83}
84
Nicolas Capens48908cb2018-01-08 13:07:14 -050085bool validateSurface(egl::Display *display, egl::Surface *surface)
Nicolas Capens0bac2852016-05-07 06:09:58 -040086{
87 if(!validateDisplay(display))
88 {
89 return false;
90 }
91
92 if(!display->isValidSurface(surface))
93 {
94 return error(EGL_BAD_SURFACE, false);
95 }
96
97 return true;
98}
99
Nicolas Capens48908cb2018-01-08 13:07:14 -0500100// Class to facilitate conversion from EGLint to EGLAttrib lists.
101class EGLAttribs
Nicolas Capens0bac2852016-05-07 06:09:58 -0400102{
Nicolas Capens48908cb2018-01-08 13:07:14 -0500103public:
104 explicit EGLAttribs(const EGLint *attrib_list)
105 {
106 if(attrib_list)
107 {
108 while(*attrib_list != EGL_NONE)
109 {
110 attrib.push_back(static_cast<EGLAttrib>(*attrib_list));
111 attrib_list++;
112 }
113 }
114
115 attrib.push_back(EGL_NONE);
116 }
117
Nicolas Capensd7622ff2018-08-07 12:24:10 -0400118 const EGLAttrib *operator&() const
Nicolas Capens48908cb2018-01-08 13:07:14 -0500119 {
120 return &attrib[0];
121 }
122
123private:
124 std::vector<EGLAttrib> attrib;
125};
126}
127
Nicolas Capens0bac2852016-05-07 06:09:58 -0400128EGLint GetError(void)
129{
130 TRACE("()");
131
132 EGLint error = egl::getCurrentError();
133
134 if(error != EGL_SUCCESS)
135 {
136 egl::setCurrentError(EGL_SUCCESS);
137 }
138
139 return error;
140}
141
142EGLDisplay GetDisplay(EGLNativeDisplayType display_id)
143{
144 TRACE("(EGLNativeDisplayType display_id = %p)", display_id);
145
146 if(display_id != EGL_DEFAULT_DISPLAY)
147 {
148 // FIXME: Check if display_id is the default display
149 }
150
151 #if defined(__linux__) && !defined(__ANDROID__)
Alexis Hetu20eea3c2018-06-19 14:50:41 -0400152 #if defined(USE_X11)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400153 if(!libX11)
Alexis Hetu20eea3c2018-06-19 14:50:41 -0400154 #endif // Non X11 linux is headless only
Nicolas Capens0bac2852016-05-07 06:09:58 -0400155 {
156 return success(HEADLESS_DISPLAY);
157 }
158 #endif
159
160 return success(PRIMARY_DISPLAY); // We only support the default display
161}
162
163EGLBoolean Initialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
164{
165 TRACE("(EGLDisplay dpy = %p, EGLint *major = %p, EGLint *minor = %p)",
166 dpy, major, minor);
167
Alexis Hetu2b6ac182017-05-24 14:06:27 -0400168 egl::Display *display = egl::Display::get(dpy);
169
170 if(!display)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400171 {
172 return error(EGL_BAD_DISPLAY, EGL_FALSE);
173 }
174
Nicolas Capens0bac2852016-05-07 06:09:58 -0400175 if(!display->initialize())
176 {
177 return error(EGL_NOT_INITIALIZED, EGL_FALSE);
178 }
179
180 if(major) *major = 1;
181 if(minor) *minor = 4;
182
183 return success(EGL_TRUE);
184}
185
186EGLBoolean Terminate(EGLDisplay dpy)
187{
188 TRACE("(EGLDisplay dpy = %p)", dpy);
189
190 if(dpy == EGL_NO_DISPLAY)
191 {
192 return error(EGL_BAD_DISPLAY, EGL_FALSE);
193 }
194
195 egl::Display *display = egl::Display::get(dpy);
196
197 display->terminate();
198
199 return success(EGL_TRUE);
200}
201
202const char *QueryString(EGLDisplay dpy, EGLint name)
203{
204 TRACE("(EGLDisplay dpy = %p, EGLint name = %d)", dpy, name);
205
Nicolas Capensdf0be382017-06-05 17:43:46 -0400206 if(dpy == EGL_NO_DISPLAY && name == EGL_EXTENSIONS)
207 {
208 return success(
Krzysztof Kosińskif919b862018-01-03 23:17:52 +0100209 "EGL_KHR_client_get_all_proc_addresses "
Nicolas Capensdf0be382017-06-05 17:43:46 -0400210#if defined(__linux__) && !defined(__ANDROID__)
211 "EGL_KHR_platform_gbm "
Alexis Hetu20eea3c2018-06-19 14:50:41 -0400212#endif
213#if defined(USE_X11)
Nicolas Capensdf0be382017-06-05 17:43:46 -0400214 "EGL_KHR_platform_x11 "
Alexis Hetud415ba12017-06-05 10:29:14 -0400215#endif
Nicolas Capensdf0be382017-06-05 17:43:46 -0400216 "EGL_EXT_client_extensions "
217 "EGL_EXT_platform_base");
218 }
Nicolas Capens0bac2852016-05-07 06:09:58 -0400219
220 egl::Display *display = egl::Display::get(dpy);
221
222 if(!validateDisplay(display))
223 {
224 return nullptr;
225 }
226
227 switch(name)
228 {
229 case EGL_CLIENT_APIS:
230 return success("OpenGL_ES");
231 case EGL_EXTENSIONS:
Alexis Hetub75bb022016-05-18 11:43:43 -0400232 return success("EGL_KHR_create_context "
Krzysztof Kosińskif919b862018-01-03 23:17:52 +0100233 "EGL_KHR_get_all_proc_addresses "
Alexis Hetub75bb022016-05-18 11:43:43 -0400234 "EGL_KHR_gl_texture_2D_image "
Nicolas Capens0bac2852016-05-07 06:09:58 -0400235 "EGL_KHR_gl_texture_cubemap_image "
236 "EGL_KHR_gl_renderbuffer_image "
237 "EGL_KHR_fence_sync "
238 "EGL_KHR_image_base "
Alexis Hetu5cd502b2018-03-22 08:29:31 -0400239 "EGL_KHR_surfaceless_context "
Alexis Hetuc80eada2018-02-13 15:02:40 -0500240 "EGL_ANGLE_iosurface_client_buffer "
Nicolas Capens0bac2852016-05-07 06:09:58 -0400241 "EGL_ANDROID_framebuffer_target "
242 "EGL_ANDROID_recordable");
243 case EGL_VENDOR:
244 return success("Google Inc.");
245 case EGL_VERSION:
246 return success("1.4 SwiftShader " VERSION_STRING);
247 }
248
249 return error(EGL_BAD_PARAMETER, (const char*)nullptr);
250}
251
252EGLBoolean GetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config)
253{
254 TRACE("(EGLDisplay dpy = %p, EGLConfig *configs = %p, "
255 "EGLint config_size = %d, EGLint *num_config = %p)",
256 dpy, configs, config_size, num_config);
257
258 egl::Display *display = egl::Display::get(dpy);
259
260 if(!validateDisplay(display))
261 {
262 return EGL_FALSE;
263 }
264
265 if(!num_config)
266 {
267 return error(EGL_BAD_PARAMETER, EGL_FALSE);
268 }
269
270 const EGLint attribList[] = {EGL_NONE};
271
272 if(!display->getConfigs(configs, attribList, config_size, num_config))
273 {
274 return error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
275 }
276
277 return success(EGL_TRUE);
278}
279
280EGLBoolean ChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config)
281{
282 TRACE("(EGLDisplay dpy = %p, const EGLint *attrib_list = %p, "
283 "EGLConfig *configs = %p, EGLint config_size = %d, EGLint *num_config = %p)",
284 dpy, attrib_list, configs, config_size, num_config);
285
286 egl::Display *display = egl::Display::get(dpy);
287
288 if(!validateDisplay(display))
289 {
290 return EGL_FALSE;
291 }
292
293 if(!num_config)
294 {
295 return error(EGL_BAD_PARAMETER, EGL_FALSE);
296 }
297
298 const EGLint attribList[] = {EGL_NONE};
299
300 if(!attrib_list)
301 {
302 attrib_list = attribList;
303 }
304
305 if(!display->getConfigs(configs, attrib_list, config_size, num_config))
306 {
307 return error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
308 }
309
310 return success(EGL_TRUE);
311}
312
313EGLBoolean GetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value)
314{
315 TRACE("(EGLDisplay dpy = %p, EGLConfig config = %p, EGLint attribute = %d, EGLint *value = %p)",
316 dpy, config, attribute, value);
317
318 egl::Display *display = egl::Display::get(dpy);
319
320 if(!validateConfig(display, config))
321 {
322 return EGL_FALSE;
323 }
324
325 if(!display->getConfigAttrib(config, attribute, value))
326 {
327 return error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
328 }
329
330 return success(EGL_TRUE);
331}
332
Nicolas Capens48908cb2018-01-08 13:07:14 -0500333EGLSurface CreatePlatformWindowSurface(EGLDisplay dpy, EGLConfig config, void *native_window, const EGLAttrib *attrib_list)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400334{
Nicolas Capens48908cb2018-01-08 13:07:14 -0500335 TRACE("(EGLDisplay dpy = %p, EGLConfig config = %p, void *native_window = %p, "
336 "const EGLint *attrib_list = %p)", dpy, config, native_window, attrib_list);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400337
338 egl::Display *display = egl::Display::get(dpy);
339
340 if(!validateConfig(display, config))
341 {
342 return EGL_NO_SURFACE;
343 }
344
Nicolas Capens48908cb2018-01-08 13:07:14 -0500345 if(!display->isValidWindow((EGLNativeWindowType)native_window))
Nicolas Capens0bac2852016-05-07 06:09:58 -0400346 {
347 return error(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
348 }
349
Nicolas Capens48908cb2018-01-08 13:07:14 -0500350 return display->createWindowSurface((EGLNativeWindowType)native_window, config, attrib_list);
351}
352
353EGLSurface CreatePlatformWindowSurfaceEXT(EGLDisplay dpy, EGLConfig config, void *native_window, const EGLint *attrib_list)
354{
355 TRACE("(EGLDisplay dpy = %p, EGLConfig config = %p, void *native_window = %p, "
356 "const EGLint *attrib_list = %p)", dpy, config, native_window, attrib_list);
357
358 EGLAttribs attribs(attrib_list);
Nicolas Capensd7622ff2018-08-07 12:24:10 -0400359 return CreatePlatformWindowSurface(dpy, config, native_window, &attribs);
Nicolas Capens48908cb2018-01-08 13:07:14 -0500360}
361
362EGLSurface CreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType window, const EGLint *attrib_list)
363{
364 TRACE("(EGLDisplay dpy = %p, EGLConfig config = %p, EGLNativeWindowType window = %p, "
365 "const EGLint *attrib_list = %p)", dpy, config, window, attrib_list);
366
367 EGLAttribs attribs(attrib_list);
Nicolas Capensd7622ff2018-08-07 12:24:10 -0400368 return CreatePlatformWindowSurface(dpy, config, (void*)window, &attribs);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400369}
370
371EGLSurface CreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list)
372{
373 TRACE("(EGLDisplay dpy = %p, EGLConfig config = %p, const EGLint *attrib_list = %p)",
374 dpy, config, attrib_list);
375
376 egl::Display *display = egl::Display::get(dpy);
377
378 if(!validateConfig(display, config))
379 {
380 return EGL_NO_SURFACE;
381 }
382
383 return display->createPBufferSurface(config, attrib_list);
384}
385
Nicolas Capens48908cb2018-01-08 13:07:14 -0500386EGLSurface CreatePlatformPixmapSurface(EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLAttrib *attrib_list)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400387{
Nicolas Capens48908cb2018-01-08 13:07:14 -0500388 TRACE("(EGLDisplay dpy = %p, EGLConfig config = %p, void *native_pixmap = %p, "
389 "const EGLint *attrib_list = %p)", dpy, config, native_pixmap, attrib_list);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400390
391 egl::Display *display = egl::Display::get(dpy);
392
393 if(!validateConfig(display, config))
394 {
395 return EGL_NO_SURFACE;
396 }
397
398 UNIMPLEMENTED(); // FIXME
399
400 return success(EGL_NO_SURFACE);
401}
402
Nicolas Capens48908cb2018-01-08 13:07:14 -0500403EGLSurface CreatePlatformPixmapSurfaceEXT(EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLint *attrib_list)
404{
405 TRACE("(EGLDisplay dpy = %p, EGLConfig config = %p, void *native_pixmap = %p, "
406 "const EGLint *attrib_list = %p)", dpy, config, native_pixmap, attrib_list);
407
408 EGLAttribs attribs(attrib_list);
Nicolas Capensd7622ff2018-08-07 12:24:10 -0400409 return CreatePlatformPixmapSurface(dpy, config, native_pixmap, &attribs);
Nicolas Capens48908cb2018-01-08 13:07:14 -0500410}
411
412EGLSurface CreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list)
413{
414 TRACE("(EGLDisplay dpy = %p, EGLConfig config = %p, EGLNativePixmapType pixmap = %p, "
415 "const EGLint *attrib_list = %p)", dpy, config, pixmap, attrib_list);
416
417 EGLAttribs attribs(attrib_list);
Nicolas Capensd7622ff2018-08-07 12:24:10 -0400418 return CreatePlatformPixmapSurface(dpy, config, (void*)pixmap, &attribs);
Nicolas Capens48908cb2018-01-08 13:07:14 -0500419}
420
Nicolas Capens0bac2852016-05-07 06:09:58 -0400421EGLBoolean DestroySurface(EGLDisplay dpy, EGLSurface surface)
422{
423 TRACE("(EGLDisplay dpy = %p, EGLSurface surface = %p)", dpy, surface);
424
425 egl::Display *display = egl::Display::get(dpy);
426 egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
427
428 if(!validateSurface(display, eglSurface))
429 {
430 return EGL_FALSE;
431 }
432
433 if(surface == EGL_NO_SURFACE)
434 {
435 return error(EGL_BAD_SURFACE, EGL_FALSE);
436 }
437
438 display->destroySurface((egl::Surface*)surface);
439
440 return success(EGL_TRUE);
441}
442
443EGLBoolean QuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value)
444{
445 TRACE("(EGLDisplay dpy = %p, EGLSurface surface = %p, EGLint attribute = %d, EGLint *value = %p)",
446 dpy, surface, attribute, value);
447
448 egl::Display *display = egl::Display::get(dpy);
449 egl::Surface *eglSurface = (egl::Surface*)surface;
450
451 if(!validateSurface(display, eglSurface))
452 {
453 return EGL_FALSE;
454 }
455
456 if(surface == EGL_NO_SURFACE)
457 {
458 return error(EGL_BAD_SURFACE, EGL_FALSE);
459 }
460
461 switch(attribute)
462 {
463 case EGL_VG_ALPHA_FORMAT:
Nicolas Capensc8eedeb2018-04-12 12:50:21 -0400464 *value = EGL_VG_ALPHA_FORMAT_NONPRE; // Default
Nicolas Capens0bac2852016-05-07 06:09:58 -0400465 break;
466 case EGL_VG_COLORSPACE:
Nicolas Capensc8eedeb2018-04-12 12:50:21 -0400467 *value = EGL_VG_COLORSPACE_sRGB; // Default
Nicolas Capens0bac2852016-05-07 06:09:58 -0400468 break;
469 case EGL_CONFIG_ID:
470 *value = eglSurface->getConfigID();
471 break;
472 case EGL_HEIGHT:
473 *value = eglSurface->getHeight();
474 break;
475 case EGL_HORIZONTAL_RESOLUTION:
Nicolas Capensc8eedeb2018-04-12 12:50:21 -0400476 *value = EGL_UNKNOWN;
Nicolas Capens0bac2852016-05-07 06:09:58 -0400477 break;
478 case EGL_LARGEST_PBUFFER:
479 if(eglSurface->isPBufferSurface()) // For a window or pixmap surface, the contents of *value are not modified.
480 {
481 *value = eglSurface->getLargestPBuffer();
482 }
483 break;
484 case EGL_MIPMAP_TEXTURE:
Nicolas Capensc8eedeb2018-04-12 12:50:21 -0400485 if(eglSurface->isPBufferSurface()) // For a window or pixmap surface, the contents of *value are not modified.
486 {
487 *value = EGL_FALSE; // UNIMPLEMENTED
488 }
Nicolas Capens0bac2852016-05-07 06:09:58 -0400489 break;
490 case EGL_MIPMAP_LEVEL:
Nicolas Capensc8eedeb2018-04-12 12:50:21 -0400491 if(eglSurface->isPBufferSurface()) // For a window or pixmap surface, the contents of *value are not modified.
492 {
493 *value = eglSurface->getMipmapLevel();
494 }
Nicolas Capens0bac2852016-05-07 06:09:58 -0400495 break;
496 case EGL_MULTISAMPLE_RESOLVE:
Nicolas Capensc8eedeb2018-04-12 12:50:21 -0400497 *value = eglSurface->getMultisampleResolve();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400498 break;
499 case EGL_PIXEL_ASPECT_RATIO:
500 *value = eglSurface->getPixelAspectRatio();
501 break;
502 case EGL_RENDER_BUFFER:
503 *value = eglSurface->getRenderBuffer();
504 break;
505 case EGL_SWAP_BEHAVIOR:
506 *value = eglSurface->getSwapBehavior();
507 break;
508 case EGL_TEXTURE_FORMAT:
Nicolas Capensc8eedeb2018-04-12 12:50:21 -0400509 if(eglSurface->isPBufferSurface()) // For a window or pixmap surface, the contents of *value are not modified.
510 {
511 *value = eglSurface->getTextureFormat();
512 }
Nicolas Capens0bac2852016-05-07 06:09:58 -0400513 break;
514 case EGL_TEXTURE_TARGET:
Nicolas Capensc8eedeb2018-04-12 12:50:21 -0400515 if(eglSurface->isPBufferSurface()) // For a window or pixmap surface, the contents of *value are not modified.
516 {
517 *value = eglSurface->getTextureTarget();
518 }
Nicolas Capens0bac2852016-05-07 06:09:58 -0400519 break;
520 case EGL_VERTICAL_RESOLUTION:
Nicolas Capensc8eedeb2018-04-12 12:50:21 -0400521 *value = EGL_UNKNOWN;
Nicolas Capens0bac2852016-05-07 06:09:58 -0400522 break;
523 case EGL_WIDTH:
524 *value = eglSurface->getWidth();
525 break;
526 default:
527 return error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
528 }
529
530 return success(EGL_TRUE);
531}
532
533EGLBoolean BindAPI(EGLenum api)
534{
535 TRACE("(EGLenum api = 0x%X)", api);
536
537 switch(api)
538 {
539 case EGL_OPENGL_API:
540 case EGL_OPENVG_API:
541 return error(EGL_BAD_PARAMETER, EGL_FALSE); // Not supported by this implementation
542 case EGL_OPENGL_ES_API:
543 break;
544 default:
545 return error(EGL_BAD_PARAMETER, EGL_FALSE);
546 }
547
548 egl::setCurrentAPI(api);
549
550 return success(EGL_TRUE);
551}
552
553EGLenum QueryAPI(void)
554{
555 TRACE("()");
556
557 EGLenum API = egl::getCurrentAPI();
558
559 return success(API);
560}
561
562EGLBoolean WaitClient(void)
563{
564 TRACE("()");
565
Alexis Hetuf3a124f2018-01-15 15:49:42 -0500566 // eglWaitClient is ignored if there is no current EGL rendering context for the current rendering API.
567 egl::Context *context = egl::getCurrentContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400568
Alexis Hetuf3a124f2018-01-15 15:49:42 -0500569 if(context)
570 {
571 context->finish();
572 }
573
574 return success(EGL_TRUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400575}
576
577EGLBoolean ReleaseThread(void)
578{
579 TRACE("()");
580
Nicolas Capenscc5c7d92016-06-13 14:35:11 -0400581 detachThread();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400582
Nicolas Capens660eba92017-09-05 14:06:06 -0400583 return EGL_TRUE; // success() is not called here because it would re-allocate thread-local storage.
Nicolas Capens0bac2852016-05-07 06:09:58 -0400584}
585
586EGLSurface CreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list)
587{
588 TRACE("(EGLDisplay dpy = %p, EGLenum buftype = 0x%X, EGLClientBuffer buffer = %p, "
589 "EGLConfig config = %p, const EGLint *attrib_list = %p)",
590 dpy, buftype, buffer, config, attrib_list);
591
Alexis Hetuc80eada2018-02-13 15:02:40 -0500592 switch(buftype)
593 {
594 case EGL_IOSURFACE_ANGLE:
595 {
596 egl::Display *display = egl::Display::get(dpy);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400597
Alexis Hetuc80eada2018-02-13 15:02:40 -0500598 if(!validateConfig(display, config))
599 {
600 return EGL_NO_SURFACE;
601 }
602
603 return display->createPBufferSurface(config, attrib_list, buffer);
604 }
605 case EGL_OPENVG_IMAGE:
606 UNIMPLEMENTED();
607 return error(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
608 default:
609 return error(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
610 };
Nicolas Capens0bac2852016-05-07 06:09:58 -0400611}
612
613EGLBoolean SurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
614{
615 TRACE("(EGLDisplay dpy = %p, EGLSurface surface = %p, EGLint attribute = %d, EGLint value = %d)",
616 dpy, surface, attribute, value);
617
618 egl::Display *display = egl::Display::get(dpy);
619 egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
620
621 if(!validateSurface(display, eglSurface))
622 {
623 return EGL_FALSE;
624 }
625
626 switch(attribute)
627 {
Nicolas Capensc8eedeb2018-04-12 12:50:21 -0400628 case EGL_MIPMAP_LEVEL:
629 eglSurface->setMipmapLevel(value);
630 break;
631 case EGL_MULTISAMPLE_RESOLVE:
632 switch(value)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400633 {
Nicolas Capensc8eedeb2018-04-12 12:50:21 -0400634 case EGL_MULTISAMPLE_RESOLVE_DEFAULT:
635 break;
636 case EGL_MULTISAMPLE_RESOLVE_BOX:
637 if(!(eglSurface->getSurfaceType() & EGL_MULTISAMPLE_RESOLVE_BOX_BIT))
638 {
639 return error(EGL_BAD_MATCH, EGL_FALSE);
640 }
641 break;
642 default:
643 return error(EGL_BAD_PARAMETER, EGL_FALSE);
644 }
645 eglSurface->setMultisampleResolve(value);
646 break;
647 case EGL_SWAP_BEHAVIOR:
648 switch(value)
649 {
650 case EGL_BUFFER_DESTROYED:
651 break;
652 case EGL_BUFFER_PRESERVED:
Nicolas Capens0bac2852016-05-07 06:09:58 -0400653 if(!(eglSurface->getSurfaceType() & EGL_SWAP_BEHAVIOR_PRESERVED_BIT))
654 {
655 return error(EGL_BAD_MATCH, EGL_FALSE);
656 }
Nicolas Capensc8eedeb2018-04-12 12:50:21 -0400657 break;
658 default:
Nicolas Capens0bac2852016-05-07 06:09:58 -0400659 return error(EGL_BAD_PARAMETER, EGL_FALSE);
660 }
661 eglSurface->setSwapBehavior(value);
662 break;
663 default:
Nicolas Capensc8eedeb2018-04-12 12:50:21 -0400664 return error(EGL_BAD_PARAMETER, EGL_FALSE);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400665 }
666
667 return success(EGL_TRUE);
668}
669
670EGLBoolean BindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
671{
672 TRACE("(EGLDisplay dpy = %p, EGLSurface surface = %p, EGLint buffer = %d)", dpy, surface, buffer);
673
674 egl::Display *display = egl::Display::get(dpy);
675 egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
676
677 if(!validateSurface(display, eglSurface))
678 {
679 return EGL_FALSE;
680 }
681
682 if(buffer != EGL_BACK_BUFFER)
683 {
684 return error(EGL_BAD_PARAMETER, EGL_FALSE);
685 }
686
687 if(surface == EGL_NO_SURFACE || eglSurface->isWindowSurface())
688 {
689 return error(EGL_BAD_SURFACE, EGL_FALSE);
690 }
691
692 if(eglSurface->getBoundTexture())
693 {
694 return error(EGL_BAD_ACCESS, EGL_FALSE);
695 }
696
697 if(eglSurface->getTextureFormat() == EGL_NO_TEXTURE)
698 {
699 return error(EGL_BAD_MATCH, EGL_FALSE);
700 }
701
702 egl::Context *context = egl::getCurrentContext();
703
704 if(context)
705 {
706 context->bindTexImage(eglSurface);
707 }
708
709 return success(EGL_TRUE);
710}
711
712EGLBoolean ReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
713{
714 TRACE("(EGLDisplay dpy = %p, EGLSurface surface = %p, EGLint buffer = %d)", dpy, surface, buffer);
715
716 egl::Display *display = egl::Display::get(dpy);
717 egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
718
719 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->getTextureFormat() == EGL_NO_TEXTURE)
735 {
736 return error(EGL_BAD_MATCH, EGL_FALSE);
737 }
738
739 egl::Texture *texture = eglSurface->getBoundTexture();
740
741 if(texture)
742 {
743 texture->releaseTexImage();
744 }
745
746 return success(EGL_TRUE);
747}
748
749EGLBoolean SwapInterval(EGLDisplay dpy, EGLint interval)
750{
751 TRACE("(EGLDisplay dpy = %p, EGLint interval = %d)", dpy, interval);
752
753 egl::Display *display = egl::Display::get(dpy);
754 egl::Context *context = egl::getCurrentContext();
755
756 if(!validateContext(display, context))
757 {
758 return EGL_FALSE;
759 }
760
761 egl::Surface *draw_surface = static_cast<egl::Surface*>(egl::getCurrentDrawSurface());
762
763 if(!draw_surface)
764 {
765 return error(EGL_BAD_SURFACE, EGL_FALSE);
766 }
767
768 draw_surface->setSwapInterval(interval);
769
770 return success(EGL_TRUE);
771}
772
773EGLContext CreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list)
774{
775 TRACE("(EGLDisplay dpy = %p, EGLConfig config = %p, EGLContext share_context = %p, "
776 "const EGLint *attrib_list = %p)", dpy, config, share_context, attrib_list);
777
Alexis Hetub75bb022016-05-18 11:43:43 -0400778 EGLint majorVersion = 1;
779 EGLint minorVersion = 0;
780
Nicolas Capens0bac2852016-05-07 06:09:58 -0400781 if(attrib_list)
782 {
783 for(const EGLint* attribute = attrib_list; attribute[0] != EGL_NONE; attribute += 2)
784 {
Alexis Hetub75bb022016-05-18 11:43:43 -0400785 switch(attribute[0])
Nicolas Capens0bac2852016-05-07 06:09:58 -0400786 {
Alexis Hetub75bb022016-05-18 11:43:43 -0400787 case EGL_CONTEXT_MAJOR_VERSION_KHR: // This token is an alias for EGL_CONTEXT_CLIENT_VERSION
788 majorVersion = attribute[1];
789 break;
790 case EGL_CONTEXT_MINOR_VERSION_KHR:
791 minorVersion = attribute[1];
792 break;
793 case EGL_CONTEXT_FLAGS_KHR:
794 switch(attribute[1])
795 {
796 case EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR:
797 // According to the EGL_KHR_create_context spec:
798 // "Khronos is still defining the expected and required features of debug contexts, so
799 // implementations are currently free to implement "debug contexts" with little or no debug
800 // functionality. However, OpenGL and OpenGL ES implementations supporting the GL_KHR_debug
801 // extension should enable it when this bit is set."
802 break;
803 case EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR:
804 case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR:
805 // These bits are for OpenGL contexts only, not OpenGL ES contexts
806 return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
807 default:
808 return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
809 }
810 break;
811 case EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR:
812 switch(attribute[1])
813 {
814 case EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR:
815 case EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR:
816 // These bits are for OpenGL contexts only, not OpenGL ES contexts
817 return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
818 default:
819 return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
820 }
821 break;
822 case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR:
823 switch(attribute[1])
824 {
825 case EGL_NO_RESET_NOTIFICATION_KHR:
826 case EGL_LOSE_CONTEXT_ON_RESET_KHR:
827 // These bits are for OpenGL contexts only, not OpenGL ES contexts
828 return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
829 default:
830 return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
831 }
832 break;
833 default:
Nicolas Capens0bac2852016-05-07 06:09:58 -0400834 return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
835 }
836 }
837 }
838
Alexis Hetub75bb022016-05-18 11:43:43 -0400839 switch(majorVersion)
840 {
841 case 1:
842 if(minorVersion != 0 && minorVersion != 1)
843 {
844 // 1.X: Only OpenGL ES 1.0 and 1.1 contexts are supported
845 return error(EGL_BAD_MATCH, EGL_NO_CONTEXT);
846 }
847 break;
848 case 2:
849 case 3:
850 if(minorVersion != 0)
851 {
852 // 2.X and 3.X: Only OpenGL ES 2.0 and 3.0 contexts are currently supported
853 return error(EGL_BAD_MATCH, EGL_NO_CONTEXT);
854 }
855 break;
856 default:
857 return error(EGL_BAD_MATCH, EGL_NO_CONTEXT);
858 }
859
Nicolas Capens0bac2852016-05-07 06:09:58 -0400860 egl::Display *display = egl::Display::get(dpy);
861 egl::Context *shareContext = static_cast<egl::Context*>(share_context);
862
863 if(!validateConfig(display, config))
864 {
865 return EGL_NO_CONTEXT;
866 }
867
Alexis Hetub75bb022016-05-18 11:43:43 -0400868 if(shareContext && shareContext->getClientVersion() != majorVersion)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400869 {
870 return error(EGL_BAD_CONTEXT, EGL_NO_CONTEXT);
871 }
872
Alexis Hetub75bb022016-05-18 11:43:43 -0400873 return display->createContext(config, shareContext, majorVersion);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400874}
875
876EGLBoolean DestroyContext(EGLDisplay dpy, EGLContext ctx)
877{
878 TRACE("(EGLDisplay dpy = %p, EGLContext ctx = %p)", dpy, ctx);
879
880 egl::Display *display = egl::Display::get(dpy);
881 egl::Context *context = static_cast<egl::Context*>(ctx);
882
883 if(!validateContext(display, context))
884 {
885 return EGL_FALSE;
886 }
887
888 if(ctx == EGL_NO_CONTEXT)
889 {
890 return error(EGL_BAD_CONTEXT, EGL_FALSE);
891 }
892
893 display->destroyContext(context);
894
895 return success(EGL_TRUE);
896}
897
898EGLBoolean MakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx)
899{
900 TRACE("(EGLDisplay dpy = %p, EGLSurface draw = %p, EGLSurface read = %p, EGLContext ctx = %p)",
901 dpy, draw, read, ctx);
902
903 egl::Display *display = egl::Display::get(dpy);
904 egl::Context *context = static_cast<egl::Context*>(ctx);
905 egl::Surface *drawSurface = static_cast<egl::Surface*>(draw);
906 egl::Surface *readSurface = static_cast<egl::Surface*>(read);
907
908 if(ctx != EGL_NO_CONTEXT || draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE)
909 {
910 if(!validateDisplay(display))
911 {
912 return EGL_FALSE;
913 }
914 }
915
916 if(ctx == EGL_NO_CONTEXT && (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE))
917 {
918 return error(EGL_BAD_MATCH, EGL_FALSE);
919 }
920
921 if(ctx != EGL_NO_CONTEXT && !validateContext(display, context))
922 {
923 return EGL_FALSE;
924 }
925
926 if((draw != EGL_NO_SURFACE && !validateSurface(display, drawSurface)) ||
927 (read != EGL_NO_SURFACE && !validateSurface(display, readSurface)))
928 {
929 return EGL_FALSE;
930 }
931
Alexis Hetuc80eada2018-02-13 15:02:40 -0500932 if((draw != EGL_NO_SURFACE && drawSurface->hasClientBuffer()) ||
933 (read != EGL_NO_SURFACE && readSurface->hasClientBuffer()))
934 {
935 // Make current is not supported on IOSurface pbuffers.
936 return error(EGL_BAD_SURFACE, EGL_FALSE);
937 }
938
Nicolas Capens0bac2852016-05-07 06:09:58 -0400939 if((draw != EGL_NO_SURFACE) ^ (read != EGL_NO_SURFACE))
940 {
941 return error(EGL_BAD_MATCH, EGL_FALSE);
942 }
943
944 if(draw != read)
945 {
946 UNIMPLEMENTED(); // FIXME
947 }
948
Nicolas Capens0bac2852016-05-07 06:09:58 -0400949 egl::setCurrentDrawSurface(drawSurface);
950 egl::setCurrentReadSurface(readSurface);
951 egl::setCurrentContext(context);
952
953 if(context)
954 {
955 context->makeCurrent(drawSurface);
956 }
957
958 return success(EGL_TRUE);
959}
960
961EGLContext GetCurrentContext(void)
962{
963 TRACE("()");
964
965 EGLContext context = egl::getCurrentContext();
966
967 return success(context);
968}
969
970EGLSurface GetCurrentSurface(EGLint readdraw)
971{
972 TRACE("(EGLint readdraw = %d)", readdraw);
973
974 if(readdraw == EGL_READ)
975 {
976 EGLSurface read = egl::getCurrentReadSurface();
977 return success(read);
978 }
979 else if(readdraw == EGL_DRAW)
980 {
981 EGLSurface draw = egl::getCurrentDrawSurface();
982 return success(draw);
983 }
984 else
985 {
986 return error(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
987 }
988}
989
990EGLDisplay GetCurrentDisplay(void)
991{
992 TRACE("()");
993
Nicolas Capens8aca1df2017-06-15 14:15:30 -0700994 egl::Context *context = egl::getCurrentContext();
995
996 if(!context)
997 {
998 return success(EGL_NO_DISPLAY);
999 }
1000
Nicolas Capense88da312017-07-10 14:26:17 -04001001 egl::Display *display = context->getDisplay();
1002
1003 if(!display)
1004 {
1005 return error(EGL_BAD_ACCESS, EGL_NO_DISPLAY);
1006 }
1007
1008 return success(display->getEGLDisplay());
Nicolas Capens0bac2852016-05-07 06:09:58 -04001009}
1010
1011EGLBoolean QueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value)
1012{
1013 TRACE("(EGLDisplay dpy = %p, EGLContext ctx = %p, EGLint attribute = %d, EGLint *value = %p)",
1014 dpy, ctx, attribute, value);
1015
1016 egl::Display *display = egl::Display::get(dpy);
1017 egl::Context *context = static_cast<egl::Context*>(ctx);
1018
1019 if(!validateContext(display, context))
1020 {
1021 return EGL_FALSE;
1022 }
1023
Nicolas Capensf6a377b2017-05-19 09:31:35 -04001024 switch(attribute)
1025 {
Nicolas Capensdf0be382017-06-05 17:43:46 -04001026 case EGL_CONFIG_ID:
1027 *value = context->getConfigID();
1028 break;
1029 case EGL_CONTEXT_CLIENT_TYPE:
1030 *value = egl::getCurrentAPI();
1031 break;
Nicolas Capensf6a377b2017-05-19 09:31:35 -04001032 case EGL_CONTEXT_CLIENT_VERSION:
1033 *value = context->getClientVersion();
1034 break;
1035 case EGL_RENDER_BUFFER:
Nicolas Capensdf0be382017-06-05 17:43:46 -04001036 *value = EGL_BACK_BUFFER;
Nicolas Capensf6a377b2017-05-19 09:31:35 -04001037 break;
1038 default:
1039 return error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
1040 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04001041
Nicolas Capensf6a377b2017-05-19 09:31:35 -04001042 return success(EGL_TRUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001043}
1044
1045EGLBoolean WaitGL(void)
1046{
1047 TRACE("()");
1048
Alexis Hetuf3a124f2018-01-15 15:49:42 -05001049 // glWaitGL is ignored if there is no current EGL rendering context for OpenGL ES.
1050 egl::Context *context = egl::getCurrentContext();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001051
Alexis Hetuf3a124f2018-01-15 15:49:42 -05001052 if(context)
1053 {
1054 context->finish();
1055 }
1056
1057 return success(EGL_TRUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001058}
1059
1060EGLBoolean WaitNative(EGLint engine)
1061{
1062 TRACE("(EGLint engine = %d)", engine);
1063
Alexis Hetuf3a124f2018-01-15 15:49:42 -05001064 if(engine != EGL_CORE_NATIVE_ENGINE)
1065 {
1066 return error(EGL_BAD_PARAMETER, EGL_FALSE);
1067 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04001068
Alexis Hetuf3a124f2018-01-15 15:49:42 -05001069 // eglWaitNative is ignored if there is no current EGL rendering context.
1070 egl::Context *context = egl::getCurrentContext();
1071
1072 if(context)
1073 {
Alexis Hetu20eea3c2018-06-19 14:50:41 -04001074 #if defined(USE_X11)
Alexis Hetuf3a124f2018-01-15 15:49:42 -05001075 egl::Display *display = context->getDisplay();
1076
1077 if(!display)
1078 {
1079 return error(EGL_BAD_DISPLAY, EGL_FALSE);
1080 }
1081
1082 libX11->XSync((::Display*)display->getNativeDisplay(), False);
1083 #else
1084 UNIMPLEMENTED();
1085 #endif
1086 }
1087
1088 return success(EGL_TRUE);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001089}
1090
1091EGLBoolean SwapBuffers(EGLDisplay dpy, EGLSurface surface)
1092{
1093 TRACE("(EGLDisplay dpy = %p, EGLSurface surface = %p)", dpy, surface);
1094
1095 egl::Display *display = egl::Display::get(dpy);
1096 egl::Surface *eglSurface = (egl::Surface*)surface;
1097
1098 if(!validateSurface(display, eglSurface))
1099 {
1100 return EGL_FALSE;
1101 }
1102
1103 if(surface == EGL_NO_SURFACE)
1104 {
1105 return error(EGL_BAD_SURFACE, EGL_FALSE);
1106 }
1107
1108 eglSurface->swap();
1109
1110 return success(EGL_TRUE);
1111}
1112
1113EGLBoolean CopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target)
1114{
1115 TRACE("(EGLDisplay dpy = %p, EGLSurface surface = %p, EGLNativePixmapType target = %p)", dpy, surface, target);
1116
1117 egl::Display *display = egl::Display::get(dpy);
1118 egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
1119
1120 if(!validateSurface(display, eglSurface))
1121 {
1122 return EGL_FALSE;
1123 }
1124
1125 UNIMPLEMENTED(); // FIXME
1126
1127 return success(EGL_FALSE);
1128}
1129
Nicolas Capens48908cb2018-01-08 13:07:14 -05001130EGLImage CreateImage(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLAttrib *attrib_list)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001131{
Nicolas Capens48908cb2018-01-08 13:07:14 -05001132 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 -04001133
1134 egl::Display *display = egl::Display::get(dpy);
1135 egl::Context *context = static_cast<egl::Context*>(ctx);
1136
1137 if(!validateDisplay(display))
1138 {
1139 return error(EGL_BAD_DISPLAY, EGL_NO_IMAGE_KHR);
1140 }
1141
1142 if(context != EGL_NO_CONTEXT && !display->isValidContext(context))
1143 {
1144 return error(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
1145 }
1146
1147 EGLenum imagePreserved = EGL_FALSE;
1148 GLuint textureLevel = 0;
1149 if(attrib_list)
1150 {
Nicolas Capens48908cb2018-01-08 13:07:14 -05001151 for(const EGLAttrib *attribute = attrib_list; attribute[0] != EGL_NONE; attribute += 2)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001152 {
1153 if(attribute[0] == EGL_IMAGE_PRESERVED_KHR)
1154 {
Nicolas Capens48908cb2018-01-08 13:07:14 -05001155 imagePreserved = static_cast<EGLenum>(attribute[1]);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001156 }
1157 else if(attribute[0] == EGL_GL_TEXTURE_LEVEL_KHR)
1158 {
Nicolas Capens48908cb2018-01-08 13:07:14 -05001159 textureLevel = static_cast<GLuint>(attribute[1]);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001160 }
1161 else
1162 {
1163 return error(EGL_BAD_ATTRIBUTE, EGL_NO_IMAGE_KHR);
1164 }
1165 }
1166 }
1167
1168 #if defined(__ANDROID__)
1169 if(target == EGL_NATIVE_BUFFER_ANDROID)
1170 {
1171 ANativeWindowBuffer *nativeBuffer = reinterpret_cast<ANativeWindowBuffer*>(buffer);
1172
1173 if(!nativeBuffer || GLPixelFormatFromAndroid(nativeBuffer->format) == GL_NONE)
1174 {
1175 ALOGW("%s badness unsupported HAL format=%x", __FUNCTION__, nativeBuffer ? nativeBuffer->format : 0);
1176 return error(EGL_BAD_ATTRIBUTE, EGL_NO_IMAGE_KHR);
1177 }
1178
Nicolas Capens58df2f62016-06-07 14:48:56 -04001179 Image *image = new AndroidNativeImage(nativeBuffer);
1180 EGLImageKHR eglImage = display->createSharedImage(image);
1181
1182 return success(eglImage);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001183 }
1184 #endif
1185
Nicolas Capens3a795c62016-06-30 10:38:12 -04001186 GLuint name = static_cast<GLuint>(reinterpret_cast<uintptr_t>(buffer));
Nicolas Capens0bac2852016-05-07 06:09:58 -04001187
1188 if(name == 0)
1189 {
1190 return error(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
1191 }
1192
1193 EGLenum validationResult = context->validateSharedImage(target, name, textureLevel);
1194
1195 if(validationResult != EGL_SUCCESS)
1196 {
1197 return error(validationResult, EGL_NO_IMAGE_KHR);
1198 }
1199
Nicolas Capens58df2f62016-06-07 14:48:56 -04001200 Image *image = context->createSharedImage(target, name, textureLevel);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001201
1202 if(!image)
1203 {
1204 return error(EGL_BAD_MATCH, EGL_NO_IMAGE_KHR);
1205 }
1206
1207 if(image->getDepth() > 1)
1208 {
1209 return error(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
1210 }
1211
Nicolas Capens48908cb2018-01-08 13:07:14 -05001212 EGLImage eglImage = display->createSharedImage(image);
Nicolas Capens58df2f62016-06-07 14:48:56 -04001213
1214 return success(eglImage);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001215}
1216
Nicolas Capens48908cb2018-01-08 13:07:14 -05001217EGLImageKHR CreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list)
1218{
1219 TRACE("(EGLDisplay dpy = %p, EGLContext ctx = %p, EGLenum target = 0x%X, buffer = %p, const EGLint attrib_list = %p)", dpy, ctx, target, buffer, attrib_list);
1220
1221 EGLAttribs attribs(attrib_list);
Nicolas Capensd7622ff2018-08-07 12:24:10 -04001222 return CreateImage(dpy, ctx, target, buffer, &attribs);
Nicolas Capens48908cb2018-01-08 13:07:14 -05001223}
1224
Nicolas Capens0bac2852016-05-07 06:09:58 -04001225EGLBoolean DestroyImageKHR(EGLDisplay dpy, EGLImageKHR image)
1226{
1227 TRACE("(EGLDisplay dpy = %p, EGLImageKHR image = %p)", dpy, image);
1228
1229 egl::Display *display = egl::Display::get(dpy);
1230
1231 if(!validateDisplay(display))
1232 {
1233 return error(EGL_BAD_DISPLAY, EGL_FALSE);
1234 }
1235
Nicolas Capens58df2f62016-06-07 14:48:56 -04001236 if(!display->destroySharedImage(image))
Nicolas Capens0bac2852016-05-07 06:09:58 -04001237 {
1238 return error(EGL_BAD_PARAMETER, EGL_FALSE);
1239 }
1240
Nicolas Capens0bac2852016-05-07 06:09:58 -04001241 return success(EGL_TRUE);
1242}
1243
Nicolas Capens48908cb2018-01-08 13:07:14 -05001244EGLDisplay GetPlatformDisplay(EGLenum platform, void *native_display, const EGLAttrib *attrib_list)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001245{
Nicolas Capens48908cb2018-01-08 13:07:14 -05001246 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 -04001247
Nicolas Capens0bac2852016-05-07 06:09:58 -04001248 #if defined(__linux__) && !defined(__ANDROID__)
Alexis Hetu1d672442016-06-23 11:24:00 -04001249 switch(platform)
1250 {
Alexis Hetuc47cd432018-08-10 11:48:33 -04001251 #if defined(USE_X11)
1252 case EGL_PLATFORM_X11_EXT: break;
1253 #endif
1254 case EGL_PLATFORM_GBM_KHR: break;
Alexis Hetu1d672442016-06-23 11:24:00 -04001255 default:
1256 return error(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
1257 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04001258
Alexis Hetuc47cd432018-08-10 11:48:33 -04001259 if(platform == EGL_PLATFORM_GBM_KHR)
1260 {
1261 if(native_display != (void*)EGL_DEFAULT_DISPLAY)
1262 {
1263 return error(EGL_BAD_PARAMETER, EGL_NO_DISPLAY); // Unimplemented
1264 }
1265
1266 if(attrib_list && attrib_list[0] != EGL_NONE)
1267 {
1268 return error(EGL_BAD_ATTRIBUTE, EGL_NO_DISPLAY); // Unimplemented
1269 }
1270
1271 return success(HEADLESS_DISPLAY);
1272 }
1273 #if defined(USE_X11)
1274 else if(platform == EGL_PLATFORM_X11_EXT)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001275 {
1276 if(!libX11)
1277 {
Nicolas Capensd7622ff2018-08-07 12:24:10 -04001278 return error(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001279 }
1280
Nicolas Capensd7622ff2018-08-07 12:24:10 -04001281 if(native_display != (void*)EGL_DEFAULT_DISPLAY)
1282 {
1283 return error(EGL_BAD_PARAMETER, EGL_NO_DISPLAY); // Unimplemented
1284 }
1285
1286 if(attrib_list && attrib_list[0] != EGL_NONE)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001287 {
1288 return error(EGL_BAD_ATTRIBUTE, EGL_NO_DISPLAY); // Unimplemented
1289 }
1290 }
Alexis Hetuc47cd432018-08-10 11:48:33 -04001291 #endif
Nicolas Capens0bac2852016-05-07 06:09:58 -04001292
Alexis Hetu1d672442016-06-23 11:24:00 -04001293 return success(PRIMARY_DISPLAY); // We only support the default display
1294 #else
1295 return error(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
1296 #endif
Nicolas Capens0bac2852016-05-07 06:09:58 -04001297}
1298
Nicolas Capens48908cb2018-01-08 13:07:14 -05001299EGLDisplay GetPlatformDisplayEXT(EGLenum platform, void *native_display, const EGLint *attrib_list)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001300{
Nicolas Capens48908cb2018-01-08 13:07:14 -05001301 TRACE("(EGLenum platform = 0x%X, void *native_display = %p, const EGLint *attrib_list = %p)", platform, native_display, attrib_list);
1302
1303 EGLAttribs attribs(attrib_list);
Nicolas Capensd7622ff2018-08-07 12:24:10 -04001304 return GetPlatformDisplay(platform, native_display, &attribs);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001305}
1306
Nicolas Capens48908cb2018-01-08 13:07:14 -05001307EGLSync CreateSync(EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001308{
Nicolas Capens48908cb2018-01-08 13:07:14 -05001309 TRACE("(EGLDisplay dpy = %p, EGLunum type = %x, EGLAttrib *attrib_list=%p)", dpy, type, attrib_list);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001310
1311 egl::Display *display = egl::Display::get(dpy);
1312
1313 if(!validateDisplay(display))
1314 {
1315 return error(EGL_BAD_DISPLAY, EGL_NO_SYNC_KHR);
1316 }
1317
1318 if(type != EGL_SYNC_FENCE_KHR)
1319 {
1320 return error(EGL_BAD_ATTRIBUTE, EGL_NO_SYNC_KHR);
1321 }
1322
1323 if(attrib_list && attrib_list[0] != EGL_NONE)
1324 {
1325 return error(EGL_BAD_ATTRIBUTE, EGL_NO_SYNC_KHR);
1326 }
1327
1328 egl::Context *context = egl::getCurrentContext();
1329
1330 if(!validateContext(display, context))
1331 {
1332 return error(EGL_BAD_MATCH, EGL_NO_SYNC_KHR);
1333 }
1334
1335 EGLSyncKHR sync = display->createSync(context);
1336
1337 return success(sync);
1338}
1339
Nicolas Capens48908cb2018-01-08 13:07:14 -05001340EGLSyncKHR CreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
1341{
1342 TRACE("(EGLDisplay dpy = %p, EGLunum type = %x, EGLint *attrib_list=%p)", dpy, type, attrib_list);
1343
1344 EGLAttribs attribs(attrib_list);
Nicolas Capensd7622ff2018-08-07 12:24:10 -04001345 return CreateSync(dpy, type, &attribs);
Nicolas Capens48908cb2018-01-08 13:07:14 -05001346}
1347
Nicolas Capens0bac2852016-05-07 06:09:58 -04001348EGLBoolean DestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
1349{
1350 TRACE("(EGLDisplay dpy = %p, EGLSyncKHR sync = %p)", dpy, sync);
1351
1352 egl::Display *display = egl::Display::get(dpy);
1353 FenceSync *eglSync = static_cast<FenceSync*>(sync);
1354
1355 if(!validateDisplay(display))
1356 {
1357 return error(EGL_BAD_DISPLAY, EGL_FALSE);
1358 }
1359
1360 if(!display->isValidSync(eglSync))
1361 {
1362 return error(EGL_BAD_PARAMETER, EGL_FALSE);
1363 }
1364
1365 display->destroySync(eglSync);
1366
1367 return success(EGL_TRUE);
1368}
1369
1370EGLint ClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout)
1371{
1372 TRACE("(EGLDisplay dpy = %p, EGLSyncKHR sync = %p, EGLint flags = %x, EGLTimeKHR value = %llx)", dpy, sync, flags, timeout);
1373
1374 egl::Display *display = egl::Display::get(dpy);
1375 FenceSync *eglSync = static_cast<FenceSync*>(sync);
1376
1377 if(!validateDisplay(display))
1378 {
1379 return error(EGL_BAD_DISPLAY, EGL_FALSE);
1380 }
1381
1382 if(!display->isValidSync(eglSync))
1383 {
1384 return error(EGL_BAD_PARAMETER, EGL_FALSE);
1385 }
1386
1387 (void)flags;
1388 (void)timeout;
1389
1390 if(!eglSync->isSignaled())
1391 {
1392 eglSync->wait();
1393 }
1394
1395 return success(EGL_CONDITION_SATISFIED_KHR);
1396}
1397
Nicolas Capens48908cb2018-01-08 13:07:14 -05001398EGLBoolean GetSyncAttrib(EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLAttrib *value)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001399{
Nicolas Capens48908cb2018-01-08 13:07:14 -05001400 TRACE("(EGLDisplay dpy = %p, EGLSyncKHR sync = %p, EGLint attribute = %x, EGLAttrib *value = %p)", dpy, sync, attribute, value);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001401
1402 egl::Display *display = egl::Display::get(dpy);
1403 FenceSync *eglSync = static_cast<FenceSync*>(sync);
1404
1405 if(!validateDisplay(display))
1406 {
1407 return error(EGL_BAD_DISPLAY, EGL_FALSE);
1408 }
1409
1410 if(!display->isValidSync(eglSync))
1411 {
1412 return error(EGL_BAD_PARAMETER, EGL_FALSE);
1413 }
1414
1415 switch(attribute)
1416 {
1417 case EGL_SYNC_TYPE_KHR:
1418 *value = EGL_SYNC_FENCE_KHR;
1419 return success(EGL_TRUE);
1420 case EGL_SYNC_STATUS_KHR:
1421 eglSync->wait(); // TODO: Don't block. Just poll based on sw::Query.
1422 *value = eglSync->isSignaled() ? EGL_SIGNALED_KHR : EGL_UNSIGNALED_KHR;
1423 return success(EGL_TRUE);
1424 case EGL_SYNC_CONDITION_KHR:
1425 *value = EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR;
1426 return success(EGL_TRUE);
1427 default:
1428 return error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
1429 }
1430}
1431
Nicolas Capens48908cb2018-01-08 13:07:14 -05001432EGLBoolean GetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value)
1433{
1434 EGLAttrib attrib_value;
1435 EGLBoolean result = GetSyncAttrib(dpy, sync, attribute, &attrib_value);
1436 *value = static_cast<EGLint>(attrib_value);
1437 return result;
1438}
1439
Nicolas Capens0bac2852016-05-07 06:09:58 -04001440__eglMustCastToProperFunctionPointerType GetProcAddress(const char *procname)
1441{
1442 TRACE("(const char *procname = \"%s\")", procname);
1443
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01001444 struct Function
Nicolas Capens0bac2852016-05-07 06:09:58 -04001445 {
1446 const char *name;
1447 __eglMustCastToProperFunctionPointerType address;
1448 };
1449
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01001450 struct CompareFunctor
Nicolas Capens0bac2852016-05-07 06:09:58 -04001451 {
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01001452 bool operator()(const Function &a, const Function &b) const
1453 {
1454 return strcmp(a.name, b.name) < 0;
1455 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04001456 };
1457
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01001458 // This array must be kept sorted with respect to strcmp(), so that binary search works correctly.
1459 // The Unix command "LC_COLLATE=C sort" will generate the correct order.
1460 static const Function eglFunctions[] =
Nicolas Capens0bac2852016-05-07 06:09:58 -04001461 {
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01001462 #define FUNCTION(name) {#name, (__eglMustCastToProperFunctionPointerType)name}
1463
1464 FUNCTION(eglBindAPI),
1465 FUNCTION(eglBindTexImage),
1466 FUNCTION(eglChooseConfig),
Nicolas Capens48908cb2018-01-08 13:07:14 -05001467 FUNCTION(eglClientWaitSync),
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01001468 FUNCTION(eglClientWaitSyncKHR),
1469 FUNCTION(eglCopyBuffers),
1470 FUNCTION(eglCreateContext),
Nicolas Capens48908cb2018-01-08 13:07:14 -05001471 FUNCTION(eglCreateImage),
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01001472 FUNCTION(eglCreateImageKHR),
1473 FUNCTION(eglCreatePbufferFromClientBuffer),
1474 FUNCTION(eglCreatePbufferSurface),
1475 FUNCTION(eglCreatePixmapSurface),
Nicolas Capens48908cb2018-01-08 13:07:14 -05001476 FUNCTION(eglCreatePlatformPixmapSurface),
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01001477 FUNCTION(eglCreatePlatformPixmapSurfaceEXT),
Nicolas Capens48908cb2018-01-08 13:07:14 -05001478 FUNCTION(eglCreatePlatformWindowSurface),
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01001479 FUNCTION(eglCreatePlatformWindowSurfaceEXT),
Nicolas Capens48908cb2018-01-08 13:07:14 -05001480 FUNCTION(eglCreateSync),
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01001481 FUNCTION(eglCreateSyncKHR),
1482 FUNCTION(eglCreateWindowSurface),
1483 FUNCTION(eglDestroyContext),
Nicolas Capens48908cb2018-01-08 13:07:14 -05001484 FUNCTION(eglDestroyImage),
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01001485 FUNCTION(eglDestroyImageKHR),
1486 FUNCTION(eglDestroySurface),
Nicolas Capens48908cb2018-01-08 13:07:14 -05001487 FUNCTION(eglDestroySync),
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01001488 FUNCTION(eglDestroySyncKHR),
1489 FUNCTION(eglGetConfigAttrib),
1490 FUNCTION(eglGetConfigs),
1491 FUNCTION(eglGetCurrentContext),
1492 FUNCTION(eglGetCurrentDisplay),
1493 FUNCTION(eglGetCurrentSurface),
1494 FUNCTION(eglGetDisplay),
1495 FUNCTION(eglGetError),
Nicolas Capens48908cb2018-01-08 13:07:14 -05001496 FUNCTION(eglGetPlatformDisplay),
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01001497 FUNCTION(eglGetPlatformDisplayEXT),
1498 FUNCTION(eglGetProcAddress),
Nicolas Capens48908cb2018-01-08 13:07:14 -05001499 FUNCTION(eglGetSyncAttrib),
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01001500 FUNCTION(eglGetSyncAttribKHR),
1501 FUNCTION(eglInitialize),
1502 FUNCTION(eglMakeCurrent),
1503 FUNCTION(eglQueryAPI),
1504 FUNCTION(eglQueryContext),
1505 FUNCTION(eglQueryString),
1506 FUNCTION(eglQuerySurface),
1507 FUNCTION(eglReleaseTexImage),
1508 FUNCTION(eglReleaseThread),
1509 FUNCTION(eglSurfaceAttrib),
1510 FUNCTION(eglSwapBuffers),
1511 FUNCTION(eglSwapInterval),
1512 FUNCTION(eglTerminate),
1513 FUNCTION(eglWaitClient),
1514 FUNCTION(eglWaitGL),
1515 FUNCTION(eglWaitNative),
Nicolas Capens48908cb2018-01-08 13:07:14 -05001516 FUNCTION(eglWaitSync),
1517 FUNCTION(eglWaitSyncKHR),
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01001518
1519 #undef FUNCTION
1520 };
1521
1522 static const size_t numFunctions = sizeof eglFunctions / sizeof(Function);
1523 static const Function *const eglFunctionsEnd = eglFunctions + numFunctions;
1524
1525 Function needle;
1526 needle.name = procname;
1527
1528 if(procname && strncmp("egl", procname, 3) == 0)
1529 {
1530 const Function *result = std::lower_bound(eglFunctions, eglFunctionsEnd, needle, CompareFunctor());
1531 if (result != eglFunctionsEnd && strcmp(procname, result->name) == 0)
Nicolas Capens0bac2852016-05-07 06:09:58 -04001532 {
Krzysztof Kosińskif919b862018-01-03 23:17:52 +01001533 return success((__eglMustCastToProperFunctionPointerType)result->address);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001534 }
1535 }
1536
1537 if(libGLESv2)
1538 {
1539 __eglMustCastToProperFunctionPointerType proc = libGLESv2->es2GetProcAddress(procname);
1540 if(proc) return success(proc);
1541 }
1542
1543 if(libGLES_CM)
1544 {
1545 __eglMustCastToProperFunctionPointerType proc = libGLES_CM->es1GetProcAddress(procname);
1546 if(proc) return success(proc);
1547 }
1548
1549 return success((__eglMustCastToProperFunctionPointerType)NULL);
1550}
1551}