diff --git a/src/d3d9/d3d9_format.h b/src/d3d9/d3d9_format.h index 617c2adc8..43d26553c 100644 --- a/src/d3d9/d3d9_format.h +++ b/src/d3d9/d3d9_format.h @@ -255,4 +255,16 @@ namespace dxvk { || format == D3D9Format::DXT5; } + // D3D9 documentation says: IDirect3DSurface9::GetDC is valid on the following formats only: + // D3DFMT_R5G6B5, D3DFMT_X1R5G5B5, D3DFMT_R8G8B8, and D3DFMT_X8R8G8B8. However, + // the equivalent formats of D3DFMT_A1R5G5B5 and D3DFMT_A8R8G8B8 are also supported. + inline bool IsSurfaceGetDCCompatibleFormat(D3D9Format format) { + return format == D3D9Format::R5G6B5 + || format == D3D9Format::X1R5G5B5 + || format == D3D9Format::A1R5G5B5 + || format == D3D9Format::R8G8B8 + || format == D3D9Format::X8R8G8B8 + || format == D3D9Format::A8R8G8B8; + } + } diff --git a/src/d3d9/d3d9_surface.cpp b/src/d3d9/d3d9_surface.cpp index dde921e5b..2290bfcf6 100644 --- a/src/d3d9/d3d9_surface.cpp +++ b/src/d3d9/d3d9_surface.cpp @@ -71,7 +71,7 @@ namespace dxvk { } HRESULT STDMETHODCALLTYPE D3D9Surface::QueryInterface(REFIID riid, void** ppvObject) { - if (ppvObject == nullptr) + if (unlikely(ppvObject == nullptr)) return E_POINTER; *ppvObject = nullptr; @@ -101,7 +101,7 @@ namespace dxvk { } HRESULT STDMETHODCALLTYPE D3D9Surface::GetDesc(D3DSURFACE_DESC *pDesc) { - if (pDesc == nullptr) + if (unlikely(pDesc == nullptr)) return D3DERR_INVALIDCALL; auto& desc = *(m_texture->Desc()); @@ -190,11 +190,14 @@ namespace dxvk { } HRESULT STDMETHODCALLTYPE D3D9Surface::GetDC(HDC *phDC) { - if (phDC == nullptr) + if (unlikely(phDC == nullptr)) return D3DERR_INVALIDCALL; const D3D9_COMMON_TEXTURE_DESC& desc = *m_texture->Desc(); + if (unlikely(!IsSurfaceGetDCCompatibleFormat(desc.Format))) + return D3DERR_INVALIDCALL; + D3DLOCKED_RECT lockedRect; HRESULT hr = LockRect(&lockedRect, nullptr, 0); if (FAILED(hr)) @@ -228,7 +231,7 @@ namespace dxvk { } HRESULT STDMETHODCALLTYPE D3D9Surface::ReleaseDC(HDC hDC) { - if (m_dcDesc.hDC == nullptr || m_dcDesc.hDC != hDC) + if (unlikely(m_dcDesc.hDC == nullptr || m_dcDesc.hDC != hDC)) return D3DERR_INVALIDCALL; D3DKMTDestroyDCFromMemory(&m_dcDesc);