Merge branch '7.8'
[mesa.git] / src / gallium / drivers / r300 / r300_blit.c
index ffe066d53693488e1eec4a19a2962fc9293ee901..bcdf950df9cfcba70332c7d5871174218a3c6707 100644 (file)
 
 #include "r300_blit.h"
 #include "r300_context.h"
+#include "r300_texture.h"
 
-#include "util/u_rect.h"
+#include "util/u_format.h"
 
 static void r300_blitter_save_states(struct r300_context* r300)
 {
-    util_blitter_save_blend(r300->blitter, r300->blend_state);
-    util_blitter_save_depth_stencil_alpha(r300->blitter, r300->dsa_state);
-    util_blitter_save_rasterizer(r300->blitter, r300->rs_state);
+    util_blitter_save_blend(r300->blitter, r300->blend_state.state);
+    util_blitter_save_depth_stencil_alpha(r300->blitter, r300->dsa_state.state);
+    util_blitter_save_stencil_ref(r300->blitter, &(r300->stencil_ref));
+    util_blitter_save_rasterizer(r300->blitter, r300->rs_state.state);
     util_blitter_save_fragment_shader(r300->blitter, r300->fs);
-    util_blitter_save_vertex_shader(r300->blitter, r300->vs);
+    util_blitter_save_vertex_shader(r300->blitter, r300->vs_state.state);
+    util_blitter_save_viewport(r300->blitter, &r300->viewport);
+    util_blitter_save_clip(r300->blitter, &r300->clip);
+    util_blitter_save_vertex_elements(r300->blitter, r300->velems);
 }
 
 /* Clear currently bound buffers. */
@@ -75,44 +80,108 @@ void r300_clear(struct pipe_context* pipe,
      */
 
     struct r300_context* r300 = r300_context(pipe);
+    struct pipe_framebuffer_state* fb =
+        (struct pipe_framebuffer_state*)r300->fb_state.state;
 
     r300_blitter_save_states(r300);
 
     util_blitter_clear(r300->blitter,
-                       r300->framebuffer_state.width,
-                       r300->framebuffer_state.height,
-                       r300->framebuffer_state.nr_cbufs,
+                       fb->width,
+                       fb->height,
+                       fb->nr_cbufs,
                        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);
+    struct r300_textures_state* state =
+        (struct r300_textures_state*)r300->textures_state.state;
 
     /* Yeah we have to save all those states to ensure this blitter operation
      * is really transparent. The states will be restored by the blitter once
      * copying is done. */
     r300_blitter_save_states(r300);
-    util_blitter_save_framebuffer(r300->blitter, &r300->framebuffer_state);
+    util_blitter_save_framebuffer(r300->blitter, r300->fb_state.state);
 
     util_blitter_save_fragment_sampler_states(
-        r300->blitter, r300->sampler_count, (void**)r300->sampler_states);
+        r300->blitter, state->sampler_count, (void**)state->sampler_states);
 
-    util_blitter_save_fragment_sampler_textures(
-        r300->blitter, r300->texture_count,
-        (struct pipe_texture**)r300->textures);
+    util_blitter_save_fragment_sampler_views(
+        r300->blitter, state->texture_count,
+        state->fragment_sampler_views);
 
     /* Do a copy */
     util_blitter_copy(r300->blitter,
                       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_B4G4R4A4_UNORM;
+                break;
+            case 4:
+                new_format = PIPE_FORMAT_B8G8R8A8_UNORM;
+                break;
+            case 8:
+                new_format = PIPE_FORMAT_R16G16B16A16_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,
@@ -123,7 +192,7 @@ void r300_surface_fill(struct pipe_context* pipe,
     struct r300_context* r300 = r300_context(pipe);
 
     r300_blitter_save_states(r300);
-    util_blitter_save_framebuffer(r300->blitter, &r300->framebuffer_state);
+    util_blitter_save_framebuffer(r300->blitter, r300->fb_state.state);
 
     util_blitter_fill(r300->blitter,
                       dst, dstx, dsty, width, height, value);