r300-gallium: Add some surface_copy.
authorCorbin Simpson <MostAwesomeDude@gmail.com>
Thu, 26 Mar 2009 04:26:02 +0000 (21:26 -0700)
committerCorbin Simpson <MostAwesomeDude@gmail.com>
Fri, 27 Mar 2009 19:41:51 +0000 (12:41 -0700)
src/gallium/drivers/r300/r300_emit.c
src/gallium/drivers/r300/r300_emit.h
src/gallium/drivers/r300/r300_reg.h
src/gallium/drivers/r300/r300_state_invariant.c
src/gallium/drivers/r300/r300_state_shader.h
src/gallium/drivers/r300/r300_surface.c
src/gallium/drivers/r300/r300_surface.h

index 16455e48ce87fa3e280172b144b809de5c178854..a2e9cca39ba8d8652c9a2bddfe92336348dd7176 100644 (file)
@@ -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);
 
index 0bc1f90e6ab1fb89656110bbf41359f8aef710d7..9d92b090aced24383bf14203befebd450376595c 100644 (file)
@@ -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);
 
index 3fe45e139325e2dc57410cb7dd01ca4c580c2896..c9a195a6ce434399e19809058e9e94586e5f7372 100644 (file)
@@ -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
index e1837b638010a697e197709b7a0920196cfc1fa0..3705ff98db596981c5e3883423afcababd10cc6a 100644 (file)
@@ -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);
index 7cbb41ffdb9c8b9ba3304c9ffd99af7fd403f08c..3c5f036d2aebb4794c12c08f865fa68f001ed93c 100644 (file)
@@ -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 */
index db18975a10f05bdbc6022a0906d930a1c0a4a870..96b63986ea7f8ab154e84ecb647d461ee64892aa 100644 (file)
@@ -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)
index b75b3ab84cf6ea33ec9b0dd4248c3f5bd0f3e619..465b8476edfe17205f0919b41ad50668cc8e7a75 100644 (file)
@@ -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 */