Beispiel #1
0
/**
 * Uploads user-supplied vertex program instructions or parameters onto
 * the graphics card.
 * Called by r300_do_cp_cmdbuf.
 */
static __inline__ int r300_emit_vpu(drm_radeon_private_t* dev_priv,
				    drm_radeon_cmd_buffer_t* cmdbuf,
				    drm_r300_cmd_header_t header)
{
	int sz;
	int addr;
	RING_LOCALS;

	sz = header.vpu.count;
	addr = (header.vpu.adrhi << 8) | header.vpu.adrlo;

	if (!sz)
		return 0;
	if (sz*16 > cmdbuf->bufsz)
		return DRM_ERR(EINVAL);

	BEGIN_RING(5+sz*4);
	/* Wait for VAP to come to senses.. */
	/* there is no need to emit it multiple times, (only once before VAP is programmed,
	   but this optimization is for later */
	OUT_RING_REG( R300_VAP_PVS_WAITIDLE, 0 );
	OUT_RING_REG( R300_VAP_PVS_UPLOAD_ADDRESS, addr );
	OUT_RING( CP_PACKET0_TABLE( R300_VAP_PVS_UPLOAD_DATA, sz*4 - 1 ) );
	OUT_RING_TABLE( (int __user*)cmdbuf->buf, sz*4 );

	ADVANCE_RING();

	cmdbuf->buf += sz*16;
	cmdbuf->bufsz -= sz*16;

	return 0;
}
static void
RADEONFlush2D(PixmapPtr pPix)
{
    RINFO_FROM_SCREEN(pPix->drawable.pScreen);

    TRACE;

    BEGIN_RING(2*2);
    OUT_RING_REG(RADEON_DSTCACHE_CTLSTAT, RADEON_RB2D_DC_FLUSH_ALL);
    OUT_RING_REG(RADEON_WAIT_UNTIL,
                  RADEON_WAIT_2D_IDLECLEAN | RADEON_WAIT_DMA_GUI_IDLE);
    ADVANCE_RING();
}
Beispiel #3
0
static int radeon_emit_irq(struct drm_device * dev)
{
	drm_radeon_private_t *dev_priv = dev->dev_private;
	unsigned int ret;
	RING_LOCALS;

	atomic_inc(&dev_priv->swi_emitted);
	ret = atomic_read(&dev_priv->swi_emitted);

	BEGIN_RING(4);
	OUT_RING_REG(RADEON_LAST_SWI_REG, ret);
	OUT_RING_REG(RADEON_GEN_INT_STATUS, RADEON_SW_INT_FIRE);
	ADVANCE_RING();
	COMMIT_RING();

	return ret;
}
static void
RADEONSolid(PixmapPtr pPix, int x1, int y1, int x2, int y2)
{
    RINFO_FROM_SCREEN(pPix->drawable.pScreen);

    TRACE;

    if (CS_FULL(info->cs)) {
	RADEONFlush2D(info->accel_state->dst_pix);
	radeon_cs_flush_indirect(pScrn);
    }

    if (info->accel_state->vsync)
	RADEONWaitForVLine(pScrn, pPix,
			   radeon_pick_best_crtc(pScrn, FALSE, x1, x2, y1, y2),
			   y1, y2);

    BEGIN_RING(2*2);
    OUT_RING_REG(RADEON_DST_Y_X, (y1 << 16) | x1);
    OUT_RING_REG(RADEON_DST_HEIGHT_WIDTH, ((y2 - y1) << 16) | (x2 - x1));
    ADVANCE_RING();
}
static void Emit2DState(ScrnInfoPtr pScrn, int op)
{
    RADEONInfoPtr info = RADEONPTR(pScrn);
    int has_src;

    /* don't emit if no operation in progress */
    if (info->state_2d.op == 0 && op == 0)
	return;

    has_src = info->state_2d.src_pitch_offset || info->state_2d.src_bo;

    if (has_src) {
      BEGIN_ACCEL_RELOC(10, 2);
    } else {
      BEGIN_ACCEL_RELOC(9, 1);
    }
    OUT_RING_REG(RADEON_DEFAULT_SC_BOTTOM_RIGHT, info->state_2d.default_sc_bottom_right);
    OUT_RING_REG(RADEON_DP_GUI_MASTER_CNTL, info->state_2d.dp_gui_master_cntl);
    OUT_RING_REG(RADEON_DP_BRUSH_FRGD_CLR, info->state_2d.dp_brush_frgd_clr);
    OUT_RING_REG(RADEON_DP_BRUSH_BKGD_CLR, info->state_2d.dp_brush_bkgd_clr);
    OUT_RING_REG(RADEON_DP_SRC_FRGD_CLR,   info->state_2d.dp_src_frgd_clr);
    OUT_RING_REG(RADEON_DP_SRC_BKGD_CLR,   info->state_2d.dp_src_bkgd_clr);
    OUT_RING_REG(RADEON_DP_WRITE_MASK, info->state_2d.dp_write_mask);
    OUT_RING_REG(RADEON_DP_CNTL, info->state_2d.dp_cntl);

    OUT_RING_REG(RADEON_DST_PITCH_OFFSET, info->state_2d.dst_pitch_offset);
    OUT_RING_RELOC(info->state_2d.dst_bo, 0, info->state_2d.dst_domain);

    if (has_src) {
	OUT_RING_REG(RADEON_SRC_PITCH_OFFSET, info->state_2d.src_pitch_offset);
	OUT_RING_RELOC(info->state_2d.src_bo, RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0);
    }
    ADVANCE_RING();

    if (op)
	info->state_2d.op = op;
    info->reemit_current2d = Emit2DState;
}
static void
RADEONCopy(PixmapPtr pDst,
	   int srcX, int srcY,
	   int dstX, int dstY,
	   int w, int h)
{
    RINFO_FROM_SCREEN(pDst->drawable.pScreen);

    TRACE;

    if (CS_FULL(info->cs)) {
        RADEONFlush2D(info->accel_state->dst_pix);
	radeon_cs_flush_indirect(pScrn);
    }

    if (info->accel_state->xdir < 0) {
	srcX += w - 1;
	dstX += w - 1;
    }
    if (info->accel_state->ydir < 0) {
	srcY += h - 1;
	dstY += h - 1;
    }

    if (info->accel_state->vsync)
	RADEONWaitForVLine(pScrn, pDst,
			   radeon_pick_best_crtc(pScrn, FALSE, dstX, dstX + w, dstY, dstY + h),
			   dstY, dstY + h);

    BEGIN_RING(2*3);

    OUT_RING_REG(RADEON_SRC_Y_X,	   (srcY << 16) | srcX);
    OUT_RING_REG(RADEON_DST_Y_X,	   (dstY << 16) | dstX);
    OUT_RING_REG(RADEON_DST_HEIGHT_WIDTH, (h  << 16) | w);

    ADVANCE_RING();
}
/* Emit blit with arbitrary source and destination offsets and pitches */
static void
RADEONBlitChunk(ScrnInfoPtr pScrn, struct radeon_bo *src_bo,
                struct radeon_bo *dst_bo, uint32_t datatype,
                uint32_t src_pitch_offset, uint32_t dst_pitch_offset,
                int srcX, int srcY, int dstX, int dstY, int w, int h,
                uint32_t src_domain, uint32_t dst_domain)
{
    RADEONInfoPtr info = RADEONPTR(pScrn);

    if (src_bo && dst_bo) {
        BEGIN_ACCEL_RELOC(6, 2);
    } else if (src_bo && dst_bo == NULL) {
        BEGIN_ACCEL_RELOC(6, 1);
    } else {
        BEGIN_RING(2*6);
    }
    OUT_RING_REG(RADEON_DP_GUI_MASTER_CNTL,
		  RADEON_GMC_DST_PITCH_OFFSET_CNTL |
		  RADEON_GMC_SRC_PITCH_OFFSET_CNTL |
		  RADEON_GMC_BRUSH_NONE |
		  (datatype << 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);
    OUT_RING_REG(RADEON_SRC_PITCH_OFFSET, src_pitch_offset);
    if (src_bo) {
	OUT_RING_RELOC(src_bo, src_domain, 0);
    }
    OUT_RING_REG(RADEON_DST_PITCH_OFFSET, dst_pitch_offset);
    if (dst_bo) {
	OUT_RING_RELOC(dst_bo, 0, dst_domain);
    }
    OUT_RING_REG(RADEON_SRC_Y_X, (srcY << 16) | srcX);
    OUT_RING_REG(RADEON_DST_Y_X, (dstY << 16) | dstX);
    OUT_RING_REG(RADEON_DST_HEIGHT_WIDTH, (h << 16) | w);
    ADVANCE_RING();
    BEGIN_RING(2*2);
    OUT_RING_REG(RADEON_DSTCACHE_CTLSTAT, RADEON_RB2D_DC_FLUSH_ALL);
    OUT_RING_REG(RADEON_WAIT_UNTIL,
                  RADEON_WAIT_2D_IDLECLEAN | RADEON_WAIT_DMA_GUI_IDLE);
    ADVANCE_RING();
}
Beispiel #8
0
/**
 * Emit up to R300_SIMULTANEOUS_CLIPRECTS cliprects from the given command
 * buffer, starting with index n.
 */
static int r300_emit_cliprects(drm_radeon_private_t* dev_priv,
			       drm_radeon_cmd_buffer_t* cmdbuf,
			       int n)
{
	drm_clip_rect_t box;
	int nr;
	int i;
	RING_LOCALS;

	nr = cmdbuf->nbox - n;
	if (nr > R300_SIMULTANEOUS_CLIPRECTS)
		nr = R300_SIMULTANEOUS_CLIPRECTS;

	DRM_DEBUG("%i cliprects\n", nr);

	if (nr) {
		BEGIN_RING(6 + nr*2);
		OUT_RING( CP_PACKET0( R300_RE_CLIPRECT_TL_0, nr*2 - 1 ) );

		for(i = 0; i < nr; ++i) {
			if (DRM_COPY_FROM_USER_UNCHECKED(&box, &cmdbuf->boxes[n+i], sizeof(box))) {
				DRM_ERROR("copy cliprect faulted\n");
				return DRM_ERR(EFAULT);
			}

			box.x1 = (box.x1 + R300_CLIPRECT_OFFSET) & R300_CLIPRECT_MASK;
			box.y1 = (box.y1 + R300_CLIPRECT_OFFSET) & R300_CLIPRECT_MASK;
			box.x2 = (box.x2 + R300_CLIPRECT_OFFSET) & R300_CLIPRECT_MASK;
			box.y2 = (box.y2 + R300_CLIPRECT_OFFSET) & R300_CLIPRECT_MASK;

			OUT_RING((box.x1 << R300_CLIPRECT_X_SHIFT) |
					(box.y1 << R300_CLIPRECT_Y_SHIFT));
			OUT_RING((box.x2 << R300_CLIPRECT_X_SHIFT) |
					(box.y2 << R300_CLIPRECT_Y_SHIFT));
		}

		OUT_RING_REG( R300_RE_CLIPRECT_CNTL, r300_cliprect_cntl[nr-1] );

		/* TODO/SECURITY: Force scissors to a safe value, otherwise the
		* client might be able to trample over memory.
		* The impact should be very limited, but I'd rather be safe than
		* sorry.
		*/
		OUT_RING( CP_PACKET0( R300_RE_SCISSORS_TL, 1 ) );
		OUT_RING( 0 );
		OUT_RING( R300_SCISSORS_X_MASK | R300_SCISSORS_Y_MASK );
		ADVANCE_RING();
		} else {
		/* Why we allow zero cliprect rendering:
		 * There are some commands in a command buffer that must be submitted
		 * even when there are no cliprects, e.g. DMA buffer discard
		 * or state setting (though state setting could be avoided by
		 * simulating a loss of context).
		 *
		 * Now since the cmdbuf interface is so chaotic right now (and is
		 * bound to remain that way for a bit until things settle down),
		 * it is basically impossible to filter out the commands that are
		 * necessary and those that aren't.
		 *
		 * So I choose the safe way and don't do any filtering at all;
		 * instead, I simply set up the engine so that all rendering
		 * can't produce any fragments.
		 */
		BEGIN_RING(2);
		OUT_RING_REG( R300_RE_CLIPRECT_CNTL, 0 );
		ADVANCE_RING();
		}

	return 0;
}