VirtualBox

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

Last change on this file since 42227 was 41963, checked in by vboxsync, 12 years ago

crOpenGL/wddm: fix flikering on window creation

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 17.0 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
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#ifdef VBOX_WITH_WDDM
252 if (!stub.bRunningUnderWDDM || pWindow->mapped)
253#endif
254 {
255 stub.spuDispatch.WindowSize(pWindow->spuWindow, winW, winH);
256 }
257 pWindow->width = winW;
258 pWindow->height = winH;
259 res = GL_TRUE;
260 }
261 }
262 if (stub.trackWindowPos) {
263 if (bForceUpdate || winX != pWindow->x || winY != pWindow->y) {
264 crDebug("Dispatched WindowPosition (%i)", pWindow->spuWindow);
265#ifdef VBOX_WITH_WDDM
266 if (!stub.bRunningUnderWDDM || pWindow->mapped)
267#endif
268 {
269 stub.spuDispatch.WindowPosition(pWindow->spuWindow, winX, winY);
270 }
271 pWindow->x = winX;
272 pWindow->y = winY;
273 res = GL_TRUE;
274 }
275 }
276 }
277
278 return res;
279}
280
281#ifdef WINDOWS
282/*
283 * Updates visible regions for given spu window.
284 * Returns GL_TRUE if regions changed since last call, GL_FALSE otherwise.
285 */
286GLboolean stubUpdateWindowVisibileRegions(WindowInfo *pWindow)
287{
288 HRGN hVisRgn;
289 HWND hwnd;
290 DWORD dwCount;
291 LPRGNDATA lpRgnData;
292 POINT pt;
293 int iret;
294
295 if (!pWindow) return GL_FALSE;
296 hwnd = pWindow->hWnd;
297 if (!hwnd) return GL_FALSE;
298
299 if (hwnd!=WindowFromDC(pWindow->drawable))
300 {
301 crWarning("Window(%i) DC is no longer valid", pWindow->spuWindow);
302 return GL_FALSE;
303 }
304
305 hVisRgn = CreateRectRgn(0,0,0,0);
306 iret = GetRandomRgn(pWindow->drawable, hVisRgn, SYSRGN);
307
308 if (iret==1)
309 {
310 /*@todo check win95/win98 here, as rects should be already in client space there*/
311 /* Convert screen related rectangles to client related rectangles */
312 pt.x = 0;
313 pt.y = 0;
314 ScreenToClient(hwnd, &pt);
315 OffsetRgn(hVisRgn, pt.x, pt.y);
316
317 /*
318 dwCount = GetRegionData(hVisRgn, 0, NULL);
319 lpRgnData = crAlloc(dwCount);
320 crDebug("GetRandomRgn returned 1, dwCount=%d", dwCount);
321 GetRegionData(hVisRgn, dwCount, lpRgnData);
322 crDebug("Region consists of %d rects", lpRgnData->rdh.nCount);
323
324 pRects = (RECT*) lpRgnData->Buffer;
325 for (i=0; i<lpRgnData->rdh.nCount; ++i)
326 {
327 crDebug("Rgn[%d] = (%d, %d, %d, %d)", i, pRects[i].left, pRects[i].top, pRects[i].right, pRects[i].bottom);
328 }
329 crFree(lpRgnData);
330 */
331
332 if (pWindow->hVisibleRegion==INVALID_HANDLE_VALUE
333 || !EqualRgn(pWindow->hVisibleRegion, hVisRgn))
334 {
335 DeleteObject(pWindow->hVisibleRegion);
336 pWindow->hVisibleRegion = hVisRgn;
337
338 dwCount = GetRegionData(hVisRgn, 0, NULL);
339 lpRgnData = crAlloc(dwCount);
340
341 if (lpRgnData)
342 {
343 GetRegionData(hVisRgn, dwCount, lpRgnData);
344 crDebug("Dispatched WindowVisibleRegion (%i, cRects=%i)", pWindow->spuWindow, lpRgnData->rdh.nCount);
345 stub.spuDispatch.WindowVisibleRegion(pWindow->spuWindow, lpRgnData->rdh.nCount, (GLint*) lpRgnData->Buffer);
346 crFree(lpRgnData);
347 return GL_TRUE;
348 }
349 else crWarning("GetRegionData failed, VisibleRegions update failed");
350 }
351 else
352 {
353 DeleteObject(hVisRgn);
354 }
355 }
356 else
357 {
358 crWarning("GetRandomRgn returned (%d) instead of (1), VisibleRegions update failed", iret);
359 DeleteObject(hVisRgn);
360 }
361
362 return GL_FALSE;
363}
364
365# ifndef CR_NEWWINTRACK
366static void stubCBCheckWindowsInfo(unsigned long key, void *data1, void *data2)
367{
368 WindowInfo *winInfo = (WindowInfo *) data1;
369 CWPRETSTRUCT *pMsgInfo = (PCWPRETSTRUCT) data2;
370
371 (void) key;
372
373 if (winInfo && pMsgInfo && winInfo->type == CHROMIUM)
374 {
375 switch (pMsgInfo->message)
376 {
377 case WM_MOVING:
378 case WM_SIZING:
379 case WM_MOVE:
380 case WM_CREATE:
381 case WM_SIZE:
382 {
383 GLboolean changed = stub.trackWindowVisibleRgn && stubUpdateWindowVisibileRegions(winInfo);
384
385 if (stubUpdateWindowGeometry(winInfo, GL_FALSE) || changed)
386 {
387 crForcedFlush();
388 }
389 break;
390 }
391
392 case WM_SHOWWINDOW:
393 case WM_ACTIVATEAPP:
394 case WM_PAINT:
395 case WM_NCPAINT:
396 case WM_NCACTIVATE:
397 case WM_ERASEBKGND:
398 {
399 if (stub.trackWindowVisibleRgn && stubUpdateWindowVisibileRegions(winInfo))
400 {
401 crForcedFlush();
402 }
403 break;
404 }
405
406 default:
407 {
408 if (stub.trackWindowVisibleRgn && stubUpdateWindowVisibileRegions(winInfo))
409 {
410 crDebug("Visibility info updated due to unknown hooked message (%d)", pMsgInfo->message);
411 crForcedFlush();
412 }
413 break;
414 }
415 }
416 }
417}
418
419LRESULT CALLBACK stubCBWindowMessageHookProc(int nCode, WPARAM wParam, LPARAM lParam)
420{
421 CWPRETSTRUCT *pMsgInfo = (PCWPRETSTRUCT) lParam;
422
423 if (nCode>=0 && pMsgInfo)
424 {
425 switch (pMsgInfo->message)
426 {
427 case WM_MOVING:
428 case WM_SIZING:
429 case WM_MOVE:
430 case WM_ACTIVATEAPP:
431 case WM_NCPAINT:
432 case WM_NCACTIVATE:
433 case WM_ERASEBKGND:
434 case WM_CREATE:
435 case WM_SIZE:
436 case WM_SHOWWINDOW:
437 {
438 crHashtableWalk(stub.windowTable, stubCBCheckWindowsInfo, (void *) lParam);
439 break;
440 }
441
442 /* @todo remove it*/
443 default:
444 {
445 /*crDebug("hook: unknown message (%d)", pMsgInfo->message);*/
446 crHashtableWalk(stub.windowTable, stubCBCheckWindowsInfo, (void *) lParam);
447 break;
448 }
449 }
450 }
451
452 return CallNextHookEx(stub.hMessageHook, nCode, wParam, lParam);
453}
454
455void stubInstallWindowMessageHook()
456{
457 stub.hMessageHook = SetWindowsHookEx(WH_CALLWNDPROCRET, stubCBWindowMessageHookProc, 0, crThreadID());
458
459 if (!stub.hMessageHook)
460 crWarning("Window message hook install failed! (not fatal)");
461}
462
463void stubUninstallWindowMessageHook()
464{
465 if (stub.hMessageHook)
466 UnhookWindowsHookEx(stub.hMessageHook);
467}
468# endif /*# ifndef CR_NEWWINTRACK*/
469
470#elif defined(GLX) //#ifdef WINDOWS
471void stubCheckXExtensions(WindowInfo *pWindow)
472{
473 int evb, erb, vmi=0, vma=0;
474 Display *dpy = stubGetWindowDisplay(pWindow);
475
476 stub.bXExtensionsChecked = GL_TRUE;
477 stub.trackWindowVisibleRgn = 0;
478
479 XLOCK(dpy);
480 if (XCompositeQueryExtension(dpy, &evb, &erb)
481 && XCompositeQueryVersion(dpy, &vma, &vmi)
482 && (vma>0 || vmi>=4))
483 {
484 stub.bHaveXComposite = GL_TRUE;
485 crDebug("XComposite %i.%i", vma, vmi);
486 vma=0;
487 vmi=0;
488 if (XFixesQueryExtension(dpy, &evb, &erb)
489 && XFixesQueryVersion(dpy, &vma, &vmi)
490 && vma>=2)
491 {
492 crDebug("XFixes %i.%i", vma, vmi);
493 stub.bHaveXFixes = GL_TRUE;
494 stub.trackWindowVisibleRgn = 1;
495 XUNLOCK(dpy);
496 return;
497 }
498 else
499 {
500 crWarning("XFixes not found or old version (%i.%i), no VisibilityTracking", vma, vmi);
501 }
502 }
503 else
504 {
505 crWarning("XComposite not found or old version (%i.%i), no VisibilityTracking", vma, vmi);
506 }
507 XUNLOCK(dpy);
508 return;
509}
510
511/*
512 * Updates visible regions for given spu window.
513 * Returns GL_TRUE if regions changed since last call, GL_FALSE otherwise.
514 */
515GLboolean stubUpdateWindowVisibileRegions(WindowInfo *pWindow)
516{
517 XserverRegion xreg;
518 int cRects, i;
519 XRectangle *pXRects;
520 GLint* pGLRects;
521 Display *dpy;
522 bool bNoUpdate = false;
523
524 if (!stub.bXExtensionsChecked)
525 {
526 stubCheckXExtensions(pWindow);
527 if (!stub.trackWindowVisibleRgn)
528 {
529 return GL_FALSE;
530 }
531 }
532
533 dpy = stubGetWindowDisplay(pWindow);
534
535 /*@todo see comment regarding size/position updates and XSync, same applies to those functions but
536 * it seems there's no way to get even based updates for this. Or I've failed to find the appropriate extension.
537 */
538 XLOCK(dpy);
539 xreg = XCompositeCreateRegionFromBorderClip(dpy, pWindow->drawable);
540 pXRects = XFixesFetchRegion(dpy, xreg, &cRects);
541 XFixesDestroyRegion(dpy, xreg);
542 XUNLOCK(dpy);
543
544 /* Check for compiz main window */
545 if (!pWindow->pVisibleRegions && !cRects)
546 {
547#ifdef VBOX_TEST_MEGOO
548 XWindowAttributes attr;
549 XLOCK(dpy);
550 XSync(dpy, false);
551 XGetWindowAttributes(dpy, pWindow->drawable, &attr);
552 XUNLOCK(dpy);
553
554 bNoUpdate = attr.override_redirect;
555#else
556 bNoUpdate = true;
557#endif
558 }
559
560 if (!bNoUpdate
561 && (!pWindow->pVisibleRegions
562 || pWindow->cVisibleRegions!=cRects
563 || (pWindow->pVisibleRegions && crMemcmp(pWindow->pVisibleRegions, pXRects, cRects * sizeof(XRectangle)))))
564 {
565 if (pWindow->pVisibleRegions)
566 {
567 XFree(pWindow->pVisibleRegions);
568 }
569
570 pWindow->pVisibleRegions = pXRects;
571 pWindow->cVisibleRegions = cRects;
572
573 pGLRects = crAlloc(4*cRects*sizeof(GLint));
574 if (!pGLRects)
575 {
576 crWarning("stubUpdateWindowVisibileRegions: failed to allocate %lu bytes",
577 (unsigned long)(4*cRects*sizeof(GLint)));
578 return GL_FALSE;
579 }
580
581 //crDebug("Got %i rects.", cRects);
582 for (i=0; i<cRects; ++i)
583 {
584 pGLRects[4*i+0] = pXRects[i].x;
585 pGLRects[4*i+1] = pXRects[i].y;
586 pGLRects[4*i+2] = pXRects[i].x+pXRects[i].width;
587 pGLRects[4*i+3] = pXRects[i].y+pXRects[i].height;
588 //crDebug("Rect[%i]=(%i,%i,%i,%i)", i, pGLRects[4*i+0], pGLRects[4*i+1], pGLRects[4*i+2], pGLRects[4*i+3]);
589 }
590
591 crDebug("Dispatched WindowVisibleRegion (%i, cRects=%i)", pWindow->spuWindow, cRects);
592 stub.spuDispatch.WindowVisibleRegion(pWindow->spuWindow, cRects, pGLRects);
593 crFree(pGLRects);
594 return GL_TRUE;
595 }
596 else
597 {
598 XFree(pXRects);
599 }
600
601 return GL_FALSE;
602}
603#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