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

Moved lock surface handling to UMD level

This commit is contained in:
narzoul 2019-08-11 22:29:36 +02:00
parent 9b24a9b306
commit 8cc73dc68d
7 changed files with 179 additions and 321 deletions

View File

@ -12,23 +12,6 @@ namespace
HANDLE g_gdiResourceHandle = nullptr;
D3dDdi::Resource* g_gdiResource = nullptr;
bool g_isReadOnlyGdiLockEnabled = false;
template <typename Container, typename Predicate>
void erase_if(Container& container, Predicate pred)
{
auto it = container.begin();
while (it != container.end())
{
if (pred(*it))
{
it = container.erase(it);
}
else
{
++it;
}
}
}
}
namespace D3dDdi
@ -116,15 +99,10 @@ namespace D3dDdi
HRESULT result = m_origVtable.pfnDestroyResource(m_device, resource);
if (SUCCEEDED(result))
{
erase_if(m_dirtyRenderTargets,
[=](const decltype(m_dirtyRenderTargets)::value_type& v) { return v.first.first == resource; });
erase_if(m_dirtyTextures,
[=](const decltype(m_dirtyTextures)::value_type& v) { return v.first.first == resource; });
auto it = m_resources.find(resource);
if (it != m_resources.end())
{
it->second.destroy();
it->second.destroyLockResource();
m_resources.erase(it);
}
@ -374,11 +352,23 @@ namespace D3dDdi
void Device::setGdiResourceHandle(HANDLE resource)
{
g_gdiResourceHandle = resource;
g_gdiResource = getResource(resource);
if ((!resource && !g_gdiResource) ||
(g_gdiResource && resource == *g_gdiResource))
{
return;
}
if (g_gdiResource)
{
g_gdiResource->resync();
g_gdiResource->setAsGdiResource(false);
}
g_gdiResourceHandle = resource;
g_gdiResource = getResource(resource);
if (g_gdiResource)
{
g_gdiResource->setAsGdiResource(true);
}
}

View File

@ -1,13 +1,14 @@
#include <type_traits>
#include "Common/HResultException.h"
#include "Common/Log.h"
#include "D3dDdi/Adapter.h"
#include "D3dDdi/Device.h"
#include "D3dDdi/Log/DeviceFuncsLog.h"
#include "D3dDdi/Resource.h"
#include "DDraw/Blitter.h"
#include "DDraw/Surfaces/Surface.h"
#include <Common/HResultException.h>
#include <Common/Log.h>
#include <D3dDdi/Adapter.h>
#include <D3dDdi/Device.h>
#include <D3dDdi/KernelModeThunks.h>
#include <D3dDdi/Log/DeviceFuncsLog.h>
#include <D3dDdi/Resource.h>
#include <DDraw/Blitter.h>
#include <Gdi/VirtualScreen.h>
namespace
{
@ -181,8 +182,8 @@ namespace D3dDdi
: m_device(device)
, m_handle(nullptr)
, m_origData(data)
, m_rootSurface(nullptr)
, m_lockResource(nullptr)
, m_canCreateLockResource(false)
{
}
@ -297,11 +298,11 @@ namespace D3dDdi
return LOG_RESULT(m_device.getOrigVtable().pfnColorFill(m_device, &data));
}
HRESULT Resource::copySubResource(Resource& dstResource, Resource& srcResource, UINT subResourceIndex)
HRESULT Resource::copySubResource(HANDLE dstResource, HANDLE srcResource, UINT subResourceIndex)
{
RECT rect = {};
rect.right = dstResource.m_fixedData.pSurfList[subResourceIndex].Width;
rect.bottom = dstResource.m_fixedData.pSurfList[subResourceIndex].Height;
rect.right = m_fixedData.pSurfList[subResourceIndex].Width;
rect.bottom = m_fixedData.pSurfList[subResourceIndex].Height;
D3DDDIARG_BLT data = {};
data.hSrcResource = srcResource;
@ -311,7 +312,7 @@ namespace D3dDdi
data.DstSubResourceIndex = subResourceIndex;
data.DstRect = rect;
HRESULT result = dstResource.m_device.getOrigVtable().pfnBlt(dstResource.m_device, &data);
HRESULT result = m_device.getOrigVtable().pfnBlt(m_device, &data);
if (FAILED(result))
{
LOG_ONCE("ERROR: Resource::copySubResource failed: " << Compat::hex(result));
@ -321,13 +322,97 @@ namespace D3dDdi
void Resource::copyToSysMem(UINT subResourceIndex)
{
copySubResource(*m_lockResource, *this, subResourceIndex);
copySubResource(m_lockResource, m_handle, subResourceIndex);
setSysMemUpToDate(subResourceIndex, true);
}
void Resource::createGdiLockResource()
{
auto gdiSurfaceDesc(Gdi::VirtualScreen::getSurfaceDesc(D3dDdi::KernelModeThunks::getMonitorRect()));
if (!gdiSurfaceDesc.lpSurface)
{
return;
}
D3DDDI_SURFACEINFO surfaceInfo = {};
surfaceInfo.Width = gdiSurfaceDesc.dwWidth;
surfaceInfo.Height = gdiSurfaceDesc.dwHeight;
surfaceInfo.pSysMem = gdiSurfaceDesc.lpSurface;
surfaceInfo.SysMemPitch = gdiSurfaceDesc.lPitch;
createSysMemResource({ surfaceInfo });
if (m_lockResource)
{
copySubResource(m_handle, m_lockResource, 0);
m_canCreateLockResource = false;
}
}
void Resource::createLockResource()
{
std::vector<D3DDDI_SURFACEINFO> surfaceInfo(m_fixedData.SurfCount);
m_lockBuffers.resize(m_fixedData.SurfCount);
for (UINT i = 0; i < m_fixedData.SurfCount; ++i)
{
auto width = m_fixedData.pSurfList[i].Width;
auto height = m_fixedData.pSurfList[i].Height;
auto pitch = divCeil(width * m_formatInfo.bytesPerPixel, 8) * 8;
m_lockBuffers[i].resize(pitch * height);
surfaceInfo[i].Width = width;
surfaceInfo[i].Height = height;
surfaceInfo[i].pSysMem = m_lockBuffers[i].data();
surfaceInfo[i].SysMemPitch = pitch;
}
createSysMemResource(surfaceInfo);
if (!m_lockResource)
{
m_lockBuffers.clear();
}
}
void Resource::createSysMemResource(const std::vector<D3DDDI_SURFACEINFO>& surfaceInfo)
{
D3DDDIARG_CREATERESOURCE2 data = {};
data.Format = m_fixedData.Format;
data.Pool = D3DDDIPOOL_SYSTEMMEM;
data.pSurfList = surfaceInfo.data();
data.SurfCount = surfaceInfo.size();
data.Rotation = D3DDDI_ROTATION_IDENTITY;
data.Flags.Texture = m_fixedData.Flags.Texture;
HRESULT result = S_OK;
if (m_device.getOrigVtable().pfnCreateResource2)
{
result = m_device.getOrigVtable().pfnCreateResource2(m_device, &data);
}
else
{
result = m_device.getOrigVtable().pfnCreateResource(m_device,
reinterpret_cast<D3DDDIARG_CREATERESOURCE*>(&data));
}
if (FAILED(result))
{
return;
}
m_lockResource = data.hResource;
m_lockData.resize(surfaceInfo.size());
for (std::size_t i = 0; i < surfaceInfo.size(); ++i)
{
m_lockData[i].data = const_cast<void*>(surfaceInfo[i].pSysMem);
m_lockData[i].pitch = surfaceInfo[i].SysMemPitch;
m_lockData[i].isSysMemUpToDate = false;
m_lockData[i].isVidMemUpToDate = true;
}
}
void Resource::copyToVidMem(UINT subResourceIndex)
{
copySubResource(*this, *m_lockResource, subResourceIndex);
copySubResource(m_handle, m_lockResource, subResourceIndex);
setVidMemUpToDate(subResourceIndex, true);
}
@ -357,6 +442,9 @@ namespace D3dDdi
}
resource.m_handle = data.hResource;
resource.m_canCreateLockResource = D3DDDIPOOL_SYSTEMMEM != data.Pool &&
0 != resource.m_formatInfo.bytesPerPixel &&
!data.Flags.Primary;
data = origData;
data.hResource = resource.m_handle;
return resource;
@ -372,11 +460,19 @@ namespace D3dDdi
return create(device, data, device.getOrigVtable().pfnCreateResource2);
}
void Resource::destroy()
void Resource::destroyLockResource()
{
if (m_rootSurface)
if (m_lockResource)
{
m_rootSurface->clearResources();
for (UINT i = 0; i < m_lockData.size(); ++i)
{
setSysMemUpToDate(i, false);
setVidMemUpToDate(i, true);
}
m_device.getOrigVtable().pfnDestroyResource(m_device, m_lockResource);
m_lockResource = nullptr;
m_lockData.clear();
m_lockBuffers.clear();
}
}
@ -435,7 +531,14 @@ namespace D3dDdi
}
return splitLock(data, m_device.getOrigVtable().pfnLock);
}
else if (m_lockResource)
if (m_canCreateLockResource)
{
createLockResource();
m_canCreateLockResource = false;
}
if (m_lockResource)
{
return bltLock(data);
}
@ -445,14 +548,14 @@ namespace D3dDdi
void Resource::moveToSysMem(UINT subResourceIndex)
{
copySubResource(*m_lockResource, *this, subResourceIndex);
copySubResource(m_lockResource, m_handle, subResourceIndex);
setSysMemUpToDate(subResourceIndex, true);
setVidMemUpToDate(subResourceIndex, false);
}
void Resource::moveToVidMem(UINT subResourceIndex)
{
copySubResource(*this, *m_lockResource, subResourceIndex);
copySubResource(m_handle, m_lockResource, subResourceIndex);
setVidMemUpToDate(subResourceIndex, true);
setSysMemUpToDate(subResourceIndex, false);
}
@ -503,7 +606,7 @@ namespace D3dDdi
{
if (srcResource.m_lockData[data.SrcSubResourceIndex].isSysMemUpToDate)
{
copySubResource(srcResource, *srcResource.m_lockResource, data.SrcSubResourceIndex);
copySubResource(srcResource.m_handle, srcResource.m_lockResource, data.SrcSubResourceIndex);
}
}
else
@ -514,83 +617,15 @@ namespace D3dDdi
return m_device.getOrigVtable().pfnBlt(m_device, &data);
}
void Resource::resync()
void Resource::setAsGdiResource(bool isGdiResource)
{
if (!m_lockData.empty() && m_lockData[0].isSysMemUpToDate)
destroyLockResource();
if (isGdiResource)
{
copySubResource(*this, *m_lockResource, 0);
if (!m_lockData[0].isVidMemUpToDate)
{
setVidMemUpToDate(0, true);
}
createGdiLockResource();
}
}
void Resource::setLockResource(Resource* lockResource)
{
if (!m_lockResource == !lockResource)
{
return;
}
if (lockResource)
{
if (lockResource->m_fixedData.SurfCount != m_fixedData.SurfCount)
{
LOG_ONCE("ERROR: Lock surface count mismatch: " <<
m_fixedData.surfaceData << " vs " << lockResource->m_fixedData.SurfCount);
return;
}
m_lockData.resize(m_fixedData.SurfCount);
for (UINT i = 0; i < m_fixedData.SurfCount; ++i)
{
m_lockData[i].data = const_cast<void*>(lockResource->m_fixedData.pSurfList[i].pSysMem);
m_lockData[i].pitch = lockResource->m_fixedData.pSurfList[i].SysMemPitch;
m_lockData[i].isSysMemUpToDate = true;
m_lockData[i].isVidMemUpToDate = true;
}
m_lockResource = lockResource;
if (m_fixedData.Flags.RenderTarget)
{
for (std::size_t i = 0; i < m_lockData.size(); ++i)
{
m_device.addDirtyRenderTarget(*this, i);
}
}
}
else
{
if (m_fixedData.Flags.RenderTarget)
{
for (std::size_t i = 0; i < m_lockData.size(); ++i)
{
if (m_lockData[i].isSysMemUpToDate)
{
m_device.removeDirtyRenderTarget(*this, i);
}
}
}
if (m_fixedData.Flags.Texture)
{
for (std::size_t i = 0; i < m_lockData.size(); ++i)
{
if (!m_lockData[i].isVidMemUpToDate)
{
m_device.removeDirtyTexture(*this, i);
}
}
}
m_lockResource = nullptr;
m_lockData.clear();
}
}
void Resource::setRootSurface(DDraw::Surface* rootSurface)
{
m_rootSurface = rootSurface;
}
void Resource::setSysMemUpToDate(UINT subResourceIndex, bool upToDate)
{
m_lockData[subResourceIndex].isSysMemUpToDate = upToDate;

View File

@ -4,15 +4,9 @@
#include <d3d.h>
#include <d3dumddi.h>
#include <ddraw.h>
#include "D3dDdi/FormatInfo.h"
namespace DDraw
{
class Surface;
}
namespace D3dDdi
{
class Device;
@ -27,14 +21,12 @@ namespace D3dDdi
HRESULT blt(D3DDDIARG_BLT data);
HRESULT colorFill(const D3DDDIARG_COLORFILL& data);
void destroy();
void destroyLockResource();
void fixVertexData(UINT offset, UINT count, UINT stride);
void* getLockPtr(UINT subResourceIndex);
HRESULT lock(D3DDDIARG_LOCK& data);
void prepareForRendering(UINT subResourceIndex, bool isReadOnly);
void resync();
void setLockResource(Resource* lockResource);
void setRootSurface(DDraw::Surface* rootSurface);
void setAsGdiResource(bool isGdiResource);
HRESULT unlock(const D3DDDIARG_UNLOCK& data);
private:
@ -72,15 +64,17 @@ namespace D3dDdi
Resource(Device& device, const D3DDDIARG_CREATERESOURCE& data);
Resource(Device& device, const D3DDDIARG_CREATERESOURCE2& data);
static HRESULT copySubResource(Resource& dstResource, Resource& srcResource, UINT subResourceIndex);
template <typename Arg>
static Resource create(Device& device, Arg& data, HRESULT(APIENTRY *createResourceFunc)(HANDLE, Arg*));
HRESULT bltLock(D3DDDIARG_LOCK& data);
HRESULT bltUnlock(const D3DDDIARG_UNLOCK& data);
HRESULT copySubResource(HANDLE dstResource, HANDLE srcResource, UINT subResourceIndex);
void copyToSysMem(UINT subResourceIndex);
void copyToVidMem(UINT subResourceIndex);
void createGdiLockResource();
void createLockResource();
void createSysMemResource(const std::vector<D3DDDI_SURFACEINFO>& surfaceInfo);
bool isOversized() const;
void moveToSysMem(UINT subResourceIndex);
void moveToVidMem(UINT subResourceIndex);
@ -100,8 +94,9 @@ namespace D3dDdi
Data m_origData;
Data m_fixedData;
FormatInfo m_formatInfo;
DDraw::Surface* m_rootSurface;
Resource* m_lockResource;
HANDLE m_lockResource;
std::vector<LockData> m_lockData;
std::vector<std::vector<BYTE>> m_lockBuffers;
bool m_canCreateLockResource;
};
}

View File

@ -14,7 +14,6 @@
namespace
{
CompatWeakPtr<IDirectDrawSurface7> g_primarySurface;
std::vector<CompatWeakPtr<IDirectDrawSurface7>> g_lockBackBuffers;
HANDLE g_gdiResourceHandle = nullptr;
HANDLE g_frontResource = nullptr;
DWORD g_origCaps = 0;
@ -32,12 +31,6 @@ namespace DDraw
g_origCaps = 0;
s_palette = nullptr;
for (auto& lockBuffer : g_lockBackBuffers)
{
lockBuffer.release();
}
g_lockBackBuffers.clear();
DDraw::RealPrimarySurface::release();
}
@ -71,30 +64,6 @@ namespace DDraw
}
g_origCaps = origCaps;
data->m_lockSurface.release();
data->m_attachedLockSurfaces.clear();
desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS;
desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
CompatPtr<TSurface> lockSurface;
dd->CreateSurface(&dd, &desc, &lockSurface.getRef(), nullptr);
data->m_lockSurface = lockSurface;
if (g_origCaps & DDSCAPS_FLIP)
{
for (std::size_t i = 0; i < desc.dwBackBufferCount; ++i)
{
CompatPtr<TSurface> lockBuffer;
dd->CreateSurface(&dd, &desc, &lockBuffer.getRef(), nullptr);
if (lockBuffer)
{
g_lockBackBuffers.push_back(CompatPtr<IDirectDrawSurface7>::from(lockBuffer.get()).detach());
data->m_attachedLockSurfaces.push_back(g_lockBackBuffers.back());
}
}
}
data->restore();
return DD_OK;
}
@ -211,13 +180,7 @@ namespace DDraw
{
LOG_FUNC("PrimarySurface::restore");
clearResources();
Gdi::VirtualScreen::update();
auto desc = Gdi::VirtualScreen::getSurfaceDesc(D3dDdi::KernelModeThunks::getMonitorRect());
desc.dwFlags &= ~DDSD_CAPS;
m_lockSurface->SetSurfaceDesc(m_lockSurface, &desc, 0);
g_primarySurface = m_surface;
g_gdiResourceHandle = getRuntimeResourceHandle(*g_primarySurface);
updateFrontResource();

View File

@ -33,46 +33,13 @@ namespace DDraw
return refCount;
}
Surface::Surface(Surface* rootSurface)
Surface::Surface()
: m_refCount(0)
, m_rootSurface(rootSurface ? rootSurface : this)
{
}
Surface::~Surface()
{
clearResources();
if (m_rootSurface != this)
{
auto it = std::find(m_rootSurface->m_attachedSurfaces.begin(),
m_rootSurface->m_attachedSurfaces.end(), this);
if (it != m_rootSurface->m_attachedSurfaces.end())
{
m_rootSurface->m_attachedSurfaces.erase(it);
}
if (m_rootSurface->m_lockSurface == m_surface)
{
m_rootSurface->m_lockSurface.detach();
m_rootSurface->m_attachedLockSurfaces.clear();
}
}
else
{
for (auto attachedSurface : m_attachedSurfaces)
{
attachedSurface->m_rootSurface = attachedSurface;
}
if (m_lockSurface)
{
auto lockSurface(getSurface(*m_lockSurface));
if (lockSurface)
{
lockSurface->m_rootSurface = lockSurface;
}
}
}
}
void Surface::attach(CompatRef<IDirectDrawSurface7> dds, std::unique_ptr<Surface> privateData)
@ -86,26 +53,6 @@ namespace DDraw
}
}
void Surface::clearResources()
{
if (!m_surface)
{
return;
}
auto resource = D3dDdi::Device::getResource(getDriverResourceHandle(*m_surface));
if (resource)
{
resource->setLockResource(nullptr);
resource->setRootSurface(nullptr);
}
for (auto attachedSurface : m_attachedSurfaces)
{
attachedSurface->clearResources();
}
}
template <typename TDirectDraw, typename TSurface, typename TSurfaceDesc>
HRESULT Surface::create(
CompatRef<TDirectDraw> dd, TSurfaceDesc desc, TSurface*& surface, std::unique_ptr<Surface> privateData)
@ -125,32 +72,16 @@ namespace DDraw
surface7->GetPixelFormat(surface7, &desc.ddpfPixelFormat);
}
privateData->m_lockSurface = privateData->createLockSurface<TDirectDraw, TSurface>(dd, desc);
if (privateData->m_lockSurface)
{
attach(*privateData->m_lockSurface, std::make_unique<Surface>(privateData.get()));
}
if (desc.ddsCaps.dwCaps & DDSCAPS_COMPLEX)
{
auto attachedSurfaces(getAllAttachedSurfaces(*surface7));
if (privateData->m_lockSurface)
{
auto attachedLockSurfaces(getAllAttachedSurfaces(*privateData->m_lockSurface));
privateData->m_attachedLockSurfaces.assign(attachedLockSurfaces.begin(), attachedLockSurfaces.end());
}
for (DWORD i = 0; i < attachedSurfaces.size(); ++i)
{
auto data(std::make_unique<Surface>(privateData.get()));
privateData->m_attachedSurfaces.push_back(data.get());
attach(*attachedSurfaces[i], std::move(data));
attach(*attachedSurfaces[i], std::make_unique<Surface>());
}
}
Surface* rootSurface = privateData.get();
attach(*surface7, std::move(privateData));
rootSurface->restore();
return result;
}
@ -184,28 +115,6 @@ namespace DDraw
template <>
SurfaceImpl<IDirectDrawSurface7>* Surface::getImpl<IDirectDrawSurface7>() const { return m_impl7.get(); }
template <typename TDirectDraw, typename TSurface, typename TSurfaceDesc>
CompatPtr<IDirectDrawSurface7> Surface::createLockSurface(CompatRef<TDirectDraw> dd, TSurfaceDesc desc)
{
LOG_FUNC("Surface::createLockSurface", dd, desc);
if ((desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) ||
!(desc.ddpfPixelFormat.dwFlags & DDPF_RGB) ||
0 == desc.ddpfPixelFormat.dwRGBBitCount ||
desc.ddpfPixelFormat.dwRGBBitCount > 32 ||
0 != (desc.ddpfPixelFormat.dwRGBBitCount % 8))
{
return LOG_RESULT(nullptr);
}
desc.ddsCaps.dwCaps &= ~(DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM | DDSCAPS_NONLOCALVIDMEM);
desc.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
CompatPtr<TSurface> lockSurface;
dd->CreateSurface(&dd, &desc, &lockSurface.getRef(), nullptr);
return LOG_RESULT(lockSurface);
}
template <typename TSurface>
Surface* Surface::getSurface(TSurface& dds)
{
@ -228,27 +137,5 @@ namespace DDraw
void Surface::restore()
{
setResources(m_lockSurface);
if (m_lockSurface)
{
for (std::size_t i = 0; i < m_attachedSurfaces.size(); ++i)
{
m_attachedSurfaces[i]->setResources(
i < m_attachedLockSurfaces.size() ? m_attachedLockSurfaces[i] : nullptr);
}
}
}
void Surface::setResources(CompatWeakPtr<IDirectDrawSurface7> lockSurface)
{
if (lockSurface)
{
auto resource = D3dDdi::Device::getResource(getDriverResourceHandle(*m_surface));
if (resource)
{
resource->setLockResource(D3dDdi::Device::getResource(getDriverResourceHandle(*lockSurface)));
resource->setRootSurface(m_rootSurface);
}
}
}
}

View File

@ -20,7 +20,7 @@ namespace DDraw
virtual ULONG STDMETHODCALLTYPE AddRef();
virtual ULONG STDMETHODCALLTYPE Release();
Surface(Surface* rootSurface = nullptr);
Surface();
virtual ~Surface();
template <typename TDirectDraw, typename TSurface, typename TSurfaceDesc>
@ -33,7 +33,6 @@ namespace DDraw
template <typename TSurface>
SurfaceImpl<TSurface>* getImpl() const;
void clearResources();
virtual void restore();
protected:
@ -49,22 +48,11 @@ namespace DDraw
std::unique_ptr<SurfaceImpl<IDirectDrawSurface7>> m_impl7;
CompatWeakPtr<IDirectDrawSurface7> m_surface;
std::vector<Surface*> m_attachedSurfaces;
CompatPtr<IDirectDrawSurface7> m_lockSurface;
std::vector<CompatWeakPtr<IDirectDrawSurface7>> m_attachedLockSurfaces;
private:
template <typename TDirectDrawSurface>
friend class SurfaceImpl;
template <typename TDirectDrawSurface>
friend class SurfaceImpl2;
template <typename TDirectDraw, typename TSurface, typename TSurfaceDesc>
CompatPtr<IDirectDrawSurface7> createLockSurface(CompatRef<TDirectDraw> dd, TSurfaceDesc desc);
void setResources(CompatWeakPtr<IDirectDrawSurface7> lockSurface);
DWORD m_refCount;
Surface* m_rootSurface;
};
}

View File

@ -210,34 +210,34 @@ namespace Gdi
{
D3dDdi::ScopedCriticalSection driverLock;
D3dDdi::Device::setGdiResourceHandle(nullptr);
}
g_region = Region();
EnumDisplayMonitors(nullptr, nullptr, addMonitorRectToRegion, reinterpret_cast<LPARAM>(&g_region));
GetRgnBox(g_region, &g_bounds);
g_region = Region();
EnumDisplayMonitors(nullptr, nullptr, addMonitorRectToRegion, reinterpret_cast<LPARAM>(&g_region));
GetRgnBox(g_region, &g_bounds);
g_bpp = bpp;
g_width = g_bounds.right - g_bounds.left;
g_height = g_bounds.bottom - g_bounds.top;
g_pitch = (g_width * g_bpp / 8 + 3) & ~3;
g_bpp = bpp;
g_width = g_bounds.right - g_bounds.left;
g_height = g_bounds.bottom - g_bounds.top;
g_pitch = (g_width * g_bpp / 8 + 3) & ~3;
if (g_surfaceFileMapping)
{
for (HDC dc : g_dcs)
{
DeleteObject(SelectObject(dc, g_stockBitmap));
}
UnmapViewOfFile(g_surfaceView);
CloseHandle(g_surfaceFileMapping);
}
g_surfaceFileMapping = CreateFileMapping(INVALID_HANDLE_VALUE, nullptr, PAGE_READWRITE, 0,
g_pitch * (g_height + Config::virtualScreenBufferExtraRows), nullptr);
g_surfaceView = MapViewOfFile(g_surfaceFileMapping, FILE_MAP_WRITE, 0, 0, 0);
if (g_surfaceFileMapping)
{
for (HDC dc : g_dcs)
{
DeleteObject(SelectObject(dc, g_stockBitmap));
SelectObject(dc, createDib());
}
UnmapViewOfFile(g_surfaceView);
CloseHandle(g_surfaceFileMapping);
}
g_surfaceFileMapping = CreateFileMapping(INVALID_HANDLE_VALUE, nullptr, PAGE_READWRITE, 0,
g_pitch * (g_height + Config::virtualScreenBufferExtraRows), nullptr);
g_surfaceView = MapViewOfFile(g_surfaceFileMapping, FILE_MAP_WRITE, 0, 0, 0);
for (HDC dc : g_dcs)
{
SelectObject(dc, createDib());
}
Gdi::redraw(nullptr);