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