VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPVbva.cpp@ 46783

Last change on this file since 46783 was 44529, checked in by vboxsync, 12 years ago

header (C) fixes

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.6 KB
Line 
1/* $Id: VBoxMPVbva.cpp 44529 2013-02-04 15:54:15Z vboxsync $ */
2
3/** @file
4 * VBox WDDM Miniport driver
5 */
6
7/*
8 * Copyright (C) 2011-2012 Oracle Corporation
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.virtualbox.org. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License (GPL) as published by the Free Software
14 * Foundation, in version 2 as it comes in the "COPYING" file of the
15 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
17 */
18
19#include "VBoxMPWddm.h"
20#include "common/VBoxMPCommon.h"
21
22static int vboxVBVAInformHost (PVBOXMP_DEVEXT pDevExt, VBOXVBVAINFO * pVbva, BOOL bEnable)
23{
24 int rc = VERR_NO_MEMORY;
25 void *p = VBoxHGSMIBufferAlloc (&VBoxCommonFromDeviceExt(pDevExt)->guestCtx,
26 sizeof (VBVAENABLE_EX),
27 HGSMI_CH_VBVA,
28 VBVA_ENABLE);
29 Assert(p);
30 if (!p)
31 {
32 LOGREL(("HGSMIHeapAlloc failed"));
33 rc = VERR_NO_MEMORY;
34 }
35 else
36 {
37 VBVAENABLE_EX *pEnableEx = (VBVAENABLE_EX *)p;
38 pEnableEx->u32ScreenId = pVbva->srcId;
39
40 VBVAENABLE *pEnable = &pEnableEx->Base;
41 pEnable->u32Flags = bEnable? VBVA_F_ENABLE: VBVA_F_DISABLE;
42 pEnable->u32Flags |= VBVA_F_EXTENDED | VBVA_F_ABSOFFSET;
43 pEnable->u32Offset = (uint32_t)pVbva->offVBVA;
44 pEnable->i32Result = VERR_NOT_SUPPORTED;
45
46 VBoxHGSMIBufferSubmit (&VBoxCommonFromDeviceExt(pDevExt)->guestCtx, p);
47
48 if (bEnable)
49 {
50 rc = pEnable->i32Result;
51 AssertRC(rc);
52 }
53 else
54 rc = VINF_SUCCESS;
55
56 VBoxHGSMIBufferFree (&VBoxCommonFromDeviceExt(pDevExt)->guestCtx, p);
57 }
58 return rc;
59}
60
61/*
62 * Public hardware buffer methods.
63 */
64int vboxVbvaEnable (PVBOXMP_DEVEXT pDevExt, VBOXVBVAINFO *pVbva)
65{
66 VBVABUFFER *pVBVA = pVbva->pVBVA;
67
68// DISPDBG((1, "VBoxDisp::vboxVbvaEnable screen %p vbva off 0x%x\n", ppdev->pjScreen, ppdev->layout.offVBVABuffer));
69
70 pVBVA->hostFlags.u32HostEvents = 0;
71 pVBVA->hostFlags.u32SupportedOrders = 0;
72 pVBVA->off32Data = 0;
73 pVBVA->off32Free = 0;
74 RtlZeroMemory (pVBVA->aRecords, sizeof (pVBVA->aRecords));
75 pVBVA->indexRecordFirst = 0;
76 pVBVA->indexRecordFree = 0;
77 pVBVA->cbPartialWriteThreshold = 256;
78 pVBVA->cbData = pVbva->cbVBVA - sizeof (VBVABUFFER) + sizeof (pVBVA->au8Data);
79
80 pVbva->fHwBufferOverflow = FALSE;
81 pVbva->pRecord = NULL;
82
83 int rc = vboxVBVAInformHost (pDevExt, pVbva, TRUE);
84 AssertRC(rc);
85
86 if (!RT_SUCCESS(rc))
87 vboxVbvaDisable (pDevExt, pVbva);
88
89 return rc;
90}
91
92int vboxVbvaDisable (PVBOXMP_DEVEXT pDevExt, VBOXVBVAINFO *pVbva)
93{
94// DISPDBG((1, "VBoxDisp::vbvaDisable called.\n"));
95
96 pVbva->fHwBufferOverflow = FALSE;
97 pVbva->pRecord = NULL;
98// ppdev->pVBVA = NULL;
99
100 return vboxVBVAInformHost (pDevExt, pVbva, FALSE);
101}
102
103int vboxVbvaCreate(PVBOXMP_DEVEXT pDevExt, VBOXVBVAINFO *pVbva, ULONG offBuffer, ULONG cbBuffer, D3DDDI_VIDEO_PRESENT_SOURCE_ID srcId)
104{
105 memset(pVbva, 0, sizeof(VBOXVBVAINFO));
106
107 KeInitializeSpinLock(&pVbva->Lock);
108
109 int rc = VBoxMPCmnMapAdapterMemory(VBoxCommonFromDeviceExt(pDevExt),
110 (void**)&pVbva->pVBVA,
111 offBuffer,
112 cbBuffer);
113 AssertRC(rc);
114 if (RT_SUCCESS(rc))
115 {
116 Assert(pVbva->pVBVA);
117 pVbva->offVBVA = offBuffer;
118 pVbva->cbVBVA = cbBuffer;
119 pVbva->srcId = srcId;
120 }
121
122 return rc;
123}
124
125int vboxVbvaDestroy(PVBOXMP_DEVEXT pDevExt, VBOXVBVAINFO *pVbva)
126{
127 int rc = VINF_SUCCESS;
128 VBoxMPCmnUnmapAdapterMemory(VBoxCommonFromDeviceExt(pDevExt), (void**)&pVbva->pVBVA);
129 memset(pVbva, 0, sizeof(VBOXVBVAINFO));
130 return rc;
131}
132
133/*
134 * Private operations.
135 */
136static uint32_t vboxHwBufferAvail (const VBVABUFFER *pVBVA)
137{
138 int32_t i32Diff = pVBVA->off32Data - pVBVA->off32Free;
139
140 return i32Diff > 0? i32Diff: pVBVA->cbData + i32Diff;
141}
142
143static void vboxHwBufferFlush (PVBOXMP_DEVEXT pDevExt, VBOXVBVAINFO *pVbva)
144{
145 /* Issue the flush command. */
146 void *p = VBoxHGSMIBufferAlloc (&VBoxCommonFromDeviceExt(pDevExt)->guestCtx,
147 sizeof (VBVAFLUSH),
148 HGSMI_CH_VBVA,
149 VBVA_FLUSH);
150 Assert(p);
151 if (!p)
152 {
153 LOGREL(("HGSMIHeapAlloc failed"));
154 }
155 else
156 {
157 VBVAFLUSH *pFlush = (VBVAFLUSH *)p;
158
159 pFlush->u32Reserved = 0;
160
161 VBoxHGSMIBufferSubmit (&VBoxCommonFromDeviceExt(pDevExt)->guestCtx, p);
162
163 VBoxHGSMIBufferFree (&VBoxCommonFromDeviceExt(pDevExt)->guestCtx, p);
164 }
165
166 return;
167}
168
169static void vboxHwBufferPlaceDataAt (VBVABUFFER *pVBVA, const void *p, uint32_t cb, uint32_t offset)
170{
171 uint32_t u32BytesTillBoundary = pVBVA->cbData - offset;
172 uint8_t *dst = &pVBVA->au8Data[offset];
173 int32_t i32Diff = cb - u32BytesTillBoundary;
174
175 if (i32Diff <= 0)
176 {
177 /* Chunk will not cross buffer boundary. */
178 memcpy (dst, p, cb);
179 }
180 else
181 {
182 /* Chunk crosses buffer boundary. */
183 memcpy (dst, p, u32BytesTillBoundary);
184 memcpy (&pVBVA->au8Data[0], (uint8_t *)p + u32BytesTillBoundary, i32Diff);
185 }
186
187 return;
188}
189
190BOOL vboxVbvaBufferBeginUpdate (PVBOXMP_DEVEXT pDevExt, VBOXVBVAINFO *pVbva)
191{
192 BOOL bRc = FALSE;
193
194 // DISPDBG((1, "VBoxDisp::vboxHwBufferBeginUpdate called flags = 0x%08X\n",
195 // ppdev->pVBVA? ppdev->pVBVA->u32HostEvents: -1));
196
197 if ( pVbva->pVBVA
198 && (pVbva->pVBVA->hostFlags.u32HostEvents & VBVA_F_MODE_ENABLED))
199 {
200 uint32_t indexRecordNext;
201
202 Assert (!pVbva->fHwBufferOverflow);
203 Assert (pVbva->pRecord == NULL);
204
205 indexRecordNext = (pVbva->pVBVA->indexRecordFree + 1) % VBVA_MAX_RECORDS;
206
207 if (indexRecordNext == pVbva->pVBVA->indexRecordFirst)
208 {
209 /* All slots in the records queue are used. */
210 vboxHwBufferFlush (pDevExt, pVbva);
211 }
212
213 if (indexRecordNext == pVbva->pVBVA->indexRecordFirst)
214 {
215// /* Even after flush there is no place. Fail the request. */
216// LOG(("no space in the queue of records!!! first %d, last %d",
217// ppdev->pVBVA->indexRecordFirst, ppdev->pVBVA->indexRecordFree));
218 }
219 else
220 {
221 /* Initialize the record. */
222 VBVARECORD *pRecord = &pVbva->pVBVA->aRecords[pVbva->pVBVA->indexRecordFree];
223
224 pRecord->cbRecord = VBVA_F_RECORD_PARTIAL;
225
226 pVbva->pVBVA->indexRecordFree = indexRecordNext;
227
228 // LOG(("indexRecordNext = %d\n", indexRecordNext));
229
230 /* Remember which record we are using. */
231 pVbva->pRecord = pRecord;
232
233 bRc = TRUE;
234 }
235 }
236
237 return bRc;
238}
239
240void vboxVbvaBufferEndUpdate (PVBOXMP_DEVEXT pDevExt, VBOXVBVAINFO *pVbva)
241{
242 VBVARECORD *pRecord;
243
244 // LOG(("VBoxDisp::vboxHwBufferEndUpdate called"));
245
246 Assert(pVbva->pVBVA);
247
248 pRecord = pVbva->pRecord;
249 Assert (pRecord && (pRecord->cbRecord & VBVA_F_RECORD_PARTIAL));
250
251 /* Mark the record completed. */
252 pRecord->cbRecord &= ~VBVA_F_RECORD_PARTIAL;
253
254 pVbva->fHwBufferOverflow = FALSE;
255 pVbva->pRecord = NULL;
256
257 return;
258}
259
260static int vboxHwBufferWrite (PVBOXMP_DEVEXT pDevExt, VBOXVBVAINFO *pVbva, const void *p, uint32_t cb)
261{
262 VBVARECORD *pRecord;
263 uint32_t cbHwBufferAvail;
264
265 uint32_t cbWritten = 0;
266
267 VBVABUFFER *pVBVA = pVbva->pVBVA;
268 Assert(pVBVA);
269
270 if (!pVBVA || pVbva->fHwBufferOverflow)
271 {
272 return VERR_INVALID_STATE;
273 }
274
275 Assert (pVBVA->indexRecordFirst != pVBVA->indexRecordFree);
276
277 pRecord = pVbva->pRecord;
278 Assert (pRecord && (pRecord->cbRecord & VBVA_F_RECORD_PARTIAL));
279
280// LOGF(("VW %d", cb));
281
282 cbHwBufferAvail = vboxHwBufferAvail (pVBVA);
283
284 while (cb > 0)
285 {
286 uint32_t cbChunk = cb;
287
288 // LOG(("pVBVA->off32Free %d, pRecord->cbRecord 0x%08X, cbHwBufferAvail %d, cb %d, cbWritten %d\n",
289 // pVBVA->off32Free, pRecord->cbRecord, cbHwBufferAvail, cb, cbWritten));
290
291 if (cbChunk >= cbHwBufferAvail)
292 {
293 LOG(("1) avail %d, chunk %d", cbHwBufferAvail, cbChunk));
294
295 vboxHwBufferFlush (pDevExt, pVbva);
296
297 cbHwBufferAvail = vboxHwBufferAvail (pVBVA);
298
299 if (cbChunk >= cbHwBufferAvail)
300 {
301 LOG(("no place for %d bytes. Only %d bytes available after flush. Going to partial writes.",
302 cb, cbHwBufferAvail));
303
304 if (cbHwBufferAvail <= pVBVA->cbPartialWriteThreshold)
305 {
306 LOGREL(("Buffer overflow!!!"));
307 pVbva->fHwBufferOverflow = TRUE;
308 Assert(FALSE);
309 return VERR_NO_MEMORY;
310 }
311
312 cbChunk = cbHwBufferAvail - pVBVA->cbPartialWriteThreshold;
313 }
314 }
315
316 Assert(cbChunk <= cb);
317 Assert(cbChunk <= vboxHwBufferAvail (pVBVA));
318
319 vboxHwBufferPlaceDataAt (pVbva->pVBVA, (uint8_t *)p + cbWritten, cbChunk, pVBVA->off32Free);
320
321 pVBVA->off32Free = (pVBVA->off32Free + cbChunk) % pVBVA->cbData;
322 pRecord->cbRecord += cbChunk;
323 cbHwBufferAvail -= cbChunk;
324
325 cb -= cbChunk;
326 cbWritten += cbChunk;
327 }
328
329 return VINF_SUCCESS;
330}
331
332/*
333 * Public writer to the hardware buffer.
334 */
335int vboxWrite (PVBOXMP_DEVEXT pDevExt, VBOXVBVAINFO *pVbva, const void *pv, uint32_t cb)
336{
337 return vboxHwBufferWrite (pDevExt, pVbva, pv, cb);
338}
339
340
341int vboxVbvaReportDirtyRect (PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_SOURCE pSrc, RECT *pRectOrig)
342{
343 VBVACMDHDR hdr;
344
345 RECT rect = *pRectOrig;
346
347// if (rect.left < 0) rect.left = 0;
348// if (rect.top < 0) rect.top = 0;
349// if (rect.right > (int)ppdev->cxScreen) rect.right = ppdev->cxScreen;
350// if (rect.bottom > (int)ppdev->cyScreen) rect.bottom = ppdev->cyScreen;
351
352 hdr.x = (int16_t)rect.left;
353 hdr.y = (int16_t)rect.top;
354 hdr.w = (uint16_t)(rect.right - rect.left);
355 hdr.h = (uint16_t)(rect.bottom - rect.top);
356
357 hdr.x += (int16_t)pSrc->VScreenPos.x;
358 hdr.y += (int16_t)pSrc->VScreenPos.y;
359
360 return vboxWrite (pDevExt, &pSrc->Vbva, &hdr, sizeof(hdr));
361}
362
363#ifdef VBOXVDMA_WITH_VBVA
364int vboxVbvaReportCmdOffset (PVBOXMP_DEVEXT pDevExt, VBOXVBVAINFO *pVbva, uint32_t offCmd)
365{
366 VBOXVDMAVBVACMD cmd;
367 cmd.offCmd = offCmd;
368 return vboxWrite (pDevExt, pVbva, &cmd, sizeof(cmd));
369}
370#endif
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