Mesa (master): r300: accelerated blit support

Maciej Cencora osiris at kemper.freedesktop.org
Fri Dec 11 16:01:10 PST 2009


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

Author: Maciej Cencora <m.cencora at gmail.com>
Date:   Sun Nov  8 22:01:12 2009 +0100

r300: accelerated blit support

---

 src/mesa/drivers/dri/r300/Makefile       |    1 +
 src/mesa/drivers/dri/r300/r300_blit.c    |  468 ++++++++++++++++++++++++++++++
 src/mesa/drivers/dri/r300/r300_blit.h    |   46 +++
 src/mesa/drivers/dri/r300/r300_context.c |    2 +
 src/mesa/drivers/dri/r300/r300_context.h |    5 +
 5 files changed, 522 insertions(+), 0 deletions(-)

diff --git a/src/mesa/drivers/dri/r300/Makefile b/src/mesa/drivers/dri/r300/Makefile
index 9fd0133..b5145d9 100644
--- a/src/mesa/drivers/dri/r300/Makefile
+++ b/src/mesa/drivers/dri/r300/Makefile
@@ -43,6 +43,7 @@ RADEON_COMMON_SOURCES = \
 
 DRIVER_SOURCES = \
 		 radeon_screen.c \
+		 r300_blit.c \
 		 r300_context.c \
 		 r300_draw.c \
 		 r300_cmdbuf.c \
diff --git a/src/mesa/drivers/dri/r300/r300_blit.c b/src/mesa/drivers/dri/r300/r300_blit.c
new file mode 100644
index 0000000..7cb6f36
--- /dev/null
+++ b/src/mesa/drivers/dri/r300/r300_blit.c
@@ -0,0 +1,468 @@
+/*
+ * Copyright (C) 2009 Maciej Cencora <m.cencora at gmail.com>
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "radeon_common.h"
+#include "r300_context.h"
+
+#include "r300_blit.h"
+#include "r300_cmdbuf.h"
+#include "r300_emit.h"
+#include "r300_tex.h"
+#include "compiler/radeon_compiler.h"
+#include "compiler/radeon_opcodes.h"
+
+/**
+ * TODO:
+ * - handle depth buffer
+ * - r300 fp and rs setup
+ */
+
+static void vp_ins_outs(struct r300_vertex_program_compiler *c)
+{
+    c->code->inputs[VERT_ATTRIB_POS] = 0;
+    c->code->inputs[VERT_ATTRIB_TEX0] = 1;
+    c->code->outputs[VERT_RESULT_HPOS] = 0;
+    c->code->outputs[VERT_RESULT_TEX0] = 1;
+}
+
+static void fp_allocate_hw_inputs(
+    struct r300_fragment_program_compiler * c,
+    void (*allocate)(void * data, unsigned input, unsigned hwreg),
+    void * mydata)
+{
+    allocate(mydata, FRAG_ATTRIB_TEX0, 0);
+}
+
+static void create_vertex_program(struct r300_context *r300)
+{
+    struct r300_vertex_program_compiler compiler;
+    struct rc_instruction *inst;
+
+    rc_init(&compiler.Base);
+
+    inst = rc_insert_new_instruction(&compiler.Base, compiler.Base.Program.Instructions.Prev);
+    inst->U.I.Opcode = RC_OPCODE_MOV;
+    inst->U.I.DstReg.File = RC_FILE_OUTPUT;
+    inst->U.I.DstReg.Index = VERT_RESULT_HPOS;
+    inst->U.I.DstReg.RelAddr = 0;
+    inst->U.I.DstReg.WriteMask = RC_MASK_XYZW;
+    inst->U.I.SrcReg[0].Abs = 0;
+    inst->U.I.SrcReg[0].File = RC_FILE_INPUT;
+    inst->U.I.SrcReg[0].Index = VERT_ATTRIB_POS;
+    inst->U.I.SrcReg[0].Negate = 0;
+    inst->U.I.SrcReg[0].RelAddr = 0;
+    inst->U.I.SrcReg[0].Swizzle = RC_SWIZZLE_XYZW;
+
+    inst = rc_insert_new_instruction(&compiler.Base, compiler.Base.Program.Instructions.Prev);
+    inst->U.I.Opcode = RC_OPCODE_MOV;
+    inst->U.I.DstReg.File = RC_FILE_OUTPUT;
+    inst->U.I.DstReg.Index = VERT_RESULT_TEX0;
+    inst->U.I.DstReg.RelAddr = 0;
+    inst->U.I.DstReg.WriteMask = RC_MASK_XYZW;
+    inst->U.I.SrcReg[0].Abs = 0;
+    inst->U.I.SrcReg[0].File = RC_FILE_INPUT;
+    inst->U.I.SrcReg[0].Index = VERT_ATTRIB_TEX0;
+    inst->U.I.SrcReg[0].Negate = 0;
+    inst->U.I.SrcReg[0].RelAddr = 0;
+    inst->U.I.SrcReg[0].Swizzle = RC_SWIZZLE_XYZW;
+
+    compiler.Base.Program.InputsRead = (1 << VERT_ATTRIB_POS) | (1 << VERT_ATTRIB_TEX0);
+    compiler.RequiredOutputs = compiler.Base.Program.OutputsWritten = (1 << VERT_RESULT_HPOS) | (1 << VERT_RESULT_TEX0);
+    compiler.SetHwInputOutput = vp_ins_outs;
+    compiler.code = &r300->blit.vp_code;
+
+    r3xx_compile_vertex_program(&compiler);
+}
+
+static void create_fragment_program(struct r300_context *r300)
+{
+    struct r300_fragment_program_compiler compiler;
+    struct rc_instruction *inst;
+
+    rc_init(&compiler.Base);
+
+    inst = rc_insert_new_instruction(&compiler.Base, compiler.Base.Program.Instructions.Prev);
+    inst->U.I.Opcode = RC_OPCODE_TEX;
+    inst->U.I.TexSrcTarget = RC_TEXTURE_2D;
+    inst->U.I.TexSrcUnit = 0;
+    inst->U.I.DstReg.File = RC_FILE_OUTPUT;
+    inst->U.I.DstReg.Index = FRAG_RESULT_COLOR;
+    inst->U.I.DstReg.WriteMask = RC_MASK_XYZW;
+    inst->U.I.SrcReg[0].Abs = 0;
+    inst->U.I.SrcReg[0].File = RC_FILE_INPUT;
+    inst->U.I.SrcReg[0].Index = FRAG_ATTRIB_TEX0;
+    inst->U.I.SrcReg[0].Negate = 0;
+    inst->U.I.SrcReg[0].RelAddr = 0;
+    inst->U.I.SrcReg[0].Swizzle = RC_SWIZZLE_XYZW;
+
+    compiler.Base.Program.InputsRead = (1 << FRAG_ATTRIB_TEX0);
+    compiler.OutputColor = FRAG_RESULT_COLOR;
+    compiler.OutputDepth = FRAG_RESULT_DEPTH;
+    compiler.is_r500 = (r300->radeon.radeonScreen->chip_family >= CHIP_FAMILY_RV515);
+    compiler.code = &r300->blit.fp_code;
+    compiler.AllocateHwInputs = fp_allocate_hw_inputs;
+
+    r3xx_compile_fragment_program(&compiler);
+}
+
+void r300_blit_init(struct r300_context *r300)
+{
+    create_vertex_program(r300);
+    create_fragment_program(r300);
+}
+
+static void r500_emit_rs_setup(struct r300_context *r300)
+{
+    BATCH_LOCALS(&r300->radeon);
+
+    BEGIN_BATCH(7);
+    OUT_BATCH_REGSEQ(R300_RS_COUNT, 2);
+    OUT_BATCH((4 << R300_IT_COUNT_SHIFT) | R300_HIRES_EN);
+    OUT_BATCH(0);
+    OUT_BATCH_REGVAL(R500_RS_INST_0,
+                     (0 << R500_RS_INST_TEX_ID_SHIFT) |
+                     (0 << R500_RS_INST_TEX_ADDR_SHIFT) |
+                     R500_RS_INST_TEX_CN_WRITE |
+                     R500_RS_INST_COL_CN_NO_WRITE);
+    OUT_BATCH_REGVAL(R500_RS_IP_0,
+                     (0 << R500_RS_IP_TEX_PTR_S_SHIFT) |
+                     (1 << R500_RS_IP_TEX_PTR_T_SHIFT) |
+                     (2 << R500_RS_IP_TEX_PTR_R_SHIFT) |
+                     (3 << R500_RS_IP_TEX_PTR_Q_SHIFT));
+    END_BATCH();
+}
+
+static void r300_emit_fp_setup(struct r300_context *r300)
+{
+    assert(0);
+}
+
+static void r300_emit_rs_setup(struct r300_context *r300)
+{
+    assert(0);
+}
+
+static void r300_emit_tx_setup(struct r300_context *r300,
+                               gl_format mesa_format,
+                               struct radeon_bo *bo,
+                               intptr_t offset,
+                               unsigned width,
+                               unsigned height,
+                               unsigned pitch)
+{
+    BATCH_LOCALS(&r300->radeon);
+
+    assert(width <= 2048);
+    assert(height <= 2048);
+    assert(r300TranslateTexFormat(mesa_format) != 0);
+    assert(offset % 32 == 0);
+
+    BEGIN_BATCH(17);
+    OUT_BATCH_REGVAL(R300_TX_FILTER0_0,
+                     (R300_TX_CLAMP_TO_EDGE  << R300_TX_WRAP_S_SHIFT) |
+                     (R300_TX_CLAMP_TO_EDGE  << R300_TX_WRAP_T_SHIFT) |
+                     (R300_TX_CLAMP_TO_EDGE  << R300_TX_WRAP_R_SHIFT) |
+                     R300_TX_MIN_FILTER_MIP_NONE |
+                     R300_TX_MIN_FILTER_LINEAR |
+                     R300_TX_MAG_FILTER_LINEAR |
+                     (0 << 28));
+    OUT_BATCH_REGVAL(R300_TX_FILTER1_0, 0);
+    OUT_BATCH_REGVAL(R300_TX_SIZE_0,
+                     ((width-1) << R300_TX_WIDTHMASK_SHIFT) |
+                     ((height-1) << R300_TX_HEIGHTMASK_SHIFT) |
+                     (0 << R300_TX_DEPTHMASK_SHIFT) |
+                     (0 << R300_TX_MAX_MIP_LEVEL_SHIFT) |
+                     R300_TX_SIZE_TXPITCH_EN);
+
+    OUT_BATCH_REGVAL(R300_TX_FORMAT_0, r300TranslateTexFormat(mesa_format));
+    OUT_BATCH_REGVAL(R300_TX_FORMAT2_0, pitch/_mesa_get_format_bytes(mesa_format) - 1);
+    OUT_BATCH_REGSEQ(R300_TX_OFFSET_0, 1);
+    OUT_BATCH_RELOC(0, bo, offset, RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0, 0);
+
+    OUT_BATCH_REGSEQ(R300_TX_INVALTAGS, 2);
+    OUT_BATCH(0);
+    OUT_BATCH(1);
+
+    END_BATCH();
+}
+
+#define EASY_US_FORMAT(FMT, C0, C1, C2, C3, SIGN) \
+    (FMT  | R500_C0_SEL_##C0 | R500_C1_SEL_##C1 | \
+    R500_C2_SEL_##C2 | R500_C3_SEL_##C3 | R500_OUT_SIGN(SIGN))
+
+static uint32_t mesa_format_to_us_format(gl_format mesa_format)
+{
+    switch(mesa_format)
+    {
+        case MESA_FORMAT_RGBA8888: // x
+            return EASY_US_FORMAT(R500_OUT_FMT_C4_8, A, B, G, R, 0);
+        case MESA_FORMAT_RGB565: // x
+        case MESA_FORMAT_ARGB1555: // x
+        case MESA_FORMAT_RGBA8888_REV: // x
+            return EASY_US_FORMAT(R500_OUT_FMT_C4_8, R, G, B, A, 0);
+        case MESA_FORMAT_ARGB8888: // x
+            return EASY_US_FORMAT(R500_OUT_FMT_C4_8, B, G, R, A, 0);
+        case MESA_FORMAT_ARGB8888_REV:
+            return EASY_US_FORMAT(R500_OUT_FMT_C4_8, A, R, G, B, 0);
+        case MESA_FORMAT_XRGB8888:
+            return EASY_US_FORMAT(R500_OUT_FMT_C4_8, A, R, G, B, 0);
+
+        case MESA_FORMAT_RGB332:
+            return EASY_US_FORMAT(R500_OUT_FMT_C_3_3_2, A, R, G, B, 0);
+
+        case MESA_FORMAT_RGBA_FLOAT32:
+            return EASY_US_FORMAT(R500_OUT_FMT_C4_32_FP, R, G, B, A, 0);
+        case MESA_FORMAT_RGBA_FLOAT16:
+            return EASY_US_FORMAT(R500_OUT_FMT_C4_16_FP, R, G, B, A, 0);
+        case MESA_FORMAT_ALPHA_FLOAT32:
+            return EASY_US_FORMAT(R500_OUT_FMT_C_32_FP, A, A, A, A, 0);
+        case MESA_FORMAT_ALPHA_FLOAT16:
+            return EASY_US_FORMAT(R500_OUT_FMT_C_16_FP, A, A, A, A, 0);
+
+        case MESA_FORMAT_SIGNED_RGBA8888:
+            return EASY_US_FORMAT(R500_OUT_FMT_C4_8, R, G, B, A, 0xf);
+        case MESA_FORMAT_SIGNED_RGBA8888_REV:
+            return EASY_US_FORMAT(R500_OUT_FMT_C4_8, A, B, G, R, 0xf);
+        case MESA_FORMAT_SIGNED_RGBA_16:
+            return EASY_US_FORMAT(R500_OUT_FMT_C4_16, R, G, B, A, 0xf);
+
+        default:
+            assert(!"Invalid format for US output\n");
+            return 0;
+    }
+}
+#undef EASY_US_FORMAT
+
+static void r500_emit_fp_setup(struct r300_context *r300,
+                               struct r500_fragment_program_code *fp,
+                               gl_format dst_format)
+{
+    r500_emit_fp(r300, (uint32_t *)fp->inst, (fp->inst_end + 1) * 6, 0, 0, 0);
+    BATCH_LOCALS(&r300->radeon);
+
+    BEGIN_BATCH(10);
+    OUT_BATCH_REGSEQ(R500_US_CODE_ADDR, 3);
+    OUT_BATCH(R500_US_CODE_START_ADDR(0) | R500_US_CODE_END_ADDR(fp->inst_end));
+    OUT_BATCH(R500_US_CODE_RANGE_ADDR(0) | R500_US_CODE_RANGE_SIZE(fp->inst_end));
+    OUT_BATCH(0);
+    OUT_BATCH_REGVAL(R500_US_CONFIG, 0);
+    OUT_BATCH_REGVAL(R500_US_OUT_FMT_0, mesa_format_to_us_format(dst_format));
+    OUT_BATCH_REGVAL(R500_US_PIXSIZE, fp->max_temp_idx);
+    END_BATCH();
+}
+
+static void emit_pvs_setup(struct r300_context *r300,
+                           uint32_t *vp_code,
+                           unsigned vp_len)
+{
+    BATCH_LOCALS(&r300->radeon);
+
+    r300_emit_vpu(r300, vp_code, vp_len * 4, R300_PVS_CODE_START);
+
+    BEGIN_BATCH(4);
+    OUT_BATCH_REGSEQ(R300_VAP_PVS_CODE_CNTL_0, 3);
+    OUT_BATCH((0 << R300_PVS_FIRST_INST_SHIFT) |
+              ((vp_len - 1)  << R300_PVS_XYZW_VALID_INST_SHIFT) |
+              ((vp_len - 1)<< R300_PVS_LAST_INST_SHIFT));
+    OUT_BATCH(0);
+    OUT_BATCH((vp_len - 1) << R300_PVS_LAST_VTX_SRC_INST_SHIFT);
+    END_BATCH();
+}
+
+static void emit_vap_setup(struct r300_context *r300, unsigned width, unsigned height)
+{
+    BATCH_LOCALS(&r300->radeon);
+
+    BEGIN_BATCH(12);
+    OUT_BATCH_REGSEQ(R300_SE_VTE_CNTL, 2);
+    OUT_BATCH(R300_VTX_XY_FMT | R300_VTX_Z_FMT);
+    OUT_BATCH(4);
+
+    OUT_BATCH_REGVAL(R300_VAP_PSC_SGN_NORM_CNTL, 0xaaaaaaaa);
+    OUT_BATCH_REGVAL(R300_VAP_PROG_STREAM_CNTL_0,
+                     ((R300_DATA_TYPE_FLOAT_2 | (0 << R300_DST_VEC_LOC_SHIFT)) << 0) |
+                     (((1 << R300_DST_VEC_LOC_SHIFT) | R300_DATA_TYPE_FLOAT_2 | R300_LAST_VEC) << 16));
+    OUT_BATCH_REGVAL(R300_VAP_PROG_STREAM_CNTL_EXT_0,
+                    ((((R300_SWIZZLE_SELECT_X << R300_SWIZZLE_SELECT_X_SHIFT) |
+                       (R300_SWIZZLE_SELECT_Y << R300_SWIZZLE_SELECT_Y_SHIFT) |
+                       (R300_SWIZZLE_SELECT_FP_ZERO << R300_SWIZZLE_SELECT_Z_SHIFT) |
+                       (R300_SWIZZLE_SELECT_FP_ONE << R300_SWIZZLE_SELECT_W_SHIFT) | 
+                       (0xf << R300_WRITE_ENA_SHIFT) ) << 0) |
+                     (((R300_SWIZZLE_SELECT_X << R300_SWIZZLE_SELECT_X_SHIFT) |
+                       (R300_SWIZZLE_SELECT_Y << R300_SWIZZLE_SELECT_Y_SHIFT) |
+                       (R300_SWIZZLE_SELECT_FP_ZERO << R300_SWIZZLE_SELECT_Z_SHIFT) |
+                       (R300_SWIZZLE_SELECT_FP_ONE << R300_SWIZZLE_SELECT_W_SHIFT) |
+                       (0xf << R300_WRITE_ENA_SHIFT) ) << 16) ) );
+    OUT_BATCH_REGSEQ(R300_VAP_OUTPUT_VTX_FMT_0, 2);
+    OUT_BATCH(R300_VAP_OUTPUT_VTX_FMT_0__POS_PRESENT);
+    OUT_BATCH(R300_VAP_OUTPUT_VTX_FMT_1__4_COMPONENTS);
+    END_BATCH();
+}
+
+static GLboolean validate_buffers(struct r300_context *r300,
+                                  struct radeon_bo *src_bo,
+                                  struct radeon_bo *dst_bo)
+{
+    int ret;
+    radeon_cs_space_add_persistent_bo(r300->radeon.cmdbuf.cs,
+                                      src_bo, RADEON_GEM_DOMAIN_VRAM, 0);
+
+    radeon_cs_space_add_persistent_bo(r300->radeon.cmdbuf.cs,
+                                      dst_bo, 0, RADEON_GEM_DOMAIN_VRAM);
+
+    ret = radeon_cs_space_check_with_bo(r300->radeon.cmdbuf.cs,
+                                        first_elem(&r300->radeon.dma.reserved)->bo,
+                                        RADEON_GEM_DOMAIN_GTT, 0);
+    if (ret)
+        return GL_FALSE;
+
+    return GL_TRUE;
+}
+
+static void emit_draw_packet(struct r300_context *r300, float width, float height)
+{
+    float verts[] = {   0.0,    0.0, 0.0, 1.0,
+                        0.0, height, 0.0, 0.0,
+                      width, height, 1.0, 0.0,
+                      width,    0.0, 1.0, 1.0 };
+
+    BATCH_LOCALS(&r300->radeon);
+
+    BEGIN_BATCH(19);
+    OUT_BATCH_PACKET3(R300_PACKET3_3D_DRAW_IMMD_2, 16);
+    OUT_BATCH(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_EMBEDDED |
+              (4 << 16) | R300_VAP_VF_CNTL__PRIM_QUADS);
+    OUT_BATCH_TABLE(verts, 16);
+    END_BATCH();
+}
+
+static void other_stuff(struct r300_context *r300)
+{
+    BATCH_LOCALS(&r300->radeon);
+
+    BEGIN_BATCH(15);
+    OUT_BATCH_REGVAL(R300_GA_POLY_MODE,
+                     R300_GA_POLY_MODE_FRONT_PTYPE_TRI | R300_GA_POLY_MODE_BACK_PTYPE_TRI);
+    OUT_BATCH_REGVAL(R300_SU_CULL_MODE, R300_FRONT_FACE_CCW);
+    OUT_BATCH_REGVAL(R300_FG_FOG_BLEND, 0);
+    OUT_BATCH_REGVAL(R300_FG_ALPHA_FUNC, 0);
+    OUT_BATCH_REGSEQ(R300_RB3D_CBLEND, 2);
+    OUT_BATCH(0x0);
+    OUT_BATCH(0x0);
+    OUT_BATCH_REGVAL(R300_VAP_CLIP_CNTL, R300_CLIP_DISABLE);
+    OUT_BATCH_REGVAL(R300_ZB_CNTL, 0);
+    END_BATCH();
+}
+
+static void emit_cb_setup(struct r300_context *r300,
+                          struct radeon_bo *bo,
+                          intptr_t offset,
+                          gl_format mesa_format,
+                          unsigned width,
+                          unsigned height)
+{
+    BATCH_LOCALS(&r300->radeon);
+
+    unsigned x1, y1, x2, y2;
+    x1 = 0;
+    y1 = 0;
+    x2 = width - 1;
+    y2 = height - 1;
+
+    if (r300->radeon.radeonScreen->chip_family < CHIP_FAMILY_RV515) {
+        x1 += R300_SCISSORS_OFFSET;
+        y1 += R300_SCISSORS_OFFSET;
+        x2 += R300_SCISSORS_OFFSET;
+        y2 += R300_SCISSORS_OFFSET;
+    }
+
+    r300_emit_cb_setup(r300, bo, offset, mesa_format,
+                       _mesa_get_format_bytes(mesa_format),
+                       _mesa_format_row_stride(mesa_format, width));
+
+    BEGIN_BATCH_NO_AUTOSTATE(3);
+    OUT_BATCH_REGSEQ(R300_SC_SCISSORS_TL, 2);
+    OUT_BATCH((x1 << R300_SCISSORS_X_SHIFT)|(y1 << R300_SCISSORS_Y_SHIFT));
+    OUT_BATCH((x2 << R300_SCISSORS_X_SHIFT)|(y2 << R300_SCISSORS_Y_SHIFT));
+    END_BATCH();
+}
+
+GLboolean r300_blit(struct r300_context *r300,
+                    struct radeon_bo *src_bo,
+                    intptr_t src_offset,
+                    gl_format src_mesaformat,
+                    unsigned src_pitch,
+                    unsigned src_width,
+                    unsigned src_height,
+                    struct radeon_bo *dst_bo,
+                    intptr_t dst_offset,
+                    gl_format dst_mesaformat,
+                    unsigned dst_width,
+                    unsigned dst_height)
+{
+    assert(src_width == dst_width);
+    assert(src_height == dst_height);
+
+    if (0) {
+        fprintf(stderr, "src: width %d, height %d, pitch %d vs %d, format %s\n",
+                src_width, src_height, src_pitch,
+                _mesa_format_row_stride(src_mesaformat, src_width),
+                _mesa_get_format_name(src_mesaformat));
+        fprintf(stderr, "dst: width %d, height %d, pitch %d, format %s\n",
+                dst_width, dst_height,
+                _mesa_format_row_stride(dst_mesaformat, dst_width),
+                _mesa_get_format_name(dst_mesaformat));
+    }
+
+    if (!validate_buffers(r300, src_bo, dst_bo))
+        return GL_FALSE;
+
+    other_stuff(r300);
+
+    r300_emit_tx_setup(r300, src_mesaformat, src_bo, src_offset, src_width, src_height, src_pitch);
+
+    if (r300->radeon.radeonScreen->chip_family >= CHIP_FAMILY_RV515) {
+        r500_emit_fp_setup(r300, &r300->blit.fp_code.code.r500, dst_mesaformat);
+        r500_emit_rs_setup(r300);
+    } else {
+        r300_emit_fp_setup(r300);
+        r300_emit_rs_setup(r300);
+    }
+
+    emit_pvs_setup(r300, r300->blit.vp_code.body.d, 2);
+    emit_vap_setup(r300, dst_width, dst_height);
+
+    emit_cb_setup(r300, dst_bo, dst_offset, dst_mesaformat, dst_width, dst_height);
+
+    emit_draw_packet(r300, dst_width, dst_height);
+
+    r300EmitCacheFlush(r300);
+
+    radeonFlush(r300->radeon.glCtx);
+
+    return GL_TRUE;
+}
\ No newline at end of file
diff --git a/src/mesa/drivers/dri/r300/r300_blit.h b/src/mesa/drivers/dri/r300/r300_blit.h
new file mode 100644
index 0000000..29c5aa9
--- /dev/null
+++ b/src/mesa/drivers/dri/r300/r300_blit.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2009 Maciej Cencora <m.cencora at gmail.com>
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef R300_BLIT_H
+#define R300_BLIT_H
+
+void r300_blit_init(struct r300_context *r300);
+
+GLboolean r300_blit(struct r300_context *r300,
+                    struct radeon_bo *src_bo,
+                    intptr_t src_offset,
+                    gl_format src_mesaformat,
+                    unsigned src_pitch,
+                    unsigned src_width,
+                    unsigned src_height,
+                    struct radeon_bo *dst_bo,
+                    intptr_t dst_offset,
+                    gl_format dst_mesaformat,
+                    unsigned dst_width,
+                    unsigned dst_height);
+
+#endif // R300_BLIT_H
\ No newline at end of file
diff --git a/src/mesa/drivers/dri/r300/r300_context.c b/src/mesa/drivers/dri/r300/r300_context.c
index 67183c3..6995637 100644
--- a/src/mesa/drivers/dri/r300/r300_context.c
+++ b/src/mesa/drivers/dri/r300/r300_context.c
@@ -60,6 +60,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "r300_context.h"
 #include "radeon_context.h"
 #include "radeon_span.h"
+#include "r300_blit.h"
 #include "r300_cmdbuf.h"
 #include "r300_state.h"
 #include "r300_tex.h"
@@ -537,6 +538,7 @@ GLboolean r300CreateContext(const __GLcontextModes * glVisual,
 		r300InitSwtcl(ctx);
 	}
 
+	r300_blit_init(r300);
 	radeon_fbo_init(&r300->radeon);
 	radeonInitSpanFuncs( ctx );
 	r300InitCmdBuf(r300);
diff --git a/src/mesa/drivers/dri/r300/r300_context.h b/src/mesa/drivers/dri/r300/r300_context.h
index 518d5cd..198414a 100644
--- a/src/mesa/drivers/dri/r300/r300_context.h
+++ b/src/mesa/drivers/dri/r300/r300_context.h
@@ -533,6 +533,11 @@ struct r300_context {
 
 	uint32_t fallback;
 
+	struct {
+		struct r300_vertex_program_code vp_code;
+		struct rX00_fragment_program_code fp_code;
+	} blit;
+
 	DECLARE_RENDERINPUTS(render_inputs_bitset);
 };
 



More information about the mesa-commit mailing list