Yet another ClearScreen fix, should be the last one now.

Should fix almost all regressions of the recent ClearScreen changes and keep the fixed stuff.
The Super Mario Sunshine glitch is caused by another issue and will be addressed in my next commit.


git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@6668 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
NeoBrainX 2010-12-27 18:09:03 +00:00
parent c33f46406e
commit 6e8df50fff
6 changed files with 36 additions and 76 deletions

View File

@ -25,7 +25,6 @@
bool textureChanged[8];
const bool renderFog = false;
int prev_pix_format = -1;
namespace BPFunctions
{
// ----------------------------------------------
@ -90,66 +89,49 @@ void CopyEFB(const BPCmd &bp, const EFBRectangle &rc, const u32 &address, const
There's numerous possible formats for the pixel data in the EFB.
However, in the HW accelerated plugins we're always using RGBA8
for the EFB format, which causes some problems:
- We're using an alpha channel although the game doesn't (1)
- If the actual EFB format is PIXELFMT_RGBA6_Z24, we are using more bits per channel than the native HW (2)
- When doing a z copy EFB copy target format GX_TF_Z24X8 , the native HW don't worry about hthe color efb format because it only uses the depth part
- When changing EFB formats the efb must be cleared (3)
- Possible other oddities should be noted here as well
- We're using an alpha channel although the game doesn't
- If the actual EFB format is RGBA6_Z24 or R5G6B5_Z16, we are using more bits per channel than the native HW
To properly emulate the above points, we're doing the following:
(1)
- disable alpha channel writing of any kind of rendering if the actual EFB format doesn't use an alpha channel
- NOTE: Always make sure that the EFB has been cleared to an alpha value of 0xFF in this case!
- in a dition to the previus make sure we always return 0xFF in alpha when reading the efb content if the efb format has no alpha
- Same for color channels, these need to be cleared to 0x00 though.
(2)
- just scale down the RGBA8 color to RGBA6 and upscale it to RGBA8 again
(3) - when the pixel format changes:
- call ClearScreen using the correct alpha format for the previus pixel format
- convert the RGBA8 color to RGBA6/RGB8/RGB565 and convert it to RGBA8 again
- convert the Z24 depth value to Z16 and back to Z24
*/
void ClearScreen(const BPCmd &bp, const EFBRectangle &rc)
{
UPE_Copy PE_copy = bpmem.triggerEFBCopy;
bool colorEnable = bpmem.blendmode.colorupdate;
bool alphaEnable = bpmem.blendmode.alphaupdate;
bool zEnable = bpmem.zmode.updateenable;
u32 color = (bpmem.clearcolorAR << 16) | bpmem.clearcolorGB;
u32 z = bpmem.clearZValue;
if(prev_pix_format == -1)
{
prev_pix_format = bpmem.zcontrol.pixel_format;
}
// (1): Disable unused color channels
switch (bpmem.zcontrol.pixel_format)
{
case PIXELFMT_RGB8_Z24:
case PIXELFMT_RGB565_Z16:
alphaEnable = true;
color |= (prev_pix_format == PIXELFMT_RGBA6_Z24)? 0x0 : 0xFF000000;//(3)
break;
case PIXELFMT_Z24:
alphaEnable = colorEnable = false;
break;
default:
break;
// (1): Disable unused color channels
if (bpmem.zcontrol.pixel_format == PIXELFMT_RGB8_Z24 ||
bpmem.zcontrol.pixel_format == PIXELFMT_RGB565_Z16 ||
bpmem.zcontrol.pixel_format == PIXELFMT_Z24)
{
alphaEnable = false;
}
if (colorEnable || alphaEnable || zEnable)
{
u32 color = (bpmem.clearcolorAR << 16) | bpmem.clearcolorGB;
u32 z = bpmem.clearZValue;
// (2) drop additional accuracy
if (bpmem.zcontrol.pixel_format == PIXELFMT_RGBA6_Z24)
{
color = RGBA8ToRGBA6ToRGBA8(color);
}
else if (bpmem.zcontrol.pixel_format == PIXELFMT_RGB565_Z16)
{
color = RGBA8ToRGB565ToRGB8(color);
color = RGBA8ToRGB565ToRGBA8(color);
z = Z24ToZ16ToZ24(z);
}
g_renderer->ClearScreen(rc, colorEnable, alphaEnable, zEnable, color, z);
}
prev_pix_format = bpmem.zcontrol.pixel_format;
}

View File

@ -545,10 +545,6 @@ void TextureCache::CopyRenderTargetToTexture(u32 address, bool bFromZBuffer,
else// alpha
{
colmat[15] = 1;
if(bpmem.zcontrol.pixel_format != PIXELFMT_RGBA6_Z24)
{
fConstAdd[3] = 1;
}
cbufid = 1;
}
@ -575,18 +571,10 @@ void TextureCache::CopyRenderTargetToTexture(u32 address, bool bFromZBuffer,
case 3: // RA8
colmat[0] = colmat[4] = colmat[8] = colmat[15] = 1;
cbufid = 3;
if(bpmem.zcontrol.pixel_format != PIXELFMT_RGBA6_Z24)
{
fConstAdd[3] = 1;
}
break;
case 7: // A8
colmat[3] = colmat[7] = colmat[11] = colmat[15] = 1;
if(bpmem.zcontrol.pixel_format != PIXELFMT_RGBA6_Z24)
{
fConstAdd[0] = fConstAdd[1] = fConstAdd[2] = fConstAdd[3] = 1;
}
cbufid = 4;
break;
@ -620,10 +608,6 @@ void TextureCache::CopyRenderTargetToTexture(u32 address, bool bFromZBuffer,
case 6: // RGBA8
colmat[0] = colmat[5] = colmat[10] = colmat[15] = 1;
cbufid = 10;
if(bpmem.zcontrol.pixel_format != PIXELFMT_RGBA6_Z24)
{
fConstAdd[3] = 1;
}
break;
default:
@ -633,8 +617,6 @@ void TextureCache::CopyRenderTargetToTexture(u32 address, bool bFromZBuffer,
break;
}
}
const unsigned int tex_w = (abs(source_rect.GetWidth()) >> (int)bScaleByHalf);
const unsigned int tex_h = (abs(source_rect.GetHeight()) >> (int)bScaleByHalf);
@ -695,4 +677,4 @@ void TextureCache::CopyRenderTargetToTexture(u32 address, bool bFromZBuffer,
entry->FromRenderTarget(bFromZBuffer, bScaleByHalf, cbufid, colmat, source_rect, bIsIntensityFmt, copyfmt);
g_renderer->RestoreAPIState();
}
}

View File

@ -163,7 +163,7 @@ inline u32 RGBA8ToRGBA6ToRGBA8(u32 src)
return color;
}
inline u32 RGBA8ToRGB565ToRGB8(u32 src)
inline u32 RGBA8ToRGB565ToRGBA8(u32 src)
{
u32 color = src;
u32 dstr5 = (color & 0xFF0000) >> 19;
@ -172,9 +172,13 @@ inline u32 RGBA8ToRGB565ToRGB8(u32 src)
u32 dstr8 = (dstr5 << 3) | (dstr5 >> 2);
u32 dstg8 = (dstg6 << 2) | (dstg6 >> 4);
u32 dstb8 = (dstb5 << 3) | (dstb5 >> 2);
color = (dstr8 << 16) | (dstg8 << 8) | dstb8;
color = 0xFF000000 | (dstr8 << 16) | (dstg8 << 8) | dstb8;
return color;
}
inline u32 Z24ToZ16ToZ24(u32 src)
{
return (src & 0xFFFF00) | (src >> 16);
}
#endif // _VIDEOCOMMON_H

View File

@ -466,7 +466,7 @@ void Renderer::SetColorMask()
UINT8 color_mask = 0;
if (bpmem.blendmode.alphaupdate && (bpmem.zcontrol.pixel_format == PIXELFMT_RGBA6_Z24))
color_mask = D3D11_COLOR_WRITE_ENABLE_ALPHA;
if (bpmem.blendmode.colorupdate && (bpmem.zcontrol.pixel_format == PIXELFMT_RGB8_Z24 || bpmem.zcontrol.pixel_format == PIXELFMT_RGBA6_Z24 || bpmem.zcontrol.pixel_format == PIXELFMT_RGB565_Z16))
if (bpmem.blendmode.colorupdate)
color_mask |= D3D11_COLOR_WRITE_ENABLE_RED | D3D11_COLOR_WRITE_ENABLE_GREEN | D3D11_COLOR_WRITE_ENABLE_BLUE;
D3D::gfxstate->SetRenderTargetWriteMask(color_mask);
}
@ -562,7 +562,7 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data)
u32 ret = 0;
if(bpmem.zcontrol.pixel_format == PIXELFMT_RGB565_Z16)
{
// if Z is in 16 bit format yo must return a 16 bit integer
// if Z is in 16 bit format you must return a 16 bit integer
ret = ((u32)(val * 0xffff));
}
else
@ -598,7 +598,7 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data)
}
else if (bpmem.zcontrol.pixel_format == PIXELFMT_RGB565_Z16)
{
ret = RGBA8ToRGB565ToRGB8(ret);
ret = RGBA8ToRGB565ToRGBA8(ret);
}
if(bpmem.zcontrol.pixel_format != PIXELFMT_RGBA6_Z24)
{

View File

@ -477,7 +477,7 @@ void Renderer::SetColorMask()
DWORD color_mask = 0;
if (bpmem.blendmode.alphaupdate && (bpmem.zcontrol.pixel_format == PIXELFMT_RGBA6_Z24))
color_mask = D3DCOLORWRITEENABLE_ALPHA;
if (bpmem.blendmode.colorupdate && (bpmem.zcontrol.pixel_format == PIXELFMT_RGB565_Z16 || bpmem.zcontrol.pixel_format == PIXELFMT_RGB8_Z24|| bpmem.zcontrol.pixel_format == PIXELFMT_RGBA6_Z24))
if (bpmem.blendmode.colorupdate)
color_mask |= D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_BLUE;
D3D::SetRenderState(D3DRS_COLORWRITEENABLE, color_mask);
}
@ -649,7 +649,7 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data)
// TODO: in RE0 this value is often off by one, which causes lighting to disappear
if(bpmem.zcontrol.pixel_format == PIXELFMT_RGB565_Z16)
{
// if Z is in 16 bit format yo must return a 16 bit integer
// if Z is in 16 bit format you must return a 16 bit integer
z = ((u32)(val * 0xffff));
}
else
@ -684,8 +684,8 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data)
}
else if (bpmem.zcontrol.pixel_format == PIXELFMT_RGB565_Z16)
{
ret = RGBA8ToRGB565ToRGB8(ret);
}
ret = RGBA8ToRGB565ToRGBA8(ret);
}
if(bpmem.zcontrol.pixel_format != PIXELFMT_RGBA6_Z24)
{
ret |= 0xFF000000;

View File

@ -663,13 +663,9 @@ void Renderer::SetColorMask()
{
// Only enable alpha channel if it's supported by the current EFB format
GLenum ColorMask = GL_FALSE, AlphaMask = GL_FALSE;
if (bpmem.blendmode.colorupdate &&
(bpmem.zcontrol.pixel_format == PIXELFMT_RGB8_Z24 ||
bpmem.zcontrol.pixel_format == PIXELFMT_RGBA6_Z24 ||
bpmem.zcontrol.pixel_format == PIXELFMT_RGB565_Z16))
if (bpmem.blendmode.colorupdate)
ColorMask = GL_TRUE;
if (bpmem.blendmode.alphaupdate &&
(bpmem.zcontrol.pixel_format == PIXELFMT_RGBA6_Z24))
if (bpmem.blendmode.alphaupdate && (bpmem.zcontrol.pixel_format == PIXELFMT_RGBA6_Z24))
AlphaMask = GL_TRUE;
glColorMask(ColorMask, ColorMask, ColorMask, AlphaMask);
}
@ -727,7 +723,7 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data)
// TODO: in RE0 this value is often off by one, which causes lighting to disappear
if(bpmem.zcontrol.pixel_format == PIXELFMT_RGB565_Z16)
{
// if Z is in 16 bit format yo must return a 16 bit integer
// if Z is in 16 bit format you must return a 16 bit integer
z = z >> 16;
}
else
@ -737,10 +733,6 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data)
return z;
}
case POKE_Z:
// TODO: Implement
break;
case PEEK_COLOR: // GXPeekARGB
{
// Although it may sound strange, this really is A8R8G8B8 and not RGBA or 24-bit...
@ -775,8 +767,8 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data)
}
else if (bpmem.zcontrol.pixel_format == PIXELFMT_RGB565_Z16)
{
color = RGBA8ToRGB565ToRGB8(color);
}
color = RGBA8ToRGB565ToRGBA8(color);
}
if(bpmem.zcontrol.pixel_format != PIXELFMT_RGBA6_Z24)
{
color |= 0xFF000000;
@ -787,13 +779,13 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data)
}
case POKE_COLOR:
case POKE_Z:
// TODO: Implement. One way is to draw a tiny pixel-sized rectangle at
// the exact location. Note: EFB pokes are susceptible to Z-buffering
// and perhaps blending.
//WARN_LOG(VIDEOINTERFACE, "This is probably some kind of software rendering");
break;
// TODO: Implement POKE_Z and POKE_COLOR
default:
break;
}