Selaa lähdekoodia

Merge pull request #940 from BeamNG/add_opengl_support

Add/Activate OpenGL render.
LuisAntonRebollo 10 vuotta sitten
vanhempi
commit
98e3651db5
55 muutettua tiedostoa jossa 2959 lisäystä ja 804 poistoa
  1. 2 0
      Engine/source/gfx/gfxDevice.cpp
  2. 5 0
      Engine/source/gfx/gfxStateBlock.h
  3. 1 1
      Engine/source/gfx/gl/gfxGLAppleFence.h
  4. 7 7
      Engine/source/gfx/gl/gfxGLCardProfiler.cpp
  5. 289 0
      Engine/source/gfx/gl/gfxGLCircularVolatileBuffer.h
  6. 7 14
      Engine/source/gfx/gl/gfxGLCubemap.cpp
  7. 328 163
      Engine/source/gfx/gl/gfxGLDevice.cpp
  8. 41 16
      Engine/source/gfx/gl/gfxGLDevice.h
  9. 1 15
      Engine/source/gfx/gl/gfxGLDevice.mac.mm
  10. 133 0
      Engine/source/gfx/gl/gfxGLDeviceProfiler.cpp
  11. 110 47
      Engine/source/gfx/gl/gfxGLEnumTranslate.cpp
  12. 1 0
      Engine/source/gfx/gl/gfxGLEnumTranslate.h
  13. 9 3
      Engine/source/gfx/gl/gfxGLOcclusionQuery.cpp
  14. 96 25
      Engine/source/gfx/gl/gfxGLPrimitiveBuffer.cpp
  15. 8 3
      Engine/source/gfx/gl/gfxGLPrimitiveBuffer.h
  16. 173 12
      Engine/source/gfx/gl/gfxGLShader.cpp
  17. 2 1
      Engine/source/gfx/gl/gfxGLShader.h
  18. 43 60
      Engine/source/gfx/gl/gfxGLStateBlock.cpp
  19. 6 0
      Engine/source/gfx/gl/gfxGLStateBlock.h
  20. 133 0
      Engine/source/gfx/gl/gfxGLStateCache.h
  21. 107 38
      Engine/source/gfx/gl/gfxGLTextureManager.cpp
  22. 1 1
      Engine/source/gfx/gl/gfxGLTextureManager.h
  23. 136 39
      Engine/source/gfx/gl/gfxGLTextureObject.cpp
  24. 16 4
      Engine/source/gfx/gl/gfxGLTextureObject.h
  25. 92 137
      Engine/source/gfx/gl/gfxGLTextureTarget.cpp
  26. 3 3
      Engine/source/gfx/gl/gfxGLTextureTarget.h
  27. 144 11
      Engine/source/gfx/gl/gfxGLUtils.h
  28. 30 0
      Engine/source/gfx/gl/gfxGLVertexAttribLocation.h
  29. 106 74
      Engine/source/gfx/gl/gfxGLVertexBuffer.cpp
  30. 18 9
      Engine/source/gfx/gl/gfxGLVertexBuffer.h
  31. 212 0
      Engine/source/gfx/gl/gfxGLVertexDecl.cpp
  32. 39 0
      Engine/source/gfx/gl/gfxGLVertexDecl.h
  33. 86 12
      Engine/source/gfx/gl/gfxGLWindowTarget.cpp
  34. 5 0
      Engine/source/gfx/gl/gfxGLWindowTarget.h
  35. 225 0
      Engine/source/gfx/gl/sdl/gfxGLDevice.sdl.cpp
  36. 41 0
      Engine/source/gfx/gl/tGL/tGL.cpp
  37. 30 0
      Engine/source/gfx/gl/tGL/tGL.h
  38. 38 0
      Engine/source/gfx/gl/tGL/tWGL.h
  39. 38 0
      Engine/source/gfx/gl/tGL/tXGL.h
  40. 53 0
      Engine/source/gfx/gl/util/glFrameAllocatorLockableHelper.h
  41. 44 89
      Engine/source/gfx/gl/win32/gfxGLDevice.win.cpp
  42. 1 1
      Engine/source/lighting/advanced/advancedLightBufferConditioner.cpp
  43. 5 0
      Engine/source/lighting/advanced/advancedLightManager.cpp
  44. 7 4
      Engine/source/materials/materialManager.cpp
  45. 17 0
      Engine/source/platform/platformGL.h
  46. 11 0
      Engine/source/platformWin32/WinPlatformGL.cpp
  47. 2 2
      Engine/source/renderInstance/renderPrePassMgr.cpp
  48. 1 0
      Engine/source/shaderGen/GLSL/bumpGLSL.cpp
  49. 5 2
      Engine/source/shaderGen/GLSL/shaderFeatureGLSL.cpp
  50. 4 1
      Engine/source/shaderGen/langElement.cpp
  51. 18 6
      Engine/source/terrain/hlsl/terrFeatureHLSL.cpp
  52. 2 0
      Engine/source/windowManager/win32/win32Window.h
  53. 2 2
      Templates/Empty/game/core/main.cs
  54. 2 2
      Templates/Full/game/core/main.cs
  55. 23 0
      Tools/CMake/torque3d.cmake

+ 2 - 0
Engine/source/gfx/gfxDevice.cpp

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

+ 5 - 0
Engine/source/gfx/gfxStateBlock.h

@@ -89,6 +89,11 @@ struct GFXSamplerStateDesc
 
    /// Returns an modulate, clamp, and point sampled state.
    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.  

+ 1 - 1
Engine/source/gfx/gl/gfxGLAppleFence.h

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

+ 7 - 7
Engine/source/gfx/gl/gfxGLCardProfiler.cpp

@@ -76,30 +76,30 @@ void GFXGLCardProfiler::setupCardCapabilities()
    setCapability("maxTextureSize", maxTexSize);
 
    // 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);
 
    // 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);
    
-   bool suppBlit = gglHasExtension(GL_EXT_framebuffer_blit);
+   bool suppBlit = gglHasExtension(EXT_framebuffer_blit);
    setCapability("GL::suppRTBlit", suppBlit);
    
-   bool suppFloatTex = gglHasExtension(GL_ATI_texture_float);
+   bool suppFloatTex = gglHasExtension(ARB_texture_float);
    setCapability("GL::suppFloatTexture", suppFloatTex);
 
    // Check for anisotropic filtering support.
-   bool suppAnisotropic = gglHasExtension( GL_EXT_texture_filter_anisotropic );
+   bool suppAnisotropic = gglHasExtension( EXT_texture_filter_anisotropic );
    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
    // also check to see if the language version is high enough
    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);
    
-   bool suppAppleFence = gglHasExtension(GL_APPLE_fence);
+   bool suppAppleFence = gglHasExtension(APPLE_fence);
    setCapability("GL::APPLE::suppFence", suppAppleFence);
    
    // When enabled, call glGenerateMipmapEXT() to generate mipmaps instead of relying on GL_GENERATE_MIPMAP

+ 289 - 0
Engine/source/gfx/gl/gfxGLCircularVolatileBuffer.h

@@ -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

+ 7 - 14
Engine/source/gfx/gl/gfxGLCubemap.cpp

@@ -27,7 +27,7 @@
 #include "gfx/gl/gfxGLCubemap.h"
 #include "gfx/gfxTextureManager.h"
 #include "gfx/gfxCardProfile.h"
-#include "gfx/bitmap/DDSFile.h"
+#include "gfx/bitmap/ddsFile.h"
 
 
 GLenum GFXGLCubemap::faceList[6] = 
@@ -56,9 +56,9 @@ GFXGLCubemap::~GFXGLCubemap()
 
 void GFXGLCubemap::fillCubeTextures(GFXTexHandle* faces)
 {
-   glActiveTexture(GL_TEXTURE0);
+   PRESERVE_CUBEMAP_TEXTURE();
    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_MAG_FILTER, GL_NEAREST);
    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);
       delete[] buf;
    }
-   
-   glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
-   glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
 }
 
 void GFXGLCubemap::initStatic(GFXTexHandle* faces)
@@ -128,9 +125,9 @@ void GFXGLCubemap::initStatic( DDSFile *dds )
 
    glGenTextures(1, &mCubemap);
 
-   glActiveTexture(GL_TEXTURE0);
+   PRESERVE_CUBEMAP_TEXTURE();
    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_MAG_FILTER, GL_NEAREST);
    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], 
                               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)
@@ -173,6 +167,7 @@ void GFXGLCubemap::initDynamic(U32 texSize, GFXFormat faceFormat)
    mFaceFormat = faceFormat;
 
    glGenTextures(1, &mCubemap);
+   PRESERVE_CUBEMAP_TEXTURE();
    glBindTexture(GL_TEXTURE_CUBE_MAP, mCubemap);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_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, 
                      0, GFXGLTextureFormat[faceFormat], GFXGLTextureType[faceFormat], NULL);
    }
-   glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
 }
 
 void GFXGLCubemap::zombify()
@@ -223,6 +217,7 @@ void GFXGLCubemap::bind(U32 textureUnit) const
 {
    glActiveTexture(GL_TEXTURE0 + textureUnit);
    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();
    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_T, GFXGLTextureAddress[ssd.addressModeV]);
    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 )

+ 328 - 163
Engine/source/gfx/gl/gfxGLDevice.cpp

@@ -22,6 +22,7 @@
 
 #include "platform/platform.h"
 #include "gfx/gl/gfxGLDevice.h"
+#include "platform/platformGL.h"
 
 #include "gfx/gfxCubemap.h"
 #include "gfx/screenshot.h"
@@ -36,12 +37,15 @@
 #include "gfx/gl/gfxGLCubemap.h"
 #include "gfx/gl/gfxGLCardProfiler.h"
 #include "gfx/gl/gfxGLWindowTarget.h"
-#include "gfx/gl/ggl/ggl.h" 
 #include "platform/platformDlibrary.h"
 #include "gfx/gl/gfxGLShader.h"
 #include "gfx/primBuilder.h"
 #include "console/console.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); 
 
@@ -77,6 +81,23 @@ void loadGLExtensions(void *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()
 {  
    // 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(); 
    glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, (GLint*)&mMaxShaderTextures);
    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);
    
-   // Apple's drivers lie and claim that everything supports fragment shaders.  Conveniently they don't lie about the number
-   // of supported image units.  Checking for 16 or more image units ensures that we don't try and use pixel shaders on
-   // 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;
-      
+   // Setting mPixelShaderVersion to 3.0 will allow Advanced Lighting to run.   
+   mPixelShaderVersion = 3.0;
+
    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) :
    mAdapterIndex(adapterIndex),
-   mCurrentVB(NULL),
    mCurrentPB(NULL),
+   mDrawInstancesCount(0),
    m_mCurrentWorld(true),
    m_mCurrentView(true),
    mContext(NULL),
@@ -118,33 +166,74 @@ GFXGLDevice::GFXGLDevice(U32 adapterIndex) :
    mPixelShaderVersion(0.0f),
    mMaxShaderTextures(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();
 
    GFXGLEnumTranslate::init();
 
    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();
    gScreenShot = new ScreenShot();
 
    for(U32 i = 0; i < TEXTURE_STAGE_COUNT; i++)
       mActiveTextureType[i] = GL_ZERO;
+
+   mNumVertexStream = 2;
+
+   for(int i = 0; i < GS_COUNT; ++i)
+      mModelViewProjSC[i] = NULL;
+
+   mOpenglStateCache = new GFXGLStateCache;
 }
 
 GFXGLDevice::~GFXGLDevice()
 {
    mCurrentStateBlock = NULL;
+
+   for(int i = 0; i < VERTEX_STREAM_COUNT; ++i)      
+      mCurrentVB[i] = NULL;
    mCurrentPB = NULL;
-   mCurrentVB = NULL;
+   
    for(U32 i = 0; i < mVolatileVBs.size(); i++)
       mVolatileVBs[i] = NULL;
    for(U32 i = 0; i < mVolatilePBs.size(); i++)
       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;
    while(walk)
    {
@@ -156,15 +245,20 @@ GFXGLDevice::~GFXGLDevice()
       SAFE_DELETE( mCardProfiler );
 
    SAFE_DELETE( gScreenShot );
+
+   SAFE_DELETE( mOpenglStateCache );
 }
 
 void GFXGLDevice::zombify()
 {
    mTextureManager->zombify();
-   if(mCurrentVB)
-      mCurrentVB->finish();
+
+   for(int i = 0; i < VERTEX_STREAM_COUNT; ++i)   
+      if(mCurrentVB[i])
+         mCurrentVB[i]->finish();
    if(mCurrentPB)
-      mCurrentPB->finish();
+         mCurrentPB->finish();
+   
    //mVolatileVBs.clear();
    //mVolatilePBs.clear();
    GFXResource* walk = mResourceListHead;
@@ -183,10 +277,12 @@ void GFXGLDevice::resurrect()
       walk->resurrect();
       walk = walk->getNextResource();
    }
-   if(mCurrentVB)
-      mCurrentVB->prepare();
+   for(int i = 0; i < VERTEX_STREAM_COUNT; ++i)   
+      if(mCurrentVB[i])
+         mCurrentVB[i]->prepare();
    if(mCurrentPB)
       mCurrentPB->prepare();
+   
    mTextureManager->resurrect();
 }
 
@@ -244,20 +340,39 @@ GFXPrimitiveBuffer *GFXGLDevice::allocPrimitiveBuffer( U32 numIndices, U32 numPr
 
 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 ) 
-      mCurrentVB->finish();
+   //if(mCurrentVB[stream] != buffer)
+   {
+      // Reset the state the old VB required, then set the state the new VB requires.
+      if( mCurrentVB[stream] )
+      {     
+         mCurrentVB[stream]->finish();
+      }
+
+      mCurrentVB[stream] = static_cast<GFXGLVertexBuffer*>( buffer );
 
-   mCurrentVB = static_cast<GFXGLVertexBuffer*>( buffer );
-   if ( mCurrentVB )
-      mCurrentVB->prepare();
+      mNeedUpdateVertexAttrib = true;
+   }
 }
 
 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()
@@ -278,14 +393,24 @@ void GFXGLDevice::clear(U32 flags, ColorI color, F32 z, U32 stencil)
    // Make sure we have flushed our render target state.
    _updateRenderTargets();
    
-   bool zwrite = true;
+   bool writeAllColors = true;
+   bool zwrite = true;   
+   bool writeAllStencil = true;
+   const GFXStateBlockDesc *desc = NULL;
    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);
-   ColorF c = color;
+   glStencilMask(0xFFFFFFFF);
+   
+
+   ColorF c = color;   
    glClearColor(c.red, c.green, c.blue, c.alpha);
    glClearDepth(z);
    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;
 
    glClear(clearflags);
+
+   if(!writeAllColors)
+      glColorMask(desc->colorWriteRed, desc->colorWriteGreen, desc->colorWriteBlue, desc->colorWriteAlpha);
    
    if(!zwrite)
       glDepthMask(false);
+
+   if(!writeAllStencil)
+      glStencilMask(desc->stencilWriteMask);
 }
 
 // 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)
    {
@@ -332,6 +463,24 @@ GLsizei GFXGLDevice::primCountToIndexCount(GFXPrimitiveType primType, U32 primit
    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()
 {
    if( mStateDirty )
@@ -341,6 +490,25 @@ inline void GFXGLDevice::preDrawPrimitive()
    
    if(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)
@@ -352,16 +520,13 @@ inline void GFXGLDevice::postDrawPrimitive(U32 primitiveCount)
 void GFXGLDevice::drawPrimitive( GFXPrimitiveType primType, U32 vertexStart, U32 primitiveCount ) 
 {
    preDrawPrimitive();
-   
-   // There are some odd performance issues if a buffer is bound to GL_ELEMENT_ARRAY_BUFFER when glDrawArrays is called.  Unbinding the buffer
-   // improves performance by 10%.
-   if(mCurrentPB)
-      mCurrentPB->finish();
+  
+   vertexStart += mCurrentVB[0]->mBufferVertexOffset;
 
-   glDrawArrays(GFXGLPrimType[primType], vertexStart, primCountToIndexCount(primType, primitiveCount));
-   
-   if(mCurrentPB)
-      mCurrentPB->prepare();
+   if(mDrawInstancesCount)
+      glDrawArraysInstanced(GFXGLPrimType[primType], vertexStart, primCountToIndexCount(primType, primitiveCount), mDrawInstancesCount);
+   else
+      glDrawArrays(GFXGLPrimType[primType], vertexStart, primCountToIndexCount(primType, primitiveCount));   
 
    postDrawPrimitive(primitiveCount);
 }
@@ -379,7 +544,12 @@ void GFXGLDevice::drawIndexedPrimitive(   GFXPrimitiveType primType,
 
    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);
 }
@@ -393,53 +563,12 @@ void GFXGLDevice::setPB(GFXGLPrimitiveBuffer* pb)
 
 void GFXGLDevice::setLightInternal(U32 lightStage, const GFXLightInfo light, bool lightEnable)
 {
-   if(!lightEnable)
-   {
-      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);
+   // ONLY NEEDED ON FFP
 }
 
 void GFXGLDevice::setLightMaterialInternal(const GFXLightMaterial mat)
 {
-   // CodeReview - Setting these for front and back is unnecessary.  We should consider
-   // 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);
+   // ONLY NEEDED ON FFP
 }
 
 void GFXGLDevice::setGlobalAmbientInternal(ColorF color)
@@ -449,91 +578,40 @@ void GFXGLDevice::setGlobalAmbientInternal(ColorF color)
 
 void GFXGLDevice::setTextureInternal(U32 textureUnit, const GFXTextureObject*texture)
 {
-   const GFXGLTextureObject *tex = static_cast<const GFXGLTextureObject*>(texture);
-   glActiveTexture(GL_TEXTURE0 + textureUnit);
+   GFXGLTextureObject *tex = static_cast<GFXGLTextureObject*>(const_cast<GFXTextureObject*>(texture));
    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();
       tex->bind(textureUnit);
    } 
    else if(mActiveTextureType[textureUnit] != GL_ZERO)
    {
+      glActiveTexture(GL_TEXTURE0 + textureUnit);
       glBindTexture(mActiveTextureType[textureUnit], 0);
-      glDisable(mActiveTextureType[textureUnit]);
+      getOpenglCache()->setCacheBindedTex(textureUnit, mActiveTextureType[textureUnit], 0);
       mActiveTextureType[textureUnit] = GL_ZERO;
    }
-   
-   glActiveTexture(GL_TEXTURE0);
 }
 
 void GFXGLDevice::setCubemapInternal(U32 textureUnit, const GFXGLCubemap* texture)
 {
-   glActiveTexture(GL_TEXTURE0 + textureUnit);
    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;
       texture->bind(textureUnit);
    }
    else if(mActiveTextureType[textureUnit] != GL_ZERO)
    {
+      glActiveTexture(GL_TEXTURE0 + textureUnit);
       glBindTexture(mActiveTextureType[textureUnit], 0);
-      glDisable(mActiveTextureType[textureUnit]);
+      getOpenglCache()->setCacheBindedTex(textureUnit, mActiveTextureType[textureUnit], 0);
       mActiveTextureType[textureUnit] = GL_ZERO;
    }
-
-   glActiveTexture(GL_TEXTURE0);
 }
 
 void GFXGLDevice::setMatrix( GFXMatrixType mtype, const MatrixF &mat )
 {
-   MatrixF modelview;
-   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;
-   }
+   // ONLY NEEDED ON FFP
 }
 
 void GFXGLDevice::setClipRect( const RectI &inRect )
@@ -584,8 +662,8 @@ void GFXGLDevice::setClipRect( const RectI &inRect )
    setViewMatrix( mTempMatrix );
    setWorldMatrix( mTempMatrix );
 
-   // Set the viewport to the clip rect (with y flip)
-   RectI viewport(mClip.point.x, size.y - (mClip.point.y + mClip.extent.y), mClip.extent.x, mClip.extent.y);
+   // Set the viewport to the clip rect
+   RectI viewport(mClip.point.x, mClip.point.y, mClip.extent.x, mClip.extent.y);
    setViewport(viewport);
 }
 
@@ -637,11 +715,58 @@ GFXOcclusionQuery* GFXGLDevice::createOcclusionQuery()
 
 void GFXGLDevice::setupGenericShaders( GenericShaderType type ) 
 {
-   TORQUE_UNUSED(type);
-   // We have FF support, use that.
-   disableShaders();
-}
+   AssertFatal(type != GSTargetRestore, "");
+
+   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()
 {
    GFXGLShader* shader = new GFXGLShader();
@@ -651,19 +776,19 @@ GFXShader* GFXGLDevice::createShader()
 
 void GFXGLDevice::setShader( GFXShader *shader )
 {
+   if(mCurrentShader == shader)
+      return;
+
    if ( shader )
    {
       GFXGLShader *glShader = static_cast<GFXGLShader*>( shader );
       glShader->useProgram();
+      mCurrentShader = shader;
    }
    else
-      glUseProgram(0);
-}
-
-void GFXGLDevice::disableShaders()
-{
-   setShader(NULL);
-   setShaderConstBuffer( NULL );
+   {
+      setupGenericShaders();
+   }
 }
 
 void GFXGLDevice::setShaderConstBufferInternal(GFXShaderConstBuffer* buffer)
@@ -673,12 +798,20 @@ void GFXGLDevice::setShaderConstBufferInternal(GFXShaderConstBuffer* buffer)
 
 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 
 { 
-   return 1; 
+   return mMaxTRColors; 
 }
 
 void GFXGLDevice::_updateRenderTargets()
@@ -748,6 +881,38 @@ GFXFormat GFXGLDevice::selectSupportedFormat(   GFXTextureProfile* profile,
    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
 //

+ 41 - 16
Engine/source/gfx/gl/gfxGLDevice.h

@@ -28,9 +28,7 @@
 #include "gfx/gfxDevice.h"
 #include "gfx/gfxInit.h"
 
-#ifndef GL_GGL_H
-#include "gfx/gl/ggl/ggl.h"
-#endif
+#include "gfx/gl/tGL/tGL.h"
 
 #include "windowManager/platformWindow.h"
 #include "gfx/gfxFence.h"
@@ -41,6 +39,8 @@ class GFXGLVertexBuffer;
 class GFXGLPrimitiveBuffer;
 class GFXGLTextureTarget;
 class GFXGLCubemap;
+class GFXGLStateCache;
+class GFXGLVertexDecl;
 
 class GFXGLDevice : public GFXDevice
 {
@@ -59,12 +59,13 @@ public:
    virtual void deactivate() { }
    virtual GFXAdapterType getAdapterType() { return OpenGL; }
 
-   virtual void enterDebugEvent(ColorI color, const char *name) { }
-   virtual void leaveDebugEvent() { }
-   virtual void setDebugMarker(ColorI color, const char *name) { }
+   virtual void enterDebugEvent(ColorI color, const char *name);
+   virtual void leaveDebugEvent();
+   virtual void setDebugMarker(ColorI color, const char *name);
 
    virtual void enumerateVideoModes();
 
+   virtual U32 getTotalVideoMemory_GL_EXT();
    virtual U32 getTotalVideoMemory();
 
    virtual GFXCubemap * createCubemap();
@@ -134,7 +135,16 @@ public:
    
    ///
    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:   
    /// Called by GFXDevice to create a device specific stateblock
    virtual GFXStateBlockRef createStateBlockInternal(const GFXStateBlockDesc& desc);
@@ -169,16 +179,12 @@ protected:
    // NOTE: The GL device doesn't need a vertex declaration at
    // this time, but we need to return something to keep the system
    // from retrying to allocate one on every call.
-   virtual GFXVertexDecl* allocVertexDecl( const GFXVertexFormat *vertexFormat ) 
-   {
-      static GFXVertexDecl decl;
-      return &decl; 
-   }
+   virtual GFXVertexDecl* allocVertexDecl( const GFXVertexFormat *vertexFormat );
 
-   virtual void setVertexDecl( const GFXVertexDecl *decl ) { }
+   virtual void setVertexDecl( const GFXVertexDecl *decl );
 
    virtual void setVertexStream( U32 stream, GFXVertexBuffer *buffer );
-   virtual void setVertexStreamFrequency( U32 stream, U32 frequency );
+   virtual void setVertexStreamFrequency( U32 stream, U32 frequency );   
 
 private:
    typedef GFXDevice Parent;
@@ -193,8 +199,16 @@ private:
 
    U32 mAdapterIndex;
    
-   StrongRefPtr<GFXGLVertexBuffer> mCurrentVB;
+   StrongRefPtr<GFXGLVertexBuffer> mCurrentVB[VERTEX_STREAM_COUNT];
+   U32 mCurrentVB_Divisor[VERTEX_STREAM_COUNT];
+   bool mNeedUpdateVertexAttrib;
    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
    MatrixF m_mCurrentWorld;
@@ -205,11 +219,15 @@ private:
 
    F32 mPixelShaderVersion;
    
-   bool mSupportsAnisotropic;
+   bool mSupportsAnisotropic;   
+
+   U32 mNumVertexStream;
    
    U32 mMaxShaderTextures;
    U32 mMaxFFTextures;
 
+   U32 mMaxTRColors;
+
    RectI mClip;
    
    GFXGLStateBlockRef mCurrentGLStateBlock;
@@ -231,6 +249,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
    
    void setPB(GFXGLPrimitiveBuffer* pb); ///< Sets mCurrentPB
+
+   GFXGLStateCache *mOpenglStateCache;
+
+   GFXWindowTargetRef *mWindowRT;
+
+   bool mUseGlMap;
 };
 
+#define GFXGL static_cast<GFXGLDevice*>(GFXDevice::get())
 #endif

+ 1 - 15
Engine/source/gfx/gl/gfxGLDevice.mac.mm

@@ -294,21 +294,7 @@ GFXFence* GFXGLDevice::_createPlatformSpecificFence()
    return new GFXGLAppleFence(this);
 }
 
-void GFXGLWindowTarget::makeActive()
-{
-   // 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() 
+void GFXGLWindowTarget::_WindowPresent()
 {
    GFX->updateStates();
    mFullscreenContext ? [(NSOpenGLContext*)mFullscreenContext flushBuffer] : [(NSOpenGLContext*)mContext flushBuffer];

+ 133 - 0
Engine/source/gfx/gl/gfxGLDeviceProfiler.cpp

@@ -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

+ 110 - 47
Engine/source/gfx/gl/gfxGLEnumTranslate.cpp

@@ -34,6 +34,7 @@ GLenum GFXGLStencilOp[GFXStencilOp_COUNT];
 GLenum GFXGLTextureInternalFormat[GFXFormat_COUNT];
 GLenum GFXGLTextureFormat[GFXFormat_COUNT];
 GLenum GFXGLTextureType[GFXFormat_COUNT];
+GLint* GFXGLTextureSwizzle[GFXFormat_COUNT];
 GLenum GFXGLBufferType[GFXBufferType_COUNT];
 GLenum GFXGLCullMode[GFXCull_COUNT];
 GLenum GFXGLFillMode[GFXFill_COUNT];
@@ -118,54 +119,50 @@ void GFXGLEnumTranslate::init()
    
    
    // Texture formats
-   GFXGLTextureInternalFormat[GFXFormatA8] = GL_ALPHA8;
-   GFXGLTextureInternalFormat[GFXFormatL8] = GL_LUMINANCE8;
-   GFXGLTextureInternalFormat[GFXFormatR5G6B5] = GL_RGB5_A1;  // OpenGL has no R5G6B5 format.
+   for(int i = 0; i < GFXFormat_COUNT; ++i)
+   {
+      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[GFXFormatR5G5B5X1] = GL_RGB5_A1;
-   GFXGLTextureInternalFormat[GFXFormatL16] = GL_LUMINANCE16;
-   GFXGLTextureInternalFormat[GFXFormatR16F] = GL_ZERO;
-   GFXGLTextureInternalFormat[GFXFormatD16] = GL_DEPTH_COMPONENT;
+   GFXGLTextureInternalFormat[GFXFormatL16] = GL_R16;
+   GFXGLTextureInternalFormat[GFXFormatD16] = GL_DEPTH_COMPONENT16;
    GFXGLTextureInternalFormat[GFXFormatR8G8B8] = GL_RGB8;
    GFXGLTextureInternalFormat[GFXFormatR8G8B8A8] = GL_RGBA8;
    GFXGLTextureInternalFormat[GFXFormatR8G8B8X8] = GL_RGBA8;
-   GFXGLTextureInternalFormat[GFXFormatR32F] = GL_ZERO; 
-   GFXGLTextureInternalFormat[GFXFormatR16G16] = GL_RGBA16;
-   GFXGLTextureInternalFormat[GFXFormatR16G16F] = GL_ZERO;
-   GFXGLTextureInternalFormat[GFXFormatR10G10B10A2] = GL_ZERO;
+   GFXGLTextureInternalFormat[GFXFormatB8G8R8A8] = GL_RGBA8;
+   GFXGLTextureInternalFormat[GFXFormatR10G10B10A2] = GL_RGB10_A2;
    GFXGLTextureInternalFormat[GFXFormatD32] = GL_DEPTH_COMPONENT32;
-   GFXGLTextureInternalFormat[GFXFormatD24X8] = GL_DEPTH_COMPONENT24;
-   GFXGLTextureInternalFormat[GFXFormatD24S8] = GL_DEPTH_COMPONENT24;
-   GFXGLTextureInternalFormat[GFXFormatR16G16B16A16] = GL_ZERO;
-   GFXGLTextureInternalFormat[GFXFormatR16G16B16A16F] = GL_ZERO;
-   GFXGLTextureInternalFormat[GFXFormatR32G32B32A32F] = GL_ZERO;
+   GFXGLTextureInternalFormat[GFXFormatD24X8] = GL_DEPTH24_STENCIL8;
+   GFXGLTextureInternalFormat[GFXFormatD24S8] = GL_DEPTH24_STENCIL8;
+   GFXGLTextureInternalFormat[GFXFormatR16G16B16A16] = GL_RGBA16;
    GFXGLTextureInternalFormat[GFXFormatDXT1] = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
    GFXGLTextureInternalFormat[GFXFormatDXT2] = GL_ZERO;
    GFXGLTextureInternalFormat[GFXFormatDXT3] = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
    GFXGLTextureInternalFormat[GFXFormatDXT4] = GL_ZERO;
    GFXGLTextureInternalFormat[GFXFormatDXT5] = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
    
-   GFXGLTextureFormat[GFXFormatA8] = GL_ALPHA;
-   GFXGLTextureFormat[GFXFormatL8] = GL_LUMINANCE;
-   GFXGLTextureFormat[GFXFormatR5G6B5] = GL_RGBA;
+   GFXGLTextureFormat[GFXFormatA8] = GL_RED;
+   GFXGLTextureFormat[GFXFormatL8] = GL_RED;
    GFXGLTextureFormat[GFXFormatR5G5B5A1] = GL_RGBA;
    GFXGLTextureFormat[GFXFormatR5G5B5X1] = GL_RGBA;
-   GFXGLTextureFormat[GFXFormatL16] = GL_LUMINANCE;
-   GFXGLTextureFormat[GFXFormatR16F] = GL_ZERO;
+   GFXGLTextureFormat[GFXFormatL16] = GL_RED;
    GFXGLTextureFormat[GFXFormatD16] = GL_DEPTH_COMPONENT;
    GFXGLTextureFormat[GFXFormatR8G8B8] = GL_RGB;
-   GFXGLTextureFormat[GFXFormatR8G8B8A8] = GL_BGRA;
-   GFXGLTextureFormat[GFXFormatR8G8B8X8] = GL_BGRA;
-   GFXGLTextureFormat[GFXFormatR32F] = GL_RGBA;
-   GFXGLTextureFormat[GFXFormatR16G16] = GL_RGBA;
-   GFXGLTextureFormat[GFXFormatR16G16F] = GL_ZERO;
+   GFXGLTextureFormat[GFXFormatR8G8B8A8] = GL_RGBA;
+   GFXGLTextureFormat[GFXFormatR8G8B8X8] = GL_RGBA;
+   GFXGLTextureFormat[GFXFormatB8G8R8A8] = GL_BGRA;
    GFXGLTextureFormat[GFXFormatR10G10B10A2] = GL_RGBA;
    GFXGLTextureFormat[GFXFormatD32] = GL_DEPTH_COMPONENT;
-   GFXGLTextureFormat[GFXFormatD24X8] = GL_DEPTH_COMPONENT;
-   GFXGLTextureFormat[GFXFormatD24S8] = GL_DEPTH_COMPONENT;
+   GFXGLTextureFormat[GFXFormatD24X8] = GL_DEPTH_STENCIL;
+   GFXGLTextureFormat[GFXFormatD24S8] = GL_DEPTH_STENCIL;
    GFXGLTextureFormat[GFXFormatR16G16B16A16] = GL_RGBA;
-   GFXGLTextureFormat[GFXFormatR16G16B16A16F] = GL_RGBA;
-   GFXGLTextureFormat[GFXFormatR32G32B32A32F] = GL_RGBA;
    GFXGLTextureFormat[GFXFormatDXT1] = GL_RGBA;
    GFXGLTextureFormat[GFXFormatDXT2] = GL_ZERO;
    GFXGLTextureFormat[GFXFormatDXT3] = GL_RGBA;
@@ -174,36 +171,102 @@ void GFXGLEnumTranslate::init()
    
    GFXGLTextureType[GFXFormatA8] = GL_UNSIGNED_BYTE;
    GFXGLTextureType[GFXFormatL8] = GL_UNSIGNED_BYTE;
-   GFXGLTextureType[GFXFormatR5G6B5] = GL_UNSIGNED_BYTE;
-   GFXGLTextureType[GFXFormatR5G5B5A1] = GL_UNSIGNED_BYTE;
-   GFXGLTextureType[GFXFormatR5G5B5X1] = GL_UNSIGNED_BYTE;
+   GFXGLTextureType[GFXFormatR5G5B5A1] = GL_UNSIGNED_SHORT_5_5_5_1;
+   GFXGLTextureType[GFXFormatR5G5B5X1] = GL_UNSIGNED_SHORT_5_5_5_1;
    GFXGLTextureType[GFXFormatL16] = GL_UNSIGNED_SHORT;
-   GFXGLTextureType[GFXFormatR16F] = GL_ZERO;
    GFXGLTextureType[GFXFormatD16] = GL_UNSIGNED_SHORT;
    GFXGLTextureType[GFXFormatR8G8B8] = GL_UNSIGNED_BYTE;
    GFXGLTextureType[GFXFormatR8G8B8A8] = GL_UNSIGNED_BYTE;
    GFXGLTextureType[GFXFormatR8G8B8X8] = GL_UNSIGNED_BYTE;
-   GFXGLTextureType[GFXFormatR32F] = GL_FLOAT;
-   GFXGLTextureType[GFXFormatR16G16] = GL_UNSIGNED_SHORT;
-   GFXGLTextureType[GFXFormatR16G16F] = GL_FLOAT;
-   GFXGLTextureType[GFXFormatR10G10B10A2] = GL_UNSIGNED_SHORT;
-   GFXGLTextureType[GFXFormatD32] = GL_UNSIGNED_BYTE;
-   GFXGLTextureType[GFXFormatD24X8] = GL_UNSIGNED_BYTE;
-   GFXGLTextureType[GFXFormatD24S8] = GL_UNSIGNED_BYTE;
+   GFXGLTextureType[GFXFormatB8G8R8A8] = GL_UNSIGNED_BYTE;;
+   GFXGLTextureType[GFXFormatR10G10B10A2] = GL_UNSIGNED_INT_10_10_10_2;
+   GFXGLTextureType[GFXFormatD32] = GL_UNSIGNED_INT;
+   GFXGLTextureType[GFXFormatD24X8] = GL_UNSIGNED_INT_24_8;
+   GFXGLTextureType[GFXFormatD24S8] = GL_UNSIGNED_INT_24_8;
    GFXGLTextureType[GFXFormatR16G16B16A16] = GL_UNSIGNED_SHORT;
-   GFXGLTextureType[GFXFormatR16G16B16A16F] = GL_FLOAT;
-   GFXGLTextureType[GFXFormatR32G32B32A32F] = GL_FLOAT;
    GFXGLTextureType[GFXFormatDXT1] = GL_UNSIGNED_BYTE;
    GFXGLTextureType[GFXFormatDXT2] = GL_ZERO;
    GFXGLTextureType[GFXFormatDXT3] = GL_UNSIGNED_BYTE;
    GFXGLTextureType[GFXFormatDXT4] = GL_ZERO;
    GFXGLTextureType[GFXFormatDXT5] = GL_UNSIGNED_BYTE;
 
-   // Cull
-   GFXGLCullMode[GFXCullNone] = GL_BACK;
-   GFXGLCullMode[GFXCullCW] = GL_BACK;
-   GFXGLCullMode[GFXCullCCW] = GL_FRONT;
-   
+   static GLint Swizzle_GFXFormatA8[] = { GL_NONE, GL_NONE, GL_NONE, GL_RED };
+   static GLint Swizzle_GFXFormatL[] = { GL_RED, GL_RED, GL_RED, GL_ALPHA };
+   GFXGLTextureSwizzle[GFXFormatA8] = Swizzle_GFXFormatA8; // old GL_ALPHA8   
+   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
    GFXGLFillMode[GFXFillPoint] = GL_POINT;
    GFXGLFillMode[GFXFillWireframe] = GL_LINE;

+ 1 - 0
Engine/source/gfx/gl/gfxGLEnumTranslate.h

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

+ 9 - 3
Engine/source/gfx/gl/gfxGLOcclusionQuery.cpp

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

+ 96 - 25
Engine/source/gfx/gl/gfxGLPrimitiveBuffer.cpp

@@ -24,23 +24,40 @@
 #include "gfx/gl/gfxGLPrimitiveBuffer.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/gfxGLCircularVolatileBuffer.h"
+
+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) 
+   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();
-	// Generate a buffer and allocate the needed memory
-	glGenBuffers(1, &mBuffer);
-	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 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()
 {
 	// This is heavy handed, but it frees the buffer memory
-	glDeleteBuffersARB(1, &mBuffer);
+   if( mBufferType != GFXBufferTypeVolatile )
+	   glDeleteBuffers(1, &mBuffer);
    
    if( mZombieCache )
       delete [] mZombieCache;
@@ -48,44 +65,72 @@ GFXGLPrimitiveBuffer::~GFXGLPrimitiveBuffer()
 
 void GFXGLPrimitiveBuffer::lock(U32 indexStart, U32 indexEnd, void **indexPtr)
 {
-	// Preserve previous binding
-   PRESERVE_INDEX_BUFFER();
-   
-   // Bind ourselves and map
-	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mBuffer);
-   glBufferData(GL_ELEMENT_ARRAY_BUFFER, mIndexCount * sizeof(U16), NULL, GFXGLBufferType[mBufferType]);
-   
-   // Offset the buffer to indexStart
-	*indexPtr = (void*)((U8*)glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY) + (indexStart * sizeof(U16)));
+   if( mBufferType == GFXBufferTypeVolatile )
+   {
+      AssertFatal(indexStart == 0, "");
+      getCircularVolatileIndexBuffer()->lock( mIndexCount * sizeof(U16), 0, mBufferOffset, *indexPtr );
+   }
+   else
+   {
+      mFrameAllocator.lock( mIndexCount * sizeof(U16) );
+
+      *indexPtr = (void*)(mFrameAllocator.getlockedPtr() + (indexStart * sizeof(U16)) );
+   }
+
+   lockedIndexStart = indexStart;
+   lockedIndexEnd = indexEnd;
 }
 
 void GFXGLPrimitiveBuffer::unlock()
 {
-	// Preserve previous binding
-   PRESERVE_INDEX_BUFFER();
+   PROFILE_SCOPE(GFXGLPrimitiveBuffer_unlock);
+
+   if( mBufferType == GFXBufferTypeVolatile )
+   {
+      getCircularVolatileIndexBuffer()->unlock();
+   }
+   else
+   {   
+      U32 offset = lockedIndexStart * sizeof(U16);
+      U32 length = (lockedIndexEnd - lockedIndexStart) * sizeof(U16);
    
-   // Bind ourselves and unmap
-   glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mBuffer);
-	bool res = glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
-   AssertFatal(res, "GFXGLPrimitiveBuffer::unlock - shouldn't fail!");
+      // Preserve previous binding
+      PRESERVE_INDEX_BUFFER();
+   
+      // 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()
 {
 	// Bind
-	static_cast<GFXGLDevice*>(mDevice)->setPB(this);
-	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mBuffer);
+   GFXGLDevice* glDevice = static_cast<GFXGLDevice*>(mDevice);
+   glDevice->setPB(this);
+   glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mBuffer);
+   glDevice->getOpenglCache()->setCacheBinded(GL_ELEMENT_ARRAY_BUFFER, mBuffer);
 }
 
 void GFXGLPrimitiveBuffer::finish()
 {
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+   static_cast<GFXGLDevice*>(mDevice)->getOpenglCache()->setCacheBinded(GL_ELEMENT_ARRAY_BUFFER, 0);
 }
 
 GLvoid* GFXGLPrimitiveBuffer::getBuffer()
 {
 	// NULL specifies no offset into the hardware buffer
-	return (GLvoid*)NULL;
+   return (GLvoid*)mBufferOffset;
 }
 
 void GFXGLPrimitiveBuffer::zombify()
@@ -114,3 +159,29 @@ void GFXGLPrimitiveBuffer::resurrect()
    delete[] mZombieCache;
    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

+ 8 - 3
Engine/source/gfx/gl/gfxGLPrimitiveBuffer.h

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

+ 173 - 12
Engine/source/gfx/gl/gfxGLShader.cpp

@@ -22,6 +22,7 @@
 
 #include "platform/platform.h"
 #include "gfx/gl/gfxGLShader.h"
+#include "gfx/gl/gfxGLVertexAttribLocation.h"
 
 #include "core/frameAllocator.h"
 #include "core/stream/fileStream.h"
@@ -59,10 +60,11 @@ public:
    U32 mOffset;
    U32 mSize;  
    S32 mSamplerNum; 
+   bool mInstancingConstant;
 };
 
 GFXGLShaderConstHandle::GFXGLShaderConstHandle( GFXGLShader *shader )
- : mShader( shader ), mSamplerNum(-1)
+ : mShader( shader ), mSamplerNum(-1), mInstancingConstant(false)
 {
    mValid = false;
 }
@@ -98,7 +100,7 @@ static U32 shaderConstTypeSize(GFXShaderConstType type)
 }
 
 GFXGLShaderConstHandle::GFXGLShaderConstHandle( GFXGLShader *shader, const GFXShaderConstDesc &desc, GLuint loc, S32 samplerNum ) 
- : mShader(shader)
+ : mShader(shader), mInstancingConstant(false)
 {
    reinit(desc, loc, samplerNum);
 }
@@ -109,6 +111,7 @@ void GFXGLShaderConstHandle::reinit( const GFXShaderConstDesc& desc, GLuint loc,
    mLocation = loc;
    mSamplerNum = samplerNum;
    mOffset = 0;
+   mInstancingConstant = false;
    
    U32 elemSize = shaderConstTypeSize(mDesc.constType);
    AssertFatal(elemSize, "GFXGLShaderConst::GFXGLShaderConst - elemSize is 0");
@@ -156,8 +159,12 @@ void GFXGLShaderConstBuffer::internalSet(GFXShaderConstHandle* handle, const Con
 
    GFXGLShaderConstHandle* _glHandle = static_cast<GFXGLShaderConstHandle*>(handle);
    AssertFatal(mShader == _glHandle->mShader, "GFXGLShaderConstBuffer::set - Should only set handles which are owned by our shader");
-   
-   dMemcpy(mBuffer + _glHandle->mOffset, &param, sizeof(ConstType));
+   U8 *buf = mBuffer + _glHandle->mOffset;
+
+   if(_glHandle->mInstancingConstant)            
+      buf = mInstPtr + _glHandle->mOffset;
+
+   dMemcpy(buf, &param, sizeof(ConstType));
 }
 
 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);
    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());
    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);
    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)
    {
@@ -296,8 +305,18 @@ void GFXGLShaderConstBuffer::set(GFXShaderConstHandle* handle, const MatrixF& ma
       reinterpret_cast<F32*>(mBuffer + _glHandle->mOffset)[8] = mat[10];
       break;
    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));
       break;
+   }
    default:
       AssertFatal(false, "GFXGLShaderConstBuffer::set - Invalid matrix type");
       break;
@@ -310,8 +329,9 @@ void GFXGLShaderConstBuffer::set(GFXShaderConstHandle* handle, const MatrixF* ma
    AssertFatal(handle->isValid(), "GFXGLShaderConstBuffer::set - Handle is not valid!" );
 
    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) {
       case GFXSCT_Float4x4:
          dMemcpy(mBuffer + _glHandle->mOffset, (F32*)mat, _glHandle->getSize());
@@ -393,6 +413,9 @@ bool GFXGLShader::_init()
    macros.increment();
    macros.last().name = "TORQUE_SM";
    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.
    bool compiledVertexShader = true;
@@ -401,6 +424,8 @@ bool GFXGLShader::_init()
    // Compile the vertex and pixel shaders if specified.
    if(!mVertexFile.isEmpty())
       compiledVertexShader = initShader(mVertexFile, true, macros);
+
+   macros.last().name = "TORQUE_PIXEL_SHADER";
    if(!mPixelFile.isEmpty())
       compiledPixelShader = initShader(mPixelFile, false, macros);
       
@@ -408,6 +433,24 @@ bool GFXGLShader::_init()
    if(!compiledVertexShader || !compiledPixelShader)
       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!
    glLinkProgram( mProgram );
 
@@ -463,6 +506,10 @@ void GFXGLShader::initConstantDescs()
    glGetProgramiv(mProgram, GL_ACTIVE_UNIFORMS, &numUniforms);
    GLint maxNameLength;
    glGetProgramiv(mProgram, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxNameLength);
+
+   if(!maxNameLength)
+      return;
+
    FrameTemp<GLchar> uniformName(maxNameLength);
    
    for(U32 i = 0; i < numUniforms; i++)
@@ -546,17 +593,23 @@ void GFXGLShader::initHandles()
 
    // Loop through all ConstantDescriptions, 
    // 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++ )
    {
       GFXShaderConstDesc &desc = mConstants[i];            
 
       // 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);
-      S32 sampler = (desc.constType == GFXSCT_Sampler || desc.constType == GFXSCT_SamplerCube) ?
-         assignedSamplerNum++ : -1;
+      S32 sampler = -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() )
       {
          handle->value->reinit( desc, loc, sampler );         
@@ -599,10 +652,69 @@ void GFXGLShader::initHandles()
          // Set sampler number on our program.
          glUniform1i(handle->mLocation, handle->mSamplerNum);
          // 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);
+
+   //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)
@@ -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)
 {
    for(Vector<GFXGLShaderConstHandle*>::iterator i = mValidHandles.begin(); i != mValidHandles.end(); ++i)
    {
       GFXGLShaderConstHandle* handle = *i;
       AssertFatal(handle, "GFXGLShader::setConstantsFromBuffer - Null handle");
+
+      if(handle->mInstancingConstant)
+         continue;
       
       // Don't set if the value has not be changed.
       if(dMemcmp(mConstBuffer + handle->mOffset, buffer->mBuffer + handle->mOffset, handle->getSize()) == 0)
@@ -669,6 +795,9 @@ void GFXGLShader::setConstantsFromBuffer(GFXGLShaderConstBuffer* buffer)
          case GFXSCT_Float4x4:
             glUniformMatrix4fv(handle->mLocation, handle->mDesc.arraySize, true, (GLfloat*)(mConstBuffer + handle->mOffset));
             break;
+         default:
+            AssertFatal(0,"");
+            break;
       }
    }
 }
@@ -813,13 +942,34 @@ bool GFXGLShader::_loadShaderFromStream(  GLuint shader,
    Vector<U32> lengths;
    
    // 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 ) );
    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.
    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() );
       buffers.push_back( dStrdup( define.c_str() ) );
       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);
 
+#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.
    for ( U32 i=0; i < buffers.size(); i++ )
       dFree( buffers[i] );

+ 2 - 1
Engine/source/gfx/gl/gfxGLShader.h

@@ -25,7 +25,7 @@
 
 #include "core/util/refBase.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/tDictionary.h"
 
@@ -43,6 +43,7 @@ public:
    /// @name GFXShader interface
    /// @{
    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
    virtual const Vector<GFXShaderConstDesc>& getShaderConstDesc() const;

+ 43 - 60
Engine/source/gfx/gl/gfxGLStateBlock.cpp

@@ -25,12 +25,47 @@
 #include "gfx/gl/gfxGLEnumTranslate.h"
 #include "gfx/gl/gfxGLUtils.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) :
    mDesc(desc),
    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()
@@ -72,11 +107,6 @@ void GFXGLStateBlock::activate(const GFXGLStateBlock* oldState)
    if(STATE_CHANGE(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
    if(STATE_CHANGE(colorWriteRed) || STATE_CHANGE(colorWriteBlue) || STATE_CHANGE(colorWriteGreen) || STATE_CHANGE(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]);
    if(STATE_CHANGE(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))
       glPolygonMode(GL_FRONT_AND_BACK, GFXGLFillMode[mDesc.fillMode]);
@@ -131,57 +156,15 @@ void GFXGLStateBlock::activate(const GFXGLStateBlock* oldState)
 #undef TOGGLE_STATE
 #undef CHECK_TOGGLE_STATE
 
-   // TODO: states added for detail blend
-
-   // Non per object texture mode states
-   for (U32 i = 0; i < getMin(getOwningDevice()->getNumSamplers(), (U32) TEXTURE_STAGE_COUNT); i++)
+   //sampler objects
+   if( gglHasExtension(ARB_sampler_objects) )
    {
-      GFXGLTextureObject* tex = static_cast<GFXGLTextureObject*>(getOwningDevice()->getCurrentTexture(i));
-      const GFXSamplerStateDesc &ssd = mDesc.samplers[i];
-      bool updateTexParam = true;
-      glActiveTexture(GL_TEXTURE0 + i);
-      switch (ssd.textureColorOp)
+      for (U32 i = 0; i < getMin(getOwningDevice()->getNumSamplers(), (U32) TEXTURE_STAGE_COUNT); i++)
       {
-      case GFXTOPDisable :
-         if(!tex)
-            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;
+         if(!oldState || oldState->mSamplerObjects[i] != mSamplerObjects[i])
+		      glBindSampler(i, mSamplerObjects[i] );
       }
+   }	  
 
-#define SSF(state, enum, value, tex) if(!oldState || oldState->mDesc.samplers[i].state != mDesc.samplers[i].state) glTexParameteri(tex->getBinding(), enum, value)
-#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
+   // TODO: states added for detail blend   
 }

+ 6 - 0
Engine/source/gfx/gl/gfxGLStateBlock.h

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

+ 133 - 0
Engine/source/gfx/gl/gfxGLStateCache.h

@@ -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

+ 107 - 38
Engine/source/gfx/gl/gfxGLTextureManager.cpp

@@ -65,6 +65,7 @@ GFXTextureObject *GFXGLTextureManager::_createTextureObject(   U32 height,
       AssertFatal( dynamic_cast<GFXGLTextureObject*>( inTex ), "GFXGLTextureManager::_createTexture() - Bad inTex type!" );
       retTex = static_cast<GFXGLTextureObject*>( inTex );
       retTex->release();
+      retTex->reInit();
    }      
    else
    {
@@ -98,23 +99,20 @@ void GFXGLTextureManager::innerCreateTexture( GFXGLTextureObject *retTex,
    retTex->mIsZombie = 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)
       retTex->mIsNPoT2 = true;
    retTex->mBinding = binding;
    
    // Bind it
-   glActiveTexture(GL_TEXTURE0);
-   PRESERVE_2D_TEXTURE();
-   PRESERVE_3D_TEXTURE();
-   glBindTexture(binding, retTex->getHandle());
+   PRESERVE_TEXTURE(binding);
+   glBindTexture(retTex->getBinding(), retTex->getHandle());
    
    // Create it
-   // TODO: Reenable mipmaps on render targets when Apple fixes their drivers
-   if(forceMips && !retTex->mIsNPoT2)
+   // @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 && !isCompressedFormat(format) )
    {
-      glTexParameteri(binding, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
-      retTex->mMipLevels = 0;
+      retTex->mMipLevels = numMipLevels > 1 ? numMipLevels : 0;
    }
    else if(profile->testFlag(GFXTextureProfile::NoMipmap) || profile->testFlag(GFXTextureProfile::RenderTarget) || numMipLevels == 1 || retTex->mIsNPoT2)
    {
@@ -122,10 +120,11 @@ void GFXGLTextureManager::innerCreateTexture( GFXGLTextureObject *retTex,
    }
    else
    {
-      glTexParameteri(binding, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
-      retTex->mMipLevels = 0;
+      retTex->mMipLevels = numMipLevels;
    }
 
+   // @todo OPENGL - OpenGL ES2 not support mipmaps on NPOT textures
+#if 0
    if(!retTex->mIsNPoT2)
    {
       if(!isPow2(width))
@@ -135,23 +134,82 @@ void GFXGLTextureManager::innerCreateTexture( GFXGLTextureObject *retTex,
       if(depth && !isPow2(depth))
          depth = getNextPow2(depth);
    }
+#endif
    
    AssertFatal(GFXGLTextureInternalFormat[format] != GL_ZERO, "GFXGLTextureManager::innerCreateTexture - invalid internal format");
    AssertFatal(GFXGLTextureFormat[format] != GL_ZERO, "GFXGLTextureManager::innerCreateTexture - invalid format");
    AssertFatal(GFXGLTextureType[format] != GL_ZERO, "GFXGLTextureManager::innerCreateTexture - invalid type");
-   
-   if(binding != GL_TEXTURE_3D)
-      glTexImage2D(binding, 0, GFXGLTextureInternalFormat[format], 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);
+
+   //calculate num mipmaps
+   if(retTex->mMipLevels == 0)
+      retTex->mMipLevels = getMaxMipmaps(width, height, 1);
+
+    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
-   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_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(binding, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    if(binding == GL_TEXTURE_3D)
       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...)
    GLint texHeight, texWidth, texDepth = 0;
@@ -173,49 +231,60 @@ static void _fastTextureLoad(GFXGLTextureObject* texture, GBitmap* pDL)
    glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, texture->getBuffer());
    U32 bufSize = pDL->getWidth(0) * pDL->getHeight(0) * pDL->getBytesPerPixel();
    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)
+   {
+      FrameAllocatorMarker mem;
+      U8* pboMemory = (U8*)mem.alloc(bufSize);
       GFX->getDeviceSwizzle32()->ToBuffer(pboMemory, pDL->getBits(0), bufSize);
+      glBufferSubData(GL_PIXEL_UNPACK_BUFFER_ARB, 0, bufSize, pboMemory );
+   }
    else
-      dMemcpy(pboMemory, pDL->getBits(0), bufSize);
-   
-   glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER_ARB);
+   {
+      glBufferSubData(GL_PIXEL_UNPACK_BUFFER_ARB, 0, bufSize, pDL->getBits(0) );
+   }
    
-   glTexSubImage2D(texture->getBinding(), 0, 0, 0, pDL->getWidth(0), pDL->getHeight(0), GFXGLTextureFormat[pDL->getFormat()], GFXGLTextureType[pDL->getFormat()], NULL);
+   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);
+   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);
 }
 
 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)
 {
    GFXGLTextureObject *texture = static_cast<GFXGLTextureObject*>(aTexture);
    
-   AssertFatal(texture->getBinding() == GL_TEXTURE_2D, 
-      "GFXGLTextureManager::_loadTexture(GBitmap) - This method can only be used with 2D textures");
+   AssertFatal(texture->getBinding() == GL_TEXTURE_1D || texture->getBinding() == GL_TEXTURE_2D, 
+      "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;
          
    // No 24bit formats.
    if(pDL->getFormat() == GFXFormatR8G8B8)
       pDL->setFormat(GFXFormatR8G8B8A8);
    // Bind to edit
-   glActiveTexture(GL_TEXTURE0);
-   PRESERVE_2D_TEXTURE();
+   PRESERVE_TEXTURE(texture->getBinding());
    glBindTexture(texture->getBinding(), texture->getHandle());
-   
+
+   texture->mFormat = pDL->getFormat();
    if(pDL->getFormat() == GFXFormatR8G8B8A8 || pDL->getFormat() == GFXFormatR8G8B8X8)
       _fastTextureLoad(texture, pDL);
    else
       _slowTextureLoad(texture, pDL);
-   
-   glBindTexture(texture->getBinding(), 0);
+
+   if(texture->getMipLevels() != 1)
+      glGenerateMipmap(texture->getBinding());
    
    return true;
 }
@@ -231,15 +300,15 @@ bool GFXGLTextureManager::_loadTexture(GFXTextureObject *aTexture, DDSFile *dds)
    if(texture->getBinding() != GL_TEXTURE_2D)
       return false;
    
-   glActiveTexture(GL_TEXTURE0);
-   PRESERVE_2D_TEXTURE();
+   PRESERVE_TEXTURE(texture->getBinding());
    glBindTexture(texture->getBinding(), texture->getHandle());
+   texture->mFormat = dds->mFormat;
    U32 numMips = dds->mSurfaces[0]->mMips.size();
    if(GFX->getCardProfiler()->queryProfile("GL::Workaround::noManualMips"))
       numMips = 1;
    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"))
          {
@@ -266,7 +335,9 @@ bool GFXGLTextureManager::_loadTexture(GFXTextureObject *aTexture, DDSFile *dds)
       else
          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;
 }
@@ -278,11 +349,9 @@ bool GFXGLTextureManager::_loadTexture(GFXTextureObject *aTexture, void *raw)
    
    GFXGLTextureObject* texture = static_cast<GFXGLTextureObject*>(aTexture);
    
-   glActiveTexture(GL_TEXTURE0);
    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);
-   glBindTexture(GL_TEXTURE_3D, 0);
    
    return true;
 }

+ 1 - 1
Engine/source/gfx/gl/gfxGLTextureManager.h

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

+ 136 - 39
Engine/source/gfx/gl/gfxGLTextureObject.cpp

@@ -21,7 +21,7 @@
 //-----------------------------------------------------------------------------
 
 #include "console/console.h"
-#include "gfx/gl/ggl/ggl.h"
+#include "gfx/gl/tGL/tGL.h"
 #include "math/mRect.h"
 #include "gfx/gl/gfxGLTextureObject.h"
 #include "gfx/gfxDevice.h"
@@ -37,7 +37,10 @@ GFXGLTextureObject::GFXGLTextureObject(GFXDevice * aDevice, GFXTextureProfile *p
    mBytesPerTexel(4),
    mLockedRectRect(0, 0, 0, 0),
    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!");
    glGenTextures(1, &mHandle);
@@ -46,6 +49,7 @@ GFXGLTextureObject::GFXGLTextureObject(GFXDevice * aDevice, GFXTextureProfile *p
 
 GFXGLTextureObject::~GFXGLTextureObject() 
 { 
+   glDeleteTextures(1, &mHandle);
    glDeleteBuffers(1, &mBuffer);
    delete[] mZombieCache;
    kill();
@@ -70,12 +74,16 @@ GFXLockedRect* GFXGLTextureObject::lock(U32 mipLevel, RectI *inRect)
    }
    
    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.
-   glBufferData(GL_PIXEL_UNPACK_BUFFER_ARB, (mLockedRectRect.extent.x + 1) * (mLockedRectRect.extent.y + 1) * mBytesPerTexel, NULL, GL_STREAM_DRAW);
-   mLockedRect.bits = (U8*)glMapBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY);
-   glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
+   U32 size = (mLockedRectRect.extent.x + 1) * (mLockedRectRect.extent.y + 1) * mBytesPerTexel;
+   AssertFatal(!mFrameAllocatorMark && !mFrameAllocatorPtr, "");
+   mFrameAllocatorMark = FrameAllocator::getWaterMark();
+   mFrameAllocatorPtr = (U8*)FrameAllocator::alloc( size );
+   mLockedRect.bits = mFrameAllocatorPtr;
+#if TORQUE_DEBUG
+   mFrameAllocatorMarkGuard = FrameAllocator::getWaterMark();
+#endif
    
    if( !mLockedRect.bits )
       return NULL;
@@ -88,20 +96,27 @@ void GFXGLTextureObject::unlock(U32 mipLevel)
    if(!mLockedRect.bits)
       return;
 
-   glActiveTexture(GL_TEXTURE0);
-   U32 boundTexture;
-   glGetIntegerv(GL_TEXTURE_BINDING_2D, (GLint*)&boundTexture);
-
-   glBindTexture(GL_TEXTURE_2D, mHandle);
+   PRESERVE_TEXTURE(mBinding);
+   glBindTexture(mBinding, mHandle);
    glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, mBuffer);
-   glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER_ARB);
-   glTexSubImage2D(GL_TEXTURE_2D, mipLevel, mLockedRectRect.point.x, mLockedRectRect.point.y, 
-      mLockedRectRect.extent.x, mLockedRectRect.extent.y, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
+   glBufferData(GL_PIXEL_UNPACK_BUFFER_ARB, (mLockedRectRect.extent.x + 1) * (mLockedRectRect.extent.y + 1) * mBytesPerTexel, mFrameAllocatorPtr, GL_STREAM_DRAW);
+
+   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);
 
    mLockedRect.bits = NULL;
-
-   glBindTexture(GL_TEXTURE_2D, boundTexture);
+#if TORQUE_DEBUG
+   AssertFatal(mFrameAllocatorMarkGuard == FrameAllocator::getWaterMark(), "");
+#endif
+   FrameAllocator::setWaterMark(mFrameAllocatorMark);
+   mFrameAllocatorMark = 0;
+   mFrameAllocatorPtr = NULL;
 }
 
 void GFXGLTextureObject::release()
@@ -113,28 +128,91 @@ void GFXGLTextureObject::release()
    mBuffer = 0;
 }
 
+void GFXGLTextureObject::reInit()
+{
+   AssertFatal(!mHandle && !mBuffer,"Must release before reInit");
+   glGenTextures(1, &mHandle);
+   glGenBuffers(1, &mBuffer);
+}
+
 bool GFXGLTextureObject::copyToBmp(GBitmap * bmp)
 {
-   GLint oldTex;
-   glGetIntegerv(0x8069, &oldTex);
-   glBindTexture(GL_TEXTURE_2D, mHandle);
-   
-   GLint textureFormat = GFXGLTextureFormat[bmp->getFormat()];
-   // Don't swizzle outgoing textures.
-   if(textureFormat == GL_BGRA)
-      textureFormat = GL_RGBA;
+   if (!bmp)
+      return false;
+
+   // 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;
    
-   glGetTexImage(GL_TEXTURE_2D, 0, textureFormat, GL_UNSIGNED_BYTE, bmp->getWritableBits());
+   U32 srcPixelCount = mTextureSize.x * mTextureSize.y;
+   U8 *dest = bmp->getWritableBits();
+   U8 *orig = (U8*)mem.alloc(srcPixelCount * srcBytesPerPixel);
+
+   glGetTexImage(mBinding, 0, GFXGLTextureFormat[mFormat], GFXGLTextureType[mFormat], orig);
    
-   glBindTexture(GL_TEXTURE_2D, oldTex);
+   for(int i = 0; i < srcPixelCount; ++i)
+   {
+      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;
 }
 
-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);
    glBindTexture(mBinding, mHandle);
-   glEnable(mBinding);
+   GFXGL->getOpenglCache()->setCacheBindedTex(textureUnit, mBinding, mHandle);
+
+   if( gglHasExtension(ARB_sampler_objects) )
+	   return;
   
    GFXGLStateBlockRef sb = mGLDevice->getCurrentStateBlock();
    AssertFatal(sb, "GFXGLTextureObject::bind - No active stateblock!");
@@ -142,26 +220,41 @@ void GFXGLTextureObject::bind(U32 textureUnit) const
       return;
          
    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)
+
+   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);
 
-   glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, ssd.mipLODBias);
+   mSampler = ssd;
 }
 
 U8* GFXGLTextureObject::getTextureData()
 {
    U8* data = new U8[mTextureSize.x * mTextureSize.y * mBytesPerTexel];
-   glBindTexture(GL_TEXTURE_2D, mHandle);
-   glGetTexImage(GL_TEXTURE_2D, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, data);
+   PRESERVE_TEXTURE(mBinding);
+   glBindTexture(mBinding, mHandle);
+   glGetTexImage(mBinding, 0, GFXGLTextureFormat[mFormat], GFXGLTextureType[mFormat], data);
    return data;
 }
 
 void GFXGLTextureObject::copyIntoCache()
 {
+   PRESERVE_TEXTURE(mBinding);
    glBindTexture(mBinding, mHandle);
    U32 cacheSize = mTextureSize.x * mTextureSize.y;
    if(mBinding == GL_TEXTURE_3D)
@@ -171,7 +264,6 @@ void GFXGLTextureObject::copyIntoCache()
    mZombieCache = new U8[cacheSize];
    
    glGetTexImage(mBinding, 0, GFXGLTextureFormat[mFormat], GFXGLTextureType[mFormat], mZombieCache);
-   glBindTexture(mBinding, 0);
 }
 
 void GFXGLTextureObject::reloadFromCache()
@@ -187,8 +279,13 @@ void GFXGLTextureObject::reloadFromCache()
       return;
    }
    
+   PRESERVE_TEXTURE(mBinding);
    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)
       glGenerateMipmapEXT(mBinding);

+ 16 - 4
Engine/source/gfx/gl/gfxGLTextureObject.h

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

+ 92 - 137
Engine/source/gfx/gl/gfxGLTextureTarget.cpp

@@ -47,6 +47,8 @@ public:
    virtual U32 getDepth() = 0;
    virtual bool hasMips() = 0;
    virtual GLenum getBinding() = 0;
+   virtual GFXFormat getFormat() = 0;
+   virtual bool isCompatible(const GFXGLTextureObject* tex) = 0;
    
    U32 getMipLevel() { return mipLevel; }
    U32 getZOffset() { return zOffset; }
@@ -73,6 +75,14 @@ public:
    virtual U32 getDepth() { return mTex->getDepth(); }
    virtual bool hasMips() { return mTex->mMipLevels != 1; }
    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:
    StrongRefPtr<GFXGLTextureObject> mTex;
@@ -95,6 +105,13 @@ public:
    virtual U32 getDepth() { return 0; }
    virtual bool hasMips() { return mTex->getNumMipLevels() != 1; }
    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:
    StrongRefPtr<GFXGLCubemap> mTex;
@@ -102,7 +119,7 @@ private:
 };
 
 // Internal implementations
-class _GFXGLTextureTargetImpl
+class _GFXGLTextureTargetImpl // TODO OPENGL remove and implement on GFXGLTextureTarget
 {
 public:
    GFXGLTextureTarget* mTarget;
@@ -128,149 +145,88 @@ public:
    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)
 {
    mTarget = target;
-   glGenFramebuffersEXT(1, &mFramebuffer);
+   glGenFramebuffers(1, &mFramebuffer);
 }
 
 _GFXGLTextureTargetFBOImpl::~_GFXGLTextureTargetFBOImpl()
 {
-   glDeleteFramebuffersEXT(1, &mFramebuffer);
+   glDeleteFramebuffers(1, &mFramebuffer);
 }
 
 void _GFXGLTextureTargetFBOImpl::applyState()
 {   
    // REMINDER: When we implement MRT support, check against GFXGLDevice::getNumRenderTargets()
    
-   glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFramebuffer);
-   
-   _GFXGLTargetDesc* color0 = mTarget->getTargetDesc(GFXTextureTarget::Color0);
-   if(color0)
-   {
-      if(color0->getDepth() == 0)
-         glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, color0->getBinding(), color0->getHandle(), color0->getMipLevel());
+   PRESERVE_FRAMEBUFFER();
+   glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
+
+   bool hasColor = false;
+   for(int i = 0; i < GFXGL->getNumRenderTargets(); ++i)
+   {   
+      _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
-         glFramebufferTexture3DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, color0->getBinding(), color0->getHandle(), color0->getMipLevel(), color0->getZOffset());
-   }
-   else
-   {
-      // Clears the texture (note that the binding is irrelevent)
-      glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, 0, 0);
+      {
+         // Clears the texture (note that the binding is irrelevent)
+         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+i, GL_TEXTURE_2D, 0, 0);
+      }
    }
    
    _GFXGLTargetDesc* depthStecil = mTarget->getTargetDesc(GFXTextureTarget::DepthStencil);
    if(depthStecil)
    {
       // 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(depthStecil->getWidth() == color0->getWidth(), "GFXGLTextureTarget::applyState() - DepthStencil and Color0 targets MUST have the same width!");
-      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());
+      AssertFatal(hasColor, "GFXGLTextureTarget::applyState() - Cannot set DepthStencil target without Color0 target!");
+      glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthStecil->getBinding(), depthStecil->getHandle(), depthStecil->getMipLevel());
    }
    else
    {
       // 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()
 {
-   glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, mFramebuffer);
-   glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, mFramebuffer);
+   glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
+   GFXGL->getOpenglCache()->setCacheBinded(GL_FRAMEBUFFER, mFramebuffer);
 }
 
 void _GFXGLTextureTargetFBOImpl::finish()
 {
-   glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0);
-   glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 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.
-class _GFXGLTextureTargetAUXBufferImpl : public _GFXGLTextureTargetImpl
-{
-public:
-   _GFXGLTextureTargetAUXBufferImpl(GFXGLTextureTarget* target);
-   
-   virtual void applyState();
-   virtual void makeActive();
-   virtual void finish();
-};
-
-_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);
+   glBindFramebuffer(GL_FRAMEBUFFER, 0);
+   GFXGL->getOpenglCache()->setCacheBinded(GL_FRAMEBUFFER, 0);
+
+   for(int i = 0; i < GFXGL->getNumRenderTargets(); ++i)
+   {   
+      _GFXGLTargetDesc* color = mTarget->getTargetDesc( static_cast<GFXTextureTarget::RenderSlot>(GFXTextureTarget::Color0+i ) );
+      if(!color || !(color->hasMips()))
+         continue;
+   
+      // Generate mips if necessary
+      // Assumes a 2D texture.
+      PRESERVE_TEXTURE(color->getBinding());
+      glBindTexture(color->getBinding(), color->getHandle());
+      glGenerateMipmapEXT(GL_TEXTURE_2D);
+   }
 }
 
 // Actual GFXGLTextureTarget interface
-GFXGLTextureTarget::GFXGLTextureTarget()
+GFXGLTextureTarget::GFXGLTextureTarget() : mCopyFboSrc(0), mCopyFboDst(0)
 {
    for(U32 i=0; i<MaxRenderSlotId; i++)
       mTargets[i] = NULL;
@@ -278,7 +234,9 @@ GFXGLTextureTarget::GFXGLTextureTarget()
    GFXTextureManager::addEventDelegate( this, &GFXGLTextureTarget::_onTextureEvent );
 
    _impl = new _GFXGLTextureTargetFBOImpl(this);
-   _needsAux = false;
+    
+   glGenFramebuffers(1, &mCopyFboSrc);
+   glGenFramebuffers(1, &mCopyFboDst);
 }
 
 GFXGLTextureTarget::~GFXGLTextureTarget()
@@ -296,18 +254,20 @@ const Point2I GFXGLTextureTarget::getSize()
 
 GFXFormat GFXGLTextureTarget::getFormat()
 {
-   // TODO: Fix me!
+   if(mTargets[Color0].isValid())
+      return mTargets[Color0]->getFormat();
+
    return GFXFormatR8G8B8A8;
 }
 
 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)
-      _needsAux = true;
-   
-   if(slot == DepthStencil && tex != GFXTextureTarget::sDefaultDepthStencil)
-      _needsAux = false;
+   if( tex == GFXTextureTarget::sDefaultDepthStencil )
+      tex = GFXGL->getDefaultDepthTex();
+
+   _GFXGLTextureTargetDesc* mTex = static_cast<_GFXGLTextureTargetDesc*>(mTargets[slot].ptr());
+   if( (!tex && !mTex) || (mTex && mTex->getTextureObject() == tex) )
+      return;
    
    // Triggers an update when we next render
    invalidateState();
@@ -376,10 +336,7 @@ void GFXGLTextureTarget::applyState()
    // So we don't do this over and over again
    stateApplied();
    
-   // Ensure we have the proper implementation (consider changing to an enum?)
-   if(_needsAux && dynamic_cast<_GFXGLTextureTargetAUXBufferImpl*>(_impl.ptr()) == NULL)
-      _impl = new _GFXGLTextureTargetAUXBufferImpl(this);
-   else if(!_needsAux && dynamic_cast<_GFXGLTextureTargetFBOImpl*>(_impl.ptr()) == NULL)
+   if(_impl.isNull())
       _impl = new _GFXGLTextureTargetFBOImpl(this);
            
    _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");
    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();
    
-   GLuint dest;
-   GLuint src;
-   
-   glGenFramebuffersEXT(1, &dest);
-   glGenFramebuffersEXT(1, &src);
+   glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mCopyFboDst);
+   glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, glTexture->getHandle(), 0);
    
-   glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, dest);
-   glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, glTexture->getHandle(), 0);
+   glBindFramebuffer(GL_READ_FRAMEBUFFER, mCopyFboSrc);
+   glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,mTargets[Color0]->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(),
+   glBlitFramebuffer(0, 0, mTargets[Color0]->getWidth(), mTargets[Color0]->getHeight(),
       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);
 }

+ 3 - 3
Engine/source/gfx/gl/gfxGLTextureTarget.h

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

+ 144 - 11
Engine/source/gfx/gl/gfxGLUtils.h

@@ -25,12 +25,15 @@
 
 #include "core/util/preprocessorHelpers.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 GFXGLTextureFilter[minFilter];
+   return getMax( getBinLog2(depth), getMax(getBinLog2(width), getBinLog2(height)));
+}
 
+inline GLenum minificationFilter(U32 minFilter, U32 mipFilter, U32 /*mipLevels*/)
+{
    // the compiler should interpret this as array lookups
    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.
 /// This class determines the integer to preserve on construction and restores 
 /// it on destruction.
 class GFXGLPreserveInteger
 {
 public:
-   typedef void(*BindFn)(GLenum, GLuint);
+   typedef void(STDCALL *BindFn)(GLenum, GLuint);
 
    /// Preserve the integer.
    /// @param binding The binding which should be set on destruction.
@@ -73,7 +112,12 @@ public:
       mBinding(binding), mPreserved(0), mBinder(binder)
    {
       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.
@@ -88,24 +132,113 @@ private:
    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.
 #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.
 #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.
 #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.
 #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() \
-GFXGLPreserveInteger TORQUE_CONCAT(preserve_, __LINE__) (GL_READ_FRAMEBUFFER_EXT, GL_READ_FRAMEBUFFER_BINDING_EXT, glBindFramebufferEXT);\
-GFXGLPreserveInteger TORQUE_CONCAT(preserve2_, __LINE__) (GL_DRAW_FRAMEBUFFER_EXT, GL_DRAW_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, 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

+ 30 - 0
Engine/source/gfx/gl/gfxGLVertexAttribLocation.h

@@ -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

+ 106 - 74
Engine/source/gfx/gl/gfxGLVertexBuffer.cpp

@@ -26,7 +26,15 @@
 #include "gfx/gl/gfxGLDevice.h"
 #include "gfx/gl/gfxGLEnumTranslate.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, 
                                        U32 numVerts, 
@@ -34,113 +42,111 @@ GFXGLVertexBuffer::GFXGLVertexBuffer(  GFXDevice *device,
                                        U32 vertexSize, 
                                        GFXBufferType 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();
-	// Generate a buffer and allocate the needed memory.
-	glGenBuffers(1, &mBuffer);
-	glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
-	glBufferData(GL_ARRAY_BUFFER, numVerts * vertexSize, NULL, GFXGLBufferType[bufferType]);
-	glBindBuffer(GL_ARRAY_BUFFER, 0);
+   glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
+   glBufferData(GL_ARRAY_BUFFER, numVerts * vertexSize, NULL, GFXGLBufferType[bufferType]);
 }
 
 GFXGLVertexBuffer::~GFXGLVertexBuffer()
 {
 	// While heavy handed, this does delete the buffer and frees the associated memory.
-   glDeleteBuffers(1, &mBuffer);
-   
+   if( mBufferType != GFXBufferTypeVolatile )
+      glDeleteBuffers(1, &mBuffer);
+
    if( mZombieCache )
       delete [] mZombieCache;
 }
 
 void GFXGLVertexBuffer::lock( U32 vertexStart, U32 vertexEnd, void **vertexPtr )
 {
-   PRESERVE_VERTEX_BUFFER();
-	// Bind us, get a pointer into the buffer, then
-	// offset it by vertexStart so we act like the D3D layer.
-	glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
-   glBufferData(GL_ARRAY_BUFFER, mNumVerts * mVertexSize, NULL, GFXGLBufferType[mBufferType]);
-	*vertexPtr = (void*)((U8*)glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY) + (vertexStart * mVertexSize));
+   PROFILE_SCOPE(GFXGLVertexBuffer_lock);
+
+   if( mBufferType == GFXBufferTypeVolatile )
+   {
+      AssertFatal(vertexStart == 0, "");
+      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;
 	lockedVertexEnd   = vertexEnd;
 }
 
 void GFXGLVertexBuffer::unlock()
 {
-   PRESERVE_VERTEX_BUFFER();
-	// Unmap the buffer and bind 0 to GL_ARRAY_BUFFER
-   glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
-	bool res = glUnmapBuffer(GL_ARRAY_BUFFER);
-   AssertFatal(res, "GFXGLVertexBuffer::unlock - shouldn't fail!");
+   PROFILE_SCOPE(GFXGLVertexBuffer_unlock);
+
+   if( mBufferType == GFXBufferTypeVolatile )
+   {
+      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;
 	lockedVertexEnd   = 0;
+   lockedVertexPtr = NULL;
 }
 
 void GFXGLVertexBuffer::prepare()
 {
-	// Bind the buffer...
-	glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
-   U8* buffer = (U8*)getBuffer();
+   AssertFatal(0, "GFXGLVertexBuffer::prepare - use GFXGLVertexBuffer::prepare(U32 stream, U32 divisor)");
+}
 
-   // Loop thru the vertex format elements adding the array state...
-   U32 texCoordIndex = 0;
-   for ( U32 i=0; i < mVertexFormat.getElementCount(); i++ )
-   {
-      const GFXVertexElement &element = mVertexFormat.getElement( i );
-      
-      if ( element.isSemantic( GFXSemantic::POSITION ) )
-      {
-         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::prepare(U32 stream, U32 divisor)
+{
+   if( gglHasExtension(ARB_vertex_attrib_binding) )
+   {      
+      glBindVertexBuffer( stream, mBuffer, mBufferOffset, mVertexSize );
+      glVertexBindingDivisor( stream, divisor );
+      return;
    }
 }
 
 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()
@@ -175,3 +181,29 @@ void GFXGLVertexBuffer::resurrect()
    delete[] mZombieCache;
    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

+ 18 - 9
Engine/source/gfx/gl/gfxGLVertexBuffer.h

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

+ 212 - 0
Engine/source/gfx/gl/gfxGLVertexDecl.cpp

@@ -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, "");
+}

+ 39 - 0
Engine/source/gfx/gl/gfxGLVertexDecl.h

@@ -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

+ 86 - 12
Engine/source/gfx/gl/gfxGLWindowTarget.cpp

@@ -25,9 +25,19 @@
 #include "gfx/gl/gfxGLWindowTarget.h"
 #include "gfx/gl/gfxGLTextureObject.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)
       : GFXWindowTarget(win), mDevice(d), mContext(NULL), mFullscreenContext(NULL)
+      , mCopyFBO(0), mBackBufferFBO(0)
 {      
    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");
    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();
+
+   if(!mCopyFBO)
+   {
+      glGenFramebuffers(1, &mCopyFBO);
+   }
    
-   GLuint dest;
-   
-   glGenFramebuffersEXT(1, &dest);
-   
-   glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, dest);
-   glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, glTexture->getHandle(), 0);
+   glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mCopyFBO);
+   glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, glTexture->getHandle(), 0);
    
-   glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
+   glBindFramebuffer(GL_READ_FRAMEBUFFER, mBackBufferFBO);
    
-   glBlitFramebufferEXT(0, 0, getSize().x, getSize().y,
+   glBlitFramebuffer(0, 0, getSize().x, getSize().y,
       0, 0, glTexture->getWidth(), glTexture->getHeight(), GL_COLOR_BUFFER_BIT, GL_NEAREST);
-   
-   glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0);
-   
-   glDeleteFramebuffersEXT(1, &dest);
+}
+
+inline void GFXGLWindowTarget::_setupAttachments()
+{
+   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;
 }

+ 5 - 0
Engine/source/gfx/gl/gfxGLWindowTarget.h

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

+ 225 - 0
Engine/source/gfx/gl/sdl/gfxGLDevice.sdl.cpp

@@ -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

+ 41 - 0
Engine/source/gfx/gl/tGL/tGL.cpp

@@ -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)
+   {
+	
+   }
+}
+

+ 30 - 0
Engine/source/gfx/gl/tGL/tGL.h

@@ -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
+

+ 38 - 0
Engine/source/gfx/gl/tGL/tWGL.h

@@ -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
+

+ 38 - 0
Engine/source/gfx/gl/tGL/tXGL.h

@@ -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
+

+ 53 - 0
Engine/source/gfx/gl/util/glFrameAllocatorLockableHelper.h

@@ -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

+ 44 - 89
Engine/source/gfx/gl/gfxGLDevice.win.cpp → Engine/source/gfx/gl/win32/gfxGLDevice.win.cpp

@@ -35,7 +35,10 @@
 #include "gfx/GL/gfxGLCubemap.h"
 #include "gfx/GL/gfxGLCardProfiler.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()
 
@@ -105,7 +108,7 @@ void GFXGLDevice::enumerateAdapters( Vector<GFXAdapter*> &adapterList )
 
    // 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
+   CreatePixelFormat( &pfd, 32, 0, 0, false );
    if( !SetPixelFormat( tempDC, ChoosePixelFormat( tempDC, &pfd ), &pfd ) )
       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!");
    HWND hwnd = GETHWND(window);
 
+   mWindowRT = &static_cast<Win32Window*>(window)->mTarget;
+
    RECT rect;
    GetClientRect(hwnd, &rect);
 
@@ -252,14 +257,41 @@ void GFXGLDevice::init( const GFXVideoMode &mode, PlatformWindow *window )
 
    // 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
+   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 ) )
    {
       AssertFatal( false, "GFXGLDevice::init - cannot get the one and only pixel format we check for." );
    }
 
-   // Create a rendering context!
-   mContext = wglCreateContext( hdcGL );
+   int OGL_MAJOR = 3;
+   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 ) )
       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() 
 {
-   glGetError();
+   mCanCurrentlyRender = true;
    return true;
 }
 
 U32 GFXGLDevice::getTotalVideoMemory()
 {
-   // CodeReview [ags 12/21/07] Figure out how to do this.
-   return 0;
+   return getTotalVideoMemory_GL_EXT();
 }
 
 //------------------------------------------------------------------------------
 
 GFXWindowTarget *GFXGLDevice::allocWindowTarget( PlatformWindow *window )
 {
-   HDC hdcGL = GetDC(GETHWND(window));
-
-   if(!mContext)
-   {
-      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;
-   }
-
+   AssertFatal(!mContext, "");
+   
+   init(window->getVideoMode(), window);
    GFXGLWindowTarget *ggwt = new GFXGLWindowTarget(window, this);
    ggwt->registerResourceWithDevice(this);
-
-   // 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();
+   ggwt->mContext = mContext;
    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;
 }
 
-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()
 {
    return NULL;
@@ -382,16 +343,10 @@ GFXFence* GFXGLDevice::_createPlatformSpecificFence()
 
 
 //-----------------------------------------------------------------------------
-
-void GFXGLWindowTarget::makeActive()
-{
-}
-
-bool GFXGLWindowTarget::present()
+void GFXGLWindowTarget::_WindowPresent()
 {
    HWND hwnd = GETHWND(getWindow());
    SwapBuffers(GetDC(hwnd));
-   return true;
 }
 
 void GFXGLWindowTarget::_teardownCurrentMode()

+ 1 - 1
Engine/source/lighting/advanced/advancedLightBufferConditioner.cpp

@@ -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( "      0.0753f,    -0.2543f,   1.1892f\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" ) );
       }
       else

+ 5 - 0
Engine/source/lighting/advanced/advancedLightManager.cpp

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

+ 7 - 4
Engine/source/materials/materialManager.cpp

@@ -81,13 +81,13 @@ MaterialManager::MaterialManager()
    Con::addVariableNotify( "$pref::Video::defaultAnisotropy", callabck );
 
    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::setVariable( "$pref::Video::disablePixSpecular", false );
+   Con::setVariable( "$pref::Video::disablePixSpecular", "false" );
    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::setVariable( "$pref::Video::disableParallaxMapping", false );
+   Con::setVariable( "$pref::Video::disableParallaxMapping", "false" );
    Con::addVariableNotify( "$pref::Video::disableParallaxMapping", callabck2 );
 }
 
@@ -416,6 +416,9 @@ void MaterialManager::recalcFeaturesFromPrefs()
    mExclusionFeatures.setFeature(   MFT_NormalMap, 
                                     Con::getBoolVariable( "$pref::Video::disableNormalMapping", false ) );
 
+   mExclusionFeatures.setFeature(   MFT_SpecularMap,
+                                    Con::getBoolVariable( "$pref::Video::disablePixSpecular", false ) );
+
    mExclusionFeatures.setFeature(   MFT_PixSpecular,
                                     Con::getBoolVariable( "$pref::Video::disablePixSpecular", false ) );
 

+ 17 - 0
Engine/source/platform/platformGL.h

@@ -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

+ 11 - 0
Engine/source/platformWin32/WinPlatformGL.cpp

@@ -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

+ 2 - 2
Engine/source/renderInstance/renderPrePassMgr.cpp

@@ -834,12 +834,12 @@ Var* LinearEyeDepthConditioner::printMethodHeader( MethodType methodType, const
       // possible so that the shader compiler can optimize.
       meta->addStatement( new GenOp( "   #if TORQUE_SM >= 30\r\n" ) );
       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
          meta->addStatement( new GenOp( "      @ = tex2Dlod(@, float4(@,0,0));\r\n", bufferSampleDecl, prepassSampler, screenUV ) );
       meta->addStatement( new GenOp( "   #else\r\n" ) );
       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
          meta->addStatement( new GenOp( "      @ = tex2D(@, @);\r\n", bufferSampleDecl, prepassSampler, screenUV ) );
       meta->addStatement( new GenOp( "   #endif\r\n\r\n" ) );

+ 1 - 0
Engine/source/shaderGen/GLSL/bumpGLSL.cpp

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

+ 5 - 2
Engine/source/shaderGen/GLSL/shaderFeatureGLSL.cpp

@@ -1073,7 +1073,10 @@ void OverlayTexFeatGLSL::setTexData(   Material::StageData &stageDat,
 {
    GFXTextureObject *tex = stageDat.getTex( MFT_OverlayMap );
    if ( tex )
+   {
+      passData.mSamplerNames[ texIndex ] = "overlayMap";
       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.
    Var *color = (Var*)LangElement::find( "col" );
    if ( color )
-      output = new GenOp( "   @.rgb = 0;\r\n", color );
+      output = new GenOp( "   @.rgb = vec3(0);\r\n", color );
 }
 
 
@@ -2395,7 +2398,7 @@ void RenderTargetZeroGLSL::processPix( Vector<ShaderComponent*> &componentList,
 {
    // Do not actually assign zero, but instead a number so close to zero it may as well be zero.
    // This will prevent a divide by zero causing an FP special on float render targets
-   output = new GenOp( "   @;\r\n", assignColor( new GenOp( "0.00001" ), Material::None, NULL, mOutputTargetMask ) );
+   output = new GenOp( "   @;\r\n", assignColor( new GenOp( "vec4(0.00001)" ), Material::None, NULL, mOutputTargetMask ) );
 }
 
 

+ 4 - 1
Engine/source/shaderGen/langElement.cpp

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

+ 18 - 6
Engine/source/terrain/hlsl/terrFeatureHLSL.cpp

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

+ 2 - 0
Engine/source/windowManager/win32/win32Window.h

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

+ 2 - 2
Templates/Empty/game/core/main.cs

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

+ 2 - 2
Templates/Full/game/core/main.cs

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

+ 23 - 0
Tools/CMake/torque3d.cmake

@@ -58,6 +58,12 @@ option(TORQUE_HIFI "HIFI? support" OFF)
 mark_as_advanced(TORQUE_HIFI)
 option(TORQUE_EXTENDED_MOVE "Extended move support" OFF)
 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)
 #mark_as_advanced(TORQUE_NAVIGATION)
 option(TORQUE_TESTING "Enable unit test module" OFF)
@@ -446,8 +452,12 @@ if( TORQUE_OPENGL )
     if( TORQUE_OPENGL AND NOT TORQUE_DEDICATED )
         addPath("${srcDir}/gfx/gl")
         addPath("${srcDir}/gfx/gl/tGL")        
+    addPath("${srcDir}/shaderGen/GLSL")
         addPath("${srcDir}/terrain/glsl")
         addPath("${srcDir}/forest/glsl")    
+
+    # glew
+    LIST(APPEND ${PROJECT_NAME}_files "${libDir}/glew/src/glew.c")
     endif()
     
     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")
     mark_as_advanced(TORQUE_EXTERNAL_LIBS)
     addLib("${TORQUE_EXTERNAL_LIBS}")
+   
+   if(TORQUE_OPENGL)
+      addLib(OpenGL32.lib)
+   endif()
 endif()
 
 if(UNIX)
@@ -544,6 +558,12 @@ if(UNIX)
 	addDef(LINUX)	
 endif()
 
+if(TORQUE_OPENGL)
+	addDef(TORQUE_OPENGL)
+   if(WIN32)
+      addDef(GLEW_STATIC)
+    endif()
+endif()
 ###############################################################################
 # Include Paths
 ###############################################################################
@@ -562,6 +582,9 @@ addInclude("${libDir}/libogg/include")
 addInclude("${libDir}/opcode")
 addInclude("${libDir}/collada/include")
 addInclude("${libDir}/collada/include/1.4")
+if(TORQUE_OPENGL)
+	addInclude("${libDir}/glew/include")
+endif()
 
 # external things
 if(WIN32)