| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221 |
- #include "anki/gl/Texture.h"
- #include "anki/gl/GlException.h"
- #include "anki/util/Exception.h"
- #include <boost/lexical_cast.hpp>
- namespace anki {
- //==============================================================================
- // TextureManager =
- //==============================================================================
- //==============================================================================
- TextureManager::TextureManager()
- {
- GLint tmp;
- glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &tmp);
- units.resize(tmp, nullptr);
-
- activeUnit = -1;
- mipmapping = true;
- anisotropyLevel = 8;
- compression = true;
- }
- //==============================================================================
- void TextureManager::activateUnit(uint unit)
- {
- ANKI_ASSERT(unit < units.size());
- if(activeUnit == unit)
- {
- return;
- }
- activeUnit = unit;
- glActiveTexture(GL_TEXTURE0 + activeUnit);
- }
- //==============================================================================
- uint TextureManager::choseUnit(Texture* tex)
- {
- // Already binded
- //
- if(tex->unit != -1)
- {
- ANKI_ASSERT(units[tex->unit] == tex);
- return tex->unit;
- }
- // Find an empty slot for it
- //
- for(uint i = 0; i < units.size(); i++)
- {
- if(units[i] == nullptr)
- {
- units[i] = tex;
- return i;
- }
- }
- // If all units occupied chose a random for now
- //
- int tmp = rand() % units.size();
- units[tmp]->unit = -1;
- units[tmp] = tex;
- return tmp;
- }
- //==============================================================================
- void TextureManager::textureDeleted(Texture* tex)
- {
- for(auto it = units.begin(); it != units.end(); ++it)
- {
- if(*it == tex)
- {
- *it = nullptr;
- return;
- }
- }
- ANKI_ASSERT(0 && "Pointer not found");
- }
- //==============================================================================
- // Texture =
- //==============================================================================
- //==============================================================================
- Texture::Texture()
- : glId(std::numeric_limits<uint>::max()), target(GL_TEXTURE_2D), unit(-1)
- {}
- //==============================================================================
- Texture::~Texture()
- {
- if(isLoaded())
- {
- glDeleteTextures(1, &glId);
- }
- TextureManagerSingleton::get().textureDeleted(this);
- }
- //==============================================================================
- void Texture::create(const Initializer& init)
- {
- // Sanity checks
- //
- ANKI_ASSERT(!isLoaded());
- ANKI_ASSERT(init.internalFormat <= 4 && "Deprecated internal format");
- // Create
- //
- glGenTextures(1, &glId);
- target = GL_TEXTURE_2D;
- internalFormat = init.internalFormat;
- format = init.format;
- type = init.type;
- width = init.width;
- height = init.height;
- // Bind
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(target, glId);
- switch(internalFormat)
- {
- case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
- case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
- case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
- glCompressedTexImage2D(target, 0, internalFormat,
- width, height, 0, init.dataSize, init.data);
- break;
- default:
- glTexImage2D(target, 0, internalFormat, width,
- height, 0, format, type, init.data);
- }
- if(init.repeat)
- {
- glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_REPEAT);
- glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_REPEAT);
- }
- else
- {
- glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- }
- if(init.mipmapping && init.data)
- {
- glGenerateMipmap(target);
- }
- // If not mipmapping then the filtering cannot be trilinear
- if(init.filteringType == TFT_TRILINEAR && !init.mipmapping)
- {
- setFilteringNoBind(TFT_LINEAR);
- }
- else
- {
- setFilteringNoBind(init.filteringType);
- }
- if(init.anisotropyLevel > 1)
- {
- glTexParameteri(target, GL_TEXTURE_MAX_ANISOTROPY_EXT,
- GLint(init.anisotropyLevel));
- }
- ANKI_CHECK_GL_ERROR();
- }
- //==============================================================================
- void Texture::bind() const
- {
- unit = TextureManagerSingleton::get().choseUnit(
- const_cast<Texture*>(this));
- TextureManagerSingleton::get().activateUnit(unit);
- glBindTexture(target, glId);
- }
- //==============================================================================
- void Texture::genMipmap()
- {
- bind();
- glGenerateMipmap(target);
- }
- //==============================================================================
- void Texture::setFilteringNoBind(TextureFilteringType filterType) const
- {
- switch(filterType)
- {
- case TFT_NEAREST:
- glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- break;
- case TFT_LINEAR:
- glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- break;
- case TFT_TRILINEAR:
- glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
- glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- }
- }
- } // end namespace
|