VirtualBox

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

Last change on this file since 32891 was 29742, checked in by vboxsync, 15 years ago

wddm/2D: more impl (get caps + initialization working)

  • 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 pfnCompletion(pHeap, VBoxSHGSMIBufferData (pHeader), (PVOID)pHeader->u64Info2);
68 }
69
70 vboxSHGSMICommandRelease(pHeap, (PVBOXSHGSMIHEADER)pHeader);
71}
72
73const VBOXSHGSMIHEADER* VBoxSHGSMICommandPrepAsynchEvent (struct _HGSMIHEAP * pHeap, PVOID pvBuff, RTSEMEVENT hEventSem)
74{
75 PVBOXSHGSMIHEADER pHeader = VBoxSHGSMIBufferHeader (pvBuff);
76 pHeader->u64Info1 = (uint64_t)vboxSHGSMICompletionSetEvent;
77 pHeader->u64Info2 = (uint64_t)hEventSem;
78 pHeader->fFlags = VBOXSHGSMI_FLAG_GH_ASYNCH_IRQ;
79
80 return vboxSHGSMICommandPrepAsynch (pHeap, pHeader);
81}
82
83const VBOXSHGSMIHEADER* VBoxSHGSMICommandPrepSynch (struct _HGSMIHEAP * pHeap, PVOID pCmd)
84{
85 RTSEMEVENT hEventSem;
86 int rc = RTSemEventCreate(&hEventSem);
87 Assert(RT_SUCCESS(rc));
88 if (RT_SUCCESS(rc))
89 {
90 return VBoxSHGSMICommandPrepAsynchEvent (pHeap, pCmd, hEventSem);
91 }
92 return NULL;
93}
94
95void VBoxSHGSMICommandDoneAsynch (struct _HGSMIHEAP * pHeap, const VBOXSHGSMIHEADER * pHeader)
96{
97 vboxSHGSMICommandDoneAsynch(pHeap, pHeader);
98}
99
100int VBoxSHGSMICommandDoneSynch (struct _HGSMIHEAP * pHeap, const VBOXSHGSMIHEADER* pHeader)
101{
102 VBoxSHGSMICommandDoneAsynch (pHeap, pHeader);
103 RTSEMEVENT hEventSem = (RTSEMEVENT)pHeader->u64Info2;
104 int rc = RTSemEventWait(hEventSem, RT_INDEFINITE_WAIT);
105 AssertRC(rc);
106 if (RT_SUCCESS(rc))
107 RTSemEventDestroy(hEventSem);
108 return rc;
109}
110
111void VBoxSHGSMICommandCancelAsynch (struct _HGSMIHEAP * pHeap, const VBOXSHGSMIHEADER* pHeader)
112{
113 vboxSHGSMICommandRelease(pHeap, (PVBOXSHGSMIHEADER)pHeader);
114}
115
116void VBoxSHGSMICommandCancelSynch (struct _HGSMIHEAP * pHeap, const VBOXSHGSMIHEADER* pHeader)
117{
118 VBoxSHGSMICommandCancelAsynch (pHeap, pHeader);
119 RTSEMEVENT hEventSem = (RTSEMEVENT)pHeader->u64Info2;
120 RTSemEventDestroy(hEventSem);
121}
122
123const VBOXSHGSMIHEADER* VBoxSHGSMICommandPrepAsynch (struct _HGSMIHEAP * pHeap, PVOID pvBuff, PFNVBOXSHGSMICMDCOMPLETION pfnCompletion, PVOID pvCompletion, uint32_t fFlags)
124{
125 fFlags &= ~VBOXSHGSMI_FLAG_GH_ASYNCH_CALLBACK_IRQ;
126 PVBOXSHGSMIHEADER pHeader = VBoxSHGSMIBufferHeader (pvBuff);
127 pHeader->u64Info1 = (uint64_t)pfnCompletion;
128 pHeader->u64Info2 = (uint64_t)pvCompletion;
129 pHeader->fFlags = fFlags;
130
131 return vboxSHGSMICommandPrepAsynch (pHeap, pHeader);
132}
133
134const VBOXSHGSMIHEADER* VBoxSHGSMICommandPrepAsynchIrq (struct _HGSMIHEAP * pHeap, PVOID pvBuff, PFNVBOXSHGSMICMDCOMPLETION_IRQ pfnCompletion, PVOID pvCompletion, uint32_t fFlags)
135{
136 fFlags |= VBOXSHGSMI_FLAG_GH_ASYNCH_CALLBACK_IRQ | VBOXSHGSMI_FLAG_GH_ASYNCH_IRQ;
137 PVBOXSHGSMIHEADER pHeader = VBoxSHGSMIBufferHeader (pvBuff);
138 pHeader->u64Info1 = (uint64_t)pfnCompletion;
139 pHeader->u64Info2 = (uint64_t)pvCompletion;
140 /* we must assign rather than or because flags field does not get zeroed on command creation */
141 pHeader->fFlags = fFlags;
142
143 return vboxSHGSMICommandPrepAsynch (pHeap, pHeader);
144}
145
146void* VBoxSHGSMICommandAlloc (struct _HGSMIHEAP * pHeap, HGSMISIZE cbData, uint8_t u8Channel, uint16_t u16ChannelInfo)
147{
148 /* Issue the flush command. */
149 PVBOXSHGSMIHEADER pHeader = (PVBOXSHGSMIHEADER)HGSMIHeapAlloc (pHeap, cbData + sizeof (VBOXSHGSMIHEADER), u8Channel, u16ChannelInfo);
150 Assert(pHeader);
151 if (pHeader)
152 {
153 pHeader->cRefs = 1;
154 return VBoxSHGSMIBufferData(pHeader);
155 }
156 return NULL;
157}
158
159void VBoxSHGSMICommandFree (struct _HGSMIHEAP * pHeap, void *pvBuffer)
160{
161 PVBOXSHGSMIHEADER pHeader = VBoxSHGSMIBufferHeader(pvBuffer);
162 vboxSHGSMICommandRelease (pHeap, pHeader);
163}
164
165//int VBoxSHGSMISetup (PVBOXSHGSMIHEAP pHeap,
166// void *pvBase,
167// HGSMISIZE cbArea,
168// HGSMIOFFSET offBase,
169// bool fOffsetBased,
170// PFNVBOXSHGSMINOTIFYHOST pfnNotifyHost,
171// PFNVBOXSHGSMINOTIFYHOST pvNotifyHost)
172//{
173// /* Setup a HGSMI heap within the adapter information area. */
174// return HGSMIHeapSetup (&pHeap->Heap,
175// pvBuffer,
176// cbBuffer,
177// offBuffer,
178// false /*fOffsetBased*/);
179//}
180//
181//int VBoxSHGSMIDestroy (PVBOXSHGSMIHEAP pHeap)
182//{
183// HGSMIHeapDestroy (pHeap);
184// return VINF_SUCCESS;
185//}
186
187#define VBOXSHGSMI_CMD2LISTENTRY(_pCmd) ((PVBOXSHGSMILIST_ENTRY)&(_pCmd)->pvNext)
188#define VBOXSHGSMI_LISTENTRY2CMD(_pEntry) ( (PVBOXSHGSMIHEADER)((uint8_t *)(_pEntry) - RT_OFFSETOF(VBOXSHGSMIHEADER, pvNext)) )
189
190int VBoxSHGSMICommandProcessCompletion (struct _HGSMIHEAP * pHeap, VBOXSHGSMIHEADER* pCur, bool bIrq, PVBOXSHGSMILIST pPostProcessList)
191{
192 int rc = VINF_SUCCESS;
193
194 do
195 {
196 if (pCur->fFlags & VBOXSHGSMI_FLAG_GH_ASYNCH_CALLBACK_IRQ)
197 {
198 Assert(bIrq);
199
200 PFNVBOXSHGSMICMDCOMPLETION pfnCompletion = NULL;
201 void *pvCompletion;
202 PFNVBOXSHGSMICMDCOMPLETION_IRQ pfnCallback = (PFNVBOXSHGSMICMDCOMPLETION_IRQ)pCur->u64Info1;
203 void *pvCallback = (void*)pCur->u64Info2;
204
205 pfnCallback(pHeap, VBoxSHGSMIBufferData(pCur), pvCallback, &pfnCompletion, &pvCompletion);
206 if (pfnCompletion)
207 {
208 pCur->u64Info1 = (uint64_t)pfnCompletion;
209 pCur->u64Info2 = (uint64_t)pvCompletion;
210 pCur->fFlags &= ~VBOXSHGSMI_FLAG_GH_ASYNCH_CALLBACK_IRQ;
211 }
212 else
213 {
214 /* nothing to do with this command */
215 break;
216 }
217 }
218
219 if (!bIrq)
220 {
221 PFNVBOXSHGSMICMDCOMPLETION pfnCallback = (PFNVBOXSHGSMICMDCOMPLETION)pCur->u64Info1;
222 void *pvCallback = (void*)pCur->u64Info2;
223 pfnCallback(pHeap, VBoxSHGSMIBufferData(pCur), pvCallback);
224 }
225 else
226 vboxSHGSMIListPut(pPostProcessList, VBOXSHGSMI_CMD2LISTENTRY(pCur), VBOXSHGSMI_CMD2LISTENTRY(pCur));
227 } while (0);
228
229
230 return rc;
231}
232
233int VBoxSHGSMICommandPostprocessCompletion (struct _HGSMIHEAP * pHeap, PVBOXSHGSMILIST pPostProcessList)
234{
235 PVBOXSHGSMILIST_ENTRY pNext, pCur;
236 for (pCur = pPostProcessList->pFirst; pCur; pCur = pNext)
237 {
238 /* need to save next since the command may be released in a pfnCallback and thus its data might be invalid */
239 pNext = pCur->pNext;
240 PVBOXSHGSMIHEADER pCmd = VBOXSHGSMI_LISTENTRY2CMD(pCur);
241 PFNVBOXSHGSMICMDCOMPLETION pfnCallback = (PFNVBOXSHGSMICMDCOMPLETION)pCmd->u64Info1;
242 void *pvCallback = (void*)pCmd->u64Info2;
243 pfnCallback(pHeap, VBoxSHGSMIBufferData(pCmd), pvCallback);
244 }
245
246 return VINF_SUCCESS;
247}
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