VirtualBox

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

Last change on this file since 57801 was 57468, checked in by vboxsync, 9 years ago

static

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.3 KB
Line 
1/* $Id: VBoxMPShgsmi.cpp 57468 2015-08-20 08:54:44Z vboxsync $ */
2
3/** @file
4 * VBox WDDM Miniport driver
5 */
6
7/*
8 * Copyright (C) 2011-2012 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 <iprt/semaphore.h>
21
22/* SHGSMI */
23DECLINLINE(void) vboxSHGSMICommandRetain (PVBOXSHGSMIHEADER pCmd)
24{
25 ASMAtomicIncU32(&pCmd->cRefs);
26}
27
28void vboxSHGSMICommandFree (PVBOXSHGSMI pHeap, PVBOXSHGSMIHEADER pCmd)
29{
30 VBoxSHGSMIHeapFree(pHeap, pCmd);
31}
32
33DECLINLINE(void) vboxSHGSMICommandRelease (PVBOXSHGSMI pHeap, PVBOXSHGSMIHEADER pCmd)
34{
35 uint32_t cRefs = ASMAtomicDecU32(&pCmd->cRefs);
36 Assert(cRefs < UINT32_MAX / 2);
37 if(!cRefs)
38 vboxSHGSMICommandFree (pHeap, pCmd);
39}
40
41static DECLCALLBACK(void) vboxSHGSMICompletionSetEvent(PVBOXSHGSMI pHeap, void *pvCmd, void *pvContext)
42{
43 RTSemEventSignal((RTSEMEVENT)pvContext);
44}
45
46DECLCALLBACK(void) vboxSHGSMICompletionCommandRelease(PVBOXSHGSMI pHeap, void *pvCmd, void *pvContext)
47{
48 vboxSHGSMICommandRelease (pHeap, VBoxSHGSMIBufferHeader(pvCmd));
49}
50
51/* do not wait for completion */
52DECLINLINE(const VBOXSHGSMIHEADER*) vboxSHGSMICommandPrepAsynch (PVBOXSHGSMI pHeap, PVBOXSHGSMIHEADER pHeader)
53{
54 /* ensure the command is not removed until we're processing it */
55 vboxSHGSMICommandRetain(pHeader);
56 return pHeader;
57}
58
59DECLINLINE(void) vboxSHGSMICommandDoneAsynch (PVBOXSHGSMI pHeap, const VBOXSHGSMIHEADER* pHeader)
60{
61 if(!(ASMAtomicReadU32((volatile uint32_t *)&pHeader->fFlags) & VBOXSHGSMI_FLAG_HG_ASYNCH))
62 {
63 PFNVBOXSHGSMICMDCOMPLETION pfnCompletion = (PFNVBOXSHGSMICMDCOMPLETION)pHeader->u64Info1;
64 if (pfnCompletion)
65 pfnCompletion(pHeap, VBoxSHGSMIBufferData (pHeader), (PVOID)pHeader->u64Info2);
66 }
67
68 vboxSHGSMICommandRelease(pHeap, (PVBOXSHGSMIHEADER)pHeader);
69}
70
71const VBOXSHGSMIHEADER* VBoxSHGSMICommandPrepAsynchEvent (PVBOXSHGSMI pHeap, PVOID pvBuff, RTSEMEVENT hEventSem)
72{
73 PVBOXSHGSMIHEADER pHeader = VBoxSHGSMIBufferHeader (pvBuff);
74 pHeader->u64Info1 = (uint64_t)vboxSHGSMICompletionSetEvent;
75 pHeader->u64Info2 = (uint64_t)hEventSem;
76 pHeader->fFlags = VBOXSHGSMI_FLAG_GH_ASYNCH_IRQ;
77
78 return vboxSHGSMICommandPrepAsynch (pHeap, pHeader);
79}
80
81const VBOXSHGSMIHEADER* VBoxSHGSMICommandPrepSynch (PVBOXSHGSMI pHeap, PVOID pCmd)
82{
83 RTSEMEVENT hEventSem;
84 int rc = RTSemEventCreate(&hEventSem);
85 Assert(RT_SUCCESS(rc));
86 if (RT_SUCCESS(rc))
87 {
88 return VBoxSHGSMICommandPrepAsynchEvent (pHeap, pCmd, hEventSem);
89 }
90 return NULL;
91}
92
93void VBoxSHGSMICommandDoneAsynch (PVBOXSHGSMI pHeap, const VBOXSHGSMIHEADER * pHeader)
94{
95 vboxSHGSMICommandDoneAsynch(pHeap, pHeader);
96}
97
98int VBoxSHGSMICommandDoneSynch (PVBOXSHGSMI pHeap, const VBOXSHGSMIHEADER* pHeader)
99{
100 VBoxSHGSMICommandDoneAsynch (pHeap, pHeader);
101 RTSEMEVENT hEventSem = (RTSEMEVENT)pHeader->u64Info2;
102 int rc = RTSemEventWait(hEventSem, RT_INDEFINITE_WAIT);
103 AssertRC(rc);
104 if (RT_SUCCESS(rc))
105 RTSemEventDestroy(hEventSem);
106 return rc;
107}
108
109void VBoxSHGSMICommandCancelAsynch (PVBOXSHGSMI pHeap, const VBOXSHGSMIHEADER* pHeader)
110{
111 vboxSHGSMICommandRelease(pHeap, (PVBOXSHGSMIHEADER)pHeader);
112}
113
114void VBoxSHGSMICommandCancelSynch (PVBOXSHGSMI pHeap, const VBOXSHGSMIHEADER* pHeader)
115{
116 VBoxSHGSMICommandCancelAsynch (pHeap, pHeader);
117 RTSEMEVENT hEventSem = (RTSEMEVENT)pHeader->u64Info2;
118 RTSemEventDestroy(hEventSem);
119}
120
121const VBOXSHGSMIHEADER* VBoxSHGSMICommandPrepAsynch (PVBOXSHGSMI pHeap, PVOID pvBuff, PFNVBOXSHGSMICMDCOMPLETION pfnCompletion, PVOID pvCompletion, uint32_t fFlags)
122{
123 fFlags &= ~VBOXSHGSMI_FLAG_GH_ASYNCH_CALLBACK_IRQ;
124 PVBOXSHGSMIHEADER pHeader = VBoxSHGSMIBufferHeader (pvBuff);
125 pHeader->u64Info1 = (uint64_t)pfnCompletion;
126 pHeader->u64Info2 = (uint64_t)pvCompletion;
127 pHeader->fFlags = fFlags;
128
129 return vboxSHGSMICommandPrepAsynch (pHeap, pHeader);
130}
131
132const VBOXSHGSMIHEADER* VBoxSHGSMICommandPrepAsynchIrq (PVBOXSHGSMI pHeap, PVOID pvBuff, PFNVBOXSHGSMICMDCOMPLETION_IRQ pfnCompletion, PVOID pvCompletion, uint32_t fFlags)
133{
134 fFlags |= VBOXSHGSMI_FLAG_GH_ASYNCH_CALLBACK_IRQ | VBOXSHGSMI_FLAG_GH_ASYNCH_IRQ;
135 PVBOXSHGSMIHEADER pHeader = VBoxSHGSMIBufferHeader (pvBuff);
136 pHeader->u64Info1 = (uint64_t)pfnCompletion;
137 pHeader->u64Info2 = (uint64_t)pvCompletion;
138 /* we must assign rather than or because flags field does not get zeroed on command creation */
139 pHeader->fFlags = fFlags;
140
141 return vboxSHGSMICommandPrepAsynch (pHeap, pHeader);
142}
143
144void* VBoxSHGSMIHeapAlloc(PVBOXSHGSMI pHeap, HGSMISIZE cbData, uint8_t u8Channel, uint16_t u16ChannelInfo)
145{
146 KIRQL OldIrql;
147 void* pvData;
148 Assert(KeGetCurrentIrql() <= DISPATCH_LEVEL);
149 KeAcquireSpinLock(&pHeap->HeapLock, &OldIrql);
150 pvData = HGSMIHeapAlloc(&pHeap->Heap, cbData, u8Channel, u16ChannelInfo);
151 KeReleaseSpinLock(&pHeap->HeapLock, OldIrql);
152 if (!pvData)
153 WARN(("HGSMIHeapAlloc failed!"));
154 return pvData;
155}
156
157void VBoxSHGSMIHeapFree(PVBOXSHGSMI pHeap, void *pvBuffer)
158{
159 KIRQL OldIrql;
160 Assert(KeGetCurrentIrql() <= DISPATCH_LEVEL);
161 KeAcquireSpinLock(&pHeap->HeapLock, &OldIrql);
162 HGSMIHeapFree(&pHeap->Heap, pvBuffer);
163 KeReleaseSpinLock(&pHeap->HeapLock, OldIrql);
164}
165
166void* VBoxSHGSMIHeapBufferAlloc(PVBOXSHGSMI pHeap, HGSMISIZE cbData)
167{
168 KIRQL OldIrql;
169 void* pvData;
170 Assert(KeGetCurrentIrql() <= DISPATCH_LEVEL);
171 KeAcquireSpinLock(&pHeap->HeapLock, &OldIrql);
172 pvData = HGSMIHeapBufferAlloc(&pHeap->Heap, cbData);
173 KeReleaseSpinLock(&pHeap->HeapLock, OldIrql);
174 if (!pvData)
175 WARN(("HGSMIHeapAlloc failed!"));
176 return pvData;
177}
178
179void VBoxSHGSMIHeapBufferFree(PVBOXSHGSMI pHeap, void *pvBuffer)
180{
181 KIRQL OldIrql;
182 Assert(KeGetCurrentIrql() <= DISPATCH_LEVEL);
183 KeAcquireSpinLock(&pHeap->HeapLock, &OldIrql);
184 HGSMIHeapBufferFree(&pHeap->Heap, pvBuffer);
185 KeReleaseSpinLock(&pHeap->HeapLock, OldIrql);
186}
187
188int VBoxSHGSMIInit(PVBOXSHGSMI pHeap, void *pvBase, HGSMISIZE cbArea, HGSMIOFFSET offBase,
189 const HGSMIENV *pEnv)
190{
191 KeInitializeSpinLock(&pHeap->HeapLock);
192 return HGSMIHeapSetup(&pHeap->Heap, pvBase, cbArea, offBase, pEnv);
193}
194
195void VBoxSHGSMITerm(PVBOXSHGSMI pHeap)
196{
197 HGSMIHeapDestroy(&pHeap->Heap);
198}
199
200void* VBoxSHGSMICommandAlloc(PVBOXSHGSMI pHeap, HGSMISIZE cbData, uint8_t u8Channel, uint16_t u16ChannelInfo)
201{
202 /* Issue the flush command. */
203 PVBOXSHGSMIHEADER pHeader = (PVBOXSHGSMIHEADER)VBoxSHGSMIHeapAlloc(pHeap, cbData + sizeof (VBOXSHGSMIHEADER), u8Channel, u16ChannelInfo);
204 Assert(pHeader);
205 if (pHeader)
206 {
207 pHeader->cRefs = 1;
208 return VBoxSHGSMIBufferData(pHeader);
209 }
210 return NULL;
211}
212
213void VBoxSHGSMICommandFree(PVBOXSHGSMI pHeap, void *pvBuffer)
214{
215 PVBOXSHGSMIHEADER pHeader = VBoxSHGSMIBufferHeader(pvBuffer);
216 vboxSHGSMICommandRelease (pHeap, pHeader);
217}
218
219#define VBOXSHGSMI_CMD2LISTENTRY(_pCmd) ((PVBOXVTLIST_ENTRY)&(_pCmd)->pvNext)
220#define VBOXSHGSMI_LISTENTRY2CMD(_pEntry) ( (PVBOXSHGSMIHEADER)((uint8_t *)(_pEntry) - RT_OFFSETOF(VBOXSHGSMIHEADER, pvNext)) )
221
222int VBoxSHGSMICommandProcessCompletion (PVBOXSHGSMI pHeap, VBOXSHGSMIHEADER* pCur, bool bIrq, PVBOXVTLIST pPostProcessList)
223{
224 int rc = VINF_SUCCESS;
225
226 do
227 {
228 if (pCur->fFlags & VBOXSHGSMI_FLAG_GH_ASYNCH_CALLBACK_IRQ)
229 {
230 Assert(bIrq);
231
232 PFNVBOXSHGSMICMDCOMPLETION pfnCompletion = NULL;
233 void *pvCompletion;
234 PFNVBOXSHGSMICMDCOMPLETION_IRQ pfnCallback = (PFNVBOXSHGSMICMDCOMPLETION_IRQ)pCur->u64Info1;
235 void *pvCallback = (void*)pCur->u64Info2;
236
237 pfnCompletion = pfnCallback(pHeap, VBoxSHGSMIBufferData(pCur), pvCallback, &pvCompletion);
238 if (pfnCompletion)
239 {
240 pCur->u64Info1 = (uint64_t)pfnCompletion;
241 pCur->u64Info2 = (uint64_t)pvCompletion;
242 pCur->fFlags &= ~VBOXSHGSMI_FLAG_GH_ASYNCH_CALLBACK_IRQ;
243 }
244 else
245 {
246 /* nothing to do with this command */
247 break;
248 }
249 }
250
251 if (!bIrq)
252 {
253 PFNVBOXSHGSMICMDCOMPLETION pfnCallback = (PFNVBOXSHGSMICMDCOMPLETION)pCur->u64Info1;
254 void *pvCallback = (void*)pCur->u64Info2;
255 pfnCallback(pHeap, VBoxSHGSMIBufferData(pCur), pvCallback);
256 }
257 else
258 vboxVtListPut(pPostProcessList, VBOXSHGSMI_CMD2LISTENTRY(pCur), VBOXSHGSMI_CMD2LISTENTRY(pCur));
259 } while (0);
260
261
262 return rc;
263}
264
265int VBoxSHGSMICommandPostprocessCompletion (PVBOXSHGSMI pHeap, PVBOXVTLIST pPostProcessList)
266{
267 PVBOXVTLIST_ENTRY pNext, pCur;
268 for (pCur = pPostProcessList->pFirst; pCur; pCur = pNext)
269 {
270 /* need to save next since the command may be released in a pfnCallback and thus its data might be invalid */
271 pNext = pCur->pNext;
272 PVBOXSHGSMIHEADER pCmd = VBOXSHGSMI_LISTENTRY2CMD(pCur);
273 PFNVBOXSHGSMICMDCOMPLETION pfnCallback = (PFNVBOXSHGSMICMDCOMPLETION)pCmd->u64Info1;
274 void *pvCallback = (void*)pCmd->u64Info2;
275 pfnCallback(pHeap, VBoxSHGSMIBufferData(pCmd), pvCallback);
276 }
277
278 return VINF_SUCCESS;
279}
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