1 /**************************************************************************
2 *
3 * Copyright 2012-2021 VMware, Inc.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
18 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20 * USE OR OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * The above copyright notice and this permission notice (including the
23 * next paragraph) shall be included in all copies or substantial portions
24 * of the Software.
25 *
26 **************************************************************************/
27
28 /*
29 * Dxgi.cpp --
30 * DXGI related functions.
31 */
32
33 #include <stdio.h>
34
35 #include "Dxgi.h"
36 #include "Format.h"
37 #include "State.h"
38
39 #include "Debug.h"
40
41 #include "util/format/u_format.h"
42
43
44 /*
45 * ----------------------------------------------------------------------
46 *
47 * _Present --
48 *
49 * This is turned into kernel callbacks rather than directly emitted
50 * as fifo packets.
51 *
52 * ----------------------------------------------------------------------
53 */
54
55 HRESULT APIENTRY
_Present(DXGI_DDI_ARG_PRESENT * pPresentData)56 _Present(DXGI_DDI_ARG_PRESENT *pPresentData)
57 {
58
59 LOG_ENTRYPOINT();
60
61 struct pipe_context *pipe = CastPipeDevice(pPresentData->hDevice);
62 Resource *pSrcResource = CastResource(pPresentData->hSurfaceToPresent);
63
64 D3DKMT_PRESENT *pPresentInfo = (D3DKMT_PRESENT *)pPresentData->pDXGIContext;
65
66 HWND hWnd = pPresentInfo->hWindow;
67
68 if (0) {
69 DebugPrintf(" hWindow = 0x%08lx\n", pPresentInfo->hWindow);
70 if (pPresentInfo->Flags.SrcRectValid) {
71 DebugPrintf(" SrcRect.left = %li\n", pPresentInfo->SrcRect.left);
72 DebugPrintf(" SrcRect.top = %li\n", pPresentInfo->SrcRect.top);
73 DebugPrintf(" SrcRect.right = %li\n", pPresentInfo->SrcRect.right);
74 DebugPrintf(" SrcRect.bottom = %li\n", pPresentInfo->SrcRect.bottom);
75 }
76 if (pPresentInfo->Flags.DstRectValid) {
77 DebugPrintf(" DstRect.left = %li\n", pPresentInfo->DstRect.left);
78 DebugPrintf(" DstRect.top = %li\n", pPresentInfo->DstRect.top);
79 DebugPrintf(" DstRect.right = %li\n", pPresentInfo->DstRect.right);
80 DebugPrintf(" DstRect.bottom = %li\n", pPresentInfo->DstRect.bottom);
81 }
82 }
83
84 RECT rect;
85 if (!GetClientRect(hWnd, &rect)) {
86 DebugPrintf("Invalid window.\n");
87 return S_OK;
88 }
89
90 int windowWidth = rect.right - rect.left;
91 int windowHeight = rect.bottom - rect.top;
92
93 HDC hDC = GetDC(hWnd);
94
95 unsigned w = pSrcResource->resource->width0;
96 unsigned h = pSrcResource->resource->height0;
97
98 void *map;
99 struct pipe_transfer *transfer;
100 map = pipe_transfer_map(pipe,
101 pSrcResource->resource,
102 0, 0, PIPE_MAP_READ,
103 0, 0, w, h,
104 &transfer);
105 if (map) {
106
107 BITMAPINFO bmi;
108
109 memset(&bmi, 0, sizeof bmi);
110 bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
111 bmi.bmiHeader.biWidth = w;
112 bmi.bmiHeader.biHeight= -(long)h;
113 bmi.bmiHeader.biPlanes = 1;
114 bmi.bmiHeader.biBitCount = 32;
115 bmi.bmiHeader.biCompression = BI_RGB;
116 bmi.bmiHeader.biSizeImage = 0;
117 bmi.bmiHeader.biXPelsPerMeter = 0;
118 bmi.bmiHeader.biYPelsPerMeter = 0;
119 bmi.bmiHeader.biClrUsed = 0;
120 bmi.bmiHeader.biClrImportant = 0;
121
122 DWORD *pixels = NULL;
123
124 // http://www.daniweb.com/software-development/cpp/code/241875/fast-animation-with-the-windows-gdi
125
126 HBITMAP hBmp = CreateDIBSection(hDC, &bmi, DIB_RGB_COLORS, (void**)&pixels, NULL, 0);
127
128 util_format_translate(
129 PIPE_FORMAT_B8G8R8X8_UNORM,
130 (void *)pixels, w * 4,
131 0, 0,
132 pSrcResource->resource->format,
133 map, transfer->stride,
134 0, 0, w, h);
135
136 if (0) {
137 /*
138 * Save a BMP for debugging.
139 */
140
141 FILE *fp = fopen("present.bmp", "wb");
142 if (fp) {
143 BITMAPFILEHEADER bmf;
144 bmf.bfType = 0x4d42;
145 bmf.bfSize = sizeof bmf + sizeof bmi + h * w * 4;
146 bmf.bfReserved1 = 0;
147 bmf.bfReserved2 = 0;
148 bmf.bfOffBits = sizeof bmf + sizeof bmi;
149
150 fwrite(&bmf, sizeof bmf, 1, fp);
151 fwrite(&bmi, sizeof bmi, 1, fp);
152 fwrite(pixels, h, w * 4, fp);
153 fclose(fp);
154 }
155 }
156
157 HDC hdcMem;
158 hdcMem = CreateCompatibleDC(hDC);
159 HBITMAP hbmOld = (HBITMAP)SelectObject(hdcMem, hBmp);
160
161 int iStretchMode = SetStretchBltMode(hDC, HALFTONE);
162
163 StretchBlt(hDC, 0, 0, windowWidth, windowHeight,
164 hdcMem, 0, 0, w, h,
165 SRCCOPY);
166
167 if (iStretchMode) {
168 SetStretchBltMode(hDC, iStretchMode);
169 }
170
171 SelectObject(hdcMem, hbmOld);
172 DeleteDC(hdcMem);
173 DeleteObject(hBmp);
174
175 pipe_transfer_unmap(pipe, transfer);
176 }
177
178 ReleaseDC(hWnd, hDC);
179
180 return S_OK;
181 }
182
183
184 /*
185 * ----------------------------------------------------------------------
186 *
187 * _GetGammaCaps --
188 *
189 * Return gamma capabilities.
190 *
191 * ----------------------------------------------------------------------
192 */
193
194 HRESULT APIENTRY
_GetGammaCaps(DXGI_DDI_ARG_GET_GAMMA_CONTROL_CAPS * GetCaps)195 _GetGammaCaps( DXGI_DDI_ARG_GET_GAMMA_CONTROL_CAPS *GetCaps )
196 {
197 LOG_ENTRYPOINT();
198
199 DXGI_GAMMA_CONTROL_CAPABILITIES *pCaps;
200
201 pCaps = GetCaps->pGammaCapabilities;
202
203 pCaps->ScaleAndOffsetSupported = FALSE;
204 pCaps->MinConvertedValue = 0.0;
205 pCaps->MaxConvertedValue = 1.0;
206 pCaps->NumGammaControlPoints = 17;
207
208 for (UINT i = 0; i < pCaps->NumGammaControlPoints; i++) {
209 pCaps->ControlPointPositions[i] = (float)i / (float)(pCaps->NumGammaControlPoints - 1);
210 }
211
212 return S_OK;
213 }
214
215
216 /*
217 * ----------------------------------------------------------------------
218 *
219 * _SetDisplayMode --
220 *
221 * Set the resource that is used to scan out to the display.
222 *
223 * ----------------------------------------------------------------------
224 */
225
226 HRESULT APIENTRY
_SetDisplayMode(DXGI_DDI_ARG_SETDISPLAYMODE * SetDisplayMode)227 _SetDisplayMode( DXGI_DDI_ARG_SETDISPLAYMODE *SetDisplayMode )
228 {
229 LOG_UNSUPPORTED_ENTRYPOINT();
230
231 return S_OK;
232 }
233
234
235 /*
236 * ----------------------------------------------------------------------
237 *
238 * _SetResourcePriority --
239 *
240 * ----------------------------------------------------------------------
241 */
242
243 HRESULT APIENTRY
_SetResourcePriority(DXGI_DDI_ARG_SETRESOURCEPRIORITY * SetResourcePriority)244 _SetResourcePriority( DXGI_DDI_ARG_SETRESOURCEPRIORITY *SetResourcePriority )
245 {
246 LOG_ENTRYPOINT();
247
248 /* ignore */
249
250 return S_OK;
251 }
252
253
254 /*
255 * ----------------------------------------------------------------------
256 *
257 * _QueryResourceResidency --
258 *
259 * ----------------------------------------------------------------------
260 */
261
262 HRESULT APIENTRY
_QueryResourceResidency(DXGI_DDI_ARG_QUERYRESOURCERESIDENCY * QueryResourceResidency)263 _QueryResourceResidency( DXGI_DDI_ARG_QUERYRESOURCERESIDENCY *QueryResourceResidency )
264 {
265 LOG_ENTRYPOINT();
266
267 for (UINT i = 0; i < QueryResourceResidency->Resources; ++i) {
268 QueryResourceResidency->pStatus[i] = DXGI_DDI_RESIDENCY_FULLY_RESIDENT;
269 }
270
271 return S_OK;
272 }
273
274
275 /*
276 * ----------------------------------------------------------------------
277 *
278 * _RotateResourceIdentities --
279 *
280 * Rotate a list of resources by recreating their views with
281 * the updated rotations.
282 *
283 * ----------------------------------------------------------------------
284 */
285
286 HRESULT APIENTRY
_RotateResourceIdentities(DXGI_DDI_ARG_ROTATE_RESOURCE_IDENTITIES * RotateResourceIdentities)287 _RotateResourceIdentities( DXGI_DDI_ARG_ROTATE_RESOURCE_IDENTITIES *RotateResourceIdentities )
288 {
289 LOG_ENTRYPOINT();
290
291 if (RotateResourceIdentities->Resources <= 1) {
292 return S_OK;
293 }
294
295 struct pipe_context *pipe = CastPipeDevice(RotateResourceIdentities->hDevice);
296 struct pipe_screen *screen = pipe->screen;
297
298 struct pipe_resource *resource0 = CastPipeResource(RotateResourceIdentities->pResources[0]);
299
300 assert(resource0);
301 LOG_UNSUPPORTED(resource0->last_level);
302
303 /*
304 * XXX: Copying is not very efficient, but it is much simpler than the
305 * alternative of recreating all views.
306 */
307
308 struct pipe_resource *temp_resource;
309 temp_resource = screen->resource_create(screen, resource0);
310 assert(temp_resource);
311 if (!temp_resource) {
312 return E_OUTOFMEMORY;
313 }
314
315 struct pipe_box src_box;
316 src_box.x = 0;
317 src_box.y = 0;
318 src_box.z = 0;
319 src_box.width = resource0->width0;
320 src_box.height = resource0->height0;
321 src_box.depth = resource0->depth0;
322
323 for (UINT i = 0; i < RotateResourceIdentities->Resources + 1; ++i) {
324 struct pipe_resource *src_resource;
325 struct pipe_resource *dst_resource;
326
327 if (i < RotateResourceIdentities->Resources) {
328 src_resource = CastPipeResource(RotateResourceIdentities->pResources[i]);
329 } else {
330 src_resource = temp_resource;
331 }
332
333 if (i > 0) {
334 dst_resource = CastPipeResource(RotateResourceIdentities->pResources[i - 1]);
335 } else {
336 dst_resource = temp_resource;
337 }
338
339 assert(dst_resource);
340 assert(src_resource);
341
342 pipe->resource_copy_region(pipe,
343 dst_resource,
344 0, // dst_level
345 0, 0, 0, // dst_x,y,z
346 src_resource,
347 0, // src_level
348 &src_box);
349 }
350
351 pipe_resource_reference(&temp_resource, NULL);
352
353 return S_OK;
354 }
355
356
357 /*
358 * ----------------------------------------------------------------------
359 *
360 * _Blt --
361 *
362 * Do a blt between two subresources. Apply MSAA resolve, format
363 * conversion and stretching.
364 *
365 * ----------------------------------------------------------------------
366 */
367
368 HRESULT APIENTRY
_Blt(DXGI_DDI_ARG_BLT * Blt)369 _Blt(DXGI_DDI_ARG_BLT *Blt)
370 {
371 LOG_UNSUPPORTED_ENTRYPOINT();
372
373 return S_OK;
374 }
375