trace/rbug: Sleep on windows when blocked
[mesa.git] / src / gallium / drivers / trace / tr_context.c
index 696b6a4f59b7d7cc9c543782d317fbe4c9305f6c..b845a649b898f45f76ea7c66b97d5ec54678c490 100644 (file)
  **************************************************************************/
 
 #include "util/u_memory.h"
+#include "util/u_simple_list.h"
+
 #include "pipe/p_screen.h"
 
 #include "tr_dump.h"
+#include "tr_dump_state.h"
 #include "tr_state.h"
 #include "tr_buffer.h"
 #include "tr_screen.h"
 #include "tr_texture.h"
-#include "tr_context.h"
 
 
 static INLINE struct pipe_buffer *
@@ -111,6 +113,34 @@ trace_context_set_edgeflags(struct pipe_context *_pipe,
 }
 
 
+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;
+#ifdef PIPE_THREAD_HAVE_CONDVAR
+      pipe_condvar_wait(tr_ctx->draw_cond, tr_ctx->draw_mutex);
+#else
+      pipe_mutex_unlock(tr_ctx->draw_mutex);
+#ifdef PIPE_SUBSYSTEM_WINDOWS_USER
+      Sleep(1);
+#endif
+      pipe_mutex_lock(tr_ctx->draw_mutex);
+#endif
+   }
+
+   pipe_mutex_unlock(tr_ctx->draw_mutex);
+}
+
 static INLINE boolean
 trace_context_draw_arrays(struct pipe_context *_pipe,
                           unsigned mode, unsigned start, unsigned count)
@@ -119,6 +149,11 @@ trace_context_draw_arrays(struct pipe_context *_pipe,
    struct pipe_context *pipe = tr_ctx->pipe;
    boolean result;
 
+   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);
@@ -132,6 +167,8 @@ trace_context_draw_arrays(struct pipe_context *_pipe,
 
    trace_dump_call_end();
 
+   trace_context_draw_block(tr_ctx, 2);
+
    return result;
 }
 
@@ -148,6 +185,11 @@ trace_context_draw_elements(struct pipe_context *_pipe,
    struct pipe_buffer *indexBuffer = tr_buf->buffer;
    boolean result;
 
+   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");
@@ -165,6 +207,8 @@ trace_context_draw_elements(struct pipe_context *_pipe,
 
    trace_dump_call_end();
 
+   trace_context_draw_block(tr_ctx, 2);
+
    return result;
 }
 
@@ -185,6 +229,11 @@ trace_context_draw_range_elements(struct pipe_context *_pipe,
    struct pipe_buffer *indexBuffer = tr_buf->buffer;
    boolean result;
 
+   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");
@@ -207,6 +256,8 @@ trace_context_draw_range_elements(struct pipe_context *_pipe,
 
    trace_dump_call_end();
 
+   trace_context_draw_block(tr_ctx, 2);
+
    return result;
 }
 
@@ -571,23 +622,32 @@ trace_context_create_fs_state(struct pipe_context *_pipe,
 
    trace_dump_call_end();
 
+   result = trace_shader_create(tr_ctx, state, result, TRACE_SHADER_FRAGMENT);
+
    return result;
 }
 
 
 static INLINE void
 trace_context_bind_fs_state(struct pipe_context *_pipe,
-                            void *state)
+                            void *_state)
 {
    struct trace_context *tr_ctx = trace_context(_pipe);
+   struct trace_shader *tr_shdr = trace_shader(_state);
    struct pipe_context *pipe = tr_ctx->pipe;
+   void *state = tr_shdr ? tr_shdr->state : NULL;
 
    trace_dump_call_begin("pipe_context", "bind_fs_state");
 
    trace_dump_arg(ptr, pipe);
    trace_dump_arg(ptr, state);
 
-   pipe->bind_fs_state(pipe, state);;
+   tr_ctx->curr.fs = tr_shdr;
+
+   if (tr_shdr && tr_shdr->replaced)
+      state = tr_shdr->replaced;
+
+   pipe->bind_fs_state(pipe, state);
 
    trace_dump_call_end();
 }
@@ -595,19 +655,23 @@ trace_context_bind_fs_state(struct pipe_context *_pipe,
 
 static INLINE void
 trace_context_delete_fs_state(struct pipe_context *_pipe,
-                              void *state)
+                              void *_state)
 {
    struct trace_context *tr_ctx = trace_context(_pipe);
+   struct trace_shader *tr_shdr = trace_shader(_state);
    struct pipe_context *pipe = tr_ctx->pipe;
+   void *state = tr_shdr->state;
 
    trace_dump_call_begin("pipe_context", "delete_fs_state");
 
    trace_dump_arg(ptr, pipe);
    trace_dump_arg(ptr, state);
 
-   pipe->delete_fs_state(pipe, state);;
+   pipe->delete_fs_state(pipe, state);
 
    trace_dump_call_end();
+
+   trace_shader_destroy(tr_ctx, tr_shdr);
 }
 
 
@@ -624,28 +688,37 @@ trace_context_create_vs_state(struct pipe_context *_pipe,
    trace_dump_arg(ptr, pipe);
    trace_dump_arg(shader_state, state);
 
-   result = pipe->create_vs_state(pipe, state);;
+   result = pipe->create_vs_state(pipe, state);
 
    trace_dump_ret(ptr, result);
 
    trace_dump_call_end();
 
+   result = trace_shader_create(tr_ctx, state, result, TRACE_SHADER_VERTEX);
+
    return result;
 }
 
 
 static INLINE void
 trace_context_bind_vs_state(struct pipe_context *_pipe,
-                            void *state)
+                            void *_state)
 {
    struct trace_context *tr_ctx = trace_context(_pipe);
+   struct trace_shader *tr_shdr = trace_shader(_state);
    struct pipe_context *pipe = tr_ctx->pipe;
+   void *state = tr_shdr ? tr_shdr->state : NULL;
 
    trace_dump_call_begin("pipe_context", "bind_vs_state");
 
    trace_dump_arg(ptr, pipe);
    trace_dump_arg(ptr, state);
 
+   tr_ctx->curr.vs = tr_shdr;
+
+   if (tr_shdr && tr_shdr->replaced)
+      state = tr_shdr->replaced;
+
    pipe->bind_vs_state(pipe, state);;
 
    trace_dump_call_end();
@@ -654,10 +727,12 @@ trace_context_bind_vs_state(struct pipe_context *_pipe,
 
 static INLINE void
 trace_context_delete_vs_state(struct pipe_context *_pipe,
-                              void *state)
+                              void *_state)
 {
    struct trace_context *tr_ctx = trace_context(_pipe);
+   struct trace_shader *tr_shdr = trace_shader(_state);
    struct pipe_context *pipe = tr_ctx->pipe;
+   void *state = tr_shdr->state;
 
    trace_dump_call_begin("pipe_context", "delete_vs_state");
 
@@ -667,6 +742,8 @@ trace_context_delete_vs_state(struct pipe_context *_pipe,
    pipe->delete_vs_state(pipe, state);;
 
    trace_dump_call_end();
+
+   trace_shader_destroy(tr_ctx, tr_shdr);
 }
 
 
@@ -745,6 +822,19 @@ trace_context_set_framebuffer_state(struct pipe_context *_pipe,
    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)
@@ -1014,16 +1104,17 @@ trace_context_flush(struct pipe_context *_pipe,
 static INLINE void
 trace_context_destroy(struct pipe_context *_pipe)
 {
+   struct trace_screen *tr_scr = trace_screen(_pipe->screen);
    struct trace_context *tr_ctx = trace_context(_pipe);
    struct pipe_context *pipe = tr_ctx->pipe;
 
    trace_dump_call_begin("pipe_context", "destroy");
-
    trace_dump_arg(ptr, pipe);
+   trace_dump_call_end();
 
-   pipe->destroy(pipe);
+   trace_screen_remove_from_list(tr_scr, contexts, tr_ctx);
 
-   trace_dump_call_end();
+   pipe->destroy(pipe);
 
    FREE(tr_ctx);
 }
@@ -1075,6 +1166,12 @@ trace_is_buffer_referenced( struct pipe_context *_pipe,
    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)
@@ -1086,7 +1183,7 @@ trace_context_create(struct pipe_screen *_screen,
    if(!pipe)
       goto error1;
 
-   if(!trace_dump_enabled())
+   if(!trace_enabled())
       goto error1;
 
    tr_scr = trace_screen(_screen);
@@ -1096,6 +1193,14 @@ trace_context_create(struct pipe_screen *_screen,
    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_condvar_init(tr_ctx->draw_cond);
+   pipe_mutex_init(tr_ctx->list_mutex);
+   make_empty_list(&tr_ctx->shaders);
+
    tr_ctx->base.winsys = _screen->winsys;
    tr_ctx->base.screen = _screen;
    tr_ctx->base.destroy = trace_context_destroy;
@@ -1150,6 +1255,8 @@ trace_context_create(struct pipe_screen *_screen,
    trace_dump_ret(ptr, pipe);
    trace_dump_call_end();
 
+   trace_screen_add_to_list(tr_scr, contexts, tr_ctx);
+
    return &tr_ctx->base;
 
 error1: