Example #1
0
U32 GFXGLDevice::getTotalVideoMemory_GL_EXT()
{
   // Source: http://www.opengl.org/registry/specs/ATI/meminfo.txt
   if( gglHasExtension(ATI_meminfo) )
   {
      GLint mem[4] = {0};
      glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI, mem);  // Retrieve the texture pool
      
      /* With mem[0] i get only the total memory free in the pool in KB
      *
      * mem[0] - total memory free in the pool
      * mem[1] - largest available free block in the pool
      * mem[2] - total auxiliary memory free
      * mem[3] - largest auxiliary free block
      */

      return  mem[0] / 1024;
   }
   
   //source http://www.opengl.org/registry/specs/NVX/gpu_memory_info.txt
   else if( gglHasExtension(NVX_gpu_memory_info) )
   {
      GLint mem = 0;
      glGetIntegerv(GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX, &mem);
      return mem / 1024;
   }

   // TODO OPENGL, add supprt for INTEL cards.
   
   return 0;
}
void GFXGLWindowTarget::resolveTo(GFXTextureObject* obj)
{
   AssertFatal(dynamic_cast<GFXGLTextureObject*>(obj), "GFXGLTextureTarget::resolveTo - Incorrect type of texture, expected a GFXGLTextureObject");
   GFXGLTextureObject* glTexture = static_cast<GFXGLTextureObject*>(obj);

   if( gglHasExtension(ARB_copy_image) )
   {
      if(mBackBufferColorTex.getWidth() == glTexture->getWidth()
         && mBackBufferColorTex.getHeight() == glTexture->getHeight()
         && mBackBufferColorTex.getFormat() == glTexture->getFormat())
      {
         glCopyImageSubData(
           static_cast<GFXGLTextureObject*>(mBackBufferColorTex.getPointer())->getHandle(), GL_TEXTURE_2D, 0, 0, 0, 0,
           glTexture->getHandle(), GL_TEXTURE_2D, 0, 0, 0, 0,
           getSize().x, getSize().y, 1);
         return;
      }
   }

   PRESERVE_FRAMEBUFFER();

   if(!mCopyFBO)
   {
      glGenFramebuffers(1, &mCopyFBO);
   }
   
   glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mCopyFBO);
   glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, glTexture->getHandle(), 0);
   
   glBindFramebuffer(GL_READ_FRAMEBUFFER, mBackBufferFBO);
   
   glBlitFramebuffer(0, 0, getSize().x, getSize().y,
      0, 0, glTexture->getWidth(), glTexture->getHeight(), GL_COLOR_BUFFER_BIT, GL_NEAREST);
}
GFXGLStateBlock::GFXGLStateBlock(const GFXStateBlockDesc& desc) :
   mDesc(desc),
   mCachedHashValue(desc.getHashValue())
{
    if( !gglHasExtension(ARB_sampler_objects) )
	   return;

   static Map<GFXSamplerStateDesc, U32> mSamplersMap;

	for(int i = 0; i < TEXTURE_STAGE_COUNT; ++i)
	{
		GLuint &id = mSamplerObjects[i];
		GFXSamplerStateDesc &ssd = mDesc.samplers[i];
      Map<GFXSamplerStateDesc, U32>::Iterator itr =  mSamplersMap.find(ssd);
      if(itr == mSamplersMap.end())
      {
		   glGenSamplers(1, &id);

		   glSamplerParameteri(id, GL_TEXTURE_MIN_FILTER, minificationFilter(ssd.minFilter, ssd.mipFilter, 1) );
		   glSamplerParameteri(id, GL_TEXTURE_MAG_FILTER, GFXGLTextureFilter[ssd.magFilter]);
		   glSamplerParameteri(id, GL_TEXTURE_WRAP_S, GFXGLTextureAddress[ssd.addressModeU]);
		   glSamplerParameteri(id, GL_TEXTURE_WRAP_T, GFXGLTextureAddress[ssd.addressModeV]);
		   glSamplerParameteri(id, GL_TEXTURE_WRAP_R, GFXGLTextureAddress[ssd.addressModeW]);
		   if(static_cast< GFXGLDevice* >( GFX )->supportsAnisotropic() )
			   glSamplerParameterf(id, GL_TEXTURE_MAX_ANISOTROPY_EXT, ssd.maxAnisotropy);

         mSamplersMap[ssd] = id;
      }
      else
         id = itr->value;
	}
}
void GFXGLCardProfiler::setupCardCapabilities()
{
   GLint maxTexSize;
   glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTexSize);

   const char* versionString = reinterpret_cast<const char*>(glGetString(GL_VERSION));
   F32 glVersion = dAtof(versionString);
   
   // OpenGL doesn't have separate maximum width/height.
   setCapability("maxTextureWidth", maxTexSize);
   setCapability("maxTextureHeight", maxTexSize);
   setCapability("maxTextureSize", maxTexSize);

   // If extensions haven't been inited, we're in trouble here.
   bool suppVBO = (gglHasExtension(GL_ARB_vertex_buffer_object) || glVersion >= 1.499f);
   setCapability("GL::suppVertexBufferObject", suppVBO);

   // check if render to texture supported is available
   bool suppRTT = gglHasExtension(GL_EXT_framebuffer_object);
   setCapability("GL::suppRenderTexture", suppRTT);
   
   bool suppBlit = gglHasExtension(GL_EXT_framebuffer_blit);
   setCapability("GL::suppRTBlit", suppBlit);
   
   bool suppFloatTex = gglHasExtension(GL_ATI_texture_float);
   setCapability("GL::suppFloatTexture", suppFloatTex);

   // Check for anisotropic filtering support.
   bool suppAnisotropic = gglHasExtension( GL_EXT_texture_filter_anisotropic );
   setCapability( "GL::suppAnisotropic", suppAnisotropic );
   
   // Check to see if mipmap lod bias is supported
   bool suppMipLodBias = gglHasExtension(GL_EXT_texture_lod_bias);
   setCapability("GL::suppMipLodBias", suppMipLodBias);

   // check to see if we have the fragment shader extension or the gl version is high enough for glsl to be core
   // also check to see if the language version is high enough
   F32 glslVersion = dAtof(reinterpret_cast<const char*>(glGetString( GL_SHADING_LANGUAGE_VERSION)));
   bool suppSPU = (gglHasExtension(GL_ARB_fragment_shader) || glVersion >= 1.999f) && glslVersion >= 1.0999;
   setCapability("GL::suppFragmentShader", suppSPU);
   
   bool suppAppleFence = gglHasExtension(GL_APPLE_fence);
   setCapability("GL::APPLE::suppFence", suppAppleFence);
   
   // When enabled, call glGenerateMipmapEXT() to generate mipmaps instead of relying on GL_GENERATE_MIPMAP
   setCapability("GL::Workaround::needsExplicitGenerateMipmap", false);
   // When enabled, binds and unbinds a texture target before doing the depth buffer copy.  Failure to do
   // so will cause a hard freeze on Mac OS 10.4 with a Radeon X1600
   setCapability("GL::Workaround::X1600DepthBufferCopy", false);
   // When enabled, does not copy the last column and row of the depth buffer in a depth buffer copy.  Failure
   // to do so will cause a kernel panic on Mac OS 10.5(.1) with a Radeon HD 2600 (fixed in 10.5.2)
   setCapability("GL::Workaround::HD2600DepthBufferCopy", false);
   
   // Certain Intel drivers have a divide by 0 crash if mipmaps are specified with
   // glTexSubImage2D.
   setCapability("GL::Workaround::noManualMips", false);
}
void GFXGLTextureObject::bind(U32 textureUnit)
{
   glActiveTexture(GL_TEXTURE0 + textureUnit);
   glBindTexture(mBinding, mHandle);
   GFXGL->getOpenglCache()->setCacheBindedTex(textureUnit, mBinding, mHandle);

   if( gglHasExtension(ARB_sampler_objects) )
	   return;
  
   GFXGLStateBlockRef sb = mGLDevice->getCurrentStateBlock();
   AssertFatal(sb, "GFXGLTextureObject::bind - No active stateblock!");
   if (!sb)
      return;
         
   const GFXSamplerStateDesc ssd = sb->getDesc().samplers[textureUnit];

   if(mNeedInitSamplerState)
   {
      initSamplerState(ssd);
      return;
   }

   if(mSampler.minFilter != ssd.minFilter || mSampler.mipFilter != ssd.mipFilter)
      glTexParameteri(mBinding, GL_TEXTURE_MIN_FILTER, minificationFilter(ssd.minFilter, ssd.mipFilter, mMipLevels));
   if(mSampler.magFilter != ssd.magFilter)
      glTexParameteri(mBinding, GL_TEXTURE_MAG_FILTER, GFXGLTextureFilter[ssd.magFilter]);
   if(mSampler.addressModeU != ssd.addressModeU)
      glTexParameteri(mBinding, GL_TEXTURE_WRAP_S, !mIsNPoT2 ? GFXGLTextureAddress[ssd.addressModeU] : GL_CLAMP_TO_EDGE);
   if(mSampler.addressModeV != ssd.addressModeV)
      glTexParameteri(mBinding, GL_TEXTURE_WRAP_T, !mIsNPoT2 ? GFXGLTextureAddress[ssd.addressModeV] : GL_CLAMP_TO_EDGE);
   if(mBinding == GL_TEXTURE_3D && mSampler.addressModeW != ssd.addressModeW )
      glTexParameteri(mBinding, GL_TEXTURE_WRAP_R, GFXGLTextureAddress[ssd.addressModeW]);
   if(mSampler.maxAnisotropy != ssd.maxAnisotropy  && static_cast< GFXGLDevice* >( GFX )->supportsAnisotropic() )
      glTexParameterf(mBinding, GL_TEXTURE_MAX_ANISOTROPY_EXT, ssd.maxAnisotropy);

   mSampler = ssd;
}
Example #6
0
void GFXGLCardProfiler::setupCardCapabilities()
{
   GLint maxTexSize;
   glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTexSize);
   
   // OpenGL doesn't have separate maximum width/height.
   setCapability("maxTextureWidth", maxTexSize);
   setCapability("maxTextureHeight", maxTexSize);
   setCapability("maxTextureSize", maxTexSize);

   // Check for anisotropic filtering support.
   setCapability("GL_EXT_texture_filter_anisotropic", gglHasExtension(EXT_texture_filter_anisotropic));

   // Check for buffer storage
#ifdef TORQUE_NSIGHT_WORKAROUND
   setCapability("GL_ARB_buffer_storage", false);
#else
   setCapability("GL_ARB_buffer_storage", gglHasExtension(ARB_buffer_storage));
#endif

   // Check for shader model 5.0
   setCapability("GL_ARB_gpu_shader5", gglHasExtension(ARB_gpu_shader5));

   // Check for texture storage
   setCapability("GL_ARB_texture_storage", gglHasExtension(ARB_texture_storage));

   // Check for sampler objects
   setCapability("GL_ARB_sampler_objects", gglHasExtension(ARB_sampler_objects));

   // Check for copy image support
   setCapability("GL_ARB_copy_image", gglHasExtension(ARB_copy_image));

   // Check for vertex attrib binding
   setCapability("GL_ARB_vertex_attrib_binding", gglHasExtension(ARB_vertex_attrib_binding));    

}
Example #7
0
bool GFXGLShader::_loadShaderFromStream(  GLuint shader, 
                                          const Torque::Path &path, 
                                          FileStream *s, 
                                          const Vector<GFXShaderMacro> &macros )
{
   Vector<char*> buffers;
   Vector<U32> lengths;
   
   // The GLSL version declaration must go first!
   const char *versionDecl = "#version 150\r\n";
   buffers.push_back( dStrdup( versionDecl ) );
   lengths.push_back( dStrlen( versionDecl ) );

   if(gglHasExtension(EXT_gpu_shader4))
   {
      const char *extension = "#extension GL_EXT_gpu_shader4 : enable\r\n";
      buffers.push_back( dStrdup( extension ) );
      lengths.push_back( dStrlen( extension ) );
   }

   if(gglHasExtension(ARB_gpu_shader5))
   {
      const char *extension = "#extension GL_ARB_gpu_shader5 : enable\r\n";
      buffers.push_back( dStrdup( extension ) );
      lengths.push_back( dStrlen( extension ) );
   }

   const char *newLine = "\r\n";
   buffers.push_back( dStrdup( newLine ) );
   lengths.push_back( dStrlen( newLine ) );

   // Now add all the macros.
   for( U32 i = 0; i < macros.size(); i++ )
   {
      if(macros[i].name.isEmpty())  // TODO OPENGL
         continue;

      String define = String::ToString( "#define %s %s\n", macros[i].name.c_str(), macros[i].value.c_str() );
      buffers.push_back( dStrdup( define.c_str() ) );
      lengths.push_back( define.length() );
   }
   
   // Now finally add the shader source.
   U32 shaderLen = s->getStreamSize();
   char *buffer = _handleIncludes(path, s);
   if ( !buffer )
      return false;
   
   buffers.push_back(buffer);
   lengths.push_back(shaderLen);
   
   glShaderSource(shader, buffers.size(), (const GLchar**)const_cast<const char**>(buffers.address()), NULL);

#if defined(TORQUE_DEBUG) && defined(TORQUE_DEBUG_GFX)
   FileStream stream;
   if ( !stream.open( path.getFullPath()+"_DEBUG", Torque::FS::File::Write ) )
   {
      AssertISV(false, avar("GFXGLShader::initShader - failed to write debug shader '%s'.", path.getFullPath().c_str()));
   }

   for(int i = 0; i < buffers.size(); ++i)
         stream.writeText(buffers[i]);
#endif

   // Cleanup the shader source buffer.
   for ( U32 i=0; i < buffers.size(); i++ )
      dFree( buffers[i] );

   glCompileShader(shader);

   return true;
}
/// Called by OpenGL device to active this state block.
/// @param oldState  The current state, used to make sure we don't set redundant states on the device.  Pass NULL to reset all states.
void GFXGLStateBlock::activate(const GFXGLStateBlock* oldState)
{
   // Big scary warning copied from Apple docs 
   // http://developer.apple.com/documentation/GraphicsImaging/Conceptual/OpenGL-MacProgGuide/opengl_performance/chapter_13_section_2.html#//apple_ref/doc/uid/TP40001987-CH213-SW12
   // Don't set a state that's already set. Once a feature is enabled, it does not need to be enabled again.
   // Calling an enable function more than once does nothing except waste time because OpenGL does not check 
   // the state of a feature when you call glEnable or glDisable. For instance, if you call glEnable(GL_LIGHTING) 
   // more than once, OpenGL does not check to see if the lighting state is already enabled. It simply updates 
   // the state value even if that value is identical to the current value.

#define STATE_CHANGE(state) (!oldState || oldState->mDesc.state != mDesc.state)
#define TOGGLE_STATE(state, enum) if(mDesc.state) glEnable(enum); else glDisable(enum)
#define CHECK_TOGGLE_STATE(state, enum) if(!oldState || oldState->mDesc.state != mDesc.state) if(mDesc.state) glEnable(enum); else glDisable(enum)

   // Blending
   CHECK_TOGGLE_STATE(blendEnable, GL_BLEND);
   if(STATE_CHANGE(blendSrc) || STATE_CHANGE(blendDest))
      glBlendFunc(GFXGLBlend[mDesc.blendSrc], GFXGLBlend[mDesc.blendDest]);
   if(STATE_CHANGE(blendOp))
      glBlendEquation(GFXGLBlendOp[mDesc.blendOp]);

   // Color write masks
   if(STATE_CHANGE(colorWriteRed) || STATE_CHANGE(colorWriteBlue) || STATE_CHANGE(colorWriteGreen) || STATE_CHANGE(colorWriteAlpha))
      glColorMask(mDesc.colorWriteRed, mDesc.colorWriteBlue, mDesc.colorWriteGreen, mDesc.colorWriteAlpha);
   
   // Culling
   if(STATE_CHANGE(cullMode))
   {
      TOGGLE_STATE(cullMode, GL_CULL_FACE);
      glCullFace(GFXGLCullMode[mDesc.cullMode]);
   }

   // Depth
   CHECK_TOGGLE_STATE(zEnable, GL_DEPTH_TEST);
   
   if(STATE_CHANGE(zFunc))
      glDepthFunc(GFXGLCmpFunc[mDesc.zFunc]);
   
   if(STATE_CHANGE(zBias))
   {
      if (mDesc.zBias == 0)
      {
         glDisable(GL_POLYGON_OFFSET_FILL);
      } else {
         F32 bias = mDesc.zBias * 10000.0f;
         glEnable(GL_POLYGON_OFFSET_FILL);
         glPolygonOffset(bias, bias);
      } 
   }
   
   if(STATE_CHANGE(zWriteEnable))
      glDepthMask(mDesc.zWriteEnable);

   // Stencil
   CHECK_TOGGLE_STATE(stencilEnable, GL_STENCIL_TEST);
   if(STATE_CHANGE(stencilFunc) || STATE_CHANGE(stencilRef) || STATE_CHANGE(stencilMask))
      glStencilFunc(GFXGLCmpFunc[mDesc.stencilFunc], mDesc.stencilRef, mDesc.stencilMask);
   if(STATE_CHANGE(stencilFailOp) || STATE_CHANGE(stencilZFailOp) || STATE_CHANGE(stencilPassOp))
      glStencilOp(GFXGLStencilOp[mDesc.stencilFailOp], GFXGLStencilOp[mDesc.stencilZFailOp], GFXGLStencilOp[mDesc.stencilPassOp]);
   if(STATE_CHANGE(stencilWriteMask))
      glStencilMask(mDesc.stencilWriteMask);
   

   if(STATE_CHANGE(fillMode))
      glPolygonMode(GL_FRONT_AND_BACK, GFXGLFillMode[mDesc.fillMode]);

#undef CHECK_STATE
#undef TOGGLE_STATE
#undef CHECK_TOGGLE_STATE

   //sampler objects
   if( gglHasExtension(ARB_sampler_objects) )
   {
      for (U32 i = 0; i < getMin(getOwningDevice()->getNumSamplers(), (U32) TEXTURE_STAGE_COUNT); i++)
      {
         if(!oldState || oldState->mSamplerObjects[i] != mSamplerObjects[i])
		      glBindSampler(i, mSamplerObjects[i] );
      }
   }	  

   // TODO: states added for detail blend   
}
Example #9
0
void GFXGLDevice::initGLState()
{  
   // We don't currently need to sync device state with a known good place because we are
   // going to set everything in GFXGLStateBlock, but if we change our GFXGLStateBlock strategy, this may
   // need to happen.
   
   // Deal with the card profiler here when we know we have a valid context.
   mCardProfiler = new GFXGLCardProfiler();
   mCardProfiler->init(); 
   glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, (GLint*)&mMaxShaderTextures);
   // JTH: Needs removed, ffp
   //glGetIntegerv(GL_MAX_TEXTURE_UNITS, (GLint*)&mMaxFFTextures);
   glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, (GLint*)&mMaxTRColors);
   mMaxTRColors = getMin( mMaxTRColors, (U32)(GFXTextureTarget::MaxRenderSlotId-1) );
   
   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
   
   // [JTH 5/6/2016] GLSL 1.50 is really SM 4.0
   // Setting mPixelShaderVersion to 3.0 will allow Advanced Lighting to run.   
   mPixelShaderVersion = 3.0;

	// Set capability extensions.
   mCapabilities.anisotropicFiltering = mCardProfiler->queryProfile("GL_EXT_texture_filter_anisotropic");
   mCapabilities.bufferStorage = mCardProfiler->queryProfile("GL_ARB_buffer_storage");
   mCapabilities.shaderModel5 = mCardProfiler->queryProfile("GL_ARB_gpu_shader5");
   mCapabilities.textureStorage = mCardProfiler->queryProfile("GL_ARB_texture_storage");
   mCapabilities.samplerObjects = mCardProfiler->queryProfile("GL_ARB_sampler_objects");
   mCapabilities.copyImage = mCardProfiler->queryProfile("GL_ARB_copy_image");
   mCapabilities.vertexAttributeBinding = mCardProfiler->queryProfile("GL_ARB_vertex_attrib_binding");

   String vendorStr = (const char*)glGetString( GL_VENDOR );
   if( vendorStr.find("NVIDIA", 0, String::NoCase | String::Left) != String::NPos)
      mUseGlMap = false;
   
   // Workaround for all Mac's, has a problem using glMap* with volatile buffers
#ifdef TORQUE_OS_MAC
   mUseGlMap = false;
#endif

#if TORQUE_DEBUG
   if( gglHasExtension(ARB_debug_output) )
   {
      glEnable(GL_DEBUG_OUTPUT);
      glDebugMessageCallbackARB(glDebugCallback, NULL);
      glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
      GLuint unusedIds = 0;
      glDebugMessageControlARB(GL_DONT_CARE,
            GL_DONT_CARE,
            GL_DONT_CARE,
            0,
            &unusedIds,
            GL_TRUE);
   }
   else if(gglHasExtension(AMD_debug_output))
   {
      glEnable(GL_DEBUG_OUTPUT);
      glDebugMessageCallbackAMD(glAmdDebugCallback, NULL);      
      //glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
      GLuint unusedIds = 0;
      glDebugMessageEnableAMD(GL_DONT_CARE, GL_DONT_CARE, 0,&unusedIds, GL_TRUE);
   }
#endif

   PlatformGL::setVSync(smDisableVSync ? 0 : 1);

   //install vsync callback
   Con::NotifyDelegate clbk(this, &GFXGLDevice::vsyncCallback);
   Con::addVariableNotify("$pref::Video::disableVerticalSync", clbk);

   //OpenGL 3 need a binded VAO for render
   GLuint vao;
   glGenVertexArrays(1, &vao);
   glBindVertexArray(vao);
}