1 //-----------------------------------------------------------------------------
2 // Copyright (c) 2012 GarageGames, LLC
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
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
);
59 extern void gglPerformBinds();
60 extern void gglPerformExtensionBinds(void *context
);
65 static bool coreLoaded
= false; // Guess what this is for.
70 // Make sure we've got our GL bindings.
71 GL::gglPerformBinds();
74 void loadGLExtensions(void *context
)
76 static bool extensionsLoaded
= false;
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
)
118 else if( GFXGL
->getOpenglCache()->getCacheBinded( target
) == framebuffer
)
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
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
)
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;
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
,
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
);
187 PlatformGL::setVSync(smDisableVSync
? 0 : 1);
189 //OpenGL 3 need a binded VAO for render
191 glGenVertexArrays(1, &vao
);
192 glBindVertexArray(vao
);
195 GFXGLDevice::GFXGLDevice(U32 adapterIndex
) :
196 mAdapterIndex(adapterIndex
),
198 mDrawInstancesCount(0),
199 m_mCurrentWorld(true),
200 m_mCurrentView(true),
203 mPixelShaderVersion(0.0f
),
204 mMaxShaderTextures(2),
208 mCurrentShader( NULL
),
209 mNeedUpdateVertexAttrib(false),
213 for(int i
= 0; i
< VERTEX_STREAM_COUNT
; ++i
)
215 mCurrentVB
[i
] = NULL
;
216 mCurrentVB_Divisor
[i
] = 0;
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
;
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
;
268 if( mTextureManager
)
270 mTextureManager
->zombify();
271 mTextureManager
->kill();
274 GFXResource
* walk
= mResourceListHead
;
278 walk
= walk
->getNextResource();
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
)
295 mCurrentVB
[i
]->finish();
297 mCurrentPB
->finish();
299 //mVolatileVBs.clear();
300 //mVolatilePBs.clear();
301 GFXResource
* walk
= mResourceListHead
;
305 walk
= walk
->getNextResource();
309 void GFXGLDevice::resurrect()
311 GFXResource
* walk
= mResourceListHead
;
315 walk
= walk
->getNextResource();
317 for(int i
= 0; i
< VERTEX_STREAM_COUNT
; ++i
)
319 mCurrentVB
[i
]->prepare();
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
,
358 GFXBufferType bufferType
,
361 if(bufferType
== GFXBufferTypeVolatile
)
362 return findVolatileVBO(numVerts
, vertexFormat
, vertSize
);
364 GFXGLVertexBuffer
* buf
= new GFXGLVertexBuffer( GFX
, numVerts
, vertexFormat
, vertSize
, bufferType
);
365 buf
->registerResourceWithDevice(this);
370 buf
->lock(0, numVerts
, &dest
);
371 dMemcpy(dest
, data
, vertSize
* numVerts
);
378 GFXPrimitiveBuffer
*GFXGLDevice::allocPrimitiveBuffer( U32 numIndices
, U32 numPrimitives
, GFXBufferType bufferType
, void* data
)
380 GFXPrimitiveBuffer
* buf
;
382 if(bufferType
== GFXBufferTypeVolatile
)
384 buf
= findVolatilePBO(numIndices
, numPrimitives
);
388 buf
= new GFXGLPrimitiveBuffer(GFX
, numIndices
, numPrimitives
, bufferType
);
389 buf
->registerResourceWithDevice(this);
395 buf
->lock(0, numIndices
, &dest
);
396 dMemcpy(dest
, data
, sizeof(U16
) * numIndices
);
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
)
424 mCurrentVB_Divisor
[stream
] = 0; // non instanced, is vertex buffer
425 mDrawInstancesCount
= frequency
; // instances count
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
433 mCurrentVB_Divisor
[stream
] = 0;
436 mNeedUpdateVertexAttrib
= true;
439 GFXCubemap
* GFXGLDevice::createCubemap()
441 GFXGLCubemap
* cube
= new GFXGLCubemap();
442 cube
->registerResourceWithDevice(this);
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;
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);
471 glStencilMask(0xFFFFFFFF);
475 glClearColor(c
.red
, c
.green
, c
.blue
, c
.alpha
);
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;
487 glColorMask(desc
->colorWriteRed
, desc
->colorWriteGreen
, desc
->colorWriteBlue
, desc
->colorWriteAlpha
);
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
)
502 return primitiveCount
;
505 return primitiveCount
* 2;
508 return primitiveCount
+ 1;
510 case GFXTriangleList
:
511 return primitiveCount
* 3;
513 case GFXTriangleStrip
:
514 return 2 + primitiveCount
;
516 case GFXTriangleFan
:
517 return 2 + primitiveCount
;
520 AssertFatal(false, "GFXGLDevice::primCountToIndexCount - unrecognized prim type");
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())
535 GFXGLVertexDecl
&decl
= declMap
[(void*)vertexFormat
->getDescription().c_str()];
536 decl
.init(vertexFormat
);
540 void GFXGLDevice::setVertexDecl( const GFXVertexDecl
*decl
)
542 static_cast<const GFXGLVertexDecl
*>(decl
)->prepareVertexFormat();
545 inline void GFXGLDevice::preDrawPrimitive()
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
)
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
)
585 vertexStart
+= mCurrentVB
[0]->mBufferVertexOffset
;
587 if(mDrawInstancesCount
)
588 glDrawArraysInstanced(GFXGLPrimType
[primType
], vertexStart
, primCountToIndexCount(primType
, primitiveCount
), mDrawInstancesCount
);
590 glDrawArrays(GFXGLPrimType
[primType
], vertexStart
, primCountToIndexCount(primType
, primitiveCount
));
592 postDrawPrimitive(primitiveCount
);
595 void GFXGLDevice::drawIndexedPrimitive( GFXPrimitiveType primType
,
602 AssertFatal( startVertex
== 0, "GFXGLDevice::drawIndexedPrimitive() - Non-zero startVertex unsupported!" );
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
);
613 glDrawElementsBaseVertex(GFXGLPrimType
[primType
], primCountToIndexCount(primType
, primitiveCount
), GL_UNSIGNED_SHORT
, buf
, baseVertex
);
615 postDrawPrimitive(primitiveCount
);
618 void GFXGLDevice::setPB(GFXGLPrimitiveBuffer
* pb
)
621 mCurrentPB
->finish();
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
));
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
)
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
);
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
);
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());
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);
760 GFXFence
* GFXGLDevice::createFence()
762 GFXFence
* fence
= _createPlatformSpecificFence();
764 fence
= new GFXGeneralFence( this );
766 fence
->registerResourceWithDevice(this);
770 GFXOcclusionQuery
* GFXGLDevice::createOcclusionQuery()
772 GFXOcclusionQuery
*query
= new GFXGLOcclusionQuery( this );
773 query
->registerResourceWithDevice(this);
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 );
838 void GFXGLDevice::setShader(GFXShader
*shader
, bool force
)
840 if(mCurrentShader
== shader
&& !force
)
845 GFXGLShader
*glShader
= static_cast<GFXGLShader
*>( shader
);
846 glShader
->useProgram();
847 mCurrentShader
= shader
;
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();
873 U32
GFXGLDevice::getNumRenderTargets() const
878 void GFXGLDevice::_updateRenderTargets()
880 if ( mRTDirty
|| mCurrentRT
->isPendingState() )
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() );
902 GFXGLWindowTarget
*win
= dynamic_cast<GFXGLWindowTarget
*>( mCurrentRT
.getPointer() );
903 AssertFatal( win
!= NULL
,
904 "GFXGLDevice::_updateRenderTargets() - invalid target subclass passed!" );
908 if( win
->mContext
!= static_cast<GFXGLDevice
*>(GFX
)->mContext
)
911 GFX
->updateStates(true);
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
,
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
))
936 if(GFXGLTextureInternalFormat
[formats
[i
]] == GL_ZERO
)
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
) )
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
) )
968 glGetIntegerv(GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX
, &mem
);
972 // TODO OPENGL, add supprt for INTEL cards.
978 // Register this device with GFXInit
980 class GFXGLRegisterDevice
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();