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 "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] = {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue