VirtualBox

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

最後變更 在這個檔案從21077是 20084,由 vboxsync 提交於 16 年 前

crOpenGL: reduce amount of sync calls to speed up d3d

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Id
檔案大小: 14.9 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
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#ifdef CHROMIUM_THREADSAFE
353 crLockMutex(&stub.mutex);
354#endif
355 switch (pMsgInfo->message)
356 {
357 case WM_MOVING:
358 case WM_SIZING:
359 case WM_MOVE:
360 case WM_ACTIVATEAPP:
361 case WM_NCPAINT:
362 case WM_NCACTIVATE:
363 case WM_ERASEBKGND:
364 case WM_CREATE:
365 case WM_SIZE:
366 case WM_SHOWWINDOW:
367 {
368 crHashtableWalk(stub.windowTable, stubCBCheckWindowsInfo, (void *) lParam);
369 break;
370 }
371
372 /* @todo remove it*/
373 default:
374 {
375 /*crDebug("hook: unknown message (%d)", pMsgInfo->message);*/
376 crHashtableWalk(stub.windowTable, stubCBCheckWindowsInfo, (void *) lParam);
377 break;
378 }
379 }
380#ifdef CHROMIUM_THREADSAFE
381 crUnlockMutex(&stub.mutex);
382#endif
383 }
384
385 return CallNextHookEx(stub.hMessageHook, nCode, wParam, lParam);
386}
387
388void stubInstallWindowMessageHook()
389{
390 stub.hMessageHook = SetWindowsHookEx(WH_CALLWNDPROCRET, stubCBWindowMessageHookProc, 0, crThreadID());
391
392 if (!stub.hMessageHook)
393 crWarning("Window message hook install failed! (not fatal)");
394}
395
396void stubUninstallWindowMessageHook()
397{
398 if (stub.hMessageHook)
399 UnhookWindowsHookEx(stub.hMessageHook);
400}
401#elif defined(GLX) //#ifdef WINDOWS
402static GLboolean stubCheckXExtensions(WindowInfo *pWindow)
403{
404 int evb, erb, vmi=0, vma=0;
405
406 if (XCompositeQueryExtension(pWindow->dpy, &evb, &erb)
407 && XCompositeQueryVersion(pWindow->dpy, &vma, &vmi)
408 && (vma>0 || vmi>=4))
409 {
410 crDebug("XComposite %i.%i", vma, vmi);
411 vma=0;
412 vmi=0;
413 if (XFixesQueryExtension(pWindow->dpy, &evb, &erb)
414 && XFixesQueryVersion(pWindow->dpy, &vma, &vmi)
415 && vma>=2)
416 {
417 crDebug("XFixes %i.%i", vma, vmi);
418 return GL_TRUE;
419 }
420 else
421 {
422 crWarning("XFixes not found or old version (%i.%i), no VisibilityTracking", vma, vmi);
423 }
424 }
425 else
426 {
427 crWarning("XComposite not found or old version (%i.%i), no VisibilityTracking", vma, vmi);
428 }
429 return GL_FALSE;
430}
431
432/*
433 * Updates visible regions for given spu window.
434 * Returns GL_TRUE if regions changed since last call, GL_FALSE overwise.
435 */
436GLboolean stubUpdateWindowVisibileRegions(WindowInfo *pWindow)
437{
438 static GLboolean bExtensionsChecked = GL_FALSE;
439
440 XserverRegion xreg;
441 int cRects, i;
442 XRectangle *pXRects;
443 GLint* pGLRects;
444
445 if (bExtensionsChecked || stubCheckXExtensions(pWindow))
446 {
447 bExtensionsChecked = GL_TRUE;
448 }
449 else
450 {
451 stub.trackWindowVisibleRgn = 0;
452 return GL_FALSE;
453 }
454
455 /*@todo see comment regarding size/position updates and XSync, same applies to those functions but
456 * it seems there's no way to get even based updates for this. Or I've failed to find the appropriate extension.
457 */
458 xreg = XCompositeCreateRegionFromBorderClip(pWindow->dpy, pWindow->drawable);
459 pXRects = XFixesFetchRegion(pWindow->dpy, xreg, &cRects);
460 XFixesDestroyRegion(pWindow->dpy, xreg);
461
462 /* @todo For some odd reason *first* run of compiz on freshly booted VM gives us 0 cRects all the time.
463 * In (!pWindow->pVisibleRegions && cRects) "&& cRects" is a workaround for that case, especially as this
464 * information is useless for full screen composing managers anyway.
465 */
466 if ((!pWindow->pVisibleRegions && cRects)
467 || pWindow->cVisibleRegions!=cRects
468 || (pWindow->pVisibleRegions && crMemcmp(pWindow->pVisibleRegions, pXRects, cRects * sizeof(XRectangle))))
469 {
470 pWindow->pVisibleRegions = pXRects;
471 pWindow->cVisibleRegions = cRects;
472
473 pGLRects = crAlloc(4*cRects*sizeof(GLint));
474 if (!pGLRects)
475 {
476 crWarning("stubUpdateWindowVisibileRegions: failed to allocate %i bytes", 4*cRects*sizeof(GLint));
477 return GL_FALSE;
478 }
479
480 //crDebug("Got %i rects.", cRects);
481 for (i=0; i<cRects; ++i)
482 {
483 pGLRects[4*i+0] = pXRects[i].x;
484 pGLRects[4*i+1] = pXRects[i].y;
485 pGLRects[4*i+2] = pXRects[i].x+pXRects[i].width;
486 pGLRects[4*i+3] = pXRects[i].y+pXRects[i].height;
487 //crDebug("Rect[%i]=(%i,%i,%i,%i)", i, pGLRects[4*i+0], pGLRects[4*i+1], pGLRects[4*i+2], pGLRects[4*i+3]);
488 }
489
490 crDebug("Dispatched WindowVisibleRegion (%i, cRects=%i)", pWindow->spuWindow, cRects);
491 stub.spuDispatch.WindowVisibleRegion(pWindow->spuWindow, cRects, pGLRects);
492 crFree(pGLRects);
493 return GL_TRUE;
494 }
495 else
496 {
497 XFree(pXRects);
498 }
499
500 return GL_FALSE;
501}
502#endif //#ifdef WINDOWS
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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