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:
parent
922d17d283
commit
6e15cb7da7
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user