VirtualBox

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

Last change on this file since 28516 was 28294, checked in by vboxsync, 15 years ago

gcc warnings

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