VirtualBox

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

Last change on this file since 19420 was 16748, checked in by vboxsync, 16 years ago

crOpenGL: use damage regions information for pixmap updates

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 14.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
12#ifdef GLX
13#include <X11/extensions/Xcomposite.h>
14#include <X11/extensions/Xfixes.h>
15#endif
16
17/**
18 * Returns -1 on error
19 */
20GLint APIENTRY crCreateContext( const char *dpyName, GLint visBits )
21{
22 ContextInfo *context;
23 stubInit();
24 /* XXX in Chromium 1.5 and earlier, the last parameter was UNDECIDED.
25 * That didn't seem right so it was changed to CHROMIUM. (Brian)
26 */
27 context = stubNewContext(dpyName, visBits, CHROMIUM, 0);
28 return context ? (int) context->id : -1;
29}
30
31void APIENTRY crDestroyContext( GLint context )
32{
33 stubDestroyContext(context);
34}
35
36void APIENTRY crMakeCurrent( GLint window, GLint context )
37{
38 WindowInfo *winInfo = (WindowInfo *)
39 crHashtableSearch(stub.windowTable, (unsigned int) window);
40 ContextInfo *contextInfo = (ContextInfo *)
41 crHashtableSearch(stub.contextTable, context);
42 if (contextInfo && contextInfo->type == NATIVE) {
43 crWarning("Can't call crMakeCurrent with native GL context");
44 return;
45 }
46
47 stubMakeCurrent(winInfo, contextInfo);
48}
49
50GLint APIENTRY crGetCurrentContext( void )
51{
52 stubInit();
53 if (stub.currentContext)
54 return (GLint) stub.currentContext->id;
55 else
56 return 0;
57}
58
59GLint APIENTRY crGetCurrentWindow( void )
60{
61 stubInit();
62 if (stub.currentContext && stub.currentContext->currentDrawable)
63 return stub.currentContext->currentDrawable->spuWindow;
64 else
65 return -1;
66}
67
68void APIENTRY crSwapBuffers( GLint window, GLint flags )
69{
70 const WindowInfo *winInfo = (const WindowInfo *)
71 crHashtableSearch(stub.windowTable, (unsigned int) window);
72 if (winInfo)
73 stubSwapBuffers(winInfo, flags);
74}
75
76/**
77 * Returns -1 on error
78 */
79GLint APIENTRY crWindowCreate( const char *dpyName, GLint visBits )
80{
81 stubInit();
82 return stubNewWindow( dpyName, visBits );
83}
84
85void APIENTRY crWindowDestroy( GLint window )
86{
87 WindowInfo *winInfo = (WindowInfo *)
88 crHashtableSearch(stub.windowTable, (unsigned int) window);
89 if (winInfo && winInfo->type == CHROMIUM && stub.spu) {
90 stub.spu->dispatch_table.WindowDestroy( winInfo->spuWindow );
91#ifdef WINDOWS
92 if (winInfo->hVisibleRegion != INVALID_HANDLE_VALUE)
93 {
94 DeleteObject(winInfo->hVisibleRegion);
95 }
96#elif defined(GLX)
97 if (winInfo->pVisibleRegions)
98 {
99 XFree(winInfo->pVisibleRegions);
100 }
101#endif
102 stub.spu->dispatch_table.Flush();
103
104 crHashtableDelete(stub.windowTable, window, crFree);
105 }
106}
107
108void APIENTRY crWindowSize( GLint window, GLint w, GLint h )
109{
110 const WindowInfo *winInfo = (const WindowInfo *)
111 crHashtableSearch(stub.windowTable, (unsigned int) window);
112 if (winInfo && winInfo->type == CHROMIUM)
113 {
114 crDebug("Dispatched crWindowSize (%i)", window);
115 stub.spu->dispatch_table.WindowSize( window, w, h );
116 }
117}
118
119void APIENTRY crWindowPosition( GLint window, GLint x, GLint y )
120{
121 const WindowInfo *winInfo = (const WindowInfo *)
122 crHashtableSearch(stub.windowTable, (unsigned int) window);
123 if (winInfo && winInfo->type == CHROMIUM)
124 {
125 crDebug("Dispatched crWindowPosition (%i)", window);
126 stub.spu->dispatch_table.WindowPosition( window, x, y );
127 }
128}
129
130void APIENTRY crWindowVisibleRegion( GLint window, GLint cRects, void *pRects )
131{
132 const WindowInfo *winInfo = (const WindowInfo *)
133 crHashtableSearch(stub.windowTable, (unsigned int) window);
134 if (winInfo && winInfo->type == CHROMIUM)
135 {
136 crDebug("Dispatched crWindowVisibleRegion (%i, cRects=%i)", window, cRects);
137 stub.spu->dispatch_table.WindowVisibleRegion( window, cRects, pRects );
138 }
139}
140
141void APIENTRY crWindowShow( GLint window, GLint flag )
142{
143 WindowInfo *winInfo = (WindowInfo *)
144 crHashtableSearch(stub.windowTable, (unsigned int) window);
145 if (winInfo && winInfo->type == CHROMIUM)
146 stub.spu->dispatch_table.WindowShow( window, flag );
147 winInfo->mapped = flag ? GL_TRUE : GL_FALSE;
148}
149
150void APIENTRY stub_GetChromiumParametervCR( GLenum target, GLuint index, GLenum type, GLsizei count, GLvoid *values )
151{
152 char **ret;
153 switch( target )
154 {
155 case GL_HEAD_SPU_NAME_CR:
156 ret = (char **) values;
157 *ret = stub.spu->name;
158 return;
159 default:
160 stub.spu->dispatch_table.GetChromiumParametervCR( target, index, type, count, values );
161 break;
162 }
163}
164
165/*
166 * Updates geometry info for given spu window.
167 * Returns GL_TRUE if it changed since last call, GL_FALSE overwise.
168 * bForceUpdate - forces dispatching of geometry info even if it's unchanged
169 */
170GLboolean stubUpdateWindowGeometry(WindowInfo *pWindow, GLboolean bForceUpdate)
171{
172 int winX, winY;
173 unsigned int winW, winH;
174 GLboolean res = GL_FALSE;
175
176 CRASSERT(pWindow);
177
178 stubGetWindowGeometry(pWindow, &winX, &winY, &winW, &winH);
179
180 /* @todo remove "if (winW && winH)"?*/
181 if (winW && winH) {
182 if (stub.trackWindowSize) {
183 if (bForceUpdate || winW != pWindow->width || winH != pWindow->height) {
184 crDebug("Dispatched WindowSize (%i)", pWindow->spuWindow);
185 stub.spuDispatch.WindowSize(pWindow->spuWindow, winW, winH);
186 pWindow->width = winW;
187 pWindow->height = winH;
188 res = GL_TRUE;
189 }
190 }
191 if (stub.trackWindowPos) {
192 if (bForceUpdate || winX != pWindow->x || winY != pWindow->y) {
193 crDebug("Dispatched WindowPosition (%i)", pWindow->spuWindow);
194 stub.spuDispatch.WindowPosition(pWindow->spuWindow, winX, winY);
195 pWindow->x = winX;
196 pWindow->y = winY;
197 res = GL_TRUE;
198 }
199 }
200 }
201
202 return res;
203}
204
205#ifdef WINDOWS
206/*
207 * Updates visible regions for given spu window.
208 * Returns GL_TRUE if regions changed since last call, GL_FALSE overwise.
209 */
210GLboolean stubUpdateWindowVisibileRegions(WindowInfo *pWindow)
211{
212 HRGN hVisRgn;
213 HWND hwnd;
214 DWORD dwCount;
215 LPRGNDATA lpRgnData;
216 POINT pt;
217 int iret;
218
219 if (!pWindow) return GL_FALSE;
220 hwnd = WindowFromDC(pWindow->drawable);
221 if (!hwnd) return GL_FALSE;
222
223
224 hVisRgn = CreateRectRgn(0,0,0,0);
225 iret = GetRandomRgn(pWindow->drawable, hVisRgn, SYSRGN);
226
227 if (iret==1)
228 {
229 /*@todo check win95/win98 here, as rects should be already in client space there*/
230 /* Convert screen related rectangles to client related rectangles */
231 pt.x = 0;
232 pt.y = 0;
233 ScreenToClient(hwnd, &pt);
234 OffsetRgn(hVisRgn, pt.x, pt.y);
235
236 /*
237 dwCount = GetRegionData(hVisRgn, 0, NULL);
238 lpRgnData = crAlloc(dwCount);
239 crDebug("GetRandomRgn returned 1, dwCount=%d", dwCount);
240 GetRegionData(hVisRgn, dwCount, lpRgnData);
241 crDebug("Region consists of %d rects", lpRgnData->rdh.nCount);
242
243 pRects = (RECT*) lpRgnData->Buffer;
244 for (i=0; i<lpRgnData->rdh.nCount; ++i)
245 {
246 crDebug("Rgn[%d] = (%d, %d, %d, %d)", i, pRects[i].left, pRects[i].top, pRects[i].right, pRects[i].bottom);
247 }
248 crFree(lpRgnData);
249 */
250
251 if (pWindow->hVisibleRegion==INVALID_HANDLE_VALUE
252 || !EqualRgn(pWindow->hVisibleRegion, hVisRgn))
253 {
254 DeleteObject(pWindow->hVisibleRegion);
255 pWindow->hVisibleRegion = hVisRgn;
256
257 dwCount = GetRegionData(hVisRgn, 0, NULL);
258 lpRgnData = crAlloc(dwCount);
259
260 if (lpRgnData)
261 {
262 GetRegionData(hVisRgn, dwCount, lpRgnData);
263 crDebug("Dispatched WindowVisibleRegion (%i, cRects=%i)", pWindow->spuWindow, lpRgnData->rdh.nCount);
264 stub.spuDispatch.WindowVisibleRegion(pWindow->spuWindow, lpRgnData->rdh.nCount, (GLint*) lpRgnData->Buffer);
265 crFree(lpRgnData);
266 return GL_TRUE;
267 }
268 else crWarning("GetRegionData failed, VisibleRegions update failed");
269 }
270 else
271 {
272 DeleteObject(hVisRgn);
273 }
274 }
275 else
276 {
277 crWarning("GetRandomRgn returned (%d) instead of (1), VisibleRegions update failed", iret);
278 DeleteObject(hVisRgn);
279 }
280
281 return GL_FALSE;
282}
283
284static void stubCBCheckWindowsInfo(unsigned long key, void *data1, void *data2)
285{
286 WindowInfo *winInfo = (WindowInfo *) data1;
287 CWPRETSTRUCT *pMsgInfo = (PCWPRETSTRUCT) data2;
288
289 (void) key;
290
291 if (winInfo && pMsgInfo && winInfo->type == CHROMIUM)
292 {
293 switch (pMsgInfo->message)
294 {
295 case WM_MOVING:
296 case WM_SIZING:
297 case WM_MOVE:
298 case WM_CREATE:
299 case WM_SIZE:
300 {
301 GLboolean changed = stub.trackWindowVisibleRgn && stubUpdateWindowVisibileRegions(winInfo);
302
303 if (stubUpdateWindowGeometry(winInfo, GL_FALSE) || changed)
304 {
305 stub.spuDispatch.Flush();
306 }
307 break;
308 }
309
310 case WM_SHOWWINDOW:
311 case WM_ACTIVATEAPP:
312 case WM_PAINT:
313 case WM_NCPAINT:
314 case WM_NCACTIVATE:
315 case WM_ERASEBKGND:
316 {
317 if (stub.trackWindowVisibleRgn && stubUpdateWindowVisibileRegions(winInfo))
318 {
319 stub.spuDispatch.Flush();
320 }
321 break;
322 }
323
324 default:
325 {
326 if (stub.trackWindowVisibleRgn && stubUpdateWindowVisibileRegions(winInfo))
327 {
328 crDebug("Visibility info updated due to unknown hooked message (%d)", pMsgInfo->message);
329 stub.spuDispatch.Flush();
330 }
331 break;
332 }
333 }
334 }
335}
336
337LRESULT CALLBACK stubCBWindowMessageHookProc(int nCode, WPARAM wParam, LPARAM lParam)
338{
339 CWPRETSTRUCT *pMsgInfo = (PCWPRETSTRUCT) lParam;
340
341 if (nCode>=0 && pMsgInfo)
342 {
343#ifdef CHROMIUM_THREADSAFE
344 crLockMutex(&stub.mutex);
345#endif
346 switch (pMsgInfo->message)
347 {
348 case WM_MOVING:
349 case WM_SIZING:
350 case WM_MOVE:
351 case WM_ACTIVATEAPP:
352 case WM_NCPAINT:
353 case WM_NCACTIVATE:
354 case WM_ERASEBKGND:
355 case WM_CREATE:
356 case WM_SIZE:
357 case WM_SHOWWINDOW:
358 {
359 crHashtableWalk(stub.windowTable, stubCBCheckWindowsInfo, (void *) lParam);
360 break;
361 }
362
363 /* @todo remove it*/
364 default:
365 {
366 /*crDebug("hook: unknown message (%d)", pMsgInfo->message);*/
367 crHashtableWalk(stub.windowTable, stubCBCheckWindowsInfo, (void *) lParam);
368 break;
369 }
370 }
371#ifdef CHROMIUM_THREADSAFE
372 crUnlockMutex(&stub.mutex);
373#endif
374 }
375
376 return CallNextHookEx(stub.hMessageHook, nCode, wParam, lParam);
377}
378
379void stubInstallWindowMessageHook()
380{
381 stub.hMessageHook = SetWindowsHookEx(WH_CALLWNDPROCRET, stubCBWindowMessageHookProc, 0, crThreadID());
382
383 if (!stub.hMessageHook)
384 crWarning("Window message hook install failed! (not fatal)");
385}
386
387void stubUninstallWindowMessageHook()
388{
389 if (stub.hMessageHook)
390 UnhookWindowsHookEx(stub.hMessageHook);
391}
392#elif defined(GLX) //#ifdef WINDOWS
393static GLboolean stubCheckXExtensions(WindowInfo *pWindow)
394{
395 int evb, erb, vmi=0, vma=0;
396
397 if (XCompositeQueryExtension(pWindow->dpy, &evb, &erb)
398 && XCompositeQueryVersion(pWindow->dpy, &vma, &vmi)
399 && (vma>0 || vmi>=4))
400 {
401 crDebug("XComposite %i.%i", vma, vmi);
402 vma=0;
403 vmi=0;
404 if (XFixesQueryExtension(pWindow->dpy, &evb, &erb)
405 && XFixesQueryVersion(pWindow->dpy, &vma, &vmi)
406 && vma>=2)
407 {
408 crDebug("XFixes %i.%i", vma, vmi);
409 return GL_TRUE;
410 }
411 else
412 {
413 crWarning("XFixes not found or old version (%i.%i), no VisibilityTracking", vma, vmi);
414 }
415 }
416 else
417 {
418 crWarning("XComposite not found or old version (%i.%i), no VisibilityTracking", vma, vmi);
419 }
420 return GL_FALSE;
421}
422
423/*
424 * Updates visible regions for given spu window.
425 * Returns GL_TRUE if regions changed since last call, GL_FALSE overwise.
426 */
427GLboolean stubUpdateWindowVisibileRegions(WindowInfo *pWindow)
428{
429 static GLboolean bExtensionsChecked = GL_FALSE;
430
431 XserverRegion xreg;
432 int cRects, i;
433 XRectangle *pXRects;
434 GLint* pGLRects;
435
436 if (bExtensionsChecked || stubCheckXExtensions(pWindow))
437 {
438 bExtensionsChecked = GL_TRUE;
439 }
440 else
441 {
442 stub.trackWindowVisibleRgn = 0;
443 return GL_FALSE;
444 }
445
446 /*@todo see comment regarding size/position updates and XSync, same applies to those functions but
447 * it seems there's no way to get even based updates for this. Or I've failed to find the appropriate extension.
448 */
449 xreg = XCompositeCreateRegionFromBorderClip(pWindow->dpy, pWindow->drawable);
450 pXRects = XFixesFetchRegion(pWindow->dpy, xreg, &cRects);
451 XFixesDestroyRegion(pWindow->dpy, xreg);
452
453 /* @todo For some odd reason *first* run of compiz on freshly booted VM gives us 0 cRects all the time.
454 * In (!pWindow->pVisibleRegions && cRects) "&& cRects" is a workaround for that case, especially as this
455 * information is useless for full screen composing managers anyway.
456 */
457 if ((!pWindow->pVisibleRegions && cRects)
458 || pWindow->cVisibleRegions!=cRects
459 || (pWindow->pVisibleRegions && crMemcmp(pWindow->pVisibleRegions, pXRects, cRects * sizeof(XRectangle))))
460 {
461 pWindow->pVisibleRegions = pXRects;
462 pWindow->cVisibleRegions = cRects;
463
464 pGLRects = crAlloc(4*cRects*sizeof(GLint));
465 if (!pGLRects)
466 {
467 crWarning("stubUpdateWindowVisibileRegions: failed to allocate %i bytes", 4*cRects*sizeof(GLint));
468 return GL_FALSE;
469 }
470
471 //crDebug("Got %i rects.", cRects);
472 for (i=0; i<cRects; ++i)
473 {
474 pGLRects[4*i+0] = pXRects[i].x;
475 pGLRects[4*i+1] = pXRects[i].y;
476 pGLRects[4*i+2] = pXRects[i].x+pXRects[i].width;
477 pGLRects[4*i+3] = pXRects[i].y+pXRects[i].height;
478 //crDebug("Rect[%i]=(%i,%i,%i,%i)", i, pGLRects[4*i+0], pGLRects[4*i+1], pGLRects[4*i+2], pGLRects[4*i+3]);
479 }
480
481 crDebug("Dispatched WindowVisibleRegion (%i, cRects=%i)", pWindow->spuWindow, cRects);
482 stub.spuDispatch.WindowVisibleRegion(pWindow->spuWindow, cRects, pGLRects);
483 crFree(pGLRects);
484 return GL_TRUE;
485 }
486 else
487 {
488 XFree(pXRects);
489 }
490
491 return GL_FALSE;
492}
493#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