reactos/win32ss/reactx/ntddraw/d3dkmt.c
Joachim Henze 1ee05f7362 [0.4.7][WIN32SS][NTDDRAW] Fix ddraw palette regression CORE-13714
This nice patch of Jerome Gardou improves palette
when VBEMP & inbuilt Mesa is used for
Diablo II, MS Age Of Empires 1, Anno 1602
to the state we had in SVN r75060 and below.

Palette still not perfect in fullscreen but at least as good as it was before
it regressed by SVN r75061 == git
4b0ee92f91

We do intend to improve on the remaining fullscreen palette issues in CORE-10738.

fix cherry picked from 0.4.9-dev-675-g
14f0e62f9a
2020-10-06 23:20:10 +02:00

124 lines
3.8 KiB
C

/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* PURPOSE: Native DirectDraw implementation
* FILE: win32ss/reactx/ntddraw/d3dkmt.c
* PROGRAMER: Sebastian Gasiorek (sebastian.gasiorek@reactos.com)
*/
#include <win32k.h>
#include <debug.h>
DWORD
APIENTRY
NtGdiDdDDICreateDCFromMemory(D3DKMT_CREATEDCFROMMEMORY *desc)
{
PSURFACE psurf;
HDC hDC;
const struct d3dddi_format_info
{
D3DDDIFORMAT format;
unsigned int bit_count;
DWORD compression;
unsigned int palette_size;
DWORD mask_r, mask_g, mask_b;
} *format = NULL;
unsigned int i;
static const struct d3dddi_format_info format_info[] =
{
{ D3DDDIFMT_R8G8B8, 24, BI_RGB, 0, 0x00000000, 0x00000000, 0x00000000 },
{ D3DDDIFMT_A8R8G8B8, 32, BI_RGB, 0, 0x00000000, 0x00000000, 0x00000000 },
{ D3DDDIFMT_X8R8G8B8, 32, BI_RGB, 0, 0x00000000, 0x00000000, 0x00000000 },
{ D3DDDIFMT_R5G6B5, 16, BI_BITFIELDS, 0, 0x0000f800, 0x000007e0, 0x0000001f },
{ D3DDDIFMT_X1R5G5B5, 16, BI_BITFIELDS, 0, 0x00007c00, 0x000003e0, 0x0000001f },
{ D3DDDIFMT_A1R5G5B5, 16, BI_BITFIELDS, 0, 0x00007c00, 0x000003e0, 0x0000001f },
{ D3DDDIFMT_A4R4G4B4, 16, BI_BITFIELDS, 0, 0x00000f00, 0x000000f0, 0x0000000f },
{ D3DDDIFMT_X4R4G4B4, 16, BI_BITFIELDS, 0, 0x00000f00, 0x000000f0, 0x0000000f },
{ D3DDDIFMT_P8, 8, BI_RGB, 256, 0x00000000, 0x00000000, 0x00000000 },
};
if (!desc)
return STATUS_INVALID_PARAMETER;
if (!desc->pMemory)
return STATUS_INVALID_PARAMETER;
for (i = 0; i < sizeof(format_info) / sizeof(*format_info); ++i)
{
if (format_info[i].format == desc->Format)
{
format = &format_info[i];
break;
}
}
if (!format)
return STATUS_INVALID_PARAMETER;
if (desc->Width > (UINT_MAX & ~3) / (format->bit_count / 8) ||
!desc->Pitch || desc->Pitch < (((desc->Width * format->bit_count + 31) >> 3) & ~3) ||
!desc->Height || desc->Height > UINT_MAX / desc->Pitch)
{
return STATUS_INVALID_PARAMETER;
}
if (!desc->hDeviceDc || !(hDC = NtGdiCreateCompatibleDC(desc->hDeviceDc)))
{
return STATUS_INVALID_PARAMETER;
}
/* Allocate a surface */
psurf = SURFACE_AllocSurface(STYPE_BITMAP,
desc->Width,
desc->Height,
BitmapFormat(format->bit_count, format->compression),
BMF_TOPDOWN | BMF_NOZEROINIT,
desc->Pitch,
0,
desc->pMemory);
/* Mark as API bitmap */
psurf->flags |= (DDB_SURFACE | API_BITMAP);
desc->hDc = hDC;
/* Get the handle for the bitmap */
desc->hBitmap = (HBITMAP)psurf->SurfObj.hsurf;
/* Allocate a palette for this surface */
if (format->bit_count <= 8)
{
PPALETTE palette = PALETTE_AllocPalette(PAL_INDEXED, 1 << format->bit_count, NULL, 0, 0, 0);
if (palette)
{
SURFACE_vSetPalette(psurf, palette);
PALETTE_ShareUnlockPalette(palette);
}
}
/* Unlock the surface and return */
SURFACE_UnlockSurface(psurf);
NtGdiSelectBitmap(desc->hDc, desc->hBitmap);
return STATUS_SUCCESS;
}
DWORD
APIENTRY
NtGdiDdDDIDestroyDCFromMemory(const D3DKMT_DESTROYDCFROMMEMORY *desc)
{
if (!desc)
return STATUS_INVALID_PARAMETER;
if (GDI_HANDLE_GET_TYPE(desc->hDc) != GDI_OBJECT_TYPE_DC ||
GDI_HANDLE_GET_TYPE(desc->hBitmap) != GDI_OBJECT_TYPE_BITMAP)
return STATUS_INVALID_PARAMETER;
NtGdiDeleteObjectApp(desc->hBitmap);
NtGdiDeleteObjectApp(desc->hDc);
return STATUS_SUCCESS;
}