[PATCH 5/5] gdi32: Implement DC creation from pre-existing memory.

Henri Verbeet hverbeet at codeweavers.com
Tue Apr 12 11:09:32 CDT 2016


Signed-off-by: Henri Verbeet <hverbeet at codeweavers.com>
---
 dlls/gdi32/dib.c          | 137 ++++++++++++++++++++++++
 dlls/gdi32/dibdrv/dc.c    |  13 +--
 dlls/gdi32/gdi32.spec     |   2 +
 dlls/gdi32/tests/bitmap.c | 261 +++++++++++++++++++++++++++++++++++++++++++++-
 include/d3dukmdt.h        | 139 ++++++++++++++++++++++++
 include/ddk/d3dkmthk.h    |  55 ++++++++++
 6 files changed, 598 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 cf1ebe4..ad2bf4f 100644
--- a/dlls/gdi32/dib.c
+++ b/dlls/gdi32/dib.c
@@ -66,8 +66,14 @@
 #include <string.h>
 #include <assert.h>
 
+#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"
 
@@ -1582,6 +1588,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
  */
 static HGDIOBJ DIB_SelectObject( HGDIOBJ handle, HDC hdc )
@@ -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 b80e522..4aa1d1d 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 7d837f6..7792731 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 e19c552..1b818b3 100644
--- a/dlls/gdi32/tests/bitmap.c
+++ b/dlls/gdi32/tests/bitmap.c
@@ -23,15 +23,21 @@
 #include <assert.h>
 #include <string.h>
 
+#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,262 @@ 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, expected %u.\n",
+           test_data[i].name, size, sizeof(dib));
+        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, expected %u.\n",
+           test_data[i].name, dib.dsBmih.biSize, sizeof(dib.dsBmih));
+        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 +5940,5 @@ START_TEST(bitmap)
     test_SetDIBits_RLE8();
     test_SetDIBitsToDevice();
     test_SetDIBitsToDevice_RLE8();
+    test_D3DKMTCreateDCFromMemory();
 }
diff --git a/include/d3dukmdt.h b/include/d3dukmdt.h
new file mode 100644
index 0000000..a7be710
--- /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 0000000..80c0c8a
--- /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 <d3dukmdt.h>
+
+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 */
-- 
2.1.4




More information about the wine-patches mailing list