2 * Copyright © 2008 Nicolai Haehnle
3 * Copyright © 2008 Jérôme Glisse
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
18 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20 * USE OR OTHER DEALINGS IN THE SOFTWARE.
22 * The above copyright notice and this permission notice (including the
23 * next paragraph) shall be included in all copies or substantial portions
28 * Aapo Tahkola <aet@rasterburn.org>
29 * Nicolai Haehnle <prefect_@gmx.net>
30 * Jérôme Glisse <glisse@freedesktop.org>
36 #include "radeon_drm.h"
38 #include "radeon_bocs_wrapper.h"
39 #include "radeon_common.h"
40 #ifdef HAVE_LIBDRM_RADEON
41 #include "radeon_cs_int.h"
43 #include "radeon_cs_int_drm.h"
45 struct cs_manager_legacy
{
46 struct radeon_cs_manager base
;
47 struct radeon_context
*ctx
;
48 /* hack for scratch stuff */
50 uint32_t pending_count
;
55 struct cs_reloc_legacy
{
56 struct radeon_cs_reloc base
;
62 static struct radeon_cs_int
*cs_create(struct radeon_cs_manager
*csm
,
65 struct radeon_cs_int
*csi
;
67 csi
= (struct radeon_cs_int
*)calloc(1, sizeof(struct radeon_cs_int
));
72 csi
->ndw
= (ndw
+ 0x3FF) & (~0x3FF);
73 csi
->packets
= (uint32_t*)malloc(4*csi
->ndw
);
74 if (csi
->packets
== NULL
) {
78 csi
->relocs_total_size
= 0;
82 static int cs_write_reloc(struct radeon_cs_int
*cs
,
85 uint32_t write_domain
,
88 struct cs_reloc_legacy
*relocs
;
91 relocs
= (struct cs_reloc_legacy
*)cs
->relocs
;
93 if ((read_domain
&& write_domain
) || (!read_domain
&& !write_domain
)) {
94 /* in one CS a bo can only be in read or write domain but not
95 * in read & write domain at the same sime
99 if (read_domain
== RADEON_GEM_DOMAIN_CPU
) {
102 if (write_domain
== RADEON_GEM_DOMAIN_CPU
) {
105 /* check if bo is already referenced */
106 for(i
= 0; i
< cs
->crelocs
; i
++) {
109 if (relocs
[i
].base
.bo
->handle
== bo
->handle
) {
110 /* Check domains must be in read or write. As we check already
111 * checked that in argument one of the read or write domain was
112 * set we only need to check that if previous reloc as the read
113 * domain set then the read_domain should also be set for this
116 if (relocs
[i
].base
.read_domain
&& !read_domain
) {
119 if (relocs
[i
].base
.write_domain
&& !write_domain
) {
122 relocs
[i
].base
.read_domain
|= read_domain
;
123 relocs
[i
].base
.write_domain
|= write_domain
;
125 relocs
[i
].cindices
++;
126 indices
= (uint32_t*)realloc(relocs
[i
].indices
,
127 relocs
[i
].cindices
* 4);
128 if (indices
== NULL
) {
129 relocs
[i
].cindices
-= 1;
132 relocs
[i
].indices
= indices
;
133 relocs
[i
].indices
[relocs
[i
].cindices
- 1] = cs
->cdw
- 1;
137 /* add bo to reloc */
138 relocs
= (struct cs_reloc_legacy
*)
140 sizeof(struct cs_reloc_legacy
) * (cs
->crelocs
+ 1));
141 if (relocs
== NULL
) {
145 relocs
[cs
->crelocs
].base
.bo
= bo
;
146 relocs
[cs
->crelocs
].base
.read_domain
= read_domain
;
147 relocs
[cs
->crelocs
].base
.write_domain
= write_domain
;
148 relocs
[cs
->crelocs
].base
.flags
= flags
;
149 relocs
[cs
->crelocs
].indices
= (uint32_t*)malloc(4);
150 if (relocs
[cs
->crelocs
].indices
== NULL
) {
153 relocs
[cs
->crelocs
].indices
[0] = cs
->cdw
- 1;
154 relocs
[cs
->crelocs
].cindices
= 1;
155 cs
->relocs_total_size
+= radeon_bo_legacy_relocs_size(bo
);
161 static int cs_begin(struct radeon_cs_int
*cs
,
167 if (cs
->section_ndw
) {
168 fprintf(stderr
, "CS already in a section(%s,%s,%d)\n",
169 cs
->section_file
, cs
->section_func
, cs
->section_line
);
170 fprintf(stderr
, "CS can't start section(%s,%s,%d)\n",
174 cs
->section_ndw
= ndw
;
176 cs
->section_file
= file
;
177 cs
->section_func
= func
;
178 cs
->section_line
= line
;
181 if (cs
->cdw
+ ndw
> cs
->ndw
) {
184 tmp
= (cs
->cdw
+ ndw
+ 0x3ff) & (~0x3ff);
185 ptr
= (uint32_t*)realloc(cs
->packets
, 4 * tmp
);
196 static int cs_end(struct radeon_cs_int
*cs
,
202 if (!cs
->section_ndw
) {
203 fprintf(stderr
, "CS no section to end at (%s,%s,%d)\n",
207 if (cs
->section_ndw
!= cs
->section_cdw
) {
208 fprintf(stderr
, "CS section size missmatch start at (%s,%s,%d) %d vs %d\n",
209 cs
->section_file
, cs
->section_func
, cs
->section_line
, cs
->section_ndw
, cs
->section_cdw
);
210 fprintf(stderr
, "CS section end at (%s,%s,%d)\n",
219 static int cs_process_relocs(struct radeon_cs_int
*cs
)
221 struct cs_manager_legacy
*csm
= (struct cs_manager_legacy
*)cs
->csm
;
222 struct cs_reloc_legacy
*relocs
;
225 csm
= (struct cs_manager_legacy
*)cs
->csm
;
226 relocs
= (struct cs_reloc_legacy
*)cs
->relocs
;
228 for (i
= 0; i
< cs
->crelocs
; i
++)
230 for (j
= 0; j
< relocs
[i
].cindices
; j
++)
232 uint32_t soffset
, eoffset
;
234 r
= radeon_bo_legacy_validate(relocs
[i
].base
.bo
,
242 fprintf(stderr
, "validated %p [0x%08X, 0x%08X]\n",
243 relocs
[i
].base
.bo
, soffset
, eoffset
);
246 cs
->packets
[relocs
[i
].indices
[j
]] += soffset
;
247 if (cs
->packets
[relocs
[i
].indices
[j
]] >= eoffset
)
249 /* radeon_bo_debug(relocs[i].base.bo, 12); */
250 fprintf(stderr
, "validated %p [0x%08X, 0x%08X]\n",
251 relocs
[i
].base
.bo
, soffset
, eoffset
);
252 fprintf(stderr
, "above end: %p 0x%08X 0x%08X\n",
254 cs
->packets
[relocs
[i
].indices
[j
]],
264 static int cs_set_age(struct radeon_cs_int
*cs
)
266 struct cs_manager_legacy
*csm
= (struct cs_manager_legacy
*)cs
->csm
;
267 struct cs_reloc_legacy
*relocs
;
270 relocs
= (struct cs_reloc_legacy
*)cs
->relocs
;
271 for (i
= 0; i
< cs
->crelocs
; i
++) {
272 radeon_bo_legacy_pending(relocs
[i
].base
.bo
, csm
->pending_age
);
273 radeon_bo_unref(relocs
[i
].base
.bo
);
278 static int cs_emit(struct radeon_cs_int
*cs
)
280 struct cs_manager_legacy
*csm
= (struct cs_manager_legacy
*)cs
->csm
;
281 drm_radeon_cmd_buffer_t cmd
;
282 drm_r300_cmd_header_t age
;
286 csm
->ctx
->vtbl
.emit_cs_header((struct radeon_cs
*)cs
, csm
->ctx
);
288 /* append buffer age */
289 if ( IS_R300_CLASS(csm
->ctx
->radeonScreen
) )
291 age
.scratch
.cmd_type
= R300_CMD_SCRATCH
;
292 /* Scratch register 2 corresponds to what radeonGetAge polls */
293 csm
->pending_age
= 0;
294 csm
->pending_count
= 1;
295 ull
= (uint64_t) (intptr_t) &csm
->pending_age
;
297 age
.scratch
.n_bufs
= 1;
298 age
.scratch
.flags
= 0;
299 radeon_cs_write_dword((struct radeon_cs
*)cs
, age
.u
);
300 radeon_cs_write_qword((struct radeon_cs
*)cs
, ull
);
301 radeon_cs_write_dword((struct radeon_cs
*)cs
, 0);
304 r
= cs_process_relocs(cs
);
309 cmd
.buf
= (char *)cs
->packets
;
310 cmd
.bufsz
= cs
->cdw
* 4;
311 if (csm
->ctx
->state
.scissor
.enabled
) {
312 cmd
.nbox
= csm
->ctx
->state
.scissor
.numClipRects
;
313 cmd
.boxes
= (drm_clip_rect_t
*) csm
->ctx
->state
.scissor
.pClipRects
;
315 cmd
.nbox
= csm
->ctx
->numClipRects
;
316 cmd
.boxes
= (drm_clip_rect_t
*) csm
->ctx
->pClipRects
;
321 r
= drmCommandWrite(cs
->csm
->fd
, DRM_RADEON_CMDBUF
, &cmd
, sizeof(cmd
));
325 if ((!IS_R300_CLASS(csm
->ctx
->radeonScreen
)) &&
326 (!IS_R600_CLASS(csm
->ctx
->radeonScreen
))) { /* +r6/r7 : No irq for r6/r7 yet. */
327 drm_radeon_irq_emit_t emit_cmd
;
328 emit_cmd
.irq_seq
= (int*)&csm
->pending_age
;
329 r
= drmCommandWriteRead(cs
->csm
->fd
, DRM_RADEON_IRQ_EMIT
, &emit_cmd
, sizeof(emit_cmd
));
336 cs
->csm
->read_used
= 0;
337 cs
->csm
->vram_write_used
= 0;
338 cs
->csm
->gart_write_used
= 0;
342 static void inline cs_free_reloc(void *relocs_p
, int crelocs
)
344 struct cs_reloc_legacy
*relocs
= relocs_p
;
348 for (i
= 0; i
< crelocs
; i
++)
349 free(relocs
[i
].indices
);
352 static int cs_destroy(struct radeon_cs_int
*cs
)
354 cs_free_reloc(cs
->relocs
, cs
->crelocs
);
361 static int cs_erase(struct radeon_cs_int
*cs
)
363 cs_free_reloc(cs
->relocs
, cs
->crelocs
);
365 cs
->relocs_total_size
= 0;
373 static int cs_need_flush(struct radeon_cs_int
*cs
)
375 /* this function used to flush when the BO usage got to
376 * a certain size, now the higher levels handle this better */
380 static void cs_print(struct radeon_cs_int
*cs
, FILE *file
)
384 static struct radeon_cs_funcs radeon_cs_legacy_funcs
= {
396 struct radeon_cs_manager
*radeon_cs_manager_legacy_ctor(struct radeon_context
*ctx
)
398 struct cs_manager_legacy
*csm
;
400 csm
= (struct cs_manager_legacy
*)
401 calloc(1, sizeof(struct cs_manager_legacy
));
405 csm
->base
.funcs
= &radeon_cs_legacy_funcs
;
406 csm
->base
.fd
= ctx
->dri
.fd
;
408 csm
->pending_age
= 1;
409 return (struct radeon_cs_manager
*)csm
;
412 void radeon_cs_manager_legacy_dtor(struct radeon_cs_manager
*csm
)