VirtualBox

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

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

Wddm/3d: fix thread sync issues

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

© 2023 Oracle
ContactPrivacy policyTerms of Use