Torque3D Documentation / _generateds / gfxGLDevice.cpp

gfxGLDevice.cpp

Engine/source/gfx/gl/gfxGLDevice.cpp

More...

Classes:

Namespaces:

namespace

Public Functions

ConsoleFunction(cycleResources , void , 1 , 1 , "" )
glAmdDebugCallback(GLuint id, GLenum category, GLenum severity, GLsizei length, const GLchar * message, GLvoid * userParam)
glDebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar * message, const void * userParam)

Detailed Description

Public Variables

GFXGLRegisterDevice pGLRegisterDevice 

Public Functions

ConsoleFunction(cycleResources , void , 1 , 1 , "" )

glAmdDebugCallback(GLuint id, GLenum category, GLenum severity, GLsizei length, const GLchar * message, GLvoid * userParam)

glDebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar * message, const void * userParam)

loadGLCore()

loadGLExtensions(void * context)

  1
  2//-----------------------------------------------------------------------------
  3// Copyright (c) 2012 GarageGames, LLC
  4//
  5// Permission is hereby granted, free of charge, to any person obtaining a copy
  6// of this software and associated documentation files (the "Software"), to
  7// deal in the Software without restriction, including without limitation the
  8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  9// sell copies of the Software, and to permit persons to whom the Software is
 10// furnished to do so, subject to the following conditions:
 11//
 12// The above copyright notice and this permission notice shall be included in
 13// all copies or substantial portions of the Software.
 14//
 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 21// IN THE SOFTWARE.
 22//-----------------------------------------------------------------------------
 23
 24#include "platform/platform.h"
 25#include "gfx/gl/gfxGLDevice.h"
 26#include "platform/platformGL.h"
 27
 28#include "gfx/gfxCubemap.h"
 29#include "gfx/screenshot.h"
 30#include "gfx/gfxDrawUtil.h"
 31
 32#include "gfx/gl/gfxGLEnumTranslate.h"
 33#include "gfx/gl/gfxGLVertexBuffer.h"
 34#include "gfx/gl/gfxGLPrimitiveBuffer.h"
 35#include "gfx/gl/gfxGLTextureTarget.h"
 36#include "gfx/gl/gfxGLTextureManager.h"
 37#include "gfx/gl/gfxGLTextureObject.h"
 38#include "gfx/gl/gfxGLCubemap.h"
 39#include "gfx/gl/gfxGLCardProfiler.h"
 40#include "gfx/gl/gfxGLWindowTarget.h"
 41#include "platform/platformDlibrary.h"
 42#include "gfx/gl/gfxGLShader.h"
 43#include "gfx/primBuilder.h"
 44#include "console/console.h"
 45#include "gfx/gl/gfxGLOcclusionQuery.h"
 46#include "materials/shaderData.h"
 47#include "gfx/gl/gfxGLStateCache.h"
 48#include "gfx/gl/gfxGLVertexAttribLocation.h"
 49#include "gfx/gl/gfxGLVertexDecl.h"
 50
 51GFXAdapter::CreateDeviceInstanceDelegate GFXGLDevice::mCreateDeviceInstance(GFXGLDevice::createInstance); 
 52
 53GFXDevice *GFXGLDevice::createInstance( U32 adapterIndex )
 54{
 55   return new GFXGLDevice(adapterIndex);
 56}
 57
 58namespace GL
 59{
 60   extern void gglPerformBinds();
 61   extern void gglPerformExtensionBinds(void *context);
 62}
 63
 64void loadGLCore()
 65{
 66   static bool coreLoaded = false; // Guess what this is for.
 67   if(coreLoaded)
 68      return;
 69   coreLoaded = true;
 70   
 71   // Make sure we've got our GL bindings.
 72   GL::gglPerformBinds();
 73}
 74
 75void loadGLExtensions(void *context)
 76{
 77   static bool extensionsLoaded = false;
 78   if(extensionsLoaded)
 79      return;
 80   extensionsLoaded = true;
 81   
 82   GL::gglPerformExtensionBinds(context);
 83}
 84
 85void STDCALL glDebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, 
 86   const GLchar *message, const void *userParam)
 87{
 88    // JTH [11/24/2016]: This is a temporary fix so that we do not get spammed for redundant fbo changes.
 89    // This only happens on Intel cards. This should be looked into sometime in the near future.
 90    if (dStrStartsWith(message, "API_ID_REDUNDANT_FBO"))
 91        return;
 92    if (severity == GL_DEBUG_SEVERITY_HIGH)
 93        Con::errorf("OPENGL: %s", message);
 94    else if (severity == GL_DEBUG_SEVERITY_MEDIUM)
 95        Con::warnf("OPENGL: %s", message);
 96    else if (severity == GL_DEBUG_SEVERITY_LOW)
 97        Con::printf("OPENGL: %s", message);
 98}
 99
100void STDCALL glAmdDebugCallback(GLuint id, GLenum category, GLenum severity, GLsizei length,
101    const GLchar* message, GLvoid* userParam)
102{
103    if (severity == GL_DEBUG_SEVERITY_HIGH)
104        Con::errorf("AMDOPENGL: %s", message);
105    else if (severity == GL_DEBUG_SEVERITY_MEDIUM)
106        Con::warnf("AMDOPENGL: %s", message);
107    else if (severity == GL_DEBUG_SEVERITY_LOW)
108        Con::printf("AMDOPENGL: %s", message);
109}
110
111void GFXGLDevice::initGLState()
112{  
113   // We don't currently need to sync device state with a known good place because we are
114   // going to set everything in GFXGLStateBlock, but if we change our GFXGLStateBlock strategy, this may
115   // need to happen.
116   
117   // Deal with the card profiler here when we know we have a valid context.
118   mCardProfiler = new GFXGLCardProfiler();
119   mCardProfiler->init(); 
120   glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, (GLint*)&mMaxShaderTextures);
121   // JTH: Needs removed, ffp
122   //glGetIntegerv(GL_MAX_TEXTURE_UNITS, (GLint*)&mMaxFFTextures);
123   glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, (GLint*)&mMaxTRColors);
124   mMaxTRColors = getMin( mMaxTRColors, (U32)(GFXTextureTarget::MaxRenderSlotId-1) );
125   
126   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
127   
128   // [JTH 5/6/2016] GLSL 1.50 is really SM 4.0
129   // Setting mPixelShaderVersion to 3.0 will allow Advanced Lighting to run.   
130   mPixelShaderVersion = 3.0;
131
132   // Set capability extensions.
133   mCapabilities.anisotropicFiltering = mCardProfiler->queryProfile("GL_EXT_texture_filter_anisotropic");
134   mCapabilities.bufferStorage = mCardProfiler->queryProfile("GL_ARB_buffer_storage");
135   mCapabilities.shaderModel5 = mCardProfiler->queryProfile("GL_ARB_gpu_shader5");
136   mCapabilities.textureStorage = mCardProfiler->queryProfile("GL_ARB_texture_storage");
137   mCapabilities.samplerObjects = mCardProfiler->queryProfile("GL_ARB_sampler_objects");
138   mCapabilities.copyImage = mCardProfiler->queryProfile("GL_ARB_copy_image");
139   mCapabilities.vertexAttributeBinding = mCardProfiler->queryProfile("GL_ARB_vertex_attrib_binding");
140
141   String vendorStr = (const char*)glGetString( GL_VENDOR );
142   if( vendorStr.find("NVIDIA", 0, String::NoCase | String::Left) != String::NPos)
143      mUseGlMap = false;
144   
145   // Workaround for all Mac's, has a problem using glMap* with volatile buffers
146#ifdef TORQUE_OS_MAC
147   mUseGlMap = false;
148#endif
149
150#if TORQUE_DEBUG
151   if( gglHasExtension(ARB_debug_output) )
152   {
153      glEnable(GL_DEBUG_OUTPUT);
154      glDebugMessageCallbackARB(glDebugCallback, NULL);
155      glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
156      GLuint unusedIds = 0;
157      glDebugMessageControlARB(GL_DONT_CARE,
158            GL_DONT_CARE,
159            GL_DONT_CARE,
160            0,
161            &unusedIds,
162            GL_TRUE);
163   }
164   else if(gglHasExtension(AMD_debug_output))
165   {
166      glEnable(GL_DEBUG_OUTPUT);
167      glDebugMessageCallbackAMD(glAmdDebugCallback, NULL);      
168      //glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
169      GLuint unusedIds = 0;
170      glDebugMessageEnableAMD(GL_DONT_CARE, GL_DONT_CARE, 0,&unusedIds, GL_TRUE);
171   }
172#endif
173
174   PlatformGL::setVSync(smDisableVSync ? 0 : 1);
175
176   //OpenGL 3 need a binded VAO for render
177   GLuint vao;
178   glGenVertexArrays(1, &vao);
179   glBindVertexArray(vao);
180}
181
182GFXGLDevice::GFXGLDevice(U32 adapterIndex) :
183   mAdapterIndex(adapterIndex),
184   mNeedUpdateVertexAttrib(false),
185   mCurrentPB(NULL),
186   mDrawInstancesCount(0),
187   mCurrentShader( NULL ),
188   m_mCurrentWorld(true),
189   m_mCurrentView(true),
190   mContext(NULL),
191   mPixelFormat(NULL),
192   mPixelShaderVersion(0.0f),
193   mMaxShaderTextures(2),
194   mMaxFFTextures(2),
195   mMaxTRColors(1),
196   mClip(0, 0, 0, 0),
197   mWindowRT(NULL),
198   mUseGlMap(true)
199{
200   for(int i = 0; i < VERTEX_STREAM_COUNT; ++i)
201   {
202      mCurrentVB[i] = NULL;
203      mCurrentVB_Divisor[i] = 0;
204   }
205
206   // Initiailize capabilities to false.
207   memset(&mCapabilities, 0, sizeof(GLCapabilities));
208
209   loadGLCore();
210
211   GFXGLEnumTranslate::init();
212
213   GFXVertexColor::setSwizzle( &Swizzles::rgba );
214
215   // OpenGL have native RGB, no need swizzle
216   mDeviceSwizzle32 = &Swizzles::rgba;
217   mDeviceSwizzle24 = &Swizzles::rgb;
218
219   mTextureManager = new GFXGLTextureManager();
220   gScreenShot = new ScreenShot();
221
222   for(U32 i = 0; i < TEXTURE_STAGE_COUNT; i++)
223      mActiveTextureType[i] = GL_ZERO;
224
225   mNumVertexStream = 2;
226
227   for(int i = 0; i < GS_COUNT; ++i)
228      mModelViewProjSC[i] = NULL;
229
230   mOpenglStateCache = new GFXGLStateCache;
231}
232
233GFXGLDevice::~GFXGLDevice()
234{
235   mCurrentStateBlock = NULL;
236
237   for(int i = 0; i < VERTEX_STREAM_COUNT; ++i)      
238      mCurrentVB[i] = NULL;
239   mCurrentPB = NULL;
240   
241   for(U32 i = 0; i < mVolatileVBs.size(); i++)
242      mVolatileVBs[i] = NULL;
243   for(U32 i = 0; i < mVolatilePBs.size(); i++)
244      mVolatilePBs[i] = NULL;
245
246   // Clear out our current texture references
247   for (U32 i = 0; i < TEXTURE_STAGE_COUNT; i++)
248   {
249      mCurrentTexture[i] = NULL;
250      mNewTexture[i] = NULL;
251      mCurrentCubemap[i] = NULL;
252      mNewCubemap[i] = NULL;
253   }
254
255   mRTStack.clear();
256   mCurrentRT = NULL;
257
258   if( mTextureManager )
259   {
260      mTextureManager->zombify();
261      mTextureManager->kill();
262   }
263
264   GFXResource* walk = mResourceListHead;
265   while(walk)
266   {
267      walk->zombify();
268      walk = walk->getNextResource();
269   }
270      
271   if( mCardProfiler )
272      SAFE_DELETE( mCardProfiler );
273
274   SAFE_DELETE( gScreenShot );
275
276   SAFE_DELETE( mOpenglStateCache );
277}
278
279void GFXGLDevice::zombify()
280{
281   mTextureManager->zombify();
282
283   for(int i = 0; i < VERTEX_STREAM_COUNT; ++i)   
284      if(mCurrentVB[i])
285         mCurrentVB[i]->finish();
286   if(mCurrentPB)
287         mCurrentPB->finish();
288   
289   //mVolatileVBs.clear();
290   //mVolatilePBs.clear();
291   GFXResource* walk = mResourceListHead;
292   while(walk)
293   {
294      walk->zombify();
295      walk = walk->getNextResource();
296   }
297}
298
299void GFXGLDevice::resurrect()
300{
301   GFXResource* walk = mResourceListHead;
302   while(walk)
303   {
304      walk->resurrect();
305      walk = walk->getNextResource();
306   }
307   for(int i = 0; i < VERTEX_STREAM_COUNT; ++i)   
308      if(mCurrentVB[i])
309         mCurrentVB[i]->prepare();
310   if(mCurrentPB)
311      mCurrentPB->prepare();
312   
313   mTextureManager->resurrect();
314}
315
316GFXVertexBuffer* GFXGLDevice::findVolatileVBO(U32 numVerts, const GFXVertexFormat *vertexFormat, U32 vertSize)
317{
318   PROFILE_SCOPE(GFXGLDevice_findVBPool);
319   for(U32 i = 0; i < mVolatileVBs.size(); i++)
320      if (  mVolatileVBs[i]->mNumVerts >= numVerts &&
321            mVolatileVBs[i]->mVertexFormat.isEqual( *vertexFormat ) &&
322            mVolatileVBs[i]->mVertexSize == vertSize &&
323            mVolatileVBs[i]->getRefCount() == 1 )
324         return mVolatileVBs[i];
325
326   // No existing VB, so create one
327   PROFILE_SCOPE(GFXGLDevice_createVBPool);
328   StrongRefPtr<GFXGLVertexBuffer> buf(new GFXGLVertexBuffer(GFX, numVerts, vertexFormat, vertSize, GFXBufferTypeVolatile));
329   buf->registerResourceWithDevice(this);
330   mVolatileVBs.push_back(buf);
331   return buf.getPointer();
332}
333
334GFXPrimitiveBuffer* GFXGLDevice::findVolatilePBO(U32 numIndices, U32 numPrimitives)
335{
336   for(U32 i = 0; i < mVolatilePBs.size(); i++)
337      if((mVolatilePBs[i]->mIndexCount >= numIndices) && (mVolatilePBs[i]->getRefCount() == 1))
338         return mVolatilePBs[i];
339   
340   // No existing PB, so create one
341   StrongRefPtr<GFXGLPrimitiveBuffer> buf(new GFXGLPrimitiveBuffer(GFX, numIndices, numPrimitives, GFXBufferTypeVolatile));
342   buf->registerResourceWithDevice(this);
343   mVolatilePBs.push_back(buf);
344   return buf.getPointer();
345}
346
347GFXVertexBuffer *GFXGLDevice::allocVertexBuffer(   U32 numVerts, 
348                                                   const GFXVertexFormat *vertexFormat, 
349                                                   U32 vertSize, 
350                                                   GFXBufferType bufferType,
351                                                   void* data )  
352{
353   PROFILE_SCOPE(GFXGLDevice_allocVertexBuffer);
354   if(bufferType == GFXBufferTypeVolatile)
355      return findVolatileVBO(numVerts, vertexFormat, vertSize);
356         
357   GFXGLVertexBuffer* buf = new GFXGLVertexBuffer( GFX, numVerts, vertexFormat, vertSize, bufferType );
358   buf->registerResourceWithDevice(this);   
359
360   if(data)
361   {
362      void* dest;
363      buf->lock(0, numVerts, &dest);
364      dMemcpy(dest, data, vertSize * numVerts);
365      buf->unlock();
366   }
367
368   return buf;
369}
370
371GFXPrimitiveBuffer *GFXGLDevice::allocPrimitiveBuffer( U32 numIndices, U32 numPrimitives, GFXBufferType bufferType, void* data ) 
372{
373   GFXPrimitiveBuffer* buf;
374   
375   if(bufferType == GFXBufferTypeVolatile)
376   {
377      buf = findVolatilePBO(numIndices, numPrimitives);
378   }
379   else
380   {
381      buf = new GFXGLPrimitiveBuffer(GFX, numIndices, numPrimitives, bufferType);
382      buf->registerResourceWithDevice(this);
383   }
384   
385   if(data)
386   {
387      void* dest;
388      buf->lock(0, numIndices, &dest);
389      dMemcpy(dest, data, sizeof(U16) * numIndices);
390      buf->unlock();
391   }
392   return buf;
393}
394
395void GFXGLDevice::setVertexStream( U32 stream, GFXVertexBuffer *buffer )
396{
397   AssertFatal(stream <= 1, "GFXGLDevice::setVertexStream only support 2 stream (0: data, 1: instancing)");
398
399   //if(mCurrentVB[stream] != buffer)
400   {
401      // Reset the state the old VB required, then set the state the new VB requires.
402      if( mCurrentVB[stream] )
403      {     
404         mCurrentVB[stream]->finish();
405      }
406
407      mCurrentVB[stream] = static_cast<GFXGLVertexBuffer*>( buffer );
408
409      mNeedUpdateVertexAttrib = true;
410   }
411}
412
413void GFXGLDevice::setVertexStreamFrequency( U32 stream, U32 frequency )
414{
415   if( stream == 0 )
416   {
417      mCurrentVB_Divisor[stream] = 0; // non instanced, is vertex buffer
418      mDrawInstancesCount = frequency; // instances count
419   }
420   else
421   {
422      AssertFatal(frequency <= 1, "GFXGLDevice::setVertexStreamFrequency only support 0/1 for this stream" );
423      if( stream == 1 && frequency == 1 )
424         mCurrentVB_Divisor[stream] = 1; // instances data need a frequency of 1
425      else
426         mCurrentVB_Divisor[stream] = 0;
427   }
428
429   mNeedUpdateVertexAttrib = true;
430}
431
432GFXCubemap* GFXGLDevice::createCubemap()
433{ 
434   GFXGLCubemap* cube = new GFXGLCubemap();
435   cube->registerResourceWithDevice(this);
436   return cube; 
437};
438
439void GFXGLDevice::endSceneInternal() 
440{
441   // nothing to do for opengl
442   mCanCurrentlyRender = false;
443}
444
445void GFXGLDevice::clear(U32 flags, ColorI color, F32 z, U32 stencil)
446{
447   // Make sure we have flushed our render target state.
448   _updateRenderTargets();
449   
450   bool writeAllColors = true;
451   bool zwrite = true;   
452   bool writeAllStencil = true;
453   const GFXStateBlockDesc *desc = NULL;
454   if (mCurrentGLStateBlock)
455   {
456      desc = &mCurrentGLStateBlock->getDesc();
457      zwrite = desc->zWriteEnable;
458      writeAllColors = desc->colorWriteRed && desc->colorWriteGreen && desc->colorWriteBlue && desc->colorWriteAlpha;
459      writeAllStencil = desc->stencilWriteMask == 0xFFFFFFFF;
460   }
461   
462   glColorMask(true, true, true, true);
463   glDepthMask(true);
464   glStencilMask(0xFFFFFFFF);
465   
466
467   ColorF c = color;   
468   glClearColor(c.red, c.green, c.blue, c.alpha);
469   glClearDepth(z);
470   glClearStencil(stencil);
471
472   GLbitfield clearflags = 0;
473   clearflags |= (flags & GFXClearTarget)   ? GL_COLOR_BUFFER_BIT : 0;
474   clearflags |= (flags & GFXClearZBuffer)  ? GL_DEPTH_BUFFER_BIT : 0;
475   clearflags |= (flags & GFXClearStencil)  ? GL_STENCIL_BUFFER_BIT : 0;
476
477   glClear(clearflags);
478
479   if(!writeAllColors)
480      glColorMask(desc->colorWriteRed, desc->colorWriteGreen, desc->colorWriteBlue, desc->colorWriteAlpha);
481   
482   if(!zwrite)
483      glDepthMask(false);
484
485   if(!writeAllStencil)
486      glStencilMask(desc->stencilWriteMask);
487}
488
489// Given a primitive type and a number of primitives, return the number of indexes/vertexes used.
490inline GLsizei GFXGLDevice::primCountToIndexCount(GFXPrimitiveType primType, U32 primitiveCount)
491{
492   switch (primType)
493   {
494      case GFXPointList :
495         return primitiveCount;
496         break;
497      case GFXLineList :
498         return primitiveCount * 2;
499         break;
500      case GFXLineStrip :
501         return primitiveCount + 1;
502         break;
503      case GFXTriangleList :
504         return primitiveCount * 3;
505         break;
506      case GFXTriangleStrip :
507         return 2 + primitiveCount;
508         break;
509      default:
510         AssertFatal(false, "GFXGLDevice::primCountToIndexCount - unrecognized prim type");
511         break;
512   }
513   
514   return 0;
515}
516
517GFXVertexDecl* GFXGLDevice::allocVertexDecl( const GFXVertexFormat *vertexFormat ) 
518{
519   PROFILE_SCOPE(GFXGLDevice_allocVertexDecl);
520   typedef Map<void*, GFXGLVertexDecl> GFXGLVertexDeclMap;
521   static GFXGLVertexDeclMap declMap;   
522   GFXGLVertexDeclMap::Iterator itr = declMap.find( (void*)vertexFormat->getDescription().c_str() ); // description string are interned, safe to use c_str()
523   if(itr != declMap.end())
524      return &itr->value;
525
526   GFXGLVertexDecl &decl = declMap[(void*)vertexFormat->getDescription().c_str()];   
527   decl.init(vertexFormat);
528   return &decl;
529}
530
531void GFXGLDevice::setVertexDecl( const GFXVertexDecl *decl )
532{
533   static_cast<const GFXGLVertexDecl*>(decl)->prepareVertexFormat();
534}
535
536inline void GFXGLDevice::preDrawPrimitive()
537{
538   if( mStateDirty )
539   {
540      updateStates();
541   }
542   
543   if(mCurrentShaderConstBuffer)
544      setShaderConstBufferInternal(mCurrentShaderConstBuffer);
545
546   if( mNeedUpdateVertexAttrib )
547   {
548      AssertFatal(mCurrVertexDecl, "");
549      const GFXGLVertexDecl* decl = static_cast<const GFXGLVertexDecl*>(mCurrVertexDecl);
550      
551      for(int i = 0; i < getNumVertexStreams(); ++i)
552      {
553         if(mCurrentVB[i])
554         {
555            mCurrentVB[i]->prepare(i, mCurrentVB_Divisor[i]);    // GL_ARB_vertex_attrib_binding  
556            decl->prepareBuffer_old( i, mCurrentVB[i]->mBuffer, mCurrentVB_Divisor[i] ); // old vertex buffer/format
557         }
558      }
559
560      decl->updateActiveVertexAttrib( GFXGL->getOpenglCache()->getCacheVertexAttribActive() );         
561   }   
562
563   mNeedUpdateVertexAttrib = false;
564}
565
566inline void GFXGLDevice::postDrawPrimitive(U32 primitiveCount)
567{
568   mDeviceStatistics.mDrawCalls++;
569   mDeviceStatistics.mPolyCount += primitiveCount;
570}
571
572void GFXGLDevice::drawPrimitive( GFXPrimitiveType primType, U32 vertexStart, U32 primitiveCount ) 
573{
574   preDrawPrimitive();
575  
576   vertexStart += mCurrentVB[0]->mBufferVertexOffset;
577
578   if(mDrawInstancesCount)
579      glDrawArraysInstanced(GFXGLPrimType[primType], vertexStart, primCountToIndexCount(primType, primitiveCount), mDrawInstancesCount);
580   else
581      glDrawArrays(GFXGLPrimType[primType], vertexStart, primCountToIndexCount(primType, primitiveCount));   
582
583   postDrawPrimitive(primitiveCount);
584}
585
586void GFXGLDevice::drawIndexedPrimitive(   GFXPrimitiveType primType, 
587                                          U32 startVertex, 
588                                          U32 minIndex, 
589                                          U32 numVerts, 
590                                          U32 startIndex, 
591                                          U32 primitiveCount )
592{
593   preDrawPrimitive();
594
595   U16* buf = (U16*)static_cast<GFXGLPrimitiveBuffer*>(mCurrentPrimitiveBuffer.getPointer())->getBuffer() + startIndex + mCurrentPrimitiveBuffer->mVolatileStart;
596
597   const U32 baseVertex = mCurrentVB[0]->mBufferVertexOffset + startVertex;
598
599   if(mDrawInstancesCount)
600      glDrawElementsInstancedBaseVertex(GFXGLPrimType[primType], primCountToIndexCount(primType, primitiveCount), GL_UNSIGNED_SHORT, buf, mDrawInstancesCount, baseVertex);
601   else
602      glDrawElementsBaseVertex(GFXGLPrimType[primType], primCountToIndexCount(primType, primitiveCount), GL_UNSIGNED_SHORT, buf, baseVertex);
603
604   postDrawPrimitive(primitiveCount);
605}
606
607void GFXGLDevice::setPB(GFXGLPrimitiveBuffer* pb)
608{
609   if(mCurrentPB)
610      mCurrentPB->finish();
611   mCurrentPB = pb;
612}
613
614void GFXGLDevice::setLightInternal(U32 lightStage, const GFXLightInfo light, bool lightEnable)
615{
616   // ONLY NEEDED ON FFP
617}
618
619void GFXGLDevice::setLightMaterialInternal(const GFXLightMaterial mat)
620{
621   // ONLY NEEDED ON FFP
622}
623
624void GFXGLDevice::setGlobalAmbientInternal(ColorF color)
625{
626   // ONLY NEEDED ON FFP
627}
628
629void GFXGLDevice::setTextureInternal(U32 textureUnit, const GFXTextureObject*texture)
630{
631   GFXGLTextureObject *tex = static_cast<GFXGLTextureObject*>(const_cast<GFXTextureObject*>(texture));
632   if (tex)
633   {
634      mActiveTextureType[textureUnit] = tex->getBinding();
635      tex->bind(textureUnit);
636   } 
637   else if(mActiveTextureType[textureUnit] != GL_ZERO)
638   {
639      glActiveTexture(GL_TEXTURE0 + textureUnit);
640      glBindTexture(mActiveTextureType[textureUnit], 0);
641      getOpenglCache()->setCacheBindedTex(textureUnit, mActiveTextureType[textureUnit], 0);
642      mActiveTextureType[textureUnit] = GL_ZERO;
643   }
644}
645
646void GFXGLDevice::setCubemapInternal(U32 textureUnit, const GFXGLCubemap* texture)
647{
648   if(texture)
649   {
650      mActiveTextureType[textureUnit] = GL_TEXTURE_CUBE_MAP;
651      texture->bind(textureUnit);
652   }
653   else if(mActiveTextureType[textureUnit] != GL_ZERO)
654   {
655      glActiveTexture(GL_TEXTURE0 + textureUnit);
656      glBindTexture(mActiveTextureType[textureUnit], 0);
657      getOpenglCache()->setCacheBindedTex(textureUnit, mActiveTextureType[textureUnit], 0);
658      mActiveTextureType[textureUnit] = GL_ZERO;
659   }
660}
661
662void GFXGLDevice::setMatrix( GFXMatrixType mtype, const MatrixF &mat )
663{
664   // ONLY NEEDED ON FFP
665}
666
667void GFXGLDevice::setClipRect( const RectI &inRect )
668{
669   AssertFatal(mCurrentRT.isValid(), "GFXGLDevice::setClipRect - must have a render target set to do any rendering operations!");
670
671   // Clip the rect against the renderable size.
672   Point2I size = mCurrentRT->getSize();
673   RectI maxRect(Point2I(0,0), size);
674   mClip = inRect;
675   mClip.intersect(maxRect);
676
677   // Create projection matrix.  See http://www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/ortho.html
678   const F32 left = mClip.point.x;
679   const F32 right = mClip.point.x + mClip.extent.x;
680   const F32 bottom = mClip.extent.y;
681   const F32 top = 0.0f;
682   const F32 nearPlane = 0.0f;
683   const F32 farPlane = 1.0f;
684   
685   const F32 tx = -(right + left)/(right - left);
686   const F32 ty = -(top + bottom)/(top - bottom);
687   const F32 tz = -(farPlane + nearPlane)/(farPlane - nearPlane);
688   
689   static Point4F pt;
690   pt.set(2.0f / (right - left), 0.0f, 0.0f, 0.0f);
691   mProjectionMatrix.setColumn(0, pt);
692   
693   pt.set(0.0f, 2.0f/(top - bottom), 0.0f, 0.0f);
694   mProjectionMatrix.setColumn(1, pt);
695   
696   pt.set(0.0f, 0.0f, -2.0f/(farPlane - nearPlane), 0.0f);
697   mProjectionMatrix.setColumn(2, pt);
698   
699   pt.set(tx, ty, tz, 1.0f);
700   mProjectionMatrix.setColumn(3, pt);
701   
702   // Translate projection matrix.
703   static MatrixF translate(true);
704   pt.set(0.0f, -mClip.point.y, 0.0f, 1.0f);
705   translate.setColumn(3, pt);
706   
707   mProjectionMatrix *= translate;
708   
709   setMatrix(GFXMatrixProjection, mProjectionMatrix);
710   
711   MatrixF mTempMatrix(true);
712   setViewMatrix( mTempMatrix );
713   setWorldMatrix( mTempMatrix );
714
715   // Set the viewport to the clip rect
716   RectI viewport(mClip.point.x, mClip.point.y, mClip.extent.x, mClip.extent.y);
717   setViewport(viewport);
718}
719
720/// Creates a state block object based on the desc passed in.  This object
721/// represents an immutable state.
722GFXStateBlockRef GFXGLDevice::createStateBlockInternal(const GFXStateBlockDesc& desc)
723{
724   return GFXStateBlockRef(new GFXGLStateBlock(desc));
725}
726
727/// Activates a stateblock
728void GFXGLDevice::setStateBlockInternal(GFXStateBlock* block, bool force)
729{
730   AssertFatal(dynamic_cast<GFXGLStateBlock*>(block), "GFXGLDevice::setStateBlockInternal - Incorrect stateblock type for this device!");
731   GFXGLStateBlock* glBlock = static_cast<GFXGLStateBlock*>(block);
732   GFXGLStateBlock* glCurrent = static_cast<GFXGLStateBlock*>(mCurrentStateBlock.getPointer());
733   if (force)
734      glCurrent = NULL;
735      
736   glBlock->activate(glCurrent); // Doesn't use current yet.
737   mCurrentGLStateBlock = glBlock;
738}
739
740//------------------------------------------------------------------------------
741
742GFXTextureTarget * GFXGLDevice::allocRenderToTextureTarget()
743{
744   GFXGLTextureTarget *targ = new GFXGLTextureTarget();
745   targ->registerResourceWithDevice(this);
746   return targ;
747}
748
749GFXFence * GFXGLDevice::createFence()
750{
751   GFXFence* fence = _createPlatformSpecificFence();
752   if(!fence)
753      fence = new GFXGeneralFence( this );
754      
755   fence->registerResourceWithDevice(this);
756   return fence;
757}
758
759GFXOcclusionQuery* GFXGLDevice::createOcclusionQuery()
760{   
761   GFXOcclusionQuery *query = new GFXGLOcclusionQuery( this );
762   query->registerResourceWithDevice(this);
763   return query;
764}
765
766void GFXGLDevice::setupGenericShaders( GenericShaderType type ) 
767{
768   AssertFatal(type != GSTargetRestore, "");
769
770   if( mGenericShader[GSColor] == NULL )
771   {
772      ShaderData *shaderData;
773
774      shaderData = new ShaderData();
775      shaderData->setField("OGLVertexShaderFile", "shaders/common/fixedFunction/gl/colorV.glsl");
776      shaderData->setField("OGLPixelShaderFile", "shaders/common/fixedFunction/gl/colorP.glsl");
777      shaderData->setField("pixVersion", "2.0");
778      shaderData->registerObject();
779      mGenericShader[GSColor] =  shaderData->getShader();
780      mGenericShaderBuffer[GSColor] = mGenericShader[GSColor]->allocConstBuffer();
781      mModelViewProjSC[GSColor] = mGenericShader[GSColor]->getShaderConstHandle( "$modelView" );
782      Sim::getRootGroup()->addObject(shaderData);
783
784      shaderData = new ShaderData();
785      shaderData->setField("OGLVertexShaderFile", "shaders/common/fixedFunction/gl/modColorTextureV.glsl");
786      shaderData->setField("OGLPixelShaderFile", "shaders/common/fixedFunction/gl/modColorTextureP.glsl");
787      shaderData->setSamplerName("$diffuseMap", 0);
788      shaderData->setField("pixVersion", "2.0");
789      shaderData->registerObject();
790      mGenericShader[GSModColorTexture] = shaderData->getShader();
791      mGenericShaderBuffer[GSModColorTexture] = mGenericShader[GSModColorTexture]->allocConstBuffer();
792      mModelViewProjSC[GSModColorTexture] = mGenericShader[GSModColorTexture]->getShaderConstHandle( "$modelView" );
793      Sim::getRootGroup()->addObject(shaderData);
794
795      shaderData = new ShaderData();
796      shaderData->setField("OGLVertexShaderFile", "shaders/common/fixedFunction/gl/addColorTextureV.glsl");
797      shaderData->setField("OGLPixelShaderFile", "shaders/common/fixedFunction/gl/addColorTextureP.glsl");
798      shaderData->setSamplerName("$diffuseMap", 0);
799      shaderData->setField("pixVersion", "2.0");
800      shaderData->registerObject();
801      mGenericShader[GSAddColorTexture] = shaderData->getShader();
802      mGenericShaderBuffer[GSAddColorTexture] = mGenericShader[GSAddColorTexture]->allocConstBuffer();
803      mModelViewProjSC[GSAddColorTexture] = mGenericShader[GSAddColorTexture]->getShaderConstHandle( "$modelView" );
804      Sim::getRootGroup()->addObject(shaderData);
805
806      shaderData = new ShaderData();
807      shaderData->setField("OGLVertexShaderFile", "shaders/common/fixedFunction/gl/textureV.glsl");
808      shaderData->setField("OGLPixelShaderFile", "shaders/common/fixedFunction/gl/textureP.glsl");
809      shaderData->setSamplerName("$diffuseMap", 0);
810      shaderData->setField("pixVersion", "2.0");
811      shaderData->registerObject();
812      mGenericShader[GSTexture] = shaderData->getShader();
813      mGenericShaderBuffer[GSTexture] = mGenericShader[GSTexture]->allocConstBuffer();
814      mModelViewProjSC[GSTexture] = mGenericShader[GSTexture]->getShaderConstHandle( "$modelView" );
815      Sim::getRootGroup()->addObject(shaderData);
816   }
817
818   MatrixF tempMatrix =  mProjectionMatrix * mViewMatrix * mWorldMatrix[mWorldStackSize];  
819   mGenericShaderBuffer[type]->setSafe(mModelViewProjSC[type], tempMatrix);
820
821   setShader( mGenericShader[type] );
822   setShaderConstBuffer( mGenericShaderBuffer[type] );
823}
824GFXShader* GFXGLDevice::createShader()
825{
826   GFXGLShader* shader = new GFXGLShader();
827   shader->registerResourceWithDevice( this );
828   return shader;
829}
830
831void GFXGLDevice::setShader(GFXShader *shader, bool force)
832{
833   if(mCurrentShader == shader && !force)
834      return;
835
836   if ( shader )
837   {
838      GFXGLShader *glShader = static_cast<GFXGLShader*>( shader );
839      glShader->useProgram();
840      mCurrentShader = shader;
841   }
842   else
843   {
844      setupGenericShaders();
845   }
846}
847
848void GFXGLDevice::setShaderConstBufferInternal(GFXShaderConstBuffer* buffer)
849{
850   PROFILE_SCOPE(GFXGLDevice_setShaderConstBufferInternal);
851   static_cast<GFXGLShaderConstBuffer*>(buffer)->activate();
852}
853
854U32 GFXGLDevice::getNumSamplers() const
855{
856   return getMin((U32)TEXTURE_STAGE_COUNT,mPixelShaderVersion > 0.001f ? mMaxShaderTextures : mMaxFFTextures);
857}
858
859GFXTextureObject* GFXGLDevice::getDefaultDepthTex() const 
860{
861   if(mWindowRT && mWindowRT->getPointer())
862      return static_cast<GFXGLWindowTarget*>( mWindowRT->getPointer() )->mBackBufferDepthTex.getPointer();
863
864   return NULL;
865}
866
867U32 GFXGLDevice::getNumRenderTargets() const 
868{ 
869   return mMaxTRColors; 
870}
871
872void GFXGLDevice::_updateRenderTargets()
873{
874   if ( mRTDirty || mCurrentRT->isPendingState() )
875   {
876      if ( mRTDeactivate )
877      {
878         mRTDeactivate->deactivate();
879         mRTDeactivate = NULL;   
880      }
881      
882      // NOTE: The render target changes is not really accurate
883      // as the GFXTextureTarget supports MRT internally.  So when
884      // we activate a GFXTarget it could result in multiple calls
885      // to SetRenderTarget on the actual device.
886      mDeviceStatistics.mRenderTargetChanges++;
887
888      GFXGLTextureTarget *tex = dynamic_cast<GFXGLTextureTarget*>( mCurrentRT.getPointer() );
889      if ( tex )
890      {
891         tex->applyState();
892         tex->makeActive();
893      }
894      else
895      {
896         GFXGLWindowTarget *win = dynamic_cast<GFXGLWindowTarget*>( mCurrentRT.getPointer() );
897         AssertFatal( win != NULL, 
898                     "GFXGLDevice::_updateRenderTargets() - invalid target subclass passed!" );
899         
900         win->makeActive();
901         
902         if( win->mContext != static_cast<GFXGLDevice*>(GFX)->mContext )
903         {
904            mRTDirty = false;
905            GFX->updateStates(true);
906         }
907      }
908      
909      mRTDirty = false;
910   }
911   
912   if ( mViewportDirty )
913   {
914      glViewport( mViewport.point.x, mViewport.point.y, mViewport.extent.x, mViewport.extent.y ); 
915      mViewportDirty = false;
916   }
917}
918
919GFXFormat GFXGLDevice::selectSupportedFormat(   GFXTextureProfile* profile, 
920                                                const Vector<GFXFormat>& formats, 
921                                                bool texture, 
922                                                bool mustblend,
923                                                bool mustfilter )
924{
925   for(U32 i = 0; i < formats.size(); i++)
926   {
927      // Single channel textures are not supported by FBOs.
928      if(profile->testFlag(GFXTextureProfile::RenderTarget) && (formats[i] == GFXFormatA8 || formats[i] == GFXFormatL8 || formats[i] == GFXFormatL16))
929         continue;
930      if(GFXGLTextureInternalFormat[formats[i]] == GL_ZERO)
931         continue;
932      
933      return formats[i];
934   }
935   
936   return GFXFormatR8G8B8A8;
937}
938
939U32 GFXGLDevice::getTotalVideoMemory_GL_EXT()
940{
941   // Source: http://www.opengl.org/registry/specs/ATI/meminfo.txt
942   if( gglHasExtension(ATI_meminfo) )
943   {
944      GLint mem[4] = {0};
945      glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI, mem);  // Retrieve the texture pool
946      
947      /* With mem[0] i get only the total memory free in the pool in KB
948      *
949      * mem[0] - total memory free in the pool
950      * mem[1] - largest available free block in the pool
951      * mem[2] - total auxiliary memory free
952      * mem[3] - largest auxiliary free block
953      */
954
955      return  mem[0] / 1024;
956   }
957   
958   //source http://www.opengl.org/registry/specs/NVX/gpu_memory_info.txt
959   else if( gglHasExtension(NVX_gpu_memory_info) )
960   {
961      GLint mem = 0;
962      glGetIntegerv(GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX, &mem);
963      return mem / 1024;
964   }
965
966   // TODO OPENGL, add supprt for INTEL cards.
967   
968   return 0;
969}
970
971//
972// Register this device with GFXInit
973//
974class GFXGLRegisterDevice
975{
976public:
977   GFXGLRegisterDevice()
978   {
979      GFXInit::getRegisterDeviceSignal().notify(&GFXGLDevice::enumerateAdapters);
980   }
981};
982
983static GFXGLRegisterDevice pGLRegisterDevice;
984
985ConsoleFunction(cycleResources, void, 1, 1, "")
986{
987   static_cast<GFXGLDevice*>(GFX)->zombify();
988   static_cast<GFXGLDevice*>(GFX)->resurrect();
989}
990