xref: /reactos/win32ss/reactx/ntddraw/d3dkmt.c (revision 8a978a17)
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     /* Allocate a palette for this surface */
90     if (format->bit_count <= 8)
91     {
92         PPALETTE palette = PALETTE_AllocPalette(PAL_INDEXED, 1 << format->bit_count, NULL, 0, 0, 0);
93         if (palette)
94         {
95             SURFACE_vSetPalette(psurf, palette);
96             PALETTE_ShareUnlockPalette(palette);
97         }
98     }
99 
100     /* Unlock the surface and return */
101     SURFACE_UnlockSurface(psurf);
102 
103     NtGdiSelectBitmap(desc->hDc, desc->hBitmap);
104 
105     return STATUS_SUCCESS;
106 }
107 
108 DWORD
109 APIENTRY
110 NtGdiDdDDIDestroyDCFromMemory(const D3DKMT_DESTROYDCFROMMEMORY *desc)
111 {
112     if (!desc)
113         return STATUS_INVALID_PARAMETER;
114 
115     if (GDI_HANDLE_GET_TYPE(desc->hDc)  != GDI_OBJECT_TYPE_DC ||
116         GDI_HANDLE_GET_TYPE(desc->hBitmap) != GDI_OBJECT_TYPE_BITMAP)
117         return STATUS_INVALID_PARAMETER;
118 
119     NtGdiDeleteObjectApp(desc->hBitmap);
120     NtGdiDeleteObjectApp(desc->hDc);
121 
122     return STATUS_SUCCESS;
123 }
124