compile fix
[Torque-3d.git] / Engine / source / gfx / gl / gfxGLDevice.cpp
blob01bbd02ea443136a28d988f66b2b4f55e7392439
1 //-----------------------------------------------------------------------------
2 // Copyright (c) 2012 GarageGames, LLC
3 //
4 // Permission is hereby granted, free of charge, to any person obtaining a copy
5 // of this software and associated documentation files (the "Software"), to
6 // deal in the Software without restriction, including without limitation the
7 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8 // sell copies of the Software, and to permit persons to whom the Software is
9 // furnished to do so, subject to the following conditions:
11 // The above copyright notice and this permission notice shall be included in
12 // all copies or substantial portions of the Software.
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20 // IN THE SOFTWARE.
21 //-----------------------------------------------------------------------------
23 #include "platform/platform.h"
24 #include "gfx/gl/gfxGLDevice.h"
25 #include "platform/platformGL.h"
27 #include "gfx/gfxCubemap.h"
28 #include "gfx/screenshot.h"
29 #include "gfx/gfxDrawUtil.h"
31 #include "gfx/gl/gfxGLEnumTranslate.h"
32 #include "gfx/gl/gfxGLVertexBuffer.h"
33 #include "gfx/gl/gfxGLPrimitiveBuffer.h"
34 #include "gfx/gl/gfxGLTextureTarget.h"
35 #include "gfx/gl/gfxGLTextureManager.h"
36 #include "gfx/gl/gfxGLTextureObject.h"
37 #include "gfx/gl/gfxGLCubemap.h"
38 #include "gfx/gl/gfxGLCardProfiler.h"
39 #include "gfx/gl/gfxGLWindowTarget.h"
40 #include "platform/platformDlibrary.h"
41 #include "gfx/gl/gfxGLShader.h"
42 #include "gfx/primBuilder.h"
43 #include "console/console.h"
44 #include "gfx/gl/gfxGLOcclusionQuery.h"
45 #include "materials/shaderData.h"
46 #include "gfx/gl/gfxGLStateCache.h"
47 #include "gfx/gl/gfxGLVertexAttribLocation.h"
48 #include "gfx/gl/gfxGLVertexDecl.h"
50 GFXAdapter::CreateDeviceInstanceDelegate GFXGLDevice::mCreateDeviceInstance(GFXGLDevice::createInstance);
52 GFXDevice *GFXGLDevice::createInstance( U32 adapterIndex )
54 return new GFXGLDevice(adapterIndex);
57 namespace GL
59 extern void gglPerformBinds();
60 extern void gglPerformExtensionBinds(void *context);
63 void loadGLCore()
65 static bool coreLoaded = false; // Guess what this is for.
66 if(coreLoaded)
67 return;
68 coreLoaded = true;
70 // Make sure we've got our GL bindings.
71 GL::gglPerformBinds();
74 void loadGLExtensions(void *context)
76 static bool extensionsLoaded = false;
77 if(extensionsLoaded)
78 return;
79 extensionsLoaded = true;
81 GL::gglPerformExtensionBinds(context);
84 void STDCALL glDebugCallback(GLenum source, GLenum type, GLuint id,
85 GLenum severity, GLsizei length, const GLchar* message, void* userParam)
87 if (severity == GL_DEBUG_SEVERITY_HIGH)
88 Con::errorf("OPENGL: %s", message);
89 else if (severity == GL_DEBUG_SEVERITY_MEDIUM)
90 Con::warnf("OPENGL: %s", message);
91 else if (severity == GL_DEBUG_SEVERITY_LOW)
92 Con::printf("OPENGL: %s", message);
95 void STDCALL glAmdDebugCallback(GLuint id, GLenum category, GLenum severity, GLsizei length,
96 const GLchar* message, GLvoid* userParam)
98 if (severity == GL_DEBUG_SEVERITY_HIGH)
99 Con::errorf("AMDOPENGL: %s", message);
100 else if (severity == GL_DEBUG_SEVERITY_MEDIUM)
101 Con::warnf("AMDOPENGL: %s", message);
102 else if (severity == GL_DEBUG_SEVERITY_LOW)
103 Con::printf("AMDOPENGL: %s", message);
107 // >>>> OPENGL INTEL WORKAROUND @todo OPENGL INTEL remove
108 PFNGLBINDFRAMEBUFFERPROC __openglBindFramebuffer = NULL;
110 void STDCALL _t3d_glBindFramebuffer(GLenum target, GLuint framebuffer)
112 if( target == GL_FRAMEBUFFER )
114 if( GFXGL->getOpenglCache()->getCacheBinded( GL_DRAW_FRAMEBUFFER ) == framebuffer
115 && GFXGL->getOpenglCache()->getCacheBinded( GL_READ_FRAMEBUFFER ) == framebuffer )
116 return;
118 else if( GFXGL->getOpenglCache()->getCacheBinded( target ) == framebuffer )
119 return;
121 __openglBindFramebuffer(target, framebuffer);
122 GFXGL->getOpenglCache()->setCacheBinded( target, framebuffer);
124 // <<<< OPENGL INTEL WORKAROUND
127 void GFXGLDevice::initGLState()
129 // We don't currently need to sync device state with a known good place because we are
130 // going to set everything in GFXGLStateBlock, but if we change our GFXGLStateBlock strategy, this may
131 // need to happen.
133 // Deal with the card profiler here when we know we have a valid context.
134 mCardProfiler = new GFXGLCardProfiler();
135 mCardProfiler->init();
136 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, (GLint*)&mMaxShaderTextures);
137 glGetIntegerv(GL_MAX_TEXTURE_UNITS, (GLint*)&mMaxFFTextures);
138 glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, (GLint*)&mMaxTRColors);
139 mMaxTRColors = getMin( mMaxTRColors, (U32)(GFXTextureTarget::MaxRenderSlotId-1) );
141 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
143 // Setting mPixelShaderVersion to 3.0 will allow Advanced Lighting to run.
144 mPixelShaderVersion = 3.0;
146 mSupportsAnisotropic = mCardProfiler->queryProfile( "GL::suppAnisotropic" );
148 String vendorStr = (const char*)glGetString( GL_VENDOR );
149 if( vendorStr.find("NVIDIA", 0, String::NoCase | String::Left) != String::NPos)
150 mUseGlMap = false;
153 if( vendorStr.find("INTEL", 0, String::NoCase | String::Left ) != String::NPos)
155 // @todo OPENGL INTEL - This is a workaround for a warning spam or even crashes with actual framebuffer code, remove when implemented TGL layer.
156 __openglBindFramebuffer = glBindFramebuffer;
157 glBindFramebuffer = &_t3d_glBindFramebuffer;
160 #ifdef TORQUE_NSIGHT_WORKAROUND
161 __GLEW_ARB_buffer_storage = false;
162 #endif
163 #if TORQUE_DEBUG
164 if( gglHasExtension(ARB_debug_output) )
166 glEnable(GL_DEBUG_OUTPUT);
167 glDebugMessageCallbackARB(glDebugCallback, NULL);
168 glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
169 GLuint unusedIds = 0;
170 glDebugMessageControlARB(GL_DONT_CARE,
171 GL_DONT_CARE,
172 GL_DONT_CARE,
174 &unusedIds,
175 GL_TRUE);
177 else if(gglHasExtension(AMD_debug_output))
179 glEnable(GL_DEBUG_OUTPUT);
180 glDebugMessageCallbackAMD(glAmdDebugCallback, NULL);
181 //glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
182 GLuint unusedIds = 0;
183 glDebugMessageEnableAMD(GL_DONT_CARE, GL_DONT_CARE, 0,&unusedIds, GL_TRUE);
185 #endif
187 PlatformGL::setVSync(smDisableVSync ? 0 : 1);
189 //OpenGL 3 need a binded VAO for render
190 GLuint vao;
191 glGenVertexArrays(1, &vao);
192 glBindVertexArray(vao);
195 GFXGLDevice::GFXGLDevice(U32 adapterIndex) :
196 mAdapterIndex(adapterIndex),
197 mCurrentPB(NULL),
198 mDrawInstancesCount(0),
199 m_mCurrentWorld(true),
200 m_mCurrentView(true),
201 mContext(NULL),
202 mPixelFormat(NULL),
203 mPixelShaderVersion(0.0f),
204 mMaxShaderTextures(2),
205 mMaxFFTextures(2),
206 mMaxTRColors(1),
207 mClip(0, 0, 0, 0),
208 mCurrentShader( NULL ),
209 mNeedUpdateVertexAttrib(false),
210 mWindowRT(NULL),
211 mUseGlMap(true)
213 for(int i = 0; i < VERTEX_STREAM_COUNT; ++i)
215 mCurrentVB[i] = NULL;
216 mCurrentVB_Divisor[i] = 0;
219 loadGLCore();
221 GFXGLEnumTranslate::init();
223 GFXVertexColor::setSwizzle( &Swizzles::rgba );
225 // OpenGL have native RGB, no need swizzle
226 mDeviceSwizzle32 = &Swizzles::rgba;
227 mDeviceSwizzle24 = &Swizzles::rgb;
229 mTextureManager = new GFXGLTextureManager();
230 gScreenShot = new ScreenShot();
232 for(U32 i = 0; i < TEXTURE_STAGE_COUNT; i++)
233 mActiveTextureType[i] = GL_ZERO;
235 mNumVertexStream = 2;
237 for(int i = 0; i < GS_COUNT; ++i)
238 mModelViewProjSC[i] = NULL;
240 mOpenglStateCache = new GFXGLStateCache;
243 GFXGLDevice::~GFXGLDevice()
245 mCurrentStateBlock = NULL;
247 for(int i = 0; i < VERTEX_STREAM_COUNT; ++i)
248 mCurrentVB[i] = NULL;
249 mCurrentPB = NULL;
251 for(U32 i = 0; i < mVolatileVBs.size(); i++)
252 mVolatileVBs[i] = NULL;
253 for(U32 i = 0; i < mVolatilePBs.size(); i++)
254 mVolatilePBs[i] = NULL;
256 // Clear out our current texture references
257 for (U32 i = 0; i < TEXTURE_STAGE_COUNT; i++)
259 mCurrentTexture[i] = NULL;
260 mNewTexture[i] = NULL;
261 mCurrentCubemap[i] = NULL;
262 mNewCubemap[i] = NULL;
265 mRTStack.clear();
266 mCurrentRT = NULL;
268 if( mTextureManager )
270 mTextureManager->zombify();
271 mTextureManager->kill();
274 GFXResource* walk = mResourceListHead;
275 while(walk)
277 walk->zombify();
278 walk = walk->getNextResource();
281 if( mCardProfiler )
282 SAFE_DELETE( mCardProfiler );
284 SAFE_DELETE( gScreenShot );
286 SAFE_DELETE( mOpenglStateCache );
289 void GFXGLDevice::zombify()
291 mTextureManager->zombify();
293 for(int i = 0; i < VERTEX_STREAM_COUNT; ++i)
294 if(mCurrentVB[i])
295 mCurrentVB[i]->finish();
296 if(mCurrentPB)
297 mCurrentPB->finish();
299 //mVolatileVBs.clear();
300 //mVolatilePBs.clear();
301 GFXResource* walk = mResourceListHead;
302 while(walk)
304 walk->zombify();
305 walk = walk->getNextResource();
309 void GFXGLDevice::resurrect()
311 GFXResource* walk = mResourceListHead;
312 while(walk)
314 walk->resurrect();
315 walk = walk->getNextResource();
317 for(int i = 0; i < VERTEX_STREAM_COUNT; ++i)
318 if(mCurrentVB[i])
319 mCurrentVB[i]->prepare();
320 if(mCurrentPB)
321 mCurrentPB->prepare();
323 mTextureManager->resurrect();
326 GFXVertexBuffer* GFXGLDevice::findVolatileVBO(U32 numVerts, const GFXVertexFormat *vertexFormat, U32 vertSize)
328 for(U32 i = 0; i < mVolatileVBs.size(); i++)
329 if ( mVolatileVBs[i]->mNumVerts >= numVerts &&
330 mVolatileVBs[i]->mVertexFormat.isEqual( *vertexFormat ) &&
331 mVolatileVBs[i]->mVertexSize == vertSize &&
332 mVolatileVBs[i]->getRefCount() == 1 )
333 return mVolatileVBs[i];
335 // No existing VB, so create one
336 StrongRefPtr<GFXGLVertexBuffer> buf(new GFXGLVertexBuffer(GFX, numVerts, vertexFormat, vertSize, GFXBufferTypeVolatile));
337 buf->registerResourceWithDevice(this);
338 mVolatileVBs.push_back(buf);
339 return buf.getPointer();
342 GFXPrimitiveBuffer* GFXGLDevice::findVolatilePBO(U32 numIndices, U32 numPrimitives)
344 for(U32 i = 0; i < mVolatilePBs.size(); i++)
345 if((mVolatilePBs[i]->mIndexCount >= numIndices) && (mVolatilePBs[i]->getRefCount() == 1))
346 return mVolatilePBs[i];
348 // No existing PB, so create one
349 StrongRefPtr<GFXGLPrimitiveBuffer> buf(new GFXGLPrimitiveBuffer(GFX, numIndices, numPrimitives, GFXBufferTypeVolatile));
350 buf->registerResourceWithDevice(this);
351 mVolatilePBs.push_back(buf);
352 return buf.getPointer();
355 GFXVertexBuffer *GFXGLDevice::allocVertexBuffer( U32 numVerts,
356 const GFXVertexFormat *vertexFormat,
357 U32 vertSize,
358 GFXBufferType bufferType,
359 void* data )
361 if(bufferType == GFXBufferTypeVolatile)
362 return findVolatileVBO(numVerts, vertexFormat, vertSize);
364 GFXGLVertexBuffer* buf = new GFXGLVertexBuffer( GFX, numVerts, vertexFormat, vertSize, bufferType );
365 buf->registerResourceWithDevice(this);
367 if(data)
369 void* dest;
370 buf->lock(0, numVerts, &dest);
371 dMemcpy(dest, data, vertSize * numVerts);
372 buf->unlock();
375 return buf;
378 GFXPrimitiveBuffer *GFXGLDevice::allocPrimitiveBuffer( U32 numIndices, U32 numPrimitives, GFXBufferType bufferType, void* data )
380 GFXPrimitiveBuffer* buf;
382 if(bufferType == GFXBufferTypeVolatile)
384 buf = findVolatilePBO(numIndices, numPrimitives);
386 else
388 buf = new GFXGLPrimitiveBuffer(GFX, numIndices, numPrimitives, bufferType);
389 buf->registerResourceWithDevice(this);
392 if(data)
394 void* dest;
395 buf->lock(0, numIndices, &dest);
396 dMemcpy(dest, data, sizeof(U16) * numIndices);
397 buf->unlock();
399 return buf;
402 void GFXGLDevice::setVertexStream( U32 stream, GFXVertexBuffer *buffer )
404 AssertFatal(stream <= 1, "GFXGLDevice::setVertexStream only support 2 stream (0: data, 1: instancing)");
406 //if(mCurrentVB[stream] != buffer)
408 // Reset the state the old VB required, then set the state the new VB requires.
409 if( mCurrentVB[stream] )
411 mCurrentVB[stream]->finish();
414 mCurrentVB[stream] = static_cast<GFXGLVertexBuffer*>( buffer );
416 mNeedUpdateVertexAttrib = true;
420 void GFXGLDevice::setVertexStreamFrequency( U32 stream, U32 frequency )
422 if( stream == 0 )
424 mCurrentVB_Divisor[stream] = 0; // non instanced, is vertex buffer
425 mDrawInstancesCount = frequency; // instances count
427 else
429 AssertFatal(frequency <= 1, "GFXGLDevice::setVertexStreamFrequency only support 0/1 for this stream" );
430 if( stream == 1 && frequency == 1 )
431 mCurrentVB_Divisor[stream] = 1; // instances data need a frequency of 1
432 else
433 mCurrentVB_Divisor[stream] = 0;
436 mNeedUpdateVertexAttrib = true;
439 GFXCubemap* GFXGLDevice::createCubemap()
441 GFXGLCubemap* cube = new GFXGLCubemap();
442 cube->registerResourceWithDevice(this);
443 return cube;
446 void GFXGLDevice::endSceneInternal()
448 // nothing to do for opengl
449 mCanCurrentlyRender = false;
452 void GFXGLDevice::clear(U32 flags, ColorI color, F32 z, U32 stencil)
454 // Make sure we have flushed our render target state.
455 _updateRenderTargets();
457 bool writeAllColors = true;
458 bool zwrite = true;
459 bool writeAllStencil = true;
460 const GFXStateBlockDesc *desc = NULL;
461 if (mCurrentGLStateBlock)
463 desc = &mCurrentGLStateBlock->getDesc();
464 zwrite = desc->zWriteEnable;
465 writeAllColors = desc->colorWriteRed && desc->colorWriteGreen && desc->colorWriteBlue && desc->colorWriteAlpha;
466 writeAllStencil = desc->stencilWriteMask == 0xFFFFFFFF;
469 glColorMask(true, true, true, true);
470 glDepthMask(true);
471 glStencilMask(0xFFFFFFFF);
474 ColorF c = color;
475 glClearColor(c.red, c.green, c.blue, c.alpha);
476 glClearDepth(z);
477 glClearStencil(stencil);
479 GLbitfield clearflags = 0;
480 clearflags |= (flags & GFXClearTarget) ? GL_COLOR_BUFFER_BIT : 0;
481 clearflags |= (flags & GFXClearZBuffer) ? GL_DEPTH_BUFFER_BIT : 0;
482 clearflags |= (flags & GFXClearStencil) ? GL_STENCIL_BUFFER_BIT : 0;
484 glClear(clearflags);
486 if(!writeAllColors)
487 glColorMask(desc->colorWriteRed, desc->colorWriteGreen, desc->colorWriteBlue, desc->colorWriteAlpha);
489 if(!zwrite)
490 glDepthMask(false);
492 if(!writeAllStencil)
493 glStencilMask(desc->stencilWriteMask);
496 // Given a primitive type and a number of primitives, return the number of indexes/vertexes used.
497 inline GLsizei GFXGLDevice::primCountToIndexCount(GFXPrimitiveType primType, U32 primitiveCount)
499 switch (primType)
501 case GFXPointList :
502 return primitiveCount;
503 break;
504 case GFXLineList :
505 return primitiveCount * 2;
506 break;
507 case GFXLineStrip :
508 return primitiveCount + 1;
509 break;
510 case GFXTriangleList :
511 return primitiveCount * 3;
512 break;
513 case GFXTriangleStrip :
514 return 2 + primitiveCount;
515 break;
516 case GFXTriangleFan :
517 return 2 + primitiveCount;
518 break;
519 default:
520 AssertFatal(false, "GFXGLDevice::primCountToIndexCount - unrecognized prim type");
521 break;
524 return 0;
527 GFXVertexDecl* GFXGLDevice::allocVertexDecl( const GFXVertexFormat *vertexFormat )
529 typedef Map<void*, GFXGLVertexDecl> GFXGLVertexDeclMap;
530 static GFXGLVertexDeclMap declMap;
531 GFXGLVertexDeclMap::Iterator itr = declMap.find( (void*)vertexFormat->getDescription().c_str() ); // description string are interned, safe to use c_str()
532 if(itr != declMap.end())
533 return &itr->value;
535 GFXGLVertexDecl &decl = declMap[(void*)vertexFormat->getDescription().c_str()];
536 decl.init(vertexFormat);
537 return &decl;
540 void GFXGLDevice::setVertexDecl( const GFXVertexDecl *decl )
542 static_cast<const GFXGLVertexDecl*>(decl)->prepareVertexFormat();
545 inline void GFXGLDevice::preDrawPrimitive()
547 if( mStateDirty )
549 updateStates();
552 if(mCurrentShaderConstBuffer)
553 setShaderConstBufferInternal(mCurrentShaderConstBuffer);
555 if( mNeedUpdateVertexAttrib )
557 AssertFatal(mCurrVertexDecl, "");
558 const GFXGLVertexDecl* decl = static_cast<const GFXGLVertexDecl*>(mCurrVertexDecl);
560 for(int i = 0; i < getNumVertexStreams(); ++i)
562 if(mCurrentVB[i])
564 mCurrentVB[i]->prepare(i, mCurrentVB_Divisor[i]); // GL_ARB_vertex_attrib_binding
565 decl->prepareBuffer_old( i, mCurrentVB[i]->mBuffer, mCurrentVB_Divisor[i] ); // old vertex buffer/format
569 decl->updateActiveVertexAttrib( GFXGL->getOpenglCache()->getCacheVertexAttribActive() );
572 mNeedUpdateVertexAttrib = false;
575 inline void GFXGLDevice::postDrawPrimitive(U32 primitiveCount)
577 mDeviceStatistics.mDrawCalls++;
578 mDeviceStatistics.mPolyCount += primitiveCount;
581 void GFXGLDevice::drawPrimitive( GFXPrimitiveType primType, U32 vertexStart, U32 primitiveCount )
583 preDrawPrimitive();
585 vertexStart += mCurrentVB[0]->mBufferVertexOffset;
587 if(mDrawInstancesCount)
588 glDrawArraysInstanced(GFXGLPrimType[primType], vertexStart, primCountToIndexCount(primType, primitiveCount), mDrawInstancesCount);
589 else
590 glDrawArrays(GFXGLPrimType[primType], vertexStart, primCountToIndexCount(primType, primitiveCount));
592 postDrawPrimitive(primitiveCount);
595 void GFXGLDevice::drawIndexedPrimitive( GFXPrimitiveType primType,
596 U32 startVertex,
597 U32 minIndex,
598 U32 numVerts,
599 U32 startIndex,
600 U32 primitiveCount )
602 AssertFatal( startVertex == 0, "GFXGLDevice::drawIndexedPrimitive() - Non-zero startVertex unsupported!" );
604 preDrawPrimitive();
606 U16* buf = (U16*)static_cast<GFXGLPrimitiveBuffer*>(mCurrentPrimitiveBuffer.getPointer())->getBuffer() + startIndex;
608 const U32 baseVertex = mCurrentVB[0]->mBufferVertexOffset;
610 if(mDrawInstancesCount)
611 glDrawElementsInstancedBaseVertex(GFXGLPrimType[primType], primCountToIndexCount(primType, primitiveCount), GL_UNSIGNED_SHORT, buf, mDrawInstancesCount, baseVertex);
612 else
613 glDrawElementsBaseVertex(GFXGLPrimType[primType], primCountToIndexCount(primType, primitiveCount), GL_UNSIGNED_SHORT, buf, baseVertex);
615 postDrawPrimitive(primitiveCount);
618 void GFXGLDevice::setPB(GFXGLPrimitiveBuffer* pb)
620 if(mCurrentPB)
621 mCurrentPB->finish();
622 mCurrentPB = pb;
625 void GFXGLDevice::setLightInternal(U32 lightStage, const GFXLightInfo light, bool lightEnable)
627 // ONLY NEEDED ON FFP
630 void GFXGLDevice::setLightMaterialInternal(const GFXLightMaterial mat)
632 // ONLY NEEDED ON FFP
635 void GFXGLDevice::setGlobalAmbientInternal(ColorF color)
637 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, (GLfloat*)&color);
640 void GFXGLDevice::setTextureInternal(U32 textureUnit, const GFXTextureObject*texture)
642 GFXGLTextureObject *tex = static_cast<GFXGLTextureObject*>(const_cast<GFXTextureObject*>(texture));
643 if (tex)
645 mActiveTextureType[textureUnit] = tex->getBinding();
646 tex->bind(textureUnit);
648 else if(mActiveTextureType[textureUnit] != GL_ZERO)
650 glActiveTexture(GL_TEXTURE0 + textureUnit);
651 glBindTexture(mActiveTextureType[textureUnit], 0);
652 getOpenglCache()->setCacheBindedTex(textureUnit, mActiveTextureType[textureUnit], 0);
653 mActiveTextureType[textureUnit] = GL_ZERO;
657 void GFXGLDevice::setCubemapInternal(U32 textureUnit, const GFXGLCubemap* texture)
659 if(texture)
661 mActiveTextureType[textureUnit] = GL_TEXTURE_CUBE_MAP;
662 texture->bind(textureUnit);
664 else if(mActiveTextureType[textureUnit] != GL_ZERO)
666 glActiveTexture(GL_TEXTURE0 + textureUnit);
667 glBindTexture(mActiveTextureType[textureUnit], 0);
668 getOpenglCache()->setCacheBindedTex(textureUnit, mActiveTextureType[textureUnit], 0);
669 mActiveTextureType[textureUnit] = GL_ZERO;
673 void GFXGLDevice::setMatrix( GFXMatrixType mtype, const MatrixF &mat )
675 // ONLY NEEDED ON FFP
678 void GFXGLDevice::setClipRect( const RectI &inRect )
680 AssertFatal(mCurrentRT.isValid(), "GFXGLDevice::setClipRect - must have a render target set to do any rendering operations!");
682 // Clip the rect against the renderable size.
683 Point2I size = mCurrentRT->getSize();
684 RectI maxRect(Point2I(0,0), size);
685 mClip = inRect;
686 mClip.intersect(maxRect);
688 // Create projection matrix. See http://www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/ortho.html
689 const F32 left = mClip.point.x;
690 const F32 right = mClip.point.x + mClip.extent.x;
691 const F32 bottom = mClip.extent.y;
692 const F32 top = 0.0f;
693 const F32 near = 0.0f;
694 const F32 far = 1.0f;
696 const F32 tx = -(right + left)/(right - left);
697 const F32 ty = -(top + bottom)/(top - bottom);
698 const F32 tz = -(far + near)/(far - near);
700 static Point4F pt;
701 pt.set(2.0f / (right - left), 0.0f, 0.0f, 0.0f);
702 mProjectionMatrix.setColumn(0, pt);
704 pt.set(0.0f, 2.0f/(top - bottom), 0.0f, 0.0f);
705 mProjectionMatrix.setColumn(1, pt);
707 pt.set(0.0f, 0.0f, -2.0f/(far - near), 0.0f);
708 mProjectionMatrix.setColumn(2, pt);
710 pt.set(tx, ty, tz, 1.0f);
711 mProjectionMatrix.setColumn(3, pt);
713 // Translate projection matrix.
714 static MatrixF translate(true);
715 pt.set(0.0f, -mClip.point.y, 0.0f, 1.0f);
716 translate.setColumn(3, pt);
718 mProjectionMatrix *= translate;
720 setMatrix(GFXMatrixProjection, mProjectionMatrix);
722 MatrixF mTempMatrix(true);
723 setViewMatrix( mTempMatrix );
724 setWorldMatrix( mTempMatrix );
726 // Set the viewport to the clip rect
727 RectI viewport(mClip.point.x, mClip.point.y, mClip.extent.x, mClip.extent.y);
728 setViewport(viewport);
731 /// Creates a state block object based on the desc passed in. This object
732 /// represents an immutable state.
733 GFXStateBlockRef GFXGLDevice::createStateBlockInternal(const GFXStateBlockDesc& desc)
735 return GFXStateBlockRef(new GFXGLStateBlock(desc));
738 /// Activates a stateblock
739 void GFXGLDevice::setStateBlockInternal(GFXStateBlock* block, bool force)
741 AssertFatal(dynamic_cast<GFXGLStateBlock*>(block), "GFXGLDevice::setStateBlockInternal - Incorrect stateblock type for this device!");
742 GFXGLStateBlock* glBlock = static_cast<GFXGLStateBlock*>(block);
743 GFXGLStateBlock* glCurrent = static_cast<GFXGLStateBlock*>(mCurrentStateBlock.getPointer());
744 if (force)
745 glCurrent = NULL;
747 glBlock->activate(glCurrent); // Doesn't use current yet.
748 mCurrentGLStateBlock = glBlock;
751 //------------------------------------------------------------------------------
753 GFXTextureTarget * GFXGLDevice::allocRenderToTextureTarget()
755 GFXGLTextureTarget *targ = new GFXGLTextureTarget();
756 targ->registerResourceWithDevice(this);
757 return targ;
760 GFXFence * GFXGLDevice::createFence()
762 GFXFence* fence = _createPlatformSpecificFence();
763 if(!fence)
764 fence = new GFXGeneralFence( this );
766 fence->registerResourceWithDevice(this);
767 return fence;
770 GFXOcclusionQuery* GFXGLDevice::createOcclusionQuery()
772 GFXOcclusionQuery *query = new GFXGLOcclusionQuery( this );
773 query->registerResourceWithDevice(this);
774 return query;
777 void GFXGLDevice::setupGenericShaders( GenericShaderType type )
779 AssertFatal(type != GSTargetRestore, "");
781 if( mGenericShader[GSColor] == NULL )
783 ShaderData *shaderData;
785 shaderData = new ShaderData();
786 shaderData->setField("OGLVertexShaderFile", "shaders/common/fixedFunction/gl/colorV.glsl");
787 shaderData->setField("OGLPixelShaderFile", "shaders/common/fixedFunction/gl/colorP.glsl");
788 shaderData->setField("pixVersion", "2.0");
789 shaderData->registerObject();
790 mGenericShader[GSColor] = shaderData->getShader();
791 mGenericShaderBuffer[GSColor] = mGenericShader[GSColor]->allocConstBuffer();
792 mModelViewProjSC[GSColor] = mGenericShader[GSColor]->getShaderConstHandle( "$modelView" );
794 shaderData = new ShaderData();
795 shaderData->setField("OGLVertexShaderFile", "shaders/common/fixedFunction/gl/modColorTextureV.glsl");
796 shaderData->setField("OGLPixelShaderFile", "shaders/common/fixedFunction/gl/modColorTextureP.glsl");
797 shaderData->setSamplerName("$diffuseMap", 0);
798 shaderData->setField("pixVersion", "2.0");
799 shaderData->registerObject();
800 mGenericShader[GSModColorTexture] = shaderData->getShader();
801 mGenericShaderBuffer[GSModColorTexture] = mGenericShader[GSModColorTexture]->allocConstBuffer();
802 mModelViewProjSC[GSModColorTexture] = mGenericShader[GSModColorTexture]->getShaderConstHandle( "$modelView" );
804 shaderData = new ShaderData();
805 shaderData->setField("OGLVertexShaderFile", "shaders/common/fixedFunction/gl/addColorTextureV.glsl");
806 shaderData->setField("OGLPixelShaderFile", "shaders/common/fixedFunction/gl/addColorTextureP.glsl");
807 shaderData->setSamplerName("$diffuseMap", 0);
808 shaderData->setField("pixVersion", "2.0");
809 shaderData->registerObject();
810 mGenericShader[GSAddColorTexture] = shaderData->getShader();
811 mGenericShaderBuffer[GSAddColorTexture] = mGenericShader[GSAddColorTexture]->allocConstBuffer();
812 mModelViewProjSC[GSAddColorTexture] = mGenericShader[GSAddColorTexture]->getShaderConstHandle( "$modelView" );
814 shaderData = new ShaderData();
815 shaderData->setField("OGLVertexShaderFile", "shaders/common/fixedFunction/gl/textureV.glsl");
816 shaderData->setField("OGLPixelShaderFile", "shaders/common/fixedFunction/gl/textureP.glsl");
817 shaderData->setSamplerName("$diffuseMap", 0);
818 shaderData->setField("pixVersion", "2.0");
819 shaderData->registerObject();
820 mGenericShader[GSTexture] = shaderData->getShader();
821 mGenericShaderBuffer[GSTexture] = mGenericShader[GSTexture]->allocConstBuffer();
822 mModelViewProjSC[GSTexture] = mGenericShader[GSTexture]->getShaderConstHandle( "$modelView" );
825 MatrixF tempMatrix = mProjectionMatrix * mViewMatrix * mWorldMatrix[mWorldStackSize];
826 mGenericShaderBuffer[type]->setSafe(mModelViewProjSC[type], tempMatrix);
828 setShader( mGenericShader[type] );
829 setShaderConstBuffer( mGenericShaderBuffer[type] );
831 GFXShader* GFXGLDevice::createShader()
833 GFXGLShader* shader = new GFXGLShader();
834 shader->registerResourceWithDevice( this );
835 return shader;
838 void GFXGLDevice::setShader(GFXShader *shader, bool force)
840 if(mCurrentShader == shader && !force)
841 return;
843 if ( shader )
845 GFXGLShader *glShader = static_cast<GFXGLShader*>( shader );
846 glShader->useProgram();
847 mCurrentShader = shader;
849 else
851 setupGenericShaders();
855 void GFXGLDevice::setShaderConstBufferInternal(GFXShaderConstBuffer* buffer)
857 static_cast<GFXGLShaderConstBuffer*>(buffer)->activate();
860 U32 GFXGLDevice::getNumSamplers() const
862 return getMin((U32)TEXTURE_STAGE_COUNT,mPixelShaderVersion > 0.001f ? mMaxShaderTextures : mMaxFFTextures);
865 GFXTextureObject* GFXGLDevice::getDefaultDepthTex() const
867 if(mWindowRT && mWindowRT->getPointer())
868 return static_cast<GFXGLWindowTarget*>( mWindowRT->getPointer() )->mBackBufferDepthTex.getPointer();
870 return NULL;
873 U32 GFXGLDevice::getNumRenderTargets() const
875 return mMaxTRColors;
878 void GFXGLDevice::_updateRenderTargets()
880 if ( mRTDirty || mCurrentRT->isPendingState() )
882 if ( mRTDeactivate )
884 mRTDeactivate->deactivate();
885 mRTDeactivate = NULL;
888 // NOTE: The render target changes is not really accurate
889 // as the GFXTextureTarget supports MRT internally. So when
890 // we activate a GFXTarget it could result in multiple calls
891 // to SetRenderTarget on the actual device.
892 mDeviceStatistics.mRenderTargetChanges++;
894 GFXGLTextureTarget *tex = dynamic_cast<GFXGLTextureTarget*>( mCurrentRT.getPointer() );
895 if ( tex )
897 tex->applyState();
898 tex->makeActive();
900 else
902 GFXGLWindowTarget *win = dynamic_cast<GFXGLWindowTarget*>( mCurrentRT.getPointer() );
903 AssertFatal( win != NULL,
904 "GFXGLDevice::_updateRenderTargets() - invalid target subclass passed!" );
906 win->makeActive();
908 if( win->mContext != static_cast<GFXGLDevice*>(GFX)->mContext )
910 mRTDirty = false;
911 GFX->updateStates(true);
915 mRTDirty = false;
918 if ( mViewportDirty )
920 glViewport( mViewport.point.x, mViewport.point.y, mViewport.extent.x, mViewport.extent.y );
921 mViewportDirty = false;
925 GFXFormat GFXGLDevice::selectSupportedFormat( GFXTextureProfile* profile,
926 const Vector<GFXFormat>& formats,
927 bool texture,
928 bool mustblend,
929 bool mustfilter )
931 for(U32 i = 0; i < formats.size(); i++)
933 // Single channel textures are not supported by FBOs.
934 if(profile->testFlag(GFXTextureProfile::RenderTarget) && (formats[i] == GFXFormatA8 || formats[i] == GFXFormatL8 || formats[i] == GFXFormatL16))
935 continue;
936 if(GFXGLTextureInternalFormat[formats[i]] == GL_ZERO)
937 continue;
939 return formats[i];
942 return GFXFormatR8G8B8A8;
945 U32 GFXGLDevice::getTotalVideoMemory_GL_EXT()
947 // Source: http://www.opengl.org/registry/specs/ATI/meminfo.txt
948 if( gglHasExtension(ATI_meminfo) )
950 GLint mem[4] = {0};
951 glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI, mem); // Retrieve the texture pool
953 /* With mem[0] i get only the total memory free in the pool in KB
955 * mem[0] - total memory free in the pool
956 * mem[1] - largest available free block in the pool
957 * mem[2] - total auxiliary memory free
958 * mem[3] - largest auxiliary free block
961 return mem[0] / 1024;
964 //source http://www.opengl.org/registry/specs/NVX/gpu_memory_info.txt
965 else if( gglHasExtension(NVX_gpu_memory_info) )
967 GLint mem = 0;
968 glGetIntegerv(GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX, &mem);
969 return mem / 1024;
972 // TODO OPENGL, add supprt for INTEL cards.
974 return 0;
978 // Register this device with GFXInit
980 class GFXGLRegisterDevice
982 public:
983 GFXGLRegisterDevice()
985 GFXInit::getRegisterDeviceSignal().notify(&GFXGLDevice::enumerateAdapters);
989 static GFXGLRegisterDevice pGLRegisterDevice;
991 ConsoleFunction(cycleResources, void, 1, 1, "")
993 static_cast<GFXGLDevice*>(GFX)->zombify();
994 static_cast<GFXGLDevice*>(GFX)->resurrect();