texenvprogram: fix for ARB_draw_buffers.
[mesa.git] / src / gallium / winsys / drm / intel / gem / intel_drm_batchbuffer.c
1
2 #include "intel_drm_winsys.h"
3 #include "util/u_memory.h"
4
5 #include "i915_drm.h"
6
7 #define BATCH_RESERVED 16
8
9 #define INTEL_DEFAULT_RELOCS 100
10 #define INTEL_MAX_RELOCS 400
11
12 #define INTEL_BATCH_NO_CLIPRECTS 0x1
13 #define INTEL_BATCH_CLIPRECTS 0x2
14
15 #undef INTEL_RUN_SYNC
16 #undef INTEL_MAP_BATCHBUFFER
17 #undef INTEL_MAP_GTT
18 #define INTEL_ALWAYS_FLUSH
19
20 struct intel_drm_batchbuffer
21 {
22 struct intel_batchbuffer base;
23
24 size_t actual_size;
25
26 drm_intel_bo *bo;
27 };
28
29 static INLINE struct intel_drm_batchbuffer *
30 intel_drm_batchbuffer(struct intel_batchbuffer *batch)
31 {
32 return (struct intel_drm_batchbuffer *)batch;
33 }
34
35 static void
36 intel_drm_batchbuffer_reset(struct intel_drm_batchbuffer *batch)
37 {
38 struct intel_drm_winsys *idws = intel_drm_winsys(batch->base.iws);
39 int ret;
40
41 if (batch->bo)
42 drm_intel_bo_unreference(batch->bo);
43 batch->bo = drm_intel_bo_alloc(idws->pools.gem,
44 "gallium3d_batchbuffer",
45 batch->actual_size,
46 4096);
47
48 #ifdef INTEL_MAP_BATCHBUFFER
49 #ifdef INTEL_MAP_GTT
50 ret = drm_intel_gem_bo_map_gtt(batch->bo);
51 #else
52 ret = drm_intel_bo_map(batch->bo, TRUE);
53 #endif
54 assert(ret == 0);
55 batch->base.map = batch->bo->virtual;
56 #else
57 (void)ret;
58 #endif
59
60 memset(batch->base.map, 0, batch->actual_size);
61 batch->base.ptr = batch->base.map;
62 batch->base.size = batch->actual_size - BATCH_RESERVED;
63 batch->base.relocs = 0;
64 }
65
66 static struct intel_batchbuffer *
67 intel_drm_batchbuffer_create(struct intel_winsys *iws)
68 {
69 struct intel_drm_winsys *idws = intel_drm_winsys(iws);
70 struct intel_drm_batchbuffer *batch = CALLOC_STRUCT(intel_drm_batchbuffer);
71
72 batch->actual_size = idws->max_batch_size;
73
74 #ifdef INTEL_MAP_BATCHBUFFER
75 batch->base.map = NULL;
76 #else
77 batch->base.map = MALLOC(batch->actual_size);
78 #endif
79 batch->base.ptr = NULL;
80 batch->base.size = 0;
81
82 batch->base.relocs = 0;
83 batch->base.max_relocs = 300;/*INTEL_DEFAULT_RELOCS;*/
84
85 batch->base.iws = iws;
86
87 intel_drm_batchbuffer_reset(batch);
88
89 return &batch->base;
90 }
91
92 static int
93 intel_drm_batchbuffer_reloc(struct intel_batchbuffer *ibatch,
94 struct intel_buffer *buffer,
95 enum intel_buffer_usage usage,
96 unsigned pre_add)
97 {
98 struct intel_drm_batchbuffer *batch = intel_drm_batchbuffer(ibatch);
99 unsigned write_domain = 0;
100 unsigned read_domain = 0;
101 unsigned offset;
102 int ret = 0;
103
104 assert(batch->base.relocs < batch->base.max_relocs);
105
106 if (usage == INTEL_USAGE_SAMPLER) {
107 write_domain = 0;
108 read_domain = I915_GEM_DOMAIN_SAMPLER;
109
110 } else if (usage == INTEL_USAGE_RENDER) {
111 write_domain = I915_GEM_DOMAIN_RENDER;
112 read_domain = I915_GEM_DOMAIN_RENDER;
113
114 } else if (usage == INTEL_USAGE_2D_TARGET) {
115 write_domain = I915_GEM_DOMAIN_RENDER;
116 read_domain = I915_GEM_DOMAIN_RENDER;
117
118 } else if (usage == INTEL_USAGE_2D_SOURCE) {
119 write_domain = 0;
120 read_domain = I915_GEM_DOMAIN_RENDER;
121
122 } else if (usage == INTEL_USAGE_VERTEX) {
123 write_domain = 0;
124 read_domain = I915_GEM_DOMAIN_VERTEX;
125
126 } else {
127 assert(0);
128 return -1;
129 }
130
131 offset = (unsigned)(batch->base.ptr - batch->base.map);
132
133 ret = drm_intel_bo_emit_reloc(batch->bo, offset,
134 intel_bo(buffer), pre_add,
135 read_domain,
136 write_domain);
137
138 ((uint32_t*)batch->base.ptr)[0] = intel_bo(buffer)->offset + pre_add;
139 batch->base.ptr += 4;
140
141 if (!ret)
142 batch->base.relocs++;
143
144 return ret;
145 }
146
147 static void
148 intel_drm_batchbuffer_flush(struct intel_batchbuffer *ibatch,
149 struct pipe_fence_handle **fence)
150 {
151 struct intel_drm_batchbuffer *batch = intel_drm_batchbuffer(ibatch);
152 unsigned used = 0;
153 int ret = 0;
154 int i;
155
156 assert(intel_batchbuffer_space(ibatch) >= 0);
157
158 used = batch->base.ptr - batch->base.map;
159 assert((used & 3) == 0);
160
161
162 #ifdef INTEL_ALWAYS_FLUSH
163 /* MI_FLUSH | FLUSH_MAP_CACHE */
164 intel_batchbuffer_dword(ibatch, (0x4<<23)|(1<<0));
165 used += 4;
166 #endif
167
168 if ((used & 4) == 0) {
169 /* MI_NOOP */
170 intel_batchbuffer_dword(ibatch, 0);
171 }
172 /* MI_BATCH_BUFFER_END */
173 intel_batchbuffer_dword(ibatch, (0xA<<23));
174
175 used = batch->base.ptr - batch->base.map;
176 assert((used & 4) == 0);
177
178 #ifdef INTEL_MAP_BATCHBUFFER
179 #ifdef INTEL_MAP_GTT
180 drm_intel_gem_bo_unmap_gtt(batch->bo);
181 #else
182 drm_intel_bo_unmap(batch->bo);
183 #endif
184 #else
185 drm_intel_bo_subdata(batch->bo, 0, used, batch->base.map);
186 #endif
187
188 /* Do the sending to HW */
189 ret = drm_intel_bo_exec(batch->bo, used, NULL, 0, 0);
190 assert(ret == 0);
191
192 if (intel_drm_winsys(ibatch->iws)->dump_cmd) {
193 unsigned *ptr;
194 drm_intel_bo_map(batch->bo, FALSE);
195 ptr = (unsigned*)batch->bo->virtual;
196
197 debug_printf("%s:\n", __func__);
198 for (i = 0; i < used / 4; i++, ptr++) {
199 debug_printf("\t%08x: %08x\n", i*4, *ptr);
200 }
201
202 drm_intel_bo_unmap(batch->bo);
203 } else {
204 #ifdef INTEL_RUN_SYNC
205 drm_intel_bo_map(batch->bo, FALSE);
206 drm_intel_bo_unmap(batch->bo);
207 #endif
208 }
209
210 if (fence) {
211 ibatch->iws->fence_reference(ibatch->iws, fence, NULL);
212
213 #ifdef INTEL_RUN_SYNC
214 /* we run synced to GPU so just pass null */
215 (*fence) = intel_drm_fence_create(NULL);
216 #else
217 (*fence) = intel_drm_fence_create(batch->bo);
218 #endif
219 }
220
221 intel_drm_batchbuffer_reset(batch);
222 }
223
224 static void
225 intel_drm_batchbuffer_destroy(struct intel_batchbuffer *ibatch)
226 {
227 struct intel_drm_batchbuffer *batch = intel_drm_batchbuffer(ibatch);
228
229 if (batch->bo)
230 drm_intel_bo_unreference(batch->bo);
231
232 #ifndef INTEL_MAP_BATCHBUFFER
233 FREE(batch->base.map);
234 #endif
235 FREE(batch);
236 }
237
238 void intel_drm_winsys_init_batchbuffer_functions(struct intel_drm_winsys *idws)
239 {
240 idws->base.batchbuffer_create = intel_drm_batchbuffer_create;
241 idws->base.batchbuffer_reloc = intel_drm_batchbuffer_reloc;
242 idws->base.batchbuffer_flush = intel_drm_batchbuffer_flush;
243 idws->base.batchbuffer_destroy = intel_drm_batchbuffer_destroy;
244 }