Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Color format cleanups #15749

Merged
merged 4 commits into from
Jul 30, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 8 additions & 45 deletions Core/TextureReplacer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,7 @@ void TextureReplacer::PopulateReplacement(ReplacedTexture *result, u64 cachekey,
}

ReplacedTextureLevel level;
level.fmt = ReplacedTextureFormat::F_8888;
level.fmt = Draw::DataFormat::R8G8B8A8_UNORM;
level.file = filename;
bool good = PopulateLevel(level);

Expand Down Expand Up @@ -635,50 +635,13 @@ void TextureReplacer::NotifyTextureDecoded(const ReplacedTextureDecodeInfo &repl

SimpleBuf<u32> saveBuf;

// Since we're copying, change the format meanwhile. Not much extra cost.
if (replacedInfo.fmt != ReplacedTextureFormat::F_8888) {
saveBuf.resize((pitch * h) / sizeof(u16));
switch (replacedInfo.fmt) {
case ReplacedTextureFormat::F_5650:
ConvertRGB565ToRGBA8888(saveBuf.data(), (const u16 *)data, (pitch * h) / sizeof(u16));
break;
case ReplacedTextureFormat::F_5551:
ConvertRGBA5551ToRGBA8888(saveBuf.data(), (const u16 *)data, (pitch * h) / sizeof(u16));
break;
case ReplacedTextureFormat::F_4444:
ConvertRGBA4444ToRGBA8888(saveBuf.data(), (const u16 *)data, (pitch * h) / sizeof(u16));
break;
case ReplacedTextureFormat::F_0565_ABGR:
ConvertBGR565ToRGBA8888(saveBuf.data(), (const u16 *)data, (pitch * h) / sizeof(u16));
break;
case ReplacedTextureFormat::F_1555_ABGR:
ConvertABGR1555ToRGBA8888(saveBuf.data(), (const u16 *)data, (pitch * h) / sizeof(u16));
break;
case ReplacedTextureFormat::F_4444_ABGR:
ConvertABGR4444ToRGBA8888(saveBuf.data(), (const u16 *)data, (pitch * h) / sizeof(u16));
break;
case ReplacedTextureFormat::F_8888_BGRA:
ConvertBGRA8888ToRGBA8888(saveBuf.data(), (const u32 *)data, (pitch * h) / sizeof(u32));
break;
case ReplacedTextureFormat::F_8888:
// Impossible. Just so we can get warnings on other missed formats.
break;
}

data = saveBuf.data();
if (replacedInfo.fmt != ReplacedTextureFormat::F_8888_BGRA) {
// We doubled our pitch.
pitch *= 2;
}
} else {
// Copy data to a buffer so we can send it to the thread. Might as well compact-away the pitch
// while we're at it.
saveBuf.resize(w * h);
for (int y = 0; y < h; y++) {
memcpy((u8 *)saveBuf.data() + y * w * 4, (const u8 *)data + y * pitch, w * sizeof(u32));
}
pitch = w * 4;
// Copy data to a buffer so we can send it to the thread. Might as well compact-away the pitch
// while we're at it.
saveBuf.resize(w * h);
for (int y = 0; y < h; y++) {
memcpy((u8 *)saveBuf.data() + y * w * 4, (const u8 *)data + y * pitch, w * sizeof(u32));
}
pitch = w * 4;

TextureSaveTask *task = new TextureSaveTask(std::move(saveBuf));
// Should probably do a proper move constructor but this'll work.
Expand All @@ -694,7 +657,7 @@ void TextureReplacer::NotifyTextureDecoded(const ReplacedTextureDecodeInfo &repl
// Remember that we've saved this for next time.
// Should be OK that the actual disk write may not be finished yet.
ReplacedTextureLevel saved;
saved.fmt = ReplacedTextureFormat::F_8888;
saved.fmt = Draw::DataFormat::R8G8B8A8_UNORM;
saved.file = filename;
saved.w = w;
saved.h = h;
Expand Down
20 changes: 5 additions & 15 deletions Core/TextureReplacer.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include "Common/CommonTypes.h"
#include "Common/MemoryUtil.h"
#include "Common/File/Path.h"
#include "Common/GPU/DataFormat.h"

#include "GPU/Common/TextureDecoder.h"
#include "GPU/ge_constants.h"
Expand All @@ -35,17 +36,6 @@ class TextureReplacer;
class ReplacedTextureTask;
class LimitedWaitable;

enum class ReplacedTextureFormat {
F_5650,
F_5551,
F_4444,
F_8888,
F_0565_ABGR,
F_1555_ABGR,
F_4444_ABGR,
F_8888_BGRA,
};

// These must match the constants in TextureCacheCommon.
enum class ReplacedTextureAlpha {
UNKNOWN = 0x04,
Expand All @@ -62,7 +52,7 @@ enum class ReplacedTextureHash {
struct ReplacedTextureLevel {
int w;
int h;
ReplacedTextureFormat fmt;
Draw::DataFormat fmt; // NOTE: Right now, the only supported format is Draw::DataFormat::R8G8B8A8_UNORM.
Path file;
};

Expand Down Expand Up @@ -146,11 +136,11 @@ struct ReplacedTexture {
return (int)levels_.size() - 1;
}

ReplacedTextureFormat Format(int level) {
Draw::DataFormat Format(int level) {
if ((size_t)level < levels_.size()) {
return levels_[level].fmt;
}
return ReplacedTextureFormat::F_8888;
return Draw::DataFormat::R8G8B8A8_UNORM;
}

u8 AlphaStatus() {
Expand Down Expand Up @@ -185,7 +175,7 @@ struct ReplacedTextureDecodeInfo {
bool isVideo;
bool isFinal;
int scaleFactor;
ReplacedTextureFormat fmt;
Draw::DataFormat fmt;
};

enum class ReplacerDecimateMode {
Expand Down
31 changes: 14 additions & 17 deletions GPU/Common/TextureCacheCommon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1319,7 +1319,7 @@ ReplacedTexture &TextureCacheCommon::FindReplacement(TexCacheEntry *entry, int &

// This is only used in the GLES backend, where we don't point these to video memory.
// So we shouldn't add a check for dstBuf != srcBuf, as long as the functions we call can handle that.
static void ReverseColors(void *dstBuf, const void *srcBuf, GETextureFormat fmt, int numPixels, bool useBGRA) {
static void ReverseColors(void *dstBuf, const void *srcBuf, GETextureFormat fmt, int numPixels) {
switch (fmt) {
case GE_TFMT_4444:
ConvertRGBA4444ToABGR4444((u16 *)dstBuf, (const u16 *)srcBuf, numPixels);
Expand All @@ -1332,12 +1332,9 @@ static void ReverseColors(void *dstBuf, const void *srcBuf, GETextureFormat fmt,
ConvertRGB565ToBGR565((u16 *)dstBuf, (const u16 *)srcBuf, numPixels);
break;
default:
if (useBGRA) {
ConvertRGBA8888ToBGRA8888((u32 *)dstBuf, (const u32 *)srcBuf, numPixels);
} else {
// No need to convert RGBA8888, right order already
if (dstBuf != srcBuf)
memcpy(dstBuf, srcBuf, numPixels * sizeof(u32));
// No need to convert RGBA8888, right order already
if (dstBuf != srcBuf) {
memcpy(dstBuf, srcBuf, numPixels * sizeof(u32));
}
break;
}
Expand Down Expand Up @@ -1367,7 +1364,7 @@ static inline void ConvertFormatToRGBA8888(GEPaletteFormat format, u32 *dst, con

template <typename DXTBlock, int n>
static CheckAlphaResult DecodeDXTBlocks(uint8_t *out, int outPitch, uint32_t texaddr, const uint8_t *texptr,
int w, int h, int bufw, bool reverseColors, bool useBGRA) {
int w, int h, int bufw, bool reverseColors) {

int minw = std::min(bufw, w);
uint32_t *dst = (uint32_t *)out;
Expand Down Expand Up @@ -1403,7 +1400,7 @@ static CheckAlphaResult DecodeDXTBlocks(uint8_t *out, int outPitch, uint32_t tex
}

if (reverseColors) {
ReverseColors(out, out, GE_TFMT_8888, outPitch32 * h, useBGRA);
ReverseColors(out, out, GE_TFMT_8888, outPitch32 * h);
}

if (n == 1) {
Expand Down Expand Up @@ -1434,7 +1431,7 @@ inline u32 TfmtRawToFullAlpha(GETextureFormat fmt) {
}
}

CheckAlphaResult TextureCacheCommon::DecodeTextureLevel(u8 *out, int outPitch, GETextureFormat format, GEPaletteFormat clutformat, uint32_t texaddr, int level, int bufw, bool reverseColors, bool useBGRA, bool expandTo32bit) {
CheckAlphaResult TextureCacheCommon::DecodeTextureLevel(u8 *out, int outPitch, GETextureFormat format, GEPaletteFormat clutformat, uint32_t texaddr, int level, int bufw, bool reverseColors, bool expandTo32bit) {
u32 alphaSum = 0xFFFFFFFF;
u32 fullAlphaMask = 0x0;

Expand Down Expand Up @@ -1549,7 +1546,7 @@ CheckAlphaResult TextureCacheCommon::DecodeTextureLevel(u8 *out, int outPitch, G
// Just check the input's alpha to reuse code. TODO: make a specialized ReverseColors that checks as we go.
for (int y = 0; y < h; ++y) {
CheckMask16((const u16 *)(texptr + bufw * sizeof(u16) * y), w, &alphaSum);
ReverseColors(out + outPitch * y, texptr + bufw * sizeof(u16) * y, format, w, useBGRA);
ReverseColors(out + outPitch * y, texptr + bufw * sizeof(u16) * y, format, w);
}
} else if (expandTo32bit) {
for (int y = 0; y < h; ++y) {
Expand Down Expand Up @@ -1579,7 +1576,7 @@ CheckAlphaResult TextureCacheCommon::DecodeTextureLevel(u8 *out, int outPitch, G
// Just check the swizzled input's alpha to reuse code. TODO: make a specialized ReverseColors that checks as we go.
for (int y = 0; y < h; ++y) {
CheckMask16((const u16 *)(unswizzled + bufw * sizeof(u16) * y), w, &alphaSum);
ReverseColors(out + outPitch * y, unswizzled + bufw * sizeof(u16) * y, format, w, useBGRA);
ReverseColors(out + outPitch * y, unswizzled + bufw * sizeof(u16) * y, format, w);
}
} else if (expandTo32bit) {
// Just check the swizzled input's alpha to reuse code. TODO: make a specialized ConvertFormatToRGBA8888 that checks as we go.
Expand All @@ -1604,7 +1601,7 @@ CheckAlphaResult TextureCacheCommon::DecodeTextureLevel(u8 *out, int outPitch, G
if (reverseColors) {
for (int y = 0; y < h; ++y) {
CheckMask32((const u32 *)(texptr + bufw * sizeof(u32) * y), w, &alphaSum);
ReverseColors(out + outPitch * y, texptr + bufw * sizeof(u32) * y, format, w, useBGRA);
ReverseColors(out + outPitch * y, texptr + bufw * sizeof(u32) * y, format, w);
}
} else {
for (int y = 0; y < h; ++y) {
Expand All @@ -1626,7 +1623,7 @@ CheckAlphaResult TextureCacheCommon::DecodeTextureLevel(u8 *out, int outPitch, G
if (reverseColors) {
for (int y = 0; y < h; ++y) {
CheckMask32((const u32 *)(unswizzled + bufw * sizeof(u32) * y), w, &alphaSum);
ReverseColors(out + outPitch * y, unswizzled + bufw * sizeof(u32) * y, format, w, useBGRA);
ReverseColors(out + outPitch * y, unswizzled + bufw * sizeof(u32) * y, format, w);
}
} else {
for (int y = 0; y < h; ++y) {
Expand All @@ -1637,13 +1634,13 @@ CheckAlphaResult TextureCacheCommon::DecodeTextureLevel(u8 *out, int outPitch, G
break;

case GE_TFMT_DXT1:
return DecodeDXTBlocks<DXT1Block, 1>(out, outPitch, texaddr, texptr, w, h, bufw, reverseColors, useBGRA);
return DecodeDXTBlocks<DXT1Block, 1>(out, outPitch, texaddr, texptr, w, h, bufw, reverseColors);

case GE_TFMT_DXT3:
return DecodeDXTBlocks<DXT3Block, 3>(out, outPitch, texaddr, texptr, w, h, bufw, reverseColors, useBGRA);
return DecodeDXTBlocks<DXT3Block, 3>(out, outPitch, texaddr, texptr, w, h, bufw, reverseColors);

case GE_TFMT_DXT5:
return DecodeDXTBlocks<DXT5Block, 5>(out, outPitch, texaddr, texptr, w, h, bufw, reverseColors, useBGRA);
return DecodeDXTBlocks<DXT5Block, 5>(out, outPitch, texaddr, texptr, w, h, bufw, reverseColors);

default:
ERROR_LOG_REPORT(G3D, "Unknown Texture Format %d!!!", format);
Expand Down
2 changes: 1 addition & 1 deletion GPU/Common/TextureCacheCommon.h
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ class TextureCacheCommon {
virtual void UpdateCurrentClut(GEPaletteFormat clutFormat, u32 clutBase, bool clutIndexIsSimple) = 0;
bool CheckFullHash(TexCacheEntry *entry, bool &doDelete);

CheckAlphaResult DecodeTextureLevel(u8 *out, int outPitch, GETextureFormat format, GEPaletteFormat clutformat, uint32_t texaddr, int level, int bufw, bool reverseColors, bool useBGRA, bool expandTo32Bit);
CheckAlphaResult DecodeTextureLevel(u8 *out, int outPitch, GETextureFormat format, GEPaletteFormat clutformat, uint32_t texaddr, int level, int bufw, bool reverseColors, bool expandTo32Bit);
void UnswizzleFromMem(u32 *dest, u32 destPitch, const u8 *texptr, u32 bufw, u32 height, u32 bytesPerPixel);
CheckAlphaResult ReadIndexedTex(u8 *out, int outPitch, int level, const u8 *texptr, int bytesPerIndex, int bufw, bool reverseColors, bool expandTo32Bit);
ReplacedTexture &FindReplacement(TexCacheEntry *entry, int &w, int &h);
Expand Down
18 changes: 7 additions & 11 deletions GPU/D3D11/TextureCacheD3D11.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -605,21 +605,17 @@ CheckAlphaResult TextureCacheD3D11::CheckAlpha(const u32 *pixelData, u32 dstFmt,
}
}

ReplacedTextureFormat FromD3D11Format(u32 fmt) {
// NOTE: In the D3D backends, we flip R and B in the shaders, so while these look wrong, they're OK.

Draw::DataFormat FromD3D11Format(u32 fmt) {
switch (fmt) {
case DXGI_FORMAT_B5G6R5_UNORM: return ReplacedTextureFormat::F_5650;
case DXGI_FORMAT_B5G5R5A1_UNORM: return ReplacedTextureFormat::F_5551;
case DXGI_FORMAT_B4G4R4A4_UNORM: return ReplacedTextureFormat::F_4444;
case DXGI_FORMAT_B8G8R8A8_UNORM: default: return ReplacedTextureFormat::F_8888;
case DXGI_FORMAT_B8G8R8A8_UNORM: default: return Draw::DataFormat::R8G8B8A8_UNORM;
}
}

DXGI_FORMAT ToDXGIFormat(ReplacedTextureFormat fmt) {
DXGI_FORMAT ToDXGIFormat(Draw::DataFormat fmt) {
switch (fmt) {
case ReplacedTextureFormat::F_5650: return DXGI_FORMAT_B5G6R5_UNORM;
case ReplacedTextureFormat::F_5551: return DXGI_FORMAT_B5G5R5A1_UNORM;
case ReplacedTextureFormat::F_4444: return DXGI_FORMAT_B4G4R4A4_UNORM;
case ReplacedTextureFormat::F_8888: default: return DXGI_FORMAT_B8G8R8A8_UNORM;
case Draw::DataFormat::R8G8B8A8_UNORM: default: return DXGI_FORMAT_B8G8R8A8_UNORM;
}
}

Expand Down Expand Up @@ -702,7 +698,7 @@ void TextureCacheD3D11::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &

bool expand32 = !gstate_c.Supports(GPU_SUPPORTS_16BIT_FORMATS);

CheckAlphaResult alphaResult = DecodeTextureLevel((u8 *)pixelData, decPitch, tfmt, clutformat, texaddr, level, bufw, false, false, expand32);
CheckAlphaResult alphaResult = DecodeTextureLevel((u8 *)pixelData, decPitch, tfmt, clutformat, texaddr, level, bufw, false, expand32);
entry.SetAlphaStatus(alphaResult, level);

if (scaleFactor > 1) {
Expand Down
18 changes: 7 additions & 11 deletions GPU/Directx9/TextureCacheDX9.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -539,21 +539,17 @@ CheckAlphaResult TextureCacheDX9::CheckAlpha(const u32 *pixelData, u32 dstFmt, i
}
}

ReplacedTextureFormat FromD3D9Format(u32 fmt) {
// NOTE: In the D3D backends, we flip R and B in the shaders, so while these look wrong, they're OK.

Draw::DataFormat FromD3D9Format(u32 fmt) {
switch (fmt) {
case D3DFMT_R5G6B5: return ReplacedTextureFormat::F_5650;
case D3DFMT_A1R5G5B5: return ReplacedTextureFormat::F_5551;
case D3DFMT_A4R4G4B4: return ReplacedTextureFormat::F_4444;
case D3DFMT_A8R8G8B8: default: return ReplacedTextureFormat::F_8888;
case D3DFMT_A8R8G8B8: default: return Draw::DataFormat::R8G8B8A8_UNORM;
}
}

D3DFORMAT ToD3D9Format(ReplacedTextureFormat fmt) {
D3DFORMAT ToD3D9Format(Draw::DataFormat fmt) {
switch (fmt) {
case ReplacedTextureFormat::F_5650: return D3DFMT_R5G6B5;
case ReplacedTextureFormat::F_5551: return D3DFMT_A1R5G5B5;
case ReplacedTextureFormat::F_4444: return D3DFMT_A4R4G4B4;
case ReplacedTextureFormat::F_8888: default: return D3DFMT_A8R8G8B8;
case Draw::DataFormat::R8G8B8A8_UNORM: default: return D3DFMT_A8R8G8B8;
}
}

Expand Down Expand Up @@ -627,7 +623,7 @@ void TextureCacheDX9::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &re
decPitch = w * bpp;
}

CheckAlphaResult alphaResult = DecodeTextureLevel((u8 *)pixelData, decPitch, tfmt, clutformat, texaddr, level, bufw, false, false, false);
CheckAlphaResult alphaResult = DecodeTextureLevel((u8 *)pixelData, decPitch, tfmt, clutformat, texaddr, level, bufw, false, false);
entry.SetAlphaStatus(alphaResult, level);

if (scaleFactor > 1) {
Expand Down
27 changes: 4 additions & 23 deletions GPU/GLES/TextureCacheGLES.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -425,25 +425,6 @@ void TextureCacheGLES::ApplyTextureFramebuffer(VirtualFramebuffer *framebuffer,
gstate_c.Dirty(DIRTY_BLEND_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_RASTER_STATE | DIRTY_VIEWPORTSCISSOR_STATE);
}

ReplacedTextureFormat FromDataFormat(Draw::DataFormat fmt) {
// TODO: 16-bit formats are incorrect, since swizzled.
switch (fmt) {
case Draw::DataFormat::R5G6B5_UNORM_PACK16: return ReplacedTextureFormat::F_0565_ABGR;
case Draw::DataFormat::R5G5B5A1_UNORM_PACK16: return ReplacedTextureFormat::F_1555_ABGR;
case Draw::DataFormat::R4G4B4A4_UNORM_PACK16: return ReplacedTextureFormat::F_4444_ABGR;
case Draw::DataFormat::R8G8B8A8_UNORM: default: return ReplacedTextureFormat::F_8888;
}
}

Draw::DataFormat ToDataFormat(ReplacedTextureFormat fmt) {
switch (fmt) {
case ReplacedTextureFormat::F_5650: return Draw::DataFormat::R5G6B5_UNORM_PACK16;
case ReplacedTextureFormat::F_5551: return Draw::DataFormat::R5G5B5A1_UNORM_PACK16;
case ReplacedTextureFormat::F_4444: return Draw::DataFormat::R4G4B4A4_UNORM_PACK16;
case ReplacedTextureFormat::F_8888: default: return Draw::DataFormat::R8G8B8A8_UNORM;
}
}

void TextureCacheGLES::BuildTexture(TexCacheEntry *const entry) {
entry->status &= ~TexCacheEntry::STATUS_ALPHA_MASK;

Expand Down Expand Up @@ -646,15 +627,15 @@ void TextureCacheGLES::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &r
if (replaced.GetSize(level, w, h)) {
PROFILE_THIS_SCOPE("replacetex");

int bpp = replaced.Format(level) == ReplacedTextureFormat::F_8888 ? 4 : 2;
int bpp = (int)DataFormatSizeInBytes(replaced.Format(level));
decPitch = w * bpp;
uint8_t *rearrange = (uint8_t *)AllocateAlignedMemory(decPitch * h, 16);
double replaceStart = time_now_d();
replaced.Load(level, rearrange, decPitch);
replacementTimeThisFrame_ += time_now_d() - replaceStart;
pixelData = rearrange;

dstFmt = ToDataFormat(replaced.Format(level));
dstFmt = replaced.Format(level);
} else {
PROFILE_THIS_SCOPE("decodetex");

Expand All @@ -668,7 +649,7 @@ void TextureCacheGLES::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &r

pixelData = (uint8_t *)AllocateAlignedMemory(decPitch * h * pixelSize, 16);

CheckAlphaResult alphaStatus = DecodeTextureLevel(pixelData, decPitch, GETextureFormat(entry.format), clutformat, texaddr, level, bufw, true, false, false);
CheckAlphaResult alphaStatus = DecodeTextureLevel(pixelData, decPitch, GETextureFormat(entry.format), clutformat, texaddr, level, bufw, true, false);
entry.SetAlphaStatus(alphaStatus, level);

if (scaleFactor > 1) {
Expand All @@ -689,7 +670,7 @@ void TextureCacheGLES::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &r
replacedInfo.isVideo = IsVideo(entry.addr);
replacedInfo.isFinal = (entry.status & TexCacheEntry::STATUS_TO_SCALE) == 0;
replacedInfo.scaleFactor = scaleFactor;
replacedInfo.fmt = FromDataFormat(dstFmt);
replacedInfo.fmt = dstFmt;

replacer_.NotifyTextureDecoded(replacedInfo, pixelData, decPitch, level, w, h);
}
Expand Down
Loading