Clone of mesa.
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

glxext.c 28KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972
  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. * \file glxext.c
  32. * GLX protocol interface boot-strap code.
  33. *
  34. * Direct rendering support added by Precision Insight, Inc.
  35. *
  36. * \author Kevin E. Martin <kevin@precisioninsight.com>
  37. */
  38. #include <assert.h>
  39. #include "glxclient.h"
  40. #include <X11/extensions/Xext.h>
  41. #include <X11/extensions/extutil.h>
  42. #include "glapi.h"
  43. #include "glxextensions.h"
  44. #include "glcontextmodes.h"
  45. #ifdef USE_XCB
  46. #include <X11/Xlib-xcb.h>
  47. #include <xcb/xcb.h>
  48. #include <xcb/glx.h>
  49. #endif
  50. #ifdef DEBUG
  51. void __glXDumpDrawBuffer(__GLXcontext * ctx);
  52. #endif
  53. /*
  54. ** You can set this cell to 1 to force the gl drawing stuff to be
  55. ** one command per packet
  56. */
  57. _X_HIDDEN int __glXDebug = 0;
  58. /* Extension required boiler plate */
  59. static char *__glXExtensionName = GLX_EXTENSION_NAME;
  60. XExtensionInfo *__glXExtensionInfo = NULL;
  61. static /* const */ char *error_list[] = {
  62. "GLXBadContext",
  63. "GLXBadContextState",
  64. "GLXBadDrawable",
  65. "GLXBadPixmap",
  66. "GLXBadContextTag",
  67. "GLXBadCurrentWindow",
  68. "GLXBadRenderRequest",
  69. "GLXBadLargeRequest",
  70. "GLXUnsupportedPrivateRequest",
  71. "GLXBadFBConfig",
  72. "GLXBadPbuffer",
  73. "GLXBadCurrentDrawable",
  74. "GLXBadWindow",
  75. };
  76. static int
  77. __glXCloseDisplay(Display * dpy, XExtCodes * codes)
  78. {
  79. GLXContext gc;
  80. gc = __glXGetCurrentContext();
  81. if (dpy == gc->currentDpy) {
  82. __glXSetCurrentContextNull();
  83. __glXFreeContext(gc);
  84. }
  85. return XextRemoveDisplay(__glXExtensionInfo, dpy);
  86. }
  87. static
  88. XEXT_GENERATE_ERROR_STRING(__glXErrorString, __glXExtensionName,
  89. __GLX_NUMBER_ERRORS, error_list)
  90. static /* const */ XExtensionHooks __glXExtensionHooks = {
  91. NULL, /* create_gc */
  92. NULL, /* copy_gc */
  93. NULL, /* flush_gc */
  94. NULL, /* free_gc */
  95. NULL, /* create_font */
  96. NULL, /* free_font */
  97. __glXCloseDisplay, /* close_display */
  98. NULL, /* wire_to_event */
  99. NULL, /* event_to_wire */
  100. NULL, /* error */
  101. __glXErrorString, /* error_string */
  102. };
  103. static
  104. XEXT_GENERATE_FIND_DISPLAY(__glXFindDisplay, __glXExtensionInfo,
  105. __glXExtensionName, &__glXExtensionHooks,
  106. __GLX_NUMBER_EVENTS, NULL)
  107. /************************************************************************/
  108. /*
  109. ** Free the per screen configs data as well as the array of
  110. ** __glXScreenConfigs.
  111. */
  112. static void
  113. FreeScreenConfigs(__GLXdisplayPrivate * priv)
  114. {
  115. __GLXscreenConfigs *psc;
  116. GLint i, screens;
  117. /* Free screen configuration information */
  118. psc = priv->screenConfigs;
  119. screens = ScreenCount(priv->dpy);
  120. for (i = 0; i < screens; i++, psc++) {
  121. if (psc->configs) {
  122. _gl_context_modes_destroy(psc->configs);
  123. if (psc->effectiveGLXexts)
  124. Xfree(psc->effectiveGLXexts);
  125. psc->configs = NULL; /* NOTE: just for paranoia */
  126. }
  127. if (psc->visuals) {
  128. _gl_context_modes_destroy(psc->visuals);
  129. psc->visuals = NULL; /* NOTE: just for paranoia */
  130. }
  131. Xfree((char *) psc->serverGLXexts);
  132. #ifdef GLX_DIRECT_RENDERING
  133. if (psc->driver_configs) {
  134. for(unsigned int i = 0; psc->driver_configs[i]; i++)
  135. free((__DRIconfig*)psc->driver_configs[i]);
  136. free(psc->driver_configs);
  137. psc->driver_configs = NULL;
  138. }
  139. if (psc->driScreen) {
  140. psc->driScreen->destroyScreen(psc);
  141. __glxHashDestroy(psc->drawHash);
  142. XFree(psc->driScreen);
  143. psc->driScreen = NULL;
  144. }
  145. #endif
  146. }
  147. XFree((char *) priv->screenConfigs);
  148. priv->screenConfigs = NULL;
  149. }
  150. /*
  151. ** Release the private memory referred to in a display private
  152. ** structure. The caller will free the extension structure.
  153. */
  154. static int
  155. __glXFreeDisplayPrivate(XExtData * extension)
  156. {
  157. __GLXdisplayPrivate *priv;
  158. priv = (__GLXdisplayPrivate *) extension->private_data;
  159. FreeScreenConfigs(priv);
  160. if (priv->serverGLXvendor) {
  161. Xfree((char *) priv->serverGLXvendor);
  162. priv->serverGLXvendor = 0x0; /* to protect against double free's */
  163. }
  164. if (priv->serverGLXversion) {
  165. Xfree((char *) priv->serverGLXversion);
  166. priv->serverGLXversion = 0x0; /* to protect against double free's */
  167. }
  168. #ifdef GLX_DIRECT_RENDERING
  169. /* Free the direct rendering per display data */
  170. if (priv->driswDisplay)
  171. (*priv->driswDisplay->destroyDisplay) (priv->driswDisplay);
  172. priv->driswDisplay = NULL;
  173. if (priv->driDisplay)
  174. (*priv->driDisplay->destroyDisplay) (priv->driDisplay);
  175. priv->driDisplay = NULL;
  176. if (priv->dri2Display)
  177. (*priv->dri2Display->destroyDisplay) (priv->dri2Display);
  178. priv->dri2Display = NULL;
  179. #endif
  180. Xfree((char *) priv);
  181. return 0;
  182. }
  183. /************************************************************************/
  184. /*
  185. ** Query the version of the GLX extension. This procedure works even if
  186. ** the client extension is not completely set up.
  187. */
  188. static Bool
  189. QueryVersion(Display * dpy, int opcode, int *major, int *minor)
  190. {
  191. #ifdef USE_XCB
  192. xcb_connection_t *c = XGetXCBConnection(dpy);
  193. xcb_glx_query_version_reply_t* reply =
  194. xcb_glx_query_version_reply(c,
  195. xcb_glx_query_version(c,
  196. GLX_MAJOR_VERSION,
  197. GLX_MINOR_VERSION),
  198. NULL);
  199. if(reply->major_version != GLX_MAJOR_VERSION)
  200. {
  201. free(reply);
  202. return GL_FALSE;
  203. }
  204. *major = reply->major_version;
  205. *minor = min(reply->minor_version, GLX_MINOR_VERSION);
  206. free(reply);
  207. return GL_TRUE;
  208. #else
  209. xGLXQueryVersionReq *req;
  210. xGLXQueryVersionReply reply;
  211. /* Send the glXQueryVersion request */
  212. LockDisplay(dpy);
  213. GetReq(GLXQueryVersion, req);
  214. req->reqType = opcode;
  215. req->glxCode = X_GLXQueryVersion;
  216. req->majorVersion = GLX_MAJOR_VERSION;
  217. req->minorVersion = GLX_MINOR_VERSION;
  218. _XReply(dpy, (xReply *) & reply, 0, False);
  219. UnlockDisplay(dpy);
  220. SyncHandle();
  221. if (reply.majorVersion != GLX_MAJOR_VERSION) {
  222. /*
  223. ** The server does not support the same major release as this
  224. ** client.
  225. */
  226. return GL_FALSE;
  227. }
  228. *major = reply.majorVersion;
  229. *minor = min(reply.minorVersion, GLX_MINOR_VERSION);
  230. return GL_TRUE;
  231. #endif /* USE_XCB */
  232. }
  233. _X_HIDDEN void
  234. __glXInitializeVisualConfigFromTags(__GLcontextModes * config, int count,
  235. const INT32 * bp, Bool tagged_only,
  236. Bool fbconfig_style_tags)
  237. {
  238. int i;
  239. if (!tagged_only) {
  240. /* Copy in the first set of properties */
  241. config->visualID = *bp++;
  242. config->visualType = _gl_convert_from_x_visual_type(*bp++);
  243. config->rgbMode = *bp++;
  244. config->redBits = *bp++;
  245. config->greenBits = *bp++;
  246. config->blueBits = *bp++;
  247. config->alphaBits = *bp++;
  248. config->accumRedBits = *bp++;
  249. config->accumGreenBits = *bp++;
  250. config->accumBlueBits = *bp++;
  251. config->accumAlphaBits = *bp++;
  252. config->doubleBufferMode = *bp++;
  253. config->stereoMode = *bp++;
  254. config->rgbBits = *bp++;
  255. config->depthBits = *bp++;
  256. config->stencilBits = *bp++;
  257. config->numAuxBuffers = *bp++;
  258. config->level = *bp++;
  259. count -= __GLX_MIN_CONFIG_PROPS;
  260. }
  261. /*
  262. ** Additional properties may be in a list at the end
  263. ** of the reply. They are in pairs of property type
  264. ** and property value.
  265. */
  266. #define FETCH_OR_SET(tag) \
  267. config-> tag = ( fbconfig_style_tags ) ? *bp++ : 1
  268. for (i = 0; i < count; i += 2) {
  269. switch (*bp++) {
  270. case GLX_RGBA:
  271. FETCH_OR_SET(rgbMode);
  272. break;
  273. case GLX_BUFFER_SIZE:
  274. config->rgbBits = *bp++;
  275. break;
  276. case GLX_LEVEL:
  277. config->level = *bp++;
  278. break;
  279. case GLX_DOUBLEBUFFER:
  280. FETCH_OR_SET(doubleBufferMode);
  281. break;
  282. case GLX_STEREO:
  283. FETCH_OR_SET(stereoMode);
  284. break;
  285. case GLX_AUX_BUFFERS:
  286. config->numAuxBuffers = *bp++;
  287. break;
  288. case GLX_RED_SIZE:
  289. config->redBits = *bp++;
  290. break;
  291. case GLX_GREEN_SIZE:
  292. config->greenBits = *bp++;
  293. break;
  294. case GLX_BLUE_SIZE:
  295. config->blueBits = *bp++;
  296. break;
  297. case GLX_ALPHA_SIZE:
  298. config->alphaBits = *bp++;
  299. break;
  300. case GLX_DEPTH_SIZE:
  301. config->depthBits = *bp++;
  302. break;
  303. case GLX_STENCIL_SIZE:
  304. config->stencilBits = *bp++;
  305. break;
  306. case GLX_ACCUM_RED_SIZE:
  307. config->accumRedBits = *bp++;
  308. break;
  309. case GLX_ACCUM_GREEN_SIZE:
  310. config->accumGreenBits = *bp++;
  311. break;
  312. case GLX_ACCUM_BLUE_SIZE:
  313. config->accumBlueBits = *bp++;
  314. break;
  315. case GLX_ACCUM_ALPHA_SIZE:
  316. config->accumAlphaBits = *bp++;
  317. break;
  318. case GLX_VISUAL_CAVEAT_EXT:
  319. config->visualRating = *bp++;
  320. break;
  321. case GLX_X_VISUAL_TYPE:
  322. config->visualType = *bp++;
  323. break;
  324. case GLX_TRANSPARENT_TYPE:
  325. config->transparentPixel = *bp++;
  326. break;
  327. case GLX_TRANSPARENT_INDEX_VALUE:
  328. config->transparentIndex = *bp++;
  329. break;
  330. case GLX_TRANSPARENT_RED_VALUE:
  331. config->transparentRed = *bp++;
  332. break;
  333. case GLX_TRANSPARENT_GREEN_VALUE:
  334. config->transparentGreen = *bp++;
  335. break;
  336. case GLX_TRANSPARENT_BLUE_VALUE:
  337. config->transparentBlue = *bp++;
  338. break;
  339. case GLX_TRANSPARENT_ALPHA_VALUE:
  340. config->transparentAlpha = *bp++;
  341. break;
  342. case GLX_VISUAL_ID:
  343. config->visualID = *bp++;
  344. break;
  345. case GLX_DRAWABLE_TYPE:
  346. config->drawableType = *bp++;
  347. break;
  348. case GLX_RENDER_TYPE:
  349. config->renderType = *bp++;
  350. break;
  351. case GLX_X_RENDERABLE:
  352. config->xRenderable = *bp++;
  353. break;
  354. case GLX_FBCONFIG_ID:
  355. config->fbconfigID = *bp++;
  356. break;
  357. case GLX_MAX_PBUFFER_WIDTH:
  358. config->maxPbufferWidth = *bp++;
  359. break;
  360. case GLX_MAX_PBUFFER_HEIGHT:
  361. config->maxPbufferHeight = *bp++;
  362. break;
  363. case GLX_MAX_PBUFFER_PIXELS:
  364. config->maxPbufferPixels = *bp++;
  365. break;
  366. case GLX_OPTIMAL_PBUFFER_WIDTH_SGIX:
  367. config->optimalPbufferWidth = *bp++;
  368. break;
  369. case GLX_OPTIMAL_PBUFFER_HEIGHT_SGIX:
  370. config->optimalPbufferHeight = *bp++;
  371. break;
  372. case GLX_VISUAL_SELECT_GROUP_SGIX:
  373. config->visualSelectGroup = *bp++;
  374. break;
  375. case GLX_SWAP_METHOD_OML:
  376. config->swapMethod = *bp++;
  377. break;
  378. case GLX_SAMPLE_BUFFERS_SGIS:
  379. config->sampleBuffers = *bp++;
  380. break;
  381. case GLX_SAMPLES_SGIS:
  382. config->samples = *bp++;
  383. break;
  384. case GLX_BIND_TO_TEXTURE_RGB_EXT:
  385. config->bindToTextureRgb = *bp++;
  386. break;
  387. case GLX_BIND_TO_TEXTURE_RGBA_EXT:
  388. config->bindToTextureRgba = *bp++;
  389. break;
  390. case GLX_BIND_TO_MIPMAP_TEXTURE_EXT:
  391. config->bindToMipmapTexture = *bp++;
  392. break;
  393. case GLX_BIND_TO_TEXTURE_TARGETS_EXT:
  394. config->bindToTextureTargets = *bp++;
  395. break;
  396. case GLX_Y_INVERTED_EXT:
  397. config->yInverted = *bp++;
  398. break;
  399. case None:
  400. i = count;
  401. break;
  402. default:
  403. break;
  404. }
  405. }
  406. config->renderType =
  407. (config->rgbMode) ? GLX_RGBA_BIT : GLX_COLOR_INDEX_BIT;
  408. config->haveAccumBuffer = ((config->accumRedBits +
  409. config->accumGreenBits +
  410. config->accumBlueBits +
  411. config->accumAlphaBits) > 0);
  412. config->haveDepthBuffer = (config->depthBits > 0);
  413. config->haveStencilBuffer = (config->stencilBits > 0);
  414. }
  415. static __GLcontextModes *
  416. createConfigsFromProperties(Display * dpy, int nvisuals, int nprops,
  417. int screen, GLboolean tagged_only)
  418. {
  419. INT32 buf[__GLX_TOTAL_CONFIG], *props;
  420. unsigned prop_size;
  421. __GLcontextModes *modes, *m;
  422. int i;
  423. if (nprops == 0)
  424. return NULL;
  425. /* FIXME: Is the __GLX_MIN_CONFIG_PROPS test correct for FBconfigs? */
  426. /* Check number of properties */
  427. if (nprops < __GLX_MIN_CONFIG_PROPS || nprops > __GLX_MAX_CONFIG_PROPS)
  428. return NULL;
  429. /* Allocate memory for our config structure */
  430. modes = _gl_context_modes_create(nvisuals, sizeof(__GLcontextModes));
  431. if (!modes)
  432. return NULL;
  433. prop_size = nprops * __GLX_SIZE_INT32;
  434. if (prop_size <= sizeof(buf))
  435. props = buf;
  436. else
  437. props = Xmalloc(prop_size);
  438. /* Read each config structure and convert it into our format */
  439. m = modes;
  440. for (i = 0; i < nvisuals; i++) {
  441. _XRead(dpy, (char *) props, prop_size);
  442. /* Older X servers don't send this so we default it here. */
  443. m->drawableType = GLX_WINDOW_BIT;
  444. __glXInitializeVisualConfigFromTags(m, nprops, props,
  445. tagged_only, GL_TRUE);
  446. m->screen = screen;
  447. m = m->next;
  448. }
  449. if (props != buf)
  450. Xfree(props);
  451. return modes;
  452. }
  453. static GLboolean
  454. getVisualConfigs(Display * dpy, __GLXdisplayPrivate * priv, int screen)
  455. {
  456. xGLXGetVisualConfigsReq *req;
  457. __GLXscreenConfigs *psc;
  458. xGLXGetVisualConfigsReply reply;
  459. LockDisplay(dpy);
  460. psc = priv->screenConfigs + screen;
  461. psc->visuals = NULL;
  462. GetReq(GLXGetVisualConfigs, req);
  463. req->reqType = priv->majorOpcode;
  464. req->glxCode = X_GLXGetVisualConfigs;
  465. req->screen = screen;
  466. if (!_XReply(dpy, (xReply *) & reply, 0, False))
  467. goto out;
  468. psc->visuals = createConfigsFromProperties(dpy,
  469. reply.numVisuals,
  470. reply.numProps,
  471. screen, GL_FALSE);
  472. out:
  473. UnlockDisplay(dpy);
  474. return psc->visuals != NULL;
  475. }
  476. static GLboolean
  477. getFBConfigs(Display * dpy, __GLXdisplayPrivate * priv, int screen)
  478. {
  479. xGLXGetFBConfigsReq *fb_req;
  480. xGLXGetFBConfigsSGIXReq *sgi_req;
  481. xGLXVendorPrivateWithReplyReq *vpreq;
  482. xGLXGetFBConfigsReply reply;
  483. __GLXscreenConfigs *psc;
  484. psc = priv->screenConfigs + screen;
  485. psc->serverGLXexts = __glXQueryServerString(dpy, priv->majorOpcode, screen, GLX_EXTENSIONS);
  486. LockDisplay(dpy);
  487. psc->configs = NULL;
  488. if (atof(priv->serverGLXversion) >= 1.3) {
  489. GetReq(GLXGetFBConfigs, fb_req);
  490. fb_req->reqType = priv->majorOpcode;
  491. fb_req->glxCode = X_GLXGetFBConfigs;
  492. fb_req->screen = screen;
  493. }
  494. else if (strstr(psc->serverGLXexts, "GLX_SGIX_fbconfig") != NULL) {
  495. GetReqExtra(GLXVendorPrivateWithReply,
  496. sz_xGLXGetFBConfigsSGIXReq +
  497. sz_xGLXVendorPrivateWithReplyReq, vpreq);
  498. sgi_req = (xGLXGetFBConfigsSGIXReq *) vpreq;
  499. sgi_req->reqType = priv->majorOpcode;
  500. sgi_req->glxCode = X_GLXVendorPrivateWithReply;
  501. sgi_req->vendorCode = X_GLXvop_GetFBConfigsSGIX;
  502. sgi_req->screen = screen;
  503. }
  504. else
  505. goto out;
  506. if (!_XReply(dpy, (xReply *) & reply, 0, False))
  507. goto out;
  508. psc->configs = createConfigsFromProperties(dpy,
  509. reply.numFBConfigs,
  510. reply.numAttribs * 2,
  511. screen, GL_TRUE);
  512. out:
  513. UnlockDisplay(dpy);
  514. return psc->configs != NULL;
  515. }
  516. /*
  517. ** Allocate the memory for the per screen configs for each screen.
  518. ** If that works then fetch the per screen configs data.
  519. */
  520. static Bool
  521. AllocAndFetchScreenConfigs(Display * dpy, __GLXdisplayPrivate * priv)
  522. {
  523. __GLXscreenConfigs *psc;
  524. GLint i, screens;
  525. /*
  526. ** First allocate memory for the array of per screen configs.
  527. */
  528. screens = ScreenCount(dpy);
  529. psc = (__GLXscreenConfigs *) Xmalloc(screens * sizeof(__GLXscreenConfigs));
  530. if (!psc) {
  531. return GL_FALSE;
  532. }
  533. memset(psc, 0, screens * sizeof(__GLXscreenConfigs));
  534. priv->screenConfigs = psc;
  535. priv->serverGLXversion = __glXQueryServerString(dpy, priv->majorOpcode, 0, GLX_VERSION);
  536. if (priv->serverGLXversion == NULL) {
  537. FreeScreenConfigs(priv);
  538. return GL_FALSE;
  539. }
  540. for (i = 0; i < screens; i++, psc++) {
  541. getVisualConfigs(dpy, priv, i);
  542. getFBConfigs(dpy, priv, i);
  543. #ifdef GLX_DIRECT_RENDERING
  544. psc->scr = i;
  545. psc->dpy = dpy;
  546. psc->drawHash = __glxHashCreate();
  547. if (psc->drawHash == NULL)
  548. continue;
  549. if (priv->dri2Display)
  550. psc->driScreen = (*priv->dri2Display->createScreen) (psc, i, priv);
  551. if (psc->driScreen == NULL && priv->driDisplay)
  552. psc->driScreen = (*priv->driDisplay->createScreen) (psc, i, priv);
  553. if (psc->driScreen == NULL && priv->driswDisplay)
  554. psc->driScreen = (*priv->driswDisplay->createScreen) (psc, i, priv);
  555. if (psc->driScreen == NULL) {
  556. __glxHashDestroy(psc->drawHash);
  557. psc->drawHash = NULL;
  558. }
  559. #endif
  560. }
  561. SyncHandle();
  562. return GL_TRUE;
  563. }
  564. /*
  565. ** Initialize the client side extension code.
  566. */
  567. _X_HIDDEN __GLXdisplayPrivate *
  568. __glXInitialize(Display * dpy)
  569. {
  570. XExtDisplayInfo *info = __glXFindDisplay(dpy);
  571. XExtData **privList, *private, *found;
  572. __GLXdisplayPrivate *dpyPriv;
  573. XEDataObject dataObj;
  574. int major, minor;
  575. #ifdef GLX_DIRECT_RENDERING
  576. Bool glx_direct, glx_accel;
  577. #endif
  578. #if defined(USE_XTHREADS)
  579. {
  580. static int firstCall = 1;
  581. if (firstCall) {
  582. /* initialize the GLX mutexes */
  583. xmutex_init(&__glXmutex);
  584. firstCall = 0;
  585. }
  586. }
  587. #endif
  588. /* The one and only long long lock */
  589. __glXLock();
  590. if (!XextHasExtension(info)) {
  591. /* No GLX extension supported by this server. Oh well. */
  592. __glXUnlock();
  593. XMissingExtension(dpy, __glXExtensionName);
  594. return 0;
  595. }
  596. /* See if a display private already exists. If so, return it */
  597. dataObj.display = dpy;
  598. privList = XEHeadOfExtensionList(dataObj);
  599. found = XFindOnExtensionList(privList, info->codes->extension);
  600. if (found) {
  601. __glXUnlock();
  602. return (__GLXdisplayPrivate *) found->private_data;
  603. }
  604. /* See if the versions are compatible */
  605. if (!QueryVersion(dpy, info->codes->major_opcode, &major, &minor)) {
  606. /* The client and server do not agree on versions. Punt. */
  607. __glXUnlock();
  608. return 0;
  609. }
  610. /*
  611. ** Allocate memory for all the pieces needed for this buffer.
  612. */
  613. private = (XExtData *) Xmalloc(sizeof(XExtData));
  614. if (!private) {
  615. __glXUnlock();
  616. return 0;
  617. }
  618. dpyPriv = (__GLXdisplayPrivate *) Xcalloc(1, sizeof(__GLXdisplayPrivate));
  619. if (!dpyPriv) {
  620. __glXUnlock();
  621. Xfree((char *) private);
  622. return 0;
  623. }
  624. /*
  625. ** Init the display private and then read in the screen config
  626. ** structures from the server.
  627. */
  628. dpyPriv->majorOpcode = info->codes->major_opcode;
  629. dpyPriv->majorVersion = major;
  630. dpyPriv->minorVersion = minor;
  631. dpyPriv->dpy = dpy;
  632. dpyPriv->serverGLXvendor = 0x0;
  633. dpyPriv->serverGLXversion = 0x0;
  634. #ifdef GLX_DIRECT_RENDERING
  635. glx_direct = (getenv("LIBGL_ALWAYS_INDIRECT") == NULL);
  636. glx_accel = (getenv("LIBGL_ALWAYS_SOFTWARE") == NULL);
  637. /*
  638. ** Initialize the direct rendering per display data and functions.
  639. ** Note: This _must_ be done before calling any other DRI routines
  640. ** (e.g., those called in AllocAndFetchScreenConfigs).
  641. */
  642. if (glx_direct && glx_accel) {
  643. dpyPriv->dri2Display = dri2CreateDisplay(dpy);
  644. dpyPriv->driDisplay = driCreateDisplay(dpy);
  645. }
  646. if (glx_direct)
  647. dpyPriv->driswDisplay = driswCreateDisplay(dpy);
  648. #endif
  649. if (!AllocAndFetchScreenConfigs(dpy, dpyPriv)) {
  650. __glXUnlock();
  651. Xfree((char *) dpyPriv);
  652. Xfree((char *) private);
  653. return 0;
  654. }
  655. /*
  656. ** Fill in the private structure. This is the actual structure that
  657. ** hangs off of the Display structure. Our private structure is
  658. ** referred to by this structure. Got that?
  659. */
  660. private->number = info->codes->extension;
  661. private->next = 0;
  662. private->free_private = __glXFreeDisplayPrivate;
  663. private->private_data = (char *) dpyPriv;
  664. XAddToExtensionList(privList, private);
  665. if (dpyPriv->majorVersion == 1 && dpyPriv->minorVersion >= 1) {
  666. __glXClientInfo(dpy, dpyPriv->majorOpcode);
  667. }
  668. __glXUnlock();
  669. return dpyPriv;
  670. }
  671. /*
  672. ** Setup for sending a GLX command on dpy. Make sure the extension is
  673. ** initialized. Try to avoid calling __glXInitialize as its kinda slow.
  674. */
  675. _X_HIDDEN CARD8
  676. __glXSetupForCommand(Display * dpy)
  677. {
  678. GLXContext gc;
  679. __GLXdisplayPrivate *priv;
  680. /* If this thread has a current context, flush its rendering commands */
  681. gc = __glXGetCurrentContext();
  682. if (gc->currentDpy) {
  683. /* Flush rendering buffer of the current context, if any */
  684. (void) __glXFlushRenderBuffer(gc, gc->pc);
  685. if (gc->currentDpy == dpy) {
  686. /* Use opcode from gc because its right */
  687. return gc->majorOpcode;
  688. }
  689. else {
  690. /*
  691. ** Have to get info about argument dpy because it might be to
  692. ** a different server
  693. */
  694. }
  695. }
  696. /* Forced to lookup extension via the slow initialize route */
  697. priv = __glXInitialize(dpy);
  698. if (!priv) {
  699. return 0;
  700. }
  701. return priv->majorOpcode;
  702. }
  703. /**
  704. * Flush the drawing command transport buffer.
  705. *
  706. * \param ctx Context whose transport buffer is to be flushed.
  707. * \param pc Pointer to first unused buffer location.
  708. *
  709. * \todo
  710. * Modify this function to use \c ctx->pc instead of the explicit
  711. * \c pc parameter.
  712. */
  713. _X_HIDDEN GLubyte *
  714. __glXFlushRenderBuffer(__GLXcontext * ctx, GLubyte * pc)
  715. {
  716. Display *const dpy = ctx->currentDpy;
  717. #ifdef USE_XCB
  718. xcb_connection_t *c = XGetXCBConnection(dpy);
  719. #else
  720. xGLXRenderReq *req;
  721. #endif /* USE_XCB */
  722. const GLint size = pc - ctx->buf;
  723. if ((dpy != NULL) && (size > 0)) {
  724. #ifdef USE_XCB
  725. xcb_glx_render(c, ctx->currentContextTag, size,
  726. (const uint8_t *) ctx->buf);
  727. #else
  728. /* Send the entire buffer as an X request */
  729. LockDisplay(dpy);
  730. GetReq(GLXRender, req);
  731. req->reqType = ctx->majorOpcode;
  732. req->glxCode = X_GLXRender;
  733. req->contextTag = ctx->currentContextTag;
  734. req->length += (size + 3) >> 2;
  735. _XSend(dpy, (char *) ctx->buf, size);
  736. UnlockDisplay(dpy);
  737. SyncHandle();
  738. #endif
  739. }
  740. /* Reset pointer and return it */
  741. ctx->pc = ctx->buf;
  742. return ctx->pc;
  743. }
  744. /**
  745. * Send a portion of a GLXRenderLarge command to the server. The advantage of
  746. * this function over \c __glXSendLargeCommand is that callers can use the
  747. * data buffer in the GLX context and may be able to avoid allocating an
  748. * extra buffer. The disadvantage is the clients will have to do more
  749. * GLX protocol work (i.e., calculating \c totalRequests, etc.).
  750. *
  751. * \sa __glXSendLargeCommand
  752. *
  753. * \param gc GLX context
  754. * \param requestNumber Which part of the whole command is this? The first
  755. * request is 1.
  756. * \param totalRequests How many requests will there be?
  757. * \param data Command data.
  758. * \param dataLen Size, in bytes, of the command data.
  759. */
  760. _X_HIDDEN void
  761. __glXSendLargeChunk(__GLXcontext * gc, GLint requestNumber,
  762. GLint totalRequests, const GLvoid * data, GLint dataLen)
  763. {
  764. Display *dpy = gc->currentDpy;
  765. #ifdef USE_XCB
  766. xcb_connection_t *c = XGetXCBConnection(dpy);
  767. xcb_glx_render_large(c, gc->currentContextTag, requestNumber,
  768. totalRequests, dataLen, data);
  769. #else
  770. xGLXRenderLargeReq *req;
  771. if (requestNumber == 1) {
  772. LockDisplay(dpy);
  773. }
  774. GetReq(GLXRenderLarge, req);
  775. req->reqType = gc->majorOpcode;
  776. req->glxCode = X_GLXRenderLarge;
  777. req->contextTag = gc->currentContextTag;
  778. req->length += (dataLen + 3) >> 2;
  779. req->requestNumber = requestNumber;
  780. req->requestTotal = totalRequests;
  781. req->dataBytes = dataLen;
  782. Data(dpy, data, dataLen);
  783. if (requestNumber == totalRequests) {
  784. UnlockDisplay(dpy);
  785. SyncHandle();
  786. }
  787. #endif /* USE_XCB */
  788. }
  789. /**
  790. * Send a command that is too large for the GLXRender protocol request.
  791. *
  792. * Send a large command, one that is too large for some reason to
  793. * send using the GLXRender protocol request. One reason to send
  794. * a large command is to avoid copying the data.
  795. *
  796. * \param ctx GLX context
  797. * \param header Header data.
  798. * \param headerLen Size, in bytes, of the header data. It is assumed that
  799. * the header data will always be small enough to fit in
  800. * a single X protocol packet.
  801. * \param data Command data.
  802. * \param dataLen Size, in bytes, of the command data.
  803. */
  804. _X_HIDDEN void
  805. __glXSendLargeCommand(__GLXcontext * ctx,
  806. const GLvoid * header, GLint headerLen,
  807. const GLvoid * data, GLint dataLen)
  808. {
  809. GLint maxSize;
  810. GLint totalRequests, requestNumber;
  811. /*
  812. ** Calculate the maximum amount of data can be stuffed into a single
  813. ** packet. sz_xGLXRenderReq is added because bufSize is the maximum
  814. ** packet size minus sz_xGLXRenderReq.
  815. */
  816. maxSize = (ctx->bufSize + sz_xGLXRenderReq) - sz_xGLXRenderLargeReq;
  817. totalRequests = 1 + (dataLen / maxSize);
  818. if (dataLen % maxSize)
  819. totalRequests++;
  820. /*
  821. ** Send all of the command, except the large array, as one request.
  822. */
  823. assert(headerLen <= maxSize);
  824. __glXSendLargeChunk(ctx, 1, totalRequests, header, headerLen);
  825. /*
  826. ** Send enough requests until the whole array is sent.
  827. */
  828. for (requestNumber = 2; requestNumber <= (totalRequests - 1);
  829. requestNumber++) {
  830. __glXSendLargeChunk(ctx, requestNumber, totalRequests, data, maxSize);
  831. data = (const GLvoid *) (((const GLubyte *) data) + maxSize);
  832. dataLen -= maxSize;
  833. assert(dataLen > 0);
  834. }
  835. assert(dataLen <= maxSize);
  836. __glXSendLargeChunk(ctx, requestNumber, totalRequests, data, dataLen);
  837. }
  838. /************************************************************************/
  839. #ifdef DEBUG
  840. _X_HIDDEN void
  841. __glXDumpDrawBuffer(__GLXcontext * ctx)
  842. {
  843. GLubyte *p = ctx->buf;
  844. GLubyte *end = ctx->pc;
  845. GLushort opcode, length;
  846. while (p < end) {
  847. /* Fetch opcode */
  848. opcode = *((GLushort *) p);
  849. length = *((GLushort *) (p + 2));
  850. printf("%2x: %5d: ", opcode, length);
  851. length -= 4;
  852. p += 4;
  853. while (length > 0) {
  854. printf("%08x ", *((unsigned *) p));
  855. p += 4;
  856. length -= 4;
  857. }
  858. printf("\n");
  859. }
  860. }
  861. #endif