trace/rbug: Add new contexts functions to trace rbug
diff --git a/src/gallium/drivers/trace/tr_context.c b/src/gallium/drivers/trace/tr_context.c
index 2ad5ca4..b04cc2c 100644
--- a/src/gallium/drivers/trace/tr_context.c
+++ b/src/gallium/drivers/trace/tr_context.c
@@ -113,6 +113,28 @@
}
+static INLINE void
+trace_context_draw_block(struct trace_context *tr_ctx, int flag)
+{
+ pipe_mutex_lock(tr_ctx->draw_mutex);
+
+ if (tr_ctx->draw_blocker & flag) {
+ tr_ctx->draw_blocked |= flag;
+
+ trace_rbug_notify_draw_blocked(tr_ctx);
+ }
+
+ /* wait for rbug to clear the blocked flag */
+ while (tr_ctx->draw_blocked & flag) {
+ tr_ctx->draw_blocked |= flag;
+ pipe_mutex_unlock(tr_ctx->draw_mutex);
+ /* TODO sleep or use conditional */
+ pipe_mutex_lock(tr_ctx->draw_mutex);
+ }
+
+ pipe_mutex_unlock(tr_ctx->draw_mutex);
+}
+
static INLINE boolean
trace_context_draw_arrays(struct pipe_context *_pipe,
unsigned mode, unsigned start, unsigned count)
@@ -124,6 +146,8 @@
if (tr_ctx->curr.fs->disabled || tr_ctx->curr.vs->disabled)
return 0;
+ trace_context_draw_block(tr_ctx, 1);
+
trace_dump_call_begin("pipe_context", "draw_arrays");
trace_dump_arg(ptr, pipe);
@@ -137,6 +161,8 @@
trace_dump_call_end();
+ trace_context_draw_block(tr_ctx, 2);
+
return result;
}
@@ -156,6 +182,8 @@
if (tr_ctx->curr.fs->disabled || tr_ctx->curr.vs->disabled)
return 0;
+ trace_context_draw_block(tr_ctx, 1);
+
trace_screen_user_buffer_update(_pipe->screen, indexBuffer);
trace_dump_call_begin("pipe_context", "draw_elements");
@@ -173,6 +201,8 @@
trace_dump_call_end();
+ trace_context_draw_block(tr_ctx, 2);
+
return result;
}
@@ -196,6 +226,8 @@
if (tr_ctx->curr.fs->disabled || tr_ctx->curr.vs->disabled)
return 0;
+ trace_context_draw_block(tr_ctx, 1);
+
trace_screen_user_buffer_update(_pipe->screen, indexBuffer);
trace_dump_call_begin("pipe_context", "draw_range_elements");
@@ -218,6 +250,8 @@
trace_dump_call_end();
+ trace_context_draw_block(tr_ctx, 2);
+
return result;
}
@@ -782,6 +816,19 @@
struct pipe_framebuffer_state unwrapped_state;
unsigned i;
+ {
+ tr_ctx->curr.nr_cbufs = state->nr_cbufs;
+ for (i = 0; i < state->nr_cbufs; i++)
+ if (state->cbufs[i])
+ tr_ctx->curr.cbufs[i] = trace_texture(state->cbufs[i]->texture);
+ else
+ tr_ctx->curr.cbufs[i] = NULL;
+ if (state->zsbuf)
+ tr_ctx->curr.zsbuf = trace_texture(state->zsbuf->texture);
+ else
+ tr_ctx->curr.zsbuf = NULL;
+ }
+
/* Unwrap the input state */
memcpy(&unwrapped_state, state, sizeof(unwrapped_state));
for(i = 0; i < state->nr_cbufs; ++i)
@@ -1113,6 +1160,12 @@
return referenced;
}
+static const struct debug_named_value rbug_blocker_flags[] = {
+ {"before", 1},
+ {"after", 2},
+ {NULL, 0},
+};
+
struct pipe_context *
trace_context_create(struct pipe_screen *_screen,
struct pipe_context *pipe)
@@ -1134,6 +1187,10 @@
if(!tr_ctx)
goto error1;
+ tr_ctx->draw_blocker = debug_get_flags_option("RBUG_BLOCK",
+ rbug_blocker_flags,
+ 0);
+ pipe_mutex_init(tr_ctx->draw_mutex);
pipe_mutex_init(tr_ctx->list_mutex);
make_empty_list(&tr_ctx->shaders);
diff --git a/src/gallium/drivers/trace/tr_context.h b/src/gallium/drivers/trace/tr_context.h
index 86827f9..770e975 100644
--- a/src/gallium/drivers/trace/tr_context.h
+++ b/src/gallium/drivers/trace/tr_context.h
@@ -50,8 +50,16 @@
struct {
struct trace_shader *fs;
struct trace_shader *vs;
+
+ unsigned nr_cbufs;
+ struct trace_texture *cbufs[PIPE_MAX_COLOR_BUFS];
+ struct trace_texture *zsbuf;
} curr;
+ pipe_mutex draw_mutex;
+ int draw_blocker;
+ int draw_blocked;
+
/* for list on screen */
struct tr_list list;
@@ -75,6 +83,9 @@
trace_context_create(struct pipe_screen *screen,
struct pipe_context *pipe);
+void
+trace_rbug_notify_draw_blocked(struct trace_context *tr_ctx);
+
#ifdef __cplusplus
}
diff --git a/src/gallium/drivers/trace/tr_rbug.c b/src/gallium/drivers/trace/tr_rbug.c
index 1b26f60..db9de8f 100644
--- a/src/gallium/drivers/trace/tr_rbug.c
+++ b/src/gallium/drivers/trace/tr_rbug.c
@@ -289,6 +289,147 @@
}
static int
+trace_rbug_context_info(struct trace_rbug *tr_rbug, struct rbug_header *header, uint32_t serial)
+{
+ struct rbug_proto_context_info *info = (struct rbug_proto_context_info *)header;
+
+ struct trace_screen *tr_scr = tr_rbug->tr_scr;
+ struct trace_context *tr_ctx = NULL;
+ rbug_texture_t cbufs[PIPE_MAX_COLOR_BUFS];
+ int i;
+
+ pipe_mutex_lock(tr_scr->list_mutex);
+ tr_ctx = trace_rbug_get_context_locked(tr_scr, info->context);
+
+ if (!tr_ctx) {
+ pipe_mutex_unlock(tr_scr->list_mutex);
+ return -ESRCH;
+ }
+
+ /* protect the pipe context */
+ pipe_mutex_lock(tr_ctx->draw_mutex);
+ trace_dump_call_lock();
+
+ for (i = 0; i < tr_ctx->curr.nr_cbufs; i++)
+ cbufs[i] = VOID2U64(tr_ctx->curr.cbufs[i]);
+
+ rbug_send_context_info_reply(tr_rbug->con, serial,
+ VOID2U64(tr_ctx->curr.vs), VOID2U64(tr_ctx->curr.fs),
+ cbufs, tr_ctx->curr.nr_cbufs, VOID2U64(tr_ctx->curr.zsbuf),
+ tr_ctx->draw_blocker, tr_ctx->draw_blocked, NULL);
+
+ trace_dump_call_unlock();
+ pipe_mutex_unlock(tr_ctx->draw_mutex);
+
+ pipe_mutex_unlock(tr_scr->list_mutex);
+
+ return 0;
+}
+
+static int
+trace_rbug_context_draw_block(struct trace_rbug *tr_rbug, struct rbug_header *header, uint32_t serial)
+{
+ struct rbug_proto_context_draw_block *block = (struct rbug_proto_context_draw_block *)header;
+
+ struct trace_screen *tr_scr = tr_rbug->tr_scr;
+ struct trace_context *tr_ctx = NULL;
+
+ pipe_mutex_lock(tr_scr->list_mutex);
+ tr_ctx = trace_rbug_get_context_locked(tr_scr, block->context);
+
+ if (!tr_ctx) {
+ pipe_mutex_unlock(tr_scr->list_mutex);
+ return -ESRCH;
+ }
+
+ pipe_mutex_lock(tr_ctx->draw_mutex);
+ tr_ctx->draw_blocker |= block->block;
+ pipe_mutex_unlock(tr_ctx->draw_mutex);
+
+ pipe_mutex_unlock(tr_scr->list_mutex);
+
+ return 0;
+}
+
+static int
+trace_rbug_context_draw_step(struct trace_rbug *tr_rbug, struct rbug_header *header, uint32_t serial)
+{
+ struct rbug_proto_context_draw_step *step = (struct rbug_proto_context_draw_step *)header;
+
+ struct trace_screen *tr_scr = tr_rbug->tr_scr;
+ struct trace_context *tr_ctx = NULL;
+
+ pipe_mutex_lock(tr_scr->list_mutex);
+ tr_ctx = trace_rbug_get_context_locked(tr_scr, step->context);
+
+ if (!tr_ctx) {
+ pipe_mutex_unlock(tr_scr->list_mutex);
+ return -ESRCH;
+ }
+
+ pipe_mutex_lock(tr_ctx->draw_mutex);
+ tr_ctx->draw_blocked &= ~step->step;
+ pipe_mutex_unlock(tr_ctx->draw_mutex);
+
+ pipe_mutex_unlock(tr_scr->list_mutex);
+
+ return 0;
+}
+
+static int
+trace_rbug_context_draw_unblock(struct trace_rbug *tr_rbug, struct rbug_header *header, uint32_t serial)
+{
+ struct rbug_proto_context_draw_unblock *unblock = (struct rbug_proto_context_draw_unblock *)header;
+
+ struct trace_screen *tr_scr = tr_rbug->tr_scr;
+ struct trace_context *tr_ctx = NULL;
+
+ pipe_mutex_lock(tr_scr->list_mutex);
+ tr_ctx = trace_rbug_get_context_locked(tr_scr, unblock->context);
+
+ if (!tr_ctx) {
+ pipe_mutex_unlock(tr_scr->list_mutex);
+ return -ESRCH;
+ }
+
+ pipe_mutex_lock(tr_ctx->draw_mutex);
+ tr_ctx->draw_blocked &= ~unblock->unblock;
+ tr_ctx->draw_blocker &= ~unblock->unblock;
+ pipe_mutex_unlock(tr_ctx->draw_mutex);
+
+ pipe_mutex_unlock(tr_scr->list_mutex);
+
+ return 0;
+}
+
+static int
+trace_rbug_context_flush(struct trace_rbug *tr_rbug, struct rbug_header *header, uint32_t serial)
+{
+ struct rbug_proto_context_flush *flush = (struct rbug_proto_context_flush *)header;
+
+ struct trace_screen *tr_scr = tr_rbug->tr_scr;
+ struct trace_context *tr_ctx = NULL;
+
+ pipe_mutex_lock(tr_scr->list_mutex);
+ tr_ctx = trace_rbug_get_context_locked(tr_scr, flush->context);
+
+ if (!tr_ctx) {
+ pipe_mutex_unlock(tr_scr->list_mutex);
+ return -ESRCH;
+ }
+
+ /* protect the pipe context */
+ trace_dump_call_lock();
+
+ tr_ctx->pipe->flush(tr_ctx->pipe, flush->flags, NULL);
+
+ trace_dump_call_unlock();
+ pipe_mutex_unlock(tr_scr->list_mutex);
+
+ return 0;
+}
+
+static int
trace_rbug_shader_list(struct trace_rbug *tr_rbug, struct rbug_header *header, uint32_t serial)
{
struct rbug_proto_shader_list *list = (struct rbug_proto_shader_list *)header;
@@ -512,6 +653,21 @@
case RBUG_OP_CONTEXT_LIST:
ret = trace_rbug_context_list(tr_rbug, header, serial);
break;
+ case RBUG_OP_CONTEXT_INFO:
+ ret = trace_rbug_context_info(tr_rbug, header, serial);
+ break;
+ case RBUG_OP_CONTEXT_DRAW_BLOCK:
+ ret = trace_rbug_context_draw_block(tr_rbug, header, serial);
+ break;
+ case RBUG_OP_CONTEXT_DRAW_STEP:
+ ret = trace_rbug_context_draw_step(tr_rbug, header, serial);
+ break;
+ case RBUG_OP_CONTEXT_DRAW_UNBLOCK:
+ ret = trace_rbug_context_draw_unblock(tr_rbug, header, serial);
+ break;
+ case RBUG_OP_CONTEXT_FLUSH:
+ ret = trace_rbug_context_flush(tr_rbug, header, serial);
+ break;
case RBUG_OP_SHADER_LIST:
ret = trace_rbug_shader_list(tr_rbug, header, serial);
break;
@@ -610,7 +766,7 @@
struct trace_rbug *
trace_rbug_start(struct trace_screen *tr_scr)
{
- struct trace_rbug *tr_rbug = MALLOC_STRUCT(trace_rbug);
+ struct trace_rbug *tr_rbug = CALLOC_STRUCT(trace_rbug);
if (!tr_rbug)
return NULL;
@@ -634,3 +790,14 @@
return;
}
+
+void
+trace_rbug_notify_draw_blocked(struct trace_context *tr_ctx)
+{
+ struct trace_screen *tr_scr = trace_screen(tr_ctx->base.screen);
+ struct trace_rbug *tr_rbug = tr_scr->rbug;
+
+ if (tr_rbug && tr_rbug->con)
+ rbug_send_context_draw_blocked(tr_rbug->con,
+ VOID2U64(tr_ctx), tr_ctx->draw_blocked, NULL);
+}