VirtualBox

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

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

crOpenGL: context & window destroy fixes

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

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