VirtualBox

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

Last change on this file since 62521 was 62521, checked in by vboxsync, 8 years ago

(C) 2016

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

© 2023 Oracle
ContactPrivacy policyTerms of Use