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; }