radeon_state.c

来自「linux 内核源代码」· C语言 代码 · 共 2,223 行 · 第 1/5 页

C
2,223
字号
	RADEON_WAIT_UNTIL_IDLE();	ADVANCE_RING();}static void radeon_cp_dispatch_swap(struct drm_device * 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;	struct drm_clip_rect *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(9);		OUT_RING(CP_PACKET0(RADEON_DP_GUI_MASTER_CNTL, 0));		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:		 */		OUT_RING(CP_PACKET0(RADEON_SRC_PITCH_OFFSET, 1));		if (dev_priv->sarea_priv->pfCurrentPage == 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(CP_PACKET0(RADEON_SRC_X_Y, 2));		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(struct drm_device * dev){	drm_radeon_private_t *dev_priv = dev->dev_private;	struct drm_sarea *sarea = (struct drm_sarea *) dev_priv->sarea->handle;	int offset = (dev_priv->sarea_priv->pfCurrentPage == 1)	    ? dev_priv->front_offset : dev_priv->back_offset;	RING_LOCALS;	DRM_DEBUG("%s: pfCurrentPage=%d\n",		  __FUNCTION__,		  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.	 */	dev_priv->sarea_priv->last_frame++;	dev_priv->sarea_priv->pfCurrentPage =		1 - dev_priv->sarea_priv->pfCurrentPage;	BEGIN_RING(2);	RADEON_FRAME_AGE(dev_priv->sarea_priv->last_frame);	ADVANCE_RING();}static int bad_prim_vertex_nr(int primitive, int nr){	switch (primitive & RADEON_PRIM_TYPE_MASK) {	case RADEON_PRIM_TYPE_NONE:	case RADEON_PRIM_TYPE_POINT:		return nr < 1;	case RADEON_PRIM_TYPE_LINE:		return (nr & 1) || nr == 0;	case RADEON_PRIM_TYPE_LINE_STRIP:		return nr < 2;	case RADEON_PRIM_TYPE_TRI_LIST:	case RADEON_PRIM_TYPE_3VRT_POINT_LIST:	case RADEON_PRIM_TYPE_3VRT_LINE_LIST:	case RADEON_PRIM_TYPE_RECT_LIST:		return nr % 3 || nr == 0;	case RADEON_PRIM_TYPE_TRI_FAN:	case RADEON_PRIM_TYPE_TRI_STRIP:		return nr < 3;	default:		return 1;	}}typedef struct {	unsigned int start;	unsigned int finish;	unsigned int prim;	unsigned int numverts;	unsigned int offset;	unsigned int vc_format;} drm_radeon_tcl_prim_t;static void radeon_cp_dispatch_vertex(struct drm_device * dev,				      struct drm_buf * buf,				      drm_radeon_tcl_prim_t * prim){	drm_radeon_private_t *dev_priv = dev->dev_private;	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;	int offset = dev_priv->gart_buffers_offset + buf->offset + prim->start;	int numverts = (int)prim->numverts;	int nbox = sarea_priv->nbox;	int i = 0;	RING_LOCALS;	DRM_DEBUG("hwprim 0x%x vfmt 0x%x %d..%d %d verts\n",		  prim->prim,		  prim->vc_format, prim->start, prim->finish, prim->numverts);	if (bad_prim_vertex_nr(prim->prim, prim->numverts)) {		DRM_ERROR("bad prim %x numverts %d\n",			  prim->prim, prim->numverts);		return;	}	do {		/* Emit the next cliprect */		if (i < nbox) {			radeon_emit_clip_rect(dev_priv, &sarea_priv->boxes[i]);		}		/* Emit the vertex buffer rendering commands */		BEGIN_RING(5);		OUT_RING(CP_PACKET3(RADEON_3D_RNDR_GEN_INDX_PRIM, 3));		OUT_RING(offset);		OUT_RING(numverts);		OUT_RING(prim->vc_format);		OUT_RING(prim->prim | RADEON_PRIM_WALK_LIST |			 RADEON_COLOR_ORDER_RGBA |			 RADEON_VTX_FMT_RADEON_MODE |			 (numverts << RADEON_NUM_VERTICES_SHIFT));		ADVANCE_RING();		i++;	} while (i < nbox);}static void radeon_cp_discard_buffer(struct drm_device * dev, struct drm_buf * buf){	drm_radeon_private_t *dev_priv = dev->dev_private;	drm_radeon_buf_priv_t *buf_priv = buf->dev_private;	RING_LOCALS;	buf_priv->age = ++dev_priv->sarea_priv->last_dispatch;	/* Emit the vertex buffer age */	BEGIN_RING(2);	RADEON_DISPATCH_AGE(buf_priv->age);	ADVANCE_RING();	buf->pending = 1;	buf->used = 0;}static void radeon_cp_dispatch_indirect(struct drm_device * dev,					struct drm_buf * buf, int start, int end){	drm_radeon_private_t *dev_priv = dev->dev_private;	RING_LOCALS;	DRM_DEBUG("indirect: buf=%d s=0x%x e=0x%x\n", buf->idx, start, end);	if (start != end) {		int offset = (dev_priv->gart_buffers_offset			      + buf->offset + start);		int dwords = (end - start + 3) / sizeof(u32);		/* Indirect buffer data must be an even number of		 * dwords, so if we've been given an odd number we must		 * pad the data with a Type-2 CP packet.		 */		if (dwords & 1) {			u32 *data = (u32 *)			    ((char *)dev->agp_buffer_map->handle			     + buf->offset + start);			data[dwords++] = RADEON_CP_PACKET2;		}		/* Fire off the indirect buffer */		BEGIN_RING(3);		OUT_RING(CP_PACKET0(RADEON_CP_IB_BASE, 1));		OUT_RING(offset);		OUT_RING(dwords);		ADVANCE_RING();	}}static void radeon_cp_dispatch_indices(struct drm_device * dev,				       struct drm_buf * elt_buf,				       drm_radeon_tcl_prim_t * prim){	drm_radeon_private_t *dev_priv = dev->dev_private;	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;	int offset = dev_priv->gart_buffers_offset + prim->offset;	u32 *data;	int dwords;	int i = 0;	int start = prim->start + RADEON_INDEX_PRIM_OFFSET;	int count = (prim->finish - start) / sizeof(u16);	int nbox = sarea_priv->nbox;	DRM_DEBUG("hwprim 0x%x vfmt 0x%x %d..%d offset: %x nr %d\n",		  prim->prim,		  prim->vc_format,		  prim->start, prim->finish, prim->offset, prim->numverts);	if (bad_prim_vertex_nr(prim->prim, count)) {		DRM_ERROR("bad prim %x count %d\n", prim->prim, count);		return;	}	if (start >= prim->finish || (prim->start & 0x7)) {		DRM_ERROR("buffer prim %d\n", prim->prim);		return;	}	dwords = (prim->finish - prim->start + 3) / sizeof(u32);	data = (u32 *) ((char *)dev->agp_buffer_map->handle +			elt_buf->offset + prim->start);	data[0] = CP_PACKET3(RADEON_3D_RNDR_GEN_INDX_PRIM, dwords - 2);	data[1] = offset;	data[2] = prim->numverts;	data[3] = prim->vc_format;	data[4] = (prim->prim |		   RADEON_PRIM_WALK_IND |		   RADEON_COLOR_ORDER_RGBA |		   RADEON_VTX_FMT_RADEON_MODE |		   (count << RADEON_NUM_VERTICES_SHIFT));	do {		if (i < nbox)			radeon_emit_clip_rect(dev_priv, &sarea_priv->boxes[i]);		radeon_cp_dispatch_indirect(dev, elt_buf,					    prim->start, prim->finish);		i++;	} while (i < nbox);}#define RADEON_MAX_TEXTURE_SIZE RADEON_BUFFER_SIZEstatic int radeon_cp_dispatch_texture(struct drm_device * dev,				      struct drm_file *file_priv,				      drm_radeon_texture_t * tex,				      drm_radeon_tex_image_t * image){	drm_radeon_private_t *dev_priv = dev->dev_private;	struct drm_buf *buf;	u32 format;	u32 *buffer;	const u8 __user *data;	int size, dwords, tex_width, blit_width, spitch;	u32 height;	int i;	u32 texpitch, microtile;	u32 offset;	RING_LOCALS;	if (radeon_check_and_fixup_offset(dev_priv, file_priv, &tex->offset)) {		DRM_ERROR("Invalid destination offset\n");		return -EINVAL;	}	dev_priv->stats.boxes |= RADEON_BOX_TEXTURE_LOAD;	/* Flush the pixel cache.  This ensures no pixel data gets mixed	 * up with the texture data from the host data blit, otherwise	 * part of the texture image may be corrupted.	 */	BEGIN_RING(4);	RADEON_FLUSH_CACHE();	RADEON_WAIT_UNTIL_IDLE();	ADVANCE_RING();	/* The compiler won't optimize away a division by a variable,	 * even if the only legal values are powers of two.  Thus, we'll	 * use a shift instead.	 */	switch (tex->format) {	case RADEON_TXFORMAT_ARGB8888:	case RADEON_TXFORMAT_RGBA8888:		format = RADEON_COLOR_FORMAT_ARGB8888;		tex_width = tex->width * 4;		blit_width = image->width * 4;		break;	case RADEON_TXFORMAT_AI88:	case RADEON_TXFORMAT_ARGB1555:	case RADEON_TXFORMAT_RGB565:	case RADEON_TXFORMAT_ARGB4444:	case RADEON_TXFORMAT_VYUY422:	case RADEON_TXFORMAT_YVYU422:		format = RADEON_COLOR_FORMAT_RGB565;		tex_width = tex->width * 2;		blit_width = image->width * 2;		break;	case RADEON_TXFORMAT_I8:	case RADEON_TXFORMAT_RGB332:		format = RADEON_COLOR_FORMAT_CI8;		tex_width = tex->width * 1;		blit_width = image->width * 1;		break;	default:		DRM_ERROR("invalid texture format %d\n", tex->format);		return -EINVAL;	}	spitch = blit_width >> 6;	if (spitch == 0 && image->height > 1)		return -EINVAL;	texpitch = tex->pitch;	if ((texpitch << 22) & RADEON_DST_TILE_MICRO) {		microtile = 1;		if (tex_width < 64) {			texpitch &= ~(RADEON_DST_TILE_MICRO >> 22);			/* we got tiled coordinates, untile them */			image->x *= 2;		}	} else		microtile = 0;	DRM_DEBUG("tex=%dx%d blit=%d\n", tex_width, tex->height, blit_width);	do {		DRM_DEBUG("tex: ofs=0x%x p=%d f=%d x=%hd y=%hd w=%hd h=%hd\n",			  tex->offset >> 10, tex->pitch, tex->format,			  image->x, image->y, image->width, image->height);		/* Make a copy of some parameters in case we have to		 * update them for a multi-pass texture blit.		 */		height = image->height;		data = (const u8 __user *)image->data;		size = height * blit_width;		if (size > RADEON_MAX_TEXTURE_SIZE) {			height = RADEON_MAX_TEXTURE_SIZE / blit_width;			size = height * blit_width;		} else if (size < 4 && size > 0) {			size = 4;		} else if (size == 0) {			return 0;		}		buf = radeon_freelist_get(dev);		if (0 && !buf) {			radeon_do_cp_idle(dev_priv);			buf = radeon_freelist_get(dev);		}		if (!buf) {			DRM_DEBUG("radeon_cp_dispatch_texture: EAGAIN\n");			if (DRM_COPY_TO_USER(tex->image, image, sizeof(*image)))				return -EFAULT;			return -EAGAIN;		}		/* Dispatch the indirect buffer.		 */		buffer =		    (u32 *) ((char *)dev->agp_buffer_map->handle + buf->offset);		dwords = size / 4;#define RADEON_COPY_MT(_buf, _data, _width) \	do { \		if (DRM_COPY_FROM_USER(_buf, _data, (_width))) {\			DRM_ERROR("EFAULT on pad, %d bytes\n", (_width)); \			return -EFAULT; \		} \	} while(0)

⌨️ 快捷键说明

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