VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/Graphics/Display/wddm/VBoxDispD3DIf.cpp@ 30685

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

wddm/3d: create fake window properly for wine (no borders & no caption)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.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 "VBoxDispD3DIf.h"
16#include "VBoxDispD3DCmn.h"
17
18#include <iprt/assert.h>
19
20void VBoxDispD3DClose(VBOXDISPD3D *pD3D)
21{
22 FreeLibrary(pD3D->hD3DLib);
23 pD3D->hD3DLib = NULL;
24}
25
26
27HRESULT VBoxDispD3DOpen(VBOXDISPD3D *pD3D)
28{
29 pD3D->hD3DLib = LoadLibraryW(L"VBoxD3D9.dll");
30 Assert(pD3D->hD3DLib);
31 if (pD3D->hD3DLib)
32 {
33 pD3D->pfnDirect3DCreate9Ex = (PFNVBOXDISPD3DCREATE9EX)GetProcAddress(pD3D->hD3DLib, "Direct3DCreate9Ex");
34 Assert(pD3D->pfnDirect3DCreate9Ex);
35 if (pD3D->pfnDirect3DCreate9Ex)
36 return S_OK;
37 else
38 {
39 DWORD winErr = GetLastError();
40 vboxVDbgPrintR((__FUNCTION__": GetProcAddressW (for Direct3DCreate9Ex) failed, winErr = (%d)", winErr));
41 }
42
43 VBoxDispD3DClose(pD3D);
44 }
45 else
46 {
47 DWORD winErr = GetLastError();
48 vboxVDbgPrintR((__FUNCTION__": LoadLibraryW failed, winErr = (%d)", winErr));
49 }
50
51 return E_FAIL;
52}
53
54#define WM_VBOXDISP_CALLPROC (WM_APP+1)
55
56typedef struct VBOXDISP_CALLPROC
57{
58 PFNVBOXDISPWORKERCB pfnCb;
59 void *pvCb;
60} VBOXDISP_CALLPROC;
61
62static DWORD WINAPI vboxDispWorkerThread(void *pvUser)
63{
64 VBOXDISPWORKER *pWorker = (VBOXDISPWORKER*)pvUser;
65 MSG Msg;
66
67 PeekMessage(&Msg,
68 NULL /* HWND hWnd */,
69 WM_USER /* UINT wMsgFilterMin */,
70 WM_USER /* UINT wMsgFilterMax */,
71 PM_NOREMOVE);
72 RTSemEventSignal(pWorker->hEvent);
73
74 do
75 {
76 BOOL bResult = GetMessage(&Msg,
77 0 /*HWND hWnd*/,
78 0 /*UINT wMsgFilterMin*/,
79 0 /*UINT wMsgFilterMax*/
80 );
81
82 if(!bResult) /* WM_QUIT was posted */
83 break;
84
85 Assert(bResult != -1);
86 if(bResult == -1) /* error occured */
87 break;
88
89 switch (Msg.message)
90 {
91 case WM_VBOXDISP_CALLPROC:
92 {
93 VBOXDISP_CALLPROC* pData = (VBOXDISP_CALLPROC*)Msg.lParam;
94 pData->pfnCb(pData->pvCb);
95 RTSemEventSignal(pWorker->hEvent);
96 break;
97 }
98 default:
99 TranslateMessage(&Msg);
100 DispatchMessage(&Msg);
101 }
102 } while (1);
103 return 0;
104}
105
106static int vboxDispWorkerSubmit(VBOXDISPWORKER *pWorker, UINT Msg, LPARAM lParam)
107{
108 /* need to serialize since vboxDispWorkerThread is using one pWorker->hEvent
109 * to signal job completion */
110 int rc = RTCritSectEnter(&pWorker->CritSect);
111 AssertRC(rc);
112 if (RT_SUCCESS(rc))
113 {
114 BOOL bResult = PostThreadMessage(pWorker->idThread, Msg, 0, lParam);
115 Assert(bResult);
116 if (bResult)
117 {
118 rc = RTSemEventWait(pWorker->hEvent, RT_INDEFINITE_WAIT);
119 AssertRC(rc);
120 }
121 else
122 rc = VERR_GENERAL_FAILURE;
123
124 int tmpRc = RTCritSectLeave(&pWorker->CritSect);
125 AssertRC(tmpRc);
126 }
127 return rc;
128}
129
130HRESULT VBoxDispWorkerSubmitProc(VBOXDISPWORKER *pWorker, PFNVBOXDISPWORKERCB pfnCb, void *pvCb)
131{
132 VBOXDISP_CALLPROC Ctx;
133 Ctx.pfnCb = pfnCb;
134 Ctx.pvCb = pvCb;
135 int rc = vboxDispWorkerSubmit(pWorker, WM_VBOXDISP_CALLPROC, (LPARAM)&Ctx);
136 AssertRC(rc);
137 return RT_SUCCESS(rc) ? S_OK : E_FAIL;
138}
139
140HRESULT VBoxDispWorkerCreate(VBOXDISPWORKER *pWorker)
141{
142 int rc = RTCritSectInit(&pWorker->CritSect);
143 AssertRC(rc);
144 if (RT_SUCCESS(rc))
145 {
146 rc = RTSemEventCreate(&pWorker->hEvent);
147 AssertRC(rc);
148 if (RT_SUCCESS(rc))
149 {
150 pWorker->hThread = CreateThread(
151 NULL /* LPSECURITY_ATTRIBUTES lpThreadAttributes */,
152 0 /* SIZE_T dwStackSize */,
153 vboxDispWorkerThread,
154 pWorker,
155 0 /* DWORD dwCreationFlags */,
156 &pWorker->idThread);
157 Assert(pWorker->hThread);
158 if (pWorker->hThread)
159 {
160 rc = RTSemEventWait(pWorker->hEvent, RT_INDEFINITE_WAIT);
161 AssertRC(rc);
162 if (RT_SUCCESS(rc))
163 return S_OK;
164 /* destroy thread ? */
165 }
166 else
167 {
168 DWORD winErr = GetLastError();
169 vboxVDbgPrintR((__FUNCTION__": CreateThread failed, winErr = (%d)", winErr));
170 rc = VERR_GENERAL_FAILURE;
171 }
172 int tmpRc = RTSemEventDestroy(pWorker->hEvent);
173 AssertRC(tmpRc);
174 }
175 int tmpRc = RTCritSectDelete(&pWorker->CritSect);
176 AssertRC(tmpRc);
177 }
178 return E_FAIL;
179}
180
181HRESULT VBoxDispWorkerDestroy(VBOXDISPWORKER *pWorker)
182{
183 int rc = VINF_SUCCESS;
184 BOOL bResult = PostThreadMessage(pWorker->idThread, WM_QUIT, 0, 0);
185 Assert(bResult);
186 if (bResult)
187 {
188 DWORD dwErr = WaitForSingleObject(pWorker->hThread, INFINITE);
189 Assert(dwErr == WAIT_OBJECT_0);
190 if (dwErr == WAIT_OBJECT_0)
191 {
192 rc = RTSemEventDestroy(pWorker->hEvent);
193 AssertRC(rc);
194 if (RT_SUCCESS(rc))
195 {
196 rc = RTCritSectDelete(&pWorker->CritSect);
197 AssertRC(rc);
198 }
199 }
200 else
201 rc = VERR_GENERAL_FAILURE;
202 }
203 else
204 rc = VERR_GENERAL_FAILURE;
205
206 return RT_SUCCESS(rc) ? S_OK : E_FAIL;
207}
208
209static LRESULT CALLBACK WindowProc(HWND hwnd,
210 UINT uMsg,
211 WPARAM wParam,
212 LPARAM lParam
213)
214{
215 switch(uMsg)
216 {
217 case WM_CLOSE:
218 vboxVDbgPrint((__FUNCTION__": got WM_CLOSE for hwnd(0x%x)", hwnd));
219 return 0;
220 case WM_DESTROY:
221 vboxVDbgPrint((__FUNCTION__": got WM_DESTROY for hwnd(0x%x)", hwnd));
222 return 0;
223 case WM_NCHITTEST:
224 vboxVDbgPrint((__FUNCTION__": got WM_NCHITTEST for hwnd(0x%x)\n", hwnd));
225 return HTNOWHERE;
226 }
227
228 return DefWindowProc(hwnd, uMsg, wParam, lParam);
229}
230
231#define VBOXDISPWND_NAME L"VboxDispD3DWindow"
232
233HRESULT vboxDispWndDoCreate(DWORD w, DWORD h, HWND *phWnd)
234{
235 HRESULT hr = S_OK;
236 HINSTANCE hInstance = (HINSTANCE)GetModuleHandle(NULL);
237 /* Register the Window Class. */
238 WNDCLASS wc;
239 if (!GetClassInfo(hInstance, VBOXDISPWND_NAME, &wc))
240 {
241 wc.style = CS_OWNDC;
242 wc.lpfnWndProc = WindowProc;
243 wc.cbClsExtra = 0;
244 wc.cbWndExtra = 0;
245 wc.hInstance = hInstance;
246 wc.hIcon = NULL;
247 wc.hCursor = NULL;
248 wc.hbrBackground = NULL;
249 wc.lpszMenuName = NULL;
250 wc.lpszClassName = VBOXDISPWND_NAME;
251 if (!RegisterClass(&wc))
252 {
253 DWORD winErr = GetLastError();
254 vboxVDbgPrint((__FUNCTION__": RegisterClass failed, winErr(%d)\n", winErr));
255 hr = E_FAIL;
256 }
257 }
258
259 if (hr == S_OK)
260 {
261 HWND hWnd = CreateWindowEx (WS_EX_TOOLWINDOW,
262 VBOXDISPWND_NAME, VBOXDISPWND_NAME,
263 WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_DISABLED,
264 0, 0,
265 w, h,
266 NULL, //GetDesktopWindow() /* hWndParent */,
267 NULL /* hMenu */,
268 hInstance,
269 NULL /* lpParam */);
270 Assert(hWnd);
271 if (hWnd)
272 {
273 *phWnd = hWnd;
274 }
275 else
276 {
277 DWORD winErr = GetLastError();
278 vboxVDbgPrint((__FUNCTION__": CreateWindowEx failed, winErr(%d)\n", winErr));
279 hr = E_FAIL;
280 }
281 }
282
283 return hr;
284}
285
286static HRESULT vboxDispWndDoDestroy(HWND hWnd)
287{
288 BOOL bResult = DestroyWindow(hWnd);
289 Assert(bResult);
290 if (bResult)
291 return S_OK;
292
293 DWORD winErr = GetLastError();
294 vboxVDbgPrint((__FUNCTION__": DestroyWindow failed, winErr(%d) for hWnd(0x%x)\n", winErr, hWnd));
295
296 return E_FAIL;
297}
298
299typedef struct VBOXDISPWND_CREATE_INFO
300{
301 int hr;
302 HWND hWnd;
303 DWORD width;
304 DWORD height;
305} VBOXDISPWND_CREATE_INFO;
306
307typedef struct VBOXDISPWND_DESTROY_INFO
308{
309 int hr;
310 HWND hWnd;
311} VBOXDISPWND_DESTROY_INFO;
312
313DECLCALLBACK(void) vboxDispWndDestroyWorker(void *pvUser)
314{
315 VBOXDISPWND_DESTROY_INFO *pInfo = (VBOXDISPWND_DESTROY_INFO*)pvUser;
316 pInfo->hr = vboxDispWndDoDestroy(pInfo->hWnd);
317 Assert(pInfo->hr == S_OK);
318}
319
320DECLCALLBACK(void) vboxDispWndCreateWorker(void *pvUser)
321{
322 VBOXDISPWND_CREATE_INFO *pInfo = (VBOXDISPWND_CREATE_INFO*)pvUser;
323 pInfo->hr = vboxDispWndDoCreate(pInfo->width, pInfo->height, &pInfo->hWnd);
324 Assert(pInfo->hr == S_OK);
325}
326
327
328HRESULT VBoxDispWndDestroy(PVBOXWDDMDISP_ADAPTER pAdapter, HWND hWnd)
329{
330 VBOXDISPWND_DESTROY_INFO Info;
331 Info.hr = E_FAIL;
332 Info.hWnd = hWnd;
333 HRESULT hr = VBoxDispWorkerSubmitProc(&pAdapter->WndWorker, vboxDispWndDestroyWorker, &Info);
334 Assert(hr == S_OK);
335 if (hr == S_OK)
336 {
337 Assert(Info.hr == S_OK);
338 return Info.hr;
339 }
340 return hr;
341}
342
343HRESULT VBoxDispWndCreate(PVBOXWDDMDISP_ADAPTER pAdapter, DWORD width, DWORD height, HWND *phWnd)
344{
345 VBOXDISPWND_CREATE_INFO Info;
346 Info.hr = E_FAIL;
347 Info.width = width;
348 Info.height = height;
349 HRESULT hr = VBoxDispWorkerSubmitProc(&pAdapter->WndWorker, vboxDispWndCreateWorker, &Info);
350 Assert(hr == S_OK);
351 if (hr == S_OK)
352 {
353 Assert(Info.hr == S_OK);
354 if (Info.hr == S_OK)
355 *phWnd = Info.hWnd;
356 return Info.hr;
357 }
358 return hr;
359}
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