ping?
On 9 October 2015 at 10:38, Dave Airlie <airl...@gmail.com> wrote: > From: Dave Airlie <airl...@redhat.com> > > 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 > > Signed-off-by: Dave Airlie <airl...@redhat.com> > --- > include/GL/internal/dri_interface.h | 11 +++++++- > src/gallium/drivers/llvmpipe/lp_texture.c | 21 ++++++++++----- > src/gallium/drivers/softpipe/sp_texture.c | 18 ++++++++++--- > src/gallium/include/pipe/p_screen.h | 4 +++ > src/gallium/include/state_tracker/drisw_api.h | 3 +++ > src/gallium/include/state_tracker/sw_winsys.h | 1 + > src/gallium/state_trackers/dri/drisw.c | 39 > +++++++++++++++++++++++++-- > src/gallium/winsys/sw/dri/dri_sw_winsys.c | 15 +++++++++++ > src/glx/drisw_glx.c | 19 +++++++++---- > 9 files changed, 113 insertions(+), 18 deletions(-) > > diff --git a/include/GL/internal/dri_interface.h > b/include/GL/internal/dri_interface.h > index a0f155a..6bbd3fa 100644 > --- a/include/GL/internal/dri_interface.h > +++ b/include/GL/internal/dri_interface.h > @@ -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); > }; > > /** > diff --git a/src/gallium/drivers/llvmpipe/lp_texture.c > b/src/gallium/drivers/llvmpipe/lp_texture.c > index af46342..7862ac8 100644 > --- a/src/gallium/drivers/llvmpipe/lp_texture.c > +++ b/src/gallium/drivers/llvmpipe/lp_texture.c > @@ -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; > diff --git a/src/gallium/drivers/softpipe/sp_texture.c > b/src/gallium/drivers/softpipe/sp_texture.c > index e1ea5df..3347f5f 100644 > --- a/src/gallium/drivers/softpipe/sp_texture.c > +++ b/src/gallium/drivers/softpipe/sp_texture.c > @@ -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; > diff --git a/src/gallium/include/pipe/p_screen.h > b/src/gallium/include/pipe/p_screen.h > index a22fb93..f868d71 100644 > --- a/src/gallium/include/pipe/p_screen.h > +++ b/src/gallium/include/pipe/p_screen.h > @@ -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 > diff --git a/src/gallium/include/state_tracker/drisw_api.h > b/src/gallium/include/state_tracker/drisw_api.h > index 328440c..cd5a27e 100644 > --- a/src/gallium/include/state_tracker/drisw_api.h > +++ b/src/gallium/include/state_tracker/drisw_api.h > @@ -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, > diff --git a/src/gallium/include/state_tracker/sw_winsys.h > b/src/gallium/include/state_tracker/sw_winsys.h > index a3479eb..0b792cd 100644 > --- a/src/gallium/include/state_tracker/sw_winsys.h > +++ b/src/gallium/include/state_tracker/sw_winsys.h > @@ -90,6 +90,7 @@ struct sw_winsys > enum pipe_format format, > unsigned width, unsigned height, > unsigned alignment, > + const void *front_private, > unsigned *stride ); > > /** > diff --git a/src/gallium/state_trackers/dri/drisw.c > b/src/gallium/state_trackers/dri/drisw.c > index 4ec6992..753c59d 100644 > --- a/src/gallium/state_trackers/dri/drisw.c > +++ b/src/gallium/state_trackers/dri/drisw.c > @@ -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) > { > @@ -105,6 +120,18 @@ drisw_update_drawable_info(struct dri_drawable *drawable) > } > > 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 > }; > diff --git a/src/gallium/winsys/sw/dri/dri_sw_winsys.c > b/src/gallium/winsys/sw/dri/dri_sw_winsys.c > index 8451d83..5c98f26 100644 > --- a/src/gallium/winsys/sw/dri/dri_sw_winsys.c > +++ b/src/gallium/winsys/sw/dri/dri_sw_winsys.c > @@ -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; > } > > diff --git a/src/glx/drisw_glx.c b/src/glx/drisw_glx.c > index 749ceb0..76cc321 100644 > --- a/src/glx/drisw_glx.c > +++ b/src/glx/drisw_glx.c > @@ -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[] = { > -- > 2.5.0 > > _______________________________________________ > mesa-dev mailing list > mesa-dev@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/mesa-dev _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev