VirtualBox

source: vbox/trunk/src/VBox/Additions/common/crOpenGL/load.c@ 34418

最後變更 在這個檔案從34418是 34345,由 vboxsync 提交於 14 年 前

wddm/3d: propper hide host window on swapchain destruction

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Id
檔案大小: 32.5 KB
 
1/* Copyright (c) 2001, Stanford University
2 * All rights reserved
3 *
4 * See the file LICENSE.txt for information on redistributing this software.
5 */
6
7#include "cr_spu.h"
8#include "cr_net.h"
9#include "cr_error.h"
10#include "cr_mem.h"
11#include "cr_string.h"
12#include "cr_net.h"
13#include "cr_environment.h"
14#include "cr_process.h"
15#include "cr_rand.h"
16#include "cr_netserver.h"
17#include "stub.h"
18#include <stdlib.h>
19#include <string.h>
20#include <signal.h>
21#include <iprt/initterm.h>
22#include <iprt/thread.h>
23#include <iprt/err.h>
24#include <iprt/asm.h>
25#ifndef WINDOWS
26# include <sys/types.h>
27# include <unistd.h>
28#endif
29#ifdef CHROMIUM_THREADSAFE
30#include "cr_threads.h"
31#endif
32
33#ifdef VBOX_WITH_WDDM
34#include <d3d9types.h>
35#include <D3dumddi.h>
36#include "../../WINNT/Graphics/Miniport/wddm/VBoxVideoIf.h"
37#include "../../WINNT/Graphics/Display/wddm/vboxdispmp.h"
38#endif
39
40/**
41 * If you change this, see the comments in tilesortspu_context.c
42 */
43#define MAGIC_CONTEXT_BASE 500
44
45#define CONFIG_LOOKUP_FILE ".crconfigs"
46
47#ifdef WINDOWS
48#define PYTHON_EXE "python.exe"
49#else
50#define PYTHON_EXE "python"
51#endif
52
53#ifdef WINDOWS
54static char* gsViewportHackApps[] = {"googleearth.exe", NULL};
55#endif
56
57static int stub_initialized = 0;
58
59/* NOTE: 'SPUDispatchTable glim' is declared in NULLfuncs.py now */
60/* NOTE: 'SPUDispatchTable stubThreadsafeDispatch' is declared in tsfuncs.c */
61Stub stub;
62
63
64static void stubInitNativeDispatch( void )
65{
66#define MAX_FUNCS 1000
67 SPUNamedFunctionTable gl_funcs[MAX_FUNCS];
68 int numFuncs;
69
70 numFuncs = crLoadOpenGL( &stub.wsInterface, gl_funcs );
71
72 stub.haveNativeOpenGL = (numFuncs > 0);
73
74 /* XXX call this after context binding */
75 numFuncs += crLoadOpenGLExtensions( &stub.wsInterface, gl_funcs + numFuncs );
76
77 CRASSERT(numFuncs < MAX_FUNCS);
78
79 crSPUInitDispatchTable( &stub.nativeDispatch );
80 crSPUInitDispatch( &stub.nativeDispatch, gl_funcs );
81 crSPUInitDispatchNops( &stub.nativeDispatch );
82#undef MAX_FUNCS
83}
84
85
86/** Pointer to the SPU's real glClear and glViewport functions */
87static ClearFunc_t origClear;
88static ViewportFunc_t origViewport;
89static SwapBuffersFunc_t origSwapBuffers;
90static DrawBufferFunc_t origDrawBuffer;
91static ScissorFunc_t origScissor;
92
93static void stubCheckWindowState(WindowInfo *window, GLboolean bFlushOnChange)
94{
95 bool bForceUpdate = false;
96 bool bChanged = false;
97
98#ifdef WINDOWS
99 /* @todo install hook and track for WM_DISPLAYCHANGE */
100 {
101 DEVMODE devMode;
102
103 devMode.dmSize = sizeof(DEVMODE);
104 EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &devMode);
105
106 if (devMode.dmPelsWidth!=window->dmPelsWidth || devMode.dmPelsHeight!=window->dmPelsHeight)
107 {
108 crDebug("Resolution changed(%d,%d), forcing window Pos/Size update", devMode.dmPelsWidth, devMode.dmPelsHeight);
109 window->dmPelsWidth = devMode.dmPelsWidth;
110 window->dmPelsHeight = devMode.dmPelsHeight;
111 bForceUpdate = true;
112 }
113 }
114#endif
115
116 bChanged = stubUpdateWindowGeometry(window, bForceUpdate) || bForceUpdate;
117
118#if defined(GLX) || defined (WINDOWS)
119 if (stub.trackWindowVisibleRgn)
120 {
121 bChanged = stubUpdateWindowVisibileRegions(window) || bChanged;
122 }
123#endif
124
125 if (stub.trackWindowVisibility && window->type == CHROMIUM && window->drawable) {
126 const int mapped = stubIsWindowVisible(window);
127 if (mapped != window->mapped) {
128 crDebug("Dispatched: WindowShow(%i, %i)", window->spuWindow, mapped);
129 stub.spu->dispatch_table.WindowShow(window->spuWindow, mapped);
130 window->mapped = mapped;
131 bChanged = true;
132 }
133 }
134
135 if (bFlushOnChange && bChanged)
136 {
137 stub.spu->dispatch_table.Flush();
138 }
139}
140
141static bool stubSystemWindowExist(WindowInfo *pWindow)
142{
143#ifdef WINDOWS
144 if (pWindow->hWnd!=WindowFromDC(pWindow->drawable))
145 {
146 return false;
147 }
148#else
149 Window root;
150 int x, y;
151 unsigned int border, depth, w, h;
152 Display *dpy;
153
154 dpy = stubGetWindowDisplay(pWindow);
155
156 XLOCK(dpy);
157 if (!XGetGeometry(dpy, pWindow->drawable, &root, &x, &y, &w, &h, &border, &depth))
158 {
159 XUNLOCK(dpy);
160 return false;
161 }
162 XUNLOCK(dpy);
163#endif
164
165 return true;
166}
167
168static void stubCheckWindowsCB(unsigned long key, void *data1, void *data2)
169{
170 WindowInfo *pWindow = (WindowInfo *) data1;
171 ContextInfo *pCtx = (ContextInfo *) data2;
172
173 if (pWindow == pCtx->currentDrawable
174 || pWindow->type!=CHROMIUM
175 || pWindow->pOwner!=pCtx)
176 {
177 return;
178 }
179
180 if (!stubSystemWindowExist(pWindow))
181 {
182#ifdef WINDOWS
183 crWindowDestroy((GLint)pWindow->hWnd);
184#else
185 crWindowDestroy((GLint)pWindow->drawable);
186#endif
187 return;
188 }
189
190 stubCheckWindowState(pWindow, GL_FALSE);
191}
192
193static void stubCheckWindowsState(void)
194{
195 CRASSERT(stub.trackWindowSize || stub.trackWindowPos);
196
197 if (!stub.currentContext)
198 return;
199
200#if defined(WINDOWS) && defined(VBOX_WITH_WDDM)
201 if (stub.bRunningUnderWDDM)
202 return;
203#endif
204
205#if defined(CR_NEWWINTRACK) && !defined(WINDOWS)
206 crLockMutex(&stub.mutex);
207#endif
208
209 stubCheckWindowState(stub.currentContext->currentDrawable, GL_TRUE);
210 crHashtableWalk(stub.windowTable, stubCheckWindowsCB, stub.currentContext);
211
212#if defined(CR_NEWWINTRACK) && !defined(WINDOWS)
213 crUnlockMutex(&stub.mutex);
214#endif
215}
216
217
218/**
219 * Override the head SPU's glClear function.
220 * We're basically trapping this function so that we can poll the
221 * application window size at a regular interval.
222 */
223static void SPU_APIENTRY trapClear(GLbitfield mask)
224{
225 stubCheckWindowsState();
226 /* call the original SPU glClear function */
227 origClear(mask);
228}
229
230/**
231 * As above, but for glViewport. Most apps call glViewport before
232 * glClear when a window is resized.
233 */
234static void SPU_APIENTRY trapViewport(GLint x, GLint y, GLsizei w, GLsizei h)
235{
236 stubCheckWindowsState();
237 /* call the original SPU glViewport function */
238 if (!stub.viewportHack)
239 {
240 origViewport(x, y, w, h);
241 }
242 else
243 {
244 int winX, winY;
245 unsigned int winW, winH;
246 WindowInfo *pWindow;
247 pWindow = stub.currentContext->currentDrawable;
248 stubGetWindowGeometry(pWindow, &winX, &winY, &winW, &winH);
249 origViewport(0, 0, winW, winH);
250 }
251}
252
253static void SPU_APIENTRY trapSwapBuffers(GLint window, GLint flags)
254{
255 stubCheckWindowsState();
256 origSwapBuffers(window, flags);
257}
258
259static void SPU_APIENTRY trapDrawBuffer(GLenum buf)
260{
261 stubCheckWindowsState();
262 origDrawBuffer(buf);
263}
264
265static void SPU_APIENTRY trapScissor(GLint x, GLint y, GLsizei w, GLsizei h)
266{
267 int winX, winY;
268 unsigned int winW, winH;
269 WindowInfo *pWindow;
270 pWindow = stub.currentContext->currentDrawable;
271 stubGetWindowGeometry(pWindow, &winX, &winY, &winW, &winH);
272 origScissor(0, 0, winW, winH);
273}
274
275/**
276 * Use the GL function pointers in <spu> to initialize the static glim
277 * dispatch table.
278 */
279static void stubInitSPUDispatch(SPU *spu)
280{
281 crSPUInitDispatchTable( &stub.spuDispatch );
282 crSPUCopyDispatchTable( &stub.spuDispatch, &(spu->dispatch_table) );
283
284 if (stub.trackWindowSize || stub.trackWindowPos || stub.trackWindowVisibleRgn) {
285 /* patch-in special glClear/Viewport function to track window sizing */
286 origClear = stub.spuDispatch.Clear;
287 origViewport = stub.spuDispatch.Viewport;
288 origSwapBuffers = stub.spuDispatch.SwapBuffers;
289 origDrawBuffer = stub.spuDispatch.DrawBuffer;
290 origScissor = stub.spuDispatch.Scissor;
291 stub.spuDispatch.Clear = trapClear;
292 stub.spuDispatch.Viewport = trapViewport;
293
294 if (stub.viewportHack)
295 stub.spuDispatch.Scissor = trapScissor;
296 /*stub.spuDispatch.SwapBuffers = trapSwapBuffers;
297 stub.spuDispatch.DrawBuffer = trapDrawBuffer;*/
298 }
299
300 crSPUCopyDispatchTable( &glim, &stub.spuDispatch );
301}
302
303// Callback function, used to destroy all created contexts
304static void hsWalkStubDestroyContexts(unsigned long key, void *data1, void *data2)
305{
306 stubDestroyContext(key);
307}
308
309/**
310 * This is called when we exit.
311 * We call all the SPU's cleanup functions.
312 */
313static void stubSPUTearDown(void)
314{
315 crDebug("stubSPUTearDown");
316 if (!stub_initialized) return;
317
318 stub_initialized = 0;
319
320#ifdef WINDOWS
321# ifndef CR_NEWWINTRACK
322 stubUninstallWindowMessageHook();
323# endif
324#endif
325
326#ifdef CR_NEWWINTRACK
327 ASMAtomicWriteBool(&stub.bShutdownSyncThread, true);
328#endif
329
330 //delete all created contexts
331 stubMakeCurrent( NULL, NULL);
332 crHashtableWalk(stub.contextTable, hsWalkStubDestroyContexts, NULL);
333
334 /* shutdown, now trap any calls to a NULL dispatcher */
335 crSPUCopyDispatchTable(&glim, &stubNULLDispatch);
336
337 crSPUUnloadChain(stub.spu);
338 stub.spu = NULL;
339
340#ifndef Linux
341 crUnloadOpenGL();
342#endif
343
344 crNetTearDown();
345
346#ifdef GLX
347 if (stub.xshmSI.shmid>=0)
348 {
349 shmctl(stub.xshmSI.shmid, IPC_RMID, 0);
350 shmdt(stub.xshmSI.shmaddr);
351 }
352 crFreeHashtable(stub.pGLXPixmapsHash, crFree);
353#endif
354
355 crFreeHashtable(stub.windowTable, crFree);
356 crFreeHashtable(stub.contextTable, NULL);
357
358 crMemset(&stub, 0, sizeof(stub));
359}
360
361static void stubSPUSafeTearDown(void)
362{
363#ifdef CHROMIUM_THREADSAFE
364 CRmutex *mutex;
365#endif
366
367 if (!stub_initialized) return;
368 stub_initialized = 0;
369
370#ifdef CHROMIUM_THREADSAFE
371 mutex = &stub.mutex;
372 crLockMutex(mutex);
373#endif
374 crDebug("stubSPUSafeTearDown");
375
376#ifdef WINDOWS
377# ifndef CR_NEWWINTRACK
378 stubUninstallWindowMessageHook();
379# endif
380#endif
381
382#if defined(CR_NEWWINTRACK)
383 crUnlockMutex(mutex);
384# if defined(WINDOWS)
385 if (RTThreadGetState(stub.hSyncThread)!=RTTHREADSTATE_TERMINATED)
386 {
387 ASMAtomicWriteBool(&stub.bShutdownSyncThread, true);
388 if (PostThreadMessage(RTThreadGetNative(stub.hSyncThread), WM_QUIT, 0, 0))
389 {
390 RTThreadWait(stub.hSyncThread, 1000, NULL);
391 }
392 else
393 {
394 crDebug("Sync thread killed before DLL_PROCESS_DETACH");
395 }
396 }
397#else
398 if (stub.hSyncThread!=NIL_RTTHREAD)
399 {
400 ASMAtomicWriteBool(&stub.bShutdownSyncThread, true);
401 {
402 /*RTThreadWait might return too early, which cause our code being unloaded while RT thread wrapper is still running*/
403 int rc = pthread_join(RTThreadGetNative(stub.hSyncThread), NULL);
404 if (!rc)
405 {
406 crDebug("pthread_join failed %i", rc);
407 }
408 }
409 }
410#endif
411 crLockMutex(mutex);
412#endif
413
414 crNetTearDown();
415#ifdef CHROMIUM_THREADSAFE
416 crUnlockMutex(mutex);
417 crFreeMutex(mutex);
418#endif
419 crMemset(&stub, 0, sizeof(stub));
420}
421
422
423static void stubExitHandler(void)
424{
425 stubSPUSafeTearDown();
426}
427
428/**
429 * Called when we receive a SIGTERM signal.
430 */
431static void stubSignalHandler(int signo)
432{
433 stubSPUSafeTearDown();
434 exit(0); /* this causes stubExitHandler() to be called */
435}
436
437
438/**
439 * Init variables in the stub structure, install signal handler.
440 */
441static void stubInitVars(void)
442{
443 WindowInfo *defaultWin;
444
445#ifdef CHROMIUM_THREADSAFE
446 crInitMutex(&stub.mutex);
447#endif
448
449 /* At the very least we want CR_RGB_BIT. */
450 stub.haveNativeOpenGL = GL_FALSE;
451 stub.spu = NULL;
452 stub.appDrawCursor = 0;
453 stub.minChromiumWindowWidth = 0;
454 stub.minChromiumWindowHeight = 0;
455 stub.maxChromiumWindowWidth = 0;
456 stub.maxChromiumWindowHeight = 0;
457 stub.matchChromiumWindowCount = 0;
458 stub.matchChromiumWindowID = NULL;
459 stub.matchWindowTitle = NULL;
460 stub.ignoreFreeglutMenus = 0;
461 stub.threadSafe = GL_FALSE;
462 stub.trackWindowSize = 0;
463 stub.trackWindowPos = 0;
464 stub.trackWindowVisibility = 0;
465 stub.trackWindowVisibleRgn = 0;
466 stub.mothershipPID = 0;
467 stub.spu_dir = NULL;
468
469 stub.freeContextNumber = MAGIC_CONTEXT_BASE;
470 stub.contextTable = crAllocHashtable();
471 stub.currentContext = NULL;
472
473 stub.windowTable = crAllocHashtable();
474
475#ifdef CR_NEWWINTRACK
476 stub.bShutdownSyncThread = false;
477 stub.hSyncThread = NIL_RTTHREAD;
478#endif
479
480 defaultWin = (WindowInfo *) crCalloc(sizeof(WindowInfo));
481 defaultWin->type = CHROMIUM;
482 defaultWin->spuWindow = 0; /* window 0 always exists */
483#ifdef WINDOWS
484 defaultWin->hVisibleRegion = INVALID_HANDLE_VALUE;
485#elif defined(GLX)
486 defaultWin->pVisibleRegions = NULL;
487 defaultWin->cVisibleRegions = 0;
488#endif
489 crHashtableAdd(stub.windowTable, 0, defaultWin);
490
491#if 1
492 atexit(stubExitHandler);
493 signal(SIGTERM, stubSignalHandler);
494 signal(SIGINT, stubSignalHandler);
495#ifndef WINDOWS
496 signal(SIGPIPE, SIG_IGN); /* the networking code should catch this */
497#endif
498#else
499 (void) stubExitHandler;
500 (void) stubSignalHandler;
501#endif
502}
503
504
505/**
506 * Return a free port number for the mothership to use, or -1 if we
507 * can't find one.
508 */
509static int
510GenerateMothershipPort(void)
511{
512 const int MAX_PORT = 10100;
513 unsigned short port;
514
515 /* generate initial port number randomly */
516 crRandAutoSeed();
517 port = (unsigned short) crRandInt(10001, MAX_PORT);
518
519#ifdef WINDOWS
520 /* XXX should implement a free port check here */
521 return port;
522#else
523 /*
524 * See if this port number really is free, try another if needed.
525 */
526 {
527 struct sockaddr_in servaddr;
528 int so_reuseaddr = 1;
529 int sock, k;
530
531 /* create socket */
532 sock = socket(AF_INET, SOCK_STREAM, 0);
533 CRASSERT(sock > 2);
534
535 /* deallocate socket/port when we exit */
536 k = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
537 (char *) &so_reuseaddr, sizeof(so_reuseaddr));
538 CRASSERT(k == 0);
539
540 /* initialize the servaddr struct */
541 crMemset(&servaddr, 0, sizeof(servaddr) );
542 servaddr.sin_family = AF_INET;
543 servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
544
545 while (port < MAX_PORT) {
546 /* Bind to the given port number, return -1 if we fail */
547 servaddr.sin_port = htons((unsigned short) port);
548 k = bind(sock, (struct sockaddr *) &servaddr, sizeof(servaddr));
549 if (k) {
550 /* failed to create port. try next one. */
551 port++;
552 }
553 else {
554 /* free the socket/port now so mothership can make it */
555 close(sock);
556 return port;
557 }
558 }
559 }
560#endif /* WINDOWS */
561 return -1;
562}
563
564
565/**
566 * Try to determine which mothership configuration to use for this program.
567 */
568static char **
569LookupMothershipConfig(const char *procName)
570{
571 const int procNameLen = crStrlen(procName);
572 FILE *f;
573 const char *home;
574 char configPath[1000];
575
576 /* first, check if the CR_CONFIG env var is set */
577 {
578 const char *conf = crGetenv("CR_CONFIG");
579 if (conf && crStrlen(conf) > 0)
580 return crStrSplit(conf, " ");
581 }
582
583 /* second, look up config name from config file */
584 home = crGetenv("HOME");
585 if (home)
586 sprintf(configPath, "%s/%s", home, CONFIG_LOOKUP_FILE);
587 else
588 crStrcpy(configPath, CONFIG_LOOKUP_FILE); /* from current dir */
589 /* Check if the CR_CONFIG_PATH env var is set. */
590 {
591 const char *conf = crGetenv("CR_CONFIG_PATH");
592 if (conf)
593 crStrcpy(configPath, conf); /* from env var */
594 }
595
596 f = fopen(configPath, "r");
597 if (!f) {
598 return NULL;
599 }
600
601 while (!feof(f)) {
602 char line[1000];
603 char **args;
604 fgets(line, 999, f);
605 line[crStrlen(line) - 1] = 0; /* remove trailing newline */
606 if (crStrncmp(line, procName, procNameLen) == 0 &&
607 (line[procNameLen] == ' ' || line[procNameLen] == '\t'))
608 {
609 crWarning("Using Chromium configuration for %s from %s",
610 procName, configPath);
611 args = crStrSplit(line + procNameLen + 1, " ");
612 return args;
613 }
614 }
615 fclose(f);
616 return NULL;
617}
618
619
620static int Mothership_Awake = 0;
621
622
623/**
624 * Signal handler to determine when mothership is ready.
625 */
626static void
627MothershipPhoneHome(int signo)
628{
629 crDebug("Got signal %d: mothership is awake!", signo);
630 Mothership_Awake = 1;
631}
632
633void stubSetDefaultConfigurationOptions(void)
634{
635 unsigned char key[16]= {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
636
637 stub.appDrawCursor = 0;
638 stub.minChromiumWindowWidth = 0;
639 stub.minChromiumWindowHeight = 0;
640 stub.maxChromiumWindowWidth = 0;
641 stub.maxChromiumWindowHeight = 0;
642 stub.matchChromiumWindowID = NULL;
643 stub.numIgnoreWindowID = 0;
644 stub.matchWindowTitle = NULL;
645 stub.ignoreFreeglutMenus = 0;
646 stub.trackWindowSize = 1;
647 stub.trackWindowPos = 1;
648 stub.trackWindowVisibility = 1;
649 stub.trackWindowVisibleRgn = 1;
650 stub.matchChromiumWindowCount = 0;
651 stub.spu_dir = NULL;
652 crNetSetRank(0);
653 crNetSetContextRange(32, 35);
654 crNetSetNodeRange("iam0", "iamvis20");
655 crNetSetKey(key,sizeof(key));
656 stub.force_pbuffers = 0;
657 stub.viewportHack = 0;
658
659#ifdef WINDOWS
660 {
661 char name[1000];
662 int i;
663
664# ifdef VBOX_WITH_WDDM
665 stub.bRunningUnderWDDM = false;
666# endif
667 /* Apply viewport hack only if we're running under wine */
668 if (NULL!=GetModuleHandle("wined3d.dll") || NULL != GetModuleHandle("wined3dwddm.dll"))
669 {
670 crGetProcName(name, 1000);
671 for (i=0; gsViewportHackApps[i]; ++i)
672 {
673 if (!stricmp(name, gsViewportHackApps[i]))
674 {
675 stub.viewportHack = 1;
676 break;
677 }
678 }
679 }
680 }
681#endif
682}
683
684#ifdef CR_NEWWINTRACK
685# ifdef VBOX_WITH_WDDM
686static stubDispatchVisibleRegions(WindowInfo *pWindow)
687{
688 DWORD dwCount;
689 LPRGNDATA lpRgnData;
690
691 dwCount = GetRegionData(pWindow->hVisibleRegion, 0, NULL);
692 lpRgnData = crAlloc(dwCount);
693
694 if (lpRgnData)
695 {
696 GetRegionData(pWindow->hVisibleRegion, dwCount, lpRgnData);
697 crDebug("Dispatched WindowVisibleRegion (%i, cRects=%i)", pWindow->spuWindow, lpRgnData->rdh.nCount);
698 stub.spuDispatch.WindowVisibleRegion(pWindow->spuWindow, lpRgnData->rdh.nCount, (GLint*) lpRgnData->Buffer);
699 crFree(lpRgnData);
700 }
701 else crWarning("GetRegionData failed, VisibleRegions update failed");
702}
703
704static HRGN stubMakeRegionFromRects(PVBOXVIDEOCM_CMD_RECTS pRegions, uint32_t start)
705{
706 HRGN hRgn, hTmpRgn;
707 uint32_t i;
708
709 if (pRegions->RectsInfo.cRects<=start)
710 {
711 return INVALID_HANDLE_VALUE;
712 }
713
714 hRgn = CreateRectRgn(0, 0, 0, 0);
715 for (i=start; i<pRegions->RectsInfo.cRects; ++i)
716 {
717 hTmpRgn = CreateRectRgnIndirect(&pRegions->RectsInfo.aRects[i]);
718 CombineRgn(hRgn, hRgn, hTmpRgn, RGN_OR);
719 DeleteObject(hTmpRgn);
720 }
721 return hRgn;
722}
723
724static void stubSyncTrUpdateWindowCB(unsigned long key, void *data1, void *data2)
725{
726 WindowInfo *pWindow = (WindowInfo *) data1;
727 VBOXDISPMP_REGIONS *pRegions = (VBOXDISPMP_REGIONS*) data2;
728 bool bChanged = false;
729 HRGN hNewRgn = INVALID_HANDLE_VALUE;
730
731 if (pRegions->hWnd != pWindow->hWnd)
732 {
733 return;
734 }
735
736 stub.spu->dispatch_table.VBoxPackSetInjectID(pWindow->u32ClientID);
737
738 if (!stubSystemWindowExist(pWindow))
739 {
740 crWindowDestroy((GLint)pWindow->hWnd);
741 return;
742 }
743
744 if (!pWindow->mapped)
745 {
746 pWindow->mapped = GL_TRUE;
747 bChanged = true;
748 crDebug("Dispatched: WindowShow(%i, %i)", pWindow->spuWindow, pWindow->mapped);
749 stub.spu->dispatch_table.WindowShow(pWindow->spuWindow, pWindow->mapped);
750 }
751
752 if (pRegions->pRegions->fFlags.bSetVisibleRects && pRegions->pRegions->fFlags.bSetViewRect)
753 {
754 int winX, winY;
755 unsigned int winW, winH;
756
757 winX = pRegions->pRegions->RectsInfo.aRects[0].left;
758 winY = pRegions->pRegions->RectsInfo.aRects[0].top;
759 winW = pRegions->pRegions->RectsInfo.aRects[0].right - winX;
760 winH = pRegions->pRegions->RectsInfo.aRects[0].bottom - winY;
761
762 if (stub.trackWindowPos && (winX!=pWindow->x || winY!=pWindow->y))
763 {
764 crDebug("Dispatched WindowPosition (%i)", pWindow->spuWindow);
765 stub.spuDispatch.WindowPosition(pWindow->spuWindow, winX, winY);
766 pWindow->x = winX;
767 pWindow->y = winY;
768 bChanged = true;
769 }
770
771 if (stub.trackWindowSize && (winW!=pWindow->width || winH!=pWindow->height))
772 {
773 crDebug("Dispatched WindowSize (%i)", pWindow->spuWindow);
774 stub.spuDispatch.WindowSize(pWindow->spuWindow, winW, winH);
775 pWindow->width = winW;
776 pWindow->height = winH;
777 bChanged = true;
778 }
779
780 hNewRgn = stubMakeRegionFromRects(pRegions->pRegions, 1);
781
782 /* ensure the window is in sync to avoid possible incorrect host notifications */
783 {
784 BOOL bRc = MoveWindow(pRegions->hWnd, winX, winY, winW, winH, FALSE /*BOOL bRepaint*/);
785 if (!bRc)
786 {
787 DWORD winEr = GetLastError();
788 crWarning("stubSyncTrUpdateWindowCB: MoveWindow failed winEr(%d)", winEr);
789 }
790 }
791 }
792 else if (!pRegions->pRegions->fFlags.bHide)
793 {
794 Assert(pRegions->pRegions->fFlags.bAddHiddenRects);
795 hNewRgn = stubMakeRegionFromRects(pRegions->pRegions, 0);
796 }
797 else
798 {
799 Assert(pRegions->pRegions->fFlags.bAddHiddenRects);
800 hNewRgn = CreateRectRgn(pWindow->x, pWindow->y, pWindow->x + pWindow->width, pWindow->y + pWindow->height);
801 }
802
803 if (hNewRgn!=INVALID_HANDLE_VALUE)
804 {
805 OffsetRgn(hNewRgn, -pWindow->x, -pWindow->y);
806
807 if (pWindow->hVisibleRegion!=INVALID_HANDLE_VALUE)
808 {
809 CombineRgn(hNewRgn, pWindow->hVisibleRegion, hNewRgn,
810 pRegions->pRegions->fFlags.bAddHiddenRects ? RGN_DIFF:RGN_OR);
811
812 if (!EqualRgn(pWindow->hVisibleRegion, hNewRgn))
813 {
814 DeleteObject(pWindow->hVisibleRegion);
815 pWindow->hVisibleRegion = hNewRgn;
816 stubDispatchVisibleRegions(pWindow);
817 bChanged = true;
818 }
819 else
820 {
821 DeleteObject(hNewRgn);
822 }
823 }
824 else
825 {
826 if (pRegions->pRegions->fFlags.bSetVisibleRects)
827 {
828 pWindow->hVisibleRegion = hNewRgn;
829 stubDispatchVisibleRegions(pWindow);
830 bChanged = true;
831 }
832 }
833 }
834
835 if (bChanged)
836 {
837 stub.spu->dispatch_table.Flush();
838 }
839}
840# endif
841
842static void stubSyncTrCheckWindowsCB(unsigned long key, void *data1, void *data2)
843{
844 WindowInfo *pWindow = (WindowInfo *) data1;
845 (void) data2;
846
847 if (pWindow->type!=CHROMIUM || pWindow->spuWindow==0)
848 {
849 return;
850 }
851
852 stub.spu->dispatch_table.VBoxPackSetInjectID(pWindow->u32ClientID);
853
854 if (!stubSystemWindowExist(pWindow))
855 {
856#ifdef WINDOWS
857 crWindowDestroy((GLint)pWindow->hWnd);
858#else
859 crWindowDestroy((GLint)pWindow->drawable);
860#endif
861 /*No need to flush here as crWindowDestroy does it*/
862 return;
863 }
864
865#if defined(WINDOWS) && defined(VBOX_WITH_WDDM)
866 if (stub.bRunningUnderWDDM)
867 return;
868#endif
869 stubCheckWindowState(pWindow, GL_TRUE);
870}
871
872static DECLCALLBACK(int) stubSyncThreadProc(RTTHREAD ThreadSelf, void *pvUser)
873{
874#ifdef WINDOWS
875 MSG msg;
876# ifdef VBOX_WITH_WDDM
877 static VBOXDISPMP_CALLBACKS VBoxDispMpTstCallbacks = {NULL, NULL, NULL};
878 HMODULE hVBoxD3D = NULL;
879 VBOXDISPMP_REGIONS Regions;
880 HRESULT hr;
881# endif
882#endif
883
884 (void) pvUser;
885
886 crDebug("Sync thread started");
887#ifdef WINDOWS
888 PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
889# ifdef VBOX_WITH_WDDM
890 if (GetModuleHandleEx(0, "VBoxDispD3D", &hVBoxD3D))
891 {
892 PFNVBOXDISPMP_GETCALLBACKS pfnVBoxDispMpGetCallbacks;
893 pfnVBoxDispMpGetCallbacks = (PFNVBOXDISPMP_GETCALLBACKS)GetProcAddress(hVBoxD3D, TEXT("VBoxDispMpGetCallbacks"));
894 if (pfnVBoxDispMpGetCallbacks)
895 {
896 hr = pfnVBoxDispMpGetCallbacks(VBOXDISPMP_VERSION, &VBoxDispMpTstCallbacks);
897 if (S_OK==hr)
898 {
899 CRASSERT(VBoxDispMpTstCallbacks.pfnEnableEvents);
900 CRASSERT(VBoxDispMpTstCallbacks.pfnDisableEvents);
901 CRASSERT(VBoxDispMpTstCallbacks.pfnGetRegions);
902
903 hr = VBoxDispMpTstCallbacks.pfnEnableEvents();
904 if (hr != S_OK)
905 {
906 crWarning("VBoxDispMpTstCallbacks.pfnEnableEvents failed");
907 }
908 else
909 {
910 crDebug("running with VBoxDispD3D");
911 stub.trackWindowVisibleRgn = 0;
912 stub.bRunningUnderWDDM = true;
913 }
914 }
915 else
916 {
917 crWarning("VBoxDispMpGetCallbacks failed");
918 }
919 }
920 }
921# endif
922#endif
923
924 crLockMutex(&stub.mutex);
925 stub.spu->dispatch_table.VBoxPackSetInjectThread();
926 crUnlockMutex(&stub.mutex);
927
928 RTThreadUserSignal(ThreadSelf);
929
930 while(!stub.bShutdownSyncThread)
931 {
932#ifdef WINDOWS
933 if (!PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
934 {
935# ifdef VBOX_WITH_WDDM
936 if (VBoxDispMpTstCallbacks.pfnGetRegions)
937 {
938 hr = VBoxDispMpTstCallbacks.pfnGetRegions(&Regions, 50);
939 if (S_OK==hr)
940 {
941# if 0
942 uint32_t i;
943 crDebug(">>>Regions for HWND(0x%x)>>>", Regions.hWnd);
944 crDebug("Flags(0x%x)", Regions.pRegions->fFlags.Value);
945 for (i = 0; i < Regions.pRegions->RectsInfo.cRects; ++i)
946 {
947 RECT *pRect = &Regions.pRegions->RectsInfo.aRects[i];
948 crDebug("Rect(%d): left(%d), top(%d), right(%d), bottom(%d)", i, pRect->left, pRect->top, pRect->right, pRect->bottom);
949 }
950 crDebug("<<<<<");
951# endif
952 /*hacky way to make sure window wouldn't be deleted in another thread as we hold hashtable lock here*/
953 crHashtableWalk(stub.windowTable, stubSyncTrUpdateWindowCB, &Regions);
954 }
955 else
956 {
957 if (WAIT_TIMEOUT!=hr)
958 {
959 crWarning("VBoxDispMpTstCallbacks.pfnGetRegions failed with 0x%x", hr);
960 }
961 crHashtableWalk(stub.windowTable, stubSyncTrCheckWindowsCB, NULL);
962 }
963 }
964 else
965# endif
966 {
967 crHashtableWalk(stub.windowTable, stubSyncTrCheckWindowsCB, NULL);
968 RTThreadSleep(50);
969 }
970 }
971 else
972 {
973 if (WM_QUIT==msg.message)
974 {
975 crDebug("Sync thread got WM_QUIT");
976 break;
977 }
978 else
979 {
980 TranslateMessage(&msg);
981 DispatchMessage(&msg);
982 }
983 }
984#else
985 crLockMutex(&stub.mutex);
986 crHashtableWalk(stub.windowTable, stubSyncTrCheckWindowsCB, NULL);
987 crUnlockMutex(&stub.mutex);
988 RTThreadSleep(50);
989#endif
990 }
991
992#ifdef VBOX_WITH_WDDM
993 if (VBoxDispMpTstCallbacks.pfnDisableEvents)
994 {
995 VBoxDispMpTstCallbacks.pfnDisableEvents();
996 }
997 if (hVBoxD3D)
998 {
999 FreeLibrary(hVBoxD3D);
1000 }
1001#endif
1002 crDebug("Sync thread stopped");
1003 return 0;
1004}
1005#endif
1006
1007/**
1008 * Do one-time initializations for the faker.
1009 * Returns TRUE on success, FALSE otherwise.
1010 */
1011bool
1012stubInit(void)
1013{
1014 /* Here is where we contact the mothership to find out what we're supposed
1015 * to be doing. Networking code in a DLL initializer. I sure hope this
1016 * works :)
1017 *
1018 * HOW can I pass the mothership address to this if I already know it?
1019 */
1020
1021 CRConnection *conn = NULL;
1022 char response[1024];
1023 char **spuchain;
1024 int num_spus;
1025 int *spu_ids;
1026 char **spu_names;
1027 const char *app_id;
1028 int i;
1029 int disable_sync = 0;
1030
1031 if (stub_initialized)
1032 return true;
1033
1034 stubInitVars();
1035
1036 crGetProcName(response, 1024);
1037 crDebug("Stub launched for %s", response);
1038
1039#if defined(CR_NEWWINTRACK) && !defined(WINDOWS)
1040 /*@todo when vm boots with compiz turned on, new code causes hang in xcb_wait_for_reply in the sync thread*/
1041 if (!crStrcmp(response, "compiz") || !crStrcmp(response, "compiz_real")
1042 || !crStrcmp(response, "compiz-bin"))
1043 {
1044 disable_sync = 1;
1045 }
1046#endif
1047
1048 /* @todo check if it'd be of any use on other than guests, no use for windows */
1049 app_id = crGetenv( "CR_APPLICATION_ID_NUMBER" );
1050
1051 crNetInit( NULL, NULL );
1052
1053#ifndef WINDOWS
1054 {
1055 CRNetServer ns;
1056
1057 ns.name = "vboxhgcm://host:0";
1058 ns.buffer_size = 1024;
1059 crNetServerConnect(&ns);
1060 if (!ns.conn)
1061 {
1062 crWarning("Failed to connect to host. Make sure 3D acceleration is enabled for this VM.");
1063 return false;
1064 }
1065 else
1066 {
1067 crNetFreeConnection(ns.conn);
1068 }
1069#if 0 && defined(CR_NEWWINTRACK)
1070 {
1071 Status st = XInitThreads();
1072 if (st==0)
1073 {
1074 crWarning("XInitThreads returned %i", (int)st);
1075 }
1076 }
1077#endif
1078 }
1079#endif
1080
1081 strcpy(response, "2 0 feedback 1 pack");
1082 spuchain = crStrSplit( response, " " );
1083 num_spus = crStrToInt( spuchain[0] );
1084 spu_ids = (int *) crAlloc( num_spus * sizeof( *spu_ids ) );
1085 spu_names = (char **) crAlloc( num_spus * sizeof( *spu_names ) );
1086 for (i = 0 ; i < num_spus ; i++)
1087 {
1088 spu_ids[i] = crStrToInt( spuchain[2*i+1] );
1089 spu_names[i] = crStrdup( spuchain[2*i+2] );
1090 crDebug( "SPU %d/%d: (%d) \"%s\"", i+1, num_spus, spu_ids[i], spu_names[i] );
1091 }
1092
1093 stubSetDefaultConfigurationOptions();
1094
1095 stub.spu = crSPULoadChain( num_spus, spu_ids, spu_names, stub.spu_dir, NULL );
1096
1097 crFree( spuchain );
1098 crFree( spu_ids );
1099 for (i = 0; i < num_spus; ++i)
1100 crFree(spu_names[i]);
1101 crFree( spu_names );
1102
1103 // spu chain load failed somewhere
1104 if (!stub.spu) {
1105 return false;
1106 }
1107
1108 crSPUInitDispatchTable( &glim );
1109
1110 /* This is unlikely to change -- We still want to initialize our dispatch
1111 * table with the functions of the first SPU in the chain. */
1112 stubInitSPUDispatch( stub.spu );
1113
1114 /* we need to plug one special stub function into the dispatch table */
1115 glim.GetChromiumParametervCR = stub_GetChromiumParametervCR;
1116
1117#if !defined(VBOX_NO_NATIVEGL)
1118 /* Load pointers to native OpenGL functions into stub.nativeDispatch */
1119 stubInitNativeDispatch();
1120#endif
1121
1122/*crDebug("stub init");
1123raise(SIGINT);*/
1124
1125#ifdef WINDOWS
1126# ifndef CR_NEWWINTRACK
1127 stubInstallWindowMessageHook();
1128# endif
1129#endif
1130
1131#ifdef CR_NEWWINTRACK
1132 {
1133 int rc;
1134
1135 RTR3Init();
1136
1137 if (!disable_sync)
1138 {
1139 crDebug("Starting sync thread");
1140
1141 rc = RTThreadCreate(&stub.hSyncThread, stubSyncThreadProc, NULL, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "Sync");
1142 if (RT_FAILURE(rc))
1143 {
1144 crError("Failed to start sync thread! (%x)", rc);
1145 }
1146 RTThreadUserWait(stub.hSyncThread, 60 * 1000);
1147 RTThreadUserReset(stub.hSyncThread);
1148
1149 crDebug("Going on");
1150 }
1151 }
1152#endif
1153
1154#ifdef GLX
1155 stub.xshmSI.shmid = -1;
1156 stub.bShmInitFailed = GL_FALSE;
1157 stub.pGLXPixmapsHash = crAllocHashtable();
1158
1159 stub.bXExtensionsChecked = GL_FALSE;
1160 stub.bHaveXComposite = GL_FALSE;
1161 stub.bHaveXFixes = GL_FALSE;
1162#endif
1163
1164 stub_initialized = 1;
1165 return true;
1166}
1167
1168/* Sigh -- we can't do initialization at load time, since Windows forbids
1169 * the loading of other libraries from DLLMain. */
1170
1171#ifdef LINUX
1172/* GCC crap
1173 *void (*stub_init_ptr)(void) __attribute__((section(".ctors"))) = __stubInit; */
1174#endif
1175
1176#ifdef WINDOWS
1177#define WIN32_LEAN_AND_MEAN
1178#include <windows.h>
1179
1180/* Windows crap */
1181BOOL WINAPI DllMain(HINSTANCE hDLLInst, DWORD fdwReason, LPVOID lpvReserved)
1182{
1183 (void) lpvReserved;
1184
1185 switch (fdwReason)
1186 {
1187 case DLL_PROCESS_ATTACH:
1188 {
1189 CRNetServer ns;
1190
1191 crNetInit(NULL, NULL);
1192 ns.name = "vboxhgcm://host:0";
1193 ns.buffer_size = 1024;
1194 crNetServerConnect(&ns);
1195 if (!ns.conn)
1196 {
1197 crDebug("Failed to connect to host (is guest 3d acceleration enabled?), aborting ICD load.");
1198 return FALSE;
1199 }
1200 else
1201 crNetFreeConnection(ns.conn);
1202
1203 break;
1204 }
1205
1206 case DLL_PROCESS_DETACH:
1207 {
1208 stubSPUSafeTearDown();
1209 break;
1210 }
1211
1212#if 0
1213 case DLL_THREAD_ATTACH:
1214 {
1215 if (stub_initialized)
1216 {
1217 CRASSERT(stub.spu);
1218 stub.spu->dispatch_table.VBoxPackAttachThread();
1219 }
1220 break;
1221 }
1222
1223 case DLL_THREAD_DETACH:
1224 {
1225 if (stub_initialized)
1226 {
1227 CRASSERT(stub.spu);
1228 stub.spu->dispatch_table.VBoxPackDetachThread();
1229 }
1230 break;
1231 }
1232#endif
1233
1234 default:
1235 break;
1236 }
1237
1238 return TRUE;
1239}
1240#endif
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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