• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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