VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/Graphics/Video/disp/wddm/VBoxDispMp.cpp@ 41374

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

wddm/3d/crogl: backdoor logging

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.1 KB
Line 
1/* $Id: VBoxDispMp.cpp 41374 2012-05-21 18:04:03Z vboxsync $ */
2
3/** @file
4 * VBoxVideo Display D3D User mode dll
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 "VBoxDispD3DCmn.h"
20#include "VBoxDispMp.h"
21
22#include <iprt/assert.h>
23
24typedef struct VBOXVIDEOCM_ITERATOR
25{
26 PVBOXVIDEOCM_CMD_HDR pCur;
27 uint32_t cbRemain;
28} VBOXVIDEOCM_ITERATOR, *PVBOXVIDEOCM_ITERATOR;
29
30typedef struct VBOXDISPMP
31{
32 CRITICAL_SECTION CritSect;
33 PVBOXDISPIFESCAPE_GETVBOXVIDEOCMCMD pEscapeCmd;
34 uint32_t cbEscapeCmd;
35 VBOXVIDEOCM_ITERATOR Iterator;
36} VBOXDISPMP, *PVBOXDISPMP;
37
38DECLINLINE(void) vboxVideoCmIterInit(PVBOXVIDEOCM_ITERATOR pIter, PVBOXVIDEOCM_CMD_HDR pStart, uint32_t cbCmds)
39{
40 pIter->pCur = pStart;
41 pIter->cbRemain= cbCmds;
42}
43
44DECLINLINE(PVBOXVIDEOCM_CMD_HDR) vboxVideoCmIterNext(PVBOXVIDEOCM_ITERATOR pIter)
45{
46 if (pIter->cbRemain)
47 {
48 PVBOXVIDEOCM_CMD_HDR pCur = pIter->pCur;
49 Assert(pIter->cbRemain >= pIter->pCur->cbCmd);
50 pIter->cbRemain -= pIter->pCur->cbCmd;
51 pIter->pCur = (PVBOXVIDEOCM_CMD_HDR)(((uint8_t*)pIter->pCur) + pIter->pCur->cbCmd);
52 return pCur;
53 }
54 return NULL;
55}
56
57DECLINLINE(VOID) vboxVideoCmIterCopyToBack(PVBOXVIDEOCM_ITERATOR pIter, PVBOXVIDEOCM_CMD_HDR pCur)
58{
59 memcpy((((uint8_t*)pIter->pCur) + pIter->cbRemain), pCur, pCur->cbCmd);
60 pIter->cbRemain += pCur->cbCmd;
61}
62
63DECLINLINE(bool) vboxVideoCmIterHasNext(PVBOXVIDEOCM_ITERATOR pIter)
64{
65 return !!(pIter->cbRemain);
66}
67
68static VBOXDISPMP g_VBoxDispMp;
69
70DECLCALLBACK(HRESULT) vboxDispMpEnableEvents()
71{
72 EnterCriticalSection(&g_VBoxDispMp.CritSect);
73 g_VBoxDispMp.pEscapeCmd = NULL;
74 g_VBoxDispMp.cbEscapeCmd = 0;
75 vboxVideoCmIterInit(&g_VBoxDispMp.Iterator, NULL, 0);
76#ifdef VBOX_WITH_CRHGSMI
77 vboxUhgsmiGlobalSetCurrent();
78#endif
79 LeaveCriticalSection(&g_VBoxDispMp.CritSect);
80 return S_OK;
81}
82
83
84DECLCALLBACK(HRESULT) vboxDispMpDisableEvents()
85{
86 EnterCriticalSection(&g_VBoxDispMp.CritSect);
87 if (g_VBoxDispMp.pEscapeCmd)
88 {
89 RTMemFree(g_VBoxDispMp.pEscapeCmd);
90 g_VBoxDispMp.pEscapeCmd = NULL;
91 }
92#ifdef VBOX_WITH_CRHGSMI
93 vboxUhgsmiGlobalClearCurrent();
94#endif
95 LeaveCriticalSection(&g_VBoxDispMp.CritSect);
96 return S_OK;
97}
98
99#define VBOXDISPMP_BUF_INITSIZE 4000
100#define VBOXDISPMP_BUF_INCREASE 4096
101#define VBOXDISPMP_BUF_MAXSIZE ((4096*4096)-96)
102
103DECLCALLBACK(HRESULT) vboxDispMpGetRegions(PVBOXDISPMP_REGIONS pRegions, DWORD dwMilliseconds)
104{
105 HRESULT hr = S_OK;
106 EnterCriticalSection(&g_VBoxDispMp.CritSect);
107 PVBOXVIDEOCM_CMD_HDR pHdr = vboxVideoCmIterNext(&g_VBoxDispMp.Iterator);
108 if (!pHdr)
109 {
110 if (!g_VBoxDispMp.pEscapeCmd)
111 {
112 g_VBoxDispMp.pEscapeCmd = (PVBOXDISPIFESCAPE_GETVBOXVIDEOCMCMD)RTMemAlloc(VBOXDISPMP_BUF_INITSIZE);
113 Assert(g_VBoxDispMp.pEscapeCmd);
114 if (g_VBoxDispMp.pEscapeCmd)
115 g_VBoxDispMp.cbEscapeCmd = VBOXDISPMP_BUF_INITSIZE;
116 else
117 {
118 LeaveCriticalSection(&g_VBoxDispMp.CritSect);
119 return E_OUTOFMEMORY;
120 }
121 }
122
123 do
124 {
125 hr = vboxDispCmCmdGet(g_VBoxDispMp.pEscapeCmd, g_VBoxDispMp.cbEscapeCmd, dwMilliseconds);
126 Assert(hr == S_OK || (dwMilliseconds != INFINITE && hr == WAIT_TIMEOUT));
127 if (hr == S_OK)
128 {
129 if (g_VBoxDispMp.pEscapeCmd->Hdr.cbCmdsReturned)
130 {
131 pHdr = (PVBOXVIDEOCM_CMD_HDR)(((uint8_t*)g_VBoxDispMp.pEscapeCmd) + sizeof (VBOXDISPIFESCAPE_GETVBOXVIDEOCMCMD));
132 vboxVideoCmIterInit(&g_VBoxDispMp.Iterator, pHdr, g_VBoxDispMp.pEscapeCmd->Hdr.cbCmdsReturned);
133 pHdr = vboxVideoCmIterNext(&g_VBoxDispMp.Iterator);
134 Assert(pHdr);
135 break;
136 }
137 else
138 {
139 Assert(g_VBoxDispMp.pEscapeCmd->Hdr.cbRemainingCmds);
140 Assert(g_VBoxDispMp.pEscapeCmd->Hdr.cbRemainingFirstCmd);
141 RTMemFree(g_VBoxDispMp.pEscapeCmd);
142 uint32_t newSize = RT_MAX(g_VBoxDispMp.cbEscapeCmd + VBOXDISPMP_BUF_INCREASE, g_VBoxDispMp.pEscapeCmd->Hdr.cbRemainingFirstCmd);
143 if (newSize < VBOXDISPMP_BUF_MAXSIZE)
144 newSize = RT_MAX(newSize, RT_MIN(g_VBoxDispMp.pEscapeCmd->Hdr.cbRemainingCmds, VBOXDISPMP_BUF_MAXSIZE));
145 Assert(g_VBoxDispMp.cbEscapeCmd < newSize);
146 g_VBoxDispMp.pEscapeCmd = (PVBOXDISPIFESCAPE_GETVBOXVIDEOCMCMD)RTMemAlloc(newSize);
147 Assert(g_VBoxDispMp.pEscapeCmd);
148 if (g_VBoxDispMp.pEscapeCmd)
149 g_VBoxDispMp.cbEscapeCmd = newSize;
150 else
151 {
152 g_VBoxDispMp.pEscapeCmd = NULL;
153 g_VBoxDispMp.cbEscapeCmd = 0;
154 hr = E_OUTOFMEMORY;
155 break;
156 }
157 }
158 }
159 else
160 break;
161 } while (1);
162 }
163
164 if (hr == S_OK)
165 {
166 Assert(pHdr);
167 VBOXWDDMDISP_CONTEXT *pContext = (VBOXWDDMDISP_CONTEXT*)pHdr->u64UmData;
168 PVBOXVIDEOCM_CMD_RECTS_INTERNAL pCmdInternal = (PVBOXVIDEOCM_CMD_RECTS_INTERNAL)(((uint8_t*)pHdr) + sizeof (VBOXVIDEOCM_CMD_HDR));
169 PVBOXWDDMDISP_SWAPCHAIN pSwapchain = (PVBOXWDDMDISP_SWAPCHAIN)pCmdInternal->hSwapchainUm;
170 /* the miniport driver should ensure all swapchain-involved commands are completed before swapchain termination,
171 * so we should have it always valid here */
172 Assert(pSwapchain);
173 Assert(pSwapchain->hWnd);
174 pRegions->hWnd = pSwapchain->hWnd;
175 pRegions->pRegions = &pCmdInternal->Cmd;
176 }
177 LeaveCriticalSection(&g_VBoxDispMp.CritSect);
178 return hr;
179}
180
181static DECLCALLBACK(void) vboxDispMpLog(LPCSTR pszMsg)
182{
183 vboxDispCmLog(pszMsg);
184}
185
186VBOXDISPMP_DECL(HRESULT) VBoxDispMpGetCallbacks(uint32_t u32Version, PVBOXDISPMP_CALLBACKS pCallbacks)
187{
188 Assert(u32Version == VBOXDISPMP_VERSION);
189 if (u32Version != VBOXDISPMP_VERSION)
190 return E_INVALIDARG;
191
192 pCallbacks->pfnEnableEvents = vboxDispMpEnableEvents;
193 pCallbacks->pfnDisableEvents = vboxDispMpDisableEvents;
194 pCallbacks->pfnGetRegions = vboxDispMpGetRegions;
195 return S_OK;
196}
197
198HRESULT vboxDispMpInternalInit()
199{
200 memset(&g_VBoxDispMp, 0, sizeof (g_VBoxDispMp));
201 InitializeCriticalSection(&g_VBoxDispMp.CritSect);
202 return S_OK;
203}
204
205HRESULT vboxDispMpInternalTerm()
206{
207 vboxDispMpDisableEvents();
208 DeleteCriticalSection(&g_VBoxDispMp.CritSect);
209 return S_OK;
210}
211
212HRESULT vboxDispMpInternalCancel(VBOXWDDMDISP_CONTEXT *pContext, PVBOXWDDMDISP_SWAPCHAIN pSwapchain)
213{
214 HRESULT hr = S_OK;
215 EnterCriticalSection(&g_VBoxDispMp.CritSect);
216 do
217 {
218 /* the pEscapeCmd is used as an indicator to whether the events capturing is active */
219 if (!g_VBoxDispMp.pEscapeCmd)
220 break;
221
222 /* copy the iterator data to restore it back later */
223 VBOXVIDEOCM_ITERATOR IterCopy = g_VBoxDispMp.Iterator;
224
225 /* first check if we have matching elements */
226 PVBOXVIDEOCM_CMD_HDR pHdr;
227 bool fHasMatch = false;
228 while (pHdr = vboxVideoCmIterNext(&g_VBoxDispMp.Iterator))
229 {
230 VBOXWDDMDISP_CONTEXT *pCurContext = (VBOXWDDMDISP_CONTEXT*)pHdr->u64UmData;
231 if (pCurContext != pContext)
232 continue;
233
234 if (!pSwapchain)
235 {
236 fHasMatch = true;
237 break;
238 }
239
240 PVBOXVIDEOCM_CMD_RECTS_INTERNAL pCmdInternal = (PVBOXVIDEOCM_CMD_RECTS_INTERNAL)(((uint8_t*)pHdr) + sizeof (VBOXVIDEOCM_CMD_HDR));
241 PVBOXWDDMDISP_SWAPCHAIN pCurSwapchain = (PVBOXWDDMDISP_SWAPCHAIN)pCmdInternal->hSwapchainUm;
242 if (pCurSwapchain != pSwapchain)
243 continue;
244
245 fHasMatch = true;
246 break;
247 }
248
249 /* restore the iterator */
250 g_VBoxDispMp.Iterator = IterCopy;
251
252 if (!fHasMatch)
253 break;
254
255 /* there are elements to remove */
256 PVBOXDISPIFESCAPE_GETVBOXVIDEOCMCMD pEscapeCmd = (PVBOXDISPIFESCAPE_GETVBOXVIDEOCMCMD)RTMemAlloc(g_VBoxDispMp.cbEscapeCmd);
257 if (!pEscapeCmd)
258 {
259 WARN(("no memory"));
260 hr = E_OUTOFMEMORY;
261 break;
262 }
263 /* copy the header data */
264 *pEscapeCmd = *g_VBoxDispMp.pEscapeCmd;
265 /* now copy the command data filtering out the canceled commands */
266 pHdr = (PVBOXVIDEOCM_CMD_HDR)(((uint8_t*)pEscapeCmd) + sizeof (VBOXDISPIFESCAPE_GETVBOXVIDEOCMCMD));
267 vboxVideoCmIterInit(&g_VBoxDispMp.Iterator, pHdr, 0);
268 while (pHdr = vboxVideoCmIterNext(&IterCopy))
269 {
270 VBOXWDDMDISP_CONTEXT *pCurContext = (VBOXWDDMDISP_CONTEXT*)pHdr->u64UmData;
271 if (pCurContext != pContext)
272 {
273 vboxVideoCmIterCopyToBack(&g_VBoxDispMp.Iterator, pHdr);
274 continue;
275 }
276
277 if (!pSwapchain)
278 {
279 /* match, just continue */
280 continue;
281 }
282
283 PVBOXVIDEOCM_CMD_RECTS_INTERNAL pCmdInternal = (PVBOXVIDEOCM_CMD_RECTS_INTERNAL)(((uint8_t*)pHdr) + sizeof (VBOXVIDEOCM_CMD_HDR));
284 PVBOXWDDMDISP_SWAPCHAIN pCurSwapchain = (PVBOXWDDMDISP_SWAPCHAIN)pCmdInternal->hSwapchainUm;
285 if (pCurSwapchain != pSwapchain)
286 {
287 vboxVideoCmIterCopyToBack(&g_VBoxDispMp.Iterator, pHdr);
288 continue;
289 }
290 /* match, just continue */
291 }
292
293 Assert(g_VBoxDispMp.pEscapeCmd);
294 RTMemFree(g_VBoxDispMp.pEscapeCmd);
295 Assert(pEscapeCmd);
296 g_VBoxDispMp.pEscapeCmd = pEscapeCmd;
297 } while (0);
298
299 LeaveCriticalSection(&g_VBoxDispMp.CritSect);
300 return hr;
301}
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