mirror of
https://github.com/moonlight-stream/moonlight-qt.git
synced 2025-07-04 00:36:36 +00:00
Use a vertex buffer for rendering the DXVA2 overlays
This commit is contained in:
parent
b66f7f6c8b
commit
94b46a2173
@ -42,7 +42,7 @@ DXVA2Renderer::DXVA2Renderer() :
|
|||||||
RtlZeroMemory(m_DecSurfaces, sizeof(m_DecSurfaces));
|
RtlZeroMemory(m_DecSurfaces, sizeof(m_DecSurfaces));
|
||||||
RtlZeroMemory(&m_DXVAContext, sizeof(m_DXVAContext));
|
RtlZeroMemory(&m_DXVAContext, sizeof(m_DXVAContext));
|
||||||
|
|
||||||
RtlZeroMemory(m_OverlaySurfaces, sizeof(m_OverlaySurfaces));
|
RtlZeroMemory(m_OverlayVertexBuffers, sizeof(m_OverlayVertexBuffers));
|
||||||
RtlZeroMemory(m_OverlayTextures, sizeof(m_OverlayTextures));
|
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
|
||||||
@ -60,10 +60,8 @@ DXVA2Renderer::~DXVA2Renderer()
|
|||||||
SAFE_COM_RELEASE(m_ProcService);
|
SAFE_COM_RELEASE(m_ProcService);
|
||||||
SAFE_COM_RELEASE(m_Processor);
|
SAFE_COM_RELEASE(m_Processor);
|
||||||
|
|
||||||
for (int i = 0; i < ARRAYSIZE(m_OverlaySurfaces); i++) {
|
for (int i = 0; i < ARRAYSIZE(m_OverlayVertexBuffers); i++) {
|
||||||
if (m_OverlaySurfaces[i] != nullptr) {
|
SAFE_COM_RELEASE(m_OverlayVertexBuffers[i]);
|
||||||
SDL_FreeSurface(m_OverlaySurfaces[i]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < ARRAYSIZE(m_OverlayTextures); i++) {
|
for (int i = 0; i < ARRAYSIZE(m_OverlayTextures); i++) {
|
||||||
@ -781,14 +779,11 @@ void DXVA2Renderer::notifyOverlayUpdated(Overlay::OverlayType type)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We must free the old texture first because it references the memory stored in the old surface.
|
|
||||||
IDirect3DTexture9* oldTexture = (IDirect3DTexture9*)SDL_AtomicSetPtr((void**)&m_OverlayTextures[type], nullptr);
|
IDirect3DTexture9* oldTexture = (IDirect3DTexture9*)SDL_AtomicSetPtr((void**)&m_OverlayTextures[type], nullptr);
|
||||||
SAFE_COM_RELEASE(oldTexture);
|
SAFE_COM_RELEASE(oldTexture);
|
||||||
|
|
||||||
SDL_Surface* oldSurface = (SDL_Surface*)SDL_AtomicSetPtr((void**)&m_OverlaySurfaces[type], nullptr);
|
IDirect3DVertexBuffer9* oldVertexBuffer = (IDirect3DVertexBuffer9*)SDL_AtomicSetPtr((void**)&m_OverlayVertexBuffers[type], nullptr);
|
||||||
if (oldSurface != nullptr) {
|
SAFE_COM_RELEASE(oldVertexBuffer);
|
||||||
SDL_FreeSurface(oldSurface);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the overlay is disabled, we're done
|
// If the overlay is disabled, we're done
|
||||||
if (!Session::get()->getOverlayManager().isOverlayEnabled(type)) {
|
if (!Session::get()->getOverlayManager().isOverlayEnabled(type)) {
|
||||||
@ -807,6 +802,7 @@ void DXVA2Renderer::notifyOverlayUpdated(Overlay::OverlayType type)
|
|||||||
&newTexture,
|
&newTexture,
|
||||||
nullptr);
|
nullptr);
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
|
SDL_FreeSurface(newSurface);
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
"CreateTexture() failed: %x",
|
"CreateTexture() failed: %x",
|
||||||
hr);
|
hr);
|
||||||
@ -816,8 +812,10 @@ void DXVA2Renderer::notifyOverlayUpdated(Overlay::OverlayType type)
|
|||||||
D3DLOCKED_RECT lockedRect;
|
D3DLOCKED_RECT lockedRect;
|
||||||
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);
|
||||||
|
SAFE_COM_RELEASE(newTexture);
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
"LockRect() failed: %x",
|
"IDirect3DTexture9::LockRect() failed: %x",
|
||||||
hr);
|
hr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -838,7 +836,65 @@ void DXVA2Renderer::notifyOverlayUpdated(Overlay::OverlayType type)
|
|||||||
|
|
||||||
newTexture->UnlockRect(0);
|
newTexture->UnlockRect(0);
|
||||||
|
|
||||||
SDL_AtomicSetPtr((void**)&m_OverlaySurfaces[type], newSurface);
|
SDL_FRect renderRect = {};
|
||||||
|
|
||||||
|
if (type == Overlay::OverlayStatusUpdate) {
|
||||||
|
// Bottom Left
|
||||||
|
renderRect.x = 0;
|
||||||
|
renderRect.y = m_DisplayHeight - newSurface->h;
|
||||||
|
}
|
||||||
|
else if (type == Overlay::OverlayDebug) {
|
||||||
|
// Top left
|
||||||
|
renderRect.x = 0;
|
||||||
|
renderRect.y = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
renderRect.w = newSurface->w;
|
||||||
|
renderRect.h = newSurface->h;
|
||||||
|
|
||||||
|
// The surface is no longer required
|
||||||
|
SDL_FreeSurface(newSurface);
|
||||||
|
newSurface = nullptr;
|
||||||
|
|
||||||
|
VERTEX verts[] =
|
||||||
|
{
|
||||||
|
{renderRect.x, renderRect.y, 0, 1, 0, 0},
|
||||||
|
{renderRect.x, renderRect.y+renderRect.h, 0, 1, 0, 1},
|
||||||
|
{renderRect.x+renderRect.w, renderRect.y+renderRect.h, 0, 1, 1, 1},
|
||||||
|
{renderRect.x+renderRect.w, renderRect.y, 0, 1, 1, 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
IDirect3DVertexBuffer9* newVertexBuffer = nullptr;
|
||||||
|
hr = m_Device->CreateVertexBuffer(sizeof(verts),
|
||||||
|
D3DUSAGE_WRITEONLY,
|
||||||
|
D3DFVF_XYZRHW | D3DFVF_TEX1,
|
||||||
|
D3DPOOL_DEFAULT,
|
||||||
|
&newVertexBuffer,
|
||||||
|
nullptr);
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
SAFE_COM_RELEASE(newTexture);
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
|
"CreateVertexBuffer() failed: %x",
|
||||||
|
hr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PVOID targetVertexBuffer = nullptr;
|
||||||
|
hr = newVertexBuffer->Lock(0, 0, &targetVertexBuffer, 0);
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
SAFE_COM_RELEASE(newTexture);
|
||||||
|
SAFE_COM_RELEASE(newVertexBuffer);
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
|
"IDirect3DVertexBuffer9::Lock() failed: %x",
|
||||||
|
hr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
RtlCopyMemory(targetVertexBuffer, verts, sizeof(verts));
|
||||||
|
|
||||||
|
newVertexBuffer->Unlock();
|
||||||
|
|
||||||
|
SDL_AtomicSetPtr((void**)&m_OverlayVertexBuffers[type], newVertexBuffer);
|
||||||
SDL_AtomicSetPtr((void**)&m_OverlayTextures[type], newTexture);
|
SDL_AtomicSetPtr((void**)&m_OverlayTextures[type], newTexture);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -851,9 +907,9 @@ void DXVA2Renderer::renderOverlay(Overlay::OverlayType type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
IDirect3DTexture9* overlayTexture = (IDirect3DTexture9*)SDL_AtomicGetPtr((void**)&m_OverlayTextures[type]);
|
IDirect3DTexture9* overlayTexture = (IDirect3DTexture9*)SDL_AtomicGetPtr((void**)&m_OverlayTextures[type]);
|
||||||
SDL_Surface* overlaySurface = (SDL_Surface*)SDL_AtomicGetPtr((void**)&m_OverlaySurfaces[type]);
|
IDirect3DVertexBuffer9* overlayVertexBuffer = (IDirect3DVertexBuffer9*)SDL_AtomicGetPtr((void**)&m_OverlayVertexBuffers[type]);
|
||||||
|
|
||||||
if (overlayTexture != nullptr && overlaySurface != nullptr) {
|
if (overlayTexture != nullptr && overlayVertexBuffer != nullptr) {
|
||||||
hr = m_Device->SetTexture(0, overlayTexture);
|
hr = m_Device->SetTexture(0, overlayTexture);
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
@ -862,34 +918,18 @@ void DXVA2Renderer::renderOverlay(Overlay::OverlayType type)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_FRect renderRect = {};
|
hr = m_Device->SetStreamSource(0, overlayVertexBuffer, 0, sizeof(VERTEX));
|
||||||
|
|
||||||
if (type == Overlay::OverlayStatusUpdate) {
|
|
||||||
// Bottom Left
|
|
||||||
renderRect.x = 0;
|
|
||||||
renderRect.y = m_DisplayHeight - overlaySurface->h;
|
|
||||||
}
|
|
||||||
else if (type == Overlay::OverlayDebug) {
|
|
||||||
// Top left
|
|
||||||
renderRect.x = 0;
|
|
||||||
renderRect.y = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
renderRect.w = overlaySurface->w;
|
|
||||||
renderRect.h = overlaySurface->h;
|
|
||||||
|
|
||||||
VERTEX verts[] =
|
|
||||||
{
|
|
||||||
{renderRect.x, renderRect.y, 0, 1, 0, 0},
|
|
||||||
{renderRect.x, renderRect.y+renderRect.h, 0, 1, 0, 1},
|
|
||||||
{renderRect.x+renderRect.w, renderRect.y+renderRect.h, 0, 1, 1, 1},
|
|
||||||
{renderRect.x+renderRect.w, renderRect.y, 0, 1, 1, 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
hr = m_Device->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, verts, sizeof(VERTEX));
|
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
"DrawPrimitiveUP() failed: %x",
|
"SetStreamSource() failed: %x",
|
||||||
|
hr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr = m_Device->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2);
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
|
"DrawPrimitive() failed: %x",
|
||||||
hr);
|
hr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,7 @@ private:
|
|||||||
int m_SurfacesUsed;
|
int m_SurfacesUsed;
|
||||||
AVBufferPool* m_Pool;
|
AVBufferPool* m_Pool;
|
||||||
|
|
||||||
SDL_Surface* m_OverlaySurfaces[Overlay::OverlayMax];
|
IDirect3DVertexBuffer9* m_OverlayVertexBuffers[Overlay::OverlayMax];
|
||||||
IDirect3DTexture9* m_OverlayTextures[Overlay::OverlayMax];
|
IDirect3DTexture9* m_OverlayTextures[Overlay::OverlayMax];
|
||||||
|
|
||||||
IDirect3DDevice9Ex* m_Device;
|
IDirect3DDevice9Ex* m_Device;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user