VirtualBox

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

Revision 69500, 34.1 KB checked in by vboxsync, 2 months ago (diff)

*: scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/* $Id$ */
2
3/** @file
4 * VBox OpenGL EGL implentation.
5 */
6
7/*
8 * Copyright (C) 2009-2017 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                fSkip == true;
350        if (fSkip)
351            continue;
352        cGLXAttrib = convertEGLAttribToGLX(*pAttrib);
353        if (cGLXAttrib != None)
354        {
355            aAttribList[cAttribs] = cGLXAttrib;
356            if (pAttrib[1] == EGL_DONT_CARE)
357                aAttribList[cAttribs + 1] = GLX_DONT_CARE;
358            else
359                aAttribList[cAttribs + 1] = pAttrib[1];
360            cAttribs += 2;
361        }
362        else
363        {
364            switch (*pAttrib)
365            {
366                case EGL_COLOR_BUFFER_TYPE:
367                    aAttribList[cAttribs] = GLX_X_VISUAL_TYPE;
368                    aAttribList[cAttribs + 1] =   pAttrib[1] == EGL_DONT_CARE ? GLX_DONT_CARE
369                                                : pAttrib[1] == EGL_RGB_BUFFER ? GLX_TRUE_COLOR
370                                                : pAttrib[1] == EGL_LUMINANCE_BUFFER ? GLX_GRAY_SCALE
371                                                : GL_FALSE;
372                    if (   *pAttrib == EGL_COLOR_BUFFER_TYPE
373                        && pAttrib[1] != EGL_DONT_CARE && pAttrib[1] != EGL_RGB_BUFFER)
374                        return setEGLError(EGL_BAD_ACCESS);
375                    break;
376                case EGL_CONFIG_CAVEAT:
377                    cConfigCaveat =   pAttrib[1] == EGL_DONT_CARE ? GLX_DONT_CARE
378                                    : pAttrib[1] == EGL_NONE ? GLX_NONE
379                                    : pAttrib[1] == EGL_SLOW_CONFIG ? GLX_SLOW_CONFIG
380                                    : pAttrib[1] == EGL_NON_CONFORMANT_CONFIG ? GLX_NON_CONFORMANT_CONFIG
381                                    : GL_FALSE;
382                    if (!cConfigCaveat)
383                        return setEGLError(EGL_BAD_ATTRIBUTE);
384                    cAttribs -= 2;
385                    break;
386                case EGL_CONFORMANT:
387                    if (pAttrib[1] != EGL_OPENGL_BIT && pAttrib[1] != 0)
388                        return setEGLError(EGL_BAD_ACCESS);
389                    cConformant =   pAttrib[1] == EGL_OPENGL_BIT ? GL_TRUE : GL_FALSE;
390                    cAttribs -= 2;
391                    break;
392                case EGL_NATIVE_VISUAL_TYPE:
393                    aAttribList[cAttribs] = GLX_X_VISUAL_TYPE;
394                    aAttribList[cAttribs + 1] =   pAttrib[1] == EGL_DONT_CARE ? GLX_DONT_CARE
395                                                : pAttrib[1] == StaticGray ? GLX_STATIC_GRAY
396                                                : pAttrib[1] == StaticColor ? GLX_STATIC_COLOR
397                                                : pAttrib[1] == TrueColor ? GLX_TRUE_COLOR
398                                                : pAttrib[1] == GrayScale ? GLX_GRAY_SCALE
399                                                : pAttrib[1] == PseudoColor ? GLX_PSEUDO_COLOR
400                                                : pAttrib[1] == DirectColor ? GLX_DIRECT_COLOR
401                                                : GL_FALSE;
402                    break;
403                case EGL_RENDERABLE_TYPE:
404                    cRenderableType = pAttrib[1];
405                    cAttribs -= 2;  /* We did not add anything to the list. */
406                    break;
407                case EGL_SURFACE_TYPE:
408                    if (pAttrib[1] & ~(EGL_PBUFFER_BIT | EGL_PIXMAP_BIT | EGL_WINDOW_BIT))
409                        return setEGLError(EGL_BAD_ACCESS);
410                    aAttribList[cAttribs] = GLX_DRAWABLE_TYPE;
411                    aAttribList[cAttribs + 1] =   (pAttrib[1] & EGL_PBUFFER_BIT ? GLX_PBUFFER_BIT : 0)
412                                                | (pAttrib[1] & EGL_PIXMAP_BIT ? GLX_PIXMAP_BIT : 0)
413                                                | (pAttrib[1] & EGL_WINDOW_BIT ? GLX_WINDOW_BIT : 0);
414                    break;
415                case EGL_TRANSPARENT_TYPE:
416                    aAttribList[cAttribs] = GLX_TRANSPARENT_TYPE;
417                    aAttribList[cAttribs + 1] =   pAttrib[1] == EGL_DONT_CARE ? GLX_DONT_CARE
418                                                : pAttrib[1] == EGL_NONE ? GLX_NONE
419                                                : pAttrib[1] == EGL_TRANSPARENT_RGB ? GLX_TRANSPARENT_RGB
420                                                : GL_FALSE;
421                    break;
422                default:
423                    return setEGLError(EGL_BAD_ATTRIBUTE);
424            }
425            cAttribs += 2;
426        }
427    }
428    if (cConfigCaveat != GLX_DONT_CARE || cConformant != GLX_DONT_CARE)
429    {
430        aAttribList[cAttribs] = GLX_CONFIG_CAVEAT;
431        aAttribList[cAttribs + 1] =   cConformant == GL_FALSE ? GLX_NON_CONFORMANT_CONFIG
432                                    : cConfigCaveat == EGL_SLOW_CONFIG ? GLX_SLOW_CONFIG
433                                    : GLX_NONE;
434        cAttribs += 2;
435    }
436    aAttribList[cAttribs] = GLX_RENDER_TYPE;
437    aAttribList[cAttribs + 1] = GLX_RGBA_BIT;
438    cAttribs += 2;
439    if (paAttribs != NULL)
440    {
441        aAttribList[cAttribs] = None;
442        EGL_ASSERT(cAttribs < RT_ELEMENTS(aAttribList));
443        if (!(cRenderableType & EGL_OPENGL_BIT))
444            return setEGLError(EGL_BAD_ACCESS);
445    }
446    paFBConfigs = glXChooseFBConfig(pDisplay, DefaultScreen(pDisplay), paAttribs != NULL ? aAttribList : NULL, &caFBConfigs);
447    if (paFBConfigs == NULL)
448        return setEGLError(EGL_BAD_ACCESS);
449    *pcConfigs = caFBConfigs;
450    for (i = 0; (GLint)i < caConfigs && (GLint)i < caFBConfigs; ++i)
451        paConfigs[i] = (EGLConfig)paFBConfigs[i];
452    XFree(paFBConfigs);
453    return clearEGLError();
454}
455
456DECLEXPORT(EGLBoolean) eglGetConfigAttrib (EGLDisplay hDisplay, EGLConfig cConfig, EGLint cAttribute, EGLint *pValue)
457{
458    Display *pDisplay = (Display *)hDisplay;
459    int cGLXAttribute = convertEGLAttribToGLX(cAttribute);
460    int cValue;
461
462    if (!VALID_PTR(hDisplay))
463        return setEGLError(EGL_NOT_INITIALIZED);
464    if (!VALID_PTR(pValue))
465        return setEGLError(EGL_BAD_PARAMETER);
466    if (glXGetFBConfigAttrib(pDisplay, (GLXFBConfig)cConfig, GLX_FBCONFIG_ID, &cValue))
467        return setEGLError(EGL_BAD_CONFIG);
468    if (cGLXAttribute != None)
469    {
470        if (glXGetFBConfigAttrib(pDisplay, (GLXFBConfig)cConfig, cGLXAttribute, &cValue))
471            return setEGLError(EGL_BAD_ACCESS);
472        *pValue = cValue;
473        return clearEGLError();
474    }
475    switch (cAttribute)
476    {
477        case EGL_ALPHA_MASK_SIZE:
478            *pValue = 0;
479            return clearEGLError();
480        case EGL_LUMINANCE_SIZE:
481            if (glXGetFBConfigAttrib(pDisplay, (GLXFBConfig)cConfig, GLX_X_VISUAL_TYPE, &cValue))
482                return setEGLError(EGL_BAD_ACCESS);
483            if (cValue == GLX_STATIC_GRAY || cValue == GLX_GRAY_SCALE)
484            {
485                if (glXGetFBConfigAttrib(pDisplay, (GLXFBConfig)cConfig, GLX_RED_SIZE, &cValue))
486                    return setEGLError(EGL_BAD_ACCESS);
487                *pValue = cValue;
488            }
489            else
490                *pValue = 0;
491            return clearEGLError();
492        case EGL_COLOR_BUFFER_TYPE:
493            if (glXGetFBConfigAttrib(pDisplay, (GLXFBConfig)cConfig, GLX_X_VISUAL_TYPE, &cValue))
494                return setEGLError(EGL_BAD_ACCESS);
495            if (cValue == GLX_STATIC_GRAY || cValue == GLX_GRAY_SCALE)
496                *pValue = EGL_LUMINANCE_BUFFER;
497            else
498                *pValue = EGL_RGB_BUFFER;
499            return clearEGLError();
500        case EGL_CONFIG_CAVEAT:
501            if (glXGetFBConfigAttrib(pDisplay, (GLXFBConfig)cConfig, GLX_CONFIG_CAVEAT, &cValue))
502                return setEGLError(EGL_BAD_ACCESS);
503            *pValue = cValue == GLX_NONE ? EGL_NONE : cValue == GLX_SLOW_CONFIG ? EGL_SLOW_CONFIG : GLX_NON_CONFORMANT_CONFIG;
504            return clearEGLError();
505        case EGL_CONFORMANT:
506            if (glXGetFBConfigAttrib(pDisplay, (GLXFBConfig)cConfig, GLX_CONFIG_CAVEAT, &cValue))
507                return setEGLError(EGL_BAD_ACCESS);
508            *pValue = cValue == GLX_NON_CONFORMANT_CONFIG ? 0 : EGL_OPENGL_BIT;
509            return clearEGLError();
510        case EGL_MATCH_NATIVE_PIXMAP:
511        case EGL_MIN_SWAP_INTERVAL:
512        case EGL_MAX_SWAP_INTERVAL:
513            return setEGLError(EGL_BAD_ACCESS);
514        case EGL_NATIVE_VISUAL_TYPE:
515            if (glXGetFBConfigAttrib(pDisplay, (GLXFBConfig)cConfig, GLX_X_VISUAL_TYPE, &cValue))
516                return setEGLError(EGL_BAD_ACCESS);
517            *pValue =   cValue == GLX_STATIC_GRAY ? StaticGray
518                      : cValue == GLX_STATIC_COLOR ? StaticColor
519                      : cValue == GLX_TRUE_COLOR ? TrueColor
520                      : cValue == GLX_GRAY_SCALE ? GrayScale
521                      : cValue == GLX_PSEUDO_COLOR ? PseudoColor
522                      : cValue == GLX_DIRECT_COLOR ? DirectColor
523                      : -1;
524            return clearEGLError();
525        case EGL_RENDERABLE_TYPE:
526            *pValue = EGL_OPENGL_BIT;
527            return clearEGLError();
528        case EGL_SURFACE_TYPE:
529            if (glXGetFBConfigAttrib(pDisplay, (GLXFBConfig)cConfig, GLX_DRAWABLE_TYPE, &cValue))
530                return setEGLError(EGL_BAD_ACCESS);
531            *pValue =   (cValue & GLX_PBUFFER_BIT ? EGL_PBUFFER_BIT : 0)
532                      | (cValue & GLX_PIXMAP_BIT ? EGL_PIXMAP_BIT : 0)
533                      | (cValue & GLX_WINDOW_BIT ? EGL_WINDOW_BIT : 0);
534            return clearEGLError();
535        case EGL_TRANSPARENT_TYPE:
536            if (glXGetFBConfigAttrib(pDisplay, (GLXFBConfig)cConfig, GLX_TRANSPARENT_TYPE, &cValue))
537                return setEGLError(EGL_BAD_ACCESS);
538            *pValue =  cValue == GLX_NONE ? EGL_NONE
539                     : cValue == GLX_TRANSPARENT_RGB ? EGL_TRANSPARENT_RGB
540                     : EGL_FALSE;
541            return *pValue != EGL_FALSE ? clearEGLError() : setEGLError(EGL_BAD_ACCESS);
542        default:
543            return setEGLError(EGL_BAD_ATTRIBUTE);
544    }
545    return clearEGLError();
546}
547
548DECLEXPORT(EGLSurface) eglCreateWindowSurface(EGLDisplay hDisplay, EGLConfig config, EGLNativeWindowType hWindow,
549                                              const EGLint *paAttributes)
550{
551    Display *pDisplay = (Display *)hDisplay;
552    GLXWindow hGLXWindow;
553
554    if (!VALID_PTR(hDisplay))
555    {
556        setEGLError(EGL_NOT_INITIALIZED);
557        return EGL_NO_SURFACE;
558    }
559    if (paAttributes != NULL)  /* Sanity test only. */
560        while (*paAttributes != EGL_NONE)
561        {
562            if (*paAttributes != EGL_RENDER_BUFFER)
563            {
564                setEGLError(EGL_BAD_MATCH);
565                return EGL_NO_SURFACE;
566            }
567            paAttributes += 2;
568        }
569    hGLXWindow = glXCreateWindow(pDisplay, (GLXFBConfig)config, (Window)hWindow, NULL);
570    if (hGLXWindow == None)
571    {
572        setEGLError(EGL_BAD_ALLOC);
573        return EGL_NO_SURFACE;
574    }
575    EGL_ASSERT(hGLXWindow < VBEGL_WINDOW_SURFACE);  /* Greater than the maximum XID. */
576    clearEGLError();
577    return (EGLSurface)(hGLXWindow | VBEGL_WINDOW_SURFACE);
578}
579
580static void setAttribute(int *pcStoreIndex, int *pcCurIndex, int *paGLXAttributes, int cAttribute, int cValue)
581{
582    if (*pcStoreIndex < 0)
583    {
584        *pcStoreIndex = *pcCurIndex;
585        *pcCurIndex += 2;
586        paGLXAttributes[*pcStoreIndex] = cAttribute;
587    }
588    paGLXAttributes[*pcStoreIndex + 1] = cValue;
589}
590
591DECLEXPORT(EGLSurface) eglCreatePbufferSurface(EGLDisplay hDisplay, EGLConfig config, EGLint const *paAttributes)
592{
593    Display *pDisplay = (Display *)hDisplay;
594    enum { CPS_WIDTH = 0, CPS_HEIGHT, CPS_LARGEST, CPS_PRESERVED, CPS_TEX_FORMAT, CPS_TEX_TARGET, CPS_MIPMAP_TEX, CPS_END };
595    int acIndices[CPS_END];
596    int aAttributes[CPS_END * 2];
597    int cIndex = 0;
598    unsigned i;
599    GLXPbuffer hPbuffer;
600
601    if (!VALID_PTR(hDisplay))
602    {
603        setEGLError(EGL_NOT_INITIALIZED);
604        return EGL_NO_SURFACE;
605    }
606    for (i = 0; i < RT_ELEMENTS(acIndices); ++i)
607        acIndices[i] = -1;
608    if (paAttributes != NULL)
609        while (*paAttributes != EGL_NONE)
610        {
611            switch (*paAttributes)
612            {
613                case EGL_WIDTH:
614                    setAttribute(&acIndices[CPS_WIDTH], &cIndex, aAttributes, GLX_PBUFFER_WIDTH, paAttributes[1]);
615                    break;
616                case EGL_HEIGHT:
617                    setAttribute(&acIndices[CPS_HEIGHT], &cIndex, aAttributes, GLX_LARGEST_PBUFFER, paAttributes[1]);
618                    break;
619                case EGL_LARGEST_PBUFFER:
620                    setAttribute(&acIndices[CPS_LARGEST], &cIndex, aAttributes, GLX_PBUFFER_HEIGHT, paAttributes[1]);
621                    break;
622                case EGL_BUFFER_PRESERVED:
623                    setAttribute(&acIndices[CPS_PRESERVED], &cIndex, aAttributes, GLX_PRESERVED_CONTENTS, paAttributes[1]);
624                    break;
625                case EGL_TEXTURE_FORMAT:
626                    setAttribute(&acIndices[CPS_TEX_FORMAT], &cIndex, aAttributes, GLX_TEXTURE_FORMAT_EXT, paAttributes[1]);
627                    break;
628                case EGL_TEXTURE_TARGET:
629                    setAttribute(&acIndices[CPS_TEX_TARGET], &cIndex, aAttributes, GLX_TEXTURE_TARGET_EXT, paAttributes[1]);
630                    break;
631                case EGL_MIPMAP_TEXTURE:
632                    setAttribute(&acIndices[CPS_MIPMAP_TEX], &cIndex, aAttributes, GLX_MIPMAP_TEXTURE_EXT, paAttributes[1]);
633                    break;
634                case EGL_VG_ALPHA_FORMAT:
635                case EGL_VG_COLORSPACE:
636                {
637                    setEGLError(EGL_BAD_MATCH);
638                    return EGL_NO_SURFACE;
639                }
640            }
641            paAttributes += 2;
642        }
643    EGL_ASSERT((unsigned)cIndex < RT_ELEMENTS(aAttributes) - 1U);
644    aAttributes[cIndex + 1] = None;
645    hPbuffer = glXCreatePbuffer(pDisplay, (GLXFBConfig)config, aAttributes);
646    if (hPbuffer == None)
647    {
648        setEGLError(EGL_BAD_ALLOC);
649        return EGL_NO_SURFACE;
650    }
651    EGL_ASSERT(hPbuffer < VBEGL_WINDOW_SURFACE);  /* Greater than the maximum XID. */
652    clearEGLError();
653    return (EGLSurface)(hPbuffer | VBEGL_PBUFFER_SURFACE);
654}
655
656DECLEXPORT(EGLSurface) eglCreatePixmapSurface(EGLDisplay hDisplay, EGLConfig config, EGLNativePixmapType hPixmap,
657                                              const EGLint *paAttributes)
658{
659    Display *pDisplay = (Display *)hDisplay;
660    GLXPixmap hGLXPixmap;
661
662    if (!VALID_PTR(hDisplay))
663    {
664        setEGLError(EGL_NOT_INITIALIZED);
665        return EGL_NO_SURFACE;
666    }
667    if (paAttributes != NULL)  /* Sanity test only. */
668        if (*paAttributes != EGL_NONE)
669        {
670            if (*paAttributes == EGL_VG_COLORSPACE || *paAttributes == EGL_VG_ALPHA_FORMAT)
671            {
672                setEGLError(EGL_BAD_MATCH);
673                return EGL_NO_SURFACE;
674            }
675            else
676            {
677                setEGLError(EGL_BAD_ATTRIBUTE);
678                return EGL_NO_SURFACE;
679            }
680        }
681    hGLXPixmap = glXCreatePixmap(pDisplay, (GLXFBConfig)config, (Pixmap)hPixmap, NULL);
682    if (hGLXPixmap == None)
683    {
684        setEGLError(EGL_BAD_MATCH);
685        return EGL_NO_SURFACE;
686    }
687    EGL_ASSERT(hGLXPixmap < VBEGL_WINDOW_SURFACE);  /* Greater than the maximum XID. */
688    clearEGLError();
689    return (EGLSurface)(hGLXPixmap | VBEGL_PIXMAP_SURFACE);
690}
691
692DECLEXPORT(EGLBoolean) eglDestroySurface(EGLDisplay hDisplay, EGLSurface hSurface)
693{
694    Display *pDisplay = (Display *)hDisplay;
695
696    if (!VALID_PTR(hDisplay))
697        return setEGLError(EGL_NOT_INITIALIZED);
698    switch ((GLXDrawable)hSurface & VBEGL_ANY_SURFACE)
699    {
700        case VBEGL_WINDOW_SURFACE:
701            glXDestroyWindow(pDisplay, (GLXWindow)hSurface & ~VBEGL_WINDOW_SURFACE);
702            return clearEGLError();
703        case VBEGL_PBUFFER_SURFACE:
704            glXDestroyPbuffer(pDisplay, (GLXPbuffer)hSurface & ~VBEGL_PBUFFER_SURFACE);
705            return clearEGLError();
706        case VBEGL_PIXMAP_SURFACE:
707            glXDestroyPixmap(pDisplay, (GLXPixmap)hSurface & ~VBEGL_PIXMAP_SURFACE);
708            return clearEGLError();
709        default:
710            return setEGLError(EGL_BAD_SURFACE);
711    }
712}
713
714DECLEXPORT(EGLBoolean) eglSurfaceAttrib(EGLDisplay hDisplay, EGLSurface hSurface, EGLint cAttribute, EGLint cValue)
715{
716    NOREF(hDisplay);
717    NOREF(hSurface);
718    NOREF(cValue);
719    switch (cAttribute)
720    {
721        case EGL_MIPMAP_LEVEL:
722        case EGL_MULTISAMPLE_RESOLVE:
723        case EGL_SWAP_BEHAVIOR:
724            return setEGLError(EGL_BAD_MATCH);
725        default:
726            return setEGLError(EGL_BAD_ATTRIBUTE);
727    }
728}
729
730DECLEXPORT(EGLBoolean) eglQuerySurface(EGLDisplay hDisplay, EGLSurface hSurface, EGLint cAttribute, EGLint *cValue)
731{
732    NOREF(hDisplay);
733    NOREF(hSurface);
734    NOREF(cAttribute);
735    NOREF(cValue);
736    return setEGLError(EGL_BAD_MATCH);
737}
738
739DECLEXPORT(EGLBoolean) eglBindTexImage(EGLDisplay hDisplay, EGLSurface hSurface, EGLint cBuffer)
740{
741    NOREF(hDisplay);
742    NOREF(hSurface);
743    NOREF(cBuffer);
744    return setEGLError(EGL_BAD_MATCH);
745}
746
747DECLEXPORT(EGLBoolean) eglReleaseTexImage(EGLDisplay hDisplay, EGLSurface hSurface, EGLint cBuffer)
748{
749    NOREF(hDisplay);
750    NOREF(hSurface);
751    NOREF(cBuffer);
752    return setEGLError(EGL_BAD_MATCH);
753}
754
755DECLEXPORT(EGLBoolean) eglBindAPI(EGLenum enmApi)
756{
757    return enmApi == EGL_OPENGL_API ? clearEGLError() : setEGLError(EGL_BAD_PARAMETER);
758}
759
760DECLEXPORT(EGLenum) eglQueryAPI(void)
761{
762    return EGL_OPENGL_API;
763}
764
765DECLEXPORT(EGLContext) eglCreateContext(EGLDisplay hDisplay, EGLConfig hConfig, EGLContext hSharedContext,
766                                        const EGLint *paAttribs)
767{
768    Display *pDisplay = (Display *)hDisplay;
769    GLXContext hNewContext;
770
771    if (!VALID_PTR(hDisplay))
772    {
773        setEGLError(EGL_NOT_INITIALIZED);
774        return EGL_NO_CONTEXT;
775    }
776    if (paAttribs != NULL && *paAttribs != EGL_NONE)
777    {
778        setEGLError(EGL_BAD_ATTRIBUTE);
779        return EGL_NO_CONTEXT;
780    }
781    hNewContext = glXCreateNewContext(pDisplay, (GLXFBConfig)hConfig, GLX_RGBA_TYPE, (GLXContext)hSharedContext, true);
782    if (hNewContext)
783    {
784        clearEGLError();
785        return (EGLContext)hNewContext;
786    }
787    setEGLError(EGL_BAD_MATCH);
788    return EGL_NO_CONTEXT;
789}
790
791DECLEXPORT(EGLBoolean) eglDestroyContext(EGLDisplay hDisplay, EGLContext hContext)
792{
793    Display *pDisplay = (Display *)hDisplay;
794
795    if (!VALID_PTR(hDisplay))
796        return setEGLError(EGL_NOT_INITIALIZED);
797    glXDestroyContext(pDisplay, (GLXContext) hContext);
798    return clearEGLError();
799}
800
801DECLEXPORT(EGLBoolean) eglMakeCurrent(EGLDisplay hDisplay, EGLSurface hDraw, EGLSurface hRead, EGLContext hContext)
802{
803    Display *pDisplay = (Display *)hDisplay;
804    GLXDrawable hGLXDraw = hDraw == EGL_NO_SURFACE ? None : (GLXDrawable)hDraw & ~VBEGL_ANY_SURFACE;
805    GLXDrawable hGLXRead = hRead == EGL_NO_SURFACE ? None : (GLXDrawable)hRead & ~VBEGL_ANY_SURFACE;
806    GLXContext hGLXContext = hContext == EGL_NO_CONTEXT ? None : (GLXContext)hContext;
807    struct VBEGLTLS *pTls = getTls();
808
809    if (!VALID_PTR(hDisplay) || !VALID_PTR(pTls))
810        return setEGLError(EGL_NOT_INITIALIZED);
811    if (glXMakeContextCurrent(pDisplay, hGLXDraw, hGLXRead, hGLXContext))
812    {
813        pTls->hCurrent = hContext;
814        pTls->hCurrentDraw = hDraw;
815        pTls->hCurrentRead = hRead;
816        return clearEGLError();
817    }
818    else
819        return setEGLError(EGL_BAD_MATCH);
820}
821
822DECLEXPORT(EGLContext) eglGetCurrentContext(void)
823{
824    struct VBEGLTLS *pTls = getTls();
825
826    if (!VALID_PTR(pTls))
827        return EGL_NO_CONTEXT;
828    clearEGLError();
829    return pTls->hCurrent;
830}
831
832DECLEXPORT(EGLSurface) eglGetCurrentSurface(EGLint cOp)
833{
834    struct VBEGLTLS *pTls = getTls();
835
836    if (!VALID_PTR(pTls))
837        return EGL_NO_SURFACE;
838    clearEGLError();
839    switch (cOp)
840    {
841        case EGL_DRAW:
842            return pTls->hCurrentDraw;
843        case EGL_READ:
844            return pTls->hCurrentRead;
845        default:
846            setEGLError(EGL_BAD_PARAMETER);
847            return EGL_NO_SURFACE;
848    }
849}
850
851DECLEXPORT(EGLDisplay) eglGetCurrentDisplay(void)
852{
853    struct VBEGLTLS *pTls;
854
855    pTls = getTls();
856    if (!VALID_PTR(pTls))
857        return EGL_NO_DISPLAY;
858    clearEGLError();
859    return pTls->hCurrentDisplay;
860}
861
862DECLEXPORT(EGLBoolean) eglQueryContext(EGLDisplay hDisplay, EGLContext hContext, EGLint cAttribute, EGLint *pcValue)
863{
864    Display *pDisplay = (Display *)hDisplay;
865
866    if (!VALID_PTR(hDisplay))
867        return setEGLError(EGL_NOT_INITIALIZED);
868    if (!VALID_PTR(pcValue))
869        return setEGLError(EGL_BAD_PARAMETER);
870    switch (cAttribute)
871    {
872        case EGL_CONFIG_ID:
873        {
874            int cValue = 0;
875
876            if (glXQueryContext(pDisplay, (GLXContext)hContext, GLX_FBCONFIG_ID, &cValue) == Success)
877            {
878                *pcValue = cValue;
879                return clearEGLError();
880            }
881            return setEGLError(EGL_BAD_MATCH);
882        }
883        case EGL_CONTEXT_CLIENT_TYPE:
884            *pcValue = EGL_OPENGL_API;
885            return clearEGLError();
886        case EGL_CONTEXT_CLIENT_VERSION:
887            *pcValue = 0;
888            return clearEGLError();
889        case EGL_RENDER_BUFFER:
890            *pcValue = EGL_BACK_BUFFER;
891            return clearEGLError();
892        default:
893            return setEGLError(EGL_BAD_ATTRIBUTE);
894    }
895}
896
897DECLEXPORT(EGLBoolean) eglWaitClient(void)
898{
899    glXWaitGL();
900    return clearEGLError();
901}
902
903DECLEXPORT(EGLBoolean) eglWaitGL(void)
904{
905    return setEGLError(EGL_BAD_PARAMETER);  /* OpenGL ES only. */
906}
907
908DECLEXPORT(EGLBoolean) eglWaitNative(EGLint cEngine)
909{
910    if (cEngine != EGL_CORE_NATIVE_ENGINE)
911        return setEGLError(EGL_BAD_PARAMETER);
912    glXWaitX();
913    return clearEGLError();
914}
915
916DECLEXPORT(EGLBoolean) eglSwapBuffers(EGLDisplay hDisplay, EGLSurface hSurface)
917{
918    Display *pDisplay = (Display *)hDisplay;
919
920    if (!VALID_PTR(hDisplay))
921        return setEGLError(EGL_NOT_INITIALIZED);
922    glXSwapBuffers(pDisplay, (GLXDrawable)hSurface & ~VBEGL_ANY_SURFACE);
923    return clearEGLError();
924}
925
926/** @todo Work out how this fits over what Chromium has to offer. */
927DECLEXPORT(EGLBoolean) eglCopyBuffers(EGLDisplay hDisplay, EGLSurface hSurface, EGLNativePixmapType hPixmap)
928{
929    Display *pDisplay = (Display *)hDisplay;
930
931    if (!VALID_PTR(pDisplay))
932        return setEGLError(EGL_NOT_INITIALIZED);
933
934    NOREF(hSurface);
935    NOREF(hPixmap);
936    return setEGLError(EGL_BAD_MATCH);
937}
938
939DECLEXPORT(EGLBoolean) eglSwapInterval (EGLDisplay dpy, EGLint interval)
940{
941    NOREF(dpy);
942    NOREF(interval);
943    return EGL_TRUE;
944}
945
946typedef void (*VBEGLFuncPtr)(void);
947DECLEXPORT(VBEGLFuncPtr)eglGetProcAddress(const char *pszName)
948{
949    clearEGLError();
950    return glXGetProcAddress((const GLubyte *)pszName);
951}
952
953DECLEXPORT(EGLBoolean) eglReleaseThread()
954{
955    struct VBEGLTLS *pTls = getTls();
956
957    if (!(pTls))
958        return EGL_TRUE;
959    free(pTls);
960    /* Can this fail with ENOMEM? */
961    pthread_setspecific(g_tls, NULL);
962    return EGL_TRUE;
963}
Note: See TracBrowser for help on using the repository browser.

www.oracle.com
ContactPrivacy policyTerms of Use