VirtualBox

source: vbox/trunk/src/VBox/Devices/Graphics/DevVGA-SVGA3d-win.cpp@ 67572

Last change on this file since 67572 was 67572, checked in by vboxsync, 8 years ago

DevVGA-SVGA3d-win.cpp: Use the bounce texture if necessary to copy surface data. Always initialize all mipmap levels when creating a new D3D texture.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 234.4 KB
Line 
1/* $Id: DevVGA-SVGA3d-win.cpp 67572 2017-06-23 07:07:59Z vboxsync $ */
2/** @file
3 * DevVMWare - VMWare SVGA device
4 */
5
6/*
7 * Copyright (C) 2013-2016 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
22#define LOG_GROUP LOG_GROUP_DEV_VMSVGA
23#include <VBox/vmm/pdmdev.h>
24#include <VBox/version.h>
25#include <VBox/err.h>
26#include <VBox/log.h>
27#include <VBox/vmm/pgm.h>
28
29#include <iprt/assert.h>
30#include <iprt/semaphore.h>
31#include <iprt/uuid.h>
32#include <iprt/mem.h>
33#include <iprt/avl.h>
34
35#include <VBoxVideo.h> /* required by DevVGA.h */
36
37/* should go BEFORE any other DevVGA include to make all DevVGA.h config defines be visible */
38#include "DevVGA.h"
39
40#include "DevVGA-SVGA.h"
41#include "DevVGA-SVGA3d.h"
42#include "DevVGA-SVGA3d-internal.h"
43
44/* Enable to disassemble defined shaders. */
45#if defined(DEBUG) && 0 /* Disabled as we don't have the DirectX SDK avaible atm. */
46#define DUMP_SHADER_DISASSEMBLY
47#endif
48
49#ifdef DUMP_SHADER_DISASSEMBLY
50#include <d3dx9shader.h>
51#endif
52
53
54/*********************************************************************************************************************************
55* Defined Constants And Macros *
56*********************************************************************************************************************************/
57/* Enable to render the result of DrawPrimitive in a seperate window. */
58//#define DEBUG_GFX_WINDOW
59
60#define FOURCC_INTZ (D3DFORMAT)MAKEFOURCC('I', 'N', 'T', 'Z')
61#define FOURCC_NULL (D3DFORMAT)MAKEFOURCC('N', 'U', 'L', 'L')
62
63
64/*********************************************************************************************************************************
65* Structures and Typedefs *
66*********************************************************************************************************************************/
67
68typedef struct
69{
70 DWORD Usage;
71 D3DRESOURCETYPE ResourceType;
72 SVGA3dFormatOp FormatOp;
73} VMSVGA3DFORMATSUPPORT;
74
75
76/*********************************************************************************************************************************
77* Global Variables *
78*********************************************************************************************************************************/
79static VMSVGA3DFORMATSUPPORT const g_aFormatSupport[] =
80{
81 {
82 0,
83 D3DRTYPE_SURFACE,
84 SVGA3DFORMAT_OP_OFFSCREENPLAIN,
85 },
86 {
87 D3DUSAGE_RENDERTARGET,
88 D3DRTYPE_SURFACE,
89 (SVGA3dFormatOp) (SVGA3DFORMAT_OP_OFFSCREEN_RENDERTARGET | SVGA3DFORMAT_OP_SAME_FORMAT_RENDERTARGET),
90 },
91 {
92 D3DUSAGE_AUTOGENMIPMAP,
93 D3DRTYPE_TEXTURE,
94 SVGA3DFORMAT_OP_AUTOGENMIPMAP,
95 },
96 {
97 D3DUSAGE_DMAP,
98 D3DRTYPE_TEXTURE,
99 SVGA3DFORMAT_OP_DMAP,
100 },
101 {
102 0,
103 D3DRTYPE_TEXTURE,
104 SVGA3DFORMAT_OP_TEXTURE,
105 },
106 {
107 0,
108 D3DRTYPE_CUBETEXTURE,
109 SVGA3DFORMAT_OP_CUBETEXTURE,
110 },
111 {
112 0,
113 D3DRTYPE_VOLUMETEXTURE,
114 SVGA3DFORMAT_OP_VOLUMETEXTURE,
115 },
116 {
117 D3DUSAGE_QUERY_VERTEXTEXTURE,
118 D3DRTYPE_TEXTURE,
119 SVGA3DFORMAT_OP_VERTEXTEXTURE,
120 },
121 {
122 D3DUSAGE_QUERY_LEGACYBUMPMAP,
123 D3DRTYPE_TEXTURE,
124 SVGA3DFORMAT_OP_BUMPMAP,
125 },
126 {
127 D3DUSAGE_QUERY_SRGBREAD,
128 D3DRTYPE_TEXTURE,
129 SVGA3DFORMAT_OP_SRGBREAD,
130 },
131 {
132 D3DUSAGE_QUERY_SRGBWRITE,
133 D3DRTYPE_TEXTURE,
134 SVGA3DFORMAT_OP_SRGBWRITE,
135 }
136};
137
138static VMSVGA3DFORMATSUPPORT const g_aFeatureReject[] =
139{
140 {
141 D3DUSAGE_QUERY_WRAPANDMIP,
142 D3DRTYPE_TEXTURE,
143 SVGA3DFORMAT_OP_NOTEXCOORDWRAPNORMIP
144 },
145 {
146 D3DUSAGE_QUERY_FILTER,
147 D3DRTYPE_TEXTURE,
148 SVGA3DFORMAT_OP_NOFILTER
149 },
150 {
151 D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING,
152 D3DRTYPE_TEXTURE, /* ?? */
153 SVGA3DFORMAT_OP_NOALPHABLEND
154 },
155};
156
157
158/*********************************************************************************************************************************
159* Internal Functions *
160*********************************************************************************************************************************/
161static void vmsvgaDumpD3DCaps(D3DCAPS9 *pCaps);
162
163
164
165int vmsvga3dInit(PVGASTATE pThis)
166{
167 PVMSVGA3DSTATE pState;
168 int rc;
169
170 pThis->svga.p3dState = pState = (PVMSVGA3DSTATE)RTMemAllocZ(sizeof(VMSVGA3DSTATE));
171 AssertReturn(pThis->svga.p3dState, VERR_NO_MEMORY);
172
173 /* Create event semaphore. */
174 rc = RTSemEventCreate(&pState->WndRequestSem);
175 if (RT_FAILURE(rc))
176 {
177 Log(("%s: Failed to create event semaphore for window handling.\n", __FUNCTION__));
178 return rc;
179 }
180
181 /* Create the async IO thread. */
182 rc = RTThreadCreate(&pState->pWindowThread, vmsvga3dWindowThread, pState->WndRequestSem, 0, RTTHREADTYPE_GUI, 0, "VMSVGA3DWND");
183 if (RT_FAILURE(rc))
184 {
185 AssertMsgFailed(("%s: Async IO Thread creation for 3d window handling failed rc=%d\n", __FUNCTION__, rc));
186 return rc;
187 }
188
189 return VINF_SUCCESS;
190}
191
192int vmsvga3dPowerOn(PVGASTATE pThis)
193{
194 PVMSVGA3DSTATE pState = pThis->svga.p3dState;
195 AssertReturn(pThis->svga.p3dState, VERR_NO_MEMORY);
196 HRESULT hr;
197
198 if (pState->pD3D9)
199 return VINF_SUCCESS; /* already initialized (load state) */
200
201#ifdef VBOX_VMSVGA3D_WITH_WINE_OPENGL
202 pState->pD3D9 = Direct3DCreate9(D3D_SDK_VERSION);
203 AssertReturn(pState->pD3D9, VERR_INTERNAL_ERROR);
204#else
205 /* Direct3DCreate9Ex was introduced in Vista, so resolve it dynamically. */
206 typedef HRESULT (WINAPI *PFNDIRECT3DCREATE9EX)(UINT, IDirect3D9Ex **);
207 PFNDIRECT3DCREATE9EX pfnDirect3dCreate9Ex = (PFNDIRECT3DCREATE9EX)RTLdrGetSystemSymbol("d3d9.dll", "Direct3DCreate9Ex");
208 if (!pfnDirect3dCreate9Ex)
209 return PDMDevHlpVMSetError(pThis->CTX_SUFF(pDevIns), VERR_SYMBOL_NOT_FOUND, RT_SRC_POS,
210 "vmsvga3d: Unable to locate Direct3DCreate9Ex. This feature requires Vista and later.");
211 hr = pfnDirect3dCreate9Ex(D3D_SDK_VERSION, &pState->pD3D9);
212 AssertReturn(hr == D3D_OK, VERR_INTERNAL_ERROR);
213#endif
214 hr = pState->pD3D9->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &pState->caps);
215 AssertReturn(hr == D3D_OK, VERR_INTERNAL_ERROR);
216
217 vmsvgaDumpD3DCaps(&pState->caps);
218
219 /* Check if INTZ is supported. */
220 hr = pState->pD3D9->CheckDeviceFormat(D3DADAPTER_DEFAULT,
221 D3DDEVTYPE_HAL,
222 D3DFMT_X8R8G8B8, /* assume standard 32-bit display mode */
223 0,
224 D3DRTYPE_TEXTURE,
225 FOURCC_INTZ);
226 if (hr != D3D_OK)
227 {
228 /* INTZ support is essential to support depth surfaces used as textures. */
229 LogRel(("VMSVGA: texture format INTZ not supported!!!\n"));
230 }
231 else
232 pState->fSupportedSurfaceINTZ = true;
233
234 /* Check if NULL is supported. */
235 hr = pState->pD3D9->CheckDeviceFormat(D3DADAPTER_DEFAULT,
236 D3DDEVTYPE_HAL,
237 D3DFMT_X8R8G8B8, /* assume standard 32-bit display mode */
238 D3DUSAGE_RENDERTARGET,
239 D3DRTYPE_SURFACE,
240 FOURCC_NULL);
241 if (hr != D3D_OK)
242 {
243 /* NULL is a dummy surface which can be used as a render target to save memory. */
244 LogRel(("VMSVGA: surface format NULL not supported!!!\n"));
245 }
246 else
247 pState->fSupportedSurfaceNULL = true;
248
249
250 /* Check if DX9 depth stencil textures are supported */
251 hr = pState->pD3D9->CheckDeviceFormat(D3DADAPTER_DEFAULT,
252 D3DDEVTYPE_HAL,
253 D3DFMT_X8R8G8B8, /* assume standard 32-bit display mode */
254 D3DUSAGE_DEPTHSTENCIL,
255 D3DRTYPE_TEXTURE,
256 D3DFMT_D16);
257 if (hr != D3D_OK)
258 {
259 LogRel(("VMSVGA: texture format D3DFMT_D16 not supported\n"));
260 }
261
262 hr = pState->pD3D9->CheckDeviceFormat(D3DADAPTER_DEFAULT,
263 D3DDEVTYPE_HAL,
264 D3DFMT_X8R8G8B8, /* assume standard 32-bit display mode */
265 D3DUSAGE_DEPTHSTENCIL,
266 D3DRTYPE_TEXTURE,
267 D3DFMT_D24X8);
268 if (hr != D3D_OK)
269 {
270 LogRel(("VMSVGA: texture format D3DFMT_D24X8 not supported\n"));
271 }
272 hr = pState->pD3D9->CheckDeviceFormat(D3DADAPTER_DEFAULT,
273 D3DDEVTYPE_HAL,
274 D3DFMT_X8R8G8B8, /* assume standard 32-bit display mode */
275 D3DUSAGE_DEPTHSTENCIL,
276 D3DRTYPE_TEXTURE,
277 D3DFMT_D24S8);
278 if (hr != D3D_OK)
279 {
280 LogRel(("VMSVGA: texture format D3DFMT_D24S8 not supported\n"));
281 }
282 return VINF_SUCCESS;
283}
284
285int vmsvga3dReset(PVGASTATE pThis)
286{
287 PVMSVGA3DSTATE pState = pThis->svga.p3dState;
288 AssertReturn(pThis->svga.p3dState, VERR_NO_MEMORY);
289
290 /* Destroy all leftover surfaces. */
291 for (uint32_t i = 0; i < pState->cSurfaces; i++)
292 {
293 if (pState->papSurfaces[i]->id != SVGA3D_INVALID_ID)
294 vmsvga3dSurfaceDestroy(pThis, pState->papSurfaces[i]->id);
295 }
296
297 /* Destroy all leftover contexts. */
298 for (uint32_t i = 0; i < pState->cContexts; i++)
299 {
300 if (pState->papContexts[i]->id != SVGA3D_INVALID_ID)
301 vmsvga3dContextDestroy(pThis, pState->papContexts[i]->id);
302 }
303 return VINF_SUCCESS;
304}
305
306int vmsvga3dTerminate(PVGASTATE pThis)
307{
308 PVMSVGA3DSTATE pState = pThis->svga.p3dState;
309 AssertReturn(pThis->svga.p3dState, VERR_NO_MEMORY);
310
311 int rc = vmsvga3dReset(pThis);
312 AssertRCReturn(rc, rc);
313
314 /* Terminate the window creation thread. */
315 rc = vmsvga3dSendThreadMessage(pState->pWindowThread, pState->WndRequestSem, WM_VMSVGA3D_EXIT, 0, 0);
316 AssertRCReturn(rc, rc);
317
318 RTSemEventDestroy(pState->WndRequestSem);
319
320 if (pState->pD3D9)
321 pState->pD3D9->Release();
322
323 return VINF_SUCCESS;
324}
325
326void vmsvga3dUpdateHostScreenViewport(PVGASTATE pThis, uint32_t idScreen, VMSVGAVIEWPORT const *pOldViewport)
327{
328 /** @todo Scroll the screen content without requiring the guest to redraw. */
329 NOREF(pThis); NOREF(idScreen); NOREF(pOldViewport);
330}
331
332static uint32_t vmsvga3dGetSurfaceFormatSupport(PVMSVGA3DSTATE pState3D, uint32_t idx3dCaps, D3DFORMAT format)
333{
334 NOREF(idx3dCaps);
335 HRESULT hr;
336 uint32_t result = 0;
337
338 /* Try if the format can be used for the primary display. */
339 hr = pState3D->pD3D9->CheckDeviceFormat(D3DADAPTER_DEFAULT,
340 D3DDEVTYPE_HAL,
341 format,
342 0,
343 D3DRTYPE_SURFACE,
344 format);
345
346 for (unsigned i = 0; i < RT_ELEMENTS(g_aFormatSupport); i++)
347 {
348 hr = pState3D->pD3D9->CheckDeviceFormat(D3DADAPTER_DEFAULT,
349 D3DDEVTYPE_HAL,
350 D3DFMT_X8R8G8B8, /* assume standard 32-bit display mode */
351 g_aFormatSupport[i].Usage,
352 g_aFormatSupport[i].ResourceType,
353 format);
354 if (hr == D3D_OK)
355 result |= g_aFormatSupport[i].FormatOp;
356 }
357
358 /* Check for features only if the format is supported in any form. */
359 if (result)
360 {
361 for (unsigned i = 0; i < RT_ELEMENTS(g_aFeatureReject); i++)
362 {
363 hr = pState3D->pD3D9->CheckDeviceFormat(D3DADAPTER_DEFAULT,
364 D3DDEVTYPE_HAL,
365 D3DFMT_X8R8G8B8, /* assume standard 32-bit display mode */
366 g_aFeatureReject[i].Usage,
367 g_aFeatureReject[i].ResourceType,
368 format);
369 if (hr != D3D_OK)
370 result |= g_aFeatureReject[i].FormatOp;
371 }
372 }
373
374 /** @todo missing:
375 *
376 * SVGA3DFORMAT_OP_PIXELSIZE
377 */
378
379 switch (idx3dCaps)
380 {
381 case SVGA3D_DEVCAP_SURFACEFMT_X8R8G8B8:
382 case SVGA3D_DEVCAP_SURFACEFMT_X1R5G5B5:
383 case SVGA3D_DEVCAP_SURFACEFMT_R5G6B5:
384 result |= SVGA3DFORMAT_OP_MEMBEROFGROUP_ARGB
385 | SVGA3DFORMAT_OP_CONVERT_TO_ARGB
386 | SVGA3DFORMAT_OP_DISPLAYMODE /* Should not be set for alpha formats. */
387 | SVGA3DFORMAT_OP_3DACCELERATION; /* implies OP_DISPLAYMODE */
388 break;
389
390 case SVGA3D_DEVCAP_SURFACEFMT_A8R8G8B8:
391 case SVGA3D_DEVCAP_SURFACEFMT_A2R10G10B10:
392 case SVGA3D_DEVCAP_SURFACEFMT_A1R5G5B5:
393 case SVGA3D_DEVCAP_SURFACEFMT_A4R4G4B4:
394 result |= SVGA3DFORMAT_OP_MEMBEROFGROUP_ARGB
395 | SVGA3DFORMAT_OP_CONVERT_TO_ARGB
396 | SVGA3DFORMAT_OP_SAME_FORMAT_UP_TO_ALPHA_RENDERTARGET;
397 break;
398
399 }
400 Log(("CAPS: %s =\n%s\n", vmsvga3dGetCapString(idx3dCaps), vmsvga3dGet3dFormatString(result)));
401
402 return result;
403}
404
405static uint32_t vmsvga3dGetDepthFormatSupport(PVMSVGA3DSTATE pState3D, uint32_t idx3dCaps, D3DFORMAT format)
406{
407 RT_NOREF(idx3dCaps);
408 HRESULT hr;
409 uint32_t result = 0;
410
411 hr = pState3D->pD3D9->CheckDeviceFormat(D3DADAPTER_DEFAULT,
412 D3DDEVTYPE_HAL,
413 D3DFMT_X8R8G8B8, /* assume standard 32-bit display mode */
414 D3DUSAGE_DEPTHSTENCIL,
415 D3DRTYPE_SURFACE,
416 format);
417 if (hr == D3D_OK)
418 result = SVGA3DFORMAT_OP_ZSTENCIL
419 | SVGA3DFORMAT_OP_ZSTENCIL_WITH_ARBITRARY_COLOR_DEPTH
420 | SVGA3DFORMAT_OP_TEXTURE /* Necessary for Ubuntu Unity */;
421
422 Log(("CAPS: %s =\n%s\n", vmsvga3dGetCapString(idx3dCaps), vmsvga3dGet3dFormatString(result)));
423 return result;
424}
425
426
427int vmsvga3dQueryCaps(PVGASTATE pThis, uint32_t idx3dCaps, uint32_t *pu32Val)
428{
429 PVMSVGA3DSTATE pState = pThis->svga.p3dState;
430 AssertReturn(pState, VERR_NO_MEMORY);
431 D3DCAPS9 *pCaps = &pState->caps;
432 int rc = VINF_SUCCESS;
433
434 *pu32Val = 0;
435
436 switch (idx3dCaps)
437 {
438 case SVGA3D_DEVCAP_3D:
439 *pu32Val = 1; /* boolean? */
440 break;
441
442 case SVGA3D_DEVCAP_MAX_LIGHTS:
443 *pu32Val = pCaps->MaxActiveLights;
444 break;
445
446 case SVGA3D_DEVCAP_MAX_TEXTURES:
447 *pu32Val = pCaps->MaxSimultaneousTextures;
448 break;
449
450 case SVGA3D_DEVCAP_MAX_CLIP_PLANES:
451 *pu32Val = pCaps->MaxUserClipPlanes;
452 break;
453
454 case SVGA3D_DEVCAP_VERTEX_SHADER_VERSION:
455 switch (pCaps->VertexShaderVersion)
456 {
457 case D3DVS_VERSION(1,1):
458 *pu32Val = SVGA3DVSVERSION_11;
459 break;
460 case D3DVS_VERSION(2,0):
461 *pu32Val = SVGA3DVSVERSION_20;
462 break;
463 case D3DVS_VERSION(3,0):
464 *pu32Val = SVGA3DVSVERSION_30;
465 break;
466 case D3DVS_VERSION(4,0):
467 *pu32Val = SVGA3DVSVERSION_40;
468 break;
469 default:
470 LogRel(("VMSVGA: Unsupported vertex shader version %x\n", pCaps->VertexShaderVersion));
471 break;
472 }
473 break;
474
475 case SVGA3D_DEVCAP_VERTEX_SHADER:
476 /* boolean? */
477 *pu32Val = 1;
478 break;
479
480 case SVGA3D_DEVCAP_FRAGMENT_SHADER_VERSION:
481 switch (pCaps->PixelShaderVersion)
482 {
483 case D3DPS_VERSION(1,1):
484 *pu32Val = SVGA3DPSVERSION_11;
485 break;
486 case D3DPS_VERSION(1,2):
487 *pu32Val = SVGA3DPSVERSION_12;
488 break;
489 case D3DPS_VERSION(1,3):
490 *pu32Val = SVGA3DPSVERSION_13;
491 break;
492 case D3DPS_VERSION(1,4):
493 *pu32Val = SVGA3DPSVERSION_14;
494 break;
495 case D3DPS_VERSION(2,0):
496 *pu32Val = SVGA3DPSVERSION_20;
497 break;
498 case D3DPS_VERSION(3,0):
499 *pu32Val = SVGA3DPSVERSION_30;
500 break;
501 case D3DPS_VERSION(4,0):
502 *pu32Val = SVGA3DPSVERSION_40;
503 break;
504 default:
505 LogRel(("VMSVGA: Unsupported pixel shader version %x\n", pCaps->PixelShaderVersion));
506 break;
507 }
508 break;
509
510 case SVGA3D_DEVCAP_FRAGMENT_SHADER:
511 /* boolean? */
512 *pu32Val = 1;
513 break;
514
515 case SVGA3D_DEVCAP_S23E8_TEXTURES:
516 case SVGA3D_DEVCAP_S10E5_TEXTURES:
517 /* Must be obsolete by now; surface format caps specify the same thing. */
518 rc = VERR_INVALID_PARAMETER;
519 break;
520
521 case SVGA3D_DEVCAP_MAX_FIXED_VERTEXBLEND:
522 break;
523
524 /*
525 * 2. The BUFFER_FORMAT capabilities are deprecated, and they always
526 * return TRUE. Even on physical hardware that does not support
527 * these formats natively, the SVGA3D device will provide an emulation
528 * which should be invisible to the guest OS.
529 */
530 case SVGA3D_DEVCAP_D16_BUFFER_FORMAT:
531 case SVGA3D_DEVCAP_D24S8_BUFFER_FORMAT:
532 case SVGA3D_DEVCAP_D24X8_BUFFER_FORMAT:
533 *pu32Val = 1;
534 break;
535
536 case SVGA3D_DEVCAP_QUERY_TYPES:
537 break;
538
539 case SVGA3D_DEVCAP_TEXTURE_GRADIENT_SAMPLING:
540 break;
541
542 case SVGA3D_DEVCAP_MAX_POINT_SIZE:
543 AssertCompile(sizeof(uint32_t) == sizeof(float));
544 *(float *)pu32Val = pCaps->MaxPointSize;
545 break;
546
547 case SVGA3D_DEVCAP_MAX_SHADER_TEXTURES:
548 /** @todo ?? */
549 rc = VERR_INVALID_PARAMETER;
550 break;
551
552 case SVGA3D_DEVCAP_MAX_TEXTURE_WIDTH:
553 *pu32Val = pCaps->MaxTextureWidth;
554 break;
555
556 case SVGA3D_DEVCAP_MAX_TEXTURE_HEIGHT:
557 *pu32Val = pCaps->MaxTextureHeight;
558 break;
559
560 case SVGA3D_DEVCAP_MAX_VOLUME_EXTENT:
561 *pu32Val = pCaps->MaxVolumeExtent;
562 break;
563
564 case SVGA3D_DEVCAP_MAX_TEXTURE_REPEAT:
565 *pu32Val = pCaps->MaxTextureRepeat;
566 break;
567
568 case SVGA3D_DEVCAP_MAX_TEXTURE_ASPECT_RATIO:
569 *pu32Val = pCaps->MaxTextureAspectRatio;
570 break;
571
572 case SVGA3D_DEVCAP_MAX_TEXTURE_ANISOTROPY:
573 *pu32Val = pCaps->MaxAnisotropy;
574 break;
575
576 case SVGA3D_DEVCAP_MAX_PRIMITIVE_COUNT:
577 *pu32Val = pCaps->MaxPrimitiveCount;
578 break;
579
580 case SVGA3D_DEVCAP_MAX_VERTEX_INDEX:
581 *pu32Val = pCaps->MaxVertexIndex;
582 break;
583
584 case SVGA3D_DEVCAP_MAX_VERTEX_SHADER_INSTRUCTIONS:
585 *pu32Val = pCaps->MaxVertexShader30InstructionSlots;
586 break;
587
588 case SVGA3D_DEVCAP_MAX_FRAGMENT_SHADER_INSTRUCTIONS:
589 *pu32Val = pCaps->MaxPixelShader30InstructionSlots;
590 break;
591
592 case SVGA3D_DEVCAP_MAX_VERTEX_SHADER_TEMPS:
593 *pu32Val = pCaps->VS20Caps.NumTemps;
594 break;
595
596 case SVGA3D_DEVCAP_MAX_FRAGMENT_SHADER_TEMPS:
597 *pu32Val = pCaps->PS20Caps.NumTemps;
598 break;
599
600 case SVGA3D_DEVCAP_TEXTURE_OPS:
601 break;
602
603 case SVGA3D_DEVCAP_MULTISAMPLE_NONMASKABLESAMPLES:
604 break;
605
606 case SVGA3D_DEVCAP_MULTISAMPLE_MASKABLESAMPLES:
607 break;
608
609 case SVGA3D_DEVCAP_ALPHATOCOVERAGE:
610 break;
611
612 case SVGA3D_DEVCAP_SUPERSAMPLE:
613 break;
614
615 case SVGA3D_DEVCAP_AUTOGENMIPMAPS:
616 *pu32Val = !!(pCaps->Caps2 & D3DCAPS2_CANAUTOGENMIPMAP);
617 break;
618
619 case SVGA3D_DEVCAP_MAX_VERTEX_SHADER_TEXTURES:
620 break;
621
622 case SVGA3D_DEVCAP_MAX_RENDER_TARGETS: /** @todo same thing? */
623 case SVGA3D_DEVCAP_MAX_SIMULTANEOUS_RENDER_TARGETS:
624 *pu32Val = pCaps->NumSimultaneousRTs;
625 break;
626
627 /*
628 * This is the maximum number of SVGA context IDs that the guest
629 * can define using SVGA_3D_CMD_CONTEXT_DEFINE.
630 */
631 case SVGA3D_DEVCAP_MAX_CONTEXT_IDS:
632 *pu32Val = SVGA3D_MAX_CONTEXT_IDS;
633 break;
634
635 /*
636 * This is the maximum number of SVGA surface IDs that the guest
637 * can define using SVGA_3D_CMD_SURFACE_DEFINE*.
638 */
639 case SVGA3D_DEVCAP_MAX_SURFACE_IDS:
640 *pu32Val = SVGA3D_MAX_SURFACE_IDS;
641 break;
642
643 /* Supported surface formats. */
644 case SVGA3D_DEVCAP_SURFACEFMT_X8R8G8B8:
645 *pu32Val = vmsvga3dGetSurfaceFormatSupport(pState, idx3dCaps, D3DFMT_X8R8G8B8);
646 break;
647
648 case SVGA3D_DEVCAP_SURFACEFMT_A8R8G8B8:
649 *pu32Val = vmsvga3dGetSurfaceFormatSupport(pState, idx3dCaps, D3DFMT_A8R8G8B8);
650 break;
651
652 case SVGA3D_DEVCAP_SURFACEFMT_A2R10G10B10:
653 *pu32Val = vmsvga3dGetSurfaceFormatSupport(pState, idx3dCaps, D3DFMT_A2R10G10B10);
654 break;
655
656 case SVGA3D_DEVCAP_SURFACEFMT_X1R5G5B5:
657 *pu32Val = vmsvga3dGetSurfaceFormatSupport(pState, idx3dCaps, D3DFMT_X1R5G5B5);
658 break;
659
660 case SVGA3D_DEVCAP_SURFACEFMT_A1R5G5B5:
661 *pu32Val = vmsvga3dGetSurfaceFormatSupport(pState, idx3dCaps, D3DFMT_A1R5G5B5);
662 break;
663
664 case SVGA3D_DEVCAP_SURFACEFMT_A4R4G4B4:
665 *pu32Val = vmsvga3dGetSurfaceFormatSupport(pState, idx3dCaps, D3DFMT_A4R4G4B4);
666 break;
667
668 case SVGA3D_DEVCAP_SURFACEFMT_R5G6B5:
669 *pu32Val = vmsvga3dGetSurfaceFormatSupport(pState, idx3dCaps, D3DFMT_A4R4G4B4);
670 break;
671
672 case SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE16:
673 *pu32Val = vmsvga3dGetSurfaceFormatSupport(pState, idx3dCaps, D3DFMT_L16);
674 break;
675
676 case SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8_ALPHA8:
677 *pu32Val = vmsvga3dGetSurfaceFormatSupport(pState, idx3dCaps, D3DFMT_A8L8);
678 break;
679
680 case SVGA3D_DEVCAP_SURFACEFMT_ALPHA8:
681 *pu32Val = vmsvga3dGetSurfaceFormatSupport(pState, idx3dCaps, D3DFMT_A8);
682 break;
683
684 case SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8:
685 *pu32Val = vmsvga3dGetSurfaceFormatSupport(pState, idx3dCaps, D3DFMT_L8);
686 break;
687
688 case SVGA3D_DEVCAP_SURFACEFMT_Z_D16:
689 *pu32Val = vmsvga3dGetDepthFormatSupport(pState, idx3dCaps, D3DFMT_D16);
690 break;
691
692 case SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8:
693 case SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8_INT: /** @todo not correct */
694 *pu32Val = vmsvga3dGetDepthFormatSupport(pState, idx3dCaps, D3DFMT_D24S8);
695 break;
696
697 case SVGA3D_DEVCAP_SURFACEFMT_Z_D24X8:
698 *pu32Val = vmsvga3dGetDepthFormatSupport(pState, idx3dCaps, D3DFMT_D24X8);
699 break;
700
701 case SVGA3D_DEVCAP_SURFACEFMT_Z_DF16:
702 /** @todo supposed to be floating-point, but unable to find a match for D3D9... */
703 *pu32Val = 0;
704 break;
705
706 case SVGA3D_DEVCAP_SURFACEFMT_Z_DF24:
707 *pu32Val = vmsvga3dGetDepthFormatSupport(pState, idx3dCaps, D3DFMT_D24FS8);
708 break;
709
710 case SVGA3D_DEVCAP_SURFACEFMT_DXT1:
711 *pu32Val = vmsvga3dGetSurfaceFormatSupport(pState, idx3dCaps, D3DFMT_DXT1);
712 break;
713
714 case SVGA3D_DEVCAP_SURFACEFMT_DXT2:
715 *pu32Val = vmsvga3dGetSurfaceFormatSupport(pState, idx3dCaps, D3DFMT_DXT2);
716 break;
717
718 case SVGA3D_DEVCAP_SURFACEFMT_DXT3:
719 *pu32Val = vmsvga3dGetSurfaceFormatSupport(pState, idx3dCaps, D3DFMT_DXT3);
720 break;
721
722 case SVGA3D_DEVCAP_SURFACEFMT_DXT4:
723 *pu32Val = vmsvga3dGetSurfaceFormatSupport(pState, idx3dCaps, D3DFMT_DXT4);
724 break;
725
726 case SVGA3D_DEVCAP_SURFACEFMT_DXT5:
727 *pu32Val = vmsvga3dGetSurfaceFormatSupport(pState, idx3dCaps, D3DFMT_DXT5);
728 break;
729
730 case SVGA3D_DEVCAP_SURFACEFMT_BUMPX8L8V8U8:
731 *pu32Val = vmsvga3dGetSurfaceFormatSupport(pState, idx3dCaps, D3DFMT_X8L8V8U8);
732 break;
733
734 case SVGA3D_DEVCAP_SURFACEFMT_A2W10V10U10:
735 *pu32Val = vmsvga3dGetSurfaceFormatSupport(pState, idx3dCaps, D3DFMT_A2W10V10U10);
736 break;
737
738 case SVGA3D_DEVCAP_SURFACEFMT_BUMPU8V8:
739 *pu32Val = vmsvga3dGetSurfaceFormatSupport(pState, idx3dCaps, D3DFMT_V8U8);
740 break;
741
742 case SVGA3D_DEVCAP_SURFACEFMT_Q8W8V8U8:
743 *pu32Val = vmsvga3dGetSurfaceFormatSupport(pState, idx3dCaps, D3DFMT_Q8W8V8U8);
744 break;
745
746 case SVGA3D_DEVCAP_SURFACEFMT_CxV8U8:
747 *pu32Val = vmsvga3dGetSurfaceFormatSupport(pState, idx3dCaps, D3DFMT_CxV8U8);
748 break;
749
750 case SVGA3D_DEVCAP_SURFACEFMT_R_S10E5:
751 *pu32Val = vmsvga3dGetSurfaceFormatSupport(pState, idx3dCaps, D3DFMT_R16F);
752 break;
753
754 case SVGA3D_DEVCAP_SURFACEFMT_R_S23E8:
755 *pu32Val = vmsvga3dGetSurfaceFormatSupport(pState, idx3dCaps, D3DFMT_R32F);
756 break;
757
758 case SVGA3D_DEVCAP_SURFACEFMT_RG_S10E5:
759 *pu32Val = vmsvga3dGetSurfaceFormatSupport(pState, idx3dCaps, D3DFMT_G16R16F);
760 break;
761
762 case SVGA3D_DEVCAP_SURFACEFMT_RG_S23E8:
763 *pu32Val = vmsvga3dGetSurfaceFormatSupport(pState, idx3dCaps, D3DFMT_G32R32F);
764 break;
765
766 case SVGA3D_DEVCAP_SURFACEFMT_ARGB_S10E5:
767 *pu32Val = vmsvga3dGetSurfaceFormatSupport(pState, idx3dCaps, D3DFMT_A16B16G16R16F);
768 break;
769
770 case SVGA3D_DEVCAP_SURFACEFMT_ARGB_S23E8:
771 *pu32Val = vmsvga3dGetSurfaceFormatSupport(pState, idx3dCaps, D3DFMT_A32B32G32R32F);
772 break;
773
774 case SVGA3D_DEVCAP_SURFACEFMT_V16U16:
775 *pu32Val = vmsvga3dGetSurfaceFormatSupport(pState, idx3dCaps, D3DFMT_V16U16);
776 break;
777
778 case SVGA3D_DEVCAP_SURFACEFMT_G16R16:
779 *pu32Val = vmsvga3dGetSurfaceFormatSupport(pState, idx3dCaps, D3DFMT_G16R16);
780 break;
781
782 case SVGA3D_DEVCAP_SURFACEFMT_A16B16G16R16:
783 *pu32Val = vmsvga3dGetSurfaceFormatSupport(pState, idx3dCaps, D3DFMT_A16B16G16R16);
784 break;
785
786 case SVGA3D_DEVCAP_SURFACEFMT_UYVY:
787 *pu32Val = vmsvga3dGetSurfaceFormatSupport(pState, idx3dCaps, D3DFMT_UYVY);
788 break;
789
790 case SVGA3D_DEVCAP_SURFACEFMT_YUY2:
791 *pu32Val = vmsvga3dGetSurfaceFormatSupport(pState, idx3dCaps, D3DFMT_YUY2);
792 break;
793
794 case SVGA3D_DEVCAP_SURFACEFMT_NV12:
795 *pu32Val = vmsvga3dGetSurfaceFormatSupport(pState, idx3dCaps, (D3DFORMAT)MAKEFOURCC('N', 'V', '1', '2'));
796 break;
797
798 case SVGA3D_DEVCAP_SURFACEFMT_AYUV:
799 *pu32Val = vmsvga3dGetSurfaceFormatSupport(pState, idx3dCaps, (D3DFORMAT)MAKEFOURCC('A', 'Y', 'U', 'V'));
800 break;
801
802 case SVGA3D_DEVCAP_SURFACEFMT_BC4_UNORM:
803 case SVGA3D_DEVCAP_SURFACEFMT_BC5_UNORM:
804 /* Unknown; only in DX10 & 11 */
805 Log(("CAPS: Unknown CAP %s\n", vmsvga3dGetCapString(idx3dCaps)));
806 rc = VERR_INVALID_PARAMETER;
807 *pu32Val = 0;
808 break;
809
810 default:
811 Log(("CAPS: Unexpected CAP %d\n", idx3dCaps));
812 rc = VERR_INVALID_PARAMETER;
813 break;
814 }
815#if 0
816 /* Dump of VMWare Player caps (from their log); for debugging purposes */
817 switch (idx3dCaps)
818 {
819 case 0:
820 *pu32Val = 0x00000001;
821 break;
822 case 1:
823 *pu32Val = 0x0000000a;
824 break;
825 case 2:
826 *pu32Val = 0x00000008;
827 break;
828 case 3: *pu32Val = 0x00000006; break;
829 case 4: *pu32Val = 0x00000007; break;
830 case 5: *pu32Val = 0x00000001; break;
831 case 6: *pu32Val = 0x0000000d; break;
832 case 7: *pu32Val = 0x00000001; break;
833 case 8: *pu32Val = 0x00000004; break;
834 case 9: *pu32Val = 0x00000001; break;
835 case 10: *pu32Val = 0x00000001; break;
836 case 11: *pu32Val = 0x00000004; break;
837 case 12: *pu32Val = 0x00000001; break;
838 case 13: *pu32Val = 0x00000001; break;
839 case 14: *pu32Val = 0x00000001; break;
840 case 15: *pu32Val = 0x00000001; break;
841 case 16: *pu32Val = 0x00000001; break;
842 case 17: *pu32Val = (uint32_t)256.000000; break;
843 case 18: *pu32Val = 0x00000014; break;
844 case 19: *pu32Val = 0x00001000; break;
845 case 20: *pu32Val = 0x00001000; break;
846 case 21: *pu32Val = 0x00000800; break;
847 case 22: *pu32Val = 0x00002000; break;
848 case 23: *pu32Val = 0x00000800; break;
849 case 24: *pu32Val = 0x00000010; break;
850 case 25: *pu32Val = 0x000fffff; break;
851 case 26: *pu32Val = 0x00ffffff; break;
852 case 27: *pu32Val = 0xffffffff; break;
853 case 28: *pu32Val = 0xffffffff; break;
854 case 29: *pu32Val = 0x00000020; break;
855 case 30: *pu32Val = 0x00000020; break;
856 case 31: *pu32Val = 0x03ffffff; break;
857 case 32: *pu32Val = 0x0098ec1f; break;
858 case 33: *pu32Val = 0x0098e11f; break;
859 case 34: *pu32Val = 0x0098e01f; break;
860 case 35: *pu32Val = 0x012c2000; break;
861 case 36: *pu32Val = 0x0098e11f; break;
862 case 37: *pu32Val = 0x0090c11f; break;
863 case 38: *pu32Val = 0x0098ec1f; break;
864 case 39: *pu32Val = 0x00804007; break;
865 case 40: *pu32Val = 0x0080c007; break;
866 case 41: *pu32Val = 0x00804007; break;
867 case 42: *pu32Val = 0x0080c007; break;
868 case 43: *pu32Val = 0x000000c1; break;
869 case 44: *pu32Val = 0x000000c1; break;
870 case 45: *pu32Val = 0x000000c1; break;
871 case 46: *pu32Val = 0x00808005; break;
872 case 47: *pu32Val = 0x00808005; break;
873 case 48: *pu32Val = 0x00808005; break;
874 case 49: *pu32Val = 0x00808005; break;
875 case 50: *pu32Val = 0x00808005; break;
876 case 51: *pu32Val = 0x01240000; break;
877 case 52: *pu32Val = 0x00814007; break;
878 case 53: *pu32Val = 0x00814007; break;
879 case 54: *pu32Val = 0x00814007; break;
880 case 55: *pu32Val = 0x01240000; break;
881 case 56: *pu32Val = 0x0080401f; break;
882 case 57: *pu32Val = 0x0080401f; break;
883 case 58: *pu32Val = 0x0080401f; break;
884 case 59: *pu32Val = 0x0080401f; break;
885 case 60: *pu32Val = 0x0080601f; break;
886 case 61: *pu32Val = 0x0080401f; break;
887 case 62: *pu32Val = 0x00000000; break;
888 case 63: *pu32Val = 0x00000004; break;
889 case 64: *pu32Val = 0x00000004; break;
890 case 65: *pu32Val = 0x00814005; break;
891 case 66: *pu32Val = 0x0080401f; break;
892 case 67: *pu32Val = 0x0080601f; break;
893 case 68: *pu32Val = 0x00006009; break;
894 case 69: *pu32Val = 0x00006001; break;
895 case 70: *pu32Val = 0x00000001; break;
896 case 71: *pu32Val = 0x0000000b; break;
897 case 72: *pu32Val = 0x00000001; break;
898 case 73: *pu32Val = 0x00000000; break;
899 case 74: *pu32Val = 0x00000000; break;
900 case 75: *pu32Val = 0x01246000; break;
901 case 76: *pu32Val = 0x00004009; break;
902 case 77: *pu32Val = 0x00000100; break;
903 case 78: *pu32Val = 0x00008000; break;
904 case 79: *pu32Val = 0x000000c1; break;
905 case 80: *pu32Val = 0x01240000; break;
906 case 81: *pu32Val = 0x000000c1; break;
907 case 82: *pu32Val = 0x00800005; break;
908 case 83: *pu32Val = 0x00800005; break;
909 case 84: *pu32Val = 0x00000000; break;
910 case 85: *pu32Val = 0x00000000; break;
911 case 86: *pu32Val = 0x00000000; break;
912 case 87: *pu32Val = 0x00000000; break;
913 case 88: *pu32Val = 0x00000000; break;
914 case 89: *pu32Val = (uint32_t) 0.000000; break;
915 case 90: *pu32Val = (uint32_t) 0.000000; break;
916 case 91: *pu32Val = 0x00006009; break;
917 default:
918// Log(("CAPS: Unexpected CAP %d\n", idx3dCaps));
919// rc = VERR_INVALID_PARAMETER;
920 break;
921 }
922#endif
923 Log(("CAPS: %d=%s - %x\n", idx3dCaps, vmsvga3dGetCapString(idx3dCaps), *pu32Val));
924 return rc;
925}
926
927/**
928 * Convert SVGA format value to its D3D equivalent
929 */
930D3DFORMAT vmsvga3dSurfaceFormat2D3D(SVGA3dSurfaceFormat format)
931{
932 switch (format)
933 {
934 case SVGA3D_X8R8G8B8:
935 return D3DFMT_X8R8G8B8;
936 case SVGA3D_A8R8G8B8:
937 return D3DFMT_A8R8G8B8;
938 case SVGA3D_R5G6B5:
939 return D3DFMT_R5G6B5;
940 case SVGA3D_X1R5G5B5:
941 return D3DFMT_X1R5G5B5;
942 case SVGA3D_A1R5G5B5:
943 return D3DFMT_A1R5G5B5;
944 case SVGA3D_A4R4G4B4:
945 return D3DFMT_A4R4G4B4;
946
947 case SVGA3D_Z_D32:
948 return D3DFMT_D32;
949 case SVGA3D_Z_D16:
950 return D3DFMT_D16;
951 case SVGA3D_Z_D24S8_INT: /** @todo not correct */
952 case SVGA3D_Z_D24S8:
953 return D3DFMT_D24S8;
954 case SVGA3D_Z_D15S1:
955 return D3DFMT_D15S1;
956 case SVGA3D_Z_D24X8:
957 return D3DFMT_D24X8;
958 /* Advanced D3D9 depth formats. */
959 case SVGA3D_Z_DF16:
960 /** @todo supposed to be floating-point, but unable to find a match for D3D9... */
961 AssertFailedReturn(D3DFMT_UNKNOWN);
962 case SVGA3D_Z_DF24:
963 return D3DFMT_D24FS8;
964
965 case SVGA3D_LUMINANCE8:
966 return D3DFMT_L8;
967 case SVGA3D_LUMINANCE4_ALPHA4:
968 return D3DFMT_A4L4;
969 case SVGA3D_LUMINANCE16:
970 return D3DFMT_L16;
971 case SVGA3D_LUMINANCE8_ALPHA8:
972 return D3DFMT_A8L8;
973
974 case SVGA3D_DXT1:
975 return D3DFMT_DXT1;
976 case SVGA3D_DXT2:
977 return D3DFMT_DXT2;
978 case SVGA3D_DXT3:
979 return D3DFMT_DXT3;
980 case SVGA3D_DXT4:
981 return D3DFMT_DXT4;
982 case SVGA3D_DXT5:
983 return D3DFMT_DXT5;
984
985 /* Bump-map formats */
986 case SVGA3D_BUMPU8V8:
987 return D3DFMT_V8U8;
988 case SVGA3D_BUMPL6V5U5:
989 return D3DFMT_L6V5U5;
990 case SVGA3D_BUMPX8L8V8U8:
991 return D3DFMT_X8L8V8U8;
992 case SVGA3D_BUMPL8V8U8:
993 /* No corresponding D3D9 equivalent. */
994 AssertFailedReturn(D3DFMT_UNKNOWN);
995 /* signed bump-map formats */
996 case SVGA3D_V8U8:
997 return D3DFMT_V8U8;
998 case SVGA3D_Q8W8V8U8:
999 return D3DFMT_Q8W8V8U8;
1000 case SVGA3D_CxV8U8:
1001 return D3DFMT_CxV8U8;
1002 /* mixed bump-map formats */
1003 case SVGA3D_X8L8V8U8:
1004 return D3DFMT_X8L8V8U8;
1005 case SVGA3D_A2W10V10U10:
1006 return D3DFMT_A2W10V10U10;
1007
1008 case SVGA3D_ARGB_S10E5: /* 16-bit floating-point ARGB */
1009 return D3DFMT_A16B16G16R16F;
1010 case SVGA3D_ARGB_S23E8: /* 32-bit floating-point ARGB */
1011 return D3DFMT_A32B32G32R32F;
1012
1013 case SVGA3D_A2R10G10B10:
1014 return D3DFMT_A2R10G10B10;
1015
1016 case SVGA3D_ALPHA8:
1017 return D3DFMT_A8;
1018
1019 /* Single- and dual-component floating point formats */
1020 case SVGA3D_R_S10E5:
1021 return D3DFMT_R16F;
1022 case SVGA3D_R_S23E8:
1023 return D3DFMT_R32F;
1024 case SVGA3D_RG_S10E5:
1025 return D3DFMT_G16R16F;
1026 case SVGA3D_RG_S23E8:
1027 return D3DFMT_G32R32F;
1028
1029 /*
1030 * Any surface can be used as a buffer object, but SVGA3D_BUFFER is
1031 * the most efficient format to use when creating new surfaces
1032 * expressly for index or vertex data.
1033 */
1034 case SVGA3D_BUFFER:
1035 return D3DFMT_UNKNOWN;
1036
1037 case SVGA3D_V16U16:
1038 return D3DFMT_V16U16;
1039
1040 case SVGA3D_G16R16:
1041 return D3DFMT_G16R16;
1042 case SVGA3D_A16B16G16R16:
1043 return D3DFMT_A16B16G16R16;
1044
1045 /* Packed Video formats */
1046 case SVGA3D_UYVY:
1047 return D3DFMT_UYVY;
1048 case SVGA3D_YUY2:
1049 return D3DFMT_YUY2;
1050
1051 /* Planar video formats */
1052 case SVGA3D_NV12:
1053 return (D3DFORMAT)MAKEFOURCC('N', 'V', '1', '2');
1054
1055 /* Video format with alpha */
1056 case SVGA3D_AYUV:
1057 return (D3DFORMAT)MAKEFOURCC('A', 'Y', 'U', 'V');
1058
1059 case SVGA3D_BC4_UNORM:
1060 case SVGA3D_BC5_UNORM:
1061 /* Unknown; only in DX10 & 11 */
1062 break;
1063
1064 case SVGA3D_FORMAT_MAX: /* shut up MSC */
1065 case SVGA3D_FORMAT_INVALID:
1066 break;
1067 }
1068 AssertFailedReturn(D3DFMT_UNKNOWN);
1069}
1070
1071/**
1072 * Convert SVGA multi sample count value to its D3D equivalent
1073 */
1074D3DMULTISAMPLE_TYPE vmsvga3dMultipeSampleCount2D3D(uint32_t multisampleCount)
1075{
1076 AssertCompile(D3DMULTISAMPLE_2_SAMPLES == 2);
1077 AssertCompile(D3DMULTISAMPLE_16_SAMPLES == 16);
1078
1079 if (multisampleCount > 16)
1080 return D3DMULTISAMPLE_NONE;
1081
1082 /** @todo exact same mapping as d3d? */
1083 return (D3DMULTISAMPLE_TYPE)multisampleCount;
1084}
1085
1086
1087/**
1088 * Destroy backend specific surface bits (part of SVGA_3D_CMD_SURFACE_DESTROY).
1089 *
1090 * @param pState The VMSVGA3d state.
1091 * @param pSurface The surface being destroyed.
1092 */
1093void vmsvga3dBackSurfaceDestroy(PVMSVGA3DSTATE pState, PVMSVGA3DSURFACE pSurface)
1094{
1095 RT_NOREF(pState);
1096 RTAvlU32Destroy(&pSurface->pSharedObjectTree, vmsvga3dSharedSurfaceDestroyTree, pSurface);
1097 Assert(pSurface->pSharedObjectTree == NULL);
1098
1099 switch (pSurface->flags & VMSVGA3D_SURFACE_HINT_SWITCH_MASK)
1100 {
1101 case SVGA3D_SURFACE_CUBEMAP:
1102 AssertFailed(); /** @todo */
1103 break;
1104
1105 case SVGA3D_SURFACE_HINT_INDEXBUFFER | SVGA3D_SURFACE_HINT_VERTEXBUFFER:
1106 case SVGA3D_SURFACE_HINT_INDEXBUFFER:
1107 case SVGA3D_SURFACE_HINT_VERTEXBUFFER:
1108 if (pSurface->fu32ActualUsageFlags == SVGA3D_SURFACE_HINT_VERTEXBUFFER)
1109 {
1110 if (pSurface->u.pVertexBuffer)
1111 pSurface->u.pVertexBuffer->Release();
1112 }
1113 else if (pSurface->fu32ActualUsageFlags == SVGA3D_SURFACE_HINT_INDEXBUFFER)
1114 {
1115 if (pSurface->u.pIndexBuffer)
1116 pSurface->u.pIndexBuffer->Release();
1117 }
1118 else
1119 AssertMsg(pSurface->u.pVertexBuffer == NULL, ("fu32ActualUsageFlags %x\n", pSurface->fu32ActualUsageFlags));
1120 break;
1121
1122 case SVGA3D_SURFACE_HINT_TEXTURE:
1123 case SVGA3D_SURFACE_HINT_TEXTURE | SVGA3D_SURFACE_HINT_RENDERTARGET:
1124 if (pSurface->u.pTexture)
1125 pSurface->u.pTexture->Release();
1126 if (pSurface->bounce.pTexture)
1127 pSurface->bounce.pTexture->Release();
1128 break;
1129
1130 case SVGA3D_SURFACE_HINT_RENDERTARGET:
1131 case SVGA3D_SURFACE_HINT_DEPTHSTENCIL:
1132 case SVGA3D_SURFACE_HINT_DEPTHSTENCIL | SVGA3D_SURFACE_HINT_TEXTURE: /** @todo actual texture surface not supported */
1133 if (pSurface->fStencilAsTexture)
1134 pSurface->u.pTexture->Release();
1135 else
1136 if (pSurface->u.pSurface)
1137 pSurface->u.pSurface->Release();
1138 break;
1139
1140 default:
1141 AssertMsg(!VMSVGA3DSURFACE_HAS_HW_SURFACE(pSurface), ("type=%x\n", (pSurface->flags & VMSVGA3D_SURFACE_HINT_SWITCH_MASK)));
1142 break;
1143 }
1144
1145 if (pSurface->pQuery)
1146 pSurface->pQuery->Release();
1147}
1148
1149
1150/*
1151 * Release all shared surface objects.
1152 */
1153DECLCALLBACK(int) vmsvga3dSharedSurfaceDestroyTree(PAVLU32NODECORE pNode, void *pvParam)
1154{
1155 PVMSVGA3DSHAREDSURFACE pSharedSurface = (PVMSVGA3DSHAREDSURFACE)pNode;
1156 PVMSVGA3DSURFACE pSurface = (PVMSVGA3DSURFACE)pvParam;
1157
1158 switch (pSurface->flags & (SVGA3D_SURFACE_HINT_INDEXBUFFER | SVGA3D_SURFACE_HINT_VERTEXBUFFER | SVGA3D_SURFACE_HINT_TEXTURE | SVGA3D_SURFACE_HINT_RENDERTARGET | SVGA3D_SURFACE_HINT_DEPTHSTENCIL | SVGA3D_SURFACE_CUBEMAP))
1159 {
1160 case SVGA3D_SURFACE_HINT_TEXTURE:
1161 case SVGA3D_SURFACE_HINT_TEXTURE | SVGA3D_SURFACE_HINT_RENDERTARGET:
1162 Log(("vmsvga3dSharedSurfaceDestroyTree: release shared object for context %d\n", pNode->Key));
1163 Assert(pSharedSurface->u.pTexture);
1164 if (pSharedSurface->u.pTexture)
1165 pSharedSurface->u.pTexture->Release();
1166 break;
1167
1168 default:
1169 AssertFailed();
1170 break;
1171 }
1172 RTMemFree(pNode);
1173 return 0;
1174}
1175
1176/* Get the shared surface copy or create a new one. */
1177static PVMSVGA3DSHAREDSURFACE vmsvga3dSurfaceGetSharedCopy(PVGASTATE pThis, PVMSVGA3DCONTEXT pContext, PVMSVGA3DSURFACE pSurface)
1178{
1179 RT_NOREF(pThis);
1180 Assert(pSurface->hSharedObject);
1181
1182 PVMSVGA3DSHAREDSURFACE pSharedSurface = (PVMSVGA3DSHAREDSURFACE)RTAvlU32Get(&pSurface->pSharedObjectTree, pContext->id);
1183 if (!pSharedSurface)
1184 {
1185 HRESULT hr;
1186 bool ret;
1187
1188 Log(("vmsvga3dSurfaceGetSharedCopy: Create shared texture copy d3d (%d,%d) cMip=%d usage %x format %x.\n",
1189 pSurface->pMipmapLevels[0].size.width,
1190 pSurface->pMipmapLevels[0].size.height,
1191 pSurface->faces[0],
1192 pSurface->fUsageD3D | D3DUSAGE_RENDERTARGET,
1193 pSurface->formatD3D));
1194
1195 pSharedSurface = (PVMSVGA3DSHAREDSURFACE)RTMemAllocZ(sizeof(*pSharedSurface));
1196 AssertReturn(pSharedSurface, NULL);
1197
1198 pSharedSurface->Core.Key = pContext->id;
1199 ret = RTAvlU32Insert(&pSurface->pSharedObjectTree, &pSharedSurface->Core);
1200 AssertReturn(ret, NULL);
1201
1202 /* Create shadow copy of the original shared texture. Shared d3d resources require Vista+ and have some restrictions. */
1203 hr = pContext->pDevice->CreateTexture(pSurface->pMipmapLevels[0].size.width,
1204 pSurface->pMipmapLevels[0].size.height,
1205 pSurface->faces[0].numMipLevels,
1206 pSurface->fUsageD3D | D3DUSAGE_RENDERTARGET /* required for use as a StretchRect destination */,
1207 pSurface->formatD3D,
1208 D3DPOOL_DEFAULT,
1209 &pSharedSurface->u.pTexture,
1210 &pSurface->hSharedObject);
1211 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSurfaceGetSharedCopy: CreateTexture failed with %x\n", hr), NULL);
1212 }
1213 return pSharedSurface;
1214}
1215
1216/* Inject a query event into the D3D pipeline so we can check when usage of this surface has finished.
1217 * (D3D does not synchronize shared surface usage)
1218 */
1219static int vmsvga3dSurfaceTrackUsage(PVMSVGA3DSTATE pState, PVMSVGA3DCONTEXT pContext, PVMSVGA3DSURFACE pSurface)
1220{
1221 RT_NOREF(pState);
1222#ifndef VBOX_VMSVGA3D_WITH_WINE_OPENGL
1223 Assert(pSurface->id != SVGA3D_INVALID_ID);
1224
1225 /* Nothing to do if this surface hasn't been shared. */
1226 if (pSurface->pSharedObjectTree == NULL)
1227 return VINF_SUCCESS;
1228
1229 Log(("vmsvga3dSurfaceTrackUsage: track usage of sid=%x (cid=%d) for cid=%d\n", pSurface->id, pSurface->idAssociatedContext, pContext->id));
1230
1231 /* Release the previous query object. */
1232 if (pSurface->pQuery)
1233 {
1234 Log(("vmsvga3dSurfaceTrackUsage: release old query object\n"));
1235 pSurface->pQuery->Release();
1236 pSurface->pQuery = NULL;
1237 }
1238 HRESULT hr = pContext->pDevice->CreateQuery(D3DQUERYTYPE_EVENT, &pSurface->pQuery);
1239 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSurfaceTrackUsage: CreateQuery failed with %x\n", hr), VERR_INTERNAL_ERROR);
1240
1241 hr = pSurface->pQuery->Issue(D3DISSUE_END);
1242 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSurfaceTrackUsage: Issue failed with %x\n", hr), VERR_INTERNAL_ERROR);
1243#endif /* !VBOX_VMSVGA3D_WITH_WINE_OPENGL */
1244
1245 return VINF_SUCCESS;
1246}
1247
1248
1249/**
1250 * Surface ID based version of vmsvga3dSurfaceTrackUsage.
1251 *
1252 * @returns VBox status code.
1253 * @param pState The VMSVGA3d state.
1254 * @param pContext The context.
1255 * @param sid The surface ID.
1256 */
1257static int vmsvga3dSurfaceTrackUsageById(PVMSVGA3DSTATE pState, PVMSVGA3DCONTEXT pContext, uint32_t sid)
1258{
1259 Assert(sid < SVGA3D_MAX_SURFACE_IDS);
1260 AssertReturn(sid < pState->cSurfaces, VERR_INVALID_PARAMETER);
1261 PVMSVGA3DSURFACE pSurface = pState->papSurfaces[sid];
1262 AssertReturn(pSurface && pSurface->id == sid, VERR_INVALID_PARAMETER);
1263
1264 return vmsvga3dSurfaceTrackUsage(pState, pContext, pSurface);
1265}
1266
1267
1268/* Wait for all drawing, that uses this surface, to finish. */
1269int vmsvga3dSurfaceFlush(PVGASTATE pThis, PVMSVGA3DSURFACE pSurface)
1270{
1271 RT_NOREF(pThis);
1272#ifndef VBOX_VMSVGA3D_WITH_WINE_OPENGL
1273 HRESULT hr;
1274
1275 if (!pSurface->pQuery)
1276 {
1277 LogFlow(("vmsvga3dSurfaceFlush: no query object\n"));
1278 return VINF_SUCCESS; /* nothing to wait for */
1279 }
1280 Assert(pSurface->pSharedObjectTree);
1281
1282 Log(("vmsvga3dSurfaceFlush: wait for draw to finish (sid=%x)\n", pSurface->id));
1283 while (true)
1284 {
1285 hr = pSurface->pQuery->GetData(NULL, 0, D3DGETDATA_FLUSH);
1286 if (hr != S_FALSE) break;
1287
1288 RTThreadSleep(1);
1289 }
1290 AssertMsgReturn(hr == S_OK, ("vmsvga3dSurfaceFinishDrawing: GetData failed with %x\n", hr), VERR_INTERNAL_ERROR);
1291
1292 pSurface->pQuery->Release();
1293 pSurface->pQuery = NULL;
1294#endif /* !VBOX_VMSVGA3D_WITH_WINE_OPENGL */
1295
1296 return VINF_SUCCESS;
1297}
1298
1299int vmsvga3dSurfaceCopy(PVGASTATE pThis, SVGA3dSurfaceImageId dest, SVGA3dSurfaceImageId src,
1300 uint32_t cCopyBoxes, SVGA3dCopyBox *pBox)
1301{
1302 PVMSVGA3DSTATE pState = pThis->svga.p3dState;
1303 PVMSVGA3DSURFACE pSurfaceSrc;
1304 uint32_t sidSrc = src.sid;
1305 PVMSVGA3DSURFACE pSurfaceDest;
1306 uint32_t sidDest = dest.sid;
1307 int rc = VINF_SUCCESS;
1308
1309 AssertReturn(pState, VERR_NO_MEMORY);
1310 AssertReturn(sidSrc < SVGA3D_MAX_SURFACE_IDS, VERR_INVALID_PARAMETER);
1311 AssertReturn(sidSrc < pState->cSurfaces && pState->papSurfaces[sidSrc]->id == sidSrc, VERR_INVALID_PARAMETER);
1312 AssertReturn(sidDest < SVGA3D_MAX_SURFACE_IDS, VERR_INVALID_PARAMETER);
1313 AssertReturn(sidDest < pState->cSurfaces && pState->papSurfaces[sidDest]->id == sidDest, VERR_INVALID_PARAMETER);
1314
1315 pSurfaceSrc = pState->papSurfaces[sidSrc];
1316 pSurfaceDest = pState->papSurfaces[sidDest];
1317
1318 AssertReturn(pSurfaceSrc->faces[0].numMipLevels > src.mipmap, VERR_INVALID_PARAMETER);
1319 AssertReturn(pSurfaceDest->faces[0].numMipLevels > dest.mipmap, VERR_INVALID_PARAMETER);
1320
1321 // AssertMsgReturn(pSurfaceSrc->format == pSurfaceDest->format, ("Format mismatch (%d vs %d)!!\n", pSurfaceSrc->format, pSurfaceDest->format), VERR_INVALID_PARAMETER);
1322
1323 bool fSrcTexture = !!(pSurfaceSrc->flags & SVGA3D_SURFACE_HINT_TEXTURE);
1324 bool fDestTexture = !!(pSurfaceDest->flags & SVGA3D_SURFACE_HINT_TEXTURE);
1325
1326 if ( fDestTexture
1327 && !pSurfaceDest->u.pSurface
1328 && pSurfaceSrc->u.pSurface)
1329 {
1330 uint32_t cid;
1331 PVMSVGA3DCONTEXT pContext;
1332
1333 /** @todo stricter checks for associated context */
1334 cid = pSurfaceSrc->idAssociatedContext;
1335 if ( cid >= pState->cContexts
1336 || pState->papContexts[cid]->id != cid)
1337 {
1338 Log(("vmsvga3dSurfaceCopy invalid context id!\n"));
1339 return VERR_INVALID_PARAMETER;
1340 }
1341 pContext = pState->papContexts[cid];
1342
1343 Log(("vmsvga3dSurfaceCopy: create texture sid=%x type=%d format=%d -> create texture\n", sidDest, pSurfaceDest->flags, pSurfaceDest->format));
1344 rc = vmsvga3dBackCreateTexture(pState, pContext, cid, pSurfaceDest);
1345 AssertRCReturn(rc, rc);
1346 }
1347
1348 if ( pSurfaceSrc->u.pSurface
1349 && pSurfaceDest->u.pSurface)
1350 {
1351 uint32_t cid;
1352 PVMSVGA3DCONTEXT pContext;
1353 IDirect3DTexture9 *pSrcTexture = pSurfaceSrc->u.pTexture;
1354
1355 /** @todo stricter checks for associated context */
1356 cid = pSurfaceDest->idAssociatedContext;
1357 if ( cid >= pState->cContexts
1358 || pState->papContexts[cid]->id != cid)
1359 {
1360 Log(("vmsvga3dSurfaceCopy invalid context id!\n"));
1361 return VERR_INVALID_PARAMETER;
1362 }
1363 pContext = pState->papContexts[cid];
1364
1365 /* Must flush the other context's 3d pipeline to make sure all drawing is complete for the surface we're about to use. */
1366 vmsvga3dSurfaceFlush(pThis, pSurfaceSrc);
1367 vmsvga3dSurfaceFlush(pThis, pSurfaceDest);
1368
1369#ifndef VBOX_VMSVGA3D_WITH_WINE_OPENGL
1370 if ( fSrcTexture
1371 && pSurfaceSrc->idAssociatedContext != cid)
1372 {
1373 Log(("vmsvga3dSurfaceCopy; using texture sid=%x created for another context (%d vs %d)\n", sidSrc, pSurfaceSrc->idAssociatedContext, cid));
1374
1375 PVMSVGA3DSHAREDSURFACE pSharedSurface = vmsvga3dSurfaceGetSharedCopy(pThis, pContext, pSurfaceSrc);
1376 AssertReturn(pSharedSurface, VERR_INTERNAL_ERROR);
1377
1378 pSrcTexture = pSharedSurface->u.pTexture;
1379 }
1380#endif
1381
1382 for (uint32_t i = 0; i < cCopyBoxes; i++)
1383 {
1384 HRESULT hr;
1385 RECT RectSrc;
1386 RECT RectDest;
1387 IDirect3DSurface9 *pSrc;
1388 IDirect3DSurface9 *pDest;
1389
1390 RectSrc.left = pBox[i].srcx;
1391 RectSrc.top = pBox[i].srcy;
1392 RectSrc.right = pBox[i].srcx + pBox[i].w; /* exclusive */
1393 RectSrc.bottom = pBox[i].srcy + pBox[i].h; /* exclusive */
1394 RectDest.left = pBox[i].x;
1395 RectDest.top = pBox[i].y;
1396 RectDest.right = pBox[i].x + pBox[i].w; /* exclusive */
1397 RectDest.bottom = pBox[i].y + pBox[i].h; /* exclusive */
1398
1399 Log(("vmsvga3dSurfaceCopy: (StretchRect) copy src sid=%x face=%d mipmap=%d (%d,%d)(%d,%d) to dest sid=%x face=%d mipmap=%d (%d,%d)\n", sidSrc, src.face, src.mipmap, RectSrc.left, RectSrc.top, RectSrc.right, RectSrc.bottom, sidDest, dest.face, dest.mipmap, pBox[i].x, pBox[i].y));
1400
1401 if ( sidSrc == sidDest
1402 && pBox[i].srcx == pBox[i].x
1403 && pBox[i].srcy == pBox[i].y)
1404 {
1405 Log(("vmsvga3dSurfaceCopy: redundant copy to the same surface at the same coordinates. Ignore. \n"));
1406 continue;
1407 }
1408 Assert(sidSrc != sidDest);
1409 Assert(!pBox[i].srcz && !pBox[i].z);
1410
1411 if (fSrcTexture)
1412 {
1413 hr = pSrcTexture->GetSurfaceLevel(src.mipmap /* Texture level */,
1414 &pSrc);
1415 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSurfaceCopy: GetSurfaceLevel failed with %x\n", hr), VERR_INTERNAL_ERROR);
1416 }
1417 else
1418 pSrc = pSurfaceSrc->u.pSurface;
1419
1420 if (fDestTexture)
1421 {
1422 hr = pSurfaceDest->u.pTexture->GetSurfaceLevel(dest.mipmap /* Texture level */,
1423 &pDest);
1424 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSurfaceCopy: GetSurfaceLevel failed with %x\n", hr), VERR_INTERNAL_ERROR);
1425 }
1426 else
1427 pDest = pSurfaceDest->u.pSurface;
1428
1429 /* UpdateSurface is too picky; use StretchRect instead */
1430 hr = pContext->pDevice->StretchRect(pSrc, &RectSrc, pDest, &RectDest, D3DTEXF_NONE);
1431
1432 /* GetSurfaceLevel increases the reference count; release the objects again. */
1433 if (fDestTexture)
1434 pDest->Release();
1435 if (fSrcTexture)
1436 pSrc->Release();
1437
1438 /* Track the StretchRect operation. */
1439 vmsvga3dSurfaceTrackUsage(pState, pContext, pSurfaceSrc);
1440 vmsvga3dSurfaceTrackUsage(pState, pContext, pSurfaceDest);
1441
1442 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSurfaceCopy: UpdateSurface failed with %x\n", hr), VERR_INTERNAL_ERROR);
1443 }
1444 }
1445 else
1446 for (uint32_t i = 0; i < cCopyBoxes; i++)
1447 {
1448 HRESULT hr = D3D_OK;
1449 D3DLOCKED_RECT LockedSrcRect;
1450 D3DLOCKED_RECT LockedDestRect;
1451 RECT Rect;
1452
1453 Rect.left = pBox[i].srcx;
1454 Rect.top = pBox[i].srcy;
1455 Rect.right = pBox[i].srcx + pBox[i].w; /* exclusive */
1456 Rect.bottom = pBox[i].srcy + pBox[i].h; /* exclusive */
1457
1458 Log(("vmsvga3dSurfaceCopy: (manual) copy sid=%x face=%d mipmap=%d (%d,%d)(%d,%d) to sid=%x face=%d mipmap=%d (%d,%d)\n", sidSrc, src.face, src.mipmap, Rect.left, Rect.top, Rect.right, Rect.bottom, sidDest, dest.face, dest.mipmap, pBox[i].x, pBox[i].y));
1459
1460 Assert(!pBox[i].srcz && !pBox[i].z);
1461
1462 if (!pSurfaceSrc->u.pSurface)
1463 {
1464 LockedSrcRect.pBits = (void *)pSurfaceSrc->pMipmapLevels[src.mipmap].pSurfaceData;
1465 LockedSrcRect.Pitch = pSurfaceSrc->pMipmapLevels[src.mipmap].cbSurfacePitch;
1466 }
1467 else
1468 {
1469 /* Must flush the other context's 3d pipeline to make sure all drawing is complete for the surface we're about to use. */
1470 vmsvga3dSurfaceFlush(pThis, pSurfaceSrc);
1471
1472 if (fSrcTexture)
1473 {
1474 Assert(!pSurfaceSrc->bounce.pTexture);
1475 hr = pSurfaceSrc->u.pTexture->LockRect(src.mipmap, /* Texture level */
1476 &LockedSrcRect,
1477 &Rect,
1478 D3DLOCK_READONLY);
1479 }
1480 else
1481 hr = pSurfaceSrc->u.pSurface->LockRect(&LockedSrcRect,
1482 &Rect,
1483 D3DLOCK_READONLY);
1484 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSurfaceCopy: LockRect failed with %x\n", hr), VERR_INTERNAL_ERROR);
1485 }
1486
1487 if (!pSurfaceDest->u.pSurface)
1488 {
1489 LockedDestRect.pBits = (void *)pSurfaceDest->pMipmapLevels[dest.mipmap].pSurfaceData;
1490 LockedDestRect.Pitch = pSurfaceDest->pMipmapLevels[dest.mipmap].cbSurfacePitch;
1491 }
1492 else
1493 {
1494 /* Must flush the other context's 3d pipeline to make sure all drawing is complete for the surface we're about to use. */
1495 vmsvga3dSurfaceFlush(pThis, pSurfaceDest);
1496
1497 if (fDestTexture)
1498 {
1499 if (pSurfaceDest->bounce.pTexture)
1500 {
1501 /* pSurfaceDest->u.pTexture can't be locked, see vmsvga3dBackCreateTexture */
1502 hr = pSurfaceDest->bounce.pTexture->LockRect(dest.mipmap, /* texture level */
1503 &LockedDestRect,
1504 &Rect,
1505 0);
1506 }
1507 else
1508 {
1509 hr = pSurfaceDest->u.pTexture->LockRect(dest.mipmap, /* texture level */
1510 &LockedDestRect,
1511 &Rect,
1512 0);
1513 }
1514 }
1515 else
1516 hr = pSurfaceDest->u.pSurface->LockRect(&LockedDestRect,
1517 &Rect,
1518 0);
1519 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSurfaceCopy: LockRect failed with %x\n", hr), VERR_INTERNAL_ERROR);
1520 }
1521
1522 uint8_t *pDest = (uint8_t *)LockedDestRect.pBits + LockedDestRect.Pitch * pBox[i].y + pBox[i].x * pSurfaceDest->cbBlock;
1523 uint8_t *pSrc = (uint8_t *)LockedSrcRect.pBits + LockedSrcRect.Pitch * pBox[i].srcy + pBox[i].srcx * pSurfaceSrc->cbBlock;
1524
1525 for (int32_t j = Rect.top; j < Rect.bottom; j++)
1526 {
1527 memcpy(pDest, pSrc, pBox[i].w * pSurfaceSrc->cbBlock);
1528
1529 pDest += LockedDestRect.Pitch;
1530 pSrc += LockedSrcRect.Pitch;
1531 }
1532
1533 if (pSurfaceDest->u.pSurface)
1534 {
1535 if (fDestTexture)
1536 {
1537 if (pSurfaceDest->bounce.pTexture)
1538 {
1539 hr = pSurfaceDest->bounce.pTexture->UnlockRect(dest.mipmap /* Texture level */);
1540
1541 /** @todo stricter checks for associated context */
1542 PVMSVGA3DCONTEXT pContext = NULL;
1543 const uint32_t cid = pSurfaceDest->idAssociatedContext;
1544 if ( cid < pState->cContexts
1545 && pState->papContexts[cid]->id == cid)
1546 pContext = pState->papContexts[cid];
1547 else
1548 AssertFailed();
1549
1550 if (pContext)
1551 {
1552 /* Copy the new content to the actual texture object. */
1553 HRESULT hr2 = pContext->pDevice->UpdateTexture(pSurfaceDest->bounce.pTexture, pSurfaceDest->u.pTexture);
1554 AssertMsg(hr2 == D3D_OK, ("UpdateTexture failed with %x\n", hr2)); RT_NOREF(hr2);
1555 }
1556 }
1557 else
1558 hr = pSurfaceDest->u.pTexture->UnlockRect(dest.mipmap /* Texture level */);
1559 }
1560 else
1561 hr = pSurfaceDest->u.pSurface->UnlockRect();
1562 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSurfaceCopy: Unlock failed with %x\n", hr), VERR_INTERNAL_ERROR);
1563 }
1564
1565 if (pSurfaceSrc->u.pSurface)
1566 {
1567 if (fSrcTexture)
1568 hr = pSurfaceSrc->u.pTexture->UnlockRect(src.mipmap /* Texture level */);
1569 else
1570 hr = pSurfaceSrc->u.pSurface->UnlockRect();
1571 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSurfaceCopy: Unlock failed with %x\n", hr), VERR_INTERNAL_ERROR);
1572 }
1573 }
1574
1575 return VINF_SUCCESS;
1576}
1577
1578
1579/**
1580 * Create D3D/OpenGL texture object for the specified surface.
1581 *
1582 * Surfaces are created when needed.
1583 *
1584 * @param pState The VMSVGA3d state.
1585 * @param pContext The context.
1586 * @param idAssociatedContext Probably the same as pContext->id.
1587 * @param pSurface The surface to create the texture for.
1588 */
1589int vmsvga3dBackCreateTexture(PVMSVGA3DSTATE pState, PVMSVGA3DCONTEXT pContext, uint32_t idAssociatedContext,
1590 PVMSVGA3DSURFACE pSurface)
1591
1592{
1593 RT_NOREF(pState);
1594 HRESULT hr;
1595 IDirect3DTexture9 *pTexture;
1596
1597 Assert(pSurface->hSharedObject == NULL);
1598
1599 if ( pSurface->formatD3D == D3DFMT_D24S8
1600 || pSurface->formatD3D == D3DFMT_D24X8)
1601 {
1602 Assert(pSurface->faces[0].numMipLevels == 1);
1603 /* Use the INTZ format for a depth/stencil surface that will be used as a texture */
1604 hr = pContext->pDevice->CreateTexture(pSurface->pMipmapLevels[0].size.width,
1605 pSurface->pMipmapLevels[0].size.height,
1606 1,
1607 D3DUSAGE_DEPTHSTENCIL,
1608 FOURCC_INTZ,
1609 D3DPOOL_DEFAULT,
1610 &pSurface->u.pTexture,
1611 &pSurface->hSharedObject /* might result in poor performance */);
1612 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dBackCreateTexture: CreateTexture INTZ failed with %x\n", hr), VERR_INTERNAL_ERROR);
1613 pTexture = pSurface->u.pTexture;
1614
1615 pSurface->fStencilAsTexture = true;
1616 }
1617 else
1618 {
1619 hr = pContext->pDevice->CreateTexture(pSurface->pMipmapLevels[0].size.width,
1620 pSurface->pMipmapLevels[0].size.height,
1621 pSurface->faces[0].numMipLevels,
1622 pSurface->fUsageD3D | D3DUSAGE_RENDERTARGET /* required for use as a StretchRect destination */,
1623 pSurface->formatD3D,
1624 D3DPOOL_DEFAULT,
1625 &pSurface->u.pTexture,
1626 &pSurface->hSharedObject);
1627 if (hr == D3D_OK)
1628 {
1629 /* Create another texture object to serve as a bounce buffer as the above texture surface can't be locked. */
1630 hr = pContext->pDevice->CreateTexture(pSurface->pMipmapLevels[0].size.width,
1631 pSurface->pMipmapLevels[0].size.height,
1632 pSurface->faces[0].numMipLevels,
1633 (pSurface->fUsageD3D & ~D3DUSAGE_RENDERTARGET) | D3DUSAGE_DYNAMIC /* Lockable */,
1634 pSurface->formatD3D,
1635 D3DPOOL_SYSTEMMEM,
1636 &pSurface->bounce.pTexture,
1637 NULL);
1638 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dBackCreateTexture: CreateTexture (systemmem) failed with %x\n", hr), VERR_INTERNAL_ERROR);
1639 pTexture = pSurface->bounce.pTexture;
1640 }
1641 else
1642 {
1643 Log(("Format not accepted -> try old method\n"));
1644 /* The format was probably not accepted; fall back to our old mode. */
1645 hr = pContext->pDevice->CreateTexture(pSurface->pMipmapLevels[0].size.width,
1646 pSurface->pMipmapLevels[0].size.height,
1647 pSurface->faces[0].numMipLevels,
1648 (pSurface->fUsageD3D & ~D3DUSAGE_RENDERTARGET) | D3DUSAGE_DYNAMIC /* Lockable */,
1649 pSurface->formatD3D,
1650 D3DPOOL_DEFAULT,
1651 &pSurface->u.pTexture,
1652 &pSurface->hSharedObject /* might result in poor performance */);
1653 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dBackCreateTexture: CreateTexture failed with %x\n", hr), VERR_INTERNAL_ERROR);
1654 pTexture = pSurface->u.pTexture;
1655 }
1656 }
1657
1658 if (pSurface->autogenFilter != SVGA3D_TEX_FILTER_NONE)
1659 {
1660 /* Set the mip map generation filter settings. */
1661 hr = pSurface->u.pTexture->SetAutoGenFilterType((D3DTEXTUREFILTERTYPE)pSurface->autogenFilter);
1662 AssertMsg(hr == D3D_OK, ("vmsvga3dBackCreateTexture: SetAutoGenFilterType failed with %x\n", hr));
1663 }
1664
1665 /*
1666 * Always initialize all mipmap levels using the in memory data
1667 * to make sure that the just created texture has the up-to-date content.
1668 * The OpenGL backend does this too.
1669 */
1670 Log(("vmsvga3dBackCreateTexture: sync texture\n"));
1671 for (uint32_t i = 0; i < pSurface->faces[0].numMipLevels; i++)
1672 {
1673 D3DLOCKED_RECT LockedRect;
1674
1675 hr = pTexture->LockRect(i, /* texture level */
1676 &LockedRect,
1677 NULL, /* entire texture */
1678 0);
1679
1680 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dBackCreateTexture: LockRect failed with %x\n", hr), VERR_INTERNAL_ERROR);
1681
1682 Log(("vmsvga3dBackCreateTexture: sync texture mipmap level %d (pitch %x vs %x)\n", i, LockedRect.Pitch, pSurface->pMipmapLevels[i].cbSurfacePitch));
1683
1684 uint8_t *pDest = (uint8_t *)LockedRect.pBits;
1685 uint8_t *pSrc = (uint8_t *)pSurface->pMipmapLevels[i].pSurfaceData;
1686 for (uint32_t j = 0; j < pSurface->pMipmapLevels[i].size.height; j++)
1687 {
1688 memcpy(pDest, pSrc, pSurface->pMipmapLevels[i].cbSurfacePitch);
1689
1690 pDest += LockedRect.Pitch;
1691 pSrc += pSurface->pMipmapLevels[i].cbSurfacePitch;
1692 }
1693
1694 hr = pTexture->UnlockRect(i /* texture level */);
1695 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dBackCreateTexture: UnlockRect failed with %x\n", hr), VERR_INTERNAL_ERROR);
1696
1697 pSurface->pMipmapLevels[i].fDirty = false;
1698 }
1699
1700 if (pSurface->bounce.pTexture)
1701 {
1702 Log(("vmsvga3dBackCreateTexture: sync dirty texture from bounce buffer\n"));
1703
1704 hr = pContext->pDevice->UpdateTexture(pSurface->bounce.pTexture, pSurface->u.pTexture);
1705 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dBackCreateTexture: UpdateTexture failed with %x\n", hr), VERR_INTERNAL_ERROR);
1706
1707 /* We will now use the bounce texture for all memory accesses, so free our surface memory buffer. */
1708 for (uint32_t i = 0; i < pSurface->faces[0].numMipLevels; i++)
1709 {
1710 RTMemFree(pSurface->pMipmapLevels[i].pSurfaceData);
1711 pSurface->pMipmapLevels[i].pSurfaceData = NULL;
1712 }
1713 }
1714 pSurface->fDirty = false;
1715
1716 pSurface->flags |= SVGA3D_SURFACE_HINT_TEXTURE;
1717 pSurface->idAssociatedContext = idAssociatedContext;
1718 return VINF_SUCCESS;
1719}
1720
1721
1722/**
1723 * Backend worker for implementing SVGA_3D_CMD_SURFACE_STRETCHBLT.
1724 *
1725 * @returns VBox status code.
1726 * @param pThis The VGA device instance.
1727 * @param pState The VMSVGA3d state.
1728 * @param pDstSurface The destination host surface.
1729 * @param uDstMipmap The destination mipmap level (valid).
1730 * @param pDstBox The destination box.
1731 * @param pSrcSurface The source host surface.
1732 * @param uSrcMipmap The source mimap level (valid).
1733 * @param pSrcBox The source box.
1734 * @param enmMode The strecht blt mode .
1735 * @param pContext The VMSVGA3d context (already current for OGL).
1736 */
1737int vmsvga3dBackSurfaceStretchBlt(PVGASTATE pThis, PVMSVGA3DSTATE pState,
1738 PVMSVGA3DSURFACE pDstSurface, uint32_t uDstMipmap, SVGA3dBox const *pDstBox,
1739 PVMSVGA3DSURFACE pSrcSurface, uint32_t uSrcMipmap, SVGA3dBox const *pSrcBox,
1740 SVGA3dStretchBltMode enmMode, PVMSVGA3DCONTEXT pContext)
1741{
1742 HRESULT hr;
1743
1744 /* Flush the drawing pipeline for this surface as it could be used in a shared context. */
1745 vmsvga3dSurfaceFlush(pThis, pSrcSurface);
1746 vmsvga3dSurfaceFlush(pThis, pDstSurface);
1747
1748 RECT RectSrc;
1749 RectSrc.left = pSrcBox->x;
1750 RectSrc.top = pSrcBox->y;
1751 RectSrc.right = pSrcBox->x + pSrcBox->w; /* exclusive */
1752 RectSrc.bottom = pSrcBox->y + pSrcBox->h; /* exclusive */
1753 Assert(!pSrcBox->z);
1754
1755 RECT RectDst;
1756 RectDst.left = pDstBox->x;
1757 RectDst.top = pDstBox->y;
1758 RectDst.right = pDstBox->x + pDstBox->w; /* exclusive */
1759 RectDst.bottom = pDstBox->y + pDstBox->h; /* exclusive */
1760 Assert(!pDstBox->z);
1761
1762 IDirect3DSurface9 *pSrc;
1763 bool const fSrcTexture = !!(pSrcSurface->flags & SVGA3D_SURFACE_HINT_TEXTURE);
1764 if (fSrcTexture)
1765 {
1766 hr = pSrcSurface->u.pTexture->GetSurfaceLevel(uSrcMipmap /* Texture level */, &pSrc);
1767 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSurfaceStretchBlt: GetSurfaceLevel failed with %x\n", hr), VERR_INTERNAL_ERROR);
1768 }
1769 else
1770 pSrc = pSrcSurface->u.pSurface;
1771
1772 IDirect3DSurface9 *pDst;
1773 bool const fDstTexture = !!(pDstSurface->flags & SVGA3D_SURFACE_HINT_TEXTURE);
1774 if (fDstTexture)
1775 {
1776 hr = pDstSurface->u.pTexture->GetSurfaceLevel(uDstMipmap /* Texture level */, &pDst);
1777 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSurfaceStretchBlt: GetSurfaceLevel failed with %x\n", hr), VERR_INTERNAL_ERROR);
1778 }
1779 else
1780 pDst = pDstSurface->u.pSurface;
1781
1782 D3DTEXTUREFILTERTYPE moded3d;
1783 switch (enmMode)
1784 {
1785 case SVGA3D_STRETCH_BLT_POINT:
1786 moded3d = D3DTEXF_POINT;
1787 break;
1788
1789 case SVGA3D_STRETCH_BLT_LINEAR:
1790 moded3d = D3DTEXF_LINEAR;
1791 break;
1792
1793 default:
1794 AssertFailed();
1795 moded3d = D3DTEXF_NONE;
1796 break;
1797 }
1798
1799 hr = pContext->pDevice->StretchRect(pSrc, &RectSrc, pDst, &RectDst, moded3d);
1800
1801 /* GetSurfaceLevel increases the reference count; release the objects again. */
1802 if (fDstTexture)
1803 pDst->Release();
1804 if (fSrcTexture)
1805 pSrc->Release();
1806
1807 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSurfaceStretchBlt: StretchRect failed with %x\n", hr), VERR_INTERNAL_ERROR);
1808
1809 /* Track the StretchRect operation. */
1810 vmsvga3dSurfaceTrackUsage(pState, pContext, pSrcSurface);
1811 vmsvga3dSurfaceTrackUsage(pState, pContext, pDstSurface);
1812
1813 return VINF_SUCCESS;
1814}
1815
1816
1817/**
1818 * Backend worker for implementing SVGA_3D_CMD_SURFACE_DMA that copies one box.
1819 *
1820 * @returns Failure status code or @a rc.
1821 * @param pThis The VGA device instance data.
1822 * @param pState The VMSVGA3d state.
1823 * @param pSurface The host surface.
1824 * @param uHostMipmap The host mipmap level (valid).
1825 * @param GuestPtr The guest pointer.
1826 * @param cbSrcPitch The guest (?) pitch.
1827 * @param transfer The transfer direction.
1828 * @param pBox The box to copy.
1829 * @param pContext The context (for OpenGL).
1830 * @param rc The current rc for all boxes.
1831 * @param iBox The current box number (for Direct 3D).
1832 */
1833int vmsvga3dBackSurfaceDMACopyBox(PVGASTATE pThis, PVMSVGA3DSTATE pState, PVMSVGA3DSURFACE pSurface, uint32_t uHostMipmap,
1834 SVGAGuestPtr GuestPtr, uint32_t cbSrcPitch, SVGA3dTransferType transfer,
1835 SVGA3dCopyBox const *pBox, PVMSVGA3DCONTEXT pContext, int rc, int iBox)
1836{
1837 HRESULT hr = D3D_OK;
1838 DWORD dwFlags = transfer == SVGA3D_READ_HOST_VRAM ? D3DLOCK_READONLY : 0;
1839 bool fTexture = false;
1840 bool fVertex = false;
1841 bool fRenderTargetTexture = false;
1842 switch (pSurface->flags & VMSVGA3D_SURFACE_HINT_SWITCH_MASK)
1843 {
1844 case SVGA3D_SURFACE_HINT_TEXTURE | SVGA3D_SURFACE_HINT_RENDERTARGET:
1845 fRenderTargetTexture = true;
1846 /* no break */
1847 case SVGA3D_SURFACE_HINT_TEXTURE:
1848 fTexture = true;
1849 /* no break */
1850 case SVGA3D_SURFACE_HINT_DEPTHSTENCIL:
1851 if (pSurface->fStencilAsTexture)
1852 fTexture = true;
1853 /* no break */
1854 case SVGA3D_SURFACE_HINT_RENDERTARGET:
1855 {
1856 D3DLOCKED_RECT LockedRect;
1857 RECT Rect;
1858
1859 Rect.left = pBox->x;
1860 Rect.top = pBox->y;
1861 Rect.right = pBox->x + pBox->w; /* exclusive */
1862 Rect.bottom = pBox->y + pBox->h; /* exclusive */
1863
1864 /** @todo inefficient for VRAM buffers!! */
1865 if (fTexture)
1866 {
1867 if (pSurface->bounce.pTexture)
1868 {
1869 if ( transfer == SVGA3D_READ_HOST_VRAM
1870 && fRenderTargetTexture
1871 && iBox == 0 /* only the first time */)
1872 {
1873 IDirect3DSurface9 *pSrc, *pDest;
1874
1875 /** @todo stricter checks for associated context */
1876 uint32_t cid = pSurface->idAssociatedContext;
1877 if ( cid >= pState->cContexts
1878 || pState->papContexts[cid]->id != cid)
1879 {
1880 Log(("vmsvga3dSurfaceDMA invalid context id (%x - %x)!\n", cid, (cid >= pState->cContexts) ? -1 : pState->papContexts[cid]->id));
1881 AssertFailedReturn(VERR_INVALID_PARAMETER);
1882 }
1883 pContext = pState->papContexts[cid];
1884
1885 /** @todo only sync when something was actually rendered (since the last sync) */
1886 Log(("vmsvga3dSurfaceDMA: sync bounce buffer\n"));
1887 hr = pSurface->bounce.pTexture->GetSurfaceLevel(uHostMipmap, &pDest);
1888 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSurfaceDMA: GetSurfaceLevel failed with %x\n", hr), VERR_INTERNAL_ERROR);
1889
1890 hr = pSurface->u.pTexture->GetSurfaceLevel(uHostMipmap, &pSrc);
1891 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSurfaceDMA: GetSurfaceLevel failed with %x\n", hr), VERR_INTERNAL_ERROR);
1892
1893 hr = pContext->pDevice->GetRenderTargetData(pSrc, pDest);
1894 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSurfaceDMA: GetRenderTargetData failed with %x\n", hr), VERR_INTERNAL_ERROR);
1895
1896 pSrc->Release();
1897 pDest->Release();
1898 }
1899
1900 hr = pSurface->bounce.pTexture->LockRect(uHostMipmap, /* texture level */
1901 &LockedRect,
1902 &Rect,
1903 dwFlags);
1904 }
1905 else
1906 hr = pSurface->u.pTexture->LockRect(uHostMipmap, /* texture level */
1907 &LockedRect,
1908 &Rect,
1909 dwFlags);
1910 }
1911 else
1912 hr = pSurface->u.pSurface->LockRect(&LockedRect,
1913 &Rect,
1914 dwFlags);
1915 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSurfaceDMA: LockRect failed with %x\n", hr), VERR_INTERNAL_ERROR);
1916
1917 if (fTexture)
1918 Log(("Lock sid=%x TEXTURE (bounce=%d) memory for rectangle (%d,%d)(%d,%d)\n", pSurface->id, !!(pSurface->bounce.pTexture), Rect.left, Rect.top, Rect.right, Rect.bottom));
1919 else
1920 Log(("Lock sid=%x %s memory for rectangle (%d,%d)(%d,%d)\n", pSurface->id, (pSurface->flags & SVGA3D_SURFACE_HINT_DEPTHSTENCIL) ? "DEPTH-STENCIL" : "RENDERTARGET", Rect.left, Rect.top, Rect.right, Rect.bottom));
1921
1922 rc = vmsvgaGMRTransfer(pThis,
1923 transfer,
1924 (uint8_t *)LockedRect.pBits,
1925 LockedRect.Pitch,
1926 GuestPtr,
1927 pBox->srcx * pSurface->cbBlock + pBox->srcy * cbSrcPitch,
1928 cbSrcPitch,
1929 pBox->w * pSurface->cbBlock,
1930 pBox->h);
1931 AssertRC(rc);
1932
1933 Log4(("first line:\n%.*Rhxd\n", pBox->w * pSurface->cbBlock, LockedRect.pBits));
1934
1935 if (fTexture)
1936 {
1937 if (pSurface->bounce.pTexture)
1938 {
1939 hr = pSurface->bounce.pTexture->UnlockRect(uHostMipmap);
1940 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSurfaceDMA: UnlockRect failed with %x\n", hr), VERR_INTERNAL_ERROR);
1941
1942 if (transfer == SVGA3D_WRITE_HOST_VRAM)
1943 {
1944 /** @todo stricter checks for associated context */
1945 uint32_t cid = pSurface->idAssociatedContext;
1946 if ( cid >= pState->cContexts
1947 || pState->papContexts[cid]->id != cid)
1948 {
1949 Log(("vmsvga3dSurfaceDMA invalid context id!\n"));
1950 AssertFailedReturn(VERR_INVALID_PARAMETER);
1951 }
1952 pContext = pState->papContexts[cid];
1953
1954 Log(("vmsvga3dSurfaceDMA: sync texture from bounce buffer\n"));
1955
1956 /* Copy the new contents to the actual texture object. */
1957 hr = pContext->pDevice->UpdateTexture(pSurface->bounce.pTexture, pSurface->u.pTexture);
1958 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSurfaceDMA: UpdateTexture failed with %x\n", hr), VERR_INTERNAL_ERROR);
1959
1960 /* Track the copy operation. */
1961 vmsvga3dSurfaceTrackUsage(pState, pContext, pSurface);
1962 }
1963 }
1964 else
1965 hr = pSurface->u.pTexture->UnlockRect(uHostMipmap);
1966 }
1967 else
1968 hr = pSurface->u.pSurface->UnlockRect();
1969 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSurfaceDMA: UnlockRect failed with %x\n", hr), VERR_INTERNAL_ERROR);
1970 break;
1971 }
1972
1973 case SVGA3D_SURFACE_HINT_VERTEXBUFFER | SVGA3D_SURFACE_HINT_INDEXBUFFER:
1974 case SVGA3D_SURFACE_HINT_VERTEXBUFFER:
1975 fVertex = RT_BOOL(pSurface->fu32ActualUsageFlags & SVGA3D_SURFACE_HINT_VERTEXBUFFER);
1976 /* no break */
1977
1978 case SVGA3D_SURFACE_HINT_INDEXBUFFER:
1979 {
1980 uint8_t *pData;
1981 unsigned uDestOffset;
1982
1983 uDestOffset = pBox->x * pSurface->cbBlock + pBox->y * pSurface->pMipmapLevels[uHostMipmap].cbSurfacePitch;
1984 AssertReturn(uDestOffset + pBox->w * pSurface->cbBlock + (pBox->h - 1) * pSurface->pMipmapLevels[uHostMipmap].cbSurfacePitch <= pSurface->pMipmapLevels[uHostMipmap].cbSurface, VERR_INTERNAL_ERROR);
1985
1986 /** @todo lock only as much as we really need */
1987 if (fVertex)
1988 hr = pSurface->u.pVertexBuffer->Lock(0, 0, (void **)&pData, dwFlags);
1989 else
1990 hr = pSurface->u.pIndexBuffer->Lock(0, 0, (void **)&pData, dwFlags);
1991 AssertMsg(hr == D3D_OK, ("vmsvga3dSurfaceDMA: Lock %s failed with %x\n", (fVertex) ? "vertex" : "index", hr));
1992
1993 Log(("Lock %s memory for rectangle (%d,%d)(%d,%d)\n", (fVertex) ? "vertex" : "index", pBox->x, pBox->y, pBox->x + pBox->w, pBox->y + pBox->h));
1994
1995 rc = vmsvgaGMRTransfer(pThis,
1996 transfer,
1997 pData + uDestOffset,
1998 pSurface->pMipmapLevels[uHostMipmap].cbSurfacePitch,
1999 GuestPtr,
2000 pBox->srcx * pSurface->cbBlock + pBox->srcy * cbSrcPitch,
2001 cbSrcPitch,
2002 pBox->w * pSurface->cbBlock,
2003 pBox->h);
2004 AssertRC(rc);
2005
2006 Log4(("first line:\n%.*Rhxd\n", cbSrcPitch, pData));
2007
2008 if (fVertex)
2009 hr = pSurface->u.pVertexBuffer->Unlock();
2010 else
2011 hr = pSurface->u.pIndexBuffer->Unlock();
2012 AssertMsg(hr == D3D_OK, ("vmsvga3dSurfaceDMA: Unlock %s failed with %x\n", (fVertex) ? "vertex" : "index", hr));
2013 break;
2014 }
2015
2016 default:
2017 AssertMsgFailed(("Unsupported surface hint 0x%08X\n", pSurface->flags & VMSVGA3D_SURFACE_HINT_SWITCH_MASK));
2018 break;
2019 }
2020
2021 return rc;
2022}
2023
2024
2025int vmsvga3dSurfaceBlitToScreen(PVGASTATE pThis, uint32_t dest, SVGASignedRect destRect, SVGA3dSurfaceImageId src, SVGASignedRect srcRect, uint32_t cRects, SVGASignedRect *pRect)
2026{
2027 /* Requires SVGA_FIFO_CAP_SCREEN_OBJECT support */
2028 Log(("vmsvga3dSurfaceBlitToScreen: dest=%d (%d,%d)(%d,%d) sid=%x (face=%d, mipmap=%d) (%d,%d)(%d,%d) cRects=%d\n", dest, destRect.left, destRect.top, destRect.right, destRect.bottom, src.sid, src.face, src.mipmap, srcRect.left, srcRect.top, srcRect.right, srcRect.bottom, cRects));
2029 for (uint32_t i = 0; i < cRects; i++)
2030 {
2031 Log(("vmsvga3dSurfaceBlitToScreen: clipping rect %d (%d,%d)(%d,%d)\n", i, pRect[i].left, pRect[i].top, pRect[i].right, pRect[i].bottom));
2032 }
2033
2034 /** @todo Only screen 0 for now. */
2035 AssertReturn(dest == 0, VERR_INTERNAL_ERROR);
2036 AssertReturn(src.mipmap == 0 && src.face == 0, VERR_INVALID_PARAMETER);
2037 /** @todo scaling */
2038 AssertReturn(destRect.right - destRect.left == srcRect.right - srcRect.left && destRect.bottom - destRect.top == srcRect.bottom - srcRect.top, VERR_INVALID_PARAMETER);
2039
2040 if (cRects == 0)
2041 {
2042 /* easy case; no clipping */
2043 SVGA3dCopyBox box;
2044 SVGA3dGuestImage dest;
2045
2046 box.x = destRect.left;
2047 box.y = destRect.top;
2048 box.z = 0;
2049 box.w = destRect.right - destRect.left;
2050 box.h = destRect.bottom - destRect.top;
2051 box.d = 1;
2052 box.srcx = srcRect.left;
2053 box.srcy = srcRect.top;
2054 box.srcz = 0;
2055
2056 dest.ptr.gmrId = SVGA_GMR_FRAMEBUFFER;
2057 dest.ptr.offset = 0;
2058 dest.pitch = pThis->svga.cbScanline;
2059
2060 int rc = vmsvga3dSurfaceDMA(pThis, dest, src, SVGA3D_READ_HOST_VRAM, 1, &box);
2061 AssertRCReturn(rc, rc);
2062
2063 vgaR3UpdateDisplay(pThis, box.x, box.y, box.w, box.h);
2064 return VINF_SUCCESS;
2065 }
2066 else
2067 {
2068 SVGA3dGuestImage dest;
2069 SVGA3dCopyBox box;
2070
2071 box.srcz = 0;
2072 box.z = 0;
2073 box.d = 1;
2074
2075 dest.ptr.gmrId = SVGA_GMR_FRAMEBUFFER;
2076 dest.ptr.offset = 0;
2077 dest.pitch = pThis->svga.cbScanline;
2078
2079 /** @todo merge into one SurfaceDMA call */
2080 for (uint32_t i = 0; i < cRects; i++)
2081 {
2082 /* The clipping rectangle is relative to the top-left corner of srcRect & destRect. Adjust here. */
2083 box.srcx = srcRect.left + pRect[i].left;
2084 box.srcy = srcRect.top + pRect[i].top;
2085
2086 box.x = pRect[i].left + destRect.left;
2087 box.y = pRect[i].top + destRect.top;
2088 box.z = 0;
2089 box.w = pRect[i].right - pRect[i].left;
2090 box.h = pRect[i].bottom - pRect[i].top;
2091
2092 int rc = vmsvga3dSurfaceDMA(pThis, dest, src, SVGA3D_READ_HOST_VRAM, 1, &box);
2093 AssertRCReturn(rc, rc);
2094
2095 vgaR3UpdateDisplay(pThis, box.x, box.y, box.w, box.h);
2096 }
2097
2098#if 0
2099 {
2100 PVMSVGA3DSTATE pState = pThis->svga.p3dState;
2101 HRESULT hr;
2102 PVMSVGA3DSURFACE pSurface;
2103 PVMSVGA3DCONTEXT pContext;
2104 uint32_t sid = src.sid;
2105 AssertReturn(sid < SVGA3D_MAX_SURFACE_IDS, VERR_INVALID_PARAMETER);
2106 AssertReturn(sid < pState->cSurfaces && pState->papSurfaces[sid]->id == sid, VERR_INVALID_PARAMETER);
2107
2108 pSurface = pState->papSurfaces[sid];
2109 uint32_t cid;
2110
2111 /** @todo stricter checks for associated context */
2112 cid = pSurface->idAssociatedContext;
2113
2114 if ( cid >= pState->cContexts
2115 || pState->papContexts[cid]->id != cid)
2116 {
2117 Log(("vmsvga3dGenerateMipmaps invalid context id!\n"));
2118 return VERR_INVALID_PARAMETER;
2119 }
2120 pContext = pState->papContexts[cid];
2121
2122 if (pSurface->id == 0x5e)
2123 {
2124 IDirect3DSurface9 *pSrc;
2125
2126 hr = pSurface->u.pTexture->GetSurfaceLevel(0/* Texture level */,
2127 &pSrc);
2128 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSurfaceStretchBlt: GetSurfaceLevel failed with %x\n", hr), VERR_INTERNAL_ERROR);
2129
2130 pContext->pDevice->ColorFill(pSrc, NULL, (D3DCOLOR)0x11122255);
2131 pSrc->Release();
2132 }
2133 }
2134#endif
2135
2136 return VINF_SUCCESS;
2137 }
2138}
2139
2140int vmsvga3dGenerateMipmaps(PVGASTATE pThis, uint32_t sid, SVGA3dTextureFilter filter)
2141{
2142 PVMSVGA3DSTATE pState = pThis->svga.p3dState;
2143 PVMSVGA3DSURFACE pSurface;
2144 int rc = VINF_SUCCESS;
2145 HRESULT hr;
2146
2147 AssertReturn(pState, VERR_NO_MEMORY);
2148 AssertReturn(sid < SVGA3D_MAX_SURFACE_IDS, VERR_INVALID_PARAMETER);
2149 AssertReturn(sid < pState->cSurfaces && pState->papSurfaces[sid]->id == sid, VERR_INVALID_PARAMETER);
2150
2151 pSurface = pState->papSurfaces[sid];
2152 AssertReturn(pSurface->idAssociatedContext != SVGA3D_INVALID_ID, VERR_INTERNAL_ERROR);
2153
2154 Assert(filter != SVGA3D_TEX_FILTER_FLATCUBIC);
2155 Assert(filter != SVGA3D_TEX_FILTER_GAUSSIANCUBIC);
2156 pSurface->autogenFilter = filter;
2157
2158 Log(("vmsvga3dGenerateMipmaps: sid=%x filter=%d\n", sid, filter));
2159
2160 if (!pSurface->u.pSurface)
2161 {
2162 PVMSVGA3DCONTEXT pContext;
2163 uint32_t cid;
2164
2165 /** @todo stricter checks for associated context */
2166 cid = pSurface->idAssociatedContext;
2167
2168 if ( cid >= pState->cContexts
2169 || pState->papContexts[cid]->id != cid)
2170 {
2171 Log(("vmsvga3dGenerateMipmaps invalid context id!\n"));
2172 return VERR_INVALID_PARAMETER;
2173 }
2174 pContext = pState->papContexts[cid];
2175
2176 /* Unknown surface type; turn it into a texture. */
2177 Log(("vmsvga3dGenerateMipmaps: unknown src surface sid=%x type=%d format=%d -> create texture\n", sid, pSurface->flags, pSurface->format));
2178 rc = vmsvga3dBackCreateTexture(pState, pContext, cid, pSurface);
2179 AssertRCReturn(rc, rc);
2180 }
2181 else
2182 {
2183 hr = pSurface->u.pTexture->SetAutoGenFilterType((D3DTEXTUREFILTERTYPE)filter);
2184 AssertMsg(hr == D3D_OK, ("vmsvga3dGenerateMipmaps: SetAutoGenFilterType failed with %x\n", hr));
2185 }
2186
2187 /* Generate the mip maps. */
2188 pSurface->u.pTexture->GenerateMipSubLevels();
2189
2190 return VINF_SUCCESS;
2191}
2192
2193int vmsvga3dCommandPresent(PVGASTATE pThis, uint32_t sid, uint32_t cRects, SVGA3dCopyRect *pRect)
2194{
2195 PVMSVGA3DSTATE pState = pThis->svga.p3dState;
2196 PVMSVGA3DSURFACE pSurface;
2197 PVMSVGA3DCONTEXT pContext;
2198 uint32_t cid;
2199 HRESULT hr;
2200 IDirect3DSurface9 *pBackBuffer;
2201 IDirect3DSurface9 *pSurfaceD3D;
2202
2203 AssertReturn(pState, VERR_NO_MEMORY);
2204 AssertReturn(sid < SVGA3D_MAX_SURFACE_IDS, VERR_INVALID_PARAMETER);
2205 AssertReturn(sid < pState->cSurfaces && pState->papSurfaces[sid]->id == sid, VERR_INVALID_PARAMETER);
2206
2207 pSurface = pState->papSurfaces[sid];
2208 AssertReturn(pSurface->idAssociatedContext != SVGA3D_INVALID_ID, VERR_INTERNAL_ERROR);
2209
2210 /** @todo stricter checks for associated context */
2211 cid = pSurface->idAssociatedContext;
2212 Log(("vmsvga3dCommandPresent: sid=%x cRects=%d cid=%x\n", sid, cRects, cid));
2213 for (uint32_t i=0; i < cRects; i++)
2214 {
2215 Log(("vmsvga3dCommandPresent: rectangle %d src=(%d,%d) (%d,%d)(%d,%d)\n", i, pRect[i].srcx, pRect[i].srcy, pRect[i].x, pRect[i].y, pRect[i].x + pRect[i].w, pRect[i].y + pRect[i].h));
2216 }
2217
2218 if ( cid >= pState->cContexts
2219 || pState->papContexts[cid]->id != cid)
2220 {
2221 Log(("vmsvga3dCommandPresent invalid context id!\n"));
2222 return VERR_INVALID_PARAMETER;
2223 }
2224 pContext = pState->papContexts[cid];
2225
2226 hr = pContext->pDevice->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer);
2227 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dCommandPresent: GetBackBuffer failed with %x\n", hr), VERR_INTERNAL_ERROR);
2228
2229 if (pSurface->flags & SVGA3D_SURFACE_HINT_TEXTURE)
2230 {
2231 hr = pSurface->u.pTexture->GetSurfaceLevel(0, &pSurfaceD3D);
2232 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dCommandPresent: GetSurfaceLevel failed with %x\n", hr), VERR_INTERNAL_ERROR);
2233 }
2234 else
2235 pSurfaceD3D = pSurface->u.pSurface;
2236
2237 /* Read the destination viewport specs in one go to try avoid some unnecessary update races. */
2238 VMSVGAVIEWPORT const DstViewport = pThis->svga.viewport;
2239 ASMCompilerBarrier(); /* paranoia */
2240 Assert(DstViewport.yHighWC >= DstViewport.yLowWC);
2241
2242 /* If there are no recangles specified, just grab a screenful. */
2243 SVGA3dCopyRect DummyRect;
2244 if (cRects != 0)
2245 { /* likely */ }
2246 else
2247 {
2248 /** @todo Find the usecase for this or check what the original device does.
2249 * The original code was doing some scaling based on the surface
2250 * size... */
2251# ifdef DEBUG_bird
2252 AssertMsgFailed(("No rects to present. Who is doing that and what do they actually expect?\n"));
2253# endif
2254 DummyRect.x = DummyRect.srcx = 0;
2255 DummyRect.y = DummyRect.srcy = 0;
2256 DummyRect.w = pThis->svga.uWidth;
2257 DummyRect.h = pThis->svga.uHeight;
2258 cRects = 1;
2259 pRect = &DummyRect;
2260 }
2261
2262 /*
2263 * Blit the surface rectangle(s) to the back buffer.
2264 */
2265 uint32_t const cxSurface = pSurface->pMipmapLevels[0].size.width;
2266 uint32_t const cySurface = pSurface->pMipmapLevels[0].size.height;
2267 for (uint32_t i = 0; i < cRects; i++)
2268 {
2269 SVGA3dCopyRect ClippedRect = pRect[i];
2270
2271 /*
2272 * Do some sanity checking and limit width and height, all so we
2273 * don't need to think about wrap-arounds below.
2274 */
2275 if (RT_LIKELY( ClippedRect.w
2276 && ClippedRect.x < VMSVGA_MAX_X
2277 && ClippedRect.srcx < VMSVGA_MAX_X
2278 && ClippedRect.h
2279 && ClippedRect.y < VMSVGA_MAX_Y
2280 && ClippedRect.srcy < VMSVGA_MAX_Y
2281 ))
2282 { /* likely */ }
2283 else
2284 continue;
2285
2286 if (RT_LIKELY(ClippedRect.w < VMSVGA_MAX_Y))
2287 { /* likely */ }
2288 else
2289 ClippedRect.w = VMSVGA_MAX_Y;
2290 if (RT_LIKELY(ClippedRect.w < VMSVGA_MAX_Y))
2291 { /* likely */ }
2292 else
2293 ClippedRect.w = VMSVGA_MAX_Y;
2294
2295 /*
2296 * Source surface clipping (paranoia). Straight forward.
2297 */
2298 if (RT_LIKELY(ClippedRect.srcx < cxSurface))
2299 { /* likely */ }
2300 else
2301 continue;
2302 if (RT_LIKELY(ClippedRect.srcx + ClippedRect.w <= cxSurface))
2303 { /* likely */ }
2304 else
2305 {
2306 AssertFailed(); /* remove if annoying. */
2307 ClippedRect.w = cxSurface - ClippedRect.srcx;
2308 }
2309
2310 if (RT_LIKELY(ClippedRect.srcy < cySurface))
2311 { /* likely */ }
2312 else
2313 continue;
2314 if (RT_LIKELY(ClippedRect.srcy + ClippedRect.h <= cySurface))
2315 { /* likely */ }
2316 else
2317 {
2318 AssertFailed(); /* remove if annoying. */
2319 ClippedRect.h = cySurface - ClippedRect.srcy;
2320 }
2321
2322 /*
2323 * Destination viewport clipping.
2324 *
2325 * This is very straight forward compared to OpenGL. There is no Y
2326 * inversion anywhere and all the coordinate systems are the same.
2327 */
2328 /* X */
2329 if (ClippedRect.x >= DstViewport.x)
2330 {
2331 if (ClippedRect.x + ClippedRect.w <= DstViewport.xRight)
2332 { /* typical */ }
2333 else if (ClippedRect.x < DstViewport.xRight)
2334 ClippedRect.w = DstViewport.xRight - ClippedRect.x;
2335 else
2336 continue;
2337 }
2338 else
2339 {
2340 uint32_t cxAdjust = DstViewport.x - ClippedRect.x;
2341 if (cxAdjust < ClippedRect.w)
2342 {
2343 ClippedRect.w -= cxAdjust;
2344 ClippedRect.x += cxAdjust;
2345 ClippedRect.srcx += cxAdjust;
2346 }
2347 else
2348 continue;
2349
2350 if (ClippedRect.x + ClippedRect.w <= DstViewport.xRight)
2351 { /* typical */ }
2352 else
2353 ClippedRect.w = DstViewport.xRight - ClippedRect.x;
2354 }
2355
2356 /* Y */
2357 if (ClippedRect.y >= DstViewport.y)
2358 {
2359 if (ClippedRect.y + ClippedRect.h <= DstViewport.y + DstViewport.cy)
2360 { /* typical */ }
2361 else if (ClippedRect.x < DstViewport.y + DstViewport.cy)
2362 ClippedRect.h = DstViewport.y + DstViewport.cy - ClippedRect.y;
2363 else
2364 continue;
2365 }
2366 else
2367 {
2368 uint32_t cyAdjust = DstViewport.y - ClippedRect.y;
2369 if (cyAdjust < ClippedRect.h)
2370 {
2371 ClippedRect.h -= cyAdjust;
2372 ClippedRect.y += cyAdjust;
2373 ClippedRect.srcy += cyAdjust;
2374 }
2375 else
2376 continue;
2377
2378 if (ClippedRect.y + ClippedRect.h <= DstViewport.y + DstViewport.cy)
2379 { /* typical */ }
2380 else
2381 ClippedRect.h = DstViewport.y + DstViewport.cy - ClippedRect.y;
2382 }
2383
2384 /* Calc source rectangle. */
2385 RECT SrcRect;
2386 SrcRect.left = ClippedRect.srcx;
2387 SrcRect.right = ClippedRect.srcx + ClippedRect.w;
2388 SrcRect.top = ClippedRect.srcy;
2389 SrcRect.bottom = ClippedRect.srcy + ClippedRect.h;
2390
2391 /* Calc destination rectangle. */
2392 RECT DstRect;
2393 DstRect.left = ClippedRect.x;
2394 DstRect.right = ClippedRect.x + ClippedRect.w;
2395 DstRect.top = ClippedRect.y;
2396 DstRect.bottom = ClippedRect.y + ClippedRect.h;
2397
2398 /* Adjust for viewport. */
2399 DstRect.left -= DstViewport.x;
2400 DstRect.right -= DstViewport.x;
2401 DstRect.bottom -= DstViewport.y;
2402 DstRect.top -= DstViewport.y;
2403
2404 Log(("SrcRect: (%d,%d)(%d,%d) DstRect: (%d,%d)(%d,%d)\n",
2405 SrcRect.left, SrcRect.bottom, SrcRect.right, SrcRect.top,
2406 DstRect.left, DstRect.bottom, DstRect.right, DstRect.top));
2407 hr = pContext->pDevice->StretchRect(pSurfaceD3D, &SrcRect, pBackBuffer, &DstRect, D3DTEXF_NONE);
2408 AssertBreak(hr == D3D_OK);
2409 }
2410
2411 if (pSurface->flags & SVGA3D_SURFACE_HINT_TEXTURE)
2412 pSurfaceD3D->Release();
2413
2414 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dCommandPresent: StretchRect failed with %x\n", hr), VERR_INTERNAL_ERROR);
2415
2416 hr = pContext->pDevice->Present(NULL, NULL, NULL, NULL);
2417 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dCommandPresent: Present failed with %x\n", hr), VERR_INTERNAL_ERROR);
2418
2419 pBackBuffer->Release();
2420 return VINF_SUCCESS;
2421}
2422
2423
2424/**
2425 * Create a new 3d context
2426 *
2427 * @returns VBox status code.
2428 * @param pThis VGA device instance data.
2429 * @param cid Context id
2430 */
2431int vmsvga3dContextDefine(PVGASTATE pThis, uint32_t cid)
2432{
2433 int rc;
2434 PVMSVGA3DCONTEXT pContext;
2435 HRESULT hr;
2436 D3DPRESENT_PARAMETERS PresParam;
2437 PVMSVGA3DSTATE pState = pThis->svga.p3dState;
2438
2439 AssertReturn(pState, VERR_NO_MEMORY);
2440 AssertReturn(cid < SVGA3D_MAX_CONTEXT_IDS, VERR_INVALID_PARAMETER);
2441
2442 Log(("vmsvga3dContextDefine id %x\n", cid));
2443
2444 if (cid >= pState->cContexts)
2445 {
2446 /* Grow the array. */
2447 uint32_t cNew = RT_ALIGN(cid + 15, 16);
2448 void *pvNew = RTMemRealloc(pState->papContexts, sizeof(pState->papContexts[0]) * cNew);
2449 AssertReturn(pvNew, VERR_NO_MEMORY);
2450 pState->papContexts = (PVMSVGA3DCONTEXT *)pvNew;
2451 while (pState->cContexts < cNew)
2452 {
2453 pContext = (PVMSVGA3DCONTEXT)RTMemAllocZ(sizeof(*pContext));
2454 AssertReturn(pContext, VERR_NO_MEMORY);
2455 pContext->id = SVGA3D_INVALID_ID;
2456 pState->papContexts[pState->cContexts++] = pContext;
2457 }
2458 }
2459 /* If one already exists with this id, then destroy it now. */
2460 if (pState->papContexts[cid]->id != SVGA3D_INVALID_ID)
2461 vmsvga3dContextDestroy(pThis, cid);
2462
2463 pContext = pState->papContexts[cid];
2464 memset(pContext, 0, sizeof(*pContext));
2465 pContext->id = cid;
2466 for (uint32_t i = 0; i< RT_ELEMENTS(pContext->aSidActiveTexture); i++)
2467 pContext->aSidActiveTexture[i] = SVGA3D_INVALID_ID;
2468 pContext->sidRenderTarget = SVGA3D_INVALID_ID;
2469 pContext->state.shidVertex = SVGA3D_INVALID_ID;
2470 pContext->state.shidPixel = SVGA3D_INVALID_ID;
2471
2472 for (uint32_t i = 0; i < RT_ELEMENTS(pContext->state.aRenderTargets); i++)
2473 pContext->state.aRenderTargets[i] = SVGA3D_INVALID_ID;
2474
2475 /* Create a context window. */
2476 CREATESTRUCT cs;
2477
2478 AssertReturn(pThis->svga.u64HostWindowId, VERR_INTERNAL_ERROR);
2479
2480 cs.lpCreateParams = NULL;
2481 cs.dwExStyle = WS_EX_NOACTIVATE | WS_EX_NOPARENTNOTIFY | WS_EX_TRANSPARENT;
2482#ifdef DEBUG_GFX_WINDOW
2483 cs.lpszName = (char *)RTMemAllocZ(256);
2484 RTStrPrintf((char *)cs.lpszName, 256, "Context %d OpenGL Window", cid);
2485#else
2486 cs.lpszName = NULL;
2487#endif
2488 cs.lpszClass = NULL;
2489#ifdef DEBUG_GFX_WINDOW
2490 cs.style = WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_VISIBLE | WS_CAPTION;
2491#else
2492 cs.style = WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_DISABLED | WS_CHILD | WS_VISIBLE;
2493#endif
2494 cs.x = 0;
2495 cs.y = 0;
2496 cs.cx = pThis->svga.uWidth;
2497 cs.cy = pThis->svga.uHeight;
2498 cs.hwndParent = (HWND)pThis->svga.u64HostWindowId;
2499 cs.hMenu = NULL;
2500 cs.hInstance = pState->hInstance;
2501
2502 rc = vmsvga3dSendThreadMessage(pState->pWindowThread, pState->WndRequestSem, WM_VMSVGA3D_CREATEWINDOW, (WPARAM)&pContext->hwnd, (LPARAM)&cs);
2503 AssertRCReturn(rc, rc);
2504
2505 /* Changed when the function returns. */
2506 PresParam.BackBufferWidth = 0;
2507 PresParam.BackBufferHeight = 0;
2508 PresParam.BackBufferFormat = D3DFMT_UNKNOWN;
2509 PresParam.BackBufferCount = 0;
2510
2511 PresParam.MultiSampleType = D3DMULTISAMPLE_NONE;
2512 PresParam.MultiSampleQuality = 0;
2513 PresParam.SwapEffect = D3DSWAPEFFECT_FLIP;
2514 PresParam.hDeviceWindow = pContext->hwnd;
2515 PresParam.Windowed = TRUE; /** @todo */
2516 PresParam.EnableAutoDepthStencil = FALSE;
2517 PresParam.AutoDepthStencilFormat = D3DFMT_UNKNOWN; /* not relevant */
2518 PresParam.Flags = 0;
2519 PresParam.FullScreen_RefreshRateInHz = 0; /* windowed -> 0 */
2520 /** @todo consider using D3DPRESENT_DONOTWAIT so we don't wait for the GPU during Present calls. */
2521 PresParam.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
2522
2523#ifdef VBOX_VMSVGA3D_WITH_WINE_OPENGL
2524 hr = pState->pD3D9->CreateDevice(D3DADAPTER_DEFAULT,
2525 D3DDEVTYPE_HAL,
2526 pContext->hwnd,
2527 D3DCREATE_MULTITHREADED | D3DCREATE_MIXED_VERTEXPROCESSING, //D3DCREATE_HARDWARE_VERTEXPROCESSING,
2528 &PresParam,
2529 &pContext->pDevice);
2530#else
2531 hr = pState->pD3D9->CreateDeviceEx(D3DADAPTER_DEFAULT,
2532 D3DDEVTYPE_HAL,
2533 pContext->hwnd,
2534 D3DCREATE_MULTITHREADED | D3DCREATE_MIXED_VERTEXPROCESSING, //D3DCREATE_HARDWARE_VERTEXPROCESSING,
2535 &PresParam,
2536 NULL,
2537 &pContext->pDevice);
2538#endif
2539 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dContextDefine: CreateDevice failed with %x\n", hr), VERR_INTERNAL_ERROR);
2540
2541 Log(("vmsvga3dContextDefine: Backbuffer (%d,%d) count=%d format=%x\n", PresParam.BackBufferWidth, PresParam.BackBufferHeight, PresParam.BackBufferCount, PresParam.BackBufferFormat));
2542 return VINF_SUCCESS;
2543}
2544
2545/**
2546 * Destroy an existing 3d context
2547 *
2548 * @returns VBox status code.
2549 * @param pThis VGA device instance data.
2550 * @param cid Context id
2551 */
2552int vmsvga3dContextDestroy(PVGASTATE pThis, uint32_t cid)
2553{
2554 PVMSVGA3DSTATE pState = pThis->svga.p3dState;
2555 AssertReturn(pState, VERR_NO_MEMORY);
2556
2557 AssertReturn(cid < SVGA3D_MAX_CONTEXT_IDS, VERR_INVALID_PARAMETER);
2558
2559 if ( cid < pState->cContexts
2560 && pState->papContexts[cid]->id == cid)
2561 {
2562 PVMSVGA3DCONTEXT pContext = pState->papContexts[cid];
2563
2564 Log(("vmsvga3dContextDestroy id %x\n", cid));
2565
2566 /* Check for all surfaces that are associated with this context to remove all dependencies */
2567 for (uint32_t sid = 0; sid < pState->cSurfaces; sid++)
2568 {
2569 PVMSVGA3DSURFACE pSurface = pState->papSurfaces[sid];
2570 if ( pSurface->id == sid
2571 && pSurface->idAssociatedContext == cid)
2572 {
2573 int rc;
2574
2575 Log(("vmsvga3dContextDestroy: remove all dependencies for surface sid=%x\n", sid));
2576
2577 uint32_t surfaceFlags = pSurface->flags;
2578 SVGA3dSurfaceFormat format = pSurface->format;
2579 SVGA3dSurfaceFace face[SVGA3D_MAX_SURFACE_FACES];
2580 uint32_t multisampleCount = pSurface->multiSampleCount;
2581 SVGA3dTextureFilter autogenFilter = pSurface->autogenFilter;
2582 SVGA3dSize *pMipLevelSize;
2583 uint32_t cFaces = pSurface->cFaces;
2584
2585 pMipLevelSize = (SVGA3dSize *)RTMemAllocZ(pSurface->faces[0].numMipLevels * pSurface->cFaces * sizeof(SVGA3dSize));
2586 AssertReturn(pMipLevelSize, VERR_NO_MEMORY);
2587
2588 for (uint32_t face=0; face < pSurface->cFaces; face++)
2589 {
2590 for (uint32_t i = 0; i < pSurface->faces[0].numMipLevels; i++)
2591 {
2592 uint32_t idx = i + face * pSurface->faces[0].numMipLevels;
2593 memcpy(&pMipLevelSize[idx], &pSurface->pMipmapLevels[idx].size, sizeof(SVGA3dSize));
2594 }
2595 }
2596 memcpy(face, pSurface->faces, sizeof(pSurface->faces));
2597
2598 /* Recreate the surface with the original settings; destroys the contents, but that seems fairly safe since the context is also destroyed. */
2599 /** @todo not safe with shared objects */
2600 Assert(pSurface->pSharedObjectTree == NULL);
2601
2602 rc = vmsvga3dSurfaceDestroy(pThis, sid);
2603 AssertRC(rc);
2604
2605 rc = vmsvga3dSurfaceDefine(pThis, sid, surfaceFlags, format, face, multisampleCount, autogenFilter, face[0].numMipLevels * cFaces, pMipLevelSize);
2606 AssertRC(rc);
2607
2608 Assert(!pSurface->u.pSurface);
2609 }
2610 else
2611 {
2612 /* Check for a shared surface object. */
2613 PVMSVGA3DSHAREDSURFACE pSharedSurface = (PVMSVGA3DSHAREDSURFACE)RTAvlU32Get(&pSurface->pSharedObjectTree, cid);
2614 if (pSharedSurface)
2615 {
2616 Log(("vmsvga3dContextDestroy: remove shared dependency for surface sid=%x\n", sid));
2617
2618 switch (pSurface->flags & (SVGA3D_SURFACE_HINT_INDEXBUFFER | SVGA3D_SURFACE_HINT_VERTEXBUFFER | SVGA3D_SURFACE_HINT_TEXTURE | SVGA3D_SURFACE_HINT_RENDERTARGET | SVGA3D_SURFACE_HINT_DEPTHSTENCIL | SVGA3D_SURFACE_CUBEMAP))
2619 {
2620 case SVGA3D_SURFACE_HINT_TEXTURE:
2621 case SVGA3D_SURFACE_HINT_TEXTURE | SVGA3D_SURFACE_HINT_RENDERTARGET:
2622 Assert(pSharedSurface->u.pTexture);
2623 if (pSharedSurface->u.pTexture)
2624 pSharedSurface->u.pTexture->Release();
2625 break;
2626
2627 default:
2628 AssertFailed();
2629 break;
2630 }
2631 RTAvlU32Remove(&pSurface->pSharedObjectTree, cid);
2632 RTMemFree(pSharedSurface);
2633 }
2634 }
2635 }
2636
2637 /* Destroy all leftover pixel shaders. */
2638 for (uint32_t i = 0; i < pContext->cPixelShaders; i++)
2639 {
2640 if (pContext->paPixelShader[i].id != SVGA3D_INVALID_ID)
2641 vmsvga3dShaderDestroy(pThis, pContext->paPixelShader[i].cid, pContext->paPixelShader[i].id, pContext->paPixelShader[i].type);
2642 }
2643 if (pContext->paPixelShader)
2644 RTMemFree(pContext->paPixelShader);
2645
2646 /* Destroy all leftover vertex shaders. */
2647 for (uint32_t i = 0; i < pContext->cVertexShaders; i++)
2648 {
2649 if (pContext->paVertexShader[i].id != SVGA3D_INVALID_ID)
2650 vmsvga3dShaderDestroy(pThis, pContext->paVertexShader[i].cid, pContext->paVertexShader[i].id, pContext->paVertexShader[i].type);
2651 }
2652 if (pContext->paVertexShader)
2653 RTMemFree(pContext->paVertexShader);
2654
2655 if (pContext->state.paVertexShaderConst)
2656 RTMemFree(pContext->state.paVertexShaderConst);
2657 if (pContext->state.paPixelShaderConst)
2658 RTMemFree(pContext->state.paPixelShaderConst);
2659
2660 /* Release the D3D device object */
2661 pContext->pDevice->Release();
2662
2663 /* Destroy the window we've created. */
2664 int rc = vmsvga3dSendThreadMessage(pState->pWindowThread, pState->WndRequestSem, WM_VMSVGA3D_DESTROYWINDOW, (WPARAM)pContext->hwnd, 0);
2665 AssertRC(rc);
2666
2667 memset(pContext, 0, sizeof(*pContext));
2668 pContext->id = SVGA3D_INVALID_ID;
2669 }
2670 else
2671 AssertFailed();
2672
2673 return VINF_SUCCESS;
2674}
2675
2676static int vmsvga3dContextTrackUsage(PVGASTATE pThis, PVMSVGA3DCONTEXT pContext)
2677{
2678#ifndef VBOX_VMSVGA3D_WITH_WINE_OPENGL
2679 PVMSVGA3DSTATE pState = pThis->svga.p3dState;
2680 AssertReturn(pState, VERR_NO_MEMORY);
2681
2682 /* Inject fences to make sure we can track surface usage in case the client wants to reuse it in another context. */
2683 for (uint32_t i = 0; i < RT_ELEMENTS(pContext->aSidActiveTexture); i++)
2684 {
2685 if (pContext->aSidActiveTexture[i] != SVGA3D_INVALID_ID)
2686 vmsvga3dSurfaceTrackUsageById(pState, pContext, pContext->aSidActiveTexture[i]);
2687 }
2688 if (pContext->sidRenderTarget != SVGA3D_INVALID_ID)
2689 vmsvga3dSurfaceTrackUsageById(pState, pContext, pContext->sidRenderTarget);
2690#endif
2691 return VINF_SUCCESS;
2692}
2693
2694/* Handle resize */
2695int vmsvga3dChangeMode(PVGASTATE pThis)
2696{
2697 PVMSVGA3DSTATE pState = pThis->svga.p3dState;
2698 AssertReturn(pState, VERR_NO_MEMORY);
2699
2700 /* Resize all active contexts. */
2701 for (uint32_t i = 0; i < pState->cContexts; i++)
2702 {
2703 PVMSVGA3DCONTEXT pContext = pState->papContexts[i];
2704 uint32_t cid = pContext->id;
2705
2706 if (cid != SVGA3D_INVALID_ID)
2707 {
2708 CREATESTRUCT cs;
2709 D3DPRESENT_PARAMETERS PresParam;
2710 D3DVIEWPORT9 viewportOrg;
2711 HRESULT hr;
2712
2713#ifdef VMSVGA3D_DIRECT3D9_RESET
2714 /* Sync back all surface data as everything is lost after the Reset. */
2715 for (uint32_t sid = 0; sid < pState->cSurfaces; sid++)
2716 {
2717 PVMSVGA3DSURFACE pSurface = pState->papSurfaces[sid];
2718 if ( pSurface->id == sid
2719 && pSurface->idAssociatedContext == cid
2720 && pSurface->u.pSurface)
2721 {
2722 Log(("vmsvga3dChangeMode: sync back data of surface sid=%x (fDirty=%d)\n", sid, pSurface->fDirty));
2723
2724 /* Reallocate our surface memory buffers. */
2725 for (uint32_t i = 0; i < pSurface->cMipLevels; i++)
2726 {
2727 PVMSVGA3DMIPMAPLEVEL pMipmapLevel = &pSurface->pMipmapLevels[i];
2728
2729 pMipmapLevel->pSurfaceData = RTMemAllocZ(pMipmapLevel->cbSurface);
2730 AssertReturn(pMipmapLevel->pSurfaceData, VERR_NO_MEMORY);
2731
2732 if (!pSurface->fDirty)
2733 {
2734 D3DLOCKED_RECT LockedRect;
2735
2736 if (pSurface->bounce.pTexture)
2737 {
2738 IDirect3DSurface9 *pSrc, *pDest;
2739
2740 /** @todo only sync when something was actually rendered (since the last sync) */
2741 Log(("vmsvga3dChangeMode: sync bounce buffer (level %d)\n", i));
2742 hr = pSurface->bounce.pTexture->GetSurfaceLevel(i, &pDest);
2743 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dChangeMode: GetSurfaceLevel failed with %x\n", hr), VERR_INTERNAL_ERROR);
2744
2745 hr = pSurface->u.pTexture->GetSurfaceLevel(i, &pSrc);
2746 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dChangeMode: GetSurfaceLevel failed with %x\n", hr), VERR_INTERNAL_ERROR);
2747
2748 hr = pContext->pDevice->GetRenderTargetData(pSrc, pDest);
2749 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dChangeMode: GetRenderTargetData failed with %x\n", hr), VERR_INTERNAL_ERROR);
2750
2751 pSrc->Release();
2752 pDest->Release();
2753
2754 hr = pSurface->bounce.pTexture->LockRect(i,
2755 &LockedRect,
2756 NULL,
2757 D3DLOCK_READONLY);
2758 }
2759 else
2760 hr = pSurface->u.pTexture->LockRect(i,
2761 &LockedRect,
2762 NULL,
2763 D3DLOCK_READONLY);
2764 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dChangeMode: LockRect failed with %x\n", hr), VERR_INTERNAL_ERROR);
2765
2766 /* Copy the data one line at a time in case the internal pitch is different. */
2767 for (uint32_t j = 0; j < pMipmapLevel->size.height; j++)
2768 {
2769 memcpy((uint8_t *)pMipmapLevel->pSurfaceData + j * pMipmapLevel->cbSurfacePitch, (uint8_t *)LockedRect.pBits + j * LockedRect.Pitch, pMipmapLevel->cbSurfacePitch);
2770 }
2771
2772 if (pSurface->bounce.pTexture)
2773 hr = pSurface->bounce.pTexture->UnlockRect(i);
2774 else
2775 hr = pSurface->u.pTexture->UnlockRect(i);
2776 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dChangeMode: UnlockRect failed with %x\n", hr), VERR_INTERNAL_ERROR);
2777 }
2778 }
2779
2780
2781 switch (pSurface->flags & (SVGA3D_SURFACE_HINT_INDEXBUFFER | SVGA3D_SURFACE_HINT_VERTEXBUFFER | SVGA3D_SURFACE_HINT_TEXTURE | SVGA3D_SURFACE_HINT_RENDERTARGET | SVGA3D_SURFACE_HINT_DEPTHSTENCIL | SVGA3D_SURFACE_CUBEMAP))
2782 {
2783 case SVGA3D_SURFACE_CUBEMAP:
2784 AssertFailed(); /** @todo */
2785 break;
2786
2787 case SVGA3D_SURFACE_HINT_INDEXBUFFER:
2788 pSurface->u.pIndexBuffer->Release();
2789 break;
2790
2791 case SVGA3D_SURFACE_HINT_VERTEXBUFFER:
2792 pSurface->u.pVertexBuffer->Release();
2793 pSurface->u.pVertexBuffer = NULL;
2794 break;
2795
2796 case SVGA3D_SURFACE_HINT_TEXTURE:
2797 case SVGA3D_SURFACE_HINT_TEXTURE | SVGA3D_SURFACE_HINT_RENDERTARGET:
2798 pSurface->u.pTexture->Release();
2799 pSurface->u.pTexture = NULL;
2800 if (pSurface->bounce.pTexture)
2801 {
2802 pSurface->bounce.pTexture->Release();
2803 pSurface->bounce.pTexture = NULL;
2804 }
2805 break;
2806
2807 case SVGA3D_SURFACE_HINT_RENDERTARGET:
2808 case SVGA3D_SURFACE_HINT_DEPTHSTENCIL:
2809 if (pSurface->fStencilAsTexture)
2810 pSurface->u.pTexture->Release();
2811 else
2812 pSurface->u.pSurface->Release();
2813 pSurface->u.pSurface = NULL;
2814 break;
2815
2816 default:
2817 break;
2818 }
2819 RTAvlU32Destroy(&pSurface->pSharedObjectTree, vmsvga3dSharedSurfaceDestroyTree, pSurface);
2820 Assert(pSurface->pSharedObjectTree == NULL);
2821
2822 pSurface->idAssociatedContext = SVGA3D_INVALID_ID;
2823 pSurface->hSharedObject = 0;
2824 }
2825 }
2826#endif /* #ifdef VMSVGA3D_DIRECT3D9_RESET */
2827 memset(&cs, 0, sizeof(cs));
2828 cs.cx = pThis->svga.uWidth;
2829 cs.cy = pThis->svga.uHeight;
2830
2831 Log(("vmsvga3dChangeMode: Resize window %x of context %d to (%d,%d)\n", pContext->hwnd, pContext->id, cs.cx, cs.cy));
2832
2833 AssertReturn(pContext->pDevice, VERR_INTERNAL_ERROR);
2834 hr = pContext->pDevice->GetViewport(&viewportOrg);
2835 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dChangeMode: GetViewport failed with %x\n", hr), VERR_INTERNAL_ERROR);
2836
2837 Log(("vmsvga3dChangeMode: old viewport settings (%d,%d)(%d,%d) z=%d/%d\n", viewportOrg.X, viewportOrg.Y, viewportOrg.Width, viewportOrg.Height, (uint32_t)(viewportOrg.MinZ * 100.0), (uint32_t)(viewportOrg.MaxZ * 100.0)));
2838
2839 /* Resize the window. */
2840 int rc = vmsvga3dSendThreadMessage(pState->pWindowThread, pState->WndRequestSem, WM_VMSVGA3D_RESIZEWINDOW, (WPARAM)pContext->hwnd, (LPARAM)&cs);
2841 AssertRC(rc);
2842
2843 /* Changed when the function returns. */
2844 PresParam.BackBufferWidth = 0;
2845 PresParam.BackBufferHeight = 0;
2846 PresParam.BackBufferFormat = D3DFMT_UNKNOWN;
2847 PresParam.BackBufferCount = 0;
2848
2849 PresParam.MultiSampleType = D3DMULTISAMPLE_NONE;
2850 PresParam.MultiSampleQuality = 0;
2851 PresParam.SwapEffect = D3DSWAPEFFECT_FLIP;
2852 PresParam.hDeviceWindow = pContext->hwnd;
2853 PresParam.Windowed = TRUE; /** @todo */
2854 PresParam.EnableAutoDepthStencil = FALSE;
2855 PresParam.AutoDepthStencilFormat = D3DFMT_UNKNOWN; /* not relevant */
2856 PresParam.Flags = 0;
2857 PresParam.FullScreen_RefreshRateInHz = 0; /* windowed -> 0 */
2858 /** @todo consider using D3DPRESENT_DONOTWAIT so we don't wait for the GPU during Present calls. */
2859 PresParam.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;;
2860
2861#ifdef VBOX_VMSVGA3D_WITH_WINE_OPENGL
2862 hr = pContext->pDevice->Reset(&PresParam);
2863 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dChangeMode: Reset failed with %x\n", hr), VERR_INTERNAL_ERROR);
2864#else
2865 /* ResetEx does not trash the device state */
2866 hr = pContext->pDevice->ResetEx(&PresParam, NULL);
2867 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dChangeMode: Reset failed with %x\n", hr), VERR_INTERNAL_ERROR);
2868#endif
2869 Log(("vmsvga3dChangeMode: Backbuffer (%d,%d) count=%d format=%x\n", PresParam.BackBufferWidth, PresParam.BackBufferHeight, PresParam.BackBufferCount, PresParam.BackBufferFormat));
2870
2871 /* ResetEx changes the viewport; restore it again. */
2872 hr = pContext->pDevice->SetViewport(&viewportOrg);
2873 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dChangeMode: SetViewport failed with %x\n", hr), VERR_INTERNAL_ERROR);
2874
2875#ifdef LOG_ENABLED
2876 {
2877 D3DVIEWPORT9 viewport;
2878 hr = pContext->pDevice->GetViewport(&viewport);
2879 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dChangeMode: GetViewport failed with %x\n", hr), VERR_INTERNAL_ERROR);
2880
2881 Log(("vmsvga3dChangeMode: changed viewport settings (%d,%d)(%d,%d) z=%d/%d\n", viewport.X, viewport.Y, viewport.Width, viewport.Height, (uint32_t)(viewport.MinZ * 100.0), (uint32_t)(viewport.MaxZ * 100.0)));
2882 }
2883#endif
2884
2885 /* First set the render targets as they change the internal state (reset viewport etc) */
2886 Log(("vmsvga3dChangeMode: Recreate render targets BEGIN\n"));
2887 for (uint32_t j = 0; j < RT_ELEMENTS(pContext->state.aRenderTargets); j++)
2888 {
2889 if (pContext->state.aRenderTargets[j] != SVGA3D_INVALID_ID)
2890 {
2891 SVGA3dSurfaceImageId target;
2892
2893 target.sid = pContext->state.aRenderTargets[j];
2894 target.face = 0;
2895 target.mipmap = 0;
2896 rc = vmsvga3dSetRenderTarget(pThis, cid, (SVGA3dRenderTargetType)j, target);
2897 AssertRCReturn(rc, rc);
2898 }
2899 }
2900
2901#ifdef VMSVGA3D_DIRECT3D9_RESET
2902 /* Recreate the render state */
2903 Log(("vmsvga3dChangeMode: Recreate render state BEGIN\n"));
2904 for (uint32_t i = 0; i < RT_ELEMENTS(pContext->state.aRenderState); i++)
2905 {
2906 SVGA3dRenderState *pRenderState = &pContext->state.aRenderState[i];
2907
2908 if (pRenderState->state != SVGA3D_RS_INVALID)
2909 vmsvga3dSetRenderState(pThis, pContext->id, 1, pRenderState);
2910 }
2911 Log(("vmsvga3dChangeMode: Recreate render state END\n"));
2912
2913 /* Recreate the texture state */
2914 Log(("vmsvga3dChangeMode: Recreate texture state BEGIN\n"));
2915 for (uint32_t iStage = 0; iStage < SVGA3D_MAX_TEXTURE_STAGE; iStage++)
2916 {
2917 for (uint32_t j = 0; j < SVGA3D_TS_MAX; j++)
2918 {
2919 SVGA3dTextureState *pTextureState = &pContext->state.aTextureState[iStage][j];
2920
2921 if (pTextureState->name != SVGA3D_RS_INVALID)
2922 vmsvga3dSetTextureState(pThis, pContext->id, 1, pTextureState);
2923 }
2924 }
2925 Log(("vmsvga3dChangeMode: Recreate texture state END\n"));
2926
2927 if (pContext->state.u32UpdateFlags & VMSVGA3D_UPDATE_SCISSORRECT)
2928 vmsvga3dSetScissorRect(pThis, cid, &pContext->state.RectScissor);
2929 if (pContext->state.u32UpdateFlags & VMSVGA3D_UPDATE_ZRANGE)
2930 vmsvga3dSetZRange(pThis, cid, pContext->state.zRange);
2931 if (pContext->state.u32UpdateFlags & VMSVGA3D_UPDATE_VIEWPORT)
2932 vmsvga3dSetViewPort(pThis, cid, &pContext->state.RectViewPort);
2933 if (pContext->state.u32UpdateFlags & VMSVGA3D_UPDATE_VERTEXSHADER)
2934 vmsvga3dShaderSet(pThis, pContext, cid, SVGA3D_SHADERTYPE_VS, pContext->state.shidVertex);
2935 if (pContext->state.u32UpdateFlags & VMSVGA3D_UPDATE_PIXELSHADER)
2936 vmsvga3dShaderSet(pThis, pContext, cid, SVGA3D_SHADERTYPE_PS, pContext->state.shidPixel);
2937 /** @todo restore more state data */
2938#endif /* #ifdef VMSVGA3D_DIRECT3D9_RESET */
2939 }
2940 }
2941 return VINF_SUCCESS;
2942}
2943
2944
2945int vmsvga3dSetTransform(PVGASTATE pThis, uint32_t cid, SVGA3dTransformType type, float matrix[16])
2946{
2947 D3DTRANSFORMSTATETYPE d3dState;
2948 HRESULT hr;
2949 PVMSVGA3DCONTEXT pContext;
2950 PVMSVGA3DSTATE pState = pThis->svga.p3dState;
2951 AssertReturn(pState, VERR_NO_MEMORY);
2952
2953 Log(("vmsvga3dSetTransform %x %s\n", cid, vmsvgaTransformToString(type)));
2954
2955 if ( cid >= pState->cContexts
2956 || pState->papContexts[cid]->id != cid)
2957 {
2958 Log(("vmsvga3dSetTransform invalid context id!\n"));
2959 return VERR_INVALID_PARAMETER;
2960 }
2961 pContext = pState->papContexts[cid];
2962
2963 switch (type)
2964 {
2965 case SVGA3D_TRANSFORM_VIEW:
2966 d3dState = D3DTS_VIEW;
2967 break;
2968 case SVGA3D_TRANSFORM_PROJECTION:
2969 d3dState = D3DTS_PROJECTION;
2970 break;
2971 case SVGA3D_TRANSFORM_TEXTURE0:
2972 d3dState = D3DTS_TEXTURE0;
2973 break;
2974 case SVGA3D_TRANSFORM_TEXTURE1:
2975 d3dState = D3DTS_TEXTURE1;
2976 break;
2977 case SVGA3D_TRANSFORM_TEXTURE2:
2978 d3dState = D3DTS_TEXTURE2;
2979 break;
2980 case SVGA3D_TRANSFORM_TEXTURE3:
2981 d3dState = D3DTS_TEXTURE3;
2982 break;
2983 case SVGA3D_TRANSFORM_TEXTURE4:
2984 d3dState = D3DTS_TEXTURE4;
2985 break;
2986 case SVGA3D_TRANSFORM_TEXTURE5:
2987 d3dState = D3DTS_TEXTURE5;
2988 break;
2989 case SVGA3D_TRANSFORM_TEXTURE6:
2990 d3dState = D3DTS_TEXTURE6;
2991 break;
2992 case SVGA3D_TRANSFORM_TEXTURE7:
2993 d3dState = D3DTS_TEXTURE7;
2994 break;
2995 case SVGA3D_TRANSFORM_WORLD:
2996 d3dState = D3DTS_WORLD;
2997 break;
2998 case SVGA3D_TRANSFORM_WORLD1:
2999 d3dState = D3DTS_WORLD1;
3000 break;
3001 case SVGA3D_TRANSFORM_WORLD2:
3002 d3dState = D3DTS_WORLD2;
3003 break;
3004 case SVGA3D_TRANSFORM_WORLD3:
3005 d3dState = D3DTS_WORLD3;
3006 break;
3007
3008 default:
3009 Log(("vmsvga3dSetTransform: unknown type!!\n"));
3010 return VERR_INVALID_PARAMETER;
3011 }
3012
3013 /* Save this matrix for vm state save/restore. */
3014 pContext->state.aTransformState[type].fValid = true;
3015 memcpy(pContext->state.aTransformState[type].matrix, matrix, sizeof(pContext->state.aTransformState[type].matrix));
3016 pContext->state.u32UpdateFlags |= VMSVGA3D_UPDATE_TRANSFORM;
3017
3018 Log(("Matrix [%d %d %d %d]\n", (int)(matrix[0] * 10.0), (int)(matrix[1] * 10.0), (int)(matrix[2] * 10.0), (int)(matrix[3] * 10.0)));
3019 Log((" [%d %d %d %d]\n", (int)(matrix[4] * 10.0), (int)(matrix[5] * 10.0), (int)(matrix[6] * 10.0), (int)(matrix[7] * 10.0)));
3020 Log((" [%d %d %d %d]\n", (int)(matrix[8] * 10.0), (int)(matrix[9] * 10.0), (int)(matrix[10] * 10.0), (int)(matrix[11] * 10.0)));
3021 Log((" [%d %d %d %d]\n", (int)(matrix[12] * 10.0), (int)(matrix[13] * 10.0), (int)(matrix[14] * 10.0), (int)(matrix[15] * 10.0)));
3022 hr = pContext->pDevice->SetTransform(d3dState, (const D3DMATRIX *)matrix);
3023 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSetTransform: SetTransform failed with %x\n", hr), VERR_INTERNAL_ERROR);
3024 return VINF_SUCCESS;
3025}
3026
3027int vmsvga3dSetZRange(PVGASTATE pThis, uint32_t cid, SVGA3dZRange zRange)
3028{
3029 D3DVIEWPORT9 viewport;
3030 HRESULT hr;
3031 PVMSVGA3DCONTEXT pContext;
3032 PVMSVGA3DSTATE pState = pThis->svga.p3dState;
3033 AssertReturn(pState, VERR_NO_MEMORY);
3034
3035 Log(("vmsvga3dSetZRange %x min=%d max=%d\n", cid, (uint32_t)(zRange.min * 100.0), (uint32_t)(zRange.max * 100.0)));
3036
3037 if ( cid >= pState->cContexts
3038 || pState->papContexts[cid]->id != cid)
3039 {
3040 Log(("vmsvga3dSetZRange invalid context id!\n"));
3041 return VERR_INVALID_PARAMETER;
3042 }
3043 pContext = pState->papContexts[cid];
3044 pContext->state.zRange = zRange;
3045 pContext->state.u32UpdateFlags |= VMSVGA3D_UPDATE_ZRANGE;
3046
3047 hr = pContext->pDevice->GetViewport(&viewport);
3048 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSetZRange: GetViewport failed with %x\n", hr), VERR_INTERNAL_ERROR);
3049
3050 Log(("vmsvga3dSetZRange: old viewport settings (%d,%d)(%d,%d) z=%d/%d\n", viewport.X, viewport.Y, viewport.Width, viewport.Height, (uint32_t)(viewport.MinZ * 100.0), (uint32_t)(viewport.MaxZ * 100.0)));
3051 /** @todo convert the depth range from -1-1 to 0-1 although we shouldn't be getting such values in the first place... */
3052 if (zRange.min < 0.0)
3053 zRange.min = 0.0;
3054 if (zRange.max > 1.0)
3055 zRange.max = 1.0;
3056
3057 viewport.MinZ = zRange.min;
3058 viewport.MaxZ = zRange.max;
3059 hr = pContext->pDevice->SetViewport(&viewport);
3060 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSetZRange: SetViewport failed with %x\n", hr), VERR_INTERNAL_ERROR);
3061 return VINF_SUCCESS;
3062}
3063
3064/**
3065 * Convert SVGA blend op value to its D3D equivalent
3066 */
3067static DWORD vmsvga3dBlendOp2D3D(uint32_t blendOp, DWORD defaultBlendOp)
3068{
3069 switch (blendOp)
3070 {
3071 case SVGA3D_BLENDOP_ZERO:
3072 return D3DBLEND_ZERO;
3073 case SVGA3D_BLENDOP_ONE:
3074 return D3DBLEND_ONE;
3075 case SVGA3D_BLENDOP_SRCCOLOR:
3076 return D3DBLEND_SRCCOLOR;
3077 case SVGA3D_BLENDOP_INVSRCCOLOR:
3078 return D3DBLEND_INVSRCCOLOR;
3079 case SVGA3D_BLENDOP_SRCALPHA:
3080 return D3DBLEND_SRCALPHA;
3081 case SVGA3D_BLENDOP_INVSRCALPHA:
3082 return D3DBLEND_INVSRCALPHA;
3083 case SVGA3D_BLENDOP_DESTALPHA:
3084 return D3DBLEND_DESTALPHA;
3085 case SVGA3D_BLENDOP_INVDESTALPHA:
3086 return D3DBLEND_INVDESTALPHA;
3087 case SVGA3D_BLENDOP_DESTCOLOR:
3088 return D3DBLEND_DESTCOLOR;
3089 case SVGA3D_BLENDOP_INVDESTCOLOR:
3090 return D3DBLEND_INVDESTCOLOR;
3091 case SVGA3D_BLENDOP_SRCALPHASAT:
3092 return D3DBLEND_SRCALPHASAT;
3093 case SVGA3D_BLENDOP_BLENDFACTOR:
3094 return D3DBLEND_BLENDFACTOR;
3095 case SVGA3D_BLENDOP_INVBLENDFACTOR:
3096 return D3DBLEND_INVBLENDFACTOR;
3097 default:
3098 AssertFailed();
3099 return defaultBlendOp;
3100 }
3101}
3102
3103int vmsvga3dSetRenderState(PVGASTATE pThis, uint32_t cid, uint32_t cRenderStates, SVGA3dRenderState *pRenderState)
3104{
3105 DWORD val = 0; /* Shut up MSC */
3106 HRESULT hr;
3107 PVMSVGA3DCONTEXT pContext;
3108 PVMSVGA3DSTATE pState = pThis->svga.p3dState;
3109 AssertReturn(pState, VERR_NO_MEMORY);
3110
3111 Log(("vmsvga3dSetRenderState cid=%x cRenderStates=%d\n", cid, cRenderStates));
3112
3113 if ( cid >= pState->cContexts
3114 || pState->papContexts[cid]->id != cid)
3115 {
3116 Log(("vmsvga3dSetRenderState invalid context id!\n"));
3117 return VERR_INVALID_PARAMETER;
3118 }
3119 pContext = pState->papContexts[cid];
3120
3121 for (unsigned i = 0; i < cRenderStates; i++)
3122 {
3123 D3DRENDERSTATETYPE renderState = D3DRS_FORCE_DWORD;
3124
3125 Log(("vmsvga3dSetRenderState: state=%s (%d) val=%x\n", vmsvga3dGetRenderStateName(pRenderState[i].state), pRenderState[i].state, pRenderState[i].uintValue));
3126 /* Save the render state for vm state saving. */
3127 if (pRenderState[i].state < SVGA3D_RS_MAX)
3128 pContext->state.aRenderState[pRenderState[i].state] = pRenderState[i];
3129
3130 switch (pRenderState[i].state)
3131 {
3132 case SVGA3D_RS_ZENABLE: /* SVGA3dBool */
3133 renderState = D3DRS_ZENABLE;
3134 val = pRenderState[i].uintValue;
3135 Assert(val == D3DZB_FALSE || val == D3DZB_TRUE);
3136 break;
3137
3138 case SVGA3D_RS_ZWRITEENABLE: /* SVGA3dBool */
3139 renderState = D3DRS_ZWRITEENABLE;
3140 val = pRenderState[i].uintValue;
3141 break;
3142
3143 case SVGA3D_RS_ALPHATESTENABLE: /* SVGA3dBool */
3144 renderState = D3DRS_ALPHATESTENABLE;
3145 val = pRenderState[i].uintValue;
3146 break;
3147
3148 case SVGA3D_RS_DITHERENABLE: /* SVGA3dBool */
3149 renderState = D3DRS_DITHERENABLE;
3150 val = pRenderState[i].uintValue;
3151 break;
3152
3153 case SVGA3D_RS_BLENDENABLE: /* SVGA3dBool */
3154 renderState = D3DRS_ALPHABLENDENABLE;
3155 val = pRenderState[i].uintValue;
3156 break;
3157
3158 case SVGA3D_RS_FOGENABLE: /* SVGA3dBool */
3159 renderState = D3DRS_FOGENABLE;
3160 val = pRenderState[i].uintValue;
3161 break;
3162
3163 case SVGA3D_RS_SPECULARENABLE: /* SVGA3dBool */
3164 renderState = D3DRS_SPECULARENABLE;
3165 val = pRenderState[i].uintValue;
3166 break;
3167
3168 case SVGA3D_RS_LIGHTINGENABLE: /* SVGA3dBool */
3169 renderState = D3DRS_LIGHTING;
3170 val = pRenderState[i].uintValue;
3171 break;
3172
3173 case SVGA3D_RS_NORMALIZENORMALS: /* SVGA3dBool */
3174 renderState = D3DRS_NORMALIZENORMALS;
3175 val = pRenderState[i].uintValue;
3176 break;
3177
3178 case SVGA3D_RS_POINTSPRITEENABLE: /* SVGA3dBool */
3179 renderState = D3DRS_POINTSPRITEENABLE;
3180 val = pRenderState[i].uintValue;
3181 break;
3182
3183 case SVGA3D_RS_POINTSCALEENABLE: /* SVGA3dBool */
3184 renderState = D3DRS_POINTSCALEENABLE;
3185 val = pRenderState[i].uintValue;
3186 break;
3187
3188 case SVGA3D_RS_POINTSIZE: /* float */
3189 renderState = D3DRS_POINTSIZE;
3190 val = pRenderState[i].uintValue;
3191 Log(("SVGA3D_RS_POINTSIZE: %d\n", (uint32_t) (pRenderState[i].floatValue * 100.0)));
3192 break;
3193
3194 case SVGA3D_RS_POINTSIZEMIN: /* float */
3195 renderState = D3DRS_POINTSIZE_MIN;
3196 val = pRenderState[i].uintValue;
3197 Log(("SVGA3D_RS_POINTSIZEMIN: %d\n", (uint32_t) (pRenderState[i].floatValue * 100.0)));
3198 break;
3199
3200 case SVGA3D_RS_POINTSIZEMAX: /* float */
3201 renderState = D3DRS_POINTSIZE_MAX;
3202 val = pRenderState[i].uintValue;
3203 Log(("SVGA3D_RS_POINTSIZEMAX: %d\n", (uint32_t) (pRenderState[i].floatValue * 100.0)));
3204 break;
3205
3206 case SVGA3D_RS_POINTSCALE_A: /* float */
3207 renderState = D3DRS_POINTSCALE_A;
3208 val = pRenderState[i].uintValue;
3209 break;
3210
3211 case SVGA3D_RS_POINTSCALE_B: /* float */
3212 renderState = D3DRS_POINTSCALE_B;
3213 val = pRenderState[i].uintValue;
3214 break;
3215
3216 case SVGA3D_RS_POINTSCALE_C: /* float */
3217 renderState = D3DRS_POINTSCALE_C;
3218 val = pRenderState[i].uintValue;
3219 break;
3220
3221 case SVGA3D_RS_AMBIENT: /* SVGA3dColor - identical */
3222 renderState = D3DRS_AMBIENT;
3223 val = pRenderState[i].uintValue;
3224 break;
3225
3226 case SVGA3D_RS_CLIPPLANEENABLE: /* SVGA3dClipPlanes - identical */
3227 renderState = D3DRS_CLIPPLANEENABLE;
3228 val = pRenderState[i].uintValue;
3229 break;
3230
3231 case SVGA3D_RS_FOGCOLOR: /* SVGA3dColor - identical */
3232 renderState = D3DRS_FOGCOLOR;
3233 val = pRenderState[i].uintValue;
3234 break;
3235
3236 case SVGA3D_RS_FOGSTART: /* float */
3237 renderState = D3DRS_FOGSTART;
3238 val = pRenderState[i].uintValue;
3239 break;
3240
3241 case SVGA3D_RS_FOGEND: /* float */
3242 renderState = D3DRS_FOGEND;
3243 val = pRenderState[i].uintValue;
3244 break;
3245
3246 case SVGA3D_RS_FOGDENSITY: /* float */
3247 renderState = D3DRS_FOGDENSITY;
3248 val = pRenderState[i].uintValue;
3249 break;
3250
3251 case SVGA3D_RS_RANGEFOGENABLE: /* SVGA3dBool */
3252 renderState = D3DRS_RANGEFOGENABLE;
3253 val = pRenderState[i].uintValue;
3254 break;
3255
3256 case SVGA3D_RS_FOGMODE: /* SVGA3dFogMode */
3257 {
3258 SVGA3dFogMode mode;
3259 mode.uintValue = pRenderState[i].uintValue;
3260
3261 switch (mode.s.function)
3262 {
3263 case SVGA3D_FOGFUNC_INVALID:
3264 val = D3DFOG_NONE;
3265 break;
3266 case SVGA3D_FOGFUNC_EXP:
3267 val = D3DFOG_EXP;
3268 break;
3269 case SVGA3D_FOGFUNC_EXP2:
3270 val = D3DFOG_EXP2;
3271 break;
3272 case SVGA3D_FOGFUNC_LINEAR:
3273 val = D3DFOG_LINEAR;
3274 break;
3275 case SVGA3D_FOGFUNC_PER_VERTEX: /* unable to find a d3d9 equivalent */
3276 AssertMsgFailedReturn(("Unsupported fog function SVGA3D_FOGFUNC_PER_VERTEX\n"), VERR_INTERNAL_ERROR);
3277 break;
3278 default:
3279 AssertMsgFailedReturn(("Unexpected fog function %d\n", mode.s.function), VERR_INTERNAL_ERROR);
3280 break;
3281 }
3282
3283 /* The fog type determines the render state. */
3284 switch (mode.s.type)
3285 {
3286 case SVGA3D_FOGTYPE_VERTEX:
3287 renderState = D3DRS_FOGVERTEXMODE;
3288 break;
3289 case SVGA3D_FOGTYPE_PIXEL:
3290 renderState = D3DRS_FOGTABLEMODE;
3291 break;
3292 default:
3293 AssertMsgFailedReturn(("Unexpected fog type %d\n", mode.s.type), VERR_INTERNAL_ERROR);
3294 break;
3295 }
3296
3297 /* Set the fog base to depth or range. */
3298 switch (mode.s.base)
3299 {
3300 case SVGA3D_FOGBASE_DEPTHBASED:
3301 hr = pContext->pDevice->SetRenderState(D3DRS_RANGEFOGENABLE, FALSE);
3302 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSetRenderState: SetRenderState SVGA3D_FOGBASE_DEPTHBASED failed with %x\n", hr), VERR_INTERNAL_ERROR);
3303 break;
3304 case SVGA3D_FOGBASE_RANGEBASED:
3305 hr = pContext->pDevice->SetRenderState(D3DRS_RANGEFOGENABLE, TRUE);
3306 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSetRenderState: SetRenderState SVGA3D_FOGBASE_RANGEBASED failed with %x\n", hr), VERR_INTERNAL_ERROR);
3307 break;
3308 default:
3309 /* ignore */
3310 AssertMsgFailed(("Unexpected fog base %d\n", mode.s.base));
3311 break;
3312 }
3313 break;
3314 }
3315
3316 case SVGA3D_RS_FILLMODE: /* SVGA3dFillMode */
3317 {
3318 SVGA3dFillMode mode;
3319
3320 mode.uintValue = pRenderState[i].uintValue;
3321
3322 switch (mode.s.mode)
3323 {
3324 case SVGA3D_FILLMODE_POINT:
3325 val = D3DFILL_POINT;
3326 break;
3327 case SVGA3D_FILLMODE_LINE:
3328 val = D3DFILL_WIREFRAME;
3329 break;
3330 case SVGA3D_FILLMODE_FILL:
3331 val = D3DFILL_SOLID;
3332 break;
3333 default:
3334 AssertMsgFailedReturn(("Unexpected fill mode %d\n", mode.s.mode), VERR_INTERNAL_ERROR);
3335 break;
3336 }
3337 /** @todo ignoring face for now. */
3338 renderState = D3DRS_FILLMODE;
3339 break;
3340 }
3341
3342 case SVGA3D_RS_SHADEMODE: /* SVGA3dShadeMode */
3343 renderState = D3DRS_SHADEMODE;
3344 AssertCompile(D3DSHADE_FLAT == SVGA3D_SHADEMODE_FLAT);
3345 val = pRenderState[i].uintValue; /* SVGA3dShadeMode == D3DSHADEMODE */
3346 break;
3347
3348 case SVGA3D_RS_LINEPATTERN: /* SVGA3dLinePattern */
3349 /* No longer supported by d3d; mesagl comments suggest not all backends support it */
3350 /** @todo */
3351 Log(("WARNING: SVGA3D_RS_LINEPATTERN %x not supported!!\n", pRenderState[i].uintValue));
3352 /*
3353 renderState = D3DRS_LINEPATTERN;
3354 val = pRenderState[i].uintValue;
3355 */
3356 break;
3357
3358 case SVGA3D_RS_SRCBLEND: /* SVGA3dBlendOp */
3359 renderState = D3DRS_SRCBLEND;
3360 val = vmsvga3dBlendOp2D3D(pRenderState[i].uintValue, D3DBLEND_ONE /* default */);
3361 break;
3362
3363 case SVGA3D_RS_DSTBLEND: /* SVGA3dBlendOp */
3364 renderState = D3DRS_DESTBLEND;
3365 val = vmsvga3dBlendOp2D3D(pRenderState[i].uintValue, D3DBLEND_ZERO /* default */);
3366 break;
3367
3368 case SVGA3D_RS_BLENDEQUATION: /* SVGA3dBlendEquation - identical */
3369 AssertCompile(SVGA3D_BLENDEQ_MAXIMUM == D3DBLENDOP_MAX);
3370 renderState = D3DRS_BLENDOP;
3371 val = pRenderState[i].uintValue;
3372 break;
3373
3374 case SVGA3D_RS_CULLMODE: /* SVGA3dFace */
3375 {
3376 switch (pRenderState[i].uintValue)
3377 {
3378 case SVGA3D_FACE_NONE:
3379 val = D3DCULL_NONE;
3380 break;
3381 case SVGA3D_FACE_FRONT:
3382 val = D3DCULL_CW;
3383 break;
3384 case SVGA3D_FACE_BACK:
3385 val = D3DCULL_CCW;
3386 break;
3387 case SVGA3D_FACE_FRONT_BACK:
3388 AssertFailed();
3389 val = D3DCULL_CW;
3390 break;
3391 default:
3392 AssertMsgFailedReturn(("Unexpected cull mode %d\n", pRenderState[i].uintValue), VERR_INTERNAL_ERROR);
3393 break;
3394 }
3395 renderState = D3DRS_CULLMODE;
3396 break;
3397 }
3398
3399 case SVGA3D_RS_ZFUNC: /* SVGA3dCmpFunc - identical */
3400 AssertCompile(SVGA3D_CMP_ALWAYS == D3DCMP_ALWAYS);
3401 renderState = D3DRS_ZFUNC;
3402 val = pRenderState[i].uintValue;
3403 break;
3404
3405 case SVGA3D_RS_ALPHAFUNC: /* SVGA3dCmpFunc - identical */
3406 renderState = D3DRS_ALPHAFUNC;
3407 val = pRenderState[i].uintValue;
3408 break;
3409
3410 case SVGA3D_RS_STENCILENABLE: /* SVGA3dBool */
3411 renderState = D3DRS_STENCILENABLE;
3412 val = pRenderState[i].uintValue;
3413 break;
3414
3415 case SVGA3D_RS_STENCILREF: /* uint32_t */
3416 renderState = D3DRS_STENCILREF;
3417 val = pRenderState[i].uintValue;
3418 break;
3419
3420 case SVGA3D_RS_STENCILMASK: /* uint32_t */
3421 renderState = D3DRS_STENCILMASK;
3422 val = pRenderState[i].uintValue;
3423 break;
3424
3425 case SVGA3D_RS_STENCILWRITEMASK: /* uint32_t */
3426 renderState = D3DRS_STENCILWRITEMASK;
3427 val = pRenderState[i].uintValue;
3428 break;
3429
3430 case SVGA3D_RS_STENCILFUNC: /* SVGA3dCmpFunc - identical */
3431 renderState = D3DRS_STENCILFUNC;
3432 val = pRenderState[i].uintValue;
3433 break;
3434
3435 case SVGA3D_RS_STENCILFAIL: /* SVGA3dStencilOp - identical */
3436 AssertCompile(D3DSTENCILOP_KEEP == SVGA3D_STENCILOP_KEEP);
3437 AssertCompile(D3DSTENCILOP_DECR == SVGA3D_STENCILOP_DECR);
3438 renderState = D3DRS_STENCILFAIL;
3439 val = pRenderState[i].uintValue;
3440 break;
3441
3442 case SVGA3D_RS_STENCILZFAIL: /* SVGA3dStencilOp - identical */
3443 renderState = D3DRS_STENCILZFAIL;
3444 val = pRenderState[i].uintValue;
3445 break;
3446
3447 case SVGA3D_RS_STENCILPASS: /* SVGA3dStencilOp - identical */
3448 renderState = D3DRS_STENCILPASS;
3449 val = pRenderState[i].uintValue;
3450 break;
3451
3452 case SVGA3D_RS_ALPHAREF: /* float (0.0 .. 1.0) */
3453 renderState = D3DRS_ALPHAREF;
3454 val = pRenderState[i].uintValue;
3455 break;
3456
3457 case SVGA3D_RS_FRONTWINDING: /* SVGA3dFrontWinding */
3458 Assert(pRenderState[i].uintValue == SVGA3D_FRONTWINDING_CW);
3459 /*
3460 renderState = D3DRS_FRONTWINDING; //D3DRS_TWOSIDEDSTENCILMODE
3461 val = pRenderState[i].uintValue;
3462 */
3463 break;
3464
3465 case SVGA3D_RS_COORDINATETYPE: /* SVGA3dCoordinateType */
3466 Assert(pRenderState[i].uintValue == SVGA3D_COORDINATE_LEFTHANDED);
3467 /** @todo setup a view matrix to scale the world space by -1 in the z-direction for right handed coordinates. */
3468 /*
3469 renderState = D3DRS_COORDINATETYPE;
3470 val = pRenderState[i].uintValue;
3471 */
3472 break;
3473
3474 case SVGA3D_RS_ZBIAS: /* float */
3475 /** @todo unknown meaning; depth bias is not identical
3476 renderState = D3DRS_DEPTHBIAS;
3477 val = pRenderState[i].uintValue;
3478 */
3479 Log(("vmsvga3dSetRenderState: WARNING unsupported SVGA3D_RS_ZBIAS\n"));
3480 break;
3481
3482 case SVGA3D_RS_SLOPESCALEDEPTHBIAS: /* float */
3483 renderState = D3DRS_SLOPESCALEDEPTHBIAS;
3484 val = pRenderState[i].uintValue;
3485 break;
3486
3487 case SVGA3D_RS_DEPTHBIAS: /* float */
3488 renderState = D3DRS_DEPTHBIAS;
3489 val = pRenderState[i].uintValue;
3490 break;
3491
3492 case SVGA3D_RS_COLORWRITEENABLE: /* SVGA3dColorMask - identical to D3DCOLORWRITEENABLE_* */
3493 renderState = D3DRS_COLORWRITEENABLE;
3494 val = pRenderState[i].uintValue;
3495 break;
3496
3497 case SVGA3D_RS_VERTEXMATERIALENABLE: /* SVGA3dBool */
3498 //AssertFailed();
3499 renderState = D3DRS_INDEXEDVERTEXBLENDENABLE; /* correct?? */
3500 val = pRenderState[i].uintValue;
3501 break;
3502
3503 case SVGA3D_RS_DIFFUSEMATERIALSOURCE: /* SVGA3dVertexMaterial - identical */
3504 AssertCompile(D3DMCS_COLOR2 == SVGA3D_VERTEXMATERIAL_SPECULAR);
3505 renderState = D3DRS_DIFFUSEMATERIALSOURCE;
3506 val = pRenderState[i].uintValue;
3507 break;
3508
3509 case SVGA3D_RS_SPECULARMATERIALSOURCE: /* SVGA3dVertexMaterial - identical */
3510 renderState = D3DRS_SPECULARMATERIALSOURCE;
3511 val = pRenderState[i].uintValue;
3512 break;
3513
3514 case SVGA3D_RS_AMBIENTMATERIALSOURCE: /* SVGA3dVertexMaterial - identical */
3515 renderState = D3DRS_AMBIENTMATERIALSOURCE;
3516 val = pRenderState[i].uintValue;
3517 break;
3518
3519 case SVGA3D_RS_EMISSIVEMATERIALSOURCE: /* SVGA3dVertexMaterial - identical */
3520 renderState = D3DRS_EMISSIVEMATERIALSOURCE;
3521 val = pRenderState[i].uintValue;
3522 break;
3523
3524 case SVGA3D_RS_TEXTUREFACTOR: /* SVGA3dColor - identical */
3525 renderState = D3DRS_TEXTUREFACTOR;
3526 val = pRenderState[i].uintValue;
3527 break;
3528
3529 case SVGA3D_RS_LOCALVIEWER: /* SVGA3dBool */
3530 renderState = D3DRS_LOCALVIEWER;
3531 val = pRenderState[i].uintValue;
3532 break;
3533
3534 case SVGA3D_RS_SCISSORTESTENABLE: /* SVGA3dBool */
3535 renderState = D3DRS_SCISSORTESTENABLE;
3536 val = pRenderState[i].uintValue;
3537 break;
3538
3539 case SVGA3D_RS_BLENDCOLOR: /* SVGA3dColor - identical */
3540 renderState = D3DRS_BLENDFACTOR;
3541 val = pRenderState[i].uintValue;
3542 break;
3543
3544 case SVGA3D_RS_STENCILENABLE2SIDED: /* SVGA3dBool */
3545 renderState = D3DRS_TWOSIDEDSTENCILMODE;
3546 val = pRenderState[i].uintValue;
3547 break;
3548
3549 case SVGA3D_RS_CCWSTENCILFUNC: /* SVGA3dCmpFunc - identical */
3550 renderState = D3DRS_CCW_STENCILFUNC;
3551 val = pRenderState[i].uintValue;
3552 break;
3553
3554 case SVGA3D_RS_CCWSTENCILFAIL: /* SVGA3dStencilOp - identical */
3555 renderState = D3DRS_CCW_STENCILFAIL;
3556 val = pRenderState[i].uintValue;
3557 break;
3558
3559 case SVGA3D_RS_CCWSTENCILZFAIL: /* SVGA3dStencilOp - identical */
3560 renderState = D3DRS_CCW_STENCILZFAIL;
3561 val = pRenderState[i].uintValue;
3562 break;
3563
3564 case SVGA3D_RS_CCWSTENCILPASS: /* SVGA3dStencilOp - identical */
3565 renderState = D3DRS_CCW_STENCILPASS;
3566 val = pRenderState[i].uintValue;
3567 break;
3568
3569 case SVGA3D_RS_VERTEXBLEND: /* SVGA3dVertexBlendFlags - identical */
3570 AssertCompile(SVGA3D_VBLEND_DISABLE == D3DVBF_DISABLE);
3571 renderState = D3DRS_VERTEXBLEND;
3572 val = pRenderState[i].uintValue;
3573 break;
3574
3575 case SVGA3D_RS_OUTPUTGAMMA: /* float */
3576 //AssertFailed();
3577 /*
3578 D3DRS_SRGBWRITEENABLE ??
3579 renderState = D3DRS_OUTPUTGAMMA;
3580 val = pRenderState[i].uintValue;
3581 */
3582 break;
3583
3584 case SVGA3D_RS_ZVISIBLE: /* SVGA3dBool */
3585 AssertFailed();
3586 /*
3587 renderState = D3DRS_ZVISIBLE;
3588 val = pRenderState[i].uintValue;
3589 */
3590 break;
3591
3592 case SVGA3D_RS_LASTPIXEL: /* SVGA3dBool */
3593 renderState = D3DRS_LASTPIXEL;
3594 val = pRenderState[i].uintValue;
3595 break;
3596
3597 case SVGA3D_RS_CLIPPING: /* SVGA3dBool */
3598 renderState = D3DRS_CLIPPING;
3599 val = pRenderState[i].uintValue;
3600 break;
3601
3602 case SVGA3D_RS_WRAP0: /* SVGA3dWrapFlags - identical */
3603 Assert(SVGA3D_WRAPCOORD_3 == D3DWRAPCOORD_3);
3604 renderState = D3DRS_WRAP0;
3605 val = pRenderState[i].uintValue;
3606 break;
3607
3608 case SVGA3D_RS_WRAP1: /* SVGA3dWrapFlags - identical */
3609 renderState = D3DRS_WRAP1;
3610 val = pRenderState[i].uintValue;
3611 break;
3612
3613 case SVGA3D_RS_WRAP2: /* SVGA3dWrapFlags - identical */
3614 renderState = D3DRS_WRAP2;
3615 val = pRenderState[i].uintValue;
3616 break;
3617
3618 case SVGA3D_RS_WRAP3: /* SVGA3dWrapFlags - identical */
3619 renderState = D3DRS_WRAP3;
3620 val = pRenderState[i].uintValue;
3621 break;
3622
3623 case SVGA3D_RS_WRAP4: /* SVGA3dWrapFlags - identical */
3624 renderState = D3DRS_WRAP4;
3625 val = pRenderState[i].uintValue;
3626 break;
3627
3628 case SVGA3D_RS_WRAP5: /* SVGA3dWrapFlags - identical */
3629 renderState = D3DRS_WRAP5;
3630 val = pRenderState[i].uintValue;
3631 break;
3632
3633 case SVGA3D_RS_WRAP6: /* SVGA3dWrapFlags - identical */
3634 renderState = D3DRS_WRAP6;
3635 val = pRenderState[i].uintValue;
3636 break;
3637
3638 case SVGA3D_RS_WRAP7: /* SVGA3dWrapFlags - identical */
3639 renderState = D3DRS_WRAP7;
3640 val = pRenderState[i].uintValue;
3641 break;
3642
3643 case SVGA3D_RS_WRAP8: /* SVGA3dWrapFlags - identical */
3644 renderState = D3DRS_WRAP8;
3645 val = pRenderState[i].uintValue;
3646 break;
3647
3648 case SVGA3D_RS_WRAP9: /* SVGA3dWrapFlags - identical */
3649 renderState = D3DRS_WRAP9;
3650 val = pRenderState[i].uintValue;
3651 break;
3652
3653 case SVGA3D_RS_WRAP10: /* SVGA3dWrapFlags - identical */
3654 renderState = D3DRS_WRAP10;
3655 val = pRenderState[i].uintValue;
3656 break;
3657
3658 case SVGA3D_RS_WRAP11: /* SVGA3dWrapFlags - identical */
3659 renderState = D3DRS_WRAP11;
3660 val = pRenderState[i].uintValue;
3661 break;
3662
3663 case SVGA3D_RS_WRAP12: /* SVGA3dWrapFlags - identical */
3664 renderState = D3DRS_WRAP12;
3665 val = pRenderState[i].uintValue;
3666 break;
3667
3668 case SVGA3D_RS_WRAP13: /* SVGA3dWrapFlags - identical */
3669 renderState = D3DRS_WRAP13;
3670 val = pRenderState[i].uintValue;
3671 break;
3672
3673 case SVGA3D_RS_WRAP14: /* SVGA3dWrapFlags - identical */
3674 renderState = D3DRS_WRAP14;
3675 val = pRenderState[i].uintValue;
3676 break;
3677
3678 case SVGA3D_RS_WRAP15: /* SVGA3dWrapFlags - identical */
3679 renderState = D3DRS_WRAP15;
3680 val = pRenderState[i].uintValue;
3681 break;
3682
3683 case SVGA3D_RS_MULTISAMPLEANTIALIAS: /* SVGA3dBool */
3684 renderState = D3DRS_MULTISAMPLEANTIALIAS;
3685 val = pRenderState[i].uintValue;
3686 break;
3687
3688 case SVGA3D_RS_MULTISAMPLEMASK: /* uint32_t */
3689 renderState = D3DRS_MULTISAMPLEMASK;
3690 val = pRenderState[i].uintValue;
3691 break;
3692
3693 case SVGA3D_RS_INDEXEDVERTEXBLENDENABLE: /* SVGA3dBool */
3694 renderState = D3DRS_INDEXEDVERTEXBLENDENABLE;
3695 val = pRenderState[i].uintValue;
3696 break;
3697
3698 case SVGA3D_RS_TWEENFACTOR: /* float */
3699 renderState = D3DRS_TWEENFACTOR;
3700 val = pRenderState[i].uintValue;
3701 break;
3702
3703 case SVGA3D_RS_ANTIALIASEDLINEENABLE: /* SVGA3dBool */
3704 renderState = D3DRS_ANTIALIASEDLINEENABLE;
3705 val = pRenderState[i].uintValue;
3706 break;
3707
3708 case SVGA3D_RS_COLORWRITEENABLE1: /* SVGA3dColorMask - identical to D3DCOLORWRITEENABLE_* */
3709 renderState = D3DRS_COLORWRITEENABLE1;
3710 val = pRenderState[i].uintValue;
3711 break;
3712
3713 case SVGA3D_RS_COLORWRITEENABLE2: /* SVGA3dColorMask - identical to D3DCOLORWRITEENABLE_* */
3714 renderState = D3DRS_COLORWRITEENABLE2;
3715 val = pRenderState[i].uintValue;
3716 break;
3717
3718 case SVGA3D_RS_COLORWRITEENABLE3: /* SVGA3dColorMask - identical to D3DCOLORWRITEENABLE_* */
3719 renderState = D3DRS_COLORWRITEENABLE3;
3720 val = pRenderState[i].uintValue;
3721 break;
3722
3723 case SVGA3D_RS_SEPARATEALPHABLENDENABLE: /* SVGA3dBool */
3724 renderState = D3DRS_SEPARATEALPHABLENDENABLE;
3725 val = pRenderState[i].uintValue;
3726 break;
3727
3728 case SVGA3D_RS_SRCBLENDALPHA: /* SVGA3dBlendOp */
3729 renderState = D3DRS_SRCBLENDALPHA;
3730 val = vmsvga3dBlendOp2D3D(pRenderState[i].uintValue, D3DBLEND_ONE /* default */);
3731 break;
3732
3733 case SVGA3D_RS_DSTBLENDALPHA: /* SVGA3dBlendOp */
3734 renderState = D3DRS_DESTBLENDALPHA;
3735 val = vmsvga3dBlendOp2D3D(pRenderState[i].uintValue, D3DBLEND_ZERO /* default */);
3736 break;
3737
3738 case SVGA3D_RS_BLENDEQUATIONALPHA: /* SVGA3dBlendEquation - identical */
3739 renderState = D3DRS_BLENDOPALPHA;
3740 val = pRenderState[i].uintValue;
3741 break;
3742
3743 case SVGA3D_RS_TRANSPARENCYANTIALIAS: /* SVGA3dTransparencyAntialiasType */
3744 AssertFailed();
3745 /*
3746 renderState = D3DRS_TRANSPARENCYANTIALIAS;
3747 val = pRenderState[i].uintValue;
3748 */
3749 break;
3750
3751 case SVGA3D_RS_LINEAA: /* SVGA3dBool */
3752 renderState = D3DRS_ANTIALIASEDLINEENABLE;
3753 val = pRenderState[i].uintValue;
3754 break;
3755
3756 case SVGA3D_RS_LINEWIDTH: /* float */
3757 AssertFailed();
3758 /*
3759 renderState = D3DRS_LINEWIDTH;
3760 val = pRenderState[i].uintValue;
3761 */
3762 break;
3763
3764 case SVGA3D_RS_MAX: /* shut up MSC */
3765 case SVGA3D_RS_INVALID:
3766 AssertFailedBreak();
3767 }
3768
3769 if (renderState != D3DRS_FORCE_DWORD)
3770 {
3771 hr = pContext->pDevice->SetRenderState(renderState, val);
3772 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSetRenderState: SetRenderState failed with %x\n", hr), VERR_INTERNAL_ERROR);
3773 }
3774 }
3775
3776 return VINF_SUCCESS;
3777}
3778
3779int vmsvga3dSetRenderTarget(PVGASTATE pThis, uint32_t cid, SVGA3dRenderTargetType type, SVGA3dSurfaceImageId target)
3780{
3781 HRESULT hr;
3782 PVMSVGA3DCONTEXT pContext;
3783 PVMSVGA3DSTATE pState = pThis->svga.p3dState;
3784 PVMSVGA3DSURFACE pRenderTarget;
3785
3786 AssertReturn(pState, VERR_NO_MEMORY);
3787 AssertReturn(type < SVGA3D_RT_MAX, VERR_INVALID_PARAMETER);
3788 AssertReturn(target.face == 0, VERR_INVALID_PARAMETER);
3789
3790 Log(("vmsvga3dSetRenderTarget cid=%x type=%x sid=%x\n", cid, type, target.sid));
3791
3792 if ( cid >= pState->cContexts
3793 || pState->papContexts[cid]->id != cid)
3794 {
3795 Log(("vmsvga3dSetRenderTarget invalid context id!\n"));
3796 return VERR_INVALID_PARAMETER;
3797 }
3798 pContext = pState->papContexts[cid];
3799
3800 /* Save for vm state save/restore. */
3801 pContext->state.aRenderTargets[type] = target.sid;
3802
3803 if (target.sid == SVGA3D_INVALID_ID)
3804 {
3805 /* Disable render target. */
3806 switch (type)
3807 {
3808 case SVGA3D_RT_DEPTH:
3809 hr = pContext->pDevice->SetDepthStencilSurface(NULL);
3810 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSetRenderTarget: SetDepthStencilSurface failed with %x\n", hr), VERR_INTERNAL_ERROR);
3811 break;
3812
3813 case SVGA3D_RT_STENCIL:
3814 /* ignore; correct?? */
3815 break;
3816
3817 case SVGA3D_RT_COLOR0:
3818 case SVGA3D_RT_COLOR1:
3819 case SVGA3D_RT_COLOR2:
3820 case SVGA3D_RT_COLOR3:
3821 case SVGA3D_RT_COLOR4:
3822 case SVGA3D_RT_COLOR5:
3823 case SVGA3D_RT_COLOR6:
3824 case SVGA3D_RT_COLOR7:
3825 pContext->sidRenderTarget = SVGA3D_INVALID_ID;
3826
3827 if (pState->fSupportedSurfaceNULL)
3828 {
3829 /* Create a dummy render target to satisfy D3D. This path is usually taken only to render into a depth buffer without
3830 * wishing to update an actual color render target
3831 */
3832 IDirect3DSurface9* pDummyRenderTarget;
3833 hr = pContext->pDevice->CreateRenderTarget(pThis->svga.uWidth,
3834 pThis->svga.uHeight,
3835 FOURCC_NULL,
3836 D3DMULTISAMPLE_NONE,
3837 0,
3838 FALSE,
3839 &pDummyRenderTarget,
3840 NULL);
3841
3842 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSetRenderTarget: CreateRenderTarget failed with %x\n", hr), VERR_INTERNAL_ERROR);
3843
3844 hr = pContext->pDevice->SetRenderTarget(type - SVGA3D_RT_COLOR0, pDummyRenderTarget);
3845 pDummyRenderTarget->Release();
3846 }
3847 else
3848 hr = pContext->pDevice->SetRenderTarget(type - SVGA3D_RT_COLOR0, NULL);
3849
3850 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSetRenderTarget: SetRenderTarget failed with %x\n", hr), VERR_INTERNAL_ERROR);
3851 break;
3852
3853 default:
3854 AssertFailedReturn(VERR_INVALID_PARAMETER);
3855 }
3856 return VINF_SUCCESS;
3857 }
3858
3859 AssertReturn(target.sid < SVGA3D_MAX_SURFACE_IDS, VERR_INVALID_PARAMETER);
3860 AssertReturn(target.sid < pState->cSurfaces && pState->papSurfaces[target.sid]->id == target.sid, VERR_INVALID_PARAMETER);
3861 pRenderTarget = pState->papSurfaces[target.sid];
3862
3863 switch (type)
3864 {
3865 case SVGA3D_RT_DEPTH:
3866 case SVGA3D_RT_STENCIL:
3867 AssertReturn(target.mipmap == 0, VERR_INVALID_PARAMETER);
3868 if (!pRenderTarget->u.pSurface)
3869 {
3870 DWORD cQualityLevels = 0;
3871
3872 /* Query the nr of quality levels for this particular format */
3873 if (pRenderTarget->multiSampleTypeD3D != D3DMULTISAMPLE_NONE)
3874 {
3875 hr = pState->pD3D9->CheckDeviceMultiSampleType(D3DADAPTER_DEFAULT,
3876 D3DDEVTYPE_HAL,
3877 pRenderTarget->formatD3D,
3878 TRUE, /* Windowed */
3879 pRenderTarget->multiSampleTypeD3D,
3880 &cQualityLevels);
3881 Assert(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE);
3882 }
3883
3884 if ( pState->fSupportedSurfaceINTZ
3885 && pRenderTarget->multiSampleTypeD3D == D3DMULTISAMPLE_NONE
3886 && ( pRenderTarget->formatD3D == D3DFMT_D24S8
3887 || pRenderTarget->formatD3D == D3DFMT_D24X8))
3888 {
3889 Log(("vmsvga3dSetRenderTarget: Creating stencil surface as texture!\n"));
3890 int rc = vmsvga3dBackCreateTexture(pState, pContext, cid, pRenderTarget);
3891 AssertRC(rc); /* non-fatal */
3892 }
3893
3894 if (!pRenderTarget->fStencilAsTexture)
3895 {
3896 Log(("vmsvga3dSetRenderTarget DEPTH/STENCIL; cQualityLevels=%d\n", cQualityLevels));
3897 hr = pContext->pDevice->CreateDepthStencilSurface(pRenderTarget->pMipmapLevels[0].size.width,
3898 pRenderTarget->pMipmapLevels[0].size.height,
3899 pRenderTarget->formatD3D,
3900 pRenderTarget->multiSampleTypeD3D,
3901 ((cQualityLevels >= 1) ? cQualityLevels - 1 : 0), /* 0 - (levels-1) */
3902 FALSE, /* not discardable */
3903 &pRenderTarget->u.pSurface,
3904 NULL);
3905 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSetRenderTarget: CreateDepthStencilSurface failed with %x\n", hr), VERR_INTERNAL_ERROR);
3906 }
3907
3908 pRenderTarget->idAssociatedContext = cid;
3909
3910#if 0 /* doesn't work */
3911 if ( !pRenderTarget->fStencilAsTexture
3912 && pRenderTarget->fDirty)
3913 {
3914 Log(("vmsvga3dSetRenderTarget: sync dirty depth/stencil buffer\n"));
3915 Assert(pRenderTarget->faces[0].numMipLevels == 1);
3916
3917 for (uint32_t i = 0; i < pRenderTarget->faces[0].numMipLevels; i++)
3918 {
3919 if (pRenderTarget->pMipmapLevels[i].fDirty)
3920 {
3921 D3DLOCKED_RECT LockedRect;
3922
3923 hr = pRenderTarget->u.pSurface->LockRect(&LockedRect,
3924 NULL, /* entire surface */
3925 0);
3926
3927 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSetRenderTarget: LockRect failed with %x\n", hr), VERR_INTERNAL_ERROR);
3928
3929 Log(("vmsvga3dSetRenderTarget: sync dirty texture mipmap level %d (pitch %x vs %x)\n", i, LockedRect.Pitch, pRenderTarget->pMipmapLevels[i].cbSurfacePitch));
3930
3931 uint8_t *pDest = (uint8_t *)LockedRect.pBits;
3932 uint8_t *pSrc = (uint8_t *)pRenderTarget->pMipmapLevels[i].pSurfaceData;
3933 for (uint32_t j = 0; j < pRenderTarget->pMipmapLevels[i].size.height; j++)
3934 {
3935 memcpy(pDest, pSrc, pRenderTarget->pMipmapLevels[i].cbSurfacePitch);
3936
3937 pDest += LockedRect.Pitch;
3938 pSrc += pRenderTarget->pMipmapLevels[i].cbSurfacePitch;
3939 }
3940
3941 hr = pRenderTarget->u.pSurface->UnlockRect();
3942 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSetRenderTarget: UnlockRect failed with %x\n", hr), VERR_INTERNAL_ERROR);
3943
3944 pRenderTarget->pMipmapLevels[i].fDirty = false;
3945 }
3946 }
3947 }
3948#endif
3949 }
3950 Assert(pRenderTarget->idAssociatedContext == cid);
3951
3952 /** @todo Assert(!pRenderTarget->fDirty); */
3953
3954 AssertReturn(pRenderTarget->u.pSurface, VERR_INVALID_PARAMETER);
3955
3956 pRenderTarget->fUsageD3D |= D3DUSAGE_DEPTHSTENCIL;
3957 pRenderTarget->flags |= SVGA3D_SURFACE_HINT_DEPTHSTENCIL;
3958
3959 if (pRenderTarget->fStencilAsTexture)
3960 {
3961 IDirect3DSurface9 *pStencilSurface;
3962
3963 hr = pRenderTarget->u.pTexture->GetSurfaceLevel(0, &pStencilSurface);
3964 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSetRenderTarget: GetSurfaceLevel failed with %x\n", hr), VERR_INTERNAL_ERROR);
3965
3966 hr = pContext->pDevice->SetDepthStencilSurface(pStencilSurface);
3967 pStencilSurface->Release();
3968 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSetRenderTarget: SetDepthStencilSurface failed with %x\n", hr), VERR_INTERNAL_ERROR);
3969 }
3970 else
3971 {
3972 hr = pContext->pDevice->SetDepthStencilSurface(pRenderTarget->u.pSurface);
3973 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSetRenderTarget: SetDepthStencilSurface failed with %x\n", hr), VERR_INTERNAL_ERROR);
3974 }
3975 break;
3976
3977 case SVGA3D_RT_COLOR0:
3978 case SVGA3D_RT_COLOR1:
3979 case SVGA3D_RT_COLOR2:
3980 case SVGA3D_RT_COLOR3:
3981 case SVGA3D_RT_COLOR4:
3982 case SVGA3D_RT_COLOR5:
3983 case SVGA3D_RT_COLOR6:
3984 case SVGA3D_RT_COLOR7:
3985 {
3986 IDirect3DSurface9 *pSurface;
3987 bool fTexture = false;
3988 bool fShared = false;
3989
3990 /* Must flush the other context's 3d pipeline to make sure all drawing is complete for the surface we're about to use. */
3991 vmsvga3dSurfaceFlush(pThis, pRenderTarget);
3992
3993 if (pRenderTarget->flags & SVGA3D_SURFACE_HINT_TEXTURE)
3994 {
3995 fTexture = true;
3996
3997 /* A texture surface can be used as a render target to fill it and later on used as a texture. */
3998 if (!pRenderTarget->u.pTexture)
3999 {
4000 Log(("vmsvga3dSetRenderTarget: create texture to be used as render target; sid=%x type=%d format=%d -> create texture\n", target.sid, pRenderTarget->flags, pRenderTarget->format));
4001 int rc = vmsvga3dBackCreateTexture(pState, pContext, cid, pRenderTarget);
4002 AssertRCReturn(rc, rc);
4003 }
4004
4005#ifndef VBOX_VMSVGA3D_WITH_WINE_OPENGL
4006 if (pRenderTarget->idAssociatedContext != cid)
4007 {
4008 Log(("vmsvga3dSetRenderTarget; using texture sid=%x created for another context (%d vs %d)\n", target.sid, pRenderTarget->idAssociatedContext, cid));
4009
4010 PVMSVGA3DSHAREDSURFACE pSharedSurface = vmsvga3dSurfaceGetSharedCopy(pThis, pContext, pRenderTarget);
4011 AssertReturn(pSharedSurface, VERR_INTERNAL_ERROR);
4012
4013 hr = pSharedSurface->u.pTexture->GetSurfaceLevel(target.mipmap,
4014 &pSurface);
4015
4016 fShared = true;
4017 }
4018 else
4019#endif
4020 hr = pRenderTarget->u.pTexture->GetSurfaceLevel(target.mipmap,
4021 &pSurface);
4022
4023 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSetRenderTarget: GetSurfaceLevel failed with %x\n", hr), VERR_INTERNAL_ERROR);
4024 }
4025 else
4026 {
4027 AssertReturn(target.mipmap == 0, VERR_INVALID_PARAMETER);
4028 if (!pRenderTarget->u.pSurface)
4029 {
4030 DWORD cQualityLevels = 0;
4031
4032 /* Query the nr of quality levels for this particular format */
4033 if (pRenderTarget->multiSampleTypeD3D != D3DMULTISAMPLE_NONE)
4034 {
4035 hr = pState->pD3D9->CheckDeviceMultiSampleType(D3DADAPTER_DEFAULT,
4036 D3DDEVTYPE_HAL,
4037 pRenderTarget->formatD3D,
4038 TRUE, /* Windowed */
4039 pRenderTarget->multiSampleTypeD3D,
4040 &cQualityLevels);
4041 Assert(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE);
4042 }
4043
4044 Log(("vmsvga3dSetRenderTarget COLOR; cQualityLevels=%d\n", cQualityLevels));
4045 Log(("Create rendertarget (%d,%d) format=%x multisample=%x\n", pRenderTarget->pMipmapLevels[0].size.width, pRenderTarget->pMipmapLevels[0].size.height, pRenderTarget->formatD3D, pRenderTarget->multiSampleTypeD3D));
4046
4047 hr = pContext->pDevice->CreateRenderTarget(pRenderTarget->pMipmapLevels[0].size.width,
4048 pRenderTarget->pMipmapLevels[0].size.height,
4049 pRenderTarget->formatD3D,
4050 pRenderTarget->multiSampleTypeD3D,
4051 ((cQualityLevels >= 1) ? cQualityLevels - 1 : 0), /* 0 - (levels-1) */
4052 TRUE, /* lockable */
4053 &pRenderTarget->u.pSurface,
4054 NULL);
4055 AssertReturn(hr == D3D_OK, VERR_INTERNAL_ERROR);
4056
4057 pRenderTarget->idAssociatedContext = cid;
4058 }
4059 else
4060 AssertReturn(pRenderTarget->fUsageD3D & D3DUSAGE_RENDERTARGET, VERR_INVALID_PARAMETER);
4061
4062 Assert(pRenderTarget->idAssociatedContext == cid);
4063 pSurface = pRenderTarget->u.pSurface;
4064 }
4065
4066 AssertReturn(pRenderTarget->u.pSurface, VERR_INVALID_PARAMETER);
4067 Assert(!pRenderTarget->fDirty);
4068
4069 pRenderTarget->fUsageD3D |= D3DUSAGE_RENDERTARGET;
4070 pRenderTarget->flags |= SVGA3D_SURFACE_HINT_RENDERTARGET;
4071
4072 hr = pContext->pDevice->SetRenderTarget(type - SVGA3D_RT_COLOR0, pSurface);
4073 if (fTexture)
4074 pSurface->Release(); /* Release reference to texture level 0 */
4075 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSetRenderTarget: SetRenderTarget failed with %x\n", hr), VERR_INTERNAL_ERROR);
4076
4077 pContext->sidRenderTarget = target.sid;
4078
4079 /* Changing the render target resets the viewport; restore it here. */
4080 if (pContext->state.u32UpdateFlags & VMSVGA3D_UPDATE_VIEWPORT)
4081 vmsvga3dSetViewPort(pThis, cid, &pContext->state.RectViewPort);
4082 /* Changing the render target also resets the scissor rectangle; restore it as well. */
4083 if (pContext->state.u32UpdateFlags & VMSVGA3D_UPDATE_SCISSORRECT)
4084 vmsvga3dSetScissorRect(pThis, cid, &pContext->state.RectScissor);
4085
4086 break;
4087 }
4088
4089 default:
4090 AssertFailedReturn(VERR_INVALID_PARAMETER);
4091 }
4092
4093 return VINF_SUCCESS;
4094}
4095
4096/**
4097 * Convert SVGA texture combiner value to its D3D equivalent
4098 */
4099static DWORD vmsvga3dTextureCombiner2D3D(uint32_t value)
4100{
4101 switch (value)
4102 {
4103 case SVGA3D_TC_DISABLE:
4104 return D3DTOP_DISABLE;
4105 case SVGA3D_TC_SELECTARG1:
4106 return D3DTOP_SELECTARG1;
4107 case SVGA3D_TC_SELECTARG2:
4108 return D3DTOP_SELECTARG2;
4109 case SVGA3D_TC_MODULATE:
4110 return D3DTOP_MODULATE;
4111 case SVGA3D_TC_ADD:
4112 return D3DTOP_ADD;
4113 case SVGA3D_TC_ADDSIGNED:
4114 return D3DTOP_ADDSIGNED;
4115 case SVGA3D_TC_SUBTRACT:
4116 return D3DTOP_SUBTRACT;
4117 case SVGA3D_TC_BLENDTEXTUREALPHA:
4118 return D3DTOP_BLENDTEXTUREALPHA;
4119 case SVGA3D_TC_BLENDDIFFUSEALPHA:
4120 return D3DTOP_BLENDDIFFUSEALPHA;
4121 case SVGA3D_TC_BLENDCURRENTALPHA:
4122 return D3DTOP_BLENDCURRENTALPHA;
4123 case SVGA3D_TC_BLENDFACTORALPHA:
4124 return D3DTOP_BLENDFACTORALPHA;
4125 case SVGA3D_TC_MODULATE2X:
4126 return D3DTOP_MODULATE2X;
4127 case SVGA3D_TC_MODULATE4X:
4128 return D3DTOP_MODULATE4X;
4129 case SVGA3D_TC_DSDT:
4130 AssertFailed(); /** @todo ??? */
4131 return D3DTOP_DISABLE;
4132 case SVGA3D_TC_DOTPRODUCT3:
4133 return D3DTOP_DOTPRODUCT3;
4134 case SVGA3D_TC_BLENDTEXTUREALPHAPM:
4135 return D3DTOP_BLENDTEXTUREALPHAPM;
4136 case SVGA3D_TC_ADDSIGNED2X:
4137 return D3DTOP_ADDSIGNED2X;
4138 case SVGA3D_TC_ADDSMOOTH:
4139 return D3DTOP_ADDSMOOTH;
4140 case SVGA3D_TC_PREMODULATE:
4141 return D3DTOP_PREMODULATE;
4142 case SVGA3D_TC_MODULATEALPHA_ADDCOLOR:
4143 return D3DTOP_MODULATEALPHA_ADDCOLOR;
4144 case SVGA3D_TC_MODULATECOLOR_ADDALPHA:
4145 return D3DTOP_MODULATECOLOR_ADDALPHA;
4146 case SVGA3D_TC_MODULATEINVALPHA_ADDCOLOR:
4147 return D3DTOP_MODULATEINVALPHA_ADDCOLOR;
4148 case SVGA3D_TC_MODULATEINVCOLOR_ADDALPHA:
4149 return D3DTOP_MODULATEINVCOLOR_ADDALPHA;
4150 case SVGA3D_TC_BUMPENVMAPLUMINANCE:
4151 return D3DTOP_BUMPENVMAPLUMINANCE;
4152 case SVGA3D_TC_MULTIPLYADD:
4153 return D3DTOP_MULTIPLYADD;
4154 case SVGA3D_TC_LERP:
4155 return D3DTOP_LERP;
4156 default:
4157 AssertFailed();
4158 return D3DTOP_DISABLE;
4159 }
4160}
4161
4162/**
4163 * Convert SVGA texture arg data value to its D3D equivalent
4164 */
4165static DWORD vmsvga3dTextureArgData2D3D(uint32_t value)
4166{
4167 switch (value)
4168 {
4169 case SVGA3D_TA_CONSTANT:
4170 return D3DTA_CONSTANT;
4171 case SVGA3D_TA_PREVIOUS:
4172 return D3DTA_CURRENT; /* current = previous */
4173 case SVGA3D_TA_DIFFUSE:
4174 return D3DTA_DIFFUSE;
4175 case SVGA3D_TA_TEXTURE:
4176 return D3DTA_TEXTURE;
4177 case SVGA3D_TA_SPECULAR:
4178 return D3DTA_SPECULAR;
4179 default:
4180 AssertFailed();
4181 return 0;
4182 }
4183}
4184
4185/**
4186 * Convert SVGA texture transform flag value to its D3D equivalent
4187 */
4188static DWORD vmsvga3dTextTransformFlags2D3D(uint32_t value)
4189{
4190 switch (value)
4191 {
4192 case SVGA3D_TEX_TRANSFORM_OFF:
4193 return D3DTTFF_DISABLE;
4194 case SVGA3D_TEX_TRANSFORM_S:
4195 return D3DTTFF_COUNT1; /** @todo correct? */
4196 case SVGA3D_TEX_TRANSFORM_T:
4197 return D3DTTFF_COUNT2; /** @todo correct? */
4198 case SVGA3D_TEX_TRANSFORM_R:
4199 return D3DTTFF_COUNT3; /** @todo correct? */
4200 case SVGA3D_TEX_TRANSFORM_Q:
4201 return D3DTTFF_COUNT4; /** @todo correct? */
4202 case SVGA3D_TEX_PROJECTED:
4203 return D3DTTFF_PROJECTED;
4204 default:
4205 AssertFailed();
4206 return 0;
4207 }
4208}
4209
4210int vmsvga3dSetTextureState(PVGASTATE pThis, uint32_t cid, uint32_t cTextureStates, SVGA3dTextureState *pTextureState)
4211{
4212 DWORD val = 0; /* Shut up MSC */
4213 HRESULT hr;
4214 PVMSVGA3DCONTEXT pContext;
4215 PVMSVGA3DSTATE pState = pThis->svga.p3dState;
4216 AssertReturn(pState, VERR_NO_MEMORY);
4217
4218 Log(("vmsvga3dSetTextureState %x cTextureState=%d\n", cid, cTextureStates));
4219
4220 if ( cid >= pState->cContexts
4221 || pState->papContexts[cid]->id != cid)
4222 {
4223 Log(("vmsvga3dSetTextureState invalid context id!\n"));
4224 return VERR_INVALID_PARAMETER;
4225 }
4226 pContext = pState->papContexts[cid];
4227
4228 for (unsigned i = 0; i < cTextureStates; i++)
4229 {
4230 D3DTEXTURESTAGESTATETYPE textureType = D3DTSS_FORCE_DWORD;
4231 D3DSAMPLERSTATETYPE samplerType = D3DSAMP_FORCE_DWORD;
4232 uint32_t currentStage = pTextureState[i].stage;
4233
4234 Log(("vmsvga3dSetTextureState: cid=%x stage=%d type=%s (%x) val=%x\n", cid, currentStage, vmsvga3dTextureStateToString(pTextureState[i].name), pTextureState[i].name, pTextureState[i].value));
4235
4236 /** @todo Is this the appropriate limit for all kinds of textures? It is the
4237 * size of aSidActiveTexture and for binding/unbinding we cannot exceed it. */
4238 if (RT_UNLIKELY(currentStage >= SVGA3D_MAX_TEXTURE_STAGE))
4239 {
4240 AssertMsgFailed(("pTextureState[%d].stage=%#x name=%#x\n", i, pTextureState[i].stage, pTextureState[i].name));
4241 continue;
4242 }
4243
4244 /* Record the texture state for vm state saving. */
4245 if ( currentStage < SVGA3D_MAX_TEXTURE_STAGE
4246 && pTextureState[i].name < SVGA3D_TS_MAX)
4247 {
4248 pContext->state.aTextureState[currentStage][pTextureState[i].name] = pTextureState[i];
4249 }
4250
4251 switch (pTextureState[i].name)
4252 {
4253 case SVGA3D_TS_COLOROP: /* SVGA3dTextureCombiner */
4254 textureType = D3DTSS_COLOROP;
4255 val = vmsvga3dTextureCombiner2D3D(pTextureState[i].value);
4256 break;
4257
4258 case SVGA3D_TS_COLORARG0: /* SVGA3dTextureArgData */
4259 textureType = D3DTSS_COLORARG0;
4260 val = vmsvga3dTextureArgData2D3D(pTextureState[i].value);
4261 break;
4262
4263 case SVGA3D_TS_COLORARG1: /* SVGA3dTextureArgData */
4264 textureType = D3DTSS_COLORARG1;
4265 val = vmsvga3dTextureArgData2D3D(pTextureState[i].value);
4266 break;
4267
4268 case SVGA3D_TS_COLORARG2: /* SVGA3dTextureArgData */
4269 textureType = D3DTSS_COLORARG2;
4270 val = vmsvga3dTextureArgData2D3D(pTextureState[i].value);
4271 break;
4272
4273 case SVGA3D_TS_ALPHAOP: /* SVGA3dTextureCombiner */
4274 textureType = D3DTSS_ALPHAOP;
4275 val = vmsvga3dTextureCombiner2D3D(pTextureState[i].value);
4276 break;
4277
4278 case SVGA3D_TS_ALPHAARG0: /* SVGA3dTextureArgData */
4279 textureType = D3DTSS_ALPHAARG0;
4280 val = vmsvga3dTextureArgData2D3D(pTextureState[i].value);
4281 break;
4282
4283 case SVGA3D_TS_ALPHAARG1: /* SVGA3dTextureArgData */
4284 textureType = D3DTSS_ALPHAARG1;
4285 val = vmsvga3dTextureArgData2D3D(pTextureState[i].value);
4286 break;
4287
4288 case SVGA3D_TS_ALPHAARG2: /* SVGA3dTextureArgData */
4289 textureType = D3DTSS_ALPHAARG2;
4290 val = vmsvga3dTextureArgData2D3D(pTextureState[i].value);
4291 break;
4292
4293 case SVGA3D_TS_BUMPENVMAT00: /* float */
4294 textureType = D3DTSS_BUMPENVMAT00;
4295 val = pTextureState[i].value;
4296 break;
4297
4298 case SVGA3D_TS_BUMPENVMAT01: /* float */
4299 textureType = D3DTSS_BUMPENVMAT01;
4300 val = pTextureState[i].value;
4301 break;
4302
4303 case SVGA3D_TS_BUMPENVMAT10: /* float */
4304 textureType = D3DTSS_BUMPENVMAT10;
4305 val = pTextureState[i].value;
4306 break;
4307
4308 case SVGA3D_TS_BUMPENVMAT11: /* float */
4309 textureType = D3DTSS_BUMPENVMAT11;
4310 val = pTextureState[i].value;
4311 break;
4312
4313 case SVGA3D_TS_TEXCOORDINDEX: /* uint32_t */
4314 textureType = D3DTSS_TEXCOORDINDEX;
4315 val = pTextureState[i].value;
4316 break;
4317
4318 case SVGA3D_TS_BUMPENVLSCALE: /* float */
4319 textureType = D3DTSS_BUMPENVLSCALE;
4320 val = pTextureState[i].value;
4321 break;
4322
4323 case SVGA3D_TS_BUMPENVLOFFSET: /* float */
4324 textureType = D3DTSS_BUMPENVLOFFSET;
4325 val = pTextureState[i].value;
4326 break;
4327
4328 case SVGA3D_TS_TEXTURETRANSFORMFLAGS: /* SVGA3dTexTransformFlags */
4329 textureType = D3DTSS_TEXTURETRANSFORMFLAGS;
4330 val = vmsvga3dTextTransformFlags2D3D(pTextureState[i].value);
4331 break;
4332
4333 case SVGA3D_TS_BIND_TEXTURE: /* SVGA3dSurfaceId */
4334 if (pTextureState[i].value == SVGA3D_INVALID_ID)
4335 {
4336 Log(("SVGA3D_TS_BIND_TEXTURE: stage %d, texture sid=%x\n", currentStage, pTextureState[i].value));
4337
4338 pContext->aSidActiveTexture[currentStage] = SVGA3D_INVALID_ID;
4339 /* Unselect the currently associated texture. */
4340 hr = pContext->pDevice->SetTexture(currentStage, NULL);
4341 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSetTextureState: SetTexture failed with %x\n", hr), VERR_INTERNAL_ERROR);
4342 }
4343 else
4344 {
4345 HRESULT hr;
4346 uint32_t sid = pTextureState[i].value;
4347
4348 AssertReturn(sid < SVGA3D_MAX_SURFACE_IDS, VERR_INVALID_PARAMETER);
4349 AssertReturn(sid < pState->cSurfaces && pState->papSurfaces[sid]->id == sid, VERR_INVALID_PARAMETER);
4350
4351 PVMSVGA3DSURFACE pSurface = pState->papSurfaces[sid];
4352
4353 Log(("SVGA3D_TS_BIND_TEXTURE: stage %d, texture sid=%x (%d,%d)\n", currentStage, pTextureState[i].value, pSurface->pMipmapLevels[0].size.width, pSurface->pMipmapLevels[0].size.height));
4354
4355 if (!pSurface->u.pTexture)
4356 {
4357 Assert(pSurface->idAssociatedContext == SVGA3D_INVALID_ID);
4358 Log(("CreateTexture (%d,%d) level=%d fUsage=%x format=%x\n", pSurface->pMipmapLevels[0].size.width, pSurface->pMipmapLevels[0].size.height, pSurface->faces[0].numMipLevels, pSurface->fUsageD3D, pSurface->formatD3D));
4359 int rc = vmsvga3dBackCreateTexture(pState, pContext, cid, pSurface);
4360 AssertRCReturn(rc, rc);
4361 }
4362 else
4363 {
4364 /* Must flush the other context's 3d pipeline to make sure all drawing is complete for the surface we're about to use. */
4365 vmsvga3dSurfaceFlush(pThis, pSurface);
4366 }
4367
4368#ifndef VBOX_VMSVGA3D_WITH_WINE_OPENGL
4369 if (pSurface->idAssociatedContext != cid)
4370 {
4371 Log(("vmsvga3dSetTextureState; using texture sid=%x created for another context (%d vs %d)\n", sid, pSurface->idAssociatedContext, cid));
4372
4373 PVMSVGA3DSHAREDSURFACE pSharedSurface = vmsvga3dSurfaceGetSharedCopy(pThis, pContext, pSurface);
4374 AssertReturn(pSharedSurface, VERR_INTERNAL_ERROR);
4375
4376 hr = pContext->pDevice->SetTexture(currentStage, pSharedSurface->u.pTexture);
4377 }
4378 else
4379#endif
4380 hr = pContext->pDevice->SetTexture(currentStage, pSurface->u.pTexture);
4381
4382 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSetTextureState: SetTexture failed with %x\n", hr), VERR_INTERNAL_ERROR);
4383
4384 pContext->aSidActiveTexture[currentStage] = sid;
4385 }
4386 /* Finished; continue with the next one. */
4387 continue;
4388
4389 case SVGA3D_TS_ADDRESSW: /* SVGA3dTextureAddress */
4390 samplerType = D3DSAMP_ADDRESSW;
4391 val = pTextureState[i].value; /* Identical otherwise */
4392 Assert(pTextureState[i].value != SVGA3D_TEX_ADDRESS_EDGE);
4393 break;
4394
4395 case SVGA3D_TS_ADDRESSU: /* SVGA3dTextureAddress */
4396 samplerType = D3DSAMP_ADDRESSU;
4397 val = pTextureState[i].value; /* Identical otherwise */
4398 Assert(pTextureState[i].value != SVGA3D_TEX_ADDRESS_EDGE);
4399 break;
4400
4401 case SVGA3D_TS_ADDRESSV: /* SVGA3dTextureAddress */
4402 samplerType = D3DSAMP_ADDRESSV;
4403 val = pTextureState[i].value; /* Identical otherwise */
4404 Assert(pTextureState[i].value != SVGA3D_TEX_ADDRESS_EDGE);
4405 break;
4406
4407 case SVGA3D_TS_MIPFILTER: /* SVGA3dTextureFilter */
4408 samplerType = D3DSAMP_MIPFILTER;
4409 val = pTextureState[i].value; /* Identical otherwise */
4410 Assert(pTextureState[i].value != SVGA3D_TEX_FILTER_FLATCUBIC);
4411 Assert(pTextureState[i].value != SVGA3D_TEX_FILTER_GAUSSIANCUBIC);
4412 break;
4413
4414 case SVGA3D_TS_MAGFILTER: /* SVGA3dTextureFilter */
4415 samplerType = D3DSAMP_MAGFILTER;
4416 val = pTextureState[i].value; /* Identical otherwise */
4417 Assert(pTextureState[i].value != SVGA3D_TEX_FILTER_FLATCUBIC);
4418 Assert(pTextureState[i].value != SVGA3D_TEX_FILTER_GAUSSIANCUBIC);
4419 break;
4420
4421 case SVGA3D_TS_MINFILTER: /* SVGA3dTextureFilter */
4422 samplerType = D3DSAMP_MINFILTER;
4423 val = pTextureState[i].value; /* Identical otherwise */
4424 Assert(pTextureState[i].value != SVGA3D_TEX_FILTER_FLATCUBIC);
4425 Assert(pTextureState[i].value != SVGA3D_TEX_FILTER_GAUSSIANCUBIC);
4426 break;
4427
4428 case SVGA3D_TS_BORDERCOLOR: /* SVGA3dColor */
4429 samplerType = D3DSAMP_BORDERCOLOR;
4430 val = pTextureState[i].value; /* Identical */
4431 break;
4432
4433 case SVGA3D_TS_TEXTURE_LOD_BIAS: /* float */
4434 samplerType = D3DSAMP_MIPMAPLODBIAS;
4435 val = pTextureState[i].value; /* Identical */
4436 break;
4437
4438 case SVGA3D_TS_TEXTURE_MIPMAP_LEVEL: /* uint32_t */
4439 samplerType = D3DSAMP_MAXMIPLEVEL;
4440 val = pTextureState[i].value; /* Identical?? */
4441 break;
4442
4443 case SVGA3D_TS_TEXTURE_ANISOTROPIC_LEVEL: /* uint32_t */
4444 samplerType = D3DSAMP_MAXANISOTROPY;
4445 val = pTextureState[i].value; /* Identical?? */
4446 break;
4447
4448 case SVGA3D_TS_GAMMA: /* float */
4449 samplerType = D3DSAMP_SRGBTEXTURE;
4450 /* Boolean in D3D */
4451 if (pTextureState[i].floatValue == 1.0f)
4452 val = FALSE;
4453 else
4454 val = TRUE;
4455 break;
4456
4457 /* Internal commands, that don't map directly to the SetTextureStageState API. */
4458 case SVGA3D_TS_TEXCOORDGEN: /* SVGA3dTextureCoordGen */
4459 AssertFailed();
4460 break;
4461
4462 case SVGA3D_TS_MAX: /* shut up MSC */
4463 case SVGA3D_TS_INVALID:
4464 AssertFailedBreak();
4465 }
4466
4467 if (textureType != D3DTSS_FORCE_DWORD)
4468 {
4469 hr = pContext->pDevice->SetTextureStageState(currentStage, textureType, val);
4470 }
4471 else
4472 {
4473 Assert(samplerType != D3DSAMP_FORCE_DWORD);
4474 hr = pContext->pDevice->SetSamplerState(currentStage, samplerType, val);
4475 }
4476
4477 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSetTextureState: SetTextureStageState failed with %x\n", hr), VERR_INTERNAL_ERROR);
4478 }
4479
4480 return VINF_SUCCESS;
4481}
4482
4483int vmsvga3dSetMaterial(PVGASTATE pThis, uint32_t cid, SVGA3dFace face, SVGA3dMaterial *pMaterial)
4484{
4485 HRESULT hr;
4486 D3DMATERIAL9 material;
4487 PVMSVGA3DCONTEXT pContext;
4488 PVMSVGA3DSTATE pState = pThis->svga.p3dState;
4489 AssertReturn(pState, VERR_NO_MEMORY);
4490
4491 Log(("vmsvga3dSetMaterial %x face %d\n", cid, face));
4492
4493 if ( cid >= pState->cContexts
4494 || pState->papContexts[cid]->id != cid)
4495 {
4496 Log(("vmsvga3dSetMaterial invalid context id!\n"));
4497 return VERR_INVALID_PARAMETER;
4498 }
4499 pContext = pState->papContexts[cid];
4500
4501 AssertReturn(face < SVGA3D_FACE_MAX, VERR_INVALID_PARAMETER);
4502
4503 /* Save for vm state save/restore. */
4504 pContext->state.aMaterial[face].fValid = true;
4505 pContext->state.aMaterial[face].material = *pMaterial;
4506 pContext->state.u32UpdateFlags |= VMSVGA3D_UPDATE_MATERIAL;
4507
4508 /* @note face not used for D3D9 */
4509 /** @todo ignore everything except SVGA3D_FACE_NONE? */
4510 //Assert(face == SVGA3D_FACE_NONE);
4511 if (face != SVGA3D_FACE_NONE)
4512 Log(("Unsupported face %d!!\n", face));
4513
4514 material.Diffuse.r = pMaterial->diffuse[0];
4515 material.Diffuse.g = pMaterial->diffuse[1];
4516 material.Diffuse.b = pMaterial->diffuse[2];
4517 material.Diffuse.a = pMaterial->diffuse[3];
4518 material.Ambient.r = pMaterial->ambient[0];
4519 material.Ambient.g = pMaterial->ambient[1];
4520 material.Ambient.b = pMaterial->ambient[2];
4521 material.Ambient.a = pMaterial->ambient[3];
4522 material.Specular.r = pMaterial->specular[0];
4523 material.Specular.g = pMaterial->specular[1];
4524 material.Specular.b = pMaterial->specular[2];
4525 material.Specular.a = pMaterial->specular[3];
4526 material.Emissive.r = pMaterial->emissive[0];
4527 material.Emissive.g = pMaterial->emissive[1];
4528 material.Emissive.b = pMaterial->emissive[2];
4529 material.Emissive.a = pMaterial->emissive[3];
4530 material.Power = pMaterial->shininess;
4531
4532 hr = pContext->pDevice->SetMaterial(&material);
4533 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSetMaterial: SetMaterial failed with %x\n", hr), VERR_INTERNAL_ERROR);
4534
4535 return VINF_SUCCESS;
4536}
4537
4538int vmsvga3dSetLightData(PVGASTATE pThis, uint32_t cid, uint32_t index, SVGA3dLightData *pData)
4539{
4540 HRESULT hr;
4541 D3DLIGHT9 light;
4542 PVMSVGA3DCONTEXT pContext;
4543 PVMSVGA3DSTATE pState = pThis->svga.p3dState;
4544 AssertReturn(pState, VERR_NO_MEMORY);
4545
4546 Log(("vmsvga3dSetLightData %x index=%d\n", cid, index));
4547
4548 if ( cid >= pState->cContexts
4549 || pState->papContexts[cid]->id != cid)
4550 {
4551 Log(("vmsvga3dSetLightData invalid context id!\n"));
4552 return VERR_INVALID_PARAMETER;
4553 }
4554 pContext = pState->papContexts[cid];
4555
4556 switch (pData->type)
4557 {
4558 case SVGA3D_LIGHTTYPE_POINT:
4559 light.Type = D3DLIGHT_POINT;
4560 break;
4561
4562 case SVGA3D_LIGHTTYPE_SPOT1: /* 1-cone, in degrees */
4563 light.Type = D3DLIGHT_SPOT;
4564 break;
4565
4566 case SVGA3D_LIGHTTYPE_DIRECTIONAL:
4567 light.Type = D3DLIGHT_DIRECTIONAL;
4568 break;
4569
4570 case SVGA3D_LIGHTTYPE_SPOT2: /* 2-cone, in radians */
4571 default:
4572 Log(("Unsupported light type!!\n"));
4573 return VERR_INVALID_PARAMETER;
4574 }
4575
4576 /* Store for vm state save/restore */
4577 if (index < SVGA3D_MAX_LIGHTS)
4578 {
4579 pContext->state.aLightData[index].fValidData = true;
4580 pContext->state.aLightData[index].data = *pData;
4581 }
4582 else
4583 AssertFailed();
4584
4585 light.Diffuse.r = pData->diffuse[0];
4586 light.Diffuse.g = pData->diffuse[1];
4587 light.Diffuse.b = pData->diffuse[2];
4588 light.Diffuse.a = pData->diffuse[3];
4589 light.Specular.r = pData->specular[0];
4590 light.Specular.g = pData->specular[1];
4591 light.Specular.b = pData->specular[2];
4592 light.Specular.a = pData->specular[3];
4593 light.Ambient.r = pData->ambient[0];
4594 light.Ambient.g = pData->ambient[1];
4595 light.Ambient.b = pData->ambient[2];
4596 light.Ambient.a = pData->ambient[3];
4597 light.Position.x = pData->position[0];
4598 light.Position.y = pData->position[1];
4599 light.Position.z = pData->position[2]; /* @note 4th position not available in D3D9 */
4600 light.Direction.x = pData->direction[0];
4601 light.Direction.y = pData->direction[1];
4602 light.Direction.z = pData->direction[2]; /* @note 4th position not available in D3D9 */
4603 light.Range = pData->range;
4604 light.Falloff = pData->falloff;
4605 light.Attenuation0 = pData->attenuation0;
4606 light.Attenuation1 = pData->attenuation1;
4607 light.Attenuation2 = pData->attenuation2;
4608 light.Theta = pData->theta;
4609 light.Phi = pData->phi;
4610
4611 hr = pContext->pDevice->SetLight(index, &light);
4612 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSetLightData: SetLight failed with %x\n", hr), VERR_INTERNAL_ERROR);
4613
4614 return VINF_SUCCESS;
4615}
4616
4617int vmsvga3dSetLightEnabled(PVGASTATE pThis, uint32_t cid, uint32_t index, uint32_t enabled)
4618{
4619 HRESULT hr;
4620 PVMSVGA3DCONTEXT pContext;
4621 PVMSVGA3DSTATE pState = pThis->svga.p3dState;
4622 AssertReturn(pState, VERR_NO_MEMORY);
4623
4624 Log(("vmsvga3dSetLightEnabled %x %d -> %d\n", cid, index, enabled));
4625
4626 if ( cid >= pState->cContexts
4627 || pState->papContexts[cid]->id != cid)
4628 {
4629 Log(("vmsvga3dSetLightEnabled invalid context id!\n"));
4630 return VERR_INVALID_PARAMETER;
4631 }
4632 pContext = pState->papContexts[cid];
4633
4634 /* Store for vm state save/restore */
4635 if (index < SVGA3D_MAX_LIGHTS)
4636 pContext->state.aLightData[index].fEnabled = !!enabled;
4637 else
4638 AssertFailed();
4639
4640 hr = pContext->pDevice->LightEnable(index, (BOOL)enabled);
4641 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSetLightEnabled: LightEnable failed with %x\n", hr), VERR_INTERNAL_ERROR);
4642
4643 return VINF_SUCCESS;
4644}
4645
4646int vmsvga3dSetViewPort(PVGASTATE pThis, uint32_t cid, SVGA3dRect *pRect)
4647{
4648 HRESULT hr;
4649 D3DVIEWPORT9 viewPort;
4650 PVMSVGA3DCONTEXT pContext;
4651 PVMSVGA3DSTATE pState = pThis->svga.p3dState;
4652 AssertReturn(pState, VERR_NO_MEMORY);
4653
4654 Log(("vmsvga3dSetViewPort %x (%d,%d)(%d,%d)\n", cid, pRect->x, pRect->y, pRect->w, pRect->h));
4655
4656 if ( cid >= pState->cContexts
4657 || pState->papContexts[cid]->id != cid)
4658 {
4659 Log(("vmsvga3dSetViewPort invalid context id!\n"));
4660 return VERR_INVALID_PARAMETER;
4661 }
4662 /* Save for vm state save/restore. */
4663 pContext = pState->papContexts[cid];
4664 pContext->state.RectViewPort = *pRect;
4665 pContext->state.u32UpdateFlags |= VMSVGA3D_UPDATE_VIEWPORT;
4666
4667 hr = pContext->pDevice->GetViewport(&viewPort);
4668 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSetViewPort: GetViewport failed with %x\n", hr), VERR_INTERNAL_ERROR);
4669
4670 viewPort.X = pRect->x;
4671 viewPort.Y = pRect->y;
4672 viewPort.Width = pRect->w;
4673 viewPort.Height = pRect->h;
4674 /* viewPort.MinZ & MaxZ are not changed from the current setting. */
4675
4676 hr = pContext->pDevice->SetViewport(&viewPort);
4677 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSetViewPort: SetViewport failed with %x\n", hr), VERR_INTERNAL_ERROR);
4678
4679 return VINF_SUCCESS;
4680}
4681
4682int vmsvga3dSetClipPlane(PVGASTATE pThis, uint32_t cid, uint32_t index, float plane[4])
4683{
4684 HRESULT hr;
4685 PVMSVGA3DCONTEXT pContext;
4686 PVMSVGA3DSTATE pState = pThis->svga.p3dState;
4687 AssertReturn(pState, VERR_NO_MEMORY);
4688
4689 Log(("vmsvga3dSetClipPlane %x %d (%d,%d)(%d,%d)\n", cid, index, (unsigned)(plane[0] * 100.0), (unsigned)(plane[1] * 100.0), (unsigned)(plane[2] * 100.0), (unsigned)(plane[3] * 100.0)));
4690 AssertReturn(index < SVGA3D_CLIPPLANE_MAX, VERR_INVALID_PARAMETER);
4691
4692 if ( cid >= pState->cContexts
4693 || pState->papContexts[cid]->id != cid)
4694 {
4695 Log(("vmsvga3dSetClipPlane invalid context id!\n"));
4696 return VERR_INVALID_PARAMETER;
4697 }
4698 pContext = pState->papContexts[cid];
4699
4700 /* Store for vm state save/restore. */
4701 pContext->state.aClipPlane[index].fValid = true;
4702 memcpy(pContext->state.aClipPlane[index].plane, plane, sizeof(pContext->state.aClipPlane[index].plane));
4703
4704 hr = pContext->pDevice->SetClipPlane(index, plane);
4705 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSetClipPlane: SetClipPlane failed with %x\n", hr), VERR_INTERNAL_ERROR);
4706 return VINF_SUCCESS;
4707}
4708
4709int vmsvga3dCommandClear(PVGASTATE pThis, uint32_t cid, SVGA3dClearFlag clearFlag, uint32_t color, float depth, uint32_t stencil, uint32_t cRects, SVGA3dRect *pRect)
4710{
4711 DWORD clearFlagD3D = 0;
4712 D3DRECT *pRectD3D = NULL;
4713 HRESULT hr;
4714 PVMSVGA3DCONTEXT pContext;
4715 PVMSVGA3DSTATE pState = pThis->svga.p3dState;
4716 AssertReturn(pState, VERR_NO_MEMORY);
4717
4718 Log(("vmsvga3dCommandClear %x clearFlag=%x color=%x depth=%d stencil=%x cRects=%d\n", cid, clearFlag, color, (uint32_t)(depth * 100.0), stencil, cRects));
4719
4720 if ( cid >= pState->cContexts
4721 || pState->papContexts[cid]->id != cid)
4722 {
4723 Log(("vmsvga3dCommandClear invalid context id!\n"));
4724 return VERR_INVALID_PARAMETER;
4725 }
4726 pContext = pState->papContexts[cid];
4727
4728 if (clearFlag & SVGA3D_CLEAR_COLOR)
4729 clearFlagD3D |= D3DCLEAR_TARGET;
4730 if (clearFlag & SVGA3D_CLEAR_STENCIL)
4731 clearFlagD3D |= D3DCLEAR_STENCIL;
4732 if (clearFlag & SVGA3D_CLEAR_DEPTH)
4733 clearFlagD3D |= D3DCLEAR_ZBUFFER;
4734
4735 if (cRects)
4736 {
4737 pRectD3D = (D3DRECT *)RTMemAlloc(sizeof(D3DRECT) * cRects);
4738 AssertReturn(pRectD3D, VERR_NO_MEMORY);
4739
4740 for (unsigned i=0; i < cRects; i++)
4741 {
4742 Log(("vmsvga3dCommandClear: rect %d (%d,%d)(%d,%d)\n", i, pRect[i].x, pRect[i].y, pRect[i].x + pRect[i].w, pRect[i].y + pRect[i].h));
4743 pRectD3D[i].x1 = pRect[i].x;
4744 pRectD3D[i].y1 = pRect[i].y;
4745 pRectD3D[i].x2 = pRect[i].x + pRect[i].w; /* exclusive */
4746 pRectD3D[i].y2 = pRect[i].y + pRect[i].h; /* exclusive */
4747 }
4748 }
4749
4750 hr = pContext->pDevice->Clear(cRects, pRectD3D, clearFlagD3D, (D3DCOLOR)color, depth, stencil);
4751 if (pRectD3D)
4752 RTMemFree(pRectD3D);
4753
4754 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dCommandClear: Clear failed with %x\n", hr), VERR_INTERNAL_ERROR);
4755
4756 /* Make sure we can track drawing usage of active render targets. */
4757 if (pContext->sidRenderTarget != SVGA3D_INVALID_ID)
4758 vmsvga3dSurfaceTrackUsageById(pState, pContext, pContext->sidRenderTarget);
4759
4760 return VINF_SUCCESS;
4761}
4762
4763/* Convert VMWare vertex declaration to its D3D equivalent. */
4764int vmsvga3dVertexDecl2D3D(SVGA3dVertexArrayIdentity &identity, D3DVERTEXELEMENT9 *pVertexElement)
4765{
4766 /* usage, method and type are identical; make sure. */
4767 AssertCompile(SVGA3D_DECLTYPE_FLOAT1 == D3DDECLTYPE_FLOAT1);
4768 AssertCompile(SVGA3D_DECLTYPE_FLOAT16_4 == D3DDECLTYPE_FLOAT16_4);
4769 AssertCompile(SVGA3D_DECLMETHOD_DEFAULT == D3DDECLMETHOD_DEFAULT);
4770 AssertCompile(SVGA3D_DECLMETHOD_LOOKUPPRESAMPLED == D3DDECLMETHOD_LOOKUPPRESAMPLED);
4771 AssertCompile(D3DDECLUSAGE_POSITION == SVGA3D_DECLUSAGE_POSITION);
4772 AssertCompile(D3DDECLUSAGE_SAMPLE == SVGA3D_DECLUSAGE_SAMPLE);
4773
4774 pVertexElement->Stream = 0;
4775 pVertexElement->Offset = 0;
4776 pVertexElement->Type = identity.type;
4777 pVertexElement->Method = identity.method;
4778 pVertexElement->Usage = identity.usage;
4779 pVertexElement->UsageIndex = identity.usageIndex;
4780 return VINF_SUCCESS;
4781}
4782
4783/* Convert VMWare primitive type to its D3D equivalent. */
4784int vmsvga3dPrimitiveType2D3D(SVGA3dPrimitiveType PrimitiveType, D3DPRIMITIVETYPE *pPrimitiveTypeD3D)
4785{
4786 switch (PrimitiveType)
4787 {
4788 case SVGA3D_PRIMITIVE_TRIANGLELIST:
4789 *pPrimitiveTypeD3D = D3DPT_TRIANGLELIST;
4790 break;
4791 case SVGA3D_PRIMITIVE_POINTLIST:
4792 *pPrimitiveTypeD3D = D3DPT_POINTLIST;
4793 break;
4794 case SVGA3D_PRIMITIVE_LINELIST:
4795 *pPrimitiveTypeD3D = D3DPT_LINELIST;
4796 break;
4797 case SVGA3D_PRIMITIVE_LINESTRIP:
4798 *pPrimitiveTypeD3D = D3DPT_LINESTRIP;
4799 break;
4800 case SVGA3D_PRIMITIVE_TRIANGLESTRIP:
4801 *pPrimitiveTypeD3D = D3DPT_TRIANGLESTRIP;
4802 break;
4803 case SVGA3D_PRIMITIVE_TRIANGLEFAN:
4804 *pPrimitiveTypeD3D = D3DPT_TRIANGLEFAN;
4805 break;
4806 default:
4807 return VERR_INVALID_PARAMETER;
4808 }
4809 return VINF_SUCCESS;
4810}
4811
4812int vmsvga3dDrawPrimitivesProcessVertexDecls(PVMSVGA3DSTATE pState, PVMSVGA3DCONTEXT pContext, uint32_t numVertexDecls, SVGA3dVertexDecl *pVertexDecl, uint32_t idStream, D3DVERTEXELEMENT9 *pVertexElement)
4813{
4814 HRESULT hr;
4815 int rc;
4816 uint32_t uVertexMinOffset = 0xffffffff;
4817 uint32_t uVertexMaxOffset = 0;
4818
4819 /* Create a vertex declaration array */
4820 for (unsigned iVertex = 0; iVertex < numVertexDecls; iVertex++)
4821 {
4822 unsigned sidVertex = pVertexDecl[iVertex].array.surfaceId;
4823 PVMSVGA3DSURFACE pVertexSurface;
4824
4825 AssertReturn(sidVertex < SVGA3D_MAX_SURFACE_IDS, VERR_INVALID_PARAMETER);
4826 AssertReturn(sidVertex < pState->cSurfaces && pState->papSurfaces[sidVertex]->id == sidVertex, VERR_INVALID_PARAMETER);
4827
4828 pVertexSurface = pState->papSurfaces[sidVertex];
4829 Log(("vmsvga3dDrawPrimitives: vertex sid=%x stream %d\n", sidVertex, idStream));
4830 Log(("vmsvga3dDrawPrimitives: type=%s (%d) method=%s (%d) usage=%s (%d) usageIndex=%d stride=%d offset=%d\n", vmsvgaDeclType2String(pVertexDecl[iVertex].identity.type), pVertexDecl[iVertex].identity.type, vmsvgaDeclMethod2String(pVertexDecl[iVertex].identity.method), pVertexDecl[iVertex].identity.method, vmsvgaDeclUsage2String(pVertexDecl[iVertex].identity.usage), pVertexDecl[iVertex].identity.usage, pVertexDecl[iVertex].identity.usageIndex, pVertexDecl[iVertex].array.stride, pVertexDecl[iVertex].array.offset));
4831
4832 rc = vmsvga3dVertexDecl2D3D(pVertexDecl[iVertex].identity, &pVertexElement[iVertex]);
4833 AssertRCReturn(rc, rc);
4834 pVertexElement[iVertex].Stream = idStream;
4835
4836#ifdef LOG_ENABLED
4837 if (pVertexDecl[iVertex].array.stride == 0)
4838 Log(("vmsvga3dDrawPrimitives: stride == 0! Can be valid\n"));
4839#endif
4840
4841 /* Find the min and max vertex offset to determine the right base offset to use in the vertex declaration. */
4842 if (pVertexDecl[iVertex].array.offset > uVertexMaxOffset)
4843 uVertexMaxOffset = pVertexDecl[iVertex].array.offset;
4844 if (pVertexDecl[iVertex].array.offset < uVertexMinOffset)
4845 uVertexMinOffset = pVertexDecl[iVertex].array.offset;
4846
4847 if (!pVertexSurface->u.pVertexBuffer)
4848 {
4849 Assert(iVertex == 0);
4850
4851 Log(("vmsvga3dDrawPrimitives: create vertex buffer fDirty=%d\n", pVertexSurface->fDirty));
4852 hr = pContext->pDevice->CreateVertexBuffer(pVertexSurface->pMipmapLevels[0].cbSurface,
4853 D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY /* possible severe performance penalty otherwise (according to d3d debug output) */,
4854 0, /* non-FVF */
4855 D3DPOOL_DEFAULT,
4856 &pVertexSurface->u.pVertexBuffer,
4857 NULL);
4858 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dDrawPrimitives: CreateVertexBuffer failed with %x\n", hr), VERR_INTERNAL_ERROR);
4859
4860 pVertexSurface->idAssociatedContext = pContext->id;
4861
4862 if (pVertexSurface->fDirty)
4863 {
4864 void *pData;
4865
4866 hr = pVertexSurface->u.pVertexBuffer->Lock(0, 0, &pData, 0);
4867 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dDrawPrimitives: Lock vertex failed with %x\n", hr), VERR_INTERNAL_ERROR);
4868
4869 memcpy(pData, pVertexSurface->pMipmapLevels[0].pSurfaceData, pVertexSurface->pMipmapLevels[0].cbSurface);
4870
4871 hr = pVertexSurface->u.pVertexBuffer->Unlock();
4872 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dDrawPrimitives: Unlock vertex failed with %x\n", hr), VERR_INTERNAL_ERROR);
4873 pVertexSurface->pMipmapLevels[0].fDirty = false;
4874 pVertexSurface->fDirty = false;
4875 }
4876 pVertexSurface->flags |= SVGA3D_SURFACE_HINT_VERTEXBUFFER;
4877 pVertexSurface->fu32ActualUsageFlags |= SVGA3D_SURFACE_HINT_VERTEXBUFFER;
4878 }
4879 else
4880 Assert(pVertexSurface->fDirty == false);
4881 }
4882
4883 /* Set the right vertex offset values for each declaration. */
4884 for (unsigned iVertex = 0; iVertex < numVertexDecls; iVertex++)
4885 {
4886 pVertexElement[iVertex].Offset = pVertexDecl[iVertex].array.offset - uVertexMinOffset;
4887#ifdef LOG_ENABLED
4888 if (pVertexElement[iVertex].Offset >= pVertexDecl[0].array.stride)
4889 Log(("vmsvga3dDrawPrimitives: WARNING: offset > stride!!\n"));
4890#endif
4891
4892 Log(("vmsvga3dDrawPrimitives: vertex %d offset = %d (stride %d) (min=%d max=%d)\n", iVertex, pVertexDecl[iVertex].array.offset, pVertexDecl[iVertex].array.stride, uVertexMinOffset, uVertexMaxOffset));
4893 }
4894
4895 PVMSVGA3DSURFACE pVertexSurface;
4896 unsigned sidVertex = pVertexDecl[0].array.surfaceId;
4897 unsigned strideVertex = pVertexDecl[0].array.stride;
4898
4899 pVertexSurface = pState->papSurfaces[sidVertex];
4900
4901 Log(("vmsvga3dDrawPrimitives: SetStreamSource %d min offset=%d stride=%d\n", idStream, uVertexMinOffset, strideVertex));
4902 hr = pContext->pDevice->SetStreamSource(idStream,
4903 pVertexSurface->u.pVertexBuffer,
4904 uVertexMinOffset,
4905 strideVertex);
4906
4907 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dDrawPrimitives: SetStreamSource failed with %x\n", hr), VERR_INTERNAL_ERROR);
4908 return VINF_SUCCESS;
4909}
4910
4911int vmsvga3dDrawPrimitives(PVGASTATE pThis, uint32_t cid, uint32_t numVertexDecls, SVGA3dVertexDecl *pVertexDecl,
4912 uint32_t numRanges, SVGA3dPrimitiveRange *pRange,
4913 uint32_t cVertexDivisor, SVGA3dVertexDivisor *pVertexDivisor)
4914{
4915 RT_NOREF(pVertexDivisor);
4916 PVMSVGA3DCONTEXT pContext;
4917 PVMSVGA3DSTATE pState = pThis->svga.p3dState;
4918 AssertReturn(pState, VERR_INTERNAL_ERROR);
4919 int rc = VINF_SUCCESS;
4920 HRESULT hr;
4921 uint32_t iCurrentVertex, iCurrentStreamId;
4922 IDirect3DVertexDeclaration9 *pVertexDeclD3D = NULL;
4923 D3DVERTEXELEMENT9 *pVertexElement = NULL;
4924 D3DVERTEXELEMENT9 VertexEnd = D3DDECL_END();
4925
4926 Log(("vmsvga3dDrawPrimitives %x numVertexDecls=%d numRanges=%d, cVertexDivisor=%d\n", cid, numVertexDecls, numRanges, cVertexDivisor));
4927
4928 AssertReturn(numVertexDecls && numVertexDecls <= SVGA3D_MAX_VERTEX_ARRAYS, VERR_INVALID_PARAMETER);
4929 AssertReturn(numRanges && numRanges <= SVGA3D_MAX_DRAW_PRIMITIVE_RANGES, VERR_INVALID_PARAMETER);
4930 AssertReturn(!cVertexDivisor || cVertexDivisor == numVertexDecls, VERR_INVALID_PARAMETER);
4931 /** @todo */
4932 Assert(!cVertexDivisor);
4933
4934 if ( cid >= pState->cContexts
4935 || pState->papContexts[cid]->id != cid)
4936 {
4937 Log(("vmsvga3dDrawPrimitives invalid context id!\n"));
4938 return VERR_INVALID_PARAMETER;
4939 }
4940
4941 pContext = pState->papContexts[cid];
4942
4943 /* Begin a scene before rendering anything. */
4944 hr = pContext->pDevice->BeginScene();
4945 AssertMsgReturn(hr == D3D_OK, ("BeginScene failed with %x\n", hr), VERR_INTERNAL_ERROR);
4946
4947 pVertexElement = (D3DVERTEXELEMENT9 *)RTMemAllocZ(sizeof(D3DVERTEXELEMENT9) * (numVertexDecls + 1));
4948 if (!pVertexElement)
4949 {
4950 Assert(pVertexElement);
4951 rc = VERR_INTERNAL_ERROR;
4952 goto internal_error;
4953 }
4954
4955 /* Process all vertex declarations. Each vertex buffer is represented by one stream source id. */
4956 iCurrentVertex = 0;
4957 iCurrentStreamId = 0;
4958 while (iCurrentVertex < numVertexDecls)
4959 {
4960 uint32_t sidVertex = SVGA_ID_INVALID;
4961 uint32_t iVertex;
4962 uint32_t uVertexMinOffset = 0xffffffff;
4963
4964 for (iVertex = iCurrentVertex; iVertex < numVertexDecls; iVertex++)
4965 {
4966 if ( ( sidVertex != SVGA_ID_INVALID
4967 && pVertexDecl[iVertex].array.surfaceId != sidVertex
4968 )
4969 /* We must put vertex declarations that start at a different element in another stream as d3d only handles offsets < stride. */
4970 || ( uVertexMinOffset != 0xffffffff
4971 && pVertexDecl[iVertex].array.offset >= uVertexMinOffset + pVertexDecl[iCurrentVertex].array.stride
4972 )
4973 )
4974 break;
4975 sidVertex = pVertexDecl[iVertex].array.surfaceId;
4976
4977 if (uVertexMinOffset > pVertexDecl[iVertex].array.offset)
4978 uVertexMinOffset = pVertexDecl[iVertex].array.offset;
4979 }
4980
4981 rc = vmsvga3dDrawPrimitivesProcessVertexDecls(pState, pContext, iVertex - iCurrentVertex, &pVertexDecl[iCurrentVertex], iCurrentStreamId, &pVertexElement[iCurrentVertex]);
4982 if (RT_FAILURE(rc))
4983 goto internal_error;
4984
4985 iCurrentVertex = iVertex;
4986 iCurrentStreamId++;
4987 }
4988
4989 /* Mark the end. */
4990 memcpy(&pVertexElement[numVertexDecls], &VertexEnd, sizeof(VertexEnd));
4991
4992 hr = pContext->pDevice->CreateVertexDeclaration(&pVertexElement[0],
4993 &pVertexDeclD3D);
4994 if (hr != D3D_OK)
4995 {
4996 AssertMsg(hr == D3D_OK, ("vmsvga3dDrawPrimitives: CreateVertexDeclaration failed with %x\n", hr));
4997 rc = VERR_INTERNAL_ERROR;
4998 goto internal_error;
4999 }
5000
5001 hr = pContext->pDevice->SetVertexDeclaration(pVertexDeclD3D);
5002 if (hr != D3D_OK)
5003 {
5004 AssertMsg(hr == D3D_OK, ("vmsvga3dDrawPrimitives: SetVertexDeclaration failed with %x\n", hr));
5005 rc = VERR_INTERNAL_ERROR;
5006 goto internal_error;
5007 }
5008
5009 /* Now draw the primitives. */
5010 for (unsigned iPrimitive = 0; iPrimitive < numRanges; iPrimitive++)
5011 {
5012 D3DPRIMITIVETYPE PrimitiveTypeD3D;
5013 unsigned sidIndex = pRange[iPrimitive].indexArray.surfaceId;
5014 PVMSVGA3DSURFACE pIndexSurface = NULL;
5015
5016 Log(("Primitive %d: type %s\n", iPrimitive, vmsvga3dPrimitiveType2String(pRange[iPrimitive].primType)));
5017 rc = vmsvga3dPrimitiveType2D3D(pRange[iPrimitive].primType, &PrimitiveTypeD3D);
5018 if (RT_FAILURE(rc))
5019 {
5020 AssertRC(rc);
5021 goto internal_error;
5022 }
5023
5024 /* Triangle strips or fans with just one primitive don't make much sense and are identical to triangle lists.
5025 * Workaround for NVidia driver crash when encountering some of these.
5026 */
5027 if ( pRange[iPrimitive].primitiveCount == 1
5028 && ( PrimitiveTypeD3D == D3DPT_TRIANGLESTRIP
5029 || PrimitiveTypeD3D == D3DPT_TRIANGLEFAN))
5030 PrimitiveTypeD3D = D3DPT_TRIANGLELIST;
5031
5032 if (sidIndex != SVGA3D_INVALID_ID)
5033 {
5034 AssertMsg(pRange[iPrimitive].indexWidth == sizeof(uint32_t) || pRange[iPrimitive].indexWidth == sizeof(uint16_t), ("Unsupported primitive width %d\n", pRange[iPrimitive].indexWidth));
5035
5036 if ( sidIndex >= SVGA3D_MAX_SURFACE_IDS
5037 || sidIndex >= pState->cSurfaces
5038 || pState->papSurfaces[sidIndex]->id != sidIndex)
5039 {
5040 Assert(sidIndex < SVGA3D_MAX_SURFACE_IDS);
5041 Assert(sidIndex < pState->cSurfaces && pState->papSurfaces[sidIndex]->id == sidIndex);
5042 rc = VERR_INVALID_PARAMETER;
5043 goto internal_error;
5044 }
5045 pIndexSurface = pState->papSurfaces[sidIndex];
5046 Log(("vmsvga3dDrawPrimitives: index sid=%x\n", sidIndex));
5047
5048 if (!pIndexSurface->u.pIndexBuffer)
5049 {
5050 Log(("vmsvga3dDrawPrimitives: create index buffer fDirty=%d\n", pIndexSurface->fDirty));
5051
5052 hr = pContext->pDevice->CreateIndexBuffer(pIndexSurface->pMipmapLevels[0].cbSurface,
5053 D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY /* possible severe performance penalty otherwise (according to d3d debug output */,
5054 (pRange[iPrimitive].indexWidth == sizeof(uint16_t)) ? D3DFMT_INDEX16 : D3DFMT_INDEX32,
5055 D3DPOOL_DEFAULT,
5056 &pIndexSurface->u.pIndexBuffer,
5057 NULL);
5058 if (hr != D3D_OK)
5059 {
5060 AssertMsg(hr == D3D_OK, ("vmsvga3dDrawPrimitives: CreateIndexBuffer failed with %x\n", hr));
5061 rc = VERR_INTERNAL_ERROR;
5062 goto internal_error;
5063 }
5064
5065 if (pIndexSurface->fDirty)
5066 {
5067 void *pData;
5068
5069 Log(("vmsvga3dDrawPrimitives: sync index buffer\n"));
5070
5071 hr = pIndexSurface->u.pIndexBuffer->Lock(0, 0, &pData, 0);
5072 AssertMsg(hr == D3D_OK, ("vmsvga3dDrawPrimitives: Lock vertex failed with %x\n", hr));
5073
5074 memcpy(pData, pIndexSurface->pMipmapLevels[0].pSurfaceData, pIndexSurface->pMipmapLevels[0].cbSurface);
5075
5076 hr = pIndexSurface->u.pIndexBuffer->Unlock();
5077 AssertMsg(hr == D3D_OK, ("vmsvga3dDrawPrimitives: Unlock vertex failed with %x\n", hr));
5078
5079 pIndexSurface->pMipmapLevels[0].fDirty = false;
5080 pIndexSurface->fDirty = false;
5081 }
5082 pIndexSurface->flags |= SVGA3D_SURFACE_HINT_INDEXBUFFER;
5083 pIndexSurface->fu32ActualUsageFlags |= SVGA3D_SURFACE_HINT_INDEXBUFFER;
5084 }
5085 else
5086 Assert(pIndexSurface->fDirty == false);
5087
5088 hr = pContext->pDevice->SetIndices(pIndexSurface->u.pIndexBuffer);
5089 AssertMsg(hr == D3D_OK, ("vmsvga3dDrawPrimitives: SetIndices vertex failed with %x\n", hr));
5090 }
5091 else
5092 {
5093 hr = pContext->pDevice->SetIndices(NULL);
5094 AssertMsg(hr == D3D_OK, ("vmsvga3dDrawPrimitives: SetIndices vertex (NULL) failed with %x\n", hr));
5095 }
5096
5097 PVMSVGA3DSURFACE pVertexSurface;
5098 unsigned sidVertex = pVertexDecl[0].array.surfaceId;
5099 unsigned strideVertex = pVertexDecl[0].array.stride;
5100
5101 pVertexSurface = pState->papSurfaces[sidVertex];
5102
5103 if (!pIndexSurface)
5104 {
5105 /* Render without an index buffer */
5106 Log(("DrawPrimitive %x primitivecount=%d index index bias=%d stride=%d\n", PrimitiveTypeD3D, pRange[iPrimitive].primitiveCount, pRange[iPrimitive].indexBias, strideVertex));
5107
5108 hr = pContext->pDevice->DrawPrimitive(PrimitiveTypeD3D,
5109 pRange[iPrimitive].indexBias,
5110 pRange[iPrimitive].primitiveCount);
5111 if (hr != D3D_OK)
5112 {
5113 AssertMsg(hr == D3D_OK, ("vmsvga3dDrawPrimitives: DrawPrimitive failed with %x\n", hr));
5114 rc = VERR_INTERNAL_ERROR;
5115 goto internal_error;
5116 }
5117 }
5118 else
5119 {
5120 Assert(pRange[iPrimitive].indexBias >= 0); /** @todo */
5121
5122 UINT numVertices;
5123
5124 if (pVertexDecl[0].rangeHint.last)
5125 numVertices = pVertexDecl[0].rangeHint.last - pVertexDecl[0].rangeHint.first + 1;
5126 else
5127 numVertices = pVertexSurface->pMipmapLevels[0].cbSurface / strideVertex - pVertexDecl[0].array.offset / strideVertex - pVertexDecl[0].rangeHint.first - pRange[iPrimitive].indexBias;
5128
5129 /* Render with an index buffer */
5130 Log(("DrawIndexedPrimitive %x startindex=%d numVertices=%d, primitivecount=%d index format=%d index bias=%d stride=%d\n", PrimitiveTypeD3D, pVertexDecl[0].rangeHint.first, numVertices, pRange[iPrimitive].primitiveCount, (pRange[iPrimitive].indexWidth == sizeof(uint16_t)) ? D3DFMT_INDEX16 : D3DFMT_INDEX32, pRange[iPrimitive].indexBias, strideVertex));
5131
5132 hr = pContext->pDevice->DrawIndexedPrimitive(PrimitiveTypeD3D,
5133 pRange[iPrimitive].indexBias, /* BaseVertexIndex */
5134 0, /* MinVertexIndex */
5135 numVertices,
5136 pRange[iPrimitive].indexArray.offset / pRange[iPrimitive].indexWidth, /* StartIndex */
5137 pRange[iPrimitive].primitiveCount);
5138 if (hr != D3D_OK)
5139 {
5140 AssertMsg(hr == D3D_OK, ("vmsvga3dDrawPrimitives: DrawIndexedPrimitive failed with %x\n", hr));
5141 rc = VERR_INTERNAL_ERROR;
5142 goto internal_error;
5143 }
5144 }
5145 }
5146 pVertexDeclD3D->Release();
5147 RTMemFree(pVertexElement);
5148
5149 hr = pContext->pDevice->EndScene();
5150 AssertMsgReturn(hr == D3D_OK, ("EndScene failed with %x\n", hr), VERR_INTERNAL_ERROR);
5151
5152 /* Clear streams above 1 as they might accidentally be reused in the future. */
5153 if (iCurrentStreamId > 1)
5154 {
5155 for (uint32_t i = 1; i < iCurrentStreamId; i++)
5156 {
5157 Log(("vmsvga3dDrawPrimitives: clear stream %d\n", i));
5158 hr = pContext->pDevice->SetStreamSource(i, NULL, 0, 0);
5159 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dDrawPrimitives: SetStreamSource failed with %x\n", hr), VERR_INTERNAL_ERROR);
5160 }
5161 }
5162
5163#if 0 /* Flush queue */
5164 {
5165 IDirect3DQuery9 *pQuery;
5166 hr = pContext->pDevice->CreateQuery(D3DQUERYTYPE_EVENT, &pQuery);
5167 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSurfaceTrackUsage: CreateQuery failed with %x\n", hr), VERR_INTERNAL_ERROR);
5168
5169 hr = pQuery->Issue(D3DISSUE_END);
5170 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSurfaceTrackUsage: Issue failed with %x\n", hr), VERR_INTERNAL_ERROR);
5171 while (true)
5172 {
5173 hr = pQuery->GetData(NULL, 0, D3DGETDATA_FLUSH);
5174 if (hr != S_FALSE) break;
5175
5176 RTThreadSleep(1);
5177 }
5178 AssertMsgReturn(hr == S_OK, ("vmsvga3dSurfaceFinishDrawing: GetData failed with %x\n", hr), VERR_INTERNAL_ERROR);
5179
5180 pQuery->Release();
5181 }
5182#endif
5183
5184 /* Make sure we can track drawing usage of active render targets and textures. */
5185 vmsvga3dContextTrackUsage(pThis, pContext);
5186
5187#ifdef DEBUG_GFX_WINDOW
5188 if (pContext->aSidActiveTexture[0] == 0x62)
5189//// if (pContext->sidActiveTexture == 0x3d)
5190 {
5191 SVGA3dCopyRect rect;
5192
5193 rect.srcx = rect.srcy = rect.x = rect.y = 0;
5194 rect.w = 800;
5195 rect.h = 600;
5196 vmsvga3dCommandPresent(pThis, pContext->sidRenderTarget /*pContext->aSidActiveTexture[0] */, 0, &rect);
5197 }
5198#endif
5199 return rc;
5200
5201internal_error:
5202 if (pVertexDeclD3D)
5203 pVertexDeclD3D->Release();
5204 if (pVertexElement)
5205 RTMemFree(pVertexElement);
5206
5207 hr = pContext->pDevice->EndScene();
5208 AssertMsgReturn(hr == D3D_OK, ("EndScene failed with %x\n", hr), VERR_INTERNAL_ERROR);
5209
5210 return rc;
5211}
5212
5213int vmsvga3dSetScissorRect(PVGASTATE pThis, uint32_t cid, SVGA3dRect *pRect)
5214{
5215 HRESULT hr;
5216 RECT rect;
5217 PVMSVGA3DCONTEXT pContext;
5218 PVMSVGA3DSTATE pState = pThis->svga.p3dState;
5219 AssertReturn(pState, VERR_NO_MEMORY);
5220
5221 Log(("vmsvga3dSetScissorRect %x (%d,%d)(%d,%d)\n", cid, pRect->x, pRect->y, pRect->w, pRect->h));
5222
5223 if ( cid >= pState->cContexts
5224 || pState->papContexts[cid]->id != cid)
5225 {
5226 Log(("vmsvga3dSetScissorRect invalid context id!\n"));
5227 return VERR_INVALID_PARAMETER;
5228 }
5229 pContext = pState->papContexts[cid];
5230
5231 /* Store for vm state save/restore. */
5232 pContext->state.u32UpdateFlags |= VMSVGA3D_UPDATE_SCISSORRECT;
5233 pContext->state.RectScissor = *pRect;
5234
5235 rect.left = pRect->x;
5236 rect.top = pRect->y;
5237 rect.right = rect.left + pRect->w; /* exclusive */
5238 rect.bottom = rect.top + pRect->h; /* exclusive */
5239
5240 hr = pContext->pDevice->SetScissorRect(&rect);
5241 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSetScissorRect: SetScissorRect failed with %x\n", hr), VERR_INTERNAL_ERROR);
5242
5243 return VINF_SUCCESS;
5244}
5245
5246
5247int vmsvga3dShaderDefine(PVGASTATE pThis, uint32_t cid, uint32_t shid, SVGA3dShaderType type, uint32_t cbData, uint32_t *pShaderData)
5248{
5249 HRESULT hr;
5250 PVMSVGA3DCONTEXT pContext;
5251 PVMSVGA3DSHADER pShader;
5252 PVMSVGA3DSTATE pState = pThis->svga.p3dState;
5253 AssertReturn(pState, VERR_NO_MEMORY);
5254
5255 Log(("vmsvga3dShaderDefine %x shid=%x type=%s cbData=%x\n", cid, shid, (type == SVGA3D_SHADERTYPE_VS) ? "VERTEX" : "PIXEL", cbData));
5256 Log3(("shader code:\n%.*Rhxd\n", cbData, pShaderData));
5257
5258 if ( cid >= pState->cContexts
5259 || pState->papContexts[cid]->id != cid)
5260 {
5261 Log(("vmsvga3dShaderDefine invalid context id!\n"));
5262 return VERR_INVALID_PARAMETER;
5263 }
5264 pContext = pState->papContexts[cid];
5265
5266 AssertReturn(shid < SVGA3D_MAX_SHADER_IDS, VERR_INVALID_PARAMETER);
5267 if (type == SVGA3D_SHADERTYPE_VS)
5268 {
5269 if (shid >= pContext->cVertexShaders)
5270 {
5271 void *pvNew = RTMemRealloc(pContext->paVertexShader, sizeof(VMSVGA3DSHADER) * (shid + 1));
5272 AssertReturn(pvNew, VERR_NO_MEMORY);
5273 pContext->paVertexShader = (PVMSVGA3DSHADER)pvNew;
5274 memset(&pContext->paVertexShader[pContext->cVertexShaders], 0, sizeof(VMSVGA3DSHADER) * (shid + 1 - pContext->cVertexShaders));
5275 for (uint32_t i = pContext->cVertexShaders; i < shid + 1; i++)
5276 pContext->paVertexShader[i].id = SVGA3D_INVALID_ID;
5277 pContext->cVertexShaders = shid + 1;
5278 }
5279 /* If one already exists with this id, then destroy it now. */
5280 if (pContext->paVertexShader[shid].id != SVGA3D_INVALID_ID)
5281 vmsvga3dShaderDestroy(pThis, cid, shid, pContext->paVertexShader[shid].type);
5282
5283 pShader = &pContext->paVertexShader[shid];
5284 }
5285 else
5286 {
5287 Assert(type == SVGA3D_SHADERTYPE_PS);
5288 if (shid >= pContext->cPixelShaders)
5289 {
5290 void *pvNew = RTMemRealloc(pContext->paPixelShader, sizeof(VMSVGA3DSHADER) * (shid + 1));
5291 AssertReturn(pvNew, VERR_NO_MEMORY);
5292 pContext->paPixelShader = (PVMSVGA3DSHADER)pvNew;
5293 memset(&pContext->paPixelShader[pContext->cPixelShaders], 0, sizeof(VMSVGA3DSHADER) * (shid + 1 - pContext->cPixelShaders));
5294 for (uint32_t i = pContext->cPixelShaders; i < shid + 1; i++)
5295 pContext->paPixelShader[i].id = SVGA3D_INVALID_ID;
5296 pContext->cPixelShaders = shid + 1;
5297 }
5298 /* If one already exists with this id, then destroy it now. */
5299 if (pContext->paPixelShader[shid].id != SVGA3D_INVALID_ID)
5300 vmsvga3dShaderDestroy(pThis, cid, shid, pContext->paPixelShader[shid].type);
5301
5302 pShader = &pContext->paPixelShader[shid];
5303 }
5304
5305 memset(pShader, 0, sizeof(*pShader));
5306 pShader->id = shid;
5307 pShader->cid = cid;
5308 pShader->type = type;
5309 pShader->cbData = cbData;
5310 pShader->pShaderProgram = RTMemAllocZ(cbData);
5311 AssertReturn(pShader->pShaderProgram, VERR_NO_MEMORY);
5312 memcpy(pShader->pShaderProgram, pShaderData, cbData);
5313
5314#ifdef DUMP_SHADER_DISASSEMBLY
5315 LPD3DXBUFFER pDisassembly;
5316 hr = D3DXDisassembleShader((const DWORD *)pShaderData, FALSE, NULL, &pDisassembly);
5317 if (hr == D3D_OK)
5318 {
5319 Log(("Shader disassembly:\n%s\n", pDisassembly->GetBufferPointer()));
5320 pDisassembly->Release();
5321 }
5322#endif
5323
5324 switch (type)
5325 {
5326 case SVGA3D_SHADERTYPE_VS:
5327 hr = pContext->pDevice->CreateVertexShader((const DWORD *)pShaderData, &pShader->u.pVertexShader);
5328 break;
5329
5330 case SVGA3D_SHADERTYPE_PS:
5331 hr = pContext->pDevice->CreatePixelShader((const DWORD *)pShaderData, &pShader->u.pPixelShader);
5332 break;
5333
5334 default:
5335 AssertFailedReturn(VERR_INVALID_PARAMETER);
5336 }
5337 if (hr != D3D_OK)
5338 {
5339 RTMemFree(pShader->pShaderProgram);
5340 memset(pShader, 0, sizeof(*pShader));
5341 pShader->id = SVGA3D_INVALID_ID;
5342 }
5343
5344 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dShaderDefine: CreateVertex/PixelShader failed with %x\n", hr), VERR_INTERNAL_ERROR);
5345 return VINF_SUCCESS;
5346}
5347
5348int vmsvga3dShaderDestroy(PVGASTATE pThis, uint32_t cid, uint32_t shid, SVGA3dShaderType type)
5349{
5350 PVMSVGA3DCONTEXT pContext;
5351 PVMSVGA3DSTATE pState = pThis->svga.p3dState;
5352 AssertReturn(pState, VERR_NO_MEMORY);
5353 PVMSVGA3DSHADER pShader = NULL;
5354
5355 Log(("vmsvga3dShaderDestroy %x shid=%x type=%s\n", cid, shid, (type == SVGA3D_SHADERTYPE_VS) ? "VERTEX" : "PIXEL"));
5356
5357 if ( cid >= pState->cContexts
5358 || pState->papContexts[cid]->id != cid)
5359 {
5360 Log(("vmsvga3dShaderDestroy invalid context id!\n"));
5361 return VERR_INVALID_PARAMETER;
5362 }
5363 pContext = pState->papContexts[cid];
5364
5365 if (type == SVGA3D_SHADERTYPE_VS)
5366 {
5367 if ( shid < pContext->cVertexShaders
5368 && pContext->paVertexShader[shid].id == shid)
5369 {
5370 pShader = &pContext->paVertexShader[shid];
5371 pShader->u.pVertexShader->Release();
5372 }
5373 }
5374 else
5375 {
5376 Assert(type == SVGA3D_SHADERTYPE_PS);
5377 if ( shid < pContext->cPixelShaders
5378 && pContext->paPixelShader[shid].id == shid)
5379 {
5380 pShader = &pContext->paPixelShader[shid];
5381 pShader->u.pPixelShader->Release();
5382 }
5383 }
5384
5385 if (pShader)
5386 {
5387 if (pShader->pShaderProgram)
5388 RTMemFree(pShader->pShaderProgram);
5389
5390 memset(pShader, 0, sizeof(*pShader));
5391 pShader->id = SVGA3D_INVALID_ID;
5392 }
5393 else
5394 AssertFailedReturn(VERR_INVALID_PARAMETER);
5395
5396 return VINF_SUCCESS;
5397}
5398
5399int vmsvga3dShaderSet(PVGASTATE pThis, PVMSVGA3DCONTEXT pContext, uint32_t cid, SVGA3dShaderType type, uint32_t shid)
5400{
5401 PVMSVGA3DSTATE pState = pThis->svga.p3dState;
5402 AssertReturn(pState, VERR_NO_MEMORY);
5403 HRESULT hr;
5404
5405 Log(("vmsvga3dShaderSet %x type=%s shid=%d\n", cid, (type == SVGA3D_SHADERTYPE_VS) ? "VERTEX" : "PIXEL", shid));
5406
5407 NOREF(pContext);
5408 if ( cid >= pState->cContexts
5409 || pState->papContexts[cid]->id != cid)
5410 {
5411 Log(("vmsvga3dShaderSet invalid context id!\n"));
5412 return VERR_INVALID_PARAMETER;
5413 }
5414 pContext = pState->papContexts[cid];
5415
5416 if (type == SVGA3D_SHADERTYPE_VS)
5417 {
5418 /* Save for vm state save/restore. */
5419 pContext->state.shidVertex = shid;
5420 pContext->state.u32UpdateFlags |= VMSVGA3D_UPDATE_VERTEXSHADER;
5421
5422 if ( shid < pContext->cVertexShaders
5423 && pContext->paVertexShader[shid].id == shid)
5424 {
5425 PVMSVGA3DSHADER pShader = &pContext->paVertexShader[shid];
5426 Assert(type == pShader->type);
5427
5428 hr = pContext->pDevice->SetVertexShader(pShader->u.pVertexShader);
5429 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dShaderSet: SetVertex/PixelShader failed with %x\n", hr), VERR_INTERNAL_ERROR);
5430 }
5431 else
5432 if (shid == SVGA_ID_INVALID)
5433 {
5434 /* Unselect shader. */
5435 hr = pContext->pDevice->SetVertexShader(NULL);
5436 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dShaderSet: SetVertex/PixelShader failed with %x\n", hr), VERR_INTERNAL_ERROR);
5437 }
5438 else
5439 AssertFailedReturn(VERR_INVALID_PARAMETER);
5440 }
5441 else
5442 {
5443 /* Save for vm state save/restore. */
5444 pContext->state.shidPixel = shid;
5445 pContext->state.u32UpdateFlags |= VMSVGA3D_UPDATE_PIXELSHADER;
5446
5447 Assert(type == SVGA3D_SHADERTYPE_PS);
5448 if ( shid < pContext->cPixelShaders
5449 && pContext->paPixelShader[shid].id == shid)
5450 {
5451 PVMSVGA3DSHADER pShader = &pContext->paPixelShader[shid];
5452 Assert(type == pShader->type);
5453
5454 hr = pContext->pDevice->SetPixelShader(pShader->u.pPixelShader);
5455 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dShaderSet: SetVertex/PixelShader failed with %x\n", hr), VERR_INTERNAL_ERROR);
5456 }
5457 else
5458 if (shid == SVGA_ID_INVALID)
5459 {
5460 /* Unselect shader. */
5461 hr = pContext->pDevice->SetPixelShader(NULL);
5462 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dShaderSet: SetVertex/PixelShader failed with %x\n", hr), VERR_INTERNAL_ERROR);
5463 }
5464 else
5465 AssertFailedReturn(VERR_INVALID_PARAMETER);
5466 }
5467
5468 return VINF_SUCCESS;
5469}
5470
5471int vmsvga3dShaderSetConst(PVGASTATE pThis, uint32_t cid, uint32_t reg, SVGA3dShaderType type, SVGA3dShaderConstType ctype, uint32_t cRegisters, uint32_t *pValues)
5472{
5473 HRESULT hr;
5474 PVMSVGA3DCONTEXT pContext;
5475 PVMSVGA3DSTATE pState = pThis->svga.p3dState;
5476 AssertReturn(pState, VERR_NO_MEMORY);
5477
5478 Log(("vmsvga3dShaderSetConst %x reg=%x type=%s ctype=%x\n", cid, reg, (type == SVGA3D_SHADERTYPE_VS) ? "VERTEX" : "PIXEL", ctype));
5479
5480 if ( cid >= pState->cContexts
5481 || pState->papContexts[cid]->id != cid)
5482 {
5483 Log(("vmsvga3dShaderSetConst invalid context id!\n"));
5484 return VERR_INVALID_PARAMETER;
5485 }
5486 pContext = pState->papContexts[cid];
5487
5488 for (uint32_t i = 0; i < cRegisters; i++)
5489 {
5490 Log(("Constant %d: value=%x-%x-%x-%x\n", reg + i, pValues[i*4 + 0], pValues[i*4 + 1], pValues[i*4 + 2], pValues[i*4 + 3]));
5491 vmsvga3dSaveShaderConst(pContext, reg + i, type, ctype, pValues[i*4 + 0], pValues[i*4 + 1], pValues[i*4 + 2], pValues[i*4 + 3]);
5492 }
5493
5494 switch (type)
5495 {
5496 case SVGA3D_SHADERTYPE_VS:
5497 switch (ctype)
5498 {
5499 case SVGA3D_CONST_TYPE_FLOAT:
5500 hr = pContext->pDevice->SetVertexShaderConstantF(reg, (const float *)pValues, cRegisters);
5501 break;
5502
5503 case SVGA3D_CONST_TYPE_INT:
5504 hr = pContext->pDevice->SetVertexShaderConstantI(reg, (const int *)pValues, cRegisters);
5505 break;
5506
5507 case SVGA3D_CONST_TYPE_BOOL:
5508 hr = pContext->pDevice->SetVertexShaderConstantB(reg, (const BOOL *)pValues, cRegisters);
5509 break;
5510
5511 default:
5512 AssertFailedReturn(VERR_INVALID_PARAMETER);
5513 }
5514 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dShaderSetConst: SetVertexShader failed with %x\n", hr), VERR_INTERNAL_ERROR);
5515 break;
5516
5517 case SVGA3D_SHADERTYPE_PS:
5518 switch (ctype)
5519 {
5520 case SVGA3D_CONST_TYPE_FLOAT:
5521 {
5522 hr = pContext->pDevice->SetPixelShaderConstantF(reg, (const float *)pValues, cRegisters);
5523 break;
5524 }
5525
5526 case SVGA3D_CONST_TYPE_INT:
5527 hr = pContext->pDevice->SetPixelShaderConstantI(reg, (const int *)pValues, cRegisters);
5528 break;
5529
5530 case SVGA3D_CONST_TYPE_BOOL:
5531 hr = pContext->pDevice->SetPixelShaderConstantB(reg, (const BOOL *)pValues, cRegisters);
5532 break;
5533
5534 default:
5535 AssertFailedReturn(VERR_INVALID_PARAMETER);
5536 }
5537 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dShaderSetConst: SetPixelShader failed with %x\n", hr), VERR_INTERNAL_ERROR);
5538 break;
5539
5540 default:
5541 AssertFailedReturn(VERR_INVALID_PARAMETER);
5542 }
5543 return VINF_SUCCESS;
5544}
5545
5546
5547int vmsvga3dQueryBegin(PVGASTATE pThis, uint32_t cid, SVGA3dQueryType type)
5548{
5549 RT_NOREF(pThis, cid, type);
5550 AssertFailed();
5551 return VERR_NOT_IMPLEMENTED;
5552}
5553
5554int vmsvga3dQueryEnd(PVGASTATE pThis, uint32_t cid, SVGA3dQueryType type, SVGAGuestPtr guestResult)
5555{
5556 RT_NOREF(pThis, cid, type, guestResult);
5557 AssertFailed();
5558 return VERR_NOT_IMPLEMENTED;
5559}
5560
5561int vmsvga3dQueryWait(PVGASTATE pThis, uint32_t cid, SVGA3dQueryType type, SVGAGuestPtr guestResult)
5562{
5563 RT_NOREF(pThis, cid, type, guestResult);
5564 AssertFailed();
5565 return VERR_NOT_IMPLEMENTED;
5566}
5567
5568static void vmsvgaDumpD3DCaps(D3DCAPS9 *pCaps)
5569{
5570 bool const fBufferingSaved = RTLogRelSetBuffering(true /*fBuffered*/);
5571
5572 LogRel(("\nD3D device caps: DevCaps2:\n"));
5573 if (pCaps->DevCaps2 & D3DDEVCAPS2_ADAPTIVETESSRTPATCH)
5574 LogRel((" - D3DDEVCAPS2_ADAPTIVETESSRTPATCH\n"));
5575 if (pCaps->DevCaps2 & D3DDEVCAPS2_ADAPTIVETESSNPATCH)
5576 LogRel((" - D3DDEVCAPS2_ADAPTIVETESSNPATCH\n"));
5577 if (pCaps->DevCaps2 & D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES)
5578 LogRel((" - D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES\n"));
5579 if (pCaps->DevCaps2 & D3DDEVCAPS2_DMAPNPATCH)
5580 LogRel((" - D3DDEVCAPS2_DMAPNPATCH\n"));
5581 if (pCaps->DevCaps2 & D3DDEVCAPS2_PRESAMPLEDDMAPNPATCH)
5582 LogRel((" - D3DDEVCAPS2_PRESAMPLEDDMAPNPATCH\n"));
5583 if (pCaps->DevCaps2 & D3DDEVCAPS2_STREAMOFFSET)
5584 LogRel((" - D3DDEVCAPS2_STREAMOFFSET\n"));
5585 if (pCaps->DevCaps2 & D3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET)
5586 LogRel((" - D3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET\n"));
5587
5588 LogRel(("\nCaps2:\n"));
5589 if (pCaps->Caps2 & D3DCAPS2_CANAUTOGENMIPMAP)
5590 LogRel((" - D3DCAPS2_CANAUTOGENMIPMAP\n"));
5591 if (pCaps->Caps2 & D3DCAPS2_CANCALIBRATEGAMMA)
5592 LogRel((" - D3DCAPS2_CANCALIBRATEGAMMA\n"));
5593 if (pCaps->Caps2 & D3DCAPS2_CANSHARERESOURCE)
5594 LogRel((" - D3DCAPS2_CANSHARERESOURCE\n"));
5595 if (pCaps->Caps2 & D3DCAPS2_CANMANAGERESOURCE)
5596 LogRel((" - D3DCAPS2_CANMANAGERESOURCE\n"));
5597 if (pCaps->Caps2 & D3DCAPS2_DYNAMICTEXTURES)
5598 LogRel((" - D3DCAPS2_DYNAMICTEXTURES\n"));
5599 if (pCaps->Caps2 & D3DCAPS2_FULLSCREENGAMMA)
5600 LogRel((" - D3DCAPS2_FULLSCREENGAMMA\n"));
5601
5602 LogRel(("\nCaps3:\n"));
5603 if (pCaps->Caps3 & D3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD)
5604 LogRel((" - D3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD\n"));
5605 if (pCaps->Caps3 & D3DCAPS3_COPY_TO_VIDMEM)
5606 LogRel((" - D3DCAPS3_COPY_TO_VIDMEM\n"));
5607 if (pCaps->Caps3 & D3DCAPS3_COPY_TO_SYSTEMMEM)
5608 LogRel((" - D3DCAPS3_COPY_TO_SYSTEMMEM\n"));
5609 if (pCaps->Caps3 & D3DCAPS3_DXVAHD)
5610 LogRel((" - D3DCAPS3_DXVAHD\n"));
5611 if (pCaps->Caps3 & D3DCAPS3_LINEAR_TO_SRGB_PRESENTATION)
5612 LogRel((" - D3DCAPS3_LINEAR_TO_SRGB_PRESENTATION\n"));
5613
5614 LogRel(("\nPresentationIntervals:\n"));
5615 if (pCaps->PresentationIntervals & D3DPRESENT_INTERVAL_IMMEDIATE)
5616 LogRel((" - D3DPRESENT_INTERVAL_IMMEDIATE\n"));
5617 if (pCaps->PresentationIntervals & D3DPRESENT_INTERVAL_ONE)
5618 LogRel((" - D3DPRESENT_INTERVAL_ONE\n"));
5619 if (pCaps->PresentationIntervals & D3DPRESENT_INTERVAL_TWO)
5620 LogRel((" - D3DPRESENT_INTERVAL_TWO\n"));
5621 if (pCaps->PresentationIntervals & D3DPRESENT_INTERVAL_THREE)
5622 LogRel((" - D3DPRESENT_INTERVAL_THREE\n"));
5623 if (pCaps->PresentationIntervals & D3DPRESENT_INTERVAL_FOUR)
5624 LogRel((" - D3DPRESENT_INTERVAL_FOUR\n"));
5625
5626 LogRel(("\nDevcaps:\n"));
5627 if (pCaps->DevCaps & D3DDEVCAPS_CANBLTSYSTONONLOCAL)
5628 LogRel((" - D3DDEVCAPS_CANBLTSYSTONONLOCAL\n"));
5629 if (pCaps->DevCaps & D3DDEVCAPS_CANRENDERAFTERFLIP)
5630 LogRel((" - D3DDEVCAPS_CANRENDERAFTERFLIP\n"));
5631 if (pCaps->DevCaps & D3DDEVCAPS_DRAWPRIMITIVES2)
5632 LogRel((" - D3DDEVCAPS_DRAWPRIMITIVES2\n"));
5633 if (pCaps->DevCaps & D3DDEVCAPS_DRAWPRIMITIVES2EX)
5634 LogRel((" - D3DDEVCAPS_DRAWPRIMITIVES2EX\n"));
5635 if (pCaps->DevCaps & D3DDEVCAPS_DRAWPRIMTLVERTEX)
5636 LogRel((" - D3DDEVCAPS_DRAWPRIMTLVERTEX\n"));
5637 if (pCaps->DevCaps & D3DDEVCAPS_EXECUTESYSTEMMEMORY)
5638 LogRel((" - D3DDEVCAPS_EXECUTESYSTEMMEMORY\n"));
5639 if (pCaps->DevCaps & D3DDEVCAPS_EXECUTEVIDEOMEMORY)
5640 LogRel((" - D3DDEVCAPS_EXECUTEVIDEOMEMORY\n"));
5641 if (pCaps->DevCaps & D3DDEVCAPS_HWRASTERIZATION)
5642 LogRel((" - D3DDEVCAPS_HWRASTERIZATION\n"));
5643 if (pCaps->DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT)
5644 LogRel((" - D3DDEVCAPS_HWTRANSFORMANDLIGHT\n"));
5645 if (pCaps->DevCaps & D3DDEVCAPS_NPATCHES)
5646 LogRel((" - D3DDEVCAPS_NPATCHES\n"));
5647 if (pCaps->DevCaps & D3DDEVCAPS_PUREDEVICE)
5648 LogRel((" - D3DDEVCAPS_PUREDEVICE\n"));
5649 if (pCaps->DevCaps & D3DDEVCAPS_QUINTICRTPATCHES)
5650 LogRel((" - D3DDEVCAPS_QUINTICRTPATCHES\n"));
5651 if (pCaps->DevCaps & D3DDEVCAPS_RTPATCHES)
5652 LogRel((" - D3DDEVCAPS_RTPATCHES\n"));
5653 if (pCaps->DevCaps & D3DDEVCAPS_RTPATCHHANDLEZERO)
5654 LogRel((" - D3DDEVCAPS_RTPATCHHANDLEZERO\n"));
5655 if (pCaps->DevCaps & D3DDEVCAPS_SEPARATETEXTUREMEMORIES)
5656 LogRel((" - D3DDEVCAPS_SEPARATETEXTUREMEMORIES\n"));
5657 if (pCaps->DevCaps & D3DDEVCAPS_TEXTURENONLOCALVIDMEM)
5658 LogRel((" - D3DDEVCAPS_TEXTURENONLOCALVIDMEM\n"));
5659 if (pCaps->DevCaps & D3DDEVCAPS_TEXTURESYSTEMMEMORY)
5660 LogRel((" - D3DDEVCAPS_TEXTURESYSTEMMEMORY\n"));
5661 if (pCaps->DevCaps & D3DDEVCAPS_TEXTUREVIDEOMEMORY)
5662 LogRel((" - D3DDEVCAPS_TEXTUREVIDEOMEMORY\n"));
5663 if (pCaps->DevCaps & D3DDEVCAPS_TLVERTEXSYSTEMMEMORY)
5664 LogRel((" - D3DDEVCAPS_TLVERTEXSYSTEMMEMORY\n"));
5665 if (pCaps->DevCaps & D3DDEVCAPS_TLVERTEXVIDEOMEMORY)
5666 LogRel((" - D3DDEVCAPS_TLVERTEXVIDEOMEMORY\n"));
5667
5668 LogRel(("\nTextureCaps:\n"));
5669 if (pCaps->TextureCaps & D3DPTEXTURECAPS_ALPHA)
5670 LogRel((" - D3DPTEXTURECAPS_ALPHA\n"));
5671 if (pCaps->TextureCaps & D3DPTEXTURECAPS_ALPHAPALETTE)
5672 LogRel((" - D3DPTEXTURECAPS_ALPHAPALETTE\n"));
5673 if (pCaps->TextureCaps & D3DPTEXTURECAPS_CUBEMAP)
5674 LogRel((" - D3DPTEXTURECAPS_CUBEMAP\n"));
5675 if (pCaps->TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2)
5676 LogRel((" - D3DPTEXTURECAPS_CUBEMAP_POW2\n"));
5677 if (pCaps->TextureCaps & D3DPTEXTURECAPS_MIPCUBEMAP)
5678 LogRel((" - D3DPTEXTURECAPS_MIPCUBEMAP\n"));
5679 if (pCaps->TextureCaps & D3DPTEXTURECAPS_MIPMAP)
5680 LogRel((" - D3DPTEXTURECAPS_MIPMAP\n"));
5681 if (pCaps->TextureCaps & D3DPTEXTURECAPS_MIPVOLUMEMAP)
5682 LogRel((" - D3DPTEXTURECAPS_MIPVOLUMEMAP\n"));
5683 if (pCaps->TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL)
5684 LogRel((" - D3DPTEXTURECAPS_NONPOW2CONDITIONAL\n"));
5685 if (pCaps->TextureCaps & D3DPTEXTURECAPS_POW2)
5686 LogRel((" - D3DPTEXTURECAPS_POW2\n"));
5687 if (pCaps->TextureCaps & D3DPTEXTURECAPS_NOPROJECTEDBUMPENV)
5688 LogRel((" - D3DPTEXTURECAPS_NOPROJECTEDBUMPENV\n"));
5689 if (pCaps->TextureCaps & D3DPTEXTURECAPS_PERSPECTIVE)
5690 LogRel((" - D3DPTEXTURECAPS_PERSPECTIVE\n"));
5691 if (pCaps->TextureCaps & D3DPTEXTURECAPS_POW2)
5692 LogRel((" - D3DPTEXTURECAPS_POW2\n"));
5693 if (pCaps->TextureCaps & D3DPTEXTURECAPS_PROJECTED)
5694 LogRel((" - D3DPTEXTURECAPS_PROJECTED\n"));
5695 if (pCaps->TextureCaps & D3DPTEXTURECAPS_SQUAREONLY)
5696 LogRel((" - D3DPTEXTURECAPS_SQUAREONLY\n"));
5697 if (pCaps->TextureCaps & D3DPTEXTURECAPS_TEXREPEATNOTSCALEDBYSIZE)
5698 LogRel((" - D3DPTEXTURECAPS_TEXREPEATNOTSCALEDBYSIZE\n"));
5699 if (pCaps->TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP)
5700 LogRel((" - D3DPTEXTURECAPS_VOLUMEMAP\n"));
5701 if (pCaps->TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP_POW2)
5702 LogRel((" - D3DPTEXTURECAPS_VOLUMEMAP_POW2\n"));
5703
5704 LogRel(("\nTextureFilterCaps\n"));
5705 if (pCaps->TextureFilterCaps & D3DPTFILTERCAPS_CONVOLUTIONMONO)
5706 LogRel((" - D3DPTFILTERCAPS_CONVOLUTIONMONO\n"));
5707 if (pCaps->TextureFilterCaps & D3DPTFILTERCAPS_MAGFPOINT)
5708 LogRel((" - D3DPTFILTERCAPS_MAGFPOINT\n"));
5709 if (pCaps->TextureFilterCaps & D3DPTFILTERCAPS_MAGFLINEAR)
5710 LogRel((" - D3DPTFILTERCAPS_MAGFLINEAR\n"));
5711 if (pCaps->TextureFilterCaps & D3DPTFILTERCAPS_MAGFANISOTROPIC)
5712 LogRel((" - D3DPTFILTERCAPS_MAGFANISOTROPIC\n"));
5713 if (pCaps->TextureFilterCaps & D3DPTFILTERCAPS_MAGFPYRAMIDALQUAD)
5714 LogRel((" - D3DPTFILTERCAPS_MAGFPYRAMIDALQUAD\n"));
5715 if (pCaps->TextureFilterCaps & D3DPTFILTERCAPS_MAGFGAUSSIANQUAD)
5716 LogRel((" - D3DPTFILTERCAPS_MAGFGAUSSIANQUAD\n"));
5717 if (pCaps->TextureFilterCaps & D3DPTFILTERCAPS_MINFPOINT)
5718 LogRel((" - D3DPTFILTERCAPS_MINFPOINT\n"));
5719 if (pCaps->TextureFilterCaps & D3DPTFILTERCAPS_MINFLINEAR)
5720 LogRel((" - D3DPTFILTERCAPS_MINFLINEAR\n"));
5721 if (pCaps->TextureFilterCaps & D3DPTFILTERCAPS_MINFANISOTROPIC)
5722 LogRel((" - D3DPTFILTERCAPS_MINFANISOTROPIC\n"));
5723 if (pCaps->TextureFilterCaps & D3DPTFILTERCAPS_MINFPYRAMIDALQUAD)
5724 LogRel((" - D3DPTFILTERCAPS_MINFPYRAMIDALQUAD\n"));
5725 if (pCaps->TextureFilterCaps & D3DPTFILTERCAPS_MINFGAUSSIANQUAD)
5726 LogRel((" - D3DPTFILTERCAPS_MINFGAUSSIANQUAD\n"));
5727 if (pCaps->TextureFilterCaps & D3DPTFILTERCAPS_MIPFPOINT)
5728 LogRel((" - D3DPTFILTERCAPS_MIPFPOINT\n"));
5729 if (pCaps->TextureFilterCaps & D3DPTFILTERCAPS_MIPFLINEAR)
5730 LogRel((" - D3DPTFILTERCAPS_MIPFLINEAR\n"));
5731
5732 LogRel(("\nCubeTextureFilterCaps\n"));
5733 if (pCaps->CubeTextureFilterCaps & D3DPTFILTERCAPS_CONVOLUTIONMONO)
5734 LogRel((" - D3DPTFILTERCAPS_CONVOLUTIONMONO\n"));
5735 if (pCaps->CubeTextureFilterCaps & D3DPTFILTERCAPS_MAGFPOINT)
5736 LogRel((" - D3DPTFILTERCAPS_MAGFPOINT\n"));
5737 if (pCaps->CubeTextureFilterCaps & D3DPTFILTERCAPS_MAGFLINEAR)
5738 LogRel((" - D3DPTFILTERCAPS_MAGFLINEAR\n"));
5739 if (pCaps->CubeTextureFilterCaps & D3DPTFILTERCAPS_MAGFANISOTROPIC)
5740 LogRel((" - D3DPTFILTERCAPS_MAGFANISOTROPIC\n"));
5741 if (pCaps->CubeTextureFilterCaps & D3DPTFILTERCAPS_MAGFPYRAMIDALQUAD)
5742 LogRel((" - D3DPTFILTERCAPS_MAGFPYRAMIDALQUAD\n"));
5743 if (pCaps->CubeTextureFilterCaps & D3DPTFILTERCAPS_MAGFGAUSSIANQUAD)
5744 LogRel((" - D3DPTFILTERCAPS_MAGFGAUSSIANQUAD\n"));
5745 if (pCaps->CubeTextureFilterCaps & D3DPTFILTERCAPS_MINFPOINT)
5746 LogRel((" - D3DPTFILTERCAPS_MINFPOINT\n"));
5747 if (pCaps->CubeTextureFilterCaps & D3DPTFILTERCAPS_MINFLINEAR)
5748 LogRel((" - D3DPTFILTERCAPS_MINFLINEAR\n"));
5749 if (pCaps->CubeTextureFilterCaps & D3DPTFILTERCAPS_MINFANISOTROPIC)
5750 LogRel((" - D3DPTFILTERCAPS_MINFANISOTROPIC\n"));
5751 if (pCaps->CubeTextureFilterCaps & D3DPTFILTERCAPS_MINFPYRAMIDALQUAD)
5752 LogRel((" - D3DPTFILTERCAPS_MINFPYRAMIDALQUAD\n"));
5753 if (pCaps->CubeTextureFilterCaps & D3DPTFILTERCAPS_MINFGAUSSIANQUAD)
5754 LogRel((" - D3DPTFILTERCAPS_MINFGAUSSIANQUAD\n"));
5755 if (pCaps->CubeTextureFilterCaps & D3DPTFILTERCAPS_MIPFPOINT)
5756 LogRel((" - D3DPTFILTERCAPS_MIPFPOINT\n"));
5757 if (pCaps->CubeTextureFilterCaps & D3DPTFILTERCAPS_MIPFLINEAR)
5758 LogRel((" - D3DPTFILTERCAPS_MIPFLINEAR\n"));
5759
5760 LogRel(("\nVolumeTextureFilterCaps\n"));
5761 if (pCaps->VolumeTextureFilterCaps & D3DPTFILTERCAPS_CONVOLUTIONMONO)
5762 LogRel((" - D3DPTFILTERCAPS_CONVOLUTIONMONO\n"));
5763 if (pCaps->VolumeTextureFilterCaps & D3DPTFILTERCAPS_MAGFPOINT)
5764 LogRel((" - D3DPTFILTERCAPS_MAGFPOINT\n"));
5765 if (pCaps->VolumeTextureFilterCaps & D3DPTFILTERCAPS_MAGFLINEAR)
5766 LogRel((" - D3DPTFILTERCAPS_MAGFLINEAR\n"));
5767 if (pCaps->VolumeTextureFilterCaps & D3DPTFILTERCAPS_MAGFANISOTROPIC)
5768 LogRel((" - D3DPTFILTERCAPS_MAGFANISOTROPIC\n"));
5769 if (pCaps->VolumeTextureFilterCaps & D3DPTFILTERCAPS_MAGFPYRAMIDALQUAD)
5770 LogRel((" - D3DPTFILTERCAPS_MAGFPYRAMIDALQUAD\n"));
5771 if (pCaps->VolumeTextureFilterCaps & D3DPTFILTERCAPS_MAGFGAUSSIANQUAD)
5772 LogRel((" - D3DPTFILTERCAPS_MAGFGAUSSIANQUAD\n"));
5773 if (pCaps->VolumeTextureFilterCaps & D3DPTFILTERCAPS_MINFPOINT)
5774 LogRel((" - D3DPTFILTERCAPS_MINFPOINT\n"));
5775 if (pCaps->VolumeTextureFilterCaps & D3DPTFILTERCAPS_MINFLINEAR)
5776 LogRel((" - D3DPTFILTERCAPS_MINFLINEAR\n"));
5777 if (pCaps->VolumeTextureFilterCaps & D3DPTFILTERCAPS_MINFANISOTROPIC)
5778 LogRel((" - D3DPTFILTERCAPS_MINFANISOTROPIC\n"));
5779 if (pCaps->VolumeTextureFilterCaps & D3DPTFILTERCAPS_MINFPYRAMIDALQUAD)
5780 LogRel((" - D3DPTFILTERCAPS_MINFPYRAMIDALQUAD\n"));
5781 if (pCaps->VolumeTextureFilterCaps & D3DPTFILTERCAPS_MINFGAUSSIANQUAD)
5782 LogRel((" - D3DPTFILTERCAPS_MINFGAUSSIANQUAD\n"));
5783 if (pCaps->VolumeTextureFilterCaps & D3DPTFILTERCAPS_MIPFPOINT)
5784 LogRel((" - D3DPTFILTERCAPS_MIPFPOINT\n"));
5785 if (pCaps->VolumeTextureFilterCaps & D3DPTFILTERCAPS_MIPFLINEAR)
5786 LogRel((" - D3DPTFILTERCAPS_MIPFLINEAR\n"));
5787
5788 LogRel(("\nTextureAddressCaps:\n"));
5789 if (pCaps->TextureAddressCaps & D3DPTADDRESSCAPS_BORDER)
5790 LogRel((" - D3DPTADDRESSCAPS_BORDER\n"));
5791 if (pCaps->TextureAddressCaps & D3DPTADDRESSCAPS_CLAMP)
5792 LogRel((" - D3DPTADDRESSCAPS_CLAMP\n"));
5793 if (pCaps->TextureAddressCaps & D3DPTADDRESSCAPS_INDEPENDENTUV)
5794 LogRel((" - D3DPTADDRESSCAPS_INDEPENDENTUV\n"));
5795 if (pCaps->TextureAddressCaps & D3DPTADDRESSCAPS_MIRROR)
5796 LogRel((" - D3DPTADDRESSCAPS_MIRROR\n"));
5797 if (pCaps->TextureAddressCaps & D3DPTADDRESSCAPS_MIRRORONCE)
5798 LogRel((" - D3DPTADDRESSCAPS_MIRRORONCE\n"));
5799 if (pCaps->TextureAddressCaps & D3DPTADDRESSCAPS_WRAP)
5800 LogRel((" - D3DPTADDRESSCAPS_WRAP\n"));
5801
5802 LogRel(("\nTextureOpCaps:\n"));
5803 if (pCaps->TextureOpCaps & D3DTEXOPCAPS_DISABLE)
5804 LogRel((" - D3DTEXOPCAPS_DISABLE\n"));
5805 if (pCaps->TextureOpCaps & D3DTEXOPCAPS_SELECTARG1)
5806 LogRel((" - D3DTEXOPCAPS_SELECTARG1\n"));
5807 if (pCaps->TextureOpCaps & D3DTEXOPCAPS_SELECTARG2)
5808 LogRel((" - D3DTEXOPCAPS_SELECTARG2\n"));
5809 if (pCaps->TextureOpCaps & D3DTEXOPCAPS_MODULATE)
5810 LogRel((" - D3DTEXOPCAPS_MODULATE\n"));
5811 if (pCaps->TextureOpCaps & D3DTEXOPCAPS_MODULATE2X)
5812 LogRel((" - D3DTEXOPCAPS_MODULATE2X\n"));
5813 if (pCaps->TextureOpCaps & D3DTEXOPCAPS_MODULATE4X)
5814 LogRel((" - D3DTEXOPCAPS_MODULATE4X\n"));
5815 if (pCaps->TextureOpCaps & D3DTEXOPCAPS_ADD)
5816 LogRel((" - D3DTEXOPCAPS_ADD\n"));
5817 if (pCaps->TextureOpCaps & D3DTEXOPCAPS_ADDSIGNED)
5818 LogRel((" - D3DTEXOPCAPS_ADDSIGNED\n"));
5819 if (pCaps->TextureOpCaps & D3DTEXOPCAPS_ADDSIGNED2X)
5820 LogRel((" - D3DTEXOPCAPS_ADDSIGNED2X\n"));
5821 if (pCaps->TextureOpCaps & D3DTEXOPCAPS_SUBTRACT)
5822 LogRel((" - D3DTEXOPCAPS_SUBTRACT\n"));
5823 if (pCaps->TextureOpCaps & D3DTEXOPCAPS_ADDSMOOTH)
5824 LogRel((" - D3DTEXOPCAPS_ADDSMOOTH\n"));
5825 if (pCaps->TextureOpCaps & D3DTEXOPCAPS_BLENDDIFFUSEALPHA)
5826 LogRel((" - D3DTEXOPCAPS_BLENDDIFFUSEALPHA\n"));
5827 if (pCaps->TextureOpCaps & D3DTEXOPCAPS_BLENDTEXTUREALPHA)
5828 LogRel((" - D3DTEXOPCAPS_BLENDTEXTUREALPHA\n"));
5829 if (pCaps->TextureOpCaps & D3DTEXOPCAPS_BLENDFACTORALPHA)
5830 LogRel((" - D3DTEXOPCAPS_BLENDFACTORALPHA\n"));
5831 if (pCaps->TextureOpCaps & D3DTEXOPCAPS_BLENDTEXTUREALPHAPM)
5832 LogRel((" - D3DTEXOPCAPS_BLENDTEXTUREALPHAPM\n"));
5833 if (pCaps->TextureOpCaps & D3DTEXOPCAPS_BLENDCURRENTALPHA)
5834 LogRel((" - D3DTEXOPCAPS_BLENDCURRENTALPHA\n"));
5835 if (pCaps->TextureOpCaps & D3DTEXOPCAPS_PREMODULATE)
5836 LogRel((" - D3DTEXOPCAPS_PREMODULATE\n"));
5837 if (pCaps->TextureOpCaps & D3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR)
5838 LogRel((" - D3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR\n"));
5839 if (pCaps->TextureOpCaps & D3DTEXOPCAPS_MODULATECOLOR_ADDALPHA)
5840 LogRel((" - D3DTEXOPCAPS_MODULATECOLOR_ADDALPHA\n"));
5841 if (pCaps->TextureOpCaps & D3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR)
5842 LogRel((" - D3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR\n"));
5843 if (pCaps->TextureOpCaps & D3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA)
5844 LogRel((" - D3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA\n"));
5845 if (pCaps->TextureOpCaps & D3DTEXOPCAPS_BUMPENVMAP)
5846 LogRel((" - D3DTEXOPCAPS_BUMPENVMAP\n"));
5847 if (pCaps->TextureOpCaps & D3DTEXOPCAPS_BUMPENVMAPLUMINANCE)
5848 LogRel((" - D3DTEXOPCAPS_BUMPENVMAPLUMINANCE\n"));
5849 if (pCaps->TextureOpCaps & D3DTEXOPCAPS_DOTPRODUCT3)
5850 LogRel((" - D3DTEXOPCAPS_DOTPRODUCT3\n"));
5851 if (pCaps->TextureOpCaps & D3DTEXOPCAPS_MULTIPLYADD)
5852 LogRel((" - D3DTEXOPCAPS_MULTIPLYADD\n"));
5853 if (pCaps->TextureOpCaps & D3DTEXOPCAPS_LERP)
5854 LogRel((" - D3DTEXOPCAPS_LERP\n"));
5855
5856
5857 LogRel(("\n"));
5858 LogRel(("PixelShaderVersion: %#x (%u.%u)\n", pCaps->PixelShaderVersion,
5859 D3DSHADER_VERSION_MAJOR(pCaps->PixelShaderVersion), D3DSHADER_VERSION_MINOR(pCaps->PixelShaderVersion)));
5860 LogRel(("VertexShaderVersion: %#x (%u.%u)\n", pCaps->VertexShaderVersion,
5861 D3DSHADER_VERSION_MAJOR(pCaps->VertexShaderVersion), D3DSHADER_VERSION_MINOR(pCaps->VertexShaderVersion)));
5862
5863 LogRel(("\n"));
5864 RTLogRelSetBuffering(fBufferingSaved);
5865}
5866
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette