VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/Graphics/Display/vbox.c@ 34406

Last change on this file since 34406 was 33890, checked in by vboxsync, 14 years ago

Additions/WINNT/Graphics: more refactoring

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 22.0 KB
Line 
1/* $Id: vbox.c 33890 2010-11-09 11:20:54Z vboxsync $ */
2/** @file
3 * Display - VirtualBox Win 2000/XP guest display driver, support functions.
4 */
5
6/*
7 * Copyright (C) 2006-2007 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#include "driver.h"
19
20#include <VBox/VMMDev.h>
21#include <VBox/VBoxGuest.h>
22#include <VBox/err.h>
23#include <iprt/asm.h>
24#include <iprt/asm-amd64-x86.h>
25
26/*
27 * There is a hardware ring buffer in the VBox VMMDev PCI memory space.
28 * All graphics commands go there serialized by vboxHwBufferBeginUpdate.
29 * and vboxHwBufferEndUpdate.
30 *
31 * off32Free is writing position. off32Data is reading position.
32 * off32Free == off32Data means buffer is empty.
33 * There must be always gap between off32Data and off32Free when data
34 * are in the buffer.
35 * Guest only changes off32Free, host changes off32Data.
36 */
37
38/* Forward declarations of internal functions. */
39static void vboxHwBufferFlush (PPDEV ppdev);
40static void vboxHwBufferPlaceDataAt (PPDEV ppdev, void *p, uint32_t cb, uint32_t offset);
41static BOOL vboxHwBufferWrite (PPDEV ppdev, const void *p, uint32_t cb);
42
43
44static void vboxHGSMIBufferSubmit (PPDEV ppdev, void *p)
45{
46 HGSMIOFFSET offBuffer = HGSMIHeapBufferOffset (&ppdev->hgsmiDisplayHeap, p);
47
48 DISPDBG((0, "VBoxDISP::vboxHGSMIBufferSubmit: offset 0x%x\n", offBuffer));
49
50 ASMOutU32(ppdev->IOPortGuestCommand, offBuffer);
51}
52
53static BOOL vboxVBVAInformHost (PPDEV ppdev, BOOL bEnable)
54{
55 BOOL bRc = FALSE;
56
57 if (ppdev->bHGSMISupported)
58 {
59 void *p = HGSMIHeapAlloc (&ppdev->hgsmiDisplayHeap,
60 sizeof (VBVAENABLE),
61 HGSMI_CH_VBVA,
62 VBVA_ENABLE);
63 if (!p)
64 {
65 DISPDBG((0, "VBoxDISP::vboxVBVAInformHost: HGSMIHeapAlloc failed\n"));
66 }
67 else
68 {
69 VBVAENABLE *pEnable = (VBVAENABLE *)p;
70
71 pEnable->u32Flags = bEnable? VBVA_F_ENABLE: VBVA_F_DISABLE;
72 pEnable->u32Offset = ppdev->layout.offVBVABuffer;
73 pEnable->i32Result = VERR_NOT_SUPPORTED;
74
75 vboxHGSMIBufferSubmit (ppdev, p);
76
77 if (bEnable)
78 {
79 bRc = RT_SUCCESS(pEnable->i32Result);
80 }
81 else
82 {
83 bRc = TRUE;
84 }
85
86 HGSMIHeapFree (&ppdev->hgsmiDisplayHeap, p);
87 }
88 }
89
90 return bRc;
91}
92
93/*
94 * Public hardware buffer methods.
95 */
96BOOL vboxVbvaEnable (PPDEV ppdev)
97{
98 BOOL bRc = FALSE;
99
100 DISPDBG((1, "VBoxDisp::vboxVbvaEnable called ppdev %p, hgsmi %d, vbva %p\n", ppdev, ppdev->bHGSMISupported, ppdev->pVBVA));
101
102 if (ppdev->bHGSMISupported)
103 {
104 VBVABUFFER *pVBVA = (VBVABUFFER *)((uint8_t *)ppdev->pjScreen + ppdev->layout.offVBVABuffer);
105
106 DISPDBG((1, "VBoxDisp::vboxVbvaEnable screen %p vbva off 0x%x\n", ppdev->pjScreen, ppdev->layout.offVBVABuffer));
107
108 pVBVA->hostFlags.u32HostEvents = 0;
109 pVBVA->hostFlags.u32SupportedOrders = 0;
110 pVBVA->off32Data = 0;
111 pVBVA->off32Free = 0;
112 RtlZeroMemory (pVBVA->aRecords, sizeof (pVBVA->aRecords));
113 pVBVA->indexRecordFirst = 0;
114 pVBVA->indexRecordFree = 0;
115 pVBVA->cbPartialWriteThreshold = 256;
116 pVBVA->cbData = ppdev->layout.cbVBVABuffer - sizeof (VBVABUFFER) + sizeof (pVBVA->au8Data);
117
118 ppdev->fHwBufferOverflow = FALSE;
119 ppdev->pRecord = NULL;
120 ppdev->pVBVA = pVBVA;
121
122 bRc = vboxVBVAInformHost (ppdev, TRUE);
123 }
124
125 if (!bRc)
126 {
127 vboxVbvaDisable (ppdev);
128 }
129
130 return bRc;
131}
132
133void vboxVbvaDisable (PPDEV ppdev)
134{
135 DISPDBG((1, "VBoxDisp::vbvaDisable called.\n"));
136
137 ppdev->fHwBufferOverflow = FALSE;
138 ppdev->pRecord = NULL;
139 ppdev->pVBVA = NULL;
140
141 vboxVBVAInformHost (ppdev, FALSE);
142
143 return;
144}
145
146BOOL vboxHwBufferBeginUpdate (PPDEV ppdev)
147{
148 BOOL bRc = FALSE;
149
150 // DISPDBG((1, "VBoxDisp::vboxHwBufferBeginUpdate called flags = 0x%08X\n",
151 // ppdev->pVBVA? ppdev->pVBVA->u32HostEvents: -1));
152
153 if ( ppdev->pVBVA
154 && (ppdev->pVBVA->hostFlags.u32HostEvents & VBVA_F_MODE_ENABLED))
155 {
156 uint32_t indexRecordNext;
157
158 VBVA_ASSERT (!ppdev->fHwBufferOverflow);
159 VBVA_ASSERT (ppdev->pRecord == NULL);
160
161 indexRecordNext = (ppdev->pVBVA->indexRecordFree + 1) % VBVA_MAX_RECORDS;
162
163 if (indexRecordNext == ppdev->pVBVA->indexRecordFirst)
164 {
165 /* All slots in the records queue are used. */
166 vboxHwBufferFlush (ppdev);
167 }
168
169 if (indexRecordNext == ppdev->pVBVA->indexRecordFirst)
170 {
171 /* Even after flush there is no place. Fail the request. */
172 DISPDBG((1, "VBoxDisp::vboxHwBufferBeginUpdate no space in the queue of records!!! first %d, last %d\n",
173 ppdev->pVBVA->indexRecordFirst, ppdev->pVBVA->indexRecordFree));
174 }
175 else
176 {
177 /* Initialize the record. */
178 VBVARECORD *pRecord = &ppdev->pVBVA->aRecords[ppdev->pVBVA->indexRecordFree];
179
180 pRecord->cbRecord = VBVA_F_RECORD_PARTIAL;
181
182 ppdev->pVBVA->indexRecordFree = indexRecordNext;
183
184 // DISPDBG((1, "VBoxDisp::vboxHwBufferBeginUpdate indexRecordNext = %d\n", indexRecordNext));
185
186 /* Remember which record we are using. */
187 ppdev->pRecord = pRecord;
188
189 bRc = TRUE;
190 }
191 }
192
193 return bRc;
194}
195
196void vboxHwBufferEndUpdate (PPDEV ppdev)
197{
198 VBVARECORD *pRecord;
199
200 // DISPDBG((1, "VBoxDisp::vboxHwBufferEndUpdate called\n"));
201
202 VBVA_ASSERT(ppdev->pVBVA);
203
204 pRecord = ppdev->pRecord;
205 VBVA_ASSERT (pRecord && (pRecord->cbRecord & VBVA_F_RECORD_PARTIAL));
206
207 /* Mark the record completed. */
208 pRecord->cbRecord &= ~VBVA_F_RECORD_PARTIAL;
209
210 ppdev->fHwBufferOverflow = FALSE;
211 ppdev->pRecord = NULL;
212
213 return;
214}
215
216/*
217 * Private operations.
218 */
219static uint32_t vboxHwBufferAvail (const VBVABUFFER *pVBVA)
220{
221 int32_t i32Diff = pVBVA->off32Data - pVBVA->off32Free;
222
223 return i32Diff > 0? i32Diff: pVBVA->cbData + i32Diff;
224}
225
226static void vboxHwBufferFlush (PPDEV ppdev)
227{
228 /* Issue the flush command. */
229 void *p = HGSMIHeapAlloc (&ppdev->hgsmiDisplayHeap,
230 sizeof (VBVAFLUSH),
231 HGSMI_CH_VBVA,
232 VBVA_FLUSH);
233 if (!p)
234 {
235 DISPDBG((0, "VBoxDISP::vboxHwBufferFlush: HGSMIHeapAlloc failed\n"));
236 }
237 else
238 {
239 VBVAFLUSH *pFlush = (VBVAFLUSH *)p;
240
241 pFlush->u32Reserved = 0;
242
243 vboxHGSMIBufferSubmit (ppdev, p);
244
245 HGSMIHeapFree (&ppdev->hgsmiDisplayHeap, p);
246 }
247
248 return;
249}
250
251static void vboxHwBufferPlaceDataAt (PPDEV ppdev, const void *p, uint32_t cb, uint32_t offset)
252{
253 VBVABUFFER *pVBVA = ppdev->pVBVA;
254 uint32_t u32BytesTillBoundary = pVBVA->cbData - offset;
255 uint8_t *dst = &pVBVA->au8Data[offset];
256 int32_t i32Diff = cb - u32BytesTillBoundary;
257
258 if (i32Diff <= 0)
259 {
260 /* Chunk will not cross buffer boundary. */
261 memcpy (dst, p, cb);
262 }
263 else
264 {
265 /* Chunk crosses buffer boundary. */
266 memcpy (dst, p, u32BytesTillBoundary);
267 memcpy (&pVBVA->au8Data[0], (uint8_t *)p + u32BytesTillBoundary, i32Diff);
268 }
269
270 return;
271}
272
273static BOOL vboxHwBufferWrite (PPDEV ppdev, const void *p, uint32_t cb)
274{
275 VBVARECORD *pRecord;
276 uint32_t cbHwBufferAvail;
277
278 uint32_t cbWritten = 0;
279
280 VBVABUFFER *pVBVA = ppdev->pVBVA;
281 VBVA_ASSERT(pVBVA);
282
283 if (!pVBVA || ppdev->fHwBufferOverflow)
284 {
285 return FALSE;
286 }
287
288 VBVA_ASSERT (pVBVA->indexRecordFirst != pVBVA->indexRecordFree);
289
290 pRecord = ppdev->pRecord;
291 VBVA_ASSERT (pRecord && (pRecord->cbRecord & VBVA_F_RECORD_PARTIAL));
292
293 DISPDBG((1, "VW %d\n", cb));
294
295 cbHwBufferAvail = vboxHwBufferAvail (pVBVA);
296
297 while (cb > 0)
298 {
299 uint32_t cbChunk = cb;
300
301 // DISPDBG((1, "VBoxDisp::vboxHwBufferWrite pVBVA->off32Free %d, pRecord->cbRecord 0x%08X, cbHwBufferAvail %d, cb %d, cbWritten %d\n",
302 // pVBVA->off32Free, pRecord->cbRecord, cbHwBufferAvail, cb, cbWritten));
303
304 if (cbChunk >= cbHwBufferAvail)
305 {
306 DISPDBG((1, "VBoxDisp::vboxHwBufferWrite 1) avail %d, chunk %d\n", cbHwBufferAvail, cbChunk));
307
308 vboxHwBufferFlush (ppdev);
309
310 cbHwBufferAvail = vboxHwBufferAvail (pVBVA);
311
312 if (cbChunk >= cbHwBufferAvail)
313 {
314 DISPDBG((1, "VBoxDisp::vboxHwBufferWrite: no place for %d bytes. Only %d bytes available after flush. Going to partial writes.\n",
315 cb, cbHwBufferAvail));
316
317 if (cbHwBufferAvail <= pVBVA->cbPartialWriteThreshold)
318 {
319 DISPDBG((1, "VBoxDisp::vboxHwBufferWrite: Buffer overflow!!!\n"));
320 ppdev->fHwBufferOverflow = TRUE;
321 VBVA_ASSERT(FALSE);
322 return FALSE;
323 }
324
325 cbChunk = cbHwBufferAvail - pVBVA->cbPartialWriteThreshold;
326 }
327 }
328
329 VBVA_ASSERT(cbChunk <= cb);
330 VBVA_ASSERT(cbChunk <= vboxHwBufferAvail (pVBVA));
331
332 vboxHwBufferPlaceDataAt (ppdev, (uint8_t *)p + cbWritten, cbChunk, pVBVA->off32Free);
333
334 pVBVA->off32Free = (pVBVA->off32Free + cbChunk) % pVBVA->cbData;
335 pRecord->cbRecord += cbChunk;
336 cbHwBufferAvail -= cbChunk;
337
338 cb -= cbChunk;
339 cbWritten += cbChunk;
340 }
341
342 return TRUE;
343}
344
345/*
346 * Public writer to the hardware buffer.
347 */
348BOOL vboxWrite (PPDEV ppdev, const void *pv, uint32_t cb)
349{
350 return vboxHwBufferWrite (ppdev, pv, cb);
351}
352
353BOOL vboxOrderSupported (PPDEV ppdev, unsigned code)
354{
355 VBVABUFFER *pVBVA = ppdev->pVBVA;
356
357 if (!pVBVA)
358 {
359 return FALSE;
360 }
361
362 if (pVBVA->hostFlags.u32SupportedOrders & (1 << code))
363 {
364 return TRUE;
365 }
366
367 return FALSE;
368}
369
370void VBoxProcessDisplayInfo (PPDEV ppdev)
371{
372 if (ppdev->bHGSMISupported)
373 {
374 /* Issue the screen info command. */
375 void *p = HGSMIHeapAlloc (&ppdev->hgsmiDisplayHeap,
376 sizeof (VBVAINFOSCREEN),
377 HGSMI_CH_VBVA,
378 VBVA_INFO_SCREEN);
379 if (!p)
380 {
381 DISPDBG((0, "VBoxDISP::VBoxProcessDisplayInfo: HGSMIHeapAlloc failed\n"));
382 }
383 else
384 {
385 VBVAINFOSCREEN *pScreen = (VBVAINFOSCREEN *)p;
386
387 pScreen->u32ViewIndex = ppdev->iDevice;
388 pScreen->i32OriginX = ppdev->ptlDevOrg.x;
389 pScreen->i32OriginY = ppdev->ptlDevOrg.y;
390 pScreen->u32StartOffset = 0;
391 pScreen->u32LineSize = ppdev->lDeltaScreen > 0?ppdev->lDeltaScreen: -ppdev->lDeltaScreen;
392 pScreen->u32Width = ppdev->cxScreen;
393 pScreen->u32Height = ppdev->cyScreen;
394 pScreen->u16BitsPerPixel = (uint16_t)ppdev->ulBitCount;
395 pScreen->u16Flags = VBVA_SCREEN_F_ACTIVE;
396
397 vboxHGSMIBufferSubmit (ppdev, p);
398
399 HGSMIHeapFree (&ppdev->hgsmiDisplayHeap, p);
400 }
401 }
402
403 return;
404}
405
406#ifdef VBOX_WITH_VIDEOHWACCEL
407
408VBOXVHWACMD* vboxVHWACommandCreate (PPDEV ppdev, VBOXVHWACMD_TYPE enmCmd, VBOXVHWACMD_LENGTH cbCmd)
409{
410 VBOXVHWACMD* pHdr = (VBOXVHWACMD*)HGSMIHeapAlloc (&ppdev->hgsmiDisplayHeap,
411 cbCmd + VBOXVHWACMD_HEADSIZE(),
412 HGSMI_CH_VBVA,
413 VBVA_VHWA_CMD);
414 if (!pHdr)
415 {
416 DISPDBG((0, "VBoxDISP::vboxVHWACommandCreate: HGSMIHeapAlloc failed\n"));
417 }
418 else
419 {
420 memset(pHdr, 0, sizeof(VBOXVHWACMD));
421 pHdr->iDisplay = ppdev->iDevice;
422 pHdr->rc = VERR_GENERAL_FAILURE;
423 pHdr->enmCmd = enmCmd;
424 pHdr->cRefs = 1;
425 }
426
427 /* temporary hack */
428 vboxVHWACommandCheckHostCmds(ppdev);
429
430 return pHdr;
431}
432
433void vboxVHWACommandFree (PPDEV ppdev, VBOXVHWACMD* pCmd)
434{
435 HGSMIHeapFree (&ppdev->hgsmiDisplayHeap, pCmd);
436}
437
438static DECLCALLBACK(void) vboxVHWACommandCompletionCallbackEvent(PPDEV ppdev, VBOXVHWACMD * pCmd, void * pContext)
439{
440 VBOXPEVENT pEvent = (VBOXPEVENT)pContext;
441 LONG oldState = ppdev->VideoPortProcs.pfnSetEvent(ppdev->pVideoPortContext, pEvent);
442 Assert(!oldState);
443}
444
445static int vboxVHWAHanldeVHWACmdCompletion(PPDEV ppdev, VBVAHOSTCMD * pHostCmd)
446{
447 VBVAHOSTCMDVHWACMDCOMPLETE * pComplete = VBVAHOSTCMD_BODY(pHostCmd, VBVAHOSTCMDVHWACMDCOMPLETE);
448 VBOXVHWACMD* pComplCmd = (VBOXVHWACMD*)HGSMIOffsetToPointer (&ppdev->hgsmiDisplayHeap.area, pComplete->offCmd);
449 PFNVBOXVHWACMDCOMPLETION pfnCompletion = (PFNVBOXVHWACMDCOMPLETION)pComplCmd->GuestVBVAReserved1;
450 void * pContext = (void *)pComplCmd->GuestVBVAReserved2;
451
452 pfnCompletion(ppdev, pComplCmd, pContext);
453
454 vboxVBVAHostCommandComplete(ppdev, pHostCmd);
455
456 return 0;
457}
458
459static void vboxVBVAHostCommandHanlder(PPDEV ppdev, VBVAHOSTCMD * pCmd)
460{
461 int rc = VINF_SUCCESS;
462 switch(pCmd->customOpCode)
463 {
464# ifdef VBOX_WITH_VIDEOHWACCEL /** @todo why is this ifdef nested within itself? */
465 case VBVAHG_DCUSTOM_VHWA_CMDCOMPLETE:
466 {
467 vboxVHWAHanldeVHWACmdCompletion(ppdev, pCmd);
468 break;
469 }
470# endif
471 default:
472 {
473 Assert(0);
474 vboxVBVAHostCommandComplete(ppdev, pCmd);
475 }
476 }
477}
478
479void vboxVHWACommandCheckHostCmds(PPDEV ppdev)
480{
481 VBVAHOSTCMD * pCmd, * pNextCmd;
482 int rc = ppdev->pfnHGSMIRequestCommands(ppdev->hMpHGSMI, HGSMI_CH_VBVA, ppdev->iDevice, &pCmd);
483 /* don't assert here, otherwise NT4 will be unhappy */
484 if(RT_SUCCESS(rc))
485 {
486 for(;pCmd; pCmd = pNextCmd)
487 {
488 pNextCmd = pCmd->u.pNext;
489 vboxVBVAHostCommandHanlder(ppdev, pCmd);
490 }
491 }
492}
493
494void vboxVHWACommandSubmitAsynchByEvent (PPDEV ppdev, VBOXVHWACMD* pCmd, VBOXPEVENT pEvent)
495{
496// Assert(0);
497 pCmd->GuestVBVAReserved1 = (uintptr_t)pEvent;
498 pCmd->GuestVBVAReserved2 = 0;
499 /* ensure the command is not removed until we're processing it */
500 vbvaVHWACommandRetain(ppdev, pCmd);
501
502 /* complete it asynchronously by setting event */
503 pCmd->Flags |= VBOXVHWACMD_FLAG_GH_ASYNCH_EVENT;
504 vboxHGSMIBufferSubmit (ppdev, pCmd);
505
506 if(!(ASMAtomicReadU32((volatile uint32_t *)&pCmd->Flags) & VBOXVHWACMD_FLAG_HG_ASYNCH))
507 {
508 /* the command is completed */
509 ppdev->VideoPortProcs.pfnSetEvent(ppdev->pVideoPortContext, pEvent);
510 }
511
512 vbvaVHWACommandRelease(ppdev, pCmd);
513}
514
515BOOL vboxVHWACommandSubmit (PPDEV ppdev, VBOXVHWACMD* pCmd)
516{
517 VBOXPEVENT pEvent;
518 VBOXVP_STATUS rc = ppdev->VideoPortProcs.pfnCreateEvent(ppdev->pVideoPortContext, VBOXNOTIFICATION_EVENT, NULL, &pEvent);
519 /* don't assert here, otherwise NT4 will be unhappy */
520 if(rc == VBOXNO_ERROR)
521 {
522 pCmd->Flags |= VBOXVHWACMD_FLAG_GH_ASYNCH_IRQ;
523 vboxVHWACommandSubmitAsynchByEvent (ppdev, pCmd, pEvent);
524
525 rc = ppdev->VideoPortProcs.pfnWaitForSingleObject(ppdev->pVideoPortContext, pEvent,
526 NULL /*IN PLARGE_INTEGER pTimeOut*/
527 );
528 Assert(rc == VBOXNO_ERROR);
529 if(rc == VBOXNO_ERROR)
530 {
531 ppdev->VideoPortProcs.pfnDeleteEvent(ppdev->pVideoPortContext, pEvent);
532 }
533 }
534 return rc == VBOXNO_ERROR;
535}
536
537/* do not wait for completion */
538void vboxVHWACommandSubmitAsynch (PPDEV ppdev, VBOXVHWACMD* pCmd, PFNVBOXVHWACMDCOMPLETION pfnCompletion, void * pContext)
539{
540// Assert(0);
541 pCmd->GuestVBVAReserved1 = (uintptr_t)pfnCompletion;
542 pCmd->GuestVBVAReserved2 = (uintptr_t)pContext;
543 vbvaVHWACommandRetain(ppdev, pCmd);
544
545 vboxHGSMIBufferSubmit (ppdev, pCmd);
546
547 if(!(pCmd->Flags & VBOXVHWACMD_FLAG_HG_ASYNCH))
548 {
549 /* the command is completed */
550 pfnCompletion(ppdev, pCmd, pContext);
551 }
552
553 vbvaVHWACommandRelease(ppdev, pCmd);
554}
555
556static DECLCALLBACK(void) vboxVHWAFreeCmdCompletion(PPDEV ppdev, VBOXVHWACMD * pCmd, void * pContext)
557{
558 vbvaVHWACommandRelease(ppdev, pCmd);
559}
560
561void vboxVHWACommandSubmitAsynchAndComplete (PPDEV ppdev, VBOXVHWACMD* pCmd)
562{
563// Assert(0);
564 pCmd->GuestVBVAReserved1 = (uintptr_t)vboxVHWAFreeCmdCompletion;
565
566 vbvaVHWACommandRetain(ppdev, pCmd);
567
568 pCmd->Flags |= VBOXVHWACMD_FLAG_GH_ASYNCH_NOCOMPLETION;
569
570 vboxHGSMIBufferSubmit (ppdev, pCmd);
571
572 if(!(pCmd->Flags & VBOXVHWACMD_FLAG_HG_ASYNCH)
573 || pCmd->Flags & VBOXVHWACMD_FLAG_HG_ASYNCH_RETURNED)
574 {
575 /* the command is completed */
576 vboxVHWAFreeCmdCompletion(ppdev, pCmd, NULL);
577 }
578
579 vbvaVHWACommandRelease(ppdev, pCmd);
580}
581
582void vboxVHWAFreeHostInfo1(PPDEV ppdev, VBOXVHWACMD_QUERYINFO1* pInfo)
583{
584 VBOXVHWACMD* pCmd = VBOXVHWACMD_HEAD(pInfo);
585 vbvaVHWACommandRelease (ppdev, pCmd);
586}
587
588void vboxVHWAFreeHostInfo2(PPDEV ppdev, VBOXVHWACMD_QUERYINFO2* pInfo)
589{
590 VBOXVHWACMD* pCmd = VBOXVHWACMD_HEAD(pInfo);
591 vbvaVHWACommandRelease (ppdev, pCmd);
592}
593
594VBOXVHWACMD_QUERYINFO1* vboxVHWAQueryHostInfo1(PPDEV ppdev)
595{
596 VBOXVHWACMD* pCmd = vboxVHWACommandCreate (ppdev, VBOXVHWACMD_TYPE_QUERY_INFO1, sizeof(VBOXVHWACMD_QUERYINFO1));
597 VBOXVHWACMD_QUERYINFO1 *pInfo1;
598 if (!pCmd)
599 {
600 DISPDBG((0, "VBoxDISP::vboxVHWAQueryHostInfo1: vboxVHWACommandCreate failed\n"));
601 return NULL;
602 }
603
604 if (!pCmd)
605 {
606 DISPDBG((0, "VBoxDISP::vboxVHWAQueryHostInfo1: vboxVHWACommandCreate failed\n"));
607 return NULL;
608 }
609
610 pInfo1 = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_QUERYINFO1);
611 pInfo1->u.in.guestVersion.maj = VBOXVHWA_VERSION_MAJ;
612 pInfo1->u.in.guestVersion.min = VBOXVHWA_VERSION_MIN;
613 pInfo1->u.in.guestVersion.bld = VBOXVHWA_VERSION_BLD;
614 pInfo1->u.in.guestVersion.reserved = VBOXVHWA_VERSION_RSV;
615
616 if(vboxVHWACommandSubmit (ppdev, pCmd))
617 {
618 if(RT_SUCCESS(pCmd->rc))
619 {
620 return VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_QUERYINFO1);
621 }
622 }
623
624 vbvaVHWACommandRelease (ppdev, pCmd);
625 return NULL;
626}
627
628VBOXVHWACMD_QUERYINFO2* vboxVHWAQueryHostInfo2(PPDEV ppdev, uint32_t numFourCC)
629{
630 VBOXVHWACMD* pCmd = vboxVHWACommandCreate (ppdev, VBOXVHWACMD_TYPE_QUERY_INFO2, VBOXVHWAINFO2_SIZE(numFourCC));
631 VBOXVHWACMD_QUERYINFO2 *pInfo2;
632 if (!pCmd)
633 {
634 DISPDBG((0, "VBoxDISP::vboxVHWAQueryHostInfo2: vboxVHWACommandCreate failed\n"));
635 return NULL;
636 }
637
638 pInfo2 = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_QUERYINFO2);
639 pInfo2->numFourCC = numFourCC;
640
641 if(vboxVHWACommandSubmit (ppdev, pCmd))
642 {
643 if(RT_SUCCESS(pCmd->rc))
644 {
645 if(pInfo2->numFourCC == numFourCC)
646 {
647 return pInfo2;
648 }
649 }
650 }
651
652 vbvaVHWACommandRelease (ppdev, pCmd);
653 return NULL;
654}
655
656int vboxVHWAInitHostInfo1(PPDEV ppdev)
657{
658 VBOXVHWACMD_QUERYINFO1* pInfo;
659
660 if (!ppdev->bHGSMISupported)
661 return VERR_NOT_SUPPORTED;
662
663 pInfo = vboxVHWAQueryHostInfo1(ppdev);
664 if(!pInfo)
665 {
666 ppdev->vhwaInfo.bVHWAEnabled = false;
667 return VERR_OUT_OF_RESOURCES;
668 }
669
670 ppdev->vhwaInfo.caps = pInfo->u.out.caps;
671 ppdev->vhwaInfo.caps2 = pInfo->u.out.caps2;
672 ppdev->vhwaInfo.colorKeyCaps = pInfo->u.out.colorKeyCaps;
673 ppdev->vhwaInfo.stretchCaps = pInfo->u.out.stretchCaps;
674 ppdev->vhwaInfo.surfaceCaps = pInfo->u.out.surfaceCaps;
675 ppdev->vhwaInfo.numOverlays = pInfo->u.out.numOverlays;
676 ppdev->vhwaInfo.numFourCC = pInfo->u.out.numFourCC;
677 ppdev->vhwaInfo.bVHWAEnabled = (pInfo->u.out.cfgFlags & VBOXVHWA_CFG_ENABLED);
678 vboxVHWAFreeHostInfo1(ppdev, pInfo);
679 return VINF_SUCCESS;
680}
681
682int vboxVHWAInitHostInfo2(PPDEV ppdev, DWORD *pFourCC)
683{
684 VBOXVHWACMD_QUERYINFO2* pInfo;
685 int rc = VINF_SUCCESS;
686
687 if (!ppdev->bHGSMISupported)
688 return VERR_NOT_SUPPORTED;
689
690 pInfo = vboxVHWAQueryHostInfo2(ppdev, ppdev->vhwaInfo.numFourCC);
691
692 Assert(pInfo);
693 if(!pInfo)
694 return VERR_OUT_OF_RESOURCES;
695
696 if(ppdev->vhwaInfo.numFourCC)
697 {
698 memcpy(pFourCC, pInfo->FourCC, ppdev->vhwaInfo.numFourCC * sizeof(pFourCC[0]));
699 }
700 else
701 {
702 Assert(0);
703 rc = VERR_GENERAL_FAILURE;
704 }
705
706 vboxVHWAFreeHostInfo2(ppdev, pInfo);
707
708 return rc;
709}
710
711int vboxVHWAEnable(PPDEV ppdev)
712{
713 int rc = VERR_GENERAL_FAILURE;
714 VBOXVHWACMD* pCmd;
715
716 if (!ppdev->bHGSMISupported)
717 return VERR_NOT_SUPPORTED;
718
719 pCmd = vboxVHWACommandCreate (ppdev, VBOXVHWACMD_TYPE_ENABLE, 0);
720 if (!pCmd)
721 {
722 DISPDBG((0, "VBoxDISP::vboxVHWAEnable: vboxVHWACommandCreate failed\n"));
723 return rc;
724 }
725
726 if(vboxVHWACommandSubmit (ppdev, pCmd))
727 {
728 if(RT_SUCCESS(pCmd->rc))
729 {
730 rc = VINF_SUCCESS;
731 }
732 }
733
734 vbvaVHWACommandRelease (ppdev, pCmd);
735 return rc;
736}
737
738int vboxVHWADisable(PPDEV ppdev)
739{
740 int rc = VERR_GENERAL_FAILURE;
741 VBOXVHWACMD* pCmd;
742
743 if (!ppdev->bHGSMISupported)
744 return VERR_NOT_SUPPORTED;
745
746 pCmd = vboxVHWACommandCreate (ppdev, VBOXVHWACMD_TYPE_DISABLE, 0);
747 if (!pCmd)
748 {
749 DISPDBG((0, "VBoxDISP::vboxVHWADisable: vboxVHWACommandCreate failed\n"));
750 return rc;
751 }
752
753 if(vboxVHWACommandSubmit (ppdev, pCmd))
754 {
755 if(RT_SUCCESS(pCmd->rc))
756 {
757 rc = VINF_SUCCESS;
758 }
759 }
760
761 vbvaVHWACommandRelease (ppdev, pCmd);
762
763 vboxVHWACommandCheckHostCmds(ppdev);
764
765 return rc;
766}
767
768void vboxVHWAInit(PPDEV ppdev)
769{
770 VHWAQUERYINFO info;
771 DWORD returnedDataLength;
772 DWORD err;
773
774 memset(&info, 0, sizeof (info));
775
776 err = EngDeviceIoControl(ppdev->hDriver,
777 IOCTL_VIDEO_VHWA_QUERY_INFO,
778 NULL,
779 0,
780 &info,
781 sizeof(info),
782 &returnedDataLength);
783 Assert(!err);
784 if(!err)
785 {
786 ppdev->vhwaInfo.offVramBase = info.offVramBase;
787 ppdev->vhwaInfo.bVHWAInited = TRUE;
788 }
789 else
790 ppdev->vhwaInfo.bVHWAInited = FALSE;
791}
792
793#endif
794
795void vboxVBVAHostCommandComplete(PPDEV ppdev, VBVAHOSTCMD * pCmd)
796{
797 ppdev->pfnHGSMICommandComplete(ppdev->hMpHGSMI, pCmd);
798}
799
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