1 #include "frontend/drm_driver.h"
2 #include "i915_drm_winsys.h"
3 #include "util/u_memory.h"
4
5 #include "drm-uapi/i915_drm.h"
6
i915_drm_type_to_name(enum i915_winsys_buffer_type type)7 static char *i915_drm_type_to_name(enum i915_winsys_buffer_type type)
8 {
9 char *name;
10
11 if (type == I915_NEW_TEXTURE) {
12 name = "gallium3d_texture";
13 } else if (type == I915_NEW_VERTEX) {
14 name = "gallium3d_vertex";
15 } else if (type == I915_NEW_SCANOUT) {
16 name = "gallium3d_scanout";
17 } else {
18 assert(0);
19 name = "gallium3d_unknown";
20 }
21
22 return name;
23 }
24
25 static struct i915_winsys_buffer *
i915_drm_buffer_create(struct i915_winsys * iws,unsigned size,enum i915_winsys_buffer_type type)26 i915_drm_buffer_create(struct i915_winsys *iws,
27 unsigned size,
28 enum i915_winsys_buffer_type type)
29 {
30 struct i915_drm_buffer *buf = CALLOC_STRUCT(i915_drm_buffer);
31 struct i915_drm_winsys *idws = i915_drm_winsys(iws);
32
33 if (!buf)
34 return NULL;
35
36 buf->magic = 0xDEAD1337;
37 buf->flinked = false;
38 buf->flink = 0;
39
40 buf->bo = drm_intel_bo_alloc(idws->gem_manager,
41 i915_drm_type_to_name(type), size, 0);
42
43 if (!buf->bo)
44 goto err;
45
46 return (struct i915_winsys_buffer *)buf;
47
48 err:
49 assert(0);
50 FREE(buf);
51 return NULL;
52 }
53
54 static struct i915_winsys_buffer *
i915_drm_buffer_create_tiled(struct i915_winsys * iws,unsigned * stride,unsigned height,enum i915_winsys_buffer_tile * tiling,enum i915_winsys_buffer_type type)55 i915_drm_buffer_create_tiled(struct i915_winsys *iws,
56 unsigned *stride, unsigned height,
57 enum i915_winsys_buffer_tile *tiling,
58 enum i915_winsys_buffer_type type)
59 {
60 struct i915_drm_buffer *buf = CALLOC_STRUCT(i915_drm_buffer);
61 struct i915_drm_winsys *idws = i915_drm_winsys(iws);
62 unsigned long pitch = 0;
63 uint32_t tiling_mode = *tiling;
64
65 if (!buf)
66 return NULL;
67
68 buf->magic = 0xDEAD1337;
69 buf->flinked = false;
70 buf->flink = 0;
71
72 buf->bo = drm_intel_bo_alloc_tiled(idws->gem_manager,
73 i915_drm_type_to_name(type),
74 *stride, height, 1,
75 &tiling_mode, &pitch, 0);
76
77 if (!buf->bo)
78 goto err;
79
80 *stride = pitch;
81 *tiling = tiling_mode;
82 return (struct i915_winsys_buffer *)buf;
83
84 err:
85 assert(0);
86 FREE(buf);
87 return NULL;
88 }
89
90 static struct i915_winsys_buffer *
i915_drm_buffer_from_handle(struct i915_winsys * iws,struct winsys_handle * whandle,unsigned height,enum i915_winsys_buffer_tile * tiling,unsigned * stride)91 i915_drm_buffer_from_handle(struct i915_winsys *iws,
92 struct winsys_handle *whandle,
93 unsigned height,
94 enum i915_winsys_buffer_tile *tiling,
95 unsigned *stride)
96 {
97 struct i915_drm_winsys *idws = i915_drm_winsys(iws);
98 struct i915_drm_buffer *buf;
99 uint32_t tile = 0, swizzle = 0;
100
101 if ((whandle->type != WINSYS_HANDLE_TYPE_SHARED) && (whandle->type != WINSYS_HANDLE_TYPE_FD))
102 return NULL;
103
104 if (whandle->offset != 0)
105 return NULL;
106
107 buf = CALLOC_STRUCT(i915_drm_buffer);
108 if (!buf)
109 return NULL;
110
111 buf->magic = 0xDEAD1337;
112
113 if (whandle->type == WINSYS_HANDLE_TYPE_SHARED)
114 buf->bo = drm_intel_bo_gem_create_from_name(idws->gem_manager, "gallium3d_from_handle", whandle->handle);
115 else if (whandle->type == WINSYS_HANDLE_TYPE_FD) {
116 int fd = (int) whandle->handle;
117 buf->bo = drm_intel_bo_gem_create_from_prime(idws->gem_manager, fd, height * whandle->stride);
118 }
119
120 buf->flinked = true;
121 buf->flink = whandle->handle;
122
123 if (!buf->bo)
124 goto err;
125
126 drm_intel_bo_get_tiling(buf->bo, &tile, &swizzle);
127
128 *stride = whandle->stride;
129 *tiling = tile;
130
131 return (struct i915_winsys_buffer *)buf;
132
133 err:
134 FREE(buf);
135 return NULL;
136 }
137
138 static bool
i915_drm_buffer_get_handle(struct i915_winsys * iws,struct i915_winsys_buffer * buffer,struct winsys_handle * whandle,unsigned stride)139 i915_drm_buffer_get_handle(struct i915_winsys *iws,
140 struct i915_winsys_buffer *buffer,
141 struct winsys_handle *whandle,
142 unsigned stride)
143 {
144 struct i915_drm_buffer *buf = i915_drm_buffer(buffer);
145
146 if (whandle->type == WINSYS_HANDLE_TYPE_SHARED) {
147 if (!buf->flinked) {
148 if (drm_intel_bo_flink(buf->bo, &buf->flink))
149 return false;
150 buf->flinked = true;
151 }
152
153 whandle->handle = buf->flink;
154 } else if (whandle->type == WINSYS_HANDLE_TYPE_KMS) {
155 whandle->handle = buf->bo->handle;
156 } else if (whandle->type == WINSYS_HANDLE_TYPE_FD) {
157 int fd;
158
159 if (drm_intel_bo_gem_export_to_prime(buf->bo, &fd))
160 return false;
161 whandle->handle = fd;
162 } else {
163 assert(!"unknown usage");
164 return false;
165 }
166
167 whandle->stride = stride;
168 return true;
169 }
170
171 static void *
i915_drm_buffer_map(struct i915_winsys * iws,struct i915_winsys_buffer * buffer,bool write)172 i915_drm_buffer_map(struct i915_winsys *iws,
173 struct i915_winsys_buffer *buffer,
174 bool write)
175 {
176 struct i915_drm_buffer *buf = i915_drm_buffer(buffer);
177 drm_intel_bo *bo = intel_bo(buffer);
178 int ret = 0;
179
180 assert(bo);
181
182 if (buf->map_count)
183 goto out;
184
185 ret = drm_intel_gem_bo_map_gtt(bo);
186
187 buf->ptr = bo->virtual;
188
189 assert(ret == 0);
190 out:
191 if (ret)
192 return NULL;
193
194 buf->map_count++;
195 return buf->ptr;
196 }
197
198 static void
i915_drm_buffer_unmap(struct i915_winsys * iws,struct i915_winsys_buffer * buffer)199 i915_drm_buffer_unmap(struct i915_winsys *iws,
200 struct i915_winsys_buffer *buffer)
201 {
202 struct i915_drm_buffer *buf = i915_drm_buffer(buffer);
203
204 if (--buf->map_count)
205 return;
206
207 drm_intel_gem_bo_unmap_gtt(intel_bo(buffer));
208 }
209
210 static int
i915_drm_buffer_write(struct i915_winsys * iws,struct i915_winsys_buffer * buffer,size_t offset,size_t size,const void * data)211 i915_drm_buffer_write(struct i915_winsys *iws,
212 struct i915_winsys_buffer *buffer,
213 size_t offset,
214 size_t size,
215 const void *data)
216 {
217 struct i915_drm_buffer *buf = i915_drm_buffer(buffer);
218
219 return drm_intel_bo_subdata(buf->bo, offset, size, (void*)data);
220 }
221
222 static void
i915_drm_buffer_destroy(struct i915_winsys * iws,struct i915_winsys_buffer * buffer)223 i915_drm_buffer_destroy(struct i915_winsys *iws,
224 struct i915_winsys_buffer *buffer)
225 {
226 drm_intel_bo_unreference(intel_bo(buffer));
227
228 #ifdef DEBUG
229 i915_drm_buffer(buffer)->magic = 0;
230 i915_drm_buffer(buffer)->bo = NULL;
231 #endif
232
233 FREE(buffer);
234 }
235
236 static bool
i915_drm_buffer_is_busy(struct i915_winsys * iws,struct i915_winsys_buffer * buffer)237 i915_drm_buffer_is_busy(struct i915_winsys *iws,
238 struct i915_winsys_buffer *buffer)
239 {
240 struct i915_drm_buffer* i915_buffer = i915_drm_buffer(buffer);
241 if (!i915_buffer)
242 return false;
243 return drm_intel_bo_busy(i915_buffer->bo);
244 }
245
246
247 void
i915_drm_winsys_init_buffer_functions(struct i915_drm_winsys * idws)248 i915_drm_winsys_init_buffer_functions(struct i915_drm_winsys *idws)
249 {
250 idws->base.buffer_create = i915_drm_buffer_create;
251 idws->base.buffer_create_tiled = i915_drm_buffer_create_tiled;
252 idws->base.buffer_from_handle = i915_drm_buffer_from_handle;
253 idws->base.buffer_get_handle = i915_drm_buffer_get_handle;
254 idws->base.buffer_map = i915_drm_buffer_map;
255 idws->base.buffer_unmap = i915_drm_buffer_unmap;
256 idws->base.buffer_write = i915_drm_buffer_write;
257 idws->base.buffer_destroy = i915_drm_buffer_destroy;
258 idws->base.buffer_is_busy = i915_drm_buffer_is_busy;
259 }
260