VirtualBox

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

Last change on this file since 63206 was 63204, checked in by vboxsync, 8 years ago

GA/common/crOpenGL: warnings (gcc)

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

© 2023 Oracle
ContactPrivacy policyTerms of Use