Tizen 2.0 Release
[profile/ivi/osmesa.git] / src / gallium / winsys / i965 / drm / i965_drm_buffer.c
1
2 #include "state_tracker/drm_driver.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->base.pci_id,
326                      data_type,
327                      buf->bo->offset + offset, 
328                      data, size, buffer->sws->gen );
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->base.pci_id,
464                      buf->data_type,
465                      buf->bo->offset + offset, 
466                      (char*)buf->bo->virtual + offset, 
467                      length, buffer->sws->gen );
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 }