VirtualBox

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

Last change on this file since 66519 was 66519, checked in by vboxsync, 8 years ago

DevVGA-SVGA3d: bugref:8735: added a couple of checks and simplified the loop for buffer allocation

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