00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include "../include/PCMXDisplay.h"
00030
00031 #include "../include/PCMStringConverter.h"
00032
00033 namespace ParCompMark
00034 {
00035
00036
00037
00038
00039
00040 const s32 XDisplay::IGNOREMULTISAMPLE = -1;
00041 const s32 XDisplay::UNKNOWNDIMENSION = 0;
00042
00043
00044
00045
00046
00047 bool XDisplay::mXMTInitialized = false;
00048 bool XDisplay::mXMTSupported = false;
00049 Mutex XDisplay::mErrorHandlerMutex;
00050 bool XDisplay::mTolerateErrors = false;
00051
00052
00053
00054
00055
00056 XDisplay::XDisplay(const std::string & displayName)
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
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
00091
00092
00093 int XDisplay::errorHandler(Display * display, XErrorEvent * errorEvent)
00094 {
00095
00096 if(mTolerateErrors)
00097 return 0;
00098
00099
00100 mErrorHandlerMutex.lock();
00101
00102 const u32 bufSize = 10240;
00103 char buffer_return[bufSize];
00104
00105 memset(buffer_return, 0, bufSize);
00106
00107
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
00118 mErrorHandlerMutex.unlock();
00119
00120
00121 Except(XLIB_ERROR, "XDisplay::errorHandler()", errorMessage);
00122
00123 return 0;
00124 }
00125
00126
00127
00128
00129
00130
00131
00132 void XDisplay::initialize()
00133 {
00134 Assert(!mInitialized, INVALID_OPERATION_ERROR, "XDisplay::initialize()");
00135
00136
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
00146 Assert(mDisplay, INVALID_NAME_ERROR, "XDisplay::initialize()");
00147
00148
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
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
00184
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
00200 theTemplate.screen = screenNumber;
00201 mask = VisualScreenMask;
00202 visuals = XGetVisualInfo(mDisplay, mask, &theTemplate, &numVisuals);
00203 if(numVisuals == 0 || visuals == 0)
00204 {
00205
00206 if(visuals)
00207 XFree(visuals);
00208 return -1;
00209 }
00210
00211 getVisualAttribs(&visuals[0], bestVis);
00212
00213
00214 for(i = 1; i < numVisuals; i++)
00215 {
00216 VisualAttribs vis;
00217
00218 getVisualAttribs(&visuals[i], vis);
00219
00220
00221 if(vis.visualCaveat == GLX_SLOW_VISUAL_EXT)
00222 continue;
00223
00224
00225 if(multiSample != -1 && vis.numSamples != multiSample)
00226 continue;
00227
00228
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
00237 bestVis = vis;
00238 }
00239
00240 }
00241
00242 XFree(visuals);
00243
00244
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
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
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
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
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 }