mirror of
https://github.com/narzoul/DDrawCompat
synced 2024-12-30 08:55:36 +01:00
Create palettized surfaces in system memory
This commit is contained in:
parent
e6bb6b1e35
commit
26995d6108
@ -1,164 +0,0 @@
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
|
||||
#include "Common/CompatPtr.h"
|
||||
#include "Common/Hook.h"
|
||||
#include "Common/ScopedCriticalSection.h"
|
||||
#include "DDraw/DisplayMode.h"
|
||||
#include "DDraw/PaletteConverter.h"
|
||||
#include "DDraw/RealPrimarySurface.h"
|
||||
#include "DDraw/Repository.h"
|
||||
#include "DDraw/Surfaces/PrimarySurface.h"
|
||||
#include "DDraw/Types.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
HDC g_dc = nullptr;
|
||||
HGDIOBJ g_oldBitmap = nullptr;
|
||||
CompatWeakPtr<IDirectDrawSurface7> g_surface;
|
||||
|
||||
void convertPaletteEntriesToRgbQuad(RGBQUAD* entries, DWORD count)
|
||||
{
|
||||
for (DWORD i = 0; i < count; ++i)
|
||||
{
|
||||
entries[i].rgbReserved = 0;
|
||||
std::swap(entries[i].rgbRed, entries[i].rgbBlue);
|
||||
}
|
||||
}
|
||||
|
||||
HBITMAP createDibSection(const DDSURFACEDESC2& dm, void*& bits)
|
||||
{
|
||||
struct PalettizedBitmapInfo
|
||||
{
|
||||
BITMAPINFOHEADER header;
|
||||
PALETTEENTRY colors[256];
|
||||
};
|
||||
|
||||
PalettizedBitmapInfo bmi = {};
|
||||
bmi.header.biSize = sizeof(bmi.header);
|
||||
bmi.header.biWidth = dm.dwWidth;
|
||||
bmi.header.biHeight = -static_cast<LONG>(dm.dwHeight);
|
||||
bmi.header.biPlanes = 1;
|
||||
bmi.header.biBitCount = static_cast<WORD>(dm.ddpfPixelFormat.dwRGBBitCount);
|
||||
bmi.header.biCompression = BI_RGB;
|
||||
|
||||
return CreateDIBSection(nullptr, reinterpret_cast<BITMAPINFO*>(&bmi),
|
||||
DIB_RGB_COLORS, &bits, nullptr, 0);
|
||||
}
|
||||
|
||||
CompatPtr<IDirectDrawSurface7> createSurface(const DDSURFACEDESC2& dm, void* bits)
|
||||
{
|
||||
DDSURFACEDESC2 desc = {};
|
||||
desc.dwSize = sizeof(desc);
|
||||
desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS |
|
||||
DDSD_PITCH | DDSD_LPSURFACE;
|
||||
desc.dwWidth = dm.dwWidth;
|
||||
desc.dwHeight = dm.dwHeight;
|
||||
desc.ddpfPixelFormat = dm.ddpfPixelFormat;
|
||||
desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
|
||||
desc.lPitch = (dm.dwWidth * dm.ddpfPixelFormat.dwRGBBitCount / 8 + 3) & ~3;
|
||||
desc.lpSurface = bits;
|
||||
|
||||
auto dd(DDraw::Repository::getDirectDraw());
|
||||
CompatPtr<IDirectDrawSurface7> surface;
|
||||
dd->CreateSurface(dd, &desc, &surface.getRef(), nullptr);
|
||||
return surface;
|
||||
}
|
||||
}
|
||||
|
||||
namespace DDraw
|
||||
{
|
||||
namespace PaletteConverter
|
||||
{
|
||||
bool create()
|
||||
{
|
||||
auto dd(Repository::getDirectDraw());
|
||||
auto dm(DisplayMode::getDisplayMode(*dd));
|
||||
DDSURFACEDESC2 realDm = {};
|
||||
realDm.dwSize = sizeof(realDm);
|
||||
dd->GetDisplayMode(dd, &realDm);
|
||||
if (dm.ddpfPixelFormat.dwRGBBitCount > 8 &&
|
||||
realDm.ddpfPixelFormat.dwRGBBitCount > 8)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void* bits = nullptr;
|
||||
HBITMAP dib = createDibSection(dm, bits);
|
||||
if (!dib)
|
||||
{
|
||||
Compat::Log() << "Failed to create the palette converter DIB section";
|
||||
return false;
|
||||
}
|
||||
|
||||
CompatPtr<IDirectDrawSurface7> surface(createSurface(dm, bits));
|
||||
if (!surface)
|
||||
{
|
||||
Compat::Log() << "Failed to create the palette converter surface";
|
||||
DeleteObject(dib);
|
||||
return false;
|
||||
}
|
||||
|
||||
HDC dc = CALL_ORIG_FUNC(CreateCompatibleDC)(nullptr);
|
||||
if (!dc)
|
||||
{
|
||||
Compat::Log() << "Failed to create the palette converter DC";
|
||||
DeleteObject(dib);
|
||||
return false;
|
||||
}
|
||||
|
||||
g_oldBitmap = SelectObject(dc, dib);
|
||||
g_dc = dc;
|
||||
g_surface = surface.detach();
|
||||
return true;
|
||||
}
|
||||
|
||||
HDC getDc()
|
||||
{
|
||||
return g_dc;
|
||||
}
|
||||
|
||||
CompatWeakPtr<IDirectDrawSurface7> getSurface()
|
||||
{
|
||||
return g_surface;
|
||||
}
|
||||
|
||||
void release()
|
||||
{
|
||||
if (!g_surface)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
g_surface.release();
|
||||
|
||||
DeleteObject(SelectObject(g_dc, g_oldBitmap));
|
||||
DeleteDC(g_dc);
|
||||
g_dc = nullptr;
|
||||
}
|
||||
|
||||
void setClipper(CompatWeakPtr<IDirectDrawClipper> clipper)
|
||||
{
|
||||
if (g_surface)
|
||||
{
|
||||
HRESULT result = g_surface->SetClipper(g_surface, clipper);
|
||||
if (FAILED(result))
|
||||
{
|
||||
LOG_ONCE("Failed to set a clipper on the palette converter surface: " << result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void updatePalette(DWORD startingEntry, DWORD count)
|
||||
{
|
||||
if (g_dc && PrimarySurface::s_palette)
|
||||
{
|
||||
RGBQUAD entries[256] = {};
|
||||
std::memcpy(entries, &PrimarySurface::s_paletteEntries[startingEntry],
|
||||
count * sizeof(PALETTEENTRY));
|
||||
convertPaletteEntriesToRgbQuad(entries, count);
|
||||
SetDIBColorTable(g_dc, startingEntry, count, entries);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#define CINTERFACE
|
||||
|
||||
#include <ddraw.h>
|
||||
|
||||
#include "Common/CompatWeakPtr.h"
|
||||
|
||||
namespace DDraw
|
||||
{
|
||||
namespace PaletteConverter
|
||||
{
|
||||
bool create();
|
||||
HDC getDc();
|
||||
CompatWeakPtr<IDirectDrawSurface7> getSurface();
|
||||
void release();
|
||||
void setClipper(CompatWeakPtr<IDirectDrawClipper> clipper);
|
||||
void updatePalette(DWORD startingEntry, DWORD count);
|
||||
}
|
||||
}
|
@ -5,8 +5,8 @@
|
||||
#include "Common/Time.h"
|
||||
#include "Config/Config.h"
|
||||
#include "DDraw/DirectDrawSurface.h"
|
||||
#include "DDraw/DisplayMode.h"
|
||||
#include "DDraw/IReleaseNotifier.h"
|
||||
#include "DDraw/PaletteConverter.h"
|
||||
#include "DDraw/RealPrimarySurface.h"
|
||||
#include "DDraw/ScopedThreadLock.h"
|
||||
#include "DDraw/Surfaces/PrimarySurface.h"
|
||||
@ -21,6 +21,7 @@ namespace
|
||||
|
||||
CompatWeakPtr<IDirectDrawSurface7> g_frontBuffer;
|
||||
CompatWeakPtr<IDirectDrawSurface7> g_backBuffer;
|
||||
CompatWeakPtr<IDirectDrawSurface7> g_paletteConverter;
|
||||
CompatWeakPtr<IDirectDrawClipper> g_clipper;
|
||||
DDSURFACEDESC2 g_surfaceDesc = {};
|
||||
DDraw::IReleaseNotifier g_releaseNotifier(onRelease);
|
||||
@ -49,22 +50,26 @@ namespace
|
||||
auto primary(DDraw::PrimarySurface::getPrimary());
|
||||
if (DDraw::PrimarySurface::getDesc().ddpfPixelFormat.dwRGBBitCount <= 8)
|
||||
{
|
||||
auto paletteConverter(DDraw::PaletteConverter::getSurface());
|
||||
paletteConverter->Blt(paletteConverter, &g_updateRect,
|
||||
primary, &g_updateRect, DDBLT_WAIT, nullptr);
|
||||
HDC paletteConverterDc = nullptr;
|
||||
g_paletteConverter->GetDC(g_paletteConverter, &paletteConverterDc);
|
||||
HDC primaryDc = nullptr;
|
||||
primary->GetDC(primary, &primaryDc);
|
||||
|
||||
HDC destDc = nullptr;
|
||||
dest->GetDC(&dest, &destDc);
|
||||
result = TRUE == CALL_ORIG_FUNC(BitBlt)(destDc, g_updateRect.left, g_updateRect.top,
|
||||
g_updateRect.right - g_updateRect.left, g_updateRect.bottom - g_updateRect.top,
|
||||
DDraw::PaletteConverter::getDc(), g_updateRect.left, g_updateRect.top, SRCCOPY);
|
||||
dest->ReleaseDC(&dest, destDc);
|
||||
|
||||
if (&dest == g_frontBuffer)
|
||||
if (paletteConverterDc && primaryDc)
|
||||
{
|
||||
// Force the screen to be updated. It won't refresh from BitBlt alone.
|
||||
RECT r = { 0, 0, 1, 1 };
|
||||
g_frontBuffer->BltFast(g_frontBuffer, 0, 0, g_frontBuffer, &r, DDBLTFAST_WAIT);
|
||||
result = TRUE == CALL_ORIG_FUNC(BitBlt)(paletteConverterDc,
|
||||
g_updateRect.left, g_updateRect.top,
|
||||
g_updateRect.right - g_updateRect.left, g_updateRect.bottom - g_updateRect.top,
|
||||
primaryDc, g_updateRect.left, g_updateRect.top, SRCCOPY);
|
||||
}
|
||||
|
||||
primary->ReleaseDC(primary, primaryDc);
|
||||
g_paletteConverter->ReleaseDC(g_paletteConverter, paletteConverterDc);
|
||||
|
||||
if (result)
|
||||
{
|
||||
result = SUCCEEDED(dest->Blt(&dest, &g_updateRect,
|
||||
g_paletteConverter, &g_updateRect, DDBLT_WAIT, nullptr));
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -78,7 +83,40 @@ namespace
|
||||
SetRectEmpty(&g_updateRect);
|
||||
}
|
||||
|
||||
Compat::LogLeave("RealPrimarySurface::compatBlt", dest);
|
||||
Compat::LogLeave("RealPrimarySurface::compatBlt", dest) << result;
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename TDirectDraw>
|
||||
HRESULT createPaletteConverter(CompatRef<TDirectDraw> dd)
|
||||
{
|
||||
auto dd7(CompatPtr<IDirectDraw7>::from(&dd));
|
||||
auto dm = DDraw::DisplayMode::getDisplayMode(*dd7);
|
||||
if (dm.ddpfPixelFormat.dwRGBBitCount > 8)
|
||||
{
|
||||
return DD_OK;
|
||||
}
|
||||
|
||||
typename DDraw::Types<TDirectDraw>::TSurfaceDesc desc = {};
|
||||
desc.dwSize = sizeof(desc);
|
||||
desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS;
|
||||
desc.dwWidth = dm.dwWidth;
|
||||
desc.dwHeight = dm.dwHeight;
|
||||
desc.ddpfPixelFormat.dwSize = sizeof(desc.ddpfPixelFormat);
|
||||
desc.ddpfPixelFormat.dwFlags = DDPF_RGB;
|
||||
desc.ddpfPixelFormat.dwRGBBitCount = 32;
|
||||
desc.ddpfPixelFormat.dwRBitMask = 0x00FF0000;
|
||||
desc.ddpfPixelFormat.dwGBitMask = 0x0000FF00;
|
||||
desc.ddpfPixelFormat.dwBBitMask = 0x000000FF;
|
||||
desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
|
||||
|
||||
CompatPtr<DDraw::Types<TDirectDraw>::TCreatedSurface> paletteConverter;
|
||||
HRESULT result = dd->CreateSurface(&dd, &desc, &paletteConverter.getRef(), nullptr);
|
||||
if (SUCCEEDED(result))
|
||||
{
|
||||
g_paletteConverter = Compat::queryInterface<IDirectDrawSurface7>(paletteConverter.get());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -91,11 +129,6 @@ namespace
|
||||
|
||||
HRESULT init(CompatPtr<IDirectDrawSurface7> surface)
|
||||
{
|
||||
if (!DDraw::PaletteConverter::create())
|
||||
{
|
||||
return DDERR_GENERIC;
|
||||
}
|
||||
|
||||
DDSURFACEDESC2 desc = {};
|
||||
desc.dwSize = sizeof(desc);
|
||||
surface->GetSurfaceDesc(surface, &desc);
|
||||
@ -152,7 +185,7 @@ namespace
|
||||
g_backBuffer = nullptr;
|
||||
g_clipper = nullptr;
|
||||
g_isFullScreen = false;
|
||||
DDraw::PaletteConverter::release();
|
||||
g_paletteConverter.release();
|
||||
|
||||
ZeroMemory(&g_surfaceDesc, sizeof(g_surfaceDesc));
|
||||
|
||||
@ -209,6 +242,13 @@ namespace DDraw
|
||||
template <typename DirectDraw>
|
||||
HRESULT RealPrimarySurface::create(CompatRef<DirectDraw> dd)
|
||||
{
|
||||
HRESULT result = createPaletteConverter(dd);
|
||||
if (FAILED(result))
|
||||
{
|
||||
Compat::Log() << "Failed to create the palette converter surface: " << Compat::hex(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
typename Types<DirectDraw>::TSurfaceDesc desc = {};
|
||||
desc.dwSize = sizeof(desc);
|
||||
desc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
|
||||
@ -216,7 +256,7 @@ namespace DDraw
|
||||
desc.dwBackBufferCount = 1;
|
||||
|
||||
CompatPtr<typename Types<DirectDraw>::TCreatedSurface> surface;
|
||||
HRESULT result = dd->CreateSurface(&dd, &desc, &surface.getRef(), nullptr);
|
||||
result = dd->CreateSurface(&dd, &desc, &surface.getRef(), nullptr);
|
||||
|
||||
bool isFlippable = true;
|
||||
if (DDERR_NOEXCLUSIVEMODE == result)
|
||||
@ -230,7 +270,8 @@ namespace DDraw
|
||||
|
||||
if (FAILED(result))
|
||||
{
|
||||
Compat::Log() << "Failed to create the real primary surface";
|
||||
Compat::Log() << "Failed to create the real primary surface: " << Compat::hex(result);
|
||||
g_paletteConverter.release();
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -343,7 +384,6 @@ namespace DDraw
|
||||
LOG_ONCE("Failed to set clipper on the real primary surface: " << result);
|
||||
return;
|
||||
}
|
||||
PaletteConverter::setClipper(clipper);
|
||||
g_clipper = clipper;
|
||||
}
|
||||
|
||||
@ -375,7 +415,6 @@ namespace DDraw
|
||||
|
||||
void RealPrimarySurface::updatePalette(DWORD startingEntry, DWORD count)
|
||||
{
|
||||
PaletteConverter::updatePalette(startingEntry, count);
|
||||
Gdi::updatePalette(startingEntry, count);
|
||||
if (PrimarySurface::s_palette)
|
||||
{
|
||||
|
@ -26,10 +26,15 @@ namespace
|
||||
pf = dm.ddpfPixelFormat;
|
||||
}
|
||||
|
||||
if ((pf.dwFlags & DDPF_RGB) && pf.dwRGBBitCount <= 8)
|
||||
{
|
||||
caps &= ~(DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM | DDSCAPS_NONLOCALVIDMEM);
|
||||
caps |= DDSCAPS_SYSTEMMEMORY;
|
||||
}
|
||||
|
||||
if (!(caps & (DDSCAPS_OFFSCREENPLAIN | DDSCAPS_OVERLAY | DDSCAPS_TEXTURE |
|
||||
DDSCAPS_FRONTBUFFER | DDSCAPS_BACKBUFFER)))
|
||||
{
|
||||
flags |= DDSD_CAPS;
|
||||
caps |= DDSCAPS_OFFSCREENPLAIN;
|
||||
}
|
||||
}
|
||||
|
@ -184,7 +184,6 @@
|
||||
<ClInclude Include="DDraw\DirectDrawPalette.h" />
|
||||
<ClInclude Include="DDraw\DirectDrawSurface.h" />
|
||||
<ClInclude Include="DDraw\DisplayMode.h" />
|
||||
<ClInclude Include="DDraw\PaletteConverter.h" />
|
||||
<ClInclude Include="DDraw\Hooks.h" />
|
||||
<ClInclude Include="DDraw\Repository.h" />
|
||||
<ClInclude Include="DDraw\ScopedThreadLock.h" />
|
||||
@ -247,7 +246,6 @@
|
||||
<ClCompile Include="DDraw\DirectDrawPalette.cpp" />
|
||||
<ClCompile Include="DDraw\DirectDrawSurface.cpp" />
|
||||
<ClCompile Include="DDraw\DisplayMode.cpp" />
|
||||
<ClCompile Include="DDraw\PaletteConverter.cpp" />
|
||||
<ClCompile Include="DDraw\Hooks.cpp" />
|
||||
<ClCompile Include="DDraw\Repository.cpp" />
|
||||
<ClCompile Include="DDraw\IReleaseNotifier.cpp" />
|
||||
|
@ -123,9 +123,6 @@
|
||||
<ClInclude Include="DDraw\DisplayMode.h">
|
||||
<Filter>Header Files\DDraw</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="DDraw\PaletteConverter.h">
|
||||
<Filter>Header Files\DDraw</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="DDraw\Hooks.h">
|
||||
<Filter>Header Files\DDraw</Filter>
|
||||
</ClInclude>
|
||||
@ -344,9 +341,6 @@
|
||||
<ClCompile Include="DDraw\DisplayMode.cpp">
|
||||
<Filter>Source Files\DDraw</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="DDraw\PaletteConverter.cpp">
|
||||
<Filter>Source Files\DDraw</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="DDraw\Hooks.cpp">
|
||||
<Filter>Source Files\DDraw</Filter>
|
||||
</ClCompile>
|
||||
|
@ -1,7 +1,6 @@
|
||||
#include <atomic>
|
||||
|
||||
#include "Common/ScopedCriticalSection.h"
|
||||
#include "DDraw/PaletteConverter.h"
|
||||
#include "DDraw/RealPrimarySurface.h"
|
||||
#include "DDraw/Surfaces/PrimarySurface.h"
|
||||
#include "Dll/Procs.h"
|
||||
|
Loading…
x
Reference in New Issue
Block a user