VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/Graphics/Wine_new/wined3d/vboxext.c@ 69362

Last change on this file since 69362 was 69362, checked in by vboxsync, 7 years ago

GA/WINNT/Graphics: scm updates

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 22.2 KB
Line 
1/* $Id: vboxext.c 69362 2017-10-26 15:12:33Z vboxsync $ */
2/** @file
3 * VBox extension to Wine D3D
4 */
5
6/*
7 * Copyright (C) 2011-2016 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#include "config.h"
19#include "wine/port.h"
20#include "wined3d_private.h"
21#include "vboxext.h"
22#ifdef VBOX_WITH_WDDM
23#include <VBoxCrHgsmi.h>
24#include <iprt/err.h>
25#endif
26
27WINE_DEFAULT_DEBUG_CHANNEL(d3d_vbox);
28
29typedef DECLCALLBACK(void) FNVBOXEXTWORKERCB(void *pvUser);
30typedef FNVBOXEXTWORKERCB *PFNVBOXEXTWORKERCB;
31
32HRESULT VBoxExtDwSubmitProcSync(PFNVBOXEXTWORKERCB pfnCb, void *pvCb);
33HRESULT VBoxExtDwSubmitProcAsync(PFNVBOXEXTWORKERCB pfnCb, void *pvCb);
34
35/*******************************/
36#ifdef VBOX_WITH_WDDM
37# if defined(VBOX_WDDM_WOW64)
38# define VBOXEXT_WINE_MODULE_NAME "wined3dwddm-x86.dll"
39# else
40# define VBOXEXT_WINE_MODULE_NAME "wined3dwddm.dll"
41# endif
42#else
43/* both 32bit and 64bit versions of xpdm wine libs are named identically */
44# define VBOXEXT_WINE_MODULE_NAME "wined3d.dll"
45#endif
46
47typedef struct VBOXEXT_WORKER
48{
49 CRITICAL_SECTION CritSect;
50
51 HANDLE hEvent;
52
53 HANDLE hThread;
54 DWORD idThread;
55 /* wine does not seem to guarantie the dll is not unloaded in case FreeLibrary is used
56 * while d3d object is not terminated, keep an extra reference to ensure we're not unloaded
57 * while we are active */
58 HMODULE hSelf;
59} VBOXEXT_WORKER, *PVBOXEXT_WORKER;
60
61
62
63HRESULT VBoxExtWorkerCreate(PVBOXEXT_WORKER pWorker);
64HRESULT VBoxExtWorkerDestroy(PVBOXEXT_WORKER pWorker);
65HRESULT VBoxExtWorkerSubmitProc(PVBOXEXT_WORKER pWorker, PFNVBOXEXTWORKERCB pfnCb, void *pvCb);
66
67
68/*******************************/
69typedef struct VBOXEXT_GLOBAL
70{
71 VBOXEXT_WORKER Worker;
72} VBOXEXT_GLOBAL, *PVBOXEXT_GLOBAL;
73
74static VBOXEXT_GLOBAL g_VBoxExtGlobal;
75
76#define WM_VBOXEXT_CALLPROC (WM_APP+1)
77#define WM_VBOXEXT_INIT_QUIT (WM_APP+2)
78
79typedef struct VBOXEXT_CALLPROC
80{
81 PFNVBOXEXTWORKERCB pfnCb;
82 void *pvCb;
83} VBOXEXT_CALLPROC, *PVBOXEXT_CALLPROC;
84
85static DWORD WINAPI vboxExtWorkerThread(void *pvUser)
86{
87 PVBOXEXT_WORKER pWorker = (PVBOXEXT_WORKER)pvUser;
88 MSG Msg;
89
90 PeekMessage(&Msg,
91 NULL /* HWND hWnd */,
92 WM_USER /* UINT wMsgFilterMin */,
93 WM_USER /* UINT wMsgFilterMax */,
94 PM_NOREMOVE);
95 SetEvent(pWorker->hEvent);
96
97 do
98 {
99 BOOL bResult = GetMessage(&Msg,
100 0 /*HWND hWnd*/,
101 0 /*UINT wMsgFilterMin*/,
102 0 /*UINT wMsgFilterMax*/
103 );
104
105 if(!bResult) /* WM_QUIT was posted */
106 break;
107
108 Assert(bResult != -1);
109 if(bResult == -1) /* error occurred */
110 break;
111
112 switch (Msg.message)
113 {
114 case WM_VBOXEXT_CALLPROC:
115 {
116 VBOXEXT_CALLPROC* pData = (VBOXEXT_CALLPROC*)Msg.lParam;
117 pData->pfnCb(pData->pvCb);
118 SetEvent(pWorker->hEvent);
119 break;
120 }
121 case WM_VBOXEXT_INIT_QUIT:
122 case WM_CLOSE:
123 {
124 PostQuitMessage(0);
125 break;
126 }
127 default:
128 TranslateMessage(&Msg);
129 DispatchMessage(&Msg);
130 }
131 } while (1);
132 return 0;
133}
134
135HRESULT VBoxExtWorkerCreate(PVBOXEXT_WORKER pWorker)
136{
137 if(!GetModuleHandleEx(0, VBOXEXT_WINE_MODULE_NAME, &pWorker->hSelf))
138 {
139 DWORD dwEr = GetLastError();
140 ERR("GetModuleHandleEx failed, %d", dwEr);
141 return E_FAIL;
142 }
143
144 InitializeCriticalSection(&pWorker->CritSect);
145 pWorker->hEvent = CreateEvent(NULL, /* LPSECURITY_ATTRIBUTES lpEventAttributes */
146 FALSE, /* BOOL bManualReset */
147 FALSE, /* BOOL bInitialState */
148 NULL /* LPCTSTR lpName */
149 );
150 if (pWorker->hEvent)
151 {
152 pWorker->hThread = CreateThread(
153 NULL /* LPSECURITY_ATTRIBUTES lpThreadAttributes */,
154 0 /* SIZE_T dwStackSize */,
155 vboxExtWorkerThread,
156 pWorker,
157 0 /* DWORD dwCreationFlags */,
158 &pWorker->idThread);
159 if (pWorker->hThread)
160 {
161 DWORD dwResult = WaitForSingleObject(pWorker->hEvent, INFINITE);
162 if (WAIT_OBJECT_0 == dwResult)
163 return S_OK;
164 ERR("WaitForSingleObject returned %d\n", dwResult);
165 }
166 else
167 {
168 DWORD winErr = GetLastError();
169 ERR("CreateThread failed, winErr = (%d)", winErr);
170 }
171
172 DeleteCriticalSection(&pWorker->CritSect);
173 }
174 else
175 {
176 DWORD winErr = GetLastError();
177 ERR("CreateEvent failed, winErr = (%d)", winErr);
178 }
179
180 FreeLibrary(pWorker->hSelf);
181
182 return E_FAIL;
183}
184
185HRESULT VBoxExtWorkerDestroy(PVBOXEXT_WORKER pWorker)
186{
187 BOOL bResult = PostThreadMessage(pWorker->idThread, WM_VBOXEXT_INIT_QUIT, 0, 0);
188 DWORD dwErr;
189 if (!bResult)
190 {
191 DWORD winErr = GetLastError();
192 ERR("PostThreadMessage failed, winErr = (%d)", winErr);
193 return E_FAIL;
194 }
195
196 dwErr = WaitForSingleObject(pWorker->hThread, INFINITE);
197 if (dwErr != WAIT_OBJECT_0)
198 {
199 ERR("WaitForSingleObject returned (%d)", dwErr);
200 return E_FAIL;
201 }
202
203 CloseHandle(pWorker->hEvent);
204 DeleteCriticalSection(&pWorker->CritSect);
205
206 FreeLibrary(pWorker->hSelf);
207
208 CloseHandle(pWorker->hThread);
209
210 return S_OK;
211}
212
213static HRESULT vboxExtWorkerSubmit(VBOXEXT_WORKER *pWorker, UINT Msg, LPARAM lParam, BOOL fSync)
214{
215 HRESULT hr = E_FAIL;
216 BOOL bResult;
217 /* need to serialize since vboxExtWorkerThread is using one pWorker->hEvent
218 * to signal job completion */
219 EnterCriticalSection(&pWorker->CritSect);
220 bResult = PostThreadMessage(pWorker->idThread, Msg, 0, lParam);
221 if (bResult)
222 {
223 if (fSync)
224 {
225 DWORD dwErr = WaitForSingleObject(pWorker->hEvent, INFINITE);
226 if (dwErr == WAIT_OBJECT_0)
227 {
228 hr = S_OK;
229 }
230 else
231 {
232 ERR("WaitForSingleObject returned (%d)", dwErr);
233 }
234 }
235 else
236 hr = S_OK;
237 }
238 else
239 {
240 DWORD winErr = GetLastError();
241 ERR("PostThreadMessage failed, winErr = (%d)", winErr);
242 return E_FAIL;
243 }
244 LeaveCriticalSection(&pWorker->CritSect);
245 return hr;
246}
247
248HRESULT VBoxExtWorkerSubmitProcSync(PVBOXEXT_WORKER pWorker, PFNVBOXEXTWORKERCB pfnCb, void *pvCb)
249{
250 VBOXEXT_CALLPROC Ctx;
251 Ctx.pfnCb = pfnCb;
252 Ctx.pvCb = pvCb;
253 return vboxExtWorkerSubmit(pWorker, WM_VBOXEXT_CALLPROC, (LPARAM)&Ctx, TRUE);
254}
255
256static DECLCALLBACK(void) vboxExtWorkerSubmitProcAsyncWorker(void *pvUser)
257{
258 PVBOXEXT_CALLPROC pCallInfo = (PVBOXEXT_CALLPROC)pvUser;
259 pCallInfo[1].pfnCb(pCallInfo[1].pvCb);
260 HeapFree(GetProcessHeap(), 0, pCallInfo);
261}
262
263HRESULT VBoxExtWorkerSubmitProcAsync(PVBOXEXT_WORKER pWorker, PFNVBOXEXTWORKERCB pfnCb, void *pvCb)
264{
265 HRESULT hr;
266 PVBOXEXT_CALLPROC pCallInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof (VBOXEXT_CALLPROC) * 2);
267 if (!pCallInfo)
268 {
269 ERR("HeapAlloc failed\n");
270 return E_OUTOFMEMORY;
271 }
272 pCallInfo[0].pfnCb = vboxExtWorkerSubmitProcAsyncWorker;
273 pCallInfo[0].pvCb = pCallInfo;
274 pCallInfo[1].pfnCb = pfnCb;
275 pCallInfo[1].pvCb = pvCb;
276 hr = vboxExtWorkerSubmit(pWorker, WM_VBOXEXT_CALLPROC, (LPARAM)pCallInfo, FALSE);
277 if (FAILED(hr))
278 {
279 ERR("vboxExtWorkerSubmit failed, hr 0x%x\n", hr);
280 HeapFree(GetProcessHeap(), 0, pCallInfo);
281 return hr;
282 }
283 return S_OK;
284}
285
286
287static HRESULT vboxExtInit(void)
288{
289 HRESULT hr = S_OK;
290#ifdef VBOX_WITH_WDDM
291 int rc = VBoxCrHgsmiInit();
292 if (!RT_SUCCESS(rc))
293 {
294 ERR("VBoxCrHgsmiInit failed rc %d", rc);
295 return E_FAIL;
296 }
297#endif
298 memset(&g_VBoxExtGlobal, 0, sizeof (g_VBoxExtGlobal));
299 hr = VBoxExtWorkerCreate(&g_VBoxExtGlobal.Worker);
300 if (SUCCEEDED(hr))
301 return S_OK;
302
303 /* failure branch */
304#ifdef VBOX_WITH_WDDM
305 VBoxCrHgsmiTerm();
306#endif
307 return hr;
308}
309
310
311static HRESULT vboxExtWndCleanup(void);
312
313static HRESULT vboxExtTerm(void)
314{
315 HRESULT hr = vboxExtWndCleanup();
316 if (!SUCCEEDED(hr))
317 {
318 ERR("vboxExtWndCleanup failed, hr %d", hr);
319 return hr;
320 }
321
322 hr = VBoxExtWorkerDestroy(&g_VBoxExtGlobal.Worker);
323 if (!SUCCEEDED(hr))
324 {
325 ERR("VBoxExtWorkerDestroy failed, hr %d", hr);
326 return hr;
327 }
328
329#ifdef VBOX_WITH_WDDM
330 VBoxCrHgsmiTerm();
331#endif
332
333 return S_OK;
334}
335
336/* wine serializes all calls to us, so no need for any synchronization here */
337static DWORD g_cVBoxExtInits = 0;
338
339static DWORD vboxExtAddRef(void)
340{
341 return ++g_cVBoxExtInits;
342}
343
344static DWORD vboxExtRelease(void)
345{
346 DWORD cVBoxExtInits = --g_cVBoxExtInits;
347 Assert(cVBoxExtInits < UINT32_MAX/2);
348 return cVBoxExtInits;
349}
350
351static DWORD vboxExtGetRef(void)
352{
353 return g_cVBoxExtInits;
354}
355
356HRESULT VBoxExtCheckInit(void)
357{
358 HRESULT hr = S_OK;
359 if (!vboxExtGetRef())
360 {
361 hr = vboxExtInit();
362 if (FAILED(hr))
363 {
364 ERR("vboxExtInit failed, hr (0x%x)", hr);
365 return hr;
366 }
367 }
368 vboxExtAddRef();
369 return S_OK;
370}
371
372HRESULT VBoxExtCheckTerm(void)
373{
374 HRESULT hr = S_OK;
375 if (vboxExtGetRef() == 1)
376 {
377 hr = vboxExtTerm();
378 if (FAILED(hr))
379 {
380 ERR("vboxExtTerm failed, hr (0x%x)", hr);
381 return hr;
382 }
383 }
384 vboxExtRelease();
385 return S_OK;
386}
387
388HRESULT VBoxExtDwSubmitProcSync(PFNVBOXEXTWORKERCB pfnCb, void *pvCb)
389{
390 return VBoxExtWorkerSubmitProcSync(&g_VBoxExtGlobal.Worker, pfnCb, pvCb);
391}
392
393HRESULT VBoxExtDwSubmitProcAsync(PFNVBOXEXTWORKERCB pfnCb, void *pvCb)
394{
395 return VBoxExtWorkerSubmitProcAsync(&g_VBoxExtGlobal.Worker, pfnCb, pvCb);
396}
397
398#if defined(VBOX_WINE_WITH_SINGLE_CONTEXT) || defined(VBOX_WINE_WITH_SINGLE_SWAPCHAIN_CONTEXT)
399# ifndef VBOX_WITH_WDDM
400typedef struct VBOXEXT_GETDC_CB
401{
402 HWND hWnd;
403 HDC hDC;
404} VBOXEXT_GETDC_CB, *PVBOXEXT_GETDC_CB;
405
406static DECLCALLBACK(void) vboxExtGetDCWorker(void *pvUser)
407{
408 PVBOXEXT_GETDC_CB pData = (PVBOXEXT_GETDC_CB)pvUser;
409 pData->hDC = GetDC(pData->hWnd);
410}
411
412typedef struct VBOXEXT_RELEASEDC_CB
413{
414 HWND hWnd;
415 HDC hDC;
416 int ret;
417} VBOXEXT_RELEASEDC_CB, *PVBOXEXT_RELEASEDC_CB;
418
419static DECLCALLBACK(void) vboxExtReleaseDCWorker(void *pvUser)
420{
421 PVBOXEXT_RELEASEDC_CB pData = (PVBOXEXT_RELEASEDC_CB)pvUser;
422 pData->ret = ReleaseDC(pData->hWnd, pData->hDC);
423}
424
425HDC VBoxExtGetDC(HWND hWnd)
426{
427 HRESULT hr;
428 VBOXEXT_GETDC_CB Data = {0};
429 Data.hWnd = hWnd;
430 Data.hDC = NULL;
431
432 hr = VBoxExtDwSubmitProcSync(vboxExtGetDCWorker, &Data);
433 if (FAILED(hr))
434 {
435 ERR("VBoxExtDwSubmitProcSync feiled, hr (0x%x)\n", hr);
436 return NULL;
437 }
438
439 return Data.hDC;
440}
441
442int VBoxExtReleaseDC(HWND hWnd, HDC hDC)
443{
444 HRESULT hr;
445 VBOXEXT_RELEASEDC_CB Data = {0};
446 Data.hWnd = hWnd;
447 Data.hDC = hDC;
448 Data.ret = 0;
449
450 hr = VBoxExtDwSubmitProcSync(vboxExtReleaseDCWorker, &Data);
451 if (FAILED(hr))
452 {
453 ERR("VBoxExtDwSubmitProcSync feiled, hr (0x%x)\n", hr);
454 return -1;
455 }
456
457 return Data.ret;
458}
459# endif /* #ifndef VBOX_WITH_WDDM */
460
461static DECLCALLBACK(void) vboxExtReleaseContextWorker(void *pvUser)
462{
463 struct wined3d_context *context = (struct wined3d_context *)pvUser;
464 VBoxTlsRefRelease(context);
465}
466
467void VBoxExtReleaseContextAsync(struct wined3d_context *context)
468{
469 HRESULT hr;
470
471 hr = VBoxExtDwSubmitProcAsync(vboxExtReleaseContextWorker, context);
472 if (FAILED(hr))
473 {
474 ERR("VBoxExtDwSubmitProcAsync feiled, hr (0x%x)\n", hr);
475 return;
476 }
477}
478
479#endif /* #if defined(VBOX_WINE_WITH_SINGLE_CONTEXT) || defined(VBOX_WINE_WITH_SINGLE_SWAPCHAIN_CONTEXT) */
480
481/* window creation API */
482static LRESULT CALLBACK vboxExtWndProc(HWND hwnd,
483 UINT uMsg,
484 WPARAM wParam,
485 LPARAM lParam
486)
487{
488 switch(uMsg)
489 {
490 case WM_CLOSE:
491 TRACE("got WM_CLOSE for hwnd(0x%x)", hwnd);
492 return 0;
493 case WM_DESTROY:
494 TRACE("got WM_DESTROY for hwnd(0x%x)", hwnd);
495 return 0;
496 case WM_NCHITTEST:
497 TRACE("got WM_NCHITTEST for hwnd(0x%x)\n", hwnd);
498 return HTNOWHERE;
499 }
500
501 return DefWindowProc(hwnd, uMsg, wParam, lParam);
502}
503
504#define VBOXEXTWND_NAME "VboxDispD3DWineWnd"
505
506static HRESULT vboxExtWndDoCleanup(void)
507{
508 HRESULT hr = S_OK;
509 HINSTANCE hInstance = (HINSTANCE)GetModuleHandle(NULL);
510 WNDCLASS wc;
511 if (GetClassInfo(hInstance, VBOXEXTWND_NAME, &wc))
512 {
513 if (!UnregisterClass(VBOXEXTWND_NAME, hInstance))
514 {
515 DWORD winEr = GetLastError();
516 ERR("UnregisterClass failed, winErr(%d)\n", winEr);
517 hr = E_FAIL;
518 }
519 }
520 return hr;
521}
522
523static HRESULT vboxExtWndDoCreate(DWORD w, DWORD h, HWND *phWnd, HDC *phDC)
524{
525 HRESULT hr = S_OK;
526 HINSTANCE hInstance = (HINSTANCE)GetModuleHandle(NULL);
527 /* Register the Window Class. */
528 WNDCLASS wc;
529 if (!GetClassInfo(hInstance, VBOXEXTWND_NAME, &wc))
530 {
531 wc.style = 0;//CS_OWNDC;
532 wc.lpfnWndProc = vboxExtWndProc;
533 wc.cbClsExtra = 0;
534 wc.cbWndExtra = 0;
535 wc.hInstance = hInstance;
536 wc.hIcon = NULL;
537 wc.hCursor = NULL;
538 wc.hbrBackground = NULL;
539 wc.lpszMenuName = NULL;
540 wc.lpszClassName = VBOXEXTWND_NAME;
541 if (!RegisterClass(&wc))
542 {
543 DWORD winErr = GetLastError();
544 ERR("RegisterClass failed, winErr(%d)\n", winErr);
545 hr = E_FAIL;
546 }
547 }
548
549 if (hr == S_OK)
550 {
551 HWND hWnd = CreateWindowEx (WS_EX_TOOLWINDOW,
552 VBOXEXTWND_NAME, VBOXEXTWND_NAME,
553 WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_DISABLED,
554 0, 0,
555 w, h,
556 NULL, //GetDesktopWindow() /* hWndParent */,
557 NULL /* hMenu */,
558 hInstance,
559 NULL /* lpParam */);
560 Assert(hWnd);
561 if (hWnd)
562 {
563 *phWnd = hWnd;
564 *phDC = GetDC(hWnd);
565 /* make sure we keep inited until the window is active */
566 vboxExtAddRef();
567 }
568 else
569 {
570 DWORD winErr = GetLastError();
571 ERR("CreateWindowEx failed, winErr(%d)\n", winErr);
572 hr = E_FAIL;
573 }
574 }
575
576 return hr;
577}
578
579static HRESULT vboxExtWndDoDestroy(HWND hWnd, HDC hDC)
580{
581 BOOL bResult;
582 DWORD winErr;
583 ReleaseDC(hWnd, hDC);
584 bResult = DestroyWindow(hWnd);
585 Assert(bResult);
586 if (bResult)
587 {
588 /* release the reference we previously acquired on window creation */
589 vboxExtRelease();
590 return S_OK;
591 }
592
593 winErr = GetLastError();
594 ERR("DestroyWindow failed, winErr(%d) for hWnd(0x%x)\n", winErr, hWnd);
595
596 return E_FAIL;
597}
598
599typedef struct VBOXEXTWND_CREATE_INFO
600{
601 int hr;
602 HWND hWnd;
603 HDC hDC;
604 DWORD width;
605 DWORD height;
606} VBOXEXTWND_CREATE_INFO;
607
608typedef struct VBOXEXTWND_DESTROY_INFO
609{
610 int hr;
611 HWND hWnd;
612 HDC hDC;
613} VBOXEXTWND_DESTROY_INFO;
614
615typedef struct VBOXEXTWND_CLEANUP_INFO
616{
617 int hr;
618} VBOXEXTWND_CLEANUP_INFO;
619
620static DECLCALLBACK(void) vboxExtWndDestroyWorker(void *pvUser)
621{
622 VBOXEXTWND_DESTROY_INFO *pInfo = (VBOXEXTWND_DESTROY_INFO*)pvUser;
623 pInfo->hr = vboxExtWndDoDestroy(pInfo->hWnd, pInfo->hDC);
624 Assert(pInfo->hr == S_OK);
625}
626
627static DECLCALLBACK(void) vboxExtWndCreateWorker(void *pvUser)
628{
629 VBOXEXTWND_CREATE_INFO *pInfo = (VBOXEXTWND_CREATE_INFO*)pvUser;
630 pInfo->hr = vboxExtWndDoCreate(pInfo->width, pInfo->height, &pInfo->hWnd, &pInfo->hDC);
631 Assert(pInfo->hr == S_OK);
632}
633
634static DECLCALLBACK(void) vboxExtWndCleanupWorker(void *pvUser)
635{
636 VBOXEXTWND_CLEANUP_INFO *pInfo = (VBOXEXTWND_CLEANUP_INFO*)pvUser;
637 pInfo-> hr = vboxExtWndDoCleanup();
638}
639
640HRESULT VBoxExtWndDestroy(HWND hWnd, HDC hDC)
641{
642 HRESULT hr;
643 VBOXEXTWND_DESTROY_INFO Info;
644 Info.hr = E_FAIL;
645 Info.hWnd = hWnd;
646 Info.hDC = hDC;
647 hr = VBoxExtDwSubmitProcSync(vboxExtWndDestroyWorker, &Info);
648 if (!SUCCEEDED(hr))
649 {
650 ERR("VBoxExtDwSubmitProcSync-vboxExtWndDestroyWorker failed hr %d", hr);
651 return hr;
652 }
653
654 if (!SUCCEEDED(Info.hr))
655 {
656 ERR("vboxExtWndDestroyWorker failed hr %d", Info.hr);
657 return Info.hr;
658 }
659
660 return S_OK;
661}
662
663HRESULT VBoxExtWndCreate(DWORD width, DWORD height, HWND *phWnd, HDC *phDC)
664{
665 HRESULT hr;
666 VBOXEXTWND_CREATE_INFO Info;
667 Info.hr = E_FAIL;
668 Info.width = width;
669 Info.height = height;
670 hr = VBoxExtDwSubmitProcSync(vboxExtWndCreateWorker, &Info);
671 if (!SUCCEEDED(hr))
672 {
673 ERR("VBoxExtDwSubmitProcSync-vboxExtWndCreateWorker failed hr %d", hr);
674 return hr;
675 }
676
677 Assert(Info.hr == S_OK);
678 if (!SUCCEEDED(Info.hr))
679 {
680 ERR("vboxExtWndCreateWorker failed hr %d", Info.hr);
681 return Info.hr;
682 }
683
684 *phWnd = Info.hWnd;
685 *phDC = Info.hDC;
686 return S_OK;
687}
688
689static HRESULT vboxExtWndCleanup(void)
690{
691 HRESULT hr;
692 VBOXEXTWND_CLEANUP_INFO Info;
693 Info.hr = E_FAIL;
694 hr = VBoxExtDwSubmitProcSync(vboxExtWndCleanupWorker, &Info);
695 if (!SUCCEEDED(hr))
696 {
697 ERR("VBoxExtDwSubmitProcSync-vboxExtWndCleanupWorker failed hr %d", hr);
698 return hr;
699 }
700
701 if (!SUCCEEDED(Info.hr))
702 {
703 ERR("vboxExtWndCleanupWorker failed hr %d", Info.hr);
704 return Info.hr;
705 }
706
707 return S_OK;
708}
709
710
711/* hash map impl */
712static void vboxExtHashInitEntries(PVBOXEXT_HASHMAP pMap)
713{
714 uint32_t i;
715 pMap->cEntries = 0;
716 for (i = 0; i < RT_ELEMENTS(pMap->aBuckets); ++i)
717 {
718 RTListInit(&pMap->aBuckets[i].EntryList);
719 }
720}
721
722void VBoxExtHashInit(PVBOXEXT_HASHMAP pMap, PFNVBOXEXT_HASHMAP_HASH pfnHash, PFNVBOXEXT_HASHMAP_EQUAL pfnEqual)
723{
724 pMap->pfnHash = pfnHash;
725 pMap->pfnEqual = pfnEqual;
726 vboxExtHashInitEntries(pMap);
727}
728
729DECLINLINE(uint32_t) vboxExtHashIdx(uint32_t u32Hash)
730{
731 return u32Hash % VBOXEXT_HASHMAP_NUM_BUCKETS;
732}
733
734#define VBOXEXT_FOREACH_NODE(_pNode, _pList, _op) do { \
735 PRTLISTNODE _pNode; \
736 PRTLISTNODE __pNext; \
737 for (_pNode = (_pList)->pNext; \
738 _pNode != (_pList); \
739 _pNode = __pNext) \
740 { \
741 __pNext = _pNode->pNext; /* <- the _pNode should not be referenced after the _op */ \
742 _op \
743 } \
744 } while (0)
745
746DECLINLINE(PVBOXEXT_HASHMAP_ENTRY) vboxExtHashSearchEntry(PVBOXEXT_HASHMAP pMap, void *pvKey)
747{
748 uint32_t u32Hash = pMap->pfnHash(pvKey);
749 uint32_t u32HashIdx = vboxExtHashIdx(u32Hash);
750 PVBOXEXT_HASHMAP_BUCKET pBucket = &pMap->aBuckets[u32HashIdx];
751 PVBOXEXT_HASHMAP_ENTRY pEntry;
752 VBOXEXT_FOREACH_NODE(pNode, &pBucket->EntryList,
753 pEntry = RT_FROM_MEMBER(pNode, VBOXEXT_HASHMAP_ENTRY, ListNode);
754 if (pEntry->u32Hash != u32Hash)
755 continue;
756
757 if (!pMap->pfnEqual(pvKey, pEntry->pvKey))
758 continue;
759 return pEntry;
760 );
761 return NULL;
762}
763
764void* VBoxExtHashRemoveEntry(PVBOXEXT_HASHMAP pMap, PVBOXEXT_HASHMAP_ENTRY pEntry)
765{
766 RTListNodeRemove(&pEntry->ListNode);
767 --pMap->cEntries;
768 Assert(pMap->cEntries <= UINT32_MAX/2);
769 return pEntry->pvKey;
770}
771
772static void vboxExtHashPutEntry(PVBOXEXT_HASHMAP pMap, PVBOXEXT_HASHMAP_BUCKET pBucket, PVBOXEXT_HASHMAP_ENTRY pEntry)
773{
774 RTListNodeInsertAfter(&pBucket->EntryList, &pEntry->ListNode);
775 ++pMap->cEntries;
776}
777
778PVBOXEXT_HASHMAP_ENTRY VBoxExtHashRemove(PVBOXEXT_HASHMAP pMap, void *pvKey)
779{
780 PVBOXEXT_HASHMAP_ENTRY pEntry = vboxExtHashSearchEntry(pMap, pvKey);
781 if (!pEntry)
782 return NULL;
783
784 VBoxExtHashRemoveEntry(pMap, pEntry);
785 return pEntry;
786}
787
788PVBOXEXT_HASHMAP_ENTRY VBoxExtHashPut(PVBOXEXT_HASHMAP pMap, void *pvKey, PVBOXEXT_HASHMAP_ENTRY pEntry)
789{
790 PVBOXEXT_HASHMAP_ENTRY pOldEntry = VBoxExtHashRemove(pMap, pvKey);
791 uint32_t u32Hash = pMap->pfnHash(pvKey);
792 uint32_t u32HashIdx = vboxExtHashIdx(u32Hash);
793 pEntry->pvKey = pvKey;
794 pEntry->u32Hash = u32Hash;
795 vboxExtHashPutEntry(pMap, &pMap->aBuckets[u32HashIdx], pEntry);
796 return pOldEntry;
797}
798
799
800PVBOXEXT_HASHMAP_ENTRY VBoxExtHashGet(PVBOXEXT_HASHMAP pMap, void *pvKey)
801{
802 return vboxExtHashSearchEntry(pMap, pvKey);
803}
804
805void VBoxExtHashVisit(PVBOXEXT_HASHMAP pMap, PFNVBOXEXT_HASHMAP_VISITOR pfnVisitor, void *pvVisitor)
806{
807 uint32_t iBucket = 0, iEntry = 0;
808 uint32_t cEntries = pMap->cEntries;
809
810 if (!cEntries)
811 return;
812
813 for (; ; ++iBucket)
814 {
815 PVBOXEXT_HASHMAP_ENTRY pEntry;
816 PVBOXEXT_HASHMAP_BUCKET pBucket = &pMap->aBuckets[iBucket];
817 Assert(iBucket < RT_ELEMENTS(pMap->aBuckets));
818 VBOXEXT_FOREACH_NODE(pNode, &pBucket->EntryList,
819 pEntry = RT_FROM_MEMBER(pNode, VBOXEXT_HASHMAP_ENTRY, ListNode);
820 if (!pfnVisitor(pMap, pEntry->pvKey, pEntry, pvVisitor))
821 return;
822
823 if (++iEntry == cEntries)
824 return;
825 );
826 }
827
828 /* should not be here! */
829 AssertFailed();
830}
831
832void VBoxExtHashCleanup(PVBOXEXT_HASHMAP pMap, PFNVBOXEXT_HASHMAP_VISITOR pfnVisitor, void *pvVisitor)
833{
834 VBoxExtHashVisit(pMap, pfnVisitor, pvVisitor);
835 vboxExtHashInitEntries(pMap);
836}
837
838static DECLCALLBACK(bool) vboxExtCacheCleanupCb(struct VBOXEXT_HASHMAP *pMap, void *pvKey, struct VBOXEXT_HASHMAP_ENTRY *pValue, void *pvVisitor)
839{
840 PVBOXEXT_HASHCACHE pCache = VBOXEXT_HASHCACHE_FROM_MAP(pMap);
841 PVBOXEXT_HASHCACHE_ENTRY pCacheEntry = VBOXEXT_HASHCACHE_ENTRY_FROM_MAP(pValue);
842 pCache->pfnCleanupEntry(pvKey, pCacheEntry);
843 return TRUE;
844}
845
846void VBoxExtCacheCleanup(PVBOXEXT_HASHCACHE pCache)
847{
848 VBoxExtHashCleanup(&pCache->Map, vboxExtCacheCleanupCb, NULL);
849}
850
851#if defined(VBOXWINEDBG_SHADERS) || defined(VBOX_WINE_WITH_PROFILE)
852void vboxWDbgPrintF(char * szString, ...)
853{
854 char szBuffer[4096*2] = {0};
855 va_list pArgList;
856 va_start(pArgList, szString);
857 _vsnprintf(szBuffer, sizeof(szBuffer) / sizeof(szBuffer[0]), szString, pArgList);
858 va_end(pArgList);
859
860 OutputDebugStringA(szBuffer);
861}
862#endif
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