VirtualBox

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

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

wddm/2d: 2D video accel support fixes

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