/* * Copyright 2008 Advanced Micro Devices, Inc. * Copyright 2008 Red Hat Inc. * Copyright 2009 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 * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) 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: Dave Airlie * Alex Deucher * Jerome Glisse
*/ #include <linux/kernel.h>
/* check offset */
tmp = r600_fmt_get_nblocksy(format, height) * r600_fmt_get_nblocksx(format, pitch) *
r600_fmt_get_blocksize(format) * nsamples; switch (array_mode) { default: case V_0280A0_ARRAY_LINEAR_GENERAL: case V_0280A0_ARRAY_LINEAR_ALIGNED:
tmp += track->cb_color_view[i] & 0xFF; break; case V_0280A0_ARRAY_1D_TILED_THIN1: case V_0280A0_ARRAY_2D_TILED_THIN1:
tmp += G_028080_SLICE_MAX(track->cb_color_view[i]) * tmp; break;
} if ((tmp + track->cb_color_bo_offset[i]) > radeon_bo_size(track->cb_color_bo[i])) { if (array_mode == V_0280A0_ARRAY_LINEAR_GENERAL) { /* the initial DDX does bad things with the CB size occasionally */ /* it rounds up height too far for slice tile max but the BO is smaller */ /* r600c,g also seem to flush at bad times in some apps resulting in * bogus values here. So for linear just allow anything to avoid breaking * broken userspace.
*/
} else {
dev_warn(p->dev, "%s offset[%d] %d %llu %d %lu too big (%d %d) (%d %d %d)\n",
__func__, i, array_mode,
track->cb_color_bo_offset[i], tmp,
radeon_bo_size(track->cb_color_bo[i]),
pitch, height, r600_fmt_get_nblocksx(format, pitch),
r600_fmt_get_nblocksy(format, height),
r600_fmt_get_blocksize(format)); return -EINVAL;
}
} /* limit max tile */
tmp = (height * pitch) >> 6; if (tmp < slice_tile_max)
slice_tile_max = tmp;
tmp = S_028060_PITCH_TILE_MAX((pitch / 8) - 1) |
S_028060_SLICE_TILE_MAX(slice_tile_max - 1);
ib[track->cb_color_size_idx[i]] = tmp;
/* FMASK/CMASK */ switch (G_0280A0_TILE_MODE(track->cb_color_info[i])) { case V_0280A0_TILE_DISABLE: break; case V_0280A0_FRAG_ENABLE: if (track->nsamples > 1) {
uint32_t tile_max = G_028100_FMASK_TILE_MAX(track->cb_color_mask[i]); /* the tile size is 8x8, but the size is in units of bits.
* for bytes, do just * 8. */
uint32_t bytes = track->nsamples * track->log_nsamples * 8 * (tile_max + 1);
if (bytes + track->cb_color_frag_offset[i] >
radeon_bo_size(track->cb_color_frag_bo[i])) {
dev_warn(p->dev, "%s FMASK_TILE_MAX too large " "(tile_max=%u, bytes=%u, offset=%llu, bo_size=%lu)\n",
__func__, tile_max, bytes,
track->cb_color_frag_offset[i],
radeon_bo_size(track->cb_color_frag_bo[i])); return -EINVAL;
}
}
fallthrough; case V_0280A0_CLEAR_ENABLE:
{
uint32_t block_max = G_028100_CMASK_BLOCK_MAX(track->cb_color_mask[i]); /* One block = 128x128 pixels, one 8x8 tile has 4 bits..
* (128*128) / (8*8) / 2 = 128 bytes per block. */
uint32_t bytes = (block_max + 1) * 128;
/* on legacy kernel we don't perform advanced check */ if (p->rdev == NULL) return 0;
/* check streamout */ if (track->streamout_dirty && track->vgt_strmout_en) { for (i = 0; i < 4; i++) { if (track->vgt_strmout_buffer_en & (1 << i)) { if (track->vgt_strmout_bo[i]) {
u64 offset = (u64)track->vgt_strmout_bo_offset[i] +
(u64)track->vgt_strmout_size[i]; if (offset > radeon_bo_size(track->vgt_strmout_bo[i])) {
DRM_ERROR("streamout %d bo too small: 0x%llx, 0x%lx\n",
i, offset,
radeon_bo_size(track->vgt_strmout_bo[i])); return -EINVAL;
}
} else {
dev_warn(p->dev, "No buffer for streamout %d\n", i); return -EINVAL;
}
}
}
track->streamout_dirty = false;
}
if (track->sx_misc_kill_all_prims) return 0;
/* check that we have a cb for each enabled target, we don't check * shader_mask because it seems mesa isn't always setting it :(
*/ if (track->cb_dirty) {
tmp = track->cb_target_mask;
/* We must check both colorbuffers for RESOLVE. */ if (track->is_resolve) {
tmp |= 0xff;
}
for (i = 0; i < 8; i++) {
u32 format = G_0280A0_FORMAT(track->cb_color_info[i]);
if (format != V_0280A0_COLOR_INVALID &&
(tmp >> (i * 4)) & 0xF) { /* at least one component is enabled */ if (track->cb_color_bo[i] == NULL) {
dev_warn(p->dev, "%s:%d mask 0x%08X | 0x%08X no cb for %d\n",
__func__, __LINE__, track->cb_target_mask, track->cb_shader_mask, i); return -EINVAL;
} /* perform rewrite of CB_COLOR[0-7]_SIZE */
r = r600_cs_track_validate_cb(p, i); if (r) return r;
}
}
track->cb_dirty = false;
}
/* Check depth buffer */ if (track->db_dirty &&
G_028010_FORMAT(track->db_depth_info) != V_028010_DEPTH_INVALID &&
(G_028800_STENCIL_ENABLE(track->db_depth_control) ||
G_028800_Z_ENABLE(track->db_depth_control))) {
r = r600_cs_track_validate_db(p); if (r) return r;
}
return 0;
}
/** * r600_cs_packet_parse_vline() - parse userspace VLINE packet * @p: parser structure holding parsing context. * * This is an R600-specific function for parsing VLINE packets. * Real work is done by r600_cs_common_vline_parse function. * Here we just set up ASIC-specific register table and call * the common implementation function.
*/ staticint r600_cs_packet_parse_vline(struct radeon_cs_parser *p)
{ static uint32_t vline_start_end[2] = {AVIVO_D1MODE_VLINE_START_END,
AVIVO_D2MODE_VLINE_START_END}; static uint32_t vline_status[2] = {AVIVO_D1MODE_VLINE_STATUS,
AVIVO_D2MODE_VLINE_STATUS};
/** * r600_cs_common_vline_parse() - common vline parser * @p: parser structure holding parsing context. * @vline_start_end: table of vline_start_end registers * @vline_status: table of vline_status registers * * Userspace sends a special sequence for VLINE waits. * PACKET0 - VLINE_START_END + value * PACKET3 - WAIT_REG_MEM poll vline status reg * RELOC (P3) - crtc_id in reloc. * * This function parses this and relocates the VLINE START END * and WAIT_REG_MEM packets to the correct crtc. * It also detects a switched off crtc and nulls out the * wait in that case. This function is common for all ASICs that * are R600 and newer. The parsing algorithm is the same, and only * differs in which registers are used. * * Caller is the ASIC-specific function which passes the parser * context and ASIC-specific register table
*/ int r600_cs_common_vline_parse(struct radeon_cs_parser *p,
uint32_t *vline_start_end,
uint32_t *vline_status)
{ struct drm_crtc *crtc; struct radeon_crtc *radeon_crtc; struct radeon_cs_packet p3reloc, wait_reg_mem; int crtc_id; int r;
uint32_t header, h_idx, reg, wait_reg_mem_info; volatile uint32_t *ib;
ib = p->ib.ptr;
/* parse the WAIT_REG_MEM */
r = radeon_cs_packet_parse(p, &wait_reg_mem, p->idx); if (r) return r;
/* check its a WAIT_REG_MEM */ if (wait_reg_mem.type != RADEON_PACKET_TYPE3 ||
wait_reg_mem.opcode != PACKET3_WAIT_REG_MEM) {
DRM_ERROR("vline wait missing WAIT_REG_MEM segment\n"); return -EINVAL;
}
wait_reg_mem_info = radeon_get_ib_value(p, wait_reg_mem.idx + 1); /* bit 4 is reg (0) or mem (1) */ if (wait_reg_mem_info & 0x10) {
DRM_ERROR("vline WAIT_REG_MEM waiting on MEM instead of REG\n"); return -EINVAL;
} /* bit 8 is me (0) or pfp (1) */ if (wait_reg_mem_info & 0x100) {
DRM_ERROR("vline WAIT_REG_MEM waiting on PFP instead of ME\n"); return -EINVAL;
} /* waiting for value to be equal */ if ((wait_reg_mem_info & 0x7) != 0x3) {
DRM_ERROR("vline WAIT_REG_MEM function not equal\n"); return -EINVAL;
} if ((radeon_get_ib_value(p, wait_reg_mem.idx + 2) << 2) != vline_status[0]) {
DRM_ERROR("vline WAIT_REG_MEM bad reg\n"); return -EINVAL;
}
if (radeon_get_ib_value(p, wait_reg_mem.idx + 5) != RADEON_VLINE_STAT) {
DRM_ERROR("vline WAIT_REG_MEM bad bit mask\n"); return -EINVAL;
}
/* jump over the NOP */
r = radeon_cs_packet_parse(p, &p3reloc, p->idx + wait_reg_mem.count + 2); if (r) return r;
idx = pkt->idx + 1;
reg = pkt->reg; for (i = 0; i <= pkt->count; i++, idx++, reg += 4) {
r = r600_packet0_check(p, pkt, idx, reg); if (r) { return r;
}
} return 0;
}
/** * r600_cs_check_reg() - check if register is authorized or not * @p: parser structure holding parsing context * @reg: register we are testing * @idx: index into the cs buffer * * This function will test against r600_reg_safe_bm and return 0 * if register is safe. If register is not flag as safe this function * will test it against a list of register needing special handling.
*/ staticint r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
{ struct r600_cs_track *track = (struct r600_cs_track *)p->track; struct radeon_bo_list *reloc;
u32 m, i, tmp, *ib; int r;
i = (reg >> 7); if (i >= ARRAY_SIZE(r600_reg_safe_bm)) {
dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx); return -EINVAL;
}
m = 1 << ((reg >> 2) & 31); if (!(r600_reg_safe_bm[i] & m)) return 0;
ib = p->ib.ptr; switch (reg) { /* force following reg to 0 in an attempt to disable out buffer * which will need us to better understand how it works to perform * security check on it (Jerome)
*/ case R_0288A8_SQ_ESGS_RING_ITEMSIZE: case R_008C44_SQ_ESGS_RING_SIZE: case R_0288B0_SQ_ESTMP_RING_ITEMSIZE: case R_008C54_SQ_ESTMP_RING_SIZE: case R_0288C0_SQ_FBUF_RING_ITEMSIZE: case R_008C74_SQ_FBUF_RING_SIZE: case R_0288B4_SQ_GSTMP_RING_ITEMSIZE: case R_008C5C_SQ_GSTMP_RING_SIZE: case R_0288AC_SQ_GSVS_RING_ITEMSIZE: case R_008C4C_SQ_GSVS_RING_SIZE: case R_0288BC_SQ_PSTMP_RING_ITEMSIZE: case R_008C6C_SQ_PSTMP_RING_SIZE: case R_0288C4_SQ_REDUC_RING_ITEMSIZE: case R_008C7C_SQ_REDUC_RING_SIZE: case R_0288B8_SQ_VSTMP_RING_ITEMSIZE: case R_008C64_SQ_VSTMP_RING_SIZE: case R_0288C8_SQ_GS_VERT_ITEMSIZE: /* get value to populate the IB don't remove */ /*tmp =radeon_get_ib_value(p, idx);
ib[idx] = 0;*/ break; case SQ_ESGS_RING_BASE: case SQ_GSVS_RING_BASE: case SQ_ESTMP_RING_BASE: case SQ_GSTMP_RING_BASE: case SQ_PSTMP_RING_BASE: case SQ_VSTMP_RING_BASE:
r = radeon_cs_packet_next_reloc(p, &reloc, 0); if (r) {
dev_warn(p->dev, "bad SET_CONTEXT_REG " "0x%04X\n", reg); return -EINVAL;
}
ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff); break; case SQ_CONFIG:
track->sq_config = radeon_get_ib_value(p, idx); break; case R_028800_DB_DEPTH_CONTROL:
track->db_depth_control = radeon_get_ib_value(p, idx);
track->db_dirty = true; break; case R_028010_DB_DEPTH_INFO: if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS) &&
radeon_cs_packet_next_is_pkt3_nop(p)) {
r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm); if (r) {
dev_warn(p->dev, "bad SET_CONTEXT_REG " "0x%04X\n", reg); return -EINVAL;
}
track->db_depth_info = radeon_get_ib_value(p, idx);
ib[idx] &= C_028010_ARRAY_MODE;
track->db_depth_info &= C_028010_ARRAY_MODE; if (reloc->tiling_flags & RADEON_TILING_MACRO) {
ib[idx] |= S_028010_ARRAY_MODE(V_028010_ARRAY_2D_TILED_THIN1);
track->db_depth_info |= S_028010_ARRAY_MODE(V_028010_ARRAY_2D_TILED_THIN1);
} else {
ib[idx] |= S_028010_ARRAY_MODE(V_028010_ARRAY_1D_TILED_THIN1);
track->db_depth_info |= S_028010_ARRAY_MODE(V_028010_ARRAY_1D_TILED_THIN1);
}
} else {
track->db_depth_info = radeon_get_ib_value(p, idx);
}
track->db_dirty = true; break; case R_028004_DB_DEPTH_VIEW:
track->db_depth_view = radeon_get_ib_value(p, idx);
track->db_dirty = true; break; case R_028000_DB_DEPTH_SIZE:
track->db_depth_size = radeon_get_ib_value(p, idx);
track->db_depth_size_idx = idx;
track->db_dirty = true; break; case R_028AB0_VGT_STRMOUT_EN:
track->vgt_strmout_en = radeon_get_ib_value(p, idx);
track->streamout_dirty = true; break; case R_028B20_VGT_STRMOUT_BUFFER_EN:
track->vgt_strmout_buffer_en = radeon_get_ib_value(p, idx);
track->streamout_dirty = true; break; case VGT_STRMOUT_BUFFER_BASE_0: case VGT_STRMOUT_BUFFER_BASE_1: case VGT_STRMOUT_BUFFER_BASE_2: case VGT_STRMOUT_BUFFER_BASE_3:
r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm); if (r) {
dev_warn(p->dev, "bad SET_CONTEXT_REG " "0x%04X\n", reg); return -EINVAL;
}
tmp = (reg - VGT_STRMOUT_BUFFER_BASE_0) / 16;
track->vgt_strmout_bo_offset[tmp] = radeon_get_ib_value(p, idx) << 8;
ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff);
track->vgt_strmout_bo[tmp] = reloc->robj;
track->vgt_strmout_bo_mc[tmp] = reloc->gpu_offset;
track->streamout_dirty = true; break; case VGT_STRMOUT_BUFFER_SIZE_0: case VGT_STRMOUT_BUFFER_SIZE_1: case VGT_STRMOUT_BUFFER_SIZE_2: case VGT_STRMOUT_BUFFER_SIZE_3:
tmp = (reg - VGT_STRMOUT_BUFFER_SIZE_0) / 16; /* size in register is DWs, convert to bytes */
track->vgt_strmout_size[tmp] = radeon_get_ib_value(p, idx) * 4;
track->streamout_dirty = true; break; case CP_COHER_BASE:
r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm); if (r) {
dev_warn(p->dev, "missing reloc for CP_COHER_BASE " "0x%04X\n", reg); return -EINVAL;
}
ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff); break; case R_028238_CB_TARGET_MASK:
track->cb_target_mask = radeon_get_ib_value(p, idx);
track->cb_dirty = true; break; case R_02823C_CB_SHADER_MASK:
track->cb_shader_mask = radeon_get_ib_value(p, idx); break; case R_028C04_PA_SC_AA_CONFIG:
tmp = G_028C04_MSAA_NUM_SAMPLES(radeon_get_ib_value(p, idx));
track->log_nsamples = tmp;
track->nsamples = 1 << tmp;
track->cb_dirty = true; break; case R_028808_CB_COLOR_CONTROL:
tmp = G_028808_SPECIAL_OP(radeon_get_ib_value(p, idx));
track->is_resolve = tmp == V_028808_SPECIAL_RESOLVE_BOX;
track->cb_dirty = true; break; case R_0280A0_CB_COLOR0_INFO: case R_0280A4_CB_COLOR1_INFO: case R_0280A8_CB_COLOR2_INFO: case R_0280AC_CB_COLOR3_INFO: case R_0280B0_CB_COLOR4_INFO: case R_0280B4_CB_COLOR5_INFO: case R_0280B8_CB_COLOR6_INFO: case R_0280BC_CB_COLOR7_INFO: if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS) &&
radeon_cs_packet_next_is_pkt3_nop(p)) {
r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm); if (r) {
dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg); return -EINVAL;
}
tmp = (reg - R_0280A0_CB_COLOR0_INFO) / 4;
track->cb_color_info[tmp] = radeon_get_ib_value(p, idx); if (reloc->tiling_flags & RADEON_TILING_MACRO) {
ib[idx] |= S_0280A0_ARRAY_MODE(V_0280A0_ARRAY_2D_TILED_THIN1);
track->cb_color_info[tmp] |= S_0280A0_ARRAY_MODE(V_0280A0_ARRAY_2D_TILED_THIN1);
} elseif (reloc->tiling_flags & RADEON_TILING_MICRO) {
ib[idx] |= S_0280A0_ARRAY_MODE(V_0280A0_ARRAY_1D_TILED_THIN1);
track->cb_color_info[tmp] |= S_0280A0_ARRAY_MODE(V_0280A0_ARRAY_1D_TILED_THIN1);
}
} else {
tmp = (reg - R_0280A0_CB_COLOR0_INFO) / 4;
track->cb_color_info[tmp] = radeon_get_ib_value(p, idx);
}
track->cb_dirty = true; break; case R_028080_CB_COLOR0_VIEW: case R_028084_CB_COLOR1_VIEW: case R_028088_CB_COLOR2_VIEW: case R_02808C_CB_COLOR3_VIEW: case R_028090_CB_COLOR4_VIEW: case R_028094_CB_COLOR5_VIEW: case R_028098_CB_COLOR6_VIEW: case R_02809C_CB_COLOR7_VIEW:
tmp = (reg - R_028080_CB_COLOR0_VIEW) / 4;
track->cb_color_view[tmp] = radeon_get_ib_value(p, idx);
track->cb_dirty = true; break; case R_028060_CB_COLOR0_SIZE: case R_028064_CB_COLOR1_SIZE: case R_028068_CB_COLOR2_SIZE: case R_02806C_CB_COLOR3_SIZE: case R_028070_CB_COLOR4_SIZE: case R_028074_CB_COLOR5_SIZE: case R_028078_CB_COLOR6_SIZE: case R_02807C_CB_COLOR7_SIZE:
tmp = (reg - R_028060_CB_COLOR0_SIZE) / 4;
track->cb_color_size[tmp] = radeon_get_ib_value(p, idx);
track->cb_color_size_idx[tmp] = idx;
track->cb_dirty = true; break; /* This register were added late, there is userspace * which does provide relocation for those but set * 0 offset. In order to avoid breaking old userspace * we detect this and set address to point to last * CB_COLOR0_BASE, note that if userspace doesn't set * CB_COLOR0_BASE before this register we will report * error. Old userspace always set CB_COLOR0_BASE * before any of this.
*/ case R_0280E0_CB_COLOR0_FRAG: case R_0280E4_CB_COLOR1_FRAG: case R_0280E8_CB_COLOR2_FRAG: case R_0280EC_CB_COLOR3_FRAG: case R_0280F0_CB_COLOR4_FRAG: case R_0280F4_CB_COLOR5_FRAG: case R_0280F8_CB_COLOR6_FRAG: case R_0280FC_CB_COLOR7_FRAG:
tmp = (reg - R_0280E0_CB_COLOR0_FRAG) / 4; if (!radeon_cs_packet_next_is_pkt3_nop(p)) { if (!track->cb_color_base_last[tmp]) {
dev_err(p->dev, "Broken old userspace ? no cb_color0_base supplied before trying to write 0x%08X\n", reg); return -EINVAL;
}
track->cb_color_frag_bo[tmp] = track->cb_color_bo[tmp];
track->cb_color_frag_offset[tmp] = track->cb_color_bo_offset[tmp];
ib[idx] = track->cb_color_base_last[tmp];
} else {
r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm); if (r) {
dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg); return -EINVAL;
}
track->cb_color_frag_bo[tmp] = reloc->robj;
track->cb_color_frag_offset[tmp] = (u64)ib[idx] << 8;
ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff);
} if (G_0280A0_TILE_MODE(track->cb_color_info[tmp])) {
track->cb_dirty = true;
} break; case R_0280C0_CB_COLOR0_TILE: case R_0280C4_CB_COLOR1_TILE: case R_0280C8_CB_COLOR2_TILE: case R_0280CC_CB_COLOR3_TILE: case R_0280D0_CB_COLOR4_TILE: case R_0280D4_CB_COLOR5_TILE: case R_0280D8_CB_COLOR6_TILE: case R_0280DC_CB_COLOR7_TILE:
tmp = (reg - R_0280C0_CB_COLOR0_TILE) / 4; if (!radeon_cs_packet_next_is_pkt3_nop(p)) { if (!track->cb_color_base_last[tmp]) {
dev_err(p->dev, "Broken old userspace ? no cb_color0_base supplied before trying to write 0x%08X\n", reg); return -EINVAL;
}
track->cb_color_tile_bo[tmp] = track->cb_color_bo[tmp];
track->cb_color_tile_offset[tmp] = track->cb_color_bo_offset[tmp];
ib[idx] = track->cb_color_base_last[tmp];
} else {
r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm); if (r) {
dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg); return -EINVAL;
}
track->cb_color_tile_bo[tmp] = reloc->robj;
track->cb_color_tile_offset[tmp] = (u64)ib[idx] << 8;
ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff);
} if (G_0280A0_TILE_MODE(track->cb_color_info[tmp])) {
track->cb_dirty = true;
} break; case R_028100_CB_COLOR0_MASK: case R_028104_CB_COLOR1_MASK: case R_028108_CB_COLOR2_MASK: case R_02810C_CB_COLOR3_MASK: case R_028110_CB_COLOR4_MASK: case R_028114_CB_COLOR5_MASK: case R_028118_CB_COLOR6_MASK: case R_02811C_CB_COLOR7_MASK:
tmp = (reg - R_028100_CB_COLOR0_MASK) / 4;
track->cb_color_mask[tmp] = radeon_get_ib_value(p, idx); if (G_0280A0_TILE_MODE(track->cb_color_info[tmp])) {
track->cb_dirty = true;
} break; case CB_COLOR0_BASE: case CB_COLOR1_BASE: case CB_COLOR2_BASE: case CB_COLOR3_BASE: case CB_COLOR4_BASE: case CB_COLOR5_BASE: case CB_COLOR6_BASE: case CB_COLOR7_BASE:
r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm); if (r) {
dev_warn(p->dev, "bad SET_CONTEXT_REG " "0x%04X\n", reg); return -EINVAL;
}
tmp = (reg - CB_COLOR0_BASE) / 4;
track->cb_color_bo_offset[tmp] = (u64)radeon_get_ib_value(p, idx) << 8;
ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff);
track->cb_color_base_last[tmp] = ib[idx];
track->cb_color_bo[tmp] = reloc->robj;
track->cb_color_bo_mc[tmp] = reloc->gpu_offset;
track->cb_dirty = true; break; case DB_DEPTH_BASE:
r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm); if (r) {
dev_warn(p->dev, "bad SET_CONTEXT_REG " "0x%04X\n", reg); return -EINVAL;
}
track->db_offset = radeon_get_ib_value(p, idx) << 8;
ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff);
track->db_bo = reloc->robj;
track->db_bo_mc = reloc->gpu_offset;
track->db_dirty = true; break; case DB_HTILE_DATA_BASE:
r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm); if (r) {
dev_warn(p->dev, "bad SET_CONTEXT_REG " "0x%04X\n", reg); return -EINVAL;
}
track->htile_offset = (u64)radeon_get_ib_value(p, idx) << 8;
ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff);
track->htile_bo = reloc->robj;
track->db_dirty = true; break; case DB_HTILE_SURFACE:
track->htile_surface = radeon_get_ib_value(p, idx); /* force 8x8 htile width and height */
ib[idx] |= 3;
track->db_dirty = true; break; case SQ_PGM_START_FS: case SQ_PGM_START_ES: case SQ_PGM_START_VS: case SQ_PGM_START_GS: case SQ_PGM_START_PS: case SQ_ALU_CONST_CACHE_GS_0: case SQ_ALU_CONST_CACHE_GS_1: case SQ_ALU_CONST_CACHE_GS_2: case SQ_ALU_CONST_CACHE_GS_3: case SQ_ALU_CONST_CACHE_GS_4: case SQ_ALU_CONST_CACHE_GS_5: case SQ_ALU_CONST_CACHE_GS_6: case SQ_ALU_CONST_CACHE_GS_7: case SQ_ALU_CONST_CACHE_GS_8: case SQ_ALU_CONST_CACHE_GS_9: case SQ_ALU_CONST_CACHE_GS_10: case SQ_ALU_CONST_CACHE_GS_11: case SQ_ALU_CONST_CACHE_GS_12: case SQ_ALU_CONST_CACHE_GS_13: case SQ_ALU_CONST_CACHE_GS_14: case SQ_ALU_CONST_CACHE_GS_15: case SQ_ALU_CONST_CACHE_PS_0: case SQ_ALU_CONST_CACHE_PS_1: case SQ_ALU_CONST_CACHE_PS_2: case SQ_ALU_CONST_CACHE_PS_3: case SQ_ALU_CONST_CACHE_PS_4: case SQ_ALU_CONST_CACHE_PS_5: case SQ_ALU_CONST_CACHE_PS_6: case SQ_ALU_CONST_CACHE_PS_7: case SQ_ALU_CONST_CACHE_PS_8: case SQ_ALU_CONST_CACHE_PS_9: case SQ_ALU_CONST_CACHE_PS_10: case SQ_ALU_CONST_CACHE_PS_11: case SQ_ALU_CONST_CACHE_PS_12: case SQ_ALU_CONST_CACHE_PS_13: case SQ_ALU_CONST_CACHE_PS_14: case SQ_ALU_CONST_CACHE_PS_15: case SQ_ALU_CONST_CACHE_VS_0: case SQ_ALU_CONST_CACHE_VS_1: case SQ_ALU_CONST_CACHE_VS_2: case SQ_ALU_CONST_CACHE_VS_3: case SQ_ALU_CONST_CACHE_VS_4: case SQ_ALU_CONST_CACHE_VS_5: case SQ_ALU_CONST_CACHE_VS_6: case SQ_ALU_CONST_CACHE_VS_7: case SQ_ALU_CONST_CACHE_VS_8: case SQ_ALU_CONST_CACHE_VS_9: case SQ_ALU_CONST_CACHE_VS_10: case SQ_ALU_CONST_CACHE_VS_11: case SQ_ALU_CONST_CACHE_VS_12: case SQ_ALU_CONST_CACHE_VS_13: case SQ_ALU_CONST_CACHE_VS_14: case SQ_ALU_CONST_CACHE_VS_15:
r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm); if (r) {
dev_warn(p->dev, "bad SET_CONTEXT_REG " "0x%04X\n", reg); return -EINVAL;
}
ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff); break; case SX_MEMORY_EXPORT_BASE:
r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm); if (r) {
dev_warn(p->dev, "bad SET_CONFIG_REG " "0x%04X\n", reg); return -EINVAL;
}
ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff); break; case SX_MISC:
track->sx_misc_kill_all_prims = (radeon_get_ib_value(p, idx) & 0x1) != 0; break; default:
dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx); return -EINVAL;
} return 0;
}
nfaces = larray - barray + 1;
}
r600_texture_size(nfaces, blevel, llevel, w0, h0, d0, array_check.nsamples, format,
pitch_align, height_align, base_align,
&l0_size, &mipmap_size); /* using get ib will give us the offset into the texture bo */ if ((l0_size + word2) > radeon_bo_size(texture)) {
dev_warn(p->dev, "texture bo too small ((%d %d) (%d %d) %d %d %d -> %d have %ld)\n",
w0, h0, pitch_align, height_align,
array_check.array_mode, format, word2,
l0_size, radeon_bo_size(texture));
dev_warn(p->dev, "alignments %d %d %d %lld\n", pitch, pitch_align, height_align, base_align); return -EINVAL;
} /* using get ib will give us the offset into the mipmap bo */ if ((mipmap_size + word3) > radeon_bo_size(mipmap)) { /*dev_warn(p->dev, "mipmap bo too small (%d %d %d %d %d %d -> %d have %ld)\n",
w0, h0, format, blevel, nlevels, word3, mipmap_size, radeon_bo_size(texture));*/
} return 0;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.