mirror of
https://github.com/moonlight-stream/moonlight-qt.git
synced 2025-07-03 16:25:54 +00:00
Use a separate texture for rendering to avoid blending in the alignment padding
Fixes #885
This commit is contained in:
parent
3dcab90752
commit
a6fccf93d1
@ -87,6 +87,7 @@ D3D11VARenderer::D3D11VARenderer(int decoderSelectionPass)
|
|||||||
m_VideoBt601LimPixelShader(nullptr),
|
m_VideoBt601LimPixelShader(nullptr),
|
||||||
m_VideoBt2020LimPixelShader(nullptr),
|
m_VideoBt2020LimPixelShader(nullptr),
|
||||||
m_VideoVertexBuffer(nullptr),
|
m_VideoVertexBuffer(nullptr),
|
||||||
|
m_VideoTexture(nullptr),
|
||||||
m_OverlayLock(0),
|
m_OverlayLock(0),
|
||||||
m_OverlayPixelShader(nullptr),
|
m_OverlayPixelShader(nullptr),
|
||||||
m_HwDeviceContext(nullptr),
|
m_HwDeviceContext(nullptr),
|
||||||
@ -114,10 +115,11 @@ D3D11VARenderer::~D3D11VARenderer()
|
|||||||
SAFE_COM_RELEASE(m_VideoGenericPixelShader);
|
SAFE_COM_RELEASE(m_VideoGenericPixelShader);
|
||||||
|
|
||||||
for (int i = 0; i < ARRAYSIZE(m_VideoTextureResourceViews); i++) {
|
for (int i = 0; i < ARRAYSIZE(m_VideoTextureResourceViews); i++) {
|
||||||
SAFE_COM_RELEASE(m_VideoTextureResourceViews[i][0]);
|
SAFE_COM_RELEASE(m_VideoTextureResourceViews[i]);
|
||||||
SAFE_COM_RELEASE(m_VideoTextureResourceViews[i][1]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SAFE_COM_RELEASE(m_VideoTexture);
|
||||||
|
|
||||||
for (int i = 0; i < ARRAYSIZE(m_OverlayVertexBuffers); i++) {
|
for (int i = 0; i < ARRAYSIZE(m_OverlayVertexBuffers); i++) {
|
||||||
SAFE_COM_RELEASE(m_OverlayVertexBuffers[i]);
|
SAFE_COM_RELEASE(m_OverlayVertexBuffers[i]);
|
||||||
}
|
}
|
||||||
@ -459,12 +461,11 @@ bool D3D11VARenderer::initialize(PDECODER_PARAMETERS params)
|
|||||||
framesContext->height = FFALIGN(params->height, m_TextureAlignment);
|
framesContext->height = FFALIGN(params->height, m_TextureAlignment);
|
||||||
|
|
||||||
// We can have up to 16 reference frames plus a working surface
|
// We can have up to 16 reference frames plus a working surface
|
||||||
framesContext->initial_pool_size = DECODER_BUFFER_POOL_SIZE;
|
framesContext->initial_pool_size = 17;
|
||||||
|
|
||||||
AVD3D11VAFramesContext* d3d11vaFramesContext = (AVD3D11VAFramesContext*)framesContext->hwctx;
|
AVD3D11VAFramesContext* d3d11vaFramesContext = (AVD3D11VAFramesContext*)framesContext->hwctx;
|
||||||
|
|
||||||
// We need to override the default D3D11VA bind flags to bind the textures as a shader resources
|
d3d11vaFramesContext->BindFlags = D3D11_BIND_DECODER;
|
||||||
d3d11vaFramesContext->BindFlags = D3D11_BIND_DECODER | D3D11_BIND_SHADER_RESOURCE;
|
|
||||||
|
|
||||||
int err = av_hwframe_ctx_init(m_HwFramesContext);
|
int err = av_hwframe_ctx_init(m_HwFramesContext);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
@ -474,8 +475,8 @@ bool D3D11VARenderer::initialize(PDECODER_PARAMETERS params)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create SRVs for all textures in the decoder pool
|
// Create our video texture and SRVs
|
||||||
if (!setupTexturePoolViews(d3d11vaFramesContext)) {
|
if (!setupVideoTexture()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -763,22 +764,21 @@ void D3D11VARenderer::renderVideo(AVFrame* frame)
|
|||||||
UINT offset = 0;
|
UINT offset = 0;
|
||||||
m_DeviceContext->IASetVertexBuffers(0, 1, &m_VideoVertexBuffer, &stride, &offset);
|
m_DeviceContext->IASetVertexBuffers(0, 1, &m_VideoVertexBuffer, &stride, &offset);
|
||||||
|
|
||||||
// Our indexing logic depends on a direct mapping into m_VideoTextureResourceViews
|
// Copy this frame (minus alignment padding) into our video texture
|
||||||
// based on the texture index provided by FFmpeg.
|
D3D11_BOX srcBox;
|
||||||
UINT textureIndex = (uintptr_t)frame->data[1];
|
srcBox.left = 0;
|
||||||
SDL_assert(textureIndex < DECODER_BUFFER_POOL_SIZE);
|
srcBox.top = 0;
|
||||||
if (textureIndex >= DECODER_BUFFER_POOL_SIZE) {
|
srcBox.right = m_DecoderParams.width;
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
srcBox.bottom = m_DecoderParams.height;
|
||||||
"Unexpected texture index: %u",
|
srcBox.front = 0;
|
||||||
textureIndex);
|
srcBox.back = 1;
|
||||||
return;
|
m_DeviceContext->CopySubresourceRegion(m_VideoTexture, 0, 0, 0, 0, (ID3D11Resource*)frame->data[0], (int)(intptr_t)frame->data[1], &srcBox);
|
||||||
}
|
|
||||||
|
|
||||||
// Bind our CSC shader (and constant buffer, if required)
|
// Bind our CSC shader (and constant buffer, if required)
|
||||||
bindColorConversion(frame);
|
bindColorConversion(frame);
|
||||||
|
|
||||||
// Bind SRVs for this frame
|
// Bind SRVs for this frame
|
||||||
m_DeviceContext->PSSetShaderResources(0, 2, m_VideoTextureResourceViews[textureIndex]);
|
m_DeviceContext->PSSetShaderResources(0, 2, m_VideoTextureResourceViews);
|
||||||
|
|
||||||
// Draw the video
|
// Draw the video
|
||||||
m_DeviceContext->DrawIndexed(6, 0, 0);
|
m_DeviceContext->DrawIndexed(6, 0, 0);
|
||||||
@ -1238,17 +1238,12 @@ bool D3D11VARenderer::setupRenderingResources()
|
|||||||
SDL_FRect renderRect;
|
SDL_FRect renderRect;
|
||||||
StreamUtils::screenSpaceToNormalizedDeviceCoords(&dst, &renderRect, m_DisplayWidth, m_DisplayHeight);
|
StreamUtils::screenSpaceToNormalizedDeviceCoords(&dst, &renderRect, m_DisplayWidth, m_DisplayHeight);
|
||||||
|
|
||||||
// Don't sample from the alignment padding area since that's not part of the video
|
|
||||||
SDL_assert(m_TextureAlignment != 0);
|
|
||||||
float uMax = (float)m_DecoderParams.width / FFALIGN(m_DecoderParams.width, m_TextureAlignment);
|
|
||||||
float vMax = (float)m_DecoderParams.height / FFALIGN(m_DecoderParams.height, m_TextureAlignment);
|
|
||||||
|
|
||||||
VERTEX verts[] =
|
VERTEX verts[] =
|
||||||
{
|
{
|
||||||
{renderRect.x, renderRect.y, 0, vMax},
|
{renderRect.x, renderRect.y, 0, 1.0f},
|
||||||
{renderRect.x, renderRect.y+renderRect.h, 0, 0},
|
{renderRect.x, renderRect.y+renderRect.h, 0, 0},
|
||||||
{renderRect.x+renderRect.w, renderRect.y, uMax, vMax},
|
{renderRect.x+renderRect.w, renderRect.y, 1.0f, 1.0f},
|
||||||
{renderRect.x+renderRect.w, renderRect.y+renderRect.h, uMax, 0},
|
{renderRect.x+renderRect.w, renderRect.y+renderRect.h, 1.0f, 0},
|
||||||
};
|
};
|
||||||
|
|
||||||
D3D11_BUFFER_DESC vbDesc = {};
|
D3D11_BUFFER_DESC vbDesc = {};
|
||||||
@ -1316,27 +1311,41 @@ bool D3D11VARenderer::setupRenderingResources()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool D3D11VARenderer::setupTexturePoolViews(AVD3D11VAFramesContext* frameContext)
|
bool D3D11VARenderer::setupVideoTexture()
|
||||||
{
|
{
|
||||||
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
|
|
||||||
srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
|
|
||||||
srvDesc.Texture2DArray.MostDetailedMip = 0;
|
|
||||||
srvDesc.Texture2DArray.MipLevels = 1;
|
|
||||||
srvDesc.Texture2DArray.ArraySize = 1;
|
|
||||||
|
|
||||||
// Create luminance and chrominance SRVs for each texture in the pool
|
|
||||||
for (int i = 0; i < DECODER_BUFFER_POOL_SIZE; i++) {
|
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
D3D11_TEXTURE2D_DESC texDesc = {};
|
||||||
|
|
||||||
// Our rendering logic depends on the texture index working to map into our SRV array
|
texDesc.Width = m_DecoderParams.width;
|
||||||
SDL_assert(i == frameContext->texture_infos[i].index);
|
texDesc.Height = m_DecoderParams.height;
|
||||||
|
texDesc.MipLevels = 1;
|
||||||
|
texDesc.ArraySize = 1;
|
||||||
|
texDesc.Format = (m_DecoderParams.videoFormat & VIDEO_FORMAT_MASK_10BIT) ? DXGI_FORMAT_P010 : DXGI_FORMAT_NV12;
|
||||||
|
texDesc.SampleDesc.Quality = 0;
|
||||||
|
texDesc.SampleDesc.Count = 1;
|
||||||
|
texDesc.Usage = D3D11_USAGE_DEFAULT;
|
||||||
|
texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
|
||||||
|
texDesc.CPUAccessFlags = 0;
|
||||||
|
texDesc.MiscFlags = 0;
|
||||||
|
|
||||||
srvDesc.Texture2DArray.FirstArraySlice = frameContext->texture_infos[i].index;
|
hr = m_Device->CreateTexture2D(&texDesc, nullptr, &m_VideoTexture);
|
||||||
|
|
||||||
srvDesc.Format = (m_DecoderParams.videoFormat & VIDEO_FORMAT_MASK_10BIT) ? DXGI_FORMAT_R16_UNORM : DXGI_FORMAT_R8_UNORM;
|
|
||||||
hr = m_Device->CreateShaderResourceView(frameContext->texture_infos[i].texture, &srvDesc, &m_VideoTextureResourceViews[i][0]);
|
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
m_VideoTextureResourceViews[i][0] = nullptr;
|
m_VideoTexture = nullptr;
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
|
"ID3D11Device::CreateTexture2D() failed: %x",
|
||||||
|
hr);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create luminance and chrominance SRVs for each plane of the texture
|
||||||
|
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
|
||||||
|
srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
|
||||||
|
srvDesc.Texture2D.MostDetailedMip = 0;
|
||||||
|
srvDesc.Texture2D.MipLevels = 1;
|
||||||
|
srvDesc.Format = (m_DecoderParams.videoFormat & VIDEO_FORMAT_MASK_10BIT) ? DXGI_FORMAT_R16_UNORM : DXGI_FORMAT_R8_UNORM;
|
||||||
|
hr = m_Device->CreateShaderResourceView(m_VideoTexture, &srvDesc, &m_VideoTextureResourceViews[0]);
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
m_VideoTextureResourceViews[0] = nullptr;
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
"ID3D11Device::CreateShaderResourceView() failed: %x",
|
"ID3D11Device::CreateShaderResourceView() failed: %x",
|
||||||
hr);
|
hr);
|
||||||
@ -1344,15 +1353,14 @@ bool D3D11VARenderer::setupTexturePoolViews(AVD3D11VAFramesContext* frameContext
|
|||||||
}
|
}
|
||||||
|
|
||||||
srvDesc.Format = (m_DecoderParams.videoFormat & VIDEO_FORMAT_MASK_10BIT) ? DXGI_FORMAT_R16G16_UNORM : DXGI_FORMAT_R8G8_UNORM;
|
srvDesc.Format = (m_DecoderParams.videoFormat & VIDEO_FORMAT_MASK_10BIT) ? DXGI_FORMAT_R16G16_UNORM : DXGI_FORMAT_R8G8_UNORM;
|
||||||
hr = m_Device->CreateShaderResourceView(frameContext->texture_infos[i].texture, &srvDesc, &m_VideoTextureResourceViews[i][1]);
|
hr = m_Device->CreateShaderResourceView(m_VideoTexture, &srvDesc, &m_VideoTextureResourceViews[1]);
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
m_VideoTextureResourceViews[i][1] = nullptr;
|
m_VideoTextureResourceViews[1] = nullptr;
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
"ID3D11Device::CreateShaderResourceView() failed: %x",
|
"ID3D11Device::CreateShaderResourceView() failed: %x",
|
||||||
hr);
|
hr);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,7 @@ private:
|
|||||||
static void unlockContext(void* lock_ctx);
|
static void unlockContext(void* lock_ctx);
|
||||||
|
|
||||||
bool setupRenderingResources();
|
bool setupRenderingResources();
|
||||||
bool setupTexturePoolViews(AVD3D11VAFramesContext* frameContext);
|
bool setupVideoTexture();
|
||||||
void renderOverlay(Overlay::OverlayType type);
|
void renderOverlay(Overlay::OverlayType type);
|
||||||
void bindColorConversion(AVFrame* frame);
|
void bindColorConversion(AVFrame* frame);
|
||||||
void renderVideo(AVFrame* frame);
|
void renderVideo(AVFrame* frame);
|
||||||
@ -60,8 +60,8 @@ private:
|
|||||||
ID3D11PixelShader* m_VideoBt2020LimPixelShader;
|
ID3D11PixelShader* m_VideoBt2020LimPixelShader;
|
||||||
ID3D11Buffer* m_VideoVertexBuffer;
|
ID3D11Buffer* m_VideoVertexBuffer;
|
||||||
|
|
||||||
#define DECODER_BUFFER_POOL_SIZE 17
|
ID3D11Texture2D* m_VideoTexture;
|
||||||
ID3D11ShaderResourceView* m_VideoTextureResourceViews[DECODER_BUFFER_POOL_SIZE][2];
|
ID3D11ShaderResourceView* m_VideoTextureResourceViews[2];
|
||||||
|
|
||||||
SDL_SpinLock m_OverlayLock;
|
SDL_SpinLock m_OverlayLock;
|
||||||
ID3D11Buffer* m_OverlayVertexBuffers[Overlay::OverlayMax];
|
ID3D11Buffer* m_OverlayVertexBuffers[Overlay::OverlayMax];
|
||||||
|
Loading…
x
Reference in New Issue
Block a user