VirtualBox

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

最後變更 在這個檔案從38157是 37986,由 vboxsync 提交於 13 年 前

Wddm/3d: fix thread sync issues

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette