Add a common TextureAlpha enum, replacing CheckAlphaResult and ReplacedTextureAlpha.

This commit is contained in:
Henrik Rydgård
2026-06-09 11:02:14 +02:00
parent fdcf923c75
commit ec6c7b08f5
12 changed files with 73 additions and 73 deletions
+1
View File
@@ -2054,6 +2054,7 @@ set(GPU_SOURCES
GPU/Common/TransformCommon.h
GPU/Common/IndexGenerator.cpp
GPU/Common/IndexGenerator.h
GPU/Common/ImageCommon.h
GPU/Common/TextureDecoder.cpp
GPU/Common/TextureDecoder.h
GPU/Common/TextureCacheCommon.cpp
+11
View File
@@ -0,0 +1,11 @@
#pragma once
// The plan is to converge Texture and Framebuffer more and more.
// Here are things that are common between the two.
#include "Common/CommonTypes.h"
enum class TextureAlpha : u8 {
Any = 0,
Solid = 1,
};
+11 -11
View File
@@ -136,7 +136,7 @@ void ReplacedTexture::PurgeIfNotUsedSinceTime(double t) {
data_.clear();
levels_.clear();
fmt = Draw::DataFormat::UNDEFINED;
alphaStatus_ = ReplacedTextureAlpha::UNKNOWN;
alphaStatus_ = TextureAlpha::Any;
// This means we have to reload. If we never purge any, there's no need.
SetState(ReplacementState::UNLOADED);
@@ -482,7 +482,7 @@ ReplacedTexture::LoadLevelResult ReplacedTexture::LoadLevelData(VFSFileReference
basist::transcoder_texture_format transcoderFormat;
if (transcoder.is_etc1s()) {
// We only support opaque colors with this compression method.
alphaStatus_ = ReplacedTextureAlpha::FULL;
alphaStatus_ = TextureAlpha::Solid;
// Let's pick a suitable compatible format.
if (desc_.formatSupport.bc123) {
transcoderFormat = basist::transcoder_texture_format::cTFBC1;
@@ -498,7 +498,7 @@ ReplacedTexture::LoadLevelResult ReplacedTexture::LoadLevelData(VFSFileReference
}
} else if (transcoder.is_uastc()) {
// TODO: Try to recover some indication of alpha from the actual data blocks.
alphaStatus_ = ReplacedTextureAlpha::UNKNOWN;
alphaStatus_ = TextureAlpha::Any;
// Let's pick a suitable compatible format.
if (desc_.formatSupport.bc7) {
transcoderFormat = basist::transcoder_texture_format::cTFBC7_RGBA;
@@ -562,7 +562,7 @@ ReplacedTexture::LoadLevelResult ReplacedTexture::LoadLevelData(VFSFileReference
return LoadLevelResult::DONE; // don't read more levels
} else if (imageType == ReplacedImageType::DDS) {
// TODO: Do better with alphaStatus, it's possible.
alphaStatus_ = ReplacedTextureAlpha::UNKNOWN;
alphaStatus_ = TextureAlpha::Any;
DDSHeader header;
DDSHeaderDXT10 header10{};
@@ -640,9 +640,9 @@ ReplacedTexture::LoadLevelResult ReplacedTexture::LoadLevelData(VFSFileReference
}
free(image);
CheckAlphaResult res = CheckAlpha32Rect((u32 *)&out[0], level.w, w, h, 0xFF000000);
if (res == CHECKALPHA_ANY || mipLevel == 0) {
alphaStatus_ = ReplacedTextureAlpha(res);
const TextureAlpha res = CheckAlpha32Rect((u32 *)&out[0], level.w, w, h, 0xFF000000);
if (res == TextureAlpha::Any || mipLevel == 0) {
alphaStatus_ = res;
}
levels_.push_back(level);
} else {
@@ -672,7 +672,7 @@ ReplacedTexture::LoadLevelResult ReplacedTexture::LoadLevelData(VFSFileReference
if ((png.format & PNG_FORMAT_FLAG_ALPHA) == 0) {
// Well, we know for sure it doesn't have alpha.
if (mipLevel == 0) {
alphaStatus_ = ReplacedTextureAlpha::FULL;
alphaStatus_ = TextureAlpha::Solid;
}
checkedAlpha = true;
}
@@ -690,9 +690,9 @@ ReplacedTexture::LoadLevelResult ReplacedTexture::LoadLevelData(VFSFileReference
if (!checkedAlpha) {
// This will only check the hashed bits.
CheckAlphaResult res = CheckAlpha32Rect((u32 *)&out[0], level.w, png.width, png.height, 0xFF000000);
if (res == CHECKALPHA_ANY || mipLevel == 0) {
alphaStatus_ = ReplacedTextureAlpha(res);
const TextureAlpha res = CheckAlpha32Rect((u32 *)&out[0], level.w, png.width, png.height, 0xFF000000);
if (res == TextureAlpha::Any || mipLevel == 0) {
alphaStatus_ = res;
}
}
+4 -9
View File
@@ -23,16 +23,11 @@
#include "Common/File/VFS/VFS.h"
#include "Common/GPU/thin3d.h"
#include "Core/ConfigValues.h"
#include "GPU/Common/ImageCommon.h"
class TextureReplacer;
class LimitedWaitable;
// These must match the constants in TextureCacheCommon.
enum class ReplacedTextureAlpha {
UNKNOWN = 0x04,
FULL = 0x00,
};
// For forward compatibility, we specify the hash.
enum class ReplacedTextureHash {
QUICK,
@@ -169,8 +164,8 @@ public:
return desc_;
}
u8 AlphaStatus() const {
return (u8)alphaStatus_;
TextureAlpha AlphaStatus() const {
return alphaStatus_;
}
bool Poll(double budget);
@@ -196,7 +191,7 @@ private:
LimitedWaitable *threadWaitable_ = nullptr;
std::mutex lock_;
Draw::DataFormat fmt = Draw::DataFormat::UNDEFINED; // NOTE: Right now, the only supported format is Draw::DataFormat::R8G8B8A8_UNORM.
ReplacedTextureAlpha alphaStatus_ = ReplacedTextureAlpha::UNKNOWN;
TextureAlpha alphaStatus_ = TextureAlpha::Any;
double lastUsed = 0.0;
std::atomic<ReplacementState> state_ = ReplacementState::UNLOADED;
+21 -21
View File
@@ -1694,7 +1694,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,
static TextureAlpha DecodeDXTBlocks(uint8_t *out, int outPitch, uint32_t texaddr, const uint8_t *texptr,
int w, int h, int bufw, bool reverseColors) {
int minw = std::min(bufw, w);
@@ -1730,10 +1730,10 @@ static CheckAlphaResult DecodeDXTBlocks(uint8_t *out, int outPitch, uint32_t tex
}
if constexpr (n == 1) {
return alphaSum == 1 ? CHECKALPHA_FULL : CHECKALPHA_ANY;
return alphaSum == 1 ? TextureAlpha::Solid : TextureAlpha::Any;
} else {
// Just report that we don't have full alpha, since these formats are made for that.
return CHECKALPHA_ANY;
return TextureAlpha::Any;
}
}
@@ -1768,7 +1768,7 @@ static void Expand4To8Bits(u8 *dest, const u8 *src, int srcWidth) {
}
}
CheckAlphaResult TextureCacheCommon::DecodeTextureLevel(u8 *out, int outPitch, GETextureFormat format, GEPaletteFormat clutformat, uint32_t texaddr, int level, int bufw, TexDecodeFlags flags) {
TextureAlpha TextureCacheCommon::DecodeTextureLevel(u8 *out, int outPitch, GETextureFormat format, GEPaletteFormat clutformat, uint32_t texaddr, int level, int bufw, TexDecodeFlags flags) {
u32 alphaSum = 0xFFFFFFFF;
u32 fullAlphaMask = 0x0;
@@ -1819,7 +1819,7 @@ CheckAlphaResult TextureCacheCommon::DecodeTextureLevel(u8 *out, int outPitch, G
Expand4To8Bits((u8 *)out + outPitch * y, texptr + (bufw * y) / 2, w);
}
// We can't know anything about alpha.
return CHECKALPHA_ANY;
return TextureAlpha::Any;
}
switch (clutformat) {
@@ -1869,7 +1869,7 @@ CheckAlphaResult TextureCacheCommon::DecodeTextureLevel(u8 *out, int outPitch, G
if (clutformat == GE_CMODE_16BIT_BGR5650) {
// Our formula at the end of the function can't handle this cast so we return early.
return CHECKALPHA_FULL;
return TextureAlpha::Solid;
}
}
break;
@@ -1886,7 +1886,7 @@ CheckAlphaResult TextureCacheCommon::DecodeTextureLevel(u8 *out, int outPitch, G
default:
ERROR_LOG_REPORT(Log::G3D, "Unknown CLUT4 texture mode %d", gstate.getClutPaletteFormat());
return CHECKALPHA_ANY;
return TextureAlpha::Any;
}
}
break;
@@ -1903,7 +1903,7 @@ CheckAlphaResult TextureCacheCommon::DecodeTextureLevel(u8 *out, int outPitch, G
memcpy((u8 *)out + outPitch * y, texptr + (bufw * y), w);
}
// We can't know anything about alpha.
return CHECKALPHA_ANY;
return TextureAlpha::Any;
}
return ReadIndexedTex(out, outPitch, level, texptr, 1, bufw, reverseColors, expandTo32bit);
@@ -1970,7 +1970,7 @@ CheckAlphaResult TextureCacheCommon::DecodeTextureLevel(u8 *out, int outPitch, G
}
}
if (format == GE_TFMT_5650) {
return CHECKALPHA_FULL;
return TextureAlpha::Solid;
}
break;
@@ -2026,10 +2026,10 @@ CheckAlphaResult TextureCacheCommon::DecodeTextureLevel(u8 *out, int outPitch, G
break;
}
return AlphaSumIsFull(alphaSum, fullAlphaMask) ? CHECKALPHA_FULL : CHECKALPHA_ANY;
return AlphaSumIsFull(alphaSum, fullAlphaMask) ? TextureAlpha::Solid : TextureAlpha::Any;
}
CheckAlphaResult TextureCacheCommon::ReadIndexedTex(u8 *out, int outPitch, int level, const u8 *texptr, int bytesPerIndex, int bufw, bool reverseColors, bool expandTo32Bit) {
TextureAlpha TextureCacheCommon::ReadIndexedTex(u8 *out, int outPitch, int level, const u8 *texptr, int bytesPerIndex, int bufw, bool reverseColors, bool expandTo32Bit) {
int w = gstate.getTextureWidth(level);
int h = gstate.getTextureHeight(level);
@@ -2124,9 +2124,9 @@ CheckAlphaResult TextureCacheCommon::ReadIndexedTex(u8 *out, int outPitch, int l
}
if (palFormat == GE_CMODE_16BIT_BGR5650) {
return CHECKALPHA_FULL;
return TextureAlpha::Solid;
} else {
return AlphaSumIsFull(alphaSum, fullAlphaMask) ? CHECKALPHA_FULL : CHECKALPHA_ANY;
return AlphaSumIsFull(alphaSum, fullAlphaMask) ? TextureAlpha::Solid : TextureAlpha::Any;
}
}
@@ -2214,7 +2214,7 @@ void TextureCacheCommon::ApplyTexture(bool doBind, bool flatZ) {
if (doBind) {
BindTexture(entry, flatZ);
}
gstate_c.SetTextureFullAlpha(entry->GetAlphaStatus() == TexCacheEntry::STATUS_ALPHA_FULL);
gstate_c.SetTextureFullAlpha(entry->GetAlphaStatus() == TextureAlpha::Solid);
gstate_c.SetTextureIs3D((entry->status & TexCacheEntry::STATUS_3D) != 0);
gstate_c.SetTextureIsArray(false);
gstate_c.SetTextureIsBGRA((entry->status & TexCacheEntry::STATUS_BGRA) != 0);
@@ -2359,8 +2359,8 @@ void TextureCacheCommon::ApplyTextureFramebuffer(VirtualFramebuffer *framebuffer
const u32 bytesPerColor = clutFormat == GE_CMODE_32BIT_ABGR8888 ? sizeof(u32) : sizeof(u16);
const u32 clutTotalColors = clutMaxBytes_ / bytesPerColor;
CheckAlphaResult alphaStatus = CheckCLUTAlpha((const uint8_t *)clutBufRaw_, clutFormat, clutTotalColors);
gstate_c.SetTextureFullAlpha(alphaStatus == CHECKALPHA_FULL);
TextureAlpha alphaStatus = CheckCLUTAlpha((const uint8_t *)clutBufRaw_, clutFormat, clutTotalColors);
gstate_c.SetTextureFullAlpha(alphaStatus == TextureAlpha::Solid);
draw_->Invalidate(InvalidationFlags::CACHED_RENDER_STATE);
return;
@@ -2434,8 +2434,8 @@ void TextureCacheCommon::ApplyTextureFramebuffer(VirtualFramebuffer *framebuffer
const u32 bytesPerColor = clutFormat == GE_CMODE_32BIT_ABGR8888 ? sizeof(u32) : sizeof(u16);
const u32 clutTotalColors = clutMaxBytes_ / bytesPerColor;
CheckAlphaResult alphaStatus = CheckCLUTAlpha((const uint8_t *)clutBufRaw_, clutFormat, clutTotalColors);
gstate_c.SetTextureFullAlpha(alphaStatus == CHECKALPHA_FULL);
TextureAlpha alphaStatus = CheckCLUTAlpha((const uint8_t *)clutBufRaw_, clutFormat, clutTotalColors);
gstate_c.SetTextureFullAlpha(alphaStatus == TextureAlpha::Solid);
draw_->Invalidate(InvalidationFlags::CACHED_RENDER_STATE);
shaderManager_->DirtyLastShader();
@@ -3045,7 +3045,7 @@ void TextureCacheCommon::LoadTextureLevel(TexCacheEntry &entry, uint8_t *data, s
texDecFlags |= TexDecodeFlags::TO_CLUT8;
}
CheckAlphaResult alphaResult = DecodeTextureLevel((u8 *)pixelData, decPitch, tfmt, clutformat, texaddr, srcLevel, bufw, texDecFlags);
TextureAlpha alphaResult = DecodeTextureLevel((u8 *)pixelData, decPitch, tfmt, clutformat, texaddr, srcLevel, bufw, texDecFlags);
entry.SetAlphaStatus(alphaResult, srcLevel);
int scaledW = w, scaledH = h;
@@ -3082,7 +3082,7 @@ void TextureCacheCommon::LoadTextureLevel(TexCacheEntry &entry, uint8_t *data, s
}
}
CheckAlphaResult TextureCacheCommon::CheckCLUTAlpha(const uint8_t *pixelData, GEPaletteFormat clutFormat, int w) {
TextureAlpha TextureCacheCommon::CheckCLUTAlpha(const uint8_t *pixelData, GEPaletteFormat clutFormat, int w) {
switch (clutFormat) {
case GE_CMODE_16BIT_ABGR4444:
return CheckAlpha16((const u16 *)pixelData, w, 0xF000);
@@ -3090,7 +3090,7 @@ CheckAlphaResult TextureCacheCommon::CheckCLUTAlpha(const uint8_t *pixelData, GE
return CheckAlpha16((const u16 *)pixelData, w, 0x8000);
case GE_CMODE_16BIT_BGR5650:
// Never has any alpha.
return CHECKALPHA_FULL;
return TextureAlpha::Solid;
default:
return CheckAlpha32((const u32 *)pixelData, w, 0xFF000000);
}
+10 -16
View File
@@ -30,6 +30,7 @@
#include "GPU/Common/TextureScalerCommon.h"
#include "GPU/Common/TextureShaderCommon.h"
#include "GPU/Common/TextureReplacer.h"
#include "GPU/Common/ImageCommon.h"
#include "GPU/GPUDefinitions.h"
class Draw2D;
@@ -204,22 +205,15 @@ struct TexCacheEntry {
u16 maxSeenV;
ReplacedTexture *replacedTexture;
TexStatus GetAlphaStatus() {
return TexStatus(status & STATUS_ALPHA_MASK);
TextureAlpha GetAlphaStatus() {
return (status & STATUS_ALPHA_MASK) == STATUS_ALPHA_FULL ? TextureAlpha::Solid : TextureAlpha::Any;
}
void SetAlphaStatus(TexStatus newStatus) {
status = (status & ~STATUS_ALPHA_MASK) | newStatus;
void SetAlphaStatus(TextureAlpha newStatus) {
status = (status & ~STATUS_ALPHA_MASK) | (newStatus == TextureAlpha::Solid ? STATUS_ALPHA_FULL : STATUS_ALPHA_UNKNOWN);
}
void SetAlphaStatus(TexStatus newStatus, int level) {
void SetAlphaStatus(TextureAlpha newStatus, int level) {
// For non-level zero, only set more restrictive.
if (newStatus == STATUS_ALPHA_UNKNOWN || level == 0) {
SetAlphaStatus(newStatus);
}
}
void SetAlphaStatus(CheckAlphaResult alphaResult, int level) {
TexStatus newStatus = (TexStatus)alphaResult;
// For non-level zero, only set more restrictive.
if (newStatus == STATUS_ALPHA_UNKNOWN || level == 0) {
if (newStatus == TextureAlpha::Any || level == 0) {
SetAlphaStatus(newStatus);
}
}
@@ -423,9 +417,9 @@ protected:
virtual void BindAsClutTexture(Draw::Texture *tex, bool smooth) {}
CheckAlphaResult DecodeTextureLevel(u8 *out, int outPitch, GETextureFormat format, GEPaletteFormat clutformat, uint32_t texaddr, int level, int bufw, TexDecodeFlags flags);
TextureAlpha DecodeTextureLevel(u8 *out, int outPitch, GETextureFormat format, GEPaletteFormat clutformat, uint32_t texaddr, int level, int bufw, TexDecodeFlags flags);
static 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);
TextureAlpha 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, int *d);
void PollReplacement(TexCacheEntry *entry, int *w, int *h, int *d);
@@ -455,7 +449,7 @@ protected:
bool IsVideo(u32 texaddr) const;
static CheckAlphaResult CheckCLUTAlpha(const uint8_t *pixelData, GEPaletteFormat clutFmt, int w);
static TextureAlpha CheckCLUTAlpha(const uint8_t *pixelData, GEPaletteFormat clutFmt, int w);
static inline u32 QuickTexHash(TextureReplacer &replacer, u32 addr, int bufw, int w, int h, bool swizzled, GETextureFormat format, const TexCacheEntry *entry) {
if (replacer.Enabled()) {
+7 -12
View File
@@ -24,12 +24,7 @@
#include "Core/MemMap.h"
#include "GPU/ge_constants.h"
#include "GPU/GPUState.h"
enum CheckAlphaResult {
// These are intended to line up with TexCacheEntry::STATUS_ALPHA_UNKNOWN, etc.
CHECKALPHA_FULL = 0,
CHECKALPHA_ANY = 4,
};
#include "GPU/Common/ImageCommon.h"
// For both of these, pitch must be aligned to 16 bits (as is the case on a PSP).
void DoSwizzleTex16(const u32 *ysrcp, u8 *texptr, int bxc, int byc, u32 pitch);
@@ -86,24 +81,24 @@ inline bool AlphaSumIsFull(u32 alphaSum, u32 fullAlphaMask) {
return fullAlphaMask != 0 && (alphaSum & fullAlphaMask) == fullAlphaMask;
}
inline CheckAlphaResult CheckAlpha16(const u16 *pixelData, int width, u32 fullAlphaMask) {
inline TextureAlpha CheckAlpha16(const u16 *pixelData, int width, u32 fullAlphaMask) {
u32 alphaSum = 0xFFFFFFFF;
CheckMask16(pixelData, width, &alphaSum);
return AlphaSumIsFull(alphaSum, fullAlphaMask) ? CHECKALPHA_FULL : CHECKALPHA_ANY;
return AlphaSumIsFull(alphaSum, fullAlphaMask) ? TextureAlpha::Solid : TextureAlpha::Any;
}
inline CheckAlphaResult CheckAlpha32(const u32 *pixelData, int width, u32 fullAlphaMask) {
inline TextureAlpha CheckAlpha32(const u32 *pixelData, int width, u32 fullAlphaMask) {
u32 alphaSum = 0xFFFFFFFF;
CheckMask32(pixelData, width, &alphaSum);
return AlphaSumIsFull(alphaSum, fullAlphaMask) ? CHECKALPHA_FULL : CHECKALPHA_ANY;
return AlphaSumIsFull(alphaSum, fullAlphaMask) ? TextureAlpha::Solid : TextureAlpha::Any;
}
inline CheckAlphaResult CheckAlpha32Rect(const u32 *pixelData, int stride, int width, int height, u32 fullAlphaMask) {
inline TextureAlpha CheckAlpha32Rect(const u32 *pixelData, int stride, int width, int height, u32 fullAlphaMask) {
u32 alphaSum = 0xFFFFFFFF;
for (int y = 0; y < height; y++) {
CheckMask32(pixelData + stride * y, width, &alphaSum);
}
return AlphaSumIsFull(alphaSum, fullAlphaMask) ? CHECKALPHA_FULL : CHECKALPHA_ANY;
return AlphaSumIsFull(alphaSum, fullAlphaMask) ? TextureAlpha::Solid : TextureAlpha::Any;
}
template <typename IndexT, typename ClutT>
+1 -1
View File
@@ -440,7 +440,7 @@ void TextureCacheD3D11::BuildTexture(TexCacheEntry *const entry) {
}
if (plan.doReplace) {
entry->SetAlphaStatus(TexCacheEntry::TexStatus(plan.replaced->AlphaStatus()));
entry->SetAlphaStatus(plan.replaced->AlphaStatus());
if (!Draw::DataFormatIsBlockCompressed(plan.replaced->Format(), nullptr)) {
entry->status |= TexCacheEntry::STATUS_BGRA;
+1 -1
View File
@@ -351,7 +351,7 @@ void TextureCacheGLES::BuildTexture(TexCacheEntry *const entry) {
}
if (plan.doReplace) {
entry->SetAlphaStatus(TexCacheEntry::TexStatus(plan.replaced->AlphaStatus()));
entry->SetAlphaStatus(plan.replaced->AlphaStatus());
}
}
+1
View File
@@ -256,6 +256,7 @@
<ItemGroup>
<ClInclude Include="..\ext\xbrz\xbrz.h" />
<ClInclude Include="Common\DepthRaster.h" />
<ClInclude Include="Common\ImageCommon.h" />
<ClInclude Include="Common\ReplacedTexture.h" />
<ClInclude Include="Common\TextureReplacer.h" />
<ClInclude Include="Common\TextureShaderCommon.h" />
+3
View File
@@ -267,6 +267,9 @@
<ClInclude Include="Common\VertexReader.h">
<Filter>Common</Filter>
</ClInclude>
<ClInclude Include="Common\ImageCommon.h">
<Filter>Common</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Math3D.cpp">
+2 -2
View File
@@ -941,7 +941,7 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) {
}
if (plan.doReplace) {
entry->SetAlphaStatus(TexCacheEntry::TexStatus(plan.replaced->AlphaStatus()));
entry->SetAlphaStatus(plan.replaced->AlphaStatus());
}
}
@@ -1015,7 +1015,7 @@ void TextureCacheVulkan::LoadVulkanTextureLevel(TexCacheEntry &entry, uint8_t *w
decPitch = rowPitch;
}
CheckAlphaResult alphaResult = DecodeTextureLevel((u8 *)pixelData, decPitch, tfmt, clutformat, texaddr, level, bufw, texDecFlags);
TextureAlpha alphaResult = DecodeTextureLevel((u8 *)pixelData, decPitch, tfmt, clutformat, texaddr, level, bufw, texDecFlags);
entry.SetAlphaStatus(alphaResult, level);
if (scaleFactor > 1) {