Merge pull request #7699 from unknownbrackets/d3d9

d3d9: Clear the stencil/alpha on buffer reformat (matching GLES)
This commit is contained in:
Henrik Rydgård 2015-04-19 10:23:15 +02:00
commit 9f7554c08f
2 changed files with 61 additions and 6 deletions

View File

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

View File

@ -70,6 +70,7 @@ public:
void Resized();
void DeviceLost();
void CopyDisplayToOutput();
void ReformatFramebufferFrom(VirtualFramebuffer *vfb, GEBufferFormat old);
void BlitFramebufferDepth(VirtualFramebuffer *src, VirtualFramebuffer *dst);