1 | /* $Id: VBoxMPVbva.h 50778 2014-03-13 18:30:47Z 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 | #ifndef ___VBoxMPVbva_h___
|
---|
20 | #define ___VBoxMPVbva_h___
|
---|
21 |
|
---|
22 | typedef struct VBOXVBVAINFO
|
---|
23 | {
|
---|
24 | VBVABUFFERCONTEXT Vbva;
|
---|
25 | D3DDDI_VIDEO_PRESENT_SOURCE_ID srcId;
|
---|
26 | KSPIN_LOCK Lock;
|
---|
27 | } VBOXVBVAINFO;
|
---|
28 |
|
---|
29 | int vboxVbvaEnable(PVBOXMP_DEVEXT pDevExt, VBOXVBVAINFO *pVbva);
|
---|
30 | int vboxVbvaDisable(PVBOXMP_DEVEXT pDevExt, VBOXVBVAINFO *pVbva);
|
---|
31 | int vboxVbvaDestroy(PVBOXMP_DEVEXT pDevExt, VBOXVBVAINFO *pVbva);
|
---|
32 | int vboxVbvaCreate(PVBOXMP_DEVEXT pDevExt, VBOXVBVAINFO *pVbva, ULONG offBuffer, ULONG cbBuffer, D3DDDI_VIDEO_PRESENT_SOURCE_ID srcId);
|
---|
33 | int vboxVbvaReportDirtyRect(PVBOXMP_DEVEXT pDevExt, struct VBOXWDDM_SOURCE *pSrc, RECT *pRectOrig);
|
---|
34 |
|
---|
35 | #define VBOXVBVA_OP(_op, _pdext, _psrc, _arg) \
|
---|
36 | do { \
|
---|
37 | if (VBoxVBVABufferBeginUpdate(&(_psrc)->Vbva.Vbva, &VBoxCommonFromDeviceExt(_pdext)->guestCtx)) \
|
---|
38 | { \
|
---|
39 | vboxVbva##_op(_pdext, _psrc, _arg); \
|
---|
40 | VBoxVBVABufferEndUpdate(&(_psrc)->Vbva.Vbva); \
|
---|
41 | } \
|
---|
42 | } while (0)
|
---|
43 |
|
---|
44 | #define VBOXVBVA_OP_WITHLOCK_ATDPC(_op, _pdext, _psrc, _arg) \
|
---|
45 | do { \
|
---|
46 | Assert(KeGetCurrentIrql() == DISPATCH_LEVEL); \
|
---|
47 | KeAcquireSpinLockAtDpcLevel(&(_psrc)->Vbva.Lock); \
|
---|
48 | VBOXVBVA_OP(_op, _pdext, _psrc, _arg); \
|
---|
49 | KeReleaseSpinLockFromDpcLevel(&(_psrc)->Vbva.Lock);\
|
---|
50 | } while (0)
|
---|
51 |
|
---|
52 | #define VBOXVBVA_OP_WITHLOCK(_op, _pdext, _psrc, _arg) \
|
---|
53 | do { \
|
---|
54 | KIRQL OldIrql; \
|
---|
55 | KeAcquireSpinLock(&(_psrc)->Vbva.Lock, &OldIrql); \
|
---|
56 | VBOXVBVA_OP(_op, _pdext, _psrc, _arg); \
|
---|
57 | KeReleaseSpinLock(&(_psrc)->Vbva.Lock, OldIrql); \
|
---|
58 | } while (0)
|
---|
59 |
|
---|
60 |
|
---|
61 | /* customized VBVA implementation */
|
---|
62 | struct VBVAEXBUFFERCONTEXT;
|
---|
63 |
|
---|
64 | typedef DECLCALLBACKPTR(void, PFNVBVAEXBUFFERFLUSH) (struct VBVAEXBUFFERCONTEXT *pCtx, PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx, void *pvFlush);
|
---|
65 |
|
---|
66 | /**
|
---|
67 | * Structure grouping the context needed for sending graphics acceleration
|
---|
68 | * information to the host via VBVA. Each screen has its own VBVA buffer.
|
---|
69 | */
|
---|
70 | typedef struct VBVAEXBUFFERCONTEXT
|
---|
71 | {
|
---|
72 | /** Offset of the buffer in the VRAM section for the screen */
|
---|
73 | uint32_t offVRAMBuffer;
|
---|
74 | /** Length of the buffer in bytes */
|
---|
75 | uint32_t cbBuffer;
|
---|
76 | /** This flag is set if we wrote to the buffer faster than the host could
|
---|
77 | * read it. */
|
---|
78 | bool fHwBufferOverflow;
|
---|
79 | /* the window between indexRecordFirstUncompleted and pVBVA->::indexRecordFirst represents
|
---|
80 | * command records processed by the host, but not completed by the guest yet */
|
---|
81 | volatile uint32_t indexRecordFirstUncompleted;
|
---|
82 | /* the window between off32DataUncompleted and pVBVA->::off32Data represents
|
---|
83 | * command data processed by the host, but not completed by the guest yet */
|
---|
84 | uint32_t off32DataUncompleted;
|
---|
85 | /* flush function */
|
---|
86 | PFNVBVAEXBUFFERFLUSH pfnFlush;
|
---|
87 | void *pvFlush;
|
---|
88 | /** The VBVA record that we are currently preparing for the host, NULL if
|
---|
89 | * none. */
|
---|
90 | struct VBVARECORD *pRecord;
|
---|
91 | /** Pointer to the VBVA buffer mapped into the current address space. Will
|
---|
92 | * be NULL if VBVA is not enabled. */
|
---|
93 | struct VBVABUFFER *pVBVA;
|
---|
94 | } VBVAEXBUFFERCONTEXT, *PVBVAEXBUFFERCONTEXT;
|
---|
95 |
|
---|
96 | typedef struct VBVAEXBUFFERITERBASE
|
---|
97 | {
|
---|
98 | struct VBVAEXBUFFERCONTEXT *pCtx;
|
---|
99 | /* index of the current record */
|
---|
100 | uint32_t iCurRecord;
|
---|
101 | /* offset of the current command */
|
---|
102 | uint32_t off32CurCmd;
|
---|
103 | } VBVAEXBUFFERITERBASE, *PVBVAEXBUFFERITERBASE;
|
---|
104 |
|
---|
105 | typedef struct VBVAEXBUFFERFORWARDITER
|
---|
106 | {
|
---|
107 | VBVAEXBUFFERITERBASE Base;
|
---|
108 | } VBVAEXBUFFERFORWARDITER, *PVBVAEXBUFFERFORWARDITER;
|
---|
109 |
|
---|
110 | typedef struct VBVAEXBUFFERBACKWARDITER
|
---|
111 | {
|
---|
112 | VBVAEXBUFFERITERBASE Base;
|
---|
113 | } VBVAEXBUFFERBACKWARDITER, *PVBVAEXBUFFERBACKWARDITER;
|
---|
114 |
|
---|
115 | #define VBOXCMDVBVA_BUFFERSIZE(_cbCmdApprox) (RT_OFFSETOF(VBVABUFFER, au8Data) + ((RT_SIZEOFMEMB(VBVABUFFER, aRecords)/RT_SIZEOFMEMB(VBVABUFFER, aRecords[0])) * (_cbCmdApprox)))
|
---|
116 |
|
---|
117 | typedef struct VBOXCMDVBVA
|
---|
118 | {
|
---|
119 | VBVAEXBUFFERCONTEXT Vbva;
|
---|
120 |
|
---|
121 | /* last completted fence id */
|
---|
122 | uint32_t u32FenceCompleted;
|
---|
123 | /* last submitted fence id */
|
---|
124 | uint32_t u32FenceSubmitted;
|
---|
125 |
|
---|
126 | /* node ordinal */
|
---|
127 | uint32_t idNode;
|
---|
128 | } VBOXCMDVBVA;
|
---|
129 |
|
---|
130 | /** @name VBVAEx APIs
|
---|
131 | * @{ */
|
---|
132 | RTDECL(int) VBoxVBVAExEnable(PVBVAEXBUFFERCONTEXT pCtx,
|
---|
133 | PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx,
|
---|
134 | struct VBVABUFFER *pVBVA);
|
---|
135 | RTDECL(void) VBoxVBVAExDisable(PVBVAEXBUFFERCONTEXT pCtx,
|
---|
136 | PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx);
|
---|
137 | RTDECL(bool) VBoxVBVAExBufferBeginUpdate(PVBVAEXBUFFERCONTEXT pCtx,
|
---|
138 | PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx);
|
---|
139 | RTDECL(void) VBoxVBVAExBufferEndUpdate(PVBVAEXBUFFERCONTEXT pCtx);
|
---|
140 | RTDECL(bool) VBoxVBVAExWrite(PVBVAEXBUFFERCONTEXT pCtx,
|
---|
141 | PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx,
|
---|
142 | const void *pv, uint32_t cb);
|
---|
143 |
|
---|
144 | RTDECL(bool) VBoxVBVAExOrderSupported(PVBVAEXBUFFERCONTEXT pCtx, unsigned code);
|
---|
145 |
|
---|
146 | RTDECL(void) VBoxVBVAExSetupBufferContext(PVBVAEXBUFFERCONTEXT pCtx,
|
---|
147 | uint32_t offVRAMBuffer,
|
---|
148 | uint32_t cbBuffer,
|
---|
149 | PFNVBVAEXBUFFERFLUSH pfnFlush,
|
---|
150 | void *pvFlush);
|
---|
151 |
|
---|
152 | DECLINLINE(uint32_t) VBoxVBVAExGetSize(PVBVAEXBUFFERCONTEXT pCtx)
|
---|
153 | {
|
---|
154 | return pCtx->pVBVA->cbData;
|
---|
155 | }
|
---|
156 |
|
---|
157 | /* can be used to ensure the command will not cross the ring buffer boundary,
|
---|
158 | * and thus will not be splitted */
|
---|
159 | RTDECL(uint32_t) VBoxVBVAExGetFreeTail(PVBVAEXBUFFERCONTEXT pCtx);
|
---|
160 | /* allocates a contiguous buffer of a given size, i.e. the one that is not splitted across ringbuffer boundaries */
|
---|
161 | RTDECL(void*) VBoxVBVAExAllocContiguous(PVBVAEXBUFFERCONTEXT pCtx, PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx, uint32_t cb);
|
---|
162 | /* answers whether host is in "processing" state now,
|
---|
163 | * i.e. if "processing" is true after the command is submitted, no notification is required to be posted to host to make the commandbe processed,
|
---|
164 | * otherwise, host should be notified about the command */
|
---|
165 | RTDECL(bool) VBoxVBVAExIsProcessing(PVBVAEXBUFFERCONTEXT pCtx);
|
---|
166 |
|
---|
167 | /* initializes iterator that starts with free record,
|
---|
168 | * i.e. VBoxVBVAExIterNext would return the first uncompleted record.
|
---|
169 | *
|
---|
170 | * can be used by submitter only */
|
---|
171 | RTDECL(void) VBoxVBVAExBIterInit(PVBVAEXBUFFERCONTEXT pCtx, PVBVAEXBUFFERBACKWARDITER pIter);
|
---|
172 | /* can be used by submitter only */
|
---|
173 | RTDECL(void*) VBoxVBVAExBIterNext(PVBVAEXBUFFERBACKWARDITER pIter, uint32_t *pcbBuffer, bool *pfProcessed);
|
---|
174 |
|
---|
175 | /* completer functions
|
---|
176 | * completer can only use below ones, and submitter is NOT allowed to use them.
|
---|
177 | * Completter functions are prefixed with VBoxVBVAExC as opposed to submitter ones,
|
---|
178 | * that do not have the last "C" in the prefix */
|
---|
179 | /* initializes iterator that starts with completed record,
|
---|
180 | * i.e. VBoxVBVAExIterPrev would return the first uncompleted record.
|
---|
181 | * note that we can not have iterator that starts at processed record
|
---|
182 | * (i.e. the one processed by host, but not completed by guest, since host modifies
|
---|
183 | * VBVABUFFER::off32Data and VBVABUFFER::indexRecordFirst concurrently,
|
---|
184 | * and so we may end up with inconsistent index-offData pair
|
---|
185 | *
|
---|
186 | * can be used by completter only */
|
---|
187 | RTDECL(void) VBoxVBVAExCFIterInit(PVBVAEXBUFFERCONTEXT pCtx, PVBVAEXBUFFERFORWARDITER pIter);
|
---|
188 | /* can be used by completter only */
|
---|
189 | RTDECL(void*) VBoxVBVAExCFIterNext(PVBVAEXBUFFERFORWARDITER pIter, uint32_t *pcbBuffer, bool *pfProcessed);
|
---|
190 |
|
---|
191 | RTDECL(void) VBoxVBVAExCBufferCompleted(PVBVAEXBUFFERCONTEXT pCtx);
|
---|
192 |
|
---|
193 | /** @} */
|
---|
194 |
|
---|
195 | struct VBOXCMDVBVA_HDR;
|
---|
196 |
|
---|
197 | int VBoxCmdVbvaEnable(PVBOXMP_DEVEXT pDevExt, VBOXCMDVBVA *pVbva);
|
---|
198 | int VBoxCmdVbvaDisable(PVBOXMP_DEVEXT pDevExt, VBOXCMDVBVA *pVbva);
|
---|
199 | int VBoxCmdVbvaDestroy(PVBOXMP_DEVEXT pDevExt, VBOXCMDVBVA *pVbva);
|
---|
200 | int VBoxCmdVbvaCreate(PVBOXMP_DEVEXT pDevExt, VBOXCMDVBVA *pVbva, ULONG offBuffer, ULONG cbBuffer);
|
---|
201 | int VBoxCmdVbvaSubmit(PVBOXMP_DEVEXT pDevExt, VBOXCMDVBVA *pVbva, struct VBOXCMDVBVA_HDR *pCmd, uint32_t cbCmd);
|
---|
202 | bool VBoxCmdVbvaPreempt(PVBOXMP_DEVEXT pDevExt, VBOXCMDVBVA *pVbva, uint32_t u32FenceID);
|
---|
203 | uint32_t VBoxCmdVbvaCheckCompleted(PVBOXMP_DEVEXT pDevExt, VBOXCMDVBVA *pVbva, bool fPingHost);
|
---|
204 | bool VBoxCmdVbvaCheckCompletedIrq(PVBOXMP_DEVEXT pDevExt, VBOXCMDVBVA *pVbva);
|
---|
205 |
|
---|
206 | /*helper functions for filling vbva commands */
|
---|
207 | DECLINLINE(void) VBoxCVDdiPackRect(VBOXCMDVBVA_RECT *pVbvaRect, const RECT *pRect)
|
---|
208 | {
|
---|
209 | pVbvaRect->xLeft = (int16_t)pRect->left;
|
---|
210 | pVbvaRect->yTop = (int16_t)pRect->top;
|
---|
211 | pVbvaRect->xRight = (int16_t)pRect->right;
|
---|
212 | pVbvaRect->yBottom = (int16_t)pRect->bottom;
|
---|
213 | }
|
---|
214 |
|
---|
215 | DECLINLINE(void) VBoxCVDdiPackRects(VBOXCMDVBVA_RECT *paVbvaRects, const RECT *paRects, uint32_t cRects)
|
---|
216 | {
|
---|
217 | for (uint32_t i = 0; i < cRects; ++i)
|
---|
218 | {
|
---|
219 | VBoxCVDdiPackRect(&paVbvaRects[i], &paRects[i]);
|
---|
220 | }
|
---|
221 |
|
---|
222 | }
|
---|
223 |
|
---|
224 | uint32_t VBoxCVDdiPTransferVRamSysBuildEls(VBOXCMDVBVA_PAGING_TRANSFER *pCmd, PMDL pMdl, uint32_t iPfn, uint32_t cPages, uint32_t cbBuffer, uint32_t *pcPagesWritten);
|
---|
225 |
|
---|
226 | #endif /* #ifndef ___VBoxMPVbva_h___ */
|
---|