VirtualBox

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

Last change on this file since 35263 was 35263, checked in by vboxsync, 13 years ago

crOpenGL: fix crashes in libnux-0.9 gpu tests

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

© 2023 Oracle
ContactPrivacy policyTerms of Use