summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2013-12-13 14:36:15 +1000
committerDave Airlie <airlied@redhat.com>2013-12-13 14:36:15 +1000
commitddf49f2d51bb65038396d28afb00170a6cead15c (patch)
tree12842b919c620717db9373fb76c6b2c61545c263
parent08bc8bfdebefcb261c2aab48c9ffe8014d472d8a (diff)
downloadmesa-ddf49f2d51bb65038396d28afb00170a6cead15c.tar.gz
mesa-ddf49f2d51bb65038396d28afb00170a6cead15c.tar.xz
mesa-ddf49f2d51bb65038396d28afb00170a6cead15c.zip
add software driver copy_sub_buffer support from upstream
-rw-r--r--0001-st-mesa-handle-texture_from_pixmap-and-other-surface.patch224
-rw-r--r--0001-swrast-gallium-classic-add-MESA_copy_sub_buffer-supp.patch1038
-rw-r--r--mesa.spec10
3 files changed, 1047 insertions, 225 deletions
diff --git a/0001-st-mesa-handle-texture_from_pixmap-and-other-surface.patch b/0001-st-mesa-handle-texture_from_pixmap-and-other-surface.patch
deleted file mode 100644
index 837f366..0000000
--- a/0001-st-mesa-handle-texture_from_pixmap-and-other-surface.patch
+++ /dev/null
@@ -1,224 +0,0 @@
-From 430343da5988f53ee6eedffb55ab38fa7cf64fd5 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Marek=20Ol=C5=A1=C3=A1k?= <maraeo@gmail.com>
-Date: Fri, 10 May 2013 03:42:23 +0200
-Subject: [PATCH] st/mesa: handle texture_from_pixmap and other surface-based
- textures correctly
-
-There were 2 issues with it:
-1) The texture format which should be used for texturing was only set
- in gl_texture_image::TexFormat, which wasn't used for sampler views.
-2) Textures are sometimes reallocated under some circumstances
- in st_finalize_texture, which is unacceptable if the texture comes
- from a window system.
-
-The issues are resolved as follows:
-1) If surface_based is true (texture_from_pixmap, etc.), store the format
- in a new variable st_texture_object::surface_format.
-2) Don't reallocate a surface-based texture in st_finalize_texture.
-
-Also don't use st_ChooseTextureFormat is st_context_teximage, because
-the format is dictated by the caller.
-
-This fixes the glx-tfp piglit test.
----
- src/mesa/state_tracker/st_atom_texture.c | 3 ++-
- src/mesa/state_tracker/st_cb_eglimage.c | 1 +
- src/mesa/state_tracker/st_cb_texture.c | 7 ++++++-
- src/mesa/state_tracker/st_format.c | 35 --------------------------------
- src/mesa/state_tracker/st_format.h | 4 ----
- src/mesa/state_tracker/st_manager.c | 25 +++++------------------
- src/mesa/state_tracker/st_texture.h | 10 +++++++--
- 7 files changed, 22 insertions(+), 63 deletions(-)
-
-diff --git a/src/mesa/state_tracker/st_atom_texture.c b/src/mesa/state_tracker/st_atom_texture.c
-index 8d1250f..d79e04c 100644
---- a/src/mesa/state_tracker/st_atom_texture.c
-+++ b/src/mesa/state_tracker/st_atom_texture.c
-@@ -239,7 +239,8 @@ update_single_texture(struct st_context *st,
- st_mesa_format_to_pipe_format(stObj->base._BufferObjectFormat);
- }
- else {
-- view_format = stObj->pt->format;
-+ view_format =
-+ stObj->surface_based ? stObj->surface_format : stObj->pt->format;
-
- /* If sRGB decoding is off, use the linear format */
- if (samp->sRGBDecode == GL_SKIP_DECODE_EXT) {
-diff --git a/src/mesa/state_tracker/st_cb_eglimage.c b/src/mesa/state_tracker/st_cb_eglimage.c
-index b162870..a396b9e 100644
---- a/src/mesa/state_tracker/st_cb_eglimage.c
-+++ b/src/mesa/state_tracker/st_cb_eglimage.c
-@@ -131,6 +131,7 @@ st_bind_surface(struct gl_context *ctx, GLenum target,
- stObj->width0 = ps->width;
- stObj->height0 = ps->height;
- stObj->depth0 = 1;
-+ stObj->surface_format = ps->format;
-
- _mesa_dirty_texobj(ctx, texObj, GL_TRUE);
- }
-diff --git a/src/mesa/state_tracker/st_cb_texture.c b/src/mesa/state_tracker/st_cb_texture.c
-index 123ed2b..56dbe85 100644
---- a/src/mesa/state_tracker/st_cb_texture.c
-+++ b/src/mesa/state_tracker/st_cb_texture.c
-@@ -1540,6 +1540,11 @@ st_finalize_texture(struct gl_context *ctx,
- pipe_sampler_view_release(st->pipe, &stObj->sampler_view);
- }
-
-+ /* If this texture comes from a window system, there is nothing else to do. */
-+ if (stObj->surface_based) {
-+ return GL_TRUE;
-+ }
-+
- /* Find gallium format for the Mesa texture */
- firstImageFormat = st_mesa_format_to_pipe_format(firstImage->base.TexFormat);
-
-@@ -1567,7 +1572,7 @@ st_finalize_texture(struct gl_context *ctx,
- */
- if (stObj->pt) {
- if (stObj->pt->target != gl_target_to_pipe(stObj->base.Target) ||
-- !st_sampler_compat_formats(stObj->pt->format, firstImageFormat) ||
-+ stObj->pt->format != firstImageFormat ||
- stObj->pt->last_level < stObj->lastLevel ||
- stObj->pt->width0 != ptWidth ||
- stObj->pt->height0 != ptHeight ||
-diff --git a/src/mesa/state_tracker/st_format.c b/src/mesa/state_tracker/st_format.c
-index c9c6163..56f3a4a 100644
---- a/src/mesa/state_tracker/st_format.c
-+++ b/src/mesa/state_tracker/st_format.c
-@@ -1800,41 +1800,6 @@ st_QuerySamplesForFormat(struct gl_context *ctx, GLenum target,
- }
-
-
--GLboolean
--st_sampler_compat_formats(enum pipe_format format1, enum pipe_format format2)
--{
-- if (format1 == format2)
-- return GL_TRUE;
--
-- if (format1 == PIPE_FORMAT_B8G8R8A8_UNORM &&
-- format2 == PIPE_FORMAT_B8G8R8X8_UNORM)
-- return GL_TRUE;
--
-- if (format1 == PIPE_FORMAT_B8G8R8X8_UNORM &&
-- format2 == PIPE_FORMAT_B8G8R8A8_UNORM)
-- return GL_TRUE;
--
-- if (format1 == PIPE_FORMAT_A8B8G8R8_UNORM &&
-- format2 == PIPE_FORMAT_X8B8G8R8_UNORM)
-- return GL_TRUE;
--
-- if (format1 == PIPE_FORMAT_X8B8G8R8_UNORM &&
-- format2 == PIPE_FORMAT_A8B8G8R8_UNORM)
-- return GL_TRUE;
--
-- if (format1 == PIPE_FORMAT_A8R8G8B8_UNORM &&
-- format2 == PIPE_FORMAT_X8R8G8B8_UNORM)
-- return GL_TRUE;
--
-- if (format1 == PIPE_FORMAT_X8R8G8B8_UNORM &&
-- format2 == PIPE_FORMAT_A8R8G8B8_UNORM)
-- return GL_TRUE;
--
-- return GL_FALSE;
--}
--
--
--
- /**
- * This is used for translating texture border color and the clear
- * color. For example, the clear color is interpreted according to
-diff --git a/src/mesa/state_tracker/st_format.h b/src/mesa/state_tracker/st_format.h
-index 0a1c18d..6e97dcb 100644
---- a/src/mesa/state_tracker/st_format.h
-+++ b/src/mesa/state_tracker/st_format.h
-@@ -70,10 +70,6 @@ size_t
- st_QuerySamplesForFormat(struct gl_context *ctx, GLenum target,
- GLenum internalFormat, int samples[16]);
-
--/* can we use a sampler view to translate these formats
-- only used to make TFP so far */
--extern GLboolean
--st_sampler_compat_formats(enum pipe_format format1, enum pipe_format format2);
-
-
- extern void
-diff --git a/src/mesa/state_tracker/st_manager.c b/src/mesa/state_tracker/st_manager.c
-index 5561af6..9e537f3 100644
---- a/src/mesa/state_tracker/st_manager.c
-+++ b/src/mesa/state_tracker/st_manager.c
-@@ -467,7 +467,7 @@ st_context_flush(struct st_context_iface *stctxi, unsigned flags,
- static boolean
- st_context_teximage(struct st_context_iface *stctxi,
- enum st_texture_type tex_type,
-- int level, enum pipe_format internal_format,
-+ int level, enum pipe_format pipe_format,
- struct pipe_resource *tex, boolean mipmap)
- {
- struct st_context *st = (struct st_context *) stctxi;
-@@ -511,29 +511,13 @@ st_context_teximage(struct st_context_iface *stctxi,
- texImage = _mesa_get_tex_image(ctx, texObj, target, level);
- stImage = st_texture_image(texImage);
- if (tex) {
-- gl_format texFormat;
--
-- /*
-- * XXX When internal_format and tex->format differ, st_finalize_texture
-- * needs to allocate a new texture with internal_format and copy the
-- * texture here into the new one. It will result in surface_copy being
-- * called on surfaces whose formats differ.
-- *
-- * To avoid that, internal_format is (wrongly) ignored here. A sane fix
-- * is to use a sampler view.
-- */
-- if (!st_sampler_compat_formats(tex->format, internal_format))
-- internal_format = tex->format;
--
-- if (util_format_get_component_bits(internal_format,
-- UTIL_FORMAT_COLORSPACE_RGB, 3) > 0)
-+ gl_format texFormat = st_pipe_format_to_mesa_format(pipe_format);
-+
-+ if (util_format_has_alpha(tex->format))
- internalFormat = GL_RGBA;
- else
- internalFormat = GL_RGB;
-
-- texFormat = st_ChooseTextureFormat(ctx, target, internalFormat,
-- GL_BGRA, GL_UNSIGNED_BYTE);
--
- _mesa_init_teximage_fields(ctx, texImage,
- tex->width0, tex->height0, 1, 0,
- internalFormat, texFormat);
-@@ -562,6 +546,7 @@ st_context_teximage(struct st_context_iface *stctxi,
- stObj->width0 = width;
- stObj->height0 = height;
- stObj->depth0 = depth;
-+ stObj->surface_format = pipe_format;
-
- _mesa_dirty_texobj(ctx, texObj, GL_TRUE);
- _mesa_unlock_texture(ctx, texObj);
-diff --git a/src/mesa/state_tracker/st_texture.h b/src/mesa/state_tracker/st_texture.h
-index da899c9..c15aeae 100644
---- a/src/mesa/state_tracker/st_texture.h
-+++ b/src/mesa/state_tracker/st_texture.h
-@@ -87,10 +87,16 @@ struct st_texture_object
- */
- struct pipe_sampler_view *sampler_view;
-
-- /* True if there is/was a surface bound to this texture object. It helps
-- * track whether the texture object is surface based or not.
-+ /* True if this texture comes from the window system. Such a texture
-+ * cannot be reallocated and the format can only be changed with a sampler
-+ * view or a surface.
- */
- GLboolean surface_based;
-+
-+ /* If surface_based is true, this format should be used for all sampler
-+ * views and surfaces instead of pt->format.
-+ */
-+ enum pipe_format surface_format;
- };
-
-
---
-1.8.2.1
-
diff --git a/0001-swrast-gallium-classic-add-MESA_copy_sub_buffer-supp.patch b/0001-swrast-gallium-classic-add-MESA_copy_sub_buffer-supp.patch
new file mode 100644
index 0000000..c1fdcb2
--- /dev/null
+++ b/0001-swrast-gallium-classic-add-MESA_copy_sub_buffer-supp.patch
@@ -0,0 +1,1038 @@
+From ba00f2f6f54cbc5ffdb0f0b94bcd672d147cdc36 Mon Sep 17 00:00:00 2001
+From: Dave Airlie <airlied@gmail.com>
+Date: Thu, 28 Nov 2013 11:08:11 +1000
+Subject: [PATCH] swrast* (gallium, classic): add MESA_copy_sub_buffer support
+ (v3)
+
+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.
+
+v3: finish off winsys interfaces, add swrast classic support as well.
+
+Reviewed-by: Jose Fonseca <jfonseca@vmware.com>
+Signed-off-by: Dave Airlie <airlied@redhat.com>
+
+swrast: add support for copy_sub_buffer
+---
+ 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 +-
+ .../winsys/sw/android/android_sw_winsys.cpp | 3 +-
+ src/gallium/winsys/sw/dri/dri_sw_winsys.c | 16 ++++--
+ src/gallium/winsys/sw/fbdev/fbdev_sw_winsys.c | 3 +-
+ src/gallium/winsys/sw/gdi/gdi_sw_winsys.c | 3 +-
+ src/gallium/winsys/sw/hgl/hgl_sw_winsys.c | 3 +-
+ src/gallium/winsys/sw/null/null_sw_winsys.c | 3 +-
+ src/gallium/winsys/sw/wayland/wayland_sw_winsys.c | 3 +-
+ src/gallium/winsys/sw/xlib/xlib_sw_winsys.c | 3 +-
+ src/glx/drisw_glx.c | 43 ++++++++++++++--
+ src/mesa/drivers/dri/common/dri_util.c | 15 ++++++
+ src/mesa/drivers/dri/common/dri_util.h | 5 +-
+ src/mesa/drivers/dri/swrast/swrast.c | 35 +++++++++++++
+ 41 files changed, 227 insertions(+), 59 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 abb9796..8b29fc2 100644
+--- a/src/gallium/drivers/i915/i915_screen.c
++++ b/src/gallium/drivers/i915/i915_screen.c
+@@ -423,7 +423,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;
+@@ -431,6 +432,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 742e7f2..c8eb3ba 100644
+--- a/src/gallium/drivers/llvmpipe/lp_screen.c
++++ b/src/gallium/drivers/llvmpipe/lp_screen.c
+@@ -411,7 +411,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;
+@@ -419,10 +420,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 0c8c94d..69cb09f 100644
+--- a/src/gallium/drivers/softpipe/sp_screen.c
++++ b/src/gallium/drivers/softpipe/sp_screen.c
+@@ -369,7 +369,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;
+@@ -377,7 +378,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 c6745af..debd031 100644
+--- a/src/gallium/drivers/trace/tr_screen.c
++++ b/src/gallium/drivers/trace/tr_screen.c
+@@ -209,7 +209,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);
+@@ -226,7 +227,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 d1e1acd..4a77a50 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/android/android_sw_winsys.cpp b/src/gallium/winsys/sw/android/android_sw_winsys.cpp
+index cb91aad..4b1040c 100644
+--- a/src/gallium/winsys/sw/android/android_sw_winsys.cpp
++++ b/src/gallium/winsys/sw/android/android_sw_winsys.cpp
+@@ -74,7 +74,8 @@ namespace android {
+ static void
+ android_displaytarget_display(struct sw_winsys *ws,
+ struct sw_displaytarget *dt,
+- void *context_private)
++ void *context_private,
++ struct pipe_box *box)
+ {
+ }
+
+diff --git a/src/gallium/winsys/sw/dri/dri_sw_winsys.c b/src/gallium/winsys/sw/dri/dri_sw_winsys.c
+index edb3a38..6fed22b 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)
+ {
+diff --git a/src/gallium/winsys/sw/fbdev/fbdev_sw_winsys.c b/src/gallium/winsys/sw/fbdev/fbdev_sw_winsys.c
+index a280985..cc3ce1a 100644
+--- a/src/gallium/winsys/sw/fbdev/fbdev_sw_winsys.c
++++ b/src/gallium/winsys/sw/fbdev/fbdev_sw_winsys.c
+@@ -74,7 +74,8 @@ fbdev_sw_winsys(struct sw_winsys *ws)
+ static void
+ fbdev_displaytarget_display(struct sw_winsys *ws,
+ struct sw_displaytarget *dt,
+- void *winsys_private)
++ void *winsys_private,
++ struct pipe_box *box)
+ {
+ struct fbdev_sw_winsys *fbdev = fbdev_sw_winsys(ws);
+ struct fbdev_sw_displaytarget *src = fbdev_sw_displaytarget(dt);
+diff --git a/src/gallium/winsys/sw/gdi/gdi_sw_winsys.c b/src/gallium/winsys/sw/gdi/gdi_sw_winsys.c
+index 2e12f6e..aae3ec5 100644
+--- a/src/gallium/winsys/sw/gdi/gdi_sw_winsys.c
++++ b/src/gallium/winsys/sw/gdi/gdi_sw_winsys.c
+@@ -207,7 +207,8 @@ gdi_sw_display( struct sw_winsys *winsys,
+ static void
+ gdi_sw_displaytarget_display(struct sw_winsys *winsys,
+ struct sw_displaytarget *dt,
+- void *context_private)
++ void *context_private,
++ struct pipe_box *box)
+ {
+ /* nasty:
+ */
+diff --git a/src/gallium/winsys/sw/hgl/hgl_sw_winsys.c b/src/gallium/winsys/sw/hgl/hgl_sw_winsys.c
+index b09584c..27eca2b 100644
+--- a/src/gallium/winsys/sw/hgl/hgl_sw_winsys.c
++++ b/src/gallium/winsys/sw/hgl/hgl_sw_winsys.c
+@@ -160,7 +160,8 @@ hgl_winsys_displaytarget_unmap(struct sw_winsys* winsys,
+
+ static void
+ hgl_winsys_displaytarget_display(struct sw_winsys* winsys,
+- struct sw_displaytarget* displayTarget, void* contextPrivate)
++ struct sw_displaytarget* displayTarget, void* contextPrivate,
++ struct pipe_box *box)
+ {
+ assert(contextPrivate);
+
+diff --git a/src/gallium/winsys/sw/null/null_sw_winsys.c b/src/gallium/winsys/sw/null/null_sw_winsys.c
+index 44849da..9c8b3ec 100644
+--- a/src/gallium/winsys/sw/null/null_sw_winsys.c
++++ b/src/gallium/winsys/sw/null/null_sw_winsys.c
+@@ -114,7 +114,8 @@ null_sw_displaytarget_get_handle(struct sw_winsys *winsys,
+ static void
+ null_sw_displaytarget_display(struct sw_winsys *winsys,
+ struct sw_displaytarget *dt,
+- void *context_private)
++ void *context_private,
++ struct pipe_box *box)
+ {
+ assert(0);
+ }
+diff --git a/src/gallium/winsys/sw/wayland/wayland_sw_winsys.c b/src/gallium/winsys/sw/wayland/wayland_sw_winsys.c
+index f432de9..e428613 100644
+--- a/src/gallium/winsys/sw/wayland/wayland_sw_winsys.c
++++ b/src/gallium/winsys/sw/wayland/wayland_sw_winsys.c
+@@ -75,7 +75,8 @@ wayland_sw_winsys(struct sw_winsys *ws)
+ static void
+ wayland_displaytarget_display(struct sw_winsys *ws,
+ struct sw_displaytarget *dt,
+- void *context_private)
++ void *context_private,
++ struct pipe_box *box)
+ {
+ }
+
+diff --git a/src/gallium/winsys/sw/xlib/xlib_sw_winsys.c b/src/gallium/winsys/sw/xlib/xlib_sw_winsys.c
+index 6e71530..99da2ae 100644
+--- a/src/gallium/winsys/sw/xlib/xlib_sw_winsys.c
++++ b/src/gallium/winsys/sw/xlib/xlib_sw_winsys.c
+@@ -376,7 +376,8 @@ xlib_sw_display(struct xlib_drawable *xlib_drawable,
+ static void
+ xlib_displaytarget_display(struct sw_winsys *ws,
+ struct sw_displaytarget *dt,
+- void *context_private)
++ void *context_private,
++ struct pipe_box *box)
+ {
+ struct xlib_drawable *xlib_drawable = (struct xlib_drawable *)context_private;
+ xlib_sw_display(xlib_drawable, dt);
+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;
+diff --git a/src/mesa/drivers/dri/swrast/swrast.c b/src/mesa/drivers/dri/swrast/swrast.c
+index 0e1c530..7eed5a4 100644
+--- a/src/mesa/drivers/dri/swrast/swrast.c
++++ b/src/mesa/drivers/dri/swrast/swrast.c
+@@ -820,6 +820,39 @@ dri_unbind_context(__DRIcontext * cPriv)
+ return GL_TRUE;
+ }
+
++static void
++dri_copy_sub_buffer(__DRIdrawable *dPriv, int x, int y,
++ int w, int h)
++{
++ __DRIscreen *sPriv = dPriv->driScreenPriv;
++ void *data;
++ int iy;
++ struct dri_drawable *drawable = dri_drawable(dPriv);
++ struct gl_framebuffer *fb;
++ struct dri_swrast_renderbuffer *frontrb, *backrb;
++
++ TRACE;
++
++ fb = &drawable->Base;
++
++ frontrb =
++ dri_swrast_renderbuffer(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer);
++ backrb =
++ dri_swrast_renderbuffer(fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer);
++
++ /* check for signle-buffered */
++ if (backrb == NULL)
++ return;
++
++ iy = frontrb->Base.Base.Height - y - h;
++ data = (char *)backrb->Base.Buffer + (iy * backrb->pitch) + (x * ((backrb->bpp + 7) / 8));
++ sPriv->swrast_loader->putImage2(dPriv, __DRI_SWRAST_IMAGE_OP_SWAP,
++ x, iy, w, h,
++ frontrb->pitch,
++ data,
++ dPriv->loaderPrivate);
++}
++
+
+ static const struct __DriverAPIRec swrast_driver_api = {
+ .InitScreen = dri_init_screen,
+@@ -831,6 +864,7 @@ static const struct __DriverAPIRec swrast_driver_api = {
+ .SwapBuffers = dri_swap_buffers,
+ .MakeCurrent = dri_make_current,
+ .UnbindContext = dri_unbind_context,
++ .CopySubBuffer = dri_copy_sub_buffer,
+ };
+
+ static const struct __DRIDriverVtableExtensionRec swrast_vtable = {
+@@ -841,6 +875,7 @@ static const struct __DRIDriverVtableExtensionRec swrast_vtable = {
+ static const __DRIextension *swrast_driver_extensions[] = {
+ &driCoreExtension.base,
+ &driSWRastExtension.base,
++ &driCopySubBufferExtension.base,
+ &swrast_vtable.base,
+ NULL
+ };
+--
+1.8.3.1
+
diff --git a/mesa.spec b/mesa.spec
index 10cd223..aecbc90 100644
--- a/mesa.spec
+++ b/mesa.spec
@@ -54,7 +54,7 @@
Summary: Mesa graphics libraries
Name: mesa
Version: 10.0
-Release: 1.%{gitdate}%{?dist}
+Release: 2.%{gitdate}%{?dist}
License: MIT
Group: System Environment/Libraries
URL: http://www.mesa3d.org
@@ -76,6 +76,9 @@ Patch12: mesa-8.0.1-fix-16bpp.patch
Patch15: mesa-9.2-hardware-float.patch
Patch20: mesa-9.2-evergreen-big-endian.patch
+# backport from upstream to allow cogl use copy_sub_buffer
+Patch30: 0001-swrast-gallium-classic-add-MESA_copy_sub_buffer-supp.patch
+
BuildRequires: pkgconfig autoconf automake libtool
%if %{with_hardware}
BuildRequires: kernel-headers
@@ -300,6 +303,8 @@ grep -q ^/ src/gallium/auxiliary/vl/vl_decoder.c && exit 1
%patch15 -p1 -b .hwfloat
%patch20 -p1 -b .egbe
+%patch30 -p1 -b .copy_sub_buffer
+
%if 0%{with_private_llvm}
sed -i 's/llvm-config/mesa-private-llvm-config-%{__isa_bits}/g' configure.ac
sed -i 's/`$LLVM_CONFIG --version`/&-mesa/' configure.ac
@@ -591,6 +596,9 @@ rm -rf $RPM_BUILD_ROOT
%endif
%changelog
+* Fri Dec 13 2013 Dave Airlie <airlied@redhat.com> 10.0-2.20131206
+- add software driver copy_sub_buffer support from upstream
+
* Sun Dec 01 2013 Igor Gnatenko <i.gnatenko.brain@gmail.com> - 10.0-1.20131206
- 10.0 upstream (RHBZ 1036361)