Clone of mesa.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

dri_glx.c 21KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749
  1. /**************************************************************************
  2. Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
  3. All Rights Reserved.
  4. Permission is hereby granted, free of charge, to any person obtaining a
  5. copy of this software and associated documentation files (the
  6. "Software"), to deal in the Software without restriction, including
  7. without limitation the rights to use, copy, modify, merge, publish,
  8. distribute, sub license, and/or sell copies of the Software, and to
  9. permit persons to whom the Software is furnished to do so, subject to
  10. the following conditions:
  11. The above copyright notice and this permission notice (including the
  12. next paragraph) shall be included in all copies or substantial portions
  13. of the Software.
  14. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  15. OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  16. MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
  17. IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
  18. ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  19. TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  20. SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  21. **************************************************************************/
  22. /*
  23. * Authors:
  24. * Kevin E. Martin <kevin@precisioninsight.com>
  25. * Brian Paul <brian@precisioninsight.com>
  26. *
  27. */
  28. #ifdef GLX_DIRECT_RENDERING
  29. #include <X11/Xlib.h>
  30. #include <X11/extensions/Xfixes.h>
  31. #include <X11/extensions/Xdamage.h>
  32. #include "glxclient.h"
  33. #include "xf86dri.h"
  34. #include "dri2.h"
  35. #include "sarea.h"
  36. #include <dlfcn.h>
  37. #include <sys/types.h>
  38. #include <sys/mman.h>
  39. #include "xf86drm.h"
  40. #include "dri_common.h"
  41. typedef struct __GLXDRIdisplayPrivateRec __GLXDRIdisplayPrivate;
  42. typedef struct __GLXDRIcontextPrivateRec __GLXDRIcontextPrivate;
  43. struct __GLXDRIdisplayPrivateRec
  44. {
  45. __GLXDRIdisplay base;
  46. /*
  47. ** XFree86-DRI version information
  48. */
  49. int driMajor;
  50. int driMinor;
  51. int driPatch;
  52. };
  53. struct __GLXDRIcontextPrivateRec
  54. {
  55. __GLXDRIcontext base;
  56. __DRIcontext *driContext;
  57. XID hwContextID;
  58. __GLXscreenConfigs *psc;
  59. };
  60. /*
  61. * Given a display pointer and screen number, determine the name of
  62. * the DRI driver for the screen. (I.e. "r128", "tdfx", etc).
  63. * Return True for success, False for failure.
  64. */
  65. static Bool
  66. driGetDriverName(Display * dpy, int scrNum, char **driverName)
  67. {
  68. int directCapable;
  69. Bool b;
  70. int event, error;
  71. int driverMajor, driverMinor, driverPatch;
  72. *driverName = NULL;
  73. if (XF86DRIQueryExtension(dpy, &event, &error)) { /* DRI1 */
  74. if (!XF86DRIQueryDirectRenderingCapable(dpy, scrNum, &directCapable)) {
  75. ErrorMessageF("XF86DRIQueryDirectRenderingCapable failed\n");
  76. return False;
  77. }
  78. if (!directCapable) {
  79. ErrorMessageF("XF86DRIQueryDirectRenderingCapable returned false\n");
  80. return False;
  81. }
  82. b = XF86DRIGetClientDriverName(dpy, scrNum, &driverMajor, &driverMinor,
  83. &driverPatch, driverName);
  84. if (!b) {
  85. ErrorMessageF("Cannot determine driver name for screen %d\n",
  86. scrNum);
  87. return False;
  88. }
  89. InfoMessageF("XF86DRIGetClientDriverName: %d.%d.%d %s (screen %d)\n",
  90. driverMajor, driverMinor, driverPatch, *driverName,
  91. scrNum);
  92. return True;
  93. }
  94. else if (DRI2QueryExtension(dpy, &event, &error)) { /* DRI2 */
  95. char *dev;
  96. Bool ret = DRI2Connect(dpy, RootWindow(dpy, scrNum), driverName, &dev);
  97. if (ret)
  98. Xfree(dev);
  99. return ret;
  100. }
  101. return False;
  102. }
  103. /*
  104. * Exported function for querying the DRI driver for a given screen.
  105. *
  106. * The returned char pointer points to a static array that will be
  107. * overwritten by subsequent calls.
  108. */
  109. PUBLIC const char *
  110. glXGetScreenDriver(Display * dpy, int scrNum)
  111. {
  112. static char ret[32];
  113. char *driverName;
  114. if (driGetDriverName(dpy, scrNum, &driverName)) {
  115. int len;
  116. if (!driverName)
  117. return NULL;
  118. len = strlen(driverName);
  119. if (len >= 31)
  120. return NULL;
  121. memcpy(ret, driverName, len + 1);
  122. Xfree(driverName);
  123. return ret;
  124. }
  125. return NULL;
  126. }
  127. /*
  128. * Exported function for obtaining a driver's option list (UTF-8 encoded XML).
  129. *
  130. * The returned char pointer points directly into the driver. Therefore
  131. * it should be treated as a constant.
  132. *
  133. * If the driver was not found or does not support configuration NULL is
  134. * returned.
  135. *
  136. * Note: The driver remains opened after this function returns.
  137. */
  138. PUBLIC const char *
  139. glXGetDriverConfig(const char *driverName)
  140. {
  141. void *handle = driOpenDriver(driverName);
  142. if (handle)
  143. return dlsym(handle, "__driConfigOptions");
  144. else
  145. return NULL;
  146. }
  147. #ifdef XDAMAGE_1_1_INTERFACE
  148. static GLboolean
  149. has_damage_post(Display * dpy)
  150. {
  151. static GLboolean inited = GL_FALSE;
  152. static GLboolean has_damage;
  153. if (!inited) {
  154. int major, minor;
  155. if (XDamageQueryVersion(dpy, &major, &minor) &&
  156. major == 1 && minor >= 1) {
  157. has_damage = GL_TRUE;
  158. }
  159. else {
  160. has_damage = GL_FALSE;
  161. }
  162. inited = GL_TRUE;
  163. }
  164. return has_damage;
  165. }
  166. static void
  167. __glXReportDamage(__DRIdrawable * driDraw,
  168. int x, int y,
  169. drm_clip_rect_t * rects, int num_rects,
  170. GLboolean front_buffer, void *loaderPrivate)
  171. {
  172. XRectangle *xrects;
  173. XserverRegion region;
  174. int i;
  175. int x_off, y_off;
  176. __GLXDRIdrawable *glxDraw = loaderPrivate;
  177. __GLXscreenConfigs *psc = glxDraw->psc;
  178. Display *dpy = psc->dpy;
  179. Drawable drawable;
  180. if (!has_damage_post(dpy))
  181. return;
  182. if (front_buffer) {
  183. x_off = x;
  184. y_off = y;
  185. drawable = RootWindow(dpy, psc->scr);
  186. }
  187. else {
  188. x_off = 0;
  189. y_off = 0;
  190. drawable = glxDraw->xDrawable;
  191. }
  192. xrects = malloc(sizeof(XRectangle) * num_rects);
  193. if (xrects == NULL)
  194. return;
  195. for (i = 0; i < num_rects; i++) {
  196. xrects[i].x = rects[i].x1 + x_off;
  197. xrects[i].y = rects[i].y1 + y_off;
  198. xrects[i].width = rects[i].x2 - rects[i].x1;
  199. xrects[i].height = rects[i].y2 - rects[i].y1;
  200. }
  201. region = XFixesCreateRegion(dpy, xrects, num_rects);
  202. free(xrects);
  203. XDamageAdd(dpy, drawable, region);
  204. XFixesDestroyRegion(dpy, region);
  205. }
  206. static const __DRIdamageExtension damageExtension = {
  207. {__DRI_DAMAGE, __DRI_DAMAGE_VERSION},
  208. __glXReportDamage,
  209. };
  210. #endif
  211. static GLboolean
  212. __glXDRIGetDrawableInfo(__DRIdrawable * drawable,
  213. unsigned int *index, unsigned int *stamp,
  214. int *X, int *Y, int *W, int *H,
  215. int *numClipRects, drm_clip_rect_t ** pClipRects,
  216. int *backX, int *backY,
  217. int *numBackClipRects,
  218. drm_clip_rect_t ** pBackClipRects,
  219. void *loaderPrivate)
  220. {
  221. __GLXDRIdrawable *glxDraw = loaderPrivate;
  222. __GLXscreenConfigs *psc = glxDraw->psc;
  223. Display *dpy = psc->dpy;
  224. return XF86DRIGetDrawableInfo(dpy, psc->scr, glxDraw->drawable,
  225. index, stamp, X, Y, W, H,
  226. numClipRects, pClipRects,
  227. backX, backY,
  228. numBackClipRects, pBackClipRects);
  229. }
  230. static const __DRIgetDrawableInfoExtension getDrawableInfoExtension = {
  231. {__DRI_GET_DRAWABLE_INFO, __DRI_GET_DRAWABLE_INFO_VERSION},
  232. __glXDRIGetDrawableInfo
  233. };
  234. static const __DRIextension *loader_extensions[] = {
  235. &systemTimeExtension.base,
  236. &getDrawableInfoExtension.base,
  237. #ifdef XDAMAGE_1_1_INTERFACE
  238. &damageExtension.base,
  239. #endif
  240. NULL
  241. };
  242. /**
  243. * Perform the required libGL-side initialization and call the client-side
  244. * driver's \c __driCreateNewScreen function.
  245. *
  246. * \param dpy Display pointer.
  247. * \param scrn Screen number on the display.
  248. * \param psc DRI screen information.
  249. * \param driDpy DRI display information.
  250. * \param createNewScreen Pointer to the client-side driver's
  251. * \c __driCreateNewScreen function.
  252. * \returns A pointer to the \c __DRIscreen structure returned by
  253. * the client-side driver on success, or \c NULL on failure.
  254. */
  255. static void *
  256. CallCreateNewScreen(Display * dpy, int scrn, __GLXscreenConfigs * psc,
  257. __GLXDRIdisplayPrivate * driDpy)
  258. {
  259. void *psp = NULL;
  260. drm_handle_t hSAREA;
  261. drmAddress pSAREA = MAP_FAILED;
  262. char *BusID;
  263. __DRIversion ddx_version;
  264. __DRIversion dri_version;
  265. __DRIversion drm_version;
  266. __DRIframebuffer framebuffer;
  267. int fd = -1;
  268. int status;
  269. drm_magic_t magic;
  270. drmVersionPtr version;
  271. int newlyopened;
  272. char *driverName;
  273. drm_handle_t hFB;
  274. int junk;
  275. const __DRIconfig **driver_configs;
  276. __GLcontextModes *visual;
  277. /* DRI protocol version. */
  278. dri_version.major = driDpy->driMajor;
  279. dri_version.minor = driDpy->driMinor;
  280. dri_version.patch = driDpy->driPatch;
  281. framebuffer.base = MAP_FAILED;
  282. framebuffer.dev_priv = NULL;
  283. framebuffer.size = 0;
  284. if (!XF86DRIOpenConnection(dpy, scrn, &hSAREA, &BusID)) {
  285. ErrorMessageF("XF86DRIOpenConnection failed\n");
  286. goto handle_error;
  287. }
  288. fd = drmOpenOnce(NULL, BusID, &newlyopened);
  289. Xfree(BusID); /* No longer needed */
  290. if (fd < 0) {
  291. ErrorMessageF("drmOpenOnce failed (%s)\n", strerror(-fd));
  292. goto handle_error;
  293. }
  294. if (drmGetMagic(fd, &magic)) {
  295. ErrorMessageF("drmGetMagic failed\n");
  296. goto handle_error;
  297. }
  298. version = drmGetVersion(fd);
  299. if (version) {
  300. drm_version.major = version->version_major;
  301. drm_version.minor = version->version_minor;
  302. drm_version.patch = version->version_patchlevel;
  303. drmFreeVersion(version);
  304. }
  305. else {
  306. drm_version.major = -1;
  307. drm_version.minor = -1;
  308. drm_version.patch = -1;
  309. }
  310. if (newlyopened && !XF86DRIAuthConnection(dpy, scrn, magic)) {
  311. ErrorMessageF("XF86DRIAuthConnection failed\n");
  312. goto handle_error;
  313. }
  314. /* Get device name (like "tdfx") and the ddx version numbers.
  315. * We'll check the version in each DRI driver's "createNewScreen"
  316. * function. */
  317. if (!XF86DRIGetClientDriverName(dpy, scrn,
  318. &ddx_version.major,
  319. &ddx_version.minor,
  320. &ddx_version.patch, &driverName)) {
  321. ErrorMessageF("XF86DRIGetClientDriverName failed\n");
  322. goto handle_error;
  323. }
  324. Xfree(driverName); /* No longer needed. */
  325. /*
  326. * Get device-specific info. pDevPriv will point to a struct
  327. * (such as DRIRADEONRec in xfree86/driver/ati/radeon_dri.h) that
  328. * has information about the screen size, depth, pitch, ancilliary
  329. * buffers, DRM mmap handles, etc.
  330. */
  331. if (!XF86DRIGetDeviceInfo(dpy, scrn, &hFB, &junk,
  332. &framebuffer.size, &framebuffer.stride,
  333. &framebuffer.dev_priv_size,
  334. &framebuffer.dev_priv)) {
  335. ErrorMessageF("XF86DRIGetDeviceInfo failed");
  336. goto handle_error;
  337. }
  338. framebuffer.width = DisplayWidth(dpy, scrn);
  339. framebuffer.height = DisplayHeight(dpy, scrn);
  340. /* Map the framebuffer region. */
  341. status = drmMap(fd, hFB, framebuffer.size,
  342. (drmAddressPtr) & framebuffer.base);
  343. if (status != 0) {
  344. ErrorMessageF("drmMap of framebuffer failed (%s)", strerror(-status));
  345. goto handle_error;
  346. }
  347. /* Map the SAREA region. Further mmap regions may be setup in
  348. * each DRI driver's "createNewScreen" function.
  349. */
  350. status = drmMap(fd, hSAREA, SAREA_MAX, &pSAREA);
  351. if (status != 0) {
  352. ErrorMessageF("drmMap of SAREA failed (%s)", strerror(-status));
  353. goto handle_error;
  354. }
  355. psp = (*psc->legacy->createNewScreen) (scrn,
  356. &ddx_version,
  357. &dri_version,
  358. &drm_version,
  359. &framebuffer,
  360. pSAREA,
  361. fd,
  362. loader_extensions,
  363. &driver_configs, psc);
  364. if (psp == NULL) {
  365. ErrorMessageF("Calling driver entry point failed");
  366. goto handle_error;
  367. }
  368. psc->configs = driConvertConfigs(psc->core, psc->configs, driver_configs);
  369. psc->visuals = driConvertConfigs(psc->core, psc->visuals, driver_configs);
  370. psc->driver_configs = driver_configs;
  371. /* Visuals with depth != screen depth are subject to automatic compositing
  372. * in the X server, so DRI1 can't render to them properly. Mark them as
  373. * non-conformant to prevent apps from picking them up accidentally.
  374. */
  375. for (visual = psc->visuals; visual; visual = visual->next) {
  376. XVisualInfo template;
  377. XVisualInfo *visuals;
  378. int num_visuals;
  379. long mask;
  380. template.visualid = visual->visualID;
  381. mask = VisualIDMask;
  382. visuals = XGetVisualInfo(dpy, mask, &template, &num_visuals);
  383. if (visuals) {
  384. if (num_visuals > 0 && visuals->depth != DefaultDepth(dpy, scrn))
  385. visual->visualRating = GLX_NON_CONFORMANT_CONFIG;
  386. XFree(visuals);
  387. }
  388. }
  389. return psp;
  390. handle_error:
  391. if (pSAREA != MAP_FAILED)
  392. drmUnmap(pSAREA, SAREA_MAX);
  393. if (framebuffer.base != MAP_FAILED)
  394. drmUnmap((drmAddress) framebuffer.base, framebuffer.size);
  395. if (framebuffer.dev_priv != NULL)
  396. Xfree(framebuffer.dev_priv);
  397. if (fd >= 0)
  398. drmCloseOnce(fd);
  399. XF86DRICloseConnection(dpy, scrn);
  400. ErrorMessageF("reverting to software direct rendering\n");
  401. return NULL;
  402. }
  403. static void
  404. driDestroyContext(__GLXDRIcontext * context,
  405. __GLXscreenConfigs * psc, Display * dpy)
  406. {
  407. __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context;
  408. (*psc->core->destroyContext) (pcp->driContext);
  409. XF86DRIDestroyContext(psc->dpy, psc->scr, pcp->hwContextID);
  410. Xfree(pcp);
  411. }
  412. static Bool
  413. driBindContext(__GLXDRIcontext * context,
  414. __GLXDRIdrawable * draw, __GLXDRIdrawable * read)
  415. {
  416. __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context;
  417. const __DRIcoreExtension *core = pcp->psc->core;
  418. return (*core->bindContext) (pcp->driContext,
  419. draw->driDrawable, read->driDrawable);
  420. }
  421. static void
  422. driUnbindContext(__GLXDRIcontext * context)
  423. {
  424. __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context;
  425. const __DRIcoreExtension *core = pcp->psc->core;
  426. (*core->unbindContext) (pcp->driContext);
  427. }
  428. static __GLXDRIcontext *
  429. driCreateContext(__GLXscreenConfigs * psc,
  430. const __GLcontextModes * mode,
  431. GLXContext gc, GLXContext shareList, int renderType)
  432. {
  433. __GLXDRIcontextPrivate *pcp, *pcp_shared;
  434. drm_context_t hwContext;
  435. __DRIcontext *shared = NULL;
  436. __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) mode;
  437. if (!psc || !psc->driScreen)
  438. return NULL;
  439. if (shareList) {
  440. pcp_shared = (__GLXDRIcontextPrivate *) shareList->driContext;
  441. shared = pcp_shared->driContext;
  442. }
  443. pcp = Xmalloc(sizeof *pcp);
  444. if (pcp == NULL)
  445. return NULL;
  446. pcp->psc = psc;
  447. if (!XF86DRICreateContextWithConfig(psc->dpy, psc->scr,
  448. mode->visualID,
  449. &pcp->hwContextID, &hwContext)) {
  450. Xfree(pcp);
  451. return NULL;
  452. }
  453. pcp->driContext =
  454. (*psc->legacy->createNewContext) (psc->__driScreen,
  455. config->driConfig,
  456. renderType, shared, hwContext, pcp);
  457. if (pcp->driContext == NULL) {
  458. XF86DRIDestroyContext(psc->dpy, psc->scr, pcp->hwContextID);
  459. Xfree(pcp);
  460. return NULL;
  461. }
  462. pcp->base.destroyContext = driDestroyContext;
  463. pcp->base.bindContext = driBindContext;
  464. pcp->base.unbindContext = driUnbindContext;
  465. return &pcp->base;
  466. }
  467. static void
  468. driDestroyDrawable(__GLXDRIdrawable * pdraw)
  469. {
  470. __GLXscreenConfigs *psc = pdraw->psc;
  471. (*psc->core->destroyDrawable) (pdraw->driDrawable);
  472. XF86DRIDestroyDrawable(psc->dpy, psc->scr, pdraw->drawable);
  473. Xfree(pdraw);
  474. }
  475. static __GLXDRIdrawable *
  476. driCreateDrawable(__GLXscreenConfigs * psc,
  477. XID xDrawable,
  478. GLXDrawable drawable, const __GLcontextModes * modes)
  479. {
  480. __GLXDRIdrawable *pdraw;
  481. drm_drawable_t hwDrawable;
  482. void *empty_attribute_list = NULL;
  483. __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) modes;
  484. /* Old dri can't handle GLX 1.3+ drawable constructors. */
  485. if (xDrawable != drawable)
  486. return NULL;
  487. pdraw = Xmalloc(sizeof(*pdraw));
  488. if (!pdraw)
  489. return NULL;
  490. pdraw->drawable = drawable;
  491. pdraw->psc = psc;
  492. if (!XF86DRICreateDrawable(psc->dpy, psc->scr, drawable, &hwDrawable)) {
  493. Xfree(pdraw);
  494. return NULL;
  495. }
  496. /* Create a new drawable */
  497. pdraw->driDrawable =
  498. (*psc->legacy->createNewDrawable) (psc->__driScreen,
  499. config->driConfig,
  500. hwDrawable,
  501. GLX_WINDOW_BIT,
  502. empty_attribute_list, pdraw);
  503. if (!pdraw->driDrawable) {
  504. XF86DRIDestroyDrawable(psc->dpy, psc->scr, drawable);
  505. Xfree(pdraw);
  506. return NULL;
  507. }
  508. pdraw->destroyDrawable = driDestroyDrawable;
  509. return pdraw;
  510. }
  511. static int64_t
  512. driSwapBuffers(__GLXDRIdrawable * pdraw, int64_t unused1, int64_t unused2,
  513. int64_t unused3)
  514. {
  515. (*pdraw->psc->core->swapBuffers) (pdraw->driDrawable);
  516. return 0;
  517. }
  518. static void
  519. driCopySubBuffer(__GLXDRIdrawable * pdraw,
  520. int x, int y, int width, int height)
  521. {
  522. (*pdraw->psc->driCopySubBuffer->copySubBuffer) (pdraw->driDrawable,
  523. x, y, width, height);
  524. }
  525. static void
  526. driDestroyScreen(__GLXscreenConfigs * psc)
  527. {
  528. /* Free the direct rendering per screen data */
  529. if (psc->__driScreen)
  530. (*psc->core->destroyScreen) (psc->__driScreen);
  531. psc->__driScreen = NULL;
  532. if (psc->driver)
  533. dlclose(psc->driver);
  534. }
  535. static __GLXDRIscreen *
  536. driCreateScreen(__GLXscreenConfigs * psc, int screen,
  537. __GLXdisplayPrivate * priv)
  538. {
  539. __GLXDRIdisplayPrivate *pdp;
  540. __GLXDRIscreen *psp;
  541. const __DRIextension **extensions;
  542. char *driverName;
  543. int i;
  544. psp = Xcalloc(1, sizeof *psp);
  545. if (psp == NULL)
  546. return NULL;
  547. if (!driGetDriverName(priv->dpy, screen, &driverName)) {
  548. Xfree(psp);
  549. return NULL;
  550. }
  551. psc->driver = driOpenDriver(driverName);
  552. Xfree(driverName);
  553. if (psc->driver == NULL) {
  554. Xfree(psp);
  555. return NULL;
  556. }
  557. extensions = dlsym(psc->driver, __DRI_DRIVER_EXTENSIONS);
  558. if (extensions == NULL) {
  559. ErrorMessageF("driver exports no extensions (%s)\n", dlerror());
  560. Xfree(psp);
  561. return NULL;
  562. }
  563. for (i = 0; extensions[i]; i++) {
  564. if (strcmp(extensions[i]->name, __DRI_CORE) == 0)
  565. psc->core = (__DRIcoreExtension *) extensions[i];
  566. if (strcmp(extensions[i]->name, __DRI_LEGACY) == 0)
  567. psc->legacy = (__DRIlegacyExtension *) extensions[i];
  568. }
  569. if (psc->core == NULL || psc->legacy == NULL) {
  570. Xfree(psp);
  571. return NULL;
  572. }
  573. pdp = (__GLXDRIdisplayPrivate *) priv->driDisplay;
  574. psc->__driScreen = CallCreateNewScreen(psc->dpy, screen, psc, pdp);
  575. if (psc->__driScreen == NULL) {
  576. dlclose(psc->driver);
  577. Xfree(psp);
  578. return NULL;
  579. }
  580. driBindExtensions(psc);
  581. driBindCommonExtensions(psc);
  582. if (psc->driCopySubBuffer)
  583. psp->copySubBuffer = driCopySubBuffer;
  584. psp->destroyScreen = driDestroyScreen;
  585. psp->createContext = driCreateContext;
  586. psp->createDrawable = driCreateDrawable;
  587. psp->swapBuffers = driSwapBuffers;
  588. psp->waitX = NULL;
  589. psp->waitGL = NULL;
  590. return psp;
  591. }
  592. /* Called from __glXFreeDisplayPrivate.
  593. */
  594. static void
  595. driDestroyDisplay(__GLXDRIdisplay * dpy)
  596. {
  597. Xfree(dpy);
  598. }
  599. /*
  600. * Allocate, initialize and return a __DRIdisplayPrivate object.
  601. * This is called from __glXInitialize() when we are given a new
  602. * display pointer.
  603. */
  604. _X_HIDDEN __GLXDRIdisplay *
  605. driCreateDisplay(Display * dpy)
  606. {
  607. __GLXDRIdisplayPrivate *pdpyp;
  608. int eventBase, errorBase;
  609. int major, minor, patch;
  610. if (!XF86DRIQueryExtension(dpy, &eventBase, &errorBase)) {
  611. return NULL;
  612. }
  613. if (!XF86DRIQueryVersion(dpy, &major, &minor, &patch)) {
  614. return NULL;
  615. }
  616. pdpyp = Xmalloc(sizeof *pdpyp);
  617. if (!pdpyp) {
  618. return NULL;
  619. }
  620. pdpyp->driMajor = major;
  621. pdpyp->driMinor = minor;
  622. pdpyp->driPatch = patch;
  623. pdpyp->base.destroyDisplay = driDestroyDisplay;
  624. pdpyp->base.createScreen = driCreateScreen;
  625. return &pdpyp->base;
  626. }
  627. #endif /* GLX_DIRECT_RENDERING */