Skip to content

Commit

Permalink
fix #5990
Browse files Browse the repository at this point in the history
  • Loading branch information
rt committed Jun 3, 2018
1 parent 2342626 commit 561e282
Show file tree
Hide file tree
Showing 9 changed files with 109 additions and 66 deletions.
23 changes: 8 additions & 15 deletions rts/Map/SMF/SMFReadMap.cpp
Expand Up @@ -194,11 +194,9 @@ void CSMFReadMap::CreateSpecularTex()
{
CBitmap specularTexBM;

if (!specularTexBM.Load(mapInfo->smf.specularTexName)) {
// maps wants specular lighting, but no moderation
specularTexBM.channels = 4;
// maps wants specular lighting, but no moderation
if (!specularTexBM.Load(mapInfo->smf.specularTexName))
specularTexBM.AllocDummy(SColor(255, 255, 255, 255));
}

specularTex.SetRawTexID(specularTexBM.CreateTexture());
specularTex.SetRawSize(int2(specularTexBM.xsize, specularTexBM.ysize));
Expand Down Expand Up @@ -252,11 +250,9 @@ void CSMFReadMap::CreateSplatDetailTextures()

// if a map supplies an intensity- AND a distribution-texture for
// detail-splat blending, the regular detail-texture is not used
if (!splatDetailTexBM.Load(mapInfo->smf.splatDetailTexName)) {
// default detail-texture should be all-grey
splatDetailTexBM.channels = 4;
splatDetailTexBM.AllocDummy(SColor(127,127,127,127));
}
// default detail-texture should be all-grey
if (!splatDetailTexBM.Load(mapInfo->smf.splatDetailTexName))
splatDetailTexBM.AllocDummy(SColor(127, 127, 127, 127));

splatDetailTex.SetRawTexID(splatDetailTexBM.CreateTexture(texAnisotropyLevels[true], 0.0f, true));
splatDetailTex.SetRawSize(int2(splatDetailTexBM.xsize, splatDetailTexBM.ysize));
Expand All @@ -265,10 +261,8 @@ void CSMFReadMap::CreateSplatDetailTextures()
{
CBitmap splatDistrTexBM;

if (!splatDistrTexBM.Load(mapInfo->smf.splatDistrTexName)) {
splatDistrTexBM.channels = 4;
splatDistrTexBM.AllocDummy(SColor(255,0,0,0));
}
if (!splatDistrTexBM.Load(mapInfo->smf.splatDistrTexName))
splatDistrTexBM.AllocDummy(SColor(255, 0, 0, 0));

splatDistrTex.SetRawTexID(splatDistrTexBM.CreateTexture(texAnisotropyLevels[true], 0.0f, true));
splatDistrTex.SetRawSize(int2(splatDistrTexBM.xsize, splatDistrTexBM.ysize));
Expand All @@ -285,8 +279,7 @@ void CSMFReadMap::CreateSplatDetailTextures()
CBitmap splatDetailNormalTextureBM;

if (!splatDetailNormalTextureBM.Load(mapInfo->smf.splatDetailNormalTexNames[i])) {
splatDetailNormalTextureBM.channels = 4;
splatDetailNormalTextureBM.Alloc(1, 1);
splatDetailNormalTextureBM.Alloc(1, 1, 4);
splatDetailNormalTextureBM.GetRawMem()[0] = 127; // RGB is packed standard normal map
splatDetailNormalTextureBM.GetRawMem()[1] = 127;
splatDetailNormalTextureBM.GetRawMem()[2] = 255; // With a single upward (+Z) pointing vector
Expand Down
3 changes: 1 addition & 2 deletions rts/Rendering/Env/GrassDrawer.cpp
Expand Up @@ -117,8 +117,7 @@ CGrassDrawer::CGrassDrawer(): CEventClient("[GrassDrawer]", 199992, false)
CBitmap grassBladeTexBM;
if (!grassBladeTexBM.Load(mapInfo->grass.bladeTexName)) {
// map didn't define a grasstex, so generate one
grassBladeTexBM.channels = 4;
grassBladeTexBM.Alloc(256, 64);
grassBladeTexBM.Alloc(256, 64, 4);

for (int a = 0; a < 16; ++a) {
CreateGrassBladeTex(&grassBladeTexBM.GetRawMem()[a * 16 * 4]);
Expand Down
31 changes: 30 additions & 1 deletion rts/Rendering/Fonts/CFontTexture.cpp
Expand Up @@ -351,6 +351,8 @@ CFontTexture::CFontTexture(const std::string& fontfile, int size, int _outlinesi
, wantedTexWidth(0)
, wantedTexHeight(0)
{
atlasGlyphs.reserve(1024);

if (fontSize <= 0)
fontSize = 14;

Expand Down Expand Up @@ -684,23 +686,50 @@ void CFontTexture::CreateTexture(const int width, const int height)

glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, 1, 1, 0, GL_RED, GL_UNSIGNED_BYTE, nullptr);

atlasUpdate = {};
atlasUpdate.Alloc(texWidth = wantedTexWidth = width, texHeight = wantedTexHeight = height, 1);

atlasUpdateShadow = {};
atlasUpdateShadow.Alloc(width, height, 1);
#endif
}

void CFontTexture::ReallocAtlases()
void CFontTexture::ReallocAtlases(bool pre)
{
#ifndef HEADLESS
assert(!atlasUpdate.Empty());


static std::vector<uint8_t> atlasMem;
static std::vector<uint8_t> atlasShadowMem;

if (pre) {
atlasMem.clear();
atlasMem.resize(atlasUpdate.GetMemSize());

atlasShadowMem.clear();
atlasShadowMem.resize(atlasUpdateShadow.GetMemSize());

memcpy(atlasMem.data(), atlasUpdate.GetRawMem(), atlasUpdate.GetMemSize());
memcpy(atlasShadowMem.data(), atlasUpdateShadow.GetRawMem(), atlasUpdateShadow.GetMemSize());

atlasUpdate = {};
atlasUpdateShadow = {};
return;
}


const int xsize = atlasUpdate.xsize;
const int ysize = atlasUpdate.ysize;

// NB: pool has already been wiped here, do not return memory to it but just realloc
atlasUpdate.Alloc(xsize, ysize, 1);
atlasUpdateShadow.Alloc(xsize, ysize, 1);

memcpy(atlasUpdate.GetRawMem(), atlasMem.data(), atlasMem.size());
memcpy(atlasUpdateShadow.GetRawMem(), atlasShadowMem.data(), atlasShadowMem.size());


if (atlasGlyphs.empty())
return;

Expand Down
2 changes: 1 addition & 1 deletion rts/Rendering/Fonts/CFontTexture.h
Expand Up @@ -99,7 +99,7 @@ class CFontTexture
const GlyphInfo& GetGlyph(char32_t ch); //< Get or load a glyph

public:
void ReallocAtlases();
void ReallocAtlases(bool pre);
protected:
void UpdateGlyphAtlasTexture();
private:
Expand Down
6 changes: 3 additions & 3 deletions rts/Rendering/Fonts/glFont.cpp
Expand Up @@ -117,12 +117,12 @@ CglFont* CglFont::LoadFont(const std::string& fontFile, int size, int outlinewid
}


void CglFont::ReallocAtlases()
void CglFont::ReallocAtlases(bool pre)
{
if (font != nullptr)
static_cast<CFontTexture*>(font)->ReallocAtlases();
static_cast<CFontTexture*>(font)->ReallocAtlases(pre);
if (smallFont != nullptr)
static_cast<CFontTexture*>(smallFont)->ReallocAtlases();
static_cast<CFontTexture*>(smallFont)->ReallocAtlases(pre);
}


Expand Down
2 changes: 1 addition & 1 deletion rts/Rendering/Fonts/glFont.h
Expand Up @@ -46,7 +46,7 @@ class CglFont : public CTextWrap
static bool LoadCustomFonts(const std::string& smallFontFile, const std::string& largeFontFile);
static CglFont* LoadFont(const std::string& fontFile, bool small);
static CglFont* LoadFont(const std::string& fontFile, int size, int outlinewidth = 2, float outlineweight = 5.0f);
static void ReallocAtlases();
static void ReallocAtlases(bool pre);

CglFont(const std::string& fontFile, int size, int outlinewidth, float outlineweight);
~CglFont();
Expand Down
88 changes: 53 additions & 35 deletions rts/Rendering/Textures/Bitmap.cpp
Expand Up @@ -26,6 +26,8 @@
#include "System/FileSystem/FileSystem.h"
#include "System/Threading/SpringThreading.h"

#define ENABLE_TEXMEMPOOL 1


struct InitializeOpenIL {
InitializeOpenIL() { ilInit(); }
Expand Down Expand Up @@ -61,7 +63,7 @@ struct TexMemPool {
}

uint8_t* AllocRaw(size_t size) {
#if 0
#if (ENABLE_TEXMEMPOOL == 0)
uint8_t* mem = new uint8_t[size];
#else
uint8_t* mem = nullptr;
Expand Down Expand Up @@ -105,7 +107,7 @@ struct TexMemPool {
freeList[bestPair].first += size;
freeList[bestPair].second -= size;
} else {
// exact match
// exact match, erase
freeList[bestPair] = freeList.back();
freeList.pop_back();
}
Expand All @@ -117,13 +119,13 @@ struct TexMemPool {
}


void Free(uint8_t* mem, size_t size) {
void Free(uint8_t*& mem, size_t size) {
std::lock_guard<spring::mutex> lck(bmpMutex);
FreeRaw(mem, size);
}

void FreeRaw(uint8_t*& mem, size_t size) {
#if 0
#if (ENABLE_TEXMEMPOOL == 0)
delete[] mem;
#else
if (mem == nullptr)
Expand All @@ -133,8 +135,23 @@ struct TexMemPool {
memset(mem, 0, size);
freeList.emplace_back(mem - &memArray[0], size);

#if 0
{
// check if freed mem overlaps any existing chunks
const FreePair& p = freeList.back();

for (size_t i = 0, n = freeList.size() - 1; i < n; i++) {
const FreePair& c = freeList[i];

assert(!((p.first < c.first) && (p.first + p.second) > c.first));
assert(!((c.first < p.first) && (c.first + c.second) > p.first));
}
}
#endif

numFrees += 1;
freeSize += size;
allocSize -= size;

// most bitmaps are transient, so keep the list short
// longer-lived textures should be allocated ASAP s.t.
Expand Down Expand Up @@ -182,7 +199,10 @@ struct TexMemPool {
}

bool DefragRaw() {
std::sort(freeList.begin(), freeList.end(), [](const FreePair& a, const FreePair& b) { return (a.first < b.first); });
constexpr auto sortPred = [](const FreePair& a, const FreePair& b) { return (a.first < b.first); };
constexpr auto accuPred = [](const FreePair& a, const FreePair& b) { return FreePair{0, a.second + b.second}; };

std::sort(freeList.begin(), freeList.end(), sortPred);

// merge adjacent chunks
for (size_t i = 0, n = freeList.size(); i < n; /**/) {
Expand All @@ -191,6 +211,8 @@ struct TexMemPool {
for (size_t j = i; j < n; j++) {
FreePair& nextPair = freeList[j];

assert(!((currPair.first + currPair.second) > nextPair.first));

if ((currPair.first + currPair.second) != nextPair.first)
break;

Expand All @@ -201,6 +223,7 @@ struct TexMemPool {
}
}


size_t i = 0;
size_t j = 0;

Expand All @@ -212,11 +235,14 @@ struct TexMemPool {
i += 1;
}


if (j >= freeList.size())
return false;

// shrink
freeList.resize(j);

freeSize = std::accumulate(freeList.begin(), freeList.end(), FreePair{0, 0}, accuPred).second;
return true;
}
};
Expand Down Expand Up @@ -248,17 +274,6 @@ static bool IsValidImageFormat(int format) {
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CBitmap::CBitmap()
: xsize(0)
, ysize(0)
, channels(4)
#ifndef BITMAP_NO_OPENGL
, textype(GL_TEXTURE_2D)
#endif
, compressed(false)
{
}

CBitmap::~CBitmap()
{
texMemPool.Free(mem, GetMemSize());
Expand All @@ -278,6 +293,9 @@ CBitmap::CBitmap(const uint8_t* data, int _xsize, int _ysize, int _channels)
mem = texMemPool.Alloc(GetMemSize());

if (data != nullptr) {
assert(!((mem < data) && (mem + GetMemSize()) > data));
assert(!((data < mem) && (data + GetMemSize()) > mem));

std::memcpy(mem, data, GetMemSize());
} else {
std::memset(mem, 0, GetMemSize());
Expand All @@ -292,6 +310,11 @@ CBitmap& CBitmap::operator=(const CBitmap& bmp)

if (bmp.mem != nullptr) {
assert(!bmp.compressed);
assert(bmp.GetMemSize() != 0);

assert(!((mem < bmp.GetRawMem()) && (mem + GetMemSize()) > bmp.GetRawMem()));
assert(!((bmp.GetRawMem() < mem) && (bmp.GetRawMem() + bmp.GetMemSize()) > mem));

mem = texMemPool.Alloc(bmp.GetMemSize());
std::memcpy(mem, bmp.mem, bmp.GetMemSize());
}
Expand All @@ -308,30 +331,24 @@ CBitmap& CBitmap::operator=(const CBitmap& bmp)
#endif
}

assert(GetMemSize() == bmp.GetMemSize());
assert((GetRawMem() != nullptr) == (bmp.GetRawMem() != nullptr));
return *this;
}

CBitmap& CBitmap::operator=(CBitmap&& bmp)
{
if (this != &bmp) {
mem = bmp.mem;
bmp.mem = nullptr;

xsize = bmp.xsize;
ysize = bmp.ysize;
channels = bmp.channels;
compressed = bmp.compressed;

bmp.xsize = 0;
bmp.ysize = 0;
bmp.channels = 0;
bmp.compressed = false;
std::swap(mem, bmp.mem);
std::swap(xsize, bmp.xsize);
std::swap(ysize, bmp.ysize);
std::swap(channels, bmp.channels);
std::swap(compressed, bmp.compressed);

#ifndef BITMAP_NO_OPENGL
textype = bmp.textype;
bmp.textype = 0;
std::swap(textype, bmp.textype);

ddsimage = std::move(bmp.ddsimage);
std::swap(ddsimage, bmp.ddsimage);
#endif
}

Expand All @@ -347,6 +364,7 @@ void CBitmap::InitPool(size_t size)
void CBitmap::Alloc(int w, int h, int c)
{
mem = texMemPool.Alloc((xsize = w) * (ysize = h) * (channels = c));
memset(mem, 0, GetMemSize());
}

void CBitmap::AllocDummy(const SColor fill)
Expand Down Expand Up @@ -995,8 +1013,8 @@ void CBitmap::Blur(int iterations, float weight)

CBitmap* src = this;
CBitmap* dst = &tmp;
dst->channels = src->channels;
dst->Alloc(xsize, ysize);

dst->Alloc(xsize, ysize, channels);

for (int i = 0; i < iterations; ++i) {
for_mt(0, ysize, [&](const int y) {
Expand Down Expand Up @@ -1032,8 +1050,8 @@ void CBitmap::CopySubImage(const CBitmap& src, int xpos, int ypos)
}

for (int y = 0; y < src.ysize; ++y) {
const int pixelDst = (((ypos + y) * xsize) + xpos) * channels;
const int pixelSrc = ((y * src.xsize) + 0 ) * channels;
const int pixelDst = (((ypos + y) * xsize) + xpos) * channels;
const int pixelSrc = (( y * src.xsize) + 0) * channels;

// copy the whole line
std::copy(&src.mem[pixelSrc], &src.mem[pixelSrc] + channels * src.xsize, &mem[pixelDst]);
Expand Down

0 comments on commit 561e282

Please sign in to comment.