VirtualBox

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

Last change on this file since 58466 was 57790, checked in by vboxsync, 9 years ago

VMSVGA3d: Turns out I'm blitting to the wrong end (Y direction) of the nsview framebuffer. Missed some [NSOpenGLContext update] calls when the parent view got resized, so it sometimes worked, but not all the time. After calling update, the visible part of the framebuffer is the bottom half, not the top half as I though and as seems to be the case on the other plaforms.

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