OpenGTA/gl_texturecache.cpp
Anonymous Maarten 78c27f03c8 2006-12-10
2015-12-03 01:37:02 +01:00

251 lines
8.7 KiB
C++

/************************************************************************
* Copyright (c) 2005-2006 tok@openlinux.org.uk *
* *
* This software is provided as-is, without any express or implied *
* warranty. In no event will the authors be held liable for any *
* damages arising from the use of this software. *
* *
* Permission is granted to anyone to use this software for any purpose, *
* including commercial applications, and to alter it and redistribute *
* it freely, subject to the following restrictions: *
* *
* 1. The origin of this software must not be misrepresented; you must *
* not claim that you wrote the original software. If you use this *
* software in a product, an acknowledgment in the product documentation *
* would be appreciated but is not required. *
* *
* 2. Altered source versions must be plainly marked as such, and must *
* not be misrepresented as being the original software. *
* *
* 3. This notice may not be removed or altered from any source *
* distribution. *
************************************************************************/
#include <iostream>
#include <limits>
#include <sstream>
#include "gl_texturecache.h"
#include "log.h"
namespace OpenGL {
template <typename key_type>
TextureCache<key_type>::TextureCache(const char* with_name) : m_name(with_name) {
instance_id = instance_count++;
clearMagic = 0;
has_cached_query = false;
last_query_result = 0;
minClearElements = 50;
}
template <typename key_type>
TextureCache<key_type>::TextureCache() {
instance_id = instance_count++;
std::ostringstream stream;
stream << "TextureCache_" << instance_count;
m_name = stream.str();
has_cached_query = false;
clearMagic = 0;
minClearElements = 50;
}
template <typename key_type>
TextureCache<key_type>::~TextureCache() {
unsigned int ts = cached.size();
clearAll();
INFO << m_name << " exited - " << ts << " textures recycled" << std::endl;
m_name.clear();
instance_count--;
}
template <typename key_type>
void TextureCache<key_type>::clearAll() {
typename std::map<key_type, texTuple*>::iterator i = cached.begin();
while (i != cached.end()) {
GLuint tid = (i->second->texId);
glDeleteTextures(1, &tid);
delete i->second;
i++;
}
cached.clear();
}
template <typename key_type>
void TextureCache<key_type>::status() {
std::cout << "* " << m_name << " status: " << cached.size() << " textures total" << std::endl
<< "position = game_id : usage_count" << std::endl;
printStats();
}
template <typename key_type>
void TextureCache<key_type>::sink() {
typename std::map<key_type, texTuple*>::iterator i = cached.begin();
while (i != cached.end()) {
if (i->second->refCount <= 1)
i->second->refCount = 0;
else if (i->second->refCount < _max_4)
i->second->refCount = i->second->refCount >> 1;
else if (i->second->refCount < _max_2) {
INFO << m_name << " texture id " << int(i->first) <<
" -- half-count reached" << std::endl;
i->second->refCount = i->second->refCount >> 2;
}
else {
WARN << m_name << " texture id " << int(i->first) <<
" -- going critical" << std::endl;
i->second->refCount = i->second->refCount >> 3;
}
i++;
}
}
template <typename key_type>
void TextureCache<key_type>::clear() {
if (clearMagic == 0)
return;
if (cached.size() < minClearElements)
return;
typename std::map<key_type, texTuple*>::iterator i = cached.begin();
uint32_t numCleared = 0;
while (i != cached.end()) {
if (i->second->refCount < clearMagic) {
//INFO <<"## " << m_name << " clearing: " << int(i->first) << " count: " << i->second->refCount << std::endl;
GLuint tid = (i->second->texId);
glDeleteTextures(1, &tid);
delete i->second;
cached.erase(i);
numCleared++;
}
i++;
}
INFO << m_name << " " << numCleared << " textures recycled" << std::endl;
}
template <typename key_type>
void TextureCache<key_type>::clearStats() {
typename std::map<key_type, texTuple*>::iterator i = cached.begin();
while (i != cached.end()) {
i->second->refCount = 0;
i++;
}
}
template <typename key_type>
void TextureCache<key_type>::printStats() {
typename std::map<key_type, texTuple*>::iterator i = cached.begin();
size_t c = 1;
size_t c_active = 0;
while (i != cached.end()) {
if (i->second->refCount > 0) {
std::cout << c << " = " << uint32_t(i->first) << " : " << i->second->refCount << std::endl;
c_active++;
}
i++;
c++;
}
std::cout << c_active << " different textures used" << std::endl;
}
template <typename key_type>
GLuint TextureCache<key_type>::getTextureWithId(key_type id) {
if (matchingCachedQuery(id)) {
last_query_result->refCount++;
return last_query_result->texId;
}
typename std::map<key_type, texTuple*>::iterator i = cached.find(id);
if (i == cached.end()) {
ERROR << m_name << " failed to find texture " << int(id) << std::endl;
return 0;
}
else {
cacheQuery(id, i->second);
i->second->refCount++;
}
/*
* if (i->second->isAnimated) {
AnimControl->lookup(i->second)
* }
*/
return i->second->texId;
}
template <typename key_type>
bool TextureCache<key_type>::hasTexture(key_type id) {
if (matchingCachedQuery(id))
return true; // last_query_result;
typename std::map<key_type, texTuple*>::iterator i = cached.find(id);
if (i == cached.end())
return false;
cacheQuery(id, i->second);
return true;
}
template <typename key_type>
void TextureCache<key_type>::setToAlpha(key_type id) {
typename std::map<key_type, texTuple*>::iterator i = cached.find(id);
if (i == cached.end()) {
ERROR << m_name << " texture not found when trying to set alpha" << std::endl;
return;
}
i->second->hasAlpha = true;
}
template <typename key_type>
void TextureCache<key_type>::setToAnimated(key_type id) {
typename std::map<key_type, texTuple*>::iterator i = cached.find(id);
if (i == cached.end()) {
ERROR << m_name << " texture not found when trying to set animation" << std::endl;
return;
}
i->second->isAnimated = true;
}
template <typename key_type>
void TextureCache<key_type>::addTexture(key_type id, GLuint texId) {
/*
std::map<uint8_t, texTuple*>::iterator i = cached.find(id);
if (i == cached.end())
return;*/
texTuple* tt = new texTuple();
tt->texId = texId;
tt->refCount = 1;
tt->hasAlpha = false;
tt->isAnimated = false;
cached[id] = tt;
INFO << m_name << " GL texture " << texId << " added for key: " << int(id) << std::endl;
}
template <typename key_type>
void TextureCache<key_type>::cacheQuery(key_type id, texTuple *pos) {
has_cached_query = true;
last_query_id = id;
last_query_result = pos;
}
template <typename key_type>
bool TextureCache<key_type>::matchingCachedQuery(key_type id) {
return ((has_cached_query) && (id == last_query_id));
}
template <typename key_type>
void TextureCache<key_type>::setClearMagic(uint32_t removeLesser) {
clearMagic = removeLesser;
}
template <typename key_type>
void TextureCache<key_type>::setMinClearElements(uint32_t minElements) {
minClearElements = minElements;
}
template <typename key_type>
unsigned int TextureCache<key_type>::instance_count = 0;
std::numeric_limits<uint32_t> _countInfo;
template <typename key_type>
const uint32_t TextureCache<key_type>::_max_4 = _countInfo.max() / 4;
template <typename key_type>
const uint32_t TextureCache<key_type>::_max_2 = _countInfo.max() / 2;
template class TextureCache<uint8_t>;
template class TextureCache<char>;
template class TextureCache<uint16_t>;
template class TextureCache<uint32_t>;
}