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

Use only static colors when default palette is selected

Fixes changing window border/caption colors (issue #86).
This commit is contained in:
narzoul 2021-01-27 09:37:47 +01:00
parent 922d17d283
commit 6e15cb7da7
8 changed files with 107 additions and 93 deletions

View File

@ -26,6 +26,7 @@ namespace
HGDIOBJ savedBrush;
HGDIOBJ savedPen;
HPALETTE savedPalette;
bool useDefaultPalette;
};
typedef std::unordered_map<HDC, CompatDc> CompatDcMap;
@ -151,7 +152,7 @@ namespace Gdi
for (auto& origDcToCompatDc : g_origDcToCompatDc)
{
restoreDc(origDcToCompatDc.second);
Gdi::DcCache::deleteDc(origDcToCompatDc.second.dc);
Gdi::VirtualScreen::deleteDc(origDcToCompatDc.second.dc);
}
g_origDcToCompatDc.clear();
}
@ -166,7 +167,7 @@ namespace Gdi
if (threadId == it->second.threadId)
{
restoreDc(it->second);
Gdi::DcCache::deleteDc(it->second.dc);
Gdi::VirtualScreen::deleteDc(it->second.dc);
it = g_origDcToCompatDc.erase(it);
}
else
@ -195,7 +196,8 @@ namespace Gdi
}
CompatDc compatDc;
compatDc.dc = Gdi::DcCache::getDc();
compatDc.useDefaultPalette = GetStockObject(DEFAULT_PALETTE) == GetCurrentObject(origDc, OBJ_PAL);
compatDc.dc = Gdi::DcCache::getDc(compatDc.useDefaultPalette);
if (!compatDc.dc)
{
return nullptr;
@ -251,7 +253,7 @@ namespace Gdi
if (0 == compatDc.refCount)
{
restoreDc(compatDc);
Gdi::DcCache::releaseDc(compatDc.dc);
Gdi::DcCache::releaseDc(compatDc.dc, compatDc.useDefaultPalette);
g_origDcToCompatDc.erase(origDc);
}
}

View File

@ -1,87 +1,61 @@
#include <algorithm>
#include <map>
#include <memory>
#include <vector>
#include "Common/ScopedCriticalSection.h"
#include "Gdi/DcCache.h"
#include "Gdi/VirtualScreen.h"
#include <Common/ScopedCriticalSection.h>
#include <Gdi/DcCache.h>
#include <Gdi/VirtualScreen.h>
namespace
{
struct Cache
{
std::vector<std::unique_ptr<HDC__, void(*)(HDC)>> cache;
std::vector<std::unique_ptr<HDC__, void(*)(HDC)>> defPalCache;
};
Compat::CriticalSection g_cs;
std::map<DWORD, std::vector<HDC>> g_threadIdToDcCache;
std::map<DWORD, Cache> g_threadIdToDcCache;
}
namespace Gdi
{
namespace DcCache
{
void deleteDc(HDC cachedDc)
{
Compat::ScopedCriticalSection lock(g_cs);
for (auto& threadIdToDcCache : g_threadIdToDcCache)
{
auto& dcCache = threadIdToDcCache.second;
auto it = std::find(dcCache.begin(), dcCache.end(), cachedDc);
if (it != dcCache.end())
{
Gdi::VirtualScreen::deleteDc(*it);
dcCache.erase(it);
return;
}
}
}
void dllProcessDetach()
{
Compat::ScopedCriticalSection lock(g_cs);
for (auto& threadIdToDcCache : g_threadIdToDcCache)
{
for (HDC dc : threadIdToDcCache.second)
{
Gdi::VirtualScreen::deleteDc(dc);
}
}
g_threadIdToDcCache.clear();
}
void dllThreadDetach()
{
Compat::ScopedCriticalSection lock(g_cs);
auto it = g_threadIdToDcCache.find(GetCurrentThreadId());
if (it == g_threadIdToDcCache.end())
{
return;
}
for (HDC dc : it->second)
{
Gdi::VirtualScreen::deleteDc(dc);
}
g_threadIdToDcCache.erase(it);
g_threadIdToDcCache.erase(GetCurrentThreadId());
}
HDC getDc()
HDC getDc(bool useDefaultPalette)
{
Compat::ScopedCriticalSection lock(g_cs);
std::vector<HDC>& dcCache = g_threadIdToDcCache[GetCurrentThreadId()];
auto& cache = g_threadIdToDcCache[GetCurrentThreadId()];
auto& dcCache = useDefaultPalette ? cache.defPalCache : cache.cache;
if (dcCache.empty())
{
return Gdi::VirtualScreen::createDc();
return Gdi::VirtualScreen::createDc(useDefaultPalette);
}
HDC dc = dcCache.back();
HDC dc = dcCache.back().release();
dcCache.pop_back();
return dc;
}
void releaseDc(HDC cachedDc)
void releaseDc(HDC cachedDc, bool useDefaultPalette)
{
Compat::ScopedCriticalSection lock(g_cs);
g_threadIdToDcCache[GetCurrentThreadId()].push_back(cachedDc);
auto& cache = g_threadIdToDcCache[GetCurrentThreadId()];
auto& dcCache = useDefaultPalette ? cache.defPalCache : cache.cache;
dcCache.emplace_back(cachedDc, Gdi::VirtualScreen::deleteDc);
}
}
}

View File

@ -6,10 +6,9 @@ namespace Gdi
{
namespace DcCache
{
void deleteDc(HDC cachedDc);
void dllProcessDetach();
void dllThreadDetach();
HDC getDc();
void releaseDc(HDC cachedDc);
HDC getDc(bool useDefaultPalette);
void releaseDc(HDC cachedDc, bool useDefaultPalette);
}
}

View File

@ -214,7 +214,8 @@ namespace
LOG_FUNC("CreateCompatibleBitmap", hdc, cx, cy);
if (g_redirectToDib && Gdi::isDisplayDc(hdc))
{
return LOG_RESULT(Gdi::VirtualScreen::createOffScreenDib(cx, cy));
const bool useDefaultPalette = false;
return LOG_RESULT(Gdi::VirtualScreen::createOffScreenDib(cx, cy, useDefaultPalette));
}
return LOG_RESULT(CALL_ORIG_FUNC(CreateCompatibleBitmap)(hdc, cx, cy));
}
@ -226,7 +227,9 @@ namespace
const DWORD CBM_CREATDIB = 2;
if (g_redirectToDib && !(fdwInit & CBM_CREATDIB) && lpbmih && Gdi::isDisplayDc(hdc))
{
HBITMAP bitmap = Gdi::VirtualScreen::createOffScreenDib(lpbmi->bmiHeader.biWidth, lpbmi->bmiHeader.biHeight);
const bool useDefaultPalette = false;
HBITMAP bitmap = Gdi::VirtualScreen::createOffScreenDib(
lpbmi->bmiHeader.biWidth, lpbmi->bmiHeader.biHeight, useDefaultPalette);
if (bitmap && lpbInit && lpbmi)
{
SetDIBits(hdc, bitmap, 0, std::abs(lpbmi->bmiHeader.biHeight), lpbInit, lpbmi, fuUsage);
@ -241,7 +244,8 @@ namespace
LOG_FUNC("CreateDiscardableBitmap", hdc, nWidth, nHeight);
if (g_redirectToDib && Gdi::isDisplayDc(hdc))
{
return LOG_RESULT(Gdi::VirtualScreen::createOffScreenDib(nWidth, nHeight));
const bool useDefaultPalette = false;
return LOG_RESULT(Gdi::VirtualScreen::createOffScreenDib(nWidth, nHeight, useDefaultPalette));
}
return LOG_RESULT(CALL_ORIG_FUNC(createDiscardableBitmap)(hdc, nWidth, nHeight));
}

View File

@ -308,7 +308,8 @@ namespace
RECT r = {};
GetClientRect(hwnd, &r);
HDC dc = CreateCompatibleDC(nullptr);
HBITMAP dib = Gdi::VirtualScreen::createOffScreenDib(r.right, r.bottom);
const bool useDefaultPalette = true;
HBITMAP dib = Gdi::VirtualScreen::createOffScreenDib(r.right, r.bottom, useDefaultPalette);
HGDIOBJ origBitmap = SelectObject(dc, dib);
CallWindowProc(origWndProc, hwnd, WM_ERASEBKGND, reinterpret_cast<WPARAM>(dc), 0);
LRESULT result = CallWindowProc(origWndProc, hwnd, msg, reinterpret_cast<WPARAM>(dc), lParam);

View File

@ -1,20 +1,25 @@
#include <set>
#include <map>
#include "Config/Config.h"
#include "Common/ScopedCriticalSection.h"
#include "D3dDdi/Device.h"
#include "D3dDdi/ScopedCriticalSection.h"
#include "DDraw/DirectDraw.h"
#include "DDraw/RealPrimarySurface.h"
#include "DDraw/ScopedThreadLock.h"
#include "DDraw/Surfaces/PrimarySurface.h"
#include "Gdi/Gdi.h"
#include "Gdi/Region.h"
#include "Gdi/VirtualScreen.h"
#include "Win32/DisplayMode.h"
#include <Config/Config.h>
#include <Common/ScopedCriticalSection.h>
#include <D3dDdi/Device.h>
#include <D3dDdi/ScopedCriticalSection.h>
#include <DDraw/DirectDraw.h>
#include <DDraw/RealPrimarySurface.h>
#include <DDraw/ScopedThreadLock.h>
#include <DDraw/Surfaces/PrimarySurface.h>
#include <Gdi/Gdi.h>
#include <Gdi/Region.h>
#include <Gdi/VirtualScreen.h>
#include <Win32/DisplayMode.h>
namespace
{
struct VirtualScreenDc
{
bool useDefaultPalette;
};
Compat::CriticalSection g_cs;
Gdi::Region g_region;
RECT g_bounds = {};
@ -26,8 +31,9 @@ namespace
void* g_surfaceView = nullptr;
HGDIOBJ g_stockBitmap = nullptr;
RGBQUAD g_defaultPalette[256] = {};
RGBQUAD g_systemPalette[256] = {};
std::set<HDC> g_dcs;
std::map<HDC, VirtualScreenDc> g_dcs;
BOOL CALLBACK addMonitorRectToRegion(
HMONITOR /*hMonitor*/, HDC /*hdcMonitor*/, LPRECT lprcMonitor, LPARAM dwData)
@ -38,7 +44,16 @@ namespace
return TRUE;
}
HBITMAP createDibSection(LONG width, LONG height, HANDLE section)
RGBQUAD convertToRgbQuad(PALETTEENTRY entry)
{
RGBQUAD quad = {};
quad.rgbRed = entry.peRed;
quad.rgbGreen = entry.peGreen;
quad.rgbBlue = entry.peBlue;
return quad;
}
HBITMAP createDibSection(LONG width, LONG height, HANDLE section, bool useDefaultPalette)
{
struct BITMAPINFO256 : public BITMAPINFO
{
@ -55,7 +70,14 @@ namespace
if (8 == g_bpp)
{
memcpy(bmi.bmiColors, g_systemPalette, sizeof(g_systemPalette));
if (useDefaultPalette)
{
memcpy(bmi.bmiColors, g_defaultPalette, sizeof(g_defaultPalette));
}
else
{
memcpy(bmi.bmiColors, g_systemPalette, sizeof(g_systemPalette));
}
}
else
{
@ -74,10 +96,10 @@ namespace Gdi
{
namespace VirtualScreen
{
HDC createDc()
HDC createDc(bool useDefaultPalette)
{
Compat::ScopedCriticalSection lock(g_cs);
std::unique_ptr<void, decltype(&DeleteObject)> dib(createDib(), DeleteObject);
std::unique_ptr<void, decltype(&DeleteObject)> dib(createDib(useDefaultPalette), DeleteObject);
if (!dib)
{
return nullptr;
@ -98,24 +120,24 @@ namespace Gdi
dib.release();
g_stockBitmap = stockBitmap;
g_dcs.insert(dc.get());
g_dcs[dc.get()] = { useDefaultPalette };
return dc.release();
}
HBITMAP createDib()
HBITMAP createDib(bool useDefaultPalette)
{
Compat::ScopedCriticalSection lock(g_cs);
if (!g_surfaceFileMapping)
{
return nullptr;
}
return createDibSection(g_width, -g_height, g_surfaceFileMapping);
return createDibSection(g_width, -g_height, g_surfaceFileMapping, useDefaultPalette);
}
HBITMAP createOffScreenDib(LONG width, LONG height)
HBITMAP createOffScreenDib(LONG width, LONG height, bool useDefaultPalette)
{
Compat::ScopedCriticalSection lock(g_cs);
return createDibSection(width, height, nullptr);
return createDibSection(width, height, nullptr, useDefaultPalette);
}
CompatPtr<IDirectDrawSurface7> createSurface(const RECT& rect)
@ -190,6 +212,16 @@ namespace Gdi
void init()
{
PALETTEENTRY entries[20] = {};
HPALETTE defaultPalette = reinterpret_cast<HPALETTE>(GetStockObject(DEFAULT_PALETTE));
GetPaletteEntries(defaultPalette, 0, 20, entries);
for (int i = 0; i < 10; ++i)
{
g_defaultPalette[i] = convertToRgbQuad(entries[i]);
g_defaultPalette[246 + i] = convertToRgbQuad(entries[10 + i]);
}
update();
}
@ -223,9 +255,9 @@ namespace Gdi
if (g_surfaceFileMapping)
{
for (HDC dc : g_dcs)
for (auto& dc : g_dcs)
{
DeleteObject(SelectObject(dc, g_stockBitmap));
DeleteObject(SelectObject(dc.first, g_stockBitmap));
}
UnmapViewOfFile(g_surfaceView);
CloseHandle(g_surfaceFileMapping);
@ -235,9 +267,9 @@ namespace Gdi
g_pitch * g_height + 8, nullptr);
g_surfaceView = MapViewOfFile(g_surfaceFileMapping, FILE_MAP_WRITE, 0, 0, 0);
for (HDC dc : g_dcs)
for (auto& dc : g_dcs)
{
SelectObject(dc, createDib());
SelectObject(dc.first, createDib(dc.second.useDefaultPalette));
}
}
@ -252,17 +284,18 @@ namespace Gdi
RGBQUAD systemPalette[256] = {};
for (int i = 0; i < 256; ++i)
{
systemPalette[i].rgbRed = palette[i].peRed;
systemPalette[i].rgbGreen = palette[i].peGreen;
systemPalette[i].rgbBlue = palette[i].peBlue;
systemPalette[i] = convertToRgbQuad(palette[i]);
}
if (0 != memcmp(g_systemPalette, systemPalette, sizeof(systemPalette)))
{
memcpy(g_systemPalette, systemPalette, sizeof(systemPalette));
for (HDC dc : g_dcs)
for (auto& dc : g_dcs)
{
SetDIBColorTable(dc, 0, 256, systemPalette);
if (!dc.second.useDefaultPalette)
{
SetDIBColorTable(dc.first, 0, 256, systemPalette);
}
}
}

View File

@ -10,9 +10,9 @@ namespace Gdi
namespace VirtualScreen
{
HDC createDc();
HBITMAP createDib();
HBITMAP createOffScreenDib(LONG width, LONG height);
HDC createDc(bool useDefaultPalette);
HBITMAP createDib(bool useDefaultPalette);
HBITMAP createOffScreenDib(LONG width, LONG height, bool useDefaultPalette);
CompatPtr<IDirectDrawSurface7> createSurface(const RECT& rect);
void deleteDc(HDC dc);

View File

@ -429,7 +429,8 @@ namespace Gdi
if (!virtualScreenDc)
{
virtualScreenDc.reset(Gdi::VirtualScreen::createDc());
const bool useDefaultPalette = false;
virtualScreenDc.reset(Gdi::VirtualScreen::createDc(useDefaultPalette));
if (!virtualScreenDc)
{
return;