VirtualBox

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

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

Additions/WINNT/Graphics and Additions/common/VBoxVideo: move the base VBVA support functions into the common driver code

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.0 KB
Line 
1/* $Id: vbox.c 34440 2010-11-28 22:12:07Z vboxsync $ */
2/** @file
3 * Display - VirtualBox Win 2000/XP guest display driver, support functions.
4 */
5
6/*
7 * Copyright (C) 2006-2010 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 <VBox/log.h>
24#include <iprt/asm.h>
25#include <iprt/asm-amd64-x86.h>
26#include <iprt/assert.h>
27
28void VBoxProcessDisplayInfo (PPDEV ppdev)
29{
30 if (ppdev->bHGSMISupported)
31 {
32 VBoxHGSMIProcessDisplayInfo(&ppdev->guestCtx, ppdev->iDevice,
33 ppdev->ptlDevOrg.x, ppdev->ptlDevOrg.y, 0,
34 ppdev->lDeltaScreen > 0
35 ? ppdev->lDeltaScreen
36 : -ppdev->lDeltaScreen, ppdev->cxScreen,
37 ppdev->cyScreen,
38 (uint16_t)ppdev->ulBitCount);
39 }
40
41 return;
42}
43
44#ifdef VBOX_WITH_VIDEOHWACCEL
45
46VBOXVHWACMD* vboxVHWACommandCreate (PPDEV ppdev, VBOXVHWACMD_TYPE enmCmd, VBOXVHWACMD_LENGTH cbCmd)
47{
48 VBOXVHWACMD* pHdr = (VBOXVHWACMD*)VBoxHGSMIBufferAlloc(&ppdev->guestCtx,
49 cbCmd + VBOXVHWACMD_HEADSIZE(),
50 HGSMI_CH_VBVA,
51 VBVA_VHWA_CMD);
52 if (!pHdr)
53 {
54 LogFunc(("HGSMIHeapAlloc failed\n"));
55 }
56 else
57 {
58 memset(pHdr, 0, sizeof(VBOXVHWACMD));
59 pHdr->iDisplay = ppdev->iDevice;
60 pHdr->rc = VERR_GENERAL_FAILURE;
61 pHdr->enmCmd = enmCmd;
62 pHdr->cRefs = 1;
63 }
64
65 /* temporary hack */
66 vboxVHWACommandCheckHostCmds(ppdev);
67
68 return pHdr;
69}
70
71void vboxVHWACommandFree (PPDEV ppdev, VBOXVHWACMD* pCmd)
72{
73 VBoxHGSMIBufferFree(&ppdev->guestCtx, pCmd);
74}
75
76static DECLCALLBACK(void) vboxVHWACommandCompletionCallbackEvent(PPDEV ppdev, VBOXVHWACMD * pCmd, void * pContext)
77{
78 VBOXPEVENT pEvent = (VBOXPEVENT)pContext;
79 LONG oldState = ppdev->VideoPortProcs.pfnSetEvent(ppdev->pVideoPortContext, pEvent);
80 Assert(!oldState);
81}
82
83static int vboxVHWAHanldeVHWACmdCompletion(PPDEV ppdev, VBVAHOSTCMD * pHostCmd)
84{
85 VBVAHOSTCMDVHWACMDCOMPLETE * pComplete = VBVAHOSTCMD_BODY(pHostCmd, VBVAHOSTCMDVHWACMDCOMPLETE);
86 VBOXVHWACMD* pComplCmd = (VBOXVHWACMD*)HGSMIOffsetToPointer (&ppdev->guestCtx.heapCtx.area, pComplete->offCmd);
87 PFNVBOXVHWACMDCOMPLETION pfnCompletion = (PFNVBOXVHWACMDCOMPLETION)pComplCmd->GuestVBVAReserved1;
88 void * pContext = (void *)pComplCmd->GuestVBVAReserved2;
89
90 pfnCompletion(ppdev, pComplCmd, pContext);
91
92 vboxVBVAHostCommandComplete(ppdev, pHostCmd);
93
94 return 0;
95}
96
97static void vboxVBVAHostCommandHanlder(PPDEV ppdev, VBVAHOSTCMD * pCmd)
98{
99 int rc = VINF_SUCCESS;
100 switch(pCmd->customOpCode)
101 {
102# ifdef VBOX_WITH_VIDEOHWACCEL /** @todo why is this ifdef nested within itself? */
103 case VBVAHG_DCUSTOM_VHWA_CMDCOMPLETE:
104 {
105 vboxVHWAHanldeVHWACmdCompletion(ppdev, pCmd);
106 break;
107 }
108# endif
109 default:
110 {
111 Assert(0);
112 vboxVBVAHostCommandComplete(ppdev, pCmd);
113 }
114 }
115}
116
117void vboxVHWACommandCheckHostCmds(PPDEV ppdev)
118{
119 VBVAHOSTCMD * pCmd, * pNextCmd;
120 int rc = ppdev->pfnHGSMIRequestCommands(ppdev->hMpHGSMI, HGSMI_CH_VBVA, ppdev->iDevice, &pCmd);
121 /* don't assert here, otherwise NT4 will be unhappy */
122 if(RT_SUCCESS(rc))
123 {
124 for(;pCmd; pCmd = pNextCmd)
125 {
126 pNextCmd = pCmd->u.pNext;
127 vboxVBVAHostCommandHanlder(ppdev, pCmd);
128 }
129 }
130}
131
132void vboxVHWACommandSubmitAsynchByEvent (PPDEV ppdev, VBOXVHWACMD* pCmd, VBOXPEVENT pEvent)
133{
134// Assert(0);
135 pCmd->GuestVBVAReserved1 = (uintptr_t)pEvent;
136 pCmd->GuestVBVAReserved2 = 0;
137 /* ensure the command is not removed until we're processing it */
138 vbvaVHWACommandRetain(ppdev, pCmd);
139
140 /* complete it asynchronously by setting event */
141 pCmd->Flags |= VBOXVHWACMD_FLAG_GH_ASYNCH_EVENT;
142 VBoxHGSMIBufferSubmit(&ppdev->guestCtx, pCmd);
143
144 if(!(ASMAtomicReadU32((volatile uint32_t *)&pCmd->Flags) & VBOXVHWACMD_FLAG_HG_ASYNCH))
145 {
146 /* the command is completed */
147 ppdev->VideoPortProcs.pfnSetEvent(ppdev->pVideoPortContext, pEvent);
148 }
149
150 vbvaVHWACommandRelease(ppdev, pCmd);
151}
152
153BOOL vboxVHWACommandSubmit (PPDEV ppdev, VBOXVHWACMD* pCmd)
154{
155 VBOXPEVENT pEvent;
156 VBOXVP_STATUS rc = ppdev->VideoPortProcs.pfnCreateEvent(ppdev->pVideoPortContext, VBOXNOTIFICATION_EVENT, NULL, &pEvent);
157 /* don't assert here, otherwise NT4 will be unhappy */
158 if(rc == VBOXNO_ERROR)
159 {
160 pCmd->Flags |= VBOXVHWACMD_FLAG_GH_ASYNCH_IRQ;
161 vboxVHWACommandSubmitAsynchByEvent (ppdev, pCmd, pEvent);
162
163 rc = ppdev->VideoPortProcs.pfnWaitForSingleObject(ppdev->pVideoPortContext, pEvent,
164 NULL /*IN PLARGE_INTEGER pTimeOut*/
165 );
166 Assert(rc == VBOXNO_ERROR);
167 if(rc == VBOXNO_ERROR)
168 {
169 ppdev->VideoPortProcs.pfnDeleteEvent(ppdev->pVideoPortContext, pEvent);
170 }
171 }
172 return rc == VBOXNO_ERROR;
173}
174
175/* do not wait for completion */
176void vboxVHWACommandSubmitAsynch (PPDEV ppdev, VBOXVHWACMD* pCmd, PFNVBOXVHWACMDCOMPLETION pfnCompletion, void * pContext)
177{
178// Assert(0);
179 pCmd->GuestVBVAReserved1 = (uintptr_t)pfnCompletion;
180 pCmd->GuestVBVAReserved2 = (uintptr_t)pContext;
181 vbvaVHWACommandRetain(ppdev, pCmd);
182
183 VBoxHGSMIBufferSubmit(&ppdev->guestCtx, pCmd);
184
185 if(!(pCmd->Flags & VBOXVHWACMD_FLAG_HG_ASYNCH))
186 {
187 /* the command is completed */
188 pfnCompletion(ppdev, pCmd, pContext);
189 }
190
191 vbvaVHWACommandRelease(ppdev, pCmd);
192}
193
194static DECLCALLBACK(void) vboxVHWAFreeCmdCompletion(PPDEV ppdev, VBOXVHWACMD * pCmd, void * pContext)
195{
196 vbvaVHWACommandRelease(ppdev, pCmd);
197}
198
199void vboxVHWACommandSubmitAsynchAndComplete (PPDEV ppdev, VBOXVHWACMD* pCmd)
200{
201// Assert(0);
202 pCmd->GuestVBVAReserved1 = (uintptr_t)vboxVHWAFreeCmdCompletion;
203
204 vbvaVHWACommandRetain(ppdev, pCmd);
205
206 pCmd->Flags |= VBOXVHWACMD_FLAG_GH_ASYNCH_NOCOMPLETION;
207
208 VBoxHGSMIBufferSubmit(&ppdev->guestCtx, pCmd);
209
210 if(!(pCmd->Flags & VBOXVHWACMD_FLAG_HG_ASYNCH)
211 || pCmd->Flags & VBOXVHWACMD_FLAG_HG_ASYNCH_RETURNED)
212 {
213 /* the command is completed */
214 vboxVHWAFreeCmdCompletion(ppdev, pCmd, NULL);
215 }
216
217 vbvaVHWACommandRelease(ppdev, pCmd);
218}
219
220void vboxVHWAFreeHostInfo1(PPDEV ppdev, VBOXVHWACMD_QUERYINFO1* pInfo)
221{
222 VBOXVHWACMD* pCmd = VBOXVHWACMD_HEAD(pInfo);
223 vbvaVHWACommandRelease (ppdev, pCmd);
224}
225
226void vboxVHWAFreeHostInfo2(PPDEV ppdev, VBOXVHWACMD_QUERYINFO2* pInfo)
227{
228 VBOXVHWACMD* pCmd = VBOXVHWACMD_HEAD(pInfo);
229 vbvaVHWACommandRelease (ppdev, pCmd);
230}
231
232VBOXVHWACMD_QUERYINFO1* vboxVHWAQueryHostInfo1(PPDEV ppdev)
233{
234 VBOXVHWACMD* pCmd = vboxVHWACommandCreate (ppdev, VBOXVHWACMD_TYPE_QUERY_INFO1, sizeof(VBOXVHWACMD_QUERYINFO1));
235 VBOXVHWACMD_QUERYINFO1 *pInfo1;
236 if (!pCmd)
237 {
238 DISPDBG((0, "VBoxDISP::vboxVHWAQueryHostInfo1: vboxVHWACommandCreate failed\n"));
239 return NULL;
240 }
241
242 if (!pCmd)
243 {
244 DISPDBG((0, "VBoxDISP::vboxVHWAQueryHostInfo1: vboxVHWACommandCreate failed\n"));
245 return NULL;
246 }
247
248 pInfo1 = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_QUERYINFO1);
249 pInfo1->u.in.guestVersion.maj = VBOXVHWA_VERSION_MAJ;
250 pInfo1->u.in.guestVersion.min = VBOXVHWA_VERSION_MIN;
251 pInfo1->u.in.guestVersion.bld = VBOXVHWA_VERSION_BLD;
252 pInfo1->u.in.guestVersion.reserved = VBOXVHWA_VERSION_RSV;
253
254 if(vboxVHWACommandSubmit (ppdev, pCmd))
255 {
256 if(RT_SUCCESS(pCmd->rc))
257 {
258 return VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_QUERYINFO1);
259 }
260 }
261
262 vbvaVHWACommandRelease (ppdev, pCmd);
263 return NULL;
264}
265
266VBOXVHWACMD_QUERYINFO2* vboxVHWAQueryHostInfo2(PPDEV ppdev, uint32_t numFourCC)
267{
268 VBOXVHWACMD* pCmd = vboxVHWACommandCreate (ppdev, VBOXVHWACMD_TYPE_QUERY_INFO2, VBOXVHWAINFO2_SIZE(numFourCC));
269 VBOXVHWACMD_QUERYINFO2 *pInfo2;
270 if (!pCmd)
271 {
272 DISPDBG((0, "VBoxDISP::vboxVHWAQueryHostInfo2: vboxVHWACommandCreate failed\n"));
273 return NULL;
274 }
275
276 pInfo2 = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_QUERYINFO2);
277 pInfo2->numFourCC = numFourCC;
278
279 if(vboxVHWACommandSubmit (ppdev, pCmd))
280 {
281 if(RT_SUCCESS(pCmd->rc))
282 {
283 if(pInfo2->numFourCC == numFourCC)
284 {
285 return pInfo2;
286 }
287 }
288 }
289
290 vbvaVHWACommandRelease (ppdev, pCmd);
291 return NULL;
292}
293
294int vboxVHWAInitHostInfo1(PPDEV ppdev)
295{
296 VBOXVHWACMD_QUERYINFO1* pInfo;
297
298 if (!ppdev->bHGSMISupported)
299 return VERR_NOT_SUPPORTED;
300
301 pInfo = vboxVHWAQueryHostInfo1(ppdev);
302 if(!pInfo)
303 {
304 ppdev->vhwaInfo.bVHWAEnabled = false;
305 return VERR_OUT_OF_RESOURCES;
306 }
307
308 ppdev->vhwaInfo.caps = pInfo->u.out.caps;
309 ppdev->vhwaInfo.caps2 = pInfo->u.out.caps2;
310 ppdev->vhwaInfo.colorKeyCaps = pInfo->u.out.colorKeyCaps;
311 ppdev->vhwaInfo.stretchCaps = pInfo->u.out.stretchCaps;
312 ppdev->vhwaInfo.surfaceCaps = pInfo->u.out.surfaceCaps;
313 ppdev->vhwaInfo.numOverlays = pInfo->u.out.numOverlays;
314 ppdev->vhwaInfo.numFourCC = pInfo->u.out.numFourCC;
315 ppdev->vhwaInfo.bVHWAEnabled = (pInfo->u.out.cfgFlags & VBOXVHWA_CFG_ENABLED);
316 vboxVHWAFreeHostInfo1(ppdev, pInfo);
317 return VINF_SUCCESS;
318}
319
320int vboxVHWAInitHostInfo2(PPDEV ppdev, DWORD *pFourCC)
321{
322 VBOXVHWACMD_QUERYINFO2* pInfo;
323 int rc = VINF_SUCCESS;
324
325 if (!ppdev->bHGSMISupported)
326 return VERR_NOT_SUPPORTED;
327
328 pInfo = vboxVHWAQueryHostInfo2(ppdev, ppdev->vhwaInfo.numFourCC);
329
330 Assert(pInfo);
331 if(!pInfo)
332 return VERR_OUT_OF_RESOURCES;
333
334 if(ppdev->vhwaInfo.numFourCC)
335 {
336 memcpy(pFourCC, pInfo->FourCC, ppdev->vhwaInfo.numFourCC * sizeof(pFourCC[0]));
337 }
338 else
339 {
340 Assert(0);
341 rc = VERR_GENERAL_FAILURE;
342 }
343
344 vboxVHWAFreeHostInfo2(ppdev, pInfo);
345
346 return rc;
347}
348
349int vboxVHWAEnable(PPDEV ppdev)
350{
351 int rc = VERR_GENERAL_FAILURE;
352 VBOXVHWACMD* pCmd;
353
354 if (!ppdev->bHGSMISupported)
355 return VERR_NOT_SUPPORTED;
356
357 pCmd = vboxVHWACommandCreate (ppdev, VBOXVHWACMD_TYPE_ENABLE, 0);
358 if (!pCmd)
359 {
360 DISPDBG((0, "VBoxDISP::vboxVHWAEnable: vboxVHWACommandCreate failed\n"));
361 return rc;
362 }
363
364 if(vboxVHWACommandSubmit (ppdev, pCmd))
365 {
366 if(RT_SUCCESS(pCmd->rc))
367 {
368 rc = VINF_SUCCESS;
369 }
370 }
371
372 vbvaVHWACommandRelease (ppdev, pCmd);
373 return rc;
374}
375
376int vboxVHWADisable(PPDEV ppdev)
377{
378 int rc = VERR_GENERAL_FAILURE;
379 VBOXVHWACMD* pCmd;
380
381 if (!ppdev->bHGSMISupported)
382 return VERR_NOT_SUPPORTED;
383
384 pCmd = vboxVHWACommandCreate (ppdev, VBOXVHWACMD_TYPE_DISABLE, 0);
385 if (!pCmd)
386 {
387 DISPDBG((0, "VBoxDISP::vboxVHWADisable: vboxVHWACommandCreate failed\n"));
388 return rc;
389 }
390
391 if(vboxVHWACommandSubmit (ppdev, pCmd))
392 {
393 if(RT_SUCCESS(pCmd->rc))
394 {
395 rc = VINF_SUCCESS;
396 }
397 }
398
399 vbvaVHWACommandRelease (ppdev, pCmd);
400
401 vboxVHWACommandCheckHostCmds(ppdev);
402
403 return rc;
404}
405
406void vboxVHWAInit(PPDEV ppdev)
407{
408 VHWAQUERYINFO info;
409 DWORD returnedDataLength;
410 DWORD err;
411
412 memset(&info, 0, sizeof (info));
413
414 err = EngDeviceIoControl(ppdev->hDriver,
415 IOCTL_VIDEO_VHWA_QUERY_INFO,
416 NULL,
417 0,
418 &info,
419 sizeof(info),
420 &returnedDataLength);
421 Assert(!err);
422 if(!err)
423 {
424 ppdev->vhwaInfo.offVramBase = info.offVramBase;
425 ppdev->vhwaInfo.bVHWAInited = TRUE;
426 }
427 else
428 ppdev->vhwaInfo.bVHWAInited = FALSE;
429}
430
431#endif
432
433void vboxVBVAHostCommandComplete(PPDEV ppdev, VBVAHOSTCMD * pCmd)
434{
435 ppdev->pfnHGSMICommandComplete(ppdev->hMpHGSMI, pCmd);
436}
437
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