mirror of
https://github.com/narzoul/DDrawCompat
synced 2024-12-30 08:55:36 +01:00
Fixed presentation of layered windows in scaled fullscreen mode
This commit is contained in:
parent
ccc23c75b9
commit
f7962f6e3b
@ -16,6 +16,7 @@
|
||||
#include <Gdi/Cursor.h>
|
||||
#include <Gdi/Palette.h>
|
||||
#include <Gdi/VirtualScreen.h>
|
||||
#include <Gdi/Window.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
@ -537,15 +538,19 @@ namespace D3dDdi
|
||||
srcResource->copyToVidMem(0);
|
||||
}
|
||||
|
||||
const auto& si = srcResource->m_fixedData.pSurfList[0];
|
||||
const bool isPalettized = D3DDDIFMT_P8 == srcResource->m_origData.Format;
|
||||
|
||||
const auto cursorInfo = Gdi::Cursor::getEmulatedCursorInfo();
|
||||
const bool isCursorEmulated = cursorInfo.flags == CURSOR_SHOWING && cursorInfo.hCursor;
|
||||
|
||||
if (isPalettized || isCursorEmulated)
|
||||
const RECT monitorRect = DDraw::PrimarySurface::getMonitorRect();
|
||||
const bool isLayeredPresentNeeded = Gdi::Window::presentLayered(nullptr, monitorRect);
|
||||
|
||||
if (isPalettized || isCursorEmulated || isLayeredPresentNeeded)
|
||||
{
|
||||
auto dst(SurfaceRepository::get(m_device.getAdapter()).getRenderTarget(si.Width, si.Height));
|
||||
if (!dst)
|
||||
const auto& si = srcResource->m_fixedData.pSurfList[0];
|
||||
const auto& dst(SurfaceRepository::get(m_device.getAdapter()).getRenderTarget(si.Width, si.Height));
|
||||
if (!dst.resource)
|
||||
{
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
@ -560,28 +565,32 @@ namespace D3dDdi
|
||||
pal[i].rgbGreen = entries[i].peGreen;
|
||||
pal[i].rgbBlue = entries[i].peBlue;
|
||||
}
|
||||
m_device.getShaderBlitter().palettizedBlt(*dst, 0, *srcResource, pal);
|
||||
m_device.getShaderBlitter().palettizedBlt(*dst.resource, 0, *srcResource, pal);
|
||||
}
|
||||
else
|
||||
{
|
||||
D3DDDIARG_BLT blt = {};
|
||||
blt.hSrcResource = data.hSrcResource;
|
||||
blt.SrcRect = data.SrcRect;
|
||||
blt.hDstResource = *dst;
|
||||
blt.hDstResource = *dst.resource;
|
||||
blt.DstRect = data.SrcRect;
|
||||
blt.Flags.Point = 1;
|
||||
m_device.getOrigVtable().pfnBlt(m_device, &blt);
|
||||
}
|
||||
|
||||
srcResource = dst;
|
||||
data.hSrcResource = *dst;
|
||||
}
|
||||
srcResource = dst.resource;
|
||||
data.hSrcResource = *dst.resource;
|
||||
|
||||
if (isCursorEmulated)
|
||||
{
|
||||
RECT monitorRect = DDraw::PrimarySurface::getMonitorRect();
|
||||
POINT pos = { cursorInfo.ptScreenPos.x - monitorRect.left, cursorInfo.ptScreenPos.y - monitorRect.top };
|
||||
m_device.getShaderBlitter().cursorBlt(*srcResource, 0, cursorInfo.hCursor, pos);
|
||||
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(*srcResource, 0, cursorInfo.hCursor, pos);
|
||||
}
|
||||
}
|
||||
|
||||
data.DstRect = g_presentationRect;
|
||||
|
@ -205,13 +205,19 @@ namespace D3dDdi
|
||||
DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY);
|
||||
}
|
||||
|
||||
Resource* SurfaceRepository::getRenderTarget(DWORD width, DWORD height)
|
||||
const SurfaceRepository::Surface& SurfaceRepository::getRenderTarget(DWORD width, DWORD height)
|
||||
{
|
||||
return getResource(m_renderTarget, width, height, DDraw::DirectDraw::getRgbPixelFormat(32),
|
||||
return getSurface(m_renderTarget, width, height, DDraw::DirectDraw::getRgbPixelFormat(32),
|
||||
DDSCAPS_3DDEVICE | DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY);
|
||||
}
|
||||
|
||||
Resource* SurfaceRepository::getResource(Surface& surface, DWORD width, DWORD height, const DDPIXELFORMAT& pf, DWORD caps)
|
||||
{
|
||||
return getSurface(surface, width, height, pf, caps).resource;
|
||||
}
|
||||
|
||||
SurfaceRepository::Surface& SurfaceRepository::getSurface(Surface& surface, DWORD width, DWORD height,
|
||||
const DDPIXELFORMAT& pf, DWORD caps)
|
||||
{
|
||||
if (surface.surface && (surface.width != width || surface.height != height ||
|
||||
0 != memcmp(&surface.pixelFormat, &pf, sizeof(pf)) || isLost(surface)))
|
||||
@ -232,7 +238,7 @@ namespace D3dDdi
|
||||
}
|
||||
}
|
||||
|
||||
return surface.resource;
|
||||
return surface;
|
||||
}
|
||||
|
||||
bool SurfaceRepository::isLost(Surface& surface)
|
||||
|
@ -24,14 +24,6 @@ namespace D3dDdi
|
||||
Resource* tempTexture;
|
||||
};
|
||||
|
||||
Cursor getCursor(HCURSOR cursor);
|
||||
Resource* getLogicalXorTexture();
|
||||
Resource* getPaletteTexture();
|
||||
Resource* getRenderTarget(DWORD width, DWORD height);
|
||||
|
||||
static SurfaceRepository& get(const Adapter& adapter);
|
||||
|
||||
private:
|
||||
struct Surface
|
||||
{
|
||||
CompatWeakPtr<IDirectDrawSurface7> surface;
|
||||
@ -41,6 +33,14 @@ namespace D3dDdi
|
||||
DDPIXELFORMAT pixelFormat;
|
||||
};
|
||||
|
||||
Cursor getCursor(HCURSOR cursor);
|
||||
Resource* getLogicalXorTexture();
|
||||
Resource* getPaletteTexture();
|
||||
const Surface& getRenderTarget(DWORD width, DWORD height);
|
||||
|
||||
static SurfaceRepository& get(const Adapter& adapter);
|
||||
|
||||
private:
|
||||
SurfaceRepository(const Adapter& adapter);
|
||||
|
||||
CompatWeakPtr<IDirectDrawSurface7> createSurface(DWORD width, DWORD height, const DDPIXELFORMAT& pf, DWORD caps);
|
||||
@ -48,6 +48,7 @@ namespace D3dDdi
|
||||
Resource* getInitializedResource(Surface& surface, DWORD width, DWORD height, const DDPIXELFORMAT& pf, DWORD caps,
|
||||
std::function<void(const DDSURFACEDESC2&)> initFunc);
|
||||
Resource* getResource(Surface& surface, DWORD width, DWORD height, const DDPIXELFORMAT& pf, DWORD caps);
|
||||
Surface& getSurface(Surface& surface, DWORD width, DWORD height, const DDPIXELFORMAT& pf, DWORD caps);
|
||||
bool isLost(Surface& surface);
|
||||
void release(Surface& surface);
|
||||
|
||||
|
@ -176,16 +176,6 @@ namespace
|
||||
D3dDdi::KernelModeThunks::setDcPaletteOverride(palette.data());
|
||||
bltToPrimaryChain(*src);
|
||||
D3dDdi::KernelModeThunks::setDcPaletteOverride(nullptr);
|
||||
|
||||
if (g_isFullScreen && src == DDraw::PrimarySurface::getGdiSurface())
|
||||
{
|
||||
auto backBuffer(getBackBuffer());
|
||||
if (backBuffer)
|
||||
{
|
||||
POINT offset = { -g_monitorRect.left, -g_monitorRect.top };
|
||||
Gdi::Window::presentLayered(*backBuffer, offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void updateNow(CompatWeakPtr<IDirectDrawSurface7> src, UINT flipInterval)
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include <Common/Log.h>
|
||||
#include <Common/ScopedSrwLock.h>
|
||||
#include <Dll/Dll.h>
|
||||
#include <DDraw/RealPrimarySurface.h>
|
||||
#include <Gdi/CompatDc.h>
|
||||
#include <Gdi/Cursor.h>
|
||||
#include <Gdi/Dc.h>
|
||||
@ -268,11 +269,9 @@ namespace
|
||||
{
|
||||
LOG_FUNC("SetLayeredWindowAttributes", hwnd, crKey, bAlpha, dwFlags);
|
||||
BOOL result = CALL_ORIG_FUNC(SetLayeredWindowAttributes)(hwnd, crKey, bAlpha, dwFlags);
|
||||
if (result)
|
||||
if (result && DDraw::RealPrimarySurface::isFullScreen())
|
||||
{
|
||||
Gdi::Window::updateLayeredWindowInfo(hwnd,
|
||||
(dwFlags & LWA_COLORKEY) ? crKey : CLR_INVALID,
|
||||
(dwFlags & LWA_ALPHA) ? bAlpha : 255);
|
||||
DDraw::RealPrimarySurface::scheduleUpdate();
|
||||
}
|
||||
return LOG_RESULT(result);
|
||||
}
|
||||
@ -340,34 +339,6 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
BOOL WINAPI updateLayeredWindow(HWND hWnd, HDC hdcDst, POINT* pptDst, SIZE* psize,
|
||||
HDC hdcSrc, POINT* pptSrc, COLORREF crKey, BLENDFUNCTION* pblend, DWORD dwFlags)
|
||||
{
|
||||
LOG_FUNC("UpdateLayeredWindow", hWnd, hdcDst, pptDst, psize, hdcSrc, pptSrc, crKey, pblend, dwFlags);
|
||||
BOOL result = CALL_ORIG_FUNC(UpdateLayeredWindow)(
|
||||
hWnd, hdcDst, pptDst, psize, hdcSrc, pptSrc, crKey, pblend, dwFlags);
|
||||
if (result && hdcSrc)
|
||||
{
|
||||
Gdi::Window::updateLayeredWindowInfo(hWnd,
|
||||
(dwFlags & ULW_COLORKEY) ? crKey : CLR_INVALID,
|
||||
((dwFlags & LWA_ALPHA) && pblend) ? pblend->SourceConstantAlpha : 255);
|
||||
}
|
||||
return LOG_RESULT(result);
|
||||
}
|
||||
|
||||
BOOL WINAPI updateLayeredWindowIndirect(HWND hwnd, const UPDATELAYEREDWINDOWINFO* pULWInfo)
|
||||
{
|
||||
LOG_FUNC("UpdateLayeredWindowIndirect", hwnd, pULWInfo);
|
||||
BOOL result = CALL_ORIG_FUNC(UpdateLayeredWindowIndirect)(hwnd, pULWInfo);
|
||||
if (result && pULWInfo)
|
||||
{
|
||||
Gdi::Window::updateLayeredWindowInfo(hwnd,
|
||||
(pULWInfo->dwFlags & ULW_COLORKEY) ? pULWInfo->crKey : CLR_INVALID,
|
||||
((pULWInfo->dwFlags & LWA_ALPHA) && pULWInfo->pblend) ? pULWInfo->pblend->SourceConstantAlpha : 255);
|
||||
}
|
||||
return LOG_RESULT(result);
|
||||
}
|
||||
|
||||
void CALLBACK winEventProc(
|
||||
HWINEVENTHOOK /*hWinEventHook*/,
|
||||
DWORD event,
|
||||
@ -393,7 +364,7 @@ namespace
|
||||
case EVENT_OBJECT_HIDE:
|
||||
if (OBJID_CURSOR == idObject && Gdi::Cursor::isEmulated())
|
||||
{
|
||||
Gdi::Cursor::setCursor(GetCursor());
|
||||
Gdi::Cursor::setCursor(CALL_ORIG_FUNC(GetCursor)());
|
||||
}
|
||||
break;
|
||||
|
||||
@ -465,8 +436,6 @@ namespace Gdi
|
||||
HOOK_FUNCTION(user32, SetWindowLongA, setWindowLongA);
|
||||
HOOK_FUNCTION(user32, SetWindowLongW, setWindowLongW);
|
||||
HOOK_FUNCTION(user32, SetWindowPos, setWindowPos);
|
||||
HOOK_FUNCTION(user32, UpdateLayeredWindow, updateLayeredWindow);
|
||||
HOOK_FUNCTION(user32, UpdateLayeredWindowIndirect, updateLayeredWindowIndirect);
|
||||
|
||||
SetWinEventHook(EVENT_OBJECT_CREATE, EVENT_OBJECT_CREATE,
|
||||
Dll::g_currentModule, &winEventProc, GetCurrentProcessId(), 0, WINEVENT_INCONTEXT);
|
||||
|
@ -31,8 +31,6 @@ namespace
|
||||
Gdi::Region windowRegion;
|
||||
Gdi::Region visibleRegion;
|
||||
Gdi::Region invalidatedRegion;
|
||||
COLORREF colorKey;
|
||||
BYTE alpha;
|
||||
bool isLayered;
|
||||
bool isVisibleRegionChanged;
|
||||
|
||||
@ -42,8 +40,6 @@ namespace
|
||||
, windowRect{}
|
||||
, clientRect{}
|
||||
, windowRegion(nullptr)
|
||||
, colorKey(CLR_INVALID)
|
||||
, alpha(255)
|
||||
, isLayered(true)
|
||||
, isVisibleRegionChanged(false)
|
||||
{
|
||||
@ -447,56 +443,64 @@ namespace Gdi
|
||||
}
|
||||
}
|
||||
|
||||
void presentLayered(CompatRef<IDirectDrawSurface7> dst, POINT offset)
|
||||
bool presentLayered(CompatWeakPtr<IDirectDrawSurface7> dst, const RECT& monitorRect)
|
||||
{
|
||||
D3dDdi::ScopedCriticalSection lock;
|
||||
|
||||
HDC dstDc = nullptr;
|
||||
bool result = false;
|
||||
for (auto it = g_windowZOrder.rbegin(); it != g_windowZOrder.rend(); ++it)
|
||||
{
|
||||
auto& window = **it;
|
||||
if (!window.isLayered)
|
||||
if (!window.isLayered || window.visibleRegion.isEmpty())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Gdi::Region rgn(window.visibleRegion);
|
||||
rgn &= monitorRect;
|
||||
if (rgn.isEmpty())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
RECT wr = window.windowRect;
|
||||
OffsetRect(&wr, -monitorRect.left, -monitorRect.top);
|
||||
rgn.offset(-monitorRect.left, -monitorRect.top);
|
||||
|
||||
if (!dst)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!dstDc)
|
||||
{
|
||||
const UINT D3DDDIFMT_UNKNOWN = 0;
|
||||
const UINT D3DDDIFMT_X8R8G8B8 = 22;
|
||||
D3dDdi::KernelModeThunks::setDcFormatOverride(D3DDDIFMT_X8R8G8B8);
|
||||
dst->GetDC(&dst, &dstDc);
|
||||
D3dDdi::KernelModeThunks::setDcFormatOverride(D3DDDIFMT_UNKNOWN);
|
||||
dst->GetDC(dst, &dstDc);
|
||||
if (!dstDc)
|
||||
{
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
result = true;
|
||||
HDC windowDc = GetWindowDC(window.hwnd);
|
||||
Gdi::Region rgn(window.visibleRegion);
|
||||
RECT wr = window.windowRect;
|
||||
|
||||
if (0 != offset.x || 0 != offset.y)
|
||||
{
|
||||
OffsetRect(&wr, offset.x, offset.y);
|
||||
rgn.offset(offset.x, offset.y);
|
||||
}
|
||||
|
||||
SelectClipRgn(dstDc, rgn);
|
||||
|
||||
auto colorKey = window.colorKey;
|
||||
if (CLR_INVALID != colorKey)
|
||||
COLORREF colorKey = 0;
|
||||
BYTE alpha = 0;
|
||||
DWORD flags = 0;
|
||||
if (CALL_ORIG_FUNC(GetLayeredWindowAttributes)(window.hwnd, &colorKey, &alpha, &flags))
|
||||
{
|
||||
CALL_ORIG_FUNC(TransparentBlt)(dstDc, wr.left, wr.top, wr.right - wr.left, wr.bottom - wr.top,
|
||||
windowDc, 0, 0, wr.right - wr.left, wr.bottom - wr.top, colorKey);
|
||||
}
|
||||
else
|
||||
{
|
||||
BLENDFUNCTION blend = {};
|
||||
blend.SourceConstantAlpha = window.alpha;
|
||||
CALL_ORIG_FUNC(AlphaBlend)(dstDc, wr.left, wr.top, wr.right - wr.left, wr.bottom - wr.top,
|
||||
windowDc, 0, 0, wr.right - wr.left, wr.bottom - wr.top, blend);
|
||||
if (flags & LWA_COLORKEY)
|
||||
{
|
||||
CALL_ORIG_FUNC(TransparentBlt)(dstDc, wr.left, wr.top, wr.right - wr.left, wr.bottom - wr.top,
|
||||
windowDc, 0, 0, wr.right - wr.left, wr.bottom - wr.top, colorKey);
|
||||
}
|
||||
else
|
||||
{
|
||||
BLENDFUNCTION blend = {};
|
||||
blend.SourceConstantAlpha = alpha;
|
||||
CALL_ORIG_FUNC(AlphaBlend)(dstDc, wr.left, wr.top, wr.right - wr.left, wr.bottom - wr.top,
|
||||
windowDc, 0, 0, wr.right - wr.left, wr.bottom - wr.top, blend);
|
||||
}
|
||||
}
|
||||
|
||||
CALL_ORIG_FUNC(ReleaseDC)(window.hwnd, windowDc);
|
||||
@ -505,8 +509,9 @@ namespace Gdi
|
||||
if (dstDc)
|
||||
{
|
||||
SelectClipRgn(dstDc, nullptr);
|
||||
dst->ReleaseDC(&dst, dstDc);
|
||||
dst->ReleaseDC(dst, dstDc);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void updateAll()
|
||||
@ -558,20 +563,5 @@ namespace Gdi
|
||||
SendNotifyMessage(hwnd, WM_SYNCPAINT, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void updateLayeredWindowInfo(HWND hwnd, COLORREF colorKey, BYTE alpha)
|
||||
{
|
||||
D3dDdi::ScopedCriticalSection lock;
|
||||
auto it = g_windows.find(hwnd);
|
||||
if (it != g_windows.end())
|
||||
{
|
||||
it->second.colorKey = colorKey;
|
||||
it->second.alpha = alpha;
|
||||
if (!it->second.visibleRegion.isEmpty())
|
||||
{
|
||||
DDraw::RealPrimarySurface::scheduleUpdate();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
#include <ddraw.h>
|
||||
|
||||
#include <Common/CompatWeakPtr.h>
|
||||
#include <Common/CompatRef.h>
|
||||
#include <Gdi/Region.h>
|
||||
|
||||
@ -14,8 +15,7 @@ namespace Gdi
|
||||
void present(CompatRef<IDirectDrawSurface7> dst, CompatRef<IDirectDrawSurface7> src,
|
||||
CompatRef<IDirectDrawClipper> clipper);
|
||||
void present(Gdi::Region excludeRegion);
|
||||
void presentLayered(CompatRef<IDirectDrawSurface7> dst, POINT offset);
|
||||
bool presentLayered(CompatWeakPtr<IDirectDrawSurface7> dst, const RECT& monitorRect);
|
||||
void updateAll();
|
||||
void updateLayeredWindowInfo(HWND hwnd, COLORREF colorKey, BYTE alpha);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user