VirtualBox

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

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

wddm/2d: overlay create/update in UMD

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 25.2 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 < (D3DDDI_VIDEO_PRESENT_SOURCE_ID)pDevExt->u.primary.cDisplays);
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 (int i = 0; i < pDevExt->u.primary.cDisplays; ++i)
401 {
402 vboxVHWAInitSrc(pDevExt, (D3DDDI_VIDEO_PRESENT_SOURCE_ID)i);
403 }
404}
405
406void vboxVHWAFree(PDEVICE_EXTENSION pDevExt)
407{
408 /* we do not allocate/map anything, just issue a Disable command
409 * to ensure all pending commands are flushed */
410 for (int i = 0; i < pDevExt->u.primary.cDisplays; ++i)
411 {
412 vboxVHWADisable(pDevExt, i);
413 }
414}
415
416int vboxVhwaHlpTranslateFormat(VBOXVHWA_PIXELFORMAT *pFormat, D3DDDIFORMAT enmFormat)
417{
418 pFormat->Reserved = 0;
419 switch (enmFormat)
420 {
421 case D3DDDIFMT_A8R8G8B8:
422 case D3DDDIFMT_X8R8G8B8:
423 pFormat->flags = VBOXVHWA_PF_RGB;
424 pFormat->c.rgbBitCount = 32;
425 pFormat->m1.rgbRBitMask = 0xff0000;
426 pFormat->m2.rgbGBitMask = 0xff00;
427 pFormat->m3.rgbBBitMask = 0xff;
428 /* always zero for now */
429 pFormat->m4.rgbABitMask = 0;
430 return VINF_SUCCESS;
431 case D3DDDIFMT_R8G8B8:
432 pFormat->flags = VBOXVHWA_PF_RGB;
433 pFormat->c.rgbBitCount = 24;
434 pFormat->m1.rgbRBitMask = 0xff0000;
435 pFormat->m2.rgbGBitMask = 0xff00;
436 pFormat->m3.rgbBBitMask = 0xff;
437 /* always zero for now */
438 pFormat->m4.rgbABitMask = 0;
439 return VINF_SUCCESS;
440 case D3DDDIFMT_R5G6B5:
441 pFormat->flags = VBOXVHWA_PF_RGB;
442 pFormat->c.rgbBitCount = 16;
443 pFormat->m1.rgbRBitMask = 0xf800;
444 pFormat->m2.rgbGBitMask = 0x7e0;
445 pFormat->m3.rgbBBitMask = 0x1f;
446 /* always zero for now */
447 pFormat->m4.rgbABitMask = 0;
448 return VINF_SUCCESS;
449 case D3DDDIFMT_P8:
450 case D3DDDIFMT_A8:
451 case D3DDDIFMT_X1R5G5B5:
452 case D3DDDIFMT_A1R5G5B5:
453 case D3DDDIFMT_A4R4G4B4:
454 case D3DDDIFMT_R3G3B2:
455 case D3DDDIFMT_A8R3G3B2:
456 case D3DDDIFMT_X4R4G4B4:
457 case D3DDDIFMT_A2B10G10R10:
458 case D3DDDIFMT_A8B8G8R8:
459 case D3DDDIFMT_X8B8G8R8:
460 case D3DDDIFMT_G16R16:
461 case D3DDDIFMT_A2R10G10B10:
462 case D3DDDIFMT_A16B16G16R16:
463 case D3DDDIFMT_A8P8:
464 default:
465 {
466 uint32_t fourcc = vboxWddmFormatToFourcc(enmFormat);
467 Assert(fourcc);
468 if (fourcc)
469 {
470 pFormat->flags = VBOXVHWA_PF_FOURCC;
471 pFormat->fourCC = fourcc;
472 return VINF_SUCCESS;
473 }
474 return VERR_NOT_SUPPORTED;
475 }
476 }
477}
478
479int vboxVhwaHlpDestroySurface(PDEVICE_EXTENSION pDevExt, PVBOXWDDM_ALLOCATION pSurf,
480 D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId)
481{
482 Assert(pSurf->hHostHandle);
483 if (!pSurf->hHostHandle)
484 return VERR_INVALID_STATE;
485
486 VBOXVHWACMD* pCmd = vboxVhwaCommandCreate(pDevExt, VidPnSourceId,
487 VBOXVHWACMD_TYPE_SURF_DESTROY, sizeof(VBOXVHWACMD_SURF_DESTROY));
488 Assert(pCmd);
489 if(pCmd)
490 {
491 VBOXVHWACMD_SURF_DESTROY * pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_DESTROY);
492
493 memset(pBody, 0, sizeof(VBOXVHWACMD_SURF_DESTROY));
494
495 pBody->u.in.hSurf = pSurf->hHostHandle;
496
497 /* we're not interested in completion, just send the command */
498 vboxVhwaCommandSubmitAsynchAndComplete(pDevExt, pCmd);
499
500 pSurf->hHostHandle = VBOXVHWA_SURFHANDLE_INVALID;
501
502 return VINF_SUCCESS;
503 }
504
505 return VERR_OUT_OF_RESOURCES;
506}
507
508int vboxVhwaHlpPopulateSurInfo(VBOXVHWA_SURFACEDESC *pInfo, PVBOXWDDM_ALLOCATION pSurf,
509 uint32_t fFlags, uint32_t cBackBuffers, uint32_t fSCaps,
510 D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId)
511{
512 memset(pInfo, 0, sizeof(VBOXVHWA_SURFACEDESC));
513
514 pInfo->height = pSurf->SurfDesc.height;
515 pInfo->width = pSurf->SurfDesc.width;
516 pInfo->flags |= VBOXVHWA_SD_HEIGHT | VBOXVHWA_SD_WIDTH;
517 if (fFlags & VBOXVHWA_SD_PITCH)
518 {
519 pInfo->pitch = pSurf->SurfDesc.pitch;
520 pInfo->flags |= VBOXVHWA_SD_PITCH;
521 pInfo->sizeX = pSurf->SurfDesc.cbSize;
522 pInfo->sizeY = 1;
523 }
524
525 if (cBackBuffers)
526 {
527 pInfo->cBackBuffers = cBackBuffers;
528 pInfo->flags |= VBOXVHWA_SD_BACKBUFFERCOUNT;
529 }
530 else
531 pInfo->cBackBuffers = 0;
532 pInfo->Reserved = 0;
533 /* @todo: color keys */
534// pInfo->DstOverlayCK;
535// pInfo->DstBltCK;
536// pInfo->SrcOverlayCK;
537// pInfo->SrcBltCK;
538 int rc = vboxVhwaHlpTranslateFormat(&pInfo->PixelFormat, pSurf->SurfDesc.format);
539 AssertRC(rc);
540 if (RT_SUCCESS(rc))
541 {
542 pInfo->flags |= VBOXVHWA_SD_PIXELFORMAT;
543 pInfo->surfCaps = fSCaps;
544 pInfo->flags |= VBOXVHWA_SD_CAPS;
545 pInfo->offSurface = pSurf->offVram;
546 }
547
548 return rc;
549}
550
551int vboxVhwaHlpCheckApplySurfInfo(PVBOXWDDM_ALLOCATION pSurf, VBOXVHWA_SURFACEDESC *pInfo,
552 uint32_t fFlags, bool bApplyHostHandle)
553{
554 int rc = VINF_SUCCESS;
555 if (!(fFlags & VBOXVHWA_SD_PITCH))
556 {
557 /* should be set by host */
558// Assert(pInfo->flags & VBOXVHWA_SD_PITCH);
559 pSurf->SurfDesc.cbSize = pInfo->sizeX * pInfo->sizeY;
560 Assert(pSurf->SurfDesc.cbSize);
561 pSurf->SurfDesc.pitch = pInfo->pitch;
562 Assert(pSurf->SurfDesc.pitch);
563 /* @todo: make this properly */
564 pSurf->SurfDesc.bpp = (pSurf->SurfDesc.cbSize * 8) / pSurf->SurfDesc.height / pSurf->SurfDesc.pitch;
565 Assert(pSurf->SurfDesc.bpp);
566 }
567 else
568 {
569 Assert(pSurf->SurfDesc.cbSize == pInfo->sizeX);
570 Assert(pInfo->sizeY == 1);
571 Assert(pInfo->pitch == pSurf->SurfDesc.pitch);
572 if (pSurf->SurfDesc.cbSize != pInfo->sizeX
573 || pInfo->sizeY != 1
574 || pInfo->pitch != pSurf->SurfDesc.pitch)
575 {
576 rc = VERR_INVALID_PARAMETER;
577 }
578 }
579
580 if (bApplyHostHandle && RT_SUCCESS(rc))
581 {
582 pSurf->hHostHandle = pInfo->hSurf;
583 }
584
585 return rc;
586}
587
588int vboxVhwaHlpCreateSurface(PDEVICE_EXTENSION pDevExt, PVBOXWDDM_ALLOCATION pSurf,
589 uint32_t fFlags, uint32_t cBackBuffers, uint32_t fSCaps,
590 D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId)
591{
592 /* the first thing we need is to post create primary */
593 VBOXVHWACMD* pCmd = vboxVhwaCommandCreate(pDevExt, VidPnSourceId,
594 VBOXVHWACMD_TYPE_SURF_CREATE, sizeof(VBOXVHWACMD_SURF_CREATE));
595 Assert(pCmd);
596 if (pCmd)
597 {
598 VBOXVHWACMD_SURF_CREATE * pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_CREATE);
599 int rc = VINF_SUCCESS;
600
601 memset(pBody, 0, sizeof(VBOXVHWACMD_SURF_CREATE));
602
603 rc = vboxVhwaHlpPopulateSurInfo(&pBody->SurfInfo, pSurf,
604 fFlags, cBackBuffers, fSCaps,
605 VidPnSourceId);
606 AssertRC(rc);
607 if (RT_SUCCESS(rc))
608 {
609 vboxVhwaCommandSubmit(pDevExt, pCmd);
610 Assert(pCmd->rc == VINF_SUCCESS);
611 if(pCmd->rc == VINF_SUCCESS)
612 {
613 rc = vboxVhwaHlpCheckApplySurfInfo(pSurf, &pBody->SurfInfo, fFlags, true);
614 }
615 else
616 rc = pCmd->rc;
617 }
618 vboxVhwaCommandFree(pDevExt, pCmd);
619 return rc;
620 }
621
622 return VERR_OUT_OF_RESOURCES;
623}
624
625int vboxVhwaHlpGetSurfInfoForSource(PDEVICE_EXTENSION pDevExt, PVBOXWDDM_ALLOCATION pSurf, D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId)
626{
627 /* the first thing we need is to post create primary */
628 VBOXVHWACMD* pCmd = vboxVhwaCommandCreate(pDevExt, VidPnSourceId,
629 VBOXVHWACMD_TYPE_SURF_GETINFO, sizeof(VBOXVHWACMD_SURF_GETINFO));
630 Assert(pCmd);
631 if (pCmd)
632 {
633 VBOXVHWACMD_SURF_GETINFO * pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_GETINFO);
634 int rc = VINF_SUCCESS;
635
636 memset(pBody, 0, sizeof(VBOXVHWACMD_SURF_GETINFO));
637
638 rc = vboxVhwaHlpPopulateSurInfo(&pBody->SurfInfo, pSurf,
639 0, 0, VBOXVHWA_SCAPS_OVERLAY | VBOXVHWA_SCAPS_VIDEOMEMORY | VBOXVHWA_SCAPS_LOCALVIDMEM | VBOXVHWA_SCAPS_COMPLEX,
640 VidPnSourceId);
641 AssertRC(rc);
642 if (RT_SUCCESS(rc))
643 {
644 vboxVhwaCommandSubmit(pDevExt, pCmd);
645 Assert(pCmd->rc == VINF_SUCCESS);
646 if(pCmd->rc == VINF_SUCCESS)
647 {
648 rc = vboxVhwaHlpCheckApplySurfInfo(pSurf, &pBody->SurfInfo, 0, true);
649 }
650 else
651 rc = pCmd->rc;
652 }
653 vboxVhwaCommandFree(pDevExt, pCmd);
654 return rc;
655 }
656
657 return VERR_OUT_OF_RESOURCES;
658}
659
660int vboxVhwaHlpGetSurfInfo(PDEVICE_EXTENSION pDevExt, PVBOXWDDM_ALLOCATION pSurf)
661{
662 for (int i = 0; i < pDevExt->u.primary.cDisplays; ++i)
663 {
664 PVBOXWDDM_SOURCE pSource = &pDevExt->aSources[i];
665 if (pSource->Vhwa.Settings.fFlags & VBOXVHWA_F_ENABLED)
666 {
667 int rc = vboxVhwaHlpGetSurfInfoForSource(pDevExt, pSurf, i);
668 AssertRC(rc);
669 return rc;
670 }
671 }
672 AssertBreakpoint();
673 return VERR_NOT_SUPPORTED;
674}
675
676int vboxVhwaHlpDestroyPrimary(PDEVICE_EXTENSION pDevExt, PVBOXWDDM_SOURCE pSource, D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId)
677{
678#ifdef VBOXWDDM_RENDER_FROM_SHADOW
679 PVBOXWDDM_ALLOCATION pFbSurf = pSource->pShadowAllocation;
680#else
681 PVBOXWDDM_ALLOCATION pFbSurf = pSource->pPrimaryAllocation;
682#endif
683
684 int rc = vboxVhwaHlpDestroySurface(pDevExt, pFbSurf, VidPnSourceId);
685 AssertRC(rc);
686 return rc;
687}
688
689int vboxVhwaHlpCreatePrimary(PDEVICE_EXTENSION pDevExt, PVBOXWDDM_SOURCE pSource, D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId)
690{
691#ifdef VBOXWDDM_RENDER_FROM_SHADOW
692 PVBOXWDDM_ALLOCATION pFbSurf = pSource->pShadowAllocation;
693#else
694 PVBOXWDDM_ALLOCATION pFbSurf = pSource->pPrimaryAllocation;
695#endif
696 Assert(pSource->Vhwa.cOverlaysCreated == 1);
697 Assert(pFbSurf->hHostHandle == VBOXVHWA_SURFHANDLE_INVALID);
698 if (pFbSurf->hHostHandle != VBOXVHWA_SURFHANDLE_INVALID)
699 return VERR_INVALID_STATE;
700
701 int rc = vboxVhwaHlpCreateSurface(pDevExt, pFbSurf,
702 VBOXVHWA_SD_PITCH, 0, VBOXVHWA_SCAPS_PRIMARYSURFACE | VBOXVHWA_SCAPS_VIDEOMEMORY | VBOXVHWA_SCAPS_LOCALVIDMEM,
703 VidPnSourceId);
704 AssertRC(rc);
705 return rc;
706}
707
708int vboxVhwaHlpCheckInit(PDEVICE_EXTENSION pDevExt, D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId)
709{
710 Assert(VidPnSourceId < (D3DDDI_VIDEO_PRESENT_SOURCE_ID)pDevExt->u.primary.cDisplays);
711 if (VidPnSourceId >= (D3DDDI_VIDEO_PRESENT_SOURCE_ID)pDevExt->u.primary.cDisplays)
712 return VERR_INVALID_PARAMETER;
713
714 PVBOXWDDM_SOURCE pSource = &pDevExt->aSources[VidPnSourceId];
715
716 Assert(!!(pSource->Vhwa.Settings.fFlags & VBOXVHWA_F_ENABLED));
717 if (!(pSource->Vhwa.Settings.fFlags & VBOXVHWA_F_ENABLED))
718 return VERR_NOT_SUPPORTED;
719
720 int rc = VINF_SUCCESS;
721 /* @todo: need a better synch */
722 uint32_t cNew = ASMAtomicIncU32(&pSource->Vhwa.cOverlaysCreated);
723 if (cNew == 1)
724 {
725 rc = vboxVhwaHlpCreatePrimary(pDevExt, pSource, VidPnSourceId);
726 AssertRC(rc);
727 }
728 else
729 {
730#ifdef VBOXWDDM_RENDER_FROM_SHADOW
731 PVBOXWDDM_ALLOCATION pFbSurf = pSource->pShadowAllocation;
732#else
733 PVBOXWDDM_ALLOCATION pFbSurf = pSource->pPrimaryAllocation;
734#endif
735 Assert(pFbSurf->hHostHandle);
736 if (pFbSurf->hHostHandle)
737 rc = VINF_ALREADY_INITIALIZED;
738 else
739 rc = VERR_INVALID_STATE;
740 }
741
742 if (RT_FAILURE(rc))
743 ASMAtomicDecU32(&pSource->Vhwa.cOverlaysCreated);
744
745 return rc;
746}
747
748int vboxVhwaHlpCheckTerm(PDEVICE_EXTENSION pDevExt, D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId)
749{
750 Assert(VidPnSourceId < (D3DDDI_VIDEO_PRESENT_SOURCE_ID)pDevExt->u.primary.cDisplays);
751 if (VidPnSourceId >= (D3DDDI_VIDEO_PRESENT_SOURCE_ID)pDevExt->u.primary.cDisplays)
752 return VERR_INVALID_PARAMETER;
753
754 PVBOXWDDM_SOURCE pSource = &pDevExt->aSources[VidPnSourceId];
755
756 Assert(!!(pSource->Vhwa.Settings.fFlags & VBOXVHWA_F_ENABLED));
757
758 /* @todo: need a better synch */
759 uint32_t cNew = ASMAtomicDecU32(&pSource->Vhwa.cOverlaysCreated);
760 int rc = VINF_SUCCESS;
761 if (!cNew)
762 {
763 rc = vboxVhwaHlpDestroyPrimary(pDevExt, pSource, VidPnSourceId);
764 AssertRC(rc);
765 }
766 else
767 {
768 Assert(cNew < UINT32_MAX / 2);
769 }
770
771 return rc;
772}
773
774int vboxVhwaHlpCreateOverlay(PDEVICE_EXTENSION pDevExt, PVBOXWDDM_ALLOCATION pSurf, uint32_t cBackBuffers, D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId)
775{
776 int rc = vboxVhwaHlpCheckInit(pDevExt, VidPnSourceId);
777 AssertRC(rc);
778 if (RT_SUCCESS(rc))
779 {
780 rc = vboxVhwaHlpCreateSurface(pDevExt, pSurf,
781 0, cBackBuffers, VBOXVHWA_SCAPS_OVERLAY | VBOXVHWA_SCAPS_VIDEOMEMORY | VBOXVHWA_SCAPS_LOCALVIDMEM | VBOXVHWA_SCAPS_COMPLEX,
782 VidPnSourceId);
783 AssertRC(rc);
784 }
785
786 return rc;
787}
788
789int vboxVhwaHlpDestroyOverlay(PDEVICE_EXTENSION pDevExt, PVBOXWDDM_ALLOCATION pSurf, D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId)
790{
791 int rc = vboxVhwaHlpDestroySurface(pDevExt, pSurf, VidPnSourceId);
792 AssertRC(rc);
793 if (RT_SUCCESS(rc))
794 {
795 rc = vboxVhwaHlpCheckTerm(pDevExt, VidPnSourceId);
796 AssertRC(rc);
797 }
798
799 return rc;
800}
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