mirror of
https://github.com/narzoul/DDrawCompat
synced 2024-12-30 08:55:36 +01:00
Apply ResolutionScale to layered windows
This commit is contained in:
parent
26261b5287
commit
7a84efc1da
43
DDrawCompat/Common/Rect.cpp
Normal file
43
DDrawCompat/Common/Rect.cpp
Normal file
@ -0,0 +1,43 @@
|
||||
#include <Common/Rect.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
template <typename Rect>
|
||||
void transform(Rect& rect, const RECT& srcView, const RECT& dstView)
|
||||
{
|
||||
const LONG srcWidth = srcView.right - srcView.left;
|
||||
const LONG srcHeight = srcView.bottom - srcView.top;
|
||||
const LONG dstWidth = dstView.right - dstView.left;
|
||||
const LONG dstHeight = dstView.bottom - dstView.top;
|
||||
|
||||
rect = {
|
||||
(rect.left - srcView.left) * dstWidth / srcWidth + dstView.left,
|
||||
(rect.top - srcView.top) * dstHeight / srcHeight + dstView.top,
|
||||
(rect.right - srcView.left) * dstWidth / srcWidth + dstView.left,
|
||||
(rect.bottom - srcView.top) * dstHeight / srcHeight + dstView.top
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
namespace Rect
|
||||
{
|
||||
RectF toRectF(const RECT& rect)
|
||||
{
|
||||
return {
|
||||
static_cast<float>(rect.left),
|
||||
static_cast<float>(rect.top),
|
||||
static_cast<float>(rect.right),
|
||||
static_cast<float>(rect.bottom)
|
||||
};
|
||||
}
|
||||
|
||||
void transform(RECT& rect, const RECT& srcView, const RECT& dstView)
|
||||
{
|
||||
::transform(rect, srcView, dstView);
|
||||
}
|
||||
|
||||
void transform(RectF& rect, const RECT& srcView, const RECT& dstView)
|
||||
{
|
||||
::transform(rect, srcView, dstView);
|
||||
}
|
||||
}
|
18
DDrawCompat/Common/Rect.h
Normal file
18
DDrawCompat/Common/Rect.h
Normal file
@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
struct RectF
|
||||
{
|
||||
float left;
|
||||
float top;
|
||||
float right;
|
||||
float bottom;
|
||||
};
|
||||
|
||||
namespace Rect
|
||||
{
|
||||
RectF toRectF(const RECT& rect);
|
||||
void transform(RECT& rect, const RECT& srcView, const RECT& dstView);
|
||||
void transform(RectF& rect, const RECT& srcView, const RECT& dstView);
|
||||
}
|
@ -3,6 +3,7 @@
|
||||
#include <Common/Comparison.h>
|
||||
#include <Common/HResultException.h>
|
||||
#include <Common/Log.h>
|
||||
#include <Common/Rect.h>
|
||||
#include <Common/Time.h>
|
||||
#include <Config/Config.h>
|
||||
#include <D3dDdi/Adapter.h>
|
||||
@ -15,6 +16,7 @@
|
||||
#include <DDraw/RealPrimarySurface.h>
|
||||
#include <DDraw/Surfaces/PrimarySurface.h>
|
||||
#include <DDraw/Surfaces/SurfaceImpl.h>
|
||||
#include <Dll/Dll.h>
|
||||
#include <Gdi/Cursor.h>
|
||||
#include <Gdi/Palette.h>
|
||||
#include <Gdi/VirtualScreen.h>
|
||||
@ -438,6 +440,44 @@ namespace D3dDdi
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Resource::downscale(Resource*& rt, LONG& srcWidth, LONG& srcHeight, LONG dstWidth, LONG dstHeight)
|
||||
{
|
||||
LONG newSrcWidth = (srcWidth + 1) / 2;
|
||||
if (newSrcWidth <= dstWidth)
|
||||
{
|
||||
newSrcWidth = srcWidth;
|
||||
}
|
||||
|
||||
LONG newSrcHeight = (srcHeight + 1) / 2;
|
||||
if (newSrcHeight <= dstHeight)
|
||||
{
|
||||
newSrcHeight = srcHeight;
|
||||
}
|
||||
|
||||
if (newSrcWidth == srcWidth && newSrcHeight == srcHeight)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
auto& repo = SurfaceRepository::get(m_device.getAdapter());
|
||||
auto newRt = &repo.getTempRenderTarget(newSrcWidth, newSrcHeight, 1);
|
||||
if (newRt->resource == rt)
|
||||
{
|
||||
newRt = &repo.getTempRenderTarget(newSrcWidth, newSrcHeight, 0);
|
||||
}
|
||||
if (!newRt->resource)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
m_device.getShaderBlitter().textureBlt(*newRt->resource, 0, { 0, 0, newSrcWidth, newSrcHeight },
|
||||
*rt, 0, { 0, 0, srcWidth, srcHeight }, D3DTEXF_LINEAR);
|
||||
rt = newRt->resource;
|
||||
srcWidth = newSrcWidth;
|
||||
srcHeight = newSrcHeight;
|
||||
return true;
|
||||
}
|
||||
|
||||
void Resource::fixResourceData()
|
||||
{
|
||||
if (m_fixedData.Flags.Primary)
|
||||
@ -768,86 +808,127 @@ namespace D3dDdi
|
||||
}
|
||||
|
||||
srcResource = &srcResource->prepareForGpuRead(0);
|
||||
data.hSrcResource = *srcResource;
|
||||
}
|
||||
|
||||
const bool isPalettized = D3DDDIFMT_P8 == srcResource->m_origData.Format;
|
||||
LONG srcWidth = srcResource->m_fixedData.pSurfList[0].Width;
|
||||
LONG srcHeight = srcResource->m_fixedData.pSurfList[0].Height;
|
||||
data.SrcRect = { 0, 0, srcWidth, srcHeight };
|
||||
data.DstRect = g_presentationRect;
|
||||
|
||||
auto& repo = SurfaceRepository::get(m_device.getAdapter());
|
||||
const auto& rtSurface = repo.getTempRenderTarget(srcWidth, srcHeight);
|
||||
auto rt = rtSurface.resource ? rtSurface.resource : this;
|
||||
auto rtIndex = rtSurface.resource ? 0 : data.DstSubResourceIndex;
|
||||
auto rtRect = rtSurface.resource ? data.SrcRect : data.DstRect;
|
||||
|
||||
if (D3DDDIFMT_P8 == srcResource->m_origData.Format)
|
||||
{
|
||||
auto entries(Gdi::Palette::getHardwarePalette());
|
||||
RGBQUAD pal[256] = {};
|
||||
for (UINT i = 0; i < 256; ++i)
|
||||
{
|
||||
pal[i].rgbRed = entries[i].peRed;
|
||||
pal[i].rgbGreen = entries[i].peGreen;
|
||||
pal[i].rgbBlue = entries[i].peBlue;
|
||||
}
|
||||
m_device.getShaderBlitter().palettizedBlt(*rt, rtIndex, rtRect, *srcResource, data.SrcRect, pal);
|
||||
}
|
||||
else
|
||||
{
|
||||
copySubResourceRegion(*rt, rtIndex, rtRect, *srcResource, 0, data.SrcRect);
|
||||
}
|
||||
|
||||
presentLayeredWindows(*rt, rtIndex, rtRect);
|
||||
|
||||
const auto cursorInfo = Gdi::Cursor::getEmulatedCursorInfo();
|
||||
const bool isCursorEmulated = cursorInfo.flags == CURSOR_SHOWING && cursorInfo.hCursor;
|
||||
|
||||
const RECT monitorRect = DDraw::PrimarySurface::getMonitorRect();
|
||||
const bool isLayeredPresentNeeded = Gdi::Window::presentLayered(nullptr, monitorRect);
|
||||
|
||||
const LONG srcWidth = srcResource->m_fixedData.pSurfList[0].Width;
|
||||
const LONG srcHeight = srcResource->m_fixedData.pSurfList[0].Height;
|
||||
data.SrcRect = { 0, 0, srcWidth, srcHeight };
|
||||
|
||||
UINT presentationFilter = Config::displayFilter.get();
|
||||
UINT presentationFilterParam = Config::displayFilter.getParam();
|
||||
if (Config::Settings::DisplayFilter::BILINEAR == presentationFilter &&
|
||||
(g_presentationRect.right - g_presentationRect.left == srcWidth &&
|
||||
g_presentationRect.bottom - g_presentationRect.top == srcHeight) ||
|
||||
(0 == presentationFilterParam &&
|
||||
0 == (g_presentationRect.right - g_presentationRect.left) % srcWidth &&
|
||||
0 == (g_presentationRect.bottom - g_presentationRect.top) % srcHeight))
|
||||
if (isCursorEmulated)
|
||||
{
|
||||
presentationFilter = Config::Settings::DisplayFilter::POINT;
|
||||
m_device.getShaderBlitter().cursorBlt(*rt, rtIndex, rtRect, cursorInfo.hCursor, cursorInfo.ptScreenPos);
|
||||
}
|
||||
|
||||
if (isPalettized || isCursorEmulated || isLayeredPresentNeeded ||
|
||||
Config::Settings::DisplayFilter::POINT != presentationFilter)
|
||||
if (!rtSurface.resource)
|
||||
{
|
||||
const auto& dst(SurfaceRepository::get(m_device.getAdapter()).getTempRenderTarget(srcWidth, srcHeight));
|
||||
if (!dst.resource)
|
||||
{
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
if (isPalettized)
|
||||
{
|
||||
auto entries(Gdi::Palette::getHardwarePalette());
|
||||
RGBQUAD pal[256] = {};
|
||||
for (UINT i = 0; i < 256; ++i)
|
||||
{
|
||||
pal[i].rgbRed = entries[i].peRed;
|
||||
pal[i].rgbGreen = entries[i].peGreen;
|
||||
pal[i].rgbBlue = entries[i].peBlue;
|
||||
}
|
||||
m_device.getShaderBlitter().palettizedBlt(*dst.resource, 0, *srcResource, pal);
|
||||
}
|
||||
else
|
||||
{
|
||||
copySubResourceRegion(*dst.resource, 0, data.SrcRect, data.hSrcResource, 0, data.SrcRect);
|
||||
}
|
||||
|
||||
if (isLayeredPresentNeeded)
|
||||
{
|
||||
Gdi::Window::presentLayered(dst.surface, monitorRect);
|
||||
}
|
||||
|
||||
if (isCursorEmulated)
|
||||
{
|
||||
POINT pos = { cursorInfo.ptScreenPos.x - monitorRect.left, cursorInfo.ptScreenPos.y - monitorRect.top };
|
||||
m_device.getShaderBlitter().cursorBlt(*dst.resource, 0, cursorInfo.hCursor, pos);
|
||||
}
|
||||
|
||||
if (Config::Settings::DisplayFilter::BILINEAR == presentationFilter)
|
||||
{
|
||||
m_device.getShaderBlitter().genBilinearBlt(*this, data.DstSubResourceIndex, g_presentationRect,
|
||||
*dst.resource, data.SrcRect, presentationFilterParam);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
data.hSrcResource = *dst.resource;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
data.DstRect = g_presentationRect;
|
||||
data.Flags.Linear = 0;
|
||||
if (Config::Settings::DisplayFilter::BILINEAR == Config::displayFilter.get())
|
||||
{
|
||||
const LONG dstWidth = data.DstRect.right - data.DstRect.left;
|
||||
const LONG dstHeight = data.DstRect.bottom - data.DstRect.top;
|
||||
while (downscale(rt, data.SrcRect.right, data.SrcRect.bottom, dstWidth, dstHeight))
|
||||
{
|
||||
}
|
||||
|
||||
m_device.getShaderBlitter().genBilinearBlt(*this, data.DstSubResourceIndex, data.DstRect,
|
||||
*rt, data.SrcRect, Config::displayFilter.getParam());
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
data.hSrcResource = *rt;
|
||||
data.SrcSubResourceIndex = 0;
|
||||
data.Flags.Point = 1;
|
||||
return m_device.getOrigVtable().pfnBlt(m_device, &data);
|
||||
}
|
||||
|
||||
void Resource::presentLayeredWindows(Resource& dst, UINT dstSubResourceIndex, const RECT& dstRect)
|
||||
{
|
||||
auto& blitter = m_device.getShaderBlitter();
|
||||
auto& repo = SurfaceRepository::get(m_device.getAdapter());
|
||||
RECT monitorRect = DDraw::PrimarySurface::getMonitorRect();
|
||||
auto layeredWindows(Gdi::Window::getVisibleLayeredWindows());
|
||||
|
||||
for (auto& layeredWindow : layeredWindows)
|
||||
{
|
||||
RECT visibleRect = {};
|
||||
IntersectRect(&visibleRect, &layeredWindow.rect, &monitorRect);
|
||||
if (IsRectEmpty(&visibleRect))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
RECT srcRect = { 0, 0, visibleRect.right - visibleRect.left, visibleRect.bottom - visibleRect.top };
|
||||
auto& windowSurface = repo.getTempSysMemSurface(srcRect.right, srcRect.bottom);
|
||||
auto& texture = repo.getTempTexture(srcRect.right, srcRect.bottom, getPixelFormat(D3DDDIFMT_A8R8G8B8));
|
||||
if (!windowSurface.resource || !texture.resource)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
HDC srcDc = GetWindowDC(layeredWindow.hwnd);
|
||||
HDC dstDc = nullptr;
|
||||
windowSurface.surface->GetDC(windowSurface.surface, &dstDc);
|
||||
CALL_ORIG_FUNC(BitBlt)(dstDc, 0, 0, srcRect.right, srcRect.bottom, srcDc,
|
||||
visibleRect.left - layeredWindow.rect.left, visibleRect.top - layeredWindow.rect.top, SRCCOPY);
|
||||
windowSurface.surface->ReleaseDC(windowSurface.surface, dstDc);
|
||||
ReleaseDC(layeredWindow.hwnd, srcDc);
|
||||
|
||||
copySubResourceRegion(*texture.resource, 0, srcRect, *windowSurface.resource, 0, srcRect);
|
||||
texture.resource->notifyLock(0);
|
||||
|
||||
COLORREF colorKey = 0;
|
||||
BYTE alpha = 0;
|
||||
DWORD flags = 0;
|
||||
GetLayeredWindowAttributes(layeredWindow.hwnd, &colorKey, &alpha, &flags);
|
||||
if (flags & ULW_COLORKEY)
|
||||
{
|
||||
colorKey = ((colorKey & 0xFF) << 16) | (colorKey & 0xFF00) | ((colorKey & 0xFF0000) >> 16);
|
||||
}
|
||||
|
||||
if (layeredWindow.region)
|
||||
{
|
||||
layeredWindow.region &= monitorRect;
|
||||
layeredWindow.region.offset(-visibleRect.left, -visibleRect.top);
|
||||
}
|
||||
Rect::transform(visibleRect, monitorRect, dstRect);
|
||||
|
||||
blitter.textureBlt(dst, dstSubResourceIndex, visibleRect, *texture.resource, 0, srcRect, D3DTEXF_POINT,
|
||||
(flags & ULW_COLORKEY) ? reinterpret_cast<UINT*>(&colorKey) : nullptr,
|
||||
(flags & ULW_ALPHA) ? &alpha : nullptr,
|
||||
layeredWindow.region);
|
||||
}
|
||||
}
|
||||
|
||||
void Resource::scaleRect(RECT& rect)
|
||||
{
|
||||
const LONG origWidth = m_fixedData.pSurfList[0].Width;
|
||||
@ -1151,6 +1232,13 @@ namespace D3dDdi
|
||||
SurfaceRepository::get(m_device.getAdapter()).getSurface(m_msaaResolvedSurface,
|
||||
scaledSize.cx, scaledSize.cy, getPixelFormat(formatConfig),
|
||||
DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY, m_fixedData.SurfCount);
|
||||
if (!m_msaaResolvedSurface.resource && m_msaaSurface.resource)
|
||||
{
|
||||
m_msaaSurface = {};
|
||||
SurfaceRepository::get(m_device.getAdapter()).getSurface(m_msaaResolvedSurface,
|
||||
scaledSize.cx, scaledSize.cy, getPixelFormat(formatConfig),
|
||||
DDSCAPS_3DDEVICE | DDSCAPS_VIDEOMEMORY, m_fixedData.SurfCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -83,6 +83,7 @@ namespace D3dDdi
|
||||
void createGdiLockResource();
|
||||
void createLockResource();
|
||||
void createSysMemResource(const std::vector<D3DDDI_SURFACEINFO>& surfaceInfo);
|
||||
bool downscale(Resource*& rt, LONG& srcWidth, LONG& srcHeight, LONG dstWidth, LONG dstHeight);
|
||||
void fixResourceData();
|
||||
D3DDDIFORMAT getFormatConfig();
|
||||
std::pair<D3DDDIMULTISAMPLE_TYPE, UINT> getMultisampleConfig();
|
||||
@ -95,6 +96,7 @@ namespace D3dDdi
|
||||
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& srcResource);
|
||||
HRESULT sysMemPreferredBlt(D3DDDIARG_BLT& data, Resource& srcResource);
|
||||
|
||||
|
@ -1,9 +1,11 @@
|
||||
#include <Common/Log.h>
|
||||
#include <Common/Rect.h>
|
||||
#include <D3dDdi/Adapter.h>
|
||||
#include <D3dDdi/Device.h>
|
||||
#include <D3dDdi/Resource.h>
|
||||
#include <D3dDdi/ShaderBlitter.h>
|
||||
#include <D3dDdi/SurfaceRepository.h>
|
||||
#include <DDraw/Surfaces/PrimarySurface.h>
|
||||
#include <Shaders/DrawCursor.h>
|
||||
#include <Shaders/GenBilinear.h>
|
||||
#include <Shaders/PaletteLookup.h>
|
||||
@ -27,10 +29,11 @@ namespace D3dDdi
|
||||
|
||||
void ShaderBlitter::blt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
|
||||
const Resource& srcResource, UINT srcSubResourceIndex, const RECT& srcRect,
|
||||
HANDLE pixelShader, UINT filter, const UINT* srcColorKey)
|
||||
HANDLE pixelShader, UINT filter, const UINT* srcColorKey, const BYTE* alpha, const Gdi::Region& srcRgn)
|
||||
{
|
||||
LOG_FUNC("ShaderBlitter::blt", static_cast<HANDLE>(dstResource), dstSubResourceIndex, dstRect,
|
||||
static_cast<HANDLE>(srcResource), srcRect, srcSubResourceIndex, pixelShader, filter, srcColorKey);
|
||||
static_cast<HANDLE>(srcResource), srcRect, srcSubResourceIndex, pixelShader, filter, srcColorKey,
|
||||
alpha, static_cast<HRGN>(srcRgn));
|
||||
|
||||
if (!m_vertexShaderDecl || !pixelShader)
|
||||
{
|
||||
@ -40,6 +43,14 @@ namespace D3dDdi
|
||||
const auto& srcSurface = srcResource.getFixedDesc().pSurfList[srcSubResourceIndex];
|
||||
const auto& dstSurface = dstResource.getFixedDesc().pSurfList[dstSubResourceIndex];
|
||||
|
||||
bool srgb = false;
|
||||
if (D3DTEXF_LINEAR == filter)
|
||||
{
|
||||
const auto& formatOps = m_device.getAdapter().getInfo().formatOps;
|
||||
srgb = (formatOps.at(srcResource.getFixedDesc().Format).Operations & FORMATOP_SRGBREAD) &&
|
||||
(formatOps.at(dstResource.getFixedDesc().Format).Operations & FORMATOP_SRGBWRITE);
|
||||
}
|
||||
|
||||
auto& state = m_device.getState();
|
||||
state.setTempRenderState({ D3DDDIRS_SCENECAPTURE, TRUE });
|
||||
state.setTempVertexShaderDecl(m_vertexShaderDecl.get());
|
||||
@ -55,7 +66,7 @@ namespace D3dDdi
|
||||
state.setTempRenderState({ D3DDDIRS_ALPHATESTENABLE, FALSE });
|
||||
state.setTempRenderState({ D3DDDIRS_CULLMODE, D3DCULL_NONE });
|
||||
state.setTempRenderState({ D3DDDIRS_DITHERENABLE, FALSE });
|
||||
state.setTempRenderState({ D3DDDIRS_ALPHABLENDENABLE, FALSE });
|
||||
state.setTempRenderState({ D3DDDIRS_ALPHABLENDENABLE, nullptr != alpha });
|
||||
state.setTempRenderState({ D3DDDIRS_FOGENABLE, FALSE });
|
||||
state.setTempRenderState({ D3DDDIRS_COLORKEYENABLE, nullptr != srcColorKey });
|
||||
state.setTempRenderState({ D3DDDIRS_STENCILENABLE, FALSE });
|
||||
@ -63,39 +74,45 @@ namespace D3dDdi
|
||||
state.setTempRenderState({ D3DDDIRS_CLIPPLANEENABLE, 0 });
|
||||
state.setTempRenderState({ D3DDDIRS_MULTISAMPLEANTIALIAS, FALSE });
|
||||
state.setTempRenderState({ D3DDDIRS_COLORWRITEENABLE, 0xF });
|
||||
state.setTempRenderState({ D3DDDIRS_SRGBWRITEENABLE, D3DTEXF_LINEAR == filter });
|
||||
state.setTempRenderState({ D3DDDIRS_SRGBWRITEENABLE, srgb });
|
||||
|
||||
if (alpha)
|
||||
{
|
||||
const UINT D3DBLEND_BLENDFACTOR = 14;
|
||||
const UINT D3DBLEND_INVBLENDFACTOR = 15;
|
||||
state.setTempRenderState({ D3DDDIRS_SRCBLEND, D3DBLEND_BLENDFACTOR });
|
||||
state.setTempRenderState({ D3DDDIRS_DESTBLEND, D3DBLEND_INVBLENDFACTOR });
|
||||
|
||||
const D3DCOLOR blendFactor = (*alpha << 16) | (*alpha << 8) | *alpha;
|
||||
state.setTempRenderState({ D3DDDIRS_BLENDFACTOR, blendFactor });
|
||||
}
|
||||
|
||||
setTempTextureStage(0, srcResource, filter, srcColorKey);
|
||||
|
||||
struct Vertex
|
||||
{
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
float rhw;
|
||||
float tu;
|
||||
float tv;
|
||||
};
|
||||
state.setTempTextureStageState({ 0, D3DDDITSS_SRGBTEXTURE, srgb });
|
||||
|
||||
const float srcWidth = static_cast<float>(srcSurface.Width);
|
||||
const float srcHeight = static_cast<float>(srcSurface.Height);
|
||||
|
||||
Vertex vertices[4] = {
|
||||
{ dstRect.left - 0.5f, dstRect.top - 0.5f, 0, 1, srcRect.left / srcWidth, srcRect.top / srcHeight },
|
||||
{ dstRect.right - 0.5f, dstRect.top - 0.5f, 0, 1, srcRect.right / srcWidth, srcRect.top / srcHeight },
|
||||
{ dstRect.left - 0.5f, dstRect.bottom - 0.5f, 0, 1, srcRect.left / srcWidth, srcRect.bottom / srcHeight },
|
||||
{ dstRect.right - 0.5f, dstRect.bottom - 0.5f, 0, 1, srcRect.right / srcWidth, srcRect.bottom / srcHeight }
|
||||
};
|
||||
|
||||
Vertex vertices[4] = {};
|
||||
state.setTempStreamSourceUm({ 0, sizeof(Vertex) }, vertices);
|
||||
|
||||
DeviceState::TempStateLock lock(state);
|
||||
|
||||
D3DDDIARG_DRAWPRIMITIVE dp = {};
|
||||
dp.PrimitiveType = D3DPT_TRIANGLESTRIP;
|
||||
dp.VStart = 0;
|
||||
dp.PrimitiveCount = 2;
|
||||
m_device.pfnDrawPrimitive(&dp, nullptr);
|
||||
if (srcRgn)
|
||||
{
|
||||
auto srcRects(srcRgn.getRects());
|
||||
for (const auto& sr : srcRects)
|
||||
{
|
||||
RectF dr = Rect::toRectF(sr);
|
||||
Rect::transform(dr, srcRect, dstRect);
|
||||
drawRect(vertices, sr, dr, srcWidth, srcHeight);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
drawRect(vertices, srcRect, Rect::toRectF(dstRect), srcWidth, srcHeight);
|
||||
}
|
||||
|
||||
m_device.flushPrimitives();
|
||||
}
|
||||
|
||||
@ -133,9 +150,10 @@ namespace D3dDdi
|
||||
return { data.ShaderHandle, ResourceDeleter(m_device, m_device.getOrigVtable().pfnDeleteVertexShaderDecl) };
|
||||
}
|
||||
|
||||
void ShaderBlitter::cursorBlt(const Resource& dstResource, UINT dstSubResourceIndex, HCURSOR cursor, POINT pt)
|
||||
void ShaderBlitter::cursorBlt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
|
||||
HCURSOR cursor, POINT pt)
|
||||
{
|
||||
LOG_FUNC("ShaderBlitter::cursorBlt", static_cast<HANDLE>(dstResource), dstSubResourceIndex, cursor, pt);
|
||||
LOG_FUNC("ShaderBlitter::cursorBlt", static_cast<HANDLE>(dstResource), dstSubResourceIndex, dstRect, cursor, pt);
|
||||
|
||||
auto& repo = SurfaceRepository::get(m_device.getAdapter());
|
||||
auto cur = repo.getCursor(cursor);
|
||||
@ -143,21 +161,21 @@ namespace D3dDdi
|
||||
|
||||
pt.x -= cur.hotspot.x;
|
||||
pt.y -= cur.hotspot.y;
|
||||
RECT dstRect = { pt.x, pt.y, pt.x + cur.size.cx, pt.y + cur.size.cy };
|
||||
RECT srcRect = { pt.x, pt.y, pt.x + cur.size.cx, pt.y + cur.size.cy };
|
||||
|
||||
auto& dstDesc = dstResource.getFixedDesc().pSurfList[dstSubResourceIndex];
|
||||
RECT clippedDstRect = {};
|
||||
clippedDstRect.right = dstDesc.Width;
|
||||
clippedDstRect.bottom = dstDesc.Height;
|
||||
IntersectRect(&clippedDstRect, &clippedDstRect, &dstRect);
|
||||
RECT monitorRect = DDraw::PrimarySurface::getMonitorRect();
|
||||
RECT clippedSrcRect = {};
|
||||
IntersectRect(&clippedSrcRect, &srcRect, &monitorRect);
|
||||
|
||||
if (!cur.maskTexture || !cur.colorTexture || !cur.tempTexture || !xorTexture || IsRectEmpty(&clippedDstRect))
|
||||
if (!cur.maskTexture || !cur.colorTexture || !cur.tempTexture || !xorTexture || IsRectEmpty(&clippedSrcRect))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
RECT clippedSrcRect = clippedDstRect;
|
||||
OffsetRect(&clippedSrcRect, -dstRect.left, -dstRect.top);
|
||||
RECT clippedDstRect = clippedSrcRect;
|
||||
Rect::transform(clippedDstRect, monitorRect, dstRect);
|
||||
|
||||
OffsetRect(&clippedSrcRect, -srcRect.left, -srcRect.top);
|
||||
|
||||
D3DDDIARG_BLT data = {};
|
||||
data.hSrcResource = dstResource;
|
||||
@ -174,6 +192,20 @@ namespace D3dDdi
|
||||
m_psDrawCursor.get(), D3DTEXF_POINT);
|
||||
}
|
||||
|
||||
void ShaderBlitter::drawRect(Vertex(&vertices)[4], const RECT& srcRect, const RectF& dstRect, float srcWidth, float srcHeight)
|
||||
{
|
||||
vertices[0] = { dstRect.left - 0.5f, dstRect.top - 0.5f, 0, 1, srcRect.left / srcWidth, srcRect.top / srcHeight };
|
||||
vertices[1] = { dstRect.right - 0.5f, dstRect.top - 0.5f, 0, 1, srcRect.right / srcWidth, srcRect.top / srcHeight };
|
||||
vertices[2] = { dstRect.left - 0.5f, dstRect.bottom - 0.5f, 0, 1, srcRect.left / srcWidth, srcRect.bottom / srcHeight };
|
||||
vertices[3] = { dstRect.right - 0.5f, dstRect.bottom - 0.5f, 0, 1, srcRect.right / srcWidth, srcRect.bottom / srcHeight };
|
||||
|
||||
D3DDDIARG_DRAWPRIMITIVE dp = {};
|
||||
dp.PrimitiveType = D3DPT_TRIANGLESTRIP;
|
||||
dp.VStart = 0;
|
||||
dp.PrimitiveCount = 2;
|
||||
m_device.pfnDrawPrimitive(&dp, nullptr);
|
||||
}
|
||||
|
||||
void ShaderBlitter::genBilinearBlt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
|
||||
const Resource& srcResource, const RECT& srcRect, UINT blurPercent)
|
||||
{
|
||||
@ -201,11 +233,11 @@ namespace D3dDdi
|
||||
blt(dstResource, dstSubResourceIndex, dstRect, srcResource, 0, srcRect, m_psGenBilinear.get(), D3DTEXF_LINEAR);
|
||||
}
|
||||
|
||||
void ShaderBlitter::palettizedBlt(const Resource& dstResource, UINT dstSubResourceIndex,
|
||||
const Resource& srcResource, RGBQUAD palette[256])
|
||||
void ShaderBlitter::palettizedBlt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
|
||||
const Resource& srcResource, const RECT& srcRect, RGBQUAD palette[256])
|
||||
{
|
||||
LOG_FUNC("ShaderBlitter::palettizedBlt", static_cast<HANDLE>(dstResource), dstSubResourceIndex,
|
||||
static_cast<HANDLE>(srcResource), Compat::array(reinterpret_cast<void**>(palette), 256));
|
||||
LOG_FUNC("ShaderBlitter::palettizedBlt", static_cast<HANDLE>(dstResource), dstSubResourceIndex, dstRect,
|
||||
static_cast<HANDLE>(srcResource), srcRect, Compat::array(reinterpret_cast<void**>(palette), 256));
|
||||
|
||||
auto paletteTexture(SurfaceRepository::get(m_device.getAdapter()).getPaletteTexture());
|
||||
if (!paletteTexture)
|
||||
@ -228,11 +260,6 @@ namespace D3dDdi
|
||||
unlock.hResource = *paletteTexture;
|
||||
m_device.getOrigVtable().pfnUnlock(m_device, &unlock);
|
||||
|
||||
const auto& dstSurface = dstResource.getFixedDesc().pSurfList[dstSubResourceIndex];
|
||||
const auto& srcSurface = srcResource.getFixedDesc().pSurfList[0];
|
||||
const RECT dstRect = { 0, 0, static_cast<LONG>(dstSurface.Width), static_cast<LONG>(dstSurface.Height) };
|
||||
const RECT srcRect = { 0, 0, static_cast<LONG>(srcSurface.Width), static_cast<LONG>(srcSurface.Height) };
|
||||
|
||||
setTempTextureStage(1, *paletteTexture, D3DTEXF_POINT);
|
||||
blt(dstResource, dstSubResourceIndex, dstRect, srcResource, 0, srcRect, m_psPaletteLookup.get(), D3DTEXF_POINT);
|
||||
}
|
||||
@ -246,15 +273,14 @@ namespace D3dDdi
|
||||
state.setTempTextureStageState({ stage, D3DDDITSS_MAGFILTER, filter });
|
||||
state.setTempTextureStageState({ stage, D3DDDITSS_MINFILTER, filter });
|
||||
state.setTempTextureStageState({ stage, D3DDDITSS_MIPFILTER, D3DTEXF_NONE });
|
||||
state.setTempTextureStageState({ stage, D3DDDITSS_SRGBTEXTURE, D3DTEXF_LINEAR == filter });
|
||||
state.setTempRenderState({ static_cast<D3DDDIRENDERSTATETYPE>(D3DDDIRS_WRAP0 + stage), 0 });
|
||||
}
|
||||
|
||||
void ShaderBlitter::textureBlt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
|
||||
const Resource& srcResource, UINT srcSubResourceIndex, const RECT& srcRect,
|
||||
UINT filter, const UINT* srcColorKey)
|
||||
UINT filter, const UINT* srcColorKey, const BYTE* alpha, const Gdi::Region& srcRgn)
|
||||
{
|
||||
blt(dstResource, dstSubResourceIndex, dstRect, srcResource, srcSubResourceIndex, srcRect,
|
||||
m_psTextureSampler.get(), filter, srcColorKey);
|
||||
m_psTextureSampler.get(), filter, srcColorKey, alpha, srcRgn);
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,9 @@
|
||||
#include <Windows.h>
|
||||
|
||||
#include <D3dDdi/ResourceDeleter.h>
|
||||
#include <Gdi/Region.h>
|
||||
|
||||
struct RectF;
|
||||
|
||||
namespace D3dDdi
|
||||
{
|
||||
@ -20,19 +23,32 @@ namespace D3dDdi
|
||||
ShaderBlitter& operator=(const ShaderBlitter&) = delete;
|
||||
ShaderBlitter& operator=(ShaderBlitter&&) = delete;
|
||||
|
||||
void cursorBlt(const Resource& dstResource, UINT dstSubResourceIndex, HCURSOR cursor, POINT pt);
|
||||
void cursorBlt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
|
||||
HCURSOR cursor, POINT pt);
|
||||
void genBilinearBlt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
|
||||
const Resource& srcResource, const RECT& srcRect, UINT blurPercent);
|
||||
void palettizedBlt(const Resource& dstResource, UINT dstSubResourceIndex,
|
||||
const Resource& srcResource, RGBQUAD palette[256]);
|
||||
void palettizedBlt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
|
||||
const Resource& srcResource, 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);
|
||||
UINT filter, const UINT* srcColorKey = nullptr, const BYTE* alpha = nullptr,
|
||||
const Gdi::Region& srcRgn = nullptr);
|
||||
|
||||
private:
|
||||
struct Vertex
|
||||
{
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
float rhw;
|
||||
float tu;
|
||||
float tv;
|
||||
};
|
||||
|
||||
void blt(const Resource& dstResource, UINT dstSubResourceIndex, const RECT& dstRect,
|
||||
const Resource& srcResource, UINT srcSubResourceIndex, const RECT& srcRect,
|
||||
HANDLE pixelShader, UINT filter, const UINT* srcColorKey = nullptr);
|
||||
HANDLE pixelShader, UINT filter, const UINT* srcColorKey = nullptr, const BYTE* alpha = nullptr,
|
||||
const Gdi::Region& srcRgn = nullptr);
|
||||
|
||||
template <int N>
|
||||
std::unique_ptr<void, ResourceDeleter> createPixelShader(const BYTE(&code)[N])
|
||||
@ -42,6 +58,7 @@ namespace D3dDdi
|
||||
|
||||
std::unique_ptr<void, ResourceDeleter> createPixelShader(const BYTE* code, UINT size);
|
||||
std::unique_ptr<void, ResourceDeleter> createVertexShaderDecl();
|
||||
void drawRect(Vertex(&vertices)[4], const RECT& srcRect, const RectF& dstRect, float srcWidth, float srcHeight);
|
||||
void setTempTextureStage(UINT stage, HANDLE texture, UINT filter, const UINT* srcColorKey = nullptr);
|
||||
|
||||
Device& m_device;
|
||||
|
@ -239,9 +239,13 @@ namespace D3dDdi
|
||||
return surface;
|
||||
}
|
||||
|
||||
const SurfaceRepository::Surface& SurfaceRepository::getTempRenderTarget(DWORD width, DWORD height)
|
||||
const SurfaceRepository::Surface& SurfaceRepository::getTempRenderTarget(DWORD width, DWORD height, UINT index)
|
||||
{
|
||||
return getTempSurface(m_renderTarget, width, height, getPixelFormat(D3DDDIFMT_A8R8G8B8),
|
||||
if (index >= m_renderTargets.size())
|
||||
{
|
||||
m_renderTargets.resize(index + 1);
|
||||
}
|
||||
return getTempSurface(m_renderTargets[index], width, height, getPixelFormat(D3DDDIFMT_A8R8G8B8),
|
||||
DDSCAPS_3DDEVICE | DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY);
|
||||
}
|
||||
|
||||
@ -251,6 +255,12 @@ namespace D3dDdi
|
||||
return getSurface(surface, max(width, surface.width), max(height, surface.height), pf, caps, surfaceCount);
|
||||
}
|
||||
|
||||
SurfaceRepository::Surface& SurfaceRepository::getTempSysMemSurface(DWORD width, DWORD height)
|
||||
{
|
||||
return getTempSurface(m_sysMemSurface, width, height, getPixelFormat(D3DDDIFMT_A8R8G8B8),
|
||||
DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY);
|
||||
}
|
||||
|
||||
const SurfaceRepository::Surface& SurfaceRepository::getTempTexture(DWORD width, DWORD height, const DDPIXELFORMAT& pf)
|
||||
{
|
||||
return getTempSurface(m_textures[pf], width, height, pf, DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY);
|
||||
|
@ -40,7 +40,8 @@ namespace D3dDdi
|
||||
Resource* getPaletteTexture();
|
||||
Surface& getSurface(Surface& surface, DWORD width, DWORD height,
|
||||
const DDPIXELFORMAT& pf, DWORD caps, UINT surfaceCount = 1);
|
||||
const Surface& getTempRenderTarget(DWORD width, DWORD height);
|
||||
const Surface& getTempRenderTarget(DWORD width, DWORD height, UINT index = 0);
|
||||
Surface& getTempSysMemSurface(DWORD width, DWORD height);
|
||||
Surface& getTempSurface(Surface& surface, DWORD width, DWORD height,
|
||||
const DDPIXELFORMAT& pf, DWORD caps, UINT surfaceCount = 1);
|
||||
const Surface& getTempTexture(DWORD width, DWORD height, const DDPIXELFORMAT& pf);
|
||||
@ -68,9 +69,10 @@ namespace D3dDdi
|
||||
Surface m_cursorTempTexture;
|
||||
Surface m_logicalXorTexture;
|
||||
Surface m_paletteTexture;
|
||||
Surface m_renderTarget;
|
||||
std::vector<Surface> m_renderTargets;
|
||||
std::map<DDPIXELFORMAT, Surface> m_textures;
|
||||
std::vector<Surface> m_releasedSurfaces;
|
||||
Surface m_sysMemSurface;
|
||||
|
||||
static bool s_inCreateSurface;
|
||||
};
|
||||
|
@ -136,14 +136,10 @@ namespace
|
||||
g_frontBuffer->GetSurfaceDesc(g_frontBuffer, &desc);
|
||||
|
||||
g_clipper.release();
|
||||
CALL_ORIG_PROC(DirectDrawCreateClipper)(0, &g_clipper.getRef(), nullptr);
|
||||
g_frontBuffer->SetClipper(g_frontBuffer, g_clipper);
|
||||
|
||||
const bool isFlippable = 0 != (desc.ddsCaps.dwCaps & DDSCAPS_FLIP);
|
||||
if (!isFlippable)
|
||||
{
|
||||
CALL_ORIG_PROC(DirectDrawCreateClipper)(0, &g_clipper.getRef(), nullptr);
|
||||
g_frontBuffer->SetClipper(g_frontBuffer, g_clipper);
|
||||
}
|
||||
|
||||
g_surfaceDesc = desc;
|
||||
g_isFullscreen = isFlippable;
|
||||
g_isUpdatePending = true;
|
||||
|
@ -201,6 +201,7 @@
|
||||
<ClInclude Include="Common\HResultException.h" />
|
||||
<ClInclude Include="Common\Log.h" />
|
||||
<ClInclude Include="Common\Path.h" />
|
||||
<ClInclude Include="Common\Rect.h" />
|
||||
<ClInclude Include="Common\ScopedSrwLock.h" />
|
||||
<ClInclude Include="Common\VtableHookVisitor.h" />
|
||||
<ClInclude Include="Common\VtableSizeVisitor.h" />
|
||||
@ -331,6 +332,7 @@
|
||||
<ClCompile Include="Common\Log.cpp" />
|
||||
<ClCompile Include="Common\Hook.cpp" />
|
||||
<ClCompile Include="Common\Path.cpp" />
|
||||
<ClCompile Include="Common\Rect.cpp" />
|
||||
<ClCompile Include="Common\Time.cpp" />
|
||||
<ClCompile Include="Config\Config.cpp" />
|
||||
<ClCompile Include="Config\EnumSetting.cpp" />
|
||||
|
@ -510,6 +510,9 @@
|
||||
<ClInclude Include="Config\Settings\ResolutionScale.h">
|
||||
<Filter>Header Files\Config\Settings</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Common\Rect.h">
|
||||
<Filter>Header Files\Common</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Gdi\Gdi.cpp">
|
||||
@ -803,6 +806,9 @@
|
||||
<ClCompile Include="Config\Settings\ResolutionScale.cpp">
|
||||
<Filter>Source Files\Config\Settings</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Common\Rect.cpp">
|
||||
<Filter>Source Files\Common</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="DDrawCompat.rc">
|
||||
|
@ -73,6 +73,17 @@ namespace Gdi
|
||||
SetRectRgn(m_region, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
std::vector<RECT> Region::getRects() const
|
||||
{
|
||||
DWORD rgnSize = GetRegionData(m_region, 0, nullptr);
|
||||
std::vector<unsigned char> rgnDataBuf(rgnSize);
|
||||
auto rgnData = reinterpret_cast<RGNDATA*>(rgnDataBuf.data());
|
||||
|
||||
GetRegionData(m_region, rgnSize, rgnData);
|
||||
auto rects = reinterpret_cast<RECT*>(rgnData->Buffer);
|
||||
return { rects, rects + rgnData->rdh.nCount };
|
||||
}
|
||||
|
||||
bool Region::isEmpty() const
|
||||
{
|
||||
return sizeof(RGNDATAHEADER) == GetRegionData(m_region, 0, nullptr);
|
||||
|
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <vector>
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
@ -19,6 +20,7 @@ namespace Gdi
|
||||
Region& operator=(Region other);
|
||||
|
||||
void clear();
|
||||
std::vector<RECT> getRects() const;
|
||||
bool isEmpty() const;
|
||||
void offset(int x, int y);
|
||||
HRGN release();
|
||||
|
@ -508,59 +508,40 @@ namespace Gdi
|
||||
}
|
||||
}
|
||||
|
||||
bool presentLayered(CompatWeakPtr<IDirectDrawSurface7> dst, const RECT& monitorRect)
|
||||
std::vector<LayeredWindow> getVisibleLayeredWindows()
|
||||
{
|
||||
HDC dstDc = nullptr;
|
||||
|
||||
try
|
||||
std::vector<LayeredWindow> layeredWindows;
|
||||
for (auto it = g_windowZOrder.rbegin(); it != g_windowZOrder.rend(); ++it)
|
||||
{
|
||||
for (auto it = g_windowZOrder.rbegin(); it != g_windowZOrder.rend(); ++it)
|
||||
auto& window = **it;
|
||||
if (window.isLayered && !window.visibleRegion.isEmpty())
|
||||
{
|
||||
auto& window = **it;
|
||||
if (!window.isLayered || window.visibleRegion.isEmpty())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Gdi::Region rgn(window.visibleRegion);
|
||||
rgn &= monitorRect;
|
||||
if (rgn.isEmpty())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
presentLayeredWindow(dst, window.hwnd, window.windowRect, monitorRect, dstDc, &rgn, window.isMenu);
|
||||
}
|
||||
|
||||
auto configWindow = PresentationWindow::getConfigWindow();
|
||||
if (configWindow && configWindow->isVisible())
|
||||
{
|
||||
presentOverlayWindow(dst, configWindow->getWindow(), monitorRect, dstDc);
|
||||
auto capture = Input::getCapture();
|
||||
if (capture && capture != configWindow)
|
||||
{
|
||||
presentOverlayWindow(dst, capture->getWindow(), monitorRect, dstDc);
|
||||
}
|
||||
}
|
||||
|
||||
HWND cursorWindow = Input::getCursorWindow();
|
||||
if (cursorWindow)
|
||||
{
|
||||
presentOverlayWindow(dst, cursorWindow, monitorRect, dstDc);
|
||||
layeredWindows.push_back({ window.hwnd, window.windowRect, window.visibleRegion });
|
||||
}
|
||||
}
|
||||
catch (bool result)
|
||||
|
||||
RECT wr = {};
|
||||
auto configWindow = PresentationWindow::getConfigWindow();
|
||||
if (configWindow && configWindow->isVisible())
|
||||
{
|
||||
return result;
|
||||
GetWindowRect(configWindow->getWindow(), &wr);
|
||||
layeredWindows.push_back({ configWindow->getWindow(), wr, nullptr });
|
||||
auto capture = Input::getCapture();
|
||||
if (capture && capture != configWindow)
|
||||
{
|
||||
GetWindowRect(capture->getWindow(), &wr);
|
||||
layeredWindows.push_back({ capture->getWindow(), wr, nullptr });
|
||||
}
|
||||
}
|
||||
|
||||
if (dstDc)
|
||||
HWND cursorWindow = Input::getCursorWindow();
|
||||
if (cursorWindow)
|
||||
{
|
||||
SelectClipRgn(dstDc, nullptr);
|
||||
dst->ReleaseDC(dst, dstDc);
|
||||
GetWindowRect(cursorWindow, &wr);
|
||||
layeredWindows.push_back({ cursorWindow, wr, nullptr });
|
||||
}
|
||||
|
||||
return false;
|
||||
return layeredWindows;
|
||||
}
|
||||
|
||||
void updateAll()
|
||||
|
@ -10,12 +10,19 @@ namespace Gdi
|
||||
{
|
||||
namespace Window
|
||||
{
|
||||
struct LayeredWindow
|
||||
{
|
||||
HWND hwnd;
|
||||
RECT rect;
|
||||
Gdi::Region region;
|
||||
};
|
||||
|
||||
std::vector<LayeredWindow> getVisibleLayeredWindows();
|
||||
void onStyleChanged(HWND hwnd, WPARAM wParam);
|
||||
void onSyncPaint(HWND hwnd);
|
||||
void present(CompatRef<IDirectDrawSurface7> dst, CompatRef<IDirectDrawSurface7> src,
|
||||
CompatRef<IDirectDrawClipper> clipper);
|
||||
void present(Gdi::Region excludeRegion);
|
||||
bool presentLayered(CompatWeakPtr<IDirectDrawSurface7> dst, const RECT& monitorRect);
|
||||
void updateAll();
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user