radeon_state.c

来自「LINUX 2.6.17.4的源码」· C语言 代码 · 共 2,231 行 · 第 1/5 页

C
2,231
字号
		RADEON_WAIT_UNTIL_2D_IDLE();		OUT_RING_REG(RADEON_RB3D_DEPTHCLEARVALUE,			     tempRB3D_DEPTHCLEARVALUE);		/* what offset is this exactly ? */		OUT_RING_REG(RADEON_RB3D_ZMASKOFFSET, 0);		/* need ctlstat, otherwise get some strange black flickering */		OUT_RING_REG(RADEON_RB3D_ZCACHE_CTLSTAT,			     RADEON_RB3D_ZC_FLUSH_ALL);		ADVANCE_RING();		for (i = 0; i < nbox; i++) {			int tileoffset, nrtilesx, nrtilesy, j;			/* it looks like r200 needs rv-style clears, at least if hierz is not enabled? */			if ((dev_priv->flags & CHIP_HAS_HIERZ)			    && !(dev_priv->microcode_version == UCODE_R200)) {				/* FIXME : figure this out for r200 (when hierz is enabled). Or				   maybe r200 actually doesn't need to put the low-res z value into				   the tile cache like r100, but just needs to clear the hi-level z-buffer?				   Works for R100, both with hierz and without.				   R100 seems to operate on 2x1 8x8 tiles, but...				   odd: offset/nrtiles need to be 64 pix (4 block) aligned? Potentially				   problematic with resolutions which are not 64 pix aligned? */				tileoffset =				    ((pbox[i].y1 >> 3) * depthpixperline +				     pbox[i].x1) >> 6;				nrtilesx =				    ((pbox[i].x2 & ~63) -				     (pbox[i].x1 & ~63)) >> 4;				nrtilesy =				    (pbox[i].y2 >> 3) - (pbox[i].y1 >> 3);				for (j = 0; j <= nrtilesy; j++) {					BEGIN_RING(4);					OUT_RING(CP_PACKET3						 (RADEON_3D_CLEAR_ZMASK, 2));					/* first tile */					OUT_RING(tileoffset * 8);					/* the number of tiles to clear */					OUT_RING(nrtilesx + 4);					/* clear mask : chooses the clearing pattern. */					OUT_RING(clearmask);					ADVANCE_RING();					tileoffset += depthpixperline >> 6;				}			} else if (dev_priv->microcode_version == UCODE_R200) {				/* works for rv250. */				/* find first macro tile (8x2 4x4 z-pixels on rv250) */				tileoffset =				    ((pbox[i].y1 >> 3) * depthpixperline +				     pbox[i].x1) >> 5;				nrtilesx =				    (pbox[i].x2 >> 5) - (pbox[i].x1 >> 5);				nrtilesy =				    (pbox[i].y2 >> 3) - (pbox[i].y1 >> 3);				for (j = 0; j <= nrtilesy; j++) {					BEGIN_RING(4);					OUT_RING(CP_PACKET3						 (RADEON_3D_CLEAR_ZMASK, 2));					/* first tile */					/* judging by the first tile offset needed, could possibly					   directly address/clear 4x4 tiles instead of 8x2 * 4x4					   macro tiles, though would still need clear mask for					   right/bottom if truely 4x4 granularity is desired ? */					OUT_RING(tileoffset * 16);					/* the number of tiles to clear */					OUT_RING(nrtilesx + 1);					/* clear mask : chooses the clearing pattern. */					OUT_RING(clearmask);					ADVANCE_RING();					tileoffset += depthpixperline >> 5;				}			} else {	/* rv 100 */				/* rv100 might not need 64 pix alignment, who knows */				/* offsets are, hmm, weird */				tileoffset =				    ((pbox[i].y1 >> 4) * depthpixperline +				     pbox[i].x1) >> 6;				nrtilesx =				    ((pbox[i].x2 & ~63) -				     (pbox[i].x1 & ~63)) >> 4;				nrtilesy =				    (pbox[i].y2 >> 4) - (pbox[i].y1 >> 4);				for (j = 0; j <= nrtilesy; j++) {					BEGIN_RING(4);					OUT_RING(CP_PACKET3						 (RADEON_3D_CLEAR_ZMASK, 2));					OUT_RING(tileoffset * 128);					/* the number of tiles to clear */					OUT_RING(nrtilesx + 4);					/* clear mask : chooses the clearing pattern. */					OUT_RING(clearmask);					ADVANCE_RING();					tileoffset += depthpixperline >> 6;				}			}		}		/* TODO don't always clear all hi-level z tiles */		if ((dev_priv->flags & CHIP_HAS_HIERZ)		    && (dev_priv->microcode_version == UCODE_R200)		    && (flags & RADEON_USE_HIERZ))			/* r100 and cards without hierarchical z-buffer have no high-level z-buffer */			/* FIXME : the mask supposedly contains low-res z values. So can't set			   just to the max (0xff? or actually 0x3fff?), need to take z clear			   value into account? */		{			BEGIN_RING(4);			OUT_RING(CP_PACKET3(RADEON_3D_CLEAR_HIZ, 2));			OUT_RING(0x0);	/* First tile */			OUT_RING(0x3cc0);			OUT_RING((0xff << 22) | (0xff << 6) | 0x003f003f);			ADVANCE_RING();		}	}	/* We have to clear the depth and/or stencil buffers by	 * rendering a quad into just those buffers.  Thus, we have to	 * make sure the 3D engine is configured correctly.	 */	else if ((dev_priv->microcode_version == UCODE_R200) &&		(flags & (RADEON_DEPTH | RADEON_STENCIL))) {		int tempPP_CNTL;		int tempRE_CNTL;		int tempRB3D_CNTL;		int tempRB3D_ZSTENCILCNTL;		int tempRB3D_STENCILREFMASK;		int tempRB3D_PLANEMASK;		int tempSE_CNTL;		int tempSE_VTE_CNTL;		int tempSE_VTX_FMT_0;		int tempSE_VTX_FMT_1;		int tempSE_VAP_CNTL;		int tempRE_AUX_SCISSOR_CNTL;		tempPP_CNTL = 0;		tempRE_CNTL = 0;		tempRB3D_CNTL = depth_clear->rb3d_cntl;		tempRB3D_ZSTENCILCNTL = depth_clear->rb3d_zstencilcntl;		tempRB3D_STENCILREFMASK = 0x0;		tempSE_CNTL = depth_clear->se_cntl;		/* Disable TCL */		tempSE_VAP_CNTL = (	/* SE_VAP_CNTL__FORCE_W_TO_ONE_MASK |  */					  (0x9 <<					   SE_VAP_CNTL__VF_MAX_VTX_NUM__SHIFT));		tempRB3D_PLANEMASK = 0x0;		tempRE_AUX_SCISSOR_CNTL = 0x0;		tempSE_VTE_CNTL =		    SE_VTE_CNTL__VTX_XY_FMT_MASK | SE_VTE_CNTL__VTX_Z_FMT_MASK;		/* Vertex format (X, Y, Z, W) */		tempSE_VTX_FMT_0 =		    SE_VTX_FMT_0__VTX_Z0_PRESENT_MASK |		    SE_VTX_FMT_0__VTX_W0_PRESENT_MASK;		tempSE_VTX_FMT_1 = 0x0;		/*		 * Depth buffer specific enables		 */		if (flags & RADEON_DEPTH) {			/* Enable depth buffer */			tempRB3D_CNTL |= RADEON_Z_ENABLE;		} else {			/* Disable depth buffer */			tempRB3D_CNTL &= ~RADEON_Z_ENABLE;		}		/*		 * Stencil buffer specific enables		 */		if (flags & RADEON_STENCIL) {			tempRB3D_CNTL |= RADEON_STENCIL_ENABLE;			tempRB3D_STENCILREFMASK = clear->depth_mask;		} else {			tempRB3D_CNTL &= ~RADEON_STENCIL_ENABLE;			tempRB3D_STENCILREFMASK = 0x00000000;		}		if (flags & RADEON_USE_COMP_ZBUF) {			tempRB3D_ZSTENCILCNTL |= RADEON_Z_COMPRESSION_ENABLE |			    RADEON_Z_DECOMPRESSION_ENABLE;		}		if (flags & RADEON_USE_HIERZ) {			tempRB3D_ZSTENCILCNTL |= RADEON_Z_HIERARCHY_ENABLE;		}		BEGIN_RING(26);		RADEON_WAIT_UNTIL_2D_IDLE();		OUT_RING_REG(RADEON_PP_CNTL, tempPP_CNTL);		OUT_RING_REG(R200_RE_CNTL, tempRE_CNTL);		OUT_RING_REG(RADEON_RB3D_CNTL, tempRB3D_CNTL);		OUT_RING_REG(RADEON_RB3D_ZSTENCILCNTL, tempRB3D_ZSTENCILCNTL);		OUT_RING_REG(RADEON_RB3D_STENCILREFMASK,			     tempRB3D_STENCILREFMASK);		OUT_RING_REG(RADEON_RB3D_PLANEMASK, tempRB3D_PLANEMASK);		OUT_RING_REG(RADEON_SE_CNTL, tempSE_CNTL);		OUT_RING_REG(R200_SE_VTE_CNTL, tempSE_VTE_CNTL);		OUT_RING_REG(R200_SE_VTX_FMT_0, tempSE_VTX_FMT_0);		OUT_RING_REG(R200_SE_VTX_FMT_1, tempSE_VTX_FMT_1);		OUT_RING_REG(R200_SE_VAP_CNTL, tempSE_VAP_CNTL);		OUT_RING_REG(R200_RE_AUX_SCISSOR_CNTL, tempRE_AUX_SCISSOR_CNTL);		ADVANCE_RING();		/* Make sure we restore the 3D state next time.		 */		dev_priv->sarea_priv->ctx_owner = 0;		for (i = 0; i < nbox; i++) {			/* Funny that this should be required --			 *  sets top-left?			 */			radeon_emit_clip_rect(dev_priv, &sarea_priv->boxes[i]);			BEGIN_RING(14);			OUT_RING(CP_PACKET3(R200_3D_DRAW_IMMD_2, 12));			OUT_RING((RADEON_PRIM_TYPE_RECT_LIST |				  RADEON_PRIM_WALK_RING |				  (3 << RADEON_NUM_VERTICES_SHIFT)));			OUT_RING(depth_boxes[i].ui[CLEAR_X1]);			OUT_RING(depth_boxes[i].ui[CLEAR_Y1]);			OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]);			OUT_RING(0x3f800000);			OUT_RING(depth_boxes[i].ui[CLEAR_X1]);			OUT_RING(depth_boxes[i].ui[CLEAR_Y2]);			OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]);			OUT_RING(0x3f800000);			OUT_RING(depth_boxes[i].ui[CLEAR_X2]);			OUT_RING(depth_boxes[i].ui[CLEAR_Y2]);			OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]);			OUT_RING(0x3f800000);			ADVANCE_RING();		}	} else if ((flags & (RADEON_DEPTH | RADEON_STENCIL))) {		int tempRB3D_ZSTENCILCNTL = depth_clear->rb3d_zstencilcntl;		rb3d_cntl = depth_clear->rb3d_cntl;		if (flags & RADEON_DEPTH) {			rb3d_cntl |= RADEON_Z_ENABLE;		} else {			rb3d_cntl &= ~RADEON_Z_ENABLE;		}		if (flags & RADEON_STENCIL) {			rb3d_cntl |= RADEON_STENCIL_ENABLE;			rb3d_stencilrefmask = clear->depth_mask;	/* misnamed field */		} else {			rb3d_cntl &= ~RADEON_STENCIL_ENABLE;			rb3d_stencilrefmask = 0x00000000;		}		if (flags & RADEON_USE_COMP_ZBUF) {			tempRB3D_ZSTENCILCNTL |= RADEON_Z_COMPRESSION_ENABLE |			    RADEON_Z_DECOMPRESSION_ENABLE;		}		if (flags & RADEON_USE_HIERZ) {			tempRB3D_ZSTENCILCNTL |= RADEON_Z_HIERARCHY_ENABLE;		}		BEGIN_RING(13);		RADEON_WAIT_UNTIL_2D_IDLE();		OUT_RING(CP_PACKET0(RADEON_PP_CNTL, 1));		OUT_RING(0x00000000);		OUT_RING(rb3d_cntl);		OUT_RING_REG(RADEON_RB3D_ZSTENCILCNTL, tempRB3D_ZSTENCILCNTL);		OUT_RING_REG(RADEON_RB3D_STENCILREFMASK, rb3d_stencilrefmask);		OUT_RING_REG(RADEON_RB3D_PLANEMASK, 0x00000000);		OUT_RING_REG(RADEON_SE_CNTL, depth_clear->se_cntl);		ADVANCE_RING();		/* Make sure we restore the 3D state next time.		 */		dev_priv->sarea_priv->ctx_owner = 0;		for (i = 0; i < nbox; i++) {			/* Funny that this should be required --			 *  sets top-left?			 */			radeon_emit_clip_rect(dev_priv, &sarea_priv->boxes[i]);			BEGIN_RING(15);			OUT_RING(CP_PACKET3(RADEON_3D_DRAW_IMMD, 13));			OUT_RING(RADEON_VTX_Z_PRESENT |				 RADEON_VTX_PKCOLOR_PRESENT);			OUT_RING((RADEON_PRIM_TYPE_RECT_LIST |				  RADEON_PRIM_WALK_RING |				  RADEON_MAOS_ENABLE |				  RADEON_VTX_FMT_RADEON_MODE |				  (3 << RADEON_NUM_VERTICES_SHIFT)));			OUT_RING(depth_boxes[i].ui[CLEAR_X1]);			OUT_RING(depth_boxes[i].ui[CLEAR_Y1]);			OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]);			OUT_RING(0x0);			OUT_RING(depth_boxes[i].ui[CLEAR_X1]);			OUT_RING(depth_boxes[i].ui[CLEAR_Y2]);			OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]);			OUT_RING(0x0);			OUT_RING(depth_boxes[i].ui[CLEAR_X2]);			OUT_RING(depth_boxes[i].ui[CLEAR_Y2]);			OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]);			OUT_RING(0x0);			ADVANCE_RING();		}	}	/* Increment the clear counter.  The client-side 3D driver must	 * wait on this value before performing the clear ioctl.  We	 * need this because the card's so damned fast...	 */	dev_priv->sarea_priv->last_clear++;	BEGIN_RING(4);	RADEON_CLEAR_AGE(dev_priv->sarea_priv->last_clear);	RADEON_WAIT_UNTIL_IDLE();	ADVANCE_RING();}static void radeon_cp_dispatch_swap(drm_device_t * dev){	drm_radeon_private_t *dev_priv = dev->dev_private;	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;	int nbox = sarea_priv->nbox;	drm_clip_rect_t *pbox = sarea_priv->boxes;	int i;	RING_LOCALS;	DRM_DEBUG("\n");	/* Do some trivial performance monitoring...	 */	if (dev_priv->do_boxes)		radeon_cp_performance_boxes(dev_priv);	/* Wait for the 3D stream to idle before dispatching the bitblt.	 * This will prevent data corruption between the two streams.	 */	BEGIN_RING(2);	RADEON_WAIT_UNTIL_3D_IDLE();	ADVANCE_RING();	for (i = 0; i < nbox; i++) {		int x = pbox[i].x1;		int y = pbox[i].y1;		int w = pbox[i].x2 - x;		int h = pbox[i].y2 - y;		DRM_DEBUG("dispatch swap %d,%d-%d,%d\n", x, y, w, h);		BEGIN_RING(7);		OUT_RING(CP_PACKET3(RADEON_CNTL_BITBLT_MULTI, 5));		OUT_RING(RADEON_GMC_SRC_PITCH_OFFSET_CNTL |			 RADEON_GMC_DST_PITCH_OFFSET_CNTL |			 RADEON_GMC_BRUSH_NONE |			 (dev_priv->color_fmt << 8) |			 RADEON_GMC_SRC_DATATYPE_COLOR |			 RADEON_ROP3_S |			 RADEON_DP_SRC_SOURCE_MEMORY |			 RADEON_GMC_CLR_CMP_CNTL_DIS | RADEON_GMC_WR_MSK_DIS);		/* Make this work even if front & back are flipped:		 */		if (dev_priv->current_page == 0) {			OUT_RING(dev_priv->back_pitch_offset);			OUT_RING(dev_priv->front_pitch_offset);		} else {			OUT_RING(dev_priv->front_pitch_offset);			OUT_RING(dev_priv->back_pitch_offset);		}		OUT_RING((x << 16) | y);		OUT_RING((x << 16) | y);		OUT_RING((w << 16) | h);		ADVANCE_RING();	}	/* Increment the frame counter.  The client-side 3D driver must	 * throttle the framerate by waiting for this value before	 * performing the swapbuffer ioctl.	 */	dev_priv->sarea_priv->last_frame++;	BEGIN_RING(4);	RADEON_FRAME_AGE(dev_priv->sarea_priv->last_frame);	RADEON_WAIT_UNTIL_2D_IDLE();	ADVANCE_RING();}static void radeon_cp_dispatch_flip(drm_device_t * dev){	drm_radeon_private_t *dev_priv = dev->dev_private;	drm_sarea_t *sarea = (drm_sarea_t *) dev_priv->sarea->handle;	int offset = (dev_priv->current_page == 1)	    ? dev_priv->front_offset : dev_priv->back_offset;	RING_LOCALS;	DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n",		  __FUNCTION__,		  dev_priv->current_page, dev_priv->sarea_priv->pfCurrentPage);	/* Do some trivial performance monitoring...	 */	if (dev_priv->do_boxes) {		dev_priv->stats.boxes |= RADEON_BOX_FLIP;		radeon_cp_performance_boxes(dev_priv);	}	/* Update the frame offsets for both CRTCs	 */	BEGIN_RING(6);	RADEON_WAIT_UNTIL_3D_IDLE();	OUT_RING_REG(RADEON_CRTC_OFFSET,		     ((sarea->frame.y * dev_priv->front_pitch +		       sarea->frame.x * (dev_priv->color_fmt - 2)) & ~7)		     + offset);	OUT_RING_REG(RADEON_CRTC2_OFFSET, dev_priv->sarea_priv->crtc2_base		     + offset);	ADVANCE_RING();	/* Increment the frame counter.  The client-side 3D driver must	 * throttle the framerate by waiting for this value before	 * performing the swapbuffer ioctl.

⌨️ 快捷键说明

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