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/PCMGLXRenderWindow.h"
00030
00031 #include "../include/PCMProcess.h"
00032
00033 #include "../include/PCMStringConverter.h"
00034
00035
00036
00037
00038
00039 #include <GL/gl.h>
00040 #include <GL/glu.h>
00041 #if defined(HAVE_LIBXRANDR)
00042 # include <X11/extensions/Xrandr.h>
00043 #endif
00044
00045 namespace ParCompMark
00046 {
00047
00048
00049
00050
00051
00052 const s32 GLXRenderWindow::CENTERED = -1;
00053 const u32 GLXRenderWindow::MAXIMALSIZE = 0;
00054 const Real GLXRenderWindow::UNDEFINEDSTATISTICS = -1.0;
00055 const s32 GLXRenderWindow::UNDEFINEDXRRCONFIGURATION = -1;
00056 const u32 GLXRenderWindow::DEFAULTWINDOWWIDTH = 128;
00057 const u32 GLXRenderWindow::DEFAULTWINDOWHEIGHT = 128;
00058
00059
00060
00061
00062
00063 GLXRenderWindow::GLXRenderWindow(XDisplay::Pointer & display, Process * process, const std::string caption,
00064 const bool & fullScreen, const u32 & colourDepth,
00065 const u32 & width, const u32 & height, const s32 & left,
00066 const s32 & top, const u32 & fsaaSamples):
00067
00068 mDisplay(display
00069 ),
00070
00071 mProcess(process
00072 )
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096 {
00097 mWindow = 0;
00098 mInitialized = false;
00099 mVisible = false;
00100 mFullScreen = fullScreen;
00101 mCaption = caption;
00102 mLeft = left;
00103 mTop = top;
00104 mWidth = width;
00105 mHeight = height;
00106 mColourDepth = colourDepth;
00107 mFSAASamples = fsaaSamples;
00108 mOriginalXRRConfiguation = UNDEFINEDXRRCONFIGURATION;
00109
00110
00111 resetStatistics();
00112 }
00113
00114
00115
00116 GLXRenderWindow::~GLXRenderWindow()
00117 {
00118 if(mInitialized)
00119 finalize();
00120 }
00121
00122
00123
00124
00125
00126
00127
00128 void GLXRenderWindow::setCurrent()
00129 {
00130 mGLXGLContext.lock();
00131 mGLXGLContext->setCurrent();
00132 mGLXGLContext.unlock();
00133 }
00134
00135
00136
00137 void GLXRenderWindow::releaseCurrent()
00138 {
00139 mGLXGLContext.lock();
00140 mGLXGLContext->releaseCurrent();
00141 mGLXGLContext.unlock();
00142 }
00143
00144
00145
00146 void GLXRenderWindow::initialize()
00147 {
00148 Assert(!mInitialized, INVALID_OPERATION_ERROR, "GLXRenderWindow::initalize()");
00149
00150
00151 createWindow();
00152
00153
00154 mSumTriangleCount = 0.0;
00155 mSumFPS = 0.0;
00156
00157
00158 mWindowStatistics.frameCount = 0;
00159
00160 mInitialized = true;
00161 }
00162
00163
00164
00165 void GLXRenderWindow::finalize()
00166 {
00167 Assert(mInitialized, INVALID_OPERATION_ERROR, "GLXRenderWindow::finalize()");
00168
00169
00170
00171
00172 destroyWindow();
00173
00174 mGLXGLContext.lock();
00175 mGLXGLContext->finalize();
00176 mGLXGLContext.unlock();
00177
00178
00179 mGLXGLContext.kill();
00180
00181 mInitialized = false;
00182
00183 }
00184
00185
00186
00187 void GLXRenderWindow::resetStatistics()
00188 {
00189 mWindowStatistics.lastTriangleCount = 0;
00190 mWindowStatistics.frameCount = 0;
00191
00192
00193 mWindowStatistics.lastFrameTime = UNDEFINEDSTATISTICS;
00194 mWindowStatistics.bestFrameTime = UNDEFINEDSTATISTICS;
00195 mWindowStatistics.worstFrameTime = UNDEFINEDSTATISTICS;
00196
00197 mWindowStatistics.avgTriangleCount = UNDEFINEDSTATISTICS;
00198 mWindowStatistics.maxTriangleCount = UNDEFINEDSTATISTICS;
00199 mWindowStatistics.minTriangleCount = UNDEFINEDSTATISTICS;
00200
00201 mWindowStatistics.lastFPS = UNDEFINEDSTATISTICS;
00202 mWindowStatistics.avgFPS = UNDEFINEDSTATISTICS;
00203 mWindowStatistics.bestFPS = UNDEFINEDSTATISTICS;
00204 mWindowStatistics.worstFPS = UNDEFINEDSTATISTICS;
00205
00206
00207 mRenderingBeginTime = mWindowStatistics.frameBeginTime = Timer::getSystemTime();
00208
00209
00210 mFPSMeasuringBeginTime = Timer::getSystemTime();
00211 mFPSMeasuringFrameCount = 0;
00212 }
00213
00214
00215
00216 void GLXRenderWindow::reportTriangles(const u32 & triangleCount)
00217 {
00218 mWindowStatistics.lastTriangleCount += triangleCount;
00219 }
00220
00221
00222
00223 void GLXRenderWindow::createWindow()
00224 {
00225 mDisplay.lock();
00226
00227
00228 if(!mDisplay->getInitialized())
00229 mDisplay->initialize();
00230
00231 ::Display * display = mDisplay->getDisplay();
00232
00233
00234
00235 int screen = DefaultScreen(display);
00236 int depth = DisplayPlanes(display, screen);
00237 Window rootWindow = RootWindow(display, screen);
00238 Window parentWindow = rootWindow;
00239
00240
00241 if(mWidth == MAXIMALSIZE)
00242 mWidth = mDisplay->getWidth();
00243 if(mHeight == MAXIMALSIZE)
00244 mWidth = mDisplay->getHeight();
00245 if(mLeft == CENTERED)
00246 mLeft = (mDisplay->getWidth() - mWidth) / 2;
00247 if(mTop == CENTERED)
00248 mTop = (mDisplay->getHeight() - mHeight) / 2;
00249
00250
00251 if(!mFullScreen && mFSAASamples > 0)
00252 {
00253 Logger::getInstance()->log(Logger::WARNING, "FSAA only supported in fullscreen mode");
00254 mFSAASamples = 0;
00255 }
00256 #ifdef HAVE_LIBXRANDR
00257
00258 int dummy;
00259
00260 if(mFullScreen && !XQueryExtension(display, "RANDR", &dummy, &dummy, &dummy))
00261 {
00262 Logger::getInstance()->log(Logger::WARNING,
00263 "Could not switch to full screen mode: No XRANDR extension found");
00264 } else if(mFullScreen)
00265 {
00266
00267
00268 XRRScreenConfiguration *config;
00269 XRRScreenSize *sizes;
00270 Rotation current_rotation;
00271 int nsizes;
00272
00273
00274 config = XRRGetScreenInfo(display, rootWindow);
00275
00276 if(config)
00277 sizes = XRRConfigSizes(config, &nsizes);
00278
00279 if(config && nsizes > 0)
00280 {
00281
00282 mOriginalXRRConfiguation = XRRConfigCurrentConfiguration(config, ¤t_rotation);
00283
00284 int mode = -1;
00285 int mode_width = INT_MAX;
00286 int mode_height = INT_MAX;
00287
00288 for(int i = 0; i < nsizes; i++)
00289 {
00290 if((u32) sizes[i].width >= mWidth && (u32) sizes[i].height >= mHeight && sizes[i].width < mode_width
00291 && sizes[i].height < mode_height)
00292 {
00293 mode = i;
00294 mode_width = sizes[i].width;
00295 mode_height = sizes[i].height;
00296 }
00297 }
00298 if(mode >= 0)
00299 {
00300
00301 Logger::getInstance()->log(Logger::NOTICE, "Entering full screen mode");
00302
00303 XRRSetScreenConfig(display, config, rootWindow, mode, current_rotation, CurrentTime);
00304 } else
00305 {
00306 Logger::getInstance()->log(Logger::WARNING,
00307 "Could not switch to full screen mode: No conforming mode was found");
00308 }
00309
00310 XRRFreeScreenConfigInfo(config);
00311 } else
00312 {
00313 Logger::getInstance()->log(Logger::WARNING,
00314 "Could not switch to full screen mode: XRRGetScreenInfo failed");
00315 }
00316 }
00317 #endif
00318
00319 XVisualInfo *visualInfo = NULL;
00320
00321
00322 int best_visual = mDisplay->findBestVisual(screen, mFSAASamples);
00323
00324 if(best_visual == -1)
00325 {
00326 best_visual = mDisplay->findBestVisual(screen);
00327 Logger::getInstance()->log(Logger::WARNING,
00328 "Requested FSAA was not acquirable, defaulting to first suitable visual");
00329 }
00330
00331 XVisualInfo templ;
00332 int nmatch;
00333
00334 templ.visualid = best_visual;
00335 visualInfo = XGetVisualInfo(display, VisualIDMask, &templ, &nmatch);
00336 Assert(visualInfo && nmatch, INVALID_OPERATION_ERROR, "GLXRenderWindow::createWindow()");
00337
00338 XSetWindowAttributes attr;
00339 unsigned long mask;
00340
00341 attr.background_pixel = 0;
00342 attr.border_pixel = 0;
00343 attr.colormap = XCreateColormap(display, rootWindow, visualInfo->visual, AllocNone);
00344 attr.event_mask = StructureNotifyMask | VisibilityChangeMask;
00345 if(mFullScreen)
00346 {
00347 mask = CWBackPixel | CWColormap | CWOverrideRedirect | CWSaveUnder | CWBackingStore | CWEventMask;
00348 attr.override_redirect = True;
00349 attr.backing_store = NotUseful;
00350 attr.save_under = False;
00351
00352
00353 mLeft = mTop = 0;
00354 mWidth = (u32) DisplayWidth(display, screen);
00355 mHeight = (u32) DisplayHeight(display, screen);
00356
00357 } else
00358 mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
00359
00360
00361 mWindow =
00362 XCreateWindow(display, parentWindow, mLeft, mTop, mWidth, mHeight, 0, visualInfo->depth, InputOutput,
00363 visualInfo->visual, mask, &attr);
00364 Assert(mWindow, INVALID_OPERATION_ERROR, "GLXRenderWindow::createWindow()");
00365
00366
00367 XWMHints *wm_hints;
00368
00369 if((wm_hints = XAllocWMHints()) != NULL)
00370 {
00371 wm_hints->initial_state = NormalState;
00372 wm_hints->input = True;
00373 wm_hints->flags = StateHint | InputHint;
00374
00375
00376 if(depth == 24 || depth == 32)
00377 {
00378
00379
00380
00381 }
00382 }
00383
00384 XSizeHints *size_hints;
00385
00386 if((size_hints = XAllocSizeHints()) != NULL)
00387 {
00388
00389 size_hints->flags = USPosition;
00390 }
00391
00392 XTextProperty titleprop;
00393 char *lst = (char *) mCaption.c_str();
00394
00395 XStringListToTextProperty((char **) &lst, 1, &titleprop);
00396
00397 XSetWMProperties(display, mWindow, &titleprop, NULL, NULL, 0, size_hints, wm_hints, NULL);
00398
00399
00400
00401 XFree(titleprop.value);
00402 XFree(wm_hints);
00403 XFree(size_hints);
00404
00405
00406
00407 mAtomDeleteWindow = XInternAtom(display, "WM_DELETE_WINDOW", False);
00408 XSetWMProtocols(display, mWindow, &mAtomDeleteWindow, 1);
00409
00410
00411 XMapWindow(display, mWindow);
00412
00413
00414
00415 XFlush(display);
00416
00417
00418 mDisplay.unlock();
00419
00420
00421 mGLXGLContext = new GLXGLContext(mDisplay, this, visualInfo);
00422 mGLXGLContext.lock();
00423 mGLXGLContext->initialize();
00424 mGLXGLContext.unlock();
00425
00426
00427 XFree(visualInfo);
00428
00429 Logger::getInstance()->log(Logger::NOTICE,
00430 "GLX Window `" + mCaption + "\' has been created on display `" +
00431 mDisplay->getDisplayName() + "\'");
00432 }
00433
00434
00435
00436 void GLXRenderWindow::destroyWindow()
00437 {
00438 Assert(mWindow, NULL_POINTER_ERROR, "GLXRenderWindow::destroyWindow()");
00439
00440 mDisplay.lock();
00441 XDestroyWindow(mDisplay->getDisplay(), mWindow);
00442 mDisplay.unlock();
00443
00444 Logger::getInstance()->log(Logger::NOTICE, "GLX Window: `" + mCaption + "\' has been destroyed.");
00445 }
00446
00447
00448
00449 void GLXRenderWindow::updateStatistics()
00450 {
00451 mWindowStatistics.frameCount++;
00452 mWindowStatistics.renderingTime = mWindowStatistics.frameEndTime - mRenderingBeginTime;
00453
00454
00455
00456
00457 mWindowStatistics.lastFrameTime = mWindowStatistics.frameEndTime - mWindowStatistics.frameBeginTime;
00458 if(mWindowStatistics.bestFrameTime == UNDEFINEDSTATISTICS)
00459 {
00460 mWindowStatistics.bestFrameTime = mWindowStatistics.lastFrameTime;
00461 } else
00462 {
00463 mWindowStatistics.bestFrameTime =
00464 mWindowStatistics.lastFrameTime <
00465 mWindowStatistics.bestFrameTime ? mWindowStatistics.lastFrameTime : mWindowStatistics.bestFrameTime;
00466 }
00467
00468 if(mWindowStatistics.worstFrameTime == UNDEFINEDSTATISTICS)
00469 {
00470 mWindowStatistics.worstFrameTime = mWindowStatistics.lastFrameTime;
00471 } else
00472 {
00473 mWindowStatistics.worstFrameTime =
00474 mWindowStatistics.lastFrameTime >
00475 mWindowStatistics.worstFrameTime ? mWindowStatistics.lastFrameTime : mWindowStatistics.worstFrameTime;
00476 }
00477
00478
00479
00480
00481 if(mWindowStatistics.minTriangleCount == UNDEFINEDSTATISTICS)
00482 {
00483 mWindowStatistics.minTriangleCount = mWindowStatistics.lastTriangleCount;
00484 } else
00485 {
00486 mWindowStatistics.minTriangleCount =
00487 mWindowStatistics.lastTriangleCount <
00488 mWindowStatistics.minTriangleCount ? mWindowStatistics.lastTriangleCount : mWindowStatistics.
00489 minTriangleCount;
00490 }
00491
00492 if(mWindowStatistics.maxTriangleCount == UNDEFINEDSTATISTICS)
00493 {
00494 mWindowStatistics.maxTriangleCount = mWindowStatistics.lastTriangleCount;
00495 } else
00496 {
00497 mWindowStatistics.maxTriangleCount =
00498 mWindowStatistics.lastTriangleCount >
00499 mWindowStatistics.maxTriangleCount ? mWindowStatistics.lastTriangleCount : mWindowStatistics.
00500 maxTriangleCount;
00501 }
00502
00503 mSumTriangleCount += mWindowStatistics.lastTriangleCount;
00504 mWindowStatistics.avgTriangleCount = mSumTriangleCount / mWindowStatistics.frameCount;
00505
00506
00507
00508
00509 mFPSMeasuringFrameCount++;
00510 Real delay = Timer::getSystemTime() - mFPSMeasuringBeginTime;
00511
00512 if(delay >= 1.0)
00513 {
00514 mWindowStatistics.lastFPS = mFPSMeasuringFrameCount / delay;
00515 mFPSMeasuringFrameCount = 0;
00516 mFPSMeasuringBeginTime = Timer::getSystemTime();
00517 }
00518
00519 if(mWindowStatistics.bestFPS == UNDEFINEDSTATISTICS)
00520 {
00521 mWindowStatistics.bestFPS = mWindowStatistics.lastFPS;
00522 } else
00523 {
00524 mWindowStatistics.bestFPS =
00525 mWindowStatistics.lastFPS >
00526 mWindowStatistics.bestFPS ? mWindowStatistics.lastFPS : mWindowStatistics.bestFPS;
00527 }
00528
00529 if(mWindowStatistics.worstFPS == UNDEFINEDSTATISTICS)
00530 {
00531 mWindowStatistics.worstFPS = mWindowStatistics.lastFPS;
00532 } else
00533 {
00534 mWindowStatistics.worstFPS =
00535 mWindowStatistics.lastFPS <
00536 mWindowStatistics.worstFPS ? mWindowStatistics.lastFPS : mWindowStatistics.worstFPS;
00537 }
00538
00539 if(mWindowStatistics.renderingTime > Timer::EPSILONDELAY)
00540 {
00541 mWindowStatistics.avgFPS = mWindowStatistics.frameCount / mWindowStatistics.renderingTime;
00542 }
00543
00544
00545
00546 setCaption(mCaption);
00547 }
00548
00549
00550
00551 void GLXRenderWindow::_setCaption()
00552 {
00553 mDisplay.lock();
00554 XStoreName(mDisplay->getDisplay(), mWindow,
00555 (mCaption + " @" + StringConverter::toString(mWindowStatistics.lastFPS, 6, 2) + " fps, frame #" +
00556 StringConverter::toString((*(mProcess->getContexts().begin()))->getFrameID())).c_str());
00557 mDisplay.unlock();
00558
00559 }
00560
00561
00562
00563 }