static Bool
setup_render_target(NVPtr pNv, PicturePtr pict, PixmapPtr pixmap)
{
	struct nouveau_pushbuf *push = pNv->pushbuf;
	struct nouveau_bo *bo = nouveau_pixmap_bo(pixmap);

	BEGIN_NV04(push, NV10_3D(RT_FORMAT), 3);
	PUSH_DATA (push, get_rt_format(pict));
	PUSH_DATA (push, (exaGetPixmapPitch(pixmap) << 16 |
			  exaGetPixmapPitch(pixmap)));
	PUSH_MTHDl(push, NV10_3D(COLOR_OFFSET), bo, 0,
			 NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR);
	return TRUE;
}
Exemple #2
0
static Bool
NV30_SetupSurface(ScrnInfoPtr pScrn, PixmapPtr pPix, PicturePtr pPict)
{
	NVPtr pNv = NVPTR(pScrn);
	struct nouveau_channel *chan = pNv->chan;
	struct nouveau_grobj *rankine = pNv->Nv3D;
	struct nouveau_bo *bo = nouveau_pixmap_bo(pPix);
	nv_pict_surface_format_t *fmt;

	fmt = NV30_GetPictSurfaceFormat(pPict->format);
	if (!fmt) {
		ErrorF("AIII no format\n");
		return FALSE;
	}

	uint32_t pitch = (uint32_t)exaGetPixmapPitch(pPix);

	BEGIN_RING(chan, rankine, NV34TCL_RT_FORMAT, 3);
	OUT_RING  (chan, fmt->card_fmt); /* format */
	OUT_RING  (chan, pitch << 16 | pitch);
	if (OUT_RELOCl(chan, bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR))
		return FALSE;

	return TRUE;
}
Exemple #3
0
static Bool
NV40_SetupSurface(ScrnInfoPtr pScrn, PixmapPtr pPix, PictFormatShort format)
{
	NVPtr pNv = NVPTR(pScrn);
	struct nouveau_channel *chan = pNv->chan;
	struct nouveau_grobj *curie = pNv->Nv3D;
	struct nouveau_bo *bo = nouveau_pixmap_bo(pPix);
	nv_pict_surface_format_t *fmt;

	fmt = NV40_GetPictSurfaceFormat(format);
	if (!fmt) {
		ErrorF("AIII no format\n");
		return FALSE;
	}

	BEGIN_RING(chan, curie, NV40TCL_RT_FORMAT, 3);
	OUT_RING  (chan, NV40TCL_RT_FORMAT_TYPE_LINEAR |
		   NV40TCL_RT_FORMAT_ZETA_Z24S8 |
		   fmt->card_fmt);
	OUT_RING  (chan, exaGetPixmapPitch(pPix));
	if (OUT_RELOCl(chan, bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR))
		return FALSE;

	return TRUE;
}
static Bool
setSrc(G80Ptr pNv, PixmapPtr pSrc)
{
    CARD32 depth;

    switch(pSrc->drawable.depth) {
        case  8: depth = 0x000000f3; break;
        case 15: depth = 0x000000f8; break;
        case 16: depth = 0x000000e8; break;
        case 24: depth = 0x000000e6; break;
        case 32: depth = 0x000000cf; break;
        default: return FALSE;
    }

    G80DmaStart(pNv, 0x230, 2);
    G80DmaNext (pNv, depth);
    G80DmaNext (pNv, 0x00000001);
    G80DmaStart(pNv, 0x244, 5);
    G80DmaNext (pNv, exaGetPixmapPitch(pSrc));
    G80DmaNext (pNv, pSrc->drawable.width);
    G80DmaNext (pNv, pSrc->drawable.height);
    G80DmaNext (pNv, 0x00000000);
    G80DmaNext (pNv, exaGetPixmapOffset(pSrc));

    return TRUE;
}
static Bool
setDst(G80Ptr pNv, PixmapPtr pDst)
{
    CARD32 depth, depth2;

    switch(pDst->drawable.depth) {
        case  8: depth = 0x000000f3; depth2 = 3; break;
        case 15: depth = 0x000000f8; depth2 = 1; break;
        case 16: depth = 0x000000e8; depth2 = 0; break;
        case 24: depth = 0x000000e6; depth2 = 2; break;
        case 32: depth = 0x000000cf; depth2 = 2; break;
        default: return FALSE;
    }

    G80DmaStart(pNv, 0x200, 2);
    G80DmaNext (pNv, depth);
    G80DmaNext (pNv, 0x00000001);
    G80DmaStart(pNv, 0x214, 5);
    G80DmaNext (pNv, exaGetPixmapPitch(pDst));
    G80DmaNext (pNv, pDst->drawable.width);
    G80DmaNext (pNv, pDst->drawable.height);
    G80DmaNext (pNv, 0x00000000);
    G80DmaNext (pNv, exaGetPixmapOffset(pDst));
    G80DmaStart(pNv, 0x2e8, 1);
    G80DmaNext (pNv, depth2);
    G80DmaStart(pNv, 0x584, 1);
    G80DmaNext (pNv, depth);
    G80SetClip(pNv, 0, 0, pDst->drawable.width, pDst->drawable.height);

    return TRUE;
}
Exemple #6
0
/**
 * Does fake acceleration of UploadToScreen using memcpy.
 */
static Bool
ephyrUploadToScreen(PixmapPtr pDst, int x, int y, int w, int h, char *src,
		    int src_pitch)
{
    KdScreenPriv(pDst->drawable.pScreen);
    KdScreenInfo *screen = pScreenPriv->screen;
    EphyrScrPriv *scrpriv = screen->driver;
    EphyrFakexaPriv *fakexa = scrpriv->fakexa;
    unsigned char *dst;
    int dst_pitch, cpp;

    if (pDst->drawable.bitsPerPixel < 8)
	return FALSE;

    ephyrPreparePipelinedAccess(pDst, EXA_PREPARE_DEST);

    cpp = pDst->drawable.bitsPerPixel / 8;
    dst_pitch = exaGetPixmapPitch(pDst);
    dst = fakexa->exa->memoryBase + exaGetPixmapOffset(pDst);
    dst += y * dst_pitch + x * cpp;

    for (; h > 0; h--) {
	memcpy(dst, src, w * cpp);
	dst += dst_pitch;
	src += src_pitch;
    }

    exaMarkSync(pDst->drawable.pScreen);

    ephyrFinishPipelinedAccess(pDst, EXA_PREPARE_DEST);

    return TRUE;
}
static Bool
nouveau_exa_download_from_screen(PixmapPtr pspix, int x, int y, int w, int h,
				 char *dst, int dst_pitch)
{
	ScrnInfoPtr pScrn = xf86Screens[pspix->drawable.pScreen->myNum];
	NVPtr pNv = NVPTR(pScrn);
	struct nouveau_bo *bo;
	int src_pitch, cpp, offset;
	const char *src;
	Bool ret;

	src_pitch  = exaGetPixmapPitch(pspix);
	cpp = pspix->drawable.bitsPerPixel >> 3;
	offset = (y * src_pitch) + (x * cpp);

	if (pNv->GART) {
		if (pNv->Architecture >= NV_ARCH_C0) {
			if (NVC0AccelDownloadM2MF(pspix, x, y, w, h,
						  dst, dst_pitch))
				return TRUE;
		} else {
			if (NVAccelDownloadM2MF(pspix, x, y, w, h,
						dst, dst_pitch))
				return TRUE;
		}
	}

	bo = nouveau_pixmap_bo(pspix);
	if (nouveau_bo_map(bo, NOUVEAU_BO_RD))
		return FALSE;
	src = (char *)bo->map + offset;
	ret = NVAccelMemcpyRect(dst, src, h, dst_pitch, src_pitch, w*cpp);
	nouveau_bo_unmap(bo);
	return ret;
}
static Bool
setup_render_target(NVPtr pNv, PicturePtr pict, PixmapPtr pixmap)
{
	struct nouveau_channel *chan = pNv->chan;
	struct nouveau_bo *bo = nouveau_pixmap_bo(pixmap);

	BEGIN_NV04(chan, NV10_3D(RT_FORMAT), 2);
	OUT_RING  (chan, get_rt_format(pict));
	OUT_RING  (chan, (exaGetPixmapPitch(pixmap) << 16 |
			  exaGetPixmapPitch(pixmap)));

	BEGIN_NV04(chan, NV10_3D(COLOR_OFFSET), 1);
	if (OUT_RELOCl(chan, bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR))
		return FALSE;

	return TRUE;
}
Exemple #9
0
static Bool
setup_texture(NVPtr pNv, int unit, PicturePtr pict, PixmapPtr pixmap)
{
	struct nouveau_channel *chan = pNv->chan;
	struct nouveau_grobj *celsius = pNv->Nv3D;
	struct nouveau_bo *bo = nouveau_pixmap_bo(pixmap);
	unsigned tex_reloc = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD;
	long w = pict->pDrawable->width,
	     h = pict->pDrawable->height;
	unsigned int txfmt =
		NV10TCL_TX_FORMAT_WRAP_T_CLAMP_TO_EDGE |
		NV10TCL_TX_FORMAT_WRAP_S_CLAMP_TO_EDGE |
		log2i(w) << 20 | log2i(h) << 16 |
		1 << 12 | /* lod == 1 */
		get_tex_format(pict) |
		0x50 /* UNK */;

	BEGIN_RING(chan, celsius, NV10TCL_TX_OFFSET(unit), 1);
	if (OUT_RELOCl(chan, bo, 0, tex_reloc))
		return FALSE;

	if (pict->repeat == RepeatNone) {
		/* NPOT_SIZE expects an even number for width, we can
		 * round up uneven numbers here because EXA always
		 * gives 64 byte aligned pixmaps and for all formats
		 * we support 64 bytes represents an even number of
		 * pixels
		 */
		w = (w + 1) &~ 1;

		BEGIN_RING(chan, celsius, NV10TCL_TX_NPOT_PITCH(unit), 1);
		OUT_RING  (chan, exaGetPixmapPitch(pixmap) << 16);

		BEGIN_RING(chan, celsius, NV10TCL_TX_NPOT_SIZE(unit), 1);
		OUT_RING  (chan, w << 16 | h);
	}

	BEGIN_RING(chan, celsius, NV10TCL_TX_FORMAT(unit), 1 );
	if (OUT_RELOCd(chan, bo, txfmt, tex_reloc | NOUVEAU_BO_OR,
		       NV10TCL_TX_FORMAT_DMA0, NV10TCL_TX_FORMAT_DMA1))
		return FALSE;

	BEGIN_RING(chan, celsius, NV10TCL_TX_ENABLE(unit), 1 );
	OUT_RING  (chan, NV10TCL_TX_ENABLE_ENABLE);

	BEGIN_RING(chan, celsius, NV10TCL_TX_FILTER(unit), 1);
	if (pict->filter == PictFilterNearest)
		OUT_RING(chan, (NV10TCL_TX_FILTER_MAGNIFY_NEAREST |
				NV10TCL_TX_FILTER_MINIFY_NEAREST));
	else
		OUT_RING(chan, (NV10TCL_TX_FILTER_MAGNIFY_LINEAR |
				NV10TCL_TX_FILTER_MINIFY_LINEAR));

	return TRUE;
}
Exemple #10
0
static Bool
NV30EXATexture(ScrnInfoPtr pScrn, PixmapPtr pPix, PicturePtr pPict, int unit)
{
	NVPtr pNv = NVPTR(pScrn);
	struct nouveau_channel *chan = pNv->chan;
	struct nouveau_grobj *rankine = pNv->Nv3D;
	struct nouveau_bo *bo = nouveau_pixmap_bo(pPix);
	nv_pict_texture_format_t *fmt;
	uint32_t card_filter, card_repeat;
	uint32_t tex_reloc = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD;
	NV30EXA_STATE;

	fmt = NV30_GetPictTextureFormat(pPict->format);
	if (!fmt)
		return FALSE;

	card_repeat = 3; /* repeatNone */

	if (pPict->filter == PictFilterBilinear)
		card_filter = 2;
	else
		card_filter = 1;

	BEGIN_RING(chan, rankine, NV34TCL_TX_OFFSET(unit), 8);
	if (OUT_RELOCl(chan, bo, 0, tex_reloc) ||
	    OUT_RELOCd(chan, bo, NV34TCL_TX_FORMAT_DIMS_2D | (1 << 16) | 8 |
		       (fmt->card_fmt << NV34TCL_TX_FORMAT_FORMAT_SHIFT) |
		       (log2i(pPix->drawable.width) <<
			NV34TCL_TX_FORMAT_BASE_SIZE_U_SHIFT) |
		       (log2i(pPix->drawable.height) <<
			NV34TCL_TX_FORMAT_BASE_SIZE_V_SHIFT),
		       tex_reloc | NOUVEAU_BO_OR,
		       NV34TCL_TX_FORMAT_DMA0, NV34TCL_TX_FORMAT_DMA1))
		return FALSE;
	OUT_RING  (chan, (card_repeat << NV34TCL_TX_WRAP_S_SHIFT) |
			(card_repeat << NV34TCL_TX_WRAP_T_SHIFT) |
			(card_repeat << NV34TCL_TX_WRAP_R_SHIFT));
	OUT_RING  (chan, NV34TCL_TX_ENABLE_ENABLE);
	OUT_RING  (chan, (((uint32_t)exaGetPixmapPitch(pPix)) << NV34TCL_TX_SWIZZLE_RECT_PITCH_SHIFT ) | 
			fmt->card_swz);

	OUT_RING  (chan, (card_filter << NV34TCL_TX_FILTER_MINIFY_SHIFT) /* min */ |
			(card_filter << NV34TCL_TX_FILTER_MAGNIFY_SHIFT) /* mag */ |
			0x2000 /* engine lock */);
	OUT_RING  (chan, (pPix->drawable.width << NV34TCL_TX_NPOT_SIZE_W_SHIFT) | pPix->drawable.height);
	OUT_RING  (chan, 0); /* border ARGB */

	state->unit[unit].width		= (float)pPix->drawable.width;
	state->unit[unit].height	= (float)pPix->drawable.height;
	state->unit[unit].transform	= pPict->transform;

	return TRUE;
}
Exemple #11
0
static Bool
NV30_SetupSurface(ScrnInfoPtr pScrn, PixmapPtr pPix, PicturePtr pPict)
{
	NVPtr pNv = NVPTR(pScrn);
	struct nouveau_pushbuf *push = pNv->pushbuf;
	struct nouveau_bo *bo = nouveau_pixmap_bo(pPix);
	uint32_t pitch = exaGetPixmapPitch(pPix);
	nv_pict_surface_format_t *fmt;

	fmt = NV30_GetPictSurfaceFormat(pPict->format);
	if (!fmt) {
		ErrorF("AIII no format\n");
		return FALSE;
	}

	BEGIN_NV04(push, NV30_3D(RT_FORMAT), 3);
	PUSH_DATA (push, fmt->card_fmt); /* format */
	PUSH_DATA (push, pitch << 16 | pitch);
	PUSH_MTHDl(push, NV30_3D(COLOR0_OFFSET), bo, 0,
			 NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR);
	return TRUE;
}
Exemple #12
0
static Bool
NV40_SetupSurface(ScrnInfoPtr pScrn, PixmapPtr pPix, PictFormatShort format)
{
	NVPtr pNv = NVPTR(pScrn);
	struct nouveau_pushbuf *push = pNv->pushbuf;
	struct nouveau_bo *bo = nouveau_pixmap_bo(pPix);
	nv_pict_surface_format_t *fmt;

	fmt = NV40_GetPictSurfaceFormat(format);
	if (!fmt) {
		ErrorF("AIII no format\n");
		return FALSE;
	}

	BEGIN_NV04(push, NV30_3D(RT_FORMAT), 3);
	PUSH_DATA (push, NV30_3D_RT_FORMAT_TYPE_LINEAR |
			 NV30_3D_RT_FORMAT_ZETA_Z24S8 | fmt->card_fmt);
	PUSH_DATA (push, exaGetPixmapPitch(pPix));
	PUSH_MTHDl(push, NV30_3D(COLOR0_OFFSET), bo, 0,
			 NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR);
	return TRUE;
}
Exemple #13
0
Bool
exaHWCopyNtoN(DrawablePtr pSrcDrawable,
              DrawablePtr pDstDrawable,
              GCPtr pGC,
              BoxPtr pbox,
              int nbox, int dx, int dy, Bool reverse, Bool upsidedown)
{
    ExaScreenPriv(pDstDrawable->pScreen);
    PixmapPtr pSrcPixmap, pDstPixmap;
    ExaPixmapPrivPtr pSrcExaPixmap, pDstExaPixmap;
    int src_off_x, src_off_y;
    int dst_off_x, dst_off_y;
    RegionPtr srcregion = NULL, dstregion = NULL;
    xRectangle *rects;
    Bool ret = TRUE;

    /* avoid doing copy operations if no boxes */
    if (nbox == 0)
        return TRUE;

    pSrcPixmap = exaGetDrawablePixmap(pSrcDrawable);
    pDstPixmap = exaGetDrawablePixmap(pDstDrawable);

    exaGetDrawableDeltas(pSrcDrawable, pSrcPixmap, &src_off_x, &src_off_y);
    exaGetDrawableDeltas(pDstDrawable, pDstPixmap, &dst_off_x, &dst_off_y);

    rects = malloc(nbox * sizeof(xRectangle));

    if (rects) {
        int i;
        int ordering;

        for (i = 0; i < nbox; i++) {
            rects[i].x = pbox[i].x1 + dx + src_off_x;
            rects[i].y = pbox[i].y1 + dy + src_off_y;
            rects[i].width = pbox[i].x2 - pbox[i].x1;
            rects[i].height = pbox[i].y2 - pbox[i].y1;
        }

        /* This must match the RegionCopy() logic for reversing rect order */
        if (nbox == 1 || (dx > 0 && dy > 0) ||
            (pDstDrawable != pSrcDrawable &&
             (pDstDrawable->type != DRAWABLE_WINDOW ||
              pSrcDrawable->type != DRAWABLE_WINDOW)))
            ordering = CT_YXBANDED;
        else
            ordering = CT_UNSORTED;

        srcregion = RegionFromRects(nbox, rects, ordering);
        free(rects);

        if (!pGC || !exaGCReadsDestination(pDstDrawable, pGC->planemask,
                                           pGC->fillStyle, pGC->alu,
                                           pGC->clientClip != NULL)) {
            dstregion = RegionCreate(NullBox, 0);
            RegionCopy(dstregion, srcregion);
            RegionTranslate(dstregion, dst_off_x - dx - src_off_x,
                            dst_off_y - dy - src_off_y);
        }
    }

    pSrcExaPixmap = ExaGetPixmapPriv(pSrcPixmap);
    pDstExaPixmap = ExaGetPixmapPriv(pDstPixmap);

    /* Check whether the accelerator can use this pixmap.
     * If the pitch of the pixmaps is out of range, there's nothing
     * we can do but fall back to software rendering.
     */
    if (pSrcExaPixmap->accel_blocked & EXA_RANGE_PITCH ||
        pDstExaPixmap->accel_blocked & EXA_RANGE_PITCH)
        goto fallback;

    /* If the width or the height of either of the pixmaps
     * is out of range, check whether the boxes are actually out of the
     * addressable range as well. If they aren't, we can still do
     * the copying in hardware.
     */
    if (pSrcExaPixmap->accel_blocked || pDstExaPixmap->accel_blocked) {
        int i;

        for (i = 0; i < nbox; i++) {
            /* src */
            if ((pbox[i].x2 + dx + src_off_x) >= pExaScr->info->maxX ||
                (pbox[i].y2 + dy + src_off_y) >= pExaScr->info->maxY)
                goto fallback;

            /* dst */
            if ((pbox[i].x2 + dst_off_x) >= pExaScr->info->maxX ||
                (pbox[i].y2 + dst_off_y) >= pExaScr->info->maxY)
                goto fallback;
        }
    }

    if (pExaScr->do_migration) {
        ExaMigrationRec pixmaps[2];

        pixmaps[0].as_dst = TRUE;
        pixmaps[0].as_src = FALSE;
        pixmaps[0].pPix = pDstPixmap;
        pixmaps[0].pReg = dstregion;
        pixmaps[1].as_dst = FALSE;
        pixmaps[1].as_src = TRUE;
        pixmaps[1].pPix = pSrcPixmap;
        pixmaps[1].pReg = srcregion;

        exaDoMigration(pixmaps, 2, TRUE);
    }

    /* Mixed directions must be handled specially if the card is lame */
    if ((pExaScr->info->flags & EXA_TWO_BITBLT_DIRECTIONS) &&
        reverse != upsidedown) {
        if (exaCopyNtoNTwoDir(pSrcDrawable, pDstDrawable, pGC, pbox, nbox,
                              dx, dy))
            goto out;
        goto fallback;
    }

    if (exaPixmapHasGpuCopy(pDstPixmap)) {
        /* Normal blitting. */
        if (exaPixmapHasGpuCopy(pSrcPixmap)) {
            if (!(*pExaScr->info->PrepareCopy)
                (pSrcPixmap, pDstPixmap, reverse ? -1 : 1, upsidedown ? -1 : 1,
                 pGC ? pGC->alu : GXcopy, pGC ? pGC->planemask : FB_ALLONES)) {
                goto fallback;
            }

            while (nbox--) {
                (*pExaScr->info->Copy) (pDstPixmap,
                                        pbox->x1 + dx + src_off_x,
                                        pbox->y1 + dy + src_off_y,
                                        pbox->x1 + dst_off_x,
                                        pbox->y1 + dst_off_y,
                                        pbox->x2 - pbox->x1,
                                        pbox->y2 - pbox->y1);
                pbox++;
            }

            (*pExaScr->info->DoneCopy) (pDstPixmap);
            exaMarkSync(pDstDrawable->pScreen);
            /* UTS: mainly for SHM PutImage's secondary path.
             *
             * Only taking this path for directly accessible pixmaps.
             */
        }
        else if (!pDstExaPixmap->pDamage && pSrcExaPixmap->sys_ptr) {
            int bpp = pSrcDrawable->bitsPerPixel;
            int src_stride = exaGetPixmapPitch(pSrcPixmap);
            CARD8 *src = NULL;

            if (!pExaScr->info->UploadToScreen)
                goto fallback;

            if (pSrcDrawable->bitsPerPixel != pDstDrawable->bitsPerPixel)
                goto fallback;

            if (pSrcDrawable->bitsPerPixel < 8)
                goto fallback;

            if (pGC &&
                !(pGC->alu == GXcopy &&
                  EXA_PM_IS_SOLID(pSrcDrawable, pGC->planemask)))
                goto fallback;

            while (nbox--) {
                src =
                    pSrcExaPixmap->sys_ptr + (pbox->y1 + dy +
                                              src_off_y) * src_stride +
                    (pbox->x1 + dx + src_off_x) * (bpp / 8);
                if (!pExaScr->info->
                    UploadToScreen(pDstPixmap, pbox->x1 + dst_off_x,
                                   pbox->y1 + dst_off_y, pbox->x2 - pbox->x1,
                                   pbox->y2 - pbox->y1, (char *) src,
                                   src_stride))
                    goto fallback;

                pbox++;
            }
        }
        else
            goto fallback;
    }
    else
        goto fallback;

    goto out;

 fallback:
    ret = FALSE;

 out:
    if (dstregion) {
        RegionUninit(dstregion);
        RegionDestroy(dstregion);
    }
    if (srcregion) {
        RegionUninit(srcregion);
        RegionDestroy(srcregion);
    }

    return ret;
}
static inline Bool
NVAccelDownloadM2MF(PixmapPtr pspix, int x, int y, int w, int h,
		    char *dst, unsigned dst_pitch)
{
	ScrnInfoPtr pScrn = xf86Screens[pspix->drawable.pScreen->myNum];
	NVPtr pNv = NVPTR(pScrn);
	struct nouveau_channel *chan = pNv->chan;
	struct nouveau_grobj *m2mf = pNv->NvMemFormat;
	struct nouveau_bo *bo = nouveau_pixmap_bo(pspix);
	unsigned cpp = pspix->drawable.bitsPerPixel / 8;
	unsigned line_len = w * cpp;
	unsigned src_offset = 0, src_pitch = 0, linear = 0;
	/* Maximum DMA transfer */
	unsigned line_count = pNv->GART->size / line_len;

	if (!nv50_style_tiled_pixmap(pspix)) {
		linear     = 1;
		src_pitch  = exaGetPixmapPitch(pspix);
		src_offset += (y * src_pitch) + (x * cpp);
	}

	/* HW limitations */
	if (line_count > 2047)
		line_count = 2047;

	while (h) {
		int i;
		char *src;

		if (line_count > h)
			line_count = h;

		if (MARK_RING(chan, 32, 6))
			return FALSE;

		BEGIN_RING(chan, m2mf, NV04_MEMORY_TO_MEMORY_FORMAT_DMA_BUFFER_IN, 2);
		if (OUT_RELOCo(chan, bo, NOUVEAU_BO_GART | NOUVEAU_BO_VRAM |
			       NOUVEAU_BO_RD) ||
		    OUT_RELOCo(chan, pNv->GART, NOUVEAU_BO_GART |
			       NOUVEAU_BO_WR)) {
			MARK_UNDO(chan);
			return FALSE;
		}

		if (pNv->Architecture >= NV_ARCH_50) {
			if (!linear) {
				BEGIN_RING(chan, m2mf, NV50_MEMORY_TO_MEMORY_FORMAT_LINEAR_IN, 7);
				OUT_RING  (chan, 0);
				OUT_RING  (chan, bo->tile_mode << 4);
				OUT_RING  (chan, pspix->drawable.width * cpp);
				OUT_RING  (chan, pspix->drawable.height);
				OUT_RING  (chan, 1);
				OUT_RING  (chan, 0);
				OUT_RING  (chan, (y << 16) | (x * cpp));
			} else {
				BEGIN_RING(chan, m2mf, NV50_MEMORY_TO_MEMORY_FORMAT_LINEAR_IN, 1);
				OUT_RING  (chan, 1);
			}

			BEGIN_RING(chan, m2mf, NV50_MEMORY_TO_MEMORY_FORMAT_LINEAR_OUT, 1);
			OUT_RING  (chan, 1);

			BEGIN_RING(chan, m2mf, NV50_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN_HIGH, 2);
			if (OUT_RELOCh(chan, bo, src_offset, NOUVEAU_BO_GART |
				       NOUVEAU_BO_VRAM | NOUVEAU_BO_RD) ||
			    OUT_RELOCh(chan, pNv->GART, 0, NOUVEAU_BO_GART |
				       NOUVEAU_BO_WR)) {
				MARK_UNDO(chan);
				return FALSE;
			}
		}

		BEGIN_RING(chan, m2mf,
			   NV04_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
		if (OUT_RELOCl(chan, bo, src_offset, NOUVEAU_BO_GART |
			       NOUVEAU_BO_VRAM | NOUVEAU_BO_RD) ||
		    OUT_RELOCl(chan, pNv->GART, 0, NOUVEAU_BO_GART |
			       NOUVEAU_BO_WR)) {
			MARK_UNDO(chan);
			return FALSE;
		}
		OUT_RING  (chan, src_pitch);
		OUT_RING  (chan, line_len);
		OUT_RING  (chan, line_len);
		OUT_RING  (chan, line_count);
		OUT_RING  (chan, (1<<8)|1);
		OUT_RING  (chan, 0);

		if (nouveau_bo_map(pNv->GART, NOUVEAU_BO_RD)) {
			MARK_UNDO(chan);
			return FALSE;
		}
		src = pNv->GART->map;
		if (dst_pitch == line_len) {
			memcpy(dst, src, dst_pitch * line_count);
			dst += dst_pitch * line_count;
		} else {
			for (i = 0; i < line_count; i++) {
				memcpy(dst, src, line_len);
				src += line_len;
				dst += dst_pitch;
			}
		}
		nouveau_bo_unmap(pNv->GART);

		if (linear)
			src_offset += line_count * src_pitch;
		h -= line_count;
		y += line_count;
	}

	return TRUE;
}
static Bool
nouveau_exa_upload_to_screen(PixmapPtr pdpix, int x, int y, int w, int h,
			     char *src, int src_pitch)
{
	ScrnInfoPtr pScrn = xf86Screens[pdpix->drawable.pScreen->myNum];
	NVPtr pNv = NVPTR(pScrn);
	struct nouveau_bo *bo;
	int dst_pitch, cpp;
	char *dst;
	Bool ret;

	dst_pitch  = exaGetPixmapPitch(pdpix);
	cpp = pdpix->drawable.bitsPerPixel >> 3;

	/* try hostdata transfer */
	if (w * h * cpp < 16*1024) /* heuristic */
	{
		if (pNv->Architecture < NV_ARCH_50) {
			if (NV04EXAUploadIFC(pScrn, src, src_pitch, pdpix,
					     x, y, w, h, cpp)) {
				exaMarkSync(pdpix->drawable.pScreen);
				return TRUE;
			}
		} else
		if (pNv->Architecture < NV_ARCH_C0) {
			if (NV50EXAUploadSIFC(src, src_pitch, pdpix,
					      x, y, w, h, cpp)) {
				exaMarkSync(pdpix->drawable.pScreen);
				return TRUE;
			}
		} else {
			if (NVC0EXAUploadSIFC(src, src_pitch, pdpix,
					      x, y, w, h, cpp)) {
				exaMarkSync(pdpix->drawable.pScreen);
				return TRUE;
			}
		}
	}

	/* try gart-based transfer */
	if (pNv->GART) {
		if (pNv->Architecture < NV_ARCH_C0) {
			ret = NVAccelUploadM2MF(pdpix, x, y, w, h,
						src, src_pitch);
		} else {
			ret = NVC0AccelUploadM2MF(pdpix, x, y, w, h,
						  src, src_pitch);
		}

		if (ret) {
			exaMarkSync(pdpix->drawable.pScreen);
			return TRUE;
		}
	}

	/* fallback to memcpy-based transfer */
	bo = nouveau_pixmap_bo(pdpix);
	if (nouveau_bo_map(bo, NOUVEAU_BO_WR))
		return FALSE;
	dst = (char *)bo->map + (y * dst_pitch) + (x * cpp);
	ret = NVAccelMemcpyRect(dst, src, h, dst_pitch, src_pitch, w*cpp);
	nouveau_bo_unmap(bo);
	return ret;
}
static Bool maliModifyPixmapHeader(PixmapPtr pPixmap, int width, int height, int depth, int bitsPerPixel, int devKind, pointer pPixData)
{
	unsigned int size;
	PrivPixmap *privPixmap = (PrivPixmap *)exaGetPixmapDriverPrivate(pPixmap);
	mali_mem_info *mem_info;
	ScreenPtr pScreen = pPixmap->drawable.pScreen;
	ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
	MaliPtr fPtr = MALIPTR(pScrn);

	if (!pPixmap)
	{
		return FALSE;
	}

	miModifyPixmapHeader(pPixmap, width, height, depth, bitsPerPixel, devKind, pPixData);

	if ((pPixData == fPtr->fbmem) || offset)
	{
		/* Wrap one of the fbdev virtual buffers */
		ump_secure_id ump_id = UMP_INVALID_SECURE_ID;

		privPixmap->isFrameBuffer = TRUE;

		mem_info = privPixmap->mem_info;

		if (mem_info)
		{
			return TRUE;
		}

		/* create new mem_info for the on-screen buffer */
		mem_info = calloc(1, sizeof(*mem_info));

		if (!mem_info)
		{
			ERROR_MSG("failed to allocate for memory metadata");
			return FALSE;
		}

		/* get the secure ID for the framebuffers */
		if (!offset)
		{
			(void)ioctl(fPtr->fb_lcd_fd, GET_UMP_SECURE_ID_BUF1, &ump_id);
			ERROR_MSG("GET_UMP_SECURE_ID_BUF1 returned 0x%x offset: %i virt address: %p fb_virt: %p\n", ump_id, offset, pPixData, fPtr->fbmem);
		}
		else
		{
			(void)ioctl(fPtr->fb_lcd_fd, GET_UMP_SECURE_ID_BUF2, &ump_id);
			ERROR_MSG("GET_UMP_SECURE_ID_BUF2 returned 0x%x offset: %i virt address: %p fb_virt: %p\n", ump_id, offset, pPixData, fPtr->fbmem);
		}

		if (UMP_INVALID_SECURE_ID == ump_id)
		{
			free(mem_info);
			privPixmap->mem_info = NULL;
			ERROR_MSG("UMP failed to retrieve secure id");
			return FALSE;
		}

		mem_info->handle = ump_handle_create_from_secure_id(ump_id);

		if (UMP_INVALID_MEMORY_HANDLE == mem_info->handle)
		{
			ERROR_MSG("UMP failed to create handle from secure id");
			free(mem_info);
			privPixmap->mem_info = NULL;
			return FALSE;
		}

		size = exaGetPixmapPitch(pPixmap) * pPixmap->drawable.height;
		mem_info->usize = size;

		privPixmap->mem_info = mem_info;

		if (bitsPerPixel != 0)
		{
			privPixmap->bits_per_pixel = bitsPerPixel;
		}

		/* When this is called directly from X to create the front buffer, offset is zero as expected. When this
		 * function is called recursively to create the back buffer, offset is the offset within the fbdev to
		 * the second buffer */
		privPixmap->mem_info->offset = offset;

		/* Only wrap the other half if there is another half! */
		if (pPixData == fPtr->fbmem)
		{
			/* This is executed only when this function is called directly from X. We need to create the
			 * back buffer now because we can't "wrap" existing memory in a pixmap during DRI2CreateBuffer
			 * for the back buffer of the framebuffer. In DRI2CreateBuffer instead of allocating a new
			 * pixmap for the back buffer like we do for non-swappable windows, we'll just grab this pointer
			 * from the screen pixmap and return it. */

			PrivPixmap *other_privPixmap;

			offset = size;
			privPixmap->other_buffer = (*pScreen->CreatePixmap)(pScreen, width, height, depth, 0);

			/* Store a pointer to this pixmap in the one we just created. Both fbdev pixmaps are then
			 * accessible from the screen pixmap, whichever of the fbdev pixmaps happens to be the screen
			 * pixmap at the time */
			other_privPixmap = (PrivPixmap *)exaGetPixmapDriverPrivate(privPixmap->other_buffer);
			other_privPixmap->other_buffer = pPixmap;

			offset = 0;
		}

		INFO_MSG("Creating FRAMEBUFFER pixmap %p at offset %lu, privPixmap=%p\n", pPixmap, privPixmap->mem_info->offset, privPixmap);

		return TRUE;
	}

	if (pPixData)
	{
		/* When this happens we're being told to wrap existing pixmap data for which we don't know the UMP
		 * handle. We can and still need to wrap it but it won't be offscreen - we can't accelerate it in any
		 * way. */

		if (privPixmap->mem_info != NULL)
		{
			return TRUE;
		}

		return FALSE;
	}

	pPixmap->devKind = ((pPixmap->drawable.width * pPixmap->drawable.bitsPerPixel) + 7) / 8;
	pPixmap->devKind = MALI_ALIGN(pPixmap->devKind, 8);

	size = exaGetPixmapPitch(pPixmap) * pPixmap->drawable.height;

	/* allocate pixmap data */
	mem_info = privPixmap->mem_info;

	if (mem_info && mem_info->usize == size)
	{
		return TRUE;
	}

	if (mem_info && mem_info->usize != 0)
	{
		ump_reference_release(mem_info->handle);
		mem_info->handle = NULL;
		memset(privPixmap, 0, sizeof(*privPixmap));

		return TRUE;
	}

	if (!size)
	{
		return TRUE;
	}

	if (NULL == mem_info)
	{
		mem_info = calloc(1, sizeof(*mem_info));

		if (!mem_info)
		{
			ERROR_MSG("failed to allocate memory metadata");
			return FALSE;
		}
	}

	if (fPtr->use_cached_ump)
	{
		mem_info->handle = ump_ref_drv_allocate(size, UMP_REF_DRV_CONSTRAINT_PHYSICALLY_LINEAR | UMP_REF_DRV_CONSTRAINT_USE_CACHE);
	}
	else
	{
		mem_info->handle = ump_ref_drv_allocate(size, UMP_REF_DRV_CONSTRAINT_PHYSICALLY_LINEAR);
	}

	if (UMP_INVALID_MEMORY_HANDLE == mem_info->handle)
	{
		ERROR_MSG("failed to allocate UMP memory (%i bytes)", size);
		return FALSE;
	}

	mem_info->usize = size;
	privPixmap->mem_info = mem_info;
	privPixmap->mem_info->usize = size;
	privPixmap->bits_per_pixel = 16;

	return TRUE;
}
Exemple #17
0
static Bool
NV30EXATexture(ScrnInfoPtr pScrn, PixmapPtr pPix, PicturePtr pPict, int unit)
{
	NVPtr pNv = NVPTR(pScrn);
	struct nouveau_pushbuf *push = pNv->pushbuf;
	struct nouveau_bo *bo = nouveau_pixmap_bo(pPix);
	nv_pict_texture_format_t *fmt;
	unsigned reloc = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD;
	uint32_t pitch = exaGetPixmapPitch(pPix);
	uint32_t log2h = log2i(pPix->drawable.height);
	uint32_t log2w = log2i(pPix->drawable.width);
	uint32_t card_filter, card_repeat;

	fmt = NV30_GetPictTextureFormat(pPict->format);
	if (!fmt)
		return FALSE;

	card_repeat = 3; /* repeatNone */

	if (pPict->filter == PictFilterBilinear)
		card_filter = 2;
	else
		card_filter = 1;

	BEGIN_NV04(push, NV30_3D(TEX_OFFSET(unit)), 8);
	PUSH_MTHDl(push, NV30_3D(TEX_OFFSET(unit)), bo, 0, reloc);
	PUSH_MTHDs(push, NV30_3D(TEX_FORMAT(unit)), bo, (1 << 16) | 8 |
			 NV30_3D_TEX_FORMAT_DIMS_2D |
			 (fmt->card_fmt << NV30_3D_TEX_FORMAT_FORMAT__SHIFT) |
			 (log2w << NV30_3D_TEX_FORMAT_BASE_SIZE_U__SHIFT) |
			 (log2h << NV30_3D_TEX_FORMAT_BASE_SIZE_V__SHIFT),
			 reloc, NV30_3D_TEX_FORMAT_DMA0,
			 NV30_3D_TEX_FORMAT_DMA1);
	PUSH_DATA (push, (card_repeat << NV30_3D_TEX_WRAP_S__SHIFT) |
			 (card_repeat << NV30_3D_TEX_WRAP_T__SHIFT) |
			 (card_repeat << NV30_3D_TEX_WRAP_R__SHIFT));
	PUSH_DATA (push, NV30_3D_TEX_ENABLE_ENABLE);
	PUSH_DATA (push, (pitch << NV30_3D_TEX_SWIZZLE_RECT_PITCH__SHIFT ) |
			 fmt->card_swz);
	PUSH_DATA (push, (card_filter << NV30_3D_TEX_FILTER_MIN__SHIFT) |
			 (card_filter << NV30_3D_TEX_FILTER_MAG__SHIFT) |
			 0x2000 /* engine lock */);
	PUSH_DATA (push, (pPix->drawable.width <<
			  NV30_3D_TEX_NPOT_SIZE_W__SHIFT) |
			 pPix->drawable.height);
	PUSH_DATA (push, 0x00000000); /* border ARGB */
	if (pPict->transform) {
		BEGIN_NV04(push, NV30_3D(TEX_MATRIX_ENABLE(unit)), 1);
		PUSH_DATA (push, 1);
		BEGIN_NV04(push, NV30_3D(TEX_MATRIX(unit, 0)), 16);
		PUSH_DATAf(push, xFixedToFloat(pPict->transform->matrix[0][0]));
		PUSH_DATAf(push, xFixedToFloat(pPict->transform->matrix[0][1]));
		PUSH_DATAf(push, 0.f);
		PUSH_DATAf(push, xFixedToFloat(pPict->transform->matrix[0][2]));
		PUSH_DATAf(push, xFixedToFloat(pPict->transform->matrix[1][0]));
		PUSH_DATAf(push, xFixedToFloat(pPict->transform->matrix[1][1]));
		PUSH_DATAf(push, 0.f);
		PUSH_DATAf(push, xFixedToFloat(pPict->transform->matrix[1][2]));
		PUSH_DATAf(push, 0.0f);
		PUSH_DATAf(push, 0.0f);
		PUSH_DATAf(push, 0.0f);
		PUSH_DATAf(push, 0.0f);
		PUSH_DATAf(push, xFixedToFloat(pPict->transform->matrix[2][0]));
		PUSH_DATAf(push, xFixedToFloat(pPict->transform->matrix[2][1]));
		PUSH_DATAf(push, 0.0f);
		PUSH_DATAf(push, xFixedToFloat(pPict->transform->matrix[2][2]));
	} else {
		BEGIN_NV04(push, NV30_3D(TEX_MATRIX_ENABLE(unit)), 1);
		PUSH_DATA (push, 0);
	}

	return TRUE;
}
static Bool maliModifyPixmapHeader(PixmapPtr pPixmap, int width, int height, int depth, int bitsPerPixel, int devKind, pointer pPixData)
{
	unsigned int size;
	PrivPixmap *privPixmap = (PrivPixmap *)exaGetPixmapDriverPrivate(pPixmap);
	mali_mem_info *mem_info;
	ScreenPtr pScreen = pPixmap->drawable.pScreen;
	ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
	MaliPtr fPtr = MALIPTR(pScrn);

	if (!pPixmap)
	{
		return FALSE;
	}

	miModifyPixmapHeader(pPixmap, width, height, depth, bitsPerPixel, devKind, pPixData);

	if ((pPixData == fPtr->fbmem) || current_buf)
	{
		/* Wrap one of the fbdev virtual buffers */
		ump_secure_id ump_id = UMP_INVALID_SECURE_ID;

		privPixmap->isFrameBuffer = TRUE;
		privPixmap->frameBufferNumber = current_buf;
		mem_info = privPixmap->mem_info;

		if (mem_info)
		{
			return TRUE;
		}

		/* create new mem_info for the on-screen buffer */
		mem_info = calloc(1, sizeof(*mem_info));

		if (!mem_info)
		{
			ERROR_MSG("failed to allocate for memory metadata");
			return FALSE;
		}

		/* get the secure ID for the framebuffers */
		if (ioctl(fPtr->fb_lcd_fd, GET_UMP_SECURE_ID_BUF(current_buf), &ump_id) < 0
		        || UMP_INVALID_SECURE_ID == ump_id)
		{
			free(mem_info);
			privPixmap->mem_info = NULL;
			ERROR_MSG("UMP failed to retrieve secure id, current_buf: %d", current_buf);
			return FALSE;
		}

		INFO_MSG("GET_UMP_SECURE_ID_BUF(%d) returned 0x%x", current_buf, ump_id);

		mem_info->handle = ump_handle_create_from_secure_id(ump_id);

		if (UMP_INVALID_MEMORY_HANDLE == mem_info->handle)
		{
			ERROR_MSG("UMP failed to create handle from secure id");
			free(mem_info);
			privPixmap->mem_info = NULL;
			return FALSE;
		}

		size = exaGetPixmapPitch(pPixmap) * pPixmap->drawable.height;
		mem_info->usize = size;

		privPixmap->mem_info = mem_info;

		if (bitsPerPixel != 0)
		{
			privPixmap->bits_per_pixel = bitsPerPixel;
		}

		/* When this is called directly from X to create the front buffer, current_buf is zero as expected. When this
		 * function is called recursively to create the back buffers, current_buf is increased to the next buffer */
		privPixmap->mem_info->offset = current_buf * size;

		if (pPixData == fPtr->fbmem)
		{
			/* This is executed only when this function is called directly from X. We need to create the other
			 * back buffers now because we can't "wrap" existing memory in a pixmap during DRI2CreateBuffer
			 * for the back buffer of the framebuffer. In DRI2CreateBuffer instead of allocating a new
			 * pixmap for the back buffer like we do for non-swappable windows, we'll just use the 'current_pixmap'
			 * to grab this pointer from the screen pixmap and return it. */

			PrivPixmap *current_privPixmap = privPixmap;
			int i;
			PrivBuffer *buf_info = calloc(1, sizeof(*buf_info));

			if (NULL == buf_info)
			{
				ERROR_MSG("Failed to allocate buf_info memory");
				free(mem_info);
				privPixmap->mem_info = NULL;
				return FALSE;
			}

			buf_info->current_pixmap = 0;
			buf_info->num_pixmaps = fPtr->dri2_num_buffers;
			buf_info->pPixmaps[0] = pPixmap;
			current_privPixmap->buf_info = buf_info;

			for (i = 1; i < buf_info->num_pixmaps; i++)
			{
				current_buf++;
				buf_info->pPixmaps[i] = (*pScreen->CreatePixmap)(pScreen, width, height, depth, 0);
				assert(buf_info->pPixmaps[i]);
				current_privPixmap = (PrivPixmap *)exaGetPixmapDriverPrivate(buf_info->pPixmaps[i]);
				current_privPixmap->buf_info = buf_info;
			}

			current_buf = 0;
		}

		INFO_MSG("Creating FRAMEBUFFER pixmap %p at offset %lu, privPixmap=%p", pPixmap, privPixmap->mem_info->offset, privPixmap);

		return TRUE;
	}

	if (pPixData)
	{
		/* When this happens we're being told to wrap existing pixmap data for which we don't know the UMP
		 * handle. We can and still need to wrap it but it won't be offscreen - we can't accelerate it in any
		 * way. */

		if (privPixmap->mem_info != NULL)
		{
			return TRUE;
		}

		return FALSE;
	}

	pPixmap->devKind = ((pPixmap->drawable.width * pPixmap->drawable.bitsPerPixel) + 7) / 8;
	pPixmap->devKind = MALI_ALIGN(pPixmap->devKind, 8);

	size = exaGetPixmapPitch(pPixmap) * pPixmap->drawable.height;

	/* allocate pixmap data */
	mem_info = privPixmap->mem_info;

	if (mem_info && mem_info->usize == size)
	{
		return TRUE;
	}

	if (mem_info && mem_info->usize != 0)
	{
		ump_reference_release(mem_info->handle);
		mem_info->handle = NULL;
		memset(privPixmap, 0, sizeof(*privPixmap));

		return TRUE;
	}

	if (!size)
	{
		return TRUE;
	}

	if (NULL == mem_info)
	{
		mem_info = calloc(1, sizeof(*mem_info));

		if (!mem_info)
		{
			ERROR_MSG("failed to allocate memory metadata");
			return FALSE;
		}
	}

	if (fPtr->use_cached_ump)
	{
		mem_info->handle = ump_ref_drv_allocate(size, UMP_REF_DRV_CONSTRAINT_PHYSICALLY_LINEAR | UMP_REF_DRV_CONSTRAINT_USE_CACHE);
	}
	else
	{
		mem_info->handle = ump_ref_drv_allocate(size, UMP_REF_DRV_CONSTRAINT_PHYSICALLY_LINEAR);
	}

	if (UMP_INVALID_MEMORY_HANDLE == mem_info->handle)
	{
		ERROR_MSG("failed to allocate UMP memory (%i bytes)", size);
		return FALSE;
	}

	mem_info->usize = size;
	privPixmap->mem_info = mem_info;
	privPixmap->mem_info->usize = size;
	privPixmap->bits_per_pixel = 16;

	return TRUE;
}
static Bool create_buffer(DrawablePtr pDraw, struct ARMSOCDRI2BufferRec *buf)
{
	ScreenPtr pScreen = pDraw->pScreen;
	ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
	struct ARMSOCRec *pARMSOC = ARMSOCPTR(pScrn);
	DRI2BufferPtr buffer = DRIBUF(buf);
	PixmapPtr pPixmap = NULL;
	struct armsoc_bo *bo;
	int ret;

	if (buffer->attachment == DRI2BufferFrontLeft) {
		pPixmap = draw2pix(pDraw);
		pPixmap->refcnt++;
	} else {
		pPixmap = createpix(pDraw);
	}

	if (!pPixmap) {
		assert(buffer->attachment != DRI2BufferFrontLeft);
		ERROR_MSG("Failed to create back buffer for window");
		goto fail;
	}

	if (buffer->attachment == DRI2BufferBackLeft && pARMSOC->driNumBufs > 2) {
		buf->pPixmaps = calloc(pARMSOC->driNumBufs-1,
				sizeof(PixmapPtr));
		buf->numPixmaps = pARMSOC->driNumBufs-1;
	} else {
		buf->pPixmaps = malloc(sizeof(PixmapPtr));
		buf->numPixmaps = 1;
	}

	if (!buf->pPixmaps) {
		ERROR_MSG("Failed to allocate PixmapPtr array for DRI2Buffer");
		goto fail;
	}

	buf->pPixmaps[0] = pPixmap;
	assert(buf->currentPixmap == 0);

	bo = ARMSOCPixmapBo(pPixmap);
	if (!bo) {
		ERROR_MSG(
				"Attempting to DRI2 wrap a pixmap with no DRM buffer object backing");
		goto fail;
	}

	DRIBUF(buf)->pitch = exaGetPixmapPitch(pPixmap);
	DRIBUF(buf)->cpp = pPixmap->drawable.bitsPerPixel / 8;
	DRIBUF(buf)->flags = 0;
	buf->refcnt = 1;
	buf->previous_canflip = canflip(pDraw);

	ret = armsoc_bo_get_name(bo, &DRIBUF(buf)->name);
	if (ret) {
		ERROR_MSG("could not get buffer name: %d", ret);
		goto fail;
	}

	if (canflip(pDraw) && buffer->attachment != DRI2BufferFrontLeft) {
		/* Create an fb around this buffer. This will fail and we will
		 * fall back to blitting if the display controller hardware
		 * cannot scan out this buffer (for example, if it doesn't
		 * support the format or there was insufficient scanout memory
		 * at buffer creation time). */
		int ret = armsoc_bo_add_fb(bo);
		if (ret) {
			WARNING_MSG(
					"Falling back to blitting a flippable window");
		}
#if DRI2INFOREC_VERSION >= 6
		else if (FALSE == DRI2SwapLimit(pDraw, pARMSOC->swap_chain_size)) {
			WARNING_MSG(
				"Failed to set DRI2SwapLimit(%x,%d)",
				(unsigned int)pDraw, pARMSOC->swap_chain_size);
		}
#endif /* DRI2INFOREC_VERSION >= 6 */
	}

	DRI2_BUFFER_SET_FB(DRIBUF(buf)->flags, armsoc_bo_get_fb(bo) > 0 ? 1 : 0);
	DRI2_BUFFER_SET_REUSED(DRIBUF(buf)->flags, 0);
	/* Register Pixmap as having a buffer that can be accessed externally,
	 * so needs synchronised access */
	ARMSOCRegisterExternalAccess(pPixmap);

	return TRUE;

fail:
	if (pPixmap != NULL) {
		if (buffer->attachment != DRI2BufferFrontLeft)
			pScreen->DestroyPixmap(pPixmap);
		else
			pPixmap->refcnt--;
	}

	return FALSE;
}
Exemple #20
0
static Bool
NV40EXATexture(ScrnInfoPtr pScrn, PixmapPtr pPix, PicturePtr pPict, int unit)
{
	NVPtr pNv = NVPTR(pScrn);
	struct nouveau_channel *chan = pNv->chan;
	struct nouveau_grobj *curie = pNv->Nv3D;
	struct nouveau_bo *bo = nouveau_pixmap_bo(pPix);
	unsigned tex_reloc = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD;
	nv_pict_texture_format_t *fmt;
	NV40EXA_STATE;

	fmt = NV40_GetPictTextureFormat(pPict->format);
	if (!fmt)
		return FALSE;

	BEGIN_RING(chan, curie, NV40TCL_TEX_OFFSET(unit), 8);
	if (OUT_RELOCl(chan, bo, 0, tex_reloc) ||
	    OUT_RELOCd(chan, bo, fmt->card_fmt | NV40TCL_TEX_FORMAT_LINEAR |
		       NV40TCL_TEX_FORMAT_DIMS_2D | 0x8000 |
		       NV40TCL_TEX_FORMAT_NO_BORDER |
		       (1 << NV40TCL_TEX_FORMAT_MIPMAP_COUNT_SHIFT),
		       tex_reloc | NOUVEAU_BO_OR,
		       NV40TCL_TEX_FORMAT_DMA0, NV40TCL_TEX_FORMAT_DMA1))
		return FALSE;

	if (pPict->repeat) {
		switch(pPict->repeatType) {
		case RepeatPad:
			OUT_RING  (chan, NV40TCL_TEX_WRAP_S_CLAMP | 
					 NV40TCL_TEX_WRAP_T_CLAMP |
					 NV40TCL_TEX_WRAP_R_CLAMP);
			break;
		case RepeatReflect:
			OUT_RING  (chan, NV40TCL_TEX_WRAP_S_MIRRORED_REPEAT |
					 NV40TCL_TEX_WRAP_T_MIRRORED_REPEAT |
					 NV40TCL_TEX_WRAP_R_MIRRORED_REPEAT);
			break;
		case RepeatNormal:
		default:
			OUT_RING  (chan, NV40TCL_TEX_WRAP_S_REPEAT |
					 NV40TCL_TEX_WRAP_T_REPEAT |
					 NV40TCL_TEX_WRAP_R_REPEAT);
			break;
		}
	} else {
		OUT_RING  (chan, NV40TCL_TEX_WRAP_S_CLAMP_TO_BORDER |
				 NV40TCL_TEX_WRAP_T_CLAMP_TO_BORDER |
				 NV40TCL_TEX_WRAP_R_CLAMP_TO_BORDER);
	}
	OUT_RING  (chan, NV40TCL_TEX_ENABLE_ENABLE);
	OUT_RING  (chan, fmt->card_swz);
	if (pPict->filter == PictFilterBilinear) {
		OUT_RING  (chan, NV40TCL_TEX_FILTER_MIN_LINEAR |
				 NV40TCL_TEX_FILTER_MAG_LINEAR | 0x3fd6);
	} else {
		OUT_RING  (chan, NV40TCL_TEX_FILTER_MIN_NEAREST |
				 NV40TCL_TEX_FILTER_MAG_NEAREST | 0x3fd6);
	}
	OUT_RING  (chan, (pPix->drawable.width << 16) | pPix->drawable.height);
	OUT_RING  (chan, 0); /* border ARGB */
	BEGIN_RING(chan, curie, NV40TCL_TEX_SIZE1(unit), 1);
	OUT_RING  (chan, (1 << NV40TCL_TEX_SIZE1_DEPTH_SHIFT) |
			 (uint32_t)exaGetPixmapPitch(pPix));

	state->unit[unit].width		= (float)pPix->drawable.width;
	state->unit[unit].height	= (float)pPix->drawable.height;
	state->unit[unit].transform	= pPict->transform;
	return TRUE;
}
void
EVERGREENDisplayTexturedVideo(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
{
    RADEONInfoPtr info = RADEONPTR(pScrn);
    struct radeon_accel_state *accel_state = info->accel_state;
    PixmapPtr pPixmap = pPriv->pPixmap;
    BoxPtr pBox = REGION_RECTS(&pPriv->clip);
    int nBox = REGION_NUM_RECTS(&pPriv->clip);
    int dstxoff, dstyoff;
    struct r600_accel_object src_obj, dst_obj;
    cb_config_t     cb_conf;
    tex_resource_t  tex_res;
    tex_sampler_t   tex_samp;
    shader_config_t vs_conf, ps_conf;
    /*
     * y' = y - .0625
     * u' = u - .5
     * v' = v - .5;
     *
     * r = 1.1643 * y' + 0.0     * u' + 1.5958  * v'
     * g = 1.1643 * y' - 0.39173 * u' - 0.81290 * v'
     * b = 1.1643 * y' + 2.017   * u' + 0.0     * v'
     *
     * DP3 might look like the straightforward solution
     * but we'd need to move the texture yuv values in
     * the same reg for this to work. Therefore use MADs.
     * Brightness just adds to the off constant.
     * Contrast is multiplication of luminance.
     * Saturation and hue change the u and v coeffs.
     * Default values (before adjustments - depend on colorspace):
     * yco = 1.1643
     * uco = 0, -0.39173, 2.017
     * vco = 1.5958, -0.8129, 0
     * off = -0.0625 * yco + -0.5 * uco[r] + -0.5 * vco[r],
     *       -0.0625 * yco + -0.5 * uco[g] + -0.5 * vco[g],
     *       -0.0625 * yco + -0.5 * uco[b] + -0.5 * vco[b],
     *
     * temp = MAD(yco, yuv.yyyy, off)
     * temp = MAD(uco, yuv.uuuu, temp)
     * result = MAD(vco, yuv.vvvv, temp)
     */
    /* TODO: calc consts in the shader */
    const float Loff = -0.0627;
    const float Coff = -0.502;
    float uvcosf, uvsinf;
    float yco;
    float uco[3], vco[3], off[3];
    float bright, cont, gamma;
    int ref = pPriv->transform_index;
    Bool needgamma = FALSE;
    float *ps_alu_consts;
    const_config_t ps_const_conf;
    float *vs_alu_consts;
    const_config_t vs_const_conf;

    cont = RTFContrast(pPriv->contrast);
    bright = RTFBrightness(pPriv->brightness);
    gamma = (float)pPriv->gamma / 1000.0;
    uvcosf = RTFSaturation(pPriv->saturation) * cos(RTFHue(pPriv->hue));
    uvsinf = RTFSaturation(pPriv->saturation) * sin(RTFHue(pPriv->hue));
    /* overlay video also does pre-gamma contrast/sat adjust, should we? */

    yco = trans[ref].RefLuma * cont;
    uco[0] = -trans[ref].RefRCr * uvsinf;
    uco[1] = trans[ref].RefGCb * uvcosf - trans[ref].RefGCr * uvsinf;
    uco[2] = trans[ref].RefBCb * uvcosf;
    vco[0] = trans[ref].RefRCr * uvcosf;
    vco[1] = trans[ref].RefGCb * uvsinf + trans[ref].RefGCr * uvcosf;
    vco[2] = trans[ref].RefBCb * uvsinf;
    off[0] = Loff * yco + Coff * (uco[0] + vco[0]) + bright;
    off[1] = Loff * yco + Coff * (uco[1] + vco[1]) + bright;
    off[2] = Loff * yco + Coff * (uco[2] + vco[2]) + bright;

    // XXX
    gamma = 1.0;

    if (gamma != 1.0) {
	needgamma = TRUE;
	/* note: gamma correction is out = in ^ gamma;
	   gpu can only do LG2/EX2 therefore we transform into
	   in ^ gamma = 2 ^ (log2(in) * gamma).
	   Lots of scalar ops, unfortunately (better solution?) -
	   without gamma that's 3 inst, with gamma it's 10...
	   could use different gamma factors per channel,
	   if that's of any use. */
    }

    CLEAR (cb_conf);
    CLEAR (tex_res);
    CLEAR (tex_samp);
    CLEAR (vs_conf);
    CLEAR (ps_conf);
    CLEAR (vs_const_conf);
    CLEAR (ps_const_conf);

    dst_obj.offset = 0;
    src_obj.offset = 0;
    dst_obj.bo = radeon_get_pixmap_bo(pPixmap);
    dst_obj.tiling_flags = radeon_get_pixmap_tiling(pPixmap);
    dst_obj.surface = radeon_get_pixmap_surface(pPixmap);

    dst_obj.pitch = exaGetPixmapPitch(pPixmap) / (pPixmap->drawable.bitsPerPixel / 8);

    src_obj.pitch = pPriv->src_pitch;
    src_obj.width = pPriv->w;
    src_obj.height = pPriv->h;
    src_obj.bpp = 16;
    src_obj.domain = RADEON_GEM_DOMAIN_VRAM | RADEON_GEM_DOMAIN_GTT;
    src_obj.bo = pPriv->src_bo[pPriv->currentBuffer];
    src_obj.tiling_flags = 0;
    src_obj.surface = NULL;

    dst_obj.width = pPixmap->drawable.width;
    dst_obj.height = pPixmap->drawable.height;
    dst_obj.bpp = pPixmap->drawable.bitsPerPixel;
    dst_obj.domain = RADEON_GEM_DOMAIN_VRAM;

    if (!R600SetAccelState(pScrn,
			   &src_obj,
			   NULL,
			   &dst_obj,
			   accel_state->xv_vs_offset, accel_state->xv_ps_offset,
			   3, 0xffffffff))
	return;

#ifdef COMPOSITE
    dstxoff = -pPixmap->screen_x + pPixmap->drawable.x;
    dstyoff = -pPixmap->screen_y + pPixmap->drawable.y;
#else
    dstxoff = 0;
    dstyoff = 0;
#endif

    radeon_vbo_check(pScrn, &accel_state->vbo, 16);
    radeon_vbo_check(pScrn, &accel_state->cbuf, 512);
    radeon_cp_start(pScrn);

    evergreen_set_default_state(pScrn);

    evergreen_set_generic_scissor(pScrn, 0, 0, accel_state->dst_obj.width, accel_state->dst_obj.height);
    evergreen_set_screen_scissor(pScrn, 0, 0, accel_state->dst_obj.width, accel_state->dst_obj.height);
    evergreen_set_window_scissor(pScrn, 0, 0, accel_state->dst_obj.width, accel_state->dst_obj.height);

    /* PS bool constant */
    switch(pPriv->id) {
    case FOURCC_YV12:
    case FOURCC_I420:
	evergreen_set_bool_consts(pScrn, SQ_BOOL_CONST_ps, (1 << 0));
	break;
    case FOURCC_UYVY:
    case FOURCC_YUY2:
    default:
	evergreen_set_bool_consts(pScrn, SQ_BOOL_CONST_ps, (0 << 0));
	break;
    }

    /* Shader */
    vs_conf.shader_addr         = accel_state->vs_mc_addr;
    vs_conf.shader_size         = accel_state->vs_size;
    vs_conf.num_gprs            = 2;
    vs_conf.stack_size          = 0;
    vs_conf.bo                  = accel_state->shaders_bo;
    evergreen_vs_setup(pScrn, &vs_conf, RADEON_GEM_DOMAIN_VRAM);

    ps_conf.shader_addr         = accel_state->ps_mc_addr;
    ps_conf.shader_size         = accel_state->ps_size;
    ps_conf.num_gprs            = 3;
    ps_conf.stack_size          = 1;
    ps_conf.clamp_consts        = 0;
    ps_conf.export_mode         = 2;
    ps_conf.bo                  = accel_state->shaders_bo;
    evergreen_ps_setup(pScrn, &ps_conf, RADEON_GEM_DOMAIN_VRAM);

    /* Texture */
    switch(pPriv->id) {
    case FOURCC_YV12:
    case FOURCC_I420:
	accel_state->src_size[0] = accel_state->src_obj[0].pitch * pPriv->h;

	/* Y texture */
	tex_res.id                  = 0;
	tex_res.w                   = accel_state->src_obj[0].width;
	tex_res.h                   = accel_state->src_obj[0].height;
	tex_res.pitch               = accel_state->src_obj[0].pitch;
	tex_res.depth               = 0;
	tex_res.dim                 = SQ_TEX_DIM_2D;
	tex_res.base                = accel_state->src_obj[0].offset;
	tex_res.mip_base            = accel_state->src_obj[0].offset;
	tex_res.size                = accel_state->src_size[0];
	tex_res.bo                  = accel_state->src_obj[0].bo;
	tex_res.mip_bo              = accel_state->src_obj[0].bo;
	tex_res.surface             = NULL;

	tex_res.format              = FMT_8;
	tex_res.dst_sel_x           = SQ_SEL_X; /* Y */
	tex_res.dst_sel_y           = SQ_SEL_1;
	tex_res.dst_sel_z           = SQ_SEL_1;
	tex_res.dst_sel_w           = SQ_SEL_1;

	tex_res.base_level          = 0;
	tex_res.last_level          = 0;
	tex_res.perf_modulation     = 0;
	tex_res.interlaced          = 0;
	if (accel_state->src_obj[0].tiling_flags == 0)
	    tex_res.array_mode          = 1;
	evergreen_set_tex_resource(pScrn, &tex_res, accel_state->src_obj[0].domain);

	/* Y sampler */
	tex_samp.id                 = 0;
	tex_samp.clamp_x            = SQ_TEX_CLAMP_LAST_TEXEL;
	tex_samp.clamp_y            = SQ_TEX_CLAMP_LAST_TEXEL;
	tex_samp.clamp_z            = SQ_TEX_WRAP;

	/* xxx: switch to bicubic */
	tex_samp.xy_mag_filter      = SQ_TEX_XY_FILTER_BILINEAR;
	tex_samp.xy_min_filter      = SQ_TEX_XY_FILTER_BILINEAR;

	tex_samp.z_filter           = SQ_TEX_Z_FILTER_NONE;
	tex_samp.mip_filter         = 0;			/* no mipmap */
	evergreen_set_tex_sampler(pScrn, &tex_samp);

	/* U or V texture */
	tex_res.id                  = 1;
	tex_res.format              = FMT_8;
	tex_res.w                   = accel_state->src_obj[0].width >> 1;
	tex_res.h                   = accel_state->src_obj[0].height >> 1;
	tex_res.pitch               = RADEON_ALIGN(accel_state->src_obj[0].pitch >> 1, pPriv->hw_align);
	tex_res.dst_sel_x           = SQ_SEL_X; /* V or U */
	tex_res.dst_sel_y           = SQ_SEL_1;
	tex_res.dst_sel_z           = SQ_SEL_1;
	tex_res.dst_sel_w           = SQ_SEL_1;
	tex_res.interlaced          = 0;

	tex_res.base                = accel_state->src_obj[0].offset + pPriv->planev_offset;
	tex_res.mip_base            = accel_state->src_obj[0].offset + pPriv->planev_offset;
	tex_res.size                = tex_res.pitch * (pPriv->h >> 1);
	if (accel_state->src_obj[0].tiling_flags == 0)
	    tex_res.array_mode          = 1;
	evergreen_set_tex_resource(pScrn, &tex_res, accel_state->src_obj[0].domain);

	/* U or V sampler */
	tex_samp.id                 = 1;
	evergreen_set_tex_sampler(pScrn, &tex_samp);

	/* U or V texture */
	tex_res.id                  = 2;
	tex_res.format              = FMT_8;
	tex_res.w                   = accel_state->src_obj[0].width >> 1;
	tex_res.h                   = accel_state->src_obj[0].height >> 1;
	tex_res.pitch               = RADEON_ALIGN(accel_state->src_obj[0].pitch >> 1, pPriv->hw_align);
	tex_res.dst_sel_x           = SQ_SEL_X; /* V or U */
	tex_res.dst_sel_y           = SQ_SEL_1;
	tex_res.dst_sel_z           = SQ_SEL_1;
	tex_res.dst_sel_w           = SQ_SEL_1;
	tex_res.interlaced          = 0;

	tex_res.base                = accel_state->src_obj[0].offset + pPriv->planeu_offset;
	tex_res.mip_base            = accel_state->src_obj[0].offset + pPriv->planeu_offset;
	tex_res.size                = tex_res.pitch * (pPriv->h >> 1);
	if (accel_state->src_obj[0].tiling_flags == 0)
	    tex_res.array_mode          = 1;
	evergreen_set_tex_resource(pScrn, &tex_res, accel_state->src_obj[0].domain);

	/* UV sampler */
	tex_samp.id                 = 2;
	evergreen_set_tex_sampler(pScrn, &tex_samp);
	break;
    case FOURCC_UYVY:
    case FOURCC_YUY2:
    default:
	accel_state->src_size[0] = accel_state->src_obj[0].pitch * pPriv->h;

	/* Y texture */
	tex_res.id                  = 0;
	tex_res.w                   = accel_state->src_obj[0].width;
	tex_res.h                   = accel_state->src_obj[0].height;
	tex_res.pitch               = accel_state->src_obj[0].pitch >> 1;
	tex_res.depth               = 0;
	tex_res.dim                 = SQ_TEX_DIM_2D;
	tex_res.base                = accel_state->src_obj[0].offset;
	tex_res.mip_base            = accel_state->src_obj[0].offset;
	tex_res.size                = accel_state->src_size[0];
	tex_res.bo                  = accel_state->src_obj[0].bo;
	tex_res.mip_bo              = accel_state->src_obj[0].bo;
	tex_res.surface             = NULL;

	tex_res.format              = FMT_8_8;
	if (pPriv->id == FOURCC_UYVY)
	    tex_res.dst_sel_x           = SQ_SEL_Y; /* Y */
	else
	    tex_res.dst_sel_x           = SQ_SEL_X; /* Y */
	tex_res.dst_sel_y           = SQ_SEL_1;
	tex_res.dst_sel_z           = SQ_SEL_1;
	tex_res.dst_sel_w           = SQ_SEL_1;

	tex_res.base_level          = 0;
	tex_res.last_level          = 0;
	tex_res.perf_modulation     = 0;
	tex_res.interlaced          = 0;
	if (accel_state->src_obj[0].tiling_flags == 0)
	    tex_res.array_mode          = 1;
	evergreen_set_tex_resource(pScrn, &tex_res, accel_state->src_obj[0].domain);

	/* Y sampler */
	tex_samp.id                 = 0;
	tex_samp.clamp_x            = SQ_TEX_CLAMP_LAST_TEXEL;
	tex_samp.clamp_y            = SQ_TEX_CLAMP_LAST_TEXEL;
	tex_samp.clamp_z            = SQ_TEX_WRAP;

	tex_samp.xy_mag_filter      = SQ_TEX_XY_FILTER_BILINEAR;
	tex_samp.xy_min_filter      = SQ_TEX_XY_FILTER_BILINEAR;

	tex_samp.z_filter           = SQ_TEX_Z_FILTER_NONE;
	tex_samp.mip_filter         = 0;			/* no mipmap */
	evergreen_set_tex_sampler(pScrn, &tex_samp);

	/* UV texture */
	tex_res.id                  = 1;
	tex_res.format              = FMT_8_8_8_8;
	tex_res.w                   = accel_state->src_obj[0].width >> 1;
	tex_res.h                   = accel_state->src_obj[0].height;
	tex_res.pitch               = accel_state->src_obj[0].pitch >> 2;
	if (pPriv->id == FOURCC_UYVY) {
	    tex_res.dst_sel_x           = SQ_SEL_X; /* V */
	    tex_res.dst_sel_y           = SQ_SEL_Z; /* U */
	} else {
	    tex_res.dst_sel_x           = SQ_SEL_Y; /* V */
	    tex_res.dst_sel_y           = SQ_SEL_W; /* U */
	}
	tex_res.dst_sel_z           = SQ_SEL_1;
	tex_res.dst_sel_w           = SQ_SEL_1;
	tex_res.interlaced          = 0;

	tex_res.base                = accel_state->src_obj[0].offset;
	tex_res.mip_base            = accel_state->src_obj[0].offset;
	tex_res.size                = accel_state->src_size[0];
	if (accel_state->src_obj[0].tiling_flags == 0)
	    tex_res.array_mode          = 1;
	evergreen_set_tex_resource(pScrn, &tex_res, accel_state->src_obj[0].domain);

	/* UV sampler */
	tex_samp.id                 = 1;
	evergreen_set_tex_sampler(pScrn, &tex_samp);
	break;
    }

    cb_conf.id = 0;
    cb_conf.w = accel_state->dst_obj.pitch;
    cb_conf.h = accel_state->dst_obj.height;
    cb_conf.base = accel_state->dst_obj.offset;
    cb_conf.bo = accel_state->dst_obj.bo;
    cb_conf.surface = accel_state->dst_obj.surface;

    switch (accel_state->dst_obj.bpp) {
    case 16:
	if (pPixmap->drawable.depth == 15) {
	    cb_conf.format = COLOR_1_5_5_5;
	    cb_conf.comp_swap = 1; /* ARGB */
	} else {
	    cb_conf.format = COLOR_5_6_5;
	    cb_conf.comp_swap = 2; /* RGB */
	}
#if X_BYTE_ORDER == X_BIG_ENDIAN
	cb_conf.endian = ENDIAN_8IN16;
#endif
	break;
    case 32:
	cb_conf.format = COLOR_8_8_8_8;
	cb_conf.comp_swap = 1; /* ARGB */
#if X_BYTE_ORDER == X_BIG_ENDIAN
	cb_conf.endian = ENDIAN_8IN32;
#endif
	break;
    default:
	return;
    }

    cb_conf.source_format = EXPORT_4C_16BPC;
    cb_conf.blend_clamp = 1;
    cb_conf.pmask = 0xf;
    cb_conf.rop = 3;
    if (accel_state->dst_obj.tiling_flags == 0) {
	cb_conf.array_mode = 1;
	cb_conf.non_disp_tiling = 1;
    }
    evergreen_set_render_target(pScrn, &cb_conf, accel_state->dst_obj.domain);

    evergreen_set_spi(pScrn, (1 - 1), 1);

    /* PS alu constants */
    ps_const_conf.size_bytes = 256;
    ps_const_conf.type = SHADER_TYPE_PS;
    ps_alu_consts = radeon_vbo_space(pScrn, &accel_state->cbuf, 256);
    ps_const_conf.bo = accel_state->cbuf.vb_bo;
    ps_const_conf.const_addr = accel_state->cbuf.vb_mc_addr + accel_state->cbuf.vb_offset;
    ps_const_conf.cpu_ptr = (uint32_t *)(char *)ps_alu_consts;

    ps_alu_consts[0] = off[0];
    ps_alu_consts[1] = off[1];
    ps_alu_consts[2] = off[2];
    ps_alu_consts[3] = yco;

    ps_alu_consts[4] = uco[0];
    ps_alu_consts[5] = uco[1];
    ps_alu_consts[6] = uco[2];
    ps_alu_consts[7] = gamma;

    ps_alu_consts[8] = vco[0];
    ps_alu_consts[9] = vco[1];
    ps_alu_consts[10] = vco[2];
    ps_alu_consts[11] = 0.0;

    radeon_vbo_commit(pScrn, &accel_state->cbuf);
    evergreen_set_alu_consts(pScrn, &ps_const_conf, RADEON_GEM_DOMAIN_GTT);

    /* VS alu constants */
    vs_const_conf.size_bytes = 256;
    vs_const_conf.type = SHADER_TYPE_VS;
    vs_alu_consts = radeon_vbo_space(pScrn, &accel_state->cbuf, 256);
    vs_const_conf.bo = accel_state->cbuf.vb_bo;
    vs_const_conf.const_addr = accel_state->cbuf.vb_mc_addr + accel_state->cbuf.vb_offset;
    vs_const_conf.cpu_ptr = (uint32_t *)(char *)vs_alu_consts;

    vs_alu_consts[0] = 1.0 / pPriv->w;
    vs_alu_consts[1] = 1.0 / pPriv->h;
    vs_alu_consts[2] = 0.0;
    vs_alu_consts[3] = 0.0;

    radeon_vbo_commit(pScrn, &accel_state->cbuf);
    evergreen_set_alu_consts(pScrn, &vs_const_conf, RADEON_GEM_DOMAIN_GTT);

    if (pPriv->vsync) {
	xf86CrtcPtr crtc;
	if (pPriv->desired_crtc)
	    crtc = pPriv->desired_crtc;
	else
	    crtc = radeon_pick_best_crtc(pScrn,
					 pPriv->drw_x,
					 pPriv->drw_x + pPriv->dst_w,
					 pPriv->drw_y,
					 pPriv->drw_y + pPriv->dst_h);
	if (crtc)
	    evergreen_cp_wait_vline_sync(pScrn, pPixmap,
					 crtc,
					 pPriv->drw_y - crtc->y,
					 (pPriv->drw_y - crtc->y) + pPriv->dst_h);
    }

    while (nBox--) {
	int srcX, srcY, srcw, srch;
	int dstX, dstY, dstw, dsth;
	float *vb;


	dstX = pBox->x1 + dstxoff;
	dstY = pBox->y1 + dstyoff;
	dstw = pBox->x2 - pBox->x1;
	dsth = pBox->y2 - pBox->y1;

	srcX = pPriv->src_x;
	srcX += ((pBox->x1 - pPriv->drw_x) *
		 pPriv->src_w) / pPriv->dst_w;
	srcY = pPriv->src_y;
	srcY += ((pBox->y1 - pPriv->drw_y) *
		 pPriv->src_h) / pPriv->dst_h;

	srcw = (pPriv->src_w * dstw) / pPriv->dst_w;
	srch = (pPriv->src_h * dsth) / pPriv->dst_h;

	vb = radeon_vbo_space(pScrn, &accel_state->vbo, 16);

	vb[0] = (float)dstX;
	vb[1] = (float)dstY;
	vb[2] = (float)srcX;
	vb[3] = (float)srcY;

	vb[4] = (float)dstX;
	vb[5] = (float)(dstY + dsth);
	vb[6] = (float)srcX;
	vb[7] = (float)(srcY + srch);

	vb[8] = (float)(dstX + dstw);
	vb[9] = (float)(dstY + dsth);
	vb[10] = (float)(srcX + srcw);
	vb[11] = (float)(srcY + srch);

	radeon_vbo_commit(pScrn, &accel_state->vbo);

	pBox++;
    }

    evergreen_finish_op(pScrn, 16);

    DamageDamageRegion(pPriv->pDraw, &pPriv->clip);
}
Exemple #22
0
static Bool
setup_texture(NVPtr pNv, int unit, PicturePtr pict, PixmapPtr pixmap)
{
	struct nouveau_pushbuf *push = pNv->pushbuf;
	struct nouveau_bo *bo = nouveau_pixmap_bo(pixmap);
	unsigned reloc = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD;
	unsigned h = pict->pDrawable->height;
	unsigned w = pict->pDrawable->width;
	unsigned format;

	format = NV10_3D_TEX_FORMAT_WRAP_T_CLAMP_TO_EDGE |
		 NV10_3D_TEX_FORMAT_WRAP_S_CLAMP_TO_EDGE |
		 log2i(w) << 20 | log2i(h) << 16 |
		 1 << 12 | /* lod == 1 */
		 get_tex_format(pNv, pict) |
		 0x50 /* UNK */;

	/* NPOT_SIZE expects an even number for width, we can round up uneven
	 * numbers here because EXA always gives 64 byte aligned pixmaps and
	 * for all formats we support 64 bytes represents an even number of
	 * pixels
	 */
	w = (w + 1) & ~1;

	BEGIN_NV04(push, NV10_3D(TEX_OFFSET(unit)), 1);
	PUSH_MTHDl(push, NV10_3D(TEX_OFFSET(unit)), bo, 0, reloc);
	BEGIN_NV04(push, NV10_3D(TEX_FORMAT(unit)), 1);
	PUSH_MTHDs(push, NV10_3D(TEX_FORMAT(unit)), bo, format, reloc,
			 NV10_3D_TEX_FORMAT_DMA0,
			 NV10_3D_TEX_FORMAT_DMA1);
	BEGIN_NV04(push, NV10_3D(TEX_ENABLE(unit)), 1 );
	PUSH_DATA (push, NV10_3D_TEX_ENABLE_ENABLE);
	BEGIN_NV04(push, NV10_3D(TEX_NPOT_PITCH(unit)), 1);
	PUSH_DATA (push, exaGetPixmapPitch(pixmap) << 16);
	BEGIN_NV04(push, NV10_3D(TEX_NPOT_SIZE(unit)), 1);
	PUSH_DATA (push, (w << 16) | h);
	BEGIN_NV04(push, NV10_3D(TEX_FILTER(unit)), 1);
	if (pict->filter == PictFilterNearest)
		PUSH_DATA(push, NV10_3D_TEX_FILTER_MAGNIFY_NEAREST |
				NV10_3D_TEX_FILTER_MINIFY_NEAREST);
	else
		PUSH_DATA(push, NV10_3D_TEX_FILTER_MAGNIFY_LINEAR |
				NV10_3D_TEX_FILTER_MINIFY_LINEAR);
	if (pict->transform) {
		BEGIN_NV04(push, NV10_3D(TEX_MATRIX_ENABLE(unit)), 1);
		PUSH_DATA (push, 1);
		BEGIN_NV04(push, NV10_3D(TEX_MATRIX(unit, 0)), 16);
		PUSH_DATAf(push, xFixedToFloat(pict->transform->matrix[0][0]));
		PUSH_DATAf(push, xFixedToFloat(pict->transform->matrix[0][1]));
		PUSH_DATAf(push, 0.f);
		PUSH_DATAf(push, xFixedToFloat(pict->transform->matrix[0][2]));
		PUSH_DATAf(push, xFixedToFloat(pict->transform->matrix[1][0]));
		PUSH_DATAf(push, xFixedToFloat(pict->transform->matrix[1][1]));
		PUSH_DATAf(push, 0.f);
		PUSH_DATAf(push, xFixedToFloat(pict->transform->matrix[1][2]));
		PUSH_DATAf(push, 0.0f);
		PUSH_DATAf(push, 0.0f);
		PUSH_DATAf(push, 0.0f);
		PUSH_DATAf(push, 0.0f);
		PUSH_DATAf(push, xFixedToFloat(pict->transform->matrix[2][0]));
		PUSH_DATAf(push, xFixedToFloat(pict->transform->matrix[2][1]));
		PUSH_DATAf(push, 0.0f);
		PUSH_DATAf(push, xFixedToFloat(pict->transform->matrix[2][2]));
	} else {
		BEGIN_NV04(push, NV10_3D(TEX_MATRIX_ENABLE(unit)), 1);
		PUSH_DATA (push, 0);
	}

	return TRUE;
}
Exemple #23
0
static Bool
NV40EXAPictTexture(NVPtr pNv, PixmapPtr pPix, PicturePtr pPict, int unit)
{
	unsigned reloc = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_WR;
	struct nouveau_pushbuf *push = pNv->pushbuf;
	struct nouveau_bo *bo = nouveau_pixmap_bo(pPix);
	nv_pict_texture_format_t *fmt;

	fmt = NV40_GetPictTextureFormat(pPict->format);
	if (!fmt)
		return FALSE;

	BEGIN_NV04(push, NV30_3D(TEX_OFFSET(unit)), 8);
	PUSH_MTHDl(push, NV30_3D(TEX_OFFSET(unit)), bo, 0, reloc);
	PUSH_MTHDs(push, NV30_3D(TEX_FORMAT(unit)), bo, fmt->card_fmt |
			 NV40_3D_TEX_FORMAT_LINEAR |
			 NV30_3D_TEX_FORMAT_DIMS_2D | 0x8000 |
			 NV30_3D_TEX_FORMAT_NO_BORDER |
			 (1 << NV40_3D_TEX_FORMAT_MIPMAP_COUNT__SHIFT),
			 reloc | NOUVEAU_BO_OR,
			 NV30_3D_TEX_FORMAT_DMA0, NV30_3D_TEX_FORMAT_DMA1);
	if (pPict->repeat) {
		switch(pPict->repeatType) {
		case RepeatPad:
			PUSH_DATA (push, NV30_3D_TEX_WRAP_S_CLAMP | 
					 NV30_3D_TEX_WRAP_T_CLAMP |
					 NV30_3D_TEX_WRAP_R_CLAMP);
			break;
		case RepeatReflect:
			PUSH_DATA (push, NV30_3D_TEX_WRAP_S_MIRRORED_REPEAT |
					 NV30_3D_TEX_WRAP_T_MIRRORED_REPEAT |
					 NV30_3D_TEX_WRAP_R_MIRRORED_REPEAT);
			break;
		case RepeatNormal:
		default:
			PUSH_DATA (push, NV30_3D_TEX_WRAP_S_REPEAT |
					 NV30_3D_TEX_WRAP_T_REPEAT |
					 NV30_3D_TEX_WRAP_R_REPEAT);
			break;
		}
	} else {
		PUSH_DATA (push, NV30_3D_TEX_WRAP_S_CLAMP_TO_BORDER |
				 NV30_3D_TEX_WRAP_T_CLAMP_TO_BORDER |
				 NV30_3D_TEX_WRAP_R_CLAMP_TO_BORDER);
	}
	PUSH_DATA (push, NV40_3D_TEX_ENABLE_ENABLE);
	PUSH_DATA (push, fmt->card_swz);
	if (pPict->filter == PictFilterBilinear) {
		PUSH_DATA (push, NV30_3D_TEX_FILTER_MIN_LINEAR |
				 NV30_3D_TEX_FILTER_MAG_LINEAR | 0x3fd6);
	} else {
		PUSH_DATA (push, NV30_3D_TEX_FILTER_MIN_NEAREST |
				 NV30_3D_TEX_FILTER_MAG_NEAREST | 0x3fd6);
	}
	PUSH_DATA (push, (pPix->drawable.width << 16) | pPix->drawable.height);
	PUSH_DATA (push, 0); /* border ARGB */
	BEGIN_NV04(push, NV40_3D(TEX_SIZE1(unit)), 1);
	PUSH_DATA (push, (1 << NV40_3D_TEX_SIZE1_DEPTH__SHIFT) |
			 (uint32_t)exaGetPixmapPitch(pPix));

	BEGIN_NV04(push, NV30_3D(VP_UPLOAD_CONST_ID), 17);
	PUSH_DATA (push, unit * 4);
	if (pPict->transform) {
		PUSH_DATAf(push, xFixedToFloat(pPict->transform->matrix[0][0]));
		PUSH_DATAf(push, xFixedToFloat(pPict->transform->matrix[0][1]));
		PUSH_DATAf(push, xFixedToFloat(pPict->transform->matrix[0][2]));
		PUSH_DATAf(push, 0);
		PUSH_DATAf(push, xFixedToFloat(pPict->transform->matrix[1][0]));
		PUSH_DATAf(push, xFixedToFloat(pPict->transform->matrix[1][1]));
		PUSH_DATAf(push, xFixedToFloat(pPict->transform->matrix[1][2]));
		PUSH_DATAf(push, 0);
		PUSH_DATAf(push, xFixedToFloat(pPict->transform->matrix[2][0]));
		PUSH_DATAf(push, xFixedToFloat(pPict->transform->matrix[2][1]));
		PUSH_DATAf(push, xFixedToFloat(pPict->transform->matrix[2][2]));
		PUSH_DATAf(push, 0);
	} else {
		PUSH_DATAf(push, 1.0);
		PUSH_DATAf(push, 0.0);
		PUSH_DATAf(push, 0.0);
		PUSH_DATAf(push, 0.0);
		PUSH_DATAf(push, 0.0);
		PUSH_DATAf(push, 1.0);
		PUSH_DATAf(push, 0.0);
		PUSH_DATAf(push, 0.0);
		PUSH_DATAf(push, 0.0);
		PUSH_DATAf(push, 0.0);
		PUSH_DATAf(push, 1.0);
		PUSH_DATAf(push, 0.0);
	}
	PUSH_DATAf(push, 1.0 / pPix->drawable.width);
	PUSH_DATAf(push, 1.0 / pPix->drawable.height);
	PUSH_DATAf(push, 0.0);
	PUSH_DATAf(push, 1.0);

	return TRUE;
}