2 Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
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.
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:
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.
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.
28 **************************************************************************/
31 * Mostly coppied from \radeon\radeon_cs_legacy.c
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"
45 #include "radeon_drm.h"
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"
57 static struct radeon_cs
* r600_cs_create(struct radeon_cs_manager
*csm
,
62 cs
= (struct radeon_cs
*)calloc(1, sizeof(struct radeon_cs
));
67 cs
->ndw
= (ndw
+ 0x3FF) & (~0x3FF);
68 cs
->packets
= (uint32_t*)malloc(4*cs
->ndw
);
69 if (cs
->packets
== NULL
) {
73 cs
->relocs_total_size
= 0;
77 int r600_cs_write_reloc(struct radeon_cs
*cs
,
80 uint32_t write_domain
,
83 struct r600_cs_reloc_legacy
*relocs
;
86 relocs
= (struct r600_cs_reloc_legacy
*)cs
->relocs
;
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
94 if (read_domain
== RADEON_GEM_DOMAIN_CPU
) {
97 if (write_domain
== RADEON_GEM_DOMAIN_CPU
) {
100 /* check if bo is already referenced */
101 for(i
= 0; i
< cs
->crelocs
; i
++) {
103 uint32_t *reloc_indices
;
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
112 if (relocs
[i
].base
.read_domain
&& !read_domain
) {
115 if (relocs
[i
].base
.write_domain
&& !write_domain
) {
118 relocs
[i
].base
.read_domain
|= read_domain
;
119 relocs
[i
].base
.write_domain
|= write_domain
;
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;
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;
140 /* add bo to reloc */
141 relocs
= (struct r600_cs_reloc_legacy
*)
143 sizeof(struct r600_cs_reloc_legacy
) * (cs
->crelocs
+ 1));
144 if (relocs
== NULL
) {
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
) )
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
);
172 static int r600_cs_begin(struct radeon_cs
*cs
,
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",
186 if (cs
->cdw
+ ndw
+ 32 > cs
->ndw
) { /* Left 32 DWORD (8 offset+pitch) spare room for reloc indices */
188 int num
= (ndw
> 0x3FF) ? ndw
: 0x3FF;
190 tmp
= (cs
->cdw
+ 1 + num
) & (~num
);
191 ptr
= (uint32_t*)realloc(cs
->packets
, 4 * tmp
);
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
;
209 static int r600_cs_end(struct radeon_cs
*cs
,
216 fprintf(stderr
, "CS no section to end at (%s,%s,%d)\n",
222 if ( (cs
->section_ndw
+ cs
->cdw
) != cs
->section_cdw
)
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",
233 cs
->cdw
= cs
->section_cdw
;
237 static int r600_cs_process_relocs(struct radeon_cs
*cs
,
238 uint32_t * reloc_chunk
,
239 uint32_t * length_dw_reloc_chunk
)
241 struct r600_cs_manager_legacy
*csm
= (struct r600_cs_manager_legacy
*)cs
->csm
;
242 struct r600_cs_reloc_legacy
*relocs
;
245 uint32_t offset_dw
= 0;
247 csm
= (struct r600_cs_manager_legacy
*)cs
->csm
;
248 relocs
= (struct r600_cs_reloc_legacy
*)cs
->relocs
;
250 for (i
= 0; i
< cs
->crelocs
; i
++) {
251 uint32_t soffset
, eoffset
, asicoffset
;
253 r
= radeon_bo_legacy_validate(relocs
[i
].base
.bo
,
259 fprintf(stderr
, "validated %p [0x%08X, 0x%08X]\n",
260 relocs
[i
].base
.bo
, soffset
, eoffset
);
263 asicoffset
= soffset
;
265 for (j
= 0; j
< relocs
[i
].cindices
; j
++) {
266 if (asicoffset
>= eoffset
) {
267 /* radeon_bo_debug(relocs[i].base.bo, 12); */
268 fprintf(stderr
, "validated %p [0x%08X, 0x%08X]\n",
269 relocs
[i
].base
.bo
, soffset
, eoffset
);
270 fprintf(stderr
, "above end: %p 0x%08X 0x%08X\n",
272 cs
->packets
[relocs
[i
].indices
[j
]],
277 /* pkt3 nop header in ib chunk */
278 cs
->packets
[relocs
[i
].reloc_indices
[j
]] = 0xC0001000;
279 /* reloc index in ib chunk */
280 cs
->packets
[relocs
[i
].reloc_indices
[j
] + 1] = offset_dw
;
283 /* asic offset in reloc chunk */ /* see alex drm r600_nomm_relocate */
284 reloc_chunk
[offset_dw
] = asicoffset
;
285 reloc_chunk
[offset_dw
+ 3] = 0;
290 *length_dw_reloc_chunk
= offset_dw
;
295 static int r600_cs_set_age(struct radeon_cs
*cs
) /* -------------- */
297 struct r600_cs_manager_legacy
*csm
= (struct r600_cs_manager_legacy
*)cs
->csm
;
298 struct r600_cs_reloc_legacy
*relocs
;
301 relocs
= (struct r600_cs_reloc_legacy
*)cs
->relocs
;
302 for (i
= 0; i
< cs
->crelocs
; i
++) {
303 radeon_bo_legacy_pending(relocs
[i
].base
.bo
, csm
->pending_age
);
304 radeon_bo_unref(relocs
[i
].base
.bo
);
309 static void dump_cmdbuf(struct radeon_cs
*cs
)
312 fprintf(stderr
,"--start--\n");
313 for (i
= 0; i
< cs
->cdw
; i
++){
314 fprintf(stderr
,"0x%08x\n", cs
->packets
[i
]);
316 fprintf(stderr
,"--end--\n");
320 static int r600_cs_emit(struct radeon_cs
*cs
)
322 struct r600_cs_manager_legacy
*csm
= (struct r600_cs_manager_legacy
*)cs
->csm
;
323 struct drm_radeon_cs cs_cmd
;
324 struct drm_radeon_cs_chunk cs_chunk
[2];
325 uint32_t length_dw_reloc_chunk
;
326 uint64_t chunk_ptrs
[2];
327 uint32_t reloc_chunk
[128];
331 /* TODO : put chip level things here if need. */
332 /* csm->ctx->vtbl.emit_cs_header(cs, csm->ctx); */
334 csm
->pending_count
= 1;
336 r
= r600_cs_process_relocs(cs
, &(reloc_chunk
[0]), &length_dw_reloc_chunk
);
342 cs_chunk
[0].chunk_id
= RADEON_CHUNK_ID_IB
;
343 cs_chunk
[0].length_dw
= cs
->cdw
;
344 cs_chunk
[0].chunk_data
= (unsigned long)(cs
->packets
);
347 cs_chunk
[1].chunk_id
= RADEON_CHUNK_ID_RELOCS
;
348 cs_chunk
[1].length_dw
= length_dw_reloc_chunk
;
349 cs_chunk
[1].chunk_data
= (unsigned long)&(reloc_chunk
[0]);
351 chunk_ptrs
[0] = (uint64_t)(unsigned long)&(cs_chunk
[0]);
352 chunk_ptrs
[1] = (uint64_t)(unsigned long)&(cs_chunk
[1]);
354 cs_cmd
.num_chunks
= 2;
355 /* cs_cmd.cs_id = 0; */
356 cs_cmd
.chunks
= (uint64_t)(unsigned long)chunk_ptrs
;
362 r
= drmCommandWriteRead(cs
->csm
->fd
, DRM_RADEON_CS
, &cs_cmd
, sizeof(cs_cmd
));
364 } while (r
== -EAGAIN
&& retry
< 1000);
370 csm
->pending_age
= cs_cmd
.cs_id
;
374 cs
->csm
->read_used
= 0;
375 cs
->csm
->vram_write_used
= 0;
376 cs
->csm
->gart_write_used
= 0;
381 static void inline r600_cs_free_reloc(void *relocs_p
, int crelocs
)
383 struct r600_cs_reloc_legacy
*relocs
= relocs_p
;
387 for (i
= 0; i
< crelocs
; i
++)
389 free(relocs
[i
].indices
);
390 free(relocs
[i
].reloc_indices
);
394 static int r600_cs_destroy(struct radeon_cs
*cs
)
396 r600_cs_free_reloc(cs
->relocs
, cs
->crelocs
);
403 static int r600_cs_erase(struct radeon_cs
*cs
)
405 r600_cs_free_reloc(cs
->relocs
, cs
->crelocs
);
407 cs
->relocs_total_size
= 0;
415 static int r600_cs_need_flush(struct radeon_cs
*cs
)
417 /* this function used to flush when the BO usage got to
418 * a certain size, now the higher levels handle this better */
422 static void r600_cs_print(struct radeon_cs
*cs
, FILE *file
)
426 static struct radeon_cs_funcs r600_cs_funcs
= {
438 struct radeon_cs_manager
* r600_radeon_cs_manager_legacy_ctor(struct radeon_context
*ctx
)
440 struct r600_cs_manager_legacy
*csm
;
442 csm
= (struct r600_cs_manager_legacy
*)
443 calloc(1, sizeof(struct r600_cs_manager_legacy
));
447 csm
->base
.funcs
= &r600_cs_funcs
;
448 csm
->base
.fd
= ctx
->dri
.fd
;
450 csm
->pending_age
= 1;
451 return (struct radeon_cs_manager
*)csm
;
454 void r600InitCmdBuf(context_t
*r600
) /* from rcommonInitCmdBuf */
456 radeonContextPtr rmesa
= &r600
->radeon
;
458 rmesa
->hw
.max_state_size
= 4000; /* rough estimate */
460 rmesa
->hw
.all_dirty
= GL_TRUE
;
461 rmesa
->hw
.is_dirty
= GL_TRUE
;
463 /* Initialize command buffer */
464 size
= 256 * driQueryOptioni(&rmesa
->optionCache
,
465 "command_buffer_size");
466 if (size
< 2 * rmesa
->hw
.max_state_size
) {
467 size
= 2 * rmesa
->hw
.max_state_size
+ 65535;
472 if (rmesa
->radeonScreen
->kernel_mm
) {
473 int fd
= rmesa
->radeonScreen
->driScreen
->fd
;
474 rmesa
->cmdbuf
.csm
= radeon_cs_manager_gem_ctor(fd
);
476 rmesa
->cmdbuf
.csm
= r600_radeon_cs_manager_legacy_ctor(rmesa
);
478 if (rmesa
->cmdbuf
.csm
== NULL
) {
479 /* FIXME: fatal error */
482 rmesa
->cmdbuf
.cs
= radeon_cs_create(rmesa
->cmdbuf
.csm
, size
);
483 assert(rmesa
->cmdbuf
.cs
!= NULL
);
484 rmesa
->cmdbuf
.size
= size
;
486 if (!rmesa
->radeonScreen
->kernel_mm
) {
487 radeon_cs_set_limit(rmesa
->cmdbuf
.cs
, RADEON_GEM_DOMAIN_VRAM
, rmesa
->radeonScreen
->texSize
[0]);
488 radeon_cs_set_limit(rmesa
->cmdbuf
.cs
, RADEON_GEM_DOMAIN_GTT
, rmesa
->radeonScreen
->gartTextures
.size
);
490 struct drm_radeon_gem_info mminfo
;
492 if (!drmCommandWriteRead(rmesa
->dri
.fd
, DRM_RADEON_GEM_INFO
, &mminfo
, sizeof(mminfo
)))
494 radeon_cs_set_limit(rmesa
->cmdbuf
.cs
, RADEON_GEM_DOMAIN_VRAM
, mminfo
.vram_visible
);
495 radeon_cs_set_limit(rmesa
->cmdbuf
.cs
, RADEON_GEM_DOMAIN_GTT
, mminfo
.gart_size
);