VirtualBox

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

Last change on this file since 47918 was 43837, checked in by vboxsync, 12 years ago

Additions/crOpenGL: small fix to FBConfig attribute handling.

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