VirtualBox

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

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

bugref:8748: Additions/Graphics/Wayland: investigate EGLStreams support feasibility: simplify GLX presence check to just check that we are using Chromium. We do not need to wrap around anything else.

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

© 2023 Oracle
ContactPrivacy policyTerms of Use