|
@@ -9,24 +9,22 @@
|
|
|
namespace BansheeEngine
|
|
namespace BansheeEngine
|
|
|
{
|
|
{
|
|
|
GLPixelBuffer::GLPixelBuffer(UINT32 inWidth, UINT32 inHeight, UINT32 inDepth,
|
|
GLPixelBuffer::GLPixelBuffer(UINT32 inWidth, UINT32 inHeight, UINT32 inDepth,
|
|
|
- PixelFormat inFormat, GpuBufferUsage usage):
|
|
|
|
|
- PixelBuffer(inWidth, inHeight, inDepth, inFormat, usage, false),
|
|
|
|
|
- mBuffer(inWidth, inHeight, inDepth, inFormat),
|
|
|
|
|
- mGLInternalFormat(GL_NONE)
|
|
|
|
|
|
|
+ PixelFormat inFormat, GpuBufferUsage usage)
|
|
|
|
|
+ : PixelBuffer(inWidth, inHeight, inDepth, inFormat, usage, false),
|
|
|
|
|
+ mBuffer(inWidth, inHeight, inDepth, inFormat),
|
|
|
|
|
+ mGLInternalFormat(GL_NONE)
|
|
|
{
|
|
{
|
|
|
mCurrentLockOptions = (GpuLockOptions)0;
|
|
mCurrentLockOptions = (GpuLockOptions)0;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
GLPixelBuffer::~GLPixelBuffer()
|
|
GLPixelBuffer::~GLPixelBuffer()
|
|
|
{
|
|
{
|
|
|
- // Force free buffer
|
|
|
|
|
mBuffer.freeInternalBuffer();
|
|
mBuffer.freeInternalBuffer();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void GLPixelBuffer::allocateBuffer()
|
|
void GLPixelBuffer::allocateBuffer()
|
|
|
{
|
|
{
|
|
|
if(mBuffer.getData())
|
|
if(mBuffer.getData())
|
|
|
- // Already allocated
|
|
|
|
|
return;
|
|
return;
|
|
|
|
|
|
|
|
mBuffer.allocateInternalBuffer();
|
|
mBuffer.allocateInternalBuffer();
|
|
@@ -35,21 +33,22 @@ namespace BansheeEngine
|
|
|
|
|
|
|
|
void GLPixelBuffer::freeBuffer()
|
|
void GLPixelBuffer::freeBuffer()
|
|
|
{
|
|
{
|
|
|
- // Free buffer if we're STATIC to save memory
|
|
|
|
|
if(mUsage & GBU_STATIC)
|
|
if(mUsage & GBU_STATIC)
|
|
|
{
|
|
{
|
|
|
mBuffer.freeInternalBuffer();
|
|
mBuffer.freeInternalBuffer();
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- PixelData GLPixelBuffer::lockImpl(PixelVolume lockBox, GpuLockOptions options)
|
|
|
|
|
|
|
+ PixelData GLPixelBuffer::lockImpl(PixelVolume lockBox, GpuLockOptions options)
|
|
|
{
|
|
{
|
|
|
allocateBuffer();
|
|
allocateBuffer();
|
|
|
|
|
+
|
|
|
if(options != GBL_WRITE_ONLY_DISCARD)
|
|
if(options != GBL_WRITE_ONLY_DISCARD)
|
|
|
{
|
|
{
|
|
|
// Download the old contents of the texture
|
|
// Download the old contents of the texture
|
|
|
download(mBuffer);
|
|
download(mBuffer);
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
mCurrentLockOptions = options;
|
|
mCurrentLockOptions = options;
|
|
|
mLockedBox = lockBox;
|
|
mLockedBox = lockBox;
|
|
|
return mBuffer.getSubVolume(lockBox);
|
|
return mBuffer.getSubVolume(lockBox);
|
|
@@ -66,46 +65,43 @@ namespace BansheeEngine
|
|
|
freeBuffer();
|
|
freeBuffer();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- void GLPixelBuffer::upload(const PixelData &data, const PixelVolume &dest)
|
|
|
|
|
|
|
+ void GLPixelBuffer::upload(const PixelData& data, const PixelVolume& dest)
|
|
|
{
|
|
{
|
|
|
- BS_EXCEPT(RenderingAPIException,
|
|
|
|
|
- "Upload not possible for this pixelbuffer type");
|
|
|
|
|
|
|
+ BS_EXCEPT(RenderingAPIException, "Upload not possible for this pixel buffer type");
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- void GLPixelBuffer::download(const PixelData &data)
|
|
|
|
|
|
|
+ void GLPixelBuffer::download(const PixelData& data)
|
|
|
{
|
|
{
|
|
|
- BS_EXCEPT(RenderingAPIException, "Download not possible for this pixelbuffer type");
|
|
|
|
|
|
|
+ BS_EXCEPT(RenderingAPIException, "Download not possible for this pixel buffer type");
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- void GLPixelBuffer::blitFromTexture(GLTextureBuffer *src)
|
|
|
|
|
|
|
+ void GLPixelBuffer::blitFromTexture(GLTextureBuffer* src)
|
|
|
{
|
|
{
|
|
|
blitFromTexture(src,
|
|
blitFromTexture(src,
|
|
|
- PixelVolume(0,0,0,src->getWidth(),src->getHeight(),src->getDepth()),
|
|
|
|
|
- PixelVolume(0,0,0,mWidth,mHeight,mDepth)
|
|
|
|
|
|
|
+ PixelVolume(0, 0, 0, src->getWidth(), src->getHeight(), src->getDepth()),
|
|
|
|
|
+ PixelVolume(0, 0, 0, mWidth, mHeight, mDepth)
|
|
|
);
|
|
);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- void GLPixelBuffer::blitFromTexture(GLTextureBuffer *src, const PixelVolume &srcBox, const PixelVolume &dstBox)
|
|
|
|
|
|
|
+ void GLPixelBuffer::blitFromTexture(GLTextureBuffer* src, const PixelVolume& srcBox, const PixelVolume& dstBox)
|
|
|
{
|
|
{
|
|
|
- BS_EXCEPT(RenderingAPIException, "BlitFromTexture not possible for this pixelbuffer type");
|
|
|
|
|
|
|
+ BS_EXCEPT(RenderingAPIException, "BlitFromTexture not possible for this pixel buffer type");
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void GLPixelBuffer::bindToFramebuffer(GLenum attachment, UINT32 zoffset)
|
|
void GLPixelBuffer::bindToFramebuffer(GLenum attachment, UINT32 zoffset)
|
|
|
{
|
|
{
|
|
|
- BS_EXCEPT(RenderingAPIException, "Framebuffer bind not possible for this pixelbuffer type");
|
|
|
|
|
|
|
+ BS_EXCEPT(RenderingAPIException, "Framebuffer bind not possible for this pixel buffer type");
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- GLTextureBuffer::GLTextureBuffer(const String &baseName, GLenum target, GLuint id,
|
|
|
|
|
- GLint face, GLint level, GpuBufferUsage usage, bool crappyCard,
|
|
|
|
|
|
|
+ GLTextureBuffer::GLTextureBuffer(GLenum target, GLuint id,
|
|
|
|
|
+ GLint face, GLint level, GpuBufferUsage usage,
|
|
|
bool writeGamma, UINT32 multisampleCount):
|
|
bool writeGamma, UINT32 multisampleCount):
|
|
|
GLPixelBuffer(0, 0, 0, PF_UNKNOWN, usage),
|
|
GLPixelBuffer(0, 0, 0, PF_UNKNOWN, usage),
|
|
|
- mTarget(target), mFaceTarget(0), mTextureID(id), mFace(face), mLevel(level),
|
|
|
|
|
- mSoftwareMipmap(crappyCard)
|
|
|
|
|
|
|
+ mTarget(target), mFaceTarget(0), mTextureID(id), mFace(face), mLevel(level)
|
|
|
{
|
|
{
|
|
|
- // devise mWidth, mHeight and mDepth and mFormat
|
|
|
|
|
GLint value = 0;
|
|
GLint value = 0;
|
|
|
|
|
|
|
|
- glBindTexture( mTarget, mTextureID );
|
|
|
|
|
|
|
+ glBindTexture(mTarget, mTextureID);
|
|
|
|
|
|
|
|
// Get face identifier
|
|
// Get face identifier
|
|
|
mFaceTarget = mTarget;
|
|
mFaceTarget = mTarget;
|
|
@@ -142,10 +138,6 @@ namespace BansheeEngine
|
|
|
|
|
|
|
|
// Set up pixel box
|
|
// Set up pixel box
|
|
|
mBuffer = PixelData(mWidth, mHeight, mDepth, mFormat);
|
|
mBuffer = PixelData(mWidth, mHeight, mDepth, mFormat);
|
|
|
-
|
|
|
|
|
- if(mWidth==0 || mHeight==0 || mDepth==0)
|
|
|
|
|
- /// We are invalid, do not allocate a buffer
|
|
|
|
|
- return;
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
GLTextureBuffer::~GLTextureBuffer()
|
|
GLTextureBuffer::~GLTextureBuffer()
|
|
@@ -162,13 +154,10 @@ namespace BansheeEngine
|
|
|
if(data.getFormat() != mFormat || !data.isConsecutive())
|
|
if(data.getFormat() != mFormat || !data.isConsecutive())
|
|
|
BS_EXCEPT(InvalidParametersException,
|
|
BS_EXCEPT(InvalidParametersException,
|
|
|
"Compressed images must be consecutive, in the source format");
|
|
"Compressed images must be consecutive, in the source format");
|
|
|
|
|
+
|
|
|
GLenum format = GLPixelUtil::getClosestGLInternalFormat(mFormat);
|
|
GLenum format = GLPixelUtil::getClosestGLInternalFormat(mFormat);
|
|
|
- // Data must be consecutive and at beginning of buffer as PixelStorei not allowed
|
|
|
|
|
- // for compressed formats
|
|
|
|
|
switch(mTarget) {
|
|
switch(mTarget) {
|
|
|
case GL_TEXTURE_1D:
|
|
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)
|
|
if (dest.left == 0)
|
|
|
{
|
|
{
|
|
|
glCompressedTexImage1D(GL_TEXTURE_1D, mLevel,
|
|
glCompressedTexImage1D(GL_TEXTURE_1D, mLevel,
|
|
@@ -189,8 +178,6 @@ namespace BansheeEngine
|
|
|
break;
|
|
break;
|
|
|
case GL_TEXTURE_2D:
|
|
case GL_TEXTURE_2D:
|
|
|
case GL_TEXTURE_CUBE_MAP:
|
|
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)
|
|
if (dest.left == 0 && dest.top == 0)
|
|
|
{
|
|
{
|
|
|
glCompressedTexImage2D(mFaceTarget, mLevel,
|
|
glCompressedTexImage2D(mFaceTarget, mLevel,
|
|
@@ -211,8 +198,6 @@ namespace BansheeEngine
|
|
|
}
|
|
}
|
|
|
break;
|
|
break;
|
|
|
case GL_TEXTURE_3D:
|
|
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)
|
|
if (dest.left == 0 && dest.top == 0 && dest.front == 0)
|
|
|
{
|
|
{
|
|
|
glCompressedTexImage3D(GL_TEXTURE_3D, mLevel,
|
|
glCompressedTexImage3D(GL_TEXTURE_3D, mLevel,
|
|
@@ -240,14 +225,16 @@ namespace BansheeEngine
|
|
|
{
|
|
{
|
|
|
if(data.getWidth() != data.getRowPitch())
|
|
if(data.getWidth() != data.getRowPitch())
|
|
|
glPixelStorei(GL_UNPACK_ROW_LENGTH, data.getRowPitch());
|
|
glPixelStorei(GL_UNPACK_ROW_LENGTH, data.getRowPitch());
|
|
|
|
|
+
|
|
|
if(data.getHeight()*data.getWidth() != data.getSlicePitch())
|
|
if(data.getHeight()*data.getWidth() != data.getSlicePitch())
|
|
|
glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, (data.getSlicePitch()/data.getWidth()));
|
|
glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, (data.getSlicePitch()/data.getWidth()));
|
|
|
|
|
+
|
|
|
if(data.getLeft() > 0 || data.getTop() > 0 || data.getFront() > 0)
|
|
if(data.getLeft() > 0 || data.getTop() > 0 || data.getFront() > 0)
|
|
|
glPixelStorei(GL_UNPACK_SKIP_PIXELS, data.getLeft() + data.getRowPitch() * data.getTop() + data.getSlicePitch() * data.getFront());
|
|
glPixelStorei(GL_UNPACK_SKIP_PIXELS, data.getLeft() + data.getRowPitch() * data.getTop() + data.getSlicePitch() * data.getFront());
|
|
|
- if((data.getWidth()*PixelUtil::getNumElemBytes(data.getFormat())) & 3) {
|
|
|
|
|
- // Standard alignment of 4 is not right
|
|
|
|
|
|
|
+
|
|
|
|
|
+ if((data.getWidth()*PixelUtil::getNumElemBytes(data.getFormat())) & 3)
|
|
|
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
|
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
|
|
- }
|
|
|
|
|
|
|
+
|
|
|
switch(mTarget) {
|
|
switch(mTarget) {
|
|
|
case GL_TEXTURE_1D:
|
|
case GL_TEXTURE_1D:
|
|
|
glTexSubImage1D(GL_TEXTURE_1D, mLevel,
|
|
glTexSubImage1D(GL_TEXTURE_1D, mLevel,
|
|
@@ -274,10 +261,10 @@ namespace BansheeEngine
|
|
|
break;
|
|
break;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
// Restore defaults
|
|
// Restore defaults
|
|
|
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
|
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
|
|
- if (GLEW_VERSION_1_2)
|
|
|
|
|
- glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0);
|
|
|
|
|
|
|
+ glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0);
|
|
|
glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
|
|
glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
|
|
|
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
|
|
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
|
|
|
}
|
|
}
|
|
@@ -290,16 +277,16 @@ namespace BansheeEngine
|
|
|
if((mUsage & TU_DEPTHSTENCIL) != 0)
|
|
if((mUsage & TU_DEPTHSTENCIL) != 0)
|
|
|
BS_EXCEPT(NotImplementedException, "Reading from depth stencil texture to CPU not supported."); // TODO: This needs to be implemented
|
|
BS_EXCEPT(NotImplementedException, "Reading from depth stencil texture to CPU not supported."); // TODO: This needs to be implemented
|
|
|
|
|
|
|
|
- if(data.getWidth() != getWidth() ||
|
|
|
|
|
- data.getHeight() != getHeight() ||
|
|
|
|
|
- data.getDepth() != getDepth())
|
|
|
|
|
|
|
+ if(data.getWidth() != getWidth() || data.getHeight() != getHeight() || data.getDepth() != getDepth())
|
|
|
BS_EXCEPT(InvalidParametersException, "only download of entire buffer is supported by GL");
|
|
BS_EXCEPT(InvalidParametersException, "only download of entire buffer is supported by GL");
|
|
|
|
|
+
|
|
|
glBindTexture( mTarget, mTextureID );
|
|
glBindTexture( mTarget, mTextureID );
|
|
|
if(PixelUtil::isCompressed(data.getFormat()))
|
|
if(PixelUtil::isCompressed(data.getFormat()))
|
|
|
{
|
|
{
|
|
|
if(data.getFormat() != mFormat || !data.isConsecutive())
|
|
if(data.getFormat() != mFormat || !data.isConsecutive())
|
|
|
BS_EXCEPT(InvalidParametersException,
|
|
BS_EXCEPT(InvalidParametersException,
|
|
|
"Compressed images must be consecutive, in the source format");
|
|
"Compressed images must be consecutive, in the source format");
|
|
|
|
|
+
|
|
|
// Data must be consecutive and at beginning of buffer as PixelStorei not allowed
|
|
// Data must be consecutive and at beginning of buffer as PixelStorei not allowed
|
|
|
// for compressed formate
|
|
// for compressed formate
|
|
|
glGetCompressedTexImage(mFaceTarget, mLevel, data.getData());
|
|
glGetCompressedTexImage(mFaceTarget, mLevel, data.getData());
|
|
@@ -308,18 +295,20 @@ namespace BansheeEngine
|
|
|
{
|
|
{
|
|
|
if(data.getWidth() != data.getRowPitch())
|
|
if(data.getWidth() != data.getRowPitch())
|
|
|
glPixelStorei(GL_PACK_ROW_LENGTH, data.getRowPitch());
|
|
glPixelStorei(GL_PACK_ROW_LENGTH, data.getRowPitch());
|
|
|
|
|
+
|
|
|
if(data.getHeight()*data.getWidth() != data.getSlicePitch())
|
|
if(data.getHeight()*data.getWidth() != data.getSlicePitch())
|
|
|
glPixelStorei(GL_PACK_IMAGE_HEIGHT, (data.getSlicePitch()/data.getWidth()));
|
|
glPixelStorei(GL_PACK_IMAGE_HEIGHT, (data.getSlicePitch()/data.getWidth()));
|
|
|
|
|
+
|
|
|
if(data.getLeft() > 0 || data.getTop() > 0 || data.getFront() > 0)
|
|
if(data.getLeft() > 0 || data.getTop() > 0 || data.getFront() > 0)
|
|
|
glPixelStorei(GL_PACK_SKIP_PIXELS, data.getLeft() + data.getRowPitch() * data.getTop() + data.getSlicePitch() * data.getFront());
|
|
glPixelStorei(GL_PACK_SKIP_PIXELS, data.getLeft() + data.getRowPitch() * data.getTop() + data.getSlicePitch() * data.getFront());
|
|
|
- if((data.getWidth()*PixelUtil::getNumElemBytes(data.getFormat())) & 3) {
|
|
|
|
|
- // Standard alignment of 4 is not right
|
|
|
|
|
|
|
+
|
|
|
|
|
+ if((data.getWidth()*PixelUtil::getNumElemBytes(data.getFormat())) & 3)
|
|
|
glPixelStorei(GL_PACK_ALIGNMENT, 1);
|
|
glPixelStorei(GL_PACK_ALIGNMENT, 1);
|
|
|
- }
|
|
|
|
|
|
|
+
|
|
|
// We can only get the entire texture
|
|
// We can only get the entire texture
|
|
|
- glGetTexImage(mFaceTarget, mLevel,
|
|
|
|
|
- GLPixelUtil::getGLOriginFormat(data.getFormat()), GLPixelUtil::getGLOriginDataType(data.getFormat()),
|
|
|
|
|
- data.getData());
|
|
|
|
|
|
|
+ glGetTexImage(mFaceTarget, mLevel, GLPixelUtil::getGLOriginFormat(data.getFormat()),
|
|
|
|
|
+ GLPixelUtil::getGLOriginDataType(data.getFormat()), data.getData());
|
|
|
|
|
+
|
|
|
// Restore defaults
|
|
// Restore defaults
|
|
|
glPixelStorei(GL_PACK_ROW_LENGTH, 0);
|
|
glPixelStorei(GL_PACK_ROW_LENGTH, 0);
|
|
|
glPixelStorei(GL_PACK_IMAGE_HEIGHT, 0);
|
|
glPixelStorei(GL_PACK_IMAGE_HEIGHT, 0);
|
|
@@ -372,192 +361,9 @@ namespace BansheeEngine
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- /// 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 PixelVolume &srcBox, const PixelVolume &dstBox)
|
|
|
|
|
|
|
+ void GLTextureBuffer::blitFromTexture(GLTextureBuffer* src, const PixelVolume& srcBox, const PixelVolume& 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);
|
|
|
|
|
-
|
|
|
|
|
- // Important to disable all other texture units
|
|
|
|
|
- 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);
|
|
|
|
|
-
|
|
|
|
|
- /// 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 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);
|
|
|
|
|
-
|
|
|
|
|
- /// 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());
|
|
|
|
|
-
|
|
|
|
|
- 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;
|
|
|
|
|
-
|
|
|
|
|
- /// 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;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /// 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);
|
|
|
|
|
|
|
+ BS_EXCEPT(NotImplementedException, "Not implemented.");
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
GLRenderBuffer::GLRenderBuffer(GLenum format, UINT32 width, UINT32 height, GLsizei numSamples):
|
|
GLRenderBuffer::GLRenderBuffer(GLenum format, UINT32 width, UINT32 height, GLsizei numSamples):
|
|
@@ -565,9 +371,7 @@ namespace BansheeEngine
|
|
|
mRenderbufferID(0)
|
|
mRenderbufferID(0)
|
|
|
{
|
|
{
|
|
|
mGLInternalFormat = format;
|
|
mGLInternalFormat = format;
|
|
|
- /// Generate renderbuffer
|
|
|
|
|
glGenRenderbuffersEXT(1, &mRenderbufferID);
|
|
glGenRenderbuffersEXT(1, &mRenderbufferID);
|
|
|
- /// Bind it to FBO
|
|
|
|
|
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, mRenderbufferID);
|
|
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, mRenderbufferID);
|
|
|
|
|
|
|
|
/// Allocate storage for depth buffer
|
|
/// Allocate storage for depth buffer
|
|
@@ -585,7 +389,6 @@ namespace BansheeEngine
|
|
|
|
|
|
|
|
GLRenderBuffer::~GLRenderBuffer()
|
|
GLRenderBuffer::~GLRenderBuffer()
|
|
|
{
|
|
{
|
|
|
- /// Generate renderbuffer
|
|
|
|
|
glDeleteRenderbuffersEXT(1, &mRenderbufferID);
|
|
glDeleteRenderbuffersEXT(1, &mRenderbufferID);
|
|
|
}
|
|
}
|
|
|
|
|
|