VirtualBox

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

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

crOpenGL: fix corrupted textures for gnome3 under ubuntu 11.04

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

© 2023 Oracle
ContactPrivacy policyTerms of Use