VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/Graphics/Display/wddm/VBoxDispCm.cpp@ 33929

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

wddm: fix guest misbehave on driver update, bugfixing

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.9 KB
Line 
1/** @file
2 *
3 * VBoxVideo Display D3D User mode dll
4 *
5 * Copyright (C) 2010 Oracle Corporation
6 *
7 * This file is part of VirtualBox Open Source Edition (OSE), as
8 * available from http://www.virtualbox.org. This file is free software;
9 * you can redistribute it and/or modify it under the terms of the GNU
10 * General Public License (GPL) as published by the Free Software
11 * Foundation, in version 2 as it comes in the "COPYING" file of the
12 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
13 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
14 */
15#include "VBoxDispD3DCmn.h"
16#include "VBoxDispD3D.h"
17#include "../../../include/VBoxDisplay.h"
18
19#include <iprt/list.h>
20
21
22typedef struct VBOXDISPCM_SESSION
23{
24 HANDLE hEvent;
25 CRITICAL_SECTION CritSect;
26 RTLISTNODE CtxList;
27 bool bQueryMp;
28} VBOXDISPCM_SESSION, *PVBOXDISPCM_SESSION;
29
30typedef struct VBOXDISPCM_MGR
31{
32 VBOXDISPCM_SESSION Session;
33} VBOXDISPCM_MGR, *PVBOXDISPCM_MGR;
34
35/* the cm is one per process */
36static VBOXDISPCM_MGR g_pVBoxCmMgr;
37
38HRESULT vboxDispCmSessionTerm(PVBOXDISPCM_SESSION pSession)
39{
40 Assert(RTListIsEmpty(&pSession->CtxList));
41 BOOL bRc = CloseHandle(pSession->hEvent);
42 Assert(bRc);
43 if (bRc)
44 {
45 DeleteCriticalSection(&pSession->CritSect);
46 return S_OK;
47 }
48 DWORD winEr = GetLastError();
49 HRESULT hr = HRESULT_FROM_WIN32(winEr);
50 return hr;
51}
52
53HRESULT vboxDispCmSessionInit(PVBOXDISPCM_SESSION pSession)
54{
55 HANDLE hEvent = CreateEvent(NULL,
56 FALSE, /* BOOL bManualReset */
57 FALSE, /* BOOL bInitialState */
58 NULL /* LPCTSTR lpName */
59 );
60 Assert(hEvent);
61 if (hEvent)
62 {
63 pSession->hEvent = hEvent;
64 InitializeCriticalSection(&pSession->CritSect);
65 RTListInit(&pSession->CtxList);
66 pSession->bQueryMp = false;
67 return S_OK;
68 }
69 DWORD winEr = GetLastError();
70 HRESULT hr = HRESULT_FROM_WIN32(winEr);
71 return hr;
72}
73
74void vboxDispCmSessionCtxAdd(PVBOXDISPCM_SESSION pSession, PVBOXWDDMDISP_CONTEXT pContext)
75{
76 EnterCriticalSection(&pSession->CritSect);
77 RTListAppend(&pSession->CtxList, &pContext->ListNode);
78 LeaveCriticalSection(&pSession->CritSect);
79}
80
81void vboxDispCmSessionCtxRemoveLocked(PVBOXDISPCM_SESSION pSession, PVBOXWDDMDISP_CONTEXT pContext)
82{
83 RTListNodeRemove(&pContext->ListNode);
84}
85
86void vboxDispCmSessionCtxRemove(PVBOXDISPCM_SESSION pSession, PVBOXWDDMDISP_CONTEXT pContext)
87{
88 EnterCriticalSection(&pSession->CritSect);
89 vboxDispCmSessionCtxRemoveLocked(pSession, pContext);
90 LeaveCriticalSection(&pSession->CritSect);
91}
92
93HRESULT vboxDispCmInit()
94{
95 HRESULT hr = vboxDispCmSessionInit(&g_pVBoxCmMgr.Session);
96 Assert(hr == S_OK);
97 return hr;
98}
99
100HRESULT vboxDispCmTerm()
101{
102 HRESULT hr = vboxDispCmSessionTerm(&g_pVBoxCmMgr.Session);
103 Assert(hr == S_OK);
104 return hr;
105}
106
107HRESULT vboxDispCmCtxCreate(PVBOXWDDMDISP_DEVICE pDevice, PVBOXWDDMDISP_CONTEXT pContext)
108{
109 VBOXWDDM_CREATECONTEXT_INFO Info;
110 Info.u32IfVersion = pDevice->u32IfVersion;
111 Info.enmType = VBOXDISPMODE_IS_3D(pDevice->pAdapter) ? VBOXWDDM_CONTEXT_TYPE_CUSTOM_3D : VBOXWDDM_CONTEXT_TYPE_CUSTOM_2D;
112 Info.hUmEvent = (uint64_t)g_pVBoxCmMgr.Session.hEvent;
113 Info.u64UmInfo = (uint64_t)pContext;
114
115 pContext->ContextInfo.NodeOrdinal = 0;
116 pContext->ContextInfo.EngineAffinity = 0;
117 pContext->ContextInfo.Flags.Value = 0;
118 pContext->ContextInfo.pPrivateDriverData = &Info;
119 pContext->ContextInfo.PrivateDriverDataSize = sizeof (Info);
120 pContext->ContextInfo.hContext = 0;
121 pContext->ContextInfo.pCommandBuffer = NULL;
122 pContext->ContextInfo.CommandBufferSize = 0;
123 pContext->ContextInfo.pAllocationList = NULL;
124 pContext->ContextInfo.AllocationListSize = 0;
125 pContext->ContextInfo.pPatchLocationList = NULL;
126 pContext->ContextInfo.PatchLocationListSize = 0;
127
128 HRESULT hr = S_OK;
129 hr = pDevice->RtCallbacks.pfnCreateContextCb(pDevice->hDevice, &pContext->ContextInfo);
130 Assert(hr == S_OK);
131 if (hr == S_OK)
132 {
133 Assert(pContext->ContextInfo.hContext);
134 pContext->ContextInfo.pPrivateDriverData = NULL;
135 pContext->ContextInfo.PrivateDriverDataSize = 0;
136 vboxDispCmSessionCtxAdd(&g_pVBoxCmMgr.Session, pContext);
137 pContext->pDevice = pDevice;
138 }
139 else
140 {
141 exit(1);
142 }
143
144 return hr;
145}
146
147HRESULT vboxDispCmSessionCtxDestroy(PVBOXDISPCM_SESSION pSession, PVBOXWDDMDISP_DEVICE pDevice, PVBOXWDDMDISP_CONTEXT pContext)
148{
149 EnterCriticalSection(&pSession->CritSect);
150 Assert(pContext->ContextInfo.hContext);
151 D3DDDICB_DESTROYCONTEXT DestroyContext;
152 Assert(pDevice->DefaultContext.ContextInfo.hContext);
153 DestroyContext.hContext = pDevice->DefaultContext.ContextInfo.hContext;
154 HRESULT hr = pDevice->RtCallbacks.pfnDestroyContextCb(pDevice->hDevice, &DestroyContext);
155 Assert(hr == S_OK);
156 if (hr == S_OK)
157 {
158 vboxDispCmSessionCtxRemoveLocked(pSession, pContext);
159 }
160 LeaveCriticalSection(&pSession->CritSect);
161 return hr;
162}
163
164HRESULT vboxDispCmCtxDestroy(PVBOXWDDMDISP_DEVICE pDevice, PVBOXWDDMDISP_CONTEXT pContext)
165{
166 return vboxDispCmSessionCtxDestroy(&g_pVBoxCmMgr.Session, pDevice, pContext);
167}
168
169static HRESULT vboxDispCmSessionCmdQueryData(PVBOXDISPCM_SESSION pSession, PVBOXDISPIFESCAPE_GETVBOXVIDEOCMCMD pCmd, uint32_t cbCmd)
170{
171
172 HRESULT hr = S_OK;
173 D3DDDICB_ESCAPE DdiEscape;
174 DdiEscape.Flags.Value = 0;
175 DdiEscape.pPrivateDriverData = pCmd;
176 DdiEscape.PrivateDriverDataSize = cbCmd;
177
178 pCmd->EscapeHdr.escapeCode = VBOXESC_GETVBOXVIDEOCMCMD;
179 /* lock to ensure the context is not destroyed */
180 EnterCriticalSection(&pSession->CritSect);
181 /* use any context for identifying the kernel CmSession. We're using the first one */
182 PVBOXWDDMDISP_CONTEXT pContext = RTListNodeGetFirst(&pSession->CtxList, VBOXWDDMDISP_CONTEXT, ListNode);
183 if (pContext)
184 {
185 PVBOXWDDMDISP_DEVICE pDevice = pContext->pDevice;
186 DdiEscape.hDevice = pDevice->hDevice;
187 DdiEscape.hContext = pContext->ContextInfo.hContext;
188 Assert (DdiEscape.hContext);
189 Assert (DdiEscape.hDevice);
190 hr = pDevice->RtCallbacks.pfnEscapeCb(pDevice->pAdapter->hAdapter, &DdiEscape);
191 LeaveCriticalSection(&pSession->CritSect);
192 Assert(hr == S_OK);
193 if (hr == S_OK)
194 {
195 if (!pCmd->Hdr.cbCmdsReturned && !pCmd->Hdr.cbRemainingFirstCmd)
196 hr = S_FALSE;
197 }
198 else
199 {
200 exit(1);
201 }
202 }
203 else
204 {
205 LeaveCriticalSection(&pSession->CritSect);
206 hr = S_FALSE;
207 }
208
209 return hr;
210}
211
212HRESULT vboxDispCmSessionCmdGet(PVBOXDISPCM_SESSION pSession, PVBOXDISPIFESCAPE_GETVBOXVIDEOCMCMD pCmd, uint32_t cbCmd, DWORD dwMilliseconds)
213{
214 Assert(cbCmd >= sizeof (VBOXDISPIFESCAPE_GETVBOXVIDEOCMCMD));
215 if (cbCmd < sizeof (VBOXDISPIFESCAPE_GETVBOXVIDEOCMCMD))
216 return E_INVALIDARG;
217
218 do
219 {
220
221 if (pSession->bQueryMp)
222 {
223 HRESULT hr = vboxDispCmSessionCmdQueryData(pSession, pCmd, cbCmd);
224 Assert(hr == S_OK || hr == S_FALSE);
225 if (hr == S_OK || hr != S_FALSE)
226 return hr;
227
228 pSession->bQueryMp = false;
229 }
230
231 DWORD dwResult = WaitForSingleObject(pSession->hEvent, dwMilliseconds);
232 switch(dwResult)
233 {
234 case WAIT_OBJECT_0:
235 {
236 pSession->bQueryMp = true;
237 break; /* <- query commands */
238 }
239 case WAIT_TIMEOUT:
240 {
241 Assert(!pSession->bQueryMp);
242 return WAIT_TIMEOUT;
243 }
244 default:
245 Assert(0);
246 return E_FAIL;
247 }
248 } while (1);
249
250 /* should never be here */
251 Assert(0);
252 return E_FAIL;
253}
254
255HRESULT vboxDispCmCmdGet(PVBOXDISPIFESCAPE_GETVBOXVIDEOCMCMD pCmd, uint32_t cbCmd, DWORD dwMilliseconds)
256{
257 return vboxDispCmSessionCmdGet(&g_pVBoxCmMgr.Session, pCmd, cbCmd, dwMilliseconds);
258}
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