VirtualBox

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

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

wddm/2d: bugfixes

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 34.1 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
86void vboxVhwaCommandCheckCompletion(PDEVICE_EXTENSION pDevExt)
87{
88 NTSTATUS Status = vboxWddmCallIsr(pDevExt);
89 Assert(Status == STATUS_SUCCESS);
90}
91
92VBOXVHWACMD* vboxVhwaCommandCreate(PDEVICE_EXTENSION pDevExt, D3DDDI_VIDEO_PRESENT_SOURCE_ID srcId, VBOXVHWACMD_TYPE enmCmd, VBOXVHWACMD_LENGTH cbCmd)
93{
94 vboxVhwaCommandCheckCompletion(pDevExt);
95#ifdef VBOXVHWA_WITH_SHGSMI
96 VBOXVHWACMD* pHdr = (VBOXVHWACMD*)VBoxSHGSMICommandAlloc(&pDevExt->u.primary.hgsmiAdapterHeap,
97 cbCmd + VBOXVHWACMD_HEADSIZE(),
98 HGSMI_CH_VBVA,
99 VBVA_VHWA_CMD);
100#else
101 VBOXVHWACMD* pHdr = (VBOXVHWACMD*)vboxHGSMIBufferAlloc(pDevExt,
102 cbCmd + VBOXVHWACMD_HEADSIZE(),
103 HGSMI_CH_VBVA,
104 VBVA_VHWA_CMD);
105#endif
106 Assert(pHdr);
107 if (!pHdr)
108 {
109 drprintf((__FUNCTION__": vboxHGSMIBufferAlloc failed\n"));
110 }
111 else
112 {
113 vboxVhwaHdrInit(pHdr, srcId, enmCmd);
114 }
115
116 return pHdr;
117}
118
119void vboxVhwaCommandFree(PDEVICE_EXTENSION pDevExt, VBOXVHWACMD* pCmd)
120{
121#ifdef VBOXVHWA_WITH_SHGSMI
122 VBoxSHGSMICommandFree(&pDevExt->u.primary.hgsmiAdapterHeap, pCmd);
123#else
124 vbvaVhwaCommandRelease(pDevExt, pCmd);
125#endif
126}
127
128int vboxVhwaCommandSubmit(PDEVICE_EXTENSION pDevExt, VBOXVHWACMD* pCmd)
129{
130#ifdef VBOXVHWA_WITH_SHGSMI
131 const VBOXSHGSMIHEADER* pHdr = VBoxSHGSMICommandPrepSynch(&pDevExt->u.primary.hgsmiAdapterHeap, pCmd);
132 Assert(pHdr);
133 int rc = VERR_GENERAL_FAILURE;
134 if (pHdr)
135 {
136 do
137 {
138 HGSMIOFFSET offCmd = VBoxSHGSMICommandOffset(&pDevExt->u.primary.hgsmiAdapterHeap, pHdr);
139 Assert(offCmd != HGSMIOFFSET_VOID);
140 if (offCmd != HGSMIOFFSET_VOID)
141 {
142 rc = vboxVhwaCommandSubmitHgsmi(pDevExt, offCmd);
143 AssertRC(rc);
144 if (RT_SUCCESS(rc))
145 {
146 VBoxSHGSMICommandDoneSynch(&pDevExt->u.primary.hgsmiAdapterHeap, pHdr);
147 AssertRC(rc);
148 break;
149 }
150 }
151 else
152 rc = VERR_INVALID_PARAMETER;
153 /* fail to submit, cancel it */
154 VBoxSHGSMICommandCancelSynch(&pDevExt->u.primary.hgsmiAdapterHeap, pHdr);
155 } while (0);
156 }
157 else
158 rc = VERR_INVALID_PARAMETER;
159 return rc;
160#else
161 RTSEMEVENT hEvent;
162 int rc = RTSemEventCreate(&hEvent);
163 AssertRC(rc);
164 if (RT_SUCCESS(rc))
165 {
166 pCmd->Flags |= VBOXVHWACMD_FLAG_GH_ASYNCH_IRQ;
167 vboxVhwaCommandSubmitAsynchByEvent(pDevExt, pCmd, hEvent);
168 rc = RTSemEventWait(hEvent, RT_INDEFINITE_WAIT);
169 AssertRC(rc);
170 if (RT_SUCCESS(rc))
171 RTSemEventDestroy(hEvent);
172 }
173 return rc;
174#endif
175}
176
177#ifndef VBOXVHWA_WITH_SHGSMI
178static DECLCALLBACK(void) vboxVhwaCompletionFreeCmd(PDEVICE_EXTENSION pDevExt, VBOXVHWACMD * pCmd, void * pContext)
179{
180 vboxVhwaCommandFree(pDevExt, pCmd);
181}
182
183void vboxVhwaCompletionListProcess(PDEVICE_EXTENSION pDevExt, VBOXSHGSMILIST *pList)
184{
185 PVBOXSHGSMILIST_ENTRY pNext, pCur;
186 for (pCur = pList->pFirst; pCur; pCur = pNext)
187 {
188 /* need to save next since the command may be released in a pfnCallback and thus its data might be invalid */
189 pNext = pCur->pNext;
190 VBOXVHWACMD *pCmd = VBOXVHWA_LISTENTRY2CMD(pCur);
191 PFNVBOXVHWACMDCOMPLETION pfnCallback = (PFNVBOXVHWACMDCOMPLETION)pCmd->GuestVBVAReserved1;
192 void *pvCallback = (void*)pCmd->GuestVBVAReserved2;
193 pfnCallback(pDevExt, pCmd, pvCallback);
194 }
195}
196
197#endif
198
199void vboxVhwaCommandSubmitAsynchAndComplete(PDEVICE_EXTENSION pDevExt, VBOXVHWACMD* pCmd)
200{
201#ifdef VBOXVHWA_WITH_SHGSMI
202# error "port me"
203#else
204 pCmd->Flags |= VBOXVHWACMD_FLAG_GH_ASYNCH_NOCOMPLETION;
205
206 vboxVhwaCommandSubmitAsynch(pDevExt, pCmd, vboxVhwaCompletionFreeCmd, NULL);
207#endif
208}
209
210void vboxVhwaFreeHostInfo1(PDEVICE_EXTENSION pDevExt, VBOXVHWACMD_QUERYINFO1* pInfo)
211{
212 VBOXVHWACMD* pCmd = VBOXVHWACMD_HEAD(pInfo);
213 vboxVhwaCommandFree(pDevExt, pCmd);
214}
215
216void vboxVhwaFreeHostInfo2(PDEVICE_EXTENSION pDevExt, VBOXVHWACMD_QUERYINFO2* pInfo)
217{
218 VBOXVHWACMD* pCmd = VBOXVHWACMD_HEAD(pInfo);
219 vboxVhwaCommandFree(pDevExt, pCmd);
220}
221
222VBOXVHWACMD_QUERYINFO1* vboxVhwaQueryHostInfo1(PDEVICE_EXTENSION pDevExt, D3DDDI_VIDEO_PRESENT_SOURCE_ID srcId)
223{
224 VBOXVHWACMD* pCmd = vboxVhwaCommandCreate(pDevExt, srcId, VBOXVHWACMD_TYPE_QUERY_INFO1, sizeof(VBOXVHWACMD_QUERYINFO1));
225 VBOXVHWACMD_QUERYINFO1 *pInfo1;
226
227 Assert(pCmd);
228 if (!pCmd)
229 {
230 drprintf((0, "VBoxDISP::vboxVhwaQueryHostInfo1: vboxVhwaCommandCreate failed\n"));
231 return NULL;
232 }
233
234 pInfo1 = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_QUERYINFO1);
235 pInfo1->u.in.guestVersion.maj = VBOXVHWA_VERSION_MAJ;
236 pInfo1->u.in.guestVersion.min = VBOXVHWA_VERSION_MIN;
237 pInfo1->u.in.guestVersion.bld = VBOXVHWA_VERSION_BLD;
238 pInfo1->u.in.guestVersion.reserved = VBOXVHWA_VERSION_RSV;
239
240 int rc = vboxVhwaCommandSubmit(pDevExt, pCmd);
241 AssertRC(rc);
242 if(RT_SUCCESS(rc))
243 {
244 if(RT_SUCCESS(pCmd->rc))
245 {
246 return VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_QUERYINFO1);
247 }
248 }
249
250 vboxVhwaCommandFree(pDevExt, pCmd);
251 return NULL;
252}
253
254VBOXVHWACMD_QUERYINFO2* vboxVhwaQueryHostInfo2(PDEVICE_EXTENSION pDevExt, D3DDDI_VIDEO_PRESENT_SOURCE_ID srcId, uint32_t numFourCC)
255{
256 VBOXVHWACMD* pCmd = vboxVhwaCommandCreate(pDevExt, srcId, VBOXVHWACMD_TYPE_QUERY_INFO2, VBOXVHWAINFO2_SIZE(numFourCC));
257 VBOXVHWACMD_QUERYINFO2 *pInfo2;
258 Assert(pCmd);
259 if (!pCmd)
260 {
261 drprintf((0, "VBoxDISP::vboxVhwaQueryHostInfo2: vboxVhwaCommandCreate failed\n"));
262 return NULL;
263 }
264
265 pInfo2 = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_QUERYINFO2);
266 pInfo2->numFourCC = numFourCC;
267
268 int rc = vboxVhwaCommandSubmit(pDevExt, pCmd);
269 AssertRC(rc);
270 if(RT_SUCCESS(rc))
271 {
272 AssertRC(pCmd->rc);
273 if(RT_SUCCESS(pCmd->rc))
274 {
275 if(pInfo2->numFourCC == numFourCC)
276 {
277 return pInfo2;
278 }
279 }
280 }
281
282 vboxVhwaCommandFree(pDevExt, pCmd);
283 return NULL;
284}
285
286int vboxVhwaEnable(PDEVICE_EXTENSION pDevExt, D3DDDI_VIDEO_PRESENT_SOURCE_ID srcId)
287{
288 int rc = VERR_GENERAL_FAILURE;
289 VBOXVHWACMD* pCmd;
290
291 pCmd = vboxVhwaCommandCreate(pDevExt, srcId, VBOXVHWACMD_TYPE_ENABLE, 0);
292 Assert(pCmd);
293 if (!pCmd)
294 {
295 drprintf((0, "VBoxDISP::vboxVhwaEnable: vboxVhwaCommandCreate failed\n"));
296 return rc;
297 }
298
299 rc = vboxVhwaCommandSubmit(pDevExt, pCmd);
300 AssertRC(rc);
301 if(RT_SUCCESS(rc))
302 {
303 AssertRC(pCmd->rc);
304 if(RT_SUCCESS(pCmd->rc))
305 rc = VINF_SUCCESS;
306 else
307 rc = pCmd->rc;
308 }
309
310 vboxVhwaCommandFree(pDevExt, pCmd);
311 return rc;
312}
313
314int vboxVhwaDisable(PDEVICE_EXTENSION pDevExt, D3DDDI_VIDEO_PRESENT_SOURCE_ID srcId)
315{
316 vboxVhwaCommandCheckCompletion(pDevExt);
317
318 int rc = VERR_GENERAL_FAILURE;
319 VBOXVHWACMD* pCmd;
320
321 pCmd = vboxVhwaCommandCreate(pDevExt, srcId, VBOXVHWACMD_TYPE_DISABLE, 0);
322 Assert(pCmd);
323 if (!pCmd)
324 {
325 drprintf((0, "VBoxDISP::vboxVhwaDisable: vboxVhwaCommandCreate failed\n"));
326 return rc;
327 }
328
329 rc = vboxVhwaCommandSubmit(pDevExt, pCmd);
330 AssertRC(rc);
331 if(RT_SUCCESS(rc))
332 {
333 AssertRC(pCmd->rc);
334 if(RT_SUCCESS(pCmd->rc))
335 rc = VINF_SUCCESS;
336 else
337 rc = pCmd->rc;
338 }
339
340 vboxVhwaCommandFree(pDevExt, pCmd);
341 return rc;
342}
343
344static void vboxVhwaInitSrc(PDEVICE_EXTENSION pDevExt, D3DDDI_VIDEO_PRESENT_SOURCE_ID srcId)
345{
346 Assert(srcId < (D3DDDI_VIDEO_PRESENT_SOURCE_ID)pDevExt->u.primary.cDisplays);
347 VBOXVHWA_INFO *pSettings = &pDevExt->aSources[srcId].Vhwa.Settings;
348 memset (pSettings, 0, sizeof (VBOXVHWA_INFO));
349
350 VBOXVHWACMD_QUERYINFO1* pInfo1 = vboxVhwaQueryHostInfo1(pDevExt, srcId);
351 if (pInfo1)
352 {
353 if ((pInfo1->u.out.cfgFlags & VBOXVHWA_CFG_ENABLED)
354 && pInfo1->u.out.numOverlays)
355 {
356 if ((pInfo1->u.out.caps & VBOXVHWA_CAPS_OVERLAY)
357 && (pInfo1->u.out.caps & VBOXVHWA_CAPS_OVERLAYSTRETCH)
358 && (pInfo1->u.out.surfaceCaps & VBOXVHWA_SCAPS_OVERLAY)
359 && (pInfo1->u.out.surfaceCaps & VBOXVHWA_SCAPS_FLIP)
360 && (pInfo1->u.out.surfaceCaps & VBOXVHWA_SCAPS_LOCALVIDMEM)
361 && pInfo1->u.out.numOverlays)
362 {
363 pSettings->fFlags |= VBOXVHWA_F_ENABLED;
364
365 if (pInfo1->u.out.caps & VBOXVHWA_CAPS_COLORKEY)
366 {
367 if (pInfo1->u.out.colorKeyCaps & VBOXVHWA_CKEYCAPS_SRCOVERLAY)
368 {
369 pSettings->fFlags |= VBOXVHWA_F_CKEY_SRC;
370 /* todo: VBOXVHWA_CKEYCAPS_SRCOVERLAYONEACTIVE ? */
371 }
372
373 if (pInfo1->u.out.colorKeyCaps & VBOXVHWA_CKEYCAPS_DESTOVERLAY)
374 {
375 pSettings->fFlags |= VBOXVHWA_F_CKEY_DST;
376 /* todo: VBOXVHWA_CKEYCAPS_DESTOVERLAYONEACTIVE ? */
377 }
378 }
379
380 pSettings->cOverlaysSupported = pInfo1->u.out.numOverlays;
381
382 pSettings->cFormats = 0;
383
384 pSettings->aFormats[pSettings->cFormats] = D3DDDIFMT_X8R8G8B8;
385 ++pSettings->cFormats;
386
387 if (pInfo1->u.out.numFourCC
388 && (pInfo1->u.out.caps & VBOXVHWA_CAPS_OVERLAYFOURCC))
389 {
390 VBOXVHWACMD_QUERYINFO2* pInfo2 = vboxVhwaQueryHostInfo2(pDevExt, srcId, pInfo1->u.out.numFourCC);
391 if (pInfo2)
392 {
393 for (uint32_t i = 0; i < pInfo2->numFourCC; ++i)
394 {
395 pSettings->aFormats[pSettings->cFormats] = (D3DDDIFORMAT)pInfo2->FourCC[i];
396 ++pSettings->cFormats;
397 }
398 vboxVhwaFreeHostInfo2(pDevExt, pInfo2);
399 }
400 }
401 }
402 }
403 vboxVhwaFreeHostInfo1(pDevExt, pInfo1);
404 }
405}
406
407void vboxVhwaInit(PDEVICE_EXTENSION pDevExt)
408{
409 for (int i = 0; i < pDevExt->u.primary.cDisplays; ++i)
410 {
411 vboxVhwaInitSrc(pDevExt, (D3DDDI_VIDEO_PRESENT_SOURCE_ID)i);
412 }
413}
414
415void vboxVhwaFree(PDEVICE_EXTENSION pDevExt)
416{
417 /* we do not allocate/map anything, just issue a Disable command
418 * to ensure all pending commands are flushed */
419 for (int i = 0; i < pDevExt->u.primary.cDisplays; ++i)
420 {
421 vboxVhwaDisable(pDevExt, i);
422 }
423}
424
425int vboxVhwaHlpTranslateFormat(VBOXVHWA_PIXELFORMAT *pFormat, D3DDDIFORMAT enmFormat)
426{
427 pFormat->Reserved = 0;
428 switch (enmFormat)
429 {
430 case D3DDDIFMT_A8R8G8B8:
431 case D3DDDIFMT_X8R8G8B8:
432 pFormat->flags = VBOXVHWA_PF_RGB;
433 pFormat->c.rgbBitCount = 32;
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_R8G8B8:
441 pFormat->flags = VBOXVHWA_PF_RGB;
442 pFormat->c.rgbBitCount = 24;
443 pFormat->m1.rgbRBitMask = 0xff0000;
444 pFormat->m2.rgbGBitMask = 0xff00;
445 pFormat->m3.rgbBBitMask = 0xff;
446 /* always zero for now */
447 pFormat->m4.rgbABitMask = 0;
448 return VINF_SUCCESS;
449 case D3DDDIFMT_R5G6B5:
450 pFormat->flags = VBOXVHWA_PF_RGB;
451 pFormat->c.rgbBitCount = 16;
452 pFormat->m1.rgbRBitMask = 0xf800;
453 pFormat->m2.rgbGBitMask = 0x7e0;
454 pFormat->m3.rgbBBitMask = 0x1f;
455 /* always zero for now */
456 pFormat->m4.rgbABitMask = 0;
457 return VINF_SUCCESS;
458 case D3DDDIFMT_P8:
459 case D3DDDIFMT_A8:
460 case D3DDDIFMT_X1R5G5B5:
461 case D3DDDIFMT_A1R5G5B5:
462 case D3DDDIFMT_A4R4G4B4:
463 case D3DDDIFMT_R3G3B2:
464 case D3DDDIFMT_A8R3G3B2:
465 case D3DDDIFMT_X4R4G4B4:
466 case D3DDDIFMT_A2B10G10R10:
467 case D3DDDIFMT_A8B8G8R8:
468 case D3DDDIFMT_X8B8G8R8:
469 case D3DDDIFMT_G16R16:
470 case D3DDDIFMT_A2R10G10B10:
471 case D3DDDIFMT_A16B16G16R16:
472 case D3DDDIFMT_A8P8:
473 default:
474 {
475 uint32_t fourcc = vboxWddmFormatToFourcc(enmFormat);
476 Assert(fourcc);
477 if (fourcc)
478 {
479 pFormat->flags = VBOXVHWA_PF_FOURCC;
480 pFormat->fourCC = fourcc;
481 return VINF_SUCCESS;
482 }
483 return VERR_NOT_SUPPORTED;
484 }
485 }
486}
487
488int vboxVhwaHlpDestroySurface(PDEVICE_EXTENSION pDevExt, PVBOXWDDM_ALLOCATION pSurf,
489 D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId)
490{
491 Assert(pSurf->hHostHandle);
492 if (!pSurf->hHostHandle)
493 return VERR_INVALID_STATE;
494
495 VBOXVHWACMD* pCmd = vboxVhwaCommandCreate(pDevExt, VidPnSourceId,
496 VBOXVHWACMD_TYPE_SURF_DESTROY, sizeof(VBOXVHWACMD_SURF_DESTROY));
497 Assert(pCmd);
498 if(pCmd)
499 {
500 VBOXVHWACMD_SURF_DESTROY * pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_DESTROY);
501
502 memset(pBody, 0, sizeof(VBOXVHWACMD_SURF_DESTROY));
503
504 pBody->u.in.hSurf = pSurf->hHostHandle;
505
506 /* we're not interested in completion, just send the command */
507 vboxVhwaCommandSubmitAsynchAndComplete(pDevExt, pCmd);
508
509 pSurf->hHostHandle = VBOXVHWA_SURFHANDLE_INVALID;
510
511 return VINF_SUCCESS;
512 }
513
514 return VERR_OUT_OF_RESOURCES;
515}
516
517int vboxVhwaHlpPopulateSurInfo(VBOXVHWA_SURFACEDESC *pInfo, PVBOXWDDM_ALLOCATION pSurf,
518 uint32_t fFlags, uint32_t cBackBuffers, uint32_t fSCaps,
519 D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId)
520{
521 memset(pInfo, 0, sizeof(VBOXVHWA_SURFACEDESC));
522
523 pInfo->height = pSurf->SurfDesc.height;
524 pInfo->width = pSurf->SurfDesc.width;
525 pInfo->flags |= VBOXVHWA_SD_HEIGHT | VBOXVHWA_SD_WIDTH;
526 if (fFlags & VBOXVHWA_SD_PITCH)
527 {
528 pInfo->pitch = pSurf->SurfDesc.pitch;
529 pInfo->flags |= VBOXVHWA_SD_PITCH;
530 pInfo->sizeX = pSurf->SurfDesc.cbSize;
531 pInfo->sizeY = 1;
532 }
533
534 if (cBackBuffers)
535 {
536 pInfo->cBackBuffers = cBackBuffers;
537 pInfo->flags |= VBOXVHWA_SD_BACKBUFFERCOUNT;
538 }
539 else
540 pInfo->cBackBuffers = 0;
541 pInfo->Reserved = 0;
542 /* @todo: color keys */
543// pInfo->DstOverlayCK;
544// pInfo->DstBltCK;
545// pInfo->SrcOverlayCK;
546// pInfo->SrcBltCK;
547 int rc = vboxVhwaHlpTranslateFormat(&pInfo->PixelFormat, pSurf->SurfDesc.format);
548 AssertRC(rc);
549 if (RT_SUCCESS(rc))
550 {
551 pInfo->flags |= VBOXVHWA_SD_PIXELFORMAT;
552 pInfo->surfCaps = fSCaps;
553 pInfo->flags |= VBOXVHWA_SD_CAPS;
554 pInfo->offSurface = pSurf->offVram;
555 }
556
557 return rc;
558}
559
560int vboxVhwaHlpCheckApplySurfInfo(PVBOXWDDM_ALLOCATION pSurf, VBOXVHWA_SURFACEDESC *pInfo,
561 uint32_t fFlags, bool bApplyHostHandle)
562{
563 int rc = VINF_SUCCESS;
564 if (!(fFlags & VBOXVHWA_SD_PITCH))
565 {
566 /* should be set by host */
567// Assert(pInfo->flags & VBOXVHWA_SD_PITCH);
568 pSurf->SurfDesc.cbSize = pInfo->sizeX * pInfo->sizeY;
569 Assert(pSurf->SurfDesc.cbSize);
570 pSurf->SurfDesc.pitch = pInfo->pitch;
571 Assert(pSurf->SurfDesc.pitch);
572 /* @todo: make this properly */
573 pSurf->SurfDesc.bpp = pSurf->SurfDesc.pitch * 8 / pSurf->SurfDesc.width;
574 Assert(pSurf->SurfDesc.bpp);
575 }
576 else
577 {
578 Assert(pSurf->SurfDesc.cbSize == pInfo->sizeX);
579 Assert(pInfo->sizeY == 1);
580 Assert(pInfo->pitch == pSurf->SurfDesc.pitch);
581 if (pSurf->SurfDesc.cbSize != pInfo->sizeX
582 || pInfo->sizeY != 1
583 || pInfo->pitch != pSurf->SurfDesc.pitch)
584 {
585 rc = VERR_INVALID_PARAMETER;
586 }
587 }
588
589 if (bApplyHostHandle && RT_SUCCESS(rc))
590 {
591 pSurf->hHostHandle = pInfo->hSurf;
592 }
593
594 return rc;
595}
596
597int vboxVhwaHlpCreateSurface(PDEVICE_EXTENSION pDevExt, PVBOXWDDM_ALLOCATION pSurf,
598 uint32_t fFlags, uint32_t cBackBuffers, uint32_t fSCaps,
599 D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId)
600{
601 /* the first thing we need is to post create primary */
602 VBOXVHWACMD* pCmd = vboxVhwaCommandCreate(pDevExt, VidPnSourceId,
603 VBOXVHWACMD_TYPE_SURF_CREATE, sizeof(VBOXVHWACMD_SURF_CREATE));
604 Assert(pCmd);
605 if (pCmd)
606 {
607 VBOXVHWACMD_SURF_CREATE * pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_CREATE);
608 int rc = VINF_SUCCESS;
609
610 memset(pBody, 0, sizeof(VBOXVHWACMD_SURF_CREATE));
611
612 rc = vboxVhwaHlpPopulateSurInfo(&pBody->SurfInfo, pSurf,
613 fFlags, cBackBuffers, fSCaps,
614 VidPnSourceId);
615 AssertRC(rc);
616 if (RT_SUCCESS(rc))
617 {
618 vboxVhwaCommandSubmit(pDevExt, pCmd);
619 Assert(pCmd->rc == VINF_SUCCESS);
620 if(pCmd->rc == VINF_SUCCESS)
621 {
622 rc = vboxVhwaHlpCheckApplySurfInfo(pSurf, &pBody->SurfInfo, fFlags, true);
623 }
624 else
625 rc = pCmd->rc;
626 }
627 vboxVhwaCommandFree(pDevExt, pCmd);
628 return rc;
629 }
630
631 return VERR_OUT_OF_RESOURCES;
632}
633
634int vboxVhwaHlpGetSurfInfoForSource(PDEVICE_EXTENSION pDevExt, PVBOXWDDM_ALLOCATION pSurf, D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId)
635{
636 /* the first thing we need is to post create primary */
637 VBOXVHWACMD* pCmd = vboxVhwaCommandCreate(pDevExt, VidPnSourceId,
638 VBOXVHWACMD_TYPE_SURF_GETINFO, sizeof(VBOXVHWACMD_SURF_GETINFO));
639 Assert(pCmd);
640 if (pCmd)
641 {
642 VBOXVHWACMD_SURF_GETINFO * pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_GETINFO);
643 int rc = VINF_SUCCESS;
644
645 memset(pBody, 0, sizeof(VBOXVHWACMD_SURF_GETINFO));
646
647 rc = vboxVhwaHlpPopulateSurInfo(&pBody->SurfInfo, pSurf,
648 0, 0, VBOXVHWA_SCAPS_OVERLAY | VBOXVHWA_SCAPS_VIDEOMEMORY | VBOXVHWA_SCAPS_LOCALVIDMEM | VBOXVHWA_SCAPS_COMPLEX,
649 VidPnSourceId);
650 AssertRC(rc);
651 if (RT_SUCCESS(rc))
652 {
653 vboxVhwaCommandSubmit(pDevExt, pCmd);
654 Assert(pCmd->rc == VINF_SUCCESS);
655 if(pCmd->rc == VINF_SUCCESS)
656 {
657 rc = vboxVhwaHlpCheckApplySurfInfo(pSurf, &pBody->SurfInfo, 0, true);
658 }
659 else
660 rc = pCmd->rc;
661 }
662 vboxVhwaCommandFree(pDevExt, pCmd);
663 return rc;
664 }
665
666 return VERR_OUT_OF_RESOURCES;
667}
668
669int vboxVhwaHlpGetSurfInfo(PDEVICE_EXTENSION pDevExt, PVBOXWDDM_ALLOCATION pSurf)
670{
671 for (int i = 0; i < pDevExt->u.primary.cDisplays; ++i)
672 {
673 PVBOXWDDM_SOURCE pSource = &pDevExt->aSources[i];
674 if (pSource->Vhwa.Settings.fFlags & VBOXVHWA_F_ENABLED)
675 {
676 int rc = vboxVhwaHlpGetSurfInfoForSource(pDevExt, pSurf, i);
677 AssertRC(rc);
678 return rc;
679 }
680 }
681 AssertBreakpoint();
682 return VERR_NOT_SUPPORTED;
683}
684
685int vboxVhwaHlpDestroyPrimary(PDEVICE_EXTENSION pDevExt, PVBOXWDDM_SOURCE pSource, D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId)
686{
687 PVBOXWDDM_ALLOCATION pFbSurf = VBOXWDDM_FB_ALLOCATION(pSource);
688
689 int rc = vboxVhwaHlpDestroySurface(pDevExt, pFbSurf, VidPnSourceId);
690 AssertRC(rc);
691 return rc;
692}
693
694int vboxVhwaHlpCreatePrimary(PDEVICE_EXTENSION pDevExt, PVBOXWDDM_SOURCE pSource, D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId)
695{
696 PVBOXWDDM_ALLOCATION pFbSurf = VBOXWDDM_FB_ALLOCATION(pSource);
697 Assert(pSource->Vhwa.cOverlaysCreated == 1);
698 Assert(pFbSurf->hHostHandle == VBOXVHWA_SURFHANDLE_INVALID);
699 if (pFbSurf->hHostHandle != VBOXVHWA_SURFHANDLE_INVALID)
700 return VERR_INVALID_STATE;
701
702 int rc = vboxVhwaHlpCreateSurface(pDevExt, pFbSurf,
703 VBOXVHWA_SD_PITCH, 0, VBOXVHWA_SCAPS_PRIMARYSURFACE | VBOXVHWA_SCAPS_VIDEOMEMORY | VBOXVHWA_SCAPS_LOCALVIDMEM,
704 VidPnSourceId);
705 AssertRC(rc);
706 return rc;
707}
708
709int vboxVhwaHlpCheckInit(PDEVICE_EXTENSION pDevExt, D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId)
710{
711 Assert(VidPnSourceId < (D3DDDI_VIDEO_PRESENT_SOURCE_ID)pDevExt->u.primary.cDisplays);
712 if (VidPnSourceId >= (D3DDDI_VIDEO_PRESENT_SOURCE_ID)pDevExt->u.primary.cDisplays)
713 return VERR_INVALID_PARAMETER;
714
715 PVBOXWDDM_SOURCE pSource = &pDevExt->aSources[VidPnSourceId];
716
717 Assert(!!(pSource->Vhwa.Settings.fFlags & VBOXVHWA_F_ENABLED));
718 if (!(pSource->Vhwa.Settings.fFlags & VBOXVHWA_F_ENABLED))
719 return VERR_NOT_SUPPORTED;
720
721 int rc = VINF_SUCCESS;
722 /* @todo: need a better synch */
723 uint32_t cNew = ASMAtomicIncU32(&pSource->Vhwa.cOverlaysCreated);
724 if (cNew == 1)
725 {
726 rc = vboxVhwaEnable(pDevExt, VidPnSourceId);
727 AssertRC(rc);
728 if (RT_SUCCESS(rc))
729 {
730 rc = vboxVhwaHlpCreatePrimary(pDevExt, pSource, VidPnSourceId);
731 AssertRC(rc);
732 if (RT_FAILURE(rc))
733 {
734 int tmpRc = vboxVhwaDisable(pDevExt, VidPnSourceId);
735 AssertRC(tmpRc);
736 }
737 }
738 }
739 else
740 {
741 PVBOXWDDM_ALLOCATION pFbSurf = VBOXWDDM_FB_ALLOCATION(pSource);
742 Assert(pFbSurf->hHostHandle);
743 if (pFbSurf->hHostHandle)
744 rc = VINF_ALREADY_INITIALIZED;
745 else
746 rc = VERR_INVALID_STATE;
747 }
748
749 if (RT_FAILURE(rc))
750 ASMAtomicDecU32(&pSource->Vhwa.cOverlaysCreated);
751
752 return rc;
753}
754
755int vboxVhwaHlpCheckTerm(PDEVICE_EXTENSION pDevExt, D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId)
756{
757 Assert(VidPnSourceId < (D3DDDI_VIDEO_PRESENT_SOURCE_ID)pDevExt->u.primary.cDisplays);
758 if (VidPnSourceId >= (D3DDDI_VIDEO_PRESENT_SOURCE_ID)pDevExt->u.primary.cDisplays)
759 return VERR_INVALID_PARAMETER;
760
761 PVBOXWDDM_SOURCE pSource = &pDevExt->aSources[VidPnSourceId];
762
763 Assert(!!(pSource->Vhwa.Settings.fFlags & VBOXVHWA_F_ENABLED));
764
765 /* @todo: need a better synch */
766 uint32_t cNew = ASMAtomicDecU32(&pSource->Vhwa.cOverlaysCreated);
767 int rc = VINF_SUCCESS;
768 if (!cNew)
769 {
770 rc = vboxVhwaHlpDestroyPrimary(pDevExt, pSource, VidPnSourceId);
771 AssertRC(rc);
772 }
773 else
774 {
775 Assert(cNew < UINT32_MAX / 2);
776 }
777
778 return rc;
779}
780
781int vboxVhwaHlpOverlayFlip(PVBOXWDDM_OVERLAY pOverlay, const DXGKARG_FLIPOVERLAY *pFlipInfo)
782{
783 PVBOXWDDM_ALLOCATION pAlloc = (PVBOXWDDM_ALLOCATION)pFlipInfo->hSource;
784 Assert(pAlloc->hHostHandle);
785 Assert(pAlloc->pResource);
786 Assert(pAlloc->pResource == pOverlay->pResource);
787 Assert(pFlipInfo->PrivateDriverDataSize == sizeof (VBOXWDDM_OVERLAYFLIP_INFO));
788 Assert(pFlipInfo->pPrivateDriverData);
789 PVBOXWDDM_SOURCE pSource = &pOverlay->pDevExt->aSources[pOverlay->VidPnSourceId];
790 Assert(!!(pSource->Vhwa.Settings.fFlags & VBOXVHWA_F_ENABLED));
791 PVBOXWDDM_ALLOCATION pFbSurf = VBOXWDDM_FB_ALLOCATION(pSource);
792 Assert(pFbSurf);
793 Assert(pFbSurf->hHostHandle);
794 Assert(pFbSurf->offVram != VBOXVIDEOOFFSET_VOID);
795 Assert(pOverlay->pCurentAlloc);
796 Assert(pOverlay->pCurentAlloc->pResource == pOverlay->pResource);
797 Assert(pOverlay->pCurentAlloc != pAlloc);
798 int rc = VINF_SUCCESS;
799 if (pFlipInfo->PrivateDriverDataSize == sizeof (VBOXWDDM_OVERLAYFLIP_INFO))
800 {
801 PVBOXWDDM_OVERLAYFLIP_INFO pOurInfo = (PVBOXWDDM_OVERLAYFLIP_INFO)pFlipInfo->pPrivateDriverData;
802
803 VBOXVHWACMD* pCmd = vboxVhwaCommandCreate(pOverlay->pDevExt, pOverlay->VidPnSourceId,
804 VBOXVHWACMD_TYPE_SURF_FLIP, sizeof(VBOXVHWACMD_SURF_FLIP));
805 Assert(pCmd);
806 if(pCmd)
807 {
808 VBOXVHWACMD_SURF_FLIP * pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_FLIP);
809
810 memset(pBody, 0, sizeof(VBOXVHWACMD_SURF_FLIP));
811
812// pBody->TargGuestSurfInfo;
813// pBody->CurrGuestSurfInfo;
814 pBody->u.in.hTargSurf = pAlloc->hHostHandle;
815 pBody->u.in.offTargSurface = pFlipInfo->SrcPhysicalAddress.QuadPart;
816 pAlloc->offVram = pFlipInfo->SrcPhysicalAddress.QuadPart;
817 pBody->u.in.hCurrSurf = pOverlay->pCurentAlloc->hHostHandle;
818 pBody->u.in.offCurrSurface = pOverlay->pCurentAlloc->offVram;
819 if (pOurInfo->DirtyRegion.fFlags & VBOXWDDM_DIRTYREGION_F_VALID)
820 {
821 pBody->u.in.xUpdatedTargMemValid = 1;
822 if (pOurInfo->DirtyRegion.fFlags & VBOXWDDM_DIRTYREGION_F_RECT_VALID)
823 pBody->u.in.xUpdatedTargMemRect = *(VBOXVHWA_RECTL*)((void*)&pOurInfo->DirtyRegion.Rect);
824 else
825 {
826 pBody->u.in.xUpdatedTargMemRect.right = pAlloc->SurfDesc.width;
827 pBody->u.in.xUpdatedTargMemRect.bottom = pAlloc->SurfDesc.height;
828 /* top & left are zero-inited with the above memset */
829 }
830 }
831
832 /* we're not interested in completion, just send the command */
833 vboxVhwaCommandSubmitAsynchAndComplete(pOverlay->pDevExt, pCmd);
834
835 pOverlay->pCurentAlloc = pAlloc;
836
837 rc = VINF_SUCCESS;
838 }
839 else
840 rc = VERR_OUT_OF_RESOURCES;
841 }
842 else
843 rc = VERR_INVALID_PARAMETER;
844
845 return rc;
846}
847
848AssertCompile(sizeof (RECT) == sizeof (VBOXVHWA_RECTL));
849AssertCompile(RT_SIZEOFMEMB(RECT, left) == RT_SIZEOFMEMB(VBOXVHWA_RECTL, left));
850AssertCompile(RT_SIZEOFMEMB(RECT, right) == RT_SIZEOFMEMB(VBOXVHWA_RECTL, right));
851AssertCompile(RT_SIZEOFMEMB(RECT, top) == RT_SIZEOFMEMB(VBOXVHWA_RECTL, top));
852AssertCompile(RT_SIZEOFMEMB(RECT, bottom) == RT_SIZEOFMEMB(VBOXVHWA_RECTL, bottom));
853AssertCompile(RT_OFFSETOF(RECT, left) == RT_OFFSETOF(VBOXVHWA_RECTL, left));
854AssertCompile(RT_OFFSETOF(RECT, right) == RT_OFFSETOF(VBOXVHWA_RECTL, right));
855AssertCompile(RT_OFFSETOF(RECT, top) == RT_OFFSETOF(VBOXVHWA_RECTL, top));
856AssertCompile(RT_OFFSETOF(RECT, bottom) == RT_OFFSETOF(VBOXVHWA_RECTL, bottom));
857
858int vboxVhwaHlpOverlayUpdate(PVBOXWDDM_OVERLAY pOverlay, const DXGK_OVERLAYINFO *pOverlayInfo)
859{
860 PVBOXWDDM_ALLOCATION pAlloc = (PVBOXWDDM_ALLOCATION)pOverlayInfo->hAllocation;
861 Assert(pAlloc->hHostHandle);
862 Assert(pAlloc->pResource);
863 Assert(pAlloc->pResource == pOverlay->pResource);
864 Assert(pOverlayInfo->PrivateDriverDataSize == sizeof (VBOXWDDM_OVERLAY_INFO));
865 Assert(pOverlayInfo->pPrivateDriverData);
866 PVBOXWDDM_SOURCE pSource = &pOverlay->pDevExt->aSources[pOverlay->VidPnSourceId];
867 Assert(!!(pSource->Vhwa.Settings.fFlags & VBOXVHWA_F_ENABLED));
868 PVBOXWDDM_ALLOCATION pFbSurf = VBOXWDDM_FB_ALLOCATION(pSource);
869 Assert(pFbSurf);
870 Assert(pFbSurf->hHostHandle);
871 Assert(pFbSurf->offVram != VBOXVIDEOOFFSET_VOID);
872 int rc = VINF_SUCCESS;
873 if (pOverlayInfo->PrivateDriverDataSize == sizeof (VBOXWDDM_OVERLAY_INFO))
874 {
875 PVBOXWDDM_OVERLAY_INFO pOurInfo = (PVBOXWDDM_OVERLAY_INFO)pOverlayInfo->pPrivateDriverData;
876
877 VBOXVHWACMD* pCmd = vboxVhwaCommandCreate(pOverlay->pDevExt, pOverlay->VidPnSourceId,
878 VBOXVHWACMD_TYPE_SURF_OVERLAY_UPDATE, sizeof(VBOXVHWACMD_SURF_OVERLAY_UPDATE));
879 Assert(pCmd);
880 if(pCmd)
881 {
882 VBOXVHWACMD_SURF_OVERLAY_UPDATE * pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_OVERLAY_UPDATE);
883
884 memset(pBody, 0, sizeof(VBOXVHWACMD_SURF_OVERLAY_UPDATE));
885
886 pBody->u.in.hDstSurf = pFbSurf->hHostHandle;
887 pBody->u.in.offDstSurface = pFbSurf->offVram;
888 pBody->u.in.dstRect = *(VBOXVHWA_RECTL*)((void*)&pOverlayInfo->DstRect);
889 pBody->u.in.hSrcSurf = pAlloc->hHostHandle;
890 pBody->u.in.offSrcSurface = pOverlayInfo->PhysicalAddress.QuadPart;
891 pAlloc->offVram = pOverlayInfo->PhysicalAddress.QuadPart;
892 pBody->u.in.srcRect = *(VBOXVHWA_RECTL*)((void*)&pOverlayInfo->SrcRect);
893 pBody->u.in.flags |= VBOXVHWA_OVER_SHOW;
894 if (pOurInfo->OverlayDesc.fFlags & VBOXWDDM_OVERLAY_F_CKEY_DST)
895 {
896 pBody->u.in.flags |= VBOXVHWA_OVER_KEYDESTOVERRIDE /* ?? VBOXVHWA_OVER_KEYDEST */;
897 pBody->u.in.desc.DstCK.high = pOurInfo->OverlayDesc.DstColorKeyHigh;
898 pBody->u.in.desc.DstCK.low = pOurInfo->OverlayDesc.DstColorKeyLow;
899 }
900
901 if (pOurInfo->OverlayDesc.fFlags & VBOXWDDM_OVERLAY_F_CKEY_SRC)
902 {
903 pBody->u.in.flags |= VBOXVHWA_OVER_KEYSRCOVERRIDE /* ?? VBOXVHWA_OVER_KEYSRC */;
904 pBody->u.in.desc.SrcCK.high = pOurInfo->OverlayDesc.SrcColorKeyHigh;
905 pBody->u.in.desc.SrcCK.low = pOurInfo->OverlayDesc.SrcColorKeyLow;
906 }
907
908 if (pOurInfo->DirtyRegion.fFlags & VBOXWDDM_DIRTYREGION_F_VALID)
909 {
910 pBody->u.in.xUpdatedSrcMemValid = 1;
911 if (pOurInfo->DirtyRegion.fFlags & VBOXWDDM_DIRTYREGION_F_RECT_VALID)
912 pBody->u.in.xUpdatedSrcMemRect = *(VBOXVHWA_RECTL*)((void*)&pOurInfo->DirtyRegion.Rect);
913 else
914 {
915 pBody->u.in.xUpdatedSrcMemRect.right = pAlloc->SurfDesc.width;
916 pBody->u.in.xUpdatedSrcMemRect.bottom = pAlloc->SurfDesc.height;
917 /* top & left are zero-inited with the above memset */
918 }
919 }
920
921 /* we're not interested in completion, just send the command */
922 vboxVhwaCommandSubmitAsynchAndComplete(pOverlay->pDevExt, pCmd);
923
924 pOverlay->pCurentAlloc = pAlloc;
925
926 rc = VINF_SUCCESS;
927 }
928 else
929 rc = VERR_OUT_OF_RESOURCES;
930 }
931 else
932 rc = VERR_INVALID_PARAMETER;
933
934 return rc;
935}
936
937int vboxVhwaHlpOverlayDestroy(PVBOXWDDM_OVERLAY pOverlay)
938{
939 int rc = VINF_SUCCESS;
940 for (uint32_t i = 0; i < pOverlay->pResource->cAllocations; ++i)
941 {
942 PVBOXWDDM_ALLOCATION pCurAlloc = &pOverlay->pResource->aAllocations[i];
943 rc = vboxVhwaHlpDestroySurface(pOverlay->pDevExt, pCurAlloc, pOverlay->VidPnSourceId);
944 AssertRC(rc);
945 }
946
947 if (RT_SUCCESS(rc))
948 {
949 int tmpRc = vboxVhwaHlpCheckTerm(pOverlay->pDevExt, pOverlay->VidPnSourceId);
950 AssertRC(tmpRc);
951 }
952
953 return rc;
954}
955
956
957int vboxVhwaHlpOverlayCreate(PDEVICE_EXTENSION pDevExt, D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId, DXGK_OVERLAYINFO *pOverlayInfo,
958 /* OUT */ PVBOXWDDM_OVERLAY pOverlay)
959{
960 int rc = vboxVhwaHlpCheckInit(pDevExt, VidPnSourceId);
961 AssertRC(rc);
962 if (RT_SUCCESS(rc))
963 {
964 PVBOXWDDM_ALLOCATION pAlloc = (PVBOXWDDM_ALLOCATION)pOverlayInfo->hAllocation;
965 PVBOXWDDM_RESOURCE pRc = pAlloc->pResource;
966 Assert(pRc);
967 for (uint32_t i = 0; i < pRc->cAllocations; ++i)
968 {
969 PVBOXWDDM_ALLOCATION pCurAlloc = &pRc->aAllocations[i];
970 rc = vboxVhwaHlpCreateSurface(pDevExt, pCurAlloc,
971 0, pRc->cAllocations - 1, VBOXVHWA_SCAPS_OVERLAY | VBOXVHWA_SCAPS_VIDEOMEMORY | VBOXVHWA_SCAPS_LOCALVIDMEM | VBOXVHWA_SCAPS_COMPLEX,
972 VidPnSourceId);
973 AssertRC(rc);
974 if (!RT_SUCCESS(rc))
975 {
976 int tmpRc;
977 for (uint32_t j = 0; j < i; ++j)
978 {
979 PVBOXWDDM_ALLOCATION pDestroyAlloc = &pRc->aAllocations[j];
980 tmpRc = vboxVhwaHlpDestroySurface(pDevExt, pDestroyAlloc, VidPnSourceId);
981 AssertRC(tmpRc);
982 }
983 break;
984 }
985 }
986
987 if (RT_SUCCESS(rc))
988 {
989 pOverlay->pDevExt = pDevExt;
990 pOverlay->pResource = pRc;
991 pOverlay->VidPnSourceId = VidPnSourceId;
992 rc = vboxVhwaHlpOverlayUpdate(pOverlay, pOverlayInfo);
993 if (!RT_SUCCESS(rc))
994 {
995 int tmpRc = vboxVhwaHlpOverlayDestroy(pOverlay);
996 AssertRC(tmpRc);
997 }
998 }
999
1000 if (RT_FAILURE(rc))
1001 {
1002 int tmpRc = vboxVhwaHlpCheckTerm(pDevExt, VidPnSourceId);
1003 AssertRC(tmpRc);
1004 AssertRC(rc);
1005 }
1006 }
1007
1008 return rc;
1009}
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