Merge branch '7.8'
[mesa.git] / src / gallium / winsys / i965 / drm / i965_drm_buffer.c
1
2 #include "state_tracker/drm_api.h"
3 #include "i965_drm_winsys.h"
4 #include "util/u_memory.h"
5 #include "util/u_inlines.h"
6
7 #include "i915_drm.h"
8 #include "intel_bufmgr.h"
9
10
11
12 const char *names[BRW_BUFFER_TYPE_MAX] = {
13 "TEXTURE",
14 "SCANOUT",
15 "VERTEX",
16 "CURBE",
17 "QUERY",
18 "SHADER_CONSTANTS",
19 "WM_SCRATCH",
20 "BATCH",
21 "GENERAL_STATE",
22 "SURFACE_STATE",
23 "PIXEL",
24 "GENERIC",
25 };
26
27 const char *usages[BRW_USAGE_MAX] = {
28 "STATE",
29 "QUERY_RESULT",
30 "RENDER_TARGET",
31 "DEPTH_BUFFER",
32 "BLIT_SOURCE",
33 "BLIT_DEST",
34 "SAMPLER",
35 "VERTEX",
36 "SCRATCH"
37 };
38
39
40 const char *data_types[BRW_DATA_MAX] =
41 {
42 "GS: CC_VP",
43 "GS: CC_UNIT",
44 "GS: WM_PROG",
45 "GS: SAMPLER_DEFAULT_COLOR",
46 "GS: SAMPLER",
47 "GS: WM_UNIT",
48 "GS: SF_PROG",
49 "GS: SF_VP",
50 "GS: SF_UNIT",
51 "GS: VS_UNIT",
52 "GS: VS_PROG",
53 "GS: GS_UNIT",
54 "GS: GS_PROG",
55 "GS: CLIP_VP",
56 "GS: CLIP_UNIT",
57 "GS: CLIP_PROG",
58 "SS: SURFACE",
59 "SS: SURF_BIND",
60 "CONSTANT DATA",
61 "BATCH DATA",
62 "(untyped)"
63 };
64
65 static enum pipe_error
66 i965_libdrm_bo_alloc(struct brw_winsys_screen *sws,
67 enum brw_buffer_type type,
68 unsigned size,
69 unsigned alignment,
70 struct brw_winsys_buffer **bo_out)
71 {
72 struct i965_libdrm_winsys *idws = i965_libdrm_winsys(sws);
73 struct i965_libdrm_buffer *buf;
74
75 if (BRW_DUMP)
76 debug_printf("%s type %s sz %d align %d\n",
77 __FUNCTION__, names[type], size, alignment );
78
79 buf = CALLOC_STRUCT(i965_libdrm_buffer);
80 if (!buf)
81 return PIPE_ERROR_OUT_OF_MEMORY;
82
83 switch (type) {
84 case BRW_BUFFER_TYPE_TEXTURE:
85 /* case BRW_BUFFER_TYPE_SCANOUT:*/
86 case BRW_BUFFER_TYPE_VERTEX:
87 case BRW_BUFFER_TYPE_CURBE:
88 case BRW_BUFFER_TYPE_QUERY:
89 case BRW_BUFFER_TYPE_SHADER_CONSTANTS:
90 case BRW_BUFFER_TYPE_SHADER_SCRATCH:
91 case BRW_BUFFER_TYPE_BATCH:
92 case BRW_BUFFER_TYPE_GENERAL_STATE:
93 case BRW_BUFFER_TYPE_SURFACE_STATE:
94 case BRW_BUFFER_TYPE_PIXEL:
95 case BRW_BUFFER_TYPE_GENERIC:
96 break;
97 case BRW_BUFFER_TYPE_SCANOUT:
98 buf->map_gtt = TRUE;
99 break;
100 default:
101 assert(0);
102 break;
103 }
104
105 buf->bo = drm_intel_bo_alloc(idws->gem,
106 names[type],
107 size,
108 alignment);
109
110 if (!buf->bo)
111 goto err;
112
113 pipe_reference_init(&buf->base.reference, 1);
114 buf->base.size = size;
115 buf->base.sws = sws;
116
117 *bo_out = &buf->base;
118 return PIPE_OK;
119
120 err:
121 assert(0);
122 FREE(buf);
123 return PIPE_ERROR_OUT_OF_MEMORY;
124 }
125
126 static enum pipe_error
127 i965_libdrm_bo_from_handle(struct brw_winsys_screen *sws,
128 struct winsys_handle *whandle,
129 unsigned *stride,
130 unsigned *tile,
131 struct brw_winsys_buffer **bo_out)
132 {
133 struct i965_libdrm_winsys *idws = i965_libdrm_winsys(sws);
134 struct i965_libdrm_buffer *buf = CALLOC_STRUCT(i965_libdrm_buffer);
135 uint32_t swizzle = 0;
136
137 if (BRW_DUMP)
138 debug_printf("%s\n", __FUNCTION__);
139
140 if (!buf)
141 return PIPE_ERROR_OUT_OF_MEMORY;
142
143 pipe_reference_init(&buf->base.reference, 1);
144 buf->bo = drm_intel_bo_gem_create_from_name(idws->gem, "FROM_HANDLE", whandle->handle);
145 buf->base.size = buf->bo->size;
146 buf->base.sws = &idws->base;
147 buf->flinked = TRUE;
148 buf->flink = whandle->handle;
149
150
151 if (!buf->bo)
152 goto err;
153
154 drm_intel_bo_get_tiling(buf->bo, &buf->tiling, &swizzle);
155 if (buf->tiling != 0)
156 buf->map_gtt = TRUE;
157
158 *tile = buf->tiling;
159 *stride = whandle->stride;
160
161 *bo_out = &buf->base;
162 return PIPE_OK;
163
164 err:
165 FREE(buf);
166 return PIPE_ERROR_OUT_OF_MEMORY;
167 }
168
169 static enum pipe_error
170 i965_libdrm_bo_get_handle(struct brw_winsys_buffer *buffer,
171 struct winsys_handle *whandle,
172 unsigned stride)
173 {
174 struct i965_libdrm_buffer *buf = i965_libdrm_buffer(buffer);
175
176 if (BRW_DUMP)
177 debug_printf("%s\n", __FUNCTION__);
178
179 if (whandle->type == DRM_API_HANDLE_TYPE_SHARED) {
180 if (!buf->flinked) {
181 if (drm_intel_bo_flink(buf->bo, &buf->flink))
182 return PIPE_ERROR_BAD_INPUT;
183 buf->flinked = TRUE;
184 }
185
186 whandle->handle = buf->flink;
187 } else if (whandle->type == DRM_API_HANDLE_TYPE_KMS) {
188 whandle->handle = buf->bo->handle;
189 } else {
190 assert(!"unknown usage");
191 return PIPE_ERROR_BAD_INPUT;
192 }
193
194 whandle->stride = stride;
195 return PIPE_OK;
196 }
197
198 static void
199 i965_libdrm_bo_destroy(struct brw_winsys_buffer *buffer)
200 {
201 struct i965_libdrm_buffer *buf = i965_libdrm_buffer(buffer);
202
203 if (BRW_DUMP)
204 debug_printf("%s\n", __FUNCTION__);
205
206 drm_intel_bo_unreference(buf->bo);
207 FREE(buffer);
208 }
209
210 static enum pipe_error
211 i965_libdrm_bo_emit_reloc(struct brw_winsys_buffer *buffer,
212 enum brw_buffer_usage usage,
213 unsigned delta,
214 unsigned offset,
215 struct brw_winsys_buffer *buffer2)
216 {
217 struct i965_libdrm_buffer *buf = i965_libdrm_buffer(buffer);
218 struct i965_libdrm_buffer *buf2 = i965_libdrm_buffer(buffer2);
219 int read, write;
220 int ret;
221
222 if (BRW_DUMP)
223 debug_printf("%s buf %p offset %x delta %x buf2 %p/%s/%s\n",
224 __FUNCTION__, (void *)buffer,
225 offset, delta,
226 (void *)buffer2, names[buf2->data_type], usages[usage]);
227
228 switch (usage) {
229 case BRW_USAGE_STATE:
230 read = I915_GEM_DOMAIN_INSTRUCTION;
231 write = 0;
232 break;
233 case BRW_USAGE_QUERY_RESULT:
234 read = I915_GEM_DOMAIN_INSTRUCTION;
235 write = I915_GEM_DOMAIN_INSTRUCTION;
236 break;
237 case BRW_USAGE_RENDER_TARGET:
238 read = I915_GEM_DOMAIN_RENDER;
239 write = 0;
240 break;
241 case BRW_USAGE_DEPTH_BUFFER:
242 read = I915_GEM_DOMAIN_RENDER;
243 write = I915_GEM_DOMAIN_RENDER;
244 break;
245 case BRW_USAGE_BLIT_SOURCE:
246 read = 0;
247 write = I915_GEM_DOMAIN_RENDER;
248 break;
249 case BRW_USAGE_BLIT_DEST:
250 read = I915_GEM_DOMAIN_RENDER;
251 write = I915_GEM_DOMAIN_RENDER;
252 break;
253 case BRW_USAGE_SAMPLER:
254 read = I915_GEM_DOMAIN_SAMPLER;
255 write = 0;
256 break;
257 case BRW_USAGE_VERTEX:
258 read = I915_GEM_DOMAIN_VERTEX;
259 write = 0;
260 break;
261 case BRW_USAGE_SCRATCH:
262 read = 0;
263 write = 0;
264 break;
265 default:
266 assert(0);
267 return -1;
268 }
269
270 /* Needed??
271 ((uint32_t *)buf->bo->virtual)[offset/4] = (delta +
272 buf2->bo->offset);
273 */
274
275 ret = dri_bo_emit_reloc( buf->bo, read, write, delta, offset, buf2->bo );
276 if (ret)
277 return -1;
278
279 return 0;
280 }
281
282 static enum pipe_error
283 i965_libdrm_bo_exec(struct brw_winsys_buffer *buffer,
284 unsigned bytes_used)
285 {
286 struct i965_libdrm_buffer *buf = i965_libdrm_buffer(buffer);
287 struct i965_libdrm_winsys *idws = i965_libdrm_winsys(buffer->sws);
288 int ret;
289
290 if (BRW_DUMP)
291 debug_printf("execute buffer %p, bytes %d\n", (void *)buffer, bytes_used);
292
293 if (idws->send_cmd) {
294 ret = dri_bo_exec(buf->bo, bytes_used, NULL, 0, 0);
295 if (ret)
296 return PIPE_ERROR;
297 }
298
299 return PIPE_OK;
300 }
301
302 static enum pipe_error
303 i965_libdrm_bo_subdata(struct brw_winsys_buffer *buffer,
304 enum brw_buffer_data_type data_type,
305 size_t offset,
306 size_t size,
307 const void *data,
308 const struct brw_winsys_reloc *reloc,
309 unsigned nr_reloc)
310 {
311 struct i965_libdrm_buffer *buf = i965_libdrm_buffer(buffer);
312 struct i965_libdrm_winsys *idws = i965_libdrm_winsys(buffer->sws);
313 int ret, i;
314
315 (void)data_type;
316
317 if (BRW_DUMP)
318 debug_printf("%s buf %p off %d sz %d %s relocs: %d\n",
319 __FUNCTION__,
320 (void *)buffer, offset, size,
321 data_types[data_type],
322 nr_reloc);
323
324 if (BRW_DUMP)
325 brw_dump_data( idws->id,
326 data_type,
327 buf->bo->offset + offset,
328 data, size );
329
330 /* XXX: use bo_map_gtt/memcpy/unmap_gtt under some circumstances???
331 */
332 ret = drm_intel_bo_subdata(buf->bo, offset, size, (void*)data);
333 if (ret)
334 return PIPE_ERROR;
335
336 for (i = 0; i < nr_reloc; i++) {
337 i965_libdrm_bo_emit_reloc(buffer, reloc[i].usage, reloc[i].delta,
338 reloc[i].offset, reloc[i].bo);
339 }
340
341 return PIPE_OK;
342 }
343
344 static boolean
345 i965_libdrm_bo_is_busy(struct brw_winsys_buffer *buffer)
346 {
347 struct i965_libdrm_buffer *buf = i965_libdrm_buffer(buffer);
348 boolean ret;
349
350 if (BRW_DUMP)
351 debug_printf("%s %p\n", __FUNCTION__, (void *)buffer);
352
353 ret = drm_intel_bo_busy(buf->bo);
354
355 if (BRW_DUMP)
356 debug_printf(" --> %d\n", ret);
357
358 return ret;
359 }
360
361 static boolean
362 i965_libdrm_bo_references(struct brw_winsys_buffer *a,
363 struct brw_winsys_buffer *b)
364 {
365 struct i965_libdrm_buffer *bufa = i965_libdrm_buffer(a);
366 struct i965_libdrm_buffer *bufb = i965_libdrm_buffer(b);
367 boolean ret;
368
369 if (BRW_DUMP)
370 debug_printf("%s %p %p\n", __FUNCTION__, (void *)a, (void *)b);
371
372 ret = drm_intel_bo_references(bufa->bo, bufb->bo);
373
374 if (BRW_DUMP)
375 debug_printf(" --> %d\n", ret);
376
377 return ret;
378 }
379
380 /* XXX: couldn't this be handled by returning true/false on
381 * bo_emit_reloc?
382 */
383 static enum pipe_error
384 i965_libdrm_check_aperture_space(struct brw_winsys_screen *iws,
385 struct brw_winsys_buffer **buffers,
386 unsigned count)
387 {
388 static drm_intel_bo *bos[128];
389 int i;
390 int ret;
391
392 if (BRW_DUMP)
393 debug_printf("%s\n", __FUNCTION__);
394
395 if (count > Elements(bos)) {
396 assert(0);
397 return FALSE;
398 }
399
400 for (i = 0; i < count; i++)
401 bos[i] = i965_libdrm_buffer(buffers[i])->bo;
402
403 /* XXX: converting from ??? to pipe_error:
404 */
405 ret = dri_bufmgr_check_aperture_space(bos, count);
406
407 if (BRW_DUMP)
408 debug_printf(" --> %d (ok == %d)\n", ret, PIPE_OK);
409
410 return ret;
411 }
412
413 static void *
414 i965_libdrm_bo_map(struct brw_winsys_buffer *buffer,
415 enum brw_buffer_data_type data_type,
416 unsigned offset,
417 unsigned length,
418 boolean write,
419 boolean discard,
420 boolean flush_explicit)
421 {
422 struct i965_libdrm_buffer *buf = i965_libdrm_buffer(buffer);
423 int ret;
424
425
426 if (BRW_DUMP)
427 debug_printf("%s %p %s %s\n", __FUNCTION__, (void *)buffer,
428 write ? "read/write" : "read",
429 write ? data_types[data_type] : "");
430
431 if (!buf->map_count) {
432 if (buf->map_gtt) {
433 ret = drm_intel_gem_bo_map_gtt(buf->bo);
434 if (ret)
435 return NULL;
436 }
437 else {
438 ret = drm_intel_bo_map(buf->bo, write);
439 if (ret)
440 return NULL;
441 }
442 }
443
444 buf->data_type = data_type;
445 buf->map_count++;
446 return buf->bo->virtual;
447 }
448
449 static void
450 i965_libdrm_bo_flush_range(struct brw_winsys_buffer *buffer,
451 unsigned offset,
452 unsigned length)
453 {
454 struct i965_libdrm_buffer *buf = i965_libdrm_buffer(buffer);
455 struct i965_libdrm_winsys *idws = i965_libdrm_winsys(buffer->sws);
456
457 if (BRW_DUMP)
458 debug_printf("%s %s offset %d len %d\n", __FUNCTION__,
459 data_types[buf->data_type],
460 offset, length);
461
462 if (BRW_DUMP)
463 brw_dump_data( idws->id,
464 buf->data_type,
465 buf->bo->offset + offset,
466 buf->bo->virtual + offset,
467 length );
468 }
469
470 static void
471 i965_libdrm_bo_unmap(struct brw_winsys_buffer *buffer)
472 {
473 struct i965_libdrm_buffer *buf = i965_libdrm_buffer(buffer);
474
475 if (BRW_DUMP)
476 debug_printf("%s\n", __FUNCTION__);
477
478 if (--buf->map_count > 0)
479 return;
480
481 if (buf->map_gtt)
482 drm_intel_gem_bo_unmap_gtt(buf->bo);
483 else
484 drm_intel_bo_unmap(buf->bo);
485 }
486
487 void
488 i965_libdrm_winsys_init_buffer_functions(struct i965_libdrm_winsys *idws)
489 {
490 idws->base.bo_alloc = i965_libdrm_bo_alloc;
491 idws->base.bo_from_handle = i965_libdrm_bo_from_handle;
492 idws->base.bo_get_handle = i965_libdrm_bo_get_handle;
493 idws->base.bo_destroy = i965_libdrm_bo_destroy;
494 idws->base.bo_emit_reloc = i965_libdrm_bo_emit_reloc;
495 idws->base.bo_exec = i965_libdrm_bo_exec;
496 idws->base.bo_subdata = i965_libdrm_bo_subdata;
497 idws->base.bo_is_busy = i965_libdrm_bo_is_busy;
498 idws->base.bo_references = i965_libdrm_bo_references;
499 idws->base.check_aperture_space = i965_libdrm_check_aperture_space;
500 idws->base.bo_map = i965_libdrm_bo_map;
501 idws->base.bo_flush_range = i965_libdrm_bo_flush_range;
502 idws->base.bo_unmap = i965_libdrm_bo_unmap;
503 }