dmx_glxvisuals.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616
  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. #ifdef HAVE_DMX_CONFIG_H
  31. #include <dmx-config.h>
  32. #endif
  33. #include "dmx.h"
  34. #include <GL/glx.h>
  35. #include <GL/glxproto.h>
  36. #include <X11/extensions/Xext.h>
  37. #include <X11/extensions/extutil.h>
  38. #include <limits.h>
  39. #include "dmx_glxvisuals.h"
  40. __GLXvisualConfig *
  41. GetGLXVisualConfigs(Display * dpy, int screen, int *nconfigs)
  42. {
  43. xGLXGetVisualConfigsReq *req;
  44. xGLXGetVisualConfigsReply reply;
  45. __GLXvisualConfig *config, *configs;
  46. GLint i, j, nvisuals, nprops;
  47. INT32 *props, *p;
  48. int majorOpcode, dummy;
  49. int num_good_visuals;
  50. if (!XQueryExtension(dpy, "GLX", &majorOpcode, &dummy, &dummy)) {
  51. return NULL;
  52. }
  53. /* Send the glXGetVisualConfigs request */
  54. LockDisplay(dpy);
  55. GetReq(GLXGetVisualConfigs, req);
  56. req->reqType = majorOpcode;
  57. req->glxCode = X_GLXGetVisualConfigs;
  58. req->screen = screen;
  59. if (!_XReply(dpy, (xReply *) &reply, 0, False)) {
  60. /* Something is busted. Punt. */
  61. UnlockDisplay(dpy);
  62. SyncHandle();
  63. return NULL;
  64. }
  65. nvisuals = (int) reply.numVisuals;
  66. if (!nvisuals) {
  67. /* This screen does not support GL rendering */
  68. UnlockDisplay(dpy);
  69. SyncHandle();
  70. return NULL;
  71. }
  72. /* Check number of properties per visual */
  73. nprops = (int) reply.numProps;
  74. if (nprops < __GLX_MIN_CONFIG_PROPS) {
  75. /* Huh? Not in protocol defined limits. Punt */
  76. UnlockDisplay(dpy);
  77. SyncHandle();
  78. return NULL;
  79. }
  80. if (nprops < (INT_MAX / __GLX_SIZE_CARD32))
  81. props = Xmalloc(nprops * __GLX_SIZE_CARD32);
  82. else
  83. props = NULL;
  84. if (!props) {
  85. UnlockDisplay(dpy);
  86. SyncHandle();
  87. return NULL;
  88. }
  89. /* Allocate memory for our config structure */
  90. if (nvisuals < (INT_MAX / sizeof(__GLXvisualConfig)))
  91. config = Xcalloc(nvisuals, sizeof(__GLXvisualConfig));
  92. else
  93. config = NULL;
  94. if (!config) {
  95. free(props);
  96. UnlockDisplay(dpy);
  97. SyncHandle();
  98. return NULL;
  99. }
  100. configs = config;
  101. num_good_visuals = 0;
  102. /* Convert config structure into our format */
  103. for (i = 0; i < nvisuals; i++) {
  104. /* Read config structure */
  105. _XRead(dpy, (char *) props, (nprops * __GLX_SIZE_CARD32));
  106. /* fill in default values */
  107. config->visualRating = GLX_NONE_EXT;
  108. config->transparentPixel = GLX_NONE_EXT;
  109. /* Copy in the first set of properties */
  110. config->vid = props[0];
  111. config->class = props[1];
  112. config->rgba = (Bool) props[2];
  113. config->redSize = props[3];
  114. config->greenSize = props[4];
  115. config->blueSize = props[5];
  116. config->alphaSize = props[6];
  117. config->accumRedSize = props[7];
  118. config->accumGreenSize = props[8];
  119. config->accumBlueSize = props[9];
  120. config->accumAlphaSize = props[10];
  121. config->doubleBuffer = (Bool) props[11];
  122. config->stereo = (Bool) props[12];
  123. config->bufferSize = props[13];
  124. config->depthSize = props[14];
  125. config->stencilSize = props[15];
  126. config->auxBuffers = props[16];
  127. config->level = props[17];
  128. /* Process remaining properties */
  129. p = &props[18];
  130. for (j = __GLX_MIN_CONFIG_PROPS; j < nprops; j += 2) {
  131. int property = *p++;
  132. int value = *p++;
  133. switch (property) {
  134. case GLX_SAMPLES_SGIS:
  135. config->multiSampleSize = value;
  136. break;
  137. case GLX_SAMPLE_BUFFERS_SGIS:
  138. config->nMultiSampleBuffers = value;
  139. break;
  140. case GLX_TRANSPARENT_TYPE_EXT:
  141. config->transparentPixel = value;
  142. break;
  143. case GLX_TRANSPARENT_INDEX_VALUE_EXT:
  144. config->transparentIndex = value;
  145. break;
  146. case GLX_TRANSPARENT_RED_VALUE_EXT:
  147. config->transparentRed = value;
  148. break;
  149. case GLX_TRANSPARENT_GREEN_VALUE_EXT:
  150. config->transparentGreen = value;
  151. break;
  152. case GLX_TRANSPARENT_BLUE_VALUE_EXT:
  153. config->transparentBlue = value;
  154. break;
  155. case GLX_TRANSPARENT_ALPHA_VALUE_EXT:
  156. config->transparentAlpha = value;
  157. break;
  158. case GLX_VISUAL_CAVEAT_EXT:
  159. config->visualRating = value;
  160. break;
  161. /* visualSelectGroup is an internal used property */
  162. case GLX_VISUAL_SELECT_GROUP_SGIX:
  163. config->visualSelectGroup = value;
  164. break;
  165. default:
  166. /* Ignore properties we don't recognize */
  167. break;
  168. }
  169. } /* for j */
  170. /*
  171. // filter out overlay visuals (dmx does not support overlays)
  172. */
  173. if (config->level == 0) {
  174. config++;
  175. num_good_visuals++;
  176. }
  177. } /* for i */
  178. UnlockDisplay(dpy);
  179. nvisuals = num_good_visuals;
  180. config = configs;
  181. for (i = 0; i < nvisuals; i++) {
  182. /* XXX hack to fill-in mask info (need a better way to do this) */
  183. {
  184. XVisualInfo *vis, template;
  185. int n;
  186. template.screen = screen;
  187. template.visualid = config->vid;
  188. vis = XGetVisualInfo(dpy, VisualScreenMask | VisualIDMask,
  189. &template, &n);
  190. if (vis != NULL) {
  191. config->redMask = vis->red_mask;
  192. config->greenMask = vis->green_mask;
  193. config->blueMask = vis->blue_mask;
  194. config->alphaMask = 0; /* XXX */
  195. free(vis);
  196. }
  197. }
  198. config++;
  199. } /* for i */
  200. XFree(props);
  201. SyncHandle();
  202. *nconfigs = nvisuals;
  203. return configs;
  204. }
  205. __GLXFBConfig *
  206. GetGLXFBConfigs(Display * dpy, int glxMajorOpcode, int *nconfigs)
  207. {
  208. xGLXGetFBConfigsReq *req;
  209. xGLXGetFBConfigsReply reply;
  210. __GLXFBConfig *config, *fbconfigs;
  211. GLint i, j, numFBConfigs, numAttribs;
  212. INT32 *attrs, *p;
  213. int screen = DefaultScreen(dpy);
  214. int numValidConfigs = 0;
  215. /* Send the glXGetFBConfigs request */
  216. LockDisplay(dpy);
  217. GetReq(GLXGetFBConfigs, req);
  218. req->reqType = glxMajorOpcode;
  219. req->glxCode = X_GLXGetFBConfigs;
  220. req->screen = screen;
  221. *nconfigs = 0;
  222. if (!_XReply(dpy, (xReply *) &reply, 0, False)) {
  223. /* Something is busted. Punt. */
  224. UnlockDisplay(dpy);
  225. SyncHandle();
  226. return NULL;
  227. }
  228. numFBConfigs = (int) reply.numFBConfigs;
  229. if (!numFBConfigs) {
  230. /* This screen does not support GL rendering */
  231. UnlockDisplay(dpy);
  232. SyncHandle();
  233. return NULL;
  234. }
  235. numAttribs = (int) reply.numAttribs;
  236. if (!numAttribs) {
  237. UnlockDisplay(dpy);
  238. SyncHandle();
  239. return NULL;
  240. }
  241. if (numAttribs < (INT_MAX / (2 * __GLX_SIZE_CARD32)))
  242. attrs = Xmalloc(2 * numAttribs * __GLX_SIZE_CARD32);
  243. else
  244. attrs = NULL;
  245. if (!attrs) {
  246. UnlockDisplay(dpy);
  247. SyncHandle();
  248. return NULL;
  249. }
  250. /* Allocate memory for our config structure */
  251. if (numFBConfigs < (INT_MAX / sizeof(__GLXFBConfig)))
  252. config = Xcalloc(numFBConfigs, sizeof(__GLXFBConfig));
  253. else
  254. config = NULL;
  255. if (!config) {
  256. free(attrs);
  257. UnlockDisplay(dpy);
  258. SyncHandle();
  259. return NULL;
  260. }
  261. fbconfigs = config;
  262. /* Convert attribute list into our format */
  263. for (i = 0; i < numFBConfigs; i++) {
  264. /* Fill in default properties */
  265. config->transparentType = GLX_NONE_EXT;
  266. config->visualCaveat = GLX_NONE_EXT;
  267. config->minRed = 0.;
  268. config->maxRed = 1.;
  269. config->minGreen = 0.;
  270. config->maxGreen = 1.;
  271. config->minBlue = 0.;
  272. config->maxBlue = 1.;
  273. config->minAlpha = 0.;
  274. config->maxAlpha = 1.;
  275. /* Read attribute list */
  276. _XRead(dpy, (char *) attrs, (2 * numAttribs * __GLX_SIZE_CARD32));
  277. p = attrs;
  278. for (j = 0; j < numAttribs; j++) {
  279. int attribute = *p++;
  280. int value = *p++;
  281. switch (attribute) {
  282. /* core attributes */
  283. case GLX_FBCONFIG_ID:
  284. config->id = value;
  285. break;
  286. case GLX_BUFFER_SIZE:
  287. config->indexBits = value;
  288. break;
  289. case GLX_LEVEL:
  290. config->level = value;
  291. break;
  292. case GLX_DOUBLEBUFFER:
  293. config->doubleBufferMode = value;
  294. break;
  295. case GLX_STEREO:
  296. config->stereoMode = value;
  297. break;
  298. case GLX_AUX_BUFFERS:
  299. config->maxAuxBuffers = value;
  300. break;
  301. case GLX_RED_SIZE:
  302. config->redBits = value;
  303. break;
  304. case GLX_GREEN_SIZE:
  305. config->greenBits = value;
  306. break;
  307. case GLX_BLUE_SIZE:
  308. config->blueBits = value;
  309. break;
  310. case GLX_ALPHA_SIZE:
  311. config->alphaBits = value;
  312. break;
  313. case GLX_DEPTH_SIZE:
  314. config->depthBits = value;
  315. break;
  316. case GLX_STENCIL_SIZE:
  317. config->stencilBits = value;
  318. break;
  319. case GLX_ACCUM_RED_SIZE:
  320. config->accumRedBits = value;
  321. break;
  322. case GLX_ACCUM_GREEN_SIZE:
  323. config->accumGreenBits = value;
  324. break;
  325. case GLX_ACCUM_BLUE_SIZE:
  326. config->accumBlueBits = value;
  327. break;
  328. case GLX_ACCUM_ALPHA_SIZE:
  329. config->accumAlphaBits = value;
  330. break;
  331. case GLX_RENDER_TYPE:
  332. config->renderType = value;
  333. break;
  334. case GLX_DRAWABLE_TYPE:
  335. config->drawableType = value;
  336. break;
  337. case GLX_X_VISUAL_TYPE:
  338. config->visualType = value;
  339. break;
  340. case GLX_CONFIG_CAVEAT:
  341. config->visualCaveat = value;
  342. break;
  343. case GLX_TRANSPARENT_TYPE:
  344. config->transparentType = value;
  345. break;
  346. case GLX_TRANSPARENT_INDEX_VALUE:
  347. config->transparentIndex = value;
  348. break;
  349. case GLX_TRANSPARENT_RED_VALUE:
  350. config->transparentRed = value;
  351. break;
  352. case GLX_TRANSPARENT_GREEN_VALUE:
  353. config->transparentGreen = value;
  354. break;
  355. case GLX_TRANSPARENT_BLUE_VALUE:
  356. config->transparentBlue = value;
  357. break;
  358. case GLX_TRANSPARENT_ALPHA_VALUE:
  359. config->transparentAlpha = value;
  360. break;
  361. case GLX_MAX_PBUFFER_WIDTH:
  362. config->maxPbufferWidth = value;
  363. break;
  364. case GLX_MAX_PBUFFER_HEIGHT:
  365. config->maxPbufferHeight = value;
  366. break;
  367. case GLX_MAX_PBUFFER_PIXELS:
  368. config->maxPbufferPixels = value;
  369. break;
  370. case GLX_VISUAL_ID:
  371. config->associatedVisualId = value;
  372. break;
  373. /* visualSelectGroup is an internal used property */
  374. case GLX_VISUAL_SELECT_GROUP_SGIX:
  375. config->visualSelectGroup = value;
  376. break;
  377. /* SGIS_multisample attributes */
  378. case GLX_SAMPLES_SGIS:
  379. config->multiSampleSize = value;
  380. break;
  381. case GLX_SAMPLE_BUFFERS_SGIS:
  382. config->nMultiSampleBuffers = value;
  383. break;
  384. /* SGIX_pbuffer specific attributes */
  385. case GLX_OPTIMAL_PBUFFER_WIDTH_SGIX:
  386. config->optimalPbufferWidth = value;
  387. break;
  388. case GLX_OPTIMAL_PBUFFER_HEIGHT_SGIX:
  389. config->optimalPbufferHeight = value;
  390. break;
  391. default:
  392. /* Ignore attributes we don't recognize */
  393. break;
  394. }
  395. } /* for j */
  396. /* Fill in derived values */
  397. config->screen = screen;
  398. /* The rgbMode should be true for any mode which has distinguishible
  399. * R, G and B components
  400. */
  401. config->rgbMode = (config->renderType
  402. & (GLX_RGBA_BIT | GLX_RGBA_FLOAT_BIT_ARB
  403. | GLX_RGBA_UNSIGNED_FLOAT_BIT_EXT)) != 0;
  404. config->colorIndexMode = !config->rgbMode;
  405. config->haveAccumBuffer =
  406. config->accumRedBits > 0 ||
  407. config->accumGreenBits > 0 || config->accumBlueBits > 0;
  408. /* Can't have alpha without color */
  409. config->haveDepthBuffer = config->depthBits > 0;
  410. config->haveStencilBuffer = config->stencilBits > 0;
  411. /* overlay visuals are not valid for now */
  412. if (!config->level) {
  413. config++;
  414. numValidConfigs++;
  415. }
  416. } /* for i */
  417. UnlockDisplay(dpy);
  418. config = fbconfigs;
  419. for (i = 0; i < numValidConfigs; i++) {
  420. /* XXX hack to fill-in mask info (need a better way to do this) */
  421. if (config->associatedVisualId != 0) {
  422. XVisualInfo *vis, template;
  423. int n;
  424. template.screen = screen;
  425. template.visualid = config->associatedVisualId;
  426. vis = XGetVisualInfo(dpy, VisualScreenMask | VisualIDMask,
  427. &template, &n);
  428. if (vis != NULL) {
  429. config->redMask = (GLuint) vis->red_mask;
  430. config->greenMask = (GLuint) vis->green_mask;
  431. config->blueMask = (GLuint) vis->blue_mask;
  432. config->alphaMask = 0; /* XXX */
  433. free(vis);
  434. }
  435. }
  436. config++;
  437. } /* for i */
  438. XFree(attrs);
  439. SyncHandle();
  440. *nconfigs = numValidConfigs;
  441. return fbconfigs;
  442. }
  443. __GLXvisualConfig *
  444. GetGLXVisualConfigsFromFBConfigs(__GLXFBConfig * fbconfigs, int nfbconfigs,
  445. XVisualInfo * visuals, int nvisuals,
  446. __GLXvisualConfig * glxConfigs,
  447. int nGlxConfigs, int *nconfigs)
  448. {
  449. __GLXvisualConfig *configs = NULL;
  450. int i;
  451. if (!fbconfigs || !nfbconfigs || !nconfigs)
  452. return NULL;
  453. *nconfigs = 0;
  454. /* Allocate memory for our config structure */
  455. configs = (__GLXvisualConfig *)
  456. Xmalloc(nfbconfigs * sizeof(__GLXvisualConfig));
  457. if (!configs) {
  458. return NULL;
  459. }
  460. memset(configs, 0, nfbconfigs * sizeof(__GLXvisualConfig));
  461. for (i = 0; i < nfbconfigs; i++) {
  462. __GLXFBConfig *fbcfg = &fbconfigs[i];
  463. if (fbcfg->associatedVisualId > 0) {
  464. __GLXvisualConfig *cfg = configs + (*nconfigs);
  465. int j;
  466. XVisualInfo *vinfo = NULL;
  467. for (j = 0; j < nvisuals; j++) {
  468. if (visuals[j].visualid == fbcfg->associatedVisualId) {
  469. vinfo = &visuals[j];
  470. break;
  471. }
  472. }
  473. if (!vinfo)
  474. continue;
  475. /* skip 16 bit colormap visuals */
  476. if (vinfo->depth == 16 &&
  477. vinfo->class != TrueColor && vinfo->class != DirectColor) {
  478. continue;
  479. }
  480. (*nconfigs)++;
  481. /*
  482. * if the same visualid exists in the glx configs,
  483. * copy the glx attributes from the glx config
  484. */
  485. for (j = 0; j < nGlxConfigs; j++) {
  486. if (glxConfigs[j].vid == vinfo->visualid)
  487. break;
  488. }
  489. if (j < nGlxConfigs) {
  490. memcpy(cfg, &glxConfigs[j], sizeof(__GLXvisualConfig));
  491. continue;
  492. }
  493. /*
  494. * make glx attributes from the FB config attributes
  495. */
  496. cfg->vid = fbcfg->associatedVisualId;
  497. cfg->class = vinfo->class;
  498. cfg->rgba = !(fbcfg->renderType & GLX_COLOR_INDEX_BIT_SGIX);
  499. cfg->redSize = fbcfg->redBits;
  500. cfg->greenSize = fbcfg->greenBits;
  501. cfg->blueSize = fbcfg->blueBits;
  502. cfg->alphaSize = fbcfg->alphaBits;
  503. cfg->redMask = fbcfg->redMask;
  504. cfg->greenMask = fbcfg->greenMask;
  505. cfg->blueMask = fbcfg->blueMask;
  506. cfg->alphaMask = fbcfg->alphaMask;
  507. cfg->accumRedSize = fbcfg->accumRedBits;
  508. cfg->accumGreenSize = fbcfg->accumGreenBits;
  509. cfg->accumBlueSize = fbcfg->accumBlueBits;
  510. cfg->accumAlphaSize = fbcfg->accumAlphaBits;
  511. cfg->doubleBuffer = fbcfg->doubleBufferMode;
  512. cfg->stereo = fbcfg->stereoMode;
  513. if (vinfo->class == TrueColor || vinfo->class == DirectColor) {
  514. cfg->bufferSize = (fbcfg->rgbMode ? (fbcfg->redBits +
  515. fbcfg->greenBits +
  516. fbcfg->blueBits +
  517. fbcfg->alphaBits)
  518. : fbcfg->indexBits);
  519. }
  520. else {
  521. cfg->bufferSize = vinfo->depth;
  522. }
  523. cfg->depthSize = fbcfg->depthBits;
  524. cfg->stencilSize = fbcfg->stencilBits;
  525. cfg->auxBuffers = fbcfg->maxAuxBuffers;
  526. cfg->level = fbcfg->level;
  527. cfg->visualRating = fbcfg->visualCaveat;
  528. cfg->transparentPixel = fbcfg->transparentType;
  529. cfg->transparentRed = fbcfg->transparentRed;
  530. cfg->transparentGreen = fbcfg->transparentGreen;
  531. cfg->transparentBlue = fbcfg->transparentBlue;
  532. cfg->transparentAlpha = fbcfg->transparentAlpha;
  533. cfg->transparentIndex = fbcfg->transparentIndex;
  534. cfg->multiSampleSize = fbcfg->multiSampleSize;
  535. cfg->nMultiSampleBuffers = fbcfg->nMultiSampleBuffers;
  536. cfg->visualSelectGroup = fbcfg->visualSelectGroup;
  537. }
  538. }
  539. return configs;
  540. }