10d16fef4Smrg/*
20a1d3ae0Smrg * Copyright © 2001 Keith Packard
30d16fef4Smrg *             2010 Intel Corporation
40d16fef4Smrg *             2012,2015 Advanced Micro Devices, Inc.
50d16fef4Smrg *
60a1d3ae0Smrg * Partly based on code Copyright © 2008 Red Hat, Inc.
70a1d3ae0Smrg * Partly based on code Copyright © 2000 SuSE, Inc.
80d16fef4Smrg *
90a1d3ae0Smrg * Partly based on code that is Copyright © The XFree86 Project Inc.
100d16fef4Smrg *
110d16fef4Smrg * Permission to use, copy, modify, distribute, and sell this software and its
120d16fef4Smrg * documentation for any purpose is hereby granted without fee, provided that
130d16fef4Smrg * the above copyright notice appear in all copies and that both that
140d16fef4Smrg * copyright notice and this permission notice appear in supporting
150d16fef4Smrg * documentation, and that the name of the opyright holders not be used in
160d16fef4Smrg * advertising or publicity pertaining to distribution of the software without
170d16fef4Smrg * specific, written prior permission.  The copyright holders make no
180d16fef4Smrg * representations about the suitability of this software for any purpose.  It
190d16fef4Smrg * is provided "as is" without express or implied warranty.
200d16fef4Smrg *
210d16fef4Smrg * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
220d16fef4Smrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
230d16fef4Smrg * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
240d16fef4Smrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
250d16fef4Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
260d16fef4Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
270d16fef4Smrg * PERFORMANCE OF THIS SOFTWARE.
280d16fef4Smrg */
290d16fef4Smrg
300d16fef4Smrg
310d16fef4Smrg#ifdef HAVE_CONFIG_H
320d16fef4Smrg#include <config.h>
330d16fef4Smrg#endif
340d16fef4Smrg
350d16fef4Smrg#ifdef USE_GLAMOR
360d16fef4Smrg
370d16fef4Smrg#include "radeon.h"
387314432eSmrg#include "radeon_bo_helper.h"
390d16fef4Smrg#include "radeon_glamor.h"
400d16fef4Smrg
410d16fef4Smrg
420d16fef4Smrg/* Are there any outstanding GPU operations for this pixmap? */
430d16fef4Smrgstatic Bool
440d16fef4Smrgradeon_glamor_gpu_pending(uint_fast32_t gpu_synced, uint_fast32_t gpu_access)
450d16fef4Smrg{
460d16fef4Smrg	return (int_fast32_t)(gpu_access - gpu_synced) > 0;
470d16fef4Smrg}
480d16fef4Smrg
490d16fef4Smrg/*
500d16fef4Smrg * Pixmap CPU access wrappers
510d16fef4Smrg */
520d16fef4Smrg
530d16fef4Smrgstatic Bool
540d16fef4Smrgradeon_glamor_prepare_access_cpu(ScrnInfoPtr scrn, RADEONInfoPtr info,
550d16fef4Smrg				 PixmapPtr pixmap, struct radeon_pixmap *priv,
560d16fef4Smrg				 Bool need_sync)
570d16fef4Smrg{
5839413783Smrg	struct radeon_buffer *bo = priv->bo;
590d16fef4Smrg	int ret;
600d16fef4Smrg
610d16fef4Smrg	if (!pixmap->devPrivate.ptr) {
6239413783Smrg		/* When falling back to swrast, flush all pending operations */
6339413783Smrg		if (need_sync) {
6439413783Smrg			glamor_block_handler(scrn->pScreen);
6539413783Smrg			info->gpu_flushed++;
6639413783Smrg		}
6739413783Smrg
6839413783Smrg		ret = radeon_bo_map(bo->bo.radeon, 1);
690d16fef4Smrg		if (ret) {
700d16fef4Smrg			xf86DrvMsg(scrn->scrnIndex, X_WARNING,
710d16fef4Smrg				   "%s: bo map (tiling_flags %d) failed: %s\n",
720d16fef4Smrg				   __FUNCTION__,
730d16fef4Smrg				   priv->tiling_flags,
740d16fef4Smrg				   strerror(-ret));
750d16fef4Smrg			return FALSE;
760d16fef4Smrg		}
770d16fef4Smrg
7839413783Smrg		pixmap->devPrivate.ptr = bo->bo.radeon->ptr;
7939413783Smrg	} else if (need_sync)
8039413783Smrg		radeon_finish(scrn, bo);
8139413783Smrg
8239413783Smrg	info->gpu_synced = info->gpu_flushed;
830d16fef4Smrg
840d16fef4Smrg	return TRUE;
850d16fef4Smrg}
860d16fef4Smrg
870d16fef4Smrgstatic Bool
880d16fef4Smrgradeon_glamor_prepare_access_cpu_ro(ScrnInfoPtr scrn, PixmapPtr pixmap,
890d16fef4Smrg				    struct radeon_pixmap *priv)
900d16fef4Smrg{
910d16fef4Smrg	RADEONInfoPtr info;
920d16fef4Smrg	Bool need_sync;
930d16fef4Smrg
940d16fef4Smrg	if (!priv)
950d16fef4Smrg		return TRUE;
960d16fef4Smrg
970d16fef4Smrg	info = RADEONPTR(scrn);
980d16fef4Smrg	need_sync = radeon_glamor_gpu_pending(info->gpu_synced, priv->gpu_write);
990d16fef4Smrg	return radeon_glamor_prepare_access_cpu(scrn, RADEONPTR(scrn), pixmap,
1000d16fef4Smrg						priv, need_sync);
1010d16fef4Smrg}
1020d16fef4Smrg
1030d16fef4Smrgstatic Bool
1040d16fef4Smrgradeon_glamor_prepare_access_cpu_rw(ScrnInfoPtr scrn, PixmapPtr pixmap,
1050d16fef4Smrg				    struct radeon_pixmap *priv)
1060d16fef4Smrg{
1070d16fef4Smrg	RADEONInfoPtr info;
1080d16fef4Smrg	uint_fast32_t gpu_synced;
1090d16fef4Smrg	Bool need_sync;
1100d16fef4Smrg
1110d16fef4Smrg	if (!priv)
1120d16fef4Smrg		return TRUE;
1130d16fef4Smrg
1140d16fef4Smrg	info = RADEONPTR(scrn);
1150d16fef4Smrg	gpu_synced = info->gpu_synced;
1160d16fef4Smrg	need_sync = radeon_glamor_gpu_pending(gpu_synced, priv->gpu_write) |
1170d16fef4Smrg		radeon_glamor_gpu_pending(gpu_synced, priv->gpu_read);
1180d16fef4Smrg	return radeon_glamor_prepare_access_cpu(scrn, info, pixmap, priv,
1190d16fef4Smrg						need_sync);
1200d16fef4Smrg}
1210d16fef4Smrg
1220d16fef4Smrgstatic void
1230d16fef4Smrgradeon_glamor_finish_access_cpu(PixmapPtr pixmap)
1240d16fef4Smrg{
1250d16fef4Smrg	/* Nothing to do */
1260d16fef4Smrg}
1270d16fef4Smrg
1280d16fef4Smrg/*
1290d16fef4Smrg * Pixmap GPU access wrappers
1300d16fef4Smrg */
1310d16fef4Smrg
1320d16fef4Smrgstatic Bool
1330d16fef4Smrgradeon_glamor_prepare_access_gpu(struct radeon_pixmap *priv)
1340d16fef4Smrg{
13539413783Smrg	return !!priv;
1360d16fef4Smrg}
1370d16fef4Smrg
1380d16fef4Smrgstatic void
1390d16fef4Smrgradeon_glamor_finish_access_gpu_ro(RADEONInfoPtr info,
1400d16fef4Smrg				   struct radeon_pixmap *priv)
1410d16fef4Smrg{
1420d16fef4Smrg	priv->gpu_read = info->gpu_flushed + 1;
1430d16fef4Smrg}
1440d16fef4Smrg
1450d16fef4Smrgstatic void
1460d16fef4Smrgradeon_glamor_finish_access_gpu_rw(RADEONInfoPtr info,
1470d16fef4Smrg				   struct radeon_pixmap *priv)
1480d16fef4Smrg{
1490d16fef4Smrg	priv->gpu_write = priv->gpu_read = info->gpu_flushed + 1;
1500d16fef4Smrg}
1510d16fef4Smrg
1520d16fef4Smrg/*
1530d16fef4Smrg * GC CPU access wrappers
1540d16fef4Smrg */
1550d16fef4Smrg
1560d16fef4Smrgstatic Bool
1570d16fef4Smrgradeon_glamor_prepare_access_gc(ScrnInfoPtr scrn, GCPtr pGC)
1580d16fef4Smrg{
1590d16fef4Smrg	struct radeon_pixmap *priv;
1600d16fef4Smrg
1610d16fef4Smrg	if (pGC->stipple) {
1620d16fef4Smrg		priv = radeon_get_pixmap_private(pGC->stipple);
1630d16fef4Smrg		if (!radeon_glamor_prepare_access_cpu_ro(scrn, pGC->stipple, priv))
1640d16fef4Smrg			return FALSE;
1650d16fef4Smrg	}
1660d16fef4Smrg	if (pGC->fillStyle == FillTiled) {
1670d16fef4Smrg		priv = radeon_get_pixmap_private(pGC->tile.pixmap);
1680d16fef4Smrg		if (!radeon_glamor_prepare_access_cpu_ro(scrn, pGC->tile.pixmap,
1690d16fef4Smrg						      priv)) {
1700d16fef4Smrg			if (pGC->stipple)
1710d16fef4Smrg				radeon_glamor_finish_access_cpu(pGC->stipple);
1720d16fef4Smrg			return FALSE;
1730d16fef4Smrg		}
1740d16fef4Smrg	}
1750d16fef4Smrg	return TRUE;
1760d16fef4Smrg}
1770d16fef4Smrg
1780d16fef4Smrgstatic void
1790d16fef4Smrgradeon_glamor_finish_access_gc(GCPtr pGC)
1800d16fef4Smrg{
1810d16fef4Smrg	if (pGC->fillStyle == FillTiled)
1820d16fef4Smrg		radeon_glamor_finish_access_cpu(pGC->tile.pixmap);
1830d16fef4Smrg	if (pGC->stipple)
1840d16fef4Smrg		radeon_glamor_finish_access_cpu(pGC->stipple);
1850d16fef4Smrg}
1860d16fef4Smrg
1870d16fef4Smrg/*
1880d16fef4Smrg * Picture CPU access wrappers
1890d16fef4Smrg */
1900d16fef4Smrg
1910d16fef4Smrgstatic void
1920d16fef4Smrgradeon_glamor_picture_finish_access_cpu(PicturePtr picture)
1930d16fef4Smrg{
1940d16fef4Smrg	/* Nothing to do */
1950d16fef4Smrg}
1960d16fef4Smrg
1970d16fef4Smrgstatic Bool
1980d16fef4Smrgradeon_glamor_picture_prepare_access_cpu_ro(ScrnInfoPtr scrn,
1990d16fef4Smrg					    PicturePtr picture)
2000d16fef4Smrg{
2010d16fef4Smrg	PixmapPtr pixmap;
2020d16fef4Smrg	struct radeon_pixmap *priv;
2030d16fef4Smrg
20439413783Smrg	if (!picture->pDrawable)
2050d16fef4Smrg		return TRUE;
2060d16fef4Smrg
2070d16fef4Smrg	pixmap = get_drawable_pixmap(picture->pDrawable);
2080d16fef4Smrg	priv = radeon_get_pixmap_private(pixmap);
2090d16fef4Smrg	if (!radeon_glamor_prepare_access_cpu_ro(scrn, pixmap, priv))
2100d16fef4Smrg		return FALSE;
2110d16fef4Smrg
2120d16fef4Smrg	if (picture->alphaMap) {
2130d16fef4Smrg		pixmap = get_drawable_pixmap(picture->alphaMap->pDrawable);
2140d16fef4Smrg		priv = radeon_get_pixmap_private(pixmap);
2150d16fef4Smrg		if (!radeon_glamor_prepare_access_cpu_ro(scrn, pixmap, priv)) {
2160d16fef4Smrg			radeon_glamor_picture_finish_access_cpu(picture);
2170d16fef4Smrg			return FALSE;
2180d16fef4Smrg		}
2190d16fef4Smrg	}
2200d16fef4Smrg
2210d16fef4Smrg	return TRUE;
2220d16fef4Smrg}
2230d16fef4Smrg
2240d16fef4Smrgstatic Bool
2250d16fef4Smrgradeon_glamor_picture_prepare_access_cpu_rw(ScrnInfoPtr scrn,
2260d16fef4Smrg					    PicturePtr picture)
2270d16fef4Smrg{
2280d16fef4Smrg	PixmapPtr pixmap;
2290d16fef4Smrg	struct radeon_pixmap *priv;
2300d16fef4Smrg
2310d16fef4Smrg	pixmap = get_drawable_pixmap(picture->pDrawable);
2320d16fef4Smrg	priv = radeon_get_pixmap_private(pixmap);
2330d16fef4Smrg	if (!radeon_glamor_prepare_access_cpu_rw(scrn, pixmap, priv))
2340d16fef4Smrg		return FALSE;
2350d16fef4Smrg
2360d16fef4Smrg	if (picture->alphaMap) {
2370d16fef4Smrg		pixmap = get_drawable_pixmap(picture->alphaMap->pDrawable);
2380d16fef4Smrg		priv = radeon_get_pixmap_private(pixmap);
2390d16fef4Smrg		if (!radeon_glamor_prepare_access_cpu_rw(scrn, pixmap, priv)) {
2400d16fef4Smrg			radeon_glamor_picture_finish_access_cpu(picture);
2410d16fef4Smrg			return FALSE;
2420d16fef4Smrg		}
2430d16fef4Smrg	}
2440d16fef4Smrg
2450d16fef4Smrg	return TRUE;
2460d16fef4Smrg}
2470d16fef4Smrg
2480d16fef4Smrg/*
2490d16fef4Smrg * GC rendering wrappers
2500d16fef4Smrg */
2510d16fef4Smrg
2520d16fef4Smrgstatic void
2530d16fef4Smrgradeon_glamor_fill_spans(DrawablePtr pDrawable, GCPtr pGC, int nspans,
2540d16fef4Smrg			 DDXPointPtr ppt, int *pwidth, int fSorted)
2550d16fef4Smrg{
2560d16fef4Smrg	ScrnInfoPtr scrn = xf86ScreenToScrn(pDrawable->pScreen);
2570d16fef4Smrg	PixmapPtr pixmap = get_drawable_pixmap(pDrawable);
2580d16fef4Smrg	struct radeon_pixmap *priv = radeon_get_pixmap_private(pixmap);
2590d16fef4Smrg
2600d16fef4Smrg	if (radeon_glamor_prepare_access_cpu_rw(scrn, pixmap, priv)) {
2610d16fef4Smrg		if (radeon_glamor_prepare_access_gc(scrn, pGC)) {
2620d16fef4Smrg			fbFillSpans(pDrawable, pGC, nspans, ppt, pwidth,
2630d16fef4Smrg				    fSorted);
2640d16fef4Smrg			radeon_glamor_finish_access_gc(pGC);
2650d16fef4Smrg		}
2660d16fef4Smrg		radeon_glamor_finish_access_cpu(pixmap);
2670d16fef4Smrg	}
2680d16fef4Smrg}
2690d16fef4Smrg
2700d16fef4Smrgstatic void
2710d16fef4Smrgradeon_glamor_set_spans(DrawablePtr pDrawable, GCPtr pGC, char *psrc,
2720d16fef4Smrg			DDXPointPtr ppt, int *pwidth, int nspans, int fSorted)
2730d16fef4Smrg{
2740d16fef4Smrg	ScrnInfoPtr scrn = xf86ScreenToScrn(pDrawable->pScreen);
2750d16fef4Smrg	PixmapPtr pixmap = get_drawable_pixmap(pDrawable);
2760d16fef4Smrg	struct radeon_pixmap *priv = radeon_get_pixmap_private(pixmap);
2770d16fef4Smrg
2780d16fef4Smrg	if (radeon_glamor_prepare_access_cpu_rw(scrn, pixmap, priv)) {
2790d16fef4Smrg		fbSetSpans(pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted);
2800d16fef4Smrg		radeon_glamor_finish_access_cpu(pixmap);
2810d16fef4Smrg	}
2820d16fef4Smrg}
2830d16fef4Smrg
2840d16fef4Smrgstatic void
2850d16fef4Smrgradeon_glamor_put_image(DrawablePtr pDrawable, GCPtr pGC, int depth,
2860d16fef4Smrg			int x, int y, int w, int h, int leftPad, int format,
2870d16fef4Smrg			char *bits)
2880d16fef4Smrg{
2890d16fef4Smrg	ScrnInfoPtr scrn = xf86ScreenToScrn(pDrawable->pScreen);
2900d16fef4Smrg	PixmapPtr pixmap = get_drawable_pixmap(pDrawable);
2910d16fef4Smrg	struct radeon_pixmap *priv = radeon_get_pixmap_private(pixmap);
2920d16fef4Smrg
2930d16fef4Smrg	if (radeon_glamor_prepare_access_cpu_rw(scrn, pixmap, priv)) {
2940d16fef4Smrg		fbPutImage(pDrawable, pGC, depth, x, y, w, h, leftPad, format,
2950d16fef4Smrg			   bits);
2960d16fef4Smrg		radeon_glamor_finish_access_cpu(pixmap);
2970d16fef4Smrg	}
2980d16fef4Smrg}
2990d16fef4Smrg
3000d16fef4Smrgstatic RegionPtr
3010d16fef4Smrgradeon_glamor_copy_plane(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
3020d16fef4Smrg			 int srcx, int srcy, int w, int h, int dstx, int dsty,
3030d16fef4Smrg			 unsigned long bitPlane)
3040d16fef4Smrg{
3050d16fef4Smrg	ScrnInfoPtr scrn = xf86ScreenToScrn(pDst->pScreen);
3060d16fef4Smrg	PixmapPtr dst_pix = get_drawable_pixmap(pDst);
3070d16fef4Smrg	struct radeon_pixmap *dst_priv = radeon_get_pixmap_private(dst_pix);
3080d16fef4Smrg	RegionPtr ret = NULL;
3090d16fef4Smrg
3100d16fef4Smrg	if (radeon_glamor_prepare_access_cpu_rw(scrn, dst_pix, dst_priv)) {
3110d16fef4Smrg		PixmapPtr src_pix = get_drawable_pixmap(pSrc);
3120d16fef4Smrg		struct radeon_pixmap *src_priv = radeon_get_pixmap_private(src_pix);
3130d16fef4Smrg		if (radeon_glamor_prepare_access_cpu_ro(scrn, src_pix, src_priv)) {
3140d16fef4Smrg			ret =
3150d16fef4Smrg			    fbCopyPlane(pSrc, pDst, pGC, srcx, srcy, w, h, dstx,
3160d16fef4Smrg					dsty, bitPlane);
3170d16fef4Smrg			radeon_glamor_finish_access_cpu(src_pix);
3180d16fef4Smrg		}
3190d16fef4Smrg		radeon_glamor_finish_access_cpu(dst_pix);
3200d16fef4Smrg	}
3210d16fef4Smrg	return ret;
3220d16fef4Smrg}
3230d16fef4Smrg
3240d16fef4Smrgstatic RegionPtr
3250d16fef4Smrgradeon_glamor_copy_plane_nodstbo(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
3260d16fef4Smrg				 int srcx, int srcy, int w, int h,
3270d16fef4Smrg				 int dstx, int dsty, unsigned long bitPlane)
3280d16fef4Smrg{
3290d16fef4Smrg	ScrnInfoPtr scrn = xf86ScreenToScrn(pDst->pScreen);
3300d16fef4Smrg	PixmapPtr src_pix = get_drawable_pixmap(pSrc);
3310d16fef4Smrg	struct radeon_pixmap *src_priv = radeon_get_pixmap_private(src_pix);
3320d16fef4Smrg	RegionPtr ret = NULL;
3330d16fef4Smrg
3340d16fef4Smrg	if (radeon_glamor_prepare_access_cpu_ro(scrn, src_pix, src_priv)) {
3350d16fef4Smrg		ret = fbCopyPlane(pSrc, pDst, pGC, srcx, srcy, w, h,
3360d16fef4Smrg				  dstx,	dsty, bitPlane);
3370d16fef4Smrg		radeon_glamor_finish_access_cpu(src_pix);
3380d16fef4Smrg	}
3390d16fef4Smrg	return ret;
3400d16fef4Smrg}
3410d16fef4Smrg
3420d16fef4Smrgstatic void
3430d16fef4Smrgradeon_glamor_poly_point(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt,
3440d16fef4Smrg			 DDXPointPtr pptInit)
3450d16fef4Smrg{
3460d16fef4Smrg	ScrnInfoPtr scrn = xf86ScreenToScrn(pDrawable->pScreen);
3470d16fef4Smrg	PixmapPtr pixmap = get_drawable_pixmap(pDrawable);
3480d16fef4Smrg	struct radeon_pixmap *priv = radeon_get_pixmap_private(pixmap);
3490d16fef4Smrg
3500d16fef4Smrg	if (radeon_glamor_prepare_access_cpu_rw(scrn, pixmap, priv)) {
3510d16fef4Smrg		fbPolyPoint(pDrawable, pGC, mode, npt, pptInit);
3520d16fef4Smrg		radeon_glamor_finish_access_cpu(pixmap);
3530d16fef4Smrg	}
3540d16fef4Smrg}
3550d16fef4Smrg
3560d16fef4Smrgstatic void
3570d16fef4Smrgradeon_glamor_poly_lines(DrawablePtr pDrawable, GCPtr pGC,
3580d16fef4Smrg			 int mode, int npt, DDXPointPtr ppt)
3590d16fef4Smrg{
3600d16fef4Smrg	if (pGC->lineWidth == 0) {
3610d16fef4Smrg		ScrnInfoPtr scrn = xf86ScreenToScrn(pDrawable->pScreen);
3620d16fef4Smrg		PixmapPtr pixmap = get_drawable_pixmap(pDrawable);
3630d16fef4Smrg		struct radeon_pixmap *priv = radeon_get_pixmap_private(pixmap);
3640d16fef4Smrg
3650d16fef4Smrg		if (radeon_glamor_prepare_access_cpu_rw(scrn, pixmap, priv)) {
3660d16fef4Smrg			if (radeon_glamor_prepare_access_gc(scrn, pGC)) {
3670d16fef4Smrg				fbPolyLine(pDrawable, pGC, mode, npt, ppt);
3680d16fef4Smrg				radeon_glamor_finish_access_gc(pGC);
3690d16fef4Smrg			}
3700d16fef4Smrg			radeon_glamor_finish_access_cpu(pixmap);
3710d16fef4Smrg		}
3720d16fef4Smrg		return;
3730d16fef4Smrg	}
3740d16fef4Smrg	/* fb calls mi functions in the lineWidth != 0 case. */
3750d16fef4Smrg	fbPolyLine(pDrawable, pGC, mode, npt, ppt);
3760d16fef4Smrg}
3770d16fef4Smrg
3780d16fef4Smrgstatic void
3790d16fef4Smrgradeon_glamor_poly_segment(DrawablePtr pDrawable, GCPtr pGC,
3800d16fef4Smrg			   int nsegInit, xSegment *pSegInit)
3810d16fef4Smrg{
3820d16fef4Smrg	if (pGC->lineWidth == 0) {
3830d16fef4Smrg		ScrnInfoPtr scrn = xf86ScreenToScrn(pDrawable->pScreen);
3840d16fef4Smrg		PixmapPtr pixmap = get_drawable_pixmap(pDrawable);
3850d16fef4Smrg		struct radeon_pixmap *priv = radeon_get_pixmap_private(pixmap);
3860d16fef4Smrg
3870d16fef4Smrg		if (radeon_glamor_prepare_access_cpu_rw(scrn, pixmap, priv)) {
3880d16fef4Smrg			if (radeon_glamor_prepare_access_gc(scrn, pGC)) {
3890d16fef4Smrg				fbPolySegment(pDrawable, pGC, nsegInit,
3900d16fef4Smrg					      pSegInit);
3910d16fef4Smrg				radeon_glamor_finish_access_gc(pGC);
3920d16fef4Smrg			}
3930d16fef4Smrg			radeon_glamor_finish_access_cpu(pixmap);
3940d16fef4Smrg		}
3950d16fef4Smrg		return;
3960d16fef4Smrg	}
3970d16fef4Smrg	/* fb calls mi functions in the lineWidth != 0 case. */
3980d16fef4Smrg	fbPolySegment(pDrawable, pGC, nsegInit, pSegInit);
3990d16fef4Smrg}
4000d16fef4Smrg
4010d16fef4Smrgstatic void
4020d16fef4Smrgradeon_glamor_poly_fill_rect(DrawablePtr pDrawable, GCPtr pGC,
4030d16fef4Smrg			     int nrect, xRectangle *prect)
4040d16fef4Smrg{
4050d16fef4Smrg	ScrnInfoPtr scrn = xf86ScreenToScrn(pDrawable->pScreen);
4060d16fef4Smrg	RADEONInfoPtr info = RADEONPTR(scrn);
4070d16fef4Smrg	PixmapPtr pixmap = get_drawable_pixmap(pDrawable);
4080d16fef4Smrg	struct radeon_pixmap *priv = radeon_get_pixmap_private(pixmap);
4090d16fef4Smrg
4100d16fef4Smrg	if ((info->accel_state->force || (priv && !priv->bo)) &&
4110d16fef4Smrg	    radeon_glamor_prepare_access_gpu(priv)) {
4120d16fef4Smrg		info->glamor.SavedPolyFillRect(pDrawable, pGC, nrect, prect);
4130d16fef4Smrg		radeon_glamor_finish_access_gpu_rw(info, priv);
4140d16fef4Smrg		return;
4150d16fef4Smrg	}
4160d16fef4Smrg
4170d16fef4Smrg	if (radeon_glamor_prepare_access_cpu_rw(scrn, pixmap, priv)) {
4180d16fef4Smrg		if (radeon_glamor_prepare_access_gc(scrn, pGC)) {
4190d16fef4Smrg			fbPolyFillRect(pDrawable, pGC, nrect, prect);
4200d16fef4Smrg			radeon_glamor_finish_access_gc(pGC);
4210d16fef4Smrg		}
4220d16fef4Smrg		radeon_glamor_finish_access_cpu(pixmap);
4230d16fef4Smrg	}
4240d16fef4Smrg}
4250d16fef4Smrg
4260d16fef4Smrgstatic void
4270d16fef4Smrgradeon_glamor_image_glyph_blt(DrawablePtr pDrawable, GCPtr pGC,
4280d16fef4Smrg			      int x, int y, unsigned int nglyph,
4290d16fef4Smrg			      CharInfoPtr *ppci, pointer pglyphBase)
4300d16fef4Smrg{
4310d16fef4Smrg	ScrnInfoPtr scrn = xf86ScreenToScrn(pDrawable->pScreen);
4320d16fef4Smrg	PixmapPtr pixmap = get_drawable_pixmap(pDrawable);
4330d16fef4Smrg	struct radeon_pixmap *priv = radeon_get_pixmap_private(pixmap);
4340d16fef4Smrg
4350d16fef4Smrg	if (radeon_glamor_prepare_access_cpu_rw(scrn, pixmap, priv)) {
4360d16fef4Smrg		if (radeon_glamor_prepare_access_gc(scrn, pGC)) {
4370d16fef4Smrg			fbImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci,
4380d16fef4Smrg					pglyphBase);
4390d16fef4Smrg			radeon_glamor_finish_access_gc(pGC);
4400d16fef4Smrg		}
4410d16fef4Smrg		radeon_glamor_finish_access_cpu(pixmap);
4420d16fef4Smrg	}
4430d16fef4Smrg}
4440d16fef4Smrg
4450d16fef4Smrgstatic void
4460d16fef4Smrgradeon_glamor_poly_glyph_blt(DrawablePtr pDrawable, GCPtr pGC,
4470d16fef4Smrg			     int x, int y, unsigned int nglyph,
4480d16fef4Smrg			     CharInfoPtr *ppci, pointer pglyphBase)
4490d16fef4Smrg{
4500d16fef4Smrg	ScrnInfoPtr scrn = xf86ScreenToScrn(pDrawable->pScreen);
4510d16fef4Smrg	PixmapPtr pixmap = get_drawable_pixmap(pDrawable);
4520d16fef4Smrg	struct radeon_pixmap *priv = radeon_get_pixmap_private(pixmap);
4530d16fef4Smrg
4540d16fef4Smrg	if (radeon_glamor_prepare_access_cpu_rw(scrn, pixmap, priv)) {
4550d16fef4Smrg		if (radeon_glamor_prepare_access_gc(scrn, pGC)) {
4560d16fef4Smrg			fbPolyGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci,
4570d16fef4Smrg				       pglyphBase);
4580d16fef4Smrg			radeon_glamor_finish_access_gc(pGC);
4590d16fef4Smrg		}
4600d16fef4Smrg		radeon_glamor_finish_access_cpu(pixmap);
4610d16fef4Smrg	}
4620d16fef4Smrg}
4630d16fef4Smrg
4640d16fef4Smrgstatic void
4650d16fef4Smrgradeon_glamor_push_pixels(GCPtr pGC, PixmapPtr pBitmap,
4660d16fef4Smrg			  DrawablePtr pDrawable, int w, int h, int x, int y)
4670d16fef4Smrg{
4680d16fef4Smrg	ScrnInfoPtr scrn = xf86ScreenToScrn(pDrawable->pScreen);
4690d16fef4Smrg	PixmapPtr pixmap = get_drawable_pixmap(pDrawable);
4700d16fef4Smrg	struct radeon_pixmap *priv = radeon_get_pixmap_private(pixmap);
4710d16fef4Smrg
4720d16fef4Smrg	if (radeon_glamor_prepare_access_cpu_rw(scrn, pixmap, priv)) {
4730d16fef4Smrg		priv = radeon_get_pixmap_private(pBitmap);
4740d16fef4Smrg		if (radeon_glamor_prepare_access_cpu_ro(scrn, pBitmap, priv)) {
4750d16fef4Smrg			if (radeon_glamor_prepare_access_gc(scrn, pGC)) {
4760d16fef4Smrg				fbPushPixels(pGC, pBitmap, pDrawable, w, h, x,
4770d16fef4Smrg					     y);
4780d16fef4Smrg				radeon_glamor_finish_access_gc(pGC);
4790d16fef4Smrg			}
4800d16fef4Smrg			radeon_glamor_finish_access_cpu(pBitmap);
4810d16fef4Smrg		}
4820d16fef4Smrg		radeon_glamor_finish_access_cpu(pixmap);
4830d16fef4Smrg	}
4840d16fef4Smrg}
4850d16fef4Smrg
4860d16fef4Smrgstatic void
4870d16fef4Smrgradeon_glamor_push_pixels_nodstbo(GCPtr pGC, PixmapPtr pBitmap,
4880d16fef4Smrg				  DrawablePtr pDrawable, int w, int h,
4890d16fef4Smrg				  int x, int y)
4900d16fef4Smrg{
4910d16fef4Smrg	ScrnInfoPtr scrn = xf86ScreenToScrn(pDrawable->pScreen);
4920d16fef4Smrg	struct radeon_pixmap *priv = radeon_get_pixmap_private(pBitmap);
4930d16fef4Smrg
4940d16fef4Smrg	if (radeon_glamor_prepare_access_cpu_ro(scrn, pBitmap, priv)) {
4950d16fef4Smrg		fbPushPixels(pGC, pBitmap, pDrawable, w, h, x, y);
4960d16fef4Smrg		radeon_glamor_finish_access_cpu(pBitmap);
4970d16fef4Smrg	}
4980d16fef4Smrg}
4990d16fef4Smrg
5000d16fef4Smrgstatic RegionPtr
5010d16fef4Smrgradeon_glamor_copy_area(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable,
5020d16fef4Smrg			GCPtr pGC, int srcx, int srcy, int width, int height,
5030d16fef4Smrg			int dstx, int dsty)
5040d16fef4Smrg{
5050d16fef4Smrg	ScreenPtr screen = pDstDrawable->pScreen;
5060d16fef4Smrg	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
5070d16fef4Smrg	RADEONInfoPtr info = RADEONPTR(scrn);
5080d16fef4Smrg	PixmapPtr src_pixmap = get_drawable_pixmap(pSrcDrawable);
5090d16fef4Smrg	PixmapPtr dst_pixmap = get_drawable_pixmap(pDstDrawable);
5100d16fef4Smrg	struct radeon_pixmap *src_priv = radeon_get_pixmap_private(src_pixmap);
5110d16fef4Smrg	struct radeon_pixmap *dst_priv = radeon_get_pixmap_private(dst_pixmap);
5120d16fef4Smrg	RegionPtr ret = NULL;
5130d16fef4Smrg
5140d16fef4Smrg	if (info->accel_state->force || (src_priv && !src_priv->bo) ||
5150d16fef4Smrg	    (dst_priv && !dst_priv->bo)) {
5160d16fef4Smrg		if (!radeon_glamor_prepare_access_gpu(dst_priv))
5170d16fef4Smrg			goto fallback;
5180d16fef4Smrg		if (src_priv != dst_priv &&
5190d16fef4Smrg		    !radeon_glamor_prepare_access_gpu(src_priv))
5200d16fef4Smrg			goto fallback;
5210d16fef4Smrg
5220d16fef4Smrg		ret = info->glamor.SavedCopyArea(pSrcDrawable, pDstDrawable,
5230d16fef4Smrg						 pGC, srcx, srcy,
5240d16fef4Smrg						 width, height, dstx, dsty);
5250d16fef4Smrg		radeon_glamor_finish_access_gpu_rw(info, dst_priv);
5260d16fef4Smrg		if (src_priv != dst_priv)
5270d16fef4Smrg			radeon_glamor_finish_access_gpu_ro(info, src_priv);
5280d16fef4Smrg
5290d16fef4Smrg		return ret;
5300d16fef4Smrg	}
5310d16fef4Smrg
5320d16fef4Smrgfallback:
5330d16fef4Smrg	if (radeon_glamor_prepare_access_cpu_rw(scrn, dst_pixmap, dst_priv)) {
5340d16fef4Smrg		if (pSrcDrawable == pDstDrawable ||
5350d16fef4Smrg			radeon_glamor_prepare_access_cpu_ro(scrn, src_pixmap,
5360d16fef4Smrg							    src_priv)) {
5370d16fef4Smrg			ret = fbCopyArea(pSrcDrawable, pDstDrawable, pGC,
5380d16fef4Smrg					 srcx, srcy, width, height, dstx, dsty);
5390d16fef4Smrg			if (pSrcDrawable != pDstDrawable)
5400d16fef4Smrg				radeon_glamor_finish_access_cpu(src_pixmap);
5410d16fef4Smrg		}
5420d16fef4Smrg		radeon_glamor_finish_access_cpu(dst_pixmap);
5430d16fef4Smrg	}
5440d16fef4Smrg
5450d16fef4Smrg	return ret;
5460d16fef4Smrg}
5470d16fef4Smrg
5480d16fef4Smrgstatic RegionPtr
5490d16fef4Smrgradeon_glamor_copy_area_nodstbo(DrawablePtr pSrcDrawable,
5500d16fef4Smrg				DrawablePtr pDstDrawable, GCPtr pGC,
5510d16fef4Smrg				int srcx, int srcy, int width, int height,
5520d16fef4Smrg				int dstx, int dsty)
5530d16fef4Smrg{
5540d16fef4Smrg	ScreenPtr screen = pDstDrawable->pScreen;
5550d16fef4Smrg	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
5560d16fef4Smrg	PixmapPtr src_pixmap = get_drawable_pixmap(pSrcDrawable);
5570d16fef4Smrg	PixmapPtr dst_pixmap = get_drawable_pixmap(pDstDrawable);
5580d16fef4Smrg	struct radeon_pixmap *src_priv;
5590d16fef4Smrg	RegionPtr ret = NULL;
5600d16fef4Smrg
5610d16fef4Smrg	if (src_pixmap != dst_pixmap) {
5620d16fef4Smrg		src_priv = radeon_get_pixmap_private(src_pixmap);
5630d16fef4Smrg
5640d16fef4Smrg		if (!radeon_glamor_prepare_access_cpu_ro(scrn, src_pixmap,
5650d16fef4Smrg							 src_priv))
5660d16fef4Smrg			return ret;
5670d16fef4Smrg	}
5680d16fef4Smrg
5690d16fef4Smrg	ret = fbCopyArea(pSrcDrawable, pDstDrawable, pGC, srcx, srcy,
5700d16fef4Smrg			 width, height, dstx, dsty);
5710d16fef4Smrg
5720d16fef4Smrg	if (src_pixmap != dst_pixmap)
5730d16fef4Smrg		radeon_glamor_finish_access_cpu(src_pixmap);
5740d16fef4Smrg
5750d16fef4Smrg	return ret;
5760d16fef4Smrg}
5770d16fef4Smrg
5780d16fef4Smrgstatic const GCOps radeon_glamor_ops = {
5790d16fef4Smrg	radeon_glamor_fill_spans,
5800d16fef4Smrg	radeon_glamor_set_spans,
5810d16fef4Smrg	radeon_glamor_put_image,
5820d16fef4Smrg	radeon_glamor_copy_area,
5830d16fef4Smrg	radeon_glamor_copy_plane,
5840d16fef4Smrg	radeon_glamor_poly_point,
5850d16fef4Smrg	radeon_glamor_poly_lines,
5860d16fef4Smrg	radeon_glamor_poly_segment,
5870d16fef4Smrg	miPolyRectangle,
5880d16fef4Smrg	miPolyArc,
5890d16fef4Smrg	miFillPolygon,
5900d16fef4Smrg	radeon_glamor_poly_fill_rect,
5910d16fef4Smrg	miPolyFillArc,
5920d16fef4Smrg	miPolyText8,
5930d16fef4Smrg	miPolyText16,
5940d16fef4Smrg	miImageText8,
5950d16fef4Smrg	miImageText16,
5960d16fef4Smrg	radeon_glamor_image_glyph_blt,
5970d16fef4Smrg	radeon_glamor_poly_glyph_blt,
5980d16fef4Smrg	radeon_glamor_push_pixels,
5990d16fef4Smrg};
6000d16fef4Smrg
6010d16fef4Smrgstatic GCOps radeon_glamor_nodstbo_ops;
6020d16fef4Smrg
6030d16fef4Smrg/**
6040d16fef4Smrg * radeon_glamor_validate_gc() sets the ops to our implementations, which may be
6050d16fef4Smrg * accelerated or may sync the card and fall back to fb.
6060d16fef4Smrg */
6070d16fef4Smrgstatic void
6080d16fef4Smrgradeon_glamor_validate_gc(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable)
6090d16fef4Smrg{
6100d16fef4Smrg	ScrnInfoPtr scrn = xf86ScreenToScrn(pGC->pScreen);
6110d16fef4Smrg	RADEONInfoPtr info = RADEONPTR(scrn);
6120d16fef4Smrg
6130d16fef4Smrg	glamor_validate_gc(pGC, changes, pDrawable);
6140d16fef4Smrg	info->glamor.SavedCopyArea = pGC->ops->CopyArea;
6150d16fef4Smrg	info->glamor.SavedPolyFillRect = pGC->ops->PolyFillRect;
6160d16fef4Smrg
6170d16fef4Smrg	if (radeon_get_pixmap_private(get_drawable_pixmap(pDrawable)) ||
6180d16fef4Smrg	    (pGC->stipple && radeon_get_pixmap_private(pGC->stipple)) ||
6190d16fef4Smrg	    (pGC->fillStyle == FillTiled &&
6200d16fef4Smrg	     radeon_get_pixmap_private(pGC->tile.pixmap)))
6210d16fef4Smrg		pGC->ops = (GCOps *)&radeon_glamor_ops;
6220d16fef4Smrg	else
6230d16fef4Smrg		pGC->ops = &radeon_glamor_nodstbo_ops;
6240d16fef4Smrg}
6250d16fef4Smrg
6260d16fef4Smrgstatic GCFuncs glamorGCFuncs = {
6270d16fef4Smrg	radeon_glamor_validate_gc,
6280d16fef4Smrg	miChangeGC,
6290d16fef4Smrg	miCopyGC,
6300d16fef4Smrg	miDestroyGC,
6310d16fef4Smrg	miChangeClip,
6320d16fef4Smrg	miDestroyClip,
6330d16fef4Smrg	miCopyClip
6340d16fef4Smrg};
6350d16fef4Smrg
6360d16fef4Smrg/**
6370d16fef4Smrg * radeon_glamor_create_gc makes a new GC and hooks up its funcs handler, so that
6380d16fef4Smrg * radeon_glamor_validate_gc() will get called.
6390d16fef4Smrg */
6400d16fef4Smrgstatic int
6410d16fef4Smrgradeon_glamor_create_gc(GCPtr pGC)
6420d16fef4Smrg{
6430d16fef4Smrg	static Bool nodstbo_ops_initialized;
6440d16fef4Smrg
6450d16fef4Smrg	if (!fbCreateGC(pGC))
6460d16fef4Smrg		return FALSE;
6470d16fef4Smrg
6480d16fef4Smrg	if (!nodstbo_ops_initialized) {
6490d16fef4Smrg		radeon_glamor_nodstbo_ops = radeon_glamor_ops;
6500d16fef4Smrg
6510d16fef4Smrg		radeon_glamor_nodstbo_ops.FillSpans = pGC->ops->FillSpans;
6520d16fef4Smrg		radeon_glamor_nodstbo_ops.SetSpans = pGC->ops->SetSpans;
6530d16fef4Smrg		radeon_glamor_nodstbo_ops.PutImage = pGC->ops->PutImage;
6540d16fef4Smrg		radeon_glamor_nodstbo_ops.CopyArea = radeon_glamor_copy_area_nodstbo;
6550d16fef4Smrg		radeon_glamor_nodstbo_ops.CopyPlane = radeon_glamor_copy_plane_nodstbo;
6560d16fef4Smrg		radeon_glamor_nodstbo_ops.PolyPoint = pGC->ops->PolyPoint;
6570d16fef4Smrg		radeon_glamor_nodstbo_ops.Polylines = pGC->ops->Polylines;
6580d16fef4Smrg		radeon_glamor_nodstbo_ops.PolySegment = pGC->ops->PolySegment;
6590d16fef4Smrg		radeon_glamor_nodstbo_ops.PolyFillRect = pGC->ops->PolyFillRect;
6600d16fef4Smrg		radeon_glamor_nodstbo_ops.ImageGlyphBlt = pGC->ops->ImageGlyphBlt;
6610d16fef4Smrg		radeon_glamor_nodstbo_ops.PolyGlyphBlt = pGC->ops->PolyGlyphBlt;
6620d16fef4Smrg		radeon_glamor_nodstbo_ops.PushPixels = radeon_glamor_push_pixels_nodstbo;
6630d16fef4Smrg
6640d16fef4Smrg		nodstbo_ops_initialized = TRUE;
6650d16fef4Smrg	}
6660d16fef4Smrg
6670d16fef4Smrg	pGC->funcs = &glamorGCFuncs;
6680d16fef4Smrg
6690d16fef4Smrg	return TRUE;
6700d16fef4Smrg}
6710d16fef4Smrg
6720d16fef4Smrg/*
6730d16fef4Smrg * Screen rendering wrappers
6740d16fef4Smrg */
6750d16fef4Smrg
6760d16fef4Smrgstatic RegionPtr
6770d16fef4Smrgradeon_glamor_bitmap_to_region(PixmapPtr pPix)
6780d16fef4Smrg{
6790d16fef4Smrg	ScrnInfoPtr scrn = xf86ScreenToScrn(pPix->drawable.pScreen);
6800d16fef4Smrg	struct radeon_pixmap *priv = radeon_get_pixmap_private(pPix);
6810d16fef4Smrg	RegionPtr ret;
6820d16fef4Smrg
6830d16fef4Smrg	if (!radeon_glamor_prepare_access_cpu_ro(scrn, pPix, priv))
6840d16fef4Smrg		return NULL;
6850d16fef4Smrg	ret = fbPixmapToRegion(pPix);
6860d16fef4Smrg	radeon_glamor_finish_access_cpu(pPix);
6870d16fef4Smrg	return ret;
6880d16fef4Smrg}
6890d16fef4Smrg
6900d16fef4Smrgstatic void
6910d16fef4Smrgradeon_glamor_copy_window(WindowPtr pWin, DDXPointRec ptOldOrg,
6920d16fef4Smrg			  RegionPtr prgnSrc)
6930d16fef4Smrg{
6940d16fef4Smrg	ScrnInfoPtr scrn = xf86ScreenToScrn(pWin->drawable.pScreen);
6950d16fef4Smrg	PixmapPtr pixmap = get_drawable_pixmap(&pWin->drawable);
6960d16fef4Smrg	struct radeon_pixmap *priv = radeon_get_pixmap_private(pixmap);
6970d16fef4Smrg
6980d16fef4Smrg	if (radeon_glamor_prepare_access_cpu_rw(scrn, pixmap, priv)) {
6990d16fef4Smrg		fbCopyWindow(pWin, ptOldOrg, prgnSrc);
7000d16fef4Smrg		radeon_glamor_finish_access_cpu(pixmap);
7010d16fef4Smrg	}
7020d16fef4Smrg}
7030d16fef4Smrg
7040d16fef4Smrgstatic void
7050d16fef4Smrgradeon_glamor_get_image(DrawablePtr pDrawable, int x, int y, int w, int h,
7060d16fef4Smrg			unsigned int format, unsigned long planeMask, char *d)
7070d16fef4Smrg{
7080d16fef4Smrg	ScrnInfoPtr scrn = xf86ScreenToScrn(pDrawable->pScreen);
7090d16fef4Smrg	PixmapPtr pixmap = get_drawable_pixmap(pDrawable);
7100d16fef4Smrg	struct radeon_pixmap *priv = radeon_get_pixmap_private(pixmap);
7110d16fef4Smrg
7120d16fef4Smrg	if (radeon_glamor_prepare_access_cpu_ro(scrn, pixmap, priv)) {
7130d16fef4Smrg		fbGetImage(pDrawable, x, y, w, h, format, planeMask, d);
7140d16fef4Smrg		radeon_glamor_finish_access_cpu(pixmap);
7150d16fef4Smrg	}
7160d16fef4Smrg}
7170d16fef4Smrg
7180d16fef4Smrgstatic void
7190d16fef4Smrgradeon_glamor_get_spans(DrawablePtr pDrawable, int wMax, DDXPointPtr ppt,
7200d16fef4Smrg			int *pwidth, int nspans, char *pdstStart)
7210d16fef4Smrg{
7220d16fef4Smrg	ScrnInfoPtr scrn = xf86ScreenToScrn(pDrawable->pScreen);
7230d16fef4Smrg	PixmapPtr pixmap = get_drawable_pixmap(pDrawable);
7240d16fef4Smrg	struct radeon_pixmap *priv = radeon_get_pixmap_private(pixmap);
7250d16fef4Smrg
7260d16fef4Smrg	if (radeon_glamor_prepare_access_cpu_ro(scrn, pixmap, priv)) {
7270d16fef4Smrg		fbGetSpans(pDrawable, wMax, ppt, pwidth, nspans, pdstStart);
7280d16fef4Smrg		radeon_glamor_finish_access_cpu(pixmap);
7290d16fef4Smrg	}
7300d16fef4Smrg}
7310d16fef4Smrg
7320d16fef4Smrg/*
7330d16fef4Smrg * Picture screen rendering wrappers
7340d16fef4Smrg */
7350d16fef4Smrg
7360d16fef4Smrg#ifdef RENDER
7370d16fef4Smrg
7380d16fef4Smrgstatic void
7390d16fef4Smrgradeon_glamor_composite(CARD8 op,
7400d16fef4Smrg		    PicturePtr pSrc,
7410d16fef4Smrg		    PicturePtr pMask,
7420d16fef4Smrg		    PicturePtr pDst,
7430d16fef4Smrg		    INT16 xSrc, INT16 ySrc,
7440d16fef4Smrg		    INT16 xMask, INT16 yMask,
7450d16fef4Smrg		    INT16 xDst, INT16 yDst,
7460d16fef4Smrg		    CARD16 width, CARD16 height)
7470d16fef4Smrg{
7480d16fef4Smrg	ScrnInfoPtr scrn = xf86ScreenToScrn(pDst->pDrawable->pScreen);
7490d16fef4Smrg	RADEONInfoPtr info;
7500d16fef4Smrg	PixmapPtr pixmap;
7510d16fef4Smrg	struct radeon_pixmap *dst_priv, *src_priv = NULL, *mask_priv = NULL;
7520d16fef4Smrg	Bool gpu_done = FALSE;
7530d16fef4Smrg
7540d16fef4Smrg	if (pDst->alphaMap || pSrc->alphaMap || (pMask && pMask->alphaMap))
7550d16fef4Smrg		goto fallback;
7560d16fef4Smrg
7570d16fef4Smrg	pixmap = get_drawable_pixmap(pDst->pDrawable);
7580d16fef4Smrg	if (&pixmap->drawable != pDst->pDrawable ||
7590d16fef4Smrg	    pixmap->usage_hint != RADEON_CREATE_PIXMAP_SCANOUT)
7600d16fef4Smrg		goto fallback;
7610d16fef4Smrg
7620d16fef4Smrg	dst_priv = radeon_get_pixmap_private(pixmap);
7630d16fef4Smrg	if (!radeon_glamor_prepare_access_gpu(dst_priv))
7640d16fef4Smrg		goto fallback;
7650d16fef4Smrg
7660d16fef4Smrg	info = RADEONPTR(scrn);
7670d16fef4Smrg	if (!pSrc->pDrawable ||
7680d16fef4Smrg	    ((pixmap = get_drawable_pixmap(pSrc->pDrawable)) &&
7690d16fef4Smrg	     (src_priv = radeon_get_pixmap_private(pixmap)) &&
7700d16fef4Smrg	     radeon_glamor_prepare_access_gpu(src_priv))) {
7710d16fef4Smrg		if (!pMask || !pMask->pDrawable ||
7720d16fef4Smrg		    ((pixmap = get_drawable_pixmap(pMask->pDrawable)) &&
7730d16fef4Smrg		     (mask_priv = radeon_get_pixmap_private(pixmap)) &&
7740d16fef4Smrg		     radeon_glamor_prepare_access_gpu(mask_priv))) {
7750d16fef4Smrg			info->glamor.SavedComposite(op, pSrc, pMask, pDst,
7760d16fef4Smrg						    xSrc, ySrc, xMask, yMask,
7770d16fef4Smrg						    xDst, yDst, width, height);
7780d16fef4Smrg			gpu_done = TRUE;
7790d16fef4Smrg
7800d16fef4Smrg			if (mask_priv)
7810d16fef4Smrg				radeon_glamor_finish_access_gpu_ro(info, mask_priv);
7820d16fef4Smrg		}
7830d16fef4Smrg
7840d16fef4Smrg		if (src_priv)
7850d16fef4Smrg			radeon_glamor_finish_access_gpu_ro(info, src_priv);
7860d16fef4Smrg	}
7870d16fef4Smrg	radeon_glamor_finish_access_gpu_rw(info, dst_priv);
7880d16fef4Smrg
7890d16fef4Smrg	if (gpu_done)
7900d16fef4Smrg		return;
7910d16fef4Smrg
7920d16fef4Smrgfallback:
7930d16fef4Smrg	if (radeon_glamor_picture_prepare_access_cpu_rw(scrn, pDst)) {
7940d16fef4Smrg		if (radeon_glamor_picture_prepare_access_cpu_ro(scrn, pSrc)) {
7950d16fef4Smrg			if (!pMask ||
7960d16fef4Smrg			    radeon_glamor_picture_prepare_access_cpu_ro(scrn, pMask)) {
7970d16fef4Smrg				fbComposite(op, pSrc, pMask, pDst,
7980d16fef4Smrg					    xSrc, ySrc,
7990d16fef4Smrg					    xMask, yMask,
8000d16fef4Smrg					    xDst, yDst,
8010d16fef4Smrg					    width, height);
8020d16fef4Smrg				if (pMask)
8030d16fef4Smrg					radeon_glamor_picture_finish_access_cpu(pMask);
8040d16fef4Smrg			}
8050d16fef4Smrg			radeon_glamor_picture_finish_access_cpu(pSrc);
8060d16fef4Smrg		}
8070d16fef4Smrg		radeon_glamor_picture_finish_access_cpu(pDst);
8080d16fef4Smrg	}
8090d16fef4Smrg}
8100d16fef4Smrg
8110d16fef4Smrgstatic void
8120d16fef4Smrgradeon_glamor_add_traps(PicturePtr pPicture,
8130d16fef4Smrg		    INT16 x_off, INT16 y_off, int ntrap, xTrap *traps)
8140d16fef4Smrg{
8150d16fef4Smrg	ScrnInfoPtr scrn = xf86ScreenToScrn(pPicture->pDrawable->pScreen);
8160d16fef4Smrg
8170d16fef4Smrg	if (radeon_glamor_picture_prepare_access_cpu_rw(scrn, pPicture)) {
8180d16fef4Smrg		fbAddTraps(pPicture, x_off, y_off, ntrap, traps);
8190d16fef4Smrg		radeon_glamor_picture_finish_access_cpu(pPicture);
8200d16fef4Smrg	}
8210d16fef4Smrg}
8220d16fef4Smrg
8230d16fef4Smrgstatic void
8240d16fef4Smrgradeon_glamor_glyphs(CARD8 op,
8250d16fef4Smrg		 PicturePtr src,
8260d16fef4Smrg		 PicturePtr dst,
8270d16fef4Smrg		 PictFormatPtr maskFormat,
8280d16fef4Smrg		 INT16 xSrc,
8290d16fef4Smrg		 INT16 ySrc, int nlist, GlyphListPtr list, GlyphPtr *glyphs)
8300d16fef4Smrg{
8310d16fef4Smrg	ScrnInfoPtr scrn = xf86ScreenToScrn(dst->pDrawable->pScreen);
8320d16fef4Smrg
8330d16fef4Smrg	if (radeon_glamor_picture_prepare_access_cpu_rw(scrn, dst)) {
8340d16fef4Smrg		if (radeon_glamor_picture_prepare_access_cpu_ro(scrn, src)) {
8350d16fef4Smrg			RADEONInfoPtr info = RADEONPTR(scrn);
8360d16fef4Smrg
8370d16fef4Smrg			info->glamor.SavedGlyphs(op, src, dst, maskFormat, xSrc,
8380d16fef4Smrg						 ySrc, nlist, list, glyphs);
8390d16fef4Smrg			radeon_glamor_picture_finish_access_cpu(src);
8400d16fef4Smrg		}
8410d16fef4Smrg		radeon_glamor_picture_finish_access_cpu(dst);
8420d16fef4Smrg	}
8430d16fef4Smrg}
8440d16fef4Smrg
8450d16fef4Smrgstatic void
8460d16fef4Smrgradeon_glamor_trapezoids(CARD8 op, PicturePtr src, PicturePtr dst,
8470d16fef4Smrg		     PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
8480d16fef4Smrg		     int ntrap, xTrapezoid *traps)
8490d16fef4Smrg{
8500d16fef4Smrg	ScrnInfoPtr scrn = xf86ScreenToScrn(dst->pDrawable->pScreen);
8510d16fef4Smrg
8520d16fef4Smrg	if (radeon_glamor_picture_prepare_access_cpu_rw(scrn, dst)) {
8530d16fef4Smrg		if (radeon_glamor_picture_prepare_access_cpu_ro(scrn, src)) {
8540d16fef4Smrg			RADEONInfoPtr info = RADEONPTR(scrn);
8550d16fef4Smrg
8560d16fef4Smrg			info->glamor.SavedTrapezoids(op, src, dst, maskFormat,
8570d16fef4Smrg						     xSrc, ySrc, ntrap, traps);
8580d16fef4Smrg			radeon_glamor_picture_finish_access_cpu(src);
8590d16fef4Smrg		}
8600d16fef4Smrg		radeon_glamor_picture_finish_access_cpu(dst);
8610d16fef4Smrg	}
8620d16fef4Smrg}
8630d16fef4Smrg
8640d16fef4Smrgstatic void
8650d16fef4Smrgradeon_glamor_triangles(CARD8 op, PicturePtr src, PicturePtr dst,
8660d16fef4Smrg		    PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
8670d16fef4Smrg		    int ntri, xTriangle *tri)
8680d16fef4Smrg{
8690d16fef4Smrg	ScrnInfoPtr scrn = xf86ScreenToScrn(dst->pDrawable->pScreen);
8700d16fef4Smrg
8710d16fef4Smrg	if (radeon_glamor_picture_prepare_access_cpu_rw(scrn, dst)) {
8720d16fef4Smrg		if (radeon_glamor_picture_prepare_access_cpu_ro(scrn, src)) {
8730d16fef4Smrg			RADEONInfoPtr info = RADEONPTR(scrn);
8740d16fef4Smrg
8750d16fef4Smrg			info->glamor.SavedTriangles(op, src, dst, maskFormat,
8760d16fef4Smrg						    xSrc, ySrc, ntri, tri);
8770d16fef4Smrg			radeon_glamor_picture_finish_access_cpu(src);
8780d16fef4Smrg		}
8790d16fef4Smrg		radeon_glamor_picture_finish_access_cpu(dst);
8800d16fef4Smrg	}
8810d16fef4Smrg}
8820d16fef4Smrg
8830d16fef4Smrg#endif /* RENDER */
8840d16fef4Smrg
8850d16fef4Smrg
8860d16fef4Smrg/**
8870d16fef4Smrg * radeon_glamor_close_screen() unwraps its wrapped screen functions and tears
8880d16fef4Smrg * down our screen private, before calling down to the next CloseScreen.
8890d16fef4Smrg */
8900d16fef4Smrgstatic Bool
8918bf5c682Smrgradeon_glamor_close_screen(ScreenPtr pScreen)
8920d16fef4Smrg{
8930d16fef4Smrg	RADEONInfoPtr info = RADEONPTR(xf86ScreenToScrn(pScreen));
8940d16fef4Smrg#ifdef RENDER
8950d16fef4Smrg	PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
8960d16fef4Smrg#endif
8970d16fef4Smrg
8980d16fef4Smrg	pScreen->CreateGC = info->glamor.SavedCreateGC;
8990d16fef4Smrg	pScreen->CloseScreen = info->glamor.SavedCloseScreen;
9000d16fef4Smrg	pScreen->GetImage = info->glamor.SavedGetImage;
9010d16fef4Smrg	pScreen->GetSpans = info->glamor.SavedGetSpans;
9020d16fef4Smrg	pScreen->CopyWindow = info->glamor.SavedCopyWindow;
9030d16fef4Smrg	pScreen->ChangeWindowAttributes =
9040d16fef4Smrg	    info->glamor.SavedChangeWindowAttributes;
9050d16fef4Smrg	pScreen->BitmapToRegion = info->glamor.SavedBitmapToRegion;
9060d16fef4Smrg#ifdef RENDER
9070d16fef4Smrg	if (ps) {
9080d16fef4Smrg		ps->Composite = info->glamor.SavedComposite;
9090d16fef4Smrg		ps->Glyphs = info->glamor.SavedGlyphs;
9100d16fef4Smrg		ps->UnrealizeGlyph = info->glamor.SavedUnrealizeGlyph;
9110d16fef4Smrg		ps->Trapezoids = info->glamor.SavedTrapezoids;
9120d16fef4Smrg		ps->AddTraps = info->glamor.SavedAddTraps;
9130d16fef4Smrg		ps->Triangles = info->glamor.SavedTriangles;
9140d16fef4Smrg
9150d16fef4Smrg		ps->UnrealizeGlyph = info->glamor.SavedUnrealizeGlyph;
9160d16fef4Smrg	}
9170d16fef4Smrg#endif
9180d16fef4Smrg
9198bf5c682Smrg	return pScreen->CloseScreen(pScreen);
9200d16fef4Smrg}
9210d16fef4Smrg
9220d16fef4Smrg/**
9230d16fef4Smrg * @param screen screen being initialized
9240d16fef4Smrg */
9250d16fef4Smrgvoid
9260d16fef4Smrgradeon_glamor_screen_init(ScreenPtr screen)
9270d16fef4Smrg{
9280d16fef4Smrg	RADEONInfoPtr info = RADEONPTR(xf86ScreenToScrn(screen));
9290d16fef4Smrg
9300d16fef4Smrg	/*
9310d16fef4Smrg	 * Replace various fb screen functions
9320d16fef4Smrg	 */
9330d16fef4Smrg	info->glamor.SavedCloseScreen = screen->CloseScreen;
9340d16fef4Smrg	screen->CloseScreen = radeon_glamor_close_screen;
9350d16fef4Smrg
9360d16fef4Smrg	info->glamor.SavedCreateGC = screen->CreateGC;
9370d16fef4Smrg	screen->CreateGC = radeon_glamor_create_gc;
9380d16fef4Smrg
9390d16fef4Smrg	info->glamor.SavedGetImage = screen->GetImage;
9400d16fef4Smrg	screen->GetImage = radeon_glamor_get_image;
9410d16fef4Smrg
9420d16fef4Smrg	info->glamor.SavedGetSpans = screen->GetSpans;
9430d16fef4Smrg	screen->GetSpans = radeon_glamor_get_spans;
9440d16fef4Smrg
9450d16fef4Smrg	info->glamor.SavedCopyWindow = screen->CopyWindow;
9460d16fef4Smrg	screen->CopyWindow = radeon_glamor_copy_window;
9470d16fef4Smrg
9480d16fef4Smrg	info->glamor.SavedBitmapToRegion = screen->BitmapToRegion;
9490d16fef4Smrg	screen->BitmapToRegion = radeon_glamor_bitmap_to_region;
9500d16fef4Smrg
9510d16fef4Smrg#ifdef RENDER
9520d16fef4Smrg	{
9530d16fef4Smrg		PictureScreenPtr ps = GetPictureScreenIfSet(screen);
9540d16fef4Smrg		if (ps) {
9550d16fef4Smrg			info->glamor.SavedComposite = ps->Composite;
9560d16fef4Smrg			ps->Composite = radeon_glamor_composite;
9570d16fef4Smrg
9580d16fef4Smrg			info->glamor.SavedUnrealizeGlyph = ps->UnrealizeGlyph;
9590d16fef4Smrg
9600d16fef4Smrg			ps->Glyphs = radeon_glamor_glyphs;
9610d16fef4Smrg			ps->Triangles = radeon_glamor_triangles;
9620d16fef4Smrg			ps->Trapezoids = radeon_glamor_trapezoids;
9630d16fef4Smrg
9640d16fef4Smrg			info->glamor.SavedAddTraps = ps->AddTraps;
9650d16fef4Smrg			ps->AddTraps = radeon_glamor_add_traps;
9660d16fef4Smrg		}
9670d16fef4Smrg	}
9680d16fef4Smrg#endif
9690d16fef4Smrg}
9700d16fef4Smrg
9710d16fef4Smrg#endif /* USE_GLAMOR */
972