VirtualBox

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

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

wddm/3d: CreateDevice basics

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