summaryrefslogtreecommitdiff
path: root/src/gallium/drivers/trace
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/drivers/trace')
-rw-r--r--src/gallium/drivers/trace/Makefile3
-rw-r--r--src/gallium/drivers/trace/README18
-rw-r--r--src/gallium/drivers/trace/SConscript2
-rw-r--r--src/gallium/drivers/trace/tr_context.c160
-rw-r--r--src/gallium/drivers/trace/tr_context.h38
-rw-r--r--src/gallium/drivers/trace/tr_drm.c211
-rw-r--r--src/gallium/drivers/trace/tr_drm.h35
-rw-r--r--src/gallium/drivers/trace/tr_dump_state.c549
-rw-r--r--src/gallium/drivers/trace/tr_dump_state.h78
-rw-r--r--src/gallium/drivers/trace/tr_rbug.c864
-rw-r--r--src/gallium/drivers/trace/tr_screen.c51
-rw-r--r--src/gallium/drivers/trace/tr_screen.h28
-rw-r--r--src/gallium/drivers/trace/tr_state.c515
-rw-r--r--src/gallium/drivers/trace/tr_state.h108
14 files changed, 2104 insertions, 556 deletions
diff --git a/src/gallium/drivers/trace/Makefile b/src/gallium/drivers/trace/Makefile
index e087db169a..dd6831c70a 100644
--- a/src/gallium/drivers/trace/Makefile
+++ b/src/gallium/drivers/trace/Makefile
@@ -7,8 +7,11 @@ C_SOURCES = \
tr_buffer.c \
tr_context.c \
tr_dump.c \
+ tr_dump_state.c \
tr_screen.c \
tr_state.c \
+ tr_rbug.c \
+ tr_drm.c \
tr_texture.c
include ../../Makefile.template
diff --git a/src/gallium/drivers/trace/README b/src/gallium/drivers/trace/README
index 73dce20372..1000c31e49 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@tungstengraphics.com>
+Jakob Bornecrantz <jakob@vmware.com>
diff --git a/src/gallium/drivers/trace/SConscript b/src/gallium/drivers/trace/SConscript
index 4215215d1a..e635fed77d 100644
--- a/src/gallium/drivers/trace/SConscript
+++ b/src/gallium/drivers/trace/SConscript
@@ -8,8 +8,10 @@ trace = env.ConvenienceLibrary(
'tr_buffer.c',
'tr_context.c',
'tr_dump.c',
+ 'tr_dump_state.c',
'tr_screen.c',
'tr_state.c',
+ 'tr_rbug.c',
'tr_texture.c',
])
diff --git a/src/gallium/drivers/trace/tr_context.c b/src/gallium/drivers/trace/tr_context.c
index 47280459a7..4ab718f233 100644
--- a/src/gallium/drivers/trace/tr_context.c
+++ b/src/gallium/drivers/trace/tr_context.c
@@ -31,11 +31,11 @@
#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 *
@@ -113,6 +113,65 @@ trace_context_set_edgeflags(struct pipe_context *_pipe,
}
+static INLINE void
+trace_context_draw_block(struct trace_context *tr_ctx, int flag)
+{
+ int k;
+
+ pipe_mutex_lock(tr_ctx->draw_mutex);
+
+ if (tr_ctx->draw_blocker & flag) {
+ tr_ctx->draw_blocked |= flag;
+ } else if ((tr_ctx->draw_rule.blocker & flag) &&
+ (tr_ctx->draw_blocker & 4)) {
+ boolean block = FALSE;
+ debug_printf("%s (%lu %lu) (%lu %lu) (%lu %u) (%lu %u)\n", __FUNCTION__,
+ tr_ctx->draw_rule.fs, tr_ctx->curr.fs,
+ tr_ctx->draw_rule.vs, tr_ctx->curr.vs,
+ tr_ctx->draw_rule.surf, 0,
+ tr_ctx->draw_rule.tex, 0);
+ if (tr_ctx->draw_rule.fs &&
+ tr_ctx->draw_rule.fs == tr_ctx->curr.fs)
+ block = TRUE;
+ if (tr_ctx->draw_rule.vs &&
+ tr_ctx->draw_rule.vs == tr_ctx->curr.vs)
+ block = TRUE;
+ if (tr_ctx->draw_rule.surf &&
+ tr_ctx->draw_rule.surf == tr_ctx->curr.zsbuf)
+ block = TRUE;
+ if (tr_ctx->draw_rule.surf)
+ for (k = 0; k < tr_ctx->curr.nr_cbufs; k++)
+ if (tr_ctx->draw_rule.surf == tr_ctx->curr.cbufs[k])
+ block = TRUE;
+ if (tr_ctx->draw_rule.tex)
+ for (k = 0; k < tr_ctx->curr.num_texs; k++)
+ if (tr_ctx->draw_rule.tex == tr_ctx->curr.tex[k])
+ block = TRUE;
+
+ if (block)
+ tr_ctx->draw_blocked |= (flag | 4);
+ }
+
+ if (tr_ctx->draw_blocked)
+ 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)
@@ -121,6 +180,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);
@@ -134,6 +198,8 @@ trace_context_draw_arrays(struct pipe_context *_pipe,
trace_dump_call_end();
+ trace_context_draw_block(tr_ctx, 2);
+
return result;
}
@@ -150,6 +216,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");
@@ -167,6 +238,8 @@ trace_context_draw_elements(struct pipe_context *_pipe,
trace_dump_call_end();
+ trace_context_draw_block(tr_ctx, 2);
+
return result;
}
@@ -187,6 +260,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");
@@ -209,6 +287,8 @@ trace_context_draw_range_elements(struct pipe_context *_pipe,
trace_dump_call_end();
+ trace_context_draw_block(tr_ctx, 2);
+
return result;
}
@@ -573,23 +653,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();
}
@@ -597,19 +686,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);
}
@@ -626,28 +719,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();
@@ -656,10 +758,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");
@@ -669,6 +773,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);
}
@@ -747,6 +853,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)
@@ -827,12 +946,17 @@ trace_context_set_sampler_textures(struct pipe_context *_pipe,
struct pipe_texture **textures)
{
struct trace_context *tr_ctx = trace_context(_pipe);
+ struct trace_texture *tr_tex;
struct pipe_context *pipe = tr_ctx->pipe;
struct pipe_texture *unwrapped_textures[PIPE_MAX_SAMPLERS];
unsigned i;
- for(i = 0; i < num_textures; ++i)
- unwrapped_textures[i] = trace_texture_unwrap(tr_ctx, textures[i]);
+ tr_ctx->curr.num_texs = num_textures;
+ for(i = 0; i < num_textures; ++i) {
+ tr_tex = trace_texture(textures[i]);
+ tr_ctx->curr.tex[i] = tr_tex;
+ unwrapped_textures[i] = tr_tex ? tr_tex->texture : NULL;
+ }
textures = unwrapped_textures;
trace_dump_call_begin("pipe_context", "set_sampler_textures");
@@ -1078,6 +1202,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)
@@ -1089,7 +1219,7 @@ trace_context_create(struct pipe_screen *_screen,
if(!pipe)
goto error1;
- if(!trace_dump_trace_enabled())
+ if(!trace_enabled())
goto error1;
tr_scr = trace_screen(_screen);
@@ -1099,6 +1229,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;
diff --git a/src/gallium/drivers/trace/tr_context.h b/src/gallium/drivers/trace/tr_context.h
index 2512a0a232..6febe4b411 100644
--- a/src/gallium/drivers/trace/tr_context.h
+++ b/src/gallium/drivers/trace/tr_context.h
@@ -33,6 +33,7 @@
#include "util/u_debug.h"
#include "pipe/p_context.h"
+#include "tr_screen.h"
#ifdef __cplusplus
extern "C" {
@@ -45,7 +46,41 @@ struct trace_context
struct pipe_context *pipe;
+ /* current state */
+ struct {
+ struct trace_shader *fs;
+ struct trace_shader *vs;
+
+ struct trace_texture *tex[PIPE_MAX_SAMPLERS];
+ unsigned num_texs;
+
+ unsigned nr_cbufs;
+ struct trace_texture *cbufs[PIPE_MAX_COLOR_BUFS];
+ struct trace_texture *zsbuf;
+ } curr;
+
+ struct {
+ struct trace_shader *fs;
+ struct trace_shader *vs;
+
+ struct trace_texture *tex;
+ struct trace_texture *surf;
+
+ int blocker;
+ } draw_rule;
+ unsigned draw_num_rules;
+ pipe_condvar draw_cond;
+ pipe_mutex draw_mutex;
+ int draw_blocker;
+ int draw_blocked;
+
+ /* for list on screen */
struct tr_list list;
+
+ /* list of state objects */
+ pipe_mutex list_mutex;
+ unsigned num_shaders;
+ struct tr_list shaders;
};
@@ -62,6 +97,9 @@ struct pipe_context *
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_drm.c b/src/gallium/drivers/trace/tr_drm.c
new file mode 100644
index 0000000000..98ac75e3fa
--- /dev/null
+++ b/src/gallium/drivers/trace/tr_drm.c
@@ -0,0 +1,211 @@
+/**************************************************************************
+ *
+ * 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 VMWARE 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 "state_tracker/drm_api.h"
+
+#include "util/u_memory.h"
+#include "trace/tr_drm.h"
+#include "trace/tr_screen.h"
+#include "trace/tr_context.h"
+#include "trace/tr_buffer.h"
+#include "trace/tr_texture.h"
+
+struct trace_drm_api
+{
+ struct drm_api base;
+
+ struct drm_api *api;
+};
+
+static INLINE struct trace_drm_api *
+trace_drm_api(struct drm_api *_api)
+{
+ return (struct trace_drm_api *)_api;
+}
+
+static struct pipe_screen *
+trace_drm_create_screen(struct drm_api *_api, int fd,
+ struct drm_create_screen_arg *arg)
+{
+ struct trace_drm_api *tr_api = trace_drm_api(_api);
+ struct drm_api *api = tr_api->api;
+ struct pipe_screen *screen;
+
+ /* TODO trace call */
+
+ if (arg && arg->mode != DRM_CREATE_NORMAL)
+ return NULL;
+
+ screen = api->create_screen(api, fd, arg);
+
+ return trace_screen_create(screen);
+};
+
+static struct pipe_context *
+trace_drm_create_context(struct drm_api *_api,
+ struct pipe_screen *_screen)
+{
+ struct trace_screen *tr_screen = trace_screen(_screen);
+ struct trace_drm_api *tr_api = trace_drm_api(_api);
+ struct pipe_screen *screen = tr_screen->screen;
+ struct drm_api *api = tr_api->api;
+ struct pipe_context *pipe;
+
+ /* TODO trace call */
+
+ pipe = api->create_context(api, screen);
+
+ pipe = trace_context_create(_screen, pipe);
+
+ return pipe;
+};
+
+static boolean
+trace_drm_buffer_from_texture(struct drm_api *_api,
+ struct pipe_texture *_texture,
+ struct pipe_buffer **_buffer,
+ unsigned *stride)
+{
+ struct trace_texture *tr_texture = trace_texture(_texture);
+ struct trace_drm_api *tr_api = trace_drm_api(_api);
+ struct pipe_texture *texture = tr_texture->texture;
+ struct drm_api *api = tr_api->api;
+ struct pipe_buffer *buffer = NULL;
+ boolean result;
+
+ /* TODO trace call */
+
+ result = api->buffer_from_texture(api, texture, &buffer, stride);
+
+ if (result && _buffer)
+ buffer = trace_buffer_create(trace_screen(texture->screen), buffer);
+
+ if (_buffer)
+ *_buffer = buffer;
+ else
+ pipe_buffer_reference(&buffer, NULL);
+
+ return result;
+}
+
+static struct pipe_buffer *
+trace_drm_buffer_from_handle(struct drm_api *_api,
+ struct pipe_screen *_screen,
+ const char *name,
+ unsigned handle)
+{
+ struct trace_screen *tr_screen = trace_screen(_screen);
+ struct trace_drm_api *tr_api = trace_drm_api(_api);
+ struct pipe_screen *screen = tr_screen->screen;
+ struct drm_api *api = tr_api->api;
+ struct pipe_buffer *result;
+
+ /* TODO trace call */
+
+ result = api->buffer_from_handle(api, screen, name, handle);
+
+ result = trace_buffer_create(trace_screen(_screen), result);
+
+ return result;
+}
+
+static boolean
+trace_drm_handle_from_buffer(struct drm_api *_api,
+ struct pipe_screen *_screen,
+ struct pipe_buffer *_buffer,
+ unsigned *handle)
+{
+ struct trace_screen *tr_screen = trace_screen(_screen);
+ struct trace_buffer *tr_buffer = trace_buffer(_buffer);
+ struct trace_drm_api *tr_api = trace_drm_api(_api);
+ struct pipe_screen *screen = tr_screen->screen;
+ struct pipe_buffer *buffer = tr_buffer->buffer;
+ struct drm_api *api = tr_api->api;
+
+ /* TODO trace call */
+
+ return api->handle_from_buffer(api, screen, buffer, handle);
+}
+
+static boolean
+trace_drm_global_handle_from_buffer(struct drm_api *_api,
+ struct pipe_screen *_screen,
+ struct pipe_buffer *_buffer,
+ unsigned *handle)
+{
+ struct trace_screen *tr_screen = trace_screen(_screen);
+ struct trace_buffer *tr_buffer = trace_buffer(_buffer);
+ struct trace_drm_api *tr_api = trace_drm_api(_api);
+ struct pipe_screen *screen = tr_screen->screen;
+ struct pipe_buffer *buffer = tr_buffer->buffer;
+ struct drm_api *api = tr_api->api;
+
+ /* TODO trace call */
+
+ return api->global_handle_from_buffer(api, screen, buffer, handle);
+}
+
+static void
+trace_drm_destroy(struct drm_api *_api)
+{
+ struct trace_drm_api *tr_api = trace_drm_api(_api);
+ struct drm_api *api = tr_api->api;
+ api->destroy(api);
+
+ free(tr_api);
+}
+
+struct drm_api *
+trace_drm_create(struct drm_api *api)
+{
+ struct trace_drm_api *tr_api;
+
+ if (!api)
+ goto error;
+
+ if (!trace_enabled())
+ goto error;
+
+ tr_api = CALLOC_STRUCT(trace_drm_api);
+
+ if (!tr_api)
+ goto error;
+
+ tr_api->base.create_screen = trace_drm_create_screen;
+ tr_api->base.create_context = trace_drm_create_context;
+ tr_api->base.buffer_from_texture = trace_drm_buffer_from_texture;
+ tr_api->base.buffer_from_handle = trace_drm_buffer_from_handle;
+ tr_api->base.handle_from_buffer = trace_drm_handle_from_buffer;
+ tr_api->base.global_handle_from_buffer = trace_drm_global_handle_from_buffer;
+ tr_api->base.destroy = trace_drm_destroy;
+ tr_api->api = api;
+
+ return &tr_api->base;
+
+error:
+ return api;
+}
diff --git a/src/gallium/drivers/trace/tr_drm.h b/src/gallium/drivers/trace/tr_drm.h
new file mode 100644
index 0000000000..845c66a32a
--- /dev/null
+++ b/src/gallium/drivers/trace/tr_drm.h
@@ -0,0 +1,35 @@
+/**************************************************************************
+ *
+ * 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 VMWARE 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.
+ *
+ **************************************************************************/
+
+#ifndef TR_DRM_H
+#define TR_DRM_H
+
+struct drm_api;
+
+struct drm_api* trace_drm_create(struct drm_api *api);
+
+#endif /* ID_DRM_H */
diff --git a/src/gallium/drivers/trace/tr_dump_state.c b/src/gallium/drivers/trace/tr_dump_state.c
new file mode 100644
index 0000000000..bcf6751af4
--- /dev/null
+++ b/src/gallium/drivers/trace/tr_dump_state.c
@@ -0,0 +1,549 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * 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 "pipe/p_compiler.h"
+#include "util/u_memory.h"
+#include "tgsi/tgsi_dump.h"
+
+#include "tr_dump.h"
+#include "tr_dump_state.h"
+
+
+void trace_dump_format(enum pipe_format format)
+{
+ if (!trace_dumping_enabled_locked())
+ return;
+
+ trace_dump_enum(pf_name(format) );
+}
+
+
+void trace_dump_block(const struct pipe_format_block *block)
+{
+ if (!trace_dumping_enabled_locked())
+ return;
+
+ trace_dump_struct_begin("pipe_format_block");
+ trace_dump_member(uint, block, size);
+ trace_dump_member(uint, block, width);
+ trace_dump_member(uint, block, height);
+ trace_dump_struct_end();
+}
+
+
+static void trace_dump_reference(const struct pipe_reference *reference)
+{
+ if (!trace_dumping_enabled_locked())
+ return;
+
+ trace_dump_struct_begin("pipe_reference");
+ trace_dump_member(int, &reference->count, count);
+ trace_dump_struct_end();
+}
+
+
+void trace_dump_template(const struct pipe_texture *templat)
+{
+ if (!trace_dumping_enabled_locked())
+ return;
+
+ if(!templat) {
+ trace_dump_null();
+ return;
+ }
+
+ trace_dump_struct_begin("pipe_texture");
+
+ trace_dump_member(int, templat, target);
+ trace_dump_member(format, templat, format);
+
+ trace_dump_member_begin("width");
+ trace_dump_array(uint, templat->width, 1);
+ trace_dump_member_end();
+
+ trace_dump_member_begin("height");
+ trace_dump_array(uint, templat->height, 1);
+ trace_dump_member_end();
+
+ trace_dump_member_begin("depth");
+ trace_dump_array(uint, templat->depth, 1);
+ trace_dump_member_end();
+
+ trace_dump_member_begin("block");
+ trace_dump_block(&templat->block);
+ trace_dump_member_end();
+
+ trace_dump_member(uint, templat, last_level);
+ trace_dump_member(uint, templat, tex_usage);
+
+ trace_dump_struct_end();
+}
+
+
+void trace_dump_rasterizer_state(const struct pipe_rasterizer_state *state)
+{
+ if (!trace_dumping_enabled_locked())
+ return;
+
+ if(!state) {
+ trace_dump_null();
+ return;
+ }
+
+ trace_dump_struct_begin("pipe_rasterizer_state");
+
+ trace_dump_member(bool, state, flatshade);
+ trace_dump_member(bool, state, light_twoside);
+ trace_dump_member(uint, state, front_winding);
+ trace_dump_member(uint, state, cull_mode);
+ trace_dump_member(uint, state, fill_cw);
+ trace_dump_member(uint, state, fill_ccw);
+ trace_dump_member(bool, state, offset_cw);
+ trace_dump_member(bool, state, offset_ccw);
+ trace_dump_member(bool, state, scissor);
+ trace_dump_member(bool, state, poly_smooth);
+ trace_dump_member(bool, state, poly_stipple_enable);
+ trace_dump_member(bool, state, point_smooth);
+ trace_dump_member(bool, state, point_sprite);
+ trace_dump_member(bool, state, point_size_per_vertex);
+ trace_dump_member(bool, state, multisample);
+ trace_dump_member(bool, state, line_smooth);
+ trace_dump_member(bool, state, line_stipple_enable);
+ trace_dump_member(uint, state, line_stipple_factor);
+ trace_dump_member(uint, state, line_stipple_pattern);
+ trace_dump_member(bool, state, line_last_pixel);
+ trace_dump_member(bool, state, bypass_vs_clip_and_viewport);
+ trace_dump_member(bool, state, flatshade_first);
+ trace_dump_member(bool, state, gl_rasterization_rules);
+
+ trace_dump_member(float, state, line_width);
+ trace_dump_member(float, state, point_size);
+ trace_dump_member(float, state, point_size_min);
+ trace_dump_member(float, state, point_size_max);
+ trace_dump_member(float, state, offset_units);
+ trace_dump_member(float, state, offset_scale);
+
+ trace_dump_member_array(uint, state, sprite_coord_mode);
+
+ trace_dump_struct_end();
+}
+
+
+void trace_dump_poly_stipple(const struct pipe_poly_stipple *state)
+{
+ if (!trace_dumping_enabled_locked())
+ return;
+
+ if(!state) {
+ trace_dump_null();
+ return;
+ }
+
+ trace_dump_struct_begin("pipe_poly_stipple");
+
+ trace_dump_member_begin("stipple");
+ trace_dump_array(uint,
+ state->stipple,
+ Elements(state->stipple));
+ trace_dump_member_end();
+
+ trace_dump_struct_end();
+}
+
+
+void trace_dump_viewport_state(const struct pipe_viewport_state *state)
+{
+ if (!trace_dumping_enabled_locked())
+ return;
+
+ if(!state) {
+ trace_dump_null();
+ return;
+ }
+
+ trace_dump_struct_begin("pipe_viewport_state");
+
+ trace_dump_member_array(float, state, scale);
+ trace_dump_member_array(float, state, translate);
+
+ trace_dump_struct_end();
+}
+
+
+void trace_dump_scissor_state(const struct pipe_scissor_state *state)
+{
+ if (!trace_dumping_enabled_locked())
+ return;
+
+ if(!state) {
+ trace_dump_null();
+ return;
+ }
+
+ trace_dump_struct_begin("pipe_scissor_state");
+
+ trace_dump_member(uint, state, minx);
+ trace_dump_member(uint, state, miny);
+ trace_dump_member(uint, state, maxx);
+ trace_dump_member(uint, state, maxy);
+
+ trace_dump_struct_end();
+}
+
+
+void trace_dump_clip_state(const struct pipe_clip_state *state)
+{
+ unsigned i;
+
+ if (!trace_dumping_enabled_locked())
+ return;
+
+ if(!state) {
+ trace_dump_null();
+ return;
+ }
+
+ trace_dump_struct_begin("pipe_clip_state");
+
+ trace_dump_member_begin("ucp");
+ trace_dump_array_begin();
+ for(i = 0; i < PIPE_MAX_CLIP_PLANES; ++i) {
+ trace_dump_elem_begin();
+ trace_dump_array(float, state->ucp[i], 4);
+ trace_dump_elem_end();
+ }
+ trace_dump_array_end();
+ trace_dump_member_end();
+
+ trace_dump_member(uint, state, nr);
+
+ trace_dump_struct_end();
+}
+
+
+void trace_dump_constant_buffer(const struct pipe_constant_buffer *state)
+{
+ if (!trace_dumping_enabled_locked())
+ return;
+
+ if(!state) {
+ trace_dump_null();
+ return;
+ }
+
+ trace_dump_struct_begin("pipe_constant_buffer");
+
+ trace_dump_member(buffer_ptr, state, buffer);
+
+ trace_dump_struct_end();
+}
+
+
+void trace_dump_shader_state(const struct pipe_shader_state *state)
+{
+ static char str[8192];
+
+ if (!trace_dumping_enabled_locked())
+ return;
+
+ if(!state) {
+ trace_dump_null();
+ return;
+ }
+
+ tgsi_dump_str(state->tokens, 0, str, sizeof(str));
+
+ trace_dump_struct_begin("pipe_shader_state");
+
+ trace_dump_member_begin("tokens");
+ trace_dump_string(str);
+ trace_dump_member_end();
+
+ trace_dump_struct_end();
+}
+
+
+void trace_dump_depth_stencil_alpha_state(const struct pipe_depth_stencil_alpha_state *state)
+{
+ unsigned i;
+
+ if (!trace_dumping_enabled_locked())
+ return;
+
+ if(!state) {
+ trace_dump_null();
+ return;
+ }
+
+ trace_dump_struct_begin("pipe_depth_stencil_alpha_state");
+
+ trace_dump_member_begin("depth");
+ trace_dump_struct_begin("pipe_depth_state");
+ trace_dump_member(bool, &state->depth, enabled);
+ trace_dump_member(bool, &state->depth, writemask);
+ trace_dump_member(uint, &state->depth, func);
+ trace_dump_struct_end();
+ trace_dump_member_end();
+
+ trace_dump_member_begin("stencil");
+ trace_dump_array_begin();
+ for(i = 0; i < Elements(state->stencil); ++i) {
+ trace_dump_elem_begin();
+ trace_dump_struct_begin("pipe_stencil_state");
+ trace_dump_member(bool, &state->stencil[i], enabled);
+ trace_dump_member(uint, &state->stencil[i], func);
+ trace_dump_member(uint, &state->stencil[i], fail_op);
+ trace_dump_member(uint, &state->stencil[i], zpass_op);
+ trace_dump_member(uint, &state->stencil[i], zfail_op);
+ trace_dump_member(uint, &state->stencil[i], ref_value);
+ trace_dump_member(uint, &state->stencil[i], valuemask);
+ trace_dump_member(uint, &state->stencil[i], writemask);
+ trace_dump_struct_end();
+ trace_dump_elem_end();
+ }
+ trace_dump_array_end();
+ trace_dump_member_end();
+
+ trace_dump_member_begin("alpha");
+ trace_dump_struct_begin("pipe_alpha_state");
+ trace_dump_member(bool, &state->alpha, enabled);
+ trace_dump_member(uint, &state->alpha, func);
+ trace_dump_member(float, &state->alpha, ref_value);
+ trace_dump_struct_end();
+ trace_dump_member_end();
+
+ trace_dump_struct_end();
+}
+
+
+void trace_dump_blend_state(const struct pipe_blend_state *state)
+{
+ if (!trace_dumping_enabled_locked())
+ return;
+
+ if(!state) {
+ trace_dump_null();
+ return;
+ }
+
+ trace_dump_struct_begin("pipe_blend_state");
+
+ trace_dump_member(bool, state, blend_enable);
+
+ trace_dump_member(uint, state, rgb_func);
+ trace_dump_member(uint, state, rgb_src_factor);
+ trace_dump_member(uint, state, rgb_dst_factor);
+
+ trace_dump_member(uint, state, alpha_func);
+ trace_dump_member(uint, state, alpha_src_factor);
+ trace_dump_member(uint, state, alpha_dst_factor);
+
+ trace_dump_member(bool, state, logicop_enable);
+ trace_dump_member(uint, state, logicop_func);
+
+ trace_dump_member(uint, state, colormask);
+ trace_dump_member(bool, state, dither);
+
+ trace_dump_struct_end();
+}
+
+
+void trace_dump_blend_color(const struct pipe_blend_color *state)
+{
+ if (!trace_dumping_enabled_locked())
+ return;
+
+ if(!state) {
+ trace_dump_null();
+ return;
+ }
+
+ trace_dump_struct_begin("pipe_blend_color");
+
+ trace_dump_member_array(float, state, color);
+
+ trace_dump_struct_end();
+}
+
+
+void trace_dump_framebuffer_state(const struct pipe_framebuffer_state *state)
+{
+ if (!trace_dumping_enabled_locked())
+ return;
+
+ trace_dump_struct_begin("pipe_framebuffer_state");
+
+ trace_dump_member(uint, state, width);
+ trace_dump_member(uint, state, height);
+ trace_dump_member(uint, state, nr_cbufs);
+ trace_dump_member_array(ptr, state, cbufs);
+ trace_dump_member(ptr, state, zsbuf);
+
+ trace_dump_struct_end();
+}
+
+
+void trace_dump_sampler_state(const struct pipe_sampler_state *state)
+{
+ if (!trace_dumping_enabled_locked())
+ return;
+
+ if(!state) {
+ trace_dump_null();
+ return;
+ }
+
+ trace_dump_struct_begin("pipe_sampler_state");
+
+ trace_dump_member(uint, state, wrap_s);
+ trace_dump_member(uint, state, wrap_t);
+ trace_dump_member(uint, state, wrap_r);
+ trace_dump_member(uint, state, min_img_filter);
+ trace_dump_member(uint, state, min_mip_filter);
+ trace_dump_member(uint, state, mag_img_filter);
+ trace_dump_member(bool, state, compare_mode);
+ trace_dump_member(uint, state, compare_func);
+ trace_dump_member(bool, state, normalized_coords);
+ trace_dump_member(uint, state, prefilter);
+ trace_dump_member(float, state, lod_bias);
+ trace_dump_member(float, state, min_lod);
+ trace_dump_member(float, state, max_lod);
+ trace_dump_member_array(float, state, border_color);
+ trace_dump_member(float, state, max_anisotropy);
+
+ trace_dump_struct_end();
+}
+
+
+void trace_dump_surface(const struct pipe_surface *state)
+{
+ if (!trace_dumping_enabled_locked())
+ return;
+
+ if(!state) {
+ trace_dump_null();
+ return;
+ }
+
+ trace_dump_struct_begin("pipe_surface");
+
+ trace_dump_reference(&state->reference);
+
+ trace_dump_member(format, state, format);
+ trace_dump_member(uint, state, width);
+ trace_dump_member(uint, state, height);
+
+ trace_dump_member(uint, state, layout);
+ trace_dump_member(uint, state, offset);
+ trace_dump_member(uint, state, usage);
+
+ trace_dump_member(ptr, state, texture);
+ trace_dump_member(uint, state, face);
+ trace_dump_member(uint, state, level);
+ trace_dump_member(uint, state, zslice);
+
+ trace_dump_struct_end();
+}
+
+
+void trace_dump_transfer(const struct pipe_transfer *state)
+{
+ if (!trace_dumping_enabled_locked())
+ return;
+
+ if(!state) {
+ trace_dump_null();
+ return;
+ }
+
+ trace_dump_struct_begin("pipe_transfer");
+
+ trace_dump_member(format, state, format);
+ trace_dump_member(uint, state, width);
+ trace_dump_member(uint, state, height);
+
+ trace_dump_member_begin("block");
+ trace_dump_block(&state->block);
+ trace_dump_member_end();
+
+ trace_dump_member(uint, state, nblocksx);
+ trace_dump_member(uint, state, nblocksy);
+ trace_dump_member(uint, state, stride);
+ trace_dump_member(uint, state, usage);
+
+ trace_dump_member(ptr, state, texture);
+ trace_dump_member(uint, state, face);
+ trace_dump_member(uint, state, level);
+ trace_dump_member(uint, state, zslice);
+
+ trace_dump_struct_end();
+}
+
+
+void trace_dump_vertex_buffer(const struct pipe_vertex_buffer *state)
+{
+ if (!trace_dumping_enabled_locked())
+ return;
+
+ if(!state) {
+ trace_dump_null();
+ return;
+ }
+
+ trace_dump_struct_begin("pipe_vertex_buffer");
+
+ trace_dump_member(uint, state, stride);
+ trace_dump_member(uint, state, max_index);
+ trace_dump_member(uint, state, buffer_offset);
+ trace_dump_member(buffer_ptr, state, buffer);
+
+ trace_dump_struct_end();
+}
+
+
+void trace_dump_vertex_element(const struct pipe_vertex_element *state)
+{
+ if (!trace_dumping_enabled_locked())
+ return;
+
+ if(!state) {
+ trace_dump_null();
+ return;
+ }
+
+ trace_dump_struct_begin("pipe_vertex_element");
+
+ trace_dump_member(uint, state, src_offset);
+
+ trace_dump_member(uint, state, vertex_buffer_index);
+ trace_dump_member(uint, state, nr_components);
+
+ trace_dump_member(format, state, src_format);
+
+ trace_dump_struct_end();
+}
diff --git a/src/gallium/drivers/trace/tr_dump_state.h b/src/gallium/drivers/trace/tr_dump_state.h
new file mode 100644
index 0000000000..05b821adb6
--- /dev/null
+++ b/src/gallium/drivers/trace/tr_dump_state.h
@@ -0,0 +1,78 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * 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.
+ *
+ **************************************************************************/
+
+#ifndef TR_DUMP_STATE_H_
+#define TR_DUMP_STATE_H_
+
+#include "pipe/p_format.h"
+#include "pipe/p_state.h"
+#include "pipe/p_shader_tokens.h"
+
+
+void trace_dump_format(enum pipe_format format);
+
+void trace_dump_block(const struct pipe_format_block *block);
+
+void trace_dump_template(const struct pipe_texture *templat);
+
+
+void trace_dump_rasterizer_state(const struct pipe_rasterizer_state *state);
+
+void trace_dump_poly_stipple(const struct pipe_poly_stipple *state);
+
+void trace_dump_viewport_state(const struct pipe_viewport_state *state);
+
+void trace_dump_scissor_state(const struct pipe_scissor_state *state);
+
+void trace_dump_clip_state(const struct pipe_clip_state *state);
+
+void trace_dump_constant_buffer(const struct pipe_constant_buffer *state);
+
+void trace_dump_token(const struct tgsi_token *token);
+
+void trace_dump_shader_state(const struct pipe_shader_state *state);
+
+void trace_dump_depth_stencil_alpha_state(const struct pipe_depth_stencil_alpha_state *state);
+
+void trace_dump_blend_state(const struct pipe_blend_state *state);
+
+void trace_dump_blend_color(const struct pipe_blend_color *state);
+
+void trace_dump_framebuffer_state(const struct pipe_framebuffer_state *state);
+
+void trace_dump_sampler_state(const struct pipe_sampler_state *state);
+
+void trace_dump_surface(const struct pipe_surface *state);
+
+void trace_dump_transfer(const struct pipe_transfer *state);
+
+void trace_dump_vertex_buffer(const struct pipe_vertex_buffer *state);
+
+void trace_dump_vertex_element(const struct pipe_vertex_element *state);
+
+
+#endif /* TR_STATE_H */
diff --git a/src/gallium/drivers/trace/tr_rbug.c b/src/gallium/drivers/trace/tr_rbug.c
new file mode 100644
index 0000000000..e85ac15edc
--- /dev/null
+++ b/src/gallium/drivers/trace/tr_rbug.c
@@ -0,0 +1,864 @@
+/**************************************************************************
+ *
+ * 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_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];
+ rbug_texture_t texs[PIPE_MAX_SAMPLERS];
+ 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]);
+
+ for (i = 0; i < tr_ctx->curr.num_texs; i++)
+ texs[i] = VOID2U64(tr_ctx->curr.tex[i]);
+
+ rbug_send_context_info_reply(tr_rbug->con, serial,
+ VOID2U64(tr_ctx->curr.vs), VOID2U64(tr_ctx->curr.fs),
+ texs, tr_ctx->curr.num_texs,
+ 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);
+ if (tr_ctx->draw_blocked & RBUG_BLOCK_RULE) {
+ if (step->step & RBUG_BLOCK_RULE)
+ tr_ctx->draw_blocked &= ~RBUG_BLOCK_MASK;
+ } else {
+ tr_ctx->draw_blocked &= ~step->step;
+ }
+ pipe_mutex_unlock(tr_ctx->draw_mutex);
+
+#ifdef PIPE_THREAD_HAVE_CONDVAR
+ pipe_condvar_broadcast(tr_ctx->draw_cond);
+#endif
+
+ 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);
+ if (tr_ctx->draw_blocked & RBUG_BLOCK_RULE) {
+ if (unblock->unblock & RBUG_BLOCK_RULE)
+ tr_ctx->draw_blocked &= ~RBUG_BLOCK_MASK;
+ } else {
+ tr_ctx->draw_blocked &= ~unblock->unblock;
+ }
+ tr_ctx->draw_blocker &= ~unblock->unblock;
+ pipe_mutex_unlock(tr_ctx->draw_mutex);
+
+#ifdef PIPE_THREAD_HAVE_CONDVAR
+ pipe_condvar_broadcast(tr_ctx->draw_cond);
+#endif
+
+ pipe_mutex_unlock(tr_scr->list_mutex);
+
+ return 0;
+}
+
+static int
+trace_rbug_context_draw_rule(struct trace_rbug *tr_rbug, struct rbug_header *header, uint32_t serial)
+{
+ struct rbug_proto_context_draw_rule *rule = (struct rbug_proto_context_draw_rule *)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, rule->context);
+
+ if (!tr_ctx) {
+ pipe_mutex_unlock(tr_scr->list_mutex);
+ return -ESRCH;
+ }
+
+ pipe_mutex_lock(tr_ctx->draw_mutex);
+ tr_ctx->draw_rule.vs = U642VOID(rule->vertex);
+ tr_ctx->draw_rule.fs = U642VOID(rule->fragment);
+ tr_ctx->draw_rule.tex = U642VOID(rule->texture);
+ tr_ctx->draw_rule.surf = U642VOID(rule->surface);
+ tr_ctx->draw_rule.blocker = rule->block;
+ tr_ctx->draw_blocker |= RBUG_BLOCK_RULE;
+ pipe_mutex_unlock(tr_ctx->draw_mutex);
+
+#ifdef PIPE_THREAD_HAVE_CONDVAR
+ pipe_condvar_broadcast(tr_ctx->draw_cond);
+#endif
+
+ 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;
+
+ 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_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_DRAW_RULE:
+ ret = trace_rbug_context_draw_rule(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;
+ 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 = CALLOC_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;
+}
+
+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);
+}
diff --git a/src/gallium/drivers/trace/tr_screen.c b/src/gallium/drivers/trace/tr_screen.c
index 12a8535342..5b1e26a52d 100644
--- a/src/gallium/drivers/trace/tr_screen.c
+++ b/src/gallium/drivers/trace/tr_screen.c
@@ -30,13 +30,16 @@
#include "tr_buffer.h"
#include "tr_dump.h"
-#include "tr_state.h"
+#include "tr_dump_state.h"
#include "tr_texture.h"
#include "tr_screen.h"
#include "pipe/p_inlines.h"
+static boolean trace = FALSE;
+static boolean rbug = FALSE;
+
static const char *
trace_screen_get_name(struct pipe_screen *_screen)
{
@@ -212,10 +215,12 @@ static struct pipe_texture *
trace_screen_texture_blanket(struct pipe_screen *_screen,
const struct pipe_texture *templat,
const unsigned *ppitch,
- struct pipe_buffer *buffer)
+ struct pipe_buffer *_buffer)
{
struct trace_screen *tr_scr = trace_screen(_screen);
+ struct trace_buffer *tr_buf = trace_buffer(_buffer);
struct pipe_screen *screen = tr_scr->screen;
+ struct pipe_buffer *buffer = tr_buf->buffer;
unsigned pitch = *ppitch;
struct pipe_texture *result;
@@ -818,18 +823,41 @@ trace_screen_destroy(struct pipe_screen *_screen)
struct pipe_screen *screen = tr_scr->screen;
trace_dump_call_begin("pipe_screen", "destroy");
-
trace_dump_arg(ptr, screen);
-
- screen->destroy(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)
+{
+ static boolean firstrun = TRUE;
+
+ if (!firstrun)
+ return trace;
+ firstrun = FALSE;
+
+ trace_dump_init();
+
+ if(trace_dump_trace_begin()) {
+ trace_dumping_start();
+ trace = TRUE;
+ }
+
+ if (debug_get_bool_option("GALLIUM_RBUG", FALSE)) {
+ trace = TRUE;
+ rbug = TRUE;
+ }
+
+ return trace;
+}
struct pipe_screen *
trace_screen_create(struct pipe_screen *screen)
@@ -840,13 +868,9 @@ trace_screen_create(struct pipe_screen *screen)
if(!screen)
goto error1;
- trace_dump_init();
-
- if(!trace_dump_trace_begin())
+ if (!trace_enabled())
goto error1;
- trace_dumping_start();
-
trace_dump_call_begin("", "pipe_screen_create");
tr_scr = CALLOC_STRUCT(trace_screen);
@@ -904,6 +928,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 59f254166d..dba8cd7c65 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;
@@ -71,14 +74,34 @@ 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);
@@ -99,6 +122,7 @@ trace_screen_user_buffer_update(struct pipe_screen *screen,
pipe_mutex_unlock(tr_scr->list_mutex); \
} while (0)
+
#ifdef __cplusplus
}
#endif
diff --git a/src/gallium/drivers/trace/tr_state.c b/src/gallium/drivers/trace/tr_state.c
index a9570c1aeb..d8c11640bf 100644
--- a/src/gallium/drivers/trace/tr_state.c
+++ b/src/gallium/drivers/trace/tr_state.c
@@ -1,491 +1,66 @@
-/**************************************************************************
- *
- * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+/*
+ * 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.
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on 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 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.
+ * 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
+ * VMWARE AND/OR THEIR 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 "pipe/p_compiler.h"
-#include "util/u_memory.h"
-#include "tgsi/tgsi_dump.h"
-
-#include "tr_dump.h"
#include "tr_state.h"
+#include "util/u_memory.h"
+#include "util/u_simple_list.h"
-void trace_dump_format(enum pipe_format format)
-{
- trace_dump_enum(pf_name(format) );
-}
-
-
-void trace_dump_block(const struct pipe_format_block *block)
-{
- trace_dump_struct_begin("pipe_format_block");
- trace_dump_member(uint, block, size);
- trace_dump_member(uint, block, width);
- trace_dump_member(uint, block, height);
- trace_dump_struct_end();
-}
-
-
-static void trace_dump_reference(const struct pipe_reference *reference)
-{
- trace_dump_struct_begin("pipe_reference");
- trace_dump_member(int, &reference->count, count);
- trace_dump_struct_end();
-}
-
-
-void trace_dump_template(const struct pipe_texture *templat)
-{
- if(!templat) {
- trace_dump_null();
- return;
- }
-
- trace_dump_struct_begin("pipe_texture");
-
- trace_dump_member(int, templat, target);
- trace_dump_member(format, templat, format);
-
- trace_dump_member_begin("width");
- trace_dump_array(uint, templat->width, 1);
- trace_dump_member_end();
-
- trace_dump_member_begin("height");
- trace_dump_array(uint, templat->height, 1);
- trace_dump_member_end();
-
- trace_dump_member_begin("depth");
- trace_dump_array(uint, templat->depth, 1);
- trace_dump_member_end();
-
- trace_dump_member_begin("block");
- trace_dump_block(&templat->block);
- trace_dump_member_end();
-
- trace_dump_member(uint, templat, last_level);
- trace_dump_member(uint, templat, tex_usage);
-
- trace_dump_struct_end();
-}
-
-
-void trace_dump_rasterizer_state(const struct pipe_rasterizer_state *state)
-{
- if(!state) {
- trace_dump_null();
- return;
- }
-
- trace_dump_struct_begin("pipe_rasterizer_state");
-
- trace_dump_member(bool, state, flatshade);
- trace_dump_member(bool, state, light_twoside);
- trace_dump_member(uint, state, front_winding);
- trace_dump_member(uint, state, cull_mode);
- trace_dump_member(uint, state, fill_cw);
- trace_dump_member(uint, state, fill_ccw);
- trace_dump_member(bool, state, offset_cw);
- trace_dump_member(bool, state, offset_ccw);
- trace_dump_member(bool, state, scissor);
- trace_dump_member(bool, state, poly_smooth);
- trace_dump_member(bool, state, poly_stipple_enable);
- trace_dump_member(bool, state, point_smooth);
- trace_dump_member(bool, state, point_sprite);
- trace_dump_member(bool, state, point_size_per_vertex);
- trace_dump_member(bool, state, multisample);
- trace_dump_member(bool, state, line_smooth);
- trace_dump_member(bool, state, line_stipple_enable);
- trace_dump_member(uint, state, line_stipple_factor);
- trace_dump_member(uint, state, line_stipple_pattern);
- trace_dump_member(bool, state, line_last_pixel);
- trace_dump_member(bool, state, bypass_vs_clip_and_viewport);
- trace_dump_member(bool, state, flatshade_first);
- trace_dump_member(bool, state, gl_rasterization_rules);
-
- trace_dump_member(float, state, line_width);
- trace_dump_member(float, state, point_size);
- trace_dump_member(float, state, point_size_min);
- trace_dump_member(float, state, point_size_max);
- trace_dump_member(float, state, offset_units);
- trace_dump_member(float, state, offset_scale);
-
- trace_dump_member_array(uint, state, sprite_coord_mode);
-
- trace_dump_struct_end();
-}
-
-
-void trace_dump_poly_stipple(const struct pipe_poly_stipple *state)
-{
- if(!state) {
- trace_dump_null();
- return;
- }
-
- trace_dump_struct_begin("pipe_poly_stipple");
-
- trace_dump_member_begin("stipple");
- trace_dump_array(uint,
- state->stipple,
- Elements(state->stipple));
- trace_dump_member_end();
-
- trace_dump_struct_end();
-}
-
-
-void trace_dump_viewport_state(const struct pipe_viewport_state *state)
-{
- if(!state) {
- trace_dump_null();
- return;
- }
-
- trace_dump_struct_begin("pipe_viewport_state");
-
- trace_dump_member_array(float, state, scale);
- trace_dump_member_array(float, state, translate);
-
- trace_dump_struct_end();
-}
-
-
-void trace_dump_scissor_state(const struct pipe_scissor_state *state)
-{
- if(!state) {
- trace_dump_null();
- return;
- }
-
- trace_dump_struct_begin("pipe_scissor_state");
-
- trace_dump_member(uint, state, minx);
- trace_dump_member(uint, state, miny);
- trace_dump_member(uint, state, maxx);
- trace_dump_member(uint, state, maxy);
-
- trace_dump_struct_end();
-}
-
-
-void trace_dump_clip_state(const struct pipe_clip_state *state)
-{
- unsigned i;
-
- if(!state) {
- trace_dump_null();
- return;
- }
-
- trace_dump_struct_begin("pipe_clip_state");
-
- trace_dump_member_begin("ucp");
- trace_dump_array_begin();
- for(i = 0; i < PIPE_MAX_CLIP_PLANES; ++i) {
- trace_dump_elem_begin();
- trace_dump_array(float, state->ucp[i], 4);
- trace_dump_elem_end();
- }
- trace_dump_array_end();
- trace_dump_member_end();
-
- trace_dump_member(uint, state, nr);
-
- trace_dump_struct_end();
-}
-
-
-void trace_dump_constant_buffer(const struct pipe_constant_buffer *state)
-{
- if(!state) {
- trace_dump_null();
- return;
- }
-
- trace_dump_struct_begin("pipe_constant_buffer");
-
- trace_dump_member(buffer_ptr, state, buffer);
-
- trace_dump_struct_end();
-}
-
-
-void trace_dump_shader_state(const struct pipe_shader_state *state)
-{
- static char str[8192];
-
- if(!state) {
- trace_dump_null();
- return;
- }
-
- tgsi_dump_str(state->tokens, 0, str, sizeof(str));
-
- trace_dump_struct_begin("pipe_shader_state");
-
- trace_dump_member_begin("tokens");
- trace_dump_string(str);
- trace_dump_member_end();
-
- trace_dump_struct_end();
-}
-
-
-void trace_dump_depth_stencil_alpha_state(const struct pipe_depth_stencil_alpha_state *state)
-{
- unsigned i;
-
- if(!state) {
- trace_dump_null();
- return;
- }
-
- trace_dump_struct_begin("pipe_depth_stencil_alpha_state");
-
- trace_dump_member_begin("depth");
- trace_dump_struct_begin("pipe_depth_state");
- trace_dump_member(bool, &state->depth, enabled);
- trace_dump_member(bool, &state->depth, writemask);
- trace_dump_member(uint, &state->depth, func);
- trace_dump_member(bool, &state->depth, occlusion_count);
- trace_dump_struct_end();
- trace_dump_member_end();
-
- trace_dump_member_begin("stencil");
- trace_dump_array_begin();
- for(i = 0; i < Elements(state->stencil); ++i) {
- trace_dump_elem_begin();
- trace_dump_struct_begin("pipe_stencil_state");
- trace_dump_member(bool, &state->stencil[i], enabled);
- trace_dump_member(uint, &state->stencil[i], func);
- trace_dump_member(uint, &state->stencil[i], fail_op);
- trace_dump_member(uint, &state->stencil[i], zpass_op);
- trace_dump_member(uint, &state->stencil[i], zfail_op);
- trace_dump_member(uint, &state->stencil[i], ref_value);
- trace_dump_member(uint, &state->stencil[i], valuemask);
- trace_dump_member(uint, &state->stencil[i], writemask);
- trace_dump_struct_end();
- trace_dump_elem_end();
- }
- trace_dump_array_end();
- trace_dump_member_end();
-
- trace_dump_member_begin("alpha");
- trace_dump_struct_begin("pipe_alpha_state");
- trace_dump_member(bool, &state->alpha, enabled);
- trace_dump_member(uint, &state->alpha, func);
- trace_dump_member(float, &state->alpha, ref_value);
- trace_dump_struct_end();
- trace_dump_member_end();
-
- trace_dump_struct_end();
-}
-
-
-void trace_dump_blend_state(const struct pipe_blend_state *state)
-{
- if(!state) {
- trace_dump_null();
- return;
- }
-
- trace_dump_struct_begin("pipe_blend_state");
-
- trace_dump_member(bool, state, blend_enable);
-
- trace_dump_member(uint, state, rgb_func);
- trace_dump_member(uint, state, rgb_src_factor);
- trace_dump_member(uint, state, rgb_dst_factor);
-
- trace_dump_member(uint, state, alpha_func);
- trace_dump_member(uint, state, alpha_src_factor);
- trace_dump_member(uint, state, alpha_dst_factor);
-
- trace_dump_member(bool, state, logicop_enable);
- trace_dump_member(uint, state, logicop_func);
-
- trace_dump_member(uint, state, colormask);
- trace_dump_member(bool, state, dither);
-
- trace_dump_struct_end();
-}
-
-
-void trace_dump_blend_color(const struct pipe_blend_color *state)
-{
- if(!state) {
- trace_dump_null();
- return;
- }
-
- trace_dump_struct_begin("pipe_blend_color");
-
- trace_dump_member_array(float, state, color);
-
- trace_dump_struct_end();
-}
-
-
-void trace_dump_framebuffer_state(const struct pipe_framebuffer_state *state)
-{
- trace_dump_struct_begin("pipe_framebuffer_state");
-
- trace_dump_member(uint, state, width);
- trace_dump_member(uint, state, height);
- trace_dump_member(uint, state, nr_cbufs);
- trace_dump_member_array(ptr, state, cbufs);
- trace_dump_member(ptr, state, zsbuf);
-
- trace_dump_struct_end();
-}
-
-
-void trace_dump_sampler_state(const struct pipe_sampler_state *state)
-{
- if(!state) {
- trace_dump_null();
- return;
- }
-
- trace_dump_struct_begin("pipe_sampler_state");
-
- trace_dump_member(uint, state, wrap_s);
- trace_dump_member(uint, state, wrap_t);
- trace_dump_member(uint, state, wrap_r);
- trace_dump_member(uint, state, min_img_filter);
- trace_dump_member(uint, state, min_mip_filter);
- trace_dump_member(uint, state, mag_img_filter);
- trace_dump_member(bool, state, compare_mode);
- trace_dump_member(uint, state, compare_func);
- trace_dump_member(bool, state, normalized_coords);
- trace_dump_member(uint, state, prefilter);
- trace_dump_member(float, state, shadow_ambient);
- trace_dump_member(float, state, lod_bias);
- trace_dump_member(float, state, min_lod);
- trace_dump_member(float, state, max_lod);
- trace_dump_member_array(float, state, border_color);
- trace_dump_member(float, state, max_anisotropy);
-
- trace_dump_struct_end();
-}
-
-
-void trace_dump_surface(const struct pipe_surface *state)
-{
- if(!state) {
- trace_dump_null();
- return;
- }
-
- trace_dump_struct_begin("pipe_surface");
-
- trace_dump_reference(&state->reference);
-
- trace_dump_member(format, state, format);
- trace_dump_member(uint, state, width);
- trace_dump_member(uint, state, height);
-
- trace_dump_member(uint, state, layout);
- trace_dump_member(uint, state, offset);
- trace_dump_member(uint, state, usage);
-
- trace_dump_member(ptr, state, texture);
- trace_dump_member(uint, state, face);
- trace_dump_member(uint, state, level);
- trace_dump_member(uint, state, zslice);
-
- trace_dump_struct_end();
-}
-
+#include "tgsi/tgsi_parse.h"
-void trace_dump_transfer(const struct pipe_transfer *state)
+struct trace_shader * trace_shader_create(struct trace_context *tr_ctx,
+ const struct pipe_shader_state *state,
+ void *result,
+ enum trace_shader_type type)
{
- if(!state) {
- trace_dump_null();
- return;
- }
+ struct trace_shader *tr_shdr = CALLOC_STRUCT(trace_shader);
- trace_dump_struct_begin("pipe_transfer");
+ tr_shdr->state = result;
+ tr_shdr->type = type;
+ tr_shdr->tokens = tgsi_dup_tokens(state->tokens);
- trace_dump_member(format, state, format);
- trace_dump_member(uint, state, width);
- trace_dump_member(uint, state, height);
+ /* works on context as well */
+ trace_screen_add_to_list(tr_ctx, shaders, tr_shdr);
- trace_dump_member_begin("block");
- trace_dump_block(&state->block);
- trace_dump_member_end();
-
- trace_dump_member(uint, state, nblocksx);
- trace_dump_member(uint, state, nblocksy);
- trace_dump_member(uint, state, stride);
- trace_dump_member(uint, state, usage);
-
- trace_dump_member(ptr, state, texture);
- trace_dump_member(uint, state, face);
- trace_dump_member(uint, state, level);
- trace_dump_member(uint, state, zslice);
-
- trace_dump_struct_end();
+ return tr_shdr;
}
-
-void trace_dump_vertex_buffer(const struct pipe_vertex_buffer *state)
+void trace_shader_destroy(struct trace_context *tr_ctx,
+ struct trace_shader *tr_shdr)
{
- if(!state) {
- trace_dump_null();
- return;
- }
+ trace_screen_remove_from_list(tr_ctx, shaders, tr_shdr);
- trace_dump_struct_begin("pipe_vertex_buffer");
-
- trace_dump_member(uint, state, stride);
- trace_dump_member(uint, state, max_index);
- trace_dump_member(uint, state, buffer_offset);
- trace_dump_member(buffer_ptr, state, buffer);
-
- trace_dump_struct_end();
-}
-
-
-void trace_dump_vertex_element(const struct pipe_vertex_element *state)
-{
- if(!state) {
- trace_dump_null();
- return;
+ if (tr_shdr->replaced) {
+ if (tr_shdr->type == TRACE_SHADER_FRAGMENT)
+ tr_ctx->pipe->delete_fs_state(tr_ctx->pipe, tr_shdr->replaced);
+ else if (tr_shdr->type == TRACE_SHADER_VERTEX)
+ tr_ctx->pipe->delete_vs_state(tr_ctx->pipe, tr_shdr->replaced);
+ else
+ assert(0);
}
- trace_dump_struct_begin("pipe_vertex_element");
-
- trace_dump_member(uint, state, src_offset);
-
- trace_dump_member(uint, state, vertex_buffer_index);
- trace_dump_member(uint, state, nr_components);
-
- trace_dump_member(format, state, src_format);
-
- trace_dump_struct_end();
+ FREE(tr_shdr->replaced_tokens);
+ FREE(tr_shdr->tokens);
+ FREE(tr_shdr);
}
diff --git a/src/gallium/drivers/trace/tr_state.h b/src/gallium/drivers/trace/tr_state.h
index 513ed0ac98..1c16042ee5 100644
--- a/src/gallium/drivers/trace/tr_state.h
+++ b/src/gallium/drivers/trace/tr_state.h
@@ -1,78 +1,68 @@
-/**************************************************************************
- *
- * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+/*
+ * 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.
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on 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 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.
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
*
- **************************************************************************/
-
-#ifndef TR_STATE_H
-#define TR_STATE_H
-
-#include "pipe/p_format.h"
-#include "pipe/p_state.h"
-#include "pipe/p_shader_tokens.h"
-
-
-void trace_dump_format(enum pipe_format format);
-
-void trace_dump_block(const struct pipe_format_block *block);
-
-void trace_dump_template(const struct pipe_texture *templat);
-
-
-void trace_dump_rasterizer_state(const struct pipe_rasterizer_state *state);
-
-void trace_dump_poly_stipple(const struct pipe_poly_stipple *state);
-
-void trace_dump_viewport_state(const struct pipe_viewport_state *state);
-
-void trace_dump_scissor_state(const struct pipe_scissor_state *state);
-
-void trace_dump_clip_state(const struct pipe_clip_state *state);
+ * 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
+ * VMWARE AND/OR THEIR 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.
+ */
-void trace_dump_constant_buffer(const struct pipe_constant_buffer *state);
+#ifndef TR_STATE_H_
+#define TR_STATE_H_
-void trace_dump_token(const struct tgsi_token *token);
+#include "tr_context.h"
-void trace_dump_shader_state(const struct pipe_shader_state *state);
+struct tgsi_token;
-void trace_dump_depth_stencil_alpha_state(const struct pipe_depth_stencil_alpha_state *state);
+enum trace_shader_type {
+ TRACE_SHADER_FRAGMENT = 0,
+ TRACE_SHADER_VERTEX = 1,
+ TRACE_SHADER_GEOMETRY = 2,
+};
-void trace_dump_blend_state(const struct pipe_blend_state *state);
+struct trace_shader
+{
+ struct tr_list list;
-void trace_dump_blend_color(const struct pipe_blend_color *state);
+ enum trace_shader_type type;
-void trace_dump_framebuffer_state(const struct pipe_framebuffer_state *state);
+ void *state;
+ void *replaced;
-void trace_dump_sampler_state(const struct pipe_sampler_state *state);
+ struct tgsi_token *tokens;
+ struct tgsi_token *replaced_tokens;
-void trace_dump_surface(const struct pipe_surface *state);
+ boolean disabled;
+};
-void trace_dump_transfer(const struct pipe_transfer *state);
-void trace_dump_vertex_buffer(const struct pipe_vertex_buffer *state);
+static INLINE struct trace_shader *
+trace_shader(void *state)
+{
+ return (struct trace_shader *)state;
+}
-void trace_dump_vertex_element(const struct pipe_vertex_element *state);
+struct trace_shader * trace_shader_create(struct trace_context *tr_ctx,
+ const struct pipe_shader_state *state,
+ void *result,
+ enum trace_shader_type type);
+void trace_shader_destroy(struct trace_context *tr_ctx,
+ struct trace_shader *tr_shdr);
-#endif /* TR_STATE_H */
+#endif