From f3336a84a16e93dfd20595201a07fc9ba20a12b5 Mon Sep 17 00:00:00 2001 From: Rodolfo Osvaldo Bogado Date: Mon, 27 Dec 2010 03:09:11 +0000 Subject: [PATCH] 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 --- Source/Core/VideoCommon/Src/BPFunctions.cpp | 75 ++++++------------- .../Core/VideoCommon/Src/TextureCacheBase.cpp | 18 +++++ Source/Core/VideoCommon/Src/VideoCommon.h | 22 ++++++ 3 files changed, 61 insertions(+), 54 deletions(-) diff --git a/Source/Core/VideoCommon/Src/BPFunctions.cpp b/Source/Core/VideoCommon/Src/BPFunctions.cpp index 8a6d9e7705..64d486eea7 100644 --- a/Source/Core/VideoCommon/Src/BPFunctions.cpp +++ b/Source/Core/VideoCommon/Src/BPFunctions.cpp @@ -25,7 +25,7 @@ bool textureChanged[8]; const bool renderFog = false; - +int prev_pix_format = -1; 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: - 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 (and possibly others?)), the native HW assumes that the EFB format is RGB8 when clearing. - Thus the RGBA6 values get overwritten with plain RGB8 data without any kind of conversion. (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) + - 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 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) - - more tricky, doing some bit magic here to properly reinterpret the data - (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 + (3) - when the pixel format changes: + - call ClearScreen using the correct alpha format for the previus pixel format + + */ 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 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_RGBA6_Z24: - if (colorEnable && PE_copy.tp_realFormat() == GX_TF_Z24X8) // (3): alpha update forced - alphaEnable = true; - break; - case PIXELFMT_RGB8_Z24: case PIXELFMT_RGB565_Z16: - alphaEnable = false; + alphaEnable = true; + color |= (prev_pix_format == PIXELFMT_RGBA6_Z24)? 0x0 : 0xFF000000;//(3) break; case PIXELFMT_Z24: alphaEnable = colorEnable = false; break; - - default: - // TODO? + default: break; } if (colorEnable || alphaEnable || zEnable) { - u32 color = (bpmem.clearcolorAR << 16) | bpmem.clearcolorGB; - u32 z = bpmem.clearZValue; 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? - 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; - } + color = RGBA8ToRGBA6ToRGBA8(color); } else if (bpmem.zcontrol.pixel_format == PIXELFMT_RGB565_Z16) { - z >>= 8; - 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; + color = RGBA8ToRGB565ToRGB8(color); } g_renderer->ClearScreen(rc, colorEnable, alphaEnable, zEnable, color, z); } + prev_pix_format = bpmem.zcontrol.pixel_format; } + void RestoreRenderState(const BPCmd &bp) { g_renderer->RestoreAPIState(); diff --git a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp index fffde7b7b2..bd7023b01e 100644 --- a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp @@ -545,6 +545,10 @@ 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; } @@ -571,10 +575,18 @@ 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; @@ -608,6 +620,10 @@ 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: @@ -617,6 +633,8 @@ 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); diff --git a/Source/Core/VideoCommon/Src/VideoCommon.h b/Source/Core/VideoCommon/Src/VideoCommon.h index 3dddf0420b..521dd94877 100644 --- a/Source/Core/VideoCommon/Src/VideoCommon.h +++ b/Source/Core/VideoCommon/Src/VideoCommon.h @@ -155,4 +155,26 @@ typedef enum API_NONE } 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