VirtualBox

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

Last change on this file since 93956 was 93115, checked in by vboxsync, 3 years ago

scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 61.0 KB
Line 
1/* $Id: DevVGA-SVGA3d.cpp 93115 2022-01-01 11:31:46Z vboxsync $ */
2/** @file
3 * DevSVGA3d - VMWare SVGA device, 3D parts - Common core code.
4 */
5
6/*
7 * Copyright (C) 2013-2022 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/AssertGuest.h>
24#include <VBox/vmm/pdmdev.h>
25#include <iprt/errcore.h>
26#include <VBox/log.h>
27
28#include <iprt/assert.h>
29#include <iprt/mem.h>
30
31#include <VBox/vmm/pgm.h> /* required by DevVGA.h */
32#include <VBoxVideo.h> /* required by DevVGA.h */
33
34/* should go BEFORE any other DevVGA include to make all DevVGA.h config defines be visible */
35#include "DevVGA.h"
36
37#include "DevVGA-SVGA.h"
38#include "DevVGA-SVGA3d.h"
39#define VMSVGA3D_INCL_STRUCTURE_DESCRIPTORS
40#include "DevVGA-SVGA3d-internal.h"
41#include "DevVGA-SVGA-internal.h"
42
43
44static int vmsvga3dSurfaceAllocMipLevels(PVMSVGA3DSURFACE pSurface)
45{
46 /* Allocate buffer to hold the surface data until we can move it into a D3D object */
47 for (uint32_t i = 0; i < pSurface->cLevels * pSurface->cFaces; ++i)
48 {
49 PVMSVGA3DMIPMAPLEVEL pMipmapLevel = &pSurface->paMipmapLevels[i];
50 AssertReturn(pMipmapLevel->pSurfaceData == NULL, VERR_INVALID_STATE);
51 pMipmapLevel->pSurfaceData = RTMemAllocZ(pMipmapLevel->cbSurface);
52 AssertReturn(pMipmapLevel->pSurfaceData, VERR_NO_MEMORY);
53 }
54 return VINF_SUCCESS;
55}
56
57
58static void vmsvga3dSurfaceFreeMipLevels(PVMSVGA3DSURFACE pSurface)
59{
60 for (uint32_t i = 0; i < pSurface->cLevels * pSurface->cFaces; ++i)
61 {
62 PVMSVGA3DMIPMAPLEVEL pMipmapLevel = &pSurface->paMipmapLevels[i];
63 RTMemFreeZ(pMipmapLevel->pSurfaceData, pMipmapLevel->cbSurface);
64 pMipmapLevel->pSurfaceData = NULL;
65 }
66}
67
68
69/**
70 * Implements the SVGA_3D_CMD_SURFACE_DEFINE_V2 and SVGA_3D_CMD_SURFACE_DEFINE
71 * commands (fifo).
72 *
73 * @returns VBox status code (currently ignored).
74 * @param pThisCC The VGA/VMSVGA state for ring-3.
75 * @param sid The ID of the surface to (re-)define.
76 * @param surfaceFlags .
77 * @param format .
78 * @param multisampleCount .
79 * @param autogenFilter .
80 * @param numMipLevels .
81 * @param pMipLevel0Size .
82 * @param fAllocMipLevels .
83 */
84int vmsvga3dSurfaceDefine(PVGASTATECC pThisCC, uint32_t sid, SVGA3dSurface1Flags surfaceFlags, SVGA3dSurfaceFormat format,
85 uint32_t multisampleCount, SVGA3dTextureFilter autogenFilter,
86 uint32_t numMipLevels, SVGA3dSize const *pMipLevel0Size, bool fAllocMipLevels)
87{
88 PVMSVGA3DSURFACE pSurface;
89 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
90 AssertReturn(pState, VERR_INVALID_STATE);
91
92 LogFunc(("sid=%u surfaceFlags=%#x format=%s (%#x) multiSampleCount=%d autogenFilter=%d, numMipLevels=%d size=(%dx%dx%d)\n",
93 sid, surfaceFlags, vmsvgaLookupEnum((int)format, &g_SVGA3dSurfaceFormat2String), format, multisampleCount, autogenFilter,
94 numMipLevels, pMipLevel0Size->width, pMipLevel0Size->height, pMipLevel0Size->depth));
95
96 ASSERT_GUEST_RETURN(sid < SVGA3D_MAX_SURFACE_IDS, VERR_INVALID_PARAMETER);
97 ASSERT_GUEST_RETURN(numMipLevels >= 1 && numMipLevels < SVGA3D_MAX_MIP_LEVELS, VERR_INVALID_PARAMETER);
98
99 if (sid >= pState->cSurfaces)
100 {
101 /* Grow the array. */
102 uint32_t cNew = RT_ALIGN(sid + 15, 16);
103 void *pvNew = RTMemRealloc(pState->papSurfaces, sizeof(pState->papSurfaces[0]) * cNew);
104 AssertReturn(pvNew, VERR_NO_MEMORY);
105 pState->papSurfaces = (PVMSVGA3DSURFACE *)pvNew;
106 while (pState->cSurfaces < cNew)
107 {
108 pSurface = (PVMSVGA3DSURFACE)RTMemAllocZ(sizeof(*pSurface));
109 AssertReturn(pSurface, VERR_NO_MEMORY);
110 pSurface->id = SVGA3D_INVALID_ID;
111 pState->papSurfaces[pState->cSurfaces++] = pSurface;
112 }
113 }
114 pSurface = pState->papSurfaces[sid];
115
116 /* If one already exists with this id, then destroy it now. */
117 if (pSurface->id != SVGA3D_INVALID_ID)
118 vmsvga3dSurfaceDestroy(pThisCC, sid);
119
120 RT_ZERO(*pSurface);
121 // pSurface->pBackendSurface = NULL;
122 pSurface->id = SVGA3D_INVALID_ID; /* Keep this value until the surface init completes */
123 pSurface->idAssociatedContext = SVGA3D_INVALID_ID;
124
125 /** @todo This 'switch' and the surfaceFlags tweaks should not be necessary.
126 * The actual surface type will be figured out when the surface is actually used later.
127 * The backends code must be reviewed for unnecessary dependencies on the surfaceFlags value.
128 */
129 /* The surface type is sort of undefined now, even though the hints and format can help to clear that up.
130 * In some case we'll have to wait until the surface is used to create the D3D object.
131 */
132 switch (format)
133 {
134 case SVGA3D_Z_D32:
135 case SVGA3D_Z_D16:
136 case SVGA3D_Z_D24S8:
137 case SVGA3D_Z_D15S1:
138 case SVGA3D_Z_D24X8:
139 case SVGA3D_Z_DF16:
140 case SVGA3D_Z_DF24:
141 case SVGA3D_Z_D24S8_INT:
142 Assert(surfaceFlags & SVGA3D_SURFACE_HINT_DEPTHSTENCIL);
143 surfaceFlags |= SVGA3D_SURFACE_HINT_DEPTHSTENCIL;
144 break;
145
146 /* Texture compression formats */
147 case SVGA3D_DXT1:
148 case SVGA3D_DXT2:
149 case SVGA3D_DXT3:
150 case SVGA3D_DXT4:
151 case SVGA3D_DXT5:
152 /* Bump-map formats */
153 case SVGA3D_BUMPU8V8:
154 case SVGA3D_BUMPL6V5U5:
155 case SVGA3D_BUMPX8L8V8U8:
156 case SVGA3D_V8U8:
157 case SVGA3D_Q8W8V8U8:
158 case SVGA3D_CxV8U8:
159 case SVGA3D_X8L8V8U8:
160 case SVGA3D_A2W10V10U10:
161 case SVGA3D_V16U16:
162 /* Typical render target formats; we should allow render target buffers to be used as textures. */
163 case SVGA3D_X8R8G8B8:
164 case SVGA3D_A8R8G8B8:
165 case SVGA3D_R5G6B5:
166 case SVGA3D_X1R5G5B5:
167 case SVGA3D_A1R5G5B5:
168 case SVGA3D_A4R4G4B4:
169 Assert(surfaceFlags & (SVGA3D_SURFACE_HINT_TEXTURE | SVGA3D_SURFACE_SCREENTARGET));
170 surfaceFlags |= SVGA3D_SURFACE_HINT_TEXTURE;
171 break;
172
173 case SVGA3D_LUMINANCE8:
174 case SVGA3D_LUMINANCE4_ALPHA4:
175 case SVGA3D_LUMINANCE16:
176 case SVGA3D_LUMINANCE8_ALPHA8:
177 case SVGA3D_ARGB_S10E5: /* 16-bit floating-point ARGB */
178 case SVGA3D_ARGB_S23E8: /* 32-bit floating-point ARGB */
179 case SVGA3D_A2R10G10B10:
180 case SVGA3D_ALPHA8:
181 case SVGA3D_R_S10E5:
182 case SVGA3D_R_S23E8:
183 case SVGA3D_RG_S10E5:
184 case SVGA3D_RG_S23E8:
185 case SVGA3D_G16R16:
186 case SVGA3D_A16B16G16R16:
187 case SVGA3D_UYVY:
188 case SVGA3D_YUY2:
189 case SVGA3D_NV12:
190 case SVGA3D_FORMAT_DEAD2: /* Old SVGA3D_AYUV */
191 case SVGA3D_ATI1:
192 case SVGA3D_ATI2:
193 break;
194
195 /*
196 * Any surface can be used as a buffer object, but SVGA3D_BUFFER is
197 * the most efficient format to use when creating new surfaces
198 * expressly for index or vertex data.
199 */
200 case SVGA3D_BUFFER:
201 break;
202
203 default:
204 break;
205 }
206
207 pSurface->surfaceFlags = surfaceFlags;
208 pSurface->format = format;
209 /* cFaces is 6 for a cubemaps and 1 otherwise. */
210 pSurface->cFaces = (uint32_t)((surfaceFlags & SVGA3D_SURFACE_CUBEMAP) ? 6 : 1);
211 pSurface->cLevels = numMipLevels;
212 pSurface->multiSampleCount = multisampleCount;
213 pSurface->autogenFilter = autogenFilter;
214 Assert(autogenFilter != SVGA3D_TEX_FILTER_FLATCUBIC);
215 Assert(autogenFilter != SVGA3D_TEX_FILTER_GAUSSIANCUBIC);
216 pSurface->paMipmapLevels = (PVMSVGA3DMIPMAPLEVEL)RTMemAllocZ(numMipLevels * pSurface->cFaces * sizeof(VMSVGA3DMIPMAPLEVEL));
217 AssertReturn(pSurface->paMipmapLevels, VERR_NO_MEMORY);
218
219 pSurface->cbBlock = vmsvga3dSurfaceFormatSize(format, &pSurface->cxBlock, &pSurface->cyBlock);
220 AssertReturn(pSurface->cbBlock, VERR_INVALID_PARAMETER);
221
222 /** @todo cbMemRemaining = value of SVGA_REG_MOB_MAX_SIZE */
223 uint32_t cbMemRemaining = SVGA3D_MAX_SURFACE_MEM_SIZE; /* Do not allow more than this for a surface. */
224 SVGA3dSize mipmapSize = *pMipLevel0Size;
225 int rc = VINF_SUCCESS;
226
227 for (uint32_t i = 0; i < numMipLevels; ++i)
228 {
229 for (uint32_t iFace = 0; iFace < pSurface->cFaces; ++iFace)
230 {
231 uint32_t const iMipmap = iFace * numMipLevels + i;
232 LogFunc(("[%d] face %d mip level %d (%d,%d,%d) cbBlock=%#x block %dx%d\n",
233 iMipmap, iFace, i, mipmapSize.width, mipmapSize.height, mipmapSize.depth,
234 pSurface->cbBlock, pSurface->cxBlock, pSurface->cyBlock));
235
236 uint32_t cBlocksX;
237 uint32_t cBlocksY;
238 if (RT_LIKELY(pSurface->cxBlock == 1 && pSurface->cyBlock == 1))
239 {
240 cBlocksX = mipmapSize.width;
241 cBlocksY = mipmapSize.height;
242 }
243 else
244 {
245 cBlocksX = mipmapSize.width / pSurface->cxBlock;
246 if (mipmapSize.width % pSurface->cxBlock)
247 ++cBlocksX;
248 cBlocksY = mipmapSize.height / pSurface->cyBlock;
249 if (mipmapSize.height % pSurface->cyBlock)
250 ++cBlocksY;
251 }
252
253 AssertBreakStmt(cBlocksX > 0 && cBlocksY > 0 && mipmapSize.depth > 0, rc = VERR_INVALID_PARAMETER);
254
255 const uint32_t cMaxBlocksX = cbMemRemaining / pSurface->cbBlock;
256 AssertBreakStmt(cBlocksX < cMaxBlocksX, rc = VERR_INVALID_PARAMETER);
257
258 const uint32_t cbSurfacePitch = pSurface->cbBlock * cBlocksX;
259 LogFunc(("cbSurfacePitch=0x%x\n", cbSurfacePitch));
260
261 const uint32_t cMaxBlocksY = cbMemRemaining / cbSurfacePitch;
262 AssertBreakStmt(cBlocksY < cMaxBlocksY, rc = VERR_INVALID_PARAMETER);
263
264 const uint32_t cbSurfacePlane = cbSurfacePitch * cBlocksY;
265
266 const uint32_t cMaxDepth = cbMemRemaining / cbSurfacePlane;
267 AssertBreakStmt(mipmapSize.depth < cMaxDepth, rc = VERR_INVALID_PARAMETER);
268
269 const uint32_t cbSurface = cbSurfacePlane * mipmapSize.depth;
270
271 PVMSVGA3DMIPMAPLEVEL pMipmapLevel = &pSurface->paMipmapLevels[iMipmap];
272 pMipmapLevel->mipmapSize = mipmapSize;
273 pMipmapLevel->cBlocksX = cBlocksX;
274 pMipmapLevel->cBlocksY = cBlocksY;
275 pMipmapLevel->cBlocks = cBlocksX * cBlocksY * mipmapSize.depth;
276 pMipmapLevel->cbSurfacePitch = cbSurfacePitch;
277 pMipmapLevel->cbSurfacePlane = cbSurfacePlane;
278 pMipmapLevel->cbSurface = cbSurface;
279 pMipmapLevel->pSurfaceData = NULL;
280
281 cbMemRemaining -= cbSurface;
282 }
283
284 AssertRCBreak(rc);
285
286 mipmapSize.width >>= 1;
287 if (mipmapSize.width == 0) mipmapSize.width = 1;
288 mipmapSize.height >>= 1;
289 if (mipmapSize.height == 0) mipmapSize.height = 1;
290 mipmapSize.depth >>= 1;
291 if (mipmapSize.depth == 0) mipmapSize.depth = 1;
292 }
293
294 AssertLogRelRCReturnStmt(rc, RTMemFree(pSurface->paMipmapLevels), rc);
295
296 if (vmsvga3dIsLegacyBackend(pThisCC))
297 {
298#ifdef VMSVGA3D_DIRECT3D
299 /* pSurface->hSharedObject = NULL; */
300 /* pSurface->pSharedObjectTree = NULL; */
301 /* Translate the format and usage flags to D3D. */
302 pSurface->d3dfmtRequested = vmsvga3dSurfaceFormat2D3D(format);
303 pSurface->formatD3D = D3D9GetActualFormat(pState, pSurface->d3dfmtRequested);
304 pSurface->multiSampleTypeD3D= vmsvga3dMultipeSampleCount2D3D(multisampleCount);
305 pSurface->fUsageD3D = 0;
306 if (surfaceFlags & SVGA3D_SURFACE_HINT_DYNAMIC)
307 pSurface->fUsageD3D |= D3DUSAGE_DYNAMIC;
308 if (surfaceFlags & SVGA3D_SURFACE_HINT_RENDERTARGET)
309 pSurface->fUsageD3D |= D3DUSAGE_RENDERTARGET;
310 if (surfaceFlags & SVGA3D_SURFACE_HINT_DEPTHSTENCIL)
311 pSurface->fUsageD3D |= D3DUSAGE_DEPTHSTENCIL;
312 if (surfaceFlags & SVGA3D_SURFACE_HINT_WRITEONLY)
313 pSurface->fUsageD3D |= D3DUSAGE_WRITEONLY;
314 if (surfaceFlags & SVGA3D_SURFACE_AUTOGENMIPMAPS)
315 pSurface->fUsageD3D |= D3DUSAGE_AUTOGENMIPMAP;
316 pSurface->enmD3DResType = VMSVGA3D_D3DRESTYPE_NONE;
317 /* pSurface->u.pSurface = NULL; */
318 /* pSurface->bounce.pTexture = NULL; */
319 /* pSurface->emulated.pTexture = NULL; */
320#else
321 /* pSurface->oglId.buffer = OPENGL_INVALID_ID; */
322 /* pSurface->fEmulated = false; */
323 /* pSurface->idEmulated = OPENGL_INVALID_ID; */
324 vmsvga3dSurfaceFormat2OGL(pSurface, format);
325#endif
326 }
327
328#ifdef LOG_ENABLED
329 SVGA3dSurfaceAllFlags const f = surfaceFlags;
330 LogFunc(("surface flags:%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s 0x%RX64\n",
331 (f & SVGA3D_SURFACE_CUBEMAP) ? " CUBEMAP" : "",
332 (f & SVGA3D_SURFACE_HINT_STATIC) ? " HINT_STATIC" : "",
333 (f & SVGA3D_SURFACE_HINT_DYNAMIC) ? " HINT_DYNAMIC" : "",
334 (f & SVGA3D_SURFACE_HINT_INDEXBUFFER) ? " HINT_INDEXBUFFER" : "",
335 (f & SVGA3D_SURFACE_HINT_VERTEXBUFFER) ? " HINT_VERTEXBUFFER" : "",
336 (f & SVGA3D_SURFACE_HINT_TEXTURE) ? " HINT_TEXTURE" : "",
337 (f & SVGA3D_SURFACE_HINT_RENDERTARGET) ? " HINT_RENDERTARGET" : "",
338 (f & SVGA3D_SURFACE_HINT_DEPTHSTENCIL) ? " HINT_DEPTHSTENCIL" : "",
339 (f & SVGA3D_SURFACE_HINT_WRITEONLY) ? " HINT_WRITEONLY" : "",
340 (f & SVGA3D_SURFACE_DEAD2) ? " DEAD2" : "",
341 (f & SVGA3D_SURFACE_AUTOGENMIPMAPS) ? " AUTOGENMIPMAPS" : "",
342 (f & SVGA3D_SURFACE_DEAD1) ? " DEAD1" : "",
343 (f & SVGA3D_SURFACE_MOB_PITCH) ? " MOB_PITCH" : "",
344 (f & SVGA3D_SURFACE_INACTIVE) ? " INACTIVE" : "",
345 (f & SVGA3D_SURFACE_HINT_RT_LOCKABLE) ? " HINT_RT_LOCKABLE" : "",
346 (f & SVGA3D_SURFACE_VOLUME) ? " VOLUME" : "",
347 (f & SVGA3D_SURFACE_SCREENTARGET) ? " SCREENTARGET" : "",
348 (f & SVGA3D_SURFACE_ALIGN16) ? " ALIGN16" : "",
349 (f & SVGA3D_SURFACE_1D) ? " 1D" : "",
350 (f & SVGA3D_SURFACE_ARRAY) ? " ARRAY" : "",
351 (f & SVGA3D_SURFACE_BIND_VERTEX_BUFFER) ? " BIND_VERTEX_BUFFER" : "",
352 (f & SVGA3D_SURFACE_BIND_INDEX_BUFFER) ? " BIND_INDEX_BUFFER" : "",
353 (f & SVGA3D_SURFACE_BIND_CONSTANT_BUFFER) ? " BIND_CONSTANT_BUFFER" : "",
354 (f & SVGA3D_SURFACE_BIND_SHADER_RESOURCE) ? " BIND_SHADER_RESOURCE" : "",
355 (f & SVGA3D_SURFACE_BIND_RENDER_TARGET) ? " BIND_RENDER_TARGET" : "",
356 (f & SVGA3D_SURFACE_BIND_DEPTH_STENCIL) ? " BIND_DEPTH_STENCIL" : "",
357 (f & SVGA3D_SURFACE_BIND_STREAM_OUTPUT) ? " BIND_STREAM_OUTPUT" : "",
358 (f & SVGA3D_SURFACE_STAGING_UPLOAD) ? " STAGING_UPLOAD" : "",
359 (f & SVGA3D_SURFACE_STAGING_DOWNLOAD) ? " STAGING_DOWNLOAD" : "",
360 (f & SVGA3D_SURFACE_HINT_INDIRECT_UPDATE) ? " HINT_INDIRECT_UPDATE" : "",
361 (f & SVGA3D_SURFACE_TRANSFER_FROM_BUFFER) ? " TRANSFER_FROM_BUFFER" : "",
362 (f & SVGA3D_SURFACE_RESERVED1) ? " RESERVED1" : "",
363 (f & SVGA3D_SURFACE_MULTISAMPLE) ? " MULTISAMPLE" : "",
364 (f & SVGA3D_SURFACE_BIND_UAVIEW) ? " BIND_UAVIEW" : "",
365 (f & SVGA3D_SURFACE_TRANSFER_TO_BUFFER) ? " TRANSFER_TO_BUFFER" : "",
366 (f & SVGA3D_SURFACE_BIND_LOGICOPS) ? " BIND_LOGICOPS" : "",
367 (f & SVGA3D_SURFACE_BIND_RAW_VIEWS) ? " BIND_RAW_VIEWS" : "",
368 (f & SVGA3D_SURFACE_BUFFER_STRUCTURED) ? " BUFFER_STRUCTURED" : "",
369 (f & SVGA3D_SURFACE_DRAWINDIRECT_ARGS) ? " DRAWINDIRECT_ARGS" : "",
370 (f & SVGA3D_SURFACE_RESOURCE_CLAMP) ? " RESOURCE_CLAMP" : "",
371 (f & SVGA3D_SURFACE_FLAG_MAX) ? " FLAG_MAX" : "",
372 f & ~(SVGA3D_SURFACE_FLAG_MAX - 1ULL)
373 ));
374#endif
375
376 Assert(!VMSVGA3DSURFACE_HAS_HW_SURFACE(pSurface));
377
378 if (fAllocMipLevels)
379 {
380 rc = vmsvga3dSurfaceAllocMipLevels(pSurface);
381 AssertRCReturn(rc, rc);
382 }
383
384 pSurface->id = sid;
385 return VINF_SUCCESS;
386}
387
388
389/**
390 * Implements the SVGA_3D_CMD_SURFACE_DESTROY command (fifo).
391 *
392 * @returns VBox status code (currently ignored).
393 * @param pThisCC The VGA/VMSVGA state for ring-3.
394 * @param sid The ID of the surface to destroy.
395 */
396int vmsvga3dSurfaceDestroy(PVGASTATECC pThisCC, uint32_t sid)
397{
398 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
399 AssertReturn(pState, VERR_NO_MEMORY);
400
401 PVMSVGA3DSURFACE pSurface;
402 int rc = vmsvga3dSurfaceFromSid(pState, sid, &pSurface);
403 AssertRCReturn(rc, rc);
404
405 LogFunc(("sid=%u\n", sid));
406
407 /* Check all contexts if this surface is used as a render target or active texture. */
408 for (uint32_t cid = 0; cid < pState->cContexts; cid++)
409 {
410 PVMSVGA3DCONTEXT pContext = pState->papContexts[cid];
411 if (pContext->id == cid)
412 {
413 for (uint32_t i = 0; i < RT_ELEMENTS(pContext->aSidActiveTextures); ++i)
414 if (pContext->aSidActiveTextures[i] == sid)
415 pContext->aSidActiveTextures[i] = SVGA3D_INVALID_ID;
416 for (uint32_t i = 0; i < RT_ELEMENTS(pContext->state.aRenderTargets); ++i)
417 if (pContext->state.aRenderTargets[i] == sid)
418 pContext->state.aRenderTargets[i] = SVGA3D_INVALID_ID;
419 }
420 }
421
422 PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
423 if (pSvgaR3State->pFuncs3D)
424 pSvgaR3State->pFuncs3D->pfnSurfaceDestroy(pThisCC, pSurface);
425
426 if (pSurface->paMipmapLevels)
427 {
428 vmsvga3dSurfaceFreeMipLevels(pSurface);
429 RTMemFree(pSurface->paMipmapLevels);
430 }
431
432 memset(pSurface, 0, sizeof(*pSurface));
433 pSurface->id = SVGA3D_INVALID_ID;
434
435 return VINF_SUCCESS;
436}
437
438
439/**
440 * Implements the SVGA_3D_CMD_SURFACE_STRETCHBLT command (fifo).
441 *
442 * @returns VBox status code (currently ignored).
443 * @param pThis The shared VGA/VMSVGA state.
444 * @param pThisCC The VGA/VMSVGA state for ring-3.
445 * @param pDstSfcImg
446 * @param pDstBox
447 * @param pSrcSfcImg
448 * @param pSrcBox
449 * @param enmMode
450 */
451int vmsvga3dSurfaceStretchBlt(PVGASTATE pThis, PVGASTATECC pThisCC, SVGA3dSurfaceImageId const *pDstSfcImg, SVGA3dBox const *pDstBox,
452 SVGA3dSurfaceImageId const *pSrcSfcImg, SVGA3dBox const *pSrcBox, SVGA3dStretchBltMode enmMode)
453{
454 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
455 AssertReturn(pState, VERR_NO_MEMORY);
456
457 int rc;
458
459 uint32_t const sidSrc = pSrcSfcImg->sid;
460 PVMSVGA3DSURFACE pSrcSurface;
461 rc = vmsvga3dSurfaceFromSid(pState, sidSrc, &pSrcSurface);
462 AssertRCReturn(rc, rc);
463
464 uint32_t const sidDst = pDstSfcImg->sid;
465 PVMSVGA3DSURFACE pDstSurface;
466 rc = vmsvga3dSurfaceFromSid(pState, sidDst, &pDstSurface);
467 AssertRCReturn(rc, rc);
468
469 AssertReturn(pSrcSfcImg->face < pSrcSurface->cFaces, VERR_INVALID_PARAMETER);
470 AssertReturn(pSrcSfcImg->mipmap < pSrcSurface->cLevels, VERR_INVALID_PARAMETER);
471 AssertReturn(pDstSfcImg->face < pDstSurface->cFaces, VERR_INVALID_PARAMETER);
472 AssertReturn(pDstSfcImg->mipmap < pDstSurface->cLevels, VERR_INVALID_PARAMETER);
473
474 PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
475 AssertReturn(pSvgaR3State->pFuncs3D, VERR_NOT_IMPLEMENTED);
476
477 PVMSVGA3DCONTEXT pContext;
478#ifdef VMSVGA3D_OPENGL
479 LogFunc(("src sid=%u (%d,%d)(%d,%d) dest sid=%u (%d,%d)(%d,%d) mode=%x\n",
480 sidSrc, pSrcBox->x, pSrcBox->y, pSrcBox->x + pSrcBox->w, pSrcBox->y + pSrcBox->h,
481 sidDst, pDstBox->x, pDstBox->y, pDstBox->x + pDstBox->w, pDstBox->y + pDstBox->h, enmMode));
482 pContext = &pState->SharedCtx;
483 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
484#else
485 LogFunc(("src sid=%u cid=%u (%d,%d)(%d,%d) dest sid=%u cid=%u (%d,%d)(%d,%d) mode=%x\n",
486 sidSrc, pSrcSurface->idAssociatedContext, pSrcBox->x, pSrcBox->y, pSrcBox->x + pSrcBox->w, pSrcBox->y + pSrcBox->h,
487 sidDst, pDstSurface->idAssociatedContext, pDstBox->x, pDstBox->y, pDstBox->x + pDstBox->w, pDstBox->y + pDstBox->h, enmMode));
488
489 uint32_t cid = pDstSurface->idAssociatedContext;
490 if (cid == SVGA3D_INVALID_ID)
491 cid = pSrcSurface->idAssociatedContext;
492
493 /* At least one of surfaces must be in hardware. */
494 AssertReturn(cid != SVGA3D_INVALID_ID, VERR_INVALID_PARAMETER);
495
496 rc = vmsvga3dContextFromCid(pState, cid, &pContext);
497 AssertRCReturn(rc, rc);
498#endif
499
500 if (!VMSVGA3DSURFACE_HAS_HW_SURFACE(pSrcSurface))
501 {
502 /* Unknown surface type; turn it into a texture, which can be used for other purposes too. */
503 LogFunc(("unknown src sid=%u type=%d format=%d -> create texture\n", sidSrc, pSrcSurface->surfaceFlags, pSrcSurface->format));
504 rc = pSvgaR3State->pFuncs3D->pfnCreateTexture(pThisCC, pContext, pContext->id, pSrcSurface);
505 AssertRCReturn(rc, rc);
506 }
507
508 if (!VMSVGA3DSURFACE_HAS_HW_SURFACE(pDstSurface))
509 {
510 /* Unknown surface type; turn it into a texture, which can be used for other purposes too. */
511 LogFunc(("unknown dest sid=%u type=%d format=%d -> create texture\n", sidDst, pDstSurface->surfaceFlags, pDstSurface->format));
512 rc = pSvgaR3State->pFuncs3D->pfnCreateTexture(pThisCC, pContext, pContext->id, pDstSurface);
513 AssertRCReturn(rc, rc);
514 }
515
516 PVMSVGA3DMIPMAPLEVEL pSrcMipmapLevel;
517 rc = vmsvga3dMipmapLevel(pSrcSurface, pSrcSfcImg->face, pSrcSfcImg->mipmap, &pSrcMipmapLevel);
518 AssertRCReturn(rc, rc);
519
520 PVMSVGA3DMIPMAPLEVEL pDstMipmapLevel;
521 rc = vmsvga3dMipmapLevel(pDstSurface, pDstSfcImg->face, pDstSfcImg->mipmap, &pDstMipmapLevel);
522 AssertRCReturn(rc, rc);
523
524 SVGA3dBox clipSrcBox = *pSrcBox;
525 SVGA3dBox clipDstBox = *pDstBox;
526 vmsvgaR3ClipBox(&pSrcMipmapLevel->mipmapSize, &clipSrcBox);
527 vmsvgaR3ClipBox(&pDstMipmapLevel->mipmapSize, &clipDstBox);
528
529 return pSvgaR3State->pFuncs3D->pfnSurfaceStretchBlt(pThis, pState,
530 pDstSurface, pDstSfcImg->face, pDstSfcImg->mipmap, &clipDstBox,
531 pSrcSurface, pSrcSfcImg->face, pSrcSfcImg->mipmap, &clipSrcBox,
532 enmMode, pContext);
533}
534
535/**
536 * Implements the SVGA_3D_CMD_SURFACE_DMA command (fifo).
537 *
538 * @returns VBox status code (currently ignored).
539 * @param pThis The shared VGA/VMSVGA instance data.
540 * @param pThisCC The VGA/VMSVGA state for ring-3.
541 * @param guest .
542 * @param host .
543 * @param transfer .
544 * @param cCopyBoxes .
545 * @param paBoxes .
546 */
547int vmsvga3dSurfaceDMA(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAGuestImage guest, SVGA3dSurfaceImageId host,
548 SVGA3dTransferType transfer, uint32_t cCopyBoxes, SVGA3dCopyBox *paBoxes)
549{
550 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
551 AssertReturn(pState, VERR_NO_MEMORY);
552
553 PVMSVGA3DSURFACE pSurface;
554 int rc = vmsvga3dSurfaceFromSid(pState, host.sid, &pSurface);
555 AssertRCReturn(rc, rc);
556
557 LogFunc(("%sguestptr gmr=%x offset=%x pitch=%x host sid=%u face=%d mipmap=%d transfer=%s cCopyBoxes=%d\n",
558 (pSurface->surfaceFlags & SVGA3D_SURFACE_HINT_TEXTURE) ? "TEXTURE " : "",
559 guest.ptr.gmrId, guest.ptr.offset, guest.pitch,
560 host.sid, host.face, host.mipmap, (transfer == SVGA3D_WRITE_HOST_VRAM) ? "READ" : "WRITE", cCopyBoxes));
561
562 PVMSVGA3DMIPMAPLEVEL pMipLevel;
563 rc = vmsvga3dMipmapLevel(pSurface, host.face, host.mipmap, &pMipLevel);
564 AssertRCReturn(rc, rc);
565
566 PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
567 AssertReturn(pSvgaR3State->pFuncs3D, VERR_NOT_IMPLEMENTED);
568
569 PVMSVGA3DCONTEXT pContext = NULL;
570 if (!VMSVGA3DSURFACE_HAS_HW_SURFACE(pSurface))
571 {
572 /*
573 * Not realized in host hardware/library yet, we have to work with
574 * the copy of the data we've got in VMSVGA3DMIMAPLEVEL::pSurfaceData.
575 */
576 if (!pMipLevel->pSurfaceData)
577 {
578 rc = vmsvga3dSurfaceAllocMipLevels(pSurface);
579 AssertRCReturn(rc, rc);
580 }
581 }
582 else if (vmsvga3dIsLegacyBackend(pThisCC))
583 {
584#ifdef VMSVGA3D_DIRECT3D
585 /* Flush the drawing pipeline for this surface as it could be used in a shared context. */
586 vmsvga3dSurfaceFlush(pSurface);
587#else /* VMSVGA3D_OPENGL */
588 pContext = &pState->SharedCtx;
589 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
590#endif
591 }
592
593 /* SVGA_3D_CMD_SURFACE_DMA:
594 * "define the 'source' in each copyBox as the guest image and the
595 * 'destination' as the host image, regardless of transfer direction."
596 */
597 for (uint32_t i = 0; i < cCopyBoxes; ++i)
598 {
599 Log(("Copy box (%s) %d (%d,%d,%d)(%d,%d,%d) dest (%d,%d)\n",
600 VMSVGA3DSURFACE_HAS_HW_SURFACE(pSurface) ? "hw" : "mem",
601 i, paBoxes[i].srcx, paBoxes[i].srcy, paBoxes[i].srcz, paBoxes[i].w, paBoxes[i].h, paBoxes[i].d, paBoxes[i].x, paBoxes[i].y));
602
603 /* Apparently we're supposed to clip it (gmr test sample) */
604
605 /* The copybox's "dest" is coords in the host surface. Verify them against the surface's mipmap size. */
606 SVGA3dBox hostBox;
607 hostBox.x = paBoxes[i].x;
608 hostBox.y = paBoxes[i].y;
609 hostBox.z = paBoxes[i].z;
610 hostBox.w = paBoxes[i].w;
611 hostBox.h = paBoxes[i].h;
612 hostBox.d = paBoxes[i].d;
613 vmsvgaR3ClipBox(&pMipLevel->mipmapSize, &hostBox);
614
615 if ( !hostBox.w
616 || !hostBox.h
617 || !hostBox.d)
618 {
619 Log(("Skip empty box\n"));
620 continue;
621 }
622 RT_UNTRUSTED_VALIDATED_FENCE();
623
624 /* Adjust the guest, i.e. "src", point.
625 * Do not try to verify them here because vmsvgaR3GmrTransfer takes care of this.
626 */
627 uint32_t const srcx = paBoxes[i].srcx + (hostBox.x - paBoxes[i].x);
628 uint32_t const srcy = paBoxes[i].srcy + (hostBox.y - paBoxes[i].y);
629 uint32_t const srcz = paBoxes[i].srcz + (hostBox.z - paBoxes[i].z);
630
631 /* Calculate offsets of the image blocks for the transfer. */
632 uint32_t u32HostBlockX;
633 uint32_t u32HostBlockY;
634 uint32_t u32GuestBlockX;
635 uint32_t u32GuestBlockY;
636 uint32_t cBlocksX;
637 uint32_t cBlocksY;
638 if (RT_LIKELY(pSurface->cxBlock == 1 && pSurface->cyBlock == 1))
639 {
640 u32HostBlockX = hostBox.x;
641 u32HostBlockY = hostBox.y;
642
643 u32GuestBlockX = srcx;
644 u32GuestBlockY = srcy;
645
646 cBlocksX = hostBox.w;
647 cBlocksY = hostBox.h;
648 }
649 else
650 {
651 /* Pixels to blocks. */
652 u32HostBlockX = hostBox.x / pSurface->cxBlock;
653 u32HostBlockY = hostBox.y / pSurface->cyBlock;
654 Assert(u32HostBlockX * pSurface->cxBlock == hostBox.x);
655 Assert(u32HostBlockY * pSurface->cyBlock == hostBox.y);
656
657 u32GuestBlockX = srcx / pSurface->cxBlock;
658 u32GuestBlockY = srcy / pSurface->cyBlock;
659 Assert(u32GuestBlockX * pSurface->cxBlock == srcx);
660 Assert(u32GuestBlockY * pSurface->cyBlock == srcy);
661
662 cBlocksX = (hostBox.w + pSurface->cxBlock - 1) / pSurface->cxBlock;
663 cBlocksY = (hostBox.h + pSurface->cyBlock - 1) / pSurface->cyBlock;
664 }
665
666 uint32_t cbGuestPitch = guest.pitch;
667 if (cbGuestPitch == 0)
668 {
669 /* Host must "assume image is tightly packed". Our surfaces are. */
670 cbGuestPitch = pMipLevel->cbSurfacePitch;
671 }
672 else
673 {
674 /* vmsvgaR3GmrTransfer will verify the value, just check it is sane. */
675 AssertReturn(cbGuestPitch <= SVGA3D_MAX_SURFACE_MEM_SIZE, VERR_INVALID_PARAMETER);
676 RT_UNTRUSTED_VALIDATED_FENCE();
677 }
678
679 /* srcx, srcy and srcz values are used to calculate the guest offset.
680 * The offset will be verified by vmsvgaR3GmrTransfer, so just check for overflows here.
681 */
682 AssertReturn(srcz < UINT32_MAX / pMipLevel->mipmapSize.height / cbGuestPitch, VERR_INVALID_PARAMETER);
683 AssertReturn(u32GuestBlockY < UINT32_MAX / cbGuestPitch, VERR_INVALID_PARAMETER);
684 AssertReturn(u32GuestBlockX < UINT32_MAX / pSurface->cbBlock, VERR_INVALID_PARAMETER);
685 RT_UNTRUSTED_VALIDATED_FENCE();
686
687 if ( !VMSVGA3DSURFACE_HAS_HW_SURFACE(pSurface)
688 || VMSVGA3DSURFACE_NEEDS_DATA(pSurface))
689 {
690 uint64_t uGuestOffset = u32GuestBlockX * pSurface->cbBlock +
691 u32GuestBlockY * cbGuestPitch +
692 srcz * pMipLevel->mipmapSize.height * cbGuestPitch;
693 AssertReturn(uGuestOffset < UINT32_MAX, VERR_INVALID_PARAMETER);
694
695 /* vmsvga3dSurfaceDefine verifies the surface dimensions and clipBox is within them. */
696 uint32_t uHostOffset = u32HostBlockX * pSurface->cbBlock +
697 u32HostBlockY * pMipLevel->cbSurfacePitch +
698 hostBox.z * pMipLevel->cbSurfacePlane;
699 AssertReturn(uHostOffset < pMipLevel->cbSurface, VERR_INTERNAL_ERROR);
700
701 for (uint32_t z = 0; z < hostBox.d; ++z)
702 {
703 rc = vmsvgaR3GmrTransfer(pThis,
704 pThisCC,
705 transfer,
706 (uint8_t *)pMipLevel->pSurfaceData,
707 pMipLevel->cbSurface,
708 uHostOffset,
709 (int32_t)pMipLevel->cbSurfacePitch,
710 guest.ptr,
711 (uint32_t)uGuestOffset,
712 cbGuestPitch,
713 cBlocksX * pSurface->cbBlock,
714 cBlocksY);
715 AssertRC(rc);
716
717 Log4(("first line [z=%d] (updated at offset 0x%x):\n%.*Rhxd\n",
718 z, uHostOffset, pMipLevel->cbSurfacePitch, pMipLevel->pSurfaceData));
719
720 uHostOffset += pMipLevel->cbSurfacePlane;
721 uGuestOffset += pMipLevel->mipmapSize.height * cbGuestPitch;
722 AssertReturn(uGuestOffset < UINT32_MAX, VERR_INVALID_PARAMETER);
723 }
724 }
725
726 if (VMSVGA3DSURFACE_HAS_HW_SURFACE(pSurface))
727 {
728 SVGA3dCopyBox clipBox;
729 clipBox.x = hostBox.x;
730 clipBox.y = hostBox.y;
731 clipBox.z = hostBox.z;
732 clipBox.w = hostBox.w;
733 clipBox.h = hostBox.h;
734 clipBox.d = hostBox.d;
735 clipBox.srcx = srcx;
736 clipBox.srcy = srcy;
737 clipBox.srcz = srcz;
738 rc = pSvgaR3State->pFuncs3D->pfnSurfaceDMACopyBox(pThis, pThisCC, pState, pSurface, pMipLevel, host.face, host.mipmap,
739 guest.ptr, cbGuestPitch, transfer,
740 &clipBox, pContext, rc, i);
741 AssertRC(rc);
742 }
743 }
744
745 if (!VMSVGA3DSURFACE_HAS_HW_SURFACE(pSurface))
746 {
747 pMipLevel->fDirty = true;
748 pSurface->fDirty = true;
749 }
750
751 return rc;
752}
753
754static int vmsvga3dQueryWriteResult(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAGuestPtr const *pGuestResult,
755 SVGA3dQueryState enmState, uint32_t u32Result)
756{
757 SVGA3dQueryResult queryResult;
758 queryResult.totalSize = sizeof(queryResult); /* Set by guest before query is ended. */
759 queryResult.state = enmState; /* Set by host or guest. See SVGA3dQueryState. */
760 queryResult.result32 = u32Result;
761
762 int rc = vmsvgaR3GmrTransfer(pThis, pThisCC, SVGA3D_READ_HOST_VRAM,
763 (uint8_t *)&queryResult, sizeof(queryResult), 0, sizeof(queryResult),
764 *pGuestResult, 0, sizeof(queryResult), sizeof(queryResult), 1);
765 AssertRC(rc);
766 return rc;
767}
768
769/* Used with saved state. */
770int vmsvga3dQueryCreate(PVGASTATECC pThisCC, uint32_t cid, SVGA3dQueryType type)
771{
772 PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
773 AssertReturn(pSvgaR3State->pFuncsVGPU9, VERR_NOT_IMPLEMENTED);
774
775 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
776 AssertReturn(pState, VERR_NO_MEMORY);
777
778 LogFunc(("cid=%u type=%d\n", cid, type));
779
780 PVMSVGA3DCONTEXT pContext;
781 int rc = vmsvga3dContextFromCid(pState, cid, &pContext);
782 AssertRCReturn(rc, rc);
783
784 if (type == SVGA3D_QUERYTYPE_OCCLUSION)
785 {
786 VMSVGA3DQUERY *p = &pContext->occlusion;
787 if (!VMSVGA3DQUERY_EXISTS(p))
788 {
789 rc = pSvgaR3State->pFuncsVGPU9->pfnOcclusionQueryCreate(pThisCC, pContext);
790 AssertRCReturn(rc, rc);
791 }
792
793 return VINF_SUCCESS;
794 }
795
796 /* Nothing else for VGPU9. */
797 AssertFailedReturn(VERR_NOT_IMPLEMENTED);
798}
799
800int vmsvga3dQueryBegin(PVGASTATECC pThisCC, uint32_t cid, SVGA3dQueryType type)
801{
802 PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
803 AssertReturn(pSvgaR3State->pFuncsVGPU9, VERR_NOT_IMPLEMENTED);
804
805 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
806 AssertReturn(pState, VERR_NO_MEMORY);
807
808 LogFunc(("cid=%u type=%d\n", cid, type));
809
810 PVMSVGA3DCONTEXT pContext;
811 int rc = vmsvga3dContextFromCid(pState, cid, &pContext);
812 AssertRCReturn(rc, rc);
813
814 if (type == SVGA3D_QUERYTYPE_OCCLUSION)
815 {
816 VMSVGA3DQUERY *p = &pContext->occlusion;
817 if (!VMSVGA3DQUERY_EXISTS(p))
818 {
819 /* Lazy creation of the query object. */
820 rc = pSvgaR3State->pFuncsVGPU9->pfnOcclusionQueryCreate(pThisCC, pContext);
821 AssertRCReturn(rc, rc);
822 }
823
824 rc = pSvgaR3State->pFuncsVGPU9->pfnOcclusionQueryBegin(pThisCC, pContext);
825 AssertRCReturn(rc, rc);
826
827 p->enmQueryState = VMSVGA3DQUERYSTATE_BUILDING;
828 p->u32QueryResult = 0;
829
830 return VINF_SUCCESS;
831 }
832
833 /* Nothing else for VGPU9. */
834 AssertFailedReturn(VERR_NOT_IMPLEMENTED);
835}
836
837int vmsvga3dQueryEnd(PVGASTATECC pThisCC, uint32_t cid, SVGA3dQueryType type)
838{
839 PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
840 AssertReturn(pSvgaR3State->pFuncsVGPU9, VERR_NOT_IMPLEMENTED);
841
842 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
843 AssertReturn(pState, VERR_NO_MEMORY);
844
845 LogFunc(("cid=%u type=%d\n", cid, type));
846
847 PVMSVGA3DCONTEXT pContext;
848 int rc = vmsvga3dContextFromCid(pState, cid, &pContext);
849 AssertRCReturn(rc, rc);
850
851 if (type == SVGA3D_QUERYTYPE_OCCLUSION)
852 {
853 VMSVGA3DQUERY *p = &pContext->occlusion;
854 Assert(p->enmQueryState == VMSVGA3DQUERYSTATE_BUILDING);
855 AssertMsgReturn(VMSVGA3DQUERY_EXISTS(p), ("Query is NULL\n"), VERR_INTERNAL_ERROR);
856
857 rc = pSvgaR3State->pFuncsVGPU9->pfnOcclusionQueryEnd(pThisCC, pContext);
858 AssertRCReturn(rc, rc);
859
860 p->enmQueryState = VMSVGA3DQUERYSTATE_ISSUED;
861 return VINF_SUCCESS;
862 }
863
864 /* Nothing else for VGPU9. */
865 AssertFailedReturn(VERR_NOT_IMPLEMENTED);
866}
867
868int vmsvga3dQueryWait(PVGASTATECC pThisCC, uint32_t cid, SVGA3dQueryType type, PVGASTATE pThis, SVGAGuestPtr const *pGuestResult)
869{
870 PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
871 AssertReturn(pSvgaR3State->pFuncsVGPU9, VERR_NOT_IMPLEMENTED);
872
873 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
874 AssertReturn(pState, VERR_NO_MEMORY);
875
876 LogFunc(("cid=%u type=%d guestResult GMR%d:0x%x\n", cid, type, pGuestResult->gmrId, pGuestResult->offset));
877
878 PVMSVGA3DCONTEXT pContext;
879 int rc = vmsvga3dContextFromCid(pState, cid, &pContext);
880 AssertRCReturn(rc, rc);
881
882 if (type == SVGA3D_QUERYTYPE_OCCLUSION)
883 {
884 VMSVGA3DQUERY *p = &pContext->occlusion;
885 if (VMSVGA3DQUERY_EXISTS(p))
886 {
887 if (p->enmQueryState == VMSVGA3DQUERYSTATE_ISSUED)
888 {
889 /* Only if not already in SIGNALED state,
890 * i.e. not a second read from the guest or after restoring saved state.
891 */
892 uint32_t u32Pixels = 0;
893 rc = pSvgaR3State->pFuncsVGPU9->pfnOcclusionQueryGetData(pThisCC, pContext, &u32Pixels);
894 if (RT_SUCCESS(rc))
895 {
896 p->enmQueryState = VMSVGA3DQUERYSTATE_SIGNALED;
897 p->u32QueryResult += u32Pixels; /* += because it might contain partial result from saved state. */
898 }
899 }
900
901 if (RT_SUCCESS(rc))
902 {
903 /* pGuestResult can be NULL when saving the state. */
904 if (pGuestResult)
905 {
906 /* Return data to the guest. */
907 vmsvga3dQueryWriteResult(pThis, pThisCC, pGuestResult, SVGA3D_QUERYSTATE_SUCCEEDED, p->u32QueryResult);
908 }
909 return VINF_SUCCESS;
910 }
911 }
912 else
913 {
914 AssertMsgFailed(("GetData Query is NULL\n"));
915 }
916
917 rc = VERR_INTERNAL_ERROR;
918 }
919 else
920 {
921 rc = VERR_NOT_IMPLEMENTED;
922 }
923
924 if (pGuestResult)
925 vmsvga3dQueryWriteResult(pThis, pThisCC, pGuestResult, SVGA3D_QUERYSTATE_FAILED, 0);
926 AssertFailedReturn(rc);
927}
928
929int vmsvga3dSurfaceBlitToScreen(PVGASTATE pThis, PVGASTATECC pThisCC, uint32_t idDstScreen, SVGASignedRect destRect,
930 SVGA3dSurfaceImageId srcImage, SVGASignedRect srcRect, uint32_t cRects, SVGASignedRect *pRect)
931{
932 /* Requires SVGA_FIFO_CAP_SCREEN_OBJECT support */
933 LogFunc(("dest=%d (%d,%d)(%d,%d) sid=%u (face=%d, mipmap=%d) (%d,%d)(%d,%d) cRects=%d\n",
934 idDstScreen, destRect.left, destRect.top, destRect.right, destRect.bottom, srcImage.sid, srcImage.face, srcImage.mipmap,
935 srcRect.left, srcRect.top, srcRect.right, srcRect.bottom, cRects));
936 for (uint32_t i = 0; i < cRects; i++)
937 {
938 LogFunc(("clipping rect %d (%d,%d)(%d,%d)\n", i, pRect[i].left, pRect[i].top, pRect[i].right, pRect[i].bottom));
939 }
940
941 VMSVGASCREENOBJECT *pScreen = vmsvgaR3GetScreenObject(pThisCC, idDstScreen);
942 AssertReturn(pScreen, VERR_INTERNAL_ERROR);
943
944 /* vmwgfx driver does not always initialize srcImage.mipmap and srcImage.face. They are assumed to be zero. */
945 SVGA3dSurfaceImageId src;
946 src.sid = srcImage.sid;
947 src.mipmap = 0;
948 src.face = 0;
949
950 if (pScreen->pHwScreen)
951 {
952 /* Use the backend accelerated method, if available. */
953 PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
954 if (pSvgaR3State->pFuncs3D)
955 {
956 int rc = pSvgaR3State->pFuncs3D->pfnSurfaceBlitToScreen(pThisCC, pScreen, destRect, src, srcRect, cRects, pRect);
957 if (rc == VINF_SUCCESS)
958 {
959 return VINF_SUCCESS;
960 }
961 }
962 }
963
964 /** @todo scaling */
965 AssertReturn(destRect.right - destRect.left == srcRect.right - srcRect.left && destRect.bottom - destRect.top == srcRect.bottom - srcRect.top, VERR_INVALID_PARAMETER);
966
967 SVGA3dCopyBox box;
968 SVGAGuestImage dest;
969
970 box.srcz = 0;
971 box.z = 0;
972 box.d = 1;
973
974 dest.ptr.gmrId = SVGA_GMR_FRAMEBUFFER;
975 dest.ptr.offset = pScreen->offVRAM;
976 dest.pitch = pScreen->cbPitch;
977
978 if (cRects == 0)
979 {
980 /* easy case; no clipping */
981
982 /* SVGA_3D_CMD_SURFACE_DMA:
983 * 'define the "source" in each copyBox as the guest image and the
984 * "destination" as the host image, regardless of transfer direction.'
985 *
986 * Since the BlitToScreen operation transfers from a host surface to the guest VRAM,
987 * it must set the copyBox "source" to the guest destination coords and
988 * the copyBox "destination" to the host surface source coords.
989 */
990 /* Host image. */
991 box.x = srcRect.left;
992 box.y = srcRect.top;
993 box.w = srcRect.right - srcRect.left;
994 box.h = srcRect.bottom - srcRect.top;
995 /* Guest image. */
996 box.srcx = destRect.left;
997 box.srcy = destRect.top;
998
999 int rc = vmsvga3dSurfaceDMA(pThis, pThisCC, dest, src, SVGA3D_READ_HOST_VRAM, 1, &box);
1000 AssertRCReturn(rc, rc);
1001
1002 /* Update the guest image, which is at box.src. */
1003 vmsvgaR3UpdateScreen(pThisCC, pScreen, box.srcx, box.srcy, box.w, box.h);
1004 }
1005 else
1006 {
1007 /** @todo merge into one SurfaceDMA call */
1008 for (uint32_t i = 0; i < cRects; i++)
1009 {
1010 /* "The clip rectangle coordinates are measured
1011 * relative to the top-left corner of destRect."
1012 * Therefore they are relative to the top-left corner of srcRect as well.
1013 */
1014
1015 /* Host image. See 'SVGA_3D_CMD_SURFACE_DMA:' comment in the 'if' branch. */
1016 box.x = srcRect.left + pRect[i].left;
1017 box.y = srcRect.top + pRect[i].top;
1018 box.w = pRect[i].right - pRect[i].left;
1019 box.h = pRect[i].bottom - pRect[i].top;
1020 /* Guest image. The target screen memory is currently in the guest VRAM. */
1021 box.srcx = destRect.left + pRect[i].left;
1022 box.srcy = destRect.top + pRect[i].top;
1023
1024 int rc = vmsvga3dSurfaceDMA(pThis, pThisCC, dest, src, SVGA3D_READ_HOST_VRAM, 1, &box);
1025 AssertRCReturn(rc, rc);
1026
1027 /* Update the guest image, which is at box.src. */
1028 vmsvgaR3UpdateScreen(pThisCC, pScreen, box.srcx, box.srcy, box.w, box.h);
1029 }
1030 }
1031
1032 return VINF_SUCCESS;
1033}
1034
1035int vmsvga3dCommandPresent(PVGASTATE pThis, PVGASTATECC pThisCC, uint32_t sid, uint32_t cRects, SVGA3dCopyRect *pRect)
1036{
1037 /* Deprecated according to svga3d_reg.h. */
1038 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
1039 AssertReturn(pState, VERR_NO_MEMORY);
1040
1041 PVMSVGA3DSURFACE pSurface;
1042 int rc = vmsvga3dSurfaceFromSid(pState, sid, &pSurface);
1043 AssertRCReturn(rc, rc);
1044
1045 /** @todo Detect screen from coords? Or split rect to screens? */
1046 VMSVGASCREENOBJECT *pScreen = vmsvgaR3GetScreenObject(pThisCC, 0);
1047 AssertReturn(pScreen, VERR_INTERNAL_ERROR);
1048
1049 /* If there are no recangles specified, just grab a screenful. */
1050 SVGA3dCopyRect DummyRect;
1051 if (cRects != 0)
1052 { /* likely */ }
1053 else
1054 {
1055 /** @todo Find the usecase for this or check what the original device does.
1056 * The original code was doing some scaling based on the surface
1057 * size... */
1058 AssertMsgFailed(("No rects to present. Who is doing that and what do they actually expect?\n"));
1059 DummyRect.x = DummyRect.srcx = 0;
1060 DummyRect.y = DummyRect.srcy = 0;
1061 DummyRect.w = pScreen->cWidth;
1062 DummyRect.h = pScreen->cHeight;
1063 cRects = 1;
1064 pRect = &DummyRect;
1065 }
1066
1067 uint32_t i;
1068 for (i = 0; i < cRects; ++i)
1069 {
1070 uint32_t idDstScreen = 0; /** @todo Use virtual coords: SVGA_ID_INVALID. */
1071 SVGASignedRect destRect;
1072 destRect.left = pRect[i].x;
1073 destRect.top = pRect[i].y;
1074 destRect.right = pRect[i].x + pRect[i].w;
1075 destRect.bottom = pRect[i].y + pRect[i].h;
1076
1077 SVGA3dSurfaceImageId src;
1078 src.sid = sid;
1079 src.face = 0;
1080 src.mipmap = 0;
1081
1082 SVGASignedRect srcRect;
1083 srcRect.left = pRect[i].srcx;
1084 srcRect.top = pRect[i].srcy;
1085 srcRect.right = pRect[i].srcx + pRect[i].w;
1086 srcRect.bottom = pRect[i].srcy + pRect[i].h;
1087
1088 /* Entire rect. */
1089 rc = vmsvga3dSurfaceBlitToScreen(pThis, pThisCC, idDstScreen, destRect, src, srcRect, 0, NULL);
1090 AssertRCReturn(rc, rc);
1091 }
1092
1093 return VINF_SUCCESS;
1094}
1095
1096int vmsvga3dDefineScreen(PVGASTATE pThis, PVGASTATECC pThisCC, VMSVGASCREENOBJECT *pScreen)
1097{
1098 PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
1099 AssertReturn(pSvgaR3State->pFuncs3D, VERR_NOT_IMPLEMENTED);
1100
1101 if (pScreen->pHwScreen)
1102 {
1103 pSvgaR3State->pFuncs3D->pfnDestroyScreen(pThisCC, pScreen);
1104 }
1105
1106 int rc = pSvgaR3State->pFuncs3D->pfnDefineScreen(pThis, pThisCC, pScreen);
1107 if (RT_SUCCESS(rc))
1108 {
1109 LogRelMax(1, ("VMSVGA: using accelerated graphics output\n"));
1110 }
1111 return rc;
1112}
1113
1114int vmsvga3dDestroyScreen(PVGASTATECC pThisCC, VMSVGASCREENOBJECT *pScreen)
1115{
1116 PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
1117 AssertReturn(pSvgaR3State->pFuncs3D, VERR_NOT_IMPLEMENTED);
1118
1119 return pSvgaR3State->pFuncs3D->pfnDestroyScreen(pThisCC, pScreen);
1120}
1121
1122int vmsvga3dSurfaceInvalidate(PVGASTATECC pThisCC, uint32_t sid, uint32_t face, uint32_t mipmap)
1123{
1124 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
1125 AssertReturn(pState, VERR_INVALID_STATE);
1126
1127 PVMSVGA3DSURFACE pSurface;
1128 int rc = vmsvga3dSurfaceFromSid(pState, sid, &pSurface);
1129 AssertRCReturn(rc, rc);
1130
1131 if (face == SVGA_ID_INVALID && mipmap == SVGA_ID_INVALID)
1132 {
1133 /* This is a notification that "All images can be lost", i.e. the backend surface is not needed anymore. */
1134 PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
1135 if (pSvgaR3State->pFuncs3D)
1136 pSvgaR3State->pFuncs3D->pfnSurfaceDestroy(pThisCC, pSurface);
1137
1138 for (uint32_t i = 0; i < pSurface->cLevels * pSurface->cFaces; ++i)
1139 {
1140 PVMSVGA3DMIPMAPLEVEL pMipmapLevel = &pSurface->paMipmapLevels[i];
1141 pMipmapLevel->fDirty = true;
1142 }
1143 }
1144 else
1145 {
1146 PVMSVGA3DMIPMAPLEVEL pMipmapLevel;
1147 rc = vmsvga3dMipmapLevel(pSurface, face, mipmap, &pMipmapLevel);
1148 AssertRCReturn(rc, rc);
1149
1150 pMipmapLevel->fDirty = true;
1151 }
1152 pSurface->fDirty = true;
1153
1154 return rc;
1155}
1156
1157
1158/*
1159 *
1160 * 3D
1161 *
1162 */
1163
1164int vmsvga3dQueryCaps(PVGASTATECC pThisCC, SVGA3dDevCapIndex idx3dCaps, uint32_t *pu32Val)
1165{
1166 PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
1167 AssertReturn(pSvgaR3State->pFuncs3D, VERR_NOT_IMPLEMENTED);
1168 return pSvgaR3State->pFuncs3D->pfnQueryCaps(pThisCC, idx3dCaps, pu32Val);
1169}
1170
1171int vmsvga3dChangeMode(PVGASTATECC pThisCC)
1172{
1173 PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
1174 AssertReturn(pSvgaR3State->pFuncs3D, VERR_NOT_IMPLEMENTED);
1175 return pSvgaR3State->pFuncs3D->pfnChangeMode(pThisCC);
1176}
1177
1178int vmsvga3dSurfaceCopy(PVGASTATECC pThisCC, SVGA3dSurfaceImageId dest, SVGA3dSurfaceImageId src, uint32_t cCopyBoxes, SVGA3dCopyBox *pBox)
1179{
1180 PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
1181 AssertReturn(pSvgaR3State->pFuncs3D, VERR_NOT_IMPLEMENTED);
1182 return pSvgaR3State->pFuncs3D->pfnSurfaceCopy(pThisCC, dest, src, cCopyBoxes, pBox);
1183}
1184
1185void vmsvga3dUpdateHostScreenViewport(PVGASTATECC pThisCC, uint32_t idScreen, VMSVGAVIEWPORT const *pOldViewport)
1186{
1187 PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
1188 AssertReturnVoid(pSvgaR3State->pFuncs3D);
1189 pSvgaR3State->pFuncs3D->pfnUpdateHostScreenViewport(pThisCC, idScreen, pOldViewport);
1190}
1191
1192/**
1193 * Updates the heap buffers for all surfaces or one specific one.
1194 *
1195 * @param pThisCC The VGA/VMSVGA state for ring-3.
1196 * @param sid The surface ID, UINT32_MAX if all.
1197 * @thread VMSVGAFIFO
1198 */
1199void vmsvga3dUpdateHeapBuffersForSurfaces(PVGASTATECC pThisCC, uint32_t sid)
1200{
1201 PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
1202 AssertReturnVoid(pSvgaR3State->pFuncs3D);
1203
1204 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
1205 AssertReturnVoid(pState);
1206
1207 if (sid == UINT32_MAX)
1208 {
1209 uint32_t cSurfaces = pState->cSurfaces;
1210 for (sid = 0; sid < cSurfaces; sid++)
1211 {
1212 PVMSVGA3DSURFACE pSurface = pState->papSurfaces[sid];
1213 if (pSurface && pSurface->id == sid)
1214 pSvgaR3State->pFuncs3D->pfnSurfaceUpdateHeapBuffers(pThisCC, pSurface);
1215 }
1216 }
1217 else if (sid < pState->cSurfaces)
1218 {
1219 PVMSVGA3DSURFACE pSurface = pState->papSurfaces[sid];
1220 if (pSurface && pSurface->id == sid)
1221 pSvgaR3State->pFuncs3D->pfnSurfaceUpdateHeapBuffers(pThisCC, pSurface);
1222 }
1223}
1224
1225
1226/*
1227 *
1228 * VGPU9
1229 *
1230 */
1231
1232int vmsvga3dContextDefine(PVGASTATECC pThisCC, uint32_t cid)
1233{
1234 PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
1235 AssertReturn(pSvgaR3State->pFuncsVGPU9, VERR_NOT_IMPLEMENTED);
1236 return pSvgaR3State->pFuncsVGPU9->pfnContextDefine(pThisCC, cid);
1237}
1238
1239int vmsvga3dContextDestroy(PVGASTATECC pThisCC, uint32_t cid)
1240{
1241 PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
1242 AssertReturn(pSvgaR3State->pFuncsVGPU9, VERR_NOT_IMPLEMENTED);
1243 return pSvgaR3State->pFuncsVGPU9->pfnContextDestroy(pThisCC, cid);
1244}
1245
1246int vmsvga3dSetTransform(PVGASTATECC pThisCC, uint32_t cid, SVGA3dTransformType type, float matrix[16])
1247{
1248 PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
1249 AssertReturn(pSvgaR3State->pFuncsVGPU9, VERR_NOT_IMPLEMENTED);
1250 return pSvgaR3State->pFuncsVGPU9->pfnSetTransform(pThisCC, cid, type, matrix);
1251}
1252
1253int vmsvga3dSetZRange(PVGASTATECC pThisCC, uint32_t cid, SVGA3dZRange zRange)
1254{
1255 PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
1256 AssertReturn(pSvgaR3State->pFuncsVGPU9, VERR_NOT_IMPLEMENTED);
1257 return pSvgaR3State->pFuncsVGPU9->pfnSetZRange(pThisCC, cid, zRange);
1258}
1259
1260int vmsvga3dSetRenderState(PVGASTATECC pThisCC, uint32_t cid, uint32_t cRenderStates, SVGA3dRenderState *pRenderState)
1261{
1262 PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
1263 AssertReturn(pSvgaR3State->pFuncsVGPU9, VERR_NOT_IMPLEMENTED);
1264 return pSvgaR3State->pFuncsVGPU9->pfnSetRenderState(pThisCC, cid, cRenderStates, pRenderState);
1265}
1266
1267int vmsvga3dSetRenderTarget(PVGASTATECC pThisCC, uint32_t cid, SVGA3dRenderTargetType type, SVGA3dSurfaceImageId target)
1268{
1269 PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
1270 AssertReturn(pSvgaR3State->pFuncsVGPU9, VERR_NOT_IMPLEMENTED);
1271 return pSvgaR3State->pFuncsVGPU9->pfnSetRenderTarget(pThisCC, cid, type, target);
1272}
1273
1274int vmsvga3dSetTextureState(PVGASTATECC pThisCC, uint32_t cid, uint32_t cTextureStates, SVGA3dTextureState *pTextureState)
1275{
1276 PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
1277 AssertReturn(pSvgaR3State->pFuncsVGPU9, VERR_NOT_IMPLEMENTED);
1278 return pSvgaR3State->pFuncsVGPU9->pfnSetTextureState(pThisCC, cid, cTextureStates, pTextureState);
1279}
1280
1281int vmsvga3dSetMaterial(PVGASTATECC pThisCC, uint32_t cid, SVGA3dFace face, SVGA3dMaterial *pMaterial)
1282{
1283 PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
1284 AssertReturn(pSvgaR3State->pFuncsVGPU9, VERR_NOT_IMPLEMENTED);
1285 return pSvgaR3State->pFuncsVGPU9->pfnSetMaterial(pThisCC, cid, face, pMaterial);
1286}
1287
1288int vmsvga3dSetLightData(PVGASTATECC pThisCC, uint32_t cid, uint32_t index, SVGA3dLightData *pData)
1289{
1290 PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
1291 AssertReturn(pSvgaR3State->pFuncsVGPU9, VERR_NOT_IMPLEMENTED);
1292 return pSvgaR3State->pFuncsVGPU9->pfnSetLightData(pThisCC, cid, index, pData);
1293}
1294
1295int vmsvga3dSetLightEnabled(PVGASTATECC pThisCC, uint32_t cid, uint32_t index, uint32_t enabled)
1296{
1297 PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
1298 AssertReturn(pSvgaR3State->pFuncsVGPU9, VERR_NOT_IMPLEMENTED);
1299 return pSvgaR3State->pFuncsVGPU9->pfnSetLightEnabled(pThisCC, cid, index, enabled);
1300}
1301
1302int vmsvga3dSetViewPort(PVGASTATECC pThisCC, uint32_t cid, SVGA3dRect *pRect)
1303{
1304 PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
1305 AssertReturn(pSvgaR3State->pFuncsVGPU9, VERR_NOT_IMPLEMENTED);
1306 return pSvgaR3State->pFuncsVGPU9->pfnSetViewPort(pThisCC, cid, pRect);
1307}
1308
1309int vmsvga3dSetClipPlane(PVGASTATECC pThisCC, uint32_t cid, uint32_t index, float plane[4])
1310{
1311 PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
1312 AssertReturn(pSvgaR3State->pFuncsVGPU9, VERR_NOT_IMPLEMENTED);
1313 return pSvgaR3State->pFuncsVGPU9->pfnSetClipPlane(pThisCC, cid, index, plane);
1314}
1315
1316int vmsvga3dCommandClear(PVGASTATECC pThisCC, uint32_t cid, SVGA3dClearFlag clearFlag, uint32_t color, float depth, uint32_t stencil, uint32_t cRects, SVGA3dRect *pRect)
1317{
1318 PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
1319 AssertReturn(pSvgaR3State->pFuncsVGPU9, VERR_NOT_IMPLEMENTED);
1320 return pSvgaR3State->pFuncsVGPU9->pfnCommandClear(pThisCC, cid, clearFlag, color, depth, stencil, cRects, pRect);
1321}
1322
1323int vmsvga3dDrawPrimitives(PVGASTATECC pThisCC, uint32_t cid, uint32_t numVertexDecls, SVGA3dVertexDecl *pVertexDecl, uint32_t numRanges, SVGA3dPrimitiveRange *pNumRange, uint32_t cVertexDivisor, SVGA3dVertexDivisor *pVertexDivisor)
1324{
1325 PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
1326 AssertReturn(pSvgaR3State->pFuncsVGPU9, VERR_NOT_IMPLEMENTED);
1327 return pSvgaR3State->pFuncsVGPU9->pfnDrawPrimitives(pThisCC, cid, numVertexDecls, pVertexDecl, numRanges, pNumRange, cVertexDivisor, pVertexDivisor);
1328}
1329
1330int vmsvga3dSetScissorRect(PVGASTATECC pThisCC, uint32_t cid, SVGA3dRect *pRect)
1331{
1332 PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
1333 AssertReturn(pSvgaR3State->pFuncsVGPU9, VERR_NOT_IMPLEMENTED);
1334 return pSvgaR3State->pFuncsVGPU9->pfnSetScissorRect(pThisCC, cid, pRect);
1335}
1336
1337int vmsvga3dGenerateMipmaps(PVGASTATECC pThisCC, uint32_t sid, SVGA3dTextureFilter filter)
1338{
1339 PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
1340 AssertReturn(pSvgaR3State->pFuncsVGPU9, VERR_NOT_IMPLEMENTED);
1341 return pSvgaR3State->pFuncsVGPU9->pfnGenerateMipmaps(pThisCC, sid, filter);
1342}
1343
1344int vmsvga3dShaderDefine(PVGASTATECC pThisCC, uint32_t cid, uint32_t shid, SVGA3dShaderType type, uint32_t cbData, uint32_t *pShaderData)
1345{
1346 PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
1347 AssertReturn(pSvgaR3State->pFuncsVGPU9, VERR_NOT_IMPLEMENTED);
1348 return pSvgaR3State->pFuncsVGPU9->pfnShaderDefine(pThisCC, cid, shid, type, cbData, pShaderData);
1349}
1350
1351int vmsvga3dShaderDestroy(PVGASTATECC pThisCC, uint32_t cid, uint32_t shid, SVGA3dShaderType type)
1352{
1353 PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
1354 AssertReturn(pSvgaR3State->pFuncsVGPU9, VERR_NOT_IMPLEMENTED);
1355 return pSvgaR3State->pFuncsVGPU9->pfnShaderDestroy(pThisCC, cid, shid, type);
1356}
1357
1358int vmsvga3dShaderSet(PVGASTATECC pThisCC, struct VMSVGA3DCONTEXT *pContext, uint32_t cid, SVGA3dShaderType type, uint32_t shid)
1359{
1360 PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
1361 AssertReturn(pSvgaR3State->pFuncsVGPU9, VERR_NOT_IMPLEMENTED);
1362 return pSvgaR3State->pFuncsVGPU9->pfnShaderSet(pThisCC, pContext, cid, type, shid);
1363}
1364
1365int vmsvga3dShaderSetConst(PVGASTATECC pThisCC, uint32_t cid, uint32_t reg, SVGA3dShaderType type, SVGA3dShaderConstType ctype, uint32_t cRegisters, uint32_t *pValues)
1366{
1367 PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
1368 AssertReturn(pSvgaR3State->pFuncsVGPU9, VERR_NOT_IMPLEMENTED);
1369 return pSvgaR3State->pFuncsVGPU9->pfnShaderSetConst(pThisCC, cid, reg, type, ctype, cRegisters, pValues);
1370}
1371
1372
1373/*
1374 *
1375 * Map
1376 *
1377 */
1378
1379int vmsvga3dSurfaceMap(PVGASTATECC pThisCC, SVGA3dSurfaceImageId const *pImage, SVGA3dBox const *pBox,
1380 VMSVGA3D_SURFACE_MAP enmMapType, VMSVGA3D_MAPPED_SURFACE *pMap)
1381{
1382 PVMSVGA3DSURFACE pSurface;
1383 int rc = vmsvga3dSurfaceFromSid(pThisCC->svga.p3dState, pImage->sid, &pSurface);
1384 AssertRCReturn(rc, rc);
1385
1386 if (VMSVGA3DSURFACE_HAS_HW_SURFACE(pSurface))
1387 {
1388 PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
1389 AssertReturn(pSvgaR3State->pFuncsMap, VERR_NOT_IMPLEMENTED);
1390 return pSvgaR3State->pFuncsMap->pfnSurfaceMap(pThisCC, pImage, pBox, enmMapType, pMap);
1391 }
1392
1393 PVMSVGA3DMIPMAPLEVEL pMipLevel;
1394 rc = vmsvga3dMipmapLevel(pSurface, pImage->face, pImage->mipmap, &pMipLevel);
1395 ASSERT_GUEST_RETURN(RT_SUCCESS(rc), rc);
1396
1397 if (!pMipLevel->pSurfaceData)
1398 {
1399 rc = vmsvga3dSurfaceAllocMipLevels(pSurface);
1400 AssertRCReturn(rc, rc);
1401 }
1402
1403 SVGA3dBox clipBox;
1404 if (pBox)
1405 {
1406 clipBox = *pBox;
1407 vmsvgaR3ClipBox(&pMipLevel->mipmapSize, &clipBox);
1408 ASSERT_GUEST_RETURN(clipBox.w && clipBox.h && clipBox.d, VERR_INVALID_PARAMETER);
1409 }
1410 else
1411 {
1412 clipBox.x = 0;
1413 clipBox.y = 0;
1414 clipBox.z = 0;
1415 clipBox.w = pMipLevel->mipmapSize.width;
1416 clipBox.h = pMipLevel->mipmapSize.height;
1417 clipBox.d = pMipLevel->mipmapSize.depth;
1418 }
1419
1420 /// @todo Zero the box?
1421 //if (enmMapType == VMSVGA3D_SURFACE_MAP_WRITE_DISCARD)
1422 // RT_BZERO(.);
1423
1424 pMap->enmMapType = enmMapType;
1425 pMap->box = clipBox;
1426 pMap->cbPixel = pSurface->cbBlock;
1427 pMap->cbRowPitch = pMipLevel->cbSurfacePitch;
1428 pMap->cbDepthPitch = pMipLevel->cbSurfacePlane;
1429 pMap->pvData = (uint8_t *)pMipLevel->pSurfaceData
1430 + pMap->box.x * pMap->cbPixel
1431 + pMap->box.y * pMap->cbRowPitch
1432 + pMap->box.z * pMap->cbDepthPitch;
1433
1434 return VINF_SUCCESS;
1435}
1436
1437int vmsvga3dSurfaceUnmap(PVGASTATECC pThisCC, SVGA3dSurfaceImageId const *pImage, VMSVGA3D_MAPPED_SURFACE *pMap, bool fWritten)
1438{
1439 PVMSVGA3DSURFACE pSurface;
1440 int rc = vmsvga3dSurfaceFromSid(pThisCC->svga.p3dState, pImage->sid, &pSurface);
1441 AssertRCReturn(rc, rc);
1442
1443 if (VMSVGA3DSURFACE_HAS_HW_SURFACE(pSurface))
1444 {
1445 PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
1446 AssertReturn(pSvgaR3State->pFuncsMap, VERR_NOT_IMPLEMENTED);
1447 return pSvgaR3State->pFuncsMap->pfnSurfaceUnmap(pThisCC, pImage, pMap, fWritten);
1448 }
1449
1450 PVMSVGA3DMIPMAPLEVEL pMipLevel;
1451 rc = vmsvga3dMipmapLevel(pSurface, pImage->face, pImage->mipmap, &pMipLevel);
1452 ASSERT_GUEST_RETURN(RT_SUCCESS(rc), rc);
1453
1454 if ( fWritten
1455 && ( pMap->enmMapType == VMSVGA3D_SURFACE_MAP_WRITE
1456 || pMap->enmMapType == VMSVGA3D_SURFACE_MAP_READ_WRITE
1457 || pMap->enmMapType == VMSVGA3D_SURFACE_MAP_WRITE_DISCARD))
1458 {
1459 pMipLevel->fDirty = true;
1460 pSurface->fDirty = true;
1461 }
1462
1463 return VINF_SUCCESS;
1464}
1465
1466
1467int vmsvga3dCalcSurfaceMipmapAndFace(PVGASTATECC pThisCC, uint32_t sid, uint32_t iSubresource, uint32_t *piMipmap, uint32_t *piFace)
1468{
1469 PVMSVGA3DSURFACE pSurface;
1470 int rc = vmsvga3dSurfaceFromSid(pThisCC->svga.p3dState, sid, &pSurface);
1471 AssertRCReturn(rc, rc);
1472
1473 vmsvga3dCalcMipmapAndFace(pSurface->cLevels, iSubresource, piMipmap, piFace);
1474 return VINF_SUCCESS;
1475}
1476
1477
1478uint32_t vmsvga3dCalcSubresourceOffset(PVGASTATECC pThisCC, SVGA3dSurfaceImageId const *pImage)
1479{
1480 PVMSVGA3DSURFACE pSurface;
1481 int rc = vmsvga3dSurfaceFromSid(pThisCC->svga.p3dState, pImage->sid, &pSurface);
1482 AssertRCReturn(rc, 0);
1483
1484 /** @todo Store cbArraySlice in the surface structure. */
1485 uint32_t cbArraySlice = 0;
1486 for (uint32_t i = 0; i < pSurface->cLevels; ++i)
1487 {
1488 PVMSVGA3DMIPMAPLEVEL pMipLevel = &pSurface->paMipmapLevels[i];
1489 cbArraySlice += pMipLevel->cbSurface;
1490 }
1491
1492 uint32_t offMipLevel = 0;
1493 for (uint32_t i = 0; i < pImage->mipmap; ++i)
1494 {
1495 PVMSVGA3DMIPMAPLEVEL pMipmapLevel = &pSurface->paMipmapLevels[i];
1496 offMipLevel += pMipmapLevel->cbSurface;
1497 }
1498
1499 uint32_t offSubresource = cbArraySlice * pImage->face + offMipLevel;
1500 /** @todo Multisample? */
1501 return offSubresource;
1502}
1503
1504
1505/*
1506 * Calculates memory layout of a surface box for memcpy:
1507 */
1508int vmsvga3dGetBoxDimensions(PVGASTATECC pThisCC, SVGA3dSurfaceImageId const *pImage, SVGA3dBox const *pBox,
1509 VMSGA3D_BOX_DIMENSIONS *pResult)
1510{
1511 PVMSVGA3DSURFACE pSurface;
1512 int rc = vmsvga3dSurfaceFromSid(pThisCC->svga.p3dState, pImage->sid, &pSurface);
1513 AssertRCReturn(rc, rc);
1514
1515 PVMSVGA3DMIPMAPLEVEL pMipLevel;
1516 rc = vmsvga3dMipmapLevel(pSurface, pImage->face, pImage->mipmap, &pMipLevel);
1517 ASSERT_GUEST_RETURN(RT_SUCCESS(rc), rc);
1518
1519 /* Clip the box. */
1520 SVGA3dBox clipBox;
1521 if (pBox)
1522 {
1523 clipBox = *pBox;
1524 vmsvgaR3ClipBox(&pMipLevel->mipmapSize, &clipBox);
1525 ASSERT_GUEST_RETURN(clipBox.w && clipBox.h && clipBox.d, VERR_INVALID_PARAMETER);
1526 }
1527 else
1528 {
1529 clipBox.x = 0;
1530 clipBox.y = 0;
1531 clipBox.z = 0;
1532 clipBox.w = pMipLevel->mipmapSize.width;
1533 clipBox.h = pMipLevel->mipmapSize.height;
1534 clipBox.d = pMipLevel->mipmapSize.depth;
1535 }
1536
1537 uint32_t const cBlocksX = (clipBox.w + pSurface->cxBlock - 1) / pSurface->cxBlock;
1538 uint32_t const cBlocksY = (clipBox.h + pSurface->cyBlock - 1) / pSurface->cyBlock;
1539
1540 /** @todo Calculate offSubresource here, when pSurface will have cbArraySlice field. */
1541 pResult->offSubresource = vmsvga3dCalcSubresourceOffset(pThisCC, pImage);
1542 pResult->offBox = (clipBox.x / pSurface->cxBlock) * pSurface->cbBlock
1543 + (clipBox.y / pSurface->cyBlock) * pMipLevel->cbSurfacePitch
1544 + clipBox.z * pMipLevel->cbSurfacePlane;
1545 pResult->cbRow = cBlocksX * pSurface->cbBlock;
1546 pResult->cbPitch = pMipLevel->cbSurfacePitch;
1547 pResult->cyBlocks = cBlocksY;
1548 pResult->cDepth = clipBox.d;
1549
1550 return VINF_SUCCESS;
1551}
1552
1553
1554/*
1555 * Whether a legacy 3D backend is used.
1556 * The new DX context can be built together with the legacy D3D9 or OpenGL backend.
1557 * The actual backend is selected at the VM startup.
1558 */
1559bool vmsvga3dIsLegacyBackend(PVGASTATECC pThisCC)
1560{
1561 PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
1562 return pSvgaR3State->pFuncsDX == NULL;
1563}
1564
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