From 6e8df50fffeb381523d40aeae31afa4f60df46a3 Mon Sep 17 00:00:00 2001 From: NeoBrainX Date: Mon, 27 Dec 2010 18:09:03 +0000 Subject: [PATCH] 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 --- Source/Core/VideoCommon/Src/BPFunctions.cpp | 50 ++++++------------- .../Core/VideoCommon/Src/TextureCacheBase.cpp | 20 +------- Source/Core/VideoCommon/Src/VideoCommon.h | 8 ++- .../Plugins/Plugin_VideoDX11/Src/Render.cpp | 6 +-- Source/Plugins/Plugin_VideoDX9/Src/Render.cpp | 8 +-- Source/Plugins/Plugin_VideoOGL/Src/Render.cpp | 20 +++----- 6 files changed, 36 insertions(+), 76 deletions(-) diff --git a/Source/Core/VideoCommon/Src/BPFunctions.cpp b/Source/Core/VideoCommon/Src/BPFunctions.cpp index 64d486eea7..df329fbeb5 100644 --- a/Source/Core/VideoCommon/Src/BPFunctions.cpp +++ b/Source/Core/VideoCommon/Src/BPFunctions.cpp @@ -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; } diff --git a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp index bd7023b01e..551d87eb11 100644 --- a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp @@ -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(); -} +} \ No newline at end of file diff --git a/Source/Core/VideoCommon/Src/VideoCommon.h b/Source/Core/VideoCommon/Src/VideoCommon.h index 521dd94877..ab79bdcbef 100644 --- a/Source/Core/VideoCommon/Src/VideoCommon.h +++ b/Source/Core/VideoCommon/Src/VideoCommon.h @@ -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 diff --git a/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp b/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp index 3391d1d446..f7d435fd8a 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp @@ -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) { diff --git a/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp b/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp index 2c8558cb87..fccc66cd42 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp @@ -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; diff --git a/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp b/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp index 454c94ad71..f246ec02b7 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp @@ -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; }