VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/Graphics/Miniport/wddm/VBoxVideoVhwa.cpp@ 29745

Last change on this file since 29745 was 29745, checked in by vboxsync, 15 years ago

wddm/2D: handle number of overlays properly

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.5 KB
Line 
1/*
2 * Copyright (C) 2010 Oracle Corporation
3 *
4 * This file is part of VirtualBox Open Source Edition (OSE), as
5 * available from http://www.virtualbox.org. This file is free software;
6 * you can redistribute it and/or modify it under the terms of the GNU
7 * General Public License (GPL) as published by the Free Software
8 * Foundation, in version 2 as it comes in the "COPYING" file of the
9 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
10 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
11 */
12#include "../VBoxVideo.h"
13#include "../Helper.h"
14
15#ifndef VBOXVHWA_WITH_SHGSMI
16# include <iprt/semaphore.h>
17# include <iprt/asm.h>
18#endif
19
20
21
22DECLINLINE(void) vboxVhwaHdrInit(VBOXVHWACMD* pHdr, D3DDDI_VIDEO_PRESENT_SOURCE_ID srcId, VBOXVHWACMD_TYPE enmCmd)
23{
24 memset(pHdr, 0, sizeof(VBOXVHWACMD));
25 pHdr->iDisplay = srcId;
26 pHdr->rc = VERR_GENERAL_FAILURE;
27 pHdr->enmCmd = enmCmd;
28#ifndef VBOXVHWA_WITH_SHGSMI
29 pHdr->cRefs = 1;
30#endif
31}
32
33#ifdef VBOXVHWA_WITH_SHGSMI
34static int vboxVhwaCommandSubmitHgsmi(struct _DEVICE_EXTENSION* pDevExt, HGSMIOFFSET offDr)
35{
36 VBoxHGSMIGuestWrite(pDevExt, offDr);
37 return VINF_SUCCESS;
38}
39#else
40DECLINLINE(void) vbvaVhwaCommandRelease(PDEVICE_EXTENSION pDevExt, VBOXVHWACMD* pCmd)
41{
42 uint32_t cRefs = ASMAtomicDecU32(&pCmd->cRefs);
43 Assert(cRefs < UINT32_MAX / 2);
44 if(!cRefs)
45 {
46 vboxHGSMIBufferFree(pDevExt, pCmd);
47 }
48}
49
50DECLINLINE(void) vbvaVhwaCommandRetain(PDEVICE_EXTENSION pDevExt, VBOXVHWACMD* pCmd)
51{
52 ASMAtomicIncU32(&pCmd->cRefs);
53}
54
55/* do not wait for completion */
56void vboxVhwaCommandSubmitAsynch(PDEVICE_EXTENSION pDevExt, VBOXVHWACMD* pCmd, PFNVBOXVHWACMDCOMPLETION pfnCompletion, void * pContext)
57{
58 pCmd->GuestVBVAReserved1 = (uintptr_t)pfnCompletion;
59 pCmd->GuestVBVAReserved2 = (uintptr_t)pContext;
60 vbvaVhwaCommandRetain(pDevExt, pCmd);
61
62 vboxHGSMIBufferSubmit(pDevExt, pCmd);
63
64 if(!(pCmd->Flags & VBOXVHWACMD_FLAG_HG_ASYNCH)
65 || ((pCmd->Flags & VBOXVHWACMD_FLAG_GH_ASYNCH_NOCOMPLETION)
66 && (pCmd->Flags & VBOXVHWACMD_FLAG_HG_ASYNCH_RETURNED)))
67 {
68 /* the command is completed */
69 pfnCompletion(pDevExt, pCmd, pContext);
70 }
71
72 vbvaVhwaCommandRelease(pDevExt, pCmd);
73}
74
75static DECLCALLBACK(void) vboxVhwaCompletionSetEvent(PDEVICE_EXTENSION pDevExt, VBOXVHWACMD * pCmd, void * pvContext)
76{
77 RTSemEventSignal((RTSEMEVENT)pvContext);
78}
79
80void vboxVhwaCommandSubmitAsynchByEvent(PDEVICE_EXTENSION pDevExt, VBOXVHWACMD* pCmd, RTSEMEVENT hEvent)
81{
82 vboxVhwaCommandSubmitAsynch(pDevExt, pCmd, vboxVhwaCompletionSetEvent, hEvent);
83}
84#endif
85
86VBOXVHWACMD* vboxVhwaCommandCreate(PDEVICE_EXTENSION pDevExt, D3DDDI_VIDEO_PRESENT_SOURCE_ID srcId, VBOXVHWACMD_TYPE enmCmd, VBOXVHWACMD_LENGTH cbCmd)
87{
88#ifdef VBOXVHWA_WITH_SHGSMI
89 VBOXVHWACMD* pHdr = (VBOXVHWACMD*)VBoxSHGSMICommandAlloc(&pDevExt->u.primary.hgsmiAdapterHeap,
90 cbCmd + VBOXVHWACMD_HEADSIZE(),
91 HGSMI_CH_VBVA,
92 VBVA_VHWA_CMD);
93#else
94 VBOXVHWACMD* pHdr = (VBOXVHWACMD*)vboxHGSMIBufferAlloc(pDevExt,
95 cbCmd + VBOXVHWACMD_HEADSIZE(),
96 HGSMI_CH_VBVA,
97 VBVA_VHWA_CMD);
98#endif
99 Assert(pHdr);
100 if (!pHdr)
101 {
102 drprintf((__FUNCTION__": vboxHGSMIBufferAlloc failed\n"));
103 }
104 else
105 {
106 vboxVhwaHdrInit(pHdr, srcId, enmCmd);
107 }
108
109 return pHdr;
110}
111
112void vboxVhwaCommandFree(PDEVICE_EXTENSION pDevExt, VBOXVHWACMD* pCmd)
113{
114#ifdef VBOXVHWA_WITH_SHGSMI
115 VBoxSHGSMICommandFree(&pDevExt->u.primary.hgsmiAdapterHeap, pCmd);
116#else
117 vbvaVhwaCommandRelease(pDevExt, pCmd);
118#endif
119}
120
121int vboxVhwaCommandSubmit(PDEVICE_EXTENSION pDevExt, VBOXVHWACMD* pCmd)
122{
123#ifdef VBOXVHWA_WITH_SHGSMI
124 const VBOXSHGSMIHEADER* pHdr = VBoxSHGSMICommandPrepSynch(&pDevExt->u.primary.hgsmiAdapterHeap, pCmd);
125 Assert(pHdr);
126 int rc = VERR_GENERAL_FAILURE;
127 if (pHdr)
128 {
129 do
130 {
131 HGSMIOFFSET offCmd = VBoxSHGSMICommandOffset(&pDevExt->u.primary.hgsmiAdapterHeap, pHdr);
132 Assert(offCmd != HGSMIOFFSET_VOID);
133 if (offCmd != HGSMIOFFSET_VOID)
134 {
135 rc = vboxVhwaCommandSubmitHgsmi(pDevExt, offCmd);
136 AssertRC(rc);
137 if (RT_SUCCESS(rc))
138 {
139 VBoxSHGSMICommandDoneSynch(&pDevExt->u.primary.hgsmiAdapterHeap, pHdr);
140 AssertRC(rc);
141 break;
142 }
143 }
144 else
145 rc = VERR_INVALID_PARAMETER;
146 /* fail to submit, cancel it */
147 VBoxSHGSMICommandCancelSynch(&pDevExt->u.primary.hgsmiAdapterHeap, pHdr);
148 } while (0);
149 }
150 else
151 rc = VERR_INVALID_PARAMETER;
152 return rc;
153#else
154 RTSEMEVENT hEvent;
155 int rc = RTSemEventCreate(&hEvent);
156 AssertRC(rc);
157 if (RT_SUCCESS(rc))
158 {
159 pCmd->Flags |= VBOXVHWACMD_FLAG_GH_ASYNCH_IRQ;
160 vboxVhwaCommandSubmitAsynchByEvent(pDevExt, pCmd, hEvent);
161 rc = RTSemEventWait(hEvent, RT_INDEFINITE_WAIT);
162 AssertRC(rc);
163 if (RT_SUCCESS(rc))
164 RTSemEventDestroy(hEvent);
165 }
166 return rc;
167#endif
168}
169
170#ifndef VBOXVHWA_WITH_SHGSMI
171static DECLCALLBACK(void) vboxVhwaCompletionFreeCmd(PDEVICE_EXTENSION pDevExt, VBOXVHWACMD * pCmd, void * pContext)
172{
173 vboxVhwaCommandFree(pDevExt, pCmd);
174}
175
176void vboxVhwaCompletionListProcess(PDEVICE_EXTENSION pDevExt, VBOXSHGSMILIST *pList)
177{
178 PVBOXSHGSMILIST_ENTRY pNext, pCur;
179 for (pCur = pList->pFirst; pCur; pCur = pNext)
180 {
181 /* need to save next since the command may be released in a pfnCallback and thus its data might be invalid */
182 pNext = pCur->pNext;
183 VBOXVHWACMD *pCmd = VBOXVHWA_LISTENTRY2CMD(pCur);
184 PFNVBOXVHWACMDCOMPLETION pfnCallback = (PFNVBOXVHWACMDCOMPLETION)pCmd->GuestVBVAReserved1;
185 void *pvCallback = (void*)pCmd->GuestVBVAReserved2;
186 pfnCallback(pDevExt, pCmd, pvCallback);
187 }
188}
189
190#endif
191
192void vboxVhwaCommandSubmitAsynchAndComplete(PDEVICE_EXTENSION pDevExt, VBOXVHWACMD* pCmd)
193{
194#ifdef VBOXVHWA_WITH_SHGSMI
195# error "port me"
196#else
197 pCmd->Flags |= VBOXVHWACMD_FLAG_GH_ASYNCH_NOCOMPLETION;
198
199 vboxVhwaCommandSubmitAsynch(pDevExt, pCmd, vboxVhwaCompletionFreeCmd, NULL);
200#endif
201}
202
203void vboxVHWAFreeHostInfo1(PDEVICE_EXTENSION pDevExt, VBOXVHWACMD_QUERYINFO1* pInfo)
204{
205 VBOXVHWACMD* pCmd = VBOXVHWACMD_HEAD(pInfo);
206 vboxVhwaCommandFree(pDevExt, pCmd);
207}
208
209void vboxVHWAFreeHostInfo2(PDEVICE_EXTENSION pDevExt, VBOXVHWACMD_QUERYINFO2* pInfo)
210{
211 VBOXVHWACMD* pCmd = VBOXVHWACMD_HEAD(pInfo);
212 vboxVhwaCommandFree(pDevExt, pCmd);
213}
214
215VBOXVHWACMD_QUERYINFO1* vboxVHWAQueryHostInfo1(PDEVICE_EXTENSION pDevExt, D3DDDI_VIDEO_PRESENT_SOURCE_ID srcId)
216{
217 VBOXVHWACMD* pCmd = vboxVhwaCommandCreate(pDevExt, srcId, VBOXVHWACMD_TYPE_QUERY_INFO1, sizeof(VBOXVHWACMD_QUERYINFO1));
218 VBOXVHWACMD_QUERYINFO1 *pInfo1;
219
220 Assert(pCmd);
221 if (!pCmd)
222 {
223 drprintf((0, "VBoxDISP::vboxVHWAQueryHostInfo1: vboxVHWACommandCreate failed\n"));
224 return NULL;
225 }
226
227 pInfo1 = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_QUERYINFO1);
228 pInfo1->u.in.guestVersion.maj = VBOXVHWA_VERSION_MAJ;
229 pInfo1->u.in.guestVersion.min = VBOXVHWA_VERSION_MIN;
230 pInfo1->u.in.guestVersion.bld = VBOXVHWA_VERSION_BLD;
231 pInfo1->u.in.guestVersion.reserved = VBOXVHWA_VERSION_RSV;
232
233 int rc = vboxVhwaCommandSubmit(pDevExt, pCmd);
234 AssertRC(rc);
235 if(RT_SUCCESS(rc))
236 {
237 if(RT_SUCCESS(pCmd->rc))
238 {
239 return VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_QUERYINFO1);
240 }
241 }
242
243 vboxVhwaCommandFree(pDevExt, pCmd);
244 return NULL;
245}
246
247VBOXVHWACMD_QUERYINFO2* vboxVHWAQueryHostInfo2(PDEVICE_EXTENSION pDevExt, D3DDDI_VIDEO_PRESENT_SOURCE_ID srcId, uint32_t numFourCC)
248{
249 VBOXVHWACMD* pCmd = vboxVhwaCommandCreate(pDevExt, srcId, VBOXVHWACMD_TYPE_QUERY_INFO2, VBOXVHWAINFO2_SIZE(numFourCC));
250 VBOXVHWACMD_QUERYINFO2 *pInfo2;
251 Assert(pCmd);
252 if (!pCmd)
253 {
254 drprintf((0, "VBoxDISP::vboxVHWAQueryHostInfo2: vboxVHWACommandCreate failed\n"));
255 return NULL;
256 }
257
258 pInfo2 = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_QUERYINFO2);
259 pInfo2->numFourCC = numFourCC;
260
261 int rc = vboxVhwaCommandSubmit(pDevExt, pCmd);
262 AssertRC(rc);
263 if(RT_SUCCESS(rc))
264 {
265 AssertRC(pCmd->rc);
266 if(RT_SUCCESS(pCmd->rc))
267 {
268 if(pInfo2->numFourCC == numFourCC)
269 {
270 return pInfo2;
271 }
272 }
273 }
274
275 vboxVhwaCommandFree(pDevExt, pCmd);
276 return NULL;
277}
278
279int vboxVHWAEnable(PDEVICE_EXTENSION pDevExt, D3DDDI_VIDEO_PRESENT_SOURCE_ID srcId)
280{
281 int rc = VERR_GENERAL_FAILURE;
282 VBOXVHWACMD* pCmd;
283
284 pCmd = vboxVhwaCommandCreate(pDevExt, srcId, VBOXVHWACMD_TYPE_ENABLE, 0);
285 Assert(pCmd);
286 if (!pCmd)
287 {
288 drprintf((0, "VBoxDISP::vboxVHWAEnable: vboxVHWACommandCreate failed\n"));
289 return rc;
290 }
291
292 rc = vboxVhwaCommandSubmit(pDevExt, pCmd);
293 AssertRC(rc);
294 if(RT_SUCCESS(rc))
295 {
296 AssertRC(pCmd->rc);
297 if(RT_SUCCESS(pCmd->rc))
298 rc = VINF_SUCCESS;
299 else
300 rc = pCmd->rc;
301 }
302
303 vboxVhwaCommandFree(pDevExt, pCmd);
304 return rc;
305}
306
307int vboxVHWADisable(PDEVICE_EXTENSION pDevExt, D3DDDI_VIDEO_PRESENT_SOURCE_ID srcId)
308{
309 int rc = VERR_GENERAL_FAILURE;
310 VBOXVHWACMD* pCmd;
311
312 pCmd = vboxVhwaCommandCreate(pDevExt, srcId, VBOXVHWACMD_TYPE_DISABLE, 0);
313 Assert(pCmd);
314 if (!pCmd)
315 {
316 drprintf((0, "VBoxDISP::vboxVHWADisable: vboxVHWACommandCreate failed\n"));
317 return rc;
318 }
319
320 rc = vboxVhwaCommandSubmit(pDevExt, pCmd);
321 AssertRC(rc);
322 if(RT_SUCCESS(rc))
323 {
324 AssertRC(pCmd->rc);
325 if(RT_SUCCESS(pCmd->rc))
326 rc = VINF_SUCCESS;
327 else
328 rc = pCmd->rc;
329 }
330
331 vboxVhwaCommandFree(pDevExt, pCmd);
332 return rc;
333}
334
335static void vboxVHWAInitSrc(PDEVICE_EXTENSION pDevExt, D3DDDI_VIDEO_PRESENT_SOURCE_ID srcId)
336{
337 Assert(srcId < pDevExt->cSources);
338 VBOXVHWA_INFO *pSettings = &pDevExt->aSources[srcId].Vhwa.Settings;
339 memset (pSettings, 0, sizeof (VBOXVHWA_INFO));
340
341 VBOXVHWACMD_QUERYINFO1* pInfo1 = vboxVHWAQueryHostInfo1(pDevExt, srcId);
342 if (pInfo1)
343 {
344 if ((pInfo1->u.out.cfgFlags & VBOXVHWA_CFG_ENABLED)
345 && pInfo1->u.out.numOverlays)
346 {
347 if ((pInfo1->u.out.caps & VBOXVHWA_CAPS_OVERLAY)
348 && (pInfo1->u.out.caps & VBOXVHWA_CAPS_OVERLAYSTRETCH)
349 && (pInfo1->u.out.surfaceCaps & VBOXVHWA_SCAPS_OVERLAY)
350 && (pInfo1->u.out.surfaceCaps & VBOXVHWA_SCAPS_FLIP)
351 && (pInfo1->u.out.surfaceCaps & VBOXVHWA_SCAPS_LOCALVIDMEM)
352 && pInfo1->u.out.numOverlays)
353 {
354 pSettings->fFlags |= VBOXVHWA_F_ENABLED;
355
356 if (pInfo1->u.out.caps & VBOXVHWA_CAPS_COLORKEY)
357 {
358 if (pInfo1->u.out.colorKeyCaps & VBOXVHWA_CKEYCAPS_SRCOVERLAY)
359 {
360 pSettings->fFlags |= VBOXVHWA_F_CKEY_SRC;
361 /* todo: VBOXVHWA_CKEYCAPS_SRCOVERLAYONEACTIVE ? */
362 }
363
364 if (pInfo1->u.out.colorKeyCaps & VBOXVHWA_CKEYCAPS_DESTOVERLAY)
365 {
366 pSettings->fFlags |= VBOXVHWA_F_CKEY_DST;
367 /* todo: VBOXVHWA_CKEYCAPS_DESTOVERLAYONEACTIVE ? */
368 }
369 }
370
371 pSettings->cOverlaysSupported = pInfo1->u.out.numOverlays;
372
373 pSettings->cFormats = 0;
374
375 pSettings->aFormats[pSettings->cFormats] = D3DDDIFMT_X8R8G8B8;
376 ++pSettings->cFormats;
377
378 if (pInfo1->u.out.numFourCC
379 && (pInfo1->u.out.caps & VBOXVHWA_CAPS_OVERLAYFOURCC))
380 {
381 VBOXVHWACMD_QUERYINFO2* pInfo2 = vboxVHWAQueryHostInfo2(pDevExt, srcId, pInfo1->u.out.numFourCC);
382 if (pInfo2)
383 {
384 for (uint32_t i = 0; i < pInfo2->numFourCC; ++i)
385 {
386 pSettings->aFormats[pSettings->cFormats] = (D3DDDIFORMAT)pInfo2->FourCC[i];
387 ++pSettings->cFormats;
388 }
389 vboxVHWAFreeHostInfo2(pDevExt, pInfo2);
390 }
391 }
392 }
393 }
394 vboxVHWAFreeHostInfo1(pDevExt, pInfo1);
395 }
396}
397
398void vboxVHWAInit(PDEVICE_EXTENSION pDevExt)
399{
400 for (uint32_t i = 0; i < pDevExt->cSources; ++i)
401 {
402 vboxVHWAInitSrc(pDevExt, i);
403 }
404}
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette