First Experimental Commit:

make some changes to the Clear code. please test a lot , the point of this commit is to determine the correct behavior of the efb clearing so feedback is welcome

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@6663 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
Rodolfo Osvaldo Bogado 2010-12-27 03:09:11 +00:00
parent 695010520f
commit f3336a84a1
3 changed files with 61 additions and 54 deletions

View File

@ -25,7 +25,7 @@
bool textureChanged[8]; bool textureChanged[8];
const bool renderFog = false; const bool renderFog = false;
int prev_pix_format = -1;
namespace BPFunctions namespace BPFunctions
{ {
// ---------------------------------------------- // ----------------------------------------------
@ -92,26 +92,22 @@ void CopyEFB(const BPCmd &bp, const EFBRectangle &rc, const u32 &address, const
for the EFB format, which causes some problems: for the EFB format, which causes some problems:
- We're using an alpha channel although the game doesn't (1) - 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) - 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 (and possibly others?)), the native HW assumes that the EFB format is RGB8 when clearing. - 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
Thus the RGBA6 values get overwritten with plain RGB8 data without any kind of conversion. (3) - When changing EFB formats the efb must be cleared (3)
- When changing EFB formats, the EFB contents will NOT get converted to the new format;
this currently isn't implemented in any HW accelerated plugin and might cause issues. (4)
- Possible other oddities should be noted here as well - Possible other oddities should be noted here as well
To properly emulate the above points, we're doing the following: To properly emulate the above points, we're doing the following:
(1) (1)
- disable alpha channel writing of any kind of rendering if the actual EFB format doesn't use an alpha channel - 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! - 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. - Same for color channels, these need to be cleared to 0x00 though.
(2) (2)
- just scale down the RGBA8 color to RGBA6 and upscale it to RGBA8 again - just scale down the RGBA8 color to RGBA6 and upscale it to RGBA8 again
(3) (3) - when the pixel format changes:
- more tricky, doing some bit magic here to properly reinterpret the data - call ClearScreen using the correct alpha format for the previus pixel format
(4) TODO
- generally delay ClearScreen calls as long as possible (until any other EFB access)
- when the pixel format changes:
- call ClearScreen if it's still being delayed, reinterpret the color for the new format though
- otherwise convert EFB contents to the new pixel format
*/ */
void ClearScreen(const BPCmd &bp, const EFBRectangle &rc) void ClearScreen(const BPCmd &bp, const EFBRectangle &rc)
{ {
@ -119,73 +115,44 @@ void ClearScreen(const BPCmd &bp, const EFBRectangle &rc)
bool colorEnable = bpmem.blendmode.colorupdate; bool colorEnable = bpmem.blendmode.colorupdate;
bool alphaEnable = bpmem.blendmode.alphaupdate; bool alphaEnable = bpmem.blendmode.alphaupdate;
bool zEnable = bpmem.zmode.updateenable; 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 // (1): Disable unused color channels
switch (bpmem.zcontrol.pixel_format) switch (bpmem.zcontrol.pixel_format)
{ {
case PIXELFMT_RGBA6_Z24:
if (colorEnable && PE_copy.tp_realFormat() == GX_TF_Z24X8) // (3): alpha update forced
alphaEnable = true;
break;
case PIXELFMT_RGB8_Z24: case PIXELFMT_RGB8_Z24:
case PIXELFMT_RGB565_Z16: case PIXELFMT_RGB565_Z16:
alphaEnable = false; alphaEnable = true;
color |= (prev_pix_format == PIXELFMT_RGBA6_Z24)? 0x0 : 0xFF000000;//(3)
break; break;
case PIXELFMT_Z24: case PIXELFMT_Z24:
alphaEnable = colorEnable = false; alphaEnable = colorEnable = false;
break; break;
default: default:
// TODO?
break; break;
} }
if (colorEnable || alphaEnable || zEnable) if (colorEnable || alphaEnable || zEnable)
{ {
u32 color = (bpmem.clearcolorAR << 16) | bpmem.clearcolorGB;
u32 z = bpmem.clearZValue;
if (bpmem.zcontrol.pixel_format == PIXELFMT_RGBA6_Z24) if (bpmem.zcontrol.pixel_format == PIXELFMT_RGBA6_Z24)
{ {
// TODO: Not sure whether there's more formats to check for here - maybe GX_TF_Z8 and GX_TF_Z16? color = RGBA8ToRGBA6ToRGBA8(color);
if (PE_copy.tp_realFormat() == GX_TF_Z24X8) // (3): Reinterpret RGB8 color as RGBA6
{
// NOTE: color is passed in ARGB order, but EFB uses RGBA
u32 srcr8 = (color & 0xFF0000) >> 16;
u32 srcg8 = (color & 0xFF00) >> 8;
u32 srcb8 = color & 0xFF;
u32 dstr6 = srcr8 >> 2;
u32 dstg6 = ((srcr8 & 0x3) << 4) | (srcg8 >> 4);
u32 dstb6 = ((srcg8 & 0xF) << 2) | (srcb8 >> 6);
u32 dsta6 = srcb8 & 0x3F;
u32 dstr8 = (dstr6 << 2) | (dstr6 >> 4);
u32 dstg8 = (dstg6 << 2) | (dstg6 >> 4);
u32 dstb8 = (dstb6 << 2) | (dstb6 >> 4);
u32 dsta8 = (dsta6 << 2) | (dsta6 >> 4);
color = (dsta8 << 24) | (dstr8 << 16) | (dstg8 << 8) | dstb8;
}
else // (2): convert RGBA8 color to RGBA6
{
color &= 0xFCFCFCFC;
color |= (color >> 6) & 0x03030303;
}
} }
else if (bpmem.zcontrol.pixel_format == PIXELFMT_RGB565_Z16) else if (bpmem.zcontrol.pixel_format == PIXELFMT_RGB565_Z16)
{ {
z >>= 8; color = RGBA8ToRGB565ToRGB8(color);
u32 dstr5 = (color & 0xFF0000) >> 19;
u32 dstg6 = (color & 0xFF00) >> 10;
u32 dstb5 = (color & 0xFF) >> 3;
u32 dstr8 = (dstr5 << 3) | (dstr5 >> 2);
u32 dstg8 = (dstg6 << 2) | (dstg6 >> 4);
u32 dstb8 = (dstb5 << 3) | (dstb5 >> 2);
color = (dstr8 << 16) | (dstg8 << 8) | dstb8;
} }
g_renderer->ClearScreen(rc, colorEnable, alphaEnable, zEnable, color, z); g_renderer->ClearScreen(rc, colorEnable, alphaEnable, zEnable, color, z);
} }
prev_pix_format = bpmem.zcontrol.pixel_format;
} }
void RestoreRenderState(const BPCmd &bp) void RestoreRenderState(const BPCmd &bp)
{ {
g_renderer->RestoreAPIState(); g_renderer->RestoreAPIState();

View File

@ -545,6 +545,10 @@ void TextureCache::CopyRenderTargetToTexture(u32 address, bool bFromZBuffer,
else// alpha else// alpha
{ {
colmat[15] = 1; colmat[15] = 1;
if(bpmem.zcontrol.pixel_format != PIXELFMT_RGBA6_Z24)
{
fConstAdd[3] = 1;
}
cbufid = 1; cbufid = 1;
} }
@ -571,10 +575,18 @@ void TextureCache::CopyRenderTargetToTexture(u32 address, bool bFromZBuffer,
case 3: // RA8 case 3: // RA8
colmat[0] = colmat[4] = colmat[8] = colmat[15] = 1; colmat[0] = colmat[4] = colmat[8] = colmat[15] = 1;
cbufid = 3; cbufid = 3;
if(bpmem.zcontrol.pixel_format != PIXELFMT_RGBA6_Z24)
{
fConstAdd[3] = 1;
}
break; break;
case 7: // A8 case 7: // A8
colmat[3] = colmat[7] = colmat[11] = colmat[15] = 1; 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; cbufid = 4;
break; break;
@ -608,6 +620,10 @@ void TextureCache::CopyRenderTargetToTexture(u32 address, bool bFromZBuffer,
case 6: // RGBA8 case 6: // RGBA8
colmat[0] = colmat[5] = colmat[10] = colmat[15] = 1; colmat[0] = colmat[5] = colmat[10] = colmat[15] = 1;
cbufid = 10; cbufid = 10;
if(bpmem.zcontrol.pixel_format != PIXELFMT_RGBA6_Z24)
{
fConstAdd[3] = 1;
}
break; break;
default: default:
@ -618,6 +634,8 @@ void TextureCache::CopyRenderTargetToTexture(u32 address, bool bFromZBuffer,
} }
} }
const unsigned int tex_w = (abs(source_rect.GetWidth()) >> (int)bScaleByHalf); const unsigned int tex_w = (abs(source_rect.GetWidth()) >> (int)bScaleByHalf);
const unsigned int tex_h = (abs(source_rect.GetHeight()) >> (int)bScaleByHalf); const unsigned int tex_h = (abs(source_rect.GetHeight()) >> (int)bScaleByHalf);

View File

@ -155,4 +155,26 @@ typedef enum
API_NONE API_NONE
} API_TYPE; } API_TYPE;
inline u32 RGBA8ToRGBA6ToRGBA8(u32 src)
{
u32 color = src;
color &= 0xFCFCFCFC;
color |= (color >> 6) & 0x03030303;
return color;
}
inline u32 RGBA8ToRGB565ToRGB8(u32 src)
{
u32 color = src;
u32 dstr5 = (color & 0xFF0000) >> 19;
u32 dstg6 = (color & 0xFF00) >> 10;
u32 dstb5 = (color & 0xFF) >> 3;
u32 dstr8 = (dstr5 << 3) | (dstr5 >> 2);
u32 dstg8 = (dstg6 << 2) | (dstg6 >> 4);
u32 dstb8 = (dstb5 << 3) | (dstb5 >> 2);
color = (dstr8 << 16) | (dstg8 << 8) | dstb8;
return color;
}
#endif // _VIDEOCOMMON_H #endif // _VIDEOCOMMON_H