Index: trunk/VUT/work/ogre_changes/RenderSystems/GL/src/OgreGLTexture.cpp
===================================================================
--- trunk/VUT/work/ogre_changes/RenderSystems/GL/src/OgreGLTexture.cpp	(revision 153)
+++ trunk/VUT/work/ogre_changes/RenderSystems/GL/src/OgreGLTexture.cpp	(revision 153)
@@ -0,0 +1,457 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://ogre.sourceforge.net/
+
+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 "OgreGLTexture.h"
+#include "OgreGLSupport.h"
+#include "OgreGLPixelFormat.h"
+#include "OgreGLHardwarePixelBuffer.h"
+
+#include "OgreTextureManager.h"
+#include "OgreImage.h"
+#include "OgreLogManager.h"
+#include "OgreCamera.h"
+#include "OgreException.h"
+#include "OgreRoot.h"
+#include "OgreCodec.h"
+#include "OgreImageCodec.h"
+
+
+#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
+#   include <windows.h>
+#   include <wingdi.h>
+#endif
+
+namespace Ogre {
+
+    unsigned int mostSignificantBitSet(unsigned int value)
+	{
+		unsigned int result = 0;
+		while (value != 0) {
+			++result;
+			value >>= 1;
+		}
+		return result-1;
+	}
+
+    GLTexture::GLTexture(ResourceManager* creator, const String& name, 
+        ResourceHandle handle, const String& group, bool isManual, 
+        ManualResourceLoader* loader, GLSupport& support) 
+        : Texture(creator, name, handle, group, isManual, loader),
+        mTextureID(0), mGLSupport(support)
+    {
+    }
+
+
+    GLTexture::~GLTexture()
+    {
+        // have to call this here reather than in Resource destructor
+        // since calling virtual methods in base destructors causes crash
+        unload(); 
+    }
+
+    GLenum GLTexture::getGLTextureTarget(void) const
+    {
+        switch(mTextureType)
+        {
+            case TEX_TYPE_1D:
+                return GL_TEXTURE_1D;
+            case TEX_TYPE_2D:
+                return GL_TEXTURE_2D;
+            case TEX_TYPE_3D:
+                return GL_TEXTURE_3D;
+            case TEX_TYPE_CUBE_MAP:
+                return GL_TEXTURE_CUBE_MAP;
+            default:
+                return 0;
+        };
+    }
+
+	//* Creation / loading methods ********************************************
+	void GLTexture::createInternalResources(void)
+    {
+		// Adjust requested parameters to capabilities
+
+		// Check power-of-two size if required
+        unsigned int newWidth = (1 << mostSignificantBitSet(mWidth));
+        if (newWidth != mWidth)
+            newWidth <<= 1;
+
+        unsigned int newHeight = (1 << mostSignificantBitSet(mHeight));
+        if (newHeight != mHeight)
+            newHeight <<= 1;
+
+		unsigned int newDepth = (1 << mostSignificantBitSet(mDepth));
+        if (newDepth != mDepth)
+            newDepth <<= 1;
+
+        if(!Root::getSingleton().getRenderSystem()->getCapabilities()->hasCapability(RSC_NON_POWER_OF_2_TEXTURES))
+		{
+			mHeight = newHeight;
+			mWidth = newWidth;
+			mDepth = newDepth;
+		}
+		
+		// Check compressed texture support
+		// if a compressed format not supported, revert to PF_A8R8G8B8
+		if(PixelUtil::isCompressed(mFormat) &&
+		 !Root::getSingleton().getRenderSystem()->getCapabilities()->hasCapability( RSC_TEXTURE_COMPRESSION_DXT ))
+		{
+			mFormat = PF_A8R8G8B8;
+		}
+		// if floating point textures not supported, revert to PF_A8R8G8B8
+		if(PixelUtil::isFloatingPoint(mFormat) &&
+		 !Root::getSingleton().getRenderSystem()->getCapabilities()->hasCapability( RSC_TEXTURE_FLOAT ))
+		{
+			mFormat = PF_A8R8G8B8;
+		}
+		
+		// Check requested number of mipmaps
+		// Zero means create mip levels until 1x1
+		size_t maxMips = GLPixelUtil::getMaxMipmaps(mWidth, mHeight, mDepth, mFormat);
+		if(mNumMipmaps>maxMips)
+			mNumMipmaps = maxMips;
+		
+		// Generate texture name
+        glGenTextures( 1, &mTextureID );
+		
+		// Set texture type
+		glBindTexture( getGLTextureTarget(), mTextureID );
+        
+		// This needs to be set otherwise the texture doesn't get rendered
+        glTexParameteri( getGLTextureTarget(), GL_TEXTURE_MAX_LEVEL, mNumMipmaps );
+		
+		// If we can do automip generation and the user desires this, do so
+		if((mUsage & TU_AUTOMIPMAP) &&
+		    mNumMipmaps &&
+		 	Root::getSingleton().getRenderSystem()->getCapabilities()->hasCapability(RSC_AUTOMIPMAP))
+        {
+            glTexParameteri( getGLTextureTarget(), GL_GENERATE_MIPMAP, GL_TRUE );
+        }
+		
+		// Allocate internal buffer so that glTexSubImageXD can be used
+		// Internal format
+		GLenum format = GLPixelUtil::getClosestGLInternalFormat(mFormat);
+		size_t width = mWidth;
+		size_t height = mHeight;
+		size_t depth = mDepth;
+		if(PixelUtil::isCompressed(mFormat))
+		{
+			// Compressed formats
+			size_t size = PixelUtil::getMemorySize(mWidth, mHeight, mDepth, mFormat);
+			// Provide temporary buffer filled with zeroes as glCompressedTexImageXD does not
+			// accept a 0 pointer like normal glTexImageXD
+			// Run through this process for every mipmap to pregenerate mipmap piramid
+			uint8 *tmpdata = new uint8[size];
+			memset(tmpdata, 0, size);
+			
+			for(int mip=0; mip<=mNumMipmaps; mip++)
+			{
+			//int mip = 0;
+				size = PixelUtil::getMemorySize(width, height, depth, mFormat);
+				switch(mTextureType)
+				{
+					case TEX_TYPE_1D:
+						glCompressedTexImage1DARB_ptr(GL_TEXTURE_1D, mip, format, 
+							width, 0, 
+							size, tmpdata);
+						break;
+					case TEX_TYPE_2D:
+						glCompressedTexImage2DARB_ptr(GL_TEXTURE_2D, mip, format,
+							width, height, 0, 
+							size, tmpdata);
+						break;
+					case TEX_TYPE_3D:
+						glCompressedTexImage3DARB_ptr(GL_TEXTURE_3D, mip, format,
+							width, height, depth, 0, 
+							size, tmpdata);
+						break;
+					case TEX_TYPE_CUBE_MAP:
+						for(int face=0; face<6; face++) {
+							glCompressedTexImage2DARB_ptr(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, mip, format,
+								width, height, 0, 
+								size, tmpdata);
+						}
+						break;
+				};
+				if(width>1)		width = width/2;
+				if(height>1)	height = height/2;
+				if(depth>1)		depth = depth/2;
+			}
+			delete tmpdata;
+		}
+		else
+		{
+			// Run through this process to pregenerate mipmap piramid
+			for(int mip=0; mip<=mNumMipmaps; mip++)
+			{
+				// Normal formats
+				switch(mTextureType)
+				{
+					case TEX_TYPE_1D:
+						glTexImage1D(GL_TEXTURE_1D, mip, format,
+							width, 0, 
+							GL_RGBA, GL_UNSIGNED_BYTE, 0);
+	
+						break;
+					case TEX_TYPE_2D:
+						glTexImage2D(GL_TEXTURE_2D, mip, format,
+							width, height, 0, 
+							GL_RGBA, GL_UNSIGNED_BYTE, 0);
+						break;
+					case TEX_TYPE_3D:
+						glTexImage3D(GL_TEXTURE_3D, mip, format,
+							width, height, depth, 0, 
+							GL_RGBA, GL_UNSIGNED_BYTE, 0);
+						break;
+					case TEX_TYPE_CUBE_MAP:
+						for(int face=0; face<6; face++) {
+							glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, mip, format,
+								width, height, 0, 
+								GL_RGBA, GL_UNSIGNED_BYTE, 0);
+						}
+						break;
+				};
+				if(width>1)		width = width/2;
+				if(height>1)	height = height/2;
+				if(depth>1)		depth = depth/2;
+			}
+		}
+		_createSurfaceList();
+		// Get final internal format
+		mFormat = getBuffer(0,0)->getFormat();
+		mIsLoaded = true;
+	}
+	
+    void GLTexture::createRenderTexture(void)
+    {
+        if (this->getTextureType() != TEX_TYPE_2D)
+            OGRE_EXCEPT( Exception::UNIMPLEMENTED_FEATURE, "**** Create render texture implemented only for 2D textures!!! ****", "GLTexture::createRenderTexture" );
+
+        // Create the GL texture
+		// This already does everything neccessary
+        createInternalResources();
+    }
+	
+	void GLTexture::loadImage( const Image& img )
+    {
+        std::vector<const Image*> images;
+		
+        images.push_back(&img);
+        _loadImages(images);
+        images.clear();
+    }
+
+    void GLTexture::loadImpl()
+    {
+        if( mUsage & TU_RENDERTARGET )
+        {
+            createRenderTexture();
+            mIsLoaded = true;     
+        }
+        else
+        {
+            if(mTextureType == TEX_TYPE_1D || mTextureType == TEX_TYPE_2D || 
+                mTextureType == TEX_TYPE_3D)
+            {
+                Image img;
+                img.load(mName, mGroup);
+
+				// If this is a cube map, set the texture type flag accordingly.
+                if (img.hasFlag(IF_CUBEMAP))
+					mTextureType = TEX_TYPE_CUBE_MAP;
+				// If this is a volumetric texture set the texture type flag accordingly.
+				if(img.getDepth() > 1)
+					mTextureType = TEX_TYPE_3D;
+
+				loadImage( img );
+            }
+            else if (mTextureType == TEX_TYPE_CUBE_MAP)
+            {
+				if(StringUtil::endsWith(getName(), ".dds"))
+				{
+					// XX HACK there should be a better way to specify wether 
+					// all faces are in the same file or not
+					Image img;
+                	img.load(mName, mGroup);
+					loadImage( img );
+				}
+				else
+				{
+					String baseName, ext;
+					std::vector<Image> images(6);
+					std::vector<const Image*> imagePtrs;
+					static const String suffixes[6] = {"_rt", "_lf", "_up", "_dn", "_fr", "_bk"};
+	
+					for(size_t i = 0; i < 6; i++)
+					{
+						size_t pos = mName.find_last_of(".");
+						baseName = mName.substr(0, pos);
+						ext = mName.substr(pos);
+						String fullName = baseName + suffixes[i] + ext;
+	
+						images[i].load(fullName, mGroup);
+						imagePtrs.push_back(&images[i]);
+					}
+	
+					_loadImages( imagePtrs );
+				}
+            }
+            else
+                OGRE_EXCEPT( Exception::UNIMPLEMENTED_FEATURE, "**** Unknown texture type ****", "GLTexture::load" );
+        }
+    }
+	
+	//*************************************************************************
+    
+    void GLTexture::unloadImpl()
+    {
+		mSurfaceList.clear();
+        glDeleteTextures( 1, &mTextureID );
+    }
+
+	
+	//---------------------------------------------------------------------------------------------
+	void GLTexture::_createSurfaceList()
+	{
+		mSurfaceList.clear();
+		// Make our understanding of the number of mips matches the GL one
+		glBindTexture( getGLTextureTarget(), mTextureID );
+		GLint value;
+		glGetTexParameteriv( getGLTextureTarget(), GL_TEXTURE_MAX_LEVEL, &value );
+		mNumMipmaps = value;
+		
+		// For all faces and mipmaps, store surfaces as HardwarePixelBufferSharedPtr
+		bool wantGeneratedMips = (mUsage & TU_AUTOMIPMAP)!=0;
+		bool canMip = Root::getSingleton().getRenderSystem()->getCapabilities()->hasCapability(RSC_AUTOMIPMAP);
+		
+		// Do mipmapping in software? (uses GLU) For some cards, this is still needed. Of course,
+		// only when mipmap generation is desired.
+		bool doSoftware = wantGeneratedMips && !canMip && getNumMipmaps(); 
+		
+		for(int face=0; face<getNumFaces(); face++)
+		{
+			for(int mip=0; mip<=getNumMipmaps(); mip++)
+			{
+				mSurfaceList.push_back(HardwarePixelBufferSharedPtr(
+					new GLHardwarePixelBuffer(getGLTextureTarget(), mTextureID, face, mip,
+						static_cast<HardwareBuffer::Usage>(mUsage), doSoftware && mip==0)
+				));
+			}
+		}
+	}
+	
+	//---------------------------------------------------------------------------------------------
+	HardwarePixelBufferSharedPtr GLTexture::getBuffer(size_t face, size_t mipmap)
+	{
+		if(face >= getNumFaces())
+			OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Face index out of range",
+					"GLTexture::getBuffer");
+		if(mipmap > mNumMipmaps)
+			OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Mipmap index out of range",
+					"GLTexture::getBuffer");
+		unsigned int idx = face*(mNumMipmaps+1) + mipmap;
+		assert(idx < mSurfaceList.size());
+		return mSurfaceList[idx];
+	}
+	
+	//---------------------------------------------------------------------------------------------
+    void GLRenderTexture::_copyToTexture(void)
+    {		
+        glBindTexture(GL_TEXTURE_2D, mGLTexture->getGLID());
+			
+        glCopyTexSubImage2D(GL_TEXTURE_2D, mGLTexture->getNumMipmaps(), 0, 0,
+            0, 0, mWidth, mHeight);
+
+    }
+    
+    void GLRenderTexture::writeContentsToFile( const String & filename ) 
+    {
+        ImageCodec::ImageData *imgData = new ImageCodec::ImageData();
+        
+        imgData->width = mGLTexture->getWidth();
+        imgData->height = mGLTexture->getHeight();
+		imgData->depth = 1;
+        imgData->format = PF_BYTE_RGB;
+
+        // Allocate buffer 
+        uchar* pBuffer = new uchar[imgData->width * imgData->height * 3];
+
+        // Read pixels
+        // I love GL: it does all the locking & colour conversion for us
+        glBindTexture(GL_TEXTURE_2D, mGLTexture->getGLID());
+        glGetTexImage(GL_TEXTURE_2D, 0, GL_RGB, GL_UNSIGNED_BYTE, pBuffer);
+
+        // Wrap buffer in a chunk
+        DataStreamPtr stream(new MemoryDataStream(
+            pBuffer, imgData->width * imgData->height * 3, false));
+
+        // Need to flip the read data over in Y though
+        Image img;
+        img.loadRawData(stream, imgData->width, imgData->height, imgData->format );
+        img.flipAroundX();
+
+        MemoryDataStreamPtr streamFlipped(
+            new MemoryDataStream(img.getData(), stream->size(), false));
+
+        // Get codec 
+        size_t pos = filename.find_last_of(".");
+            String extension;
+        if( pos == String::npos )
+            OGRE_EXCEPT(
+                Exception::ERR_INVALIDPARAMS, 
+            "Unable to determine image type for '" + filename + "' - invalid extension.",
+                "GLRenderTexture::writeContentsToFile" );
+
+        while( pos != filename.length() - 1 )
+            extension += filename[++pos];
+
+        // Get the codec
+        Codec * pCodec = Codec::getCodec(extension);
+
+        // Write out
+        Codec::CodecDataPtr codecDataPtr(imgData);
+        pCodec->codeToFile(streamFlipped, filename, codecDataPtr);
+
+        delete [] pBuffer;
+    }
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+	uchar *GLRenderTexture::getBufferContents(int &dimx, int &dimy)
+	{
+		ImageCodec::ImageData *imgData = new ImageCodec::ImageData();
+		dimx = mWidth;
+		dimy = mHeight;
+		
+		// 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);
+
+		return pBuffer;
+	}
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+}
+
Index: trunk/VUT/work/ogre_changes/RenderSystems/GL/src/OgreWin32Window.cpp
===================================================================
--- trunk/VUT/work/ogre_changes/RenderSystems/GL/src/OgreWin32Window.cpp	(revision 153)
+++ trunk/VUT/work/ogre_changes/RenderSystems/GL/src/OgreWin32Window.cpp	(revision 153)
@@ -0,0 +1,498 @@
+/*
+-----------------------------------------------------------------------------
+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 "OgreWin32Window.h"
+#include "OgreRoot.h"
+#include "OgreLogManager.h"
+#include "OgreRenderSystem.h"
+#include "OgreImageCodec.h"
+#include "OgreStringConverter.h"
+#include "OgreException.h"
+#include "OgreWin32GLSupport.h"
+#include "OgreWin32Context.h"
+
+namespace Ogre {
+
+	Win32Window::Win32Window(Win32GLSupport &glsupport):
+		mGLSupport(glsupport),
+        mContext(0)
+    {
+		mIsFullScreen = false;
+		mHWnd = 0;
+		mActive = false;
+		mReady = false;
+		mClosed = false;
+    }
+
+    Win32Window::~Win32Window()
+    {
+		destroy();
+    }
+
+	void Win32Window::create(const String& name, unsigned int width, unsigned int height,
+	            bool fullScreen, const NameValuePairList *miscParams)
+    {
+        HWND parentHWnd = 0;
+		HWND externalHandle = 0;
+		HINSTANCE hInst = GetModuleHandle("RenderSystem_GL.dll");
+		bool vsync = false;
+		unsigned int displayFrequency = 0;
+		String title = name;
+		unsigned int colourDepth = 32;
+		unsigned int left = 0; // Defaults to screen center
+		unsigned int top = 0; // Defaults to screen center
+		bool depthBuffer = true;
+		int multisample = 0;
+
+		if(miscParams)
+		{
+			// Get variable-length params
+			NameValuePairList::const_iterator opt;
+			// left (x)
+			opt = miscParams->find("left");
+			if(opt != miscParams->end())
+				left = StringConverter::parseUnsignedInt(opt->second);
+			// top (y)
+			opt = miscParams->find("top");
+			if(opt != miscParams->end())
+				top = StringConverter::parseUnsignedInt(opt->second);
+			// Window title
+			opt = miscParams->find("title");
+			if(opt != miscParams->end())
+				title = opt->second;
+			// externalWindowHandle		-> externalHandle
+			opt = miscParams->find("externalWindowHandle");
+			if(opt != miscParams->end())
+				externalHandle = (HWND)StringConverter::parseUnsignedInt(opt->second);
+			// parentWindowHandle -> parentHWnd
+			opt = miscParams->find("parentWindowHandle");
+			if(opt != miscParams->end()) 
+				parentHWnd = (HWND)StringConverter::parseUnsignedInt(opt->second);
+			// vsync	[parseBool]
+			opt = miscParams->find("vsync");
+			if(opt != miscParams->end())
+				vsync = StringConverter::parseBool(opt->second);
+			// displayFrequency
+			opt = miscParams->find("displayFrequency");
+			if(opt != miscParams->end())
+				displayFrequency = StringConverter::parseUnsignedInt(opt->second);
+			// colourDepth
+			opt = miscParams->find("colourDepth");
+			if(opt != miscParams->end())
+				colourDepth = StringConverter::parseUnsignedInt(opt->second);
+			// depthBuffer [parseBool]
+			opt = miscParams->find("depthBuffer");
+			if(opt != miscParams->end())
+				depthBuffer = StringConverter::parseBool(opt->second);
+			// FSAA
+			opt = miscParams->find("FSAA");
+			if(opt != miscParams->end())
+				multisample = StringConverter::parseUnsignedInt(opt->second);
+		}
+		
+		// Destroy current window if any
+		if( mHWnd )
+			destroy();
+
+        if (fullScreen)
+        {
+			mColourDepth = colourDepth;
+        }
+		else 
+		{
+			// Get colour depth from display
+			mColourDepth = GetDeviceCaps(GetDC(0), BITSPIXEL);
+		}
+
+		if (!externalHandle) {
+			DWORD dwStyle = (fullScreen ? WS_POPUP : WS_OVERLAPPEDWINDOW) | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
+			RECT rc;
+
+			mWidth = width;
+			mHeight = height;
+
+			if (!fullScreen)
+			{
+				// Calculate window dimensions required to get the requested client area
+				SetRect(&rc, 0, 0, mWidth, mHeight);
+				AdjustWindowRect(&rc, dwStyle, false);
+				mWidth = rc.right - rc.left;
+				mHeight = rc.bottom - rc.top;
+
+				// Clamp width and height to the desktop dimensions
+				if (mWidth > (unsigned)GetSystemMetrics(SM_CXSCREEN))
+					mWidth = (unsigned)GetSystemMetrics(SM_CXSCREEN);
+				if (mHeight > (unsigned)GetSystemMetrics(SM_CYSCREEN))
+					mHeight = (unsigned)GetSystemMetrics(SM_CYSCREEN);
+
+				if (!left)
+                {
+					mLeft = (GetSystemMetrics(SM_CXSCREEN) / 2) - (mWidth / 2);
+                }
+				else
+                {
+					mLeft = left;
+                }
+				if (!top)
+                {
+					mTop = (GetSystemMetrics(SM_CYSCREEN) / 2) - (mHeight / 2);
+                }
+				else
+                {
+                    mTop = top;
+                }
+			}
+			else
+            {
+				mTop = mLeft = 0;
+            }
+
+			// Register the window class
+
+			WNDCLASS wndClass = { CS_HREDRAW | CS_VREDRAW | CS_OWNDC,
+				WndProc, 0, 4, hInst,
+				LoadIcon( NULL, IDI_APPLICATION ),
+				LoadCursor( NULL, IDC_ARROW ),
+				(HBRUSH)GetStockObject( BLACK_BRUSH ), NULL,
+				TEXT(title.c_str()) };
+			RegisterClass( &wndClass );
+
+			// Create our main window
+			// Pass pointer to self
+			HWND hWnd = CreateWindowEx(fullScreen?WS_EX_TOPMOST:0, TEXT(title.c_str()), TEXT(title.c_str()),
+				dwStyle, mLeft, mTop, mWidth, mHeight, 0L, 0L, hInst, this);
+			mHWnd = hWnd;
+
+			GetClientRect(mHWnd,&rc);
+			mWidth = rc.right;
+			mHeight = rc.bottom;
+
+            if (fullScreen) {
+			    DEVMODE DevMode;
+			    DevMode.dmSize = sizeof(DevMode);
+			    DevMode.dmBitsPerPel = mColourDepth;
+			    DevMode.dmPelsWidth = mWidth;
+			    DevMode.dmPelsHeight = mHeight;
+			    DevMode.dmDisplayFrequency = displayFrequency;
+			    DevMode.dmFields = DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT|DM_DISPLAYFREQUENCY;
+			    if (ChangeDisplaySettings(&DevMode, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
+				    LogManager::getSingleton().logMessage(LML_CRITICAL, "ChangeDisplaySettingsEx");
+
+		    }
+
+		}
+		else {
+			mHWnd = externalHandle;
+			RECT rc;
+			GetClientRect(mHWnd, &rc);
+			mWidth = rc.right;
+			mHeight = rc.bottom;
+			mLeft = rc.left;
+			mTop = rc.top;
+		}
+		ShowWindow(mHWnd, SW_SHOWNORMAL);
+		UpdateWindow(mHWnd);
+		mName = name;
+		mIsDepthBuffered = depthBuffer;
+		mIsFullScreen = fullScreen;
+
+		
+		HDC hdc = GetDC(mHWnd);
+
+        StringUtil::StrStreamType str;
+        str << "Created Win32Window '"
+            << mName << "' : " << mWidth << "x" << mHeight
+            << ", " << mColourDepth << "bpp";
+        LogManager::getSingleton().logMessage(LML_NORMAL, str.str());
+
+		if (!mGLSupport.selectPixelFormat(hdc, mColourDepth, multisample))
+		{
+			if (multisample == 0)
+				OGRE_EXCEPT(0, "selectPixelFormat failed", "Win32Window::create");
+
+			LogManager::getSingleton().logMessage(LML_NORMAL, "FSAA level not supported, falling back");
+			if (!mGLSupport.selectPixelFormat(hdc, mColourDepth, 0))
+				OGRE_EXCEPT(0, "selectPixelFormat failed", "Win32Window::create");
+		}
+
+		HGLRC glrc = wglCreateContext(hdc);
+		if (!glrc)
+			OGRE_EXCEPT(0, "wglCreateContext", "Win32Window::create");
+		if (!wglMakeCurrent(hdc, glrc))
+			OGRE_EXCEPT(0, "wglMakeCurrent", "Win32Window::create");
+		
+		mGlrc = glrc;
+		mHDC = hdc;
+
+		mOldSwapIntervall = wglGetSwapIntervalEXT();
+		if (vsync) 
+			wglSwapIntervalEXT(1);
+		else
+			wglSwapIntervalEXT(0);
+
+		mReady = true;
+
+        // Create RenderSystem context
+        mContext = new Win32Context(mHDC, mGlrc);
+        // 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 Win32Window::destroy(void)
+    {
+        // Unregister and destroy OGRE GLContext
+        if (mContext)
+        {
+            GLRenderSystem *rs = static_cast<GLRenderSystem*>(Root::getSingleton().getRenderSystem());
+            rs->_unregisterContext(this);
+            delete mContext;
+            mContext = NULL;
+
+            wglSwapIntervalEXT(mOldSwapIntervall);
+        }
+		if (mGlrc) {
+			wglMakeCurrent(NULL, NULL);
+			wglDeleteContext(mGlrc);
+			mGlrc = NULL;
+		}
+		if (mHDC) {
+			ReleaseDC(mHWnd, mHDC);
+			mHDC = NULL;
+		}
+		if (mIsFullScreen)
+		{
+			ChangeDisplaySettings(NULL, 0);
+		}
+        if (mHWnd)
+        {
+	        DestroyWindow(mHWnd);
+            mHWnd = 0;
+        }
+        mActive = false;
+    }
+
+    bool Win32Window::isActive() const
+    {
+        return mActive;
+    }
+
+    bool Win32Window::isClosed() const
+    {
+        return mClosed;
+    }
+
+    void Win32Window::reposition(int left, int top)
+    {
+        // XXX FIXME
+    }
+
+    void Win32Window::resize(unsigned int width, unsigned int height)
+    {
+
+		mWidth = width;
+		mHeight = height;
+
+		// Notify viewports of resize
+		ViewportList::iterator it, itend;
+        itend = mViewportList.end();
+		for( it = mViewportList.begin(); it != itend; ++it )
+			(*it).second->_updateDimensions();
+		// TODO - resize window
+    }
+
+	void Win32Window::windowMovedOrResized()
+	{
+		RECT temprect;
+		::GetClientRect(getWindowHandle(),&temprect);
+		resize(temprect.right-temprect.left,temprect.bottom-temprect.top);
+		// TODO
+	}
+
+    void Win32Window::swapBuffers(bool waitForVSync)
+    {
+		SwapBuffers(mHDC);
+    }
+
+	void Win32Window::writeContentsToFile(const String& filename)
+	{
+		ImageCodec::ImageData *imgData = new ImageCodec::ImageData();
+		imgData->width = mWidth;
+		imgData->height = mHeight;
+		imgData->depth = 1;
+		imgData->format = PF_BYTE_RGB;
+
+		// 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 memory stream
+		DataStreamPtr stream(new MemoryDataStream(pBuffer, mWidth * mHeight * 3, false));
+
+		// Need to flip the read data over in Y though
+		Image img;
+		img.loadRawData(stream, mWidth, mHeight, imgData->format );
+		img.flipAroundX();
+
+		MemoryDataStreamPtr streamFlipped(new MemoryDataStream(img.getData(), stream->size(), false));
+
+		// Get codec 
+		size_t pos = filename.find_last_of(".");
+		String extension;
+		if( pos == String::npos )
+			OGRE_EXCEPT(
+			Exception::ERR_INVALIDPARAMS, 
+			"Unable to determine image type for '" + filename + "' - invalid extension.",
+			"Win32Window::writeContentsToFile" );
+
+		while( pos != filename.length() - 1 )
+			extension += filename[++pos];
+
+		// Get the codec
+		Codec * pCodec = Codec::getCodec(extension);
+
+		// Write out
+		Codec::CodecDataPtr ptr(imgData);
+        pCodec->codeToFile(streamFlipped, filename, ptr);
+
+		delete [] pBuffer;
+	}
+
+#ifdef GTP_VISIBILITY_MODIFIED_OGRE
+	uchar *Win32Window::getBufferContents(int &dimx, int &dimy)
+	{
+		ImageCodec::ImageData *imgData = new ImageCodec::ImageData();
+		dimx = mWidth;
+		dimy = mHeight;
+		
+		// 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);
+
+		return pBuffer;
+	}
+#endif // GTP_VISIBILITY_MODIFIED_OGRE
+
+	// Window procedure callback
+	// This is a static member, so applies to all windows but we store the
+	// Win32Window instance in the window data GetWindowLog/SetWindowLog
+	LRESULT Win32Window::WndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
+	{
+		Win32Window* win;
+
+		// look up window instance
+		if( WM_CREATE != uMsg )
+			win = (Win32Window*)GetWindowLong( hWnd, 0 );
+
+		switch( uMsg )
+		{
+		case WM_ACTIVATE:
+			if( WA_INACTIVE == LOWORD( wParam ) )
+				win->mActive = false;
+			else
+				win->mActive = true;
+			break;
+
+		case WM_CREATE: {
+			// Log the new window
+			// Get CREATESTRUCT
+			LPCREATESTRUCT lpcs = (LPCREATESTRUCT)lParam;
+			win = (Win32Window*)(lpcs->lpCreateParams);
+			// Store pointer in window user data area
+			SetWindowLong( hWnd, 0, (long)win );
+			win->mActive = true;
+
+			return 0; }
+			break;
+
+		case WM_PAINT:
+			// If we get WM_PAINT messges, it usually means our window was
+			// comvered up, so we need to refresh it by re-showing the contents
+			// of the current frame.
+			if( win->mActive && win->mReady )
+				win->update();
+			break;
+
+		case WM_MOVE:
+			// Move messages need to be tracked to update the screen rects
+			// used for blitting the backbuffer to the primary
+			// *** This doesn't need to be used to Direct3D9 ***
+			break;
+
+		case WM_ENTERSIZEMOVE:
+			// Previent rendering while moving / sizing
+			win->mReady = false;
+			break;
+
+		case WM_EXITSIZEMOVE:
+			win->windowMovedOrResized();
+			win->mReady = true;
+			break;
+
+		case WM_SIZE:
+			// Check to see if we are losing or gaining our window.  Set the 
+			// active flag to match
+			if( SIZE_MAXHIDE == wParam || SIZE_MINIMIZED == wParam )
+				win->mActive = false;
+			else
+			{
+				win->mActive = true;
+				if( win->mReady )
+					win->windowMovedOrResized();
+			}
+			break;
+
+		case WM_GETMINMAXINFO:
+			// Prevent the window from going smaller than some minimu size
+			((MINMAXINFO*)lParam)->ptMinTrackSize.x = 100;
+			((MINMAXINFO*)lParam)->ptMinTrackSize.y = 100;
+			break;
+
+		case WM_CLOSE:
+			DestroyWindow( win->mHWnd );
+			win->mClosed = true;
+			return 0;
+		}
+
+		return DefWindowProc( hWnd, uMsg, wParam, lParam );
+	}
+	
+	void Win32Window::getCustomAttribute( const String& name, void* pData )
+	{
+		if( name == "HWND" )
+		{
+			HWND *pHwnd = (HWND*)pData;
+			*pHwnd = getWindowHandle();
+			return;
+		}
+	}
+
+}
