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