/* radeon_state.c -- State support for Radeon -*- linux-c -*- */
/*
* Copyright 2000 VA Linux Systems, Inc., Fremont, California.
* All Rights Reserved.
*
* 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 (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 NONINFRINGEMENT. IN NO EVENT SHALL
* PRECISION INSIGHT AND/OR ITS 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:
* Gareth Hughes <gareth@valinux.com>
* Kevin E. Martin <martin@valinux.com>
*/
#include "drmP.h"
#include "drm.h"
#include "drm_sarea.h"
#include "radeon_drm.h"
#include "radeon_drv.h"
/* ================================================================
* Helper functions for client state checking and fixup
*/
static __inline__ int radeon_check_and_fixup_offset(drm_radeon_private_t *
dev_priv,
drm_file_t * filp_priv,
u32 * offset)
{
u64 off = *offset;
u32 fb_end = dev_priv->fb_location + dev_priv->fb_size - 1;
struct drm_radeon_driver_file_fields *radeon_priv;
/* Hrm ... the story of the offset ... So this function converts
* the various ideas of what userland clients might have for an
* offset in the card address space into an offset into the card
* address space :) So with a sane client, it should just keep
* the value intact and just do some boundary checking. However,
* not all clients are sane. Some older clients pass us 0 based
* offsets relative to the start of the framebuffer and some may
* assume the AGP aperture it appended to the framebuffer, so we
* try to detect those cases and fix them up.
*
* Note: It might be a good idea here to make sure the offset lands
* in some "allowed" area to protect things like the PCIE GART...
*/
/* First, the best case, the offset already lands in either the
* framebuffer or the GART mapped space
*/
if (radeon_check_offset(dev_priv, off))
return 0;
/* Ok, that didn't happen... now check if we have a zero based
* offset that fits in the framebuffer + gart space, apply the
* magic offset we get from SETPARAM or calculated from fb_location
*/
if (off < (dev_priv->fb_size + dev_priv->gart_size)) {
radeon_priv = filp_priv->driver_priv;
off += radeon_priv->radeon_fb_delta;
}
/* Finally, assume we aimed at a GART offset if beyond the fb */
if (off > fb_end)
off = off - fb_end - 1 + dev_priv->gart_vm_start;
/* Now recheck and fail if out of bounds */
if (radeon_check_offset(dev_priv, off)) {
DRM_DEBUG("offset fixed up to 0x%x\n", (unsigned int)off);
*offset = off;
return 0;
}
return DRM_ERR(EINVAL);
}
static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t *
dev_priv,
drm_file_t * filp_priv,
int id, u32 *data)
{
switch (id) {
case RADEON_EMIT_PP_MISC:
if (radeon_check_and_fixup_offset(dev_priv, filp_priv,
&data[(RADEON_RB3D_DEPTHOFFSET - RADEON_PP_MISC) / 4])) {
DRM_ERROR("Invalid depth buffer offset\n");
return DRM_ERR(EINVAL);
}
break;
case RADEON_EMIT_PP_CNTL:
if (radeon_check_and_fixup_offset(dev_priv, filp_priv,
&data[(RADEON_RB3D_COLOROFFSET - RADEON_PP_CNTL) / 4])) {
DRM_ERROR("Invalid colour buffer offset\n");
return DRM_ERR(EINVAL);
}
break;
case R200_EMIT_PP_TXOFFSET_0:
case R200_EMIT_PP_TXOFFSET_1:
case R200_EMIT_PP_TXOFFSET_2:
case R200_EMIT_PP_TXOFFSET_3:
case R200_EMIT_PP_TXOFFSET_4:
case R200_EMIT_PP_TXOFFSET_5:
if (radeon_check_and_fixup_offset(dev_priv, filp_priv,
&data[0])) {
DRM_ERROR("Invalid R200 texture offset\n");
return DRM_ERR(EINVAL);
}
break;
case RADEON_EMIT_PP_TXFILTER_0:
case RADEON_EMIT_PP_TXFILTER_1:
case RADEON_EMIT_PP_TXFILTER_2:
if (radeon_check_and_fixup_offset(dev_priv, filp_priv,
&data[(RADEON_PP_TXOFFSET_0 - RADEON_PP_TXFILTER_0) / 4])) {
DRM_ERROR("Invalid R100 texture offset\n");
return DRM_ERR(EINVAL);
}
break;
case R200_EMIT_PP_CUBIC_OFFSETS_0:
case R200_EMIT_PP_CUBIC_OFFSETS_1:
case R200_EMIT_PP_CUBIC_OFFSETS_2:
case R200_EMIT_PP_CUBIC_OFFSETS_3:
case R200_EMIT_PP_CUBIC_OFFSETS_4:
case R200_EMIT_PP_CUBIC_OFFSETS_5:{
int i;
for (i = 0; i < 5; i++) {
if (radeon_check_and_fixup_offset(dev_priv,
filp_priv,
&data[i])) {
DRM_ERROR
("Invalid R200 cubic texture offset\n");
return DRM_ERR(EINVAL);
}
}
break;
}
case RADEON_EMIT_PP_CUBIC_OFFSETS_T0:
case RADEON_EMIT_PP_CUBIC_OFFSETS_T1:
case RADEON_EMIT_PP_CUBIC_OFFSETS_T2:{
int i;
for (i = 0; i < 5; i++) {
if (radeon_check_and_fixup_offset(dev_priv,
filp_priv,
&data[i])) {
DRM_ERROR
("Invalid R100 cubic texture offset\n");
return DRM_ERR(EINVAL);
}
}
}
break;
case R200_EMIT_VAP_CTL: {
RING_LOCALS;
BEGIN_RING(2);
OUT_RING_REG(RADEON_SE_TCL_STATE_FLUSH, 0);
ADVANCE_RING();
}
break;
case RADEON_EMIT_RB3D_COLORPITCH:
case RADEON_EMIT_RE_LINE_PATTERN:
case RADEON_EMIT_SE_LINE_WIDTH:
case RADEON_EMIT_PP_LUM_MATRIX:
case RADEON_EMIT_PP_ROT_MATRIX_0:
case RADEON_EMIT_RB3D_STENCILREFMASK:
case RADEON_EMIT_SE_VPORT_XSCALE:
case RADEON_EMIT_SE_CNTL:
case RADEON_EMIT_SE_CNTL_STATUS:
case RADEON_EMIT_RE_MISC:
case RADEON_EMIT_PP_BORDER_COLOR_0:
case RADEON_EMIT_PP_BORDER_COLOR_1:
case RADEON_EMIT_PP_BORDER_COLOR_2:
case RADEON_EMIT_SE_ZBIAS_FACTOR:
case RADEON_EMIT_SE_TCL_OUTPUT_VTX_FMT:
case RADEON_EMIT_SE_TCL_MATERIAL_EMMISSIVE_RED:
case R200_EMIT_PP_TXCBLEND_0:
case R200_EMIT_PP_TXCBLEND_1:
case R200_EMIT_PP_TXCBLEND_2:
case R200_EMIT_PP_TXCBLEND_3:
case R200_EMIT_PP_TXCBLEND_4:
case R200_EMIT_PP_TXCBLEND_5:
case R200_EMIT_PP_TXCBLEND_6:
case R200_EMIT_PP_TXCBLEND_7:
case R200_EMIT_TCL_LIGHT_MODEL_CTL_0:
case R200_EMIT_TFACTOR_0:
case R200_EMIT_VTX_FMT_0:
case R200_EMIT_MATRIX_SELECT_0:
case R200_EMIT_TEX_PROC_CTL_2:
case R200_EMIT_TCL_UCP_VERT_BLEND_CTL:
case R200_EMIT_PP_TXFILTER_0:
case R200_EMIT_PP_TXFILTER_1:
case R200_EMIT_PP_TXFILTER_2:
case R200_EMIT_PP_TXFILTER_3:
case R200_EMIT_PP_TXFILTER_4:
case R200_EMIT_PP_TXFILTER_5:
case R200_EMIT_VTE_CNTL:
case R200_EMIT_OUTPUT_VTX_COMP_SEL:
case R200_EMIT_PP_TAM_DEBUG3:
case R200_EMIT_PP_CNTL_X:
case R200_EMIT_RB3D_DEPTHXY_OFFSET:
case R200_EMIT_RE_AUX_SCISSOR_CNTL:
case R200_EMIT_RE_SCISSOR_TL_0:
case R200_EMIT_RE_SCISSOR_TL_1:
case R200_EMIT_RE_SCISSOR_TL_2:
case R200_EMIT_SE_VAP_CNTL_STATUS:
case R200_EMIT_SE_VTX_STATE_CNTL:
case R200_EMIT_RE_POINTSIZE:
case R200_EMIT_TCL_INPUT_VTX_VECTOR_ADDR_0:
case R200_EMIT_PP_CUBIC_FACES_0:
case R200_EMIT_PP_CUBIC_FACES_1:
case R200_EMIT_PP_CUBIC_FACES_2:
case R200_EMIT_PP_CUBIC_FACES_3:
case R200_EMIT_PP_CUBIC_FACES_4:
case R200_EMIT_PP_CUBIC_FACES_5:
case RADEON_EMIT_PP_TEX_SIZE_0:
case RADEON_EMIT_PP_TEX_SIZE_1:
case RADEON_EMIT_PP_TEX_SIZE_2:
case R200_EMIT_RB3D_BLENDCOLOR:
case R200_EMIT_TCL_POINT_SPRITE_CNTL:
case RADEON_EMIT_PP_CUBIC_FACES_0:
case RADEON_EMIT_PP_CUBIC_FACES_1:
case RADEON_EMIT_PP_CUBIC_FACES_2:
case R200_EMIT_PP_TRI_PERF_CNTL:
case R200_EMIT_PP_AFS_0:
case R200_EMIT_PP_AFS_1:
case R200_EMIT_ATF_TFACTOR:
case R200_EMIT_PP_TXCTLALL_0:
case R200_EMIT_PP_TXCTLALL_1:
case R200_EMIT_PP_TXCTLALL_2:
case R200_EMIT_PP_TXCTLALL_3:
case R200_EMIT_PP_TXCTLALL_4:
case R200_EMIT_PP_TXCTLALL_5:
case R200_EMIT_VAP_PVS_CNTL:
/* These packets don't contain memory offsets */
break;
default:
DRM_ERROR("Unknown state packet ID %d\n", id);
return DRM_ERR(EINVAL);
}
return 0;
}
static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t *
dev_priv,
drm_file_t *filp_priv,
drm_radeon_kcmd_buffer_t *
cmdbuf,
unsigned int *cmdsz)
{
u32 *cmd = (u32 *) cmdbuf->buf;
u32 offset, narrays;
int count, i, k;
*cmdsz = 2 + ((cmd[0] & RADEON_CP_PACKET_COUNT_MASK) >> 16);
if ((cmd[0] & 0xc0000000) != RADEON_CP_PACKET3) {
DRM_ERROR("Not a type 3 packet\n");
return DRM_ERR(EINVAL);
}
if (4 * *cmdsz > cmdbuf->bufsz) {
DRM_ERROR("Packet size larger than size of data provided\n");
return DRM_ERR(EINVAL);
}
switch(cmd[0] & 0xff00) {
/* XXX Are there old drivers needing other packets? */
case RADEON_3D_DRAW_IMMD:
case RADEON_3D_DRAW_VBUF:
case RADEON_3D_DRAW_INDX:
case RADEON_WAIT_FOR_IDLE:
case RADEON_CP_NOP:
case RADEON_3D_CLEAR_ZMASK:
/* case RADEON_CP_NEXT_CHAR:
case RADEON_CP_PLY_NEXTSCAN:
case RADEON_CP_SET_SCISSORS: */ /* probably safe but will never need them? */
/* these packets are safe */
break;
case RADEON_CP_3D_DRAW_IMMD_2:
case RADEON_CP_3D_DRAW_VBUF_2:
case RADEON_CP_3D_DRAW_INDX_2:
case RADEON_3D_CLEAR_HIZ:
/* safe but r200 only */
if (dev_priv->microcode_version != UCODE_R200) {
DRM_ERROR("Invalid 3d packet for r100-class chip\n");
return DRM_ERR(EINVAL);
}
break;
case RADEON_3D_LOAD_VBPNTR:
count = (cmd[0] >> 16) & 0x3fff;
if (count > 18) { /* 12 arrays max */
DRM_ERROR("Too large payload in 3D_LOAD_VBPNTR (count=%d)\n",
count);
return DRM_ERR(EINVAL);
}
/* carefully check packet contents */
narrays = cmd[1] & ~0xc000;
k = 0;
i = 2;
while ((k < narrays) && (i < (count + 2))) {
i++; /* skip attribute field */
if (radeon_check_and_fixup_offset(dev_priv, filp_priv, &cmd[i])) {
DRM_ERROR
("Invalid offset (k=%d i=%d) in 3D_LOAD_VBPNTR packet.\n",
k, i);
return DRM_ERR(EINVAL);
}
k++;
i++;
if (k == narrays)
break;
/* have one more to process, they come in pairs */
if (radeon_check_and_fixup_offset(dev_priv, filp_priv, &cmd[i])) {
DRM_ERROR
("Invalid offset (k=%d i=%d) in 3D_LOAD_VBPNTR packet.\n",
k, i);
return DRM_ERR(EINVAL);
}
k++;
i++;
}
/* do the counts match what we expect ? */
if ((k != narrays) || (i != (count + 2))) {
DRM_ERROR
("Malformed 3D_LOAD_VBPNTR packet (k=%d i=%d narrays=%d count+1=%d).\n",
k, i, narrays, count + 1);
return DRM_ERR(EINVAL);
}
break;
case RADEON_3D_RNDR_GEN_INDX_PRIM:
if (dev_priv->microcode_version != UCODE_R100) {
DRM_ERROR("Invalid 3d packet for r200-class chip\n");
return DRM_ERR(EINVAL);
}
if (radeon_check_and_fixup_offset(dev_priv, filp_priv, &cmd[1])) {
DRM_ERROR("Invalid rndr_gen_indx offset\n");
return DRM_ERR(EINVAL);
}
break;
case RADEON_CP_INDX_BUFFER:
if (dev_priv->microcode_version != UCODE_R200) {
DRM_ERROR("Invalid 3d packet for r100-class chip\n");
return DRM_ERR(EINVAL);
}
if ((cmd[1] & 0x8000ffff) != 0x80000810) {
DRM_ERROR("Invalid indx_buffer reg address %08X\n", cmd[1]);
return DRM_ERR(EINVAL);
}
if (radeon_check_and_fixup_offset(dev_priv, filp_priv, &cmd[2])) {
DRM_ERROR("Invalid indx_buffer offset is %08X\n", cmd[2]);
return DRM_ERR(EINVAL);
}
break;
case RADEON_CNTL_HOSTDATA_BLT:
case RADEON_CNTL_PAINT_MULTI:
case RADEON_CNTL_BITBLT_MULTI:
/* MSB of opcode: next DWORD GUI_CNTL */
if (cmd[1] & (RADEON_GMC_SRC_PITCH_OFFSET_CNTL
| RADEON_GMC_DST_PITCH_OFFSET_CNTL)) {
offset = cmd[2] << 10;
if (radeon_check_and_fixup_offset
(dev_priv, filp_priv, &offset)) {
DRM_ERROR("Invalid first packet offset\n");
return DRM_ERR(EINVAL);
}
cmd[2] = (cmd[2] & 0xffc00000) | offset >> 10;
}
if ((cmd[1] & RADEON_GMC_SRC_PITCH_OFFSET_CNTL) &&
(cmd[1] & RADEON_GMC_DST_PITCH_OFFSET_CNTL)) {
offset = cmd[3] << 10;
if (radeon_check_and_fixup_offset
(dev_priv, filp_priv, &offset)) {
DRM_ERROR("Invalid second packet offset\n");
return DRM_ERR(EINVAL);
}
cmd[3] = (cmd[3] & 0xffc00000) | offset >> 10;
}
break;
default:
DRM_ERROR("Invalid packet type %x\n", cmd[0] & 0xff00);
return DRM_ERR(EINVAL);
}
return 0;
}
/* ================================================================
* CP hardware state programming functions
*/
static __inline__ void radeon_emit_clip_rect(drm_radeon_private_t * dev_priv,
drm_clip_rect_t * box)
{
RING_LOCALS;
DRM_DEBUG(" box: x1=%d y1=%d x2=%d y2=%d\n",
box->x1, box->y1, box->x2, box->y2);
BEGIN_RING(4);
OUT_RING(CP_PACKET0(RADEON_RE_TOP_LEFT, 0));
OUT_RING((box->y1 << 16) | box->x1);
OUT_RING(CP_PACKET0(RADEON_RE_WIDTH_HEIGHT, 0));
OUT_RING(((box->y2 - 1) << 16) | (box->x2 - 1));
ADVANCE_RING();
}
/* Emit 1.1 state
*/
static int radeon_emit_state(drm_radeon_private_t * dev_priv,
drm_file_t * filp_priv,
drm_radeon_context_regs_t * ctx,
drm_radeon_texture_regs_t * tex,
unsigned int dirty)
{
RING_LOCALS;
DRM_DEBUG("dirty=0x%08x\n", dirty);
if (dirty & RADEON_UPLOAD_CONTEXT) {
if (radeon_check_and_fixup_offset(dev_priv, filp_priv,
&ctx->rb3d_depthoffset)) {
DRM_ERROR("Invalid depth buffer offset\n");
return DRM_ERR(EINVAL);
}
if (radeon_check_and_fixup_offset(dev_priv, filp_priv,
&ctx->rb3d_coloroffset)) {
DRM_ERROR("Invalid depth buffer offset\n");
return DRM_ERR(EINVAL);
}
BEGIN_RING(14);
OUT_RING(CP_PACKET0(RADEON_PP_MISC, 6));
OUT_RING(ctx->pp_misc);
OUT_RING(ctx->pp_fog_color);
OUT_RING(ctx->re_solid_color);
OUT_RING(ctx->rb3d_blendcntl);
OUT_RING(ctx->rb3d_depthoffset);
OUT_RING(ctx->rb3d_depthpitch);
OUT_RING(ctx->rb3d_zstencilcntl);
OUT_RING(CP_PACKET0(RADEON_PP_CNTL, 2));
OUT_RING(ctx->pp_cntl);
OUT_RING(ctx->rb3d_cntl);
OUT_RING(ctx->rb3d_coloroffset);
OUT_RING(CP_PACKET0(RADEON_RB3D_COLORPITCH, 0));
OUT_RING(ctx->rb3d_colorpitch);
ADVANCE_RING();
}
if (dirty & RADEON_UPLOAD_VERTFMT) {
BEGIN_RING(2);
OUT_RING(CP_PACKET0(RADEON_SE_COORD_FMT, 0));
OUT_RING(ctx->se_coord_fmt);
ADVANCE_RING();
}
if (dirty & RADEON_UPLOAD_LINE) {
BEGIN_RING(5);
OUT_RING(CP_PACKET0(RADEON_RE_LINE_PATTERN, 1));
OUT_RING(ctx->re_line_pattern);
OUT_RING(ctx->re_line_state);
OUT_RING(CP_PACKET0(RADEON_SE_LINE_WIDTH, 0));
OUT_RING(ctx->se_line_width);
ADVANCE_RING();
}
if (dirty & RADEON_UPLOAD_BUMPMAP) {
BEGIN_RING(5);
OUT_RING(CP_PACKET0(RADEON_PP_LUM_MATRIX, 0));
OUT_RING(ctx->pp_lum_matrix);
OUT_RING(CP_PACKET0(RADEON_PP_ROT_MATRIX_0, 1));
OUT_RING(ctx->pp_rot_matrix_0);
OUT_RING(ctx->pp_rot_matrix_1);
ADVANCE_RING();
}
if (dirty & RADEON_UPLOAD_MASKS) {
BEGIN_RING(4);
OUT_RING(CP_PACKET0(RADEON_RB3D_STENCILREFMASK, 2));
OUT_RING(ctx->rb3d_stencilrefmask);
OUT_RING(ctx->rb3d_ropcntl);
OUT_RING(ctx->rb3d_planemask);
ADVANCE_RING();
}
if (dirty & RADEON_UPLOAD_VIEWPORT) {
BEGIN_RING(7);
OUT_RING(CP_PACKET0(RADEON_SE_VPORT_XSCALE, 5));
OUT_RING(ctx->se_vport_xscale);
OUT_RING(ctx->se_vport_xoffset);
OUT_RING(ctx->se_vport_yscale);
OUT_RING(ctx->se_vport_yoffset);
OUT_RING(ctx->se_vport_zscale);
OUT_RING(ctx->se_vport_zoffset);
ADVANCE_RING();
}
if (dirty & RADEON_UPLOAD_SETUP) {
BEGIN_RING(4);
OUT_RING(CP_PACKET0(RADEON_SE_CNTL, 0));
OUT_RING(ctx->se_cntl);
OUT_RING(CP_PACKET0(RADEON_SE_CNTL_STATUS, 0));
OUT_RING(ctx->se_cntl_status);
ADVANCE_RING();
}
if (dirty & RADEON_UPLOAD_MISC) {
BEGIN_RING(2);
OUT_RING(CP_PACKET0(RADEON_RE_MISC, 0));
OUT_RING(ctx->re_misc);
ADVANCE_RING();
}
if (dirty & RADEON_UPLOAD_TEX0) {
if (radeon_check_and_fixup_offset(dev_priv, filp_priv,
&tex[0].pp_txoffset)) {
DRM_ERROR("Invalid texture offset for unit 0\n");
return DRM_ERR(EINVAL);
}
BEGIN_RING(9);
OUT_RING(CP_PACKET0(RADEON_PP_TXFILTER_0, 5));
OUT_RING(tex[0].pp_txfilter);
OUT_RING(tex[0].pp_txformat);
OUT_RING(tex[0].pp_txoffset);
OUT_RING(tex[0].pp_txcblend);
OUT_RING(tex[0].pp_txablend);
OUT_RING(tex[0].pp_tfactor);
OUT_RING(CP_PACKET0(RADEON_PP_BORDER_COLOR_0, 0));
OUT_RING(tex[0].pp_border_color);
ADVANCE_RING();
}
if (dirty & RADEON_UPLOAD_TEX1) {
if (radeon_check_and_fixup_offset(dev_priv, filp_priv,
&tex[1].pp_txoffset)) {
DRM_ERROR("Invalid texture offset for unit 1\n");
return DRM_ERR(EINVAL);
}
BEGIN_RING(9);
OUT_RING(CP_PACKET0(RADEON_PP_TXFILTER_1, 5));
OUT_RING(tex[1].pp_txfilter);
OUT_RING(tex[1].pp_txformat);
OUT_RING(tex[1].pp_txoffset);
OUT_RING(tex[1].pp_txcblend);
OUT_RING(tex[1].pp_txablend);
OUT_RING(tex[1].pp_tfactor);
OUT_RING(CP_PACKET0(RADEON_PP_BORDER_COLOR_1, 0));
OUT_RING(tex[1].pp_border_color);
ADVANCE_RING();
}
if (dirty & RADEON_UPLOAD_TEX2) {
if (radeon_check_and_fixup_offset(dev_priv, filp_priv,
&tex[2].pp_txoffset)) {
DRM_ERROR("Invalid texture offset for unit 2\n");
return DRM_ERR(EINVAL);
}
BEGIN_RING(9);
OUT_RING(CP_PACKET0(RADEON_PP_TXFILTER_2, 5));
OUT_RING(tex[2].pp_txfilter);
OUT_RING(tex[2].pp_txformat);
OUT_RING(tex[2].pp_txoffset);
OUT_RING(tex[2].pp_txcblend);
OUT_RING(tex[2].pp_txablend);
OUT_RING(tex[2].pp_tfactor);
OUT_RING(CP_PACKET0(RADEON_PP_BORDER_COLOR_2, 0));
OUT_RING(tex[2].pp_border_color);
ADVANCE_RING();
}
return 0;
}
/* Emit 1.2 state
*/
static int radeon_emit_state2(drm_radeon_private_t * dev_priv,
drm_file_t * filp_priv,
drm_radeon_state_t * state)
{
RING_LOCALS;
if (state->dirty & RADEON_UPLOAD_ZBIAS) {
BEGIN_RING(3);
OUT_RING(CP_PACKET0(RADEON_SE_ZBIAS_FACTOR, 1));
OUT_RING(state->context2.se_zbias_factor);
OUT_RING(state->context2.se_zbias_constant);
ADVANCE_RING();
}
return radeon_emit_state(dev_priv, filp_priv, &state->context,
state->tex, state->dirty);
}
/* New (1.3) state mechanism. 3 commands (packet, scalar, vector) in
* 1.3 cmdbuffers allow all previous state to be updated as well as
* the tcl scalar and vector areas.
*/
static struct {
int start;
int len;
const char *name;
} packet[RADEON_MAX_STATE_PACKETS] = {
{RADEON_PP_MISC, 7, "RADEON_PP_MISC"},
{RADEON_PP_CNTL, 3, "RADEON_PP_CNTL"},
{RADEON_RB3D_COLORPITCH, 1, "RADEON_RB3D_COLORPITCH"},
{RADEON_RE_LINE_PATTERN, 2, "RADEON_RE_LINE_PATTERN"},
{RADEON_SE_LINE_WIDTH, 1, "RADEON_SE_LINE_WIDTH"},
{RADEON_PP_LUM_MATRIX, 1, "RADEON_PP_LUM_MATRIX"},
{RADEON_PP_ROT_MATRIX_0, 2, "RADEON_PP_ROT_MATRIX_0"},
{RADEON_RB3D_STENCILREFMASK, 3, "RADEON_RB3D_STENCILREFMASK"},
{RADEON_SE_VPORT_XSCALE, 6, "RADEON_SE_VPORT_XSCALE"},
{RADEON_SE_CNTL, 2, "RADEON_SE_CNTL"},
{RADEON_SE_CNTL_STATUS, 1, "RADEON_SE_CNTL_STATUS"},
{RADEON_RE_MISC, 1, "RADEON_RE_MISC"},
{RADEON_PP_TXFILTER_0, 6, "RADEON_PP_TXFILTER_0"},
{RADEON_PP_BORDER_COLOR_0, 1, "RADEON_PP_BORDER_COLOR_0"},
{RADEON_PP_TXFILTER_1, 6, "RADEON_PP_TXFILTER_1"},
{RADEON_PP_BORDER_COLOR_1, 1, "RADEON_PP_BORDER_COLOR_1"},
{RADEON_PP_TXFILTER_2, 6, "RADEON_PP_TXFILTER_2"},
{RADEON_PP_BORDER_COLOR_2, 1, "RADEON_PP_BORDER_COLOR_2"},
{RADEON_SE_ZBIAS_FACTOR, 2, "RADEON_SE_ZBIAS_FACTOR"},
{RADEON_SE_TCL_OUTPUT_VTX_FMT, 11, "RADEON_SE_TCL_OUTPUT_VTX_FMT"},
{RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED, 17,
"RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED"},
{R200_PP_TXCBLEND_0, 4, "R200_PP_TXCBLEND_0"},
{R200_PP_TXCBLEND_1, 4, "R200_PP_TXCBLEND_1"},
{R200_PP_TXCBLEND_2, 4, "R200_PP_TXCBLEND_2"},
{R200_PP_TXCBLEND_3, 4, "R200_PP_TXCBLEND_3"},
{R200_PP_TXCBLEND_4, 4, "R200_PP_TXCBLEND_4"},
{R200_PP_TXCBLEND_5, 4, "R200_PP_TXCBLEND_5"},
{R200_PP_TXCBLEND_6, 4, "R200_PP_TXCBLEND_6"},
{R200_PP_TXCBLEND_7, 4, "R200_PP_TXCBLEND_7"},
{R200_SE_TCL_LIGHT_MODEL_CTL_0, 6, "R200_SE_TCL_LIGHT_MODEL_CTL_0"},
{R200_PP_TFACTOR_0, 6, "R200_PP_TFACTOR_0"},
{R200_SE_VTX_FMT_0, 4, "R200_SE_VTX_FMT_0"},
{R200_SE_VAP_CNTL, 1, "R200_SE_VAP_CNTL"},
{R200_SE_TCL_MATRIX_SEL_0, 5, "R200_SE_TCL_MATRIX_SEL_0"},
{R200_SE_TCL_TEX_PROC_CTL_2, 5, "R200_SE_TCL_TEX_PROC_CTL_2"},
|