VirtualBox

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

Last change on this file since 69052 was 67972, checked in by vboxsync, 7 years ago

bugref:8863: several DevVGA-SVGA fixes

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 24.3 KB
Line 
1/* $Id: DevVGA-SVGA3d.cpp 67972 2017-07-14 13:44:02Z vboxsync $ */
2/** @file
3 * DevSVGA3d - VMWare SVGA device, 3D parts - Common core code.
4 */
5
6/*
7 * Copyright (C) 2013-2016 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
22#define LOG_GROUP LOG_GROUP_DEV_VMSVGA
23#include <VBox/vmm/pdmdev.h>
24#include <VBox/err.h>
25#include <VBox/log.h>
26
27#include <iprt/assert.h>
28#include <iprt/mem.h>
29
30#include <VBox/vmm/pgm.h> /* required by DevVGA.h */
31#include <VBoxVideo.h> /* required by DevVGA.h */
32
33/* should go BEFORE any other DevVGA include to make all DevVGA.h config defines be visible */
34#include "DevVGA.h"
35
36#include "DevVGA-SVGA.h"
37#include "DevVGA-SVGA3d.h"
38#define VMSVGA3D_INCL_STRUCTURE_DESCRIPTORS
39#include "DevVGA-SVGA3d-internal.h"
40
41
42
43/**
44 * Implements the SVGA_3D_CMD_SURFACE_DEFINE_V2 and SVGA_3D_CMD_SURFACE_DEFINE
45 * commands (fifo).
46 *
47 * @returns VBox status code (currently ignored).
48 * @param pThis The VGA device instance data.
49 * @param sid The ID of the surface to (re-)define.
50 * @param surfaceFlags .
51 * @param format .
52 * @param face .
53 * @param multisampleCount .
54 * @param autogenFilter .
55 * @param cMipLevels .
56 * @param paMipLevelSizes .
57 */
58int vmsvga3dSurfaceDefine(PVGASTATE pThis, uint32_t sid, uint32_t surfaceFlags, SVGA3dSurfaceFormat format,
59 SVGA3dSurfaceFace face[SVGA3D_MAX_SURFACE_FACES], uint32_t multisampleCount,
60 SVGA3dTextureFilter autogenFilter, uint32_t cMipLevels, SVGA3dSize *paMipLevelSizes)
61{
62 PVMSVGA3DSURFACE pSurface;
63 PVMSVGA3DSTATE pState = pThis->svga.p3dState;
64 AssertReturn(pState, VERR_NO_MEMORY);
65
66 Log(("vmsvga3dSurfaceDefine: sid=%x surfaceFlags=%x format=%s (%x) multiSampleCount=%d autogenFilter=%d, cMipLevels=%d size=(%d,%d,%d)\n",
67 sid, surfaceFlags, vmsvgaLookupEnum((int)format, &g_SVGA3dSurfaceFormat2String), format, multisampleCount, autogenFilter,
68 cMipLevels, paMipLevelSizes->width, paMipLevelSizes->height, paMipLevelSizes->depth));
69
70 AssertReturn(sid < SVGA3D_MAX_SURFACE_IDS, VERR_INVALID_PARAMETER);
71 AssertReturn(cMipLevels >= 1, VERR_INVALID_PARAMETER);
72
73 /* Number of faces (cFaces) is specified as the number of the first non-zero elements in the 'face' array.
74 * Since only plain surfaces (cFaces == 1) and cubemaps (cFaces == 6) are supported
75 * (see also SVGA3dCmdDefineSurface definition in svga3d_reg.h), we ignore anything else.
76 */
77 uint32_t cRemainingMipLevels = cMipLevels;
78 uint32_t cFaces = 0;
79 for (uint32_t i = 0; i < SVGA3D_MAX_SURFACE_FACES; ++i)
80 {
81 if (face[i].numMipLevels == 0)
82 break;
83
84 /* All SVGA3dSurfaceFace structures must have the same value of numMipLevels field */
85 AssertReturn(face[i].numMipLevels == face[0].numMipLevels, VERR_INVALID_PARAMETER);
86
87 /* numMipLevels value can't be greater than the number of remaining elements in the paMipLevelSizes array. */
88 AssertReturn(face[i].numMipLevels <= cRemainingMipLevels, VERR_INVALID_PARAMETER);
89 cRemainingMipLevels -= face[i].numMipLevels;
90
91 ++cFaces;
92 }
93 for (uint32_t i = cFaces; i < SVGA3D_MAX_SURFACE_FACES; ++i)
94 AssertReturn(face[i].numMipLevels == 0, VERR_INVALID_PARAMETER);
95
96 /* cFaces must be 6 for a cubemap and 1 otherwise. */
97 AssertReturn(cFaces == (uint32_t)((surfaceFlags & SVGA3D_SURFACE_CUBEMAP) ? 6 : 1), VERR_INVALID_PARAMETER);
98
99 /* Sum of face[i].numMipLevels must be equal to cMipLevels. */
100 AssertReturn(cRemainingMipLevels == 0, VERR_INVALID_PARAMETER);
101
102 if (sid >= pState->cSurfaces)
103 {
104 /* Grow the array. */
105 uint32_t cNew = RT_ALIGN(sid + 15, 16);
106 void *pvNew = RTMemRealloc(pState->papSurfaces, sizeof(pState->papSurfaces[0]) * cNew);
107 AssertReturn(pvNew, VERR_NO_MEMORY);
108 pState->papSurfaces = (PVMSVGA3DSURFACE *)pvNew;
109 while (pState->cSurfaces < cNew)
110 {
111 pSurface = (PVMSVGA3DSURFACE)RTMemAllocZ(sizeof(*pSurface));
112 AssertReturn(pSurface, VERR_NO_MEMORY);
113 pSurface->id = SVGA3D_INVALID_ID;
114 pState->papSurfaces[pState->cSurfaces++] = pSurface;
115 }
116 }
117 pSurface = pState->papSurfaces[sid];
118
119 /* If one already exists with this id, then destroy it now. */
120 if (pSurface->id != SVGA3D_INVALID_ID)
121 vmsvga3dSurfaceDestroy(pThis, sid);
122
123 RT_ZERO(*pSurface);
124 pSurface->id = sid;
125#ifdef VMSVGA3D_OPENGL
126 pSurface->idWeakContextAssociation = SVGA3D_INVALID_ID;
127#else
128 pSurface->idAssociatedContext = SVGA3D_INVALID_ID;
129#endif
130#ifdef VMSVGA3D_DIRECT3D
131 pSurface->hSharedObject = NULL;
132 pSurface->pSharedObjectTree = NULL;
133#else
134 pSurface->oglId.buffer = OPENGL_INVALID_ID;
135#endif
136
137 /* The surface type is sort of undefined now, even though the hints and format can help to clear that up.
138 * In some case we'll have to wait until the surface is used to create the D3D object.
139 */
140 switch (format)
141 {
142 case SVGA3D_Z_D32:
143 case SVGA3D_Z_D16:
144 case SVGA3D_Z_D24S8:
145 case SVGA3D_Z_D15S1:
146 case SVGA3D_Z_D24X8:
147 case SVGA3D_Z_DF16:
148 case SVGA3D_Z_DF24:
149 case SVGA3D_Z_D24S8_INT:
150 surfaceFlags |= SVGA3D_SURFACE_HINT_DEPTHSTENCIL;
151 break;
152
153 /* Texture compression formats */
154 case SVGA3D_DXT1:
155 case SVGA3D_DXT2:
156 case SVGA3D_DXT3:
157 case SVGA3D_DXT4:
158 case SVGA3D_DXT5:
159 /* Bump-map formats */
160 case SVGA3D_BUMPU8V8:
161 case SVGA3D_BUMPL6V5U5:
162 case SVGA3D_BUMPX8L8V8U8:
163 case SVGA3D_BUMPL8V8U8:
164 case SVGA3D_V8U8:
165 case SVGA3D_Q8W8V8U8:
166 case SVGA3D_CxV8U8:
167 case SVGA3D_X8L8V8U8:
168 case SVGA3D_A2W10V10U10:
169 case SVGA3D_V16U16:
170 /* Typical render target formats; we should allow render target buffers to be used as textures. */
171 case SVGA3D_X8R8G8B8:
172 case SVGA3D_A8R8G8B8:
173 case SVGA3D_R5G6B5:
174 case SVGA3D_X1R5G5B5:
175 case SVGA3D_A1R5G5B5:
176 case SVGA3D_A4R4G4B4:
177 surfaceFlags |= SVGA3D_SURFACE_HINT_TEXTURE;
178 break;
179
180 case SVGA3D_LUMINANCE8:
181 case SVGA3D_LUMINANCE4_ALPHA4:
182 case SVGA3D_LUMINANCE16:
183 case SVGA3D_LUMINANCE8_ALPHA8:
184 case SVGA3D_ARGB_S10E5: /* 16-bit floating-point ARGB */
185 case SVGA3D_ARGB_S23E8: /* 32-bit floating-point ARGB */
186 case SVGA3D_A2R10G10B10:
187 case SVGA3D_ALPHA8:
188 case SVGA3D_R_S10E5:
189 case SVGA3D_R_S23E8:
190 case SVGA3D_RG_S10E5:
191 case SVGA3D_RG_S23E8:
192 case SVGA3D_G16R16:
193 case SVGA3D_A16B16G16R16:
194 case SVGA3D_UYVY:
195 case SVGA3D_YUY2:
196 case SVGA3D_NV12:
197 case SVGA3D_AYUV:
198 case SVGA3D_BC4_UNORM:
199 case SVGA3D_BC5_UNORM:
200 break;
201
202 /*
203 * Any surface can be used as a buffer object, but SVGA3D_BUFFER is
204 * the most efficient format to use when creating new surfaces
205 * expressly for index or vertex data.
206 */
207 case SVGA3D_BUFFER:
208 break;
209
210 default:
211 break;
212 }
213
214 pSurface->flags = surfaceFlags;
215 pSurface->format = format;
216 memcpy(pSurface->faces, face, sizeof(pSurface->faces));
217 pSurface->cFaces = cFaces;
218 pSurface->multiSampleCount = multisampleCount;
219 pSurface->autogenFilter = autogenFilter;
220 Assert(autogenFilter != SVGA3D_TEX_FILTER_FLATCUBIC);
221 Assert(autogenFilter != SVGA3D_TEX_FILTER_GAUSSIANCUBIC);
222 pSurface->cMipmapLevels = cMipLevels;
223 pSurface->pMipmapLevels = (PVMSVGA3DMIPMAPLEVEL)RTMemAllocZ(cMipLevels * sizeof(VMSVGA3DMIPMAPLEVEL));
224 AssertReturn(pSurface->pMipmapLevels, VERR_NO_MEMORY);
225
226 for (uint32_t i=0; i < cMipLevels; i++)
227 pSurface->pMipmapLevels[i].size = paMipLevelSizes[i];
228
229 pSurface->cbBlock = vmsvga3dSurfaceFormatSize(format);
230 AssertReturn(pSurface->cbBlock, VERR_INVALID_PARAMETER);
231
232#ifdef VMSVGA3D_DIRECT3D
233 /* Translate the format and usage flags to D3D. */
234 pSurface->formatD3D = vmsvga3dSurfaceFormat2D3D(format);
235 pSurface->multiSampleTypeD3D= vmsvga3dMultipeSampleCount2D3D(multisampleCount);
236 pSurface->fUsageD3D = 0;
237 if (surfaceFlags & SVGA3D_SURFACE_HINT_DYNAMIC)
238 pSurface->fUsageD3D |= D3DUSAGE_DYNAMIC;
239 if (surfaceFlags & SVGA3D_SURFACE_HINT_RENDERTARGET)
240 pSurface->fUsageD3D |= D3DUSAGE_RENDERTARGET;
241 if (surfaceFlags & SVGA3D_SURFACE_HINT_DEPTHSTENCIL)
242 pSurface->fUsageD3D |= D3DUSAGE_DEPTHSTENCIL;
243 if (surfaceFlags & SVGA3D_SURFACE_HINT_WRITEONLY)
244 pSurface->fUsageD3D |= D3DUSAGE_WRITEONLY;
245 if (surfaceFlags & SVGA3D_SURFACE_AUTOGENMIPMAPS)
246 pSurface->fUsageD3D |= D3DUSAGE_AUTOGENMIPMAP;
247 pSurface->fu32ActualUsageFlags = 0;
248#else
249 vmsvga3dSurfaceFormat2OGL(pSurface, format);
250#endif
251
252 switch (surfaceFlags & (SVGA3D_SURFACE_HINT_INDEXBUFFER | SVGA3D_SURFACE_HINT_VERTEXBUFFER | SVGA3D_SURFACE_HINT_TEXTURE | SVGA3D_SURFACE_HINT_RENDERTARGET | SVGA3D_SURFACE_HINT_DEPTHSTENCIL | SVGA3D_SURFACE_CUBEMAP))
253 {
254 case SVGA3D_SURFACE_CUBEMAP:
255 Log(("SVGA3D_SURFACE_CUBEMAP\n"));
256 break;
257
258 case SVGA3D_SURFACE_HINT_INDEXBUFFER:
259 Log(("SVGA3D_SURFACE_HINT_INDEXBUFFER\n"));
260 /* else type unknown at this time; postpone buffer creation */
261 break;
262
263 case SVGA3D_SURFACE_HINT_VERTEXBUFFER:
264 Log(("SVGA3D_SURFACE_HINT_VERTEXBUFFER\n"));
265 /* Type unknown at this time; postpone buffer creation */
266 break;
267
268 case SVGA3D_SURFACE_HINT_TEXTURE:
269 Log(("SVGA3D_SURFACE_HINT_TEXTURE\n"));
270 break;
271
272 case SVGA3D_SURFACE_HINT_RENDERTARGET:
273 Log(("SVGA3D_SURFACE_HINT_RENDERTARGET\n"));
274 break;
275
276 case SVGA3D_SURFACE_HINT_DEPTHSTENCIL:
277 Log(("SVGA3D_SURFACE_HINT_DEPTHSTENCIL\n"));
278 break;
279
280 default:
281 /* Unknown; decide later. */
282 break;
283 }
284
285 Assert(!VMSVGA3DSURFACE_HAS_HW_SURFACE(pSurface));
286
287 /* Allocate buffer to hold the surface data until we can move it into a D3D object */
288 uint32_t cbMemRemaining = SVGA3D_MAX_SURFACE_MEM_SIZE; /* Do not allow more than this for a surface. */
289 for (uint32_t i = 0; i < cMipLevels; ++i)
290 {
291 PVMSVGA3DMIPMAPLEVEL pMipmapLevel = &pSurface->pMipmapLevels[i];
292 LogFunc(("[%d] face %d mip level %d (%d,%d,%d) cbBlock=0x%x\n",
293 i, i / pSurface->faces[0].numMipLevels, i % pSurface->faces[0].numMipLevels,
294 pMipmapLevel->size.width, pMipmapLevel->size.height, pMipmapLevel->size.depth, pSurface->cbBlock));
295
296 if ( pMipmapLevel->size.width == 0
297 || pMipmapLevel->size.height == 0
298 || pMipmapLevel->size.depth == 0)
299 return VERR_INVALID_PARAMETER;
300
301 const uint32_t cMaxWidth = cbMemRemaining / pSurface->cbBlock;
302 if (pMipmapLevel->size.width > cMaxWidth)
303 return VERR_INVALID_PARAMETER;
304 const uint32_t cbSurfacePitch = pSurface->cbBlock * pMipmapLevel->size.width;
305 LogFunc(("cbPitch=0x%x\n", cbSurfacePitch));
306
307 const uint32_t cMaxHeight = cbMemRemaining / cbSurfacePitch;
308 if (pMipmapLevel->size.height > cMaxHeight)
309 return VERR_INVALID_PARAMETER;
310 const uint32_t cbSurfacePlane = cbSurfacePitch * pMipmapLevel->size.height;
311
312 const uint32_t cMaxDepth = cbMemRemaining / cbSurfacePlane;
313 if (pMipmapLevel->size.depth > cMaxDepth)
314 return VERR_INVALID_PARAMETER;
315 const uint32_t cbSurface = cbSurfacePlane * pMipmapLevel->size.depth;
316
317 pMipmapLevel->cbSurfacePitch = cbSurfacePitch;
318 pMipmapLevel->cbSurface = cbSurface;
319 pMipmapLevel->pSurfaceData = RTMemAllocZ(cbSurface);
320 AssertReturn(pMipmapLevel->pSurfaceData, VERR_NO_MEMORY);
321
322 cbMemRemaining -= cbSurface;
323 }
324 return VINF_SUCCESS;
325}
326
327
328/**
329 * Implements the SVGA_3D_CMD_SURFACE_DESTROY command (fifo).
330 *
331 * @returns VBox status code (currently ignored).
332 * @param pThis The VGA device instance data.
333 * @param sid The ID of the surface to destroy.
334 */
335int vmsvga3dSurfaceDestroy(PVGASTATE pThis, uint32_t sid)
336{
337 PVMSVGA3DSTATE pState = pThis->svga.p3dState;
338 AssertReturn(pState, VERR_NO_MEMORY);
339
340 if ( sid < pState->cSurfaces
341 && pState->papSurfaces[sid]->id == sid)
342 {
343 PVMSVGA3DSURFACE pSurface = pState->papSurfaces[sid];
344
345 Log(("vmsvga3dSurfaceDestroy id %x\n", sid));
346
347 /* Check all contexts if this surface is used as a render target or active texture. */
348 for (uint32_t cid = 0; cid < pState->cContexts; cid++)
349 {
350 PVMSVGA3DCONTEXT pContext = pState->papContexts[cid];
351 if (pContext->id == cid)
352 {
353 for (uint32_t i = 0; i < RT_ELEMENTS(pContext->aSidActiveTexture); i++)
354 if (pContext->aSidActiveTexture[i] == sid)
355 pContext->aSidActiveTexture[i] = SVGA3D_INVALID_ID;
356 if (pContext->sidRenderTarget == sid)
357 pContext->sidRenderTarget = SVGA3D_INVALID_ID;
358 }
359 }
360
361 vmsvga3dBackSurfaceDestroy(pState, pSurface);
362
363 if (pSurface->pMipmapLevels)
364 {
365 for (uint32_t i = 0; i < pSurface->cMipmapLevels; ++i)
366 RTMemFree(pSurface->pMipmapLevels[i].pSurfaceData);
367 RTMemFree(pSurface->pMipmapLevels);
368 }
369
370 memset(pSurface, 0, sizeof(*pSurface));
371 pSurface->id = SVGA3D_INVALID_ID;
372 }
373 else
374 AssertFailedReturn(VERR_INVALID_PARAMETER);
375
376 return VINF_SUCCESS;
377}
378
379
380/**
381 * Implements the SVGA_3D_CMD_SURFACE_STRETCHBLT command (fifo).
382 *
383 * @returns VBox status code (currently ignored).
384 * @param pThis The VGA device instance data.
385 * @param pDstSfcImg
386 * @param pDstBox
387 * @param pSrcSfcImg
388 * @param pSrcBox
389 * @param enmMode
390 */
391int vmsvga3dSurfaceStretchBlt(PVGASTATE pThis, SVGA3dSurfaceImageId const *pDstSfcImg, SVGA3dBox const *pDstBox,
392 SVGA3dSurfaceImageId const *pSrcSfcImg, SVGA3dBox const *pSrcBox, SVGA3dStretchBltMode enmMode)
393{
394 PVMSVGA3DSTATE pState = pThis->svga.p3dState;
395
396 AssertReturn(pState, VERR_NO_MEMORY);
397
398 uint32_t const sidSrc = pSrcSfcImg->sid;
399 Assert(sidSrc < SVGA3D_MAX_SURFACE_IDS);
400 AssertReturn(sidSrc < pState->cSurfaces, VERR_INVALID_PARAMETER);
401 PVMSVGA3DSURFACE pSrcSurface = pState->papSurfaces[sidSrc];
402 AssertReturn(pSrcSurface && pSrcSurface->id == sidSrc, VERR_INVALID_PARAMETER);
403
404 uint32_t const sidDst = pDstSfcImg->sid;
405 Assert(sidDst < SVGA3D_MAX_SURFACE_IDS);
406 AssertReturn(sidDst < pState->cSurfaces, VERR_INVALID_PARAMETER);
407 PVMSVGA3DSURFACE pDstSurface = pState->papSurfaces[sidDst];
408 AssertReturn(pDstSurface && pDstSurface->id == sidDst, VERR_INVALID_PARAMETER);
409
410 Assert(pSrcSfcImg->face == 0);
411 AssertReturn(pSrcSfcImg->mipmap < pSrcSurface->faces[0].numMipLevels, VERR_INVALID_PARAMETER);
412 Assert(pDstSfcImg->face == 0);
413 AssertReturn(pDstSfcImg->mipmap < pDstSurface->faces[0].numMipLevels, VERR_INVALID_PARAMETER);
414
415 PVMSVGA3DCONTEXT pContext;
416#ifdef VMSVGA3D_OPENGL
417 Log(("vmsvga3dSurfaceStretchBlt: src sid=%x (%d,%d)(%d,%d) dest sid=%x (%d,%d)(%d,%d) mode=%x\n",
418 sidSrc, pSrcBox->x, pSrcBox->y, pSrcBox->x + pSrcBox->w, pSrcBox->y + pSrcBox->h,
419 sidDst, pDstBox->x, pDstBox->y, pDstBox->x + pDstBox->w, pDstBox->y + pDstBox->h, enmMode));
420 pContext = &pState->SharedCtx;
421 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
422#else
423 Log(("vmsvga3dSurfaceStretchBlt: src sid=%x cid=%x (%d,%d)(%d,%d) dest sid=%x cid=%x (%d,%d)(%d,%d) mode=%x\n",
424 sidSrc, pSrcSurface->idAssociatedContext, pSrcBox->x, pSrcBox->y, pSrcBox->x + pSrcBox->w, pSrcBox->y + pSrcBox->h,
425 sidDst, pDstSurface->idAssociatedContext, pDstBox->x, pDstBox->y, pDstBox->x + pDstBox->w, pDstBox->y + pDstBox->h, enmMode));
426
427 /** @todo stricter checks for associated context */
428 uint32_t cid = pDstSurface->idAssociatedContext;
429 if (cid == SVGA3D_INVALID_ID)
430 cid = pSrcSurface->idAssociatedContext;
431
432 if ( cid >= pState->cContexts
433 || pState->papContexts[cid]->id != cid)
434 {
435 Log(("vmsvga3dSurfaceStretchBlt invalid context id!\n"));
436 AssertFailedReturn(VERR_INVALID_PARAMETER);
437 }
438 pContext = pState->papContexts[cid];
439#endif
440
441 int rc;
442 if (!VMSVGA3DSURFACE_HAS_HW_SURFACE(pSrcSurface))
443 {
444 /* Unknown surface type; turn it into a texture, which can be used for other purposes too. */
445 Log(("vmsvga3dSurfaceStretchBlt: unknown src surface id=%x type=%d format=%d -> create texture\n", sidSrc, pSrcSurface->flags, pSrcSurface->format));
446 rc = vmsvga3dBackCreateTexture(pState, pContext, pContext->id, pSrcSurface);
447 AssertRCReturn(rc, rc);
448 }
449
450 if (!VMSVGA3DSURFACE_HAS_HW_SURFACE(pDstSurface))
451 {
452 /* Unknown surface type; turn it into a texture, which can be used for other purposes too. */
453 Log(("vmsvga3dSurfaceStretchBlt: unknown dest surface id=%x type=%d format=%d -> create texture\n", sidDst, pDstSurface->flags, pDstSurface->format));
454 rc = vmsvga3dBackCreateTexture(pState, pContext, pContext->id, pDstSurface);
455 AssertRCReturn(rc, rc);
456 }
457
458 SVGA3dBox clipSrcBox = *pSrcBox;
459 SVGA3dBox clipDstBox = *pDstBox;
460 vmsvgaClipBox(&pSrcSurface->pMipmapLevels[pSrcSfcImg->mipmap].size, &clipSrcBox);
461 vmsvgaClipBox(&pDstSurface->pMipmapLevels[pDstSfcImg->mipmap].size, &clipDstBox);
462
463 return vmsvga3dBackSurfaceStretchBlt(pThis, pState,
464 pDstSurface, pDstSfcImg->mipmap, &clipDstBox,
465 pSrcSurface, pSrcSfcImg->mipmap, &clipSrcBox,
466 enmMode, pContext);
467}
468
469
470
471/**
472 * Implements the SVGA_3D_CMD_SURFACE_DMA command (fifo).
473 *
474 * @returns VBox status code (currently ignored).
475 * @param pThis The VGA device instance data.
476 * @param guest .
477 * @param host .
478 * @param transfer .
479 * @param cCopyBoxes .
480 * @param paBoxes .
481 */
482int vmsvga3dSurfaceDMA(PVGASTATE pThis, SVGA3dGuestImage guest, SVGA3dSurfaceImageId host, SVGA3dTransferType transfer,
483 uint32_t cCopyBoxes, SVGA3dCopyBox *paBoxes)
484{
485 int rc = VINF_SUCCESS;
486
487 PVMSVGA3DSTATE pState = pThis->svga.p3dState;
488 AssertReturn(pState, VERR_NO_MEMORY);
489
490 uint32_t sid = host.sid;
491 Assert(sid < SVGA3D_MAX_SURFACE_IDS);
492 AssertReturn(sid < pState->cSurfaces, VERR_INVALID_PARAMETER);
493 PVMSVGA3DSURFACE pSurface = pState->papSurfaces[sid];
494 AssertReturn(pSurface && pSurface->id == sid, VERR_INVALID_PARAMETER);
495
496 if (pSurface->flags & SVGA3D_SURFACE_HINT_TEXTURE)
497 Log(("vmsvga3dSurfaceDMA TEXTURE guestptr gmr=%x offset=%x pitch=%x host sid=%x face=%d mipmap=%d transfer=%s cCopyBoxes=%d\n", guest.ptr.gmrId, guest.ptr.offset, guest.pitch, host.sid, host.face, host.mipmap, (transfer == SVGA3D_WRITE_HOST_VRAM) ? "READ" : "WRITE", cCopyBoxes));
498 else
499 Log(("vmsvga3dSurfaceDMA guestptr gmr=%x offset=%x pitch=%x host sid=%x face=%d mipmap=%d transfer=%s cCopyBoxes=%d\n", guest.ptr.gmrId, guest.ptr.offset, guest.pitch, host.sid, host.face, host.mipmap, (transfer == SVGA3D_WRITE_HOST_VRAM) ? "READ" : "WRITE", cCopyBoxes));
500
501 AssertMsg(host.face == 0, ("host.face=%#x\n", host.face));
502 AssertMsgReturn(pSurface->faces[0].numMipLevels > host.mipmap, ("numMipLevels %d, host.mipmap %d", pSurface->faces[0].numMipLevels, host.mipmap), VERR_INVALID_PARAMETER);
503 PVMSVGA3DMIPMAPLEVEL pMipLevel = &pSurface->pMipmapLevels[host.mipmap];
504
505 if (!VMSVGA3DSURFACE_HAS_HW_SURFACE(pSurface))
506 {
507 /*
508 * Not realized in host hardware/library yet, we have to work with
509 * the copy of the data we've got in VMSVGA3DMIMAPLEVEL::pvSurfaceData.
510 */
511 AssertReturn(pSurface->pMipmapLevels[host.mipmap].pSurfaceData, VERR_INTERNAL_ERROR);
512
513 for (unsigned i = 0; i < cCopyBoxes; i++)
514 {
515 unsigned uDestOffset;
516 unsigned cbSrcPitch;
517 uint8_t *pBufferStart;
518
519 Log(("Copy box %d (%d,%d,%d)(%d,%d,%d) dest (%d,%d)\n", 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));
520
521 /* Apparently we're supposed to clip it (gmr test sample) */
522 SVGA3dCopyBox clipBox = paBoxes[i];
523 vmsvgaClipCopyBox(&pMipLevel->size, &pMipLevel->size, &clipBox);
524 if ( !clipBox.w
525 || !clipBox.h
526 || !clipBox.d)
527 {
528 Log(("Empty box; skip\n"));
529 continue;
530 }
531
532 uDestOffset = clipBox.x * pSurface->cbBlock + clipBox.y * pMipLevel->cbSurfacePitch + clipBox.z * pMipLevel->size.height * pMipLevel->cbSurfacePitch;
533 AssertReturn(uDestOffset + clipBox.w * pSurface->cbBlock * clipBox.h * clipBox.d <= pMipLevel->cbSurface, VERR_INTERNAL_ERROR);
534
535 cbSrcPitch = (guest.pitch == 0) ? clipBox.w * pSurface->cbBlock : guest.pitch;
536#ifdef MANUAL_FLIP_SURFACE_DATA
537 pBufferStart = (uint8_t *)pMipLevel->pSurfaceData
538 + clipBox.x * pSurface->cbBlock
539 + pMipLevel->cbSurface - clipBox.y * pMipLevel->cbSurfacePitch
540 - pMipLevel->cbSurfacePitch; /* flip image during copy */
541#else
542 pBufferStart = (uint8_t *)pMipLevel->pSurfaceData + uDestOffset;
543#endif
544 rc = vmsvgaGMRTransfer(pThis,
545 transfer,
546 pBufferStart,
547#ifdef MANUAL_FLIP_SURFACE_DATA
548 -(int32_t)pMipLevel->cbSurfacePitch,
549#else
550 (int32_t)pMipLevel->cbSurfacePitch,
551#endif
552 guest.ptr,
553 clipBox.srcx * pSurface->cbBlock + (clipBox.srcy + clipBox.srcz * clipBox.h) * cbSrcPitch,
554 cbSrcPitch,
555 clipBox.w * pSurface->cbBlock,
556 clipBox.d * clipBox.h);
557
558 Log4(("first line:\n%.*Rhxd\n", pMipLevel->cbSurfacePitch, pMipLevel->pSurfaceData));
559
560 AssertRC(rc);
561 }
562 pSurface->pMipmapLevels[host.mipmap].fDirty = true;
563 pSurface->fDirty = true;
564 }
565 else
566 {
567 /*
568 * Because of the clipping below, we're doing a little more
569 * here before calling the backend specific code.
570 */
571#ifdef VMSVGA3D_DIRECT3D
572 /* Flush the drawing pipeline for this surface as it could be used in a shared context. */
573 vmsvga3dSurfaceFlush(pThis, pSurface);
574 PVMSVGA3DCONTEXT pContext = NULL;
575
576#else /* VMSVGA3D_OPENGL */
577 PVMSVGA3DCONTEXT pContext = &pState->SharedCtx;
578 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
579#endif
580
581 for (unsigned i = 0; i < cCopyBoxes; i++)
582 {
583 Log(("Copy box %d (%d,%d,%d)(%d,%d,%d) dest (%d,%d)\n", 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));
584
585 /** @todo Is d == 0 valid? */
586 Assert((paBoxes[i].d == 1 || paBoxes[i].d == 0) && paBoxes[i].z == 0);
587
588 /* Apparently we're supposed to clip it (gmr test sample) */
589 SVGA3dCopyBox clipBox = paBoxes[i];
590 vmsvgaClipCopyBox(&pMipLevel->size, &pMipLevel->size, &clipBox);
591 if ( !clipBox.w
592 || !clipBox.h
593 || !clipBox.d)
594 {
595 Log(("Empty box; skip\n"));
596 continue;
597 }
598
599 uint32_t cbSrcPitch = (guest.pitch == 0) ? clipBox.w * pSurface->cbBlock : guest.pitch;
600 rc = vmsvga3dBackSurfaceDMACopyBox(pThis, pState, pSurface, host.mipmap, guest.ptr, cbSrcPitch, transfer,
601 &clipBox, pContext, rc, i);
602 }
603 }
604
605 return rc;
606}
607
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