فهرست منبع

RenderTexture & PixelBuffer ported

Marko Pintera 13 سال پیش
والد
کامیت
ee12339cc3

+ 7 - 0
CamelotRenderer/CamelotRenderer.vcxproj

@@ -100,10 +100,12 @@
     <ClInclude Include="OgreHardwareBufferManager.h" />
     <ClInclude Include="OgreHardwareIndexBuffer.h" />
     <ClInclude Include="OgreHardwareOcclusionQuery.h" />
+    <ClInclude Include="OgreHardwarePixelBuffer.h" />
     <ClInclude Include="OgreHardwareVertexBuffer.h" />
     <ClInclude Include="OgreHeaderPrefix.h" />
     <ClInclude Include="OgreHeaderSuffix.h" />
     <ClInclude Include="OgreHighLevelGpuProgram.h" />
+    <ClInclude Include="OgreImageResampler.h" />
     <ClInclude Include="OgreMath.h" />
     <ClInclude Include="OgreMatrix3.h" />
     <ClInclude Include="OgreMatrix4.h" />
@@ -118,6 +120,8 @@
     <ClInclude Include="OgreRenderOperation.h" />
     <ClInclude Include="OgreRenderSystemCapabilities.h" />
     <ClInclude Include="OgreRenderTarget.h" />
+    <ClInclude Include="OgreRenderTexture.h" />
+    <ClInclude Include="OgreRenderWindow.h" />
     <ClInclude Include="OgreSharedPtr.h" />
     <ClInclude Include="OgreSingleton.h" />
     <ClInclude Include="OgreSphere.h" />
@@ -150,6 +154,7 @@
     <ClCompile Include="OgreHardwareBufferManager.cpp" />
     <ClCompile Include="OgreHardwareIndexBuffer.cpp" />
     <ClCompile Include="OgreHardwareOcclusionQuery.cpp" />
+    <ClCompile Include="OgreHardwarePixelBuffer.cpp" />
     <ClCompile Include="OgreHardwareVertexBuffer.cpp" />
     <ClCompile Include="OgreHighLevelGpuProgram.cpp" />
     <ClCompile Include="OgreMath.cpp" />
@@ -160,6 +165,8 @@
     <ClCompile Include="OgreQuaternion.cpp" />
     <ClCompile Include="OgreRenderSystemCapabilities.cpp" />
     <ClCompile Include="OgreRenderTarget.cpp" />
+    <ClCompile Include="OgreRenderTexture.cpp" />
+    <ClCompile Include="OgreRenderWindow.cpp" />
     <ClCompile Include="OgreString.cpp" />
     <ClCompile Include="OgreStringConverter.cpp" />
     <ClCompile Include="OgreStringInterface.cpp" />

+ 21 - 0
CamelotRenderer/CamelotRenderer.vcxproj.filters

@@ -198,6 +198,18 @@
     <ClInclude Include="OgreHardwareOcclusionQuery.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="OgreRenderWindow.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="OgreRenderTexture.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="OgreHardwarePixelBuffer.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="OgreImageResampler.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="stdafx.cpp">
@@ -299,5 +311,14 @@
     <ClCompile Include="OgreHardwareOcclusionQuery.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="OgreRenderWindow.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="OgreRenderTexture.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="OgreHardwarePixelBuffer.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>

+ 194 - 0
CamelotRenderer/OgreHardwarePixelBuffer.cpp

@@ -0,0 +1,194 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org
+
+Copyright (c) 2000-2011 Torus Knot Software Ltd
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+-----------------------------------------------------------------------------
+*/
+#include "OgreHardwarePixelBuffer.h"
+#include "OgreException.h"
+
+namespace Ogre 
+{
+  
+    //-----------------------------------------------------------------------------    
+    HardwarePixelBuffer::HardwarePixelBuffer(size_t width, size_t height, size_t depth,
+            PixelFormat format,
+            HardwareBuffer::Usage usage, bool useSystemMemory, bool useShadowBuffer):
+        HardwareBuffer(usage, useSystemMemory, useShadowBuffer),
+        mWidth(width), mHeight(height), mDepth(depth),
+        mFormat(format)
+    {
+        // Default
+        mRowPitch = mWidth;
+        mSlicePitch = mHeight*mWidth;
+		mSizeInBytes = mHeight*mWidth*PixelUtil::getNumElemBytes(mFormat);
+    }
+    
+    //-----------------------------------------------------------------------------    
+    HardwarePixelBuffer::~HardwarePixelBuffer()
+    {
+    }
+    
+    //-----------------------------------------------------------------------------    
+    void* HardwarePixelBuffer::lock(size_t offset, size_t length, LockOptions options)
+    {
+        assert(!isLocked() && "Cannot lock this buffer, it is already locked!");
+        assert(offset == 0 && length == mSizeInBytes && "Cannot lock memory region, most lock box or entire buffer");
+        
+        Box myBox(0, 0, 0, mWidth, mHeight, mDepth);
+        const PixelBox &rv = lock(myBox, options);
+        return rv.data;
+    }
+    
+    //-----------------------------------------------------------------------------    
+    const PixelBox& HardwarePixelBuffer::lock(const Box& lockBox, LockOptions options)
+    {
+        if (mUseShadowBuffer)
+        {
+            if (options != HBL_READ_ONLY)
+            {
+                // we have to assume a read / write lock so we use the shadow buffer
+                // and tag for sync on unlock()
+                mShadowUpdated = true;
+            }
+
+            mCurrentLock = static_cast<HardwarePixelBuffer*>(mpShadowBuffer)->lock(lockBox, options);
+        }
+        else
+        {
+            // Lock the real buffer if there is no shadow buffer 
+            mCurrentLock = lockImpl(lockBox, options);
+            mIsLocked = true;
+        }
+
+        return mCurrentLock;
+    }
+    
+    //-----------------------------------------------------------------------------    
+    const PixelBox& HardwarePixelBuffer::getCurrentLock() 
+	{ 
+        assert(isLocked() && "Cannot get current lock: buffer not locked");
+        
+        return mCurrentLock; 
+    }
+    
+    //-----------------------------------------------------------------------------    
+    /// Internal implementation of lock()
+    void* HardwarePixelBuffer::lockImpl(size_t offset, size_t length, LockOptions options)
+    {
+        OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, "lockImpl(offset,length) is not valid for PixelBuffers and should never be called",
+            "HardwarePixelBuffer::lockImpl");
+    }
+
+    //-----------------------------------------------------------------------------    
+
+    void HardwarePixelBuffer::blit(const HardwarePixelBufferSharedPtr &src, const Box &srcBox, const Box &dstBox)
+	{
+		if(isLocked() || src->isLocked())
+		{
+			OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR,
+				"Source and destination buffer may not be locked!",
+				"HardwarePixelBuffer::blit");
+		}
+		if(src.getPointer() == this)
+		{
+			OGRE_EXCEPT( Exception::ERR_INVALIDPARAMS,
+                "Source must not be the same object",
+                "HardwarePixelBuffer::blit" ) ;
+		}
+		const PixelBox &srclock = src->lock(srcBox, HBL_READ_ONLY);
+
+		LockOptions method = HBL_NORMAL;
+		if(dstBox.left == 0 && dstBox.top == 0 && dstBox.front == 0 &&
+		   dstBox.right == mWidth && dstBox.bottom == mHeight &&
+		   dstBox.back == mDepth)
+			// Entire buffer -- we can discard the previous contents
+			method = HBL_DISCARD;
+			
+		const PixelBox &dstlock = lock(dstBox, method);
+		if(dstlock.getWidth() != srclock.getWidth() ||
+        	dstlock.getHeight() != srclock.getHeight() ||
+        	dstlock.getDepth() != srclock.getDepth())
+		{
+			// Scaling desired
+			PixelUtil::scale(srclock, dstlock);
+		}
+		else
+		{
+			// No scaling needed
+			PixelUtil::bulkPixelConversion(srclock, dstlock);
+		}
+
+		unlock();
+		src->unlock();
+	}
+    //-----------------------------------------------------------------------------       
+    void HardwarePixelBuffer::blit(const HardwarePixelBufferSharedPtr &src)
+    {
+        blit(src, 
+            Box(0,0,0,src->getWidth(),src->getHeight(),src->getDepth()), 
+            Box(0,0,0,mWidth,mHeight,mDepth)
+        );
+    }
+    //-----------------------------------------------------------------------------    
+	void HardwarePixelBuffer::readData(size_t offset, size_t length, void* pDest)
+	{
+		// TODO
+		OGRE_EXCEPT(Exception::ERR_NOT_IMPLEMENTED,
+				"Reading a byte range is not implemented. Use blitToMemory.",
+				"HardwarePixelBuffer::readData");
+	}
+	//-----------------------------------------------------------------------------    
+
+	void HardwarePixelBuffer::writeData(size_t offset, size_t length, const void* pSource,
+			bool discardWholeBuffer)
+	{
+		// TODO
+		OGRE_EXCEPT(Exception::ERR_NOT_IMPLEMENTED,
+				"Writing a byte range is not implemented. Use blitFromMemory.",
+				"HardwarePixelBuffer::writeData");
+	}
+    //-----------------------------------------------------------------------------    
+    
+    RenderTexture *HardwarePixelBuffer::getRenderTarget(size_t)
+    {
+        OGRE_EXCEPT(Exception::ERR_NOT_IMPLEMENTED,
+				"Not yet implemented for this rendersystem.",
+				"HardwarePixelBuffer::getRenderTarget");
+    }
+
+    //-----------------------------------------------------------------------------    
+    
+    HardwarePixelBufferSharedPtr::HardwarePixelBufferSharedPtr(HardwarePixelBuffer* buf)
+        : SharedPtr<HardwarePixelBuffer>(buf)
+    {
+
+    }   
+	//-----------------------------------------------------------------------------    
+
+	void HardwarePixelBuffer::_clearSliceRTT(size_t zoffset)
+	{
+	}
+
+}

+ 207 - 0
CamelotRenderer/OgreHardwarePixelBuffer.h

@@ -0,0 +1,207 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2011 Torus Knot Software Ltd
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+-----------------------------------------------------------------------------
+*/
+#ifndef __HardwarePixelBuffer__
+#define __HardwarePixelBuffer__
+
+// Precompiler options
+#include "OgrePrerequisites.h"
+#include "OgreHardwareBuffer.h"
+#include "OgreSharedPtr.h"
+#include "OgrePixelFormat.h"
+
+namespace Ogre {
+
+	/** \addtogroup Core
+	*  @{
+	*/
+	/** \addtogroup RenderSystem
+	*  @{
+	*/
+	/** Specialisation of HardwareBuffer for a pixel buffer. The
+    	HardwarePixelbuffer abstracts an 1D, 2D or 3D quantity of pixels
+    	stored by the rendering API. The buffer can be located on the card
+    	or in main memory depending on its usage. One mipmap level of a
+    	texture is an example of a HardwarePixelBuffer.
+    */
+    class _OgreExport HardwarePixelBuffer : public HardwareBuffer
+    {
+    protected: 
+        // Extents
+        size_t mWidth, mHeight, mDepth;
+        // Pitches (offsets between rows and slices)
+        size_t mRowPitch, mSlicePitch;
+        // Internal format
+        PixelFormat mFormat;
+        // Currently locked region (local coords)
+        PixelBox mCurrentLock;
+		// The current locked box of this surface (entire surface coords)
+		Box mLockedBox;
+
+        
+        /// Internal implementation of lock(), must be overridden in subclasses
+        virtual PixelBox lockImpl(const Box lockBox,  LockOptions options) = 0;
+
+        /// Internal implementation of lock(), do not OVERRIDE or CALL this
+        /// for HardwarePixelBuffer implementations, but override the previous method
+        virtual void* lockImpl(size_t offset, size_t length, LockOptions options);
+
+        /// Internal implementation of unlock(), must be overridden in subclasses
+        // virtual void unlockImpl(void) = 0;
+
+		/** Notify TextureBuffer of destruction of render target.
+			Called by RenderTexture when destroyed.
+		*/
+		virtual void _clearSliceRTT(size_t zoffset);
+		friend class RenderTexture;
+    public:
+        /// Should be called by HardwareBufferManager
+        HardwarePixelBuffer(size_t mWidth, size_t mHeight, size_t mDepth,
+                PixelFormat mFormat,
+                HardwareBuffer::Usage usage, bool useSystemMemory, bool useShadowBuffer);
+        ~HardwarePixelBuffer();
+
+        /** make every lock method from HardwareBuffer available.
+        See http://www.research.att.com/~bs/bs_faq2.html#overloadderived
+        */
+        using HardwareBuffer::lock;	
+
+        /** Lock the buffer for (potentially) reading / writing.
+		    @param lockBox Region of the buffer to lock
+		    @param options Locking options
+		    @returns PixelBox containing the locked region, the pitches and
+		    	the pixel format
+		*/
+		virtual const PixelBox& lock(const Box& lockBox, LockOptions options);
+		/// @copydoc HardwareBuffer::lock
+        virtual void* lock(size_t offset, size_t length, LockOptions options);
+
+		/** Get the current locked region. This is the same value as returned
+		    by lock(const Image::Box, LockOptions)
+		    @returns PixelBox containing the locked region
+		*/        
+        const PixelBox& getCurrentLock();
+		
+		/// @copydoc HardwareBuffer::readData
+		virtual void readData(size_t offset, size_t length, void* pDest);
+		/// @copydoc HardwareBuffer::writeData
+		virtual void writeData(size_t offset, size_t length, const void* pSource,
+				bool discardWholeBuffer = false);
+        
+        /** Copies a box from another PixelBuffer to a region of the 
+        	this PixelBuffer. 
+			@param dst		Source pixel buffer
+        	@param srcBox	Image::Box describing the source region in src
+        	@param dstBox	Image::Box describing the destination region in this buffer
+			@remarks The source and destination regions dimensions don't have to match, in which
+		   	case scaling is done. This scaling is generally done using a bilinear filter in hardware,
+            but it is faster to pass the source image in the right dimensions.
+			@note Only call this function when both  buffers are unlocked. 
+         */        
+        virtual void blit(const HardwarePixelBufferSharedPtr &src, const Box &srcBox, const Box &dstBox);
+
+		/** Convenience function that blits the entire source pixel buffer to this buffer. 
+			If source and destination dimensions don't match, scaling is done.
+			@param src		PixelBox containing the source pixels and format in memory
+			@note Only call this function when the buffer is unlocked. 
+		*/
+		void blit(const HardwarePixelBufferSharedPtr &src); 
+		
+		/** Copies a region from normal memory to a region of this pixelbuffer. The source
+			image can be in any pixel format supported by OGRE, and in any size. 
+		   	@param src		PixelBox containing the source pixels and format in memory
+		   	@param dstBox	Image::Box describing the destination region in this buffer
+            @remarks The source and destination regions dimensions don't have to match, in which
+            case scaling is done. This scaling is generally done using a bilinear filter in hardware,
+            but it is faster to pass the source image in the right dimensions.
+			@note Only call this function when the buffer is unlocked. 
+		*/
+		virtual void blitFromMemory(const PixelBox &src, const Box &dstBox) = 0;
+		
+		/** Convenience function that blits a pixelbox from memory to the entire 
+			buffer. The source image is scaled as needed.
+			@param src		PixelBox containing the source pixels and format in memory
+			@note Only call this function when the buffer is unlocked. 
+		*/
+		void blitFromMemory(const PixelBox &src)
+		{
+			blitFromMemory(src, Box(0,0,0,mWidth,mHeight,mDepth));
+		}
+		
+		/** Copies a region of this pixelbuffer to normal memory.
+		   	@param srcBox	Image::Box describing the source region of this buffer
+		   	@param dst		PixelBox describing the destination pixels and format in memory
+		   	@remarks The source and destination regions don't have to match, in which
+		   	case scaling is done.
+			@note Only call this function when the buffer is unlocked. 
+		 */
+		virtual void blitToMemory(const Box &srcBox, const PixelBox &dst) = 0;
+
+		/** Convience function that blits this entire buffer to a pixelbox.
+			The image is scaled as needed.
+			@param src		PixelBox containing the source pixels and format in memory
+			@note Only call this function when the buffer is unlocked. 
+		*/
+		void blitToMemory(const PixelBox &dst)
+		{
+			blitToMemory(Box(0,0,0,mWidth,mHeight,mDepth), dst);
+		}
+        
+        /** Get a render target for this PixelBuffer, or a slice of it. The texture this
+            was acquired from must have TU_RENDERTARGET set, otherwise it is possible to
+            render to it and this method will throw an ERR_RENDERSYSTEM exception.
+            @param slice    Which slice
+            @returns A pointer to the render target. This pointer has the lifespan of this
+            PixelBuffer.
+        */
+        virtual RenderTexture *getRenderTarget(size_t slice=0);
+        
+        /// Gets the width of this buffer
+        size_t getWidth() const { return mWidth; }
+        /// Gets the height of this buffer
+        size_t getHeight() const { return mHeight; }
+        /// Gets the depth of this buffer
+        size_t getDepth() const { return mDepth; }
+        /// Gets the native pixel format of this buffer
+        PixelFormat getFormat() const { return mFormat; }
+    };
+
+    /** Shared pointer implementation used to share pixel buffers. */
+    class _OgreExport HardwarePixelBufferSharedPtr : public SharedPtr<HardwarePixelBuffer>
+    {
+    public:
+        HardwarePixelBufferSharedPtr() : SharedPtr<HardwarePixelBuffer>() {}
+        explicit HardwarePixelBufferSharedPtr(HardwarePixelBuffer* buf);
+
+
+    };
+
+	/** @} */
+	/** @} */
+}
+#endif
+

+ 349 - 0
CamelotRenderer/OgreImageResampler.h

@@ -0,0 +1,349 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2011 Torus Knot Software Ltd
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+-----------------------------------------------------------------------------
+*/
+#ifndef OGREIMAGERESAMPLER_H
+#define OGREIMAGERESAMPLER_H
+
+#include <algorithm>
+
+// this file is inlined into OgreImage.cpp!
+// do not include anywhere else.
+namespace Ogre {
+	/** \addtogroup Core
+	*  @{
+	*/
+	/** \addtogroup Image
+	*  @{
+	*/
+
+// variable name hints:
+// sx_48 = 16/48-bit fixed-point x-position in source
+// stepx = difference between adjacent sx_48 values
+// sx1 = lower-bound integer x-position in source
+// sx2 = upper-bound integer x-position in source
+// sxf = fractional weight beween sx1 and sx2
+// x,y,z = location of output pixel in destination
+
+// nearest-neighbor resampler, does not convert formats.
+// templated on bytes-per-pixel to allow compiler optimizations, such
+// as simplifying memcpy() and replacing multiplies with bitshifts
+template<unsigned int elemsize> struct NearestResampler {
+	static void scale(const PixelBox& src, const PixelBox& dst) {
+		// assert(src.format == dst.format);
+
+		// srcdata stays at beginning, pdst is a moving pointer
+		uchar* srcdata = (uchar*)src.data;
+		uchar* pdst = (uchar*)dst.data;
+
+		// sx_48,sy_48,sz_48 represent current position in source
+		// using 16/48-bit fixed precision, incremented by steps
+		uint64 stepx = ((uint64)src.getWidth() << 48) / dst.getWidth();
+		uint64 stepy = ((uint64)src.getHeight() << 48) / dst.getHeight();
+		uint64 stepz = ((uint64)src.getDepth() << 48) / dst.getDepth();
+
+		// note: ((stepz>>1) - 1) is an extra half-step increment to adjust
+		// for the center of the destination pixel, not the top-left corner
+		uint64 sz_48 = (stepz >> 1) - 1;
+		for (size_t z = dst.front; z < dst.back; z++, sz_48 += stepz) {
+			size_t srczoff = (size_t)(sz_48 >> 48) * src.slicePitch;
+			
+			uint64 sy_48 = (stepy >> 1) - 1;
+			for (size_t y = dst.top; y < dst.bottom; y++, sy_48 += stepy) {
+				size_t srcyoff = (size_t)(sy_48 >> 48) * src.rowPitch;
+			
+				uint64 sx_48 = (stepx >> 1) - 1;
+				for (size_t x = dst.left; x < dst.right; x++, sx_48 += stepx) {
+					uchar* psrc = srcdata +
+						elemsize*((size_t)(sx_48 >> 48) + srcyoff + srczoff);
+                    memcpy(pdst, psrc, elemsize);
+					pdst += elemsize;
+				}
+				pdst += elemsize*dst.getRowSkip();
+			}
+			pdst += elemsize*dst.getSliceSkip();
+		}
+	}
+};
+
+
+// default floating-point linear resampler, does format conversion
+struct LinearResampler {
+	static void scale(const PixelBox& src, const PixelBox& dst) {
+		size_t srcelemsize = PixelUtil::getNumElemBytes(src.format);
+		size_t dstelemsize = PixelUtil::getNumElemBytes(dst.format);
+
+		// srcdata stays at beginning, pdst is a moving pointer
+		uchar* srcdata = (uchar*)src.data;
+		uchar* pdst = (uchar*)dst.data;
+		
+		// sx_48,sy_48,sz_48 represent current position in source
+		// using 16/48-bit fixed precision, incremented by steps
+		uint64 stepx = ((uint64)src.getWidth() << 48) / dst.getWidth();
+		uint64 stepy = ((uint64)src.getHeight() << 48) / dst.getHeight();
+		uint64 stepz = ((uint64)src.getDepth() << 48) / dst.getDepth();
+		
+		// temp is 16/16 bit fixed precision, used to adjust a source
+		// coordinate (x, y, or z) backwards by half a pixel so that the
+		// integer bits represent the first sample (eg, sx1) and the
+		// fractional bits are the blend weight of the second sample
+		unsigned int temp;
+
+		// note: ((stepz>>1) - 1) is an extra half-step increment to adjust
+		// for the center of the destination pixel, not the top-left corner
+		uint64 sz_48 = (stepz >> 1) - 1;
+		for (size_t z = dst.front; z < dst.back; z++, sz_48+=stepz) {
+			temp = static_cast<unsigned int>(sz_48 >> 32);
+			temp = (temp > 0x8000)? temp - 0x8000 : 0;
+			size_t sz1 = temp >> 16;				 // src z, sample #1
+			size_t sz2 = std::min(sz1+1,src.getDepth()-1);// src z, sample #2
+			float szf = (temp & 0xFFFF) / 65536.f; // weight of sample #2
+
+			uint64 sy_48 = (stepy >> 1) - 1;
+			for (size_t y = dst.top; y < dst.bottom; y++, sy_48+=stepy) {
+				temp = static_cast<unsigned int>(sy_48 >> 32);
+				temp = (temp > 0x8000)? temp - 0x8000 : 0;
+				size_t sy1 = temp >> 16;					// src y #1
+				size_t sy2 = std::min(sy1+1,src.getHeight()-1);// src y #2
+				float syf = (temp & 0xFFFF) / 65536.f; // weight of #2
+				
+				uint64 sx_48 = (stepx >> 1) - 1;
+				for (size_t x = dst.left; x < dst.right; x++, sx_48+=stepx) {
+					temp = static_cast<unsigned int>(sx_48 >> 32);
+					temp = (temp > 0x8000)? temp - 0x8000 : 0;
+					size_t sx1 = temp >> 16;					// src x #1
+					size_t sx2 = std::min(sx1+1,src.getWidth()-1);// src x #2
+					float sxf = (temp & 0xFFFF) / 65536.f; // weight of #2
+				
+					ColourValue x1y1z1, x2y1z1, x1y2z1, x2y2z1;
+					ColourValue x1y1z2, x2y1z2, x1y2z2, x2y2z2;
+
+#define UNPACK(dst,x,y,z) PixelUtil::unpackColour(&dst, src.format, \
+	srcdata + srcelemsize*((x)+(y)*src.rowPitch+(z)*src.slicePitch))
+
+					UNPACK(x1y1z1,sx1,sy1,sz1); UNPACK(x2y1z1,sx2,sy1,sz1);
+					UNPACK(x1y2z1,sx1,sy2,sz1); UNPACK(x2y2z1,sx2,sy2,sz1);
+					UNPACK(x1y1z2,sx1,sy1,sz2); UNPACK(x2y1z2,sx2,sy1,sz2);
+					UNPACK(x1y2z2,sx1,sy2,sz2); UNPACK(x2y2z2,sx2,sy2,sz2);
+#undef UNPACK
+
+					ColourValue accum =
+						x1y1z1 * ((1.0f - sxf)*(1.0f - syf)*(1.0f - szf)) +
+						x2y1z1 * (        sxf *(1.0f - syf)*(1.0f - szf)) +
+						x1y2z1 * ((1.0f - sxf)*        syf *(1.0f - szf)) +
+						x2y2z1 * (        sxf *        syf *(1.0f - szf)) +
+						x1y1z2 * ((1.0f - sxf)*(1.0f - syf)*        szf ) +
+						x2y1z2 * (        sxf *(1.0f - syf)*        szf ) +
+						x1y2z2 * ((1.0f - sxf)*        syf *        szf ) +
+						x2y2z2 * (        sxf *        syf *        szf );
+
+					PixelUtil::packColour(accum, dst.format, pdst);
+
+					pdst += dstelemsize;
+				}
+				pdst += dstelemsize*dst.getRowSkip();
+			}
+			pdst += dstelemsize*dst.getSliceSkip();
+		}
+	}
+};
+
+
+// float32 linear resampler, converts FLOAT32_RGB/FLOAT32_RGBA only.
+// avoids overhead of pixel unpack/repack function calls
+struct LinearResampler_Float32 {
+	static void scale(const PixelBox& src, const PixelBox& dst) {
+		size_t srcchannels = PixelUtil::getNumElemBytes(src.format) / sizeof(float);
+		size_t dstchannels = PixelUtil::getNumElemBytes(dst.format) / sizeof(float);
+		// assert(srcchannels == 3 || srcchannels == 4);
+		// assert(dstchannels == 3 || dstchannels == 4);
+
+		// srcdata stays at beginning, pdst is a moving pointer
+		float* srcdata = (float*)src.data;
+		float* pdst = (float*)dst.data;
+		
+		// sx_48,sy_48,sz_48 represent current position in source
+		// using 16/48-bit fixed precision, incremented by steps
+		uint64 stepx = ((uint64)src.getWidth() << 48) / dst.getWidth();
+		uint64 stepy = ((uint64)src.getHeight() << 48) / dst.getHeight();
+		uint64 stepz = ((uint64)src.getDepth() << 48) / dst.getDepth();
+		
+		// temp is 16/16 bit fixed precision, used to adjust a source
+		// coordinate (x, y, or z) backwards by half a pixel so that the
+		// integer bits represent the first sample (eg, sx1) and the
+		// fractional bits are the blend weight of the second sample
+		unsigned int temp;
+
+		// note: ((stepz>>1) - 1) is an extra half-step increment to adjust
+		// for the center of the destination pixel, not the top-left corner
+		uint64 sz_48 = (stepz >> 1) - 1;
+		for (size_t z = dst.front; z < dst.back; z++, sz_48+=stepz) {
+			temp = static_cast<unsigned int>(sz_48 >> 32);
+			temp = (temp > 0x8000)? temp - 0x8000 : 0;
+			size_t sz1 = temp >> 16;				 // src z, sample #1
+			size_t sz2 = std::min(sz1+1,src.getDepth()-1);// src z, sample #2
+			float szf = (temp & 0xFFFF) / 65536.f; // weight of sample #2
+
+			uint64 sy_48 = (stepy >> 1) - 1;
+			for (size_t y = dst.top; y < dst.bottom; y++, sy_48+=stepy) {
+				temp = static_cast<unsigned int>(sy_48 >> 32);
+				temp = (temp > 0x8000)? temp - 0x8000 : 0;
+				size_t sy1 = temp >> 16;					// src y #1
+				size_t sy2 = std::min(sy1+1,src.getHeight()-1);// src y #2
+				float syf = (temp & 0xFFFF) / 65536.f; // weight of #2
+				
+				uint64 sx_48 = (stepx >> 1) - 1;
+				for (size_t x = dst.left; x < dst.right; x++, sx_48+=stepx) {
+					temp = static_cast<unsigned int>(sx_48 >> 32);
+					temp = (temp > 0x8000)? temp - 0x8000 : 0;
+					size_t sx1 = temp >> 16;					// src x #1
+					size_t sx2 = std::min(sx1+1,src.getWidth()-1);// src x #2
+					float sxf = (temp & 0xFFFF) / 65536.f; // weight of #2
+					
+					// process R,G,B,A simultaneously for cache coherence?
+					float accum[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
+
+#define ACCUM3(x,y,z,factor) \
+	{ float f = factor; \
+	size_t off = (x+y*src.rowPitch+z*src.slicePitch)*srcchannels; \
+    accum[0]+=srcdata[off+0]*f; accum[1]+=srcdata[off+1]*f; \
+	accum[2]+=srcdata[off+2]*f; }
+
+#define ACCUM4(x,y,z,factor) \
+	{ float f = factor; \
+	size_t off = (x+y*src.rowPitch+z*src.slicePitch)*srcchannels; \
+    accum[0]+=srcdata[off+0]*f; accum[1]+=srcdata[off+1]*f; \
+	accum[2]+=srcdata[off+2]*f; accum[3]+=srcdata[off+3]*f; }
+
+					if (srcchannels == 3 || dstchannels == 3) {
+						// RGB, no alpha
+						ACCUM3(sx1,sy1,sz1,(1.0f-sxf)*(1.0f-syf)*(1.0f-szf));
+						ACCUM3(sx2,sy1,sz1,      sxf *(1.0f-syf)*(1.0f-szf));
+						ACCUM3(sx1,sy2,sz1,(1.0f-sxf)*      syf *(1.0f-szf));
+						ACCUM3(sx2,sy2,sz1,      sxf *      syf *(1.0f-szf));
+						ACCUM3(sx1,sy1,sz2,(1.0f-sxf)*(1.0f-syf)*      szf );
+						ACCUM3(sx2,sy1,sz2,      sxf *(1.0f-syf)*      szf );
+						ACCUM3(sx1,sy2,sz2,(1.0f-sxf)*      syf *      szf );
+						ACCUM3(sx2,sy2,sz2,      sxf *      syf *      szf );
+						accum[3] = 1.0f;
+					} else {
+						// RGBA
+						ACCUM4(sx1,sy1,sz1,(1.0f-sxf)*(1.0f-syf)*(1.0f-szf));
+						ACCUM4(sx2,sy1,sz1,      sxf *(1.0f-syf)*(1.0f-szf));
+						ACCUM4(sx1,sy2,sz1,(1.0f-sxf)*      syf *(1.0f-szf));
+						ACCUM4(sx2,sy2,sz1,      sxf *      syf *(1.0f-szf));
+						ACCUM4(sx1,sy1,sz2,(1.0f-sxf)*(1.0f-syf)*      szf );
+						ACCUM4(sx2,sy1,sz2,      sxf *(1.0f-syf)*      szf );
+						ACCUM4(sx1,sy2,sz2,(1.0f-sxf)*      syf *      szf );
+						ACCUM4(sx2,sy2,sz2,      sxf *      syf *      szf );
+					}
+
+					memcpy(pdst, accum, sizeof(float)*dstchannels);
+
+#undef ACCUM3
+#undef ACCUM4
+
+					pdst += dstchannels;
+				}
+				pdst += dstchannels*dst.getRowSkip();
+			}
+			pdst += dstchannels*dst.getSliceSkip();
+		}
+	}
+};
+
+
+
+// byte linear resampler, does not do any format conversions.
+// only handles pixel formats that use 1 byte per color channel.
+// 2D only; punts 3D pixelboxes to default LinearResampler (slow).
+// templated on bytes-per-pixel to allow compiler optimizations, such
+// as unrolling loops and replacing multiplies with bitshifts
+template<unsigned int channels> struct LinearResampler_Byte {
+	static void scale(const PixelBox& src, const PixelBox& dst) {
+		// assert(src.format == dst.format);
+
+		// only optimized for 2D
+		if (src.getDepth() > 1 || dst.getDepth() > 1) {
+			LinearResampler::scale(src, dst);
+			return;
+		}
+
+		// srcdata stays at beginning of slice, pdst is a moving pointer
+		uchar* srcdata = (uchar*)src.data;
+		uchar* pdst = (uchar*)dst.data;
+
+		// sx_48,sy_48 represent current position in source
+		// using 16/48-bit fixed precision, incremented by steps
+		uint64 stepx = ((uint64)src.getWidth() << 48) / dst.getWidth();
+		uint64 stepy = ((uint64)src.getHeight() << 48) / dst.getHeight();
+		
+		// bottom 28 bits of temp are 16/12 bit fixed precision, used to
+		// adjust a source coordinate backwards by half a pixel so that the
+		// integer bits represent the first sample (eg, sx1) and the
+		// fractional bits are the blend weight of the second sample
+		unsigned int temp;
+		
+		uint64 sy_48 = (stepy >> 1) - 1;
+		for (size_t y = dst.top; y < dst.bottom; y++, sy_48+=stepy) {
+			temp = static_cast<unsigned int>(sy_48 >> 36);
+			temp = (temp > 0x800)? temp - 0x800: 0;
+			unsigned int syf = temp & 0xFFF;
+			size_t sy1 = temp >> 12;
+			size_t sy2 = std::min(sy1+1, src.bottom-src.top-1);
+			size_t syoff1 = sy1 * src.rowPitch;
+			size_t syoff2 = sy2 * src.rowPitch;
+
+			uint64 sx_48 = (stepx >> 1) - 1;
+			for (size_t x = dst.left; x < dst.right; x++, sx_48+=stepx) {
+				temp = static_cast<unsigned int>(sx_48 >> 36);
+				temp = (temp > 0x800)? temp - 0x800 : 0;
+				unsigned int sxf = temp & 0xFFF;
+				size_t sx1 = temp >> 12;
+				size_t sx2 = std::min(sx1+1, src.right-src.left-1);
+
+				unsigned int sxfsyf = sxf*syf;
+				for (unsigned int k = 0; k < channels; k++) {
+					unsigned int accum =
+						srcdata[(sx1 + syoff1)*channels+k]*(0x1000000-(sxf<<12)-(syf<<12)+sxfsyf) +
+						srcdata[(sx2 + syoff1)*channels+k]*((sxf<<12)-sxfsyf) +
+						srcdata[(sx1 + syoff2)*channels+k]*((syf<<12)-sxfsyf) +
+						srcdata[(sx2 + syoff2)*channels+k]*sxfsyf;
+					// accum is computed using 8/24-bit fixed-point math
+					// (maximum is 0xFF000000; rounding will not cause overflow)
+					*pdst++ = static_cast<uchar>((accum + 0x800000) >> 24);
+				}
+			}
+			pdst += channels*dst.getRowSkip();
+		}
+	}
+};
+/** @} */
+/** @} */
+
+}
+
+#endif

+ 101 - 0
CamelotRenderer/OgrePixelFormat.cpp

@@ -29,6 +29,7 @@ THE SOFTWARE.
 #include "OgrePixelFormat.h"
 #include "OgreBitwise.h"
 #include "OgreColourValue.h"
+#include "OgreImageResampler.h"
 #include "OgreException.h"
 
 
@@ -1362,6 +1363,106 @@ namespace Ogre {
         }
     }
 
+	void PixelUtil::scale(const PixelBox &src, const PixelBox &scaled, Filter filter)
+	{
+		assert(PixelUtil::isAccessible(src.format));
+		assert(PixelUtil::isAccessible(scaled.format));
+
+		PixelBox temp;
+		switch (filter) 
+		{
+		default:
+		case FILTER_NEAREST:
+			if(src.format == scaled.format) 
+			{
+				// No intermediate buffer needed
+				temp = scaled;
+			}
+			else
+			{
+				// Allocate temporary buffer of destination size in source format 
+				temp = PixelBox(scaled.getWidth(), scaled.getHeight(), scaled.getDepth(), src.format);
+				temp.data = OGRE_MALLOC(temp.getConsecutiveSize(), 0);
+			}
+			// super-optimized: no conversion
+			switch (PixelUtil::getNumElemBytes(src.format)) 
+			{
+			case 1: NearestResampler<1>::scale(src, temp); break;
+			case 2: NearestResampler<2>::scale(src, temp); break;
+			case 3: NearestResampler<3>::scale(src, temp); break;
+			case 4: NearestResampler<4>::scale(src, temp); break;
+			case 6: NearestResampler<6>::scale(src, temp); break;
+			case 8: NearestResampler<8>::scale(src, temp); break;
+			case 12: NearestResampler<12>::scale(src, temp); break;
+			case 16: NearestResampler<16>::scale(src, temp); break;
+			default:
+				// never reached
+				assert(false);
+			}
+			if(temp.data != scaled.data)
+			{
+				// Blit temp buffer
+				PixelUtil::bulkPixelConversion(temp, scaled);
+
+				OGRE_FREE(temp.data, 0);
+			}
+			break;
+
+		case FILTER_LINEAR:
+		case FILTER_BILINEAR:
+			switch (src.format) 
+			{
+			case PF_L8: case PF_A8: case PF_BYTE_LA:
+			case PF_R8G8B8: case PF_B8G8R8:
+			case PF_R8G8B8A8: case PF_B8G8R8A8:
+			case PF_A8B8G8R8: case PF_A8R8G8B8:
+			case PF_X8B8G8R8: case PF_X8R8G8B8:
+				if(src.format == scaled.format) 
+				{
+					// No intermediate buffer needed
+					temp = scaled;
+				}
+				else
+				{
+					// Allocate temp buffer of destination size in source format 
+					temp = PixelBox(scaled.getWidth(), scaled.getHeight(), scaled.getDepth(), src.format);
+					temp.data = OGRE_MALLOC(temp.getConsecutiveSize(), 0);
+				}
+				// super-optimized: byte-oriented math, no conversion
+				switch (PixelUtil::getNumElemBytes(src.format)) 
+				{
+				case 1: LinearResampler_Byte<1>::scale(src, temp); break;
+				case 2: LinearResampler_Byte<2>::scale(src, temp); break;
+				case 3: LinearResampler_Byte<3>::scale(src, temp); break;
+				case 4: LinearResampler_Byte<4>::scale(src, temp); break;
+				default:
+					// never reached
+					assert(false);
+				}
+				if(temp.data != scaled.data)
+				{
+					// Blit temp buffer
+					PixelUtil::bulkPixelConversion(temp, scaled);
+					OGRE_FREE(temp.data, 0);
+				}
+				break;
+			case PF_FLOAT32_RGB:
+			case PF_FLOAT32_RGBA:
+				if (scaled.format == PF_FLOAT32_RGB || scaled.format == PF_FLOAT32_RGBA)
+				{
+					// float32 to float32, avoid unpack/repack overhead
+					LinearResampler_Float32::scale(src, scaled);
+					break;
+				}
+				// else, fall through
+			default:
+				// non-optimized: floating-point math, performs conversion but always works
+				LinearResampler::scale(src, scaled);
+			}
+			break;
+		}
+	}
+
     ColourValue PixelBox::getColourAt(size_t x, size_t y, size_t z)
     {
         ColourValue cv;

+ 19 - 0
CamelotRenderer/OgrePixelFormat.h

@@ -500,6 +500,25 @@ namespace Ogre {
          	dimensions. In case the source and destination format match, a plain copy is done.
         */
         static void bulkPixelConversion(const PixelBox &src, const PixelBox &dst);
+
+		enum Filter
+		{
+			FILTER_NEAREST,
+			FILTER_LINEAR,
+			FILTER_BILINEAR,
+			FILTER_BOX,
+			FILTER_TRIANGLE,
+			FILTER_BICUBIC
+		};
+
+		/** Scale a 1D, 2D or 3D image volume. 
+			@param 	src			PixelBox containing the source pointer, dimensions and format
+			@param 	dst			PixelBox containing the destination pointer, dimensions and format
+			@param 	filter		Which filter to use
+			@remarks 	This function can do pixel format conversion in the process.
+			@note	dst and src can point to the same PixelBox object without any problem
+		*/
+		static void scale(const PixelBox &src, const PixelBox &dst, Filter filter = FILTER_BILINEAR);
     };
 	/** @} */
 	/** @} */

+ 83 - 0
CamelotRenderer/OgreRenderTexture.cpp

@@ -0,0 +1,83 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+(Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2011 Torus Knot Software Ltd
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+-----------------------------------------------------------------------------
+*/
+
+#include "OgreRenderTexture.h"
+#include "OgreException.h"
+#include "OgreHardwarePixelBuffer.h"
+
+namespace Ogre
+{
+
+    //-----------------------------------------------------------------------------
+	RenderTexture::RenderTexture(HardwarePixelBuffer *buffer, size_t zoffset):
+		mBuffer(buffer), mZOffset(zoffset)
+    {
+        mPriority = OGRE_REND_TO_TEX_RT_GROUP;
+		mWidth = static_cast<unsigned int>(mBuffer->getWidth());
+		mHeight = static_cast<unsigned int>(mBuffer->getHeight());
+        mColourDepth = static_cast<unsigned int>(
+			Ogre::PixelUtil::getNumElemBits(mBuffer->getFormat()));
+    }
+    RenderTexture::~RenderTexture()
+    {
+		mBuffer->_clearSliceRTT(0);
+    }
+
+	void RenderTexture::copyContentsToMemory(const PixelBox &dst, FrameBuffer buffer)
+    {
+		if (buffer == FB_AUTO) buffer = FB_FRONT;
+		if (buffer != FB_FRONT)
+		{
+			OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
+						"Invalid buffer.",
+						"RenderTexture::copyContentsToMemory" );
+		}
+
+		mBuffer->blitToMemory(dst);
+	}
+	//---------------------------------------------------------------------
+	PixelFormat RenderTexture::suggestPixelFormat() const
+	{
+		return mBuffer->getFormat();
+	}
+	//-----------------------------------------------------------------------------
+	MultiRenderTarget::MultiRenderTarget(const String &name)
+    {
+        mPriority = OGRE_REND_TO_TEX_RT_GROUP;
+		mName = name;
+		/// Width and height is unknown with no targets attached
+		mWidth = mHeight = 0;
+    }
+	//-----------------------------------------------------------------------------
+	void MultiRenderTarget::copyContentsToMemory(const PixelBox &dst, FrameBuffer buffer)
+	{
+		OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, 
+					"Cannot get MultiRenderTargets pixels",
+					"MultiRenderTarget::copyContentsToMemory");
+	}
+}

+ 140 - 0
CamelotRenderer/OgreRenderTexture.h

@@ -0,0 +1,140 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+(Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2011 Torus Knot Software Ltd
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+-----------------------------------------------------------------------------
+*/
+#ifndef __RenderTexture_H__
+#define __RenderTexture_H__
+
+#include "OgrePrerequisites.h"
+
+#include "OgreRenderTarget.h"
+
+namespace Ogre
+{    
+	/** \addtogroup Core
+	*  @{
+	*/
+	/** \addtogroup RenderSystem
+	*  @{
+	*/
+	/** This class represents a RenderTarget that renders to a Texture. There is no 1 on 1
+        relation between Textures and RenderTextures, as there can be multiple 
+        RenderTargets rendering to different mipmaps, faces (for cubemaps) or slices (for 3D textures)
+        of the same Texture.
+    */
+    class _OgreExport RenderTexture: public RenderTarget
+    {
+    public:
+        RenderTexture(HardwarePixelBuffer *buffer, size_t zoffset);
+        virtual ~RenderTexture();
+
+		virtual void copyContentsToMemory(const PixelBox &dst, FrameBuffer buffer);
+		PixelFormat suggestPixelFormat() const;
+
+	protected:
+		HardwarePixelBuffer *mBuffer;
+		size_t mZOffset;
+    };
+
+	/** This class represents a render target that renders to multiple RenderTextures
+		at once. Surfaces can be bound and unbound at will, as long as the following constraints
+		are met:
+		- All bound surfaces have the same size
+		- All bound surfaces have the same bit depth
+		- Target 0 is bound
+	*/
+	class _OgreExport MultiRenderTarget: public RenderTarget
+	{
+	public:
+		MultiRenderTarget(const String &name);
+
+		/** Bind a surface to a certain attachment point.
+            @param attachment	0 .. mCapabilities->getNumMultiRenderTargets()-1
+			@param target		RenderTexture to bind.
+
+			It does not bind the surface and fails with an exception (ERR_INVALIDPARAMS) if:
+			- Not all bound surfaces have the same size
+			- Not all bound surfaces have the same internal format 
+		*/
+
+		virtual void bindSurface(size_t attachment, RenderTexture *target)
+		{
+			for (size_t i = mBoundSurfaces.size(); i <= attachment; ++i)
+			{
+				mBoundSurfaces.push_back(0);
+			}
+			mBoundSurfaces[attachment] = target;
+
+			bindSurfaceImpl(attachment, target);
+		}
+
+
+
+		/** Unbind attachment.
+		*/
+
+		virtual void unbindSurface(size_t attachment)
+		{
+			if (attachment < mBoundSurfaces.size())
+				mBoundSurfaces[attachment] = 0;
+			unbindSurfaceImpl(attachment);
+		}
+
+		/** Error throwing implementation, it's not possible to write a MultiRenderTarget
+			to disk. 
+		*/
+		virtual void copyContentsToMemory(const PixelBox &dst, FrameBuffer buffer);
+
+		/// Irrelevant implementation since cannot copy
+		PixelFormat suggestPixelFormat() const { return PF_UNKNOWN; }
+
+		typedef vector<RenderTexture*>::type BoundSufaceList;
+		/// Get a list of the surfaces which have been bound
+		const BoundSufaceList& getBoundSurfaceList() const { return mBoundSurfaces; }
+
+		/** Get a pointer to a bound surface */
+		RenderTexture* getBoundSurface(size_t index)
+		{
+			assert (index < mBoundSurfaces.size());
+			return mBoundSurfaces[index];
+		}
+
+
+	protected:
+		BoundSufaceList mBoundSurfaces;
+
+		/// implementation of bindSurface, must be provided
+		virtual void bindSurfaceImpl(size_t attachment, RenderTexture *target) = 0;
+		/// implementation of unbindSurface, must be provided
+		virtual void unbindSurfaceImpl(size_t attachment) = 0;
+
+
+	};
+	/** @} */
+	/** @} */
+}
+
+#endif

+ 70 - 0
CamelotRenderer/OgreRenderWindow.cpp

@@ -0,0 +1,70 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2011 Torus Knot Software Ltd
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+-----------------------------------------------------------------------------
+*/
+#include "OgreRenderWindow.h"
+
+#include "OgreViewport.h"
+
+namespace Ogre {
+
+    RenderWindow::RenderWindow()
+        : RenderTarget(), mIsPrimary(false)
+    {
+        mAutoDeactivatedOnFocusChange = true;
+    }
+
+    //-----------------------------------------------------------------------
+    void RenderWindow::getMetrics(unsigned int& width, unsigned int& height, unsigned int& colourDepth,
+		int& left, int& top)
+    {
+        width = mWidth;
+        height = mHeight;
+        colourDepth = mColourDepth;
+        left = mLeft;
+        top = mTop;
+    }
+    //-----------------------------------------------------------------------
+    bool RenderWindow::isFullScreen(void) const
+    {
+        return mIsFullScreen;
+    }
+	//-----------------------------------------------------------------------
+    bool RenderWindow::isPrimary(void) const
+    {
+        return mIsPrimary;
+    }
+
+    bool RenderWindow::isDeactivatedOnFocusChange() const
+    {
+        return mAutoDeactivatedOnFocusChange;
+    }
+
+    void RenderWindow::setDeactivateOnFocusChange(bool deactivate)
+    {
+        mAutoDeactivatedOnFocusChange = deactivate;
+    }
+}

+ 190 - 0
CamelotRenderer/OgreRenderWindow.h

@@ -0,0 +1,190 @@
+/*-------------------------------------------------------------------------
+This source file is a part of OGRE
+(Object-oriented Graphics Rendering Engine)
+
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2011 Torus Knot Software Ltd
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE
+-------------------------------------------------------------------------*/
+#ifndef __RenderWindow_H__
+#define __RenderWindow_H__
+
+#include "OgrePrerequisites.h"
+
+#include "OgreRenderTarget.h"
+
+namespace Ogre
+{
+	/** \addtogroup Core
+	*  @{
+	*/
+	/** \addtogroup RenderSystem
+	*  @{
+	*/
+	/** Manages the target rendering window.
+        @remarks
+            This class handles a window into which the contents
+            of a scene are rendered. There is a many-to-1 relationship
+            between instances of this class an instance of RenderSystem
+            which controls the rendering of the scene. There may be
+            more than one window in the case of level editor tools etc.
+            This class is abstract since there may be
+            different implementations for different windowing systems.
+        @remarks
+            Instances are created and communicated with by the render system
+            although client programs can get a reference to it from
+            the render system if required for resizing or moving.
+            Note that you can have multiple viewpoints
+            in the window for effects like rear-view mirrors and
+            picture-in-picture views (see Viewport and Camera).
+        @author
+            Steven Streeting
+        @version
+            1.0
+    */
+    class _OgreExport RenderWindow : public RenderTarget
+    {
+
+    public:
+        /** Default constructor.
+        */
+        RenderWindow();
+
+        /** Creates & displays the new window.
+            @param
+                width The width of the window in pixels.
+            @param
+                height The height of the window in pixels.
+            @param
+                colourDepth The colour depth in bits. Ignored if
+                fullScreen is false since the desktop depth is used.
+            @param
+                fullScreen If true, the window fills the screen,
+                with no title bar or border.
+            @param
+                left The x-position of the window. Ignored if
+                fullScreen = true.
+            @param
+                top The y-position of the window. Ignored if
+                fullScreen = true.
+            @param
+                depthBuffer Specify true to include a depth-buffer.
+            @param
+                miscParam A variable number of pointers to platform-specific arguments. The
+                actual requirements must be defined by the implementing subclasses.
+        */
+		virtual void create(const String& name, unsigned int width, unsigned int height,
+	            bool fullScreen, const NameValuePairList *miscParams) = 0;
+
+		/** Alter fullscreen mode options. 
+		@note Nothing will happen unless the settings here are different from the
+			current settings.
+		@param fullScreen Whether to use fullscreen mode or not. 
+		@param width The new width to use
+		@param height The new height to use
+		*/
+		virtual void setFullscreen(bool fullScreen, unsigned int width, unsigned int height)
+                { (void)fullScreen; (void)width; (void)height; }
+        
+        /** Destroys the window.
+        */
+        virtual void destroy(void) = 0;
+
+        /** Alter the size of the window.
+        */
+        virtual void resize(unsigned int width, unsigned int height) = 0;
+
+        /** Notify that the window has been resized
+        @remarks
+            You don't need to call this unless you created the window externally.
+        */
+        virtual void windowMovedOrResized() {}
+
+        /** Reposition the window.
+        */
+        virtual void reposition(int left, int top) = 0;
+
+        /** Indicates whether the window is visible (not minimized or obscured)
+        */
+        virtual bool isVisible(void) const { return true; }
+
+        /** Set the visibility state
+        */
+        virtual void setVisible(bool visible)
+        { (void)visible; }
+
+        /** Overridden from RenderTarget, flags invisible windows as inactive
+        */
+        virtual bool isActive(void) const { return mActive && isVisible(); }
+
+        /** Indicates whether the window has been closed by the user.
+        */
+        virtual bool isClosed(void) const = 0;
+        
+        /** Indicates whether the window is the primary window. The
+        	primary window is special in that it is destroyed when 
+        	ogre is shut down, and cannot be destroyed directly.
+        	This is the case because it holds the context for vertex,
+        	index buffers and textures.
+        */
+        virtual bool isPrimary(void) const;
+
+        /** Returns true if window is running in fullscreen mode.
+        */
+        virtual bool isFullScreen(void) const;
+
+        /** Overloaded version of getMetrics from RenderTarget, including extra details
+            specific to windowing systems.
+        */
+        virtual void getMetrics(unsigned int& width, unsigned int& height, unsigned int& colourDepth, 
+			int& left, int& top);
+
+		/// Override since windows don't usually have alpha
+		PixelFormat suggestPixelFormat() const { return PF_BYTE_RGB; }
+
+        /** Returns true if the window will automatically de-activate itself when it loses focus.
+        */
+        bool isDeactivatedOnFocusChange() const;
+
+        /** Indicates whether the window will automatically deactivate itself when it loses focus.
+          * \param deactivate a value of 'true' will cause the window to deactivate itself when it loses focus.  'false' will allow it to continue to render even when window focus is lost.
+          * \note 'true' is the default behavior.
+          */
+        void setDeactivateOnFocusChange(bool deactivate);
+
+    protected:
+        bool mIsFullScreen;
+        bool mIsPrimary;
+        bool mAutoDeactivatedOnFocusChange;
+        int mLeft;
+        int mTop;
+        
+        /** Indicates that this is the primary window. Only to be called by
+            Ogre::Root
+        */
+        void _setPrimary() { mIsPrimary = true; }
+        
+        friend class Root;
+    };
+	/** @} */
+	/** @} */
+
+} // Namespace
+#endif