Imported Upstream version 1.15.1
[deb_xorg-server.git] / hw / dmx / dmx_glxvisuals.c
CommitLineData
a09e091a
JB
1/*
2 * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
3 * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice including the dates of first publication and
13 * either this permission notice or a reference to
14 * http://oss.sgi.com/projects/FreeB/
15 * shall be included in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
22 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE.
24 *
25 * Except as contained in this notice, the name of Silicon Graphics, Inc.
26 * shall not be used in advertising or otherwise to promote the sale, use or
27 * other dealings in this Software without prior written authorization from
28 * Silicon Graphics, Inc.
29 */
30
31#ifdef HAVE_DMX_CONFIG_H
32#include <dmx-config.h>
33#endif
34
35#include "dmx.h"
36#include <GL/glx.h>
37#include <GL/glxproto.h>
38#include <X11/extensions/Xext.h>
39#include <X11/extensions/extutil.h>
40#include <limits.h>
41
42#include "dmx_glxvisuals.h"
43
44__GLXvisualConfig *
45GetGLXVisualConfigs(Display * dpy, int screen, int *nconfigs)
46{
47 xGLXGetVisualConfigsReq *req;
48 xGLXGetVisualConfigsReply reply;
49 __GLXvisualConfig *config, *configs;
50 GLint i, j, nvisuals, nprops;
51 INT32 *props, *p;
52 int majorOpcode, dummy;
53 int num_good_visuals;
54
55 if (!XQueryExtension(dpy, "GLX", &majorOpcode, &dummy, &dummy)) {
56 return NULL;
57 }
58
59 /* Send the glXGetVisualConfigs request */
60 LockDisplay(dpy);
61 GetReq(GLXGetVisualConfigs, req);
62 req->reqType = majorOpcode;
63 req->glxCode = X_GLXGetVisualConfigs;
64 req->screen = screen;
65 if (!_XReply(dpy, (xReply *) &reply, 0, False)) {
66 /* Something is busted. Punt. */
67 UnlockDisplay(dpy);
68 SyncHandle();
69 return NULL;
70 }
71
72 nvisuals = (int) reply.numVisuals;
73 if (!nvisuals) {
74 /* This screen does not support GL rendering */
75 UnlockDisplay(dpy);
76 SyncHandle();
77 return NULL;
78 }
79
80 /* Check number of properties per visual */
81 nprops = (int) reply.numProps;
82 if (nprops < __GLX_MIN_CONFIG_PROPS) {
83 /* Huh? Not in protocol defined limits. Punt */
84 UnlockDisplay(dpy);
85 SyncHandle();
86 return NULL;
87 }
88 if (nprops < (INT_MAX / __GLX_SIZE_CARD32))
89 props = Xmalloc(nprops * __GLX_SIZE_CARD32);
90 else
91 props = NULL;
92 if (!props) {
93 UnlockDisplay(dpy);
94 SyncHandle();
95 return NULL;
96 }
97
98 /* Allocate memory for our config structure */
99 if (nvisuals < (INT_MAX / sizeof(__GLXvisualConfig)))
100 config = Xcalloc(nvisuals, sizeof(__GLXvisualConfig));
101 else
102 config = NULL;
103 if (!config) {
104 free(props);
105 UnlockDisplay(dpy);
106 SyncHandle();
107 return NULL;
108 }
109 configs = config;
110 num_good_visuals = 0;
111
112 /* Convert config structure into our format */
113 for (i = 0; i < nvisuals; i++) {
114
115 /* Read config structure */
116 _XRead(dpy, (char *) props, (nprops * __GLX_SIZE_CARD32));
117
118 /* fill in default values */
119 config->visualRating = GLX_NONE_EXT;
120 config->transparentPixel = GLX_NONE_EXT;
121
122 /* Copy in the first set of properties */
123 config->vid = props[0];
124 config->class = props[1];
125
126 config->rgba = (Bool) props[2];
127
128 config->redSize = props[3];
129 config->greenSize = props[4];
130 config->blueSize = props[5];
131 config->alphaSize = props[6];
132
133 config->accumRedSize = props[7];
134 config->accumGreenSize = props[8];
135 config->accumBlueSize = props[9];
136 config->accumAlphaSize = props[10];
137
138 config->doubleBuffer = (Bool) props[11];
139 config->stereo = (Bool) props[12];
140
141 config->bufferSize = props[13];
142 config->depthSize = props[14];
143 config->stencilSize = props[15];
144
145 config->auxBuffers = props[16];
146 config->level = props[17];
147
148 /* Process remaining properties */
149 p = &props[18];
150 for (j = __GLX_MIN_CONFIG_PROPS; j < nprops; j += 2) {
151 int property = *p++;
152 int value = *p++;
153
154 switch (property) {
155 case GLX_SAMPLES_SGIS:
156 config->multiSampleSize = value;
157 break;
158 case GLX_SAMPLE_BUFFERS_SGIS:
159 config->nMultiSampleBuffers = value;
160 break;
161
162 case GLX_TRANSPARENT_TYPE_EXT:
163 config->transparentPixel = value;
164 break;
165 case GLX_TRANSPARENT_INDEX_VALUE_EXT:
166 config->transparentIndex = value;
167 break;
168 case GLX_TRANSPARENT_RED_VALUE_EXT:
169 config->transparentRed = value;
170 break;
171 case GLX_TRANSPARENT_GREEN_VALUE_EXT:
172 config->transparentGreen = value;
173 break;
174 case GLX_TRANSPARENT_BLUE_VALUE_EXT:
175 config->transparentBlue = value;
176 break;
177 case GLX_TRANSPARENT_ALPHA_VALUE_EXT:
178 config->transparentAlpha = value;
179 break;
180
181 case GLX_VISUAL_CAVEAT_EXT:
182 config->visualRating = value;
183 break;
184
185 /* visualSelectGroup is an internal used property */
186 case GLX_VISUAL_SELECT_GROUP_SGIX:
187 config->visualSelectGroup = value;
188 break;
189
190 default:
191 /* Ignore properties we don't recognize */
192 break;
193 }
194 } /* for j */
195
196 /*
197 // filter out overlay visuals (dmx does not support overlays)
198 */
199 if (config->level == 0) {
200 config++;
201 num_good_visuals++;
202 }
203
204 } /* for i */
205
206 UnlockDisplay(dpy);
207
208 nvisuals = num_good_visuals;
209
210 config = configs;
211 for (i = 0; i < nvisuals; i++) {
212 /* XXX hack to fill-in mask info (need a better way to do this) */
213 {
214 XVisualInfo *vis, template;
215 int n;
216
217 template.screen = screen;
218 template.visualid = config->vid;
219 vis = XGetVisualInfo(dpy, VisualScreenMask | VisualIDMask,
220 &template, &n);
221
222 if (vis != NULL) {
223 config->redMask = vis->red_mask;
224 config->greenMask = vis->green_mask;
225 config->blueMask = vis->blue_mask;
226 config->alphaMask = 0; /* XXX */
227 free(vis);
228 }
229 }
230 config++;
231 } /* for i */
232
233 XFree(props);
234 SyncHandle();
235
236 *nconfigs = nvisuals;
237 return configs;
238}
239
240__GLXFBConfig *
241GetGLXFBConfigs(Display * dpy, int glxMajorOpcode, int *nconfigs)
242{
243 xGLXGetFBConfigsReq *req;
244 xGLXGetFBConfigsReply reply;
245 __GLXFBConfig *config, *fbconfigs;
246 GLint i, j, numFBConfigs, numAttribs;
247 INT32 *attrs, *p;
248 int screen = DefaultScreen(dpy);
249 int numValidConfigs = 0;
250
251 /* Send the glXGetFBConfigs request */
252 LockDisplay(dpy);
253 GetReq(GLXGetFBConfigs, req);
254 req->reqType = glxMajorOpcode;
255 req->glxCode = X_GLXGetFBConfigs;
256 req->screen = screen;
257
258 *nconfigs = 0;
259
260 if (!_XReply(dpy, (xReply *) &reply, 0, False)) {
261 /* Something is busted. Punt. */
262 UnlockDisplay(dpy);
263 SyncHandle();
264 return NULL;
265 }
266
267 numFBConfigs = (int) reply.numFBConfigs;
268 if (!numFBConfigs) {
269 /* This screen does not support GL rendering */
270 UnlockDisplay(dpy);
271 SyncHandle();
272 return NULL;
273 }
274
275 numAttribs = (int) reply.numAttribs;
276 if (!numAttribs) {
277 UnlockDisplay(dpy);
278 SyncHandle();
279 return NULL;
280 }
281
282 if (numAttribs < (INT_MAX / (2 * __GLX_SIZE_CARD32)))
283 attrs = Xmalloc(2 * numAttribs * __GLX_SIZE_CARD32);
284 else
285 attrs = NULL;
286 if (!attrs) {
287 UnlockDisplay(dpy);
288 SyncHandle();
289 return NULL;
290 }
291
292 /* Allocate memory for our config structure */
293 if (numFBConfigs < (INT_MAX / sizeof(__GLXFBConfig)))
294 config = Xcalloc(numFBConfigs, sizeof(__GLXFBConfig));
295 else
296 config = NULL;
297 if (!config) {
298 free(attrs);
299 UnlockDisplay(dpy);
300 SyncHandle();
301 return NULL;
302 }
303 fbconfigs = config;
304
305 /* Convert attribute list into our format */
306 for (i = 0; i < numFBConfigs; i++) {
307
308 /* Fill in default properties */
309 config->transparentType = GLX_NONE_EXT;
310 config->visualCaveat = GLX_NONE_EXT;
311 config->minRed = 0.;
312 config->maxRed = 1.;
313 config->minGreen = 0.;
314 config->maxGreen = 1.;
315 config->minBlue = 0.;
316 config->maxBlue = 1.;
317 config->minAlpha = 0.;
318 config->maxAlpha = 1.;
319
320 /* Read attribute list */
321 _XRead(dpy, (char *) attrs, (2 * numAttribs * __GLX_SIZE_CARD32));
322
323 p = attrs;
324 for (j = 0; j < numAttribs; j++) {
325 int attribute = *p++;
326 int value = *p++;
327
328 switch (attribute) {
329 /* core attributes */
330 case GLX_FBCONFIG_ID:
331 config->id = value;
332 break;
333 case GLX_BUFFER_SIZE:
334 config->indexBits = value;
335 break;
336 case GLX_LEVEL:
337 config->level = value;
338 break;
339 case GLX_DOUBLEBUFFER:
340 config->doubleBufferMode = value;
341 break;
342 case GLX_STEREO:
343 config->stereoMode = value;
344 break;
345 case GLX_AUX_BUFFERS:
346 config->maxAuxBuffers = value;
347 break;
348 case GLX_RED_SIZE:
349 config->redBits = value;
350 break;
351 case GLX_GREEN_SIZE:
352 config->greenBits = value;
353 break;
354 case GLX_BLUE_SIZE:
355 config->blueBits = value;
356 break;
357 case GLX_ALPHA_SIZE:
358 config->alphaBits = value;
359 break;
360 case GLX_DEPTH_SIZE:
361 config->depthBits = value;
362 break;
363 case GLX_STENCIL_SIZE:
364 config->stencilBits = value;
365 break;
366 case GLX_ACCUM_RED_SIZE:
367 config->accumRedBits = value;
368 break;
369 case GLX_ACCUM_GREEN_SIZE:
370 config->accumGreenBits = value;
371 break;
372 case GLX_ACCUM_BLUE_SIZE:
373 config->accumBlueBits = value;
374 break;
375 case GLX_ACCUM_ALPHA_SIZE:
376 config->accumAlphaBits = value;
377 break;
378 case GLX_RENDER_TYPE:
379 config->renderType = value;
380 break;
381 case GLX_DRAWABLE_TYPE:
382 config->drawableType = value;
383 break;
384 case GLX_X_VISUAL_TYPE:
385 config->visualType = value;
386 break;
387 case GLX_CONFIG_CAVEAT:
388 config->visualCaveat = value;
389 break;
390 case GLX_TRANSPARENT_TYPE:
391 config->transparentType = value;
392 break;
393 case GLX_TRANSPARENT_INDEX_VALUE:
394 config->transparentIndex = value;
395 break;
396 case GLX_TRANSPARENT_RED_VALUE:
397 config->transparentRed = value;
398 break;
399 case GLX_TRANSPARENT_GREEN_VALUE:
400 config->transparentGreen = value;
401 break;
402 case GLX_TRANSPARENT_BLUE_VALUE:
403 config->transparentBlue = value;
404 break;
405 case GLX_TRANSPARENT_ALPHA_VALUE:
406 config->transparentAlpha = value;
407 break;
408 case GLX_MAX_PBUFFER_WIDTH:
409 config->maxPbufferWidth = value;
410 break;
411 case GLX_MAX_PBUFFER_HEIGHT:
412 config->maxPbufferHeight = value;
413 break;
414 case GLX_MAX_PBUFFER_PIXELS:
415 config->maxPbufferPixels = value;
416 break;
417 case GLX_VISUAL_ID:
418 config->associatedVisualId = value;
419 break;
420
421 /* visualSelectGroup is an internal used property */
422 case GLX_VISUAL_SELECT_GROUP_SGIX:
423 config->visualSelectGroup = value;
424 break;
425
426 /* SGIS_multisample attributes */
427 case GLX_SAMPLES_SGIS:
428 config->multiSampleSize = value;
429 break;
430 case GLX_SAMPLE_BUFFERS_SGIS:
431 config->nMultiSampleBuffers = value;
432 break;
433
434 /* SGIX_pbuffer specific attributes */
435 case GLX_OPTIMAL_PBUFFER_WIDTH_SGIX:
436 config->optimalPbufferWidth = value;
437 break;
438 case GLX_OPTIMAL_PBUFFER_HEIGHT_SGIX:
439 config->optimalPbufferHeight = value;
440 break;
441
442 default:
443 /* Ignore attributes we don't recognize */
444 break;
445 }
446 } /* for j */
447
448 /* Fill in derived values */
449 config->screen = screen;
450
451 /* The rgbMode should be true for any mode which has distinguishible
452 * R, G and B components
453 */
454 config->rgbMode = (config->renderType
455 & (GLX_RGBA_BIT | GLX_RGBA_FLOAT_BIT_ARB
456 | GLX_RGBA_UNSIGNED_FLOAT_BIT_EXT)) != 0;
457 config->colorIndexMode = !config->rgbMode;
458
459 config->haveAccumBuffer =
460 config->accumRedBits > 0 ||
461 config->accumGreenBits > 0 || config->accumBlueBits > 0;
462 /* Can't have alpha without color */
463
464 config->haveDepthBuffer = config->depthBits > 0;
465 config->haveStencilBuffer = config->stencilBits > 0;
466
467 /* overlay visuals are not valid for now */
468 if (!config->level) {
469 config++;
470 numValidConfigs++;
471 }
472
473 } /* for i */
474 UnlockDisplay(dpy);
475
476 config = fbconfigs;
477 for (i = 0; i < numValidConfigs; i++) {
478
479 /* XXX hack to fill-in mask info (need a better way to do this) */
480 if (config->associatedVisualId != 0) {
481 XVisualInfo *vis, template;
482 int n;
483
484 template.screen = screen;
485 template.visualid = config->associatedVisualId;
486 vis = XGetVisualInfo(dpy, VisualScreenMask | VisualIDMask,
487 &template, &n);
488
489 if (vis != NULL) {
490 config->redMask = (GLuint) vis->red_mask;
491 config->greenMask = (GLuint) vis->green_mask;
492 config->blueMask = (GLuint) vis->blue_mask;
493 config->alphaMask = 0; /* XXX */
494 free(vis);
495 }
496 }
497
498 config++;
499 } /* for i */
500
501 XFree(attrs);
502 SyncHandle();
503
504 *nconfigs = numValidConfigs;
505 return fbconfigs;
506}
507
508__GLXvisualConfig *
509GetGLXVisualConfigsFromFBConfigs(__GLXFBConfig * fbconfigs, int nfbconfigs,
510 XVisualInfo * visuals, int nvisuals,
511 __GLXvisualConfig * glxConfigs,
512 int nGlxConfigs, int *nconfigs)
513{
514 __GLXvisualConfig *configs = NULL;
515 int i;
516
517 if (!fbconfigs || !nfbconfigs || !nconfigs)
518 return NULL;
519 *nconfigs = 0;
520
521 /* Allocate memory for our config structure */
522 configs = (__GLXvisualConfig *)
523 Xmalloc(nfbconfigs * sizeof(__GLXvisualConfig));
524 if (!configs) {
525 return NULL;
526 }
527 memset(configs, 0, nfbconfigs * sizeof(__GLXvisualConfig));
528
529 for (i = 0; i < nfbconfigs; i++) {
530 __GLXFBConfig *fbcfg = &fbconfigs[i];
531
532 if (fbcfg->associatedVisualId > 0) {
533 __GLXvisualConfig *cfg = configs + (*nconfigs);
534 int j;
535 XVisualInfo *vinfo = NULL;
536
537 for (j = 0; j < nvisuals; j++) {
538 if (visuals[j].visualid == fbcfg->associatedVisualId) {
539 vinfo = &visuals[j];
540 break;
541 }
542 }
543 if (!vinfo)
544 continue;
545
546 /* skip 16 bit colormap visuals */
547 if (vinfo->depth == 16 &&
548 vinfo->class != TrueColor && vinfo->class != DirectColor) {
549 continue;
550 }
551
552 (*nconfigs)++;
553
554 /*
555 * if the same visualid exists in the glx configs,
556 * copy the glx attributes from the glx config
557 */
558 for (j = 0; j < nGlxConfigs; j++) {
559 if (glxConfigs[j].vid == vinfo->visualid)
560 break;
561 }
562 if (j < nGlxConfigs) {
563 memcpy(cfg, &glxConfigs[j], sizeof(__GLXvisualConfig));
564 continue;
565 }
566
567 /*
568 * make glx attributes from the FB config attributes
569 */
570 cfg->vid = fbcfg->associatedVisualId;
571 cfg->class = vinfo->class;
572 cfg->rgba = !(fbcfg->renderType & GLX_COLOR_INDEX_BIT_SGIX);
573 cfg->redSize = fbcfg->redBits;
574 cfg->greenSize = fbcfg->greenBits;
575 cfg->blueSize = fbcfg->blueBits;
576 cfg->alphaSize = fbcfg->alphaBits;
577 cfg->redMask = fbcfg->redMask;
578 cfg->greenMask = fbcfg->greenMask;
579 cfg->blueMask = fbcfg->blueMask;
580 cfg->alphaMask = fbcfg->alphaMask;
581 cfg->accumRedSize = fbcfg->accumRedBits;
582 cfg->accumGreenSize = fbcfg->accumGreenBits;
583 cfg->accumBlueSize = fbcfg->accumBlueBits;
584 cfg->accumAlphaSize = fbcfg->accumAlphaBits;
585 cfg->doubleBuffer = fbcfg->doubleBufferMode;
586 cfg->stereo = fbcfg->stereoMode;
587 if (vinfo->class == TrueColor || vinfo->class == DirectColor) {
588 cfg->bufferSize = (fbcfg->rgbMode ? (fbcfg->redBits +
589 fbcfg->greenBits +
590 fbcfg->blueBits +
591 fbcfg->alphaBits)
592 : fbcfg->indexBits);
593 }
594 else {
595 cfg->bufferSize = vinfo->depth;
596 }
597 cfg->depthSize = fbcfg->depthBits;
598 cfg->stencilSize = fbcfg->stencilBits;
599 cfg->auxBuffers = fbcfg->maxAuxBuffers;
600 cfg->level = fbcfg->level;
601 cfg->visualRating = fbcfg->visualCaveat;
602 cfg->transparentPixel = fbcfg->transparentType;
603 cfg->transparentRed = fbcfg->transparentRed;
604 cfg->transparentGreen = fbcfg->transparentGreen;
605 cfg->transparentBlue = fbcfg->transparentBlue;
606 cfg->transparentAlpha = fbcfg->transparentAlpha;
607 cfg->transparentIndex = fbcfg->transparentIndex;
608 cfg->multiSampleSize = fbcfg->multiSampleSize;
609 cfg->nMultiSampleBuffers = fbcfg->nMultiSampleBuffers;
610 cfg->visualSelectGroup = fbcfg->visualSelectGroup;
611 }
612 }
613
614 return configs;
615}