📄 savage_state.c
字号:
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, &data->clear1.mask); DRM_GET_USER_UNCHECKED(value, &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 + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -