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.

x11_screen.c 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435
  1. /*
  2. * Mesa 3-D graphics library
  3. * Version: 7.8
  4. *
  5. * Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org>
  6. *
  7. * Permission is hereby granted, free of charge, to any person obtaining a
  8. * copy of this software and associated documentation files (the "Software"),
  9. * to deal in the Software without restriction, including without limitation
  10. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  11. * and/or sell copies of the Software, and to permit persons to whom the
  12. * Software is furnished to do so, subject to the following conditions:
  13. *
  14. * The above copyright notice and this permission notice shall be included
  15. * in all copies or substantial portions of the Software.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  20. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  22. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  23. * DEALINGS IN THE SOFTWARE.
  24. */
  25. #include <unistd.h>
  26. #include <fcntl.h>
  27. #include <sys/types.h>
  28. #include <sys/stat.h>
  29. #include <X11/Xlibint.h>
  30. #include <X11/extensions/XShm.h>
  31. #include "util/u_memory.h"
  32. #include "util/u_math.h"
  33. #include "util/u_format.h"
  34. #include "xf86drm.h"
  35. #include "egllog.h"
  36. #include "x11_screen.h"
  37. #include "dri2.h"
  38. #include "glxinit.h"
  39. struct x11_screen {
  40. /* dummy base class */
  41. struct __GLXDRIdisplayRec base;
  42. Display *dpy;
  43. int number;
  44. /*
  45. * This is used to fetch GLX visuals/fbconfigs. It steals code from GLX.
  46. * It might be better to rewrite the part in Xlib or XCB.
  47. */
  48. __GLXdisplayPrivate *glx_dpy;
  49. int dri_major, dri_minor;
  50. char *dri_driver;
  51. char *dri_device;
  52. int dri_fd;
  53. x11_drawable_invalidate_buffers dri_invalidate_buffers;
  54. void *dri_user_data;
  55. XVisualInfo *visuals;
  56. int num_visuals;
  57. /* cached values for x11_drawable_get_depth */
  58. Drawable last_drawable;
  59. unsigned int last_depth;
  60. };
  61. /**
  62. * Create a X11 screen.
  63. */
  64. struct x11_screen *
  65. x11_screen_create(Display *dpy, int screen)
  66. {
  67. struct x11_screen *xscr;
  68. if (screen >= ScreenCount(dpy))
  69. return NULL;
  70. xscr = CALLOC_STRUCT(x11_screen);
  71. if (xscr) {
  72. xscr->dpy = dpy;
  73. xscr->number = screen;
  74. xscr->dri_major = -1;
  75. xscr->dri_fd = -1;
  76. }
  77. return xscr;
  78. }
  79. /**
  80. * Destroy a X11 screen.
  81. */
  82. void
  83. x11_screen_destroy(struct x11_screen *xscr)
  84. {
  85. if (xscr->dri_fd >= 0)
  86. close(xscr->dri_fd);
  87. if (xscr->dri_driver)
  88. Xfree(xscr->dri_driver);
  89. if (xscr->dri_device)
  90. Xfree(xscr->dri_device);
  91. /* xscr->glx_dpy will be destroyed with the X display */
  92. if (xscr->glx_dpy)
  93. xscr->glx_dpy->dri2Display = NULL;
  94. if (xscr->visuals)
  95. XFree(xscr->visuals);
  96. free(xscr);
  97. }
  98. static boolean
  99. x11_screen_init_dri2(struct x11_screen *xscr)
  100. {
  101. if (xscr->dri_major < 0) {
  102. int eventBase, errorBase;
  103. if (!DRI2QueryExtension(xscr->dpy, &eventBase, &errorBase) ||
  104. !DRI2QueryVersion(xscr->dpy, &xscr->dri_major, &xscr->dri_minor))
  105. xscr->dri_major = -1;
  106. }
  107. return (xscr->dri_major >= 0);
  108. }
  109. static boolean
  110. x11_screen_init_glx(struct x11_screen *xscr)
  111. {
  112. if (!xscr->glx_dpy)
  113. xscr->glx_dpy = __glXInitialize(xscr->dpy);
  114. return (xscr->glx_dpy != NULL);
  115. }
  116. /**
  117. * Return true if the screen supports the extension.
  118. */
  119. boolean
  120. x11_screen_support(struct x11_screen *xscr, enum x11_screen_extension ext)
  121. {
  122. boolean supported = FALSE;
  123. switch (ext) {
  124. case X11_SCREEN_EXTENSION_XSHM:
  125. supported = XShmQueryExtension(xscr->dpy);
  126. break;
  127. case X11_SCREEN_EXTENSION_GLX:
  128. supported = x11_screen_init_glx(xscr);
  129. break;
  130. case X11_SCREEN_EXTENSION_DRI2:
  131. supported = x11_screen_init_dri2(xscr);
  132. break;
  133. default:
  134. break;
  135. }
  136. return supported;
  137. }
  138. /**
  139. * Return the X visuals.
  140. */
  141. const XVisualInfo *
  142. x11_screen_get_visuals(struct x11_screen *xscr, int *num_visuals)
  143. {
  144. if (!xscr->visuals) {
  145. XVisualInfo vinfo_template;
  146. vinfo_template.screen = xscr->number;
  147. xscr->visuals = XGetVisualInfo(xscr->dpy, VisualScreenMask,
  148. &vinfo_template, &xscr->num_visuals);
  149. }
  150. if (num_visuals)
  151. *num_visuals = xscr->num_visuals;
  152. return xscr->visuals;
  153. }
  154. /**
  155. * Return the GLX fbconfigs.
  156. */
  157. const __GLcontextModes *
  158. x11_screen_get_glx_configs(struct x11_screen *xscr)
  159. {
  160. return (x11_screen_init_glx(xscr))
  161. ? xscr->glx_dpy->screenConfigs[xscr->number].configs
  162. : NULL;
  163. }
  164. /**
  165. * Return the GLX visuals.
  166. */
  167. const __GLcontextModes *
  168. x11_screen_get_glx_visuals(struct x11_screen *xscr)
  169. {
  170. return (x11_screen_init_glx(xscr))
  171. ? xscr->glx_dpy->screenConfigs[xscr->number].visuals
  172. : NULL;
  173. }
  174. /**
  175. * Probe the screen for the DRI2 driver name.
  176. */
  177. const char *
  178. x11_screen_probe_dri2(struct x11_screen *xscr, int *major, int *minor)
  179. {
  180. if (!x11_screen_init_dri2(xscr))
  181. return NULL;
  182. /* get the driver name and the device name */
  183. if (!xscr->dri_driver) {
  184. if (!DRI2Connect(xscr->dpy, RootWindow(xscr->dpy, xscr->number),
  185. &xscr->dri_driver, &xscr->dri_device))
  186. xscr->dri_driver = xscr->dri_device = NULL;
  187. }
  188. if (major)
  189. *major = xscr->dri_major;
  190. if (minor)
  191. *minor = xscr->dri_minor;
  192. return xscr->dri_driver;
  193. }
  194. /**
  195. * Enable DRI2 and returns the file descriptor of the DRM device. The file
  196. * descriptor will be closed automatically when the screen is destoryed.
  197. */
  198. int
  199. x11_screen_enable_dri2(struct x11_screen *xscr,
  200. x11_drawable_invalidate_buffers invalidate_buffers,
  201. void *user_data)
  202. {
  203. if (xscr->dri_fd < 0) {
  204. int fd;
  205. drm_magic_t magic;
  206. /* get the driver name and the device name first */
  207. if (!x11_screen_probe_dri2(xscr, NULL, NULL))
  208. return -1;
  209. fd = open(xscr->dri_device, O_RDWR);
  210. if (fd < 0) {
  211. _eglLog(_EGL_WARNING, "failed to open %s", xscr->dri_device);
  212. return -1;
  213. }
  214. memset(&magic, 0, sizeof(magic));
  215. if (drmGetMagic(fd, &magic)) {
  216. _eglLog(_EGL_WARNING, "failed to get magic");
  217. close(fd);
  218. return -1;
  219. }
  220. if (!DRI2Authenticate(xscr->dpy,
  221. RootWindow(xscr->dpy, xscr->number), magic)) {
  222. _eglLog(_EGL_WARNING, "failed to authenticate magic");
  223. close(fd);
  224. return -1;
  225. }
  226. if (!x11_screen_init_glx(xscr)) {
  227. _eglLog(_EGL_WARNING, "failed to initialize GLX");
  228. close(fd);
  229. return -1;
  230. }
  231. if (xscr->glx_dpy->dri2Display) {
  232. _eglLog(_EGL_WARNING,
  233. "display is already managed by another x11 screen");
  234. close(fd);
  235. return -1;
  236. }
  237. xscr->glx_dpy->dri2Display = (__GLXDRIdisplay *) xscr;
  238. xscr->dri_invalidate_buffers = invalidate_buffers;
  239. xscr->dri_user_data = user_data;
  240. xscr->dri_fd = fd;
  241. }
  242. return xscr->dri_fd;
  243. }
  244. /**
  245. * Create/Destroy the DRI drawable.
  246. */
  247. void
  248. x11_drawable_enable_dri2(struct x11_screen *xscr,
  249. Drawable drawable, boolean on)
  250. {
  251. if (on)
  252. DRI2CreateDrawable(xscr->dpy, drawable);
  253. else
  254. DRI2DestroyDrawable(xscr->dpy, drawable);
  255. }
  256. /**
  257. * Copy between buffers of the DRI2 drawable.
  258. */
  259. void
  260. x11_drawable_copy_buffers(struct x11_screen *xscr, Drawable drawable,
  261. int x, int y, int width, int height,
  262. int src_buf, int dst_buf)
  263. {
  264. XRectangle rect;
  265. XserverRegion region;
  266. rect.x = x;
  267. rect.y = y;
  268. rect.width = width;
  269. rect.height = height;
  270. region = XFixesCreateRegion(xscr->dpy, &rect, 1);
  271. DRI2CopyRegion(xscr->dpy, drawable, region, dst_buf, src_buf);
  272. XFixesDestroyRegion(xscr->dpy, region);
  273. }
  274. /**
  275. * Get the buffers of the DRI2 drawable. The returned array should be freed.
  276. */
  277. struct x11_drawable_buffer *
  278. x11_drawable_get_buffers(struct x11_screen *xscr, Drawable drawable,
  279. int *width, int *height, unsigned int *attachments,
  280. boolean with_format, int num_ins, int *num_outs)
  281. {
  282. DRI2Buffer *dri2bufs;
  283. if (with_format)
  284. dri2bufs = DRI2GetBuffersWithFormat(xscr->dpy, drawable, width, height,
  285. attachments, num_ins, num_outs);
  286. else
  287. dri2bufs = DRI2GetBuffers(xscr->dpy, drawable, width, height,
  288. attachments, num_ins, num_outs);
  289. return (struct x11_drawable_buffer *) dri2bufs;
  290. }
  291. /**
  292. * Return the depth of a drawable.
  293. *
  294. * Unlike other drawable functions, the drawable needs not be a DRI2 drawable.
  295. */
  296. uint
  297. x11_drawable_get_depth(struct x11_screen *xscr, Drawable drawable)
  298. {
  299. unsigned int depth;
  300. if (drawable != xscr->last_drawable) {
  301. Window root;
  302. int x, y;
  303. unsigned int w, h, border;
  304. Status ok;
  305. ok = XGetGeometry(xscr->dpy, drawable, &root,
  306. &x, &y, &w, &h, &border, &depth);
  307. if (!ok)
  308. depth = 0;
  309. xscr->last_drawable = drawable;
  310. xscr->last_depth = depth;
  311. }
  312. else {
  313. depth = xscr->last_depth;
  314. }
  315. return depth;
  316. }
  317. /**
  318. * Create a mode list of the given size.
  319. */
  320. __GLcontextModes *
  321. x11_context_modes_create(unsigned count)
  322. {
  323. const size_t size = sizeof(__GLcontextModes);
  324. __GLcontextModes *base = NULL;
  325. __GLcontextModes **next;
  326. unsigned i;
  327. next = &base;
  328. for (i = 0; i < count; i++) {
  329. *next = (__GLcontextModes *) calloc(1, size);
  330. if (*next == NULL) {
  331. x11_context_modes_destroy(base);
  332. base = NULL;
  333. break;
  334. }
  335. next = &((*next)->next);
  336. }
  337. return base;
  338. }
  339. /**
  340. * Destroy a mode list.
  341. */
  342. void
  343. x11_context_modes_destroy(__GLcontextModes *modes)
  344. {
  345. while (modes != NULL) {
  346. __GLcontextModes *next = modes->next;
  347. free(modes);
  348. modes = next;
  349. }
  350. }
  351. /**
  352. * Return the number of the modes in the mode list.
  353. */
  354. unsigned
  355. x11_context_modes_count(const __GLcontextModes *modes)
  356. {
  357. const __GLcontextModes *mode;
  358. int count = 0;
  359. for (mode = modes; mode; mode = mode->next)
  360. count++;
  361. return count;
  362. }
  363. /**
  364. * This is called from src/glx/dri2.c.
  365. */
  366. void
  367. dri2InvalidateBuffers(Display *dpy, XID drawable)
  368. {
  369. __GLXdisplayPrivate *priv = __glXInitialize(dpy);
  370. struct x11_screen *xscr = NULL;
  371. if (priv && priv->dri2Display)
  372. xscr = (struct x11_screen *) priv->dri2Display;
  373. if (!xscr || !xscr->dri_invalidate_buffers)
  374. return;
  375. xscr->dri_invalidate_buffers(xscr, drawable, xscr->dri_user_data);
  376. }