VirtualBox

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

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

burn fix

  • Property svn:eol-style set to native
File size: 83.2 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 {
686 crHashtableLock(stub.windowTable);
687 crHashtableLock(stub.contextTable);
688
689 context = (ContextInfo *) crHashtableSearch(stub.contextTable, (unsigned long) ctx);
690 window = stubGetWindowInfo(dpy, drawable);
691
692 if (context && context->type == UNDECIDED) {
693 XLOCK(dpy);
694 XSync(dpy, 0); /* sync to force window creation on the server */
695 XUNLOCK(dpy);
696 }
697 }
698 else
699 {
700 dpy = NULL;
701 window = NULL;
702 context = NULL;
703 }
704
705 currentDisplay = dpy;
706 currentDrawable = drawable;
707
708 retVal = stubMakeCurrent(window, context);
709
710 if (ctx && drawable)
711 {
712 crHashtableUnlock(stub.contextTable);
713 crHashtableUnlock(stub.windowTable);
714 }
715
716 return retVal;
717}
718
719
720DECLEXPORT(GLXPixmap) VBOXGLXTAG(glXCreateGLXPixmap)( Display *dpy, XVisualInfo *vis, Pixmap pixmap )
721{
722 stubInit();
723 return VBOXGLXTAG(glXCreatePixmap)(dpy, (GLXFBConfig)vis->visualid, pixmap, NULL);
724}
725
726DECLEXPORT(void) VBOXGLXTAG(glXDestroyGLXPixmap)( Display *dpy, GLXPixmap pix )
727{
728 VBOXGLXTAG(glXDestroyPixmap)(dpy, pix);
729}
730
731#ifndef VBOX_NO_NATIVEGL /* old code */
732DECLEXPORT(int) VBOXGLXTAG(glXGetConfig)( Display *dpy, XVisualInfo *vis, int attrib, int *value )
733{
734 struct VisualInfo *v;
735 int visBits;
736
737 if (!vis) {
738 /* SGI OpenGL Performer hits this */
739 crWarning("glXGetConfig called with NULL XVisualInfo");
740 return GLX_BAD_VISUAL;
741 }
742
743 v = FindVisualInfo(dpy, DefaultScreen(dpy), vis->visual->visualid);
744 if (v) {
745 visBits = v->visBits;
746 }
747 else {
748 visBits = 0;
749 }
750
751 stubInit();
752
753 /* try to satisfy this request with the native glXGetConfig() */
754 if (stub.haveNativeOpenGL)
755 {
756 int foo, bar;
757 int return_val;
758
759 if (stub.wsInterface.glXQueryExtension(dpy, &foo, &bar))
760 {
761 return_val = stub.wsInterface.glXGetConfig( dpy, vis, attrib, value );
762 if (return_val)
763 {
764 crDebug("faker native glXGetConfig returned %s",
765 glx_error_string(return_val));
766 }
767 return return_val;
768 }
769 }
770
771 /*
772 * If the GLX application chooses its visual via a bunch of calls to
773 * glXGetConfig, instead of by calling glXChooseVisual, we need to keep
774 * track of which attributes are queried to help satisfy context creation
775 * later.
776 */
777 switch ( attrib ) {
778
779 case GLX_USE_GL:
780 *value = 1;
781 break;
782
783 case GLX_BUFFER_SIZE:
784 *value = 32;
785 break;
786
787 case GLX_LEVEL:
788 visBits |= CR_OVERLAY_BIT;
789 *value = (visBits & CR_OVERLAY_BIT) ? 1 : 0;
790 break;
791
792 case GLX_RGBA:
793 visBits |= CR_RGB_BIT;
794 *value = 1;
795 break;
796
797 case GLX_DOUBLEBUFFER:
798 *value = 1;
799 break;
800
801 case GLX_STEREO:
802 *value = 1;
803 break;
804
805 case GLX_AUX_BUFFERS:
806 *value = 0;
807 break;
808
809 case GLX_RED_SIZE:
810 *value = 8;
811 break;
812
813 case GLX_GREEN_SIZE:
814 *value = 8;
815 break;
816
817 case GLX_BLUE_SIZE:
818 *value = 8;
819 break;
820
821 case GLX_ALPHA_SIZE:
822 visBits |= CR_ALPHA_BIT;
823 *value = (visBits & CR_ALPHA_BIT) ? 8 : 0;
824 break;
825
826 case GLX_DEPTH_SIZE:
827 visBits |= CR_DEPTH_BIT;
828 *value = 16;
829 break;
830
831 case GLX_STENCIL_SIZE:
832 visBits |= CR_STENCIL_BIT;
833 *value = 8;
834 break;
835
836 case GLX_ACCUM_RED_SIZE:
837 visBits |= CR_ACCUM_BIT;
838 *value = 16;
839 break;
840
841 case GLX_ACCUM_GREEN_SIZE:
842 visBits |= CR_ACCUM_BIT;
843 *value = 16;
844 break;
845
846 case GLX_ACCUM_BLUE_SIZE:
847 visBits |= CR_ACCUM_BIT;
848 *value = 16;
849 break;
850
851 case GLX_ACCUM_ALPHA_SIZE:
852 visBits |= CR_ACCUM_BIT;
853 *value = 16;
854 break;
855
856 case GLX_SAMPLE_BUFFERS_SGIS:
857 visBits |= CR_MULTISAMPLE_BIT;
858 *value = 0; /* fix someday */
859 break;
860
861 case GLX_SAMPLES_SGIS:
862 visBits |= CR_MULTISAMPLE_BIT;
863 *value = 0; /* fix someday */
864 break;
865
866 case GLX_VISUAL_CAVEAT_EXT:
867 *value = GLX_NONE_EXT;
868 break;
869#if defined(SunOS)
870 /*
871 I don't think this is even a valid attribute for glxGetConfig.
872 No idea why this gets called under SunOS but we simply ignore it
873 -- jw
874 */
875 case GLX_X_VISUAL_TYPE:
876 crWarning ("Ignoring Unsupported GLX Call: glxGetConfig with attrib 0x%x", attrib);
877 break;
878#endif
879
880 case GLX_TRANSPARENT_TYPE:
881 *value = GLX_NONE_EXT;
882 break;
883 case GLX_TRANSPARENT_INDEX_VALUE:
884 *value = 0;
885 break;
886 case GLX_TRANSPARENT_RED_VALUE:
887 *value = 0;
888 break;
889 case GLX_TRANSPARENT_GREEN_VALUE:
890 *value = 0;
891 break;
892 case GLX_TRANSPARENT_BLUE_VALUE:
893 *value = 0;
894 break;
895 case GLX_TRANSPARENT_ALPHA_VALUE:
896 *value = 0;
897 break;
898 default:
899 crWarning( "Unsupported GLX Call: glXGetConfig with attrib 0x%x", attrib );
900 return GLX_BAD_ATTRIBUTE;
901 }
902
903 AddVisualInfo(dpy, DefaultScreen(dpy), vis->visual->visualid, visBits);
904
905 return 0;
906}
907#else /* not 0 */
908DECLEXPORT(int) VBOXGLXTAG(glXGetConfig)( Display *dpy, XVisualInfo *vis, int attrib, int *value )
909{
910 if (!vis) {
911 /* SGI OpenGL Performer hits this */
912 crWarning("glXGetConfig called with NULL XVisualInfo");
913 return GLX_BAD_VISUAL;
914 }
915
916 stubInit();
917
918 *value = 0; /* For sanity */
919
920 switch ( attrib ) {
921
922 case GLX_USE_GL:
923 *value = 1;
924 break;
925
926 case GLX_BUFFER_SIZE:
927 *value = 32;
928 break;
929
930 case GLX_LEVEL:
931 *value = 0; /* for now */
932 break;
933
934 case GLX_RGBA:
935 *value = 1;
936 break;
937
938 case GLX_DOUBLEBUFFER:
939 *value = 1;
940 break;
941
942 case GLX_STEREO:
943 *value = 1;
944 break;
945
946 case GLX_AUX_BUFFERS:
947 *value = 0;
948 break;
949
950 case GLX_RED_SIZE:
951 *value = 8;
952 break;
953
954 case GLX_GREEN_SIZE:
955 *value = 8;
956 break;
957
958 case GLX_BLUE_SIZE:
959 *value = 8;
960 break;
961
962 case GLX_ALPHA_SIZE:
963 *value = 8;
964 break;
965
966 case GLX_DEPTH_SIZE:
967 *value = 16;
968 break;
969
970 case GLX_STENCIL_SIZE:
971 *value = 8;
972 break;
973
974 case GLX_ACCUM_RED_SIZE:
975 *value = 16;
976 break;
977
978 case GLX_ACCUM_GREEN_SIZE:
979 *value = 16;
980 break;
981
982 case GLX_ACCUM_BLUE_SIZE:
983 *value = 16;
984 break;
985
986 case GLX_ACCUM_ALPHA_SIZE:
987 *value = 16;
988 break;
989
990 case GLX_SAMPLE_BUFFERS_SGIS:
991 *value = 0; /* fix someday */
992 break;
993
994 case GLX_SAMPLES_SGIS:
995 *value = 0; /* fix someday */
996 break;
997
998 case GLX_VISUAL_CAVEAT_EXT:
999 *value = GLX_NONE_EXT;
1000 break;
1001#if defined(SunOS) || 1
1002 /*
1003 I don't think this is even a valid attribute for glxGetConfig.
1004 No idea why this gets called under SunOS but we simply ignore it
1005 -- jw
1006 */
1007 case GLX_X_VISUAL_TYPE:
1008 crWarning ("Ignoring Unsupported GLX Call: glxGetConfig with attrib 0x%x", attrib);
1009 break;
1010#endif
1011
1012 case GLX_TRANSPARENT_TYPE:
1013 *value = GLX_NONE_EXT;
1014 break;
1015 case GLX_TRANSPARENT_INDEX_VALUE:
1016 *value = 0;
1017 break;
1018 case GLX_TRANSPARENT_RED_VALUE:
1019 *value = 0;
1020 break;
1021 case GLX_TRANSPARENT_GREEN_VALUE:
1022 *value = 0;
1023 break;
1024 case GLX_TRANSPARENT_BLUE_VALUE:
1025 *value = 0;
1026 break;
1027 case GLX_TRANSPARENT_ALPHA_VALUE:
1028 *value = 0;
1029 break;
1030 case GLX_DRAWABLE_TYPE:
1031 *value = GLX_WINDOW_BIT;
1032 break;
1033 default:
1034 crWarning( "Unsupported GLX Call: glXGetConfig with attrib 0x%x, ignoring...", attrib );
1035 //return GLX_BAD_ATTRIBUTE;
1036 *value = 0;
1037 }
1038
1039 return 0;
1040}
1041#endif
1042
1043DECLEXPORT(GLXContext) VBOXGLXTAG(glXGetCurrentContext)( void )
1044{
1045 ContextInfo *context = stubGetCurrentContext();
1046 if (context)
1047 return (GLXContext) context->id;
1048 else
1049 return (GLXContext) NULL;
1050}
1051
1052DECLEXPORT(GLXDrawable) VBOXGLXTAG(glXGetCurrentDrawable)(void)
1053{
1054 return currentDrawable;
1055}
1056
1057DECLEXPORT(Display *) VBOXGLXTAG(glXGetCurrentDisplay)(void)
1058{
1059 return currentDisplay;
1060}
1061
1062DECLEXPORT(Bool) VBOXGLXTAG(glXIsDirect)(Display *dpy, GLXContext ctx)
1063{
1064 (void) dpy;
1065 (void) ctx;
1066 crDebug("->glXIsDirect");
1067 return True;
1068}
1069
1070DECLEXPORT(Bool) VBOXGLXTAG(glXQueryExtension)(Display *dpy, int *errorBase, int *eventBase)
1071{
1072 (void) dpy;
1073 (void) errorBase;
1074 (void) eventBase;
1075 return 1; /* You BET we do... */
1076}
1077
1078DECLEXPORT(Bool) VBOXGLXTAG(glXQueryVersion)( Display *dpy, int *major, int *minor )
1079{
1080 (void) dpy;
1081 *major = 1;
1082 *minor = 3;
1083 return 1;
1084}
1085
1086static XErrorHandler oldErrorHandler;
1087static unsigned char lastXError = Success;
1088
1089static int
1090errorHandler (Display *dpy, XErrorEvent *e)
1091{
1092 lastXError = e->error_code;
1093 return 0;
1094}
1095
1096DECLEXPORT(void) VBOXGLXTAG(glXSwapBuffers)( Display *dpy, GLXDrawable drawable )
1097{
1098 WindowInfo *window = stubGetWindowInfo(dpy, drawable);
1099 stubSwapBuffers( window, 0 );
1100
1101#ifdef VBOX_TEST_MEGOO
1102 if (!stub.bXExtensionsChecked)
1103 {
1104 stubCheckXExtensions(window);
1105 }
1106
1107 if (!stub.bHaveXComposite)
1108 {
1109 return;
1110 }
1111
1112 {
1113 Pixmap p;
1114 XWindowAttributes attr;
1115
1116 XLOCK(dpy);
1117 XGetWindowAttributes(dpy, window->drawable, &attr);
1118 if (attr.override_redirect)
1119 {
1120 XUNLOCK(dpy);
1121 return;
1122 }
1123
1124 crLockMutex(&stub.mutex);
1125
1126 XSync(dpy, false);
1127 oldErrorHandler = XSetErrorHandler(errorHandler);
1128 /*@todo this creates new pixmap for window every call*/
1129 /*p = XCompositeNameWindowPixmap(dpy, window->drawable);*/
1130 XSync(dpy, false);
1131 XSetErrorHandler(oldErrorHandler);
1132 XUNLOCK(dpy);
1133
1134 if (lastXError==Success)
1135 {
1136 char *data, *imgdata;
1137 GC gc;
1138 XImage *image;
1139 XVisualInfo searchvis, *pret;
1140 int nvisuals;
1141 XGCValues gcValues;
1142 int i, rowsize;
1143
1144 XLOCK(dpy);
1145
1146 searchvis.visualid = attr.visual->visualid;
1147 pret = XGetVisualInfo(dpy, VisualIDMask, &searchvis, &nvisuals);
1148 if (nvisuals!=1) crWarning("XGetVisualInfo returned %i visuals for %x", nvisuals, (unsigned int) searchvis.visualid);
1149 CRASSERT(pret);
1150
1151 gc = XCreateGC(dpy, window->drawable, 0, &gcValues);
1152 if (!gc) crWarning("Failed to create gc!");
1153
1154 data = crCalloc(window->width * window->height * 4);
1155 imgdata = crCalloc(window->width * window->height * 4);
1156 CRASSERT(data && imgdata);
1157 stub.spu->dispatch_table.ReadPixels(0, 0, window->width, window->height, GL_RGBA, GL_UNSIGNED_BYTE, data);
1158 /*y-invert image*/
1159 rowsize = 4*window->width;
1160 for (i=0; i<window->height; ++i)
1161 {
1162 crMemcpy(imgdata+rowsize*i, data+rowsize*(window->height-i-1), rowsize);
1163 }
1164 crFree(data);
1165
1166 XSync(dpy, false);
1167 image = XCreateImage(dpy, attr.visual, pret->depth, ZPixmap, 0, imgdata, window->width, window->height, 32, 0);
1168 XPutImage(dpy, window->drawable, gc, image, 0, 0, 0, 0, window->width, window->height);
1169
1170 XFree(pret);
1171 /*XFreePixmap(dpy, p);*/
1172 XFreeGC(dpy, gc);
1173 XDestroyImage(image);
1174 XUNLOCK(dpy);
1175 }
1176 lastXError=Success;
1177 crUnlockMutex(&stub.mutex);
1178 }
1179#endif
1180}
1181
1182#ifndef VBOX_NO_NATIVEGL
1183DECLEXPORT(void) VBOXGLXTAG(glXUseXFont)( Font font, int first, int count, int listBase )
1184{
1185 ContextInfo *context = stubGetCurrentContext();
1186 if (context->type == CHROMIUM)
1187 {
1188 Display *dpy = stub.wsInterface.glXGetCurrentDisplay();
1189 if (dpy) {
1190 stubUseXFont( dpy, font, first, count, listBase );
1191 }
1192 else {
1193 dpy = XOpenDisplay(NULL);
1194 if (!dpy)
1195 return;
1196 stubUseXFont( dpy, font, first, count, listBase );
1197 XCloseDisplay(dpy);
1198 }
1199 } else
1200 stub.wsInterface.glXUseXFont( font, first, count, listBase );
1201}
1202#else /* not 0 */
1203DECLEXPORT(void) VBOXGLXTAG(glXUseXFont)( Font font, int first, int count, int listBase )
1204{
1205 ContextInfo *context = stubGetCurrentContext();
1206 Display *dpy = context->dpy;
1207 if (dpy) {
1208 stubUseXFont( dpy, font, first, count, listBase );
1209 }
1210 else {
1211 dpy = XOpenDisplay(NULL);
1212 if (!dpy)
1213 return;
1214 stubUseXFont( dpy, font, first, count, listBase );
1215 XCloseDisplay(dpy);
1216 }
1217}
1218#endif
1219
1220DECLEXPORT(void) VBOXGLXTAG(glXWaitGL)( void )
1221{
1222 static int first_call = 1;
1223
1224 if ( first_call )
1225 {
1226 crDebug( "Ignoring unsupported GLX call: glXWaitGL()" );
1227 first_call = 0;
1228 }
1229}
1230
1231DECLEXPORT(void) VBOXGLXTAG(glXWaitX)( void )
1232{
1233 static int first_call = 1;
1234
1235 if ( first_call )
1236 {
1237 crDebug( "Ignoring unsupported GLX call: glXWaitX()" );
1238 first_call = 0;
1239 }
1240}
1241
1242DECLEXPORT(const char *) VBOXGLXTAG(glXQueryExtensionsString)( Display *dpy, int screen )
1243{
1244 /* XXX maybe also advertise GLX_SGIS_multisample? */
1245
1246 static const char *retval = "GLX_ARB_multisample GLX_EXT_texture_from_pixmap GLX_SGIX_fbconfig GLX_ARB_get_proc_address";
1247
1248 (void) dpy;
1249 (void) screen;
1250
1251 crDebug("->glXQueryExtensionsString");
1252 return retval;
1253}
1254
1255DECLEXPORT(const char *) VBOXGLXTAG(glXGetClientString)( Display *dpy, int name )
1256{
1257 const char *retval;
1258 (void) dpy;
1259 (void) name;
1260
1261 switch ( name ) {
1262
1263 case GLX_VENDOR:
1264 retval = "Chromium";
1265 break;
1266
1267 case GLX_VERSION:
1268 retval = "1.3 Chromium";
1269 break;
1270
1271 case GLX_EXTENSIONS:
1272 /*@todo should be a screen not a name...but it's not used anyway*/
1273 retval = glXQueryExtensionsString(dpy, name);
1274 break;
1275
1276 default:
1277 retval = NULL;
1278 }
1279
1280 return retval;
1281}
1282
1283DECLEXPORT(const char *) VBOXGLXTAG(glXQueryServerString)( Display *dpy, int screen, int name )
1284{
1285 const char *retval;
1286 (void) dpy;
1287 (void) screen;
1288
1289 switch ( name ) {
1290
1291 case GLX_VENDOR:
1292 retval = "Chromium";
1293 break;
1294
1295 case GLX_VERSION:
1296 retval = "1.3 Chromium";
1297 break;
1298
1299 case GLX_EXTENSIONS:
1300 retval = glXQueryExtensionsString(dpy, screen);
1301 break;
1302
1303 default:
1304 retval = NULL;
1305 }
1306
1307 return retval;
1308}
1309
1310DECLEXPORT(CR_GLXFuncPtr) VBOXGLXTAG(glXGetProcAddressARB)( const GLubyte *name )
1311{
1312 return (CR_GLXFuncPtr) crGetProcAddress( (const char *) name );
1313}
1314
1315DECLEXPORT(CR_GLXFuncPtr) VBOXGLXTAG(glXGetProcAddress)( const GLubyte *name )
1316{
1317 return (CR_GLXFuncPtr) crGetProcAddress( (const char *) name );
1318}
1319
1320
1321#if GLX_EXTRAS
1322
1323DECLEXPORT(GLXPbufferSGIX)
1324VBOXGLXTAG(glXCreateGLXPbufferSGIX)(Display *dpy, GLXFBConfigSGIX config,
1325 unsigned int width, unsigned int height,
1326 int *attrib_list)
1327{
1328 (void) dpy;
1329 (void) config;
1330 (void) width;
1331 (void) height;
1332 (void) attrib_list;
1333 crWarning("glXCreateGLXPbufferSGIX not implemented by Chromium");
1334 return 0;
1335}
1336
1337DECLEXPORT(void) VBOXGLXTAG(glXDestroyGLXPbufferSGIX)(Display *dpy, GLXPbuffer pbuf)
1338{
1339 (void) dpy;
1340 (void) pbuf;
1341 crWarning("glXDestroyGLXPbufferSGIX not implemented by Chromium");
1342}
1343
1344DECLEXPORT(void) VBOXGLXTAG(glXSelectEventSGIX)(Display *dpy, GLXDrawable drawable, unsigned long mask)
1345{
1346 (void) dpy;
1347 (void) drawable;
1348 (void) mask;
1349}
1350
1351DECLEXPORT(void) VBOXGLXTAG(glXGetSelectedEventSGIX)(Display *dpy, GLXDrawable drawable, unsigned long *mask)
1352{
1353 (void) dpy;
1354 (void) drawable;
1355 (void) mask;
1356}
1357
1358DECLEXPORT(int) VBOXGLXTAG(glXQueryGLXPbufferSGIX)(Display *dpy, GLXPbuffer pbuf,
1359 int attribute, unsigned int *value)
1360{
1361 (void) dpy;
1362 (void) pbuf;
1363 (void) attribute;
1364 (void) value;
1365 crWarning("glXQueryGLXPbufferSGIX not implemented by Chromium");
1366 return 0;
1367}
1368
1369DECLEXPORT(int) VBOXGLXTAG(glXGetFBConfigAttribSGIX)(Display *dpy, GLXFBConfig config,
1370 int attribute, int *value)
1371{
1372 return VBOXGLXTAG(glXGetFBConfigAttrib)(dpy, config, attribute, value);
1373}
1374
1375DECLEXPORT(GLXFBConfigSGIX *)
1376VBOXGLXTAG(glXChooseFBConfigSGIX)(Display *dpy, int screen,
1377 int *attrib_list, int *nelements)
1378{
1379 return VBOXGLXTAG(glXChooseFBConfig)(dpy, screen, attrib_list, nelements);
1380}
1381
1382DECLEXPORT(GLXPixmap)
1383VBOXGLXTAG(glXCreateGLXPixmapWithConfigSGIX)(Display *dpy,
1384 GLXFBConfig config,
1385 Pixmap pixmap)
1386{
1387 return VBOXGLXTAG(glXCreatePixmap)(dpy, config, pixmap, NULL);
1388}
1389
1390DECLEXPORT(GLXContext)
1391VBOXGLXTAG(glXCreateContextWithConfigSGIX)(Display *dpy, GLXFBConfig config,
1392 int render_type,
1393 GLXContext share_list,
1394 Bool direct)
1395{
1396 if (render_type!=GLX_RGBA_TYPE_SGIX)
1397 {
1398 crWarning("glXCreateContextWithConfigSGIX: Unsupported render type %i", render_type);
1399 return NULL;
1400 }
1401 else
1402 {
1403 XVisualInfo *vis;
1404 GLXContext ret;
1405
1406 vis = VBOXGLXTAG(glXGetVisualFromFBConfigSGIX)(dpy, config);
1407 if (!vis)
1408 {
1409 crWarning("glXCreateContextWithConfigSGIX: no visuals for %p", config);
1410 return NULL;
1411 }
1412 ret = VBOXGLXTAG(glXCreateContext)(dpy, vis, share_list, direct);
1413 XFree(vis);
1414 return ret;
1415 }
1416}
1417
1418DECLEXPORT(XVisualInfo *)
1419VBOXGLXTAG(glXGetVisualFromFBConfigSGIX)(Display *dpy,
1420 GLXFBConfig config)
1421{
1422 return VBOXGLXTAG(glXGetVisualFromFBConfig)(dpy, config);
1423}
1424
1425DECLEXPORT(GLXFBConfigSGIX)
1426VBOXGLXTAG(glXGetFBConfigFromVisualSGIX)(Display *dpy, XVisualInfo *vis)
1427{
1428 if (!vis)
1429 {
1430 return NULL;
1431 }
1432 /*Note: Caller is supposed to call XFree on returned value, so can't just return (GLXFBConfig)vis->visualid*/
1433 return (GLXFBConfigSGIX) VBOXGLXTAG(glXGetVisualFromFBConfig)(dpy, (GLXFBConfig)vis->visualid);
1434}
1435
1436/*
1437 * GLX 1.3 functions
1438 */
1439DECLEXPORT(GLXFBConfig *)
1440VBOXGLXTAG(glXChooseFBConfig)(Display *dpy, int screen, ATTRIB_TYPE *attrib_list, int *nelements)
1441{
1442 ATTRIB_TYPE *attrib;
1443 intptr_t fbconfig = 0;
1444
1445 stubInit();
1446
1447 if (!attrib_list)
1448 {
1449 return VBOXGLXTAG(glXGetFBConfigs)(dpy, screen, nelements);
1450 }
1451
1452 for (attrib = attrib_list; *attrib != None; attrib++)
1453 {
1454 switch (*attrib)
1455 {
1456 case GLX_FBCONFIG_ID:
1457 fbconfig = attrib[1];
1458 attrib++;
1459 break;
1460
1461 case GLX_BUFFER_SIZE:
1462 /* this is for color-index visuals, which we don't support */
1463 goto err_exit;
1464 attrib++;
1465 break;
1466
1467 case GLX_LEVEL:
1468 if (attrib[1] != 0)
1469 goto err_exit;
1470 attrib++;
1471 break;
1472
1473 case GLX_AUX_BUFFERS:
1474 if (attrib[1] != 0)
1475 goto err_exit;
1476 attrib++;
1477 break;
1478
1479 case GLX_DOUBLEBUFFER: /* @todo, check if we support it */
1480 attrib++;
1481 break;
1482
1483 case GLX_STEREO:
1484 if (attrib[1] != 0)
1485 goto err_exit;
1486 attrib++;
1487 break;
1488
1489 case GLX_RED_SIZE:
1490 case GLX_GREEN_SIZE:
1491 case GLX_BLUE_SIZE:
1492 case GLX_ALPHA_SIZE:
1493 if (attrib[1] > 8)
1494 goto err_exit;
1495 attrib++;
1496 break;
1497
1498 case GLX_DEPTH_SIZE:
1499 if (attrib[1] > 16)
1500 goto err_exit;
1501 attrib++;
1502 break;
1503
1504 case GLX_STENCIL_SIZE:
1505 if (attrib[1] > 8)
1506 goto err_exit;
1507 attrib++;
1508 break;
1509
1510 case GLX_ACCUM_RED_SIZE:
1511 case GLX_ACCUM_GREEN_SIZE:
1512 case GLX_ACCUM_BLUE_SIZE:
1513 case GLX_ACCUM_ALPHA_SIZE:
1514 if (attrib[1] > 16)
1515 goto err_exit;
1516 attrib++;
1517 break;
1518
1519 case GLX_X_RENDERABLE:
1520 case GLX_CONFIG_CAVEAT:
1521 attrib++;
1522 break;
1523
1524 case GLX_RENDER_TYPE:
1525 if (attrib[1]!=GLX_RGBA_BIT)
1526 goto err_exit;
1527 attrib++;
1528 break;
1529
1530 case GLX_DRAWABLE_TYPE:
1531 if (attrib[1]!=GLX_WINDOW_BIT)
1532 goto err_exit;
1533 attrib++;
1534 break;
1535
1536 case GLX_X_VISUAL_TYPE:
1537 case GLX_TRANSPARENT_TYPE_EXT:
1538 case GLX_TRANSPARENT_INDEX_VALUE_EXT:
1539 case GLX_TRANSPARENT_RED_VALUE_EXT:
1540 case GLX_TRANSPARENT_GREEN_VALUE_EXT:
1541 case GLX_TRANSPARENT_BLUE_VALUE_EXT:
1542 case GLX_TRANSPARENT_ALPHA_VALUE_EXT:
1543 /* ignore */
1544 crWarning("glXChooseVisual: ignoring attribute 0x%x", *attrib);
1545 attrib++;
1546 break;
1547
1548 break;
1549 default:
1550 crWarning( "glXChooseVisual: bad attrib=0x%x, ignoring", *attrib );
1551 attrib++;
1552 break;
1553 }
1554 }
1555
1556 if (fbconfig)
1557 {
1558 GLXFBConfig *pGLXFBConfigs;
1559
1560 *nelements = 1;
1561 pGLXFBConfigs = (GLXFBConfig *) crAlloc(*nelements * sizeof(GLXFBConfig));
1562 pGLXFBConfigs[0] = (GLXFBConfig)fbconfig;
1563 return pGLXFBConfigs;
1564 }
1565 else
1566 {
1567 return VBOXGLXTAG(glXGetFBConfigs)(dpy, screen, nelements);
1568 }
1569
1570err_exit:
1571 crWarning("glXChooseFBConfig returning NULL, due to attrib=0x%x, next=0x%x", attrib[0], attrib[1]);
1572 return NULL;
1573}
1574
1575DECLEXPORT(GLXContext)
1576VBOXGLXTAG(glXCreateNewContext)(Display *dpy, GLXFBConfig config, int render_type, GLXContext share_list, Bool direct)
1577{
1578 XVisualInfo *vis;
1579
1580 (void) dpy;
1581 (void) config;
1582 (void) render_type;
1583 (void) share_list;
1584 (void) direct;
1585
1586 if (render_type != GLX_RGBA_TYPE)
1587 {
1588 crWarning("glXCreateNewContext, unsupported render_type %x", render_type);
1589 return NULL;
1590 }
1591
1592 vis = VBOXGLXTAG(glXGetVisualFromFBConfig)(dpy, config);
1593 return VBOXGLXTAG(glXCreateContext)(dpy, vis, share_list, direct);
1594}
1595
1596DECLEXPORT(GLXPbuffer)
1597VBOXGLXTAG(glXCreatePbuffer)(Display *dpy, GLXFBConfig config, ATTRIB_TYPE *attrib_list)
1598{
1599 (void) dpy;
1600 (void) config;
1601 (void) attrib_list;
1602 crWarning("glXCreatePbuffer not implemented by Chromium");
1603 return 0;
1604}
1605
1606/* Note: there're examples where glxpixmaps are created without current context, so can't do much of the work here.
1607 * Instead we'd do necessary initialization on first use of those pixmaps.
1608 */
1609DECLEXPORT(GLXPixmap)
1610VBOXGLXTAG(glXCreatePixmap)(Display *dpy, GLXFBConfig config, Pixmap pixmap, const ATTRIB_TYPE *attrib_list)
1611{
1612 ATTRIB_TYPE *attrib;
1613 XVisualInfo *pVis;
1614 GLX_Pixmap_t *pGlxPixmap;
1615 (void) dpy;
1616 (void) config;
1617
1618#if 0
1619 {
1620 int x, y;
1621 unsigned int w, h;
1622 unsigned int border;
1623 unsigned int depth;
1624 Window root;
1625
1626 crDebug("glXCreatePixmap called for %lu", pixmap);
1627
1628 XLOCK(dpy);
1629 if (!XGetGeometry(dpy, pixmap, &root, &x, &y, &w, &h, &border, &depth))
1630 {
1631 XSync(dpy, False);
1632 if (!XGetGeometry(dpy, pixmap, &root, &x, &y, &w, &h, &border, &depth))
1633 {
1634 crDebug("fail");
1635 }
1636 }
1637 crDebug("root: %lu, [%i,%i %u,%u]", root, x, y, w, h);
1638 XUNLOCK(dpy);
1639 }
1640#endif
1641
1642 pGlxPixmap = crCalloc(sizeof(GLX_Pixmap_t));
1643 if (!pGlxPixmap)
1644 {
1645 crWarning("glXCreatePixmap failed to allocate memory");
1646 return 0;
1647 }
1648
1649 pVis = VBOXGLXTAG(glXGetVisualFromFBConfig)(dpy, config);
1650 if (!pVis)
1651 {
1652 crWarning("Unknown config %p in glXCreatePixmap", config);
1653 return 0;
1654 }
1655
1656 pGlxPixmap->format = pVis->depth==24 ? GL_RGB:GL_RGBA;
1657 pGlxPixmap->target = GL_TEXTURE_2D;
1658
1659 if (attrib_list)
1660 {
1661 for (attrib = attrib_list; *attrib != None; attrib++)
1662 {
1663 switch (*attrib)
1664 {
1665 case GLX_TEXTURE_FORMAT_EXT:
1666 attrib++;
1667 switch (*attrib)
1668 {
1669 case GLX_TEXTURE_FORMAT_RGBA_EXT:
1670 pGlxPixmap->format = GL_RGBA;
1671 break;
1672 case GLX_TEXTURE_FORMAT_RGB_EXT:
1673 pGlxPixmap->format = GL_RGB;
1674 break;
1675 default:
1676 crDebug("Unexpected GLX_TEXTURE_FORMAT_EXT 0x%x", (unsigned int) *attrib);
1677 }
1678 break;
1679 case GLX_TEXTURE_TARGET_EXT:
1680 attrib++;
1681 switch (*attrib)
1682 {
1683 case GLX_TEXTURE_2D_EXT:
1684 pGlxPixmap->target = GL_TEXTURE_2D;
1685 break;
1686 case GLX_TEXTURE_RECTANGLE_EXT:
1687 pGlxPixmap->target = GL_TEXTURE_RECTANGLE_NV;
1688 break;
1689 default:
1690 crDebug("Unexpected GLX_TEXTURE_TARGET_EXT 0x%x", (unsigned int) *attrib);
1691 }
1692 break;
1693 default: attrib++;
1694 }
1695 }
1696 }
1697
1698 crHashtableAdd(stub.pGLXPixmapsHash, (unsigned int) pixmap, pGlxPixmap);
1699 return (GLXPixmap) pixmap;
1700}
1701
1702DECLEXPORT(GLXWindow)
1703VBOXGLXTAG(glXCreateWindow)(Display *dpy, GLXFBConfig config, Window win, ATTRIB_TYPE *attrib_list)
1704{
1705 GLXFBConfig *realcfg;
1706 int nconfigs;
1707 (void) config;
1708
1709 if (stub.wsInterface.glXGetFBConfigs)
1710 {
1711 realcfg = stub.wsInterface.glXGetFBConfigs(dpy, 0, &nconfigs);
1712 if (!realcfg || nconfigs<1)
1713 {
1714 crWarning("glXCreateWindow !realcfg || nconfigs<1");
1715 return 0;
1716 }
1717 else
1718 {
1719 return stub.wsInterface.glXCreateWindow(dpy, realcfg[0], win, attrib_list);
1720 }
1721 }
1722 else
1723 {
1724 if (attrib_list && *attrib_list!=None)
1725 {
1726 crWarning("Non empty attrib list in glXCreateWindow");
1727 return 0;
1728 }
1729 return (GLXWindow)win;
1730 }
1731}
1732
1733DECLEXPORT(void) VBOXGLXTAG(glXDestroyPbuffer)(Display *dpy, GLXPbuffer pbuf)
1734{
1735 (void) dpy;
1736 (void) pbuf;
1737 crWarning("glXDestroyPbuffer not implemented by Chromium");
1738}
1739
1740DECLEXPORT(void) VBOXGLXTAG(glXDestroyPixmap)(Display *dpy, GLXPixmap pixmap)
1741{
1742 stubFindPixmapParms_t parms;
1743
1744 if (crHashtableSearch(stub.pGLXPixmapsHash, (unsigned int) pixmap))
1745 {
1746 /*it's valid but never used glxpixmap, so simple free stored ptr*/
1747 crHashtableDelete(stub.pGLXPixmapsHash, (unsigned int) pixmap, crFree);
1748 return;
1749 }
1750 else
1751 {
1752 /*it's either invalid glxpixmap or one which was already initialized, so it's stored in appropriate ctx hash*/
1753 parms.pCtx = NULL;
1754 parms.pGlxPixmap = NULL;
1755 parms.draw = pixmap;
1756 crHashtableWalk(stub.contextTable, stubFindPixmapCB, &parms);
1757 }
1758
1759 if (!parms.pGlxPixmap)
1760 {
1761 crWarning("glXDestroyPixmap called for unknown glxpixmap 0x%x", (unsigned int) pixmap);
1762 return;
1763 }
1764
1765 XLOCK(dpy);
1766 if (parms.pGlxPixmap->gc)
1767 {
1768 XFreeGC(dpy, parms.pGlxPixmap->gc);
1769 }
1770
1771 if (parms.pGlxPixmap->hShmPixmap>0)
1772 {
1773 XFreePixmap(dpy, parms.pGlxPixmap->hShmPixmap);
1774 }
1775 XUNLOCK(dpy);
1776
1777 if (parms.pGlxPixmap->hDamage>0)
1778 {
1779 //crDebug("Destroy: Damage for drawable 0x%x, handle 0x%x", (unsigned int) pixmap, (unsigned int) parms.pGlxPixmap->damage);
1780 XDamageDestroy(parms.pCtx->damageDpy, parms.pGlxPixmap->hDamage);
1781 }
1782
1783 if (parms.pGlxPixmap->pDamageRegion)
1784 {
1785 XDestroyRegion(parms.pGlxPixmap->pDamageRegion);
1786 }
1787
1788 crHashtableDelete(parms.pCtx->pGLXPixmapsHash, (unsigned int) pixmap, crFree);
1789}
1790
1791DECLEXPORT(void) VBOXGLXTAG(glXDestroyWindow)(Display *dpy, GLXWindow win)
1792{
1793 (void) dpy;
1794 (void) win;
1795 /*crWarning("glXDestroyWindow not implemented by Chromium");*/
1796}
1797
1798DECLEXPORT(GLXDrawable) VBOXGLXTAG(glXGetCurrentReadDrawable)(void)
1799{
1800 return currentReadDrawable;
1801}
1802
1803DECLEXPORT(int) VBOXGLXTAG(glXGetFBConfigAttrib)(Display *dpy, GLXFBConfig config, int attribute, int *value)
1804{
1805 XVisualInfo * pVisual;
1806 const char * pExt;
1807
1808 pVisual = VBOXGLXTAG(glXGetVisualFromFBConfig)(dpy, config);
1809 if (!pVisual)
1810 {
1811 crWarning("glXGetFBConfigAttrib for %p, failed to get XVisualInfo", config);
1812 return GLX_BAD_ATTRIBUTE;
1813 }
1814 //crDebug("glXGetFBConfigAttrib 0x%x for 0x%x, visualid=0x%x, depth=%i", attribute, (int)config, (int)pVisual->visualid, pVisual->depth);
1815
1816
1817 switch (attribute)
1818 {
1819 case GLX_DRAWABLE_TYPE:
1820 *value = GLX_PIXMAP_BIT;
1821 break;
1822 case GLX_BIND_TO_TEXTURE_TARGETS_EXT:
1823 *value = GLX_TEXTURE_2D_BIT_EXT;
1824 pExt = (const char *) stub.spu->dispatch_table.GetString(GL_EXTENSIONS);
1825 if (crStrstr(pExt, "GL_NV_texture_rectangle")
1826 || crStrstr(pExt, "GL_ARB_texture_rectangle")
1827 || crStrstr(pExt, "GL_EXT_texture_rectangle"))
1828 {
1829 *value |= GLX_TEXTURE_RECTANGLE_BIT_EXT;
1830 }
1831 break;
1832 case GLX_BIND_TO_TEXTURE_RGBA_EXT:
1833 *value = pVisual->depth==32;
1834 break;
1835 case GLX_BIND_TO_TEXTURE_RGB_EXT:
1836 *value = True;
1837 break;
1838 case GLX_DOUBLEBUFFER:
1839 //crDebug("attribute=GLX_DOUBLEBUFFER");
1840 *value = True;
1841 break;
1842 case GLX_Y_INVERTED_EXT:
1843 *value = True;
1844 break;
1845 case GLX_ALPHA_SIZE:
1846 //crDebug("attribute=GLX_ALPHA_SIZE");
1847 *value = pVisual->depth==32 ? 8:0;
1848 break;
1849 case GLX_BUFFER_SIZE:
1850 //crDebug("attribute=GLX_BUFFER_SIZE");
1851 *value = pVisual->depth;
1852 break;
1853 case GLX_STENCIL_SIZE:
1854 //crDebug("attribute=GLX_STENCIL_SIZE");
1855 *value = 8;
1856 break;
1857 case GLX_DEPTH_SIZE:
1858 *value = 16;
1859 //crDebug("attribute=GLX_DEPTH_SIZE");
1860 break;
1861 case GLX_BIND_TO_MIPMAP_TEXTURE_EXT:
1862 *value = 0;
1863 break;
1864 case GLX_RENDER_TYPE:
1865 //crDebug("attribute=GLX_RENDER_TYPE");
1866 *value = GLX_RGBA_BIT;
1867 break;
1868 case GLX_CONFIG_CAVEAT:
1869 //crDebug("attribute=GLX_CONFIG_CAVEAT");
1870 *value = GLX_NONE;
1871 break;
1872 case GLX_VISUAL_ID:
1873 //crDebug("attribute=GLX_VISUAL_ID");
1874 *value = pVisual->visualid;
1875 break;
1876 case GLX_FBCONFIG_ID:
1877 *value = pVisual->visualid; /*or config, though those are the same at the moment but this could change one day?*/
1878 break;
1879 case GLX_RED_SIZE:
1880 case GLX_GREEN_SIZE:
1881 case GLX_BLUE_SIZE:
1882 *value = 8;
1883 break;
1884 case GLX_LEVEL:
1885 *value = 0;
1886 break;
1887 case GLX_STEREO:
1888 *value = false;
1889 break;
1890 case GLX_AUX_BUFFERS:
1891 *value = 0;
1892 break;
1893 case GLX_ACCUM_RED_SIZE:
1894 case GLX_ACCUM_GREEN_SIZE:
1895 case GLX_ACCUM_BLUE_SIZE:
1896 case GLX_ACCUM_ALPHA_SIZE:
1897 *value = 0;
1898 break;
1899 case GLX_X_VISUAL_TYPE:
1900 *value = GLX_TRUE_COLOR;
1901 break;
1902 case GLX_TRANSPARENT_TYPE:
1903 *value = GLX_NONE;
1904 break;
1905 case GLX_SAMPLE_BUFFERS:
1906 case GLX_SAMPLES:
1907 *value = 1;
1908 break;
1909 case GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT:
1910 *value = 0;
1911 break;
1912 default:
1913 crDebug("glXGetFBConfigAttrib: unknown attribute=0x%x", attribute);
1914 XFree(pVisual);
1915 return GLX_BAD_ATTRIBUTE;
1916 }
1917
1918 XFree(pVisual);
1919 return Success;
1920}
1921
1922#if !defined(VBOX_NO_NATIVEGL) || 1 /* need fbconfigs atleast for depths 24 and 32 */
1923DECLEXPORT(GLXFBConfig *) VBOXGLXTAG(glXGetFBConfigs)(Display *dpy, int screen, int *nelements)
1924{
1925 GLXFBConfig *pGLXFBConfigs = NULL;
1926 struct VisualInfo *v;
1927 int i=0, cVisuals;
1928 XVisualInfo searchvis, *pVisuals;
1929
1930 *nelements = 0;
1931
1932 /*
1933 for (v = VisualInfoList; v; v = v->next) {
1934 if (v->dpy == dpy && v->screen == screen)
1935 ++*nelements;
1936 }
1937
1938 if (*nelements)
1939 pGLXFBConfigs = crAlloc(*nelements * sizeof(GLXFBConfig));
1940
1941 for (v = VisualInfoList; v && i<*nelements; v = v->next) {
1942 if (v->dpy == dpy && v->screen == screen)
1943 pGLXFBConfigs[i++] = (GLXFBConfig) v->visualid;
1944 }
1945 */
1946
1947 /*@todo doesn't really list all the common visuals, have to use some static list*/
1948 searchvis.screen = screen;
1949 XLOCK(dpy);
1950 pVisuals = XGetVisualInfo(dpy, VisualScreenMask, &searchvis, nelements);
1951 XUNLOCK(dpy);
1952
1953 if (*nelements)
1954 pGLXFBConfigs = crAlloc(*nelements * sizeof(GLXFBConfig));
1955
1956 for (i=0; i<*nelements; ++i)
1957 {
1958 pGLXFBConfigs[i] = (GLXFBConfig) pVisuals[i].visualid;
1959 }
1960
1961 XFree(pVisuals);
1962
1963 crDebug("glXGetFBConfigs returned %i configs", *nelements);
1964 for (i=0; i<*nelements; ++i)
1965 {
1966 crDebug("glXGetFBConfigs[%i]=%p", i, pGLXFBConfigs[i]);
1967 }
1968 return pGLXFBConfigs;
1969}
1970#else /* not 0 */
1971DECLEXPORT(GLXFBConfig *) VBOXGLXTAG(glXGetFBConfigs)(Display *dpy, int screen, int *nelements)
1972{
1973 int i;
1974
1975 GLXFBConfig *pGLXFBConfigs = crAlloc(sizeof(GLXFBConfig));
1976
1977 *nelements = 1;
1978 XLOCK(dpy);
1979 *pGLXFBConfigs = (GLXFBConfig) XVisualIDFromVisual(DefaultVisual(dpy, screen));
1980 XUNLOCK(dpy);
1981
1982 crDebug("glXGetFBConfigs returned %i configs", *nelements);
1983 for (i=0; i<*nelements; ++i)
1984 {
1985 crDebug("glXGetFBConfigs[%i]=0x%x", i, (unsigned int) pGLXFBConfigs[i]);
1986 }
1987 return pGLXFBConfigs;
1988}
1989#endif
1990
1991DECLEXPORT(void) VBOXGLXTAG(glXGetSelectedEvent)(Display *dpy, GLXDrawable draw, unsigned long *event_mask)
1992{
1993 (void) dpy;
1994 (void) draw;
1995 (void) event_mask;
1996 crWarning("glXGetSelectedEvent not implemented by Chromium");
1997}
1998
1999DECLEXPORT(XVisualInfo *) VBOXGLXTAG(glXGetVisualFromFBConfig)(Display *dpy, GLXFBConfig config)
2000{
2001 (void) dpy;
2002 (void) config;
2003
2004 struct VisualInfo *v;
2005
2006 /*
2007 for (v = VisualInfoList; v; v = v->next) {
2008 if (v->dpy == dpy && v->visualid == (VisualID)config)
2009 {
2010 XVisualInfo temp, *pret;
2011 int nret;
2012
2013 temp.visualid = v->visualid;
2014 pret = XGetVisualInfo(dpy, VisualIDMask, &temp, &nret);
2015
2016 if (nret!=1) crWarning("XGetVisualInfo returned %i visuals", nret);
2017 crDebug("glXGetVisualFromFBConfig(cfg/visid==0x%x): depth=%i", (int) config, pret->depth);
2018 return pret;
2019 }
2020 }
2021 */
2022 {
2023 XVisualInfo temp, *pret;
2024 int nret;
2025
2026 temp.visualid = (VisualID)config;
2027 XLOCK(dpy);
2028 pret = XGetVisualInfo(dpy, VisualIDMask, &temp, &nret);
2029 XUNLOCK(dpy);
2030
2031 if (nret!=1)
2032 {
2033 crWarning("XGetVisualInfo returned %i visuals for %p", nret, config);
2034 /* Hack for glut based apps.
2035 We fail to patch first call to glXChooseFBConfigSGIX, which ends up in the mesa's fbconfigs being passed to this function later.
2036 */
2037 if (!nret && config)
2038 {
2039 temp.visualid = (VisualID) ((__GLcontextModes*)config)->visualID;
2040 XLOCK(dpy);
2041 pret = XGetVisualInfo(dpy, VisualIDMask, &temp, &nret);
2042 XUNLOCK(dpy);
2043 crWarning("Retry with %#x returned %i visuals", ((__GLcontextModes*)config)->visualID, nret);
2044 }
2045 }
2046 //crDebug("glXGetVisualFromFBConfig(cfg/visid==0x%x): depth=%i", (int) config, pret->depth);
2047//crDebug("here");
2048 return pret;
2049 }
2050
2051 crDebug("glXGetVisualFromFBConfig unknown fbconfig %p", config);
2052 return NULL;
2053}
2054
2055DECLEXPORT(Bool) VBOXGLXTAG(glXMakeContextCurrent)(Display *display, GLXDrawable draw, GLXDrawable read, GLXContext ctx)
2056{
2057 currentReadDrawable = read;
2058 return VBOXGLXTAG(glXMakeCurrent)(display, draw, ctx);
2059}
2060
2061DECLEXPORT(int) VBOXGLXTAG(glXQueryContext)(Display *dpy, GLXContext ctx, int attribute, int *value)
2062{
2063 (void) dpy;
2064 (void) ctx;
2065 (void) attribute;
2066 (void) value;
2067 crWarning("glXQueryContext not implemented by Chromium");
2068 return 0;
2069}
2070
2071DECLEXPORT(void) VBOXGLXTAG(glXQueryDrawable)(Display *dpy, GLXDrawable draw, int attribute, unsigned int *value)
2072{
2073 (void) dpy;
2074 (void) draw;
2075 (void) attribute;
2076 (void) value;
2077 crWarning("glXQueryDrawable not implemented by Chromium");
2078}
2079
2080DECLEXPORT(void) VBOXGLXTAG(glXSelectEvent)(Display *dpy, GLXDrawable draw, unsigned long event_mask)
2081{
2082 (void) dpy;
2083 (void) draw;
2084 (void) event_mask;
2085 crWarning("glXSelectEvent not implemented by Chromium");
2086}
2087
2088#ifdef CR_EXT_texture_from_pixmap
2089/*typedef struct
2090{
2091 int x, y;
2092 unsigned int w, h, border, depth;
2093 Window root;
2094 void *data;
2095} pminfo;*/
2096
2097static void stubInitXSharedMemory(Display *dpy)
2098{
2099 int vma, vmi;
2100 Bool pixmaps;
2101
2102 if (stub.bShmInitFailed || stub.xshmSI.shmid>=0)
2103 return;
2104
2105 stub.bShmInitFailed = GL_TRUE;
2106
2107 /* Check for extension and pixmaps format */
2108 XLOCK(dpy);
2109 if (!XShmQueryExtension(dpy))
2110 {
2111 crWarning("No XSHM extension");
2112 XUNLOCK(dpy);
2113 return;
2114 }
2115
2116 if (!XShmQueryVersion(dpy, &vma, &vmi, &pixmaps) || !pixmaps)
2117 {
2118 crWarning("XSHM extension doesn't support pixmaps");
2119 XUNLOCK(dpy);
2120 return;
2121 }
2122
2123 if (XShmPixmapFormat(dpy)!=ZPixmap)
2124 {
2125 crWarning("XSHM extension doesn't support ZPixmap format");
2126 XUNLOCK(dpy);
2127 return;
2128 }
2129 XUNLOCK(dpy);
2130
2131 /* Alloc shared memory, so far using hardcoded value...could fail for bigger displays one day */
2132 stub.xshmSI.readOnly = false;
2133 stub.xshmSI.shmid = shmget(IPC_PRIVATE, 4*4096*2048, IPC_CREAT | 0600);
2134 if (stub.xshmSI.shmid<0)
2135 {
2136 crWarning("XSHM Failed to create shared segment");
2137 return;
2138 }
2139
2140 stub.xshmSI.shmaddr = (char*) shmat(stub.xshmSI.shmid, NULL, 0);
2141 if (stub.xshmSI.shmaddr==(void*)-1)
2142 {
2143 crWarning("XSHM Failed to attach shared segment");
2144 shmctl(stub.xshmSI.shmid, IPC_RMID, 0);
2145 return;
2146 }
2147
2148 XLOCK(dpy);
2149 if (!XShmAttach(dpy, &stub.xshmSI))
2150 {
2151 crWarning("XSHM Failed to attach shared segment to XServer");
2152 shmctl(stub.xshmSI.shmid, IPC_RMID, 0);
2153 shmdt(stub.xshmSI.shmaddr);
2154 XUNLOCK(dpy);
2155 return;
2156 }
2157 XUNLOCK(dpy);
2158
2159 stub.bShmInitFailed = GL_FALSE;
2160 crInfo("Using XSHM for GLX_EXT_texture_from_pixmap");
2161
2162 /*Anyway mark to be deleted when our process detaches it, in case of segfault etc*/
2163
2164/* Ramshankar: Solaris compiz fix */
2165#ifndef RT_OS_SOLARIS
2166 shmctl(stub.xshmSI.shmid, IPC_RMID, 0);
2167#endif
2168}
2169
2170static void stubInitXDamageExtension(ContextInfo *pContext)
2171{
2172 int erb, vma, vmi;
2173
2174 CRASSERT(pContext);
2175
2176 if (pContext->damageInitFailed || pContext->damageDpy)
2177 return;
2178
2179 pContext->damageInitFailed = True;
2180
2181 /* Open second xserver connection to make sure we'd receive all the xdamage messages
2182 * and those wouldn't be eaten by application even queue */
2183 pContext->damageDpy = XOpenDisplay(DisplayString(pContext->dpy));
2184
2185 if (!pContext->damageDpy)
2186 {
2187 crWarning("XDamage: Can't connect to display %s", DisplayString(pContext->dpy));
2188 return;
2189 }
2190
2191 if (!XDamageQueryExtension(pContext->damageDpy, &pContext->damageEventsBase, &erb)
2192 || !XDamageQueryVersion(pContext->damageDpy, &vma, &vmi))
2193 {
2194 crWarning("XDamage not found or old version (%i.%i), going to run *very* slow", vma, vmi);
2195 XCloseDisplay(pContext->damageDpy);
2196 pContext->damageDpy = NULL;
2197 return;
2198 }
2199
2200 crDebug("XDamage %i.%i", vma, vmi);
2201 pContext->damageInitFailed = False;
2202}
2203
2204static void stubCheckXDamageCB(unsigned long key, void *data1, void *data2)
2205{
2206 GLX_Pixmap_t *pGlxPixmap = (GLX_Pixmap_t *) data1;
2207 XDamageNotifyEvent *e = (XDamageNotifyEvent *) data2;
2208
2209 if (pGlxPixmap->hDamage==e->damage)
2210 {
2211 /*crDebug("Event: Damage for pixmap 0x%lx(drawable 0x%x), handle 0x%x (level=%i) [%i,%i,%i,%i]",
2212 key, (unsigned int) e->drawable, (unsigned int) e->damage, (int) e->level,
2213 e->area.x, e->area.y, e->area.width, e->area.height);*/
2214
2215 if (pGlxPixmap->pDamageRegion)
2216 {
2217 /* If it's dirty and regions are empty, it marked for full update, so do nothing.*/
2218 if (!pGlxPixmap->bPixmapImageDirty || !XEmptyRegion(pGlxPixmap->pDamageRegion))
2219 {
2220 if (CR_MAX_DAMAGE_REGIONS_TRACKED <= pGlxPixmap->pDamageRegion->numRects)
2221 {
2222 /* Mark for full update */
2223 EMPTY_REGION(pGlxPixmap->pDamageRegion);
2224 }
2225 else
2226 {
2227 /* Add to damage regions */
2228 XUnionRectWithRegion(&e->area, pGlxPixmap->pDamageRegion, pGlxPixmap->pDamageRegion);
2229 }
2230 }
2231 }
2232
2233 pGlxPixmap->bPixmapImageDirty = True;
2234 }
2235}
2236
2237static const CRPixelPackState defaultPacking =
2238{
2239 0, /*rowLength*/
2240 0, /*skipRows*/
2241 0, /*skipPixels*/
2242 1, /*alignment*/
2243 0, /*imageHeight*/
2244 0, /*skipImages*/
2245 GL_FALSE, /*swapBytes*/
2246 GL_FALSE /*lsbFirst*/
2247};
2248
2249static void stubGetUnpackState(CRPixelPackState *pUnpackState)
2250{
2251 stub.spu->dispatch_table.GetIntegerv(GL_UNPACK_ROW_LENGTH, &pUnpackState->rowLength);
2252 stub.spu->dispatch_table.GetIntegerv(GL_UNPACK_SKIP_ROWS, &pUnpackState->skipRows);
2253 stub.spu->dispatch_table.GetIntegerv(GL_UNPACK_SKIP_PIXELS, &pUnpackState->skipPixels);
2254 stub.spu->dispatch_table.GetIntegerv(GL_UNPACK_ALIGNMENT, &pUnpackState->alignment);
2255 stub.spu->dispatch_table.GetBooleanv(GL_UNPACK_SWAP_BYTES, &pUnpackState->swapBytes);
2256 stub.spu->dispatch_table.GetBooleanv(GL_UNPACK_LSB_FIRST, &pUnpackState->psLSBFirst);
2257}
2258
2259static void stubSetUnpackState(const CRPixelPackState *pUnpackState)
2260{
2261 stub.spu->dispatch_table.PixelStorei(GL_UNPACK_ROW_LENGTH, pUnpackState->rowLength);
2262 stub.spu->dispatch_table.PixelStorei(GL_UNPACK_SKIP_ROWS, pUnpackState->skipRows);
2263 stub.spu->dispatch_table.PixelStorei(GL_UNPACK_SKIP_PIXELS, pUnpackState->skipPixels);
2264 stub.spu->dispatch_table.PixelStorei(GL_UNPACK_ALIGNMENT, pUnpackState->alignment);
2265 stub.spu->dispatch_table.PixelStorei(GL_UNPACK_SWAP_BYTES, pUnpackState->swapBytes);
2266 stub.spu->dispatch_table.PixelStorei(GL_UNPACK_LSB_FIRST, pUnpackState->psLSBFirst);
2267}
2268
2269static GLX_Pixmap_t* stubInitGlxPixmap(GLX_Pixmap_t* pCreateInfoPixmap, Display *dpy, GLXDrawable draw, ContextInfo *pContext)
2270{
2271 int x, y;
2272 unsigned int w, h;
2273 unsigned int border;
2274 unsigned int depth;
2275 Window root;
2276 GLX_Pixmap_t *pGlxPixmap;
2277
2278 CRASSERT(pContext && pCreateInfoPixmap);
2279
2280 XLOCK(dpy);
2281 if (!XGetGeometry(dpy, (Pixmap)draw, &root, &x, &y, &w, &h, &border, &depth))
2282 {
2283 XSync(dpy, False);
2284 if (!XGetGeometry(dpy, (Pixmap)draw, &root, &x, &y, &w, &h, &border, &depth))
2285 {
2286 crWarning("stubInitGlxPixmap failed in call to XGetGeometry for 0x%x", (int) draw);
2287 XUNLOCK(dpy);
2288 return NULL;
2289 }
2290 }
2291
2292 pGlxPixmap = crAlloc(sizeof(GLX_Pixmap_t));
2293 if (!pGlxPixmap)
2294 {
2295 crWarning("stubInitGlxPixmap failed to allocate memory");
2296 XUNLOCK(dpy);
2297 return NULL;
2298 }
2299
2300 pGlxPixmap->x = x;
2301 pGlxPixmap->y = y;
2302 pGlxPixmap->w = w;
2303 pGlxPixmap->h = h;
2304 pGlxPixmap->border = border;
2305 pGlxPixmap->depth = depth;
2306 pGlxPixmap->root = root;
2307 pGlxPixmap->format = pCreateInfoPixmap->format;
2308 pGlxPixmap->target = pCreateInfoPixmap->target;
2309
2310 /* Try to allocate shared memory
2311 * As we're allocating huge chunk of memory, do it in this function, only if this extension is really used
2312 */
2313 if (!stub.bShmInitFailed && stub.xshmSI.shmid<0)
2314 {
2315 stubInitXSharedMemory(dpy);
2316 }
2317
2318 if (stub.xshmSI.shmid>=0)
2319 {
2320 XGCValues xgcv;
2321 xgcv.graphics_exposures = False;
2322 xgcv.subwindow_mode = IncludeInferiors;
2323 pGlxPixmap->gc = XCreateGC(dpy, (Pixmap)draw, GCGraphicsExposures|GCSubwindowMode, &xgcv);
2324
2325 pGlxPixmap->hShmPixmap = XShmCreatePixmap(dpy, pGlxPixmap->root, stub.xshmSI.shmaddr, &stub.xshmSI,
2326 pGlxPixmap->w, pGlxPixmap->h, pGlxPixmap->depth);
2327 }
2328 else
2329 {
2330 pGlxPixmap->gc = NULL;
2331 pGlxPixmap->hShmPixmap = 0;
2332 }
2333 XUNLOCK(dpy);
2334
2335 stubInitXDamageExtension(pContext);
2336
2337 /* If there's damage extension, then get handle for damage events related to this pixmap */
2338 if (pContext->damageDpy)
2339 {
2340 pGlxPixmap->hDamage = XDamageCreate(pContext->damageDpy, (Pixmap)draw, XDamageReportRawRectangles);
2341 /*crDebug("Create: Damage for drawable 0x%x, handle 0x%x (level=%i)",
2342 (unsigned int) draw, (unsigned int) pGlxPixmap->damage, (int) XDamageReportRawRectangles);*/
2343 pGlxPixmap->pDamageRegion = XCreateRegion();
2344 if (!pGlxPixmap->pDamageRegion)
2345 {
2346 crWarning("stubInitGlxPixmap failed to create empty damage region for drawable 0x%x", (unsigned int) draw);
2347 }
2348
2349 /*We have never seen this pixmap before, so mark it as dirty for first use*/
2350 pGlxPixmap->bPixmapImageDirty = True;
2351 }
2352 else
2353 {
2354 pGlxPixmap->hDamage = 0;
2355 pGlxPixmap->pDamageRegion = NULL;
2356 }
2357
2358 /* glTexSubImage2D generates GL_INVALID_OP if texture array hasn't been defined by a call to glTexImage2D first.
2359 * It's fine for small textures which would be updated in stubXshmUpdateWholeImage, but we'd never call glTexImage2D for big ones.
2360 * Note that we're making empty texture by passing NULL as pixels pointer, so there's no overhead transferring data to host.*/
2361 if (CR_MAX_TRANSFER_SIZE < 4*pGlxPixmap->w*pGlxPixmap->h)
2362 {
2363 stub.spu->dispatch_table.TexImage2D(pGlxPixmap->target, 0, pGlxPixmap->format, pGlxPixmap->w, pGlxPixmap->h, 0,
2364 GL_BGRA, GL_UNSIGNED_BYTE, NULL);
2365 }
2366
2367 crHashtableAdd(pContext->pGLXPixmapsHash, (unsigned int) draw, pGlxPixmap);
2368 crHashtableDelete(stub.pGLXPixmapsHash, (unsigned int) draw, crFree);
2369
2370 return pGlxPixmap;
2371}
2372
2373static void stubXshmUpdateWholeImage(Display *dpy, GLXDrawable draw, GLX_Pixmap_t *pGlxPixmap)
2374{
2375 /* To limit the size of transferring buffer, split bigger texture into regions
2376 * which fit into connection buffer. Could be done in hgcm or packspu but implementation in this place allows to avoid
2377 * unnecessary memcpy.
2378 * This also workarounds guest driver failures when sending 6+mb texture buffers on linux.
2379 */
2380 if (CR_MAX_TRANSFER_SIZE < 4*pGlxPixmap->w*pGlxPixmap->h)
2381 {
2382 XRectangle rect;
2383
2384 rect.x = pGlxPixmap->x;
2385 rect.y = pGlxPixmap->y;
2386 rect.width = pGlxPixmap->w;
2387 rect.height = CR_MAX_TRANSFER_SIZE/(4*pGlxPixmap->w);
2388
2389 /*crDebug("Texture size too big, splitting in lower sized chunks. [%i,%i,%i,%i] (%i)",
2390 pGlxPixmap->x, pGlxPixmap->y, pGlxPixmap->w, pGlxPixmap->h, rect.height);*/
2391
2392 for (; (rect.y+rect.height)<=(pGlxPixmap->y+pGlxPixmap->h); rect.y+=rect.height)
2393 {
2394 stubXshmUpdateImageRect(dpy, draw, pGlxPixmap, &rect);
2395 }
2396
2397 if (rect.y!=(pGlxPixmap->y+pGlxPixmap->h))
2398 {
2399 rect.height=pGlxPixmap->h-rect.y;
2400 stubXshmUpdateImageRect(dpy, draw, pGlxPixmap, &rect);
2401 }
2402 }
2403 else
2404 {
2405 CRPixelPackState unpackState;
2406
2407 XLOCK(dpy);
2408 XCopyArea(dpy, (Pixmap)draw, pGlxPixmap->hShmPixmap, pGlxPixmap->gc,
2409 pGlxPixmap->x, pGlxPixmap->y, pGlxPixmap->w, pGlxPixmap->h, 0, 0);
2410 /* Have to make sure XCopyArea is processed */
2411 XSync(dpy, False);
2412 XUNLOCK(dpy);
2413
2414 stubGetUnpackState(&unpackState);
2415 stubSetUnpackState(&defaultPacking);
2416 stub.spu->dispatch_table.TexImage2D(pGlxPixmap->target, 0, pGlxPixmap->format, pGlxPixmap->w, pGlxPixmap->h, 0,
2417 GL_BGRA, GL_UNSIGNED_BYTE, stub.xshmSI.shmaddr);
2418 stubSetUnpackState(&unpackState);
2419 /*crDebug("Sync texture for drawable 0x%x(dmg handle 0x%x) [%i,%i,%i,%i]",
2420 (unsigned int) draw, (unsigned int)pGlxPixmap->hDamage,
2421 pGlxPixmap->x, pGlxPixmap->y, pGlxPixmap->w, pGlxPixmap->h);*/
2422 }
2423}
2424
2425static void stubXshmUpdateImageRect(Display *dpy, GLXDrawable draw, GLX_Pixmap_t *pGlxPixmap, XRectangle *pRect)
2426{
2427 /* See comment in stubXshmUpdateWholeImage */
2428 if (CR_MAX_TRANSFER_SIZE < 4*pRect->width*pRect->height)
2429 {
2430 XRectangle rect;
2431
2432 rect.x = pRect->x;
2433 rect.y = pRect->y;
2434 rect.width = pRect->width;
2435 rect.height = CR_MAX_TRANSFER_SIZE/(4*pRect->width);
2436
2437 /*crDebug("Region size too big, splitting in lower sized chunks. [%i,%i,%i,%i] (%i)",
2438 pRect->x, pRect->y, pRect->width, pRect->height, rect.height);*/
2439
2440 for (; (rect.y+rect.height)<=(pRect->y+pRect->height); rect.y+=rect.height)
2441 {
2442 stubXshmUpdateImageRect(dpy, draw, pGlxPixmap, &rect);
2443 }
2444
2445 if (rect.y!=(pRect->y+pRect->height))
2446 {
2447 rect.height=pRect->y+pRect->height-rect.y;
2448 stubXshmUpdateImageRect(dpy, draw, pGlxPixmap, &rect);
2449 }
2450 }
2451 else
2452 {
2453 CRPixelPackState unpackState;
2454
2455 XLOCK(dpy);
2456 XCopyArea(dpy, (Pixmap)draw, pGlxPixmap->hShmPixmap, pGlxPixmap->gc,
2457 pRect->x, pRect->y, pRect->width, pRect->height, 0, 0);
2458 /* Have to make sure XCopyArea is processed */
2459 XSync(dpy, False);
2460 XUNLOCK(dpy);
2461
2462 stubGetUnpackState(&unpackState);
2463 stubSetUnpackState(&defaultPacking);
2464 if (pRect->width!=pGlxPixmap->w)
2465 {
2466 stub.spu->dispatch_table.PixelStorei(GL_UNPACK_ROW_LENGTH, pGlxPixmap->w);
2467 }
2468 stub.spu->dispatch_table.TexSubImage2D(pGlxPixmap->target, 0, pRect->x, pRect->y, pRect->width, pRect->height,
2469 GL_BGRA, GL_UNSIGNED_BYTE, stub.xshmSI.shmaddr);
2470 stubSetUnpackState(&unpackState);
2471
2472 /*crDebug("Region sync texture for drawable 0x%x(dmg handle 0x%x) [%i,%i,%i,%i]",
2473 (unsigned int) draw, (unsigned int)pGlxPixmap->hDamage,
2474 pRect->x, pRect->y, pRect->width, pRect->height);*/
2475 }
2476}
2477
2478#if 0
2479Bool checkevents(Display *display, XEvent *event, XPointer arg)
2480{
2481 //crDebug("got type: 0x%x", event->type);
2482 if (event->type==damage_evb+XDamageNotify)
2483 {
2484 ContextInfo *context = stubGetCurrentContext();
2485 XDamageNotifyEvent *e = (XDamageNotifyEvent *) event;
2486 /* we're interested in pixmaps only...and those have e->drawable set to 0 or other strange value for some odd reason
2487 * so have to walk glxpixmaps hashtable to find if we have damage event handle assigned to some pixmap
2488 */
2489 /*crDebug("Event: Damage for drawable 0x%x, handle 0x%x (level=%i) [%i,%i,%i,%i]",
2490 (unsigned int) e->drawable, (unsigned int) e->damage, (int) e->level,
2491 e->area.x, e->area.y, e->area.width, e->area.height);*/
2492 CRASSERT(context);
2493 crHashtableWalk(context->pGLXPixmapsHash, checkdamageCB, e);
2494 }
2495 return False;
2496}
2497#endif
2498
2499/*@todo check what error codes could we throw for failures here*/
2500DECLEXPORT(void) VBOXGLXTAG(glXBindTexImageEXT)(Display *dpy, GLXDrawable draw, int buffer, const int *attrib_list)
2501{
2502 static int cnt=0;
2503 XImage dummyimg;
2504 ContextInfo *context = stubGetCurrentContext();
2505
2506 GLX_Pixmap_t *pGlxPixmap;
2507
2508 if (!context)
2509 {
2510 crWarning("glXBindTexImageEXT called without current context");
2511 return;
2512 }
2513
2514 pGlxPixmap = (GLX_Pixmap_t *) crHashtableSearch(context->pGLXPixmapsHash, (unsigned int) draw);
2515 if (!pGlxPixmap)
2516 {
2517 pGlxPixmap = (GLX_Pixmap_t *) crHashtableSearch(stub.pGLXPixmapsHash, (unsigned int) draw);
2518 if (!pGlxPixmap)
2519 {
2520 crDebug("Unknown drawable 0x%x in glXBindTexImageEXT!", (unsigned int) draw);
2521 return;
2522 }
2523 pGlxPixmap = stubInitGlxPixmap(pGlxPixmap, dpy, draw, context);
2524 if (!pGlxPixmap)
2525 {
2526 crDebug("glXBindTexImageEXT failed to get pGlxPixmap");
2527 return;
2528 }
2529 }
2530
2531 /* If there's damage extension, then process incoming events as we need the information right now */
2532 if (context->damageDpy)
2533 {
2534 /* Sync connections, note that order of syncs is important here.
2535 * First make sure client commands are finished, then make sure we get all the damage events back*/
2536 XLOCK(dpy);
2537 XSync(dpy, False);
2538 XUNLOCK(dpy);
2539 XSync(context->damageDpy, False);
2540
2541 while (XPending(context->damageDpy))
2542 {
2543 XEvent event;
2544 XNextEvent(context->damageDpy, &event);
2545 if (event.type==context->damageEventsBase+XDamageNotify)
2546 {
2547 crHashtableWalk(context->pGLXPixmapsHash, stubCheckXDamageCB, &event);
2548 }
2549 }
2550 }
2551
2552 /* No shared memory? Rollback to use slow x protocol then */
2553 if (stub.xshmSI.shmid<0)
2554 {
2555 /*@todo add damage support here too*/
2556 XImage *pxim;
2557 CRPixelPackState unpackState;
2558
2559 XLOCK(dpy);
2560 pxim = XGetImage(dpy, (Pixmap)draw, pGlxPixmap->x, pGlxPixmap->y, pGlxPixmap->w, pGlxPixmap->h, AllPlanes, ZPixmap);
2561 XUNLOCK(dpy);
2562 /*if (pxim)
2563 {
2564 if (!ptextable)
2565 {
2566 ptextable = crAllocHashtable();
2567 }
2568 pm = crHashtableSearch(ptextable, (unsigned int) draw);
2569 if (!pm)
2570 {
2571 pm = crCalloc(sizeof(pminfo));
2572 crHashtableAdd(ptextable, (unsigned int) draw, pm);
2573 }
2574 pm->w = w;
2575 pm->h = h;
2576 if (pm->data) crFree(pm->data);
2577 pm->data = crAlloc(4*w*h);
2578 crMemcpy(pm->data, (void*)(&(pxim->data[0])), 4*w*h);
2579 }*/
2580
2581 if (NULL==pxim)
2582 {
2583 crWarning("Failed, to get pixmap data for 0x%x", (unsigned int) draw);
2584 return;
2585 }
2586
2587 stubGetUnpackState(&unpackState);
2588 stubSetUnpackState(&defaultPacking);
2589 stub.spu->dispatch_table.TexImage2D(pGlxPixmap->target, 0, pGlxPixmap->format, pxim->width, pxim->height, 0,
2590 GL_BGRA, GL_UNSIGNED_BYTE, (void*)(&(pxim->data[0])));
2591 stubSetUnpackState(&unpackState);
2592 XDestroyImage(pxim);
2593 }
2594 else /* Use shm to get pixmap data */
2595 {
2596 /* Check if we have damage extension */
2597 if (context->damageDpy)
2598 {
2599 if (pGlxPixmap->bPixmapImageDirty)
2600 {
2601 /* Either we failed to allocate damage region or this pixmap is marked for full update */
2602 if (!pGlxPixmap->pDamageRegion || XEmptyRegion(pGlxPixmap->pDamageRegion))
2603 {
2604 /*crDebug("**FULL** update for 0x%x", (unsigned int)draw);*/
2605 stubXshmUpdateWholeImage(dpy, draw, pGlxPixmap);
2606 }
2607 else
2608 {
2609 long fullArea, damageArea=0, clipdamageArea, i;
2610 XRectangle damageClipBox;
2611
2612 fullArea = pGlxPixmap->w * pGlxPixmap->h;
2613 XClipBox(pGlxPixmap->pDamageRegion, &damageClipBox);
2614 clipdamageArea = damageClipBox.width * damageClipBox.height;
2615
2616 //crDebug("FullSize [%i,%i,%i,%i]", pGlxPixmap->x, pGlxPixmap->y, pGlxPixmap->w, pGlxPixmap->h);
2617 //crDebug("Clip [%i,%i,%i,%i]", damageClipBox.x, damageClipBox.y, damageClipBox.width, damageClipBox.height);
2618
2619 for (i=0; i<pGlxPixmap->pDamageRegion->numRects; ++i)
2620 {
2621 BoxPtr pBox = &pGlxPixmap->pDamageRegion->rects[i];
2622 damageArea += (pBox->x2-pBox->x1)*(pBox->y2-pBox->y1);
2623 //crDebug("Damage rect [%i,%i,%i,%i]", pBox->x1, pBox->y1, pBox->x2, pBox->y2);
2624 }
2625
2626 if (damageArea>clipdamageArea || clipdamageArea>fullArea)
2627 {
2628 crWarning("glXBindTexImageEXT, damage regions seems to be broken, forcing full update");
2629 /*crDebug("**FULL** update for 0x%x, numRect=%li, *FS*=%li, CS=%li, DS=%li",
2630 (unsigned int)draw, pGlxPixmap->pDamageRegion->numRects, fullArea, clipdamageArea, damageArea);*/
2631 stubXshmUpdateWholeImage(dpy, draw, pGlxPixmap);
2632 }
2633 else /*We have corect damage info*/
2634 {
2635 if (CR_MIN_DAMAGE_PROFIT_SIZE > (fullArea-damageArea))
2636 {
2637 /*crDebug("**FULL** update for 0x%x, numRect=%li, *FS*=%li, CS=%li, DS=%li",
2638 (unsigned int)draw, pGlxPixmap->pDamageRegion->numRects, fullArea, clipdamageArea, damageArea);*/
2639 stubXshmUpdateWholeImage(dpy, draw, pGlxPixmap);
2640 }
2641 else if (CR_MIN_DAMAGE_PROFIT_SIZE > (clipdamageArea-damageArea))
2642 {
2643 /*crDebug("**PARTIAL** update for 0x%x, numRect=%li, FS=%li, *CS*=%li, DS=%li",
2644 (unsigned int)draw, pGlxPixmap->pDamageRegion->numRects, fullArea, clipdamageArea, damageArea);*/
2645 stubXshmUpdateImageRect(dpy, draw, pGlxPixmap, &damageClipBox);
2646 }
2647 else
2648 {
2649 /*crDebug("**PARTIAL** update for 0x%x, numRect=*%li*, FS=%li, CS=%li, *DS*=%li",
2650 (unsigned int)draw, pGlxPixmap->pDamageRegion->numRects, fullArea, clipdamageArea, damageArea);*/
2651 for (i=0; i<pGlxPixmap->pDamageRegion->numRects; ++i)
2652 {
2653 XRectangle rect;
2654 BoxPtr pBox = &pGlxPixmap->pDamageRegion->rects[i];
2655
2656 rect.x = pBox->x1;
2657 rect.y = pBox->y1;
2658 rect.width = pBox->x2-pBox->x1;
2659 rect.height = pBox->y2-pBox->y1;
2660
2661 stubXshmUpdateImageRect(dpy, draw, pGlxPixmap, &rect);
2662 }
2663 }
2664 }
2665 }
2666
2667 /* Clean dirty flag and damage region */
2668 pGlxPixmap->bPixmapImageDirty = False;
2669 if (pGlxPixmap->pDamageRegion)
2670 EMPTY_REGION(pGlxPixmap->pDamageRegion);
2671 }
2672 }
2673 else
2674 {
2675 stubXshmUpdateWholeImage(dpy, draw, pGlxPixmap);
2676 }
2677 }
2678}
2679
2680DECLEXPORT(void) VBOXGLXTAG(glXReleaseTexImageEXT)(Display *dpy, GLXDrawable draw, int buffer)
2681{
2682 (void) dpy;
2683 (void) draw;
2684 (void) buffer;
2685 //crDebug("glXReleaseTexImageEXT 0x%x", (unsigned int)draw);
2686}
2687#endif
2688
2689#endif /* GLX_EXTRAS */
2690
2691
2692#ifdef GLX_SGIX_video_resize
2693/* more dummy funcs. These help when linking with older GLUTs */
2694
2695DECLEXPORT(int) VBOXGLXTAG(glXBindChannelToWindowSGIX)(Display *dpy, int scrn, int chan, Window w)
2696{
2697 (void) dpy;
2698 (void) scrn;
2699 (void) chan;
2700 (void) w;
2701 crDebug("glXBindChannelToWindowSGIX");
2702 return 0;
2703}
2704
2705DECLEXPORT(int) VBOXGLXTAG(glXChannelRectSGIX)(Display *dpy, int scrn, int chan, int x , int y, int w, int h)
2706{
2707 (void) dpy;
2708 (void) scrn;
2709 (void) chan;
2710 (void) x;
2711 (void) y;
2712 (void) w;
2713 (void) h;
2714 crDebug("glXChannelRectSGIX");
2715 return 0;
2716}
2717
2718DECLEXPORT(int) VBOXGLXTAG(glXQueryChannelRectSGIX)(Display *dpy, int scrn, int chan, int *x, int *y, int *w, int *h)
2719{
2720 (void) dpy;
2721 (void) scrn;
2722 (void) chan;
2723 (void) x;
2724 (void) y;
2725 (void) w;
2726 (void) h;
2727 crDebug("glXQueryChannelRectSGIX");
2728 return 0;
2729}
2730
2731DECLEXPORT(int) VBOXGLXTAG(glXQueryChannelDeltasSGIX)(Display *dpy, int scrn, int chan, int *dx, int *dy, int *dw, int *dh)
2732{
2733 (void) dpy;
2734 (void) scrn;
2735 (void) chan;
2736 (void) dx;
2737 (void) dy;
2738 (void) dw;
2739 (void) dh;
2740 crDebug("glXQueryChannelDeltasSGIX");
2741 return 0;
2742}
2743
2744DECLEXPORT(int) VBOXGLXTAG(glXChannelRectSyncSGIX)(Display *dpy, int scrn, int chan, GLenum synctype)
2745{
2746 (void) dpy;
2747 (void) scrn;
2748 (void) chan;
2749 (void) synctype;
2750 crDebug("glXChannelRectSyncSGIX");
2751 return 0;
2752}
2753
2754#endif /* GLX_SGIX_video_resize */
2755
2756#ifdef VBOXOGL_FAKEDRI
2757DECLEXPORT(const char *) VBOXGLXTAG(glXGetDriverConfig)(const char *driverName)
2758{
2759 return NULL;
2760}
2761
2762DECLEXPORT(void) VBOXGLXTAG(glXFreeMemoryMESA)(Display *dpy, int scrn, void *pointer)
2763{
2764 (void) dpy;
2765 (void) scrn;
2766 (void) pointer;
2767}
2768
2769DECLEXPORT(GLXContext) VBOXGLXTAG(glXImportContextEXT)(Display *dpy, GLXContextID contextID)
2770{
2771 (void) dpy;
2772 (void) contextID;
2773 return NULL;
2774}
2775
2776DECLEXPORT(GLXContextID) VBOXGLXTAG(glXGetContextIDEXT)(const GLXContext ctx)
2777{
2778 (void) ctx;
2779 return 0;
2780}
2781
2782DECLEXPORT(Bool) VBOXGLXTAG(glXMakeCurrentReadSGI)(Display *display, GLXDrawable draw, GLXDrawable read, GLXContext ctx)
2783{
2784 return VBOXGLXTAG(glXMakeContextCurrent)(display, draw, read, ctx);
2785}
2786
2787DECLEXPORT(const char *) VBOXGLXTAG(glXGetScreenDriver)(Display *dpy, int scrNum)
2788{
2789 static char *screendriver = "vboxvideo";
2790 return screendriver;
2791}
2792
2793DECLEXPORT(Display *) VBOXGLXTAG(glXGetCurrentDisplayEXT)(void)
2794{
2795 return VBOXGLXTAG(glXGetCurrentDisplay());
2796}
2797
2798DECLEXPORT(void) VBOXGLXTAG(glXFreeContextEXT)(Display *dpy, GLXContext ctx)
2799{
2800 VBOXGLXTAG(glXDestroyContext(dpy, ctx));
2801}
2802
2803/*Mesa internal*/
2804DECLEXPORT(int) VBOXGLXTAG(glXQueryContextInfoEXT)(Display *dpy, GLXContext ctx)
2805{
2806 (void) dpy;
2807 (void) ctx;
2808 return 0;
2809}
2810
2811DECLEXPORT(void *) VBOXGLXTAG(glXAllocateMemoryMESA)(Display *dpy, int scrn,
2812 size_t size, float readFreq,
2813 float writeFreq, float priority)
2814{
2815 (void) dpy;
2816 (void) scrn;
2817 (void) size;
2818 (void) readFreq;
2819 (void) writeFreq;
2820 (void) priority;
2821 return NULL;
2822}
2823
2824DECLEXPORT(GLuint) VBOXGLXTAG(glXGetMemoryOffsetMESA)(Display *dpy, int scrn, const void *pointer)
2825{
2826 (void) dpy;
2827 (void) scrn;
2828 (void) pointer;
2829 return 0;
2830}
2831
2832DECLEXPORT(GLXPixmap) VBOXGLXTAG(glXCreateGLXPixmapMESA)(Display *dpy, XVisualInfo *visual, Pixmap pixmap, Colormap cmap)
2833{
2834 (void) dpy;
2835 (void) visual;
2836 (void) pixmap;
2837 (void) cmap;
2838 return 0;
2839}
2840
2841#endif /*VBOXOGL_FAKEDRI*/
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette