VirtualBox

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

Last change on this file since 35263 was 34295, checked in by vboxsync, 13 years ago

crOpenGL/wddm: more strict window info tracking

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 16.4 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
13static void crForcedFlush()
14{
15#if 0
16 GLint buffer;
17 stub.spu->dispatch_table.GetIntegerv(GL_DRAW_BUFFER, &buffer);
18 stub.spu->dispatch_table.DrawBuffer(GL_FRONT);
19 stub.spu->dispatch_table.Flush();
20 stub.spu->dispatch_table.DrawBuffer(buffer);
21#else
22 stub.spu->dispatch_table.Flush();
23#endif
24}
25
26#ifdef GLX
27Display* stubGetWindowDisplay(WindowInfo *pWindow)
28{
29#if defined(CR_NEWWINTRACK)
30 if ((NIL_RTTHREAD!=stub.hSyncThread) && (RTThreadNativeSelf()==RTThreadGetNative(stub.hSyncThread)))
31 {
32 if (pWindow && pWindow->dpy && !pWindow->syncDpy)
33 {
34 crDebug("going to XOpenDisplay(%s)", pWindow->dpyName);
35 pWindow->syncDpy = XOpenDisplay(pWindow->dpyName);
36 if (!pWindow->syncDpy)
37 {
38 crWarning("Failed to open display %s", pWindow->dpyName);
39 }
40 return pWindow->syncDpy;
41 }
42 else
43 {
44 return pWindow ? pWindow->syncDpy:NULL;
45 }
46 }
47 else
48#endif
49 {
50 return pWindow ? pWindow->dpy:NULL;
51 }
52}
53#endif
54
55/**
56 * Returns -1 on error
57 */
58GLint APIENTRY crCreateContext( const char *dpyName, GLint visBits )
59{
60 ContextInfo *context;
61 stubInit();
62 /* XXX in Chromium 1.5 and earlier, the last parameter was UNDECIDED.
63 * That didn't seem right so it was changed to CHROMIUM. (Brian)
64 */
65 context = stubNewContext(dpyName, visBits, CHROMIUM, 0);
66 return context ? (int) context->id : -1;
67}
68
69void APIENTRY crDestroyContext( GLint context )
70{
71 stubDestroyContext(context);
72}
73
74void APIENTRY crMakeCurrent( GLint window, GLint context )
75{
76 WindowInfo *winInfo = (WindowInfo *)
77 crHashtableSearch(stub.windowTable, (unsigned int) window);
78 ContextInfo *contextInfo = (ContextInfo *)
79 crHashtableSearch(stub.contextTable, context);
80 if (contextInfo && contextInfo->type == NATIVE) {
81 crWarning("Can't call crMakeCurrent with native GL context");
82 return;
83 }
84
85 stubMakeCurrent(winInfo, contextInfo);
86}
87
88GLint APIENTRY crGetCurrentContext( void )
89{
90 stubInit();
91 if (stub.currentContext)
92 return (GLint) stub.currentContext->id;
93 else
94 return 0;
95}
96
97GLint APIENTRY crGetCurrentWindow( void )
98{
99 stubInit();
100 if (stub.currentContext && stub.currentContext->currentDrawable)
101 return stub.currentContext->currentDrawable->spuWindow;
102 else
103 return -1;
104}
105
106void APIENTRY crSwapBuffers( GLint window, GLint flags )
107{
108 WindowInfo *winInfo = (WindowInfo *)
109 crHashtableSearch(stub.windowTable, (unsigned int) window);
110 if (winInfo)
111 stubSwapBuffers(winInfo, flags);
112}
113
114/**
115 * Returns -1 on error
116 */
117GLint APIENTRY crWindowCreate( const char *dpyName, GLint visBits )
118{
119 stubInit();
120 return stubNewWindow( dpyName, visBits );
121}
122
123void APIENTRY crWindowDestroy( GLint window )
124{
125 WindowInfo *winInfo = (WindowInfo *)
126 crHashtableSearch(stub.windowTable, (unsigned int) window);
127 if (winInfo && winInfo->type == CHROMIUM && stub.spu)
128 {
129 stub.spu->dispatch_table.WindowDestroy( winInfo->spuWindow );
130#ifdef CR_NEWWINTRACK
131 crLockMutex(&stub.mutex);
132#endif
133#ifdef WINDOWS
134 if (winInfo->hVisibleRegion != INVALID_HANDLE_VALUE)
135 {
136 DeleteObject(winInfo->hVisibleRegion);
137 }
138#elif defined(GLX)
139 if (winInfo->pVisibleRegions)
140 {
141 XFree(winInfo->pVisibleRegions);
142 }
143# ifdef CR_NEWWINTRACK
144 if (winInfo->syncDpy)
145 {
146 XCloseDisplay(winInfo->syncDpy);
147 }
148# endif
149#endif
150#ifdef CR_NEWWINTRACK
151 crUnlockMutex(&stub.mutex);
152#endif
153 crForcedFlush();
154 crHashtableDelete(stub.windowTable, window, crFree);
155 }
156}
157
158void APIENTRY crWindowSize( GLint window, GLint w, GLint h )
159{
160 const WindowInfo *winInfo = (const WindowInfo *)
161 crHashtableSearch(stub.windowTable, (unsigned int) window);
162 if (winInfo && winInfo->type == CHROMIUM)
163 {
164 crDebug("Dispatched crWindowSize (%i)", window);
165 stub.spu->dispatch_table.WindowSize( window, w, h );
166 }
167}
168
169void APIENTRY crWindowPosition( GLint window, GLint x, GLint y )
170{
171 const WindowInfo *winInfo = (const WindowInfo *)
172 crHashtableSearch(stub.windowTable, (unsigned int) window);
173 if (winInfo && winInfo->type == CHROMIUM)
174 {
175 crDebug("Dispatched crWindowPosition (%i)", window);
176 stub.spu->dispatch_table.WindowPosition( window, x, y );
177 }
178}
179
180void APIENTRY crWindowVisibleRegion( GLint window, GLint cRects, void *pRects )
181{
182 const WindowInfo *winInfo = (const WindowInfo *)
183 crHashtableSearch(stub.windowTable, (unsigned int) window);
184 if (winInfo && winInfo->type == CHROMIUM)
185 {
186 crDebug("Dispatched crWindowVisibleRegion (%i, cRects=%i)", window, cRects);
187 stub.spu->dispatch_table.WindowVisibleRegion( window, cRects, pRects );
188 }
189}
190
191void APIENTRY crWindowShow( GLint window, GLint flag )
192{
193 WindowInfo *winInfo = (WindowInfo *)
194 crHashtableSearch(stub.windowTable, (unsigned int) window);
195 if (winInfo && winInfo->type == CHROMIUM)
196 stub.spu->dispatch_table.WindowShow( window, flag );
197 winInfo->mapped = flag ? GL_TRUE : GL_FALSE;
198}
199
200void APIENTRY stub_GetChromiumParametervCR( GLenum target, GLuint index, GLenum type, GLsizei count, GLvoid *values )
201{
202 char **ret;
203 switch( target )
204 {
205 case GL_HEAD_SPU_NAME_CR:
206 ret = (char **) values;
207 *ret = stub.spu->name;
208 return;
209 default:
210 stub.spu->dispatch_table.GetChromiumParametervCR( target, index, type, count, values );
211 break;
212 }
213}
214
215/*
216 * Updates geometry info for given spu window.
217 * Returns GL_TRUE if it changed since last call, GL_FALSE otherwise.
218 * bForceUpdate - forces dispatching of geometry info even if it's unchanged
219 */
220GLboolean stubUpdateWindowGeometry(WindowInfo *pWindow, GLboolean bForceUpdate)
221{
222 int winX, winY;
223 unsigned int winW, winH;
224 GLboolean res = GL_FALSE;
225
226 CRASSERT(pWindow);
227
228 stubGetWindowGeometry(pWindow, &winX, &winY, &winW, &winH);
229
230 /* @todo remove "if (winW && winH)"?*/
231 if (winW && winH) {
232 if (stub.trackWindowSize) {
233 if (bForceUpdate || winW != pWindow->width || winH != pWindow->height) {
234 crDebug("Dispatched WindowSize (%i)", pWindow->spuWindow);
235 stub.spuDispatch.WindowSize(pWindow->spuWindow, winW, winH);
236 pWindow->width = winW;
237 pWindow->height = winH;
238 res = GL_TRUE;
239 }
240 }
241 if (stub.trackWindowPos) {
242 if (bForceUpdate || winX != pWindow->x || winY != pWindow->y) {
243 crDebug("Dispatched WindowPosition (%i)", pWindow->spuWindow);
244 stub.spuDispatch.WindowPosition(pWindow->spuWindow, winX, winY);
245 pWindow->x = winX;
246 pWindow->y = winY;
247 res = GL_TRUE;
248 }
249 }
250 }
251
252 return res;
253}
254
255#ifdef WINDOWS
256/*
257 * Updates visible regions for given spu window.
258 * Returns GL_TRUE if regions changed since last call, GL_FALSE otherwise.
259 */
260GLboolean stubUpdateWindowVisibileRegions(WindowInfo *pWindow)
261{
262 HRGN hVisRgn;
263 HWND hwnd;
264 DWORD dwCount;
265 LPRGNDATA lpRgnData;
266 POINT pt;
267 int iret;
268
269 if (!pWindow) return GL_FALSE;
270 hwnd = pWindow->hWnd;
271 if (!hwnd) return GL_FALSE;
272
273 if (hwnd!=WindowFromDC(pWindow->drawable))
274 {
275 crWarning("Window(%i) DC is no longer valid", pWindow->spuWindow);
276 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
445void stubCheckXExtensions(WindowInfo *pWindow)
446{
447 int evb, erb, vmi=0, vma=0;
448 Display *dpy = stubGetWindowDisplay(pWindow);
449
450 stub.bXExtensionsChecked = GL_TRUE;
451 stub.trackWindowVisibleRgn = 0;
452
453 XLOCK(dpy);
454 if (XCompositeQueryExtension(dpy, &evb, &erb)
455 && XCompositeQueryVersion(dpy, &vma, &vmi)
456 && (vma>0 || vmi>=4))
457 {
458 stub.bHaveXComposite = GL_TRUE;
459 crDebug("XComposite %i.%i", vma, vmi);
460 vma=0;
461 vmi=0;
462 if (XFixesQueryExtension(dpy, &evb, &erb)
463 && XFixesQueryVersion(dpy, &vma, &vmi)
464 && vma>=2)
465 {
466 crDebug("XFixes %i.%i", vma, vmi);
467 stub.bHaveXFixes = GL_TRUE;
468 stub.trackWindowVisibleRgn = 1;
469 XUNLOCK(dpy);
470 return;
471 }
472 else
473 {
474 crWarning("XFixes not found or old version (%i.%i), no VisibilityTracking", vma, vmi);
475 }
476 }
477 else
478 {
479 crWarning("XComposite not found or old version (%i.%i), no VisibilityTracking", vma, vmi);
480 }
481 XUNLOCK(dpy);
482 return;
483}
484
485/*
486 * Updates visible regions for given spu window.
487 * Returns GL_TRUE if regions changed since last call, GL_FALSE otherwise.
488 */
489GLboolean stubUpdateWindowVisibileRegions(WindowInfo *pWindow)
490{
491 XserverRegion xreg;
492 int cRects, i;
493 XRectangle *pXRects;
494 GLint* pGLRects;
495 Display *dpy;
496 bool bNoUpdate = false;
497
498 if (!stub.bXExtensionsChecked)
499 {
500 stubCheckXExtensions(pWindow);
501 if (!stub.trackWindowVisibleRgn)
502 {
503 return GL_FALSE;
504 }
505 }
506
507 dpy = stubGetWindowDisplay(pWindow);
508
509 /*@todo see comment regarding size/position updates and XSync, same applies to those functions but
510 * it seems there's no way to get even based updates for this. Or I've failed to find the appropriate extension.
511 */
512 XLOCK(dpy);
513 xreg = XCompositeCreateRegionFromBorderClip(dpy, pWindow->drawable);
514 pXRects = XFixesFetchRegion(dpy, xreg, &cRects);
515 XFixesDestroyRegion(dpy, xreg);
516 XUNLOCK(dpy);
517
518 /* Check for compiz main window */
519 if (!pWindow->pVisibleRegions && !cRects)
520 {
521#ifdef VBOX_TEST_MEGOO
522 XWindowAttributes attr;
523 XLOCK(dpy);
524 XSync(dpy, false);
525 XGetWindowAttributes(dpy, pWindow->drawable, &attr);
526 XUNLOCK(dpy);
527
528 bNoUpdate = attr.override_redirect;
529#else
530 bNoUpdate = true;
531#endif
532 }
533
534 if (!bNoUpdate
535 && (!pWindow->pVisibleRegions
536 || pWindow->cVisibleRegions!=cRects
537 || (pWindow->pVisibleRegions && crMemcmp(pWindow->pVisibleRegions, pXRects, cRects * sizeof(XRectangle)))))
538 {
539 if (pWindow->pVisibleRegions)
540 {
541 XFree(pWindow->pVisibleRegions);
542 }
543
544 pWindow->pVisibleRegions = pXRects;
545 pWindow->cVisibleRegions = cRects;
546
547 pGLRects = crAlloc(4*cRects*sizeof(GLint));
548 if (!pGLRects)
549 {
550 crWarning("stubUpdateWindowVisibileRegions: failed to allocate %lu bytes",
551 (unsigned long)(4*cRects*sizeof(GLint)));
552 return GL_FALSE;
553 }
554
555 //crDebug("Got %i rects.", cRects);
556 for (i=0; i<cRects; ++i)
557 {
558 pGLRects[4*i+0] = pXRects[i].x;
559 pGLRects[4*i+1] = pXRects[i].y;
560 pGLRects[4*i+2] = pXRects[i].x+pXRects[i].width;
561 pGLRects[4*i+3] = pXRects[i].y+pXRects[i].height;
562 //crDebug("Rect[%i]=(%i,%i,%i,%i)", i, pGLRects[4*i+0], pGLRects[4*i+1], pGLRects[4*i+2], pGLRects[4*i+3]);
563 }
564
565 crDebug("Dispatched WindowVisibleRegion (%i, cRects=%i)", pWindow->spuWindow, cRects);
566 stub.spuDispatch.WindowVisibleRegion(pWindow->spuWindow, cRects, pGLRects);
567 crFree(pGLRects);
568 return GL_TRUE;
569 }
570 else
571 {
572 XFree(pXRects);
573 }
574
575 return GL_FALSE;
576}
577#endif //#ifdef WINDOWS
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use