SuperTuxKart 1.5 upstream source (from official release tarball)
This commit is contained in:
@@ -0,0 +1,240 @@
|
||||
#include "ge_gl_texture.hpp"
|
||||
#include "ge_gl_utils.hpp"
|
||||
#include "ge_main.hpp"
|
||||
#include "ge_texture.hpp"
|
||||
|
||||
#include <IAttributes.h>
|
||||
#include <vector>
|
||||
|
||||
// TODO remove it after vulkan is done
|
||||
namespace irr
|
||||
{
|
||||
namespace video { extern bool useCoreContext; }
|
||||
}
|
||||
|
||||
namespace GE
|
||||
{
|
||||
GEGLTexture::GEGLTexture(const std::string& path,
|
||||
std::function<void(video::IImage*)> image_mani)
|
||||
: video::ITexture(path.c_str()), m_image_mani(image_mani),
|
||||
m_locked_data(NULL), m_texture_name(0), m_texture_size(0),
|
||||
m_driver_type(GE::getDriver()->getDriverType()),
|
||||
m_disable_reload(false), m_single_channel(false)
|
||||
{
|
||||
reload();
|
||||
} // GEGLTexture
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
GEGLTexture::GEGLTexture(video::IImage* img, const std::string& name)
|
||||
: video::ITexture(name.c_str()), m_image_mani(nullptr),
|
||||
m_locked_data(NULL), m_texture_name(0), m_texture_size(0),
|
||||
m_driver_type(GE::getDriver()->getDriverType()),
|
||||
m_disable_reload(true), m_single_channel(false)
|
||||
{
|
||||
if (!img)
|
||||
{
|
||||
LoadingFailed = true;
|
||||
return;
|
||||
}
|
||||
glGenTextures(1, &m_texture_name);
|
||||
m_size = m_orig_size = img->getDimension();
|
||||
uint8_t* data = (uint8_t*)img->lock();
|
||||
upload(data);
|
||||
img->unlock();
|
||||
img->drop();
|
||||
} // GEGLTexture
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
GEGLTexture::GEGLTexture(const std::string& name, unsigned int size,
|
||||
bool single_channel)
|
||||
: video::ITexture(name.c_str()), m_image_mani(nullptr),
|
||||
m_locked_data(NULL), m_texture_name(0), m_texture_size(0),
|
||||
m_driver_type(GE::getDriver()->getDriverType()),
|
||||
m_disable_reload(true), m_single_channel(false)
|
||||
{
|
||||
glGenTextures(1, &m_texture_name);
|
||||
m_orig_size.Width = size;
|
||||
m_orig_size.Height = size;
|
||||
m_size = m_orig_size;
|
||||
|
||||
bool texture_swizzle = false;
|
||||
if (m_driver_type == video::EDT_OGLES2)
|
||||
{
|
||||
int gl_major_version = 0;
|
||||
glGetIntegerv(GL_MAJOR_VERSION, &gl_major_version);
|
||||
if (gl_major_version >=3)
|
||||
texture_swizzle = true;
|
||||
else
|
||||
texture_swizzle = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
texture_swizzle = irr::video::useCoreContext &&
|
||||
GE::hasGLExtension("GL_ARB_texture_swizzle");
|
||||
}
|
||||
|
||||
if (single_channel && texture_swizzle)
|
||||
m_single_channel = true;
|
||||
std::vector<uint8_t> data;
|
||||
data.resize(size * size * (m_single_channel ? 1 : 4), 0);
|
||||
upload(data.data());
|
||||
} // GEGLTexture
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
GEGLTexture::~GEGLTexture()
|
||||
{
|
||||
if (m_texture_name != 0)
|
||||
glDeleteTextures(1, &m_texture_name);
|
||||
} // ~GEGLTexture
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void GEGLTexture::reload()
|
||||
{
|
||||
if (m_disable_reload)
|
||||
return;
|
||||
const core::dimension2du & max_size = getDriver()->getDriverAttributes()
|
||||
.getAttributeAsDimension2d("MAX_TEXTURE_SIZE");
|
||||
video::IImage* texture_image = getResizedImage(NamedPath.getPtr(),
|
||||
max_size, &m_orig_size);
|
||||
if (texture_image == NULL)
|
||||
{
|
||||
LoadingFailed = true;
|
||||
return;
|
||||
}
|
||||
m_size = texture_image->getDimension();
|
||||
if (m_image_mani)
|
||||
m_image_mani(texture_image);
|
||||
if (m_texture_name == 0)
|
||||
glGenTextures(1, &m_texture_name);
|
||||
uint8_t* data = (uint8_t*)texture_image->lock();
|
||||
upload(data);
|
||||
texture_image->unlock();
|
||||
texture_image->drop();
|
||||
} // reload
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void GEGLTexture::upload(uint8_t* data)
|
||||
{
|
||||
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 : GL_RGBA8;
|
||||
|
||||
if (m_driver_type == video::EDT_OGLES2)
|
||||
{
|
||||
formatConversion(data, &format, w, h);
|
||||
int gl_major_version = 0;
|
||||
glGetIntegerv(GL_MAJOR_VERSION, &gl_major_version);
|
||||
// GLES 2.0 specs doesn't allow GL_RGBA8 internal format
|
||||
if (gl_major_version < 3)
|
||||
internal_format = GL_RGBA;
|
||||
}
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, m_texture_name);
|
||||
if (m_single_channel)
|
||||
{
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
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);
|
||||
}
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, internal_format, w, h, 0, format,
|
||||
GL_UNSIGNED_BYTE, data);
|
||||
if (hasMipMaps())
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
m_texture_size = w * h * (m_single_channel ? 1 : 4);
|
||||
} // upload
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void* GEGLTexture::lock(video::E_TEXTURE_LOCK_MODE mode, u32 mipmap_level)
|
||||
{
|
||||
if (mode != video::ETLM_READ_ONLY)
|
||||
return NULL;
|
||||
|
||||
if (m_driver_type == video::EDT_OGLES2 || !glGetTexImage)
|
||||
{
|
||||
const core::dimension2du & max_size = getDriver()->getDriverAttributes()
|
||||
.getAttributeAsDimension2d("MAX_TEXTURE_SIZE");
|
||||
video::IImage* img = getResizedImage(NamedPath.getPtr(), max_size,
|
||||
NULL, &m_size);
|
||||
if (!img)
|
||||
return NULL;
|
||||
img->setDeleteMemory(false);
|
||||
m_locked_data = (uint8_t*)img->lock();
|
||||
img->unlock();
|
||||
img->drop();
|
||||
return m_locked_data;
|
||||
}
|
||||
m_locked_data = new uint8_t[m_size.Width * m_size.Height * 4]();
|
||||
GLint tmp_texture;
|
||||
glGetIntegerv(GL_TEXTURE_BINDING_2D, &tmp_texture);
|
||||
glBindTexture(GL_TEXTURE_2D, m_texture_name);
|
||||
glGetTexImage(GL_TEXTURE_2D, 0, GL_BGRA, GL_UNSIGNED_BYTE, m_locked_data);
|
||||
glBindTexture(GL_TEXTURE_2D, tmp_texture);
|
||||
return m_locked_data;
|
||||
} // lock
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void GEGLTexture::formatConversion(uint8_t* data, unsigned int* format,
|
||||
unsigned int w, unsigned int h) const
|
||||
{
|
||||
if (!m_single_channel)
|
||||
{
|
||||
if (format)
|
||||
*format = GL_RGBA;
|
||||
for (unsigned int i = 0; i < w * h; i++)
|
||||
{
|
||||
uint8_t tmp_val = data[i * 4];
|
||||
data[i * 4] = data[i * 4 + 2];
|
||||
data[i * 4 + 2] = tmp_val;
|
||||
}
|
||||
}
|
||||
} // formatConversion
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void GEGLTexture::updateTexture(void* data, video::ECOLOR_FORMAT format, u32 w,
|
||||
u32 h, u32 x, u32 y)
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, m_texture_name);
|
||||
|
||||
if (m_single_channel)
|
||||
{
|
||||
if (format == video::ECF_R8)
|
||||
{
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, GL_RED,
|
||||
GL_UNSIGNED_BYTE, data);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (format == video::ECF_R8)
|
||||
{
|
||||
const unsigned int size = w * h;
|
||||
std::vector<uint8_t> image_data(size * 4, 255);
|
||||
uint8_t* orig_data = (uint8_t*)data;
|
||||
for (unsigned int i = 0; i < size; i++)
|
||||
image_data[4 * i + 3] = orig_data[i];
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, GL_RGBA,
|
||||
GL_UNSIGNED_BYTE, image_data.data());
|
||||
}
|
||||
else if (format == video::ECF_A8R8G8B8)
|
||||
{
|
||||
uint8_t* u8_data = (uint8_t*)data;
|
||||
for (unsigned int i = 0; i < w * h; i++)
|
||||
{
|
||||
uint8_t tmp_val = u8_data[i * 4];
|
||||
u8_data[i * 4] = u8_data[i * 4 + 2];
|
||||
u8_data[i * 4 + 2] = tmp_val;
|
||||
}
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, GL_RGBA,
|
||||
GL_UNSIGNED_BYTE, u8_data);
|
||||
}
|
||||
}
|
||||
if (hasMipMaps())
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
} // updateTexture
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user