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