From fb1579929adcb19cb9e37a8e782b7d29af414bcf Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Fri, 9 Dec 2022 18:12:39 +0000 Subject: Save texture to TGA using mmap Removes the need to allocate a large temporary buffer, instead just memmaps a file big enough and has OpenGL write the texture data directly to it. --- gfx/models/texture.cpp | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) (limited to 'gfx/models') diff --git a/gfx/models/texture.cpp b/gfx/models/texture.cpp index 645920f..5b8d376 100644 --- a/gfx/models/texture.cpp +++ b/gfx/models/texture.cpp @@ -7,6 +7,7 @@ #include #include #include +#include Cache Texture::cachedTexture; @@ -44,17 +45,23 @@ void Texture::save(const glTexture & texture, GLenum format, const glm::ivec2 & size, unsigned short channels, const char * path, short tgaFormat) { - using PixelData = std::vector; - PixelData buffer(static_cast(size.x * size.y * channels)); - glGetTextureImage(texture, 0, format, GL_UNSIGNED_BYTE, static_cast(buffer.size()), buffer.data()); + using TGAHead = std::array; - auto out = open(path, O_WRONLY | O_CREAT, 0660); - const short TGAhead[] = {0, tgaFormat, 0, 0, 0, 0, static_cast(size.x), static_cast(size.y), - static_cast(8 * channels)}; - std::ignore = write(out, &TGAhead, sizeof(TGAhead)); - std::ignore = write(out, buffer.data(), buffer.size()); - std::ignore = ftruncate(out, static_cast(buffer.size() + sizeof(TGAhead))); + size_t dataSize = (static_cast(size.x * size.y * channels)); + size_t fileSize = dataSize + sizeof(TGAHead); + + auto out = open(path, O_RDWR | O_CREAT, 0660); + std::ignore = ftruncate(out, static_cast(fileSize)); + TGAHead * tga = static_cast(mmap(nullptr, fileSize, PROT_WRITE, MAP_SHARED, out, 0)); close(out); + if (tga == MAP_FAILED) { + return; + } + *tga = {0, tgaFormat, 0, 0, 0, 0, static_cast(size.x), static_cast(size.y), + static_cast(8 * channels)}; + glGetTextureImage(texture, 0, format, GL_UNSIGNED_BYTE, static_cast(dataSize), tga + 1); + msync(tga, fileSize, MS_ASYNC); + munmap(tga, fileSize); } void -- cgit v1.2.3