1 /* 2 ----------------------------------------------------------------------------- 3 This source file is part of OGRE 4 (Object-oriented Graphics Rendering Engine) 5 For the latest info, see http://www.ogre3d.org/ 6 7 Copyright (c) 2000-2014 Torus Knot Software Ltd 8 9 Permission is hereby granted, free of charge, to any person obtaining a copy 10 of this software and associated documentation files (the "Software"), to deal 11 in the Software without restriction, including without limitation the rights 12 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 copies of the Software, and to permit persons to whom the Software is 14 furnished to do so, subject to the following conditions: 15 16 The above copyright notice and this permission notice shall be included in 17 all copies or substantial portions of the Software. 18 19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 THE SOFTWARE. 26 ----------------------------------------------------------------------------- 27 */ 28 29 #include "OgreGL3PlusTextureManager.h" 30 #include "OgreGL3PlusStateCacheManager.h" 31 #include "OgreGL3PlusRenderSystem.h" 32 #include "OgreGLRenderTexture.h" 33 #include "OgreRoot.h" 34 #include "OgreGL3PlusPixelFormat.h" 35 36 #ifndef GL_EXT_texture_filter_anisotropic 37 #define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE 38 #endif 39 40 namespace Ogre { getCombinedMinMipFilter(FilterOptions min,FilterOptions mip)41 GLint GL3PlusSampler::getCombinedMinMipFilter(FilterOptions min, FilterOptions mip) 42 { 43 switch(min) 44 { 45 case FO_ANISOTROPIC: 46 case FO_LINEAR: 47 switch (mip) 48 { 49 case FO_ANISOTROPIC: 50 case FO_LINEAR: 51 // linear min, linear mip 52 return GL_LINEAR_MIPMAP_LINEAR; 53 case FO_POINT: 54 // linear min, point mip 55 return GL_LINEAR_MIPMAP_NEAREST; 56 case FO_NONE: 57 // linear min, no mip 58 return GL_LINEAR; 59 } 60 break; 61 case FO_POINT: 62 case FO_NONE: 63 switch (mip) 64 { 65 case FO_ANISOTROPIC: 66 case FO_LINEAR: 67 // nearest min, linear mip 68 return GL_NEAREST_MIPMAP_LINEAR; 69 case FO_POINT: 70 // nearest min, point mip 71 return GL_NEAREST_MIPMAP_NEAREST; 72 case FO_NONE: 73 // nearest min, no mip 74 return GL_NEAREST; 75 } 76 break; 77 } 78 79 // should never get here 80 return 0; 81 } 82 getTextureAddressingMode(TextureAddressingMode tam)83 GLint GL3PlusSampler::getTextureAddressingMode(TextureAddressingMode tam) 84 { 85 switch (tam) 86 { 87 default: 88 case TextureUnitState::TAM_WRAP: 89 return GL_REPEAT; 90 case TextureUnitState::TAM_MIRROR: 91 return GL_MIRRORED_REPEAT; 92 case TextureUnitState::TAM_CLAMP: 93 return GL_CLAMP_TO_EDGE; 94 case TextureUnitState::TAM_BORDER: 95 return GL_CLAMP_TO_BORDER; 96 } 97 } 98 GL3PlusSampler(GL3PlusRenderSystem * rs)99 GL3PlusSampler::GL3PlusSampler(GL3PlusRenderSystem* rs) : mSamplerId(0) 100 { 101 if(rs->hasMinGLVersion(3, 3)) 102 glGenSamplers(1, &mSamplerId); 103 } ~GL3PlusSampler()104 GL3PlusSampler::~GL3PlusSampler() 105 { 106 glDeleteSamplers(1, &mSamplerId); 107 } bind(uint32 unit)108 void GL3PlusSampler::bind(uint32 unit) 109 { 110 OGRE_CHECK_GL_ERROR(glBindSampler(unit, mSamplerId)); 111 112 if(!mDirty) 113 return; 114 115 OGRE_CHECK_GL_ERROR(glSamplerParameteri(mSamplerId, GL_TEXTURE_WRAP_S, 116 getTextureAddressingMode(mAddressMode.u))); 117 OGRE_CHECK_GL_ERROR(glSamplerParameteri(mSamplerId, GL_TEXTURE_WRAP_T, 118 getTextureAddressingMode(mAddressMode.v))); 119 OGRE_CHECK_GL_ERROR(glSamplerParameteri(mSamplerId, GL_TEXTURE_WRAP_R, 120 getTextureAddressingMode(mAddressMode.w))); 121 122 if (mAddressMode.u == TAM_BORDER || mAddressMode.v == TAM_BORDER || mAddressMode.w == TAM_BORDER) 123 OGRE_CHECK_GL_ERROR(glSamplerParameterfv( mSamplerId, GL_TEXTURE_BORDER_COLOR, mBorderColour.ptr())); 124 OGRE_CHECK_GL_ERROR(glSamplerParameterf(mSamplerId, GL_TEXTURE_LOD_BIAS, mMipmapBias)); 125 126 auto caps = Root::getSingleton().getRenderSystem()->getCapabilities(); 127 if (caps->hasCapability(RSC_ANISOTROPY)) 128 OGRE_CHECK_GL_ERROR( 129 glSamplerParameteri(mSamplerId, GL_TEXTURE_MAX_ANISOTROPY_EXT, 130 std::min<uint>(caps->getMaxSupportedAnisotropy(), mMaxAniso))); 131 132 OGRE_CHECK_GL_ERROR( 133 glSamplerParameteri(mSamplerId, GL_TEXTURE_COMPARE_MODE, 134 mCompareEnabled ? GL_COMPARE_REF_TO_TEXTURE : GL_NONE)); 135 OGRE_CHECK_GL_ERROR( 136 glSamplerParameteri(mSamplerId, GL_TEXTURE_COMPARE_FUNC, 137 GL3PlusRenderSystem::convertCompareFunction(mCompareFunc))); 138 139 // Combine with existing mip filter 140 OGRE_CHECK_GL_ERROR(glSamplerParameteri(mSamplerId, GL_TEXTURE_MIN_FILTER, 141 getCombinedMinMipFilter(mMinFilter, mMipFilter))); 142 143 switch (mMagFilter) 144 { 145 case FO_ANISOTROPIC: // GL treats linear and aniso the same 146 case FO_LINEAR: 147 OGRE_CHECK_GL_ERROR(glSamplerParameteri(mSamplerId, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); 148 break; 149 case FO_POINT: 150 case FO_NONE: 151 OGRE_CHECK_GL_ERROR(glSamplerParameteri(mSamplerId, GL_TEXTURE_MAG_FILTER, GL_NEAREST)); 152 break; 153 } 154 155 mDirty = false; 156 } 157 GL3PlusTextureManager(GL3PlusRenderSystem * renderSystem)158 GL3PlusTextureManager::GL3PlusTextureManager(GL3PlusRenderSystem* renderSystem) 159 : TextureManager(), mRenderSystem(renderSystem) 160 { 161 // Register with group manager 162 ResourceGroupManager::getSingleton()._registerResourceManager(mResourceType, this); 163 } 164 ~GL3PlusTextureManager()165 GL3PlusTextureManager::~GL3PlusTextureManager() 166 { 167 // Unregister with group manager 168 ResourceGroupManager::getSingleton()._unregisterResourceManager(mResourceType); 169 } 170 createImpl(const String & name,ResourceHandle handle,const String & group,bool isManual,ManualResourceLoader * loader,const NameValuePairList * createParams)171 Resource* GL3PlusTextureManager::createImpl(const String& name, ResourceHandle handle, 172 const String& group, bool isManual, 173 ManualResourceLoader* loader, 174 const NameValuePairList* createParams) 175 { 176 return new GL3PlusTexture(this, name, handle, group, isManual, loader, mRenderSystem); 177 } 178 _createSamplerImpl()179 SamplerPtr GL3PlusTextureManager::_createSamplerImpl() 180 { 181 return std::make_shared<GL3PlusSampler>(mRenderSystem); 182 } 183 184 // TexturePtr GL3PlusTextureManager::createManual(const String & name, const String& group, 185 // TextureType texType, uint width, uint height, uint depth, int numMipmaps, 186 // PixelFormat format, int usage, ManualResourceLoader* loader, bool hwGamma, 187 // uint fsaa, const String& fsaaHint) 188 // { 189 // TexturePtr texture = TextureManager::createManual( 190 // name, group, texType, 191 // width, height, depth, numMipmaps, 192 // format, usage, loader, hwGamma, 193 // fsaa, fsaaHint); 194 195 // if (texture->getUsage() == TU_DYNAMIC_SHADER) 196 // { 197 // registerImage(texture); 198 // } 199 200 // return texture; 201 // } 202 203 getNativeFormat(TextureType ttype,PixelFormat format,int usage)204 PixelFormat GL3PlusTextureManager::getNativeFormat(TextureType ttype, PixelFormat format, int usage) 205 { 206 // Adjust requested parameters to capabilities 207 const RenderSystemCapabilities *caps = Root::getSingleton().getRenderSystem()->getCapabilities(); 208 209 // Check compressed texture support 210 // if a compressed format not supported, revert to PF_A8R8G8B8 211 if(PixelUtil::isCompressed(format) && 212 !caps->hasCapability( RSC_TEXTURE_COMPRESSION_DXT )) 213 { 214 return PF_BYTE_RGBA; 215 } 216 // if floating point textures not supported, revert to PF_A8R8G8B8 217 if (PixelUtil::isFloatingPoint(format) && 218 !caps->hasCapability(RSC_TEXTURE_FLOAT)) 219 { 220 return PF_BYTE_RGBA; 221 } 222 223 if(GL3PlusPixelUtil::getGLInternalFormat(format) == GL_NONE) 224 { 225 return PF_BYTE_RGBA; 226 } 227 228 // Check if this is a valid rendertarget format 229 if (usage & TU_RENDERTARGET) 230 { 231 /// Get closest supported alternative 232 /// If mFormat is supported it's returned 233 return GL3PlusRTTManager::getSingleton().getSupportedAlternative(format); 234 } 235 236 // Supported 237 return format; 238 } 239 240 // void GL3PlusTextureManager::registerImage(TexturePtr texture) 241 // { 242 // mImages.push_back(texture); 243 // } 244 245 //FIXME Should this become a standard Texture class feature? 246 // void GL3PlusTextureManager::bindImages() 247 // { 248 // //FIXME currently produces a GL_INVALID_OPERATION, so temporarily run once 249 // // static bool images_bound = false; 250 251 // TexturePtrList::iterator texture = mImages.begin(); 252 // TexturePtrList::iterator end = mImages.end(); 253 254 // // if (!images_bound && !mImages.empty()) { 255 // for (; texture != end; texture++) 256 // { 257 // //std::cout << "IMAGE LOAD/STORE" << std::endl; 258 // GL3PlusTexturePtr tex = texture->staticCast<GL3PlusTexture>(); 259 // //TODO This needs to be redone so that: 260 // // * binding point (first parameter) and possibly other parameters come from shader 261 // // * simple conversion of shader format to GLenum format 262 // // * material scripts can create images 263 // //OGRE_CHECK_GL_ERROR(glBindImageTexture(0, tex->getGLID(), 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA8)); 264 // } 265 // // images_bound = true; 266 // // } 267 // } 268 } 269