Merge commit 'origin/master' into gallium-msaa
[mesa.git] / src / gallium / drivers / r300 / r300_blit.c
index 415e6e0a168cc8ce80cf17daca5f6fc30247f882..85c2c1490167cfc8fcc7730364229342748d0758 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com>
+ * Copyright 2009 Marek Olšák <maraeo@gmail.com>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
  * USE OR OTHER DEALINGS IN THE SOFTWARE. */
 
 #include "r300_blit.h"
+#include "r300_context.h"
+#include "r300_texture.h"
 
-/* Does a "paint" into the specified rectangle.
- * Returns 1 on success, 0 on error. */
-int r300_fill_blit(struct r300_context* r300,
-                   unsigned cpp,
-                   short dst_pitch,
-                   struct pipe_buffer* dst_buffer,
-                   unsigned dst_offset,
-                   short x, short y,
-                   short w, short h,
-                   unsigned color)
+#include "util/u_format.h"
+
+static void r300_blitter_save_states(struct r300_context* r300)
+{
+    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.state);
+    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);
+    /* XXX this crashes the driver
+    util_blitter_save_vertex_buffers(r300->blitter, r300->vertex_buffer_count,
+                                     r300->vertex_buffer); */
+}
+
+/* Clear currently bound buffers. */
+void r300_clear(struct pipe_context* pipe,
+                unsigned buffers,
+                const float* rgba,
+                double depth,
+                unsigned stencil)
+{
+    /* XXX Implement fastfill.
+     *
+     * If fastfill is enabled, a few facts should be considered:
+     *
+     * 1) Zbuffer must be micro-tiled and whole microtiles must be
+     *    written.
+     *
+     * 2) ZB_DEPTHCLEARVALUE is used to clear a zbuffer and Z Mask must be
+     *    equal to 0.
+     *
+     * 3) For 16-bit integer buffering, compression causes a hung with one or
+     *    two samples and should not be used.
+     *
+     * 4) Fastfill must not be used if reading of compressed Z data is disabled
+     *    and writing of compressed Z data is enabled (RD/WR_COMP_ENABLE),
+     *    i.e. it cannot be used to compress the zbuffer.
+     *    (what the hell does that mean and how does it fit in clearing
+     *    the buffers?)
+     *
+     * - Marek
+     */
+
+    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,
+                       fb->width,
+                       fb->height,
+                       fb->nr_cbufs,
+                       buffers, rgba, depth, stencil);
+}
+
+/* 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)
 {
-    uint32_t dest_type;
-
-    /* Check for fallbacks. */
-    /* XXX we can do YUV surfaces, too, but only in 3D mode. Hmm... */
-    switch(cpp) {
-        case 2:
-        case 6:
-            dest_type = ATI_DATATYPE_CI8;
-            break;
-        case 4:
-            dest_type = ATI_DATATYPE_RGB565;
-            break;
-        case 8:
-            dest_type = ATI_DATATYPE_ARGB8888;
-            break;
-        default:
-            /* Whatever this is, we can't fill it. (Yet.) */
-            return 0;
+    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->fb_state.state);
+
+    util_blitter_save_fragment_sampler_states(
+        r300->blitter, state->sampler_state_count,
+        (void**)state->sampler_states);
+
+    util_blitter_save_fragment_sampler_views(
+        r300->blitter, state->sampler_view_count,
+        (struct pipe_sampler_view**)state->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;
+
+    if (dst->texture->format != src->texture->format) {
+        debug_printf("r300: Implementation error: Format mismatch in %s\n"
+            "    : src: %s dst: %s\n", __FUNCTION__,
+            util_format_short_name(src->texture->format),
+            util_format_short_name(dst->texture->format));
+        debug_assert(0);
+    }
+
+    if (!pipe->screen->is_format_supported(pipe->screen,
+                                           old_format, src->texture->target,
+                                           PIPE_BIND_RENDER_TARGET |
+                                           PIPE_BIND_SAMPLER_VIEW, 0) &&
+        util_format_is_plain(old_format)) {
+        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_short_name(old_format));
+        }
     }
 
-    /* XXX odds are *incredibly* good that we were in 3D just a bit ago,
-     * so flush here first. */
-
-    /* Set up the 2D engine. */
-    OUT_CS_REG(RADEON_DEFAULT_SC_BOTTOM_RIGHT,
-                  RADEON_DEFAULT_SC_RIGHT_MAX | RADEON_DEFAULT_SC_BOTTOM_MAX);
-    OUT_CS_REG(RADEON_DP_GUI_MASTER_CNTL,
-                  RADEON_GMC_DST_PITCH_OFFSET_CNTL |
-                  RADEON_GMC_BRUSH_SOLID_COLOR |
-                  (dest_type << 8) |
-                  RADEON_GMC_SRC_DATATYPE_COLOR |
-                  RADEON_ROP3_P |
-                  RADEON_GMC_CLR_CMP_CNTL_DIS);
-    /* XXX pack this? */
-    OUT_CS_REG(RADEON_DP_BRUSH_FRGD_CLR, color);
-    OUT_CS_REG(RADEON_DP_BRUSH_BKGD_CLR, 0x00000000);
-    OUT_CS_REG(RADEON_DP_SRC_FRGD_CLR, 0xffffffff);
-    OUT_CS_REG(RADEON_DP_SRC_BKGD_CLR, 0x00000000);
-    /* XXX what should this be? */
-    OUT_CS_REG(RADEON_DP_WRITE_MASK, 0x00000000);
-    OUT_CS_REG(RADEON_DP_CNTL,
-                  RADEON_DST_X_LEFT_TO_RIGHT | RADEON_DST_Y_TOP_TO_BOTTOM);
-    OUT_CS_REG(RADEON_DST_PITCH_OFFSET, 0x0);
-    /* XXX fix this shit -> OUT_RELOC(dst, 0, RADEON_GEM_DOMAIN_VRAM) */
-
-    /* Do the actual paint. */
-    OUT_CS_REG(RADEON_DST_Y_X, (y << 16) | x);
-    OUT_CS_REG(RADEON_DST_HEIGHT_WIDTH, (h << 16) | w);
-
-    /* Let the 2D engine settle. */
-    OUT_CS_REG(RADEON_DSTCACHE_CTLSTAT, RADEON_RB2D_DC_FLUSH_ALL);
-    OUT_CS_REG(RADEON_WAIT_UNTIL,
-               RADEON_WAIT_2D_IDLECLEAN | RADEON_WAIT_DMA_GUI_IDLE);
-    return 1;
+    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,
+                       unsigned dstx, unsigned dsty,
+                       unsigned width, unsigned height,
+                       unsigned value)
+{
+    struct r300_context* r300 = r300_context(pipe);
+
+    r300_blitter_save_states(r300);
+    util_blitter_save_framebuffer(r300->blitter, r300->fb_state.state);
+
+    util_blitter_fill(r300->blitter,
+                      dst, dstx, dsty, width, height, value);
 }