📄 ogreglxwindow.cpp
字号:
/*
-----------------------------------------------------------------------------
This source file is part of OGRE
(Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/
Copyright ? 2000-2004 The OGRE Team
Also see acknowledgements in Readme.html
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA, or go to
http://www.gnu.org/copyleft/lesser.txt.
-----------------------------------------------------------------------------
*/
#include "OgreGLXWindow.h"
#include "OgreRoot.h"
#include "OgreGLRenderSystem.h"
#include "OgreImageCodec.h"
#include "OgreException.h"
#include "OgreLogManager.h"
#include "OgreStringConverter.h"
#include <iostream>
#include <algorithm>
#include <sys/time.h>
#include <climits>
#include <X11/Xlib.h>
#include <X11/keysym.h>
#ifndef NO_XRANDR
#include <X11/extensions/Xrandr.h>
#endif
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glx.h>
namespace Ogre {
GLXWindow::GLXWindow(Display *display) :
mDisplay(display),
mWindow(0),
mGlxContext(0),
mActive(false), mClosed(false),mFullScreen(false), mOldMode(-1),
mContext(0) {}
GLXWindow::~GLXWindow() {
if(mGlxContext)
glXDestroyContext(mDisplay, mGlxContext);
if(mWindow)
XDestroyWindow(mDisplay, mWindow);
#ifndef NO_XRANDR
if(mFullScreen) {
// Restore original video mode.
Window rootWindow = DefaultRootWindow(mDisplay);
XRRScreenConfiguration *config;
// Get current screen info
config = XRRGetScreenInfo(mDisplay, rootWindow);
if(config) {
Rotation current_rotation;
XRRConfigCurrentConfiguration (config, ¤t_rotation);
//std::cerr << "Restore mode " << mOldMode << std::endl;
LogManager::getSingleton().logMessage("GLXWindow::~GLXWindow -- Leaving full screen mode");
XRRSetScreenConfig(mDisplay, config, rootWindow, mOldMode, current_rotation, CurrentTime);
XRRFreeScreenConfigInfo(config);
} else {
LogManager::getSingleton().logMessage("GLXWindow::~GLXWindow -- Could not switch from full screen mode: XRRGetScreenInfo failed");
}
}
#endif
}
namespace {
/**
* Loads an icon from an Ogre resource into the X Server. This currently only
* works for 24 and 32 bit displays. The image must be findable by the Ogre
* resource system, and of format PF_A8R8G8B8.
*
* @param mDisplay,rootWindow X resources to use
* @param name Name of image to load
* @param pix Receiver for the output pixmap
* @param mask Receiver for the output mask (alpha bitmap)
* @returns true on success
*/
bool LoadIcon(Display *mDisplay, Window rootWindow, const std::string &name, Pixmap *pix, Pixmap *mask) {
Image img;
int mWidth, mHeight;
char *data, *bitmap;
try {
// Try to load image
img.load(name);
mWidth = img.getWidth();
mHeight = img.getHeight();
if(img.getFormat() != PF_A8R8G8B8)
// Image format must be RGBA
return 0;
} catch(Exception &e) {
// Could not find image; never mind
return false;
}
// Allocate space for image data
data = (char*)malloc(mWidth * mHeight * 4); // Must be allocated with malloc
// Allocate space for transparency bitmap
int wbits = (mWidth+7)/8;
bitmap = (char*)malloc(wbits * mHeight);
// Convert and copy image
const char *imgdata = (const char*)img.getData();
int sptr = 0, dptr = 0;
for(int y=0; y<mHeight; y++) {
for(int x=0; x<mWidth; x++) {
data[dptr + 0] = 0;
data[dptr + 1] = imgdata[sptr + 0];
data[dptr + 2] = imgdata[sptr + 1];
data[dptr + 3] = imgdata[sptr + 2];
// Alpha threshold
if(((unsigned char)imgdata[sptr + 3])<128) {
bitmap[y*wbits+(x>>3)] &= ~(1<<(x&7));
} else {
bitmap[y*wbits+(x>>3)] |= 1<<(x&7);
}
sptr += 4;
dptr += 4;
}
}
/* put my pixmap data into the client side X image data structure */
XImage *image = XCreateImage (mDisplay, NULL, 24, ZPixmap, 0,
data,
mWidth, mHeight, 8,
mWidth*4);
image->byte_order = MSBFirst; // 0RGB format
/* tell server to start managing my pixmap */
Pixmap retval = XCreatePixmap(mDisplay, rootWindow, mWidth,
mHeight, 24);
/* copy from client to server */
GC context = XCreateGC (mDisplay, rootWindow, 0, NULL);
XPutImage(mDisplay, retval, context, image, 0, 0, 0, 0,
mWidth, mHeight);
/* free up the client side pixmap data area */
XDestroyImage(image); // also cleans data
XFreeGC(mDisplay, context);
*pix = retval;
*mask = XCreateBitmapFromData(mDisplay, rootWindow, bitmap, mWidth, mHeight);
free(bitmap);
return true;
}
struct visual_attribs
{
/* X visual attribs */
int id;
int klass;
int depth;
int redMask, greenMask, blueMask;
int colormapSize;
int bitsPerRGB;
/* GL visual attribs */
int supportsGL;
int transparentType;
int transparentRedValue;
int transparentGreenValue;
int transparentBlueValue;
int transparentAlphaValue;
int transparentIndexValue;
int bufferSize;
int level;
int rgba;
int doubleBuffer;
int stereo;
int auxBuffers;
int redSize, greenSize, blueSize, alphaSize;
int depthSize;
int stencilSize;
int accumRedSize, accumGreenSize, accumBlueSize, accumAlphaSize;
int numSamples, numMultisample;
int visualCaveat;
};
static void
get_visual_attribs(Display *dpy, XVisualInfo *vInfo,
struct visual_attribs *attribs) {
const char *ext = glXQueryExtensionsString(dpy, vInfo->screen);
memset(attribs, 0, sizeof(struct visual_attribs));
attribs->id = vInfo->visualid;
#if defined(__cplusplus) || defined(c_plusplus)
attribs->klass = vInfo->c_class;
#else
attribs->klass = vInfo->class;
#endif
attribs->depth = vInfo->depth;
attribs->redMask = vInfo->red_mask;
attribs->greenMask = vInfo->green_mask;
attribs->blueMask = vInfo->blue_mask;
attribs->colormapSize = vInfo->colormap_size;
attribs->bitsPerRGB = vInfo->bits_per_rgb;
if (glXGetConfig(dpy, vInfo, GLX_USE_GL, &attribs->supportsGL) != 0)
return;
glXGetConfig(dpy, vInfo, GLX_BUFFER_SIZE, &attribs->bufferSize);
glXGetConfig(dpy, vInfo, GLX_LEVEL, &attribs->level);
glXGetConfig(dpy, vInfo, GLX_RGBA, &attribs->rgba);
glXGetConfig(dpy, vInfo, GLX_DOUBLEBUFFER, &attribs->doubleBuffer);
glXGetConfig(dpy, vInfo, GLX_STEREO, &attribs->stereo);
glXGetConfig(dpy, vInfo, GLX_AUX_BUFFERS, &attribs->auxBuffers);
glXGetConfig(dpy, vInfo, GLX_RED_SIZE, &attribs->redSize);
glXGetConfig(dpy, vInfo, GLX_GREEN_SIZE, &attribs->greenSize);
glXGetConfig(dpy, vInfo, GLX_BLUE_SIZE, &attribs->blueSize);
glXGetConfig(dpy, vInfo, GLX_ALPHA_SIZE, &attribs->alphaSize);
glXGetConfig(dpy, vInfo, GLX_DEPTH_SIZE, &attribs->depthSize);
glXGetConfig(dpy, vInfo, GLX_STENCIL_SIZE, &attribs->stencilSize);
glXGetConfig(dpy, vInfo, GLX_ACCUM_RED_SIZE, &attribs->accumRedSize);
glXGetConfig(dpy, vInfo, GLX_ACCUM_GREEN_SIZE, &attribs->accumGreenSize);
glXGetConfig(dpy, vInfo, GLX_ACCUM_BLUE_SIZE, &attribs->accumBlueSize);
glXGetConfig(dpy, vInfo, GLX_ACCUM_ALPHA_SIZE, &attribs->accumAlphaSize);
/* get transparent pixel stuff */
glXGetConfig(dpy, vInfo,GLX_TRANSPARENT_TYPE, &attribs->transparentType);
if (attribs->transparentType == GLX_TRANSPARENT_RGB) {
glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_RED_VALUE, &attribs->transparentRedValue);
glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_GREEN_VALUE, &attribs->transparentGreenValue);
glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_BLUE_VALUE, &attribs->transparentBlueValue);
glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_ALPHA_VALUE, &attribs->transparentAlphaValue);
} else if (attribs->transparentType == GLX_TRANSPARENT_INDEX) {
glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_INDEX_VALUE, &attribs->transparentIndexValue);
}
/* multisample attribs */
#ifdef GLX_ARB_multisample
if (ext && strstr("GLX_ARB_multisample", ext) == 0) {
glXGetConfig(dpy, vInfo, GLX_SAMPLE_BUFFERS_ARB, &attribs->numMultisample);
glXGetConfig(dpy, vInfo, GLX_SAMPLES_ARB, &attribs->numSamples);
}
#endif
else {
attribs->numSamples = 0;
attribs->numMultisample = 0;
}
#if defined(GLX_EXT_visual_rating)
if (ext && strstr(ext, "GLX_EXT_visual_rating")) {
glXGetConfig(dpy, vInfo, GLX_VISUAL_CAVEAT_EXT, &attribs->visualCaveat);
} else {
attribs->visualCaveat = GLX_NONE_EXT;
}
#else
attribs->visualCaveat = 0;
#endif
}
/*
* Examine all visuals to find the so-called best one.
* We prefer deepest RGBA buffer with depth, stencil and accum
* that has no caveats.
* @author Brian Paul (from the glxinfo source)
*/
int find_best_visual(Display *dpy, int scrnum) {
XVisualInfo theTemplate;
XVisualInfo *visuals;
int numVisuals;
long mask;
int i;
struct visual_attribs bestVis;
/* get list of all visuals on this screen */
theTemplate.screen = scrnum;
mask = VisualScreenMask;
visuals = XGetVisualInfo(dpy, mask, &theTemplate, &numVisuals);
if(numVisuals == 0 || visuals == 0) {
/* something went wrong */
if(visuals)
XFree(visuals);
return -1;
}
/* init bestVis with first visual info */
get_visual_attribs(dpy, &visuals[0], &bestVis);
/* try to find a "better" visual */
for (i = 1; i < numVisuals; i++) {
struct visual_attribs vis;
get_visual_attribs(dpy, &visuals[i], &vis);
/* always skip visuals with caveats */
if (vis.visualCaveat != GLX_NONE_EXT)
continue;
/* see if this vis is better than bestVis */
if ((!bestVis.supportsGL && vis.supportsGL) ||
(bestVis.visualCaveat != GLX_NONE_EXT) ||
(!bestVis.rgba && vis.rgba) ||
(!bestVis.doubleBuffer && vis.doubleBuffer) ||
(bestVis.redSize < vis.redSize) ||
(bestVis.greenSize < vis.greenSize) ||
(bestVis.blueSize < vis.blueSize) ||
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -