VirtualBox

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

Last change on this file since 78581 was 76553, checked in by vboxsync, 6 years ago

scm --update-copyright-year

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette