VirtualBox

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

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

Additions/VBoxVideo: support disabling the screen via VBVA_SCREEN_F_DISABLE

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