mirror of
https://github.com/moonlight-stream/moonlight-qt.git
synced 2025-07-01 23:35:55 +00:00
Use ComPtr for lifetime management in DXVA2
This commit is contained in:
parent
9e811f54f1
commit
99749d4730
@ -26,7 +26,7 @@ DEFINE_GUID(DXVA2_ModeAV1_VLD_Profile0,0xb8be4ccb,0xcf53,0x46ba,0x8d,0x59,0xd6,0
|
|||||||
#define FF_DXVA2_WORKAROUND_INTEL_CLEARVIDEO 2
|
#define FF_DXVA2_WORKAROUND_INTEL_CLEARVIDEO 2
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define SAFE_COM_RELEASE(x) if (x) { (x)->Release(); }
|
using Microsoft::WRL::ComPtr;
|
||||||
|
|
||||||
typedef struct _VERTEX
|
typedef struct _VERTEX
|
||||||
{
|
{
|
||||||
@ -36,25 +36,15 @@ typedef struct _VERTEX
|
|||||||
|
|
||||||
DXVA2Renderer::DXVA2Renderer(int decoderSelectionPass) :
|
DXVA2Renderer::DXVA2Renderer(int decoderSelectionPass) :
|
||||||
m_DecoderSelectionPass(decoderSelectionPass),
|
m_DecoderSelectionPass(decoderSelectionPass),
|
||||||
m_DecService(nullptr),
|
|
||||||
m_Decoder(nullptr),
|
|
||||||
m_SurfacesUsed(0),
|
m_SurfacesUsed(0),
|
||||||
m_Pool(nullptr),
|
m_Pool(nullptr),
|
||||||
m_OverlayLock(0),
|
m_OverlayLock(0),
|
||||||
m_Device(nullptr),
|
|
||||||
m_RenderTarget(nullptr),
|
|
||||||
m_ProcService(nullptr),
|
|
||||||
m_Processor(nullptr),
|
|
||||||
m_FrameIndex(0),
|
m_FrameIndex(0),
|
||||||
m_BlockingPresent(false),
|
m_BlockingPresent(false),
|
||||||
m_DeviceQuirks(0)
|
m_DeviceQuirks(0)
|
||||||
{
|
{
|
||||||
RtlZeroMemory(m_DecSurfaces, sizeof(m_DecSurfaces));
|
|
||||||
RtlZeroMemory(&m_DXVAContext, sizeof(m_DXVAContext));
|
RtlZeroMemory(&m_DXVAContext, sizeof(m_DXVAContext));
|
||||||
|
|
||||||
RtlZeroMemory(m_OverlayVertexBuffers, sizeof(m_OverlayVertexBuffers));
|
|
||||||
RtlZeroMemory(m_OverlayTextures, sizeof(m_OverlayTextures));
|
|
||||||
|
|
||||||
// Use MMCSS scheduling for lower scheduling latency while we're streaming
|
// Use MMCSS scheduling for lower scheduling latency while we're streaming
|
||||||
DwmEnableMMCSS(TRUE);
|
DwmEnableMMCSS(TRUE);
|
||||||
}
|
}
|
||||||
@ -63,23 +53,23 @@ DXVA2Renderer::~DXVA2Renderer()
|
|||||||
{
|
{
|
||||||
DwmEnableMMCSS(FALSE);
|
DwmEnableMMCSS(FALSE);
|
||||||
|
|
||||||
SAFE_COM_RELEASE(m_DecService);
|
m_DecService.Reset();
|
||||||
SAFE_COM_RELEASE(m_Decoder);
|
m_Decoder.Reset();
|
||||||
SAFE_COM_RELEASE(m_Device);
|
m_Device.Reset();
|
||||||
SAFE_COM_RELEASE(m_RenderTarget);
|
m_RenderTarget.Reset();
|
||||||
SAFE_COM_RELEASE(m_ProcService);
|
m_ProcService.Reset();
|
||||||
SAFE_COM_RELEASE(m_Processor);
|
m_Processor.Reset();
|
||||||
|
|
||||||
for (int i = 0; i < ARRAYSIZE(m_OverlayVertexBuffers); i++) {
|
for (int i = 0; i < m_OverlayVertexBuffers.size(); i++) {
|
||||||
SAFE_COM_RELEASE(m_OverlayVertexBuffers[i]);
|
m_OverlayVertexBuffers[i].Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < ARRAYSIZE(m_OverlayTextures); i++) {
|
for (int i = 0; i < m_OverlayTextures.size(); i++) {
|
||||||
SAFE_COM_RELEASE(m_OverlayTextures[i]);
|
m_OverlayTextures[i].Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < ARRAYSIZE(m_DecSurfaces); i++) {
|
for (int i = 0; i < m_DecSurfaces.size(); i++) {
|
||||||
SAFE_COM_RELEASE(m_DecSurfaces[i]);
|
m_DecSurfaces[i].Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_Pool != nullptr) {
|
if (m_Pool != nullptr) {
|
||||||
@ -96,12 +86,12 @@ AVBufferRef* DXVA2Renderer::ffPoolAlloc(void* opaque, FF_POOL_SIZE_TYPE)
|
|||||||
{
|
{
|
||||||
DXVA2Renderer* me = reinterpret_cast<DXVA2Renderer*>(opaque);
|
DXVA2Renderer* me = reinterpret_cast<DXVA2Renderer*>(opaque);
|
||||||
|
|
||||||
if (me->m_SurfacesUsed < ARRAYSIZE(me->m_DecSurfaces)) {
|
if (me->m_SurfacesUsed < me->m_DecSurfaces.size()) {
|
||||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
|
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
"DXVA2 decoder surface high-water mark: %d",
|
"DXVA2 decoder surface high-water mark: %d",
|
||||||
me->m_SurfacesUsed);
|
me->m_SurfacesUsed);
|
||||||
return av_buffer_create((uint8_t*)me->m_DecSurfaces[me->m_SurfacesUsed++],
|
return av_buffer_create((uint8_t*)me->m_DecSurfacesRaw[me->m_SurfacesUsed++],
|
||||||
sizeof(*me->m_DecSurfaces), ffPoolDummyDelete, 0, 0);
|
sizeof(me->m_DecSurfacesRaw[0]), ffPoolDummyDelete, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -110,10 +100,10 @@ AVBufferRef* DXVA2Renderer::ffPoolAlloc(void* opaque, FF_POOL_SIZE_TYPE)
|
|||||||
bool DXVA2Renderer::prepareDecoderContext(AVCodecContext* context, AVDictionary**)
|
bool DXVA2Renderer::prepareDecoderContext(AVCodecContext* context, AVDictionary**)
|
||||||
{
|
{
|
||||||
// m_DXVAContext.workaround and report_id already initialized elsewhere
|
// m_DXVAContext.workaround and report_id already initialized elsewhere
|
||||||
m_DXVAContext.decoder = m_Decoder;
|
m_DXVAContext.decoder = m_Decoder.Get();
|
||||||
m_DXVAContext.cfg = &m_Config;
|
m_DXVAContext.cfg = &m_Config;
|
||||||
m_DXVAContext.surface = m_DecSurfaces;
|
m_DXVAContext.surface = m_DecSurfacesRaw.data();
|
||||||
m_DXVAContext.surface_count = ARRAYSIZE(m_DecSurfaces);
|
m_DXVAContext.surface_count = (unsigned int)m_DecSurfacesRaw.size();
|
||||||
|
|
||||||
context->hwaccel_context = &m_DXVAContext;
|
context->hwaccel_context = &m_DXVAContext;
|
||||||
|
|
||||||
@ -124,7 +114,7 @@ bool DXVA2Renderer::prepareDecoderContext(AVCodecContext* context, AVDictionary*
|
|||||||
)
|
)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
m_Pool = av_buffer_pool_init2(ARRAYSIZE(m_DecSurfaces), this, ffPoolAlloc, nullptr);
|
m_Pool = av_buffer_pool_init2(m_DecSurfaces.size(), this, ffPoolAlloc, nullptr);
|
||||||
if (!m_Pool) {
|
if (!m_Pool) {
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
"Failed create buffer pool");
|
"Failed create buffer pool");
|
||||||
@ -162,8 +152,7 @@ bool DXVA2Renderer::initializeDecoder()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = DXVA2CreateVideoService(m_Device, IID_IDirectXVideoDecoderService,
|
hr = DXVA2CreateVideoService(m_Device.Get(), IID_IDirectXVideoDecoderService, &m_DecService);
|
||||||
reinterpret_cast<void**>(&m_DecService));
|
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
"DXVA2CreateVideoService(IID_IDirectXVideoDecoderService) failed: %x",
|
"DXVA2CreateVideoService(IID_IDirectXVideoDecoderService) failed: %x",
|
||||||
@ -255,12 +244,12 @@ bool DXVA2Renderer::initializeDecoder()
|
|||||||
SDL_assert(m_Desc.SampleHeight % 16 == 0);
|
SDL_assert(m_Desc.SampleHeight % 16 == 0);
|
||||||
hr = m_DecService->CreateSurface(m_Desc.SampleWidth,
|
hr = m_DecService->CreateSurface(m_Desc.SampleWidth,
|
||||||
m_Desc.SampleHeight,
|
m_Desc.SampleHeight,
|
||||||
ARRAYSIZE(m_DecSurfaces) - 1,
|
(UINT)m_DecSurfacesRaw.size() - 1,
|
||||||
m_Desc.Format,
|
m_Desc.Format,
|
||||||
D3DPOOL_DEFAULT,
|
D3DPOOL_DEFAULT,
|
||||||
0,
|
0,
|
||||||
DXVA2_VideoDecoderRenderTarget,
|
DXVA2_VideoDecoderRenderTarget,
|
||||||
m_DecSurfaces,
|
m_DecSurfacesRaw.data(),
|
||||||
nullptr);
|
nullptr);
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
@ -269,8 +258,14 @@ bool DXVA2Renderer::initializeDecoder()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Transfer ownership into ComPtrs
|
||||||
|
for (int i = 0; i < m_DecSurfaces.size(); i++) {
|
||||||
|
m_DecSurfaces[i].Attach(m_DecSurfacesRaw[i]);
|
||||||
|
}
|
||||||
|
|
||||||
hr = m_DecService->CreateVideoDecoder(chosenDeviceGuid, &m_Desc, &m_Config,
|
hr = m_DecService->CreateVideoDecoder(chosenDeviceGuid, &m_Desc, &m_Config,
|
||||||
m_DecSurfaces, ARRAYSIZE(m_DecSurfaces),
|
m_DecSurfacesRaw.data(),
|
||||||
|
(UINT)m_DecSurfacesRaw.size(),
|
||||||
&m_Decoder);
|
&m_Decoder);
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
@ -301,8 +296,7 @@ bool DXVA2Renderer::initializeRenderer()
|
|||||||
m_DisplayHeight = renderTargetDesc.Height;
|
m_DisplayHeight = renderTargetDesc.Height;
|
||||||
|
|
||||||
if (!(m_DeviceQuirks & DXVA2_QUIRK_NO_VP)) {
|
if (!(m_DeviceQuirks & DXVA2_QUIRK_NO_VP)) {
|
||||||
hr = DXVA2CreateVideoService(m_Device, IID_IDirectXVideoProcessorService,
|
hr = DXVA2CreateVideoService(m_Device.Get(), IID_IDirectXVideoProcessorService, &m_ProcService);
|
||||||
reinterpret_cast<void**>(&m_ProcService));
|
|
||||||
|
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
@ -386,7 +380,7 @@ bool DXVA2Renderer::initializeQuirksForAdapter(IDirect3D9Ex* d3d9ex, int adapter
|
|||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
|
||||||
SDL_assert(m_DeviceQuirks == 0);
|
SDL_assert(m_DeviceQuirks == 0);
|
||||||
SDL_assert(m_Device == nullptr);
|
SDL_assert(!m_Device);
|
||||||
|
|
||||||
{
|
{
|
||||||
bool ok;
|
bool ok;
|
||||||
@ -466,7 +460,7 @@ bool DXVA2Renderer::initializeQuirksForAdapter(IDirect3D9Ex* d3d9ex, int adapter
|
|||||||
|
|
||||||
bool DXVA2Renderer::isDecoderBlacklisted()
|
bool DXVA2Renderer::isDecoderBlacklisted()
|
||||||
{
|
{
|
||||||
IDirect3D9* d3d9;
|
ComPtr<IDirect3D9> d3d9;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
bool result = false;
|
bool result = false;
|
||||||
|
|
||||||
@ -523,8 +517,6 @@ bool DXVA2Renderer::isDecoderBlacklisted()
|
|||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
"GetDeviceCaps() failed: %x", hr);
|
"GetDeviceCaps() failed: %x", hr);
|
||||||
}
|
}
|
||||||
|
|
||||||
d3d9->Release();
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
@ -547,7 +539,7 @@ bool DXVA2Renderer::initializeDevice(SDL_Window* window, bool enableVsync)
|
|||||||
SDL_VERSION(&info.version);
|
SDL_VERSION(&info.version);
|
||||||
SDL_GetWindowWMInfo(window, &info);
|
SDL_GetWindowWMInfo(window, &info);
|
||||||
|
|
||||||
IDirect3D9Ex* d3d9ex;
|
ComPtr<IDirect3D9Ex> d3d9ex;
|
||||||
HRESULT hr = Direct3DCreate9Ex(D3D_SDK_VERSION, &d3d9ex);
|
HRESULT hr = Direct3DCreate9Ex(D3D_SDK_VERSION, &d3d9ex);
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
@ -561,8 +553,7 @@ bool DXVA2Renderer::initializeDevice(SDL_Window* window, bool enableVsync)
|
|||||||
|
|
||||||
// Initialize quirks *before* calling CreateDeviceEx() to allow our below
|
// Initialize quirks *before* calling CreateDeviceEx() to allow our below
|
||||||
// logic to avoid a hang with NahimicOSD.dll's broken full-screen handling.
|
// logic to avoid a hang with NahimicOSD.dll's broken full-screen handling.
|
||||||
if (!initializeQuirksForAdapter(d3d9ex, adapterIndex)) {
|
if (!initializeQuirksForAdapter(d3d9ex.Get(), adapterIndex)) {
|
||||||
d3d9ex->Release();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -588,7 +579,6 @@ bool DXVA2Renderer::initializeDevice(SDL_Window* window, bool enableVsync)
|
|||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
"GPU/driver doesn't support A2R10G10B10");
|
"GPU/driver doesn't support A2R10G10B10");
|
||||||
d3d9ex->Release();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -685,9 +675,6 @@ bool DXVA2Renderer::initializeDevice(SDL_Window* window, bool enableVsync)
|
|||||||
&d3dpp,
|
&d3dpp,
|
||||||
d3dpp.Windowed ? nullptr : ¤tMode,
|
d3dpp.Windowed ? nullptr : ¤tMode,
|
||||||
&m_Device);
|
&m_Device);
|
||||||
|
|
||||||
d3d9ex->Release();
|
|
||||||
|
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
"CreateDeviceEx() failed: %x",
|
"CreateDeviceEx() failed: %x",
|
||||||
@ -810,16 +797,10 @@ void DXVA2Renderer::notifyOverlayUpdated(Overlay::OverlayType type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
SDL_AtomicLock(&m_OverlayLock);
|
SDL_AtomicLock(&m_OverlayLock);
|
||||||
IDirect3DTexture9* oldTexture = m_OverlayTextures[type];
|
ComPtr<IDirect3DTexture9> oldTexture = std::move(m_OverlayTextures[type]);
|
||||||
m_OverlayTextures[type] = nullptr;
|
ComPtr<IDirect3DVertexBuffer9> oldVertexBuffer = std::move(m_OverlayVertexBuffers[type]);
|
||||||
|
|
||||||
IDirect3DVertexBuffer9* oldVertexBuffer = m_OverlayVertexBuffers[type];
|
|
||||||
m_OverlayVertexBuffers[type] = nullptr;
|
|
||||||
SDL_AtomicUnlock(&m_OverlayLock);
|
SDL_AtomicUnlock(&m_OverlayLock);
|
||||||
|
|
||||||
SAFE_COM_RELEASE(oldTexture);
|
|
||||||
SAFE_COM_RELEASE(oldVertexBuffer);
|
|
||||||
|
|
||||||
// If the overlay is disabled, we're done
|
// If the overlay is disabled, we're done
|
||||||
if (!overlayEnabled) {
|
if (!overlayEnabled) {
|
||||||
SDL_FreeSurface(newSurface);
|
SDL_FreeSurface(newSurface);
|
||||||
@ -828,7 +809,7 @@ void DXVA2Renderer::notifyOverlayUpdated(Overlay::OverlayType type)
|
|||||||
|
|
||||||
// Create a dynamic texture to populate with our pixel data
|
// Create a dynamic texture to populate with our pixel data
|
||||||
SDL_assert(!SDL_MUSTLOCK(newSurface));
|
SDL_assert(!SDL_MUSTLOCK(newSurface));
|
||||||
IDirect3DTexture9* newTexture = nullptr;
|
ComPtr<IDirect3DTexture9> newTexture;
|
||||||
hr = m_Device->CreateTexture(newSurface->w,
|
hr = m_Device->CreateTexture(newSurface->w,
|
||||||
newSurface->h,
|
newSurface->h,
|
||||||
1,
|
1,
|
||||||
@ -849,7 +830,6 @@ void DXVA2Renderer::notifyOverlayUpdated(Overlay::OverlayType type)
|
|||||||
hr = newTexture->LockRect(0, &lockedRect, nullptr, D3DLOCK_DISCARD);
|
hr = newTexture->LockRect(0, &lockedRect, nullptr, D3DLOCK_DISCARD);
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
SDL_FreeSurface(newSurface);
|
SDL_FreeSurface(newSurface);
|
||||||
SAFE_COM_RELEASE(newTexture);
|
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
"IDirect3DTexture9::LockRect() failed: %x",
|
"IDirect3DTexture9::LockRect() failed: %x",
|
||||||
hr);
|
hr);
|
||||||
@ -890,7 +870,7 @@ void DXVA2Renderer::notifyOverlayUpdated(Overlay::OverlayType type)
|
|||||||
{renderRect.x+renderRect.w, renderRect.y, 0, 1, 1, 0}
|
{renderRect.x+renderRect.w, renderRect.y, 0, 1, 1, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
IDirect3DVertexBuffer9* newVertexBuffer = nullptr;
|
ComPtr<IDirect3DVertexBuffer9> newVertexBuffer;
|
||||||
hr = m_Device->CreateVertexBuffer(sizeof(verts),
|
hr = m_Device->CreateVertexBuffer(sizeof(verts),
|
||||||
D3DUSAGE_WRITEONLY,
|
D3DUSAGE_WRITEONLY,
|
||||||
D3DFVF_XYZRHW | D3DFVF_TEX1,
|
D3DFVF_XYZRHW | D3DFVF_TEX1,
|
||||||
@ -898,7 +878,6 @@ void DXVA2Renderer::notifyOverlayUpdated(Overlay::OverlayType type)
|
|||||||
&newVertexBuffer,
|
&newVertexBuffer,
|
||||||
nullptr);
|
nullptr);
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
SAFE_COM_RELEASE(newTexture);
|
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
"CreateVertexBuffer() failed: %x",
|
"CreateVertexBuffer() failed: %x",
|
||||||
hr);
|
hr);
|
||||||
@ -908,8 +887,6 @@ void DXVA2Renderer::notifyOverlayUpdated(Overlay::OverlayType type)
|
|||||||
PVOID targetVertexBuffer = nullptr;
|
PVOID targetVertexBuffer = nullptr;
|
||||||
hr = newVertexBuffer->Lock(0, 0, &targetVertexBuffer, 0);
|
hr = newVertexBuffer->Lock(0, 0, &targetVertexBuffer, 0);
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
SAFE_COM_RELEASE(newTexture);
|
|
||||||
SAFE_COM_RELEASE(newVertexBuffer);
|
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
"IDirect3DVertexBuffer9::Lock() failed: %x",
|
"IDirect3DVertexBuffer9::Lock() failed: %x",
|
||||||
hr);
|
hr);
|
||||||
@ -921,8 +898,8 @@ void DXVA2Renderer::notifyOverlayUpdated(Overlay::OverlayType type)
|
|||||||
newVertexBuffer->Unlock();
|
newVertexBuffer->Unlock();
|
||||||
|
|
||||||
SDL_AtomicLock(&m_OverlayLock);
|
SDL_AtomicLock(&m_OverlayLock);
|
||||||
m_OverlayVertexBuffers[type] = newVertexBuffer;
|
m_OverlayVertexBuffers[type] = std::move(newVertexBuffer);
|
||||||
m_OverlayTextures[type] = newTexture;
|
m_OverlayTextures[type] = std::move(newTexture);
|
||||||
SDL_AtomicUnlock(&m_OverlayLock);
|
SDL_AtomicUnlock(&m_OverlayLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -939,36 +916,30 @@ void DXVA2Renderer::renderOverlay(Overlay::OverlayType type)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
IDirect3DTexture9* overlayTexture = m_OverlayTextures[type];
|
// Reference these objects so they don't immediately go away if the
|
||||||
IDirect3DVertexBuffer9* overlayVertexBuffer = m_OverlayVertexBuffers[type];
|
// overlay update thread tries to release them.
|
||||||
|
ComPtr<IDirect3DTexture9> overlayTexture = m_OverlayTextures[type];
|
||||||
|
ComPtr<IDirect3DVertexBuffer9> overlayVertexBuffer = m_OverlayVertexBuffers[type];
|
||||||
|
SDL_AtomicUnlock(&m_OverlayLock);
|
||||||
|
|
||||||
if (overlayTexture == nullptr) {
|
if (overlayTexture == nullptr) {
|
||||||
SDL_AtomicUnlock(&m_OverlayLock);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reference these objects so they don't immediately go away if the
|
hr = m_Device->SetTexture(0, overlayTexture.Get());
|
||||||
// overlay update thread tries to release them.
|
|
||||||
SDL_assert(overlayVertexBuffer != nullptr);
|
|
||||||
overlayTexture->AddRef();
|
|
||||||
overlayVertexBuffer->AddRef();
|
|
||||||
|
|
||||||
SDL_AtomicUnlock(&m_OverlayLock);
|
|
||||||
|
|
||||||
hr = m_Device->SetTexture(0, overlayTexture);
|
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
"SetTexture() failed: %x",
|
"SetTexture() failed: %x",
|
||||||
hr);
|
hr);
|
||||||
goto Exit;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = m_Device->SetStreamSource(0, overlayVertexBuffer, 0, sizeof(VERTEX));
|
hr = m_Device->SetStreamSource(0, overlayVertexBuffer.Get(), 0, sizeof(VERTEX));
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
"SetStreamSource() failed: %x",
|
"SetStreamSource() failed: %x",
|
||||||
hr);
|
hr);
|
||||||
goto Exit;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = m_Device->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2);
|
hr = m_Device->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2);
|
||||||
@ -976,12 +947,8 @@ void DXVA2Renderer::renderOverlay(Overlay::OverlayType type)
|
|||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
"DrawPrimitive() failed: %x",
|
"DrawPrimitive() failed: %x",
|
||||||
hr);
|
hr);
|
||||||
goto Exit;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Exit:
|
|
||||||
overlayTexture->Release();
|
|
||||||
overlayVertexBuffer->Release();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int DXVA2Renderer::getDecoderColorspace()
|
int DXVA2Renderer::getDecoderColorspace()
|
||||||
@ -1158,13 +1125,12 @@ void DXVA2Renderer::renderFrame(AVFrame *frame)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (m_Processor) {
|
if (m_Processor) {
|
||||||
hr = m_Processor->VideoProcessBlt(m_RenderTarget, &bltParams, &sample, 1, nullptr);
|
hr = m_Processor->VideoProcessBlt(m_RenderTarget.Get(), &bltParams, &sample, 1, nullptr);
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
"VideoProcessBlt() failed, falling back to StretchRect(): %x",
|
"VideoProcessBlt() failed, falling back to StretchRect(): %x",
|
||||||
hr);
|
hr);
|
||||||
m_Processor->Release();
|
m_Processor.Reset();
|
||||||
m_Processor = nullptr;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1173,7 +1139,7 @@ void DXVA2Renderer::renderFrame(AVFrame *frame)
|
|||||||
SDL_assert(m_Desc.SampleFormat.VideoTransferMatrix == DXVA2_VideoTransferMatrix_BT601);
|
SDL_assert(m_Desc.SampleFormat.VideoTransferMatrix == DXVA2_VideoTransferMatrix_BT601);
|
||||||
|
|
||||||
// This function doesn't trigger any of Intel's garbage video "enhancements"
|
// This function doesn't trigger any of Intel's garbage video "enhancements"
|
||||||
hr = m_Device->StretchRect(surface, &sample.SrcRect, m_RenderTarget, &sample.DstRect, D3DTEXF_NONE);
|
hr = m_Device->StretchRect(surface, &sample.SrcRect, m_RenderTarget.Get(), &sample.DstRect, D3DTEXF_NONE);
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
"StretchRect() failed: %x",
|
"StretchRect() failed: %x",
|
||||||
|
@ -10,6 +10,8 @@ extern "C" {
|
|||||||
#include <libavcodec/dxva2.h>
|
#include <libavcodec/dxva2.h>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include <wrl/client.h>
|
||||||
|
|
||||||
class DXVA2Renderer : public IFFmpegRenderer
|
class DXVA2Renderer : public IFFmpegRenderer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -55,21 +57,22 @@ private:
|
|||||||
int m_DisplayHeight;
|
int m_DisplayHeight;
|
||||||
|
|
||||||
struct dxva_context m_DXVAContext;
|
struct dxva_context m_DXVAContext;
|
||||||
IDirect3DSurface9* m_DecSurfaces[19];
|
std::array<Microsoft::WRL::ComPtr<IDirect3DSurface9>, 19> m_DecSurfaces;
|
||||||
|
std::array<IDirect3DSurface9*, 19> m_DecSurfacesRaw; // Referenced by m_DecSurfaces
|
||||||
DXVA2_ConfigPictureDecode m_Config;
|
DXVA2_ConfigPictureDecode m_Config;
|
||||||
IDirectXVideoDecoderService* m_DecService;
|
Microsoft::WRL::ComPtr<IDirectXVideoDecoderService> m_DecService;
|
||||||
IDirectXVideoDecoder* m_Decoder;
|
Microsoft::WRL::ComPtr<IDirectXVideoDecoder> m_Decoder;
|
||||||
int m_SurfacesUsed;
|
int m_SurfacesUsed;
|
||||||
AVBufferPool* m_Pool;
|
AVBufferPool* m_Pool;
|
||||||
|
|
||||||
SDL_SpinLock m_OverlayLock;
|
SDL_SpinLock m_OverlayLock;
|
||||||
IDirect3DVertexBuffer9* m_OverlayVertexBuffers[Overlay::OverlayMax];
|
std::array<Microsoft::WRL::ComPtr<IDirect3DVertexBuffer9>, Overlay::OverlayMax> m_OverlayVertexBuffers;
|
||||||
IDirect3DTexture9* m_OverlayTextures[Overlay::OverlayMax];
|
std::array<Microsoft::WRL::ComPtr<IDirect3DTexture9>, Overlay::OverlayMax> m_OverlayTextures;
|
||||||
|
|
||||||
IDirect3DDevice9Ex* m_Device;
|
Microsoft::WRL::ComPtr<IDirect3DDevice9Ex> m_Device;
|
||||||
IDirect3DSurface9* m_RenderTarget;
|
Microsoft::WRL::ComPtr<IDirect3DSurface9> m_RenderTarget;
|
||||||
IDirectXVideoProcessorService* m_ProcService;
|
Microsoft::WRL::ComPtr<IDirectXVideoProcessorService> m_ProcService;
|
||||||
IDirectXVideoProcessor* m_Processor;
|
Microsoft::WRL::ComPtr<IDirectXVideoProcessor> m_Processor;
|
||||||
DXVA2_ValueRange m_BrightnessRange;
|
DXVA2_ValueRange m_BrightnessRange;
|
||||||
DXVA2_ValueRange m_ContrastRange;
|
DXVA2_ValueRange m_ContrastRange;
|
||||||
DXVA2_ValueRange m_HueRange;
|
DXVA2_ValueRange m_HueRange;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user