VirtualBox

source: vbox/trunk/src/VBox/Additions/common/crOpenGL/stub.c@ 42500

最後變更 在這個檔案從42500是 42500,由 vboxsync 提交於 13 年 前

burn fix

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Id
檔案大小: 17.7 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_error.h"
9#include "cr_mem.h"
10#include "stub.h"
11#include <iprt/thread.h>
12
13static void crForcedFlush(
14#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
15 GLint con
16#endif
17 )
18{
19#if 0
20 GLint buffer;
21 stub.spu->dispatch_table.GetIntegerv(GL_DRAW_BUFFER, &buffer);
22 stub.spu->dispatch_table.DrawBuffer(GL_FRONT);
23 stub.spu->dispatch_table.Flush();
24 stub.spu->dispatch_table.DrawBuffer(buffer);
25#else
26#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
27 if (con)
28 {
29 stub.spu->dispatch_table.VBoxConFlush(con);
30 }
31 else
32#endif
33 {
34 stub.spu->dispatch_table.Flush();
35 }
36#endif
37}
38
39#ifdef GLX
40Display* stubGetWindowDisplay(WindowInfo *pWindow)
41{
42#if defined(CR_NEWWINTRACK)
43 if ((NIL_RTTHREAD!=stub.hSyncThread) && (RTThreadNativeSelf()==RTThreadGetNative(stub.hSyncThread)))
44 {
45 if (pWindow && pWindow->dpy && !pWindow->syncDpy)
46 {
47 crDebug("going to XOpenDisplay(%s)", pWindow->dpyName);
48 pWindow->syncDpy = XOpenDisplay(pWindow->dpyName);
49 if (!pWindow->syncDpy)
50 {
51 crWarning("Failed to open display %s", pWindow->dpyName);
52 }
53 return pWindow->syncDpy;
54 }
55 else
56 {
57 return pWindow ? pWindow->syncDpy:NULL;
58 }
59 }
60 else
61#endif
62 {
63 return pWindow ? pWindow->dpy:NULL;
64 }
65}
66#endif
67
68/**
69 * Returns -1 on error
70 */
71GLint APIENTRY crCreateContext( const char *dpyName, GLint visBits )
72{
73 ContextInfo *context;
74 stubInit();
75 /* XXX in Chromium 1.5 and earlier, the last parameter was UNDECIDED.
76 * That didn't seem right so it was changed to CHROMIUM. (Brian)
77 */
78 context = stubNewContext(dpyName, visBits, CHROMIUM, 0
79#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
80 , NULL
81#endif
82 );
83 return context ? (int) context->id : -1;
84}
85
86void APIENTRY crDestroyContext( GLint context )
87{
88 stubDestroyContext(context);
89}
90
91void APIENTRY crMakeCurrent( GLint window, GLint context )
92{
93 WindowInfo *winInfo = (WindowInfo *)
94 crHashtableSearch(stub.windowTable, (unsigned int) window);
95 ContextInfo *contextInfo = (ContextInfo *)
96 crHashtableSearch(stub.contextTable, context);
97 if (contextInfo && contextInfo->type == NATIVE) {
98 crWarning("Can't call crMakeCurrent with native GL context");
99 return;
100 }
101
102 stubMakeCurrent(winInfo, contextInfo);
103}
104
105GLint APIENTRY crGetCurrentContext( void )
106{
107 ContextInfo *context;
108 stubInit();
109 context = stubGetCurrentContext();
110 if (context)
111 return (GLint) context->id;
112 else
113 return 0;
114}
115
116GLint APIENTRY crGetCurrentWindow( void )
117{
118 ContextInfo *context;
119 stubInit();
120 context = stubGetCurrentContext();
121 if (context && context->currentDrawable)
122 return context->currentDrawable->spuWindow;
123 else
124 return -1;
125}
126
127void APIENTRY crSwapBuffers( GLint window, GLint flags )
128{
129 WindowInfo *winInfo = (WindowInfo *)
130 crHashtableSearch(stub.windowTable, (unsigned int) window);
131 if (winInfo)
132 stubSwapBuffers(winInfo, flags);
133}
134
135/**
136 * Returns -1 on error
137 */
138GLint APIENTRY crWindowCreate( const char *dpyName, GLint visBits )
139{
140 stubInit();
141 return stubNewWindow( dpyName, visBits );
142}
143
144static void stubWindowCleanupForContextsCB(unsigned long key, void *data1, void *data2)
145{
146 ContextInfo *context = (ContextInfo *) data1;
147
148 CRASSERT(context);
149
150 if (context->currentDrawable == data2)
151 context->currentDrawable = NULL;
152}
153
154void APIENTRY crWindowDestroy( GLint window )
155{
156 WindowInfo *winInfo = (WindowInfo *)
157 crHashtableSearch(stub.windowTable, (unsigned int) window);
158 if (winInfo && winInfo->type == CHROMIUM && stub.spu)
159 {
160 crHashtableLock(stub.windowTable);
161
162 stub.spu->dispatch_table.VBoxWindowDestroy(
163#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
164 winInfo->spuConnection,
165#else
166 0,
167#endif
168 winInfo->spuWindow );
169
170#ifdef WINDOWS
171 if (winInfo->hVisibleRegion != INVALID_HANDLE_VALUE)
172 {
173 DeleteObject(winInfo->hVisibleRegion);
174 }
175#elif defined(GLX)
176 if (winInfo->pVisibleRegions)
177 {
178 XFree(winInfo->pVisibleRegions);
179 }
180# ifdef CR_NEWWINTRACK
181 if (winInfo->syncDpy)
182 {
183 XCloseDisplay(winInfo->syncDpy);
184 }
185# endif
186#endif
187 crForcedFlush(
188#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
189 winInfo->spuConnection
190#endif
191 );
192
193#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
194 winInfo->spuConnection = 0;
195#endif
196 crHashtableWalk(stub.contextTable, stubWindowCleanupForContextsCB, winInfo);
197
198 crHashtableDelete(stub.windowTable, window, crFree);
199
200 crHashtableUnlock(stub.windowTable);
201 }
202}
203
204void APIENTRY crWindowSize( GLint window, GLint w, GLint h )
205{
206 const WindowInfo *winInfo = (const WindowInfo *)
207 crHashtableSearch(stub.windowTable, (unsigned int) window);
208 if (winInfo && winInfo->type == CHROMIUM)
209 {
210 crDebug("Dispatched crWindowSize (%i)", window);
211 stub.spu->dispatch_table.WindowSize( window, w, h );
212 }
213}
214
215void APIENTRY crWindowPosition( GLint window, GLint x, GLint y )
216{
217 const WindowInfo *winInfo = (const WindowInfo *)
218 crHashtableSearch(stub.windowTable, (unsigned int) window);
219 if (winInfo && winInfo->type == CHROMIUM)
220 {
221 crDebug("Dispatched crWindowPosition (%i)", window);
222 stub.spu->dispatch_table.WindowPosition( window, x, y );
223 }
224}
225
226void APIENTRY crWindowVisibleRegion( GLint window, GLint cRects, void *pRects )
227{
228 const WindowInfo *winInfo = (const WindowInfo *)
229 crHashtableSearch(stub.windowTable, (unsigned int) window);
230 if (winInfo && winInfo->type == CHROMIUM)
231 {
232 crDebug("Dispatched crWindowVisibleRegion (%i, cRects=%i)", window, cRects);
233 stub.spu->dispatch_table.WindowVisibleRegion( window, cRects, pRects );
234 }
235}
236
237void APIENTRY crWindowShow( GLint window, GLint flag )
238{
239 WindowInfo *winInfo = (WindowInfo *)
240 crHashtableSearch(stub.windowTable, (unsigned int) window);
241 if (winInfo && winInfo->type == CHROMIUM)
242 stub.spu->dispatch_table.WindowShow( window, flag );
243 winInfo->mapped = flag ? GL_TRUE : GL_FALSE;
244}
245
246void APIENTRY stub_GetChromiumParametervCR( GLenum target, GLuint index, GLenum type, GLsizei count, GLvoid *values )
247{
248 char **ret;
249 switch( target )
250 {
251 case GL_HEAD_SPU_NAME_CR:
252 ret = (char **) values;
253 *ret = stub.spu->name;
254 return;
255 default:
256 stub.spu->dispatch_table.GetChromiumParametervCR( target, index, type, count, values );
257 break;
258 }
259}
260
261/*
262 * Updates geometry info for given spu window.
263 * Returns GL_TRUE if it changed since last call, GL_FALSE otherwise.
264 * bForceUpdate - forces dispatching of geometry info even if it's unchanged
265 */
266GLboolean stubUpdateWindowGeometry(WindowInfo *pWindow, GLboolean bForceUpdate)
267{
268 int winX, winY;
269 unsigned int winW, winH;
270 GLboolean res = GL_FALSE;
271
272 CRASSERT(pWindow);
273
274 stubGetWindowGeometry(pWindow, &winX, &winY, &winW, &winH);
275
276 /* @todo remove "if (winW && winH)"?*/
277 if (winW && winH) {
278 if (stub.trackWindowSize) {
279 if (bForceUpdate || winW != pWindow->width || winH != pWindow->height) {
280 crDebug("Dispatched WindowSize (%i)", pWindow->spuWindow);
281#ifdef VBOX_WITH_WDDM
282 if (!stub.bRunningUnderWDDM || pWindow->mapped)
283#endif
284 {
285 stub.spuDispatch.WindowSize(pWindow->spuWindow, winW, winH);
286 }
287 pWindow->width = winW;
288 pWindow->height = winH;
289 res = GL_TRUE;
290 }
291 }
292 if (stub.trackWindowPos) {
293 if (bForceUpdate || winX != pWindow->x || winY != pWindow->y) {
294 crDebug("Dispatched WindowPosition (%i)", pWindow->spuWindow);
295#ifdef VBOX_WITH_WDDM
296 if (!stub.bRunningUnderWDDM || pWindow->mapped)
297#endif
298 {
299 stub.spuDispatch.WindowPosition(pWindow->spuWindow, winX, winY);
300 }
301 pWindow->x = winX;
302 pWindow->y = winY;
303 res = GL_TRUE;
304 }
305 }
306 }
307
308 return res;
309}
310
311#ifdef WINDOWS
312/*
313 * Updates visible regions for given spu window.
314 * Returns GL_TRUE if regions changed since last call, GL_FALSE otherwise.
315 */
316GLboolean stubUpdateWindowVisibileRegions(WindowInfo *pWindow)
317{
318 HRGN hVisRgn;
319 HWND hwnd;
320 DWORD dwCount;
321 LPRGNDATA lpRgnData;
322 POINT pt;
323 int iret;
324
325 if (!pWindow) return GL_FALSE;
326 hwnd = pWindow->hWnd;
327 if (!hwnd) return GL_FALSE;
328
329 if (hwnd!=WindowFromDC(pWindow->drawable))
330 {
331 crWarning("Window(%i) DC is no longer valid", pWindow->spuWindow);
332 return GL_FALSE;
333 }
334
335 hVisRgn = CreateRectRgn(0,0,0,0);
336 iret = GetRandomRgn(pWindow->drawable, hVisRgn, SYSRGN);
337
338 if (iret==1)
339 {
340 /*@todo check win95/win98 here, as rects should be already in client space there*/
341 /* Convert screen related rectangles to client related rectangles */
342 pt.x = 0;
343 pt.y = 0;
344 ScreenToClient(hwnd, &pt);
345 OffsetRgn(hVisRgn, pt.x, pt.y);
346
347 /*
348 dwCount = GetRegionData(hVisRgn, 0, NULL);
349 lpRgnData = crAlloc(dwCount);
350 crDebug("GetRandomRgn returned 1, dwCount=%d", dwCount);
351 GetRegionData(hVisRgn, dwCount, lpRgnData);
352 crDebug("Region consists of %d rects", lpRgnData->rdh.nCount);
353
354 pRects = (RECT*) lpRgnData->Buffer;
355 for (i=0; i<lpRgnData->rdh.nCount; ++i)
356 {
357 crDebug("Rgn[%d] = (%d, %d, %d, %d)", i, pRects[i].left, pRects[i].top, pRects[i].right, pRects[i].bottom);
358 }
359 crFree(lpRgnData);
360 */
361
362 if (pWindow->hVisibleRegion==INVALID_HANDLE_VALUE
363 || !EqualRgn(pWindow->hVisibleRegion, hVisRgn))
364 {
365 DeleteObject(pWindow->hVisibleRegion);
366 pWindow->hVisibleRegion = hVisRgn;
367
368 dwCount = GetRegionData(hVisRgn, 0, NULL);
369 lpRgnData = crAlloc(dwCount);
370
371 if (lpRgnData)
372 {
373 GetRegionData(hVisRgn, dwCount, lpRgnData);
374 crDebug("Dispatched WindowVisibleRegion (%i, cRects=%i)", pWindow->spuWindow, lpRgnData->rdh.nCount);
375 stub.spuDispatch.WindowVisibleRegion(pWindow->spuWindow, lpRgnData->rdh.nCount, (GLint*) lpRgnData->Buffer);
376 crFree(lpRgnData);
377 return GL_TRUE;
378 }
379 else crWarning("GetRegionData failed, VisibleRegions update failed");
380 }
381 else
382 {
383 DeleteObject(hVisRgn);
384 }
385 }
386 else
387 {
388 crWarning("GetRandomRgn returned (%d) instead of (1), VisibleRegions update failed", iret);
389 DeleteObject(hVisRgn);
390 }
391
392 return GL_FALSE;
393}
394
395# ifndef CR_NEWWINTRACK
396static void stubCBCheckWindowsInfo(unsigned long key, void *data1, void *data2)
397{
398 WindowInfo *winInfo = (WindowInfo *) data1;
399 CWPRETSTRUCT *pMsgInfo = (PCWPRETSTRUCT) data2;
400
401 (void) key;
402
403 if (winInfo && pMsgInfo && winInfo->type == CHROMIUM)
404 {
405 switch (pMsgInfo->message)
406 {
407 case WM_MOVING:
408 case WM_SIZING:
409 case WM_MOVE:
410 case WM_CREATE:
411 case WM_SIZE:
412 {
413 GLboolean changed = stub.trackWindowVisibleRgn && stubUpdateWindowVisibileRegions(winInfo);
414
415 if (stubUpdateWindowGeometry(winInfo, GL_FALSE) || changed)
416 {
417 crForcedFlush();
418 }
419 break;
420 }
421
422 case WM_SHOWWINDOW:
423 case WM_ACTIVATEAPP:
424 case WM_PAINT:
425 case WM_NCPAINT:
426 case WM_NCACTIVATE:
427 case WM_ERASEBKGND:
428 {
429 if (stub.trackWindowVisibleRgn && stubUpdateWindowVisibileRegions(winInfo))
430 {
431 crForcedFlush();
432 }
433 break;
434 }
435
436 default:
437 {
438 if (stub.trackWindowVisibleRgn && stubUpdateWindowVisibileRegions(winInfo))
439 {
440 crDebug("Visibility info updated due to unknown hooked message (%d)", pMsgInfo->message);
441 crForcedFlush();
442 }
443 break;
444 }
445 }
446 }
447}
448
449LRESULT CALLBACK stubCBWindowMessageHookProc(int nCode, WPARAM wParam, LPARAM lParam)
450{
451 CWPRETSTRUCT *pMsgInfo = (PCWPRETSTRUCT) lParam;
452
453 if (nCode>=0 && pMsgInfo)
454 {
455 switch (pMsgInfo->message)
456 {
457 case WM_MOVING:
458 case WM_SIZING:
459 case WM_MOVE:
460 case WM_ACTIVATEAPP:
461 case WM_NCPAINT:
462 case WM_NCACTIVATE:
463 case WM_ERASEBKGND:
464 case WM_CREATE:
465 case WM_SIZE:
466 case WM_SHOWWINDOW:
467 {
468 crHashtableWalk(stub.windowTable, stubCBCheckWindowsInfo, (void *) lParam);
469 break;
470 }
471
472 /* @todo remove it*/
473 default:
474 {
475 /*crDebug("hook: unknown message (%d)", pMsgInfo->message);*/
476 crHashtableWalk(stub.windowTable, stubCBCheckWindowsInfo, (void *) lParam);
477 break;
478 }
479 }
480 }
481
482 return CallNextHookEx(stub.hMessageHook, nCode, wParam, lParam);
483}
484
485void stubInstallWindowMessageHook()
486{
487 stub.hMessageHook = SetWindowsHookEx(WH_CALLWNDPROCRET, stubCBWindowMessageHookProc, 0, crThreadID());
488
489 if (!stub.hMessageHook)
490 crWarning("Window message hook install failed! (not fatal)");
491}
492
493void stubUninstallWindowMessageHook()
494{
495 if (stub.hMessageHook)
496 UnhookWindowsHookEx(stub.hMessageHook);
497}
498# endif /*# ifndef CR_NEWWINTRACK*/
499
500#elif defined(GLX) //#ifdef WINDOWS
501void stubCheckXExtensions(WindowInfo *pWindow)
502{
503 int evb, erb, vmi=0, vma=0;
504 Display *dpy = stubGetWindowDisplay(pWindow);
505
506 stub.bXExtensionsChecked = GL_TRUE;
507 stub.trackWindowVisibleRgn = 0;
508
509 XLOCK(dpy);
510 if (XCompositeQueryExtension(dpy, &evb, &erb)
511 && XCompositeQueryVersion(dpy, &vma, &vmi)
512 && (vma>0 || vmi>=4))
513 {
514 stub.bHaveXComposite = GL_TRUE;
515 crDebug("XComposite %i.%i", vma, vmi);
516 vma=0;
517 vmi=0;
518 if (XFixesQueryExtension(dpy, &evb, &erb)
519 && XFixesQueryVersion(dpy, &vma, &vmi)
520 && vma>=2)
521 {
522 crDebug("XFixes %i.%i", vma, vmi);
523 stub.bHaveXFixes = GL_TRUE;
524 stub.trackWindowVisibleRgn = 1;
525 XUNLOCK(dpy);
526 return;
527 }
528 else
529 {
530 crWarning("XFixes not found or old version (%i.%i), no VisibilityTracking", vma, vmi);
531 }
532 }
533 else
534 {
535 crWarning("XComposite not found or old version (%i.%i), no VisibilityTracking", vma, vmi);
536 }
537 XUNLOCK(dpy);
538 return;
539}
540
541/*
542 * Updates visible regions for given spu window.
543 * Returns GL_TRUE if regions changed since last call, GL_FALSE otherwise.
544 */
545GLboolean stubUpdateWindowVisibileRegions(WindowInfo *pWindow)
546{
547 XserverRegion xreg;
548 int cRects, i;
549 XRectangle *pXRects;
550 GLint* pGLRects;
551 Display *dpy;
552 bool bNoUpdate = false;
553
554 if (!stub.bXExtensionsChecked)
555 {
556 stubCheckXExtensions(pWindow);
557 if (!stub.trackWindowVisibleRgn)
558 {
559 return GL_FALSE;
560 }
561 }
562
563 dpy = stubGetWindowDisplay(pWindow);
564
565 /*@todo see comment regarding size/position updates and XSync, same applies to those functions but
566 * it seems there's no way to get even based updates for this. Or I've failed to find the appropriate extension.
567 */
568 XLOCK(dpy);
569 xreg = XCompositeCreateRegionFromBorderClip(dpy, pWindow->drawable);
570 pXRects = XFixesFetchRegion(dpy, xreg, &cRects);
571 XFixesDestroyRegion(dpy, xreg);
572 XUNLOCK(dpy);
573
574 /* Check for compiz main window */
575 if (!pWindow->pVisibleRegions && !cRects)
576 {
577#ifdef VBOX_TEST_MEGOO
578 XWindowAttributes attr;
579 XLOCK(dpy);
580 XSync(dpy, false);
581 XGetWindowAttributes(dpy, pWindow->drawable, &attr);
582 XUNLOCK(dpy);
583
584 bNoUpdate = attr.override_redirect;
585#else
586 bNoUpdate = true;
587#endif
588 }
589
590 if (!bNoUpdate
591 && (!pWindow->pVisibleRegions
592 || pWindow->cVisibleRegions!=cRects
593 || (pWindow->pVisibleRegions && crMemcmp(pWindow->pVisibleRegions, pXRects, cRects * sizeof(XRectangle)))))
594 {
595 if (pWindow->pVisibleRegions)
596 {
597 XFree(pWindow->pVisibleRegions);
598 }
599
600 pWindow->pVisibleRegions = pXRects;
601 pWindow->cVisibleRegions = cRects;
602
603 pGLRects = crAlloc(4*cRects*sizeof(GLint));
604 if (!pGLRects)
605 {
606 crWarning("stubUpdateWindowVisibileRegions: failed to allocate %lu bytes",
607 (unsigned long)(4*cRects*sizeof(GLint)));
608 return GL_FALSE;
609 }
610
611 //crDebug("Got %i rects.", cRects);
612 for (i=0; i<cRects; ++i)
613 {
614 pGLRects[4*i+0] = pXRects[i].x;
615 pGLRects[4*i+1] = pXRects[i].y;
616 pGLRects[4*i+2] = pXRects[i].x+pXRects[i].width;
617 pGLRects[4*i+3] = pXRects[i].y+pXRects[i].height;
618 //crDebug("Rect[%i]=(%i,%i,%i,%i)", i, pGLRects[4*i+0], pGLRects[4*i+1], pGLRects[4*i+2], pGLRects[4*i+3]);
619 }
620
621 crDebug("Dispatched WindowVisibleRegion (%i, cRects=%i)", pWindow->spuWindow, cRects);
622 stub.spuDispatch.WindowVisibleRegion(pWindow->spuWindow, cRects, pGLRects);
623 crFree(pGLRects);
624 return GL_TRUE;
625 }
626 else
627 {
628 XFree(pXRects);
629 }
630
631 return GL_FALSE;
632}
633#endif //#ifdef WINDOWS
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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