mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-01-31 14:52:11 +01:00
[d3d8] Slightly clean up CopyRects
This commit is contained in:
parent
5f9ca08071
commit
a7ae5999a9
@ -562,11 +562,11 @@ namespace dxvk {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief D3D8 CopyRects implementation
|
* \brief D3D8 CopyRects implementation
|
||||||
*
|
*
|
||||||
* \details
|
* \details
|
||||||
* The following table shows the possible combinations of source
|
* The following table shows the possible combinations of source
|
||||||
* and destination surface pools, and how we handle each of them.
|
* and destination surface pools, and how we handle each of them.
|
||||||
*
|
*
|
||||||
* ┌────────────┬───────────────────────────┬───────────────────────┬───────────────────────┬──────────┐
|
* ┌────────────┬───────────────────────────┬───────────────────────┬───────────────────────┬──────────┐
|
||||||
* │ Src/Dst │ DEFAULT │ MANAGED │ SYSTEMMEM │ SCRATCH │
|
* │ Src/Dst │ DEFAULT │ MANAGED │ SYSTEMMEM │ SCRATCH │
|
||||||
* ├────────────┼───────────────────────────┼───────────────────────┼───────────────────────┼──────────┤
|
* ├────────────┼───────────────────────────┼───────────────────────┼───────────────────────┼──────────┤
|
||||||
@ -587,7 +587,7 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: No format conversion, no stretching, no clipping.
|
// TODO: No format conversion, no stretching, no clipping.
|
||||||
// All src/dest rectangles must fit within the dest surface.
|
// All src/dest rectangles must fit within the dest surface.
|
||||||
|
|
||||||
Com<D3D8Surface> src = static_cast<D3D8Surface*>(pSourceSurface);
|
Com<D3D8Surface> src = static_cast<D3D8Surface*>(pSourceSurface);
|
||||||
Com<D3D8Surface> dst = static_cast<D3D8Surface*>(pDestinationSurface);
|
Com<D3D8Surface> dst = static_cast<D3D8Surface*>(pDestinationSurface);
|
||||||
@ -618,8 +618,6 @@ namespace dxvk {
|
|||||||
pDestPointsArray = &point;
|
pDestPointsArray = &point;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT res = D3DERR_INVALIDCALL;
|
|
||||||
|
|
||||||
for (UINT i = 0; i < cRects; i++) {
|
for (UINT i = 0; i < cRects; i++) {
|
||||||
|
|
||||||
RECT srcRect, dstRect;
|
RECT srcRect, dstRect;
|
||||||
@ -639,10 +637,10 @@ namespace dxvk {
|
|||||||
dstRect.bottom = dstRect.top + (srcRect.bottom - srcRect.top);
|
dstRect.bottom = dstRect.top + (srcRect.bottom - srcRect.top);
|
||||||
asymmetric = dstRect.left != srcRect.left || dstRect.top != srcRect.top
|
asymmetric = dstRect.left != srcRect.left || dstRect.top != srcRect.top
|
||||||
|| dstRect.right != srcRect.right || dstRect.bottom != srcRect.bottom;
|
|| dstRect.right != srcRect.right || dstRect.bottom != srcRect.bottom;
|
||||||
|
|
||||||
stretch = (dstRect.right-dstRect.left) != (srcRect.right-srcRect.left)
|
stretch = (dstRect.right-dstRect.left) != (srcRect.right-srcRect.left)
|
||||||
|| (dstRect.bottom-dstRect.top) != (srcRect.bottom-srcRect.top);
|
|| (dstRect.bottom-dstRect.top) != (srcRect.bottom-srcRect.top);
|
||||||
|
|
||||||
offset = !stretch && asymmetric;
|
offset = !stretch && asymmetric;
|
||||||
} else {
|
} else {
|
||||||
dstRect = srcRect;
|
dstRect = srcRect;
|
||||||
@ -651,102 +649,103 @@ namespace dxvk {
|
|||||||
|
|
||||||
POINT dstPt = { dstRect.left, dstRect.top };
|
POINT dstPt = { dstRect.left, dstRect.top };
|
||||||
|
|
||||||
res = D3DERR_INVALIDCALL;
|
|
||||||
|
|
||||||
auto unhandled = [&] {
|
auto unhandled = [&] {
|
||||||
Logger::debug(str::format("CopyRects: Hit unhandled case from src pool ", srcDesc.Pool, " to dst pool ", dstDesc.Pool));
|
Logger::warn(str::format("CopyRects: Hit unhandled case from src pool ", srcDesc.Pool, " to dst pool ", dstDesc.Pool));
|
||||||
return D3DERR_INVALIDCALL;
|
return D3DERR_INVALIDCALL;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
auto logError = [&] (HRESULT res) {
|
||||||
|
if (FAILED(res)) {
|
||||||
|
// Only a debug message because some games mess up CopyRects every frame in a way
|
||||||
|
// that fails on native too but are perfectly fine with it.
|
||||||
|
Logger::debug(str::format("CopyRects: FAILED to copy from src pool ", srcDesc.Pool, " to dst pool ", dstDesc.Pool));
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
};
|
||||||
|
|
||||||
switch (dstDesc.Pool) {
|
switch (dstDesc.Pool) {
|
||||||
|
|
||||||
// Dest: DEFAULT
|
// Dest: DEFAULT
|
||||||
case D3DPOOL_DEFAULT:
|
case d3d9::D3DPOOL_DEFAULT:
|
||||||
switch (srcDesc.Pool) {
|
switch (srcDesc.Pool) {
|
||||||
case D3DPOOL_DEFAULT: {
|
case d3d9::D3DPOOL_DEFAULT: {
|
||||||
// DEFAULT -> DEFAULT: use StretchRect
|
// DEFAULT -> DEFAULT: use StretchRect
|
||||||
res = GetD3D9()->StretchRect(
|
return logError(GetD3D9()->StretchRect(
|
||||||
src->GetD3D9(),
|
src->GetD3D9(),
|
||||||
&srcRect,
|
&srcRect,
|
||||||
dst->GetD3D9(),
|
dst->GetD3D9(),
|
||||||
&dstRect,
|
&dstRect,
|
||||||
d3d9::D3DTEXF_NONE
|
d3d9::D3DTEXF_NONE
|
||||||
);
|
));
|
||||||
goto done;
|
|
||||||
}
|
}
|
||||||
case D3DPOOL_MANAGED: {
|
case d3d9::D3DPOOL_MANAGED: {
|
||||||
// MANAGED -> DEFAULT: UpdateTextureFromBuffer
|
// MANAGED -> DEFAULT: UpdateTextureFromBuffer
|
||||||
res = m_bridge->UpdateTextureFromBuffer(
|
return logError(m_bridge->UpdateTextureFromBuffer(
|
||||||
src->GetD3D9(),
|
src->GetD3D9(),
|
||||||
dst->GetD3D9(),
|
dst->GetD3D9(),
|
||||||
&srcRect,
|
&srcRect,
|
||||||
&dstPt
|
&dstPt
|
||||||
);
|
));
|
||||||
goto done;
|
|
||||||
}
|
}
|
||||||
case D3DPOOL_SYSTEMMEM: {
|
case d3d9::D3DPOOL_SYSTEMMEM: {
|
||||||
// SYSTEMMEM -> DEFAULT: use UpdateSurface
|
// SYSTEMMEM -> DEFAULT: use UpdateSurface
|
||||||
res = GetD3D9()->UpdateSurface(
|
return logError(GetD3D9()->UpdateSurface(
|
||||||
src->GetD3D9(),
|
src->GetD3D9(),
|
||||||
&srcRect,
|
&srcRect,
|
||||||
dst->GetD3D9(),
|
dst->GetD3D9(),
|
||||||
&dstPt
|
&dstPt
|
||||||
);
|
));
|
||||||
goto done;
|
|
||||||
}
|
}
|
||||||
case D3DPOOL_SCRATCH:
|
case d3d9::D3DPOOL_SCRATCH:
|
||||||
default: {
|
default: {
|
||||||
// TODO: Unhandled case.
|
// TODO: Unhandled case.
|
||||||
return unhandled();
|
return unhandled();
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
// Dest: MANAGED
|
// Dest: MANAGED
|
||||||
case D3DPOOL_MANAGED:
|
case d3d9::D3DPOOL_MANAGED:
|
||||||
switch (srcDesc.Pool) {
|
switch (srcDesc.Pool) {
|
||||||
case D3DPOOL_DEFAULT: {
|
case d3d9::D3DPOOL_DEFAULT: {
|
||||||
// TODO: Copy on GPU (handle MANAGED similarly to SYSTEMMEM for now)
|
// TODO: Copy on GPU (handle MANAGED similarly to SYSTEMMEM for now)
|
||||||
|
|
||||||
// Get temporary off-screen surface for stretching.
|
// Get temporary off-screen surface for stretching.
|
||||||
Com<d3d9::IDirect3DSurface9> pBlitImage = dst->GetBlitImage();
|
Com<d3d9::IDirect3DSurface9> pBlitImage = dst->GetBlitImage();
|
||||||
|
|
||||||
// Stretch the source RT to the temporary surface.
|
// Stretch the source RT to the temporary surface.
|
||||||
res = GetD3D9()->StretchRect(
|
HRESULT res = GetD3D9()->StretchRect(
|
||||||
src->GetD3D9(),
|
src->GetD3D9(),
|
||||||
&srcRect,
|
&srcRect,
|
||||||
pBlitImage.ptr(),
|
pBlitImage.ptr(),
|
||||||
&dstRect,
|
&dstRect,
|
||||||
d3d9::D3DTEXF_NONE);
|
d3d9::D3DTEXF_NONE);
|
||||||
|
|
||||||
if (FAILED(res)) {
|
if (FAILED(res)) {
|
||||||
goto done;
|
return logError(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now sync the rendertarget data into main memory.
|
// Now sync the rendertarget data into main memory.
|
||||||
res = GetD3D9()->GetRenderTargetData(pBlitImage.ptr(), dst->GetD3D9());
|
return logError(GetD3D9()->GetRenderTargetData(pBlitImage.ptr(), dst->GetD3D9()));
|
||||||
goto done;
|
|
||||||
}
|
}
|
||||||
case D3DPOOL_MANAGED:
|
case d3d9::D3DPOOL_MANAGED:
|
||||||
case D3DPOOL_SYSTEMMEM: {
|
case d3d9::D3DPOOL_SYSTEMMEM: {
|
||||||
// SYSTEMMEM -> MANAGED: LockRect / memcpy
|
// SYSTEMMEM -> MANAGED: LockRect / memcpy
|
||||||
|
|
||||||
if (stretch) {
|
if (stretch) {
|
||||||
res = D3DERR_INVALIDCALL;
|
return logError(D3DERR_INVALIDCALL);
|
||||||
goto done;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
res = copyTextureBuffers(src.ptr(), dst.ptr(), srcDesc, dstDesc, srcRect, dstRect);
|
return logError(copyTextureBuffers(src.ptr(), dst.ptr(), srcDesc, dstDesc, srcRect, dstRect));
|
||||||
|
|
||||||
goto done;
|
|
||||||
}
|
}
|
||||||
case D3DPOOL_SCRATCH:
|
case d3d9::D3DPOOL_SCRATCH:
|
||||||
default: {
|
default: {
|
||||||
// TODO: Unhandled case.
|
// TODO: Unhandled case.
|
||||||
return unhandled();
|
return unhandled();
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
// DEST: SYSTEMMEM
|
// DEST: SYSTEMMEM
|
||||||
case D3DPOOL_SYSTEMMEM: {
|
case d3d9::D3DPOOL_SYSTEMMEM: {
|
||||||
|
|
||||||
// RT (DEFAULT) -> SYSTEMMEM: Use GetRenderTargetData as fast path if possible
|
// RT (DEFAULT) -> SYSTEMMEM: Use GetRenderTargetData as fast path if possible
|
||||||
if ((srcDesc.Usage & D3DUSAGE_RENDERTARGET || m_renderTarget.ptr() == src.ptr())) {
|
if ((srcDesc.Usage & D3DUSAGE_RENDERTARGET || m_renderTarget.ptr() == src.ptr())) {
|
||||||
@ -757,44 +756,40 @@ namespace dxvk {
|
|||||||
&& srcDesc.Height == dstDesc.Height
|
&& srcDesc.Height == dstDesc.Height
|
||||||
&& srcDesc.Format == dstDesc.Format
|
&& srcDesc.Format == dstDesc.Format
|
||||||
&& !asymmetric) {
|
&& !asymmetric) {
|
||||||
res = GetD3D9()->GetRenderTargetData(src->GetD3D9(), dst->GetD3D9());
|
return logError(GetD3D9()->GetRenderTargetData(src->GetD3D9(), dst->GetD3D9()));
|
||||||
goto done;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (srcDesc.Pool) {
|
switch (srcDesc.Pool) {
|
||||||
case D3DPOOL_DEFAULT: {
|
case d3d9::D3DPOOL_DEFAULT: {
|
||||||
// Get temporary off-screen surface for stretching.
|
// Get temporary off-screen surface for stretching.
|
||||||
Com<d3d9::IDirect3DSurface9> pBlitImage = dst->GetBlitImage();
|
Com<d3d9::IDirect3DSurface9> pBlitImage = dst->GetBlitImage();
|
||||||
|
|
||||||
// Stretch the source RT to the temporary surface.
|
// Stretch the source RT to the temporary surface.
|
||||||
res = GetD3D9()->StretchRect(
|
HRESULT res = GetD3D9()->StretchRect(
|
||||||
src->GetD3D9(),
|
src->GetD3D9(),
|
||||||
&srcRect,
|
&srcRect,
|
||||||
pBlitImage.ptr(),
|
pBlitImage.ptr(),
|
||||||
&dstRect,
|
&dstRect,
|
||||||
d3d9::D3DTEXF_NONE);
|
d3d9::D3DTEXF_NONE);
|
||||||
if (FAILED(res)) {
|
if (FAILED(res)) {
|
||||||
goto done;
|
return logError(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now sync the rendertarget data into main memory.
|
// Now sync the rendertarget data into main memory.
|
||||||
res = GetD3D9()->GetRenderTargetData(pBlitImage.ptr(), dst->GetD3D9());
|
return logError(GetD3D9()->GetRenderTargetData(pBlitImage.ptr(), dst->GetD3D9()));
|
||||||
goto done;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SYSMEM/MANAGED -> SYSMEM: LockRect / memcpy
|
// SYSMEM/MANAGED -> SYSMEM: LockRect / memcpy
|
||||||
case D3DPOOL_MANAGED:
|
case d3d9::D3DPOOL_MANAGED:
|
||||||
case D3DPOOL_SYSTEMMEM: {
|
case d3d9::D3DPOOL_SYSTEMMEM: {
|
||||||
if (stretch) {
|
if (stretch) {
|
||||||
res = D3DERR_INVALIDCALL;
|
return logError(D3DERR_INVALIDCALL);
|
||||||
goto done;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
res = copyTextureBuffers(src.ptr(), dst.ptr(), srcDesc, dstDesc, srcRect, dstRect);
|
return logError(copyTextureBuffers(src.ptr(), dst.ptr(), srcDesc, dstDesc, srcRect, dstRect));
|
||||||
goto done;
|
|
||||||
}
|
}
|
||||||
case D3DPOOL_SCRATCH:
|
case d3d9::D3DPOOL_SCRATCH:
|
||||||
default: {
|
default: {
|
||||||
// TODO: Unhandled case.
|
// TODO: Unhandled case.
|
||||||
return unhandled();
|
return unhandled();
|
||||||
@ -803,22 +798,15 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DEST: SCRATCH
|
// DEST: SCRATCH
|
||||||
case D3DPOOL_SCRATCH:
|
case d3d9::D3DPOOL_SCRATCH:
|
||||||
default: {
|
default: {
|
||||||
// TODO: Unhandled case.
|
// TODO: Unhandled case.
|
||||||
return unhandled();
|
return unhandled();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
|
||||||
if (FAILED(res)) {
|
|
||||||
Logger::debug(str::format("CopyRects: FAILED to copy from src pool ", srcDesc.Pool, " to dst pool ", dstDesc.Pool));
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
return D3DERR_INVALIDCALL;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT STDMETHODCALLTYPE D3D8Device::UpdateTexture(
|
HRESULT STDMETHODCALLTYPE D3D8Device::UpdateTexture(
|
||||||
|
@ -3,8 +3,6 @@
|
|||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include "../util/config/config.h"
|
#include "../util/config/config.h"
|
||||||
|
|
||||||
#include "../vulkan/vulkan_loader.h"
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The D3D9 bridge allows D3D8 to access DXVK internals.
|
* The D3D9 bridge allows D3D8 to access DXVK internals.
|
||||||
* For Vulkan interop without needing DXVK internals, see d3d9_interop.h.
|
* For Vulkan interop without needing DXVK internals, see d3d9_interop.h.
|
||||||
@ -111,7 +109,7 @@ namespace dxvk {
|
|||||||
void** ppvObject);
|
void** ppvObject);
|
||||||
|
|
||||||
const Config* GetConfig() const;
|
const Config* GetConfig() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
D3D9InterfaceEx* m_interface;
|
D3D9InterfaceEx* m_interface;
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user