From 00fc3cb9b2c06026fab0e4760609fe02e027b6df Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sun, 8 Mar 2026 16:02:56 +0000 Subject: Move all low level texture operations to DSA helpers in glTexture --- gfx/gl/glTexture.cpp | 161 ++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 152 insertions(+), 9 deletions(-) (limited to 'gfx/gl/glTexture.cpp') diff --git a/gfx/gl/glTexture.cpp b/gfx/gl/glTexture.cpp index 8dcf16f..e334d5e 100644 --- a/gfx/gl/glTexture.cpp +++ b/gfx/gl/glTexture.cpp @@ -1,18 +1,161 @@ #include "glTexture.h" +#include "filesystem.h" +#include "gfx/models/tga.h" +#include +#include +#include -TextureDimensions -Impl::glTexture::getSize() const +void +Impl::glTextureBase::bind(const GLuint unit) const +{ + glBindTextureUnit(unit, name); +} + +void +Impl::glTextureBase::generateMipmap() +{ + glGenerateTextureMipmap(name); +} + +template + requires(Dims >= 1 && Dims <= 3) +glm::vec +Impl::glTextureDims::getSize() const { - TextureDimensions size {}; - glGetTextureLevelParameteriv(name, 0, GL_TEXTURE_WIDTH, &size.x); - glGetTextureLevelParameteriv(name, 0, GL_TEXTURE_HEIGHT, &size.y); - glGetTextureLevelParameteriv(name, 0, GL_TEXTURE_DEPTH, &size.z); + static constexpr std::array PARAMS {GL_TEXTURE_WIDTH, GL_TEXTURE_HEIGHT, GL_TEXTURE_DEPTH}; + glm::vec size {}; + for (auto [dim, param] : std::views::enumerate(PARAMS) | std::views::take(Dims)) { + glGetTextureLevelParameteriv(name, 0, param, &size[static_cast(dim)]); + } return size; } +template<> +void +Impl::glTextureDims<1>::storage(const GLsizei levels, const GLenum internalformat, glm::vec<1, GLsizei> dims) +{ + glTextureStorage1D(name, levels, internalformat, dims.x); +} + +template<> +void +Impl::glTextureDims<2>::storage(const GLsizei levels, const GLenum internalformat, glm::vec<2, GLsizei> dims) +{ + glTextureStorage2D(name, levels, internalformat, dims.x, dims.y); +} + +template<> +void +Impl::glTextureDims<3>::storage(const GLsizei levels, const GLenum internalformat, glm::vec<3, GLsizei> dims) +{ + glTextureStorage3D(name, levels, internalformat, dims.x, dims.y, dims.z); +} + +template<> +void +Impl::glTextureDims<1>::subImage( + glm::vec<1, GLint> offset, glm::vec<1, GLint> size, const GLenum format, const GLenum type, const void * pixels) +{ + glTextureSubImage1D(name, 0, offset.x, size.x, format, type, pixels); +} + +template<> +void +Impl::glTextureDims<2>::subImage( + glm::vec<2, GLint> offset, glm::vec<2, GLint> size, const GLenum format, const GLenum type, const void * pixels) +{ + glTextureSubImage2D(name, 0, offset.x, offset.y, size.x, size.y, format, type, pixels); +} + +template<> void -Impl::glTexture::bind(GLenum type, GLenum unit) const +Impl::glTextureDims<3>::subImage( + glm::vec<3, GLint> offset, glm::vec<3, GLint> size, const GLenum format, const GLenum type, const void * pixels) { - glActiveTexture(unit); - glBindTexture(type, name); + glTextureSubImage3D(name, 0, offset.x, offset.y, offset.z, size.x, size.y, size.z, format, type, pixels); } + +template + requires(Dims >= 1 && Dims <= 3) +void +Impl::glTextureDims::image( + glm::vec size, const GLenum format, const GLenum type, const void * pixels) +{ + subImage({}, size, format, type, pixels); +} + +template + requires(Dims >= 1 && Dims <= 3) +void +Impl::glTextureDims::image(const GLenum format, const GLenum type, const void * pixels) +{ + image(getSize(), format, type, pixels); +} + +namespace { + template + requires(Dims >= 1 && Dims <= 3) + void + save(const Impl::glTextureDims & texture, const GLenum format, const GLenum type, uint8_t channels, + const char * path, uint8_t tgaFormat) + { + const auto size = texture.getSize(); + const auto area = [size]() { + size_t area = 1; + for (auto dim = 0; dim < Dims; ++dim) { + area *= static_cast(size[dim]); + } + return area; + }(); + size_t dataSize = area * channels; + const size_t fileSize = dataSize + sizeof(TGAHead); + + filesystem::fh out {path, O_RDWR | O_CREAT, 0660}; + out.truncate(fileSize); + auto tga = out.mmap(fileSize, 0, PROT_WRITE, MAP_SHARED); + *tga.get() = { + .format = tgaFormat, + .size = {size.x, 1 * (area / static_cast(size.x))}, + .pixelDepth = static_cast(8 * channels), + }; + glPixelStorei(GL_PACK_ALIGNMENT, 1); + glGetTextureImage(texture, 0, format, type, static_cast(dataSize), tga.get() + 1); + tga.msync(MS_ASYNC); + } +} + +template + requires(Dims >= 1 && Dims <= 3) +void +Impl::glTextureDims::saveColour(const char * path) const +{ + save(*this, GL_BGR, GL_UNSIGNED_BYTE, 3, path, 2); +} + +template + requires(Dims >= 1 && Dims <= 3) +void +Impl::glTextureDims::savePosition(const char * path) const +{ + save(*this, GL_BGR_INTEGER, GL_UNSIGNED_BYTE, 3, path, 2); +} + +template + requires(Dims >= 1 && Dims <= 3) +void +Impl::glTextureDims::saveDepth(const char * path) const +{ + save(*this, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 1, path, 3); +} + +template + requires(Dims >= 1 && Dims <= 3) +void +Impl::glTextureDims::saveNormal(const char * path) const +{ + save(*this, GL_BGR, GL_BYTE, 3, path, 2); +} + +template struct Impl::glTextureDims<1>; +template struct Impl::glTextureDims<2>; +template struct Impl::glTextureDims<3>; -- cgit v1.3