From 8a51e05c2ed7a1c2552a0a2a1ba8184beeb8930c Mon Sep 17 00:00:00 2001 From: vladislavbelov Date: Mon, 11 Apr 2022 16:28:41 +0000 Subject: [PATCH] Avoids a crash if a texture size is not a power of two. Tested By: Stan Differential Revision: https://code.wildfiregames.com/D4586 This was SVN commit r26774. --- .../mods/_test.tex/art/textures/b/npot.png | 3 +++ source/graphics/TextureConverter.cpp | 14 ++++++++++--- source/graphics/TextureManager.cpp | 21 ++++++++++++++----- source/graphics/tests/test_TextureConverter.h | 20 ++++++++++++------ source/ps/Profiler2GPU.cpp | 5 +++++ 5 files changed, 49 insertions(+), 14 deletions(-) create mode 100644 binaries/data/mods/_test.tex/art/textures/b/npot.png diff --git a/binaries/data/mods/_test.tex/art/textures/b/npot.png b/binaries/data/mods/_test.tex/art/textures/b/npot.png new file mode 100644 index 0000000000..2d3d04f0a1 --- /dev/null +++ b/binaries/data/mods/_test.tex/art/textures/b/npot.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9e5c835a1c27c338216b6c12c1c3ccaf6b3a262f9abce38fefe05053612547d5 +size 131 diff --git a/source/graphics/TextureConverter.cpp b/source/graphics/TextureConverter.cpp index a4ff4d23d2..9ad1246af5 100644 --- a/source/graphics/TextureConverter.cpp +++ b/source/graphics/TextureConverter.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2021 Wildfire Games. +/* Copyright (C) 2022 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -19,10 +19,11 @@ #include "TextureConverter.h" -#include "lib/regex.h" -#include "lib/timer.h" #include "lib/allocators/shared_ptr.h" +#include "lib/bits.h" +#include "lib/regex.h" #include "lib/tex/tex.h" +#include "lib/timer.h" #include "maths/MD5.h" #include "ps/CLogger.h" #include "ps/CStr.h" @@ -347,6 +348,13 @@ bool CTextureConverter::ConvertTexture(const CTexturePtr& texture, const VfsPath return false; } + if (!is_pow2(tex.m_Width) || !is_pow2(tex.m_Height)) + { + LOGERROR("Texture to convert \"%s\" should have width and height be power of two: %zux%zu", + src.string8(), tex.m_Width, tex.m_Height); + return false; + } + // Check whether there's any alpha channel bool hasAlpha = ((tex.m_Flags & TEX_ALPHA) != 0); diff --git a/source/graphics/TextureManager.cpp b/source/graphics/TextureManager.cpp index 0b3c80230d..8bca789531 100644 --- a/source/graphics/TextureManager.cpp +++ b/source/graphics/TextureManager.cpp @@ -22,6 +22,7 @@ #include "graphics/Color.h" #include "graphics/TextureConverter.h" #include "lib/allocators/shared_ptr.h" +#include "lib/bits.h" #include "lib/file/vfs/vfs_tree.h" #include "lib/hash.h" #include "lib/timer.h" @@ -408,6 +409,17 @@ public: LOGERROR("Texture failed to load; \"%s\"", texture->m_Properties.m_Path.string8()); texture->ResetBackendTexture( nullptr, m_ErrorTexture.GetTexture()->GetBackendTexture()); + texture->m_TextureData.reset(); + return; + } + + if (!is_pow2(textureData.m_Width) || !is_pow2(textureData.m_Height)) + { + LOGERROR("Texture should have width and height be power of two; \"%s\" %zux%zu", + texture->m_Properties.m_Path.string8(), textureData.m_Width, textureData.m_Height); + texture->ResetBackendTexture( + nullptr, m_ErrorTexture.GetTexture()->GetBackendTexture()); + texture->m_TextureData.reset(); return; } @@ -442,6 +454,7 @@ public: LOGERROR("Texture failed to choose format; \"%s\"", texture->m_Properties.m_Path.string8()); texture->ResetBackendTexture( nullptr, m_ErrorTexture.GetTexture()->GetBackendTexture()); + texture->m_TextureData.reset(); return; } @@ -557,7 +570,7 @@ public: */ void ConvertTexture(const CTexturePtr& texture) { - VfsPath sourcePath = texture->m_Properties.m_Path; + const VfsPath sourcePath = texture->m_Properties.m_Path; PROFILE2("convert texture"); PROFILE2_ATTR("name: %ls", sourcePath.string().c_str()); @@ -565,9 +578,7 @@ public: MD5 hash; u32 version; PrepareCacheKey(texture, hash, version); - VfsPath looseCachePath = m_CacheLoader.LooseCachePath(sourcePath, hash, version); - -// LOGWARNING("Converting texture \"%s\"", srcPath.c_str()); + const VfsPath looseCachePath = m_CacheLoader.LooseCachePath(sourcePath, hash, version); CTextureConverter::Settings settings = GetConverterSettings(texture); @@ -854,7 +865,7 @@ void CTexture::UploadBackendTextureIfNeeded( if (!IsLoaded()) return; - else if (!m_TextureData) + else if (!m_TextureData || !m_BackendTexture) { ResetBackendTexture(nullptr, m_TextureManager->GetErrorTexture()->GetBackendTexture()); m_State = UPLOADED; diff --git a/source/graphics/tests/test_TextureConverter.h b/source/graphics/tests/test_TextureConverter.h index d9fe399777..8cd4316417 100644 --- a/source/graphics/tests/test_TextureConverter.h +++ b/source/graphics/tests/test_TextureConverter.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2021 Wildfire Games. +/* Copyright (C) 2022 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -85,11 +85,19 @@ public: TS_ASSERT_DIFFERS(texdata[0*4], texdata[8*4]); TS_ASSERT_EQUALS(texdata[8*4], texdata[16*4]); TS_ASSERT_DIFFERS(texdata[16*4], texdata[24*4]); + } -// for (size_t i = 0; i < tex.dataSize; ++i) -// { -// if (i % 4 == 0) printf("\n"); -// printf("%02x ", texdata[i]); -// } + void test_not_pot() + { + // CTextureConverter prints to logs in case of an error. + TestLogger logger; + + const VfsPath path = L"art/textures/b/npot.png"; + + CTextureConverter converter(m_VFS, false); + CTextureConverter::Settings settings = + converter.ComputeSettings(L"", std::vector()); + TS_ASSERT(!converter.ConvertTexture(CTexturePtr(), path, L"cache/npot.png", settings)); + TS_ASSERT(logger.GetOutput().find("be power of two") != std::string::npos); } }; diff --git a/source/ps/Profiler2GPU.cpp b/source/ps/Profiler2GPU.cpp index 44bba0ff5c..5255b9dd87 100644 --- a/source/ps/Profiler2GPU.cpp +++ b/source/ps/Profiler2GPU.cpp @@ -286,6 +286,11 @@ void CProfiler2GPU::RegionLeave(const char* id) #else // CONFIG2_GLES +class CProfiler2GPUARB +{ +public: +}; + CProfiler2GPU::CProfiler2GPU(CProfiler2& profiler) : m_Profiler(profiler) {