1/* Copyright © 2014 Advanced Micro Devices, Inc.
2 *
3 * Permission is hereby granted, free of charge, to any person
4 * obtaining a copy of this software and associated documentation
5 * files (the "Software"), to deal in the Software without
6 * restriction, including without limitation the rights to use, copy,
7 * modify, merge, publish, distribute, sublicense, and/or sell copies
8 * of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including
12 * the next paragraph) shall be included in all copies or substantial
13 * portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 */
24
25#ifdef HAVE_CONFIG_H
26#include "config.h"
27#endif
28
29#include <xf86.h>
30#include "amdgpu_pixmap.h"
31#include "amdgpu_bo_helper.h"
32
33static PixmapPtr
34amdgpu_pixmap_create(ScreenPtr screen, int w, int h, int depth,	unsigned usage)
35{
36	ScrnInfoPtr scrn;
37	struct amdgpu_pixmap *priv;
38	PixmapPtr pixmap;
39	AMDGPUInfoPtr info;
40
41	/* only DRI2 pixmap is supported */
42	if (!(usage & AMDGPU_CREATE_PIXMAP_DRI2))
43		return fbCreatePixmap(screen, w, h, depth, usage);
44
45	if (w > 32767 || h > 32767)
46		return NullPixmap;
47
48	if (depth == 1)
49		return fbCreatePixmap(screen, w, h, depth, usage);
50
51	pixmap = fbCreatePixmap(screen, 0, 0, depth, usage);
52	if (pixmap == NullPixmap)
53		return pixmap;
54
55	if (w && h) {
56		int stride;
57
58		priv = calloc(1, sizeof(struct amdgpu_pixmap));
59		if (!priv)
60			goto fallback_pixmap;
61
62		scrn = xf86ScreenToScrn(screen);
63		info = AMDGPUPTR(scrn);
64		if (!info->use_glamor)
65			usage |= AMDGPU_CREATE_PIXMAP_LINEAR;
66		priv->bo = amdgpu_alloc_pixmap_bo(scrn, w, h, depth, usage,
67						  pixmap->drawable.bitsPerPixel,
68						  &stride);
69		if (!priv->bo)
70			goto fallback_priv;
71
72		amdgpu_set_pixmap_private(pixmap, priv);
73
74		if (amdgpu_bo_map(scrn, priv->bo)) {
75			ErrorF("Failed to mmap the bo\n");
76			goto fallback_bo;
77		}
78
79		screen->ModifyPixmapHeader(pixmap, w, h, 0, 0, stride,
80					   priv->bo->cpu_ptr);
81	}
82
83	return pixmap;
84
85fallback_bo:
86	amdgpu_bo_unref(&priv->bo);
87fallback_priv:
88	free(priv);
89fallback_pixmap:
90	fbDestroyPixmap(pixmap);
91	return fbCreatePixmap(screen, w, h, depth, usage);
92}
93
94static Bool amdgpu_pixmap_destroy(PixmapPtr pixmap)
95{
96	if (pixmap->refcnt == 1) {
97		amdgpu_set_pixmap_bo(pixmap, NULL);
98	}
99	fbDestroyPixmap(pixmap);
100	return TRUE;
101}
102
103/* This should only be called when glamor is disabled */
104Bool amdgpu_pixmap_init(ScreenPtr screen)
105{
106	if (!dixRegisterPrivateKey(&amdgpu_pixmap_index, PRIVATE_PIXMAP, 0))
107		return FALSE;
108
109	screen->CreatePixmap = amdgpu_pixmap_create;
110	screen->DestroyPixmap = amdgpu_pixmap_destroy;
111	return TRUE;
112}
113