VirtualBox

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

Last change on this file since 62521 was 59505, checked in by vboxsync, 8 years ago

bugref:8087: Additions/x11: support non-root X server: fix r104816: we were no longer passing through information about visible window regions when no regions were visible at all. This broke switching to a virtual terminal while Compiz was in use, as it prevented the Compiz window from being hidden.

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

© 2023 Oracle
ContactPrivacy policyTerms of Use