VirtualBox

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

Last change on this file since 39614 was 39568, checked in by vboxsync, 13 years ago

crOpenGL: more threading fixes

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