VirtualBox

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

Last change on this file since 42973 was 42518, checked in by vboxsync, 13 years ago

crOpenGL/wddm: context-connection and other fixes

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