28
28
#include "freedreno_blitter.h"
29
29
#include "freedreno_draw.h"
30
30
#include "freedreno_fence.h"
31
#include "freedreno_log.h"
32
31
#include "freedreno_program.h"
33
32
#include "freedreno_resource.h"
34
33
#include "freedreno_texture.h"
39
38
#include "freedreno_util.h"
40
39
#include "util/u_upload_mgr.h"
43
#include "util/u_process.h"
45
#include <sys/types.h>
49
42
fd_context_flush(struct pipe_context *pctx, struct pipe_fence_handle **fencep,
52
45
struct fd_context *ctx = fd_context(pctx);
53
46
struct pipe_fence_handle *fence = NULL;
54
// TODO we want to lookup batch if it exists, but not create one if not.
55
struct fd_batch *batch = fd_context_batch(ctx);
57
DBG("%p: flush: flags=%x\n", ctx->batch, flags);
47
struct fd_batch *batch = NULL;
49
/* We want to lookup current batch if it exists, but not create a new
50
* one if not (unless we need a fence)
52
fd_batch_reference(&batch, ctx->batch);
54
DBG("%p: flush: flags=%x", batch, flags);
59
56
/* In some sequence of events, we can end up with a last_fence that is
60
57
* not an "fd" fence, which results in eglDupNativeFenceFDANDROID()
198
struct fd_batch *batch = fd_context_batch_locked(ctx);
197
200
ctx->batch->needs_flush = true;
199
202
if (ctx->screen->gpu_id >= 500) {
200
fd_emit_string5(ctx->batch->draw, string, len);
203
fd_emit_string5(batch->draw, string, len);
202
fd_emit_string(ctx->batch->draw, string, len);
205
fd_emit_string(batch->draw, string, len);
208
fd_batch_unlock_submit(batch);
209
fd_batch_reference(&batch, NULL);
213
* If we have a pending fence_server_sync() (GPU side sync), flush now.
214
* The alternative to try to track this with batch dependencies gets
217
* Call this before switching to a different batch, to handle this case.
220
fd_context_switch_from(struct fd_context *ctx)
222
if (ctx->batch && (ctx->batch->in_fence_fd != -1))
223
fd_batch_flush(ctx->batch);
227
* If there is a pending fence-fd that we need to sync on, this will
228
* transfer the reference to the next batch we are going to render
232
fd_context_switch_to(struct fd_context *ctx, struct fd_batch *batch)
234
if (ctx->in_fence_fd != -1) {
235
sync_accumulate("freedreno", &batch->in_fence_fd, ctx->in_fence_fd);
236
close(ctx->in_fence_fd);
237
ctx->in_fence_fd = -1;
242
* Return a reference to the current batch, caller must unref.
245
fd_context_batch(struct fd_context *ctx)
247
struct fd_batch *batch = NULL;
249
fd_batch_reference(&batch, ctx->batch);
251
if (unlikely(!batch)) {
252
batch = fd_batch_from_fb(&ctx->screen->batch_cache, ctx, &ctx->framebuffer);
253
util_copy_framebuffer_state(&batch->framebuffer, &ctx->framebuffer);
254
fd_batch_reference(&ctx->batch, batch);
255
fd_context_all_dirty(ctx);
257
fd_context_switch_to(ctx, batch);
263
* Return a locked reference to the current batch. A batch with emit
264
* lock held is protected against flushing while the lock is held.
265
* The emit-lock should be acquired before screen-lock. The emit-lock
266
* should be held while emitting cmdstream.
269
fd_context_batch_locked(struct fd_context *ctx)
271
struct fd_batch *batch = NULL;
274
batch = fd_context_batch(ctx);
275
if (!fd_batch_lock_submit(batch)) {
276
fd_batch_reference(&batch, NULL);
215
292
list_del(&ctx->node);
216
293
fd_screen_unlock(ctx->screen);
218
fd_log_process(ctx, true);
219
assert(list_is_empty(&ctx->log_chunks));
221
295
fd_fence_ref(&ctx->last_fence, NULL);
223
297
if (ctx->in_fence_fd != -1)
224
298
close(ctx->in_fence_fd);
300
for (i = 0; i < ARRAY_SIZE(ctx->pvtmem); i++) {
301
if (ctx->pvtmem[i].bo)
302
fd_bo_del(ctx->pvtmem[i].bo);
226
305
util_copy_framebuffer_state(&ctx->framebuffer, NULL);
227
306
fd_batch_reference(&ctx->batch, NULL); /* unref current batch */
228
307
fd_bc_invalidate_context(ctx);
253
332
fd_device_del(ctx->dev);
254
333
fd_pipe_del(ctx->pipe);
256
mtx_destroy(&ctx->gmem_lock);
335
simple_mtx_destroy(&ctx->gmem_lock);
337
u_trace_context_fini(&ctx->trace_context);
258
339
if (fd_mesa_debug & (FD_DBG_BSTAT | FD_DBG_MSGS)) {
259
340
printf("batch_total=%u, batch_sysmem=%u, batch_gmem=%u, batch_nondraw=%u, batch_restore=%u\n",
393
fd_trace_record_ts(struct u_trace *ut, struct pipe_resource *timestamps,
396
struct fd_batch *batch = container_of(ut, struct fd_batch, trace);
397
struct fd_ringbuffer *ring = batch->nondraw ? batch->draw : batch->gmem;
399
if (ring->cur == batch->last_timestamp_cmd) {
400
uint64_t *ts = fd_bo_map(fd_resource(timestamps)->bo);
401
ts[idx] = U_TRACE_NO_TIMESTAMP;
405
unsigned ts_offset = idx * sizeof(uint64_t);
406
batch->ctx->record_timestamp(ring, fd_resource(timestamps)->bo, ts_offset);
407
batch->last_timestamp_cmd = ring->cur;
411
fd_trace_read_ts(struct u_trace_context *utctx,
412
struct pipe_resource *timestamps, unsigned idx)
414
struct fd_context *ctx = container_of(utctx, struct fd_context, trace_context);
415
struct fd_bo *ts_bo = fd_resource(timestamps)->bo;
417
/* Only need to stall on results for the first entry: */
419
int ret = fd_bo_cpu_prep(ts_bo, ctx->pipe, DRM_FREEDRENO_PREP_READ);
421
return U_TRACE_NO_TIMESTAMP;
424
uint64_t *ts = fd_bo_map(ts_bo);
426
/* Don't translate the no-timestamp marker: */
427
if (ts[idx] == U_TRACE_NO_TIMESTAMP)
428
return U_TRACE_NO_TIMESTAMP;
430
return ctx->ts_to_ns(ts[idx]);
311
433
/* TODO we could combine a few of these small buffers (solid_vbuf,
312
434
* blit_texcoord_vbuf, and vsc_size_mem, into a single buffer and
313
435
* save a tiny bit of memory
462
584
list_inithead(&ctx->hw_active_queries);
463
585
list_inithead(&ctx->acc_active_queries);
464
list_inithead(&ctx->log_chunks);
466
587
fd_screen_lock(ctx->screen);
588
ctx->seqno = ++screen->ctx_seqno;
467
589
list_add(&ctx->node, &ctx->screen->context_list);
468
590
fd_screen_unlock(ctx->screen);
470
592
ctx->current_scissor = &ctx->disabled_scissor;
472
ctx->log_out = stdout;
474
if ((fd_mesa_debug & FD_DBG_LOG) &&
475
!(ctx->record_timestamp && ctx->ts_to_ns)) {
476
printf("logging not supported!\n");
477
fd_mesa_debug &= ~FD_DBG_LOG;
480
#if DETECT_OS_ANDROID
481
if (fd_mesa_debug & FD_DBG_LOG) {
482
static unsigned idx = 0;
484
asprintf(&p, "/data/fdlog/%s-%d.log", util_get_process_name(), idx++);
486
FILE *f = fopen(p, "w");
594
u_trace_context_init(&ctx->trace_context, pctx,
595
fd_trace_record_ts, fd_trace_read_ts);