VirtualBox

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

Last change on this file since 41379 was 41109, checked in by vboxsync, 13 years ago

crOpenGL,wined3d,wddm: second part of fixing resource leakage, basics for cr commands submission from r0 miniport driver (for r0 visible region reporting, WPF 3D rendering fixes w/o Aero, etc.)

  • 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 41109 2012-05-02 08:37:46Z 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 <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
41DECLCALLBACK(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, bool fOffsetBased)
189{
190 KeInitializeSpinLock(&pHeap->HeapLock);
191 return HGSMIHeapSetup(&pHeap->Heap, pvBase, cbArea, offBase, fOffsetBased);
192}
193
194void VBoxSHGSMITerm(PVBOXSHGSMI pHeap)
195{
196 HGSMIHeapDestroy(&pHeap->Heap);
197}
198
199void* VBoxSHGSMICommandAlloc(PVBOXSHGSMI pHeap, HGSMISIZE cbData, uint8_t u8Channel, uint16_t u16ChannelInfo)
200{
201 /* Issue the flush command. */
202 PVBOXSHGSMIHEADER pHeader = (PVBOXSHGSMIHEADER)VBoxSHGSMIHeapAlloc(pHeap, cbData + sizeof (VBOXSHGSMIHEADER), u8Channel, u16ChannelInfo);
203 Assert(pHeader);
204 if (pHeader)
205 {
206 pHeader->cRefs = 1;
207 return VBoxSHGSMIBufferData(pHeader);
208 }
209 return NULL;
210}
211
212void VBoxSHGSMICommandFree(PVBOXSHGSMI pHeap, void *pvBuffer)
213{
214 PVBOXSHGSMIHEADER pHeader = VBoxSHGSMIBufferHeader(pvBuffer);
215 vboxSHGSMICommandRelease (pHeap, pHeader);
216}
217
218#define VBOXSHGSMI_CMD2LISTENTRY(_pCmd) ((PVBOXVTLIST_ENTRY)&(_pCmd)->pvNext)
219#define VBOXSHGSMI_LISTENTRY2CMD(_pEntry) ( (PVBOXSHGSMIHEADER)((uint8_t *)(_pEntry) - RT_OFFSETOF(VBOXSHGSMIHEADER, pvNext)) )
220
221int VBoxSHGSMICommandProcessCompletion (PVBOXSHGSMI pHeap, VBOXSHGSMIHEADER* pCur, bool bIrq, PVBOXVTLIST pPostProcessList)
222{
223 int rc = VINF_SUCCESS;
224
225 do
226 {
227 if (pCur->fFlags & VBOXSHGSMI_FLAG_GH_ASYNCH_CALLBACK_IRQ)
228 {
229 Assert(bIrq);
230
231 PFNVBOXSHGSMICMDCOMPLETION pfnCompletion = NULL;
232 void *pvCompletion;
233 PFNVBOXSHGSMICMDCOMPLETION_IRQ pfnCallback = (PFNVBOXSHGSMICMDCOMPLETION_IRQ)pCur->u64Info1;
234 void *pvCallback = (void*)pCur->u64Info2;
235
236 pfnCallback(pHeap, VBoxSHGSMIBufferData(pCur), pvCallback, &pfnCompletion, &pvCompletion);
237 if (pfnCompletion)
238 {
239 pCur->u64Info1 = (uint64_t)pfnCompletion;
240 pCur->u64Info2 = (uint64_t)pvCompletion;
241 pCur->fFlags &= ~VBOXSHGSMI_FLAG_GH_ASYNCH_CALLBACK_IRQ;
242 }
243 else
244 {
245 /* nothing to do with this command */
246 break;
247 }
248 }
249
250 if (!bIrq)
251 {
252 PFNVBOXSHGSMICMDCOMPLETION pfnCallback = (PFNVBOXSHGSMICMDCOMPLETION)pCur->u64Info1;
253 void *pvCallback = (void*)pCur->u64Info2;
254 pfnCallback(pHeap, VBoxSHGSMIBufferData(pCur), pvCallback);
255 }
256 else
257 vboxVtListPut(pPostProcessList, VBOXSHGSMI_CMD2LISTENTRY(pCur), VBOXSHGSMI_CMD2LISTENTRY(pCur));
258 } while (0);
259
260
261 return rc;
262}
263
264int VBoxSHGSMICommandPostprocessCompletion (PVBOXSHGSMI pHeap, PVBOXVTLIST pPostProcessList)
265{
266 PVBOXVTLIST_ENTRY pNext, pCur;
267 for (pCur = pPostProcessList->pFirst; pCur; pCur = pNext)
268 {
269 /* need to save next since the command may be released in a pfnCallback and thus its data might be invalid */
270 pNext = pCur->pNext;
271 PVBOXSHGSMIHEADER pCmd = VBOXSHGSMI_LISTENTRY2CMD(pCur);
272 PFNVBOXSHGSMICMDCOMPLETION pfnCallback = (PFNVBOXSHGSMICMDCOMPLETION)pCmd->u64Info1;
273 void *pvCallback = (void*)pCmd->u64Info2;
274 pfnCallback(pHeap, VBoxSHGSMIBufferData(pCmd), pvCallback);
275 }
276
277 return VINF_SUCCESS;
278}
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