VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPVhwa.cpp@ 42091

Last change on this file since 42091 was 42081, checked in by vboxsync, 12 years ago

wddm/display-only: more imple and fixes

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 40.8 KB
Line 
1/* $Id: VBoxMPVhwa.cpp 42081 2012-07-10 09:47:29Z vboxsync $ */
2
3/** @file
4 * VBox WDDM Miniport driver
5 */
6
7/*
8 * Copyright (C) 2011 Oracle Corporation
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.virtualbox.org. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License (GPL) as published by the Free Software
14 * Foundation, in version 2 as it comes in the "COPYING" file of the
15 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
17 */
18
19#include "VBoxMPWddm.h"
20#include "VBoxMPVhwa.h"
21
22#ifndef VBOXVHWA_WITH_SHGSMI
23# include <iprt/semaphore.h>
24# include <iprt/asm.h>
25#endif
26
27#define VBOXVHWA_PRIMARY_ALLOCATION(_pSrc) ((_pSrc)->pPrimaryAllocation)
28
29
30DECLINLINE(void) vboxVhwaHdrInit(VBOXVHWACMD* pHdr, D3DDDI_VIDEO_PRESENT_SOURCE_ID srcId, VBOXVHWACMD_TYPE enmCmd)
31{
32 memset(pHdr, 0, sizeof(VBOXVHWACMD));
33 pHdr->iDisplay = srcId;
34 pHdr->rc = VERR_GENERAL_FAILURE;
35 pHdr->enmCmd = enmCmd;
36#ifndef VBOXVHWA_WITH_SHGSMI
37 pHdr->cRefs = 1;
38#endif
39}
40
41#ifdef VBOXVHWA_WITH_SHGSMI
42static int vboxVhwaCommandSubmitHgsmi(struct _DEVICE_EXTENSION* pDevExt, HGSMIOFFSET offDr)
43{
44 VBoxHGSMIGuestWrite(pDevExt, offDr);
45 return VINF_SUCCESS;
46}
47#else
48DECLINLINE(void) vbvaVhwaCommandRelease(PVBOXMP_DEVEXT pDevExt, VBOXVHWACMD* pCmd)
49{
50 uint32_t cRefs = ASMAtomicDecU32(&pCmd->cRefs);
51 Assert(cRefs < UINT32_MAX / 2);
52 if(!cRefs)
53 {
54 VBoxHGSMIBufferFree(&VBoxCommonFromDeviceExt(pDevExt)->guestCtx, pCmd);
55 }
56}
57
58DECLINLINE(void) vbvaVhwaCommandRetain(PVBOXMP_DEVEXT pDevExt, VBOXVHWACMD* pCmd)
59{
60 ASMAtomicIncU32(&pCmd->cRefs);
61}
62
63/* do not wait for completion */
64void vboxVhwaCommandSubmitAsynch(PVBOXMP_DEVEXT pDevExt, VBOXVHWACMD* pCmd, PFNVBOXVHWACMDCOMPLETION pfnCompletion, void * pContext)
65{
66 pCmd->GuestVBVAReserved1 = (uintptr_t)pfnCompletion;
67 pCmd->GuestVBVAReserved2 = (uintptr_t)pContext;
68 vbvaVhwaCommandRetain(pDevExt, pCmd);
69
70 VBoxHGSMIBufferSubmit(&VBoxCommonFromDeviceExt(pDevExt)->guestCtx, pCmd);
71
72 if(!(pCmd->Flags & VBOXVHWACMD_FLAG_HG_ASYNCH)
73 || ((pCmd->Flags & VBOXVHWACMD_FLAG_GH_ASYNCH_NOCOMPLETION)
74 && (pCmd->Flags & VBOXVHWACMD_FLAG_HG_ASYNCH_RETURNED)))
75 {
76 /* the command is completed */
77 pfnCompletion(pDevExt, pCmd, pContext);
78 }
79
80 vbvaVhwaCommandRelease(pDevExt, pCmd);
81}
82
83static DECLCALLBACK(void) vboxVhwaCompletionSetEvent(PVBOXMP_DEVEXT pDevExt, VBOXVHWACMD * pCmd, void * pvContext)
84{
85 RTSemEventSignal((RTSEMEVENT)pvContext);
86}
87
88void vboxVhwaCommandSubmitAsynchByEvent(PVBOXMP_DEVEXT pDevExt, VBOXVHWACMD* pCmd, RTSEMEVENT hEvent)
89{
90 vboxVhwaCommandSubmitAsynch(pDevExt, pCmd, vboxVhwaCompletionSetEvent, hEvent);
91}
92#endif
93
94void vboxVhwaCommandCheckCompletion(PVBOXMP_DEVEXT pDevExt)
95{
96 NTSTATUS Status = vboxWddmCallIsr(pDevExt);
97 Assert(Status == STATUS_SUCCESS);
98}
99
100VBOXVHWACMD* vboxVhwaCommandCreate(PVBOXMP_DEVEXT pDevExt, D3DDDI_VIDEO_PRESENT_SOURCE_ID srcId, VBOXVHWACMD_TYPE enmCmd, VBOXVHWACMD_LENGTH cbCmd)
101{
102 vboxVhwaCommandCheckCompletion(pDevExt);
103#ifdef VBOXVHWA_WITH_SHGSMI
104 VBOXVHWACMD* pHdr = (VBOXVHWACMD*)VBoxSHGSMICommandAlloc(&pDevExt->u.primary.hgsmiAdapterHeap,
105 cbCmd + VBOXVHWACMD_HEADSIZE(),
106 HGSMI_CH_VBVA,
107 VBVA_VHWA_CMD);
108#else
109 VBOXVHWACMD* pHdr = (VBOXVHWACMD*)VBoxHGSMIBufferAlloc(&VBoxCommonFromDeviceExt(pDevExt)->guestCtx,
110 cbCmd + VBOXVHWACMD_HEADSIZE(),
111 HGSMI_CH_VBVA,
112 VBVA_VHWA_CMD);
113#endif
114 Assert(pHdr);
115 if (!pHdr)
116 {
117 LOGREL(("VBoxHGSMIBufferAlloc failed"));
118 }
119 else
120 {
121 vboxVhwaHdrInit(pHdr, srcId, enmCmd);
122 }
123
124 return pHdr;
125}
126
127void vboxVhwaCommandFree(PVBOXMP_DEVEXT pDevExt, VBOXVHWACMD* pCmd)
128{
129#ifdef VBOXVHWA_WITH_SHGSMI
130 VBoxSHGSMICommandFree(&pDevExt->u.primary.hgsmiAdapterHeap, pCmd);
131#else
132 vbvaVhwaCommandRelease(pDevExt, pCmd);
133#endif
134}
135
136int vboxVhwaCommandSubmit(PVBOXMP_DEVEXT pDevExt, VBOXVHWACMD* pCmd)
137{
138#ifdef VBOXVHWA_WITH_SHGSMI
139 const VBOXSHGSMIHEADER* pHdr = VBoxSHGSMICommandPrepSynch(&pDevExt->u.primary.hgsmiAdapterHeap, pCmd);
140 Assert(pHdr);
141 int rc = VERR_GENERAL_FAILURE;
142 if (pHdr)
143 {
144 do
145 {
146 HGSMIOFFSET offCmd = VBoxSHGSMICommandOffset(&pDevExt->u.primary.hgsmiAdapterHeap, pHdr);
147 Assert(offCmd != HGSMIOFFSET_VOID);
148 if (offCmd != HGSMIOFFSET_VOID)
149 {
150 rc = vboxVhwaCommandSubmitHgsmi(pDevExt, offCmd);
151 AssertRC(rc);
152 if (RT_SUCCESS(rc))
153 {
154 VBoxSHGSMICommandDoneSynch(&pDevExt->u.primary.hgsmiAdapterHeap, pHdr);
155 AssertRC(rc);
156 break;
157 }
158 }
159 else
160 rc = VERR_INVALID_PARAMETER;
161 /* fail to submit, cancel it */
162 VBoxSHGSMICommandCancelSynch(&pDevExt->u.primary.hgsmiAdapterHeap, pHdr);
163 } while (0);
164 }
165 else
166 rc = VERR_INVALID_PARAMETER;
167 return rc;
168#else
169 RTSEMEVENT hEvent;
170 int rc = RTSemEventCreate(&hEvent);
171 AssertRC(rc);
172 if (RT_SUCCESS(rc))
173 {
174 pCmd->Flags |= VBOXVHWACMD_FLAG_GH_ASYNCH_IRQ;
175 vboxVhwaCommandSubmitAsynchByEvent(pDevExt, pCmd, hEvent);
176 rc = RTSemEventWait(hEvent, RT_INDEFINITE_WAIT);
177 AssertRC(rc);
178 if (RT_SUCCESS(rc))
179 RTSemEventDestroy(hEvent);
180 }
181 return rc;
182#endif
183}
184
185#ifndef VBOXVHWA_WITH_SHGSMI
186static DECLCALLBACK(void) vboxVhwaCompletionFreeCmd(PVBOXMP_DEVEXT pDevExt, VBOXVHWACMD * pCmd, void * pContext)
187{
188 vboxVhwaCommandFree(pDevExt, pCmd);
189}
190
191void vboxVhwaCompletionListProcess(PVBOXMP_DEVEXT pDevExt, VBOXVTLIST *pList)
192{
193 PVBOXVTLIST_ENTRY pNext, pCur;
194 for (pCur = pList->pFirst; pCur; pCur = pNext)
195 {
196 /* need to save next since the command may be released in a pfnCallback and thus its data might be invalid */
197 pNext = pCur->pNext;
198 VBOXVHWACMD *pCmd = VBOXVHWA_LISTENTRY2CMD(pCur);
199 PFNVBOXVHWACMDCOMPLETION pfnCallback = (PFNVBOXVHWACMDCOMPLETION)pCmd->GuestVBVAReserved1;
200 void *pvCallback = (void*)pCmd->GuestVBVAReserved2;
201 pfnCallback(pDevExt, pCmd, pvCallback);
202 }
203}
204
205#endif
206
207void vboxVhwaCommandSubmitAsynchAndComplete(PVBOXMP_DEVEXT pDevExt, VBOXVHWACMD* pCmd)
208{
209#ifdef VBOXVHWA_WITH_SHGSMI
210# error "port me"
211#else
212 pCmd->Flags |= VBOXVHWACMD_FLAG_GH_ASYNCH_NOCOMPLETION;
213
214 vboxVhwaCommandSubmitAsynch(pDevExt, pCmd, vboxVhwaCompletionFreeCmd, NULL);
215#endif
216}
217
218void vboxVhwaFreeHostInfo1(PVBOXMP_DEVEXT pDevExt, VBOXVHWACMD_QUERYINFO1* pInfo)
219{
220 VBOXVHWACMD* pCmd = VBOXVHWACMD_HEAD(pInfo);
221 vboxVhwaCommandFree(pDevExt, pCmd);
222}
223
224void vboxVhwaFreeHostInfo2(PVBOXMP_DEVEXT pDevExt, VBOXVHWACMD_QUERYINFO2* pInfo)
225{
226 VBOXVHWACMD* pCmd = VBOXVHWACMD_HEAD(pInfo);
227 vboxVhwaCommandFree(pDevExt, pCmd);
228}
229
230VBOXVHWACMD_QUERYINFO1* vboxVhwaQueryHostInfo1(PVBOXMP_DEVEXT pDevExt, D3DDDI_VIDEO_PRESENT_SOURCE_ID srcId)
231{
232 VBOXVHWACMD* pCmd = vboxVhwaCommandCreate(pDevExt, srcId, VBOXVHWACMD_TYPE_QUERY_INFO1, sizeof(VBOXVHWACMD_QUERYINFO1));
233 VBOXVHWACMD_QUERYINFO1 *pInfo1;
234
235 Assert(pCmd);
236 if (!pCmd)
237 {
238 LOGREL(("vboxVhwaCommandCreate failed"));
239 return NULL;
240 }
241
242 pInfo1 = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_QUERYINFO1);
243 pInfo1->u.in.guestVersion.maj = VBOXVHWA_VERSION_MAJ;
244 pInfo1->u.in.guestVersion.min = VBOXVHWA_VERSION_MIN;
245 pInfo1->u.in.guestVersion.bld = VBOXVHWA_VERSION_BLD;
246 pInfo1->u.in.guestVersion.reserved = VBOXVHWA_VERSION_RSV;
247
248 int rc = vboxVhwaCommandSubmit(pDevExt, pCmd);
249 AssertRC(rc);
250 if(RT_SUCCESS(rc))
251 {
252 if(RT_SUCCESS(pCmd->rc))
253 {
254 return VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_QUERYINFO1);
255 }
256 }
257
258 vboxVhwaCommandFree(pDevExt, pCmd);
259 return NULL;
260}
261
262VBOXVHWACMD_QUERYINFO2* vboxVhwaQueryHostInfo2(PVBOXMP_DEVEXT pDevExt, D3DDDI_VIDEO_PRESENT_SOURCE_ID srcId, uint32_t numFourCC)
263{
264 VBOXVHWACMD* pCmd = vboxVhwaCommandCreate(pDevExt, srcId, VBOXVHWACMD_TYPE_QUERY_INFO2, VBOXVHWAINFO2_SIZE(numFourCC));
265 VBOXVHWACMD_QUERYINFO2 *pInfo2;
266 Assert(pCmd);
267 if (!pCmd)
268 {
269 LOGREL(("vboxVhwaCommandCreate failed"));
270 return NULL;
271 }
272
273 pInfo2 = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_QUERYINFO2);
274 pInfo2->numFourCC = numFourCC;
275
276 int rc = vboxVhwaCommandSubmit(pDevExt, pCmd);
277 AssertRC(rc);
278 if(RT_SUCCESS(rc))
279 {
280 AssertRC(pCmd->rc);
281 if(RT_SUCCESS(pCmd->rc))
282 {
283 if(pInfo2->numFourCC == numFourCC)
284 {
285 return pInfo2;
286 }
287 }
288 }
289
290 vboxVhwaCommandFree(pDevExt, pCmd);
291 return NULL;
292}
293
294int vboxVhwaEnable(PVBOXMP_DEVEXT pDevExt, D3DDDI_VIDEO_PRESENT_SOURCE_ID srcId)
295{
296 int rc = VERR_GENERAL_FAILURE;
297 VBOXVHWACMD* pCmd;
298
299 pCmd = vboxVhwaCommandCreate(pDevExt, srcId, VBOXVHWACMD_TYPE_ENABLE, 0);
300 Assert(pCmd);
301 if (!pCmd)
302 {
303 LOGREL(("vboxVhwaCommandCreate failed"));
304 return rc;
305 }
306
307 rc = vboxVhwaCommandSubmit(pDevExt, pCmd);
308 AssertRC(rc);
309 if(RT_SUCCESS(rc))
310 {
311 AssertRC(pCmd->rc);
312 if(RT_SUCCESS(pCmd->rc))
313 rc = VINF_SUCCESS;
314 else
315 rc = pCmd->rc;
316 }
317
318 vboxVhwaCommandFree(pDevExt, pCmd);
319 return rc;
320}
321
322int vboxVhwaDisable(PVBOXMP_DEVEXT pDevExt, D3DDDI_VIDEO_PRESENT_SOURCE_ID srcId)
323{
324 vboxVhwaCommandCheckCompletion(pDevExt);
325
326 int rc = VERR_GENERAL_FAILURE;
327 VBOXVHWACMD* pCmd;
328
329 pCmd = vboxVhwaCommandCreate(pDevExt, srcId, VBOXVHWACMD_TYPE_DISABLE, 0);
330 Assert(pCmd);
331 if (!pCmd)
332 {
333 LOGREL(("vboxVhwaCommandCreate failed"));
334 return rc;
335 }
336
337 rc = vboxVhwaCommandSubmit(pDevExt, pCmd);
338 AssertRC(rc);
339 if(RT_SUCCESS(rc))
340 {
341 AssertRC(pCmd->rc);
342 if(RT_SUCCESS(pCmd->rc))
343 rc = VINF_SUCCESS;
344 else
345 rc = pCmd->rc;
346 }
347
348 vboxVhwaCommandFree(pDevExt, pCmd);
349 return rc;
350}
351
352DECLINLINE(VOID) vboxVhwaHlpOverlayListInit(PVBOXMP_DEVEXT pDevExt, D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId)
353{
354 PVBOXWDDM_SOURCE pSource = &pDevExt->aSources[VidPnSourceId];
355 pSource->cOverlays = 0;
356 InitializeListHead(&pSource->OverlayList);
357 KeInitializeSpinLock(&pSource->OverlayListLock);
358}
359
360static void vboxVhwaInitSrc(PVBOXMP_DEVEXT pDevExt, D3DDDI_VIDEO_PRESENT_SOURCE_ID srcId)
361{
362 Assert(srcId < (D3DDDI_VIDEO_PRESENT_SOURCE_ID)VBoxCommonFromDeviceExt(pDevExt)->cDisplays);
363 VBOXVHWA_INFO *pSettings = &pDevExt->aSources[srcId].Vhwa.Settings;
364 memset (pSettings, 0, sizeof (VBOXVHWA_INFO));
365
366 vboxVhwaHlpOverlayListInit(pDevExt, srcId);
367
368 VBOXVHWACMD_QUERYINFO1* pInfo1 = vboxVhwaQueryHostInfo1(pDevExt, srcId);
369 if (pInfo1)
370 {
371 if ((pInfo1->u.out.cfgFlags & VBOXVHWA_CFG_ENABLED)
372 && pInfo1->u.out.numOverlays)
373 {
374 if ((pInfo1->u.out.caps & VBOXVHWA_CAPS_OVERLAY)
375 && (pInfo1->u.out.caps & VBOXVHWA_CAPS_OVERLAYSTRETCH)
376 && (pInfo1->u.out.surfaceCaps & VBOXVHWA_SCAPS_OVERLAY)
377 && (pInfo1->u.out.surfaceCaps & VBOXVHWA_SCAPS_FLIP)
378 && (pInfo1->u.out.surfaceCaps & VBOXVHWA_SCAPS_LOCALVIDMEM)
379 && pInfo1->u.out.numOverlays)
380 {
381 pSettings->fFlags |= VBOXVHWA_F_ENABLED;
382
383 if (pInfo1->u.out.caps & VBOXVHWA_CAPS_COLORKEY)
384 {
385 if (pInfo1->u.out.colorKeyCaps & VBOXVHWA_CKEYCAPS_SRCOVERLAY)
386 {
387 pSettings->fFlags |= VBOXVHWA_F_CKEY_SRC;
388 /* todo: VBOXVHWA_CKEYCAPS_SRCOVERLAYONEACTIVE ? */
389 }
390
391 if (pInfo1->u.out.colorKeyCaps & VBOXVHWA_CKEYCAPS_DESTOVERLAY)
392 {
393 pSettings->fFlags |= VBOXVHWA_F_CKEY_DST;
394 /* todo: VBOXVHWA_CKEYCAPS_DESTOVERLAYONEACTIVE ? */
395 }
396 }
397
398 pSettings->cOverlaysSupported = pInfo1->u.out.numOverlays;
399
400 pSettings->cFormats = 0;
401
402 pSettings->aFormats[pSettings->cFormats] = D3DDDIFMT_X8R8G8B8;
403 ++pSettings->cFormats;
404
405 if (pInfo1->u.out.numFourCC
406 && (pInfo1->u.out.caps & VBOXVHWA_CAPS_OVERLAYFOURCC))
407 {
408 VBOXVHWACMD_QUERYINFO2* pInfo2 = vboxVhwaQueryHostInfo2(pDevExt, srcId, pInfo1->u.out.numFourCC);
409 if (pInfo2)
410 {
411 for (uint32_t i = 0; i < pInfo2->numFourCC; ++i)
412 {
413 pSettings->aFormats[pSettings->cFormats] = (D3DDDIFORMAT)pInfo2->FourCC[i];
414 ++pSettings->cFormats;
415 }
416 vboxVhwaFreeHostInfo2(pDevExt, pInfo2);
417 }
418 }
419 }
420 }
421 vboxVhwaFreeHostInfo1(pDevExt, pInfo1);
422 }
423}
424
425void vboxVhwaInit(PVBOXMP_DEVEXT pDevExt)
426{
427 for (int i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
428 {
429 vboxVhwaInitSrc(pDevExt, (D3DDDI_VIDEO_PRESENT_SOURCE_ID)i);
430 }
431}
432
433void vboxVhwaFree(PVBOXMP_DEVEXT pDevExt)
434{
435 /* we do not allocate/map anything, just issue a Disable command
436 * to ensure all pending commands are flushed */
437 for (int i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
438 {
439 vboxVhwaDisable(pDevExt, i);
440 }
441}
442
443int vboxVhwaHlpTranslateFormat(VBOXVHWA_PIXELFORMAT *pFormat, D3DDDIFORMAT enmFormat)
444{
445 pFormat->Reserved = 0;
446 switch (enmFormat)
447 {
448 case D3DDDIFMT_A8R8G8B8:
449 case D3DDDIFMT_X8R8G8B8:
450 pFormat->flags = VBOXVHWA_PF_RGB;
451 pFormat->c.rgbBitCount = 32;
452 pFormat->m1.rgbRBitMask = 0xff0000;
453 pFormat->m2.rgbGBitMask = 0xff00;
454 pFormat->m3.rgbBBitMask = 0xff;
455 /* always zero for now */
456 pFormat->m4.rgbABitMask = 0;
457 return VINF_SUCCESS;
458 case D3DDDIFMT_R8G8B8:
459 pFormat->flags = VBOXVHWA_PF_RGB;
460 pFormat->c.rgbBitCount = 24;
461 pFormat->m1.rgbRBitMask = 0xff0000;
462 pFormat->m2.rgbGBitMask = 0xff00;
463 pFormat->m3.rgbBBitMask = 0xff;
464 /* always zero for now */
465 pFormat->m4.rgbABitMask = 0;
466 return VINF_SUCCESS;
467 case D3DDDIFMT_R5G6B5:
468 pFormat->flags = VBOXVHWA_PF_RGB;
469 pFormat->c.rgbBitCount = 16;
470 pFormat->m1.rgbRBitMask = 0xf800;
471 pFormat->m2.rgbGBitMask = 0x7e0;
472 pFormat->m3.rgbBBitMask = 0x1f;
473 /* always zero for now */
474 pFormat->m4.rgbABitMask = 0;
475 return VINF_SUCCESS;
476 case D3DDDIFMT_P8:
477 case D3DDDIFMT_A8:
478 case D3DDDIFMT_X1R5G5B5:
479 case D3DDDIFMT_A1R5G5B5:
480 case D3DDDIFMT_A4R4G4B4:
481 case D3DDDIFMT_R3G3B2:
482 case D3DDDIFMT_A8R3G3B2:
483 case D3DDDIFMT_X4R4G4B4:
484 case D3DDDIFMT_A2B10G10R10:
485 case D3DDDIFMT_A8B8G8R8:
486 case D3DDDIFMT_X8B8G8R8:
487 case D3DDDIFMT_G16R16:
488 case D3DDDIFMT_A2R10G10B10:
489 case D3DDDIFMT_A16B16G16R16:
490 case D3DDDIFMT_A8P8:
491 default:
492 {
493 uint32_t fourcc = vboxWddmFormatToFourcc(enmFormat);
494 Assert(fourcc);
495 if (fourcc)
496 {
497 pFormat->flags = VBOXVHWA_PF_FOURCC;
498 pFormat->fourCC = fourcc;
499 return VINF_SUCCESS;
500 }
501 return VERR_NOT_SUPPORTED;
502 }
503 }
504}
505
506int vboxVhwaHlpDestroySurface(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_ALLOCATION pSurf,
507 D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId)
508{
509 Assert(pSurf->hHostHandle);
510 if (!pSurf->hHostHandle)
511 return VERR_INVALID_STATE;
512
513 VBOXVHWACMD* pCmd = vboxVhwaCommandCreate(pDevExt, VidPnSourceId,
514 VBOXVHWACMD_TYPE_SURF_DESTROY, sizeof(VBOXVHWACMD_SURF_DESTROY));
515 Assert(pCmd);
516 if(pCmd)
517 {
518 VBOXVHWACMD_SURF_DESTROY * pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_DESTROY);
519
520 memset(pBody, 0, sizeof(VBOXVHWACMD_SURF_DESTROY));
521
522 pBody->u.in.hSurf = pSurf->hHostHandle;
523
524 /* we're not interested in completion, just send the command */
525 vboxVhwaCommandSubmitAsynchAndComplete(pDevExt, pCmd);
526
527 pSurf->hHostHandle = VBOXVHWA_SURFHANDLE_INVALID;
528
529 return VINF_SUCCESS;
530 }
531
532 return VERR_OUT_OF_RESOURCES;
533}
534
535int vboxVhwaHlpPopulateSurInfo(VBOXVHWA_SURFACEDESC *pInfo, PVBOXWDDM_ALLOCATION pSurf,
536 uint32_t fFlags, uint32_t cBackBuffers, uint32_t fSCaps,
537 D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId)
538{
539 memset(pInfo, 0, sizeof(VBOXVHWA_SURFACEDESC));
540
541 pInfo->height = pSurf->AllocData.SurfDesc.height;
542 pInfo->width = pSurf->AllocData.SurfDesc.width;
543 pInfo->flags |= VBOXVHWA_SD_HEIGHT | VBOXVHWA_SD_WIDTH;
544 if (fFlags & VBOXVHWA_SD_PITCH)
545 {
546 pInfo->pitch = pSurf->AllocData.SurfDesc.pitch;
547 pInfo->flags |= VBOXVHWA_SD_PITCH;
548 pInfo->sizeX = pSurf->AllocData.SurfDesc.cbSize;
549 pInfo->sizeY = 1;
550 }
551
552 if (cBackBuffers)
553 {
554 pInfo->cBackBuffers = cBackBuffers;
555 pInfo->flags |= VBOXVHWA_SD_BACKBUFFERCOUNT;
556 }
557 else
558 pInfo->cBackBuffers = 0;
559 pInfo->Reserved = 0;
560 /* @todo: color keys */
561// pInfo->DstOverlayCK;
562// pInfo->DstBltCK;
563// pInfo->SrcOverlayCK;
564// pInfo->SrcBltCK;
565 int rc = vboxVhwaHlpTranslateFormat(&pInfo->PixelFormat, pSurf->AllocData.SurfDesc.format);
566 AssertRC(rc);
567 if (RT_SUCCESS(rc))
568 {
569 pInfo->flags |= VBOXVHWA_SD_PIXELFORMAT;
570 pInfo->surfCaps = fSCaps;
571 pInfo->flags |= VBOXVHWA_SD_CAPS;
572 pInfo->offSurface = pSurf->AllocData.Addr.offVram;
573 }
574
575 return rc;
576}
577
578int vboxVhwaHlpCheckApplySurfInfo(PVBOXWDDM_ALLOCATION pSurf, VBOXVHWA_SURFACEDESC *pInfo,
579 uint32_t fFlags, bool bApplyHostHandle)
580{
581 int rc = VINF_SUCCESS;
582 if (!(fFlags & VBOXVHWA_SD_PITCH))
583 {
584 /* should be set by host */
585// Assert(pInfo->flags & VBOXVHWA_SD_PITCH);
586 pSurf->AllocData.SurfDesc.cbSize = pInfo->sizeX * pInfo->sizeY;
587 Assert(pSurf->AllocData.SurfDesc.cbSize);
588 pSurf->AllocData.SurfDesc.pitch = pInfo->pitch;
589 Assert(pSurf->AllocData.SurfDesc.pitch);
590 /* @todo: make this properly */
591 pSurf->AllocData.SurfDesc.bpp = pSurf->AllocData.SurfDesc.pitch * 8 / pSurf->AllocData.SurfDesc.width;
592 Assert(pSurf->AllocData.SurfDesc.bpp);
593 }
594 else
595 {
596 Assert(pSurf->AllocData.SurfDesc.cbSize == pInfo->sizeX);
597 Assert(pInfo->sizeY == 1);
598 Assert(pInfo->pitch == pSurf->AllocData.SurfDesc.pitch);
599 if (pSurf->AllocData.SurfDesc.cbSize != pInfo->sizeX
600 || pInfo->sizeY != 1
601 || pInfo->pitch != pSurf->AllocData.SurfDesc.pitch)
602 {
603 rc = VERR_INVALID_PARAMETER;
604 }
605 }
606
607 if (bApplyHostHandle && RT_SUCCESS(rc))
608 {
609 pSurf->hHostHandle = pInfo->hSurf;
610 }
611
612 return rc;
613}
614
615int vboxVhwaHlpCreateSurface(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_ALLOCATION pSurf,
616 uint32_t fFlags, uint32_t cBackBuffers, uint32_t fSCaps,
617 D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId)
618{
619 /* the first thing we need is to post create primary */
620 VBOXVHWACMD* pCmd = vboxVhwaCommandCreate(pDevExt, VidPnSourceId,
621 VBOXVHWACMD_TYPE_SURF_CREATE, sizeof(VBOXVHWACMD_SURF_CREATE));
622 Assert(pCmd);
623 if (pCmd)
624 {
625 VBOXVHWACMD_SURF_CREATE * pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_CREATE);
626 int rc = VINF_SUCCESS;
627
628 memset(pBody, 0, sizeof(VBOXVHWACMD_SURF_CREATE));
629
630 rc = vboxVhwaHlpPopulateSurInfo(&pBody->SurfInfo, pSurf,
631 fFlags, cBackBuffers, fSCaps,
632 VidPnSourceId);
633 AssertRC(rc);
634 if (RT_SUCCESS(rc))
635 {
636 vboxVhwaCommandSubmit(pDevExt, pCmd);
637 Assert(pCmd->rc == VINF_SUCCESS);
638 if(pCmd->rc == VINF_SUCCESS)
639 {
640 rc = vboxVhwaHlpCheckApplySurfInfo(pSurf, &pBody->SurfInfo, fFlags, true);
641 }
642 else
643 rc = pCmd->rc;
644 }
645 vboxVhwaCommandFree(pDevExt, pCmd);
646 return rc;
647 }
648
649 return VERR_OUT_OF_RESOURCES;
650}
651
652int vboxVhwaHlpGetSurfInfoForSource(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_ALLOCATION pSurf, D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId)
653{
654 /* the first thing we need is to post create primary */
655 VBOXVHWACMD* pCmd = vboxVhwaCommandCreate(pDevExt, VidPnSourceId,
656 VBOXVHWACMD_TYPE_SURF_GETINFO, sizeof(VBOXVHWACMD_SURF_GETINFO));
657 Assert(pCmd);
658 if (pCmd)
659 {
660 VBOXVHWACMD_SURF_GETINFO * pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_GETINFO);
661 int rc = VINF_SUCCESS;
662
663 memset(pBody, 0, sizeof(VBOXVHWACMD_SURF_GETINFO));
664
665 rc = vboxVhwaHlpPopulateSurInfo(&pBody->SurfInfo, pSurf,
666 0, 0, VBOXVHWA_SCAPS_OVERLAY | VBOXVHWA_SCAPS_VIDEOMEMORY | VBOXVHWA_SCAPS_LOCALVIDMEM | VBOXVHWA_SCAPS_COMPLEX,
667 VidPnSourceId);
668 AssertRC(rc);
669 if (RT_SUCCESS(rc))
670 {
671 vboxVhwaCommandSubmit(pDevExt, pCmd);
672 Assert(pCmd->rc == VINF_SUCCESS);
673 if(pCmd->rc == VINF_SUCCESS)
674 {
675 rc = vboxVhwaHlpCheckApplySurfInfo(pSurf, &pBody->SurfInfo, 0, true);
676 }
677 else
678 rc = pCmd->rc;
679 }
680 vboxVhwaCommandFree(pDevExt, pCmd);
681 return rc;
682 }
683
684 return VERR_OUT_OF_RESOURCES;
685}
686
687int vboxVhwaHlpGetSurfInfo(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_ALLOCATION pSurf)
688{
689 for (int i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
690 {
691 PVBOXWDDM_SOURCE pSource = &pDevExt->aSources[i];
692 if (pSource->Vhwa.Settings.fFlags & VBOXVHWA_F_ENABLED)
693 {
694 int rc = vboxVhwaHlpGetSurfInfoForSource(pDevExt, pSurf, i);
695 AssertRC(rc);
696 return rc;
697 }
698 }
699 AssertBreakpoint();
700 return VERR_NOT_SUPPORTED;
701}
702
703int vboxVhwaHlpDestroyPrimary(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_SOURCE pSource, D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId)
704{
705 PVBOXWDDM_ALLOCATION pFbSurf = VBOXVHWA_PRIMARY_ALLOCATION(pSource);
706
707 int rc = vboxVhwaHlpDestroySurface(pDevExt, pFbSurf, VidPnSourceId);
708 AssertRC(rc);
709 return rc;
710}
711
712int vboxVhwaHlpCreatePrimary(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_SOURCE pSource, D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId)
713{
714 PVBOXWDDM_ALLOCATION pFbSurf = VBOXVHWA_PRIMARY_ALLOCATION(pSource);
715 Assert(pSource->Vhwa.cOverlaysCreated == 1);
716 Assert(pFbSurf->hHostHandle == VBOXVHWA_SURFHANDLE_INVALID);
717 if (pFbSurf->hHostHandle != VBOXVHWA_SURFHANDLE_INVALID)
718 return VERR_INVALID_STATE;
719
720 int rc = vboxVhwaHlpCreateSurface(pDevExt, pFbSurf,
721 VBOXVHWA_SD_PITCH, 0, VBOXVHWA_SCAPS_PRIMARYSURFACE | VBOXVHWA_SCAPS_VIDEOMEMORY | VBOXVHWA_SCAPS_LOCALVIDMEM,
722 VidPnSourceId);
723 AssertRC(rc);
724 return rc;
725}
726
727int vboxVhwaHlpCheckInit(PVBOXMP_DEVEXT pDevExt, D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId)
728{
729 Assert(VidPnSourceId < (D3DDDI_VIDEO_PRESENT_SOURCE_ID)VBoxCommonFromDeviceExt(pDevExt)->cDisplays);
730 if (VidPnSourceId >= (D3DDDI_VIDEO_PRESENT_SOURCE_ID)VBoxCommonFromDeviceExt(pDevExt)->cDisplays)
731 return VERR_INVALID_PARAMETER;
732
733 PVBOXWDDM_SOURCE pSource = &pDevExt->aSources[VidPnSourceId];
734
735 Assert(!!(pSource->Vhwa.Settings.fFlags & VBOXVHWA_F_ENABLED));
736 if (!(pSource->Vhwa.Settings.fFlags & VBOXVHWA_F_ENABLED))
737 return VERR_NOT_SUPPORTED;
738
739 int rc = VINF_SUCCESS;
740 /* @todo: need a better sync */
741 uint32_t cNew = ASMAtomicIncU32(&pSource->Vhwa.cOverlaysCreated);
742 if (cNew == 1)
743 {
744 rc = vboxVhwaEnable(pDevExt, VidPnSourceId);
745 AssertRC(rc);
746 if (RT_SUCCESS(rc))
747 {
748 rc = vboxVhwaHlpCreatePrimary(pDevExt, pSource, VidPnSourceId);
749 AssertRC(rc);
750 if (RT_FAILURE(rc))
751 {
752 int tmpRc = vboxVhwaDisable(pDevExt, VidPnSourceId);
753 AssertRC(tmpRc);
754 }
755 }
756 }
757 else
758 {
759 PVBOXWDDM_ALLOCATION pFbSurf = VBOXVHWA_PRIMARY_ALLOCATION(pSource);
760 Assert(pFbSurf->hHostHandle);
761 if (pFbSurf->hHostHandle)
762 rc = VINF_ALREADY_INITIALIZED;
763 else
764 rc = VERR_INVALID_STATE;
765 }
766
767 if (RT_FAILURE(rc))
768 ASMAtomicDecU32(&pSource->Vhwa.cOverlaysCreated);
769
770 return rc;
771}
772
773int vboxVhwaHlpCheckTerm(PVBOXMP_DEVEXT pDevExt, D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId)
774{
775 Assert(VidPnSourceId < (D3DDDI_VIDEO_PRESENT_SOURCE_ID)VBoxCommonFromDeviceExt(pDevExt)->cDisplays);
776 if (VidPnSourceId >= (D3DDDI_VIDEO_PRESENT_SOURCE_ID)VBoxCommonFromDeviceExt(pDevExt)->cDisplays)
777 return VERR_INVALID_PARAMETER;
778
779 PVBOXWDDM_SOURCE pSource = &pDevExt->aSources[VidPnSourceId];
780
781 Assert(!!(pSource->Vhwa.Settings.fFlags & VBOXVHWA_F_ENABLED));
782
783 /* @todo: need a better sync */
784 uint32_t cNew = ASMAtomicDecU32(&pSource->Vhwa.cOverlaysCreated);
785 int rc = VINF_SUCCESS;
786 if (!cNew)
787 {
788 rc = vboxVhwaHlpDestroyPrimary(pDevExt, pSource, VidPnSourceId);
789 AssertRC(rc);
790 }
791 else
792 {
793 Assert(cNew < UINT32_MAX / 2);
794 }
795
796 return rc;
797}
798
799int vboxVhwaHlpOverlayFlip(PVBOXWDDM_OVERLAY pOverlay, const DXGKARG_FLIPOVERLAY *pFlipInfo)
800{
801 PVBOXWDDM_ALLOCATION pAlloc = (PVBOXWDDM_ALLOCATION)pFlipInfo->hSource;
802 Assert(pAlloc->hHostHandle);
803 Assert(pAlloc->pResource);
804 Assert(pAlloc->pResource == pOverlay->pResource);
805 Assert(pFlipInfo->PrivateDriverDataSize == sizeof (VBOXWDDM_OVERLAYFLIP_INFO));
806 Assert(pFlipInfo->pPrivateDriverData);
807 PVBOXWDDM_SOURCE pSource = &pOverlay->pDevExt->aSources[pOverlay->VidPnSourceId];
808 Assert(!!(pSource->Vhwa.Settings.fFlags & VBOXVHWA_F_ENABLED));
809 PVBOXWDDM_ALLOCATION pFbSurf = VBOXVHWA_PRIMARY_ALLOCATION(pSource);
810 Assert(pFbSurf);
811 Assert(pFbSurf->hHostHandle);
812 Assert(pFbSurf->AllocData.Addr.offVram != VBOXVIDEOOFFSET_VOID);
813 Assert(pOverlay->pCurentAlloc);
814 Assert(pOverlay->pCurentAlloc->pResource == pOverlay->pResource);
815 Assert(pOverlay->pCurentAlloc != pAlloc);
816 int rc = VINF_SUCCESS;
817 if (pFlipInfo->PrivateDriverDataSize == sizeof (VBOXWDDM_OVERLAYFLIP_INFO))
818 {
819 PVBOXWDDM_OVERLAYFLIP_INFO pOurInfo = (PVBOXWDDM_OVERLAYFLIP_INFO)pFlipInfo->pPrivateDriverData;
820
821 VBOXVHWACMD* pCmd = vboxVhwaCommandCreate(pOverlay->pDevExt, pOverlay->VidPnSourceId,
822 VBOXVHWACMD_TYPE_SURF_FLIP, sizeof(VBOXVHWACMD_SURF_FLIP));
823 Assert(pCmd);
824 if(pCmd)
825 {
826 VBOXVHWACMD_SURF_FLIP * pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_FLIP);
827
828 memset(pBody, 0, sizeof(VBOXVHWACMD_SURF_FLIP));
829
830// pBody->TargGuestSurfInfo;
831// pBody->CurrGuestSurfInfo;
832 pBody->u.in.hTargSurf = pAlloc->hHostHandle;
833 pBody->u.in.offTargSurface = pFlipInfo->SrcPhysicalAddress.QuadPart;
834 pAlloc->AllocData.Addr.offVram = pFlipInfo->SrcPhysicalAddress.QuadPart;
835 pBody->u.in.hCurrSurf = pOverlay->pCurentAlloc->hHostHandle;
836 pBody->u.in.offCurrSurface = pOverlay->pCurentAlloc->AllocData.Addr.offVram;
837 if (pOurInfo->DirtyRegion.fFlags & VBOXWDDM_DIRTYREGION_F_VALID)
838 {
839 pBody->u.in.xUpdatedTargMemValid = 1;
840 if (pOurInfo->DirtyRegion.fFlags & VBOXWDDM_DIRTYREGION_F_RECT_VALID)
841 pBody->u.in.xUpdatedTargMemRect = *(VBOXVHWA_RECTL*)((void*)&pOurInfo->DirtyRegion.Rect);
842 else
843 {
844 pBody->u.in.xUpdatedTargMemRect.right = pAlloc->AllocData.SurfDesc.width;
845 pBody->u.in.xUpdatedTargMemRect.bottom = pAlloc->AllocData.SurfDesc.height;
846 /* top & left are zero-inited with the above memset */
847 }
848 }
849
850 /* we're not interested in completion, just send the command */
851 vboxVhwaCommandSubmitAsynchAndComplete(pOverlay->pDevExt, pCmd);
852
853 pOverlay->pCurentAlloc = pAlloc;
854
855 rc = VINF_SUCCESS;
856 }
857 else
858 rc = VERR_OUT_OF_RESOURCES;
859 }
860 else
861 rc = VERR_INVALID_PARAMETER;
862
863 return rc;
864}
865
866AssertCompile(sizeof (RECT) == sizeof (VBOXVHWA_RECTL));
867AssertCompile(RT_SIZEOFMEMB(RECT, left) == RT_SIZEOFMEMB(VBOXVHWA_RECTL, left));
868AssertCompile(RT_SIZEOFMEMB(RECT, right) == RT_SIZEOFMEMB(VBOXVHWA_RECTL, right));
869AssertCompile(RT_SIZEOFMEMB(RECT, top) == RT_SIZEOFMEMB(VBOXVHWA_RECTL, top));
870AssertCompile(RT_SIZEOFMEMB(RECT, bottom) == RT_SIZEOFMEMB(VBOXVHWA_RECTL, bottom));
871AssertCompile(RT_OFFSETOF(RECT, left) == RT_OFFSETOF(VBOXVHWA_RECTL, left));
872AssertCompile(RT_OFFSETOF(RECT, right) == RT_OFFSETOF(VBOXVHWA_RECTL, right));
873AssertCompile(RT_OFFSETOF(RECT, top) == RT_OFFSETOF(VBOXVHWA_RECTL, top));
874AssertCompile(RT_OFFSETOF(RECT, bottom) == RT_OFFSETOF(VBOXVHWA_RECTL, bottom));
875
876int vboxVhwaHlpColorFill(PVBOXWDDM_OVERLAY pOverlay, PVBOXWDDM_DMA_PRIVATEDATA_CLRFILL pCF)
877{
878 PVBOXWDDM_ALLOCATION pAlloc = pCF->ClrFill.Alloc.pAlloc;
879 Assert(pAlloc->pResource == pOverlay->pResource);
880#ifdef VBOXWDDM_RENDER_FROM_SHADOW
881 if (pAlloc->bAssigned)
882 {
883 /* check if this is a primary surf */
884 PVBOXWDDM_SOURCE pSource = &pOverlay->pDevExt->aSources[pOverlay->VidPnSourceId];
885 if (pSource->pPrimaryAllocation == pAlloc)
886 {
887 pAlloc = pSource->pShadowAllocation;
888 Assert(pAlloc->pResource == pOverlay->pResource);
889 }
890 }
891#endif
892 Assert(pAlloc->hHostHandle);
893 Assert(pAlloc->pResource);
894 Assert(pAlloc->AllocData.Addr.offVram != VBOXVIDEOOFFSET_VOID);
895
896 int rc;
897 VBOXVHWACMD* pCmd = vboxVhwaCommandCreate(pOverlay->pDevExt, pOverlay->VidPnSourceId,
898 VBOXVHWACMD_TYPE_SURF_FLIP, RT_OFFSETOF(VBOXVHWACMD_SURF_COLORFILL, u.in.aRects[pCF->ClrFill.Rects.cRects]));
899 Assert(pCmd);
900 if(pCmd)
901 {
902 VBOXVHWACMD_SURF_COLORFILL * pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_COLORFILL);
903
904 memset(pBody, 0, sizeof(VBOXVHWACMD_SURF_COLORFILL));
905
906 pBody->u.in.hSurf = pAlloc->hHostHandle;
907 pBody->u.in.offSurface = pAlloc->AllocData.Addr.offVram;
908 pBody->u.in.cRects = pCF->ClrFill.Rects.cRects;
909 memcpy (pBody->u.in.aRects, pCF->ClrFill.Rects.aRects, pCF->ClrFill.Rects.cRects * sizeof (pCF->ClrFill.Rects.aRects[0]));
910 vboxVhwaCommandSubmitAsynchAndComplete(pOverlay->pDevExt, pCmd);
911
912 rc = VINF_SUCCESS;
913 }
914 else
915 rc = VERR_OUT_OF_RESOURCES;
916
917 return rc;
918}
919
920static void vboxVhwaHlpOverlayDstRectSet(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_OVERLAY pOverlay, const RECT *pRect)
921{
922 PVBOXWDDM_SOURCE pSource = &pDevExt->aSources[pOverlay->VidPnSourceId];
923 KIRQL OldIrql;
924 KeAcquireSpinLock(&pSource->OverlayListLock, &OldIrql);
925 pOverlay->DstRect = *pRect;
926 KeReleaseSpinLock(&pSource->OverlayListLock, OldIrql);
927}
928
929static void vboxVhwaHlpOverlayListAdd(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_OVERLAY pOverlay)
930{
931 PVBOXWDDM_SOURCE pSource = &pDevExt->aSources[pOverlay->VidPnSourceId];
932 KIRQL OldIrql;
933 KeAcquireSpinLock(&pSource->OverlayListLock, &OldIrql);
934 ASMAtomicIncU32(&pSource->cOverlays);
935 InsertHeadList(&pSource->OverlayList, &pOverlay->ListEntry);
936 KeReleaseSpinLock(&pSource->OverlayListLock, OldIrql);
937}
938
939static void vboxVhwaHlpOverlayListRemove(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_OVERLAY pOverlay)
940{
941 PVBOXWDDM_SOURCE pSource = &pDevExt->aSources[pOverlay->VidPnSourceId];
942 KIRQL OldIrql;
943 KeAcquireSpinLock(&pSource->OverlayListLock, &OldIrql);
944 ASMAtomicDecU32(&pSource->cOverlays);
945 RemoveEntryList(&pOverlay->ListEntry);
946 KeReleaseSpinLock(&pSource->OverlayListLock, OldIrql);
947}
948
949AssertCompile(sizeof (RECT) == sizeof (VBOXVHWA_RECTL));
950AssertCompile(RT_SIZEOFMEMB(RECT, left) == RT_SIZEOFMEMB(VBOXVHWA_RECTL, left));
951AssertCompile(RT_SIZEOFMEMB(RECT, right) == RT_SIZEOFMEMB(VBOXVHWA_RECTL, right));
952AssertCompile(RT_SIZEOFMEMB(RECT, top) == RT_SIZEOFMEMB(VBOXVHWA_RECTL, top));
953AssertCompile(RT_SIZEOFMEMB(RECT, bottom) == RT_SIZEOFMEMB(VBOXVHWA_RECTL, bottom));
954AssertCompile(RT_OFFSETOF(RECT, left) == RT_OFFSETOF(VBOXVHWA_RECTL, left));
955AssertCompile(RT_OFFSETOF(RECT, right) == RT_OFFSETOF(VBOXVHWA_RECTL, right));
956AssertCompile(RT_OFFSETOF(RECT, top) == RT_OFFSETOF(VBOXVHWA_RECTL, top));
957AssertCompile(RT_OFFSETOF(RECT, bottom) == RT_OFFSETOF(VBOXVHWA_RECTL, bottom));
958
959int vboxVhwaHlpOverlayUpdate(PVBOXWDDM_OVERLAY pOverlay, const DXGK_OVERLAYINFO *pOverlayInfo, RECT * pDstUpdateRect)
960{
961 PVBOXWDDM_ALLOCATION pAlloc = (PVBOXWDDM_ALLOCATION)pOverlayInfo->hAllocation;
962 Assert(pAlloc->hHostHandle);
963 Assert(pAlloc->pResource);
964 Assert(pAlloc->pResource == pOverlay->pResource);
965 Assert(pOverlayInfo->PrivateDriverDataSize == sizeof (VBOXWDDM_OVERLAY_INFO));
966 Assert(pOverlayInfo->pPrivateDriverData);
967 PVBOXWDDM_SOURCE pSource = &pOverlay->pDevExt->aSources[pOverlay->VidPnSourceId];
968 Assert(!!(pSource->Vhwa.Settings.fFlags & VBOXVHWA_F_ENABLED));
969 PVBOXWDDM_ALLOCATION pFbSurf = VBOXVHWA_PRIMARY_ALLOCATION(pSource);
970 Assert(pFbSurf);
971 Assert(pFbSurf->hHostHandle);
972 Assert(pFbSurf->AllocData.Addr.offVram != VBOXVIDEOOFFSET_VOID);
973 int rc = VINF_SUCCESS;
974 if (pOverlayInfo->PrivateDriverDataSize == sizeof (VBOXWDDM_OVERLAY_INFO))
975 {
976 PVBOXWDDM_OVERLAY_INFO pOurInfo = (PVBOXWDDM_OVERLAY_INFO)pOverlayInfo->pPrivateDriverData;
977
978 VBOXVHWACMD* pCmd = vboxVhwaCommandCreate(pOverlay->pDevExt, pOverlay->VidPnSourceId,
979 VBOXVHWACMD_TYPE_SURF_OVERLAY_UPDATE, sizeof(VBOXVHWACMD_SURF_OVERLAY_UPDATE));
980 Assert(pCmd);
981 if(pCmd)
982 {
983 VBOXVHWACMD_SURF_OVERLAY_UPDATE * pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_OVERLAY_UPDATE);
984
985 memset(pBody, 0, sizeof(VBOXVHWACMD_SURF_OVERLAY_UPDATE));
986
987 pBody->u.in.hDstSurf = pFbSurf->hHostHandle;
988 pBody->u.in.offDstSurface = pFbSurf->AllocData.Addr.offVram;
989 pBody->u.in.dstRect = *(VBOXVHWA_RECTL*)((void*)&pOverlayInfo->DstRect);
990 pBody->u.in.hSrcSurf = pAlloc->hHostHandle;
991 pBody->u.in.offSrcSurface = pOverlayInfo->PhysicalAddress.QuadPart;
992 pAlloc->AllocData.Addr.offVram = pOverlayInfo->PhysicalAddress.QuadPart;
993 pBody->u.in.srcRect = *(VBOXVHWA_RECTL*)((void*)&pOverlayInfo->SrcRect);
994 pBody->u.in.flags |= VBOXVHWA_OVER_SHOW;
995 if (pOurInfo->OverlayDesc.fFlags & VBOXWDDM_OVERLAY_F_CKEY_DST)
996 {
997 pBody->u.in.flags |= VBOXVHWA_OVER_KEYDESTOVERRIDE /* ?? VBOXVHWA_OVER_KEYDEST */;
998 pBody->u.in.desc.DstCK.high = pOurInfo->OverlayDesc.DstColorKeyHigh;
999 pBody->u.in.desc.DstCK.low = pOurInfo->OverlayDesc.DstColorKeyLow;
1000 }
1001
1002 if (pOurInfo->OverlayDesc.fFlags & VBOXWDDM_OVERLAY_F_CKEY_SRC)
1003 {
1004 pBody->u.in.flags |= VBOXVHWA_OVER_KEYSRCOVERRIDE /* ?? VBOXVHWA_OVER_KEYSRC */;
1005 pBody->u.in.desc.SrcCK.high = pOurInfo->OverlayDesc.SrcColorKeyHigh;
1006 pBody->u.in.desc.SrcCK.low = pOurInfo->OverlayDesc.SrcColorKeyLow;
1007 }
1008
1009 if (pOurInfo->DirtyRegion.fFlags & VBOXWDDM_DIRTYREGION_F_VALID)
1010 {
1011 pBody->u.in.xFlags |= VBOXVHWACMD_SURF_OVERLAY_UPDATE_F_SRCMEMRECT;
1012 if (pOurInfo->DirtyRegion.fFlags & VBOXWDDM_DIRTYREGION_F_RECT_VALID)
1013 pBody->u.in.xUpdatedSrcMemRect = *(VBOXVHWA_RECTL*)((void*)&pOurInfo->DirtyRegion.Rect);
1014 else
1015 {
1016 pBody->u.in.xUpdatedSrcMemRect.right = pAlloc->AllocData.SurfDesc.width;
1017 pBody->u.in.xUpdatedSrcMemRect.bottom = pAlloc->AllocData.SurfDesc.height;
1018 /* top & left are zero-inited with the above memset */
1019 }
1020 }
1021
1022 if (pDstUpdateRect)
1023 {
1024 pBody->u.in.xFlags |= VBOXVHWACMD_SURF_OVERLAY_UPDATE_F_DSTMEMRECT;
1025 pBody->u.in.xUpdatedDstMemRect = *(VBOXVHWA_RECTL*)((void*)pDstUpdateRect);
1026 }
1027
1028 /* we're not interested in completion, just send the command */
1029 vboxVhwaCommandSubmitAsynchAndComplete(pOverlay->pDevExt, pCmd);
1030
1031 pOverlay->pCurentAlloc = pAlloc;
1032
1033 vboxVhwaHlpOverlayDstRectSet(pOverlay->pDevExt, pOverlay, &pOverlayInfo->DstRect);
1034
1035 rc = VINF_SUCCESS;
1036 }
1037 else
1038 rc = VERR_OUT_OF_RESOURCES;
1039 }
1040 else
1041 rc = VERR_INVALID_PARAMETER;
1042
1043 return rc;
1044}
1045
1046int vboxVhwaHlpOverlayUpdate(PVBOXWDDM_OVERLAY pOverlay, const DXGK_OVERLAYINFO *pOverlayInfo)
1047{
1048 return vboxVhwaHlpOverlayUpdate(pOverlay, pOverlayInfo, NULL);
1049}
1050
1051int vboxVhwaHlpOverlayDestroy(PVBOXWDDM_OVERLAY pOverlay)
1052{
1053 int rc = VINF_SUCCESS;
1054
1055 vboxVhwaHlpOverlayListRemove(pOverlay->pDevExt, pOverlay);
1056
1057 for (uint32_t i = 0; i < pOverlay->pResource->cAllocations; ++i)
1058 {
1059 PVBOXWDDM_ALLOCATION pCurAlloc = &pOverlay->pResource->aAllocations[i];
1060 rc = vboxVhwaHlpDestroySurface(pOverlay->pDevExt, pCurAlloc, pOverlay->VidPnSourceId);
1061 AssertRC(rc);
1062 }
1063
1064 if (RT_SUCCESS(rc))
1065 {
1066 int tmpRc = vboxVhwaHlpCheckTerm(pOverlay->pDevExt, pOverlay->VidPnSourceId);
1067 AssertRC(tmpRc);
1068 }
1069
1070 return rc;
1071}
1072
1073
1074int vboxVhwaHlpOverlayCreate(PVBOXMP_DEVEXT pDevExt, D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId, DXGK_OVERLAYINFO *pOverlayInfo,
1075 /* OUT */ PVBOXWDDM_OVERLAY pOverlay)
1076{
1077 int rc = vboxVhwaHlpCheckInit(pDevExt, VidPnSourceId);
1078 AssertRC(rc);
1079 if (RT_SUCCESS(rc))
1080 {
1081 PVBOXWDDM_ALLOCATION pAlloc = (PVBOXWDDM_ALLOCATION)pOverlayInfo->hAllocation;
1082 PVBOXWDDM_RESOURCE pRc = pAlloc->pResource;
1083 Assert(pRc);
1084 for (uint32_t i = 0; i < pRc->cAllocations; ++i)
1085 {
1086 PVBOXWDDM_ALLOCATION pCurAlloc = &pRc->aAllocations[i];
1087 rc = vboxVhwaHlpCreateSurface(pDevExt, pCurAlloc,
1088 0, pRc->cAllocations - 1, VBOXVHWA_SCAPS_OVERLAY | VBOXVHWA_SCAPS_VIDEOMEMORY | VBOXVHWA_SCAPS_LOCALVIDMEM | VBOXVHWA_SCAPS_COMPLEX,
1089 VidPnSourceId);
1090 AssertRC(rc);
1091 if (!RT_SUCCESS(rc))
1092 {
1093 int tmpRc;
1094 for (uint32_t j = 0; j < i; ++j)
1095 {
1096 PVBOXWDDM_ALLOCATION pDestroyAlloc = &pRc->aAllocations[j];
1097 tmpRc = vboxVhwaHlpDestroySurface(pDevExt, pDestroyAlloc, VidPnSourceId);
1098 AssertRC(tmpRc);
1099 }
1100 break;
1101 }
1102 }
1103
1104 if (RT_SUCCESS(rc))
1105 {
1106 pOverlay->pDevExt = pDevExt;
1107 pOverlay->pResource = pRc;
1108 pOverlay->VidPnSourceId = VidPnSourceId;
1109
1110 vboxVhwaHlpOverlayListAdd(pDevExt, pOverlay);
1111#ifdef VBOXWDDM_RENDER_FROM_SHADOW
1112 RECT DstRect;
1113 vboxVhwaHlpOverlayDstRectGet(pDevExt, pOverlay, &DstRect);
1114 NTSTATUS Status = vboxVdmaHlpUpdatePrimary(pDevExt, VidPnSourceId, &DstRect);
1115 Assert(Status == STATUS_SUCCESS);
1116 /* ignore primary update failure */
1117 Status = STATUS_SUCCESS;
1118#endif
1119 rc = vboxVhwaHlpOverlayUpdate(pOverlay, pOverlayInfo, DstRect.right ? &DstRect : NULL);
1120 if (!RT_SUCCESS(rc))
1121 {
1122 int tmpRc = vboxVhwaHlpOverlayDestroy(pOverlay);
1123 AssertRC(tmpRc);
1124 }
1125 }
1126
1127 if (RT_FAILURE(rc))
1128 {
1129 int tmpRc = vboxVhwaHlpCheckTerm(pDevExt, VidPnSourceId);
1130 AssertRC(tmpRc);
1131 AssertRC(rc);
1132 }
1133 }
1134
1135 return rc;
1136}
1137
1138BOOLEAN vboxVhwaHlpOverlayListIsEmpty(PVBOXMP_DEVEXT pDevExt, D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId)
1139{
1140 PVBOXWDDM_SOURCE pSource = &pDevExt->aSources[VidPnSourceId];
1141 return !ASMAtomicReadU32(&pSource->cOverlays);
1142}
1143
1144#define VBOXWDDM_OVERLAY_FROM_ENTRY(_pEntry) ((PVBOXWDDM_OVERLAY)(((uint8_t*)(_pEntry)) - RT_OFFSETOF(VBOXWDDM_OVERLAY, ListEntry)))
1145
1146void vboxVhwaHlpOverlayDstRectUnion(PVBOXMP_DEVEXT pDevExt, D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId, RECT *pRect)
1147{
1148 if (vboxVhwaHlpOverlayListIsEmpty(pDevExt, VidPnSourceId))
1149 {
1150 memset(pRect, 0, sizeof (*pRect));
1151 return;
1152 }
1153
1154 PVBOXWDDM_SOURCE pSource = &pDevExt->aSources[VidPnSourceId];
1155 KIRQL OldIrql;
1156 KeAcquireSpinLock(&pSource->OverlayListLock, &OldIrql);
1157 if (pSource->cOverlays)
1158 {
1159 PVBOXWDDM_OVERLAY pOverlay = VBOXWDDM_OVERLAY_FROM_ENTRY(pSource->OverlayList.Flink);
1160 *pRect = pOverlay->DstRect;
1161 while (pOverlay->ListEntry.Flink != &pSource->OverlayList)
1162 {
1163 pOverlay = VBOXWDDM_OVERLAY_FROM_ENTRY(pOverlay->ListEntry.Flink);
1164 vboxWddmRectUnite(pRect, &pOverlay->DstRect);
1165 }
1166 }
1167 KeReleaseSpinLock(&pSource->OverlayListLock, OldIrql);
1168}
1169
1170void vboxVhwaHlpOverlayDstRectGet(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_OVERLAY pOverlay, RECT *pRect)
1171{
1172 PVBOXWDDM_SOURCE pSource = &pDevExt->aSources[pOverlay->VidPnSourceId];
1173 KIRQL OldIrql;
1174 KeAcquireSpinLock(&pSource->OverlayListLock, &OldIrql);
1175 *pRect = pOverlay->DstRect;
1176 KeReleaseSpinLock(&pSource->OverlayListLock, OldIrql);
1177}
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