VirtualBox

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

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

crOpenGL: another 8x speed up for compiz, xdamage but without regions info yet

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 30.6 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/**
8 * \mainpage OpenGL_stub
9 *
10 * \section OpenGL_stubIntroduction Introduction
11 *
12 * Chromium consists of all the top-level files in the cr
13 * directory. The OpenGL_stub module basically takes care of API dispatch,
14 * and OpenGL state management.
15 *
16 */
17
18/**
19 * This file manages OpenGL rendering contexts in the faker library.
20 * The big issue is switching between Chromium and native GL context
21 * management. This is where we support multiple client OpenGL
22 * windows. Typically, one window is handled by Chromium while any
23 * other windows are handled by the native OpenGL library.
24 */
25
26#include "chromium.h"
27#include "cr_error.h"
28#include "cr_spu.h"
29#include "cr_mem.h"
30#include "cr_string.h"
31#include "cr_environment.h"
32#include "stub.h"
33
34
35/**
36 * This function should be called from MakeCurrent(). It'll detect if
37 * we're in a multi-thread situation, and do the right thing for dispatch.
38 */
39#ifdef CHROMIUM_THREADSAFE
40 static void
41stubCheckMultithread( void )
42{
43 static unsigned long knownID;
44 static GLboolean firstCall = GL_TRUE;
45
46 if (stub.threadSafe)
47 return; /* nothing new, nothing to do */
48
49 if (firstCall) {
50 knownID = crThreadID();
51 firstCall = GL_FALSE;
52 }
53 else if (knownID != crThreadID()) {
54 /* going thread-safe now! */
55 stub.threadSafe = GL_TRUE;
56 crSPUCopyDispatchTable(&glim, &stubThreadsafeDispatch);
57 }
58}
59#endif
60
61
62/**
63 * Install the given dispatch table as the table used for all gl* calls.
64 */
65 static void
66stubSetDispatch( SPUDispatchTable *table )
67{
68 CRASSERT(table);
69
70#ifdef CHROMIUM_THREADSAFE
71 /* always set the per-thread dispatch pointer */
72 crSetTSD(&stub.dispatchTSD, (void *) table);
73 if (stub.threadSafe) {
74 /* Do nothing - the thread-safe dispatch functions will call GetTSD()
75 * to get a pointer to the dispatch table, and jump through it.
76 */
77 }
78 else
79#endif
80 {
81 /* Single thread mode - just install the caller's dispatch table */
82 /* This conditional is an optimization to try to avoid unnecessary
83 * copying. It seems to work with atlantis, multiwin, etc. but
84 * _could_ be a problem. (Brian)
85 */
86 if (glim.copy_of != table->copy_of)
87 crSPUCopyDispatchTable(&glim, table);
88 }
89}
90
91
92/**
93 * Create a new _Chromium_ window, not GLX, WGL or CGL.
94 * Called by crWindowCreate() only.
95 */
96 GLint
97stubNewWindow( const char *dpyName, GLint visBits )
98{
99 WindowInfo *winInfo;
100 GLint spuWin, size[2];
101
102 spuWin = stub.spu->dispatch_table.WindowCreate( dpyName, visBits );
103 if (spuWin < 0) {
104 return -1;
105 }
106
107 winInfo = (WindowInfo *) crCalloc(sizeof(WindowInfo));
108 if (!winInfo) {
109 stub.spu->dispatch_table.WindowDestroy(spuWin);
110 return -1;
111 }
112
113 winInfo->type = CHROMIUM;
114
115 /* Ask the head SPU for the initial window size */
116 size[0] = size[1] = 0;
117 stub.spu->dispatch_table.GetChromiumParametervCR(GL_WINDOW_SIZE_CR, 0, GL_INT, 2, size);
118 if (size[0] == 0 && size[1] == 0) {
119 /* use some reasonable defaults */
120 size[0] = size[1] = 512;
121 }
122 winInfo->width = size[0];
123 winInfo->height = size[1];
124 winInfo->mapped = 1;
125
126 if (!dpyName)
127 dpyName = "";
128
129 crStrncpy(winInfo->dpyName, dpyName, MAX_DPY_NAME);
130 winInfo->dpyName[MAX_DPY_NAME-1] = 0;
131
132 /* Use spuWin as the hash table index and GLX/WGL handle */
133#ifdef WINDOWS
134 winInfo->drawable = (HDC) spuWin;
135 winInfo->hVisibleRegion = INVALID_HANDLE_VALUE;
136#elif defined(Darwin)
137 winInfo->drawable = (CGSWindowID) spuWin;
138#elif defined(GLX)
139 winInfo->drawable = (GLXDrawable) spuWin;
140 winInfo->pVisibleRegions = NULL;
141 winInfo->cVisibleRegions = 0;
142#endif
143 winInfo->spuWindow = spuWin;
144
145 crHashtableAdd(stub.windowTable, (unsigned int) spuWin, winInfo);
146
147 return spuWin;
148}
149
150
151GLboolean
152stubIsWindowVisible( const WindowInfo *win )
153{
154#if defined(WINDOWS)
155 return GL_TRUE;
156#elif defined(Darwin)
157 return GL_TRUE;
158#elif defined(GLX)
159 if (win->dpy) {
160 XWindowAttributes attr;
161 XGetWindowAttributes(win->dpy, win->drawable, &attr);
162 return (attr.map_state != IsUnmapped);
163 }
164 else {
165 /* probably created by crWindowCreate() */
166 return win->mapped;
167 }
168#endif
169}
170
171
172/**
173 * Given a Windows HDC or GLX Drawable, return the corresponding
174 * WindowInfo structure. Create a new one if needed.
175 */
176WindowInfo *
177#ifdef WINDOWS
178 stubGetWindowInfo( HDC drawable )
179#elif defined(Darwin)
180 stubGetWindowInfo( CGSWindowID drawable )
181#elif defined(GLX)
182stubGetWindowInfo( Display *dpy, GLXDrawable drawable )
183#endif
184{
185#ifndef WINDOWS
186 WindowInfo *winInfo = (WindowInfo *) crHashtableSearch(stub.windowTable, (unsigned int) drawable);
187#else
188 WindowInfo *winInfo;
189 HWND hwnd;
190 hwnd = WindowFromDC(drawable);
191
192 if (!hwnd)
193 {
194 crError("Can't get HWND for given HDC(%x)", drawable);
195 }
196
197 winInfo = (WindowInfo *) crHashtableSearch(stub.windowTable, (unsigned int) hwnd);
198#endif
199 if (!winInfo) {
200 winInfo = (WindowInfo *) crCalloc(sizeof(WindowInfo));
201 if (!winInfo)
202 return NULL;
203#ifdef GLX
204 crStrncpy(winInfo->dpyName, DisplayString(dpy), MAX_DPY_NAME);
205 winInfo->dpyName[MAX_DPY_NAME-1] = 0;
206 winInfo->dpy = dpy;
207 winInfo->pVisibleRegions = NULL;
208#elif defined(Darwin)
209 winInfo->connection = _CGSDefaultConnection(); // store our connection as default
210#elif defined(WINDOWS)
211 winInfo->hVisibleRegion = INVALID_HANDLE_VALUE;
212 winInfo->hWnd = hwnd;
213#endif
214 winInfo->drawable = drawable;
215 winInfo->type = UNDECIDED;
216 winInfo->spuWindow = -1;
217 winInfo->mapped = -1; /* don't know */
218#ifndef WINDOWS
219 crHashtableAdd(stub.windowTable, (unsigned int) drawable, winInfo);
220#else
221 crHashtableAdd(stub.windowTable, (unsigned int) hwnd, winInfo);
222#endif
223 }
224 return winInfo;
225}
226
227
228/**
229 * Allocate a new ContextInfo object, initialize it, put it into the
230 * context hash table. If type==CHROMIUM, call the head SPU's
231 * CreateContext() function too.
232 */
233 ContextInfo *
234stubNewContext( const char *dpyName, GLint visBits, ContextType type,
235 unsigned long shareCtx )
236{
237 GLint spuContext = -1, spuShareCtx = 0;
238 ContextInfo *context;
239
240 if (shareCtx > 0) {
241 /* translate shareCtx to a SPU context ID */
242 context = (ContextInfo *)
243 crHashtableSearch(stub.contextTable, shareCtx);
244 if (context)
245 spuShareCtx = context->spuContext;
246 }
247
248 if (type == CHROMIUM) {
249 spuContext
250 = stub.spu->dispatch_table.CreateContext(dpyName, visBits, spuShareCtx);
251 if (spuContext < 0)
252 return NULL;
253 }
254
255 context = crCalloc(sizeof(ContextInfo));
256 if (!context) {
257 stub.spu->dispatch_table.DestroyContext(spuContext);
258 return NULL;
259 }
260
261 if (!dpyName)
262 dpyName = "";
263
264 context->id = stub.freeContextNumber++;
265 context->type = type;
266 context->spuContext = spuContext;
267 context->visBits = visBits;
268 context->currentDrawable = NULL;
269 context->pOwnWindow = NULL;
270 crStrncpy(context->dpyName, dpyName, MAX_DPY_NAME);
271 context->dpyName[MAX_DPY_NAME-1] = 0;
272
273#if defined(GLX) || defined(DARWIN)
274 context->share = (ContextInfo *)
275 crHashtableSearch(stub.contextTable, (unsigned long) shareCtx);
276#endif
277
278#ifdef GLX
279 context->pGLXPixmapsHash = crAllocHashtable();
280 context->damageInitFailed = GL_FALSE;
281 context->damageDpy = NULL;
282 context->damageEventsBase = 0;
283#endif
284
285 crHashtableAdd(stub.contextTable, context->id, (void *) context);
286
287 return context;
288}
289
290
291#ifdef Darwin
292
293#define SET_ATTR(l,i,a) ( (l)[(i)++] = (a) )
294#define SET_ATTR_V(l,i,a,v) ( SET_ATTR(l,i,a), SET_ATTR(l,i,v) )
295
296void stubSetPFA( ContextInfo *ctx, CGLPixelFormatAttribute *attribs, int size, GLint *num ) {
297 GLuint visual = ctx->visBits;
298 int i = 0;
299
300 CRASSERT(visual & CR_RGB_BIT);
301
302 SET_ATTR_V(attribs, i, kCGLPFAColorSize, 8);
303
304 if( visual & CR_DEPTH_BIT )
305 SET_ATTR_V(attribs, i, kCGLPFADepthSize, 16);
306
307 if( visual & CR_ACCUM_BIT )
308 SET_ATTR_V(attribs, i, kCGLPFAAccumSize, 1);
309
310 if( visual & CR_STENCIL_BIT )
311 SET_ATTR_V(attribs, i, kCGLPFAStencilSize, 1);
312
313 if( visual & CR_ALPHA_BIT )
314 SET_ATTR_V(attribs, i, kCGLPFAAlphaSize, 1);
315
316 if( visual & CR_DOUBLE_BIT )
317 SET_ATTR(attribs, i, kCGLPFADoubleBuffer);
318
319 if( visual & CR_STEREO_BIT )
320 SET_ATTR(attribs, i, kCGLPFAStereo);
321
322/* SET_ATTR_V(attribs, i, kCGLPFASampleBuffers, 1);
323 SET_ATTR_V(attribs, i, kCGLPFASamples, 0);
324 SET_ATTR_V(attribs, i, kCGLPFADisplayMask, 0); */
325 SET_ATTR(attribs, i, kCGLPFABackingStore);
326 SET_ATTR(attribs, i, kCGLPFAWindow);
327 SET_ATTR_V(attribs, i, kCGLPFADisplayMask, ctx->disp_mask);
328
329 SET_ATTR(attribs, i, 0);
330
331 *num = i;
332}
333
334#endif
335
336/**
337 * This creates a native GLX/WGL context.
338 */
339static GLboolean
340InstantiateNativeContext( WindowInfo *window, ContextInfo *context )
341{
342#ifdef WINDOWS
343 context->hglrc = stub.wsInterface.wglCreateContext( window->drawable );
344 return context->hglrc ? GL_TRUE : GL_FALSE;
345#elif defined(Darwin)
346 CGLContextObj shareCtx = NULL;
347 CGLPixelFormatObj pix;
348 long npix;
349
350 CGLPixelFormatAttribute attribs[16];
351 GLint ind = 0;
352
353 if( context->share ) {
354 if( context->cglc != context->share->cglc ) {
355 crWarning("CGLCreateContext() is trying to share a non-existant "
356 "CGL context. Setting share context to zero.");
357 shareCtx = 0;
358 }
359 else
360 shareCtx = context->cglc;
361 }
362
363 stubSetPFA( context, attribs, 16, &ind );
364
365 stub.wsInterface.CGLChoosePixelFormat( attribs, &pix, &npix );
366 stub.wsInterface.CGLCreateContext( pix, shareCtx, &context->cglc );
367 if( !context->cglc )
368 crError("InstantiateNativeContext: Couldn't Create the context!");
369
370 stub.wsInterface.CGLDestroyPixelFormat( pix );
371
372 if( context->parambits ) {
373 /* Set the delayed parameters */
374 if( context->parambits & VISBIT_SWAP_RECT )
375 stub.wsInterface.CGLSetParameter( context->cglc, kCGLCPSwapRectangle, context->swap_rect );
376
377 if( context->parambits & VISBIT_SWAP_INTERVAL )
378 stub.wsInterface.CGLSetParameter( context->cglc, kCGLCPSwapInterval, &(context->swap_interval) );
379
380 if( context->parambits & VISBIT_CLIENT_STORAGE )
381 stub.wsInterface.CGLSetParameter( context->cglc, kCGLCPClientStorage, (long*)&(context->client_storage) );
382
383 context->parambits = 0;
384 }
385
386 return context->cglc ? GL_TRUE : GL_FALSE;
387#elif defined(GLX)
388 GLXContext shareCtx = 0;
389
390 /* sort out context sharing here */
391 if (context->share) {
392 if (context->glxContext != context->share->glxContext) {
393 crWarning("glXCreateContext() is trying to share a non-existant "
394 "GLX context. Setting share context to zero.");
395 shareCtx = 0;
396 }
397 else {
398 shareCtx = context->glxContext;
399 }
400 }
401
402 context->glxContext = stub.wsInterface.glXCreateContext( window->dpy,
403 context->visual, shareCtx, context->direct );
404
405 return context->glxContext ? GL_TRUE : GL_FALSE;
406#endif
407}
408
409
410/**
411 * Utility functions to get window size and titlebar text.
412 */
413#ifdef WINDOWS
414
415void
416stubGetWindowGeometry( const WindowInfo *window, int *x, int *y,
417 unsigned int *w, unsigned int *h )
418{
419 RECT rect;
420 HWND hwnd;
421
422 if (!window->drawable) {
423 *w = *h = 0;
424 return;
425 }
426
427 hwnd = WindowFromDC( window->drawable );
428
429 if (!hwnd) {
430 *w = 0;
431 *h = 0;
432 }
433 else {
434 GetClientRect( hwnd, &rect );
435 *w = rect.right - rect.left;
436 *h = rect.bottom - rect.top;
437 ClientToScreen( hwnd, (LPPOINT) &rect );
438 *x = rect.left;
439 *y = rect.top;
440 }
441}
442
443static void
444GetWindowTitle( const WindowInfo *window, char *title )
445{
446 HWND hwnd;
447 /* XXX - we don't handle recurseUp */
448 hwnd = WindowFromDC( window->drawable );
449 if (hwnd)
450 GetWindowText(hwnd, title, 100);
451 else
452 title[0] = 0;
453}
454
455static void
456GetCursorPosition( const WindowInfo *window, int pos[2] )
457{
458 RECT rect;
459 POINT point;
460 GLint size[2], x, y;
461 unsigned int NativeHeight, NativeWidth, ChromiumHeight, ChromiumWidth;
462 float WidthRatio, HeightRatio;
463 static int DebugFlag = 0;
464
465 // apparently the "window" parameter passed to this
466 // function contains the native window information
467 HWND NATIVEhwnd = WindowFromDC( window->drawable );
468
469 // get the native window's height and width
470 stubGetWindowGeometry(window, &x, &y, &NativeWidth, &NativeHeight);
471
472 // get the spu window's height and width
473 stub.spu->dispatch_table.GetChromiumParametervCR(GL_WINDOW_SIZE_CR, window->spuWindow, GL_INT, 2, size);
474 ChromiumWidth = size[0];
475 ChromiumHeight = size[1];
476
477 // get the ratio of the size of the native window to the cr window
478 WidthRatio = (float)ChromiumWidth / (float)NativeWidth;
479 HeightRatio = (float)ChromiumHeight / (float)NativeHeight;
480
481 // output some debug information at the beginning
482 if(DebugFlag)
483 {
484 DebugFlag = 0;
485 crDebug("Native Window Handle = %d", NATIVEhwnd);
486 crDebug("Native Width = %i", NativeWidth);
487 crDebug("Native Height = %i", NativeHeight);
488 crDebug("Chromium Width = %i", ChromiumWidth);
489 crDebug("Chromium Height = %i", ChromiumHeight);
490 }
491
492 if (NATIVEhwnd)
493 {
494 GetClientRect( NATIVEhwnd, &rect );
495 GetCursorPos (&point);
496
497 // make sure these coordinates are relative to the native window,
498 // not the whole desktop
499 ScreenToClient(NATIVEhwnd, &point);
500
501 // calculate the new position of the virtual cursor
502 pos[0] = (int)(point.x * WidthRatio);
503 pos[1] = (int)((NativeHeight - point.y) * HeightRatio);
504 }
505 else
506 {
507 pos[0] = 0;
508 pos[1] = 0;
509 }
510}
511
512#elif defined(Darwin)
513
514extern OSStatus CGSGetScreenRectForWindow( CGSConnectionID cid, CGSWindowID wid, float *outRect );
515extern OSStatus CGSGetWindowBounds( CGSConnectionID cid, CGSWindowID wid, float *bounds );
516
517void
518stubGetWindowGeometry( const WindowInfo *window, int *x, int *y, unsigned int *w, unsigned int *h )
519{
520 float rect[4];
521
522 if( !window ||
523 !window->connection ||
524 !window->drawable ||
525 CGSGetWindowBounds( window->connection, window->drawable, rect ) != noErr )
526 {
527 *x = *y = 0;
528 *w = *h = 0;
529 } else {
530 *x = (int) rect[0];
531 *y = (int) rect[1];
532 *w = (int) rect[2];
533 *h = (int) rect[3];
534 }
535}
536
537
538static void
539GetWindowTitle( const WindowInfo *window, char *title )
540{
541 /* XXX \todo Darwin window Title */
542 title[0] = '\0';
543}
544
545
546static void
547GetCursorPosition( const WindowInfo *window, int pos[2] )
548{
549 Point mouse_pos;
550 float window_rect[4];
551
552 GetMouse( &mouse_pos );
553 CGSGetScreenRectForWindow( window->connection, window->drawable, window_rect );
554
555 pos[0] = mouse_pos.h - (int) window_rect[0];
556 pos[1] = (int) window_rect[3] - (mouse_pos.v - (int) window_rect[1]);
557
558 /*crDebug( "%i %i", pos[0], pos[1] );*/
559}
560
561#elif defined(GLX)
562
563void
564stubGetWindowGeometry( const WindowInfo *window, int *x, int *y,
565 unsigned int *w, unsigned int *h )
566{
567 Window root, child;
568 unsigned int border, depth;
569
570 //@todo: Performing those checks is expensive operation, especially for simple apps with high FPS.
571 // Disabling those tripples glxgears fps, thus using xevens instead of per frame polling is much more preffered.
572 //@todo: Check similiar on windows guests, though doubtfull as there're no XSync like calls on windows.
573 if (!window
574 || !window->dpy
575 || !window->drawable
576 || !XGetGeometry(window->dpy, window->drawable, &root,
577 x, y, w, h, &border, &depth)
578 || !XTranslateCoordinates(window->dpy, window->drawable, root,
579 0, 0, x, y, &child))
580 {
581 crWarning("Failed to get windows geometry for %x, try xwininfo", (int) window);
582 *x = *y = 0;
583 *w = *h = 0;
584 }
585}
586
587static char *
588GetWindowTitleHelper( Display *dpy, Window window, GLboolean recurseUp )
589{
590 while (1) {
591 char *name;
592 if (!XFetchName(dpy, window, &name))
593 return NULL;
594 if (name[0]) {
595 return name;
596 }
597 else if (recurseUp) {
598 /* This window has no name, try the parent */
599 Status stat;
600 Window root, parent, *children;
601 unsigned int numChildren;
602 stat = XQueryTree( dpy, window, &root, &parent,
603 &children, &numChildren );
604 if (!stat || window == root)
605 return NULL;
606 if (children)
607 XFree(children);
608 window = parent;
609 }
610 else {
611 XFree(name);
612 return NULL;
613 }
614 }
615}
616
617static void
618GetWindowTitle( const WindowInfo *window, char *title )
619{
620 char *t = GetWindowTitleHelper(window->dpy, window->drawable, GL_TRUE);
621 if (t) {
622 crStrcpy(title, t);
623 XFree(t);
624 }
625 else {
626 title[0] = 0;
627 }
628}
629
630
631/**
632 *Return current cursor position in local window coords.
633 */
634static void
635GetCursorPosition( const WindowInfo *window, int pos[2] )
636{
637 int rootX, rootY;
638 Window root, child;
639 unsigned int mask;
640 int x, y;
641 Bool q = XQueryPointer(window->dpy, window->drawable, &root, &child,
642 &rootX, &rootY, &pos[0], &pos[1], &mask);
643 if (q) {
644 unsigned int w, h;
645 stubGetWindowGeometry( window, &x, &y, &w, &h );
646 /* invert Y */
647 pos[1] = (int) h - pos[1] - 1;
648 }
649 else {
650 pos[0] = pos[1] = 0;
651 }
652}
653
654#endif
655
656
657/**
658 * This function is called by MakeCurrent() and determines whether or
659 * not a new rendering context should be bound to Chromium or the native
660 * OpenGL.
661 * \return GL_FALSE if native OpenGL should be used, or GL_TRUE if Chromium
662 * should be used.
663 */
664static GLboolean
665stubCheckUseChromium( WindowInfo *window )
666{
667 int x, y;
668 unsigned int w, h;
669
670 /* If the provided window is CHROMIUM, we're clearly intended
671 * to create a CHROMIUM context.
672 */
673 if (window->type == CHROMIUM)
674 return GL_TRUE;
675
676 if (stub.ignoreFreeglutMenus) {
677 const char *glutMenuTitle = "freeglut menu";
678 char title[1000];
679 GetWindowTitle(window, title);
680 if (crStrcmp(title, glutMenuTitle) == 0) {
681 crDebug("GL faker: Ignoring freeglut menu window");
682 return GL_FALSE;
683 }
684 }
685
686 /* If the user's specified a window count for Chromium, see if
687 * this window satisfies that criterium.
688 */
689 stub.matchChromiumWindowCounter++;
690 if (stub.matchChromiumWindowCount > 0) {
691 if (stub.matchChromiumWindowCounter != stub.matchChromiumWindowCount) {
692 crDebug("Using native GL, app window doesn't meet match_window_count");
693 return GL_FALSE;
694 }
695 }
696
697 /* If the user's specified a window list to ignore, see if this
698 * window satisfies that criterium.
699 */
700 if (stub.matchChromiumWindowID) {
701 GLuint i;
702
703 for (i = 0; i <= stub.numIgnoreWindowID; i++) {
704 if (stub.matchChromiumWindowID[i] == stub.matchChromiumWindowCounter) {
705 crDebug("Ignore window ID %d, using native GL", stub.matchChromiumWindowID[i]);
706 return GL_FALSE;
707 }
708 }
709 }
710
711 /* If the user's specified a minimum window size for Chromium, see if
712 * this window satisfies that criterium.
713 */
714 if (stub.minChromiumWindowWidth > 0 &&
715 stub.minChromiumWindowHeight > 0) {
716 stubGetWindowGeometry( window, &x, &y, &w, &h );
717 if (w >= stub.minChromiumWindowWidth &&
718 h >= stub.minChromiumWindowHeight) {
719
720 /* Check for maximum sized window now too */
721 if (stub.maxChromiumWindowWidth &&
722 stub.maxChromiumWindowHeight) {
723 if (w < stub.maxChromiumWindowWidth &&
724 h < stub.maxChromiumWindowHeight)
725 return GL_TRUE;
726 else
727 return GL_FALSE;
728 }
729
730 return GL_TRUE;
731 }
732 crDebug("Using native GL, app window doesn't meet minimum_window_size");
733 return GL_FALSE;
734 }
735 else if (stub.matchWindowTitle) {
736 /* If the user's specified a window title for Chromium, see if this
737 * window satisfies that criterium.
738 */
739 GLboolean wildcard = GL_FALSE;
740 char title[1000];
741 char *titlePattern;
742 int len;
743 /* check for leading '*' wildcard */
744 if (stub.matchWindowTitle[0] == '*') {
745 titlePattern = crStrdup( stub.matchWindowTitle + 1 );
746 wildcard = GL_TRUE;
747 }
748 else {
749 titlePattern = crStrdup( stub.matchWindowTitle );
750 }
751 /* check for trailing '*' wildcard */
752 len = crStrlen(titlePattern);
753 if (len > 0 && titlePattern[len - 1] == '*') {
754 titlePattern[len - 1] = '\0'; /* terminate here */
755 wildcard = GL_TRUE;
756 }
757
758 GetWindowTitle( window, title );
759 if (title[0]) {
760 if (wildcard) {
761 if (crStrstr(title, titlePattern)) {
762 crFree(titlePattern);
763 return GL_TRUE;
764 }
765 }
766 else if (crStrcmp(title, titlePattern) == 0) {
767 crFree(titlePattern);
768 return GL_TRUE;
769 }
770 }
771 crFree(titlePattern);
772 crDebug("Using native GL, app window title doesn't match match_window_title string (\"%s\" != \"%s\")", title, stub.matchWindowTitle);
773 return GL_FALSE;
774 }
775
776 /* Window title and size don't matter */
777 CRASSERT(stub.minChromiumWindowWidth == 0);
778 CRASSERT(stub.minChromiumWindowHeight == 0);
779 CRASSERT(stub.matchWindowTitle == NULL);
780
781 /* User hasn't specified a width/height or window title.
782 * We'll use chromium for this window (and context) if no other is.
783 */
784
785 return GL_TRUE; /* use Chromium! */
786}
787
788
789GLboolean
790stubMakeCurrent( WindowInfo *window, ContextInfo *context )
791{
792 GLboolean retVal;
793
794 /*
795 * Get WindowInfo and ContextInfo pointers.
796 */
797
798 if (!context || !window) {
799 if (stub.currentContext)
800 stub.currentContext->currentDrawable = NULL;
801 if (context)
802 context->currentDrawable = NULL;
803 stub.currentContext = NULL;
804 return GL_TRUE; /* OK */
805 }
806
807#ifdef CHROMIUM_THREADSAFE
808 stubCheckMultithread();
809#endif
810
811 if (context->type == UNDECIDED) {
812 /* Here's where we really create contexts */
813#ifdef CHROMIUM_THREADSAFE
814 crLockMutex(&stub.mutex);
815#endif
816
817 if (stubCheckUseChromium(window)) {
818 /*
819 * Create a Chromium context.
820 */
821#if defined(GLX) || defined(DARWIN)
822 GLint spuShareCtx = context->share ? context->share->spuContext : 0;
823#else
824 GLint spuShareCtx = 0;
825#endif
826
827 CRASSERT(stub.spu);
828 CRASSERT(stub.spu->dispatch_table.CreateContext);
829 context->type = CHROMIUM;
830
831 context->spuContext
832 = stub.spu->dispatch_table.CreateContext( context->dpyName,
833 context->visBits,
834 spuShareCtx );
835 if (window->spuWindow == -1)
836 {
837 window->spuWindow = stub.spu->dispatch_table.WindowCreate( window->dpyName, context->visBits );
838 CRASSERT(!context->pOwnWindow);
839 context->pOwnWindow = window;
840 }
841 }
842 else {
843 /*
844 * Create a native OpenGL context.
845 */
846 if (!InstantiateNativeContext(window, context))
847 {
848#ifdef CHROMIUM_THREADSAFE
849 crUnlockMutex(&stub.mutex);
850#endif
851 return 0; /* false */
852 }
853 context->type = NATIVE;
854 }
855
856#ifdef CHROMIUM_THREADSAFE
857 crUnlockMutex(&stub.mutex);
858#endif
859 }
860
861
862 if (context->type == NATIVE) {
863 /*
864 * Native OpenGL MakeCurrent().
865 */
866#ifdef WINDOWS
867 retVal = (GLboolean) stub.wsInterface.wglMakeCurrent( window->drawable, context->hglrc );
868#elif defined(Darwin)
869 // XXX \todo We need to differentiate between these two..
870 retVal = ( stub.wsInterface.CGLSetSurface(context->cglc, window->connection, window->drawable, window->surface) == noErr );
871 retVal = ( stub.wsInterface.CGLSetCurrentContext(context->cglc) == noErr );
872#elif defined(GLX)
873 retVal = (GLboolean) stub.wsInterface.glXMakeCurrent( window->dpy, window->drawable, context->glxContext );
874#endif
875 }
876 else {
877 /*
878 * SPU chain MakeCurrent().
879 */
880 CRASSERT(context->type == CHROMIUM);
881 CRASSERT(context->spuContext >= 0);
882
883 if (context->currentDrawable && context->currentDrawable != window)
884 crWarning("Rebinding context %p to a different window", context);
885
886 if (window->type == NATIVE) {
887 crWarning("Can't rebind a chromium context to a native window\n");
888 retVal = 0;
889 }
890 else {
891 if (window->spuWindow == -1)
892 {
893 window->spuWindow = stub.spu->dispatch_table.WindowCreate( window->dpyName, context->visBits );
894 CRASSERT(!context->pOwnWindow);
895 context->pOwnWindow = window;
896 }
897
898 if (window->spuWindow != (GLint)window->drawable)
899 stub.spu->dispatch_table.MakeCurrent( window->spuWindow, (GLint) window->drawable, context->spuContext );
900 else
901 stub.spu->dispatch_table.MakeCurrent( window->spuWindow, 0, /* native window handle */ context->spuContext );
902
903 retVal = 1;
904 }
905 }
906
907 window->type = context->type;
908 context->currentDrawable = window;
909 stub.currentContext = context;
910
911 if (retVal) {
912 /* Now, if we've transitions from Chromium to native rendering, or
913 * vice versa, we have to change all the OpenGL entrypoint pointers.
914 */
915 if (context->type == NATIVE) {
916 /* Switch to native API */
917 /*printf(" Switching to native API\n");*/
918 stubSetDispatch(&stub.nativeDispatch);
919 }
920 else if (context->type == CHROMIUM) {
921 /* Switch to stub (SPU) API */
922 /*printf(" Switching to spu API\n");*/
923 stubSetDispatch(&stub.spuDispatch);
924 }
925 else {
926 /* no API switch needed */
927 }
928 }
929
930 if (!window->width && window->type == CHROMIUM) {
931 /* One time window setup */
932 int x, y;
933 unsigned int winW, winH;
934
935 stubGetWindowGeometry( window, &x, &y, &winW, &winH );
936
937 /* If we're not using GLX/WGL (no app window) we'll always get
938 * a width and height of zero here. In that case, skip the viewport
939 * call since we're probably using a tilesort SPU with fake_window_dims
940 * which the tilesort SPU will use for the viewport.
941 */
942 window->width = winW;
943 window->height = winH;
944 if (stub.trackWindowSize)
945 stub.spuDispatch.WindowSize( window->spuWindow, winW, winH );
946 if (winW > 0 && winH > 0)
947 stub.spu->dispatch_table.Viewport( 0, 0, winW, winH );
948 }
949
950 /* Update window mapping state.
951 * Basically, this lets us hide render SPU windows which correspond
952 * to unmapped application windows. Without this, perfly (for example)
953 * opens *lots* of temporary windows which otherwise clutter the screen.
954 */
955 if (stub.trackWindowVisibility && window->type == CHROMIUM && window->drawable) {
956 const int mapped = stubIsWindowVisible(window);
957 if (mapped != window->mapped) {
958 crDebug("Dispatched: WindowShow(%i, %i)", window->spuWindow, mapped);
959 stub.spu->dispatch_table.WindowShow(window->spuWindow, mapped);
960 window->mapped = mapped;
961 }
962 }
963
964 return retVal;
965}
966
967
968
969void
970stubDestroyContext( unsigned long contextId )
971{
972 ContextInfo *context;
973
974 if (!stub.contextTable) {
975 return;
976 }
977 context = (ContextInfo *) crHashtableSearch(stub.contextTable, contextId);
978
979 CRASSERT(context);
980
981 if (context->type == NATIVE) {
982#ifdef WINDOWS
983 stub.wsInterface.wglDeleteContext( context->hglrc );
984#elif defined(Darwin)
985 stub.wsInterface.CGLDestroyContext( context->cglc );
986#elif defined(GLX)
987 stub.wsInterface.glXDestroyContext( context->dpy, context->glxContext );
988#endif
989 }
990 else if (context->type == CHROMIUM) {
991 /* Have pack SPU or tilesort SPU, etc. destroy the context */
992 CRASSERT(context->spuContext >= 0);
993 stub.spu->dispatch_table.DestroyContext( context->spuContext );
994 if (context->pOwnWindow)
995 {
996 /* Note: can't use WindowFromDC(context->pOwnWindow->drawable) here
997 because GL context is already released from DC and actual guest window
998 could be destroyed.
999 */
1000#ifdef WINDOWS
1001 crWindowDestroy((GLint)context->pOwnWindow->hWnd);
1002#else
1003 crWindowDestroy((GLint)context->pOwnWindow->drawable);
1004#endif
1005 }
1006 }
1007
1008 if (stub.currentContext == context) {
1009 stub.currentContext = NULL;
1010 }
1011
1012#ifdef GLX
1013 crFreeHashtable(context->pGLXPixmapsHash, crFree);
1014 if (context->damageDpy)
1015 {
1016 XCloseDisplay(context->damageDpy);
1017 }
1018#endif
1019
1020 crMemZero(context, sizeof(ContextInfo)); /* just to be safe */
1021 crHashtableDelete(stub.contextTable, contextId, crFree);
1022}
1023
1024
1025void
1026stubSwapBuffers( const WindowInfo *window, GLint flags )
1027{
1028 if (!window)
1029 return;
1030
1031 /* Determine if this window is being rendered natively or through
1032 * Chromium.
1033 */
1034
1035 if (window->type == NATIVE) {
1036 /*printf("*** Swapping native window %d\n", (int) drawable);*/
1037#ifdef WINDOWS
1038 (void) stub.wsInterface.wglSwapBuffers( window->drawable );
1039#elif defined(Darwin)
1040 /* ...is this ok? */
1041/* stub.wsInterface.CGLFlushDrawable( context->cglc ); */
1042 crDebug("stubSwapBuffers: unable to swap (no context!)");
1043#elif defined(GLX)
1044 stub.wsInterface.glXSwapBuffers( window->dpy, window->drawable );
1045#endif
1046 }
1047 else if (window->type == CHROMIUM) {
1048 /* Let the SPU do the buffer swap */
1049 /*printf("*** Swapping chromium window %d\n", (int) drawable);*/
1050 if (stub.appDrawCursor) {
1051 int pos[2];
1052 GetCursorPosition(window, pos);
1053 stub.spu->dispatch_table.ChromiumParametervCR(GL_CURSOR_POSITION_CR, GL_INT, 2, pos);
1054 }
1055 stub.spu->dispatch_table.SwapBuffers( window->spuWindow, flags );
1056 }
1057 else {
1058 crDebug("Calling SwapBuffers on a window we haven't seen before (no-op).");
1059 }
1060}
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