/* ----------------------------------------------------------------------------- This source file is part of OGRE (Object-oriented Graphics Rendering Engine) For the latest info, see http://www.ogre3d.org/ Copyright (c) 2000-2005 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 "OgreStableHeaders.h" #include "OgreException.h" #include "OgreLogManager.h" #include "OgreRoot.h" #include "OgreStringConverter.h" #include "OgreGLRenderSystem.h" #include "OgreGLXRenderTexture.h" #include "OgreGLXContext.h" #include "OgreGLXUtils.h" #include // Replace by arb ASAP #ifndef GLX_ATI_pixel_format_float #define GLX_ATI_pixel_format_float 1 #define GLX_RGBA_FLOAT_ATI_BIT 0x00000100 #endif namespace Ogre { GLXRenderTexture::GLXRenderTexture( const String & name, unsigned int width, unsigned int height, TextureType texType, PixelFormat internalFormat, const NameValuePairList *miscParams): GLRenderTexture(name, width, height, texType, internalFormat, miscParams), _hPBuffer(0), mContext(0) { createPBuffer(); // Create context mContext = new GLXContext(_pDpy, _hPBuffer, _hGLContext); // Register the context with the rendersystem GLRenderSystem *rs = static_cast(Root::getSingleton().getRenderSystem()); rs->_registerContext(this, mContext); } void GLXRenderTexture::createPBuffer() { LogManager::getSingleton().logMessage( "GLXRenderTexture::Creating PBuffer" ); _pDpy = glXGetCurrentDisplay(); ::GLXContext context = glXGetCurrentContext(); int screen = DefaultScreen(_pDpy); int iFormat = 0; int iNumFormats; int attribs[50], ideal[50]; int attrib; // Attribs for glXChooseFBConfig // Get R,G,B,A depths int depths[4]; PixelUtil::getBitDepths(mInternalFormat, depths); int renderType; if(PixelUtil::getFlags(mInternalFormat) & PFF_FLOAT) renderType = GLX_RGBA_FLOAT_ATI_BIT; // GLX_RGBA_FLOAT_BIT else renderType = GLX_RGBA_BIT; // Create base required format description attrib = 0; attribs[attrib++] = GLX_RENDER_TYPE; attribs[attrib++] = renderType; attribs[attrib++] = GLX_DRAWABLE_TYPE; attribs[attrib++] = GLX_PBUFFER_BIT; attribs[attrib++] = GLX_DOUBLEBUFFER; attribs[attrib++] = 0; attribs[attrib++] = None; // Create "ideal" format description attrib = 0; ideal[attrib++] = GLX_RED_SIZE; ideal[attrib++] = depths[0]; ideal[attrib++] = GLX_GREEN_SIZE; ideal[attrib++] = depths[1]; ideal[attrib++] = GLX_BLUE_SIZE; ideal[attrib++] = depths[2]; ideal[attrib++] = GLX_ALPHA_SIZE; ideal[attrib++] = depths[3]; ideal[attrib++] = GLX_DEPTH_SIZE; ideal[attrib++] = 24; ideal[attrib++] = GLX_STENCIL_SIZE; ideal[attrib++] = 8; ideal[attrib++] = GLX_ACCUM_RED_SIZE; ideal[attrib++] = 0; // Accumulation buffer not used ideal[attrib++] = GLX_ACCUM_GREEN_SIZE; ideal[attrib++] = 0; // Accumulation buffer not used ideal[attrib++] = GLX_ACCUM_BLUE_SIZE; ideal[attrib++] = 0; // Accumulation buffer not used ideal[attrib++] = GLX_ACCUM_ALPHA_SIZE; ideal[attrib++] = 0; // Accumulation buffer not used ideal[attrib++] = None; // Create vector of existing config data formats GLXFBConfig config = GLXUtils::findBestMatch(_pDpy, screen, attribs, ideal); // Create the pbuffer in the best matching format attrib = 0; attribs[attrib++] = GLX_PBUFFER_WIDTH; attribs[attrib++] = mWidth; // Get from texture? attribs[attrib++] = GLX_PBUFFER_HEIGHT; attribs[attrib++] = mHeight; // Get from texture? attribs[attrib++] = GLX_PRESERVED_CONTENTS; attribs[attrib++] = 1; attribs[attrib++] = None; FBConfigData configData(_pDpy, config); LogManager::getSingleton().logMessage( LML_NORMAL, "GLXRenderTexture::PBuffer chose format "+configData.toString()); _hPBuffer = glXCreatePbuffer(_pDpy, config, attribs); if (!_hPBuffer) OGRE_EXCEPT(Exception::UNIMPLEMENTED_FEATURE, "glXCreatePbuffer() failed", "GLRenderTexture::createPBuffer"); _hGLContext = glXCreateNewContext(_pDpy, config, GLX_RGBA_TYPE, context, True); if (!_hGLContext) OGRE_EXCEPT(Exception::UNIMPLEMENTED_FEATURE, "glXCreateContext() failed", "GLRenderTexture::createPBuffer"); // Query real width and height GLuint iWidth, iHeight; glXQueryDrawable(_pDpy, _hPBuffer, GLX_WIDTH, &iWidth); glXQueryDrawable(_pDpy, _hPBuffer, GLX_HEIGHT, &iHeight); LogManager::getSingleton().logMessage( LML_NORMAL, "GLXRenderTexture::PBuffer created -- Real dimensions "+ StringConverter::toString(iWidth)+"x"+StringConverter::toString(iHeight) ); mWidth = iWidth; mHeight = iHeight; } GLXRenderTexture::~GLXRenderTexture() { // Unregister and destroy mContext GLRenderSystem *rs = static_cast(Root::getSingleton().getRenderSystem()); rs->_unregisterContext(this); delete mContext; // Destroy GL context glXDestroyContext(_pDpy, _hGLContext); _hGLContext = 0; glXDestroyPbuffer(_pDpy, _hPBuffer); _hPBuffer = 0; } /* void GLXRenderTexture::_copyToTexture() { // Should do nothing } */ }