VirtualBox

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

Last change on this file was 102808, checked in by vboxsync, 4 months ago

Devices/Graphics: multisampling.

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

© 2023 Oracle
ContactPrivacy policyTerms of Use