glxwrapper.cc

Go to the documentation of this file.
00001 
00004 
00005 //
00006 // Copyright (c) 2005-2007 University of Southern California
00007 // Rob Peters <rjpeters at usc dot edu>
00008 //
00009 // created: Fri Nov 11 16:10:15 2005
00010 // commit: $Id: glxwrapper.cc 10065 2007-04-12 05:54:56Z rjpeters $
00011 // $HeadURL: file:///lab/rjpeters/svnrepo/code/trunk/groovx/src/gfx/glxwrapper.cc $
00012 //
00013 // --------------------------------------------------------------------
00014 //
00015 // This file is part of GroovX.
00016 //   [http://www.klab.caltech.edu/rjpeters/groovx/]
00017 //
00018 // GroovX is free software; you can redistribute it and/or modify it
00019 // under the terms of the GNU General Public License as published by
00020 // the Free Software Foundation; either version 2 of the License, or
00021 // (at your option) any later version.
00022 //
00023 // GroovX is distributed in the hope that it will be useful, but
00024 // WITHOUT ANY WARRANTY; without even the implied warranty of
00025 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00026 // General Public License for more details.
00027 //
00028 // You should have received a copy of the GNU General Public License
00029 // along with GroovX; if not, write to the Free Software Foundation,
00030 // Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
00031 //
00033 
00034 #ifndef GROOVX_GFX_GLXWRAPPER_CC_UTC20051112001015_DEFINED
00035 #define GROOVX_GFX_GLXWRAPPER_CC_UTC20051112001015_DEFINED
00036 
00037 #ifdef GVX_GL_PLATFORM_GLX
00038 
00039 #include "gfx/glxwrapper.h"
00040 
00041 #include "gfx/glxopts.h"
00042 
00043 #include "rutz/error.h"
00044 #include "rutz/shared_ptr.h"
00045 
00046 #include "rutz/debug.h"
00047 GVX_DBG_REGISTER
00048 #include "rutz/trace.h"
00049 
00050 namespace
00051 {
00052   // For caching the latest subject of GlxWrapper::makeCurrent()
00053   const GlxWrapper* currentGlxWrapper = 0;
00054 
00055   // Builds a formatted data array for constructing a GLX context.
00056   class AttribList
00057   {
00058   private:
00059     enum { MAXSIZE = 1000 };
00060 
00061     void push(int v)
00062     {
00063       GVX_ASSERT(next < MAXSIZE);
00064       data[next++] = v;
00065     }
00066 
00067     void cap()
00068     {
00069       data[next] = None;
00070     }
00071 
00072     int data[MAXSIZE];
00073     int next;
00074 
00075   public:
00077     AttribList(const GlxOpts& opts) : next(0)
00078     {
00079       push( GLX_USE_GL );
00080 
00081       if (opts.rgbaFlag)        this->rgba(opts.rgbaRed, opts.rgbaGreen, opts.rgbaBlue,
00082                                            opts.alphaFlag ? opts.alphaSize : -1);
00083 
00084       else                      this->colorIndex( opts.colorIndexSize );
00085 
00086       if (opts.depthFlag)       this->depthBuffer( opts.depthSize );
00087 
00088       if (opts.doubleFlag)      this->doubleBuffer();
00089 
00090       if (opts.stencilFlag)     this->stencilBuffer( opts.stencilSize );
00091 
00092       if (opts.accumFlag)       this->accum(opts.accumRed, opts.accumGreen, opts.accumBlue,
00093                                             opts.alphaFlag ? opts.accumAlpha : -1);
00094 
00095       if (opts.auxNumber > 0)   this->auxBuffers( opts.auxNumber );
00096 
00097       if (opts.level != 0)      this->level( opts.level );
00098 
00099       if (opts.transparent)     this->transparent();
00100     }
00101 
00103     int* get() { cap(); return data; }
00104 
00106     void rgba(int rbits, int gbits, int bbits, int abits = -1)
00107     {
00108       push( GLX_RGBA );
00109       push( GLX_RED_SIZE );
00110       push( rbits );          dbg_eval(3, rbits);
00111       push( GLX_GREEN_SIZE );
00112       push( gbits );          dbg_eval(3, gbits);
00113       push( GLX_BLUE_SIZE );
00114       push( bbits );          dbg_eval_nl(3, bbits);
00115       if (abits > 0)
00116         {
00117           push( GLX_ALPHA_SIZE );
00118           push( abits );      dbg_eval_nl(3, abits);
00119         }
00120     }
00121 
00123     void level(int lev)
00124     {
00125       push( GLX_LEVEL );
00126       push( lev );
00127     }
00128 
00130     void colorIndex(int bits)
00131     {
00132       push( GLX_BUFFER_SIZE );
00133       push( bits );
00134     }
00135 
00137     void depthBuffer(int bits)
00138     {
00139       push( GLX_DEPTH_SIZE );
00140       push( bits );
00141     }
00142 
00144     void doubleBuffer()
00145     {
00146       push( GLX_DOUBLEBUFFER );
00147     }
00148 
00150     void stencilBuffer(int bits)
00151     {
00152       push( GLX_STENCIL_SIZE );
00153       push( bits );
00154     }
00155 
00157     void accum(int rbits, int gbits, int bbits, int abits = -1)
00158     {
00159       push( GLX_ACCUM_RED_SIZE );
00160       push( rbits );
00161       push( GLX_ACCUM_GREEN_SIZE );
00162       push( gbits );
00163       push( GLX_ACCUM_BLUE_SIZE );
00164       push( bbits );
00165       if (abits > 0)
00166         {
00167           push( GLX_ACCUM_ALPHA_SIZE );
00168           push( abits );
00169         }
00170     }
00171 
00173     void auxBuffers(int n)
00174     {
00175       push( GLX_AUX_BUFFERS );
00176       push( n );
00177     }
00178 
00180     void transparent()
00181     {
00182 #ifdef GLX_TRANSPARENT_TYPE_EXT
00183       push( GLX_TRANSPARENT_TYPE_EXT );
00184       push( GLX_TRANSPARENT_INDEX_EXT );
00185 #endif
00186     }
00187   };
00188 }
00189 
00190 GlxWrapper::GlxWrapper(Display* dpy, GlxOpts& opts, GlxWrapper* share) :
00191   itsDisplay(dpy),
00192   itsVisInfo(0),
00193   itsContext(0),
00194   itsCurrentWin(0)
00195 {
00196 GVX_TRACE("GlxWrapper::GlxWrapper");
00197 
00198   int dummy;
00199   if (!glXQueryExtension(dpy, &dummy, &dummy))
00200     {
00201       throw rutz::error("GlxWrapper: X server has no OpenGL GLX extension", SRC_POS);
00202     }
00203 
00204   AttribList attribs(opts);
00205 
00206   dbg_eval_nl(3, (void*)itsDisplay);
00207   dbg_eval_nl(3, DefaultScreen(itsDisplay));
00208 
00209   int errorBase = 0;
00210   int eventBase = 0;
00211 
00212   if (False == glXQueryExtension(itsDisplay, &errorBase, &eventBase))
00213     {
00214       throw rutz::error("no GLX extension on the X server", SRC_POS);
00215     }
00216 
00217   itsVisInfo = glXChooseVisual(itsDisplay,
00218                                DefaultScreen(itsDisplay),
00219                                attribs.get());
00220 
00221   // If we had requested single-buffering, then now try for
00222   // double-buffering, since that can emulate single-buffering
00223   if (itsVisInfo == 0)
00224     {
00225       attribs.doubleBuffer();
00226       itsVisInfo = glXChooseVisual(itsDisplay,
00227                                    DefaultScreen(itsDisplay),
00228                                    attribs.get());
00229     }
00230 
00231   // If we still didn't get a matching visual, then bail out
00232   if (itsVisInfo == 0)
00233     {
00234       throw rutz::error("couldn't find a matching visual", SRC_POS);
00235     }
00236 
00237   dbg_eval_nl(3, (void*)itsVisInfo->visualid);
00238   dbg_eval_nl(3, itsVisInfo->depth);
00239   dbg_eval_nl(3, itsVisInfo->bits_per_rgb);
00240 
00241   itsContext = glXCreateContext(itsDisplay,
00242                                 itsVisInfo,
00243                                 share ? share->itsContext : None,
00244                                 opts.indirect ? GL_FALSE : GL_TRUE);
00245 
00246   dbg_eval_nl(3, itsContext);
00247 
00248   if (itsContext == 0)
00249     {
00250       throw rutz::error("could not create GL rendering context", SRC_POS);
00251     }
00252 }
00253 
00254 GlxWrapper::~GlxWrapper()
00255 {
00256 GVX_TRACE("GlxWrapper::~GlxWrapper");
00257 
00258   glXDestroyContext(itsDisplay, itsContext);
00259   XFree(itsVisInfo);
00260 }
00261 
00262 GlxWrapper* GlxWrapper::make(Display* dpy, GlxOpts& opts, GlxWrapper* share)
00263 {
00264 GVX_TRACE("GlxWrapper::make");
00265 
00266   // Create a new OpenGL rendering context.
00267   GlxWrapper* glx = new GlxWrapper(dpy, opts, share);
00268 
00269   // Make sure we don't try to use a depth buffer with indirect rendering
00270   if ( !glx->isDirect() && opts.depthFlag )
00271     {
00272       delete glx;
00273       opts.depthFlag = false;
00274       return make(dpy, opts, share);
00275     }
00276 
00277   opts.indirect = !glx->isDirect();
00278 
00279   return glx;
00280 }
00281 
00282 void GlxWrapper::makeCurrent()
00283 {
00284 GVX_TRACE("GlxWrapper::makeCurrent");
00285 
00286   GVX_ASSERT(itsCurrentWin != 0);
00287 
00288   if (currentGlxWrapper != this)
00289     {
00290       glXMakeCurrent(itsDisplay, itsCurrentWin, itsContext);
00291       currentGlxWrapper = this;
00292     }
00293 }
00294 
00295 void GlxWrapper::onReshape(int /*width*/, int /*height*/)
00296 {
00297   // nothing to do here
00298 }
00299 
00300 bool GlxWrapper::isDoubleBuffered() const
00301 {
00302 GVX_TRACE("GlxWrapper::isDoubleBuffered");
00303 
00304   int dbl_flag;
00305 
00306   if (glXGetConfig(itsDisplay, itsVisInfo, GLX_DOUBLEBUFFER, &dbl_flag) != 0)
00307     {
00308       throw rutz::error("glXGetConfig failed", SRC_POS);
00309     }
00310 
00311   return bool(dbl_flag);
00312 }
00313 
00314 unsigned int GlxWrapper::bitsPerPixel() const
00315 {
00316 GVX_TRACE("GlxWrapper::bitsPerPixel");
00317   return itsVisInfo->depth;
00318 }
00319 
00320 void GlxWrapper::swapBuffers() const
00321 {
00322   glXSwapBuffers(itsDisplay, itsCurrentWin);
00323 }
00324 
00325 #endif // GVX_GL_PLATFORM_GLX
00326 
00327 static const char __attribute__((used)) vcid_groovx_gfx_glxwrapper_cc_utc20051112001015[] = "$Id: glxwrapper.cc 10065 2007-04-12 05:54:56Z rjpeters $ $HeadURL: file:
00328 #endif // !GROOVX_GFX_GLXWRAPPER_CC_UTC20051112001015DEFINED

The software described here is Copyright (c) 1998-2005, Rob Peters.
This page was generated Wed Dec 3 06:49:38 2008 by Doxygen version 1.5.5.