2 * Copyright 2010 Jerome Glisse <glisse@freedesktop.org>
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * on the rights to use, copy, modify, merge, publish, distribute, sub
8 * license, and/or sell copies of the Software, and to permit persons to whom
9 * the Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21 * USE OR OTHER DEALINGS IN THE SOFTWARE.
29 #include "radeon_priv.h"
30 #include "radeon_drm.h"
33 int radeon_ctx_set_bo_new(struct radeon_ctx
*ctx
, struct radeon_bo
*bo
)
37 ptr
= realloc(ctx
->bo
, sizeof(struct radeon_bo
) * (ctx
->nbo
+ 1));
42 ctx
->bo
[ctx
->nbo
] = bo
;
47 struct radeon_bo
*radeon_ctx_get_bo(struct radeon_ctx
*ctx
, unsigned reloc
)
49 struct radeon_cs_reloc
*greloc
;
52 greloc
= (void *)(((u8
*)ctx
->reloc
) + reloc
* 4);
53 for (i
= 0; i
< ctx
->nbo
; i
++) {
54 if (ctx
->bo
[i
]->handle
== greloc
->handle
) {
55 return radeon_bo_incref(ctx
->radeon
, ctx
->bo
[i
]);
58 fprintf(stderr
, "%s no bo for reloc[%d 0x%08X] %d\n", __func__
, reloc
, greloc
->handle
, ctx
->nbo
);
62 void radeon_ctx_get_placement(struct radeon_ctx
*ctx
, unsigned reloc
, u32
*placement
)
64 struct radeon_cs_reloc
*greloc
;
69 greloc
= (void *)(((u8
*)ctx
->reloc
) + reloc
* 4);
70 for (i
= 0; i
< ctx
->nbo
; i
++) {
71 if (ctx
->bo
[i
]->handle
== greloc
->handle
) {
72 placement
[0] = greloc
->read_domain
| greloc
->write_domain
;
73 placement
[1] = placement
[0];
79 struct radeon_ctx
*radeon_ctx(struct radeon
*radeon
)
81 struct radeon_ctx
*ctx
;
85 ctx
= calloc(1, sizeof(*ctx
));
88 ctx
->radeon
= radeon_incref(radeon
);
92 struct radeon_ctx
*radeon_ctx_incref(struct radeon_ctx
*ctx
)
98 struct radeon_ctx
*radeon_ctx_decref(struct radeon_ctx
*ctx
)
104 if (--ctx
->refcount
> 0) {
108 for (i
= 0; i
< ctx
->ndraw
; i
++) {
109 ctx
->draw
[i
] = radeon_draw_decref(ctx
->draw
[i
]);
111 for (i
= 0; i
< ctx
->nbo
; i
++) {
112 ctx
->bo
[i
] = radeon_bo_decref(ctx
->radeon
, ctx
->bo
[i
]);
114 ctx
->radeon
= radeon_decref(ctx
->radeon
);
119 memset(ctx
, 0, sizeof(*ctx
));
124 static int radeon_ctx_state_bo(struct radeon_ctx
*ctx
, struct radeon_state
*state
)
131 for (i
= 0; i
< state
->nbo
; i
++) {
132 for (j
= 0; j
< ctx
->nbo
; j
++) {
133 if (state
->bo
[i
] == ctx
->bo
[j
])
137 radeon_bo_incref(ctx
->radeon
, state
->bo
[i
]);
138 r
= radeon_ctx_set_bo_new(ctx
, state
->bo
[i
]);
147 int radeon_ctx_submit(struct radeon_ctx
*ctx
)
149 struct drm_radeon_cs drmib
;
150 struct drm_radeon_cs_chunk chunks
[2];
151 uint64_t chunk_array
[2];
155 for (r
= 0; r
< ctx
->cpm4
; r
++) {
156 fprintf(stderr
, "0x%08X\n", ctx
->pm4
[r
]);
159 drmib
.num_chunks
= 2;
160 drmib
.chunks
= (uint64_t)(uintptr_t)chunk_array
;
161 chunks
[0].chunk_id
= RADEON_CHUNK_ID_IB
;
162 chunks
[0].length_dw
= ctx
->cpm4
;
163 chunks
[0].chunk_data
= (uint64_t)(uintptr_t)ctx
->pm4
;
164 chunks
[1].chunk_id
= RADEON_CHUNK_ID_RELOCS
;
165 chunks
[1].length_dw
= ctx
->nreloc
* sizeof(struct radeon_cs_reloc
) / 4;
166 chunks
[1].chunk_data
= (uint64_t)(uintptr_t)ctx
->reloc
;
167 chunk_array
[0] = (uint64_t)(uintptr_t)&chunks
[0];
168 chunk_array
[1] = (uint64_t)(uintptr_t)&chunks
[1];
170 r
= drmCommandWriteRead(ctx
->radeon
->fd
, DRM_RADEON_CS
, &drmib
,
171 sizeof(struct drm_radeon_cs
));
176 static int radeon_ctx_reloc(struct radeon_ctx
*ctx
, struct radeon_bo
*bo
,
177 unsigned id
, unsigned *placement
)
180 struct radeon_cs_reloc
*ptr
;
182 for (i
= 0; i
< ctx
->nreloc
; i
++) {
183 if (ctx
->reloc
[i
].handle
== bo
->handle
) {
184 ctx
->pm4
[id
] = i
* sizeof(struct radeon_cs_reloc
) / 4;
188 ptr
= realloc(ctx
->reloc
, sizeof(struct radeon_cs_reloc
) * (ctx
->nreloc
+ 1));
192 ptr
[ctx
->nreloc
].handle
= bo
->handle
;
193 ptr
[ctx
->nreloc
].read_domain
= placement
[0] | placement
[1];
194 ptr
[ctx
->nreloc
].write_domain
= placement
[0] | placement
[1];
195 ptr
[ctx
->nreloc
].flags
= 0;
196 ctx
->pm4
[id
] = ctx
->nreloc
* sizeof(struct radeon_cs_reloc
) / 4;
201 static int radeon_ctx_state_schedule(struct radeon_ctx
*ctx
, struct radeon_state
*state
)
203 unsigned i
, rid
, bid
, cid
;
208 memcpy(&ctx
->pm4
[ctx
->id
], state
->pm4
, state
->cpm4
* 4);
209 for (i
= 0; i
< state
->nreloc
; i
++) {
210 rid
= state
->reloc_pm4_id
[i
];
211 bid
= state
->reloc_bo_id
[i
];
213 r
= radeon_ctx_reloc(ctx
, state
->bo
[bid
], cid
,
214 &state
->placement
[bid
* 2]);
216 fprintf(stderr
, "%s state %d failed to reloc\n", __func__
, state
->type
);
220 ctx
->id
+= state
->cpm4
;
224 int radeon_ctx_set_draw_new(struct radeon_ctx
*ctx
, struct radeon_draw
*draw
)
226 struct radeon_draw
*pdraw
= NULL
;
227 struct radeon_draw
**ndraw
;
228 struct radeon_state
*nstate
, *ostate
;
229 unsigned cpm4
, i
, cstate
;
233 ndraw
= realloc(ctx
->draw
, sizeof(void*) * (ctx
->ndraw
+ 1));
237 for (i
= 0; i
< draw
->nstate
; i
++) {
238 r
= radeon_ctx_state_bo(ctx
, draw
->state
[i
]);
242 r
= radeon_draw_check(draw
);
245 if (draw
->cpm4
>= RADEON_CTX_MAX_PM4
) {
246 fprintf(stderr
, "%s single draw too big %d, max %d\n",
247 __func__
, draw
->cpm4
, RADEON_CTX_MAX_PM4
);
250 tmp
= realloc(ctx
->state
, (ctx
->nstate
+ draw
->nstate
) * sizeof(void*));
255 for (i
= 0, cpm4
= 0, cstate
= ctx
->nstate
; i
< draw
->nstate
- 1; i
++) {
256 nstate
= draw
->state
[i
];
258 if (pdraw
&& pdraw
->state
[i
]) {
259 ostate
= pdraw
->state
[i
];
260 if (ostate
->pm4_crc
!= nstate
->pm4_crc
) {
261 ctx
->state
[cstate
++] = nstate
;
262 cpm4
+= nstate
->cpm4
;
265 ctx
->state
[cstate
++] = nstate
;
266 cpm4
+= nstate
->cpm4
;
270 /* The last state is the draw state always add it */
271 if (draw
->state
[i
] == NULL
) {
272 fprintf(stderr
, "%s no draw command\n", __func__
);
275 ctx
->state
[cstate
++] = draw
->state
[i
];
276 cpm4
+= draw
->state
[i
]->cpm4
;
277 if ((ctx
->draw_cpm4
+ cpm4
) > RADEON_CTX_MAX_PM4
) {
281 ctx
->draw_cpm4
+= cpm4
;
282 ctx
->nstate
= cstate
;
283 ctx
->draw
[ctx
->ndraw
++] = draw
;
288 int radeon_ctx_set_draw(struct radeon_ctx
*ctx
, struct radeon_draw
*draw
)
292 radeon_draw_incref(draw
);
293 r
= radeon_ctx_set_draw_new(ctx
, draw
);
295 radeon_draw_decref(draw
);
299 int radeon_ctx_pm4(struct radeon_ctx
*ctx
)
306 ctx
->pm4
= malloc(ctx
->draw_cpm4
* 4);
307 if (ctx
->pm4
== NULL
)
309 for (i
= 0, ctx
->id
= 0; i
< ctx
->nstate
; i
++) {
310 r
= radeon_ctx_state_schedule(ctx
, ctx
->state
[i
]);
314 if (ctx
->id
!= ctx
->draw_cpm4
) {
315 fprintf(stderr
, "%s miss predicted pm4 size %d for %d\n",
316 __func__
, ctx
->draw_cpm4
, ctx
->id
);
319 ctx
->cpm4
= ctx
->draw_cpm4
;
323 void radeon_ctx_dump_bof(struct radeon_ctx
*ctx
, const char *file
)
325 bof_t
*bcs
, *blob
, *array
, *bo
, *size
, *handle
, *device_id
, *root
;
328 root
= device_id
= bcs
= blob
= array
= bo
= size
= handle
= NULL
;
332 device_id
= bof_int32(ctx
->radeon
->device
);
333 if (device_id
== NULL
)
335 if (bof_object_set(root
, "device_id", device_id
))
337 bof_decref(device_id
);
340 printf("%d relocs\n", ctx
->nreloc
);
341 blob
= bof_blob(ctx
->nreloc
* 16, ctx
->reloc
);
344 if (bof_object_set(root
, "reloc", blob
))
349 printf("%d pm4\n", ctx
->cpm4
);
350 blob
= bof_blob(ctx
->cpm4
* 4, ctx
->pm4
);
353 if (bof_object_set(root
, "pm4", blob
))
361 for (i
= 0; i
< ctx
->nbo
; i
++) {
365 size
= bof_int32(ctx
->bo
[i
]->size
);
366 printf("[%d] %d bo\n", i
, size
);
369 if (bof_object_set(bo
, "size", size
))
373 handle
= bof_int32(ctx
->bo
[i
]->handle
);
376 if (bof_object_set(bo
, "handle", handle
))
380 radeon_bo_map(ctx
->radeon
, ctx
->bo
[i
]);
381 blob
= bof_blob(ctx
->bo
[i
]->size
, ctx
->bo
[i
]->data
);
382 radeon_bo_unmap(ctx
->radeon
, ctx
->bo
[i
]);
385 if (bof_object_set(bo
, "data", blob
))
389 if (bof_array_append(array
, bo
))
394 if (bof_object_set(root
, "bo", array
))
396 bof_dump_file(root
, file
);
397 printf("done dump\n");
404 bof_decref(device_id
);