0026-egl-wayland-add-pbuffer-support.patch 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469
  1. From 965b7a6be10d89e8cf3bfcf6737a7b9e3375e394 Mon Sep 17 00:00:00 2001
  2. From: Brendan King <Brendan.King@imgtec.com>
  3. Date: Fri, 17 Mar 2017 16:23:07 +0000
  4. Subject: [PATCH] egl/wayland: add pbuffer support
  5. The pbuffer code is based on that in the Surfaceless platform code.
  6. ---
  7. src/egl/drivers/dri2/egl_dri2.h | 4 +
  8. src/egl/drivers/dri2/platform_wayland.c | 270 ++++++++++++++++++++----
  9. 2 files changed, 236 insertions(+), 38 deletions(-)
  10. diff --git a/src/egl/drivers/dri2/egl_dri2.h b/src/egl/drivers/dri2/egl_dri2.h
  11. index 546bc0a..f41f32c 100644
  12. --- a/src/egl/drivers/dri2/egl_dri2.h
  13. +++ b/src/egl/drivers/dri2/egl_dri2.h
  14. @@ -405,6 +405,10 @@ struct dri2_egl_surface
  15. __DRIimage *front;
  16. unsigned int visual;
  17. +#ifdef HAVE_WAYLAND_PLATFORM
  18. + void *swrast_front;
  19. +#endif
  20. +
  21. int out_fence_fd;
  22. EGLBoolean enable_out_fence;
  23. diff --git a/src/egl/drivers/dri2/platform_wayland.c b/src/egl/drivers/dri2/platform_wayland.c
  24. index 811d28b..a096d95 100644
  25. --- a/src/egl/drivers/dri2/platform_wayland.c
  26. +++ b/src/egl/drivers/dri2/platform_wayland.c
  27. @@ -427,6 +427,99 @@ dri2_wl_create_pixmap_surface(_EGLDisplay *disp, _EGLConfig *conf,
  28. return NULL;
  29. }
  30. +static _EGLSurface *
  31. +dri2_wl_create_pbuffer_surface(_EGLDisplay *disp, _EGLConfig *conf,
  32. + const EGLint *attrib_list)
  33. +{
  34. + struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
  35. + struct dri2_egl_config *dri2_conf = dri2_egl_config(conf);
  36. + struct dri2_egl_surface *dri2_surf;
  37. + int visual_idx;
  38. + const __DRIconfig *config;
  39. +
  40. + dri2_surf = calloc(1, sizeof *dri2_surf);
  41. + if (!dri2_surf) {
  42. + _eglError(EGL_BAD_ALLOC, "dri2_create_surface");
  43. + return NULL;
  44. + }
  45. +
  46. + if (!dri2_init_surface(&dri2_surf->base, disp, EGL_PBUFFER_BIT, conf,
  47. + attrib_list, false, NULL))
  48. + goto cleanup_surf;
  49. +
  50. + config = dri2_get_dri_config(dri2_conf, EGL_PBUFFER_BIT,
  51. + dri2_surf->base.GLColorspace);
  52. + if (!config) {
  53. + _eglError(EGL_BAD_MATCH, "Unsupported surfacetype/colorspace configuration");
  54. + goto cleanup_surf;
  55. + }
  56. +
  57. + visual_idx = dri2_wl_visual_idx_from_config(dri2_dpy, config);
  58. + assert(visual_idx != -1);
  59. +
  60. + if (dri2_dpy->wl_dmabuf || dri2_dpy->wl_drm) {
  61. + dri2_surf->format = dri2_wl_visuals[visual_idx].wl_drm_format;
  62. + } else {
  63. + assert(dri2_dpy->wl_shm);
  64. + dri2_surf->format = dri2_wl_visuals[visual_idx].wl_shm_format;
  65. + }
  66. +
  67. + if (!dri2_create_drawable(dri2_dpy, config, dri2_surf, dri2_surf))
  68. + goto cleanup_surf;
  69. +
  70. + return &dri2_surf->base;
  71. +
  72. + cleanup_surf:
  73. + free(dri2_surf);
  74. +
  75. + return NULL;
  76. +}
  77. +
  78. +static int
  79. +allocate_front_buffer(struct dri2_egl_display *dri2_dpy,
  80. + struct dri2_egl_surface *dri2_surf,
  81. + EGLBoolean need_name)
  82. +{
  83. + int use_flags = need_name ? __DRI_IMAGE_USE_SHARE : 0;
  84. + int visual_idx;
  85. + unsigned int dri_image_format;
  86. +
  87. + visual_idx = dri2_wl_visual_idx_from_fourcc(dri2_surf->format);
  88. + assert(visual_idx != -1);
  89. + dri_image_format = dri2_wl_visuals[visual_idx].dri_image_format;
  90. +
  91. + if (!dri2_surf->front)
  92. + dri2_surf->front = dri2_dpy->image->createImage(dri2_dpy->dri_screen,
  93. + dri2_surf->base.Width,
  94. + dri2_surf->base.Height,
  95. + dri_image_format,
  96. + use_flags,
  97. + NULL);
  98. + if (!dri2_surf->front) {
  99. + _eglError(EGL_BAD_ALLOC, "failed to allocate front buffer");
  100. + return -1;
  101. + }
  102. +
  103. + return 0;
  104. +}
  105. +
  106. +static void
  107. +free_front_buffer(struct dri2_egl_display *dri2_dpy,
  108. + struct dri2_egl_surface *dri2_surf)
  109. +{
  110. + if (dri2_surf->front) {
  111. + dri2_dpy->image->destroyImage(dri2_surf->front);
  112. + dri2_surf->front = NULL;
  113. + }
  114. +}
  115. +
  116. +static void
  117. +swrast_free_front_buffer(struct dri2_egl_surface *dri2_surf)
  118. +{
  119. + free(dri2_surf->swrast_front);
  120. + dri2_surf->swrast_front = NULL;
  121. +}
  122. +
  123. /**
  124. * Called via eglDestroySurface(), drv->DestroySurface().
  125. */
  126. @@ -453,6 +546,9 @@ dri2_wl_destroy_surface(_EGLDisplay *disp, _EGLSurface *surf)
  127. if (dri2_dpy->dri2)
  128. dri2_egl_surface_free_local_buffers(dri2_surf);
  129. + free_front_buffer(dri2_dpy, dri2_surf);
  130. + swrast_free_front_buffer(dri2_surf);
  131. +
  132. if (dri2_surf->throttle_callback)
  133. wl_callback_destroy(dri2_surf->throttle_callback);
  134. @@ -462,11 +558,14 @@ dri2_wl_destroy_surface(_EGLDisplay *disp, _EGLSurface *surf)
  135. dri2_surf->wl_win->destroy_window_callback = NULL;
  136. }
  137. - wl_proxy_wrapper_destroy(dri2_surf->wl_surface_wrapper);
  138. - wl_proxy_wrapper_destroy(dri2_surf->wl_dpy_wrapper);
  139. + if (dri2_surf->wl_surface_wrapper)
  140. + wl_proxy_wrapper_destroy(dri2_surf->wl_surface_wrapper);
  141. + if (dri2_surf->wl_dpy_wrapper)
  142. + wl_proxy_wrapper_destroy(dri2_surf->wl_dpy_wrapper);
  143. if (dri2_surf->wl_drm_wrapper)
  144. wl_proxy_wrapper_destroy(dri2_surf->wl_drm_wrapper);
  145. - wl_event_queue_destroy(dri2_surf->wl_queue);
  146. + if (dri2_surf->wl_queue)
  147. + wl_event_queue_destroy(dri2_surf->wl_queue);
  148. dri2_fini_surface(surf);
  149. free(surf);
  150. @@ -628,20 +727,16 @@ get_back_bo(struct dri2_egl_surface *dri2_surf)
  151. static void
  152. -back_bo_to_dri_buffer(struct dri2_egl_surface *dri2_surf, __DRIbuffer *buffer)
  153. +bo_to_dri_buffer(struct dri2_egl_display *dri2_dpy, unsigned int attachment,
  154. + __DRIimage *image, __DRIbuffer *buffer)
  155. {
  156. - struct dri2_egl_display *dri2_dpy =
  157. - dri2_egl_display(dri2_surf->base.Resource.Display);
  158. - __DRIimage *image;
  159. int name, pitch, format;
  160. - image = dri2_surf->back->dri_image;
  161. -
  162. dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_NAME, &name);
  163. dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_STRIDE, &pitch);
  164. dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_FORMAT, &format);
  165. - buffer->attachment = __DRI_BUFFER_BACK_LEFT;
  166. + buffer->attachment = attachment;
  167. buffer->name = name;
  168. buffer->pitch = pitch;
  169. buffer->flags = 0;
  170. @@ -656,12 +751,28 @@ back_bo_to_dri_buffer(struct dri2_egl_surface *dri2_surf, __DRIbuffer *buffer)
  171. }
  172. }
  173. -static int
  174. -update_buffers(struct dri2_egl_surface *dri2_surf)
  175. +static void
  176. +back_bo_to_dri_buffer(struct dri2_egl_display *dri2_dpy,
  177. + struct dri2_egl_surface *dri2_surf,
  178. + __DRIbuffer *buffer)
  179. {
  180. - struct dri2_egl_display *dri2_dpy =
  181. - dri2_egl_display(dri2_surf->base.Resource.Display);
  182. + bo_to_dri_buffer(dri2_dpy, __DRI_BUFFER_BACK_LEFT,
  183. + dri2_surf->back->dri_image, buffer);
  184. +}
  185. +
  186. +static void
  187. +front_bo_to_dri_buffer(struct dri2_egl_display *dri2_dpy,
  188. + struct dri2_egl_surface *dri2_surf,
  189. + __DRIbuffer *buffer)
  190. +{
  191. + bo_to_dri_buffer(dri2_dpy, __DRI_BUFFER_FRONT_LEFT,
  192. + dri2_surf->front, buffer);
  193. +}
  194. +static int
  195. +update_buffers(struct dri2_egl_display *dri2_dpy,
  196. + struct dri2_egl_surface *dri2_surf)
  197. +{
  198. if (dri2_surf->wl_win &&
  199. (dri2_surf->base.Width != dri2_surf->wl_win->width ||
  200. dri2_surf->base.Height != dri2_surf->wl_win->height)) {
  201. @@ -703,12 +814,13 @@ update_buffers(struct dri2_egl_surface *dri2_surf)
  202. }
  203. static int
  204. -update_buffers_if_needed(struct dri2_egl_surface *dri2_surf)
  205. +update_buffers_if_needed(struct dri2_egl_display *dri2_dpy,
  206. + struct dri2_egl_surface *dri2_surf)
  207. {
  208. if (dri2_surf->back != NULL)
  209. return 0;
  210. - return update_buffers(dri2_surf);
  211. + return update_buffers(dri2_dpy, dri2_surf);
  212. }
  213. static __DRIbuffer *
  214. @@ -718,17 +830,25 @@ dri2_wl_get_buffers_with_format(__DRIdrawable * driDrawable,
  215. int *out_count, void *loaderPrivate)
  216. {
  217. struct dri2_egl_surface *dri2_surf = loaderPrivate;
  218. + struct dri2_egl_display *dri2_dpy =
  219. + dri2_egl_display(dri2_surf->base.Resource.Display);
  220. int i, j;
  221. - if (update_buffers(dri2_surf) < 0)
  222. - return NULL;
  223. -
  224. for (i = 0, j = 0; i < 2 * count; i += 2, j++) {
  225. __DRIbuffer *local;
  226. switch (attachments[i]) {
  227. case __DRI_BUFFER_BACK_LEFT:
  228. - back_bo_to_dri_buffer(dri2_surf, &dri2_surf->buffers[j]);
  229. + if (update_buffers(dri2_dpy, dri2_surf) < 0)
  230. + return NULL;
  231. +
  232. + back_bo_to_dri_buffer(dri2_dpy, dri2_surf, &dri2_surf->buffers[j]);
  233. + break;
  234. + case __DRI_BUFFER_FRONT_LEFT:
  235. + if (allocate_front_buffer(dri2_dpy, dri2_surf, EGL_TRUE) < 0)
  236. + return NULL;
  237. +
  238. + front_bo_to_dri_buffer(dri2_dpy, dri2_surf, &dri2_surf->buffers[j]);
  239. break;
  240. default:
  241. local = dri2_egl_surface_alloc_local_buffer(dri2_surf, attachments[i],
  242. @@ -798,12 +918,30 @@ image_get_buffers(__DRIdrawable *driDrawable,
  243. struct __DRIimageList *buffers)
  244. {
  245. struct dri2_egl_surface *dri2_surf = loaderPrivate;
  246. + struct dri2_egl_display *dri2_dpy =
  247. + dri2_egl_display(dri2_surf->base.Resource.Display);
  248. - if (update_buffers(dri2_surf) < 0)
  249. - return 0;
  250. + buffers->image_mask = 0;
  251. + buffers->front = NULL;
  252. + buffers->back = NULL;
  253. +
  254. + if (buffer_mask & __DRI_IMAGE_BUFFER_BACK)
  255. + {
  256. + if (update_buffers(dri2_dpy, dri2_surf) < 0)
  257. + return 0;
  258. - buffers->image_mask = __DRI_IMAGE_BUFFER_BACK;
  259. - buffers->back = dri2_surf->back->dri_image;
  260. + buffers->image_mask |= __DRI_IMAGE_BUFFER_BACK;
  261. + buffers->back = dri2_surf->back->dri_image;
  262. + }
  263. +
  264. + if (buffer_mask & __DRI_IMAGE_BUFFER_FRONT)
  265. + {
  266. + if (allocate_front_buffer(dri2_dpy, dri2_surf, EGL_FALSE) < 0)
  267. + return 0;
  268. +
  269. + buffers->image_mask |= __DRI_IMAGE_BUFFER_FRONT;
  270. + buffers->front = dri2_surf->front;
  271. + }
  272. return 1;
  273. }
  274. @@ -1054,6 +1192,9 @@ dri2_wl_swap_buffers_with_damage(_EGLDisplay *disp,
  275. struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
  276. struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
  277. + if (draw->Type != EGL_WINDOW_BIT)
  278. + return EGL_TRUE;
  279. +
  280. if (!dri2_surf->wl_win)
  281. return _eglError(EGL_BAD_NATIVE_WINDOW, "dri2_swap_buffers");
  282. @@ -1068,7 +1209,7 @@ dri2_wl_swap_buffers_with_damage(_EGLDisplay *disp,
  283. /* Make sure we have a back buffer in case we're swapping without ever
  284. * rendering. */
  285. - if (update_buffers_if_needed(dri2_surf) < 0)
  286. + if (update_buffers_if_needed(dri2_dpy, dri2_surf) < 0)
  287. return _eglError(EGL_BAD_ALLOC, "dri2_swap_buffers");
  288. if (draw->SwapInterval > 0) {
  289. @@ -1153,9 +1294,13 @@ dri2_wl_swap_buffers_with_damage(_EGLDisplay *disp,
  290. static EGLint
  291. dri2_wl_query_buffer_age(_EGLDisplay *disp, _EGLSurface *surface)
  292. {
  293. + struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
  294. struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surface);
  295. - if (update_buffers_if_needed(dri2_surf) < 0) {
  296. + if (surface->Type != EGL_WINDOW_BIT)
  297. + return 0;
  298. +
  299. + if (update_buffers_if_needed(dri2_dpy, dri2_surf) < 0) {
  300. _eglError(EGL_BAD_ALLOC, "dri2_query_buffer_age");
  301. return -1;
  302. }
  303. @@ -1376,6 +1521,7 @@ static const struct dri2_egl_display_vtbl dri2_wl_display_vtbl = {
  304. .authenticate = dri2_wl_authenticate,
  305. .create_window_surface = dri2_wl_create_window_surface,
  306. .create_pixmap_surface = dri2_wl_create_pixmap_surface,
  307. + .create_pbuffer_surface = dri2_wl_create_pbuffer_surface,
  308. .destroy_surface = dri2_wl_destroy_surface,
  309. .create_image = dri2_create_image_khr,
  310. .swap_buffers = dri2_wl_swap_buffers,
  311. @@ -1418,7 +1564,7 @@ dri2_wl_add_configs_for_visuals(_EGLDisplay *disp)
  312. continue;
  313. dri2_conf = dri2_add_config(disp, dri2_dpy->driver_configs[i],
  314. - count + 1, EGL_WINDOW_BIT, NULL, dri2_wl_visuals[j].rgba_shifts, dri2_wl_visuals[j].rgba_sizes);
  315. + count + 1, EGL_WINDOW_BIT | EGL_PBUFFER_BIT, NULL, dri2_wl_visuals[j].rgba_shifts, dri2_wl_visuals[j].rgba_sizes);
  316. if (dri2_conf) {
  317. if (dri2_conf->base.ConfigID == count + 1)
  318. count++;
  319. @@ -1654,6 +1800,23 @@ dri2_wl_swrast_get_stride_for_format(int format, int w)
  320. return w * (dri2_wl_visuals[visual_idx].bpp / 8);
  321. }
  322. +static EGLBoolean
  323. +swrast_allocate_local_buffer(int format, int w, int h, void **data)
  324. +{
  325. + int stride, size_map;
  326. + void *data_map;
  327. +
  328. + stride = dri2_wl_swrast_get_stride_for_format(format, w);
  329. + size_map = h * stride;
  330. +
  331. + data_map = malloc(size_map);
  332. + if (!data_map)
  333. + return EGL_FALSE;
  334. +
  335. + *data = data_map;
  336. + return EGL_TRUE;
  337. +}
  338. +
  339. static EGLBoolean
  340. dri2_wl_swrast_allocate_buffer(struct dri2_egl_surface *dri2_surf,
  341. int format, int w, int h,
  342. @@ -1775,8 +1938,24 @@ swrast_update_buffers(struct dri2_egl_surface *dri2_surf)
  343. return 0;
  344. }
  345. +static int
  346. +swrast_allocate_front_buffer(struct dri2_egl_surface *dri2_surf)
  347. +{
  348. + if (!dri2_surf->swrast_front) {
  349. + if (!swrast_allocate_local_buffer(dri2_surf->format,
  350. + dri2_surf->base.Width,
  351. + dri2_surf->base.Height,
  352. + &dri2_surf->swrast_front)) {
  353. + _eglError(EGL_BAD_ALLOC, "failed to allocate front buffer");
  354. + return -1;
  355. + }
  356. + }
  357. +
  358. + return 0;
  359. +}
  360. +
  361. static void*
  362. -dri2_wl_swrast_get_frontbuffer_data(struct dri2_egl_surface *dri2_surf)
  363. +dri2_wl_swrast_get_currentbuffer_data(struct dri2_egl_surface *dri2_surf)
  364. {
  365. /* if there has been a resize: */
  366. if (!dri2_surf->current)
  367. @@ -1846,7 +2025,9 @@ dri2_wl_swrast_get_drawable_info(__DRIdrawable * draw,
  368. {
  369. struct dri2_egl_surface *dri2_surf = loaderPrivate;
  370. - (void) swrast_update_buffers(dri2_surf);
  371. + if (dri2_surf->base.Type == EGL_WINDOW_BIT)
  372. + (void) swrast_update_buffers(dri2_surf);
  373. +
  374. *x = 0;
  375. *y = 0;
  376. *w = dri2_surf->base.Width;
  377. @@ -1865,7 +2046,11 @@ dri2_wl_swrast_get_image(__DRIdrawable * read,
  378. int dst_stride = copy_width;
  379. char *src, *dst;
  380. - src = dri2_wl_swrast_get_frontbuffer_data(dri2_surf);
  381. + if (dri2_surf->base.Type == EGL_WINDOW_BIT)
  382. + src = dri2_wl_swrast_get_currentbuffer_data(dri2_surf);
  383. + else
  384. + src = dri2_surf->swrast_front;
  385. +
  386. if (!src) {
  387. memset(data, 0, copy_width * h);
  388. return;
  389. @@ -1903,14 +2088,20 @@ dri2_wl_swrast_put_image2(__DRIdrawable * draw, int op,
  390. assert(copy_width <= stride);
  391. - (void) swrast_update_buffers(dri2_surf);
  392. - dst = dri2_wl_swrast_get_backbuffer_data(dri2_surf);
  393. + if (dri2_surf->base.Type == EGL_WINDOW_BIT) {
  394. + (void) swrast_update_buffers(dri2_surf);
  395. + dst = dri2_wl_swrast_get_backbuffer_data(dri2_surf);
  396. - /* partial copy, copy old content */
  397. - if (copy_width < dst_stride)
  398. - dri2_wl_swrast_get_image(draw, 0, 0,
  399. - dri2_surf->base.Width, dri2_surf->base.Height,
  400. - dst, loaderPrivate);
  401. + /* partial copy, copy old content */
  402. + if (copy_width < dst_stride)
  403. + dri2_wl_swrast_get_image(draw, 0, 0,
  404. + dri2_surf->base.Width, dri2_surf->base.Height,
  405. + dst, loaderPrivate);
  406. + } else {
  407. + (void) swrast_allocate_front_buffer(dri2_surf);
  408. + dst = dri2_surf->swrast_front;
  409. + assert(dst);
  410. + }
  411. dst += x_offset;
  412. dst += y * dst_stride;
  413. @@ -1928,7 +2119,9 @@ dri2_wl_swrast_put_image2(__DRIdrawable * draw, int op,
  414. src += stride;
  415. dst += dst_stride;
  416. }
  417. - dri2_wl_swrast_commit_backbuffer(dri2_surf);
  418. +
  419. + if (dri2_surf->base.Type == EGL_WINDOW_BIT)
  420. + dri2_wl_swrast_commit_backbuffer(dri2_surf);
  421. }
  422. static void
  423. @@ -1996,6 +2189,7 @@ static const struct dri2_egl_display_vtbl dri2_wl_swrast_display_vtbl = {
  424. .authenticate = NULL,
  425. .create_window_surface = dri2_wl_create_window_surface,
  426. .create_pixmap_surface = dri2_wl_create_pixmap_surface,
  427. + .create_pbuffer_surface = dri2_wl_create_pbuffer_surface,
  428. .destroy_surface = dri2_wl_destroy_surface,
  429. .create_image = dri2_create_image_khr,
  430. .swap_buffers = dri2_wl_swrast_swap_buffers,