[Mesa3d-dev] gallium: add overlapping blit support to u_blitter

2010-01-06 Thread Dave Airlie

This makes the r300g + X.org state tracker work a bit better, I can 
start X + xterm + metacity and drag a window around now at least.

A full gnome session seems to have other issuess.

Dave.From b8f1d1cf45aa23c74b2d150058506a6a27737d25 Mon Sep 17 00:00:00 2001
From: Dave Airlie airl...@redhat.com
Date: Thu, 7 Jan 2010 11:45:48 +1000
Subject: [PATCH] gallium: u_blitter add overlapping blit support.

the xorg state tracker really wants the driver to handle overlapping
blits, and r300 uses u_blitter for blits. This patch adds overlapping
blit support via a temporary surface when its required.
---
 src/gallium/auxiliary/util/u_blitter.c |  158 +---
 1 files changed, 124 insertions(+), 34 deletions(-)

diff --git a/src/gallium/auxiliary/util/u_blitter.c b/src/gallium/auxiliary/util/u_blitter.c
index 1f794d3..58f0b6d 100644
--- a/src/gallium/auxiliary/util/u_blitter.c
+++ b/src/gallium/auxiliary/util/u_blitter.c
@@ -560,45 +560,30 @@ void util_blitter_clear(struct blitter_context *blitter,
blitter_restore_CSOs(ctx);
 }
 
-void util_blitter_copy(struct blitter_context *blitter,
-   struct pipe_surface *dst,
-   unsigned dstx, unsigned dsty,
-   struct pipe_surface *src,
-   unsigned srcx, unsigned srcy,
-   unsigned width, unsigned height,
-   boolean ignore_stencil)
+static boolean
+is_overlap(int sx1, int sx2, int sy1, int sy2, int dx1, int dx2, int dy1, int dy2)
+{
+if (((sx1 = dx1)  (sx1 = dx2)  (sy1 = dy1)  (sy1 = dy2)) || /* TL x1, y1 */
+	((sx2 = dx1)  (sx2 = dx2)  (sy1 = dy1)  (sy1 = dy2)) || /* TR x2, y1 */
+	((sx1 = dx1)  (sx1 = dx2)  (sy2 = dy1)  (sy2 = dy2)) || /* BL x1, y2 */
+	((sx2 = dx1)  (sx2 = dx2)  (sy2 = dy1)  (sy2 = dy2)))   /* BR x2, y2 */
+	return TRUE;
+else
+	return FALSE;
+}
+
+static void util_blitter_do_copy(struct blitter_context *blitter,
+ struct pipe_surface *dst,
+ unsigned dstx, unsigned dsty,
+ struct pipe_surface *src,
+ unsigned srcx, unsigned srcy,
+ unsigned width, unsigned height,
+ boolean is_depth)
 {
struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
struct pipe_context *pipe = ctx-pipe;
-   struct pipe_screen *screen = pipe-screen;
struct pipe_framebuffer_state fb_state;
-   boolean is_stencil, is_depth;
-   unsigned dst_tex_usage;
-
-   /* give up if textures are not set */
-   assert(dst-texture  src-texture);
-   if (!dst-texture || !src-texture)
-  return;
-
-   is_depth = util_format_get_component_bits(src-format, UTIL_FORMAT_COLORSPACE_ZS, 0) != 0;
-   is_stencil = util_format_get_component_bits(src-format, UTIL_FORMAT_COLORSPACE_ZS, 1) != 0;
-   dst_tex_usage = is_depth || is_stencil ? PIPE_TEXTURE_USAGE_DEPTH_STENCIL :
-PIPE_TEXTURE_USAGE_RENDER_TARGET;
-
-   /* check if we can sample from and render to the surfaces */
-   /* (assuming copying a stencil buffer is not possible) */
-   if ((!ignore_stencil  is_stencil) ||
-   !screen-is_format_supported(screen, dst-format, dst-texture-target,
-dst_tex_usage, 0) ||
-   !screen-is_format_supported(screen, src-format, src-texture-target,
-PIPE_TEXTURE_USAGE_SAMPLER, 0)) {
-  util_surface_copy(pipe, FALSE, dst, dstx, dsty, src, srcx, srcy,
-width, height);
-  return;
-   }
 
-   /* check whether the states are properly saved */
-   blitter_check_saved_CSOs(ctx);
assert(blitter-saved_fb_state.nr_cbufs != ~0);
assert(blitter-saved_num_textures != ~0);
assert(blitter-saved_num_sampler_states != ~0);
@@ -656,6 +641,111 @@ void util_blitter_copy(struct blitter_context *blitter,
 
blitter_set_rectangle(ctx, dstx, dsty, dstx+width, dsty+height, 0);
blitter_draw_quad(ctx);
+
+}
+
+static void util_blitter_overlap_copy(struct blitter_context *blitter,
+  struct pipe_surface *dst,
+  unsigned dstx, unsigned dsty,
+  struct pipe_surface *src,
+  unsigned srcx, unsigned srcy,
+  unsigned width, unsigned height)
+{
+   struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
+   struct pipe_context *pipe = ctx-pipe;
+   struct pipe_screen *screen = pipe-screen;
+
+   struct pipe_texture texTemp;
+   struct pipe_texture *texture;
+   struct pipe_surface *tex_surf;
+   uint level;
+
+   /* check whether the states are properly saved */
+   blitter_check_saved_CSOs(ctx);
+
+   memset(texTemp, 0, sizeof(texTemp));
+   texTemp.target = PIPE_TEXTURE_2D;
+   texTemp.format = dst-texture-format; /* XXX verify supported by driver! */
+   texTemp.last_level = 0;
+   texTemp.width0 = width;
+   texTemp.height0 = height;
+   texTemp.depth0 = 1;
+
+   texture = screen-texture_create(screen, texTemp);
+   if (!texture)
+  return;
+
+   tex_surf = screen-get_tex_surface(screen, texture, 0, 

Re: [Mesa3d-dev] gallium: add overlapping blit support to u_blitter

2010-01-06 Thread Brian Paul
On Wed, Jan 6, 2010 at 6:50 PM, Dave Airlie airl...@linux.ie wrote:

 This makes the r300g + X.org state tracker work a bit better, I can
 start X + xterm + metacity and drag a window around now at least.

 A full gnome session seems to have other issuess.

Hi Dave, a couple comments on your patch...


diff --git a/src/gallium/auxiliary/util/u_blitter.c
b/src/gallium/auxiliary/util/u_blitter.c
index 1f794d3..58f0b6d 100644
--- a/src/gallium/auxiliary/util/u_blitter.c
+++ b/src/gallium/auxiliary/util/u_blitter.c
@@ -560,10 +560,14 @@ void util_blitter_clear(struct blitter_context *blitter,
blitter_restore_CSOs(ctx);
 }

-void util_blitter_copy(struct blitter_context *blitter,
-   struct pipe_surface *dst,
-   unsigned dstx, unsigned dsty,
-   struct pipe_surface *src,
-   unsigned srcx, unsigned srcy,
-   unsigned width, unsigned height,
-   boolean ignore_stencil)
+static boolean
+is_overlap(int sx1, int sx2, int sy1, int sy2, int dx1, int dx2, int
dy1, int dy2)
+{
+if (((sx1 = dx1)  (sx1 = dx2)  (sy1 = dy1)  (sy1 =
dy2)) || /* TL x1, y1 */
+   ((sx2 = dx1)  (sx2 = dx2)  (sy1 = dy1)  (sy1 = dy2)) || /*
TR x2, y1 */
+   ((sx1 = dx1)  (sx1 = dx2)  (sy2 = dy1)  (sy2 = dy2)) || /*
BL x1, y2 */
+   ((sx2 = dx1)  (sx2 = dx2)  (sy2 = dy1)  (sy2 = dy2)))   /*
BR x2, y2 */
+   return TRUE;
+else
+   return FALSE;
+}

If we know that sx1sx2, sy1sy2, dx1dx2, dy1dy2, then I think you can do this
instead:

static boolean
is_overlap(int sx1, int sx2, int sy1, int sy2, int dx1, int dx2, int
dy1, int dy2)
{
   return !(sx2  dx1 || sx1  dx2 || sy2  dy1 || sy1  dy2);
}

And if the -1 terms are removed from the call below, the
inequalities can be changed to = and =.


+
+static void util_blitter_do_copy(struct blitter_context *blitter,
+struct pipe_surface *dst,
+unsigned dstx, unsigned dsty,
+struct pipe_surface *src,
+unsigned srcx, unsigned srcy,
+unsigned width, unsigned height,
+boolean is_depth)
 {
struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
struct pipe_context *pipe = ctx-pipe;
-   struct pipe_screen *screen = pipe-screen;
struct pipe_framebuffer_state fb_state;
-   boolean is_stencil, is_depth;
-   unsigned dst_tex_usage;
-
-   /* give up if textures are not set */
-   assert(dst-texture  src-texture);
-   if (!dst-texture || !src-texture)
-  return;
-
-   is_depth = util_format_get_component_bits(src-format,
UTIL_FORMAT_COLORSPACE_ZS, 0) != 0;
-   is_stencil = util_format_get_component_bits(src-format,
UTIL_FORMAT_COLORSPACE_ZS, 1) != 0;
-   dst_tex_usage = is_depth || is_stencil ? PIPE_TEXTURE_USAGE_DEPTH_STENCIL :
-PIPE_TEXTURE_USAGE_RENDER_TARGET;
-
-   /* check if we can sample from and render to the surfaces */
-   /* (assuming copying a stencil buffer is not possible) */
-   if ((!ignore_stencil  is_stencil) ||
-   !screen-is_format_supported(screen, dst-format, dst-texture-target,
-dst_tex_usage, 0) ||
-   !screen-is_format_supported(screen, src-format, src-texture-target,
-PIPE_TEXTURE_USAGE_SAMPLER, 0)) {
-  util_surface_copy(pipe, FALSE, dst, dstx, dsty, src, srcx, srcy,
-width, height);
-  return;
-   }

-   /* check whether the states are properly saved */
-   blitter_check_saved_CSOs(ctx);
assert(blitter-saved_fb_state.nr_cbufs != ~0);
assert(blitter-saved_num_textures != ~0);
assert(blitter-saved_num_sampler_states != ~0);
@@ -656,3 +641,79 @@ void util_blitter_copy(struct blitter_context *blitter,

blitter_set_rectangle(ctx, dstx, dsty, dstx+width, dsty+height, 0);
blitter_draw_quad(ctx);
+
+}
+
+static void util_blitter_overlap_copy(struct blitter_context *blitter,
+ struct pipe_surface *dst,
+ unsigned dstx, unsigned dsty,
+ struct pipe_surface *src,
+ unsigned srcx, unsigned srcy,
+ unsigned width, unsigned height)
+{
+   struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
+   struct pipe_context *pipe = ctx-pipe;
+   struct pipe_screen *screen = pipe-screen;
+
+   struct pipe_texture texTemp;
+   struct pipe_texture *texture;
+   struct pipe_surface *tex_surf;
+   uint level;
+
+   /* check whether the states are properly saved */
+   blitter_check_saved_CSOs(ctx);
+
+   memset(texTemp, 0, sizeof(texTemp));
+   texTemp.target = PIPE_TEXTURE_2D;
+   texTemp.format = dst-texture-format; /* XXX verify supported by driver! */
+