Exemplo n.º 1
0
void r300_emit_vertex_stream_state(struct r300_context* r300,
                                   unsigned size, void* state)
{
    struct r300_vertex_stream_state *streams =
        (struct r300_vertex_stream_state*)state;
    unsigned i;
    CS_LOCALS(r300);

    if (DBG_ON(r300, DBG_PSC)) {
        fprintf(stderr, "r300: PSC emit:\n");

        for (i = 0; i < streams->count; i++) {
            fprintf(stderr, "    : prog_stream_cntl%d: 0x%08x\n", i,
                   streams->vap_prog_stream_cntl[i]);
        }

        for (i = 0; i < streams->count; i++) {
            fprintf(stderr, "    : prog_stream_cntl_ext%d: 0x%08x\n", i,
                   streams->vap_prog_stream_cntl_ext[i]);
        }
    }

    BEGIN_CS(size);
    OUT_CS_REG_SEQ(R300_VAP_PROG_STREAM_CNTL_0, streams->count);
    OUT_CS_TABLE(streams->vap_prog_stream_cntl, streams->count);
    OUT_CS_REG_SEQ(R300_VAP_PROG_STREAM_CNTL_EXT_0, streams->count);
    OUT_CS_TABLE(streams->vap_prog_stream_cntl_ext, streams->count);
    END_CS;
}
Exemplo n.º 2
0
void r300_emit_vs_state(struct r300_context* r300, unsigned size, void* state)
{
    struct r300_vertex_shader* vs = (struct r300_vertex_shader*)state;
    struct r300_vertex_program_code* code = &vs->code;
    struct r300_screen* r300screen = r300->screen;
    unsigned instruction_count = code->length / 4;

    unsigned vtx_mem_size = r300screen->caps.is_r500 ? 128 : 72;
    unsigned input_count = MAX2(util_bitcount(code->InputsRead), 1);
    unsigned output_count = MAX2(util_bitcount(code->OutputsWritten), 1);
    unsigned temp_count = MAX2(code->num_temporaries, 1);

    unsigned pvs_num_slots = MIN3(vtx_mem_size / input_count,
                                  vtx_mem_size / output_count, 10);
    unsigned pvs_num_controllers = MIN2(vtx_mem_size / temp_count, 5);

    CS_LOCALS(r300);

    BEGIN_CS(size);

    /* R300_VAP_PVS_CODE_CNTL_0
     * R300_VAP_PVS_CONST_CNTL
     * R300_VAP_PVS_CODE_CNTL_1
     * See the r5xx docs for instructions on how to use these. */
    OUT_CS_REG(R300_VAP_PVS_CODE_CNTL_0, R300_PVS_FIRST_INST(0) |
	       R300_PVS_XYZW_VALID_INST(instruction_count - 1) |
	       R300_PVS_LAST_INST(instruction_count - 1));
    OUT_CS_REG(R300_VAP_PVS_CODE_CNTL_1, instruction_count - 1);

    OUT_CS_REG(R300_VAP_PVS_VECTOR_INDX_REG, 0);
    OUT_CS_ONE_REG(R300_VAP_PVS_UPLOAD_DATA, code->length);
    OUT_CS_TABLE(code->body.d, code->length);

    OUT_CS_REG(R300_VAP_CNTL, R300_PVS_NUM_SLOTS(pvs_num_slots) |
            R300_PVS_NUM_CNTLRS(pvs_num_controllers) |
            R300_PVS_NUM_FPUS(r300screen->caps.num_vert_fpus) |
            R300_PVS_VF_MAX_VTX_NUM(12) |
            (r300->clip_halfz ? R300_DX_CLIP_SPACE_DEF : 0) |
            (r300screen->caps.is_r500 ? R500_TCL_STATE_OPTIMIZATION : 0));

    /* Emit flow control instructions.  Even if there are no fc instructions,
     * we still need to write the registers to make sure they are cleared. */
    OUT_CS_REG(R300_VAP_PVS_FLOW_CNTL_OPC, code->fc_ops);
    if (r300screen->caps.is_r500) {
        OUT_CS_REG_SEQ(R500_VAP_PVS_FLOW_CNTL_ADDRS_LW_0, R300_VS_MAX_FC_OPS * 2);
        OUT_CS_TABLE(code->fc_op_addrs.r500, R300_VS_MAX_FC_OPS * 2);
    } else {
        OUT_CS_REG_SEQ(R300_VAP_PVS_FLOW_CNTL_ADDRS_0, R300_VS_MAX_FC_OPS);
        OUT_CS_TABLE(code->fc_op_addrs.r300, R300_VS_MAX_FC_OPS);
    }
    OUT_CS_REG_SEQ(R300_VAP_PVS_FLOW_CNTL_LOOP_INDEX_0, R300_VS_MAX_FC_OPS);
    OUT_CS_TABLE(code->fc_loop_index, R300_VS_MAX_FC_OPS);

    END_CS;
}
Exemplo n.º 3
0
static void r300_emit_draw_arrays(struct r300_context *r300,
                                  unsigned mode,
                                  unsigned count)
{
    boolean alt_num_verts = count > 65535;
    CS_LOCALS(r300);

    if (count >= (1 << 24)) {
        fprintf(stderr, "r300: Got a huge number of vertices: %i, "
                "refusing to render.\n", count);
        return;
    }

    BEGIN_CS(7 + (alt_num_verts ? 2 : 0));
    if (alt_num_verts) {
        OUT_CS_REG(R500_VAP_ALT_NUM_VERTICES, count);
    }
    OUT_CS_REG(R300_GA_COLOR_CONTROL,
            r300_provoking_vertex_fixes(r300, mode));
    OUT_CS_REG_SEQ(R300_VAP_VF_MAX_VTX_INDX, 2);
    OUT_CS(count - 1);
    OUT_CS(0);
    OUT_CS_PKT3(R300_PACKET3_3D_DRAW_VBUF_2, 0);
    OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_LIST | (count << 16) |
           r300_translate_primitive(mode) |
           (alt_num_verts ? R500_VAP_VF_CNTL__USE_ALT_NUM_VERTS : 0));
    END_CS;
}
Exemplo n.º 4
0
void r300_emit_fs_rc_constant_state(struct r300_context* r300, unsigned size, void *state)
{
    struct r300_fragment_shader *fs = r300_fs(r300);
    struct rc_constant_list *constants = &fs->shader->code.constants;
    unsigned i;
    unsigned count = fs->shader->rc_state_count;
    unsigned first = fs->shader->externals_count;
    unsigned end = constants->Count;
    unsigned j;
    CS_LOCALS(r300);

    if (count == 0)
        return;

    BEGIN_CS(size);
    for(i = first; i < end; ++i) {
        if (constants->Constants[i].Type == RC_CONSTANT_STATE) {
            float data[4];

            get_rc_constant_state(data, r300, &constants->Constants[i]);

            OUT_CS_REG_SEQ(R300_PFS_PARAM_0_X + i * 16, 4);
            for (j = 0; j < 4; j++)
                OUT_CS(pack_float24(data[j]));
        }
    }
    END_CS;
}
Exemplo n.º 5
0
void r300_emit_fs_constants(struct r300_context* r300, unsigned size, void *state)
{
    struct r300_fragment_shader *fs = r300_fs(r300);
    struct r300_constant_buffer *buf = (struct r300_constant_buffer*)state;
    unsigned count = fs->shader->externals_count;
    unsigned i, j;
    CS_LOCALS(r300);

    if (count == 0)
        return;

    BEGIN_CS(size);
    OUT_CS_REG_SEQ(R300_PFS_PARAM_0_X, count * 4);
    if (buf->remap_table){
        for (i = 0; i < count; i++) {
            float *data = (float*)&buf->ptr[buf->remap_table[i]*4];
            for (j = 0; j < 4; j++)
                OUT_CS(pack_float24(data[j]));
        }
    } else {
        for (i = 0; i < count; i++)
            for (j = 0; j < 4; j++)
                OUT_CS(pack_float24(*(float*)&buf->ptr[i*4+j]));
    }

    END_CS;
}
Exemplo n.º 6
0
void r300_emit_rs_block_state(struct r300_context* r300,
                              unsigned size, void* state)
{
    struct r300_rs_block* rs = (struct r300_rs_block*)state;
    unsigned i;
    /* It's the same for both INST and IP tables */
    unsigned count = (rs->inst_count & R300_RS_INST_COUNT_MASK) + 1;
    CS_LOCALS(r300);

    if (DBG_ON(r300, DBG_RS_BLOCK)) {
        r500_dump_rs_block(rs);

        fprintf(stderr, "r300: RS emit:\n");

        for (i = 0; i < count; i++)
            fprintf(stderr, "    : ip %d: 0x%08x\n", i, rs->ip[i]);

        for (i = 0; i < count; i++)
            fprintf(stderr, "    : inst %d: 0x%08x\n", i, rs->inst[i]);

        fprintf(stderr, "    : count: 0x%08x inst_count: 0x%08x\n",
            rs->count, rs->inst_count);
    }

    BEGIN_CS(size);
    OUT_CS_REG_SEQ(R300_VAP_VTX_STATE_CNTL, 2);
    OUT_CS(rs->vap_vtx_state_cntl);
    OUT_CS(rs->vap_vsm_vtx_assm);
    OUT_CS_REG_SEQ(R300_VAP_OUTPUT_VTX_FMT_0, 2);
    OUT_CS(rs->vap_out_vtx_fmt[0]);
    OUT_CS(rs->vap_out_vtx_fmt[1]);
    OUT_CS_REG_SEQ(R300_GB_ENABLE, 1);
    OUT_CS(rs->gb_enable);

    if (r300->screen->caps.is_r500) {
        OUT_CS_REG_SEQ(R500_RS_IP_0, count);
    } else {
        OUT_CS_REG_SEQ(R300_RS_IP_0, count);
    }
    OUT_CS_TABLE(rs->ip, count);

    OUT_CS_REG_SEQ(R300_RS_COUNT, 2);
    OUT_CS(rs->count);
    OUT_CS(rs->inst_count);

    if (r300->screen->caps.is_r500) {
        OUT_CS_REG_SEQ(R500_RS_INST_0, count);
    } else {
        OUT_CS_REG_SEQ(R300_RS_INST_0, count);
    }
    OUT_CS_TABLE(rs->inst, count);
    END_CS;
}
Exemplo n.º 7
0
static void r300_end_query(struct pipe_context* pipe,
                           struct pipe_query* query)
{
    struct r300_context* r300 = r300_context(pipe);
    struct r300_query* q = (struct r300_query*)query;
    CS_LOCALS(r300);

    BEGIN_CS(4);
    OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1);
    OUT_CS_RELOC(q->buf, 0, 0, RADEON_GEM_DOMAIN_GTT, 0);
    END_CS;
}
Exemplo n.º 8
0
void r300_emit_viewport_state(struct r300_context* r300,
                              unsigned size, void* state)
{
    struct r300_viewport_state* viewport = (struct r300_viewport_state*)state;
    CS_LOCALS(r300);

    BEGIN_CS(size);
    OUT_CS_REG_SEQ(R300_SE_VPORT_XSCALE, 6);
    OUT_CS_TABLE(&viewport->xscale, 6);
    OUT_CS_REG(R300_VAP_VTE_CNTL, viewport->vte_control);
    END_CS;
}
Exemplo n.º 9
0
static void r300_emit_draw_init(struct r300_context *r300, unsigned mode,
                                unsigned max_index)
{
    CS_LOCALS(r300);

    assert(max_index < (1 << 24));

    BEGIN_CS(5);
    OUT_CS_REG(R300_GA_COLOR_CONTROL,
            r300_provoking_vertex_fixes(r300, mode));
    OUT_CS_REG_SEQ(R300_VAP_VF_MAX_VTX_INDX, 2);
    OUT_CS(max_index);
    OUT_CS(0);
    END_CS;
}
Exemplo n.º 10
0
void r300_emit_scissor_state(struct r300_context* r300,
                             unsigned size, void* state)
{
    struct pipe_scissor_state* scissor = (struct pipe_scissor_state*)state;
    CS_LOCALS(r300);

    BEGIN_CS(size);
    OUT_CS_REG_SEQ(R300_SC_CLIPRECT_TL_0, 2);
    if (r300->screen->caps.is_r500) {
        OUT_CS((scissor->minx << R300_CLIPRECT_X_SHIFT) |
               (scissor->miny << R300_CLIPRECT_Y_SHIFT));
        OUT_CS(((scissor->maxx - 1) << R300_CLIPRECT_X_SHIFT) |
               ((scissor->maxy - 1) << R300_CLIPRECT_Y_SHIFT));
    } else {
        OUT_CS(((scissor->minx + 1440) << R300_CLIPRECT_X_SHIFT) |
               ((scissor->miny + 1440) << R300_CLIPRECT_Y_SHIFT));
        OUT_CS(((scissor->maxx + 1440-1) << R300_CLIPRECT_X_SHIFT) |
               ((scissor->maxy + 1440-1) << R300_CLIPRECT_Y_SHIFT));
    }
    END_CS;
}
Exemplo n.º 11
0
void r300_emit_aa_state(struct r300_context *r300, unsigned size, void *state)
{
    struct r300_aa_state *aa = (struct r300_aa_state*)state;
    CS_LOCALS(r300);

    BEGIN_CS(size);
    OUT_CS_REG(R300_GB_AA_CONFIG, aa->aa_config);

    if (aa->dest) {
        OUT_CS_REG_SEQ(R300_RB3D_AARESOLVE_OFFSET, 3);
        OUT_CS(aa->dest->offset);
        OUT_CS(aa->dest->pitch & R300_RB3D_AARESOLVE_PITCH_MASK);
        OUT_CS(R300_RB3D_AARESOLVE_CTL_AARESOLVE_MODE_RESOLVE |
               R300_RB3D_AARESOLVE_CTL_AARESOLVE_ALPHA_AVERAGE);
        OUT_CS_RELOC(aa->dest);
    } else {
        OUT_CS_REG(R300_RB3D_AARESOLVE_CTL, 0);
    }

    END_CS;
}
Exemplo n.º 12
0
void r300_emit_gpu_flush(struct r300_context *r300, unsigned size, void *state)
{
    struct r300_gpu_flush *gpuflush = (struct r300_gpu_flush*)state;
    struct pipe_framebuffer_state* fb =
            (struct pipe_framebuffer_state*)r300->fb_state.state;
    uint32_t height = fb->height;
    uint32_t width = fb->width;
    CS_LOCALS(r300);

    if (r300->cbzb_clear) {
        struct r300_surface *surf = r300_surface(fb->cbufs[0]);

        height = surf->cbzb_height;
        width = surf->cbzb_width;
    }

    DBG(r300, DBG_SCISSOR,
	"r300: Scissor width: %i, height: %i, CBZB clear: %s\n",
	width, height, r300->cbzb_clear ? "YES" : "NO");

    BEGIN_CS(size);

    /* Set up scissors.
     * By writing to the SC registers, SC & US assert idle. */
    OUT_CS_REG_SEQ(R300_SC_SCISSORS_TL, 2);
    if (r300->screen->caps.is_r500) {
        OUT_CS(0);
        OUT_CS(((width  - 1) << R300_SCISSORS_X_SHIFT) |
               ((height - 1) << R300_SCISSORS_Y_SHIFT));
    } else {
        OUT_CS((1440 << R300_SCISSORS_X_SHIFT) |
               (1440 << R300_SCISSORS_Y_SHIFT));
        OUT_CS(((width  + 1440-1) << R300_SCISSORS_X_SHIFT) |
               ((height + 1440-1) << R300_SCISSORS_Y_SHIFT));
    }

    /* Flush CB & ZB caches and wait until the 3D engine is idle and clean. */
    OUT_CS_TABLE(gpuflush->cb_flush_clean, 6);
    END_CS;
}
Exemplo n.º 13
0
static void r300_flush_and_cleanup(struct r300_context *r300, unsigned flags,
                                   struct pipe_fence_handle **fence)
{
    struct r300_atom *atom;

    r300_emit_hyperz_end(r300);
    r300_emit_query_end(r300);
    if (r300->screen->caps.is_r500)
        r500_emit_index_bias(r300, 0);

    /* The DDX doesn't set these regs. */
    if (r300->screen->info.drm_minor >= 6) {
        CS_LOCALS(r300);
        OUT_CS_REG_SEQ(R300_GB_MSPOS0, 2);
        OUT_CS(0x66666666);
        OUT_CS(0x6666666);
    }

    r300->flush_counter++;
    r300->rws->cs_flush(r300->cs, flags, fence, 0);
    r300->dirty_hw = 0;

    /* New kitchen sink, baby. */
    foreach_atom(r300, atom) {
        if (atom->state || atom->allow_null_state) {
            r300_mark_atom_dirty(r300, atom);
        }
    }
    r300->vertex_arrays_dirty = TRUE;

    /* Unmark HWTCL state for SWTCL. */
    if (!r300->screen->caps.has_tcl) {
        r300->vs_state.dirty = FALSE;
        r300->vs_constants.dirty = FALSE;
        r300->clip_state.dirty = FALSE;
    }
}
Exemplo n.º 14
0
void r300_emit_fb_state_pipelined(struct r300_context *r300,
                                  unsigned size, void *state)
{
    struct pipe_framebuffer_state* fb =
            (struct pipe_framebuffer_state*)r300->fb_state.state;
    unsigned i, num_cbufs = fb->nr_cbufs;
    unsigned mspos0, mspos1;
    CS_LOCALS(r300);

    /* If we use the multiwrite feature, the colorbuffers 2,3,4 must be
     * marked as UNUSED in the US block. */
    if (r300->fb_multiwrite) {
        num_cbufs = MIN2(num_cbufs, 1);
    }

    BEGIN_CS(size);

    /* Colorbuffer format in the US block.
     * (must be written after unpipelined regs) */
    OUT_CS_REG_SEQ(R300_US_OUT_FMT_0, 4);
    for (i = 0; i < num_cbufs; i++) {
        OUT_CS(r300_surface(fb->cbufs[i])->format);
    }
    for (; i < 1; i++) {
        OUT_CS(R300_US_OUT_FMT_C4_8 |
               R300_C0_SEL_B | R300_C1_SEL_G |
               R300_C2_SEL_R | R300_C3_SEL_A);
    }
    for (; i < 4; i++) {
        OUT_CS(R300_US_OUT_FMT_UNUSED);
    }

    /* Multisampling. Depends on framebuffer sample count.
     * These are pipelined regs and as such cannot be moved
     * to the AA state. */
    mspos0 = 0x66666666;
    mspos1 = 0x6666666;

    if (fb->nr_cbufs && fb->cbufs[0]->texture->nr_samples > 1) {
        /* Subsample placement. These may not be optimal. */
        switch (fb->cbufs[0]->texture->nr_samples) {
        case 2:
            mspos0 = 0x33996633;
            mspos1 = 0x6666663;
            break;
        case 3:
            mspos0 = 0x33936933;
            mspos1 = 0x6666663;
            break;
        case 4:
            mspos0 = 0x33939933;
            mspos1 = 0x3966663;
            break;
        case 6:
            mspos0 = 0x22a2aa22;
            mspos1 = 0x2a65672;
            break;
        default:
            debug_printf("r300: Bad number of multisamples!\n");
        }
    }

    OUT_CS_REG_SEQ(R300_GB_MSPOS0, 2);
    OUT_CS(mspos0);
    OUT_CS(mspos1);
    END_CS;
}
Exemplo n.º 15
0
/* This functions is used to draw a rectangle for the blitter module.
 *
 * If we rendered a quad, the pixels on the main diagonal
 * would be computed and stored twice, which makes the clear/copy codepaths
 * somewhat inefficient. Instead we use a rectangular point sprite. */
void r300_blitter_draw_rectangle(struct blitter_context *blitter,
                                 int x1, int y1, int x2, int y2,
                                 float depth,
                                 enum blitter_attrib_type type,
                                 const union pipe_color_union *attrib)
{
    struct r300_context *r300 = r300_context(util_blitter_get_pipe(blitter));
    unsigned last_sprite_coord_enable = r300->sprite_coord_enable;
    unsigned width = x2 - x1;
    unsigned height = y2 - y1;
    unsigned vertex_size =
            type == UTIL_BLITTER_ATTRIB_COLOR || !r300->draw ? 8 : 4;
    unsigned dwords = 13 + vertex_size +
                      (type == UTIL_BLITTER_ATTRIB_TEXCOORD ? 7 : 0);
    static const union pipe_color_union zeros;
    CS_LOCALS(r300);

    /* XXX workaround for a lockup in MSAA resolve on SWTCL chipsets, this
     * function most probably doesn't handle type=NONE correctly */
    if (!r300->screen->caps.has_tcl && type == UTIL_BLITTER_ATTRIB_NONE) {
        util_blitter_draw_rectangle(blitter, x1, y1, x2, y2, depth, type, attrib);
        return;
    }

    if (r300->skip_rendering)
        return;

    if (type == UTIL_BLITTER_ATTRIB_TEXCOORD)
        r300->sprite_coord_enable = 1;

    r300_update_derived_state(r300);

    /* Mark some states we don't care about as non-dirty. */
    r300->viewport_state.dirty = FALSE;

    if (!r300_prepare_for_rendering(r300, PREP_EMIT_STATES, NULL, dwords, 0, 0, -1))
        goto done;

    DBG(r300, DBG_DRAW, "r300: draw_rectangle\n");

    BEGIN_CS(dwords);
    /* Set up GA. */
    OUT_CS_REG(R300_GA_POINT_SIZE, (height * 6) | ((width * 6) << 16));

    if (type == UTIL_BLITTER_ATTRIB_TEXCOORD) {
        /* Set up the GA to generate texcoords. */
        OUT_CS_REG(R300_GB_ENABLE, R300_GB_POINT_STUFF_ENABLE |
                   (R300_GB_TEX_STR << R300_GB_TEX0_SOURCE_SHIFT));
        OUT_CS_REG_SEQ(R300_GA_POINT_S0, 4);
        OUT_CS_32F(attrib->f[0]);
        OUT_CS_32F(attrib->f[3]);
        OUT_CS_32F(attrib->f[2]);
        OUT_CS_32F(attrib->f[1]);
    }

    /* Set up VAP controls. */
    OUT_CS_REG(R300_VAP_CLIP_CNTL, R300_CLIP_DISABLE);
    OUT_CS_REG(R300_VAP_VTE_CNTL, R300_VTX_XY_FMT | R300_VTX_Z_FMT);
    OUT_CS_REG(R300_VAP_VTX_SIZE, vertex_size);
    OUT_CS_REG_SEQ(R300_VAP_VF_MAX_VTX_INDX, 2);
    OUT_CS(1);
    OUT_CS(0);

    /* Draw. */
    OUT_CS_PKT3(R300_PACKET3_3D_DRAW_IMMD_2, vertex_size);
    OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_EMBEDDED | (1 << 16) |
           R300_VAP_VF_CNTL__PRIM_POINTS);

    OUT_CS_32F(x1 + width * 0.5f);
    OUT_CS_32F(y1 + height * 0.5f);
    OUT_CS_32F(depth);
    OUT_CS_32F(1);

    if (vertex_size == 8) {
        if (!attrib)
            attrib = &zeros;
        OUT_CS_TABLE(attrib->f, 4);
    }
    END_CS;

done:
    /* Restore the state. */
    r300_mark_atom_dirty(r300, &r300->rs_state);
    r300_mark_atom_dirty(r300, &r300->viewport_state);

    r300->sprite_coord_enable = last_sprite_coord_enable;
}
Exemplo n.º 16
0
static void r300_emit_draw_elements(struct r300_context *r300,
                                    struct pipe_resource* indexBuffer,
                                    unsigned indexSize,
                                    unsigned minIndex,
                                    unsigned maxIndex,
                                    unsigned mode,
                                    unsigned start,
                                    unsigned count)
{
    uint32_t count_dwords;
    uint32_t offset_dwords = indexSize * start / sizeof(uint32_t);
    boolean alt_num_verts = count > 65535;
    CS_LOCALS(r300);

    if (count >= (1 << 24)) {
        fprintf(stderr, "r300: Got a huge number of vertices: %i, "
                "refusing to render.\n", count);
        return;
    }

    maxIndex = MIN2(maxIndex, r300->vertex_buffer_max_index);

    DBG(r300, DBG_DRAW, "r300: Indexbuf of %u indices, min %u max %u\n",
        count, minIndex, maxIndex);

    BEGIN_CS(13 + (alt_num_verts ? 2 : 0));
    if (alt_num_verts) {
        OUT_CS_REG(R500_VAP_ALT_NUM_VERTICES, count);
    }
    OUT_CS_REG(R300_GA_COLOR_CONTROL,
            r300_provoking_vertex_fixes(r300, mode));
    OUT_CS_REG_SEQ(R300_VAP_VF_MAX_VTX_INDX, 2);
    OUT_CS(maxIndex);
    OUT_CS(minIndex);
    OUT_CS_PKT3(R300_PACKET3_3D_DRAW_INDX_2, 0);
    if (indexSize == 4) {
        count_dwords = count;
        OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (count << 16) |
               R300_VAP_VF_CNTL__INDEX_SIZE_32bit |
               r300_translate_primitive(mode) |
               (alt_num_verts ? R500_VAP_VF_CNTL__USE_ALT_NUM_VERTS : 0));
    } else {
        count_dwords = (count + 1) / 2;
        OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (count << 16) |
               r300_translate_primitive(mode) |
               (alt_num_verts ? R500_VAP_VF_CNTL__USE_ALT_NUM_VERTS : 0));
    }

    /* INDX_BUFFER is a truly special packet3.
     * Unlike most other packet3, where the offset is after the count,
     * the order is reversed, so the relocation ends up carrying the
     * size of the indexbuf instead of the offset.
     */
    OUT_CS_PKT3(R300_PACKET3_INDX_BUFFER, 2);
    OUT_CS(R300_INDX_BUFFER_ONE_REG_WR | (R300_VAP_PORT_IDX0 >> 2) |
           (0 << R300_INDX_BUFFER_SKIP_SHIFT));
    OUT_CS(offset_dwords << 2);
    OUT_CS_BUF_RELOC(indexBuffer, count_dwords,
                     r300_buffer(indexBuffer)->domain, 0);

    END_CS;
}
Exemplo n.º 17
0
static void r300_emit_draw_arrays_immediate(struct r300_context *r300,
                                            unsigned mode,
                                            unsigned start,
                                            unsigned count)
{
    struct pipe_vertex_element* velem;
    struct pipe_vertex_buffer* vbuf;
    unsigned vertex_element_count = r300->velems->count;
    unsigned i, v, vbi;

    /* Size of the vertex, in dwords. */
    unsigned vertex_size = r300->velems->vertex_size_dwords;

    /* The number of dwords for this draw operation. */
    unsigned dwords = 9 + count * vertex_size;

    /* Size of the vertex element, in dwords. */
    unsigned size[PIPE_MAX_ATTRIBS];

    /* Stride to the same attrib in the next vertex in the vertex buffer,
     * in dwords. */
    unsigned stride[PIPE_MAX_ATTRIBS];

    /* Mapped vertex buffers. */
    uint32_t* map[PIPE_MAX_ATTRIBS];
    uint32_t* mapelem[PIPE_MAX_ATTRIBS];
    struct pipe_transfer* transfer[PIPE_MAX_ATTRIBS] = {0};

    CS_LOCALS(r300);

    if (!r300_prepare_for_rendering(r300, PREP_FIRST_DRAW, NULL, dwords, 0, 0))
        return;

    /* Calculate the vertex size, offsets, strides etc. and map the buffers. */
    for (i = 0; i < vertex_element_count; i++) {
        velem = &r300->velems->velem[i];
        size[i] = r300->velems->hw_format_size[i] / 4;
        vbi = velem->vertex_buffer_index;
        vbuf = &r300->vertex_buffer[vbi];
        stride[i] = vbuf->stride / 4;

        /* Map the buffer. */
        if (!transfer[vbi]) {
            map[vbi] = (uint32_t*)pipe_buffer_map(&r300->context,
                                                  vbuf->buffer,
                                                  PIPE_TRANSFER_READ,
						  &transfer[vbi]);
            map[vbi] += (vbuf->buffer_offset / 4) + stride[i] * start;
        }
        mapelem[i] = map[vbi] + (velem->src_offset / 4);
    }

    BEGIN_CS(dwords);
    OUT_CS_REG(R300_GA_COLOR_CONTROL,
            r300_provoking_vertex_fixes(r300, mode));
    OUT_CS_REG(R300_VAP_VTX_SIZE, vertex_size);
    OUT_CS_REG_SEQ(R300_VAP_VF_MAX_VTX_INDX, 2);
    OUT_CS(count - 1);
    OUT_CS(0);
    OUT_CS_PKT3(R300_PACKET3_3D_DRAW_IMMD_2, count * vertex_size);
    OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_EMBEDDED | (count << 16) |
            r300_translate_primitive(mode));

    /* Emit vertices. */
    for (v = 0; v < count; v++) {
        for (i = 0; i < vertex_element_count; i++) {
            OUT_CS_TABLE(&mapelem[i][stride[i] * v], size[i]);
        }
    }
    END_CS;

    /* Unmap buffers. */
    for (i = 0; i < vertex_element_count; i++) {
        vbi = r300->velems->velem[i].vertex_buffer_index;

        if (transfer[vbi]) {
            vbuf = &r300->vertex_buffer[vbi];
            pipe_buffer_unmap(&r300->context, vbuf->buffer, transfer[vbi]);
            transfer[vbi] = NULL;
        }
    }
}
Exemplo n.º 18
0
/* This functions is used to draw a rectangle for the blitter module.
 *
 * If we rendered a quad, the pixels on the main diagonal
 * would be computed and stored twice, which makes the clear/copy codepaths
 * somewhat inefficient. Instead we use a rectangular point sprite. */
static void r300_blitter_draw_rectangle(struct blitter_context *blitter,
                                        unsigned x1, unsigned y1,
                                        unsigned x2, unsigned y2,
                                        float depth,
                                        enum blitter_attrib_type type,
                                        const float attrib[4])
{
    struct r300_context *r300 = r300_context(util_blitter_get_pipe(blitter));
    unsigned last_sprite_coord_enable = r300->sprite_coord_enable;
    unsigned width = x2 - x1;
    unsigned height = y2 - y1;
    unsigned vertex_size =
            type == UTIL_BLITTER_ATTRIB_COLOR || !r300->draw ? 8 : 4;
    unsigned dwords = 13 + vertex_size +
                      (type == UTIL_BLITTER_ATTRIB_TEXCOORD ? 7 : 0);
    const float zeros[4] = {0, 0, 0, 0};
    CS_LOCALS(r300);

    if (type == UTIL_BLITTER_ATTRIB_TEXCOORD)
        r300->sprite_coord_enable = 1;

    r300_update_derived_state(r300);

    /* Mark some states we don't care about as non-dirty. */
    r300->clip_state.dirty = FALSE;
    r300->viewport_state.dirty = FALSE;

    if (!r300_prepare_for_rendering(r300, PREP_FIRST_DRAW, NULL, dwords, 0, 0))
        goto done;

    DBG(r300, DBG_DRAW, "r300: draw_rectangle\n");

    BEGIN_CS(dwords);
    /* Set up GA. */
    OUT_CS_REG(R300_GA_POINT_SIZE, (height * 6) | ((width * 6) << 16));

    if (type == UTIL_BLITTER_ATTRIB_TEXCOORD) {
        /* Set up the GA to generate texcoords. */
        OUT_CS_REG(R300_GB_ENABLE, R300_GB_POINT_STUFF_ENABLE |
                   (R300_GB_TEX_STR << R300_GB_TEX0_SOURCE_SHIFT));
        OUT_CS_REG_SEQ(R300_GA_POINT_S0, 4);
        OUT_CS_32F(attrib[0]);
        OUT_CS_32F(attrib[3]);
        OUT_CS_32F(attrib[2]);
        OUT_CS_32F(attrib[1]);
    }

    /* Set up VAP controls. */
    OUT_CS_REG(R300_VAP_CLIP_CNTL, R300_CLIP_DISABLE);
    OUT_CS_REG(R300_VAP_VTE_CNTL, R300_VTX_XY_FMT | R300_VTX_Z_FMT);
    OUT_CS_REG(R300_VAP_VTX_SIZE, vertex_size);
    OUT_CS_REG_SEQ(R300_VAP_VF_MAX_VTX_INDX, 2);
    OUT_CS(1);
    OUT_CS(0);

    /* Draw. */
    OUT_CS_PKT3(R300_PACKET3_3D_DRAW_IMMD_2, vertex_size);
    OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_EMBEDDED | (1 << 16) |
           R300_VAP_VF_CNTL__PRIM_POINTS);

    OUT_CS_32F(x1 + width * 0.5f);
    OUT_CS_32F(y1 + height * 0.5f);
    OUT_CS_32F(depth);
    OUT_CS_32F(1);

    if (vertex_size == 8) {
        if (!attrib)
            attrib = zeros;
        OUT_CS_TABLE(attrib, 4);
    }
    END_CS;

done:
    /* Restore the state. */
    r300->clip_state.dirty = TRUE;
    r300->rs_state.dirty = TRUE;
    r300->viewport_state.dirty = TRUE;

    r300->sprite_coord_enable = last_sprite_coord_enable;
}
Exemplo n.º 19
0
void r300_emit_fb_state(struct r300_context* r300, unsigned size, void* state)
{
    struct pipe_framebuffer_state* fb = (struct pipe_framebuffer_state*)state;
    struct r300_surface* surf;
    unsigned i;
    uint32_t rb3d_cctl = 0;

    CS_LOCALS(r300);

    BEGIN_CS(size);

    if (r300->screen->caps.is_r500) {
        rb3d_cctl = R300_RB3D_CCTL_INDEPENDENT_COLORFORMAT_ENABLE_ENABLE;
    }
    /* NUM_MULTIWRITES replicates COLOR[0] to all colorbuffers. */
    if (fb->nr_cbufs && r300->fb_multiwrite) {
        rb3d_cctl |= R300_RB3D_CCTL_NUM_MULTIWRITES(fb->nr_cbufs);
    }
    if (r300->cmask_in_use) {
        rb3d_cctl |= R300_RB3D_CCTL_AA_COMPRESSION_ENABLE |
                     R300_RB3D_CCTL_CMASK_ENABLE;
    }

    OUT_CS_REG(R300_RB3D_CCTL, rb3d_cctl);

    /* Set up colorbuffers. */
    for (i = 0; i < fb->nr_cbufs; i++) {
        surf = r300_surface(r300_get_nonnull_cb(fb, i));

        OUT_CS_REG(R300_RB3D_COLOROFFSET0 + (4 * i), surf->offset);
        OUT_CS_RELOC(surf);

        OUT_CS_REG(R300_RB3D_COLORPITCH0 + (4 * i), surf->pitch);
        OUT_CS_RELOC(surf);

        if (r300->cmask_in_use && i == 0) {
            OUT_CS_REG(R300_RB3D_CMASK_OFFSET0, 0);
            OUT_CS_REG(R300_RB3D_CMASK_PITCH0, surf->pitch_cmask);
            OUT_CS_REG(R300_RB3D_COLOR_CLEAR_VALUE, r300->color_clear_value);
            if (r300->screen->caps.is_r500 && r300->screen->info.drm_minor >= 29) {
                OUT_CS_REG_SEQ(R500_RB3D_COLOR_CLEAR_VALUE_AR, 2);
                OUT_CS(r300->color_clear_value_ar);
                OUT_CS(r300->color_clear_value_gb);
            }
        }
    }

    /* Set up the ZB part of the CBZB clear. */
    if (r300->cbzb_clear) {
        surf = r300_surface(fb->cbufs[0]);

        OUT_CS_REG(R300_ZB_FORMAT, surf->cbzb_format);

        OUT_CS_REG(R300_ZB_DEPTHOFFSET, surf->cbzb_midpoint_offset);
        OUT_CS_RELOC(surf);

        OUT_CS_REG(R300_ZB_DEPTHPITCH, surf->cbzb_pitch);
        OUT_CS_RELOC(surf);

        DBG(r300, DBG_CBZB,
            "CBZB clearing cbuf %08x %08x\n", surf->cbzb_format,
            surf->cbzb_pitch);
    }
    /* Set up a zbuffer. */
    else if (fb->zsbuf) {
        surf = r300_surface(fb->zsbuf);

        OUT_CS_REG(R300_ZB_FORMAT, surf->format);

        OUT_CS_REG(R300_ZB_DEPTHOFFSET, surf->offset);
        OUT_CS_RELOC(surf);

        OUT_CS_REG(R300_ZB_DEPTHPITCH, surf->pitch);
        OUT_CS_RELOC(surf);

        if (r300->hyperz_enabled) {
            /* HiZ RAM. */
            OUT_CS_REG(R300_ZB_HIZ_OFFSET, 0);
            OUT_CS_REG(R300_ZB_HIZ_PITCH, surf->pitch_hiz);
            /* Z Mask RAM. (compressed zbuffer) */
            OUT_CS_REG(R300_ZB_ZMASK_OFFSET, 0);
            OUT_CS_REG(R300_ZB_ZMASK_PITCH, surf->pitch_zmask);
        }
    }

    END_CS;
}
Exemplo n.º 20
0
void r300_emit_fb_state_pipelined(struct r300_context *r300,
                                  unsigned size, void *state)
{
    /* The sample coordinates are in the range [0,11], because
     * GB_TILE_CONFIG.SUBPIXEL is set to the 1/12 subpixel precision.
     *
     * Some sample coordinates reach to neighboring pixels and should not be used.
     * (e.g. Y=11)
     *
     * The unused samples must be set to the positions of other valid samples. */
    static unsigned sample_locs_1x[12] = {
        6,6,  6,6,  6,6,  6,6,  6,6,  6,6
    };
    static unsigned sample_locs_2x[12] = {
        3,9,  9,3,  9,3,  9,3,  9,3,  9,3
    };
    static unsigned sample_locs_4x[12] = {
        4,4,  8,8,  2,10,  10,2,  10,2,  10,2
    };
    static unsigned sample_locs_6x[12] = {
        3,1,  7,3,  11,5,  1,7,  5,9,  9,10
    };

    struct pipe_framebuffer_state* fb =
            (struct pipe_framebuffer_state*)r300->fb_state.state;
    unsigned i, num_cbufs = fb->nr_cbufs;
    unsigned mspos0, mspos1;
    CS_LOCALS(r300);

    /* If we use the multiwrite feature, the colorbuffers 2,3,4 must be
     * marked as UNUSED in the US block. */
    if (r300->fb_multiwrite) {
        num_cbufs = MIN2(num_cbufs, 1);
    }

    BEGIN_CS(size);

    /* Colorbuffer format in the US block.
     * (must be written after unpipelined regs) */
    OUT_CS_REG_SEQ(R300_US_OUT_FMT_0, 4);
    for (i = 0; i < num_cbufs; i++) {
        OUT_CS(r300_surface(r300_get_nonnull_cb(fb, i))->format);
    }
    for (; i < 1; i++) {
        OUT_CS(R300_US_OUT_FMT_C4_8 |
               R300_C0_SEL_B | R300_C1_SEL_G |
               R300_C2_SEL_R | R300_C3_SEL_A);
    }
    for (; i < 4; i++) {
        OUT_CS(R300_US_OUT_FMT_UNUSED);
    }

    /* Set sample positions. It depends on the framebuffer sample count.
     * These are pipelined regs and as such cannot be moved to the AA state.
     */
    switch (r300->num_samples) {
    default:
        mspos0 = r300_get_mspos(0, sample_locs_1x);
        mspos1 = r300_get_mspos(1, sample_locs_1x);
        break;
    case 2:
        mspos0 = r300_get_mspos(0, sample_locs_2x);
        mspos1 = r300_get_mspos(1, sample_locs_2x);
        break;
    case 4:
        mspos0 = r300_get_mspos(0, sample_locs_4x);
        mspos1 = r300_get_mspos(1, sample_locs_4x);
        break;
    case 6:
        mspos0 = r300_get_mspos(0, sample_locs_6x);
        mspos1 = r300_get_mspos(1, sample_locs_6x);
        break;
    }

    OUT_CS_REG_SEQ(R300_GB_MSPOS0, 2);
    OUT_CS(mspos0);
    OUT_CS(mspos1);
    END_CS;
}