VirtualBox

source: vbox/trunk/src/VBox/Additions/common/crOpenGL/egl.c@ 65535

Last change on this file since 65535 was 65535, checked in by vboxsync, 7 years ago

8748: Additions/Graphics/Wayland: investigate EGLStreams support feasibility: fix problem with hole in attribute list when wrapping around glXChooseFBConfig in eglChooseConfig.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 33.5 KB
Line 
1/* $Id: egl.c 65535 2017-01-31 11:17:12Z vboxsync $ */
2
3/** @file
4 * VBox OpenGL EGL implentation.
5 */
6
7/*
8 * Copyright (C) 2009-2016 Oracle Corporation
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.virtualbox.org. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License (GPL) as published by the Free Software
14 * Foundation, in version 2 as it comes in the "COPYING" file of the
15 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
17 */
18
19/*******************************************************************************
20* Header Files *
21*******************************************************************************/
22#include <iprt/cdefs.h>
23#include <iprt/types.h>
24
25#include <EGL/egl.h>
26#include <GL/glx.h>
27#include <X11/Xlib.h>
28
29#include <dlfcn.h>
30#include <pthread.h>
31#include <stdio.h>
32#include <stdlib.h>
33#include <string.h>
34
35#define EGL_ASSERT(expr) \
36 if (!(expr)) { printf("Assertion failed: %s\n", #expr); exit(1); }
37
38/*******************************************************************************
39* Structures and Typedefs *
40*******************************************************************************/
41
42struct VBEGLTLS
43{
44 /** The last EGL error. */
45 EGLint cErr;
46 /** The EGL API currently bound to this thread. */
47 EGLenum enmAPI;
48 /** The current context. */
49 EGLContext hCurrent;
50 /** The display bound to the current context. */
51 EGLDisplay hCurrentDisplay;
52 /** The draw surface bound to the current context. */
53 EGLSurface hCurrentDraw;
54 /** The read surface bound to the current context. */
55 EGLSurface hCurrentRead;
56};
57
58/*******************************************************************************
59* Defined Constants And Macros *
60*******************************************************************************/
61/** @note IDs returned for surfaces should always be lower than these constants.
62 */
63/** This is OR-ed with a surface ID to mark it as a window, as GLX needs to
64 * know. */
65#define VBEGL_WINDOW_SURFACE 0x20000000
66/** This is OR-ed with a surface ID to mark it as a pbuffer, as GLX needs to
67 * know. */
68#define VBEGL_PBUFFER_SURFACE 0x40000000
69/** This is OR-ed with a surface ID to mark it as a pixmap, as GLX needs to
70 * know. */
71#define VBEGL_PIXMAP_SURFACE 0x80000000
72#define VBEGL_ANY_SURFACE (VBEGL_WINDOW_SURFACE | VBEGL_PBUFFER_SURFACE | VBEGL_PIXMAP_SURFACE)
73
74/*******************************************************************************
75* Global variables *
76*******************************************************************************/
77
78static pthread_key_t g_tls;
79static pthread_once_t g_tlsOnce = PTHREAD_ONCE_INIT;
80static Display *g_pDefaultDisplay = NULL;
81static pthread_once_t g_defaultDisplayOnce = PTHREAD_ONCE_INIT;
82
83static void tlsInitOnce(void)
84{
85 pthread_key_create(&g_tls, NULL);
86}
87
88static struct VBEGLTLS *getTls(void)
89{
90 struct VBEGLTLS *pTls;
91
92 pthread_once(&g_tlsOnce, tlsInitOnce);
93 pTls = (struct VBEGLTLS *)pthread_getspecific(g_tls);
94 if (RT_LIKELY(pTls))
95 return pTls;
96 pTls = (struct VBEGLTLS *)malloc(sizeof(*pTls));
97 if (!VALID_PTR(pTls))
98 return NULL;
99 pTls->cErr = EGL_SUCCESS;
100 pTls->enmAPI = EGL_NONE;
101 pTls->hCurrent = EGL_NO_CONTEXT;
102 pTls->hCurrentDisplay = EGL_NO_DISPLAY;
103 pTls->hCurrentDraw = EGL_NO_SURFACE;
104 pTls->hCurrentRead = EGL_NO_SURFACE;
105 if (pthread_setspecific(g_tls, pTls) == 0)
106 return pTls;
107 free(pTls);
108 return NULL;
109}
110
111static void defaultDisplayInitOnce(void)
112{
113 g_pDefaultDisplay = XOpenDisplay(NULL);
114}
115
116static EGLBoolean clearEGLError(void)
117{
118 struct VBEGLTLS *pTls = getTls();
119
120 if (!VALID_PTR(pTls))
121 return EGL_FALSE;
122 pTls->cErr = EGL_SUCCESS;
123 return EGL_TRUE;
124}
125
126static EGLBoolean setEGLError(EGLint cErr)
127{
128 struct VBEGLTLS *pTls = getTls();
129
130 if (pTls)
131 pTls->cErr = cErr;
132 return EGL_FALSE;
133}
134
135static EGLBoolean testValidDisplay(EGLNativeDisplayType hDisplay)
136{
137 void *pSymbol = dlsym(NULL, "gbm_create_device");
138
139 if (hDisplay == EGL_DEFAULT_DISPLAY)
140 return EGL_TRUE;
141 if ((void *)hDisplay == NULL)
142 return EGL_FALSE;
143 /* This is the test that Mesa uses to see if this is a GBM "display". Not
144 * very pretty, but since no one can afford to break Mesa it should be
145 * safe. We need this to detect when the X server tries to load us. */
146 if (pSymbol != NULL && *(void **)hDisplay == pSymbol)
147 return EGL_FALSE;
148 return EGL_TRUE;
149}
150
151DECLEXPORT(EGLDisplay) eglGetDisplay(EGLNativeDisplayType hDisplay)
152{
153 Display *pDisplay;
154
155 if (!testValidDisplay(hDisplay))
156 return EGL_NO_DISPLAY;
157 if (!clearEGLError()) /* Set up our tls. */
158 return EGL_NO_DISPLAY;
159 if (hDisplay != EGL_DEFAULT_DISPLAY)
160 pDisplay = hDisplay;
161 else
162 {
163 pthread_once(&g_defaultDisplayOnce, defaultDisplayInitOnce);
164 pDisplay = g_pDefaultDisplay;
165 }
166 if (pDisplay && !strcmp(glXGetClientString(pDisplay, GLX_VENDOR), "Chromium"))
167 return (EGLDisplay) pDisplay;
168 return EGL_NO_DISPLAY;
169}
170
171DECLEXPORT(EGLint) eglGetError(void)
172{
173 struct VBEGLTLS *pTls = getTls();
174
175 if (pTls)
176 return pTls->cErr;
177 return EGL_NOT_INITIALIZED;
178}
179
180DECLEXPORT(EGLBoolean) eglInitialize (EGLDisplay hDisplay, EGLint *pcMajor, EGLint *pcMinor)
181{
182 if (hDisplay == EGL_NO_DISPLAY)
183 return EGL_FALSE;
184 if (!VALID_PTR(hDisplay))
185 return setEGLError(EGL_BAD_DISPLAY);
186 if (pcMajor)
187 *pcMajor = 1;
188 if (pcMinor)
189 *pcMinor = 4;
190 return clearEGLError();
191}
192
193/** @todo This function should terminate all allocated resources. */
194DECLEXPORT(EGLBoolean) eglTerminate(EGLDisplay hDisplay)
195{
196 if (!VALID_PTR(hDisplay))
197 return EGL_FALSE;
198 return EGL_TRUE;
199}
200
201DECLEXPORT(const char *) eglQueryString(EGLDisplay hDisplay, EGLint name)
202{
203 RT_NOREF(hDisplay);
204 switch (name)
205 {
206 case EGL_CLIENT_APIS:
207 return "OpenGL";
208 case EGL_VENDOR:
209 return "Chromium";
210 case EGL_VERSION:
211 return "1.4 Chromium";
212 case EGL_EXTENSIONS:
213 return "";
214 default:
215 return NULL;
216 }
217}
218
219DECLEXPORT(EGLBoolean) eglGetConfigs (EGLDisplay hDisplay, EGLConfig *paConfigs, EGLint caConfigs, EGLint *pcaConfigs)
220{
221 Display *pDisplay = (Display *)hDisplay;
222 GLXFBConfig *paFBConfigs;
223 int caFBConfigs, i;
224
225 if (!VALID_PTR(pDisplay))
226 return setEGLError(EGL_NOT_INITIALIZED);
227 if (!VALID_PTR(pcaConfigs))
228 return setEGLError(EGL_BAD_PARAMETER);
229 if (caConfigs > 0 && !VALID_PTR(paConfigs))
230 return setEGLError(EGL_BAD_PARAMETER);
231 paFBConfigs = glXGetFBConfigs(pDisplay, DefaultScreen(pDisplay), &caFBConfigs);
232 if (!VALID_PTR(paFBConfigs))
233 return setEGLError(EGL_BAD_PARAMETER);
234 if (caFBConfigs > caConfigs)
235 caFBConfigs = caConfigs;
236 *pcaConfigs = caFBConfigs;
237 for (i = 0; i < caFBConfigs; ++i)
238 paConfigs[i] = (EGLConfig)paFBConfigs[i];
239 XFree(paFBConfigs);
240 return clearEGLError();
241}
242
243static int convertEGLAttribToGLX(EGLint a_EGLAttrib)
244{
245 switch (a_EGLAttrib)
246 {
247 case EGL_BUFFER_SIZE:
248 return GLX_BUFFER_SIZE;
249 case EGL_RED_SIZE:
250 return GLX_RED_SIZE;
251 case EGL_GREEN_SIZE:
252 return GLX_GREEN_SIZE;
253 case EGL_BLUE_SIZE:
254 return GLX_BLUE_SIZE;
255 case EGL_LUMINANCE_SIZE:
256 return GLX_RED_SIZE;
257 case EGL_ALPHA_SIZE:
258 return GLX_ALPHA_SIZE;
259 /* case EGL_ALPHA_MASK_SIZE: */
260 /* case EGL_BIND_TO_TEXTURE_RGB: */
261 /* case EGL_BIND_TO_TEXTURE_RGBA: */
262 /* case EGL_COLOR_BUFFER_TYPE: */
263 /* case EGL_CONFIG_CAVEAT: */
264 case EGL_CONFIG_ID:
265 return GLX_FBCONFIG_ID;
266 /* case EGL_CONFORMANT: */
267 case EGL_DEPTH_SIZE:
268 return GLX_DEPTH_SIZE;
269 case EGL_LEVEL:
270 return GLX_LEVEL;
271 case EGL_MAX_PBUFFER_WIDTH:
272 return GLX_MAX_PBUFFER_WIDTH;
273 case EGL_MAX_PBUFFER_HEIGHT:
274 return GLX_MAX_PBUFFER_HEIGHT;
275 case EGL_MAX_PBUFFER_PIXELS:
276 return GLX_MAX_PBUFFER_PIXELS;
277 /* case EGL_MATCH_NATIVE_PIXMAP: */
278 /* case EGL_MAX_SWAP_INTERVAL: */
279 /* case EGL_MIN_SWAP_INTERVAL: */
280 case EGL_NATIVE_RENDERABLE:
281 return GLX_X_RENDERABLE;
282 case EGL_NATIVE_VISUAL_ID:
283 return GLX_VISUAL_ID;
284 /* case EGL_NATIVE_VISUAL_TYPE: */
285 /* case EGL_RENDERABLE_TYPE: */
286 case EGL_SAMPLE_BUFFERS:
287 return GLX_SAMPLE_BUFFERS;
288 case EGL_SAMPLES:
289 return GLX_SAMPLES;
290 case EGL_STENCIL_SIZE:
291 return GLX_STENCIL_SIZE;
292 /* case EGL_SURFACE_TYPE: */
293 /* case EGL_TRANSPARENT_TYPE: */
294 case EGL_TRANSPARENT_RED_VALUE:
295 return GLX_TRANSPARENT_RED_VALUE;
296 case EGL_TRANSPARENT_GREEN_VALUE:
297 return GLX_TRANSPARENT_GREEN_VALUE;
298 case EGL_TRANSPARENT_BLUE_VALUE:
299 return GLX_TRANSPARENT_BLUE_VALUE;
300 default:
301 return None;
302 }
303}
304
305DECLEXPORT(EGLBoolean) eglChooseConfig (EGLDisplay hDisplay, const EGLint *paAttribs, EGLConfig *paConfigs, EGLint caConfigs,
306 EGLint *pcConfigs)
307{
308 Display *pDisplay = (Display *)hDisplay;
309 int aAttribList[256]; /* The list cannot be this long. */
310 unsigned cAttribs = 0, i;
311 const EGLint *pAttrib, *pAttrib2;
312 EGLint cRenderableType = EGL_OPENGL_ES_BIT;
313 unsigned cConfigCaveat = GLX_DONT_CARE, cConformant = GLX_DONT_CARE;
314 GLXFBConfig *paFBConfigs;
315 int caFBConfigs;
316
317 if (!VALID_PTR(hDisplay))
318 return setEGLError(EGL_NOT_INITIALIZED);
319 if (!VALID_PTR(pcConfigs))
320 return setEGLError(EGL_BAD_PARAMETER);
321 if (caConfigs > 0 && !VALID_PTR(paConfigs))
322 return setEGLError(EGL_BAD_PARAMETER);
323 for (pAttrib = paAttribs; pAttrib != NULL && *pAttrib != EGL_NONE; pAttrib += 2)
324 {
325 bool fSkip = false;
326 int cGLXAttrib;
327
328 /* Check for illegal values. */
329 if ((*pAttrib == EGL_LEVEL || *pAttrib == EGL_MATCH_NATIVE_PIXMAP) && pAttrib[1] == EGL_DONT_CARE)
330 return setEGLError(EGL_BAD_ATTRIBUTE);
331 /* Check for values we can't handle. */
332 if ( (*pAttrib == EGL_ALPHA_MASK_SIZE)
333 && pAttrib[1] != EGL_DONT_CARE && pAttrib[1] != 0)
334 return setEGLError(EGL_BAD_ACCESS);
335 /** @todo try creating a pixmap from a native one with the configurations returned. */
336 if (*pAttrib == EGL_MATCH_NATIVE_PIXMAP)
337 return setEGLError(EGL_BAD_ACCESS);
338 if ( ( *pAttrib == EGL_MIN_SWAP_INTERVAL || *pAttrib == EGL_MAX_SWAP_INTERVAL
339 || *pAttrib == EGL_BIND_TO_TEXTURE_RGB || *pAttrib == EGL_BIND_TO_TEXTURE_RGBA)
340 && pAttrib[1] != EGL_DONT_CARE)
341 return setEGLError(EGL_BAD_ACCESS);
342 /* Ignore attributes which are repeated later. */
343 for (pAttrib2 = pAttrib + 2; *pAttrib2 != EGL_NONE; pAttrib2 += 2)
344 if (*pAttrib2 == *pAttrib)
345 fSkip == true;
346 if (fSkip)
347 continue;
348 cGLXAttrib = convertEGLAttribToGLX(*pAttrib);
349 if (cGLXAttrib != None)
350 {
351 aAttribList[cAttribs] = cGLXAttrib;
352 if (pAttrib[1] == EGL_DONT_CARE)
353 aAttribList[cAttribs + 1] = GLX_DONT_CARE;
354 else
355 aAttribList[cAttribs + 1] = pAttrib[1];
356 cAttribs += 2;
357 }
358 else
359 {
360 switch (*pAttrib)
361 {
362 case EGL_COLOR_BUFFER_TYPE:
363 aAttribList[cAttribs] = GLX_X_VISUAL_TYPE;
364 aAttribList[cAttribs + 1] = pAttrib[1] == EGL_DONT_CARE ? GLX_DONT_CARE
365 : pAttrib[1] == EGL_RGB_BUFFER ? GLX_TRUE_COLOR
366 : pAttrib[1] == EGL_LUMINANCE_BUFFER ? GLX_GRAY_SCALE
367 : GL_FALSE;
368 if ( *pAttrib == EGL_COLOR_BUFFER_TYPE
369 && pAttrib[1] != EGL_DONT_CARE && pAttrib[1] != EGL_RGB_BUFFER)
370 return setEGLError(EGL_BAD_ACCESS);
371 break;
372 case EGL_CONFIG_CAVEAT:
373 cConfigCaveat = pAttrib[1] == EGL_DONT_CARE ? GLX_DONT_CARE
374 : pAttrib[1] == EGL_NONE ? GLX_NONE
375 : pAttrib[1] == EGL_SLOW_CONFIG ? GLX_SLOW_CONFIG
376 : pAttrib[1] == EGL_NON_CONFORMANT_CONFIG ? GLX_NON_CONFORMANT_CONFIG
377 : GL_FALSE;
378 if (!cConfigCaveat)
379 return setEGLError(EGL_BAD_ATTRIBUTE);
380 cAttribs -= 2;
381 break;
382 case EGL_CONFORMANT:
383 if (pAttrib[1] != EGL_OPENGL_BIT && pAttrib[1] != 0)
384 return setEGLError(EGL_BAD_ACCESS);
385 cConformant = pAttrib[1] == EGL_OPENGL_BIT ? GL_TRUE : GL_FALSE;
386 cAttribs -= 2;
387 break;
388 case EGL_NATIVE_VISUAL_TYPE:
389 aAttribList[cAttribs] = GLX_X_VISUAL_TYPE;
390 aAttribList[cAttribs + 1] = pAttrib[1] == EGL_DONT_CARE ? GLX_DONT_CARE
391 : pAttrib[1] == StaticGray ? GLX_STATIC_GRAY
392 : pAttrib[1] == StaticColor ? GLX_STATIC_COLOR
393 : pAttrib[1] == TrueColor ? GLX_TRUE_COLOR
394 : pAttrib[1] == GrayScale ? GLX_GRAY_SCALE
395 : pAttrib[1] == PseudoColor ? GLX_PSEUDO_COLOR
396 : pAttrib[1] == DirectColor ? GLX_DIRECT_COLOR
397 : GL_FALSE;
398 break;
399 case EGL_RENDERABLE_TYPE:
400 cRenderableType = pAttrib[1];
401 cAttribs -= 2; /* We did not add anything to the list. */
402 break;
403 case EGL_SURFACE_TYPE:
404 if (pAttrib[1] & ~(EGL_PBUFFER_BIT | EGL_PIXMAP_BIT | EGL_WINDOW_BIT))
405 return setEGLError(EGL_BAD_ACCESS);
406 aAttribList[cAttribs] = GLX_DRAWABLE_TYPE;
407 aAttribList[cAttribs + 1] = (pAttrib[1] & EGL_PBUFFER_BIT ? GLX_PBUFFER_BIT : 0)
408 | (pAttrib[1] & EGL_PIXMAP_BIT ? GLX_PIXMAP_BIT : 0)
409 | (pAttrib[1] & EGL_WINDOW_BIT ? GLX_WINDOW_BIT : 0);
410 break;
411 case EGL_TRANSPARENT_TYPE:
412 aAttribList[cAttribs] = GLX_TRANSPARENT_TYPE;
413 aAttribList[cAttribs + 1] = pAttrib[1] == EGL_DONT_CARE ? GLX_DONT_CARE
414 : pAttrib[1] == EGL_NONE ? GLX_NONE
415 : pAttrib[1] == EGL_TRANSPARENT_RGB ? GLX_TRANSPARENT_RGB
416 : GL_FALSE;
417 break;
418 default:
419 return setEGLError(EGL_BAD_ATTRIBUTE);
420 }
421 cAttribs += 2;
422 }
423 }
424 if (cConfigCaveat != GLX_DONT_CARE || cConformant != GLX_DONT_CARE)
425 {
426 aAttribList[cAttribs] = GLX_CONFIG_CAVEAT;
427 aAttribList[cAttribs + 1] = cConformant == GL_FALSE ? GLX_NON_CONFORMANT_CONFIG
428 : cConfigCaveat == EGL_SLOW_CONFIG ? GLX_SLOW_CONFIG
429 : GLX_NONE;
430 cAttribs += 2;
431 }
432 aAttribList[cAttribs] = GLX_RENDER_TYPE;
433 aAttribList[cAttribs + 1] = GLX_RGBA_BIT;
434 cAttribs += 2;
435 if (paAttribs != NULL)
436 {
437 aAttribList[cAttribs] = None;
438 EGL_ASSERT(cAttribs < RT_ELEMENTS(aAttribList));
439 if (!(cRenderableType & EGL_OPENGL_BIT))
440 return setEGLError(EGL_BAD_ACCESS);
441 }
442 paFBConfigs = glXChooseFBConfig(pDisplay, DefaultScreen(pDisplay), paAttribs != NULL ? aAttribList : NULL, &caFBConfigs);
443 if (paFBConfigs == NULL)
444 return setEGLError(EGL_BAD_ACCESS);
445 *pcConfigs = caFBConfigs;
446 for (i = 0; (GLint)i < caConfigs && (GLint)i < caFBConfigs; ++i)
447 paConfigs[i] = (EGLConfig)paFBConfigs[i];
448 XFree(paFBConfigs);
449 return clearEGLError();
450}
451
452DECLEXPORT(EGLBoolean) eglGetConfigAttrib (EGLDisplay hDisplay, EGLConfig cConfig, EGLint cAttribute, EGLint *pValue)
453{
454 Display *pDisplay = (Display *)hDisplay;
455 int cGLXAttribute = convertEGLAttribToGLX(cAttribute);
456 int cValue;
457
458 if (!VALID_PTR(hDisplay))
459 return setEGLError(EGL_NOT_INITIALIZED);
460 if (!VALID_PTR(pValue))
461 return setEGLError(EGL_BAD_PARAMETER);
462 if (glXGetFBConfigAttrib(pDisplay, (GLXFBConfig)cConfig, GLX_FBCONFIG_ID, &cValue))
463 return setEGLError(EGL_BAD_CONFIG);
464 if (cGLXAttribute != None)
465 {
466 if (glXGetFBConfigAttrib(pDisplay, (GLXFBConfig)cConfig, cGLXAttribute, &cValue))
467 return setEGLError(EGL_BAD_ACCESS);
468 *pValue = cValue;
469 return clearEGLError();
470 }
471 switch (cAttribute)
472 {
473 case EGL_ALPHA_MASK_SIZE:
474 *pValue = 0;
475 return clearEGLError();
476 case EGL_LUMINANCE_SIZE:
477 if (glXGetFBConfigAttrib(pDisplay, (GLXFBConfig)cConfig, GLX_X_VISUAL_TYPE, &cValue))
478 return setEGLError(EGL_BAD_ACCESS);
479 if (cValue == GLX_STATIC_GRAY || cValue == GLX_GRAY_SCALE)
480 {
481 if (glXGetFBConfigAttrib(pDisplay, (GLXFBConfig)cConfig, GLX_RED_SIZE, &cValue))
482 return setEGLError(EGL_BAD_ACCESS);
483 *pValue = cValue;
484 }
485 else
486 *pValue = 0;
487 return clearEGLError();
488 case EGL_COLOR_BUFFER_TYPE:
489 if (glXGetFBConfigAttrib(pDisplay, (GLXFBConfig)cConfig, GLX_X_VISUAL_TYPE, &cValue))
490 return setEGLError(EGL_BAD_ACCESS);
491 if (cValue == GLX_STATIC_GRAY || cValue == GLX_GRAY_SCALE)
492 *pValue = EGL_LUMINANCE_BUFFER;
493 else
494 *pValue = EGL_RGB_BUFFER;
495 return clearEGLError();
496 case EGL_CONFIG_CAVEAT:
497 if (glXGetFBConfigAttrib(pDisplay, (GLXFBConfig)cConfig, GLX_CONFIG_CAVEAT, &cValue))
498 return setEGLError(EGL_BAD_ACCESS);
499 *pValue = cValue == GLX_NONE ? EGL_NONE : cValue == GLX_SLOW_CONFIG ? EGL_SLOW_CONFIG : GLX_NON_CONFORMANT_CONFIG;
500 return clearEGLError();
501 case EGL_CONFORMANT:
502 if (glXGetFBConfigAttrib(pDisplay, (GLXFBConfig)cConfig, GLX_CONFIG_CAVEAT, &cValue))
503 return setEGLError(EGL_BAD_ACCESS);
504 *pValue = cValue == GLX_NON_CONFORMANT_CONFIG ? 0 : EGL_OPENGL_BIT;
505 return clearEGLError();
506 case EGL_MATCH_NATIVE_PIXMAP:
507 case EGL_MIN_SWAP_INTERVAL:
508 case EGL_MAX_SWAP_INTERVAL:
509 return setEGLError(EGL_BAD_ACCESS);
510 case EGL_NATIVE_VISUAL_TYPE:
511 if (glXGetFBConfigAttrib(pDisplay, (GLXFBConfig)cConfig, GLX_X_VISUAL_TYPE, &cValue))
512 return setEGLError(EGL_BAD_ACCESS);
513 *pValue = cValue == GLX_STATIC_GRAY ? StaticGray
514 : cValue == GLX_STATIC_COLOR ? StaticColor
515 : cValue == GLX_TRUE_COLOR ? TrueColor
516 : cValue == GLX_GRAY_SCALE ? GrayScale
517 : cValue == GLX_PSEUDO_COLOR ? PseudoColor
518 : cValue == GLX_DIRECT_COLOR ? DirectColor
519 : -1;
520 return clearEGLError();
521 case EGL_RENDERABLE_TYPE:
522 *pValue = EGL_OPENGL_BIT;
523 return clearEGLError();
524 case EGL_SURFACE_TYPE:
525 if (glXGetFBConfigAttrib(pDisplay, (GLXFBConfig)cConfig, GLX_DRAWABLE_TYPE, &cValue))
526 return setEGLError(EGL_BAD_ACCESS);
527 *pValue = (cValue & GLX_PBUFFER_BIT ? EGL_PBUFFER_BIT : 0)
528 | (cValue & GLX_PIXMAP_BIT ? EGL_PIXMAP_BIT : 0)
529 | (cValue & GLX_WINDOW_BIT ? EGL_WINDOW_BIT : 0);
530 return clearEGLError();
531 case EGL_TRANSPARENT_TYPE:
532 if (glXGetFBConfigAttrib(pDisplay, (GLXFBConfig)cConfig, GLX_TRANSPARENT_TYPE, &cValue))
533 return setEGLError(EGL_BAD_ACCESS);
534 *pValue = cValue == GLX_NONE ? EGL_NONE
535 : cValue == GLX_TRANSPARENT_RGB ? EGL_TRANSPARENT_RGB
536 : EGL_FALSE;
537 return *pValue != EGL_FALSE ? clearEGLError() : setEGLError(EGL_BAD_ACCESS);
538 default:
539 return setEGLError(EGL_BAD_ATTRIBUTE);
540 }
541 return clearEGLError();
542}
543
544DECLEXPORT(EGLSurface) eglCreateWindowSurface(EGLDisplay hDisplay, EGLConfig config, EGLNativeWindowType hWindow,
545 const EGLint *paAttributes)
546{
547 Display *pDisplay = (Display *)hDisplay;
548 GLXWindow hGLXWindow;
549
550 if (!VALID_PTR(hDisplay))
551 {
552 setEGLError(EGL_NOT_INITIALIZED);
553 return EGL_NO_SURFACE;
554 }
555 if (paAttributes != NULL) /* Sanity test only. */
556 while (*paAttributes != EGL_NONE)
557 {
558 if (*paAttributes != EGL_RENDER_BUFFER)
559 {
560 setEGLError(EGL_BAD_MATCH);
561 return EGL_NO_SURFACE;
562 }
563 paAttributes += 2;
564 }
565 hGLXWindow = glXCreateWindow(pDisplay, (GLXFBConfig)config, (Window)hWindow, NULL);
566 if (hGLXWindow == None)
567 {
568 setEGLError(EGL_BAD_ALLOC);
569 return EGL_NO_SURFACE;
570 }
571 EGL_ASSERT(hGLXWindow < VBEGL_WINDOW_SURFACE); /* Greater than the maximum XID. */
572 clearEGLError();
573 return (EGLSurface)(hGLXWindow | VBEGL_WINDOW_SURFACE);
574}
575
576static void setAttribute(int *pcStoreIndex, int *pcCurIndex, int *paGLXAttributes, int cAttribute, int cValue)
577{
578 if (*pcStoreIndex < 0)
579 {
580 *pcStoreIndex = *pcCurIndex;
581 *pcCurIndex += 2;
582 paGLXAttributes[*pcStoreIndex] = cAttribute;
583 }
584 paGLXAttributes[*pcStoreIndex + 1] = cValue;
585}
586
587DECLEXPORT(EGLSurface) eglCreatePbufferSurface(EGLDisplay hDisplay, EGLConfig config, EGLint const *paAttributes)
588{
589 Display *pDisplay = (Display *)hDisplay;
590 enum { CPS_WIDTH = 0, CPS_HEIGHT, CPS_LARGEST, CPS_PRESERVED, CPS_TEX_FORMAT, CPS_TEX_TARGET, CPS_MIPMAP_TEX, CPS_END };
591 int acIndices[CPS_END];
592 int aAttributes[CPS_END * 2];
593 int cIndex = 0;
594 unsigned i;
595 GLXPbuffer hPbuffer;
596
597 if (!VALID_PTR(hDisplay))
598 {
599 setEGLError(EGL_NOT_INITIALIZED);
600 return EGL_NO_SURFACE;
601 }
602 for (i = 0; i < RT_ELEMENTS(acIndices); ++i)
603 acIndices[i] = -1;
604 if (paAttributes != NULL)
605 while (*paAttributes != EGL_NONE)
606 {
607 switch (*paAttributes)
608 {
609 case EGL_WIDTH:
610 setAttribute(&acIndices[CPS_WIDTH], &cIndex, aAttributes, GLX_PBUFFER_WIDTH, paAttributes[1]);
611 break;
612 case EGL_HEIGHT:
613 setAttribute(&acIndices[CPS_HEIGHT], &cIndex, aAttributes, GLX_LARGEST_PBUFFER, paAttributes[1]);
614 break;
615 case EGL_LARGEST_PBUFFER:
616 setAttribute(&acIndices[CPS_LARGEST], &cIndex, aAttributes, GLX_PBUFFER_HEIGHT, paAttributes[1]);
617 break;
618 case EGL_BUFFER_PRESERVED:
619 setAttribute(&acIndices[CPS_PRESERVED], &cIndex, aAttributes, GLX_PRESERVED_CONTENTS, paAttributes[1]);
620 break;
621 case EGL_TEXTURE_FORMAT:
622 setAttribute(&acIndices[CPS_TEX_FORMAT], &cIndex, aAttributes, GLX_TEXTURE_FORMAT_EXT, paAttributes[1]);
623 break;
624 case EGL_TEXTURE_TARGET:
625 setAttribute(&acIndices[CPS_TEX_TARGET], &cIndex, aAttributes, GLX_TEXTURE_TARGET_EXT, paAttributes[1]);
626 break;
627 case EGL_MIPMAP_TEXTURE:
628 setAttribute(&acIndices[CPS_MIPMAP_TEX], &cIndex, aAttributes, GLX_MIPMAP_TEXTURE_EXT, paAttributes[1]);
629 break;
630 case EGL_VG_ALPHA_FORMAT:
631 case EGL_VG_COLORSPACE:
632 {
633 setEGLError(EGL_BAD_MATCH);
634 return EGL_NO_SURFACE;
635 }
636 }
637 paAttributes += 2;
638 }
639 EGL_ASSERT((unsigned)cIndex < RT_ELEMENTS(aAttributes) - 1U);
640 aAttributes[cIndex + 1] = None;
641 hPbuffer = glXCreatePbuffer(pDisplay, (GLXFBConfig)config, aAttributes);
642 if (hPbuffer == None)
643 {
644 setEGLError(EGL_BAD_ALLOC);
645 return EGL_NO_SURFACE;
646 }
647 EGL_ASSERT(hPbuffer < VBEGL_WINDOW_SURFACE); /* Greater than the maximum XID. */
648 clearEGLError();
649 return (EGLSurface)(hPbuffer | VBEGL_PBUFFER_SURFACE);
650}
651
652DECLEXPORT(EGLSurface) eglCreatePixmapSurface(EGLDisplay hDisplay, EGLConfig config, EGLNativePixmapType hPixmap,
653 const EGLint *paAttributes)
654{
655 Display *pDisplay = (Display *)hDisplay;
656 GLXPixmap hGLXPixmap;
657
658 if (!VALID_PTR(hDisplay))
659 {
660 setEGLError(EGL_NOT_INITIALIZED);
661 return EGL_NO_SURFACE;
662 }
663 if (paAttributes != NULL) /* Sanity test only. */
664 if (*paAttributes != EGL_NONE)
665 {
666 if (*paAttributes == EGL_VG_COLORSPACE || *paAttributes == EGL_VG_ALPHA_FORMAT)
667 {
668 setEGLError(EGL_BAD_MATCH);
669 return EGL_NO_SURFACE;
670 }
671 else
672 {
673 setEGLError(EGL_BAD_ATTRIBUTE);
674 return EGL_NO_SURFACE;
675 }
676 }
677 hGLXPixmap = glXCreatePixmap(pDisplay, (GLXFBConfig)config, (Pixmap)hPixmap, NULL);
678 if (hGLXPixmap == None)
679 {
680 setEGLError(EGL_BAD_MATCH);
681 return EGL_NO_SURFACE;
682 }
683 EGL_ASSERT(hGLXPixmap < VBEGL_WINDOW_SURFACE); /* Greater than the maximum XID. */
684 clearEGLError();
685 return (EGLSurface)(hGLXPixmap | VBEGL_PIXMAP_SURFACE);
686}
687
688DECLEXPORT(EGLBoolean) eglDestroySurface(EGLDisplay hDisplay, EGLSurface hSurface)
689{
690 Display *pDisplay = (Display *)hDisplay;
691
692 if (!VALID_PTR(hDisplay))
693 return setEGLError(EGL_NOT_INITIALIZED);
694 switch ((GLXDrawable)hSurface & VBEGL_ANY_SURFACE)
695 {
696 case VBEGL_WINDOW_SURFACE:
697 glXDestroyWindow(pDisplay, (GLXWindow)hSurface & ~VBEGL_WINDOW_SURFACE);
698 return clearEGLError();
699 case VBEGL_PBUFFER_SURFACE:
700 glXDestroyPbuffer(pDisplay, (GLXPbuffer)hSurface & ~VBEGL_PBUFFER_SURFACE);
701 return clearEGLError();
702 case VBEGL_PIXMAP_SURFACE:
703 glXDestroyPixmap(pDisplay, (GLXPixmap)hSurface & ~VBEGL_PIXMAP_SURFACE);
704 return clearEGLError();
705 default:
706 return setEGLError(EGL_BAD_SURFACE);
707 }
708}
709
710DECLEXPORT(EGLBoolean) eglSurfaceAttrib(EGLDisplay hDisplay, EGLSurface hSurface, EGLint cAttribute, EGLint cValue)
711{
712 NOREF(hDisplay);
713 NOREF(hSurface);
714 NOREF(cValue);
715 switch (cAttribute)
716 {
717 case EGL_MIPMAP_LEVEL:
718 case EGL_MULTISAMPLE_RESOLVE:
719 case EGL_SWAP_BEHAVIOR:
720 return setEGLError(EGL_BAD_MATCH);
721 default:
722 return setEGLError(EGL_BAD_ATTRIBUTE);
723 }
724}
725
726DECLEXPORT(EGLBoolean) eglQuerySurface(EGLDisplay hDisplay, EGLSurface hSurface, EGLint cAttribute, EGLint *cValue)
727{
728 NOREF(hDisplay);
729 NOREF(hSurface);
730 NOREF(cAttribute);
731 NOREF(cValue);
732 return setEGLError(EGL_BAD_MATCH);
733}
734
735DECLEXPORT(EGLBoolean) eglBindTexImage(EGLDisplay hDisplay, EGLSurface hSurface, EGLint cBuffer)
736{
737 NOREF(hDisplay);
738 NOREF(hSurface);
739 NOREF(cBuffer);
740 return setEGLError(EGL_BAD_MATCH);
741}
742
743DECLEXPORT(EGLBoolean) eglReleaseTexImage(EGLDisplay hDisplay, EGLSurface hSurface, EGLint cBuffer)
744{
745 NOREF(hDisplay);
746 NOREF(hSurface);
747 NOREF(cBuffer);
748 return setEGLError(EGL_BAD_MATCH);
749}
750
751DECLEXPORT(EGLBoolean) eglBindAPI(EGLenum enmApi)
752{
753 return enmApi == EGL_OPENGL_API ? clearEGLError() : setEGLError(EGL_BAD_PARAMETER);
754}
755
756DECLEXPORT(EGLenum) eglQueryAPI(void)
757{
758 return EGL_OPENGL_API;
759}
760
761DECLEXPORT(EGLContext) eglCreateContext(EGLDisplay hDisplay, EGLConfig hConfig, EGLContext hSharedContext,
762 const EGLint *paAttribs)
763{
764 Display *pDisplay = (Display *)hDisplay;
765 GLXContext hNewContext;
766
767 if (!VALID_PTR(hDisplay))
768 {
769 setEGLError(EGL_NOT_INITIALIZED);
770 return EGL_NO_CONTEXT;
771 }
772 if (paAttribs != NULL && *paAttribs != EGL_NONE)
773 {
774 setEGLError(EGL_BAD_ATTRIBUTE);
775 return EGL_NO_CONTEXT;
776 }
777 hNewContext = glXCreateNewContext(pDisplay, (GLXFBConfig)hConfig, GLX_RGBA_TYPE, (GLXContext)hSharedContext, true);
778 if (hNewContext)
779 {
780 clearEGLError();
781 return (EGLContext)hNewContext;
782 }
783 setEGLError(EGL_BAD_MATCH);
784 return EGL_NO_CONTEXT;
785}
786
787DECLEXPORT(EGLBoolean) eglDestroyContext(EGLDisplay hDisplay, EGLContext hContext)
788{
789 Display *pDisplay = (Display *)hDisplay;
790
791 if (!VALID_PTR(hDisplay))
792 return setEGLError(EGL_NOT_INITIALIZED);
793 glXDestroyContext(pDisplay, (GLXContext) hContext);
794 return clearEGLError();
795}
796
797DECLEXPORT(EGLBoolean) eglMakeCurrent(EGLDisplay hDisplay, EGLSurface hDraw, EGLSurface hRead, EGLContext hContext)
798{
799 Display *pDisplay = (Display *)hDisplay;
800 GLXDrawable hGLXDraw = hDraw == EGL_NO_SURFACE ? None : (GLXDrawable)hDraw & ~VBEGL_ANY_SURFACE;
801 GLXDrawable hGLXRead = hRead == EGL_NO_SURFACE ? None : (GLXDrawable)hRead & ~VBEGL_ANY_SURFACE;
802 GLXContext hGLXContext = hContext == EGL_NO_CONTEXT ? None : (GLXContext)hContext;
803 struct VBEGLTLS *pTls = getTls();
804
805 if (!VALID_PTR(hDisplay) || !VALID_PTR(pTls))
806 return setEGLError(EGL_NOT_INITIALIZED);
807 if (glXMakeContextCurrent(pDisplay, hGLXDraw, hGLXRead, hGLXContext))
808 {
809 pTls->hCurrent = hContext;
810 pTls->hCurrentDraw = hDraw;
811 pTls->hCurrentRead = hRead;
812 return clearEGLError();
813 }
814 else
815 return setEGLError(EGL_BAD_MATCH);
816}
817
818DECLEXPORT(EGLContext) eglGetCurrentContext(void)
819{
820 struct VBEGLTLS *pTls = getTls();
821
822 if (!VALID_PTR(pTls))
823 return EGL_NO_CONTEXT;
824 clearEGLError();
825 return pTls->hCurrent;
826}
827
828DECLEXPORT(EGLSurface) eglGetCurrentSurface(EGLint cOp)
829{
830 struct VBEGLTLS *pTls = getTls();
831
832 if (!VALID_PTR(pTls))
833 return EGL_NO_SURFACE;
834 clearEGLError();
835 switch (cOp)
836 {
837 case EGL_DRAW:
838 return pTls->hCurrentDraw;
839 case EGL_READ:
840 return pTls->hCurrentRead;
841 default:
842 setEGLError(EGL_BAD_PARAMETER);
843 return EGL_NO_SURFACE;
844 }
845}
846
847DECLEXPORT(EGLDisplay) eglGetCurrentDisplay(void)
848{
849 struct VBEGLTLS *pTls;
850
851 pTls = getTls();
852 if (!VALID_PTR(pTls))
853 return EGL_NO_DISPLAY;
854 clearEGLError();
855 return pTls->hCurrentDisplay;
856}
857
858DECLEXPORT(EGLBoolean) eglQueryContext(EGLDisplay hDisplay, EGLContext hContext, EGLint cAttribute, EGLint *pcValue)
859{
860 Display *pDisplay = (Display *)hDisplay;
861
862 if (!VALID_PTR(hDisplay))
863 return setEGLError(EGL_NOT_INITIALIZED);
864 if (!VALID_PTR(pcValue))
865 return setEGLError(EGL_BAD_PARAMETER);
866 switch (cAttribute)
867 {
868 case EGL_CONFIG_ID:
869 {
870 int cValue = 0;
871
872 if (glXQueryContext(pDisplay, (GLXContext)hContext, GLX_FBCONFIG_ID, &cValue) == Success)
873 {
874 *pcValue = cValue;
875 return clearEGLError();
876 }
877 return setEGLError(EGL_BAD_MATCH);
878 }
879 case EGL_CONTEXT_CLIENT_TYPE:
880 *pcValue = EGL_OPENGL_API;
881 return clearEGLError();
882 case EGL_CONTEXT_CLIENT_VERSION:
883 *pcValue = 0;
884 return clearEGLError();
885 case EGL_RENDER_BUFFER:
886 *pcValue = EGL_BACK_BUFFER;
887 return clearEGLError();
888 default:
889 return setEGLError(EGL_BAD_ATTRIBUTE);
890 }
891}
892
893DECLEXPORT(EGLBoolean) eglWaitClient(void)
894{
895 glXWaitGL();
896 return clearEGLError();
897}
898
899DECLEXPORT(EGLBoolean) eglWaitGL(void)
900{
901 return setEGLError(EGL_BAD_PARAMETER); /* OpenGL ES only. */
902}
903
904DECLEXPORT(EGLBoolean) eglWaitNative(EGLint cEngine)
905{
906 if (cEngine != EGL_CORE_NATIVE_ENGINE)
907 return setEGLError(EGL_BAD_PARAMETER);
908 glXWaitX();
909 return clearEGLError();
910}
911
912DECLEXPORT(EGLBoolean) eglSwapBuffers(EGLDisplay hDisplay, EGLSurface hSurface)
913{
914 Display *pDisplay = (Display *)hDisplay;
915
916 if (!VALID_PTR(hDisplay))
917 return setEGLError(EGL_NOT_INITIALIZED);
918 glXSwapBuffers(pDisplay, (GLXDrawable)hSurface & ~VBEGL_ANY_SURFACE);
919 return clearEGLError();
920}
921
922/** @todo Work out how this fits over what Chromium has to offer. */
923DECLEXPORT(EGLBoolean) eglCopyBuffers(EGLDisplay hDisplay, EGLSurface hSurface, EGLNativePixmapType hPixmap)
924{
925 Display *pDisplay = (Display *)hDisplay;
926
927 if (!VALID_PTR(pDisplay))
928 return setEGLError(EGL_NOT_INITIALIZED);
929
930 NOREF(hSurface);
931 NOREF(hPixmap);
932 return setEGLError(EGL_BAD_MATCH);
933}
934
935DECLEXPORT(EGLBoolean) eglSwapInterval (EGLDisplay dpy, EGLint interval)
936{
937 NOREF(dpy);
938 NOREF(interval);
939 return EGL_TRUE;
940}
941
942typedef void (*VBEGLFuncPtr)(void);
943DECLEXPORT(VBEGLFuncPtr)eglGetProcAddress(const char *pszName)
944{
945 clearEGLError();
946 return glXGetProcAddress((const GLubyte *)pszName);
947}
948
949DECLEXPORT(EGLBoolean) eglReleaseThread()
950{
951 struct VBEGLTLS *pTls = getTls();
952
953 if (!(pTls))
954 return EGL_TRUE;
955 free(pTls);
956 /* Can this fail with ENOMEM? */
957 pthread_setspecific(g_tls, NULL);
958 return EGL_TRUE;
959}
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use