----- 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 <airl...@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@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 > _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev