diff options
author | Mathias Fröhlich <mathias.froehlich@web.de> | 2019-12-13 17:09:56 +0100 |
---|---|---|
committer | Dylan Baker <dylan@pnwbakers.com> | 2020-02-18 08:52:35 -0800 |
commit | a0e6341fe4417e41cda0b19e4fa7f8bbe4e1dba1 (patch) | |
tree | 512e951f8e0d6e3afa2043b5085d6d6a13cc3616 | |
parent | 59e65b6aa27096002451bea6a0c6cf8b91f20b95 (diff) | |
download | mesa-a0e6341fe4417e41cda0b19e4fa7f8bbe4e1dba1.tar.gz |
egl: Implement getImage/putImage on pbuffer swrast.
This change adds getImage/putImage callbacks to the swrast pbuffer
loader extension.
This fixes a recent crash with Weston as well as a crashing
test with classic swrast without an official gitlab issue.
v2: Determine bytes per pixel differently and fix non X11 builds.
v3: Plug memory leak and fix crash on out of bounds access.
(Daniel Stone)
v4: Follow the code structure of the wayland get/put image
implementation - hopefully being more obvious.
Handle 64 bits formats.
Use BufferSize directly.
(Emil Velikov)
v5: Change pixel size computation.
(Eric Engestrom)
Reviewed-by: Daniel Stone <daniels@collabora.com>
Reviewed-by: Emil Velikov <emil.velikov@collabora.com>
Closes: https://gitlab.freedesktop.org/mesa/mesa/issues/2219
Fixes: d6edccee8da "egl: add EGL_platform_device support"
Signed-off-by: Mathias Fröhlich <Mathias.Froehlich@web.de>
Tested-by: Marge Bot <https://gitlab.freedesktop.org/mesa/mesa/merge_requests/3711>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/merge_requests/3711>
(cherry picked from commit c7617d8908a970124321ce731b43d5996c3c5775)
-rw-r--r-- | .pick_status.json | 2 | ||||
-rw-r--r-- | src/egl/drivers/dri2/egl_dri2.c | 92 | ||||
-rw-r--r-- | src/egl/drivers/dri2/egl_dri2.h | 3 | ||||
-rw-r--r-- | src/egl/drivers/dri2/platform_device.c | 3 | ||||
-rw-r--r-- | src/egl/drivers/dri2/platform_surfaceless.c | 3 |
5 files changed, 97 insertions, 6 deletions
diff --git a/.pick_status.json b/.pick_status.json index bbb6d9df41c..2b9063a6fad 100644 --- a/.pick_status.json +++ b/.pick_status.json @@ -247,7 +247,7 @@ "description": "egl: Implement getImage/putImage on pbuffer swrast.", "nominated": true, "nomination_type": 1, - "resolution": 0, + "resolution": 1, "master_sha": null, "because_sha": "d6edccee8da38d4802020d5aa4d9e11bb7aae801" }, diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c index 23d0e469427..36828847e75 100644 --- a/src/egl/drivers/dri2/egl_dri2.c +++ b/src/egl/drivers/dri2/egl_dri2.c @@ -66,6 +66,7 @@ #include "util/u_vector.h" #include "mapi/glapi/glapi.h" #include "util/bitscan.h" +#include "util/u_math.h" /* Additional definitions not yet in the drm_fourcc.h. */ @@ -162,15 +163,96 @@ dri2_get_pbuffer_drawable_info(__DRIdrawable * draw, *h = dri2_surf->base.Height; } -/* HACK: technically we should have swrast_null, instead of these. We - * get away since only pbuffers are supported, thus the callbacks are - * unused. +static int +dri2_get_bytes_per_pixel(struct dri2_egl_surface *dri2_surf) +{ + const int depth = dri2_surf->base.Config->BufferSize; + return depth ? util_next_power_of_two(depth / 8) : 0; +} + +static void +dri2_put_image(__DRIdrawable * draw, int op, + int x, int y, int w, int h, + char *data, void *loaderPrivate) +{ + struct dri2_egl_surface *dri2_surf = loaderPrivate; + const int bpp = dri2_get_bytes_per_pixel(dri2_surf); + const int width = dri2_surf->base.Width; + const int height = dri2_surf->base.Height; + const int dst_stride = width*bpp; + const int src_stride = w*bpp; + const int x_offset = x*bpp; + int copy_width = src_stride; + + if (!dri2_surf->swrast_device_buffer) + dri2_surf->swrast_device_buffer = malloc(height*dst_stride); + + if (dri2_surf->swrast_device_buffer) { + const char *src = data; + char *dst = dri2_surf->swrast_device_buffer; + + dst += x_offset; + dst += y*dst_stride; + + /* Drivers are allowed to submit OOB PutImage requests, so clip here. */ + if (copy_width > dst_stride - x_offset) + copy_width = dst_stride - x_offset; + if (h > height - y) + h = height - y; + + for (; 0 < h; --h) { + memcpy(dst, src, copy_width); + dst += dst_stride; + src += src_stride; + } + } +} + +static void +dri2_get_image(__DRIdrawable * read, + int x, int y, int w, int h, + char *data, void *loaderPrivate) +{ + struct dri2_egl_surface *dri2_surf = loaderPrivate; + const int bpp = dri2_get_bytes_per_pixel(dri2_surf); + const int width = dri2_surf->base.Width; + const int height = dri2_surf->base.Height; + const int src_stride = width*bpp; + const int dst_stride = w*bpp; + const int x_offset = x*bpp; + int copy_width = dst_stride; + const char *src = dri2_surf->swrast_device_buffer; + char *dst = data; + + if (!src) { + memset(data, 0, copy_width * h); + return; + } + + src += x_offset; + src += y*src_stride; + + /* Drivers are allowed to submit OOB GetImage requests, so clip here. */ + if (copy_width > src_stride - x_offset) + copy_width = src_stride - x_offset; + if (h > height - y) + h = height - y; + + for (; 0 < h; --h) { + memcpy(dst, src, copy_width); + src += src_stride; + dst += dst_stride; + } + +} + +/* HACK: technically we should have swrast_null, instead of these. */ const __DRIswrastLoaderExtension swrast_pbuffer_loader_extension = { .base = { __DRI_SWRAST_LOADER, 1 }, .getDrawableInfo = dri2_get_pbuffer_drawable_info, - .putImage = NULL, - .getImage = NULL, + .putImage = dri2_put_image, + .getImage = dri2_get_image, }; static const EGLint dri2_to_egl_attribute_map[__DRI_ATTRIB_MAX] = { diff --git a/src/egl/drivers/dri2/egl_dri2.h b/src/egl/drivers/dri2/egl_dri2.h index 146f954eacf..8272da886ee 100644 --- a/src/egl/drivers/dri2/egl_dri2.h +++ b/src/egl/drivers/dri2/egl_dri2.h @@ -338,6 +338,9 @@ struct dri2_egl_surface int out_fence_fd; EGLBoolean enable_out_fence; + + /* swrast device */ + char *swrast_device_buffer; }; struct dri2_egl_config diff --git a/src/egl/drivers/dri2/platform_device.c b/src/egl/drivers/dri2/platform_device.c index 9bd7a93270d..eb2a743b01d 100644 --- a/src/egl/drivers/dri2/platform_device.c +++ b/src/egl/drivers/dri2/platform_device.c @@ -66,6 +66,9 @@ device_free_images(struct dri2_egl_surface *dri2_surf) dri2_dpy->image->destroyImage(dri2_surf->front); dri2_surf->front = NULL; } + + free(dri2_surf->swrast_device_buffer); + dri2_surf->swrast_device_buffer = NULL; } static int diff --git a/src/egl/drivers/dri2/platform_surfaceless.c b/src/egl/drivers/dri2/platform_surfaceless.c index 1a2d3be0aad..19d28aa61ab 100644 --- a/src/egl/drivers/dri2/platform_surfaceless.c +++ b/src/egl/drivers/dri2/platform_surfaceless.c @@ -60,6 +60,9 @@ surfaceless_free_images(struct dri2_egl_surface *dri2_surf) dri2_dpy->image->destroyImage(dri2_surf->front); dri2_surf->front = NULL; } + + free(dri2_surf->swrast_device_buffer); + dri2_surf->swrast_device_buffer = NULL; } static int |