VirtualBox

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

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

crOpenGL: tracking fixes

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