Mesa (master): r300g: accelerate blitting for all formats by faking the texture format

Marek Olšák mareko at kemper.freedesktop.org
Sun Feb 14 17:16:14 UTC 2010


Module: Mesa
Branch: master
Commit: f22ddd8e4743dbbfea2fac6c54837b30cbb1eb0e
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=f22ddd8e4743dbbfea2fac6c54837b30cbb1eb0e

Author: Marek Olšák <maraeo at gmail.com>
Date:   Sun Feb 14 04:57:03 2010 +0100

r300g: accelerate blitting for all formats by faking the texture format

---

 src/gallium/drivers/r300/r300_blit.c    |   74 ++++++++++++++++++++++++++++---
 src/gallium/drivers/r300/r300_texture.c |   14 ++++++
 src/gallium/drivers/r300/r300_texture.h |    4 ++
 3 files changed, 85 insertions(+), 7 deletions(-)

diff --git a/src/gallium/drivers/r300/r300_blit.c b/src/gallium/drivers/r300/r300_blit.c
index faaf952..eb9b0be 100644
--- a/src/gallium/drivers/r300/r300_blit.c
+++ b/src/gallium/drivers/r300/r300_blit.c
@@ -22,6 +22,9 @@
 
 #include "r300_blit.h"
 #include "r300_context.h"
+#include "r300_texture.h"
+
+#include "util/u_format.h"
 
 static void r300_blitter_save_states(struct r300_context* r300)
 {
@@ -86,13 +89,13 @@ void r300_clear(struct pipe_context* pipe,
                        buffers, rgba, depth, stencil);
 }
 
-/* Copy a block of pixels from one surface to another. */
-void r300_surface_copy(struct pipe_context* pipe,
-                       struct pipe_surface* dst,
-                       unsigned dstx, unsigned dsty,
-                       struct pipe_surface* src,
-                       unsigned srcx, unsigned srcy,
-                       unsigned width, unsigned height)
+/* Copy a block of pixels from one surface to another using HW. */
+static void r300_hw_copy(struct pipe_context* pipe,
+                         struct pipe_surface* dst,
+                         unsigned dstx, unsigned dsty,
+                         struct pipe_surface* src,
+                         unsigned srcx, unsigned srcy,
+                         unsigned width, unsigned height)
 {
     struct r300_context* r300 = r300_context(pipe);
 
@@ -114,6 +117,63 @@ void r300_surface_copy(struct pipe_context* pipe,
                       dst, dstx, dsty, src, srcx, srcy, width, height, TRUE);
 }
 
+/* Copy a block of pixels from one surface to another. */
+void r300_surface_copy(struct pipe_context* pipe,
+                       struct pipe_surface* dst,
+                       unsigned dstx, unsigned dsty,
+                       struct pipe_surface* src,
+                       unsigned srcx, unsigned srcy,
+                       unsigned width, unsigned height)
+{
+    enum pipe_format old_format = dst->texture->format;
+    enum pipe_format new_format = old_format;
+
+    assert(dst->texture->format == src->texture->format);
+
+    if (!pipe->screen->is_format_supported(pipe->screen,
+                                           old_format, src->texture->target,
+                                           PIPE_TEXTURE_USAGE_RENDER_TARGET |
+                                           PIPE_TEXTURE_USAGE_SAMPLER, 0)) {
+        switch (util_format_get_blocksize(old_format)) {
+            case 1:
+                new_format = PIPE_FORMAT_I8_UNORM;
+                break;
+            case 2:
+                new_format = PIPE_FORMAT_A4R4G4B4_UNORM;
+                break;
+            case 4:
+                new_format = PIPE_FORMAT_A8R8G8B8_UNORM;
+                break;
+            default:
+                debug_printf("r300: surface_copy: Unhandled format: %s. Falling back to software.\n"
+                             "r300: surface_copy: Software fallback doesn't work for tiled textures.\n",
+                             util_format_name(old_format));
+        }
+    }
+
+    if (old_format != new_format) {
+        dst->format = new_format;
+        src->format = new_format;
+
+        r300_texture_reinterpret_format(pipe->screen,
+                                        dst->texture, new_format);
+        r300_texture_reinterpret_format(pipe->screen,
+                                        src->texture, new_format);
+    }
+
+    r300_hw_copy(pipe, dst, dstx, dsty, src, srcx, srcy, width, height);
+
+    if (old_format != new_format) {
+        dst->format = old_format;
+        src->format = old_format;
+
+        r300_texture_reinterpret_format(pipe->screen,
+                                        dst->texture, old_format);
+        r300_texture_reinterpret_format(pipe->screen,
+                                        src->texture, old_format);
+    }
+}
+
 /* Fill a region of a surface with a constant value. */
 void r300_surface_fill(struct pipe_context* pipe,
                        struct pipe_surface* dst,
diff --git a/src/gallium/drivers/r300/r300_texture.c b/src/gallium/drivers/r300/r300_texture.c
index f228220..f3325be 100644
--- a/src/gallium/drivers/r300/r300_texture.c
+++ b/src/gallium/drivers/r300/r300_texture.c
@@ -85,6 +85,20 @@ static void r300_setup_texture_state(struct r300_screen* screen, struct r300_tex
                pt->width0, pt->height0, pt->last_level);
 }
 
+void r300_texture_reinterpret_format(struct pipe_screen *screen,
+                                     struct pipe_texture *tex,
+                                     enum pipe_format new_format)
+{
+    struct r300_screen *r300screen = r300_screen(screen);
+
+    SCREEN_DBG(r300screen, DBG_TEX, "r300: Reinterpreting format: %s -> %s\n",
+               util_format_name(tex->format), util_format_name(new_format));
+
+    tex->format = new_format;
+
+    r300_setup_texture_state(r300_screen(screen), (struct r300_texture*)tex);
+}
+
 unsigned r300_texture_get_offset(struct r300_texture* tex, unsigned level,
                                  unsigned zslice, unsigned face)
 {
diff --git a/src/gallium/drivers/r300/r300_texture.h b/src/gallium/drivers/r300/r300_texture.h
index 1d2382d..b9c3ab8 100644
--- a/src/gallium/drivers/r300/r300_texture.h
+++ b/src/gallium/drivers/r300/r300_texture.h
@@ -38,6 +38,10 @@ unsigned r300_texture_get_stride(struct r300_screen* screen,
 unsigned r300_texture_get_offset(struct r300_texture* tex, unsigned level,
                                  unsigned zslice, unsigned face);
 
+void r300_texture_reinterpret_format(struct pipe_screen *screen,
+                                     struct pipe_texture *tex,
+                                     enum pipe_format new_format);
+
 /* Translate a pipe_format into a useful texture format for sampling.
  *
  * R300_EASY_TX_FORMAT swizzles the texture.




More information about the mesa-commit mailing list