summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMathias Fröhlich <mathias.froehlich@web.de>2019-12-13 17:09:56 +0100
committerDaniel Stone <daniels@collabora.com>2020-02-17 04:01:37 +0000
commitc7617d8908a970124321ce731b43d5996c3c5775 (patch)
treeaa39bb22306678f050838f40fbf5e724fbdb2f8e
parent6fc0890cd9cf53dc41fee070faf4570314fdcbc3 (diff)
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>
-rw-r--r--src/egl/drivers/dri2/egl_dri2.c92
-rw-r--r--src/egl/drivers/dri2/egl_dri2.h3
-rw-r--r--src/egl/drivers/dri2/platform_device.c3
-rw-r--r--src/egl/drivers/dri2/platform_surfaceless.c3
4 files changed, 96 insertions, 5 deletions
diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c
index b418d81c56b..5e497b79bc4 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