|
|
@@ -33,790 +33,756 @@ THE SOFTWARE.
|
|
|
#include "CmBitwise.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;
|
|
|
- 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();
|
|
|
- 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
|
|
|
{
|
|
|
- // 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.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);
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- glCompressedTexSubImage2DARB(mFaceTarget, mLevel,
|
|
|
+ break;
|
|
|
+ case GL_TEXTURE_2D:
|
|
|
+ case GL_TEXTURE_CUBE_MAP:
|
|
|
+ glTexSubImage2D(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)
|
|
|
- {
|
|
|
- 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);
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- glCompressedTexSubImage3DARB(GL_TEXTURE_3D, mLevel,
|
|
|
+ break;
|
|
|
+ case GL_TEXTURE_3D:
|
|
|
+ glTexSubImage3D(
|
|
|
+ GL_TEXTURE_3D, mLevel,
|
|
|
dest.left, dest.top, dest.front,
|
|
|
dest.getWidth(), dest.getHeight(), dest.getDepth(),
|
|
|
- format, data.getConsecutiveSize(),
|
|
|
+ GLPixelUtil::getGLOriginFormat(data.format), GLPixelUtil::getGLOriginDataType(data.format),
|
|
|
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),
|
|
|
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:
|
|
|
- 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:
|
|
|
- /* 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;
|
|
|
}
|
|
|
- }
|
|
|
- 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);
|
|
|
-}
|
|
|
-
|
|
|
};
|