mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-04-30 23:28:06 +02:00
egl_glx: Clean up the initialization code.
Proper detection of GLX extensions. Convert fbconfigs or visuals in a more unified way and validate the resulting configs. Signed-off-by: Chia-I Wu <olvaffe@gmail.com>
This commit is contained in:
parent
326baecd75
commit
78c3a351bc
1 changed files with 383 additions and 299 deletions
|
|
@ -40,16 +40,14 @@
|
|||
*/
|
||||
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include "dlfcn.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <GL/gl.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
#include "glxclient.h"
|
||||
|
||||
#include "eglconfigutil.h"
|
||||
#include "eglconfig.h"
|
||||
#include "eglcontext.h"
|
||||
#include "egldisplay.h"
|
||||
|
|
@ -58,46 +56,19 @@
|
|||
#include "egllog.h"
|
||||
#include "eglsurface.h"
|
||||
|
||||
#include <GL/gl.h>
|
||||
|
||||
#define CALLOC_STRUCT(T) (struct T *) calloc(1, sizeof(struct T))
|
||||
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
|
||||
|
||||
static const EGLint all_apis = (EGL_OPENGL_ES_BIT
|
||||
| EGL_OPENGL_ES2_BIT
|
||||
| EGL_OPENVG_BIT
|
||||
/* | EGL_OPENGL_BIT */); /* can't do */
|
||||
#ifndef GLX_VERSION_1_4
|
||||
#error "GL/glx.h must be equal to or greater than GLX 1.4"
|
||||
#endif
|
||||
|
||||
struct visual_attribs
|
||||
{
|
||||
/* X visual attribs */
|
||||
int id;
|
||||
int klass;
|
||||
int depth;
|
||||
int redMask, greenMask, blueMask;
|
||||
int colormapSize;
|
||||
int bitsPerRGB;
|
||||
/*
|
||||
* report OpenGL ES bits because apps usually forget to specify
|
||||
* EGL_RENDERABLE_TYPE when choosing configs
|
||||
*/
|
||||
#define GLX_EGL_APIS (EGL_OPENGL_BIT | EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT)
|
||||
|
||||
/* GL visual attribs */
|
||||
int supportsGL;
|
||||
int transparentType;
|
||||
int transparentRedValue;
|
||||
int transparentGreenValue;
|
||||
int transparentBlueValue;
|
||||
int transparentAlphaValue;
|
||||
int transparentIndexValue;
|
||||
int bufferSize;
|
||||
int level;
|
||||
int render_type;
|
||||
int doubleBuffer;
|
||||
int stereo;
|
||||
int auxBuffers;
|
||||
int redSize, greenSize, blueSize, alphaSize;
|
||||
int depthSize;
|
||||
int stencilSize;
|
||||
int accumRedSize, accumGreenSize, accumBlueSize, accumAlphaSize;
|
||||
int numSamples, numMultisample;
|
||||
int visualCaveat;
|
||||
};
|
||||
|
||||
/** subclass of _EGLDriver */
|
||||
struct GLX_egl_driver
|
||||
|
|
@ -114,6 +85,21 @@ struct GLX_egl_display
|
|||
GLXFBConfig *fbconfigs;
|
||||
|
||||
int glx_maj, glx_min;
|
||||
|
||||
const char *extensions;
|
||||
EGLBoolean have_1_3;
|
||||
EGLBoolean have_make_current_read;
|
||||
EGLBoolean have_fbconfig;
|
||||
EGLBoolean have_pbuffer;
|
||||
|
||||
/* GLX_SGIX_pbuffer */
|
||||
PFNGLXCREATEGLXPBUFFERSGIXPROC glXCreateGLXPbufferSGIX;
|
||||
PFNGLXDESTROYGLXPBUFFERSGIXPROC glXDestroyGLXPbufferSGIX;
|
||||
|
||||
/* workaround quirks of different GLX implementations */
|
||||
EGLBoolean single_buffered_quirk;
|
||||
EGLBoolean glx_window_quirk;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -139,6 +125,7 @@ struct GLX_egl_surface
|
|||
struct GLX_egl_config
|
||||
{
|
||||
_EGLConfig Base; /**< base class */
|
||||
EGLBoolean double_buffered;
|
||||
int index;
|
||||
};
|
||||
|
||||
|
|
@ -173,288 +160,369 @@ GLX_egl_config_index(_EGLConfig *conf)
|
|||
return ((struct GLX_egl_config *) conf)->index;
|
||||
}
|
||||
|
||||
static GLboolean
|
||||
get_visual_attribs(Display *dpy, XVisualInfo *vInfo,
|
||||
struct visual_attribs *attribs)
|
||||
{
|
||||
const char *ext = glXQueryExtensionsString(dpy, vInfo->screen);
|
||||
int rgba;
|
||||
|
||||
memset(attribs, 0, sizeof(struct visual_attribs));
|
||||
#define MAP_ATTRIB(attr, memb) \
|
||||
{ attr, offsetof(__GLcontextModes, memb) }
|
||||
|
||||
attribs->id = vInfo->visualid;
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
attribs->klass = vInfo->c_class;
|
||||
#else
|
||||
attribs->klass = vInfo->class;
|
||||
#endif
|
||||
attribs->depth = vInfo->depth;
|
||||
attribs->redMask = vInfo->red_mask;
|
||||
attribs->greenMask = vInfo->green_mask;
|
||||
attribs->blueMask = vInfo->blue_mask;
|
||||
attribs->colormapSize = vInfo->colormap_size;
|
||||
attribs->bitsPerRGB = vInfo->bits_per_rgb;
|
||||
|
||||
if (glXGetConfig(dpy, vInfo, GLX_USE_GL, &attribs->supportsGL) != 0 ||
|
||||
!attribs->supportsGL)
|
||||
return GL_FALSE;
|
||||
glXGetConfig(dpy, vInfo, GLX_BUFFER_SIZE, &attribs->bufferSize);
|
||||
glXGetConfig(dpy, vInfo, GLX_LEVEL, &attribs->level);
|
||||
glXGetConfig(dpy, vInfo, GLX_RGBA, &rgba);
|
||||
if (!rgba)
|
||||
return GL_FALSE;
|
||||
attribs->render_type = GLX_RGBA_BIT;
|
||||
|
||||
glXGetConfig(dpy, vInfo, GLX_DOUBLEBUFFER, &attribs->doubleBuffer);
|
||||
if (!attribs->doubleBuffer)
|
||||
return GL_FALSE;
|
||||
static const struct {
|
||||
int attr;
|
||||
int offset;
|
||||
} fbconfig_attributes[] = {
|
||||
/* table 3.1 of GLX 1.4 */
|
||||
MAP_ATTRIB(GLX_FBCONFIG_ID, fbconfigID),
|
||||
MAP_ATTRIB(GLX_BUFFER_SIZE, rgbBits),
|
||||
MAP_ATTRIB(GLX_LEVEL, level),
|
||||
MAP_ATTRIB(GLX_DOUBLEBUFFER, doubleBufferMode),
|
||||
MAP_ATTRIB(GLX_STEREO, stereoMode),
|
||||
MAP_ATTRIB(GLX_AUX_BUFFERS, numAuxBuffers),
|
||||
MAP_ATTRIB(GLX_RED_SIZE, redBits),
|
||||
MAP_ATTRIB(GLX_GREEN_SIZE, greenBits),
|
||||
MAP_ATTRIB(GLX_BLUE_SIZE, blueBits),
|
||||
MAP_ATTRIB(GLX_ALPHA_SIZE, alphaBits),
|
||||
MAP_ATTRIB(GLX_DEPTH_SIZE, depthBits),
|
||||
MAP_ATTRIB(GLX_STENCIL_SIZE, stencilBits),
|
||||
MAP_ATTRIB(GLX_ACCUM_RED_SIZE, accumRedBits),
|
||||
MAP_ATTRIB(GLX_ACCUM_GREEN_SIZE, accumGreenBits),
|
||||
MAP_ATTRIB(GLX_ACCUM_BLUE_SIZE, accumBlueBits),
|
||||
MAP_ATTRIB(GLX_ACCUM_ALPHA_SIZE, accumAlphaBits),
|
||||
MAP_ATTRIB(GLX_SAMPLE_BUFFERS, sampleBuffers),
|
||||
MAP_ATTRIB(GLX_SAMPLES, samples),
|
||||
MAP_ATTRIB(GLX_RENDER_TYPE, renderType),
|
||||
MAP_ATTRIB(GLX_DRAWABLE_TYPE, drawableType),
|
||||
MAP_ATTRIB(GLX_X_RENDERABLE, xRenderable),
|
||||
MAP_ATTRIB(GLX_X_VISUAL_TYPE, visualType),
|
||||
MAP_ATTRIB(GLX_CONFIG_CAVEAT, visualRating),
|
||||
MAP_ATTRIB(GLX_TRANSPARENT_TYPE, transparentPixel),
|
||||
MAP_ATTRIB(GLX_TRANSPARENT_INDEX_VALUE, transparentIndex),
|
||||
MAP_ATTRIB(GLX_TRANSPARENT_RED_VALUE, transparentRed),
|
||||
MAP_ATTRIB(GLX_TRANSPARENT_GREEN_VALUE, transparentGreen),
|
||||
MAP_ATTRIB(GLX_TRANSPARENT_BLUE_VALUE, transparentBlue),
|
||||
MAP_ATTRIB(GLX_TRANSPARENT_ALPHA_VALUE, transparentAlpha),
|
||||
MAP_ATTRIB(GLX_MAX_PBUFFER_WIDTH, maxPbufferWidth),
|
||||
MAP_ATTRIB(GLX_MAX_PBUFFER_HEIGHT, maxPbufferHeight),
|
||||
MAP_ATTRIB(GLX_MAX_PBUFFER_PIXELS, maxPbufferPixels),
|
||||
MAP_ATTRIB(GLX_VISUAL_ID, visualID),
|
||||
};
|
||||
|
||||
glXGetConfig(dpy, vInfo, GLX_STEREO, &attribs->stereo);
|
||||
glXGetConfig(dpy, vInfo, GLX_AUX_BUFFERS, &attribs->auxBuffers);
|
||||
glXGetConfig(dpy, vInfo, GLX_RED_SIZE, &attribs->redSize);
|
||||
glXGetConfig(dpy, vInfo, GLX_GREEN_SIZE, &attribs->greenSize);
|
||||
glXGetConfig(dpy, vInfo, GLX_BLUE_SIZE, &attribs->blueSize);
|
||||
glXGetConfig(dpy, vInfo, GLX_ALPHA_SIZE, &attribs->alphaSize);
|
||||
glXGetConfig(dpy, vInfo, GLX_DEPTH_SIZE, &attribs->depthSize);
|
||||
glXGetConfig(dpy, vInfo, GLX_STENCIL_SIZE, &attribs->stencilSize);
|
||||
glXGetConfig(dpy, vInfo, GLX_ACCUM_RED_SIZE, &attribs->accumRedSize);
|
||||
glXGetConfig(dpy, vInfo, GLX_ACCUM_GREEN_SIZE, &attribs->accumGreenSize);
|
||||
glXGetConfig(dpy, vInfo, GLX_ACCUM_BLUE_SIZE, &attribs->accumBlueSize);
|
||||
glXGetConfig(dpy, vInfo, GLX_ACCUM_ALPHA_SIZE, &attribs->accumAlphaSize);
|
||||
|
||||
/* get transparent pixel stuff */
|
||||
glXGetConfig(dpy, vInfo,GLX_TRANSPARENT_TYPE, &attribs->transparentType);
|
||||
if (attribs->transparentType == GLX_TRANSPARENT_RGB) {
|
||||
glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_RED_VALUE, &attribs->transparentRedValue);
|
||||
glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_GREEN_VALUE, &attribs->transparentGreenValue);
|
||||
glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_BLUE_VALUE, &attribs->transparentBlueValue);
|
||||
glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_ALPHA_VALUE, &attribs->transparentAlphaValue);
|
||||
}
|
||||
else if (attribs->transparentType == GLX_TRANSPARENT_INDEX) {
|
||||
glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_INDEX_VALUE, &attribs->transparentIndexValue);
|
||||
}
|
||||
|
||||
/* multisample attribs */
|
||||
#ifdef GLX_ARB_multisample
|
||||
if (ext && strstr(ext, "GLX_ARB_multisample")) {
|
||||
glXGetConfig(dpy, vInfo, GLX_SAMPLE_BUFFERS_ARB, &attribs->numMultisample);
|
||||
glXGetConfig(dpy, vInfo, GLX_SAMPLES_ARB, &attribs->numSamples);
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
attribs->numSamples = 0;
|
||||
attribs->numMultisample = 0;
|
||||
}
|
||||
|
||||
#if defined(GLX_EXT_visual_rating)
|
||||
if (ext && strstr(ext, "GLX_EXT_visual_rating")) {
|
||||
glXGetConfig(dpy, vInfo, GLX_VISUAL_CAVEAT_EXT, &attribs->visualCaveat);
|
||||
}
|
||||
else {
|
||||
attribs->visualCaveat = GLX_NONE_EXT;
|
||||
}
|
||||
#else
|
||||
attribs->visualCaveat = 0;
|
||||
#endif
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
#ifdef GLX_VERSION_1_3
|
||||
|
||||
static int
|
||||
glx_token_to_visual_class(int visual_type)
|
||||
{
|
||||
switch (visual_type) {
|
||||
case GLX_TRUE_COLOR:
|
||||
return TrueColor;
|
||||
case GLX_DIRECT_COLOR:
|
||||
return DirectColor;
|
||||
case GLX_PSEUDO_COLOR:
|
||||
return PseudoColor;
|
||||
case GLX_STATIC_COLOR:
|
||||
return StaticColor;
|
||||
case GLX_GRAY_SCALE:
|
||||
return GrayScale;
|
||||
case GLX_STATIC_GRAY:
|
||||
return StaticGray;
|
||||
case GLX_NONE:
|
||||
default:
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
get_fbconfig_attribs(Display *dpy, GLXFBConfig fbconfig,
|
||||
struct visual_attribs *attribs)
|
||||
{
|
||||
int visual_type;
|
||||
int fbconfig_id;
|
||||
|
||||
memset(attribs, 0, sizeof(struct visual_attribs));
|
||||
|
||||
glXGetFBConfigAttrib(dpy, fbconfig, GLX_FBCONFIG_ID, &fbconfig_id);
|
||||
|
||||
glXGetFBConfigAttrib(dpy, fbconfig, GLX_VISUAL_ID, &attribs->id);
|
||||
|
||||
#if 0
|
||||
attribs->depth = vInfo->depth;
|
||||
attribs->redMask = vInfo->red_mask;
|
||||
attribs->greenMask = vInfo->green_mask;
|
||||
attribs->blueMask = vInfo->blue_mask;
|
||||
attribs->colormapSize = vInfo->colormap_size;
|
||||
attribs->bitsPerRGB = vInfo->bits_per_rgb;
|
||||
#endif
|
||||
|
||||
glXGetFBConfigAttrib(dpy, fbconfig, GLX_X_VISUAL_TYPE, &visual_type);
|
||||
attribs->klass = glx_token_to_visual_class(visual_type);
|
||||
|
||||
glXGetFBConfigAttrib(dpy, fbconfig, GLX_BUFFER_SIZE, &attribs->bufferSize);
|
||||
glXGetFBConfigAttrib(dpy, fbconfig, GLX_LEVEL, &attribs->level);
|
||||
glXGetFBConfigAttrib(dpy, fbconfig, GLX_RENDER_TYPE, &attribs->render_type);
|
||||
if (!(attribs->render_type & GLX_RGBA_BIT))
|
||||
return 0;
|
||||
|
||||
glXGetFBConfigAttrib(dpy, fbconfig, GLX_DOUBLEBUFFER, &attribs->doubleBuffer);
|
||||
if (!attribs->doubleBuffer)
|
||||
return 0;
|
||||
|
||||
glXGetFBConfigAttrib(dpy, fbconfig, GLX_STEREO, &attribs->stereo);
|
||||
glXGetFBConfigAttrib(dpy, fbconfig, GLX_AUX_BUFFERS, &attribs->auxBuffers);
|
||||
|
||||
glXGetFBConfigAttrib(dpy, fbconfig, GLX_RED_SIZE, &attribs->redSize);
|
||||
glXGetFBConfigAttrib(dpy, fbconfig, GLX_GREEN_SIZE, &attribs->greenSize);
|
||||
glXGetFBConfigAttrib(dpy, fbconfig, GLX_BLUE_SIZE, &attribs->blueSize);
|
||||
glXGetFBConfigAttrib(dpy, fbconfig, GLX_ALPHA_SIZE, &attribs->alphaSize);
|
||||
glXGetFBConfigAttrib(dpy, fbconfig, GLX_DEPTH_SIZE, &attribs->depthSize);
|
||||
glXGetFBConfigAttrib(dpy, fbconfig, GLX_STENCIL_SIZE, &attribs->stencilSize);
|
||||
|
||||
glXGetFBConfigAttrib(dpy, fbconfig, GLX_ACCUM_RED_SIZE, &attribs->accumRedSize);
|
||||
glXGetFBConfigAttrib(dpy, fbconfig, GLX_ACCUM_GREEN_SIZE, &attribs->accumGreenSize);
|
||||
glXGetFBConfigAttrib(dpy, fbconfig, GLX_ACCUM_BLUE_SIZE, &attribs->accumBlueSize);
|
||||
glXGetFBConfigAttrib(dpy, fbconfig, GLX_ACCUM_ALPHA_SIZE, &attribs->accumAlphaSize);
|
||||
|
||||
/* get transparent pixel stuff */
|
||||
glXGetFBConfigAttrib(dpy, fbconfig,GLX_TRANSPARENT_TYPE, &attribs->transparentType);
|
||||
if (attribs->transparentType == GLX_TRANSPARENT_RGB) {
|
||||
glXGetFBConfigAttrib(dpy, fbconfig, GLX_TRANSPARENT_RED_VALUE, &attribs->transparentRedValue);
|
||||
glXGetFBConfigAttrib(dpy, fbconfig, GLX_TRANSPARENT_GREEN_VALUE, &attribs->transparentGreenValue);
|
||||
glXGetFBConfigAttrib(dpy, fbconfig, GLX_TRANSPARENT_BLUE_VALUE, &attribs->transparentBlueValue);
|
||||
glXGetFBConfigAttrib(dpy, fbconfig, GLX_TRANSPARENT_ALPHA_VALUE, &attribs->transparentAlphaValue);
|
||||
}
|
||||
else if (attribs->transparentType == GLX_TRANSPARENT_INDEX) {
|
||||
glXGetFBConfigAttrib(dpy, fbconfig, GLX_TRANSPARENT_INDEX_VALUE, &attribs->transparentIndexValue);
|
||||
}
|
||||
|
||||
glXGetFBConfigAttrib(dpy, fbconfig, GLX_SAMPLE_BUFFERS, &attribs->numMultisample);
|
||||
glXGetFBConfigAttrib(dpy, fbconfig, GLX_SAMPLES, &attribs->numSamples);
|
||||
|
||||
glXGetFBConfigAttrib(dpy, fbconfig, GLX_CONFIG_CAVEAT, &attribs->visualCaveat);
|
||||
|
||||
if (attribs->id == 0) {
|
||||
attribs->id = fbconfig_id;
|
||||
return EGL_PBUFFER_BIT | EGL_PIXMAP_BIT;
|
||||
}
|
||||
|
||||
return EGL_WINDOW_BIT;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static EGLBoolean
|
||||
create_configs(_EGLDisplay *disp, struct GLX_egl_display *GLX_dpy)
|
||||
convert_fbconfig(Display *dpy, GLXFBConfig fbconfig,
|
||||
struct GLX_egl_config *GLX_conf)
|
||||
{
|
||||
XVisualInfo theTemplate;
|
||||
int numVisuals;
|
||||
long mask;
|
||||
int i;
|
||||
struct visual_attribs attribs;
|
||||
__GLcontextModes mode;
|
||||
int err = 0, attr, val, i;
|
||||
|
||||
GLX_dpy->fbconfigs = NULL;
|
||||
memset(&mode, 0, sizeof(mode));
|
||||
|
||||
#ifdef GLX_VERSION_1_3
|
||||
/* get list of all fbconfigs on this screen */
|
||||
GLX_dpy->fbconfigs = glXGetFBConfigs(GLX_dpy->dpy, DefaultScreen(GLX_dpy->dpy), &numVisuals);
|
||||
for (i = 0; i < ARRAY_SIZE(fbconfig_attributes); i++) {
|
||||
int offset = fbconfig_attributes[i].offset;
|
||||
attr = fbconfig_attributes[i].attr;
|
||||
err = glXGetFBConfigAttrib(dpy, fbconfig, attr, &val);
|
||||
if (err) {
|
||||
if (err == GLX_BAD_ATTRIBUTE) {
|
||||
err = 0;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
*((int *) ((char *) &mode + offset)) = val;
|
||||
}
|
||||
if (err)
|
||||
return EGL_FALSE;
|
||||
|
||||
if (numVisuals == 0) {
|
||||
GLX_dpy->fbconfigs = NULL;
|
||||
goto xvisual;
|
||||
/* must have rgba bit */
|
||||
if (!(mode.renderType & GLX_RGBA_BIT))
|
||||
return EGL_FALSE;
|
||||
|
||||
/* pixmap and pbuffer surfaces must be single-buffered in EGL */
|
||||
if (mode.doubleBufferMode) {
|
||||
mode.drawableType &= ~(GLX_PIXMAP_BIT | GLX_PBUFFER_BIT);
|
||||
if (!mode.drawableType)
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
for (i = 0; i < numVisuals; i++) {
|
||||
struct GLX_egl_config *config;
|
||||
int bit;
|
||||
mode.rgbMode = GL_TRUE;
|
||||
mode.haveAccumBuffer = (mode.accumRedBits +
|
||||
mode.accumGreenBits +
|
||||
mode.accumBlueBits +
|
||||
mode.accumAlphaBits > 0);
|
||||
mode.haveDepthBuffer = (mode.depthBits > 0);
|
||||
mode.haveStencilBuffer = (mode.stencilBits > 0);
|
||||
|
||||
bit = get_fbconfig_attribs(GLX_dpy->dpy, GLX_dpy->fbconfigs[i], &attribs);
|
||||
if (!bit)
|
||||
continue;
|
||||
GLX_conf->double_buffered = (mode.doubleBufferMode != 0);
|
||||
return _eglConfigFromContextModesRec(&GLX_conf->Base, &mode,
|
||||
GLX_EGL_APIS, GLX_EGL_APIS);
|
||||
}
|
||||
|
||||
config = CALLOC_STRUCT(GLX_egl_config);
|
||||
|
||||
config->index = i;
|
||||
_eglInitConfig(&config->Base, (i+1));
|
||||
SET_CONFIG_ATTRIB(&config->Base, EGL_NATIVE_VISUAL_ID, attribs.id);
|
||||
SET_CONFIG_ATTRIB(&config->Base, EGL_BUFFER_SIZE, attribs.bufferSize);
|
||||
SET_CONFIG_ATTRIB(&config->Base, EGL_RED_SIZE, attribs.redSize);
|
||||
SET_CONFIG_ATTRIB(&config->Base, EGL_GREEN_SIZE, attribs.greenSize);
|
||||
SET_CONFIG_ATTRIB(&config->Base, EGL_BLUE_SIZE, attribs.blueSize);
|
||||
SET_CONFIG_ATTRIB(&config->Base, EGL_ALPHA_SIZE, attribs.alphaSize);
|
||||
SET_CONFIG_ATTRIB(&config->Base, EGL_DEPTH_SIZE, attribs.depthSize);
|
||||
SET_CONFIG_ATTRIB(&config->Base, EGL_STENCIL_SIZE, attribs.stencilSize);
|
||||
SET_CONFIG_ATTRIB(&config->Base, EGL_SAMPLES, attribs.numSamples);
|
||||
SET_CONFIG_ATTRIB(&config->Base, EGL_SAMPLE_BUFFERS, attribs.numMultisample);
|
||||
SET_CONFIG_ATTRIB(&config->Base, EGL_CONFORMANT, all_apis);
|
||||
SET_CONFIG_ATTRIB(&config->Base, EGL_RENDERABLE_TYPE, all_apis);
|
||||
SET_CONFIG_ATTRIB(&config->Base, EGL_SURFACE_TYPE, bit);
|
||||
static const struct {
|
||||
int attr;
|
||||
int offset;
|
||||
} visual_attributes[] = {
|
||||
/* table 3.7 of GLX 1.4 */
|
||||
/* no GLX_USE_GL */
|
||||
MAP_ATTRIB(GLX_BUFFER_SIZE, rgbBits),
|
||||
MAP_ATTRIB(GLX_LEVEL, level),
|
||||
MAP_ATTRIB(GLX_RGBA, rgbMode),
|
||||
MAP_ATTRIB(GLX_DOUBLEBUFFER, doubleBufferMode),
|
||||
MAP_ATTRIB(GLX_STEREO, stereoMode),
|
||||
MAP_ATTRIB(GLX_AUX_BUFFERS, numAuxBuffers),
|
||||
MAP_ATTRIB(GLX_RED_SIZE, redBits),
|
||||
MAP_ATTRIB(GLX_GREEN_SIZE, greenBits),
|
||||
MAP_ATTRIB(GLX_BLUE_SIZE, blueBits),
|
||||
MAP_ATTRIB(GLX_ALPHA_SIZE, alphaBits),
|
||||
MAP_ATTRIB(GLX_DEPTH_SIZE, depthBits),
|
||||
MAP_ATTRIB(GLX_STENCIL_SIZE, stencilBits),
|
||||
MAP_ATTRIB(GLX_ACCUM_RED_SIZE, accumRedBits),
|
||||
MAP_ATTRIB(GLX_ACCUM_GREEN_SIZE, accumGreenBits),
|
||||
MAP_ATTRIB(GLX_ACCUM_BLUE_SIZE, accumBlueBits),
|
||||
MAP_ATTRIB(GLX_ACCUM_ALPHA_SIZE, accumAlphaBits),
|
||||
MAP_ATTRIB(GLX_SAMPLE_BUFFERS, sampleBuffers),
|
||||
MAP_ATTRIB(GLX_SAMPLES, samples),
|
||||
MAP_ATTRIB(GLX_FBCONFIG_ID, fbconfigID),
|
||||
/* GLX_EXT_visual_rating */
|
||||
MAP_ATTRIB(GLX_VISUAL_CAVEAT_EXT, visualRating),
|
||||
};
|
||||
|
||||
/* XXX possibly other things to init... */
|
||||
|
||||
_eglAddConfig(disp, &config->Base);
|
||||
}
|
||||
static int
|
||||
get_visual_type(const XVisualInfo *vis)
|
||||
{
|
||||
int klass;
|
||||
|
||||
goto end;
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
klass = vis->c_class;
|
||||
#else
|
||||
klass = vis->class;
|
||||
#endif
|
||||
|
||||
xvisual:
|
||||
/* get list of all visuals on this screen */
|
||||
theTemplate.screen = DefaultScreen(GLX_dpy->dpy);
|
||||
mask = VisualScreenMask;
|
||||
GLX_dpy->visuals = XGetVisualInfo(GLX_dpy->dpy, mask, &theTemplate, &numVisuals);
|
||||
switch (klass) {
|
||||
case TrueColor:
|
||||
return GLX_TRUE_COLOR;
|
||||
case DirectColor:
|
||||
return GLX_DIRECT_COLOR;
|
||||
case PseudoColor:
|
||||
return GLX_PSEUDO_COLOR;
|
||||
case StaticColor:
|
||||
return GLX_STATIC_COLOR;
|
||||
case GrayScale:
|
||||
return GLX_GRAY_SCALE;
|
||||
case StaticGray:
|
||||
return GLX_STATIC_GRAY;
|
||||
default:
|
||||
return GLX_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < numVisuals; i++) {
|
||||
struct GLX_egl_config *config;
|
||||
|
||||
if (!get_visual_attribs(GLX_dpy->dpy, &GLX_dpy->visuals[i], &attribs))
|
||||
continue;
|
||||
static EGLBoolean
|
||||
convert_visual(Display *dpy, XVisualInfo *vinfo,
|
||||
struct GLX_egl_config *GLX_conf)
|
||||
{
|
||||
__GLcontextModes mode;
|
||||
int err, attr, val, i;
|
||||
|
||||
config = CALLOC_STRUCT(GLX_egl_config);
|
||||
/* the visual must support OpenGL */
|
||||
err = glXGetConfig(dpy, vinfo, GLX_USE_GL, &val);
|
||||
if (err || !val)
|
||||
return EGL_FALSE;
|
||||
|
||||
config->index = i;
|
||||
_eglInitConfig(&config->Base, (i+1));
|
||||
SET_CONFIG_ATTRIB(&config->Base, EGL_NATIVE_VISUAL_ID, attribs.id);
|
||||
SET_CONFIG_ATTRIB(&config->Base, EGL_BUFFER_SIZE, attribs.bufferSize);
|
||||
SET_CONFIG_ATTRIB(&config->Base, EGL_RED_SIZE, attribs.redSize);
|
||||
SET_CONFIG_ATTRIB(&config->Base, EGL_GREEN_SIZE, attribs.greenSize);
|
||||
SET_CONFIG_ATTRIB(&config->Base, EGL_BLUE_SIZE, attribs.blueSize);
|
||||
SET_CONFIG_ATTRIB(&config->Base, EGL_ALPHA_SIZE, attribs.alphaSize);
|
||||
SET_CONFIG_ATTRIB(&config->Base, EGL_DEPTH_SIZE, attribs.depthSize);
|
||||
SET_CONFIG_ATTRIB(&config->Base, EGL_STENCIL_SIZE, attribs.stencilSize);
|
||||
SET_CONFIG_ATTRIB(&config->Base, EGL_SAMPLES, attribs.numSamples);
|
||||
SET_CONFIG_ATTRIB(&config->Base, EGL_SAMPLE_BUFFERS, attribs.numMultisample);
|
||||
SET_CONFIG_ATTRIB(&config->Base, EGL_CONFORMANT, all_apis);
|
||||
SET_CONFIG_ATTRIB(&config->Base, EGL_RENDERABLE_TYPE, all_apis);
|
||||
SET_CONFIG_ATTRIB(&config->Base, EGL_SURFACE_TYPE,
|
||||
(EGL_WINDOW_BIT /*| EGL_PBUFFER_BIT | EGL_PIXMAP_BIT*/));
|
||||
memset(&mode, 0, sizeof(mode));
|
||||
|
||||
/* XXX possibly other things to init... */
|
||||
for (i = 0; i < ARRAY_SIZE(visual_attributes); i++) {
|
||||
int offset = visual_attributes[i].offset;
|
||||
attr = visual_attributes[i].attr;
|
||||
err = glXGetConfig(dpy, vinfo, attr, &val);
|
||||
if (err) {
|
||||
if (err == GLX_BAD_ATTRIBUTE) {
|
||||
err = 0;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
*((int *) ((char *) &mode + offset)) = val;
|
||||
}
|
||||
if (err)
|
||||
return EGL_FALSE;
|
||||
|
||||
_eglAddConfig(disp, &config->Base);
|
||||
/* must be RGB mode */
|
||||
if (!mode.rgbMode)
|
||||
return EGL_FALSE;
|
||||
|
||||
mode.visualID = vinfo->visualid;
|
||||
mode.visualType = get_visual_type(vinfo);
|
||||
mode.redMask = vinfo->red_mask;
|
||||
mode.greenMask = vinfo->green_mask;
|
||||
mode.blueMask = vinfo->blue_mask;
|
||||
|
||||
mode.drawableType = GLX_WINDOW_BIT;
|
||||
/* pixmap surfaces must be single-buffered in EGL */
|
||||
if (!mode.doubleBufferMode)
|
||||
mode.drawableType |= GLX_PIXMAP_BIT;
|
||||
|
||||
mode.renderType = GLX_RGBA_BIT;
|
||||
mode.xRenderable = GL_TRUE;
|
||||
mode.haveAccumBuffer = (mode.accumRedBits +
|
||||
mode.accumGreenBits +
|
||||
mode.accumBlueBits +
|
||||
mode.accumAlphaBits > 0);
|
||||
mode.haveDepthBuffer = (mode.depthBits > 0);
|
||||
mode.haveStencilBuffer = (mode.stencilBits > 0);
|
||||
|
||||
GLX_conf->double_buffered = (mode.doubleBufferMode != 0);
|
||||
return _eglConfigFromContextModesRec(&GLX_conf->Base, &mode,
|
||||
GLX_EGL_APIS, GLX_EGL_APIS);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
fix_config(struct GLX_egl_display *GLX_dpy, struct GLX_egl_config *GLX_conf)
|
||||
{
|
||||
_EGLConfig *conf = &GLX_conf->Base;
|
||||
EGLint surface_type, r, g, b, a;
|
||||
|
||||
surface_type = GET_CONFIG_ATTRIB(conf, EGL_SURFACE_TYPE);
|
||||
if (!GLX_conf->double_buffered && GLX_dpy->single_buffered_quirk) {
|
||||
/* some GLX impls do not like single-buffered window surface */
|
||||
surface_type &= ~EGL_WINDOW_BIT;
|
||||
/* pbuffer bit is usually not set */
|
||||
if (GLX_dpy->have_pbuffer)
|
||||
surface_type |= EGL_PBUFFER_BIT;
|
||||
SET_CONFIG_ATTRIB(conf, EGL_SURFACE_TYPE, surface_type);
|
||||
}
|
||||
|
||||
/* no visual attribs unless window bit is set */
|
||||
if (!(surface_type & EGL_WINDOW_BIT)) {
|
||||
SET_CONFIG_ATTRIB(conf, EGL_NATIVE_VISUAL_ID, 0);
|
||||
SET_CONFIG_ATTRIB(conf, EGL_NATIVE_VISUAL_TYPE, EGL_NONE);
|
||||
}
|
||||
|
||||
/* make sure buffer size is set correctly */
|
||||
r = GET_CONFIG_ATTRIB(conf, EGL_RED_SIZE);
|
||||
g = GET_CONFIG_ATTRIB(conf, EGL_GREEN_SIZE);
|
||||
b = GET_CONFIG_ATTRIB(conf, EGL_BLUE_SIZE);
|
||||
a = GET_CONFIG_ATTRIB(conf, EGL_ALPHA_SIZE);
|
||||
SET_CONFIG_ATTRIB(conf, EGL_BUFFER_SIZE, r + g + b + a);
|
||||
}
|
||||
|
||||
|
||||
static EGLBoolean
|
||||
create_configs(_EGLDisplay *dpy, struct GLX_egl_display *GLX_dpy,
|
||||
EGLint screen)
|
||||
{
|
||||
EGLint num_configs = 0, i;
|
||||
EGLint id = 1;
|
||||
|
||||
if (GLX_dpy->have_fbconfig) {
|
||||
GLX_dpy->fbconfigs = glXGetFBConfigs(GLX_dpy->dpy, screen, &num_configs);
|
||||
}
|
||||
else {
|
||||
XVisualInfo vinfo_template;
|
||||
long mask;
|
||||
|
||||
vinfo_template.screen = screen;
|
||||
mask = VisualScreenMask;
|
||||
GLX_dpy->visuals = XGetVisualInfo(GLX_dpy->dpy, mask, &vinfo_template,
|
||||
&num_configs);
|
||||
}
|
||||
|
||||
if (!num_configs)
|
||||
return EGL_FALSE;
|
||||
|
||||
for (i = 0; i < num_configs; i++) {
|
||||
struct GLX_egl_config *GLX_conf, template;
|
||||
EGLBoolean ok;
|
||||
|
||||
memset(&template, 0, sizeof(template));
|
||||
_eglInitConfig(&template.Base, id);
|
||||
if (GLX_dpy->have_fbconfig)
|
||||
ok = convert_fbconfig(GLX_dpy->dpy, GLX_dpy->fbconfigs[i], &template);
|
||||
else
|
||||
ok = convert_visual(GLX_dpy->dpy, &GLX_dpy->visuals[i], &template);
|
||||
if (!ok)
|
||||
continue;
|
||||
|
||||
fix_config(GLX_dpy, &template);
|
||||
if (!_eglValidateConfig(&template.Base, EGL_FALSE)) {
|
||||
_eglLog(_EGL_DEBUG, "GLX: failed to validate config %d", i);
|
||||
continue;
|
||||
}
|
||||
|
||||
GLX_conf = CALLOC_STRUCT(GLX_egl_config);
|
||||
if (GLX_conf) {
|
||||
memcpy(GLX_conf, &template, sizeof(template));
|
||||
GLX_conf->index = i;
|
||||
|
||||
_eglAddConfig(dpy, &GLX_conf->Base);
|
||||
id++;
|
||||
}
|
||||
}
|
||||
|
||||
end:
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
check_extensions(struct GLX_egl_display *GLX_dpy, EGLint screen)
|
||||
{
|
||||
GLX_dpy->extensions =
|
||||
glXQueryExtensionsString(GLX_dpy->dpy, screen);
|
||||
if (GLX_dpy->extensions) {
|
||||
/* glXGetProcAddress is assumed */
|
||||
|
||||
if (strstr(GLX_dpy->extensions, "GLX_SGI_make_current_read")) {
|
||||
/* GLX 1.3 entry points are used */
|
||||
GLX_dpy->have_make_current_read = EGL_TRUE;
|
||||
}
|
||||
|
||||
if (strstr(GLX_dpy->extensions, "GLX_SGIX_fbconfig")) {
|
||||
/* GLX 1.3 entry points are used */
|
||||
GLX_dpy->have_fbconfig = EGL_TRUE;
|
||||
}
|
||||
|
||||
if (strstr(GLX_dpy->extensions, "GLX_SGIX_pbuffer")) {
|
||||
GLX_dpy->glXCreateGLXPbufferSGIX = (PFNGLXCREATEGLXPBUFFERSGIXPROC)
|
||||
glXGetProcAddress((const GLubyte *) "glXCreateGLXPbufferSGIX");
|
||||
GLX_dpy->glXDestroyGLXPbufferSGIX = (PFNGLXDESTROYGLXPBUFFERSGIXPROC)
|
||||
glXGetProcAddress((const GLubyte *) "glXDestroyGLXPbufferSGIX");
|
||||
|
||||
if (GLX_dpy->glXCreateGLXPbufferSGIX &&
|
||||
GLX_dpy->glXDestroyGLXPbufferSGIX &&
|
||||
GLX_dpy->have_fbconfig)
|
||||
GLX_dpy->have_pbuffer = EGL_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (GLX_dpy->glx_maj == 1 && GLX_dpy->glx_min >= 3) {
|
||||
GLX_dpy->have_1_3 = EGL_TRUE;
|
||||
GLX_dpy->have_make_current_read = EGL_TRUE;
|
||||
GLX_dpy->have_fbconfig = EGL_TRUE;
|
||||
GLX_dpy->have_pbuffer = EGL_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
check_quirks(struct GLX_egl_display *GLX_dpy, EGLint screen)
|
||||
{
|
||||
const char *vendor;
|
||||
|
||||
GLX_dpy->single_buffered_quirk = EGL_TRUE;
|
||||
GLX_dpy->glx_window_quirk = EGL_TRUE;
|
||||
|
||||
vendor = glXGetClientString(GLX_dpy->dpy, GLX_VENDOR);
|
||||
if (vendor && strstr(vendor, "NVIDIA")) {
|
||||
vendor = glXQueryServerString(GLX_dpy->dpy, screen, GLX_VENDOR);
|
||||
if (vendor && strstr(vendor, "NVIDIA")) {
|
||||
_eglLog(_EGL_DEBUG, "disable quirks");
|
||||
GLX_dpy->single_buffered_quirk = EGL_FALSE;
|
||||
GLX_dpy->glx_window_quirk = EGL_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called via eglInitialize(), GLX_drv->API.Initialize().
|
||||
*/
|
||||
|
|
@ -478,17 +546,33 @@ GLX_eglInitialize(_EGLDriver *drv, _EGLDisplay *disp,
|
|||
}
|
||||
}
|
||||
|
||||
disp->DriverData = (void *) GLX_dpy;
|
||||
disp->ClientAPIsMask = all_apis;
|
||||
if (!glXQueryVersion(GLX_dpy->dpy, &GLX_dpy->glx_maj, &GLX_dpy->glx_min)) {
|
||||
_eglLog(_EGL_WARNING, "GLX: glXQueryVersion failed");
|
||||
if (!disp->NativeDisplay)
|
||||
XCloseDisplay(GLX_dpy->dpy);
|
||||
free(GLX_dpy);
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
glXQueryVersion(GLX_dpy->dpy, &GLX_dpy->glx_maj, &GLX_dpy->glx_min);
|
||||
check_extensions(GLX_dpy, DefaultScreen(GLX_dpy->dpy));
|
||||
check_quirks(GLX_dpy, DefaultScreen(GLX_dpy->dpy));
|
||||
|
||||
create_configs(disp, GLX_dpy, DefaultScreen(GLX_dpy->dpy));
|
||||
if (!disp->NumConfigs) {
|
||||
_eglLog(_EGL_WARNING, "GLX: failed to create any config");
|
||||
if (!disp->NativeDisplay)
|
||||
XCloseDisplay(GLX_dpy->dpy);
|
||||
free(GLX_dpy);
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
disp->DriverData = (void *) GLX_dpy;
|
||||
disp->ClientAPIsMask = GLX_EGL_APIS;
|
||||
|
||||
/* we're supporting EGL 1.4 */
|
||||
*major = 1;
|
||||
*minor = 4;
|
||||
|
||||
create_configs(disp, GLX_dpy);
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue