From 649fd3d95b01b06252ad2f116add708795f59cf6 Mon Sep 17 00:00:00 2001 From: TheCow Date: Wed, 26 Dec 2012 10:02:03 -0500 Subject: [PATCH] D3D11: Set proper border color for Real XFB YUY2 texture. Fixes issue 6483. --- .../Plugin_VideoDX11/Src/Television.cpp | 33 ++++++++++++++++++- .../Plugins/Plugin_VideoDX11/Src/Television.h | 2 ++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/Source/Plugins/Plugin_VideoDX11/Src/Television.cpp b/Source/Plugins/Plugin_VideoDX11/Src/Television.cpp index e1feec595b..daabf6d8b3 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/Television.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/Television.cpp @@ -10,6 +10,7 @@ #include "D3DUtil.h" #include "VertexShaderCache.h" #include "HW/Memmap.h" +#include namespace DX11 { @@ -67,10 +68,22 @@ void Television::Init() // Create YUYV texture for real XFB mode + + // Initialize the texture with YCbCr black + // + // Some games use narrower XFB widths (Nintendo titles are fond of 608), + // so the sampler's BorderColor won't cover the right side + // (see sampler state below) + const unsigned int MAX_XFB_SIZE = 2*(MAX_XFB_WIDTH) * MAX_XFB_HEIGHT; + std::vector fill(MAX_XFB_SIZE); + for (size_t i = 0; i < MAX_XFB_SIZE / sizeof(u32); ++i) + reinterpret_cast(fill.data())[i] = 0x80108010; + D3D11_SUBRESOURCE_DATA srd = { fill.data(), 2*(MAX_XFB_WIDTH), 0 }; + // This texture format is designed for YUYV data. D3D11_TEXTURE2D_DESC t2dd = CD3D11_TEXTURE2D_DESC( DXGI_FORMAT_G8R8_G8B8_UNORM, MAX_XFB_WIDTH, MAX_XFB_HEIGHT, 1, 1); - hr = D3D::device->CreateTexture2D(&t2dd, NULL, &m_yuyvTexture); + hr = D3D::device->CreateTexture2D(&t2dd, &srd, &m_yuyvTexture); CHECK(SUCCEEDED(hr), "create tv yuyv texture"); D3D::SetDebugObjectName(m_yuyvTexture, "tv yuyv texture"); @@ -88,6 +101,21 @@ void Television::Init() m_pShader = D3D::CompileAndCreatePixelShader(YUYV_DECODER_PS, sizeof(YUYV_DECODER_PS)); CHECK(m_pShader != NULL, "compile and create yuyv decoder pixel shader"); D3D::SetDebugObjectName(m_pShader, "yuyv decoder pixel shader"); + + // Create sampler state and set border color + // + // The default sampler border color of { 0.f, 0.f, 0.f, 0.f } + // creates a green border around the image - see issue 6483 + // (remember, the XFB is being interpreted as YUYV, and 0,0,0,0 + // is actually two green pixels in YUYV - black should be 16,128,16,128, + // but we reverse the order to match DXGI_FORMAT_G8R8_G8B8_UNORM's ordering) + float border[4] = { 128.0f/255.0f, 16.0f/255.0f, 128.0f/255.0f, 16.0f/255.0f }; + D3D11_SAMPLER_DESC samDesc = CD3D11_SAMPLER_DESC(D3D11_FILTER_MIN_MAG_MIP_LINEAR, + D3D11_TEXTURE_ADDRESS_BORDER, D3D11_TEXTURE_ADDRESS_BORDER, D3D11_TEXTURE_ADDRESS_BORDER, + 0.f, 1, D3D11_COMPARISON_ALWAYS, border, 0.f, 0.f); + hr = D3D::device->CreateSamplerState(&samDesc, &m_samplerState); + CHECK(SUCCEEDED(hr), "create yuyv decoder sampler state"); + D3D::SetDebugObjectName(m_samplerState, "yuyv decoder sampler state"); } void Television::Shutdown() @@ -95,6 +123,7 @@ void Television::Shutdown() SAFE_RELEASE(m_pShader); SAFE_RELEASE(m_yuyvTextureSRV); SAFE_RELEASE(m_yuyvTexture); + SAFE_RELEASE(m_samplerState); } void Television::Submit(u32 xfbAddr, u32 width, u32 height) @@ -121,6 +150,8 @@ void Television::Render() MathUtil::Rectangle sourceRc(0.f, 0.f, float(m_curWidth), float(m_curHeight)); MathUtil::Rectangle destRc(-1.f, 1.f, 1.f, -1.f); + D3D::context->PSSetSamplers(0, 1, &m_samplerState); + D3D::drawShadedTexSubQuad( m_yuyvTextureSRV, &sourceRc, MAX_XFB_WIDTH, MAX_XFB_HEIGHT, diff --git a/Source/Plugins/Plugin_VideoDX11/Src/Television.h b/Source/Plugins/Plugin_VideoDX11/Src/Television.h index 163d9131a6..a33ae7112d 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/Television.h +++ b/Source/Plugins/Plugin_VideoDX11/Src/Television.h @@ -10,6 +10,7 @@ struct ID3D11Texture2D; struct ID3D11ShaderResourceView; struct ID3D11PixelShader; +struct ID3D11SamplerState; namespace DX11 { @@ -44,6 +45,7 @@ private: ID3D11Texture2D* m_yuyvTexture; ID3D11ShaderResourceView* m_yuyvTextureSRV; ID3D11PixelShader* m_pShader; + ID3D11SamplerState* m_samplerState; };