1d6c0b56eSmrg/*
2d6c0b56eSmrg * Copyright © 2011 Intel Corporation.
3d6c0b56eSmrg *             2012 Advanced Micro Devices, Inc.
4d6c0b56eSmrg *
5d6c0b56eSmrg * Permission is hereby granted, free of charge, to any person
6d6c0b56eSmrg * obtaining a copy of this software and associated documentation
7d6c0b56eSmrg * files (the "Software"), to deal in the Software without
8d6c0b56eSmrg * restriction, including without limitation the rights to use, copy,
9d6c0b56eSmrg * modify, merge, publish, distribute, sublicense, and/or sell copies
10d6c0b56eSmrg * of the Software, and to permit persons to whom the Software is
11d6c0b56eSmrg * furnished to do so, subject to the following conditions:
12d6c0b56eSmrg *
13d6c0b56eSmrg * The above copyright notice and this permission notice (including
14d6c0b56eSmrg * the next paragraph) shall be included in all copies or substantial
15d6c0b56eSmrg * portions of the Software.
16d6c0b56eSmrg *
17d6c0b56eSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18d6c0b56eSmrg * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19d6c0b56eSmrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20d6c0b56eSmrg * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
21d6c0b56eSmrg * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22d6c0b56eSmrg * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23d6c0b56eSmrg * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24d6c0b56eSmrg * DEALINGS IN THE SOFTWARE.
25d6c0b56eSmrg */
26d6c0b56eSmrg
27d6c0b56eSmrg#ifdef HAVE_CONFIG_H
28d6c0b56eSmrg#include "config.h"
29d6c0b56eSmrg#endif
30d6c0b56eSmrg
3190f2b693Smrg#ifdef USE_GLAMOR
3290f2b693Smrg
33d6c0b56eSmrg#include <xf86.h>
34d6c0b56eSmrg
35d6c0b56eSmrg#include "amdgpu_bo_helper.h"
36d6c0b56eSmrg#include "amdgpu_pixmap.h"
37d6c0b56eSmrg#include "amdgpu_glamor.h"
38d6c0b56eSmrg
39d6c0b56eSmrg#include <gbm.h>
40d6c0b56eSmrg
4111bf0794Smrg#ifndef HAVE_GLAMOR_FINISH
42d6c0b56eSmrg#include <GL/gl.h>
4311bf0794Smrg#endif
44d6c0b56eSmrg
45d6c0b56eSmrgDevPrivateKeyRec amdgpu_pixmap_index;
46d6c0b56eSmrg
47d6c0b56eSmrgvoid amdgpu_glamor_exchange_buffers(PixmapPtr src, PixmapPtr dst)
48d6c0b56eSmrg{
49d6c0b56eSmrg	AMDGPUInfoPtr info = AMDGPUPTR(xf86ScreenToScrn(dst->drawable.pScreen));
50d6c0b56eSmrg
51d6c0b56eSmrg	if (!info->use_glamor)
52d6c0b56eSmrg		return;
53d6c0b56eSmrg	glamor_egl_exchange_buffers(src, dst);
54d6c0b56eSmrg}
55d6c0b56eSmrg
56d6c0b56eSmrgBool amdgpu_glamor_create_screen_resources(ScreenPtr screen)
57d6c0b56eSmrg{
5835d5b7c7Smrg	PixmapPtr screen_pixmap = screen->GetScreenPixmap(screen);
59d6c0b56eSmrg	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
60d6c0b56eSmrg	AMDGPUInfoPtr info = AMDGPUPTR(scrn);
61d6c0b56eSmrg
62d6c0b56eSmrg	if (!info->use_glamor)
63d6c0b56eSmrg		return TRUE;
64d6c0b56eSmrg
65d6c0b56eSmrg#ifdef HAVE_GLAMOR_GLYPHS_INIT
66d6c0b56eSmrg	if (!glamor_glyphs_init(screen))
67d6c0b56eSmrg		return FALSE;
68d6c0b56eSmrg#endif
69d6c0b56eSmrg
7035d5b7c7Smrg	return amdgpu_glamor_create_textured_pixmap(screen_pixmap,
7135d5b7c7Smrg						    info->front_buffer);
72d6c0b56eSmrg}
73d6c0b56eSmrg
74d6c0b56eSmrgBool amdgpu_glamor_pre_init(ScrnInfoPtr scrn)
75d6c0b56eSmrg{
76d6c0b56eSmrg	AMDGPUInfoPtr info = AMDGPUPTR(scrn);
77d6c0b56eSmrg	pointer glamor_module;
78d6c0b56eSmrg	CARD32 version;
79d6c0b56eSmrg
8090f2b693Smrg#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1,20,99,0,0)
81d6c0b56eSmrg	if (scrn->depth < 24) {
8290f2b693Smrg#else
8390f2b693Smrg	if (scrn->depth < 15) {
8490f2b693Smrg#endif
85d6c0b56eSmrg		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
8690f2b693Smrg			   "Depth %d not supported with glamor, disabling\n",
8790f2b693Smrg			   scrn->depth);
88d6c0b56eSmrg		return FALSE;
89d6c0b56eSmrg	}
9090f2b693Smrg
91d6c0b56eSmrg#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1,15,0,0,0)
92d6c0b56eSmrg	if (!xf86LoaderCheckSymbol("glamor_egl_init")) {
93d6c0b56eSmrg		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
94d6c0b56eSmrg			   "glamor requires Load \"glamoregl\" in "
95d6c0b56eSmrg			   "Section \"Module\", disabling.\n");
96d6c0b56eSmrg		return FALSE;
97d6c0b56eSmrg	}
98d6c0b56eSmrg#endif
99d6c0b56eSmrg
100d6c0b56eSmrg	/* Load glamor module */
101d6c0b56eSmrg	if ((glamor_module = xf86LoadSubModule(scrn, GLAMOR_EGL_MODULE_NAME))) {
102d6c0b56eSmrg		version = xf86GetModuleVersion(glamor_module);
103d6c0b56eSmrg		if (version < MODULE_VERSION_NUMERIC(0, 3, 1)) {
104d6c0b56eSmrg			xf86DrvMsg(scrn->scrnIndex, X_ERROR,
105d6c0b56eSmrg				   "Incompatible glamor version, required >= 0.3.0.\n");
106d6c0b56eSmrg			return FALSE;
107d6c0b56eSmrg		} else {
108d6c0b56eSmrg			AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn);
109d6c0b56eSmrg
11035d5b7c7Smrg			if (scrn->depth == 30 &&
11135d5b7c7Smrg			    version < MODULE_VERSION_NUMERIC(1, 0, 1)) {
11235d5b7c7Smrg				xf86DrvMsg(scrn->scrnIndex, X_WARNING,
11335d5b7c7Smrg					   "Depth 30 requires glamor >= 1.0.1 (xserver 1.20),"
11435d5b7c7Smrg					   " can't enable glamor\n");
11535d5b7c7Smrg				return FALSE;
11635d5b7c7Smrg			}
11735d5b7c7Smrg
118d6c0b56eSmrg			if (glamor_egl_init(scrn, pAMDGPUEnt->fd)) {
119d6c0b56eSmrg				xf86DrvMsg(scrn->scrnIndex, X_INFO,
120d6c0b56eSmrg					   "glamor detected, initialising EGL layer.\n");
121d6c0b56eSmrg			} else {
122d6c0b56eSmrg				xf86DrvMsg(scrn->scrnIndex, X_ERROR,
123d6c0b56eSmrg					   "glamor detected, failed to initialize EGL.\n");
124d6c0b56eSmrg				return FALSE;
125d6c0b56eSmrg			}
126d6c0b56eSmrg		}
127d6c0b56eSmrg	} else {
128d6c0b56eSmrg		xf86DrvMsg(scrn->scrnIndex, X_ERROR, "glamor not available\n");
129d6c0b56eSmrg		return FALSE;
130d6c0b56eSmrg	}
131d6c0b56eSmrg
132d6c0b56eSmrg	info->use_glamor = TRUE;
133d6c0b56eSmrg
134d6c0b56eSmrg	return TRUE;
135d6c0b56eSmrg}
136d6c0b56eSmrg
137d6c0b56eSmrgBool
138504d986fSmrgamdgpu_glamor_create_textured_pixmap(PixmapPtr pixmap, struct amdgpu_buffer *bo)
139d6c0b56eSmrg{
140d6c0b56eSmrg	ScrnInfoPtr scrn = xf86ScreenToScrn(pixmap->drawable.pScreen);
141d6c0b56eSmrg	AMDGPUInfoPtr info = AMDGPUPTR(scrn);
142d6c0b56eSmrg
143d6c0b56eSmrg	if ((info->use_glamor) == 0)
144d6c0b56eSmrg		return TRUE;
145d6c0b56eSmrg
14635d5b7c7Smrg	if (bo->flags & AMDGPU_BO_FLAGS_GBM) {
14735d5b7c7Smrg		return glamor_egl_create_textured_pixmap_from_gbm_bo(pixmap,
14835d5b7c7Smrg								     bo->bo.gbm
14935d5b7c7Smrg#if XORG_VERSION_CURRENT > XORG_VERSION_NUMERIC(1,19,99,903,0)
15035d5b7c7Smrg								     , FALSE
15135d5b7c7Smrg#endif
15235d5b7c7Smrg								     );
15335d5b7c7Smrg	} else {
15435d5b7c7Smrg		uint32_t bo_handle;
155d6c0b56eSmrg
15635d5b7c7Smrg		if (!amdgpu_bo_get_handle(bo, &bo_handle))
15735d5b7c7Smrg			return FALSE;
15835d5b7c7Smrg
15935d5b7c7Smrg		return glamor_egl_create_textured_pixmap(pixmap, bo_handle,
16035d5b7c7Smrg							 pixmap->devKind);
16135d5b7c7Smrg	}
162d6c0b56eSmrg}
163d6c0b56eSmrg
164d6c0b56eSmrgstatic Bool amdgpu_glamor_destroy_pixmap(PixmapPtr pixmap)
165d6c0b56eSmrg{
166d6c0b56eSmrg#ifndef HAVE_GLAMOR_EGL_DESTROY_TEXTURED_PIXMAP
167d6c0b56eSmrg	ScreenPtr screen = pixmap->drawable.pScreen;
168d6c0b56eSmrg	AMDGPUInfoPtr info = AMDGPUPTR(xf86ScreenToScrn(screen));
169d6c0b56eSmrg	Bool ret;
170d6c0b56eSmrg#endif
171d6c0b56eSmrg
172d6c0b56eSmrg	if (pixmap->refcnt == 1) {
173d6c0b56eSmrg		if (pixmap->devPrivate.ptr) {
174d6c0b56eSmrg			struct amdgpu_buffer *bo = amdgpu_get_pixmap_bo(pixmap);
175d6c0b56eSmrg
176d6c0b56eSmrg			if (bo)
177d6c0b56eSmrg				amdgpu_bo_unmap(bo);
178d6c0b56eSmrg		}
179d6c0b56eSmrg
180d6c0b56eSmrg#ifdef HAVE_GLAMOR_EGL_DESTROY_TEXTURED_PIXMAP
181d6c0b56eSmrg		glamor_egl_destroy_textured_pixmap(pixmap);
182d6c0b56eSmrg#endif
183d6c0b56eSmrg		amdgpu_set_pixmap_bo(pixmap, NULL);
184d6c0b56eSmrg	}
185d6c0b56eSmrg
186d6c0b56eSmrg#ifdef HAVE_GLAMOR_EGL_DESTROY_TEXTURED_PIXMAP
187d6c0b56eSmrg	fbDestroyPixmap(pixmap);
188d6c0b56eSmrg	return TRUE;
189d6c0b56eSmrg#else
190d6c0b56eSmrg	screen->DestroyPixmap = info->glamor.SavedDestroyPixmap;
191d6c0b56eSmrg	ret = screen->DestroyPixmap(pixmap);
192d6c0b56eSmrg	info->glamor.SavedDestroyPixmap = screen->DestroyPixmap;
193d6c0b56eSmrg	screen->DestroyPixmap = amdgpu_glamor_destroy_pixmap;
194d6c0b56eSmrg
195d6c0b56eSmrg	return ret;
196d6c0b56eSmrg#endif
197d6c0b56eSmrg}
198d6c0b56eSmrg
199d6c0b56eSmrgstatic PixmapPtr
200d6c0b56eSmrgamdgpu_glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth,
201d6c0b56eSmrg			    unsigned usage)
202d6c0b56eSmrg{
203d6c0b56eSmrg	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
20446845023Smrg	PixmapFormatPtr format = xf86GetPixFormat(scrn, depth);
205d6c0b56eSmrg	AMDGPUInfoPtr info = AMDGPUPTR(scrn);
206d6c0b56eSmrg	struct amdgpu_pixmap *priv;
207d6c0b56eSmrg	PixmapPtr pixmap, new_pixmap = NULL;
208d6c0b56eSmrg
20946845023Smrg	if (!format)
21035d5b7c7Smrg		return NULL;
21135d5b7c7Smrg
212e49c54bcSmrg	if (usage != CREATE_PIXMAP_USAGE_BACKING_PIXMAP &&
213e49c54bcSmrg	    usage != CREATE_PIXMAP_USAGE_SHARED &&
214e49c54bcSmrg	    !info->shadow_primary &&
215e49c54bcSmrg	    w >= scrn->virtualX &&
216e49c54bcSmrg	    w <= scrn->displayWidth &&
217e49c54bcSmrg	    h == scrn->virtualY &&
218e49c54bcSmrg	    format->bitsPerPixel == scrn->bitsPerPixel)
219e49c54bcSmrg		usage |= AMDGPU_CREATE_PIXMAP_SCANOUT;
220e49c54bcSmrg
22146845023Smrg	if (!(usage & AMDGPU_CREATE_PIXMAP_SCANOUT) &&
22246845023Smrg	    !AMDGPU_CREATE_PIXMAP_SHARED(usage)) {
223d6c0b56eSmrg		if (info->shadow_primary) {
224d6c0b56eSmrg			if (usage != CREATE_PIXMAP_USAGE_BACKING_PIXMAP)
225d6c0b56eSmrg				return fbCreatePixmap(screen, w, h, depth, usage);
226d6c0b56eSmrg
227d6c0b56eSmrg			usage |= AMDGPU_CREATE_PIXMAP_LINEAR |
228d6c0b56eSmrg				 AMDGPU_CREATE_PIXMAP_GTT;
22990f2b693Smrg		} else if (usage != CREATE_PIXMAP_USAGE_BACKING_PIXMAP) {
230e49c54bcSmrg			pixmap = glamor_create_pixmap(screen, w, h, depth, usage);
231e49c54bcSmrg			if (pixmap)
232e49c54bcSmrg				return pixmap;
233d6c0b56eSmrg		}
234d6c0b56eSmrg	}
235d6c0b56eSmrg
236d6c0b56eSmrg	if (w > 32767 || h > 32767)
237d6c0b56eSmrg		return NullPixmap;
238d6c0b56eSmrg
239d6c0b56eSmrg	if (depth == 1)
240d6c0b56eSmrg		return fbCreatePixmap(screen, w, h, depth, usage);
241d6c0b56eSmrg
242d6c0b56eSmrg	if (usage == CREATE_PIXMAP_USAGE_GLYPH_PICTURE && w <= 32 && h <= 32)
243d6c0b56eSmrg		return fbCreatePixmap(screen, w, h, depth, usage);
244d6c0b56eSmrg
245d6c0b56eSmrg	pixmap = fbCreatePixmap(screen, 0, 0, depth, usage);
246d6c0b56eSmrg	if (pixmap == NullPixmap)
247d6c0b56eSmrg		return pixmap;
248d6c0b56eSmrg
249d6c0b56eSmrg	if (w && h) {
250d6c0b56eSmrg		int stride;
251d6c0b56eSmrg
252d6c0b56eSmrg		priv = calloc(1, sizeof(struct amdgpu_pixmap));
25335d5b7c7Smrg		if (!priv)
254d6c0b56eSmrg			goto fallback_pixmap;
255d6c0b56eSmrg
256d6c0b56eSmrg		priv->bo = amdgpu_alloc_pixmap_bo(scrn, w, h, depth, usage,
257d6c0b56eSmrg						  pixmap->drawable.bitsPerPixel,
258d6c0b56eSmrg						  &stride);
259d6c0b56eSmrg		if (!priv->bo)
260d6c0b56eSmrg			goto fallback_priv;
261d6c0b56eSmrg
262d6c0b56eSmrg		amdgpu_set_pixmap_private(pixmap, priv);
263d6c0b56eSmrg
264d6c0b56eSmrg		screen->ModifyPixmapHeader(pixmap, w, h, 0, 0, stride, NULL);
265d6c0b56eSmrg
266d6c0b56eSmrg		pixmap->devPrivate.ptr = NULL;
267d6c0b56eSmrg
268504d986fSmrg		if (!amdgpu_glamor_create_textured_pixmap(pixmap, priv->bo))
269d6c0b56eSmrg			goto fallback_glamor;
270d6c0b56eSmrg	}
271d6c0b56eSmrg
272d6c0b56eSmrg	return pixmap;
273d6c0b56eSmrg
274d6c0b56eSmrgfallback_glamor:
275d6c0b56eSmrg	if (AMDGPU_CREATE_PIXMAP_SHARED(usage)) {
276d6c0b56eSmrg		/* XXX need further work to handle the DRI2 failure case.
277d6c0b56eSmrg		 * Glamor don't know how to handle a BO only pixmap. Put
278d6c0b56eSmrg		 * a warning indicator here.
279d6c0b56eSmrg		 */
280d6c0b56eSmrg		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
281d6c0b56eSmrg			   "Failed to create textured DRI2/PRIME pixmap.");
282d6c0b56eSmrg
283d6c0b56eSmrg		amdgpu_glamor_destroy_pixmap(pixmap);
284d6c0b56eSmrg		return NullPixmap;
285d6c0b56eSmrg	}
286d6c0b56eSmrg	/* Create textured pixmap failed means glamor failed to
287d6c0b56eSmrg	 * create a texture from current BO for some reasons. We turn
288d6c0b56eSmrg	 * to create a new glamor pixmap and clean up current one.
289d6c0b56eSmrg	 * One thing need to be noted, this new pixmap doesn't
290d6c0b56eSmrg	 * has a priv and bo attached to it. It's glamor's responsbility
291d6c0b56eSmrg	 * to take care of it. Glamor will mark this new pixmap as a
292d6c0b56eSmrg	 * texture only pixmap and will never fallback to DDX layer
293d6c0b56eSmrg	 * afterwards.
294d6c0b56eSmrg	 */
295d6c0b56eSmrg	new_pixmap = glamor_create_pixmap(screen, w, h, depth, usage);
296d6c0b56eSmrg	amdgpu_bo_unref(&priv->bo);
297d6c0b56eSmrgfallback_priv:
298d6c0b56eSmrg	free(priv);
299d6c0b56eSmrgfallback_pixmap:
300d6c0b56eSmrg	fbDestroyPixmap(pixmap);
301d6c0b56eSmrg	if (new_pixmap)
302d6c0b56eSmrg		return new_pixmap;
303d6c0b56eSmrg	else
304d6c0b56eSmrg		return fbCreatePixmap(screen, w, h, depth, usage);
305d6c0b56eSmrg}
306d6c0b56eSmrg
307504d986fSmrgPixmapPtr
308504d986fSmrgamdgpu_glamor_set_pixmap_bo(DrawablePtr drawable, PixmapPtr pixmap)
309504d986fSmrg{
310504d986fSmrg	PixmapPtr old = get_drawable_pixmap(drawable);
311504d986fSmrg	ScreenPtr screen = drawable->pScreen;
312504d986fSmrg	struct amdgpu_pixmap *priv = amdgpu_get_pixmap_private(pixmap);
313504d986fSmrg	GCPtr gc;
314504d986fSmrg
315504d986fSmrg	/* With a glamor pixmap, 2D pixmaps are created in texture
316504d986fSmrg	 * and without a static BO attached to it. To support DRI,
317504d986fSmrg	 * we need to create a new textured-drm pixmap and
318504d986fSmrg	 * need to copy the original content to this new textured-drm
319504d986fSmrg	 * pixmap, and then convert the old pixmap to a coherent
320504d986fSmrg	 * textured-drm pixmap which has a valid BO attached to it
321504d986fSmrg	 * and also has a valid texture, thus both glamor and DRI2
322504d986fSmrg	 * can access it.
323504d986fSmrg	 *
324504d986fSmrg	 */
325504d986fSmrg
326504d986fSmrg	/* Copy the current contents of the pixmap to the bo. */
327504d986fSmrg	gc = GetScratchGC(drawable->depth, screen);
328504d986fSmrg	if (gc) {
329504d986fSmrg		ValidateGC(&pixmap->drawable, gc);
330504d986fSmrg		gc->ops->CopyArea(&old->drawable, &pixmap->drawable,
331504d986fSmrg				  gc,
332504d986fSmrg				  0, 0,
333504d986fSmrg				  old->drawable.width,
334504d986fSmrg				  old->drawable.height, 0, 0);
335504d986fSmrg		FreeScratchGC(gc);
336504d986fSmrg	}
337504d986fSmrg
338504d986fSmrg	/* And redirect the pixmap to the new bo (for 3D). */
339504d986fSmrg	glamor_egl_exchange_buffers(old, pixmap);
340504d986fSmrg	amdgpu_set_pixmap_private(pixmap, amdgpu_get_pixmap_private(old));
341504d986fSmrg	amdgpu_set_pixmap_private(old, priv);
342504d986fSmrg
343504d986fSmrg	screen->ModifyPixmapHeader(old,
344504d986fSmrg				   old->drawable.width,
345504d986fSmrg				   old->drawable.height,
346504d986fSmrg				   0, 0, pixmap->devKind, NULL);
347504d986fSmrg	old->devPrivate.ptr = NULL;
348504d986fSmrg
349504d986fSmrg	screen->DestroyPixmap(pixmap);
350504d986fSmrg
351504d986fSmrg	return old;
352504d986fSmrg}
353504d986fSmrg
354d6c0b56eSmrg
355d6c0b56eSmrgstatic Bool
35646845023Smrgamdgpu_glamor_share_pixmap_backing(PixmapPtr pixmap, ScreenPtr secondary,
357d6c0b56eSmrg				   void **handle_p)
358d6c0b56eSmrg{
359504d986fSmrg	ScreenPtr screen = pixmap->drawable.pScreen;
36024b90cf4Smrg	AMDGPUInfoPtr info = AMDGPUPTR(xf86ScreenToScrn(screen));
361504d986fSmrg	uint64_t tiling_info;
362504d986fSmrg	CARD16 stride;
363504d986fSmrg	CARD32 size;
36424b90cf4Smrg	Bool is_linear;
365504d986fSmrg	int fd;
366504d986fSmrg
367504d986fSmrg	tiling_info = amdgpu_pixmap_get_tiling_info(pixmap);
36824b90cf4Smrg
36924b90cf4Smrg	if (info->family >= AMDGPU_FAMILY_AI)
37024b90cf4Smrg		is_linear = AMDGPU_TILING_GET(tiling_info, SWIZZLE_MODE) == 0;
37124b90cf4Smrg	else
37224b90cf4Smrg		is_linear = AMDGPU_TILING_GET(tiling_info, ARRAY_MODE) == 1;
37324b90cf4Smrg
37424b90cf4Smrg	if (!is_linear) {
375504d986fSmrg		PixmapPtr linear;
376504d986fSmrg
377504d986fSmrg		/* We don't want to re-allocate the screen pixmap as
378504d986fSmrg		 * linear, to avoid trouble with page flipping
379504d986fSmrg		 */
380504d986fSmrg		if (screen->GetScreenPixmap(screen) == pixmap)
381504d986fSmrg			return FALSE;
382d6c0b56eSmrg
383504d986fSmrg		linear = screen->CreatePixmap(screen, pixmap->drawable.width,
384504d986fSmrg					      pixmap->drawable.height,
385504d986fSmrg					      pixmap->drawable.depth,
386504d986fSmrg					      CREATE_PIXMAP_USAGE_SHARED);
387504d986fSmrg		if (!linear)
388504d986fSmrg			return FALSE;
389504d986fSmrg
390504d986fSmrg		amdgpu_glamor_set_pixmap_bo(&pixmap->drawable, linear);
391504d986fSmrg	}
392504d986fSmrg
393504d986fSmrg	fd = glamor_fd_from_pixmap(screen, pixmap, &stride, &size);
394504d986fSmrg	if (fd < 0)
395d6c0b56eSmrg		return FALSE;
396d6c0b56eSmrg
397504d986fSmrg	*handle_p = (void *)(long)fd;
398504d986fSmrg	return TRUE;
399d6c0b56eSmrg}
400d6c0b56eSmrg
401d6c0b56eSmrgstatic Bool
402d6c0b56eSmrgamdgpu_glamor_set_shared_pixmap_backing(PixmapPtr pixmap, void *handle)
403d6c0b56eSmrg{
404d6c0b56eSmrg	ScreenPtr screen = pixmap->drawable.pScreen;
405d6c0b56eSmrg	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
40635d5b7c7Smrg	int ihandle = (int)(long)handle;
407d6c0b56eSmrg	struct amdgpu_pixmap *priv;
408d6c0b56eSmrg
409d6c0b56eSmrg	if (!amdgpu_set_shared_pixmap_backing(pixmap, handle))
410d6c0b56eSmrg		return FALSE;
411d6c0b56eSmrg
412d6c0b56eSmrg	priv = amdgpu_get_pixmap_private(pixmap);
413d6c0b56eSmrg
41435d5b7c7Smrg	if (ihandle != -1 &&
41535d5b7c7Smrg	    !amdgpu_glamor_create_textured_pixmap(pixmap, priv->bo)) {
416d6c0b56eSmrg		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
417d6c0b56eSmrg			   "Failed to get PRIME drawable for glamor pixmap.\n");
418d6c0b56eSmrg		return FALSE;
419d6c0b56eSmrg	}
420d6c0b56eSmrg
421d6c0b56eSmrg	screen->ModifyPixmapHeader(pixmap,
422d6c0b56eSmrg				   pixmap->drawable.width,
423d6c0b56eSmrg				   pixmap->drawable.height,
424d6c0b56eSmrg				   0, 0, 0, NULL);
425d6c0b56eSmrg
426d6c0b56eSmrg	return TRUE;
427d6c0b56eSmrg}
428d6c0b56eSmrg
429d6c0b56eSmrg
430d6c0b56eSmrgBool amdgpu_glamor_init(ScreenPtr screen)
431d6c0b56eSmrg{
432d6c0b56eSmrg	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
433d6c0b56eSmrg	AMDGPUInfoPtr info = AMDGPUPTR(scrn);
434d6c0b56eSmrg#ifdef RENDER
435d6c0b56eSmrg#ifdef HAVE_FBGLYPHS
436d6c0b56eSmrg	UnrealizeGlyphProcPtr SavedUnrealizeGlyph = NULL;
437d6c0b56eSmrg#endif
438d6c0b56eSmrg	PictureScreenPtr ps = NULL;
439d6c0b56eSmrg
440d6c0b56eSmrg	if (info->shadow_primary) {
441d6c0b56eSmrg		ps = GetPictureScreenIfSet(screen);
442d6c0b56eSmrg
443d6c0b56eSmrg		if (ps) {
444d6c0b56eSmrg#ifdef HAVE_FBGLYPHS
445d6c0b56eSmrg			SavedUnrealizeGlyph = ps->UnrealizeGlyph;
446d6c0b56eSmrg#endif
447d6c0b56eSmrg			info->glamor.SavedGlyphs = ps->Glyphs;
448d6c0b56eSmrg			info->glamor.SavedTriangles = ps->Triangles;
449d6c0b56eSmrg			info->glamor.SavedTrapezoids = ps->Trapezoids;
450d6c0b56eSmrg		}
451d6c0b56eSmrg	}
452d6c0b56eSmrg#endif /* RENDER */
453d6c0b56eSmrg
454d6c0b56eSmrg	if (!glamor_init(screen, GLAMOR_USE_EGL_SCREEN | GLAMOR_USE_SCREEN |
455d6c0b56eSmrg			 GLAMOR_USE_PICTURE_SCREEN | GLAMOR_INVERTED_Y_AXIS |
456d6c0b56eSmrg			 GLAMOR_NO_DRI3)) {
457d6c0b56eSmrg		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
458d6c0b56eSmrg			   "Failed to initialize glamor.\n");
459d6c0b56eSmrg		return FALSE;
460d6c0b56eSmrg	}
461d6c0b56eSmrg
462d6c0b56eSmrg	if (!glamor_egl_init_textured_pixmap(screen)) {
463d6c0b56eSmrg		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
464d6c0b56eSmrg			   "Failed to initialize textured pixmap of screen for glamor.\n");
465d6c0b56eSmrg		return FALSE;
466d6c0b56eSmrg	}
467d6c0b56eSmrg	if (!dixRegisterPrivateKey(&amdgpu_pixmap_index, PRIVATE_PIXMAP, 0))
468d6c0b56eSmrg		return FALSE;
469d6c0b56eSmrg
470d6c0b56eSmrg	if (info->shadow_primary)
471d6c0b56eSmrg		amdgpu_glamor_screen_init(screen);
472d6c0b56eSmrg
473d6c0b56eSmrg#if defined(RENDER) && defined(HAVE_FBGLYPHS)
474d6c0b56eSmrg	/* For ShadowPrimary, we need fbUnrealizeGlyph instead of
475d6c0b56eSmrg	 * glamor_unrealize_glyph
476d6c0b56eSmrg	 */
477d6c0b56eSmrg	if (ps)
478d6c0b56eSmrg		ps->UnrealizeGlyph = SavedUnrealizeGlyph;
479d6c0b56eSmrg#endif
480d6c0b56eSmrg
481d6c0b56eSmrg	info->glamor.SavedCreatePixmap = screen->CreatePixmap;
482d6c0b56eSmrg	screen->CreatePixmap = amdgpu_glamor_create_pixmap;
483d6c0b56eSmrg	info->glamor.SavedDestroyPixmap = screen->DestroyPixmap;
484d6c0b56eSmrg	screen->DestroyPixmap = amdgpu_glamor_destroy_pixmap;
485d6c0b56eSmrg	info->glamor.SavedSharePixmapBacking = screen->SharePixmapBacking;
486d6c0b56eSmrg	screen->SharePixmapBacking = amdgpu_glamor_share_pixmap_backing;
487d6c0b56eSmrg	info->glamor.SavedSetSharedPixmapBacking = screen->SetSharedPixmapBacking;
488d6c0b56eSmrg	screen->SetSharedPixmapBacking =
489d6c0b56eSmrg	    amdgpu_glamor_set_shared_pixmap_backing;
490d6c0b56eSmrg
491d6c0b56eSmrg	xf86DrvMsg(scrn->scrnIndex, X_INFO, "Use GLAMOR acceleration.\n");
492d6c0b56eSmrg	return TRUE;
493d6c0b56eSmrg}
494d6c0b56eSmrg
495d6c0b56eSmrgvoid amdgpu_glamor_flush(ScrnInfoPtr pScrn)
496d6c0b56eSmrg{
497d6c0b56eSmrg	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
498d6c0b56eSmrg
499d6c0b56eSmrg	if (info->use_glamor) {
500d6c0b56eSmrg		glamor_block_handler(pScrn->pScreen);
501d6c0b56eSmrg	}
502504d986fSmrg
503504d986fSmrg	info->gpu_flushed++;
504d6c0b56eSmrg}
505d6c0b56eSmrg
506d6c0b56eSmrgvoid amdgpu_glamor_finish(ScrnInfoPtr pScrn)
507d6c0b56eSmrg{
508d6c0b56eSmrg	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
509d6c0b56eSmrg
510d6c0b56eSmrg	if (info->use_glamor) {
51111bf0794Smrg#if HAVE_GLAMOR_FINISH
51211bf0794Smrg		glamor_finish(pScrn->pScreen);
51311bf0794Smrg		info->gpu_flushed++;
51411bf0794Smrg#else
515d6c0b56eSmrg		amdgpu_glamor_flush(pScrn);
516d6c0b56eSmrg		glFinish();
51711bf0794Smrg#endif
518d6c0b56eSmrg	}
519d6c0b56eSmrg}
520d6c0b56eSmrg
521d6c0b56eSmrgvoid
522d6c0b56eSmrgamdgpu_glamor_fini(ScreenPtr screen)
523d6c0b56eSmrg{
524d6c0b56eSmrg	AMDGPUInfoPtr info = AMDGPUPTR(xf86ScreenToScrn(screen));
525d6c0b56eSmrg
526d6c0b56eSmrg	if (!info->use_glamor)
527d6c0b56eSmrg		return;
528d6c0b56eSmrg
529d6c0b56eSmrg	screen->CreatePixmap = info->glamor.SavedCreatePixmap;
530d6c0b56eSmrg	screen->DestroyPixmap = info->glamor.SavedDestroyPixmap;
531d6c0b56eSmrg	screen->SharePixmapBacking = info->glamor.SavedSharePixmapBacking;
532d6c0b56eSmrg	screen->SetSharedPixmapBacking = info->glamor.SavedSetSharedPixmapBacking;
533d6c0b56eSmrg}
534d6c0b56eSmrg
535d6c0b56eSmrgXF86VideoAdaptorPtr amdgpu_glamor_xv_init(ScreenPtr pScreen, int num_adapt)
536d6c0b56eSmrg{
537d6c0b56eSmrg	return glamor_xv_init(pScreen, num_adapt);
538d6c0b56eSmrg}
53990f2b693Smrg
54090f2b693Smrg#endif /* USE_GLAMOR */
541