[WIN32SS] Implement D3DKMT{Create,Destroy}DCFromMemory. Brought to you by Sebastian...
[reactos.git] / reactos / win32ss / reactx / ntddraw / d3dkmt.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * PURPOSE: Native DirectDraw implementation
5 * FILE: win32ss/reactx/ntddraw/d3dkmt.c
6 * PROGRAMER: Sebastian Gasiorek (sebastian.gasiorek@reactos.com)
7 */
8
9 #include <win32k.h>
10 #include <debug.h>
11
12 DWORD
13 APIENTRY
14 NtGdiDdDDICreateDCFromMemory(D3DKMT_CREATEDCFROMMEMORY *desc)
15 {
16 PSURFACE psurf;
17 HDC hDC;
18
19 const struct d3dddi_format_info
20 {
21 D3DDDIFORMAT format;
22 unsigned int bit_count;
23 DWORD compression;
24 unsigned int palette_size;
25 DWORD mask_r, mask_g, mask_b;
26 } *format = NULL;
27 unsigned int i;
28
29 static const struct d3dddi_format_info format_info[] =
30 {
31 { D3DDDIFMT_R8G8B8, 24, BI_RGB, 0, 0x00000000, 0x00000000, 0x00000000 },
32 { D3DDDIFMT_A8R8G8B8, 32, BI_RGB, 0, 0x00000000, 0x00000000, 0x00000000 },
33 { D3DDDIFMT_X8R8G8B8, 32, BI_RGB, 0, 0x00000000, 0x00000000, 0x00000000 },
34 { D3DDDIFMT_R5G6B5, 16, BI_BITFIELDS, 0, 0x0000f800, 0x000007e0, 0x0000001f },
35 { D3DDDIFMT_X1R5G5B5, 16, BI_BITFIELDS, 0, 0x00007c00, 0x000003e0, 0x0000001f },
36 { D3DDDIFMT_A1R5G5B5, 16, BI_BITFIELDS, 0, 0x00007c00, 0x000003e0, 0x0000001f },
37 { D3DDDIFMT_A4R4G4B4, 16, BI_BITFIELDS, 0, 0x00000f00, 0x000000f0, 0x0000000f },
38 { D3DDDIFMT_X4R4G4B4, 16, BI_BITFIELDS, 0, 0x00000f00, 0x000000f0, 0x0000000f },
39 { D3DDDIFMT_P8, 8, BI_RGB, 256, 0x00000000, 0x00000000, 0x00000000 },
40 };
41
42 if (!desc)
43 return STATUS_INVALID_PARAMETER;
44
45 if (!desc->pMemory)
46 return STATUS_INVALID_PARAMETER;
47
48 for (i = 0; i < sizeof(format_info) / sizeof(*format_info); ++i)
49 {
50 if (format_info[i].format == desc->Format)
51 {
52 format = &format_info[i];
53 break;
54 }
55 }
56
57 if (!format)
58 return STATUS_INVALID_PARAMETER;
59
60 if (desc->Width > (UINT_MAX & ~3) / (format->bit_count / 8) ||
61 !desc->Pitch || desc->Pitch < (((desc->Width * format->bit_count + 31) >> 3) & ~3) ||
62 !desc->Height || desc->Height > UINT_MAX / desc->Pitch)
63 {
64 return STATUS_INVALID_PARAMETER;
65 }
66
67 if (!desc->hDeviceDc || !(hDC = NtGdiCreateCompatibleDC(desc->hDeviceDc)))
68 {
69 return STATUS_INVALID_PARAMETER;
70 }
71
72 /* Allocate a surface */
73 psurf = SURFACE_AllocSurface(STYPE_BITMAP,
74 desc->Width,
75 desc->Height,
76 BitmapFormat(format->bit_count, format->compression),
77 BMF_TOPDOWN | BMF_NOZEROINIT,
78 desc->Pitch,
79 0,
80 desc->pMemory);
81
82 /* Mark as API bitmap */
83 psurf->flags |= (DDB_SURFACE | API_BITMAP);
84
85 desc->hDc = hDC;
86 /* Get the handle for the bitmap */
87 desc->hBitmap = (HBITMAP)psurf->SurfObj.hsurf;
88
89 /* Unlock the surface and return */
90 SURFACE_UnlockSurface(psurf);
91
92 NtGdiSelectBitmap(desc->hDc, desc->hBitmap);
93
94 return STATUS_SUCCESS;
95 }
96
97 DWORD
98 APIENTRY
99 NtGdiDdDDIDestroyDCFromMemory(const D3DKMT_DESTROYDCFROMMEMORY *desc)
100 {
101 if (!desc)
102 return STATUS_INVALID_PARAMETER;
103
104 if (GDI_HANDLE_GET_TYPE(desc->hDc) != GDI_OBJECT_TYPE_DC ||
105 GDI_HANDLE_GET_TYPE(desc->hBitmap) != GDI_OBJECT_TYPE_BITMAP)
106 return STATUS_INVALID_PARAMETER;
107
108 NtGdiDeleteObjectApp(desc->hBitmap);
109 NtGdiDeleteObjectApp(desc->hDc);
110
111 return STATUS_SUCCESS;
112 }