Logo Search packages:      
Sourcecode: xserver-xorg-video-ati version File versions  Download package

radeon_commonfuncs.c

/*
 * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and
 *                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 on 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
 * NON-INFRINGEMENT.  IN NO EVENT SHALL ATI, VA LINUX SYSTEMS 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.
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "ati_pciids_gen.h"

#if defined(ACCEL_MMIO) && defined(ACCEL_CP)
#error Cannot define both MMIO and CP acceleration!
#endif

#if !defined(UNIXCPP) || defined(ANSICPP)
#define FUNC_NAME_CAT(prefix,suffix) prefix##suffix
#else
#define FUNC_NAME_CAT(prefix,suffix) prefix/**/suffix
#endif

#ifdef ACCEL_MMIO
#define FUNC_NAME(prefix) FUNC_NAME_CAT(prefix,MMIO)
#else
#ifdef ACCEL_CP
#define FUNC_NAME(prefix) FUNC_NAME_CAT(prefix,CP)
#else
#error No accel type defined!
#endif
#endif

static void FUNC_NAME(RADEONInit3DEngine)(ScrnInfoPtr pScrn)
{
    RADEONInfoPtr  info       = RADEONPTR(pScrn);
    uint32_t gb_tile_config, su_reg_dest, vap_cntl;
    int size;
    ACCEL_PREAMBLE();

    info->accel_state->texW[0] = info->accel_state->texH[0] =
      info->accel_state->texW[1] = info->accel_state->texH[1] = 1;

    if (IS_R300_3D || IS_R500_3D) {

      if (!info->cs) {
          BEGIN_ACCEL(3);
          OUT_ACCEL_REG(R300_RB3D_DSTCACHE_CTLSTAT, R300_DC_FLUSH_3D | R300_DC_FREE_3D);
          OUT_ACCEL_REG(R300_RB3D_ZCACHE_CTLSTAT, R300_ZC_FLUSH | R300_ZC_FREE);
          OUT_ACCEL_REG(RADEON_WAIT_UNTIL, RADEON_WAIT_2D_IDLECLEAN | RADEON_WAIT_3D_IDLECLEAN);
          FINISH_ACCEL();
      }

      gb_tile_config = (R300_ENABLE_TILING | R300_TILE_SIZE_16);

      switch(info->accel_state->num_gb_pipes) {
      case 2: gb_tile_config |= R300_PIPE_COUNT_R300; break;
      case 3: gb_tile_config |= R300_PIPE_COUNT_R420_3P; break;
      case 4: gb_tile_config |= R300_PIPE_COUNT_R420; break;
      default:
      case 1: gb_tile_config |= R300_PIPE_COUNT_RV350; break;
      }

      if (!info->cs) {
          size = (info->ChipFamily >= CHIP_FAMILY_R420) ? 5 : 4;
          BEGIN_ACCEL(size);
          OUT_ACCEL_REG(R300_GB_TILE_CONFIG, gb_tile_config);
          OUT_ACCEL_REG(RADEON_WAIT_UNTIL, RADEON_WAIT_2D_IDLECLEAN | RADEON_WAIT_3D_IDLECLEAN);
          if (info->ChipFamily >= CHIP_FAMILY_R420)
            OUT_ACCEL_REG(R300_DST_PIPE_CONFIG, R300_PIPE_AUTO_CONFIG);
          OUT_ACCEL_REG(R300_GB_SELECT, 0);
          OUT_ACCEL_REG(R300_GB_ENABLE, 0);
          FINISH_ACCEL();
      }

      if (IS_R500_3D) {
          if (!info->cs) {
            su_reg_dest = ((1 << info->accel_state->num_gb_pipes) - 1);
            BEGIN_ACCEL(2);
            OUT_ACCEL_REG(R500_SU_REG_DEST, su_reg_dest);
            OUT_ACCEL_REG(R500_VAP_INDEX_OFFSET, 0);
            FINISH_ACCEL();
          }
      }

      BEGIN_ACCEL(3);
      OUT_ACCEL_REG(R300_RB3D_DSTCACHE_CTLSTAT, R300_DC_FLUSH_3D | R300_DC_FREE_3D);
      OUT_ACCEL_REG(R300_RB3D_ZCACHE_CTLSTAT, R300_ZC_FLUSH | R300_ZC_FREE);
      OUT_ACCEL_REG(RADEON_WAIT_UNTIL, RADEON_WAIT_2D_IDLECLEAN | RADEON_WAIT_3D_IDLECLEAN);
      FINISH_ACCEL();

      BEGIN_ACCEL(3);
      OUT_ACCEL_REG(R300_GB_AA_CONFIG, 0);
      OUT_ACCEL_REG(R300_RB3D_DSTCACHE_CTLSTAT, R300_DC_FLUSH_3D | R300_DC_FREE_3D);
      OUT_ACCEL_REG(R300_RB3D_ZCACHE_CTLSTAT, R300_ZC_FLUSH | R300_ZC_FREE);
      FINISH_ACCEL();

      if (!info->cs) {
          BEGIN_ACCEL(3);
          OUT_ACCEL_REG(R300_GB_MSPOS0, ((6 << R300_MS_X0_SHIFT) |
                                 (6 << R300_MS_Y0_SHIFT) |
                                 (6 << R300_MS_X1_SHIFT) |
                                 (6 << R300_MS_Y1_SHIFT) |
                                 (6 << R300_MS_X2_SHIFT) |
                                 (6 << R300_MS_Y2_SHIFT) |
                                 (6 << R300_MSBD0_Y_SHIFT) |
                                 (6 << R300_MSBD0_X_SHIFT)));
          OUT_ACCEL_REG(R300_GB_MSPOS1, ((6 << R300_MS_X3_SHIFT) |
                                 (6 << R300_MS_Y3_SHIFT) |
                                 (6 << R300_MS_X4_SHIFT) |
                                 (6 << R300_MS_Y4_SHIFT) |
                                 (6 << R300_MS_X5_SHIFT) |
                                 (6 << R300_MS_Y5_SHIFT) |
                                 (6 << R300_MSBD1_SHIFT)));
          OUT_ACCEL_REG(R300_GA_ENHANCE, R300_GA_DEADLOCK_CNTL | R300_GA_FASTSYNC_CNTL);
          FINISH_ACCEL();
      }

      BEGIN_ACCEL(4);
      OUT_ACCEL_REG(R300_GA_POLY_MODE, R300_FRONT_PTYPE_TRIANGE | R300_BACK_PTYPE_TRIANGE);
      OUT_ACCEL_REG(R300_GA_ROUND_MODE, (R300_GEOMETRY_ROUND_NEAREST |
                                 R300_COLOR_ROUND_NEAREST));
      OUT_ACCEL_REG(R300_GA_COLOR_CONTROL, (R300_RGB0_SHADING_GOURAUD |
                                    R300_ALPHA0_SHADING_GOURAUD |
                                    R300_RGB1_SHADING_GOURAUD |
                                    R300_ALPHA1_SHADING_GOURAUD |
                                    R300_RGB2_SHADING_GOURAUD |
                                    R300_ALPHA2_SHADING_GOURAUD |
                                    R300_RGB3_SHADING_GOURAUD |
                                    R300_ALPHA3_SHADING_GOURAUD));
      OUT_ACCEL_REG(R300_GA_OFFSET, 0);
      FINISH_ACCEL();

      BEGIN_ACCEL(5);
      OUT_ACCEL_REG(R300_SU_TEX_WRAP, 0);
      OUT_ACCEL_REG(R300_SU_POLY_OFFSET_ENABLE, 0);
      OUT_ACCEL_REG(R300_SU_CULL_MODE, R300_FACE_NEG);
      OUT_ACCEL_REG(R300_SU_DEPTH_SCALE, 0x4b7fffff);
      OUT_ACCEL_REG(R300_SU_DEPTH_OFFSET, 0);
      FINISH_ACCEL();

      /* setup the VAP */
      if (info->accel_state->has_tcl)
          vap_cntl = ((5 << R300_PVS_NUM_SLOTS_SHIFT) |
                  (5 << R300_PVS_NUM_CNTLRS_SHIFT) |
                  (9 << R300_VF_MAX_VTX_NUM_SHIFT));
      else
          vap_cntl = ((10 << R300_PVS_NUM_SLOTS_SHIFT) |
                  (5 << R300_PVS_NUM_CNTLRS_SHIFT) |
                  (5 << R300_VF_MAX_VTX_NUM_SHIFT));

      if (info->ChipFamily == CHIP_FAMILY_RV515)
          vap_cntl |= (2 << R300_PVS_NUM_FPUS_SHIFT);
      else if ((info->ChipFamily == CHIP_FAMILY_RV530) ||
             (info->ChipFamily == CHIP_FAMILY_RV560) ||
             (info->ChipFamily == CHIP_FAMILY_RV570))
          vap_cntl |= (5 << R300_PVS_NUM_FPUS_SHIFT);
      else if ((info->ChipFamily == CHIP_FAMILY_RV410) ||
             (info->ChipFamily == CHIP_FAMILY_R420))
          vap_cntl |= (6 << R300_PVS_NUM_FPUS_SHIFT);
      else if ((info->ChipFamily == CHIP_FAMILY_R520) ||
             (info->ChipFamily == CHIP_FAMILY_R580))
          vap_cntl |= (8 << R300_PVS_NUM_FPUS_SHIFT);
      else
          vap_cntl |= (4 << R300_PVS_NUM_FPUS_SHIFT);

      if (info->accel_state->has_tcl)
          BEGIN_ACCEL(15);
      else
          BEGIN_ACCEL(9);
      OUT_ACCEL_REG(R300_VAP_VTX_STATE_CNTL, 0);
      OUT_ACCEL_REG(R300_VAP_PVS_STATE_FLUSH_REG, 0);

      if (info->accel_state->has_tcl)
          OUT_ACCEL_REG(R300_VAP_CNTL_STATUS, 0);
      else
          OUT_ACCEL_REG(R300_VAP_CNTL_STATUS, R300_PVS_BYPASS);
      OUT_ACCEL_REG(R300_VAP_CNTL, vap_cntl);
      OUT_ACCEL_REG(R300_VAP_PVS_STATE_FLUSH_REG, 0);
      OUT_ACCEL_REG(R300_VAP_VTE_CNTL, R300_VTX_XY_FMT | R300_VTX_Z_FMT);
      OUT_ACCEL_REG(R300_VAP_PSC_SGN_NORM_CNTL, 0);

      OUT_ACCEL_REG(R300_VAP_PROG_STREAM_CNTL_EXT_0,
                  ((R300_SWIZZLE_SELECT_X << R300_SWIZZLE_SELECT_X_0_SHIFT) |
                   (R300_SWIZZLE_SELECT_Y << R300_SWIZZLE_SELECT_Y_0_SHIFT) |
                   (R300_SWIZZLE_SELECT_Z << R300_SWIZZLE_SELECT_Z_0_SHIFT) |
                   (R300_SWIZZLE_SELECT_W << R300_SWIZZLE_SELECT_W_0_SHIFT) |
                   ((R300_WRITE_ENA_X | R300_WRITE_ENA_Y | R300_WRITE_ENA_Z | R300_WRITE_ENA_W)
                  << R300_WRITE_ENA_0_SHIFT) |
                   (R300_SWIZZLE_SELECT_X << R300_SWIZZLE_SELECT_X_1_SHIFT) |
                   (R300_SWIZZLE_SELECT_Y << R300_SWIZZLE_SELECT_Y_1_SHIFT) |
                   (R300_SWIZZLE_SELECT_Z << R300_SWIZZLE_SELECT_Z_1_SHIFT) |
                   (R300_SWIZZLE_SELECT_W << R300_SWIZZLE_SELECT_W_1_SHIFT) |
                   ((R300_WRITE_ENA_X | R300_WRITE_ENA_Y | R300_WRITE_ENA_Z | R300_WRITE_ENA_W)
                  << R300_WRITE_ENA_1_SHIFT)));
      OUT_ACCEL_REG(R300_VAP_PROG_STREAM_CNTL_EXT_1,
                  ((R300_SWIZZLE_SELECT_X << R300_SWIZZLE_SELECT_X_2_SHIFT) |
                   (R300_SWIZZLE_SELECT_Y << R300_SWIZZLE_SELECT_Y_2_SHIFT) |
                   (R300_SWIZZLE_SELECT_Z << R300_SWIZZLE_SELECT_Z_2_SHIFT) |
                   (R300_SWIZZLE_SELECT_W << R300_SWIZZLE_SELECT_W_2_SHIFT) |
                   ((R300_WRITE_ENA_X | R300_WRITE_ENA_Y | R300_WRITE_ENA_Z | R300_WRITE_ENA_W)
                  << R300_WRITE_ENA_2_SHIFT)));

      if (info->accel_state->has_tcl) {
          OUT_ACCEL_REG(R300_VAP_PVS_FLOW_CNTL_OPC, 0);
          OUT_ACCEL_REG(R300_VAP_GB_VERT_CLIP_ADJ, 0x3f800000);
          OUT_ACCEL_REG(R300_VAP_GB_VERT_DISC_ADJ, 0x3f800000);
          OUT_ACCEL_REG(R300_VAP_GB_HORZ_CLIP_ADJ, 0x3f800000);
          OUT_ACCEL_REG(R300_VAP_GB_HORZ_DISC_ADJ, 0x3f800000);
          OUT_ACCEL_REG(R300_VAP_CLIP_CNTL, R300_CLIP_DISABLE);
      }
      FINISH_ACCEL();

      /* pre-load the vertex shaders */
      if (info->accel_state->has_tcl) {
          BEGIN_ACCEL(37);
          /* exa composite shader program */
          OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_INDX_REG, R300_PVS_VECTOR_INST_INDEX(0));
          /* PVS inst 0 - dst X,Y */
          OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,
                    (R300_PVS_DST_OPCODE(R300_VE_ADD) |
                     R300_PVS_DST_REG_TYPE(R300_PVS_DST_REG_OUT) |
                     R300_PVS_DST_OFFSET(0) |
                     R300_PVS_DST_WE_X | R300_PVS_DST_WE_Y |
                     R300_PVS_DST_WE_Z | R300_PVS_DST_WE_W));
          OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,
                    (R300_PVS_SRC_REG_TYPE(R300_PVS_SRC_REG_INPUT) |
                     R300_PVS_SRC_OFFSET(0) |
                     R300_PVS_SRC_SWIZZLE_X(R300_PVS_SRC_SELECT_X) |
                     R300_PVS_SRC_SWIZZLE_Y(R300_PVS_SRC_SELECT_Y) |
                     R300_PVS_SRC_SWIZZLE_Z(R300_PVS_SRC_SELECT_FORCE_0) |
                     R300_PVS_SRC_SWIZZLE_W(R300_PVS_SRC_SELECT_FORCE_1)));
          OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,
                    (R300_PVS_SRC_REG_TYPE(R300_PVS_SRC_REG_INPUT) |
                     R300_PVS_SRC_OFFSET(0) |
                     R300_PVS_SRC_SWIZZLE_X(R300_PVS_SRC_SELECT_FORCE_0) |
                     R300_PVS_SRC_SWIZZLE_Y(R300_PVS_SRC_SELECT_FORCE_0) |
                     R300_PVS_SRC_SWIZZLE_Z(R300_PVS_SRC_SELECT_FORCE_0) |
                     R300_PVS_SRC_SWIZZLE_W(R300_PVS_SRC_SELECT_FORCE_0)));
          OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,
                    (R300_PVS_SRC_REG_TYPE(R300_PVS_SRC_REG_INPUT) |
                     R300_PVS_SRC_OFFSET(0) |
                     R300_PVS_SRC_SWIZZLE_X(R300_PVS_SRC_SELECT_FORCE_0) |
                     R300_PVS_SRC_SWIZZLE_Y(R300_PVS_SRC_SELECT_FORCE_0) |
                     R300_PVS_SRC_SWIZZLE_Z(R300_PVS_SRC_SELECT_FORCE_0) |
                     R300_PVS_SRC_SWIZZLE_W(R300_PVS_SRC_SELECT_FORCE_0)));

          /* PVS inst 1 - src X */
          OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,
                    (R300_PVS_DST_OPCODE(R300_VE_DOT_PRODUCT) |
                     R300_PVS_DST_REG_TYPE(R300_PVS_DST_REG_TEMPORARY) |
                     R300_PVS_DST_OFFSET(0) |
                     R300_PVS_DST_WE_X));
          OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,
                    (R300_PVS_SRC_REG_TYPE(R300_PVS_SRC_REG_INPUT) |
                     R300_PVS_SRC_OFFSET(6) |
                     R300_PVS_SRC_SWIZZLE_X(R300_PVS_SRC_SELECT_X) |
                     R300_PVS_SRC_SWIZZLE_Y(R300_PVS_SRC_SELECT_Y) |
                     R300_PVS_SRC_SWIZZLE_Z(R300_PVS_SRC_SELECT_FORCE_1) |
                     R300_PVS_SRC_SWIZZLE_W(R300_PVS_SRC_SELECT_FORCE_0)));
          OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,
                    (R300_PVS_SRC_REG_TYPE(R300_PVS_SRC_REG_CONSTANT) |
                     R300_PVS_SRC_OFFSET(0) |
                     R300_PVS_SRC_SWIZZLE_X(R300_PVS_SRC_SELECT_X) |
                     R300_PVS_SRC_SWIZZLE_Y(R300_PVS_SRC_SELECT_Y) |
                     R300_PVS_SRC_SWIZZLE_Z(R300_PVS_SRC_SELECT_Z) |
                     R300_PVS_SRC_SWIZZLE_W(R300_PVS_SRC_SELECT_FORCE_0)));
          OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,
                    (R300_PVS_SRC_REG_TYPE(R300_PVS_SRC_REG_INPUT) |
                     R300_PVS_SRC_OFFSET(6) |
                     R300_PVS_SRC_SWIZZLE_X(R300_PVS_SRC_SELECT_FORCE_0) |
                     R300_PVS_SRC_SWIZZLE_Y(R300_PVS_SRC_SELECT_FORCE_0) |
                     R300_PVS_SRC_SWIZZLE_Z(R300_PVS_SRC_SELECT_FORCE_0) |
                     R300_PVS_SRC_SWIZZLE_W(R300_PVS_SRC_SELECT_FORCE_0)));

          /* PVS inst 2 - src Y */
          OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,
                    (R300_PVS_DST_OPCODE(R300_VE_DOT_PRODUCT) |
                     R300_PVS_DST_REG_TYPE(R300_PVS_DST_REG_TEMPORARY) |
                     R300_PVS_DST_OFFSET(0) |
                     R300_PVS_DST_WE_Y));
          OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,
                    (R300_PVS_SRC_REG_TYPE(R300_PVS_SRC_REG_INPUT) |
                     R300_PVS_SRC_OFFSET(6) |
                     R300_PVS_SRC_SWIZZLE_X(R300_PVS_SRC_SELECT_X) |
                     R300_PVS_SRC_SWIZZLE_Y(R300_PVS_SRC_SELECT_Y) |
                     R300_PVS_SRC_SWIZZLE_Z(R300_PVS_SRC_SELECT_FORCE_1) |
                     R300_PVS_SRC_SWIZZLE_W(R300_PVS_SRC_SELECT_FORCE_0)));
          OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,
                    (R300_PVS_SRC_REG_TYPE(R300_PVS_SRC_REG_CONSTANT) |
                     R300_PVS_SRC_OFFSET(1) |
                     R300_PVS_SRC_SWIZZLE_X(R300_PVS_SRC_SELECT_X) |
                     R300_PVS_SRC_SWIZZLE_Y(R300_PVS_SRC_SELECT_Y) |
                     R300_PVS_SRC_SWIZZLE_Z(R300_PVS_SRC_SELECT_Z) |
                     R300_PVS_SRC_SWIZZLE_W(R300_PVS_SRC_SELECT_FORCE_0)));
          OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,
                    (R300_PVS_SRC_REG_TYPE(R300_PVS_SRC_REG_INPUT) |
                     R300_PVS_SRC_OFFSET(6) |
                     R300_PVS_SRC_SWIZZLE_X(R300_PVS_SRC_SELECT_FORCE_0) |
                     R300_PVS_SRC_SWIZZLE_Y(R300_PVS_SRC_SELECT_FORCE_0) |
                     R300_PVS_SRC_SWIZZLE_Z(R300_PVS_SRC_SELECT_FORCE_0) |
                     R300_PVS_SRC_SWIZZLE_W(R300_PVS_SRC_SELECT_FORCE_0)));

          /* PVS inst 3 - src X / w */
          OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,
                    (R300_PVS_DST_OPCODE(R300_VE_MULTIPLY) |
                     R300_PVS_DST_REG_TYPE(R300_PVS_DST_REG_OUT) |
                     R300_PVS_DST_OFFSET(1) |
                     R300_PVS_DST_WE_X));
          OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,
                    (R300_PVS_SRC_REG_TYPE(R300_PVS_SRC_REG_TEMPORARY) |
                     R300_PVS_SRC_OFFSET(0) |
                     R300_PVS_SRC_SWIZZLE_X(R300_PVS_SRC_SELECT_X) |
                     R300_PVS_SRC_SWIZZLE_Y(R300_PVS_SRC_SELECT_FORCE_0) |
                     R300_PVS_SRC_SWIZZLE_Z(R300_PVS_SRC_SELECT_FORCE_0) |
                     R300_PVS_SRC_SWIZZLE_W(R300_PVS_SRC_SELECT_FORCE_0)));
          OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,
                    (R300_PVS_SRC_REG_TYPE(R300_PVS_SRC_REG_CONSTANT) |
                     R300_PVS_SRC_OFFSET(0) |
                     R300_PVS_SRC_SWIZZLE_X(R300_PVS_SRC_SELECT_W) |
                     R300_PVS_SRC_SWIZZLE_Y(R300_PVS_SRC_SELECT_FORCE_0) |
                     R300_PVS_SRC_SWIZZLE_Z(R300_PVS_SRC_SELECT_FORCE_0) |
                     R300_PVS_SRC_SWIZZLE_W(R300_PVS_SRC_SELECT_FORCE_0)));
          OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,
                    (R300_PVS_SRC_REG_TYPE(R300_PVS_SRC_REG_INPUT) |
                     R300_PVS_SRC_OFFSET(6) |
                     R300_PVS_SRC_SWIZZLE_X(R300_PVS_SRC_SELECT_FORCE_0) |
                     R300_PVS_SRC_SWIZZLE_Y(R300_PVS_SRC_SELECT_FORCE_0) |
                     R300_PVS_SRC_SWIZZLE_Z(R300_PVS_SRC_SELECT_FORCE_0) |
                     R300_PVS_SRC_SWIZZLE_W(R300_PVS_SRC_SELECT_FORCE_0)));

          /* PVS inst 4 - src y / h */
          OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,
                    (R300_PVS_DST_OPCODE(R300_VE_MULTIPLY) |
                     R300_PVS_DST_REG_TYPE(R300_PVS_DST_REG_OUT) |
                     R300_PVS_DST_OFFSET(1) |
                     R300_PVS_DST_WE_Y));
          OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,
                    (R300_PVS_SRC_REG_TYPE(R300_PVS_SRC_REG_TEMPORARY) |
                     R300_PVS_SRC_OFFSET(0) |
                     R300_PVS_SRC_SWIZZLE_X(R300_PVS_SRC_SELECT_FORCE_0) |
                     R300_PVS_SRC_SWIZZLE_Y(R300_PVS_SRC_SELECT_Y) |
                     R300_PVS_SRC_SWIZZLE_Z(R300_PVS_SRC_SELECT_FORCE_0) |
                     R300_PVS_SRC_SWIZZLE_W(R300_PVS_SRC_SELECT_FORCE_0)));
          OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,
                    (R300_PVS_SRC_REG_TYPE(R300_PVS_SRC_REG_CONSTANT) |
                     R300_PVS_SRC_OFFSET(1) |
                     R300_PVS_SRC_SWIZZLE_X(R300_PVS_SRC_SELECT_FORCE_0) |
                     R300_PVS_SRC_SWIZZLE_Y(R300_PVS_SRC_SELECT_W) |
                     R300_PVS_SRC_SWIZZLE_Z(R300_PVS_SRC_SELECT_FORCE_0) |
                     R300_PVS_SRC_SWIZZLE_W(R300_PVS_SRC_SELECT_FORCE_0)));
          OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,
                    (R300_PVS_SRC_REG_TYPE(R300_PVS_SRC_REG_INPUT) |
                     R300_PVS_SRC_OFFSET(6) |
                     R300_PVS_SRC_SWIZZLE_X(R300_PVS_SRC_SELECT_FORCE_0) |
                     R300_PVS_SRC_SWIZZLE_Y(R300_PVS_SRC_SELECT_FORCE_0) |
                     R300_PVS_SRC_SWIZZLE_Z(R300_PVS_SRC_SELECT_FORCE_0) |
                     R300_PVS_SRC_SWIZZLE_W(R300_PVS_SRC_SELECT_FORCE_0)));

          /* PVS inst 5 - mask X */
          OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,
                    (R300_PVS_DST_OPCODE(R300_VE_DOT_PRODUCT) |
                     R300_PVS_DST_REG_TYPE(R300_PVS_DST_REG_TEMPORARY) |
                     R300_PVS_DST_OFFSET(0) |
                     R300_PVS_DST_WE_Z));
          OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,
                    (R300_PVS_SRC_REG_TYPE(R300_PVS_SRC_REG_INPUT) |
                     R300_PVS_SRC_OFFSET(7) |
                     R300_PVS_SRC_SWIZZLE_X(R300_PVS_SRC_SELECT_X) |
                     R300_PVS_SRC_SWIZZLE_Y(R300_PVS_SRC_SELECT_Y) |
                     R300_PVS_SRC_SWIZZLE_Z(R300_PVS_SRC_SELECT_FORCE_1) |
                     R300_PVS_SRC_SWIZZLE_W(R300_PVS_SRC_SELECT_FORCE_0)));
          OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,
                    (R300_PVS_SRC_REG_TYPE(R300_PVS_SRC_REG_CONSTANT) |
                     R300_PVS_SRC_OFFSET(2) |
                     R300_PVS_SRC_SWIZZLE_X(R300_PVS_SRC_SELECT_X) |
                     R300_PVS_SRC_SWIZZLE_Y(R300_PVS_SRC_SELECT_Y) |
                     R300_PVS_SRC_SWIZZLE_Z(R300_PVS_SRC_SELECT_Z) |
                     R300_PVS_SRC_SWIZZLE_W(R300_PVS_SRC_SELECT_FORCE_0)));
          OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,
                    (R300_PVS_SRC_REG_TYPE(R300_PVS_SRC_REG_INPUT) |
                     R300_PVS_SRC_OFFSET(7) |
                     R300_PVS_SRC_SWIZZLE_X(R300_PVS_SRC_SELECT_FORCE_0) |
                     R300_PVS_SRC_SWIZZLE_Y(R300_PVS_SRC_SELECT_FORCE_0) |
                     R300_PVS_SRC_SWIZZLE_Z(R300_PVS_SRC_SELECT_FORCE_0) |
                     R300_PVS_SRC_SWIZZLE_W(R300_PVS_SRC_SELECT_FORCE_0)));

          /* PVS inst 6 - mask Y */
          OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,
                    (R300_PVS_DST_OPCODE(R300_VE_DOT_PRODUCT) |
                     R300_PVS_DST_REG_TYPE(R300_PVS_DST_REG_TEMPORARY) |
                     R300_PVS_DST_OFFSET(0) |
                     R300_PVS_DST_WE_W));
          OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,
                    (R300_PVS_SRC_REG_TYPE(R300_PVS_SRC_REG_INPUT) |
                     R300_PVS_SRC_OFFSET(7) |
                     R300_PVS_SRC_SWIZZLE_X(R300_PVS_SRC_SELECT_X) |
                     R300_PVS_SRC_SWIZZLE_Y(R300_PVS_SRC_SELECT_Y) |
                     R300_PVS_SRC_SWIZZLE_Z(R300_PVS_SRC_SELECT_FORCE_1) |
                     R300_PVS_SRC_SWIZZLE_W(R300_PVS_SRC_SELECT_FORCE_0)));
          OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,
                    (R300_PVS_SRC_REG_TYPE(R300_PVS_SRC_REG_CONSTANT) |
                     R300_PVS_SRC_OFFSET(3) |
                     R300_PVS_SRC_SWIZZLE_X(R300_PVS_SRC_SELECT_X) |
                     R300_PVS_SRC_SWIZZLE_Y(R300_PVS_SRC_SELECT_Y) |
                     R300_PVS_SRC_SWIZZLE_Z(R300_PVS_SRC_SELECT_Z) |
                     R300_PVS_SRC_SWIZZLE_W(R300_PVS_SRC_SELECT_FORCE_0)));
          OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,
                    (R300_PVS_SRC_REG_TYPE(R300_PVS_SRC_REG_INPUT) |
                     R300_PVS_SRC_OFFSET(7) |
                     R300_PVS_SRC_SWIZZLE_X(R300_PVS_SRC_SELECT_FORCE_0) |
                     R300_PVS_SRC_SWIZZLE_Y(R300_PVS_SRC_SELECT_FORCE_0) |
                     R300_PVS_SRC_SWIZZLE_Z(R300_PVS_SRC_SELECT_FORCE_0) |
                     R300_PVS_SRC_SWIZZLE_W(R300_PVS_SRC_SELECT_FORCE_0)));

          /* PVS inst 7 - mask X / w */
          OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,
                    (R300_PVS_DST_OPCODE(R300_VE_MULTIPLY) |
                     R300_PVS_DST_REG_TYPE(R300_PVS_DST_REG_OUT) |
                     R300_PVS_DST_OFFSET(2) |
                     R300_PVS_DST_WE_X));
          OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,
                    (R300_PVS_SRC_REG_TYPE(R300_PVS_SRC_REG_TEMPORARY) |
                     R300_PVS_SRC_OFFSET(0) |
                     R300_PVS_SRC_SWIZZLE_X(R300_PVS_SRC_SELECT_Z) |
                     R300_PVS_SRC_SWIZZLE_Y(R300_PVS_SRC_SELECT_FORCE_0) |
                     R300_PVS_SRC_SWIZZLE_Z(R300_PVS_SRC_SELECT_FORCE_0) |
                     R300_PVS_SRC_SWIZZLE_W(R300_PVS_SRC_SELECT_FORCE_0)));
          OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,
                    (R300_PVS_SRC_REG_TYPE(R300_PVS_SRC_REG_CONSTANT) |
                     R300_PVS_SRC_OFFSET(2) |
                     R300_PVS_SRC_SWIZZLE_X(R300_PVS_SRC_SELECT_W) |
                     R300_PVS_SRC_SWIZZLE_Y(R300_PVS_SRC_SELECT_FORCE_0) |
                     R300_PVS_SRC_SWIZZLE_Z(R300_PVS_SRC_SELECT_FORCE_0) |
                     R300_PVS_SRC_SWIZZLE_W(R300_PVS_SRC_SELECT_FORCE_0)));
          OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,
                    (R300_PVS_SRC_REG_TYPE(R300_PVS_SRC_REG_INPUT) |
                     R300_PVS_SRC_OFFSET(6) |
                     R300_PVS_SRC_SWIZZLE_X(R300_PVS_SRC_SELECT_FORCE_0) |
                     R300_PVS_SRC_SWIZZLE_Y(R300_PVS_SRC_SELECT_FORCE_0) |
                     R300_PVS_SRC_SWIZZLE_Z(R300_PVS_SRC_SELECT_FORCE_0) |
                     R300_PVS_SRC_SWIZZLE_W(R300_PVS_SRC_SELECT_FORCE_0)));

          /* PVS inst 8 - mask y / h */
          OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,
                    (R300_PVS_DST_OPCODE(R300_VE_MULTIPLY) |
                     R300_PVS_DST_REG_TYPE(R300_PVS_DST_REG_OUT) |
                     R300_PVS_DST_OFFSET(2) |
                     R300_PVS_DST_WE_Y));
          OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,
                    (R300_PVS_SRC_REG_TYPE(R300_PVS_SRC_REG_TEMPORARY) |
                     R300_PVS_SRC_OFFSET(0) |
                     R300_PVS_SRC_SWIZZLE_X(R300_PVS_SRC_SELECT_FORCE_0) |
                     R300_PVS_SRC_SWIZZLE_Y(R300_PVS_SRC_SELECT_W) |
                     R300_PVS_SRC_SWIZZLE_Z(R300_PVS_SRC_SELECT_FORCE_0) |
                     R300_PVS_SRC_SWIZZLE_W(R300_PVS_SRC_SELECT_FORCE_0)));
          OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,
                    (R300_PVS_SRC_REG_TYPE(R300_PVS_SRC_REG_CONSTANT) |
                     R300_PVS_SRC_OFFSET(3) |
                     R300_PVS_SRC_SWIZZLE_X(R300_PVS_SRC_SELECT_FORCE_0) |
                     R300_PVS_SRC_SWIZZLE_Y(R300_PVS_SRC_SELECT_W) |
                     R300_PVS_SRC_SWIZZLE_Z(R300_PVS_SRC_SELECT_FORCE_0) |
                     R300_PVS_SRC_SWIZZLE_W(R300_PVS_SRC_SELECT_FORCE_0)));
          OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,
                    (R300_PVS_SRC_REG_TYPE(R300_PVS_SRC_REG_INPUT) |
                     R300_PVS_SRC_OFFSET(6) |
                     R300_PVS_SRC_SWIZZLE_X(R300_PVS_SRC_SELECT_FORCE_0) |
                     R300_PVS_SRC_SWIZZLE_Y(R300_PVS_SRC_SELECT_FORCE_0) |
                     R300_PVS_SRC_SWIZZLE_Z(R300_PVS_SRC_SELECT_FORCE_0) |
                     R300_PVS_SRC_SWIZZLE_W(R300_PVS_SRC_SELECT_FORCE_0)));
          FINISH_ACCEL();

          /* Xv shader program */
          BEGIN_ACCEL(9);
          OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_INDX_REG, R300_PVS_VECTOR_INST_INDEX(9));

          OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,
                    (R300_PVS_DST_OPCODE(R300_VE_ADD) |
                     R300_PVS_DST_REG_TYPE(R300_PVS_DST_REG_OUT) |
                     R300_PVS_DST_OFFSET(0) |
                     R300_PVS_DST_WE_X | R300_PVS_DST_WE_Y |
                     R300_PVS_DST_WE_Z | R300_PVS_DST_WE_W));
          OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,
                    (R300_PVS_SRC_REG_TYPE(R300_PVS_SRC_REG_INPUT) |
                     R300_PVS_SRC_OFFSET(0) |
                     R300_PVS_SRC_SWIZZLE_X(R300_PVS_SRC_SELECT_X) |
                     R300_PVS_SRC_SWIZZLE_Y(R300_PVS_SRC_SELECT_Y) |
                     R300_PVS_SRC_SWIZZLE_Z(R300_PVS_SRC_SELECT_FORCE_0) |
                     R300_PVS_SRC_SWIZZLE_W(R300_PVS_SRC_SELECT_FORCE_1)));
          OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,
                    (R300_PVS_SRC_REG_TYPE(R300_PVS_SRC_REG_INPUT) |
                     R300_PVS_SRC_OFFSET(0) |
                     R300_PVS_SRC_SWIZZLE_X(R300_PVS_SRC_SELECT_FORCE_0) |
                     R300_PVS_SRC_SWIZZLE_Y(R300_PVS_SRC_SELECT_FORCE_0) |
                     R300_PVS_SRC_SWIZZLE_Z(R300_PVS_SRC_SELECT_FORCE_0) |
                     R300_PVS_SRC_SWIZZLE_W(R300_PVS_SRC_SELECT_FORCE_0)));
          OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,
                    (R300_PVS_SRC_REG_TYPE(R300_PVS_SRC_REG_INPUT) |
                     R300_PVS_SRC_OFFSET(0) |
                     R300_PVS_SRC_SWIZZLE_X(R300_PVS_SRC_SELECT_FORCE_0) |
                     R300_PVS_SRC_SWIZZLE_Y(R300_PVS_SRC_SELECT_FORCE_0) |
                     R300_PVS_SRC_SWIZZLE_Z(R300_PVS_SRC_SELECT_FORCE_0) |
                     R300_PVS_SRC_SWIZZLE_W(R300_PVS_SRC_SELECT_FORCE_0)));

          OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,
                    (R300_PVS_DST_OPCODE(R300_VE_ADD) |
                     R300_PVS_DST_REG_TYPE(R300_PVS_DST_REG_OUT) |
                     R300_PVS_DST_OFFSET(1) |
                     R300_PVS_DST_WE_X | R300_PVS_DST_WE_Y));
          OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,
                    (R300_PVS_SRC_REG_TYPE(R300_PVS_SRC_REG_INPUT) |
                     R300_PVS_SRC_OFFSET(6) |
                     R300_PVS_SRC_SWIZZLE_X(R300_PVS_SRC_SELECT_X) |
                     R300_PVS_SRC_SWIZZLE_Y(R300_PVS_SRC_SELECT_Y) |
                     R300_PVS_SRC_SWIZZLE_Z(R300_PVS_SRC_SELECT_FORCE_0) |
                     R300_PVS_SRC_SWIZZLE_W(R300_PVS_SRC_SELECT_FORCE_1)));
          OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,
                    (R300_PVS_SRC_REG_TYPE(R300_PVS_SRC_REG_INPUT) |
                     R300_PVS_SRC_OFFSET(6) |
                     R300_PVS_SRC_SWIZZLE_X(R300_PVS_SRC_SELECT_FORCE_0) |
                     R300_PVS_SRC_SWIZZLE_Y(R300_PVS_SRC_SELECT_FORCE_0) |
                     R300_PVS_SRC_SWIZZLE_Z(R300_PVS_SRC_SELECT_FORCE_0) |
                     R300_PVS_SRC_SWIZZLE_W(R300_PVS_SRC_SELECT_FORCE_0)));
          OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,
                    (R300_PVS_SRC_REG_TYPE(R300_PVS_SRC_REG_INPUT) |
                     R300_PVS_SRC_OFFSET(6) |
                     R300_PVS_SRC_SWIZZLE_X(R300_PVS_SRC_SELECT_FORCE_0) |
                     R300_PVS_SRC_SWIZZLE_Y(R300_PVS_SRC_SELECT_FORCE_0) |
                     R300_PVS_SRC_SWIZZLE_Z(R300_PVS_SRC_SELECT_FORCE_0) |
                     R300_PVS_SRC_SWIZZLE_W(R300_PVS_SRC_SELECT_FORCE_0)));
          FINISH_ACCEL();

            /* Xv bicubic shader program */
          BEGIN_ACCEL(13);
            OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_INDX_REG, R300_PVS_VECTOR_INST_INDEX(11));
            /* PVS inst 0 */
            OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,
                          (R300_PVS_DST_OPCODE(R300_VE_ADD) |
                           R300_PVS_DST_REG_TYPE(R300_PVS_DST_REG_OUT) |
                     R300_PVS_DST_OFFSET(0) |
                           R300_PVS_DST_WE_X | R300_PVS_DST_WE_Y |
                           R300_PVS_DST_WE_Z | R300_PVS_DST_WE_W));
          OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,
                    (R300_PVS_SRC_REG_TYPE(R300_PVS_SRC_REG_INPUT) |
                           R300_PVS_SRC_OFFSET(0) |
                           R300_PVS_SRC_SWIZZLE_X(R300_PVS_SRC_SELECT_X) |
                           R300_PVS_SRC_SWIZZLE_Y(R300_PVS_SRC_SELECT_Y) |
                           R300_PVS_SRC_SWIZZLE_Z(R300_PVS_SRC_SELECT_FORCE_0) |
                           R300_PVS_SRC_SWIZZLE_W(R300_PVS_SRC_SELECT_FORCE_1)));
          OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,
                          (R300_PVS_SRC_REG_TYPE(R300_PVS_SRC_REG_INPUT) |
                           R300_PVS_SRC_OFFSET(0) |
                           R300_PVS_SRC_SWIZZLE_X(R300_PVS_SRC_SELECT_FORCE_0) |
                           R300_PVS_SRC_SWIZZLE_Y(R300_PVS_SRC_SELECT_FORCE_0) |
                     R300_PVS_SRC_SWIZZLE_Z(R300_PVS_SRC_SELECT_FORCE_0) |
                           R300_PVS_SRC_SWIZZLE_W(R300_PVS_SRC_SELECT_FORCE_0)));
          OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,
                    (R300_PVS_SRC_REG_TYPE(R300_PVS_SRC_REG_INPUT) |
                           R300_PVS_SRC_OFFSET(0) |
                           R300_PVS_SRC_SWIZZLE_X(R300_PVS_SRC_SELECT_FORCE_0) |
                     R300_PVS_SRC_SWIZZLE_Y(R300_PVS_SRC_SELECT_FORCE_0) |
                           R300_PVS_SRC_SWIZZLE_Z(R300_PVS_SRC_SELECT_FORCE_0) |
                           R300_PVS_SRC_SWIZZLE_W(R300_PVS_SRC_SELECT_FORCE_0)));

            /* PVS inst 1 */
            OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,
                          (R300_PVS_DST_OPCODE(R300_VE_ADD) |
                           R300_PVS_DST_REG_TYPE(R300_PVS_DST_REG_OUT) |
                           R300_PVS_DST_OFFSET(1) |
                           R300_PVS_DST_WE_X | R300_PVS_DST_WE_Y |
                           R300_PVS_DST_WE_Z | R300_PVS_DST_WE_W));
            OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,
                          (R300_PVS_SRC_REG_TYPE(R300_PVS_SRC_REG_INPUT) |
                           R300_PVS_SRC_OFFSET(6) |
                           R300_PVS_SRC_SWIZZLE_X(R300_PVS_SRC_SELECT_X) |
                           R300_PVS_SRC_SWIZZLE_Y(R300_PVS_SRC_SELECT_Y) |
                           R300_PVS_SRC_SWIZZLE_Z(R300_PVS_SRC_SELECT_FORCE_0) |
                           R300_PVS_SRC_SWIZZLE_W(R300_PVS_SRC_SELECT_FORCE_1)));
          OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,
                          (R300_PVS_SRC_REG_TYPE(R300_PVS_SRC_REG_INPUT) |
                           R300_PVS_SRC_OFFSET(6) |
                           R300_PVS_SRC_SWIZZLE_X(R300_PVS_SRC_SELECT_FORCE_0) |
                           R300_PVS_SRC_SWIZZLE_Y(R300_PVS_SRC_SELECT_FORCE_0) |
                     R300_PVS_SRC_SWIZZLE_Z(R300_PVS_SRC_SELECT_FORCE_0) |
                           R300_PVS_SRC_SWIZZLE_W(R300_PVS_SRC_SELECT_FORCE_0)));
          OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,
                    (R300_PVS_SRC_REG_TYPE(R300_PVS_SRC_REG_INPUT) |
                           R300_PVS_SRC_OFFSET(6) |
                           R300_PVS_SRC_SWIZZLE_X(R300_PVS_SRC_SELECT_FORCE_0) |
                     R300_PVS_SRC_SWIZZLE_Y(R300_PVS_SRC_SELECT_FORCE_0) |
                           R300_PVS_SRC_SWIZZLE_Z(R300_PVS_SRC_SELECT_FORCE_0) |
                           R300_PVS_SRC_SWIZZLE_W(R300_PVS_SRC_SELECT_FORCE_0)));

            /* PVS inst 2 */
            OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,
                          (R300_PVS_DST_OPCODE(R300_VE_ADD) |
                           R300_PVS_DST_REG_TYPE(R300_PVS_DST_REG_OUT) |
                           R300_PVS_DST_OFFSET(2) |
                           R300_PVS_DST_WE_X | R300_PVS_DST_WE_Y |
                           R300_PVS_DST_WE_Z | R300_PVS_DST_WE_W));
            OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,
                          (R300_PVS_SRC_REG_TYPE(R300_PVS_SRC_REG_INPUT) |
                           R300_PVS_SRC_OFFSET(7) |
                           R300_PVS_SRC_SWIZZLE_X(R300_PVS_SRC_SELECT_X) |
                           R300_PVS_SRC_SWIZZLE_Y(R300_PVS_SRC_SELECT_Y) |
                           R300_PVS_SRC_SWIZZLE_Z(R300_PVS_SRC_SELECT_FORCE_0) |
                           R300_PVS_SRC_SWIZZLE_W(R300_PVS_SRC_SELECT_FORCE_1)));
            OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,
                          (R300_PVS_SRC_REG_TYPE(R300_PVS_SRC_REG_INPUT) |
                           R300_PVS_SRC_OFFSET(7) |
                           R300_PVS_SRC_SWIZZLE_X(R300_PVS_SRC_SELECT_FORCE_0) |
                           R300_PVS_SRC_SWIZZLE_Y(R300_PVS_SRC_SELECT_FORCE_0) |
                           R300_PVS_SRC_SWIZZLE_Z(R300_PVS_SRC_SELECT_FORCE_0) |
                           R300_PVS_SRC_SWIZZLE_W(R300_PVS_SRC_SELECT_FORCE_0)));
            OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,
                          (R300_PVS_SRC_REG_TYPE(R300_PVS_SRC_REG_INPUT) |
                           R300_PVS_SRC_OFFSET(7) |
                           R300_PVS_SRC_SWIZZLE_X(R300_PVS_SRC_SELECT_FORCE_0) |
                           R300_PVS_SRC_SWIZZLE_Y(R300_PVS_SRC_SELECT_FORCE_0) |
                           R300_PVS_SRC_SWIZZLE_Z(R300_PVS_SRC_SELECT_FORCE_0) |
                           R300_PVS_SRC_SWIZZLE_W(R300_PVS_SRC_SELECT_FORCE_0)));
            FINISH_ACCEL();
      }

      /* pre-load the RS instructions */
      BEGIN_ACCEL(4);
      if (IS_R300_3D) {
          /* rasterizer source table
           * R300_RS_TEX_PTR is the offset into the input RS stream
           * 0,1 are tex0
           * 2,3 are tex1
           */
          OUT_ACCEL_REG(R300_RS_IP_0,
                    (R300_RS_TEX_PTR(0) |
                     R300_RS_SEL_S(R300_RS_SEL_C0) |
                     R300_RS_SEL_T(R300_RS_SEL_C1) |
                     R300_RS_SEL_R(R300_RS_SEL_K0) |
                     R300_RS_SEL_Q(R300_RS_SEL_K1)));
          OUT_ACCEL_REG(R300_RS_IP_1,
                    (R300_RS_TEX_PTR(2) |
                     R300_RS_SEL_S(R300_RS_SEL_C0) |
                     R300_RS_SEL_T(R300_RS_SEL_C1) |
                     R300_RS_SEL_R(R300_RS_SEL_K0) |
                     R300_RS_SEL_Q(R300_RS_SEL_K1)));
          /* src tex */
          /* R300_INST_TEX_ID - select the RS source table entry
           * R300_INST_TEX_ADDR - the FS temp register for the texture data
           */
          OUT_ACCEL_REG(R300_RS_INST_0, (R300_INST_TEX_ID(0) |
                                 R300_RS_INST_TEX_CN_WRITE |
                                 R300_INST_TEX_ADDR(0)));
          /* mask tex */
          OUT_ACCEL_REG(R300_RS_INST_1, (R300_INST_TEX_ID(1) |
                                 R300_RS_INST_TEX_CN_WRITE |
                                 R300_INST_TEX_ADDR(1)));

      } else {
          /* rasterizer source table
           * R300_RS_TEX_PTR is the offset into the input RS stream
           * 0,1 are tex0
           * 2,3 are tex1
           */
          OUT_ACCEL_REG(R500_RS_IP_0, ((0 << R500_RS_IP_TEX_PTR_S_SHIFT) |
                               (1 << R500_RS_IP_TEX_PTR_T_SHIFT) |
                               (R500_RS_IP_PTR_K0 << R500_RS_IP_TEX_PTR_R_SHIFT) |
                               (R500_RS_IP_PTR_K1 << R500_RS_IP_TEX_PTR_Q_SHIFT)));

          OUT_ACCEL_REG(R500_RS_IP_1, ((2 << R500_RS_IP_TEX_PTR_S_SHIFT) |
                               (3 << R500_RS_IP_TEX_PTR_T_SHIFT) |
                               (R500_RS_IP_PTR_K0 << R500_RS_IP_TEX_PTR_R_SHIFT) |
                               (R500_RS_IP_PTR_K1 << R500_RS_IP_TEX_PTR_Q_SHIFT)));
          /* src tex */
          /* R500_RS_INST_TEX_ID_SHIFT - select the RS source table entry
           * R500_RS_INST_TEX_ADDR_SHIFT - the FS temp register for the texture data
           */
          OUT_ACCEL_REG(R500_RS_INST_0, ((0 << R500_RS_INST_TEX_ID_SHIFT) |
                                 R500_RS_INST_TEX_CN_WRITE |
                                 (0 << R500_RS_INST_TEX_ADDR_SHIFT)));
          /* mask tex */
          OUT_ACCEL_REG(R500_RS_INST_1, ((1 << R500_RS_INST_TEX_ID_SHIFT) |
                                 R500_RS_INST_TEX_CN_WRITE |
                                 (1 << R500_RS_INST_TEX_ADDR_SHIFT)));
      }
      FINISH_ACCEL();

      if (IS_R300_3D)
          BEGIN_ACCEL(4);
      else {
          BEGIN_ACCEL(6);
          OUT_ACCEL_REG(R300_US_CONFIG, R500_ZERO_TIMES_ANYTHING_EQUALS_ZERO);
          OUT_ACCEL_REG(R500_US_FC_CTRL, 0);
      }
      OUT_ACCEL_REG(R300_US_W_FMT, 0);
      OUT_ACCEL_REG(R300_US_OUT_FMT_1, (R300_OUT_FMT_UNUSED |
                                R300_OUT_FMT_C0_SEL_BLUE |
                                R300_OUT_FMT_C1_SEL_GREEN |
                                R300_OUT_FMT_C2_SEL_RED |
                                R300_OUT_FMT_C3_SEL_ALPHA));
      OUT_ACCEL_REG(R300_US_OUT_FMT_2, (R300_OUT_FMT_UNUSED |
                                R300_OUT_FMT_C0_SEL_BLUE |
                                R300_OUT_FMT_C1_SEL_GREEN |
                                R300_OUT_FMT_C2_SEL_RED |
                                R300_OUT_FMT_C3_SEL_ALPHA));
      OUT_ACCEL_REG(R300_US_OUT_FMT_3, (R300_OUT_FMT_UNUSED |
                                R300_OUT_FMT_C0_SEL_BLUE |
                                R300_OUT_FMT_C1_SEL_GREEN |
                                R300_OUT_FMT_C2_SEL_RED |
                                R300_OUT_FMT_C3_SEL_ALPHA));
      FINISH_ACCEL();


      BEGIN_ACCEL(3);
      OUT_ACCEL_REG(R300_FG_DEPTH_SRC, 0);
      OUT_ACCEL_REG(R300_FG_FOG_BLEND, 0);
      OUT_ACCEL_REG(R300_FG_ALPHA_FUNC, 0);
      FINISH_ACCEL();

      BEGIN_ACCEL(13);
      OUT_ACCEL_REG(R300_RB3D_ABLENDCNTL, 0);
      OUT_ACCEL_REG(R300_RB3D_ZSTENCILCNTL, 0);
      OUT_ACCEL_REG(R300_RB3D_ZCACHE_CTLSTAT, R300_ZC_FLUSH | R300_ZC_FREE);
      OUT_ACCEL_REG(R300_RB3D_BW_CNTL, 0);
      OUT_ACCEL_REG(R300_RB3D_ZCNTL, 0);
      OUT_ACCEL_REG(R300_RB3D_ZTOP, 0);
      OUT_ACCEL_REG(R300_RB3D_ROPCNTL, 0);

      OUT_ACCEL_REG(R300_RB3D_AARESOLVE_CTL, 0);
      OUT_ACCEL_REG(R300_RB3D_COLOR_CHANNEL_MASK, (R300_BLUE_MASK_EN |
                                         R300_GREEN_MASK_EN |
                                         R300_RED_MASK_EN |
                                         R300_ALPHA_MASK_EN));
      OUT_ACCEL_REG(R300_RB3D_DSTCACHE_CTLSTAT, R300_DC_FLUSH_3D | R300_DC_FREE_3D);
      OUT_ACCEL_REG(R300_RB3D_CCTL, 0);
      OUT_ACCEL_REG(R300_RB3D_DITHER_CTL, 0);
      OUT_ACCEL_REG(R300_RB3D_DSTCACHE_CTLSTAT, R300_DC_FLUSH_3D | R300_DC_FREE_3D);
      FINISH_ACCEL();

      BEGIN_ACCEL(5);
      OUT_ACCEL_REG(R300_SC_EDGERULE, 0xA5294A5);
      if (IS_R300_3D) {
          /* clip has offset 1440 */
          OUT_ACCEL_REG(R300_SC_CLIP_0_A, ((1440 << R300_CLIP_X_SHIFT) |
                                   (1440 << R300_CLIP_Y_SHIFT)));
          OUT_ACCEL_REG(R300_SC_CLIP_0_B, ((4080 << R300_CLIP_X_SHIFT) |
                                   (4080 << R300_CLIP_Y_SHIFT)));
      } else {
          OUT_ACCEL_REG(R300_SC_CLIP_0_A, ((0 << R300_CLIP_X_SHIFT) |
                                   (0 << R300_CLIP_Y_SHIFT)));
          OUT_ACCEL_REG(R300_SC_CLIP_0_B, ((4080 << R300_CLIP_X_SHIFT) |
                                   (4080 << R300_CLIP_Y_SHIFT)));
      }
      OUT_ACCEL_REG(R300_SC_CLIP_RULE, 0xAAAA);
      OUT_ACCEL_REG(R300_SC_SCREENDOOR, 0xffffff);
      FINISH_ACCEL();
    } else if (IS_R200_3D) {

      BEGIN_ACCEL(6);
      if (info->ChipFamily == CHIP_FAMILY_RS300) {
          OUT_ACCEL_REG(R200_SE_VAP_CNTL_STATUS, RADEON_TCL_BYPASS);
      } else {
          OUT_ACCEL_REG(R200_SE_VAP_CNTL_STATUS, 0);
      }
      OUT_ACCEL_REG(R200_PP_CNTL_X, 0);
      OUT_ACCEL_REG(R200_PP_TXMULTI_CTL_0, 0);
      OUT_ACCEL_REG(R200_SE_VTX_STATE_CNTL, 0);
      OUT_ACCEL_REG(R200_SE_VTE_CNTL, 0);
      OUT_ACCEL_REG(R200_SE_VAP_CNTL, R200_VAP_FORCE_W_TO_ONE |
          R200_VAP_VF_MAX_VTX_NUM);
      FINISH_ACCEL();

      BEGIN_ACCEL(4);
      OUT_ACCEL_REG(R200_RE_AUX_SCISSOR_CNTL, 0);
      OUT_ACCEL_REG(R200_RE_CNTL, 0);
      OUT_ACCEL_REG(RADEON_RB3D_PLANEMASK, 0xffffffff);
      OUT_ACCEL_REG(RADEON_SE_CNTL, (RADEON_DIFFUSE_SHADE_GOURAUD |
                               RADEON_BFACE_SOLID |
                               RADEON_FFACE_SOLID |
                               RADEON_VTX_PIX_CENTER_OGL |
                               RADEON_ROUND_MODE_ROUND |
                               RADEON_ROUND_PREC_4TH_PIX));
      FINISH_ACCEL();
    } else {
      BEGIN_ACCEL(2);
      if ((info->ChipFamily == CHIP_FAMILY_RADEON) ||
          (info->ChipFamily == CHIP_FAMILY_RV200))
          OUT_ACCEL_REG(RADEON_SE_CNTL_STATUS, 0);
      else
          OUT_ACCEL_REG(RADEON_SE_CNTL_STATUS, RADEON_TCL_BYPASS);
      OUT_ACCEL_REG(RADEON_SE_COORD_FMT,
                  RADEON_VTX_XY_PRE_MULT_1_OVER_W0 |
                  RADEON_TEX1_W_ROUTING_USE_W0);
      FINISH_ACCEL();

      BEGIN_ACCEL(2);
      OUT_ACCEL_REG(RADEON_RB3D_PLANEMASK, 0xffffffff);
      OUT_ACCEL_REG(RADEON_SE_CNTL, (RADEON_DIFFUSE_SHADE_GOURAUD |
                               RADEON_BFACE_SOLID |
                               RADEON_FFACE_SOLID |
                               RADEON_VTX_PIX_CENTER_OGL |
                               RADEON_ROUND_MODE_ROUND |
                               RADEON_ROUND_PREC_4TH_PIX));
      FINISH_ACCEL();
    }

}

/* inserts a wait for vline in the command stream */
void FUNC_NAME(RADEONWaitForVLine)(ScrnInfoPtr pScrn, PixmapPtr pPix,
                           xf86CrtcPtr crtc, int start, int stop)
{
    RADEONInfoPtr  info = RADEONPTR(pScrn);
    uint32_t offset;
    ACCEL_PREAMBLE();

    if (!crtc)
      return;

    if (stop < start)
      return;

    if (!crtc->enabled)
      return;

    if (info->cs) {
        if (pPix != pScrn->pScreen->GetScreenPixmap(pScrn->pScreen))
          return;
    } else {
#ifdef USE_EXA
      if (info->useEXA)
          offset = exaGetPixmapOffset(pPix);
      else
#endif
          offset = pPix->devPrivate.ptr - info->FB;

      /* if drawing to front buffer */
      if (offset != 0)
          return;
    }

    start = max(start, 0);
    stop = min(stop, crtc->mode.VDisplay);

    if (start > crtc->mode.VDisplay)
      return;

#if defined(ACCEL_CP) && defined(XF86DRM_MODE)
    if (info->cs) {
      drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;

      BEGIN_ACCEL(3);
      if (IS_AVIVO_VARIANT) {
          OUT_ACCEL_REG(AVIVO_D1MODE_VLINE_START_END, /* this is just a marker */
                    ((start << AVIVO_D1MODE_VLINE_START_SHIFT) |
                     (stop << AVIVO_D1MODE_VLINE_END_SHIFT) |
                     AVIVO_D1MODE_VLINE_INV));
      } else {
          OUT_ACCEL_REG(RADEON_CRTC_GUI_TRIG_VLINE, /* another placeholder */
                    ((start << RADEON_CRTC_GUI_TRIG_VLINE_START_SHIFT) |
                     (stop << RADEON_CRTC_GUI_TRIG_VLINE_END_SHIFT) |
                     RADEON_CRTC_GUI_TRIG_VLINE_INV |
                     RADEON_CRTC_GUI_TRIG_VLINE_STALL));
      }
      OUT_ACCEL_REG(RADEON_WAIT_UNTIL, (RADEON_WAIT_CRTC_VLINE |
                                RADEON_ENG_DISPLAY_SELECT_CRTC0));

      OUT_RING(CP_PACKET3(RADEON_CP_PACKET3_NOP, 0));
      OUT_RING(drmmode_crtc->mode_crtc->crtc_id);
      FINISH_ACCEL();
    } else
#endif
    {
      RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private;

      BEGIN_ACCEL(2);
      if (IS_AVIVO_VARIANT) {
          OUT_ACCEL_REG(AVIVO_D1MODE_VLINE_START_END + radeon_crtc->crtc_offset,
                    ((start << AVIVO_D1MODE_VLINE_START_SHIFT) |
                     (stop << AVIVO_D1MODE_VLINE_END_SHIFT) |
                     AVIVO_D1MODE_VLINE_INV));
      } else {
          if (radeon_crtc->crtc_id == 0)
            OUT_ACCEL_REG(RADEON_CRTC_GUI_TRIG_VLINE,
                        ((start << RADEON_CRTC_GUI_TRIG_VLINE_START_SHIFT) |
                         (stop << RADEON_CRTC_GUI_TRIG_VLINE_END_SHIFT) |
                         RADEON_CRTC_GUI_TRIG_VLINE_INV |
                         RADEON_CRTC_GUI_TRIG_VLINE_STALL));
          else
            OUT_ACCEL_REG(RADEON_CRTC2_GUI_TRIG_VLINE,
                        ((start << RADEON_CRTC_GUI_TRIG_VLINE_START_SHIFT) |
                         (stop << RADEON_CRTC_GUI_TRIG_VLINE_END_SHIFT) |
                         RADEON_CRTC_GUI_TRIG_VLINE_INV |
                         RADEON_CRTC_GUI_TRIG_VLINE_STALL));
      }

      if (radeon_crtc->crtc_id == 0)
          OUT_ACCEL_REG(RADEON_WAIT_UNTIL, (RADEON_WAIT_CRTC_VLINE |
                                    RADEON_ENG_DISPLAY_SELECT_CRTC0));
      else
          OUT_ACCEL_REG(RADEON_WAIT_UNTIL, (RADEON_WAIT_CRTC_VLINE |
                                    RADEON_ENG_DISPLAY_SELECT_CRTC1));
      FINISH_ACCEL();
    }
}

/* MMIO:
 *
 * Wait for the graphics engine to be completely idle: the FIFO has
 * drained, the Pixel Cache is flushed, and the engine is idle.  This is
 * a standard "sync" function that will make the hardware "quiescent".
 *
 * CP:
 *
 * Wait until the CP is completely idle: the FIFO has drained and the CP
 * is idle.
 */
void FUNC_NAME(RADEONWaitForIdle)(ScrnInfoPtr pScrn)
{
    RADEONInfoPtr  info = RADEONPTR(pScrn);
    unsigned char *RADEONMMIO = info->MMIO;
    int            i    = 0;

#ifdef ACCEL_CP
    /* Make sure the CP is idle first */
    if (info->cp->CPStarted) {
      int  ret;

      FLUSH_RING();

      for (;;) {
          do {
            ret = drmCommandNone(info->dri->drmFD, DRM_RADEON_CP_IDLE);
            if (ret && ret != -EBUSY) {
                xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
                         "%s: CP idle %d\n", __FUNCTION__, ret);
            }
          } while ((ret == -EBUSY) && (i++ < RADEON_TIMEOUT));

          if (ret == 0) return;

          xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
                   "Idle timed out, resetting engine...\n");
          if (info->ChipFamily < CHIP_FAMILY_R600) {
            RADEONEngineReset(pScrn);
            RADEONEngineRestore(pScrn);
          } else
            R600EngineReset(pScrn);

          /* Always restart the engine when doing CP 2D acceleration */
          RADEONCP_RESET(pScrn, info);
          RADEONCP_START(pScrn, info);
      }
    }
#endif

    if (info->ChipFamily >= CHIP_FAMILY_R600) {
      if (!info->accelOn)
          return;

      /* Wait for the engine to go idle */
      if (info->ChipFamily >= CHIP_FAMILY_RV770)
          R600WaitForFifoFunction(pScrn, 8);
      else
          R600WaitForFifoFunction(pScrn, 16);

      for (;;) {
          for (i = 0; i < RADEON_TIMEOUT; i++) {
            if (!(INREG(R600_GRBM_STATUS) & R600_GUI_ACTIVE))
                return;
          }
          xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
                     "Idle timed out: stat=0x%08x\n",
                     (unsigned int)INREG(R600_GRBM_STATUS));
          xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
                   "Idle timed out, resetting engine...\n");
          R600EngineReset(pScrn);
#ifdef XF86DRI
          if (info->directRenderingEnabled) {
            RADEONCP_RESET(pScrn, info);
            RADEONCP_START(pScrn, info);
          }
#endif
      }
    } else {
      /* Wait for the engine to go idle */
      RADEONWaitForFifoFunction(pScrn, 64);

      for (;;) {
          for (i = 0; i < RADEON_TIMEOUT; i++) {
            if (!(INREG(RADEON_RBBM_STATUS) & RADEON_RBBM_ACTIVE)) {
                RADEONEngineFlush(pScrn);
                return;
            }
          }
          xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
                     "Idle timed out: %u entries, stat=0x%08x\n",
                     (unsigned int)INREG(RADEON_RBBM_STATUS) & RADEON_RBBM_FIFOCNT_MASK,
                     (unsigned int)INREG(RADEON_RBBM_STATUS));
          xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
                   "Idle timed out, resetting engine...\n");
          RADEONEngineReset(pScrn);
          RADEONEngineRestore(pScrn);
#ifdef XF86DRI
          if (info->directRenderingEnabled) {
            RADEONCP_RESET(pScrn, info);
            RADEONCP_START(pScrn, info);
          }
#endif
      }
    }
}

Generated by  Doxygen 1.6.0   Back to index