r600: remove unused offset_mod stuff
[mesa.git] / src / mesa / drivers / dri / r600 / r600_cmdbuf.c
1 /*
2 Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
3
4 The Weather Channel (TM) funded Tungsten Graphics to develop the
5 initial release of the Radeon 8500 driver under the XFree86 license.
6 This notice must be preserved.
7
8 Permission is hereby granted, free of charge, to any person obtaining
9 a copy of this software and associated documentation files (the
10 "Software"), to deal in the Software without restriction, including
11 without limitation the rights to use, copy, modify, merge, publish,
12 distribute, sublicense, and/or sell copies of the Software, and to
13 permit persons to whom the Software is furnished to do so, subject to
14 the following conditions:
15
16 The above copyright notice and this permission notice (including the
17 next paragraph) shall be included in all copies or substantial
18 portions of the Software.
19
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
24 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27
28 **************************************************************************/
29
30 /**
31 * Mostly coppied from \radeon\radeon_cs_legacy.c
32 */
33
34 #include <errno.h>
35
36 #include "main/glheader.h"
37 #include "main/state.h"
38 #include "main/imports.h"
39 #include "main/macros.h"
40 #include "main/context.h"
41 #include "main/simple_list.h"
42 #include "swrast/swrast.h"
43
44 #include "drm.h"
45 #include "radeon_drm.h"
46
47 #include "r600_context.h"
48 #include "radeon_reg.h"
49 #include "r600_cmdbuf.h"
50 #include "r600_emit.h"
51 #include "radeon_bocs_wrapper.h"
52 #include "radeon_mipmap_tree.h"
53 #include "radeon_reg.h"
54
55
56
57 static struct radeon_cs * r600_cs_create(struct radeon_cs_manager *csm,
58 uint32_t ndw)
59 {
60 struct radeon_cs *cs;
61
62 cs = (struct radeon_cs*)calloc(1, sizeof(struct radeon_cs));
63 if (cs == NULL) {
64 return NULL;
65 }
66 cs->csm = csm;
67 cs->ndw = (ndw + 0x3FF) & (~0x3FF);
68 cs->packets = (uint32_t*)malloc(4*cs->ndw);
69 if (cs->packets == NULL) {
70 free(cs);
71 return NULL;
72 }
73 cs->relocs_total_size = 0;
74 return cs;
75 }
76
77 int r600_cs_write_reloc(struct radeon_cs *cs,
78 struct radeon_bo *bo,
79 uint32_t read_domain,
80 uint32_t write_domain,
81 uint32_t flags)
82 {
83 struct r600_cs_reloc_legacy *relocs;
84 int i;
85
86 relocs = (struct r600_cs_reloc_legacy *)cs->relocs;
87 /* check domains */
88 if ((read_domain && write_domain) || (!read_domain && !write_domain)) {
89 /* in one CS a bo can only be in read or write domain but not
90 * in read & write domain at the same sime
91 */
92 return -EINVAL;
93 }
94 if (read_domain == RADEON_GEM_DOMAIN_CPU) {
95 return -EINVAL;
96 }
97 if (write_domain == RADEON_GEM_DOMAIN_CPU) {
98 return -EINVAL;
99 }
100 /* check if bo is already referenced */
101 for(i = 0; i < cs->crelocs; i++) {
102 uint32_t *indices;
103 uint32_t *reloc_indices;
104
105 if (relocs[i].base.bo->handle == bo->handle) {
106 /* Check domains must be in read or write. As we check already
107 * checked that in argument one of the read or write domain was
108 * set we only need to check that if previous reloc as the read
109 * domain set then the read_domain should also be set for this
110 * new relocation.
111 */
112 if (relocs[i].base.read_domain && !read_domain) {
113 return -EINVAL;
114 }
115 if (relocs[i].base.write_domain && !write_domain) {
116 return -EINVAL;
117 }
118 relocs[i].base.read_domain |= read_domain;
119 relocs[i].base.write_domain |= write_domain;
120 /* save indice */
121 relocs[i].cindices++;
122 indices = (uint32_t*)realloc(relocs[i].indices,
123 relocs[i].cindices * 4);
124 reloc_indices = (uint32_t*)realloc(relocs[i].reloc_indices,
125 relocs[i].cindices * 4);
126 if ( (indices == NULL) || (reloc_indices == NULL) ) {
127 relocs[i].cindices -= 1;
128 return -ENOMEM;
129 }
130 relocs[i].indices = indices;
131 relocs[i].reloc_indices = reloc_indices;
132 relocs[i].indices[relocs[i].cindices - 1] = cs->cdw - 1;
133 relocs[i].reloc_indices[relocs[i].cindices - 1] = cs->section_cdw;
134 cs->section_ndw += 2;
135 cs->section_cdw += 2;
136
137 return 0;
138 }
139 }
140 /* add bo to reloc */
141 relocs = (struct r600_cs_reloc_legacy*)
142 realloc(cs->relocs,
143 sizeof(struct r600_cs_reloc_legacy) * (cs->crelocs + 1));
144 if (relocs == NULL) {
145 return -ENOMEM;
146 }
147 cs->relocs = relocs;
148 relocs[cs->crelocs].base.bo = bo;
149 relocs[cs->crelocs].base.read_domain = read_domain;
150 relocs[cs->crelocs].base.write_domain = write_domain;
151 relocs[cs->crelocs].base.flags = flags;
152 relocs[cs->crelocs].indices = (uint32_t*)malloc(4);
153 relocs[cs->crelocs].reloc_indices = (uint32_t*)malloc(4);
154 if ( (relocs[cs->crelocs].indices == NULL) || (relocs[cs->crelocs].reloc_indices == NULL) )
155 {
156 return -ENOMEM;
157 }
158
159 relocs[cs->crelocs].indices[0] = cs->cdw - 1;
160 relocs[cs->crelocs].reloc_indices[0] = cs->section_cdw;
161 cs->section_ndw += 2;
162 cs->section_cdw += 2;
163 relocs[cs->crelocs].cindices = 1;
164 cs->relocs_total_size += radeon_bo_legacy_relocs_size(bo);
165 cs->crelocs++;
166
167 radeon_bo_ref(bo);
168
169 return 0;
170 }
171
172 static int r600_cs_begin(struct radeon_cs *cs,
173 uint32_t ndw,
174 const char *file,
175 const char *func,
176 int line)
177 {
178 if (cs->section) {
179 fprintf(stderr, "CS already in a section(%s,%s,%d)\n",
180 cs->section_file, cs->section_func, cs->section_line);
181 fprintf(stderr, "CS can't start section(%s,%s,%d)\n",
182 file, func, line);
183 return -EPIPE;
184 }
185
186 if (cs->cdw + ndw + 32 > cs->ndw) { /* Left 32 DWORD (8 offset+pitch) spare room for reloc indices */
187 uint32_t tmp, *ptr;
188 int num = (ndw > 0x3FF) ? ndw : 0x3FF;
189
190 tmp = (cs->cdw + 1 + num) & (~num);
191 ptr = (uint32_t*)realloc(cs->packets, 4 * tmp);
192 if (ptr == NULL) {
193 return -ENOMEM;
194 }
195 cs->packets = ptr;
196 cs->ndw = tmp;
197 }
198
199 cs->section = 1;
200 cs->section_ndw = 0;
201 cs->section_cdw = cs->cdw + ndw; /* start of reloc indices. */
202 cs->section_file = file;
203 cs->section_func = func;
204 cs->section_line = line;
205
206 return 0;
207 }
208
209 static int r600_cs_end(struct radeon_cs *cs,
210 const char *file,
211 const char *func,
212 int line)
213
214 {
215 if (!cs->section) {
216 fprintf(stderr, "CS no section to end at (%s,%s,%d)\n",
217 file, func, line);
218 return -EPIPE;
219 }
220 cs->section = 0;
221
222 if ( (cs->section_ndw + cs->cdw) != cs->section_cdw )
223 {
224 fprintf(stderr, "CS section size missmatch start at (%s,%s,%d) %d vs %d\n",
225 cs->section_file, cs->section_func, cs->section_line, cs->section_ndw, cs->section_cdw);
226 fprintf(stderr, "cs->section_ndw = %d, cs->cdw = %d, cs->section_cdw = %d \n",
227 cs->section_ndw, cs->cdw, cs->section_cdw);
228 fprintf(stderr, "CS section end at (%s,%s,%d)\n",
229 file, func, line);
230 return -EPIPE;
231 }
232
233 cs->cdw = cs->section_cdw;
234 return 0;
235 }
236
237 static int r600_cs_process_relocs(struct radeon_cs *cs,
238 uint32_t * reloc_chunk,
239 uint32_t * length_dw_reloc_chunk)
240 {
241 struct r600_cs_manager_legacy *csm = (struct r600_cs_manager_legacy*)cs->csm;
242 struct r600_cs_reloc_legacy *relocs;
243 int i, j, r;
244
245 uint32_t offset_dw = 0;
246
247 csm = (struct r600_cs_manager_legacy*)cs->csm;
248 relocs = (struct r600_cs_reloc_legacy *)cs->relocs;
249 restart:
250 for (i = 0; i < cs->crelocs; i++)
251 {
252 for (j = 0; j < relocs[i].cindices; j++)
253 {
254 uint32_t soffset, eoffset, asicoffset;
255
256 r = radeon_bo_legacy_validate(relocs[i].base.bo,
257 &soffset, &eoffset);
258 if (r == -EAGAIN)
259 {
260 goto restart;
261 }
262 if (r)
263 {
264 fprintf(stderr, "validated %p [0x%08X, 0x%08X]\n",
265 relocs[i].base.bo, soffset, eoffset);
266 return r;
267 }
268 asicoffset = soffset;
269 if (asicoffset >= eoffset)
270 {
271 /* radeon_bo_debug(relocs[i].base.bo, 12); */
272 fprintf(stderr, "validated %p [0x%08X, 0x%08X]\n",
273 relocs[i].base.bo, soffset, eoffset);
274 fprintf(stderr, "above end: %p 0x%08X 0x%08X\n",
275 relocs[i].base.bo,
276 cs->packets[relocs[i].indices[j]],
277 eoffset);
278 exit(0);
279 return -EINVAL;
280 }
281
282 /* pkt3 nop header in ib chunk */
283 cs->packets[relocs[i].reloc_indices[j]] = 0xC0001000;
284
285 /* reloc index in ib chunk */
286 cs->packets[relocs[i].reloc_indices[j] + 1] = offset_dw;
287
288 /* asic offset in reloc chunk */ /* see alex drm r600_nomm_relocate */
289 reloc_chunk[offset_dw] = asicoffset;
290 reloc_chunk[offset_dw + 3] = 0;
291
292 offset_dw += 4;
293 }
294 }
295
296 *length_dw_reloc_chunk = offset_dw;
297
298 return 0;
299 }
300
301 static int r600_cs_set_age(struct radeon_cs *cs) /* -------------- */
302 {
303 struct r600_cs_manager_legacy *csm = (struct r600_cs_manager_legacy*)cs->csm;
304 struct r600_cs_reloc_legacy *relocs;
305 int i;
306
307 relocs = (struct r600_cs_reloc_legacy *)cs->relocs;
308 for (i = 0; i < cs->crelocs; i++) {
309 radeon_bo_legacy_pending(relocs[i].base.bo, csm->pending_age);
310 radeon_bo_unref(relocs[i].base.bo);
311 }
312 return 0;
313 }
314
315 static void dump_cmdbuf(struct radeon_cs *cs)
316 {
317 int i;
318 fprintf(stderr,"--start--\n");
319 for (i = 0; i < cs->cdw; i++){
320 fprintf(stderr,"0x%08x\n", cs->packets[i]);
321 }
322 fprintf(stderr,"--end--\n");
323
324 }
325
326 static int r600_cs_emit(struct radeon_cs *cs)
327 {
328 struct r600_cs_manager_legacy *csm = (struct r600_cs_manager_legacy*)cs->csm;
329 struct drm_radeon_cs cs_cmd;
330 struct drm_radeon_cs_chunk cs_chunk[2];
331 uint32_t length_dw_reloc_chunk;
332 uint64_t chunk_ptrs[2];
333 uint32_t reloc_chunk[128];
334 int r;
335 int retry = 0;
336
337 /* TODO : put chip level things here if need. */
338 /* csm->ctx->vtbl.emit_cs_header(cs, csm->ctx); */
339
340 csm->pending_count = 1;
341
342 r = r600_cs_process_relocs(cs, &(reloc_chunk[0]), &length_dw_reloc_chunk);
343 if (r) {
344 return 0;
345 }
346
347 /* raw ib chunk */
348 cs_chunk[0].chunk_id = RADEON_CHUNK_ID_IB;
349 cs_chunk[0].length_dw = cs->cdw;
350 cs_chunk[0].chunk_data = (unsigned long)(cs->packets);
351
352 /* reloc chaunk */
353 cs_chunk[1].chunk_id = RADEON_CHUNK_ID_RELOCS;
354 cs_chunk[1].length_dw = length_dw_reloc_chunk;
355 cs_chunk[1].chunk_data = (unsigned long)&(reloc_chunk[0]);
356
357 chunk_ptrs[0] = (uint64_t)(unsigned long)&(cs_chunk[0]);
358 chunk_ptrs[1] = (uint64_t)(unsigned long)&(cs_chunk[1]);
359
360 cs_cmd.num_chunks = 2;
361 /* cs_cmd.cs_id = 0; */
362 cs_cmd.chunks = (uint64_t)(unsigned long)chunk_ptrs;
363
364 //dump_cmdbuf(cs);
365
366 do
367 {
368 r = drmCommandWriteRead(cs->csm->fd, DRM_RADEON_CS, &cs_cmd, sizeof(cs_cmd));
369 retry++;
370 } while (r == -EAGAIN && retry < 1000);
371
372 if (r) {
373 return r;
374 }
375
376 csm->pending_age = cs_cmd.cs_id;
377
378 r600_cs_set_age(cs);
379
380 cs->csm->read_used = 0;
381 cs->csm->vram_write_used = 0;
382 cs->csm->gart_write_used = 0;
383
384 return 0;
385 }
386
387 static void inline r600_cs_free_reloc(void *relocs_p, int crelocs)
388 {
389 struct r600_cs_reloc_legacy *relocs = relocs_p;
390 int i;
391 if (!relocs_p)
392 return;
393 for (i = 0; i < crelocs; i++)
394 {
395 free(relocs[i].indices);
396 free(relocs[i].reloc_indices);
397 }
398 }
399
400 static int r600_cs_destroy(struct radeon_cs *cs)
401 {
402 r600_cs_free_reloc(cs->relocs, cs->crelocs);
403 free(cs->relocs);
404 free(cs->packets);
405 free(cs);
406 return 0;
407 }
408
409 static int r600_cs_erase(struct radeon_cs *cs)
410 {
411 r600_cs_free_reloc(cs->relocs, cs->crelocs);
412 free(cs->relocs);
413 cs->relocs_total_size = 0;
414 cs->relocs = NULL;
415 cs->crelocs = 0;
416 cs->cdw = 0;
417 cs->section = 0;
418 return 0;
419 }
420
421 static int r600_cs_need_flush(struct radeon_cs *cs)
422 {
423 /* this function used to flush when the BO usage got to
424 * a certain size, now the higher levels handle this better */
425 return 0;
426 }
427
428 static void r600_cs_print(struct radeon_cs *cs, FILE *file)
429 {
430 }
431
432 static struct radeon_cs_funcs r600_cs_funcs = {
433 r600_cs_create,
434 r600_cs_write_reloc,
435 r600_cs_begin,
436 r600_cs_end,
437 r600_cs_emit,
438 r600_cs_destroy,
439 r600_cs_erase,
440 r600_cs_need_flush,
441 r600_cs_print
442 };
443
444 struct radeon_cs_manager * r600_radeon_cs_manager_legacy_ctor(struct radeon_context *ctx)
445 {
446 struct r600_cs_manager_legacy *csm;
447
448 csm = (struct r600_cs_manager_legacy*)
449 calloc(1, sizeof(struct r600_cs_manager_legacy));
450 if (csm == NULL) {
451 return NULL;
452 }
453 csm->base.funcs = &r600_cs_funcs;
454 csm->base.fd = ctx->dri.fd;
455 csm->ctx = ctx;
456 csm->pending_age = 1;
457 return (struct radeon_cs_manager*)csm;
458 }
459
460 void r600InitCmdBuf(context_t *r600) /* from rcommonInitCmdBuf */
461 {
462 radeonContextPtr rmesa = &r600->radeon;
463 GLuint size;
464 rmesa->hw.max_state_size = 4000; /* rough estimate */
465
466 /* Initialize command buffer */
467 size = 256 * driQueryOptioni(&rmesa->optionCache,
468 "command_buffer_size");
469 if (size < 2 * rmesa->hw.max_state_size) {
470 size = 2 * rmesa->hw.max_state_size + 65535;
471 }
472 if (size > 64 * 256)
473 size = 64 * 256;
474
475 if (rmesa->radeonScreen->kernel_mm) {
476 int fd = rmesa->radeonScreen->driScreen->fd;
477 rmesa->cmdbuf.csm = radeon_cs_manager_gem_ctor(fd);
478 } else {
479 rmesa->cmdbuf.csm = r600_radeon_cs_manager_legacy_ctor(rmesa);
480 }
481 if (rmesa->cmdbuf.csm == NULL) {
482 /* FIXME: fatal error */
483 return;
484 }
485 rmesa->cmdbuf.cs = radeon_cs_create(rmesa->cmdbuf.csm, size);
486 assert(rmesa->cmdbuf.cs != NULL);
487 rmesa->cmdbuf.size = size;
488
489 if (!rmesa->radeonScreen->kernel_mm) {
490 radeon_cs_set_limit(rmesa->cmdbuf.cs, RADEON_GEM_DOMAIN_VRAM, rmesa->radeonScreen->texSize[0]);
491 radeon_cs_set_limit(rmesa->cmdbuf.cs, RADEON_GEM_DOMAIN_GTT, rmesa->radeonScreen->gartTextures.size);
492 } else {
493 struct drm_radeon_gem_info mminfo;
494
495 if (!drmCommandWriteRead(rmesa->dri.fd, DRM_RADEON_GEM_INFO, &mminfo, sizeof(mminfo)))
496 {
497 radeon_cs_set_limit(rmesa->cmdbuf.cs, RADEON_GEM_DOMAIN_VRAM, mminfo.vram_visible);
498 radeon_cs_set_limit(rmesa->cmdbuf.cs, RADEON_GEM_DOMAIN_GTT, mminfo.gart_size);
499 }
500 }
501 }
502