Mesa (master): trace/rbug: Add rbug integration for remote debugging

Jakob Bornecrantz wallbraker at kemper.freedesktop.org
Mon Jun 1 10:44:59 UTC 2009


Module: Mesa
Branch: master
Commit: 01fa34cb98d9ea6008c7108b6112348e278864f4
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=01fa34cb98d9ea6008c7108b6112348e278864f4

Author: Jakob Bornecrantz <jakob at vmware.com>
Date:   Mon Jun  1 11:19:55 2009 +0100

trace/rbug: Add rbug integration for remote debugging

---

 src/gallium/drivers/trace/Makefile    |    1 +
 src/gallium/drivers/trace/README      |   18 +-
 src/gallium/drivers/trace/SConscript  |    1 +
 src/gallium/drivers/trace/tr_rbug.c   |  636 +++++++++++++++++++++++++++++++++
 src/gallium/drivers/trace/tr_screen.c |   14 +-
 src/gallium/drivers/trace/tr_screen.h |   21 +-
 6 files changed, 685 insertions(+), 6 deletions(-)

diff --git a/src/gallium/drivers/trace/Makefile b/src/gallium/drivers/trace/Makefile
index ecb69fb..4aeb8e3 100644
--- a/src/gallium/drivers/trace/Makefile
+++ b/src/gallium/drivers/trace/Makefile
@@ -10,6 +10,7 @@ C_SOURCES = \
 	tr_dump_state.c \
 	tr_screen.c \
 	tr_state.c \
+	tr_rbug.c \
 	tr_texture.c
 
 include ../../Makefile.template
diff --git a/src/gallium/drivers/trace/README b/src/gallium/drivers/trace/README
index 73dce20..1000c31 100644
--- a/src/gallium/drivers/trace/README
+++ b/src/gallium/drivers/trace/README
@@ -3,7 +3,8 @@
 
 = About =
 
-This directory contains a Gallium3D pipe driver which traces all incoming calls.
+This directory contains a Gallium3D debugger pipe driver.
+It can traces all incoming calls and/or provide remote debugging functionality.
 
 
 = Build Instructions =
@@ -23,7 +24,9 @@ ensure the right libGL.so is being picked by doing
 
  ldd progs/trivial/tri 
 
-and then try running
+== Traceing ==
+
+For traceing then do
 
  export XMESA_TRACE=y
  GALLIUM_TRACE=tri.trace progs/trivial/tri
@@ -32,6 +35,16 @@ which should create a tri.trace file, which is an XML file. You can view copying
 trace.xsl to the same directory, and opening with a XSLT capable browser such as 
 Firefox or Internet Explorer.
 
+== Remote debugging ==
+
+For remote debugging
+
+ export XMESA_TRACE=y
+ GALLIUM_RBUG=true progs/trivial/tri
+
+which should open gallium remote debugging session. While the program is running
+you can launch the small remote debugging application from progs/rbug. More
+information is in that directory.
 
 = Integrating =
 
@@ -62,3 +75,4 @@ trace_screen with real_screen when creating them.
 
 --
 Jose Fonseca <jrfonseca at tungstengraphics.com>
+Jakob Bornecrantz <jakob at vmware.com>
diff --git a/src/gallium/drivers/trace/SConscript b/src/gallium/drivers/trace/SConscript
index 9b5af0d..e635fed 100644
--- a/src/gallium/drivers/trace/SConscript
+++ b/src/gallium/drivers/trace/SConscript
@@ -11,6 +11,7 @@ trace = env.ConvenienceLibrary(
         'tr_dump_state.c',
         'tr_screen.c',
         'tr_state.c',
+        'tr_rbug.c',
         'tr_texture.c',
     ])
 
diff --git a/src/gallium/drivers/trace/tr_rbug.c b/src/gallium/drivers/trace/tr_rbug.c
new file mode 100644
index 0000000..1b26f60
--- /dev/null
+++ b/src/gallium/drivers/trace/tr_rbug.c
@@ -0,0 +1,636 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include "util/u_string.h"
+#include "util/u_memory.h"
+#include "util/u_simple_list.h"
+#include "util/u_network.h"
+
+#include "tgsi/tgsi_parse.h"
+
+#include "tr_dump.h"
+#include "tr_state.h"
+#include "tr_buffer.h"
+#include "tr_texture.h"
+
+#include "rbug/rbug.h"
+
+#include <errno.h>
+
+#if defined(PIPE_SUBSYSTEM_WINDOWS_USER)
+#  define sleep Sleep
+#elif defined(PIPE_OS_LINUX)
+void usleep(int);
+#  define sleep usleep
+#else
+#  warning "No socket implementation"
+#endif
+
+#define U642VOID(x) ((void *)(unsigned long)(x))
+#define VOID2U64(x) ((uint64_t)(unsigned long)(x))
+
+struct trace_rbug
+{
+   struct trace_screen *tr_scr;
+   struct rbug_connection *con;
+   pipe_thread thread;
+   boolean running;
+};
+
+PIPE_THREAD_ROUTINE(trace_rbug_thread, void_tr_rbug);
+
+
+/**********************************************************
+ * Helper functions
+ */
+
+
+static struct trace_context *
+trace_rbug_get_context_locked(struct trace_screen *tr_scr, rbug_context_t ctx)
+{
+   struct trace_context *tr_ctx = NULL;
+   struct tr_list *ptr;
+
+   foreach(ptr, &tr_scr->contexts) {
+      tr_ctx = (struct trace_context *)((char*)ptr - offsetof(struct trace_context, list));
+      if (ctx == VOID2U64(tr_ctx))
+         break;
+      tr_ctx = NULL;
+   }
+
+   return tr_ctx;
+}
+
+static struct trace_shader *
+trace_rbug_get_shader_locked(struct trace_context *tr_ctx, rbug_shader_t shdr)
+{
+   struct trace_shader *tr_shdr = NULL;
+   struct tr_list *ptr;
+
+   foreach(ptr, &tr_ctx->shaders) {
+      tr_shdr = (struct trace_shader *)((char*)ptr - offsetof(struct trace_shader, list));
+      if (shdr == VOID2U64(tr_shdr))
+         break;
+      tr_shdr = NULL;
+   }
+
+   return tr_shdr;
+}
+
+static void *
+trace_shader_create_locked(struct pipe_context *pipe,
+                           struct trace_shader *tr_shdr,
+                           struct tgsi_token *tokens)
+{
+   void *state = NULL;
+   struct pipe_shader_state pss = { 0 };
+   pss.tokens = tokens;
+
+   if (tr_shdr->type == TRACE_SHADER_FRAGMENT) {
+      state = pipe->create_fs_state(pipe, &pss);
+   } else if (tr_shdr->type == TRACE_SHADER_VERTEX) {
+      state = pipe->create_vs_state(pipe, &pss);
+   } else
+      assert(0);
+
+   return state;
+}
+
+static void
+trace_shader_bind_locked(struct pipe_context *pipe,
+                         struct trace_shader *tr_shdr,
+                         void *state)
+{
+   if (tr_shdr->type == TRACE_SHADER_FRAGMENT) {
+      pipe->bind_fs_state(pipe, state);
+   } else if (tr_shdr->type == TRACE_SHADER_VERTEX) {
+      pipe->bind_vs_state(pipe, state);
+   } else
+      assert(0);
+}
+
+static void
+trace_shader_delete_locked(struct pipe_context *pipe,
+                           struct trace_shader *tr_shdr,
+                           void *state)
+{
+   if (tr_shdr->type == TRACE_SHADER_FRAGMENT) {
+      pipe->delete_fs_state(pipe, state);
+   } else if (tr_shdr->type == TRACE_SHADER_VERTEX) {
+      pipe->delete_vs_state(pipe, state);
+   } else
+      assert(0);
+}
+
+/************************************************
+ * Request handler functions
+ */
+
+
+static int
+trace_rbug_texture_list(struct trace_rbug *tr_rbug, struct rbug_header *header, uint32_t serial)
+{
+   struct trace_screen *tr_scr = tr_rbug->tr_scr;
+   struct trace_texture *tr_tex = NULL;
+   struct tr_list *ptr;
+   rbug_texture_t *texs;
+   int i = 0;
+
+   pipe_mutex_lock(tr_scr->list_mutex);
+   texs = MALLOC(tr_scr->num_textures * sizeof(rbug_texture_t));
+   foreach(ptr, &tr_scr->textures) {
+      tr_tex = (struct trace_texture *)((char*)ptr - offsetof(struct trace_texture, list));
+      texs[i++] = VOID2U64(tr_tex);
+   }
+   pipe_mutex_unlock(tr_scr->list_mutex);
+
+   rbug_send_texture_list_reply(tr_rbug->con, serial, texs, i, NULL);
+   FREE(texs);
+
+   return 0;
+}
+
+static int
+trace_rbug_texture_info(struct trace_rbug *tr_rbug, struct rbug_header *header, uint32_t serial)
+{
+   struct trace_screen *tr_scr = tr_rbug->tr_scr;
+   struct trace_texture *tr_tex;
+   struct rbug_proto_texture_info *gpti = (struct rbug_proto_texture_info *)header;
+   struct tr_list *ptr;
+   struct pipe_texture *t;
+
+   pipe_mutex_lock(tr_scr->list_mutex);
+   foreach(ptr, &tr_scr->textures) {
+      tr_tex = (struct trace_texture *)((char*)ptr - offsetof(struct trace_texture, list));
+      if (gpti->texture == VOID2U64(tr_tex))
+         break;
+      tr_tex = NULL;
+   }
+
+   if (!tr_tex) {
+      pipe_mutex_unlock(tr_scr->list_mutex);
+      return -ESRCH;
+   }
+
+   t = tr_tex->texture;
+   rbug_send_texture_info_reply(tr_rbug->con, serial,
+                               t->target, t->format,
+                               t->width, t->last_level + 1,
+                               t->height, t->last_level + 1,
+                               t->depth, t->last_level + 1,
+                               t->block.width, t->block.height, t->block.size,
+                               t->last_level,
+                               t->nr_samples,
+                               t->tex_usage,
+                               NULL);
+
+   pipe_mutex_unlock(tr_scr->list_mutex);
+
+   return 0;
+}
+
+static int
+trace_rbug_texture_read(struct trace_rbug *tr_rbug, struct rbug_header *header, uint32_t serial)
+{
+   struct rbug_proto_texture_read *gptr = (struct rbug_proto_texture_read *)header;
+
+   struct trace_screen *tr_scr = tr_rbug->tr_scr;
+   struct trace_texture *tr_tex;
+   struct tr_list *ptr;
+
+   struct pipe_screen *screen = tr_scr->screen;
+   struct pipe_texture *tex;
+   struct pipe_transfer *t;
+
+   void *map;
+
+   pipe_mutex_lock(tr_scr->list_mutex);
+   foreach(ptr, &tr_scr->textures) {
+      tr_tex = (struct trace_texture *)((char*)ptr - offsetof(struct trace_texture, list));
+      if (gptr->texture == VOID2U64(tr_tex))
+         break;
+      tr_tex = NULL;
+   }
+
+   if (!tr_tex) {
+      pipe_mutex_unlock(tr_scr->list_mutex);
+      return -ESRCH;
+   }
+
+   tex = tr_tex->texture;
+   t = screen->get_tex_transfer(tr_scr->screen, tex,
+                                gptr->face, gptr->level, gptr->zslice,
+                                PIPE_TRANSFER_READ,
+                                gptr->x, gptr->y, gptr->w, gptr->h);
+
+   map = screen->transfer_map(screen, t);
+
+   rbug_send_texture_read_reply(tr_rbug->con, serial,
+                                t->format,
+                                t->block.width, t->block.height, t->block.size,
+                                (uint8_t*)map, t->stride * t->nblocksy,
+                                t->stride,
+                                NULL);
+
+   screen->transfer_unmap(screen, t);
+   screen->tex_transfer_destroy(t);
+
+   pipe_mutex_unlock(tr_scr->list_mutex);
+
+   return 0;
+}
+
+static int
+trace_rbug_context_list(struct trace_rbug *tr_rbug, struct rbug_header *header, uint32_t serial)
+{
+   struct trace_screen *tr_scr = tr_rbug->tr_scr;
+   struct tr_list *ptr;
+   struct trace_context *tr_ctx = NULL;
+   rbug_context_t *ctxs;
+   int i = 0;
+
+   pipe_mutex_lock(tr_scr->list_mutex);
+   ctxs = MALLOC(tr_scr->num_contexts * sizeof(rbug_context_t));
+   foreach(ptr, &tr_scr->contexts) {
+      tr_ctx = (struct trace_context *)((char*)ptr - offsetof(struct trace_context, list));
+      ctxs[i++] = VOID2U64(tr_ctx);
+   }
+   pipe_mutex_unlock(tr_scr->list_mutex);
+
+   rbug_send_context_list_reply(tr_rbug->con, serial, ctxs, i, NULL);
+   FREE(ctxs);
+
+   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;
+
+   struct trace_screen *tr_scr = tr_rbug->tr_scr;
+   struct trace_context *tr_ctx = NULL;
+   struct trace_shader *tr_shdr = NULL;
+   struct tr_list *ptr;
+   rbug_shader_t *shdrs;
+   int i = 0;
+
+   pipe_mutex_lock(tr_scr->list_mutex);
+   tr_ctx = trace_rbug_get_context_locked(tr_scr, list->context);
+
+   if (!tr_ctx) {
+      pipe_mutex_unlock(tr_scr->list_mutex);
+      return -ESRCH;
+   }
+
+   pipe_mutex_lock(tr_ctx->list_mutex);
+   shdrs = MALLOC(tr_ctx->num_shaders * sizeof(rbug_shader_t));
+   foreach(ptr, &tr_ctx->shaders) {
+      tr_shdr = (struct trace_shader *)((char*)ptr - offsetof(struct trace_shader, list));
+      shdrs[i++] = VOID2U64(tr_shdr);
+   }
+
+   pipe_mutex_unlock(tr_ctx->list_mutex);
+   pipe_mutex_unlock(tr_scr->list_mutex);
+
+   rbug_send_shader_list_reply(tr_rbug->con, serial, shdrs, i, NULL);
+   FREE(shdrs);
+
+   return 0;
+}
+
+static int
+trace_rbug_shader_info(struct trace_rbug *tr_rbug, struct rbug_header *header, uint32_t serial)
+{
+   struct rbug_proto_shader_info *info = (struct rbug_proto_shader_info *)header;
+
+   struct trace_screen *tr_scr = tr_rbug->tr_scr;
+   struct trace_context *tr_ctx = NULL;
+   struct trace_shader *tr_shdr = NULL;
+   unsigned original_len;
+   unsigned replaced_len;
+
+   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;
+   }
+
+   pipe_mutex_lock(tr_ctx->list_mutex);
+
+   tr_shdr = trace_rbug_get_shader_locked(tr_ctx, info->shader);
+
+   if (!tr_shdr) {
+      pipe_mutex_unlock(tr_ctx->list_mutex);
+      pipe_mutex_unlock(tr_scr->list_mutex);
+      return -ESRCH;
+   }
+
+   /* just in case */
+   assert(sizeof(struct tgsi_token) == 4);
+
+   original_len = tgsi_num_tokens(tr_shdr->tokens);
+   if (tr_shdr->replaced_tokens)
+      replaced_len = tgsi_num_tokens(tr_shdr->replaced_tokens);
+   else
+      replaced_len = 0;
+
+   rbug_send_shader_info_reply(tr_rbug->con, serial,
+                               (uint32_t*)tr_shdr->tokens, original_len,
+                               (uint32_t*)tr_shdr->replaced_tokens, replaced_len,
+                               tr_shdr->disabled,
+                               NULL);
+
+   pipe_mutex_unlock(tr_ctx->list_mutex);
+   pipe_mutex_unlock(tr_scr->list_mutex);
+
+   return 0;
+}
+
+static int
+trace_rbug_shader_disable(struct trace_rbug *tr_rbug, struct rbug_header *header)
+{
+   struct rbug_proto_shader_disable *dis = (struct rbug_proto_shader_disable *)header;
+
+   struct trace_screen *tr_scr = tr_rbug->tr_scr;
+   struct trace_context *tr_ctx = NULL;
+   struct trace_shader *tr_shdr = NULL;
+
+   pipe_mutex_lock(tr_scr->list_mutex);
+   tr_ctx = trace_rbug_get_context_locked(tr_scr, dis->context);
+
+   if (!tr_ctx) {
+      pipe_mutex_unlock(tr_scr->list_mutex);
+      return -ESRCH;
+   }
+
+   pipe_mutex_lock(tr_ctx->list_mutex);
+
+   tr_shdr = trace_rbug_get_shader_locked(tr_ctx, dis->shader);
+
+   if (!tr_shdr) {
+      pipe_mutex_unlock(tr_ctx->list_mutex);
+      pipe_mutex_unlock(tr_scr->list_mutex);
+      return -ESRCH;
+   }
+
+   tr_shdr->disabled = dis->disable;
+
+   pipe_mutex_unlock(tr_ctx->list_mutex);
+   pipe_mutex_unlock(tr_scr->list_mutex);
+
+   return 0;
+}
+
+static int
+trace_rbug_shader_replace(struct trace_rbug *tr_rbug, struct rbug_header *header)
+{
+   struct rbug_proto_shader_replace *rep = (struct rbug_proto_shader_replace *)header;
+
+   struct trace_screen *tr_scr = tr_rbug->tr_scr;
+   struct trace_context *tr_ctx = NULL;
+   struct trace_shader *tr_shdr = NULL;
+   struct pipe_context *pipe = NULL;
+   void *state;
+
+   pipe_mutex_lock(tr_scr->list_mutex);
+   tr_ctx = trace_rbug_get_context_locked(tr_scr, rep->context);
+
+   if (!tr_ctx) {
+      pipe_mutex_unlock(tr_scr->list_mutex);
+      return -ESRCH;
+   }
+
+   pipe_mutex_lock(tr_ctx->list_mutex);
+
+   tr_shdr = trace_rbug_get_shader_locked(tr_ctx, rep->shader);
+
+   if (!tr_shdr) {
+      pipe_mutex_unlock(tr_ctx->list_mutex);
+      pipe_mutex_unlock(tr_scr->list_mutex);
+      return -ESRCH;
+   }
+
+   /* protect the pipe context */
+   trace_dump_call_lock();
+
+   pipe = tr_ctx->pipe;
+
+   /* remove old replaced shader */
+   if (tr_shdr->replaced) {
+      if (tr_ctx->curr.fs == tr_shdr || tr_ctx->curr.vs == tr_shdr)
+         trace_shader_bind_locked(pipe, tr_shdr, tr_shdr->state);
+
+      FREE(tr_shdr->replaced_tokens);
+      trace_shader_delete_locked(pipe, tr_shdr, tr_shdr->replaced);
+      tr_shdr->replaced = NULL;
+      tr_shdr->replaced_tokens = NULL;
+   }
+
+   /* empty inputs means restore old which we did above */
+   if (rep->tokens_len == 0)
+      goto out;
+
+   tr_shdr->replaced_tokens = tgsi_dup_tokens((struct tgsi_token *)rep->tokens);
+   if (!tr_shdr->replaced_tokens)
+      goto err;
+
+   state = trace_shader_create_locked(pipe, tr_shdr, tr_shdr->replaced_tokens);
+   if (!state)
+      goto err;
+
+   /* bind new shader if the shader is currently a bound */
+   if (tr_ctx->curr.fs == tr_shdr || tr_ctx->curr.vs == tr_shdr)
+      trace_shader_bind_locked(pipe, tr_shdr, state);
+
+   /* save state */
+   tr_shdr->replaced = state;
+
+out:
+   trace_dump_call_unlock();
+   pipe_mutex_unlock(tr_ctx->list_mutex);
+   pipe_mutex_unlock(tr_scr->list_mutex);
+
+   return 0;
+
+err:
+   FREE(tr_shdr->replaced_tokens);
+   tr_shdr->replaced = NULL;
+   tr_shdr->replaced_tokens = NULL;
+
+   trace_dump_call_unlock();
+   pipe_mutex_unlock(tr_ctx->list_mutex);
+   pipe_mutex_unlock(tr_scr->list_mutex);
+   return -EINVAL;
+}
+
+static boolean
+trace_rbug_header(struct trace_rbug *tr_rbug, struct rbug_header *header, uint32_t serial)
+{
+   int ret = 0;
+
+   switch(header->opcode) {
+      case RBUG_OP_PING:
+         rbug_send_ping_reply(tr_rbug->con, serial, NULL);
+         break;
+      case RBUG_OP_TEXTURE_LIST:
+         ret = trace_rbug_texture_list(tr_rbug, header, serial);
+         break;
+      case RBUG_OP_TEXTURE_INFO:
+         ret = trace_rbug_texture_info(tr_rbug, header, serial);
+         break;
+      case RBUG_OP_TEXTURE_READ:
+         ret = trace_rbug_texture_read(tr_rbug, header, serial);
+         break;
+      case RBUG_OP_CONTEXT_LIST:
+         ret = trace_rbug_context_list(tr_rbug, header, serial);
+         break;
+      case RBUG_OP_SHADER_LIST:
+         ret = trace_rbug_shader_list(tr_rbug, header, serial);
+         break;
+      case RBUG_OP_SHADER_INFO:
+         ret = trace_rbug_shader_info(tr_rbug, header, serial);
+         break;
+      case RBUG_OP_SHADER_DISABLE:
+         ret = trace_rbug_shader_disable(tr_rbug, header);
+         break;
+      case RBUG_OP_SHADER_REPLACE:
+         ret = trace_rbug_shader_replace(tr_rbug, header);
+         break;
+      default:
+         debug_printf("%s - unsupported opcode %u\n", __FUNCTION__, header->opcode);
+         ret = -ENOSYS;
+         break;
+   }
+   rbug_free_header(header);
+
+   if (ret)
+      rbug_send_error_reply(tr_rbug->con, serial, ret, NULL);
+
+   return TRUE;
+}
+
+static void
+trace_rbug_con(struct trace_rbug *tr_rbug)
+{
+   struct rbug_header *header;
+   uint32_t serial;
+
+   debug_printf("%s - connection received\n", __FUNCTION__);
+
+   while(tr_rbug->running) {
+      header = rbug_get_message(tr_rbug->con, &serial);
+      if (!header)
+         break;
+
+      if (!trace_rbug_header(tr_rbug, header, serial))
+         break;
+   }
+
+   debug_printf("%s - connection closed\n", __FUNCTION__);
+
+   rbug_disconnect(tr_rbug->con);
+   tr_rbug->con = NULL;
+}
+
+PIPE_THREAD_ROUTINE(trace_rbug_thread, void_tr_rbug)
+{
+   struct trace_rbug *tr_rbug = void_tr_rbug;
+   uint16_t port = 13370;
+   int s = -1;
+   int c;
+
+   u_socket_init();
+
+   for (;port <= 13379 && s < 0; port++)
+      s = u_socket_listen_on_port(port);
+
+   if (s < 0) {
+      debug_printf("trace_rbug - failed to listen\n");
+      return NULL;
+   }
+
+   u_socket_block(s, false);
+
+   debug_printf("trace_rbug - remote debugging listening on port %u\n", --port);
+
+   while(tr_rbug->running) {
+      sleep(1);
+
+      c = u_socket_accept(s);
+      if (c < 0)
+         continue;
+
+      u_socket_block(c, true);
+      tr_rbug->con = rbug_from_socket(c);
+
+      trace_rbug_con(tr_rbug);
+
+      u_socket_close(c);
+   }
+
+   u_socket_close(s);
+
+   u_socket_stop();
+
+   return NULL;
+}
+
+/**********************************************************
+ *
+ */
+
+struct trace_rbug *
+trace_rbug_start(struct trace_screen *tr_scr)
+{
+   struct trace_rbug *tr_rbug = MALLOC_STRUCT(trace_rbug);
+   if (!tr_rbug)
+      return NULL;
+
+   tr_rbug->tr_scr = tr_scr;
+   tr_rbug->running = TRUE;
+   tr_rbug->thread = pipe_thread_create(trace_rbug_thread, tr_rbug);
+
+   return tr_rbug;
+}
+
+void
+trace_rbug_stop(struct trace_rbug *tr_rbug)
+{
+   if (!tr_rbug)
+      return;
+
+   tr_rbug->running = false;
+   pipe_thread_wait(tr_rbug->thread);
+
+   FREE(tr_rbug);
+
+   return;
+}
diff --git a/src/gallium/drivers/trace/tr_screen.c b/src/gallium/drivers/trace/tr_screen.c
index bc14248..920f418 100644
--- a/src/gallium/drivers/trace/tr_screen.c
+++ b/src/gallium/drivers/trace/tr_screen.c
@@ -826,24 +826,26 @@ trace_screen_destroy(struct pipe_screen *_screen)
    trace_dump_call_end();
    trace_dump_trace_end();
 
+   if (tr_scr->rbug)
+      trace_rbug_stop(tr_scr->rbug);
+
    screen->destroy(screen);
 
    FREE(tr_scr);
 }
 
-
 boolean
 trace_enabled(void)
 {
    return trace;
 }
 
-
 struct pipe_screen *
 trace_screen_create(struct pipe_screen *screen)
 {
    struct trace_screen *tr_scr;
    struct pipe_winsys *winsys;
+   boolean rbug = FALSE;
 
    if(!screen)
       goto error1;
@@ -855,6 +857,11 @@ trace_screen_create(struct pipe_screen *screen)
       trace = TRUE;
    }
 
+   if (debug_get_bool_option("GALLIUM_RBUG", FALSE)) {
+      trace = TRUE;
+      rbug = TRUE;
+   }
+
    if (!trace)
       goto error1;
 
@@ -915,6 +922,9 @@ trace_screen_create(struct pipe_screen *screen)
    trace_dump_ret(ptr, screen);
    trace_dump_call_end();
 
+   if (rbug)
+      tr_scr->rbug = trace_rbug_start(tr_scr);
+
    return &tr_scr->base;
 
 #if 0
diff --git a/src/gallium/drivers/trace/tr_screen.h b/src/gallium/drivers/trace/tr_screen.h
index 7fae182..dba8cd7 100644
--- a/src/gallium/drivers/trace/tr_screen.h
+++ b/src/gallium/drivers/trace/tr_screen.h
@@ -57,6 +57,9 @@ struct trace_screen
 
    struct pipe_screen *screen;
 
+   /* remote debugger */
+   struct trace_rbug *rbug;
+
    pipe_mutex list_mutex;
    int num_buffers;
    int num_contexts;
@@ -72,20 +75,33 @@ struct trace_screen
 
 
 /*
+ * tr_rbug.c
+ */
+
+
+struct trace_rbug;
+
+struct trace_rbug *
+trace_rbug_start(struct trace_screen *tr_scr);
+
+void
+trace_rbug_stop(struct trace_rbug *tr_rbug);
+
+
+/*
  * tr_screen.c
  */
 
+
 boolean
 trace_enabled(void);
 
 struct trace_screen *
 trace_screen(struct pipe_screen *screen);
 
-
 struct pipe_screen *
 trace_screen_create(struct pipe_screen *screen);
 
-
 void
 trace_screen_user_buffer_update(struct pipe_screen *screen,
                                 struct pipe_buffer *buffer);
@@ -106,6 +122,7 @@ trace_screen_user_buffer_update(struct pipe_screen *screen,
       pipe_mutex_unlock(tr_scr->list_mutex);             \
    } while (0)
 
+
 #ifdef __cplusplus
 }
 #endif




More information about the mesa-commit mailing list