VirtualBox

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

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

wddm/3d: 1. fix invalid visible rectreporting on swapchain destruction 2. single context for wine (disabled so far), 3 wine & 3d driver bugfixes

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.2 KB
Line 
1/* $Id: VBoxDispMp.cpp 38112 2011-07-22 13:26:19Z 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 pCallbacks->pfnLog = vboxDispMpLog;
196 return S_OK;
197}
198
199HRESULT vboxDispMpInternalInit()
200{
201 memset(&g_VBoxDispMp, 0, sizeof (g_VBoxDispMp));
202 InitializeCriticalSection(&g_VBoxDispMp.CritSect);
203 return S_OK;
204}
205
206HRESULT vboxDispMpInternalTerm()
207{
208 vboxDispMpDisableEvents();
209 DeleteCriticalSection(&g_VBoxDispMp.CritSect);
210 return S_OK;
211}
212
213HRESULT vboxDispMpInternalCancel(VBOXWDDMDISP_CONTEXT *pContext, PVBOXWDDMDISP_SWAPCHAIN pSwapchain)
214{
215 HRESULT hr = S_OK;
216 EnterCriticalSection(&g_VBoxDispMp.CritSect);
217 do
218 {
219 /* the pEscapeCmd is used as an indicator to whether the events capturing is active */
220 if (!g_VBoxDispMp.pEscapeCmd)
221 break;
222
223 /* copy the iterator data to restore it back later */
224 VBOXVIDEOCM_ITERATOR IterCopy = g_VBoxDispMp.Iterator;
225
226 /* first check if we have matching elements */
227 PVBOXVIDEOCM_CMD_HDR pHdr;
228 bool fHasMatch = false;
229 while (pHdr = vboxVideoCmIterNext(&g_VBoxDispMp.Iterator))
230 {
231 VBOXWDDMDISP_CONTEXT *pCurContext = (VBOXWDDMDISP_CONTEXT*)pHdr->u64UmData;
232 if (pCurContext != pContext)
233 continue;
234
235 if (!pSwapchain)
236 {
237 fHasMatch = true;
238 break;
239 }
240
241 PVBOXVIDEOCM_CMD_RECTS_INTERNAL pCmdInternal = (PVBOXVIDEOCM_CMD_RECTS_INTERNAL)(((uint8_t*)pHdr) + sizeof (VBOXVIDEOCM_CMD_HDR));
242 PVBOXWDDMDISP_SWAPCHAIN pCurSwapchain = (PVBOXWDDMDISP_SWAPCHAIN)pCmdInternal->hSwapchainUm;
243 if (pCurSwapchain != pSwapchain)
244 continue;
245
246 fHasMatch = true;
247 break;
248 }
249
250 /* restore the iterator */
251 g_VBoxDispMp.Iterator = IterCopy;
252
253 if (!fHasMatch)
254 break;
255
256 /* there are elements to remove */
257 PVBOXDISPIFESCAPE_GETVBOXVIDEOCMCMD pEscapeCmd = (PVBOXDISPIFESCAPE_GETVBOXVIDEOCMCMD)RTMemAlloc(g_VBoxDispMp.cbEscapeCmd);
258 if (!pEscapeCmd)
259 {
260 WARN(("no memory"));
261 hr = E_OUTOFMEMORY;
262 break;
263 }
264 /* copy the header data */
265 *pEscapeCmd = *g_VBoxDispMp.pEscapeCmd;
266 /* now copy the command data filtering out the canceled commands */
267 pHdr = (PVBOXVIDEOCM_CMD_HDR)(((uint8_t*)pEscapeCmd) + sizeof (VBOXDISPIFESCAPE_GETVBOXVIDEOCMCMD));
268 vboxVideoCmIterInit(&g_VBoxDispMp.Iterator, pHdr, 0);
269 while (pHdr = vboxVideoCmIterNext(&IterCopy))
270 {
271 VBOXWDDMDISP_CONTEXT *pCurContext = (VBOXWDDMDISP_CONTEXT*)pHdr->u64UmData;
272 if (pCurContext != pContext)
273 {
274 vboxVideoCmIterCopyToBack(&g_VBoxDispMp.Iterator, pHdr);
275 continue;
276 }
277
278 if (!pSwapchain)
279 {
280 /* match, just continue */
281 continue;
282 }
283
284 PVBOXVIDEOCM_CMD_RECTS_INTERNAL pCmdInternal = (PVBOXVIDEOCM_CMD_RECTS_INTERNAL)(((uint8_t*)pHdr) + sizeof (VBOXVIDEOCM_CMD_HDR));
285 PVBOXWDDMDISP_SWAPCHAIN pCurSwapchain = (PVBOXWDDMDISP_SWAPCHAIN)pCmdInternal->hSwapchainUm;
286 if (pCurSwapchain != pSwapchain)
287 {
288 vboxVideoCmIterCopyToBack(&g_VBoxDispMp.Iterator, pHdr);
289 continue;
290 }
291 /* match, just continue */
292 }
293
294 Assert(g_VBoxDispMp.pEscapeCmd);
295 RTMemFree(g_VBoxDispMp.pEscapeCmd);
296 Assert(pEscapeCmd);
297 g_VBoxDispMp.pEscapeCmd = pEscapeCmd;
298 } while (0);
299
300 LeaveCriticalSection(&g_VBoxDispMp.CritSect);
301 return hr;
302}
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