Mesa (master): r300-gallium: Add some surface_copy.

Corbin Simpson csimpson at kemper.freedesktop.org
Fri Mar 27 19:43:18 UTC 2009


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

Author: Corbin Simpson <MostAwesomeDude at gmail.com>
Date:   Wed Mar 25 21:26:02 2009 -0700

r300-gallium: Add some surface_copy.

---

 src/gallium/drivers/r300/r300_emit.c            |    2 +-
 src/gallium/drivers/r300/r300_emit.h            |    2 +
 src/gallium/drivers/r300/r300_reg.h             |    3 +
 src/gallium/drivers/r300/r300_state_invariant.c |   17 ----
 src/gallium/drivers/r300/r300_state_shader.h    |   54 ++++++++++++
 src/gallium/drivers/r300/r300_surface.c         |  101 +++++++++++++++++++++--
 src/gallium/drivers/r300/r300_surface.h         |   29 +++++++
 7 files changed, 184 insertions(+), 24 deletions(-)

diff --git a/src/gallium/drivers/r300/r300_emit.c b/src/gallium/drivers/r300/r300_emit.c
index 16455e4..a2e9cca 100644
--- a/src/gallium/drivers/r300/r300_emit.c
+++ b/src/gallium/drivers/r300/r300_emit.c
@@ -343,7 +343,7 @@ void r300_emit_viewport_state(struct r300_context* r300,
     END_CS;
 }
 
-static void r300_flush_textures(struct r300_context* r300)
+void r300_flush_textures(struct r300_context* r300)
 {
     CS_LOCALS(r300);
 
diff --git a/src/gallium/drivers/r300/r300_emit.h b/src/gallium/drivers/r300/r300_emit.h
index 0bc1f90..9d92b09 100644
--- a/src/gallium/drivers/r300/r300_emit.h
+++ b/src/gallium/drivers/r300/r300_emit.h
@@ -67,6 +67,8 @@ void r300_emit_vertex_format_state(struct r300_context* r300);
 void r300_emit_viewport_state(struct r300_context* r300,
                               struct r300_viewport_state* viewport);
 
+void r300_flush_textures(struct r300_context* r300);
+
 /* Emit all dirty state. */
 void r300_emit_dirty_state(struct r300_context* r300);
 
diff --git a/src/gallium/drivers/r300/r300_reg.h b/src/gallium/drivers/r300/r300_reg.h
index 3fe45e1..c9a195a 100644
--- a/src/gallium/drivers/r300/r300_reg.h
+++ b/src/gallium/drivers/r300/r300_reg.h
@@ -1191,6 +1191,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #       define R300_RS_INST_COUNT_MASK           0x0000000f
 #       define R300_RS_TX_OFFSET_SHIFT           5
 #	define R300_RS_TX_OFFSET_MASK            0x000000e0
+#       define R300_RS_TX_OFFSET(x)              ((x) << 5)
 
 /* gap */
 
@@ -1434,6 +1435,8 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #	define R300_TX_MAX_ANISO_8_TO_1          (3 << 21)
 #	define R300_TX_MAX_ANISO_16_TO_1         (4 << 21)
 #	define R300_TX_MAX_ANISO_MASK            (7 << 21)
+#       define R300_TX_WRAP_S(x)                 ((x) << 0)
+#       define R300_TX_WRAP_T(x)                 ((x) << 3)
 
 #define R300_TX_FILTER1_0                      0x4440
 #	define R300_CHROMA_KEY_MODE_DISABLE    0
diff --git a/src/gallium/drivers/r300/r300_state_invariant.c b/src/gallium/drivers/r300/r300_state_invariant.c
index e1837b6..3705ff9 100644
--- a/src/gallium/drivers/r300/r300_state_invariant.c
+++ b/src/gallium/drivers/r300/r300_state_invariant.c
@@ -141,28 +141,11 @@ void r300_emit_invariant_state(struct r300_context* r300)
     OUT_CS_REG(R300_ZB_DEPTHCLEARVALUE, 0x00000000);
     OUT_CS_REG(R300_ZB_HIZ_OFFSET, 0x00000000);
     OUT_CS_REG(R300_ZB_HIZ_PITCH, 0x00000000);
-    if (caps->has_tcl) {
-        OUT_CS_REG(R300_VAP_PROG_STREAM_CNTL_0,
-            (R300_DATA_TYPE_FLOAT_4 << R300_DATA_TYPE_0_SHIFT) |
-            ((R300_LAST_VEC | (1 << R300_DST_VEC_LOC_SHIFT) |
-                R300_DATA_TYPE_FLOAT_4) << R300_DATA_TYPE_1_SHIFT));
-    } else {
-        OUT_CS_REG(R300_VAP_PROG_STREAM_CNTL_0,
-            (R300_DATA_TYPE_FLOAT_4 << R300_DATA_TYPE_0_SHIFT) |
-            ((R300_LAST_VEC | (2 << R300_DST_VEC_LOC_SHIFT) |
-                R300_DATA_TYPE_FLOAT_4) << R300_DATA_TYPE_1_SHIFT));
-    }
-    OUT_CS_REG(R300_VAP_PROG_STREAM_CNTL_EXT_0,
-            (R300_VAP_SWIZZLE_XYZW << R300_SWIZZLE0_SHIFT) |
-            (R300_VAP_SWIZZLE_XYZW << R300_SWIZZLE1_SHIFT));
     OUT_CS_REG(R300_VAP_VTX_STATE_CNTL, 0x1);
     OUT_CS_REG(R300_VAP_VSM_VTX_ASSM, 0x405);
     OUT_CS_REG(R300_SE_VTE_CNTL, 0x0000043F);
     /* Vertex size. */
     OUT_CS_REG(R300_VAP_VTX_SIZE, 0x8);
-    OUT_CS_REG(R300_VAP_OUTPUT_VTX_FMT_0, 0x00000003);
-    OUT_CS_REG(R300_VAP_OUTPUT_VTX_FMT_1, 0x00000000);
-    OUT_CS_REG(R300_TX_ENABLE, 0x0);
 
     /* XXX */
     OUT_CS_REG(R300_SC_CLIP_RULE, 0xaaaa);
diff --git a/src/gallium/drivers/r300/r300_state_shader.h b/src/gallium/drivers/r300/r300_state_shader.h
index 7cbb41f..3c5f036 100644
--- a/src/gallium/drivers/r300/r300_state_shader.h
+++ b/src/gallium/drivers/r300/r300_state_shader.h
@@ -158,4 +158,58 @@ static const struct r500_fragment_shader r500_passthrough_fragment_shader = {
         R500_ALU_RGBA_A_SWIZ_0,
 };
 
+static const struct r300_fragment_shader r300_texture_fragment_shader = {
+    /* XXX This is the emission code. TODO: decode
+    OUT_CS_REG(R300_US_CONFIG, 0);
+    OUT_CS_REG(R300_US_CODE_OFFSET, 0x0);
+    OUT_CS_REG(R300_US_CODE_ADDR_0, 0x0);
+    OUT_CS_REG(R300_US_CODE_ADDR_1, 0x0);
+    OUT_CS_REG(R300_US_CODE_ADDR_2, 0x0);
+    OUT_CS_REG(R300_US_CODE_ADDR_3, 0x400000);
+*/
+    .alu_instruction_count = 1,
+    .tex_instruction_count = 0,
+    .indirections = 0,
+    .shader.stack_size = 1,
+
+    .instructions[0].alu_rgb_inst = R300_RGB_SWIZA(R300_ALU_ARGC_SRC0C_XYZ) |
+        R300_RGB_SWIZB(R300_ALU_ARGC_SRC0C_XYZ) |
+        R300_RGB_SWIZC(R300_ALU_ARGC_ZERO) |
+        R300_ALU_OUTC_CMP,
+    .instructions[0].alu_rgb_addr = R300_RGB_ADDR0(0) | R300_RGB_ADDR1(0) |
+        R300_RGB_ADDR2(0) | R300_ALU_DSTC_OUTPUT_XYZ,
+    .instructions[0].alu_alpha_inst = R300_ALPHA_SWIZA(R300_ALU_ARGA_SRC0A) |
+        R300_ALPHA_SWIZB(R300_ALU_ARGA_SRC0A) |
+        R300_ALPHA_SWIZC(R300_ALU_ARGA_ZERO) |
+        R300_ALU_OUTA_CMP,
+    .instructions[0].alu_alpha_addr = R300_ALPHA_ADDR0(0) |
+        R300_ALPHA_ADDR1(0) | R300_ALPHA_ADDR2(0) | R300_ALU_DSTA_OUTPUT,
+};
+
+static const struct r500_fragment_shader r500_texture_fragment_shader = {
+    .shader.stack_size = 0,
+    .instruction_count = 1,
+    .instructions[0].inst0 = R500_INST_TYPE_OUT |
+        R500_INST_TEX_SEM_WAIT | R500_INST_LAST |
+        R500_INST_RGB_OMASK_RGB | R500_INST_ALPHA_OMASK |
+        R500_INST_RGB_CLAMP | R500_INST_ALPHA_CLAMP,
+    .instructions[0].inst1 =
+        R500_RGB_ADDR0(0) | R500_RGB_ADDR1(0) | R500_RGB_ADDR1_CONST |
+        R500_RGB_ADDR2(0) | R500_RGB_ADDR2_CONST,
+    .instructions[0].inst2 =
+        R500_ALPHA_ADDR0(0) | R500_ALPHA_ADDR1(0) | R500_ALPHA_ADDR1_CONST |
+        R500_ALPHA_ADDR2(0) | R500_ALPHA_ADDR2_CONST,
+    .instructions[0].inst3 =
+        R500_ALU_RGB_SEL_A_SRC0 | R500_ALU_RGB_R_SWIZ_A_R |
+        R500_ALU_RGB_G_SWIZ_A_G | R500_ALU_RGB_B_SWIZ_A_B |
+        R500_ALU_RGB_SEL_B_SRC0 | R500_ALU_RGB_R_SWIZ_B_R |
+        R500_ALU_RGB_B_SWIZ_B_G | R500_ALU_RGB_G_SWIZ_B_B,
+    .instructions[0].inst4 =
+        R500_ALPHA_OP_CMP | R500_ALPHA_SWIZ_A_A | R500_ALPHA_SWIZ_B_A,
+    .instructions[0].inst5 =
+        R500_ALU_RGBA_OP_CMP | R500_ALU_RGBA_R_SWIZ_0 |
+        R500_ALU_RGBA_G_SWIZ_0 | R500_ALU_RGBA_B_SWIZ_0 |
+        R500_ALU_RGBA_A_SWIZ_0,
+};
+
 #endif /* R300_STATE_SHADER_H */
diff --git a/src/gallium/drivers/r300/r300_surface.c b/src/gallium/drivers/r300/r300_surface.c
index db18975..96b6398 100644
--- a/src/gallium/drivers/r300/r300_surface.c
+++ b/src/gallium/drivers/r300/r300_surface.c
@@ -113,7 +113,32 @@ static void r300_surface_fill(struct pipe_context* pipe,
         r300_emit_rs_block_state(r300, &r300_rs_block_clear_state);
     }
 
-    BEGIN_CS(21);
+    BEGIN_CS(31);
+
+    /* VAP stream control, mapping from input memory to PVS/RS memory */
+    if (caps->has_tcl) {
+        OUT_CS_REG(R300_VAP_PROG_STREAM_CNTL_0,
+            (R300_DATA_TYPE_FLOAT_4 << R300_DATA_TYPE_0_SHIFT) |
+            ((R300_LAST_VEC | (1 << R300_DST_VEC_LOC_SHIFT) |
+                R300_DATA_TYPE_FLOAT_4) << R300_DATA_TYPE_1_SHIFT));
+    } else {
+        OUT_CS_REG(R300_VAP_PROG_STREAM_CNTL_0,
+            (R300_DATA_TYPE_FLOAT_4 << R300_DATA_TYPE_0_SHIFT) |
+            ((R300_LAST_VEC | (2 << R300_DST_VEC_LOC_SHIFT) |
+                R300_DATA_TYPE_FLOAT_4) << R300_DATA_TYPE_1_SHIFT));
+    }
+    OUT_CS_REG(R300_VAP_PROG_STREAM_CNTL_EXT_0,
+            (R300_VAP_SWIZZLE_XYZW << R300_SWIZZLE0_SHIFT) |
+            (R300_VAP_SWIZZLE_XYZW << R300_SWIZZLE1_SHIFT));
+
+    /* VAP format controls */
+    OUT_CS_REG(R300_VAP_OUTPUT_VTX_FMT_0,
+            R300_VAP_OUTPUT_VTX_FMT_0__POS_PRESENT |
+            R300_VAP_OUTPUT_VTX_FMT_0__COLOR_0_PRESENT);
+    OUT_CS_REG(R300_VAP_OUTPUT_VTX_FMT_1, 0x0);
+
+    /* Disable textures */
+    OUT_CS_REG(R300_TX_ENABLE, 0x0);
 
     /* Viewport setup */
     OUT_CS_REG_SEQ(R300_SE_VPORT_XSCALE, 6);
@@ -132,7 +157,7 @@ static void r300_surface_fill(struct pipe_context* pipe,
     /* Packet3 with our point vertex */
     OUT_CS_PKT3(R200_3D_DRAW_IMMD_2, 8);
     OUT_CS(R300_PRIM_TYPE_POINT | R300_PRIM_WALK_RING |
-    (1 << R300_PRIM_NUM_VERTICES_SHIFT));
+            (1 << R300_PRIM_NUM_VERTICES_SHIFT));
     OUT_CS_32F(w / 2.0);
     OUT_CS_32F(h / 2.0);
     /* XXX this should be the depth value to clear to */
@@ -163,6 +188,7 @@ static void r300_surface_copy(struct pipe_context* pipe,
 {
     struct r300_context* r300 = r300_context(pipe);
     CS_LOCALS(r300);
+    struct r300_capabilities* caps = r300_screen(pipe->screen)->caps;
     struct r300_texture* srctex = (struct r300_texture*)src->texture;
     struct r300_texture* desttex = (struct r300_texture*)dest->texture;
 
@@ -171,14 +197,77 @@ static void r300_surface_copy(struct pipe_context* pipe,
         " dimensions %dx%d (pixel pitch %d)\n",
         src, srcx, srcy, dest, destx, desty, w, h, pixpitch);
 
-    /* if ((srctex == desttex) &&
+    if ((srctex == desttex) &&
             ((destx < srcx + w) || (srcx < destx + w)) &&
-            ((desty < srcy + h) || (srcy < destx + h))) { */
-    if (TRUE) {
+            ((desty < srcy + h) || (srcy < desty + h))) {
         debug_printf("r300: Falling back on surface_copy\n");
-        return util_surface_copy(pipe, FALSE, dest, destx, desty, src,
+        util_surface_copy(pipe, FALSE, dest, destx, desty, src,
                 srcx, srcy, w, h);
     }
+
+    r300_emit_sampler(r300, &r300_sampler_copy_state, 0);
+    r300_emit_texture(r300, srctex, 0);
+    r300_flush_textures(r300);
+
+    /* Fragment shader setup */
+    if (caps->is_r500) {
+        r500_emit_fragment_shader(r300, &r500_texture_fragment_shader);
+        r300_emit_rs_block_state(r300, &r500_rs_block_copy_state);
+    } else {
+        r300_emit_fragment_shader(r300, &r300_texture_fragment_shader);
+        r300_emit_rs_block_state(r300, &r300_rs_block_copy_state);
+    }
+
+    /* VAP stream control, mapping from input memory to PVS/RS memory */
+    if (caps->has_tcl) {
+        OUT_CS_REG(R300_VAP_PROG_STREAM_CNTL_0,
+            (R300_DATA_TYPE_FLOAT_2 << R300_DATA_TYPE_0_SHIFT) |
+            ((R300_LAST_VEC | (1 << R300_DST_VEC_LOC_SHIFT) |
+                R300_DATA_TYPE_FLOAT_2) << R300_DATA_TYPE_1_SHIFT));
+    } else {
+        OUT_CS_REG(R300_VAP_PROG_STREAM_CNTL_0,
+            (R300_DATA_TYPE_FLOAT_2 << R300_DATA_TYPE_0_SHIFT) |
+            ((R300_LAST_VEC | (6 << R300_DST_VEC_LOC_SHIFT) |
+                R300_DATA_TYPE_FLOAT_2) << R300_DATA_TYPE_1_SHIFT));
+    }
+    OUT_CS_REG(R300_VAP_PROG_STREAM_CNTL_EXT_0,
+            (R300_VAP_SWIZZLE_XYZW << R300_SWIZZLE0_SHIFT) |
+            (R300_VAP_SWIZZLE_XYZW << R300_SWIZZLE1_SHIFT));
+
+    /* VAP format controls */
+    OUT_CS_REG(R300_VAP_OUTPUT_VTX_FMT_0,
+            R300_VAP_OUTPUT_VTX_FMT_0__POS_PRESENT);
+    /* Two components of texture 0 */
+    OUT_CS_REG(R300_VAP_OUTPUT_VTX_FMT_1, 0x2);
+
+    /* Packet3 with our texcoords */
+    OUT_CS_PKT3(R200_3D_DRAW_IMMD_2, 8);
+    OUT_CS(R300_PRIM_TYPE_QUADS | R300_PRIM_WALK_RING |
+            (4 << R300_PRIM_NUM_VERTICES_SHIFT));
+    /* (x    , y    ) */
+    OUT_CS_32F((float)destx);
+    OUT_CS_32F((float)desty);
+    OUT_CS_32F((float)srcx);
+    OUT_CS_32F((float)srcy);
+    /* (x    , y + h) */
+    OUT_CS_32F((float)destx);
+    OUT_CS_32F((float)(desty + h));
+    OUT_CS_32F((float)srcx);
+    OUT_CS_32F((float)(srcy + h));
+    /* (x + w, y + h) */
+    OUT_CS_32F((float)(destx + w));
+    OUT_CS_32F((float)(desty + h));
+    OUT_CS_32F((float)(srcx + w));
+    OUT_CS_32F((float)(srcy + h));
+    /* (x + w, y    ) */
+    OUT_CS_32F((float)(destx + w));
+    OUT_CS_32F((float)desty);
+    OUT_CS_32F((float)(srcx + w));
+    OUT_CS_32F((float)srcy);
+
+    OUT_CS_REG(R300_RB3D_DSTCACHE_CTLSTAT, 0xA);
+
+    r300->dirty_hw++;
 }
 
 void r300_init_surface_functions(struct r300_context* r300)
diff --git a/src/gallium/drivers/r300/r300_surface.h b/src/gallium/drivers/r300/r300_surface.h
index b75b3ab..465b847 100644
--- a/src/gallium/drivers/r300/r300_surface.h
+++ b/src/gallium/drivers/r300/r300_surface.h
@@ -91,4 +91,33 @@ const struct r300_rs_block r500_rs_block_clear_state = {
     .inst_count = 0,
 };
 
+/* The following state is used for surface_copy only. */
+
+const struct r300_rs_block r300_rs_block_copy_state = {
+    .ip[0] = R500_RS_SEL_S(R300_RS_SEL_K0) |
+        R500_RS_SEL_T(R300_RS_SEL_K0) |
+        R500_RS_SEL_R(R300_RS_SEL_K0) |
+        R500_RS_SEL_Q(R300_RS_SEL_K1),
+    .inst[0] = R300_RS_INST_COL_CN_WRITE,
+    .count = R300_IT_COUNT(2) | R300_IC_COUNT(0) | R300_HIRES_EN,
+    .inst_count = R300_RS_TX_OFFSET(6),
+};
+
+const struct r300_rs_block r500_rs_block_copy_state = {
+    .ip[0] = R500_RS_SEL_S(R500_RS_IP_PTR_K0) |
+        R500_RS_SEL_T(R500_RS_IP_PTR_K0) |
+        R500_RS_SEL_R(R500_RS_IP_PTR_K0) |
+        R500_RS_SEL_Q(R500_RS_IP_PTR_K1),
+    .inst[0] = R500_RS_INST_COL_CN_WRITE,
+    .count = R300_IT_COUNT(2) | R300_IC_COUNT(0) | R300_HIRES_EN,
+    .inst_count = R300_RS_TX_OFFSET(6),
+};
+
+const struct r300_sampler_state r300_sampler_copy_state = {
+    .filter0 = R300_TX_WRAP_S(R300_TX_CLAMP) |
+        R300_TX_WRAP_T(R300_TX_CLAMP) |
+        R300_TX_MAG_FILTER_NEAREST |
+        R300_TX_MIN_FILTER_NEAREST,
+};
+
 #endif /* R300_SURFACE_H */




More information about the mesa-commit mailing list