gfxGLDevice.cpp
Engine/source/gfx/gl/gfxGLDevice.cpp
Classes:
class
Namespaces:
namespace
Public Variables
Public Functions
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
