VirtualBox

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

Last change on this file since 74944 was 74549, checked in by vboxsync, 6 years ago

DevVGA-SVGA: further cleanup of context windows creation (Windows host only); removed obsolete debug code.

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

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