VirtualBox

source: vbox/trunk/src/VBox/Additions/common/crOpenGL/glx.c@ 32420

Last change on this file since 32420 was 32420, checked in by vboxsync, 14 years ago

crOpenGL: some mutter/meego related fixes

  • Property svn:eol-style set to native
File size: 75.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/* opengl_stub/glx.c */
8#include "chromium.h"
9#include "cr_error.h"
10#include "cr_spu.h"
11#include "cr_mem.h"
12#include "cr_string.h"
13#include "stub.h"
14#include "dri_glx.h"
15
16#include <X11/Xregion.h>
17
18//#define VBOX_NO_NATIVEGL
19
20/* Force full pixmap update if there're more damaged regions than this number*/
21#define CR_MAX_DAMAGE_REGIONS_TRACKED 50
22
23/* Force "bigger" update (full or clip) if it's reducing number of regions updated
24 * but doesn't increase updated area more than given number
25 */
26#define CR_MIN_DAMAGE_PROFIT_SIZE 64*64
27
28/*@todo combine it in some other place*/
29/* Size of pack spu buffer - some delta for commands packing, see pack/packspu_config.c*/
30
31/** Ramshankar: Solaris compiz fix */
32#ifdef RT_OS_SOLARIS
33# define CR_MAX_TRANSFER_SIZE 20*1024*1024
34#else
35# define CR_MAX_TRANSFER_SIZE 4*1024*1024
36#endif
37
38/** For optimizing glXMakeCurrent */
39static Display *currentDisplay = NULL;
40static GLXDrawable currentDrawable = 0;
41static GLXDrawable currentReadDrawable = 0;
42
43/**
44 * Keep a list of structures which associates X visual IDs with
45 * Chromium visual bitmasks.
46 */
47struct VisualInfo {
48 Display *dpy;
49 int screen;
50 VisualID visualid;
51 int visBits;
52 struct VisualInfo *next;
53};
54
55static struct VisualInfo *VisualInfoList = NULL;
56
57static void stubXshmUpdateImageRect(Display *dpy, GLXDrawable draw, GLX_Pixmap_t *pGlxPixmap, XRectangle *pRect);
58
59static void
60AddVisualInfo(Display *dpy, int screen, VisualID visualid, int visBits)
61{
62 struct VisualInfo *v;
63 for (v = VisualInfoList; v; v = v->next) {
64 if (v->dpy == dpy && v->screen == screen && v->visualid == visualid) {
65 v->visBits |= visBits;
66 return;
67 }
68 }
69 v = (struct VisualInfo *) crAlloc(sizeof(struct VisualInfo));
70 v->dpy = dpy;
71 v->screen = screen;
72 v->visualid = visualid;
73 v->visBits = visBits;
74 v->next = VisualInfoList;
75 VisualInfoList = v;
76}
77
78static struct VisualInfo *
79FindVisualInfo(Display *dpy, int screen, VisualID visualid)
80{
81 struct VisualInfo *v;
82 for (v = VisualInfoList; v; v = v->next) {
83 if (v->dpy == dpy && v->screen == screen && v->visualid == visualid)
84 return v;
85 }
86 return NULL;
87}
88
89/**
90 * Return string for a GLX error code
91 */
92static const char *glx_error_string(int err)
93{
94 static const char *glxErrors[] = {
95 "none",
96 "GLX_BAD_SCREEN",
97 "GLX_BAD_ATTRIBUTE",
98 "GLX_NO_EXTENSION",
99 "GLX_BAD_VISUAL",
100 "GLX_BAD_CONTEXT",
101 "GLX_BAD_VALUE",
102 "GLX_BAD_ENUM"
103 };
104 if (err > 0 && err < 8) {
105 return glxErrors[err];
106 }
107 else {
108 static char tmp[100];
109 sprintf(tmp, "0x%x", err);
110 return tmp;
111 }
112}
113
114/* Given an XVisualInfo structure, try to figure out what its
115 * OpenGL capabilities are, if we have a native OpenGL.
116 * Returns 0 if no information is available.
117 */
118static struct {
119 int gl_attrib;
120 char *attrib_name;
121 enum {TEST_TRUE, TEST_GREATER_0} test;
122 int match_vis_bits;
123} attrib_map[] = {
124 {GLX_RGBA, "GLX_RGBA", TEST_TRUE, CR_RGB_BIT},
125 {GLX_DOUBLEBUFFER, "GLX_DOUBLEBUFFER", TEST_TRUE, CR_DOUBLE_BIT},
126 {GLX_STEREO, "GLX_STEREO", TEST_TRUE, CR_STEREO_BIT},
127 {GLX_LEVEL, "GLX_LEVEL", TEST_GREATER_0, CR_OVERLAY_BIT},
128 {GLX_ALPHA_SIZE, "GLX_ALPHA_SIZE", TEST_GREATER_0, CR_ALPHA_BIT},
129 {GLX_DEPTH_SIZE, "GLX_DEPTH_SIZE", TEST_GREATER_0, CR_DEPTH_BIT},
130 {GLX_STENCIL_SIZE, "GLX_STENCIL_SIZE", TEST_GREATER_0, CR_STENCIL_BIT},
131 {GLX_ACCUM_RED_SIZE, "GLX_ACCUM_RED_SIZE", TEST_GREATER_0, CR_ACCUM_BIT},
132 {GLX_SAMPLE_BUFFERS_SGIS, "GLX_SAMPLE_BUFFERS_SGIS", TEST_GREATER_0, CR_MULTISAMPLE_BIT},
133};
134#ifndef VBOX_NO_NATIVEGL /* Currently not used */
135static int QueryVisBits(Display *dpy, XVisualInfo *vis)
136{
137 int visBits = 0;
138 int foo, bar, return_val, value;
139 unsigned int i;
140
141 /* We can only query the OpenGL capabilities if we actually
142 * have a native OpenGL underneath us. Without it, we can't
143 * get at all the actual OpenGL characteristics.
144 */
145 if (!stub.haveNativeOpenGL) return 0;
146
147 if (!stub.wsInterface.glXQueryExtension(dpy, &foo, &bar)) return 0;
148
149 /* If we don't have the GLX_USE_GL attribute, we've failed. */
150 return_val = stub.wsInterface.glXGetConfig(dpy, vis, GLX_USE_GL, &value);
151 if (return_val) {
152 crDebug("native glXGetConfig returned %d (%s) at %s line %d",
153 return_val, glx_error_string(return_val), __FILE__, __LINE__);
154 return 0;
155 }
156 if (value == 0) {
157 crDebug("visual ID 0x%x doesn't support OpenGL at %s line %d",
158 (int) vis->visual->visualid, __FILE__, __LINE__);
159 return 0;
160 }
161
162 for (i = 0; i < sizeof(attrib_map)/sizeof(attrib_map[0]); i++) {
163 return_val = stub.wsInterface.glXGetConfig(dpy, vis, attrib_map[i].gl_attrib, &value);
164 if (return_val) {
165 crDebug("native glXGetConfig(%s) returned %d (%s) at %s line %d",
166 attrib_map[i].attrib_name, return_val, glx_error_string(return_val), __FILE__, __LINE__);
167 return 0;
168 }
169
170 switch(attrib_map[i].test) {
171 case TEST_TRUE:
172 if (value)
173 visBits |= attrib_map[i].match_vis_bits;
174 break;
175
176 case TEST_GREATER_0:
177 if (value > 0)
178 visBits |= attrib_map[i].match_vis_bits;
179 break;
180
181 default:
182 crWarning("illegal attribute map test for %s at %s line %d",
183 attrib_map[i].attrib_name, __FILE__, __LINE__);
184 return 0;
185 }
186 }
187
188 return visBits;
189}
190#endif /* not 0 */
191
192
193
194#ifndef VBOX_NO_NATIVEGL /* Old code */
195DECLEXPORT(XVisualInfo *)
196VBOXGLXTAG(glXChooseVisual)( Display *dpy, int screen, int *attribList )
197{
198 XVisualInfo *vis;
199 int *attrib;
200 int visBits = 0;
201
202 stubInit();
203
204 for (attrib = attribList; *attrib != None; attrib++)
205 {
206 switch (*attrib)
207 {
208 case GLX_USE_GL:
209 /* ignored, this is mandatory */
210 break;
211
212 case GLX_BUFFER_SIZE:
213 /* this is for color-index visuals, which we don't support */
214 attrib++;
215 break;
216
217 case GLX_LEVEL:
218 if (attrib[1] > 0)
219 visBits |= CR_OVERLAY_BIT;
220 attrib++;
221 break;
222
223 case GLX_RGBA:
224 visBits |= CR_RGB_BIT;
225 break;
226
227 case GLX_DOUBLEBUFFER:
228 visBits |= CR_DOUBLE_BIT;
229 break;
230
231 case GLX_STEREO:
232 visBits |= CR_STEREO_BIT;
233 /*
234 crWarning( "glXChooseVisual: stereo unsupported" );
235 return NULL;
236 */
237 break;
238
239 case GLX_AUX_BUFFERS:
240 {
241 int aux_buffers = attrib[1];
242 if (aux_buffers != 0)
243 {
244 crWarning("glXChooseVisual: aux_buffers=%d unsupported",
245 aux_buffers);
246 return NULL;
247 }
248 }
249 attrib++;
250 break;
251
252 case GLX_RED_SIZE:
253 case GLX_GREEN_SIZE:
254 case GLX_BLUE_SIZE:
255 if (attrib[1] > 0)
256 visBits |= CR_RGB_BIT;
257 attrib++;
258 break;
259
260 case GLX_ALPHA_SIZE:
261 if (attrib[1] > 0)
262 visBits |= CR_ALPHA_BIT;
263 attrib++;
264 break;
265
266 case GLX_DEPTH_SIZE:
267 if (attrib[1] > 0)
268 visBits |= CR_DEPTH_BIT;
269 attrib++;
270 break;
271
272 case GLX_STENCIL_SIZE:
273 if (attrib[1] > 0)
274 visBits |= CR_STENCIL_BIT;
275 attrib++;
276 break;
277
278 case GLX_ACCUM_RED_SIZE:
279 case GLX_ACCUM_GREEN_SIZE:
280 case GLX_ACCUM_BLUE_SIZE:
281 case GLX_ACCUM_ALPHA_SIZE:
282 if (attrib[1] > 0)
283 visBits |= CR_ACCUM_BIT;
284 attrib++;
285 break;
286
287 case GLX_SAMPLE_BUFFERS_SGIS: /* aka GLX_SAMPLES_ARB */
288 if (attrib[1] > 0)
289 visBits |= CR_MULTISAMPLE_BIT;
290 attrib++;
291 break;
292 case GLX_SAMPLES_SGIS: /* aka GLX_SAMPLES_ARB */
293 /* just ignore value for now, we'll try to get 4 samples/pixel */
294 if (attrib[1] > 4)
295 return NULL;
296 visBits |= CR_MULTISAMPLE_BIT;
297 attrib++;
298 break;
299
300#ifdef GLX_VERSION_1_3
301 case GLX_X_VISUAL_TYPE:
302 case GLX_TRANSPARENT_TYPE_EXT:
303 case GLX_TRANSPARENT_INDEX_VALUE_EXT:
304 case GLX_TRANSPARENT_RED_VALUE_EXT:
305 case GLX_TRANSPARENT_GREEN_VALUE_EXT:
306 case GLX_TRANSPARENT_BLUE_VALUE_EXT:
307 case GLX_TRANSPARENT_ALPHA_VALUE_EXT:
308 /* ignore */
309 crWarning("glXChooseVisual: ignoring attribute 0x%x", *attrib);
310 attrib++;
311 break;
312#endif
313
314 default:
315 crWarning( "glXChooseVisual: bad attrib=0x%x", *attrib );
316 return NULL;
317 }
318 }
319
320 if ((visBits & CR_RGB_BIT) == 0 && (visBits & CR_OVERLAY_BIT) == 0)
321 {
322 /* normal layer, color index mode not supported */
323 crWarning( "glXChooseVisual: didn't request RGB visual?" );
324 return NULL;
325 }
326
327 vis = crChooseVisual(&stub.wsInterface, dpy, screen, GL_FALSE, visBits);
328 if (!vis && (visBits & CR_STEREO_BIT)) {
329 /* try non-stereo */
330 visBits &= ~CR_STEREO_BIT;
331 vis = crChooseVisual(&stub.wsInterface, dpy, screen, GL_FALSE, visBits);
332 }
333
334 if (vis) {
335 AddVisualInfo(dpy, screen, vis->visual->visualid, visBits);
336 }
337 return vis;
338}
339#else /* not 0 */
340DECLEXPORT(XVisualInfo *)
341VBOXGLXTAG(glXChooseVisual)( Display *dpy, int screen, int *attribList )
342{
343 bool useRGBA = false;
344 int *attrib;
345 XVisualInfo searchvis, *pret;
346 int nvisuals;
347 stubInit();
348
349 for (attrib = attribList; *attrib != None; attrib++)
350 {
351 switch (*attrib)
352 {
353 case GLX_USE_GL:
354 /* ignored, this is mandatory */
355 break;
356
357 case GLX_BUFFER_SIZE:
358 /* this is for color-index visuals, which we don't support */
359 attrib++;
360 break;
361
362 case GLX_LEVEL:
363 if (attrib[1] != 0)
364 goto err_exit;
365 attrib++;
366 break;
367
368 case GLX_RGBA:
369 useRGBA = true;
370 break;
371
372 case GLX_STEREO:
373 goto err_exit;
374 /*
375 crWarning( "glXChooseVisual: stereo unsupported" );
376 return NULL;
377 */
378 break;
379
380 case GLX_AUX_BUFFERS:
381 if (attrib[1] != 0)
382 goto err_exit;
383 attrib++;
384 break;
385
386 case GLX_RED_SIZE:
387 case GLX_GREEN_SIZE:
388 case GLX_BLUE_SIZE:
389 if (attrib[1] > 8)
390 goto err_exit;
391 attrib++;
392 break;
393
394 case GLX_ALPHA_SIZE:
395 if (attrib[1] > 8)
396 goto err_exit;
397 attrib++;
398 break;
399
400 case GLX_DEPTH_SIZE:
401 if (attrib[1] > 16)
402 goto err_exit;
403 attrib++;
404 break;
405
406 case GLX_STENCIL_SIZE:
407 if (attrib[1] > 8)
408 goto err_exit;
409 attrib++;
410 break;
411
412 case GLX_ACCUM_RED_SIZE:
413 case GLX_ACCUM_GREEN_SIZE:
414 case GLX_ACCUM_BLUE_SIZE:
415 case GLX_ACCUM_ALPHA_SIZE:
416 if (attrib[1] > 16)
417 goto err_exit;
418 attrib++;
419 break;
420
421 case GLX_SAMPLE_BUFFERS_SGIS: /* aka GLX_SAMPLES_ARB */
422 if (attrib[1] > 0)
423 goto err_exit;
424 attrib++;
425 break;
426 case GLX_SAMPLES_SGIS: /* aka GLX_SAMPLES_ARB */
427 if (attrib[1] > 0)
428 goto err_exit;
429 attrib++;
430 break;
431
432 case GLX_DOUBLEBUFFER: /* @todo, check if we support it */
433 break;
434
435#ifdef GLX_VERSION_1_3
436 case GLX_X_VISUAL_TYPE:
437 case GLX_TRANSPARENT_TYPE_EXT:
438 case GLX_TRANSPARENT_INDEX_VALUE_EXT:
439 case GLX_TRANSPARENT_RED_VALUE_EXT:
440 case GLX_TRANSPARENT_GREEN_VALUE_EXT:
441 case GLX_TRANSPARENT_BLUE_VALUE_EXT:
442 case GLX_TRANSPARENT_ALPHA_VALUE_EXT:
443 /* ignore */
444 crWarning("glXChooseVisual: ignoring attribute 0x%x", *attrib);
445 attrib++;
446 break;
447#endif
448
449 default:
450 crWarning( "glXChooseVisual: bad attrib=0x%x, ignoring", *attrib );
451 attrib++;
452 //return NULL;
453 }
454 }
455
456 if (!useRGBA)
457 return NULL;
458
459 XLOCK(dpy);
460 searchvis.visualid = XVisualIDFromVisual(DefaultVisual(dpy, screen));
461 pret = XGetVisualInfo(dpy, VisualIDMask, &searchvis, &nvisuals);
462 XUNLOCK(dpy);
463
464 if (nvisuals!=1) crWarning("glXChooseVisual: XGetVisualInfo returned %i visuals for %x", nvisuals, (unsigned int) searchvis.visualid);
465 if (pret)
466 crDebug("glXChooseVisual returned %x depth=%i", (unsigned int)pret->visualid, pret->depth);
467 return pret;
468
469err_exit:
470 crDebug("glXChooseVisual returning NULL, due to attrib=0x%x, next=0x%x", attrib[0], attrib[1]);
471 return NULL;
472}
473#endif
474
475/**
476 ** There is a problem with glXCopyContext.
477 ** IRIX and Mesa both define glXCopyContext
478 ** to have the mask argument being a
479 ** GLuint. XFree 4 and oss.sgi.com
480 ** define it to be an unsigned long.
481 ** Solution: We don't support
482 ** glXCopyContext anyway so we'll just
483 ** #ifdef out the code.
484 */
485DECLEXPORT(void)
486VBOXGLXTAG(glXCopyContext)( Display *dpy, GLXContext src, GLXContext dst,
487#if defined(AIX) || defined(PLAYSTATION2)
488GLuint mask )
489#elif defined(SunOS)
490unsigned long mask )
491#else
492unsigned long mask )
493#endif
494{
495 (void) dpy;
496 (void) src;
497 (void) dst;
498 (void) mask;
499 crWarning( "Unsupported GLX Call: glXCopyContext()" );
500}
501
502
503/**
504 * Get the display string for the given display pointer.
505 * Never return just ":0.0". In that case, prefix with our host name.
506 */
507static void
508stubGetDisplayString( Display *dpy, char *nameResult, int maxResult )
509{
510 const char *dpyName = DisplayString(dpy);
511 char host[1000];
512#ifndef VBOX_NO_NATIVEGL
513 if (dpyName[0] == ':')
514 {
515 crGetHostname(host, 1000);
516 }
517 else
518#endif
519 {
520 host[0] = 0;
521 }
522 if (crStrlen(host) + crStrlen(dpyName) >= maxResult - 1)
523 {
524 /* return null string */
525 crWarning("Very long host / display name string in stubDisplayString!");
526 nameResult[0] = 0;
527 }
528 else
529 {
530 /* return host concatenated with dpyName */
531 crStrcpy(nameResult, host);
532 crStrcat(nameResult, dpyName);
533 }
534}
535
536
537
538DECLEXPORT(GLXContext)
539VBOXGLXTAG(glXCreateContext)(Display *dpy, XVisualInfo *vis, GLXContext share, Bool direct)
540{
541 char dpyName[MAX_DPY_NAME];
542 ContextInfo *context;
543 int visBits = CR_RGB_BIT | CR_DOUBLE_BIT | CR_DEPTH_BIT; /* default vis */
544 int i, numExt;
545
546 stubInit();
547
548 CRASSERT(stub.contextTable);
549
550 /*
551 {
552 char **list;
553
554 list = XListExtensions(dpy, &numExt);
555 crDebug("X extensions [%i]:", numExt);
556 for (i=0; i<numExt; ++i)
557 {
558 crDebug("%s", list[i]);
559 }
560 XFreeExtensionList(list);
561 }
562 */
563
564 stubGetDisplayString(dpy, dpyName, MAX_DPY_NAME);
565#ifndef VBOX_NO_NATIVEGL /* We only care about the host capabilities, not the guest. */
566 if (stub.haveNativeOpenGL) {
567 int foo, bar;
568 if (stub.wsInterface.glXQueryExtension(dpy, &foo, &bar)) {
569 /* If we have real GLX, compute the Chromium visual bitmask now.
570 * otherwise, we'll use the default desiredVisual bitmask.
571 */
572 struct VisualInfo *v = FindVisualInfo(dpy, DefaultScreen(dpy),
573 vis->visual->visualid);
574 if (v) {
575 visBits = v->visBits;
576 /*crDebug("%s visBits=0x%x", __FUNCTION__, visBits);*/
577 }
578 else {
579 /* For some reason, we haven't tested this visual
580 * before. This could be because the visual was found
581 * through a different display connection to the same
582 * display (as happens in GeoProbe), or through a
583 * connection to an external daemon that queries
584 * visuals. If we can query it directly, we can still
585 * find the proper visBits.
586 */
587 int newVisBits = QueryVisBits(dpy, vis);
588 if (newVisBits > 0) {
589 AddVisualInfo(dpy, DefaultScreen(dpy), vis->visual->visualid, newVisBits);
590 crDebug("Application used unexpected but queryable visual id 0x%x", (int) vis->visual->visualid);
591 visBits = newVisBits;
592 }
593 else {
594 crWarning("Application used unexpected and unqueryable visual id 0x%x; using default visbits", (int) vis->visual->visualid);
595 }
596 }
597
598 /*crDebug("ComputeVisBits(0x%x) = 0x%x", (int)vis->visual->visualid, visBits);*/
599 if (stub.force_pbuffers) {
600 crDebug("App faker: Forcing use of Pbuffers");
601 visBits |= CR_PBUFFER_BIT;
602 }
603
604 if (!v) {
605 AddVisualInfo(dpy, DefaultScreen(dpy),
606 vis->visual->visualid, visBits);
607 }
608
609 }
610 }
611 else {
612 crDebug("No native OpenGL; cannot compute visbits");
613 }
614#endif
615
616 context = stubNewContext(dpyName, visBits, UNDECIDED, (unsigned long) share);
617 if (!context)
618 return 0;
619
620 context->dpy = dpy;
621 context->visual = vis;
622 context->direct = direct;
623
624 return (GLXContext) context->id;
625}
626
627
628DECLEXPORT(void) VBOXGLXTAG(glXDestroyContext)( Display *dpy, GLXContext ctx )
629{
630 (void) dpy;
631 stubDestroyContext( (unsigned long) ctx );
632}
633
634
635DECLEXPORT(Bool) VBOXGLXTAG(glXMakeCurrent)( Display *dpy, GLXDrawable drawable, GLXContext ctx )
636{
637 ContextInfo *context;
638 WindowInfo *window;
639 Bool retVal;
640
641 /*crDebug("glXMakeCurrent(%p, 0x%x, 0x%x)", (void *) dpy, (int) drawable, (int) ctx);*/
642
643 if (ctx && drawable) {
644 context = (ContextInfo *) crHashtableSearch(stub.contextTable, (unsigned long) ctx);
645 window = stubGetWindowInfo(dpy, drawable);
646
647 if (context && context->type == UNDECIDED) {
648 XLOCK(dpy);
649 XSync(dpy, 0); /* sync to force window creation on the server */
650 XUNLOCK(dpy);
651 }
652 }
653 else {
654 dpy = NULL;
655 window = NULL;
656 context = NULL;
657 }
658
659 currentDisplay = dpy;
660 currentDrawable = drawable;
661
662 retVal = stubMakeCurrent(window, context);
663 return retVal;
664}
665
666
667DECLEXPORT(GLXPixmap) VBOXGLXTAG(glXCreateGLXPixmap)( Display *dpy, XVisualInfo *vis, Pixmap pixmap )
668{
669 (void) dpy;
670 (void) vis;
671 (void) pixmap;
672
673 stubInit();
674 crWarning( "Unsupported GLX Call: glXCreateGLXPixmap()" );
675 return (GLXPixmap) 0;
676}
677
678DECLEXPORT(void) VBOXGLXTAG(glXDestroyGLXPixmap)( Display *dpy, GLXPixmap pix )
679{
680 VBOXGLXTAG(glXDestroyPixmap)(dpy, pix);
681}
682
683#ifndef VBOX_NO_NATIVEGL /* old code */
684DECLEXPORT(int) VBOXGLXTAG(glXGetConfig)( Display *dpy, XVisualInfo *vis, int attrib, int *value )
685{
686 struct VisualInfo *v;
687 int visBits;
688
689 if (!vis) {
690 /* SGI OpenGL Performer hits this */
691 crWarning("glXGetConfig called with NULL XVisualInfo");
692 return GLX_BAD_VISUAL;
693 }
694
695 v = FindVisualInfo(dpy, DefaultScreen(dpy), vis->visual->visualid);
696 if (v) {
697 visBits = v->visBits;
698 }
699 else {
700 visBits = 0;
701 }
702
703 stubInit();
704
705 /* try to satisfy this request with the native glXGetConfig() */
706 if (stub.haveNativeOpenGL)
707 {
708 int foo, bar;
709 int return_val;
710
711 if (stub.wsInterface.glXQueryExtension(dpy, &foo, &bar))
712 {
713 return_val = stub.wsInterface.glXGetConfig( dpy, vis, attrib, value );
714 if (return_val)
715 {
716 crDebug("faker native glXGetConfig returned %s",
717 glx_error_string(return_val));
718 }
719 return return_val;
720 }
721 }
722
723 /*
724 * If the GLX application chooses its visual via a bunch of calls to
725 * glXGetConfig, instead of by calling glXChooseVisual, we need to keep
726 * track of which attributes are queried to help satisfy context creation
727 * later.
728 */
729 switch ( attrib ) {
730
731 case GLX_USE_GL:
732 *value = 1;
733 break;
734
735 case GLX_BUFFER_SIZE:
736 *value = 32;
737 break;
738
739 case GLX_LEVEL:
740 visBits |= CR_OVERLAY_BIT;
741 *value = (visBits & CR_OVERLAY_BIT) ? 1 : 0;
742 break;
743
744 case GLX_RGBA:
745 visBits |= CR_RGB_BIT;
746 *value = 1;
747 break;
748
749 case GLX_DOUBLEBUFFER:
750 *value = 1;
751 break;
752
753 case GLX_STEREO:
754 *value = 1;
755 break;
756
757 case GLX_AUX_BUFFERS:
758 *value = 0;
759 break;
760
761 case GLX_RED_SIZE:
762 *value = 8;
763 break;
764
765 case GLX_GREEN_SIZE:
766 *value = 8;
767 break;
768
769 case GLX_BLUE_SIZE:
770 *value = 8;
771 break;
772
773 case GLX_ALPHA_SIZE:
774 visBits |= CR_ALPHA_BIT;
775 *value = (visBits & CR_ALPHA_BIT) ? 8 : 0;
776 break;
777
778 case GLX_DEPTH_SIZE:
779 visBits |= CR_DEPTH_BIT;
780 *value = 16;
781 break;
782
783 case GLX_STENCIL_SIZE:
784 visBits |= CR_STENCIL_BIT;
785 *value = 8;
786 break;
787
788 case GLX_ACCUM_RED_SIZE:
789 visBits |= CR_ACCUM_BIT;
790 *value = 16;
791 break;
792
793 case GLX_ACCUM_GREEN_SIZE:
794 visBits |= CR_ACCUM_BIT;
795 *value = 16;
796 break;
797
798 case GLX_ACCUM_BLUE_SIZE:
799 visBits |= CR_ACCUM_BIT;
800 *value = 16;
801 break;
802
803 case GLX_ACCUM_ALPHA_SIZE:
804 visBits |= CR_ACCUM_BIT;
805 *value = 16;
806 break;
807
808 case GLX_SAMPLE_BUFFERS_SGIS:
809 visBits |= CR_MULTISAMPLE_BIT;
810 *value = 0; /* fix someday */
811 break;
812
813 case GLX_SAMPLES_SGIS:
814 visBits |= CR_MULTISAMPLE_BIT;
815 *value = 0; /* fix someday */
816 break;
817
818 case GLX_VISUAL_CAVEAT_EXT:
819 *value = GLX_NONE_EXT;
820 break;
821#if defined(SunOS)
822 /*
823 I don't think this is even a valid attribute for glxGetConfig.
824 No idea why this gets called under SunOS but we simply ignore it
825 -- jw
826 */
827 case GLX_X_VISUAL_TYPE:
828 crWarning ("Ignoring Unsuported GLX Call: glxGetConfig with attrib 0x%x", attrib);
829 break;
830#endif
831
832 case GLX_TRANSPARENT_TYPE:
833 *value = GLX_NONE_EXT;
834 break;
835 case GLX_TRANSPARENT_INDEX_VALUE:
836 *value = 0;
837 break;
838 case GLX_TRANSPARENT_RED_VALUE:
839 *value = 0;
840 break;
841 case GLX_TRANSPARENT_GREEN_VALUE:
842 *value = 0;
843 break;
844 case GLX_TRANSPARENT_BLUE_VALUE:
845 *value = 0;
846 break;
847 case GLX_TRANSPARENT_ALPHA_VALUE:
848 *value = 0;
849 break;
850 default:
851 crWarning( "Unsupported GLX Call: glXGetConfig with attrib 0x%x", attrib );
852 return GLX_BAD_ATTRIBUTE;
853 }
854
855 AddVisualInfo(dpy, DefaultScreen(dpy), vis->visual->visualid, visBits);
856
857 return 0;
858}
859#else /* not 0 */
860DECLEXPORT(int) VBOXGLXTAG(glXGetConfig)( Display *dpy, XVisualInfo *vis, int attrib, int *value )
861{
862 if (!vis) {
863 /* SGI OpenGL Performer hits this */
864 crWarning("glXGetConfig called with NULL XVisualInfo");
865 return GLX_BAD_VISUAL;
866 }
867
868 stubInit();
869
870 *value = 0; /* For sanity */
871
872 switch ( attrib ) {
873
874 case GLX_USE_GL:
875 *value = 1;
876 break;
877
878 case GLX_BUFFER_SIZE:
879 *value = 32;
880 break;
881
882 case GLX_LEVEL:
883 *value = 0; /* for now */
884 break;
885
886 case GLX_RGBA:
887 *value = 1;
888 break;
889
890 case GLX_DOUBLEBUFFER:
891 *value = 1;
892 break;
893
894 case GLX_STEREO:
895 *value = 1;
896 break;
897
898 case GLX_AUX_BUFFERS:
899 *value = 0;
900 break;
901
902 case GLX_RED_SIZE:
903 *value = 8;
904 break;
905
906 case GLX_GREEN_SIZE:
907 *value = 8;
908 break;
909
910 case GLX_BLUE_SIZE:
911 *value = 8;
912 break;
913
914 case GLX_ALPHA_SIZE:
915 *value = 8;
916 break;
917
918 case GLX_DEPTH_SIZE:
919 *value = 16;
920 break;
921
922 case GLX_STENCIL_SIZE:
923 *value = 8;
924 break;
925
926 case GLX_ACCUM_RED_SIZE:
927 *value = 16;
928 break;
929
930 case GLX_ACCUM_GREEN_SIZE:
931 *value = 16;
932 break;
933
934 case GLX_ACCUM_BLUE_SIZE:
935 *value = 16;
936 break;
937
938 case GLX_ACCUM_ALPHA_SIZE:
939 *value = 16;
940 break;
941
942 case GLX_SAMPLE_BUFFERS_SGIS:
943 *value = 0; /* fix someday */
944 break;
945
946 case GLX_SAMPLES_SGIS:
947 *value = 0; /* fix someday */
948 break;
949
950 case GLX_VISUAL_CAVEAT_EXT:
951 *value = GLX_NONE_EXT;
952 break;
953#if defined(SunOS) || 1
954 /*
955 I don't think this is even a valid attribute for glxGetConfig.
956 No idea why this gets called under SunOS but we simply ignore it
957 -- jw
958 */
959 case GLX_X_VISUAL_TYPE:
960 crWarning ("Ignoring Unsuported GLX Call: glxGetConfig with attrib 0x%x", attrib);
961 break;
962#endif
963
964 case GLX_TRANSPARENT_TYPE:
965 *value = GLX_NONE_EXT;
966 break;
967 case GLX_TRANSPARENT_INDEX_VALUE:
968 *value = 0;
969 break;
970 case GLX_TRANSPARENT_RED_VALUE:
971 *value = 0;
972 break;
973 case GLX_TRANSPARENT_GREEN_VALUE:
974 *value = 0;
975 break;
976 case GLX_TRANSPARENT_BLUE_VALUE:
977 *value = 0;
978 break;
979 case GLX_TRANSPARENT_ALPHA_VALUE:
980 *value = 0;
981 break;
982 default:
983 crWarning( "Unsupported GLX Call: glXGetConfig with attrib 0x%x, ignoring...", attrib );
984 //return GLX_BAD_ATTRIBUTE;
985 *value = 0;
986 }
987
988 return 0;
989}
990#endif
991
992DECLEXPORT(GLXContext) VBOXGLXTAG(glXGetCurrentContext)( void )
993{
994 if (stub.currentContext)
995 return (GLXContext) stub.currentContext->id;
996 else
997 return (GLXContext) NULL;
998}
999
1000DECLEXPORT(GLXDrawable) VBOXGLXTAG(glXGetCurrentDrawable)(void)
1001{
1002 return currentDrawable;
1003}
1004
1005DECLEXPORT(Display *) VBOXGLXTAG(glXGetCurrentDisplay)(void)
1006{
1007 return currentDisplay;
1008}
1009
1010DECLEXPORT(Bool) VBOXGLXTAG(glXIsDirect)(Display *dpy, GLXContext ctx)
1011{
1012 (void) dpy;
1013 (void) ctx;
1014 crDebug("->glXIsDirect");
1015 return True;
1016}
1017
1018DECLEXPORT(Bool) VBOXGLXTAG(glXQueryExtension)(Display *dpy, int *errorBase, int *eventBase)
1019{
1020 (void) dpy;
1021 (void) errorBase;
1022 (void) eventBase;
1023 return 1; /* You BET we do... */
1024}
1025
1026DECLEXPORT(Bool) VBOXGLXTAG(glXQueryVersion)( Display *dpy, int *major, int *minor )
1027{
1028 (void) dpy;
1029 *major = 1;
1030 *minor = 3;
1031 return 1;
1032}
1033
1034static XErrorHandler oldErrorHandler;
1035static unsigned char lastXError = Success;
1036
1037static int
1038errorHandler (Display *dpy, XErrorEvent *e)
1039{
1040 lastXError = e->error_code;
1041 return 0;
1042}
1043
1044DECLEXPORT(void) VBOXGLXTAG(glXSwapBuffers)( Display *dpy, GLXDrawable drawable )
1045{
1046 WindowInfo *window = stubGetWindowInfo(dpy, drawable);
1047 stubSwapBuffers( window, 0 );
1048
1049#ifdef VBOX_TEST_MEGOO
1050 if (!stub.bXExtensionsChecked)
1051 {
1052 stubCheckXExtensions(window);
1053 }
1054
1055 if (!stub.bHaveXComposite)
1056 {
1057 return;
1058 }
1059
1060 {
1061 Pixmap p;
1062 XWindowAttributes attr;
1063
1064 XLOCK(dpy);
1065 XGetWindowAttributes(dpy, window->drawable, &attr);
1066 if (attr.override_redirect)
1067 {
1068 XUNLOCK(dpy);
1069 return;
1070 }
1071
1072 crLockMutex(&stub.mutex);
1073
1074 XSync(dpy, false);
1075 oldErrorHandler = XSetErrorHandler(errorHandler);
1076 /*@todo this creates new pixmap for window every call*/
1077 /*p = XCompositeNameWindowPixmap(dpy, window->drawable);*/
1078 XSync(dpy, false);
1079 XSetErrorHandler(oldErrorHandler);
1080 XUNLOCK(dpy);
1081
1082 if (lastXError==Success)
1083 {
1084 char *data, *imgdata;
1085 GC gc;
1086 XImage *image;
1087 XVisualInfo searchvis, *pret;
1088 int nvisuals;
1089 XGCValues gcValues;
1090 int i, rowsize;
1091
1092 XLOCK(dpy);
1093
1094 searchvis.visualid = attr.visual->visualid;
1095 pret = XGetVisualInfo(dpy, VisualIDMask, &searchvis, &nvisuals);
1096 if (nvisuals!=1) crWarning("XGetVisualInfo returned %i visuals for %x", nvisuals, (unsigned int) searchvis.visualid);
1097 CRASSERT(pret);
1098
1099 gc = XCreateGC(dpy, window->drawable, 0, &gcValues);
1100 if (!gc) crWarning("Failed to create gc!");
1101
1102 data = crCalloc(window->width * window->height * 4);
1103 imgdata = crCalloc(window->width * window->height * 4);
1104 CRASSERT(data && imgdata);
1105 stub.spu->dispatch_table.ReadPixels(0, 0, window->width, window->height, GL_RGBA, GL_UNSIGNED_BYTE, data);
1106 /*y-invert image*/
1107 rowsize = 4*window->width;
1108 for (i=0; i<window->height; ++i)
1109 {
1110 crMemcpy(imgdata+rowsize*i, data+rowsize*(window->height-i-1), rowsize);
1111 }
1112 crFree(data);
1113
1114 XSync(dpy, false);
1115 image = XCreateImage(dpy, attr.visual, pret->depth, ZPixmap, 0, imgdata, window->width, window->height, 32, 0);
1116 XPutImage(dpy, window->drawable, gc, image, 0, 0, 0, 0, window->width, window->height);
1117
1118 XFree(pret);
1119 /*XFreePixmap(dpy, p);*/
1120 XFreeGC(dpy, gc);
1121 XDestroyImage(image);
1122 XUNLOCK(dpy);
1123 }
1124 lastXError=Success;
1125 crUnlockMutex(&stub.mutex);
1126 }
1127#endif
1128}
1129
1130#ifndef VBOX_NO_NATIVEGL
1131DECLEXPORT(void) VBOXGLXTAG(glXUseXFont)( Font font, int first, int count, int listBase )
1132{
1133 if (stub.currentContext->type == CHROMIUM)
1134 {
1135 Display *dpy = stub.wsInterface.glXGetCurrentDisplay();
1136 if (dpy) {
1137 stubUseXFont( dpy, font, first, count, listBase );
1138 }
1139 else {
1140 dpy = XOpenDisplay(NULL);
1141 if (!dpy)
1142 return;
1143 stubUseXFont( dpy, font, first, count, listBase );
1144 XCloseDisplay(dpy);
1145 }
1146 } else
1147 stub.wsInterface.glXUseXFont( font, first, count, listBase );
1148}
1149#else /* not 0 */
1150DECLEXPORT(void) VBOXGLXTAG(glXUseXFont)( Font font, int first, int count, int listBase )
1151{
1152 Display *dpy = stub.currentContext->dpy;
1153 if (dpy) {
1154 stubUseXFont( dpy, font, first, count, listBase );
1155 }
1156 else {
1157 dpy = XOpenDisplay(NULL);
1158 if (!dpy)
1159 return;
1160 stubUseXFont( dpy, font, first, count, listBase );
1161 XCloseDisplay(dpy);
1162 }
1163}
1164#endif
1165
1166DECLEXPORT(void) VBOXGLXTAG(glXWaitGL)( void )
1167{
1168 static int first_call = 1;
1169
1170 if ( first_call )
1171 {
1172 crDebug( "Ignoring unsupported GLX call: glXWaitGL()" );
1173 first_call = 0;
1174 }
1175}
1176
1177DECLEXPORT(void) VBOXGLXTAG(glXWaitX)( void )
1178{
1179 static int first_call = 1;
1180
1181 if ( first_call )
1182 {
1183 crDebug( "Ignoring unsupported GLX call: glXWaitX()" );
1184 first_call = 0;
1185 }
1186}
1187
1188DECLEXPORT(const char *) VBOXGLXTAG(glXQueryExtensionsString)( Display *dpy, int screen )
1189{
1190 /* XXX maybe also advertise GLX_SGIS_multisample? */
1191
1192 static const char *retval = "GLX_ARB_multisample GLX_EXT_texture_from_pixmap GLX_SGIX_fbconfig GLX_ARB_get_proc_address";
1193
1194 (void) dpy;
1195 (void) screen;
1196
1197 crDebug("->glXQueryExtensionsString");
1198 return retval;
1199}
1200
1201DECLEXPORT(const char *) VBOXGLXTAG(glXGetClientString)( Display *dpy, int name )
1202{
1203 const char *retval;
1204 (void) dpy;
1205 (void) name;
1206
1207 switch ( name ) {
1208
1209 case GLX_VENDOR:
1210 retval = "Chromium";
1211 break;
1212
1213 case GLX_VERSION:
1214 retval = "1.2 Chromium";
1215 break;
1216
1217 case GLX_EXTENSIONS:
1218 /*@todo should be a screen not a name...but it's not used anyway*/
1219 retval = glXQueryExtensionsString(dpy, name);
1220 break;
1221
1222 default:
1223 retval = NULL;
1224 }
1225
1226 return retval;
1227}
1228
1229DECLEXPORT(const char *) VBOXGLXTAG(glXQueryServerString)( Display *dpy, int screen, int name )
1230{
1231 const char *retval;
1232 (void) dpy;
1233 (void) screen;
1234
1235 switch ( name ) {
1236
1237 case GLX_VENDOR:
1238 retval = "Chromium";
1239 break;
1240
1241 case GLX_VERSION:
1242 retval = "1.2 Chromium";
1243 break;
1244
1245 case GLX_EXTENSIONS:
1246 retval = glXQueryExtensionsString(dpy, screen);
1247 break;
1248
1249 default:
1250 retval = NULL;
1251 }
1252
1253 return retval;
1254}
1255
1256DECLEXPORT(CR_GLXFuncPtr) VBOXGLXTAG(glXGetProcAddressARB)( const GLubyte *name )
1257{
1258 return (CR_GLXFuncPtr) crGetProcAddress( (const char *) name );
1259}
1260
1261DECLEXPORT(CR_GLXFuncPtr) VBOXGLXTAG(glXGetProcAddress)( const GLubyte *name )
1262{
1263 return (CR_GLXFuncPtr) crGetProcAddress( (const char *) name );
1264}
1265
1266
1267#if GLX_EXTRAS
1268
1269DECLEXPORT(GLXPbufferSGIX)
1270VBOXGLXTAG(glXCreateGLXPbufferSGIX)(Display *dpy, GLXFBConfigSGIX config,
1271 unsigned int width, unsigned int height,
1272 int *attrib_list)
1273{
1274 (void) dpy;
1275 (void) config;
1276 (void) width;
1277 (void) height;
1278 (void) attrib_list;
1279 crWarning("glXCreateGLXPbufferSGIX not implemented by Chromium");
1280 return 0;
1281}
1282
1283DECLEXPORT(void) VBOXGLXTAG(glXDestroyGLXPbufferSGIX)(Display *dpy, GLXPbuffer pbuf)
1284{
1285 (void) dpy;
1286 (void) pbuf;
1287 crWarning("glXDestroyGLXPbufferSGIX not implemented by Chromium");
1288}
1289
1290DECLEXPORT(void) VBOXGLXTAG(glXSelectEventSGIX)(Display *dpy, GLXDrawable drawable, unsigned long mask)
1291{
1292 (void) dpy;
1293 (void) drawable;
1294 (void) mask;
1295}
1296
1297DECLEXPORT(void) VBOXGLXTAG(glXGetSelectedEventSGIX)(Display *dpy, GLXDrawable drawable, unsigned long *mask)
1298{
1299 (void) dpy;
1300 (void) drawable;
1301 (void) mask;
1302}
1303
1304DECLEXPORT(int) VBOXGLXTAG(glXQueryGLXPbufferSGIX)(Display *dpy, GLXPbuffer pbuf,
1305 int attribute, unsigned int *value)
1306{
1307 (void) dpy;
1308 (void) pbuf;
1309 (void) attribute;
1310 (void) value;
1311 crWarning("glXQueryGLXPbufferSGIX not implemented by Chromium");
1312 return 0;
1313}
1314
1315DECLEXPORT(int) VBOXGLXTAG(glXGetFBConfigAttribSGIX)(Display *dpy, GLXFBConfig config,
1316 int attribute, int *value)
1317{
1318 return VBOXGLXTAG(glXGetFBConfigAttrib)(dpy, config, attribute, value);
1319}
1320
1321DECLEXPORT(GLXFBConfigSGIX *)
1322VBOXGLXTAG(glXChooseFBConfigSGIX)(Display *dpy, int screen,
1323 int *attrib_list, int *nelements)
1324{
1325 (void) dpy;
1326 (void) screen;
1327 (void) attrib_list;
1328 (void) nelements;
1329 crWarning("glXChooseFBConfigSGIX not implemented by Chromium");
1330 return NULL;
1331}
1332
1333DECLEXPORT(GLXPixmap)
1334VBOXGLXTAG(glXCreateGLXPixmapWithConfigSGIX)(Display *dpy,
1335 GLXFBConfig config,
1336 Pixmap pixmap)
1337{
1338 (void) dpy;
1339 (void) config;
1340 (void) pixmap;
1341 crWarning("glXCreateGLXPixmapWithConfigSGIX not implemented by Chromium");
1342 return 0; }
1343
1344DECLEXPORT(GLXContext)
1345VBOXGLXTAG(glXCreateContextWithConfigSGIX)(Display *dpy, GLXFBConfig config,
1346 int render_type,
1347 GLXContext share_list,
1348 Bool direct)
1349{
1350 (void) dpy;
1351 (void) config;
1352 (void) render_type;
1353 (void) share_list;
1354 (void) direct;
1355 crWarning("glXCreateContextWithConfigSGIX not implemented by Chromium");
1356 return NULL;
1357}
1358
1359DECLEXPORT(XVisualInfo *)
1360VBOXGLXTAG(glXGetVisualFromFBConfigSGIX)(Display *dpy,
1361 GLXFBConfig config)
1362{
1363 (void) dpy;
1364 (void) config;
1365 crWarning("glXGetVisualFromFBConfigSGIX not implemented by Chromium");
1366 return NULL;
1367}
1368
1369DECLEXPORT(GLXFBConfigSGIX)
1370VBOXGLXTAG(glXGetFBConfigFromVisualSGIX)(Display *dpy, XVisualInfo *vis)
1371{
1372 (void) dpy;
1373 (void) vis;
1374 crWarning("glXGetFBConfigFromVisualSGIX not implemented by Chromium");
1375 return NULL;
1376}
1377
1378/*
1379 * GLX 1.3 functions
1380 */
1381DECLEXPORT(GLXFBConfig *)
1382VBOXGLXTAG(glXChooseFBConfig)(Display *dpy, int screen, ATTRIB_TYPE *attrib_list, int *nelements)
1383{
1384 (void) dpy;
1385 (void) screen;
1386 (void) attrib_list;
1387 (void) nelements;
1388 crWarning("glXChooseFBConfig not implemented by Chromium");
1389 return NULL;
1390}
1391
1392DECLEXPORT(GLXContext)
1393VBOXGLXTAG(glXCreateNewContext)(Display *dpy, GLXFBConfig config, int render_type, GLXContext share_list, Bool direct)
1394{
1395 XVisualInfo *vis;
1396
1397 (void) dpy;
1398 (void) config;
1399 (void) render_type;
1400 (void) share_list;
1401 (void) direct;
1402
1403 if (render_type != GLX_RGBA_TYPE)
1404 {
1405 crWarning("glXCreateNewContext, unsupported render_type %x", render_type);
1406 return NULL;
1407 }
1408
1409 vis = VBOXGLXTAG(glXGetVisualFromFBConfig)(dpy, config);
1410 return VBOXGLXTAG(glXCreateContext)(dpy, vis, share_list, direct);
1411}
1412
1413DECLEXPORT(GLXPbuffer)
1414VBOXGLXTAG(glXCreatePbuffer)(Display *dpy, GLXFBConfig config, ATTRIB_TYPE *attrib_list)
1415{
1416 (void) dpy;
1417 (void) config;
1418 (void) attrib_list;
1419 crWarning("glXCreatePbuffer not implemented by Chromium");
1420 return 0;
1421}
1422
1423/* Note: there're examples where glxpixmaps are created without current context, so can't do much of the work here.
1424 * Instead we'd do necessary initialization on first use of those pixmaps.
1425 */
1426DECLEXPORT(GLXPixmap)
1427VBOXGLXTAG(glXCreatePixmap)(Display *dpy, GLXFBConfig config, Pixmap pixmap, const ATTRIB_TYPE *attrib_list)
1428{
1429 ATTRIB_TYPE *attrib;
1430 XVisualInfo *pVis;
1431 GLX_Pixmap_t *pGlxPixmap;
1432 (void) dpy;
1433 (void) config;
1434
1435#if 0
1436 {
1437 int x, y;
1438 unsigned int w, h;
1439 unsigned int border;
1440 unsigned int depth;
1441 Window root;
1442
1443 crDebug("glXCreatePixmap called for %lu", pixmap);
1444
1445 XLOCK(dpy);
1446 if (!XGetGeometry(dpy, pixmap, &root, &x, &y, &w, &h, &border, &depth))
1447 {
1448 XSync(dpy, False);
1449 if (!XGetGeometry(dpy, pixmap, &root, &x, &y, &w, &h, &border, &depth))
1450 {
1451 crDebug("fail");
1452 }
1453 }
1454 crDebug("root: %lu, [%i,%i %u,%u]", root, x, y, w, h);
1455 XUNLOCK(dpy);
1456 }
1457#endif
1458
1459 pGlxPixmap = crCalloc(sizeof(GLX_Pixmap_t));
1460 if (!pGlxPixmap)
1461 {
1462 crWarning("glXCreatePixmap failed to allocate memory");
1463 return 0;
1464 }
1465
1466 pVis = VBOXGLXTAG(glXGetVisualFromFBConfig)(dpy, config);
1467 if (!pVis)
1468 {
1469 crWarning("Unknown config %p in glXCreatePixmap", config);
1470 return 0;
1471 }
1472
1473 pGlxPixmap->format = pVis->depth==24 ? GL_RGB:GL_RGBA;
1474 pGlxPixmap->target = GL_TEXTURE_2D;
1475
1476 if (attrib_list)
1477 {
1478 for (attrib = attrib_list; *attrib != None; attrib++)
1479 {
1480 switch (*attrib)
1481 {
1482 case GLX_TEXTURE_FORMAT_EXT:
1483 attrib++;
1484 switch (*attrib)
1485 {
1486 case GLX_TEXTURE_FORMAT_RGBA_EXT:
1487 pGlxPixmap->format = GL_RGBA;
1488 break;
1489 case GLX_TEXTURE_FORMAT_RGB_EXT:
1490 pGlxPixmap->format = GL_RGB;
1491 break;
1492 default:
1493 crDebug("Unexpected GLX_TEXTURE_FORMAT_EXT 0x%x", (unsigned int) *attrib);
1494 }
1495 break;
1496 case GLX_TEXTURE_TARGET_EXT:
1497 attrib++;
1498 switch (*attrib)
1499 {
1500 case GLX_TEXTURE_2D_EXT:
1501 pGlxPixmap->target = GL_TEXTURE_2D;
1502 break;
1503 case GLX_TEXTURE_RECTANGLE_EXT:
1504 pGlxPixmap->target = GL_TEXTURE_RECTANGLE_NV;
1505 break;
1506 default:
1507 crDebug("Unexpected GLX_TEXTURE_TARGET_EXT 0x%x", (unsigned int) *attrib);
1508 }
1509 break;
1510 default: attrib++;
1511 }
1512 }
1513 }
1514
1515 crHashtableAdd(stub.pGLXPixmapsHash, (unsigned int) pixmap, pGlxPixmap);
1516 return (GLXPixmap) pixmap;
1517}
1518
1519DECLEXPORT(GLXWindow)
1520VBOXGLXTAG(glXCreateWindow)(Display *dpy, GLXFBConfig config, Window win, ATTRIB_TYPE *attrib_list)
1521{
1522 GLXFBConfig *realcfg;
1523 int nconfigs;
1524 //XVisualInfo *vis;
1525 (void) dpy;
1526 (void) config;
1527 (void) win;
1528 (void) attrib_list;
1529 //crWarning("glXCreateWindow not implemented by Chromium");
1530 //vis = VBOXGLXTAG(glXGetVisualFromFBConfig)(config);
1531 if (stub.wsInterface.glXGetFBConfigs)
1532 {
1533 realcfg = stub.wsInterface.glXGetFBConfigs(dpy, 0, &nconfigs);
1534 if (!realcfg || nconfigs<1)
1535 {
1536 crWarning("glXCreateWindow !realcfg || nconfigs<1");
1537 return 0;
1538 }
1539 else
1540 {
1541 return stub.wsInterface.glXCreateWindow(dpy, realcfg[0], win, attrib_list);
1542 }
1543 }
1544 else
1545 {
1546 crWarning("glXCreateWindow stub.wsInterface.glXChooseFBConfig==NULL");
1547 return 0;
1548 }
1549}
1550
1551DECLEXPORT(void) VBOXGLXTAG(glXDestroyPbuffer)(Display *dpy, GLXPbuffer pbuf)
1552{
1553 (void) dpy;
1554 (void) pbuf;
1555 crWarning("glXDestroyPbuffer not implemented by Chromium");
1556}
1557
1558DECLEXPORT(void) VBOXGLXTAG(glXDestroyPixmap)(Display *dpy, GLXPixmap pixmap)
1559{
1560 GLX_Pixmap_t *pGlxPixmap;
1561
1562 if (!stub.currentContext)
1563 {
1564 crWarning("glXDestroyPixmap failed, no current context");
1565 return;
1566 }
1567
1568 pGlxPixmap = (GLX_Pixmap_t *) crHashtableSearch(stub.currentContext->pGLXPixmapsHash, (unsigned int) pixmap);
1569
1570 if (pGlxPixmap)
1571 {
1572 XLOCK(dpy);
1573 if (pGlxPixmap->gc)
1574 {
1575 XFreeGC(dpy, pGlxPixmap->gc);
1576 }
1577
1578 if (pGlxPixmap->hShmPixmap>0)
1579 {
1580 XFreePixmap(dpy, pGlxPixmap->hShmPixmap);
1581 }
1582 XUNLOCK(dpy);
1583
1584 if (pGlxPixmap->hDamage>0)
1585 {
1586 //crDebug("Destroy: Damage for drawable 0x%x, handle 0x%x", (unsigned int) pixmap, (unsigned int) pGlxPixmap->damage);
1587 XDamageDestroy(stub.currentContext->damageDpy, pGlxPixmap->hDamage);
1588 }
1589
1590 if (pGlxPixmap->pDamageRegion)
1591 {
1592 XDestroyRegion(pGlxPixmap->pDamageRegion);
1593 }
1594
1595 crHashtableDelete(stub.currentContext->pGLXPixmapsHash, (unsigned int) pixmap, crFree);
1596 }
1597 /*else
1598 {
1599 crWarning("glXDestroyPixmap called for unknown glxpixmap 0x%x", (unsigned int) pixmap);
1600 }*/
1601}
1602
1603DECLEXPORT(void) VBOXGLXTAG(glXDestroyWindow)(Display *dpy, GLXWindow win)
1604{
1605 (void) dpy;
1606 (void) win;
1607 crWarning("glXDestroyWindow not implemented by Chromium");
1608}
1609
1610DECLEXPORT(GLXDrawable) VBOXGLXTAG(glXGetCurrentReadDrawable)(void)
1611{
1612 //crWarning("glXGetCurrentReadDrawable not implemented by Chromium");
1613 return currentReadDrawable;
1614}
1615
1616DECLEXPORT(int) VBOXGLXTAG(glXGetFBConfigAttrib)(Display *dpy, GLXFBConfig config, int attribute, int *value)
1617{
1618 XVisualInfo * pVisual;
1619 const char * pExt;
1620
1621 pVisual = VBOXGLXTAG(glXGetVisualFromFBConfig)(dpy, config);
1622 if (!pVisual)
1623 {
1624 crWarning("glXGetFBConfigAttrib for %p, failed to get XVisualInfo", config);
1625 return GLX_BAD_ATTRIBUTE;
1626 }
1627 //crDebug("glXGetFBConfigAttrib 0x%x for 0x%x, visualid=0x%x, depth=%i", attribute, (int)config, (int)pVisual->visualid, pVisual->depth);
1628
1629
1630 switch (attribute)
1631 {
1632 case GLX_DRAWABLE_TYPE:
1633 *value = GLX_PIXMAP_BIT;
1634 break;
1635 case GLX_BIND_TO_TEXTURE_TARGETS_EXT:
1636 *value = GLX_TEXTURE_2D_BIT_EXT;
1637 pExt = (const char *) stub.spu->dispatch_table.GetString(GL_EXTENSIONS);
1638 if (crStrstr(pExt, "GL_NV_texture_rectangle")
1639 || crStrstr(pExt, "GL_ARB_texture_rectangle")
1640 || crStrstr(pExt, "GL_EXT_texture_rectangle"))
1641 {
1642 *value |= GLX_TEXTURE_RECTANGLE_BIT_EXT;
1643 }
1644 break;
1645 case GLX_BIND_TO_TEXTURE_RGBA_EXT:
1646 *value = pVisual->depth==32;
1647 break;
1648 case GLX_BIND_TO_TEXTURE_RGB_EXT:
1649 *value = True;
1650 break;
1651 case GLX_DOUBLEBUFFER:
1652 //crDebug("attribute=GLX_DOUBLEBUFFER");
1653 *value = True;
1654 break;
1655 case GLX_Y_INVERTED_EXT:
1656 *value = True;
1657 break;
1658 case GLX_ALPHA_SIZE:
1659 //crDebug("attribute=GLX_ALPHA_SIZE");
1660 *value = pVisual->depth==32 ? 8:0;
1661 break;
1662 case GLX_BUFFER_SIZE:
1663 //crDebug("attribute=GLX_BUFFER_SIZE");
1664 *value = pVisual->depth;
1665 break;
1666 case GLX_STENCIL_SIZE:
1667 //crDebug("attribute=GLX_STENCIL_SIZE");
1668 *value = 8;
1669 break;
1670 case GLX_DEPTH_SIZE:
1671 *value = 16;
1672 //crDebug("attribute=GLX_DEPTH_SIZE");
1673 break;
1674 case GLX_BIND_TO_MIPMAP_TEXTURE_EXT:
1675 *value = 0;
1676 break;
1677 case GLX_RENDER_TYPE:
1678 //crDebug("attribute=GLX_RENDER_TYPE");
1679 *value = GLX_RGBA_BIT;
1680 break;
1681 case GLX_CONFIG_CAVEAT:
1682 //crDebug("attribute=GLX_CONFIG_CAVEAT");
1683 *value = GLX_NONE;
1684 break;
1685 case GLX_VISUAL_ID:
1686 //crDebug("attribute=GLX_VISUAL_ID");
1687 *value = pVisual->visualid;
1688 break;
1689 case GLX_FBCONFIG_ID:
1690 *value = pVisual->visualid; /*or config, though those are the same at the moment but this could change one day?*/
1691 break;
1692 case GLX_RED_SIZE:
1693 case GLX_GREEN_SIZE:
1694 case GLX_BLUE_SIZE:
1695 *value = 8;
1696 break;
1697 case GLX_LEVEL:
1698 *value = 0;
1699 break;
1700 case GLX_STEREO:
1701 *value = false;
1702 break;
1703 case GLX_AUX_BUFFERS:
1704 *value = 0;
1705 break;
1706 case GLX_ACCUM_RED_SIZE:
1707 case GLX_ACCUM_GREEN_SIZE:
1708 case GLX_ACCUM_BLUE_SIZE:
1709 case GLX_ACCUM_ALPHA_SIZE:
1710 *value = 0;
1711 break;
1712 case GLX_X_VISUAL_TYPE:
1713 *value = GLX_TRUE_COLOR;
1714 break;
1715 case GLX_TRANSPARENT_TYPE:
1716 *value = GLX_NONE;
1717 break;
1718 case GLX_SAMPLE_BUFFERS:
1719 case GLX_SAMPLES:
1720 *value = 1;
1721 break;
1722 default:
1723 crDebug("glXGetFBConfigAttrib: unknown attribute=0x%x", attribute);
1724 XFree(pVisual);
1725 return GLX_BAD_ATTRIBUTE;
1726 }
1727
1728 XFree(pVisual);
1729 return Success;
1730}
1731
1732#if !defined(VBOX_NO_NATIVEGL) || 1 /* need fbconfigs atleast for depths 24 and 32 */
1733DECLEXPORT(GLXFBConfig *) VBOXGLXTAG(glXGetFBConfigs)(Display *dpy, int screen, int *nelements)
1734{
1735 GLXFBConfig *pGLXFBConfigs = NULL;
1736 struct VisualInfo *v;
1737 int i=0, cVisuals;
1738 XVisualInfo searchvis, *pVisuals;
1739
1740 *nelements = 0;
1741
1742 /*
1743 for (v = VisualInfoList; v; v = v->next) {
1744 if (v->dpy == dpy && v->screen == screen)
1745 ++*nelements;
1746 }
1747
1748 if (*nelements)
1749 pGLXFBConfigs = crAlloc(*nelements * sizeof(GLXFBConfig));
1750
1751 for (v = VisualInfoList; v && i<*nelements; v = v->next) {
1752 if (v->dpy == dpy && v->screen == screen)
1753 pGLXFBConfigs[i++] = (GLXFBConfig) v->visualid;
1754 }
1755 */
1756
1757 /*@todo doesn't really list all the common visuals, have to use some static list*/
1758 searchvis.screen = screen;
1759 XLOCK(dpy);
1760 pVisuals = XGetVisualInfo(dpy, VisualScreenMask, &searchvis, nelements);
1761 XUNLOCK(dpy);
1762
1763 if (*nelements)
1764 pGLXFBConfigs = crAlloc(*nelements * sizeof(GLXFBConfig));
1765
1766 for (i=0; i<*nelements; ++i)
1767 {
1768 pGLXFBConfigs[i] = (GLXFBConfig) pVisuals[i].visualid;
1769 }
1770
1771 XFree(pVisuals);
1772
1773 crDebug("glXGetFBConfigs returned %i configs", *nelements);
1774 for (i=0; i<*nelements; ++i)
1775 {
1776 crDebug("glXGetFBConfigs[%i]=%p", i, pGLXFBConfigs[i]);
1777 }
1778 return pGLXFBConfigs;
1779}
1780#else /* not 0 */
1781DECLEXPORT(GLXFBConfig *) VBOXGLXTAG(glXGetFBConfigs)(Display *dpy, int screen, int *nelements)
1782{
1783 int i;
1784
1785 GLXFBConfig *pGLXFBConfigs = crAlloc(sizeof(GLXFBConfig));
1786
1787 *nelements = 1;
1788 XLOCK(dpy);
1789 *pGLXFBConfigs = (GLXFBConfig) XVisualIDFromVisual(DefaultVisual(dpy, screen));
1790 XUNLOCK(dpy);
1791
1792 crDebug("glXGetFBConfigs returned %i configs", *nelements);
1793 for (i=0; i<*nelements; ++i)
1794 {
1795 crDebug("glXGetFBConfigs[%i]=0x%x", i, (unsigned int) pGLXFBConfigs[i]);
1796 }
1797 return pGLXFBConfigs;
1798}
1799#endif
1800
1801DECLEXPORT(void) VBOXGLXTAG(glXGetSelectedEvent)(Display *dpy, GLXDrawable draw, unsigned long *event_mask)
1802{
1803 (void) dpy;
1804 (void) draw;
1805 (void) event_mask;
1806 crWarning("glXGetSelectedEvent not implemented by Chromium");
1807}
1808
1809DECLEXPORT(XVisualInfo *) VBOXGLXTAG(glXGetVisualFromFBConfig)(Display *dpy, GLXFBConfig config)
1810{
1811 (void) dpy;
1812 (void) config;
1813
1814 struct VisualInfo *v;
1815
1816 /*
1817 for (v = VisualInfoList; v; v = v->next) {
1818 if (v->dpy == dpy && v->visualid == (VisualID)config)
1819 {
1820 XVisualInfo temp, *pret;
1821 int nret;
1822
1823 temp.visualid = v->visualid;
1824 pret = XGetVisualInfo(dpy, VisualIDMask, &temp, &nret);
1825
1826 if (nret!=1) crWarning("XGetVisualInfo returned %i visuals", nret);
1827 crDebug("glXGetVisualFromFBConfig(cfg/visid==0x%x): depth=%i", (int) config, pret->depth);
1828 return pret;
1829 }
1830 }
1831 */
1832
1833 {
1834 XVisualInfo temp, *pret;
1835 int nret;
1836
1837 temp.visualid = (VisualID)config;
1838 XLOCK(dpy);
1839 pret = XGetVisualInfo(dpy, VisualIDMask, &temp, &nret);
1840 XUNLOCK(dpy);
1841
1842 if (nret!=1) crWarning("XGetVisualInfo returned %i visuals for %p", nret, config);
1843 //crDebug("glXGetVisualFromFBConfig(cfg/visid==0x%x): depth=%i", (int) config, pret->depth);
1844 return pret;
1845 }
1846
1847 crDebug("glXGetVisualFromFBConfig unknown fbconfig %p", config);
1848 return NULL;
1849}
1850
1851DECLEXPORT(Bool) VBOXGLXTAG(glXMakeContextCurrent)(Display *display, GLXDrawable draw, GLXDrawable read, GLXContext ctx)
1852{
1853 (void) display;
1854 (void) draw;
1855 (void) read;
1856 (void) ctx;
1857 //crWarning("glXMakeContextCurrent not implemented by Chromium");
1858 currentReadDrawable = read;
1859 return VBOXGLXTAG(glXMakeCurrent)(display, draw, ctx);
1860}
1861
1862DECLEXPORT(int) VBOXGLXTAG(glXQueryContext)(Display *dpy, GLXContext ctx, int attribute, int *value)
1863{
1864 (void) dpy;
1865 (void) ctx;
1866 (void) attribute;
1867 (void) value;
1868 crWarning("glXQueryContext not implemented by Chromium");
1869 return 0;
1870}
1871
1872DECLEXPORT(void) VBOXGLXTAG(glXQueryDrawable)(Display *dpy, GLXDrawable draw, int attribute, unsigned int *value)
1873{
1874 (void) dpy;
1875 (void) draw;
1876 (void) attribute;
1877 (void) value;
1878 crWarning("glXQueryDrawable not implemented by Chromium");
1879}
1880
1881DECLEXPORT(void) VBOXGLXTAG(glXSelectEvent)(Display *dpy, GLXDrawable draw, unsigned long event_mask)
1882{
1883 (void) dpy;
1884 (void) draw;
1885 (void) event_mask;
1886 crWarning("glXSelectEvent not implemented by Chromium");
1887}
1888
1889#ifdef CR_EXT_texture_from_pixmap
1890/*typedef struct
1891{
1892 int x, y;
1893 unsigned int w, h, border, depth;
1894 Window root;
1895 void *data;
1896} pminfo;*/
1897
1898static void stubInitXSharedMemory(Display *dpy)
1899{
1900 int vma, vmi;
1901 Bool pixmaps;
1902
1903 if (stub.bShmInitFailed || stub.xshmSI.shmid>=0)
1904 return;
1905
1906 stub.bShmInitFailed = GL_TRUE;
1907
1908 /* Check for extension and pixmaps format */
1909 XLOCK(dpy);
1910 if (!XShmQueryExtension(dpy))
1911 {
1912 crWarning("No XSHM extension");
1913 XUNLOCK(dpy);
1914 return;
1915 }
1916
1917 if (!XShmQueryVersion(dpy, &vma, &vmi, &pixmaps) || !pixmaps)
1918 {
1919 crWarning("XSHM extension doesn't support pixmaps");
1920 XUNLOCK(dpy);
1921 return;
1922 }
1923
1924 if (XShmPixmapFormat(dpy)!=ZPixmap)
1925 {
1926 crWarning("XSHM extension doesn't support ZPixmap format");
1927 XUNLOCK(dpy);
1928 return;
1929 }
1930 XUNLOCK(dpy);
1931
1932 /* Alloc shared memory, so far using hardcoded value...could fail for bigger displays one day */
1933 stub.xshmSI.readOnly = false;
1934 stub.xshmSI.shmid = shmget(IPC_PRIVATE, 4*4096*2048, IPC_CREAT | 0600);
1935 if (stub.xshmSI.shmid<0)
1936 {
1937 crWarning("XSHM Failed to create shared segment");
1938 return;
1939 }
1940
1941 stub.xshmSI.shmaddr = (char*) shmat(stub.xshmSI.shmid, NULL, 0);
1942 if (stub.xshmSI.shmaddr==(void*)-1)
1943 {
1944 crWarning("XSHM Failed to attach shared segment");
1945 shmctl(stub.xshmSI.shmid, IPC_RMID, 0);
1946 return;
1947 }
1948
1949 XLOCK(dpy);
1950 if (!XShmAttach(dpy, &stub.xshmSI))
1951 {
1952 crWarning("XSHM Failed to attach shared segment to XServer");
1953 shmctl(stub.xshmSI.shmid, IPC_RMID, 0);
1954 shmdt(stub.xshmSI.shmaddr);
1955 XUNLOCK(dpy);
1956 return;
1957 }
1958 XUNLOCK(dpy);
1959
1960 stub.bShmInitFailed = GL_FALSE;
1961 crInfo("Using XSHM for GLX_EXT_texture_from_pixmap");
1962
1963 /*Anyway mark to be deleted when our process detaches it, in case of segfault etc*/
1964
1965/* Ramshankar: Solaris compiz fix */
1966#ifndef RT_OS_SOLARIS
1967 shmctl(stub.xshmSI.shmid, IPC_RMID, 0);
1968#endif
1969}
1970
1971static void stubInitXDamageExtension(ContextInfo *pContext)
1972{
1973 int erb, vma, vmi;
1974
1975 CRASSERT(pContext);
1976
1977 if (pContext->damageInitFailed || pContext->damageDpy)
1978 return;
1979
1980 pContext->damageInitFailed = True;
1981
1982 /* Open second xserver connection to make sure we'd recieve all the xdamage messages
1983 * and those wouldn't be eaten by application even queue */
1984 pContext->damageDpy = XOpenDisplay(DisplayString(pContext->dpy));
1985
1986 if (!pContext->damageDpy)
1987 {
1988 crWarning("XDamage: Can't connect to display %s", DisplayString(pContext->dpy));
1989 return;
1990 }
1991
1992 if (!XDamageQueryExtension(pContext->damageDpy, &pContext->damageEventsBase, &erb)
1993 || !XDamageQueryVersion(pContext->damageDpy, &vma, &vmi))
1994 {
1995 crWarning("XDamage not found or old version (%i.%i), going to run *very* slow", vma, vmi);
1996 XCloseDisplay(pContext->damageDpy);
1997 pContext->damageDpy = NULL;
1998 return;
1999 }
2000
2001 crDebug("XDamage %i.%i", vma, vmi);
2002 pContext->damageInitFailed = False;
2003}
2004
2005static void stubCheckXDamageCB(unsigned long key, void *data1, void *data2)
2006{
2007 GLX_Pixmap_t *pGlxPixmap = (GLX_Pixmap_t *) data1;
2008 XDamageNotifyEvent *e = (XDamageNotifyEvent *) data2;
2009
2010 if (pGlxPixmap->hDamage==e->damage)
2011 {
2012 /*crDebug("Event: Damage for pixmap 0x%lx(drawable 0x%x), handle 0x%x (level=%i) [%i,%i,%i,%i]",
2013 key, (unsigned int) e->drawable, (unsigned int) e->damage, (int) e->level,
2014 e->area.x, e->area.y, e->area.width, e->area.height);*/
2015
2016 if (pGlxPixmap->pDamageRegion)
2017 {
2018 /* If it's dirty and regions are empty, it marked for full update, so do nothing.*/
2019 if (!pGlxPixmap->bPixmapImageDirty || !XEmptyRegion(pGlxPixmap->pDamageRegion))
2020 {
2021 if (CR_MAX_DAMAGE_REGIONS_TRACKED <= pGlxPixmap->pDamageRegion->numRects)
2022 {
2023 /* Mark for full update */
2024 EMPTY_REGION(pGlxPixmap->pDamageRegion);
2025 }
2026 else
2027 {
2028 /* Add to damage regions */
2029 XUnionRectWithRegion(&e->area, pGlxPixmap->pDamageRegion, pGlxPixmap->pDamageRegion);
2030 }
2031 }
2032 }
2033
2034 pGlxPixmap->bPixmapImageDirty = True;
2035 }
2036}
2037
2038static GLX_Pixmap_t* stubInitGlxPixmap(GLX_Pixmap_t* pCreateInfoPixmap, Display *dpy, GLXDrawable draw, ContextInfo *pContext)
2039{
2040 int x, y;
2041 unsigned int w, h;
2042 unsigned int border;
2043 unsigned int depth;
2044 Window root;
2045 GLX_Pixmap_t *pGlxPixmap;
2046
2047 CRASSERT(pContext && pCreateInfoPixmap);
2048
2049 XLOCK(dpy);
2050 if (!XGetGeometry(dpy, (Pixmap)draw, &root, &x, &y, &w, &h, &border, &depth))
2051 {
2052 XSync(dpy, False);
2053 if (!XGetGeometry(dpy, (Pixmap)draw, &root, &x, &y, &w, &h, &border, &depth))
2054 {
2055 crWarning("stubInitGlxPixmap failed in call to XGetGeometry for 0x%x", (int) draw);
2056 XUNLOCK(dpy);
2057 return NULL;
2058 }
2059 }
2060
2061 pGlxPixmap = crAlloc(sizeof(GLX_Pixmap_t));
2062 if (!pGlxPixmap)
2063 {
2064 crWarning("stubInitGlxPixmap failed to allocate memory");
2065 XUNLOCK(dpy);
2066 return NULL;
2067 }
2068
2069 pGlxPixmap->x = x;
2070 pGlxPixmap->y = y;
2071 pGlxPixmap->w = w;
2072 pGlxPixmap->h = h;
2073 pGlxPixmap->border = border;
2074 pGlxPixmap->depth = depth;
2075 pGlxPixmap->root = root;
2076 pGlxPixmap->format = pCreateInfoPixmap->format;
2077 pGlxPixmap->target = pCreateInfoPixmap->target;
2078
2079 /* Try to allocate shared memory
2080 * As we're allocating huge chunk of memory, do it in this function, only if this extension is really used
2081 */
2082 if (!stub.bShmInitFailed && stub.xshmSI.shmid<0)
2083 {
2084 stubInitXSharedMemory(dpy);
2085 }
2086
2087 if (stub.xshmSI.shmid>=0)
2088 {
2089 XGCValues xgcv;
2090 xgcv.graphics_exposures = False;
2091 xgcv.subwindow_mode = IncludeInferiors;
2092 pGlxPixmap->gc = XCreateGC(dpy, (Pixmap)draw, GCGraphicsExposures|GCSubwindowMode, &xgcv);
2093
2094 pGlxPixmap->hShmPixmap = XShmCreatePixmap(dpy, pGlxPixmap->root, stub.xshmSI.shmaddr, &stub.xshmSI,
2095 pGlxPixmap->w, pGlxPixmap->h, pGlxPixmap->depth);
2096 }
2097 else
2098 {
2099 pGlxPixmap->gc = NULL;
2100 pGlxPixmap->hShmPixmap = 0;
2101 }
2102 XUNLOCK(dpy);
2103
2104 stubInitXDamageExtension(pContext);
2105
2106 /* If there's damage extension, then get handle for damage events related to this pixmap */
2107 if (pContext->damageDpy)
2108 {
2109 pGlxPixmap->hDamage = XDamageCreate(pContext->damageDpy, (Pixmap)draw, XDamageReportRawRectangles);
2110 /*crDebug("Create: Damage for drawable 0x%x, handle 0x%x (level=%i)",
2111 (unsigned int) draw, (unsigned int) pGlxPixmap->damage, (int) XDamageReportRawRectangles);*/
2112 pGlxPixmap->pDamageRegion = XCreateRegion();
2113 if (!pGlxPixmap->pDamageRegion)
2114 {
2115 crWarning("stubInitGlxPixmap failed to create empty damage region for drawable 0x%x", (unsigned int) draw);
2116 }
2117
2118 /*We have never seen this pixmap before, so mark it as dirty for first use*/
2119 pGlxPixmap->bPixmapImageDirty = True;
2120 }
2121 else
2122 {
2123 pGlxPixmap->hDamage = 0;
2124 pGlxPixmap->pDamageRegion = NULL;
2125 }
2126
2127 /* glTexSubImage2D generates GL_INVALID_OP if texture array hasn't been defined by a call to glTexImage2D first.
2128 * It's fine for small textures which would be updated in stubXshmUpdateWholeImage, but we'd never call glTexImage2D for big ones.
2129 * Note that we're making empty texture by passing NULL as pixels pointer, so there's no overhead transferring data to host.*/
2130 if (CR_MAX_TRANSFER_SIZE < 4*pGlxPixmap->w*pGlxPixmap->h)
2131 {
2132 stub.spu->dispatch_table.TexImage2D(pGlxPixmap->target, 0, pGlxPixmap->format, pGlxPixmap->w, pGlxPixmap->h, 0,
2133 GL_BGRA, GL_UNSIGNED_BYTE, NULL);
2134 }
2135
2136 crHashtableAdd(pContext->pGLXPixmapsHash, (unsigned int) draw, pGlxPixmap);
2137 crHashtableDelete(stub.pGLXPixmapsHash, (unsigned int) draw, crFree);
2138
2139 return pGlxPixmap;
2140}
2141
2142static void stubXshmUpdateWholeImage(Display *dpy, GLXDrawable draw, GLX_Pixmap_t *pGlxPixmap)
2143{
2144 /* To limit the size of transferring buffer, split bigger texture into regions
2145 * which fit into connection buffer. Could be done in hgcm or packspu but implementation in this place allows to avoid
2146 * unnecessary memcpy.
2147 * This also workarounds guest driver failures when sending 6+mb texture buffers on linux.
2148 */
2149 if (CR_MAX_TRANSFER_SIZE < 4*pGlxPixmap->w*pGlxPixmap->h)
2150 {
2151 XRectangle rect;
2152
2153 rect.x = pGlxPixmap->x;
2154 rect.y = pGlxPixmap->y;
2155 rect.width = pGlxPixmap->w;
2156 rect.height = CR_MAX_TRANSFER_SIZE/(4*pGlxPixmap->w);
2157
2158 /*crDebug("Texture size too big, splitting in lower sized chunks. [%i,%i,%i,%i] (%i)",
2159 pGlxPixmap->x, pGlxPixmap->y, pGlxPixmap->w, pGlxPixmap->h, rect.height);*/
2160
2161 for (; (rect.y+rect.height)<=(pGlxPixmap->y+pGlxPixmap->h); rect.y+=rect.height)
2162 {
2163 stubXshmUpdateImageRect(dpy, draw, pGlxPixmap, &rect);
2164 }
2165
2166 if (rect.y!=(pGlxPixmap->y+pGlxPixmap->h))
2167 {
2168 rect.height=pGlxPixmap->h-rect.y;
2169 stubXshmUpdateImageRect(dpy, draw, pGlxPixmap, &rect);
2170 }
2171 }
2172 else
2173 {
2174 XLOCK(dpy);
2175 XCopyArea(dpy, (Pixmap)draw, pGlxPixmap->hShmPixmap, pGlxPixmap->gc,
2176 pGlxPixmap->x, pGlxPixmap->y, pGlxPixmap->w, pGlxPixmap->h, 0, 0);
2177 /* Have to make sure XCopyArea is processed */
2178 XSync(dpy, False);
2179 XUNLOCK(dpy);
2180 stub.spu->dispatch_table.TexImage2D(pGlxPixmap->target, 0, pGlxPixmap->format, pGlxPixmap->w, pGlxPixmap->h, 0,
2181 GL_BGRA, GL_UNSIGNED_BYTE, stub.xshmSI.shmaddr);
2182 /*crDebug("Sync texture for drawable 0x%x(dmg handle 0x%x) [%i,%i,%i,%i]",
2183 (unsigned int) draw, (unsigned int)pGlxPixmap->hDamage,
2184 pGlxPixmap->x, pGlxPixmap->y, pGlxPixmap->w, pGlxPixmap->h);*/
2185 }
2186}
2187
2188static void stubXshmUpdateImageRect(Display *dpy, GLXDrawable draw, GLX_Pixmap_t *pGlxPixmap, XRectangle *pRect)
2189{
2190 /* See comment in stubXshmUpdateWholeImage */
2191 if (CR_MAX_TRANSFER_SIZE < 4*pRect->width*pRect->height)
2192 {
2193 XRectangle rect;
2194
2195 rect.x = pRect->x;
2196 rect.y = pRect->y;
2197 rect.width = pRect->width;
2198 rect.height = CR_MAX_TRANSFER_SIZE/(4*pRect->width);
2199
2200 /*crDebug("Region size too big, splitting in lower sized chunks. [%i,%i,%i,%i] (%i)",
2201 pRect->x, pRect->y, pRect->width, pRect->height, rect.height);*/
2202
2203 for (; (rect.y+rect.height)<=(pRect->y+pRect->height); rect.y+=rect.height)
2204 {
2205 stubXshmUpdateImageRect(dpy, draw, pGlxPixmap, &rect);
2206 }
2207
2208 if (rect.y!=(pRect->y+pRect->height))
2209 {
2210 rect.height=pRect->y+pRect->height-rect.y;
2211 stubXshmUpdateImageRect(dpy, draw, pGlxPixmap, &rect);
2212 }
2213 }
2214 else
2215 {
2216 GLint origUnpackRowLength;
2217
2218 XLOCK(dpy);
2219 XCopyArea(dpy, (Pixmap)draw, pGlxPixmap->hShmPixmap, pGlxPixmap->gc,
2220 pRect->x, pRect->y, pRect->width, pRect->height, 0, 0);
2221 /* Have to make sure XCopyArea is processed */
2222 XSync(dpy, False);
2223 XUNLOCK(dpy);
2224
2225 /* Save original value, doesn't cause sync as it's reported by state tracker*/
2226 if (pRect->width!=pGlxPixmap->w)
2227 {
2228 stub.spu->dispatch_table.GetIntegerv(GL_UNPACK_ROW_LENGTH, &origUnpackRowLength);
2229 stub.spu->dispatch_table.PixelStorei(GL_UNPACK_ROW_LENGTH, pGlxPixmap->w);
2230 }
2231 stub.spu->dispatch_table.TexSubImage2D(pGlxPixmap->target, 0, pRect->x, pRect->y, pRect->width, pRect->height,
2232 GL_BGRA, GL_UNSIGNED_BYTE, stub.xshmSI.shmaddr);
2233 if (pRect->width!=pGlxPixmap->w)
2234 {
2235 /* Restore original value*/
2236 stub.spu->dispatch_table.PixelStorei(GL_UNPACK_ROW_LENGTH, origUnpackRowLength);
2237 }
2238
2239 /*crDebug("Region sync texture for drawable 0x%x(dmg handle 0x%x) [%i,%i,%i,%i]",
2240 (unsigned int) draw, (unsigned int)pGlxPixmap->hDamage,
2241 pRect->x, pRect->y, pRect->width, pRect->height);*/
2242 }
2243}
2244
2245#if 0
2246Bool checkevents(Display *display, XEvent *event, XPointer arg)
2247{
2248 //crDebug("got type: 0x%x", event->type);
2249 if (event->type==damage_evb+XDamageNotify)
2250 {
2251 XDamageNotifyEvent *e = (XDamageNotifyEvent *) event;
2252 /* we're interested in pixmaps only...and those have e->drawable set to 0 or other strange value for some odd reason
2253 * so have to walk glxpixmaps hashtable to find if we have damage event handle assigned to some pixmap
2254 */
2255 /*crDebug("Event: Damage for drawable 0x%x, handle 0x%x (level=%i) [%i,%i,%i,%i]",
2256 (unsigned int) e->drawable, (unsigned int) e->damage, (int) e->level,
2257 e->area.x, e->area.y, e->area.width, e->area.height);*/
2258 CRASSERT(stub.currentContext);
2259 crHashtableWalk(stub.currentContext->pGLXPixmapsHash, checkdamageCB, e);
2260 }
2261 return False;
2262}
2263#endif
2264
2265/*@todo check what error codes could we throw for failures here*/
2266DECLEXPORT(void) VBOXGLXTAG(glXBindTexImageEXT)(Display *dpy, GLXDrawable draw, int buffer, const int *attrib_list)
2267{
2268 static int cnt=0;
2269 XImage dummyimg;
2270
2271 GLX_Pixmap_t *pGlxPixmap;
2272
2273 if (!stub.currentContext)
2274 {
2275 crWarning("glXBindTexImageEXT called without current context");
2276 return;
2277 }
2278
2279 pGlxPixmap = (GLX_Pixmap_t *) crHashtableSearch(stub.currentContext->pGLXPixmapsHash, (unsigned int) draw);
2280 if (!pGlxPixmap)
2281 {
2282 pGlxPixmap = (GLX_Pixmap_t *) crHashtableSearch(stub.pGLXPixmapsHash, (unsigned int) draw);
2283 if (!pGlxPixmap)
2284 {
2285 crDebug("Unknown drawable 0x%x in glXBindTexImageEXT!", (unsigned int) draw);
2286 return;
2287 }
2288 pGlxPixmap = stubInitGlxPixmap(pGlxPixmap, dpy, draw, stub.currentContext);
2289 if (!pGlxPixmap)
2290 {
2291 crDebug("glXBindTexImageEXT failed to get pGlxPixmap");
2292 return;
2293 }
2294 }
2295
2296 /* If there's damage extension, then process incoming events as we need the information right now */
2297 if (stub.currentContext->damageDpy)
2298 {
2299 /* Sync connections, note that order of syncs is important here.
2300 * First make sure client commands are finished, then make sure we get all the damage events back*/
2301 XLOCK(dpy);
2302 XSync(dpy, False);
2303 XUNLOCK(dpy);
2304 XSync(stub.currentContext->damageDpy, False);
2305
2306 while (XPending(stub.currentContext->damageDpy))
2307 {
2308 XEvent event;
2309 XNextEvent(stub.currentContext->damageDpy, &event);
2310 if (event.type==stub.currentContext->damageEventsBase+XDamageNotify)
2311 {
2312 crHashtableWalk(stub.currentContext->pGLXPixmapsHash, stubCheckXDamageCB, &event);
2313 }
2314 }
2315 }
2316
2317 /* No shared memory? Rollback to use slow x protocol then */
2318 if (stub.xshmSI.shmid<0)
2319 {
2320 /*@todo add damage support here too*/
2321 XImage *pxim;
2322
2323 XLOCK(dpy);
2324 pxim = XGetImage(dpy, (Pixmap)draw, pGlxPixmap->x, pGlxPixmap->y, pGlxPixmap->w, pGlxPixmap->h, AllPlanes, ZPixmap);
2325 XUNLOCK(dpy);
2326 /*if (pxim)
2327 {
2328 if (!ptextable)
2329 {
2330 ptextable = crAllocHashtable();
2331 }
2332 pm = crHashtableSearch(ptextable, (unsigned int) draw);
2333 if (!pm)
2334 {
2335 pm = crCalloc(sizeof(pminfo));
2336 crHashtableAdd(ptextable, (unsigned int) draw, pm);
2337 }
2338 pm->w = w;
2339 pm->h = h;
2340 if (pm->data) crFree(pm->data);
2341 pm->data = crAlloc(4*w*h);
2342 crMemcpy(pm->data, (void*)(&(pxim->data[0])), 4*w*h);
2343 }*/
2344
2345 if (NULL==pxim)
2346 {
2347 crWarning("Failed, to get pixmap data for 0x%x", (unsigned int) draw);
2348 return;
2349 }
2350
2351 stub.spu->dispatch_table.TexImage2D(pGlxPixmap->target, 0, pGlxPixmap->format, pxim->width, pxim->height, 0,
2352 GL_BGRA, GL_UNSIGNED_BYTE, (void*)(&(pxim->data[0])));
2353 XDestroyImage(pxim);
2354 }
2355 else /* Use shm to get pixmap data */
2356 {
2357 /* Check if we have damage extension */
2358 if (stub.currentContext->damageDpy)
2359 {
2360 if (pGlxPixmap->bPixmapImageDirty)
2361 {
2362 /* Either we failed to allocate damage region or this pixmap is marked for full update */
2363 if (!pGlxPixmap->pDamageRegion || XEmptyRegion(pGlxPixmap->pDamageRegion))
2364 {
2365 /*crDebug("**FULL** update for 0x%x", (unsigned int)draw);*/
2366 stubXshmUpdateWholeImage(dpy, draw, pGlxPixmap);
2367 }
2368 else
2369 {
2370 long fullArea, damageArea=0, clipdamageArea, i;
2371 XRectangle damageClipBox;
2372
2373 fullArea = pGlxPixmap->w * pGlxPixmap->h;
2374 XClipBox(pGlxPixmap->pDamageRegion, &damageClipBox);
2375 clipdamageArea = damageClipBox.width * damageClipBox.height;
2376
2377 //crDebug("FullSize [%i,%i,%i,%i]", pGlxPixmap->x, pGlxPixmap->y, pGlxPixmap->w, pGlxPixmap->h);
2378 //crDebug("Clip [%i,%i,%i,%i]", damageClipBox.x, damageClipBox.y, damageClipBox.width, damageClipBox.height);
2379
2380 for (i=0; i<pGlxPixmap->pDamageRegion->numRects; ++i)
2381 {
2382 BoxPtr pBox = &pGlxPixmap->pDamageRegion->rects[i];
2383 damageArea += (pBox->x2-pBox->x1)*(pBox->y2-pBox->y1);
2384 //crDebug("Damage rect [%i,%i,%i,%i]", pBox->x1, pBox->y1, pBox->x2, pBox->y2);
2385 }
2386
2387 if (damageArea>clipdamageArea || clipdamageArea>fullArea)
2388 {
2389 crWarning("glXBindTexImageEXT, damage regions seems to be broken, forcing full update");
2390 /*crDebug("**FULL** update for 0x%x, numRect=%li, *FS*=%li, CS=%li, DS=%li",
2391 (unsigned int)draw, pGlxPixmap->pDamageRegion->numRects, fullArea, clipdamageArea, damageArea);*/
2392 stubXshmUpdateWholeImage(dpy, draw, pGlxPixmap);
2393 }
2394 else /*We have corect damage info*/
2395 {
2396 if (CR_MIN_DAMAGE_PROFIT_SIZE > (fullArea-damageArea))
2397 {
2398 /*crDebug("**FULL** update for 0x%x, numRect=%li, *FS*=%li, CS=%li, DS=%li",
2399 (unsigned int)draw, pGlxPixmap->pDamageRegion->numRects, fullArea, clipdamageArea, damageArea);*/
2400 stubXshmUpdateWholeImage(dpy, draw, pGlxPixmap);
2401 }
2402 else if (CR_MIN_DAMAGE_PROFIT_SIZE > (clipdamageArea-damageArea))
2403 {
2404 /*crDebug("**PARTIAL** update for 0x%x, numRect=%li, FS=%li, *CS*=%li, DS=%li",
2405 (unsigned int)draw, pGlxPixmap->pDamageRegion->numRects, fullArea, clipdamageArea, damageArea);*/
2406 stubXshmUpdateImageRect(dpy, draw, pGlxPixmap, &damageClipBox);
2407 }
2408 else
2409 {
2410 /*crDebug("**PARTIAL** update for 0x%x, numRect=*%li*, FS=%li, CS=%li, *DS*=%li",
2411 (unsigned int)draw, pGlxPixmap->pDamageRegion->numRects, fullArea, clipdamageArea, damageArea);*/
2412 for (i=0; i<pGlxPixmap->pDamageRegion->numRects; ++i)
2413 {
2414 XRectangle rect;
2415 BoxPtr pBox = &pGlxPixmap->pDamageRegion->rects[i];
2416
2417 rect.x = pBox->x1;
2418 rect.y = pBox->y1;
2419 rect.width = pBox->x2-pBox->x1;
2420 rect.height = pBox->y2-pBox->y1;
2421
2422 stubXshmUpdateImageRect(dpy, draw, pGlxPixmap, &rect);
2423 }
2424 }
2425 }
2426 }
2427
2428 /* Clean dirty flag and damage region */
2429 pGlxPixmap->bPixmapImageDirty = False;
2430 if (pGlxPixmap->pDamageRegion)
2431 EMPTY_REGION(pGlxPixmap->pDamageRegion);
2432 }
2433 }
2434 else
2435 {
2436 stubXshmUpdateWholeImage(dpy, draw, pGlxPixmap);
2437 }
2438 }
2439}
2440
2441DECLEXPORT(void) VBOXGLXTAG(glXReleaseTexImageEXT)(Display *dpy, GLXDrawable draw, int buffer)
2442{
2443 (void) dpy;
2444 (void) draw;
2445 (void) buffer;
2446 //crDebug("glXReleaseTexImageEXT 0x%x", (unsigned int)draw);
2447}
2448#endif
2449
2450#endif /* GLX_EXTRAS */
2451
2452
2453#ifdef GLX_SGIX_video_resize
2454/* more dummy funcs. These help when linking with older GLUTs */
2455
2456DECLEXPORT(int) VBOXGLXTAG(glXBindChannelToWindowSGIX)(Display *dpy, int scrn, int chan, Window w)
2457{
2458 (void) dpy;
2459 (void) scrn;
2460 (void) chan;
2461 (void) w;
2462 crDebug("glXBindChannelToWindowSGIX");
2463 return 0;
2464}
2465
2466DECLEXPORT(int) VBOXGLXTAG(glXChannelRectSGIX)(Display *dpy, int scrn, int chan, int x , int y, int w, int h)
2467{
2468 (void) dpy;
2469 (void) scrn;
2470 (void) chan;
2471 (void) x;
2472 (void) y;
2473 (void) w;
2474 (void) h;
2475 crDebug("glXChannelRectSGIX");
2476 return 0;
2477}
2478
2479DECLEXPORT(int) VBOXGLXTAG(glXQueryChannelRectSGIX)(Display *dpy, int scrn, int chan, int *x, int *y, int *w, int *h)
2480{
2481 (void) dpy;
2482 (void) scrn;
2483 (void) chan;
2484 (void) x;
2485 (void) y;
2486 (void) w;
2487 (void) h;
2488 crDebug("glXQueryChannelRectSGIX");
2489 return 0;
2490}
2491
2492DECLEXPORT(int) VBOXGLXTAG(glXQueryChannelDeltasSGIX)(Display *dpy, int scrn, int chan, int *dx, int *dy, int *dw, int *dh)
2493{
2494 (void) dpy;
2495 (void) scrn;
2496 (void) chan;
2497 (void) dx;
2498 (void) dy;
2499 (void) dw;
2500 (void) dh;
2501 crDebug("glXQueryChannelDeltasSGIX");
2502 return 0;
2503}
2504
2505DECLEXPORT(int) VBOXGLXTAG(glXChannelRectSyncSGIX)(Display *dpy, int scrn, int chan, GLenum synctype)
2506{
2507 (void) dpy;
2508 (void) scrn;
2509 (void) chan;
2510 (void) synctype;
2511 crDebug("glXChannelRectSyncSGIX");
2512 return 0;
2513}
2514
2515#endif /* GLX_SGIX_video_resize */
2516
2517#ifdef VBOXOGL_FAKEDRI
2518DECLEXPORT(const char *) VBOXGLXTAG(glXGetDriverConfig)(const char *driverName)
2519{
2520 return NULL;
2521}
2522
2523DECLEXPORT(void) VBOXGLXTAG(glXFreeMemoryMESA)(Display *dpy, int scrn, void *pointer)
2524{
2525 (void) dpy;
2526 (void) scrn;
2527 (void) pointer;
2528}
2529
2530DECLEXPORT(GLXContext) VBOXGLXTAG(glXImportContextEXT)(Display *dpy, GLXContextID contextID)
2531{
2532 (void) dpy;
2533 (void) contextID;
2534 return NULL;
2535}
2536
2537DECLEXPORT(GLXContextID) VBOXGLXTAG(glXGetContextIDEXT)(const GLXContext ctx)
2538{
2539 (void) ctx;
2540 return 0;
2541}
2542
2543DECLEXPORT(Bool) VBOXGLXTAG(glXMakeCurrentReadSGI)(Display *display, GLXDrawable draw, GLXDrawable read, GLXContext ctx)
2544{
2545 return VBOXGLXTAG(glXMakeContextCurrent)(display, draw, read, ctx);
2546}
2547
2548DECLEXPORT(const char *) VBOXGLXTAG(glXGetScreenDriver)(Display *dpy, int scrNum)
2549{
2550 static char *screendriver = "vboxvideo";
2551 return screendriver;
2552}
2553
2554DECLEXPORT(Display *) VBOXGLXTAG(glXGetCurrentDisplayEXT)(void)
2555{
2556 return VBOXGLXTAG(glXGetCurrentDisplay());
2557}
2558
2559DECLEXPORT(void) VBOXGLXTAG(glXFreeContextEXT)(Display *dpy, GLXContext ctx)
2560{
2561 VBOXGLXTAG(glXDestroyContext(dpy, ctx));
2562}
2563
2564/*Mesa internal*/
2565DECLEXPORT(int) VBOXGLXTAG(glXQueryContextInfoEXT)(Display *dpy, GLXContext ctx)
2566{
2567 (void) dpy;
2568 (void) ctx;
2569 return 0;
2570}
2571
2572DECLEXPORT(void *) VBOXGLXTAG(glXAllocateMemoryMESA)(Display *dpy, int scrn,
2573 size_t size, float readFreq,
2574 float writeFreq, float priority)
2575{
2576 (void) dpy;
2577 (void) scrn;
2578 (void) size;
2579 (void) readFreq;
2580 (void) writeFreq;
2581 (void) priority;
2582 return NULL;
2583}
2584
2585DECLEXPORT(GLuint) VBOXGLXTAG(glXGetMemoryOffsetMESA)(Display *dpy, int scrn, const void *pointer)
2586{
2587 (void) dpy;
2588 (void) scrn;
2589 (void) pointer;
2590 return 0;
2591}
2592
2593DECLEXPORT(GLXPixmap) VBOXGLXTAG(glXCreateGLXPixmapMESA)(Display *dpy, XVisualInfo *visual, Pixmap pixmap, Colormap cmap)
2594{
2595 (void) dpy;
2596 (void) visual;
2597 (void) pixmap;
2598 (void) cmap;
2599 return 0;
2600}
2601
2602#endif /*VBOXOGL_FAKEDRI*/
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