VirtualBox

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

Last change on this file since 78376 was 69310, checked in by vboxsync, 7 years ago

common/crOpenGL: scm updates

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