VirtualBox

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

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

Additions/Video: display/miniport drivers

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