Show pixelbuffer.cpp syntax highlighted
/***************************************************************************
pixelbuffer.cpp - OpenGL pixel buffer implementation
-------------------
begin : Thu April 17, 2003
copyright : (C) 2003 by Cody Russell
email : cody [at] jhu.edu
last modify date : Fri Jul 07 2006
last modify :
l.m. copyright : (C) 2006 by Arcadia Design s.r.l.
email : Dario Deledda (penguindark@hotmail.com)
***************************************************************************
The contents of this file are subject to the Mozilla Public License Version
1.1 (the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.mozilla.org/MPL/
Software distributed under the License is distributed on an "AS IS" basis,
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
for the specific language governing rights and limitations under the
License.
The Original Code is the NeoEngine, NeoDevOpenGL, pixelbuffer.cpp
The Initial Developer of the Original Code is Cody Russell.
Portions created by Cody Russell are Copyright (C) 2003
Cody Russell. All Rights Reserved.
Contributors: Mattias Jansson (mattias@realityrift.com)
***************************************************************************/
#define __NEED_VECTOR_INT
#define NEEDGDI
#include "device.h"
#include "pixelbuffer.h"
#include "pixelbuffertarget.h"
#include "textureunit.h"
#include <neoengine/logstream.h>
using namespace std;
using namespace NeoEngine;
namespace NeoOGL
{
/*! Free buffer IDs */
vector< int > g_vuiFreePBufferID;
/*! Last buffer ID */
unsigned int g_uiNextPBufferID = 0;
GLenum g_Kdrawbuffers[] = {
GL_COLOR_ATTACHMENT0_EXT,
GL_COLOR_ATTACHMENT1_EXT,
GL_COLOR_ATTACHMENT2_EXT,
GL_COLOR_ATTACHMENT3_EXT,
GL_COLOR_ATTACHMENT4_EXT,
GL_COLOR_ATTACHMENT5_EXT,
GL_COLOR_ATTACHMENT6_EXT,
GL_COLOR_ATTACHMENT7_EXT,
GL_COLOR_ATTACHMENT8_EXT,
GL_COLOR_ATTACHMENT9_EXT ,
GL_COLOR_ATTACHMENT10_EXT,
GL_COLOR_ATTACHMENT11_EXT,
GL_COLOR_ATTACHMENT12_EXT,
GL_COLOR_ATTACHMENT13_EXT,
GL_COLOR_ATTACHMENT14_EXT,
GL_COLOR_ATTACHMENT15_EXT
};
#ifdef WIN32
//Helper method
string GetLastErrorString( DWORD dwError )
{
LPVOID lpMsgBuf;
FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dwError, MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), (LPTSTR)&lpMsgBuf, 0, NULL );
string strRet = (char*)lpMsgBuf;
LocalFree( lpMsgBuf );
return strRet;
}
#endif
NeoEngine::PixelBuffer *Device::CreatePixelBuffer( unsigned int uiWidth, unsigned int uiHeight, unsigned int uiBPP, Texture::TEXTURETYPE eTextureType, Texture::TEXTUREFORMAT eTextureFormat )
{
if( m_kWindow.m_kCaps.IsSet( RenderCaps::RENDERTEXTURE ) )
{
PixelBuffer *pkPBuffer = new PixelBuffer( this );
if( pkPBuffer->Open( uiWidth, uiHeight, uiBPP, eTextureType, eTextureFormat ) )
return pkPBuffer;
neolog << LogLevel( ERROR ) << "*** Unable to create pixel buffer: Unable to open buffer [" << uiWidth << "x" << uiHeight << "x" << uiBPP << "]" << endl;
delete pkPBuffer;
}
return 0;
}
unsigned int PixelBuffer::AddTarget( NeoEngine::TexturePtr pTexture)
{
if ( pTexture && ( m_vMtTexture.size() < m_pkDevice->GetFBOMaxTarget() ) ){
m_vMtTexture.push_back(pTexture);
return m_vMtTexture.size();
}
return 0;
}
bool PixelBuffer::RemoveTarget( NeoEngine::TexturePtr pTexture)
{
std::vector< NeoEngine::TexturePtr >::iterator iter=m_vMtTexture.begin();
std::vector< NeoEngine::TexturePtr >::iterator end=m_vMtTexture.end();
while ( iter != end){
if ( *iter == pTexture){
m_vMtTexture.erase(iter);
return true;
}
iter++;
}
return false;
}
PixelBuffer::PixelBuffer( Device *pkDevice ) :
Activator(),
NeoEngine::PixelBuffer(),
m_pkDevice( pkDevice ),
m_bIsBound( false ),
m_kViewport( m_pkDevice->GetViewport() ),
m_eCurCubemapFace( Texture::CUBEFACE_FRONT )
{
Deactivate();
if( g_vuiFreePBufferID.size() )
{
m_uiID = *( g_vuiFreePBufferID.end() - 1 );
g_vuiFreePBufferID.pop_back();
}
else
m_uiID = g_uiNextPBufferID++;
m_pkDevice->m_vpkPixelBuffers.push_back( this );
m_iFrameBufObj = 0;
m_iDepthBufObj = 0;
m_vMtTexture.clear();
}
PixelBuffer::~PixelBuffer()
{
Close();
g_vuiFreePBufferID.push_back( m_uiID );
std::vector< NeoEngine::TexturePtr >::iterator iter=m_vMtTexture.begin();
std::vector< NeoEngine::TexturePtr >::iterator end=m_vMtTexture.end();
while ( iter != end){
m_vMtTexture.erase(iter);
iter=m_vMtTexture.begin();
end=m_vMtTexture.end();
}
vector< PixelBuffer* >::iterator ppkBuffer = m_pkDevice->m_vpkPixelBuffers.begin();
vector< PixelBuffer* >::iterator ppkBufferEnd = m_pkDevice->m_vpkPixelBuffers.end();
for( ; ppkBuffer != ppkBufferEnd; ++ppkBuffer )
if( *ppkBuffer == this )
{
m_pkDevice->m_vpkPixelBuffers.erase( ppkBuffer );
break;
}
if( m_pkDevice->m_pkPixelBufferTarget->m_pkCurBuffer == this )
m_pkDevice->m_pkPixelBufferTarget->m_pkCurBuffer = 0;
// test for Frame Object support
if ( m_pkTexture && m_pkTexture->GetType() == Texture::TEX2DF && m_pkDevice->m_kExtensions.IsSupported( Extensions::EXT_FRAME_BUFFER) ){
if ( m_iFrameBufObj ){
neoglDeleteFramebuffersEXT (1,&m_iFrameBufObj);
}
if ( m_iDepthBufObj ){
neoglDeleteFramebuffersEXT (1,&m_iDepthBufObj);
}
}
if ( m_pkTexture && m_pkTexture->GetType() == Texture::CUBEMAPFBO && m_pkDevice->m_kExtensions.IsSupported( Extensions::EXT_FRAME_BUFFER) ){
int index=0;
while ( index < 6 ){
if ( m_iCubeMapBufObj[index] )
neoglGenFramebuffersEXT(1, &m_iCubeMapBufObj[index] );
index++;
}
if ( m_iDepthBufObj ){
neoglDeleteFramebuffersEXT (1,&m_iDepthBufObj);
}
}
}
bool PixelBuffer::Open( unsigned int uiWidth, unsigned int uiHeight, unsigned int uiBPP, Texture::TEXTURETYPE eTextureType, Texture::TEXTUREFORMAT eTextureFormat )
{
m_uiWidth = uiWidth;
m_uiHeight = uiHeight;
m_uiBPP = uiBPP;
int iComp = 0;
GLenum iInternalFormat = 0;
GLenum iDataFormat = GL_RGB;
GLenum iDataType = GL_UNSIGNED_BYTE;
if ( eTextureType==Texture::TEXDEPTH && !m_pkDevice->m_kExtensions.IsSupported( Extensions::ARB_DEPTH_TEXTURE ) ){
m_uiWidth = 0;
m_uiHeight = 0;
neolog << LogLevel( ERROR ) << "*** Invalid texture type [ ARB_DEPTH_TEXTURE ] not supported by this graphic card!!!" << endl;
return false;
}
switch( eTextureFormat )
{
case Texture::ALPHA:
{
iInternalFormat = GL_ALPHA;
iDataFormat = GL_ALPHA;
iComp = 1;
iDataType = GL_UNSIGNED_BYTE;
//m_iInternalFormat = Texture::INTERNALFORMAT_ALPHA8;
break;
}
case Texture::RGB:
{
iInternalFormat = GL_RGB;
iDataFormat = GL_RGB;
iComp = 3;
iDataType = GL_UNSIGNED_BYTE;
//m_iInternalFormat = Texture::INTERNALFORMAT_RGB888;
break;
}
case Texture::RGBA:
{
iInternalFormat = GL_RGBA;
iDataFormat = GL_RGBA;
iComp = 4;
iDataType = GL_UNSIGNED_BYTE;
//m_iInternalFormat = Texture::INTERNALFORMAT_RGBA8888;
break;
}
case Texture::DEPTH:
{
iInternalFormat = GL_DEPTH_COMPONENT;
iDataFormat = GL_DEPTH_COMPONENT;
iComp = 1;
iDataType = GL_UNSIGNED_INT;
//m_iInternalFormat = Texture::INTERNALFORMAT_DEPTH;
break;
}
case Texture::RGBA16F:
{
if( m_pkDevice->m_kExtensions.IsSupported( Extensions::ARB_FLOAT_TEXTURE ) ){
iInternalFormat = GL_RGBA16F_ARB;
iDataFormat = GL_RGBA;
iComp = 4;
iDataType = GL_FLOAT;
//m_iInternalFormat = Texture::INTERNALFORMAT_RGBA16F;
}else{
neolog << LogLevel( ERROR ) << "*** Invalid texture format [" << (int)eTextureFormat << "]" << endl;
}
break;
}
case Texture::RGB16F:
{
if( m_pkDevice->m_kExtensions.IsSupported( Extensions::ARB_FLOAT_TEXTURE ) ){
iInternalFormat = GL_RGB16F_ARB;
iDataFormat = GL_RGB;
iComp = 3;
iDataType = GL_FLOAT;
//m_iInternalFormat = Texture::INTERNALFORMAT_RGB16F;
}else{
neolog << LogLevel( ERROR ) << "*** Invalid texture format [" << (int)eTextureFormat << "]" << endl;
}
break;
}
case Texture::RGBA32F:
{
if( m_pkDevice->m_kExtensions.IsSupported( Extensions::ARB_FLOAT_TEXTURE ) ){
iInternalFormat = GL_RGBA32F_ARB;
iDataFormat = GL_RGBA;
iComp = 4;
iDataType = GL_FLOAT;
//m_iInternalFormat = Texture::INTERNALFORMAT_RGBA32F;
}else{
neolog << LogLevel( ERROR ) << "*** Invalid texture format [" << (int)eTextureFormat << "]" << endl;
}
break;
}
case Texture::RGB32F:
{
if( m_pkDevice->m_kExtensions.IsSupported( Extensions::ARB_FLOAT_TEXTURE ) ){
iInternalFormat = GL_RGB32F_ARB;
iDataFormat = GL_RGB;
iComp = 3;
iDataType = GL_FLOAT;
//m_iInternalFormat = Texture::INTERNALFORMAT_RGB32F;
}else{
neolog << LogLevel( ERROR ) << "*** Invalid texture format [" << (int)eTextureFormat << "]" << endl;
}
break;
}
default:
{
neolog << LogLevel( ERROR ) << "*** Invalid texture format [" << (int)eTextureFormat << "]" << endl;
break;
}
}
// Prevent depth texture greater than screen
if ( eTextureType == Texture::TEXDEPTH){
while( m_uiWidth > m_pkDevice->GetWidth() )
m_uiWidth >>= 2;
while( m_uiHeight > m_pkDevice->GetHeight() )
m_uiHeight >>= 2;
}
// test for non power of two texture support
if ( !m_pkDevice->m_kExtensions.IsSupported( Extensions::ARB_NP2_TEXTURE) ){
float fExp = float( log( float( m_uiWidth ) ) ) / float( log( 2.0f ) );
float fFrac = fExp - float( int( fExp ) );
if( ( fFrac > 0.0001f ) && ( fFrac < 0.9999f ) )
{
neolog << LogLevel( ERROR ) << "*** Unable to create pixelbuffer: width [" << m_uiWidth << "] not a power of 2, exponent [" << fExp << "]" << endl;
return false;
}
fExp = float( log( float( m_uiHeight ) ) ) / float( log( 2.0f ) );
fFrac = fExp - float( int( fExp ) );
if( ( fFrac > 0.0001f ) && ( fFrac < 0.9999f ) )
{
neolog << LogLevel( ERROR ) << "*** Unable to create pixelbuffer: height [" << m_uiHeight << "] not a power of 2, exponent [" << fExp << "]" << endl;
return false;
}
if( eTextureType != Texture::TEXDEPTH ){
while( m_uiWidth > m_pkDevice->GetWidth() )
m_uiWidth >>= 2;
while( m_uiHeight > m_pkDevice->GetHeight() )
m_uiHeight >>= 2;
}
}
// test for rectangular texture support
if ( !m_pkDevice->m_kExtensions.IsSupported( Extensions::ARB_RECT_TEXTURE) )
{
// We shouldn't ruin the squareness when resizing
if( m_uiWidth != m_uiHeight )
{
m_uiWidth = MIN( m_uiWidth, m_uiHeight );
m_uiHeight = m_uiWidth;
}
}
// test for Frame Object support
if ( (eTextureType == Texture::TEX2DF || eTextureType == Texture::CUBEMAPFBO )
&& m_pkDevice->m_kExtensions.IsSupported( Extensions::EXT_FRAME_BUFFER) ){
// create FBO (off-screen framebuffer)
m_iFrameBufObj=0;
m_iDepthBufObj=0;
m_iCubeMapBufObj[0]=0;
if ( eTextureType == Texture::CUBEMAPFBO){
int i=0;
while (i < 6){
m_iCubeMapBufObj[i]=0;
neoglGenFramebuffersEXT(1, &m_iCubeMapBufObj[i] );
i++;
}
neoglGenFramebuffersEXT(1, &m_iDepthBufObj );
} else if ( eTextureFormat == Texture::DEPTH){
neoglGenFramebuffersEXT(1, &m_iDepthBufObj );
}else{
neoglGenFramebuffersEXT(1, &m_iFrameBufObj );
neoglGenFramebuffersEXT(1, &m_iDepthBufObj );
}
}
m_kViewport.m_iX=0;
m_kViewport.m_iY=0;
m_kViewport.m_iWidth=m_uiWidth;
m_kViewport.m_iHeight=m_uiHeight;
m_pkTexture = new NeoOGL::Texture( m_pkDevice, "__pbuffer", eTextureType, eTextureFormat, Texture::LINEAR | ( Texture::LINEAR << 8 ), 1, 0, 0, m_uiWidth, m_uiHeight );
m_pkDevice->m_ppkTMU[0]->SetTexture( (NeoOGL::Texture*)(NeoEngine::Texture*)m_pkTexture );
if( eTextureType == Texture::TEXDEPTH )
{
iDataFormat = GL_DEPTH_COMPONENT;
GLint iInternalFormat;
if ( m_uiBPP == 24 )
iInternalFormat = GL_DEPTH_COMPONENT24;
else if ( m_uiBPP == 16 )
iInternalFormat = GL_DEPTH_COMPONENT16;
else if ( m_uiBPP == 32 )
iInternalFormat = GL_DEPTH_COMPONENT32;
else
iInternalFormat = GL_DEPTH_COMPONENT;
iDataType = GL_UNSIGNED_INT;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
//glTexImage2D( GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, m_uiWidth, m_uiHeight, 0, iDataFormat, iDataType, 0 );
glTexImage2D( GL_TEXTURE_2D, 0, iInternalFormat, m_uiWidth, m_uiHeight, 0, iDataFormat, iDataType, 0 );
}
else if( eTextureType == Texture::TEX2D )
{
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, m_uiWidth, m_uiHeight, 0, iDataFormat, iDataType, 0 );
}
else if( eTextureType == Texture::TEX2DF )
{
if ( eTextureFormat== Texture::DEPTH )
{
iDataFormat = GL_DEPTH_COMPONENT;
GLint iInternalFormat;
if ( m_uiBPP == 24 )
iInternalFormat = GL_DEPTH_COMPONENT24;
else if ( m_uiBPP == 16 )
iInternalFormat = GL_DEPTH_COMPONENT16;
else if ( m_uiBPP == 32 )
iInternalFormat = GL_DEPTH_COMPONENT32;
else
iInternalFormat = GL_DEPTH_COMPONENT;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
// glTexImage2D( GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, m_uiWidth, m_uiHeight, 0, iDataFormat, iDataType, 0 );
glTexImage2D( GL_TEXTURE_2D, 0, iInternalFormat, m_uiWidth, m_uiHeight, 0, iDataFormat, iDataType, 0 );
}else{
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
glTexImage2D( GL_TEXTURE_2D, 0, iInternalFormat , m_uiWidth, m_uiHeight, 0, iDataFormat, iDataType, 0 );
}
}
else if( eTextureType == Texture::CUBEMAP )
{
if( !m_pkDevice->m_kExtensions.IsSupported( Extensions::ARB_TEXTURE_CUBE_MAP ) )
{
neolog << LogLevel( ERROR ) << "*** Unable to create pixelbuffer: no cubemap support" << endl;
return false;
}
glTexParameteri( GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
glTexParameteri( GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
glTexParameteri( GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE );
glTexParameteri( GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
for( int iFace = 0; iFace < 6; ++iFace )
glTexImage2D( Texture::s_aeOGLCubeFaces[iFace], 0, GL_RGB, m_uiWidth, m_uiHeight, 0, iDataFormat, iDataType, 0 );
}
else if( eTextureType == Texture::CUBEMAPFBO ){
if( !m_pkDevice->m_kExtensions.IsSupported( Extensions::ARB_TEXTURE_CUBE_MAP ) )
{
neolog << LogLevel( ERROR ) << "*** Unable to create pixelbuffer: no cubemap support" << endl;
return false;
}
glTexParameteri( GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
glTexParameteri( GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
glTexParameteri( GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE );
glTexParameteri( GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
// for( int iFace = 0; iFace < 6; ++iFace )
// glTexImage2D(Texture::s_aeOGLCubeFaces[iFace], 0, iInternalFormat, m_uiWidth, m_uiHeight, 0, iDataFormat, iDataType, 0 );
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, iInternalFormat, m_uiWidth, m_uiHeight, 0, iDataFormat, iDataType, 0 );
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, iInternalFormat, m_uiWidth, m_uiHeight, 0, iDataFormat, iDataType, 0 );
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, iInternalFormat, m_uiWidth, m_uiHeight, 0, iDataFormat, iDataType, 0 );
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, iInternalFormat, m_uiWidth, m_uiHeight, 0, iDataFormat, iDataType, 0 );
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, iInternalFormat, m_uiWidth, m_uiHeight, 0, iDataFormat, iDataType, 0 );
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, iInternalFormat, m_uiWidth, m_uiHeight, 0, iDataFormat, iDataType, 0 );
}
else
{
neolog << LogLevel( ERROR ) << "*** Unable to create pixelbuffer: unsupported texture type [" << (int)eTextureType << "]" << endl;
return false;
}
neoglCheckError();
GLint iRealWidth = 0;
GLint iRealHeight = 0;
GLint iA = 0;
GLint iR = 0;
GLint iG = 0;
GLint iB = 0;
GLint iD = 0;
GLint iIntFmt = 0;
GLenum eTextureID = 0;
if( eTextureType == Texture::TEX2D || eTextureType == Texture::TEX2DF ) eTextureID= GL_TEXTURE_2D;
if( eTextureType == Texture::TEXDEPTH ) eTextureID= GL_TEXTURE_2D;
if( eTextureType == Texture::CUBEMAP ) eTextureID= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB;
if( eTextureType == Texture::CUBEMAPFBO ) eTextureID= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB;
glGetTexLevelParameteriv( eTextureID, 0, GL_TEXTURE_WIDTH, &iRealWidth );
glGetTexLevelParameteriv( eTextureID, 0, GL_TEXTURE_HEIGHT, &iRealHeight );
glGetTexLevelParameteriv( eTextureID, 0, GL_TEXTURE_ALPHA_SIZE, &iA );
glGetTexLevelParameteriv( eTextureID, 0, GL_TEXTURE_RED_SIZE, &iR );
glGetTexLevelParameteriv( eTextureID, 0, GL_TEXTURE_GREEN_SIZE, &iG );
glGetTexLevelParameteriv( eTextureID, 0, GL_TEXTURE_BLUE_SIZE, &iB );
glGetTexLevelParameteriv( eTextureID, 0, GL_TEXTURE_DEPTH_SIZE_ARB, &iD );
glGetTexLevelParameteriv( eTextureID, 0, GL_TEXTURE_INTERNAL_FORMAT,&iIntFmt);
neolog << LogLevel( DEBUG ) << "Created pixelbuffer texture " << uiWidth << "x" << uiHeight
<< " ID " << m_pkTexture->GetID() << " -> [" << iRealWidth << "x" << iRealHeight
<< "] ARGB" << iA << iR << iG << iB << ( ( eTextureType == Texture::CUBEMAP || eTextureType == Texture::CUBEMAPFBO ) ? " x 6" : "" )
<< " depth:"<< iD
<< " Internal Format:"<<iIntFmt
<<endl;
m_uiWidth = (unsigned int)iRealWidth;
m_uiHeight = (unsigned int)iRealHeight;
Deactivate();
return true;
}
void PixelBuffer::Close()
{
m_pkTexture = 0;
}
void PixelBuffer::Activate()
{
if( IsActive() )
return;
if ( m_iCubeMapBufObj[0] && m_pkTexture && m_pkTexture->GetType() == Texture::CUBEMAPFBO ){
Activator::Activate();
m_pkDevice->SetCullMode( m_pkDevice->m_eCullMode );
//m_pkDevice->m_bIsRenderingTexture = true;
int index=m_eCurCubemapFace;
// bind offscreen buffer
neoglBindFramebufferEXT(GL_FRAMEBUFFER_EXT,
m_iCubeMapBufObj[index] );
// set viewport with FBO flag true
m_pkDevice->SetViewport( 0, 0, m_uiWidth, m_uiHeight, true );
// attach texture
neoglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
GL_COLOR_ATTACHMENT0_EXT,
GL_TEXTURE_CUBE_MAP_POSITIVE_X+index,m_pkTexture->GetID(),0);
// initialize depth renderbuffer
neoglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_iDepthBufObj);
neoglRenderbufferStorageEXT(GL_RENDERBUFFER_EXT,
GL_DEPTH_COMPONENT24, m_uiWidth, m_uiHeight);
neoglFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,
GL_DEPTH_ATTACHMENT_EXT,
GL_RENDERBUFFER_EXT, m_iDepthBufObj);
// set the texture as render target
glDrawBuffer (GL_COLOR_ATTACHMENT0_EXT);
return;
}
if ( m_iDepthBufObj && m_pkTexture && m_pkTexture->GetFormat() == Texture::DEPTH ){
Activator::Activate();
m_kViewport = m_pkDevice->GetViewport();
//m_pkDevice->m_bIsRenderingTexture = true;
// Enable render-to-texture
neoglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_iDepthBufObj);
// Set up depth_tex for render-to-texture
neoglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
GL_DEPTH_ATTACHMENT_EXT,
GL_TEXTURE_2D, m_pkTexture->GetID(), 0);
// No color buffer to draw to or read from
glDrawBuffer(GL_NONE);
glReadBuffer(GL_NONE);
// set viewport with FBO flag true
m_pkDevice->SetViewport( 0, 0, m_uiWidth, m_uiHeight, true );
return;
}
// test for Frame Object support
else if ( m_iFrameBufObj && m_pkTexture && m_pkTexture->GetType() == Texture::TEX2DF ){
Activator::Activate();
//m_pkDevice->m_bIsRenderingTexture = true;
m_pkDevice->SetCullMode( m_pkDevice->m_eCullMode );
// bind offscreen buffer
neoglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_iFrameBufObj );
// attach texture
// set viewport with FBO flag true
neoglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
GL_COLOR_ATTACHMENT0_EXT,
GL_TEXTURE_2D,m_pkTexture->GetID(),0);
// set the other target textures
std::vector< NeoEngine::TexturePtr >::iterator iter=m_vMtTexture.begin();
std::vector< NeoEngine::TexturePtr >::iterator end=m_vMtTexture.end();
unsigned int nAttach=1;
while ( iter != end ){
neoglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
GL_COLOR_ATTACHMENT0_EXT+nAttach,
GL_TEXTURE_2D,(*iter)->GetID(),0);
nAttach++;
iter++;
}
// initialize depth renderbuffer
neoglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_iDepthBufObj);
neoglRenderbufferStorageEXT(GL_RENDERBUFFER_EXT,
GL_DEPTH_COMPONENT24, m_uiWidth, m_uiHeight);
neoglFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,
GL_DEPTH_ATTACHMENT_EXT,
GL_RENDERBUFFER_EXT, m_iDepthBufObj);
// set the texture as render target
if (nAttach > 1){
neoglDrawBuffersEXT(nAttach,g_Kdrawbuffers);
}else{
// neoglDrawBuffersEXT(1,g_Kdrawbuffers);
glDrawBuffer (GL_COLOR_ATTACHMENT0_EXT);
}
m_pkDevice->SetViewport( 0, 0, m_uiWidth, m_uiHeight, true );
return;
} else {
Activator::Activate();
m_kViewport = m_pkDevice->GetViewport();
m_pkDevice->SetViewport( 0, 0, m_uiWidth, m_uiHeight );
m_pkDevice->m_bIsRenderingTexture = true;
m_pkDevice->SetCullMode( m_pkDevice->m_eCullMode );
}
}
void PixelBuffer::Deactivate()
{
if( !IsActive() )
return;
if ( m_iCubeMapBufObj[0] && m_pkTexture && m_pkTexture->GetType() == Texture::CUBEMAPFBO ){
neoglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0 );
Activator::Deactivate();
m_pkDevice->SetViewport( m_kViewport.m_iX, m_kViewport.m_iY, m_kViewport.m_iWidth, m_kViewport.m_iHeight );
m_pkDevice->m_bIsRenderingTexture = false;
m_pkDevice->SetCullMode( m_pkDevice->m_eCullMode );
glDrawBuffer( GL_BACK );
return;
}
// test for depth Frame Object support
if ( m_iDepthBufObj && m_pkTexture && m_pkTexture->GetFormat() == Texture::DEPTH ){
neoglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0 );
Activator::Deactivate();
m_pkDevice->SetViewport( m_kViewport.m_iX, m_kViewport.m_iY, m_kViewport.m_iWidth, m_kViewport.m_iHeight );
m_pkDevice->m_bIsRenderingTexture = false;
m_pkDevice->SetCullMode( m_pkDevice->m_eCullMode );
glDrawBuffer( GL_BACK );
return;
}
// test for Frame Object support
if ( m_iFrameBufObj && m_pkTexture && m_pkTexture->GetType() == Texture::TEX2DF ){
neoglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0 );
Activator::Deactivate();
m_pkDevice->SetViewport( m_kViewport.m_iX, m_kViewport.m_iY, m_kViewport.m_iWidth, m_kViewport.m_iHeight );
m_pkDevice->m_bIsRenderingTexture = false;
m_pkDevice->SetCullMode( m_pkDevice->m_eCullMode );
glDrawBuffer( GL_BACK );
return;
}else{
Activator::Deactivate();
GrabTexture();
m_pkDevice->SetViewport( m_kViewport.m_iX, m_kViewport.m_iY, m_kViewport.m_iWidth, m_kViewport.m_iHeight );
m_pkDevice->m_bIsRenderingTexture = false;
m_pkDevice->SetCullMode( m_pkDevice->m_eCullMode );
return;
}
}
void PixelBuffer::SetCubeMapFace( Texture::TEXTURECUBEMAPFACE eCubeMapFace )
{
if( m_eCurCubemapFace == eCubeMapFace )
return;
if( IsActive() && m_pkTexture && ( m_pkTexture->GetType() == Texture::CUBEMAP ) )
GrabTexture();
m_eCurCubemapFace = eCubeMapFace;
if( !IsActive() )
return;
if ( m_iCubeMapBufObj[0] && m_pkTexture && m_pkTexture->GetType() == Texture::CUBEMAPFBO ){
Activator::Activate();
m_pkDevice->SetCullMode( m_pkDevice->m_eCullMode );
int index=m_eCurCubemapFace;
// bind offscreen buffer
neoglBindFramebufferEXT(GL_FRAMEBUFFER_EXT,
m_iCubeMapBufObj[index] );
// attach texture
neoglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
GL_COLOR_ATTACHMENT0_EXT,
GL_TEXTURE_CUBE_MAP_POSITIVE_X+index,m_pkTexture->GetID(),0);
// initialize depth renderbuffer
neoglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_iDepthBufObj);
neoglRenderbufferStorageEXT(GL_RENDERBUFFER_EXT,
GL_DEPTH_COMPONENT24, m_uiWidth, m_uiHeight);
neoglFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,
GL_DEPTH_ATTACHMENT_EXT,
GL_RENDERBUFFER_EXT, m_iDepthBufObj);
// set viewport with FBO flag true
m_pkDevice->SetViewport( 0, 0, m_uiWidth, m_uiHeight, true );
// set the texture as render target
glDrawBuffer (GL_COLOR_ATTACHMENT0_EXT);
return;
}
}
void PixelBuffer::GrabTexture()
{
if( m_pkTexture )
{
//Copy texture data
m_pkDevice->m_ppkTMU[0]->SetTexture( (NeoOGL::Texture*)(NeoEngine::Texture*)m_pkTexture );
GLenum eTarget = GL_TEXTURE_2D;
if( m_pkTexture->GetType() == Texture::CUBEMAP )
eTarget = Texture::s_aeOGLCubeFaces[ m_eCurCubemapFace ];
glCopyTexSubImage2D( eTarget, 0, 0, 0, 0, m_pkDevice->GetHeight() - m_uiHeight, m_uiWidth, m_uiHeight );
}
}
}; // namespace NeoOGL
See more files for this project here