diff --git a/src/d3d9/d3d9_device.cpp b/src/d3d9/d3d9_device.cpp index a98454c..7cbb03d 100644 --- a/src/d3d9/d3d9_device.cpp +++ b/src/d3d9/d3d9_device.cpp @@ -891,11 +891,60 @@ namespace dxup { HRESULT STDMETHODCALLTYPE Direct3DDevice9Ex::UpdateSurface(IDirect3DSurface9* pSourceSurface, CONST RECT* pSourceRect, IDirect3DSurface9* pDestinationSurface, CONST POINT* pDestPoint) { CriticalSection cs(this); - RECT destRect; - destRect.left = pDestPoint ? pDestPoint->x : 0; - destRect.top = pDestPoint ? pDestPoint->y : 0; + Direct3DSurface9* src = reinterpret_cast(pSourceSurface); + Direct3DSurface9* dst = reinterpret_cast(pDestinationSurface); + + if (src == nullptr) + return log::d3derr(D3DERR_INVALIDCALL, "UpdateSurface: src was nullptr."); + + if (dst == nullptr) + return log::d3derr(D3DERR_INVALIDCALL, "UpdateSurface: dst was nullptr."); + + D3DSURFACE_DESC srcDesc; + D3DSURFACE_DESC dstDesc; + pSourceSurface->GetDesc(&srcDesc); + pDestinationSurface->GetDesc(&dstDesc); + + D3D11_BOX srcBox; + srcBox.front = 0; + srcBox.back = 1; + + UINT dstX = 0; + UINT dstY = 0; + + if (pSourceRect != nullptr) { + srcBox.left = pSourceRect->left; + srcBox.top = pSourceRect->top; + srcBox.right = pSourceRect->right; + srcBox.bottom = pSourceRect->bottom; + + } + else { + srcBox.left = 0; + srcBox.top = 0; + srcBox.right = srcDesc.Width; + srcBox.bottom = srcDesc.Height; + } + + if (pDestPoint != nullptr) { + dstX = pDestPoint->x; + dstY = pDestPoint->y; + } + + if (!src->isBoxValid(&srcBox)) + return log::d3derr(D3DERR_INVALIDCALL, "UpdateSurface: box was invalid."); + + if (srcDesc.MultiSampleType != D3DMULTISAMPLE_NONE) + return log::d3derr(D3DERR_INVALIDCALL, "UpdateSurface: src has multisampling."); + + if (dstDesc.MultiSampleType != D3DMULTISAMPLE_NONE) + return log::d3derr(D3DERR_INVALIDCALL, "UpdateSurface: dst has multisampling."); + + if (srcDesc.Format != dstDesc.Format) + return log::d3derr(D3DERR_INVALIDCALL, "UpdateSurface: src format is not the same as dst format."); - StretchRect(pSourceSurface, pSourceRect, pDestinationSurface, pDestPoint ? &destRect : nullptr, D3DTEXF_NONE); + // TODO: do we need to do staging here too? Look into this. + m_context->CopySubresourceRegion(dst->GetDXUPResource()->GetResource(), dst->GetSubresource(), dstX, dstY, 0, src->GetDXUPResource()->GetResource(), src->GetSubresource(), &srcBox); return D3D_OK; } diff --git a/src/d3d9/d3d9_surface.cpp b/src/d3d9/d3d9_surface.cpp index 1216191..40872e6 100644 --- a/src/d3d9/d3d9_surface.cpp +++ b/src/d3d9/d3d9_surface.cpp @@ -185,5 +185,36 @@ namespace dxup { if (config::getBool(config::GDICompatible)) resource->GetResource()->QueryInterface(__uuidof(IDXGISurface1), (void**)&m_surface); } + bool Direct3DSurface9::isRectValid(const RECT* rect) { + if (rect == nullptr) + return true; + if (rect->right <= rect->left || rect->bottom <= rect->top) + return false; + + if (rect->left < 0 || rect->top < 0) + return false; + + D3DSURFACE_DESC desc; + this->GetDesc(&desc); + if (rect->right > (int)desc.Width || rect->bottom > desc.Height) + return false; + + return true; + } + + bool Direct3DSurface9::isBoxValid(const D3D11_BOX* box) { + if (box == nullptr) + return true; + + if (box->front != 0 || box->back != 1) + return false; + + RECT rect; + rect.left = box->left; + rect.top = box->top; + rect.right = box->right; + rect.bottom = box->bottom; + return this->isRectValid(&rect); + } } \ No newline at end of file diff --git a/src/d3d9/d3d9_surface.h b/src/d3d9/d3d9_surface.h index d267589..9ace493 100644 --- a/src/d3d9/d3d9_surface.h +++ b/src/d3d9/d3d9_surface.h @@ -39,6 +39,9 @@ namespace dxup { void ClearResource(); void SetResource(DXUPResource* resource); + bool isRectValid(const RECT* rect); + bool isBoxValid(const D3D11_BOX* box); + private: IUnknown* m_container;