diff options
Diffstat (limited to 'src/r600_atom.c')
-rw-r--r-- | src/r600_atom.c | 762 |
1 files changed, 762 insertions, 0 deletions
diff --git a/src/r600_atom.c b/src/r600_atom.c new file mode 100644 index 0000000..cc92100 --- /dev/null +++ b/src/r600_atom.c @@ -0,0 +1,762 @@ +/* + * Copyright 2010 Jerome Glisse <glisse@freedesktop.org> + * + * 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 + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, 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 NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR 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. + * + * Authors: + * Jerome Glisse + */ +#include "r600.h" +#include "r600d.h" + +/* + * framebuffer + */ +int r600_framebuffer_emit(struct r600_winsys *rdev, + struct r600_atom *atom, + void *data, + struct radeon_ib *ib) +{ + struct r600_framebuffer *fb = atom->state; + int i, j; + + for (i = 0, j = 0; i < (fb->ncb * 26); i += 26, j++) { + atom->pkts[i + 4] = radeon_ib_reloc(ib, atom->bo[j], fb->cb[i].placements[0] | fb->cb[i].placements[1]); + atom->pkts[i + 18] = radeon_ib_reloc(ib, atom->bo[j], fb->cb[i].placements[0] | fb->cb[i].placements[1]); + atom->pkts[i + 23] = radeon_ib_reloc(ib, atom->bo[j], fb->cb[i].placements[0] | fb->cb[i].placements[1]); + } + if (fb->db_handle) { + atom->pkts[i + 5] = radeon_ib_reloc(ib, atom->bo[j], fb->db_placements[0] | fb->db_placements[1]); + } + return radeon_ib_copy(ib, atom->pkts, atom->npkts); +} + +int r600_framebuffer_create(struct r600_winsys *rdev, struct r600_atom *atom, void *data) +{ + struct r600_framebuffer *fb; + u32 cb_target_mask, cb_shader_mask; + int i; + + fb = malloc(sizeof(struct r600_framebuffer)); + if (fb == NULL) + return -ENOMEM; + memcpy(fb, data, sizeof(struct r600_framebuffer)); + atom->state = fb; + atom->nflushes = 1; + /* take a references on the bo */ + for (i = 0, atom->nbo = 0; i < fb->ncb; i++, atom->nbo++) { + atom->bo[i] = radeon_bo_lookup(rdev, fb->cb[i].handle); + atom->flags[i] = 0x02000040; + if (atom->bo[i] == NULL) { + return -EINVAL; + } + } + if (fb->db_handle) { + atom->bo[atom->nbo] = radeon_bo_lookup(rdev, fb->db_handle); + atom->flags[atom->nbo] = 0x04004000; + if (atom->bo[atom->nbo] == NULL) { + return -EINVAL; + } + atom->nbo++; + } + for (i = 0, cb_target_mask = 0, cb_shader_mask = 0; i < fb->ncb; i++) { + cb_target_mask |= (fb->cb[i].cb_target_mask & 0xf) << (i * 4); + cb_shader_mask |= (fb->cb[i].cb_shader_mask & 0xf) << (i * 4); + /* CB_COLOR0_BASE */ + atom->pkts[atom->npkts++] = PKT3(PKT3_SET_CONTEXT_REG, 1); + atom->pkts[atom->npkts++] = 0x00000010 + i; + atom->pkts[atom->npkts++] = 0x00000000; + atom->pkts[atom->npkts++] = PKT3(PKT3_NOP, 0); + atom->pkts[atom->npkts++] = 0x00000000; + /* CB_COLOR0_SIZE */ + atom->pkts[atom->npkts++] = PKT3(PKT3_SET_CONTEXT_REG, 1); + atom->pkts[atom->npkts++] = 0x00000018 + i; + atom->pkts[atom->npkts++] = + S_028060_PITCH_TILE_MAX((fb->cb[i].stride >> 3) - 1) | + S_028060_SLICE_TILE_MAX(((fb->cb[i].stride * fb->cb[i].height) >> 6) - 1); + /* CB_COLOR0_VIEW */ + atom->pkts[atom->npkts++] = PKT3(PKT3_SET_CONTEXT_REG, 1); + atom->pkts[atom->npkts++] = 0x00000020 + i; + atom->pkts[atom->npkts++] = 0x00000000; + /* CB_COLOR0_INFO */ + atom->pkts[atom->npkts++] = PKT3(PKT3_SET_CONTEXT_REG, 1); + atom->pkts[atom->npkts++] = 0x00000028 + i; + atom->pkts[atom->npkts++] = fb->cb[i].color_info; + /* CB_COLOR0_TILE */ + atom->pkts[atom->npkts++] = PKT3(PKT3_SET_CONTEXT_REG, 1); + atom->pkts[atom->npkts++] = 0x00000030 + i; + atom->pkts[atom->npkts++] = 0x00000000; + atom->pkts[atom->npkts++] = PKT3(PKT3_NOP, 0); + atom->pkts[atom->npkts++] = 0x00000000; + /* CB_COLOR0_FRAG */ + atom->pkts[atom->npkts++] = PKT3(PKT3_SET_CONTEXT_REG, 1); + atom->pkts[atom->npkts++] = 0x00000038 + i; + atom->pkts[atom->npkts++] = 0x00000000; + atom->pkts[atom->npkts++] = PKT3(PKT3_NOP, 0); + atom->pkts[atom->npkts++] = 0x00000000; + /* CB_COLOR0_MASK */ + atom->pkts[atom->npkts++] = PKT3(PKT3_SET_CONTEXT_REG, 1); + atom->pkts[atom->npkts++] = 0x00000040 + i; + atom->pkts[atom->npkts++] = 0x00000000; + } + if (fb->db_handle) { + /* R_02800C_DB_DEPTH_BASE */ + atom->pkts[atom->npkts++] = PKT3(PKT3_SET_CONTEXT_REG, 1); + atom->pkts[atom->npkts++] = 0x00000003; + atom->pkts[atom->npkts++] = 0x00000000; + atom->pkts[atom->npkts++] = PKT3(PKT3_NOP, 0); + atom->pkts[atom->npkts++] = 0x00000000; + } + /* R_028000_DB_DEPTH_SIZE */ + atom->pkts[atom->npkts++] = PKT3(PKT3_SET_CONTEXT_REG, 2); + atom->pkts[atom->npkts++] = 0x00000000; + atom->pkts[atom->npkts++] = fb->db_depth_size; + atom->pkts[atom->npkts++] = fb->db_depth_view; + /* R_028010_DB_DEPTH_INFO */ + atom->pkts[atom->npkts++] = PKT3(PKT3_SET_CONTEXT_REG, 1); + atom->pkts[atom->npkts++] = 0x00000004; + atom->pkts[atom->npkts++] = fb->db_depth_info; + /* R_028D24_DB_HTILE_SURFACE */ + atom->pkts[atom->npkts++] = PKT3(PKT3_SET_CONTEXT_REG, 1); + atom->pkts[atom->npkts++] = 0x00000349; + atom->pkts[atom->npkts++] = fb->db_htile_surface; + /* R_028D34_DB_PREFETCH_LIMIT */ + atom->pkts[atom->npkts++] = PKT3(PKT3_SET_CONTEXT_REG, 1); + atom->pkts[atom->npkts++] = 0x0000034D; + atom->pkts[atom->npkts++] = fb->db_prefetch_limit; + /* PA_SC_GENERIC_SCISSOR_TL */ + atom->pkts[atom->npkts++] = PKT3(PKT3_SET_CONTEXT_REG, 2); + atom->pkts[atom->npkts++] = 0x00000090; + atom->pkts[atom->npkts++] = 0x80000000; + atom->pkts[atom->npkts++] = S_028244_BR_X(fb->width) | S_028244_BR_Y(fb->height); + /* PA_SC_SCREEN_SCISSOR_TL */ + atom->pkts[atom->npkts++] = PKT3(PKT3_SET_CONTEXT_REG, 2); + atom->pkts[atom->npkts++] = 0x0000000C; + atom->pkts[atom->npkts++] = 0x80000000; + atom->pkts[atom->npkts++] = S_028034_BR_X(fb->width) | S_028034_BR_Y(fb->height); + /* PA_SC_WINDOW_OFFSET */ + atom->pkts[atom->npkts++] = PKT3(PKT3_SET_CONTEXT_REG, 2); + atom->pkts[atom->npkts++] = 0x00000081; + atom->pkts[atom->npkts++] = 0x80000000; + atom->pkts[atom->npkts++] = S_028208_BR_X(fb->width) | S_028208_BR_Y(fb->height); + /* CB_TARGET_MASK */ + atom->pkts[atom->npkts++] = PKT3(PKT3_SET_CONTEXT_REG, 2); + atom->pkts[atom->npkts++] = 0x0000008E; + atom->pkts[atom->npkts++] = cb_target_mask; + atom->pkts[atom->npkts++] = cb_shader_mask; + return 0; +} + +/* + * r600_cb_cntl + */ +int r600_cb_cntl_create(struct r600_winsys *rdev, struct r600_atom *atom, void *data) +{ + struct r600_cb_cntl *cb_cntl; + + cb_cntl = malloc(sizeof(struct r600_cb_cntl)); + if (cb_cntl == NULL) + return -ENOMEM; + memcpy(cb_cntl, data, sizeof(struct r600_cb_cntl)); + atom->state = cb_cntl; + /* CB_CLRCMP_CONTROL */ + atom->pkts[atom->npkts++] = PKT3(PKT3_SET_CONTEXT_REG, 4); + atom->pkts[atom->npkts++] = 0x0000030C; + atom->pkts[atom->npkts++] = cb_cntl->cb_clrcmp_control; + atom->pkts[atom->npkts++] = cb_cntl->cb_clrcmp_src; + atom->pkts[atom->npkts++] = cb_cntl->cb_clrcmp_dst; + atom->pkts[atom->npkts++] = cb_cntl->cb_clrcmp_msk; + /* CB_COLOR_CONTROL */ + atom->pkts[atom->npkts++] = PKT3(PKT3_SET_CONTEXT_REG, 1); + atom->pkts[atom->npkts++] = 0x00000202; + atom->pkts[atom->npkts++] = cb_cntl->cb_color_control; + /* CB_CLEAR_RED */ + atom->pkts[atom->npkts++] = PKT3(PKT3_SET_CONTEXT_REG, 4); + atom->pkts[atom->npkts++] = 0x00000048; + atom->pkts[atom->npkts++] = cb_cntl->cb_clear_red; + atom->pkts[atom->npkts++] = cb_cntl->cb_clear_green; + atom->pkts[atom->npkts++] = cb_cntl->cb_clear_blue; + atom->pkts[atom->npkts++] = cb_cntl->cb_clear_alpha; + /* CB_BLEND_RED */ + atom->pkts[atom->npkts++] = PKT3(PKT3_SET_CONTEXT_REG, 4); + atom->pkts[atom->npkts++] = 0x00000105; + atom->pkts[atom->npkts++] = cb_cntl->cb_blend_red; + atom->pkts[atom->npkts++] = cb_cntl->cb_blend_green; + atom->pkts[atom->npkts++] = cb_cntl->cb_blend_blue; + atom->pkts[atom->npkts++] = cb_cntl->cb_blend_alpha; + /* CB_FOG_RED */ + atom->pkts[atom->npkts++] = PKT3(PKT3_SET_CONTEXT_REG, 3); + atom->pkts[atom->npkts++] = 0x00000109; + atom->pkts[atom->npkts++] = cb_cntl->cb_fog_red; + atom->pkts[atom->npkts++] = cb_cntl->cb_fog_green; + atom->pkts[atom->npkts++] = cb_cntl->cb_fog_blue; + return 0; +} + +/* + * rasterizer + */ +int r600_rasterizer_create(struct r600_winsys *rdev, struct r600_atom *atom, void *data) +{ + struct r600_rasterizer *rasterizer; + + rasterizer = malloc(sizeof(struct r600_rasterizer)); + if (rasterizer == NULL) + return -ENOMEM; + memcpy(rasterizer, data, sizeof(struct r600_rasterizer)); + atom->state = rasterizer; + /* PA_SC_MPASS_PS_CNTL */ + atom->pkts[atom->npkts++] = PKT3(PKT3_SET_CONTEXT_REG, 1); + atom->pkts[atom->npkts++] = 0x00000292; + atom->pkts[atom->npkts++] = rasterizer->pa_sc_mpass_ps_cntl; + /* PA_SC_LINE_CNTL */ + atom->pkts[atom->npkts++] = PKT3(PKT3_SET_CONTEXT_REG, 1); + atom->pkts[atom->npkts++] = 0x00000300; + atom->pkts[atom->npkts++] = rasterizer->pa_sc_line_cntl; + /* PA_SC_AA_CONFIG */ + atom->pkts[atom->npkts++] = PKT3(PKT3_SET_CONTEXT_REG, 1); + atom->pkts[atom->npkts++] = 0x00000301; + atom->pkts[atom->npkts++] = rasterizer->pa_sc_aa_config; + /* PA_SC_AA_SAMPLE_LOCS_MCTX */ + atom->pkts[atom->npkts++] = PKT3(PKT3_SET_CONTEXT_REG, 1); + atom->pkts[atom->npkts++] = 0x00000307; + atom->pkts[atom->npkts++] = rasterizer->pa_sc_aa_sample_locs_mctx; + /* PA_SC_AA_MASK */ + atom->pkts[atom->npkts++] = PKT3(PKT3_SET_CONTEXT_REG, 1); + atom->pkts[atom->npkts++] = 0x00000312; + atom->pkts[atom->npkts++] = rasterizer->pa_sc_aa_mask; + /* PA_CL_CLIP_CNTL */ + atom->pkts[atom->npkts++] = PKT3(PKT3_SET_CONTEXT_REG, 1); + atom->pkts[atom->npkts++] = 0x00000204; + atom->pkts[atom->npkts++] = rasterizer->pa_cl_clip_cntl; + /* PA_CL_VS_OUT_CNTL */ + atom->pkts[atom->npkts++] = PKT3(PKT3_SET_CONTEXT_REG, 1); + atom->pkts[atom->npkts++] = 0x00000207; + atom->pkts[atom->npkts++] = rasterizer->pa_cl_vs_out_cntl; + /* PA_CL_NANINF_CNTL */ + atom->pkts[atom->npkts++] = PKT3(PKT3_SET_CONTEXT_REG, 1); + atom->pkts[atom->npkts++] = 0x00000208; + atom->pkts[atom->npkts++] = rasterizer->pa_cl_naninf_cntl; + /* PA_CL_GB_VERT_CLIP_ADJ */ + atom->pkts[atom->npkts++] = PKT3(PKT3_SET_CONTEXT_REG, 4); + atom->pkts[atom->npkts++] = 0x00000303; + atom->pkts[atom->npkts++] = rasterizer->pa_cl_gb_vert_clip_adj; + atom->pkts[atom->npkts++] = rasterizer->pa_cl_gb_vert_disc_adj; + atom->pkts[atom->npkts++] = rasterizer->pa_cl_gb_horz_clip_adj; + atom->pkts[atom->npkts++] = rasterizer->pa_cl_gb_horz_disc_adj; + /* PA_SU_SC_MODE_CNTL */ + atom->pkts[atom->npkts++] = PKT3(PKT3_SET_CONTEXT_REG, 1); + atom->pkts[atom->npkts++] = 0x00000205; + atom->pkts[atom->npkts++] = rasterizer->pa_su_sc_mode_cntl; + /* PA_SU_POINT_SIZE */ + atom->pkts[atom->npkts++] = PKT3(PKT3_SET_CONTEXT_REG, 4); + atom->pkts[atom->npkts++] = 0x00000280; + atom->pkts[atom->npkts++] = rasterizer->pa_su_point_size; + atom->pkts[atom->npkts++] = rasterizer->pa_su_point_minmax; + atom->pkts[atom->npkts++] = rasterizer->pa_su_line_cntl; + atom->pkts[atom->npkts++] = rasterizer->pa_sc_line_stipple; + /* PA_SU_POLY_OFFSET_DB_FMT_CNTL */ + atom->pkts[atom->npkts++] = PKT3(PKT3_SET_CONTEXT_REG, 2); + atom->pkts[atom->npkts++] = 0x0000037E; + atom->pkts[atom->npkts++] = rasterizer->pa_su_poly_offset_db_fmt_cntl; + atom->pkts[atom->npkts++] = rasterizer->pa_su_poly_offset_clamp; + /* PA_SU_POLY_OFFSET_FRONT_SCALE */ + atom->pkts[atom->npkts++] = PKT3(PKT3_SET_CONTEXT_REG, 4); + atom->pkts[atom->npkts++] = 0x00000380; + atom->pkts[atom->npkts++] = rasterizer->pa_su_poly_offset_front_scale; + atom->pkts[atom->npkts++] = rasterizer->pa_su_poly_offset_front_offset; + atom->pkts[atom->npkts++] = rasterizer->pa_su_poly_offset_back_scale; + atom->pkts[atom->npkts++] = rasterizer->pa_su_poly_offset_back_offset; + return 0; +} + +/* + * viewport state + */ +int r600_viewport_create(struct r600_winsys *rdev, struct r600_atom *atom, void *data) +{ + struct r600_viewport *vport; + + vport = malloc(sizeof(struct r600_viewport)); + if (vport == NULL) + return -ENOMEM; + memcpy(vport, data, sizeof(struct r600_viewport)); + atom->state = vport; + /* PA_CL_VPORT_XSCALE_0 */ + atom->pkts[atom->npkts++] = PKT3(PKT3_SET_CONTEXT_REG, 6); + atom->pkts[atom->npkts++] = 0x0000010F; + atom->pkts[atom->npkts++] = vport->pa_cl_vport_xscale_0; + atom->pkts[atom->npkts++] = vport->pa_cl_vport_xoffset_0; + atom->pkts[atom->npkts++] = vport->pa_cl_vport_yscale_0; + atom->pkts[atom->npkts++] = vport->pa_cl_vport_yoffset_0; + atom->pkts[atom->npkts++] = vport->pa_cl_vport_zscale_0; + atom->pkts[atom->npkts++] = vport->pa_cl_vport_zoffset_0; + /* PA_CL_VTE_CNTL */ + atom->pkts[atom->npkts++] = PKT3(PKT3_SET_CONTEXT_REG, 1); + atom->pkts[atom->npkts++] = 0x00000206; + atom->pkts[atom->npkts++] = vport->pa_cl_vte_cntl; + return 0; +} + +/* + * scissor state + */ +int r600_scissor_create(struct r600_winsys *rdev, struct r600_atom *atom, void *data) +{ + struct r600_scissor *scissor; + + scissor = malloc(sizeof(struct r600_scissor)); + if (scissor == NULL) + return -ENOMEM; + memcpy(scissor, data, sizeof(struct r600_scissor)); + atom->state = scissor; + /* PA_SC_VPORT_SCISSOR_0_BR */ + atom->pkts[atom->npkts++] = PKT3(PKT3_SET_CONTEXT_REG, 2); + atom->pkts[atom->npkts++] = 0x00000094; + atom->pkts[atom->npkts++] = scissor->pa_sc_vport_scissor_0_tl; + atom->pkts[atom->npkts++] = scissor->pa_sc_vport_scissor_0_br; + return 0; +} + +/* + * blend state + */ +int r600_blend_create(struct r600_winsys *rdev, struct r600_atom *atom, void *data) +{ + struct r600_blend *blend; + + blend = malloc(sizeof(struct r600_blend)); + if (blend == NULL) + return -ENOMEM; + memcpy(blend, data, sizeof(struct r600_blend)); + atom->state = blend; + /* CB_BLEND0_CONTROL */ + atom->pkts[atom->npkts++] = PKT3(PKT3_SET_CONTEXT_REG, 8); + atom->pkts[atom->npkts++] = 0x000001E0; + atom->pkts[atom->npkts++] = blend->cb_blend0_control; + atom->pkts[atom->npkts++] = blend->cb_blend1_control; + atom->pkts[atom->npkts++] = blend->cb_blend2_control; + atom->pkts[atom->npkts++] = blend->cb_blend3_control; + atom->pkts[atom->npkts++] = blend->cb_blend4_control; + atom->pkts[atom->npkts++] = blend->cb_blend5_control; + atom->pkts[atom->npkts++] = blend->cb_blend6_control; + atom->pkts[atom->npkts++] = blend->cb_blend7_control; + /* CB_BLEND_CONTROL */ + atom->pkts[atom->npkts++] = PKT3(PKT3_SET_CONTEXT_REG, 1); + atom->pkts[atom->npkts++] = 0x00000201; + atom->pkts[atom->npkts++] = blend->cb_blend_control; + return 0; +} + +/* + * r600_constant + */ +int r600_constants_create(struct r600_winsys *rdev, struct r600_atom *atom, void *data) +{ + struct r600_constants *constants; + + constants = malloc(sizeof(struct r600_constants)); + if (constants == NULL) + return -ENOMEM; + memcpy(constants, data, sizeof(struct r600_constants)); + atom->state = constants; + if ((constants->nconstants & 0x3) || (constants->offset & 0x3)) { + fprintf(stderr, "invalid offset or number of constants (0x%08X %d)\n", + constants->offset, constants->nconstants); + return -EINVAL; + } + /* constants */ + atom->pkts[atom->npkts++] = PKT3(PKT3_SET_ALU_CONST, constants->nconstants * 4); + atom->pkts[atom->npkts++] = constants->offset; + memcpy(&atom->pkts[atom->npkts], + (void*)(unsigned long)constants->constants, + constants->nconstants * 4 * 4); + atom->npkts += constants->nconstants * 4; + return 0; +} + + +/* + * depth, stencil, alpha control + */ +int r600_dsa_create(struct r600_winsys *rdev, struct r600_atom *atom, void *data) +{ + struct r600_dsa *dsa; + + dsa = malloc(sizeof(struct r600_dsa)); + if (dsa == NULL) + return -ENOMEM; + memcpy(dsa, data, sizeof(struct r600_dsa)); + atom->state = dsa; + /* DB_STENCIL_CLEAR */ + atom->pkts[atom->npkts++] = PKT3(PKT3_SET_CONTEXT_REG, 2); + atom->pkts[atom->npkts++] = 0x0000000A; + atom->pkts[atom->npkts++] = dsa->db_stencil_clear; + atom->pkts[atom->npkts++] = dsa->db_depth_clear; + /* DB_STENCILREFMASK */ + atom->pkts[atom->npkts++] = PKT3(PKT3_SET_CONTEXT_REG, 2); + atom->pkts[atom->npkts++] = 0x0000010C; + atom->pkts[atom->npkts++] = dsa->db_stencilrefmask; + atom->pkts[atom->npkts++] = dsa->db_stencilrefmask_bf; + /* DB_DEPTH_CONTROL */ + atom->pkts[atom->npkts++] = PKT3(PKT3_SET_CONTEXT_REG, 1); + atom->pkts[atom->npkts++] = 0x00000200; + atom->pkts[atom->npkts++] = dsa->db_depth_control; + /* DB_SHADER_CONTROL */ + atom->pkts[atom->npkts++] = PKT3(PKT3_SET_CONTEXT_REG, 1); + atom->pkts[atom->npkts++] = 0x00000203; + atom->pkts[atom->npkts++] = dsa->db_shader_control; + /* DB_RENDER_CONTROL */ + atom->pkts[atom->npkts++] = PKT3(PKT3_SET_CONTEXT_REG, 2); + atom->pkts[atom->npkts++] = 0x00000343; + atom->pkts[atom->npkts++] = dsa->db_render_control; + atom->pkts[atom->npkts++] = dsa->db_render_override; + /* DB_SRESULTS_COMPARE_STATE1 */ + atom->pkts[atom->npkts++] = PKT3(PKT3_SET_CONTEXT_REG, 2); + atom->pkts[atom->npkts++] = 0x0000034B; + atom->pkts[atom->npkts++] = dsa->db_sresults_compare_state1; + atom->pkts[atom->npkts++] = dsa->db_preload_control; + /* DB_ALPHA_TO_MASK */ + atom->pkts[atom->npkts++] = PKT3(PKT3_SET_CONTEXT_REG, 1); + atom->pkts[atom->npkts++] = 0x00000351; + atom->pkts[atom->npkts++] = dsa->db_alpha_to_mask; + return 0; +} + +/* + * vexter shader + */ +int r600_vs_shader_emit(struct r600_winsys *rdev, + struct r600_atom *atom, + void *data, + struct radeon_ib *ib) +{ + int r; + + atom->pkts[4] = radeon_ib_reloc(ib, atom->bo[0], RADEON_GEM_DOMAIN_GTT); + r = radeon_ib_copy(ib, atom->pkts, atom->npkts); + return r; +} + +int r600_vs_shader_create(struct r600_winsys *rdev, struct r600_atom *atom, void *data) +{ + struct r600_vs_shader *vs_shader; + int i, j; + u32 tmp; + + vs_shader = malloc(sizeof(struct r600_vs_shader)); + if (vs_shader == NULL) + return -ENOMEM; + memcpy(vs_shader, data, sizeof(struct r600_vs_shader)); + atom->bo[0] = radeon_bo_lookup(rdev, vs_shader->handle); + atom->flags[0] = 0x08000000; + if (atom->bo[0] == NULL) { + return -EINVAL; + } + atom->nbo = 1; + atom->nflushes = 1; + atom->state = vs_shader; + /* SQ_PGM_START_VS */ + atom->pkts[atom->npkts++] = PKT3(PKT3_SET_CONTEXT_REG, 1); + atom->pkts[atom->npkts++] = 0x00000216; + atom->pkts[atom->npkts++] = vs_shader->offset; + atom->pkts[atom->npkts++] = PKT3(PKT3_NOP, 0); + atom->pkts[atom->npkts++] = 0x00000000; + /* SQ_PGM_RESOURCES_VS */ + atom->pkts[atom->npkts++] = PKT3(PKT3_SET_CONTEXT_REG, 1); + atom->pkts[atom->npkts++] = 0x0000021A; + atom->pkts[atom->npkts++] = vs_shader->sq_pgm_resources_vs; + /* SQ_PGM_CF_OFFSET_VS */ + atom->pkts[atom->npkts++] = PKT3(PKT3_SET_CONTEXT_REG, 1); + atom->pkts[atom->npkts++] = 0x00000234; + atom->pkts[atom->npkts++] = 0; + /* SPI_VS_OUT_CONFIG */ + tmp = S_0286C4_VS_EXPORT_COUNT(vs_shader->noutputs - 1); + if (vs_shader->fog_output_id < 32) { + tmp |= S_0286C4_VS_OUT_FOG_VEC_ADDR(vs_shader->fog_output_id); + tmp |= S_0286C4_VS_EXPORTS_FOG(1); + } + atom->pkts[atom->npkts++] = PKT3(PKT3_SET_CONTEXT_REG, 1); + atom->pkts[atom->npkts++] = 0x000001B1; + atom->pkts[atom->npkts++] = tmp; + /* SPI_VS_OUT_ID_* */ + atom->pkts[atom->npkts++] = PKT3(PKT3_SET_CONTEXT_REG, 10); + atom->pkts[atom->npkts++] = 0x00000185; + /* set unused field to 255 */ + for (i = vs_shader->noutputs; i < 32; i++) { + vs_shader->output_semantic[i] = 255; + } + for (i = 0; i < 8; i++) { + atom->pkts[atom->npkts] = 0; + for (j = 0; j < 4; j++) { + atom->pkts[atom->npkts] |= vs_shader->output_semantic[(i*4)+j] << (j * 8); + } + atom->npkts++; + } + /* FIXME: why is their 10 vector if we only have 32 outputs ? */ + atom->pkts[atom->npkts++] = 0xFFFFFFFF; + atom->pkts[atom->npkts++] = 0xFFFFFFFF; + return 0; +} + +/* + * fragment shader + */ +int r600_fs_shader_emit(struct r600_winsys *rdev, + struct r600_atom *atom, + void *data, + struct radeon_ib *ib) +{ + atom->pkts[4] = radeon_ib_reloc(ib, atom->bo[0], RADEON_GEM_DOMAIN_GTT); + return radeon_ib_copy(ib, atom->pkts, atom->npkts); +} + +int r600_fs_shader_create(struct r600_winsys *rdev, struct r600_atom *atom, void *data) +{ + struct r600_fs_shader *fs_shader; + u32 ninputs; + int i; + + fs_shader = malloc(sizeof(struct r600_fs_shader)); + if (fs_shader == NULL) + return -ENOMEM; + memcpy(fs_shader, data, sizeof(struct r600_fs_shader)); + atom->state = fs_shader; + atom->bo[0] = radeon_bo_lookup(rdev, fs_shader->handle); + atom->flags[0] = 0x08000000; + if (atom->bo[0] == NULL) { + return -EINVAL; + } + atom->nbo = 1; + atom->nflushes = 1; + /* SQ_PGM_START_PS */ + atom->pkts[atom->npkts++] = PKT3(PKT3_SET_CONTEXT_REG, 1); + atom->pkts[atom->npkts++] = 0x00000210; + atom->pkts[atom->npkts++] = fs_shader->offset; + atom->pkts[atom->npkts++] = PKT3(PKT3_NOP, 0); + atom->pkts[atom->npkts++] = 0x00000000; + /* SQ_PGM_RESOURCES_PS */ + atom->pkts[atom->npkts++] = PKT3(PKT3_SET_CONTEXT_REG, 2); + atom->pkts[atom->npkts++] = 0x00000214; + atom->pkts[atom->npkts++] = fs_shader->sq_pgm_resources_ps; + atom->pkts[atom->npkts++] = fs_shader->sq_pgm_exports_ps; + /* SQ_PGM_CF_OFFSET_PS */ + atom->pkts[atom->npkts++] = PKT3(PKT3_SET_CONTEXT_REG, 1); + atom->pkts[atom->npkts++] = 0x00000233; + atom->pkts[atom->npkts++] = 0; + /* setup pixel shader input */ + ninputs = G_0286CC_NUM_INTERP(fs_shader->spi_ps_in_control_0) + 1; + atom->pkts[atom->npkts++] = PKT3(PKT3_SET_CONTEXT_REG, ninputs); + atom->pkts[atom->npkts++] = 0x00000191; + for (i = 0; i < ninputs; i++) { + atom->pkts[atom->npkts++] = fs_shader->spi_ps_input_cntl[i]; + } + atom->pkts[atom->npkts++] = PKT3(PKT3_SET_CONTEXT_REG, 2); + atom->pkts[atom->npkts++] = 0x000001B3; + atom->pkts[atom->npkts++] = fs_shader->spi_ps_in_control_0; + atom->pkts[atom->npkts++] = fs_shader->spi_ps_in_control_1; + return 0; +} + +/* + * shader resource + */ +int r600_shader_resource_emit(struct r600_winsys *rdev, + struct r600_atom *atom, + void *data, + struct radeon_ib *ib) +{ + struct r600_shader_resource *shader_resource = atom->state; + int i; + + for (i = 0; i < shader_resource->nresource; i++) { + atom->pkts[i * 11 + 10] = radeon_ib_reloc(ib, atom->bo[i], RADEON_GEM_DOMAIN_GTT); + } + return radeon_ib_copy(ib, atom->pkts, atom->npkts); +} + +int r600_shader_resource_create(struct r600_winsys *rdev, struct r600_atom *atom, void *data) +{ + struct r600_shader_resource *shader_resource; + int i; + + shader_resource = malloc(sizeof(struct r600_shader_resource)); + if (shader_resource == NULL) + return -ENOMEM; + memcpy(shader_resource, data, sizeof(struct r600_shader_resource)); + atom->state = shader_resource; + for (i = 0, atom->nbo = 0; i < shader_resource->nresource; i++, atom->nbo++) { + atom->bo[i] = radeon_bo_lookup(rdev, shader_resource->resource[i].handle); + atom->flags[i] = 0x01000000; + if (atom->bo[i] == NULL) + return -EINVAL; + } + atom->nflushes = atom->nbo; + for (i = 0; i < shader_resource->nresource; i++) { + /* SET_RESOURCE */ + atom->pkts[atom->npkts++] = PKT3(PKT3_SET_RESOURCE, 7); + atom->pkts[atom->npkts++] = (shader_resource->resource[i].resource_id + 160) * 7; + atom->pkts[atom->npkts++] = shader_resource->resource[i].sq_vtx_constant_word0; + atom->pkts[atom->npkts++] = shader_resource->resource[i].sq_vtx_constant_word1; + atom->pkts[atom->npkts++] = shader_resource->resource[i].sq_vtx_constant_word2; + atom->pkts[atom->npkts++] = shader_resource->resource[i].sq_vtx_constant_word3; + atom->pkts[atom->npkts++] = shader_resource->resource[i].sq_vtx_constant_word4; + atom->pkts[atom->npkts++] = shader_resource->resource[i].sq_vtx_constant_word5; + atom->pkts[atom->npkts++] = shader_resource->resource[i].sq_vtx_constant_word6; + atom->pkts[atom->npkts++] = PKT3(PKT3_NOP, 0); + atom->pkts[atom->npkts++] = 0x00000000; + } + return 0; +} + +int r600_draw_cmd_size(struct r600_batch *batch) +{ + switch (G_0287F0_SOURCE_SELECT(batch->vgt_draw_initiator)) { + case 2: + return 10; + default: + return 0; + } +} + +int r600_draw_cmd_emit(struct radeon_ib *ib, struct r600_batch *batch) +{ + u32 pkts[32], i = 0; + + switch (G_0287F0_SOURCE_SELECT(batch->vgt_draw_initiator)) { + case 2: + pkts[i++] = PKT3(PKT3_SET_CONFIG_REG, 1); + pkts[i++] = 0x00000256; + pkts[i++] = batch->vgt_primitive_type; + pkts[i++] = PKT3(PKT3_INDEX_TYPE, 0); + pkts[i++] = batch->vgt_dma_index_type; + pkts[i++] = PKT3(PKT3_NUM_INSTANCES, 0); + pkts[i++] = batch->vgt_dma_num_instances; + pkts[i++] = PKT3(PKT3_DRAW_INDEX_AUTO, 1); + pkts[i++] = batch->vgt_num_indices; + pkts[i++] = batch->vgt_draw_initiator; + return radeon_ib_copy(ib, pkts, i); + default: + return 0; + } +} + +void *r600_atom_state(struct r600_atom *atom) +{ + return atom->state; +} + +/* + * r600 atom core functions + */ +struct r600_atom_funcs { + u32 type; + u32 size; + r600_atom_create_t create; + r600_atom_emit_t emit; +}; + +static struct r600_atom_funcs _r600_atom_funcs[] = { + {0, 0, NULL, NULL}, + {R600_ATOM_FRAMEBUFFER, sizeof(struct r600_framebuffer), + &r600_framebuffer_create, &r600_framebuffer_emit}, + {R600_ATOM_RASTERIZER, sizeof(struct r600_rasterizer), + &r600_rasterizer_create, &r600_atom_emit_default}, + {R600_ATOM_CB_CNTL, sizeof(struct r600_cb_cntl), + &r600_cb_cntl_create, &r600_atom_emit_default}, + {R600_ATOM_VIEWPORT, sizeof(struct r600_viewport), + &r600_viewport_create, &r600_atom_emit_default}, + {R600_ATOM_SCISSOR, sizeof(struct r600_scissor), + &r600_scissor_create, &r600_atom_emit_default}, + {R600_ATOM_BLEND, sizeof(struct r600_blend), + &r600_blend_create, &r600_atom_emit_default}, + {R600_ATOM_CONSTANTS, sizeof(struct r600_constants), + &r600_constants_create, &r600_atom_emit_default}, + {R600_ATOM_DSA, sizeof(struct r600_dsa), + &r600_dsa_create, &r600_atom_emit_default}, + {R600_ATOM_VS_SHADER, sizeof(struct r600_vs_shader), + &r600_vs_shader_create, &r600_vs_shader_emit}, + {R600_ATOM_FS_SHADER, sizeof(struct r600_fs_shader), + &r600_fs_shader_create, &r600_fs_shader_emit}, + {R600_ATOM_SHADER_RESOURCE, sizeof(struct r600_shader_resource), + &r600_shader_resource_create, &r600_shader_resource_emit}, +}; + +struct r600_atom *r600_atom_create(struct r600_winsys *rdev, struct r600_request *rq) +{ + struct r600_atom *atom; + int r; + + if (!rq->type || rq->type >= R600_BATCH_NATOMS) { + fprintf(stderr, "%s %d invalid atom type %d\n", __func__, __LINE__, rq->type); + return NULL; + } + if (_r600_atom_funcs[rq->type].type != rq->type) { + fprintf(stderr, "%s %d mismatch for type %d have %d\n", + __func__, __LINE__, _r600_atom_funcs[rq->type].type, rq->type); + return NULL; + } + r600_winsys_set_bo_list(rdev, rq->nbo, rq->bo); + /* create the atom */ + atom = malloc(sizeof(struct r600_atom)); + if (atom == NULL) + return NULL; + memset(atom, 0, sizeof(struct r600_atom)); + atom->refcount = 1; + atom->emit = _r600_atom_funcs[rq->type].emit; + atom->nflushes = 0; + atom->id = crc_64(rq->data, _r600_atom_funcs[rq->type].size); + atom->type = rq->type; + r = _r600_atom_funcs[rq->type].create(rdev, atom, rq->data); + if (r) { + r600_atom_destroy(atom); + return NULL; + } + return atom; +} + +int r600_atom_emit_default(struct r600_winsys *rdev, struct r600_atom *atom, + void *data, struct radeon_ib *ib) +{ + return radeon_ib_copy(ib, atom->pkts, atom->npkts); +} + +void r600_atom_ref(struct r600_atom *atom) +{ + if (atom == NULL) + return; + atom->refcount++; +} + +struct r600_atom *r600_atom_destroy(struct r600_atom *atom) +{ + int i; + + if (atom == NULL) + return NULL; + if (--atom->refcount > 0) + return NULL; + for (i = 0; i < atom->nbo; i++) { + radeon_bo_unref(atom->bo[i]); + } + free(atom->state); + free(atom); + return NULL; +} |