From 0a41694b535914726df5cbeb4bb1cf7724c5c41e Mon Sep 17 00:00:00 2001 From: Henri Verbeet Date: Wed, 13 Apr 2016 12:18:51 +0200 Subject: [PATCH] gdi32: Implement DC creation from pre-existing memory. Signed-off-by: Henri Verbeet Signed-off-by: Huw Davies Signed-off-by: Alexandre Julliard --- dlls/gdi32/dib.c | 137 ++++++++++++++++++++ dlls/gdi32/dibdrv/dc.c | 13 +- dlls/gdi32/gdi32.spec | 2 + dlls/gdi32/tests/bitmap.c | 260 +++++++++++++++++++++++++++++++++++++- include/Makefile.in | 2 + include/d3dukmdt.h | 139 ++++++++++++++++++++ include/ddk/d3dkmthk.h | 55 ++++++++ 7 files changed, 599 insertions(+), 9 deletions(-) create mode 100644 include/d3dukmdt.h create mode 100644 include/ddk/d3dkmthk.h diff --git a/dlls/gdi32/dib.c b/dlls/gdi32/dib.c index cf1ebe4241..ad2bf4f2d9 100644 --- a/dlls/gdi32/dib.c +++ b/dlls/gdi32/dib.c @@ -66,8 +66,14 @@ #include #include +#include "ntstatus.h" +#define WIN32_NO_STATUS #include "windef.h" #include "winbase.h" +#include "wingdi.h" +#include "winternl.h" +#include "ddk/d3dkmthk.h" + #include "gdi_private.h" #include "wine/debug.h" @@ -1581,6 +1587,135 @@ error: } +/*********************************************************************** + * D3DKMTCreateDCFromMemory (GDI32.@) + */ +NTSTATUS WINAPI D3DKMTCreateDCFromMemory( D3DKMT_CREATEDCFROMMEMORY *desc ) +{ + 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; + BITMAPOBJ *bmp = NULL; + HBITMAP bitmap; + unsigned int i; + HDC dc; + + 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_P8, 8, BI_RGB, 256, 0x00000000, 0x00000000, 0x00000000 }, + }; + + if (!desc) return STATUS_INVALID_PARAMETER; + + TRACE("memory %p, format %#x, width %u, height %u, pitch %u, device dc %p, color table %p.\n", + desc->pMemory, desc->Format, desc->Width, desc->Height, + desc->Pitch, desc->hDeviceDc, desc->pColorTable); + + 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 < get_dib_stride( desc->Width, format->bit_count ) || + !desc->Height || desc->Height > UINT_MAX / desc->Pitch) return STATUS_INVALID_PARAMETER; + + if (!desc->hDeviceDc || !(dc = CreateCompatibleDC( desc->hDeviceDc ))) return STATUS_INVALID_PARAMETER; + + if (!(bmp = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*bmp) ))) goto error; + + bmp->dib.dsBm.bmWidth = desc->Width; + bmp->dib.dsBm.bmHeight = desc->Height; + bmp->dib.dsBm.bmWidthBytes = desc->Pitch; + bmp->dib.dsBm.bmPlanes = 1; + bmp->dib.dsBm.bmBitsPixel = format->bit_count; + bmp->dib.dsBm.bmBits = desc->pMemory; + + bmp->dib.dsBmih.biSize = sizeof(bmp->dib.dsBmih); + bmp->dib.dsBmih.biWidth = desc->Width; + bmp->dib.dsBmih.biHeight = -(LONG)desc->Height; + bmp->dib.dsBmih.biPlanes = 1; + bmp->dib.dsBmih.biBitCount = format->bit_count; + bmp->dib.dsBmih.biCompression = format->compression; + bmp->dib.dsBmih.biClrUsed = format->palette_size; + bmp->dib.dsBmih.biClrImportant = format->palette_size; + + bmp->dib.dsBitfields[0] = format->mask_r; + bmp->dib.dsBitfields[1] = format->mask_g; + bmp->dib.dsBitfields[2] = format->mask_b; + + if (format->palette_size) + { + if (!(bmp->color_table = HeapAlloc( GetProcessHeap(), 0, format->palette_size * sizeof(*bmp->color_table) ))) + goto error; + if (desc->pColorTable) + { + for (i = 0; i < format->palette_size; ++i) + { + bmp->color_table[i].rgbRed = desc->pColorTable[i].peRed; + bmp->color_table[i].rgbGreen = desc->pColorTable[i].peGreen; + bmp->color_table[i].rgbBlue = desc->pColorTable[i].peBlue; + bmp->color_table[i].rgbReserved = 0; + } + } + else + { + memcpy( bmp->color_table, get_default_color_table( format->bit_count ), + format->palette_size * sizeof(*bmp->color_table) ); + } + } + + if (!(bitmap = alloc_gdi_handle( bmp, OBJ_BITMAP, &dib_funcs ))) goto error; + + desc->hDc = dc; + desc->hBitmap = bitmap; + SelectObject( dc, bitmap ); + return STATUS_SUCCESS; + +error: + if (bmp) HeapFree( GetProcessHeap(), 0, bmp->color_table ); + HeapFree( GetProcessHeap(), 0, bmp ); + DeleteDC( dc ); + return STATUS_INVALID_PARAMETER; +} + + +/*********************************************************************** + * D3DKMTDestroyDCFromMemory (GDI32.@) + */ +NTSTATUS WINAPI D3DKMTDestroyDCFromMemory( const D3DKMT_DESTROYDCFROMMEMORY *desc ) +{ + if (!desc) return STATUS_INVALID_PARAMETER; + + TRACE("dc %p, bitmap %p.\n", desc->hDc, desc->hBitmap); + + if (GetObjectType( desc->hDc ) != OBJ_MEMDC || + GetObjectType( desc->hBitmap ) != OBJ_BITMAP) return STATUS_INVALID_PARAMETER; + DeleteObject( desc->hBitmap ); + DeleteDC( desc->hDc ); + + return STATUS_SUCCESS; +} + + /*********************************************************************** * DIB_SelectObject */ @@ -1657,6 +1792,7 @@ static INT DIB_GetObject( HGDIOBJ handle, INT count, LPVOID buffer ) { DIBSECTION *dib = buffer; *dib = bmp->dib; + dib->dsBm.bmWidthBytes = get_dib_stride( dib->dsBm.bmWidth, dib->dsBm.bmBitsPixel ); dib->dsBmih.biHeight = abs( dib->dsBmih.biHeight ); ret = sizeof(DIBSECTION); } @@ -1664,6 +1800,7 @@ static INT DIB_GetObject( HGDIOBJ handle, INT count, LPVOID buffer ) { BITMAP *bitmap = buffer; *bitmap = bmp->dib.dsBm; + bitmap->bmWidthBytes = get_dib_stride( bitmap->bmWidth, bitmap->bmBitsPixel ); ret = sizeof(BITMAP); } diff --git a/dlls/gdi32/dibdrv/dc.c b/dlls/gdi32/dibdrv/dc.c index b80e522163..4aa1d1d162 100644 --- a/dlls/gdi32/dibdrv/dc.c +++ b/dlls/gdi32/dibdrv/dc.c @@ -67,8 +67,8 @@ static void init_bit_fields(dib_info *dib, const DWORD *bit_fields) calc_shift_and_len(dib->blue_mask, &dib->blue_shift, &dib->blue_len); } -static void init_dib_info(dib_info *dib, const BITMAPINFOHEADER *bi, const DWORD *bit_fields, - const RGBQUAD *color_table, void *bits) +static void init_dib_info(dib_info *dib, const BITMAPINFOHEADER *bi, int stride, + const DWORD *bit_fields, const RGBQUAD *color_table, void *bits) { dib->bit_count = bi->biBitCount; dib->width = bi->biWidth; @@ -78,7 +78,7 @@ static void init_dib_info(dib_info *dib, const BITMAPINFOHEADER *bi, const DWORD dib->rect.right = bi->biWidth; dib->rect.bottom = abs( bi->biHeight ); dib->compression = bi->biCompression; - dib->stride = get_dib_stride( dib->width, dib->bit_count ); + dib->stride = stride; dib->bits.ptr = bits; dib->bits.is_copy = FALSE; dib->bits.free = NULL; @@ -154,7 +154,8 @@ static void init_dib_info(dib_info *dib, const BITMAPINFOHEADER *bi, const DWORD void init_dib_info_from_bitmapinfo(dib_info *dib, const BITMAPINFO *info, void *bits) { - init_dib_info( dib, &info->bmiHeader, (const DWORD *)info->bmiColors, info->bmiColors, bits ); + init_dib_info( dib, &info->bmiHeader, get_dib_stride( info->bmiHeader.biWidth, info->bmiHeader.biBitCount ), + (const DWORD *)info->bmiColors, info->bmiColors, bits ); } BOOL init_dib_info_from_bitmapobj(dib_info *dib, BITMAPOBJ *bmp) @@ -173,8 +174,8 @@ BOOL init_dib_info_from_bitmapobj(dib_info *dib, BITMAPOBJ *bmp) } init_dib_info_from_bitmapinfo( dib, &info, bmp->dib.dsBm.bmBits ); } - else init_dib_info( dib, &bmp->dib.dsBmih, bmp->dib.dsBitfields, - bmp->color_table, bmp->dib.dsBm.bmBits ); + else init_dib_info( dib, &bmp->dib.dsBmih, bmp->dib.dsBm.bmWidthBytes, + bmp->dib.dsBitfields, bmp->color_table, bmp->dib.dsBm.bmBits ); return TRUE; } diff --git a/dlls/gdi32/gdi32.spec b/dlls/gdi32/gdi32.spec index 7d837f692a..7792731b9e 100644 --- a/dlls/gdi32/gdi32.spec +++ b/dlls/gdi32/gdi32.spec @@ -80,6 +80,8 @@ @ stdcall CreateScalableFontResourceA(long str str str) @ stdcall CreateScalableFontResourceW(long wstr wstr wstr) @ stdcall CreateSolidBrush(long) +@ stdcall D3DKMTCreateDCFromMemory(ptr) +@ stdcall D3DKMTDestroyDCFromMemory(ptr) @ stdcall D3DKMTEscape(ptr) @ stdcall D3DKMTOpenAdapterFromHdc(ptr) @ stdcall DPtoLP(long ptr long) diff --git a/dlls/gdi32/tests/bitmap.c b/dlls/gdi32/tests/bitmap.c index e19c5525ca..5539283e7b 100644 --- a/dlls/gdi32/tests/bitmap.c +++ b/dlls/gdi32/tests/bitmap.c @@ -23,15 +23,21 @@ #include #include +#include "ntstatus.h" +#define WIN32_NO_STATUS #include "windef.h" #include "winbase.h" #include "winerror.h" #include "wingdi.h" #include "winuser.h" #include "mmsystem.h" +#include "winternl.h" +#include "ddk/d3dkmthk.h" #include "wine/test.h" +static NTSTATUS (WINAPI *pD3DKMTCreateDCFromMemory)( D3DKMT_CREATEDCFROMMEMORY *desc ); +static NTSTATUS (WINAPI *pD3DKMTDestroyDCFromMemory)( const D3DKMT_DESTROYDCFROMMEMORY *desc ); static BOOL (WINAPI *pGdiAlphaBlend)(HDC,int,int,int,int,HDC,int,int,int,int,BLENDFUNCTION); static BOOL (WINAPI *pGdiGradientFill)(HDC,TRIVERTEX*,ULONG,void*,ULONG,ULONG); static DWORD (WINAPI *pSetLayout)(HDC hdc, DWORD layout); @@ -5642,14 +5648,261 @@ static void test_SetDIBitsToDevice_RLE8(void) HeapFree( GetProcessHeap(), 0, info ); } +static void test_D3DKMTCreateDCFromMemory( void ) +{ + D3DKMT_DESTROYDCFROMMEMORY destroy_desc; + D3DKMT_CREATEDCFROMMEMORY create_desc; + unsigned int width_bytes; + unsigned int i, x, y, z; + DWORD expected, colour; + BYTE data[12][48]; + NTSTATUS status; + HGDIOBJ *bitmap; + DIBSECTION dib; + BOOL fail, ret; + DWORD type; + int size; + + static const struct + { + const char *name; + D3DDDIFORMAT format; + unsigned int bit_count; + DWORD mask_r, mask_g, mask_b; + NTSTATUS status; + } + test_data[] = + { + { "R8G8B8", D3DDDIFMT_R8G8B8, 24, 0x00000000, 0x00000000, 0x00000000, STATUS_SUCCESS }, + { "A8R8G8B8", D3DDDIFMT_A8R8G8B8, 32, 0x00000000, 0x00000000, 0x00000000, STATUS_SUCCESS }, + { "X8R8G8B8", D3DDDIFMT_X8R8G8B8, 32, 0x00000000, 0x00000000, 0x00000000, STATUS_SUCCESS }, + { "R5G6B5", D3DDDIFMT_R5G6B5, 16, 0x0000f800, 0x000007e0, 0x0000001f, STATUS_SUCCESS }, + { "X1R5G5B5", D3DDDIFMT_X1R5G5B5, 16, 0x00007c00, 0x000003e0, 0x0000001f, STATUS_SUCCESS }, + { "A1R5G5B5", D3DDDIFMT_A1R5G5B5, 16, 0x00007c00, 0x000003e0, 0x0000001f, STATUS_SUCCESS }, + { "R3G3B2", D3DDDIFMT_R3G3B2, 8, 0x00000000, 0x00000000, 0x00000000, STATUS_INVALID_PARAMETER }, + { "A2B10G10R10", D3DDDIFMT_A2B10G10R10, 32, 0x00000000, 0x00000000, 0x00000000, STATUS_INVALID_PARAMETER }, + { "A8B8G8R8", D3DDDIFMT_A8B8G8R8, 32, 0x00000000, 0x00000000, 0x00000000, STATUS_INVALID_PARAMETER }, + { "X8B8G8R8", D3DDDIFMT_A8B8G8R8, 32, 0x00000000, 0x00000000, 0x00000000, STATUS_INVALID_PARAMETER }, + { "A2R10G10B10", D3DDDIFMT_A2R10G10B10, 32, 0x00000000, 0x00000000, 0x00000000, STATUS_INVALID_PARAMETER }, + { "P8", D3DDDIFMT_P8, 8, 0x00000000, 0x00000000, 0x00000000, STATUS_SUCCESS }, + { "L8", D3DDDIFMT_L8, 8, 0x00000000, 0x00000000, 0x00000000, STATUS_INVALID_PARAMETER }, + { "A8L8", D3DDDIFMT_A8L8, 16, 0x00000000, 0x00000000, 0x00000000, STATUS_INVALID_PARAMETER }, + { "V8U8", D3DDDIFMT_V8U8, 16, 0x00000000, 0x00000000, 0x00000000, STATUS_INVALID_PARAMETER }, + { "Q8W8V8U8", D3DDDIFMT_Q8W8V8U8, 32, 0x00000000, 0x00000000, 0x00000000, STATUS_INVALID_PARAMETER }, + { "DXT1", D3DDDIFMT_DXT1, 4, 0x00000000, 0x00000000, 0x00000000, STATUS_INVALID_PARAMETER }, + { "DXT2", D3DDDIFMT_DXT2, 8, 0x00000000, 0x00000000, 0x00000000, STATUS_INVALID_PARAMETER }, + { "DXT3", D3DDDIFMT_DXT3, 8, 0x00000000, 0x00000000, 0x00000000, STATUS_INVALID_PARAMETER }, + { "DXT4", D3DDDIFMT_DXT4, 8, 0x00000000, 0x00000000, 0x00000000, STATUS_INVALID_PARAMETER }, + { "DXT5", D3DDDIFMT_DXT5, 8, 0x00000000, 0x00000000, 0x00000000, STATUS_INVALID_PARAMETER }, + }; + + if (!pD3DKMTCreateDCFromMemory) + { + win_skip("D3DKMTCreateDCFromMemory() is not implemented.\n"); + return; + } + + status = pD3DKMTCreateDCFromMemory( NULL ); + ok(status == STATUS_INVALID_PARAMETER, "Got unexpected status %#x.\n", status); + + for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i) + { + memset( data, 0xaa, sizeof(data) ); + + create_desc.pMemory = data; + create_desc.Format = test_data[i].format; + create_desc.Width = 9; + create_desc.Height = 7; + create_desc.Pitch = sizeof(*data); + create_desc.hDeviceDc = NULL; + create_desc.pColorTable = NULL; + create_desc.hDc = (void *)0x010baade; + create_desc.hBitmap = (void *)0x020baade; + + status = pD3DKMTCreateDCFromMemory( &create_desc ); + ok(status == STATUS_INVALID_PARAMETER, "%s: Got unexpected status %#x.\n", + test_data[i].name, status); + + create_desc.hDeviceDc = CreateCompatibleDC( NULL ); + create_desc.pMemory = NULL; + status = pD3DKMTCreateDCFromMemory( &create_desc ); + ok(status == STATUS_INVALID_PARAMETER, "%s: Got unexpected status %#x.\n", + test_data[i].name, status); + + create_desc.pMemory = data; + create_desc.Height = 0; + status = pD3DKMTCreateDCFromMemory( &create_desc ); + ok(status == STATUS_INVALID_PARAMETER, "%s: Got unexpected status %#x.\n", + test_data[i].name, status); + ok(create_desc.hDc == (void *)0x010baade, "%s: Got unexpected dc %p.\n", + test_data[i].name, create_desc.hDc); + ok(create_desc.hBitmap == (void *)0x020baade, "%s: Got unexpected bitmap %p.\n", + test_data[i].name, create_desc.hBitmap); + + create_desc.Height = 7; + create_desc.Width = 0; + status = pD3DKMTCreateDCFromMemory( &create_desc ); + ok(status == test_data[i].status, "%s: Got unexpected status %#x, expected %#x.\n", + test_data[i].name, status, test_data[i].status); + if (status == STATUS_SUCCESS) + { + destroy_desc.hDc = create_desc.hDc; + destroy_desc.hBitmap = create_desc.hBitmap; + status = pD3DKMTDestroyDCFromMemory( &destroy_desc ); + ok(status == STATUS_SUCCESS, "%s: Got unexpected status %#x.\n", test_data[i].name, status); + create_desc.hDc = (void *)0x010baade; + create_desc.hBitmap = (void *)0x020baade; + } + + create_desc.Pitch = 0; + status = pD3DKMTCreateDCFromMemory( &create_desc ); + ok(status == STATUS_INVALID_PARAMETER, "%s: Got unexpected status %#x.\n", + test_data[i].name, status); + ok(create_desc.hDc == (void *)0x010baade, "%s: Got unexpected dc %p.\n", + test_data[i].name, create_desc.hDc); + ok(create_desc.hBitmap == (void *)0x020baade, "%s: Got unexpected bitmap %p.\n", + test_data[i].name, create_desc.hBitmap); + + create_desc.Width = 9; + create_desc.Pitch = sizeof(*data); + status = pD3DKMTCreateDCFromMemory( &create_desc ); + ok(status == test_data[i].status, "%s: Got unexpected status %#x, expected %#x.\n", + test_data[i].name, status, test_data[i].status); + if (status == STATUS_SUCCESS) + { + ok(!!create_desc.hDc, "%s: Got unexpected dc %p.\n", + test_data[i].name, create_desc.hDc); + ok(!!create_desc.hBitmap, "%s: Got unexpected bitmap %p.\n", + test_data[i].name, create_desc.hBitmap); + } + else + { + ok(create_desc.hDc == (void *)0x010baade, "%s: Got unexpected dc %p.\n", + test_data[i].name, create_desc.hDc); + ok(create_desc.hBitmap == (void *)0x020baade, "%s: Got unexpected bitmap %p.\n", + test_data[i].name, create_desc.hBitmap); + continue; + } + + type = GetObjectType( create_desc.hDc ); + ok(type == OBJ_MEMDC, "%s: Got unexpected object type %#x.\n", test_data[i].name, type); + type = GetObjectType( create_desc.hBitmap ); + ok(type == OBJ_BITMAP, "%s: Got unexpected object type %#x.\n", test_data[i].name, type); + bitmap = GetCurrentObject( create_desc.hDc, OBJ_BITMAP ); + ok(bitmap == create_desc.hBitmap, "%s: Got unexpected bitmap %p, expected %p.\n", + test_data[i].name, bitmap, create_desc.hBitmap); + + size = GetObjectA( bitmap, sizeof(dib), &dib ); + ok(size == sizeof(dib), "%s: Got unexpected size %d.\n", test_data[i].name, size); + ok(!dib.dsBm.bmType, "%s: Got unexpected type %#x.\n", + test_data[i].name, dib.dsBm.bmType); + ok(dib.dsBm.bmWidth == create_desc.Width, "%s: Got unexpected width %d.\n", + test_data[i].name, dib.dsBm.bmWidth); + ok(dib.dsBm.bmHeight == create_desc.Height, "%s: Got unexpected height %d.\n", + test_data[i].name, dib.dsBm.bmHeight); + width_bytes = get_dib_stride( create_desc.Width, test_data[i].bit_count ); + ok(dib.dsBm.bmWidthBytes == width_bytes, "%s: Got unexpected width bytes %d.\n", + test_data[i].name, dib.dsBm.bmWidthBytes); + ok(dib.dsBm.bmPlanes == 1, "%s: Got unexpected plane count %d.\n", + test_data[i].name, dib.dsBm.bmPlanes); + ok(dib.dsBm.bmBitsPixel == test_data[i].bit_count, "%s: Got unexpected bit count %d.\n", + test_data[i].name, dib.dsBm.bmBitsPixel); + ok(dib.dsBm.bmBits == create_desc.pMemory, "%s: Got unexpected bits %p, expected %p.\n", + test_data[i].name, dib.dsBm.bmBits, create_desc.pMemory); + + ok(dib.dsBmih.biSize == sizeof(dib.dsBmih), "%s: Got unexpected size %u.\n", + test_data[i].name, dib.dsBmih.biSize); + ok(dib.dsBmih.biWidth == create_desc.Width, "%s: Got unexpected width %d.\n", + test_data[i].name, dib.dsBmih.biHeight); + ok(dib.dsBmih.biHeight == create_desc.Height, "%s: Got unexpected height %d.\n", + test_data[i].name, dib.dsBmih.biHeight); + ok(dib.dsBmih.biPlanes == 1, "%s: Got unexpected plane count %u.\n", + test_data[i].name, dib.dsBmih.biPlanes); + ok(dib.dsBmih.biBitCount == test_data[i].bit_count, "%s: Got unexpected bit count %u.\n", + test_data[i].name, dib.dsBmih.biBitCount); + ok(dib.dsBmih.biCompression == (test_data[i].bit_count == 16 ? BI_BITFIELDS : BI_RGB), + "%s: Got unexpected compression %#x.\n", + test_data[i].name, dib.dsBmih.biCompression); + ok(!dib.dsBmih.biSizeImage, "%s: Got unexpected image size %u.\n", + test_data[i].name, dib.dsBmih.biSizeImage); + ok(!dib.dsBmih.biXPelsPerMeter, "%s: Got unexpected horizontal resolution %d.\n", + test_data[i].name, dib.dsBmih.biXPelsPerMeter); + ok(!dib.dsBmih.biYPelsPerMeter, "%s: Got unexpected vertical resolution %d.\n", + test_data[i].name, dib.dsBmih.biYPelsPerMeter); + if (test_data[i].format == D3DDDIFMT_P8) + { + ok(dib.dsBmih.biClrUsed == 256, "%s: Got unexpected used colour count %u.\n", + test_data[i].name, dib.dsBmih.biClrUsed); + ok(dib.dsBmih.biClrImportant == 256, "%s: Got unexpected important colour count %u.\n", + test_data[i].name, dib.dsBmih.biClrImportant); + } + else + { + ok(!dib.dsBmih.biClrUsed, "%s: Got unexpected used colour count %u.\n", + test_data[i].name, dib.dsBmih.biClrUsed); + ok(!dib.dsBmih.biClrImportant, "%s: Got unexpected important colour count %u.\n", + test_data[i].name, dib.dsBmih.biClrImportant); + } + + ok(dib.dsBitfields[0] == test_data[i].mask_r && dib.dsBitfields[1] == test_data[i].mask_g + && dib.dsBitfields[2] == test_data[i].mask_b, + "%s: Got unexpected colour masks 0x%08x 0x%08x 0x%08x.\n", + test_data[i].name, dib.dsBitfields[0], dib.dsBitfields[1], dib.dsBitfields[2]); + ok(!dib.dshSection, "%s: Got unexpected section %p.\n", test_data[i].name, dib.dshSection); + ok(!dib.dsOffset, "%s: Got unexpected offset %u.\n", test_data[i].name, dib.dsOffset); + + ret = BitBlt( create_desc.hDc, 0, 0, 4, 10, NULL, 0, 0, BLACKNESS ); + ok(ret, "Failed to blit.\n"); + ret = BitBlt( create_desc.hDc, 1, 1, 2, 2, NULL, 0, 0, WHITENESS ); + ok(ret, "Failed to blit.\n"); + + destroy_desc.hDc = create_desc.hDc; + destroy_desc.hBitmap = create_desc.hBitmap; + + status = pD3DKMTDestroyDCFromMemory( NULL ); + ok(status == STATUS_INVALID_PARAMETER, "%s: Got unexpected status %#x.\n", test_data[i].name, status); + status = pD3DKMTDestroyDCFromMemory( &destroy_desc ); + ok(status == STATUS_SUCCESS, "%s: Got unexpected status %#x.\n", test_data[i].name, status); + status = pD3DKMTDestroyDCFromMemory( &destroy_desc ); + ok(status == STATUS_INVALID_PARAMETER, "%s: Got unexpected status %#x.\n", test_data[i].name, status); + + ret = DeleteDC( create_desc.hDeviceDc ); + ok(ret, "Failed to delete dc.\n"); + + for (y = 0, fail = FALSE; y < 12 && !fail; ++y) + { + for (x = 0; x < sizeof(*data) / (test_data[i].bit_count / 8) && !fail; ++x) + { + for (z = 0, colour = 0; z < test_data[i].bit_count / 8; ++z) + { + colour = colour << 8 | data[y][x * (test_data[i].bit_count / 8) + z]; + } + + if ((x == 1 || x == 2) && (y == 1 || y == 2)) + expected = 0xffffffff >> (32 - test_data[i].bit_count); + else if (x < 4 && y < 7) + expected = 0x00000000; + else + expected = 0xaaaaaaaa >> (32 - test_data[i].bit_count); + ok(colour == expected, "%s: Got unexpected colour 0x%08x at %u, %u, expected 0x%08x.\n", + test_data[i].name, colour, x, y, expected); + if (colour != expected) + fail = TRUE; + } + } + } +} + START_TEST(bitmap) { HMODULE hdll; hdll = GetModuleHandleA("gdi32.dll"); - pGdiAlphaBlend = (void*)GetProcAddress(hdll, "GdiAlphaBlend"); - pGdiGradientFill = (void*)GetProcAddress(hdll, "GdiGradientFill"); - pSetLayout = (void*)GetProcAddress(hdll, "SetLayout"); + pD3DKMTCreateDCFromMemory = (void *)GetProcAddress( hdll, "D3DKMTCreateDCFromMemory" ); + pD3DKMTDestroyDCFromMemory = (void *)GetProcAddress( hdll, "D3DKMTDestroyDCFromMemory" ); + pGdiAlphaBlend = (void *)GetProcAddress( hdll, "GdiAlphaBlend" ); + pGdiGradientFill = (void *)GetProcAddress( hdll, "GdiGradientFill" ); + pSetLayout = (void *)GetProcAddress( hdll, "SetLayout" ); test_createdibitmap(); test_dibsections(); @@ -5686,4 +5939,5 @@ START_TEST(bitmap) test_SetDIBits_RLE8(); test_SetDIBitsToDevice(); test_SetDIBitsToDevice_RLE8(); + test_D3DKMTCreateDCFromMemory(); } diff --git a/include/Makefile.in b/include/Makefile.in index fb1c195896..250166d444 100644 --- a/include/Makefile.in +++ b/include/Makefile.in @@ -250,6 +250,7 @@ HEADER_SRCS = \ d3drmobj.h \ d3drmwin.h \ d3dtypes.h \ + d3dukmdt.h \ d3dvec.inl \ d3dx10.h \ d3dx10async.h \ @@ -276,6 +277,7 @@ HEADER_SRCS = \ ddeml.h \ ddk/compstui.h \ ddk/csq.h \ + ddk/d3dkmthk.h \ ddk/hidclass.h \ ddk/hidpi.h \ ddk/hidport.h \ diff --git a/include/d3dukmdt.h b/include/d3dukmdt.h new file mode 100644 index 0000000000..a7be710ef1 --- /dev/null +++ b/include/d3dukmdt.h @@ -0,0 +1,139 @@ +/* + * Copyright 2016 Henri Verbeet for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef __WINE_D3DUKMDT_H +#define __WINE_D3DUKMDT_H + +#ifndef MAKEFOURCC +#define MAKEFOURCC(ch0, ch1, ch2, ch3) \ + ((DWORD)(BYTE)(ch0) | ((DWORD)(BYTE)(ch1) << 8) | \ + ((DWORD)(BYTE)(ch2) << 16) | ((DWORD)(BYTE)(ch3) << 24)) +#endif /* MAKEFOURCC */ + +typedef enum _D3DDDIFORMAT +{ + D3DDDIFMT_UNKNOWN = 0, + D3DDDIFMT_R8G8B8 = 0x14, + D3DDDIFMT_A8R8G8B8 = 0x15, + D3DDDIFMT_X8R8G8B8 = 0x16, + D3DDDIFMT_R5G6B5 = 0x17, + D3DDDIFMT_X1R5G5B5 = 0x18, + D3DDDIFMT_A1R5G5B5 = 0x19, + D3DDDIFMT_A4R4G4B4 = 0x1a, + D3DDDIFMT_R3G3B2 = 0x1b, + D3DDDIFMT_A8 = 0x1c, + D3DDDIFMT_A8R3G3B2 = 0x1d, + D3DDDIFMT_X4R4G4B4 = 0x1e, + D3DDDIFMT_A2B10G10R10 = 0x1f, + D3DDDIFMT_A8B8G8R8 = 0x20, + D3DDDIFMT_X8B8G8R8 = 0x21, + D3DDDIFMT_G16R16 = 0x22, + D3DDDIFMT_A2R10G10B10 = 0x23, + D3DDDIFMT_A16B16G16R16 = 0x24, + D3DDDIFMT_A8P8 = 0x28, + D3DDDIFMT_P8 = 0x29, + D3DDDIFMT_L8 = 0x32, + D3DDDIFMT_A8L8 = 0x33, + D3DDDIFMT_A4L4 = 0x34, + D3DDDIFMT_V8U8 = 0x3c, + D3DDDIFMT_L6V5U5 = 0x3d, + D3DDDIFMT_X8L8V8U8 = 0x3e, + D3DDDIFMT_Q8W8V8U8 = 0x3f, + D3DDDIFMT_V16U16 = 0x40, + D3DDDIFMT_W11V11U10 = 0x41, + D3DDDIFMT_A2W10V10U10 = 0x43, + D3DDDIFMT_D16_LOCKABLE = 0x46, + D3DDDIFMT_D32 = 0x47, + D3DDDIFMT_S1D15 = 0x48, + D3DDDIFMT_D15S1 = 0x49, + D3DDDIFMT_S8D24 = 0x4a, + D3DDDIFMT_D24S8 = 0x4b, + D3DDDIFMT_X8D24 = 0x4c, + D3DDDIFMT_D24X8 = 0x4d, + D3DDDIFMT_X4S4D24 = 0x4e, + D3DDDIFMT_D24X4S4 = 0x4f, + D3DDDIFMT_D16 = 0x50, + D3DDDIFMT_L16 = 0x51, + D3DDDIFMT_D32F_LOCKABLE = 0x52, + D3DDDIFMT_D24FS8 = 0x53, + D3DDDIFMT_D32_LOCKABLE = 0x54, + D3DDDIFMT_S8_LOCKABLE = 0x55, + D3DDDIFMT_G8R8 = 0x5b, + D3DDDIFMT_R8 = 0x5c, + D3DDDIFMT_VERTEXDATA = 0x64, + D3DDDIFMT_INDEX16 = 0x65, + D3DDDIFMT_INDEX32 = 0x66, + D3DDDIFMT_Q16W16V16U16 = 0x6e, + D3DDDIFMT_R16F = 0x6f, + D3DDDIFMT_G16R16F = 0x70, + D3DDDIFMT_A16B16G16R16F = 0x71, + D3DDDIFMT_R32F = 0x72, + D3DDDIFMT_G32R32F = 0x73, + D3DDDIFMT_A32B32G32R32F = 0x74, + D3DDDIFMT_CxV8U8 = 0x75, + D3DDDIFMT_A1 = 0x76, + D3DDDIFMT_A2B10G10R10_XR_BIAS = 0x77, + D3DDDIFMT_DXVACOMPBUFFER_BASE = 0x96, + D3DDDIFMT_PICTUREPARAMSDATA = D3DDDIFMT_DXVACOMPBUFFER_BASE + 0, + D3DDDIFMT_MACROBLOCKDATA = D3DDDIFMT_DXVACOMPBUFFER_BASE + 0x01, + D3DDDIFMT_RESIDUALDIFFERENCEDATA = D3DDDIFMT_DXVACOMPBUFFER_BASE + 0x02, + D3DDDIFMT_DEBLOCKINGDATA = D3DDDIFMT_DXVACOMPBUFFER_BASE + 0x03, + D3DDDIFMT_INVERSEQUANTIZATIONDATA = D3DDDIFMT_DXVACOMPBUFFER_BASE + 0x04, + D3DDDIFMT_SLICECONTROLDATA = D3DDDIFMT_DXVACOMPBUFFER_BASE + 0x05, + D3DDDIFMT_BITSTREAMDATA = D3DDDIFMT_DXVACOMPBUFFER_BASE + 0x06, + D3DDDIFMT_MOTIONVECTORBUFFER = D3DDDIFMT_DXVACOMPBUFFER_BASE + 0x07, + D3DDDIFMT_FILMGRAINBUFFER = D3DDDIFMT_DXVACOMPBUFFER_BASE + 0x08, + D3DDDIFMT_DXVA_RESERVED9 = D3DDDIFMT_DXVACOMPBUFFER_BASE + 0x09, + D3DDDIFMT_DXVA_RESERVED10 = D3DDDIFMT_DXVACOMPBUFFER_BASE + 0x0a, + D3DDDIFMT_DXVA_RESERVED11 = D3DDDIFMT_DXVACOMPBUFFER_BASE + 0x0b, + D3DDDIFMT_DXVA_RESERVED12 = D3DDDIFMT_DXVACOMPBUFFER_BASE + 0x0c, + D3DDDIFMT_DXVA_RESERVED13 = D3DDDIFMT_DXVACOMPBUFFER_BASE + 0x0d, + D3DDDIFMT_DXVA_RESERVED14 = D3DDDIFMT_DXVACOMPBUFFER_BASE + 0x0e, + D3DDDIFMT_DXVA_RESERVED15 = D3DDDIFMT_DXVACOMPBUFFER_BASE + 0x0f, + D3DDDIFMT_DXVA_RESERVED16 = D3DDDIFMT_DXVACOMPBUFFER_BASE + 0x10, + D3DDDIFMT_DXVA_RESERVED17 = D3DDDIFMT_DXVACOMPBUFFER_BASE + 0x11, + D3DDDIFMT_DXVA_RESERVED18 = D3DDDIFMT_DXVACOMPBUFFER_BASE + 0x12, + D3DDDIFMT_DXVA_RESERVED19 = D3DDDIFMT_DXVACOMPBUFFER_BASE + 0x13, + D3DDDIFMT_DXVA_RESERVED20 = D3DDDIFMT_DXVACOMPBUFFER_BASE + 0x14, + D3DDDIFMT_DXVA_RESERVED21 = D3DDDIFMT_DXVACOMPBUFFER_BASE + 0x15, + D3DDDIFMT_DXVA_RESERVED22 = D3DDDIFMT_DXVACOMPBUFFER_BASE + 0x16, + D3DDDIFMT_DXVA_RESERVED23 = D3DDDIFMT_DXVACOMPBUFFER_BASE + 0x17, + D3DDDIFMT_DXVA_RESERVED24 = D3DDDIFMT_DXVACOMPBUFFER_BASE + 0x18, + D3DDDIFMT_DXVA_RESERVED25 = D3DDDIFMT_DXVACOMPBUFFER_BASE + 0x19, + D3DDDIFMT_DXVA_RESERVED26 = D3DDDIFMT_DXVACOMPBUFFER_BASE + 0x1a, + D3DDDIFMT_DXVA_RESERVED27 = D3DDDIFMT_DXVACOMPBUFFER_BASE + 0x1b, + D3DDDIFMT_DXVA_RESERVED28 = D3DDDIFMT_DXVACOMPBUFFER_BASE + 0x1c, + D3DDDIFMT_DXVA_RESERVED29 = D3DDDIFMT_DXVACOMPBUFFER_BASE + 0x1d, + D3DDDIFMT_DXVA_RESERVED30 = D3DDDIFMT_DXVACOMPBUFFER_BASE + 0x1e, + D3DDDIFMT_DXVA_RESERVED31 = D3DDDIFMT_DXVACOMPBUFFER_BASE + 0x1f, + D3DDDIFMT_DXVACOMPBUFFER_MAX = D3DDDIFMT_DXVA_RESERVED31, + D3DDDIFMT_BINARYBUFFER = 0xc7, + D3DDDIFMT_DXT1 = MAKEFOURCC('D', 'X', 'T', '1'), + D3DDDIFMT_DXT2 = MAKEFOURCC('D', 'X', 'T', '2'), + D3DDDIFMT_DXT3 = MAKEFOURCC('D', 'X', 'T', '3'), + D3DDDIFMT_DXT4 = MAKEFOURCC('D', 'X', 'T', '4'), + D3DDDIFMT_DXT5 = MAKEFOURCC('D', 'X', 'T', '5'), + D3DDDIFMT_G8R8_G8B8 = MAKEFOURCC('G', 'R', 'G', 'B'), + D3DDDIFMT_MULTI2_ARGB8 = MAKEFOURCC('M', 'E', 'T', '1'), + D3DDDIFMT_R8G8_B8G8 = MAKEFOURCC('R', 'G', 'B', 'G'), + D3DDDIFMT_UYVY = MAKEFOURCC('U', 'Y', 'V', 'Y'), + D3DDDIFMT_YUY2 = MAKEFOURCC('Y', 'U', 'Y', '2'), + D3DDDIFMT_FORCE_UINT = 0x7fffffff, +} D3DDDIFORMAT; + +#endif /* __WINE_D3DUKMDT_H */ diff --git a/include/ddk/d3dkmthk.h b/include/ddk/d3dkmthk.h new file mode 100644 index 0000000000..80c0c8a27e --- /dev/null +++ b/include/ddk/d3dkmthk.h @@ -0,0 +1,55 @@ +/* + * Copyright 2016 Henri Verbeet for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef __WINE_D3DKMTHK_H +#define __WINE_D3DKMTHK_H + +#include + +typedef struct _D3DKMT_CREATEDCFROMMEMORY +{ + void *pMemory; + D3DDDIFORMAT Format; + UINT Width; + UINT Height; + UINT Pitch; + HDC hDeviceDc; + PALETTEENTRY *pColorTable; + HDC hDc; + HANDLE hBitmap; +} D3DKMT_CREATEDCFROMMEMORY; + +typedef struct _D3DKMT_DESTROYDCFROMMEMORY +{ + HDC hDc; + HANDLE hBitmap; +} D3DKMT_DESTROYDCFROMMEMORY; + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +NTSTATUS WINAPI D3DKMTCreateDCFromMemory(D3DKMT_CREATEDCFROMMEMORY *desc); +NTSTATUS WINAPI D3DKMTDestroyDCFromMemory(const D3DKMT_DESTROYDCFROMMEMORY *desc); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __WINE_D3DKMTHK_H */