Skip to content

Commit

Permalink
fix #6105
Browse files Browse the repository at this point in the history
downgrade detailtex/infomap loading exceptions
  • Loading branch information
rt committed Dec 22, 2018
1 parent 8c46dd8 commit 9bad771
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 53 deletions.
57 changes: 32 additions & 25 deletions rts/Map/SMF/SMFReadMap.cpp
Expand Up @@ -302,10 +302,12 @@ void CSMFReadMap::CreateGrassTex()
grassShadingTex.SetRawSize(int2(1024, 1024));

CBitmap grassShadingTexBM;
if (grassShadingTexBM.Load(mapInfo->smf.grassShadingTexName)) {
grassShadingTex.SetRawTexID(grassShadingTexBM.CreateMipMapTexture());
grassShadingTex.SetRawSize(int2(grassShadingTexBM.xsize, grassShadingTexBM.ysize));
}

if (!grassShadingTexBM.Load(mapInfo->smf.grassShadingTexName))
grassShadingTexBM.AllocDummy();

grassShadingTex.SetRawTexID(grassShadingTexBM.CreateMipMapTexture());
grassShadingTex.SetRawSize(int2(grassShadingTexBM.xsize, grassShadingTexBM.ysize));
}


Expand All @@ -314,7 +316,7 @@ void CSMFReadMap::CreateDetailTex()
CBitmap detailTexBM;

if (!detailTexBM.Load(mapInfo->smf.detailTexName))
throw content_error("Could not load detail texture from file " + mapInfo->smf.detailTexName);
detailTexBM.AllocDummy();

detailTex.SetRawTexID(detailTexBM.CreateTexture(texAnisotropyLevels[false], 0.0f, true));
detailTex.SetRawSize(int2(detailTexBM.xsize, detailTexBM.ysize));
Expand Down Expand Up @@ -849,51 +851,56 @@ const char* CSMFReadMap::GetFeatureTypeName(int typeID) { return mapFile.GetFeat

unsigned char* CSMFReadMap::GetInfoMap(const std::string& name, MapBitmapInfo* bmInfo)
{
char failMsg[512];

// get size
mapFile.GetInfoMapSize(name, bmInfo);

if (bmInfo->width <= 0)
return nullptr;

char errMsg[512];
unsigned char* data = new unsigned char[bmInfo->width * bmInfo->height];

CBitmap infomapBM;
std::string texName;
if (name == "metal" && !mapInfo->smf.metalmapTexName.empty()) {
texName = mapInfo->smf.metalmapTexName;
} else if (name == "type" && !mapInfo->smf.typemapTexName.empty()) {
texName = mapInfo->smf.typemapTexName;
} else if (name == "grass" && !mapInfo->smf.grassmapTexName.empty()) {
texName = mapInfo->smf.grassmapTexName;

switch (hashString(name.c_str())) {
case hashString("metal"): { texName = mapInfo->smf.metalmapTexName; } break;
case hashString("type" ): { texName = mapInfo->smf.typemapTexName ; } break;
case hashString("grass"): { texName = mapInfo->smf.grassmapTexName; } break;
default: {
LOG_L(L_WARNING, "[SMFReadMap::%s] unknown texture-name \"%s\"", __func__, name.c_str());
} break;
}

// get data from mapinfo-override texture
if (!texName.empty() && !infomapBM.LoadGrayscale(texName))
throw content_error("[CSMFReadMap::GetInfoMap] cannot load: " + texName);
LOG_L(L_WARNING, "[SMFReadMap::%s] cannot load override-texture \"%s\"", __func__, texName.c_str());

if (!infomapBM.Empty()) {
if (infomapBM.xsize == bmInfo->width && infomapBM.ysize == bmInfo->height) {
memcpy(data, infomapBM.GetRawMem(), bmInfo->width * bmInfo->height);
return data;
}
sprintf(failMsg, "[CSMFReadMap::GetInfoMap] Invalid image dimensions: %s %ix%i != %ix%i",
texName.c_str(), infomapBM.xsize, infomapBM.ysize,
bmInfo->width, bmInfo->height);
throw content_error(failMsg);
}

// get data
if (!mapFile.ReadInfoMap(name, data)) {
delete[] data;
data = nullptr;
snprintf(errMsg, sizeof(errMsg), "[SMFReadMap::%s] invalid dimensions for override-texture \"%s\": %ix%i != %ix%i",
__func__, texName.c_str(),
infomapBM.xsize, infomapBM.ysize,
bmInfo->width, bmInfo->height
);

throw content_error(errMsg);
}

return data;
// get data from map itself
if (mapFile.ReadInfoMap(name, data))
return data;

delete[] data;
return nullptr;
}


void CSMFReadMap::FreeInfoMap(const std::string& name, unsigned char *data)
void CSMFReadMap::FreeInfoMap(const std::string& name, unsigned char* data)
{
delete[] data;
}
Expand Down
57 changes: 29 additions & 28 deletions rts/Rendering/Textures/Bitmap.cpp
Expand Up @@ -385,13 +385,17 @@ const uint8_t* CBitmap::GetRawMem() const { return ((memIdx == size_t(-1))? null

void CBitmap::Alloc(int w, int h, int c)
{
if (!Empty())
texMemPool.Free(GetRawMem(), GetMemSize());

memIdx = texMemPool.AllocIdx((xsize = w) * (ysize = h) * (channels = c));
memset(GetRawMem(), 0, GetMemSize());
}

void CBitmap::AllocDummy(const SColor fill)
{
compressed = false;

Alloc(1, 1, sizeof(SColor));
memcpy(GetRawMem(), &fill.r, sizeof(SColor));
}
Expand All @@ -402,14 +406,17 @@ bool CBitmap::Load(std::string const& filename, uint8_t defaultAlpha)
SCOPED_TIMER("Misc::Bitmap::Load");
#endif

bool noAlpha = true;
bool isLoaded = false;
bool isValid = false;
bool noAlpha = true;

const bool loadDDS = (FileSystem::GetExtension(filename) == "dds"); // always lower-case
const bool flipDDS = true; // default, also assumed by gl.TexRect

const size_t curMemSize = GetMemSize();


channels = 4;
#ifndef BITMAP_NO_OPENGL
textype = GL_TEXTURE_2D;
#endif
Expand Down Expand Up @@ -458,21 +465,18 @@ bool CBitmap::Load(std::string const& filename, uint8_t defaultAlpha)
compressed = loadDDS;
#endif

channels = 4;


CFileHandler file(filename);
std::vector<uint8_t> buffer;

if (!file.FileExists()) {
AllocDummy();
return false;
}

std::vector<uint8_t> buffer;

if (!file.IsBuffered()) {
buffer.resize(file.FileSize() + 2, 0);
file.Read(buffer.data(), file.FileSize());
buffer.resize(file.FileSize(), 0);
file.Read(buffer.data(), buffer.size());
} else {
// steal if file was loaded from VFS
buffer = std::move(file.GetBuffer());
Expand All @@ -482,7 +486,8 @@ bool CBitmap::Load(std::string const& filename, uint8_t defaultAlpha)
{
std::lock_guard<spring::mutex> lck(texMemPool.GetMutex());

// IL does not vertically flip DDS images by default, unlike nv_dds
// do not preserve the image origin since IL does not
// vertically flip DDS images by default, unlike nv_dds
ilOriginFunc((loadDDS && flipDDS)? IL_ORIGIN_LOWER_LEFT: IL_ORIGIN_UPPER_LEFT);
ilEnable(IL_ORIGIN_SET);

Expand All @@ -494,43 +499,39 @@ bool CBitmap::Load(std::string const& filename, uint8_t defaultAlpha)
// do not signal floating point exceptions in devil library
ScopedDisableFpuExceptions fe;

const bool success = !!ilLoadL(IL_TYPE_UNKNOWN, buffer.data(), buffer.size());
isLoaded = !!ilLoadL(IL_TYPE_UNKNOWN, buffer.data(), buffer.size());
isValid = (isLoaded && IsValidImageFormat(ilGetInteger(IL_IMAGE_FORMAT)));
noAlpha = (isValid && (ilGetInteger(IL_IMAGE_BYTES_PER_PIXEL) != 4));

// FPU control word has to be restored as well
streflop::streflop_init<streflop::Simple>();

ilDisable(IL_ORIGIN_SET);

if (!success) {
AllocDummy();
return false;
}
}

{
if (!IsValidImageFormat(ilGetInteger(IL_IMAGE_FORMAT))) {
LOG_L(L_ERROR, "Invalid image format for %s: %d", filename.c_str(), ilGetInteger(IL_IMAGE_FORMAT));
return false;
}
}
if (isValid) {
ilConvertImage(IL_RGBA, IL_UNSIGNED_BYTE);

noAlpha = (ilGetInteger(IL_IMAGE_BYTES_PER_PIXEL) != 4);
ilConvertImage(IL_RGBA, IL_UNSIGNED_BYTE);
xsize = ilGetInteger(IL_IMAGE_WIDTH);
ysize = ilGetInteger(IL_IMAGE_HEIGHT);

xsize = ilGetInteger(IL_IMAGE_WIDTH);
ysize = ilGetInteger(IL_IMAGE_HEIGHT);

{
texMemPool.FreeRaw(GetRawMem(), curMemSize);
memIdx = texMemPool.AllocIdxRaw(GetMemSize());

// ilCopyPixels(0, 0, 0, xsize, ysize, 0, IL_RGBA, IL_UNSIGNED_BYTE, GetRawMem());
std::memcpy(GetRawMem(), ilGetData(), GetMemSize());
} else {
LOG_L(L_ERROR, "[BMP::%s] failed to load \"%s\" or invalid format %d", __func__, filename.c_str(), ilGetInteger(IL_IMAGE_FORMAT));
}

ilDisable(IL_ORIGIN_SET);
ilDeleteImages(1, &imageID);
}

// has to be outside the mutex scope
if (!isValid) {
AllocDummy();
return false;
}

if (noAlpha) {
uint8_t* mem = GetRawMem();

Expand Down

0 comments on commit 9bad771

Please sign in to comment.