i810_dma.c
来自「linux 内核源代码」· C语言 代码 · 共 1,290 行 · 第 1/3 页
C
1,290 行
static int i810_dma_init(struct drm_device *dev, void *data, struct drm_file *file_priv){ drm_i810_private_t *dev_priv; drm_i810_init_t *init = data; int retcode = 0; switch (init->func) { case I810_INIT_DMA_1_4: DRM_INFO("Using v1.4 init.\n"); dev_priv = drm_alloc(sizeof(drm_i810_private_t), DRM_MEM_DRIVER); if (dev_priv == NULL) return -ENOMEM; retcode = i810_dma_initialize(dev, dev_priv, init); break; case I810_CLEANUP_DMA: DRM_INFO("DMA Cleanup\n"); retcode = i810_dma_cleanup(dev); break; default: return -EINVAL; } return retcode;}/* Most efficient way to verify state for the i810 is as it is * emitted. Non-conformant state is silently dropped. * * Use 'volatile' & local var tmp to force the emitted values to be * identical to the verified ones. */static void i810EmitContextVerified(struct drm_device * dev, volatile unsigned int *code){ drm_i810_private_t *dev_priv = dev->dev_private; int i, j = 0; unsigned int tmp; RING_LOCALS; BEGIN_LP_RING(I810_CTX_SETUP_SIZE); OUT_RING(GFX_OP_COLOR_FACTOR); OUT_RING(code[I810_CTXREG_CF1]); OUT_RING(GFX_OP_STIPPLE); OUT_RING(code[I810_CTXREG_ST1]); for (i = 4; i < I810_CTX_SETUP_SIZE; i++) { tmp = code[i]; if ((tmp & (7 << 29)) == (3 << 29) && (tmp & (0x1f << 24)) < (0x1d << 24)) { OUT_RING(tmp); j++; } else printk("constext state dropped!!!\n"); } if (j & 1) OUT_RING(0); ADVANCE_LP_RING();}static void i810EmitTexVerified(struct drm_device * dev, volatile unsigned int *code){ drm_i810_private_t *dev_priv = dev->dev_private; int i, j = 0; unsigned int tmp; RING_LOCALS; BEGIN_LP_RING(I810_TEX_SETUP_SIZE); OUT_RING(GFX_OP_MAP_INFO); OUT_RING(code[I810_TEXREG_MI1]); OUT_RING(code[I810_TEXREG_MI2]); OUT_RING(code[I810_TEXREG_MI3]); for (i = 4; i < I810_TEX_SETUP_SIZE; i++) { tmp = code[i]; if ((tmp & (7 << 29)) == (3 << 29) && (tmp & (0x1f << 24)) < (0x1d << 24)) { OUT_RING(tmp); j++; } else printk("texture state dropped!!!\n"); } if (j & 1) OUT_RING(0); ADVANCE_LP_RING();}/* Need to do some additional checking when setting the dest buffer. */static void i810EmitDestVerified(struct drm_device * dev, volatile unsigned int *code){ drm_i810_private_t *dev_priv = dev->dev_private; unsigned int tmp; RING_LOCALS; BEGIN_LP_RING(I810_DEST_SETUP_SIZE + 2); tmp = code[I810_DESTREG_DI1]; if (tmp == dev_priv->front_di1 || tmp == dev_priv->back_di1) { OUT_RING(CMD_OP_DESTBUFFER_INFO); OUT_RING(tmp); } else DRM_DEBUG("bad di1 %x (allow %x or %x)\n", tmp, dev_priv->front_di1, dev_priv->back_di1); /* invarient: */ OUT_RING(CMD_OP_Z_BUFFER_INFO); OUT_RING(dev_priv->zi1); OUT_RING(GFX_OP_DESTBUFFER_VARS); OUT_RING(code[I810_DESTREG_DV1]); OUT_RING(GFX_OP_DRAWRECT_INFO); OUT_RING(code[I810_DESTREG_DR1]); OUT_RING(code[I810_DESTREG_DR2]); OUT_RING(code[I810_DESTREG_DR3]); OUT_RING(code[I810_DESTREG_DR4]); OUT_RING(0); ADVANCE_LP_RING();}static void i810EmitState(struct drm_device * dev){ drm_i810_private_t *dev_priv = dev->dev_private; drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv; unsigned int dirty = sarea_priv->dirty; DRM_DEBUG("%s %x\n", __FUNCTION__, dirty); if (dirty & I810_UPLOAD_BUFFERS) { i810EmitDestVerified(dev, sarea_priv->BufferState); sarea_priv->dirty &= ~I810_UPLOAD_BUFFERS; } if (dirty & I810_UPLOAD_CTX) { i810EmitContextVerified(dev, sarea_priv->ContextState); sarea_priv->dirty &= ~I810_UPLOAD_CTX; } if (dirty & I810_UPLOAD_TEX0) { i810EmitTexVerified(dev, sarea_priv->TexState[0]); sarea_priv->dirty &= ~I810_UPLOAD_TEX0; } if (dirty & I810_UPLOAD_TEX1) { i810EmitTexVerified(dev, sarea_priv->TexState[1]); sarea_priv->dirty &= ~I810_UPLOAD_TEX1; }}/* need to verify */static void i810_dma_dispatch_clear(struct drm_device * dev, int flags, unsigned int clear_color, unsigned int clear_zval){ drm_i810_private_t *dev_priv = dev->dev_private; drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv; int nbox = sarea_priv->nbox; struct drm_clip_rect *pbox = sarea_priv->boxes; int pitch = dev_priv->pitch; int cpp = 2; int i; RING_LOCALS; if (dev_priv->current_page == 1) { unsigned int tmp = flags; flags &= ~(I810_FRONT | I810_BACK); if (tmp & I810_FRONT) flags |= I810_BACK; if (tmp & I810_BACK) flags |= I810_FRONT; } i810_kernel_lost_context(dev); if (nbox > I810_NR_SAREA_CLIPRECTS) nbox = I810_NR_SAREA_CLIPRECTS; for (i = 0; i < nbox; i++, pbox++) { unsigned int x = pbox->x1; unsigned int y = pbox->y1; unsigned int width = (pbox->x2 - x) * cpp; unsigned int height = pbox->y2 - y; unsigned int start = y * pitch + x * cpp; if (pbox->x1 > pbox->x2 || pbox->y1 > pbox->y2 || pbox->x2 > dev_priv->w || pbox->y2 > dev_priv->h) continue; if (flags & I810_FRONT) { BEGIN_LP_RING(6); OUT_RING(BR00_BITBLT_CLIENT | BR00_OP_COLOR_BLT | 0x3); OUT_RING(BR13_SOLID_PATTERN | (0xF0 << 16) | pitch); OUT_RING((height << 16) | width); OUT_RING(start); OUT_RING(clear_color); OUT_RING(0); ADVANCE_LP_RING(); } if (flags & I810_BACK) { BEGIN_LP_RING(6); OUT_RING(BR00_BITBLT_CLIENT | BR00_OP_COLOR_BLT | 0x3); OUT_RING(BR13_SOLID_PATTERN | (0xF0 << 16) | pitch); OUT_RING((height << 16) | width); OUT_RING(dev_priv->back_offset + start); OUT_RING(clear_color); OUT_RING(0); ADVANCE_LP_RING(); } if (flags & I810_DEPTH) { BEGIN_LP_RING(6); OUT_RING(BR00_BITBLT_CLIENT | BR00_OP_COLOR_BLT | 0x3); OUT_RING(BR13_SOLID_PATTERN | (0xF0 << 16) | pitch); OUT_RING((height << 16) | width); OUT_RING(dev_priv->depth_offset + start); OUT_RING(clear_zval); OUT_RING(0); ADVANCE_LP_RING(); } }}static void i810_dma_dispatch_swap(struct drm_device * dev){ drm_i810_private_t *dev_priv = dev->dev_private; drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv; int nbox = sarea_priv->nbox; struct drm_clip_rect *pbox = sarea_priv->boxes; int pitch = dev_priv->pitch; int cpp = 2; int i; RING_LOCALS; DRM_DEBUG("swapbuffers\n"); i810_kernel_lost_context(dev); if (nbox > I810_NR_SAREA_CLIPRECTS) nbox = I810_NR_SAREA_CLIPRECTS; for (i = 0; i < nbox; i++, pbox++) { unsigned int w = pbox->x2 - pbox->x1; unsigned int h = pbox->y2 - pbox->y1; unsigned int dst = pbox->x1 * cpp + pbox->y1 * pitch; unsigned int start = dst; if (pbox->x1 > pbox->x2 || pbox->y1 > pbox->y2 || pbox->x2 > dev_priv->w || pbox->y2 > dev_priv->h) continue; BEGIN_LP_RING(6); OUT_RING(BR00_BITBLT_CLIENT | BR00_OP_SRC_COPY_BLT | 0x4); OUT_RING(pitch | (0xCC << 16)); OUT_RING((h << 16) | (w * cpp)); if (dev_priv->current_page == 0) OUT_RING(dev_priv->front_offset + start); else OUT_RING(dev_priv->back_offset + start); OUT_RING(pitch); if (dev_priv->current_page == 0) OUT_RING(dev_priv->back_offset + start); else OUT_RING(dev_priv->front_offset + start); ADVANCE_LP_RING(); }}static void i810_dma_dispatch_vertex(struct drm_device * dev, struct drm_buf * buf, int discard, int used){ drm_i810_private_t *dev_priv = dev->dev_private; drm_i810_buf_priv_t *buf_priv = buf->dev_private; drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv; struct drm_clip_rect *box = sarea_priv->boxes; int nbox = sarea_priv->nbox; unsigned long address = (unsigned long)buf->bus_address; unsigned long start = address - dev->agp->base; int i = 0; RING_LOCALS; i810_kernel_lost_context(dev); if (nbox > I810_NR_SAREA_CLIPRECTS) nbox = I810_NR_SAREA_CLIPRECTS; if (used > 4 * 1024) used = 0; if (sarea_priv->dirty) i810EmitState(dev); if (buf_priv->currently_mapped == I810_BUF_MAPPED) { unsigned int prim = (sarea_priv->vertex_prim & PR_MASK); *(u32 *) buf_priv->kernel_virtual = ((GFX_OP_PRIMITIVE | prim | ((used / 4) - 2))); if (used & 4) { *(u32 *) ((char *) buf_priv->kernel_virtual + used) = 0; used += 4; } i810_unmap_buffer(buf); } if (used) { do { if (i < nbox) { BEGIN_LP_RING(4); OUT_RING(GFX_OP_SCISSOR | SC_UPDATE_SCISSOR | SC_ENABLE); OUT_RING(GFX_OP_SCISSOR_INFO); OUT_RING(box[i].x1 | (box[i].y1 << 16)); OUT_RING((box[i].x2 - 1) | ((box[i].y2 - 1) << 16)); ADVANCE_LP_RING(); } BEGIN_LP_RING(4); OUT_RING(CMD_OP_BATCH_BUFFER); OUT_RING(start | BB1_PROTECTED); OUT_RING(start + used - 4); OUT_RING(0); ADVANCE_LP_RING(); } while (++i < nbox); } if (discard) { dev_priv->counter++; (void)cmpxchg(buf_priv->in_use, I810_BUF_CLIENT, I810_BUF_HARDWARE); BEGIN_LP_RING(8); OUT_RING(CMD_STORE_DWORD_IDX); OUT_RING(20); OUT_RING(dev_priv->counter); OUT_RING(CMD_STORE_DWORD_IDX); OUT_RING(buf_priv->my_use_idx); OUT_RING(I810_BUF_FREE); OUT_RING(CMD_REPORT_HEAD); OUT_RING(0); ADVANCE_LP_RING(); }}static void i810_dma_dispatch_flip(struct drm_device * dev){ drm_i810_private_t *dev_priv = dev->dev_private; int pitch = dev_priv->pitch; RING_LOCALS; DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n", __FUNCTION__, dev_priv->current_page, dev_priv->sarea_priv->pf_current_page); i810_kernel_lost_context(dev); BEGIN_LP_RING(2); OUT_RING(INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE); OUT_RING(0); ADVANCE_LP_RING(); BEGIN_LP_RING(I810_DEST_SETUP_SIZE + 2); /* On i815 at least ASYNC is buggy */ /* pitch<<5 is from 11.2.8 p158, its the pitch / 8 then left shifted 8, so (pitch >> 3) << 8 */ OUT_RING(CMD_OP_FRONTBUFFER_INFO | (pitch << 5) /*| ASYNC_FLIP */ ); if (dev_priv->current_page == 0) { OUT_RING(dev_priv->back_offset); dev_priv->current_page = 1; } else { OUT_RING(dev_priv->front_offset); dev_priv->current_page = 0; } OUT_RING(0); ADVANCE_LP_RING(); BEGIN_LP_RING(2); OUT_RING(CMD_OP_WAIT_FOR_EVENT | WAIT_FOR_PLANE_A_FLIP); OUT_RING(0); ADVANCE_LP_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->pf_current_page = dev_priv->current_page;}static void i810_dma_quiescent(struct drm_device * dev){ drm_i810_private_t *dev_priv = dev->dev_private; RING_LOCALS;/* printk("%s\n", __FUNCTION__); */ i810_kernel_lost_context(dev); BEGIN_LP_RING(4); OUT_RING(INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE); OUT_RING(CMD_REPORT_HEAD); OUT_RING(0); OUT_RING(0); ADVANCE_LP_RING();
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?