[657] | 1 | /*
|
---|
| 2 | -----------------------------------------------------------------------------
|
---|
| 3 | This source file is part of OGRE
|
---|
| 4 | (Object-oriented Graphics Rendering Engine)
|
---|
| 5 | For the latest info, see http://www.ogre3d.org/
|
---|
| 6 |
|
---|
| 7 | Copyright (c) 2000-2005 The OGRE Team
|
---|
| 8 | Also see acknowledgements in Readme.html
|
---|
| 9 |
|
---|
| 10 | This program is free software; you can redistribute it and/or modify it under
|
---|
| 11 | the terms of the GNU Lesser General Public License as published by the Free Software
|
---|
| 12 | Foundation; either version 2 of the License, or (at your option) any later
|
---|
| 13 | version.
|
---|
| 14 |
|
---|
| 15 | This program is distributed in the hope that it will be useful, but WITHOUT
|
---|
| 16 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
---|
| 17 | FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
---|
| 18 |
|
---|
| 19 | You should have received a copy of the GNU Lesser General Public License along with
|
---|
| 20 | this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
---|
| 21 | Place - Suite 330, Boston, MA 02111-1307, USA, or go to
|
---|
| 22 | http://www.gnu.org/copyleft/lesser.txt.
|
---|
| 23 | -----------------------------------------------------------------------------
|
---|
| 24 | */
|
---|
| 25 |
|
---|
| 26 | #include "OgreGLXWindow.h"
|
---|
| 27 | #include "OgreRoot.h"
|
---|
| 28 | #include "OgreGLRenderSystem.h"
|
---|
| 29 | #include "OgreImageCodec.h"
|
---|
| 30 | #include "OgreException.h"
|
---|
| 31 | #include "OgreLogManager.h"
|
---|
| 32 | #include "OgreStringConverter.h"
|
---|
| 33 | #include "OgreGLXUtils.h"
|
---|
| 34 |
|
---|
| 35 | #include <iostream>
|
---|
| 36 | #include <algorithm>
|
---|
| 37 | #include <sys/time.h>
|
---|
| 38 | #include <climits>
|
---|
| 39 |
|
---|
| 40 | #include <X11/Xlib.h>
|
---|
| 41 | #include <X11/keysym.h>
|
---|
| 42 |
|
---|
| 43 | #ifndef NO_XRANDR
|
---|
| 44 | #include <X11/extensions/Xrandr.h>
|
---|
| 45 | #endif
|
---|
| 46 |
|
---|
| 47 | #include <GL/gl.h>
|
---|
| 48 | #include <GL/glu.h>
|
---|
| 49 | #include <GL/glx.h>
|
---|
| 50 |
|
---|
| 51 |
|
---|
| 52 | namespace Ogre {
|
---|
| 53 |
|
---|
| 54 | GLXWindow::GLXWindow(Display *display) :
|
---|
| 55 | mDisplay(display),
|
---|
| 56 | mWindow(0),
|
---|
| 57 | mGlxContext(0),
|
---|
| 58 | mClosed(false),mFullScreen(false), mOldMode(-1),
|
---|
| 59 | mContext(0) {
|
---|
| 60 | mActive = false;
|
---|
| 61 | }
|
---|
| 62 |
|
---|
| 63 | GLXWindow::~GLXWindow() {
|
---|
| 64 | if(mGlxContext)
|
---|
| 65 | glXDestroyContext(mDisplay, mGlxContext);
|
---|
| 66 | if(mWindow)
|
---|
| 67 | XDestroyWindow(mDisplay, mWindow);
|
---|
| 68 | #ifndef NO_XRANDR
|
---|
| 69 |
|
---|
| 70 | if(mFullScreen) {
|
---|
| 71 | // Restore original video mode.
|
---|
| 72 | Window rootWindow = DefaultRootWindow(mDisplay);
|
---|
| 73 | XRRScreenConfiguration *config;
|
---|
| 74 |
|
---|
| 75 | // Get current screen info
|
---|
| 76 | config = XRRGetScreenInfo(mDisplay, rootWindow);
|
---|
| 77 | if(config) {
|
---|
| 78 | Rotation current_rotation;
|
---|
| 79 | XRRConfigCurrentConfiguration (config, ¤t_rotation);
|
---|
| 80 | //std::cerr << "Restore mode " << mOldMode << std::endl;
|
---|
| 81 | LogManager::getSingleton().logMessage("GLXWindow::~GLXWindow -- Leaving full screen mode");
|
---|
| 82 | XRRSetScreenConfig(mDisplay, config, rootWindow, mOldMode, current_rotation, CurrentTime);
|
---|
| 83 | XRRFreeScreenConfigInfo(config);
|
---|
| 84 | } else {
|
---|
| 85 | LogManager::getSingleton().logMessage("GLXWindow::~GLXWindow -- Could not switch from full screen mode: XRRGetScreenInfo failed");
|
---|
| 86 | }
|
---|
| 87 | }
|
---|
| 88 | #endif
|
---|
| 89 | }
|
---|
| 90 |
|
---|
| 91 | void GLXWindow::create(const String& name, unsigned int width, unsigned int height,
|
---|
| 92 | bool fullScreen, const NameValuePairList *miscParams)
|
---|
| 93 | {
|
---|
| 94 | LogManager::getSingleton().logMessage("GLXWindow::create");
|
---|
| 95 |
|
---|
| 96 | String title = name;
|
---|
| 97 | size_t fsaa_samples = 0;
|
---|
| 98 |
|
---|
| 99 | // We will attempt to create new window on default screen op display 0
|
---|
| 100 | // unless external window handle passed below
|
---|
| 101 | int screen = DefaultScreen(mDisplay);
|
---|
| 102 | int depth = DisplayPlanes(mDisplay, screen);
|
---|
| 103 | Window rootWindow = RootWindow(mDisplay,screen);
|
---|
| 104 | Window parentWindow = rootWindow;
|
---|
| 105 |
|
---|
| 106 | // Make sure the window is centered if no left and top in parameters
|
---|
| 107 | size_t left = (int)DisplayWidth(mDisplay, screen)/2 - width/2;
|
---|
| 108 | size_t top = (int)DisplayHeight(mDisplay, screen)/2 - height/2;
|
---|
| 109 |
|
---|
| 110 | // Maybe user already created the window and passed its visualinfo in miscParams
|
---|
| 111 | XVisualInfo * extVisualHandler = NULL;
|
---|
| 112 |
|
---|
| 113 | // Unless parentWindowHandle is given in miscParams we're top-level
|
---|
| 114 | mTopLevel = true;
|
---|
| 115 |
|
---|
| 116 | LogManager::getSingleton().logMessage("Parsing miscParams");
|
---|
| 117 | if(miscParams)
|
---|
| 118 | {
|
---|
| 119 | // Parse miscellenous parameters
|
---|
| 120 | NameValuePairList::const_iterator opt;
|
---|
| 121 | // Full screen anti aliasing
|
---|
| 122 | opt = miscParams->find("FSAA");
|
---|
| 123 | if(opt != miscParams->end()) //check for FSAA parameter, if not ignore it...
|
---|
| 124 | fsaa_samples = StringConverter::parseUnsignedInt(opt->second);
|
---|
| 125 | // left (x)
|
---|
| 126 | opt = miscParams->find("left");
|
---|
| 127 | if(opt != miscParams->end())
|
---|
| 128 | left = StringConverter::parseUnsignedInt(opt->second);
|
---|
| 129 | // top (y)
|
---|
| 130 | opt = miscParams->find("top");
|
---|
| 131 | if(opt != miscParams->end())
|
---|
| 132 | top = StringConverter::parseUnsignedInt(opt->second);
|
---|
| 133 | // Window title
|
---|
| 134 | opt = miscParams->find("title");
|
---|
| 135 | if(opt != miscParams->end()) //check for FSAA parameter, if not ignore it...
|
---|
| 136 | title = opt->second;
|
---|
| 137 | opt = miscParams->find("parentWindowHandle");
|
---|
| 138 | if(opt != miscParams->end()) { // embedding OGRE
|
---|
| 139 | std::vector<String> tokens = StringUtil::split(opt->second, " :");
|
---|
| 140 | String new_display = tokens[0];
|
---|
| 141 | String new_screen = tokens[1];
|
---|
| 142 | String wid = tokens[2];
|
---|
| 143 |
|
---|
| 144 | // Now set things to their correct values
|
---|
| 145 | // This must be the ugliest line of code I have ever written :P
|
---|
| 146 | mDisplay = reinterpret_cast<Display*>(StringConverter::parseUnsignedLong(new_display));
|
---|
| 147 | screen = StringConverter::parseUnsignedInt(new_screen);
|
---|
| 148 | parentWindow = StringConverter::parseUnsignedLong(wid);
|
---|
| 149 |
|
---|
| 150 | depth = DisplayPlanes(mDisplay, screen);
|
---|
| 151 | rootWindow = RootWindow(mDisplay, screen);
|
---|
| 152 |
|
---|
| 153 | left = top = 0;
|
---|
| 154 | fullScreen = false; // Can't be full screen if embedded in an app!
|
---|
| 155 | mTopLevel = false; // Can't be top-level if embedded
|
---|
| 156 | }
|
---|
| 157 |
|
---|
| 158 | opt = miscParams->find("externalWindowHandle");
|
---|
| 159 | if(opt != miscParams->end()) // embedding OGRE in already created window
|
---|
| 160 | {
|
---|
| 161 | std::vector<String> tokens = StringUtil::split(opt->second, " :");
|
---|
| 162 | String new_display = tokens[0];
|
---|
| 163 | String new_screen = tokens[1];
|
---|
| 164 | String wid = tokens[2];
|
---|
| 165 |
|
---|
| 166 | mDisplay = reinterpret_cast<Display*>(StringConverter::parseUnsignedLong(new_display));
|
---|
| 167 | screen = StringConverter::parseUnsignedInt(new_screen);
|
---|
| 168 | mWindow = StringConverter::parseUnsignedLong(wid);
|
---|
| 169 |
|
---|
| 170 | if(tokens.size() > 3) // external visual was already setup
|
---|
| 171 | {
|
---|
| 172 | extVisualHandler = reinterpret_cast<XVisualInfo*>(StringConverter::parseUnsignedLong(tokens[3]));
|
---|
| 173 | }
|
---|
| 174 |
|
---|
| 175 | depth = DisplayPlanes(mDisplay, screen);
|
---|
| 176 | rootWindow = RootWindow(mDisplay, screen);
|
---|
| 177 |
|
---|
| 178 | left = top = 0;
|
---|
| 179 | fullScreen = false; // Can't be full screen if embedded in an app!
|
---|
| 180 | mTopLevel = false; // Can't be top-level if embedded
|
---|
| 181 | }
|
---|
| 182 |
|
---|
| 183 | }
|
---|
| 184 |
|
---|
| 185 | // Check for full screen mode if FSAA was asked for
|
---|
| 186 | if(!fullScreen && fsaa_samples>0)
|
---|
| 187 | {
|
---|
| 188 | LogManager::getSingleton().logMessage("GLXWindow::create -- FSAA only supported in fullscreen mode");
|
---|
| 189 | fsaa_samples = 0;
|
---|
| 190 | }
|
---|
| 191 | // Disable FSAA for now -- it doesn't work on NVIDIA
|
---|
| 192 | fsaa_samples = 0;
|
---|
| 193 |
|
---|
| 194 | #ifndef NO_XRANDR
|
---|
| 195 | // Attempt mode switch for fullscreen -- only if RANDR extension is there
|
---|
| 196 | int dummy;
|
---|
| 197 | if(fullScreen && ! XQueryExtension(mDisplay, "RANDR", &dummy, &dummy, &dummy)) {
|
---|
| 198 | LogManager::getSingleton().logMessage("GLXWindow::create -- Could not switch to full screen mode: No XRANDR extension found");
|
---|
| 199 | } else if(fullScreen) {
|
---|
| 200 | // Use Xrandr extension to switch video modes. This is much better than
|
---|
| 201 | // XVidMode as you can't scroll away from the full-screen applications.
|
---|
| 202 | XRRScreenConfiguration *config;
|
---|
| 203 | XRRScreenSize *sizes;
|
---|
| 204 | Rotation current_rotation;
|
---|
| 205 | int nsizes;
|
---|
| 206 |
|
---|
| 207 | // Get current screen info
|
---|
| 208 | config = XRRGetScreenInfo(mDisplay, rootWindow);
|
---|
| 209 | // Get available sizes
|
---|
| 210 | if(config)
|
---|
| 211 | sizes = XRRConfigSizes (config, &nsizes);
|
---|
| 212 |
|
---|
| 213 | if(config && nsizes > 0) {
|
---|
| 214 | // Get current size and rotation
|
---|
| 215 | mOldMode = XRRConfigCurrentConfiguration (config, ¤t_rotation);
|
---|
| 216 | // Find smallest matching mode
|
---|
| 217 | int mode = -1;
|
---|
| 218 | int mode_width = INT_MAX;
|
---|
| 219 | int mode_height = INT_MAX;
|
---|
| 220 | for(size_t i=0; i<nsizes; i++) {
|
---|
| 221 | if(sizes[i].width >= width && sizes[i].height >= height &&
|
---|
| 222 | sizes[i].width < mode_width && sizes[i].height < mode_height) {
|
---|
| 223 | mode = i;
|
---|
| 224 | mode_width = sizes[i].width;
|
---|
| 225 | mode_height = sizes[i].height;
|
---|
| 226 | }
|
---|
| 227 | }
|
---|
| 228 | if(mode >= 0) {
|
---|
| 229 | // Finally, set the screen configuration
|
---|
| 230 | LogManager::getSingleton().logMessage("GLXWindow::create -- Entering full screen mode");
|
---|
| 231 | XRRSetScreenConfig(mDisplay, config, rootWindow, mode, current_rotation, CurrentTime);
|
---|
| 232 | } else {
|
---|
| 233 | LogManager::getSingleton().logMessage("GLXWindow::create -- Could not switch to full screen mode: No conforming mode was found");
|
---|
| 234 | }
|
---|
| 235 | // Free configuration data
|
---|
| 236 | XRRFreeScreenConfigInfo(config);
|
---|
| 237 | } else {
|
---|
| 238 | LogManager::getSingleton().logMessage("GLXWindow::create -- Could not switch to full screen mode: XRRGetScreenInfo failed");
|
---|
| 239 | }
|
---|
| 240 | }
|
---|
| 241 | #endif
|
---|
| 242 |
|
---|
| 243 | XVisualInfo* visualInfo = NULL;
|
---|
| 244 | if(extVisualHandler == NULL) // user didn't create visual ( and window ) himself
|
---|
| 245 | {
|
---|
| 246 | // Apply some magic algorithm to get the best visual
|
---|
| 247 | int best_visual = GLXUtils::findBestVisual(mDisplay, screen, fsaa_samples);
|
---|
| 248 | if(best_visual == -1)
|
---|
| 249 | {
|
---|
| 250 | best_visual = GLXUtils::findBestVisual(mDisplay, screen);
|
---|
| 251 | LogManager::getSingleton().logMessage("GLXWindow::create -- Requested FSAA of "+
|
---|
| 252 | StringConverter::toString(fsaa_samples)+" was not acquirable, defaulting to first suitable visual");
|
---|
| 253 | }
|
---|
| 254 | LogManager::getSingleton().logMessage("GLXWindow::create -- Best visual is "+StringConverter::toString(best_visual));
|
---|
| 255 |
|
---|
| 256 | // Get information about this so-called-best visual
|
---|
| 257 | XVisualInfo templ;
|
---|
| 258 | int nmatch;
|
---|
| 259 | templ.visualid = best_visual;
|
---|
| 260 | visualInfo = XGetVisualInfo(mDisplay, VisualIDMask, &templ, &nmatch);
|
---|
| 261 | if(visualInfo==0 || nmatch==0) {
|
---|
| 262 | OGRE_EXCEPT(999, "GLXWindow: error choosing visual", "GLXWindow::create");
|
---|
| 263 | }
|
---|
| 264 |
|
---|
| 265 | XSetWindowAttributes attr;
|
---|
| 266 | unsigned long mask;
|
---|
| 267 | attr.background_pixel = 0;
|
---|
| 268 | attr.border_pixel = 0;
|
---|
| 269 | attr.colormap = XCreateColormap(mDisplay,rootWindow,visualInfo->visual,AllocNone);
|
---|
| 270 | attr.event_mask = StructureNotifyMask | KeyPressMask | KeyReleaseMask | PointerMotionMask | ButtonPressMask | ButtonReleaseMask;
|
---|
| 271 | if(fullScreen) {
|
---|
| 272 | mask = CWBackPixel | CWColormap | CWOverrideRedirect | CWSaveUnder | CWBackingStore | CWEventMask;
|
---|
| 273 | attr.override_redirect = True;
|
---|
| 274 | attr.backing_store = NotUseful;
|
---|
| 275 | attr.save_under = False;
|
---|
| 276 | // Fullscreen windows are always in the top left origin
|
---|
| 277 | left = top = 0;
|
---|
| 278 | } else
|
---|
| 279 | mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
|
---|
| 280 |
|
---|
| 281 | // Create window on server
|
---|
| 282 | mWindow = XCreateWindow(mDisplay,parentWindow,left,top,width,height,0,visualInfo->depth,InputOutput,visualInfo->visual,mask,&attr);
|
---|
| 283 | if(!mWindow) {
|
---|
| 284 | OGRE_EXCEPT(999, "GLXWindow: XCreateWindow failed", "GLXWindow::create");
|
---|
| 285 | }
|
---|
| 286 |
|
---|
| 287 | // Make sure the window is in normal state
|
---|
| 288 | XWMHints *wm_hints;
|
---|
| 289 | if ((wm_hints = XAllocWMHints()) != NULL) {
|
---|
| 290 | wm_hints->initial_state = NormalState;
|
---|
| 291 | wm_hints->input = True;
|
---|
| 292 | wm_hints->flags = StateHint | InputHint;
|
---|
| 293 |
|
---|
| 294 | // Check if we can give it an icon
|
---|
| 295 | if(depth == 24 || depth == 32) {
|
---|
| 296 | // Woot! The right bit depth, we can load an icon
|
---|
| 297 | if(GLXUtils::LoadIcon(mDisplay, rootWindow, "GLX_icon.png", &wm_hints->icon_pixmap, &wm_hints->icon_mask))
|
---|
| 298 | wm_hints->flags |= IconPixmapHint | IconMaskHint;
|
---|
| 299 | }
|
---|
| 300 | }
|
---|
| 301 |
|
---|
| 302 | // Set size and location hints
|
---|
| 303 | XSizeHints *size_hints;
|
---|
| 304 | if ((size_hints = XAllocSizeHints()) != NULL) {
|
---|
| 305 | // Otherwise some window managers ignore our position request
|
---|
| 306 | size_hints->flags = USPosition;
|
---|
| 307 | }
|
---|
| 308 |
|
---|
| 309 | // Make text property from title
|
---|
| 310 | XTextProperty titleprop;
|
---|
| 311 | char *lst = (char*)title.c_str();
|
---|
| 312 | XStringListToTextProperty((char **)&lst, 1, &titleprop);
|
---|
| 313 |
|
---|
| 314 | XSetWMProperties(mDisplay, mWindow, &titleprop, NULL, NULL, 0, size_hints, wm_hints, NULL);
|
---|
| 315 |
|
---|
| 316 | // We don't like memory leaks. Free the clientside storage, but not the
|
---|
| 317 | // pixmaps as they're still being used by the server.
|
---|
| 318 | XFree(titleprop.value);
|
---|
| 319 | XFree(wm_hints);
|
---|
| 320 | XFree(size_hints);
|
---|
| 321 |
|
---|
| 322 | // Acquire atom to recognize window close events
|
---|
| 323 | mAtomDeleteWindow = XInternAtom(mDisplay,"WM_DELETE_WINDOW",False);
|
---|
| 324 | XSetWMProtocols(mDisplay,mWindow,&mAtomDeleteWindow,1);
|
---|
| 325 |
|
---|
| 326 | // Map window unto screen and focus it.
|
---|
| 327 | XMapWindow(mDisplay,mWindow);
|
---|
| 328 |
|
---|
| 329 | // Make sure the server is up to date and focus the window
|
---|
| 330 | XFlush(mDisplay);
|
---|
| 331 | }
|
---|
| 332 | else
|
---|
| 333 | {
|
---|
| 334 | LogManager::getSingleton().logMessage("GLXWindow::create -- using external window handle");
|
---|
| 335 | visualInfo = extVisualHandler;
|
---|
| 336 | }
|
---|
| 337 |
|
---|
| 338 | GLRenderSystem *rs = static_cast<GLRenderSystem*>(Root::getSingleton().getRenderSystem());
|
---|
| 339 | GLXContext* mainContext = static_cast<GLXContext*>( rs->_getMainContext() );
|
---|
| 340 | if ( mainContext == 0 )
|
---|
| 341 | {
|
---|
| 342 | // Finally, create a GL context
|
---|
| 343 | // we want to share it with main
|
---|
| 344 | mGlxContext = glXCreateContext(mDisplay,visualInfo,NULL,True);
|
---|
| 345 | }
|
---|
| 346 | else
|
---|
| 347 | mGlxContext = glXCreateContext(mDisplay,visualInfo,mainContext->mCtx,True);
|
---|
| 348 |
|
---|
| 349 | if(!mGlxContext) {
|
---|
| 350 | OGRE_EXCEPT(999, "glXCreateContext failed", "GLXWindow::create");
|
---|
| 351 | }
|
---|
| 352 |
|
---|
| 353 | // Free visual info
|
---|
| 354 | if (extVisualHandler == NULL)
|
---|
| 355 | XFree(visualInfo);
|
---|
| 356 |
|
---|
| 357 | mName = name;
|
---|
| 358 | mWidth = width;
|
---|
| 359 | mHeight = height;
|
---|
| 360 | mFullScreen = fullScreen;
|
---|
| 361 |
|
---|
| 362 | // Create OGRE GL context
|
---|
| 363 | mContext = new GLXContext(mDisplay, mWindow, mGlxContext);
|
---|
| 364 | // Register the context with the rendersystem and associate it with this window
|
---|
| 365 | rs->_registerContext(this, mContext);
|
---|
| 366 |
|
---|
| 367 | if ( rs->_getMainContext() == 0 )
|
---|
| 368 | glXMakeCurrent(mDisplay,mWindow,mGlxContext);
|
---|
| 369 | }
|
---|
| 370 |
|
---|
| 371 | void GLXWindow::destroy(void)
|
---|
| 372 | {
|
---|
| 373 | // Unregister and destroy OGRE GLContext
|
---|
| 374 | GLRenderSystem *rs = static_cast<GLRenderSystem*>(Root::getSingleton().getRenderSystem());
|
---|
| 375 | rs->_unregisterContext(this);
|
---|
| 376 | delete mContext;
|
---|
| 377 |
|
---|
| 378 | // Destroy GL context
|
---|
| 379 | if(mGlxContext)
|
---|
| 380 | glXDestroyContext(mDisplay, mGlxContext);
|
---|
| 381 | if(mWindow)
|
---|
| 382 | XDestroyWindow(mDisplay, mWindow);
|
---|
| 383 | mWindow = 0;
|
---|
| 384 | mGlxContext = 0;
|
---|
| 385 | mActive = false;
|
---|
| 386 |
|
---|
| 387 | Root::getSingleton().getRenderSystem()->detachRenderTarget( this->getName() );
|
---|
| 388 | }
|
---|
| 389 |
|
---|
| 390 | bool GLXWindow::isActive() const
|
---|
| 391 | {
|
---|
| 392 | return mActive;
|
---|
| 393 | }
|
---|
| 394 |
|
---|
| 395 | bool GLXWindow::isClosed() const
|
---|
| 396 | {
|
---|
| 397 | return mClosed;
|
---|
| 398 | }
|
---|
| 399 |
|
---|
| 400 | void GLXWindow::reposition(int left, int top)
|
---|
| 401 | {
|
---|
| 402 | XMoveWindow(mDisplay,mWindow,left,top);
|
---|
| 403 | }
|
---|
| 404 |
|
---|
| 405 | void GLXWindow::resize(unsigned int width, unsigned int height)
|
---|
| 406 | {
|
---|
| 407 | if (!mTopLevel)
|
---|
| 408 | /// Embedded
|
---|
| 409 | resized(width, height);
|
---|
| 410 | else
|
---|
| 411 | /// Ogre handles window
|
---|
| 412 | XResizeWindow(mDisplay,mWindow,width,height);
|
---|
| 413 | }
|
---|
| 414 |
|
---|
| 415 | void GLXWindow::swapBuffers(bool waitForVSync)
|
---|
| 416 | {
|
---|
| 417 | glXSwapBuffers(mDisplay,mWindow);
|
---|
| 418 | }
|
---|
| 419 |
|
---|
| 420 | void GLXWindow::processEvent(const XEvent &event)
|
---|
| 421 | {
|
---|
| 422 | // Process only events for this window
|
---|
| 423 | switch(event.type) {
|
---|
| 424 | case ClientMessage:
|
---|
| 425 | if(event.xclient.display != mDisplay || event.xclient.window != mWindow)
|
---|
| 426 | // Not for me
|
---|
| 427 | break;
|
---|
| 428 | if(event.xclient.format == 32 && event.xclient.data.l[0] == (long)mAtomDeleteWindow) {
|
---|
| 429 | // Window deleted -- oops, this does not work, ogre doesn't register the close
|
---|
| 430 | //mClosed = true;
|
---|
| 431 | //mActive = false;
|
---|
| 432 | //Root::getSingleton().getRenderSystem()->detachRenderTarget( this->getName() );
|
---|
| 433 | }
|
---|
| 434 | break;
|
---|
| 435 | case ConfigureNotify:
|
---|
| 436 | if(event.xconfigure.display != mDisplay || event.xconfigure.window != mWindow)
|
---|
| 437 | // Not for me
|
---|
| 438 | break;
|
---|
| 439 | resized(event.xconfigure.width, event.xconfigure.height);
|
---|
| 440 | break;
|
---|
| 441 | case MapNotify:
|
---|
| 442 | if(event.xconfigure.display != mDisplay || event.xconfigure.window != mWindow)
|
---|
| 443 | // Not for me
|
---|
| 444 | break;
|
---|
| 445 | // Window was mapped to the screen
|
---|
| 446 | exposed(true);
|
---|
| 447 | break;
|
---|
| 448 | case UnmapNotify:
|
---|
| 449 | if(event.xconfigure.display != mDisplay || event.xconfigure.window != mWindow)
|
---|
| 450 | // Not for me
|
---|
| 451 | break;
|
---|
| 452 | // Window was unmapped from the screen (user switched
|
---|
| 453 | // to another workspace, for example)
|
---|
| 454 | exposed(false);
|
---|
| 455 | break;
|
---|
| 456 | }
|
---|
| 457 | }
|
---|
| 458 |
|
---|
| 459 | void GLXWindow::exposed(bool active)
|
---|
| 460 | {
|
---|
| 461 | mActive = active;
|
---|
| 462 | }
|
---|
| 463 | void GLXWindow::resized(size_t width, size_t height)
|
---|
| 464 | {
|
---|
| 465 | // Check if the window size really changed
|
---|
| 466 | if(mWidth == width && mHeight == height)
|
---|
| 467 | return;
|
---|
| 468 | mWidth = width;
|
---|
| 469 | mHeight = height;
|
---|
| 470 |
|
---|
| 471 | for (ViewportList::iterator it = mViewportList.begin();
|
---|
| 472 | it != mViewportList.end(); ++it) {
|
---|
| 473 | (*it).second->_updateDimensions();
|
---|
| 474 | }
|
---|
| 475 | }
|
---|
| 476 | /// Pure virtual destructor must be defined
|
---|
| 477 | GLXWindowInterface::~GLXWindowInterface()
|
---|
| 478 | {
|
---|
| 479 | }
|
---|
| 480 |
|
---|
| 481 | void GLXWindow::getCustomAttribute( const String& name, void* pData )
|
---|
| 482 | {
|
---|
| 483 | if( name == "GLXWINDOW" ) {
|
---|
| 484 | *static_cast<Window*>(pData) = mWindow;
|
---|
| 485 | return;
|
---|
| 486 | } else if( name == "GLXDISPLAY" ) {
|
---|
| 487 | *static_cast<Display**>(pData) = mDisplay;
|
---|
| 488 | return;
|
---|
| 489 | } else if( name == "GLXWINDOWINTERFACE" ) {
|
---|
| 490 | *static_cast<GLXWindowInterface**>(pData) = this;
|
---|
| 491 | return;
|
---|
| 492 | }
|
---|
| 493 | RenderWindow::getCustomAttribute(name, pData);
|
---|
| 494 | }
|
---|
| 495 |
|
---|
| 496 |
|
---|
| 497 |
|
---|
| 498 | void GLXWindow::writeContentsToFile(const String& filename)
|
---|
| 499 | {
|
---|
| 500 | ImageCodec::ImageData* imgData = new ImageCodec::ImageData;
|
---|
| 501 | imgData->width = mWidth;
|
---|
| 502 | imgData->height = mHeight;
|
---|
| 503 | imgData->format = PF_BYTE_RGB;
|
---|
| 504 |
|
---|
| 505 | // Allocate buffer
|
---|
| 506 | uchar* pBuffer = new uchar[mWidth * mHeight * 3];
|
---|
| 507 |
|
---|
| 508 | // Read pixels
|
---|
| 509 | // I love GL: it does all the locking & colour conversion for us
|
---|
| 510 | glReadPixels(0,0, mWidth-1, mHeight-1, GL_RGB, GL_UNSIGNED_BYTE, pBuffer);
|
---|
| 511 |
|
---|
| 512 | // Wrap buffer in a memory stream
|
---|
| 513 | DataStreamPtr stream(new MemoryDataStream(pBuffer, mWidth * mHeight * 3, false));
|
---|
| 514 |
|
---|
| 515 | // Need to flip the read data over in Y though
|
---|
| 516 | Image img;
|
---|
| 517 | img.loadRawData(stream, mWidth, mHeight, PF_BYTE_RGB );
|
---|
| 518 | img.flipAroundX();
|
---|
| 519 |
|
---|
| 520 | MemoryDataStreamPtr streamFlipped(new MemoryDataStream(img.getData(), stream->size(), false));
|
---|
| 521 |
|
---|
| 522 | // Get codec
|
---|
| 523 | size_t pos = filename.find_last_of(".");
|
---|
| 524 | String extension;
|
---|
| 525 | if( pos == String::npos )
|
---|
| 526 | OGRE_EXCEPT(
|
---|
| 527 | Exception::ERR_INVALIDPARAMS,
|
---|
| 528 | "Unable to determine image type for '" + filename + "' - invalid extension.",
|
---|
| 529 | "SDLWindow::writeContentsToFile" );
|
---|
| 530 |
|
---|
| 531 | while( pos != filename.length() - 1 )
|
---|
| 532 | extension += filename[++pos];
|
---|
| 533 |
|
---|
| 534 | // Get the codec
|
---|
| 535 | Codec * pCodec = Codec::getCodec(extension);
|
---|
| 536 |
|
---|
| 537 | // Write out
|
---|
| 538 | Codec::CodecDataPtr codecDataPtr(imgData);
|
---|
| 539 | pCodec->codeToFile(streamFlipped, filename, codecDataPtr);
|
---|
| 540 |
|
---|
| 541 | delete [] pBuffer;
|
---|
| 542 | }
|
---|
| 543 |
|
---|
| 544 | }
|
---|