📄 ogreglxwindow.cpp
字号:
(bestVis.alphaSize < vis.alphaSize) ||
(bestVis.depthSize < vis.depthSize) ||
(bestVis.stencilSize < vis.stencilSize) ||
(bestVis.accumRedSize < vis.accumRedSize)) {
/* found a better visual */
bestVis = vis;
}
}
XFree(visuals);
return bestVis.id;
}
};
void GLXWindow::create(const String& name, unsigned int width, unsigned int height, unsigned int colourDepth,
bool fullScreen, int left, int top, bool depthBuffer,
void* miscParam, ...) {
std::cerr << "GLXWindow::create" << std::endl;
// We will attempt to create new window on default screen op display 0
int screen = DefaultScreen(mDisplay);
int depth = DisplayPlanes(mDisplay, screen);
Window rootWindow = RootWindow(mDisplay,screen);
#ifndef NO_XRANDR
// Attempt mode switch for fullscreen -- only if RANDR extension is there
int dummy;
if(fullScreen && ! XQueryExtension(mDisplay, "RANDR", &dummy, &dummy, &dummy)) {
LogManager::getSingleton().logMessage("GLXWindow::create -- Could not switch to full screen mode: No XRANDR extension found");
} else if(fullScreen) {
// Use Xrandr extension to switch video modes. This is much better than
// XVidMode as you can't scroll away from the full-screen applications.
XRRScreenConfiguration *config;
XRRScreenSize *sizes;
Rotation current_rotation;
int current_size;
int nsizes;
// Get current screen info
config = XRRGetScreenInfo(mDisplay, rootWindow);
// Get available sizes
if(config)
sizes = XRRConfigSizes (config, &nsizes);
if(config && nsizes > 0) {
// Get current size and rotation
mOldMode = XRRConfigCurrentConfiguration (config, ¤t_rotation);
// Find smallest matching mode
int mode = -1;
int mode_width = INT_MAX;
int mode_height = INT_MAX;
for(int i=0; i<nsizes; i++) {
if(sizes[i].width >= width && sizes[i].height >= height &&
sizes[i].width < mode_width && sizes[i].height < mode_height) {
mode = i;
mode_width = sizes[i].width;
mode_height = sizes[i].height;
}
}
if(mode >= 0) {
// Finally, set the screen configuration
LogManager::getSingleton().logMessage("GLXWindow::create -- Entering full screen mode");
XRRSetScreenConfig(mDisplay, config, rootWindow, mode, current_rotation, CurrentTime);
} else {
LogManager::getSingleton().logMessage("GLXWindow::create -- Could not switch to full screen mode: No conforming mode was found");
}
// Free configuration data
XRRFreeScreenConfigInfo(config);
} else {
LogManager::getSingleton().logMessage("GLXWindow::create -- Could not switch to full screen mode: XRRGetScreenInfo failed");
}
}
#endif
// Apply some magic algorithm to get the best visual
int best_visual = find_best_visual(mDisplay, screen);
LogManager::getSingleton().logMessage("GLXWindow::create -- Best visual is "+StringConverter::toString(best_visual));
// Get information about this so-called-best visual
XVisualInfo templ;
int nmatch;
templ.visualid = best_visual;
XVisualInfo *visualInfo = XGetVisualInfo(mDisplay, VisualIDMask, &templ, &nmatch);
if(visualInfo==0 || nmatch==0) {
Except(999, "GLXWindow: error choosing visual", "GLXWindow::create");
}
XSetWindowAttributes attr;
unsigned long mask;
attr.background_pixel = 0;
attr.border_pixel = 0;
attr.colormap = XCreateColormap(mDisplay,rootWindow,visualInfo->visual,AllocNone);
attr.event_mask = StructureNotifyMask | KeyPressMask | KeyReleaseMask | PointerMotionMask | ButtonPressMask | ButtonReleaseMask;
if(fullScreen) {
mask = CWBackPixel | CWColormap | CWOverrideRedirect | CWSaveUnder | CWBackingStore | CWEventMask;
attr.override_redirect = True;
attr.backing_store = NotUseful;
attr.save_under = False;
// Fullscreen windows are always in the top left origin
left = top = 0;
} else
mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
// Create window on server
mWindow = XCreateWindow(mDisplay,rootWindow,left,top,width,height,0,visualInfo->depth,InputOutput,visualInfo->visual,mask,&attr);
if(!mWindow) {
Except(999, "GLXWindow: XCreateWindow failed", "GLXWindow::create");
}
// Make sure the window is in normal state
XWMHints *wm_hints;
if ((wm_hints = XAllocWMHints()) != NULL) {
wm_hints->initial_state = NormalState;
wm_hints->input = True;
wm_hints->flags = StateHint | InputHint;
// Check if we can give it an icon
if(depth == 24 || depth == 32) {
// Woot! The right bit depth, we can load an icon
if(LoadIcon(mDisplay, rootWindow, "GLX_icon.png", &wm_hints->icon_pixmap, &wm_hints->icon_mask))
wm_hints->flags |= IconPixmapHint | IconMaskHint;
}
}
// Set size and location hints
XSizeHints *size_hints;
if ((size_hints = XAllocSizeHints()) != NULL) {
// Otherwise some window managers ignore our position request
size_hints->flags = USPosition;
}
// Make text property from title
XTextProperty titleprop;
char *lst = (char*)name.c_str();
XStringListToTextProperty((char **)&lst, 1, &titleprop);
XSetWMProperties(mDisplay, mWindow, &titleprop, NULL, NULL, 0, size_hints, wm_hints, NULL);
// We don't like memory leaks. Free the clientside storage, but not the
// pixmaps as they're still being used by the server.
XFree(titleprop.value);
XFree(wm_hints);
XFree(size_hints);
// Acquire atom to recognize window close events
mAtomDeleteWindow = XInternAtom(mDisplay,"WM_DELETE_WINDOW",False);
XSetWMProtocols(mDisplay,mWindow,&mAtomDeleteWindow,1);
// Map window unto screen and focus it.
XMapWindow(mDisplay,mWindow);
// Make sure the server is up to date and focus the window
XFlush(mDisplay);
// Finally, create a GL context
mGlxContext = glXCreateContext(mDisplay,visualInfo,NULL,True);
if(!mGlxContext) {
Except(999, "glXCreateContext failed", "GLXWindow::create");
}
glXMakeCurrent(mDisplay,mWindow,mGlxContext);
// Free visual info
XFree(visualInfo);
mName = name;
mWidth = width;
mHeight = height;
mFullScreen = fullScreen;
// Create OGRE GL context
mContext = new GLXContext(mDisplay, mWindow, mGlxContext);
// Register the context with the rendersystem and associate it with this window
GLRenderSystem *rs = static_cast<GLRenderSystem*>(Root::getSingleton().getRenderSystem());
rs->_registerContext(this, mContext);
}
void GLXWindow::destroy(void) {
// Unregister and destroy OGRE GLContext
GLRenderSystem *rs = static_cast<GLRenderSystem*>(Root::getSingleton().getRenderSystem());
rs->_unregisterContext(this);
delete mContext;
// Destroy GL context
if(mGlxContext)
glXDestroyContext(mDisplay, mGlxContext);
if(mWindow)
XDestroyWindow(mDisplay, mWindow);
mWindow = 0;
mGlxContext = 0;
mActive = false;
Root::getSingleton().getRenderSystem()->detachRenderTarget( this->getName() );
}
bool GLXWindow::isActive() const {
return mActive;
}
bool GLXWindow::isClosed() const {
return mClosed;
}
void GLXWindow::reposition(int left, int top) {
XMoveWindow(mDisplay,mWindow,left,top);
}
void GLXWindow::resize(unsigned int width, unsigned int height) {
XResizeWindow(mDisplay,mWindow,width,height);
}
void GLXWindow::swapBuffers(bool waitForVSync) {
glXSwapBuffers(mDisplay,mWindow);
}
void GLXWindow::processEvent(const XEvent &event) {
// Process only events for this window
switch(event.type) {
case ClientMessage:
if(event.xclient.display != mDisplay || event.xclient.window != mWindow)
// Not for me
break;
if(event.xclient.format == 32 && event.xclient.data.l[0] == (long)mAtomDeleteWindow) {
// Window deleted -- oops, this does not work, ogre doesn't register the close
//mClosed = true;
//mActive = false;
//Root::getSingleton().getRenderSystem()->detachRenderTarget( this->getName() );
}
break;
case ConfigureNotify:
if(event.xconfigure.display != mDisplay || event.xconfigure.window != mWindow)
// Not for me
break;
// Check if the window size really changed
if(mWidth == event.xconfigure.width && mHeight == event.xconfigure.height)
break;
mWidth = event.xconfigure.width;
mHeight = event.xconfigure.height;
for (ViewportList::iterator it = mViewportList.begin();
it != mViewportList.end(); ++it) {
(*it).second->_updateDimensions();
}
break;
case MapNotify:
if(event.xconfigure.display != mDisplay || event.xconfigure.window != mWindow)
// Not for me
break;
// Window was mapped to the screen
mActive = true;
break;
case UnmapNotify:
if(event.xconfigure.display != mDisplay || event.xconfigure.window != mWindow)
// Not for me
break;
// Window was unmapped from the screen (user switched
// to another workspace, for example)
mActive = false;
break;
}
}
void GLXWindow::getCustomAttribute( const String& name, void* pData ) {
if( name == "GLXWINDOW" ) {
*static_cast<Window*>(pData) = mWindow;
return;
} else if( name == "GLXDISPLAY" ) {
*static_cast<Display**>(pData) = mDisplay;
return;
}
RenderWindow::getCustomAttribute(name, pData);
}
void GLXWindow::writeContentsToFile(const String& filename) {
ImageCodec::ImageData imgData;
imgData.width = mWidth;
imgData.height = mHeight;
imgData.format = PF_R8G8B8;
// Allocate buffer
uchar* pBuffer = new uchar[mWidth * mHeight * 3];
// Read pixels
// I love GL: it does all the locking & colour conversion for us
glReadPixels(0,0, mWidth-1, mHeight-1, GL_RGB, GL_UNSIGNED_BYTE, pBuffer);
// Wrap buffer in a chunk
DataChunk chunk(pBuffer, mWidth * mHeight * 3);
// Need to flip the read data over in Y though
Image img;
img.loadRawData(chunk, mWidth, mHeight, PF_R8G8B8 );
img.flipAroundX();
DataChunk chunkFlipped(img.getData(), chunk.getSize());
// Get codec
size_t pos = filename.find_last_of(".");
String extension;
if( pos == String::npos )
Except(
Exception::ERR_INVALIDPARAMS,
"Unable to determine image type for '" + filename + "' - invalid extension.",
"GLXWindow::writeContentsToFile" );
while( pos != filename.length() - 1 )
extension += filename[++pos];
// Get the codec
Codec * pCodec = Codec::getCodec(extension);
// Write out
pCodec->codeToFile(chunkFlipped, filename, &imgData);
delete [] pBuffer;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -