gallium/swrast: fix front buffer blitting. (v2)
So I've known this was broken before, cogl has a workaround for it from what I know, but with the gallium based swrast drivers BlitFramebuffer from back to front or vice-versa was pretty broken. The legacy swrast driver tracks when a front buffer is used and does the get/put images when it is mapped/unmapped, so this patch attempts to add the same functionality to the gallium drivers. It creates a new context interface to denote when a front buffer is being created, and passes a private pointer to it, this pointer is then used to decide on map/unmap if the contents should be updated from the real frontbuffer using get/put image. This is primarily to make gtk's gl code work, the only thing I've tested so far is the glarea test from https://github.com/ebassi/glarea-example.git v2: bump extension version, check extension version before calling get image. (Ian) Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=91930 Cc: <mesa-stable@lists.freedesktop.org> Signed-off-by: Dave Airlie <airlied@redhat.com>
This commit is contained in:
parent
103de0225b
commit
2b67657096
|
@ -495,7 +495,7 @@ struct __DRIdamageExtensionRec {
|
|||
* SWRast Loader extension.
|
||||
*/
|
||||
#define __DRI_SWRAST_LOADER "DRI_SWRastLoader"
|
||||
#define __DRI_SWRAST_LOADER_VERSION 2
|
||||
#define __DRI_SWRAST_LOADER_VERSION 3
|
||||
struct __DRIswrastLoaderExtensionRec {
|
||||
__DRIextension base;
|
||||
|
||||
|
@ -528,6 +528,15 @@ struct __DRIswrastLoaderExtensionRec {
|
|||
void (*putImage2)(__DRIdrawable *drawable, int op,
|
||||
int x, int y, int width, int height, int stride,
|
||||
char *data, void *loaderPrivate);
|
||||
|
||||
/**
|
||||
* Put image to drawable
|
||||
*
|
||||
* \since 3
|
||||
*/
|
||||
void (*getImage2)(__DRIdrawable *readable,
|
||||
int x, int y, int width, int height, int stride,
|
||||
char *data, void *loaderPrivate);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -200,7 +200,8 @@ llvmpipe_can_create_resource(struct pipe_screen *screen,
|
|||
|
||||
static boolean
|
||||
llvmpipe_displaytarget_layout(struct llvmpipe_screen *screen,
|
||||
struct llvmpipe_resource *lpr)
|
||||
struct llvmpipe_resource *lpr,
|
||||
const void *map_front_private)
|
||||
{
|
||||
struct sw_winsys *winsys = screen->winsys;
|
||||
|
||||
|
@ -215,12 +216,13 @@ llvmpipe_displaytarget_layout(struct llvmpipe_screen *screen,
|
|||
lpr->base.format,
|
||||
width, height,
|
||||
64,
|
||||
map_front_private,
|
||||
&lpr->row_stride[0] );
|
||||
|
||||
if (lpr->dt == NULL)
|
||||
return FALSE;
|
||||
|
||||
{
|
||||
if (!map_front_private) {
|
||||
void *map = winsys->displaytarget_map(winsys, lpr->dt,
|
||||
PIPE_TRANSFER_WRITE);
|
||||
|
||||
|
@ -235,8 +237,9 @@ llvmpipe_displaytarget_layout(struct llvmpipe_screen *screen,
|
|||
|
||||
|
||||
static struct pipe_resource *
|
||||
llvmpipe_resource_create(struct pipe_screen *_screen,
|
||||
const struct pipe_resource *templat)
|
||||
llvmpipe_resource_create_front(struct pipe_screen *_screen,
|
||||
const struct pipe_resource *templat,
|
||||
const void *map_front_private)
|
||||
{
|
||||
struct llvmpipe_screen *screen = llvmpipe_screen(_screen);
|
||||
struct llvmpipe_resource *lpr = CALLOC_STRUCT(llvmpipe_resource);
|
||||
|
@ -254,7 +257,7 @@ llvmpipe_resource_create(struct pipe_screen *_screen,
|
|||
PIPE_BIND_SCANOUT |
|
||||
PIPE_BIND_SHARED)) {
|
||||
/* displayable surface */
|
||||
if (!llvmpipe_displaytarget_layout(screen, lpr))
|
||||
if (!llvmpipe_displaytarget_layout(screen, lpr, map_front_private))
|
||||
goto fail;
|
||||
}
|
||||
else {
|
||||
|
@ -300,7 +303,12 @@ llvmpipe_resource_create(struct pipe_screen *_screen,
|
|||
FREE(lpr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct pipe_resource *
|
||||
llvmpipe_resource_create(struct pipe_screen *_screen,
|
||||
const struct pipe_resource *templat)
|
||||
{
|
||||
return llvmpipe_resource_create_front(_screen, templat, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
llvmpipe_resource_destroy(struct pipe_screen *pscreen,
|
||||
|
@ -797,6 +805,7 @@ llvmpipe_init_screen_resource_funcs(struct pipe_screen *screen)
|
|||
#endif
|
||||
|
||||
screen->resource_create = llvmpipe_resource_create;
|
||||
screen->resource_create_front = llvmpipe_resource_create_front;
|
||||
screen->resource_destroy = llvmpipe_resource_destroy;
|
||||
screen->resource_from_handle = llvmpipe_resource_from_handle;
|
||||
screen->resource_get_handle = llvmpipe_resource_get_handle;
|
||||
|
|
|
@ -127,7 +127,8 @@ softpipe_can_create_resource(struct pipe_screen *screen,
|
|||
*/
|
||||
static boolean
|
||||
softpipe_displaytarget_layout(struct pipe_screen *screen,
|
||||
struct softpipe_resource *spr)
|
||||
struct softpipe_resource *spr,
|
||||
const void *map_front_private)
|
||||
{
|
||||
struct sw_winsys *winsys = softpipe_screen(screen)->winsys;
|
||||
|
||||
|
@ -139,6 +140,7 @@ softpipe_displaytarget_layout(struct pipe_screen *screen,
|
|||
spr->base.width0,
|
||||
spr->base.height0,
|
||||
64,
|
||||
map_front_private,
|
||||
&spr->stride[0] );
|
||||
|
||||
return spr->dt != NULL;
|
||||
|
@ -149,8 +151,9 @@ softpipe_displaytarget_layout(struct pipe_screen *screen,
|
|||
* Create new pipe_resource given the template information.
|
||||
*/
|
||||
static struct pipe_resource *
|
||||
softpipe_resource_create(struct pipe_screen *screen,
|
||||
const struct pipe_resource *templat)
|
||||
softpipe_resource_create_front(struct pipe_screen *screen,
|
||||
const struct pipe_resource *templat,
|
||||
const void *map_front_private)
|
||||
{
|
||||
struct softpipe_resource *spr = CALLOC_STRUCT(softpipe_resource);
|
||||
if (!spr)
|
||||
|
@ -169,7 +172,7 @@ softpipe_resource_create(struct pipe_screen *screen,
|
|||
if (spr->base.bind & (PIPE_BIND_DISPLAY_TARGET |
|
||||
PIPE_BIND_SCANOUT |
|
||||
PIPE_BIND_SHARED)) {
|
||||
if (!softpipe_displaytarget_layout(screen, spr))
|
||||
if (!softpipe_displaytarget_layout(screen, spr, map_front_private))
|
||||
goto fail;
|
||||
}
|
||||
else {
|
||||
|
@ -184,6 +187,12 @@ softpipe_resource_create(struct pipe_screen *screen,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static struct pipe_resource *
|
||||
softpipe_resource_create(struct pipe_screen *screen,
|
||||
const struct pipe_resource *templat)
|
||||
{
|
||||
return softpipe_resource_create_front(screen, templat, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
softpipe_resource_destroy(struct pipe_screen *pscreen,
|
||||
|
@ -514,6 +523,7 @@ void
|
|||
softpipe_init_screen_texture_funcs(struct pipe_screen *screen)
|
||||
{
|
||||
screen->resource_create = softpipe_resource_create;
|
||||
screen->resource_create_front = softpipe_resource_create_front;
|
||||
screen->resource_destroy = softpipe_resource_destroy;
|
||||
screen->resource_from_handle = softpipe_resource_from_handle;
|
||||
screen->resource_get_handle = softpipe_resource_get_handle;
|
||||
|
|
|
@ -169,6 +169,10 @@ struct pipe_screen {
|
|||
struct pipe_resource * (*resource_create)(struct pipe_screen *,
|
||||
const struct pipe_resource *templat);
|
||||
|
||||
struct pipe_resource * (*resource_create_front)(struct pipe_screen *,
|
||||
const struct pipe_resource *templat,
|
||||
const void *map_front_private);
|
||||
|
||||
/**
|
||||
* Create a texture from a winsys_handle. The handle is often created in
|
||||
* another process by first creating a pipe texture and then calling
|
||||
|
|
|
@ -11,6 +11,9 @@ struct dri_drawable;
|
|||
*/
|
||||
struct drisw_loader_funcs
|
||||
{
|
||||
void (*get_image) (struct dri_drawable *dri_drawable,
|
||||
int x, int y, unsigned width, unsigned height, unsigned stride,
|
||||
void *data);
|
||||
void (*put_image) (struct dri_drawable *dri_drawable,
|
||||
void *data, unsigned width, unsigned height);
|
||||
void (*put_image2) (struct dri_drawable *dri_drawable,
|
||||
|
|
|
@ -90,6 +90,7 @@ struct sw_winsys
|
|||
enum pipe_format format,
|
||||
unsigned width, unsigned height,
|
||||
unsigned alignment,
|
||||
const void *front_private,
|
||||
unsigned *stride );
|
||||
|
||||
/**
|
||||
|
|
|
@ -95,6 +95,21 @@ get_image(__DRIdrawable *dPriv, int x, int y, int width, int height, void *data)
|
|||
data, dPriv->loaderPrivate);
|
||||
}
|
||||
|
||||
static inline void
|
||||
get_image2(__DRIdrawable *dPriv, int x, int y, int width, int height, int stride, void *data)
|
||||
{
|
||||
__DRIscreen *sPriv = dPriv->driScreenPriv;
|
||||
const __DRIswrastLoaderExtension *loader = sPriv->swrast_loader;
|
||||
|
||||
/* getImage2 support is only in version 3 or newer */
|
||||
if (loader->base.version < 3)
|
||||
return;
|
||||
|
||||
loader->getImage2(dPriv,
|
||||
x, y, width, height, stride,
|
||||
data, dPriv->loaderPrivate);
|
||||
}
|
||||
|
||||
static void
|
||||
drisw_update_drawable_info(struct dri_drawable *drawable)
|
||||
{
|
||||
|
@ -104,6 +119,18 @@ drisw_update_drawable_info(struct dri_drawable *drawable)
|
|||
get_drawable_info(dPriv, &x, &y, &dPriv->w, &dPriv->h);
|
||||
}
|
||||
|
||||
static void
|
||||
drisw_get_image(struct dri_drawable *drawable,
|
||||
int x, int y, unsigned width, unsigned height, unsigned stride,
|
||||
void *data)
|
||||
{
|
||||
__DRIdrawable *dPriv = drawable->dPriv;
|
||||
int draw_x, draw_y, draw_w, draw_h;
|
||||
|
||||
get_drawable_info(dPriv, &draw_x, &draw_y, &draw_w, &draw_h);
|
||||
get_image2(dPriv, x, y, draw_w, draw_h, stride, data);
|
||||
}
|
||||
|
||||
static void
|
||||
drisw_put_image(struct dri_drawable *drawable,
|
||||
void *data, unsigned width, unsigned height)
|
||||
|
@ -236,6 +263,7 @@ drisw_allocate_textures(struct dri_context *stctx,
|
|||
unsigned count)
|
||||
{
|
||||
struct dri_screen *screen = dri_screen(drawable->sPriv);
|
||||
const __DRIswrastLoaderExtension *loader = drawable->dPriv->driScreenPriv->swrast_loader;
|
||||
struct pipe_resource templ;
|
||||
unsigned width, height;
|
||||
boolean resized;
|
||||
|
@ -281,8 +309,14 @@ drisw_allocate_textures(struct dri_context *stctx,
|
|||
templ.format = format;
|
||||
templ.bind = bind;
|
||||
|
||||
drawable->textures[statts[i]] =
|
||||
screen->base.screen->resource_create(screen->base.screen, &templ);
|
||||
if (statts[i] == ST_ATTACHMENT_FRONT_LEFT &&
|
||||
screen->base.screen->resource_create_front &&
|
||||
loader->base.version >= 3) {
|
||||
drawable->textures[statts[i]] =
|
||||
screen->base.screen->resource_create_front(screen->base.screen, &templ, (const void *)drawable);
|
||||
} else
|
||||
drawable->textures[statts[i]] =
|
||||
screen->base.screen->resource_create(screen->base.screen, &templ);
|
||||
}
|
||||
|
||||
drawable->old_w = width;
|
||||
|
@ -338,6 +372,7 @@ static const __DRIextension *drisw_screen_extensions[] = {
|
|||
};
|
||||
|
||||
static struct drisw_loader_funcs drisw_lf = {
|
||||
.get_image = drisw_get_image,
|
||||
.put_image = drisw_put_image,
|
||||
.put_image2 = drisw_put_image2
|
||||
};
|
||||
|
|
|
@ -44,8 +44,10 @@ struct dri_sw_displaytarget
|
|||
unsigned height;
|
||||
unsigned stride;
|
||||
|
||||
unsigned map_flags;
|
||||
void *data;
|
||||
void *mapped;
|
||||
const void *front_private;
|
||||
};
|
||||
|
||||
struct dri_sw_winsys
|
||||
|
@ -83,6 +85,7 @@ dri_sw_displaytarget_create(struct sw_winsys *winsys,
|
|||
enum pipe_format format,
|
||||
unsigned width, unsigned height,
|
||||
unsigned alignment,
|
||||
const void *front_private,
|
||||
unsigned *stride)
|
||||
{
|
||||
struct dri_sw_displaytarget *dri_sw_dt;
|
||||
|
@ -95,6 +98,7 @@ dri_sw_displaytarget_create(struct sw_winsys *winsys,
|
|||
dri_sw_dt->format = format;
|
||||
dri_sw_dt->width = width;
|
||||
dri_sw_dt->height = height;
|
||||
dri_sw_dt->front_private = front_private;
|
||||
|
||||
format_stride = util_format_get_stride(format, width);
|
||||
dri_sw_dt->stride = align(format_stride, alignment);
|
||||
|
@ -133,6 +137,12 @@ dri_sw_displaytarget_map(struct sw_winsys *ws,
|
|||
{
|
||||
struct dri_sw_displaytarget *dri_sw_dt = dri_sw_displaytarget(dt);
|
||||
dri_sw_dt->mapped = dri_sw_dt->data;
|
||||
|
||||
if (dri_sw_dt->front_private && (flags & PIPE_TRANSFER_READ)) {
|
||||
struct dri_sw_winsys *dri_sw_ws = dri_sw_winsys(ws);
|
||||
dri_sw_ws->lf->get_image((void *)dri_sw_dt->front_private, 0, 0, dri_sw_dt->width, dri_sw_dt->height, dri_sw_dt->stride, dri_sw_dt->data);
|
||||
}
|
||||
dri_sw_dt->map_flags = flags;
|
||||
return dri_sw_dt->mapped;
|
||||
}
|
||||
|
||||
|
@ -141,6 +151,11 @@ dri_sw_displaytarget_unmap(struct sw_winsys *ws,
|
|||
struct sw_displaytarget *dt)
|
||||
{
|
||||
struct dri_sw_displaytarget *dri_sw_dt = dri_sw_displaytarget(dt);
|
||||
if (dri_sw_dt->front_private && (dri_sw_dt->map_flags & PIPE_TRANSFER_WRITE)) {
|
||||
struct dri_sw_winsys *dri_sw_ws = dri_sw_winsys(ws);
|
||||
dri_sw_ws->lf->put_image2((void *)dri_sw_dt->front_private, dri_sw_dt->data, 0, 0, dri_sw_dt->width, dri_sw_dt->height, dri_sw_dt->stride);
|
||||
}
|
||||
dri_sw_dt->map_flags = 0;
|
||||
dri_sw_dt->mapped = NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -177,9 +177,9 @@ swrastPutImage(__DRIdrawable * draw, int op,
|
|||
}
|
||||
|
||||
static void
|
||||
swrastGetImage(__DRIdrawable * read,
|
||||
int x, int y, int w, int h,
|
||||
char *data, void *loaderPrivate)
|
||||
swrastGetImage2(__DRIdrawable * read,
|
||||
int x, int y, int w, int h, int stride,
|
||||
char *data, void *loaderPrivate)
|
||||
{
|
||||
struct drisw_drawable *prp = loaderPrivate;
|
||||
__GLXDRIdrawable *pread = &(prp->base);
|
||||
|
@ -193,20 +193,29 @@ swrastGetImage(__DRIdrawable * read,
|
|||
ximage->data = data;
|
||||
ximage->width = w;
|
||||
ximage->height = h;
|
||||
ximage->bytes_per_line = bytes_per_line(w * ximage->bits_per_pixel, 32);
|
||||
ximage->bytes_per_line = stride ? stride : bytes_per_line(w * ximage->bits_per_pixel, 32);
|
||||
|
||||
XGetSubImage(dpy, readable, x, y, w, h, ~0L, ZPixmap, ximage, 0, 0);
|
||||
|
||||
ximage->data = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
swrastGetImage(__DRIdrawable * read,
|
||||
int x, int y, int w, int h,
|
||||
char *data, void *loaderPrivate)
|
||||
{
|
||||
swrastGetImage2(read, x, y, w, h, 0, data, loaderPrivate);
|
||||
}
|
||||
|
||||
static const __DRIswrastLoaderExtension swrastLoaderExtension = {
|
||||
.base = {__DRI_SWRAST_LOADER, 2 },
|
||||
.base = {__DRI_SWRAST_LOADER, 3 },
|
||||
|
||||
.getDrawableInfo = swrastGetDrawableInfo,
|
||||
.putImage = swrastPutImage,
|
||||
.getImage = swrastGetImage,
|
||||
.putImage2 = swrastPutImage2,
|
||||
.getImage2 = swrastGetImage2,
|
||||
};
|
||||
|
||||
static const __DRIextension *loader_extensions[] = {
|
||||
|
|
Loading…
Reference in New Issue