Browse Source

Added GLRenderTexture

Marko Pintera 13 năm trước cách đây
mục cha
commit
9ebcf2cb30

+ 2 - 18
CamelotD3D11RenderSystem/Include/CmD3D11RenderTexture.h

@@ -9,30 +9,14 @@ namespace CamelotEngine
 	class D3D11RenderTexture : public RenderTexture
 	class D3D11RenderTexture : public RenderTexture
 	{
 	{
 	public:
 	public:
-		D3D11RenderTexture(TextureType textureType, UINT32 width, UINT32 height, 
-			PixelFormat format, bool hwGamma, UINT32 fsaa, const String& fsaaHint, 
-			bool createDepth = true, UINT32 depthBits = 32);
-		D3D11RenderTexture(TexturePtr texture, DepthStencilBufferPtr depthStencilbuffer);
+		D3D11RenderTexture();
 		virtual ~D3D11RenderTexture();
 		virtual ~D3D11RenderTexture();
 
 
-		void setBuffers(TexturePtr texture, DepthStencilBufferPtr depthStencilbuffer);
-
-		TexturePtr getTexture() const { return mTexture; }
-		DepthStencilBufferPtr getDepthStencilBuffer() const { return mDepthStencilBuffer; }
-
 		bool requiresTextureFlipping() const { return false; }
 		bool requiresTextureFlipping() const { return false; }
 
 
 	protected:
 	protected:
-		TextureType mType;
-		PixelFormat mFormat;
-		UINT32 mDepthBits;
-
-		TexturePtr mTexture;
-		DepthStencilBufferPtr mDepthStencilBuffer;
 		ID3D11RenderTargetView* mRenderTargetView;
 		ID3D11RenderTargetView* mRenderTargetView;
 
 
-		void createTextureBuffer();
-		void createDepthStencilBuffer();
-		void createResourceView();
+		void createInternalResourcesImpl();
 	};
 	};
 }
 }

+ 20 - 85
CamelotD3D11RenderSystem/Source/CmD3D11RenderTexture.cpp

@@ -9,80 +9,10 @@
 
 
 namespace CamelotEngine
 namespace CamelotEngine
 {
 {
-	D3D11RenderTexture::D3D11RenderTexture(TextureType textureType, UINT32 width, UINT32 height, 
-		PixelFormat format, bool hwGamma, UINT32 fsaa, const String& fsaaHint,
-		bool createDepth, UINT32 depthBits)
-		:mRenderTargetView(nullptr)
+	D3D11RenderTexture::D3D11RenderTexture()
+		:RenderTexture(), mRenderTargetView(nullptr)
 	{
 	{
-		mPriority = CM_REND_TO_TEX_RT_GROUP;
 
 
-		if(textureType != TEX_TYPE_2D)
-			CM_EXCEPT(NotImplementedException, "Render textures are currently only implemented for 2D surfaces.");
-
-		mWidth = width;
-		mHeight = height;
-		mType = textureType;
-		mFormat = format;
-		mColorDepth = CamelotEngine::PixelUtil::getNumElemBits(format);
-		mActive = true;
-		mHwGamma = hwGamma;
-		mFSAA = fsaa;
-		mFSAAHint = fsaaHint;
-		mDepthBits = depthBits;
-
-		createTextureBuffer();
-
-		if(createDepth)
-			createDepthStencilBuffer();
-
-		createResourceView();
-	}
-
-	D3D11RenderTexture::D3D11RenderTexture(TexturePtr texture, DepthStencilBufferPtr depthStencilbuffer)
-		:mRenderTargetView(nullptr)
-	{
-		setBuffers(texture, depthStencilbuffer);
-	}
-
-	void D3D11RenderTexture::setBuffers(TexturePtr texture, DepthStencilBufferPtr depthStencilBuffer)
-	{
-		assert(texture != nullptr);
-		assert(depthStencilBuffer != nullptr);
-
-		SAFE_RELEASE(mRenderTargetView)
-		mPriority = CM_REND_TO_TEX_RT_GROUP;
-
-		if(texture->getTextureType() != TEX_TYPE_2D)
-			CM_EXCEPT(NotImplementedException, "Render textures are currently only implemented for 2D surfaces.");
-
-		if(texture->getWidth() != depthStencilBuffer->getWidth() ||
-			texture->getHeight() != depthStencilBuffer->getWidth() ||
-			texture->getFSAA() != depthStencilBuffer->getFsaa() ||
-			texture->getFSAAHint() != depthStencilBuffer->getFsaaHint())
-		{
-			String errorInfo = "\nWidth: " + toString(texture->getWidth()) + "/" + toString(depthStencilBuffer->getWidth());
-			errorInfo += "\nHeight: " + toString(texture->getHeight()) + "/" + toString(depthStencilBuffer->getHeight());
-			errorInfo += "\nFSAA: " + toString(texture->getFSAA()) + "/" + toString(depthStencilBuffer->getFsaa());
-			errorInfo += "\nFSAAHint: " + texture->getFSAAHint() + "/" + depthStencilBuffer->getFsaaHint();
-
-			CM_EXCEPT(InvalidParametersException, "Provided texture and depth stencil buffer don't match!" + errorInfo);
-		}
-
-		mWidth = texture->getWidth();
-		mHeight = texture->getWidth();
-		mColorDepth = CamelotEngine::PixelUtil::getNumElemBits(texture->getFormat());
-		mActive = true;
-		mHwGamma = texture->isHardwareGammaEnabled();
-		mFSAA = texture->getFSAA();
-		mFSAAHint = texture->getFSAAHint();
-		mType = texture->getTextureType();
-		mFormat = texture->getFormat();
-		mDepthBits = depthStencilBuffer->getBitDepth();
-
-		mTexture = texture;
-		mDepthStencilBuffer = depthStencilBuffer;
-
-		createResourceView();
 	}
 	}
 
 
 	D3D11RenderTexture::~D3D11RenderTexture()
 	D3D11RenderTexture::~D3D11RenderTexture()
@@ -90,18 +20,10 @@ namespace CamelotEngine
 		SAFE_RELEASE(mRenderTargetView);
 		SAFE_RELEASE(mRenderTargetView);
 	}
 	}
 
 
-	void D3D11RenderTexture::createTextureBuffer()
+	void D3D11RenderTexture::createInternalResourcesImpl()
 	{
 	{
-		mTexture = TextureManager::instance().createTexture(mType, mWidth, mHeight, 0, mFormat, TU_RENDERTARGET, mHwGamma, mFSAA, mFSAAHint);
-	}
-
-	void D3D11RenderTexture::createDepthStencilBuffer()
-	{
-		mDepthStencilBuffer = TextureManager::instance().createDepthStencilBuffer(mDepthBits, mWidth, mHeight, mFSAA, mFSAAHint);
-	}
+		SAFE_RELEASE(mRenderTargetView);
 
 
-	void D3D11RenderTexture::createResourceView()
-	{
 		D3D11_RENDER_TARGET_VIEW_DESC RTVDesc;
 		D3D11_RENDER_TARGET_VIEW_DESC RTVDesc;
 		ZeroMemory(&RTVDesc, sizeof(RTVDesc));
 		ZeroMemory(&RTVDesc, sizeof(RTVDesc));
 
 
@@ -117,30 +39,43 @@ namespace CamelotEngine
 			break;
 			break;
 		case D3D11_SRV_DIMENSION_TEXTURE1D:
 		case D3D11_SRV_DIMENSION_TEXTURE1D:
 			RTVDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE1D;
 			RTVDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE1D;
+			RTVDesc.Texture1D.MipSlice = mMipLevel;
 			break;
 			break;
 		case D3D11_SRV_DIMENSION_TEXTURE1DARRAY:
 		case D3D11_SRV_DIMENSION_TEXTURE1DARRAY:
 			RTVDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE1DARRAY;
 			RTVDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE1DARRAY;
+			RTVDesc.Texture1DArray.FirstArraySlice = mFace;
+			RTVDesc.Texture1DArray.ArraySize = mNumFaces;
+			RTVDesc.Texture1DArray.MipSlice = mMipLevel;
 			break;
 			break;
 		case D3D11_SRV_DIMENSION_TEXTURECUBE:
 		case D3D11_SRV_DIMENSION_TEXTURECUBE:
 			RTVDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
 			RTVDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
-			RTVDesc.Texture2DArray.FirstArraySlice = 0;
-			RTVDesc.Texture2DArray.ArraySize = 6;
-			RTVDesc.Texture2DArray.MipSlice = 0;
+			RTVDesc.Texture2DArray.FirstArraySlice = mFace;
+			RTVDesc.Texture2DArray.ArraySize = mNumFaces;
+			RTVDesc.Texture2DArray.MipSlice = mMipLevel;
 			break;
 			break;
 		case D3D11_SRV_DIMENSION_TEXTURE2D:
 		case D3D11_SRV_DIMENSION_TEXTURE2D:
 			RTVDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
 			RTVDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
+			RTVDesc.Texture2D.MipSlice = mMipLevel;
 			break;
 			break;
 		case D3D11_SRV_DIMENSION_TEXTURE2DARRAY:
 		case D3D11_SRV_DIMENSION_TEXTURE2DARRAY:
 			RTVDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
 			RTVDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
+			RTVDesc.Texture2DArray.FirstArraySlice = mFace;
+			RTVDesc.Texture2DArray.ArraySize = mNumFaces;
+			RTVDesc.Texture2DArray.MipSlice = mMipLevel;
 			break;
 			break;
 		case D3D11_SRV_DIMENSION_TEXTURE2DMS:
 		case D3D11_SRV_DIMENSION_TEXTURE2DMS:
 			RTVDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS;
 			RTVDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS;
 			break;
 			break;
 		case D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY:
 		case D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY:
 			RTVDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY;
 			RTVDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY;
+			RTVDesc.Texture2DMSArray.FirstArraySlice = mFace;
+			RTVDesc.Texture2DMSArray.ArraySize = mNumFaces;
 			break;
 			break;
 		case D3D11_SRV_DIMENSION_TEXTURE3D:
 		case D3D11_SRV_DIMENSION_TEXTURE3D:
 			RTVDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
 			RTVDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
+			RTVDesc.Texture3D.MipSlice = mMipLevel;
+			RTVDesc.Texture3D.FirstWSlice = mFace;
+			RTVDesc.Texture3D.WSize = mNumFaces;
 			break;
 			break;
 		default:
 		default:
 			assert(false);
 			assert(false);

+ 0 - 4
CamelotD3D9Renderer/Include/CmD3D9Texture.h

@@ -208,10 +208,6 @@ namespace CamelotEngine {
 		virtual void getCustomAttribute_internal( const String& name, void *pData );
 		virtual void getCustomAttribute_internal( const String& name, void *pData );
 
 
 		bool requiresTextureFlipping() const { return false; }
 		bool requiresTextureFlipping() const { return false; }
-
-		/// Override needed to deal with FSAA
-		void swapBuffers(bool waitForVSync = true);
-
 	protected:
 	protected:
 		D3D9HardwarePixelBuffer* mBuffer;
 		D3D9HardwarePixelBuffer* mBuffer;
 
 

+ 0 - 28
CamelotD3D9Renderer/Source/CmD3D9Texture.cpp

@@ -1281,34 +1281,6 @@ namespace CamelotEngine
 			return;
 			return;
 		}
 		}
 	}    
 	}    
-	//---------------------------------------------------------------------
-	void D3D9RenderTexture::swapBuffers(bool waitForVSync /* = true */)
-	{
-		// Only needed if we have to blit from AA surface
-		if (mFSAA > 0)
-		{
-			D3D9DeviceManager* deviceManager = D3D9RenderSystem::getDeviceManager();     					
-			D3D9HardwarePixelBuffer* buf = static_cast<D3D9HardwarePixelBuffer*>(mBuffer);
-
-			for (UINT i=0; i < deviceManager->getDeviceCount(); ++i)
-			{
-				D3D9Device* device = deviceManager->getDevice(i);
-				 				
-				if (device->isDeviceLost() == false)
-				{
-					IDirect3DDevice9* d3d9Device = device->getD3D9Device();
-
-					HRESULT hr = d3d9Device->StretchRect(buf->getFSAASurface(d3d9Device), 0, 
-						buf->getSurface(d3d9Device), 0, D3DTEXF_NONE);
-
-					if (FAILED(hr))
-					{
-						CM_EXCEPT(InternalErrorException, "Unable to copy AA buffer to final buffer: " + String(DXGetErrorDescription(hr)));
-					}
-				}								
-			}																		
-		}			
-	}	
 }
 }
 
 
 #undef THROW_IF_NOT_RENDER_THREAD
 #undef THROW_IF_NOT_RENDER_THREAD

+ 6 - 1
CamelotGLRenderer/Include/CmGLDepthStencilBuffer.h

@@ -9,6 +9,11 @@ namespace CamelotEngine
 	{
 	{
 	public:
 	public:
 		GLDepthStencilBuffer(UINT32 bitDepth, UINT32 width, UINT32 height, UINT32 fsaa, const String &fsaaHint);
 		GLDepthStencilBuffer(UINT32 bitDepth, UINT32 width, UINT32 height, UINT32 fsaa, const String &fsaaHint);
-		// TODO - Add GL specific implementation
+		~GLDepthStencilBuffer();
+
+		GLRenderBufferPtr getGLRenderBuffer() const { return mDepthStencilRenderBuffer; }
+
+	protected:
+		GLRenderBufferPtr mDepthStencilRenderBuffer;
 	};
 	};
 }
 }

+ 21 - 18
CamelotGLRenderer/Include/CmGLFrameBufferObject.h

@@ -28,7 +28,9 @@ THE SOFTWARE.
 #ifndef __OgreGLFBO_H__
 #ifndef __OgreGLFBO_H__
 #define __OgreGLFBO_H__
 #define __OgreGLFBO_H__
 
 
+#include "CmGLPrerequisites.h"
 #include "CmGLContext.h"
 #include "CmGLContext.h"
+#include "CmGLHardwarePixelBuffer.h"
 #include "CmPixelData.h"
 #include "CmPixelData.h"
 
 
 namespace CamelotEngine 
 namespace CamelotEngine 
@@ -38,7 +40,7 @@ namespace CamelotEngine
     struct CM_RSGL_EXPORT GLSurfaceDesc
     struct CM_RSGL_EXPORT GLSurfaceDesc
     {
     {
     public:
     public:
-        GLHardwarePixelBuffer *buffer;
+        GLHardwarePixelBufferPtr buffer;
         UINT32 zoffset;
         UINT32 zoffset;
 		UINT32 numSamples;
 		UINT32 numSamples;
 
 
@@ -50,47 +52,48 @@ namespace CamelotEngine
     class CM_RSGL_EXPORT GLFrameBufferObject
     class CM_RSGL_EXPORT GLFrameBufferObject
     {
     {
     public:
     public:
-        GLFrameBufferObject(GLRTTManager *manager, UINT32 fsaa);
+        GLFrameBufferObject(UINT32 fsaa);
         ~GLFrameBufferObject();
         ~GLFrameBufferObject();
-        //void bindSurface(size_t attachment, RenderTarget *target);
+
         /** Bind a surface to a certain attachment point.
         /** Bind a surface to a certain attachment point.
             attachment: 0..CM_MAX_MULTIPLE_RENDER_TARGETS-1
             attachment: 0..CM_MAX_MULTIPLE_RENDER_TARGETS-1
         */
         */
         void bindSurface(UINT32 attachment, const GLSurfaceDesc &target);
         void bindSurface(UINT32 attachment, const GLSurfaceDesc &target);
+
         /** Unbind attachment
         /** Unbind attachment
         */
         */
         void unbindSurface(UINT32 attachment);
         void unbindSurface(UINT32 attachment);
+
+		/**
+		 * @brief	Bind depth stencil buffer.
+		 */
+		void bindDepthStencil(GLHardwarePixelBufferPtr depthStencilBuffer);
+
+		/**
+		 * @brief	Unbinds depth stencil buffer.
+		 */
+		void unbindDepthStencil();
         
         
         /** Bind FrameBufferObject
         /** Bind FrameBufferObject
         */
         */
         void bind();
         void bind();
 
 
-		/** Swap buffers - only useful when using multisample buffers.
-		*/
-		void swapBuffers();
-		
 		/// Get the GL id for the FBO
 		/// Get the GL id for the FBO
 		GLuint getGLFBOID() const { return mFB; }
 		GLuint getGLFBOID() const { return mFB; }
-		/// Get the GL id for the multisample FBO
-		GLuint getGLMultisampleFBOID() const { return mMultisampleFB; }
-        
+
         /// Accessors
         /// Accessors
         UINT32 getWidth();
         UINT32 getWidth();
         UINT32 getHeight();
         UINT32 getHeight();
         PixelFormat getFormat();
         PixelFormat getFormat();
         
         
-		const GLSurfaceDesc &getSurface(UINT32 attachment) { return mColour[attachment]; }
+		const GLSurfaceDesc &getSurface(UINT32 attachment) { return mColor[attachment]; }
     private:
     private:
-        GLRTTManager *mManager;
 		GLsizei mNumSamples;
 		GLsizei mNumSamples;
         GLuint mFB;
         GLuint mFB;
-		GLuint mMultisampleFB;
-		GLSurfaceDesc mMultisampleColourBuffer;
-        GLSurfaceDesc mDepth;
-        GLSurfaceDesc mStencil;
-        // Arbitrary number of texture surfaces
-        GLSurfaceDesc mColour[CM_MAX_MULTIPLE_RENDER_TARGETS];
 
 
+        GLHardwarePixelBufferPtr mDepthStencilBuffer;
+        // Arbitrary number of texture surfaces
+        GLSurfaceDesc mColor[CM_MAX_MULTIPLE_RENDER_TARGETS];
 
 
 		/** Initialise object (find suitable depth and stencil format).
 		/** Initialise object (find suitable depth and stencil format).
             Must be called every time the bindings change.
             Must be called every time the bindings change.

+ 7 - 0
CamelotGLRenderer/Include/CmGLPixelFormat.h

@@ -71,6 +71,13 @@ namespace CamelotEngine {
 			@remarks It is valid for this function to always return PF_A8R8G8B8.
 			@remarks It is valid for this function to always return PF_A8R8G8B8.
 		*/
 		*/
 		static PixelFormat getClosestEngineFormat(GLenum fmt);
 		static PixelFormat getClosestEngineFormat(GLenum fmt);
+
+		/**
+		 * @brief	Gets OpenGL format based on a compressed OpenGL internal format.
+		 * 			e.g. GL_COMPRESSED_RGBA_S3TC_DXT1_EXT will return GL_RGBA
+		 *
+		 */
+		static GLenum getBaseFormatFromCompressedInternalFormat(GLenum internalFormat);
 	
 	
 		/** Returns the maximum number of Mipmaps that can be generated until we reach
 		/** Returns the maximum number of Mipmaps that can be generated until we reach
 			the mininum format possible. This does not count the base level.
 			the mininum format possible. This does not count the base level.

+ 3 - 0
CamelotGLRenderer/Include/CmGLPrerequisites.h

@@ -42,6 +42,9 @@ namespace CamelotEngine {
     class GLHardwarePixelBuffer;
     class GLHardwarePixelBuffer;
     class GLRenderBuffer;
     class GLRenderBuffer;
 
 
+	typedef std::shared_ptr<GLHardwarePixelBuffer> GLHardwarePixelBufferPtr;
+	typedef std::shared_ptr<GLRenderBuffer> GLRenderBufferPtr;
+
 	enum TypeID_D3D9
 	enum TypeID_D3D9
 	{
 	{
 		TID_GL_GLSLProgram = 11000
 		TID_GL_GLSLProgram = 11000

+ 10 - 100
CamelotGLRenderer/Include/CmGLRenderTexture.h

@@ -43,60 +43,27 @@ namespace CamelotEngine
     */
     */
     class CM_RSGL_EXPORT GLRenderTexture: public RenderTexture
     class CM_RSGL_EXPORT GLRenderTexture: public RenderTexture
     {
     {
-    public:
-        GLRenderTexture(GLRTTManager* manager, const String &name, const GLSurfaceDesc &target, bool writeGamma, UINT32 fsaa);
-        virtual ~GLRenderTexture();
-        
-        bool requiresTextureFlipping() const { return true; }
+	public:
+		GLRenderTexture();
+		virtual ~GLRenderTexture();
 
 
+		bool requiresTextureFlipping() const { return false; }
 		virtual void getCustomAttribute_internal(const String& name, void* pData);
 		virtual void getCustomAttribute_internal(const String& name, void* pData);
 
 
-		virtual void swapBuffers(bool waitForVSync = true);
 	protected:
 	protected:
-		GLFrameBufferObject mFB;
+		GLFrameBufferObject* mFB;
+
+		void createInternalResourcesImpl();
     };
     };
-    
+
     /** Manager/factory for RenderTextures.
     /** Manager/factory for RenderTextures.
     */
     */
     class CM_RSGL_EXPORT GLRTTManager : public Module<GLRTTManager>
     class CM_RSGL_EXPORT GLRTTManager : public Module<GLRTTManager>
     {
     {
     public:
     public:
-        GLRTTManager(bool atimode);
+        GLRTTManager();
 		~GLRTTManager();
 		~GLRTTManager();
         
         
-        /** Bind a certain render target if it is a FBO. If it is not a FBO, bind the
-            main frame buffer.
-        */
-        void bind(RenderTarget *target);
-        
-        /** Unbind a certain render target. No-op for FBOs.
-        */
-        void unbind(RenderTarget *target) {};
-        
-        /** Get best depth and stencil supported for given internalFormat
-        */
-        void getBestDepthStencil(GLenum internalFormat, GLenum *depthFormat, GLenum *stencilFormat);
-        
-        /** Create a texture rendertarget object
-        */
-        virtual GLRenderTexture *createRenderTexture(const String &name, 
-			const GLSurfaceDesc &target, bool writeGamma, UINT32 fsaa);
-
-		/** Create a multi render target 
-		*/
-		virtual MultiRenderTarget* createMultiRenderTarget(const String & name);
-        
-        /** Request a render buffer. If format is GL_NONE, return a zero buffer.
-        */
-        GLSurfaceDesc requestRenderBuffer(GLenum format, UINT32 width, UINT32 height, UINT32 fsaa);
-        /** Request the specify render buffer in case shared somewhere. Ignore
-            silently if surface.buffer is 0.
-        */
-        void requestRenderBuffer(const GLSurfaceDesc &surface);
-        /** Release a render buffer. Ignore silently if surface.buffer is 0.
-        */
-        void releaseRenderBuffer(const GLSurfaceDesc &surface);
-        
         /** Check if a certain format is usable as FBO rendertarget format
         /** Check if a certain format is usable as FBO rendertarget format
         */
         */
         bool checkFormat(PixelFormat format) { return mProps[format].valid; }
         bool checkFormat(PixelFormat format) { return mProps[format].valid; }
@@ -128,72 +95,15 @@ namespace CamelotEngine
         /** Properties for all internal formats defined by the engine
         /** Properties for all internal formats defined by the engine
         */
         */
         FormatProperties mProps[PF_COUNT];
         FormatProperties mProps[PF_COUNT];
-        
-        /** Stencil and depth renderbuffers of the same format are re-used between surfaces of the 
-            same size and format. This can save a lot of memory when a large amount of rendertargets
-            are used.
-        */
-        struct RBFormat
-        {
-            RBFormat(GLenum inFormat, UINT32 inWidth, UINT32 inHeight, UINT32 fsaa):
-                format(inFormat), width(inWidth), height(inHeight), samples(fsaa)
-            {}
-            GLenum format;
-            UINT32 width;
-            UINT32 height;
-			UINT32 samples;
-            // Overloaded comparison operator for usage in map
-            bool operator < (const RBFormat &other) const
-            {
-                if(format < other.format)
-                {
-                    return true;
-                }
-                else if(format == other.format)
-                {
-                    if(width < other.width)
-                    {
-                        return true;
-                    }
-                    else if(width == other.width)
-                    {
-                        if(height < other.height)
-                            return true;
-						else if (height == other.height)
-						{
-							if (samples < other.samples)
-								return true;
-						}
-                    }
-                }
-                return false;
-            }
-        };
-        struct RBRef
-        {
-            RBRef(){}
-            RBRef(GLRenderBuffer *inBuffer):
-                buffer(inBuffer), refcount(1)
-            { }
-            GLRenderBuffer *buffer;
-            size_t refcount;
-        };
-        typedef map<RBFormat, RBRef>::type RenderBufferMap;
-        RenderBufferMap mRenderBufferMap;
-        // map(format, sizex, sizey) -> [GLSurface*,refcount]
-        
+
         /** Temporary FBO identifier
         /** Temporary FBO identifier
          */
          */
         GLuint mTempFBO;
         GLuint mTempFBO;
         
         
-		/// Buggy ATI driver?
-		bool mATIMode;
-        
         /** Detect allowed FBO formats */
         /** Detect allowed FBO formats */
         void detectFBOFormats();
         void detectFBOFormats();
         GLuint _tryFormat(GLenum depthFormat, GLenum stencilFormat);
         GLuint _tryFormat(GLenum depthFormat, GLenum stencilFormat);
         bool _tryPackedFormat(GLenum packedFormat);
         bool _tryPackedFormat(GLenum packedFormat);
-       
     };
     };
 }
 }
 
 

+ 16 - 16
CamelotGLRenderer/Include/CmGLTexture.h

@@ -43,12 +43,26 @@ namespace CamelotEngine {
         virtual ~GLTexture();      
         virtual ~GLTexture();      
 
 
         // Takes the OGRE texture type (1d/2d/3d/cube) and returns the appropriate GL one
         // Takes the OGRE texture type (1d/2d/3d/cube) and returns the appropriate GL one
-        GLenum getGLTextureTarget_internal(void) const;
+        GLenum getGLTextureTarget(void) const;
 
 
-        GLuint getGLID_internal() const;
+        GLuint getGLID() const;
 		
 		
 		void getCustomAttribute_internal(const String& name, void* pData);
 		void getCustomAttribute_internal(const String& name, void* pData);
 
 
+		/** Return hardware pixel buffer for a surface. This buffer can then
+			be used to copy data from and to a particular level of the texture.
+			@param face 	Face number, in case of a cubemap texture. Must be 0
+							for other types of textures.
+                            For cubemaps, this is one of 
+                            +X (0), -X (1), +Y (2), -Y (3), +Z (4), -Z (5)
+			@param mipmap	Mipmap level. This goes from 0 for the first, largest
+							mipmap level to getNumMipmaps()-1 for the smallest.
+			@returns	A shared pointer to a hardware pixel buffer
+			@remarks	The buffer is invalidated when the resource is unloaded or destroyed.
+						Do not use it after the lifetime of the containing texture.
+		*/
+		HardwarePixelBufferPtr getBuffer(UINT32 face, UINT32 mipmap);
+
     protected:
     protected:
 		friend class GLTextureManager;
 		friend class GLTextureManager;
 
 
@@ -74,20 +88,6 @@ namespace CamelotEngine {
 		*/
 		*/
 		void createSurfaceList();
 		void createSurfaceList();
 
 
-		/** Return hardware pixel buffer for a surface. This buffer can then
-			be used to copy data from and to a particular level of the texture.
-			@param face 	Face number, in case of a cubemap texture. Must be 0
-							for other types of textures.
-                            For cubemaps, this is one of 
-                            +X (0), -X (1), +Y (2), -Y (3), +Z (4), -Z (5)
-			@param mipmap	Mipmap level. This goes from 0 for the first, largest
-							mipmap level to getNumMipmaps()-1 for the smallest.
-			@returns	A shared pointer to a hardware pixel buffer
-			@remarks	The buffer is invalidated when the resource is unloaded or destroyed.
-						Do not use it after the lifetime of the containing texture.
-		*/
-		HardwarePixelBufferPtr getBuffer(UINT32 face, UINT32 mipmap);
-
     private:
     private:
         GLuint mTextureID;
         GLuint mTextureID;
         GLSupport& mGLSupport;
         GLSupport& mGLSupport;

+ 9 - 1
CamelotGLRenderer/Source/CmGLDepthStencilBuffer.cpp

@@ -1,8 +1,16 @@
 #include "CmGLDepthStencilBuffer.h"
 #include "CmGLDepthStencilBuffer.h"
+#include "CmGLHardwarePixelBuffer.h"
 
 
 namespace CamelotEngine
 namespace CamelotEngine
 {
 {
 	GLDepthStencilBuffer::GLDepthStencilBuffer(UINT32 bitDepth, UINT32 width, UINT32 height, UINT32 fsaa, const String &fsaaHint)
 	GLDepthStencilBuffer::GLDepthStencilBuffer(UINT32 bitDepth, UINT32 width, UINT32 height, UINT32 fsaa, const String &fsaaHint)
 		:DepthStencilBuffer(bitDepth, width, height, fsaa, fsaaHint)
 		:DepthStencilBuffer(bitDepth, width, height, fsaa, fsaaHint)
-	{ }
+	{
+		mDepthStencilRenderBuffer = GLRenderBufferPtr(new GLRenderBuffer(GL_DEPTH24_STENCIL8_EXT, width, height, fsaa));
+	}
+
+	GLDepthStencilBuffer::~GLDepthStencilBuffer()
+	{
+
+	}
 }
 }

+ 58 - 148
CamelotGLRenderer/Source/CmGLFrameBufferObject.cpp

@@ -31,11 +31,10 @@ THE SOFTWARE.
 #include "CmGLHardwarePixelBuffer.h"
 #include "CmGLHardwarePixelBuffer.h"
 #include "CmGLRenderTexture.h"
 #include "CmGLRenderTexture.h"
 
 
-namespace CamelotEngine {
-
-//-----------------------------------------------------------------------------
-    GLFrameBufferObject::GLFrameBufferObject(GLRTTManager *manager, UINT32 fsaa):
-        mManager(manager), mNumSamples(fsaa)
+namespace CamelotEngine 
+{
+    GLFrameBufferObject::GLFrameBufferObject(UINT32 fsaa)
+		:mNumSamples(fsaa)
     {
     {
         /// Generate framebuffer object
         /// Generate framebuffer object
         glGenFramebuffersEXT(1, &mFB);
         glGenFramebuffersEXT(1, &mFB);
@@ -53,102 +52,90 @@ namespace CamelotEngine {
 		{
 		{
 			mNumSamples = 0;
 			mNumSamples = 0;
 		}
 		}
-		// will we need a second FBO to do multisampling?
-		if (mNumSamples)
-		{
-			glGenFramebuffersEXT(1, &mMultisampleFB);
-		}
-		else
-		{
-			mMultisampleFB = 0;
-		}
+
         /// Initialise state
         /// Initialise state
-        mDepth.buffer=0;
-        mStencil.buffer=0;
-        for(UINT32 x=0; x<CM_MAX_MULTIPLE_RENDER_TARGETS; ++x)
-        {
-            mColour[x].buffer=0;
-        }
+        for(UINT32 x = 0; x < CM_MAX_MULTIPLE_RENDER_TARGETS; ++x)
+            mColor[x].buffer = nullptr;
     }
     }
+
     GLFrameBufferObject::~GLFrameBufferObject()
     GLFrameBufferObject::~GLFrameBufferObject()
     {
     {
-        mManager->releaseRenderBuffer(mDepth);
-        mManager->releaseRenderBuffer(mStencil);
-		mManager->releaseRenderBuffer(mMultisampleColourBuffer);
         /// Delete framebuffer object
         /// Delete framebuffer object
         glDeleteFramebuffersEXT(1, &mFB);        
         glDeleteFramebuffersEXT(1, &mFB);        
-		if (mMultisampleFB)
-			glDeleteFramebuffersEXT(1, &mMultisampleFB);
-
     }
     }
+
     void GLFrameBufferObject::bindSurface(UINT32 attachment, const GLSurfaceDesc &target)
     void GLFrameBufferObject::bindSurface(UINT32 attachment, const GLSurfaceDesc &target)
     {
     {
         assert(attachment < CM_MAX_MULTIPLE_RENDER_TARGETS);
         assert(attachment < CM_MAX_MULTIPLE_RENDER_TARGETS);
-        mColour[attachment] = target;
+        mColor[attachment] = target;
+
 		// Re-initialise
 		// Re-initialise
-		if(mColour[0].buffer)
+		if(mColor[0].buffer)
 			initialise();
 			initialise();
     }
     }
+
     void GLFrameBufferObject::unbindSurface(UINT32 attachment)
     void GLFrameBufferObject::unbindSurface(UINT32 attachment)
     {
     {
         assert(attachment < CM_MAX_MULTIPLE_RENDER_TARGETS);
         assert(attachment < CM_MAX_MULTIPLE_RENDER_TARGETS);
-        mColour[attachment].buffer = 0;
+        mColor[attachment].buffer = nullptr;
+
 		// Re-initialise if buffer 0 still bound
 		// Re-initialise if buffer 0 still bound
-		if(mColour[0].buffer)
+		if(mColor[0].buffer)
 		{
 		{
 			initialise();
 			initialise();
 		}
 		}
     }
     }
+
+	void GLFrameBufferObject::bindDepthStencil(GLHardwarePixelBufferPtr depthStencilBuffer)
+	{
+		mDepthStencilBuffer = depthStencilBuffer;
+	}
+
+	void GLFrameBufferObject::unbindDepthStencil()
+	{
+		mDepthStencilBuffer = nullptr;
+	}
+
     void GLFrameBufferObject::initialise()
     void GLFrameBufferObject::initialise()
     {
     {
-		// Release depth and stencil, if they were bound
-        mManager->releaseRenderBuffer(mDepth);
-        mManager->releaseRenderBuffer(mStencil);
-		mManager->releaseRenderBuffer(mMultisampleColourBuffer);
         /// First buffer must be bound
         /// First buffer must be bound
-        if(!mColour[0].buffer)
-        {
-			CM_EXCEPT(InvalidParametersException, 
-            "Attachment 0 must have surface attached");
-        }
-
-		// If we're doing multisampling, then we need another FBO which contains a
-		// renderbuffer which is set up to multisample, and we'll blit it to the final 
-		// FBO afterwards to perform the multisample resolve. In that case, the 
-		// mMultisampleFB is bound during rendering and is the one with a depth/stencil
+        if(!mColor[0].buffer)
+			CM_EXCEPT(InvalidParametersException, "Attachment 0 must have surface attached");
 
 
         /// Store basic stats
         /// Store basic stats
-        UINT32 width = mColour[0].buffer->getWidth();
-        UINT32 height = mColour[0].buffer->getHeight();
-        GLuint glformat = mColour[0].buffer->getGLFormat();
-        PixelFormat format = mColour[0].buffer->getFormat();
+        UINT32 width = mColor[0].buffer->getWidth();
+        UINT32 height = mColor[0].buffer->getHeight();
+        GLuint glformat = mColor[0].buffer->getGLFormat();
+        PixelFormat format = mColor[0].buffer->getFormat();
         UINT16 maxSupportedMRTs = CamelotEngine::RenderSystem::instancePtr()->getCapabilities()->getNumMultiRenderTargets();
         UINT16 maxSupportedMRTs = CamelotEngine::RenderSystem::instancePtr()->getCapabilities()->getNumMultiRenderTargets();
 
 
 		// Bind simple buffer to add colour attachments
 		// Bind simple buffer to add colour attachments
 		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFB);
 		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFB);
 
 
         /// Bind all attachment points to frame buffer
         /// Bind all attachment points to frame buffer
-        for(UINT16 x=0; x<maxSupportedMRTs; ++x)
+        for(UINT16 x = 0; x < maxSupportedMRTs; ++x)
         {
         {
-            if(mColour[x].buffer)
+            if(mColor[x].buffer)
             {
             {
-                if(mColour[x].buffer->getWidth() != width || mColour[x].buffer->getHeight() != height)
+                if(mColor[x].buffer->getWidth() != width || mColor[x].buffer->getHeight() != height)
                 {
                 {
                     StringStream ss;
                     StringStream ss;
                     ss << "Attachment " << x << " has incompatible size ";
                     ss << "Attachment " << x << " has incompatible size ";
-                    ss << mColour[x].buffer->getWidth() << "x" << mColour[x].buffer->getHeight();
+                    ss << mColor[x].buffer->getWidth() << "x" << mColor[x].buffer->getHeight();
                     ss << ". It must be of the same as the size of surface 0, ";
                     ss << ". It must be of the same as the size of surface 0, ";
                     ss << width << "x" << height;
                     ss << width << "x" << height;
                     ss << ".";
                     ss << ".";
                     CM_EXCEPT(InvalidParametersException, ss.str());
                     CM_EXCEPT(InvalidParametersException, ss.str());
                 }
                 }
-                if(mColour[x].buffer->getGLFormat() != glformat)
+
+                if(mColor[x].buffer->getGLFormat() != glformat)
                 {
                 {
                     StringStream ss;
                     StringStream ss;
                     ss << "Attachment " << x << " has incompatible format.";
                     ss << "Attachment " << x << " has incompatible format.";
                     CM_EXCEPT(InvalidParametersException, ss.str());
                     CM_EXCEPT(InvalidParametersException, ss.str());
                 }
                 }
-	            mColour[x].buffer->bindToFramebuffer(GL_COLOR_ATTACHMENT0_EXT+x, mColour[x].zoffset);
+
+	            mColor[x].buffer->bindToFramebuffer(GL_COLOR_ATTACHMENT0_EXT+x, mColor[x].zoffset);
             }
             }
             else
             else
             {
             {
@@ -158,63 +145,7 @@ namespace CamelotEngine {
             }
             }
         }
         }
 
 
-		// Now deal with depth / stencil
-		if (mMultisampleFB)
-		{
-			// Bind multisample buffer
-			glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mMultisampleFB);
-
-			// Create AA render buffer (colour)
-			// note, this can be shared too because we blit it to the final FBO
-			// right after the render is finished
-			mMultisampleColourBuffer = mManager->requestRenderBuffer(glformat, width, height, mNumSamples);
-
-			// Attach it, because we won't be attaching below and non-multisample has
-			// actually been attached to other FBO
-			mMultisampleColourBuffer.buffer->bindToFramebuffer(GL_COLOR_ATTACHMENT0_EXT, 
-				mMultisampleColourBuffer.zoffset);
-
-			// depth & stencil will be dealt with below
-
-		}
-
-        /// Find suitable depth and stencil format that is compatible with colour format
-        GLenum depthFormat, stencilFormat;
-        mManager->getBestDepthStencil(format, &depthFormat, &stencilFormat);
-        
-        /// Request surfaces
-        mDepth = mManager->requestRenderBuffer(depthFormat, width, height, mNumSamples);
-		if (depthFormat == GL_DEPTH24_STENCIL8_EXT)
-		{
-			// bind same buffer to depth and stencil attachments
-            mManager->requestRenderBuffer(mDepth);
-			mStencil = mDepth;
-		}
-		else
-		{
-			// separate stencil
-			mStencil = mManager->requestRenderBuffer(stencilFormat, width, height, mNumSamples);
-		}
-        
-        /// Attach/detach surfaces
-        if(mDepth.buffer)
-        {
-            mDepth.buffer->bindToFramebuffer(GL_DEPTH_ATTACHMENT_EXT, mDepth.zoffset);
-        }
-        else
-        {
-            glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
-                GL_RENDERBUFFER_EXT, 0);
-        }
-        if(mStencil.buffer)
-        {
-            mStencil.buffer->bindToFramebuffer(GL_STENCIL_ATTACHMENT_EXT, mStencil.zoffset);
-        }
-        else
-        {
-            glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT,
-                GL_RENDERBUFFER_EXT, 0);
-        }
+		mDepthStencilBuffer->bindToFramebuffer(GL_DEPTH_STENCIL_ATTACHMENT, 0);
 
 
 		/// Do glDrawBuffer calls
 		/// Do glDrawBuffer calls
 		GLenum bufs[CM_MAX_MULTIPLE_RENDER_TARGETS];
 		GLenum bufs[CM_MAX_MULTIPLE_RENDER_TARGETS];
@@ -222,7 +153,7 @@ namespace CamelotEngine {
 		for(UINT32 x=0; x<CM_MAX_MULTIPLE_RENDER_TARGETS; ++x)
 		for(UINT32 x=0; x<CM_MAX_MULTIPLE_RENDER_TARGETS; ++x)
 		{
 		{
 			// Fill attached colour buffers
 			// Fill attached colour buffers
-			if(mColour[x].buffer)
+			if(mColor[x].buffer)
 			{
 			{
 				bufs[x] = GL_COLOR_ATTACHMENT0_EXT + x;
 				bufs[x] = GL_COLOR_ATTACHMENT0_EXT + x;
 				// Keep highest used buffer + 1
 				// Keep highest used buffer + 1
@@ -233,6 +164,7 @@ namespace CamelotEngine {
 				bufs[x] = GL_NONE;
 				bufs[x] = GL_NONE;
 			}
 			}
 		}
 		}
+
 		if(glDrawBuffers)
 		if(glDrawBuffers)
 		{
 		{
 			/// Drawbuffer extension supported, use it
 			/// Drawbuffer extension supported, use it
@@ -243,17 +175,10 @@ namespace CamelotEngine {
 			/// In this case, the capabilities will not show more than 1 simultaneaous render target.
 			/// In this case, the capabilities will not show more than 1 simultaneaous render target.
 			glDrawBuffer(bufs[0]);
 			glDrawBuffer(bufs[0]);
 		}
 		}
-		if (mMultisampleFB)
-		{
-			// we need a read buffer because we'll be blitting to mFB
-			glReadBuffer(bufs[0]);
-		}
-		else
-		{
-			/// No read buffer, by default, if we want to read anyway we must not forget to set this.
-			glReadBuffer(GL_NONE);
-		}
-        
+
+		/// No read buffer, by default, if we want to read anyway we must not forget to set this.
+		glReadBuffer(GL_NONE);
+
         /// Check status
         /// Check status
         GLuint status;
         GLuint status;
         status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
         status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
@@ -273,44 +198,29 @@ namespace CamelotEngine {
             CM_EXCEPT(InvalidParametersException, 
             CM_EXCEPT(InvalidParametersException, 
             "Framebuffer incomplete or other FBO status error");
             "Framebuffer incomplete or other FBO status error");
         }
         }
-        
     }
     }
+
     void GLFrameBufferObject::bind()
     void GLFrameBufferObject::bind()
     {
     {
         /// Bind it to FBO
         /// Bind it to FBO
-		if (mMultisampleFB)
-			glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mMultisampleFB);
-		else
-			glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFB);
+		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFB);
     }
     }
 
 
-	void GLFrameBufferObject::swapBuffers()
-	{
-		if (mMultisampleFB)
-		{
-			// blit from multisample buffer to final buffer, triggers resolve
-			UINT32 width = mColour[0].buffer->getWidth();
-			UINT32 height = mColour[0].buffer->getHeight();
-			glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, mMultisampleFB);
-			glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, mFB);
-			glBlitFramebufferEXT(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
-
-		}
-	}
-
     UINT32 GLFrameBufferObject::getWidth()
     UINT32 GLFrameBufferObject::getWidth()
     {
     {
-        assert(mColour[0].buffer);
-        return mColour[0].buffer->getWidth();
+        assert(mColor[0].buffer);
+        return mColor[0].buffer->getWidth();
     }
     }
+
     UINT32 GLFrameBufferObject::getHeight()
     UINT32 GLFrameBufferObject::getHeight()
     {
     {
-        assert(mColour[0].buffer);
-        return mColour[0].buffer->getHeight();
+        assert(mColor[0].buffer);
+        return mColor[0].buffer->getHeight();
     }
     }
+
     PixelFormat GLFrameBufferObject::getFormat()
     PixelFormat GLFrameBufferObject::getFormat()
     {
     {
-        assert(mColour[0].buffer);
-        return mColour[0].buffer->getFormat();
+        assert(mColor[0].buffer);
+        return mColor[0].buffer->getFormat();
     }
     }
 }
 }

+ 659 - 693
CamelotGLRenderer/Source/CmGLHardwarePixelBuffer.cpp

@@ -33,790 +33,756 @@ THE SOFTWARE.
 #include "CmBitwise.h"
 #include "CmBitwise.h"
 #include "CmGLRenderTexture.h"
 #include "CmGLRenderTexture.h"
 
 
-namespace CamelotEngine {
-//----------------------------------------------------------------------------- 
-GLHardwarePixelBuffer::GLHardwarePixelBuffer(UINT32 inWidth, UINT32 inHeight, UINT32 inDepth,
-                PixelFormat inFormat,
-                HardwareBuffer::Usage usage):
-      HardwarePixelBuffer(inWidth, inHeight, inDepth, inFormat, usage, false),
-      mBuffer(inWidth, inHeight, inDepth, inFormat),
-      mGLInternalFormat(GL_NONE)
+namespace CamelotEngine 
 {
 {
-    mCurrentLockOptions = (LockOptions)0;
-}
+	//----------------------------------------------------------------------------- 
+	GLHardwarePixelBuffer::GLHardwarePixelBuffer(UINT32 inWidth, UINT32 inHeight, UINT32 inDepth,
+					PixelFormat inFormat,
+					HardwareBuffer::Usage usage):
+		  HardwarePixelBuffer(inWidth, inHeight, inDepth, inFormat, usage, false),
+		  mBuffer(inWidth, inHeight, inDepth, inFormat),
+		  mGLInternalFormat(GL_NONE)
+	{
+		mCurrentLockOptions = (LockOptions)0;
+	}
 
 
-//-----------------------------------------------------------------------------  
-GLHardwarePixelBuffer::~GLHardwarePixelBuffer()
-{
-	// Force free buffer
-	delete [] (UINT8*)mBuffer.data;
-}
-//-----------------------------------------------------------------------------  
-void GLHardwarePixelBuffer::allocateBuffer()
-{
-	if(mBuffer.data)
-		// Already allocated
-		return;
-	mBuffer.data = new UINT8[mSizeInBytes];
-	// TODO: use PBO if we're HBU_DYNAMIC
-}
-//-----------------------------------------------------------------------------  
-void GLHardwarePixelBuffer::freeBuffer()
-{
-	// Free buffer if we're STATIC to save memory
-	if(mUsage & HBU_STATIC)
+	//-----------------------------------------------------------------------------  
+	GLHardwarePixelBuffer::~GLHardwarePixelBuffer()
 	{
 	{
+		// Force free buffer
 		delete [] (UINT8*)mBuffer.data;
 		delete [] (UINT8*)mBuffer.data;
-		mBuffer.data = 0;
 	}
 	}
-}
-//-----------------------------------------------------------------------------  
-PixelData GLHardwarePixelBuffer::lockImpl(const Box lockBox,  LockOptions options)
-{
-	allocateBuffer();
-	if(options != HBL_WRITE_ONLY_DISCARD) 
+	//-----------------------------------------------------------------------------  
+	void GLHardwarePixelBuffer::allocateBuffer()
 	{
 	{
-		// Download the old contents of the texture
-		download(mBuffer);
+		if(mBuffer.data)
+			// Already allocated
+			return;
+		mBuffer.data = new UINT8[mSizeInBytes];
+		// TODO: use PBO if we're HBU_DYNAMIC
 	}
 	}
-	mCurrentLockOptions = options;
-	mLockedBox = lockBox;
-	return mBuffer.getSubVolume(lockBox);
-}
-//-----------------------------------------------------------------------------  
-void GLHardwarePixelBuffer::unlockImpl(void)
-{
-	if (mCurrentLockOptions != HBL_READ_ONLY)
+	//-----------------------------------------------------------------------------  
+	void GLHardwarePixelBuffer::freeBuffer()
 	{
 	{
-		// From buffer to card, only upload if was locked for writing
-		upload(mCurrentLock, mLockedBox);
+		// Free buffer if we're STATIC to save memory
+		if(mUsage & HBU_STATIC)
+		{
+			delete [] (UINT8*)mBuffer.data;
+			mBuffer.data = 0;
+		}
 	}
 	}
-	
-	freeBuffer();
-}
-
-//-----------------------------------------------------------------------------  
-void GLHardwarePixelBuffer::blitFromMemory(const PixelData &src, const Box &dstBox)
-{
-	if(!mBuffer.contains(dstBox))
-		CM_EXCEPT(InvalidParametersException, "destination box out of range");
-	PixelData scaled;
-	
-	if(src.getWidth() != dstBox.getWidth() ||
-		src.getHeight() != dstBox.getHeight() ||
-		src.getDepth() != dstBox.getDepth())
+	//-----------------------------------------------------------------------------  
+	PixelData GLHardwarePixelBuffer::lockImpl(const Box lockBox,  LockOptions options)
 	{
 	{
-		// Scale to destination size. Use DevIL and not iluScale because ILU screws up for 
-		// floating point textures and cannot cope with 3D images.
-		// This also does pixel format conversion if needed
 		allocateBuffer();
 		allocateBuffer();
-		scaled = mBuffer.getSubVolume(dstBox);
-		PixelUtil::scale(src, scaled, PixelUtil::FILTER_BILINEAR);
+		if(options != HBL_WRITE_ONLY_DISCARD) 
+		{
+			// Download the old contents of the texture
+			download(mBuffer);
+		}
+		mCurrentLockOptions = options;
+		mLockedBox = lockBox;
+		return mBuffer.getSubVolume(lockBox);
 	}
 	}
-	else if(GLPixelUtil::getGLOriginFormat(src.format) == 0)
+	//-----------------------------------------------------------------------------  
+	void GLHardwarePixelBuffer::unlockImpl(void)
 	{
 	{
-		// Extents match, but format is not accepted as valid source format for GL
-		// do conversion in temporary buffer
-		allocateBuffer();
-		scaled = mBuffer.getSubVolume(dstBox);
-		PixelUtil::bulkPixelConversion(src, scaled);
+		if (mCurrentLockOptions != HBL_READ_ONLY)
+		{
+			// From buffer to card, only upload if was locked for writing
+			upload(mCurrentLock, mLockedBox);
+		}
+	
+		freeBuffer();
 	}
 	}
-	else
+
+	//-----------------------------------------------------------------------------  
+	void GLHardwarePixelBuffer::blitFromMemory(const PixelData &src, const Box &dstBox)
 	{
 	{
-		allocateBuffer();
-		// No scaling or conversion needed
-		scaled = src;
-	}
+		if(!mBuffer.contains(dstBox))
+			CM_EXCEPT(InvalidParametersException, "destination box out of range");
+		PixelData scaled;
 	
 	
-	upload(scaled, dstBox);
-	freeBuffer();
-}
-//-----------------------------------------------------------------------------  
-void GLHardwarePixelBuffer::blitToMemory(const Box &srcBox, const PixelData &dst)
-{
-	if(!mBuffer.contains(srcBox))
-		CM_EXCEPT(InvalidParametersException, "source box out of range");
-	if(srcBox.left == 0 && srcBox.right == getWidth() &&
-	   srcBox.top == 0 && srcBox.bottom == getHeight() &&
-	   srcBox.front == 0 && srcBox.back == getDepth() &&
-	   dst.getWidth() == getWidth() &&
-	   dst.getHeight() == getHeight() &&
-	   dst.getDepth() == getDepth() &&
-	   GLPixelUtil::getGLOriginFormat(dst.format) != 0)
-	{
-		// The direct case: the user wants the entire texture in a format supported by GL
-		// so we don't need an intermediate buffer
-		download(dst);
+		if(src.getWidth() != dstBox.getWidth() ||
+			src.getHeight() != dstBox.getHeight() ||
+			src.getDepth() != dstBox.getDepth())
+		{
+			// Scale to destination size. Use DevIL and not iluScale because ILU screws up for 
+			// floating point textures and cannot cope with 3D images.
+			// This also does pixel format conversion if needed
+			allocateBuffer();
+			scaled = mBuffer.getSubVolume(dstBox);
+			PixelUtil::scale(src, scaled, PixelUtil::FILTER_BILINEAR);
+		}
+		else if(GLPixelUtil::getGLOriginFormat(src.format) == 0)
+		{
+			// Extents match, but format is not accepted as valid source format for GL
+			// do conversion in temporary buffer
+			allocateBuffer();
+			scaled = mBuffer.getSubVolume(dstBox);
+			PixelUtil::bulkPixelConversion(src, scaled);
+		}
+		else
+		{
+			allocateBuffer();
+			// No scaling or conversion needed
+			scaled = src;
+		}
+	
+		upload(scaled, dstBox);
+		freeBuffer();
 	}
 	}
-	else
+	//-----------------------------------------------------------------------------  
+	void GLHardwarePixelBuffer::blitToMemory(const Box &srcBox, const PixelData &dst)
 	{
 	{
-		// Use buffer for intermediate copy
-		allocateBuffer();
-		// Download entire buffer
-		download(mBuffer);
-		if(srcBox.getWidth() != dst.getWidth() ||
-			srcBox.getHeight() != dst.getHeight() ||
-			srcBox.getDepth() != dst.getDepth())
+		if(!mBuffer.contains(srcBox))
+			CM_EXCEPT(InvalidParametersException, "source box out of range");
+		if(srcBox.left == 0 && srcBox.right == getWidth() &&
+		   srcBox.top == 0 && srcBox.bottom == getHeight() &&
+		   srcBox.front == 0 && srcBox.back == getDepth() &&
+		   dst.getWidth() == getWidth() &&
+		   dst.getHeight() == getHeight() &&
+		   dst.getDepth() == getDepth() &&
+		   GLPixelUtil::getGLOriginFormat(dst.format) != 0)
 		{
 		{
-			// We need scaling
-			PixelUtil::scale(mBuffer.getSubVolume(srcBox), dst, PixelUtil::FILTER_BILINEAR);
+			// The direct case: the user wants the entire texture in a format supported by GL
+			// so we don't need an intermediate buffer
+			download(dst);
 		}
 		}
 		else
 		else
 		{
 		{
-			// Just copy the bit that we need
-			PixelUtil::bulkPixelConversion(mBuffer.getSubVolume(srcBox), dst);
+			// Use buffer for intermediate copy
+			allocateBuffer();
+			// Download entire buffer
+			download(mBuffer);
+			if(srcBox.getWidth() != dst.getWidth() ||
+				srcBox.getHeight() != dst.getHeight() ||
+				srcBox.getDepth() != dst.getDepth())
+			{
+				// We need scaling
+				PixelUtil::scale(mBuffer.getSubVolume(srcBox), dst, PixelUtil::FILTER_BILINEAR);
+			}
+			else
+			{
+				// Just copy the bit that we need
+				PixelUtil::bulkPixelConversion(mBuffer.getSubVolume(srcBox), dst);
+			}
+			freeBuffer();
 		}
 		}
-		freeBuffer();
 	}
 	}
-}
-//-----------------------------------------------------------------------------
-void GLHardwarePixelBuffer::upload(const PixelData &data, const Box &dest)
-{
-    CM_EXCEPT(RenderingAPIException, 
-		"Upload not possible for this pixelbuffer type");
-}
-//-----------------------------------------------------------------------------  
-void GLHardwarePixelBuffer::download(const PixelData &data)
-{
-    CM_EXCEPT(RenderingAPIException, "Download not possible for this pixelbuffer type");
-}
-//-----------------------------------------------------------------------------  
-void GLHardwarePixelBuffer::bindToFramebuffer(GLenum attachment, UINT32 zoffset)
-{
-    CM_EXCEPT(RenderingAPIException, "Framebuffer bind not possible for this pixelbuffer type");
-}
-//********* GLTextureBuffer
-GLTextureBuffer::GLTextureBuffer(const String &baseName, GLenum target, GLuint id, 
-								 GLint face, GLint level, Usage usage, bool crappyCard, 
-								 bool writeGamma, UINT32 fsaa):
-	GLHardwarePixelBuffer(0, 0, 0, PF_UNKNOWN, usage),
-	mTarget(target), mFaceTarget(0), mTextureID(id), mFace(face), mLevel(level),
-    mSoftwareMipmap(crappyCard)
-{
-	// devise mWidth, mHeight and mDepth and mFormat
-	GLint value = 0;
+	//-----------------------------------------------------------------------------
+	void GLHardwarePixelBuffer::upload(const PixelData &data, const Box &dest)
+	{
+		CM_EXCEPT(RenderingAPIException, 
+			"Upload not possible for this pixelbuffer type");
+	}
+	//-----------------------------------------------------------------------------  
+	void GLHardwarePixelBuffer::download(const PixelData &data)
+	{
+		CM_EXCEPT(RenderingAPIException, "Download not possible for this pixelbuffer type");
+	}
+	//-----------------------------------------------------------------------------  
+	void GLHardwarePixelBuffer::bindToFramebuffer(GLenum attachment, UINT32 zoffset)
+	{
+		CM_EXCEPT(RenderingAPIException, "Framebuffer bind not possible for this pixelbuffer type");
+	}
+	//********* GLTextureBuffer
+	GLTextureBuffer::GLTextureBuffer(const String &baseName, GLenum target, GLuint id, 
+									 GLint face, GLint level, Usage usage, bool crappyCard, 
+									 bool writeGamma, UINT32 fsaa):
+		GLHardwarePixelBuffer(0, 0, 0, PF_UNKNOWN, usage),
+		mTarget(target), mFaceTarget(0), mTextureID(id), mFace(face), mLevel(level),
+		mSoftwareMipmap(crappyCard)
+	{
+		// devise mWidth, mHeight and mDepth and mFormat
+		GLint value = 0;
 	
 	
-	glBindTexture( mTarget, mTextureID );
+		glBindTexture( mTarget, mTextureID );
 	
 	
-	// Get face identifier
-	mFaceTarget = mTarget;
-	if(mTarget == GL_TEXTURE_CUBE_MAP)
-		mFaceTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + face;
+		// Get face identifier
+		mFaceTarget = mTarget;
+		if(mTarget == GL_TEXTURE_CUBE_MAP)
+			mFaceTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + face;
 	
 	
-	// Get width
-	glGetTexLevelParameteriv(mFaceTarget, level, GL_TEXTURE_WIDTH, &value);
-	mWidth = value;
+		// Get width
+		glGetTexLevelParameteriv(mFaceTarget, level, GL_TEXTURE_WIDTH, &value);
+		mWidth = value;
 	
 	
-	// Get height
-	if(target == GL_TEXTURE_1D)
-		value = 1;	// Height always 1 for 1D textures
-	else
-		glGetTexLevelParameteriv(mFaceTarget, level, GL_TEXTURE_HEIGHT, &value);
-	mHeight = value;
+		// Get height
+		if(target == GL_TEXTURE_1D)
+			value = 1;	// Height always 1 for 1D textures
+		else
+			glGetTexLevelParameteriv(mFaceTarget, level, GL_TEXTURE_HEIGHT, &value);
+		mHeight = value;
 	
 	
-	// Get depth
-	if(target != GL_TEXTURE_3D)
-		value = 1; // Depth always 1 for non-3D textures
-	else
-		glGetTexLevelParameteriv(mFaceTarget, level, GL_TEXTURE_DEPTH, &value);
-	mDepth = value;
+		// Get depth
+		if(target != GL_TEXTURE_3D)
+			value = 1; // Depth always 1 for non-3D textures
+		else
+			glGetTexLevelParameteriv(mFaceTarget, level, GL_TEXTURE_DEPTH, &value);
+		mDepth = value;
 
 
-	// Get format
-	glGetTexLevelParameteriv(mFaceTarget, level, GL_TEXTURE_INTERNAL_FORMAT, &value);
-	mGLInternalFormat = value;
-	mFormat = GLPixelUtil::getClosestEngineFormat(value);
+		// Get format
+		glGetTexLevelParameteriv(mFaceTarget, level, GL_TEXTURE_INTERNAL_FORMAT, &value);
+		mGLInternalFormat = value;
+		mFormat = GLPixelUtil::getClosestEngineFormat(value);
 	
 	
-	// Default
-	mRowPitch = mWidth;
-	mSlicePitch = mHeight*mWidth;
-	mSizeInBytes = PixelUtil::getMemorySize(mWidth, mHeight, mDepth, mFormat);
+		// Default
+		mRowPitch = mWidth;
+		mSlicePitch = mHeight*mWidth;
+		mSizeInBytes = PixelUtil::getMemorySize(mWidth, mHeight, mDepth, mFormat);
 	
 	
-	// Set up pixel box
-	mBuffer = PixelData(mWidth, mHeight, mDepth, mFormat);
+		// Set up pixel box
+		mBuffer = PixelData(mWidth, mHeight, mDepth, mFormat);
 	
 	
-    if(mWidth==0 || mHeight==0 || mDepth==0)
-        /// We are invalid, do not allocate a buffer
-        return;
-}
-GLTextureBuffer::~GLTextureBuffer()
-{ }
-//-----------------------------------------------------------------------------
-void GLTextureBuffer::upload(const PixelData &data, const Box &dest)
-{
-	glBindTexture( mTarget, mTextureID );
-	if(PixelUtil::isCompressed(data.format))
+		if(mWidth==0 || mHeight==0 || mDepth==0)
+			/// We are invalid, do not allocate a buffer
+			return;
+	}
+	GLTextureBuffer::~GLTextureBuffer()
+	{ }
+	//-----------------------------------------------------------------------------
+	void GLTextureBuffer::upload(const PixelData &data, const Box &dest)
 	{
 	{
-		if(data.format != mFormat || !data.isConsecutive())
-			CM_EXCEPT(InvalidParametersException, 
-			"Compressed images must be consecutive, in the source format");
-		GLenum format = GLPixelUtil::getClosestGLInternalFormat(mFormat);
-		// Data must be consecutive and at beginning of buffer as PixelStorei not allowed
-		// for compressed formats
-		switch(mTarget) {
-			case GL_TEXTURE_1D:
-				// some systems (e.g. old Apple) don't like compressed subimage calls
-				// so prefer non-sub versions
-				if (dest.left == 0)
-				{
-					glCompressedTexImage1DARB(GL_TEXTURE_1D, mLevel,
-						format,
-						dest.getWidth(),
-						0,
-						data.getConsecutiveSize(),
-						data.data);
-				}
-				else
-				{
-					glCompressedTexSubImage1DARB(GL_TEXTURE_1D, mLevel, 
+		if((mUsage & TU_RENDERTARGET) != 0)
+			CM_EXCEPT(NotImplementedException, "Writing to render texture from CPU not supported.");
+
+		glBindTexture( mTarget, mTextureID );
+		if(PixelUtil::isCompressed(data.format))
+		{
+			if(data.format != mFormat || !data.isConsecutive())
+				CM_EXCEPT(InvalidParametersException, 
+				"Compressed images must be consecutive, in the source format");
+			GLenum format = GLPixelUtil::getClosestGLInternalFormat(mFormat);
+			// Data must be consecutive and at beginning of buffer as PixelStorei not allowed
+			// for compressed formats
+			switch(mTarget) {
+				case GL_TEXTURE_1D:
+					// some systems (e.g. old Apple) don't like compressed subimage calls
+					// so prefer non-sub versions
+					if (dest.left == 0)
+					{
+						glCompressedTexImage1D(GL_TEXTURE_1D, mLevel,
+							format,
+							dest.getWidth(),
+							0,
+							data.getConsecutiveSize(),
+							data.data);
+					}
+					else
+					{
+						glCompressedTexSubImage1D(GL_TEXTURE_1D, mLevel, 
+							dest.left,
+							dest.getWidth(),
+							format, data.getConsecutiveSize(),
+							data.data);
+					}
+					break;
+				case GL_TEXTURE_2D:
+				case GL_TEXTURE_CUBE_MAP:
+					// some systems (e.g. old Apple) don't like compressed subimage calls
+					// so prefer non-sub versions
+					if (dest.left == 0 && dest.top == 0)
+					{
+						glCompressedTexImage2D(mFaceTarget, mLevel,
+							format,
+							dest.getWidth(),
+							dest.getHeight(),
+							0,
+							data.getConsecutiveSize(),
+							data.data);
+					}
+					else
+					{
+						glCompressedTexSubImage2D(mFaceTarget, mLevel, 
+							dest.left, dest.top, 
+							dest.getWidth(), dest.getHeight(),
+							format, data.getConsecutiveSize(),
+							data.data);
+					}
+					break;
+				case GL_TEXTURE_3D:
+					// some systems (e.g. old Apple) don't like compressed subimage calls
+					// so prefer non-sub versions
+					if (dest.left == 0 && dest.top == 0 && dest.front == 0)
+					{
+						glCompressedTexImage3D(GL_TEXTURE_3D, mLevel,
+							format,
+							dest.getWidth(),
+							dest.getHeight(),
+							dest.getDepth(),
+							0,
+							data.getConsecutiveSize(),
+							data.data);
+					}
+					else
+					{			
+						glCompressedTexSubImage3D(GL_TEXTURE_3D, mLevel, 
+							dest.left, dest.top, dest.front,
+							dest.getWidth(), dest.getHeight(), dest.getDepth(),
+							format, data.getConsecutiveSize(),
+							data.data);
+					}
+					break;
+			}
+		
+		} 
+		else
+		{
+			if(data.getWidth() != data.rowPitch)
+				glPixelStorei(GL_UNPACK_ROW_LENGTH, data.rowPitch);
+			if(data.getHeight()*data.getWidth() != data.slicePitch)
+				glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, (data.slicePitch/data.getWidth()));
+			if(data.left > 0 || data.top > 0 || data.front > 0)
+				glPixelStorei(GL_UNPACK_SKIP_PIXELS, data.left + data.rowPitch * data.top + data.slicePitch * data.front);
+			if((data.getWidth()*PixelUtil::getNumElemBytes(data.format)) & 3) {
+				// Standard alignment of 4 is not right
+				glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+			}
+			switch(mTarget) {
+				case GL_TEXTURE_1D:
+					glTexSubImage1D(GL_TEXTURE_1D, mLevel, 
 						dest.left,
 						dest.left,
 						dest.getWidth(),
 						dest.getWidth(),
-						format, data.getConsecutiveSize(),
-						data.data);
-				}
-				break;
-			case GL_TEXTURE_2D:
-			case GL_TEXTURE_CUBE_MAP:
-				// some systems (e.g. old Apple) don't like compressed subimage calls
-				// so prefer non-sub versions
-				if (dest.left == 0 && dest.top == 0)
-				{
-					glCompressedTexImage2DARB(mFaceTarget, mLevel,
-						format,
-						dest.getWidth(),
-						dest.getHeight(),
-						0,
-						data.getConsecutiveSize(),
+						GLPixelUtil::getGLOriginFormat(data.format), GLPixelUtil::getGLOriginDataType(data.format),
 						data.data);
 						data.data);
-				}
-				else
-				{
-					glCompressedTexSubImage2DARB(mFaceTarget, mLevel, 
+					break;
+				case GL_TEXTURE_2D:
+				case GL_TEXTURE_CUBE_MAP:
+					glTexSubImage2D(mFaceTarget, mLevel, 
 						dest.left, dest.top, 
 						dest.left, dest.top, 
 						dest.getWidth(), dest.getHeight(),
 						dest.getWidth(), dest.getHeight(),
-						format, data.getConsecutiveSize(),
-						data.data);
-				}
-				break;
-			case GL_TEXTURE_3D:
-				// some systems (e.g. old Apple) don't like compressed subimage calls
-				// so prefer non-sub versions
-				if (dest.left == 0 && dest.top == 0 && dest.front == 0)
-				{
-					glCompressedTexImage3DARB(GL_TEXTURE_3D, mLevel,
-						format,
-						dest.getWidth(),
-						dest.getHeight(),
-						dest.getDepth(),
-						0,
-						data.getConsecutiveSize(),
+						GLPixelUtil::getGLOriginFormat(data.format), GLPixelUtil::getGLOriginDataType(data.format),
 						data.data);
 						data.data);
-				}
-				else
-				{			
-					glCompressedTexSubImage3DARB(GL_TEXTURE_3D, mLevel, 
+					break;
+				case GL_TEXTURE_3D:
+					glTexSubImage3D(
+						GL_TEXTURE_3D, mLevel, 
 						dest.left, dest.top, dest.front,
 						dest.left, dest.top, dest.front,
 						dest.getWidth(), dest.getHeight(), dest.getDepth(),
 						dest.getWidth(), dest.getHeight(), dest.getDepth(),
-						format, data.getConsecutiveSize(),
+						GLPixelUtil::getGLOriginFormat(data.format), GLPixelUtil::getGLOriginDataType(data.format),
 						data.data);
 						data.data);
-				}
-				break;
+					break;
+			}	
 		}
 		}
-		
-	} 
-	else if(mSoftwareMipmap)
+		// Restore defaults
+		glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+		if (GLEW_VERSION_1_2)
+			glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0);
+		glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
+		glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
+	}
+	//-----------------------------------------------------------------------------  
+	void GLTextureBuffer::download(const PixelData &data)
 	{
 	{
-		GLint components = PixelUtil::getComponentCount(mFormat);
-		if(data.getWidth() != data.rowPitch)
-			glPixelStorei(GL_UNPACK_ROW_LENGTH, data.rowPitch);
-		if(data.getHeight()*data.getWidth() != data.slicePitch)
-			glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, (data.slicePitch/data.getWidth()));
-		if(data.left > 0 || data.top > 0 || data.front > 0)
-			glPixelStorei(GL_UNPACK_SKIP_PIXELS, data.left + data.rowPitch * data.top + data.slicePitch * data.front);
-		glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
-		
-		switch(mTarget)
+		if((mUsage & TU_RENDERTARGET) != 0)
+			CM_EXCEPT(NotImplementedException, "Reading from render texture to CPU not supported."); // TODO: This needs to be implemented
+
+		if(data.getWidth() != getWidth() ||
+			data.getHeight() != getHeight() ||
+			data.getDepth() != getDepth())
+			CM_EXCEPT(InvalidParametersException, "only download of entire buffer is supported by GL");
+		glBindTexture( mTarget, mTextureID );
+		if(PixelUtil::isCompressed(data.format))
 		{
 		{
-		case GL_TEXTURE_1D:
-			gluBuild1DMipmaps(
-				GL_TEXTURE_1D, components,
-				dest.getWidth(),
+			if(data.format != mFormat || !data.isConsecutive())
+				CM_EXCEPT(InvalidParametersException, 
+				"Compressed images must be consecutive, in the source format");
+			// Data must be consecutive and at beginning of buffer as PixelStorei not allowed
+			// for compressed formate
+			glGetCompressedTexImage(mFaceTarget, mLevel, data.data);
+		} 
+		else
+		{
+			if(data.getWidth() != data.rowPitch)
+				glPixelStorei(GL_PACK_ROW_LENGTH, data.rowPitch);
+			if(data.getHeight()*data.getWidth() != data.slicePitch)
+				glPixelStorei(GL_PACK_IMAGE_HEIGHT, (data.slicePitch/data.getWidth()));
+			if(data.left > 0 || data.top > 0 || data.front > 0)
+				glPixelStorei(GL_PACK_SKIP_PIXELS, data.left + data.rowPitch * data.top + data.slicePitch * data.front);
+			if((data.getWidth()*PixelUtil::getNumElemBytes(data.format)) & 3) {
+				// Standard alignment of 4 is not right
+				glPixelStorei(GL_PACK_ALIGNMENT, 1);
+			}
+			// We can only get the entire texture
+			glGetTexImage(mFaceTarget, mLevel, 
 				GLPixelUtil::getGLOriginFormat(data.format), GLPixelUtil::getGLOriginDataType(data.format),
 				GLPixelUtil::getGLOriginFormat(data.format), GLPixelUtil::getGLOriginDataType(data.format),
 				data.data);
 				data.data);
+			// Restore defaults
+			glPixelStorei(GL_PACK_ROW_LENGTH, 0);
+			glPixelStorei(GL_PACK_IMAGE_HEIGHT, 0);
+			glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
+			glPixelStorei(GL_PACK_ALIGNMENT, 4);
+		}
+	}
+	//-----------------------------------------------------------------------------  
+	void GLTextureBuffer::bindToFramebuffer(GLenum attachment, UINT32 zoffset)
+	{
+		assert(zoffset < mDepth);
+
+		switch(mTarget)
+		{
+		case GL_TEXTURE_1D:
+			glFramebufferTexture1DEXT(GL_FRAMEBUFFER_EXT, attachment,
+				mFaceTarget, mTextureID, mLevel);
 			break;
 			break;
 		case GL_TEXTURE_2D:
 		case GL_TEXTURE_2D:
 		case GL_TEXTURE_CUBE_MAP:
 		case GL_TEXTURE_CUBE_MAP:
-			gluBuild2DMipmaps(
-				mFaceTarget,
-				components, dest.getWidth(), dest.getHeight(), 
-				GLPixelUtil::getGLOriginFormat(data.format), GLPixelUtil::getGLOriginDataType(data.format), 
-				data.data);
-			break;		
+			glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attachment,
+				mFaceTarget, mTextureID, mLevel);
+			break;
+		case GL_TEXTURE_2D_MULTISAMPLE:
+			glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attachment,
+				mFaceTarget, mTextureID, 0);
+			break;
 		case GL_TEXTURE_3D:
 		case GL_TEXTURE_3D:
-			/* Requires GLU 1.3 which is harder to come by than cards doing hardware mipmapping
-				Most 3D textures don't need mipmaps?
-			gluBuild3DMipmaps(
-				GL_TEXTURE_3D, internalFormat, 
-				data.getWidth(), data.getHeight(), data.getDepth(),
-				GLPixelUtil::getGLOriginFormat(data.format), GLPixelUtil::getGLOriginDataType(data.format),
-				data.data);
-			*/
-			glTexImage3D(
-				GL_TEXTURE_3D, 0, components, 
-				dest.getWidth(), dest.getHeight(), dest.getDepth(), 0, 
-				GLPixelUtil::getGLOriginFormat(data.format), GLPixelUtil::getGLOriginDataType(data.format),
-				data.data );
+			glFramebufferTexture3DEXT(GL_FRAMEBUFFER_EXT, attachment,
+				mFaceTarget, mTextureID, mLevel, zoffset);
 			break;
 			break;
 		}
 		}
-	} 
-	else
+	}
+	//-----------------------------------------------------------------------------
+	void GLTextureBuffer::copyFromFramebuffer(UINT32 zoffset)
 	{
 	{
-		if(data.getWidth() != data.rowPitch)
-			glPixelStorei(GL_UNPACK_ROW_LENGTH, data.rowPitch);
-		if(data.getHeight()*data.getWidth() != data.slicePitch)
-			glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, (data.slicePitch/data.getWidth()));
-		if(data.left > 0 || data.top > 0 || data.front > 0)
-			glPixelStorei(GL_UNPACK_SKIP_PIXELS, data.left + data.rowPitch * data.top + data.slicePitch * data.front);
-		if((data.getWidth()*PixelUtil::getNumElemBytes(data.format)) & 3) {
-			// Standard alignment of 4 is not right
-			glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+		glBindTexture(mTarget, mTextureID);
+		switch(mTarget)
+		{
+		case GL_TEXTURE_1D:
+			glCopyTexSubImage1D(mFaceTarget, mLevel, 0, 0, 0, mWidth);
+			break;
+		case GL_TEXTURE_2D:
+		case GL_TEXTURE_CUBE_MAP:
+			glCopyTexSubImage2D(mFaceTarget, mLevel, 0, 0, 0, 0, mWidth, mHeight);
+			break;
+		case GL_TEXTURE_3D:
+			glCopyTexSubImage3D(mFaceTarget, mLevel, 0, 0, zoffset, 0, 0, mWidth, mHeight);
+			break;
 		}
 		}
-		switch(mTarget) {
-			case GL_TEXTURE_1D:
-				glTexSubImage1D(GL_TEXTURE_1D, mLevel, 
-					dest.left,
-					dest.getWidth(),
-					GLPixelUtil::getGLOriginFormat(data.format), GLPixelUtil::getGLOriginDataType(data.format),
-					data.data);
-				break;
-			case GL_TEXTURE_2D:
-			case GL_TEXTURE_CUBE_MAP:
-				glTexSubImage2D(mFaceTarget, mLevel, 
-					dest.left, dest.top, 
-					dest.getWidth(), dest.getHeight(),
-					GLPixelUtil::getGLOriginFormat(data.format), GLPixelUtil::getGLOriginDataType(data.format),
-					data.data);
-				break;
-			case GL_TEXTURE_3D:
-				glTexSubImage3D(
-					GL_TEXTURE_3D, mLevel, 
-					dest.left, dest.top, dest.front,
-					dest.getWidth(), dest.getHeight(), dest.getDepth(),
-					GLPixelUtil::getGLOriginFormat(data.format), GLPixelUtil::getGLOriginDataType(data.format),
-					data.data);
-				break;
-		}	
 	}
 	}
-	// Restore defaults
-	glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
-	if (GLEW_VERSION_1_2)
-		glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0);
-	glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
-	glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
-}
-//-----------------------------------------------------------------------------  
-void GLTextureBuffer::download(const PixelData &data)
-{
-	if(data.getWidth() != getWidth() ||
-		data.getHeight() != getHeight() ||
-		data.getDepth() != getDepth())
-		CM_EXCEPT(InvalidParametersException, "only download of entire buffer is supported by GL");
-	glBindTexture( mTarget, mTextureID );
-	if(PixelUtil::isCompressed(data.format))
-	{
-		if(data.format != mFormat || !data.isConsecutive())
-			CM_EXCEPT(InvalidParametersException, 
-			"Compressed images must be consecutive, in the source format");
-		// Data must be consecutive and at beginning of buffer as PixelStorei not allowed
-		// for compressed formate
-		glGetCompressedTexImageARB(mFaceTarget, mLevel, data.data);
-	} 
-	else
+	//-----------------------------------------------------------------------------  
+	void GLTextureBuffer::blit(const HardwarePixelBufferPtr &src, const Box &srcBox, const Box &dstBox)
 	{
 	{
-		if(data.getWidth() != data.rowPitch)
-			glPixelStorei(GL_PACK_ROW_LENGTH, data.rowPitch);
-		if(data.getHeight()*data.getWidth() != data.slicePitch)
-			glPixelStorei(GL_PACK_IMAGE_HEIGHT, (data.slicePitch/data.getWidth()));
-		if(data.left > 0 || data.top > 0 || data.front > 0)
-			glPixelStorei(GL_PACK_SKIP_PIXELS, data.left + data.rowPitch * data.top + data.slicePitch * data.front);
-		if((data.getWidth()*PixelUtil::getNumElemBytes(data.format)) & 3) {
-			// Standard alignment of 4 is not right
-			glPixelStorei(GL_PACK_ALIGNMENT, 1);
+		GLTextureBuffer *srct = static_cast<GLTextureBuffer *>(src.get());
+		/// Check for FBO support first
+		/// Destination texture must be 1D, 2D, 3D, or Cube
+		/// Source texture must be 1D, 2D or 3D
+	
+		// This does not sem to work for RTTs after the first update
+		// I have no idea why! For the moment, disable 
+		if(GLEW_EXT_framebuffer_object && (src->getUsage() & TU_RENDERTARGET) == 0 &&
+			(srct->mTarget==GL_TEXTURE_1D||srct->mTarget==GL_TEXTURE_2D||srct->mTarget==GL_TEXTURE_3D))
+		{
+			blitFromTexture(srct, srcBox, dstBox);
+		}
+		else
+		{
+			GLHardwarePixelBuffer::blit(src, srcBox, dstBox);
 		}
 		}
-		// We can only get the entire texture
-		glGetTexImage(mFaceTarget, mLevel, 
-			GLPixelUtil::getGLOriginFormat(data.format), GLPixelUtil::getGLOriginDataType(data.format),
-			data.data);
-		// Restore defaults
-		glPixelStorei(GL_PACK_ROW_LENGTH, 0);
-		glPixelStorei(GL_PACK_IMAGE_HEIGHT, 0);
-		glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
-		glPixelStorei(GL_PACK_ALIGNMENT, 4);
 	}
 	}
-}
-//-----------------------------------------------------------------------------  
-void GLTextureBuffer::bindToFramebuffer(GLenum attachment, UINT32 zoffset)
-{
-    assert(zoffset < mDepth);
-    switch(mTarget)
-    {
-    case GL_TEXTURE_1D:
-        glFramebufferTexture1DEXT(GL_FRAMEBUFFER_EXT, attachment,
-                            mFaceTarget, mTextureID, mLevel);
-        break;
-    case GL_TEXTURE_2D:
-    case GL_TEXTURE_CUBE_MAP:
-        glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attachment,
-                            mFaceTarget, mTextureID, mLevel);
-        break;
-    case GL_TEXTURE_3D:
-        glFramebufferTexture3DEXT(GL_FRAMEBUFFER_EXT, attachment,
-                            mFaceTarget, mTextureID, mLevel, zoffset);
-        break;
-    }
-}
-//-----------------------------------------------------------------------------
-void GLTextureBuffer::copyFromFramebuffer(UINT32 zoffset)
-{
-    glBindTexture(mTarget, mTextureID);
-    switch(mTarget)
-    {
-    case GL_TEXTURE_1D:
-        glCopyTexSubImage1D(mFaceTarget, mLevel, 0, 0, 0, mWidth);
-        break;
-    case GL_TEXTURE_2D:
-    case GL_TEXTURE_CUBE_MAP:
-        glCopyTexSubImage2D(mFaceTarget, mLevel, 0, 0, 0, 0, mWidth, mHeight);
-        break;
-    case GL_TEXTURE_3D:
-        glCopyTexSubImage3D(mFaceTarget, mLevel, 0, 0, zoffset, 0, 0, mWidth, mHeight);
-        break;
-    }
-}
-//-----------------------------------------------------------------------------  
-void GLTextureBuffer::blit(const HardwarePixelBufferPtr &src, const Box &srcBox, const Box &dstBox)
-{
-    GLTextureBuffer *srct = static_cast<GLTextureBuffer *>(src.get());
-    /// Check for FBO support first
-    /// Destination texture must be 1D, 2D, 3D, or Cube
-    /// Source texture must be 1D, 2D or 3D
-	
-	// This does not sem to work for RTTs after the first update
-	// I have no idea why! For the moment, disable 
-    if(GLEW_EXT_framebuffer_object && (src->getUsage() & TU_RENDERTARGET) == 0 &&
-        (srct->mTarget==GL_TEXTURE_1D||srct->mTarget==GL_TEXTURE_2D||srct->mTarget==GL_TEXTURE_3D))
-    {
-        blitFromTexture(srct, srcBox, dstBox);
-    }
-    else
-    {
-        GLHardwarePixelBuffer::blit(src, srcBox, dstBox);
-    }
-}
 
 
-//-----------------------------------------------------------------------------  
-/// Very fast texture-to-texture blitter and hardware bi/trilinear scaling implementation using FBO
-/// Destination texture must be 1D, 2D, 3D, or Cube
-/// Source texture must be 1D, 2D or 3D
-/// Supports compressed formats as both source and destination format, it will use the hardware DXT compressor
-/// if available.
-/// @author W.J. van der Laan
-void GLTextureBuffer::blitFromTexture(GLTextureBuffer *src, const Box &srcBox, const Box &dstBox)
-{
-    //std::cerr << "GLTextureBuffer::blitFromTexture " <<
-    //src->mTextureID << ":" << srcBox.left << "," << srcBox.top << "," << srcBox.right << "," << srcBox.bottom << " " << 
-    //mTextureID << ":" << dstBox.left << "," << dstBox.top << "," << dstBox.right << "," << dstBox.bottom << std::endl;
-    /// Store reference to FBO manager
-    GLRTTManager *fboMan = static_cast<GLRTTManager *>(GLRTTManager::instancePtr());
+	//-----------------------------------------------------------------------------  
+	/// Very fast texture-to-texture blitter and hardware bi/trilinear scaling implementation using FBO
+	/// Destination texture must be 1D, 2D, 3D, or Cube
+	/// Source texture must be 1D, 2D or 3D
+	/// Supports compressed formats as both source and destination format, it will use the hardware DXT compressor
+	/// if available.
+	/// @author W.J. van der Laan
+	void GLTextureBuffer::blitFromTexture(GLTextureBuffer *src, const Box &srcBox, const Box &dstBox)
+	{
+		//std::cerr << "GLTextureBuffer::blitFromTexture " <<
+		//src->mTextureID << ":" << srcBox.left << "," << srcBox.top << "," << srcBox.right << "," << srcBox.bottom << " " << 
+		//mTextureID << ":" << dstBox.left << "," << dstBox.top << "," << dstBox.right << "," << dstBox.bottom << std::endl;
+		/// Store reference to FBO manager
+		GLRTTManager *fboMan = static_cast<GLRTTManager *>(GLRTTManager::instancePtr());
     
     
-    /// Save and clear GL state for rendering
-    glPushAttrib(GL_COLOR_BUFFER_BIT | GL_CURRENT_BIT | GL_DEPTH_BUFFER_BIT | GL_ENABLE_BIT | 
-        GL_FOG_BIT | GL_LIGHTING_BIT | GL_POLYGON_BIT | GL_SCISSOR_BIT | GL_STENCIL_BUFFER_BIT |
-        GL_TEXTURE_BIT | GL_VIEWPORT_BIT);
+		/// Save and clear GL state for rendering
+		glPushAttrib(GL_COLOR_BUFFER_BIT | GL_CURRENT_BIT | GL_DEPTH_BUFFER_BIT | GL_ENABLE_BIT | 
+			GL_FOG_BIT | GL_LIGHTING_BIT | GL_POLYGON_BIT | GL_SCISSOR_BIT | GL_STENCIL_BUFFER_BIT |
+			GL_TEXTURE_BIT | GL_VIEWPORT_BIT);
 
 
-	// Important to disable all other texture units
-	RenderSystem* rsys = CamelotEngine::RenderSystem::instancePtr();
-	rsys->disableTextureUnitsFrom(0);
-	if (GLEW_VERSION_1_2)
-	{
-		glActiveTextureARB(GL_TEXTURE0);
-	}
+		// Important to disable all other texture units
+		RenderSystem* rsys = CamelotEngine::RenderSystem::instancePtr();
+		rsys->disableTextureUnitsFrom(0);
+		if (GLEW_VERSION_1_2)
+		{
+			glActiveTextureARB(GL_TEXTURE0);
+		}
 
 
 
 
-    /// Disable alpha, depth and scissor testing, disable blending, 
-    /// disable culling, disble lighting, disable fog and reset foreground
-    /// colour.
-    glDisable(GL_ALPHA_TEST);
-    glDisable(GL_DEPTH_TEST);
-    glDisable(GL_SCISSOR_TEST);
-    glDisable(GL_BLEND);
-    glDisable(GL_CULL_FACE);
-    glDisable(GL_LIGHTING);
-    glDisable(GL_FOG);
-    glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
+		/// Disable alpha, depth and scissor testing, disable blending, 
+		/// disable culling, disble lighting, disable fog and reset foreground
+		/// colour.
+		glDisable(GL_ALPHA_TEST);
+		glDisable(GL_DEPTH_TEST);
+		glDisable(GL_SCISSOR_TEST);
+		glDisable(GL_BLEND);
+		glDisable(GL_CULL_FACE);
+		glDisable(GL_LIGHTING);
+		glDisable(GL_FOG);
+		glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
     
     
-    /// Save and reset matrices
-    glMatrixMode(GL_MODELVIEW);
-    glPushMatrix();
-    glLoadIdentity();
-    glMatrixMode(GL_PROJECTION);
-    glPushMatrix();
-    glLoadIdentity();
-    glMatrixMode(GL_TEXTURE);
-    glPushMatrix();
-    glLoadIdentity();
+		/// Save and reset matrices
+		glMatrixMode(GL_MODELVIEW);
+		glPushMatrix();
+		glLoadIdentity();
+		glMatrixMode(GL_PROJECTION);
+		glPushMatrix();
+		glLoadIdentity();
+		glMatrixMode(GL_TEXTURE);
+		glPushMatrix();
+		glLoadIdentity();
     
     
-    /// Set up source texture
-    glBindTexture(src->mTarget, src->mTextureID);
+		/// Set up source texture
+		glBindTexture(src->mTarget, src->mTextureID);
     
     
-    /// Set filtering modes depending on the dimensions and source
-    if(srcBox.getWidth()==dstBox.getWidth() &&
-        srcBox.getHeight()==dstBox.getHeight() &&
-        srcBox.getDepth()==dstBox.getDepth())
-    {
-        /// Dimensions match -- use nearest filtering (fastest and pixel correct)
-        glTexParameteri(src->mTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-        glTexParameteri(src->mTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-    }
-    else
-    {
-        /// Manual mipmaps, stay safe with bilinear filtering so that no
-        /// intermipmap leakage occurs.
-        glTexParameteri(src->mTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-        glTexParameteri(src->mTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-    }
-    /// Clamp to edge (fastest)
-    glTexParameteri(src->mTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-    glTexParameteri(src->mTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-    glTexParameteri(src->mTarget, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
+		/// Set filtering modes depending on the dimensions and source
+		if(srcBox.getWidth()==dstBox.getWidth() &&
+			srcBox.getHeight()==dstBox.getHeight() &&
+			srcBox.getDepth()==dstBox.getDepth())
+		{
+			/// Dimensions match -- use nearest filtering (fastest and pixel correct)
+			glTexParameteri(src->mTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+			glTexParameteri(src->mTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+		}
+		else
+		{
+			/// Manual mipmaps, stay safe with bilinear filtering so that no
+			/// intermipmap leakage occurs.
+			glTexParameteri(src->mTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+			glTexParameteri(src->mTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+		}
+		/// Clamp to edge (fastest)
+		glTexParameteri(src->mTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+		glTexParameteri(src->mTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+		glTexParameteri(src->mTarget, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
     
     
-    /// Set origin base level mipmap to make sure we source from the right mip
-    /// level.
-    glTexParameteri(src->mTarget, GL_TEXTURE_BASE_LEVEL, src->mLevel);
+		/// Set origin base level mipmap to make sure we source from the right mip
+		/// level.
+		glTexParameteri(src->mTarget, GL_TEXTURE_BASE_LEVEL, src->mLevel);
     
     
-    /// Store old binding so it can be restored later
-    GLint oldfb;
-    glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &oldfb);
+		/// Store old binding so it can be restored later
+		GLint oldfb;
+		glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &oldfb);
     
     
-    /// Set up temporary FBO
-    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboMan->getTemporaryFBO());
+		/// Set up temporary FBO
+		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboMan->getTemporaryFBO());
     
     
-    GLuint tempTex = 0;
-    if(!fboMan->checkFormat(mFormat))
-    {
-        /// If target format not directly supported, create intermediate texture
-        GLenum tempFormat = GLPixelUtil::getClosestGLInternalFormat(fboMan->getSupportedAlternative(mFormat));
-        glGenTextures(1, &tempTex);
-        glBindTexture(GL_TEXTURE_2D, tempTex);
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
-        /// Allocate temporary texture of the size of the destination area
-        glTexImage2D(GL_TEXTURE_2D, 0, tempFormat, 
-            GLPixelUtil::optionalPO2(dstBox.getWidth()), GLPixelUtil::optionalPO2(dstBox.getHeight()), 
-            0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
-        glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
-            GL_TEXTURE_2D, tempTex, 0);
-        /// Set viewport to size of destination slice
-        glViewport(0, 0, dstBox.getWidth(), dstBox.getHeight());
-    }
-    else
-    {
-        /// We are going to bind directly, so set viewport to size and position of destination slice
-        glViewport(dstBox.left, dstBox.top, dstBox.getWidth(), dstBox.getHeight());
-    }
+		GLuint tempTex = 0;
+		if(!fboMan->checkFormat(mFormat))
+		{
+			/// If target format not directly supported, create intermediate texture
+			GLenum tempFormat = GLPixelUtil::getClosestGLInternalFormat(fboMan->getSupportedAlternative(mFormat));
+			glGenTextures(1, &tempTex);
+			glBindTexture(GL_TEXTURE_2D, tempTex);
+			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
+			/// Allocate temporary texture of the size of the destination area
+			glTexImage2D(GL_TEXTURE_2D, 0, tempFormat, 
+				GLPixelUtil::optionalPO2(dstBox.getWidth()), GLPixelUtil::optionalPO2(dstBox.getHeight()), 
+				0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
+			glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
+				GL_TEXTURE_2D, tempTex, 0);
+			/// Set viewport to size of destination slice
+			glViewport(0, 0, dstBox.getWidth(), dstBox.getHeight());
+		}
+		else
+		{
+			/// We are going to bind directly, so set viewport to size and position of destination slice
+			glViewport(dstBox.left, dstBox.top, dstBox.getWidth(), dstBox.getHeight());
+		}
     
     
-    /// Process each destination slice
-    for(UINT32 slice=dstBox.front; slice<dstBox.back; ++slice)
-    {
-        if(!tempTex)
-        {
-            /// Bind directly
-            bindToFramebuffer(GL_COLOR_ATTACHMENT0_EXT, slice);
-        }
-        /// Calculate source texture coordinates
-        float u1 = (float)srcBox.left / (float)src->mWidth;
-        float v1 = (float)srcBox.top / (float)src->mHeight;
-        float u2 = (float)srcBox.right / (float)src->mWidth;
-        float v2 = (float)srcBox.bottom / (float)src->mHeight;
-        /// Calculate source slice for this destination slice
-        float w = (float)(slice - dstBox.front) / (float)dstBox.getDepth();
-        /// Get slice # in source
-        w = w * (float)(srcBox.getDepth() + srcBox.front);
-        /// Normalise to texture coordinate in 0.0 .. 1.0
-        w = (w+0.5f) / (float)src->mDepth;
+		/// Process each destination slice
+		for(UINT32 slice=dstBox.front; slice<dstBox.back; ++slice)
+		{
+			if(!tempTex)
+			{
+				/// Bind directly
+				bindToFramebuffer(GL_COLOR_ATTACHMENT0_EXT, slice);
+			}
+			/// Calculate source texture coordinates
+			float u1 = (float)srcBox.left / (float)src->mWidth;
+			float v1 = (float)srcBox.top / (float)src->mHeight;
+			float u2 = (float)srcBox.right / (float)src->mWidth;
+			float v2 = (float)srcBox.bottom / (float)src->mHeight;
+			/// Calculate source slice for this destination slice
+			float w = (float)(slice - dstBox.front) / (float)dstBox.getDepth();
+			/// Get slice # in source
+			w = w * (float)(srcBox.getDepth() + srcBox.front);
+			/// Normalise to texture coordinate in 0.0 .. 1.0
+			w = (w+0.5f) / (float)src->mDepth;
         
         
-        /// Finally we're ready to rumble	
-        glBindTexture(src->mTarget, src->mTextureID);
-        glEnable(src->mTarget);
-        glBegin(GL_QUADS);
-        glTexCoord3f(u1, v1, w);
-        glVertex2f(-1.0f, -1.0f);
-        glTexCoord3f(u2, v1, w);
-        glVertex2f(1.0f, -1.0f);
-        glTexCoord3f(u2, v2, w);
-        glVertex2f(1.0f, 1.0f);
-        glTexCoord3f(u1, v2, w);
-        glVertex2f(-1.0f, 1.0f);
-        glEnd();
-        glDisable(src->mTarget);
+			/// Finally we're ready to rumble	
+			glBindTexture(src->mTarget, src->mTextureID);
+			glEnable(src->mTarget);
+			glBegin(GL_QUADS);
+			glTexCoord3f(u1, v1, w);
+			glVertex2f(-1.0f, -1.0f);
+			glTexCoord3f(u2, v1, w);
+			glVertex2f(1.0f, -1.0f);
+			glTexCoord3f(u2, v2, w);
+			glVertex2f(1.0f, 1.0f);
+			glTexCoord3f(u1, v2, w);
+			glVertex2f(-1.0f, 1.0f);
+			glEnd();
+			glDisable(src->mTarget);
         
         
-        if(tempTex)
-        {
-            /// Copy temporary texture
-            glBindTexture(mTarget, mTextureID);
-            switch(mTarget)
-            {
-            case GL_TEXTURE_1D:
-                glCopyTexSubImage1D(mFaceTarget, mLevel, 
-                    dstBox.left, 
-                    0, 0, dstBox.getWidth());
-                break;
-            case GL_TEXTURE_2D:
-            case GL_TEXTURE_CUBE_MAP:
-                glCopyTexSubImage2D(mFaceTarget, mLevel, 
-                    dstBox.left, dstBox.top, 
-                    0, 0, dstBox.getWidth(), dstBox.getHeight());
-                break;
-            case GL_TEXTURE_3D:
-                glCopyTexSubImage3D(mFaceTarget, mLevel, 
-                    dstBox.left, dstBox.top, slice, 
-                    0, 0, dstBox.getWidth(), dstBox.getHeight());
-                break;
-            }
-        }
-    }
+			if(tempTex)
+			{
+				/// Copy temporary texture
+				glBindTexture(mTarget, mTextureID);
+				switch(mTarget)
+				{
+				case GL_TEXTURE_1D:
+					glCopyTexSubImage1D(mFaceTarget, mLevel, 
+						dstBox.left, 
+						0, 0, dstBox.getWidth());
+					break;
+				case GL_TEXTURE_2D:
+				case GL_TEXTURE_CUBE_MAP:
+					glCopyTexSubImage2D(mFaceTarget, mLevel, 
+						dstBox.left, dstBox.top, 
+						0, 0, dstBox.getWidth(), dstBox.getHeight());
+					break;
+				case GL_TEXTURE_3D:
+					glCopyTexSubImage3D(mFaceTarget, mLevel, 
+						dstBox.left, dstBox.top, slice, 
+						0, 0, dstBox.getWidth(), dstBox.getHeight());
+					break;
+				}
+			}
+		}
 
 
-    /// Reset source texture to sane state
-    glBindTexture(src->mTarget, src->mTextureID);
-    glTexParameteri(src->mTarget, GL_TEXTURE_BASE_LEVEL, 0);
+		/// Reset source texture to sane state
+		glBindTexture(src->mTarget, src->mTextureID);
+		glTexParameteri(src->mTarget, GL_TEXTURE_BASE_LEVEL, 0);
     
     
-    /// Detach texture from temporary framebuffer
-    glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
-                    GL_RENDERBUFFER_EXT, 0);
-    /// Restore old framebuffer
-    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, oldfb);
-    /// Restore matrix stacks and render state
-    glMatrixMode(GL_TEXTURE);
-    glPopMatrix();
-    glMatrixMode(GL_PROJECTION);
-    glPopMatrix();
-    glMatrixMode(GL_MODELVIEW);
-    glPopMatrix();
-    glPopAttrib();
-    glDeleteTextures(1, &tempTex);
-}
-//-----------------------------------------------------------------------------  
-/// blitFromMemory doing hardware trilinear scaling
-void GLTextureBuffer::blitFromMemory(const PixelData &src_orig, const Box &dstBox)
-{
-    /// Fall back to normal GLHardwarePixelBuffer::blitFromMemory in case 
-    /// - FBO is not supported
-    /// - Either source or target is luminance due doesn't looks like supported by hardware
-    /// - the source dimensions match the destination ones, in which case no scaling is needed
-    if(!GLEW_EXT_framebuffer_object ||
-        PixelUtil::isLuminance(src_orig.format) ||
-        PixelUtil::isLuminance(mFormat) ||
-        (src_orig.getWidth() == dstBox.getWidth() &&
-        src_orig.getHeight() == dstBox.getHeight() &&
-        src_orig.getDepth() == dstBox.getDepth()))
-    {
-        GLHardwarePixelBuffer::blitFromMemory(src_orig, dstBox);
-        return;
-    }
-    if(!mBuffer.contains(dstBox))
-        CM_EXCEPT(InvalidParametersException, "destination box out of range");
-    /// For scoped deletion of conversion buffer
-	void* data = NULL;
-    PixelData src;
+		/// Detach texture from temporary framebuffer
+		glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
+						GL_RENDERBUFFER_EXT, 0);
+		/// Restore old framebuffer
+		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, oldfb);
+		/// Restore matrix stacks and render state
+		glMatrixMode(GL_TEXTURE);
+		glPopMatrix();
+		glMatrixMode(GL_PROJECTION);
+		glPopMatrix();
+		glMatrixMode(GL_MODELVIEW);
+		glPopMatrix();
+		glPopAttrib();
+		glDeleteTextures(1, &tempTex);
+	}
+	//-----------------------------------------------------------------------------  
+	/// blitFromMemory doing hardware trilinear scaling
+	void GLTextureBuffer::blitFromMemory(const PixelData &src_orig, const Box &dstBox)
+	{
+		/// Fall back to normal GLHardwarePixelBuffer::blitFromMemory in case 
+		/// - FBO is not supported
+		/// - Either source or target is luminance due doesn't looks like supported by hardware
+		/// - the source dimensions match the destination ones, in which case no scaling is needed
+		if(!GLEW_EXT_framebuffer_object ||
+			PixelUtil::isLuminance(src_orig.format) ||
+			PixelUtil::isLuminance(mFormat) ||
+			(src_orig.getWidth() == dstBox.getWidth() &&
+			src_orig.getHeight() == dstBox.getHeight() &&
+			src_orig.getDepth() == dstBox.getDepth()))
+		{
+			GLHardwarePixelBuffer::blitFromMemory(src_orig, dstBox);
+			return;
+		}
+		if(!mBuffer.contains(dstBox))
+			CM_EXCEPT(InvalidParametersException, "destination box out of range");
+		/// For scoped deletion of conversion buffer
+		void* data = NULL;
+		PixelData src;
     
     
-    /// First, convert the srcbox to a OpenGL compatible pixel format
-    if(GLPixelUtil::getGLOriginFormat(src_orig.format) == 0)
-    {
-        /// Convert to buffer internal format
-		data = new void*[PixelUtil::getMemorySize(src.getWidth(), src.getHeight(), src.getDepth(), mFormat)];
-        src = PixelData(src_orig.getWidth(), src_orig.getHeight(), src_orig.getDepth(), mFormat, data);
-        PixelUtil::bulkPixelConversion(src_orig, src);
-    }
-    else
-    {
-        /// No conversion needed
-        src = src_orig;
-    }
+		/// First, convert the srcbox to a OpenGL compatible pixel format
+		if(GLPixelUtil::getGLOriginFormat(src_orig.format) == 0)
+		{
+			/// Convert to buffer internal format
+			data = new void*[PixelUtil::getMemorySize(src.getWidth(), src.getHeight(), src.getDepth(), mFormat)];
+			src = PixelData(src_orig.getWidth(), src_orig.getHeight(), src_orig.getDepth(), mFormat, data);
+			PixelUtil::bulkPixelConversion(src_orig, src);
+		}
+		else
+		{
+			/// No conversion needed
+			src = src_orig;
+		}
     
     
-    /// Create temporary texture to store source data
-    GLuint id;
-    GLenum target = (src.getDepth()!=1)?GL_TEXTURE_3D:GL_TEXTURE_2D;
-    GLsizei width = GLPixelUtil::optionalPO2(src.getWidth());
-    GLsizei height = GLPixelUtil::optionalPO2(src.getHeight());
-    GLsizei depth = GLPixelUtil::optionalPO2(src.getDepth());
-    GLenum format = GLPixelUtil::getClosestGLInternalFormat(src.format);
+		/// Create temporary texture to store source data
+		GLuint id;
+		GLenum target = (src.getDepth()!=1)?GL_TEXTURE_3D:GL_TEXTURE_2D;
+		GLsizei width = GLPixelUtil::optionalPO2(src.getWidth());
+		GLsizei height = GLPixelUtil::optionalPO2(src.getHeight());
+		GLsizei depth = GLPixelUtil::optionalPO2(src.getDepth());
+		GLenum format = GLPixelUtil::getClosestGLInternalFormat(src.format);
     
     
-    /// Generate texture name
-    glGenTextures(1, &id);
+		/// Generate texture name
+		glGenTextures(1, &id);
     
     
-    /// Set texture type
-    glBindTexture(target, id);
+		/// Set texture type
+		glBindTexture(target, id);
     
     
-    /// Set automatic mipmap generation; nice for minimisation
-    glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, 1000 );
-    glTexParameteri(target, GL_GENERATE_MIPMAP, GL_TRUE );
+		/// Set automatic mipmap generation; nice for minimisation
+		glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, 1000 );
+		glTexParameteri(target, GL_GENERATE_MIPMAP, GL_TRUE );
     
     
-    /// Allocate texture memory
-    if(target == GL_TEXTURE_3D)
-        glTexImage3D(target, 0, format, width, height, depth, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
-    else
-        glTexImage2D(target, 0, format, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
+		/// Allocate texture memory
+		if(target == GL_TEXTURE_3D)
+			glTexImage3D(target, 0, format, width, height, depth, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
+		else
+			glTexImage2D(target, 0, format, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
 
 
-    /// GL texture buffer
-    GLTextureBuffer tex(StringUtil::BLANK, target, id, 0, 0, (Usage)(HBU_STATIC_WRITE_ONLY), false, false, 0);
+		/// GL texture buffer
+		GLTextureBuffer tex(StringUtil::BLANK, target, id, 0, 0, (Usage)(HBU_STATIC_WRITE_ONLY), false, false, 0);
     
     
-    /// Upload data to 0,0,0 in temporary texture
-	Box tempTarget(0, 0, 0, src.getWidth(), src.getHeight(), src.getDepth());
-    tex.upload(src, tempTarget);
+		/// Upload data to 0,0,0 in temporary texture
+		Box tempTarget(0, 0, 0, src.getWidth(), src.getHeight(), src.getDepth());
+		tex.upload(src, tempTarget);
     
     
-    /// Blit
-    blitFromTexture(&tex, tempTarget, dstBox);
+		/// Blit
+		blitFromTexture(&tex, tempTarget, dstBox);
     
     
-    /// Delete temp texture
-    glDeleteTextures(1, &id);
+		/// Delete temp texture
+		glDeleteTextures(1, &id);
 
 
-	if(data != NULL)
-		delete[] data;
-}
-//********* GLRenderBuffer
-//----------------------------------------------------------------------------- 
-GLRenderBuffer::GLRenderBuffer(GLenum format, UINT32 width, UINT32 height, GLsizei numSamples):
-    GLHardwarePixelBuffer(width, height, 1, GLPixelUtil::getClosestEngineFormat(format),HBU_WRITE_ONLY),
-    mRenderbufferID(0)
-{
-    mGLInternalFormat = format;
-    /// Generate renderbuffer
-    glGenRenderbuffersEXT(1, &mRenderbufferID);
-    /// Bind it to FBO
-    glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, mRenderbufferID);
+		if(data != NULL)
+			delete[] data;
+	}
+	//********* GLRenderBuffer
+	//----------------------------------------------------------------------------- 
+	GLRenderBuffer::GLRenderBuffer(GLenum format, UINT32 width, UINT32 height, GLsizei numSamples):
+		GLHardwarePixelBuffer(width, height, 1, GLPixelUtil::getClosestEngineFormat(format),HBU_WRITE_ONLY),
+		mRenderbufferID(0)
+	{
+		mGLInternalFormat = format;
+		/// Generate renderbuffer
+		glGenRenderbuffersEXT(1, &mRenderbufferID);
+		/// Bind it to FBO
+		glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, mRenderbufferID);
     
     
-    /// Allocate storage for depth buffer
-	if (numSamples > 0)
+		/// Allocate storage for depth buffer
+		if (numSamples > 0)
+		{
+			glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, 
+				numSamples, format, width, height);
+		}
+		else
+		{
+			glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, format,
+								width, height);
+		}
+	}
+	//----------------------------------------------------------------------------- 
+	GLRenderBuffer::~GLRenderBuffer()
 	{
 	{
-		glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, 
-			numSamples, format, width, height);
+		/// Generate renderbuffer
+		glDeleteRenderbuffersEXT(1, &mRenderbufferID);
 	}
 	}
-	else
+	//-----------------------------------------------------------------------------  
+	void GLRenderBuffer::bindToFramebuffer(GLenum attachment, UINT32 zoffset)
 	{
 	{
-		glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, format,
-							width, height);
+		assert(zoffset < mDepth);
+		glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, attachment,
+							GL_RENDERBUFFER_EXT, mRenderbufferID);
 	}
 	}
-}
-//----------------------------------------------------------------------------- 
-GLRenderBuffer::~GLRenderBuffer()
-{
-    /// Generate renderbuffer
-    glDeleteRenderbuffersEXT(1, &mRenderbufferID);
-}
-//-----------------------------------------------------------------------------  
-void GLRenderBuffer::bindToFramebuffer(GLenum attachment, UINT32 zoffset)
-{
-    assert(zoffset < mDepth);
-    glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, attachment,
-                        GL_RENDERBUFFER_EXT, mRenderbufferID);
-}
-
 };
 };

+ 1 - 1
CamelotGLRenderer/Source/CmGLMultiRenderTarget.cpp

@@ -35,7 +35,7 @@ namespace CamelotEngine {
 
 
 	GLMultiRenderTarget::GLMultiRenderTarget(GLRTTManager *manager, const String &name):
 	GLMultiRenderTarget::GLMultiRenderTarget(GLRTTManager *manager, const String &name):
 		MultiRenderTarget(name),
 		MultiRenderTarget(name),
-		fbo(manager, 0 /* TODO: multisampling on MRTs? */)
+		fbo(0 /* TODO: multisampling on MRTs? */)
 	{
 	{
 	}
 	}
 
 

+ 25 - 0
CamelotGLRenderer/Source/CmGLPixelFormat.cpp

@@ -180,6 +180,31 @@ namespace CamelotEngine  {
                 return 0;
                 return 0;
         }
         }
     }
     }
+
+	GLenum GLPixelUtil::getBaseFormatFromCompressedInternalFormat(GLenum internalFormat)
+	{
+		 switch(internalFormat) 
+		 {
+		 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
+		 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+		 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
+		 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
+		 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
+		 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
+			 return GL_RGBA;
+		 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+		 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
+			 return GL_RGB;
+		 case GL_COMPRESSED_RED_RGTC1:
+		 case GL_COMPRESSED_SIGNED_RED_RGTC1:
+			 return GL_RED;
+		 case GL_COMPRESSED_RG_RGTC2:
+		 case GL_COMPRESSED_SIGNED_RG_RGTC2:
+			 return GL_RG;
+		 }
+
+		 return GL_RGBA;
+	}
     
     
     GLenum GLPixelUtil::getGLInternalFormat(PixelFormat mFormat, bool hwGamma)
     GLenum GLPixelUtil::getGLInternalFormat(PixelFormat mFormat, bool hwGamma)
     {
     {

+ 10 - 9
CamelotGLRenderer/Source/CmGLRenderSystem.cpp

@@ -359,7 +359,7 @@ namespace CamelotEngine {
 			if (tex)
 			if (tex)
 			{
 			{
 				// note used
 				// note used
-				mTextureTypes[stage] = tex->getGLTextureTarget_internal();
+				mTextureTypes[stage] = tex->getGLTextureTarget();
 			}
 			}
 			else
 			else
 				// assume 2D
 				// assume 2D
@@ -379,7 +379,7 @@ namespace CamelotEngine {
 			}
 			}
 
 
 			if(tex)
 			if(tex)
-				glBindTexture( mTextureTypes[stage], tex->getGLID_internal() );
+				glBindTexture( mTextureTypes[stage], tex->getGLID() );
 			else
 			else
 			{
 			{
 				glBindTexture( mTextureTypes[stage], static_cast<GLTextureManager*>(&TextureManager::instance())->getWarningTextureID() );
 				glBindTexture( mTextureTypes[stage], static_cast<GLTextureManager*>(&TextureManager::instance())->getWarningTextureID() );
@@ -524,10 +524,6 @@ namespace CamelotEngine {
 	{
 	{
 		THROW_IF_NOT_RENDER_THREAD;
 		THROW_IF_NOT_RENDER_THREAD;
 
 
-		// Unbind frame buffer object
-		if(mActiveRenderTarget)
-			GLRTTManager::instancePtr()->unbind(mActiveRenderTarget);
-
 		mActiveRenderTarget = target;
 		mActiveRenderTarget = target;
 
 
 		// Switch context if different from current one
 		// Switch context if different from current one
@@ -538,8 +534,13 @@ namespace CamelotEngine {
 			switchContext(newContext);
 			switchContext(newContext);
 		}
 		}
 
 
-		// Bind frame buffer object
-		GLRTTManager::instancePtr()->bind(target);
+		GLFrameBufferObject *fbo = 0;
+		target->getCustomAttribute_internal("FBO", &fbo);
+		if(fbo)
+			fbo->bind();
+		else
+			// Old style context (window/pbuffer) or copying render texture
+			glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
 
 
 		if (GLEW_EXT_framebuffer_sRGB)
 		if (GLEW_EXT_framebuffer_sRGB)
 		{
 		{
@@ -1975,7 +1976,7 @@ namespace CamelotEngine {
 			if(caps->hasCapability(RSC_HWRENDER_TO_TEXTURE))
 			if(caps->hasCapability(RSC_HWRENDER_TO_TEXTURE))
 			{
 			{
 				// Create FBO manager
 				// Create FBO manager
-				GLRTTManager::startUp(new GLRTTManager(false));
+				GLRTTManager::startUp(new GLRTTManager());
 			}
 			}
 		}
 		}
 		else
 		else

+ 32 - 185
CamelotGLRenderer/Source/CmGLRenderTexture.cpp

@@ -27,50 +27,56 @@ THE SOFTWARE.
 */
 */
 #include "CmGLRenderTexture.h"
 #include "CmGLRenderTexture.h"
 #include "CmGLPixelFormat.h"
 #include "CmGLPixelFormat.h"
+#include "CmGLDepthStencilBuffer.h"
 #include "CmGLHardwarePixelBuffer.h"
 #include "CmGLHardwarePixelBuffer.h"
 #include "CmGLMultiRenderTarget.h"
 #include "CmGLMultiRenderTarget.h"
 
 
 namespace CamelotEngine 
 namespace CamelotEngine 
 {
 {
-	GLRenderTexture::GLRenderTexture(GLRTTManager* manager, const String &name, const GLSurfaceDesc &target, bool writeGamma, UINT32 fsaa):
-		mFB(manager, fsaa)
+	GLRenderTexture::GLRenderTexture()
+		:mFB(nullptr)
 	{
 	{
-		mName = name;
-		mHwGamma = writeGamma;
-		mFSAA = fsaa;
-
-		// Bind target to surface 0 and initialise
-		mFB.bindSurface(0, target);
-		// Get attributes
-		mWidth = mFB.getWidth();
-		mHeight = mFB.getHeight();
 	}
 	}
 
 
 	GLRenderTexture::~GLRenderTexture()
 	GLRenderTexture::~GLRenderTexture()
 	{
 	{
+		if(mFB != nullptr)
+			delete mFB;
+	}
+
+	void GLRenderTexture::createInternalResourcesImpl()
+	{
+		if(mFB != nullptr)
+			delete mFB;
+
+		mFB = new GLFrameBufferObject(mFSAA);
+
+		GLSurfaceDesc surfaceDesc;
+		surfaceDesc.numSamples = mFSAA;
+		surfaceDesc.zoffset = 0;
+
+		GLTexture* glTexture = static_cast<GLTexture*>(mTexture.get());
+		surfaceDesc.buffer = std::static_pointer_cast<GLHardwarePixelBuffer>(glTexture->getBuffer(mFace, mMipLevel));
+
+		mFB->bindSurface(0, surfaceDesc);
+
+		GLDepthStencilBuffer* glDepthStencilBuffer = static_cast<GLDepthStencilBuffer*>(mDepthStencilBuffer.get());
+
+		mFB->bindDepthStencil(glDepthStencilBuffer->getGLRenderBuffer());
 	}
 	}
 
 
 	void GLRenderTexture::getCustomAttribute_internal(const String& name, void* pData)
 	void GLRenderTexture::getCustomAttribute_internal(const String& name, void* pData)
 	{
 	{
 		if(name=="FBO")
 		if(name=="FBO")
 		{
 		{
-			*static_cast<GLFrameBufferObject **>(pData) = &mFB;
-		}
-		else if (name == "GL_FBOID")
-		{
-			*static_cast<GLuint*>(pData) = mFB.getGLFBOID();
+			*static_cast<GLFrameBufferObject **>(pData) = mFB;
 		}
 		}
-		else if (name == "GL_MULTISAMPLEFBOID")
+		else if (name == "GL_FBOID" || name == "GL_MULTISAMPLEFBOID")
 		{
 		{
-			*static_cast<GLuint*>(pData) = mFB.getGLMultisampleFBOID();
+			*static_cast<GLuint*>(pData) = mFB->getGLFBOID();
 		}
 		}
 	}
 	}
 
 
-	void GLRenderTexture::swapBuffers(bool waitForVSync)
-	{
-		mFB.swapBuffers();
-	}
-
 /// Size of probe texture
 /// Size of probe texture
 #define PROBE_SIZE 16
 #define PROBE_SIZE 16
 
 
@@ -103,22 +109,15 @@ static const UINT32 depthBits[] =
 };
 };
 #define DEPTHFORMAT_COUNT (sizeof(depthFormats)/sizeof(GLenum))
 #define DEPTHFORMAT_COUNT (sizeof(depthFormats)/sizeof(GLenum))
 
 
-	GLRTTManager::GLRTTManager(bool atimode):
-		mATIMode(atimode)
+	GLRTTManager::GLRTTManager()
     {
     {
-        detectFBOFormats();
-        
+		detectFBOFormats();
+
         glGenFramebuffersEXT(1, &mTempFBO);
         glGenFramebuffersEXT(1, &mTempFBO);
     }
     }
 
 
 	GLRTTManager::~GLRTTManager()
 	GLRTTManager::~GLRTTManager()
 	{
 	{
-		if(!mRenderBufferMap.empty())
-		{
-			// TODO LOG PORT - Log this somewhere
-			//LogManager::getSingleton().logMessage("GL: Warning! GLFBOManager destructor called, but not all renderbuffers were released.");
-		}
-        
         glDeleteFramebuffersEXT(1, &mTempFBO);      
         glDeleteFramebuffersEXT(1, &mTempFBO);      
 	}
 	}
 
 
@@ -247,12 +246,6 @@ static const UINT32 depthBits[] =
 			if(PixelUtil::isCompressed((PixelFormat)x))
 			if(PixelUtil::isCompressed((PixelFormat)x))
 				continue;
 				continue;
 
 
-			// Buggy ATI cards *crash* on non-RGB(A) formats
-			int depths[4];
-			PixelUtil::getBitDepths((PixelFormat)x, depths);
-			if(fmt!=GL_NONE && mATIMode && (!depths[0] || !depths[1] || !depths[2]))
-				continue;
-
             // Create and attach framebuffer
             // Create and attach framebuffer
             glGenFramebuffersEXT(1, &fb);
             glGenFramebuffersEXT(1, &fb);
             glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb);
             glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb);
@@ -289,9 +282,6 @@ static const UINT32 depthBits[] =
             if(fmt == GL_NONE || status == GL_FRAMEBUFFER_COMPLETE_EXT)
             if(fmt == GL_NONE || status == GL_FRAMEBUFFER_COMPLETE_EXT)
             {
             {
                 mProps[x].valid = true;
                 mProps[x].valid = true;
-				StringUtil::StrStreamType str;
-				str << "FBO " << PixelUtil::getFormatName((PixelFormat)x) 
-					<< " depth/stencil support: ";
 
 
                 // For each depth/stencil formats
                 // For each depth/stencil formats
                 for (UINT32 depth = 0; depth < DEPTHFORMAT_COUNT; ++depth)
                 for (UINT32 depth = 0; depth < DEPTHFORMAT_COUNT; ++depth)
@@ -299,19 +289,11 @@ static const UINT32 depthBits[] =
                     if (depthFormats[depth] != GL_DEPTH24_STENCIL8_EXT)
                     if (depthFormats[depth] != GL_DEPTH24_STENCIL8_EXT)
                     {
                     {
                         // General depth/stencil combination
                         // General depth/stencil combination
-
                         for (UINT32 stencil = 0; stencil < STENCILFORMAT_COUNT; ++stencil)
                         for (UINT32 stencil = 0; stencil < STENCILFORMAT_COUNT; ++stencil)
                         {
                         {
-                            //StringUtil::StrStreamType l;
-                            //l << "Trying " << PixelUtil::getFormatName((PixelFormat)x) 
-                            //	<< " D" << depthBits[depth] 
-                            //	<< "S" << stencilBits[stencil];
-                            //LogManager::getSingleton().logMessage(l.str());
-
                             if (_tryFormat(depthFormats[depth], stencilFormats[stencil]))
                             if (_tryFormat(depthFormats[depth], stencilFormats[stencil]))
                             {
                             {
                                 /// Add mode to allowed modes
                                 /// Add mode to allowed modes
-                                str << "D" << depthBits[depth] << "S" << stencilBits[stencil] << " ";
                                 FormatProperties::Mode mode;
                                 FormatProperties::Mode mode;
                                 mode.depth = depth;
                                 mode.depth = depth;
                                 mode.stencil = stencil;
                                 mode.stencil = stencil;
@@ -325,7 +307,6 @@ static const UINT32 depthBits[] =
                         if (_tryPackedFormat(depthFormats[depth]))
                         if (_tryPackedFormat(depthFormats[depth]))
                         {
                         {
                             /// Add mode to allowed modes
                             /// Add mode to allowed modes
-                            str << "Packed-D" << depthBits[depth] << "S" << 8 << " ";
                             FormatProperties::Mode mode;
                             FormatProperties::Mode mode;
                             mode.depth = depth;
                             mode.depth = depth;
                             mode.stencil = 0;   // unuse
                             mode.stencil = 0;   // unuse
@@ -356,141 +337,7 @@ static const UINT32 depthBits[] =
                 fmtstring += PixelUtil::getFormatName((PixelFormat)x)+" ";
                 fmtstring += PixelUtil::getFormatName((PixelFormat)x)+" ";
         }
         }
     }
     }
-    void GLRTTManager::getBestDepthStencil(GLenum internalFormat, GLenum *depthFormat, GLenum *stencilFormat)
-    {
-        const FormatProperties &props = mProps[internalFormat];
-        /// Decide what stencil and depth formats to use
-        /// [best supported for internal format]
-        size_t bestmode=0;
-        UINT32 bestscore=0;
-        for(size_t mode=0; mode<props.modes.size(); mode++)
-        {
-#if 0
-            /// Always prefer D24S8
-            if(stencilBits[props.modes[mode].stencil]==8 &&
-                depthBits[props.modes[mode].depth]==24)
-            {
-                bestmode = mode;
-                break;
-            }
-#endif
-            UINT32 desirability = 0;
-            /// Find most desirable mode
-            /// desirability == 0            if no depth, no stencil
-            /// desirability == 1000...2000  if no depth, stencil
-            /// desirability == 2000...3000  if depth, no stencil
-            /// desirability == 3000+        if depth and stencil
-            /// beyond this, the total numer of bits (stencil+depth) is maximised
-            if(props.modes[mode].stencil)
-                desirability += 1000;
-            if(props.modes[mode].depth)
-                desirability += 2000;
-            if(depthBits[props.modes[mode].depth]==24) // Prefer 24 bit for now
-                desirability += 500;
-			if(depthFormats[props.modes[mode].depth]==GL_DEPTH24_STENCIL8_EXT) // Prefer 24/8 packed 
-				desirability += 5000;
-            desirability += stencilBits[props.modes[mode].stencil] + depthBits[props.modes[mode].depth];
-            
-            if(desirability>bestscore)
-            {
-                bestscore = desirability;
-                bestmode = mode;
-            }
-        }
-        *depthFormat = depthFormats[props.modes[bestmode].depth];
-        *stencilFormat = stencilFormats[props.modes[bestmode].stencil];
-    }
-
-    GLRenderTexture *GLRTTManager::createRenderTexture(const String &name, 
-		const GLSurfaceDesc &target, bool writeGamma, UINT32 fsaa)
-    {
-        GLRenderTexture *retval = new GLRenderTexture(this, name, target, writeGamma, fsaa);
-        return retval;
-    }
-
-	MultiRenderTarget *GLRTTManager::createMultiRenderTarget(const String & name)
-	{
-		return new GLMultiRenderTarget(this, name);
-	}
-
-    void GLRTTManager::bind(RenderTarget *target)
-    {
-        /// Check if the render target is in the rendertarget->FBO map
-        GLFrameBufferObject *fbo = 0;
-        target->getCustomAttribute_internal("FBO", &fbo);
-        if(fbo)
-            fbo->bind();
-        else
-            // Old style context (window/pbuffer) or copying render texture
-            glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
-    }
     
     
-    GLSurfaceDesc GLRTTManager::requestRenderBuffer(GLenum format, UINT32 width, UINT32 height, UINT32 fsaa)
-    {
-        GLSurfaceDesc retval;
-        retval.buffer = 0; // Return 0 buffer if GL_NONE is requested
-        if(format != GL_NONE)
-        {
-            RBFormat key(format, width, height, fsaa);
-            RenderBufferMap::iterator it = mRenderBufferMap.find(key);
-            if(it != mRenderBufferMap.end())
-            {
-                retval.buffer = it->second.buffer;
-                retval.zoffset = 0;
-				retval.numSamples = fsaa;
-                // Increase refcount
-                ++it->second.refcount;
-            }
-            else
-            {
-                // New one
-                GLRenderBuffer *rb = new GLRenderBuffer(format, width, height, fsaa);
-                mRenderBufferMap[key] = RBRef(rb);
-                retval.buffer = rb;
-                retval.zoffset = 0;
-				retval.numSamples = fsaa;
-            }
-        }
-
-        return retval;
-    }
-
-    void GLRTTManager::requestRenderBuffer(const GLSurfaceDesc &surface)
-    {
-        if(surface.buffer == 0)
-            return;
-        RBFormat key(surface.buffer->getGLFormat(), surface.buffer->getWidth(), surface.buffer->getHeight(), surface.numSamples);
-        RenderBufferMap::iterator it = mRenderBufferMap.find(key);
-        assert(it != mRenderBufferMap.end());
-        if (it != mRenderBufferMap.end())   // Just in case
-        {
-            assert(it->second.buffer == surface.buffer);
-            // Increase refcount
-            ++it->second.refcount;
-        }
-    }
-
-    void GLRTTManager::releaseRenderBuffer(const GLSurfaceDesc &surface)
-    {
-        if(surface.buffer == 0)
-            return;
-        RBFormat key(surface.buffer->getGLFormat(), surface.buffer->getWidth(), surface.buffer->getHeight(), surface.numSamples);
-        RenderBufferMap::iterator it = mRenderBufferMap.find(key);
-        if(it != mRenderBufferMap.end())
-		{
-			// Decrease refcount
-			--it->second.refcount;
-			if(it->second.refcount==0)
-			{
-				// If refcount reaches zero, delete buffer and remove from map
-				delete it->second.buffer;
-				mRenderBufferMap.erase(it);
-				//std::cerr << "Destroyed renderbuffer of format " << std::hex << key.format << std::dec
-				//        << " of " << key.width << "x" << key.height << std::endl;
-			}
-		}
-    }
-
     PixelFormat GLRTTManager::getSupportedAlternative(PixelFormat format)
     PixelFormat GLRTTManager::getSupportedAlternative(PixelFormat format)
     {
     {
         if(checkFormat(format))
         if(checkFormat(format))

+ 55 - 75
CamelotGLRenderer/Source/CmGLTexture.cpp

@@ -77,14 +77,17 @@ namespace CamelotEngine {
 		Resource::initialize_internal();
 		Resource::initialize_internal();
 	}
 	}
 
 
-    GLenum GLTexture::getGLTextureTarget_internal(void) const
+    GLenum GLTexture::getGLTextureTarget(void) const
     {
     {
         switch(mTextureType)
         switch(mTextureType)
         {
         {
             case TEX_TYPE_1D:
             case TEX_TYPE_1D:
                 return GL_TEXTURE_1D;
                 return GL_TEXTURE_1D;
             case TEX_TYPE_2D:
             case TEX_TYPE_2D:
-                return GL_TEXTURE_2D;
+				if(mFSAA > 0)
+					return GL_TEXTURE_2D_MULTISAMPLE;
+				else
+					return GL_TEXTURE_2D;
             case TEX_TYPE_3D:
             case TEX_TYPE_3D:
                 return GL_TEXTURE_3D;
                 return GL_TEXTURE_3D;
             case TEX_TYPE_CUBE_MAP:
             case TEX_TYPE_CUBE_MAP:
@@ -94,7 +97,7 @@ namespace CamelotEngine {
         };
         };
     }
     }
 
 
-	GLuint GLTexture::getGLID_internal() const
+	GLuint GLTexture::getGLID() const
 	{
 	{
 		THROW_IF_NOT_RENDER_THREAD;
 		THROW_IF_NOT_RENDER_THREAD;
 
 
@@ -152,7 +155,6 @@ namespace CamelotEngine {
         mWidth = GLPixelUtil::optionalPO2(mWidth);      
         mWidth = GLPixelUtil::optionalPO2(mWidth);      
         mHeight = GLPixelUtil::optionalPO2(mHeight);
         mHeight = GLPixelUtil::optionalPO2(mHeight);
         mDepth = GLPixelUtil::optionalPO2(mDepth);
         mDepth = GLPixelUtil::optionalPO2(mDepth);
-		
 
 
 		// Adjust format if required
 		// Adjust format if required
 		mFormat = TextureManager::instance().getNativeFormat(mTextureType, mFormat, mUsage);
 		mFormat = TextureManager::instance().getNativeFormat(mTextureType, mFormat, mUsage);
@@ -162,23 +164,31 @@ namespace CamelotEngine {
 		if(mNumMipmaps>maxMips)
 		if(mNumMipmaps>maxMips)
 			mNumMipmaps = maxMips;
 			mNumMipmaps = maxMips;
 		
 		
+		if((mUsage & TU_RENDERTARGET) != 0)
+		{
+			mNumMipmaps = 1;
+
+			if(mTextureType != TEX_TYPE_2D)
+				CM_EXCEPT(NotImplementedException, "Only 2D render targets are supported at the moment");
+		}
+
 		// Generate texture name
 		// Generate texture name
         glGenTextures( 1, &mTextureID );
         glGenTextures( 1, &mTextureID );
 		
 		
 		// Set texture type
 		// Set texture type
-		glBindTexture( getGLTextureTarget_internal(), mTextureID );
+		glBindTexture( getGLTextureTarget(), mTextureID );
         
         
 		// This needs to be set otherwise the texture doesn't get rendered
 		// This needs to be set otherwise the texture doesn't get rendered
 		if (GLEW_VERSION_1_2)
 		if (GLEW_VERSION_1_2)
-			glTexParameteri( getGLTextureTarget_internal(), GL_TEXTURE_MAX_LEVEL, mNumMipmaps );
+			glTexParameteri( getGLTextureTarget(), GL_TEXTURE_MAX_LEVEL, mNumMipmaps );
         
         
         // Set some misc default parameters so NVidia won't complain, these can of course be changed later
         // Set some misc default parameters so NVidia won't complain, these can of course be changed later
-        glTexParameteri(getGLTextureTarget_internal(), GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-        glTexParameteri(getGLTextureTarget_internal(), GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+        glTexParameteri(getGLTextureTarget(), GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+        glTexParameteri(getGLTextureTarget(), GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 		if (GLEW_VERSION_1_2)
 		if (GLEW_VERSION_1_2)
 		{
 		{
-			glTexParameteri(getGLTextureTarget_internal(), GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-			glTexParameteri(getGLTextureTarget_internal(), GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+			glTexParameteri(getGLTextureTarget(), GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+			glTexParameteri(getGLTextureTarget(), GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
 		}
 		}
 		
 		
 		// Allocate internal buffer so that glTexSubImageXD can be used
 		// Allocate internal buffer so that glTexSubImageXD can be used
@@ -188,49 +198,19 @@ namespace CamelotEngine {
 		UINT32 height = mHeight;
 		UINT32 height = mHeight;
 		UINT32 depth = mDepth;
 		UINT32 depth = mDepth;
 
 
+		GLenum glFormat = GL_RGBA;
 		if(PixelUtil::isCompressed(mFormat))
 		if(PixelUtil::isCompressed(mFormat))
 		{
 		{
-			// Compressed formats
-			UINT32 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(UINT32 mip=0; mip<=mNumMipmaps; mip++)
-			{
-				size = PixelUtil::getMemorySize(width, height, depth, mFormat);
-				switch(mTextureType)
-				{
-					case TEX_TYPE_1D:
-						glCompressedTexImage1DARB(GL_TEXTURE_1D, mip, format, 
-							width, 0, 
-							size, tmpdata);
-						break;
-					case TEX_TYPE_2D:
-						glCompressedTexImage2DARB(GL_TEXTURE_2D, mip, format,
-							width, height, 0, 
-							size, tmpdata);
-						break;
-					case TEX_TYPE_3D:
-						glCompressedTexImage3DARB(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(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;
+			if((mUsage & TU_RENDERTARGET) != 0)
+				CM_EXCEPT(InvalidParametersException, "Cannot use a compressed format for a render target.");
+
+			glFormat = GLPixelUtil::getBaseFormatFromCompressedInternalFormat(mFormat);
+		}
+
+		if((mUsage & TU_RENDERTARGET) != 0 && mTextureType == TEX_TYPE_2D && mFSAA > 0)
+		{
+			glTexImage2DMultisample(GL_TEXTURE_2D, mFSAA, format,
+				width, height, GL_FALSE);
 		}
 		}
 		else
 		else
 		{
 		{
@@ -240,35 +220,35 @@ namespace CamelotEngine {
 				// Normal formats
 				// Normal formats
 				switch(mTextureType)
 				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;
+				case TEX_TYPE_1D:
+					glTexImage1D(GL_TEXTURE_1D, mip, format,
+						width, 0, 
+						GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+
+					break;
+				case TEX_TYPE_2D:
+					glTexImage2D(GL_TEXTURE_2D, mip, format,
+						width, height, 0, 
+						GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+					break;
+				case TEX_TYPE_3D:
+					glTexImage3D(GL_TEXTURE_3D, mip, format,
+						width, height, depth, 0, 
+						GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+					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, nullptr);
+					}
+					break;
 				};
 				};
 				if(width>1)		width = width/2;
 				if(width>1)		width = width/2;
 				if(height>1)	height = height/2;
 				if(height>1)	height = height/2;
 				if(depth>1)		depth = depth/2;
 				if(depth>1)		depth = depth/2;
 			}
 			}
 		}
 		}
+
 		createSurfaceList();
 		createSurfaceList();
 		// Get final internal format
 		// Get final internal format
 		mFormat = getBuffer(0,0)->getFormat();
 		mFormat = getBuffer(0,0)->getFormat();
@@ -288,7 +268,7 @@ namespace CamelotEngine {
 		{
 		{
 			for(UINT32 mip=0; mip<=getNumMipmaps(); mip++)
 			for(UINT32 mip=0; mip<=getNumMipmaps(); mip++)
 			{
 			{
-                GLHardwarePixelBuffer *buf = new GLTextureBuffer("", getGLTextureTarget_internal(), mTextureID, face, mip,
+                GLHardwarePixelBuffer *buf = new GLTextureBuffer("", getGLTextureTarget(), mTextureID, face, mip,
 						static_cast<HardwareBuffer::Usage>(mUsage), false, mHwGamma, mFSAA);
 						static_cast<HardwareBuffer::Usage>(mUsage), false, mHwGamma, mFSAA);
 				mSurfaceList.push_back(HardwarePixelBufferPtr(buf));
 				mSurfaceList.push_back(HardwarePixelBufferPtr(buf));
                 
                 

+ 34 - 6
CamelotRenderer/Include/CmRenderTexture.h

@@ -29,7 +29,7 @@ THE SOFTWARE.
 #define __RenderTexture_H__
 #define __RenderTexture_H__
 
 
 #include "CmPrerequisites.h"
 #include "CmPrerequisites.h"
-
+#include "CmTexture.h"
 #include "CmRenderTarget.h"
 #include "CmRenderTarget.h"
 
 
 namespace CamelotEngine
 namespace CamelotEngine
@@ -47,14 +47,42 @@ namespace CamelotEngine
     */
     */
     class CM_EXPORT RenderTexture: public RenderTarget
     class CM_EXPORT RenderTexture: public RenderTarget
     {
     {
-    public:
-        RenderTexture();
-        virtual ~RenderTexture();
+	public:
+		virtual ~RenderTexture() {}
 
 
-		virtual void copyContentsToMemory(const PixelData &dst, FrameBuffer buffer);
-		PixelFormat suggestPixelFormat() const;
+		void setBuffers(TexturePtr texture, DepthStencilBufferPtr depthStencilbuffer, 
+			UINT32 face = 0, UINT32 numFaces = 0, UINT32 mipLevel = 0);
+
+		TexturePtr getTexture() const { return mTexture; }
+		DepthStencilBufferPtr getDepthStencilBuffer() const { return mDepthStencilBuffer; }
+
+		bool requiresTextureFlipping() const { return false; }
 
 
 	protected:
 	protected:
+		TextureType mType;
+		PixelFormat mFormat;
+		UINT32 mDepthBits;
+		UINT32 mFace;
+		UINT32 mNumFaces;
+		UINT32 mMipLevel;
+
+		TexturePtr mTexture;
+		DepthStencilBufferPtr mDepthStencilBuffer;
+
+		RenderTexture();
+
+		void initialize(TextureType textureType, UINT32 width, UINT32 height, 
+			PixelFormat format, bool hwGamma, UINT32 fsaa, const String& fsaaHint, 
+			bool createDepth = true, UINT32 depthBits = 32);
+
+		void initialize(TexturePtr texture, DepthStencilBufferPtr depthStencilbuffer, 
+			UINT32 face = 0, UINT32 numFaces = 0, UINT32 mipLevel = 0);
+
+		void createTextureBuffer();
+		void createDepthStencilBuffer();
+
+		void createInternalResources();
+		virtual void createInternalResourcesImpl() = 0;
     };
     };
 
 
 	/** This class represents a render target that renders to multiple RenderTextures
 	/** This class represents a render target that renders to multiple RenderTextures

+ 102 - 13
CamelotRenderer/Source/CmRenderTexture.cpp

@@ -29,27 +29,116 @@ THE SOFTWARE.
 #include "CmRenderTexture.h"
 #include "CmRenderTexture.h"
 #include "CmException.h"
 #include "CmException.h"
 #include "CmHardwarePixelBuffer.h"
 #include "CmHardwarePixelBuffer.h"
+#include "CmTexture.h"
+#include "CmTextureManager.h"
+#include "CmDepthStencilBuffer.h"
 
 
 namespace CamelotEngine
 namespace CamelotEngine
 {
 {
-
-    //-----------------------------------------------------------------------------
 	RenderTexture::RenderTexture()
 	RenderTexture::RenderTexture()
-    {
-    }
-    RenderTexture::~RenderTexture()
-    {
+	{
 
 
-    }
+	}
 
 
-	void RenderTexture::copyContentsToMemory(const PixelData &dst, FrameBuffer buffer)
-    {
-		CM_EXCEPT(NotImplementedException, "Not implemented");
+	void RenderTexture::initialize(TextureType textureType, UINT32 width, UINT32 height, 
+		PixelFormat format, bool hwGamma, UINT32 fsaa, const String& fsaaHint,
+		bool createDepth, UINT32 depthBits)
+	{
+		mPriority = CM_REND_TO_TEX_RT_GROUP;
+		mWidth = width;
+		mHeight = height;
+		mType = textureType;
+		mFormat = format;
+		mColorDepth = CamelotEngine::PixelUtil::getNumElemBits(format);
+		mActive = true;
+		mHwGamma = hwGamma;
+		mFSAA = fsaa;
+		mFSAAHint = fsaaHint;
+		mDepthBits = depthBits;
+		mFace = 0;
+		mMipLevel = 0;
+
+		createTextureBuffer();
+
+		if(createDepth)
+			createDepthStencilBuffer();
+
+		createInternalResourcesImpl();
+	}
+
+	void RenderTexture::initialize(TexturePtr texture, DepthStencilBufferPtr depthStencilbuffer, UINT32 face, UINT32 numFaces, UINT32 mipLevel)
+	{
+		setBuffers(texture, depthStencilbuffer, face, numFaces, mipLevel);
+	}
+
+	void RenderTexture::createInternalResources()
+	{
+		if(mTexture->getTextureType() != TEX_TYPE_2D)
+			CM_EXCEPT(NotImplementedException, "Render textures are currently only implemented for 2D surfaces.");
+
+		if((mFace + mNumFaces) >= mTexture->getNumFaces())
+		{
+			CM_EXCEPT(InvalidParametersException, "Provided number of faces is out of range. Face: " + 
+				toString(mFace + mNumFaces) + ". Max num faces: " + toString(mTexture->getNumFaces()));
+		}
+
+		if(mMipLevel >= mTexture->getNumMipmaps())
+		{
+			CM_EXCEPT(InvalidParametersException, "Provided number of mip maps is out of range. Mip level: " + 
+				toString(mMipLevel) + ". Max num mipmaps: " + toString(mTexture->getNumMipmaps()));
+		}
+
+		createInternalResourcesImpl();
 	}
 	}
-	//---------------------------------------------------------------------
-	PixelFormat RenderTexture::suggestPixelFormat() const
+
+	void RenderTexture::createTextureBuffer()
 	{
 	{
-		CM_EXCEPT(NotImplementedException, "Not implemented");
+		mTexture = TextureManager::instance().createTexture(mType, mWidth, mHeight, 0, mFormat, TU_RENDERTARGET, mHwGamma, mFSAA, mFSAAHint);
+	}
+
+	void RenderTexture::createDepthStencilBuffer()
+	{
+		mDepthStencilBuffer = TextureManager::instance().createDepthStencilBuffer(mDepthBits, mWidth, mHeight, mFSAA, mFSAAHint);
+	}
+
+	void RenderTexture::setBuffers(TexturePtr texture, DepthStencilBufferPtr depthStencilBuffer, UINT32 face, UINT32 numFaces, UINT32 mipLevel)
+	{
+		assert(texture != nullptr);
+		assert(depthStencilBuffer != nullptr);
+
+		mPriority = CM_REND_TO_TEX_RT_GROUP;
+
+		if(texture->getWidth() != depthStencilBuffer->getWidth() ||
+			texture->getHeight() != depthStencilBuffer->getWidth() ||
+			texture->getFSAA() != depthStencilBuffer->getFsaa() ||
+			texture->getFSAAHint() != depthStencilBuffer->getFsaaHint())
+		{
+			String errorInfo = "\nWidth: " + toString(texture->getWidth()) + "/" + toString(depthStencilBuffer->getWidth());
+			errorInfo += "\nHeight: " + toString(texture->getHeight()) + "/" + toString(depthStencilBuffer->getHeight());
+			errorInfo += "\nFSAA: " + toString(texture->getFSAA()) + "/" + toString(depthStencilBuffer->getFsaa());
+			errorInfo += "\nFSAAHint: " + texture->getFSAAHint() + "/" + depthStencilBuffer->getFsaaHint();
+
+			CM_EXCEPT(InvalidParametersException, "Provided texture and depth stencil buffer don't match!" + errorInfo);
+		}
+
+		mWidth = texture->getWidth();
+		mHeight = texture->getWidth();
+		mColorDepth = CamelotEngine::PixelUtil::getNumElemBits(texture->getFormat());
+		mActive = true;
+		mHwGamma = texture->isHardwareGammaEnabled();
+		mFSAA = texture->getFSAA();
+		mFSAAHint = texture->getFSAAHint();
+		mType = texture->getTextureType();
+		mFormat = texture->getFormat();
+		mDepthBits = depthStencilBuffer->getBitDepth();
+		mFace = face;
+		mNumFaces = face;
+		mMipLevel = mipLevel;
+
+		mTexture = texture;
+		mDepthStencilBuffer = depthStencilBuffer;
+
+		createInternalResourcesImpl();
 	}
 	}
 	//-----------------------------------------------------------------------------
 	//-----------------------------------------------------------------------------
 	MultiRenderTarget::MultiRenderTarget(const String &name)
 	MultiRenderTarget::MultiRenderTarget(const String &name)

+ 8 - 0
CamelotRenderer/TODO.txt

@@ -17,6 +17,12 @@
 
 
 
 
 /////
 /////
+
+Make separate DepthStencilBuffer object for OpenGL and assign it in GLRenderTexture & GLFrameBufferObject. Right now a new one is created or taken from a pool
+Add support for MultiRenderTexture
+Enhance TextureManager so it creates RenderTextures and MultiRenderTextures
+Create DX9 and OpenGL RenderTextures
+
 waitForVsync can probably be moved somewhere other than being directly in RenderSystem? (where is it in DX11?)
 waitForVsync can probably be moved somewhere other than being directly in RenderSystem? (where is it in DX11?)
 Drop OpenGL support for low level shaders? (See if cg can translate to GLSL)
 Drop OpenGL support for low level shaders? (See if cg can translate to GLSL)
 
 
@@ -137,6 +143,7 @@ Low priority TODO:
      - setPreprocessorDefines, setColumnMajorMatrices, setOptimisationLevel
      - setPreprocessorDefines, setColumnMajorMatrices, setOptimisationLevel
  - OpenGL seems to generate a mip pyramid regardless of the setting (in createInternalResourcesImpl)
  - OpenGL seems to generate a mip pyramid regardless of the setting (in createInternalResourcesImpl)
  - DepthStencilBuffer & Texture should possibly share the same interface instead of being two separate classes? I'll need to assign DepthStencil to shaders sometimes. Not possible in DX9 but possible in DX11.
  - DepthStencilBuffer & Texture should possibly share the same interface instead of being two separate classes? I'll need to assign DepthStencil to shaders sometimes. Not possible in DX9 but possible in DX11.
+ - CPU reading or writing to a render texture in OpenGL is not supported. (CmGLHardwarePixelBuffer::upload/download). 
 
 
 Optional TODO:
 Optional TODO:
  - Add precompiled headers to all projects
  - Add precompiled headers to all projects
@@ -147,6 +154,7 @@ Optional TODO:
  - Serializable callbacks can't be null otherwise compiler complains
  - Serializable callbacks can't be null otherwise compiler complains
  - FBX importer can be greatly sped up by implementing a better allocator
  - FBX importer can be greatly sped up by implementing a better allocator
  - Extend texture copy so it accepts different subregions & subresources (currently only entire resource can be copied)
  - Extend texture copy so it accepts different subregions & subresources (currently only entire resource can be copied)
+ - Need a way to convert MSAA render texture into a normal render texture
 
 
  -----------------------------------------------------------------------------------------------
  -----------------------------------------------------------------------------------------------