mirror of
https://github.com/moonlight-stream/moonlight-qt.git
synced 2025-07-01 23:35:55 +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_VideoBt2020LimPixelShader(nullptr),
|
||||
m_VideoVertexBuffer(nullptr),
|
||||
m_VideoTexture(nullptr),
|
||||
m_OverlayLock(0),
|
||||
m_OverlayPixelShader(nullptr),
|
||||
m_HwDeviceContext(nullptr),
|
||||
@ -114,10 +115,11 @@ D3D11VARenderer::~D3D11VARenderer()
|
||||
SAFE_COM_RELEASE(m_VideoGenericPixelShader);
|
||||
|
||||
for (int i = 0; i < ARRAYSIZE(m_VideoTextureResourceViews); i++) {
|
||||
SAFE_COM_RELEASE(m_VideoTextureResourceViews[i][0]);
|
||||
SAFE_COM_RELEASE(m_VideoTextureResourceViews[i][1]);
|
||||
SAFE_COM_RELEASE(m_VideoTextureResourceViews[i]);
|
||||
}
|
||||
|
||||
SAFE_COM_RELEASE(m_VideoTexture);
|
||||
|
||||
for (int i = 0; i < ARRAYSIZE(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);
|
||||
|
||||
// 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;
|
||||
|
||||
// We need to override the default D3D11VA bind flags to bind the textures as a shader resources
|
||||
d3d11vaFramesContext->BindFlags = D3D11_BIND_DECODER | D3D11_BIND_SHADER_RESOURCE;
|
||||
d3d11vaFramesContext->BindFlags = D3D11_BIND_DECODER;
|
||||
|
||||
int err = av_hwframe_ctx_init(m_HwFramesContext);
|
||||
if (err < 0) {
|
||||
@ -474,8 +475,8 @@ bool D3D11VARenderer::initialize(PDECODER_PARAMETERS params)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create SRVs for all textures in the decoder pool
|
||||
if (!setupTexturePoolViews(d3d11vaFramesContext)) {
|
||||
// Create our video texture and SRVs
|
||||
if (!setupVideoTexture()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -763,22 +764,21 @@ void D3D11VARenderer::renderVideo(AVFrame* frame)
|
||||
UINT offset = 0;
|
||||
m_DeviceContext->IASetVertexBuffers(0, 1, &m_VideoVertexBuffer, &stride, &offset);
|
||||
|
||||
// Our indexing logic depends on a direct mapping into m_VideoTextureResourceViews
|
||||
// based on the texture index provided by FFmpeg.
|
||||
UINT textureIndex = (uintptr_t)frame->data[1];
|
||||
SDL_assert(textureIndex < DECODER_BUFFER_POOL_SIZE);
|
||||
if (textureIndex >= DECODER_BUFFER_POOL_SIZE) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Unexpected texture index: %u",
|
||||
textureIndex);
|
||||
return;
|
||||
}
|
||||
// Copy this frame (minus alignment padding) into our video texture
|
||||
D3D11_BOX srcBox;
|
||||
srcBox.left = 0;
|
||||
srcBox.top = 0;
|
||||
srcBox.right = m_DecoderParams.width;
|
||||
srcBox.bottom = m_DecoderParams.height;
|
||||
srcBox.front = 0;
|
||||
srcBox.back = 1;
|
||||
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)
|
||||
bindColorConversion(frame);
|
||||
|
||||
// Bind SRVs for this frame
|
||||
m_DeviceContext->PSSetShaderResources(0, 2, m_VideoTextureResourceViews[textureIndex]);
|
||||
m_DeviceContext->PSSetShaderResources(0, 2, m_VideoTextureResourceViews);
|
||||
|
||||
// Draw the video
|
||||
m_DeviceContext->DrawIndexed(6, 0, 0);
|
||||
@ -1238,17 +1238,12 @@ bool D3D11VARenderer::setupRenderingResources()
|
||||
SDL_FRect renderRect;
|
||||
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[] =
|
||||
{
|
||||
{renderRect.x, renderRect.y, 0, vMax},
|
||||
{renderRect.x, renderRect.y, 0, 1.0f},
|
||||
{renderRect.x, renderRect.y+renderRect.h, 0, 0},
|
||||
{renderRect.x+renderRect.w, renderRect.y, uMax, vMax},
|
||||
{renderRect.x+renderRect.w, renderRect.y+renderRect.h, uMax, 0},
|
||||
{renderRect.x+renderRect.w, renderRect.y, 1.0f, 1.0f},
|
||||
{renderRect.x+renderRect.w, renderRect.y+renderRect.h, 1.0f, 0},
|
||||
};
|
||||
|
||||
D3D11_BUFFER_DESC vbDesc = {};
|
||||
@ -1316,42 +1311,55 @@ bool D3D11VARenderer::setupRenderingResources()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool D3D11VARenderer::setupTexturePoolViews(AVD3D11VAFramesContext* frameContext)
|
||||
bool D3D11VARenderer::setupVideoTexture()
|
||||
{
|
||||
HRESULT hr;
|
||||
D3D11_TEXTURE2D_DESC texDesc = {};
|
||||
|
||||
texDesc.Width = m_DecoderParams.width;
|
||||
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;
|
||||
|
||||
hr = m_Device->CreateTexture2D(&texDesc, nullptr, &m_VideoTexture);
|
||||
if (FAILED(hr)) {
|
||||
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_TEXTURE2DARRAY;
|
||||
srvDesc.Texture2DArray.MostDetailedMip = 0;
|
||||
srvDesc.Texture2DArray.MipLevels = 1;
|
||||
srvDesc.Texture2DArray.ArraySize = 1;
|
||||
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,
|
||||
"ID3D11Device::CreateShaderResourceView() failed: %x",
|
||||
hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create luminance and chrominance SRVs for each texture in the pool
|
||||
for (int i = 0; i < DECODER_BUFFER_POOL_SIZE; i++) {
|
||||
HRESULT hr;
|
||||
|
||||
// Our rendering logic depends on the texture index working to map into our SRV array
|
||||
SDL_assert(i == frameContext->texture_infos[i].index);
|
||||
|
||||
srvDesc.Texture2DArray.FirstArraySlice = frameContext->texture_infos[i].index;
|
||||
|
||||
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)) {
|
||||
m_VideoTextureResourceViews[i][0] = nullptr;
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"ID3D11Device::CreateShaderResourceView() failed: %x",
|
||||
hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
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]);
|
||||
if (FAILED(hr)) {
|
||||
m_VideoTextureResourceViews[i][1] = nullptr;
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"ID3D11Device::CreateShaderResourceView() failed: %x",
|
||||
hr);
|
||||
return false;
|
||||
}
|
||||
srvDesc.Format = (m_DecoderParams.videoFormat & VIDEO_FORMAT_MASK_10BIT) ? DXGI_FORMAT_R16G16_UNORM : DXGI_FORMAT_R8G8_UNORM;
|
||||
hr = m_Device->CreateShaderResourceView(m_VideoTexture, &srvDesc, &m_VideoTextureResourceViews[1]);
|
||||
if (FAILED(hr)) {
|
||||
m_VideoTextureResourceViews[1] = nullptr;
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||
"ID3D11Device::CreateShaderResourceView() failed: %x",
|
||||
hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -30,7 +30,7 @@ private:
|
||||
static void unlockContext(void* lock_ctx);
|
||||
|
||||
bool setupRenderingResources();
|
||||
bool setupTexturePoolViews(AVD3D11VAFramesContext* frameContext);
|
||||
bool setupVideoTexture();
|
||||
void renderOverlay(Overlay::OverlayType type);
|
||||
void bindColorConversion(AVFrame* frame);
|
||||
void renderVideo(AVFrame* frame);
|
||||
@ -60,8 +60,8 @@ private:
|
||||
ID3D11PixelShader* m_VideoBt2020LimPixelShader;
|
||||
ID3D11Buffer* m_VideoVertexBuffer;
|
||||
|
||||
#define DECODER_BUFFER_POOL_SIZE 17
|
||||
ID3D11ShaderResourceView* m_VideoTextureResourceViews[DECODER_BUFFER_POOL_SIZE][2];
|
||||
ID3D11Texture2D* m_VideoTexture;
|
||||
ID3D11ShaderResourceView* m_VideoTextureResourceViews[2];
|
||||
|
||||
SDL_SpinLock m_OverlayLock;
|
||||
ID3D11Buffer* m_OverlayVertexBuffers[Overlay::OverlayMax];
|
||||
|
Loading…
x
Reference in New Issue
Block a user