osgEarth 2.1.1
|
00001 /* -*-c++-*- */ 00002 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph 00003 * Copyright 2008-2010 Pelican Mapping 00004 * http://osgearth.org 00005 * 00006 * osgEarth is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU Lesser General Public License as published by 00008 * the Free Software Foundation; either version 2 of the License, or 00009 * (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU Lesser General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public License 00017 * along with this program. If not, see <http://www.gnu.org/licenses/> 00018 */ 00019 #include <osgEarth/Capabilities> 00020 #include <osg/FragmentProgram> 00021 #include <osg/GraphicsContext> 00022 #include <osg/GL> 00023 #include <osg/GLExtensions> 00024 #include <osg/GL2Extensions> 00025 #include <osg/Texture> 00026 #include <osgViewer/Version> 00027 00028 using namespace osgEarth; 00029 00030 #define LC "[Capabilities] " 00031 00032 // --------------------------------------------------------------------------- 00033 // A custom P-Buffer graphics context that we will use to query for OpenGL 00034 // extension and hardware support. (Adapted from osgconv in OpenSceneGraph) 00035 00036 struct MyGraphicsContext 00037 { 00038 MyGraphicsContext() 00039 { 00040 osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits; 00041 traits->x = 0; 00042 traits->y = 0; 00043 traits->width = 1; 00044 traits->height = 1; 00045 traits->windowDecoration = false; 00046 traits->doubleBuffer = false; 00047 traits->sharedContext = 0; 00048 traits->pbuffer = false; 00049 00050 // Intel graphics adapters dont' support pbuffers, and some of their drivers crash when 00051 // you try to create them. So by default we will only use the unmapped/pbuffer method 00052 // upon special request. 00053 if ( getenv( "OSGEARTH_USE_PBUFFER_TEST" ) ) 00054 { 00055 traits->pbuffer = true; 00056 OE_INFO << LC << "Activating pbuffer test for graphics capabilities" << std::endl; 00057 _gc = osg::GraphicsContext::createGraphicsContext(traits.get()); 00058 if ( !_gc.valid() ) 00059 OE_WARN << LC << "Failed to create pbuffer" << std::endl; 00060 } 00061 00062 if (!_gc.valid()) 00063 { 00064 // fall back on a mapped window 00065 traits->pbuffer = false; 00066 _gc = osg::GraphicsContext::createGraphicsContext(traits.get()); 00067 } 00068 00069 if (_gc.valid()) 00070 { 00071 _gc->realize(); 00072 _gc->makeCurrent(); 00073 00074 if ( traits->pbuffer == false ) 00075 { 00076 OE_DEBUG << LC << "Realized graphics window for OpenGL operations." << std::endl; 00077 } 00078 else 00079 { 00080 OE_DEBUG << LC << "Realized pbuffer for OpenGL operations." << std::endl; 00081 } 00082 } 00083 else 00084 { 00085 OE_WARN << LC << "Failed to create graphic window too." << std::endl; 00086 } 00087 } 00088 00089 bool valid() const { return _gc.valid() && _gc->isRealized(); } 00090 00091 osg::ref_ptr<osg::GraphicsContext> _gc; 00092 }; 00093 00094 // --------------------------------------------------------------------------- 00095 00096 #define SAYBOOL(X) (X?"yes":"no") 00097 00098 Capabilities::Capabilities() : 00099 _maxFFPTextureUnits ( 1 ), 00100 _maxGPUTextureUnits ( 1 ), 00101 _maxGPUTextureCoordSets ( 1 ), 00102 _maxTextureSize ( 256 ), 00103 _maxFastTextureSize ( 256 ), 00104 _maxLights ( 1 ), 00105 _supportsGLSL ( false ), 00106 _GLSLversion ( 1.0f ), 00107 _supportsTextureArrays ( false ), 00108 _supportsMultiTexture ( false ), 00109 _supportsStencilWrap ( true ), 00110 _supportsTwoSidedStencil( false ), 00111 _supportsTexture2DLod ( false ), 00112 _supportsMipmappedTextureUpdates( false ) 00113 { 00114 // little hack to force the osgViewer library to link so we can create a graphics context 00115 osgViewerGetVersion(); 00116 00117 // check the environment in order to disable ATI workarounds 00118 bool enableATIworkarounds = true; 00119 if ( ::getenv( "OSGEARTH_DISABLE_ATI_WORKAROUNDS" ) != 0L ) 00120 enableATIworkarounds = false; 00121 00122 // create a graphics context so we can query OpenGL support: 00123 MyGraphicsContext mgc; 00124 00125 if ( mgc.valid() ) 00126 { 00127 osg::GraphicsContext* gc = mgc._gc.get(); 00128 unsigned int id = gc->getState()->getContextID(); 00129 const osg::GL2Extensions* GL2 = osg::GL2Extensions::Get( id, true ); 00130 00131 OE_INFO << LC << "Detected hardware capabilities:" << std::endl; 00132 00133 _vendor = std::string( reinterpret_cast<const char*>(glGetString(GL_VENDOR)) ); 00134 OE_INFO << LC << " Vendor = " << _vendor << std::endl; 00135 00136 _renderer = std::string( reinterpret_cast<const char*>(glGetString(GL_RENDERER)) ); 00137 OE_INFO << LC << " Renderer = " << _renderer << std::endl; 00138 00139 _version = std::string( reinterpret_cast<const char*>(glGetString(GL_VERSION)) ); 00140 OE_INFO << LC << " Version = " << _version << std::endl; 00141 00142 glGetIntegerv( GL_MAX_TEXTURE_UNITS, &_maxFFPTextureUnits ); 00143 OE_INFO << LC << " Max FFP texture units = " << _maxFFPTextureUnits << std::endl; 00144 00145 glGetIntegerv( GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &_maxGPUTextureUnits ); 00146 OE_INFO << LC << " Max GPU texture units = " << _maxGPUTextureUnits << std::endl; 00147 00148 glGetIntegerv( GL_MAX_TEXTURE_COORDS_ARB, &_maxGPUTextureCoordSets ); 00149 OE_INFO << LC << " Max GPU texture coordinate sets = " << _maxGPUTextureCoordSets << std::endl; 00150 00151 // Use the texture-proxy method to determine the maximum texture size 00152 glGetIntegerv( GL_MAX_TEXTURE_SIZE, &_maxTextureSize ); 00153 for( int s = _maxTextureSize; s > 2; s >>= 1 ) 00154 { 00155 glTexImage2D( GL_PROXY_TEXTURE_2D, 0, GL_RGBA8, s, s, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0L ); 00156 GLint width = 0; 00157 glGetTexLevelParameteriv( GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width ); 00158 if ( width == s ) 00159 { 00160 _maxTextureSize = s; 00161 break; 00162 } 00163 } 00164 OE_INFO << LC << " Max texture size = " << _maxTextureSize << std::endl; 00165 00166 glGetIntegerv( GL_MAX_LIGHTS, &_maxLights ); 00167 OE_INFO << LC << " Max lights = " << _maxLights << std::endl; 00168 00169 _supportsGLSL = GL2->isGlslSupported(); 00170 OE_INFO << LC << " GLSL = " << SAYBOOL(_supportsGLSL) << std::endl; 00171 00172 if ( _supportsGLSL ) 00173 { 00174 _GLSLversion = GL2->getLanguageVersion(); 00175 OE_INFO << LC << " GLSL Version = " << _GLSLversion << std::endl; 00176 } 00177 00178 _supportsTextureArrays = 00179 _supportsGLSL && 00180 osg::getGLVersionNumber() >= 2.0 && // hopefully this will detect Intel cards 00181 osg::isGLExtensionSupported( id, "GL_EXT_texture_array" ); 00182 OE_INFO << LC << " Texture arrays = " << SAYBOOL(_supportsTextureArrays) << std::endl; 00183 00184 _supportsTexture3D = osg::isGLExtensionSupported( id, "GL_EXT_texture3D" ); 00185 OE_INFO << LC << " 3D textures = " << SAYBOOL(_supportsTexture3D) << std::endl; 00186 00187 _supportsMultiTexture = 00188 osg::getGLVersionNumber() >= 1.3 || 00189 osg::isGLExtensionSupported( id, "GL_ARB_multitexture") || 00190 osg::isGLExtensionSupported( id, "GL_EXT_multitexture" ); 00191 OE_INFO << LC << " Multitexturing = " << SAYBOOL(_supportsMultiTexture) << std::endl; 00192 00193 _supportsStencilWrap = osg::isGLExtensionSupported( id, "GL_EXT_stencil_wrap" ); 00194 OE_INFO << LC << " Stencil wrapping = " << SAYBOOL(_supportsStencilWrap) << std::endl; 00195 00196 _supportsTwoSidedStencil = osg::isGLExtensionSupported( id, "GL_EXT_stencil_two_side" ); 00197 OE_INFO << LC << " 2-sided stencils = " << SAYBOOL(_supportsTwoSidedStencil) << std::endl; 00198 00199 //_supportsTexture2DLod = osg::isGLExtensionSupported( id, "GL_ARB_shader_texture_lod" ); 00200 //OE_INFO << LC << " texture2DLod = " << SAYBOOL(_supportsTexture2DLod) << std::endl; 00201 00202 // ATI workarounds: 00203 bool isATI = _vendor.find("ATI ") == 0; 00204 00205 _supportsMipmappedTextureUpdates = isATI && enableATIworkarounds ? false : true; 00206 OE_INFO << LC << " Mipmapped texture updates = " << SAYBOOL(_supportsMipmappedTextureUpdates) << std::endl; 00207 00208 // Intel workarounds: 00209 bool isIntel = 00210 _vendor.find("Intel ") != std::string::npos || 00211 _vendor.find("Intel(R)") != std::string::npos; 00212 _maxFastTextureSize = isIntel ? std::min(2048, _maxTextureSize) : _maxTextureSize; 00213 OE_INFO << LC << "Max Fast Texture Size = " << _maxFastTextureSize << std::endl; 00214 } 00215 } 00216