diff --git a/GPU/Directx9/FramebufferDX9.cpp b/GPU/Directx9/FramebufferDX9.cpp index ad1b86398..335852299 100644 --- a/GPU/Directx9/FramebufferDX9.cpp +++ b/GPU/Directx9/FramebufferDX9.cpp @@ -81,7 +81,7 @@ namespace DX9 { dxstate.colorMask.set(true, true, true, true); dxstate.stencilFunc.set(D3DCMP_ALWAYS, 0, 0); dxstate.stencilMask.set(0xFF); - pD3Ddevice->Clear(0, NULL, D3DCLEAR_STENCIL|D3DCLEAR_TARGET |D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 0, 0); + pD3Ddevice->Clear(0, NULL, D3DCLEAR_STENCIL|D3DCLEAR_TARGET |D3DCLEAR_ZBUFFER, D3DCOLOR_ARGB(0, 0, 0, 0), 0, 0); } void FramebufferManagerDX9::ClearDepthBuffer() { @@ -89,7 +89,7 @@ namespace DX9 { dxstate.depthWrite.set(TRUE); dxstate.colorMask.set(false, false, false, false); dxstate.stencilFunc.set(D3DCMP_NEVER, 0, 0); - pD3Ddevice->Clear(0, NULL, D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 0, 0); + pD3Ddevice->Clear(0, NULL, D3DCLEAR_ZBUFFER, D3DCOLOR_ARGB(0, 0, 0, 0), 0, 0); } void FramebufferManagerDX9::DisableState() { @@ -435,8 +435,7 @@ namespace DX9 { } if (vfb->drawnFormat != vfb->format) { // TODO: Might ultimately combine this with the resize step in DoSetRenderFrameBuffer(). - // TODO - //ReformatFramebufferFrom(vfb, vfb->drawnFormat); + ReformatFramebufferFrom(vfb, vfb->drawnFormat); } // ugly... @@ -453,8 +452,7 @@ namespace DX9 { if (vfbFormatChanged) { textureCache_->NotifyFramebuffer(vfb->fb_address, vfb, NOTIFY_FB_UPDATED); if (vfb->drawnFormat != vfb->format) { - // TODO - //ReformatFramebufferFrom(vfb, vfb->drawnFormat); + ReformatFramebufferFrom(vfb, vfb->drawnFormat); } } @@ -468,6 +466,62 @@ namespace DX9 { } } + void FramebufferManagerDX9::ReformatFramebufferFrom(VirtualFramebuffer *vfb, GEBufferFormat old) { + if (!useBufferedRendering_ || !vfb->fbo) { + return; + } + + fbo_bind_as_render_target(vfb->fbo); + + // Technically, we should at this point re-interpret the bytes of the old format to the new. + // That might get tricky, and could cause unnecessary slowness in some games. + // For now, we just clear alpha/stencil from 565, which fixes shadow issues in Kingdom Hearts. + // (it uses 565 to write zeros to the buffer, than 4444 to actually render the shadow.) + // + // The best way to do this may ultimately be to create a new FBO (combine with any resize?) + // and blit with a shader to that, then replace the FBO on vfb. Stencil would still be complex + // to exactly reproduce in 4444 and 8888 formats. + + if (old == GE_FORMAT_565) { + dxstate.scissorTest.disable(); + dxstate.depthWrite.set(FALSE); + dxstate.colorMask.set(false, false, false, true); + dxstate.stencilFunc.set(D3DCMP_ALWAYS, 0, 0); + dxstate.stencilMask.set(0xFF); + + float coord[20] = { + -1.0f,-1.0f,0, 0,0, + 1.0f,-1.0f,0, 0,0, + 1.0f,1.0f,0, 0,0, + -1.0f,1.0f,0, 0,0, + }; + + dxstate.cullMode.set(false, false); + pD3Ddevice->SetVertexDeclaration(pFramebufferVertexDecl); + pD3Ddevice->SetPixelShader(pFramebufferPixelShader); + pD3Ddevice->SetVertexShader(pFramebufferVertexShader); + shaderManager_->DirtyLastShader(); + pD3Ddevice->SetTexture(0, nullptr); + + D3DVIEWPORT9 vp; + vp.MinZ = 0; + vp.MaxZ = 1; + vp.X = 0; + vp.Y = 0; + vp.Width = vfb->renderWidth; + vp.Height = vfb->renderHeight; + pD3Ddevice->SetViewport(&vp); + + // This should clear stencil and alpha without changing the other colors. + HRESULT hr = pD3Ddevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, coord, 5 * sizeof(float)); + if (FAILED(hr)) { + ERROR_LOG_REPORT(G3D, "ReformatFramebufferFrom() failed: %08x", hr); + } + } + + RebindFramebuffer(); + } + void FramebufferManagerDX9::BlitFramebufferDepth(VirtualFramebuffer *src, VirtualFramebuffer *dst) { if (!src->fbo || !dst->fbo || !useBufferedRendering_) { return; diff --git a/GPU/Directx9/FramebufferDX9.h b/GPU/Directx9/FramebufferDX9.h index c27a14987..9dc34f95b 100644 --- a/GPU/Directx9/FramebufferDX9.h +++ b/GPU/Directx9/FramebufferDX9.h @@ -70,6 +70,7 @@ public: void Resized(); void DeviceLost(); void CopyDisplayToOutput(); + void ReformatFramebufferFrom(VirtualFramebuffer *vfb, GEBufferFormat old); void BlitFramebufferDepth(VirtualFramebuffer *src, VirtualFramebuffer *dst);