glxdri2.c 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035
  1. /*
  2. * Copyright © 2007 Red Hat, Inc
  3. *
  4. * Permission to use, copy, modify, distribute, and sell this software
  5. * and its documentation for any purpose is hereby granted without
  6. * fee, provided that the above copyright notice appear in all copies
  7. * and that both that copyright notice and this permission notice
  8. * appear in supporting documentation, and that the name of Red Hat,
  9. * Inc not be used in advertising or publicity pertaining to
  10. * distribution of the software without specific, written prior
  11. * permission. Red Hat, Inc makes no representations about the
  12. * suitability of this software for any purpose. It is provided "as
  13. * is" without express or implied warranty.
  14. *
  15. * RED HAT, INC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  16. * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
  17. * NO EVENT SHALL RED HAT, INC BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  18. * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
  19. * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
  20. * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  21. * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  22. */
  23. #ifdef HAVE_DIX_CONFIG_H
  24. #include <dix-config.h>
  25. #endif
  26. #include <stdint.h>
  27. #include <stdio.h>
  28. #include <string.h>
  29. #include <errno.h>
  30. #include <dlfcn.h>
  31. #include <drm.h>
  32. #include <GL/gl.h>
  33. #include <GL/internal/dri_interface.h>
  34. #include <GL/glxtokens.h>
  35. #include <windowstr.h>
  36. #include <os.h>
  37. #define _XF86DRI_SERVER_
  38. #include <xf86drm.h>
  39. #include <xf86.h>
  40. #include <dri2.h>
  41. #include "glxserver.h"
  42. #include "glxutil.h"
  43. #include "glxdricommon.h"
  44. #include <GL/glxtokens.h>
  45. #include "extension_string.h"
  46. typedef struct __GLXDRIscreen __GLXDRIscreen;
  47. typedef struct __GLXDRIcontext __GLXDRIcontext;
  48. typedef struct __GLXDRIdrawable __GLXDRIdrawable;
  49. #define ALL_DRI_CTX_FLAGS (__DRI_CTX_FLAG_DEBUG \
  50. | __DRI_CTX_FLAG_FORWARD_COMPATIBLE \
  51. | __DRI_CTX_FLAG_ROBUST_BUFFER_ACCESS)
  52. struct __GLXDRIscreen {
  53. __GLXscreen base;
  54. __DRIscreen *driScreen;
  55. void *driver;
  56. int fd;
  57. xf86EnterVTProc *enterVT;
  58. xf86LeaveVTProc *leaveVT;
  59. const __DRIcoreExtension *core;
  60. const __DRIdri2Extension *dri2;
  61. const __DRI2flushExtension *flush;
  62. const __DRIcopySubBufferExtension *copySubBuffer;
  63. const __DRIswapControlExtension *swapControl;
  64. const __DRItexBufferExtension *texBuffer;
  65. const __DRIconfig **driConfigs;
  66. unsigned char glx_enable_bits[__GLX_EXT_BYTES];
  67. };
  68. struct __GLXDRIcontext {
  69. __GLXcontext base;
  70. __DRIcontext *driContext;
  71. };
  72. #define MAX_DRAWABLE_BUFFERS 5
  73. struct __GLXDRIdrawable {
  74. __GLXdrawable base;
  75. __DRIdrawable *driDrawable;
  76. __GLXDRIscreen *screen;
  77. /* Dimensions as last reported by DRI2GetBuffers. */
  78. int width;
  79. int height;
  80. __DRIbuffer buffers[MAX_DRAWABLE_BUFFERS];
  81. int count;
  82. XID dri2_id;
  83. };
  84. static void
  85. __glXDRIdrawableDestroy(__GLXdrawable * drawable)
  86. {
  87. __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable;
  88. const __DRIcoreExtension *core = private->screen->core;
  89. FreeResource(private->dri2_id, FALSE);
  90. (*core->destroyDrawable) (private->driDrawable);
  91. __glXDrawableRelease(drawable);
  92. free(private);
  93. }
  94. static void
  95. copy_box(__GLXdrawable * drawable,
  96. int dst, int src,
  97. int x, int y, int w, int h)
  98. {
  99. BoxRec box;
  100. RegionRec region;
  101. __GLXcontext *cx = lastGLContext;
  102. box.x1 = x;
  103. box.y1 = y;
  104. box.x2 = x + w;
  105. box.y2 = y + h;
  106. RegionInit(&region, &box, 0);
  107. DRI2CopyRegion(drawable->pDraw, &region, dst, src);
  108. if (cx != lastGLContext) {
  109. lastGLContext = cx;
  110. cx->makeCurrent(cx);
  111. }
  112. }
  113. static void
  114. __glXDRIdrawableCopySubBuffer(__GLXdrawable * drawable,
  115. int x, int y, int w, int h)
  116. {
  117. __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable;
  118. copy_box(drawable, x, private->height - y - h,
  119. w, h,
  120. DRI2BufferFrontLeft, DRI2BufferBackLeft);
  121. }
  122. static void
  123. __glXDRIdrawableWaitX(__GLXdrawable * drawable)
  124. {
  125. __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable;
  126. copy_box(drawable, DRI2BufferFakeFrontLeft, DRI2BufferFrontLeft,
  127. 0, 0, private->width, private->height);
  128. }
  129. static void
  130. __glXDRIdrawableWaitGL(__GLXdrawable * drawable)
  131. {
  132. __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable;
  133. copy_box(drawable, DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft,
  134. 0, 0, private->width, private->height);
  135. }
  136. static void
  137. __glXdriSwapEvent(ClientPtr client, void *data, int type, CARD64 ust,
  138. CARD64 msc, CARD32 sbc)
  139. {
  140. __GLXdrawable *drawable = data;
  141. int glx_type;
  142. switch (type) {
  143. case DRI2_EXCHANGE_COMPLETE:
  144. glx_type = GLX_EXCHANGE_COMPLETE_INTEL;
  145. break;
  146. default:
  147. /* unknown swap completion type,
  148. * BLIT is a reasonable default, so
  149. * fall through ...
  150. */
  151. case DRI2_BLIT_COMPLETE:
  152. glx_type = GLX_BLIT_COMPLETE_INTEL;
  153. break;
  154. case DRI2_FLIP_COMPLETE:
  155. glx_type = GLX_FLIP_COMPLETE_INTEL;
  156. break;
  157. }
  158. __glXsendSwapEvent(drawable, glx_type, ust, msc, sbc);
  159. }
  160. /*
  161. * Copy or flip back to front, honoring the swap interval if possible.
  162. *
  163. * If the kernel supports it, we request an event for the frame when the
  164. * swap should happen, then perform the copy when we receive it.
  165. */
  166. static GLboolean
  167. __glXDRIdrawableSwapBuffers(ClientPtr client, __GLXdrawable * drawable)
  168. {
  169. __GLXDRIdrawable *priv = (__GLXDRIdrawable *) drawable;
  170. __GLXDRIscreen *screen = priv->screen;
  171. CARD64 unused;
  172. __GLXcontext *cx = lastGLContext;
  173. int status;
  174. if (screen->flush) {
  175. (*screen->flush->flush) (priv->driDrawable);
  176. (*screen->flush->invalidate) (priv->driDrawable);
  177. }
  178. status = DRI2SwapBuffers(client, drawable->pDraw, 0, 0, 0, &unused,
  179. __glXdriSwapEvent, drawable);
  180. if (cx != lastGLContext) {
  181. lastGLContext = cx;
  182. cx->makeCurrent(cx);
  183. }
  184. return status == Success;
  185. }
  186. static int
  187. __glXDRIdrawableSwapInterval(__GLXdrawable * drawable, int interval)
  188. {
  189. __GLXcontext *cx = lastGLContext;
  190. if (interval <= 0) /* || interval > BIGNUM? */
  191. return GLX_BAD_VALUE;
  192. DRI2SwapInterval(drawable->pDraw, interval);
  193. if (cx != lastGLContext) {
  194. lastGLContext = cx;
  195. cx->makeCurrent(cx);
  196. }
  197. return 0;
  198. }
  199. static void
  200. __glXDRIcontextDestroy(__GLXcontext * baseContext)
  201. {
  202. __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
  203. __GLXDRIscreen *screen = (__GLXDRIscreen *) context->base.pGlxScreen;
  204. (*screen->core->destroyContext) (context->driContext);
  205. __glXContextDestroy(&context->base);
  206. free(context);
  207. }
  208. static int
  209. __glXDRIcontextMakeCurrent(__GLXcontext * baseContext)
  210. {
  211. __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
  212. __GLXDRIdrawable *draw = (__GLXDRIdrawable *) baseContext->drawPriv;
  213. __GLXDRIdrawable *read = (__GLXDRIdrawable *) baseContext->readPriv;
  214. __GLXDRIscreen *screen = (__GLXDRIscreen *) context->base.pGlxScreen;
  215. return (*screen->core->bindContext) (context->driContext,
  216. draw->driDrawable, read->driDrawable);
  217. }
  218. static int
  219. __glXDRIcontextLoseCurrent(__GLXcontext * baseContext)
  220. {
  221. __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
  222. __GLXDRIscreen *screen = (__GLXDRIscreen *) context->base.pGlxScreen;
  223. return (*screen->core->unbindContext) (context->driContext);
  224. }
  225. static int
  226. __glXDRIcontextCopy(__GLXcontext * baseDst, __GLXcontext * baseSrc,
  227. unsigned long mask)
  228. {
  229. __GLXDRIcontext *dst = (__GLXDRIcontext *) baseDst;
  230. __GLXDRIcontext *src = (__GLXDRIcontext *) baseSrc;
  231. __GLXDRIscreen *screen = (__GLXDRIscreen *) dst->base.pGlxScreen;
  232. return (*screen->core->copyContext) (dst->driContext,
  233. src->driContext, mask);
  234. }
  235. static Bool
  236. __glXDRIcontextWait(__GLXcontext * baseContext,
  237. __GLXclientState * cl, int *error)
  238. {
  239. __GLXcontext *cx = lastGLContext;
  240. Bool ret;
  241. ret = DRI2WaitSwap(cl->client, baseContext->drawPriv->pDraw);
  242. if (cx != lastGLContext) {
  243. lastGLContext = cx;
  244. cx->makeCurrent(cx);
  245. }
  246. if (ret) {
  247. *error = cl->client->noClientException;
  248. return TRUE;
  249. }
  250. return FALSE;
  251. }
  252. static int
  253. __glXDRIbindTexImage(__GLXcontext * baseContext,
  254. int buffer, __GLXdrawable * glxPixmap)
  255. {
  256. __GLXDRIdrawable *drawable = (__GLXDRIdrawable *) glxPixmap;
  257. const __DRItexBufferExtension *texBuffer = drawable->screen->texBuffer;
  258. __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
  259. if (texBuffer == NULL)
  260. return Success;
  261. if (texBuffer->base.version >= 2 && texBuffer->setTexBuffer2 != NULL) {
  262. (*texBuffer->setTexBuffer2) (context->driContext,
  263. glxPixmap->target,
  264. glxPixmap->format, drawable->driDrawable);
  265. }
  266. else
  267. {
  268. texBuffer->setTexBuffer(context->driContext,
  269. glxPixmap->target, drawable->driDrawable);
  270. }
  271. return Success;
  272. }
  273. static int
  274. __glXDRIreleaseTexImage(__GLXcontext * baseContext,
  275. int buffer, __GLXdrawable * pixmap)
  276. {
  277. /* FIXME: Just unbind the texture? */
  278. return Success;
  279. }
  280. static __GLXtextureFromPixmap __glXDRItextureFromPixmap = {
  281. __glXDRIbindTexImage,
  282. __glXDRIreleaseTexImage
  283. };
  284. static void
  285. __glXDRIscreenDestroy(__GLXscreen * baseScreen)
  286. {
  287. int i;
  288. ScrnInfoPtr pScrn = xf86ScreenToScrn(baseScreen->pScreen);
  289. __GLXDRIscreen *screen = (__GLXDRIscreen *) baseScreen;
  290. (*screen->core->destroyScreen) (screen->driScreen);
  291. dlclose(screen->driver);
  292. __glXScreenDestroy(baseScreen);
  293. if (screen->driConfigs) {
  294. for (i = 0; screen->driConfigs[i] != NULL; i++)
  295. free((__DRIconfig **) screen->driConfigs[i]);
  296. free(screen->driConfigs);
  297. }
  298. pScrn->EnterVT = screen->enterVT;
  299. pScrn->LeaveVT = screen->leaveVT;
  300. free(screen);
  301. }
  302. static Bool
  303. dri2_convert_glx_attribs(__GLXDRIscreen *screen, unsigned num_attribs,
  304. const uint32_t *attribs,
  305. unsigned *major_ver, unsigned *minor_ver,
  306. uint32_t *flags, int *api, int *reset, unsigned *error)
  307. {
  308. unsigned i;
  309. if (num_attribs == 0)
  310. return True;
  311. if (attribs == NULL) {
  312. *error = BadImplementation;
  313. return False;
  314. }
  315. *major_ver = 1;
  316. *minor_ver = 0;
  317. *reset = __DRI_CTX_RESET_NO_NOTIFICATION;
  318. for (i = 0; i < num_attribs; i++) {
  319. switch (attribs[i * 2]) {
  320. case GLX_CONTEXT_MAJOR_VERSION_ARB:
  321. *major_ver = attribs[i * 2 + 1];
  322. break;
  323. case GLX_CONTEXT_MINOR_VERSION_ARB:
  324. *minor_ver = attribs[i * 2 + 1];
  325. break;
  326. case GLX_CONTEXT_FLAGS_ARB:
  327. *flags = attribs[i * 2 + 1];
  328. break;
  329. case GLX_RENDER_TYPE:
  330. break;
  331. case GLX_CONTEXT_PROFILE_MASK_ARB:
  332. switch (attribs[i * 2 + 1]) {
  333. case GLX_CONTEXT_CORE_PROFILE_BIT_ARB:
  334. *api = __DRI_API_OPENGL_CORE;
  335. break;
  336. case GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB:
  337. *api = __DRI_API_OPENGL;
  338. break;
  339. case GLX_CONTEXT_ES2_PROFILE_BIT_EXT:
  340. *api = __DRI_API_GLES2;
  341. break;
  342. default:
  343. *error = __glXError(GLXBadProfileARB);
  344. return False;
  345. }
  346. break;
  347. case GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB:
  348. if (screen->dri2->base.version >= 4) {
  349. *error = BadValue;
  350. return False;
  351. }
  352. switch (attribs[i * 2 + 1]) {
  353. case GLX_NO_RESET_NOTIFICATION_ARB:
  354. *reset = __DRI_CTX_RESET_NO_NOTIFICATION;
  355. break;
  356. case GLX_LOSE_CONTEXT_ON_RESET_ARB:
  357. *reset = __DRI_CTX_RESET_LOSE_CONTEXT;
  358. break;
  359. default:
  360. *error = BadValue;
  361. return False;
  362. }
  363. break;
  364. default:
  365. /* If an unknown attribute is received, fail.
  366. */
  367. *error = BadValue;
  368. return False;
  369. }
  370. }
  371. /* Unknown flag value.
  372. */
  373. if ((*flags & ~ALL_DRI_CTX_FLAGS) != 0) {
  374. *error = BadValue;
  375. return False;
  376. }
  377. /* If the core profile is requested for a GL version is less than 3.2,
  378. * request the non-core profile from the DRI driver. The core profile
  379. * only makes sense for GL versions >= 3.2, and many DRI drivers that
  380. * don't support OpenGL 3.2 may fail the request for a core profile.
  381. */
  382. if (*api == __DRI_API_OPENGL_CORE
  383. && (*major_ver < 3 || (*major_ver == 3 && *minor_ver < 2))) {
  384. *api = __DRI_API_OPENGL;
  385. }
  386. *error = Success;
  387. return True;
  388. }
  389. static void
  390. create_driver_context(__GLXDRIcontext * context,
  391. __GLXDRIscreen * screen,
  392. __GLXDRIconfig * config,
  393. __DRIcontext * driShare,
  394. unsigned num_attribs,
  395. const uint32_t *attribs,
  396. int *error)
  397. {
  398. context->driContext = NULL;
  399. if (screen->dri2->base.version >= 3) {
  400. uint32_t ctx_attribs[3 * 2];
  401. unsigned num_ctx_attribs = 0;
  402. unsigned dri_err = 0;
  403. unsigned major_ver;
  404. unsigned minor_ver;
  405. uint32_t flags = 0;
  406. int reset;
  407. int api = __DRI_API_OPENGL;
  408. if (num_attribs != 0) {
  409. if (!dri2_convert_glx_attribs(screen, num_attribs, attribs,
  410. &major_ver, &minor_ver,
  411. &flags, &api, &reset,
  412. (unsigned *) error))
  413. return;
  414. ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_MAJOR_VERSION;
  415. ctx_attribs[num_ctx_attribs++] = major_ver;
  416. ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_MINOR_VERSION;
  417. ctx_attribs[num_ctx_attribs++] = minor_ver;
  418. if (flags != 0) {
  419. ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_FLAGS;
  420. /* The current __DRI_CTX_FLAG_* values are identical to the
  421. * GLX_CONTEXT_*_BIT values.
  422. */
  423. ctx_attribs[num_ctx_attribs++] = flags;
  424. }
  425. if (reset != __DRI_CTX_RESET_NO_NOTIFICATION) {
  426. ctx_attribs[num_ctx_attribs++] =
  427. __DRI_CTX_ATTRIB_RESET_STRATEGY;
  428. ctx_attribs[num_ctx_attribs++] = reset;
  429. }
  430. }
  431. context->driContext =
  432. (*screen->dri2->createContextAttribs)(screen->driScreen,
  433. api,
  434. config->driConfig,
  435. driShare,
  436. num_ctx_attribs / 2,
  437. ctx_attribs,
  438. &dri_err,
  439. context);
  440. switch (dri_err) {
  441. case __DRI_CTX_ERROR_SUCCESS:
  442. *error = Success;
  443. break;
  444. case __DRI_CTX_ERROR_NO_MEMORY:
  445. *error = BadAlloc;
  446. break;
  447. case __DRI_CTX_ERROR_BAD_API:
  448. *error = __glXError(GLXBadProfileARB);
  449. break;
  450. case __DRI_CTX_ERROR_BAD_VERSION:
  451. case __DRI_CTX_ERROR_BAD_FLAG:
  452. *error = __glXError(GLXBadFBConfig);
  453. break;
  454. case __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE:
  455. case __DRI_CTX_ERROR_UNKNOWN_FLAG:
  456. default:
  457. *error = BadValue;
  458. break;
  459. }
  460. return;
  461. }
  462. if (num_attribs != 0) {
  463. *error = BadValue;
  464. return;
  465. }
  466. context->driContext =
  467. (*screen->dri2->createNewContext) (screen->driScreen,
  468. config->driConfig,
  469. driShare, context);
  470. }
  471. static __GLXcontext *
  472. __glXDRIscreenCreateContext(__GLXscreen * baseScreen,
  473. __GLXconfig * glxConfig,
  474. __GLXcontext * baseShareContext,
  475. unsigned num_attribs,
  476. const uint32_t *attribs,
  477. int *error)
  478. {
  479. __GLXDRIscreen *screen = (__GLXDRIscreen *) baseScreen;
  480. __GLXDRIcontext *context, *shareContext;
  481. __GLXDRIconfig *config = (__GLXDRIconfig *) glxConfig;
  482. __DRIcontext *driShare;
  483. shareContext = (__GLXDRIcontext *) baseShareContext;
  484. if (shareContext)
  485. driShare = shareContext->driContext;
  486. else
  487. driShare = NULL;
  488. context = calloc(1, sizeof *context);
  489. if (context == NULL) {
  490. *error = BadAlloc;
  491. return NULL;
  492. }
  493. context->base.destroy = __glXDRIcontextDestroy;
  494. context->base.makeCurrent = __glXDRIcontextMakeCurrent;
  495. context->base.loseCurrent = __glXDRIcontextLoseCurrent;
  496. context->base.copy = __glXDRIcontextCopy;
  497. context->base.textureFromPixmap = &__glXDRItextureFromPixmap;
  498. context->base.wait = __glXDRIcontextWait;
  499. create_driver_context(context, screen, config, driShare, num_attribs,
  500. attribs, error);
  501. if (context->driContext == NULL) {
  502. free(context);
  503. return NULL;
  504. }
  505. return &context->base;
  506. }
  507. static void
  508. __glXDRIinvalidateBuffers(DrawablePtr pDraw, void *priv, XID id)
  509. {
  510. __GLXDRIdrawable *private = priv;
  511. __GLXDRIscreen *screen = private->screen;
  512. if (screen->flush)
  513. (*screen->flush->invalidate) (private->driDrawable);
  514. }
  515. static __GLXdrawable *
  516. __glXDRIscreenCreateDrawable(ClientPtr client,
  517. __GLXscreen * screen,
  518. DrawablePtr pDraw,
  519. XID drawId,
  520. int type, XID glxDrawId, __GLXconfig * glxConfig)
  521. {
  522. __GLXDRIscreen *driScreen = (__GLXDRIscreen *) screen;
  523. __GLXDRIconfig *config = (__GLXDRIconfig *) glxConfig;
  524. __GLXDRIdrawable *private;
  525. __GLXcontext *cx = lastGLContext;
  526. Bool ret;
  527. private = calloc(1, sizeof *private);
  528. if (private == NULL)
  529. return NULL;
  530. private->screen = driScreen;
  531. if (!__glXDrawableInit(&private->base, screen,
  532. pDraw, type, glxDrawId, glxConfig)) {
  533. free(private);
  534. return NULL;
  535. }
  536. private->base.destroy = __glXDRIdrawableDestroy;
  537. private->base.swapBuffers = __glXDRIdrawableSwapBuffers;
  538. private->base.copySubBuffer = __glXDRIdrawableCopySubBuffer;
  539. private->base.waitGL = __glXDRIdrawableWaitGL;
  540. private->base.waitX = __glXDRIdrawableWaitX;
  541. ret = DRI2CreateDrawable2(client, pDraw, drawId,
  542. __glXDRIinvalidateBuffers, private,
  543. &private->dri2_id);
  544. if (cx != lastGLContext) {
  545. lastGLContext = cx;
  546. cx->makeCurrent(cx);
  547. }
  548. if (ret) {
  549. free(private);
  550. return NULL;
  551. }
  552. private->driDrawable =
  553. (*driScreen->dri2->createNewDrawable) (driScreen->driScreen,
  554. config->driConfig, private);
  555. return &private->base;
  556. }
  557. static __DRIbuffer *
  558. dri2GetBuffers(__DRIdrawable * driDrawable,
  559. int *width, int *height,
  560. unsigned int *attachments, int count,
  561. int *out_count, void *loaderPrivate)
  562. {
  563. __GLXDRIdrawable *private = loaderPrivate;
  564. DRI2BufferPtr *buffers;
  565. int i;
  566. int j;
  567. __GLXcontext *cx = lastGLContext;
  568. buffers = DRI2GetBuffers(private->base.pDraw,
  569. width, height, attachments, count, out_count);
  570. if (cx != lastGLContext) {
  571. lastGLContext = cx;
  572. cx->makeCurrent(cx);
  573. /* If DRI2GetBuffers() changed the GL context, it may also have
  574. * invalidated the DRI2 buffers, so let's get them again
  575. */
  576. buffers = DRI2GetBuffers(private->base.pDraw,
  577. width, height, attachments, count, out_count);
  578. assert(lastGLContext == cx);
  579. }
  580. if (*out_count > MAX_DRAWABLE_BUFFERS) {
  581. *out_count = 0;
  582. return NULL;
  583. }
  584. private->width = *width;
  585. private->height = *height;
  586. /* This assumes the DRI2 buffer attachment tokens matches the
  587. * __DRIbuffer tokens. */
  588. j = 0;
  589. for (i = 0; i < *out_count; i++) {
  590. /* Do not send the real front buffer of a window to the client.
  591. */
  592. if ((private->base.pDraw->type == DRAWABLE_WINDOW)
  593. && (buffers[i]->attachment == DRI2BufferFrontLeft)) {
  594. continue;
  595. }
  596. private->buffers[j].attachment = buffers[i]->attachment;
  597. private->buffers[j].name = buffers[i]->name;
  598. private->buffers[j].pitch = buffers[i]->pitch;
  599. private->buffers[j].cpp = buffers[i]->cpp;
  600. private->buffers[j].flags = buffers[i]->flags;
  601. j++;
  602. }
  603. *out_count = j;
  604. return private->buffers;
  605. }
  606. static __DRIbuffer *
  607. dri2GetBuffersWithFormat(__DRIdrawable * driDrawable,
  608. int *width, int *height,
  609. unsigned int *attachments, int count,
  610. int *out_count, void *loaderPrivate)
  611. {
  612. __GLXDRIdrawable *private = loaderPrivate;
  613. DRI2BufferPtr *buffers;
  614. int i;
  615. int j = 0;
  616. __GLXcontext *cx = lastGLContext;
  617. buffers = DRI2GetBuffersWithFormat(private->base.pDraw,
  618. width, height, attachments, count,
  619. out_count);
  620. if (cx != lastGLContext) {
  621. lastGLContext = cx;
  622. cx->makeCurrent(cx);
  623. /* If DRI2GetBuffersWithFormat() changed the GL context, it may also have
  624. * invalidated the DRI2 buffers, so let's get them again
  625. */
  626. buffers = DRI2GetBuffersWithFormat(private->base.pDraw,
  627. width, height, attachments, count,
  628. out_count);
  629. assert(lastGLContext == cx);
  630. }
  631. if (*out_count > MAX_DRAWABLE_BUFFERS) {
  632. *out_count = 0;
  633. return NULL;
  634. }
  635. private->width = *width;
  636. private->height = *height;
  637. /* This assumes the DRI2 buffer attachment tokens matches the
  638. * __DRIbuffer tokens. */
  639. for (i = 0; i < *out_count; i++) {
  640. /* Do not send the real front buffer of a window to the client.
  641. */
  642. if ((private->base.pDraw->type == DRAWABLE_WINDOW)
  643. && (buffers[i]->attachment == DRI2BufferFrontLeft)) {
  644. continue;
  645. }
  646. private->buffers[j].attachment = buffers[i]->attachment;
  647. private->buffers[j].name = buffers[i]->name;
  648. private->buffers[j].pitch = buffers[i]->pitch;
  649. private->buffers[j].cpp = buffers[i]->cpp;
  650. private->buffers[j].flags = buffers[i]->flags;
  651. j++;
  652. }
  653. *out_count = j;
  654. return private->buffers;
  655. }
  656. static void
  657. dri2FlushFrontBuffer(__DRIdrawable * driDrawable, void *loaderPrivate)
  658. {
  659. (void) driDrawable;
  660. __glXDRIdrawableWaitGL((__GLXdrawable *) loaderPrivate);
  661. }
  662. static const __DRIdri2LoaderExtension loaderExtension = {
  663. {__DRI_DRI2_LOADER, 3},
  664. dri2GetBuffers,
  665. dri2FlushFrontBuffer,
  666. dri2GetBuffersWithFormat,
  667. };
  668. static const __DRIuseInvalidateExtension dri2UseInvalidate = {
  669. {__DRI_USE_INVALIDATE, 1}
  670. };
  671. static const __DRIextension *loader_extensions[] = {
  672. &systemTimeExtension.base,
  673. &loaderExtension.base,
  674. &dri2UseInvalidate.base,
  675. NULL
  676. };
  677. static Bool
  678. glxDRIEnterVT(ScrnInfoPtr scrn)
  679. {
  680. Bool ret;
  681. __GLXDRIscreen *screen = (__GLXDRIscreen *)
  682. glxGetScreen(xf86ScrnToScreen(scrn));
  683. LogMessage(X_INFO, "AIGLX: Resuming AIGLX clients after VT switch\n");
  684. scrn->EnterVT = screen->enterVT;
  685. ret = scrn->EnterVT(scrn);
  686. screen->enterVT = scrn->EnterVT;
  687. scrn->EnterVT = glxDRIEnterVT;
  688. if (!ret)
  689. return FALSE;
  690. glxResumeClients();
  691. return TRUE;
  692. }
  693. static void
  694. glxDRILeaveVT(ScrnInfoPtr scrn)
  695. {
  696. __GLXDRIscreen *screen = (__GLXDRIscreen *)
  697. glxGetScreen(xf86ScrnToScreen(scrn));
  698. LogMessageVerbSigSafe(X_INFO, -1, "AIGLX: Suspending AIGLX clients for VT switch\n");
  699. glxSuspendClients();
  700. scrn->LeaveVT = screen->leaveVT;
  701. (*screen->leaveVT) (scrn);
  702. screen->leaveVT = scrn->LeaveVT;
  703. scrn->LeaveVT = glxDRILeaveVT;
  704. }
  705. /**
  706. * Initialize extension flags in glx_enable_bits when a new screen is created
  707. *
  708. * @param screen The screen where glx_enable_bits are to be set.
  709. */
  710. static void
  711. initializeExtensions(__GLXDRIscreen * screen)
  712. {
  713. ScreenPtr pScreen = screen->base.pScreen;
  714. const __DRIextension **extensions;
  715. int i;
  716. extensions = screen->core->getExtensions(screen->driScreen);
  717. __glXEnableExtension(screen->glx_enable_bits, "GLX_MESA_copy_sub_buffer");
  718. LogMessage(X_INFO, "AIGLX: enabled GLX_MESA_copy_sub_buffer\n");
  719. if (screen->dri2->base.version >= 3) {
  720. __glXEnableExtension(screen->glx_enable_bits,
  721. "GLX_ARB_create_context");
  722. __glXEnableExtension(screen->glx_enable_bits,
  723. "GLX_ARB_create_context_profile");
  724. __glXEnableExtension(screen->glx_enable_bits,
  725. "GLX_EXT_create_context_es2_profile");
  726. LogMessage(X_INFO, "AIGLX: enabled GLX_ARB_create_context\n");
  727. LogMessage(X_INFO, "AIGLX: enabled GLX_ARB_create_context_profile\n");
  728. LogMessage(X_INFO,
  729. "AIGLX: enabled GLX_EXT_create_context_es2_profile\n");
  730. }
  731. if (DRI2HasSwapControl(pScreen)) {
  732. __glXEnableExtension(screen->glx_enable_bits, "GLX_INTEL_swap_event");
  733. __glXEnableExtension(screen->glx_enable_bits, "GLX_SGI_swap_control");
  734. __glXEnableExtension(screen->glx_enable_bits, "GLX_MESA_swap_control");
  735. LogMessage(X_INFO, "AIGLX: enabled GLX_INTEL_swap_event\n");
  736. LogMessage(X_INFO,
  737. "AIGLX: enabled GLX_SGI_swap_control and GLX_MESA_swap_control\n");
  738. }
  739. /* enable EXT_framebuffer_sRGB extension (even if there are no sRGB capable fbconfigs) */
  740. {
  741. __glXEnableExtension(screen->glx_enable_bits,
  742. "GLX_EXT_framebuffer_sRGB");
  743. LogMessage(X_INFO, "AIGLX: enabled GLX_EXT_framebuffer_sRGB\n");
  744. }
  745. /* enable ARB_fbconfig_float extension (even if there are no float fbconfigs) */
  746. {
  747. __glXEnableExtension(screen->glx_enable_bits, "GLX_ARB_fbconfig_float");
  748. LogMessage(X_INFO, "AIGLX: enabled GLX_ARB_fbconfig_float\n");
  749. }
  750. for (i = 0; extensions[i]; i++) {
  751. if (strcmp(extensions[i]->name, __DRI_READ_DRAWABLE) == 0) {
  752. __glXEnableExtension(screen->glx_enable_bits,
  753. "GLX_SGI_make_current_read");
  754. LogMessage(X_INFO, "AIGLX: enabled GLX_SGI_make_current_read\n");
  755. }
  756. if (strcmp(extensions[i]->name, __DRI_TEX_BUFFER) == 0) {
  757. screen->texBuffer = (const __DRItexBufferExtension *) extensions[i];
  758. /* GLX_EXT_texture_from_pixmap is always enabled. */
  759. LogMessage(X_INFO,
  760. "AIGLX: GLX_EXT_texture_from_pixmap backed by buffer objects\n");
  761. }
  762. if (strcmp(extensions[i]->name, __DRI2_FLUSH) == 0 &&
  763. extensions[i]->version >= 3) {
  764. screen->flush = (__DRI2flushExtension *) extensions[i];
  765. }
  766. if (strcmp(extensions[i]->name, __DRI2_ROBUSTNESS) == 0 &&
  767. screen->dri2->base.version >= 3) {
  768. __glXEnableExtension(screen->glx_enable_bits,
  769. "GLX_ARB_create_context_robustness");
  770. LogMessage(X_INFO,
  771. "AIGLX: enabled GLX_ARB_create_context_robustness\n");
  772. }
  773. /* Ignore unknown extensions */
  774. }
  775. }
  776. /* white lie */
  777. extern glx_func_ptr glXGetProcAddressARB(const char *);
  778. static __GLXscreen *
  779. __glXDRIscreenProbe(ScreenPtr pScreen)
  780. {
  781. const char *driverName, *deviceName;
  782. __GLXDRIscreen *screen;
  783. size_t buffer_size;
  784. ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
  785. screen = calloc(1, sizeof *screen);
  786. if (screen == NULL)
  787. return NULL;
  788. if (!DRI2Connect(serverClient, pScreen, DRI2DriverDRI,
  789. &screen->fd, &driverName, &deviceName)) {
  790. LogMessage(X_INFO,
  791. "AIGLX: Screen %d is not DRI2 capable\n", pScreen->myNum);
  792. goto handle_error;
  793. }
  794. screen->base.destroy = __glXDRIscreenDestroy;
  795. screen->base.createContext = __glXDRIscreenCreateContext;
  796. screen->base.createDrawable = __glXDRIscreenCreateDrawable;
  797. screen->base.swapInterval = __glXDRIdrawableSwapInterval;
  798. screen->base.pScreen = pScreen;
  799. __glXInitExtensionEnableBits(screen->glx_enable_bits);
  800. screen->driver =
  801. glxProbeDriver(driverName, (void **) &screen->core, __DRI_CORE, 1,
  802. (void **) &screen->dri2, __DRI_DRI2, 1);
  803. if (screen->driver == NULL) {
  804. goto handle_error;
  805. }
  806. screen->driScreen =
  807. (*screen->dri2->createNewScreen) (pScreen->myNum,
  808. screen->fd,
  809. loader_extensions,
  810. &screen->driConfigs, screen);
  811. if (screen->driScreen == NULL) {
  812. LogMessage(X_ERROR, "AIGLX error: Calling driver entry point failed\n");
  813. goto handle_error;
  814. }
  815. initializeExtensions(screen);
  816. screen->base.fbconfigs = glxConvertConfigs(screen->core, screen->driConfigs,
  817. GLX_WINDOW_BIT |
  818. GLX_PIXMAP_BIT |
  819. GLX_PBUFFER_BIT);
  820. __glXScreenInit(&screen->base, pScreen);
  821. /* The first call simply determines the length of the extension string.
  822. * This allows us to allocate some memory to hold the extension string,
  823. * but it requires that we call __glXGetExtensionString a second time.
  824. */
  825. buffer_size = __glXGetExtensionString(screen->glx_enable_bits, NULL);
  826. if (buffer_size > 0) {
  827. free(screen->base.GLXextensions);
  828. screen->base.GLXextensions = xnfalloc(buffer_size);
  829. (void) __glXGetExtensionString(screen->glx_enable_bits,
  830. screen->base.GLXextensions);
  831. }
  832. /* We're going to assume (perhaps incorrectly?) that all DRI2-enabled
  833. * drivers support the required extensions for GLX 1.4. The extensions
  834. * we're assuming are:
  835. *
  836. * - GLX_SGI_make_current_read (1.3)
  837. * - GLX_SGIX_fbconfig (1.3)
  838. * - GLX_SGIX_pbuffer (1.3)
  839. * - GLX_ARB_multisample (1.4)
  840. */
  841. screen->base.GLXmajor = 1;
  842. screen->base.GLXminor = 4;
  843. screen->enterVT = pScrn->EnterVT;
  844. pScrn->EnterVT = glxDRIEnterVT;
  845. screen->leaveVT = pScrn->LeaveVT;
  846. pScrn->LeaveVT = glxDRILeaveVT;
  847. __glXsetGetProcAddress(glXGetProcAddressARB);
  848. LogMessage(X_INFO, "AIGLX: Loaded and initialized %s\n", driverName);
  849. return &screen->base;
  850. handle_error:
  851. if (screen->driver)
  852. dlclose(screen->driver);
  853. free(screen);
  854. LogMessage(X_ERROR, "AIGLX: reverting to software rendering\n");
  855. return NULL;
  856. }
  857. _X_EXPORT __GLXprovider __glXDRI2Provider = {
  858. __glXDRIscreenProbe,
  859. "DRI2",
  860. NULL
  861. };