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: d6edccee8d "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>
This commit is contained in:
Mathias Fröhlich 2019-12-13 17:09:56 +01:00 committed by Daniel Stone
parent 6fc0890cd9
commit c7617d8908
4 changed files with 96 additions and 5 deletions

View File

@ -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] = {

View File

@ -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

View File

@ -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

View File

@ -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