VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/Graphics/Miniport/wddm/VBoxVideoShgsmi.cpp@ 33890

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

wddm/3d: chromium hgsmi fixes

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.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
13#include "../VBoxVideo.h"
14#include "../Helper.h"
15
16#include <VBox/VBoxGuestLib.h>
17#include <VBox/VBoxVideo.h>
18
19#include <iprt/asm.h>
20#include <iprt/semaphore.h>
21
22#include "VBoxVideoShgsmi.h"
23
24
25/* SHGSMI */
26DECLINLINE(void) vboxSHGSMICommandRetain (PVBOXSHGSMIHEADER pCmd)
27{
28 ASMAtomicIncU32(&pCmd->cRefs);
29}
30
31void vboxSHGSMICommandFree (struct _HGSMIHEAP * pHeap, PVBOXSHGSMIHEADER pCmd)
32{
33 HGSMIHeapFree (pHeap, pCmd);
34}
35
36DECLINLINE(void) vboxSHGSMICommandRelease (struct _HGSMIHEAP * pHeap, PVBOXSHGSMIHEADER pCmd)
37{
38 uint32_t cRefs = ASMAtomicDecU32(&pCmd->cRefs);
39 Assert(cRefs < UINT32_MAX / 2);
40 if(!cRefs)
41 vboxSHGSMICommandFree (pHeap, pCmd);
42}
43
44DECLCALLBACK(void) vboxSHGSMICompletionSetEvent(struct _HGSMIHEAP * pHeap, void *pvCmd, void *pvContext)
45{
46 RTSemEventSignal((RTSEMEVENT)pvContext);
47}
48
49DECLCALLBACK(void) vboxSHGSMICompletionCommandRelease(struct _HGSMIHEAP * pHeap, void *pvCmd, void *pvContext)
50{
51 vboxSHGSMICommandRelease (pHeap, VBoxSHGSMIBufferHeader(pvCmd));
52}
53
54/* do not wait for completion */
55DECLINLINE(const VBOXSHGSMIHEADER*) vboxSHGSMICommandPrepAsynch (struct _HGSMIHEAP * pHeap, PVBOXSHGSMIHEADER pHeader)
56{
57 /* ensure the command is not removed until we're processing it */
58 vboxSHGSMICommandRetain(pHeader);
59 return pHeader;
60}
61
62DECLINLINE(void) vboxSHGSMICommandDoneAsynch (struct _HGSMIHEAP * pHeap, const VBOXSHGSMIHEADER* pHeader)
63{
64 if(!(ASMAtomicReadU32((volatile uint32_t *)&pHeader->fFlags) & VBOXSHGSMI_FLAG_HG_ASYNCH))
65 {
66 PFNVBOXSHGSMICMDCOMPLETION pfnCompletion = (PFNVBOXSHGSMICMDCOMPLETION)pHeader->u64Info1;
67 if (pfnCompletion)
68 pfnCompletion(pHeap, VBoxSHGSMIBufferData (pHeader), (PVOID)pHeader->u64Info2);
69 }
70
71 vboxSHGSMICommandRelease(pHeap, (PVBOXSHGSMIHEADER)pHeader);
72}
73
74const VBOXSHGSMIHEADER* VBoxSHGSMICommandPrepAsynchEvent (struct _HGSMIHEAP * pHeap, PVOID pvBuff, RTSEMEVENT hEventSem)
75{
76 PVBOXSHGSMIHEADER pHeader = VBoxSHGSMIBufferHeader (pvBuff);
77 pHeader->u64Info1 = (uint64_t)vboxSHGSMICompletionSetEvent;
78 pHeader->u64Info2 = (uint64_t)hEventSem;
79 pHeader->fFlags = VBOXSHGSMI_FLAG_GH_ASYNCH_IRQ;
80
81 return vboxSHGSMICommandPrepAsynch (pHeap, pHeader);
82}
83
84const VBOXSHGSMIHEADER* VBoxSHGSMICommandPrepSynch (struct _HGSMIHEAP * pHeap, PVOID pCmd)
85{
86 RTSEMEVENT hEventSem;
87 int rc = RTSemEventCreate(&hEventSem);
88 Assert(RT_SUCCESS(rc));
89 if (RT_SUCCESS(rc))
90 {
91 return VBoxSHGSMICommandPrepAsynchEvent (pHeap, pCmd, hEventSem);
92 }
93 return NULL;
94}
95
96void VBoxSHGSMICommandDoneAsynch (struct _HGSMIHEAP * pHeap, const VBOXSHGSMIHEADER * pHeader)
97{
98 vboxSHGSMICommandDoneAsynch(pHeap, pHeader);
99}
100
101int VBoxSHGSMICommandDoneSynch (struct _HGSMIHEAP * pHeap, const VBOXSHGSMIHEADER* pHeader)
102{
103 VBoxSHGSMICommandDoneAsynch (pHeap, pHeader);
104 RTSEMEVENT hEventSem = (RTSEMEVENT)pHeader->u64Info2;
105 int rc = RTSemEventWait(hEventSem, RT_INDEFINITE_WAIT);
106 AssertRC(rc);
107 if (RT_SUCCESS(rc))
108 RTSemEventDestroy(hEventSem);
109 return rc;
110}
111
112void VBoxSHGSMICommandCancelAsynch (struct _HGSMIHEAP * pHeap, const VBOXSHGSMIHEADER* pHeader)
113{
114 vboxSHGSMICommandRelease(pHeap, (PVBOXSHGSMIHEADER)pHeader);
115}
116
117void VBoxSHGSMICommandCancelSynch (struct _HGSMIHEAP * pHeap, const VBOXSHGSMIHEADER* pHeader)
118{
119 VBoxSHGSMICommandCancelAsynch (pHeap, pHeader);
120 RTSEMEVENT hEventSem = (RTSEMEVENT)pHeader->u64Info2;
121 RTSemEventDestroy(hEventSem);
122}
123
124const VBOXSHGSMIHEADER* VBoxSHGSMICommandPrepAsynch (struct _HGSMIHEAP * pHeap, PVOID pvBuff, PFNVBOXSHGSMICMDCOMPLETION pfnCompletion, PVOID pvCompletion, uint32_t fFlags)
125{
126 fFlags &= ~VBOXSHGSMI_FLAG_GH_ASYNCH_CALLBACK_IRQ;
127 PVBOXSHGSMIHEADER pHeader = VBoxSHGSMIBufferHeader (pvBuff);
128 pHeader->u64Info1 = (uint64_t)pfnCompletion;
129 pHeader->u64Info2 = (uint64_t)pvCompletion;
130 pHeader->fFlags = fFlags;
131
132 return vboxSHGSMICommandPrepAsynch (pHeap, pHeader);
133}
134
135const VBOXSHGSMIHEADER* VBoxSHGSMICommandPrepAsynchIrq (struct _HGSMIHEAP * pHeap, PVOID pvBuff, PFNVBOXSHGSMICMDCOMPLETION_IRQ pfnCompletion, PVOID pvCompletion, uint32_t fFlags)
136{
137 fFlags |= VBOXSHGSMI_FLAG_GH_ASYNCH_CALLBACK_IRQ | VBOXSHGSMI_FLAG_GH_ASYNCH_IRQ;
138 PVBOXSHGSMIHEADER pHeader = VBoxSHGSMIBufferHeader (pvBuff);
139 pHeader->u64Info1 = (uint64_t)pfnCompletion;
140 pHeader->u64Info2 = (uint64_t)pvCompletion;
141 /* we must assign rather than or because flags field does not get zeroed on command creation */
142 pHeader->fFlags = fFlags;
143
144 return vboxSHGSMICommandPrepAsynch (pHeap, pHeader);
145}
146
147void* VBoxSHGSMICommandAlloc (struct _HGSMIHEAP * pHeap, HGSMISIZE cbData, uint8_t u8Channel, uint16_t u16ChannelInfo)
148{
149 /* Issue the flush command. */
150 PVBOXSHGSMIHEADER pHeader = (PVBOXSHGSMIHEADER)HGSMIHeapAlloc (pHeap, cbData + sizeof (VBOXSHGSMIHEADER), u8Channel, u16ChannelInfo);
151 Assert(pHeader);
152 if (pHeader)
153 {
154 pHeader->cRefs = 1;
155 return VBoxSHGSMIBufferData(pHeader);
156 }
157 return NULL;
158}
159
160void VBoxSHGSMICommandFree (struct _HGSMIHEAP * pHeap, void *pvBuffer)
161{
162 PVBOXSHGSMIHEADER pHeader = VBoxSHGSMIBufferHeader(pvBuffer);
163 vboxSHGSMICommandRelease (pHeap, pHeader);
164}
165
166//int VBoxSHGSMISetup (PVBOXSHGSMIHEAP pHeap,
167// void *pvBase,
168// HGSMISIZE cbArea,
169// HGSMIOFFSET offBase,
170// bool fOffsetBased,
171// PFNVBOXSHGSMINOTIFYHOST pfnNotifyHost,
172// PFNVBOXSHGSMINOTIFYHOST pvNotifyHost)
173//{
174// /* Setup a HGSMI heap within the adapter information area. */
175// return HGSMIHeapSetup (&pHeap->Heap,
176// pvBuffer,
177// cbBuffer,
178// offBuffer,
179// false /*fOffsetBased*/);
180//}
181//
182//int VBoxSHGSMIDestroy (PVBOXSHGSMIHEAP pHeap)
183//{
184// HGSMIHeapDestroy (pHeap);
185// return VINF_SUCCESS;
186//}
187
188#define VBOXSHGSMI_CMD2LISTENTRY(_pCmd) ((PVBOXSHGSMILIST_ENTRY)&(_pCmd)->pvNext)
189#define VBOXSHGSMI_LISTENTRY2CMD(_pEntry) ( (PVBOXSHGSMIHEADER)((uint8_t *)(_pEntry) - RT_OFFSETOF(VBOXSHGSMIHEADER, pvNext)) )
190
191int VBoxSHGSMICommandProcessCompletion (struct _HGSMIHEAP * pHeap, VBOXSHGSMIHEADER* pCur, bool bIrq, PVBOXSHGSMILIST pPostProcessList)
192{
193 int rc = VINF_SUCCESS;
194
195 do
196 {
197 if (pCur->fFlags & VBOXSHGSMI_FLAG_GH_ASYNCH_CALLBACK_IRQ)
198 {
199 Assert(bIrq);
200
201 PFNVBOXSHGSMICMDCOMPLETION pfnCompletion = NULL;
202 void *pvCompletion;
203 PFNVBOXSHGSMICMDCOMPLETION_IRQ pfnCallback = (PFNVBOXSHGSMICMDCOMPLETION_IRQ)pCur->u64Info1;
204 void *pvCallback = (void*)pCur->u64Info2;
205
206 pfnCallback(pHeap, VBoxSHGSMIBufferData(pCur), pvCallback, &pfnCompletion, &pvCompletion);
207 if (pfnCompletion)
208 {
209 pCur->u64Info1 = (uint64_t)pfnCompletion;
210 pCur->u64Info2 = (uint64_t)pvCompletion;
211 pCur->fFlags &= ~VBOXSHGSMI_FLAG_GH_ASYNCH_CALLBACK_IRQ;
212 }
213 else
214 {
215 /* nothing to do with this command */
216 break;
217 }
218 }
219
220 if (!bIrq)
221 {
222 PFNVBOXSHGSMICMDCOMPLETION pfnCallback = (PFNVBOXSHGSMICMDCOMPLETION)pCur->u64Info1;
223 void *pvCallback = (void*)pCur->u64Info2;
224 pfnCallback(pHeap, VBoxSHGSMIBufferData(pCur), pvCallback);
225 }
226 else
227 vboxSHGSMIListPut(pPostProcessList, VBOXSHGSMI_CMD2LISTENTRY(pCur), VBOXSHGSMI_CMD2LISTENTRY(pCur));
228 } while (0);
229
230
231 return rc;
232}
233
234int VBoxSHGSMICommandPostprocessCompletion (struct _HGSMIHEAP * pHeap, PVBOXSHGSMILIST pPostProcessList)
235{
236 PVBOXSHGSMILIST_ENTRY pNext, pCur;
237 for (pCur = pPostProcessList->pFirst; pCur; pCur = pNext)
238 {
239 /* need to save next since the command may be released in a pfnCallback and thus its data might be invalid */
240 pNext = pCur->pNext;
241 PVBOXSHGSMIHEADER pCmd = VBOXSHGSMI_LISTENTRY2CMD(pCur);
242 PFNVBOXSHGSMICMDCOMPLETION pfnCallback = (PFNVBOXSHGSMICMDCOMPLETION)pCmd->u64Info1;
243 void *pvCallback = (void*)pCmd->u64Info2;
244 pfnCallback(pHeap, VBoxSHGSMIBufferData(pCmd), pvCallback);
245 }
246
247 return VINF_SUCCESS;
248}
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