mirror of
https://github.com/libretro/ppsspp.git
synced 2024-12-11 10:24:43 +00:00
SoftGPU: Implement dithering.
Note: it applies even in 8888, so it can be used as a slight brightness adjustment.
This commit is contained in:
parent
eff793cb7b
commit
7412e13767
@ -173,10 +173,7 @@ struct GPUgstate {
|
|||||||
blend,
|
blend,
|
||||||
blendfixa,
|
blendfixa,
|
||||||
blendfixb,
|
blendfixb,
|
||||||
dith1,
|
dithmtx[4],
|
||||||
dith2,
|
|
||||||
dith3,
|
|
||||||
dith4,
|
|
||||||
lop, // 0xE6
|
lop, // 0xE6
|
||||||
zmsk,
|
zmsk,
|
||||||
pmskc,
|
pmskc,
|
||||||
@ -249,6 +246,11 @@ struct GPUgstate {
|
|||||||
|
|
||||||
// Dither
|
// Dither
|
||||||
bool isDitherEnabled() const { return ditherEnable & 1; }
|
bool isDitherEnabled() const { return ditherEnable & 1; }
|
||||||
|
int getDitherValue(int x, int y) const {
|
||||||
|
u8 raw = (dithmtx[y & 3] >> ((x & 3) * 4)) & 0xF;
|
||||||
|
// Apply sign extension to make 8-F negative, 0-7 positive.
|
||||||
|
return ((s8)(raw << 4)) >> 4;
|
||||||
|
}
|
||||||
|
|
||||||
// Color Mask
|
// Color Mask
|
||||||
u32 getColorMask() const { return (pmskc & 0xFFFFFF) | ((pmska & 0xFF) << 24); }
|
u32 getColorMask() const { return (pmskc & 0xFFFFFF) | ((pmska & 0xFF) << 24); }
|
||||||
|
@ -895,12 +895,24 @@ inline void DrawSinglePixel(const DrawingCoords &p, u16 z, u8 fog, const Vec4<in
|
|||||||
const u32 old_color = GetPixelColor(p.x, p.y);
|
const u32 old_color = GetPixelColor(p.x, p.y);
|
||||||
u32 new_color;
|
u32 new_color;
|
||||||
|
|
||||||
|
// Dithering happens before the logic op and regardless of framebuffer format or clear mode.
|
||||||
|
// We do it while alpha blending because it happens before clamping.
|
||||||
if (gstate.isAlphaBlendEnabled() && !clearMode) {
|
if (gstate.isAlphaBlendEnabled() && !clearMode) {
|
||||||
const Vec4<int> dst = Vec4<int>::FromRGBA(old_color);
|
const Vec4<int> dst = Vec4<int>::FromRGBA(old_color);
|
||||||
|
Vec3<int> blended = AlphaBlendingResult(prim_color, dst);
|
||||||
|
if (gstate.isDitherEnabled()) {
|
||||||
|
blended += Vec3<int>::AssignToAll(gstate.getDitherValue(p.x, p.y));
|
||||||
|
}
|
||||||
|
|
||||||
// ToRGB() always automatically clamps.
|
// ToRGB() always automatically clamps.
|
||||||
new_color = AlphaBlendingResult(prim_color, dst).ToRGB();
|
new_color = blended.ToRGB();
|
||||||
new_color |= stencil << 24;
|
new_color |= stencil << 24;
|
||||||
} else {
|
} else {
|
||||||
|
if (gstate.isDitherEnabled()) {
|
||||||
|
// We'll discard alpha anyway.
|
||||||
|
prim_color += Vec4<int>::AssignToAll(gstate.getDitherValue(p.x, p.y));
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(_M_SSE)
|
#if defined(_M_SSE)
|
||||||
new_color = Vec3<int>(prim_color.ivec).ToRGB();
|
new_color = Vec3<int>(prim_color.ivec).ToRGB();
|
||||||
new_color |= stencil << 24;
|
new_color |= stencil << 24;
|
||||||
@ -920,7 +932,6 @@ inline void DrawSinglePixel(const DrawingCoords &p, u16 z, u8 fog, const Vec4<in
|
|||||||
}
|
}
|
||||||
new_color = (new_color & ~gstate.getColorMask()) | (old_color & gstate.getColorMask());
|
new_color = (new_color & ~gstate.getColorMask()) | (old_color & gstate.getColorMask());
|
||||||
|
|
||||||
// TODO: Dither before or inside SetPixelColor
|
|
||||||
SetPixelColor(p.x, p.y, new_color);
|
SetPixelColor(p.x, p.y, new_color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user