[Mesa-dev] [PATCH] drisw/gallium/llvmpipe: add MESA_copy_sub_buffer support (v2)

Dave Airlie airlied at gmail.com
Thu Nov 28 12:50:26 PST 2013


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.

v2: pass a pipe_box, to reduce the entrypoints, as per Jose's review,
add to p_screen doc comments.

Signed-off-by: Dave Airlie <airlied at redhat.com>
---
 include/GL/internal/dri_interface.h                |  9 +++-
 src/gallium/auxiliary/vl/vl_winsys_dri.c           |  2 +-
 src/gallium/drivers/galahad/glhd_screen.c          |  5 +-
 src/gallium/drivers/i915/i915_screen.c             |  4 +-
 src/gallium/drivers/identity/id_screen.c           |  5 +-
 src/gallium/drivers/llvmpipe/lp_screen.c           |  6 +--
 src/gallium/drivers/noop/noop_pipe.c               |  2 +-
 src/gallium/drivers/rbug/rbug_screen.c             |  4 +-
 src/gallium/drivers/softpipe/sp_screen.c           |  5 +-
 src/gallium/drivers/trace/tr_screen.c              |  5 +-
 src/gallium/include/pipe/p_screen.h                |  7 +--
 src/gallium/include/state_tracker/drisw_api.h      |  2 +
 src/gallium/include/state_tracker/sw_winsys.h      |  5 +-
 src/gallium/state_trackers/dri/sw/drisw.c          | 58 ++++++++++++++++++++--
 .../state_trackers/egl/common/native_helper.c      |  2 +-
 src/gallium/state_trackers/egl/x11/native_ximage.c |  2 +-
 src/gallium/state_trackers/glx/xlib/xm_st.c        |  2 +-
 src/gallium/state_trackers/vdpau/presentation.c    |  2 +-
 src/gallium/state_trackers/xvmc/surface.c          |  2 +-
 .../targets/haiku-softpipe/GalliumContext.cpp      |  4 +-
 src/gallium/tests/graw/clear.c                     |  2 +-
 src/gallium/tests/graw/fs-test.c                   |  2 +-
 src/gallium/tests/graw/graw_util.h                 |  2 +-
 src/gallium/tests/graw/gs-test.c                   |  2 +-
 src/gallium/tests/graw/quad-sample.c               |  2 +-
 src/gallium/tests/graw/shader-leak.c               |  2 +-
 src/gallium/tests/graw/tri-gs.c                    |  2 +-
 src/gallium/tests/graw/tri-instanced.c             |  2 +-
 src/gallium/tests/graw/vs-test.c                   |  2 +-
 src/gallium/winsys/sw/dri/dri_sw_winsys.c          | 17 +++++--
 src/glx/drisw_glx.c                                | 43 ++++++++++++++--
 src/mesa/drivers/dri/common/dri_util.c             | 15 ++++++
 src/mesa/drivers/dri/common/dri_util.h             |  5 +-
 33 files changed, 178 insertions(+), 53 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/auxiliary/vl/vl_winsys_dri.c b/src/gallium/auxiliary/vl/vl_winsys_dri.c
index 7aec3fe..e747a66 100644
--- a/src/gallium/auxiliary/vl/vl_winsys_dri.c
+++ b/src/gallium/auxiliary/vl/vl_winsys_dri.c
@@ -115,7 +115,7 @@ static void
 vl_dri2_flush_frontbuffer(struct pipe_screen *screen,
                           struct pipe_resource *resource,
                           unsigned level, unsigned layer,
-                          void *context_private)
+                          void *context_private, struct pipe_box *sub_box)
 {
    struct vl_dri_screen *scrn = (struct vl_dri_screen*)context_private;
    uint32_t msc_hi, msc_lo;
diff --git a/src/gallium/drivers/galahad/glhd_screen.c b/src/gallium/drivers/galahad/glhd_screen.c
index 16a5ff1..5a91077 100644
--- a/src/gallium/drivers/galahad/glhd_screen.c
+++ b/src/gallium/drivers/galahad/glhd_screen.c
@@ -275,7 +275,8 @@ static void
 galahad_screen_flush_frontbuffer(struct pipe_screen *_screen,
                                   struct pipe_resource *_resource,
                                   unsigned level, unsigned layer,
-                                  void *context_private)
+                                  void *context_private,
+                                  struct pipe_box *sub_box)
 {
    struct galahad_screen *glhd_screen = galahad_screen(_screen);
    struct galahad_resource *glhd_resource = galahad_resource(_resource);
@@ -285,7 +286,7 @@ galahad_screen_flush_frontbuffer(struct pipe_screen *_screen,
    screen->flush_frontbuffer(screen,
                              resource,
                              level, layer,
-                             context_private);
+                             context_private, sub_box);
 }
 
 static void
diff --git a/src/gallium/drivers/i915/i915_screen.c b/src/gallium/drivers/i915/i915_screen.c
index 77607d0..7e35d84 100644
--- a/src/gallium/drivers/i915/i915_screen.c
+++ b/src/gallium/drivers/i915/i915_screen.c
@@ -420,7 +420,8 @@ static void
 i915_flush_frontbuffer(struct pipe_screen *screen,
                        struct pipe_resource *resource,
                        unsigned level, unsigned layer,
-                       void *winsys_drawable_handle)
+                       void *winsys_drawable_handle,
+                       struct pipe_box *sub_box)
 {
    /* XXX: Dummy right now. */
    (void)screen;
@@ -428,6 +429,7 @@ i915_flush_frontbuffer(struct pipe_screen *screen,
    (void)level;
    (void)layer;
    (void)winsys_drawable_handle;
+   (void)sub_box;
 }
 
 static void
diff --git a/src/gallium/drivers/identity/id_screen.c b/src/gallium/drivers/identity/id_screen.c
index 26df7f6..28cfa1f6 100644
--- a/src/gallium/drivers/identity/id_screen.c
+++ b/src/gallium/drivers/identity/id_screen.c
@@ -192,7 +192,8 @@ static void
 identity_screen_flush_frontbuffer(struct pipe_screen *_screen,
                                   struct pipe_resource *_resource,
                                   unsigned level, unsigned layer,
-                                  void *context_private)
+                                  void *context_private,
+                                  struct pipe_box *sub_box)
 {
    struct identity_screen *id_screen = identity_screen(_screen);
    struct identity_resource *id_resource = identity_resource(_resource);
@@ -202,7 +203,7 @@ identity_screen_flush_frontbuffer(struct pipe_screen *_screen,
    screen->flush_frontbuffer(screen,
                              resource,
                              level, layer,
-                             context_private);
+                             context_private, sub_box);
 }
 
 static void
diff --git a/src/gallium/drivers/llvmpipe/lp_screen.c b/src/gallium/drivers/llvmpipe/lp_screen.c
index f61df98..3501387 100644
--- a/src/gallium/drivers/llvmpipe/lp_screen.c
+++ b/src/gallium/drivers/llvmpipe/lp_screen.c
@@ -404,7 +404,8 @@ static void
 llvmpipe_flush_frontbuffer(struct pipe_screen *_screen,
                            struct pipe_resource *resource,
                            unsigned level, unsigned layer,
-                           void *context_private)
+                           void *context_private,
+                           struct pipe_box *sub_box)
 {
    struct llvmpipe_screen *screen = llvmpipe_screen(_screen);
    struct sw_winsys *winsys = screen->winsys;
@@ -412,10 +413,9 @@ llvmpipe_flush_frontbuffer(struct pipe_screen *_screen,
 
    assert(texture->dt);
    if (texture->dt)
-      winsys->displaytarget_display(winsys, texture->dt, context_private);
+      winsys->displaytarget_display(winsys, texture->dt, context_private, sub_box);
 }
 
-
 static void
 llvmpipe_destroy_screen( struct pipe_screen *_screen )
 {
diff --git a/src/gallium/drivers/noop/noop_pipe.c b/src/gallium/drivers/noop/noop_pipe.c
index 889e95e..27197a5 100644
--- a/src/gallium/drivers/noop/noop_pipe.c
+++ b/src/gallium/drivers/noop/noop_pipe.c
@@ -296,7 +296,7 @@ static struct pipe_context *noop_create_context(struct pipe_screen *screen, void
 static void noop_flush_frontbuffer(struct pipe_screen *_screen,
 				   struct pipe_resource *resource,
 				   unsigned level, unsigned layer,
-				   void *context_private)
+				   void *context_private, struct pipe_box *box)
 {
 }
 
diff --git a/src/gallium/drivers/rbug/rbug_screen.c b/src/gallium/drivers/rbug/rbug_screen.c
index 2471fdb..8576e2f 100644
--- a/src/gallium/drivers/rbug/rbug_screen.c
+++ b/src/gallium/drivers/rbug/rbug_screen.c
@@ -190,7 +190,7 @@ static void
 rbug_screen_flush_frontbuffer(struct pipe_screen *_screen,
                               struct pipe_resource *_resource,
                               unsigned level, unsigned layer,
-                              void *context_private)
+                              void *context_private, struct pipe_box *sub_box)
 {
    struct rbug_screen *rb_screen = rbug_screen(_screen);
    struct rbug_resource *rb_resource = rbug_resource(_resource);
@@ -200,7 +200,7 @@ rbug_screen_flush_frontbuffer(struct pipe_screen *_screen,
    screen->flush_frontbuffer(screen,
                              resource,
                              level, layer,
-                             context_private);
+                             context_private, sub_box);
 }
 
 static void
diff --git a/src/gallium/drivers/softpipe/sp_screen.c b/src/gallium/drivers/softpipe/sp_screen.c
index 47ef20e..358b552 100644
--- a/src/gallium/drivers/softpipe/sp_screen.c
+++ b/src/gallium/drivers/softpipe/sp_screen.c
@@ -366,7 +366,8 @@ static void
 softpipe_flush_frontbuffer(struct pipe_screen *_screen,
                            struct pipe_resource *resource,
                            unsigned level, unsigned layer,
-                           void *context_private)
+                           void *context_private,
+                           struct pipe_box *sub_box)
 {
    struct softpipe_screen *screen = softpipe_screen(_screen);
    struct sw_winsys *winsys = screen->winsys;
@@ -374,7 +375,7 @@ softpipe_flush_frontbuffer(struct pipe_screen *_screen,
 
    assert(texture->dt);
    if (texture->dt)
-      winsys->displaytarget_display(winsys, texture->dt, context_private);
+      winsys->displaytarget_display(winsys, texture->dt, context_private, sub_box);
 }
 
 static uint64_t
diff --git a/src/gallium/drivers/trace/tr_screen.c b/src/gallium/drivers/trace/tr_screen.c
index 5281ba8..b71ebbe 100644
--- a/src/gallium/drivers/trace/tr_screen.c
+++ b/src/gallium/drivers/trace/tr_screen.c
@@ -210,7 +210,8 @@ static void
 trace_screen_flush_frontbuffer(struct pipe_screen *_screen,
                                struct pipe_resource *_resource,
                                unsigned level, unsigned layer,
-                               void *context_private)
+                               void *context_private,
+                               struct pipe_box *sub_box)
 {
    struct trace_screen *tr_scr = trace_screen(_screen);
    struct trace_resource *tr_res = trace_resource(_resource);
@@ -227,7 +228,7 @@ trace_screen_flush_frontbuffer(struct pipe_screen *_screen,
    trace_dump_arg(ptr, context_private);
    */
 
-   screen->flush_frontbuffer(screen, resource, level, layer, context_private);
+   screen->flush_frontbuffer(screen, resource, level, layer, context_private, sub_box);
 
    trace_dump_call_end();
 }
diff --git a/src/gallium/include/pipe/p_screen.h b/src/gallium/include/pipe/p_screen.h
index 3ed7f26..bdd727d 100644
--- a/src/gallium/include/pipe/p_screen.h
+++ b/src/gallium/include/pipe/p_screen.h
@@ -56,6 +56,7 @@ struct pipe_fence_handle;
 struct pipe_resource;
 struct pipe_surface;
 struct pipe_transfer;
+struct pipe_box;
 
 
 /**
@@ -181,13 +182,13 @@ struct pipe_screen {
     * displayed, eg copy fake frontbuffer.
     * \param winsys_drawable_handle  an opaque handle that the calling context
     *                                gets out-of-band
+    * \param subbox an optional sub region to flush
     */
    void (*flush_frontbuffer)( struct pipe_screen *screen,
                               struct pipe_resource *resource,
                               unsigned level, unsigned layer,
-                              void *winsys_drawable_handle );
-
-
+                              void *winsys_drawable_handle,
+                              struct pipe_box *subbox );
 
    /** 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..d08ddd6 100644
--- a/src/gallium/include/state_tracker/sw_winsys.h
+++ b/src/gallium/include/state_tracker/sw_winsys.h
@@ -48,7 +48,7 @@ struct winsys_handle;
 struct pipe_screen;
 struct pipe_context;
 struct pipe_resource;
-
+struct pipe_box;
 
 /**
  * Opaque pointer.
@@ -129,7 +129,8 @@ struct sw_winsys
    void
    (*displaytarget_display)( struct sw_winsys *ws, 
                              struct sw_displaytarget *dt,
-                             void *context_private );
+                             void *context_private,
+                             struct pipe_box *box );
 
    void 
    (*displaytarget_destroy)( struct sw_winsys *ws, 
diff --git a/src/gallium/state_trackers/dri/sw/drisw.c b/src/gallium/state_trackers/dri/sw/drisw.c
index 9f00a53..64a64af 100644
--- a/src/gallium/state_trackers/dri/sw/drisw.c
+++ b/src/gallium/state_trackers/dri/sw/drisw.c
@@ -37,6 +37,7 @@
 #include "util/u_format.h"
 #include "util/u_memory.h"
 #include "util/u_inlines.h"
+#include "util/u_box.h"
 #include "pipe/p_context.h"
 #include "state_tracker/drisw_api.h"
 #include "state_tracker/st_context.h"
@@ -71,6 +72,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,9 +112,19 @@ 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)
+                      struct pipe_resource *ptex, struct pipe_box *sub_box)
 {
    struct dri_drawable *drawable = dri_drawable(dPriv);
    struct dri_screen *screen = dri_screen(drawable->sPriv);
@@ -109,7 +132,7 @@ drisw_present_texture(__DRIdrawable *dPriv,
    if (swrast_no_present)
       return;
 
-   screen->base.screen->flush_frontbuffer(screen->base.screen, ptex, 0, 0, drawable);
+   screen->base.screen->flush_frontbuffer(screen->base.screen, ptex, 0, 0, drawable, sub_box);
 }
 
 static INLINE void
@@ -126,7 +149,7 @@ static INLINE void
 drisw_copy_to_front(__DRIdrawable * dPriv,
                     struct pipe_resource *ptex)
 {
-   drisw_present_texture(dPriv, ptex);
+   drisw_present_texture(dPriv, ptex, NULL);
 
    drisw_invalidate_drawable(dPriv);
 }
@@ -158,6 +181,30 @@ 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;
+   struct pipe_box box;
+   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);
+
+      u_box_2d(x, dPriv->h - y - h, w, h, &box);
+      drisw_present_texture(dPriv, ptex, &box);
+   }
+}
+
+static void
 drisw_flush_frontbuffer(struct dri_context *ctx,
                         struct dri_drawable *drawable,
                         enum st_attachment_type statt)
@@ -288,7 +335,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 +407,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/state_trackers/egl/common/native_helper.c b/src/gallium/state_trackers/egl/common/native_helper.c
index b578a8a..5c2be19 100644
--- a/src/gallium/state_trackers/egl/common/native_helper.c
+++ b/src/gallium/state_trackers/egl/common/native_helper.c
@@ -244,7 +244,7 @@ resource_surface_present(struct resource_surface *rsurf,
       return TRUE;
 
    rsurf->screen->flush_frontbuffer(rsurf->screen,
-         pres, 0, 0, winsys_drawable_handle);
+         pres, 0, 0, winsys_drawable_handle, NULL);
 
    return TRUE;
 }
diff --git a/src/gallium/state_trackers/egl/x11/native_ximage.c b/src/gallium/state_trackers/egl/x11/native_ximage.c
index 28c6442..019e535 100644
--- a/src/gallium/state_trackers/egl/x11/native_ximage.c
+++ b/src/gallium/state_trackers/egl/x11/native_ximage.c
@@ -476,7 +476,7 @@ ximage_display_copy_to_pixmap(struct native_display *ndpy,
       xdraw.drawable = (Drawable) pix;
 
       xdpy->base.screen->flush_frontbuffer(xdpy->base.screen,
-            src, 0, 0, &xdraw);
+            src, 0, 0, &xdraw, NULL);
 
       return TRUE;
    }
diff --git a/src/gallium/state_trackers/glx/xlib/xm_st.c b/src/gallium/state_trackers/glx/xlib/xm_st.c
index fb69998..7f73a3a 100644
--- a/src/gallium/state_trackers/glx/xlib/xm_st.c
+++ b/src/gallium/state_trackers/glx/xlib/xm_st.c
@@ -74,7 +74,7 @@ xmesa_st_framebuffer_display(struct st_framebuffer_iface *stfbi,
       pres = xstfb->display_resource;
    }
 
-   xstfb->screen->flush_frontbuffer(xstfb->screen, pres, 0, 0, &xstfb->buffer->ws);
+   xstfb->screen->flush_frontbuffer(xstfb->screen, pres, 0, 0, &xstfb->buffer->ws, NULL);
    return TRUE;
 }
 
diff --git a/src/gallium/state_trackers/vdpau/presentation.c b/src/gallium/state_trackers/vdpau/presentation.c
index 81e0328..b574ddd 100644
--- a/src/gallium/state_trackers/vdpau/presentation.c
+++ b/src/gallium/state_trackers/vdpau/presentation.c
@@ -269,7 +269,7 @@ vlVdpPresentationQueueDisplay(VdpPresentationQueue presentation_queue,
    pipe->screen->flush_frontbuffer
    (
       pipe->screen, tex, 0, 0,
-      vl_screen_get_private(pq->device->vscreen)
+      vl_screen_get_private(pq->device->vscreen), NULL
    );
 
    pipe->screen->fence_reference(pipe->screen, &surf->fence, NULL);
diff --git a/src/gallium/state_trackers/xvmc/surface.c b/src/gallium/state_trackers/xvmc/surface.c
index 13f337c..f6876be 100644
--- a/src/gallium/state_trackers/xvmc/surface.c
+++ b/src/gallium/state_trackers/xvmc/surface.c
@@ -447,7 +447,7 @@ Status XvMCPutSurface(Display *dpy, XvMCSurface *surface, Drawable drawable,
    pipe->screen->flush_frontbuffer
    (
       pipe->screen, tex, 0, 0,
-      vl_screen_get_private(context_priv->vscreen)
+      vl_screen_get_private(context_priv->vscreen), NULL
    );
 
    if(dump_window == -1) {
diff --git a/src/gallium/targets/haiku-softpipe/GalliumContext.cpp b/src/gallium/targets/haiku-softpipe/GalliumContext.cpp
index b750f65..1078cb7 100644
--- a/src/gallium/targets/haiku-softpipe/GalliumContext.cpp
+++ b/src/gallium/targets/haiku-softpipe/GalliumContext.cpp
@@ -504,14 +504,14 @@ GalliumContext::SwapBuffers(context_id contextID)
 		// We pass our destination bitmap to flush_fronbuffer which passes it
 		// to the private winsys display call.
 		fScreen->flush_frontbuffer(fScreen, surface->texture, 0, 0,
-			context->bitmap);
+			context->bitmap, NULL);
 	}
 
 	#if 0
 	// TODO... should we flush the z stencil buffer?
 	pipe_surface* zSurface = stContext->state.framebuffer.zsbuf;
 	fScreen->flush_frontbuffer(fScreen, zSurface->texture, 0, 0,
-		context->bitmap);
+		context->bitmap, NULL);
 	#endif
 
 	return B_OK;
diff --git a/src/gallium/tests/graw/clear.c b/src/gallium/tests/graw/clear.c
index 77c59db..f38da47 100644
--- a/src/gallium/tests/graw/clear.c
+++ b/src/gallium/tests/graw/clear.c
@@ -33,7 +33,7 @@ static void draw( void )
 
    graw_save_surface_to_file(ctx, surf, NULL);
 
-   screen->flush_frontbuffer(screen, tex, 0, 0, window);
+   screen->flush_frontbuffer(screen, tex, 0, 0, window, NULL);
 }
 
 static void init( void )
diff --git a/src/gallium/tests/graw/fs-test.c b/src/gallium/tests/graw/fs-test.c
index 4d38e08..0560e31 100644
--- a/src/gallium/tests/graw/fs-test.c
+++ b/src/gallium/tests/graw/fs-test.c
@@ -240,7 +240,7 @@ static void draw( void )
 
    graw_save_surface_to_file(ctx, surf, NULL);
 
-   screen->flush_frontbuffer(screen, rttex, 0, 0, window);
+   screen->flush_frontbuffer(screen, rttex, 0, 0, window, NULL);
 }
 
 #define SIZE 16
diff --git a/src/gallium/tests/graw/graw_util.h b/src/gallium/tests/graw/graw_util.h
index 8557285..1856f0d 100644
--- a/src/gallium/tests/graw/graw_util.h
+++ b/src/gallium/tests/graw/graw_util.h
@@ -211,7 +211,7 @@ static INLINE void
 graw_util_flush_front(const struct graw_info *info)
 {
    info->screen->flush_frontbuffer(info->screen, info->color_buf[0],
-                                   0, 0, info->window);
+                                   0, 0, info->window, NULL);
 }
 
 
diff --git a/src/gallium/tests/graw/gs-test.c b/src/gallium/tests/graw/gs-test.c
index 3ada18a..879bf3e 100644
--- a/src/gallium/tests/graw/gs-test.c
+++ b/src/gallium/tests/graw/gs-test.c
@@ -347,7 +347,7 @@ static void draw( void )
 
    graw_save_surface_to_file(ctx, surf, NULL);
 
-   screen->flush_frontbuffer(screen, rttex, 0, 0, window);
+   screen->flush_frontbuffer(screen, rttex, 0, 0, window, NULL);
 }
 
 #define SIZE 16
diff --git a/src/gallium/tests/graw/quad-sample.c b/src/gallium/tests/graw/quad-sample.c
index b4a29e1..2e248a8 100644
--- a/src/gallium/tests/graw/quad-sample.c
+++ b/src/gallium/tests/graw/quad-sample.c
@@ -156,7 +156,7 @@ static void draw( void )
 
    graw_save_surface_to_file(ctx, surf, NULL);
 
-   screen->flush_frontbuffer(screen, rttex, 0, 0, window);
+   screen->flush_frontbuffer(screen, rttex, 0, 0, window, NULL);
 }
 
 #define SIZE 16
diff --git a/src/gallium/tests/graw/shader-leak.c b/src/gallium/tests/graw/shader-leak.c
index 4ef752b..754ada6 100644
--- a/src/gallium/tests/graw/shader-leak.c
+++ b/src/gallium/tests/graw/shader-leak.c
@@ -158,7 +158,7 @@ static void draw( void )
       ctx->delete_fs_state(ctx, fs);
    }
 
-   screen->flush_frontbuffer(screen, tex, 0, 0, window);
+   screen->flush_frontbuffer(screen, tex, 0, 0, window, NULL);
    ctx->destroy(ctx);
 
    exit(0);
diff --git a/src/gallium/tests/graw/tri-gs.c b/src/gallium/tests/graw/tri-gs.c
index 37323aa..24de12b 100644
--- a/src/gallium/tests/graw/tri-gs.c
+++ b/src/gallium/tests/graw/tri-gs.c
@@ -168,7 +168,7 @@ static void draw( void )
    util_draw_arrays(ctx, PIPE_PRIM_TRIANGLES, 0, 3);
    ctx->flush(ctx, NULL, 0);
 
-   screen->flush_frontbuffer(screen, tex, 0, 0, window);
+   screen->flush_frontbuffer(screen, tex, 0, 0, window, NULL);
 }
 
 
diff --git a/src/gallium/tests/graw/tri-instanced.c b/src/gallium/tests/graw/tri-instanced.c
index f84463d..55bc3a5 100644
--- a/src/gallium/tests/graw/tri-instanced.c
+++ b/src/gallium/tests/graw/tri-instanced.c
@@ -219,7 +219,7 @@ static void draw( void )
 
    graw_save_surface_to_file(ctx, surf, NULL);
 
-   screen->flush_frontbuffer(screen, tex, 0, 0, window);
+   screen->flush_frontbuffer(screen, tex, 0, 0, window, NULL);
 }
 
 
diff --git a/src/gallium/tests/graw/vs-test.c b/src/gallium/tests/graw/vs-test.c
index f7d4d73..0e9fc53 100644
--- a/src/gallium/tests/graw/vs-test.c
+++ b/src/gallium/tests/graw/vs-test.c
@@ -234,7 +234,7 @@ static void draw( void )
 
    graw_save_surface_to_file(ctx, surf, NULL);
 
-   screen->flush_frontbuffer(screen, rttex, 0, 0, window);
+   screen->flush_frontbuffer(screen, rttex, 0, 0, window, NULL);
 }
 
 #define SIZE 16
diff --git a/src/gallium/winsys/sw/dri/dri_sw_winsys.c b/src/gallium/winsys/sw/dri/dri_sw_winsys.c
index edb3a38..cc3b4a1 100644
--- a/src/gallium/winsys/sw/dri/dri_sw_winsys.c
+++ b/src/gallium/winsys/sw/dri/dri_sw_winsys.c
@@ -166,25 +166,33 @@ dri_sw_displaytarget_get_handle(struct sw_winsys *winsys,
 static void
 dri_sw_displaytarget_display(struct sw_winsys *ws,
                              struct sw_displaytarget *dt,
-                             void *context_private)
+                             void *context_private,
+                             struct pipe_box *box)
 {
    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;
+   unsigned blsize = util_format_get_blocksize(dri_sw_dt->format);
 
    /* Set the width to 'stride / cpp'.
     *
     * PutImage correctly clips to the width of the dst drawable.
     */
-   width = dri_sw_dt->stride / util_format_get_blocksize(dri_sw_dt->format);
+   width = dri_sw_dt->stride / blsize;
 
    height = dri_sw_dt->height;
 
-   dri_sw_ws->lf->put_image(dri_drawable, dri_sw_dt->data, width, height);
+   if (box) {
+       void *data;
+       data = dri_sw_dt->data + (dri_sw_dt->stride * box->y) + box->x * blsize;
+       dri_sw_ws->lf->put_image2(dri_drawable, data,
+                                 box->x, box->y, box->width, box->height, dri_sw_dt->stride);
+   } else {
+       dri_sw_ws->lf->put_image(dri_drawable, dri_sw_dt->data, width, height);
+   }
 }
 
-
 static void
 dri_destroy_sw_winsys(struct sw_winsys *winsys)
 {
@@ -216,7 +224,6 @@ 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;
-
    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



More information about the mesa-dev mailing list