Skip to content

Commit

Permalink
Replacement: Delay load texture data.
Browse files Browse the repository at this point in the history
  • Loading branch information
unknownbrackets committed Oct 17, 2021
1 parent 909628b commit be3c1f5
Showing 1 changed file with 55 additions and 26 deletions.
81 changes: 55 additions & 26 deletions Core/TextureReplacer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -764,24 +764,15 @@ bool ReplacedTexture::IsReady(double budget) {
}

void ReplacedTexture::PrepareData(int level) {
// TODO
}

void ReplacedTexture::PurgeIfOlder(double t) {
if (lastUsed_ < t) {
levelData_.clear();
}
}

bool ReplacedTexture::Load(int level, void *out, int rowPitch) {
_assert_msg_((size_t)level < levels_.size(), "Invalid miplevel");
_assert_msg_(out != nullptr && rowPitch > 0, "Invalid out/pitch");

const ReplacedTextureLevel &info = levels_[level];
std::vector<uint8_t> &out = levelData_[level];

FILE *fp = File::OpenCFile(info.file, "rb");
if (!fp) {
return false;
// Leaving the data sized at zero means failure.
return;
}

auto imageType = Identify(fp);
Expand All @@ -791,29 +782,30 @@ bool ReplacedTexture::Load(int level, void *out, int rowPitch) {
if (!zim) {
ERROR_LOG(G3D, "Failed to allocate memory for texture replacement");
fclose(fp);
return false;
return;
}

if (fread(&zim[0], 1, zimSize, fp) != zimSize) {
ERROR_LOG(G3D, "Could not load texture replacement: %s - failed to read ZIM", info.file.c_str());
fclose(fp);
return false;
return;
}

int w, h, f;
uint8_t *image;
const int MIN_LINES_PER_THREAD = 4;
if (LoadZIMPtr(&zim[0], zimSize, &w, &h, &f, &image)) {
ParallelRangeLoop(&g_threadManager, [&](int l, int h) {
for (int y = l; y < h; ++y) {
memcpy((uint8_t *)out + rowPitch * y, image + w * 4 * y, w * 4);
}
}, 0, h, MIN_LINES_PER_THREAD);
if (w != info.w || h != info.h) {
ERROR_LOG(G3D, "Texture replacement changed since header read: %s", info.file.c_str());
fclose(fp);
return;
}

out.resize(w * h * 4);
ParallelMemcpy(&g_threadManager, &out[0], image, info.w * 4 * info.h);
free(image);
}

// This will only check the hashed bits.
CheckAlphaResult res = CheckAlphaRGBA8888Basic((u32 *)out, rowPitch / sizeof(u32), w, h);
CheckAlphaResult res = CheckAlphaRGBA8888Basic((u32 *)&out[0], w, w, h);
if (res == CHECKALPHA_ANY || level == 0) {
alphaStatus_ = ReplacedTextureAlpha(res);
}
Expand All @@ -824,7 +816,12 @@ bool ReplacedTexture::Load(int level, void *out, int rowPitch) {
if (!png_image_begin_read_from_stdio(&png, fp)) {
ERROR_LOG(G3D, "Could not load texture replacement info: %s - %s", info.file.c_str(), png.message);
fclose(fp);
return false;
return;
}
if (png.width != info.w || png.height != info.h) {
ERROR_LOG(G3D, "Texture replacement changed since header read: %s", info.file.c_str());
fclose(fp);
return;
}

bool checkedAlpha = false;
Expand All @@ -837,23 +834,55 @@ bool ReplacedTexture::Load(int level, void *out, int rowPitch) {
}
png.format = PNG_FORMAT_RGBA;

if (!png_image_finish_read(&png, nullptr, out, rowPitch, nullptr)) {
out.resize(png.width * png.height * 4);
if (!png_image_finish_read(&png, nullptr, &out[0], png.width * 4, nullptr)) {
ERROR_LOG(G3D, "Could not load texture replacement: %s - %s", info.file.c_str(), png.message);
fclose(fp);
return false;
out.resize(0);
return;
}
png_image_free(&png);

if (!checkedAlpha) {
// This will only check the hashed bits.
CheckAlphaResult res = CheckAlphaRGBA8888Basic((u32 *)out, rowPitch / sizeof(u32), png.width, png.height);
CheckAlphaResult res = CheckAlphaRGBA8888Basic((u32 *)&out[0], png.width, png.width, png.height);
if (res == CHECKALPHA_ANY || level == 0) {
alphaStatus_ = ReplacedTextureAlpha(res);
}
}
}

fclose(fp);
}

void ReplacedTexture::PurgeIfOlder(double t) {
if (lastUsed_ < t) {
levelData_.clear();
}
}

bool ReplacedTexture::Load(int level, void *out, int rowPitch) {
_assert_msg_((size_t)level < levels_.size(), "Invalid miplevel");
_assert_msg_(out != nullptr && rowPitch > 0, "Invalid out/pitch");

const ReplacedTextureLevel &info = levels_[level];
const std::vector<uint8_t> &data = levelData_[level];

if (data.empty())
return false;
_assert_msg_(data.size() == info.w * info.h * 4, "Data has wrong size");

if (rowPitch == info.w * 4) {
ParallelMemcpy(&g_threadManager, out, &data[0], info.w * 4 * info.h);
} else {
const int MIN_LINES_PER_THREAD = 4;
ParallelRangeLoop(&g_threadManager, [&](int l, int h) {
for (int y = l; y < h; ++y) {
memcpy((uint8_t *)out + rowPitch * y, &data[0] + info.w * 4 * y, info.w * 4);
}
}, 0, info.h, MIN_LINES_PER_THREAD);
}

return true;
}

Expand Down

0 comments on commit be3c1f5

Please sign in to comment.