PCMXDisplay.cpp

Go to the documentation of this file.
00001 
00002 //
00003 // This source file is a part of ParCompMark
00004 // Parallel Compositing Benchmark Framework
00005 //
00006 // for latest info see http://parcompmark.sourceforge.net
00007 
00008 //
00009 // Copyright (C) 2006 IT2 ParCompMark Dev. Team
00010 // 
00011 // This program is free software; you can redistribute it and/or
00012 // modify it under the terms of the GNU General Public License
00013 // as published by the Free Software Foundation; either version 2
00014 // of the License, or (at your option) any later version.
00015 // 
00016 // This program is distributed in the hope that it will be useful,
00017 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00018 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00019 // GNU General Public License for more details.
00020 // 
00021 // You should have received a copy of the GNU General Public License
00022 // along with this program; if not, write to the Free Software
00023 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00024 
00025 //
00026 // Inner includes
00027 //
00028 
00029 #include "../include/PCMXDisplay.h"
00030 
00031 #include "../include/PCMStringConverter.h"
00032 
00033 namespace ParCompMark
00034 {
00035 
00036   //
00037   // Class constants
00038   //
00039 
00040   const s32 XDisplay::IGNOREMULTISAMPLE = -1;
00041   const s32 XDisplay::UNKNOWNDIMENSION = 0;
00042 
00043   //
00044   // Class variables
00045   //
00046 
00047   bool XDisplay::mXMTInitialized = false;
00048   bool XDisplay::mXMTSupported = false;
00049   Mutex XDisplay::mErrorHandlerMutex;
00050   bool XDisplay::mTolerateErrors = false;
00051 
00052   //
00053   // Constructors & destructor
00054   //
00055 
00056    XDisplay::XDisplay(const std::string & displayName)
00057         // You have to initialize the following attributes:
00058         // - mDisplayName
00059         // - mDisplay
00060         // - mInitialized
00061         // - mXMTInitialized
00062         // - mXMTSupported
00063         // - mWidth
00064         // - mHeight
00065         // - mErrorHandlerMutex
00066         // - mTolerateErrors
00067   {
00068         mDisplayName = displayName;
00069         mDisplay = 0;
00070         mInitialized = false;
00071 
00072         mWidth = mHeight = UNKNOWNDIMENSION;
00073 
00074         Logger::getInstance()->log(Logger::NOTICE, "Display `" + mDisplayName + "\' has been created.");
00075   }
00076 
00077  /*----------------------------------------------------------------------*/
00078 
00079   XDisplay::~XDisplay()
00080   {
00081         if(mInitialized)
00082          finalize();
00083 
00084         Logger::getInstance()->log(Logger::NOTICE, "Display `" + mDisplayName + "\' has been destroyed.");
00085   }
00086 
00087  /*----------------------------------------------------------------------*/
00088 
00089   //
00090   // Class methods
00091   //
00092 
00093   int XDisplay::errorHandler(Display * display, XErrorEvent * errorEvent)
00094   {
00095         // Skip Xlib errors
00096         if(mTolerateErrors)
00097          return 0;
00098 
00099         // For synchronization the class level error handling
00100         mErrorHandlerMutex.lock();
00101 
00102         const u32 bufSize = 10240;
00103         char buffer_return[bufSize];
00104 
00105         memset(buffer_return, 0, bufSize);
00106 
00107         // Obtain error message
00108         XGetErrorText(errorEvent->display, errorEvent->error_code, buffer_return, bufSize);
00109 
00110         std::string errorMessage =
00111          buffer_return + std::string(" (error code: " + StringConverter::toString((u16) errorEvent->error_code) +
00112                                         ") on display `") + DisplayString(errorEvent->display) +
00113          "\', serial number of failed request: " + StringConverter::toString((u32) errorEvent->serial) +
00114          ", op-code of failed request: " + StringConverter::toString((u16) errorEvent->request_code) + "." +
00115          StringConverter::toString((u16) errorEvent->minor_code);
00116 
00117         // For synchronization the class level error handling
00118         mErrorHandlerMutex.unlock();
00119 
00120         // Throw an exception
00121         Except(XLIB_ERROR, "XDisplay::errorHandler()", errorMessage);
00122 
00123         return 0;
00124   }
00125 
00126  /*----------------------------------------------------------------------*/
00127 
00128   //
00129   // Methods
00130   //
00131 
00132   void XDisplay::initialize()
00133   {
00134         Assert(!mInitialized, INVALID_OPERATION_ERROR, "XDisplay::initialize()");
00135 
00136         // Initialize multi-threading if needed
00137         if(!mXMTInitialized)
00138          initializeMT();
00139 
00140         if(mDisplayName.length() > 0)
00141          mDisplay = XOpenDisplay(mDisplayName.c_str());
00142         else
00143          mDisplay = XOpenDisplay(0);
00144 
00145         // If XOpenDisplay() does not succeed, it returns NULL
00146         Assert(mDisplay, INVALID_NAME_ERROR, "XDisplay::initialize()");
00147 
00148         // Get dimensions
00149         int screen = DefaultScreen(mDisplay);
00150 
00151         mWidth = (u32) DisplayWidth(mDisplay, screen);
00152         mHeight = (u32) DisplayHeight(mDisplay, screen);
00153 
00154         mInitialized = true;
00155 
00156         Logger::getInstance()->log(Logger::DEBUG,
00157                                  "Display `" + mDisplayName + "\' has been initialized: " +
00158                                  StringConverter::toString(mDisplay) + ".");
00159   }
00160 
00161  /*----------------------------------------------------------------------*/
00162 
00163   void XDisplay::finalize()
00164   {
00165         Assert(mInitialized, INVALID_OPERATION_ERROR, "XDisplay::finalize()");
00166         Assert(mDisplay, NULL_POINTER_ERROR, "XDisplay::finalize()");
00167 
00168         synchronize();
00169 
00170         // Close display
00171         XCloseDisplay(mDisplay);
00172         mDisplay = 0;
00173 
00174         mInitialized = false;
00175 
00176         Logger::getInstance()->log(Logger::DEBUG, "Display `" + mDisplayName + "\' has been finalized.");
00177   }
00178 
00179  /*----------------------------------------------------------------------*/
00180 
00181   void XDisplay::synchronize(const bool & discard)
00182   {
00183         // The XSync() function flushes the output buffer and then waits until all 
00184         // requests have been received and processed by the X server.
00185         XSync(mDisplay, discard ? True : False);
00186   }
00187 
00188  /*----------------------------------------------------------------------*/
00189 
00190   s32 XDisplay::findBestVisual(const s32 & screenNumber, const s32 & multiSample)
00191   {
00192         XVisualInfo theTemplate;
00193         XVisualInfo *visuals;
00194         int numVisuals;
00195         long mask;
00196         int i;
00197         VisualAttribs bestVis;
00198 
00199         // get list of all visuals on this screen 
00200         theTemplate.screen = screenNumber;
00201         mask = VisualScreenMask;
00202         visuals = XGetVisualInfo(mDisplay, mask, &theTemplate, &numVisuals);
00203         if(numVisuals == 0 || visuals == 0)
00204         {
00205          // something went wrong 
00206          if(visuals)
00207                 XFree(visuals);
00208          return -1;
00209         }
00210         // init bestVis with first visual info 
00211         getVisualAttribs(&visuals[0], bestVis);
00212 
00213         // try to find a "better" visual 
00214         for(i = 1; i < numVisuals; i++)
00215         {
00216          VisualAttribs vis;
00217 
00218          getVisualAttribs(&visuals[i], vis);
00219 
00220          // always skip visuals that are slow 
00221          if(vis.visualCaveat == GLX_SLOW_VISUAL_EXT)
00222                 continue;
00223 
00224          // skip visual if it doesn't have the desired number of multisamples 
00225          if(multiSample != -1 && vis.numSamples != multiSample)
00226                 continue;
00227 
00228          // see if this vis is better than bestVis 
00229          if((!bestVis.supportsGL && vis.supportsGL) || (bestVis.visualCaveat != GLX_NONE_EXT)
00230            || (!bestVis.rgba && vis.rgba) || (!bestVis.doubleBuffer && vis.doubleBuffer)
00231            || (bestVis.redSize < vis.redSize) || (bestVis.greenSize < vis.greenSize)
00232            || (bestVis.blueSize < vis.blueSize) || (bestVis.alphaSize < vis.alphaSize)
00233            || (bestVis.depthSize < vis.depthSize) || (bestVis.stencilSize < vis.stencilSize)
00234            || (bestVis.accumRedSize < vis.accumRedSize))
00235          {
00236                 // found a better visual 
00237                 bestVis = vis;
00238          }
00239 
00240         }
00241 
00242         XFree(visuals);
00243 
00244         // We found no visual with the desired FSAA
00245         if(multiSample != -1 && bestVis.numSamples != multiSample)
00246          return -1;
00247 
00248         Logger::getInstance()->log(Logger::DEBUG,
00249                                  std::string("Found visual attributes: ") +
00250                                  (bestVis.supportsGL ? "OpenGL;" : "no OpenGL;") +
00251                                  (bestVis.doubleBuffer ? "double;" : "single;") + "R" +
00252                                  StringConverter::toString(bestVis.redSize) + "G" +
00253                                  StringConverter::toString(bestVis.greenSize) + "B" +
00254                                  StringConverter::toString(bestVis.blueSize) + "A" +
00255                                  StringConverter::toString(bestVis.alphaSize) + "-Z" +
00256                                  StringConverter::toString(bestVis.depthSize));
00257 
00258         return bestVis.id;
00259   }
00260 
00261  /*----------------------------------------------------------------------*/
00262 
00263   void XDisplay::getVisualAttribs(XVisualInfo * vInfo, VisualAttribs & attribs)
00264   {
00265         const char *ext = glXQueryExtensionsString(mDisplay, vInfo->screen);
00266 
00267         // initialize with zeros
00268         memset(&attribs, 0, sizeof(VisualAttribs));
00269 
00270         attribs.id = vInfo->visualid;
00271         attribs.klass = vInfo->c_class;
00272 
00273         attribs.depth = vInfo->depth;
00274         attribs.redMask = vInfo->red_mask;
00275         attribs.greenMask = vInfo->green_mask;
00276         attribs.blueMask = vInfo->blue_mask;
00277         attribs.colormapSize = vInfo->colormap_size;
00278         attribs.bitsPerRGB = vInfo->bits_per_rgb;
00279 
00280         if(glXGetConfig(mDisplay, vInfo, GLX_USE_GL, &attribs.supportsGL) != 0)
00281          return;
00282         glXGetConfig(mDisplay, vInfo, GLX_BUFFER_SIZE, &attribs.bufferSize);
00283         glXGetConfig(mDisplay, vInfo, GLX_LEVEL, &attribs.level);
00284         glXGetConfig(mDisplay, vInfo, GLX_RGBA, &attribs.rgba);
00285         glXGetConfig(mDisplay, vInfo, GLX_DOUBLEBUFFER, &attribs.doubleBuffer);
00286         glXGetConfig(mDisplay, vInfo, GLX_STEREO, &attribs.stereo);
00287         glXGetConfig(mDisplay, vInfo, GLX_AUX_BUFFERS, &attribs.auxBuffers);
00288         glXGetConfig(mDisplay, vInfo, GLX_RED_SIZE, &attribs.redSize);
00289         glXGetConfig(mDisplay, vInfo, GLX_GREEN_SIZE, &attribs.greenSize);
00290         glXGetConfig(mDisplay, vInfo, GLX_BLUE_SIZE, &attribs.blueSize);
00291         glXGetConfig(mDisplay, vInfo, GLX_ALPHA_SIZE, &attribs.alphaSize);
00292         glXGetConfig(mDisplay, vInfo, GLX_DEPTH_SIZE, &attribs.depthSize);
00293         glXGetConfig(mDisplay, vInfo, GLX_STENCIL_SIZE, &attribs.stencilSize);
00294         glXGetConfig(mDisplay, vInfo, GLX_ACCUM_RED_SIZE, &attribs.accumRedSize);
00295         glXGetConfig(mDisplay, vInfo, GLX_ACCUM_GREEN_SIZE, &attribs.accumGreenSize);
00296         glXGetConfig(mDisplay, vInfo, GLX_ACCUM_BLUE_SIZE, &attribs.accumBlueSize);
00297         glXGetConfig(mDisplay, vInfo, GLX_ACCUM_ALPHA_SIZE, &attribs.accumAlphaSize);
00298 
00299         // get transparent pixel stuff 
00300         glXGetConfig(mDisplay, vInfo, GLX_TRANSPARENT_TYPE, &attribs.transparentType);
00301         if(attribs.transparentType == GLX_TRANSPARENT_RGB)
00302         {
00303          glXGetConfig(mDisplay, vInfo, GLX_TRANSPARENT_RED_VALUE, &attribs.transparentRedValue);
00304          glXGetConfig(mDisplay, vInfo, GLX_TRANSPARENT_GREEN_VALUE, &attribs.transparentGreenValue);
00305          glXGetConfig(mDisplay, vInfo, GLX_TRANSPARENT_BLUE_VALUE, &attribs.transparentBlueValue);
00306          glXGetConfig(mDisplay, vInfo, GLX_TRANSPARENT_ALPHA_VALUE, &attribs.transparentAlphaValue);
00307         } else if(attribs.transparentType == GLX_TRANSPARENT_INDEX)
00308         {
00309          glXGetConfig(mDisplay, vInfo, GLX_TRANSPARENT_INDEX_VALUE, &attribs.transparentIndexValue);
00310         }
00311         // multisample attribs 
00312         if(ext && strstr("GLX_ARB_multisample", ext) == 0)
00313         {
00314          glXGetConfig(mDisplay, vInfo, GLX_SAMPLE_BUFFERS_ARB, &attribs.numMultisample);
00315          glXGetConfig(mDisplay, vInfo, GLX_SAMPLES_ARB, &attribs.numSamples);
00316         } else
00317         {
00318          attribs.numSamples = 0;
00319          attribs.numMultisample = 0;
00320         }
00321 
00322         if(ext && strstr(ext, "GLX_EXT_visual_rating"))
00323         {
00324          glXGetConfig(mDisplay, vInfo, GLX_VISUAL_CAVEAT_EXT, &attribs.visualCaveat);
00325         } else
00326         {
00327          attribs.visualCaveat = GLX_NONE_EXT;
00328         }
00329   }
00330 
00331  /*----------------------------------------------------------------------*/
00332 
00333   void XDisplay::initializeMT()
00334   {
00335         if((mXMTSupported = XInitThreads() != 0))
00336          Logger::getInstance()->log(Logger::NOTICE, "Multi-threading is initialized for Xlib. ");
00337         else
00338          Logger::getInstance()->log(Logger::WARNING,
00339                                    "No multi-threading is supported for your Xlib. No warranty for thread safeness. Some crashes might be occured.");
00340 
00341         // Also set error handler
00342         XSetErrorHandler(XDisplay::errorHandler);
00343         Logger::getInstance()->log(Logger::NOTICE, "Error handler registered for X errors");
00344 
00345         mXMTInitialized = true;
00346   }
00347 
00348  /*----------------------------------------------------------------------*/
00349 
00350 }