📄 savage_state.c
字号:
for (i = start + 1; i + 1 < start + count; i += 2) BCI_WRITE((i + reorder[i % 3]) | ((i + 1 + reorder[(i + 1) % 3]) << 16)); if (i < start + count) BCI_WRITE(i + reorder[i % 3]); } else if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) { BEGIN_BCI((count + 1 + 1) / 2); BCI_DRAW_INDICES_S3D(count, prim, start); for (i = start + 1; i + 1 < start + count; i += 2) BCI_WRITE(i | ((i + 1) << 16)); if (i < start + count) BCI_WRITE(i); } else { BEGIN_BCI((count + 2 + 1) / 2); BCI_DRAW_INDICES_S4(count, prim, skip); for (i = start; i + 1 < start + count; i += 2) BCI_WRITE(i | ((i + 1) << 16)); if (i < start + count) BCI_WRITE(i); } start += count; n -= count; prim |= BCI_CMD_DRAW_CONT; } return 0;}static int savage_dispatch_vb_prim(drm_savage_private_t * dev_priv, const drm_savage_cmd_header_t * cmd_header, const uint32_t __user * vtxbuf, unsigned int vb_size, unsigned int vb_stride){ unsigned char reorder = 0; unsigned int prim = cmd_header->prim.prim; unsigned int skip = cmd_header->prim.skip; unsigned int n = cmd_header->prim.count; unsigned int start = cmd_header->prim.start; unsigned int vtx_size; unsigned int i; DMA_LOCALS; if (!n) return 0; switch (prim) { case SAVAGE_PRIM_TRILIST_201: reorder = 1; prim = SAVAGE_PRIM_TRILIST; case SAVAGE_PRIM_TRILIST: if (n % 3 != 0) { DRM_ERROR("wrong number of vertices %u in TRILIST\n", n); return DRM_ERR(EINVAL); } break; case SAVAGE_PRIM_TRISTRIP: case SAVAGE_PRIM_TRIFAN: if (n < 3) { DRM_ERROR ("wrong number of vertices %u in TRIFAN/STRIP\n", n); return DRM_ERR(EINVAL); } break; default: DRM_ERROR("invalid primitive type %u\n", prim); return DRM_ERR(EINVAL); } if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) { if (skip > SAVAGE_SKIP_ALL_S3D) { DRM_ERROR("invalid skip flags 0x%04x\n", skip); return DRM_ERR(EINVAL); } vtx_size = 8; /* full vertex */ } else { if (skip > SAVAGE_SKIP_ALL_S4) { DRM_ERROR("invalid skip flags 0x%04x\n", skip); return DRM_ERR(EINVAL); } vtx_size = 10; /* full vertex */ } vtx_size -= (skip & 1) + (skip >> 1 & 1) + (skip >> 2 & 1) + (skip >> 3 & 1) + (skip >> 4 & 1) + (skip >> 5 & 1) + (skip >> 6 & 1) + (skip >> 7 & 1); if (vtx_size > vb_stride) { DRM_ERROR("vertex size greater than vb stride (%u > %u)\n", vtx_size, vb_stride); return DRM_ERR(EINVAL); } if (start + n > vb_size / (vb_stride * 4)) { DRM_ERROR("vertex indices (%u-%u) out of range (0-%u)\n", start, start + n - 1, vb_size / (vb_stride * 4)); return DRM_ERR(EINVAL); } prim <<= 25; while (n != 0) { /* Can emit up to 255 vertices (85 triangles) at once. */ unsigned int count = n > 255 ? 255 : n; if (reorder) { /* Need to reorder vertices for correct flat * shading while preserving the clock sense * for correct culling. Only on Savage3D. */ int reorder[3] = { -1, -1, -1 }; reorder[start % 3] = 2; BEGIN_DMA(count * vtx_size + 1); DMA_DRAW_PRIMITIVE(count, prim, skip); for (i = start; i < start + count; ++i) { unsigned int j = 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); if (vb_stride == vtx_size) { DMA_COPY_FROM_USER(&vtxbuf[vb_stride * start], vtx_size * count); } else { for (i = start; i < start + count; ++i) { DMA_COPY_FROM_USER(&vtxbuf [vb_stride * i], vtx_size); } } DMA_COMMIT(); } start += count; n -= count; prim |= BCI_CMD_DRAW_CONT; } return 0;}static int savage_dispatch_dma_idx(drm_savage_private_t * dev_priv, const drm_savage_cmd_header_t * cmd_header, const uint16_t __user * usr_idx, const drm_buf_t * dmabuf){ unsigned char reorder = 0; unsigned int prim = cmd_header->idx.prim; unsigned int skip = cmd_header->idx.skip; unsigned int n = cmd_header->idx.count; unsigned int i; BCI_LOCALS; if (!dmabuf) { DRM_ERROR("called without dma buffers!\n"); return DRM_ERR(EINVAL); } if (!n) return 0; switch (prim) { case SAVAGE_PRIM_TRILIST_201: reorder = 1; prim = SAVAGE_PRIM_TRILIST; case SAVAGE_PRIM_TRILIST: if (n % 3 != 0) { DRM_ERROR("wrong number of indices %u in TRILIST\n", n); return DRM_ERR(EINVAL); } break; case SAVAGE_PRIM_TRISTRIP: case SAVAGE_PRIM_TRIFAN: if (n < 3) { DRM_ERROR ("wrong number of indices %u in TRIFAN/STRIP\n", n); return DRM_ERR(EINVAL); } break; default: DRM_ERROR("invalid primitive type %u\n", prim); return DRM_ERR(EINVAL); } if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) { if (skip != 0) { DRM_ERROR("invalid skip flags 0x%04x for DMA\n", skip); return DRM_ERR(EINVAL); } } else { unsigned int size = 10 - (skip & 1) - (skip >> 1 & 1) - (skip >> 2 & 1) - (skip >> 3 & 1) - (skip >> 4 & 1) - (skip >> 5 & 1) - (skip >> 6 & 1) - (skip >> 7 & 1); if (skip > SAVAGE_SKIP_ALL_S4 || size != 8) { DRM_ERROR("invalid skip flags 0x%04x for DMA\n", skip); return DRM_ERR(EINVAL); } if (reorder) { DRM_ERROR("TRILIST_201 used on Savage4 hardware\n"); return DRM_ERR(EINVAL); } } /* Vertex DMA doesn't work with command DMA at the same time, * so we use BCI_... to submit commands here. Flush buffered * faked DMA first. */ DMA_FLUSH(); if (dmabuf->bus_address != dev_priv->state.common.vbaddr) { BEGIN_BCI(2); BCI_SET_REGISTERS(SAVAGE_VERTBUFADDR, 1); BCI_WRITE(dmabuf->bus_address | dev_priv->dma_type); dev_priv->state.common.vbaddr = dmabuf->bus_address; } if (S3_SAVAGE3D_SERIES(dev_priv->chipset) && dev_priv->waiting) { /* Workaround for what looks like a hardware bug. If a * WAIT_3D_IDLE was emitted some time before the * indexed drawing command then the engine will lock * up. There are two known workarounds: * WAIT_IDLE_EMPTY or emit at least 63 NOPs. */ BEGIN_BCI(63); for (i = 0; i < 63; ++i) BCI_WRITE(BCI_CMD_WAIT); dev_priv->waiting = 0; } prim <<= 25; while (n != 0) { /* Can emit up to 255 indices (85 triangles) at once. */ unsigned int count = n > 255 ? 255 : n; /* Is it ok to allocate 510 bytes on the stack in an ioctl? */ uint16_t idx[255]; /* Copy and check indices */ DRM_COPY_FROM_USER_UNCHECKED(idx, usr_idx, count * 2); for (i = 0; i < count; ++i) { if (idx[i] > dmabuf->total / 32) { DRM_ERROR("idx[%u]=%u out of range (0-%u)\n", i, idx[i], dmabuf->total / 32); return DRM_ERR(EINVAL); } } if (reorder) { /* Need to reorder indices for correct flat * shading while preserving the clock sense * for correct culling. Only on Savage3D. */ int reorder[3] = { 2, -1, -1 }; BEGIN_BCI((count + 1 + 1) / 2); BCI_DRAW_INDICES_S3D(count, prim, idx[2]); for (i = 1; i + 1 < count; i += 2) BCI_WRITE(idx[i + reorder[i % 3]] | (idx[i + 1 + reorder[(i + 1) % 3]] << 16)); if (i < count) BCI_WRITE(idx[i + reorder[i % 3]]); } else if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) { BEGIN_BCI((count + 1 + 1) / 2); BCI_DRAW_INDICES_S3D(count, prim, idx[0]); for (i = 1; i + 1 < count; i += 2) BCI_WRITE(idx[i] | (idx[i + 1] << 16)); if (i < count) BCI_WRITE(idx[i]); } else { BEGIN_BCI((count + 2 + 1) / 2); BCI_DRAW_INDICES_S4(count, prim, skip); for (i = 0; i + 1 < count; i += 2) BCI_WRITE(idx[i] | (idx[i + 1] << 16)); if (i < count) BCI_WRITE(idx[i]); } usr_idx += count; n -= count; prim |= BCI_CMD_DRAW_CONT; } return 0;}static int savage_dispatch_vb_idx(drm_savage_private_t * dev_priv, const drm_savage_cmd_header_t * cmd_header, const uint16_t __user * usr_idx, const uint32_t __user * vtxbuf, unsigned int vb_size, unsigned int vb_stride){ unsigned char reorder = 0; unsigned int prim = cmd_header->idx.prim; unsigned int skip = cmd_header->idx.skip; unsigned int n = cmd_header->idx.count; unsigned int vtx_size; unsigned int i; DMA_LOCALS; if (!n) return 0; switch (prim) { case SAVAGE_PRIM_TRILIST_201: reorder = 1; prim = SAVAGE_PRIM_TRILIST; case SAVAGE_PRIM_TRILIST: if (n % 3 != 0) { DRM_ERROR("wrong number of indices %u in TRILIST\n", n); return DRM_ERR(EINVAL); } break; case SAVAGE_PRIM_TRISTRIP: case SAVAGE_PRIM_TRIFAN: if (n < 3) { DRM_ERROR ("wrong number of indices %u in TRIFAN/STRIP\n", n); return DRM_ERR(EINVAL); } break; default: DRM_ERROR("invalid primitive type %u\n", prim); return DRM_ERR(EINVAL); } if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) { if (skip > SAVAGE_SKIP_ALL_S3D) { DRM_ERROR("invalid skip flags 0x%04x\n", skip); return DRM_ERR(EINVAL); } vtx_size = 8; /* full vertex */ } else { if (skip > SAVAGE_SKIP_ALL_S4) { DRM_ERROR("invalid skip flags 0x%04x\n", skip); return DRM_ERR(EINVAL); } vtx_size = 10; /* full vertex */ } vtx_size -= (skip & 1) + (skip >> 1 & 1) + (skip >> 2 & 1) + (skip >> 3 & 1) + (skip >> 4 & 1) + (skip >> 5 & 1) + (skip >> 6 & 1) + (skip >> 7 & 1); if (vtx_size > vb_stride) { DRM_ERROR("vertex size greater than vb stride (%u > %u)\n", vtx_size, vb_stride); return DRM_ERR(EINVAL); } prim <<= 25; while (n != 0) { /* Can emit up to 255 vertices (85 triangles) at once. */ unsigned int count = n > 255 ? 255 : n; /* Is it ok to allocate 510 bytes on the stack in an ioctl? */ uint16_t idx[255]; /* Copy and check indices */ DRM_COPY_FROM_USER_UNCHECKED(idx, usr_idx, count * 2); for (i = 0; i < count; ++i) { if (idx[i] > vb_size / (vb_stride * 4)) { DRM_ERROR("idx[%u]=%u out of range (0-%u)\n", i, idx[i], vb_size / (vb_stride * 4)); return DRM_ERR(EINVAL); } } if (reorder) { /* Need to reorder vertices for correct flat * 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) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -