/* * Copyright 2010 Jerome Glisse * * 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 r, 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].width >> 3) - 1) | S_028060_SLICE_TILE_MAX(((fb->cb[i].width * 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; int r; 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; int r; 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; int r; 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; int r; 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; int r; 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; int r; 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; int r; 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 r, 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) { int r; 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 r, 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; u32 ninputs; int r, 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__); 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; }