choosevisual.c revision e0e0c19eefceaf5d4ec40f9466b58a771f50e799
#include "chromium.h"
#include "cr_spu.h"
#include "cr_error.h"
#include "cr_string.h"
/**
* Wrappers for glXChooseVisual/etc.
*
* By using this function, the fake GLX, render SPU, tilesort SPU,
* etc can be assured of getting the same GLX visual for a set of CR_*_BIT
* visual flags. This helps ensure that render_to_app_window will work
* properly.
*/
#if defined(WINDOWS)
int
crChooseVisual(const crOpenGLInterface *ws, int visBits)
{
/* placeholder */
return 0;
}
#endif
#if defined(DARWIN)
int
crChooseVisual(const crOpenGLInterface *ws, int visBits)
{
/* placeholder */
return 0;
}
#endif
#if defined(GLX)
XVisualInfo *
crChooseVisual(const crOpenGLInterface *ws, Display *dpy, int screen,
GLboolean directColor, int visBits)
{
XVisualInfo *vis;
int errorBase, eventBase;
if (ws->glXQueryExtension(dpy, &errorBase, &eventBase))
{
if (ws->glXChooseVisual)
{
/* Use the real OpenGL's glXChooseVisual function */
int attribList[100];
int i = 0;
/* Build the attribute list */
if (visBits & CR_RGB_BIT)
{
attribList[i++] = GLX_RGBA;
attribList[i++] = GLX_RED_SIZE;
attribList[i++] = 1;
attribList[i++] = GLX_GREEN_SIZE;
attribList[i++] = 1;
attribList[i++] = GLX_BLUE_SIZE;
attribList[i++] = 1;
}
if (visBits & CR_ALPHA_BIT)
{
attribList[i++] = GLX_ALPHA_SIZE;
attribList[i++] = 1;
}
if (visBits & CR_DOUBLE_BIT)
{
attribList[i++] = GLX_DOUBLEBUFFER;
}
if (visBits & CR_STEREO_BIT)
{
attribList[i++] = GLX_STEREO;
}
if (visBits & CR_DEPTH_BIT)
{
attribList[i++] = GLX_DEPTH_SIZE;
attribList[i++] = 1;
}
if (visBits & CR_STENCIL_BIT)
{
attribList[i++] = GLX_STENCIL_SIZE;
attribList[i++] = 1;
}
if (visBits & CR_ACCUM_BIT)
{
attribList[i++] = GLX_ACCUM_RED_SIZE;
attribList[i++] = 1;
attribList[i++] = GLX_ACCUM_GREEN_SIZE;
attribList[i++] = 1;
attribList[i++] = GLX_ACCUM_BLUE_SIZE;
attribList[i++] = 1;
if (visBits & CR_ALPHA_BIT)
{
attribList[i++] = GLX_ACCUM_ALPHA_SIZE;
attribList[i++] = 1;
}
}
if (visBits & CR_MULTISAMPLE_BIT)
{
attribList[i++] = GLX_SAMPLE_BUFFERS_SGIS;
attribList[i++] = 1;
attribList[i++] = GLX_SAMPLES_SGIS;
attribList[i++] = 4;
}
if (visBits & CR_OVERLAY_BIT)
{
attribList[i++] = GLX_LEVEL;
attribList[i++] = 1;
}
if (directColor)
{
/*
* See if we have have GLX_EXT_visual_info so we
* can grab a Direct Color visual
*/
#ifdef GLX_EXT_visual_info
if (crStrstr(ws->glXQueryExtensionsString(dpy, screen),
"GLX_EXT_visual_info"))
{
attribList[i++] = GLX_X_VISUAL_TYPE_EXT;
attribList[i++] = GLX_DIRECT_COLOR_EXT;
}
#endif
}
/* End the list */
attribList[i++] = None;
vis = ws->glXChooseVisual(dpy, screen, attribList);
return vis;
}
else
{
/* Don't use glXChooseVisual, use glXGetConfig.
*
* Here's the deal:
* Some (all?) versions of the libGL.so that's shipped with ATI's
* drivers aren't built with the -Bsymbolic flag. That's bad.
*
* If we call the glXChooseVisual() function that's built into ATI's
* libGL, it in turn calls the glXGetConfig() function. Now, there's
* a glXGetConfig function in libGL.so **AND** there's a glXGetConfig
* function in Chromium's libcrfaker.so library. Unfortunately, the
* later one gets called instead of the former. At this point, things
* go haywire. If -Bsymbolic were used, this would not happen.
*/
XVisualInfo templateVis;
long templateFlags;
int count, i, visType;
visType = directColor ? DirectColor : TrueColor;
/* Get list of candidate visuals */
templateFlags = VisualScreenMask | VisualClassMask;
templateVis.screen = screen;
#if defined(__cplusplus) || defined(c_plusplus)
templateVis.c_class = visType;
#else
templateVis.class = visType;
#endif
vis = XGetVisualInfo(dpy, templateFlags, &templateVis, &count);
/* find first visual that's good enough */
for (i = 0; i < count; i++)
{
int val;
/* Need exact match on RGB, DOUBLEBUFFER, STEREO, LEVEL, MULTISAMPLE */
ws->glXGetConfig(dpy, vis + i, GLX_RGBA, &val);
if (((visBits & CR_RGB_BIT) && !val) ||
(((visBits & CR_RGB_BIT) == 0) && val))
{
continue;
}
ws->glXGetConfig(dpy, vis + i, GLX_DOUBLEBUFFER, &val);
if (((visBits & CR_DOUBLE_BIT) && !val) ||
(((visBits & CR_DOUBLE_BIT) == 0) && val))
{
continue;
}
ws->glXGetConfig(dpy, vis + i, GLX_STEREO, &val);
if (((visBits & CR_STEREO_BIT) && !val) ||
(((visBits & CR_STEREO_BIT) == 0) && val))
{
continue;
}
ws->glXGetConfig(dpy, vis + i, GLX_LEVEL, &val);
if (((visBits & CR_OVERLAY_BIT) && !val) ||
(((visBits & CR_OVERLAY_BIT) == 0) && val))
{
continue;
}
ws->glXGetConfig(dpy, vis + i, GLX_SAMPLE_BUFFERS_SGIS, &val);
if (visBits & CR_MULTISAMPLE_BIT)
{
if (!val)
continue;
ws->glXGetConfig(dpy, vis + i, GLX_SAMPLES_SGIS, &val);
if (val < 4)
continue;
}
else {
/* don't want multisample */
if (val)
continue;
}
/* Need good enough for ALPHA, DEPTH, STENCIL, ACCUM */
if (visBits & CR_ALPHA_BIT)
{
ws->glXGetConfig(dpy, vis + i, GLX_ALPHA_SIZE, &val);
if (!val)
continue;
}
if (visBits & CR_DEPTH_BIT)
{
ws->glXGetConfig(dpy, vis + i, GLX_DEPTH_SIZE, &val);
if (!val)
continue;
}
if (visBits & CR_STENCIL_BIT)
{
ws->glXGetConfig(dpy, vis + i, GLX_STENCIL_SIZE, &val);
if (!val)
continue;
}
if (visBits & CR_ACCUM_BIT)
{
ws->glXGetConfig(dpy, vis + i, GLX_ACCUM_RED_SIZE, &val);
if (!val)
continue;
if (visBits & CR_ALPHA_BIT)
{
ws->glXGetConfig(dpy, vis + i, GLX_ACCUM_ALPHA_SIZE, &val);
if (!val)
continue;
}
}
/* If we get here, we found a good visual.
* Now, we need to get a new XVisualInfo pointer in case the caller
* calls XFree on it.
*/
templateFlags = VisualScreenMask | VisualIDMask;
templateVis.screen = screen;
templateVis.visualid = vis[i].visual->visualid;
XFree(vis); /* free the list */
vis = XGetVisualInfo(dpy, templateFlags, &templateVis, &count);
return vis;
}
/* if we get here, we failed to find a sufficient visual */
return NULL;
}
}
else
{
/* use Xlib instead of GLX */
XVisualInfo templateVis, *best;
long templateFlags;
int i, count, visType;
if (visBits & CR_RGB_BIT)
visType = directColor ? DirectColor : TrueColor;
else
visType = PseudoColor;
/* Get list of candidate visuals */
templateFlags = VisualScreenMask | VisualClassMask;
templateVis.screen = screen;
#if defined(__cplusplus) || defined(c_plusplus)
templateVis.c_class = visType;
#else
templateVis.class = visType;
#endif
vis = XGetVisualInfo(dpy, templateFlags, &templateVis, &count);
if (!vis)
return NULL;
/* okay, select the RGB visual with the most depth */
best = vis + 0;
for (i = 1; i < count; i++)
{
if (vis[i].depth > best->depth &&
vis[i].bits_per_rgb > best->bits_per_rgb )
best = vis + i;
}
if (best)
{
/* If we get here, we found a good visual.
* Now, we need to get a new XVisualInfo pointer in case the caller
* calls XFree on it.
*/
templateFlags = VisualScreenMask | VisualIDMask;
templateVis.screen = screen;
templateVis.visualid = best->visualid;
XFree(vis); /* free the list */
best = XGetVisualInfo(dpy, templateFlags, &templateVis, &count);
}
return best;
}
}
#endif /* GLX */