dx9, dx11: video shift support

Shift the framebuffer according to VO_STARTX and VO_STARTY.
Issue #594
lr: draw overlay and manage shifting in dx11 context
This commit is contained in:
Flyinghead 2023-03-27 16:41:59 +02:00
parent b94200233d
commit caec338d25
5 changed files with 118 additions and 10 deletions

View File

@ -462,10 +462,9 @@ bool DX11Renderer::Render()
DrawOSD(false);
theDX11Context.setFrameRendered();
#else
theDX11Context.drawOverlay(width, height);
ID3D11RenderTargetView *nullView = nullptr;
deviceContext->OMSetRenderTargets(1, &nullView, nullptr);
deviceContext->PSSetShaderResources(0, 1, &fbTextureView.get());
theDX11Context.presentFrame(fbTextureView, width, height);
#endif
frameRendered = true;
frameRenderedOnce = true;
@ -490,11 +489,18 @@ void DX11Renderer::displayFramebuffer()
VO_BORDER_COL.getRGBColor(colors);
colors[3] = 1.f;
deviceContext->ClearRenderTargetView(theDX11Context.getRenderTarget(), colors);
float shiftX, shiftY;
getVideoShift(shiftX, shiftY);
shiftX *= 2.f / width;
shiftY *= -2.f / height;
int outwidth = settings.display.width;
int outheight = settings.display.height;
float renderAR = aspectRatio;
if (config::Rotate90) {
std::swap(outwidth, outheight);
std::swap(shiftX, shiftY);
renderAR = 1 / renderAR;
}
float screenAR = (float)outwidth / outheight;
@ -515,6 +521,9 @@ void DX11Renderer::displayFramebuffer()
w *= 2.f / outwidth;
y = y * 2.f / outheight - 1.f;
h *= 2.f / outheight;
// Shift
x += shiftX;
y += shiftY;
deviceContext->OMSetBlendState(blendStates.getState(false), nullptr, 0xffffffff);
quad->draw(fbTextureView, samplers->getSampler(config::TextureFiltering != 1), nullptr, x, y, w, h, config::Rotate90);
#endif
@ -953,11 +962,9 @@ void DX11Renderer::RenderFramebuffer(const FramebufferInfo& info)
DrawOSD(false);
theDX11Context.setFrameRendered();
#else
// FIXME won't look great on a 1x1 texture in case video output is disabled
theDX11Context.drawOverlay(this->width, this->height);
ID3D11RenderTargetView *nullView = nullptr;
deviceContext->OMSetRenderTargets(1, &nullView, nullptr);
deviceContext->PSSetShaderResources(0, 1, &dcfbTextureView.get());
theDX11Context.presentFrame(dcfbTextureView, width, height);
#endif
frameRendered = true;
frameRenderedOnce = true;

View File

@ -20,6 +20,7 @@
#include "dx11context_lr.h"
#include <dxgi1_2.h>
#include "rend/osd.h"
#include "rend/transform_matrix.h"
DX11Context theDX11Context;
@ -53,6 +54,9 @@ bool DX11Context::init(ID3D11Device *device, ID3D11DeviceContext *deviceContext,
shaders.init(pDevice, D3DCompile);
overlay.init(pDevice, pDeviceContext, &shaders, &samplers);
quad = std::make_unique<Quad>();
quad->init(pDevice, pDeviceContext, &shaders);
bool success = checkTextureSupport();
if (!success)
term();
@ -63,6 +67,11 @@ void DX11Context::term()
{
NOTICE_LOG(RENDERER, "DX11 Context terminating");
GraphicsContext::instance = nullptr;
blendStates.term();
quad.reset();
textureView.reset();
renderTargetView.reset();
texture.reset();
overlay.term();
samplers.term();
shaders.term();
@ -81,4 +90,77 @@ void DX11Context::drawOverlay(int width, int height)
overlay.draw(width, height, true, true);
}
ComPtr<ID3D11RenderTargetView>& DX11Context::getRenderTarget(int width, int height)
{
if (width != renderTargetWidth || height != renderTargetHeight || !renderTargetView)
{
renderTargetWidth = width;
renderTargetHeight = height;
texture.reset();
renderTargetView.reset();
D3D11_TEXTURE2D_DESC desc{};
desc.Width = width;
desc.Height = height;
desc.ArraySize = 1;
desc.SampleDesc.Count = 1;
desc.Usage = D3D11_USAGE_DEFAULT;
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
desc.MipLevels = 1;
HRESULT hr = pDevice->CreateTexture2D(&desc, nullptr, &texture.get());
if (FAILED(hr))
WARN_LOG(RENDERER, "Framebuffer texture(%d x %d) creation failed: %x", width, height, hr);
D3D11_SHADER_RESOURCE_VIEW_DESC viewDesc{};
viewDesc.Format = desc.Format;
viewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
viewDesc.Texture2D.MipLevels = 1;
hr = pDevice->CreateShaderResourceView(texture, &viewDesc, &textureView.get());
if (FAILED(hr))
WARN_LOG(RENDERER, "DC Framebuffer texture view creation failed");
hr = pDevice->CreateRenderTargetView(texture, nullptr, &renderTargetView.get());
if (FAILED(hr))
WARN_LOG(RENDERER, "Framebuffer render target creation failed");
FLOAT black[4] = { 0.f, 0.f, 0.f, 0.f };
pDeviceContext->ClearRenderTargetView(renderTargetView, black);
}
return renderTargetView;
}
void DX11Context::presentFrame(ComPtr<ID3D11ShaderResourceView>& textureView, int width, int height)
{
ComPtr<ID3D11RenderTargetView> renderTarget = getRenderTarget(width, height);
pDeviceContext->OMSetRenderTargets(1, &renderTarget.get(), nullptr);
D3D11_VIEWPORT vp{};
vp.Width = (FLOAT)width;
vp.Height = (FLOAT)height;
vp.MinDepth = 0.f;
vp.MaxDepth = 1.f;
pDeviceContext->RSSetViewports(1, &vp);
const D3D11_RECT r = { 0, 0, width, height };
pDeviceContext->RSSetScissorRects(1, &r);
float colors[4];
VO_BORDER_COL.getRGBColor(colors);
colors[3] = 1.f;
pDeviceContext->ClearRenderTargetView(renderTarget, colors);
float shiftX, shiftY;
getVideoShift(shiftX, shiftY);
shiftX *= 2.f / width;
shiftY *= -2.f / height;
pDeviceContext->OMSetBlendState(blendStates.getState(false), nullptr, 0xffffffff);
quad->draw(textureView, samplers.getSampler(false), nullptr, -1 + shiftX, -1 + shiftY, 2, 2, false);
drawOverlay(width, height);
ID3D11RenderTargetView *nullView = nullptr;
pDeviceContext->OMSetRenderTargets(1, &nullView, nullptr);
pDeviceContext->PSSetShaderResources(0, 1, &this->textureView.get());
}
#endif

View File

@ -27,6 +27,8 @@
#include "dx11_shaders.h"
#include "dx11_texture.h"
#include "wsi/context.h"
#include "dx11_renderstate.h"
#include "dx11_quad.h"
class DX11Context : public GraphicsContext
{
@ -37,6 +39,7 @@ public:
const ComPtr<ID3D11Device>& getDevice() const { return pDevice; }
const ComPtr<ID3D11DeviceContext>& getDeviceContext() const { return pDeviceContext; }
const pD3DCompile getCompiler() const { return this->D3DCompile; }
void presentFrame(ComPtr<ID3D11ShaderResourceView>& textureView, int width, int height);
std::string getDriverName() override { return ""; }
std::string getDriverVersion() override { return ""; }
@ -65,6 +68,7 @@ public:
private:
bool checkTextureSupport();
ComPtr<ID3D11RenderTargetView>& getRenderTarget(int width, int height);
ComPtr<ID3D11Device> pDevice;
ComPtr<ID3D11DeviceContext> pDeviceContext;
@ -74,6 +78,14 @@ private:
DX11Shaders shaders;
Samplers samplers;
DX11Overlay overlay;
ComPtr<ID3D11Texture2D> texture;
ComPtr<ID3D11ShaderResourceView> textureView;
ComPtr<ID3D11RenderTargetView> renderTargetView;
int renderTargetWidth = 0;
int renderTargetHeight = 0;
BlendStates blendStates;
std::unique_ptr<Quad> quad;
D3D_FEATURE_LEVEL featureLevel{};
bool supportedTexFormats[5] {}; // indexed by TextureType enum

View File

@ -671,10 +671,9 @@ struct DX11OITRenderer : public DX11Renderer
DrawOSD(false);
theDX11Context.setFrameRendered();
#else
theDX11Context.drawOverlay(width, height);
ID3D11RenderTargetView *nullView = nullptr;
deviceContext->OMSetRenderTargets(1, &nullView, nullptr);
deviceContext->PSSetShaderResources(0, 1, &fbTextureView.get());
theDX11Context.presentFrame(fbTextureView, width, height);
#endif
frameRendered = true;
frameRenderedOnce = true;

View File

@ -1147,7 +1147,9 @@ void D3DRenderer::displayFramebuffer()
else
dx = (int)roundf(settings.display.width * (1 - aspectRatio / screenAR) / 2.f);
if (!config::Rotate90)
float shiftX, shiftY;
getVideoShift(shiftX, shiftY);
if (!config::Rotate90 && shiftX == 0 && shiftY == 0)
{
RECT rs { 0, 0, (long)width, (long)height };
RECT rd { dx, dy, settings.display.width - dx, settings.display.height - dy };
@ -1166,8 +1168,9 @@ void D3DRenderer::displayFramebuffer()
device->SetSamplerState(0, D3DSAMP_MAGFILTER, config::TextureFiltering == 1 ? D3DTEXF_POINT : D3DTEXF_LINEAR);
glm::mat4 identity = glm::identity<glm::mat4>();
glm::mat4 projection = glm::translate(glm::vec3(-1.f / settings.display.width, 1.f / settings.display.height, 0))
* glm::rotate((float)M_PI_2, glm::vec3(0, 0, 1));
glm::mat4 projection = glm::translate(glm::vec3(-1.f / settings.display.width, 1.f / settings.display.height, 0));
if (config::Rotate90)
projection *= glm::rotate((float)M_PI_2, glm::vec3(0, 0, 1));
device->SetTransform(D3DTS_WORLD, (const D3DMATRIX *)&identity[0][0]);
device->SetTransform(D3DTS_VIEW, (const D3DMATRIX *)&identity[0][0]);
@ -1189,6 +1192,11 @@ void D3DRenderer::displayFramebuffer()
1, 1, 0.5f, 1, 0,
1, -1, 0.5f, 1, 1,
};
coords[0] = coords[5] = -1.f + shiftX * 2.f / width;
coords[10] = coords[15] = coords[0] + 2;
coords[1] = coords[11] = 1.f - shiftY * 2.f / height;
coords[6] = coords[16] = coords[1] - 2;
device->SetTexture(0, framebufferTexture);
device->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, coords, sizeof(float) * 5);
}