savage_state.c

来自「底层驱动开发」· C语言 代码 · 共 1,147 行 · 第 1/3 页

C
1,147
字号
			 * shading while preserving the clock sense			 * for correct culling. Only on Savage3D. */			int reorder[3] = {2, -1, -1};			BEGIN_DMA(count*vtx_size+1);			DMA_DRAW_PRIMITIVE(count, prim, skip);			for (i = 0; i < count; ++i) {				unsigned int j = idx[i + reorder[i % 3]];				DMA_COPY_FROM_USER(&vtxbuf[vb_stride*j],						   vtx_size);			}			DMA_COMMIT();		} else {			BEGIN_DMA(count*vtx_size+1);			DMA_DRAW_PRIMITIVE(count, prim, skip);			for (i = 0; i < count; ++i) {				unsigned int j = idx[i];				DMA_COPY_FROM_USER(&vtxbuf[vb_stride*j],						   vtx_size);			}			DMA_COMMIT();		}		usr_idx += count;		n -= count;		prim |= BCI_CMD_DRAW_CONT;	}	return 0;}static int savage_dispatch_clear(drm_savage_private_t *dev_priv,				 const drm_savage_cmd_header_t *cmd_header,				 const drm_savage_cmd_header_t __user *data,				 unsigned int nbox,				 const drm_clip_rect_t __user *usr_boxes){	unsigned int flags = cmd_header->clear0.flags, mask, value;	unsigned int clear_cmd;	unsigned int i, nbufs;	DMA_LOCALS;	if (nbox == 0)		return 0;	DRM_GET_USER_UNCHECKED(mask, &((const drm_savage_cmd_header_t*)data)			       ->clear1.mask);	DRM_GET_USER_UNCHECKED(value, &((const drm_savage_cmd_header_t*)data)			       ->clear1.value);	clear_cmd = BCI_CMD_RECT | BCI_CMD_RECT_XP | BCI_CMD_RECT_YP |		BCI_CMD_SEND_COLOR | BCI_CMD_DEST_PBD_NEW;	BCI_CMD_SET_ROP(clear_cmd,0xCC);	nbufs = ((flags & SAVAGE_FRONT) ? 1 : 0) +		((flags & SAVAGE_BACK) ? 1 : 0) +		((flags & SAVAGE_DEPTH) ? 1 : 0);	if (nbufs == 0)		return 0;	if (mask != 0xffffffff) {		/* set mask */		BEGIN_DMA(2);		DMA_SET_REGISTERS(SAVAGE_BITPLANEWTMASK, 1);		DMA_WRITE(mask);		DMA_COMMIT();	}	for (i = 0; i < nbox; ++i) {		drm_clip_rect_t box;		unsigned int x, y, w, h;		unsigned int buf;		DRM_COPY_FROM_USER_UNCHECKED(&box, &usr_boxes[i], sizeof(box));		x = box.x1, y = box.y1;		w = box.x2 - box.x1;		h = box.y2 - box.y1;		BEGIN_DMA(nbufs*6);		for (buf = SAVAGE_FRONT; buf <= SAVAGE_DEPTH; buf <<= 1) {			if (!(flags & buf))				continue;			DMA_WRITE(clear_cmd);			switch(buf) {			case SAVAGE_FRONT:				DMA_WRITE(dev_priv->front_offset);				DMA_WRITE(dev_priv->front_bd);				break;			case SAVAGE_BACK:				DMA_WRITE(dev_priv->back_offset);				DMA_WRITE(dev_priv->back_bd);				break;			case SAVAGE_DEPTH:				DMA_WRITE(dev_priv->depth_offset);				DMA_WRITE(dev_priv->depth_bd);				break;			}			DMA_WRITE(value);			DMA_WRITE(BCI_X_Y(x, y));			DMA_WRITE(BCI_W_H(w, h));		}		DMA_COMMIT();	}	if (mask != 0xffffffff) {		/* reset mask */		BEGIN_DMA(2);		DMA_SET_REGISTERS(SAVAGE_BITPLANEWTMASK, 1);		DMA_WRITE(0xffffffff);		DMA_COMMIT();	}	return 0;}static int savage_dispatch_swap(drm_savage_private_t *dev_priv,				unsigned int nbox,				const drm_clip_rect_t __user *usr_boxes){	unsigned int swap_cmd;	unsigned int i;	DMA_LOCALS;	if (nbox == 0)		return 0;	swap_cmd = BCI_CMD_RECT | BCI_CMD_RECT_XP | BCI_CMD_RECT_YP |		BCI_CMD_SRC_PBD_COLOR_NEW | BCI_CMD_DEST_GBD;	BCI_CMD_SET_ROP(swap_cmd,0xCC);	for (i = 0; i < nbox; ++i) {		drm_clip_rect_t box;		DRM_COPY_FROM_USER_UNCHECKED(&box, &usr_boxes[i], sizeof(box));		BEGIN_DMA(6);		DMA_WRITE(swap_cmd);		DMA_WRITE(dev_priv->back_offset);		DMA_WRITE(dev_priv->back_bd);		DMA_WRITE(BCI_X_Y(box.x1, box.y1));		DMA_WRITE(BCI_X_Y(box.x1, box.y1));		DMA_WRITE(BCI_W_H(box.x2-box.x1, box.y2-box.y1));		DMA_COMMIT();	}	return 0;}static int savage_dispatch_draw(drm_savage_private_t *dev_priv,				const drm_savage_cmd_header_t __user *start,				const drm_savage_cmd_header_t __user *end,				const drm_buf_t *dmabuf,				const unsigned int __user *usr_vtxbuf,				unsigned int vb_size, unsigned int vb_stride,				unsigned int nbox,				const drm_clip_rect_t __user *usr_boxes){	unsigned int i, j;	int ret;	for (i = 0; i < nbox; ++i) {		drm_clip_rect_t box;		const drm_savage_cmd_header_t __user *usr_cmdbuf;		DRM_COPY_FROM_USER_UNCHECKED(&box, &usr_boxes[i], sizeof(box));		dev_priv->emit_clip_rect(dev_priv, &box);		usr_cmdbuf = start;		while (usr_cmdbuf < end) {			drm_savage_cmd_header_t cmd_header;			DRM_COPY_FROM_USER_UNCHECKED(&cmd_header, usr_cmdbuf,						     sizeof(cmd_header));			usr_cmdbuf++;			switch (cmd_header.cmd.cmd) {			case SAVAGE_CMD_DMA_PRIM:				ret = savage_dispatch_dma_prim(					dev_priv, &cmd_header, dmabuf);				break;			case SAVAGE_CMD_VB_PRIM:				ret = savage_dispatch_vb_prim(					dev_priv, &cmd_header,					(const uint32_t __user *)usr_vtxbuf,					vb_size, vb_stride);				break;			case SAVAGE_CMD_DMA_IDX:				j = (cmd_header.idx.count + 3) / 4;				/* j was check in savage_bci_cmdbuf */				ret = savage_dispatch_dma_idx(					dev_priv, &cmd_header,					(const uint16_t __user *)usr_cmdbuf,					dmabuf);				usr_cmdbuf += j;				break;			case SAVAGE_CMD_VB_IDX:				j = (cmd_header.idx.count + 3) / 4;				/* j was check in savage_bci_cmdbuf */				ret = savage_dispatch_vb_idx(					dev_priv, &cmd_header,					(const uint16_t __user *)usr_cmdbuf,					(const uint32_t __user *)usr_vtxbuf,					vb_size, vb_stride);				usr_cmdbuf += j;				break;			default:				/* What's the best return code? EFAULT? */				DRM_ERROR("IMPLEMENTATION ERROR: "					  "non-drawing-command %d\n",					  cmd_header.cmd.cmd);				return DRM_ERR(EINVAL);			}			if (ret != 0)				return ret;		}	}	return 0;}int savage_bci_cmdbuf(DRM_IOCTL_ARGS){	DRM_DEVICE;	drm_savage_private_t *dev_priv = dev->dev_private;	drm_device_dma_t *dma = dev->dma;	drm_buf_t *dmabuf;	drm_savage_cmdbuf_t cmdbuf;	drm_savage_cmd_header_t __user *usr_cmdbuf;	drm_savage_cmd_header_t __user *first_draw_cmd;	unsigned int __user *usr_vtxbuf;	drm_clip_rect_t __user *usr_boxes;	unsigned int i, j;	int ret = 0;	DRM_DEBUG("\n");		LOCK_TEST_WITH_RETURN(dev, filp);	DRM_COPY_FROM_USER_IOCTL(cmdbuf, (drm_savage_cmdbuf_t __user *)data,				 sizeof(cmdbuf));	if (dma && dma->buflist) {		if (cmdbuf.dma_idx > dma->buf_count) {			DRM_ERROR("vertex buffer index %u out of range (0-%u)\n",				  cmdbuf.dma_idx, dma->buf_count-1);			return DRM_ERR(EINVAL);		}		dmabuf = dma->buflist[cmdbuf.dma_idx];	} else {		dmabuf = NULL;	}	usr_cmdbuf = (drm_savage_cmd_header_t __user *)cmdbuf.cmd_addr;	usr_vtxbuf = (unsigned int __user *)cmdbuf.vb_addr;	usr_boxes = (drm_clip_rect_t __user *)cmdbuf.box_addr;	if ((cmdbuf.size && DRM_VERIFYAREA_READ(usr_cmdbuf, cmdbuf.size*8)) ||	    (cmdbuf.vb_size && DRM_VERIFYAREA_READ(		    usr_vtxbuf, cmdbuf.vb_size)) ||	    (cmdbuf.nbox && DRM_VERIFYAREA_READ(		    usr_boxes, cmdbuf.nbox*sizeof(drm_clip_rect_t))))		return DRM_ERR(EFAULT);	/* Make sure writes to DMA buffers are finished before sending	 * DMA commands to the graphics hardware. */	DRM_MEMORYBARRIER();	/* Coming from user space. Don't know if the Xserver has	 * emitted wait commands. Assuming the worst. */	dev_priv->waiting = 1;	i = 0;	first_draw_cmd = NULL;	while (i < cmdbuf.size) {		drm_savage_cmd_header_t cmd_header;		DRM_COPY_FROM_USER_UNCHECKED(&cmd_header, usr_cmdbuf,					     sizeof(cmd_header));		usr_cmdbuf++;		i++;		/* Group drawing commands with same state to minimize		 * iterations over clip rects. */		j = 0;		switch (cmd_header.cmd.cmd) {		case SAVAGE_CMD_DMA_IDX:		case SAVAGE_CMD_VB_IDX:			j = (cmd_header.idx.count + 3) / 4;			if (i + j > cmdbuf.size) {				DRM_ERROR("indexed drawing command extends "					  "beyond end of command buffer\n");				DMA_FLUSH();				return DRM_ERR(EINVAL);			}			/* fall through */		case SAVAGE_CMD_DMA_PRIM:		case SAVAGE_CMD_VB_PRIM:			if (!first_draw_cmd)				first_draw_cmd = usr_cmdbuf-1;			usr_cmdbuf += j;			i += j;			break;		default:			if (first_draw_cmd) {				ret = savage_dispatch_draw (					dev_priv, first_draw_cmd, usr_cmdbuf-1,					dmabuf, usr_vtxbuf, cmdbuf.vb_size,					cmdbuf.vb_stride,					cmdbuf.nbox, usr_boxes);				if (ret != 0)					return ret;				first_draw_cmd = NULL;			}		}		if (first_draw_cmd)			continue;		switch (cmd_header.cmd.cmd) {		case SAVAGE_CMD_STATE:			j = (cmd_header.state.count + 1) / 2;			if (i + j > cmdbuf.size) {				DRM_ERROR("command SAVAGE_CMD_STATE extends "					  "beyond end of command buffer\n");				DMA_FLUSH();				return DRM_ERR(EINVAL);			}			ret = savage_dispatch_state(				dev_priv, &cmd_header,				(uint32_t __user *)usr_cmdbuf);			usr_cmdbuf += j;			i += j;			break;		case SAVAGE_CMD_CLEAR:			if (i + 1 > cmdbuf.size) {				DRM_ERROR("command SAVAGE_CMD_CLEAR extends "					  "beyond end of command buffer\n");				DMA_FLUSH();				return DRM_ERR(EINVAL);			}			ret = savage_dispatch_clear(dev_priv, &cmd_header,						    usr_cmdbuf,						    cmdbuf.nbox, usr_boxes);			usr_cmdbuf++;			i++;			break;		case SAVAGE_CMD_SWAP:			ret = savage_dispatch_swap(dev_priv,						   cmdbuf.nbox, usr_boxes);			break;		default:			DRM_ERROR("invalid command 0x%x\n", cmd_header.cmd.cmd);			DMA_FLUSH();			return DRM_ERR(EINVAL);		}		if (ret != 0) {			DMA_FLUSH();			return ret;		}	}	if (first_draw_cmd) {		ret = savage_dispatch_draw (			dev_priv, first_draw_cmd, usr_cmdbuf, dmabuf,			usr_vtxbuf, cmdbuf.vb_size, cmdbuf.vb_stride,			cmdbuf.nbox, usr_boxes);		if (ret != 0) {			DMA_FLUSH();			return ret;		}	}	DMA_FLUSH();	if (dmabuf && cmdbuf.discard) {		drm_savage_buf_priv_t *buf_priv = dmabuf->dev_private;		uint16_t event;		event = savage_bci_emit_event(dev_priv, SAVAGE_WAIT_3D);		SET_AGE(&buf_priv->age, event, dev_priv->event_wrap);		savage_freelist_put(dev, dmabuf);	}	return 0;}

⌨️ 快捷键说明

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