VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/Graphics/Wine/wined3d/vboxext.c@ 38363

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

wddm/3d: make wine handle gl window create/destroy

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.7 KB
Line 
1/* $Id: vboxext.c 38363 2011-08-08 19:01:30Z vboxsync $ */
2/** @file
3 *
4 * VBox extension to Wine D3D
5 *
6 * Copyright (C) 2011 Oracle Corporation
7 *
8 * This file is part of VirtualBox Open Source Edition (OSE), as
9 * available from http://www.virtualbox.org. This file is free software;
10 * you can redistribute it and/or modify it under the terms of the GNU
11 * General Public License (GPL) as published by the Free Software
12 * Foundation, in version 2 as it comes in the "COPYING" file of the
13 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
14 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
15 */
16#include "config.h"
17#include "wined3d_private.h"
18#include "vboxext.h"
19
20WINE_DEFAULT_DEBUG_CHANNEL(d3d_vbox);
21
22typedef DECLCALLBACK(void) FNVBOXEXTWORKERCB(void *pvUser);
23typedef FNVBOXEXTWORKERCB *PFNVBOXEXTWORKERCB;
24
25HRESULT VBoxExtDwSubmitProc(PFNVBOXEXTWORKERCB pfnCb, void *pvCb);
26
27/*******************************/
28#if defined(VBOX_WDDM_WOW64)
29# define VBOXEXT_WINE_MODULE_NAME "wined3dwddm-x86.dll"
30#else
31# define VBOXEXT_WINE_MODULE_NAME "wined3dwddm.dll"
32#endif
33
34typedef struct VBOXEXT_WORKER
35{
36 CRITICAL_SECTION CritSect;
37
38 HANDLE hEvent;
39
40 HANDLE hThread;
41 DWORD idThread;
42 /* wine does not seem to guarantie the dll is not unloaded in case FreeLibrary is used
43 * while d3d object is not terminated, keep an extra reference to ensure we're not unloaded
44 * while we are active */
45 HMODULE hSelf;
46} VBOXEXT_WORKER, *PVBOXEXT_WORKER;
47
48
49
50HRESULT VBoxExtWorkerCreate(PVBOXEXT_WORKER pWorker);
51HRESULT VBoxExtWorkerDestroy(PVBOXEXT_WORKER pWorker);
52HRESULT VBoxExtWorkerSubmitProc(PVBOXEXT_WORKER pWorker, PFNVBOXEXTWORKERCB pfnCb, void *pvCb);
53
54
55/*******************************/
56typedef struct VBOXEXT_GLOBAL
57{
58 VBOXEXT_WORKER Worker;
59} VBOXEXT_GLOBAL, *PVBOXEXT_GLOBAL;
60
61static VBOXEXT_GLOBAL g_VBoxExtGlobal;
62
63#define WM_VBOXEXT_CALLPROC (WM_APP+1)
64
65typedef struct VBOXEXT_CALLPROC
66{
67 PFNVBOXEXTWORKERCB pfnCb;
68 void *pvCb;
69} VBOXEXT_CALLPROC, *PVBOXEXT_CALLPROC;
70
71static DWORD WINAPI vboxExtWorkerThread(void *pvUser)
72{
73 PVBOXEXT_WORKER pWorker = (PVBOXEXT_WORKER)pvUser;
74 MSG Msg;
75
76 PeekMessage(&Msg,
77 NULL /* HWND hWnd */,
78 WM_USER /* UINT wMsgFilterMin */,
79 WM_USER /* UINT wMsgFilterMax */,
80 PM_NOREMOVE);
81 SetEvent(pWorker->hEvent);
82
83 do
84 {
85 BOOL bResult = GetMessage(&Msg,
86 0 /*HWND hWnd*/,
87 0 /*UINT wMsgFilterMin*/,
88 0 /*UINT wMsgFilterMax*/
89 );
90
91 if(!bResult) /* WM_QUIT was posted */
92 break;
93
94 Assert(bResult != -1);
95 if(bResult == -1) /* error occurred */
96 break;
97
98 switch (Msg.message)
99 {
100 case WM_VBOXEXT_CALLPROC:
101 {
102 VBOXEXT_CALLPROC* pData = (VBOXEXT_CALLPROC*)Msg.lParam;
103 pData->pfnCb(pData->pvCb);
104 SetEvent(pWorker->hEvent);
105 break;
106 }
107 default:
108 TranslateMessage(&Msg);
109 DispatchMessage(&Msg);
110 }
111 } while (1);
112 return 0;
113}
114
115HRESULT VBoxExtWorkerCreate(PVBOXEXT_WORKER pWorker)
116{
117 if(!GetModuleHandleEx(0, VBOXEXT_WINE_MODULE_NAME, &pWorker->hSelf))
118 {
119 DWORD dwEr = GetLastError();
120 ERR("GetModuleHandleEx failed, %d", dwEr);
121 return E_FAIL;
122 }
123
124 InitializeCriticalSection(&pWorker->CritSect);
125 pWorker->hEvent = CreateEvent(NULL, /* LPSECURITY_ATTRIBUTES lpEventAttributes */
126 FALSE, /* BOOL bManualReset */
127 FALSE, /* BOOL bInitialState */
128 NULL /* LPCTSTR lpName */
129 );
130 if (pWorker->hEvent)
131 {
132 pWorker->hThread = CreateThread(
133 NULL /* LPSECURITY_ATTRIBUTES lpThreadAttributes */,
134 0 /* SIZE_T dwStackSize */,
135 vboxExtWorkerThread,
136 pWorker,
137 0 /* DWORD dwCreationFlags */,
138 &pWorker->idThread);
139 if (pWorker->hThread)
140 {
141 DWORD dwResult = WaitForSingleObject(pWorker->hEvent, INFINITE);
142 if (WAIT_OBJECT_0 == dwResult)
143 return S_OK;
144 ERR("WaitForSingleObject returned %d\n", dwResult);
145 }
146 else
147 {
148 DWORD winErr = GetLastError();
149 ERR("CreateThread failed, winErr = (%d)", winErr);
150 }
151
152 DeleteCriticalSection(&pWorker->CritSect);
153 }
154 else
155 {
156 DWORD winErr = GetLastError();
157 ERR("CreateEvent failed, winErr = (%d)", winErr);
158 }
159
160 FreeLibrary(pWorker->hSelf);
161
162 return E_FAIL;
163}
164
165HRESULT VBoxExtWorkerDestroy(PVBOXEXT_WORKER pWorker)
166{
167 BOOL bResult = PostThreadMessage(pWorker->idThread, WM_QUIT, 0, 0);
168 DWORD dwErr;
169 if (!bResult)
170 {
171 DWORD winErr = GetLastError();
172 ERR("PostThreadMessage failed, winErr = (%d)", winErr);
173 return E_FAIL;
174 }
175
176 dwErr = WaitForSingleObject(pWorker->hThread, INFINITE);
177 if (dwErr != WAIT_OBJECT_0)
178 {
179 ERR("WaitForSingleObject returned (%d)", dwErr);
180 return E_FAIL;
181 }
182
183 CloseHandle(pWorker->hEvent);
184 DeleteCriticalSection(&pWorker->CritSect);
185
186 FreeLibrary(pWorker->hSelf);
187
188 return S_OK;
189}
190
191static HRESULT vboxExtWorkerSubmit(VBOXEXT_WORKER *pWorker, UINT Msg, LPARAM lParam)
192{
193 HRESULT hr = E_FAIL;
194 BOOL bResult;
195 /* need to serialize since vboxExtWorkerThread is using one pWorker->hEvent
196 * to signal job completion */
197 EnterCriticalSection(&pWorker->CritSect);
198 bResult = PostThreadMessage(pWorker->idThread, Msg, 0, lParam);
199 if (bResult)
200 {
201 DWORD dwErr = WaitForSingleObject(pWorker->hEvent, INFINITE);
202 if (dwErr == WAIT_OBJECT_0)
203 {
204 hr = S_OK;
205 }
206 else
207 {
208 ERR("WaitForSingleObject returned (%d)", dwErr);
209 }
210 }
211 else
212 {
213 DWORD winErr = GetLastError();
214 ERR("PostThreadMessage failed, winErr = (%d)", winErr);
215 return E_FAIL;
216 }
217 LeaveCriticalSection(&pWorker->CritSect);
218 return hr;
219}
220
221HRESULT VBoxExtWorkerSubmitProc(PVBOXEXT_WORKER pWorker, PFNVBOXEXTWORKERCB pfnCb, void *pvCb)
222{
223 VBOXEXT_CALLPROC Ctx;
224 Ctx.pfnCb = pfnCb;
225 Ctx.pvCb = pvCb;
226 return vboxExtWorkerSubmit(pWorker, WM_VBOXEXT_CALLPROC, (LPARAM)&Ctx);
227}
228
229static HRESULT vboxExtInit()
230{
231 HRESULT hr = S_OK;
232 memset(&g_VBoxExtGlobal, 0, sizeof (g_VBoxExtGlobal));
233 hr = VBoxExtWorkerCreate(&g_VBoxExtGlobal.Worker);
234 return hr;
235}
236
237static HRESULT vboxExtTerm()
238{
239 HRESULT hr = VBoxExtWorkerDestroy(&g_VBoxExtGlobal.Worker);
240 return hr;
241}
242
243static DWORD g_cVBoxExtInits = 0;
244HRESULT VBoxExtCheckInit()
245{
246 HRESULT hr = S_OK;
247 if (!g_cVBoxExtInits)
248 {
249 hr = vboxExtInit();
250 if (FAILED(hr))
251 {
252 ERR("vboxExtInit failed, hr (0x%x)", hr);
253 return hr;
254 }
255 }
256 ++g_cVBoxExtInits;
257 return S_OK;
258}
259
260HRESULT VBoxExtCheckTerm()
261{
262 HRESULT hr = S_OK;
263 if (g_cVBoxExtInits == 1)
264 {
265 hr = vboxExtTerm();
266 if (FAILED(hr))
267 {
268 ERR("vboxExtTerm failed, hr (0x%x)", hr);
269 return hr;
270 }
271 }
272 --g_cVBoxExtInits;
273 return S_OK;
274}
275
276HRESULT VBoxExtDwSubmitProc(PFNVBOXEXTWORKERCB pfnCb, void *pvCb)
277{
278 return VBoxExtWorkerSubmitProc(&g_VBoxExtGlobal.Worker, pfnCb, pvCb);
279}
280
281typedef struct VBOXEXT_GETDC_CB
282{
283 HWND hWnd;
284 HDC hDC;
285} VBOXEXT_GETDC_CB, *PVBOXEXT_GETDC_CB;
286
287static DECLCALLBACK(void) vboxExtGetDCWorker(void *pvUser)
288{
289 PVBOXEXT_GETDC_CB pData = (PVBOXEXT_GETDC_CB)pvUser;
290 pData->hDC = GetDC(pData->hWnd);
291}
292
293typedef struct VBOXEXT_RELEASEDC_CB
294{
295 HWND hWnd;
296 HDC hDC;
297 int ret;
298} VBOXEXT_RELEASEDC_CB, *PVBOXEXT_RELEASEDC_CB;
299
300static DECLCALLBACK(void) vboxExtReleaseDCWorker(void *pvUser)
301{
302 PVBOXEXT_RELEASEDC_CB pData = (PVBOXEXT_RELEASEDC_CB)pvUser;
303 pData->ret = ReleaseDC(pData->hWnd, pData->hDC);
304}
305#if 0
306HDC VBoxExtGetDC(HWND hWnd)
307{
308#ifdef VBOX_WINE_WITH_SINGLE_CONTEXT
309 HRESULT hr;
310 VBOXEXT_GETDC_CB Data = {0};
311 Data.hWnd = hWnd;
312 Data.hDC = NULL;
313
314 hr = VBoxExtDwSubmitProc(vboxExtGetDCWorker, &Data);
315 if (FAILED(hr))
316 {
317 ERR("VBoxExtDwSubmitProc feiled, hr (0x%x)\n", hr);
318 return NULL;
319 }
320
321 return Data.hDC;
322#else
323 return GetDC(hWnd);
324#endif
325}
326
327int VBoxExtReleaseDC(HWND hWnd, HDC hDC)
328{
329#ifdef VBOX_WINE_WITH_SINGLE_CONTEXT
330 HRESULT hr;
331 VBOXEXT_RELEASEDC_CB Data = {0};
332 Data.hWnd = hWnd;
333 Data.hDC = hDC;
334 Data.ret = 0;
335
336 hr = VBoxExtDwSubmitProc(vboxExtReleaseDCWorker, &Data);
337 if (FAILED(hr))
338 {
339 ERR("VBoxExtDwSubmitProc feiled, hr (0x%x)\n", hr);
340 return -1;
341 }
342
343 return Data.ret;
344#else
345 return ReleaseDC(hWnd, hDC);
346#endif
347}
348#endif
349
350/* window creation API */
351static LRESULT CALLBACK vboxExtWndProc(HWND hwnd,
352 UINT uMsg,
353 WPARAM wParam,
354 LPARAM lParam
355)
356{
357 switch(uMsg)
358 {
359 case WM_CLOSE:
360 TRACE("got WM_CLOSE for hwnd(0x%x)", hwnd);
361 return 0;
362 case WM_DESTROY:
363 TRACE("got WM_DESTROY for hwnd(0x%x)", hwnd);
364 return 0;
365 case WM_NCHITTEST:
366 TRACE("got WM_NCHITTEST for hwnd(0x%x)\n", hwnd);
367 return HTNOWHERE;
368 }
369
370 return DefWindowProc(hwnd, uMsg, wParam, lParam);
371}
372
373#define VBOXEXTWND_NAME "VboxDispD3DWineWnd"
374
375HRESULT vboxExtWndDoCreate(DWORD w, DWORD h, HWND *phWnd, HDC *phDC)
376{
377 HRESULT hr = S_OK;
378 HINSTANCE hInstance = (HINSTANCE)GetModuleHandle(NULL);
379 /* Register the Window Class. */
380 WNDCLASS wc;
381 if (!GetClassInfo(hInstance, VBOXEXTWND_NAME, &wc))
382 {
383 wc.style = 0;//CS_OWNDC;
384 wc.lpfnWndProc = vboxExtWndProc;
385 wc.cbClsExtra = 0;
386 wc.cbWndExtra = 0;
387 wc.hInstance = hInstance;
388 wc.hIcon = NULL;
389 wc.hCursor = NULL;
390 wc.hbrBackground = NULL;
391 wc.lpszMenuName = NULL;
392 wc.lpszClassName = VBOXEXTWND_NAME;
393 if (!RegisterClass(&wc))
394 {
395 DWORD winErr = GetLastError();
396 ERR("RegisterClass failed, winErr(%d)\n", winErr);
397 hr = E_FAIL;
398 }
399 }
400
401 if (hr == S_OK)
402 {
403 HWND hWnd = CreateWindowEx (WS_EX_TOOLWINDOW,
404 VBOXEXTWND_NAME, VBOXEXTWND_NAME,
405 WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_DISABLED,
406 0, 0,
407 w, h,
408 NULL, //GetDesktopWindow() /* hWndParent */,
409 NULL /* hMenu */,
410 hInstance,
411 NULL /* lpParam */);
412 Assert(hWnd);
413 if (hWnd)
414 {
415 *phWnd = hWnd;
416 *phDC = GetDC(hWnd);
417 }
418 else
419 {
420 DWORD winErr = GetLastError();
421 ERR("CreateWindowEx failed, winErr(%d)\n", winErr);
422 hr = E_FAIL;
423 }
424 }
425
426 return hr;
427}
428
429static HRESULT vboxExtWndDoDestroy(HWND hWnd, HDC hDC)
430{
431 BOOL bResult;
432 DWORD winErr;
433 ReleaseDC(hWnd, hDC);
434 bResult = DestroyWindow(hWnd);
435 Assert(bResult);
436 if (bResult)
437 return S_OK;
438
439 winErr = GetLastError();
440 ERR("DestroyWindow failed, winErr(%d) for hWnd(0x%x)\n", winErr, hWnd);
441
442 return E_FAIL;
443}
444
445typedef struct VBOXEXTWND_CREATE_INFO
446{
447 int hr;
448 HWND hWnd;
449 HDC hDC;
450 DWORD width;
451 DWORD height;
452} VBOXEXTWND_CREATE_INFO;
453
454typedef struct VBOXEXTWND_DESTROY_INFO
455{
456 int hr;
457 HWND hWnd;
458 HDC hDC;
459} VBOXEXTWND_DESTROY_INFO;
460
461DECLCALLBACK(void) vboxExtWndDestroyWorker(void *pvUser)
462{
463 VBOXEXTWND_DESTROY_INFO *pInfo = (VBOXEXTWND_DESTROY_INFO*)pvUser;
464 pInfo->hr = vboxExtWndDoDestroy(pInfo->hWnd, pInfo->hDC);
465 Assert(pInfo->hr == S_OK);
466}
467
468DECLCALLBACK(void) vboxExtWndCreateWorker(void *pvUser)
469{
470 VBOXEXTWND_CREATE_INFO *pInfo = (VBOXEXTWND_CREATE_INFO*)pvUser;
471 pInfo->hr = vboxExtWndDoCreate(pInfo->width, pInfo->height, &pInfo->hWnd, &pInfo->hDC);
472 Assert(pInfo->hr == S_OK);
473}
474
475HRESULT VBoxExtWndDestroy(HWND hWnd, HDC hDC)
476{
477 HRESULT hr;
478 VBOXEXTWND_DESTROY_INFO Info;
479 Info.hr = E_FAIL;
480 Info.hWnd = hWnd;
481 Info.hDC = hDC;
482 hr = VBoxExtDwSubmitProc(vboxExtWndDestroyWorker, &Info);
483 Assert(hr == S_OK);
484 if (hr == S_OK)
485 {
486 Assert(Info.hr == S_OK);
487 return Info.hr;
488 }
489 return hr;
490}
491
492HRESULT VBoxExtWndCreate(DWORD width, DWORD height, HWND *phWnd, HDC *phDC)
493{
494 HRESULT hr;
495 VBOXEXTWND_CREATE_INFO Info;
496 Info.hr = E_FAIL;
497 Info.width = width;
498 Info.height = height;
499 hr = VBoxExtDwSubmitProc(vboxExtWndCreateWorker, &Info);
500 Assert(hr == S_OK);
501 if (hr == S_OK)
502 {
503 Assert(Info.hr == S_OK);
504 if (Info.hr == S_OK)
505 {
506 *phWnd = Info.hWnd;
507 *phDC = Info.hDC;
508 }
509 return Info.hr;
510 }
511 return hr;
512}
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette