2011-10-25 05:03:10 +00:00
|
|
|
//
|
|
|
|
|
// KRTexture.cpp
|
2012-03-15 20:09:01 +00:00
|
|
|
// KREngine
|
2011-10-25 05:03:10 +00:00
|
|
|
//
|
2012-10-05 21:22:47 +00:00
|
|
|
// Created by Kearwood Gilbert on 2012-10-05.
|
|
|
|
|
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
2011-10-25 05:03:10 +00:00
|
|
|
//
|
|
|
|
|
|
2013-01-11 03:21:19 +00:00
|
|
|
#include "KREngine-common.h"
|
2011-10-25 05:03:10 +00:00
|
|
|
#include "KRTexture.h"
|
2012-10-06 01:43:11 +00:00
|
|
|
#include "KRDataBlock.h"
|
2012-11-17 00:15:52 +00:00
|
|
|
#include "KRContext.h"
|
|
|
|
|
#include "KRTextureManager.h"
|
2011-10-25 05:03:10 +00:00
|
|
|
|
2012-12-20 01:23:57 +00:00
|
|
|
KRTexture::KRTexture(KRContext &context, std::string name) : KRResource(context, name)
|
2012-10-06 01:43:11 +00:00
|
|
|
{
|
2014-04-14 00:47:29 -07:00
|
|
|
m_current_lod_max_dim = 0;
|
|
|
|
|
m_new_lod_max_dim = 0;
|
2012-10-06 01:43:11 +00:00
|
|
|
m_iHandle = 0;
|
2013-11-02 16:27:24 -07:00
|
|
|
m_iNewHandle = 0;
|
2012-10-06 01:43:11 +00:00
|
|
|
m_textureMemUsed = 0;
|
2013-11-02 16:27:24 -07:00
|
|
|
m_newTextureMemUsed = 0;
|
2012-11-17 00:15:52 +00:00
|
|
|
m_last_frame_used = 0;
|
2014-04-11 01:15:40 -07:00
|
|
|
m_last_frame_max_lod_coverage = 0.0f;
|
|
|
|
|
m_last_frame_usage = TEXTURE_USAGE_NONE;
|
2013-11-16 03:22:31 -08:00
|
|
|
m_handle_lock.clear();
|
2012-10-06 01:43:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
KRTexture::~KRTexture()
|
|
|
|
|
{
|
2013-11-02 16:27:24 -07:00
|
|
|
releaseHandles();
|
2012-10-06 01:43:11 +00:00
|
|
|
}
|
|
|
|
|
|
2013-11-02 16:27:24 -07:00
|
|
|
void KRTexture::releaseHandles() {
|
2013-11-16 02:34:18 -08:00
|
|
|
long mem_size = getMemSize();
|
|
|
|
|
|
2013-11-16 03:22:31 -08:00
|
|
|
while(m_handle_lock.test_and_set()); // Spin lock
|
|
|
|
|
|
2013-11-02 16:27:24 -07:00
|
|
|
if(m_iNewHandle != 0) {
|
|
|
|
|
GLDEBUG(glDeleteTextures(1, &m_iNewHandle));
|
|
|
|
|
m_iNewHandle = 0;
|
|
|
|
|
m_newTextureMemUsed = 0;
|
|
|
|
|
}
|
2012-10-06 01:43:11 +00:00
|
|
|
if(m_iHandle != 0) {
|
|
|
|
|
GLDEBUG(glDeleteTextures(1, &m_iHandle));
|
|
|
|
|
m_iHandle = 0;
|
|
|
|
|
m_textureMemUsed = 0;
|
|
|
|
|
}
|
2014-04-14 00:47:29 -07:00
|
|
|
m_current_lod_max_dim = 0;
|
|
|
|
|
m_new_lod_max_dim = 0;
|
2013-11-16 03:22:31 -08:00
|
|
|
|
|
|
|
|
m_handle_lock.clear();
|
|
|
|
|
|
2013-11-16 02:34:18 -08:00
|
|
|
getContext().getTextureManager()->memoryChanged(-mem_size);
|
2012-10-06 01:43:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
long KRTexture::getMemSize() {
|
2013-11-02 16:27:24 -07:00
|
|
|
return m_textureMemUsed + m_newTextureMemUsed; // TODO - This is not 100% accurate, as loaded format may differ in size while in GPU memory
|
2011-10-25 05:03:10 +00:00
|
|
|
}
|
|
|
|
|
|
2012-11-29 23:44:50 +00:00
|
|
|
long KRTexture::getReferencedMemSize() {
|
|
|
|
|
// Return the amount of memory used by other textures referenced by this texture (for cube maps and animated textures)
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-17 00:15:52 +00:00
|
|
|
void KRTexture::resize(int max_dim)
|
|
|
|
|
{
|
2014-04-13 01:53:16 -07:00
|
|
|
while(m_handle_lock.test_and_set()); // Spin lock
|
2013-11-16 02:34:18 -08:00
|
|
|
{
|
|
|
|
|
if(m_iHandle == m_iNewHandle) {
|
|
|
|
|
if(max_dim == 0) {
|
|
|
|
|
m_iNewHandle = 0;
|
|
|
|
|
} else {
|
|
|
|
|
int target_dim = max_dim;
|
|
|
|
|
if(target_dim < m_min_lod_max_dim) target_dim = m_min_lod_max_dim;
|
|
|
|
|
|
2014-04-14 00:47:29 -07:00
|
|
|
if(m_new_lod_max_dim != target_dim || (m_iHandle == 0 && m_iNewHandle == 0)) {
|
2013-11-16 02:34:18 -08:00
|
|
|
assert(m_newTextureMemUsed == 0);
|
|
|
|
|
m_newTextureMemUsed = getMemRequiredForSize(target_dim);
|
|
|
|
|
|
|
|
|
|
getContext().getTextureManager()->memoryChanged(m_newTextureMemUsed);
|
|
|
|
|
getContext().getTextureManager()->addMemoryTransferredThisFrame(m_newTextureMemUsed);
|
|
|
|
|
|
|
|
|
|
if(!createGLTexture(target_dim)) {
|
|
|
|
|
getContext().getTextureManager()->memoryChanged(-m_newTextureMemUsed);
|
|
|
|
|
m_newTextureMemUsed = 0;
|
2014-01-24 02:13:34 -08:00
|
|
|
assert(false); // Failed to create the texture
|
2013-11-16 02:34:18 -08:00
|
|
|
}
|
2012-11-17 00:15:52 +00:00
|
|
|
}
|
|
|
|
|
}
|
2013-11-16 02:34:18 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m_handle_lock.clear();
|
2012-11-17 00:15:52 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GLuint KRTexture::getHandle() {
|
2014-04-11 01:15:40 -07:00
|
|
|
resetPoolExpiry(0.0f, KRTexture::TEXTURE_USAGE_NONE); // TODO - Pass through getHandle() arguements to replace extraneous resetPoolExpiry calls?
|
2012-11-17 00:15:52 +00:00
|
|
|
return m_iHandle;
|
|
|
|
|
}
|
|
|
|
|
|
2014-04-11 01:15:40 -07:00
|
|
|
void KRTexture::resetPoolExpiry(float lodCoverage, KRTexture::texture_usage_t textureUsage)
|
2012-11-17 07:57:28 +00:00
|
|
|
{
|
2014-04-11 01:15:40 -07:00
|
|
|
long current_frame = getContext().getCurrentFrame();
|
|
|
|
|
if(current_frame != m_last_frame_used) {
|
|
|
|
|
m_last_frame_used = current_frame;
|
|
|
|
|
m_last_frame_max_lod_coverage = 0.0f;
|
|
|
|
|
m_last_frame_usage = TEXTURE_USAGE_NONE;
|
|
|
|
|
|
|
|
|
|
getContext().getTextureManager()->primeTexture(this);
|
|
|
|
|
}
|
|
|
|
|
m_last_frame_max_lod_coverage = KRMAX(lodCoverage, m_last_frame_max_lod_coverage);
|
|
|
|
|
m_last_frame_usage = static_cast<texture_usage_t>(static_cast<int>(m_last_frame_usage) | static_cast<int>(textureUsage));
|
2012-11-17 07:57:28 +00:00
|
|
|
}
|
|
|
|
|
|
2014-04-23 01:43:00 -07:00
|
|
|
kraken_stream_level KRTexture::getStreamLevel(KRTexture::texture_usage_t textureUsage)
|
2014-03-10 22:32:49 -07:00
|
|
|
{
|
|
|
|
|
if(m_current_lod_max_dim == 0) {
|
|
|
|
|
return kraken_stream_level::STREAM_LEVEL_OUT;
|
2014-04-11 01:15:40 -07:00
|
|
|
} else if(m_current_lod_max_dim == KRMIN(getContext().KRENGINE_MAX_TEXTURE_DIM, m_max_lod_max_dim)) {
|
2014-03-10 22:32:49 -07:00
|
|
|
return kraken_stream_level::STREAM_LEVEL_IN_HQ;
|
2014-04-14 02:27:16 -07:00
|
|
|
} else if(m_current_lod_max_dim >= KRMAX(getContext().KRENGINE_MIN_TEXTURE_DIM, m_min_lod_max_dim)) {
|
2014-03-10 22:32:49 -07:00
|
|
|
return kraken_stream_level::STREAM_LEVEL_IN_LQ;
|
2014-04-14 02:27:16 -07:00
|
|
|
} else {
|
|
|
|
|
return kraken_stream_level::STREAM_LEVEL_OUT;
|
2014-03-10 22:32:49 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-04-11 01:15:40 -07:00
|
|
|
float KRTexture::getStreamPriority()
|
|
|
|
|
{
|
|
|
|
|
long current_frame = getContext().getCurrentFrame();
|
|
|
|
|
if(current_frame > m_last_frame_used + 5) {
|
|
|
|
|
return 1.0f - KRCLAMP((float)(current_frame - m_last_frame_used) / 60.0f, 0.0f, 1.0f);
|
|
|
|
|
} else {
|
|
|
|
|
float priority = 100.0f;
|
|
|
|
|
if(m_last_frame_usage & (TEXTURE_USAGE_UI | TEXTURE_USAGE_SHADOW_DEPTH)) {
|
|
|
|
|
priority += 10000000.0f;
|
|
|
|
|
}
|
|
|
|
|
if(m_last_frame_usage & (TEXTURE_USAGE_SKY_CUBE | TEXTURE_USAGE_PARTICLE | TEXTURE_USAGE_SPRITE | TEXTURE_USAGE_LIGHT_FLARE)) {
|
|
|
|
|
priority += 1000000.0f;
|
|
|
|
|
}
|
|
|
|
|
if(m_last_frame_usage & (TEXTURE_USAGE_DIFFUSE_MAP | TEXTURE_USAGE_AMBIENT_MAP | TEXTURE_USAGE_SPECULAR_MAP | TEXTURE_USAGE_NORMAL_MAP | TEXTURE_USAGE_REFLECTION_MAP)) {
|
|
|
|
|
priority += 100000.0f;
|
|
|
|
|
}
|
|
|
|
|
if(m_last_frame_usage & (TEXTURE_USAGE_LIGHT_MAP)) {
|
|
|
|
|
priority += 100000.0f;
|
|
|
|
|
}
|
|
|
|
|
if(m_last_frame_usage & (TEXTURE_USAGE_REFECTION_CUBE)) {
|
2014-04-12 23:42:26 -07:00
|
|
|
priority += 100000.0f;
|
2014-04-11 01:15:40 -07:00
|
|
|
}
|
|
|
|
|
priority += m_last_frame_max_lod_coverage * 10.0f;
|
|
|
|
|
return priority;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
float KRTexture::getLastFrameLodCoverage() const
|
|
|
|
|
{
|
|
|
|
|
return m_last_frame_max_lod_coverage;
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-17 00:15:52 +00:00
|
|
|
long KRTexture::getLastFrameUsed()
|
|
|
|
|
{
|
|
|
|
|
return m_last_frame_used;
|
|
|
|
|
}
|
2012-11-29 23:44:50 +00:00
|
|
|
bool KRTexture::isAnimated()
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2014-01-23 21:40:29 -08:00
|
|
|
KRTexture *KRTexture::compress(bool premultiply_alpha)
|
2012-12-20 01:23:57 +00:00
|
|
|
{
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
2012-11-17 00:15:52 +00:00
|
|
|
|
2013-03-21 13:21:04 -07:00
|
|
|
int KRTexture::getCurrentLodMaxDim() {
|
|
|
|
|
return m_current_lod_max_dim;
|
|
|
|
|
}
|
|
|
|
|
|
2014-04-14 00:47:29 -07:00
|
|
|
int KRTexture::getNewLodMaxDim() {
|
|
|
|
|
return m_new_lod_max_dim;
|
|
|
|
|
}
|
|
|
|
|
|
2013-03-21 13:21:04 -07:00
|
|
|
int KRTexture::getMaxMipMap() {
|
|
|
|
|
return m_max_lod_max_dim;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int KRTexture::getMinMipMap() {
|
|
|
|
|
return m_min_lod_max_dim;
|
|
|
|
|
}
|
2013-03-21 19:58:35 -07:00
|
|
|
|
|
|
|
|
bool KRTexture::hasMipmaps() {
|
|
|
|
|
return m_max_lod_max_dim != m_min_lod_max_dim;
|
|
|
|
|
}
|
2013-11-02 16:27:24 -07:00
|
|
|
|
|
|
|
|
void KRTexture::bind(GLuint texture_unit) {
|
2014-04-23 01:43:00 -07:00
|
|
|
|
2013-11-02 16:27:24 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void KRTexture::_swapHandles()
|
|
|
|
|
{
|
2014-04-13 01:53:16 -07:00
|
|
|
//while(m_handle_lock.test_and_set()); // Spin lock
|
2013-11-16 03:22:31 -08:00
|
|
|
if(!m_handle_lock.test_and_set()) {
|
2013-11-16 02:34:18 -08:00
|
|
|
if(m_iHandle != m_iNewHandle) {
|
|
|
|
|
if(m_iHandle != 0) {
|
|
|
|
|
GLDEBUG(glDeleteTextures(1, &m_iHandle));
|
|
|
|
|
getContext().getTextureManager()->memoryChanged(-m_textureMemUsed);
|
|
|
|
|
}
|
|
|
|
|
m_textureMemUsed = (long)m_newTextureMemUsed;
|
2013-11-02 16:27:24 -07:00
|
|
|
m_newTextureMemUsed = 0;
|
2013-11-16 02:34:18 -08:00
|
|
|
m_iHandle = m_iNewHandle;
|
2014-04-14 00:47:29 -07:00
|
|
|
m_current_lod_max_dim = m_new_lod_max_dim;
|
2013-11-02 16:27:24 -07:00
|
|
|
}
|
2013-11-16 02:34:18 -08:00
|
|
|
m_handle_lock.clear();
|
2013-11-02 16:27:24 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|