mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
softgpu: Use cached write mask in draw pixel.
This commit is contained in:
parent
f1ce2e7715
commit
c0d548846f
2 changed files with 36 additions and 17 deletions
|
@ -62,22 +62,22 @@ static inline u8 GetPixelStencil(GEBufferFormat fmt, int fbStride, int x, int y)
|
|||
}
|
||||
}
|
||||
|
||||
static inline void SetPixelStencil(GEBufferFormat fmt, int fbStride, int x, int y, u8 value) {
|
||||
static inline void SetPixelStencil(GEBufferFormat fmt, int fbStride, uint32_t targetWriteMask, int x, int y, u8 value) {
|
||||
if (fmt == GE_FORMAT_565) {
|
||||
// Do nothing
|
||||
} else if (fmt == GE_FORMAT_5551) {
|
||||
if ((gstate.getStencilWriteMask() & 0x80) == 0) {
|
||||
if ((targetWriteMask & 0x8000) == 0) {
|
||||
u16 pixel = fb.Get16(x, y, fbStride) & ~0x8000;
|
||||
pixel |= (value & 0x80) << 8;
|
||||
fb.Set16(x, y, fbStride, pixel);
|
||||
}
|
||||
} else if (fmt == GE_FORMAT_4444) {
|
||||
const u16 write_mask = (gstate.getStencilWriteMask() << 8) | 0x0FFF;
|
||||
const u16 write_mask = targetWriteMask | 0x0FFF;
|
||||
u16 pixel = fb.Get16(x, y, fbStride) & write_mask;
|
||||
pixel |= ((u16)value << 8) & ~write_mask;
|
||||
fb.Set16(x, y, fbStride, pixel);
|
||||
} else {
|
||||
const u32 write_mask = (gstate.getStencilWriteMask() << 24) | 0x00FFFFFF;
|
||||
const u32 write_mask = targetWriteMask | 0x00FFFFFF;
|
||||
u32 pixel = fb.Get32(x, y, fbStride) & write_mask;
|
||||
pixel |= ((u32)value << 24) & ~write_mask;
|
||||
fb.Set32(x, y, fbStride, pixel);
|
||||
|
@ -113,21 +113,37 @@ static inline u32 GetPixelColor(GEBufferFormat fmt, int fbStride, int x, int y)
|
|||
}
|
||||
}
|
||||
|
||||
static inline void SetPixelColor(GEBufferFormat fmt, int fbStride, int x, int y, u32 value) {
|
||||
static inline void SetPixelColor(GEBufferFormat fmt, int fbStride, int x, int y, u32 value, u32 old_value, u32 targetWriteMask) {
|
||||
switch (fmt) {
|
||||
case GE_FORMAT_565:
|
||||
fb.Set16(x, y, fbStride, RGBA8888ToRGB565(value));
|
||||
value = RGBA8888ToRGB565(value);
|
||||
if (targetWriteMask != 0) {
|
||||
old_value = RGBA8888ToRGB565(old_value);
|
||||
value = (value & ~targetWriteMask) | (old_value & targetWriteMask);
|
||||
}
|
||||
fb.Set16(x, y, fbStride, value);
|
||||
break;
|
||||
|
||||
case GE_FORMAT_5551:
|
||||
fb.Set16(x, y, fbStride, RGBA8888ToRGBA5551(value));
|
||||
value = RGBA8888ToRGBA5551(value);
|
||||
if (targetWriteMask != 0) {
|
||||
old_value = RGBA8888ToRGBA5551(old_value);
|
||||
value = (value & ~targetWriteMask) | (old_value & targetWriteMask);
|
||||
}
|
||||
fb.Set16(x, y, fbStride, value);
|
||||
break;
|
||||
|
||||
case GE_FORMAT_4444:
|
||||
fb.Set16(x, y, fbStride, RGBA8888ToRGBA4444(value));
|
||||
value = RGBA8888ToRGBA4444(value);
|
||||
if (targetWriteMask != 0) {
|
||||
old_value = RGBA8888ToRGBA4444(old_value);
|
||||
value = (value & ~targetWriteMask) | (old_value & targetWriteMask);
|
||||
}
|
||||
fb.Set16(x, y, fbStride, value);
|
||||
break;
|
||||
|
||||
case GE_FORMAT_8888:
|
||||
value = (value & ~targetWriteMask) | (old_value & targetWriteMask);
|
||||
fb.Set32(x, y, fbStride, value);
|
||||
break;
|
||||
|
||||
|
@ -405,6 +421,7 @@ void SOFTRAST_CALL DrawSinglePixel(int x, int y, int z, int fog, Vec4IntArg colo
|
|||
return;
|
||||
|
||||
// In clear mode, it uses the alpha color as stencil.
|
||||
uint32_t targetWriteMask = pixelID.applyColorWriteMask ? pixelID.cached.colorWriteMask : 0;
|
||||
u8 stencil = clearMode ? prim_color.a() : GetPixelStencil(fbFormat, pixelID.cached.framebufStride, x, y);
|
||||
if (clearMode) {
|
||||
if (pixelID.DepthClear())
|
||||
|
@ -412,14 +429,14 @@ void SOFTRAST_CALL DrawSinglePixel(int x, int y, int z, int fog, Vec4IntArg colo
|
|||
} else if (pixelID.stencilTest) {
|
||||
if (!StencilTestPassed(pixelID, stencil)) {
|
||||
stencil = ApplyStencilOp(fbFormat, pixelID.SFail(), stencil);
|
||||
SetPixelStencil(fbFormat, pixelID.cached.framebufStride, x, y, stencil);
|
||||
SetPixelStencil(fbFormat, pixelID.cached.framebufStride, targetWriteMask, x, y, stencil);
|
||||
return;
|
||||
}
|
||||
|
||||
// Also apply depth at the same time. If disabled, same as passing.
|
||||
if (pixelID.DepthTestFunc() != GE_COMP_ALWAYS && !DepthTestPassed(pixelID.DepthTestFunc(), x, y, pixelID.cached.depthbufStride, z)) {
|
||||
stencil = ApplyStencilOp(fbFormat, pixelID.ZFail(), stencil);
|
||||
SetPixelStencil(fbFormat, pixelID.cached.framebufStride, x, y, stencil);
|
||||
SetPixelStencil(fbFormat, pixelID.cached.framebufStride, targetWriteMask, x, y, stencil);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -474,9 +491,8 @@ void SOFTRAST_CALL DrawSinglePixel(int x, int y, int z, int fog, Vec4IntArg colo
|
|||
if (!pixelID.StencilClear())
|
||||
new_color = (new_color & 0x00FFFFFF) | (old_color & 0xFF000000);
|
||||
}
|
||||
new_color = (new_color & ~gstate.getColorMask()) | (old_color & gstate.getColorMask());
|
||||
|
||||
SetPixelColor(fbFormat, pixelID.cached.framebufStride, x, y, new_color);
|
||||
SetPixelColor(fbFormat, pixelID.cached.framebufStride, x, y, new_color, old_color, targetWriteMask);
|
||||
}
|
||||
|
||||
SingleFunc GetSingleFunc(const PixelFuncID &id) {
|
||||
|
|
|
@ -932,7 +932,7 @@ bool PixelJitCache::Jit_WriteStencilOnly(const PixelFuncID &id, RegCache::Reg st
|
|||
X64Reg colorOffReg = GetColorOff(id);
|
||||
Describe("WriteStencil");
|
||||
if (id.applyColorWriteMask) {
|
||||
X64Reg gstateReg = GetGState();
|
||||
X64Reg idReg = GetPixelID();
|
||||
X64Reg maskReg = regCache_.Alloc(RegCache::GEN_TEMP5);
|
||||
|
||||
switch (id.fbFormat) {
|
||||
|
@ -940,7 +940,8 @@ bool PixelJitCache::Jit_WriteStencilOnly(const PixelFuncID &id, RegCache::Reg st
|
|||
break;
|
||||
|
||||
case GE_FORMAT_5551:
|
||||
MOVZX(32, 8, maskReg, MDisp(gstateReg, offsetof(GPUgstate, pmska)));
|
||||
// Read the high 8 bits of the 16-bit color mask.
|
||||
MOVZX(32, 8, maskReg, MDisp(idReg, offsetof(PixelFuncID, cached.colorWriteMask) + 1));
|
||||
OR(8, R(maskReg), Imm8(0x7F));
|
||||
|
||||
// Poor man's BIC...
|
||||
|
@ -953,7 +954,8 @@ bool PixelJitCache::Jit_WriteStencilOnly(const PixelFuncID &id, RegCache::Reg st
|
|||
break;
|
||||
|
||||
case GE_FORMAT_4444:
|
||||
MOVZX(32, 8, maskReg, MDisp(gstateReg, offsetof(GPUgstate, pmska)));
|
||||
// Read the high 8 bits of the 16-bit color mask.
|
||||
MOVZX(32, 8, maskReg, MDisp(idReg, offsetof(PixelFuncID, cached.colorWriteMask) + 1));
|
||||
OR(8, R(maskReg), Imm8(0x0F));
|
||||
|
||||
// Poor man's BIC...
|
||||
|
@ -966,7 +968,8 @@ bool PixelJitCache::Jit_WriteStencilOnly(const PixelFuncID &id, RegCache::Reg st
|
|||
break;
|
||||
|
||||
case GE_FORMAT_8888:
|
||||
MOVZX(32, 8, maskReg, MDisp(gstateReg, offsetof(GPUgstate, pmska)));
|
||||
// Read the high 8 bits of the 32-bit color mask.
|
||||
MOVZX(32, 8, maskReg, MDisp(idReg, offsetof(PixelFuncID, cached.colorWriteMask) + 3));
|
||||
|
||||
// Poor man's BIC...
|
||||
NOT(32, R(stencilReg));
|
||||
|
@ -979,7 +982,7 @@ bool PixelJitCache::Jit_WriteStencilOnly(const PixelFuncID &id, RegCache::Reg st
|
|||
}
|
||||
|
||||
regCache_.Release(maskReg, RegCache::GEN_TEMP5);
|
||||
regCache_.Unlock(gstateReg, RegCache::GEN_GSTATE);
|
||||
UnlockPixelID(idReg);
|
||||
} else {
|
||||
switch (id.fbFormat) {
|
||||
case GE_FORMAT_565:
|
||||
|
|
Loading…
Add table
Reference in a new issue