VirtualBox

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

Last change on this file since 65124 was 65124, checked in by vboxsync, 7 years ago

Additions: doxygen fixes

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

© 2023 Oracle
ContactPrivacy policyTerms of Use