[Mesa-dev] [PATCH] drisw/gallium/llvmpipe: add MESA_copy_sub_buffer support
Jose Fonseca
jfonseca at vmware.com
Thu Nov 28 08:31:48 PST 2013
----- Original Message -----
> This patches add MESA_copy_sub_buffer support to the dri sw loader and
> then to gallium state tracker, llvmpipe, softpipe and other bits.
>
> It reuses the dri1 driver extension interface, and it updates the swrast
> loader interface for a new putimage which can take a stride.
>
> I've tested this with gnome-shell with a cogl hacked to reenable sub copies
> for llvmpipe and the one piglit test.
>
> I could probably split this patch up as well.
>
> Signed-off-by: Dave Airlie <airlied at redhat.com>
> ---
> include/GL/internal/dri_interface.h | 9 +++-
> src/gallium/drivers/llvmpipe/lp_screen.c | 17 +++++++
> src/gallium/drivers/softpipe/sp_screen.c | 19 ++++++++
> src/gallium/include/pipe/p_screen.h | 6 ++-
> src/gallium/include/state_tracker/drisw_api.h | 2 +
> src/gallium/include/state_tracker/sw_winsys.h | 6 +++
> src/gallium/state_trackers/dri/sw/drisw.c | 64
> ++++++++++++++++++++++++++-
> src/gallium/winsys/sw/dri/dri_sw_winsys.c | 22 ++++++++-
> src/glx/drisw_glx.c | 43 +++++++++++++++---
> src/mesa/drivers/dri/common/dri_util.c | 15 +++++++
> src/mesa/drivers/dri/common/dri_util.h | 5 ++-
> 11 files changed, 198 insertions(+), 10 deletions(-)
>
> diff --git a/include/GL/internal/dri_interface.h
> b/include/GL/internal/dri_interface.h
> index b012570..81f7e60 100644
> --- a/include/GL/internal/dri_interface.h
> +++ b/include/GL/internal/dri_interface.h
> @@ -437,7 +437,7 @@ struct __DRIdamageExtensionRec {
> * SWRast Loader extension.
> */
> #define __DRI_SWRAST_LOADER "DRI_SWRastLoader"
> -#define __DRI_SWRAST_LOADER_VERSION 1
> +#define __DRI_SWRAST_LOADER_VERSION 2
> struct __DRIswrastLoaderExtensionRec {
> __DRIextension base;
>
> @@ -461,6 +461,13 @@ struct __DRIswrastLoaderExtensionRec {
> void (*getImage)(__DRIdrawable *readable,
> int x, int y, int width, int height,
> char *data, void *loaderPrivate);
> +
> + /**
> + * Put image to drawable
> + */
> + void (*putImage2)(__DRIdrawable *drawable, int op,
> + int x, int y, int width, int height, int stride,
> + char *data, void *loaderPrivate);
> };
>
> /**
> diff --git a/src/gallium/drivers/llvmpipe/lp_screen.c
> b/src/gallium/drivers/llvmpipe/lp_screen.c
> index f61df98..a4bf27a 100644
> --- a/src/gallium/drivers/llvmpipe/lp_screen.c
> +++ b/src/gallium/drivers/llvmpipe/lp_screen.c
> @@ -415,6 +415,22 @@ llvmpipe_flush_frontbuffer(struct pipe_screen *_screen,
> winsys->displaytarget_display(winsys, texture->dt, context_private);
> }
>
> +static void
> +llvmpipe_flush_sub_frontbuffer(struct pipe_screen *_screen,
> + struct pipe_resource *resource,
> + unsigned level, unsigned layer,
> + void *context_private,
> + int x, int y, int w, int h)
> +{
> + struct llvmpipe_screen *screen = llvmpipe_screen(_screen);
> + struct sw_winsys *winsys = screen->winsys;
> + struct llvmpipe_resource *texture = llvmpipe_resource(resource);
> +
> + assert(texture->dt);
> + if (texture->dt)
> + winsys->displaytarget_sub_display(winsys, texture->dt,
> context_private,
> + x, y, w, h);
> +}
>
> static void
> llvmpipe_destroy_screen( struct pipe_screen *_screen )
> @@ -525,6 +541,7 @@ llvmpipe_create_screen(struct sw_winsys *winsys)
>
> screen->base.context_create = llvmpipe_create_context;
> screen->base.flush_frontbuffer = llvmpipe_flush_frontbuffer;
> + screen->base.flush_sub_frontbuffer = llvmpipe_flush_sub_frontbuffer;
> screen->base.fence_reference = llvmpipe_fence_reference;
> screen->base.fence_signalled = llvmpipe_fence_signalled;
> screen->base.fence_finish = llvmpipe_fence_finish;
> diff --git a/src/gallium/drivers/softpipe/sp_screen.c
> b/src/gallium/drivers/softpipe/sp_screen.c
> index 47ef20e..093357b 100644
> --- a/src/gallium/drivers/softpipe/sp_screen.c
> +++ b/src/gallium/drivers/softpipe/sp_screen.c
> @@ -377,6 +377,23 @@ softpipe_flush_frontbuffer(struct pipe_screen *_screen,
> winsys->displaytarget_display(winsys, texture->dt, context_private);
> }
>
> +static void
> +softpipe_flush_sub_frontbuffer(struct pipe_screen *_screen,
> + struct pipe_resource *resource,
> + unsigned level, unsigned layer,
> + void *context_private,
> + int x, int y, int w, int h)
> +{
> + struct softpipe_screen *screen = softpipe_screen(_screen);
> + struct sw_winsys *winsys = screen->winsys;
> + struct softpipe_resource *texture = softpipe_resource(resource);
> +
> + assert(texture->dt);
> + if (texture->dt)
> + winsys->displaytarget_sub_display(winsys, texture->dt,
> context_private,
> + x, y, w, h);
> +}
> +
> static uint64_t
> softpipe_get_timestamp(struct pipe_screen *_screen)
> {
> @@ -411,6 +428,8 @@ softpipe_create_screen(struct sw_winsys *winsys)
> screen->base.context_create = softpipe_create_context;
> screen->base.flush_frontbuffer = softpipe_flush_frontbuffer;
>
> + screen->base.flush_sub_frontbuffer = softpipe_flush_sub_frontbuffer;
> +
> screen->use_llvm = debug_get_option_use_llvm();
>
> util_format_s3tc_init();
> diff --git a/src/gallium/include/pipe/p_screen.h
> b/src/gallium/include/pipe/p_screen.h
> index 3ed7f26..8fd4f72 100644
> --- a/src/gallium/include/pipe/p_screen.h
> +++ b/src/gallium/include/pipe/p_screen.h
> @@ -187,7 +187,11 @@ struct pipe_screen {
> unsigned level, unsigned layer,
> void *winsys_drawable_handle );
>
> -
> + void (*flush_sub_frontbuffer)( struct pipe_screen *screen,
> + struct pipe_resource *resource,
> + unsigned level, unsigned layer,
> + void *winsys_drawable_handle,
> + int x, int y, int w, int h);
Instead of I'd prefer that we added an optional rectangle structure pointer to flush_frontbuffer. Less one entrypoint, and both paths can probably share a lot of code in most cases. Ditto for sw_winsys.h.
This should be documented in src/gallium/docs.
Jose
>
> /** Set ptr = fence, with reference counting */
> void (*fence_reference)( struct pipe_screen *screen,
> diff --git a/src/gallium/include/state_tracker/drisw_api.h
> b/src/gallium/include/state_tracker/drisw_api.h
> index 944a649..328440c 100644
> --- a/src/gallium/include/state_tracker/drisw_api.h
> +++ b/src/gallium/include/state_tracker/drisw_api.h
> @@ -13,6 +13,8 @@ struct drisw_loader_funcs
> {
> void (*put_image) (struct dri_drawable *dri_drawable,
> void *data, unsigned width, unsigned height);
> + void (*put_image2) (struct dri_drawable *dri_drawable,
> + void *data, int x, int y, unsigned width, unsigned
> height, unsigned stride);
> };
>
> /**
> diff --git a/src/gallium/include/state_tracker/sw_winsys.h
> b/src/gallium/include/state_tracker/sw_winsys.h
> index 0b11fe3..6422f98 100644
> --- a/src/gallium/include/state_tracker/sw_winsys.h
> +++ b/src/gallium/include/state_tracker/sw_winsys.h
> @@ -131,6 +131,12 @@ struct sw_winsys
> struct sw_displaytarget *dt,
> void *context_private );
>
> + void
> + (*displaytarget_sub_display)( struct sw_winsys *ws,
> + struct sw_displaytarget *dt,
> + void *context_private,
> + int x, int y, int w, int h);
> +
> void
> (*displaytarget_destroy)( struct sw_winsys *ws,
> struct sw_displaytarget *dt );
> diff --git a/src/gallium/state_trackers/dri/sw/drisw.c
> b/src/gallium/state_trackers/dri/sw/drisw.c
> index 9f00a53..6268906 100644
> --- a/src/gallium/state_trackers/dri/sw/drisw.c
> +++ b/src/gallium/state_trackers/dri/sw/drisw.c
> @@ -71,6 +71,18 @@ put_image(__DRIdrawable *dPriv, void *data, unsigned
> width, unsigned height)
> }
>
> static INLINE void
> +put_image2(__DRIdrawable *dPriv, void *data, int x, int y,
> + unsigned width, unsigned height, unsigned stride)
> +{
> + __DRIscreen *sPriv = dPriv->driScreenPriv;
> + const __DRIswrastLoaderExtension *loader = sPriv->swrast_loader;
> +
> + loader->putImage2(dPriv, __DRI_SWRAST_IMAGE_OP_SWAP,
> + x, y, width, height, stride,
> + data, dPriv->loaderPrivate);
> +}
> +
> +static INLINE void
> get_image(__DRIdrawable *dPriv, int x, int y, int width, int height, void
> *data)
> {
> __DRIscreen *sPriv = dPriv->driScreenPriv;
> @@ -99,6 +111,16 @@ drisw_put_image(struct dri_drawable *drawable,
> put_image(dPriv, data, width, height);
> }
>
> +static void
> +drisw_put_image2(struct dri_drawable *drawable,
> + void *data, int x, int y, unsigned width, unsigned height,
> + unsigned stride)
> +{
> + __DRIdrawable *dPriv = drawable->dPriv;
> +
> + put_image2(dPriv, data, x, y, width, height, stride);
> +}
> +
> static INLINE void
> drisw_present_texture(__DRIdrawable *dPriv,
> struct pipe_resource *ptex)
> @@ -113,6 +135,20 @@ drisw_present_texture(__DRIdrawable *dPriv,
> }
>
> static INLINE void
> +drisw_present_sub_texture(__DRIdrawable *dPriv,
> + struct pipe_resource *ptex, int x, int y,
> + int w, int h)
> +{
> + struct dri_drawable *drawable = dri_drawable(dPriv);
> + struct dri_screen *screen = dri_screen(drawable->sPriv);
> +
> + if (swrast_no_present)
> + return;
> +
> + screen->base.screen->flush_sub_frontbuffer(screen->base.screen, ptex, 0,
> 0, drawable, x, y, w, h);
> +}
> +
> +static INLINE void
> drisw_invalidate_drawable(__DRIdrawable *dPriv)
> {
> struct dri_drawable *drawable = dri_drawable(dPriv);
> @@ -158,6 +194,29 @@ drisw_swap_buffers(__DRIdrawable *dPriv)
> }
>
> static void
> +drisw_copy_sub_buffer(__DRIdrawable *dPriv, int x, int y,
> + int w, int h)
> +{
> + struct dri_context *ctx = dri_get_current(dPriv->driScreenPriv);
> + struct dri_drawable *drawable = dri_drawable(dPriv);
> + struct pipe_resource *ptex;
> +
> + if (!ctx)
> + return;
> +
> + ptex = drawable->textures[ST_ATTACHMENT_BACK_LEFT];
> +
> + if (ptex) {
> + if (ctx->pp && drawable->textures[ST_ATTACHMENT_DEPTH_STENCIL])
> + pp_run(ctx->pp, ptex, ptex,
> drawable->textures[ST_ATTACHMENT_DEPTH_STENCIL]);
> +
> + ctx->st->flush(ctx->st, ST_FLUSH_FRONT, NULL);
> +
> + drisw_present_sub_texture(dPriv, ptex, x, dPriv->h - y - h, w, h);
> + }
> +}
> +
> +static void
> drisw_flush_frontbuffer(struct dri_context *ctx,
> struct dri_drawable *drawable,
> enum st_attachment_type statt)
> @@ -288,7 +347,8 @@ static const __DRIextension *drisw_screen_extensions[] =
> {
> };
>
> static struct drisw_loader_funcs drisw_lf = {
> - .put_image = drisw_put_image
> + .put_image = drisw_put_image,
> + .put_image2 = drisw_put_image2
> };
>
> static const __DRIconfig **
> @@ -359,12 +419,14 @@ const struct __DriverAPIRec driDriverAPI = {
> .SwapBuffers = drisw_swap_buffers,
> .MakeCurrent = dri_make_current,
> .UnbindContext = dri_unbind_context,
> + .CopySubBuffer = drisw_copy_sub_buffer,
> };
>
> /* This is the table of extensions that the loader will dlsym() for. */
> PUBLIC const __DRIextension *__driDriverExtensions[] = {
> &driCoreExtension.base,
> &driSWRastExtension.base,
> + &driCopySubBufferExtension,
> &gallium_config_options.base,
> NULL
> };
> diff --git a/src/gallium/winsys/sw/dri/dri_sw_winsys.c
> b/src/gallium/winsys/sw/dri/dri_sw_winsys.c
> index edb3a38..3854228 100644
> --- a/src/gallium/winsys/sw/dri/dri_sw_winsys.c
> +++ b/src/gallium/winsys/sw/dri/dri_sw_winsys.c
> @@ -184,6 +184,26 @@ dri_sw_displaytarget_display(struct sw_winsys *ws,
> dri_sw_ws->lf->put_image(dri_drawable, dri_sw_dt->data, width, height);
> }
>
> +static void
> +dri_sw_displaytarget_sub_display(struct sw_winsys *ws,
> + struct sw_displaytarget *dt,
> + void *context_private,
> + int x, int y, int w, int h)
> +{
> + struct dri_sw_winsys *dri_sw_ws = dri_sw_winsys(ws);
> + struct dri_sw_displaytarget *dri_sw_dt = dri_sw_displaytarget(dt);
> + struct dri_drawable *dri_drawable = (struct dri_drawable
> *)context_private;
> + unsigned width, height;
> + int blsize = util_format_get_blocksize(dri_sw_dt->format);
> + int line;
> + void *data;
> +
> + width = dri_sw_dt->stride / blsize;
> +
> + data = dri_sw_dt->data + (dri_sw_dt->stride * y) + x * blsize;
> + dri_sw_ws->lf->put_image2(dri_drawable, data,
> + x, y, w, h, dri_sw_dt->stride);
> +}
>
> static void
> dri_destroy_sw_winsys(struct sw_winsys *winsys)
> @@ -216,7 +236,7 @@ dri_create_sw_winsys(struct drisw_loader_funcs *lf)
> ws->base.displaytarget_unmap = dri_sw_displaytarget_unmap;
>
> ws->base.displaytarget_display = dri_sw_displaytarget_display;
> -
> + ws->base.displaytarget_sub_display = dri_sw_displaytarget_sub_display;
> return &ws->base;
> }
>
> diff --git a/src/glx/drisw_glx.c b/src/glx/drisw_glx.c
> index cb1d650..13a4b96 100644
> --- a/src/glx/drisw_glx.c
> +++ b/src/glx/drisw_glx.c
> @@ -49,6 +49,7 @@ struct drisw_screen
> const __DRIcoreExtension *core;
> const __DRIswrastExtension *swrast;
> const __DRItexBufferExtension *texBuffer;
> + const __DRIcopySubBufferExtension *copySubBuffer;
>
> const __DRIconfig **driver_configs;
>
> @@ -171,9 +172,9 @@ bytes_per_line(unsigned pitch_bits, unsigned mul)
> }
>
> static void
> -swrastPutImage(__DRIdrawable * draw, int op,
> - int x, int y, int w, int h,
> - char *data, void *loaderPrivate)
> +swrastPutImage2(__DRIdrawable * draw, int op,
> + int x, int y, int w, int h, int stride,
> + char *data, void *loaderPrivate)
> {
> struct drisw_drawable *pdp = loaderPrivate;
> __GLXDRIdrawable *pdraw = &(pdp->base);
> @@ -199,7 +200,7 @@ swrastPutImage(__DRIdrawable * draw, int op,
> 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);
>
> XPutImage(dpy, drawable, gc, ximage, 0, 0, x, y, w, h);
>
> @@ -207,6 +208,14 @@ swrastPutImage(__DRIdrawable * draw, int op,
> }
>
> static void
> +swrastPutImage(__DRIdrawable * draw, int op,
> + int x, int y, int w, int h,
> + char *data, void *loaderPrivate)
> +{
> + swrastPutImage2(draw, op, x, y, w, h, 0, data, loaderPrivate);
> +}
> +
> +static void
> swrastGetImage(__DRIdrawable * read,
> int x, int y, int w, int h,
> char *data, void *loaderPrivate)
> @@ -234,7 +243,8 @@ static const __DRIswrastLoaderExtension
> swrastLoaderExtension = {
> {__DRI_SWRAST_LOADER, __DRI_SWRAST_LOADER_VERSION},
> swrastGetDrawableInfo,
> swrastPutImage,
> - swrastGetImage
> + swrastGetImage,
> + swrastPutImage2,
> };
>
> static const __DRIextension *loader_extensions[] = {
> @@ -585,6 +595,21 @@ driswSwapBuffers(__GLXDRIdrawable * pdraw,
> }
>
> static void
> +driswCopySubBuffer(__GLXDRIdrawable * pdraw,
> + int x, int y, int width, int height, Bool flush)
> +{
> + struct drisw_drawable *pdp = (struct drisw_drawable *) pdraw;
> + struct drisw_screen *psc = (struct drisw_screen *) pdp->base.psc;
> +
> + if (flush) {
> + glFlush();
> + }
> +
> + (*psc->copySubBuffer->copySubBuffer) (pdp->driDrawable,
> + x, y, width, height);
> +}
> +
> +static void
> driswDestroyScreen(struct glx_screen *base)
> {
> struct drisw_screen *psc = (struct drisw_screen *) base;
> @@ -632,6 +657,9 @@ driswBindExtensions(struct drisw_screen *psc, const
> __DRIextension **extensions)
> "GLX_EXT_create_context_es2_profile");
> }
>
> + if (psc->copySubBuffer)
> + __glXEnableDirectExtension(&psc->base, "GLX_MESA_copy_sub_buffer");
> +
> /* FIXME: Figure out what other extensions can be ported here from dri2.
> */
> for (i = 0; extensions[i]; i++) {
> if ((strcmp(extensions[i]->name, __DRI_TEX_BUFFER) == 0)) {
> @@ -673,6 +701,8 @@ driswCreateScreen(int screen, struct glx_display *priv)
> psc->core = (__DRIcoreExtension *) extensions[i];
> if (strcmp(extensions[i]->name, __DRI_SWRAST) == 0)
> psc->swrast = (__DRIswrastExtension *) extensions[i];
> + if (strcmp(extensions[i]->name, __DRI_COPY_SUB_BUFFER) == 0)
> + psc->copySubBuffer = (__DRIcopySubBufferExtension *) extensions[i];
> }
>
> if (psc->core == NULL || psc->swrast == NULL) {
> @@ -718,6 +748,9 @@ driswCreateScreen(int screen, struct glx_display *priv)
> psp->createDrawable = driswCreateDrawable;
> psp->swapBuffers = driswSwapBuffers;
>
> + if (psc->copySubBuffer)
> + psp->copySubBuffer = driswCopySubBuffer;
> +
> return &psc->base;
>
> handle_error:
> diff --git a/src/mesa/drivers/dri/common/dri_util.c
> b/src/mesa/drivers/dri/common/dri_util.c
> index 0bce77e..fd2eca7 100644
> --- a/src/mesa/drivers/dri/common/dri_util.c
> +++ b/src/mesa/drivers/dri/common/dri_util.c
> @@ -873,3 +873,18 @@ const __DRIimageDriverExtension driImageDriverExtension
> = {
> .getAPIMask = driGetAPIMask,
> .createContextAttribs = driCreateContextAttribs,
> };
> +
> +/* swrast copy sub buffer entrypoint. */
> +static void driCopySubBuffer(__DRIdrawable *pdp, int x, int y,
> + int w, int h)
> +{
> + assert(pdp->driScreenPriv->swrast_loader);
> +
> + pdp->driScreenPriv->driver->CopySubBuffer(pdp, x, y, w, h);
> +}
> +
> +/* for swrast only */
> +const __DRIcopySubBufferExtension driCopySubBufferExtension = {
> + { __DRI_COPY_SUB_BUFFER, 1 },
> + .copySubBuffer = driCopySubBuffer,
> +};
> diff --git a/src/mesa/drivers/dri/common/dri_util.h
> b/src/mesa/drivers/dri/common/dri_util.h
> index 79a8564..4cfa75d 100644
> --- a/src/mesa/drivers/dri/common/dri_util.h
> +++ b/src/mesa/drivers/dri/common/dri_util.h
> @@ -66,7 +66,7 @@ extern const __DRIcoreExtension driCoreExtension;
> extern const __DRIswrastExtension driSWRastExtension;
> extern const __DRIdri2Extension driDRI2Extension;
> extern const __DRI2configQueryExtension dri2ConfigQueryExtension;
> -
> +extern const __DRIcopySubBufferExtension driCopySubBufferExtension;
> /**
> * Driver callback functions.
> *
> @@ -115,6 +115,9 @@ struct __DriverAPIRec {
> int width, int height);
>
> void (*ReleaseBuffer) (__DRIscreen *screenPrivate, __DRIbuffer *buffer);
> +
> + void (*CopySubBuffer)(__DRIdrawable *driDrawPriv, int x, int y,
> + int w, int h);
> };
>
> extern const struct __DriverAPIRec driDriverAPI;
> --
> 1.8.3.1
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> https://urldefense.proofpoint.com/v1/url?u=http://lists.freedesktop.org/mailman/listinfo/mesa-dev&k=oIvRg1%2BdGAgOoM1BIlLLqw%3D%3D%0A&r=NMr9uy2iTjWVixC0wOcYCWEIYhfo80qKwRgdodpoDzA%3D%0A&m=zoWAJA8PJdcFkgUaNDdbhLd398VJUf%2Bn9wo0ZSx0NcQ%3D%0A&s=a81127bd14656765a2bad54fc18ccdce2f0e0ecfeadd427382f9a564ffcdcb7b
>
More information about the mesa-dev
mailing list