Mesa (staging/20.0): egl: Implement getImage/putImage on pbuffer swrast.

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Wed Feb 19 17:20:03 UTC 2020


Module: Mesa
Branch: staging/20.0
Commit: f27e5d9df5bc9c85d45c2cb1f2a4997b453365fe
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=f27e5d9df5bc9c85d45c2cb1f2a4997b453365fe

Author: Mathias Fröhlich <mathias.froehlich at web.de>
Date:   Fri Dec 13 17:09:56 2019 +0100

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 at collabora.com>
Reviewed-by: Emil Velikov <emil.velikov at 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 at 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)

---

 .pick_status.json                           |  2 +-
 src/egl/drivers/dri2/egl_dri2.c             | 92 +++++++++++++++++++++++++++--
 src/egl/drivers/dri2/egl_dri2.h             |  3 +
 src/egl/drivers/dri2/platform_device.c      |  3 +
 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 0a16dce4dfc..f7b677d798b 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



More information about the mesa-commit mailing list