1d6c0b56eSmrg/*
2d6c0b56eSmrg * Copyright © 2001 Keith Packard
3d6c0b56eSmrg *             2010 Intel Corporation
4d6c0b56eSmrg *             2012,2015 Advanced Micro Devices, Inc.
5d6c0b56eSmrg *
6d6c0b56eSmrg * Partly based on code Copyright © 2008 Red Hat, Inc.
7d6c0b56eSmrg * Partly based on code Copyright © 2000 SuSE, Inc.
8d6c0b56eSmrg *
9d6c0b56eSmrg * Partly based on code that is Copyright © The XFree86 Project Inc.
10d6c0b56eSmrg *
11d6c0b56eSmrg * Permission to use, copy, modify, distribute, and sell this software and its
12d6c0b56eSmrg * documentation for any purpose is hereby granted without fee, provided that
13d6c0b56eSmrg * the above copyright notice appear in all copies and that both that
14d6c0b56eSmrg * copyright notice and this permission notice appear in supporting
15d6c0b56eSmrg * documentation, and that the name of the opyright holders not be used in
16d6c0b56eSmrg * advertising or publicity pertaining to distribution of the software without
17d6c0b56eSmrg * specific, written prior permission.  The copyright holders make no
18d6c0b56eSmrg * representations about the suitability of this software for any purpose.  It
19d6c0b56eSmrg * is provided "as is" without express or implied warranty.
20d6c0b56eSmrg *
21d6c0b56eSmrg * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
22d6c0b56eSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
23d6c0b56eSmrg * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
24d6c0b56eSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
25d6c0b56eSmrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
26d6c0b56eSmrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
27d6c0b56eSmrg * PERFORMANCE OF THIS SOFTWARE.
28d6c0b56eSmrg */
29d6c0b56eSmrg
30d6c0b56eSmrg
31d6c0b56eSmrg#ifdef HAVE_CONFIG_H
32d6c0b56eSmrg#include <config.h>
33d6c0b56eSmrg#endif
34d6c0b56eSmrg
35d6c0b56eSmrg#ifdef USE_GLAMOR
36d6c0b56eSmrg
37d6c0b56eSmrg#include "amdgpu_drv.h"
38d6c0b56eSmrg#include "amdgpu_glamor.h"
39d6c0b56eSmrg#include "amdgpu_pixmap.h"
40d6c0b56eSmrg
41d6c0b56eSmrg
42d6c0b56eSmrg/* Are there any outstanding GPU operations for this pixmap? */
43d6c0b56eSmrgstatic Bool
44d6c0b56eSmrgamdgpu_glamor_gpu_pending(uint_fast32_t gpu_synced, uint_fast32_t gpu_access)
45d6c0b56eSmrg{
46d6c0b56eSmrg	return (int_fast32_t)(gpu_access - gpu_synced) > 0;
47d6c0b56eSmrg}
48d6c0b56eSmrg
49d6c0b56eSmrg/*
50d6c0b56eSmrg * Pixmap CPU access wrappers
51d6c0b56eSmrg */
52d6c0b56eSmrg
53d6c0b56eSmrgstatic Bool
54d6c0b56eSmrgamdgpu_glamor_prepare_access_cpu(ScrnInfoPtr scrn, AMDGPUInfoPtr info,
55d6c0b56eSmrg				 PixmapPtr pixmap, struct amdgpu_pixmap *priv,
56d6c0b56eSmrg				 Bool need_sync)
57d6c0b56eSmrg{
58d6c0b56eSmrg	struct amdgpu_buffer *bo = priv->bo;
59d6c0b56eSmrg	int ret;
60d6c0b56eSmrg
61d6c0b56eSmrg	/* When falling back to swrast, flush all pending operations */
62d6c0b56eSmrg	if (need_sync)
63d6c0b56eSmrg		amdgpu_glamor_flush(scrn);
64d6c0b56eSmrg
65d6c0b56eSmrg	if (!pixmap->devPrivate.ptr) {
66d6c0b56eSmrg		ret = amdgpu_bo_map(scrn, bo);
67d6c0b56eSmrg		if (ret) {
68d6c0b56eSmrg			xf86DrvMsg(scrn->scrnIndex, X_WARNING,
69d6c0b56eSmrg				   "%s: bo map failed: %s\n", __FUNCTION__,
70d6c0b56eSmrg				   strerror(-ret));
71d6c0b56eSmrg			return FALSE;
72d6c0b56eSmrg		}
73d6c0b56eSmrg
74d6c0b56eSmrg		pixmap->devPrivate.ptr = bo->cpu_ptr;
75d6c0b56eSmrg		info->gpu_synced = info->gpu_flushed;
76d6c0b56eSmrg	} else if (need_sync) {
77d6c0b56eSmrg		char pixel[4];
78d6c0b56eSmrg
79d6c0b56eSmrg		info->glamor.SavedGetImage(&pixmap->drawable, 0, 0, 1, 1,
80d6c0b56eSmrg					   ZPixmap, ~0, pixel);
81d6c0b56eSmrg		info->gpu_synced = info->gpu_flushed;
82d6c0b56eSmrg	}
83d6c0b56eSmrg
84d6c0b56eSmrg	return TRUE;
85d6c0b56eSmrg}
86d6c0b56eSmrg
87d6c0b56eSmrgstatic Bool
88d6c0b56eSmrgamdgpu_glamor_prepare_access_cpu_ro(ScrnInfoPtr scrn, PixmapPtr pixmap,
89d6c0b56eSmrg				    struct amdgpu_pixmap *priv)
90d6c0b56eSmrg{
91d6c0b56eSmrg	AMDGPUInfoPtr info;
92d6c0b56eSmrg	Bool need_sync;
93d6c0b56eSmrg
94d6c0b56eSmrg	if (!priv)
95d6c0b56eSmrg		return TRUE;
96d6c0b56eSmrg
97d6c0b56eSmrg	info = AMDGPUPTR(scrn);
98d6c0b56eSmrg	need_sync = amdgpu_glamor_gpu_pending(info->gpu_synced, priv->gpu_write);
99d6c0b56eSmrg	return amdgpu_glamor_prepare_access_cpu(scrn, AMDGPUPTR(scrn), pixmap,
100d6c0b56eSmrg						priv, need_sync);
101d6c0b56eSmrg}
102d6c0b56eSmrg
103d6c0b56eSmrgstatic Bool
104d6c0b56eSmrgamdgpu_glamor_prepare_access_cpu_rw(ScrnInfoPtr scrn, PixmapPtr pixmap,
105d6c0b56eSmrg				    struct amdgpu_pixmap *priv)
106d6c0b56eSmrg{
107d6c0b56eSmrg	AMDGPUInfoPtr info;
108d6c0b56eSmrg	uint_fast32_t gpu_synced;
109d6c0b56eSmrg	Bool need_sync;
110d6c0b56eSmrg
111d6c0b56eSmrg	if (!priv)
112d6c0b56eSmrg		return TRUE;
113d6c0b56eSmrg
114d6c0b56eSmrg	info = AMDGPUPTR(scrn);
115d6c0b56eSmrg	gpu_synced = info->gpu_synced;
116d6c0b56eSmrg	need_sync = amdgpu_glamor_gpu_pending(gpu_synced, priv->gpu_write) |
117d6c0b56eSmrg		amdgpu_glamor_gpu_pending(gpu_synced, priv->gpu_read);
118d6c0b56eSmrg	return amdgpu_glamor_prepare_access_cpu(scrn, info, pixmap, priv,
119d6c0b56eSmrg						need_sync);
120d6c0b56eSmrg}
121d6c0b56eSmrg
122d6c0b56eSmrgstatic void
123d6c0b56eSmrgamdgpu_glamor_finish_access_cpu(PixmapPtr pixmap)
124d6c0b56eSmrg{
125d6c0b56eSmrg	/* Nothing to do */
126d6c0b56eSmrg}
127d6c0b56eSmrg
128d6c0b56eSmrg/*
129d6c0b56eSmrg * Pixmap GPU access wrappers
130d6c0b56eSmrg */
131d6c0b56eSmrg
132d6c0b56eSmrgstatic Bool
133d6c0b56eSmrgamdgpu_glamor_use_gpu(PixmapPtr pixmap, struct amdgpu_pixmap *priv)
134d6c0b56eSmrg{
135d6c0b56eSmrg	return (pixmap->usage_hint &
136d6c0b56eSmrg		(AMDGPU_CREATE_PIXMAP_SCANOUT | AMDGPU_CREATE_PIXMAP_DRI2)) != 0 ||
137d6c0b56eSmrg		(priv && !priv->bo);
138d6c0b56eSmrg}
139d6c0b56eSmrg
140d6c0b56eSmrgstatic Bool
141d6c0b56eSmrgamdgpu_glamor_prepare_access_gpu(struct amdgpu_pixmap *priv)
142d6c0b56eSmrg{
143d6c0b56eSmrg	return priv != NULL;
144d6c0b56eSmrg}
145d6c0b56eSmrg
146d6c0b56eSmrgstatic void
147d6c0b56eSmrgamdgpu_glamor_finish_access_gpu_ro(AMDGPUInfoPtr info,
148d6c0b56eSmrg				   struct amdgpu_pixmap *priv)
149d6c0b56eSmrg{
150d6c0b56eSmrg	priv->gpu_read = info->gpu_flushed + 1;
151d6c0b56eSmrg}
152d6c0b56eSmrg
153d6c0b56eSmrgstatic void
154d6c0b56eSmrgamdgpu_glamor_finish_access_gpu_rw(AMDGPUInfoPtr info,
155d6c0b56eSmrg				   struct amdgpu_pixmap *priv)
156d6c0b56eSmrg{
157d6c0b56eSmrg	priv->gpu_write = priv->gpu_read = info->gpu_flushed + 1;
158d6c0b56eSmrg}
159d6c0b56eSmrg
160d6c0b56eSmrg/*
161d6c0b56eSmrg * GC CPU access wrappers
162d6c0b56eSmrg */
163d6c0b56eSmrg
164d6c0b56eSmrgstatic Bool
165d6c0b56eSmrgamdgpu_glamor_prepare_access_gc(ScrnInfoPtr scrn, GCPtr pGC)
166d6c0b56eSmrg{
167d6c0b56eSmrg	struct amdgpu_pixmap *priv;
168d6c0b56eSmrg
169d6c0b56eSmrg	if (pGC->stipple) {
170d6c0b56eSmrg		priv = amdgpu_get_pixmap_private(pGC->stipple);
171d6c0b56eSmrg		if (!amdgpu_glamor_prepare_access_cpu_ro(scrn, pGC->stipple, priv))
172d6c0b56eSmrg			return FALSE;
173d6c0b56eSmrg	}
174d6c0b56eSmrg	if (pGC->fillStyle == FillTiled) {
175d6c0b56eSmrg		priv = amdgpu_get_pixmap_private(pGC->tile.pixmap);
176d6c0b56eSmrg		if (!amdgpu_glamor_prepare_access_cpu_ro(scrn, pGC->tile.pixmap,
177d6c0b56eSmrg						      priv)) {
178d6c0b56eSmrg			if (pGC->stipple)
179d6c0b56eSmrg				amdgpu_glamor_finish_access_cpu(pGC->stipple);
180d6c0b56eSmrg			return FALSE;
181d6c0b56eSmrg		}
182d6c0b56eSmrg	}
183d6c0b56eSmrg	return TRUE;
184d6c0b56eSmrg}
185d6c0b56eSmrg
186d6c0b56eSmrgstatic void
187d6c0b56eSmrgamdgpu_glamor_finish_access_gc(GCPtr pGC)
188d6c0b56eSmrg{
189d6c0b56eSmrg	if (pGC->fillStyle == FillTiled)
190d6c0b56eSmrg		amdgpu_glamor_finish_access_cpu(pGC->tile.pixmap);
191d6c0b56eSmrg	if (pGC->stipple)
192d6c0b56eSmrg		amdgpu_glamor_finish_access_cpu(pGC->stipple);
193d6c0b56eSmrg}
194d6c0b56eSmrg
195d6c0b56eSmrg/*
196d6c0b56eSmrg * Picture CPU access wrappers
197d6c0b56eSmrg */
198d6c0b56eSmrg
199d6c0b56eSmrgstatic void
200d6c0b56eSmrgamdgpu_glamor_picture_finish_access_cpu(PicturePtr picture)
201d6c0b56eSmrg{
202d6c0b56eSmrg	/* Nothing to do */
203d6c0b56eSmrg}
204d6c0b56eSmrg
205d6c0b56eSmrgstatic Bool
206d6c0b56eSmrgamdgpu_glamor_picture_prepare_access_cpu_ro(ScrnInfoPtr scrn,
207d6c0b56eSmrg					    PicturePtr picture)
208d6c0b56eSmrg{
209d6c0b56eSmrg	PixmapPtr pixmap;
210d6c0b56eSmrg	struct amdgpu_pixmap *priv;
211d6c0b56eSmrg
21235d5b7c7Smrg	if (!picture->pDrawable)
213d6c0b56eSmrg		return TRUE;
214d6c0b56eSmrg
215d6c0b56eSmrg	pixmap = get_drawable_pixmap(picture->pDrawable);
216d6c0b56eSmrg	priv = amdgpu_get_pixmap_private(pixmap);
217d6c0b56eSmrg	if (!amdgpu_glamor_prepare_access_cpu_ro(scrn, pixmap, priv))
218d6c0b56eSmrg		return FALSE;
219d6c0b56eSmrg
220d6c0b56eSmrg	if (picture->alphaMap) {
221d6c0b56eSmrg		pixmap = get_drawable_pixmap(picture->alphaMap->pDrawable);
222d6c0b56eSmrg		priv = amdgpu_get_pixmap_private(pixmap);
223d6c0b56eSmrg		if (!amdgpu_glamor_prepare_access_cpu_ro(scrn, pixmap, priv)) {
224d6c0b56eSmrg			amdgpu_glamor_picture_finish_access_cpu(picture);
225d6c0b56eSmrg			return FALSE;
226d6c0b56eSmrg		}
227d6c0b56eSmrg	}
228d6c0b56eSmrg
229d6c0b56eSmrg	return TRUE;
230d6c0b56eSmrg}
231d6c0b56eSmrg
232d6c0b56eSmrgstatic Bool
233d6c0b56eSmrgamdgpu_glamor_picture_prepare_access_cpu_rw(ScrnInfoPtr scrn,
234d6c0b56eSmrg					    PicturePtr picture)
235d6c0b56eSmrg{
236d6c0b56eSmrg	PixmapPtr pixmap;
237d6c0b56eSmrg	struct amdgpu_pixmap *priv;
238d6c0b56eSmrg
239d6c0b56eSmrg	pixmap = get_drawable_pixmap(picture->pDrawable);
240d6c0b56eSmrg	priv = amdgpu_get_pixmap_private(pixmap);
241d6c0b56eSmrg	if (!amdgpu_glamor_prepare_access_cpu_rw(scrn, pixmap, priv))
242d6c0b56eSmrg		return FALSE;
243d6c0b56eSmrg
244d6c0b56eSmrg	if (picture->alphaMap) {
245d6c0b56eSmrg		pixmap = get_drawable_pixmap(picture->alphaMap->pDrawable);
246d6c0b56eSmrg		priv = amdgpu_get_pixmap_private(pixmap);
247d6c0b56eSmrg		if (!amdgpu_glamor_prepare_access_cpu_rw(scrn, pixmap, priv)) {
248d6c0b56eSmrg			amdgpu_glamor_picture_finish_access_cpu(picture);
249d6c0b56eSmrg			return FALSE;
250d6c0b56eSmrg		}
251d6c0b56eSmrg	}
252d6c0b56eSmrg
253d6c0b56eSmrg	return TRUE;
254d6c0b56eSmrg}
255d6c0b56eSmrg
256d6c0b56eSmrg/*
257d6c0b56eSmrg * GC rendering wrappers
258d6c0b56eSmrg */
259d6c0b56eSmrg
260d6c0b56eSmrgstatic void
261d6c0b56eSmrgamdgpu_glamor_fill_spans(DrawablePtr pDrawable, GCPtr pGC, int nspans,
262d6c0b56eSmrg			 DDXPointPtr ppt, int *pwidth, int fSorted)
263d6c0b56eSmrg{
264d6c0b56eSmrg	ScrnInfoPtr scrn = xf86ScreenToScrn(pDrawable->pScreen);
265d6c0b56eSmrg	PixmapPtr pixmap = get_drawable_pixmap(pDrawable);
266d6c0b56eSmrg	struct amdgpu_pixmap *priv = amdgpu_get_pixmap_private(pixmap);
267d6c0b56eSmrg
268d6c0b56eSmrg	if (amdgpu_glamor_prepare_access_cpu_rw(scrn, pixmap, priv)) {
269d6c0b56eSmrg		if (amdgpu_glamor_prepare_access_gc(scrn, pGC)) {
270d6c0b56eSmrg			fbFillSpans(pDrawable, pGC, nspans, ppt, pwidth,
271d6c0b56eSmrg				    fSorted);
272d6c0b56eSmrg			amdgpu_glamor_finish_access_gc(pGC);
273d6c0b56eSmrg		}
274d6c0b56eSmrg		amdgpu_glamor_finish_access_cpu(pixmap);
275d6c0b56eSmrg	}
276d6c0b56eSmrg}
277d6c0b56eSmrg
278d6c0b56eSmrgstatic void
279d6c0b56eSmrgamdgpu_glamor_set_spans(DrawablePtr pDrawable, GCPtr pGC, char *psrc,
280d6c0b56eSmrg			DDXPointPtr ppt, int *pwidth, int nspans, int fSorted)
281d6c0b56eSmrg{
282d6c0b56eSmrg	ScrnInfoPtr scrn = xf86ScreenToScrn(pDrawable->pScreen);
283d6c0b56eSmrg	PixmapPtr pixmap = get_drawable_pixmap(pDrawable);
284d6c0b56eSmrg	struct amdgpu_pixmap *priv = amdgpu_get_pixmap_private(pixmap);
285d6c0b56eSmrg
286d6c0b56eSmrg	if (amdgpu_glamor_prepare_access_cpu_rw(scrn, pixmap, priv)) {
287d6c0b56eSmrg		fbSetSpans(pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted);
288d6c0b56eSmrg		amdgpu_glamor_finish_access_cpu(pixmap);
289d6c0b56eSmrg	}
290d6c0b56eSmrg}
291d6c0b56eSmrg
292d6c0b56eSmrgstatic void
293d6c0b56eSmrgamdgpu_glamor_put_image(DrawablePtr pDrawable, GCPtr pGC, int depth,
294d6c0b56eSmrg			int x, int y, int w, int h, int leftPad, int format,
295d6c0b56eSmrg			char *bits)
296d6c0b56eSmrg{
297d6c0b56eSmrg	ScrnInfoPtr scrn = xf86ScreenToScrn(pDrawable->pScreen);
298d6c0b56eSmrg	PixmapPtr pixmap = get_drawable_pixmap(pDrawable);
299d6c0b56eSmrg	struct amdgpu_pixmap *priv = amdgpu_get_pixmap_private(pixmap);
300d6c0b56eSmrg
301d6c0b56eSmrg	if (amdgpu_glamor_prepare_access_cpu_rw(scrn, pixmap, priv)) {
302d6c0b56eSmrg		fbPutImage(pDrawable, pGC, depth, x, y, w, h, leftPad, format,
303d6c0b56eSmrg			   bits);
304d6c0b56eSmrg		amdgpu_glamor_finish_access_cpu(pixmap);
305d6c0b56eSmrg	}
306d6c0b56eSmrg}
307d6c0b56eSmrg
308d6c0b56eSmrgstatic RegionPtr
309d6c0b56eSmrgamdgpu_glamor_copy_plane(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
310d6c0b56eSmrg			 int srcx, int srcy, int w, int h, int dstx, int dsty,
311d6c0b56eSmrg			 unsigned long bitPlane)
312d6c0b56eSmrg{
313d6c0b56eSmrg	ScrnInfoPtr scrn = xf86ScreenToScrn(pDst->pScreen);
314d6c0b56eSmrg	PixmapPtr dst_pix = get_drawable_pixmap(pDst);
315d6c0b56eSmrg	struct amdgpu_pixmap *dst_priv = amdgpu_get_pixmap_private(dst_pix);
316d6c0b56eSmrg	RegionPtr ret = NULL;
317d6c0b56eSmrg
318d6c0b56eSmrg	if (amdgpu_glamor_prepare_access_cpu_rw(scrn, dst_pix, dst_priv)) {
319d6c0b56eSmrg		PixmapPtr src_pix = get_drawable_pixmap(pSrc);
320d6c0b56eSmrg		struct amdgpu_pixmap *src_priv = amdgpu_get_pixmap_private(src_pix);
321d6c0b56eSmrg		if (amdgpu_glamor_prepare_access_cpu_ro(scrn, src_pix, src_priv)) {
322d6c0b56eSmrg			ret =
323d6c0b56eSmrg			    fbCopyPlane(pSrc, pDst, pGC, srcx, srcy, w, h, dstx,
324d6c0b56eSmrg					dsty, bitPlane);
325d6c0b56eSmrg			amdgpu_glamor_finish_access_cpu(src_pix);
326d6c0b56eSmrg		}
327d6c0b56eSmrg		amdgpu_glamor_finish_access_cpu(dst_pix);
328d6c0b56eSmrg	}
329d6c0b56eSmrg	return ret;
330d6c0b56eSmrg}
331d6c0b56eSmrg
332d6c0b56eSmrgstatic RegionPtr
333d6c0b56eSmrgamdgpu_glamor_copy_plane_nodstbo(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
334d6c0b56eSmrg				 int srcx, int srcy, int w, int h,
335d6c0b56eSmrg				 int dstx, int dsty, unsigned long bitPlane)
336d6c0b56eSmrg{
337d6c0b56eSmrg	ScrnInfoPtr scrn = xf86ScreenToScrn(pDst->pScreen);
338d6c0b56eSmrg	PixmapPtr src_pix = get_drawable_pixmap(pSrc);
339d6c0b56eSmrg	struct amdgpu_pixmap *src_priv = amdgpu_get_pixmap_private(src_pix);
340d6c0b56eSmrg	RegionPtr ret = NULL;
341d6c0b56eSmrg
342d6c0b56eSmrg	if (amdgpu_glamor_prepare_access_cpu_ro(scrn, src_pix, src_priv)) {
343d6c0b56eSmrg		ret = fbCopyPlane(pSrc, pDst, pGC, srcx, srcy, w, h,
344d6c0b56eSmrg				  dstx,	dsty, bitPlane);
345d6c0b56eSmrg		amdgpu_glamor_finish_access_cpu(src_pix);
346d6c0b56eSmrg	}
347d6c0b56eSmrg	return ret;
348d6c0b56eSmrg}
349d6c0b56eSmrg
350d6c0b56eSmrgstatic void
351d6c0b56eSmrgamdgpu_glamor_poly_point(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt,
352d6c0b56eSmrg			 DDXPointPtr pptInit)
353d6c0b56eSmrg{
354d6c0b56eSmrg	ScrnInfoPtr scrn = xf86ScreenToScrn(pDrawable->pScreen);
355d6c0b56eSmrg	PixmapPtr pixmap = get_drawable_pixmap(pDrawable);
356d6c0b56eSmrg	struct amdgpu_pixmap *priv = amdgpu_get_pixmap_private(pixmap);
357d6c0b56eSmrg
358d6c0b56eSmrg	if (amdgpu_glamor_prepare_access_cpu_rw(scrn, pixmap, priv)) {
359d6c0b56eSmrg		fbPolyPoint(pDrawable, pGC, mode, npt, pptInit);
360d6c0b56eSmrg		amdgpu_glamor_finish_access_cpu(pixmap);
361d6c0b56eSmrg	}
362d6c0b56eSmrg}
363d6c0b56eSmrg
364d6c0b56eSmrgstatic void
365d6c0b56eSmrgamdgpu_glamor_poly_lines(DrawablePtr pDrawable, GCPtr pGC,
366d6c0b56eSmrg			 int mode, int npt, DDXPointPtr ppt)
367d6c0b56eSmrg{
368d6c0b56eSmrg	if (pGC->lineWidth == 0) {
369d6c0b56eSmrg		ScrnInfoPtr scrn = xf86ScreenToScrn(pDrawable->pScreen);
370d6c0b56eSmrg		PixmapPtr pixmap = get_drawable_pixmap(pDrawable);
371d6c0b56eSmrg		struct amdgpu_pixmap *priv = amdgpu_get_pixmap_private(pixmap);
372d6c0b56eSmrg
373d6c0b56eSmrg		if (amdgpu_glamor_prepare_access_cpu_rw(scrn, pixmap, priv)) {
374d6c0b56eSmrg			if (amdgpu_glamor_prepare_access_gc(scrn, pGC)) {
375d6c0b56eSmrg				fbPolyLine(pDrawable, pGC, mode, npt, ppt);
376d6c0b56eSmrg				amdgpu_glamor_finish_access_gc(pGC);
377d6c0b56eSmrg			}
378d6c0b56eSmrg			amdgpu_glamor_finish_access_cpu(pixmap);
379d6c0b56eSmrg		}
380d6c0b56eSmrg		return;
381d6c0b56eSmrg	}
382d6c0b56eSmrg	/* fb calls mi functions in the lineWidth != 0 case. */
383d6c0b56eSmrg	fbPolyLine(pDrawable, pGC, mode, npt, ppt);
384d6c0b56eSmrg}
385d6c0b56eSmrg
386d6c0b56eSmrgstatic void
387d6c0b56eSmrgamdgpu_glamor_poly_segment(DrawablePtr pDrawable, GCPtr pGC,
388d6c0b56eSmrg			   int nsegInit, xSegment *pSegInit)
389d6c0b56eSmrg{
390d6c0b56eSmrg	if (pGC->lineWidth == 0) {
391d6c0b56eSmrg		ScrnInfoPtr scrn = xf86ScreenToScrn(pDrawable->pScreen);
392d6c0b56eSmrg		PixmapPtr pixmap = get_drawable_pixmap(pDrawable);
393d6c0b56eSmrg		struct amdgpu_pixmap *priv = amdgpu_get_pixmap_private(pixmap);
394d6c0b56eSmrg
395d6c0b56eSmrg		if (amdgpu_glamor_prepare_access_cpu_rw(scrn, pixmap, priv)) {
396d6c0b56eSmrg			if (amdgpu_glamor_prepare_access_gc(scrn, pGC)) {
397d6c0b56eSmrg				fbPolySegment(pDrawable, pGC, nsegInit,
398d6c0b56eSmrg					      pSegInit);
399d6c0b56eSmrg				amdgpu_glamor_finish_access_gc(pGC);
400d6c0b56eSmrg			}
401d6c0b56eSmrg			amdgpu_glamor_finish_access_cpu(pixmap);
402d6c0b56eSmrg		}
403d6c0b56eSmrg		return;
404d6c0b56eSmrg	}
405d6c0b56eSmrg	/* fb calls mi functions in the lineWidth != 0 case. */
406d6c0b56eSmrg	fbPolySegment(pDrawable, pGC, nsegInit, pSegInit);
407d6c0b56eSmrg}
408d6c0b56eSmrg
409d6c0b56eSmrgstatic void
410d6c0b56eSmrgamdgpu_glamor_poly_fill_rect(DrawablePtr pDrawable, GCPtr pGC,
411d6c0b56eSmrg			     int nrect, xRectangle *prect)
412d6c0b56eSmrg{
413d6c0b56eSmrg	ScrnInfoPtr scrn = xf86ScreenToScrn(pDrawable->pScreen);
414d6c0b56eSmrg	AMDGPUInfoPtr info = AMDGPUPTR(scrn);
415d6c0b56eSmrg	PixmapPtr pixmap = get_drawable_pixmap(pDrawable);
416d6c0b56eSmrg	struct amdgpu_pixmap *priv = amdgpu_get_pixmap_private(pixmap);
417d6c0b56eSmrg
418d6c0b56eSmrg	if ((info->force_accel || amdgpu_glamor_use_gpu(pixmap, priv)) &&
419d6c0b56eSmrg	    amdgpu_glamor_prepare_access_gpu(priv)) {
420d6c0b56eSmrg		info->glamor.SavedPolyFillRect(pDrawable, pGC, nrect, prect);
421d6c0b56eSmrg		amdgpu_glamor_finish_access_gpu_rw(info, priv);
422d6c0b56eSmrg		return;
423d6c0b56eSmrg	}
424d6c0b56eSmrg
425d6c0b56eSmrg	if (amdgpu_glamor_prepare_access_cpu_rw(scrn, pixmap, priv)) {
426d6c0b56eSmrg		if (amdgpu_glamor_prepare_access_gc(scrn, pGC)) {
427d6c0b56eSmrg			fbPolyFillRect(pDrawable, pGC, nrect, prect);
428d6c0b56eSmrg			amdgpu_glamor_finish_access_gc(pGC);
429d6c0b56eSmrg		}
430d6c0b56eSmrg		amdgpu_glamor_finish_access_cpu(pixmap);
431d6c0b56eSmrg	}
432d6c0b56eSmrg}
433d6c0b56eSmrg
434d6c0b56eSmrgstatic void
435d6c0b56eSmrgamdgpu_glamor_image_glyph_blt(DrawablePtr pDrawable, GCPtr pGC,
436d6c0b56eSmrg			      int x, int y, unsigned int nglyph,
437d6c0b56eSmrg			      CharInfoPtr *ppci, pointer pglyphBase)
438d6c0b56eSmrg{
439d6c0b56eSmrg	ScrnInfoPtr scrn = xf86ScreenToScrn(pDrawable->pScreen);
440d6c0b56eSmrg	PixmapPtr pixmap = get_drawable_pixmap(pDrawable);
441d6c0b56eSmrg	struct amdgpu_pixmap *priv = amdgpu_get_pixmap_private(pixmap);
442d6c0b56eSmrg
443d6c0b56eSmrg	if (amdgpu_glamor_prepare_access_cpu_rw(scrn, pixmap, priv)) {
444d6c0b56eSmrg		if (amdgpu_glamor_prepare_access_gc(scrn, pGC)) {
445d6c0b56eSmrg			fbImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci,
446d6c0b56eSmrg					pglyphBase);
447d6c0b56eSmrg			amdgpu_glamor_finish_access_gc(pGC);
448d6c0b56eSmrg		}
449d6c0b56eSmrg		amdgpu_glamor_finish_access_cpu(pixmap);
450d6c0b56eSmrg	}
451d6c0b56eSmrg}
452d6c0b56eSmrg
453d6c0b56eSmrgstatic void
454d6c0b56eSmrgamdgpu_glamor_poly_glyph_blt(DrawablePtr pDrawable, GCPtr pGC,
455d6c0b56eSmrg			     int x, int y, unsigned int nglyph,
456d6c0b56eSmrg			     CharInfoPtr *ppci, pointer pglyphBase)
457d6c0b56eSmrg{
458d6c0b56eSmrg	ScrnInfoPtr scrn = xf86ScreenToScrn(pDrawable->pScreen);
459d6c0b56eSmrg	PixmapPtr pixmap = get_drawable_pixmap(pDrawable);
460d6c0b56eSmrg	struct amdgpu_pixmap *priv = amdgpu_get_pixmap_private(pixmap);
461d6c0b56eSmrg
462d6c0b56eSmrg	if (amdgpu_glamor_prepare_access_cpu_rw(scrn, pixmap, priv)) {
463d6c0b56eSmrg		if (amdgpu_glamor_prepare_access_gc(scrn, pGC)) {
464d6c0b56eSmrg			fbPolyGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci,
465d6c0b56eSmrg				       pglyphBase);
466d6c0b56eSmrg			amdgpu_glamor_finish_access_gc(pGC);
467d6c0b56eSmrg		}
468d6c0b56eSmrg		amdgpu_glamor_finish_access_cpu(pixmap);
469d6c0b56eSmrg	}
470d6c0b56eSmrg}
471d6c0b56eSmrg
472d6c0b56eSmrgstatic void
473d6c0b56eSmrgamdgpu_glamor_push_pixels(GCPtr pGC, PixmapPtr pBitmap,
474d6c0b56eSmrg			  DrawablePtr pDrawable, int w, int h, int x, int y)
475d6c0b56eSmrg{
476d6c0b56eSmrg	ScrnInfoPtr scrn = xf86ScreenToScrn(pDrawable->pScreen);
477d6c0b56eSmrg	PixmapPtr pixmap = get_drawable_pixmap(pDrawable);
478d6c0b56eSmrg	struct amdgpu_pixmap *priv = amdgpu_get_pixmap_private(pixmap);
479d6c0b56eSmrg
480d6c0b56eSmrg	if (amdgpu_glamor_prepare_access_cpu_rw(scrn, pixmap, priv)) {
481d6c0b56eSmrg		priv = amdgpu_get_pixmap_private(pBitmap);
482d6c0b56eSmrg		if (amdgpu_glamor_prepare_access_cpu_ro(scrn, pBitmap, priv)) {
483d6c0b56eSmrg			if (amdgpu_glamor_prepare_access_gc(scrn, pGC)) {
484d6c0b56eSmrg				fbPushPixels(pGC, pBitmap, pDrawable, w, h, x,
485d6c0b56eSmrg					     y);
486d6c0b56eSmrg				amdgpu_glamor_finish_access_gc(pGC);
487d6c0b56eSmrg			}
488d6c0b56eSmrg			amdgpu_glamor_finish_access_cpu(pBitmap);
489d6c0b56eSmrg		}
490d6c0b56eSmrg		amdgpu_glamor_finish_access_cpu(pixmap);
491d6c0b56eSmrg	}
492d6c0b56eSmrg}
493d6c0b56eSmrg
494d6c0b56eSmrgstatic void
495d6c0b56eSmrgamdgpu_glamor_push_pixels_nodstbo(GCPtr pGC, PixmapPtr pBitmap,
496d6c0b56eSmrg				  DrawablePtr pDrawable, int w, int h,
497d6c0b56eSmrg				  int x, int y)
498d6c0b56eSmrg{
499d6c0b56eSmrg	ScrnInfoPtr scrn = xf86ScreenToScrn(pDrawable->pScreen);
500d6c0b56eSmrg	struct amdgpu_pixmap *priv = amdgpu_get_pixmap_private(pBitmap);
501d6c0b56eSmrg
502d6c0b56eSmrg	if (amdgpu_glamor_prepare_access_cpu_ro(scrn, pBitmap, priv)) {
503d6c0b56eSmrg		fbPushPixels(pGC, pBitmap, pDrawable, w, h, x, y);
504d6c0b56eSmrg		amdgpu_glamor_finish_access_cpu(pBitmap);
505d6c0b56eSmrg	}
506d6c0b56eSmrg}
507d6c0b56eSmrg
508d6c0b56eSmrgstatic RegionPtr
509d6c0b56eSmrgamdgpu_glamor_copy_area(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable,
510d6c0b56eSmrg			GCPtr pGC, int srcx, int srcy, int width, int height,
511d6c0b56eSmrg			int dstx, int dsty)
512d6c0b56eSmrg{
513d6c0b56eSmrg	ScreenPtr screen = pDstDrawable->pScreen;
514d6c0b56eSmrg	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
515d6c0b56eSmrg	AMDGPUInfoPtr info = AMDGPUPTR(scrn);
516d6c0b56eSmrg	PixmapPtr src_pixmap = get_drawable_pixmap(pSrcDrawable);
517d6c0b56eSmrg	PixmapPtr dst_pixmap = get_drawable_pixmap(pDstDrawable);
518d6c0b56eSmrg	struct amdgpu_pixmap *src_priv = amdgpu_get_pixmap_private(src_pixmap);
519d6c0b56eSmrg	struct amdgpu_pixmap *dst_priv = amdgpu_get_pixmap_private(dst_pixmap);
520d6c0b56eSmrg	RegionPtr ret = NULL;
521d6c0b56eSmrg
522d6c0b56eSmrg	if (amdgpu_glamor_use_gpu(dst_pixmap, dst_priv) ||
523d6c0b56eSmrg	    amdgpu_glamor_use_gpu(src_pixmap, src_priv)) {
524d6c0b56eSmrg		if (!amdgpu_glamor_prepare_access_gpu(dst_priv))
525d6c0b56eSmrg			goto fallback;
526d6c0b56eSmrg		if (src_priv != dst_priv &&
527d6c0b56eSmrg		    !amdgpu_glamor_prepare_access_gpu(src_priv))
528d6c0b56eSmrg			goto fallback;
529d6c0b56eSmrg
530d6c0b56eSmrg		ret = info->glamor.SavedCopyArea(pSrcDrawable, pDstDrawable,
531d6c0b56eSmrg						 pGC, srcx, srcy,
532d6c0b56eSmrg						 width, height, dstx, dsty);
533d6c0b56eSmrg		amdgpu_glamor_finish_access_gpu_rw(info, dst_priv);
534d6c0b56eSmrg		if (src_priv != dst_priv)
535d6c0b56eSmrg			amdgpu_glamor_finish_access_gpu_ro(info, src_priv);
536d6c0b56eSmrg
537d6c0b56eSmrg		return ret;
538d6c0b56eSmrg	}
539d6c0b56eSmrg
540d6c0b56eSmrgfallback:
541d6c0b56eSmrg	if (amdgpu_glamor_prepare_access_cpu_rw(scrn, dst_pixmap, dst_priv)) {
542d6c0b56eSmrg		if (pSrcDrawable == pDstDrawable ||
543d6c0b56eSmrg			amdgpu_glamor_prepare_access_cpu_ro(scrn, src_pixmap,
544d6c0b56eSmrg							    src_priv)) {
545d6c0b56eSmrg			ret = fbCopyArea(pSrcDrawable, pDstDrawable, pGC,
546d6c0b56eSmrg					 srcx, srcy, width, height, dstx, dsty);
547d6c0b56eSmrg			if (pSrcDrawable != pDstDrawable)
548d6c0b56eSmrg				amdgpu_glamor_finish_access_cpu(src_pixmap);
549d6c0b56eSmrg		}
550d6c0b56eSmrg		amdgpu_glamor_finish_access_cpu(dst_pixmap);
551d6c0b56eSmrg	}
552d6c0b56eSmrg
553d6c0b56eSmrg	return ret;
554d6c0b56eSmrg}
555d6c0b56eSmrg
556d6c0b56eSmrgstatic RegionPtr
557d6c0b56eSmrgamdgpu_glamor_copy_area_nodstbo(DrawablePtr pSrcDrawable,
558d6c0b56eSmrg				DrawablePtr pDstDrawable, GCPtr pGC,
559d6c0b56eSmrg				int srcx, int srcy, int width, int height,
560d6c0b56eSmrg				int dstx, int dsty)
561d6c0b56eSmrg{
562d6c0b56eSmrg	ScreenPtr screen = pDstDrawable->pScreen;
563d6c0b56eSmrg	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
564d6c0b56eSmrg	PixmapPtr src_pixmap = get_drawable_pixmap(pSrcDrawable);
565d6c0b56eSmrg	PixmapPtr dst_pixmap = get_drawable_pixmap(pDstDrawable);
566d6c0b56eSmrg	struct amdgpu_pixmap *src_priv;
567d6c0b56eSmrg	RegionPtr ret = NULL;
568d6c0b56eSmrg
569d6c0b56eSmrg	if (src_pixmap != dst_pixmap) {
570d6c0b56eSmrg		src_priv = amdgpu_get_pixmap_private(src_pixmap);
571d6c0b56eSmrg
572d6c0b56eSmrg		if (!amdgpu_glamor_prepare_access_cpu_ro(scrn, src_pixmap,
573d6c0b56eSmrg							 src_priv))
574d6c0b56eSmrg			return ret;
575d6c0b56eSmrg	}
576d6c0b56eSmrg
577d6c0b56eSmrg	ret = fbCopyArea(pSrcDrawable, pDstDrawable, pGC, srcx, srcy,
578d6c0b56eSmrg			 width, height, dstx, dsty);
579d6c0b56eSmrg
580d6c0b56eSmrg	if (src_pixmap != dst_pixmap)
581d6c0b56eSmrg		amdgpu_glamor_finish_access_cpu(src_pixmap);
582d6c0b56eSmrg
583d6c0b56eSmrg	return ret;
584d6c0b56eSmrg}
585d6c0b56eSmrg
586d6c0b56eSmrgstatic const GCOps amdgpu_glamor_ops = {
587d6c0b56eSmrg	amdgpu_glamor_fill_spans,
588d6c0b56eSmrg	amdgpu_glamor_set_spans,
589d6c0b56eSmrg	amdgpu_glamor_put_image,
590d6c0b56eSmrg	amdgpu_glamor_copy_area,
591d6c0b56eSmrg	amdgpu_glamor_copy_plane,
592d6c0b56eSmrg	amdgpu_glamor_poly_point,
593d6c0b56eSmrg	amdgpu_glamor_poly_lines,
594d6c0b56eSmrg	amdgpu_glamor_poly_segment,
595d6c0b56eSmrg	miPolyRectangle,
596d6c0b56eSmrg	miPolyArc,
597d6c0b56eSmrg	miFillPolygon,
598d6c0b56eSmrg	amdgpu_glamor_poly_fill_rect,
599d6c0b56eSmrg	miPolyFillArc,
600d6c0b56eSmrg	miPolyText8,
601d6c0b56eSmrg	miPolyText16,
602d6c0b56eSmrg	miImageText8,
603d6c0b56eSmrg	miImageText16,
604d6c0b56eSmrg	amdgpu_glamor_image_glyph_blt,
605d6c0b56eSmrg	amdgpu_glamor_poly_glyph_blt,
606d6c0b56eSmrg	amdgpu_glamor_push_pixels,
607d6c0b56eSmrg};
608d6c0b56eSmrg
609d6c0b56eSmrgstatic GCOps amdgpu_glamor_nodstbo_ops;
610d6c0b56eSmrg
611d6c0b56eSmrg/**
612d6c0b56eSmrg * amdgpu_glamor_validate_gc() sets the ops to our implementations, which may be
613d6c0b56eSmrg * accelerated or may sync the card and fall back to fb.
614d6c0b56eSmrg */
615d6c0b56eSmrgstatic void
616d6c0b56eSmrgamdgpu_glamor_validate_gc(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable)
617d6c0b56eSmrg{
618d6c0b56eSmrg	ScrnInfoPtr scrn = xf86ScreenToScrn(pGC->pScreen);
619d6c0b56eSmrg	AMDGPUInfoPtr info = AMDGPUPTR(scrn);
620d6c0b56eSmrg
621d6c0b56eSmrg	glamor_validate_gc(pGC, changes, pDrawable);
622d6c0b56eSmrg	info->glamor.SavedCopyArea = pGC->ops->CopyArea;
623d6c0b56eSmrg	info->glamor.SavedPolyFillRect = pGC->ops->PolyFillRect;
624d6c0b56eSmrg
625d6c0b56eSmrg	if (amdgpu_get_pixmap_private(get_drawable_pixmap(pDrawable)) ||
626d6c0b56eSmrg	    (pGC->stipple && amdgpu_get_pixmap_private(pGC->stipple)) ||
627d6c0b56eSmrg	    (pGC->fillStyle == FillTiled &&
628d6c0b56eSmrg	     amdgpu_get_pixmap_private(pGC->tile.pixmap)))
629d6c0b56eSmrg		pGC->ops = (GCOps *)&amdgpu_glamor_ops;
630d6c0b56eSmrg	else
631d6c0b56eSmrg		pGC->ops = &amdgpu_glamor_nodstbo_ops;
632d6c0b56eSmrg}
633d6c0b56eSmrg
634d6c0b56eSmrgstatic GCFuncs glamorGCFuncs = {
635d6c0b56eSmrg	amdgpu_glamor_validate_gc,
636d6c0b56eSmrg	miChangeGC,
637d6c0b56eSmrg	miCopyGC,
638d6c0b56eSmrg	miDestroyGC,
639d6c0b56eSmrg	miChangeClip,
640d6c0b56eSmrg	miDestroyClip,
641d6c0b56eSmrg	miCopyClip
642d6c0b56eSmrg};
643d6c0b56eSmrg
644d6c0b56eSmrg/**
645d6c0b56eSmrg * amdgpu_glamor_create_gc makes a new GC and hooks up its funcs handler, so that
646d6c0b56eSmrg * amdgpu_glamor_validate_gc() will get called.
647d6c0b56eSmrg */
648d6c0b56eSmrgstatic int
649d6c0b56eSmrgamdgpu_glamor_create_gc(GCPtr pGC)
650d6c0b56eSmrg{
651d6c0b56eSmrg	static Bool nodstbo_ops_initialized;
652d6c0b56eSmrg
653d6c0b56eSmrg	if (!fbCreateGC(pGC))
654d6c0b56eSmrg		return FALSE;
655d6c0b56eSmrg
656d6c0b56eSmrg	if (!nodstbo_ops_initialized) {
657d6c0b56eSmrg		amdgpu_glamor_nodstbo_ops = amdgpu_glamor_ops;
658d6c0b56eSmrg
659d6c0b56eSmrg		amdgpu_glamor_nodstbo_ops.FillSpans = pGC->ops->FillSpans;
660d6c0b56eSmrg		amdgpu_glamor_nodstbo_ops.SetSpans = pGC->ops->SetSpans;
661d6c0b56eSmrg		amdgpu_glamor_nodstbo_ops.PutImage = pGC->ops->PutImage;
662d6c0b56eSmrg		amdgpu_glamor_nodstbo_ops.CopyArea = amdgpu_glamor_copy_area_nodstbo;
663d6c0b56eSmrg		amdgpu_glamor_nodstbo_ops.CopyPlane = amdgpu_glamor_copy_plane_nodstbo;
664d6c0b56eSmrg		amdgpu_glamor_nodstbo_ops.PolyPoint = pGC->ops->PolyPoint;
665d6c0b56eSmrg		amdgpu_glamor_nodstbo_ops.Polylines = pGC->ops->Polylines;
666d6c0b56eSmrg		amdgpu_glamor_nodstbo_ops.PolySegment = pGC->ops->PolySegment;
667d6c0b56eSmrg		amdgpu_glamor_nodstbo_ops.PolyFillRect = pGC->ops->PolyFillRect;
668d6c0b56eSmrg		amdgpu_glamor_nodstbo_ops.ImageGlyphBlt = pGC->ops->ImageGlyphBlt;
669d6c0b56eSmrg		amdgpu_glamor_nodstbo_ops.PolyGlyphBlt = pGC->ops->PolyGlyphBlt;
670d6c0b56eSmrg		amdgpu_glamor_nodstbo_ops.PushPixels = amdgpu_glamor_push_pixels_nodstbo;
671d6c0b56eSmrg
672d6c0b56eSmrg		nodstbo_ops_initialized = TRUE;
673d6c0b56eSmrg	}
674d6c0b56eSmrg
675d6c0b56eSmrg	pGC->funcs = &glamorGCFuncs;
676d6c0b56eSmrg
677d6c0b56eSmrg	return TRUE;
678d6c0b56eSmrg}
679d6c0b56eSmrg
680d6c0b56eSmrg/*
681d6c0b56eSmrg * Screen rendering wrappers
682d6c0b56eSmrg */
683d6c0b56eSmrg
684d6c0b56eSmrgstatic RegionPtr
685d6c0b56eSmrgamdgpu_glamor_bitmap_to_region(PixmapPtr pPix)
686d6c0b56eSmrg{
687d6c0b56eSmrg	ScrnInfoPtr scrn = xf86ScreenToScrn(pPix->drawable.pScreen);
688d6c0b56eSmrg	struct amdgpu_pixmap *priv = amdgpu_get_pixmap_private(pPix);
689d6c0b56eSmrg	RegionPtr ret;
690d6c0b56eSmrg
691d6c0b56eSmrg	if (!amdgpu_glamor_prepare_access_cpu_ro(scrn, pPix, priv))
692d6c0b56eSmrg		return NULL;
693d6c0b56eSmrg	ret = fbPixmapToRegion(pPix);
694d6c0b56eSmrg	amdgpu_glamor_finish_access_cpu(pPix);
695d6c0b56eSmrg	return ret;
696d6c0b56eSmrg}
697d6c0b56eSmrg
698d6c0b56eSmrgstatic void
699d6c0b56eSmrgamdgpu_glamor_copy_window(WindowPtr pWin, DDXPointRec ptOldOrg,
700d6c0b56eSmrg			  RegionPtr prgnSrc)
701d6c0b56eSmrg{
702d6c0b56eSmrg	ScrnInfoPtr scrn = xf86ScreenToScrn(pWin->drawable.pScreen);
703d6c0b56eSmrg	PixmapPtr pixmap = get_drawable_pixmap(&pWin->drawable);
704d6c0b56eSmrg	struct amdgpu_pixmap *priv = amdgpu_get_pixmap_private(pixmap);
705d6c0b56eSmrg
706d6c0b56eSmrg	if (amdgpu_glamor_prepare_access_cpu_rw(scrn, pixmap, priv)) {
707d6c0b56eSmrg		fbCopyWindow(pWin, ptOldOrg, prgnSrc);
708d6c0b56eSmrg		amdgpu_glamor_finish_access_cpu(pixmap);
709d6c0b56eSmrg	}
710d6c0b56eSmrg}
711d6c0b56eSmrg
712d6c0b56eSmrgstatic void
713d6c0b56eSmrgamdgpu_glamor_get_image(DrawablePtr pDrawable, int x, int y, int w, int h,
714d6c0b56eSmrg			unsigned int format, unsigned long planeMask, char *d)
715d6c0b56eSmrg{
716d6c0b56eSmrg	ScrnInfoPtr scrn = xf86ScreenToScrn(pDrawable->pScreen);
717d6c0b56eSmrg	PixmapPtr pixmap = get_drawable_pixmap(pDrawable);
718d6c0b56eSmrg	struct amdgpu_pixmap *priv = amdgpu_get_pixmap_private(pixmap);
719d6c0b56eSmrg
720d6c0b56eSmrg	if (amdgpu_glamor_prepare_access_cpu_ro(scrn, pixmap, priv)) {
721d6c0b56eSmrg		fbGetImage(pDrawable, x, y, w, h, format, planeMask, d);
722d6c0b56eSmrg		amdgpu_glamor_finish_access_cpu(pixmap);
723d6c0b56eSmrg	}
724d6c0b56eSmrg}
725d6c0b56eSmrg
726d6c0b56eSmrgstatic void
727d6c0b56eSmrgamdgpu_glamor_get_spans(DrawablePtr pDrawable, int wMax, DDXPointPtr ppt,
728d6c0b56eSmrg			int *pwidth, int nspans, char *pdstStart)
729d6c0b56eSmrg{
730d6c0b56eSmrg	ScrnInfoPtr scrn = xf86ScreenToScrn(pDrawable->pScreen);
731d6c0b56eSmrg	PixmapPtr pixmap = get_drawable_pixmap(pDrawable);
732d6c0b56eSmrg	struct amdgpu_pixmap *priv = amdgpu_get_pixmap_private(pixmap);
733d6c0b56eSmrg
734d6c0b56eSmrg	if (amdgpu_glamor_prepare_access_cpu_ro(scrn, pixmap, priv)) {
735d6c0b56eSmrg		fbGetSpans(pDrawable, wMax, ppt, pwidth, nspans, pdstStart);
736d6c0b56eSmrg		amdgpu_glamor_finish_access_cpu(pixmap);
737d6c0b56eSmrg	}
738d6c0b56eSmrg}
739d6c0b56eSmrg
740d6c0b56eSmrg/*
741d6c0b56eSmrg * Picture screen rendering wrappers
742d6c0b56eSmrg */
743d6c0b56eSmrg
744d6c0b56eSmrg#ifdef RENDER
745d6c0b56eSmrg
746d6c0b56eSmrgstatic void
747d6c0b56eSmrgamdgpu_glamor_composite(CARD8 op,
748d6c0b56eSmrg			PicturePtr pSrc,
749d6c0b56eSmrg			PicturePtr pMask,
750d6c0b56eSmrg			PicturePtr pDst,
751d6c0b56eSmrg			INT16 xSrc, INT16 ySrc,
752d6c0b56eSmrg			INT16 xMask, INT16 yMask,
753d6c0b56eSmrg			INT16 xDst, INT16 yDst,
754d6c0b56eSmrg			CARD16 width, CARD16 height)
755d6c0b56eSmrg{
756d6c0b56eSmrg	ScrnInfoPtr scrn = xf86ScreenToScrn(pDst->pDrawable->pScreen);
757d6c0b56eSmrg	AMDGPUInfoPtr info;
758d6c0b56eSmrg	PixmapPtr pixmap;
759d6c0b56eSmrg	struct amdgpu_pixmap *dst_priv, *src_priv = NULL, *mask_priv = NULL;
760d6c0b56eSmrg	Bool gpu_done = FALSE;
761d6c0b56eSmrg
762d6c0b56eSmrg	if (pDst->alphaMap || pSrc->alphaMap || (pMask && pMask->alphaMap))
763d6c0b56eSmrg		goto fallback;
764d6c0b56eSmrg
765d6c0b56eSmrg	pixmap = get_drawable_pixmap(pDst->pDrawable);
766d6c0b56eSmrg	if (&pixmap->drawable != pDst->pDrawable ||
767d6c0b56eSmrg	    pixmap->usage_hint != AMDGPU_CREATE_PIXMAP_SCANOUT)
768d6c0b56eSmrg		goto fallback;
769d6c0b56eSmrg
770d6c0b56eSmrg	dst_priv = amdgpu_get_pixmap_private(pixmap);
771d6c0b56eSmrg	if (!amdgpu_glamor_prepare_access_gpu(dst_priv))
772d6c0b56eSmrg		goto fallback;
773d6c0b56eSmrg
774d6c0b56eSmrg	info = AMDGPUPTR(scrn);
775d6c0b56eSmrg	if (!pSrc->pDrawable ||
776d6c0b56eSmrg	    ((pixmap = get_drawable_pixmap(pSrc->pDrawable)) &&
777d6c0b56eSmrg	     (src_priv = amdgpu_get_pixmap_private(pixmap)) &&
778d6c0b56eSmrg	     amdgpu_glamor_prepare_access_gpu(src_priv))) {
779d6c0b56eSmrg		if (!pMask || !pMask->pDrawable ||
780d6c0b56eSmrg		    ((pixmap = get_drawable_pixmap(pMask->pDrawable)) &&
781d6c0b56eSmrg		     (mask_priv = amdgpu_get_pixmap_private(pixmap)) &&
782d6c0b56eSmrg		     amdgpu_glamor_prepare_access_gpu(mask_priv))) {
783d6c0b56eSmrg			info->glamor.SavedComposite(op, pSrc, pMask, pDst,
784d6c0b56eSmrg						    xSrc, ySrc, xMask, yMask,
785d6c0b56eSmrg						    xDst, yDst, width, height);
786d6c0b56eSmrg			gpu_done = TRUE;
787d6c0b56eSmrg
788d6c0b56eSmrg			if (mask_priv)
789d6c0b56eSmrg				amdgpu_glamor_finish_access_gpu_ro(info, mask_priv);
790d6c0b56eSmrg		}
791d6c0b56eSmrg
792d6c0b56eSmrg		if (src_priv)
793d6c0b56eSmrg			amdgpu_glamor_finish_access_gpu_ro(info, src_priv);
794d6c0b56eSmrg	}
795d6c0b56eSmrg	amdgpu_glamor_finish_access_gpu_rw(info, dst_priv);
796d6c0b56eSmrg
797d6c0b56eSmrg	if (gpu_done)
798d6c0b56eSmrg		return;
799d6c0b56eSmrg
800d6c0b56eSmrgfallback:
801d6c0b56eSmrg	if (amdgpu_glamor_picture_prepare_access_cpu_rw(scrn, pDst)) {
802d6c0b56eSmrg		if (amdgpu_glamor_picture_prepare_access_cpu_ro(scrn, pSrc)) {
803d6c0b56eSmrg			if (!pMask ||
804d6c0b56eSmrg			    amdgpu_glamor_picture_prepare_access_cpu_ro(scrn, pMask)) {
805d6c0b56eSmrg				fbComposite(op, pSrc, pMask, pDst,
806d6c0b56eSmrg					    xSrc, ySrc,
807d6c0b56eSmrg					    xMask, yMask,
808d6c0b56eSmrg					    xDst, yDst,
809d6c0b56eSmrg					    width, height);
810d6c0b56eSmrg				if (pMask)
811d6c0b56eSmrg					amdgpu_glamor_picture_finish_access_cpu(pMask);
812d6c0b56eSmrg			}
813d6c0b56eSmrg			amdgpu_glamor_picture_finish_access_cpu(pSrc);
814d6c0b56eSmrg		}
815d6c0b56eSmrg		amdgpu_glamor_picture_finish_access_cpu(pDst);
816d6c0b56eSmrg	}
817d6c0b56eSmrg}
818d6c0b56eSmrg
819d6c0b56eSmrgstatic void
820d6c0b56eSmrgamdgpu_glamor_add_traps(PicturePtr pPicture,
821d6c0b56eSmrg		    INT16 x_off, INT16 y_off, int ntrap, xTrap *traps)
822d6c0b56eSmrg{
823d6c0b56eSmrg	ScrnInfoPtr scrn = xf86ScreenToScrn(pPicture->pDrawable->pScreen);
824d6c0b56eSmrg
825d6c0b56eSmrg	if (amdgpu_glamor_picture_prepare_access_cpu_rw(scrn, pPicture)) {
826d6c0b56eSmrg		fbAddTraps(pPicture, x_off, y_off, ntrap, traps);
827d6c0b56eSmrg		amdgpu_glamor_picture_finish_access_cpu(pPicture);
828d6c0b56eSmrg	}
829d6c0b56eSmrg}
830d6c0b56eSmrg
831d6c0b56eSmrgstatic void
832d6c0b56eSmrgamdgpu_glamor_glyphs(CARD8 op,
833d6c0b56eSmrg		     PicturePtr src,
834d6c0b56eSmrg		     PicturePtr dst,
835d6c0b56eSmrg		     PictFormatPtr maskFormat,
836d6c0b56eSmrg		     INT16 xSrc,
837d6c0b56eSmrg		     INT16 ySrc, int nlist, GlyphListPtr list, GlyphPtr *glyphs)
838d6c0b56eSmrg{
839d6c0b56eSmrg	ScrnInfoPtr scrn = xf86ScreenToScrn(dst->pDrawable->pScreen);
840d6c0b56eSmrg
841d6c0b56eSmrg	if (amdgpu_glamor_picture_prepare_access_cpu_rw(scrn, dst)) {
842d6c0b56eSmrg		if (amdgpu_glamor_picture_prepare_access_cpu_ro(scrn, src)) {
843d6c0b56eSmrg			AMDGPUInfoPtr info = AMDGPUPTR(scrn);
844d6c0b56eSmrg
845d6c0b56eSmrg			info->glamor.SavedGlyphs(op, src, dst, maskFormat, xSrc,
846d6c0b56eSmrg						 ySrc, nlist, list, glyphs);
847d6c0b56eSmrg			amdgpu_glamor_picture_finish_access_cpu(src);
848d6c0b56eSmrg		}
849d6c0b56eSmrg		amdgpu_glamor_picture_finish_access_cpu(dst);
850d6c0b56eSmrg	}
851d6c0b56eSmrg}
852d6c0b56eSmrg
853d6c0b56eSmrgstatic void
854d6c0b56eSmrgamdgpu_glamor_trapezoids(CARD8 op, PicturePtr src, PicturePtr dst,
855d6c0b56eSmrg			 PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
856d6c0b56eSmrg			 int ntrap, xTrapezoid *traps)
857d6c0b56eSmrg{
858d6c0b56eSmrg	ScrnInfoPtr scrn = xf86ScreenToScrn(dst->pDrawable->pScreen);
859d6c0b56eSmrg
860d6c0b56eSmrg	if (amdgpu_glamor_picture_prepare_access_cpu_rw(scrn, dst)) {
861d6c0b56eSmrg		if (amdgpu_glamor_picture_prepare_access_cpu_ro(scrn, src)) {
862d6c0b56eSmrg			AMDGPUInfoPtr info = AMDGPUPTR(scrn);
863d6c0b56eSmrg
864d6c0b56eSmrg			info->glamor.SavedTrapezoids(op, src, dst, maskFormat,
865d6c0b56eSmrg						     xSrc, ySrc, ntrap, traps);
866d6c0b56eSmrg			amdgpu_glamor_picture_finish_access_cpu(src);
867d6c0b56eSmrg		}
868d6c0b56eSmrg		amdgpu_glamor_picture_finish_access_cpu(dst);
869d6c0b56eSmrg	}
870d6c0b56eSmrg}
871d6c0b56eSmrg
872d6c0b56eSmrgstatic void
873d6c0b56eSmrgamdgpu_glamor_triangles(CARD8 op, PicturePtr src, PicturePtr dst,
874d6c0b56eSmrg			PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
875d6c0b56eSmrg			int ntri, xTriangle *tri)
876d6c0b56eSmrg{
877d6c0b56eSmrg	ScrnInfoPtr scrn = xf86ScreenToScrn(dst->pDrawable->pScreen);
878d6c0b56eSmrg
879d6c0b56eSmrg	if (amdgpu_glamor_picture_prepare_access_cpu_rw(scrn, dst)) {
880d6c0b56eSmrg		if (amdgpu_glamor_picture_prepare_access_cpu_ro(scrn, src)) {
881d6c0b56eSmrg			AMDGPUInfoPtr info = AMDGPUPTR(scrn);
882d6c0b56eSmrg
883d6c0b56eSmrg			info->glamor.SavedTriangles(op, src, dst, maskFormat,
884d6c0b56eSmrg						    xSrc, ySrc, ntri, tri);
885d6c0b56eSmrg			amdgpu_glamor_picture_finish_access_cpu(src);
886d6c0b56eSmrg		}
887d6c0b56eSmrg		amdgpu_glamor_picture_finish_access_cpu(dst);
888d6c0b56eSmrg	}
889d6c0b56eSmrg}
890d6c0b56eSmrg
891d6c0b56eSmrg#endif /* RENDER */
892d6c0b56eSmrg
893d6c0b56eSmrg
894d6c0b56eSmrg/**
895d6c0b56eSmrg * amdgpu_glamor_close_screen() unwraps its wrapped screen functions and tears
896d6c0b56eSmrg * down our screen private, before calling down to the next CloseScreen.
897d6c0b56eSmrg */
898d6c0b56eSmrgstatic Bool
89924b90cf4Smrgamdgpu_glamor_close_screen(ScreenPtr pScreen)
900d6c0b56eSmrg{
901d6c0b56eSmrg	AMDGPUInfoPtr info = AMDGPUPTR(xf86ScreenToScrn(pScreen));
902d6c0b56eSmrg#ifdef RENDER
903d6c0b56eSmrg	PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
904d6c0b56eSmrg#endif
905d6c0b56eSmrg
906d6c0b56eSmrg	pScreen->CreateGC = info->glamor.SavedCreateGC;
907d6c0b56eSmrg	pScreen->CloseScreen = info->glamor.SavedCloseScreen;
908d6c0b56eSmrg	pScreen->GetImage = info->glamor.SavedGetImage;
909d6c0b56eSmrg	pScreen->GetSpans = info->glamor.SavedGetSpans;
910d6c0b56eSmrg	pScreen->CopyWindow = info->glamor.SavedCopyWindow;
911d6c0b56eSmrg	pScreen->ChangeWindowAttributes =
912d6c0b56eSmrg	    info->glamor.SavedChangeWindowAttributes;
913d6c0b56eSmrg	pScreen->BitmapToRegion = info->glamor.SavedBitmapToRegion;
914d6c0b56eSmrg#ifdef RENDER
915d6c0b56eSmrg	if (ps) {
916d6c0b56eSmrg		ps->Composite = info->glamor.SavedComposite;
917d6c0b56eSmrg		ps->Glyphs = info->glamor.SavedGlyphs;
918d6c0b56eSmrg		ps->UnrealizeGlyph = info->glamor.SavedUnrealizeGlyph;
919d6c0b56eSmrg		ps->Trapezoids = info->glamor.SavedTrapezoids;
920d6c0b56eSmrg		ps->AddTraps = info->glamor.SavedAddTraps;
921d6c0b56eSmrg		ps->Triangles = info->glamor.SavedTriangles;
922d6c0b56eSmrg
923d6c0b56eSmrg		ps->UnrealizeGlyph = info->glamor.SavedUnrealizeGlyph;
924d6c0b56eSmrg	}
925d6c0b56eSmrg#endif
926d6c0b56eSmrg
92724b90cf4Smrg	return pScreen->CloseScreen(pScreen);
928d6c0b56eSmrg}
929d6c0b56eSmrg
930d6c0b56eSmrg/**
931d6c0b56eSmrg * @param screen screen being initialized
932d6c0b56eSmrg */
933d6c0b56eSmrgvoid
934d6c0b56eSmrgamdgpu_glamor_screen_init(ScreenPtr screen)
935d6c0b56eSmrg{
936d6c0b56eSmrg	AMDGPUInfoPtr info = AMDGPUPTR(xf86ScreenToScrn(screen));
937d6c0b56eSmrg
938d6c0b56eSmrg	/*
939d6c0b56eSmrg	 * Replace various fb screen functions
940d6c0b56eSmrg	 */
941d6c0b56eSmrg	info->glamor.SavedCloseScreen = screen->CloseScreen;
942d6c0b56eSmrg	screen->CloseScreen = amdgpu_glamor_close_screen;
943d6c0b56eSmrg
944d6c0b56eSmrg	info->glamor.SavedCreateGC = screen->CreateGC;
945d6c0b56eSmrg	screen->CreateGC = amdgpu_glamor_create_gc;
946d6c0b56eSmrg
947d6c0b56eSmrg	info->glamor.SavedGetImage = screen->GetImage;
948d6c0b56eSmrg	screen->GetImage = amdgpu_glamor_get_image;
949d6c0b56eSmrg
950d6c0b56eSmrg	info->glamor.SavedGetSpans = screen->GetSpans;
951d6c0b56eSmrg	screen->GetSpans = amdgpu_glamor_get_spans;
952d6c0b56eSmrg
953d6c0b56eSmrg	info->glamor.SavedCopyWindow = screen->CopyWindow;
954d6c0b56eSmrg	screen->CopyWindow = amdgpu_glamor_copy_window;
955d6c0b56eSmrg
956d6c0b56eSmrg	info->glamor.SavedBitmapToRegion = screen->BitmapToRegion;
957d6c0b56eSmrg	screen->BitmapToRegion = amdgpu_glamor_bitmap_to_region;
958d6c0b56eSmrg
959d6c0b56eSmrg#ifdef RENDER
960d6c0b56eSmrg	{
961d6c0b56eSmrg		PictureScreenPtr ps = GetPictureScreenIfSet(screen);
962d6c0b56eSmrg		if (ps) {
963d6c0b56eSmrg			info->glamor.SavedComposite = ps->Composite;
964d6c0b56eSmrg			ps->Composite = amdgpu_glamor_composite;
965d6c0b56eSmrg
966d6c0b56eSmrg			info->glamor.SavedUnrealizeGlyph = ps->UnrealizeGlyph;
967d6c0b56eSmrg
968d6c0b56eSmrg			ps->Glyphs = amdgpu_glamor_glyphs;
969d6c0b56eSmrg			ps->Triangles = amdgpu_glamor_triangles;
970d6c0b56eSmrg			ps->Trapezoids = amdgpu_glamor_trapezoids;
971d6c0b56eSmrg
972d6c0b56eSmrg			info->glamor.SavedAddTraps = ps->AddTraps;
973d6c0b56eSmrg			ps->AddTraps = amdgpu_glamor_add_traps;
974d6c0b56eSmrg		}
975d6c0b56eSmrg	}
976d6c0b56eSmrg#endif
977d6c0b56eSmrg}
978d6c0b56eSmrg
979d6c0b56eSmrg#endif /* USE_GLAMOR */
980