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 * DxgiFns.cpp -- 30 * DXGI related functions. 31 */ 32 33#include <stdio.h> 34 35#include "DxgiFns.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 55HRESULT APIENTRY 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_texture_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_texture_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 194HRESULT APIENTRY 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 226HRESULT APIENTRY 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 243HRESULT APIENTRY 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 262HRESULT APIENTRY 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 286HRESULT APIENTRY 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 368HRESULT APIENTRY 369_Blt(DXGI_DDI_ARG_BLT *Blt) 370{ 371 LOG_UNSUPPORTED_ENTRYPOINT(); 372 373 return S_OK; 374} 375