123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469 |
- From 965b7a6be10d89e8cf3bfcf6737a7b9e3375e394 Mon Sep 17 00:00:00 2001
- From: Brendan King <Brendan.King@imgtec.com>
- Date: Fri, 17 Mar 2017 16:23:07 +0000
- Subject: [PATCH] egl/wayland: add pbuffer support
- The pbuffer code is based on that in the Surfaceless platform code.
- ---
- src/egl/drivers/dri2/egl_dri2.h | 4 +
- src/egl/drivers/dri2/platform_wayland.c | 270 ++++++++++++++++++++----
- 2 files changed, 236 insertions(+), 38 deletions(-)
- diff --git a/src/egl/drivers/dri2/egl_dri2.h b/src/egl/drivers/dri2/egl_dri2.h
- index 546bc0a..f41f32c 100644
- --- a/src/egl/drivers/dri2/egl_dri2.h
- +++ b/src/egl/drivers/dri2/egl_dri2.h
- @@ -405,6 +405,10 @@ struct dri2_egl_surface
- __DRIimage *front;
- unsigned int visual;
-
- +#ifdef HAVE_WAYLAND_PLATFORM
- + void *swrast_front;
- +#endif
- +
- int out_fence_fd;
- EGLBoolean enable_out_fence;
-
- diff --git a/src/egl/drivers/dri2/platform_wayland.c b/src/egl/drivers/dri2/platform_wayland.c
- index 811d28b..a096d95 100644
- --- a/src/egl/drivers/dri2/platform_wayland.c
- +++ b/src/egl/drivers/dri2/platform_wayland.c
- @@ -427,6 +427,99 @@ dri2_wl_create_pixmap_surface(_EGLDisplay *disp, _EGLConfig *conf,
- return NULL;
- }
-
- +static _EGLSurface *
- +dri2_wl_create_pbuffer_surface(_EGLDisplay *disp, _EGLConfig *conf,
- + const EGLint *attrib_list)
- +{
- + struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
- + struct dri2_egl_config *dri2_conf = dri2_egl_config(conf);
- + struct dri2_egl_surface *dri2_surf;
- + int visual_idx;
- + const __DRIconfig *config;
- +
- + dri2_surf = calloc(1, sizeof *dri2_surf);
- + if (!dri2_surf) {
- + _eglError(EGL_BAD_ALLOC, "dri2_create_surface");
- + return NULL;
- + }
- +
- + if (!dri2_init_surface(&dri2_surf->base, disp, EGL_PBUFFER_BIT, conf,
- + attrib_list, false, NULL))
- + goto cleanup_surf;
- +
- + config = dri2_get_dri_config(dri2_conf, EGL_PBUFFER_BIT,
- + dri2_surf->base.GLColorspace);
- + if (!config) {
- + _eglError(EGL_BAD_MATCH, "Unsupported surfacetype/colorspace configuration");
- + goto cleanup_surf;
- + }
- +
- + visual_idx = dri2_wl_visual_idx_from_config(dri2_dpy, config);
- + assert(visual_idx != -1);
- +
- + if (dri2_dpy->wl_dmabuf || dri2_dpy->wl_drm) {
- + dri2_surf->format = dri2_wl_visuals[visual_idx].wl_drm_format;
- + } else {
- + assert(dri2_dpy->wl_shm);
- + dri2_surf->format = dri2_wl_visuals[visual_idx].wl_shm_format;
- + }
- +
- + if (!dri2_create_drawable(dri2_dpy, config, dri2_surf, dri2_surf))
- + goto cleanup_surf;
- +
- + return &dri2_surf->base;
- +
- + cleanup_surf:
- + free(dri2_surf);
- +
- + return NULL;
- +}
- +
- +static int
- +allocate_front_buffer(struct dri2_egl_display *dri2_dpy,
- + struct dri2_egl_surface *dri2_surf,
- + EGLBoolean need_name)
- +{
- + int use_flags = need_name ? __DRI_IMAGE_USE_SHARE : 0;
- + int visual_idx;
- + unsigned int dri_image_format;
- +
- + visual_idx = dri2_wl_visual_idx_from_fourcc(dri2_surf->format);
- + assert(visual_idx != -1);
- + dri_image_format = dri2_wl_visuals[visual_idx].dri_image_format;
- +
- + if (!dri2_surf->front)
- + dri2_surf->front = dri2_dpy->image->createImage(dri2_dpy->dri_screen,
- + dri2_surf->base.Width,
- + dri2_surf->base.Height,
- + dri_image_format,
- + use_flags,
- + NULL);
- + if (!dri2_surf->front) {
- + _eglError(EGL_BAD_ALLOC, "failed to allocate front buffer");
- + return -1;
- + }
- +
- + return 0;
- +}
- +
- +static void
- +free_front_buffer(struct dri2_egl_display *dri2_dpy,
- + struct dri2_egl_surface *dri2_surf)
- +{
- + if (dri2_surf->front) {
- + dri2_dpy->image->destroyImage(dri2_surf->front);
- + dri2_surf->front = NULL;
- + }
- +}
- +
- +static void
- +swrast_free_front_buffer(struct dri2_egl_surface *dri2_surf)
- +{
- + free(dri2_surf->swrast_front);
- + dri2_surf->swrast_front = NULL;
- +}
- +
- /**
- * Called via eglDestroySurface(), drv->DestroySurface().
- */
- @@ -453,6 +546,9 @@ dri2_wl_destroy_surface(_EGLDisplay *disp, _EGLSurface *surf)
- if (dri2_dpy->dri2)
- dri2_egl_surface_free_local_buffers(dri2_surf);
-
- + free_front_buffer(dri2_dpy, dri2_surf);
- + swrast_free_front_buffer(dri2_surf);
- +
- if (dri2_surf->throttle_callback)
- wl_callback_destroy(dri2_surf->throttle_callback);
-
- @@ -462,11 +558,14 @@ dri2_wl_destroy_surface(_EGLDisplay *disp, _EGLSurface *surf)
- dri2_surf->wl_win->destroy_window_callback = NULL;
- }
-
- - wl_proxy_wrapper_destroy(dri2_surf->wl_surface_wrapper);
- - wl_proxy_wrapper_destroy(dri2_surf->wl_dpy_wrapper);
- + if (dri2_surf->wl_surface_wrapper)
- + wl_proxy_wrapper_destroy(dri2_surf->wl_surface_wrapper);
- + if (dri2_surf->wl_dpy_wrapper)
- + wl_proxy_wrapper_destroy(dri2_surf->wl_dpy_wrapper);
- if (dri2_surf->wl_drm_wrapper)
- wl_proxy_wrapper_destroy(dri2_surf->wl_drm_wrapper);
- - wl_event_queue_destroy(dri2_surf->wl_queue);
- + if (dri2_surf->wl_queue)
- + wl_event_queue_destroy(dri2_surf->wl_queue);
-
- dri2_fini_surface(surf);
- free(surf);
- @@ -628,20 +727,16 @@ get_back_bo(struct dri2_egl_surface *dri2_surf)
-
-
- static void
- -back_bo_to_dri_buffer(struct dri2_egl_surface *dri2_surf, __DRIbuffer *buffer)
- +bo_to_dri_buffer(struct dri2_egl_display *dri2_dpy, unsigned int attachment,
- + __DRIimage *image, __DRIbuffer *buffer)
- {
- - struct dri2_egl_display *dri2_dpy =
- - dri2_egl_display(dri2_surf->base.Resource.Display);
- - __DRIimage *image;
- int name, pitch, format;
-
- - image = dri2_surf->back->dri_image;
- -
- dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_NAME, &name);
- dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_STRIDE, &pitch);
- dri2_dpy->image->queryImage(image, __DRI_IMAGE_ATTRIB_FORMAT, &format);
-
- - buffer->attachment = __DRI_BUFFER_BACK_LEFT;
- + buffer->attachment = attachment;
- buffer->name = name;
- buffer->pitch = pitch;
- buffer->flags = 0;
- @@ -656,12 +751,28 @@ back_bo_to_dri_buffer(struct dri2_egl_surface *dri2_surf, __DRIbuffer *buffer)
- }
- }
-
- -static int
- -update_buffers(struct dri2_egl_surface *dri2_surf)
- +static void
- +back_bo_to_dri_buffer(struct dri2_egl_display *dri2_dpy,
- + struct dri2_egl_surface *dri2_surf,
- + __DRIbuffer *buffer)
- {
- - struct dri2_egl_display *dri2_dpy =
- - dri2_egl_display(dri2_surf->base.Resource.Display);
- + bo_to_dri_buffer(dri2_dpy, __DRI_BUFFER_BACK_LEFT,
- + dri2_surf->back->dri_image, buffer);
- +}
- +
- +static void
- +front_bo_to_dri_buffer(struct dri2_egl_display *dri2_dpy,
- + struct dri2_egl_surface *dri2_surf,
- + __DRIbuffer *buffer)
- +{
- + bo_to_dri_buffer(dri2_dpy, __DRI_BUFFER_FRONT_LEFT,
- + dri2_surf->front, buffer);
- +}
-
- +static int
- +update_buffers(struct dri2_egl_display *dri2_dpy,
- + struct dri2_egl_surface *dri2_surf)
- +{
- if (dri2_surf->wl_win &&
- (dri2_surf->base.Width != dri2_surf->wl_win->width ||
- dri2_surf->base.Height != dri2_surf->wl_win->height)) {
- @@ -703,12 +814,13 @@ update_buffers(struct dri2_egl_surface *dri2_surf)
- }
-
- static int
- -update_buffers_if_needed(struct dri2_egl_surface *dri2_surf)
- +update_buffers_if_needed(struct dri2_egl_display *dri2_dpy,
- + struct dri2_egl_surface *dri2_surf)
- {
- if (dri2_surf->back != NULL)
- return 0;
-
- - return update_buffers(dri2_surf);
- + return update_buffers(dri2_dpy, dri2_surf);
- }
-
- static __DRIbuffer *
- @@ -718,17 +830,25 @@ dri2_wl_get_buffers_with_format(__DRIdrawable * driDrawable,
- int *out_count, void *loaderPrivate)
- {
- struct dri2_egl_surface *dri2_surf = loaderPrivate;
- + struct dri2_egl_display *dri2_dpy =
- + dri2_egl_display(dri2_surf->base.Resource.Display);
- int i, j;
-
- - if (update_buffers(dri2_surf) < 0)
- - return NULL;
- -
- for (i = 0, j = 0; i < 2 * count; i += 2, j++) {
- __DRIbuffer *local;
-
- switch (attachments[i]) {
- case __DRI_BUFFER_BACK_LEFT:
- - back_bo_to_dri_buffer(dri2_surf, &dri2_surf->buffers[j]);
- + if (update_buffers(dri2_dpy, dri2_surf) < 0)
- + return NULL;
- +
- + back_bo_to_dri_buffer(dri2_dpy, dri2_surf, &dri2_surf->buffers[j]);
- + break;
- + case __DRI_BUFFER_FRONT_LEFT:
- + if (allocate_front_buffer(dri2_dpy, dri2_surf, EGL_TRUE) < 0)
- + return NULL;
- +
- + front_bo_to_dri_buffer(dri2_dpy, dri2_surf, &dri2_surf->buffers[j]);
- break;
- default:
- local = dri2_egl_surface_alloc_local_buffer(dri2_surf, attachments[i],
- @@ -798,12 +918,30 @@ image_get_buffers(__DRIdrawable *driDrawable,
- struct __DRIimageList *buffers)
- {
- struct dri2_egl_surface *dri2_surf = loaderPrivate;
- + struct dri2_egl_display *dri2_dpy =
- + dri2_egl_display(dri2_surf->base.Resource.Display);
-
- - if (update_buffers(dri2_surf) < 0)
- - return 0;
- + buffers->image_mask = 0;
- + buffers->front = NULL;
- + buffers->back = NULL;
- +
- + if (buffer_mask & __DRI_IMAGE_BUFFER_BACK)
- + {
- + if (update_buffers(dri2_dpy, dri2_surf) < 0)
- + return 0;
-
- - buffers->image_mask = __DRI_IMAGE_BUFFER_BACK;
- - buffers->back = dri2_surf->back->dri_image;
- + buffers->image_mask |= __DRI_IMAGE_BUFFER_BACK;
- + buffers->back = dri2_surf->back->dri_image;
- + }
- +
- + if (buffer_mask & __DRI_IMAGE_BUFFER_FRONT)
- + {
- + if (allocate_front_buffer(dri2_dpy, dri2_surf, EGL_FALSE) < 0)
- + return 0;
- +
- + buffers->image_mask |= __DRI_IMAGE_BUFFER_FRONT;
- + buffers->front = dri2_surf->front;
- + }
-
- return 1;
- }
- @@ -1054,6 +1192,9 @@ dri2_wl_swap_buffers_with_damage(_EGLDisplay *disp,
- struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
- struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
-
- + if (draw->Type != EGL_WINDOW_BIT)
- + return EGL_TRUE;
- +
- if (!dri2_surf->wl_win)
- return _eglError(EGL_BAD_NATIVE_WINDOW, "dri2_swap_buffers");
-
- @@ -1068,7 +1209,7 @@ dri2_wl_swap_buffers_with_damage(_EGLDisplay *disp,
-
- /* Make sure we have a back buffer in case we're swapping without ever
- * rendering. */
- - if (update_buffers_if_needed(dri2_surf) < 0)
- + if (update_buffers_if_needed(dri2_dpy, dri2_surf) < 0)
- return _eglError(EGL_BAD_ALLOC, "dri2_swap_buffers");
-
- if (draw->SwapInterval > 0) {
- @@ -1153,9 +1294,13 @@ dri2_wl_swap_buffers_with_damage(_EGLDisplay *disp,
- static EGLint
- dri2_wl_query_buffer_age(_EGLDisplay *disp, _EGLSurface *surface)
- {
- + struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
- struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surface);
-
- - if (update_buffers_if_needed(dri2_surf) < 0) {
- + if (surface->Type != EGL_WINDOW_BIT)
- + return 0;
- +
- + if (update_buffers_if_needed(dri2_dpy, dri2_surf) < 0) {
- _eglError(EGL_BAD_ALLOC, "dri2_query_buffer_age");
- return -1;
- }
- @@ -1376,6 +1521,7 @@ static const struct dri2_egl_display_vtbl dri2_wl_display_vtbl = {
- .authenticate = dri2_wl_authenticate,
- .create_window_surface = dri2_wl_create_window_surface,
- .create_pixmap_surface = dri2_wl_create_pixmap_surface,
- + .create_pbuffer_surface = dri2_wl_create_pbuffer_surface,
- .destroy_surface = dri2_wl_destroy_surface,
- .create_image = dri2_create_image_khr,
- .swap_buffers = dri2_wl_swap_buffers,
- @@ -1418,7 +1564,7 @@ dri2_wl_add_configs_for_visuals(_EGLDisplay *disp)
- continue;
-
- dri2_conf = dri2_add_config(disp, dri2_dpy->driver_configs[i],
- - count + 1, EGL_WINDOW_BIT, NULL, dri2_wl_visuals[j].rgba_shifts, dri2_wl_visuals[j].rgba_sizes);
- + count + 1, EGL_WINDOW_BIT | EGL_PBUFFER_BIT, NULL, dri2_wl_visuals[j].rgba_shifts, dri2_wl_visuals[j].rgba_sizes);
- if (dri2_conf) {
- if (dri2_conf->base.ConfigID == count + 1)
- count++;
- @@ -1654,6 +1800,23 @@ dri2_wl_swrast_get_stride_for_format(int format, int w)
- return w * (dri2_wl_visuals[visual_idx].bpp / 8);
- }
-
- +static EGLBoolean
- +swrast_allocate_local_buffer(int format, int w, int h, void **data)
- +{
- + int stride, size_map;
- + void *data_map;
- +
- + stride = dri2_wl_swrast_get_stride_for_format(format, w);
- + size_map = h * stride;
- +
- + data_map = malloc(size_map);
- + if (!data_map)
- + return EGL_FALSE;
- +
- + *data = data_map;
- + return EGL_TRUE;
- +}
- +
- static EGLBoolean
- dri2_wl_swrast_allocate_buffer(struct dri2_egl_surface *dri2_surf,
- int format, int w, int h,
- @@ -1775,8 +1938,24 @@ swrast_update_buffers(struct dri2_egl_surface *dri2_surf)
- return 0;
- }
-
- +static int
- +swrast_allocate_front_buffer(struct dri2_egl_surface *dri2_surf)
- +{
- + if (!dri2_surf->swrast_front) {
- + if (!swrast_allocate_local_buffer(dri2_surf->format,
- + dri2_surf->base.Width,
- + dri2_surf->base.Height,
- + &dri2_surf->swrast_front)) {
- + _eglError(EGL_BAD_ALLOC, "failed to allocate front buffer");
- + return -1;
- + }
- + }
- +
- + return 0;
- +}
- +
- static void*
- -dri2_wl_swrast_get_frontbuffer_data(struct dri2_egl_surface *dri2_surf)
- +dri2_wl_swrast_get_currentbuffer_data(struct dri2_egl_surface *dri2_surf)
- {
- /* if there has been a resize: */
- if (!dri2_surf->current)
- @@ -1846,7 +2025,9 @@ dri2_wl_swrast_get_drawable_info(__DRIdrawable * draw,
- {
- struct dri2_egl_surface *dri2_surf = loaderPrivate;
-
- - (void) swrast_update_buffers(dri2_surf);
- + if (dri2_surf->base.Type == EGL_WINDOW_BIT)
- + (void) swrast_update_buffers(dri2_surf);
- +
- *x = 0;
- *y = 0;
- *w = dri2_surf->base.Width;
- @@ -1865,7 +2046,11 @@ dri2_wl_swrast_get_image(__DRIdrawable * read,
- int dst_stride = copy_width;
- char *src, *dst;
-
- - src = dri2_wl_swrast_get_frontbuffer_data(dri2_surf);
- + if (dri2_surf->base.Type == EGL_WINDOW_BIT)
- + src = dri2_wl_swrast_get_currentbuffer_data(dri2_surf);
- + else
- + src = dri2_surf->swrast_front;
- +
- if (!src) {
- memset(data, 0, copy_width * h);
- return;
- @@ -1903,14 +2088,20 @@ dri2_wl_swrast_put_image2(__DRIdrawable * draw, int op,
-
- assert(copy_width <= stride);
-
- - (void) swrast_update_buffers(dri2_surf);
- - dst = dri2_wl_swrast_get_backbuffer_data(dri2_surf);
- + if (dri2_surf->base.Type == EGL_WINDOW_BIT) {
- + (void) swrast_update_buffers(dri2_surf);
- + dst = dri2_wl_swrast_get_backbuffer_data(dri2_surf);
-
- - /* partial copy, copy old content */
- - if (copy_width < dst_stride)
- - dri2_wl_swrast_get_image(draw, 0, 0,
- - dri2_surf->base.Width, dri2_surf->base.Height,
- - dst, loaderPrivate);
- + /* partial copy, copy old content */
- + if (copy_width < dst_stride)
- + dri2_wl_swrast_get_image(draw, 0, 0,
- + dri2_surf->base.Width, dri2_surf->base.Height,
- + dst, loaderPrivate);
- + } else {
- + (void) swrast_allocate_front_buffer(dri2_surf);
- + dst = dri2_surf->swrast_front;
- + assert(dst);
- + }
-
- dst += x_offset;
- dst += y * dst_stride;
- @@ -1928,7 +2119,9 @@ dri2_wl_swrast_put_image2(__DRIdrawable * draw, int op,
- src += stride;
- dst += dst_stride;
- }
- - dri2_wl_swrast_commit_backbuffer(dri2_surf);
- +
- + if (dri2_surf->base.Type == EGL_WINDOW_BIT)
- + dri2_wl_swrast_commit_backbuffer(dri2_surf);
- }
-
- static void
- @@ -1996,6 +2189,7 @@ static const struct dri2_egl_display_vtbl dri2_wl_swrast_display_vtbl = {
- .authenticate = NULL,
- .create_window_surface = dri2_wl_create_window_surface,
- .create_pixmap_surface = dri2_wl_create_pixmap_surface,
- + .create_pbuffer_surface = dri2_wl_create_pbuffer_surface,
- .destroy_surface = dri2_wl_destroy_surface,
- .create_image = dri2_create_image_khr,
- .swap_buffers = dri2_wl_swrast_swap_buffers,
|