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 }