SuperTuxKart 1.5 upstream source (from official release tarball)

This commit is contained in:
Benjamin
2026-06-11 20:04:02 +02:00
commit 2957e51aaa
8551 changed files with 1801800 additions and 0 deletions
+240
View File
@@ -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
}