⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 radeon_state.c

📁 h内核
💻 C
📖 第 1 页 / 共 5 页
字号:
/* 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"drm_ioctl_desc_t radeon_ioctls[] = {	[DRM_IOCTL_NR(DRM_RADEON_CP_INIT)]    = { radeon_cp_init,      1, 1 },	[DRM_IOCTL_NR(DRM_RADEON_CP_START)]   = { radeon_cp_start,     1, 1 },	[DRM_IOCTL_NR(DRM_RADEON_CP_STOP)]    = { radeon_cp_stop,      1, 1 },	[DRM_IOCTL_NR(DRM_RADEON_CP_RESET)]   = { radeon_cp_reset,     1, 1 },	[DRM_IOCTL_NR(DRM_RADEON_CP_IDLE)]    = { radeon_cp_idle,      1, 0 },	[DRM_IOCTL_NR(DRM_RADEON_CP_RESUME)]  = { radeon_cp_resume,    1, 0 },	[DRM_IOCTL_NR(DRM_RADEON_RESET)]      = { radeon_engine_reset, 1, 0 },	[DRM_IOCTL_NR(DRM_RADEON_FULLSCREEN)] = { radeon_fullscreen,   1, 0 },	[DRM_IOCTL_NR(DRM_RADEON_SWAP)]       = { radeon_cp_swap,      1, 0 },	[DRM_IOCTL_NR(DRM_RADEON_CLEAR)]      = { radeon_cp_clear,     1, 0 },	[DRM_IOCTL_NR(DRM_RADEON_VERTEX)]     = { radeon_cp_vertex,    1, 0 },	[DRM_IOCTL_NR(DRM_RADEON_INDICES)]    = { radeon_cp_indices,   1, 0 },	[DRM_IOCTL_NR(DRM_RADEON_TEXTURE)]    = { radeon_cp_texture,   1, 0 },	[DRM_IOCTL_NR(DRM_RADEON_STIPPLE)]    = { radeon_cp_stipple,   1, 0 },	[DRM_IOCTL_NR(DRM_RADEON_INDIRECT)]   = { radeon_cp_indirect,  1, 1 },	[DRM_IOCTL_NR(DRM_RADEON_VERTEX2)]    = { radeon_cp_vertex2,   1, 0 },	[DRM_IOCTL_NR(DRM_RADEON_CMDBUF)]     = { radeon_cp_cmdbuf,    1, 0 },	[DRM_IOCTL_NR(DRM_RADEON_GETPARAM)]   = { radeon_cp_getparam,  1, 0 },	[DRM_IOCTL_NR(DRM_RADEON_FLIP)]       = { radeon_cp_flip,      1, 0 },	[DRM_IOCTL_NR(DRM_RADEON_ALLOC)]      = { radeon_mem_alloc,    1, 0 },	[DRM_IOCTL_NR(DRM_RADEON_FREE)]       = { radeon_mem_free,     1, 0 },	[DRM_IOCTL_NR(DRM_RADEON_INIT_HEAP)]  = { radeon_mem_init_heap,1, 1 },	[DRM_IOCTL_NR(DRM_RADEON_IRQ_EMIT)]   = { radeon_irq_emit,     1, 0 },	[DRM_IOCTL_NR(DRM_RADEON_IRQ_WAIT)]   = { radeon_irq_wait,     1, 0 },	[DRM_IOCTL_NR(DRM_RADEON_SETPARAM)]   = { radeon_cp_setparam,  1, 0 },	[DRM_IOCTL_NR(DRM_RADEON_SURF_ALLOC)] = { radeon_surface_alloc,1, 0 },	[DRM_IOCTL_NR(DRM_RADEON_SURF_FREE)]  = { radeon_surface_free, 1, 0 }};int radeon_max_ioctl = DRM_ARRAY_SIZE(radeon_ioctls);/* ================================================================ * 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 ) {	u32 off = *offset;	struct drm_radeon_driver_file_fields *radeon_priv;	if ( off >= dev_priv->fb_location &&	     off < ( dev_priv->gart_vm_start + dev_priv->gart_size ) )		return 0;	radeon_priv = filp_priv->driver_priv;	off += radeon_priv->radeon_fb_delta;	DRM_DEBUG( "offset fixed up to 0x%x\n", off );	if ( off < dev_priv->fb_location ||	     off >= ( dev_priv->gart_vm_start + dev_priv->gart_size ) )		return DRM_ERR( EINVAL );	*offset = off;	return 0;}static __inline__ int radeon_check_and_fixup_packets( drm_radeon_private_t *dev_priv,						      drm_file_t *filp_priv,						      int id,						      u32 __user *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_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_VAP_CTL:	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:		/* 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_cmd_buffer_t *cmdbuf,						      unsigned int *cmdsz ) {	u32 *cmd = (u32 *) cmdbuf->buf;	*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 );	}	/* Check client state and fix it up if necessary */	if ( cmd[0] & 0x8000 ) { /* MSB of opcode: next DWORD GUI_CNTL */		u32 offset;		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;		}	}	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 );

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -