Add OpenGL support.

This commit is contained in:
LuisAntonRebollo 2014-11-08 17:41:17 +01:00
parent c354f59b72
commit dd08fd2e7d
55 changed files with 2957 additions and 802 deletions

View file

@ -267,6 +267,8 @@ GFXDevice::~GFXDevice()
mNewCubemap[i] = NULL; mNewCubemap[i] = NULL;
} }
mCurrentRT = NULL;
// Release all the unreferenced textures in the cache. // Release all the unreferenced textures in the cache.
mTextureManager->cleanupCache(); mTextureManager->cleanupCache();

View file

@ -89,6 +89,11 @@ struct GFXSamplerStateDesc
/// Returns an modulate, clamp, and point sampled state. /// Returns an modulate, clamp, and point sampled state.
static GFXSamplerStateDesc getClampPoint(); static GFXSamplerStateDesc getClampPoint();
bool operator==(const GFXSamplerStateDesc &b) const
{
return !dMemcmp(this, &b, sizeof(GFXSamplerStateDesc));
}
}; };
/// GFXStateBlockDesc defines a render state, which is then used to create a GFXStateBlock instance. /// GFXStateBlockDesc defines a render state, which is then used to create a GFXStateBlock instance.

View file

@ -24,7 +24,7 @@
#define _GFXGLAPPLEFENCE_H_ #define _GFXGLAPPLEFENCE_H_
#include "gfx/gfxFence.h" #include "gfx/gfxFence.h"
#include "gfx/gl/ggl/ggl.h" #include "gfx/gl/tGL/tGL.h"
class GFXGLAppleFence : public GFXFence class GFXGLAppleFence : public GFXFence
{ {

View file

@ -76,30 +76,30 @@ void GFXGLCardProfiler::setupCardCapabilities()
setCapability("maxTextureSize", maxTexSize); setCapability("maxTextureSize", maxTexSize);
// If extensions haven't been inited, we're in trouble here. // If extensions haven't been inited, we're in trouble here.
bool suppVBO = (gglHasExtension(GL_ARB_vertex_buffer_object) || glVersion >= 1.499f); bool suppVBO = (gglHasExtension(ARB_vertex_buffer_object) || glVersion >= 1.499f);
setCapability("GL::suppVertexBufferObject", suppVBO); setCapability("GL::suppVertexBufferObject", suppVBO);
// check if render to texture supported is available // check if render to texture supported is available
bool suppRTT = gglHasExtension(GL_EXT_framebuffer_object); bool suppRTT = gglHasExtension(EXT_framebuffer_object);
setCapability("GL::suppRenderTexture", suppRTT); setCapability("GL::suppRenderTexture", suppRTT);
bool suppBlit = gglHasExtension(GL_EXT_framebuffer_blit); bool suppBlit = gglHasExtension(EXT_framebuffer_blit);
setCapability("GL::suppRTBlit", suppBlit); setCapability("GL::suppRTBlit", suppBlit);
bool suppFloatTex = gglHasExtension(GL_ATI_texture_float); bool suppFloatTex = gglHasExtension(ARB_texture_float);
setCapability("GL::suppFloatTexture", suppFloatTex); setCapability("GL::suppFloatTexture", suppFloatTex);
// Check for anisotropic filtering support. // Check for anisotropic filtering support.
bool suppAnisotropic = gglHasExtension( GL_EXT_texture_filter_anisotropic ); bool suppAnisotropic = gglHasExtension( EXT_texture_filter_anisotropic );
setCapability( "GL::suppAnisotropic", suppAnisotropic ); setCapability( "GL::suppAnisotropic", suppAnisotropic );
// check to see if we have the fragment shader extension or the gl version is high enough for glsl to be core // check to see if we have the fragment shader extension or the gl version is high enough for glsl to be core
// also check to see if the language version is high enough // also check to see if the language version is high enough
F32 glslVersion = dAtof(reinterpret_cast<const char*>(glGetString( GL_SHADING_LANGUAGE_VERSION))); F32 glslVersion = dAtof(reinterpret_cast<const char*>(glGetString( GL_SHADING_LANGUAGE_VERSION)));
bool suppSPU = (gglHasExtension(GL_ARB_fragment_shader) || glVersion >= 1.999f) && glslVersion >= 1.0999; bool suppSPU = (gglHasExtension(ARB_fragment_shader) || glVersion >= 1.999f) && glslVersion >= 1.0999;
setCapability("GL::suppFragmentShader", suppSPU); setCapability("GL::suppFragmentShader", suppSPU);
bool suppAppleFence = gglHasExtension(GL_APPLE_fence); bool suppAppleFence = gglHasExtension(APPLE_fence);
setCapability("GL::APPLE::suppFence", suppAppleFence); setCapability("GL::APPLE::suppFence", suppAppleFence);
// When enabled, call glGenerateMipmapEXT() to generate mipmaps instead of relying on GL_GENERATE_MIPMAP // When enabled, call glGenerateMipmapEXT() to generate mipmaps instead of relying on GL_GENERATE_MIPMAP

View file

@ -0,0 +1,289 @@
#ifndef GL_CIRCULAR_VOLATILE_BUFFER_H
#define GL_CIRCULAR_VOLATILE_BUFFER_H
#include "gfx/gl/gfxGLDevice.h"
#include "gfx/gl/gfxGLUtils.h"
class GLFenceRange
{
public:
GLFenceRange() : mStart(0), mEnd(0), mSync(0)
{
}
~GLFenceRange()
{
AssertFatal( mSync == 0, "");
}
void init(U32 start, U32 end)
{
mStart = start;
mEnd = end;
mSync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
}
bool checkOverlap(U32 start, U32 end)
{
if( mStart < end && start < mEnd )
return true;
return false;
}
void wait()
{
GLbitfield waitFlags = 0;
GLuint64 waitDuration = 0;
while( 1 )
{
GLenum waitRet = glClientWaitSync( mSync, waitFlags, waitDuration );
if( waitRet == GL_ALREADY_SIGNALED || waitRet == GL_CONDITION_SATISFIED )
{
break;
}
if( waitRet == GL_WAIT_FAILED )
{
AssertFatal(0, "GLSync failed.");
break;
}
waitFlags = GL_SYNC_FLUSH_COMMANDS_BIT;
waitDuration = scOneSecondInNanoSeconds;
}
glDeleteSync(mSync);
mSync = 0;
}
void swap( GLFenceRange &r )
{
GLFenceRange temp;
temp = *this;
*this = r;
r = temp;
}
protected:
U32 mStart, mEnd;
GLsync mSync;
static const GLuint64 scOneSecondInNanoSeconds = 1000000000;
GLFenceRange( const GLFenceRange &);
GLFenceRange& operator=(const GLFenceRange &r)
{
mStart = r.mStart;
mEnd = r.mEnd;
mSync = r.mSync;
return *this;
}
};
class GLOrderedFenceRangeManager
{
public:
~GLOrderedFenceRangeManager( )
{
waitAllRanges( );
}
void protectOrderedRange( U32 start, U32 end )
{
mFenceRanges.increment();
GLFenceRange &range = mFenceRanges.last();
range.init( start, end );
}
void waitFirstRange( U32 start, U32 end )
{
if( !mFenceRanges.size() || !mFenceRanges[0].checkOverlap( start, end ) )
return;
mFenceRanges[0].wait();
mFenceRanges.pop_front();
}
void waitOverlapRanges( U32 start, U32 end )
{
for( U32 i = 0; i < mFenceRanges.size(); ++i )
{
if( !mFenceRanges[i].checkOverlap( start, end ) )
continue;
mFenceRanges[i].wait();
mFenceRanges.erase(i);
}
}
void waitAllRanges()
{
for( int i = 0; i < mFenceRanges.size(); ++i )
mFenceRanges[i].wait();
mFenceRanges.clear();
}
protected:
Vector<GLFenceRange> mFenceRanges;
};
class GLCircularVolatileBuffer
{
public:
GLCircularVolatileBuffer(GLuint binding)
: mBinding(binding), mBufferName(0), mBufferPtr(NULL), mBufferSize(0), mBufferFreePos(0), mCurrectUsedRangeStart(0)
{
init();
}
void init()
{
glGenBuffers(1, &mBufferName);
PRESERVE_VERTEX_BUFFER();
glBindBuffer(mBinding, mBufferName);
const U32 cSizeInMB = 10;
mBufferSize = (cSizeInMB << 20);
if( gglHasExtension(ARB_buffer_storage) )
{
const GLbitfield flags = GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT;
glBufferStorage(mBinding, mBufferSize, NULL, flags);
mBufferPtr = glMapBufferRange(mBinding, 0, mBufferSize, flags);
}
else
{
glBufferData(mBinding, mBufferSize, NULL, GL_DYNAMIC_DRAW);
}
}
struct
{
U32 mOffset, mSize;
}_getBufferData;
void lock(const U32 size, U32 offsetAlign, U32 &outOffset, void* &outPtr)
{
if( !size )
{
AssertFatal(0, "");
outOffset = 0;
outPtr = NULL;
}
mLockManager.waitFirstRange( mBufferFreePos, (mBufferFreePos + size)-1 );
if( mBufferFreePos + size > mBufferSize )
{
mUsedRanges.push_back( UsedRange( mBufferFreePos, mBufferSize-1 ) );
mBufferFreePos = 0;
}
// force offset buffer align
if( offsetAlign )
mBufferFreePos = ( (mBufferFreePos/offsetAlign) + 1 ) * offsetAlign;
outOffset = mBufferFreePos;
if( gglHasExtension(ARB_buffer_storage) )
{
outPtr = (U8*)(mBufferPtr) + mBufferFreePos;
}
else if( GFXGL->glUseMap() )
{
PRESERVE_VERTEX_BUFFER();
glBindBuffer(GL_ARRAY_BUFFER, mBufferName);
const GLbitfield access = GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
outPtr = glMapBufferRange(GL_ARRAY_BUFFER, outOffset, size, access);
}
else
{
_getBufferData.mOffset = outOffset;
_getBufferData.mSize = size;
outPtr = mFrameAllocator.lock( size );
}
//set new buffer pos
mBufferFreePos = mBufferFreePos + size;
//align 4bytes
mBufferFreePos = ( (mBufferFreePos/4) + 1 ) * 4;
}
void unlock()
{
if( gglHasExtension(ARB_buffer_storage) )
{
return;
}
else if( GFXGL->glUseMap() )
{
PRESERVE_VERTEX_BUFFER();
glBindBuffer(GL_ARRAY_BUFFER, mBufferName);
glUnmapBuffer(GL_ARRAY_BUFFER);
}
else
{
PRESERVE_VERTEX_BUFFER();
glBindBuffer(GL_ARRAY_BUFFER, mBufferName);
glBufferSubData( mBinding, _getBufferData.mOffset, _getBufferData.mSize, mFrameAllocator.getlockedPtr() );
_getBufferData.mOffset = 0;
_getBufferData.mSize = 0;
mFrameAllocator.unlock();
}
}
U32 getHandle() const { return mBufferName; }
void protectUsedRange()
{
for( int i = 0; i < mUsedRanges.size(); ++i )
{
mLockManager.protectOrderedRange( mUsedRanges[i].start, mUsedRanges[i].end );
}
mUsedRanges.clear();
if( mCurrectUsedRangeStart < mBufferFreePos )
{
mLockManager.protectOrderedRange( mCurrectUsedRangeStart, mBufferFreePos-1 );
mCurrectUsedRangeStart = mBufferFreePos;
}
}
protected:
GLuint mBinding;
GLuint mBufferName;
void *mBufferPtr;
U32 mBufferSize;
U32 mBufferFreePos;
U32 mCurrectUsedRangeStart;
GLOrderedFenceRangeManager mLockManager;
FrameAllocatorLockableHelper mFrameAllocator;
struct UsedRange
{
UsedRange(U32 _start = 0, U32 _end = 0)
: start(_start), end(_end)
{
}
U32 start, end;
};
Vector<UsedRange> mUsedRanges;
};
#endif

View file

@ -27,7 +27,7 @@
#include "gfx/gl/gfxGLCubemap.h" #include "gfx/gl/gfxGLCubemap.h"
#include "gfx/gfxTextureManager.h" #include "gfx/gfxTextureManager.h"
#include "gfx/gfxCardProfile.h" #include "gfx/gfxCardProfile.h"
#include "gfx/bitmap/DDSFile.h" #include "gfx/bitmap/ddsFile.h"
GLenum GFXGLCubemap::faceList[6] = GLenum GFXGLCubemap::faceList[6] =
@ -56,9 +56,9 @@ GFXGLCubemap::~GFXGLCubemap()
void GFXGLCubemap::fillCubeTextures(GFXTexHandle* faces) void GFXGLCubemap::fillCubeTextures(GFXTexHandle* faces)
{ {
glActiveTexture(GL_TEXTURE0); PRESERVE_CUBEMAP_TEXTURE();
glBindTexture(GL_TEXTURE_CUBE_MAP, mCubemap); glBindTexture(GL_TEXTURE_CUBE_MAP, mCubemap);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_GENERATE_MIPMAP, GL_TRUE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, 0 ); // TODO OPENGL GFXGLCubemap mipmaps
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
@ -89,9 +89,6 @@ void GFXGLCubemap::fillCubeTextures(GFXTexHandle* faces)
0, GFXGLTextureFormat[faceFormat], GFXGLTextureType[faceFormat], buf); 0, GFXGLTextureFormat[faceFormat], GFXGLTextureType[faceFormat], buf);
delete[] buf; delete[] buf;
} }
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
} }
void GFXGLCubemap::initStatic(GFXTexHandle* faces) void GFXGLCubemap::initStatic(GFXTexHandle* faces)
@ -128,9 +125,9 @@ void GFXGLCubemap::initStatic( DDSFile *dds )
glGenTextures(1, &mCubemap); glGenTextures(1, &mCubemap);
glActiveTexture(GL_TEXTURE0); PRESERVE_CUBEMAP_TEXTURE();
glBindTexture(GL_TEXTURE_CUBE_MAP, mCubemap); glBindTexture(GL_TEXTURE_CUBE_MAP, mCubemap);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_GENERATE_MIPMAP, GL_TRUE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, 0 );
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
@ -162,9 +159,6 @@ void GFXGLCubemap::initStatic( DDSFile *dds )
glCompressedTexImage2D( faceList[i], 0, GFXGLTextureInternalFormat[mFaceFormat], glCompressedTexImage2D( faceList[i], 0, GFXGLTextureInternalFormat[mFaceFormat],
mWidth, mHeight, 0, surfaceSize, buffer ); mWidth, mHeight, 0, surfaceSize, buffer );
} }
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
} }
void GFXGLCubemap::initDynamic(U32 texSize, GFXFormat faceFormat) void GFXGLCubemap::initDynamic(U32 texSize, GFXFormat faceFormat)
@ -173,6 +167,7 @@ void GFXGLCubemap::initDynamic(U32 texSize, GFXFormat faceFormat)
mFaceFormat = faceFormat; mFaceFormat = faceFormat;
glGenTextures(1, &mCubemap); glGenTextures(1, &mCubemap);
PRESERVE_CUBEMAP_TEXTURE();
glBindTexture(GL_TEXTURE_CUBE_MAP, mCubemap); glBindTexture(GL_TEXTURE_CUBE_MAP, mCubemap);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
@ -187,7 +182,6 @@ void GFXGLCubemap::initDynamic(U32 texSize, GFXFormat faceFormat)
glTexImage2D( faceList[i], 0, GFXGLTextureInternalFormat[faceFormat], texSize, texSize, glTexImage2D( faceList[i], 0, GFXGLTextureInternalFormat[faceFormat], texSize, texSize,
0, GFXGLTextureFormat[faceFormat], GFXGLTextureType[faceFormat], NULL); 0, GFXGLTextureFormat[faceFormat], GFXGLTextureType[faceFormat], NULL);
} }
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
} }
void GFXGLCubemap::zombify() void GFXGLCubemap::zombify()
@ -223,6 +217,7 @@ void GFXGLCubemap::bind(U32 textureUnit) const
{ {
glActiveTexture(GL_TEXTURE0 + textureUnit); glActiveTexture(GL_TEXTURE0 + textureUnit);
glBindTexture(GL_TEXTURE_CUBE_MAP, mCubemap); glBindTexture(GL_TEXTURE_CUBE_MAP, mCubemap);
static_cast<GFXGLDevice*>(getOwningDevice())->getOpenglCache()->setCacheBindedTex(textureUnit, GL_TEXTURE_CUBE_MAP, mCubemap);
GFXGLStateBlockRef sb = static_cast<GFXGLDevice*>(GFX)->getCurrentStateBlock(); GFXGLStateBlockRef sb = static_cast<GFXGLDevice*>(GFX)->getCurrentStateBlock();
AssertFatal(sb, "GFXGLCubemap::bind - No active stateblock!"); AssertFatal(sb, "GFXGLCubemap::bind - No active stateblock!");
@ -235,8 +230,6 @@ void GFXGLCubemap::bind(U32 textureUnit) const
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GFXGLTextureAddress[ssd.addressModeU]); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GFXGLTextureAddress[ssd.addressModeU]);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GFXGLTextureAddress[ssd.addressModeV]); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GFXGLTextureAddress[ssd.addressModeV]);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GFXGLTextureAddress[ssd.addressModeW]); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GFXGLTextureAddress[ssd.addressModeW]);
glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, ssd.mipLODBias);
} }
void GFXGLCubemap::_onTextureEvent( GFXTexCallbackCode code ) void GFXGLCubemap::_onTextureEvent( GFXTexCallbackCode code )

View file

@ -22,6 +22,7 @@
#include "platform/platform.h" #include "platform/platform.h"
#include "gfx/gl/gfxGLDevice.h" #include "gfx/gl/gfxGLDevice.h"
#include "platform/platformGL.h"
#include "gfx/gfxCubemap.h" #include "gfx/gfxCubemap.h"
#include "gfx/screenshot.h" #include "gfx/screenshot.h"
@ -36,12 +37,15 @@
#include "gfx/gl/gfxGLCubemap.h" #include "gfx/gl/gfxGLCubemap.h"
#include "gfx/gl/gfxGLCardProfiler.h" #include "gfx/gl/gfxGLCardProfiler.h"
#include "gfx/gl/gfxGLWindowTarget.h" #include "gfx/gl/gfxGLWindowTarget.h"
#include "gfx/gl/ggl/ggl.h"
#include "platform/platformDlibrary.h" #include "platform/platformDlibrary.h"
#include "gfx/gl/gfxGLShader.h" #include "gfx/gl/gfxGLShader.h"
#include "gfx/primBuilder.h" #include "gfx/primBuilder.h"
#include "console/console.h" #include "console/console.h"
#include "gfx/gl/gfxGLOcclusionQuery.h" #include "gfx/gl/gfxGLOcclusionQuery.h"
#include "materials/shaderData.h"
#include "gfx/gl/gfxGLStateCache.h"
#include "gfx/gl/gfxGLVertexAttribLocation.h"
#include "gfx/gl/gfxGLVertexDecl.h"
GFXAdapter::CreateDeviceInstanceDelegate GFXGLDevice::mCreateDeviceInstance(GFXGLDevice::createInstance); GFXAdapter::CreateDeviceInstanceDelegate GFXGLDevice::mCreateDeviceInstance(GFXGLDevice::createInstance);
@ -77,6 +81,23 @@ void loadGLExtensions(void *context)
GL::gglPerformExtensionBinds(context); GL::gglPerformExtensionBinds(context);
} }
void STDCALL glDebugCallback(GLenum source, GLenum type, GLuint id,
GLenum severity, GLsizei length, const GLchar* message, void* userParam)
{
#if defined(TORQUE_DEBUG) && !defined(TORQUE_DEBUG_GFX)
if( type == GL_DEBUG_TYPE_OTHER_ARB )
return;
#endif
Con::errorf("OPENGL: %s", message);
}
void STDCALL glAmdDebugCallback(GLuint id, GLenum category, GLenum severity, GLsizei length,
const GLchar* message,GLvoid* userParam)
{
Con::errorf("OPENGL: %s",message);
}
void GFXGLDevice::initGLState() void GFXGLDevice::initGLState()
{ {
// We don't currently need to sync device state with a known good place because we are // We don't currently need to sync device state with a known good place because we are
@ -88,29 +109,56 @@ void GFXGLDevice::initGLState()
mCardProfiler->init(); mCardProfiler->init();
glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, (GLint*)&mMaxShaderTextures); glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, (GLint*)&mMaxShaderTextures);
glGetIntegerv(GL_MAX_TEXTURE_UNITS, (GLint*)&mMaxFFTextures); glGetIntegerv(GL_MAX_TEXTURE_UNITS, (GLint*)&mMaxFFTextures);
glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, (GLint*)&mMaxTRColors);
mMaxTRColors = getMin( mMaxTRColors, (U32)(GFXTextureTarget::MaxRenderSlotId-1) );
glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
// Apple's drivers lie and claim that everything supports fragment shaders. Conveniently they don't lie about the number // Setting mPixelShaderVersion to 3.0 will allow Advanced Lighting to run.
// of supported image units. Checking for 16 or more image units ensures that we don't try and use pixel shaders on mPixelShaderVersion = 3.0;
// cards which don't support them.
if(mCardProfiler->queryProfile("GL::suppFragmentShader") && mMaxShaderTextures >= 16)
mPixelShaderVersion = 2.0f;
else
mPixelShaderVersion = 0.0f;
// MACHAX - Setting mPixelShaderVersion to 3.0 will allow Advanced Lighting
// to run. At the time of writing (6/18) it doesn't quite work yet.
if(Con::getBoolVariable("$pref::machax::enableAdvancedLighting", false))
mPixelShaderVersion = 3.0f;
mSupportsAnisotropic = mCardProfiler->queryProfile( "GL::suppAnisotropic" ); mSupportsAnisotropic = mCardProfiler->queryProfile( "GL::suppAnisotropic" );
String vendorStr = (const char*)glGetString( GL_VENDOR );
if( vendorStr.find("NVIDIA") != String::NPos)
mUseGlMap = false;
#if TORQUE_DEBUG
if( gglHasExtension(ARB_debug_output) )
{
glEnable(GL_DEBUG_OUTPUT);
glDebugMessageCallbackARB(glDebugCallback, NULL);
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
GLuint unusedIds = 0;
glDebugMessageControlARB(GL_DONT_CARE,
GL_DONT_CARE,
GL_DONT_CARE,
0,
&unusedIds,
GL_TRUE);
}
else if(gglHasExtension(AMD_debug_output))
{
glEnable(GL_DEBUG_OUTPUT);
glDebugMessageCallbackAMD(glAmdDebugCallback, NULL);
//glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
GLuint unusedIds = 0;
glDebugMessageEnableAMD(GL_DONT_CARE, GL_DONT_CARE, 0,&unusedIds, GL_TRUE);
}
#endif
PlatformGL::setVSync(0);
//OpenGL 3 need a binded VAO for render
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
} }
GFXGLDevice::GFXGLDevice(U32 adapterIndex) : GFXGLDevice::GFXGLDevice(U32 adapterIndex) :
mAdapterIndex(adapterIndex), mAdapterIndex(adapterIndex),
mCurrentVB(NULL),
mCurrentPB(NULL), mCurrentPB(NULL),
mDrawInstancesCount(0),
m_mCurrentWorld(true), m_mCurrentWorld(true),
m_mCurrentView(true), m_mCurrentView(true),
mContext(NULL), mContext(NULL),
@ -118,33 +166,74 @@ GFXGLDevice::GFXGLDevice(U32 adapterIndex) :
mPixelShaderVersion(0.0f), mPixelShaderVersion(0.0f),
mMaxShaderTextures(2), mMaxShaderTextures(2),
mMaxFFTextures(2), mMaxFFTextures(2),
mClip(0, 0, 0, 0) mMaxTRColors(1),
mClip(0, 0, 0, 0),
mCurrentShader( NULL ),
mNeedUpdateVertexAttrib(false),
mWindowRT(NULL),
mUseGlMap(true)
{ {
for(int i = 0; i < VERTEX_STREAM_COUNT; ++i)
{
mCurrentVB[i] = NULL;
mCurrentVB_Divisor[i] = 0;
}
loadGLCore(); loadGLCore();
GFXGLEnumTranslate::init(); GFXGLEnumTranslate::init();
GFXVertexColor::setSwizzle( &Swizzles::rgba ); GFXVertexColor::setSwizzle( &Swizzles::rgba );
mDeviceSwizzle32 = &Swizzles::bgra;
mDeviceSwizzle24 = &Swizzles::bgr; // OpenGL have native RGB, no need swizzle
mDeviceSwizzle32 = &Swizzles::rgba;
mDeviceSwizzle24 = &Swizzles::rgb;
mTextureManager = new GFXGLTextureManager(); mTextureManager = new GFXGLTextureManager();
gScreenShot = new ScreenShot(); gScreenShot = new ScreenShot();
for(U32 i = 0; i < TEXTURE_STAGE_COUNT; i++) for(U32 i = 0; i < TEXTURE_STAGE_COUNT; i++)
mActiveTextureType[i] = GL_ZERO; mActiveTextureType[i] = GL_ZERO;
mNumVertexStream = 2;
for(int i = 0; i < GS_COUNT; ++i)
mModelViewProjSC[i] = NULL;
mOpenglStateCache = new GFXGLStateCache;
} }
GFXGLDevice::~GFXGLDevice() GFXGLDevice::~GFXGLDevice()
{ {
mCurrentStateBlock = NULL; mCurrentStateBlock = NULL;
for(int i = 0; i < VERTEX_STREAM_COUNT; ++i)
mCurrentVB[i] = NULL;
mCurrentPB = NULL; mCurrentPB = NULL;
mCurrentVB = NULL;
for(U32 i = 0; i < mVolatileVBs.size(); i++) for(U32 i = 0; i < mVolatileVBs.size(); i++)
mVolatileVBs[i] = NULL; mVolatileVBs[i] = NULL;
for(U32 i = 0; i < mVolatilePBs.size(); i++) for(U32 i = 0; i < mVolatilePBs.size(); i++)
mVolatilePBs[i] = NULL; mVolatilePBs[i] = NULL;
// Clear out our current texture references
for (U32 i = 0; i < TEXTURE_STAGE_COUNT; i++)
{
mCurrentTexture[i] = NULL;
mNewTexture[i] = NULL;
mCurrentCubemap[i] = NULL;
mNewCubemap[i] = NULL;
}
mRTStack.clear();
mCurrentRT = NULL;
if( mTextureManager )
{
mTextureManager->zombify();
mTextureManager->kill();
}
GFXResource* walk = mResourceListHead; GFXResource* walk = mResourceListHead;
while(walk) while(walk)
{ {
@ -156,15 +245,20 @@ GFXGLDevice::~GFXGLDevice()
SAFE_DELETE( mCardProfiler ); SAFE_DELETE( mCardProfiler );
SAFE_DELETE( gScreenShot ); SAFE_DELETE( gScreenShot );
SAFE_DELETE( mOpenglStateCache );
} }
void GFXGLDevice::zombify() void GFXGLDevice::zombify()
{ {
mTextureManager->zombify(); mTextureManager->zombify();
if(mCurrentVB)
mCurrentVB->finish(); for(int i = 0; i < VERTEX_STREAM_COUNT; ++i)
if(mCurrentVB[i])
mCurrentVB[i]->finish();
if(mCurrentPB) if(mCurrentPB)
mCurrentPB->finish(); mCurrentPB->finish();
//mVolatileVBs.clear(); //mVolatileVBs.clear();
//mVolatilePBs.clear(); //mVolatilePBs.clear();
GFXResource* walk = mResourceListHead; GFXResource* walk = mResourceListHead;
@ -183,10 +277,12 @@ void GFXGLDevice::resurrect()
walk->resurrect(); walk->resurrect();
walk = walk->getNextResource(); walk = walk->getNextResource();
} }
if(mCurrentVB) for(int i = 0; i < VERTEX_STREAM_COUNT; ++i)
mCurrentVB->prepare(); if(mCurrentVB[i])
mCurrentVB[i]->prepare();
if(mCurrentPB) if(mCurrentPB)
mCurrentPB->prepare(); mCurrentPB->prepare();
mTextureManager->resurrect(); mTextureManager->resurrect();
} }
@ -244,20 +340,39 @@ GFXPrimitiveBuffer *GFXGLDevice::allocPrimitiveBuffer( U32 numIndices, U32 numPr
void GFXGLDevice::setVertexStream( U32 stream, GFXVertexBuffer *buffer ) void GFXGLDevice::setVertexStream( U32 stream, GFXVertexBuffer *buffer )
{ {
AssertFatal( stream == 0, "GFXGLDevice::setVertexStream - We don't support multiple vertex streams!" ); AssertFatal(stream <= 1, "GFXGLDevice::setVertexStream only support 2 stream (0: data, 1: instancing)");
// Reset the state the old VB required, then set the state the new VB requires. //if(mCurrentVB[stream] != buffer)
if ( mCurrentVB ) {
mCurrentVB->finish(); // Reset the state the old VB required, then set the state the new VB requires.
if( mCurrentVB[stream] )
{
mCurrentVB[stream]->finish();
}
mCurrentVB = static_cast<GFXGLVertexBuffer*>( buffer ); mCurrentVB[stream] = static_cast<GFXGLVertexBuffer*>( buffer );
if ( mCurrentVB )
mCurrentVB->prepare(); mNeedUpdateVertexAttrib = true;
}
} }
void GFXGLDevice::setVertexStreamFrequency( U32 stream, U32 frequency ) void GFXGLDevice::setVertexStreamFrequency( U32 stream, U32 frequency )
{ {
// We don't support vertex stream frequency or mesh instancing in OGL yet. if( stream == 0 )
{
mCurrentVB_Divisor[stream] = 0; // non instanced, is vertex buffer
mDrawInstancesCount = frequency; // instances count
}
else
{
AssertFatal(frequency <= 1, "GFXGLDevice::setVertexStreamFrequency only support 0/1 for this stream" );
if( stream == 1 && frequency == 1 )
mCurrentVB_Divisor[stream] = 1; // instances data need a frequency of 1
else
mCurrentVB_Divisor[stream] = 0;
}
mNeedUpdateVertexAttrib = true;
} }
GFXCubemap* GFXGLDevice::createCubemap() GFXCubemap* GFXGLDevice::createCubemap()
@ -278,14 +393,24 @@ void GFXGLDevice::clear(U32 flags, ColorI color, F32 z, U32 stencil)
// Make sure we have flushed our render target state. // Make sure we have flushed our render target state.
_updateRenderTargets(); _updateRenderTargets();
bool zwrite = true; bool writeAllColors = true;
bool zwrite = true;
bool writeAllStencil = true;
const GFXStateBlockDesc *desc = NULL;
if (mCurrentGLStateBlock) if (mCurrentGLStateBlock)
{ {
zwrite = mCurrentGLStateBlock->getDesc().zWriteEnable; desc = &mCurrentGLStateBlock->getDesc();
} zwrite = desc->zWriteEnable;
writeAllColors = desc->colorWriteRed && desc->colorWriteGreen && desc->colorWriteBlue && desc->colorWriteAlpha;
writeAllStencil = desc->stencilWriteMask == 0xFFFFFFFF;
}
glColorMask(true, true, true, true);
glDepthMask(true); glDepthMask(true);
ColorF c = color; glStencilMask(0xFFFFFFFF);
ColorF c = color;
glClearColor(c.red, c.green, c.blue, c.alpha); glClearColor(c.red, c.green, c.blue, c.alpha);
glClearDepth(z); glClearDepth(z);
glClearStencil(stencil); glClearStencil(stencil);
@ -296,13 +421,19 @@ void GFXGLDevice::clear(U32 flags, ColorI color, F32 z, U32 stencil)
clearflags |= (flags & GFXClearStencil) ? GL_STENCIL_BUFFER_BIT : 0; clearflags |= (flags & GFXClearStencil) ? GL_STENCIL_BUFFER_BIT : 0;
glClear(clearflags); glClear(clearflags);
if(!writeAllColors)
glColorMask(desc->colorWriteRed, desc->colorWriteGreen, desc->colorWriteBlue, desc->colorWriteAlpha);
if(!zwrite) if(!zwrite)
glDepthMask(false); glDepthMask(false);
if(!writeAllStencil)
glStencilMask(desc->stencilWriteMask);
} }
// Given a primitive type and a number of primitives, return the number of indexes/vertexes used. // Given a primitive type and a number of primitives, return the number of indexes/vertexes used.
GLsizei GFXGLDevice::primCountToIndexCount(GFXPrimitiveType primType, U32 primitiveCount) inline GLsizei GFXGLDevice::primCountToIndexCount(GFXPrimitiveType primType, U32 primitiveCount)
{ {
switch (primType) switch (primType)
{ {
@ -332,6 +463,24 @@ GLsizei GFXGLDevice::primCountToIndexCount(GFXPrimitiveType primType, U32 primit
return 0; return 0;
} }
GFXVertexDecl* GFXGLDevice::allocVertexDecl( const GFXVertexFormat *vertexFormat )
{
typedef Map<void*, GFXGLVertexDecl> GFXGLVertexDeclMap;
static GFXGLVertexDeclMap declMap;
GFXGLVertexDeclMap::Iterator itr = declMap.find( (void*)vertexFormat->getDescription().c_str() ); // description string are interned, safe to use c_str()
if(itr != declMap.end())
return &itr->value;
GFXGLVertexDecl &decl = declMap[(void*)vertexFormat->getDescription().c_str()];
decl.init(vertexFormat);
return &decl;
}
void GFXGLDevice::setVertexDecl( const GFXVertexDecl *decl )
{
static_cast<const GFXGLVertexDecl*>(decl)->prepareVertexFormat();
}
inline void GFXGLDevice::preDrawPrimitive() inline void GFXGLDevice::preDrawPrimitive()
{ {
if( mStateDirty ) if( mStateDirty )
@ -341,6 +490,25 @@ inline void GFXGLDevice::preDrawPrimitive()
if(mCurrentShaderConstBuffer) if(mCurrentShaderConstBuffer)
setShaderConstBufferInternal(mCurrentShaderConstBuffer); setShaderConstBufferInternal(mCurrentShaderConstBuffer);
if( mNeedUpdateVertexAttrib )
{
AssertFatal(mCurrVertexDecl, "");
const GFXGLVertexDecl* decl = static_cast<const GFXGLVertexDecl*>(mCurrVertexDecl);
for(int i = 0; i < getNumVertexStreams(); ++i)
{
if(mCurrentVB[i])
{
mCurrentVB[i]->prepare(i, mCurrentVB_Divisor[i]); // GL_ARB_vertex_attrib_binding
decl->prepareBuffer_old( i, mCurrentVB[i]->mBuffer, mCurrentVB_Divisor[i] ); // old vertex buffer/format
}
}
decl->updateActiveVertexAttrib( GFXGL->getOpenglCache()->getCacheVertexAttribActive() );
}
mNeedUpdateVertexAttrib = false;
} }
inline void GFXGLDevice::postDrawPrimitive(U32 primitiveCount) inline void GFXGLDevice::postDrawPrimitive(U32 primitiveCount)
@ -352,16 +520,13 @@ inline void GFXGLDevice::postDrawPrimitive(U32 primitiveCount)
void GFXGLDevice::drawPrimitive( GFXPrimitiveType primType, U32 vertexStart, U32 primitiveCount ) void GFXGLDevice::drawPrimitive( GFXPrimitiveType primType, U32 vertexStart, U32 primitiveCount )
{ {
preDrawPrimitive(); preDrawPrimitive();
// There are some odd performance issues if a buffer is bound to GL_ELEMENT_ARRAY_BUFFER when glDrawArrays is called. Unbinding the buffer vertexStart += mCurrentVB[0]->mBufferVertexOffset;
// improves performance by 10%.
if(mCurrentPB)
mCurrentPB->finish();
glDrawArrays(GFXGLPrimType[primType], vertexStart, primCountToIndexCount(primType, primitiveCount)); if(mDrawInstancesCount)
glDrawArraysInstanced(GFXGLPrimType[primType], vertexStart, primCountToIndexCount(primType, primitiveCount), mDrawInstancesCount);
if(mCurrentPB) else
mCurrentPB->prepare(); glDrawArrays(GFXGLPrimType[primType], vertexStart, primCountToIndexCount(primType, primitiveCount));
postDrawPrimitive(primitiveCount); postDrawPrimitive(primitiveCount);
} }
@ -379,7 +544,12 @@ void GFXGLDevice::drawIndexedPrimitive( GFXPrimitiveType primType,
U16* buf = (U16*)static_cast<GFXGLPrimitiveBuffer*>(mCurrentPrimitiveBuffer.getPointer())->getBuffer() + startIndex; U16* buf = (U16*)static_cast<GFXGLPrimitiveBuffer*>(mCurrentPrimitiveBuffer.getPointer())->getBuffer() + startIndex;
glDrawElements(GFXGLPrimType[primType], primCountToIndexCount(primType, primitiveCount), GL_UNSIGNED_SHORT, buf); const U32 baseVertex = mCurrentVB[0]->mBufferVertexOffset;
if(mDrawInstancesCount)
glDrawElementsInstancedBaseVertex(GFXGLPrimType[primType], primCountToIndexCount(primType, primitiveCount), GL_UNSIGNED_SHORT, buf, mDrawInstancesCount, baseVertex);
else
glDrawElementsBaseVertex(GFXGLPrimType[primType], primCountToIndexCount(primType, primitiveCount), GL_UNSIGNED_SHORT, buf, baseVertex);
postDrawPrimitive(primitiveCount); postDrawPrimitive(primitiveCount);
} }
@ -393,53 +563,12 @@ void GFXGLDevice::setPB(GFXGLPrimitiveBuffer* pb)
void GFXGLDevice::setLightInternal(U32 lightStage, const GFXLightInfo light, bool lightEnable) void GFXGLDevice::setLightInternal(U32 lightStage, const GFXLightInfo light, bool lightEnable)
{ {
if(!lightEnable) // ONLY NEEDED ON FFP
{
glDisable(GL_LIGHT0 + lightStage);
return;
}
if(light.mType == GFXLightInfo::Ambient)
{
AssertFatal(false, "Instead of setting an ambient light you should set the global ambient color.");
return;
}
GLenum lightEnum = GL_LIGHT0 + lightStage;
glLightfv(lightEnum, GL_AMBIENT, (GLfloat*)&light.mAmbient);
glLightfv(lightEnum, GL_DIFFUSE, (GLfloat*)&light.mColor);
glLightfv(lightEnum, GL_SPECULAR, (GLfloat*)&light.mColor);
F32 pos[4];
if(light.mType != GFXLightInfo::Vector)
{
dMemcpy(pos, &light.mPos, sizeof(light.mPos));
pos[3] = 1.0;
}
else
{
dMemcpy(pos, &light.mDirection, sizeof(light.mDirection));
pos[3] = 0.0;
}
// Harcoded attenuation
glLightf(lightEnum, GL_CONSTANT_ATTENUATION, 1.0f);
glLightf(lightEnum, GL_LINEAR_ATTENUATION, 0.1f);
glLightf(lightEnum, GL_QUADRATIC_ATTENUATION, 0.0f);
glLightfv(lightEnum, GL_POSITION, (GLfloat*)&pos);
glEnable(lightEnum);
} }
void GFXGLDevice::setLightMaterialInternal(const GFXLightMaterial mat) void GFXGLDevice::setLightMaterialInternal(const GFXLightMaterial mat)
{ {
// CodeReview - Setting these for front and back is unnecessary. We should consider // ONLY NEEDED ON FFP
// checking what faces we're culling and setting this only for the unculled faces.
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (GLfloat*)&mat.ambient);
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (GLfloat*)&mat.diffuse);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (GLfloat*)&mat.specular);
glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (GLfloat*)&mat.emissive);
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, mat.shininess);
} }
void GFXGLDevice::setGlobalAmbientInternal(ColorF color) void GFXGLDevice::setGlobalAmbientInternal(ColorF color)
@ -449,91 +578,40 @@ void GFXGLDevice::setGlobalAmbientInternal(ColorF color)
void GFXGLDevice::setTextureInternal(U32 textureUnit, const GFXTextureObject*texture) void GFXGLDevice::setTextureInternal(U32 textureUnit, const GFXTextureObject*texture)
{ {
const GFXGLTextureObject *tex = static_cast<const GFXGLTextureObject*>(texture); GFXGLTextureObject *tex = static_cast<GFXGLTextureObject*>(const_cast<GFXTextureObject*>(texture));
glActiveTexture(GL_TEXTURE0 + textureUnit);
if (tex) if (tex)
{ {
// GFXGLTextureObject::bind also handles applying the current sampler state.
if(mActiveTextureType[textureUnit] != tex->getBinding() && mActiveTextureType[textureUnit] != GL_ZERO)
{
glBindTexture(mActiveTextureType[textureUnit], 0);
glDisable(mActiveTextureType[textureUnit]);
}
mActiveTextureType[textureUnit] = tex->getBinding(); mActiveTextureType[textureUnit] = tex->getBinding();
tex->bind(textureUnit); tex->bind(textureUnit);
} }
else if(mActiveTextureType[textureUnit] != GL_ZERO) else if(mActiveTextureType[textureUnit] != GL_ZERO)
{ {
glActiveTexture(GL_TEXTURE0 + textureUnit);
glBindTexture(mActiveTextureType[textureUnit], 0); glBindTexture(mActiveTextureType[textureUnit], 0);
glDisable(mActiveTextureType[textureUnit]); getOpenglCache()->setCacheBindedTex(textureUnit, mActiveTextureType[textureUnit], 0);
mActiveTextureType[textureUnit] = GL_ZERO; mActiveTextureType[textureUnit] = GL_ZERO;
} }
glActiveTexture(GL_TEXTURE0);
} }
void GFXGLDevice::setCubemapInternal(U32 textureUnit, const GFXGLCubemap* texture) void GFXGLDevice::setCubemapInternal(U32 textureUnit, const GFXGLCubemap* texture)
{ {
glActiveTexture(GL_TEXTURE0 + textureUnit);
if(texture) if(texture)
{ {
if(mActiveTextureType[textureUnit] != GL_TEXTURE_CUBE_MAP && mActiveTextureType[textureUnit] != GL_ZERO)
{
glBindTexture(mActiveTextureType[textureUnit], 0);
glDisable(mActiveTextureType[textureUnit]);
}
mActiveTextureType[textureUnit] = GL_TEXTURE_CUBE_MAP; mActiveTextureType[textureUnit] = GL_TEXTURE_CUBE_MAP;
texture->bind(textureUnit); texture->bind(textureUnit);
} }
else if(mActiveTextureType[textureUnit] != GL_ZERO) else if(mActiveTextureType[textureUnit] != GL_ZERO)
{ {
glActiveTexture(GL_TEXTURE0 + textureUnit);
glBindTexture(mActiveTextureType[textureUnit], 0); glBindTexture(mActiveTextureType[textureUnit], 0);
glDisable(mActiveTextureType[textureUnit]); getOpenglCache()->setCacheBindedTex(textureUnit, mActiveTextureType[textureUnit], 0);
mActiveTextureType[textureUnit] = GL_ZERO; mActiveTextureType[textureUnit] = GL_ZERO;
} }
glActiveTexture(GL_TEXTURE0);
} }
void GFXGLDevice::setMatrix( GFXMatrixType mtype, const MatrixF &mat ) void GFXGLDevice::setMatrix( GFXMatrixType mtype, const MatrixF &mat )
{ {
MatrixF modelview; // ONLY NEEDED ON FFP
switch (mtype)
{
case GFXMatrixWorld :
{
glMatrixMode(GL_MODELVIEW);
m_mCurrentWorld = mat;
modelview = m_mCurrentWorld;
modelview *= m_mCurrentView;
modelview.transpose();
glLoadMatrixf((F32*) modelview);
}
break;
case GFXMatrixView :
{
glMatrixMode(GL_MODELVIEW);
m_mCurrentView = mat;
modelview = m_mCurrentView;
modelview *= m_mCurrentWorld;
modelview.transpose();
glLoadMatrixf((F32*) modelview);
}
break;
case GFXMatrixProjection :
{
glMatrixMode(GL_PROJECTION);
MatrixF t(mat);
t.transpose();
glLoadMatrixf((F32*) t);
glMatrixMode(GL_MODELVIEW);
}
break;
// CodeReview - Add support for texture transform matrix types
default:
AssertFatal(false, "GFXGLDevice::setMatrix - Unknown matrix mode!");
return;
}
} }
void GFXGLDevice::setClipRect( const RectI &inRect ) void GFXGLDevice::setClipRect( const RectI &inRect )
@ -584,8 +662,8 @@ void GFXGLDevice::setClipRect( const RectI &inRect )
setViewMatrix( mTempMatrix ); setViewMatrix( mTempMatrix );
setWorldMatrix( mTempMatrix ); setWorldMatrix( mTempMatrix );
// Set the viewport to the clip rect (with y flip) // Set the viewport to the clip rect
RectI viewport(mClip.point.x, size.y - (mClip.point.y + mClip.extent.y), mClip.extent.x, mClip.extent.y); RectI viewport(mClip.point.x, mClip.point.y, mClip.extent.x, mClip.extent.y);
setViewport(viewport); setViewport(viewport);
} }
@ -637,11 +715,58 @@ GFXOcclusionQuery* GFXGLDevice::createOcclusionQuery()
void GFXGLDevice::setupGenericShaders( GenericShaderType type ) void GFXGLDevice::setupGenericShaders( GenericShaderType type )
{ {
TORQUE_UNUSED(type); AssertFatal(type != GSTargetRestore, "");
// We have FF support, use that.
disableShaders();
}
if( mGenericShader[GSColor] == NULL )
{
ShaderData *shaderData;
shaderData = new ShaderData();
shaderData->setField("OGLVertexShaderFile", "shaders/common/fixedFunction/gl/colorV.glsl");
shaderData->setField("OGLPixelShaderFile", "shaders/common/fixedFunction/gl/colorP.glsl");
shaderData->setField("pixVersion", "2.0");
shaderData->registerObject();
mGenericShader[GSColor] = shaderData->getShader();
mGenericShaderBuffer[GSColor] = mGenericShader[GSColor]->allocConstBuffer();
mModelViewProjSC[GSColor] = mGenericShader[GSColor]->getShaderConstHandle( "$modelView" );
shaderData = new ShaderData();
shaderData->setField("OGLVertexShaderFile", "shaders/common/fixedFunction/gl/modColorTextureV.glsl");
shaderData->setField("OGLPixelShaderFile", "shaders/common/fixedFunction/gl/modColorTextureP.glsl");
shaderData->setSamplerName("$diffuseMap", 0);
shaderData->setField("pixVersion", "2.0");
shaderData->registerObject();
mGenericShader[GSModColorTexture] = shaderData->getShader();
mGenericShaderBuffer[GSModColorTexture] = mGenericShader[GSModColorTexture]->allocConstBuffer();
mModelViewProjSC[GSModColorTexture] = mGenericShader[GSModColorTexture]->getShaderConstHandle( "$modelView" );
shaderData = new ShaderData();
shaderData->setField("OGLVertexShaderFile", "shaders/common/fixedFunction/gl/addColorTextureV.glsl");
shaderData->setField("OGLPixelShaderFile", "shaders/common/fixedFunction/gl/addColorTextureP.glsl");
shaderData->setSamplerName("$diffuseMap", 0);
shaderData->setField("pixVersion", "2.0");
shaderData->registerObject();
mGenericShader[GSAddColorTexture] = shaderData->getShader();
mGenericShaderBuffer[GSAddColorTexture] = mGenericShader[GSAddColorTexture]->allocConstBuffer();
mModelViewProjSC[GSAddColorTexture] = mGenericShader[GSAddColorTexture]->getShaderConstHandle( "$modelView" );
shaderData = new ShaderData();
shaderData->setField("OGLVertexShaderFile", "shaders/common/fixedFunction/gl/textureV.glsl");
shaderData->setField("OGLPixelShaderFile", "shaders/common/fixedFunction/gl/textureP.glsl");
shaderData->setSamplerName("$diffuseMap", 0);
shaderData->setField("pixVersion", "2.0");
shaderData->registerObject();
mGenericShader[GSTexture] = shaderData->getShader();
mGenericShaderBuffer[GSTexture] = mGenericShader[GSTexture]->allocConstBuffer();
mModelViewProjSC[GSTexture] = mGenericShader[GSTexture]->getShaderConstHandle( "$modelView" );
}
MatrixF tempMatrix = mProjectionMatrix * mViewMatrix * mWorldMatrix[mWorldStackSize];
mGenericShaderBuffer[type]->setSafe(mModelViewProjSC[type], tempMatrix);
setShader( mGenericShader[type] );
setShaderConstBuffer( mGenericShaderBuffer[type] );
}
GFXShader* GFXGLDevice::createShader() GFXShader* GFXGLDevice::createShader()
{ {
GFXGLShader* shader = new GFXGLShader(); GFXGLShader* shader = new GFXGLShader();
@ -651,19 +776,19 @@ GFXShader* GFXGLDevice::createShader()
void GFXGLDevice::setShader( GFXShader *shader ) void GFXGLDevice::setShader( GFXShader *shader )
{ {
if(mCurrentShader == shader)
return;
if ( shader ) if ( shader )
{ {
GFXGLShader *glShader = static_cast<GFXGLShader*>( shader ); GFXGLShader *glShader = static_cast<GFXGLShader*>( shader );
glShader->useProgram(); glShader->useProgram();
mCurrentShader = shader;
} }
else else
glUseProgram(0); {
} setupGenericShaders();
}
void GFXGLDevice::disableShaders()
{
setShader(NULL);
setShaderConstBuffer( NULL );
} }
void GFXGLDevice::setShaderConstBufferInternal(GFXShaderConstBuffer* buffer) void GFXGLDevice::setShaderConstBufferInternal(GFXShaderConstBuffer* buffer)
@ -673,12 +798,20 @@ void GFXGLDevice::setShaderConstBufferInternal(GFXShaderConstBuffer* buffer)
U32 GFXGLDevice::getNumSamplers() const U32 GFXGLDevice::getNumSamplers() const
{ {
return mPixelShaderVersion > 0.001f ? mMaxShaderTextures : mMaxFFTextures; return getMin((U32)TEXTURE_STAGE_COUNT,mPixelShaderVersion > 0.001f ? mMaxShaderTextures : mMaxFFTextures);
}
GFXTextureObject* GFXGLDevice::getDefaultDepthTex() const
{
if(mWindowRT && mWindowRT->getPointer())
return static_cast<GFXGLWindowTarget*>( mWindowRT->getPointer() )->mBackBufferDepthTex.getPointer();
return NULL;
} }
U32 GFXGLDevice::getNumRenderTargets() const U32 GFXGLDevice::getNumRenderTargets() const
{ {
return 1; return mMaxTRColors;
} }
void GFXGLDevice::_updateRenderTargets() void GFXGLDevice::_updateRenderTargets()
@ -748,6 +881,38 @@ GFXFormat GFXGLDevice::selectSupportedFormat( GFXTextureProfile* profile,
return GFXFormatR8G8B8A8; return GFXFormatR8G8B8A8;
} }
U32 GFXGLDevice::getTotalVideoMemory_GL_EXT()
{
// Source: http://www.opengl.org/registry/specs/ATI/meminfo.txt
if( gglHasExtension(ATI_meminfo) )
{
GLint mem[4] = {0};
glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI, mem); // Retrieve the texture pool
/* With mem[0] i get only the total memory free in the pool in KB
*
* mem[0] - total memory free in the pool
* mem[1] - largest available free block in the pool
* mem[2] - total auxiliary memory free
* mem[3] - largest auxiliary free block
*/
return mem[0] / 1024;
}
//source http://www.opengl.org/registry/specs/NVX/gpu_memory_info.txt
else if( gglHasExtension(NVX_gpu_memory_info) )
{
GLint mem = 0;
glGetIntegerv(GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX, &mem);
return mem / 1024;
}
// TODO OPENGL, add supprt for INTEL cards.
return 0;
}
// //
// Register this device with GFXInit // Register this device with GFXInit
// //

View file

@ -28,9 +28,7 @@
#include "gfx/gfxDevice.h" #include "gfx/gfxDevice.h"
#include "gfx/gfxInit.h" #include "gfx/gfxInit.h"
#ifndef GL_GGL_H #include "gfx/gl/tGL/tGL.h"
#include "gfx/gl/ggl/ggl.h"
#endif
#include "windowManager/platformWindow.h" #include "windowManager/platformWindow.h"
#include "gfx/gfxFence.h" #include "gfx/gfxFence.h"
@ -41,6 +39,8 @@ class GFXGLVertexBuffer;
class GFXGLPrimitiveBuffer; class GFXGLPrimitiveBuffer;
class GFXGLTextureTarget; class GFXGLTextureTarget;
class GFXGLCubemap; class GFXGLCubemap;
class GFXGLStateCache;
class GFXGLVertexDecl;
class GFXGLDevice : public GFXDevice class GFXGLDevice : public GFXDevice
{ {
@ -59,12 +59,13 @@ public:
virtual void deactivate() { } virtual void deactivate() { }
virtual GFXAdapterType getAdapterType() { return OpenGL; } virtual GFXAdapterType getAdapterType() { return OpenGL; }
virtual void enterDebugEvent(ColorI color, const char *name) { } virtual void enterDebugEvent(ColorI color, const char *name);
virtual void leaveDebugEvent() { } virtual void leaveDebugEvent();
virtual void setDebugMarker(ColorI color, const char *name) { } virtual void setDebugMarker(ColorI color, const char *name);
virtual void enumerateVideoModes(); virtual void enumerateVideoModes();
virtual U32 getTotalVideoMemory_GL_EXT();
virtual U32 getTotalVideoMemory(); virtual U32 getTotalVideoMemory();
virtual GFXCubemap * createCubemap(); virtual GFXCubemap * createCubemap();
@ -135,7 +136,16 @@ public:
/// ///
bool supportsAnisotropic() const { return mSupportsAnisotropic; } bool supportsAnisotropic() const { return mSupportsAnisotropic; }
GFXGLStateCache* getOpenglCache() { return mOpenglStateCache; }
GFXTextureObject* getDefaultDepthTex() const;
/// Returns the number of vertex streams supported by the device.
const U32 getNumVertexStreams() const { return mNumVertexStream; }
bool glUseMap() const { return mUseGlMap; }
protected: protected:
/// Called by GFXDevice to create a device specific stateblock /// Called by GFXDevice to create a device specific stateblock
virtual GFXStateBlockRef createStateBlockInternal(const GFXStateBlockDesc& desc); virtual GFXStateBlockRef createStateBlockInternal(const GFXStateBlockDesc& desc);
@ -170,16 +180,12 @@ protected:
// NOTE: The GL device doesn't need a vertex declaration at // NOTE: The GL device doesn't need a vertex declaration at
// this time, but we need to return something to keep the system // this time, but we need to return something to keep the system
// from retrying to allocate one on every call. // from retrying to allocate one on every call.
virtual GFXVertexDecl* allocVertexDecl( const GFXVertexFormat *vertexFormat ) virtual GFXVertexDecl* allocVertexDecl( const GFXVertexFormat *vertexFormat );
{
static GFXVertexDecl decl;
return &decl;
}
virtual void setVertexDecl( const GFXVertexDecl *decl ) { } virtual void setVertexDecl( const GFXVertexDecl *decl );
virtual void setVertexStream( U32 stream, GFXVertexBuffer *buffer ); virtual void setVertexStream( U32 stream, GFXVertexBuffer *buffer );
virtual void setVertexStreamFrequency( U32 stream, U32 frequency ); virtual void setVertexStreamFrequency( U32 stream, U32 frequency );
private: private:
typedef GFXDevice Parent; typedef GFXDevice Parent;
@ -194,8 +200,16 @@ private:
U32 mAdapterIndex; U32 mAdapterIndex;
StrongRefPtr<GFXGLVertexBuffer> mCurrentVB; StrongRefPtr<GFXGLVertexBuffer> mCurrentVB[VERTEX_STREAM_COUNT];
U32 mCurrentVB_Divisor[VERTEX_STREAM_COUNT];
bool mNeedUpdateVertexAttrib;
StrongRefPtr<GFXGLPrimitiveBuffer> mCurrentPB; StrongRefPtr<GFXGLPrimitiveBuffer> mCurrentPB;
U32 mDrawInstancesCount;
GFXShader* mCurrentShader;
GFXShaderRef mGenericShader[GS_COUNT];
GFXShaderConstBufferRef mGenericShaderBuffer[GS_COUNT];
GFXShaderConstHandle *mModelViewProjSC[GS_COUNT];
/// Since GL does not have separate world and view matrices we need to track them /// Since GL does not have separate world and view matrices we need to track them
MatrixF m_mCurrentWorld; MatrixF m_mCurrentWorld;
@ -206,11 +220,15 @@ private:
F32 mPixelShaderVersion; F32 mPixelShaderVersion;
bool mSupportsAnisotropic; bool mSupportsAnisotropic;
U32 mNumVertexStream;
U32 mMaxShaderTextures; U32 mMaxShaderTextures;
U32 mMaxFFTextures; U32 mMaxFFTextures;
U32 mMaxTRColors;
RectI mClip; RectI mClip;
GFXGLStateBlockRef mCurrentGLStateBlock; GFXGLStateBlockRef mCurrentGLStateBlock;
@ -232,6 +250,13 @@ private:
GFXFence* _createPlatformSpecificFence(); ///< If our platform (e.g. OS X) supports a fence extenstion (e.g. GL_APPLE_fence) this will create one, otherwise returns NULL GFXFence* _createPlatformSpecificFence(); ///< If our platform (e.g. OS X) supports a fence extenstion (e.g. GL_APPLE_fence) this will create one, otherwise returns NULL
void setPB(GFXGLPrimitiveBuffer* pb); ///< Sets mCurrentPB void setPB(GFXGLPrimitiveBuffer* pb); ///< Sets mCurrentPB
GFXGLStateCache *mOpenglStateCache;
GFXWindowTargetRef *mWindowRT;
bool mUseGlMap;
}; };
#define GFXGL static_cast<GFXGLDevice*>(GFXDevice::get())
#endif #endif

View file

@ -294,21 +294,7 @@ GFXFence* GFXGLDevice::_createPlatformSpecificFence()
return new GFXGLAppleFence(this); return new GFXGLAppleFence(this);
} }
void GFXGLWindowTarget::makeActive() void GFXGLWindowTarget::_WindowPresent()
{
// If we're supposed to be running fullscreen, but haven't yet set up for it,
// do it now.
if( !mFullscreenContext && mWindow->getVideoMode().fullScreen )
{
static_cast< GFXGLDevice* >( mDevice )->zombify();
_setupNewMode();
}
mFullscreenContext ? [(NSOpenGLContext*)mFullscreenContext makeCurrentContext] : [(NSOpenGLContext*)mContext makeCurrentContext];
}
bool GFXGLWindowTarget::present()
{ {
GFX->updateStates(); GFX->updateStates();
mFullscreenContext ? [(NSOpenGLContext*)mFullscreenContext flushBuffer] : [(NSOpenGLContext*)mContext flushBuffer]; mFullscreenContext ? [(NSOpenGLContext*)mFullscreenContext flushBuffer] : [(NSOpenGLContext*)mContext flushBuffer];

View file

@ -0,0 +1,133 @@
#include "gui/core/guiCanvas.h"
#include "console/engineAPI.h"
#include "gfx/gfxDebugEvent.h"
#include "gfx/gl/gfxGLDevice.h"
#ifndef TORQUE_BASIC_GPU_PROFILER
//#define TORQUE_BASIC_GPU_PROFILER
#endif
class GLTimer
{
public:
void begin()
{
glBeginQuery(GL_TIME_ELAPSED, mQueryId);
}
void end()
{
glEndQuery(GL_TIME_ELAPSED);
}
F64 getTime()
{
GLuint64 time;
glGetQueryObjectui64v(mQueryId, GL_QUERY_RESULT, &time);
return static_cast<F64>(time)/1000000.0f;
}
class Data
{
public:
Data() {}
void init()
{
}
void onBeginFrame()
{
}
void onEndFrame()
{
}
};
typedef Data DataType;
GLTimer(GFXDevice *device, Data &data) : mData(&data)
{
glGenQueries(1, &mQueryId);
}
GLTimer() : mName(NULL), mQueryId(0), mData(NULL)
{
}
GLTimer& operator=(const GLTimer &b)
{
mName = b.mName;
mQueryId = b.mQueryId;
return *this;
}
StringTableEntry mName;
protected:
Data *mData;
GLuint mQueryId;
};
#ifdef TORQUE_BASIC_GPU_PROFILER
#include "gfx/gfxProfiler.h"
GFXProfiler<GLTimer> gfxProfiler;
DefineConsoleFunction(printGFXGLTimers, void,(), ,"")
{
gfxProfiler.printTimes();
}
#endif
bool initGLProfiler(GFXDevice::GFXDeviceEventType ev)
{
if(ev != GFXDevice::deInit || GFX->getAdapterType() != OpenGL)
return true;
Con::evaluatef("GlobalActionMap.bindCmd(keyboard, \"alt F4\", \"printGFXGLTimers();\");");
return true;
}
void GFXGLDevice::enterDebugEvent(ColorI color, const char *name)
{
#ifdef TORQUE_BASIC_GPU_PROFILER
gfxProfiler.enterDebugEvent(color, name);
#endif
}
void GFXGLDevice::leaveDebugEvent()
{
#ifdef TORQUE_BASIC_GPU_PROFILER
gfxProfiler.leaveDebugEvent();
#endif
}
void GFXGLDevice::setDebugMarker(ColorI color, const char *name)
{
}
#ifdef TORQUE_BASIC_GPU_PROFILER
AFTER_MODULE_INIT(Sim)
{
// GFXGLDevice Profiler
GuiCanvas::getGuiCanvasFrameSignal().notify(&gfxProfiler, &GFXProfiler<GLTimer>::onEndFrame);
GFXDevice::getDeviceEventSignal().notify( &initGLProfiler );
}
#endif

View file

@ -34,6 +34,7 @@ GLenum GFXGLStencilOp[GFXStencilOp_COUNT];
GLenum GFXGLTextureInternalFormat[GFXFormat_COUNT]; GLenum GFXGLTextureInternalFormat[GFXFormat_COUNT];
GLenum GFXGLTextureFormat[GFXFormat_COUNT]; GLenum GFXGLTextureFormat[GFXFormat_COUNT];
GLenum GFXGLTextureType[GFXFormat_COUNT]; GLenum GFXGLTextureType[GFXFormat_COUNT];
GLint* GFXGLTextureSwizzle[GFXFormat_COUNT];
GLenum GFXGLBufferType[GFXBufferType_COUNT]; GLenum GFXGLBufferType[GFXBufferType_COUNT];
GLenum GFXGLCullMode[GFXCull_COUNT]; GLenum GFXGLCullMode[GFXCull_COUNT];
GLenum GFXGLFillMode[GFXFill_COUNT]; GLenum GFXGLFillMode[GFXFill_COUNT];
@ -118,54 +119,50 @@ void GFXGLEnumTranslate::init()
// Texture formats // Texture formats
GFXGLTextureInternalFormat[GFXFormatA8] = GL_ALPHA8; for(int i = 0; i < GFXFormat_COUNT; ++i)
GFXGLTextureInternalFormat[GFXFormatL8] = GL_LUMINANCE8; {
GFXGLTextureInternalFormat[GFXFormatR5G6B5] = GL_RGB5_A1; // OpenGL has no R5G6B5 format. GFXGLTextureInternalFormat[i] = GL_NONE;
GFXGLTextureFormat[i] = GL_NONE;
GFXGLTextureType[i] = GL_NONE;
GFXGLTextureSwizzle[i] = NULL;
}
GFXGLTextureInternalFormat[GFXFormatA8] = GL_R8;
GFXGLTextureInternalFormat[GFXFormatL8] = GL_R8;
GFXGLTextureInternalFormat[GFXFormatR5G5B5A1] = GL_RGB5_A1; GFXGLTextureInternalFormat[GFXFormatR5G5B5A1] = GL_RGB5_A1;
GFXGLTextureInternalFormat[GFXFormatR5G5B5X1] = GL_RGB5_A1; GFXGLTextureInternalFormat[GFXFormatR5G5B5X1] = GL_RGB5_A1;
GFXGLTextureInternalFormat[GFXFormatL16] = GL_LUMINANCE16; GFXGLTextureInternalFormat[GFXFormatL16] = GL_R16;
GFXGLTextureInternalFormat[GFXFormatR16F] = GL_ZERO; GFXGLTextureInternalFormat[GFXFormatD16] = GL_DEPTH_COMPONENT16;
GFXGLTextureInternalFormat[GFXFormatD16] = GL_DEPTH_COMPONENT;
GFXGLTextureInternalFormat[GFXFormatR8G8B8] = GL_RGB8; GFXGLTextureInternalFormat[GFXFormatR8G8B8] = GL_RGB8;
GFXGLTextureInternalFormat[GFXFormatR8G8B8A8] = GL_RGBA8; GFXGLTextureInternalFormat[GFXFormatR8G8B8A8] = GL_RGBA8;
GFXGLTextureInternalFormat[GFXFormatR8G8B8X8] = GL_RGBA8; GFXGLTextureInternalFormat[GFXFormatR8G8B8X8] = GL_RGBA8;
GFXGLTextureInternalFormat[GFXFormatR32F] = GL_ZERO; GFXGLTextureInternalFormat[GFXFormatB8G8R8A8] = GL_RGBA8;
GFXGLTextureInternalFormat[GFXFormatR16G16] = GL_RGBA16; GFXGLTextureInternalFormat[GFXFormatR10G10B10A2] = GL_RGB10_A2;
GFXGLTextureInternalFormat[GFXFormatR16G16F] = GL_ZERO;
GFXGLTextureInternalFormat[GFXFormatR10G10B10A2] = GL_ZERO;
GFXGLTextureInternalFormat[GFXFormatD32] = GL_DEPTH_COMPONENT32; GFXGLTextureInternalFormat[GFXFormatD32] = GL_DEPTH_COMPONENT32;
GFXGLTextureInternalFormat[GFXFormatD24X8] = GL_DEPTH_COMPONENT24; GFXGLTextureInternalFormat[GFXFormatD24X8] = GL_DEPTH24_STENCIL8;
GFXGLTextureInternalFormat[GFXFormatD24S8] = GL_DEPTH_COMPONENT24; GFXGLTextureInternalFormat[GFXFormatD24S8] = GL_DEPTH24_STENCIL8;
GFXGLTextureInternalFormat[GFXFormatR16G16B16A16] = GL_ZERO; GFXGLTextureInternalFormat[GFXFormatR16G16B16A16] = GL_RGBA16;
GFXGLTextureInternalFormat[GFXFormatR16G16B16A16F] = GL_ZERO;
GFXGLTextureInternalFormat[GFXFormatR32G32B32A32F] = GL_ZERO;
GFXGLTextureInternalFormat[GFXFormatDXT1] = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; GFXGLTextureInternalFormat[GFXFormatDXT1] = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
GFXGLTextureInternalFormat[GFXFormatDXT2] = GL_ZERO; GFXGLTextureInternalFormat[GFXFormatDXT2] = GL_ZERO;
GFXGLTextureInternalFormat[GFXFormatDXT3] = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; GFXGLTextureInternalFormat[GFXFormatDXT3] = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
GFXGLTextureInternalFormat[GFXFormatDXT4] = GL_ZERO; GFXGLTextureInternalFormat[GFXFormatDXT4] = GL_ZERO;
GFXGLTextureInternalFormat[GFXFormatDXT5] = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; GFXGLTextureInternalFormat[GFXFormatDXT5] = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
GFXGLTextureFormat[GFXFormatA8] = GL_ALPHA; GFXGLTextureFormat[GFXFormatA8] = GL_RED;
GFXGLTextureFormat[GFXFormatL8] = GL_LUMINANCE; GFXGLTextureFormat[GFXFormatL8] = GL_RED;
GFXGLTextureFormat[GFXFormatR5G6B5] = GL_RGBA;
GFXGLTextureFormat[GFXFormatR5G5B5A1] = GL_RGBA; GFXGLTextureFormat[GFXFormatR5G5B5A1] = GL_RGBA;
GFXGLTextureFormat[GFXFormatR5G5B5X1] = GL_RGBA; GFXGLTextureFormat[GFXFormatR5G5B5X1] = GL_RGBA;
GFXGLTextureFormat[GFXFormatL16] = GL_LUMINANCE; GFXGLTextureFormat[GFXFormatL16] = GL_RED;
GFXGLTextureFormat[GFXFormatR16F] = GL_ZERO;
GFXGLTextureFormat[GFXFormatD16] = GL_DEPTH_COMPONENT; GFXGLTextureFormat[GFXFormatD16] = GL_DEPTH_COMPONENT;
GFXGLTextureFormat[GFXFormatR8G8B8] = GL_RGB; GFXGLTextureFormat[GFXFormatR8G8B8] = GL_RGB;
GFXGLTextureFormat[GFXFormatR8G8B8A8] = GL_BGRA; GFXGLTextureFormat[GFXFormatR8G8B8A8] = GL_RGBA;
GFXGLTextureFormat[GFXFormatR8G8B8X8] = GL_BGRA; GFXGLTextureFormat[GFXFormatR8G8B8X8] = GL_RGBA;
GFXGLTextureFormat[GFXFormatR32F] = GL_RGBA; GFXGLTextureFormat[GFXFormatB8G8R8A8] = GL_BGRA;
GFXGLTextureFormat[GFXFormatR16G16] = GL_RGBA;
GFXGLTextureFormat[GFXFormatR16G16F] = GL_ZERO;
GFXGLTextureFormat[GFXFormatR10G10B10A2] = GL_RGBA; GFXGLTextureFormat[GFXFormatR10G10B10A2] = GL_RGBA;
GFXGLTextureFormat[GFXFormatD32] = GL_DEPTH_COMPONENT; GFXGLTextureFormat[GFXFormatD32] = GL_DEPTH_COMPONENT;
GFXGLTextureFormat[GFXFormatD24X8] = GL_DEPTH_COMPONENT; GFXGLTextureFormat[GFXFormatD24X8] = GL_DEPTH_STENCIL;
GFXGLTextureFormat[GFXFormatD24S8] = GL_DEPTH_COMPONENT; GFXGLTextureFormat[GFXFormatD24S8] = GL_DEPTH_STENCIL;
GFXGLTextureFormat[GFXFormatR16G16B16A16] = GL_RGBA; GFXGLTextureFormat[GFXFormatR16G16B16A16] = GL_RGBA;
GFXGLTextureFormat[GFXFormatR16G16B16A16F] = GL_RGBA;
GFXGLTextureFormat[GFXFormatR32G32B32A32F] = GL_RGBA;
GFXGLTextureFormat[GFXFormatDXT1] = GL_RGBA; GFXGLTextureFormat[GFXFormatDXT1] = GL_RGBA;
GFXGLTextureFormat[GFXFormatDXT2] = GL_ZERO; GFXGLTextureFormat[GFXFormatDXT2] = GL_ZERO;
GFXGLTextureFormat[GFXFormatDXT3] = GL_RGBA; GFXGLTextureFormat[GFXFormatDXT3] = GL_RGBA;
@ -174,36 +171,102 @@ void GFXGLEnumTranslate::init()
GFXGLTextureType[GFXFormatA8] = GL_UNSIGNED_BYTE; GFXGLTextureType[GFXFormatA8] = GL_UNSIGNED_BYTE;
GFXGLTextureType[GFXFormatL8] = GL_UNSIGNED_BYTE; GFXGLTextureType[GFXFormatL8] = GL_UNSIGNED_BYTE;
GFXGLTextureType[GFXFormatR5G6B5] = GL_UNSIGNED_BYTE; GFXGLTextureType[GFXFormatR5G5B5A1] = GL_UNSIGNED_SHORT_5_5_5_1;
GFXGLTextureType[GFXFormatR5G5B5A1] = GL_UNSIGNED_BYTE; GFXGLTextureType[GFXFormatR5G5B5X1] = GL_UNSIGNED_SHORT_5_5_5_1;
GFXGLTextureType[GFXFormatR5G5B5X1] = GL_UNSIGNED_BYTE;
GFXGLTextureType[GFXFormatL16] = GL_UNSIGNED_SHORT; GFXGLTextureType[GFXFormatL16] = GL_UNSIGNED_SHORT;
GFXGLTextureType[GFXFormatR16F] = GL_ZERO;
GFXGLTextureType[GFXFormatD16] = GL_UNSIGNED_SHORT; GFXGLTextureType[GFXFormatD16] = GL_UNSIGNED_SHORT;
GFXGLTextureType[GFXFormatR8G8B8] = GL_UNSIGNED_BYTE; GFXGLTextureType[GFXFormatR8G8B8] = GL_UNSIGNED_BYTE;
GFXGLTextureType[GFXFormatR8G8B8A8] = GL_UNSIGNED_BYTE; GFXGLTextureType[GFXFormatR8G8B8A8] = GL_UNSIGNED_BYTE;
GFXGLTextureType[GFXFormatR8G8B8X8] = GL_UNSIGNED_BYTE; GFXGLTextureType[GFXFormatR8G8B8X8] = GL_UNSIGNED_BYTE;
GFXGLTextureType[GFXFormatR32F] = GL_FLOAT; GFXGLTextureType[GFXFormatB8G8R8A8] = GL_UNSIGNED_BYTE;;
GFXGLTextureType[GFXFormatR16G16] = GL_UNSIGNED_SHORT; GFXGLTextureType[GFXFormatR10G10B10A2] = GL_UNSIGNED_INT_10_10_10_2;
GFXGLTextureType[GFXFormatR16G16F] = GL_FLOAT; GFXGLTextureType[GFXFormatD32] = GL_UNSIGNED_INT;
GFXGLTextureType[GFXFormatR10G10B10A2] = GL_UNSIGNED_SHORT; GFXGLTextureType[GFXFormatD24X8] = GL_UNSIGNED_INT_24_8;
GFXGLTextureType[GFXFormatD32] = GL_UNSIGNED_BYTE; GFXGLTextureType[GFXFormatD24S8] = GL_UNSIGNED_INT_24_8;
GFXGLTextureType[GFXFormatD24X8] = GL_UNSIGNED_BYTE;
GFXGLTextureType[GFXFormatD24S8] = GL_UNSIGNED_BYTE;
GFXGLTextureType[GFXFormatR16G16B16A16] = GL_UNSIGNED_SHORT; GFXGLTextureType[GFXFormatR16G16B16A16] = GL_UNSIGNED_SHORT;
GFXGLTextureType[GFXFormatR16G16B16A16F] = GL_FLOAT;
GFXGLTextureType[GFXFormatR32G32B32A32F] = GL_FLOAT;
GFXGLTextureType[GFXFormatDXT1] = GL_UNSIGNED_BYTE; GFXGLTextureType[GFXFormatDXT1] = GL_UNSIGNED_BYTE;
GFXGLTextureType[GFXFormatDXT2] = GL_ZERO; GFXGLTextureType[GFXFormatDXT2] = GL_ZERO;
GFXGLTextureType[GFXFormatDXT3] = GL_UNSIGNED_BYTE; GFXGLTextureType[GFXFormatDXT3] = GL_UNSIGNED_BYTE;
GFXGLTextureType[GFXFormatDXT4] = GL_ZERO; GFXGLTextureType[GFXFormatDXT4] = GL_ZERO;
GFXGLTextureType[GFXFormatDXT5] = GL_UNSIGNED_BYTE; GFXGLTextureType[GFXFormatDXT5] = GL_UNSIGNED_BYTE;
// Cull static GLint Swizzle_GFXFormatA8[] = { GL_NONE, GL_NONE, GL_NONE, GL_RED };
GFXGLCullMode[GFXCullNone] = GL_BACK; static GLint Swizzle_GFXFormatL[] = { GL_RED, GL_RED, GL_RED, GL_ALPHA };
GFXGLCullMode[GFXCullCW] = GL_BACK; GFXGLTextureSwizzle[GFXFormatA8] = Swizzle_GFXFormatA8; // old GL_ALPHA8
GFXGLCullMode[GFXCullCCW] = GL_FRONT; GFXGLTextureSwizzle[GFXFormatL8] = Swizzle_GFXFormatL; // old GL_LUMINANCE8
GFXGLTextureSwizzle[GFXFormatL16] = Swizzle_GFXFormatL; // old GL_LUMINANCE16
if( gglHasExtension(ARB_texture_float) )
{
GFXGLTextureInternalFormat[GFXFormatR32F] = GL_R32F;
GFXGLTextureFormat[GFXFormatR32F] = GL_RED;
GFXGLTextureType[GFXFormatR32F] = GL_FLOAT;
GFXGLTextureInternalFormat[GFXFormatR32G32B32A32F] = GL_RGBA32F_ARB;
GFXGLTextureFormat[GFXFormatR32G32B32A32F] = GL_RGBA;
GFXGLTextureType[GFXFormatR32G32B32A32F] = GL_FLOAT;
if( gglHasExtension(ARB_half_float_pixel) )
{
GFXGLTextureInternalFormat[GFXFormatR16F] = GL_R16F;
GFXGLTextureFormat[GFXFormatR16F] = GL_RED;
GFXGLTextureType[GFXFormatR16F] = GL_HALF_FLOAT_ARB;
GFXGLTextureInternalFormat[GFXFormatR16G16F] = GL_RG16F;
GFXGLTextureFormat[GFXFormatR16G16F] = GL_RG;
GFXGLTextureType[GFXFormatR16G16F] = GL_HALF_FLOAT_ARB;
GFXGLTextureInternalFormat[GFXFormatR16G16B16A16F] = GL_RGBA16F_ARB;
GFXGLTextureFormat[GFXFormatR16G16B16A16F] = GL_RGBA;
GFXGLTextureType[GFXFormatR16G16B16A16F] = GL_HALF_FLOAT_ARB;
}
else
{
GFXGLTextureInternalFormat[GFXFormatR16F] = GL_R32F;
GFXGLTextureFormat[GFXFormatR16F] = GL_RED;
GFXGLTextureType[GFXFormatR16F] = GL_FLOAT;
GFXGLTextureInternalFormat[GFXFormatR16G16F] = GL_RG32F;
GFXGLTextureFormat[GFXFormatR16G16F] = GL_RG;
GFXGLTextureType[GFXFormatR16G16F] = GL_FLOAT;
GFXGLTextureInternalFormat[GFXFormatR16G16B16A16F] = GL_RGBA32F_ARB;
GFXGLTextureFormat[GFXFormatR16G16B16A16F] = GL_RGBA;
GFXGLTextureType[GFXFormatR16G16B16A16F] = GL_FLOAT;
}
}
if( gglHasExtension(ARB_ES2_compatibility) )
{
GFXGLTextureInternalFormat[GFXFormatR5G6B5] = GL_RGB5_A1;
GFXGLTextureFormat[GFXFormatR5G6B5] = GL_RGBA;
GFXGLTextureType[GFXFormatR5G6B5] = GL_UNSIGNED_SHORT_5_5_5_1;
}
else
{
GFXGLTextureInternalFormat[GFXFormatR5G6B5] = GL_RGB565;
GFXGLTextureFormat[GFXFormatR5G6B5] = GL_RGB;
GFXGLTextureType[GFXFormatR5G6B5] = GL_UNSIGNED_SHORT_5_6_5;
}
if( gglHasExtension(ARB_texture_rg) )
{
GFXGLTextureInternalFormat[GFXFormatR16G16] = GL_RG16;
GFXGLTextureFormat[GFXFormatR16G16] = GL_RG;
GFXGLTextureType[GFXFormatR16G16] = GL_UNSIGNED_SHORT;
}
else
{
GFXGLTextureInternalFormat[GFXFormatR16G16] = GL_RGBA16;
GFXGLTextureFormat[GFXFormatR16G16] = GL_RGBA;
GFXGLTextureType[GFXFormatR16G16] = GL_UNSIGNED_SHORT;
}
// Cull - Opengl render upside down need to invert cull
GFXGLCullMode[GFXCullNone] = GL_FRONT;
GFXGLCullMode[GFXCullCW] = GL_FRONT;
GFXGLCullMode[GFXCullCCW] = GL_BACK;
// Fill // Fill
GFXGLFillMode[GFXFillPoint] = GL_POINT; GFXGLFillMode[GFXFillPoint] = GL_POINT;
GFXGLFillMode[GFXFillWireframe] = GL_LINE; GFXGLFillMode[GFXFillWireframe] = GL_LINE;

View file

@ -43,6 +43,7 @@ extern GLenum GFXGLStencilOp[GFXStencilOp_COUNT];
extern GLenum GFXGLTextureInternalFormat[GFXFormat_COUNT]; extern GLenum GFXGLTextureInternalFormat[GFXFormat_COUNT];
extern GLenum GFXGLTextureFormat[GFXFormat_COUNT]; extern GLenum GFXGLTextureFormat[GFXFormat_COUNT];
extern GLenum GFXGLTextureType[GFXFormat_COUNT]; extern GLenum GFXGLTextureType[GFXFormat_COUNT];
extern GLint* GFXGLTextureSwizzle[GFXFormat_COUNT];
extern GLenum GFXGLBufferType[GFXBufferType_COUNT]; extern GLenum GFXGLBufferType[GFXBufferType_COUNT];
extern GLenum GFXGLCullMode[GFXCull_COUNT]; extern GLenum GFXGLCullMode[GFXCull_COUNT];

View file

@ -22,12 +22,12 @@
#include "platform/platform.h" #include "platform/platform.h"
#include "gfx/gl/gfxGLOcclusionQuery.h" #include "gfx/gl/gfxGLOcclusionQuery.h"
#include "gfx/gl/ggl/ggl.h" #include "gfx/gl/tGL/tGL.h"
GFXGLOcclusionQuery::GFXGLOcclusionQuery(GFXDevice* device) : GFXGLOcclusionQuery::GFXGLOcclusionQuery(GFXDevice* device) :
GFXOcclusionQuery(device), mQuery(0) GFXOcclusionQuery(device), mQuery(-1)
{ {
glGenQueries(1, &mQuery);
} }
GFXGLOcclusionQuery::~GFXGLOcclusionQuery() GFXGLOcclusionQuery::~GFXGLOcclusionQuery()
@ -37,6 +37,9 @@ GFXGLOcclusionQuery::~GFXGLOcclusionQuery()
bool GFXGLOcclusionQuery::begin() bool GFXGLOcclusionQuery::begin()
{ {
if(mQuery == -1)
glGenQueries(1, &mQuery);
glBeginQuery(GL_SAMPLES_PASSED, mQuery); glBeginQuery(GL_SAMPLES_PASSED, mQuery);
return true; return true;
} }
@ -51,6 +54,9 @@ GFXOcclusionQuery::OcclusionQueryStatus GFXGLOcclusionQuery::getStatus(bool bloc
// If this ever shows up near the top of a profile // If this ever shows up near the top of a profile
// then your system is GPU bound. // then your system is GPU bound.
PROFILE_SCOPE(GFXGLOcclusionQuery_getStatus); PROFILE_SCOPE(GFXGLOcclusionQuery_getStatus);
if(mQuery == -1)
return NotOccluded;
GLint numPixels = 0; GLint numPixels = 0;
GLint queryDone = false; GLint queryDone = false;

View file

@ -24,23 +24,40 @@
#include "gfx/gl/gfxGLPrimitiveBuffer.h" #include "gfx/gl/gfxGLPrimitiveBuffer.h"
#include "gfx/gl/gfxGLEnumTranslate.h" #include "gfx/gl/gfxGLEnumTranslate.h"
#include "gfx/gl/ggl/ggl.h" #include "gfx/gl/tGL/tGL.h"
#include "gfx/gl/gfxGLUtils.h" #include "gfx/gl/gfxGLUtils.h"
GFXGLPrimitiveBuffer::GFXGLPrimitiveBuffer(GFXDevice *device, U32 indexCount, U32 primitiveCount, GFXBufferType bufferType) : #include "gfx/gl/gfxGLCircularVolatileBuffer.h"
GFXPrimitiveBuffer(device, indexCount, primitiveCount, bufferType), mZombieCache(NULL)
GLCircularVolatileBuffer* getCircularVolatileIndexBuffer()
{ {
static GLCircularVolatileBuffer sCircularVolatileIndexBuffer(GL_ELEMENT_ARRAY_BUFFER);
return &sCircularVolatileIndexBuffer;
}
GFXGLPrimitiveBuffer::GFXGLPrimitiveBuffer(GFXDevice *device, U32 indexCount, U32 primitiveCount, GFXBufferType bufferType) :
GFXPrimitiveBuffer(device, indexCount, primitiveCount, bufferType), mZombieCache(NULL),
mBufferOffset(0)
{
if( mBufferType == GFXBufferTypeVolatile )
{
mBuffer = getCircularVolatileIndexBuffer()->getHandle();
return;
}
// Generate a buffer and allocate the needed memory
glGenBuffers(1, &mBuffer);
PRESERVE_INDEX_BUFFER(); PRESERVE_INDEX_BUFFER();
// Generate a buffer and allocate the needed memory glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mBuffer);
glGenBuffers(1, &mBuffer); glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexCount * sizeof(U16), NULL, GFXGLBufferType[bufferType]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexCount * sizeof(U16), NULL, GFXGLBufferType[bufferType]);
} }
GFXGLPrimitiveBuffer::~GFXGLPrimitiveBuffer() GFXGLPrimitiveBuffer::~GFXGLPrimitiveBuffer()
{ {
// This is heavy handed, but it frees the buffer memory // This is heavy handed, but it frees the buffer memory
glDeleteBuffersARB(1, &mBuffer); if( mBufferType != GFXBufferTypeVolatile )
glDeleteBuffers(1, &mBuffer);
if( mZombieCache ) if( mZombieCache )
delete [] mZombieCache; delete [] mZombieCache;
@ -48,44 +65,72 @@ GFXGLPrimitiveBuffer::~GFXGLPrimitiveBuffer()
void GFXGLPrimitiveBuffer::lock(U32 indexStart, U32 indexEnd, void **indexPtr) void GFXGLPrimitiveBuffer::lock(U32 indexStart, U32 indexEnd, void **indexPtr)
{ {
// Preserve previous binding if( mBufferType == GFXBufferTypeVolatile )
PRESERVE_INDEX_BUFFER(); {
AssertFatal(indexStart == 0, "");
// Bind ourselves and map getCircularVolatileIndexBuffer()->lock( mIndexCount * sizeof(U16), 0, mBufferOffset, *indexPtr );
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mBuffer); }
glBufferData(GL_ELEMENT_ARRAY_BUFFER, mIndexCount * sizeof(U16), NULL, GFXGLBufferType[mBufferType]); else
{
// Offset the buffer to indexStart mFrameAllocator.lock( mIndexCount * sizeof(U16) );
*indexPtr = (void*)((U8*)glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY) + (indexStart * sizeof(U16)));
*indexPtr = (void*)(mFrameAllocator.getlockedPtr() + (indexStart * sizeof(U16)) );
}
lockedIndexStart = indexStart;
lockedIndexEnd = indexEnd;
} }
void GFXGLPrimitiveBuffer::unlock() void GFXGLPrimitiveBuffer::unlock()
{ {
// Preserve previous binding PROFILE_SCOPE(GFXGLPrimitiveBuffer_unlock);
PRESERVE_INDEX_BUFFER();
if( mBufferType == GFXBufferTypeVolatile )
{
getCircularVolatileIndexBuffer()->unlock();
}
else
{
U32 offset = lockedIndexStart * sizeof(U16);
U32 length = (lockedIndexEnd - lockedIndexStart) * sizeof(U16);
// Bind ourselves and unmap // Preserve previous binding
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mBuffer); PRESERVE_INDEX_BUFFER();
bool res = glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
AssertFatal(res, "GFXGLPrimitiveBuffer::unlock - shouldn't fail!"); // Bind ourselves
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mBuffer);
if( !lockedIndexStart && lockedIndexEnd == mIndexCount)
glBufferData(GL_ELEMENT_ARRAY_BUFFER, mIndexCount * sizeof(U16), NULL, GFXGLBufferType[mBufferType]); // orphan the buffer
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, offset, length, mFrameAllocator.getlockedPtr() + offset );
mFrameAllocator.unlock();
}
lockedIndexStart = 0;
lockedIndexEnd = 0;
} }
void GFXGLPrimitiveBuffer::prepare() void GFXGLPrimitiveBuffer::prepare()
{ {
// Bind // Bind
static_cast<GFXGLDevice*>(mDevice)->setPB(this); GFXGLDevice* glDevice = static_cast<GFXGLDevice*>(mDevice);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mBuffer); glDevice->setPB(this);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mBuffer);
glDevice->getOpenglCache()->setCacheBinded(GL_ELEMENT_ARRAY_BUFFER, mBuffer);
} }
void GFXGLPrimitiveBuffer::finish() void GFXGLPrimitiveBuffer::finish()
{ {
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
static_cast<GFXGLDevice*>(mDevice)->getOpenglCache()->setCacheBinded(GL_ELEMENT_ARRAY_BUFFER, 0);
} }
GLvoid* GFXGLPrimitiveBuffer::getBuffer() GLvoid* GFXGLPrimitiveBuffer::getBuffer()
{ {
// NULL specifies no offset into the hardware buffer // NULL specifies no offset into the hardware buffer
return (GLvoid*)NULL; return (GLvoid*)mBufferOffset;
} }
void GFXGLPrimitiveBuffer::zombify() void GFXGLPrimitiveBuffer::zombify()
@ -114,3 +159,29 @@ void GFXGLPrimitiveBuffer::resurrect()
delete[] mZombieCache; delete[] mZombieCache;
mZombieCache = NULL; mZombieCache = NULL;
} }
namespace
{
bool onGFXDeviceSignal( GFXDevice::GFXDeviceEventType type )
{
if( GFX->getAdapterType() == OpenGL && GFXDevice::deEndOfFrame == type )
getCircularVolatileIndexBuffer()->protectUsedRange();
return true;
}
}
MODULE_BEGIN( GFX_GL_PrimitiveBuffer )
MODULE_INIT_AFTER( gfx )
MODULE_SHUTDOWN_BEFORE( gfx )
MODULE_INIT
{
GFXDevice::getDeviceEventSignal( ).notify( &onGFXDeviceSignal );
}
MODULE_SHUTDOWN
{
GFXDevice::getDeviceEventSignal( ).remove( &onGFXDeviceSignal );
}
MODULE_END

View file

@ -24,6 +24,7 @@
#define _GFXGLPRIMITIVEBUFFER_H_ #define _GFXGLPRIMITIVEBUFFER_H_
#include "gfx/gfxPrimitiveBuffer.h" #include "gfx/gfxPrimitiveBuffer.h"
#include "gfx/gl/util/glFrameAllocatorLockableHelper.h"
/// This is a primitive buffer (index buffer to GL users) which uses VBOs. /// This is a primitive buffer (index buffer to GL users) which uses VBOs.
class GFXGLPrimitiveBuffer : public GFXPrimitiveBuffer class GFXGLPrimitiveBuffer : public GFXPrimitiveBuffer
@ -32,8 +33,8 @@ public:
GFXGLPrimitiveBuffer(GFXDevice *device, U32 indexCount, U32 primitiveCount, GFXBufferType bufferType); GFXGLPrimitiveBuffer(GFXDevice *device, U32 indexCount, U32 primitiveCount, GFXBufferType bufferType);
~GFXGLPrimitiveBuffer(); ~GFXGLPrimitiveBuffer();
virtual void lock(U32 indexStart, U32 indexEnd, void **indexPtr); ///< calls glMapBuffer, offets pointer by indexStart virtual void lock(U32 indexStart, U32 indexEnd, void **indexPtr); ///< only write lock are supported
virtual void unlock(); ///< calls glUnmapBuffer, unbinds the buffer virtual void unlock(); ///<
virtual void prepare(); ///< binds the buffer virtual void prepare(); ///< binds the buffer
virtual void finish(); ///< We're done with this buffer virtual void finish(); ///< We're done with this buffer
@ -46,8 +47,12 @@ public:
private: private:
/// Handle to our GL buffer object /// Handle to our GL buffer object
GLuint mBuffer; GLuint mBuffer;
U32 mBufferOffset;
U8* mZombieCache; U8* mZombieCache;
U32 lockedIndexEnd, lockedIndexStart;
FrameAllocatorLockableHelper mFrameAllocator;
}; };
#endif #endif

View file

@ -22,6 +22,7 @@
#include "platform/platform.h" #include "platform/platform.h"
#include "gfx/gl/gfxGLShader.h" #include "gfx/gl/gfxGLShader.h"
#include "gfx/gl/gfxGLVertexAttribLocation.h"
#include "core/frameAllocator.h" #include "core/frameAllocator.h"
#include "core/stream/fileStream.h" #include "core/stream/fileStream.h"
@ -59,10 +60,11 @@ public:
U32 mOffset; U32 mOffset;
U32 mSize; U32 mSize;
S32 mSamplerNum; S32 mSamplerNum;
bool mInstancingConstant;
}; };
GFXGLShaderConstHandle::GFXGLShaderConstHandle( GFXGLShader *shader ) GFXGLShaderConstHandle::GFXGLShaderConstHandle( GFXGLShader *shader )
: mShader( shader ), mSamplerNum(-1) : mShader( shader ), mSamplerNum(-1), mInstancingConstant(false)
{ {
mValid = false; mValid = false;
} }
@ -98,7 +100,7 @@ static U32 shaderConstTypeSize(GFXShaderConstType type)
} }
GFXGLShaderConstHandle::GFXGLShaderConstHandle( GFXGLShader *shader, const GFXShaderConstDesc &desc, GLuint loc, S32 samplerNum ) GFXGLShaderConstHandle::GFXGLShaderConstHandle( GFXGLShader *shader, const GFXShaderConstDesc &desc, GLuint loc, S32 samplerNum )
: mShader(shader) : mShader(shader), mInstancingConstant(false)
{ {
reinit(desc, loc, samplerNum); reinit(desc, loc, samplerNum);
} }
@ -109,6 +111,7 @@ void GFXGLShaderConstHandle::reinit( const GFXShaderConstDesc& desc, GLuint loc,
mLocation = loc; mLocation = loc;
mSamplerNum = samplerNum; mSamplerNum = samplerNum;
mOffset = 0; mOffset = 0;
mInstancingConstant = false;
U32 elemSize = shaderConstTypeSize(mDesc.constType); U32 elemSize = shaderConstTypeSize(mDesc.constType);
AssertFatal(elemSize, "GFXGLShaderConst::GFXGLShaderConst - elemSize is 0"); AssertFatal(elemSize, "GFXGLShaderConst::GFXGLShaderConst - elemSize is 0");
@ -156,8 +159,12 @@ void GFXGLShaderConstBuffer::internalSet(GFXShaderConstHandle* handle, const Con
GFXGLShaderConstHandle* _glHandle = static_cast<GFXGLShaderConstHandle*>(handle); GFXGLShaderConstHandle* _glHandle = static_cast<GFXGLShaderConstHandle*>(handle);
AssertFatal(mShader == _glHandle->mShader, "GFXGLShaderConstBuffer::set - Should only set handles which are owned by our shader"); AssertFatal(mShader == _glHandle->mShader, "GFXGLShaderConstBuffer::set - Should only set handles which are owned by our shader");
U8 *buf = mBuffer + _glHandle->mOffset;
dMemcpy(mBuffer + _glHandle->mOffset, &param, sizeof(ConstType));
if(_glHandle->mInstancingConstant)
buf = mInstPtr + _glHandle->mOffset;
dMemcpy(buf, &param, sizeof(ConstType));
} }
void GFXGLShaderConstBuffer::set(GFXShaderConstHandle* handle, const F32 fv) void GFXGLShaderConstBuffer::set(GFXShaderConstHandle* handle, const F32 fv)
@ -219,6 +226,7 @@ void GFXGLShaderConstBuffer::internalSet(GFXShaderConstHandle* handle, const Ali
GFXGLShaderConstHandle* _glHandle = static_cast<GFXGLShaderConstHandle*>(handle); GFXGLShaderConstHandle* _glHandle = static_cast<GFXGLShaderConstHandle*>(handle);
AssertFatal(mShader == _glHandle->mShader, "GFXGLShaderConstBuffer::set - Should only set handles which are owned by our shader"); AssertFatal(mShader == _glHandle->mShader, "GFXGLShaderConstBuffer::set - Should only set handles which are owned by our shader");
AssertFatal(!_glHandle->mInstancingConstant, "GFXGLShaderConstBuffer::set - Instancing not supported for array");
const U8* fvBuffer = static_cast<const U8*>(fv.getBuffer()); const U8* fvBuffer = static_cast<const U8*>(fv.getBuffer());
for(U32 i = 0; i < fv.size(); ++i) for(U32 i = 0; i < fv.size(); ++i)
{ {
@ -275,6 +283,7 @@ void GFXGLShaderConstBuffer::set(GFXShaderConstHandle* handle, const MatrixF& ma
GFXGLShaderConstHandle* _glHandle = static_cast<GFXGLShaderConstHandle*>(handle); GFXGLShaderConstHandle* _glHandle = static_cast<GFXGLShaderConstHandle*>(handle);
AssertFatal(mShader == _glHandle->mShader, "GFXGLShaderConstBuffer::set - Should only set handles which are owned by our shader"); AssertFatal(mShader == _glHandle->mShader, "GFXGLShaderConstBuffer::set - Should only set handles which are owned by our shader");
AssertFatal(!_glHandle->mInstancingConstant || matType == GFXSCT_Float4x4, "GFXGLShaderConstBuffer::set - Only support GFXSCT_Float4x4 for instancing");
switch(matType) switch(matType)
{ {
@ -296,8 +305,18 @@ void GFXGLShaderConstBuffer::set(GFXShaderConstHandle* handle, const MatrixF& ma
reinterpret_cast<F32*>(mBuffer + _glHandle->mOffset)[8] = mat[10]; reinterpret_cast<F32*>(mBuffer + _glHandle->mOffset)[8] = mat[10];
break; break;
case GFXSCT_Float4x4: case GFXSCT_Float4x4:
{
if(_glHandle->mInstancingConstant)
{
MatrixF transposed;
mat.transposeTo(transposed);
dMemcpy( mInstPtr + _glHandle->mOffset, (const F32*)transposed, sizeof(MatrixF) );
return;
}
dMemcpy(mBuffer + _glHandle->mOffset, (const F32*)mat, sizeof(MatrixF)); dMemcpy(mBuffer + _glHandle->mOffset, (const F32*)mat, sizeof(MatrixF));
break; break;
}
default: default:
AssertFatal(false, "GFXGLShaderConstBuffer::set - Invalid matrix type"); AssertFatal(false, "GFXGLShaderConstBuffer::set - Invalid matrix type");
break; break;
@ -310,8 +329,9 @@ void GFXGLShaderConstBuffer::set(GFXShaderConstHandle* handle, const MatrixF* ma
AssertFatal(handle->isValid(), "GFXGLShaderConstBuffer::set - Handle is not valid!" ); AssertFatal(handle->isValid(), "GFXGLShaderConstBuffer::set - Handle is not valid!" );
GFXGLShaderConstHandle* _glHandle = static_cast<GFXGLShaderConstHandle*>(handle); GFXGLShaderConstHandle* _glHandle = static_cast<GFXGLShaderConstHandle*>(handle);
AssertFatal(mShader == _glHandle->mShader, "GFXGLShaderConstBuffer::set - Should only set handles which are owned by our shader"); AssertFatal(mShader == _glHandle->mShader, "GFXGLShaderConstBuffer::set - Should only set handles which are owned by our shader");
AssertFatal(!_glHandle->mInstancingConstant, "GFXGLShaderConstBuffer::set - Instancing not supported for matrix arrays");
switch (matrixType) { switch (matrixType) {
case GFXSCT_Float4x4: case GFXSCT_Float4x4:
dMemcpy(mBuffer + _glHandle->mOffset, (F32*)mat, _glHandle->getSize()); dMemcpy(mBuffer + _glHandle->mOffset, (F32*)mat, _glHandle->getSize());
@ -393,6 +413,9 @@ bool GFXGLShader::_init()
macros.increment(); macros.increment();
macros.last().name = "TORQUE_SM"; macros.last().name = "TORQUE_SM";
macros.last().value = String::ToString( mjVer * 10 + mnVer ); macros.last().value = String::ToString( mjVer * 10 + mnVer );
macros.increment();
macros.last().name = "TORQUE_VERTEX_SHADER";
macros.last().value = "";
// Default to true so we're "successful" if a vertex/pixel shader wasn't specified. // Default to true so we're "successful" if a vertex/pixel shader wasn't specified.
bool compiledVertexShader = true; bool compiledVertexShader = true;
@ -401,6 +424,8 @@ bool GFXGLShader::_init()
// Compile the vertex and pixel shaders if specified. // Compile the vertex and pixel shaders if specified.
if(!mVertexFile.isEmpty()) if(!mVertexFile.isEmpty())
compiledVertexShader = initShader(mVertexFile, true, macros); compiledVertexShader = initShader(mVertexFile, true, macros);
macros.last().name = "TORQUE_PIXEL_SHADER";
if(!mPixelFile.isEmpty()) if(!mPixelFile.isEmpty())
compiledPixelShader = initShader(mPixelFile, false, macros); compiledPixelShader = initShader(mPixelFile, false, macros);
@ -408,6 +433,24 @@ bool GFXGLShader::_init()
if(!compiledVertexShader || !compiledPixelShader) if(!compiledVertexShader || !compiledPixelShader)
return false; return false;
//bind vertex attributes
glBindAttribLocation(mProgram, Torque::GL_VertexAttrib_Position, "vPosition");
glBindAttribLocation(mProgram, Torque::GL_VertexAttrib_Normal, "vNormal");
glBindAttribLocation(mProgram, Torque::GL_VertexAttrib_Color, "vColor");
glBindAttribLocation(mProgram, Torque::GL_VertexAttrib_Tangent, "vTangent");
glBindAttribLocation(mProgram, Torque::GL_VertexAttrib_TangentW, "vTangentW");
glBindAttribLocation(mProgram, Torque::GL_VertexAttrib_Binormal, "vBinormal");
glBindAttribLocation(mProgram, Torque::GL_VertexAttrib_TexCoord0, "vTexCoord0");
glBindAttribLocation(mProgram, Torque::GL_VertexAttrib_TexCoord1, "vTexCoord1");
glBindAttribLocation(mProgram, Torque::GL_VertexAttrib_TexCoord2, "vTexCoord2");
glBindAttribLocation(mProgram, Torque::GL_VertexAttrib_TexCoord3, "vTexCoord3");
glBindAttribLocation(mProgram, Torque::GL_VertexAttrib_TexCoord4, "vTexCoord4");
glBindAttribLocation(mProgram, Torque::GL_VertexAttrib_TexCoord5, "vTexCoord5");
glBindAttribLocation(mProgram, Torque::GL_VertexAttrib_TexCoord6, "vTexCoord6");
glBindAttribLocation(mProgram, Torque::GL_VertexAttrib_TexCoord7, "vTexCoord7");
glBindAttribLocation(mProgram, Torque::GL_VertexAttrib_TexCoord8, "vTexCoord8");
glBindAttribLocation(mProgram, Torque::GL_VertexAttrib_TexCoord9, "vTexCoord9");
// Link it! // Link it!
glLinkProgram( mProgram ); glLinkProgram( mProgram );
@ -463,6 +506,10 @@ void GFXGLShader::initConstantDescs()
glGetProgramiv(mProgram, GL_ACTIVE_UNIFORMS, &numUniforms); glGetProgramiv(mProgram, GL_ACTIVE_UNIFORMS, &numUniforms);
GLint maxNameLength; GLint maxNameLength;
glGetProgramiv(mProgram, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxNameLength); glGetProgramiv(mProgram, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxNameLength);
if(!maxNameLength)
return;
FrameTemp<GLchar> uniformName(maxNameLength); FrameTemp<GLchar> uniformName(maxNameLength);
for(U32 i = 0; i < numUniforms; i++) for(U32 i = 0; i < numUniforms; i++)
@ -546,17 +593,23 @@ void GFXGLShader::initHandles()
// Loop through all ConstantDescriptions, // Loop through all ConstantDescriptions,
// if they aren't in the HandleMap add them, if they are reinitialize them. // if they aren't in the HandleMap add them, if they are reinitialize them.
S32 assignedSamplerNum = 0;
for ( U32 i = 0; i < mConstants.size(); i++ ) for ( U32 i = 0; i < mConstants.size(); i++ )
{ {
GFXShaderConstDesc &desc = mConstants[i]; GFXShaderConstDesc &desc = mConstants[i];
// Index element 1 of the name to skip the '$' we inserted earier. // Index element 1 of the name to skip the '$' we inserted earier.
U32 loc = glGetUniformLocation(mProgram, &desc.name.c_str()[1]); GLint loc = glGetUniformLocation(mProgram, &desc.name.c_str()[1]);
AssertFatal(loc != -1, "");
HandleMap::Iterator handle = mHandles.find(desc.name); HandleMap::Iterator handle = mHandles.find(desc.name);
S32 sampler = (desc.constType == GFXSCT_Sampler || desc.constType == GFXSCT_SamplerCube) ? S32 sampler = -1;
assignedSamplerNum++ : -1; if(desc.constType == GFXSCT_Sampler || desc.constType == GFXSCT_SamplerCube)
{
S32 idx = mSamplerNamesOrdered.find_next(desc.name);
AssertFatal(idx != -1, "");
sampler = idx; //assignedSamplerNum++;
}
if ( handle != mHandles.end() ) if ( handle != mHandles.end() )
{ {
handle->value->reinit( desc, loc, sampler ); handle->value->reinit( desc, loc, sampler );
@ -599,10 +652,69 @@ void GFXGLShader::initHandles()
// Set sampler number on our program. // Set sampler number on our program.
glUniform1i(handle->mLocation, handle->mSamplerNum); glUniform1i(handle->mLocation, handle->mSamplerNum);
// Set sampler in constant buffer so it does not get unset later. // Set sampler in constant buffer so it does not get unset later.
dMemcpy(mConstBuffer + handle->mOffset, &handle->mLocation, handle->getSize()); dMemcpy(mConstBuffer + handle->mOffset, &handle->mSamplerNum, handle->getSize());
} }
} }
glUseProgram(0); glUseProgram(0);
//instancing
U32 offset = 0;
for ( U32 i=0; i < mInstancingFormat.getElementCount(); i++ )
{
const GFXVertexElement &element = mInstancingFormat.getElement( i );
String constName = String::ToString( "$%s", element.getSemantic().c_str() );
HandleMap::Iterator handle = mHandles.find(constName);
if ( handle != mHandles.end() )
{
AssertFatal(0, "");
}
else
{
GFXShaderConstDesc desc;
desc.name = constName;
desc.arraySize = 1;
switch(element.getType())
{
case GFXDeclType_Float4:
desc.constType = GFXSCT_Float4;
break;
default:
desc.constType = GFXSCT_Float;
break;
}
GFXGLShaderConstHandle *h = new GFXGLShaderConstHandle( this, desc, -1, -1 );
h->mInstancingConstant = true;
h->mOffset = offset;
mHandles[constName] = h;
offset += element.getSizeInBytes();
++i;
// If this is a matrix we will have 2 or 3 more of these
// semantics with the same name after it.
for ( ; i < mInstancingFormat.getElementCount(); i++ )
{
const GFXVertexElement &nextElement = mInstancingFormat.getElement( i );
if ( nextElement.getSemantic() != element.getSemantic() )
{
i--;
break;
}
++desc.arraySize;
if(desc.arraySize == 4 && desc.constType == GFXSCT_Float4)
{
desc.arraySize = 1;
desc.constType = GFXSCT_Float4x4;
}
offset += nextElement.getSizeInBytes();
}
}
}
} }
GFXShaderConstHandle* GFXGLShader::getShaderConstHandle(const String& name) GFXShaderConstHandle* GFXGLShader::getShaderConstHandle(const String& name)
@ -619,12 +731,26 @@ GFXShaderConstHandle* GFXGLShader::getShaderConstHandle(const String& name)
} }
} }
GFXShaderConstHandle* GFXGLShader::findShaderConstHandle(const String& name)
{
HandleMap::Iterator i = mHandles.find(name);
if(i != mHandles.end())
return i->value;
else
{
return NULL;
}
}
void GFXGLShader::setConstantsFromBuffer(GFXGLShaderConstBuffer* buffer) void GFXGLShader::setConstantsFromBuffer(GFXGLShaderConstBuffer* buffer)
{ {
for(Vector<GFXGLShaderConstHandle*>::iterator i = mValidHandles.begin(); i != mValidHandles.end(); ++i) for(Vector<GFXGLShaderConstHandle*>::iterator i = mValidHandles.begin(); i != mValidHandles.end(); ++i)
{ {
GFXGLShaderConstHandle* handle = *i; GFXGLShaderConstHandle* handle = *i;
AssertFatal(handle, "GFXGLShader::setConstantsFromBuffer - Null handle"); AssertFatal(handle, "GFXGLShader::setConstantsFromBuffer - Null handle");
if(handle->mInstancingConstant)
continue;
// Don't set if the value has not be changed. // Don't set if the value has not be changed.
if(dMemcmp(mConstBuffer + handle->mOffset, buffer->mBuffer + handle->mOffset, handle->getSize()) == 0) if(dMemcmp(mConstBuffer + handle->mOffset, buffer->mBuffer + handle->mOffset, handle->getSize()) == 0)
@ -669,6 +795,9 @@ void GFXGLShader::setConstantsFromBuffer(GFXGLShaderConstBuffer* buffer)
case GFXSCT_Float4x4: case GFXSCT_Float4x4:
glUniformMatrix4fv(handle->mLocation, handle->mDesc.arraySize, true, (GLfloat*)(mConstBuffer + handle->mOffset)); glUniformMatrix4fv(handle->mLocation, handle->mDesc.arraySize, true, (GLfloat*)(mConstBuffer + handle->mOffset));
break; break;
default:
AssertFatal(0,"");
break;
} }
} }
} }
@ -813,13 +942,34 @@ bool GFXGLShader::_loadShaderFromStream( GLuint shader,
Vector<U32> lengths; Vector<U32> lengths;
// The GLSL version declaration must go first! // The GLSL version declaration must go first!
const char *versionDecl = "#version 120\r\n\r\n"; const char *versionDecl = "#version 150\r\n";
buffers.push_back( dStrdup( versionDecl ) ); buffers.push_back( dStrdup( versionDecl ) );
lengths.push_back( dStrlen( versionDecl ) ); lengths.push_back( dStrlen( versionDecl ) );
if(gglHasExtension(EXT_gpu_shader4))
{
const char *extension = "#extension GL_EXT_gpu_shader4 : enable\r\n";
buffers.push_back( dStrdup( extension ) );
lengths.push_back( dStrlen( extension ) );
}
if(gglHasExtension(ARB_gpu_shader5))
{
const char *extension = "#extension GL_ARB_gpu_shader5 : enable\r\n";
buffers.push_back( dStrdup( extension ) );
lengths.push_back( dStrlen( extension ) );
}
const char *newLine = "\r\n";
buffers.push_back( dStrdup( newLine ) );
lengths.push_back( dStrlen( newLine ) );
// Now add all the macros. // Now add all the macros.
for( U32 i = 0; i < macros.size(); i++ ) for( U32 i = 0; i < macros.size(); i++ )
{ {
if(macros[i].name.isEmpty()) // TODO OPENGL
continue;
String define = String::ToString( "#define %s %s\n", macros[i].name.c_str(), macros[i].value.c_str() ); String define = String::ToString( "#define %s %s\n", macros[i].name.c_str(), macros[i].value.c_str() );
buffers.push_back( dStrdup( define.c_str() ) ); buffers.push_back( dStrdup( define.c_str() ) );
lengths.push_back( define.length() ); lengths.push_back( define.length() );
@ -836,6 +986,17 @@ bool GFXGLShader::_loadShaderFromStream( GLuint shader,
glShaderSource(shader, buffers.size(), (const GLchar**)const_cast<const char**>(buffers.address()), NULL); glShaderSource(shader, buffers.size(), (const GLchar**)const_cast<const char**>(buffers.address()), NULL);
#if defined(TORQUE_DEBUG) && defined(TORQUE_DEBUG_GFX)
FileStream stream;
if ( !stream.open( path.getFullPath()+"_DEBUG", Torque::FS::File::Write ) )
{
AssertISV(false, avar("GFXGLShader::initShader - failed to write debug shader '%s'.", path.getFullPath().c_str()));
}
for(int i = 0; i < buffers.size(); ++i)
stream.writeText(buffers[i]);
#endif
// Cleanup the shader source buffer. // Cleanup the shader source buffer.
for ( U32 i=0; i < buffers.size(); i++ ) for ( U32 i=0; i < buffers.size(); i++ )
dFree( buffers[i] ); dFree( buffers[i] );

View file

@ -25,7 +25,7 @@
#include "core/util/refBase.h" #include "core/util/refBase.h"
#include "gfx/gfxShader.h" #include "gfx/gfxShader.h"
#include "gfx/gl/ggl/ggl.h" #include "gfx/gl/tGL/tGL.h"
#include "core/util/tSignal.h" #include "core/util/tSignal.h"
#include "core/util/tDictionary.h" #include "core/util/tDictionary.h"
@ -43,6 +43,7 @@ public:
/// @name GFXShader interface /// @name GFXShader interface
/// @{ /// @{
virtual GFXShaderConstHandle* getShaderConstHandle(const String& name); virtual GFXShaderConstHandle* getShaderConstHandle(const String& name);
virtual GFXShaderConstHandle* findShaderConstHandle(const String& name);
/// Returns our list of shader constants, the material can get this and just set the constants it knows about /// Returns our list of shader constants, the material can get this and just set the constants it knows about
virtual const Vector<GFXShaderConstDesc>& getShaderConstDesc() const; virtual const Vector<GFXShaderConstDesc>& getShaderConstDesc() const;

View file

@ -25,12 +25,47 @@
#include "gfx/gl/gfxGLEnumTranslate.h" #include "gfx/gl/gfxGLEnumTranslate.h"
#include "gfx/gl/gfxGLUtils.h" #include "gfx/gl/gfxGLUtils.h"
#include "gfx/gl/gfxGLTextureObject.h" #include "gfx/gl/gfxGLTextureObject.h"
#include "core/crc.h"
namespace DictHash
{
inline U32 hash(const GFXSamplerStateDesc &data)
{
return CRC::calculateCRC(&data, sizeof(GFXSamplerStateDesc));;
}
}
GFXGLStateBlock::GFXGLStateBlock(const GFXStateBlockDesc& desc) : GFXGLStateBlock::GFXGLStateBlock(const GFXStateBlockDesc& desc) :
mDesc(desc), mDesc(desc),
mCachedHashValue(desc.getHashValue()) mCachedHashValue(desc.getHashValue())
{ {
if( !gglHasExtension(ARB_sampler_objects) )
return;
static Map<GFXSamplerStateDesc, U32> mSamplersMap;
for(int i = 0; i < TEXTURE_STAGE_COUNT; ++i)
{
GLuint &id = mSamplerObjects[i];
GFXSamplerStateDesc &ssd = mDesc.samplers[i];
Map<GFXSamplerStateDesc, U32>::Iterator itr = mSamplersMap.find(ssd);
if(itr == mSamplersMap.end())
{
glGenSamplers(1, &id);
glSamplerParameteri(id, GL_TEXTURE_MIN_FILTER, minificationFilter(ssd.minFilter, ssd.mipFilter, 1) );
glSamplerParameteri(id, GL_TEXTURE_MAG_FILTER, GFXGLTextureFilter[ssd.magFilter]);
glSamplerParameteri(id, GL_TEXTURE_WRAP_S, GFXGLTextureAddress[ssd.addressModeU]);
glSamplerParameteri(id, GL_TEXTURE_WRAP_T, GFXGLTextureAddress[ssd.addressModeV]);
glSamplerParameteri(id, GL_TEXTURE_WRAP_R, GFXGLTextureAddress[ssd.addressModeW]);
if(static_cast< GFXGLDevice* >( GFX )->supportsAnisotropic() )
glSamplerParameterf(id, GL_TEXTURE_MAX_ANISOTROPY_EXT, ssd.maxAnisotropy);
mSamplersMap[ssd] = id;
}
else
id = itr->value;
}
} }
GFXGLStateBlock::~GFXGLStateBlock() GFXGLStateBlock::~GFXGLStateBlock()
@ -72,11 +107,6 @@ void GFXGLStateBlock::activate(const GFXGLStateBlock* oldState)
if(STATE_CHANGE(blendOp)) if(STATE_CHANGE(blendOp))
glBlendEquation(GFXGLBlendOp[mDesc.blendOp]); glBlendEquation(GFXGLBlendOp[mDesc.blendOp]);
// Alpha testing
CHECK_TOGGLE_STATE(alphaTestEnable, GL_ALPHA_TEST);
if(STATE_CHANGE(alphaTestFunc) || STATE_CHANGE(alphaTestRef))
glAlphaFunc(GFXGLCmpFunc[mDesc.alphaTestFunc], (F32) mDesc.alphaTestRef * 1.0f/255.0f);
// Color write masks // Color write masks
if(STATE_CHANGE(colorWriteRed) || STATE_CHANGE(colorWriteBlue) || STATE_CHANGE(colorWriteGreen) || STATE_CHANGE(colorWriteAlpha)) if(STATE_CHANGE(colorWriteRed) || STATE_CHANGE(colorWriteBlue) || STATE_CHANGE(colorWriteGreen) || STATE_CHANGE(colorWriteAlpha))
glColorMask(mDesc.colorWriteRed, mDesc.colorWriteBlue, mDesc.colorWriteGreen, mDesc.colorWriteAlpha); glColorMask(mDesc.colorWriteRed, mDesc.colorWriteBlue, mDesc.colorWriteGreen, mDesc.colorWriteAlpha);
@ -117,12 +147,7 @@ void GFXGLStateBlock::activate(const GFXGLStateBlock* oldState)
glStencilOp(GFXGLStencilOp[mDesc.stencilFailOp], GFXGLStencilOp[mDesc.stencilZFailOp], GFXGLStencilOp[mDesc.stencilPassOp]); glStencilOp(GFXGLStencilOp[mDesc.stencilFailOp], GFXGLStencilOp[mDesc.stencilZFailOp], GFXGLStencilOp[mDesc.stencilPassOp]);
if(STATE_CHANGE(stencilWriteMask)) if(STATE_CHANGE(stencilWriteMask))
glStencilMask(mDesc.stencilWriteMask); glStencilMask(mDesc.stencilWriteMask);
// "Misc"
CHECK_TOGGLE_STATE(ffLighting, GL_LIGHTING);
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
CHECK_TOGGLE_STATE(vertexColorEnable, GL_COLOR_MATERIAL);
if(STATE_CHANGE(fillMode)) if(STATE_CHANGE(fillMode))
glPolygonMode(GL_FRONT_AND_BACK, GFXGLFillMode[mDesc.fillMode]); glPolygonMode(GL_FRONT_AND_BACK, GFXGLFillMode[mDesc.fillMode]);
@ -131,57 +156,15 @@ void GFXGLStateBlock::activate(const GFXGLStateBlock* oldState)
#undef TOGGLE_STATE #undef TOGGLE_STATE
#undef CHECK_TOGGLE_STATE #undef CHECK_TOGGLE_STATE
// TODO: states added for detail blend //sampler objects
if( gglHasExtension(ARB_sampler_objects) )
// Non per object texture mode states
for (U32 i = 0; i < getMin(getOwningDevice()->getNumSamplers(), (U32) TEXTURE_STAGE_COUNT); i++)
{ {
GFXGLTextureObject* tex = static_cast<GFXGLTextureObject*>(getOwningDevice()->getCurrentTexture(i)); for (U32 i = 0; i < getMin(getOwningDevice()->getNumSamplers(), (U32) TEXTURE_STAGE_COUNT); i++)
const GFXSamplerStateDesc &ssd = mDesc.samplers[i];
bool updateTexParam = true;
glActiveTexture(GL_TEXTURE0 + i);
switch (ssd.textureColorOp)
{ {
case GFXTOPDisable : if(!oldState || oldState->mSamplerObjects[i] != mSamplerObjects[i])
if(!tex) glBindSampler(i, mSamplerObjects[i] );
break;
glDisable(GL_TEXTURE_2D);
updateTexParam = false;
break;
case GFXTOPModulate :
glEnable(GL_TEXTURE_2D);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
break;
case GFXTOPAdd :
glEnable(GL_TEXTURE_2D);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD);
break;
default :
glEnable(GL_TEXTURE_2D);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
break;
} }
}
#define SSF(state, enum, value, tex) if(!oldState || oldState->mDesc.samplers[i].state != mDesc.samplers[i].state) glTexParameteri(tex->getBinding(), enum, value) // TODO: states added for detail blend
#define SSW(state, enum, value, tex) if(!oldState || oldState->mDesc.samplers[i].state != mDesc.samplers[i].state) glTexParameteri(tex->getBinding(), enum, !tex->mIsNPoT2 ? value : GL_CLAMP_TO_EDGE)
// Per object texture mode states.
// TODO: Check dirty flag of samplers[i] and don't do this if it's dirty (it'll happen in the texture bind)
if (updateTexParam && tex)
{
SSF(minFilter, GL_TEXTURE_MIN_FILTER, minificationFilter(ssd.minFilter, ssd.mipFilter, tex->mMipLevels), tex);
SSF(mipFilter, GL_TEXTURE_MIN_FILTER, minificationFilter(ssd.minFilter, ssd.mipFilter, tex->mMipLevels), tex);
SSF(magFilter, GL_TEXTURE_MAG_FILTER, GFXGLTextureFilter[ssd.magFilter], tex);
SSW(addressModeU, GL_TEXTURE_WRAP_S, GFXGLTextureAddress[ssd.addressModeU], tex);
SSW(addressModeV, GL_TEXTURE_WRAP_T, GFXGLTextureAddress[ssd.addressModeV], tex);
if( ( !oldState || oldState->mDesc.samplers[i].maxAnisotropy != ssd.maxAnisotropy ) &&
static_cast< GFXGLDevice* >( GFX )->supportsAnisotropic() )
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, ssd.maxAnisotropy);
if( ( !oldState || oldState->mDesc.samplers[i].mipLODBias != ssd.mipLODBias ) )
glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, ssd.mipLODBias);
}
}
#undef SSF
#undef SSW
} }

View file

@ -25,6 +25,11 @@
#include "gfx/gfxStateBlock.h" #include "gfx/gfxStateBlock.h"
namespace DictHash
{
U32 hash(const GFXSamplerStateDesc &data);
}
class GFXGLStateBlock : public GFXStateBlock class GFXGLStateBlock : public GFXStateBlock
{ {
public: public:
@ -58,6 +63,7 @@ public:
private: private:
GFXStateBlockDesc mDesc; GFXStateBlockDesc mDesc;
U32 mCachedHashValue; U32 mCachedHashValue;
U32 mSamplerObjects[TEXTURE_STAGE_COUNT];
}; };
typedef StrongRefPtr<GFXGLStateBlock> GFXGLStateBlockRef; typedef StrongRefPtr<GFXGLStateBlock> GFXGLStateBlockRef;

View file

@ -0,0 +1,133 @@
#ifndef GFX_GL_STATE_CACHE
#define GFX_GL_STATE_CACHE
/// GFXGLStateCache store OpenGL state to avoid performance penalities of glGet* calls
/// GL_TEXTURE_1D/2D/3D, GL_FRAMEBUFFER, GL_ARRAY_BUFFER, GL_ELEMENT_ARRAY_BUFFER
class GFXGLStateCache
{
public:
GFXGLStateCache()
{
mActiveTexture = 0;
mBindedVBO = 0;
mBindedIBO = 0;
mBindedFBO_W = 0;
mBindedFBO_R = 0;
mVertexAttribActive = 0;
}
class TextureUnit
{
public:
TextureUnit() : mTexture1D(0), mTexture2D(0), mTexture3D(0), mTextureCube(0)
{
}
GLuint mTexture1D, mTexture2D, mTexture3D, mTextureCube;
};
/// after glBindTexture
void setCacheBindedTex(U32 texUnit, GLenum biding, GLuint handle)
{
mActiveTexture = texUnit;
switch (biding)
{
case GL_TEXTURE_2D:
mTextureUnits[mActiveTexture].mTexture2D = handle;
break;
case GL_TEXTURE_3D:
mTextureUnits[mActiveTexture].mTexture3D = handle;
break;
case GL_TEXTURE_1D:
mTextureUnits[mActiveTexture].mTexture1D = handle;
break;
case GL_TEXTURE_CUBE_MAP:
mTextureUnits[mActiveTexture].mTextureCube = handle;
break;
default:
AssertFatal(0, avar("GFXGLStateCache::setCacheBindedTex - binding (%x) not supported.", biding) );
return;
}
}
/// after opengl object binded
void setCacheBinded(GLenum biding, GLuint handle)
{
switch (biding)
{
case GL_TEXTURE_2D:
mTextureUnits[mActiveTexture].mTexture2D = handle;
break;
case GL_TEXTURE_3D:
mTextureUnits[mActiveTexture].mTexture3D = handle;
break;
case GL_TEXTURE_1D:
mTextureUnits[mActiveTexture].mTexture1D = handle;
break;
case GL_TEXTURE_CUBE_MAP:
mTextureUnits[mActiveTexture].mTextureCube = handle;
break;
case GL_FRAMEBUFFER:
mBindedFBO_W = mBindedFBO_R = handle;
break;
case GL_DRAW_FRAMEBUFFER:
mBindedFBO_W = handle;
break;
case GL_READ_FRAMEBUFFER:
mBindedFBO_R = handle;
break;
case GL_ARRAY_BUFFER:
mBindedVBO = handle;
break;
case GL_ELEMENT_ARRAY_BUFFER:
mBindedIBO = handle;
break;
default:
AssertFatal(0, avar("GFXGLStateCache::setCacheBinded - binding (%x) not supported.", biding) );
break;
}
}
GLuint getCacheBinded(GLenum biding) const
{
switch (biding)
{
case GL_TEXTURE_2D:
return mTextureUnits[mActiveTexture].mTexture2D;
case GL_TEXTURE_3D:
return mTextureUnits[mActiveTexture].mTexture3D;
case GL_TEXTURE_1D:
return mTextureUnits[mActiveTexture].mTexture1D;
case GL_TEXTURE_CUBE_MAP:
return mTextureUnits[mActiveTexture].mTextureCube;
case GL_DRAW_FRAMEBUFFER:
return mBindedFBO_W;
case GL_READ_FRAMEBUFFER:
return mBindedFBO_R;
case GL_ARRAY_BUFFER:
return mBindedVBO;
case GL_ELEMENT_ARRAY_BUFFER:
return mBindedIBO;
default:
AssertFatal(0, avar("GFXGLStateCache::getCacheBinded - binding (%x) not supported.", biding) );
return 0;
}
}
/// after glActiveTexture
void setCacheActiveTexture(U32 unit) { mActiveTexture = unit; }
U32 getCacheActiveTexture() const { return mActiveTexture; }
/// for cache glEnableVertexAttribArray / glDisableVertexAttribArray
void setCacheVertexAttribActive(U32 activeMask) { mVertexAttribActive = activeMask; }
U32 getCacheVertexAttribActive() const { return mVertexAttribActive; }
protected:
GLuint mActiveTexture, mBindedVBO, mBindedIBO, mBindedFBO_W, mBindedFBO_R;
TextureUnit mTextureUnits[TEXTURE_STAGE_COUNT];
U32 mVertexAttribActive;
};
#endif

View file

@ -65,6 +65,7 @@ GFXTextureObject *GFXGLTextureManager::_createTextureObject( U32 height,
AssertFatal( dynamic_cast<GFXGLTextureObject*>( inTex ), "GFXGLTextureManager::_createTexture() - Bad inTex type!" ); AssertFatal( dynamic_cast<GFXGLTextureObject*>( inTex ), "GFXGLTextureManager::_createTexture() - Bad inTex type!" );
retTex = static_cast<GFXGLTextureObject*>( inTex ); retTex = static_cast<GFXGLTextureObject*>( inTex );
retTex->release(); retTex->release();
retTex->reInit();
} }
else else
{ {
@ -98,23 +99,20 @@ void GFXGLTextureManager::innerCreateTexture( GFXGLTextureObject *retTex,
retTex->mIsZombie = false; retTex->mIsZombie = false;
retTex->mIsNPoT2 = false; retTex->mIsNPoT2 = false;
GLenum binding = (depth == 0) ? GL_TEXTURE_2D : GL_TEXTURE_3D; GLenum binding = ( (height == 1 || width == 1) && ( height != width ) ) ? GL_TEXTURE_1D : ( (depth == 0) ? GL_TEXTURE_2D : GL_TEXTURE_3D );
if((profile->testFlag(GFXTextureProfile::RenderTarget) || profile->testFlag(GFXTextureProfile::ZTarget)) && (!isPow2(width) || !isPow2(height)) && !depth) if((profile->testFlag(GFXTextureProfile::RenderTarget) || profile->testFlag(GFXTextureProfile::ZTarget)) && (!isPow2(width) || !isPow2(height)) && !depth)
retTex->mIsNPoT2 = true; retTex->mIsNPoT2 = true;
retTex->mBinding = binding; retTex->mBinding = binding;
// Bind it // Bind it
glActiveTexture(GL_TEXTURE0); PRESERVE_TEXTURE(binding);
PRESERVE_2D_TEXTURE(); glBindTexture(retTex->getBinding(), retTex->getHandle());
PRESERVE_3D_TEXTURE();
glBindTexture(binding, retTex->getHandle());
// Create it // Create it
// TODO: Reenable mipmaps on render targets when Apple fixes their drivers // @todo OPENGL - Creating mipmaps for compressed formats. Not supported on OpenGL ES and bugged on AMD. We use mipmaps present on file.
if(forceMips && !retTex->mIsNPoT2) if( forceMips && !retTex->mIsNPoT2 && !isCompressedFormat(format) )
{ {
glTexParameteri(binding, GL_GENERATE_MIPMAP_SGIS, GL_TRUE); retTex->mMipLevels = numMipLevels > 1 ? numMipLevels : 0;
retTex->mMipLevels = 0;
} }
else if(profile->testFlag(GFXTextureProfile::NoMipmap) || profile->testFlag(GFXTextureProfile::RenderTarget) || numMipLevels == 1 || retTex->mIsNPoT2) else if(profile->testFlag(GFXTextureProfile::NoMipmap) || profile->testFlag(GFXTextureProfile::RenderTarget) || numMipLevels == 1 || retTex->mIsNPoT2)
{ {
@ -122,10 +120,11 @@ void GFXGLTextureManager::innerCreateTexture( GFXGLTextureObject *retTex,
} }
else else
{ {
glTexParameteri(binding, GL_GENERATE_MIPMAP_SGIS, GL_TRUE); retTex->mMipLevels = numMipLevels;
retTex->mMipLevels = 0;
} }
// @todo OPENGL - OpenGL ES2 not support mipmaps on NPOT textures
#if 0
if(!retTex->mIsNPoT2) if(!retTex->mIsNPoT2)
{ {
if(!isPow2(width)) if(!isPow2(width))
@ -135,23 +134,82 @@ void GFXGLTextureManager::innerCreateTexture( GFXGLTextureObject *retTex,
if(depth && !isPow2(depth)) if(depth && !isPow2(depth))
depth = getNextPow2(depth); depth = getNextPow2(depth);
} }
#endif
AssertFatal(GFXGLTextureInternalFormat[format] != GL_ZERO, "GFXGLTextureManager::innerCreateTexture - invalid internal format"); AssertFatal(GFXGLTextureInternalFormat[format] != GL_ZERO, "GFXGLTextureManager::innerCreateTexture - invalid internal format");
AssertFatal(GFXGLTextureFormat[format] != GL_ZERO, "GFXGLTextureManager::innerCreateTexture - invalid format"); AssertFatal(GFXGLTextureFormat[format] != GL_ZERO, "GFXGLTextureManager::innerCreateTexture - invalid format");
AssertFatal(GFXGLTextureType[format] != GL_ZERO, "GFXGLTextureManager::innerCreateTexture - invalid type"); AssertFatal(GFXGLTextureType[format] != GL_ZERO, "GFXGLTextureManager::innerCreateTexture - invalid type");
if(binding != GL_TEXTURE_3D) //calculate num mipmaps
glTexImage2D(binding, 0, GFXGLTextureInternalFormat[format], width, height, 0, GFXGLTextureFormat[format], GFXGLTextureType[format], NULL); if(retTex->mMipLevels == 0)
else retTex->mMipLevels = getMaxMipmaps(width, height, 1);
glTexImage3D(GL_TEXTURE_3D, 0, GFXGLTextureInternalFormat[format], width, height, depth, 0, GFXGLTextureFormat[format], GFXGLTextureType[format], NULL);
glTexParameteri(binding, GL_TEXTURE_MAX_LEVEL, retTex->mMipLevels-1 );
if( gglHasExtension(ARB_texture_storage) )
{
if(binding == GL_TEXTURE_2D)
glTexStorage2D( retTex->getBinding(), retTex->mMipLevels, GFXGLTextureInternalFormat[format], width, height );
else if(binding == GL_TEXTURE_1D)
glTexStorage1D( retTex->getBinding(), retTex->mMipLevels, GFXGLTextureInternalFormat[format], getMax(width, height) );
else
glTexStorage3D( retTex->getBinding(), retTex->mMipLevels, GFXGLTextureInternalFormat[format], width, height, depth );
}
else
{
//If it wasn't for problems on amd drivers this next part could be really simplified and we wouldn't need to go through manually creating our
//mipmap pyramid and instead just use glGenerateMipmap
if(isCompressedFormat(format))
{
AssertFatal(binding == GL_TEXTURE_2D,
"GFXGLTextureManager::innerCreateTexture - Only compressed 2D textures are supported");
U32 tempWidth = width;
U32 tempHeight = height;
U32 size = getCompressedSurfaceSize(format,height,width);
//Fill compressed images with 0's
U8 *pTemp = (U8*)dMalloc(sizeof(U8)*size);
dMemset(pTemp,0,size);
for(U32 i=0;i< retTex->mMipLevels;i++)
{
tempWidth = getMax( U32(1), width >> i );
tempHeight = getMax( U32(1), height >> i );
size = getCompressedSurfaceSize(format,width,height,i);
glCompressedTexImage2D(binding,i,GFXGLTextureInternalFormat[format],tempWidth,tempHeight,0,size,pTemp);
}
dFree(pTemp);
}
else
{
if(binding == GL_TEXTURE_2D)
glTexImage2D(binding, 0, GFXGLTextureInternalFormat[format], width, height, 0, GFXGLTextureFormat[format], GFXGLTextureType[format], NULL);
else if(binding == GL_TEXTURE_1D)
glTexImage1D(binding, 0, GFXGLTextureInternalFormat[format], (width > 1 ? width : height), 0, GFXGLTextureFormat[format], GFXGLTextureType[format], NULL);
else
glTexImage3D(GL_TEXTURE_3D, 0, GFXGLTextureInternalFormat[format], width, height, depth, 0, GFXGLTextureFormat[format], GFXGLTextureType[format], NULL);
if(retTex->mMipLevels > 1)
glGenerateMipmap(binding);
}
}
// Complete the texture // Complete the texture
glTexParameteri(binding, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // Complete the texture - this does get changed later but we need to complete the texture anyway
if(retTex->mMipLevels == 1)
glTexParameteri(binding, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
else
glTexParameteri(binding, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(binding, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(binding, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(binding, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(binding, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(binding, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(binding, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
if(binding == GL_TEXTURE_3D) if(binding == GL_TEXTURE_3D)
glTexParameteri(binding, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); glTexParameteri(binding, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
if(GFXGLTextureSwizzle[format])
glTexParameteriv(binding, GL_TEXTURE_SWIZZLE_RGBA, GFXGLTextureSwizzle[format]);
// Get the size from GL (you never know...) // Get the size from GL (you never know...)
GLint texHeight, texWidth, texDepth = 0; GLint texHeight, texWidth, texDepth = 0;
@ -173,49 +231,60 @@ static void _fastTextureLoad(GFXGLTextureObject* texture, GBitmap* pDL)
glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, texture->getBuffer()); glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, texture->getBuffer());
U32 bufSize = pDL->getWidth(0) * pDL->getHeight(0) * pDL->getBytesPerPixel(); U32 bufSize = pDL->getWidth(0) * pDL->getHeight(0) * pDL->getBytesPerPixel();
glBufferData(GL_PIXEL_UNPACK_BUFFER_ARB, bufSize, NULL, GL_STREAM_DRAW); glBufferData(GL_PIXEL_UNPACK_BUFFER_ARB, bufSize, NULL, GL_STREAM_DRAW);
U8* pboMemory = (U8*)glMapBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY);
if(pDL->getFormat() == GFXFormatR8G8B8A8 || pDL->getFormat() == GFXFormatR8G8B8X8) if(pDL->getFormat() == GFXFormatR8G8B8A8 || pDL->getFormat() == GFXFormatR8G8B8X8)
{
FrameAllocatorMarker mem;
U8* pboMemory = (U8*)mem.alloc(bufSize);
GFX->getDeviceSwizzle32()->ToBuffer(pboMemory, pDL->getBits(0), bufSize); GFX->getDeviceSwizzle32()->ToBuffer(pboMemory, pDL->getBits(0), bufSize);
glBufferSubData(GL_PIXEL_UNPACK_BUFFER_ARB, 0, bufSize, pboMemory );
}
else else
dMemcpy(pboMemory, pDL->getBits(0), bufSize); {
glBufferSubData(GL_PIXEL_UNPACK_BUFFER_ARB, 0, bufSize, pDL->getBits(0) );
}
glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER_ARB); if(texture->getBinding() == GL_TEXTURE_2D)
glTexSubImage2D(texture->getBinding(), 0, 0, 0, pDL->getWidth(0), pDL->getHeight(0), GFXGLTextureFormat[pDL->getFormat()], GFXGLTextureType[pDL->getFormat()], NULL);
glTexSubImage2D(texture->getBinding(), 0, 0, 0, pDL->getWidth(0), pDL->getHeight(0), GFXGLTextureFormat[pDL->getFormat()], GFXGLTextureType[pDL->getFormat()], NULL); else
glTexSubImage1D(texture->getBinding(), 0, 0, (pDL->getWidth(0) > 1 ? pDL->getWidth(0) : pDL->getHeight(0)), GFXGLTextureFormat[pDL->getFormat()], GFXGLTextureType[pDL->getFormat()], NULL);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, 0); glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
} }
static void _slowTextureLoad(GFXGLTextureObject* texture, GBitmap* pDL) static void _slowTextureLoad(GFXGLTextureObject* texture, GBitmap* pDL)
{ {
glTexSubImage2D(texture->getBinding(), 0, 0, 0, pDL->getWidth(0), pDL->getHeight(0), GFXGLTextureFormat[pDL->getFormat()], GFXGLTextureType[pDL->getFormat()], pDL->getBits(0)); if(texture->getBinding() == GL_TEXTURE_2D)
glTexSubImage2D(texture->getBinding(), 0, 0, 0, pDL->getWidth(0), pDL->getHeight(0), GFXGLTextureFormat[pDL->getFormat()], GFXGLTextureType[pDL->getFormat()], pDL->getBits(0));
else
glTexSubImage1D(texture->getBinding(), 0, 0, (pDL->getWidth(0) > 1 ? pDL->getWidth(0) : pDL->getHeight(0)), GFXGLTextureFormat[pDL->getFormat()], GFXGLTextureType[pDL->getFormat()], pDL->getBits(0));
} }
bool GFXGLTextureManager::_loadTexture(GFXTextureObject *aTexture, GBitmap *pDL) bool GFXGLTextureManager::_loadTexture(GFXTextureObject *aTexture, GBitmap *pDL)
{ {
GFXGLTextureObject *texture = static_cast<GFXGLTextureObject*>(aTexture); GFXGLTextureObject *texture = static_cast<GFXGLTextureObject*>(aTexture);
AssertFatal(texture->getBinding() == GL_TEXTURE_2D, AssertFatal(texture->getBinding() == GL_TEXTURE_1D || texture->getBinding() == GL_TEXTURE_2D,
"GFXGLTextureManager::_loadTexture(GBitmap) - This method can only be used with 2D textures"); "GFXGLTextureManager::_loadTexture(GBitmap) - This method can only be used with 1D/2D textures");
if(texture->getBinding() != GL_TEXTURE_2D) if(texture->getBinding() == GL_TEXTURE_3D)
return false; return false;
// No 24bit formats. // No 24bit formats.
if(pDL->getFormat() == GFXFormatR8G8B8) if(pDL->getFormat() == GFXFormatR8G8B8)
pDL->setFormat(GFXFormatR8G8B8A8); pDL->setFormat(GFXFormatR8G8B8A8);
// Bind to edit // Bind to edit
glActiveTexture(GL_TEXTURE0); PRESERVE_TEXTURE(texture->getBinding());
PRESERVE_2D_TEXTURE();
glBindTexture(texture->getBinding(), texture->getHandle()); glBindTexture(texture->getBinding(), texture->getHandle());
texture->mFormat = pDL->getFormat();
if(pDL->getFormat() == GFXFormatR8G8B8A8 || pDL->getFormat() == GFXFormatR8G8B8X8) if(pDL->getFormat() == GFXFormatR8G8B8A8 || pDL->getFormat() == GFXFormatR8G8B8X8)
_fastTextureLoad(texture, pDL); _fastTextureLoad(texture, pDL);
else else
_slowTextureLoad(texture, pDL); _slowTextureLoad(texture, pDL);
glBindTexture(texture->getBinding(), 0); if(texture->getMipLevels() != 1)
glGenerateMipmap(texture->getBinding());
return true; return true;
} }
@ -231,15 +300,15 @@ bool GFXGLTextureManager::_loadTexture(GFXTextureObject *aTexture, DDSFile *dds)
if(texture->getBinding() != GL_TEXTURE_2D) if(texture->getBinding() != GL_TEXTURE_2D)
return false; return false;
glActiveTexture(GL_TEXTURE0); PRESERVE_TEXTURE(texture->getBinding());
PRESERVE_2D_TEXTURE();
glBindTexture(texture->getBinding(), texture->getHandle()); glBindTexture(texture->getBinding(), texture->getHandle());
texture->mFormat = dds->mFormat;
U32 numMips = dds->mSurfaces[0]->mMips.size(); U32 numMips = dds->mSurfaces[0]->mMips.size();
if(GFX->getCardProfiler()->queryProfile("GL::Workaround::noManualMips")) if(GFX->getCardProfiler()->queryProfile("GL::Workaround::noManualMips"))
numMips = 1; numMips = 1;
for(U32 i = 0; i < numMips; i++) for(U32 i = 0; i < numMips; i++)
{ {
if(dds->mFormat == GFXFormatDXT1 || dds->mFormat == GFXFormatDXT3 || dds->mFormat == GFXFormatDXT5) if(isCompressedFormat(dds->mFormat))
{ {
if((!isPow2(dds->getWidth()) || !isPow2(dds->getHeight())) && GFX->getCardProfiler()->queryProfile("GL::Workaround::noCompressedNPoTTextures")) if((!isPow2(dds->getWidth()) || !isPow2(dds->getHeight())) && GFX->getCardProfiler()->queryProfile("GL::Workaround::noCompressedNPoTTextures"))
{ {
@ -266,7 +335,9 @@ bool GFXGLTextureManager::_loadTexture(GFXTextureObject *aTexture, DDSFile *dds)
else else
glTexSubImage2D(texture->getBinding(), i, 0, 0, dds->getWidth(i), dds->getHeight(i), GFXGLTextureFormat[dds->mFormat], GFXGLTextureType[dds->mFormat], dds->mSurfaces[0]->mMips[i]); glTexSubImage2D(texture->getBinding(), i, 0, 0, dds->getWidth(i), dds->getHeight(i), GFXGLTextureFormat[dds->mFormat], GFXGLTextureType[dds->mFormat], dds->mSurfaces[0]->mMips[i]);
} }
glBindTexture(texture->getBinding(), 0);
if(numMips !=1 && !isCompressedFormat(dds->mFormat))
glGenerateMipmap(texture->getBinding());
return true; return true;
} }
@ -278,11 +349,9 @@ bool GFXGLTextureManager::_loadTexture(GFXTextureObject *aTexture, void *raw)
GFXGLTextureObject* texture = static_cast<GFXGLTextureObject*>(aTexture); GFXGLTextureObject* texture = static_cast<GFXGLTextureObject*>(aTexture);
glActiveTexture(GL_TEXTURE0);
PRESERVE_3D_TEXTURE(); PRESERVE_3D_TEXTURE();
glBindTexture(GL_TEXTURE_3D, texture->getHandle()); glBindTexture(texture->getBinding(), texture->getHandle());
glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, texture->getWidth(), texture->getHeight(), texture->getDepth(), GFXGLTextureFormat[texture->mFormat], GFXGLTextureType[texture->mFormat], raw); glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, texture->getWidth(), texture->getHeight(), texture->getDepth(), GFXGLTextureFormat[texture->mFormat], GFXGLTextureType[texture->mFormat], raw);
glBindTexture(GL_TEXTURE_3D, 0);
return true; return true;
} }

View file

@ -26,7 +26,7 @@
#include "gfx/gfxDevice.h" #include "gfx/gfxDevice.h"
#include "gfx/gfxTextureManager.h" #include "gfx/gfxTextureManager.h"
#include "gfx/gl/gfxGLTextureObject.h" #include "gfx/gl/gfxGLTextureObject.h"
#include "gfx/gl/ggl/ggl.h" #include "gfx/gl/tGL/tGL.h"
class GFXGLTextureManager : public GFXTextureManager class GFXGLTextureManager : public GFXTextureManager
{ {

View file

@ -21,7 +21,7 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#include "console/console.h" #include "console/console.h"
#include "gfx/gl/ggl/ggl.h" #include "gfx/gl/tGL/tGL.h"
#include "math/mRect.h" #include "math/mRect.h"
#include "gfx/gl/gfxGLTextureObject.h" #include "gfx/gl/gfxGLTextureObject.h"
#include "gfx/gfxDevice.h" #include "gfx/gfxDevice.h"
@ -37,7 +37,10 @@ GFXGLTextureObject::GFXGLTextureObject(GFXDevice * aDevice, GFXTextureProfile *p
mBytesPerTexel(4), mBytesPerTexel(4),
mLockedRectRect(0, 0, 0, 0), mLockedRectRect(0, 0, 0, 0),
mGLDevice(static_cast<GFXGLDevice*>(mDevice)), mGLDevice(static_cast<GFXGLDevice*>(mDevice)),
mZombieCache(NULL) mZombieCache(NULL),
mNeedInitSamplerState(true),
mFrameAllocatorMark(0),
mFrameAllocatorPtr(NULL)
{ {
AssertFatal(dynamic_cast<GFXGLDevice*>(mDevice), "GFXGLTextureObject::GFXGLTextureObject - Invalid device type, expected GFXGLDevice!"); AssertFatal(dynamic_cast<GFXGLDevice*>(mDevice), "GFXGLTextureObject::GFXGLTextureObject - Invalid device type, expected GFXGLDevice!");
glGenTextures(1, &mHandle); glGenTextures(1, &mHandle);
@ -46,6 +49,7 @@ GFXGLTextureObject::GFXGLTextureObject(GFXDevice * aDevice, GFXTextureProfile *p
GFXGLTextureObject::~GFXGLTextureObject() GFXGLTextureObject::~GFXGLTextureObject()
{ {
glDeleteTextures(1, &mHandle);
glDeleteBuffers(1, &mBuffer); glDeleteBuffers(1, &mBuffer);
delete[] mZombieCache; delete[] mZombieCache;
kill(); kill();
@ -70,12 +74,16 @@ GFXLockedRect* GFXGLTextureObject::lock(U32 mipLevel, RectI *inRect)
} }
mLockedRect.pitch = mLockedRectRect.extent.x * mBytesPerTexel; mLockedRect.pitch = mLockedRectRect.extent.x * mBytesPerTexel;
glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, mBuffer);
// CodeReview [ags 12/19/07] This one texel boundary is necessary to keep the clipmap code from crashing. Figure out why. // CodeReview [ags 12/19/07] This one texel boundary is necessary to keep the clipmap code from crashing. Figure out why.
glBufferData(GL_PIXEL_UNPACK_BUFFER_ARB, (mLockedRectRect.extent.x + 1) * (mLockedRectRect.extent.y + 1) * mBytesPerTexel, NULL, GL_STREAM_DRAW); U32 size = (mLockedRectRect.extent.x + 1) * (mLockedRectRect.extent.y + 1) * mBytesPerTexel;
mLockedRect.bits = (U8*)glMapBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY); AssertFatal(!mFrameAllocatorMark && !mFrameAllocatorPtr, "");
glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, 0); mFrameAllocatorMark = FrameAllocator::getWaterMark();
mFrameAllocatorPtr = (U8*)FrameAllocator::alloc( size );
mLockedRect.bits = mFrameAllocatorPtr;
#if TORQUE_DEBUG
mFrameAllocatorMarkGuard = FrameAllocator::getWaterMark();
#endif
if( !mLockedRect.bits ) if( !mLockedRect.bits )
return NULL; return NULL;
@ -88,20 +96,27 @@ void GFXGLTextureObject::unlock(U32 mipLevel)
if(!mLockedRect.bits) if(!mLockedRect.bits)
return; return;
glActiveTexture(GL_TEXTURE0); PRESERVE_TEXTURE(mBinding);
U32 boundTexture; glBindTexture(mBinding, mHandle);
glGetIntegerv(GL_TEXTURE_BINDING_2D, (GLint*)&boundTexture);
glBindTexture(GL_TEXTURE_2D, mHandle);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, mBuffer); glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, mBuffer);
glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER_ARB); glBufferData(GL_PIXEL_UNPACK_BUFFER_ARB, (mLockedRectRect.extent.x + 1) * (mLockedRectRect.extent.y + 1) * mBytesPerTexel, mFrameAllocatorPtr, GL_STREAM_DRAW);
glTexSubImage2D(GL_TEXTURE_2D, mipLevel, mLockedRectRect.point.x, mLockedRectRect.point.y,
mLockedRectRect.extent.x, mLockedRectRect.extent.y, GL_BGRA, GL_UNSIGNED_BYTE, NULL); if(mBinding == GL_TEXTURE_2D)
glTexSubImage2D(mBinding, mipLevel, mLockedRectRect.point.x, mLockedRectRect.point.y,
mLockedRectRect.extent.x, mLockedRectRect.extent.y, GFXGLTextureFormat[mFormat], GFXGLTextureType[mFormat], NULL);
else if(mBinding == GL_TEXTURE_1D)
glTexSubImage1D(mBinding, mipLevel, (mLockedRectRect.point.x > 1 ? mLockedRectRect.point.x : mLockedRectRect.point.y),
(mLockedRectRect.extent.x > 1 ? mLockedRectRect.extent.x : mLockedRectRect.extent.y), GFXGLTextureFormat[mFormat], GFXGLTextureType[mFormat], NULL);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, 0); glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
mLockedRect.bits = NULL; mLockedRect.bits = NULL;
#if TORQUE_DEBUG
glBindTexture(GL_TEXTURE_2D, boundTexture); AssertFatal(mFrameAllocatorMarkGuard == FrameAllocator::getWaterMark(), "");
#endif
FrameAllocator::setWaterMark(mFrameAllocatorMark);
mFrameAllocatorMark = 0;
mFrameAllocatorPtr = NULL;
} }
void GFXGLTextureObject::release() void GFXGLTextureObject::release()
@ -113,28 +128,91 @@ void GFXGLTextureObject::release()
mBuffer = 0; mBuffer = 0;
} }
void GFXGLTextureObject::reInit()
{
AssertFatal(!mHandle && !mBuffer,"Must release before reInit");
glGenTextures(1, &mHandle);
glGenBuffers(1, &mBuffer);
}
bool GFXGLTextureObject::copyToBmp(GBitmap * bmp) bool GFXGLTextureObject::copyToBmp(GBitmap * bmp)
{ {
GLint oldTex; if (!bmp)
glGetIntegerv(0x8069, &oldTex); return false;
glBindTexture(GL_TEXTURE_2D, mHandle);
// check format limitations
// at the moment we only support RGBA for the source (other 4 byte formats should
// be easy to add though)
AssertFatal(mFormat == GFXFormatR8G8B8A8, "GFXGLTextureObject::copyToBmp - invalid format");
AssertFatal(bmp->getFormat() == GFXFormatR8G8B8A8 || bmp->getFormat() == GFXFormatR8G8B8, "GFXGLTextureObject::copyToBmp - invalid format");
if(mFormat != GFXFormatR8G8B8A8)
return false;
if(bmp->getFormat() != GFXFormatR8G8B8A8 && bmp->getFormat() != GFXFormatR8G8B8)
return false;
AssertFatal(bmp->getWidth() == getWidth(), "GFXGLTextureObject::copyToBmp - invalid size");
AssertFatal(bmp->getHeight() == getHeight(), "GFXGLTextureObject::copyToBmp - invalid size");
PROFILE_SCOPE(GFXGLTextureObject_copyToBmp);
PRESERVE_TEXTURE(mBinding);
glBindTexture(mBinding, mHandle);
U8 dstBytesPerPixel = GFXFormat_getByteSize( bmp->getFormat() );
U8 srcBytesPerPixel = GFXFormat_getByteSize( mFormat );
if(dstBytesPerPixel == srcBytesPerPixel)
{
glGetTexImage(mBinding, 0, GFXGLTextureFormat[mFormat], GFXGLTextureType[mFormat], bmp->getWritableBits());
return true;
}
FrameAllocatorMarker mem;
GLint textureFormat = GFXGLTextureFormat[bmp->getFormat()]; U32 srcPixelCount = mTextureSize.x * mTextureSize.y;
// Don't swizzle outgoing textures. U8 *dest = bmp->getWritableBits();
if(textureFormat == GL_BGRA) U8 *orig = (U8*)mem.alloc(srcPixelCount * srcBytesPerPixel);
textureFormat = GL_RGBA;
glGetTexImage(mBinding, 0, GFXGLTextureFormat[mFormat], GFXGLTextureType[mFormat], orig);
glGetTexImage(GL_TEXTURE_2D, 0, textureFormat, GL_UNSIGNED_BYTE, bmp->getWritableBits()); for(int i = 0; i < srcPixelCount; ++i)
{
glBindTexture(GL_TEXTURE_2D, oldTex); dest[0] = orig[0];
dest[1] = orig[1];
dest[2] = orig[2];
if(dstBytesPerPixel == 4)
dest[3] = orig[3];
orig += srcBytesPerPixel;
dest += dstBytesPerPixel;
}
return true; return true;
} }
void GFXGLTextureObject::bind(U32 textureUnit) const void GFXGLTextureObject::initSamplerState(const GFXSamplerStateDesc &ssd)
{
glTexParameteri(mBinding, GL_TEXTURE_MIN_FILTER, minificationFilter(ssd.minFilter, ssd.mipFilter, mMipLevels));
glTexParameteri(mBinding, GL_TEXTURE_MAG_FILTER, GFXGLTextureFilter[ssd.magFilter]);
glTexParameteri(mBinding, GL_TEXTURE_WRAP_S, !mIsNPoT2 ? GFXGLTextureAddress[ssd.addressModeU] : GL_CLAMP_TO_EDGE);
glTexParameteri(mBinding, GL_TEXTURE_WRAP_T, !mIsNPoT2 ? GFXGLTextureAddress[ssd.addressModeV] : GL_CLAMP_TO_EDGE);
if(mBinding == GL_TEXTURE_3D)
glTexParameteri(mBinding, GL_TEXTURE_WRAP_R, GFXGLTextureAddress[ssd.addressModeW]);
if(static_cast< GFXGLDevice* >( GFX )->supportsAnisotropic() )
glTexParameterf(mBinding, GL_TEXTURE_MAX_ANISOTROPY_EXT, ssd.maxAnisotropy);
mNeedInitSamplerState = false;
mSampler = ssd;
}
void GFXGLTextureObject::bind(U32 textureUnit)
{ {
glActiveTexture(GL_TEXTURE0 + textureUnit); glActiveTexture(GL_TEXTURE0 + textureUnit);
glBindTexture(mBinding, mHandle); glBindTexture(mBinding, mHandle);
glEnable(mBinding); GFXGL->getOpenglCache()->setCacheBindedTex(textureUnit, mBinding, mHandle);
if( gglHasExtension(ARB_sampler_objects) )
return;
GFXGLStateBlockRef sb = mGLDevice->getCurrentStateBlock(); GFXGLStateBlockRef sb = mGLDevice->getCurrentStateBlock();
AssertFatal(sb, "GFXGLTextureObject::bind - No active stateblock!"); AssertFatal(sb, "GFXGLTextureObject::bind - No active stateblock!");
@ -142,26 +220,41 @@ void GFXGLTextureObject::bind(U32 textureUnit) const
return; return;
const GFXSamplerStateDesc ssd = sb->getDesc().samplers[textureUnit]; const GFXSamplerStateDesc ssd = sb->getDesc().samplers[textureUnit];
glTexParameteri(mBinding, GL_TEXTURE_MIN_FILTER, minificationFilter(ssd.minFilter, ssd.mipFilter, mMipLevels));
glTexParameteri(mBinding, GL_TEXTURE_MAG_FILTER, GFXGLTextureFilter[ssd.magFilter]);
glTexParameteri(mBinding, GL_TEXTURE_WRAP_S, !mIsNPoT2 ? GFXGLTextureAddress[ssd.addressModeU] : GL_CLAMP_TO_EDGE);
glTexParameteri(mBinding, GL_TEXTURE_WRAP_T, !mIsNPoT2 ? GFXGLTextureAddress[ssd.addressModeV] : GL_CLAMP_TO_EDGE);
if(mBinding == GL_TEXTURE_3D)
glTexParameteri(mBinding, GL_TEXTURE_WRAP_R, GFXGLTextureAddress[ssd.addressModeW]);
glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, ssd.mipLODBias); if(mNeedInitSamplerState)
{
initSamplerState(ssd);
return;
}
if(mSampler.minFilter != ssd.minFilter || mSampler.mipFilter != ssd.mipFilter)
glTexParameteri(mBinding, GL_TEXTURE_MIN_FILTER, minificationFilter(ssd.minFilter, ssd.mipFilter, mMipLevels));
if(mSampler.magFilter != ssd.magFilter)
glTexParameteri(mBinding, GL_TEXTURE_MAG_FILTER, GFXGLTextureFilter[ssd.magFilter]);
if(mSampler.addressModeU != ssd.addressModeU)
glTexParameteri(mBinding, GL_TEXTURE_WRAP_S, !mIsNPoT2 ? GFXGLTextureAddress[ssd.addressModeU] : GL_CLAMP_TO_EDGE);
if(mSampler.addressModeV != ssd.addressModeV)
glTexParameteri(mBinding, GL_TEXTURE_WRAP_T, !mIsNPoT2 ? GFXGLTextureAddress[ssd.addressModeV] : GL_CLAMP_TO_EDGE);
if(mBinding == GL_TEXTURE_3D && mSampler.addressModeW != ssd.addressModeW )
glTexParameteri(mBinding, GL_TEXTURE_WRAP_R, GFXGLTextureAddress[ssd.addressModeW]);
if(mSampler.maxAnisotropy != ssd.maxAnisotropy && static_cast< GFXGLDevice* >( GFX )->supportsAnisotropic() )
glTexParameterf(mBinding, GL_TEXTURE_MAX_ANISOTROPY_EXT, ssd.maxAnisotropy);
mSampler = ssd;
} }
U8* GFXGLTextureObject::getTextureData() U8* GFXGLTextureObject::getTextureData()
{ {
U8* data = new U8[mTextureSize.x * mTextureSize.y * mBytesPerTexel]; U8* data = new U8[mTextureSize.x * mTextureSize.y * mBytesPerTexel];
glBindTexture(GL_TEXTURE_2D, mHandle); PRESERVE_TEXTURE(mBinding);
glGetTexImage(GL_TEXTURE_2D, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, data); glBindTexture(mBinding, mHandle);
glGetTexImage(mBinding, 0, GFXGLTextureFormat[mFormat], GFXGLTextureType[mFormat], data);
return data; return data;
} }
void GFXGLTextureObject::copyIntoCache() void GFXGLTextureObject::copyIntoCache()
{ {
PRESERVE_TEXTURE(mBinding);
glBindTexture(mBinding, mHandle); glBindTexture(mBinding, mHandle);
U32 cacheSize = mTextureSize.x * mTextureSize.y; U32 cacheSize = mTextureSize.x * mTextureSize.y;
if(mBinding == GL_TEXTURE_3D) if(mBinding == GL_TEXTURE_3D)
@ -171,7 +264,6 @@ void GFXGLTextureObject::copyIntoCache()
mZombieCache = new U8[cacheSize]; mZombieCache = new U8[cacheSize];
glGetTexImage(mBinding, 0, GFXGLTextureFormat[mFormat], GFXGLTextureType[mFormat], mZombieCache); glGetTexImage(mBinding, 0, GFXGLTextureFormat[mFormat], GFXGLTextureType[mFormat], mZombieCache);
glBindTexture(mBinding, 0);
} }
void GFXGLTextureObject::reloadFromCache() void GFXGLTextureObject::reloadFromCache()
@ -187,8 +279,13 @@ void GFXGLTextureObject::reloadFromCache()
return; return;
} }
PRESERVE_TEXTURE(mBinding);
glBindTexture(mBinding, mHandle); glBindTexture(mBinding, mHandle);
glTexSubImage2D(mBinding, 0, 0, 0, mTextureSize.x, mTextureSize.y, GFXGLTextureFormat[mFormat], GFXGLTextureType[mFormat], mZombieCache);
if(mBinding == GL_TEXTURE_2D)
glTexSubImage2D(mBinding, 0, 0, 0, mTextureSize.x, mTextureSize.y, GFXGLTextureFormat[mFormat], GFXGLTextureType[mFormat], mZombieCache);
else if(mBinding == GL_TEXTURE_1D)
glTexSubImage1D(mBinding, 0, 0, (mTextureSize.x > 1 ? mTextureSize.x : mTextureSize.y), GFXGLTextureFormat[mFormat], GFXGLTextureType[mFormat], mZombieCache);
if(GFX->getCardProfiler()->queryProfile("GL::Workaround::needsExplicitGenerateMipmap") && mMipLevels != 1) if(GFX->getCardProfiler()->queryProfile("GL::Workaround::needsExplicitGenerateMipmap") && mMipLevels != 1)
glGenerateMipmapEXT(mBinding); glGenerateMipmapEXT(mBinding);

View file

@ -24,7 +24,8 @@
#define _GFXGLTEXTUREOBJECT_H #define _GFXGLTEXTUREOBJECT_H
#include "gfx/gfxTextureObject.h" #include "gfx/gfxTextureObject.h"
#include "gfx/gl/ggl/ggl.h" #include "gfx/gl/tGL/tGL.h"
#include "gfx/gfxStateBlock.h"
class GFXGLDevice; class GFXGLDevice;
@ -32,9 +33,10 @@ class GFXGLTextureObject : public GFXTextureObject
{ {
public: public:
GFXGLTextureObject(GFXDevice * aDevice, GFXTextureProfile *profile); GFXGLTextureObject(GFXDevice * aDevice, GFXTextureProfile *profile);
virtual ~GFXGLTextureObject(); ~GFXGLTextureObject();
void release(); void release();
void reInit();
inline GLuint getHandle() const { return mHandle; } inline GLuint getHandle() const { return mHandle; }
inline GLenum getBinding() const { return mBinding; } inline GLenum getBinding() const { return mBinding; }
@ -45,7 +47,7 @@ public:
/// Binds the texture to the given texture unit /// Binds the texture to the given texture unit
/// and applies the current sampler state because GL tracks /// and applies the current sampler state because GL tracks
/// filtering and wrapper per object, while GFX tracks per sampler. /// filtering and wrapper per object, while GFX tracks per sampler.
void bind(U32 textureUnit) const; void bind(U32 textureUnit);
/// @return An array containing the texture data /// @return An array containing the texture data
/// @note You are responsible for deleting the returned data! (Use delete[]) /// @note You are responsible for deleting the returned data! (Use delete[])
@ -73,6 +75,8 @@ public:
virtual void zombify(); virtual void zombify();
virtual void resurrect(); virtual void resurrect();
virtual const String describeSelf() const; virtual const String describeSelf() const;
void initSamplerState(const GFXSamplerStateDesc &ssd);
private: private:
friend class GFXGLTextureManager; friend class GFXGLTextureManager;
@ -80,7 +84,8 @@ private:
/// Internal GL object /// Internal GL object
GLuint mHandle; GLuint mHandle;
GLuint mBuffer; GLuint mBuffer;
bool mNeedInitSamplerState;
GFXSamplerStateDesc mSampler;
GLenum mBinding; GLenum mBinding;
U32 mBytesPerTexel; U32 mBytesPerTexel;
@ -94,6 +99,13 @@ private:
U8* mZombieCache; U8* mZombieCache;
void copyIntoCache(); void copyIntoCache();
//FrameAllocator
U32 mFrameAllocatorMark;
#if TORQUE_DEBUG
U32 mFrameAllocatorMarkGuard;
#endif
U8 *mFrameAllocatorPtr;
}; };
#endif #endif

View file

@ -47,6 +47,8 @@ public:
virtual U32 getDepth() = 0; virtual U32 getDepth() = 0;
virtual bool hasMips() = 0; virtual bool hasMips() = 0;
virtual GLenum getBinding() = 0; virtual GLenum getBinding() = 0;
virtual GFXFormat getFormat() = 0;
virtual bool isCompatible(const GFXGLTextureObject* tex) = 0;
U32 getMipLevel() { return mipLevel; } U32 getMipLevel() { return mipLevel; }
U32 getZOffset() { return zOffset; } U32 getZOffset() { return zOffset; }
@ -73,6 +75,14 @@ public:
virtual U32 getDepth() { return mTex->getDepth(); } virtual U32 getDepth() { return mTex->getDepth(); }
virtual bool hasMips() { return mTex->mMipLevels != 1; } virtual bool hasMips() { return mTex->mMipLevels != 1; }
virtual GLenum getBinding() { return mTex->getBinding(); } virtual GLenum getBinding() { return mTex->getBinding(); }
virtual GFXFormat getFormat() { return mTex->getFormat(); }
virtual bool isCompatible(const GFXGLTextureObject* tex)
{
return mTex->getFormat() == tex->getFormat()
&& mTex->getWidth() == tex->getWidth()
&& mTex->getHeight() == tex->getHeight();
}
GFXGLTextureObject* getTextureObject() const {return mTex; }
private: private:
StrongRefPtr<GFXGLTextureObject> mTex; StrongRefPtr<GFXGLTextureObject> mTex;
@ -95,6 +105,13 @@ public:
virtual U32 getDepth() { return 0; } virtual U32 getDepth() { return 0; }
virtual bool hasMips() { return mTex->getNumMipLevels() != 1; } virtual bool hasMips() { return mTex->getNumMipLevels() != 1; }
virtual GLenum getBinding() { return GFXGLCubemap::getEnumForFaceNumber(mFace); } virtual GLenum getBinding() { return GFXGLCubemap::getEnumForFaceNumber(mFace); }
virtual GFXFormat getFormat() { return mTex->getFormat(); }
virtual bool isCompatible(const GFXGLTextureObject* tex)
{
return mTex->getFormat() == tex->getFormat()
&& mTex->getWidth() == tex->getWidth()
&& mTex->getHeight() == tex->getHeight();
}
private: private:
StrongRefPtr<GFXGLCubemap> mTex; StrongRefPtr<GFXGLCubemap> mTex;
@ -102,7 +119,7 @@ private:
}; };
// Internal implementations // Internal implementations
class _GFXGLTextureTargetImpl class _GFXGLTextureTargetImpl // TODO OPENGL remove and implement on GFXGLTextureTarget
{ {
public: public:
GFXGLTextureTarget* mTarget; GFXGLTextureTarget* mTarget;
@ -128,149 +145,88 @@ public:
virtual void finish(); virtual void finish();
}; };
// Handy macro for checking the status of a framebuffer. Framebuffers can fail in
// all sorts of interesting ways, these are just the most common. Further, no existing GL profiling
// tool catches framebuffer errors when the framebuffer is created, so we actually need this.
#define CHECK_FRAMEBUFFER_STATUS()\
{\
GLenum status;\
status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);\
switch(status) {\
case GL_FRAMEBUFFER_COMPLETE_EXT:\
break;\
case GL_FRAMEBUFFER_UNSUPPORTED_EXT:\
AssertFatal(false, "Unsupported FBO");\
break;\
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:\
AssertFatal(false, "Incomplete FBO Attachment");\
break;\
case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:\
AssertFatal(false, "Incomplete FBO dimensions");\
break;\
case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:\
AssertFatal(false, "Incomplete FBO formats");\
default:\
/* programming error; will fail on all hardware */\
AssertFatal(false, "Something really bad happened with an FBO");\
}\
}
_GFXGLTextureTargetFBOImpl::_GFXGLTextureTargetFBOImpl(GFXGLTextureTarget* target) _GFXGLTextureTargetFBOImpl::_GFXGLTextureTargetFBOImpl(GFXGLTextureTarget* target)
{ {
mTarget = target; mTarget = target;
glGenFramebuffersEXT(1, &mFramebuffer); glGenFramebuffers(1, &mFramebuffer);
} }
_GFXGLTextureTargetFBOImpl::~_GFXGLTextureTargetFBOImpl() _GFXGLTextureTargetFBOImpl::~_GFXGLTextureTargetFBOImpl()
{ {
glDeleteFramebuffersEXT(1, &mFramebuffer); glDeleteFramebuffers(1, &mFramebuffer);
} }
void _GFXGLTextureTargetFBOImpl::applyState() void _GFXGLTextureTargetFBOImpl::applyState()
{ {
// REMINDER: When we implement MRT support, check against GFXGLDevice::getNumRenderTargets() // REMINDER: When we implement MRT support, check against GFXGLDevice::getNumRenderTargets()
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFramebuffer); PRESERVE_FRAMEBUFFER();
glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
_GFXGLTargetDesc* color0 = mTarget->getTargetDesc(GFXTextureTarget::Color0);
if(color0) bool hasColor = false;
{ for(int i = 0; i < GFXGL->getNumRenderTargets(); ++i)
if(color0->getDepth() == 0) {
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, color0->getBinding(), color0->getHandle(), color0->getMipLevel()); _GFXGLTargetDesc* color = mTarget->getTargetDesc( static_cast<GFXTextureTarget::RenderSlot>(GFXTextureTarget::Color0+i ));
if(color)
{
hasColor = true;
if( color->getBinding( ) == GL_TEXTURE_2D )
glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, color->getBinding( ), color->getHandle( ), color->getMipLevel( ) );
else if( color->getBinding( ) == GL_TEXTURE_1D )
glFramebufferTexture1D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, color->getBinding( ), color->getHandle( ), color->getMipLevel( ) );
else if( color->getBinding( ) == GL_TEXTURE_3D )
glFramebufferTexture3D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, color->getBinding( ), color->getHandle( ), color->getMipLevel( ), color->getZOffset( ) );
}
else else
glFramebufferTexture3DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, color0->getBinding(), color0->getHandle(), color0->getMipLevel(), color0->getZOffset()); {
} // Clears the texture (note that the binding is irrelevent)
else glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+i, GL_TEXTURE_2D, 0, 0);
{ }
// Clears the texture (note that the binding is irrelevent)
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, 0, 0);
} }
_GFXGLTargetDesc* depthStecil = mTarget->getTargetDesc(GFXTextureTarget::DepthStencil); _GFXGLTargetDesc* depthStecil = mTarget->getTargetDesc(GFXTextureTarget::DepthStencil);
if(depthStecil) if(depthStecil)
{ {
// Certain drivers have issues with depth only FBOs. That and the next two asserts assume we have a color target. // Certain drivers have issues with depth only FBOs. That and the next two asserts assume we have a color target.
AssertFatal(color0, "GFXGLTextureTarget::applyState() - Cannot set DepthStencil target without Color0 target!"); AssertFatal(hasColor, "GFXGLTextureTarget::applyState() - Cannot set DepthStencil target without Color0 target!");
AssertFatal(depthStecil->getWidth() == color0->getWidth(), "GFXGLTextureTarget::applyState() - DepthStencil and Color0 targets MUST have the same width!"); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthStecil->getBinding(), depthStecil->getHandle(), depthStecil->getMipLevel());
AssertFatal(depthStecil->getHeight() == color0->getHeight(), "GFXGLTextureTarget::applyState() - DepthStencil and Color0 targets MUST have the same height!");
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, depthStecil->getBinding(), depthStecil->getHandle(), depthStecil->getMipLevel());
} }
else else
{ {
// Clears the texture (note that the binding is irrelevent) // Clears the texture (note that the binding is irrelevent)
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, 0, 0); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
} }
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); CHECK_FRAMEBUFFER_STATUS();
} }
void _GFXGLTextureTargetFBOImpl::makeActive() void _GFXGLTextureTargetFBOImpl::makeActive()
{ {
glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, mFramebuffer); glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, mFramebuffer); GFXGL->getOpenglCache()->setCacheBinded(GL_FRAMEBUFFER, mFramebuffer);
} }
void _GFXGLTextureTargetFBOImpl::finish() void _GFXGLTextureTargetFBOImpl::finish()
{ {
glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0); glBindFramebuffer(GL_FRAMEBUFFER, 0);
glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0); GFXGL->getOpenglCache()->setCacheBinded(GL_FRAMEBUFFER, 0);
_GFXGLTargetDesc* color0 = mTarget->getTargetDesc(GFXTextureTarget::Color0);
if(!color0 || !(color0->hasMips()))
return;
// Generate mips if necessary
// Assumes a 2D texture.
glActiveTexture(GL_TEXTURE0);
PRESERVE_2D_TEXTURE();
glBindTexture(GL_TEXTURE_2D, color0->getHandle());
glGenerateMipmapEXT(GL_TEXTURE_2D);
}
// This implementations uses AUX buffers (we should always have at least one) to do render to texture. It is currently only used when we need access to the windows depth buffer. for(int i = 0; i < GFXGL->getNumRenderTargets(); ++i)
class _GFXGLTextureTargetAUXBufferImpl : public _GFXGLTextureTargetImpl {
{ _GFXGLTargetDesc* color = mTarget->getTargetDesc( static_cast<GFXTextureTarget::RenderSlot>(GFXTextureTarget::Color0+i ) );
public: if(!color || !(color->hasMips()))
_GFXGLTextureTargetAUXBufferImpl(GFXGLTextureTarget* target); continue;
virtual void applyState(); // Generate mips if necessary
virtual void makeActive(); // Assumes a 2D texture.
virtual void finish(); PRESERVE_TEXTURE(color->getBinding());
}; glBindTexture(color->getBinding(), color->getHandle());
glGenerateMipmapEXT(GL_TEXTURE_2D);
_GFXGLTextureTargetAUXBufferImpl::_GFXGLTextureTargetAUXBufferImpl(GFXGLTextureTarget* target) }
{
mTarget = target;
}
void _GFXGLTextureTargetAUXBufferImpl::applyState()
{
}
void _GFXGLTextureTargetAUXBufferImpl::makeActive()
{
glDrawBuffer(GL_AUX0);
glReadBuffer(GL_AUX0);
}
void _GFXGLTextureTargetAUXBufferImpl::finish()
{
// Bind the Color0 texture
_GFXGLTargetDesc* color0 = mTarget->getTargetDesc(GFXTextureTarget::Color0);
glActiveTexture(GL_TEXTURE0);
// Assume we're a 2D texture for now.
PRESERVE_2D_TEXTURE();
glBindTexture(color0->getBinding(), color0->getHandle());
glCopyTexSubImage2D(color0->getBinding(), 0, 0, 0, 0, 0, color0->getWidth(), color0->getHeight());
glDrawBuffer(GL_BACK);
glReadBuffer(GL_BACK);
} }
// Actual GFXGLTextureTarget interface // Actual GFXGLTextureTarget interface
GFXGLTextureTarget::GFXGLTextureTarget() GFXGLTextureTarget::GFXGLTextureTarget() : mCopyFboSrc(0), mCopyFboDst(0)
{ {
for(U32 i=0; i<MaxRenderSlotId; i++) for(U32 i=0; i<MaxRenderSlotId; i++)
mTargets[i] = NULL; mTargets[i] = NULL;
@ -278,7 +234,9 @@ GFXGLTextureTarget::GFXGLTextureTarget()
GFXTextureManager::addEventDelegate( this, &GFXGLTextureTarget::_onTextureEvent ); GFXTextureManager::addEventDelegate( this, &GFXGLTextureTarget::_onTextureEvent );
_impl = new _GFXGLTextureTargetFBOImpl(this); _impl = new _GFXGLTextureTargetFBOImpl(this);
_needsAux = false;
glGenFramebuffers(1, &mCopyFboSrc);
glGenFramebuffers(1, &mCopyFboDst);
} }
GFXGLTextureTarget::~GFXGLTextureTarget() GFXGLTextureTarget::~GFXGLTextureTarget()
@ -296,18 +254,20 @@ const Point2I GFXGLTextureTarget::getSize()
GFXFormat GFXGLTextureTarget::getFormat() GFXFormat GFXGLTextureTarget::getFormat()
{ {
// TODO: Fix me! if(mTargets[Color0].isValid())
return mTargets[Color0]->getFormat();
return GFXFormatR8G8B8A8; return GFXFormatR8G8B8A8;
} }
void GFXGLTextureTarget::attachTexture( RenderSlot slot, GFXTextureObject *tex, U32 mipLevel/*=0*/, U32 zOffset /*= 0*/ ) void GFXGLTextureTarget::attachTexture( RenderSlot slot, GFXTextureObject *tex, U32 mipLevel/*=0*/, U32 zOffset /*= 0*/ )
{ {
// GFXTextureTarget::sDefaultDepthStencil is a hint that we want the window's depth buffer. if( tex == GFXTextureTarget::sDefaultDepthStencil )
if(tex == GFXTextureTarget::sDefaultDepthStencil) tex = GFXGL->getDefaultDepthTex();
_needsAux = true;
_GFXGLTextureTargetDesc* mTex = static_cast<_GFXGLTextureTargetDesc*>(mTargets[slot].ptr());
if(slot == DepthStencil && tex != GFXTextureTarget::sDefaultDepthStencil) if( (!tex && !mTex) || (mTex && mTex->getTextureObject() == tex) )
_needsAux = false; return;
// Triggers an update when we next render // Triggers an update when we next render
invalidateState(); invalidateState();
@ -376,10 +336,7 @@ void GFXGLTextureTarget::applyState()
// So we don't do this over and over again // So we don't do this over and over again
stateApplied(); stateApplied();
// Ensure we have the proper implementation (consider changing to an enum?) if(_impl.isNull())
if(_needsAux && dynamic_cast<_GFXGLTextureTargetAUXBufferImpl*>(_impl.ptr()) == NULL)
_impl = new _GFXGLTextureTargetAUXBufferImpl(this);
else if(!_needsAux && dynamic_cast<_GFXGLTextureTargetFBOImpl*>(_impl.ptr()) == NULL)
_impl = new _GFXGLTextureTargetFBOImpl(this); _impl = new _GFXGLTextureTargetFBOImpl(this);
_impl->applyState(); _impl->applyState();
@ -413,26 +370,24 @@ void GFXGLTextureTarget::resolveTo(GFXTextureObject* obj)
AssertFatal(dynamic_cast<GFXGLTextureObject*>(obj), "GFXGLTextureTarget::resolveTo - Incorrect type of texture, expected a GFXGLTextureObject"); AssertFatal(dynamic_cast<GFXGLTextureObject*>(obj), "GFXGLTextureTarget::resolveTo - Incorrect type of texture, expected a GFXGLTextureObject");
GFXGLTextureObject* glTexture = static_cast<GFXGLTextureObject*>(obj); GFXGLTextureObject* glTexture = static_cast<GFXGLTextureObject*>(obj);
if( gglHasExtension(ARB_copy_image) && mTargets[Color0]->isCompatible(glTexture) )
{
glCopyImageSubData(
mTargets[Color0]->getHandle(), GL_TEXTURE_2D, 0, 0, 0, 0,
glTexture->getHandle(), GL_TEXTURE_2D, 0, 0, 0, 0,
mTargets[Color0]->getWidth(), mTargets[Color0]->getHeight(), 1);
return;
}
PRESERVE_FRAMEBUFFER(); PRESERVE_FRAMEBUFFER();
GLuint dest; glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mCopyFboDst);
GLuint src; glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, glTexture->getHandle(), 0);
glGenFramebuffersEXT(1, &dest); glBindFramebuffer(GL_READ_FRAMEBUFFER, mCopyFboSrc);
glGenFramebuffersEXT(1, &src); glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,mTargets[Color0]->getHandle(), 0);
glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, dest); glBlitFramebuffer(0, 0, mTargets[Color0]->getWidth(), mTargets[Color0]->getHeight(),
glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, glTexture->getHandle(), 0);
glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, src);
glFramebufferTexture2DEXT(GL_READ_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D,mTargets[Color0]->getHandle(), 0);
glBlitFramebufferEXT(0, 0, mTargets[Color0]->getWidth(), mTargets[Color0]->getHeight(),
0, 0, glTexture->getWidth(), glTexture->getHeight(), GL_COLOR_BUFFER_BIT, GL_NEAREST); 0, 0, glTexture->getWidth(), glTexture->getHeight(), GL_COLOR_BUFFER_BIT, GL_NEAREST);
glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0);
glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
glDeleteFramebuffersEXT(1, &dest);
glDeleteFramebuffersEXT(1, &src);
} }

View file

@ -79,9 +79,6 @@ protected:
/// @see GFXTextureManager::addEventDelegate /// @see GFXTextureManager::addEventDelegate
void _onTextureEvent( GFXTexCallbackCode code ); void _onTextureEvent( GFXTexCallbackCode code );
/// If true our implementation should use AUX buffers
bool _needsAux;
/// Pointer to our internal implementation /// Pointer to our internal implementation
AutoPtr<_GFXGLTextureTargetImpl> _impl; AutoPtr<_GFXGLTextureTargetImpl> _impl;
@ -96,6 +93,9 @@ protected:
/// @} /// @}
//copy FBO
GLuint mCopyFboSrc, mCopyFboDst;
}; };
#endif #endif

View file

@ -25,12 +25,15 @@
#include "core/util/preprocessorHelpers.h" #include "core/util/preprocessorHelpers.h"
#include "gfx/gl/gfxGLEnumTranslate.h" #include "gfx/gl/gfxGLEnumTranslate.h"
#include "gfx/gl/gfxGLStateCache.h"
static inline GLenum minificationFilter(U32 minFilter, U32 mipFilter, U32 mipLevels) inline U32 getMaxMipmaps(U32 width, U32 height, U32 depth)
{ {
if(mipLevels == 1) return getMax( getBinLog2(depth), getMax(getBinLog2(width), getBinLog2(height)));
return GFXGLTextureFilter[minFilter]; }
inline GLenum minificationFilter(U32 minFilter, U32 mipFilter, U32 /*mipLevels*/)
{
// the compiler should interpret this as array lookups // the compiler should interpret this as array lookups
switch( minFilter ) switch( minFilter )
{ {
@ -56,13 +59,49 @@ static inline GLenum minificationFilter(U32 minFilter, U32 mipFilter, U32 mipLev
} }
} }
// Check if format is compressed format.
// Even though dxt2/4 are not supported, they are included because they are a compressed format.
// Assert checks on supported formats are done elsewhere.
inline bool isCompressedFormat( GFXFormat format )
{
bool compressed = false;
if(format == GFXFormatDXT1 || format == GFXFormatDXT2
|| format == GFXFormatDXT3
|| format == GFXFormatDXT4
|| format == GFXFormatDXT5 )
{
compressed = true;
}
return compressed;
}
//Get the surface size of a compressed mip map level - see ddsLoader.cpp
inline U32 getCompressedSurfaceSize(GFXFormat format,U32 width, U32 height, U32 mipLevel=0 )
{
if(!isCompressedFormat(format))
return 0;
// Bump by the mip level.
height = getMax(U32(1), height >> mipLevel);
width = getMax(U32(1), width >> mipLevel);
U32 sizeMultiple = 0;
if(format == GFXFormatDXT1)
sizeMultiple = 8;
else
sizeMultiple = 16;
return getMax(U32(1), width/4) * getMax(U32(1), height/4) * sizeMultiple;
}
/// Simple class which preserves a given GL integer. /// Simple class which preserves a given GL integer.
/// This class determines the integer to preserve on construction and restores /// This class determines the integer to preserve on construction and restores
/// it on destruction. /// it on destruction.
class GFXGLPreserveInteger class GFXGLPreserveInteger
{ {
public: public:
typedef void(*BindFn)(GLenum, GLuint); typedef void(STDCALL *BindFn)(GLenum, GLuint);
/// Preserve the integer. /// Preserve the integer.
/// @param binding The binding which should be set on destruction. /// @param binding The binding which should be set on destruction.
@ -73,7 +112,12 @@ public:
mBinding(binding), mPreserved(0), mBinder(binder) mBinding(binding), mPreserved(0), mBinder(binder)
{ {
AssertFatal(mBinder, "GFXGLPreserveInteger - Need a valid binder function"); AssertFatal(mBinder, "GFXGLPreserveInteger - Need a valid binder function");
glGetIntegerv(getBinding, &mPreserved); mPreserved = GFXGL->getOpenglCache()->getCacheBinded(mBinding);
#if defined(TORQUE_DEBUG) && defined(TORQUE_DEBUG_GFX)
GLint bindedOnOpenglDriver;
glGetIntegerv(getBinding, &bindedOnOpenglDriver);
AssertFatal( mPreserved == bindedOnOpenglDriver, "GFXGLPreserveInteger - GFXGLDevice/OpenGL mismatch on cache binded resource.");
#endif
} }
/// Restores the integer. /// Restores the integer.
@ -88,24 +132,113 @@ private:
BindFn mBinder; BindFn mBinder;
}; };
class GFXGLPreserveTexture
{
public:
typedef void(STDCALL *BindFn)(GLenum, GLuint);
GFXGLPreserveTexture(GLenum binding, GLint getBinding, BindFn binder) :
mBinding(binding), mPreserved(0), mBinder(binder)
{
AssertFatal(mBinder, "GFXGLPreserveTexture - Need a valid binder function");
GFXGLDevice *gfx = GFXGL;
mPreserved = gfx->getOpenglCache()->getCacheBinded(mBinding);
mActiveTexture = gfx->getOpenglCache()->getCacheActiveTexture();
#if defined(TORQUE_DEBUG) && defined(TORQUE_DEBUG_GFX)
GLint activeTextureOnOpenglDriver, bindedTextureOnOpenglDriver;
glGetIntegerv(getBinding, &bindedTextureOnOpenglDriver);
glGetIntegerv(GL_ACTIVE_TEXTURE, &activeTextureOnOpenglDriver);
activeTextureOnOpenglDriver -= GL_TEXTURE0;
AssertFatal( mPreserved == bindedTextureOnOpenglDriver, "GFXGLPreserveTexture - GFXGLDevice/OpenGL mismatch on cache binded resource.");
AssertFatal( activeTextureOnOpenglDriver == mActiveTexture, "GFXGLPreserveTexture - GFXGLDevice/OpenGL mismatch on cache binded resource.");
#endif
}
/// Restores the texture.
~GFXGLPreserveTexture()
{
#if defined(TORQUE_DEBUG) && defined(TORQUE_DEBUG_GFX)
GLint activeTextureOnOpenglDriver;
glGetIntegerv(GL_ACTIVE_TEXTURE, &activeTextureOnOpenglDriver);
activeTextureOnOpenglDriver -= GL_TEXTURE0;
GLint cacheActiveTexture = GFXGL->getOpenglCache()->getCacheActiveTexture();
AssertFatal( cacheActiveTexture == activeTextureOnOpenglDriver, "GFXGLPreserveTexture - GFXGLDevice/OpenGL mismatch on cache ActiveTexture.");
#endif
mBinder(mBinding, mPreserved);
}
private:
GLenum mBinding;
GLint mPreserved;
BindFn mBinder;
S16 mActiveTexture;
};
/// Helper macro to preserve the current VBO binding. /// Helper macro to preserve the current VBO binding.
#define PRESERVE_VERTEX_BUFFER() \ #define PRESERVE_VERTEX_BUFFER() \
GFXGLPreserveInteger TORQUE_CONCAT(preserve_, __LINE__) (GL_ARRAY_BUFFER, GL_ARRAY_BUFFER_BINDING, glBindBuffer) GFXGLPreserveInteger TORQUE_CONCAT(preserve_, __LINE__) (GL_ARRAY_BUFFER, GL_ARRAY_BUFFER_BINDING, (GFXGLPreserveInteger::BindFn)glBindBuffer)
/// Helper macro to preserve the current element array binding. /// Helper macro to preserve the current element array binding.
#define PRESERVE_INDEX_BUFFER() \ #define PRESERVE_INDEX_BUFFER() \
GFXGLPreserveInteger TORQUE_CONCAT(preserve_, __LINE__) (GL_ELEMENT_ARRAY_BUFFER, GL_ELEMENT_ARRAY_BUFFER_BINDING, glBindBuffer) GFXGLPreserveInteger TORQUE_CONCAT(preserve_, __LINE__) (GL_ELEMENT_ARRAY_BUFFER, GL_ELEMENT_ARRAY_BUFFER_BINDING, (GFXGLPreserveInteger::BindFn)glBindBuffer)
/// ASSERT: Never call glActiveTexture for a "bind to modify" or in a PRESERVER_TEXTURE MACRO scope.
/// Helper macro to preserve the current 1D texture binding.
#define PRESERVE_1D_TEXTURE() \
GFXGLPreserveTexture TORQUE_CONCAT(preserve_, __LINE__) (GL_TEXTURE_1D, GL_TEXTURE_BINDING_1D, (GFXGLPreserveInteger::BindFn)glBindTexture)
/// Helper macro to preserve the current 2D texture binding. /// Helper macro to preserve the current 2D texture binding.
#define PRESERVE_2D_TEXTURE() \ #define PRESERVE_2D_TEXTURE() \
GFXGLPreserveInteger TORQUE_CONCAT(preserve_, __LINE__) (GL_TEXTURE_2D, GL_TEXTURE_BINDING_2D, glBindTexture) GFXGLPreserveTexture TORQUE_CONCAT(preserve_, __LINE__) (GL_TEXTURE_2D, GL_TEXTURE_BINDING_2D, (GFXGLPreserveInteger::BindFn)glBindTexture)
/// Helper macro to preserve the current 3D texture binding. /// Helper macro to preserve the current 3D texture binding.
#define PRESERVE_3D_TEXTURE() \ #define PRESERVE_3D_TEXTURE() \
GFXGLPreserveInteger TORQUE_CONCAT(preserve_, __LINE__) (GL_TEXTURE_3D, GL_TEXTURE_BINDING_3D, glBindTexture) GFXGLPreserveTexture TORQUE_CONCAT(preserve_, __LINE__) (GL_TEXTURE_3D, GL_TEXTURE_BINDING_3D, (GFXGLPreserveInteger::BindFn)glBindTexture)
/// Helper macro to preserve the current 3D texture binding.
#define PRESERVE_CUBEMAP_TEXTURE() \
GFXGLPreserveTexture TORQUE_CONCAT(preserve_, __LINE__) (GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BINDING_CUBE_MAP, (GFXGLPreserveInteger::BindFn)glBindTexture)
#define _GET_TEXTURE_BINDING(binding) \
binding == GL_TEXTURE_2D ? GL_TEXTURE_BINDING_2D : (binding == GL_TEXTURE_3D ? GL_TEXTURE_BINDING_3D : GL_TEXTURE_BINDING_1D )
#define PRESERVE_TEXTURE(binding) \
GFXGLPreserveTexture TORQUE_CONCAT(preserve_, __LINE__) (binding, _GET_TEXTURE_BINDING(binding), (GFXGLPreserveInteger::BindFn)glBindTexture)
#define PRESERVE_FRAMEBUFFER() \ #define PRESERVE_FRAMEBUFFER() \
GFXGLPreserveInteger TORQUE_CONCAT(preserve_, __LINE__) (GL_READ_FRAMEBUFFER_EXT, GL_READ_FRAMEBUFFER_BINDING_EXT, glBindFramebufferEXT);\ GFXGLPreserveInteger TORQUE_CONCAT(preserve_, __LINE__) (GL_READ_FRAMEBUFFER, GL_READ_FRAMEBUFFER_BINDING, (GFXGLPreserveInteger::BindFn)glBindFramebuffer);\
GFXGLPreserveInteger TORQUE_CONCAT(preserve2_, __LINE__) (GL_DRAW_FRAMEBUFFER_EXT, GL_DRAW_FRAMEBUFFER_BINDING_EXT, glBindFramebufferEXT) GFXGLPreserveInteger TORQUE_CONCAT(preserve2_, __LINE__) (GL_DRAW_FRAMEBUFFER, GL_DRAW_FRAMEBUFFER_BINDING, (GFXGLPreserveInteger::BindFn)glBindFramebuffer)
// Handy macro for checking the status of a framebuffer. Framebuffers can fail in
// all sorts of interesting ways, these are just the most common. Further, no existing GL profiling
// tool catches framebuffer errors when the framebuffer is created, so we actually need this.
#define CHECK_FRAMEBUFFER_STATUS()\
{\
GLenum status;\
status = glCheckFramebufferStatus(GL_FRAMEBUFFER);\
switch(status) {\
case GL_FRAMEBUFFER_COMPLETE:\
break;\
case GL_FRAMEBUFFER_UNSUPPORTED:\
AssertFatal(false, "Unsupported FBO");\
break;\
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:\
AssertFatal(false, "Incomplete FBO Attachment");\
break;\
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:\
AssertFatal(false, "Incomplete FBO Missing Attachment");\
break;\
case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:\
AssertFatal(false, "Incomplete FBO Draw buffer");\
break;\
case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:\
AssertFatal(false, "Incomplete FBO Read buffer");\
break;\
default:\
/* programming error; will fail on all hardware */\
AssertFatal(false, "Something really bad happened with an FBO");\
}\
}
#endif #endif

View file

@ -0,0 +1,30 @@
#ifndef GFX_GL_VERTEX_ATTRIB_LOCATION_H
#define GFX_GL_VERTEX_ATTRIB_LOCATION_H
namespace Torque
{
enum GL_AttributeLocation
{
GL_VertexAttrib_Position = 0,
GL_VertexAttrib_Normal,
GL_VertexAttrib_Color,
GL_VertexAttrib_Tangent,
GL_VertexAttrib_TangentW,
GL_VertexAttrib_Binormal,
GL_VertexAttrib_TexCoord0,
GL_VertexAttrib_TexCoord1,
GL_VertexAttrib_TexCoord2,
GL_VertexAttrib_TexCoord3,
GL_VertexAttrib_TexCoord4,
GL_VertexAttrib_TexCoord5,
GL_VertexAttrib_TexCoord6,
GL_VertexAttrib_TexCoord7,
GL_VertexAttrib_TexCoord8,
GL_VertexAttrib_TexCoord9,
GL_VertexAttrib_LAST = GL_VertexAttrib_TexCoord9,
GL_VertexAttrib_COUNT
};
}
#endif //GFX_GL_VERTEX_ATTRIB_LOCATION_H

View file

@ -26,7 +26,15 @@
#include "gfx/gl/gfxGLDevice.h" #include "gfx/gl/gfxGLDevice.h"
#include "gfx/gl/gfxGLEnumTranslate.h" #include "gfx/gl/gfxGLEnumTranslate.h"
#include "gfx/gl/gfxGLUtils.h" #include "gfx/gl/gfxGLUtils.h"
#include "gfx/gl/gfxGLVertexAttribLocation.h"
#include "gfx/gl/gfxGLCircularVolatileBuffer.h"
GLCircularVolatileBuffer* getCircularVolatileVertexBuffer()
{
static GLCircularVolatileBuffer sCircularVolatileVertexBuffer(GL_ARRAY_BUFFER);
return &sCircularVolatileVertexBuffer;
}
GFXGLVertexBuffer::GFXGLVertexBuffer( GFXDevice *device, GFXGLVertexBuffer::GFXGLVertexBuffer( GFXDevice *device,
U32 numVerts, U32 numVerts,
@ -34,113 +42,111 @@ GFXGLVertexBuffer::GFXGLVertexBuffer( GFXDevice *device,
U32 vertexSize, U32 vertexSize,
GFXBufferType bufferType ) GFXBufferType bufferType )
: GFXVertexBuffer( device, numVerts, vertexFormat, vertexSize, bufferType ), : GFXVertexBuffer( device, numVerts, vertexFormat, vertexSize, bufferType ),
mZombieCache(NULL) mZombieCache(NULL),
mBufferOffset(0),
mBufferVertexOffset(0)
{ {
if( mBufferType == GFXBufferTypeVolatile )
{
mBuffer = getCircularVolatileVertexBuffer()->getHandle();
return;
}
// Generate a buffer
glGenBuffers(1, &mBuffer);
//and allocate the needed memory
PRESERVE_VERTEX_BUFFER(); PRESERVE_VERTEX_BUFFER();
// Generate a buffer and allocate the needed memory. glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
glGenBuffers(1, &mBuffer); glBufferData(GL_ARRAY_BUFFER, numVerts * vertexSize, NULL, GFXGLBufferType[bufferType]);
glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
glBufferData(GL_ARRAY_BUFFER, numVerts * vertexSize, NULL, GFXGLBufferType[bufferType]);
glBindBuffer(GL_ARRAY_BUFFER, 0);
} }
GFXGLVertexBuffer::~GFXGLVertexBuffer() GFXGLVertexBuffer::~GFXGLVertexBuffer()
{ {
// While heavy handed, this does delete the buffer and frees the associated memory. // While heavy handed, this does delete the buffer and frees the associated memory.
glDeleteBuffers(1, &mBuffer); if( mBufferType != GFXBufferTypeVolatile )
glDeleteBuffers(1, &mBuffer);
if( mZombieCache ) if( mZombieCache )
delete [] mZombieCache; delete [] mZombieCache;
} }
void GFXGLVertexBuffer::lock( U32 vertexStart, U32 vertexEnd, void **vertexPtr ) void GFXGLVertexBuffer::lock( U32 vertexStart, U32 vertexEnd, void **vertexPtr )
{ {
PRESERVE_VERTEX_BUFFER(); PROFILE_SCOPE(GFXGLVertexBuffer_lock);
// Bind us, get a pointer into the buffer, then
// offset it by vertexStart so we act like the D3D layer. if( mBufferType == GFXBufferTypeVolatile )
glBindBuffer(GL_ARRAY_BUFFER, mBuffer); {
glBufferData(GL_ARRAY_BUFFER, mNumVerts * mVertexSize, NULL, GFXGLBufferType[mBufferType]); AssertFatal(vertexStart == 0, "");
*vertexPtr = (void*)((U8*)glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY) + (vertexStart * mVertexSize)); if( gglHasExtension(ARB_vertex_attrib_binding) )
{
getCircularVolatileVertexBuffer()->lock( mNumVerts * mVertexSize, 0, mBufferOffset, *vertexPtr );
}
else
{
getCircularVolatileVertexBuffer()->lock( mNumVerts * mVertexSize, mVertexSize, mBufferOffset, *vertexPtr );
mBufferVertexOffset = mBufferOffset / mVertexSize;
}
}
else
{
mFrameAllocator.lock( mNumVerts * mVertexSize );
lockedVertexPtr = (void*)(mFrameAllocator.getlockedPtr() + (vertexStart * mVertexSize));
*vertexPtr = lockedVertexPtr;
}
lockedVertexStart = vertexStart; lockedVertexStart = vertexStart;
lockedVertexEnd = vertexEnd; lockedVertexEnd = vertexEnd;
} }
void GFXGLVertexBuffer::unlock() void GFXGLVertexBuffer::unlock()
{ {
PRESERVE_VERTEX_BUFFER(); PROFILE_SCOPE(GFXGLVertexBuffer_unlock);
// Unmap the buffer and bind 0 to GL_ARRAY_BUFFER
glBindBuffer(GL_ARRAY_BUFFER, mBuffer); if( mBufferType == GFXBufferTypeVolatile )
bool res = glUnmapBuffer(GL_ARRAY_BUFFER); {
AssertFatal(res, "GFXGLVertexBuffer::unlock - shouldn't fail!"); getCircularVolatileVertexBuffer()->unlock();
}
else
{
U32 offset = lockedVertexStart * mVertexSize;
U32 length = (lockedVertexEnd - lockedVertexStart) * mVertexSize;
PRESERVE_VERTEX_BUFFER();
glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
if( !lockedVertexStart && lockedVertexEnd == mNumVerts)
glBufferData(GL_ARRAY_BUFFER, mNumVerts * mVertexSize, NULL, GFXGLBufferType[mBufferType]); // orphan the buffer
glBufferSubData(GL_ARRAY_BUFFER, offset, length, mFrameAllocator.getlockedPtr() + offset );
mFrameAllocator.unlock();
}
lockedVertexStart = 0; lockedVertexStart = 0;
lockedVertexEnd = 0; lockedVertexEnd = 0;
lockedVertexPtr = NULL;
} }
void GFXGLVertexBuffer::prepare() void GFXGLVertexBuffer::prepare()
{ {
// Bind the buffer... AssertFatal(0, "GFXGLVertexBuffer::prepare - use GFXGLVertexBuffer::prepare(U32 stream, U32 divisor)");
glBindBuffer(GL_ARRAY_BUFFER, mBuffer); }
U8* buffer = (U8*)getBuffer();
// Loop thru the vertex format elements adding the array state... void GFXGLVertexBuffer::prepare(U32 stream, U32 divisor)
U32 texCoordIndex = 0; {
for ( U32 i=0; i < mVertexFormat.getElementCount(); i++ ) if( gglHasExtension(ARB_vertex_attrib_binding) )
{ {
const GFXVertexElement &element = mVertexFormat.getElement( i ); glBindVertexBuffer( stream, mBuffer, mBufferOffset, mVertexSize );
glVertexBindingDivisor( stream, divisor );
if ( element.isSemantic( GFXSemantic::POSITION ) ) return;
{
glEnableClientState( GL_VERTEX_ARRAY );
glVertexPointer( element.getSizeInBytes() / 4, GL_FLOAT, mVertexSize, buffer );
buffer += element.getSizeInBytes();
}
else if ( element.isSemantic( GFXSemantic::NORMAL ) )
{
glEnableClientState( GL_NORMAL_ARRAY );
glNormalPointer( GL_FLOAT, mVertexSize, buffer );
buffer += element.getSizeInBytes();
}
else if ( element.isSemantic( GFXSemantic::COLOR ) )
{
glEnableClientState( GL_COLOR_ARRAY );
glColorPointer( element.getSizeInBytes(), GL_UNSIGNED_BYTE, mVertexSize, buffer );
buffer += element.getSizeInBytes();
}
else // Everything else is a texture coordinate.
{
glClientActiveTexture( GL_TEXTURE0 + texCoordIndex );
glEnableClientState( GL_TEXTURE_COORD_ARRAY );
glTexCoordPointer( element.getSizeInBytes() / 4, GL_FLOAT, mVertexSize, buffer );
buffer += element.getSizeInBytes();
++texCoordIndex;
}
} }
} }
void GFXGLVertexBuffer::finish() void GFXGLVertexBuffer::finish()
{ {
glBindBuffer(GL_ARRAY_BUFFER, 0);
U32 texCoordIndex = 0;
for ( U32 i=0; i < mVertexFormat.getElementCount(); i++ )
{
const GFXVertexElement &element = mVertexFormat.getElement( i );
if ( element.isSemantic( GFXSemantic::POSITION ) )
glDisableClientState( GL_VERTEX_ARRAY );
else if ( element.isSemantic( GFXSemantic::NORMAL ) )
glDisableClientState( GL_NORMAL_ARRAY );
else if ( element.isSemantic( GFXSemantic::COLOR ) )
glDisableClientState( GL_COLOR_ARRAY );
else
{
glClientActiveTexture( GL_TEXTURE0 + texCoordIndex );
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
++texCoordIndex;
}
}
} }
GLvoid* GFXGLVertexBuffer::getBuffer() GLvoid* GFXGLVertexBuffer::getBuffer()
@ -175,3 +181,29 @@ void GFXGLVertexBuffer::resurrect()
delete[] mZombieCache; delete[] mZombieCache;
mZombieCache = NULL; mZombieCache = NULL;
} }
namespace
{
bool onGFXDeviceSignal( GFXDevice::GFXDeviceEventType type )
{
if( GFX->getAdapterType() == OpenGL && GFXDevice::deEndOfFrame == type )
getCircularVolatileVertexBuffer()->protectUsedRange();
return true;
}
}
MODULE_BEGIN( GFX_GL_VertexBuffer )
MODULE_INIT_AFTER( gfx )
MODULE_SHUTDOWN_BEFORE( gfx )
MODULE_INIT
{
GFXDevice::getDeviceEventSignal().notify( &onGFXDeviceSignal );
}
MODULE_SHUTDOWN
{
GFXDevice::getDeviceEventSignal( ).remove( &onGFXDeviceSignal );
}
MODULE_END

View file

@ -26,14 +26,14 @@
#ifndef _GFXVERTEXBUFFER_H_ #ifndef _GFXVERTEXBUFFER_H_
#include "gfx/gfxVertexBuffer.h" #include "gfx/gfxVertexBuffer.h"
#endif #endif
#ifndef GL_GGL_H #include "gfx/gl/tGL/tGL.h"
#include "gfx/gl/ggl/ggl.h" #include "gfx/gl/util/glFrameAllocatorLockableHelper.h"
#endif
/// This is a vertex buffer which uses GL_ARB_vertex_buffer_object. /// This is a vertex buffer which uses GL_ARB_vertex_buffer_object.
class GFXGLVertexBuffer : public GFXVertexBuffer class GFXGLVertexBuffer : public GFXVertexBuffer
{ {
public: public:
GFXGLVertexBuffer( GFXDevice *device, GFXGLVertexBuffer( GFXDevice *device,
U32 numVerts, U32 numVerts,
const GFXVertexFormat *vertexFormat, const GFXVertexFormat *vertexFormat,
@ -42,23 +42,32 @@ public:
~GFXGLVertexBuffer(); ~GFXGLVertexBuffer();
virtual void lock(U32 vertexStart, U32 vertexEnd, void **vertexPtr); ///< calls glMapBuffer and offsets the pointer by vertex start virtual void lock(U32 vertexStart, U32 vertexEnd, void **vertexPtr); ///< Only write lock are supported.
virtual void unlock(); ///< calls glUnmapBuffer, unbinds the buffer virtual void unlock(); ///<
virtual void prepare(); ///< Binds the buffer virtual void prepare(); ///< Do nothing. Use void prepare(U32 stream, U32 divisor).
virtual void finish(); ///< We're done here virtual void finish(); ///< Do nothing.
void prepare(U32 stream, U32 divisor);
GLvoid* getBuffer(); ///< returns NULL GLvoid* getBuffer(); ///< returns NULL
// GFXResource interface // GFXResource interface
virtual void zombify(); virtual void zombify();
virtual void resurrect(); virtual void resurrect();
private: private:
friend class GFXGLDevice; friend class GFXGLDevice;
/// GL buffer handle /// GL buffer handle
GLuint mBuffer; GLuint mBuffer;
/// bytes offset in buffer
U32 mBufferOffset;
/// start vertex offset in buffer
U32 mBufferVertexOffset;
U8* mZombieCache; U8* mZombieCache;
FrameAllocatorLockableHelper mFrameAllocator;
}; };
#endif #endif

View file

@ -0,0 +1,212 @@
#include "gfx/gl/gfxGLDevice.h"
#include "gfx/gl/gfxGLStateCache.h"
#include "gfx/gl/gfxGLVertexAttribLocation.h"
#include "gfx/gl/gfxGLVertexDecl.h"
void GFXGLVertexDecl::init(const GFXVertexFormat *format)
{
AssertFatal(!mFormat, "");
mFormat = format;
for(int i = 0; i < GFXGL->getNumVertexStreams(); ++i)
_initVerticesFormat(i);
}
void GFXGLVertexDecl::prepareVertexFormat() const
{
AssertFatal(mFormat, "GFXGLVertexDecl - Not inited");
if( gglHasExtension(ARB_vertex_attrib_binding) )
{
for ( U32 i=0; i < glVerticesFormat.size(); i++ )
{
const glVertexAttribData &glElement = glVerticesFormat[i];
glVertexAttribFormat( glElement.attrIndex, glElement.elementCount, glElement.type, glElement.normalized, (U32)glElement.pointerFirst );
glVertexAttribBinding( glElement.attrIndex, glElement.stream );
}
updateActiveVertexAttrib( GFXGL->getOpenglCache()->getCacheVertexAttribActive() );
return;
}
}
void GFXGLVertexDecl::prepareBuffer_old(U32 stream, GLint mBuffer, GLint mDivisor) const
{
PROFILE_SCOPE(GFXGLVertexDecl_prepare);
AssertFatal(mFormat, "GFXGLVertexDecl - Not inited");
if( gglHasExtension(ARB_vertex_attrib_binding) )
return;
// Bind the buffer...
glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
GFXGL->getOpenglCache()->setCacheBinded(GL_ARRAY_BUFFER, mBuffer);
// Loop thru the vertex format elements adding the array state...
for ( U32 i=0; i < glVerticesFormat.size(); i++ )
{
// glEnableVertexAttribArray are called and cache in GFXGLDevice::preDrawPrimitive
const glVertexAttribData &e = glVerticesFormat[i];
if(e.stream != stream)
continue;
glVertexAttribPointer(
e.attrIndex, // attribute
e.elementCount, // number of elements per vertex, here (r,g,b)
e.type, // the type of each element
e.normalized, // take our values as-is
e.stride, // stride between each position
e.pointerFirst // offset of first element
);
glVertexAttribDivisor( e.attrIndex, mDivisor );
}
}
void GFXGLVertexDecl::updateActiveVertexAttrib(U32 lastActiveMask) const
{
AssertFatal(mVertexAttribActiveMask, "GFXGLVertexDecl::updateActiveVertexAttrib - No vertex attribute are active");
U32 lastActiveVerxtexAttrib = GFXGL->getOpenglCache()->getCacheVertexAttribActive();
if(mVertexAttribActiveMask == lastActiveVerxtexAttrib)
return;
U32 forActiveMask = mVertexAttribActiveMask & ~lastActiveVerxtexAttrib;
U32 forDeactiveMask = ~mVertexAttribActiveMask & lastActiveVerxtexAttrib;
for(int i = 0; i < Torque::GL_VertexAttrib_COUNT; ++i)
{
if( BIT(i) & forActiveMask ) //if is active but not in last mask
glEnableVertexAttribArray(i);
else if( BIT(i) & forDeactiveMask ) // if not active but in last mask
glDisableVertexAttribArray(i);
}
GFXGL->getOpenglCache()->setCacheVertexAttribActive(mVertexAttribActiveMask);
}
void GFXGLVertexDecl::_initVerticesFormat2()
{
for( U32 i=0; i < GFXGL->getNumVertexStreams(); ++i )
{
_initVerticesFormat(i);
}
}
void GFXGLVertexDecl::_initVerticesFormat(U32 stream)
{
U32 buffer = 0;
U32 vertexSize = 0;
for ( U32 i=0; i < mFormat->getElementCount(); i++ )
{
const GFXVertexElement &element = mFormat->getElement( i );
if(element.getStreamIndex() != stream)
continue;
vertexSize += element.getSizeInBytes();
}
// Loop thru the vertex format elements adding the array state...
U32 texCoordIndex = 0;
for ( U32 i=0; i < mFormat->getElementCount(); i++ )
{
const GFXVertexElement &element = mFormat->getElement( i );
if(element.getStreamIndex() != stream)
continue;
glVerticesFormat.increment();
glVertexAttribData &glElement = glVerticesFormat.last();
glElement.stream = element.getStreamIndex();
if ( element.isSemantic( GFXSemantic::POSITION ) )
{
glElement.attrIndex = Torque::GL_VertexAttrib_Position;
glElement.elementCount = element.getSizeInBytes() / 4;
glElement.normalized = false;
glElement.type = GL_FLOAT;
glElement.stride = vertexSize;
glElement.pointerFirst = (void*)buffer;
buffer += element.getSizeInBytes();
}
else if ( element.isSemantic( GFXSemantic::NORMAL ) )
{
glElement.attrIndex = Torque::GL_VertexAttrib_Normal;
glElement.elementCount = 3;
glElement.normalized = false;
glElement.type = GL_FLOAT;
glElement.stride = vertexSize;
glElement.pointerFirst = (void*)buffer;
buffer += element.getSizeInBytes();
}
else if ( element.isSemantic( GFXSemantic::TANGENT ) )
{
glElement.attrIndex = Torque::GL_VertexAttrib_Tangent;
glElement.elementCount = 3;
glElement.normalized = false;
glElement.type = GL_FLOAT;
glElement.stride = vertexSize;
glElement.pointerFirst = (void*)buffer;
buffer += element.getSizeInBytes();
}
else if ( element.isSemantic( GFXSemantic::TANGENTW ) )
{
glElement.attrIndex = Torque::GL_VertexAttrib_TangentW;
glElement.elementCount = element.getSizeInBytes()/4;
glElement.normalized = false;
glElement.type = GL_FLOAT;
glElement.stride = vertexSize;
glElement.pointerFirst = (void*)buffer;
buffer += element.getSizeInBytes();
}
else if ( element.isSemantic( GFXSemantic::BINORMAL ) )
{
glElement.attrIndex = Torque::GL_VertexAttrib_Binormal;
glElement.elementCount = 3;
glElement.normalized = false;
glElement.type = GL_FLOAT;
glElement.stride = vertexSize;
glElement.pointerFirst = (void*)buffer;
buffer += element.getSizeInBytes();
}
else if ( element.isSemantic( GFXSemantic::COLOR ) )
{
glElement.attrIndex = Torque::GL_VertexAttrib_Color;
glElement.elementCount = element.getSizeInBytes();
glElement.normalized = true;
glElement.type = GL_UNSIGNED_BYTE;
glElement.stride = vertexSize;
glElement.pointerFirst = (void*)buffer;
buffer += element.getSizeInBytes();
}
else // Everything else is a texture coordinate.
{
String name = element.getSemantic();
glElement.elementCount = element.getSizeInBytes() / 4;
texCoordIndex = getMax(texCoordIndex, element.getSemanticIndex());
glElement.attrIndex = Torque::GL_VertexAttrib_TexCoord0 + texCoordIndex;
glElement.normalized = false;
glElement.type = GL_FLOAT;
glElement.stride = vertexSize;
glElement.pointerFirst = (void*)buffer;
buffer += element.getSizeInBytes();
++texCoordIndex;
}
AssertFatal(!( mVertexAttribActiveMask & BIT(glElement.attrIndex) ), "GFXGLVertexBuffer::_initVerticesFormat - Duplicate vertex attrib index");
mVertexAttribActiveMask |= BIT(glElement.attrIndex);
}
mVertexSize[stream] = vertexSize;
AssertFatal(vertexSize == buffer, "");
}

View file

@ -0,0 +1,39 @@
#ifndef GFX_GL_VERTEX_DECL
#define GFX_GL_VERTEX_DECL
class GFXVertexFormat;
class GFXGLDevice;
class GFXGLVertexDecl : public GFXVertexDecl
{
public:
GFXGLVertexDecl() : mFormat(NULL), mVertexAttribActiveMask(0) {}
void init(const GFXVertexFormat *format);
void prepareVertexFormat() const;
void prepareBuffer_old(U32 stream, GLint mBuffer, GLint mDivisor) const;
void updateActiveVertexAttrib(U32 lastActiveMask) const;
struct glVertexAttribData
{
U32 stream;
GLint attrIndex;
GLint elementCount; // 1 - 4
GLenum type; // GL_FLOAT...
GLboolean normalized;
GLsizei stride;
GLvoid *pointerFirst;
};
protected:
friend class GFXGLDevice;
const GFXVertexFormat *mFormat;
GLuint mVertexSize[4];
U32 mVertexAttribActiveMask;
Vector<glVertexAttribData> glVerticesFormat;
void _initVerticesFormat(U32 stream);
void _initVerticesFormat2();
};
#endif //GFX_GL_VERTEX_DECL

View file

@ -25,9 +25,19 @@
#include "gfx/gl/gfxGLWindowTarget.h" #include "gfx/gl/gfxGLWindowTarget.h"
#include "gfx/gl/gfxGLTextureObject.h" #include "gfx/gl/gfxGLTextureObject.h"
#include "gfx/gl/gfxGLUtils.h" #include "gfx/gl/gfxGLUtils.h"
#include "postFx/postEffect.h"
GFX_ImplementTextureProfile( BackBufferDepthProfile,
GFXTextureProfile::DiffuseMap,
GFXTextureProfile::PreserveSize |
GFXTextureProfile::NoMipmap |
GFXTextureProfile::ZTarget |
GFXTextureProfile::Pooled,
GFXTextureProfile::NONE );
GFXGLWindowTarget::GFXGLWindowTarget(PlatformWindow *win, GFXDevice *d) GFXGLWindowTarget::GFXGLWindowTarget(PlatformWindow *win, GFXDevice *d)
: GFXWindowTarget(win), mDevice(d), mContext(NULL), mFullscreenContext(NULL) : GFXWindowTarget(win), mDevice(d), mContext(NULL), mFullscreenContext(NULL)
, mCopyFBO(0), mBackBufferFBO(0)
{ {
win->appEvent.notify(this, &GFXGLWindowTarget::_onAppSignal); win->appEvent.notify(this, &GFXGLWindowTarget::_onAppSignal);
} }
@ -59,21 +69,85 @@ void GFXGLWindowTarget::resolveTo(GFXTextureObject* obj)
AssertFatal(dynamic_cast<GFXGLTextureObject*>(obj), "GFXGLTextureTarget::resolveTo - Incorrect type of texture, expected a GFXGLTextureObject"); AssertFatal(dynamic_cast<GFXGLTextureObject*>(obj), "GFXGLTextureTarget::resolveTo - Incorrect type of texture, expected a GFXGLTextureObject");
GFXGLTextureObject* glTexture = static_cast<GFXGLTextureObject*>(obj); GFXGLTextureObject* glTexture = static_cast<GFXGLTextureObject*>(obj);
if( gglHasExtension(ARB_copy_image) )
{
if(mBackBufferColorTex.getWidth() == glTexture->getWidth()
&& mBackBufferColorTex.getHeight() == glTexture->getHeight()
&& mBackBufferColorTex.getFormat() == glTexture->getFormat())
{
glCopyImageSubData(
static_cast<GFXGLTextureObject*>(mBackBufferColorTex.getPointer())->getHandle(), GL_TEXTURE_2D, 0, 0, 0, 0,
glTexture->getHandle(), GL_TEXTURE_2D, 0, 0, 0, 0,
getSize().x, getSize().y, 1);
return;
}
}
PRESERVE_FRAMEBUFFER(); PRESERVE_FRAMEBUFFER();
if(!mCopyFBO)
{
glGenFramebuffers(1, &mCopyFBO);
}
GLuint dest; glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mCopyFBO);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, glTexture->getHandle(), 0);
glGenFramebuffersEXT(1, &dest); glBindFramebuffer(GL_READ_FRAMEBUFFER, mBackBufferFBO);
glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, dest); glBlitFramebuffer(0, 0, getSize().x, getSize().y,
glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, glTexture->getHandle(), 0);
glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
glBlitFramebufferEXT(0, 0, getSize().x, getSize().y,
0, 0, glTexture->getWidth(), glTexture->getHeight(), GL_COLOR_BUFFER_BIT, GL_NEAREST); 0, 0, glTexture->getWidth(), glTexture->getHeight(), GL_COLOR_BUFFER_BIT, GL_NEAREST);
}
glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0);
inline void GFXGLWindowTarget::_setupAttachments()
glDeleteFramebuffersEXT(1, &dest); {
glBindFramebuffer( GL_FRAMEBUFFER, mBackBufferFBO);
GFXGL->getOpenglCache()->setCacheBinded(GL_FRAMEBUFFER, mBackBufferFBO);
const Point2I dstSize = getSize();
mBackBufferColorTex.set(dstSize.x, dstSize.y, getFormat(), &PostFxTargetProfile, "backBuffer");
GFXGLTextureObject *color = static_cast<GFXGLTextureObject*>(mBackBufferColorTex.getPointer());
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color->getHandle(), 0);
mBackBufferDepthTex.set(dstSize.x, dstSize.y, GFXFormatD24S8, &BackBufferDepthProfile, "backBuffer");
GFXGLTextureObject *depth = static_cast<GFXGLTextureObject*>(mBackBufferDepthTex.getPointer());
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depth->getHandle(), 0);
}
void GFXGLWindowTarget::makeActive()
{
if(mBackBufferFBO)
{
glBindFramebuffer( GL_FRAMEBUFFER, mBackBufferFBO);
GFXGL->getOpenglCache()->setCacheBinded(GL_FRAMEBUFFER, mBackBufferFBO);
}
else
{
glGenFramebuffers(1, &mBackBufferFBO);
_setupAttachments();
CHECK_FRAMEBUFFER_STATUS();
}
}
bool GFXGLWindowTarget::present()
{
PRESERVE_FRAMEBUFFER();
const Point2I srcSize = mBackBufferColorTex.getWidthHeight();
const Point2I dstSize = getSize();
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glBindFramebuffer(GL_READ_FRAMEBUFFER, mBackBufferFBO);
// OpenGL render upside down for make render more similar to DX.
// Final screen are corrected here
glBlitFramebuffer(
0, 0, srcSize.x, srcSize.y,
0, dstSize.y, dstSize.x, 0, // Y inverted
GL_COLOR_BUFFER_BIT, GL_NEAREST);
_WindowPresent();
if(srcSize != dstSize || mBackBufferDepthTex.getWidthHeight() != dstSize)
_setupAttachments();
return true;
} }

View file

@ -51,12 +51,17 @@ public:
private: private:
friend class GFXGLDevice; friend class GFXGLDevice;
GLuint mCopyFBO, mBackBufferFBO;
GFXTexHandle mBackBufferColorTex, mBackBufferDepthTex;
Point2I size; Point2I size;
GFXDevice* mDevice; GFXDevice* mDevice;
void* mContext; void* mContext;
void* mFullscreenContext; void* mFullscreenContext;
void _teardownCurrentMode(); void _teardownCurrentMode();
void _setupNewMode(); void _setupNewMode();
void _setupAttachments();
void _WindowPresent();
}; };
#endif #endif

View file

@ -0,0 +1,225 @@
//-----------------------------------------------------------------------------
// Copyright (c) 2012 GarageGames, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#if defined( TORQUE_SDL )
#include "gfx/gfxCubemap.h"
#include "gfx/screenshot.h"
#include "gfx/gl/gfxGLDevice.h"
#include "gfx/gl/gfxGLEnumTranslate.h"
#include "gfx/gl/gfxGLVertexBuffer.h"
#include "gfx/gl/gfxGLPrimitiveBuffer.h"
#include "gfx/gl/gfxGLTextureTarget.h"
#include "gfx/gl/gfxGLWindowTarget.h"
#include "gfx/gl/gfxGLTextureManager.h"
#include "gfx/gl/gfxGLTextureObject.h"
#include "gfx/gl/gfxGLCubemap.h"
#include "gfx/gl/gfxGLCardProfiler.h"
#include "windowManager/sdl/sdlWindow.h"
#include "platform/platformGL.h"
#include "SDL.h"
extern void loadGLCore();
extern void loadGLExtensions(void* context);
void EnumerateVideoModes(Vector<GFXVideoMode>& outModes)
{
int count = SDL_GetNumDisplayModes( 0 );
if( count < 0)
{
AssertFatal(0, "");
return;
}
SDL_DisplayMode mode;
for(int i = 0; i < count; ++i)
{
SDL_GetDisplayMode( 0, i, &mode);
GFXVideoMode outMode;
outMode.resolution.set( mode.w, mode.h );
outMode.refreshRate = mode.refresh_rate;
outMode.bitDepth = SDL_BYTESPERPIXEL( mode.format );
outMode.wideScreen = (mode.w / mode.h) > (4 / 3);
outMode.fullScreen = true;
outModes.push_back( outMode );
}
}
void GFXGLDevice::enumerateAdapters( Vector<GFXAdapter*> &adapterList )
{
AssertFatal( SDL_WasInit(SDL_INIT_VIDEO), "");
PlatformGL::init(); // for hints about context creation
// Create a dummy window & openGL context so that gl functions can be used here
SDL_Window* tempWindow = SDL_CreateWindow(
"", // window title
SDL_WINDOWPOS_UNDEFINED, // initial x position
SDL_WINDOWPOS_UNDEFINED, // initial y position
640, // width, in pixels
480, // height, in pixels
SDL_WINDOW_OPENGL | SDL_WINDOW_HIDDEN // flags - see below
);
SDL_ClearError();
SDL_GLContext tempContext = SDL_GL_CreateContext( tempWindow );
if( !tempContext )
{
const char *err = SDL_GetError();
Con::printf( err );
AssertFatal(0, err );
return;
}
SDL_ClearError();
SDL_GL_MakeCurrent( tempWindow, tempContext );
const char *err = SDL_GetError();
if( err && err[0] )
{
Con::printf( err );
AssertFatal(0, err );
}
//check minimun Opengl 3.2
int major, minor;
glGetIntegerv(GL_MAJOR_VERSION, &major);
glGetIntegerv(GL_MINOR_VERSION, &minor);
if( major < 3 || ( major == 3 && minor < 2 ) )
{
return;
}
loadGLCore();
GFXAdapter *toAdd = new GFXAdapter;
toAdd->mIndex = 0;
const char* renderer = (const char*) glGetString( GL_RENDERER );
AssertFatal( renderer != NULL, "GL_RENDERER returned NULL!" );
if (renderer)
{
dStrcpy(toAdd->mName, renderer);
dStrncat(toAdd->mName, " OpenGL", GFXAdapter::MaxAdapterNameLen);
}
else
dStrcpy(toAdd->mName, "OpenGL");
toAdd->mType = OpenGL;
toAdd->mShaderModel = 0.f;
toAdd->mCreateDeviceInstanceDelegate = mCreateDeviceInstance;
// Enumerate all available resolutions:
EnumerateVideoModes(toAdd->mAvailableModes);
// Add to the list of available adapters.
adapterList.push_back(toAdd);
// Cleanup window & open gl context
SDL_DestroyWindow( tempWindow );
SDL_GL_DeleteContext( tempContext );
}
void GFXGLDevice::enumerateVideoModes()
{
mVideoModes.clear();
EnumerateVideoModes(mVideoModes);
}
void GFXGLDevice::init( const GFXVideoMode &mode, PlatformWindow *window )
{
AssertFatal(window, "GFXGLDevice::init - no window specified, can't init device without a window!");
PlatformWindowSDL* x11Window = dynamic_cast<PlatformWindowSDL*>(window);
AssertFatal(x11Window, "Window is not a valid PlatformWindowSDL object");
// Create OpenGL context
mContext = PlatformGL::CreateContextGL( x11Window );
PlatformGL::MakeCurrentGL( x11Window, mContext );
loadGLCore();
loadGLExtensions(0);
// It is very important that extensions be loaded before we call initGLState()
initGLState();
mProjectionMatrix.identity();
mInitialized = true;
deviceInited();
}
bool GFXGLDevice::beginSceneInternal()
{
mCanCurrentlyRender = true;
return true;
}
U32 GFXGLDevice::getTotalVideoMemory()
{
return getTotalVideoMemory_GL_EXT();
}
//------------------------------------------------------------------------------
GFXWindowTarget *GFXGLDevice::allocWindowTarget( PlatformWindow *window )
{
AssertFatal(!mContext, "This GFXGLDevice is already assigned to a window");
GFXGLWindowTarget* ggwt = 0;
if( !mContext )
{
// no context, init the device now
init(window->getVideoMode(), window);
ggwt = new GFXGLWindowTarget(window, this);
ggwt->registerResourceWithDevice(this);
ggwt->mContext = mContext;
}
return ggwt;
}
GFXFence* GFXGLDevice::_createPlatformSpecificFence()
{
return NULL;
}
//-----------------------------------------------------------------------------
void GFXGLWindowTarget::_WindowPresent()
{
SDL_GL_SwapWindow( static_cast<PlatformWindowSDL*>( getWindow() )->getSDLWindow() );
}
void GFXGLWindowTarget::_teardownCurrentMode()
{
}
void GFXGLWindowTarget::_setupNewMode()
{
}
#endif

View file

@ -0,0 +1,41 @@
//-----------------------------------------------------------------------------
// Copyright (c) 2012 GarageGames, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#include "tGL.h"
#include "core/strings/stringFunctions.h"
#include "console/console.h"
namespace GL
{
void gglPerformBinds()
{
GLenum err = glewInit();
AssertFatal(GLEW_OK == err, avar("Error: %s\n", glewGetErrorString(err)) );
}
void gglPerformExtensionBinds(void *context)
{
}
}

View file

@ -0,0 +1,30 @@
//-----------------------------------------------------------------------------
// Copyright (c) 2012 GarageGames, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#ifndef T_GL_H
#define T_GL_H
#include "GL/glew.h"
#define gglHasExtension(EXTENSION) GLEW_##EXTENSION
#endif

View file

@ -0,0 +1,38 @@
//-----------------------------------------------------------------------------
// Copyright (c) 2012 GarageGames, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#ifndef GFX_TORQUE_WGL_H
#define GFX_TORQUE_WGL_H
#include "platform/platform.h"
#ifdef TORQUE_OS_WIN32
#include "tGL.h"
#include "GL/wglew.h"
#define gglHasWExtension(EXTENSION) WGLEW_##EXTENSION
#endif //TORQUE_OS_WIN32
#endif

View file

@ -0,0 +1,38 @@
//-----------------------------------------------------------------------------
// Copyright (c) 2012 GarageGames, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#ifndef GFX_TORQUE_XGL_H
#define GFX_TORQUE_XGL_H
#include "platform/platform.h"
#ifdef TORQUE_OS_LINUX
#include "tGL.h"
#include "GL/glxew.h"
#define gglHasXExtension(EXTENSION) GLXEW##EXTENSION
#endif //TORQUE_OS_LINUX
#endif

View file

@ -0,0 +1,53 @@
#ifndef GL_FRAMEALLOCATOR_LOCKABLE_HELPER_H
#define GL_FRAMEALLOCATOR_LOCKABLE_HELPER_H
#include "core/frameAllocator.h"
/// Helper class for simulate lock/unlock on gfx buffers using FrameAllocator
class FrameAllocatorLockableHelper
{
public:
FrameAllocatorLockableHelper()
: mFrameAllocatorMark(0),
mFrameAllocatorPtr(NULL)
#if TORQUE_DEBUG
, mFrameAllocatorMarkGuard(0)
#endif
{
}
U8* lock(const U32 size)
{
AssertFatal(!mFrameAllocatorMark && !mFrameAllocatorPtr, "");
mFrameAllocatorMark = FrameAllocator::getWaterMark();
mFrameAllocatorPtr = (U8*)FrameAllocator::alloc( size );
#if TORQUE_DEBUG
mFrameAllocatorMarkGuard = FrameAllocator::getWaterMark();
#endif
return mFrameAllocatorPtr;
}
void unlock()
{
#if TORQUE_DEBUG
AssertFatal(mFrameAllocatorMarkGuard == FrameAllocator::getWaterMark(), "");
#endif
FrameAllocator::setWaterMark(mFrameAllocatorMark);
mFrameAllocatorMark = 0;
mFrameAllocatorPtr = NULL;
}
U8* getlockedPtr() const { return mFrameAllocatorPtr; }
protected:
U32 mFrameAllocatorMark;
U8 *mFrameAllocatorPtr;
#if TORQUE_DEBUG
U32 mFrameAllocatorMarkGuard;
#endif
};
#endif //GL_FRAMEALLOCATOR_LOCKABLE_HELPER_H

View file

@ -35,7 +35,10 @@
#include "gfx/GL/gfxGLCubemap.h" #include "gfx/GL/gfxGLCubemap.h"
#include "gfx/GL/gfxGLCardProfiler.h" #include "gfx/GL/gfxGLCardProfiler.h"
#include "windowManager/win32/win32Window.h" #include "windowManager/win32/win32Window.h"
#include "ggl/Win32/wgl.h" #include "gfx/gl/tGL/tWGL.h"
#include "postFx/postEffect.h"
#include "gfx/gl/gfxGLUtils.h"
#define GETHWND(x) static_cast<Win32Window*>(x)->getHWND() #define GETHWND(x) static_cast<Win32Window*>(x)->getHWND()
@ -105,7 +108,7 @@ void GFXGLDevice::enumerateAdapters( Vector<GFXAdapter*> &adapterList )
// Create pixel format descriptor... // Create pixel format descriptor...
PIXELFORMATDESCRIPTOR pfd; PIXELFORMATDESCRIPTOR pfd;
CreatePixelFormat( &pfd, 16, 16, 8, false ); // 16 bit color, 16 bit depth, 8 bit stencil...everyone can do this CreatePixelFormat( &pfd, 32, 0, 0, false );
if( !SetPixelFormat( tempDC, ChoosePixelFormat( tempDC, &pfd ), &pfd ) ) if( !SetPixelFormat( tempDC, ChoosePixelFormat( tempDC, &pfd ), &pfd ) )
AssertFatal( false, "I don't know who's responcible for this, but I want caught..." ); AssertFatal( false, "I don't know who's responcible for this, but I want caught..." );
@ -239,6 +242,8 @@ void GFXGLDevice::init( const GFXVideoMode &mode, PlatformWindow *window )
AssertFatal(dynamic_cast<Win32Window*>(window), "Invalid window class type!"); AssertFatal(dynamic_cast<Win32Window*>(window), "Invalid window class type!");
HWND hwnd = GETHWND(window); HWND hwnd = GETHWND(window);
mWindowRT = &static_cast<Win32Window*>(window)->mTarget;
RECT rect; RECT rect;
GetClientRect(hwnd, &rect); GetClientRect(hwnd, &rect);
@ -252,14 +257,41 @@ void GFXGLDevice::init( const GFXVideoMode &mode, PlatformWindow *window )
// Create pixel format descriptor... // Create pixel format descriptor...
PIXELFORMATDESCRIPTOR pfd; PIXELFORMATDESCRIPTOR pfd;
CreatePixelFormat( &pfd, 16, 16, 8, false ); // 16 bit color, 16 bit depth, 8 bit stencil...everyone can do this CreatePixelFormat( &pfd, 32, 0, 0, false ); // 32 bit color... We do not need depth or stencil, OpenGL renders into a FBO and then copy the image to window
if( !SetPixelFormat( hdcGL, ChoosePixelFormat( hdcGL, &pfd ), &pfd ) ) if( !SetPixelFormat( hdcGL, ChoosePixelFormat( hdcGL, &pfd ), &pfd ) )
{ {
AssertFatal( false, "GFXGLDevice::init - cannot get the one and only pixel format we check for." ); AssertFatal( false, "GFXGLDevice::init - cannot get the one and only pixel format we check for." );
} }
// Create a rendering context! int OGL_MAJOR = 3;
mContext = wglCreateContext( hdcGL ); int OGL_MINOR = 2;
#if TORQUE_DEBUG
int debugFlag = WGL_CONTEXT_DEBUG_BIT_ARB;
#else
int debugFlag = 0;
#endif
if( gglHasWExtension(ARB_create_context) )
{
int const create_attribs[] = {
WGL_CONTEXT_MAJOR_VERSION_ARB, OGL_MAJOR,
WGL_CONTEXT_MINOR_VERSION_ARB, OGL_MINOR,
WGL_CONTEXT_FLAGS_ARB, /*WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB |*/ debugFlag,
WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
//WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
0
};
mContext = wglCreateContextAttribsARB(hdcGL, 0, create_attribs);
if(!mContext)
{
AssertFatal(0,"");
}
}
else
mContext = wglCreateContext( hdcGL );
if( !wglMakeCurrent( hdcGL, (HGLRC)mContext ) ) if( !wglMakeCurrent( hdcGL, (HGLRC)mContext ) )
AssertFatal( false , "GFXGLDevice::init - cannot make our context current. Or maybe we can't create it." ); AssertFatal( false , "GFXGLDevice::init - cannot make our context current. Or maybe we can't create it." );
@ -280,101 +312,30 @@ void GFXGLDevice::init( const GFXVideoMode &mode, PlatformWindow *window )
bool GFXGLDevice::beginSceneInternal() bool GFXGLDevice::beginSceneInternal()
{ {
glGetError(); mCanCurrentlyRender = true;
return true; return true;
} }
U32 GFXGLDevice::getTotalVideoMemory() U32 GFXGLDevice::getTotalVideoMemory()
{ {
// CodeReview [ags 12/21/07] Figure out how to do this. return getTotalVideoMemory_GL_EXT();
return 0;
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
GFXWindowTarget *GFXGLDevice::allocWindowTarget( PlatformWindow *window ) GFXWindowTarget *GFXGLDevice::allocWindowTarget( PlatformWindow *window )
{ {
HDC hdcGL = GetDC(GETHWND(window)); AssertFatal(!mContext, "");
if(!mContext) init(window->getVideoMode(), window);
{
init(window->getVideoMode(), window);
GFXGLWindowTarget *ggwt = new GFXGLWindowTarget(window, this);
ggwt->registerResourceWithDevice(this);
ggwt->mContext = wglCreateContext(hdcGL);
AssertFatal(ggwt->mContext, "GFXGLDevice::allocWindowTarget - failed to allocate window target!");
return ggwt;
}
GFXGLWindowTarget *ggwt = new GFXGLWindowTarget(window, this); GFXGLWindowTarget *ggwt = new GFXGLWindowTarget(window, this);
ggwt->registerResourceWithDevice(this); ggwt->registerResourceWithDevice(this);
ggwt->mContext = mContext;
// Create pixel format descriptor...
PIXELFORMATDESCRIPTOR pfd;
CreatePixelFormat( &pfd, 16, 16, 8, false ); // 16 bit color, 16 bit depth, 8 bit stencil...everyone can do this
if( !SetPixelFormat( hdcGL, ChoosePixelFormat( hdcGL, &pfd ), &pfd ) )
{
AssertFatal( false, "GFXGLDevice::allocWindowTarget - cannot get the one and only pixel format we check for." );
}
ggwt->mContext = wglCreateContext(hdcGL);
DWORD w = GetLastError();
AssertFatal(ggwt->mContext, "GFXGLDevice::allocWindowTarget - failed to allocate window target!"); AssertFatal(ggwt->mContext, "GFXGLDevice::allocWindowTarget - failed to allocate window target!");
wglMakeCurrent(NULL, NULL);
bool res = wglShareLists((HGLRC)mContext, (HGLRC)ggwt->mContext);
w = GetLastError();
wglMakeCurrent(hdcGL, (HGLRC)ggwt->mContext);
AssertFatal(res, "GFXGLDevice::allocWindowTarget - wasn't able to share contexts!");
return ggwt; return ggwt;
} }
void GFXGLDevice::_updateRenderTargets()
{
if ( mRTDirty || mCurrentRT->isPendingState() )
{
// GL doesn't need to deactivate targets.
mRTDeactivate = NULL;
// NOTE: The render target changes is not really accurate
// as the GFXTextureTarget supports MRT internally. So when
// we activate a GFXTarget it could result in multiple calls
// to SetRenderTarget on the actual device.
mDeviceStatistics.mRenderTargetChanges++;
GFXGLTextureTarget *tex = dynamic_cast<GFXGLTextureTarget*>( mCurrentRT.getPointer() );
if ( tex )
{
tex->applyState();
tex->makeActive();
}
else
{
GFXGLWindowTarget *win = dynamic_cast<GFXGLWindowTarget*>( mCurrentRT.getPointer() );
AssertFatal( win != NULL,
"GFXGLDevice::_updateRenderTargets() - invalid target subclass passed!" );
//DWORD w1 = GetLastError();
HWND hwnd = GETHWND(win->getWindow());
HDC winDc = GetDC(hwnd);
bool res = wglMakeCurrent(winDc,(HGLRC)win->mContext);
//DWORD w2 = GetLastError();
AssertFatal(res==true,"GFXGLDevice::setActiveRenderTarget - failed");
}
mRTDirty = false;
}
if ( mViewportDirty )
{
glViewport( mViewport.point.x, mViewport.point.y, mViewport.extent.x, mViewport.extent.y );
mViewportDirty = false;
}
}
GFXFence* GFXGLDevice::_createPlatformSpecificFence() GFXFence* GFXGLDevice::_createPlatformSpecificFence()
{ {
return NULL; return NULL;
@ -382,16 +343,10 @@ GFXFence* GFXGLDevice::_createPlatformSpecificFence()
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void GFXGLWindowTarget::_WindowPresent()
void GFXGLWindowTarget::makeActive()
{
}
bool GFXGLWindowTarget::present()
{ {
HWND hwnd = GETHWND(getWindow()); HWND hwnd = GETHWND(getWindow());
SwapBuffers(GetDC(hwnd)); SwapBuffers(GetDC(hwnd));
return true;
} }
void GFXGLWindowTarget::_teardownCurrentMode() void GFXGLWindowTarget::_teardownCurrentMode()

View file

@ -142,7 +142,7 @@ Var *AdvancedLightBufferConditioner::printMethodHeader( MethodType methodType, c
meta->addStatement( new GenOp( " -1.0217f, 1.9777f, 0.0439f,\r\n" ) ); meta->addStatement( new GenOp( " -1.0217f, 1.9777f, 0.0439f,\r\n" ) );
meta->addStatement( new GenOp( " 0.0753f, -0.2543f, 1.1892f\r\n" ) ); meta->addStatement( new GenOp( " 0.0753f, -0.2543f, 1.1892f\r\n" ) );
meta->addStatement( new GenOp( " };\r\n" ) ); meta->addStatement( new GenOp( " };\r\n" ) );
meta->addStatement( new GenOp( " return mul(XYZ2RGB, XYZ);\r\n" ) ); meta->addStatement( new GenOp( " return tMul(XYZ2RGB, XYZ);\r\n" ) );
meta->addStatement( new GenOp( "}\r\n\r\n" ) ); meta->addStatement( new GenOp( "}\r\n\r\n" ) );
} }
else else

View file

@ -35,6 +35,8 @@
#include "math/util/sphereMesh.h" #include "math/util/sphereMesh.h"
#include "console/consoleTypes.h" #include "console/consoleTypes.h"
#include "scene/sceneRenderState.h" #include "scene/sceneRenderState.h"
#include "gfx/gfxCardProfile.h"
#include "gfx/gfxTextureProfile.h"
ImplementEnumType( ShadowType, ImplementEnumType( ShadowType,
@ -81,6 +83,9 @@ bool AdvancedLightManager::isCompatible() const
return false; return false;
// TODO: Test for the necessary texture formats! // TODO: Test for the necessary texture formats!
bool autoMips;
if(!GFX->getCardProfiler()->checkFormat(GFXFormatR16F, &GFXDefaultRenderTargetProfile, autoMips))
return false;
return true; return true;
} }

View file

@ -81,13 +81,13 @@ MaterialManager::MaterialManager()
Con::addVariableNotify( "$pref::Video::defaultAnisotropy", callabck ); Con::addVariableNotify( "$pref::Video::defaultAnisotropy", callabck );
Con::NotifyDelegate callabck2( this, &MaterialManager::_onDisableMaterialFeature ); Con::NotifyDelegate callabck2( this, &MaterialManager::_onDisableMaterialFeature );
Con::setVariable( "$pref::Video::disableNormalMapping", false ); Con::setVariable( "$pref::Video::disableNormalMapping", "false" );
Con::addVariableNotify( "$pref::Video::disableNormalMapping", callabck2 ); Con::addVariableNotify( "$pref::Video::disableNormalMapping", callabck2 );
Con::setVariable( "$pref::Video::disablePixSpecular", false ); Con::setVariable( "$pref::Video::disablePixSpecular", "false" );
Con::addVariableNotify( "$pref::Video::disablePixSpecular", callabck2 ); Con::addVariableNotify( "$pref::Video::disablePixSpecular", callabck2 );
Con::setVariable( "$pref::Video::disableCubemapping", false ); Con::setVariable( "$pref::Video::disableCubemapping", "false" );
Con::addVariableNotify( "$pref::Video::disableCubemapping", callabck2 ); Con::addVariableNotify( "$pref::Video::disableCubemapping", callabck2 );
Con::setVariable( "$pref::Video::disableParallaxMapping", false ); Con::setVariable( "$pref::Video::disableParallaxMapping", "false" );
Con::addVariableNotify( "$pref::Video::disableParallaxMapping", callabck2 ); Con::addVariableNotify( "$pref::Video::disableParallaxMapping", callabck2 );
} }
@ -416,6 +416,9 @@ void MaterialManager::recalcFeaturesFromPrefs()
mExclusionFeatures.setFeature( MFT_NormalMap, mExclusionFeatures.setFeature( MFT_NormalMap,
Con::getBoolVariable( "$pref::Video::disableNormalMapping", false ) ); Con::getBoolVariable( "$pref::Video::disableNormalMapping", false ) );
mExclusionFeatures.setFeature( MFT_SpecularMap,
Con::getBoolVariable( "$pref::Video::disablePixSpecular", false ) );
mExclusionFeatures.setFeature( MFT_PixSpecular, mExclusionFeatures.setFeature( MFT_PixSpecular,
Con::getBoolVariable( "$pref::Video::disablePixSpecular", false ) ); Con::getBoolVariable( "$pref::Video::disablePixSpecular", false ) );

View file

@ -0,0 +1,17 @@
#ifndef PLATFORM_GL_H
#define PLATFORM_GL_H
class PlatformWindow;
namespace PlatformGL
{
void init();
void* CreateContextGL( PlatformWindow *window );
void MakeCurrentGL( PlatformWindow *window, void *glContext );
void setVSync(const int i);
}
#endif //PLATFORM_GL_H

View file

@ -0,0 +1,11 @@
#if defined(TORQUE_OPENGL) && !defined(TORQUE_SDL)
#include "platform/platformGL.h"
#include "gfx/gl/tGL/tWGL.h"
void PlatformGL::setVSync(const int i)
{
wglSwapIntervalEXT( i );
}
#endif

View file

@ -834,12 +834,12 @@ Var* LinearEyeDepthConditioner::printMethodHeader( MethodType methodType, const
// possible so that the shader compiler can optimize. // possible so that the shader compiler can optimize.
meta->addStatement( new GenOp( " #if TORQUE_SM >= 30\r\n" ) ); meta->addStatement( new GenOp( " #if TORQUE_SM >= 30\r\n" ) );
if (GFX->getAdapterType() == OpenGL) if (GFX->getAdapterType() == OpenGL)
meta->addStatement( new GenOp( " @ = texture2DLod(@, @, 0); \r\n", bufferSampleDecl, prepassSampler, screenUV) ); meta->addStatement( new GenOp( " @ = textureLod(@, @, 0); \r\n", bufferSampleDecl, prepassSampler, screenUV) );
else else
meta->addStatement( new GenOp( " @ = tex2Dlod(@, float4(@,0,0));\r\n", bufferSampleDecl, prepassSampler, screenUV ) ); meta->addStatement( new GenOp( " @ = tex2Dlod(@, float4(@,0,0));\r\n", bufferSampleDecl, prepassSampler, screenUV ) );
meta->addStatement( new GenOp( " #else\r\n" ) ); meta->addStatement( new GenOp( " #else\r\n" ) );
if (GFX->getAdapterType() == OpenGL) if (GFX->getAdapterType() == OpenGL)
meta->addStatement( new GenOp( " @ = texture2D(@, @);\r\n", bufferSampleDecl, prepassSampler, screenUV) ); meta->addStatement( new GenOp( " @ = texture(@, @);\r\n", bufferSampleDecl, prepassSampler, screenUV) );
else else
meta->addStatement( new GenOp( " @ = tex2D(@, @);\r\n", bufferSampleDecl, prepassSampler, screenUV ) ); meta->addStatement( new GenOp( " @ = tex2D(@, @);\r\n", bufferSampleDecl, prepassSampler, screenUV ) );
meta->addStatement( new GenOp( " #endif\r\n\r\n" ) ); meta->addStatement( new GenOp( " #endif\r\n\r\n" ) );

View file

@ -384,6 +384,7 @@ void ParallaxFeatGLSL::setTexData( Material::StageData &stageDat,
GFXTextureObject *tex = stageDat.getTex( MFT_NormalMap ); GFXTextureObject *tex = stageDat.getTex( MFT_NormalMap );
if ( tex ) if ( tex )
{ {
passData.mSamplerNames[ texIndex ] = "bumpMap";
passData.mTexType[ texIndex ] = Material::Bump; passData.mTexType[ texIndex ] = Material::Bump;
passData.mTexSlot[ texIndex++ ].texObject = tex; passData.mTexSlot[ texIndex++ ].texObject = tex;
} }

View file

@ -1073,7 +1073,10 @@ void OverlayTexFeatGLSL::setTexData( Material::StageData &stageDat,
{ {
GFXTextureObject *tex = stageDat.getTex( MFT_OverlayMap ); GFXTextureObject *tex = stageDat.getTex( MFT_OverlayMap );
if ( tex ) if ( tex )
{
passData.mSamplerNames[ texIndex ] = "overlayMap";
passData.mTexSlot[ texIndex++ ].texObject = tex; passData.mTexSlot[ texIndex++ ].texObject = tex;
}
} }
@ -2383,7 +2386,7 @@ void GlowMaskGLSL::processPix( Vector<ShaderComponent*> &componentList,
// code above that doesn't contribute to the alpha mask. // code above that doesn't contribute to the alpha mask.
Var *color = (Var*)LangElement::find( "col" ); Var *color = (Var*)LangElement::find( "col" );
if ( color ) if ( color )
output = new GenOp( " @.rgb = 0;\r\n", color ); output = new GenOp( " @.rgb = vec3(0);\r\n", color );
} }

View file

@ -22,7 +22,7 @@
#include "core/strings/stringFunctions.h" #include "core/strings/stringFunctions.h"
#include "core/util/str.h" #include "core/util/str.h"
#include "gfx/gfxDevice.h"
#include "langElement.h" #include "langElement.h"
//************************************************************************** //**************************************************************************
@ -158,6 +158,9 @@ void Var::print( Stream &stream )
if( structName[0] != '\0' ) if( structName[0] != '\0' )
{ {
stream.write( dStrlen((char*)structName), structName ); stream.write( dStrlen((char*)structName), structName );
if(GFX->getAdapterType() == OpenGL)
stream.write( 1, "_" );
else
stream.write( 1, "." ); stream.write( 1, "." );
} }

View file

@ -30,15 +30,16 @@
#include "shaderGen/langElement.h" #include "shaderGen/langElement.h"
#include "shaderGen/shaderOp.h" #include "shaderGen/shaderOp.h"
#include "shaderGen/featureMgr.h" #include "shaderGen/featureMgr.h"
#include "shaderGen/shaderGen.h"
#include "core/module.h" #include "core/module.h"
namespace
MODULE_BEGIN( TerrainFeatHLSL ) {
void register_hlsl_shader_features_for_terrain(GFXAdapterType type)
MODULE_INIT_AFTER( ShaderGenFeatureMgr )
MODULE_INIT
{ {
if(type != Direct3D9 && type != Direct3D9_360)
return;
FEATUREMGR->registerFeature( MFT_TerrainBaseMap, new TerrainBaseMapFeatHLSL ); FEATUREMGR->registerFeature( MFT_TerrainBaseMap, new TerrainBaseMapFeatHLSL );
FEATUREMGR->registerFeature( MFT_TerrainParallaxMap, new NamedFeatureHLSL( "Terrain Parallax Texture" ) ); FEATUREMGR->registerFeature( MFT_TerrainParallaxMap, new NamedFeatureHLSL( "Terrain Parallax Texture" ) );
FEATUREMGR->registerFeature( MFT_TerrainDetailMap, new TerrainDetailMapFeatHLSL ); FEATUREMGR->registerFeature( MFT_TerrainDetailMap, new TerrainDetailMapFeatHLSL );
@ -49,6 +50,17 @@ MODULE_BEGIN( TerrainFeatHLSL )
FEATUREMGR->registerFeature( MFT_TerrainAdditive, new TerrainAdditiveFeatHLSL ); FEATUREMGR->registerFeature( MFT_TerrainAdditive, new TerrainAdditiveFeatHLSL );
} }
};
MODULE_BEGIN( TerrainFeatHLSL )
MODULE_INIT_AFTER( ShaderGen )
MODULE_INIT
{
SHADERGEN->getFeatureInitSignal().notify(&register_hlsl_shader_features_for_terrain);
}
MODULE_END; MODULE_END;

View file

@ -30,12 +30,14 @@
#include "sim/actionMap.h" #include "sim/actionMap.h"
class Win32WindowManager; class Win32WindowManager;
class GFXGLDevice;
/// Implementation of a window on Win32. /// Implementation of a window on Win32.
class Win32Window : public PlatformWindow class Win32Window : public PlatformWindow
{ {
friend class Win32WindowManager; friend class Win32WindowManager;
friend class GFXPCD3D9Device; friend class GFXPCD3D9Device;
friend class GFXGLDevice;
friend class GFXPCD3D9WindowTarget; friend class GFXPCD3D9WindowTarget;
friend class GFXD3D8WindowTarget; friend class GFXD3D8WindowTarget;

View file

@ -68,8 +68,8 @@ function onStart()
if ($platform $= "macos") if ($platform $= "macos")
$pref::Video::displayDevice = "OpenGL"; $pref::Video::displayDevice = "OpenGL";
else //else
$pref::Video::displayDevice = "D3D9"; //$pref::Video::displayDevice = "D3D9";
// Initialise stuff. // Initialise stuff.
exec("./scripts/client/core.cs"); exec("./scripts/client/core.cs");

View file

@ -68,8 +68,8 @@ function onStart()
if ($platform $= "macos") if ($platform $= "macos")
$pref::Video::displayDevice = "OpenGL"; $pref::Video::displayDevice = "OpenGL";
else //else
$pref::Video::displayDevice = "D3D9"; //$pref::Video::displayDevice = "D3D9";
// Initialise stuff. // Initialise stuff.
exec("./scripts/client/core.cs"); exec("./scripts/client/core.cs");

View file

@ -58,6 +58,12 @@ option(TORQUE_HIFI "HIFI? support" OFF)
mark_as_advanced(TORQUE_HIFI) mark_as_advanced(TORQUE_HIFI)
option(TORQUE_EXTENDED_MOVE "Extended move support" OFF) option(TORQUE_EXTENDED_MOVE "Extended move support" OFF)
mark_as_advanced(TORQUE_EXTENDED_MOVE) mark_as_advanced(TORQUE_EXTENDED_MOVE)
if(WIN32)
option(TORQUE_OPENGL "Allow OpenGL render" OFF)
#mark_as_advanced(TORQUE_OPENGL)
else()
set(TORQUE_OPENGL ON) # we need OpenGL to render on Linux/Mac
endif()
option(TORQUE_NAVIGATION "Enable Navigation module" OFF) option(TORQUE_NAVIGATION "Enable Navigation module" OFF)
#mark_as_advanced(TORQUE_NAVIGATION) #mark_as_advanced(TORQUE_NAVIGATION)
option(TORQUE_TESTING "Enable unit test module" OFF) option(TORQUE_TESTING "Enable unit test module" OFF)
@ -446,8 +452,12 @@ if( TORQUE_OPENGL )
if( TORQUE_OPENGL AND NOT TORQUE_DEDICATED ) if( TORQUE_OPENGL AND NOT TORQUE_DEDICATED )
addPath("${srcDir}/gfx/gl") addPath("${srcDir}/gfx/gl")
addPath("${srcDir}/gfx/gl/tGL") addPath("${srcDir}/gfx/gl/tGL")
addPath("${srcDir}/shaderGen/GLSL")
addPath("${srcDir}/terrain/glsl") addPath("${srcDir}/terrain/glsl")
addPath("${srcDir}/forest/glsl") addPath("${srcDir}/forest/glsl")
# glew
LIST(APPEND ${PROJECT_NAME}_files "${libDir}/glew/src/glew.c")
endif() endif()
if(WIN32 AND NOT TORQUE_SDL) if(WIN32 AND NOT TORQUE_SDL)
@ -506,6 +516,10 @@ if(WIN32)
set(TORQUE_EXTERNAL_LIBS "COMCTL32.LIB;COMDLG32.LIB;USER32.LIB;ADVAPI32.LIB;GDI32.LIB;WINMM.LIB;WSOCK32.LIB;vfw32.lib;Imm32.lib;d3d9.lib;d3dx9.lib;DxErr.lib;ole32.lib;shell32.lib;oleaut32.lib;version.lib" CACHE STRING "external libs to link against") set(TORQUE_EXTERNAL_LIBS "COMCTL32.LIB;COMDLG32.LIB;USER32.LIB;ADVAPI32.LIB;GDI32.LIB;WINMM.LIB;WSOCK32.LIB;vfw32.lib;Imm32.lib;d3d9.lib;d3dx9.lib;DxErr.lib;ole32.lib;shell32.lib;oleaut32.lib;version.lib" CACHE STRING "external libs to link against")
mark_as_advanced(TORQUE_EXTERNAL_LIBS) mark_as_advanced(TORQUE_EXTERNAL_LIBS)
addLib("${TORQUE_EXTERNAL_LIBS}") addLib("${TORQUE_EXTERNAL_LIBS}")
if(TORQUE_OPENGL)
addLib(OpenGL32.lib)
endif()
endif() endif()
if(UNIX) if(UNIX)
@ -544,6 +558,12 @@ if(UNIX)
addDef(LINUX) addDef(LINUX)
endif() endif()
if(TORQUE_OPENGL)
addDef(TORQUE_OPENGL)
if(WIN32)
addDef(GLEW_STATIC)
endif()
endif()
############################################################################### ###############################################################################
# Include Paths # Include Paths
############################################################################### ###############################################################################
@ -562,6 +582,9 @@ addInclude("${libDir}/libogg/include")
addInclude("${libDir}/opcode") addInclude("${libDir}/opcode")
addInclude("${libDir}/collada/include") addInclude("${libDir}/collada/include")
addInclude("${libDir}/collada/include/1.4") addInclude("${libDir}/collada/include/1.4")
if(TORQUE_OPENGL)
addInclude("${libDir}/glew/include")
endif()
# external things # external things
if(WIN32) if(WIN32)