summaryrefslogtreecommitdiff
path: root/src/r600_atom.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/r600_atom.c')
-rw-r--r--src/r600_atom.c762
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;
+}