1
0
forked from 0ad/0ad

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.
This commit is contained in:
Vladislav Belov 2022-04-11 16:28:41 +00:00
parent b55c71ab88
commit 8a51e05c2e
5 changed files with 49 additions and 14 deletions

BIN
binaries/data/mods/_test.tex/art/textures/b/npot.png (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2021 Wildfire Games. /* Copyright (C) 2022 Wildfire Games.
* This file is part of 0 A.D. * This file is part of 0 A.D.
* *
* 0 A.D. is free software: you can redistribute it and/or modify * 0 A.D. is free software: you can redistribute it and/or modify
@ -19,10 +19,11 @@
#include "TextureConverter.h" #include "TextureConverter.h"
#include "lib/regex.h"
#include "lib/timer.h"
#include "lib/allocators/shared_ptr.h" #include "lib/allocators/shared_ptr.h"
#include "lib/bits.h"
#include "lib/regex.h"
#include "lib/tex/tex.h" #include "lib/tex/tex.h"
#include "lib/timer.h"
#include "maths/MD5.h" #include "maths/MD5.h"
#include "ps/CLogger.h" #include "ps/CLogger.h"
#include "ps/CStr.h" #include "ps/CStr.h"
@ -347,6 +348,13 @@ bool CTextureConverter::ConvertTexture(const CTexturePtr& texture, const VfsPath
return false; 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 // Check whether there's any alpha channel
bool hasAlpha = ((tex.m_Flags & TEX_ALPHA) != 0); bool hasAlpha = ((tex.m_Flags & TEX_ALPHA) != 0);

View File

@ -22,6 +22,7 @@
#include "graphics/Color.h" #include "graphics/Color.h"
#include "graphics/TextureConverter.h" #include "graphics/TextureConverter.h"
#include "lib/allocators/shared_ptr.h" #include "lib/allocators/shared_ptr.h"
#include "lib/bits.h"
#include "lib/file/vfs/vfs_tree.h" #include "lib/file/vfs/vfs_tree.h"
#include "lib/hash.h" #include "lib/hash.h"
#include "lib/timer.h" #include "lib/timer.h"
@ -408,6 +409,17 @@ public:
LOGERROR("Texture failed to load; \"%s\"", texture->m_Properties.m_Path.string8()); LOGERROR("Texture failed to load; \"%s\"", texture->m_Properties.m_Path.string8());
texture->ResetBackendTexture( texture->ResetBackendTexture(
nullptr, m_ErrorTexture.GetTexture()->GetBackendTexture()); 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; return;
} }
@ -442,6 +454,7 @@ public:
LOGERROR("Texture failed to choose format; \"%s\"", texture->m_Properties.m_Path.string8()); LOGERROR("Texture failed to choose format; \"%s\"", texture->m_Properties.m_Path.string8());
texture->ResetBackendTexture( texture->ResetBackendTexture(
nullptr, m_ErrorTexture.GetTexture()->GetBackendTexture()); nullptr, m_ErrorTexture.GetTexture()->GetBackendTexture());
texture->m_TextureData.reset();
return; return;
} }
@ -557,7 +570,7 @@ public:
*/ */
void ConvertTexture(const CTexturePtr& texture) void ConvertTexture(const CTexturePtr& texture)
{ {
VfsPath sourcePath = texture->m_Properties.m_Path; const VfsPath sourcePath = texture->m_Properties.m_Path;
PROFILE2("convert texture"); PROFILE2("convert texture");
PROFILE2_ATTR("name: %ls", sourcePath.string().c_str()); PROFILE2_ATTR("name: %ls", sourcePath.string().c_str());
@ -565,9 +578,7 @@ public:
MD5 hash; MD5 hash;
u32 version; u32 version;
PrepareCacheKey(texture, hash, version); PrepareCacheKey(texture, hash, version);
VfsPath looseCachePath = m_CacheLoader.LooseCachePath(sourcePath, hash, version); const VfsPath looseCachePath = m_CacheLoader.LooseCachePath(sourcePath, hash, version);
// LOGWARNING("Converting texture \"%s\"", srcPath.c_str());
CTextureConverter::Settings settings = GetConverterSettings(texture); CTextureConverter::Settings settings = GetConverterSettings(texture);
@ -854,7 +865,7 @@ void CTexture::UploadBackendTextureIfNeeded(
if (!IsLoaded()) if (!IsLoaded())
return; return;
else if (!m_TextureData) else if (!m_TextureData || !m_BackendTexture)
{ {
ResetBackendTexture(nullptr, m_TextureManager->GetErrorTexture()->GetBackendTexture()); ResetBackendTexture(nullptr, m_TextureManager->GetErrorTexture()->GetBackendTexture());
m_State = UPLOADED; m_State = UPLOADED;

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2021 Wildfire Games. /* Copyright (C) 2022 Wildfire Games.
* This file is part of 0 A.D. * This file is part of 0 A.D.
* *
* 0 A.D. is free software: you can redistribute it and/or modify * 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_DIFFERS(texdata[0*4], texdata[8*4]);
TS_ASSERT_EQUALS(texdata[8*4], texdata[16*4]); TS_ASSERT_EQUALS(texdata[8*4], texdata[16*4]);
TS_ASSERT_DIFFERS(texdata[16*4], texdata[24*4]); TS_ASSERT_DIFFERS(texdata[16*4], texdata[24*4]);
}
// for (size_t i = 0; i < tex.dataSize; ++i) void test_not_pot()
// { {
// if (i % 4 == 0) printf("\n"); // CTextureConverter prints to logs in case of an error.
// printf("%02x ", texdata[i]); TestLogger logger;
// }
const VfsPath path = L"art/textures/b/npot.png";
CTextureConverter converter(m_VFS, false);
CTextureConverter::Settings settings =
converter.ComputeSettings(L"", std::vector<CTextureConverter::SettingsFile*>());
TS_ASSERT(!converter.ConvertTexture(CTexturePtr(), path, L"cache/npot.png", settings));
TS_ASSERT(logger.GetOutput().find("be power of two") != std::string::npos);
} }
}; };

View File

@ -286,6 +286,11 @@ void CProfiler2GPU::RegionLeave(const char* id)
#else // CONFIG2_GLES #else // CONFIG2_GLES
class CProfiler2GPUARB
{
public:
};
CProfiler2GPU::CProfiler2GPU(CProfiler2& profiler) : CProfiler2GPU::CProfiler2GPU(CProfiler2& profiler) :
m_Profiler(profiler) m_Profiler(profiler)
{ {