Applications that implement their own visual selection by iterating
the visuals and calling glXGetConfig() need this. Previously
the same config was always selected and if it didn't have the
attribs the app wanted the app was stuck.
(In the real-world case the app was forced to choose a visual without a
depth buffer and the resultant drawing was messed up.)
Criticism / comments / suggestions welcome.
-Nathan
--
Open Text Connectivity Solutions Group
Nathan Kidd http://connectivity.opentext.com/
Research and Development Phone: +1 905 762 6001
[email protected] Toll Free: 1 877 359 4866
>From bbddae2e2c981e629bf5ecd4f9540a0853153ef6 Mon Sep 17 00:00:00 2001
From: Nathan Kidd <[email protected]>
Date: Fri, 25 Feb 2011 13:36:22 -0500
Subject: [PATCH 2/2] Let glXGetConfig see variety of visuals
Applications that implement their own visual selection by iterating
the visuals and calling glXGetConfig() need this. Previously
the same config was always selected and if it didn't have the
attribs the app wanted the app was stuck.
---
rr/faker-glx.cpp | 133 +++++++++++++++++++++++++++++++++++++++---------------
rr/glxvisual.cpp | 60 +++++++++++++++++++++++-
2 files changed, 153 insertions(+), 40 deletions(-)
diff --git a/rr/faker-glx.cpp b/rr/faker-glx.cpp
index 267d4d9..7065301 100644
--- a/rr/faker-glx.cpp
+++ b/rr/faker-glx.cpp
@@ -43,58 +43,117 @@ static VisualID _MatchVisual(Display *dpy, GLXFBConfig config)
return vid;
}
+void setAttrib(int *alist, int attrib, int value)
+{
+ for (; *alist != None; alist+=2)
+ {
+ if (*alist == attrib)
+ {
+ *(++alist) = value;
+ return;
+ }
+ }
+}
+
+int getAttrib(int *alist, int attrib)
+{
+ for (; *alist != None; alist+=2)
+ if (*alist == attrib)
+ return *(++alist);
+ return 0;
+}
+
static GLXFBConfig _MatchConfig(Display *dpy, XVisualInfo *vis)
{
- GLXFBConfig c=0, *configs=NULL; int n=0;
+ GLXFBConfig c=0, *configs=NULL; int n=0, i;
if(!dpy || !vis) return 0;
if(!(c=vish.getpbconfig(dpy, vis))&& !(c=vish.mostrecentcfg(dpy, vis)))
{
- // Punt. We can't figure out where the visual came from
- int attribs[]={GLX_DOUBLEBUFFER, 1, GLX_RED_SIZE, 8, GLX_GREEN_SIZE, 8,
- GLX_BLUE_SIZE, 8, GLX_RENDER_TYPE, GLX_RGBA_BIT, GLX_STEREO, 0,
- GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT, None};
- if(__vglClientVisualAttrib(dpy, DefaultScreen(dpy), vis->visualid, GLX_STEREO))
- attribs[11]=1;
+ // An application may implement its own internal glXChooseVisual
+ // by iterating the visual list and calling glXGetConfig. Thus
+ // it is normal to hit this case where we don't yet know about the visual
+ // We should find the server FBConfig that most closely matches the
+ // client visual. If we pick the same generic config every time then
+ // the app will not have any variety to choose from and may not get
+ // the attribs it wants even though such a config is available.
+ // Therefore, we artificially populate the Visual table with
+ // a nice selection of attributes, and do our best to match each
+ // visual's properties here.
+
+ // For GLX we force a GLX_X_VISUAL_TYPE match to ensure VGL_WINDOW will work.
+ int attribs[]={
+ // GLX only
+ // WINDOW_BIT must be present for GLX_X_VISUAL_TYPE to count and VGL_WINDOW=1 to work
+ GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT | GLX_WINDOW_BIT, // GLP doesn't set *any* bits
+ GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR,
+ // GLX and GLP
+ GLX_RENDER_TYPE, GLX_RGBA_BIT,
+ GLX_RED_SIZE, 0, GLX_GREEN_SIZE, 0, GLX_BLUE_SIZE, 0, GLX_ALPHA_SIZE, 0,
+ GLX_DOUBLEBUFFER, 0,
+ GLX_STEREO, 0,
+ GLX_AUX_BUFFERS, 0,
+ GLX_DEPTH_SIZE, 0,
+ GLX_STENCIL_SIZE, 0,
+ None};
#ifdef USEGLP
- if(fconfig.glp)
+ int *glpattribs=&attribs[4]; // GLP can't have some attribs
+ #endif
+
+ // Initialize values we care about from this visual
+ setAttrib(attribs, GLX_RED_SIZE, __vglClientVisualAttrib(dpy, DefaultScreen(dpy), vis->visualid, GLX_RED_SIZE));
+ setAttrib(attribs, GLX_GREEN_SIZE, __vglClientVisualAttrib(dpy, DefaultScreen(dpy), vis->visualid, GLX_GREEN_SIZE));
+ setAttrib(attribs, GLX_BLUE_SIZE, __vglClientVisualAttrib(dpy, DefaultScreen(dpy), vis->visualid, GLX_BLUE_SIZE));
+ setAttrib(attribs, GLX_ALPHA_SIZE, __vglClientVisualAttrib(dpy, DefaultScreen(dpy), vis->visualid, GLX_ALPHA_SIZE));
+ setAttrib(attribs, GLX_DOUBLEBUFFER, __vglClientVisualAttrib(dpy, DefaultScreen(dpy), vis->visualid, GLX_DOUBLEBUFFER));
+ setAttrib(attribs, GLX_STEREO, __vglClientVisualAttrib(dpy, DefaultScreen(dpy), vis->visualid, GLX_STEREO));
+ setAttrib(attribs, GLX_AUX_BUFFERS, __vglClientVisualAttrib(dpy, DefaultScreen(dpy), vis->visualid, GLX_AUX_BUFFERS));
+ setAttrib(attribs, GLX_DEPTH_SIZE, __vglClientVisualAttrib(dpy, DefaultScreen(dpy), vis->visualid, GLX_DEPTH_SIZE));
+ setAttrib(attribs, GLX_STENCIL_SIZE, __vglClientVisualAttrib(dpy, DefaultScreen(dpy), vis->visualid, GLX_STENCIL_SIZE));
+
+ // This could end up causing a lot of work for the local libGL, but only happens once
+ // per visual and the dataset isn't going to be more than a few hundred configs at most.
+ // To keep it simple, no effort is made to skip redundant queries (e.g. if stereo was already off)
+ for (i=0; i<=8; i++)
{
- attribs[12]=attribs[13]=None;
- if(!attribs[11]) attribs[10]=None;
- configs=glPChooseFBConfig(_localdev, attribs, &n);
- if((!configs || n<1) && attribs[11])
+ // We try to match the original visual settings, and if no config matches we
+ // start resetting attributes to their default values, in order of least importance.
+ // Most GLX attributes have default values. Explicitly specifying
+ // the default value is the same as not specifying the attrib at all.
+ switch (i)
{
- attribs[10]=attribs[11]=0;
- configs=glPChooseFBConfig(_localdev, attribs, &n);
+ case 0: break; // use original values
+ case 1: setAttrib(attribs, GLX_DRAWABLE_TYPE, getAttrib(attribs, GLX_DRAWABLE_TYPE)& ~GLX_WINDOW_BIT); break;
+ case 2: setAttrib(attribs, GLX_STENCIL_SIZE, 0); break;
+ case 3: setAttrib(attribs, GLX_DEPTH_SIZE, 16); break;
+ case 4: setAttrib(attribs, GLX_DEPTH_SIZE, 0); break;
+ case 5: setAttrib(attribs, GLX_AUX_BUFFERS, 0); break;
+ case 6: setAttrib(attribs, GLX_STEREO, 0); break;
+ case 7: setAttrib(attribs, GLX_DOUBLEBUFFER, 0); break;
+ case 8: setAttrib(attribs, GLX_ALPHA_SIZE, 0); break;
}
- if((!configs || n<1) && attribs[1])
+
+ #ifdef USEGLP
+ if(fconfig.glp)
{
- attribs[1]=0;
- configs=glPChooseFBConfig(_localdev, attribs, &n);
+ configs=glPChooseFBConfig(_localdev, glpattribs, &n);
}
- if(!configs || n<1) return 0;
- }
- else
- #endif
- {
- configs=glXChooseFBConfig(_localdpy, DefaultScreen(_localdpy), attribs, &n);
- if((!configs || n<1) && attribs[11])
+ else
+ #endif
{
- attribs[11]=0;
- configs=glXChooseFBConfig(_localdpy, DefaultScreen(_localdpy), attribs, &n);
+ configs=glXChooseFBConfig(_localdpy, DefaultScreen(_localdpy), attribs, &n);
}
- if((!configs || n<1) && attribs[1])
+
+ if(configs && n>0)
{
- attribs[1]=0;
- configs=glXChooseFBConfig(_localdpy, DefaultScreen(_localdpy), attribs, &n);
+ c=configs[0];
+ XFree(configs);
+ if(c)
+ {
+ vish.add(dpy, vis, c);
+ cfgh.add(dpy, c, vis->visualid);
+ break;
+ }
}
- if(!configs || n<1) return 0;
- }
- c=configs[0];
- XFree(configs);
- if(c)
- {
- vish.add(dpy, vis, c);
- cfgh.add(dpy, c, vis->visualid);
}
}
return c;
diff --git a/rr/glxvisual.cpp b/rr/glxvisual.cpp
index 599ac33..071abdc 100644
--- a/rr/glxvisual.cpp
+++ b/rr/glxvisual.cpp
@@ -37,6 +37,9 @@ struct _visattrib
int depth, c_class;
int level, stereo, db, gl, trans;
int tindex, tr, tg, tb, ta;
+ // Artificial values we make up and try to match on the local libGL
+ int rsize, gsize, bsize, asize;
+ int auxbufs, depthbufsize, stencilsize;
};
static Display *_vadpy=NULL;
@@ -126,16 +129,58 @@ static void buildVisAttribTable(Display *dpy, int screen)
if(olprop) {XFree(olprop); olprop=NULL;}
}
+
_vahasgcv=false;
- for(int i=0; i<nv; i++)
+ int red=8, green=8, blue=8, alpha=0;
+ int db=1, stereo=0, auxbufs=4, depthbufsize=24, stencilsize=8, gl=1;
+ for(int i=0, c=0, tc=0, other=0; i<nv; i++)
{
+ // Except for stereo and gamma features, the visual attributes available
+ // on the client (possibly none if no GLX extension) needn't have any
+ // bearing on the visual attributes we present to the application.
+ // Here we make up GL attributes that would be nice to give the
+ // application, and let _MatchConfig worry about finding the closest
+ // match it can.
+
+ // Iterate two separate attrib lists, one for TrueColor visuals, and
+ // one for other classes. The idea is to ensure TrueColor visuals have
+ // a full range of attributes while other classes at least have some variety.
+ if (_va[i].c_class == TrueColor)
+ c=tc++;
+ else
+ c=other++;
+
+ alpha= (c&1) ? 8 : 0; // flip every other visual
+ db= (c&2) ? 0 : 1; // flip every two
+ stencilsize= (c&4) ? 0 : 8; // ...
+ depthbufsize=(c&8) ? 0 :24;
+ auxbufs= (c&16)? 0 : 4;
+
+ _va[i].gl=gl;
+ _va[i].rsize=red;
+ _va[i].gsize=green;
+ _va[i].bsize=blue;
+ _va[i].asize=alpha;
+ _va[i].db=db;
+ _va[i].stereo=stereo;
+ _va[i].auxbufs=auxbufs;
+ _va[i].depthbufsize=depthbufsize;
+ _va[i].stencilsize=stencilsize;
+
+ // These values need to be fetched from the actual display because
+ // they're related to the physical display device.
_XSolarisGetVisualGamma(dpy, screen, visuals[i].visual, &_va[i].gamma);
if(_va[i].gamma==1.00) _vahasgcv=true;
if(clientglx)
{
- _glXGetConfig(dpy, &visuals[i], GLX_DOUBLEBUFFER, &_va[i].db);
- _glXGetConfig(dpy, &visuals[i], GLX_USE_GL, &_va[i].gl);
_glXGetConfig(dpy, &visuals[i], GLX_STEREO, &_va[i].stereo);
+ if (_va[i].stereo)
+ {
+ // Override artificial values only when stereo in use
+ // so in the non-stereo case we get full visual selection
+ _glXGetConfig(dpy, &visuals[i], GLX_DOUBLEBUFFER, &_va[i].db);
+ _glXGetConfig(dpy, &visuals[i], GLX_USE_GL, &_va[i].gl);
+ }
}
}
@@ -310,10 +355,19 @@ int __vglClientVisualAttrib(Display *dpy, int screen, VisualID vid, int attribut
if(attribute==GLX_TRANSPARENT_GREEN_VALUE) return _va[i].tg;
if(attribute==GLX_TRANSPARENT_BLUE_VALUE) return _va[i].tb;
if(attribute==GLX_TRANSPARENT_ALPHA_VALUE) return _va[i].ta;
+ // Note: GL attributes may be artificial (not taken from client side)
if(attribute==GLX_STEREO)
{
return (_va[i].stereo && _va[i].gl && _va[i].db);
}
+ if(attribute==GLX_DOUBLEBUFFER) return _va[i].db;
+ if(attribute==GLX_RED_SIZE) return _va[i].rsize;
+ if(attribute==GLX_GREEN_SIZE) return _va[i].gsize;
+ if(attribute==GLX_BLUE_SIZE) return _va[i].bsize;
+ if(attribute==GLX_ALPHA_SIZE) return _va[i].asize;
+ if(attribute==GLX_AUX_BUFFERS) return _va[i].auxbufs;
+ if(attribute==GLX_DEPTH_SIZE) return _va[i].depthbufsize;
+ if(attribute==GLX_STENCIL_SIZE) return _va[i].stencilsize;
}
}
return 0;
--
1.6.3.3
------------------------------------------------------------------------------
Free Software Download: Index, Search & Analyze Logs and other IT data in
Real-Time with Splunk. Collect, index and harness all the fast moving IT data
generated by your applications, servers and devices whether physical, virtual
or in the cloud. Deliver compliance at lower cost and gain new business
insights. http://p.sf.net/sfu/splunk-dev2dev
_______________________________________________
VirtualGL-Users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/virtualgl-users