1
0
mirror of https://github.com/narzoul/DDrawCompat synced 2024-12-30 08:55:36 +01:00

Handle resolution scaling in windowed mode

This commit is contained in:
narzoul 2022-06-05 15:08:53 +02:00
parent 96ad1d6ab6
commit fc16184256
7 changed files with 118 additions and 21 deletions

View File

@ -1038,19 +1038,22 @@ namespace D3dDdi
{
if (srcResource->m_lockResource)
{
if (srcResource->m_lockData[0].isSysMemUpToDate &&
if (srcResource->m_lockData[data.SrcSubResourceIndex].isSysMemUpToDate &&
!srcResource->m_fixedData.Flags.RenderTarget)
{
srcResource->m_lockData[0].isVidMemUpToDate = false;
srcResource->m_lockData[data.SrcSubResourceIndex].isVidMemUpToDate = false;
}
srcResource = &srcResource->prepareForGpuRead(0);
srcResource = &srcResource->prepareForGpuRead(data.SrcSubResourceIndex);
}
LONG srcWidth = srcResource->m_fixedData.pSurfList[0].Width;
LONG srcHeight = srcResource->m_fixedData.pSurfList[0].Height;
LONG srcWidth = srcResource->m_fixedData.pSurfList[data.SrcSubResourceIndex].Width;
LONG srcHeight = srcResource->m_fixedData.pSurfList[data.SrcSubResourceIndex].Height;
data.SrcRect = { 0, 0, srcWidth, srcHeight };
data.DstRect = g_presentationRect;
if (!IsRectEmpty(&g_presentationRect))
{
data.DstRect = g_presentationRect;
}
auto& repo = SurfaceRepository::get(m_device.getAdapter());
const auto& rtSurface = repo.getTempRenderTarget(srcWidth, srcHeight);
@ -1078,14 +1081,18 @@ namespace D3dDdi
pal[i].rgbGreen = entries[i].peGreen;
pal[i].rgbBlue = entries[i].peBlue;
}
m_device.getShaderBlitter().palettizedBlt(*rt, rtIndex, rtRect, *srcResource, data.SrcRect, pal);
m_device.getShaderBlitter().palettizedBlt(
*rt, rtIndex, rtRect, *srcResource, data.SrcSubResourceIndex, data.SrcRect, pal);
}
else
{
copySubResourceRegion(*rt, rtIndex, rtRect, *srcResource, 0, data.SrcRect);
copySubResourceRegion(*rt, rtIndex, rtRect, *srcResource, data.SrcSubResourceIndex, data.SrcRect);
}
presentLayeredWindows(*rt, rtIndex, rtRect);
if (!IsRectEmpty(&g_presentationRect))
{
presentLayeredWindows(*rt, rtIndex, rtRect);
}
const auto cursorInfo = Gdi::Cursor::getEmulatedCursorInfo();
const bool isCursorEmulated = cursorInfo.flags == CURSOR_SHOWING && cursorInfo.hCursor;

View File

@ -45,6 +45,7 @@ namespace D3dDdi
void prepareForCpuWrite(UINT subResourceIndex);
Resource& prepareForGpuRead(UINT subResourceIndex);
void prepareForGpuWrite(UINT subResourceIndex);
HRESULT presentationBlt(D3DDDIARG_BLT data, Resource* srcResource);
void scaleRect(RECT& rect);
void setAsGdiResource(bool isGdiResource);
void setAsPrimary();
@ -106,7 +107,6 @@ namespace D3dDdi
void loadSysMemResource(UINT subResourceIndex);
void loadVidMemResource(UINT subResourceIndex);
void notifyLock(UINT subResourceIndex);
HRESULT presentationBlt(D3DDDIARG_BLT data, Resource* srcResource);
void presentLayeredWindows(Resource& dst, UINT dstSubResourceIndex, const RECT& dstRect);
HRESULT shaderBlt(D3DDDIARG_BLT& data, Resource& dstResource, Resource& srcResource);

View File

@ -317,10 +317,11 @@ namespace D3dDdi
}
void ShaderBlitter::palettizedBlt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
const Resource& srcResource, const RECT& srcRect, RGBQUAD palette[256])
const Resource& srcResource, UINT srcSubResourceIndex, const RECT& srcRect, RGBQUAD palette[256])
{
LOG_FUNC("ShaderBlitter::palettizedBlt", static_cast<HANDLE>(dstResource), dstSubResourceIndex, dstRect,
static_cast<HANDLE>(srcResource), srcRect, Compat::array(reinterpret_cast<void**>(palette), 256));
static_cast<HANDLE>(srcResource), srcSubResourceIndex, srcRect,
Compat::array(reinterpret_cast<void**>(palette), 256));
auto paletteTexture(SurfaceRepository::get(m_device.getAdapter()).getPaletteTexture());
if (!paletteTexture)
@ -344,7 +345,8 @@ namespace D3dDdi
m_device.getOrigVtable().pfnUnlock(m_device, &unlock);
setTempTextureStage(1, *paletteTexture, srcRect, D3DTEXF_POINT);
blt(dstResource, dstSubResourceIndex, dstRect, srcResource, 0, srcRect, m_psPaletteLookup.get(), D3DTEXF_POINT);
blt(dstResource, dstSubResourceIndex, dstRect, srcResource, srcSubResourceIndex, srcRect,
m_psPaletteLookup.get(), D3DTEXF_POINT);
}
void ShaderBlitter::resetGammaRamp()

View File

@ -34,7 +34,7 @@ namespace D3dDdi
const Resource& srcResource, UINT srcSubResourceIndex, const RECT& srcRect,
const Resource& lockRefResource);
void palettizedBlt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
const Resource& srcResource, const RECT& srcRect, RGBQUAD palette[256]);
const Resource& srcResource, UINT srcSubResourceIndex, const RECT& srcRect, RGBQUAD palette[256]);
void textureBlt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
const Resource& srcResource, UINT srcSubResourceIndex, const RECT& srcRect,
UINT filter, const UINT* srcColorKey = nullptr, const BYTE* alpha = nullptr,

View File

@ -9,12 +9,16 @@
#include <Config/Config.h>
#include <D3dDdi/Device.h>
#include <D3dDdi/KernelModeThunks.h>
#include <D3dDdi/Resource.h>
#include <D3dDdi/ScopedCriticalSection.h>
#include <D3dDdi/SurfaceRepository.h>
#include <DDraw/DirectDraw.h>
#include <DDraw/DirectDrawSurface.h>
#include <DDraw/IReleaseNotifier.h>
#include <DDraw/RealPrimarySurface.h>
#include <DDraw/ScopedThreadLock.h>
#include <DDraw/Surfaces/PrimarySurface.h>
#include <DDraw/Surfaces/TagSurface.h>
#include <DDraw/Types.h>
#include <Gdi/Caret.h>
#include <Gdi/Cursor.h>
@ -34,6 +38,7 @@ namespace
void onRelease();
CompatWeakPtr<IDirectDrawSurface7> g_frontBuffer;
CompatWeakPtr<IDirectDrawSurface7> g_windowedBackBuffer;
CompatWeakPtr<IDirectDrawClipper> g_clipper;
RECT g_monitorRect = {};
DDSURFACEDESC2 g_surfaceDesc = {};
@ -65,7 +70,24 @@ namespace
{
if (!g_isFullscreen)
{
Gdi::Window::present(*g_frontBuffer, src, *g_clipper);
{
D3dDdi::ScopedCriticalSection lock;
auto srcResource = D3dDdi::Device::findResource(
DDraw::DirectDrawSurface::getDriverResourceHandle(src.get()));
auto bbResource = D3dDdi::Device::findResource(
DDraw::DirectDrawSurface::getDriverResourceHandle(*g_windowedBackBuffer));
D3DDDIARG_BLT blt = {};
blt.hSrcResource = *srcResource;
blt.SrcSubResourceIndex = DDraw::DirectDrawSurface::getSubResourceIndex(src.get());
blt.SrcRect = DDraw::PrimarySurface::getMonitorRect();
blt.hDstResource = *bbResource;
blt.DstSubResourceIndex = 0;
blt.DstRect = g_monitorRect;
bbResource->presentationBlt(blt, srcResource);
}
Gdi::Window::present(*g_frontBuffer, *g_windowedBackBuffer, *g_clipper);
return;
}
@ -76,6 +98,48 @@ namespace
}
}
CompatPtr<IDirectDrawSurface7> createWindowedBackBuffer(DDRAWI_DIRECTDRAW_LCL* ddLcl, DWORD width, DWORD height)
{
if (!ddLcl)
{
LOG_INFO << "ERROR: createWindowedBackBuffer: ddLcl is null";
return nullptr;
}
auto tagSurface = DDraw::TagSurface::get(ddLcl);
if (!tagSurface)
{
LOG_INFO << "ERROR: createWindowedBackBuffer: TagSurface not found";
return nullptr;
}
auto resource = DDraw::DirectDrawSurface::getDriverResourceHandle(*tagSurface->getDDS());
if (!resource)
{
LOG_INFO << "ERROR: createWindowedBackBuffer: driver resource handle not found";
return nullptr;
}
auto device = D3dDdi::Device::findDeviceByResource(resource);
if (!device)
{
LOG_INFO << "ERROR: createWindowedBackBuffer: device not found";
return nullptr;
}
auto& repo = D3dDdi::SurfaceRepository::get(device->getAdapter());
D3dDdi::SurfaceRepository::Surface surface = {};
repo.getSurface(surface, width, height, DDraw::DirectDraw::getRgbPixelFormat(32),
DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY);
if (!surface.surface)
{
LOG_INFO << "ERROR: createWindowedBackBuffer: surface creation failed";
return nullptr;
}
return surface.surface;
}
CompatPtr<IDirectDrawSurface7> getBackBuffer()
{
DDSCAPS2 caps = {};
@ -133,6 +197,7 @@ namespace
g_frontBuffer = nullptr;
g_lastFlipSurface = nullptr;
g_windowedBackBuffer.release();
g_clipper.release();
g_isFullscreen = false;
g_surfaceDesc = {};
@ -164,6 +229,11 @@ namespace
D3dDdi::KernelModeThunks::waitForVsyncCounter(D3dDdi::KernelModeThunks::getVsyncCounter() + 1);
}
if (g_windowedBackBuffer)
{
g_windowedBackBuffer->Restore(g_windowedBackBuffer);
}
Compat::ScopedCriticalSection lock(g_presentCs);
g_isUpdatePending = false;
g_isUpdateReady = false;
@ -204,11 +274,7 @@ namespace
Gdi::Region excludeRegion(DDraw::PrimarySurface::getMonitorRect());
Gdi::Window::present(excludeRegion);
auto palette(Gdi::Palette::getHardwarePalette());
D3dDdi::KernelModeThunks::setDcPaletteOverride(palette.data());
bltToPrimaryChain(*src);
D3dDdi::KernelModeThunks::setDcPaletteOverride(nullptr);
}
void updateNow(CompatWeakPtr<IDirectDrawSurface7> src)
@ -282,6 +348,17 @@ namespace DDraw
return result;
}
if (0 == desc.dwBackBufferCount)
{
g_windowedBackBuffer = createWindowedBackBuffer(DDraw::DirectDraw::getInt(dd.get()).lpLcl,
g_monitorRect.right - g_monitorRect.left, g_monitorRect.bottom - g_monitorRect.top).detach();
if (!g_windowedBackBuffer)
{
g_monitorRect = {};
return DDERR_GENERIC;
}
}
g_frontBuffer = CompatPtr<IDirectDrawSurface7>::from(surface.get()).detach();
g_frontBuffer->SetPrivateData(g_frontBuffer, IID_IReleaseNotifier,
&g_releaseNotifier, sizeof(&g_releaseNotifier), DDSPD_IUNKNOWNPOINTER);

View File

@ -67,14 +67,24 @@ namespace DDraw
}
}
TagSurface* TagSurface::get(CompatRef<IDirectDraw> dd)
TagSurface* TagSurface::get(DDRAWI_DIRECTDRAW_LCL* ddLcl)
{
auto ddLcl = DDraw::DirectDraw::getInt(dd.get()).lpLcl;
auto it = g_ddObjects.find(ddLcl);
if (it != g_ddObjects.end())
{
return it->second;
}
return nullptr;
}
TagSurface* TagSurface::get(CompatRef<IDirectDraw> dd)
{
auto ddLcl = DDraw::DirectDraw::getInt(dd.get()).lpLcl;
auto tagSurface = get(ddLcl);
if (tagSurface)
{
return tagSurface;
}
if (FAILED(create(dd)))
{

View File

@ -15,6 +15,7 @@ namespace DDraw
TagSurface(DWORD origCaps, DDRAWI_DIRECTDRAW_LCL* ddLcl);
virtual ~TagSurface() override;
static TagSurface* get(DDRAWI_DIRECTDRAW_LCL* ddLcl);
static TagSurface* get(CompatRef<IDirectDraw> dd);
static TagSurface* findFullscreenWindow(HWND hwnd);