Remove unused texture code

This commit is contained in:
Benau 2018-01-11 12:47:02 +08:00
parent 3374ec66e3
commit 68ceceb6e3
11 changed files with 39 additions and 1203 deletions

View File

@ -195,19 +195,8 @@ public:
//! return open gl texture name
virtual u32 getOpenGLTextureName() const = 0;
virtual u64 getHandle() = 0;
virtual void unloadHandle() {}
virtual u32 getTextureSize() const { return 0; }
virtual void threadedReload(void* ptr, void* param) const {}
virtual void threadedSubImage(void* ptr) const {}
virtual void cleanThreadedLoader() {}
virtual int getThreadedLoadTextureCounter() const { return 0; }
protected:
//! Helper function, helps to get the desired texture creation format from the flags.

View File

@ -1,120 +0,0 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2017 SuperTuxKart-Team
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#if !(defined(SERVER_ONLY) || defined(USE_GLES2))
#include "graphics/hq_mipmap_generator.hpp"
#include "graphics/stk_tex_manager.hpp"
#undef DUMP_MIPMAP
#ifdef DUMP_MIPMAP
#include "graphics/irr_driver.hpp"
#include "utils/string_utils.hpp"
#endif
#include <cassert>
extern "C"
{
#include <mipmap/img.h>
#include <mipmap/imgresize.h>
}
// ----------------------------------------------------------------------------
HQMipmapGenerator::HQMipmapGenerator(const io::path& name, uint8_t* data,
const core::dimension2d<u32>& size,
GLuint texture_name, TexConfig* tc)
: video::ITexture(name), m_orig_data(data), m_size(size),
m_texture_name(texture_name), m_texture_size(0),
m_mipmap_data(NULL), m_tex_config(tc)
{
assert(m_tex_config != NULL);
unsigned width = m_size.Width;
unsigned height = m_size.Height;
while (true)
{
width = width < 2 ? 1 : width >> 1;
height = height < 2 ? 1 : height >> 1;
m_mipmap_sizes.emplace_back(core::dimension2du(width, height),
m_texture_size);
m_texture_size += width * height * 4;
if (width == 1 && height == 1)
break;
}
m_texture_size = unsigned(m_mipmap_sizes.back().second) + 4;
m_mipmap_data = malloc(sizeof(imMipmapCascade));
} // HQMipmapGenerator
// ----------------------------------------------------------------------------
void HQMipmapGenerator::threadedReload(void* ptr, void* param) const
{
imReduceOptions options;
imReduceSetOptions(&options,
m_tex_config->m_normal_map ?
IM_REDUCE_FILTER_NORMALMAP: m_tex_config->m_srgb ?
IM_REDUCE_FILTER_SRGB : IM_REDUCE_FILTER_LINEAR/*filter*/,
2/*hopcount*/, 2.0f/*alpha*/, 1.0f/*amplifynormal*/,
0.0f/*normalsustainfactor*/);
imMipmapCascade* mm_cascade = (imMipmapCascade*)m_mipmap_data;
#ifdef DEBUG
int ret = imBuildMipmapCascade(mm_cascade, m_orig_data, m_size.Width,
m_size.Height, 1/*layercount*/, 4, m_size.Width * 4, &options, 0);
assert(ret == 1);
#else
imBuildMipmapCascade(mm_cascade, m_orig_data, m_size.Width,
m_size.Height, 1/*layercount*/, 4, m_size.Width * 4, &options, 0);
#endif
for (unsigned int i = 0; i < m_mipmap_sizes.size(); i++)
{
const unsigned size = m_mipmap_sizes[i].first.getArea() * 4;
memcpy((uint8_t*)ptr + m_mipmap_sizes[i].second,
mm_cascade->mipmap[i + 1], size);
#ifdef DUMP_MIPMAP
video::IImage* image = irr_driver->getVideoDriver()
->createImageFromData(video::ECF_A8R8G8B8, m_mipmap_sizes[i].first,
mm_cascade->mipmap[i + 1], false/*ownForeignMemory*/);
irr_driver->getVideoDriver()->writeImageToFile(image, std::string
(StringUtils::toString(i) + "_" +
StringUtils::getBasename(NamedPath.getPtr())).c_str());
image->drop();
#endif
}
} // threadedReload
// ----------------------------------------------------------------------------
void HQMipmapGenerator::threadedSubImage(void* ptr) const
{
#if !(defined(SERVER_ONLY) || defined(USE_GLES2))
glBindTexture(GL_TEXTURE_2D, m_texture_name);
for (unsigned int i = 0; i < m_mipmap_sizes.size(); i++)
{
glTexSubImage2D(GL_TEXTURE_2D, i + 1, 0, 0,
m_mipmap_sizes[i].first.Width, m_mipmap_sizes[i].first.Height,
GL_BGRA, GL_UNSIGNED_BYTE,
(uint8_t*)ptr + m_mipmap_sizes[i].second);
}
delete this;
#endif
} // threadedSubImage
// ----------------------------------------------------------------------------
void HQMipmapGenerator::cleanThreadedLoader()
{
delete[] m_orig_data;
imFreeMipmapCascade((imMipmapCascade*)m_mipmap_data);
free(m_mipmap_data);
} // cleanThreadedLoader
#endif

View File

@ -1,103 +0,0 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2017 SuperTuxKart-Team
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifndef HEADER_HQ_MIPMAP_GENERATOR_HPP
#define HEADER_HQ_MIPMAP_GENERATOR_HPP
#if !(defined(SERVER_ONLY) || defined(USE_GLES2))
#include "graphics/gl_headers.hpp"
#include "utils/no_copy.hpp"
#include "utils/types.hpp"
#include <vector>
#include <ITexture.h>
using namespace irr;
struct TexConfig;
class HQMipmapGenerator : public video::ITexture, NoCopy
{
private:
uint8_t* m_orig_data;
core::dimension2d<u32> m_size;
GLuint m_texture_name;
unsigned int m_texture_size;
void* m_mipmap_data;
TexConfig* m_tex_config;
std::vector<std::pair<core::dimension2d<u32>, size_t> > m_mipmap_sizes;
public:
// ------------------------------------------------------------------------
HQMipmapGenerator(const io::path& name, uint8_t* data,
const core::dimension2d<u32>& size, GLuint texture_name,
TexConfig* tc);
// ------------------------------------------------------------------------
virtual ~HQMipmapGenerator() {}
// ------------------------------------------------------------------------
virtual void* lock(video::E_TEXTURE_LOCK_MODE mode =
video::ETLM_READ_WRITE, u32 mipmap_level = 0)
{ return NULL; }
// ------------------------------------------------------------------------
virtual void unlock() {}
// ------------------------------------------------------------------------
virtual const core::dimension2d<u32>& getOriginalSize() const
{ return m_size; }
// ------------------------------------------------------------------------
virtual const core::dimension2d<u32>& getSize() const { return m_size; }
// ------------------------------------------------------------------------
virtual video::E_DRIVER_TYPE getDriverType() const
{
#if defined(USE_GLES2)
return video::EDT_OGLES2;
#else
return video::EDT_OPENGL;
#endif
}
// ------------------------------------------------------------------------
virtual video::ECOLOR_FORMAT getColorFormat() const
{ return video::ECF_A8R8G8B8; }
// ------------------------------------------------------------------------
virtual u32 getPitch() const { return 0; }
// ------------------------------------------------------------------------
virtual bool hasMipMaps() const { return false; }
// ------------------------------------------------------------------------
virtual void regenerateMipMapLevels(void* mipmap_data = NULL) {}
// ------------------------------------------------------------------------
virtual u32 getOpenGLTextureName() const { return m_texture_name; }
// ------------------------------------------------------------------------
virtual u64 getHandle() { return 0; }
// ------------------------------------------------------------------------
virtual unsigned int getTextureSize() const { return m_texture_size; }
// ------------------------------------------------------------------------
virtual void threadedReload(void* ptr, void* param) const;
// ------------------------------------------------------------------------
virtual void threadedSubImage(void* ptr) const;
// ------------------------------------------------------------------------
virtual void cleanThreadedLoader();
}; // HQMipmapGenerator
#endif
#endif

View File

@ -218,8 +218,10 @@ std::shared_ptr<video::IImage> SPTexture::getTextureImage() const
for (unsigned int i = 0; i < image->getDimension().Width *
image->getDimension().Height; i++)
{
const bool use_tex_compress = CVS->isTextureCompressionEnabled() &&
!m_cache_directory.empty();
#ifndef USE_GLES2
if (CVS->isTextureCompressionEnabled())
if (use_tex_compress)
{
#endif
// to RGBA for libsquish or for gles it's always true
@ -229,7 +231,7 @@ std::shared_ptr<video::IImage> SPTexture::getTextureImage() const
#ifndef USE_GLES2
}
#endif
if (m_undo_srgb && !CVS->isTextureCompressionEnabled())
if (m_undo_srgb && !use_tex_compress)
{
data[i * 4] = srgbToLinear(data[i * 4] / 255.0f);
data[i * 4 + 1] = srgbToLinear(data[i * 4 + 1] / 255.0f);
@ -927,8 +929,8 @@ std::vector<std::pair<core::dimension2du, unsigned> >
}
}
// For array textures all textures need to have a same internal format
const unsigned tc_flag = squish::kDxt5 | stk_config->m_tc_quality |
(m_undo_srgb && CVS->useArrayTextures() ? squish::kToLinear : 0);
const unsigned tc_flag = squish::kDxt5 | stk_config->m_tc_quality;
// | (m_undo_srgb && CVS->useArrayTextures() ? squish::kToLinear : 0);
const unsigned compressed_size = squish::GetStorageRequirements(
mipmap_sizes[0].first.Width, mipmap_sizes[0].first.Height,
tc_flag);

View File

@ -19,7 +19,6 @@
#include "config/hardware_stats.hpp"
#include "config/user_config.hpp"
#include "graphics/central_settings.hpp"
#include "graphics/threaded_tex_loader.hpp"
#include "graphics/stk_texture.hpp"
#include "io/file_manager.hpp"
#include "utils/string_utils.hpp"
@ -27,95 +26,12 @@
#include <algorithm>
// ----------------------------------------------------------------------------
STKTexManager::STKTexManager() : m_pbo(0), m_thread_size(0),
m_threaded_load_textures_counter(0)
{
createThreadedTexLoaders();
} // STKTexManager
// ----------------------------------------------------------------------------
STKTexManager::~STKTexManager()
{
removeTexture(NULL/*texture*/, true/*remove_all*/);
destroyThreadedTexLoaders();
} // ~STKTexManager
// ----------------------------------------------------------------------------
void STKTexManager::createThreadedTexLoaders()
{
#if !(defined(SERVER_ONLY) || defined(USE_GLES2))
if (CVS->supportsThreadedTextureLoading())
{
pthread_mutex_init(&m_threaded_load_textures_mutex, NULL);
pthread_cond_init(&m_cond_request, NULL);
m_thread_size = HardwareStats::getNumProcessors();
if (m_thread_size == 0)
m_thread_size = 1;
m_thread_size = core::clamp(m_thread_size, 1,
UserConfigParams::m_hq_mipmap ? m_thread_size : 3);
const unsigned max_tex_size =
(UserConfigParams::m_high_definition_textures & 0x01) == 0 ?
UserConfigParams::m_max_texture_size : 2048;
const unsigned each_capacity = max_tex_size * max_tex_size * 4;
const unsigned pbo_size = each_capacity * m_thread_size;
Log::info("STKTexManager", "%d thread(s) for texture loading,"
" each capacity %d MB.", m_thread_size,
each_capacity / 1024 / 1024);
if (UserConfigParams::m_hq_mipmap)
Log::info("STKTexManager", "High quality mipmap enabled.");
glGenBuffers(1, &m_pbo);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, m_pbo);
glBufferStorage(GL_PIXEL_UNPACK_BUFFER, pbo_size, NULL,
GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT |
GL_MAP_COHERENT_BIT);
uint8_t* pbo_ptr = (uint8_t*)glMapBufferRange(GL_PIXEL_UNPACK_BUFFER,
0, pbo_size, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT |
GL_MAP_COHERENT_BIT);
size_t offset = 0;
for (int i = 0; i < m_thread_size; i++)
{
m_all_tex_loaders.push_back(new ThreadedTexLoader(each_capacity,
offset, pbo_ptr + offset, &m_threaded_load_textures_mutex,
&m_cond_request, this));
offset += each_capacity;
}
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
}
#endif
} // createThreadedTexLoaders
// ----------------------------------------------------------------------------
void STKTexManager::destroyThreadedTexLoaders()
{
#if !(defined(SERVER_ONLY) || defined(USE_GLES2))
if (CVS->supportsThreadedTextureLoading())
{
STKTexture* delete_ttl = new STKTexture((uint8_t*)NULL, "delete_ttl",
0, false, true);
for (int i = 0; i < m_thread_size; i++)
addThreadedLoadTexture(delete_ttl);
for (int i = 0; i < m_thread_size; i++)
{
if (!m_all_tex_loaders[i]->waitForReadyToDeleted(2.0f))
{
Log::info("STKTexManager", "ThreadedTexLoader %d not stopping,"
"exiting anyway.", i);
}
delete m_all_tex_loaders[i];
}
delete delete_ttl;
glDeleteBuffers(1, &m_pbo);
pthread_mutex_destroy(&m_threaded_load_textures_mutex);
pthread_cond_destroy(&m_cond_request);
m_pbo = 0;
m_thread_size = 0;
m_threaded_load_textures_counter = 0;
m_all_tex_loaders.clear();
}
#endif
} // destroyThreadedTexLoaders
// ----------------------------------------------------------------------------
STKTexture* STKTexManager::findTextureInFileSystem(const std::string& filename,
std::string* full_path)
@ -185,11 +101,6 @@ video::ITexture* STKTexManager::getTexture(const std::string& path,
delete new_texture;
return NULL;
}
if (new_texture->useThreadedLoading())
{
addThreadedLoadTexture(new_texture);
checkThreadedLoadTextures(false/*util_queue_empty*/);
}
}
if (create_if_unfound && !no_upload)
@ -267,23 +178,6 @@ int STKTexManager::dumpTextureUsage()
return size;
} // dumpAllTexture
// ----------------------------------------------------------------------------
video::ITexture* STKTexManager::getUnicolorTexture(const irr::video::SColor &c)
{
std::string name = StringUtils::toString(c.color) + "unic";
auto ret = m_all_textures.find(name);
if (ret != m_all_textures.end())
return ret->second;
uint8_t* data = new uint8_t[2 * 2 * 4];
memcpy(data, &c.color, sizeof(video::SColor));
memcpy(data + 4, &c.color, sizeof(video::SColor));
memcpy(data + 8, &c.color, sizeof(video::SColor));
memcpy(data + 12, &c.color, sizeof(video::SColor));
return addTexture(new STKTexture(data, name, 2));
} // getUnicolorTexture
// ----------------------------------------------------------------------------
core::stringw STKTexManager::reloadTexture(const irr::core::stringw& name)
{
@ -299,10 +193,6 @@ core::stringw STKTexManager::reloadTexture(const irr::core::stringw& name)
if (p.second == NULL || !p.second->isMeshTexture())
continue;
p.second->reload();
if (p.second->useThreadedLoading())
{
addThreadedLoadTexture(p.second);
}
Log::info("STKTexManager", "%s reloaded",
p.second->getName().getPtr());
}
@ -325,10 +215,6 @@ core::stringw STKTexManager::reloadTexture(const irr::core::stringw& name)
if (fname == tex_name || fname == tex_path)
{
p.second->reload();
if (p.second->useThreadedLoading())
{
addThreadedLoadTexture(p.second);
}
result += tex_name.c_str();
result += L" ";
break;
@ -341,11 +227,6 @@ core::stringw STKTexManager::reloadTexture(const irr::core::stringw& name)
return result + "reloaded.";
} // reloadTexture
// ----------------------------------------------------------------------------
void STKTexManager::reset()
{
} // reset
// ----------------------------------------------------------------------------
/** Sets an error message to be displayed when a texture is not found. This
* error message is shown before the "Texture %s not found or invalid"
@ -363,78 +244,3 @@ void STKTexManager::setTextureErrorMessage(const std::string &error,
else
m_texture_error_message = StringUtils::insertValues(error, detail);
} // setTextureErrorMessage
// ----------------------------------------------------------------------------
void STKTexManager::checkThreadedLoadTextures(bool util_queue_empty)
{
#if !(defined(SERVER_ONLY) || defined(USE_GLES2))
if (!CVS->supportsThreadedTextureLoading()) return;
bool uploaded = false;
bool empty_queue = false;
if (util_queue_empty)
{
while (true)
{
pthread_mutex_lock(&m_threaded_load_textures_mutex);
empty_queue = m_threaded_load_textures_counter == 0;
pthread_mutex_unlock(&m_threaded_load_textures_mutex);
if (empty_queue)
{
for (ThreadedTexLoader* ttl : m_all_tex_loaders)
{
if (ttl->lastQueueReady())
{
ttl->lock();
ttl->setFinishLoading();
uploaded = true;
ttl->unlock(false/*finish_it*/);
}
}
break;
}
else
{
checkThreadedLoadTextures(false/*util_queue_empty*/);
}
}
}
if (empty_queue && !uploaded)
return;
uploaded = false;
for (ThreadedTexLoader* ttl : m_all_tex_loaders)
{
ttl->lock();
if (ttl->finishedLoading())
{
if (!uploaded)
{
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, m_pbo);
uploaded = true;
}
ttl->handleCompletedTextures();
}
else
{
ttl->unlock(false/*finish_it*/);
}
}
if (uploaded)
{
GLsync sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
GLenum reason = glClientWaitSync(sync, GL_SYNC_FLUSH_COMMANDS_BIT, 0);
if (reason != GL_ALREADY_SIGNALED)
{
do
{
reason = glClientWaitSync(sync, GL_SYNC_FLUSH_COMMANDS_BIT,
1000000);
}
while (reason == GL_TIMEOUT_EXPIRED);
}
glDeleteSync(sync);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
for (ThreadedTexLoader* ttl : m_all_tex_loaders)
ttl->unlock(true/*finish_it*/);
}
#endif
} // checkThreadedLoadTextures

View File

@ -69,37 +69,12 @@ private:
* This is used to specify details like: "while loading kart '...'" */
std::string m_texture_error_message;
std::vector<ThreadedTexLoader*> m_all_tex_loaders;
GLuint m_pbo;
int m_thread_size;
class SmallestTexture
{
public:
inline bool operator()(const irr::video::ITexture* a,
const irr::video::ITexture* b) const
{
return a->getTextureSize() > b->getTextureSize();
}
};
std::priority_queue<irr::video::ITexture*,
std::vector<irr::video::ITexture*>, SmallestTexture>
m_threaded_load_textures;
int m_threaded_load_textures_counter;
pthread_mutex_t m_threaded_load_textures_mutex;
pthread_cond_t m_cond_request;
// ------------------------------------------------------------------------
STKTexture* findTextureInFileSystem(const std::string& filename,
std::string* full_path);
public:
// ------------------------------------------------------------------------
STKTexManager();
STKTexManager() {}
// ------------------------------------------------------------------------
~STKTexManager();
// ------------------------------------------------------------------------
@ -108,8 +83,6 @@ public:
bool no_upload = false,
bool create_if_unfound = true);
// ------------------------------------------------------------------------
irr::video::ITexture* getUnicolorTexture(const irr::video::SColor &c);
// ------------------------------------------------------------------------
irr::video::ITexture* addTexture(STKTexture* texture);
// ------------------------------------------------------------------------
void removeTexture(STKTexture* texture, bool remove_all = false);
@ -120,8 +93,6 @@ public:
// ------------------------------------------------------------------------
irr::core::stringw reloadTexture(const irr::core::stringw& name);
// ------------------------------------------------------------------------
void reset();
// ------------------------------------------------------------------------
/** Returns the currently defined texture error message, which is used
* by event_handler.cpp to print additional info about irrlicht
* internal errors or warnings. If no error message is currently
@ -174,35 +145,6 @@ public:
return getTexture(filename, std::string(error_message),
std::string(detail));
} // getTexture
// ------------------------------------------------------------------------
void checkThreadedLoadTextures(bool util_queue_empty);
// ------------------------------------------------------------------------
irr::video::ITexture* getThreadedLoadTexture()
{ return m_threaded_load_textures.top(); }
// ------------------------------------------------------------------------
void setThreadedLoadTextureCounter(int val)
{
m_threaded_load_textures_counter += val;
assert(m_threaded_load_textures_counter >= 0);
}
// ------------------------------------------------------------------------
void addThreadedLoadTexture(irr::video::ITexture* t)
{
pthread_mutex_lock(&m_threaded_load_textures_mutex);
m_threaded_load_textures.push(t);
setThreadedLoadTextureCounter(t->getThreadedLoadTextureCounter());
pthread_cond_signal(&m_cond_request);
pthread_mutex_unlock(&m_threaded_load_textures_mutex);
}
// ------------------------------------------------------------------------
void removeThreadedLoadTexture() { m_threaded_load_textures.pop(); }
// ------------------------------------------------------------------------
bool isThreadedLoadTexturesEmpty()
{ return m_threaded_load_textures.empty(); }
// ------------------------------------------------------------------------
void createThreadedTexLoaders();
// ------------------------------------------------------------------------
void destroyThreadedTexLoaders();
}; // STKTexManager

View File

@ -18,35 +18,22 @@
#include "graphics/stk_texture.hpp"
#include "config/user_config.hpp"
#include "graphics/central_settings.hpp"
#include "graphics/hq_mipmap_generator.hpp"
#include "graphics/irr_driver.hpp"
#include "graphics/material.hpp"
#include "graphics/material_manager.hpp"
#include "graphics/stk_tex_manager.hpp"
#include "graphics/irr_driver.hpp"
#include "modes/profile_world.hpp"
#include "utils/log.hpp"
#include "utils/string_utils.hpp"
#include <fstream>
#include <functional>
#if !defined(USE_GLES2)
static const uint8_t CACHE_VERSION = 2;
#endif
// ----------------------------------------------------------------------------
STKTexture::STKTexture(const std::string& path, TexConfig* tc, bool no_upload)
: video::ITexture(path.c_str()), m_texture_handle(0),
m_single_channel(false), m_tex_config(NULL), m_material(NULL),
m_texture_name(0), m_texture_size(0), m_texture_image(NULL),
m_file(NULL), m_img_loader(NULL)
: video::ITexture(path.c_str()), m_single_channel(false),
m_tex_config(NULL), m_texture_name(0), m_texture_size(0),
m_texture_image(NULL)
{
if (tc != NULL)
{
m_tex_config = (TexConfig*)malloc(sizeof(TexConfig));
memcpy(m_tex_config, tc, sizeof(TexConfig));
m_single_channel = m_tex_config->m_colorization_mask;
if (m_tex_config->m_set_material)
m_material = material_manager->getMaterialFor(this);
}
#ifndef SERVER_ONLY
if (m_tex_config)
@ -66,25 +53,22 @@ STKTexture::STKTexture(const std::string& path, TexConfig* tc, bool no_upload)
// ----------------------------------------------------------------------------
STKTexture::STKTexture(uint8_t* data, const std::string& name, unsigned int size,
bool single_channel, bool delete_ttl)
: video::ITexture(name.c_str()), m_texture_handle(0),
m_single_channel(single_channel), m_tex_config(NULL),
m_material(NULL), m_texture_name(0), m_texture_size(0),
m_texture_image(NULL), m_file(NULL), m_img_loader(NULL)
bool single_channel)
: video::ITexture(name.c_str()), m_single_channel(single_channel),
m_tex_config(NULL), m_texture_name(0), m_texture_size(0),
m_texture_image(NULL)
{
m_size.Width = size;
m_size.Height = size;
m_orig_size = m_size;
if (!delete_ttl)
reload(false/*no_upload*/, data);
reload(false/*no_upload*/, data);
} // STKTexture
// ----------------------------------------------------------------------------
STKTexture::STKTexture(video::IImage* img, const std::string& name)
: video::ITexture(name.c_str()), m_texture_handle(0),
m_single_channel(false), m_tex_config(NULL), m_material(NULL),
m_texture_name(0), m_texture_size(0), m_texture_image(NULL),
m_file(NULL), m_img_loader(NULL)
: video::ITexture(name.c_str()), m_single_channel(false),
m_tex_config(NULL), m_texture_name(0), m_texture_size(0),
m_texture_image(NULL)
{
reload(false/*no_upload*/, NULL/*preload_data*/, img);
} // STKTexture
@ -93,7 +77,6 @@ STKTexture::STKTexture(video::IImage* img, const std::string& name)
STKTexture::~STKTexture()
{
#ifndef SERVER_ONLY
unloadHandle();
if (m_texture_name != 0)
{
glDeleteTextures(1, &m_texture_name);
@ -122,112 +105,34 @@ void STKTexture::reload(bool no_upload, uint8_t* preload_data,
}
#ifndef SERVER_ONLY
std::string compressed_texture;
#if !defined(USE_GLES2)
if (!no_upload && isMeshTexture() && CVS->isTextureCompressionEnabled())
{
std::string orig_file = NamedPath.getPtr();
std::string basename = StringUtils::getBasename(orig_file);
std::string container_id;
if (file_manager->searchTextureContainerId(container_id, basename))
{
std::string cache_subdir = "hd/";
if ((UserConfigParams::m_high_definition_textures & 0x01) == 0x01)
{
cache_subdir = "hd/";
}
else
{
cache_subdir = StringUtils::insertValues("resized_%i/",
(int)UserConfigParams::m_max_texture_size);
}
std::string cache_dir = file_manager->getCachedTexturesDir() +
cache_subdir + container_id;
compressed_texture = cache_dir + "/" + basename + ".stktz";
if ((!file_manager->fileExists(compressed_texture) ||
file_manager->fileIsNewer(compressed_texture, orig_file)) &&
loadCompressedTexture(compressed_texture))
{
Log::debug("STKTexture", "Compressed %s for texture %s",
compressed_texture.c_str(), orig_file.c_str());
return;
}
file_manager->checkAndCreateDirectoryP(cache_dir);
}
else
{
Log::warn("STKTexture", "Cannot find container_id for texture %s",
orig_file.c_str());
}
}
#endif
video::IImage* orig_img = NULL;
uint8_t* data = preload_data;
if (data == NULL)
{
if (preload_img)
orig_img = preload_img;
else
orig_img = preload_img ? preload_img :
irr_driver->getVideoDriver()->createImageFromFile(NamedPath);
if (orig_img == NULL)
{
m_file = irr_driver->getDevice()->getFileSystem()
->createAndOpenFile(NamedPath);
if (m_file == NULL)
return;
irr_driver->getVideoDriver()->createImageFromFile(m_file,
&m_img_loader);
if (m_img_loader == NULL)
return;
m_file->seek(0);
m_orig_size = m_img_loader->getImageSize(m_file);
if ((!m_material || m_material->getAlphaMask().empty()) &&
useThreadedLoading() && !no_upload)
{
if (m_orig_size.Width == 0 || m_orig_size.Height == 0)
{
m_file->drop();
m_file = NULL;
m_img_loader = NULL;
return;
}
}
else
{
orig_img = m_img_loader->loadImage(m_file);
m_file->drop();
m_file = NULL;
if (orig_img == NULL || orig_img->getDimension().Width == 0 ||
orig_img->getDimension().Height == 0)
{
if (orig_img)
orig_img->drop();
return;
}
m_img_loader = NULL;
}
return;
}
if (orig_img->getDimension().Width == 0 ||
orig_img->getDimension().Height == 0)
{
orig_img->drop();
return;
}
orig_img = resizeImage(orig_img, &m_orig_size, &m_size);
applyMask(orig_img);
data = orig_img ? (uint8_t*)orig_img->lock() : NULL;
if (m_single_channel && !useThreadedLoading())
{
data = singleChannelConversion(data);
orig_img->unlock();
orig_img->drop();
orig_img = NULL;
}
}
const unsigned int w = m_size.Width;
const unsigned int h = m_size.Height;
unsigned int format = m_single_channel ? GL_RED : GL_BGRA;
unsigned int internal_format = m_single_channel ? GL_R8 : isSrgb() ?
GL_SRGB8_ALPHA8 : GL_RGBA8;
unsigned int internal_format = m_single_channel ? GL_R8 : isSrgb() ?
GL_SRGB8_ALPHA8 : GL_RGBA8;
// GLES 2.0 specs doesn't allow GL_RGBA8 internal format
// GLES 2.0 specs doesn't allow GL_RGBA8 internal format
#if defined(USE_GLES2)
if (!CVS->isGLSL())
{
@ -235,17 +140,7 @@ void STKTexture::reload(bool no_upload, uint8_t* preload_data,
}
#endif
#if !defined(USE_GLES2)
if (isMeshTexture() && CVS->isTextureCompressionEnabled())
{
internal_format = m_single_channel ? GL_COMPRESSED_RED_RGTC1 :
isSrgb() ? GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT :
GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
}
#endif
if (!useThreadedLoading())
formatConversion(data, &format, w, h);
formatConversion(data, &format, w, h);
if (!no_upload)
{
@ -264,35 +159,17 @@ void STKTexture::reload(bool no_upload, uint8_t* preload_data,
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_ONE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_RED);
}
if (useThreadedLoading())
{
int levels = 1;
int width = w;
int height = h;
while (true)
{
width = width < 2 ? 1 : width >> 1;
height = height < 2 ? 1 : height >> 1;
levels++;
if (width == 1 && height == 1)
break;
}
glTexStorage2D(GL_TEXTURE_2D, levels, internal_format, w, h);
}
else
{
glTexImage2D(GL_TEXTURE_2D, 0, internal_format, w, h, 0, format,
GL_UNSIGNED_BYTE, data);
}
glTexImage2D(GL_TEXTURE_2D, 0, internal_format, w, h, 0, format,
GL_UNSIGNED_BYTE, data);
}
else if (!useThreadedLoading())
else
{
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, format,
GL_UNSIGNED_BYTE, data);
}
if (orig_img)
orig_img->unlock();
if (!useThreadedLoading() && hasMipMaps())
if (hasMipMaps())
glGenerateMipmap(GL_TEXTURE_2D);
}
@ -304,8 +181,6 @@ void STKTexture::reload(bool no_upload, uint8_t* preload_data,
else
delete[] data;
if (!compressed_texture.empty())
saveCompressedTexture(compressed_texture);
if (!no_upload)
glBindTexture(GL_TEXTURE_2D, 0);
@ -398,201 +273,6 @@ video::IImage* STKTexture::resizeImage(video::IImage* orig_img,
return image;
} // resizeImage
// ----------------------------------------------------------------------------
void STKTexture::applyMask(video::IImage* orig_img)
{
#ifndef SERVER_ONLY
if (m_material && !m_material->getAlphaMask().empty())
{
video::IImage* converted_mask = irr_driver->getVideoDriver()
->createImageFromFile(m_material->getAlphaMask().c_str());
if (converted_mask == NULL)
{
Log::warn("STKTexture", "Applying mask failed for '%s'!",
m_material->getAlphaMask().c_str());
return;
}
converted_mask = resizeImage(converted_mask);
if (converted_mask->lock())
{
const core::dimension2du& dim = orig_img->getDimension();
for (unsigned int x = 0; x < dim.Width; x++)
{
for (unsigned int y = 0; y < dim.Height; y++)
{
video::SColor col = orig_img->getPixel(x, y);
video::SColor alpha = converted_mask->getPixel(x, y);
col.setAlpha(alpha.getRed());
orig_img->setPixel(x, y, col, false);
} // for y
} // for x
}
converted_mask->unlock();
converted_mask->drop();
}
#endif // !SERVER_ONLY
} // applyMask
//-----------------------------------------------------------------------------
/** Try to load a compressed texture from the given file name.
* Data in the specified file need to have a specific format. See the
* saveCompressedTexture() function for a description of the format.
* \return true if the loading succeeded, false otherwise.
* \see saveCompressedTexture
*/
bool STKTexture::loadCompressedTexture(const std::string& file_name)
{
#if !(defined(SERVER_ONLY) || defined(USE_GLES2))
std::ifstream ifs(file_name.c_str(), std::ios::in | std::ios::binary);
if (!ifs.is_open())
return false;
int internal_format;
uint8_t cache_verison;
ifs.read((char*)&cache_verison, sizeof(uint8_t));
if (cache_verison != CACHE_VERSION)
{
Log::debug("STKTexture", "%s version %d is not supported!",
file_name.c_str(), cache_verison);
ifs.close();
std::remove(file_name.c_str());
return false;
}
ifs.read((char*)&internal_format, sizeof(int));
ifs.read((char*)&m_size.Width, sizeof(unsigned int));
ifs.read((char*)&m_size.Height, sizeof(unsigned int));
ifs.read((char*)&m_orig_size.Width, sizeof(unsigned int));
ifs.read((char*)&m_orig_size.Height, sizeof(unsigned int));
ifs.read((char*)&m_texture_size, sizeof(unsigned int));
if (ifs.fail() || m_texture_size == 0)
return false;
std::vector<char> compressed;
compressed.resize(m_texture_size);
ifs.read(compressed.data(), m_texture_size);
if (!ifs.fail())
{
// No on the fly reload is supported for compressed texture
assert(m_texture_name == 0);
glGenTextures(1, &m_texture_name);
glBindTexture(GL_TEXTURE_2D, m_texture_name);
if (internal_format == GL_COMPRESSED_RED_RGTC1)
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_ONE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, GL_ONE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_ONE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_RED);
}
glCompressedTexImage2D(GL_TEXTURE_2D, 0, internal_format,
m_size.Width, m_size.Height, 0, m_texture_size, compressed.data());
unsigned width = m_size.Width;
unsigned height = m_size.Height;
std::vector<std::pair<unsigned, unsigned> > mipmap_sizes;
while (true)
{
width = width < 2 ? 1 : width >> 1;
height = height < 2 ? 1 : height >> 1;
mipmap_sizes.emplace_back(width, height);
if (width == 1 && height == 1)
break;
}
for (unsigned i = 0; i < mipmap_sizes.size(); i++)
{
unsigned cur_mipmap_size = 0;
ifs.read((char*)&cur_mipmap_size, sizeof(unsigned int));
ifs.read(compressed.data(), cur_mipmap_size);
if (cur_mipmap_size == 0 || ifs.fail())
{
ifs.close();
std::remove(file_name.c_str());
return false;
}
glCompressedTexImage2D(GL_TEXTURE_2D, i + 1, internal_format,
mipmap_sizes[i].first, mipmap_sizes[i].second, 0,
cur_mipmap_size, compressed.data());
}
glBindTexture(GL_TEXTURE_2D, 0);
return true;
}
ifs.close();
std::remove(file_name.c_str());
#endif
return false;
} // loadCompressedTexture
//-----------------------------------------------------------------------------
/** Try to save the last texture sent to glTexImage2D in a file of the given
* file name. This function should only be used for textures sent to
* glTexImage2D with a compressed internal format as argument.<br>
* \note The following format is used to save the compressed texture:<br>
* <version><internal-format><w><h><orig_w><orig_h><size><data> <br>
* The first element is the version of cache, next six elements are
* integers and the last one is stored on \c size bytes.
* \see loadCompressedTexture
*/
void STKTexture::saveCompressedTexture(const std::string& compressed_tex)
{
#if !(defined(SERVER_ONLY) || defined(USE_GLES2))
int internal_format;
int compression_successful = 0;
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT,
(GLint *)&internal_format);
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH,
(GLint *)&m_size.Width);
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT,
(GLint *)&m_size.Height);
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_COMPRESSED,
(GLint *)&compression_successful);
if (compression_successful == 0) return;
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0,
GL_TEXTURE_COMPRESSED_IMAGE_SIZE, (GLint *)&m_texture_size);
if (m_texture_size == 0) return;
std::vector<char> compressed;
compressed.resize(m_texture_size);
glGetCompressedTexImage(GL_TEXTURE_2D, 0, compressed.data());
std::ofstream ofs(compressed_tex.c_str(),
std::ios::out | std::ios::binary);
if (ofs.is_open())
{
ofs.write((char*)&CACHE_VERSION, sizeof(uint8_t));
ofs.write((char*)&internal_format, sizeof(int));
ofs.write((char*)&m_size.Width, sizeof(unsigned int));
ofs.write((char*)&m_size.Height, sizeof(unsigned int));
ofs.write((char*)&m_orig_size.Width, sizeof(unsigned int));
ofs.write((char*)&m_orig_size.Height, sizeof(unsigned int));
ofs.write((char*)&m_texture_size, sizeof(unsigned int));
ofs.write(compressed.data(), m_texture_size);
unsigned width = m_size.Width;
unsigned height = m_size.Height;
std::vector<std::pair<unsigned, unsigned> > mipmap_sizes;
while (true)
{
width = width < 2 ? 1 : width >> 1;
height = height < 2 ? 1 : height >> 1;
mipmap_sizes.emplace_back(width, height);
if (width == 1 && height == 1)
break;
}
for (unsigned i = 0; i < mipmap_sizes.size(); i++)
{
GLint cur_mipmap_size = 0;
glGetTexLevelParameteriv(GL_TEXTURE_2D, i + 1,
GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &cur_mipmap_size);
if (cur_mipmap_size == 0)
{
ofs.close();
std::remove(compressed_tex.c_str());
}
glGetCompressedTexImage(GL_TEXTURE_2D, i + 1, compressed.data());
ofs.write((char*)&cur_mipmap_size, sizeof(unsigned int));
ofs.write(compressed.data(), cur_mipmap_size);
}
}
#endif
} // saveCompressedTexture
//-----------------------------------------------------------------------------
bool STKTexture::hasMipMaps() const
{
@ -623,97 +303,6 @@ void* STKTexture::lock(video::E_TEXTURE_LOCK_MODE mode, u32 mipmap_level)
return NULL;
} // lock
//-----------------------------------------------------------------------------
u64 STKTexture::getHandle()
{
return m_texture_handle;
} // getHandle
//-----------------------------------------------------------------------------
void STKTexture::unloadHandle()
{
} // unloadHandle
//-----------------------------------------------------------------------------
bool STKTexture::useThreadedLoading() const
{
#ifdef SERVER_ONLY
return false;
#else
return CVS->supportsThreadedTextureLoading() &&
!CVS->isTextureCompressionEnabled() && isMeshTexture() &&
m_img_loader && m_img_loader->supportThreadedLoading();
#endif
} // useThreadedLoading
//-----------------------------------------------------------------------------
void STKTexture::threadedReload(void* ptr, void* param) const
{
#if !(defined(SERVER_ONLY) || defined(USE_GLES2))
video::IImage* orig_img =
m_img_loader->loadImage(m_file, true/*skip_checking*/);
orig_img = resizeImage(orig_img);
uint8_t* data = (uint8_t*)orig_img->lock();
if (m_single_channel)
{
data = singleChannelConversion(data);
orig_img->unlock();
orig_img->drop();
orig_img = NULL;
}
formatConversion(data, NULL, m_size.Width, m_size.Height);
memcpy(ptr, data, m_texture_size);
if (orig_img)
{
orig_img->unlock();
orig_img->setDeleteMemory(false);
orig_img->drop();
}
if (useHQMipmap())
{
HQMipmapGenerator* hqmg = new HQMipmapGenerator(NamedPath, data,
m_size, m_texture_name, m_tex_config);
((STKTexManager*)(param))->addThreadedLoadTexture(hqmg);
}
else
delete[] data;
#endif
} // threadedReload
//-----------------------------------------------------------------------------
void STKTexture::threadedSubImage(void* ptr) const
{
#if !(defined(SERVER_ONLY) || defined(USE_GLES2))
glBindTexture(GL_TEXTURE_2D, m_texture_name);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_size.Width, m_size.Height,
m_single_channel ? GL_RED : GL_BGRA, GL_UNSIGNED_BYTE, ptr);
if (useHQMipmap())
return;
if (hasMipMaps())
glGenerateMipmap(GL_TEXTURE_2D);
#endif
} // threadedSubImage
//-----------------------------------------------------------------------------
void STKTexture::cleanThreadedLoader()
{
#if !(defined(SERVER_ONLY) || defined(USE_GLES2))
assert(m_file);
m_file->drop();
m_file = NULL;
m_img_loader = NULL;
#endif
} // cleanThreadedLoader
//-----------------------------------------------------------------------------
bool STKTexture::useHQMipmap() const
{
return !m_single_channel && UserConfigParams::m_hq_mipmap &&
m_size.Width > 1 && m_size.Height > 1;
} // useHQMipmap
//-----------------------------------------------------------------------------
bool STKTexture::isSrgb() const
{

View File

@ -24,64 +24,33 @@
#include <string>
#include <ITexture.h>
namespace irr
{
namespace io { class IReadFile; }
namespace video { class IImageLoader; }
}
using namespace irr;
struct TexConfig;
class Material;
class STKTexture : public video::ITexture, NoCopy
{
private:
core::dimension2d<u32> m_size, m_orig_size;
uint64_t m_texture_handle;
bool m_single_channel;
TexConfig* m_tex_config;
Material* m_material;
GLuint m_texture_name;
unsigned int m_texture_size;
video::IImage* m_texture_image;
io::IReadFile* m_file;
video::IImageLoader* m_img_loader;
// ------------------------------------------------------------------------
video::IImage* resizeImage(video::IImage* orig_img,
core::dimension2du* orig_size = NULL,
core::dimension2du* final_size = NULL) const;
// ------------------------------------------------------------------------
void applyMask(video::IImage* orig_img);
// ------------------------------------------------------------------------
bool loadCompressedTexture(const std::string& file_name);
// ------------------------------------------------------------------------
void saveCompressedTexture(const std::string& file_name);
// ------------------------------------------------------------------------
void formatConversion(uint8_t* data, unsigned int* format, unsigned int w,
unsigned int h) const;
// ------------------------------------------------------------------------
uint8_t* singleChannelConversion(uint8_t* data) const
{
uint8_t* sc = new uint8_t[m_size.Width * m_size.Height];
for (unsigned int i = 0; i < m_size.Width * m_size.Height; i++)
sc[i] = data[4 * i + 3];
return sc;
}
// ------------------------------------------------------------------------
bool useHQMipmap() const;
// ------------------------------------------------------------------------
bool isSrgb() const;
// ------------------------------------------------------------------------
bool isPremulAlpha() const;
@ -91,7 +60,7 @@ public:
STKTexture(const std::string& path, TexConfig* tc, bool no_upload = false);
// ------------------------------------------------------------------------
STKTexture(uint8_t* data, const std::string& name, unsigned int size,
bool single_channel = false, bool delete_ttl = false);
bool single_channel = false);
// ------------------------------------------------------------------------
STKTexture(video::IImage* img, const std::string& name);
// ------------------------------------------------------------------------
@ -131,10 +100,6 @@ public:
// ------------------------------------------------------------------------
virtual u32 getOpenGLTextureName() const { return m_texture_name; }
// ------------------------------------------------------------------------
virtual u64 getHandle();
// ------------------------------------------------------------------------
virtual void unloadHandle();
// ------------------------------------------------------------------------
virtual unsigned int getTextureSize() const { return m_texture_size; }
// ------------------------------------------------------------------------
void reload(bool no_upload = false, uint8_t* preload_data = NULL,
@ -142,19 +107,6 @@ public:
// ------------------------------------------------------------------------
video::IImage* getTextureImage() { return m_texture_image; }
// ------------------------------------------------------------------------
bool useThreadedLoading() const;
// ------------------------------------------------------------------------
virtual void threadedReload(void* ptr, void* param) const;
// ------------------------------------------------------------------------
virtual void threadedSubImage(void* ptr) const;
// ------------------------------------------------------------------------
virtual void cleanThreadedLoader();
// ------------------------------------------------------------------------
virtual int getThreadedLoadTextureCounter() const
{
return useHQMipmap() ? 2 : 1;
}
// ------------------------------------------------------------------------
bool isMeshTexture() const;
}; // STKTexture

View File

@ -1,100 +0,0 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2017 SuperTuxKart-Team
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#if !(defined(SERVER_ONLY) || defined(USE_GLES2))
#include "graphics/threaded_tex_loader.hpp"
#include "graphics/stk_tex_manager.hpp"
#include "utils/string_utils.hpp"
#include "utils/vs.hpp"
#include <cassert>
#include <ITexture.h>
// ----------------------------------------------------------------------------
void* ThreadedTexLoader::startRoutine(void *obj)
{
ThreadedTexLoader* ttl = (ThreadedTexLoader*)obj;
VS::setThreadName((std::string("ThrTexLoader") +
StringUtils::toString(ttl->m_pbo_offset / 1024 / 1024)).c_str());
while (true)
{
pthread_mutex_lock(&ttl->m_mutex);
bool finished = ttl->finishedLoading();
pthread_mutex_unlock(&ttl->m_mutex);
if (finished)
{
continue;
}
pthread_mutex_lock(ttl->m_texture_queue_mutex);
bool waiting = ttl->m_stktm->isThreadedLoadTexturesEmpty();
ttl->m_last_queue_ready.setAtomic(!ttl->m_completed_textures.empty() &&
waiting);
while (waiting)
{
pthread_cond_wait(ttl->m_cond_request, ttl->m_texture_queue_mutex);
waiting = ttl->m_stktm->isThreadedLoadTexturesEmpty();
}
irr::video::ITexture* target_tex =
ttl->m_stktm->getThreadedLoadTexture();
if (strcmp(target_tex->getName().getPtr(), "delete_ttl") == 0)
{
ttl->m_stktm->removeThreadedLoadTexture();
ttl->m_stktm->setThreadedLoadTextureCounter(-1);
pthread_mutex_unlock(ttl->m_texture_queue_mutex);
ttl->setCanBeDeleted();
return NULL;
}
assert(target_tex->getTextureSize() <= ttl->m_tex_capacity);
if (target_tex->getTextureSize() + ttl->m_tex_size_loaded >
ttl->m_tex_capacity)
{
pthread_mutex_lock(&ttl->m_mutex);
ttl->setFinishLoading();
pthread_mutex_unlock(&ttl->m_mutex);
pthread_mutex_unlock(ttl->m_texture_queue_mutex);
continue;
}
ttl->m_stktm->removeThreadedLoadTexture();
pthread_mutex_unlock(ttl->m_texture_queue_mutex);
target_tex->threadedReload(ttl->m_pbo_ptr + ttl->m_tex_size_loaded,
ttl->m_stktm);
target_tex->cleanThreadedLoader();
ttl->m_tex_size_loaded += target_tex->getTextureSize();
ttl->m_completed_textures.push_back(target_tex);
pthread_mutex_lock(ttl->m_texture_queue_mutex);
ttl->m_stktm->setThreadedLoadTextureCounter(-1);
pthread_mutex_unlock(ttl->m_texture_queue_mutex);
}
return NULL;
} // startRoutine
// ----------------------------------------------------------------------------
void ThreadedTexLoader::handleCompletedTextures()
{
assert(m_locked);
size_t offset = m_pbo_offset;
for (irr::video::ITexture* tex : m_completed_textures)
{
size_t cur_offset = tex->getTextureSize();
tex->threadedSubImage((void*)offset);
offset += cur_offset;
}
m_completed_textures.clear();
} // handleCompletedTextures
#endif

View File

@ -1,118 +0,0 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2017 SuperTuxKart-Team
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifndef HEADER_THREADED_TEX_LOADER_HPP
#define HEADER_THREADED_TEX_LOADER_HPP
#if !(defined(SERVER_ONLY) || defined(USE_GLES2))
#include "utils/can_be_deleted.hpp"
#include "utils/no_copy.hpp"
#include "utils/synchronised.hpp"
#include "utils/types.hpp"
#include <vector>
namespace irr
{
namespace video { class ITexture; }
}
class STKTexManager;
class ThreadedTexLoader : public NoCopy, public CanBeDeleted
{
private:
const unsigned m_tex_capacity;
const size_t m_pbo_offset;
uint8_t* m_pbo_ptr;
pthread_mutex_t m_mutex;
pthread_mutex_t* m_texture_queue_mutex;
pthread_cond_t* m_cond_request;
STKTexManager* m_stktm;
unsigned m_tex_size_loaded;
pthread_t m_thread;
bool m_finished_loading, m_locked;
Synchronised<bool> m_last_queue_ready;
std::vector<irr::video::ITexture*> m_completed_textures;
public:
// ------------------------------------------------------------------------
static void* startRoutine(void *obj);
// ------------------------------------------------------------------------
ThreadedTexLoader(unsigned capacity, size_t offset, uint8_t* pbo_ptr,
pthread_mutex_t* mutex, pthread_cond_t* cond,
STKTexManager* stktm)
: m_tex_capacity(capacity), m_pbo_offset(offset),
m_pbo_ptr(pbo_ptr), m_texture_queue_mutex(mutex),
m_cond_request(cond), m_stktm(stktm),
m_tex_size_loaded(0), m_finished_loading(false),
m_locked(false), m_last_queue_ready(false)
{
pthread_mutex_init(&m_mutex, NULL);
pthread_create(&m_thread, NULL, &startRoutine, this);
}
// ------------------------------------------------------------------------
~ThreadedTexLoader()
{
pthread_mutex_destroy(&m_mutex);
pthread_join(m_thread, NULL);
}
// ------------------------------------------------------------------------
bool finishedLoading() const { return m_finished_loading; }
// ------------------------------------------------------------------------
void setFinishLoading()
{
m_last_queue_ready.setAtomic(false);
m_finished_loading = true;
m_tex_size_loaded = 0;
}
// ------------------------------------------------------------------------
bool lastQueueReady() const { return m_last_queue_ready.getAtomic(); }
// ------------------------------------------------------------------------
void handleCompletedTextures();
// ------------------------------------------------------------------------
void lock()
{
pthread_mutex_lock(&m_mutex);
m_locked = true;
}
// ------------------------------------------------------------------------
void unlock(bool finish_it)
{
if (!m_locked) return;
m_locked = false;
if (finish_it)
m_finished_loading = false;
pthread_mutex_unlock(&m_mutex);
}
}; // ThreadedTexLoader
#endif
#endif

View File

@ -23,7 +23,6 @@
#include "config/user_config.hpp"
#include "graphics/central_settings.hpp"
#include "graphics/irr_driver.hpp"
#include "graphics/stk_tex_manager.hpp"
#include "guiengine/screen.hpp"
#include "guiengine/widgets/button_widget.hpp"
#include "guiengine/widgets/check_box_widget.hpp"
@ -649,8 +648,6 @@ void OptionsScreenVideo::tearDown()
else if (m_prev_img_quality != getImageQuality())
{
irr_driver->setMaxTextureSize();
STKTexManager::getInstance()->destroyThreadedTexLoaders();
STKTexManager::getInstance()->createThreadedTexLoaders();
}
Screen::tearDown();
// save changes when leaving screen