1 /*
2  * Copyright © 2014 Advanced Micro Devices, Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person
5  * obtaining a copy of this software and associated documentation
6  * files (the "Software"), to deal in the Software without
7  * restriction, including without limitation the rights to use, copy,
8  * modify, merge, publish, distribute, sublicense, and/or sell copies
9  * of the Software, and to permit persons to whom the Software is
10  * furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice (including
13  * the next paragraph) shall be included in all copies or substantial
14  * portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19  * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23  * DEALINGS IN THE SOFTWARE.
24  */
25 
26 #ifndef AMDGPU_PIXMAP_H
27 #define AMDGPU_PIXMAP_H
28 
29 #include "amdgpu_drv.h"
30 
31 struct amdgpu_pixmap {
32 	uint_fast32_t gpu_read;
33 	uint_fast32_t gpu_write;
34 
35 	uint64_t tiling_info;
36 
37 	struct amdgpu_buffer *bo;
38 	struct drmmode_fb *fb;
39 	Bool fb_failed;
40 
41 	/* GEM handle for pixmaps shared via DRI2/3 */
42 	Bool handle_valid;
43 	uint32_t handle;
44 };
45 
46 extern DevPrivateKeyRec amdgpu_pixmap_index;
47 
amdgpu_get_pixmap_private(PixmapPtr pixmap)48 static inline struct amdgpu_pixmap *amdgpu_get_pixmap_private(PixmapPtr pixmap)
49 {
50 	return dixGetPrivate(&pixmap->devPrivates, &amdgpu_pixmap_index);
51 }
52 
amdgpu_set_pixmap_private(PixmapPtr pixmap,struct amdgpu_pixmap * priv)53 static inline void amdgpu_set_pixmap_private(PixmapPtr pixmap,
54 					     struct amdgpu_pixmap *priv)
55 {
56 	dixSetPrivate(&pixmap->devPrivates, &amdgpu_pixmap_index, priv);
57 }
58 
amdgpu_set_pixmap_bo(PixmapPtr pPix,struct amdgpu_buffer * bo)59 static inline Bool amdgpu_set_pixmap_bo(PixmapPtr pPix, struct amdgpu_buffer *bo)
60 {
61 	ScrnInfoPtr scrn = xf86ScreenToScrn(pPix->drawable.pScreen);
62 	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn);
63 	struct amdgpu_pixmap *priv;
64 
65 	priv = amdgpu_get_pixmap_private(pPix);
66 	if (!priv && !bo)
67 		return TRUE;
68 
69 	if (priv) {
70 		if (priv->bo) {
71 			if (priv->bo == bo)
72 				return TRUE;
73 
74 			amdgpu_bo_unref(&priv->bo);
75 			priv->handle_valid = FALSE;
76 		}
77 
78 		drmmode_fb_reference(pAMDGPUEnt->fd, &priv->fb, NULL);
79 
80 		if (!bo) {
81 			free(priv);
82 			priv = NULL;
83 		}
84 	}
85 
86 	if (bo) {
87 		if (!priv) {
88 			priv = calloc(1, sizeof(struct amdgpu_pixmap));
89 			if (!priv)
90 				return FALSE;
91 		}
92 		amdgpu_bo_ref(bo);
93 		priv->bo = bo;
94 	}
95 
96 	amdgpu_set_pixmap_private(pPix, priv);
97 	return TRUE;
98 }
99 
amdgpu_get_pixmap_bo(PixmapPtr pPix)100 static inline struct amdgpu_buffer *amdgpu_get_pixmap_bo(PixmapPtr pPix)
101 {
102 	struct amdgpu_pixmap *priv;
103 	priv = amdgpu_get_pixmap_private(pPix);
104 	return priv ? priv->bo : NULL;
105 }
106 
107 static inline struct drmmode_fb*
amdgpu_fb_create(ScrnInfoPtr scrn,int drm_fd,uint32_t width,uint32_t height,uint32_t pitch,uint32_t handle)108 amdgpu_fb_create(ScrnInfoPtr scrn, int drm_fd, uint32_t width, uint32_t height,
109 		 uint32_t pitch, uint32_t handle)
110 {
111 	struct drmmode_fb *fb  = malloc(sizeof(*fb));
112 
113 	if (!fb)
114 		return NULL;
115 
116 	fb->refcnt = 1;
117 	if (drmModeAddFB(drm_fd, width, height, scrn->depth, scrn->bitsPerPixel,
118 			 pitch, handle, &fb->handle) == 0)
119 		return fb;
120 
121 	free(fb);
122 	return NULL;
123 }
124 
125 static inline struct drmmode_fb**
amdgpu_pixmap_get_fb_ptr(PixmapPtr pix)126 amdgpu_pixmap_get_fb_ptr(PixmapPtr pix)
127 {
128 	ScrnInfoPtr scrn = xf86ScreenToScrn(pix->drawable.pScreen);
129 	AMDGPUInfoPtr info = AMDGPUPTR(scrn);
130 
131 	if (info->use_glamor) {
132 		struct amdgpu_pixmap *priv = amdgpu_get_pixmap_private(pix);
133 
134 		if (!priv)
135 			return NULL;
136 
137 		return &priv->fb;
138 	}
139 
140 	return NULL;
141 }
142 
143 static inline struct drmmode_fb*
amdgpu_pixmap_get_fb(PixmapPtr pix)144 amdgpu_pixmap_get_fb(PixmapPtr pix)
145 {
146 	struct drmmode_fb **fb_ptr = amdgpu_pixmap_get_fb_ptr(pix);
147 	uint32_t handle;
148 
149 	if (fb_ptr && *fb_ptr)
150 		return *fb_ptr;
151 
152 	if (amdgpu_pixmap_get_handle(pix, &handle)) {
153 		ScrnInfoPtr scrn = xf86ScreenToScrn(pix->drawable.pScreen);
154 		AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn);
155 
156 		if (!fb_ptr)
157 			fb_ptr = amdgpu_pixmap_get_fb_ptr(pix);
158 
159 		*fb_ptr = amdgpu_fb_create(scrn, pAMDGPUEnt->fd,
160 					   pix->drawable.width,
161 					   pix->drawable.height, pix->devKind,
162 					   handle);
163 	}
164 
165 	return *fb_ptr;
166 }
167 
168 enum {
169 	AMDGPU_CREATE_PIXMAP_DRI2    = 0x08000000,
170 	AMDGPU_CREATE_PIXMAP_LINEAR  = 0x04000000,
171 	AMDGPU_CREATE_PIXMAP_SCANOUT = 0x02000000,
172 	AMDGPU_CREATE_PIXMAP_GTT     = 0x01000000,
173 };
174 
175 extern Bool amdgpu_pixmap_init(ScreenPtr screen);
176 
177 #endif /* AMDGPU_PIXMAP_H */
178