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:
parent
6fc0890cd9
commit
c7617d8908
|
@ -66,6 +66,7 @@
|
||||||
#include "util/u_vector.h"
|
#include "util/u_vector.h"
|
||||||
#include "mapi/glapi/glapi.h"
|
#include "mapi/glapi/glapi.h"
|
||||||
#include "util/bitscan.h"
|
#include "util/bitscan.h"
|
||||||
|
#include "util/u_math.h"
|
||||||
|
|
||||||
/* Additional definitions not yet in the drm_fourcc.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;
|
*h = dri2_surf->base.Height;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* HACK: technically we should have swrast_null, instead of these. We
|
static int
|
||||||
* get away since only pbuffers are supported, thus the callbacks are
|
dri2_get_bytes_per_pixel(struct dri2_egl_surface *dri2_surf)
|
||||||
* unused.
|
{
|
||||||
|
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 = {
|
const __DRIswrastLoaderExtension swrast_pbuffer_loader_extension = {
|
||||||
.base = { __DRI_SWRAST_LOADER, 1 },
|
.base = { __DRI_SWRAST_LOADER, 1 },
|
||||||
.getDrawableInfo = dri2_get_pbuffer_drawable_info,
|
.getDrawableInfo = dri2_get_pbuffer_drawable_info,
|
||||||
.putImage = NULL,
|
.putImage = dri2_put_image,
|
||||||
.getImage = NULL,
|
.getImage = dri2_get_image,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const EGLint dri2_to_egl_attribute_map[__DRI_ATTRIB_MAX] = {
|
static const EGLint dri2_to_egl_attribute_map[__DRI_ATTRIB_MAX] = {
|
||||||
|
|
|
@ -338,6 +338,9 @@ struct dri2_egl_surface
|
||||||
|
|
||||||
int out_fence_fd;
|
int out_fence_fd;
|
||||||
EGLBoolean enable_out_fence;
|
EGLBoolean enable_out_fence;
|
||||||
|
|
||||||
|
/* swrast device */
|
||||||
|
char *swrast_device_buffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct dri2_egl_config
|
struct dri2_egl_config
|
||||||
|
|
|
@ -66,6 +66,9 @@ device_free_images(struct dri2_egl_surface *dri2_surf)
|
||||||
dri2_dpy->image->destroyImage(dri2_surf->front);
|
dri2_dpy->image->destroyImage(dri2_surf->front);
|
||||||
dri2_surf->front = NULL;
|
dri2_surf->front = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free(dri2_surf->swrast_device_buffer);
|
||||||
|
dri2_surf->swrast_device_buffer = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
|
|
@ -60,6 +60,9 @@ surfaceless_free_images(struct dri2_egl_surface *dri2_surf)
|
||||||
dri2_dpy->image->destroyImage(dri2_surf->front);
|
dri2_dpy->image->destroyImage(dri2_surf->front);
|
||||||
dri2_surf->front = NULL;
|
dri2_surf->front = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free(dri2_surf->swrast_device_buffer);
|
||||||
|
dri2_surf->swrast_device_buffer = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
|
Loading…
Reference in New Issue