VirtualBox

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

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

wddm/3d: add cube textures support

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