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"
55 #ifdef HAVE_LIBDRM_RADEON
56 #include "radeon_cs_int.h"
58 #include "radeon_cs_int_drm.h"
61 struct r600_cs_manager_legacy
63 struct radeon_cs_manager base
;
64 struct radeon_context
*ctx
;
65 /* hack for scratch stuff */
67 uint32_t pending_count
;
70 struct r600_cs_reloc_legacy
{
71 struct radeon_cs_reloc base
;
74 uint32_t *reloc_indices
;
77 static struct radeon_cs_int
*r600_cs_create(struct radeon_cs_manager
*csm
,
80 struct radeon_cs_int
*csi
;
82 csi
= (struct radeon_cs_int
*)calloc(1, sizeof(struct radeon_cs_int
));
87 csi
->ndw
= (ndw
+ 0x3FF) & (~0x3FF);
88 csi
->packets
= (uint32_t*)malloc(4*csi
->ndw
);
89 if (csi
->packets
== NULL
) {
93 csi
->relocs_total_size
= 0;
97 static int r600_cs_write_reloc(struct radeon_cs_int
*csi
,
100 uint32_t write_domain
,
103 struct r600_cs_reloc_legacy
*relocs
;
106 relocs
= (struct r600_cs_reloc_legacy
*)csi
->relocs
;
108 if ((read_domain
&& write_domain
) || (!read_domain
&& !write_domain
)) {
109 /* in one CS a bo can only be in read or write domain but not
110 * in read & write domain at the same sime
114 if (read_domain
== RADEON_GEM_DOMAIN_CPU
) {
117 if (write_domain
== RADEON_GEM_DOMAIN_CPU
) {
120 /* check if bo is already referenced */
121 for(i
= 0; i
< csi
->crelocs
; i
++) {
123 uint32_t *reloc_indices
;
125 if (relocs
[i
].base
.bo
->handle
== bo
->handle
) {
126 /* Check domains must be in read or write. As we check already
127 * checked that in argument one of the read or write domain was
128 * set we only need to check that if previous reloc as the read
129 * domain set then the read_domain should also be set for this
132 if (relocs
[i
].base
.read_domain
&& !read_domain
) {
135 if (relocs
[i
].base
.write_domain
&& !write_domain
) {
138 relocs
[i
].base
.read_domain
|= read_domain
;
139 relocs
[i
].base
.write_domain
|= write_domain
;
141 relocs
[i
].cindices
++;
142 indices
= (uint32_t*)realloc(relocs
[i
].indices
,
143 relocs
[i
].cindices
* 4);
144 reloc_indices
= (uint32_t*)realloc(relocs
[i
].reloc_indices
,
145 relocs
[i
].cindices
* 4);
146 if ( (indices
== NULL
) || (reloc_indices
== NULL
) ) {
147 relocs
[i
].cindices
-= 1;
150 relocs
[i
].indices
= indices
;
151 relocs
[i
].reloc_indices
= reloc_indices
;
152 relocs
[i
].indices
[relocs
[i
].cindices
- 1] = csi
->cdw
;
153 relocs
[i
].reloc_indices
[relocs
[i
].cindices
- 1] = csi
->cdw
;
154 csi
->section_cdw
+= 2;
160 /* add bo to reloc */
161 relocs
= (struct r600_cs_reloc_legacy
*)
163 sizeof(struct r600_cs_reloc_legacy
) * (csi
->crelocs
+ 1));
164 if (relocs
== NULL
) {
167 csi
->relocs
= relocs
;
168 relocs
[csi
->crelocs
].base
.bo
= bo
;
169 relocs
[csi
->crelocs
].base
.read_domain
= read_domain
;
170 relocs
[csi
->crelocs
].base
.write_domain
= write_domain
;
171 relocs
[csi
->crelocs
].base
.flags
= flags
;
172 relocs
[csi
->crelocs
].indices
= (uint32_t*)malloc(4);
173 relocs
[csi
->crelocs
].reloc_indices
= (uint32_t*)malloc(4);
174 if ( (relocs
[csi
->crelocs
].indices
== NULL
) || (relocs
[csi
->crelocs
].reloc_indices
== NULL
) )
179 relocs
[csi
->crelocs
].indices
[0] = csi
->cdw
;
180 relocs
[csi
->crelocs
].reloc_indices
[0] = csi
->cdw
;
181 csi
->section_cdw
+= 2;
183 relocs
[csi
->crelocs
].cindices
= 1;
184 csi
->relocs_total_size
+= radeon_bo_legacy_relocs_size(bo
);
192 static int r600_cs_begin(struct radeon_cs_int
*csi
,
198 if (csi
->section_ndw
) {
199 fprintf(stderr
, "CS already in a section(%s,%s,%d)\n",
200 csi
->section_file
, csi
->section_func
, csi
->section_line
);
201 fprintf(stderr
, "CS can't start section(%s,%s,%d)\n",
206 csi
->section_ndw
= ndw
;
207 csi
->section_cdw
= 0;
208 csi
->section_file
= file
;
209 csi
->section_func
= func
;
210 csi
->section_line
= line
;
212 if (csi
->cdw
+ ndw
> csi
->ndw
) {
214 int num
= (ndw
> 0x400) ? ndw
: 0x400;
216 tmp
= (csi
->cdw
+ num
+ 0x3FF) & (~0x3FF);
217 ptr
= (uint32_t*)realloc(csi
->packets
, 4 * tmp
);
228 static int r600_cs_end(struct radeon_cs_int
*csi
,
234 if (!csi
->section_ndw
) {
235 fprintf(stderr
, "CS no section to end at (%s,%s,%d)\n",
240 if ( csi
->section_ndw
!= csi
->section_cdw
) {
241 fprintf(stderr
, "CS section size missmatch start at (%s,%s,%d) %d vs %d\n",
242 csi
->section_file
, csi
->section_func
, csi
->section_line
, csi
->section_ndw
, csi
->section_cdw
);
243 fprintf(stderr
, "csi->section_ndw = %d, csi->cdw = %d, csi->section_cdw = %d \n",
244 csi
->section_ndw
, csi
->cdw
, csi
->section_cdw
);
245 fprintf(stderr
, "CS section end at (%s,%s,%d)\n",
249 csi
->section_ndw
= 0;
251 if (csi
->cdw
> csi
->ndw
) {
252 fprintf(stderr
, "CS section overflow at (%s,%s,%d) cdw %d ndw %d\n",
253 csi
->section_file
, csi
->section_func
, csi
->section_line
,csi
->cdw
,csi
->ndw
);
254 fprintf(stderr
, "CS section end at (%s,%s,%d)\n",
262 static int r600_cs_process_relocs(struct radeon_cs_int
*csi
,
263 uint32_t * reloc_chunk
,
264 uint32_t * length_dw_reloc_chunk
)
266 struct r600_cs_manager_legacy
*csm
= (struct r600_cs_manager_legacy
*)csi
->csm
;
267 struct r600_cs_reloc_legacy
*relocs
;
270 uint32_t offset_dw
= 0;
272 csm
= (struct r600_cs_manager_legacy
*)csi
->csm
;
273 relocs
= (struct r600_cs_reloc_legacy
*)csi
->relocs
;
275 for (i
= 0; i
< csi
->crelocs
; i
++) {
276 uint32_t soffset
, eoffset
;
278 r
= radeon_bo_legacy_validate(relocs
[i
].base
.bo
,
284 fprintf(stderr
, "invalid bo(%p) [0x%08X, 0x%08X]\n",
285 relocs
[i
].base
.bo
, soffset
, eoffset
);
289 for (j
= 0; j
< relocs
[i
].cindices
; j
++) {
290 /* pkt3 nop header in ib chunk */
291 csi
->packets
[relocs
[i
].reloc_indices
[j
]] = 0xC0001000;
292 /* reloc index in ib chunk */
293 csi
->packets
[relocs
[i
].reloc_indices
[j
] + 1] = offset_dw
;
296 /* asic offset in reloc chunk */ /* see alex drm r600_nomm_relocate */
297 reloc_chunk
[offset_dw
] = soffset
;
298 reloc_chunk
[offset_dw
+ 3] = 0;
303 *length_dw_reloc_chunk
= offset_dw
;
308 static int r600_cs_set_age(struct radeon_cs_int
*csi
) /* -------------- */
310 struct r600_cs_manager_legacy
*csm
= (struct r600_cs_manager_legacy
*)csi
->csm
;
311 struct r600_cs_reloc_legacy
*relocs
;
314 relocs
= (struct r600_cs_reloc_legacy
*)csi
->relocs
;
315 for (i
= 0; i
< csi
->crelocs
; i
++) {
316 radeon_bo_legacy_pending(relocs
[i
].base
.bo
, csm
->pending_age
);
317 radeon_bo_unref(relocs
[i
].base
.bo
);
323 static void dump_cmdbuf(struct radeon_cs_int
*csi
)
326 fprintf(stderr
,"--start--\n");
327 for (i
= 0; i
< csi
->cdw
; i
++){
328 fprintf(stderr
,"0x%08x\n", csi
->packets
[i
]);
330 fprintf(stderr
,"--end--\n");
335 static int r600_cs_emit(struct radeon_cs_int
*csi
)
337 struct r600_cs_manager_legacy
*csm
= (struct r600_cs_manager_legacy
*)csi
->csm
;
338 struct drm_radeon_cs cs_cmd
;
339 struct drm_radeon_cs_chunk cs_chunk
[2];
340 uint32_t length_dw_reloc_chunk
;
341 uint64_t chunk_ptrs
[2];
342 uint32_t *reloc_chunk
;
346 /* TODO : put chip level things here if need. */
347 /* csm->ctx->vtbl.emit_cs_header(cs, csm->ctx); */
349 csm
->pending_count
= 1;
351 reloc_chunk
= (uint32_t*)calloc(1, csi
->crelocs
* 4 * 4);
353 r
= r600_cs_process_relocs(csi
, reloc_chunk
, &length_dw_reloc_chunk
);
360 cs_chunk
[0].chunk_id
= RADEON_CHUNK_ID_IB
;
361 cs_chunk
[0].length_dw
= csi
->cdw
;
362 cs_chunk
[0].chunk_data
= (unsigned long)(csi
->packets
);
365 cs_chunk
[1].chunk_id
= RADEON_CHUNK_ID_RELOCS
;
366 cs_chunk
[1].length_dw
= length_dw_reloc_chunk
;
367 cs_chunk
[1].chunk_data
= (unsigned long)reloc_chunk
;
369 chunk_ptrs
[0] = (uint64_t)(unsigned long)&(cs_chunk
[0]);
370 chunk_ptrs
[1] = (uint64_t)(unsigned long)&(cs_chunk
[1]);
372 cs_cmd
.num_chunks
= 2;
373 /* cs_cmd.cs_id = 0; */
374 cs_cmd
.chunks
= (uint64_t)(unsigned long)chunk_ptrs
;
380 r
= drmCommandWriteRead(csi
->csm
->fd
, DRM_RADEON_CS
, &cs_cmd
, sizeof(cs_cmd
));
382 } while (r
== -EAGAIN
&& retry
< 1000);
389 csm
->pending_age
= cs_cmd
.cs_id
;
391 r600_cs_set_age(csi
);
393 csi
->csm
->read_used
= 0;
394 csi
->csm
->vram_write_used
= 0;
395 csi
->csm
->gart_write_used
= 0;
402 static void inline r600_cs_free_reloc(void *relocs_p
, int crelocs
)
404 struct r600_cs_reloc_legacy
*relocs
= relocs_p
;
408 for (i
= 0; i
< crelocs
; i
++)
410 free(relocs
[i
].indices
);
411 free(relocs
[i
].reloc_indices
);
415 static int r600_cs_destroy(struct radeon_cs_int
*csi
)
417 r600_cs_free_reloc(csi
->relocs
, csi
->crelocs
);
424 static int r600_cs_erase(struct radeon_cs_int
*csi
)
426 r600_cs_free_reloc(csi
->relocs
, csi
->crelocs
);
428 csi
->relocs_total_size
= 0;
435 static int r600_cs_need_flush(struct radeon_cs_int
*csi
)
437 /* this function used to flush when the BO usage got to
438 * a certain size, now the higher levels handle this better */
442 static void r600_cs_print(struct radeon_cs_int
*csi
, FILE *file
)
446 static struct radeon_cs_funcs r600_cs_funcs
= {
458 struct radeon_cs_manager
* r600_radeon_cs_manager_legacy_ctor(struct radeon_context
*ctx
)
460 struct r600_cs_manager_legacy
*csm
;
462 csm
= (struct r600_cs_manager_legacy
*)
463 calloc(1, sizeof(struct r600_cs_manager_legacy
));
467 csm
->base
.funcs
= &r600_cs_funcs
;
468 csm
->base
.fd
= ctx
->dri
.fd
;
470 csm
->pending_age
= 1;
471 return (struct radeon_cs_manager
*)csm
;
474 void r600InitCmdBuf(context_t
*r600
) /* from rcommonInitCmdBuf */
476 radeonContextPtr rmesa
= &r600
->radeon
;
481 /* Initialize command buffer */
482 size
= 256 * driQueryOptioni(&rmesa
->optionCache
,
483 "command_buffer_size");
484 if (size
< 2 * rmesa
->hw
.max_state_size
) {
485 size
= 2 * rmesa
->hw
.max_state_size
+ 65535;
490 if (rmesa
->radeonScreen
->kernel_mm
) {
491 int fd
= rmesa
->radeonScreen
->driScreen
->fd
;
492 rmesa
->cmdbuf
.csm
= radeon_cs_manager_gem_ctor(fd
);
494 rmesa
->cmdbuf
.csm
= r600_radeon_cs_manager_legacy_ctor(rmesa
);
496 if (rmesa
->cmdbuf
.csm
== NULL
) {
497 /* FIXME: fatal error */
500 rmesa
->cmdbuf
.cs
= radeon_cs_create(rmesa
->cmdbuf
.csm
, size
);
501 assert(rmesa
->cmdbuf
.cs
!= NULL
);
502 rmesa
->cmdbuf
.size
= size
;
504 radeon_cs_space_set_flush(rmesa
->cmdbuf
.cs
,
505 (void (*)(void *))rmesa
->glCtx
->Driver
.Flush
, rmesa
->glCtx
);
507 if (!rmesa
->radeonScreen
->kernel_mm
) {
508 radeon_cs_set_limit(rmesa
->cmdbuf
.cs
, RADEON_GEM_DOMAIN_VRAM
, rmesa
->radeonScreen
->texSize
[0]);
509 radeon_cs_set_limit(rmesa
->cmdbuf
.cs
, RADEON_GEM_DOMAIN_GTT
, rmesa
->radeonScreen
->gartTextures
.size
);
511 struct drm_radeon_gem_info mminfo
;
513 if (!drmCommandWriteRead(rmesa
->dri
.fd
, DRM_RADEON_GEM_INFO
, &mminfo
, sizeof(mminfo
)))
515 radeon_cs_set_limit(rmesa
->cmdbuf
.cs
, RADEON_GEM_DOMAIN_VRAM
, mminfo
.vram_visible
);
516 radeon_cs_set_limit(rmesa
->cmdbuf
.cs
, RADEON_GEM_DOMAIN_GTT
, mminfo
.gart_size
);