diff options
| author | Xavier Del Campo Romero <xavi92@disroot.org> | 2025-12-04 13:58:02 +0100 |
|---|---|---|
| committer | Xavier Del Campo Romero <xavi92@disroot.org> | 2025-12-15 23:04:39 +0100 |
| commit | 600ff28dd73f2cf17725382b68a4b1b2573f2e34 (patch) | |
| tree | a105c686458d8998438652aeca6299cf9000edcd /src/dtx/dtx.cpp | |
Diffstat (limited to 'src/dtx/dtx.cpp')
| -rw-r--r-- | src/dtx/dtx.cpp | 207 |
1 files changed, 207 insertions, 0 deletions
diff --git a/src/dtx/dtx.cpp b/src/dtx/dtx.cpp new file mode 100644 index 0000000..463bb1d --- /dev/null +++ b/src/dtx/dtx.cpp @@ -0,0 +1,207 @@ +#include <dtx.h> +#include <rez/file.h> +#include <GL/gl.h> +#include <GL/glext.h> +#include <cstdint> +#include <cstdio> +#include <iostream> + +int dtx::draw() const +{ + int ret = 0; + GLenum error; + + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, texture); + + if (bpp == bpp_s3tc_dxt5) + { + glEnable(GL_BLEND); + glBlendFunc(GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA); + } + + glBegin(GL_QUADS); + glTexCoord2f(0.0f, 0.0f); glVertex2f(-0.5f, 0.5f); + glTexCoord2f(0.0f, 1.0f); glVertex2f(0.5f, 0.5f); + glTexCoord2f(1.0f, 1.0f); glVertex2f(0.5f, -0.5f); + glTexCoord2f(1.0f, 0.0f); glVertex2f(-0.5f, -0.5f); + glEnd(); + + glFlush(); + glDisable(GL_BLEND); + glDisable(GL_TEXTURE_2D); + + while ((error = glGetError()) != GL_NO_ERROR) + { + ret = -1; + fprintf(stderr, "%s:%d: glGetError returned %x\n", __FILE__, + __LINE__, error); + } + + return ret; +} + +int dtx::parse(rez::file &f) +{ + uint32_t restype, uversion; + + if (f.read_le(restype) || f.read_le(uversion)) + return -1; + + const uint32_t exp_type = 0; + const int32_t exp_version = -5; + int32_t version = uversion; + + if (restype != exp_type) + { + std::cerr << f.path() << ": invalid resource type " << restype + << ", expected " << exp_type << '\n'; + return -1; + } + else if (version != exp_version) + { + std::cerr << f.path() << ": invalid or unsupported version " << version + << ", expected " << exp_version << '\n'; + return -1; + } + + const uint16_t max_mipmaps = 8; + uint16_t w, h, n_mipmaps, n_sections, tex_angle; + uint32_t iflags, userflags, tex_scale; + unsigned char tex_group, n_rtmipmaps, bpp, mipmap_off_nc, mipmap_off, + tex_prio; + char cmd[128]; + + if (f.read_le(w) + || f.read_le(h) + || f.read_le(n_mipmaps) + || f.read_le(n_sections)) + { + std::cerr << f.path() << ": failed to read header\n"; + return -1; + } + else if (!n_mipmaps || n_mipmaps > max_mipmaps) + { + std::cerr << f.path() << ": invalid number of mipmaps: " + << n_mipmaps << '\n'; + return -1; + } + else if (f.read_le(iflags) || f.read_le(userflags)) + { + std::cerr << f.path() << ": failed to read flags\n"; + return -1; + } + else if (f.read(tex_group) + || f.read(n_rtmipmaps) + || f.read(bpp) + || f.read(mipmap_off_nc) + || f.read(mipmap_off) + || f.read(tex_prio) + || f.read_le(tex_scale) + || f.read_le(tex_angle)) + { + std::cerr << f.path() << ": failed to read extra data\n"; + return -1; + } + else if (bpp != bpp::bpp_32 + && bpp != bpp::bpp_s3tc_dxt1 + && bpp != bpp::bpp_s3tc_dxt5) + { + std::cerr << f.path() << ": invalid or unsupported bpp " + << std::to_string(bpp) << ", expected " << bpp::bpp_s3tc_dxt1 + << ", " << bpp::bpp_32 << " or " << bpp::bpp_s3tc_dxt5 << '\n'; + return -1; + } + else if (f.read(cmd, sizeof cmd)) + { + std::cerr << f.path() << ": failed to read cmd\n"; + return -1; + } + + this->bpp = static_cast<enum bpp>(bpp); + this->w = w; + this->h = h; + + glGenTextures(1, &texture); + glBindTexture(GL_TEXTURE_2D, texture); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + + GLint level = 0; + + for (uint32_t i = 0; i < n_mipmaps; i++) + { + GLenum format; + unsigned long n_pix = (w >> i) * (h >> i); + pixdata mipmap; + + switch (this->bpp) + { + case bpp_32: + format = GL_BGRA; + n_pix *= sizeof (uint32_t); + break; + + case bpp_s3tc_dxt1: + format = GL_COMPRESSED_RGB_S3TC_DXT1_EXT; + n_pix >>= 1; + break; + + case bpp_s3tc_dxt5: + format = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; + break; + + default: + return -1; + } + + mipmap.reserve(n_pix); + + while (n_pix) + { + unsigned char buf[BUFSIZ]; + size_t n = n_pix > sizeof buf ? sizeof buf : n_pix; + + if (f.read(buf, n)) + return -1; + + mipmap.insert(mipmap.end(), buf, &buf[n]); + n_pix -= n; + } + + GLenum error; + int ret = 0; + + if (bpp == bpp::bpp_s3tc_dxt1 || bpp == bpp::bpp_s3tc_dxt5) + glCompressedTexImage2D(GL_TEXTURE_2D, level++, format, + w >> i, h >> i, 0, mipmap.size(), mipmap.data()); + else if (bpp == bpp::bpp_32) + glTexImage2D(GL_TEXTURE_2D, level++, format, w >> i, h >> i, 0, + format, GL_UNSIGNED_BYTE, mipmap.data()); + + while ((error = glGetError()) != GL_NO_ERROR) + { + fprintf(stderr, "%s:%d: glGetError returned %x\n", __FILE__, + __LINE__, error); + ret = -1; + } + + if (ret) + return ret; + } + + return 0; +} + +dtx::~dtx() +{ + if (texture) + glDeleteTextures(1, &texture); +} + +dtx::dtx() : + texture(0) +{ +} |
