diff options
author | Chia-I Wu <olvaffe@gmail.com> | 2009-09-15 14:16:22 +0800 |
---|---|---|
committer | Chia-I Wu <olvaffe@gmail.com> | 2009-09-15 14:16:22 +0800 |
commit | e2ba90a9cc762cf00a168f0a59d31e7dc52fc42e (patch) | |
tree | fe3206d7602ad935296884742980f3c4d30bd867 /src/gallium/drivers/trace | |
parent | 11a4292d4eb515813b82b8d688a318adef66b3e6 (diff) | |
parent | b4b8800315637d9218a81c76f09df7d601710d29 (diff) |
Merge commit 'eee/mesa-es' into android
Diffstat (limited to 'src/gallium/drivers/trace')
21 files changed, 5887 insertions, 0 deletions
diff --git a/src/gallium/drivers/trace/Makefile b/src/gallium/drivers/trace/Makefile new file mode 100644 index 0000000000..dd6831c70a --- /dev/null +++ b/src/gallium/drivers/trace/Makefile @@ -0,0 +1,17 @@ +TOP = ../../../.. +include $(TOP)/configs/current + +LIBNAME = trace + +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 new file mode 100644 index 0000000000..1000c31e49 --- /dev/null +++ b/src/gallium/drivers/trace/README @@ -0,0 +1,78 @@ + TRACE PIPE DRIVER + + += About = + +This directory contains a Gallium3D debugger pipe driver. +It can traces all incoming calls and/or provide remote debugging functionality. + + += Build Instructions = + +To build, invoke scons on the top dir as + + scons dri=no statetrackers=mesa drivers=softpipe,i965simple,trace winsys=xlib + + += Usage = + +To use do + + export LD_LIBRARY_PATH=$PWD/build/linux-x86-debug/lib + +ensure the right libGL.so is being picked by doing + + ldd progs/trivial/tri + +== Traceing == + +For traceing then do + + export XMESA_TRACE=y + GALLIUM_TRACE=tri.trace progs/trivial/tri + +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 = + +You can integrate the trace pipe driver either inside the state tracker or the +winsys. The procedure on both cases is the same. Let's assume you have a +pipe_screen and a pipe_context pair obtained by the usual means (variable and +function names are just for illustration purposes): + + real_screen = real_screen_create(...); + + real_context = real_context_create(...); + +The trace screen and pipe_context is then created by doing + + trace_screen = trace_screen_create(real_screen); + + trace_context = trace_context_create(trace_screen, real_context); + +You can then simply use trace_screen and trace_context instead of real_screen +and real_context. + +Do not call trace_winsys_create. Simply pass trace_screen->winsys or +trace_context->winsys in places you would pass winsys. + +You can create as many contexts you wish. Just ensure that you don't mistake +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 new file mode 100644 index 0000000000..c1675d1c16 --- /dev/null +++ b/src/gallium/drivers/trace/SConscript @@ -0,0 +1,19 @@ +Import('*') + +env = env.Clone() + +trace = env.ConvenienceLibrary( + target = 'trace', + source = [ + 'tr_buffer.c', + 'tr_context.c', + 'tr_drm.c', + 'tr_dump.c', + 'tr_dump_state.c', + 'tr_screen.c', + 'tr_state.c', + 'tr_rbug.c', + 'tr_texture.c', + ]) + +Export('trace') diff --git a/src/gallium/drivers/trace/tr_buffer.c b/src/gallium/drivers/trace/tr_buffer.c new file mode 100644 index 0000000000..4f0eff6a5a --- /dev/null +++ b/src/gallium/drivers/trace/tr_buffer.c @@ -0,0 +1,75 @@ +/************************************************************************** + * + * 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_memory.h" +#include "util/u_simple_list.h" + +#include "tr_buffer.h" + +struct pipe_buffer * +trace_buffer_create(struct trace_screen *tr_scr, + struct pipe_buffer *buffer) +{ + struct trace_buffer *tr_buf; + + if(!buffer) + goto error; + + assert(buffer->screen == tr_scr->screen); + + tr_buf = CALLOC_STRUCT(trace_buffer); + if(!tr_buf) + goto error; + + memcpy(&tr_buf->base, buffer, sizeof(struct pipe_buffer)); + + pipe_reference_init(&tr_buf->base.reference, 1); + tr_buf->base.screen = &tr_scr->base; + tr_buf->buffer = buffer; + + trace_screen_add_to_list(tr_scr, buffers, tr_buf); + + return &tr_buf->base; + +error: + pipe_buffer_reference(&buffer, NULL); + return NULL; +} + + +void +trace_buffer_destroy(struct trace_screen *tr_scr, + struct pipe_buffer *buffer) +{ + struct trace_buffer *tr_buf = trace_buffer(buffer); + + trace_screen_remove_from_list(tr_scr, buffers, tr_buf); + + pipe_buffer_reference(&tr_buf->buffer, NULL); + FREE(tr_buf); +} diff --git a/src/gallium/drivers/trace/tr_buffer.h b/src/gallium/drivers/trace/tr_buffer.h new file mode 100644 index 0000000000..1a2d0b9aea --- /dev/null +++ b/src/gallium/drivers/trace/tr_buffer.h @@ -0,0 +1,70 @@ +/************************************************************************** + * + * 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. + * + **************************************************************************/ + +#ifndef TR_BUFFER_H_ +#define TR_BUFFER_H_ + + +#include "pipe/p_compiler.h" +#include "pipe/p_state.h" + +#include "tr_screen.h" + + +struct trace_buffer +{ + struct pipe_buffer base; + + struct pipe_buffer *buffer; + + struct tr_list list; + + void *map; + boolean range_flushed; +}; + + +static INLINE struct trace_buffer * +trace_buffer(struct pipe_buffer *buffer) +{ + if(!buffer) + return NULL; + (void)trace_screen(buffer->screen); + return (struct trace_buffer *)buffer; +} + + +struct pipe_buffer * +trace_buffer_create(struct trace_screen *tr_scr, + struct pipe_buffer *buffer); + +void +trace_buffer_destroy(struct trace_screen *tr_scr, + struct pipe_buffer *buffer); + + +#endif diff --git a/src/gallium/drivers/trace/tr_context.c b/src/gallium/drivers/trace/tr_context.c new file mode 100644 index 0000000000..ae0af4d055 --- /dev/null +++ b/src/gallium/drivers/trace/tr_context.c @@ -0,0 +1,1302 @@ +/************************************************************************** + * + * 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 "util/u_memory.h" +#include "util/u_simple_list.h" + +#include "pipe/p_screen.h" + +#include "tr_dump.h" +#include "tr_dump_state.h" +#include "tr_state.h" +#include "tr_buffer.h" +#include "tr_screen.h" +#include "tr_texture.h" + + +static INLINE struct pipe_buffer * +trace_buffer_unwrap(struct trace_context *tr_ctx, + struct pipe_buffer *buffer) +{ + struct trace_screen *tr_scr = trace_screen(tr_ctx->base.screen); + struct trace_buffer *tr_buf; + + if(!buffer) + return NULL; + + tr_buf = trace_buffer(buffer); + + assert(tr_buf->buffer); + assert(tr_buf->buffer->screen == tr_scr->screen); + return tr_buf->buffer; +} + + +static INLINE struct pipe_texture * +trace_texture_unwrap(struct trace_context *tr_ctx, + struct pipe_texture *texture) +{ + struct trace_texture *tr_tex; + + if(!texture) + return NULL; + + tr_tex = trace_texture(texture); + + assert(tr_tex->texture); + return tr_tex->texture; +} + + +static INLINE struct pipe_surface * +trace_surface_unwrap(struct trace_context *tr_ctx, + struct pipe_surface *surface) +{ + struct trace_screen *tr_scr = trace_screen(tr_ctx->base.screen); + struct trace_surface *tr_surf; + + if(!surface) + return NULL; + + assert(surface->texture); + if(!surface->texture) + return surface; + + tr_surf = trace_surface(surface); + + assert(tr_surf->surface); + assert(tr_surf->surface->texture->screen == tr_scr->screen); + return tr_surf->surface; +} + + +static INLINE void +trace_context_set_edgeflags(struct pipe_context *_pipe, + const unsigned *bitfield) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct pipe_context *pipe = tr_ctx->pipe; + + trace_dump_call_begin("pipe_context", "set_edgeflags"); + + trace_dump_arg(ptr, pipe); + /* FIXME: we don't know how big this array is */ + trace_dump_arg(ptr, bitfield); + + pipe->set_edgeflags(pipe, bitfield);; + + trace_dump_call_end(); +} + + +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) +{ + struct trace_context *tr_ctx = trace_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); + trace_dump_arg(uint, mode); + trace_dump_arg(uint, start); + trace_dump_arg(uint, count); + + result = pipe->draw_arrays(pipe, mode, start, count);; + + trace_dump_ret(bool, result); + + trace_dump_call_end(); + + trace_context_draw_block(tr_ctx, 2); + + return result; +} + + +static INLINE boolean +trace_context_draw_elements(struct pipe_context *_pipe, + struct pipe_buffer *_indexBuffer, + unsigned indexSize, + unsigned mode, unsigned start, unsigned count) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct trace_buffer *tr_buf = trace_buffer(_indexBuffer); + struct pipe_context *pipe = tr_ctx->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"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(ptr, indexBuffer); + trace_dump_arg(uint, indexSize); + trace_dump_arg(uint, mode); + trace_dump_arg(uint, start); + trace_dump_arg(uint, count); + + result = pipe->draw_elements(pipe, indexBuffer, indexSize, mode, start, count);; + + trace_dump_ret(bool, result); + + trace_dump_call_end(); + + trace_context_draw_block(tr_ctx, 2); + + return result; +} + + +static INLINE boolean +trace_context_draw_range_elements(struct pipe_context *_pipe, + struct pipe_buffer *_indexBuffer, + unsigned indexSize, + unsigned minIndex, + unsigned maxIndex, + unsigned mode, + unsigned start, + unsigned count) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct trace_buffer *tr_buf = trace_buffer(_indexBuffer); + struct pipe_context *pipe = tr_ctx->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"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(ptr, indexBuffer); + trace_dump_arg(uint, indexSize); + trace_dump_arg(uint, minIndex); + trace_dump_arg(uint, maxIndex); + trace_dump_arg(uint, mode); + trace_dump_arg(uint, start); + trace_dump_arg(uint, count); + + result = pipe->draw_range_elements(pipe, + indexBuffer, + indexSize, minIndex, maxIndex, + mode, start, count); + + trace_dump_ret(bool, result); + + trace_dump_call_end(); + + trace_context_draw_block(tr_ctx, 2); + + return result; +} + + +static INLINE struct pipe_query * +trace_context_create_query(struct pipe_context *_pipe, + unsigned query_type) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct pipe_context *pipe = tr_ctx->pipe; + struct pipe_query *result; + + trace_dump_call_begin("pipe_context", "create_query"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(uint, query_type); + + result = pipe->create_query(pipe, query_type);; + + trace_dump_ret(ptr, result); + + trace_dump_call_end(); + + return result; +} + + +static INLINE void +trace_context_destroy_query(struct pipe_context *_pipe, + struct pipe_query *query) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct pipe_context *pipe = tr_ctx->pipe; + + trace_dump_call_begin("pipe_context", "destroy_query"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(ptr, query); + + pipe->destroy_query(pipe, query);; + + trace_dump_call_end(); +} + + +static INLINE void +trace_context_begin_query(struct pipe_context *_pipe, + struct pipe_query *query) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct pipe_context *pipe = tr_ctx->pipe; + + trace_dump_call_begin("pipe_context", "begin_query"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(ptr, query); + + pipe->begin_query(pipe, query);; + + trace_dump_call_end(); +} + + +static INLINE void +trace_context_end_query(struct pipe_context *_pipe, + struct pipe_query *query) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct pipe_context *pipe = tr_ctx->pipe; + + trace_dump_call_begin("pipe_context", "end_query"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(ptr, query); + + pipe->end_query(pipe, query); + + trace_dump_call_end(); +} + + +static INLINE boolean +trace_context_get_query_result(struct pipe_context *_pipe, + struct pipe_query *query, + boolean wait, + uint64_t *presult) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct pipe_context *pipe = tr_ctx->pipe; + uint64_t result; + boolean _result; + + trace_dump_call_begin("pipe_context", "get_query_result"); + + trace_dump_arg(ptr, pipe); + + _result = pipe->get_query_result(pipe, query, wait, presult);; + result = *presult; + + trace_dump_arg(uint, result); + trace_dump_ret(bool, _result); + + trace_dump_call_end(); + + return _result; +} + + +static INLINE void * +trace_context_create_blend_state(struct pipe_context *_pipe, + const struct pipe_blend_state *state) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct pipe_context *pipe = tr_ctx->pipe; + void * result; + + trace_dump_call_begin("pipe_context", "create_blend_state"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(blend_state, state); + + result = pipe->create_blend_state(pipe, state);; + + trace_dump_ret(ptr, result); + + trace_dump_call_end(); + + return result; +} + + +static INLINE void +trace_context_bind_blend_state(struct pipe_context *_pipe, + void *state) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct pipe_context *pipe = tr_ctx->pipe; + + trace_dump_call_begin("pipe_context", "bind_blend_state"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(ptr, state); + + pipe->bind_blend_state(pipe, state);; + + trace_dump_call_end(); +} + + +static INLINE void +trace_context_delete_blend_state(struct pipe_context *_pipe, + void *state) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct pipe_context *pipe = tr_ctx->pipe; + + trace_dump_call_begin("pipe_context", "delete_blend_state"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(ptr, state); + + pipe->delete_blend_state(pipe, state);; + + trace_dump_call_end(); +} + + +static INLINE void * +trace_context_create_sampler_state(struct pipe_context *_pipe, + const struct pipe_sampler_state *state) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct pipe_context *pipe = tr_ctx->pipe; + void * result; + + trace_dump_call_begin("pipe_context", "create_sampler_state"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(sampler_state, state); + + result = pipe->create_sampler_state(pipe, state);; + + trace_dump_ret(ptr, result); + + trace_dump_call_end(); + + return result; +} + + +static INLINE void +trace_context_bind_sampler_states(struct pipe_context *_pipe, + unsigned num_states, void **states) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct pipe_context *pipe = tr_ctx->pipe; + + trace_dump_call_begin("pipe_context", "bind_sampler_states"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(uint, num_states); + trace_dump_arg_array(ptr, states, num_states); + + pipe->bind_sampler_states(pipe, num_states, states);; + + trace_dump_call_end(); +} + + +static INLINE void +trace_context_delete_sampler_state(struct pipe_context *_pipe, + void *state) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct pipe_context *pipe = tr_ctx->pipe; + + trace_dump_call_begin("pipe_context", "delete_sampler_state"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(ptr, state); + + pipe->delete_sampler_state(pipe, state);; + + trace_dump_call_end(); +} + + +static INLINE void * +trace_context_create_rasterizer_state(struct pipe_context *_pipe, + const struct pipe_rasterizer_state *state) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct pipe_context *pipe = tr_ctx->pipe; + void * result; + + trace_dump_call_begin("pipe_context", "create_rasterizer_state"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(rasterizer_state, state); + + result = pipe->create_rasterizer_state(pipe, state);; + + trace_dump_ret(ptr, result); + + trace_dump_call_end(); + + return result; +} + + +static INLINE void +trace_context_bind_rasterizer_state(struct pipe_context *_pipe, + void *state) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct pipe_context *pipe = tr_ctx->pipe; + + trace_dump_call_begin("pipe_context", "bind_rasterizer_state"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(ptr, state); + + pipe->bind_rasterizer_state(pipe, state);; + + trace_dump_call_end(); +} + + +static INLINE void +trace_context_delete_rasterizer_state(struct pipe_context *_pipe, + void *state) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct pipe_context *pipe = tr_ctx->pipe; + + trace_dump_call_begin("pipe_context", "delete_rasterizer_state"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(ptr, state); + + pipe->delete_rasterizer_state(pipe, state);; + + trace_dump_call_end(); +} + + +static INLINE void * +trace_context_create_depth_stencil_alpha_state(struct pipe_context *_pipe, + const struct pipe_depth_stencil_alpha_state *state) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct pipe_context *pipe = tr_ctx->pipe; + void * result; + + trace_dump_call_begin("pipe_context", "create_depth_stencil_alpha_state"); + + result = pipe->create_depth_stencil_alpha_state(pipe, state);; + + trace_dump_arg(ptr, pipe); + trace_dump_arg(depth_stencil_alpha_state, state); + + trace_dump_ret(ptr, result); + + trace_dump_call_end(); + + return result; +} + + +static INLINE void +trace_context_bind_depth_stencil_alpha_state(struct pipe_context *_pipe, + void *state) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct pipe_context *pipe = tr_ctx->pipe; + + trace_dump_call_begin("pipe_context", "bind_depth_stencil_alpha_state"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(ptr, state); + + pipe->bind_depth_stencil_alpha_state(pipe, state);; + + trace_dump_call_end(); +} + + +static INLINE void +trace_context_delete_depth_stencil_alpha_state(struct pipe_context *_pipe, + void *state) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct pipe_context *pipe = tr_ctx->pipe; + + trace_dump_call_begin("pipe_context", "delete_depth_stencil_alpha_state"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(ptr, state); + + pipe->delete_depth_stencil_alpha_state(pipe, state);; + + trace_dump_call_end(); +} + + +static INLINE void * +trace_context_create_fs_state(struct pipe_context *_pipe, + const struct pipe_shader_state *state) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct pipe_context *pipe = tr_ctx->pipe; + void * result; + + trace_dump_call_begin("pipe_context", "create_fs_state"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(shader_state, state); + + result = pipe->create_fs_state(pipe, state);; + + trace_dump_ret(ptr, result); + + 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) +{ + 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); + + 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(); +} + + +static INLINE void +trace_context_delete_fs_state(struct pipe_context *_pipe, + 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); + + trace_dump_call_end(); + + trace_shader_destroy(tr_ctx, tr_shdr); +} + + +static INLINE void * +trace_context_create_vs_state(struct pipe_context *_pipe, + const struct pipe_shader_state *state) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct pipe_context *pipe = tr_ctx->pipe; + void * result; + + trace_dump_call_begin("pipe_context", "create_vs_state"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(shader_state, 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) +{ + 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(); +} + + +static INLINE void +trace_context_delete_vs_state(struct pipe_context *_pipe, + 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"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(ptr, state); + + pipe->delete_vs_state(pipe, state);; + + trace_dump_call_end(); + + trace_shader_destroy(tr_ctx, tr_shdr); +} + + +static INLINE void +trace_context_set_blend_color(struct pipe_context *_pipe, + const struct pipe_blend_color *state) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct pipe_context *pipe = tr_ctx->pipe; + + trace_dump_call_begin("pipe_context", "set_blend_color"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(blend_color, state); + + pipe->set_blend_color(pipe, state);; + + trace_dump_call_end(); +} + + +static INLINE void +trace_context_set_clip_state(struct pipe_context *_pipe, + const struct pipe_clip_state *state) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct pipe_context *pipe = tr_ctx->pipe; + + trace_dump_call_begin("pipe_context", "set_clip_state"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(clip_state, state); + + pipe->set_clip_state(pipe, state);; + + trace_dump_call_end(); +} + + +static INLINE void +trace_context_set_constant_buffer(struct pipe_context *_pipe, + uint shader, uint index, + const struct pipe_constant_buffer *buffer) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct pipe_context *pipe = tr_ctx->pipe; + + if (buffer) + trace_screen_user_buffer_update(_pipe->screen, buffer->buffer); + + trace_dump_call_begin("pipe_context", "set_constant_buffer"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(uint, shader); + trace_dump_arg(uint, index); + trace_dump_arg(constant_buffer, buffer); + + if (buffer) { + struct pipe_constant_buffer _buffer; + _buffer.buffer = trace_buffer_unwrap(tr_ctx, buffer->buffer); + pipe->set_constant_buffer(pipe, shader, index, &_buffer); + } else { + pipe->set_constant_buffer(pipe, shader, index, buffer); + } + + trace_dump_call_end(); +} + + +static INLINE void +trace_context_set_framebuffer_state(struct pipe_context *_pipe, + const struct pipe_framebuffer_state *state) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct pipe_context *pipe = tr_ctx->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) + unwrapped_state.cbufs[i] = trace_surface_unwrap(tr_ctx, state->cbufs[i]); + for(i = state->nr_cbufs; i < PIPE_MAX_COLOR_BUFS; ++i) + unwrapped_state.cbufs[i] = NULL; + unwrapped_state.zsbuf = trace_surface_unwrap(tr_ctx, state->zsbuf); + state = &unwrapped_state; + + trace_dump_call_begin("pipe_context", "set_framebuffer_state"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(framebuffer_state, state); + + pipe->set_framebuffer_state(pipe, state);; + + trace_dump_call_end(); +} + + +static INLINE void +trace_context_set_polygon_stipple(struct pipe_context *_pipe, + const struct pipe_poly_stipple *state) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct pipe_context *pipe = tr_ctx->pipe; + + trace_dump_call_begin("pipe_context", "set_polygon_stipple"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(poly_stipple, state); + + pipe->set_polygon_stipple(pipe, state);; + + trace_dump_call_end(); +} + + +static INLINE void +trace_context_set_scissor_state(struct pipe_context *_pipe, + const struct pipe_scissor_state *state) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct pipe_context *pipe = tr_ctx->pipe; + + trace_dump_call_begin("pipe_context", "set_scissor_state"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(scissor_state, state); + + pipe->set_scissor_state(pipe, state);; + + trace_dump_call_end(); +} + + +static INLINE void +trace_context_set_viewport_state(struct pipe_context *_pipe, + const struct pipe_viewport_state *state) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct pipe_context *pipe = tr_ctx->pipe; + + trace_dump_call_begin("pipe_context", "set_viewport_state"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(viewport_state, state); + + pipe->set_viewport_state(pipe, state);; + + trace_dump_call_end(); +} + + +static INLINE void +trace_context_set_sampler_textures(struct pipe_context *_pipe, + unsigned num_textures, + 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; + + 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"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(uint, num_textures); + trace_dump_arg_array(ptr, textures, num_textures); + + pipe->set_sampler_textures(pipe, num_textures, textures);; + + trace_dump_call_end(); +} + + +static INLINE void +trace_context_set_vertex_buffers(struct pipe_context *_pipe, + unsigned num_buffers, + const struct pipe_vertex_buffer *buffers) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct pipe_context *pipe = tr_ctx->pipe; + unsigned i; + + for(i = 0; i < num_buffers; ++i) + trace_screen_user_buffer_update(_pipe->screen, buffers[i].buffer); + + trace_dump_call_begin("pipe_context", "set_vertex_buffers"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(uint, num_buffers); + + trace_dump_arg_begin("buffers"); + trace_dump_struct_array(vertex_buffer, buffers, num_buffers); + trace_dump_arg_end(); + + if (num_buffers) { + struct pipe_vertex_buffer *_buffers = malloc(num_buffers * sizeof(*_buffers)); + memcpy(_buffers, buffers, num_buffers * sizeof(*_buffers)); + for (i = 0; i < num_buffers; i++) + _buffers[i].buffer = trace_buffer_unwrap(tr_ctx, buffers[i].buffer); + pipe->set_vertex_buffers(pipe, num_buffers, _buffers); + free(_buffers); + } else { + pipe->set_vertex_buffers(pipe, num_buffers, NULL); + } + + trace_dump_call_end(); +} + + +static INLINE void +trace_context_set_vertex_elements(struct pipe_context *_pipe, + unsigned num_elements, + const struct pipe_vertex_element *elements) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct pipe_context *pipe = tr_ctx->pipe; + + trace_dump_call_begin("pipe_context", "set_vertex_elements"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(uint, num_elements); + + trace_dump_arg_begin("elements"); + trace_dump_struct_array(vertex_element, elements, num_elements); + trace_dump_arg_end(); + + pipe->set_vertex_elements(pipe, num_elements, elements);; + + trace_dump_call_end(); +} + + +static INLINE void +trace_context_surface_copy(struct pipe_context *_pipe, + struct pipe_surface *dest, + unsigned destx, unsigned desty, + struct pipe_surface *src, + unsigned srcx, unsigned srcy, + unsigned width, unsigned height) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct pipe_context *pipe = tr_ctx->pipe; + + dest = trace_surface_unwrap(tr_ctx, dest); + src = trace_surface_unwrap(tr_ctx, src); + + trace_dump_call_begin("pipe_context", "surface_copy"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(ptr, dest); + trace_dump_arg(uint, destx); + trace_dump_arg(uint, desty); + trace_dump_arg(ptr, src); + trace_dump_arg(uint, srcx); + trace_dump_arg(uint, srcy); + trace_dump_arg(uint, width); + trace_dump_arg(uint, height); + + pipe->surface_copy(pipe, + dest, destx, desty, + src, srcx, srcy, width, height); + + trace_dump_call_end(); +} + + +static INLINE void +trace_context_surface_fill(struct pipe_context *_pipe, + struct pipe_surface *dst, + unsigned dstx, unsigned dsty, + unsigned width, unsigned height, + unsigned value) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct pipe_context *pipe = tr_ctx->pipe; + + dst = trace_surface_unwrap(tr_ctx, dst); + + trace_dump_call_begin("pipe_context", "surface_fill"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(ptr, dst); + trace_dump_arg(uint, dstx); + trace_dump_arg(uint, dsty); + trace_dump_arg(uint, width); + trace_dump_arg(uint, height); + + pipe->surface_fill(pipe, dst, dstx, dsty, width, height, value);; + + trace_dump_call_end(); +} + + +static INLINE void +trace_context_clear(struct pipe_context *_pipe, + unsigned buffers, + const float *rgba, + double depth, + unsigned stencil) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct pipe_context *pipe = tr_ctx->pipe; + + trace_dump_call_begin("pipe_context", "clear"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(uint, buffers); + trace_dump_arg_array(float, rgba, 4); + trace_dump_arg(float, depth); + trace_dump_arg(uint, stencil); + + pipe->clear(pipe, buffers, rgba, depth, stencil); + + trace_dump_call_end(); +} + + +static INLINE void +trace_context_flush(struct pipe_context *_pipe, + unsigned flags, + struct pipe_fence_handle **fence) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct pipe_context *pipe = tr_ctx->pipe; + + trace_dump_call_begin("pipe_context", "flush"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(uint, flags); + + pipe->flush(pipe, flags, fence);; + + if(fence) + trace_dump_ret(ptr, *fence); + + trace_dump_call_end(); +} + + +static INLINE void +trace_context_destroy(struct pipe_context *_pipe) +{ + struct trace_screen *tr_scr = trace_screen(_pipe->screen); + struct trace_context *tr_ctx = trace_context(_pipe); + struct pipe_context *pipe = tr_ctx->pipe; + + trace_dump_call_begin("pipe_context", "destroy"); + trace_dump_arg(ptr, pipe); + trace_dump_call_end(); + + trace_screen_remove_from_list(tr_scr, contexts, tr_ctx); + + pipe->destroy(pipe); + + FREE(tr_ctx); +} + +static unsigned int +trace_is_texture_referenced( struct pipe_context *_pipe, + struct pipe_texture *_texture, + unsigned face, unsigned level) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct trace_texture *tr_tex = trace_texture(_texture); + struct pipe_context *pipe = tr_ctx->pipe; + struct pipe_texture *texture = tr_tex->texture; + unsigned int referenced; + + trace_dump_call_begin("pipe_context", "is_texture_referenced"); + trace_dump_arg(ptr, pipe); + trace_dump_arg(ptr, texture); + trace_dump_arg(uint, face); + trace_dump_arg(uint, level); + + referenced = pipe->is_texture_referenced(pipe, texture, face, level); + + trace_dump_ret(uint, referenced); + trace_dump_call_end(); + + return referenced; +} + +static unsigned int +trace_is_buffer_referenced( struct pipe_context *_pipe, + struct pipe_buffer *_buf) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct trace_buffer *tr_buf = trace_buffer(_buf); + struct pipe_context *pipe = tr_ctx->pipe; + struct pipe_buffer *buf = tr_buf->buffer; + unsigned int referenced; + + trace_dump_call_begin("pipe_context", "is_buffer_referenced"); + trace_dump_arg(ptr, pipe); + trace_dump_arg(ptr, buf); + + referenced = pipe->is_buffer_referenced(pipe, buf); + + trace_dump_ret(uint, referenced); + trace_dump_call_end(); + + 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) +{ + struct trace_screen *tr_scr; + struct trace_context *tr_ctx; + struct pipe_screen *screen; + + if(!pipe) + goto error1; + + if(!trace_enabled()) + goto error1; + + tr_scr = trace_screen(_screen); + screen = tr_scr->screen; + + tr_ctx = CALLOC_STRUCT(trace_context); + 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; + tr_ctx->base.set_edgeflags = trace_context_set_edgeflags; + tr_ctx->base.draw_arrays = trace_context_draw_arrays; + tr_ctx->base.draw_elements = trace_context_draw_elements; + tr_ctx->base.draw_range_elements = trace_context_draw_range_elements; + tr_ctx->base.create_query = trace_context_create_query; + tr_ctx->base.destroy_query = trace_context_destroy_query; + tr_ctx->base.begin_query = trace_context_begin_query; + tr_ctx->base.end_query = trace_context_end_query; + tr_ctx->base.get_query_result = trace_context_get_query_result; + tr_ctx->base.create_blend_state = trace_context_create_blend_state; + tr_ctx->base.bind_blend_state = trace_context_bind_blend_state; + tr_ctx->base.delete_blend_state = trace_context_delete_blend_state; + tr_ctx->base.create_sampler_state = trace_context_create_sampler_state; + tr_ctx->base.bind_sampler_states = trace_context_bind_sampler_states; + tr_ctx->base.delete_sampler_state = trace_context_delete_sampler_state; + tr_ctx->base.create_rasterizer_state = trace_context_create_rasterizer_state; + tr_ctx->base.bind_rasterizer_state = trace_context_bind_rasterizer_state; + tr_ctx->base.delete_rasterizer_state = trace_context_delete_rasterizer_state; + tr_ctx->base.create_depth_stencil_alpha_state = trace_context_create_depth_stencil_alpha_state; + tr_ctx->base.bind_depth_stencil_alpha_state = trace_context_bind_depth_stencil_alpha_state; + tr_ctx->base.delete_depth_stencil_alpha_state = trace_context_delete_depth_stencil_alpha_state; + tr_ctx->base.create_fs_state = trace_context_create_fs_state; + tr_ctx->base.bind_fs_state = trace_context_bind_fs_state; + tr_ctx->base.delete_fs_state = trace_context_delete_fs_state; + tr_ctx->base.create_vs_state = trace_context_create_vs_state; + tr_ctx->base.bind_vs_state = trace_context_bind_vs_state; + tr_ctx->base.delete_vs_state = trace_context_delete_vs_state; + tr_ctx->base.set_blend_color = trace_context_set_blend_color; + tr_ctx->base.set_clip_state = trace_context_set_clip_state; + tr_ctx->base.set_constant_buffer = trace_context_set_constant_buffer; + tr_ctx->base.set_framebuffer_state = trace_context_set_framebuffer_state; + tr_ctx->base.set_polygon_stipple = trace_context_set_polygon_stipple; + tr_ctx->base.set_scissor_state = trace_context_set_scissor_state; + tr_ctx->base.set_viewport_state = trace_context_set_viewport_state; + tr_ctx->base.set_sampler_textures = trace_context_set_sampler_textures; + tr_ctx->base.set_vertex_buffers = trace_context_set_vertex_buffers; + tr_ctx->base.set_vertex_elements = trace_context_set_vertex_elements; + if (pipe->surface_copy) + tr_ctx->base.surface_copy = trace_context_surface_copy; + if (pipe->surface_fill) + tr_ctx->base.surface_fill = trace_context_surface_fill; + tr_ctx->base.clear = trace_context_clear; + tr_ctx->base.flush = trace_context_flush; + tr_ctx->base.is_texture_referenced = trace_is_texture_referenced; + tr_ctx->base.is_buffer_referenced = trace_is_buffer_referenced; + + tr_ctx->pipe = pipe; + + trace_dump_call_begin("", "pipe_context_create"); + trace_dump_arg(ptr, screen); + trace_dump_ret(ptr, pipe); + trace_dump_call_end(); + + trace_screen_add_to_list(tr_scr, contexts, tr_ctx); + + return &tr_ctx->base; + +error1: + return pipe; +} diff --git a/src/gallium/drivers/trace/tr_context.h b/src/gallium/drivers/trace/tr_context.h new file mode 100644 index 0000000000..6febe4b411 --- /dev/null +++ b/src/gallium/drivers/trace/tr_context.h @@ -0,0 +1,108 @@ +/************************************************************************** + * + * 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_CONTEXT_H_ +#define TR_CONTEXT_H_ + + +#include "pipe/p_compiler.h" +#include "util/u_debug.h" +#include "pipe/p_context.h" + +#include "tr_screen.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +struct trace_context +{ + struct pipe_context base; + + 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; +}; + + +static INLINE struct trace_context * +trace_context(struct pipe_context *pipe) +{ + assert(pipe); + return (struct trace_context *)pipe; +} + + + +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 +} +#endif + +#endif /* TR_CONTEXT_H_ */ diff --git a/src/gallium/drivers/trace/tr_drm.c b/src/gallium/drivers/trace/tr_drm.c new file mode 100644 index 0000000000..781ca5d3bc --- /dev/null +++ b/src/gallium/drivers/trace/tr_drm.c @@ -0,0 +1,186 @@ +/************************************************************************** + * + * 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 struct pipe_texture * +trace_drm_texture_from_shared_handle(struct drm_api *_api, + struct pipe_screen *_screen, + struct pipe_texture *templ, + const char *name, + unsigned stride, + 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_texture *result; + + /* TODO trace call */ + + result = api->texture_from_shared_handle(api, screen, templ, name, stride, handle); + + result = trace_texture_create(trace_screen(_screen), result); + + return result; +} + +static boolean +trace_drm_shared_handle_from_texture(struct drm_api *_api, + struct pipe_screen *_screen, + struct pipe_texture *_texture, + unsigned *stride, + unsigned *handle) +{ + struct trace_screen *tr_screen = trace_screen(_screen); + struct trace_texture *tr_texture = trace_texture(_texture); + struct trace_drm_api *tr_api = trace_drm_api(_api); + struct pipe_screen *screen = tr_screen->screen; + struct pipe_texture *texture = tr_texture->texture; + struct drm_api *api = tr_api->api; + + /* TODO trace call */ + + return api->shared_handle_from_texture(api, screen, texture, stride, handle); +} + +static boolean +trace_drm_local_handle_from_texture(struct drm_api *_api, + struct pipe_screen *_screen, + struct pipe_texture *_texture, + unsigned *stride, + unsigned *handle) +{ + struct trace_screen *tr_screen = trace_screen(_screen); + struct trace_texture *tr_texture = trace_texture(_texture); + struct trace_drm_api *tr_api = trace_drm_api(_api); + struct pipe_screen *screen = tr_screen->screen; + struct pipe_texture *texture = tr_texture->texture; + struct drm_api *api = tr_api->api; + + /* TODO trace call */ + + return api->local_handle_from_texture(api, screen, texture, stride, 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.texture_from_shared_handle = trace_drm_texture_from_shared_handle; + tr_api->base.shared_handle_from_texture = trace_drm_shared_handle_from_texture; + tr_api->base.local_handle_from_texture = trace_drm_local_handle_from_texture; + 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.c b/src/gallium/drivers/trace/tr_dump.c new file mode 100644 index 0000000000..7e2ccbcfdc --- /dev/null +++ b/src/gallium/drivers/trace/tr_dump.c @@ -0,0 +1,627 @@ +/************************************************************************** + * + * 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. + * + **************************************************************************/ + + +/** + * @file + * Trace dumping functions. + * + * For now we just use standard XML for dumping the trace calls, as this is + * simple to write, parse, and visually inspect, but the actual representation + * is abstracted out of this file, so that we can switch to a binary + * representation if/when it becomes justified. + * + * @author Jose Fonseca <jrfonseca@tungstengraphics.com> + */ + +#include "pipe/p_config.h" + +#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) +#include <stdlib.h> +#endif + +#include "pipe/p_compiler.h" +#include "pipe/p_thread.h" +#include "util/u_debug.h" +#include "util/u_memory.h" +#include "util/u_string.h" +#include "util/u_stream.h" + +#include "tr_dump.h" +#include "tr_screen.h" +#include "tr_texture.h" +#include "tr_buffer.h" + + +static struct util_stream *stream = NULL; +static unsigned refcount = 0; +static pipe_mutex call_mutex; +static long unsigned call_no = 0; +static boolean dumping = FALSE; +static boolean initialized = FALSE; + + +static INLINE void +trace_dump_write(const char *buf, size_t size) +{ + if(stream) + util_stream_write(stream, buf, size); +} + + +static INLINE void +trace_dump_writes(const char *s) +{ + trace_dump_write(s, strlen(s)); +} + + +static INLINE void +trace_dump_writef(const char *format, ...) +{ + static char buf[1024]; + unsigned len; + va_list ap; + va_start(ap, format); + len = util_vsnprintf(buf, sizeof(buf), format, ap); + va_end(ap); + trace_dump_write(buf, len); +} + + +static INLINE void +trace_dump_escape(const char *str) +{ + const unsigned char *p = (const unsigned char *)str; + unsigned char c; + while((c = *p++) != 0) { + if(c == '<') + trace_dump_writes("<"); + else if(c == '>') + trace_dump_writes(">"); + else if(c == '&') + trace_dump_writes("&"); + else if(c == '\'') + trace_dump_writes("'"); + else if(c == '\"') + trace_dump_writes("""); + else if(c >= 0x20 && c <= 0x7e) + trace_dump_writef("%c", c); + else + trace_dump_writef("&#%u;", c); + } +} + + +static INLINE void +trace_dump_indent(unsigned level) +{ + unsigned i; + for(i = 0; i < level; ++i) + trace_dump_writes("\t"); +} + + +static INLINE void +trace_dump_newline(void) +{ + trace_dump_writes("\n"); +} + + +static INLINE void +trace_dump_tag(const char *name) +{ + trace_dump_writes("<"); + trace_dump_writes(name); + trace_dump_writes("/>"); +} + + +static INLINE void +trace_dump_tag_begin(const char *name) +{ + trace_dump_writes("<"); + trace_dump_writes(name); + trace_dump_writes(">"); +} + +static INLINE void +trace_dump_tag_begin1(const char *name, + const char *attr1, const char *value1) +{ + trace_dump_writes("<"); + trace_dump_writes(name); + trace_dump_writes(" "); + trace_dump_writes(attr1); + trace_dump_writes("='"); + trace_dump_escape(value1); + trace_dump_writes("'>"); +} + + +static INLINE void +trace_dump_tag_begin2(const char *name, + const char *attr1, const char *value1, + const char *attr2, const char *value2) +{ + trace_dump_writes("<"); + trace_dump_writes(name); + trace_dump_writes(" "); + trace_dump_writes(attr1); + trace_dump_writes("=\'"); + trace_dump_escape(value1); + trace_dump_writes("\' "); + trace_dump_writes(attr2); + trace_dump_writes("=\'"); + trace_dump_escape(value2); + trace_dump_writes("\'>"); +} + + +static INLINE void +trace_dump_tag_begin3(const char *name, + const char *attr1, const char *value1, + const char *attr2, const char *value2, + const char *attr3, const char *value3) +{ + trace_dump_writes("<"); + trace_dump_writes(name); + trace_dump_writes(" "); + trace_dump_writes(attr1); + trace_dump_writes("=\'"); + trace_dump_escape(value1); + trace_dump_writes("\' "); + trace_dump_writes(attr2); + trace_dump_writes("=\'"); + trace_dump_escape(value2); + trace_dump_writes("\' "); + trace_dump_writes(attr3); + trace_dump_writes("=\'"); + trace_dump_escape(value3); + trace_dump_writes("\'>"); +} + + +static INLINE void +trace_dump_tag_end(const char *name) +{ + trace_dump_writes("</"); + trace_dump_writes(name); + trace_dump_writes(">"); +} + +static void +trace_dump_trace_close(void) +{ + if(stream) { + trace_dump_writes("</trace>\n"); + util_stream_close(stream); + stream = NULL; + refcount = 0; + call_no = 0; + pipe_mutex_destroy(call_mutex); + } +} + +void trace_dump_init() +{ + if (initialized) + return; + + pipe_mutex_init(call_mutex); + dumping = FALSE; + initialized = TRUE; +} + +boolean trace_dump_trace_begin() +{ + const char *filename; + + assert(initialized); + + filename = debug_get_option("GALLIUM_TRACE", NULL); + if(!filename) + return FALSE; + + if(!stream) { + + stream = util_stream_create(filename, 0); + if(!stream) + return FALSE; + + trace_dump_writes("<?xml version='1.0' encoding='UTF-8'?>\n"); + trace_dump_writes("<?xml-stylesheet type='text/xsl' href='trace.xsl'?>\n"); + trace_dump_writes("<trace version='0.1'>\n"); + +#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) + /* Linux applications rarely cleanup GL / Gallium resources so catch + * application exit here */ + atexit(trace_dump_trace_close); +#endif + } + + ++refcount; + + return TRUE; +} + +boolean trace_dump_trace_enabled(void) +{ + return stream ? TRUE : FALSE; +} + +void trace_dump_trace_end(void) +{ + if(stream) + if(!--refcount) + trace_dump_trace_close(); +} + +/* + * Call lock + */ + +void trace_dump_call_lock(void) +{ + pipe_mutex_lock(call_mutex); +} + +void trace_dump_call_unlock(void) +{ + pipe_mutex_unlock(call_mutex); +} + +/* + * Dumping control + */ + +void trace_dumping_start_locked(void) +{ + dumping = TRUE; +} + +void trace_dumping_stop_locked(void) +{ + dumping = FALSE; +} + +boolean trace_dumping_enabled_locked(void) +{ + return dumping; +} + +void trace_dumping_start(void) +{ + pipe_mutex_lock(call_mutex); + trace_dumping_start_locked(); + pipe_mutex_unlock(call_mutex); +} + +void trace_dumping_stop(void) +{ + pipe_mutex_lock(call_mutex); + trace_dumping_stop_locked(); + pipe_mutex_unlock(call_mutex); +} + +boolean trace_dumping_enabled(void) +{ + boolean ret; + pipe_mutex_lock(call_mutex); + ret = trace_dumping_enabled_locked(); + pipe_mutex_unlock(call_mutex); + return ret; +} + +/* + * Dump functions + */ + +void trace_dump_call_begin_locked(const char *klass, const char *method) +{ + if (!dumping) + return; + + ++call_no; + trace_dump_indent(1); + trace_dump_writes("<call no=\'"); + trace_dump_writef("%lu", call_no); + trace_dump_writes("\' class=\'"); + trace_dump_escape(klass); + trace_dump_writes("\' method=\'"); + trace_dump_escape(method); + trace_dump_writes("\'>"); + trace_dump_newline(); +} + +void trace_dump_call_end_locked(void) +{ + if (!dumping) + return; + + trace_dump_indent(1); + trace_dump_tag_end("call"); + trace_dump_newline(); + util_stream_flush(stream); +} + +void trace_dump_call_begin(const char *klass, const char *method) +{ + pipe_mutex_lock(call_mutex); + trace_dump_call_begin_locked(klass, method); +} + +void trace_dump_call_end(void) +{ + trace_dump_call_end_locked(); + pipe_mutex_unlock(call_mutex); +} + +void trace_dump_arg_begin(const char *name) +{ + if (!dumping) + return; + + trace_dump_indent(2); + trace_dump_tag_begin1("arg", "name", name); +} + +void trace_dump_arg_end(void) +{ + if (!dumping) + return; + + trace_dump_tag_end("arg"); + trace_dump_newline(); +} + +void trace_dump_ret_begin(void) +{ + if (!dumping) + return; + + trace_dump_indent(2); + trace_dump_tag_begin("ret"); +} + +void trace_dump_ret_end(void) +{ + if (!dumping) + return; + + trace_dump_tag_end("ret"); + trace_dump_newline(); +} + +void trace_dump_bool(int value) +{ + if (!dumping) + return; + + trace_dump_writef("<bool>%c</bool>", value ? '1' : '0'); +} + +void trace_dump_int(long long int value) +{ + if (!dumping) + return; + + trace_dump_writef("<int>%lli</int>", value); +} + +void trace_dump_uint(long long unsigned value) +{ + if (!dumping) + return; + + trace_dump_writef("<uint>%llu</uint>", value); +} + +void trace_dump_float(double value) +{ + if (!dumping) + return; + + trace_dump_writef("<float>%g</float>", value); +} + +void trace_dump_bytes(const void *data, + size_t size) +{ + static const char hex_table[16] = "0123456789ABCDEF"; + const uint8_t *p = data; + size_t i; + + if (!dumping) + return; + + trace_dump_writes("<bytes>"); + for(i = 0; i < size; ++i) { + uint8_t byte = *p++; + char hex[2]; + hex[0] = hex_table[byte >> 4]; + hex[1] = hex_table[byte & 0xf]; + trace_dump_write(hex, 2); + } + trace_dump_writes("</bytes>"); +} + +void trace_dump_string(const char *str) +{ + if (!dumping) + return; + + trace_dump_writes("<string>"); + trace_dump_escape(str); + trace_dump_writes("</string>"); +} + +void trace_dump_enum(const char *value) +{ + if (!dumping) + return; + + trace_dump_writes("<enum>"); + trace_dump_escape(value); + trace_dump_writes("</enum>"); +} + +void trace_dump_array_begin(void) +{ + if (!dumping) + return; + + trace_dump_writes("<array>"); +} + +void trace_dump_array_end(void) +{ + if (!dumping) + return; + + trace_dump_writes("</array>"); +} + +void trace_dump_elem_begin(void) +{ + if (!dumping) + return; + + trace_dump_writes("<elem>"); +} + +void trace_dump_elem_end(void) +{ + if (!dumping) + return; + + trace_dump_writes("</elem>"); +} + +void trace_dump_struct_begin(const char *name) +{ + if (!dumping) + return; + + trace_dump_writef("<struct name='%s'>", name); +} + +void trace_dump_struct_end(void) +{ + if (!dumping) + return; + + trace_dump_writes("</struct>"); +} + +void trace_dump_member_begin(const char *name) +{ + if (!dumping) + return; + + trace_dump_writef("<member name='%s'>", name); +} + +void trace_dump_member_end(void) +{ + if (!dumping) + return; + + trace_dump_writes("</member>"); +} + +void trace_dump_null(void) +{ + if (!dumping) + return; + + trace_dump_writes("<null/>"); +} + +void trace_dump_ptr(const void *value) +{ + if (!dumping) + return; + + if(value) + trace_dump_writef("<ptr>0x%08lx</ptr>", (unsigned long)(uintptr_t)value); + else + trace_dump_null(); +} + +void trace_dump_buffer_ptr(struct pipe_buffer *_buffer) +{ + if (!dumping) + return; + + if (_buffer) { + struct trace_buffer *tr_buf = trace_buffer(_buffer); + trace_dump_ptr(tr_buf->buffer); + } else { + trace_dump_null(); + } +} + +void trace_dump_texture_ptr(struct pipe_texture *_texture) +{ + if (!dumping) + return; + + if (_texture) { + struct trace_texture *tr_tex = trace_texture(_texture); + trace_dump_ptr(tr_tex->texture); + } else { + trace_dump_null(); + } +} + +void trace_dump_surface_ptr(struct pipe_surface *_surface) +{ + if (!dumping) + return; + + if (_surface) { + struct trace_surface *tr_surf = trace_surface(_surface); + trace_dump_ptr(tr_surf->surface); + } else { + trace_dump_null(); + } +} + +void trace_dump_transfer_ptr(struct pipe_transfer *_transfer) +{ + if (!dumping) + return; + + if (_transfer) { + struct trace_transfer *tr_tran = trace_transfer(_transfer); + trace_dump_ptr(tr_tran->transfer); + } else { + trace_dump_null(); + } +} diff --git a/src/gallium/drivers/trace/tr_dump.h b/src/gallium/drivers/trace/tr_dump.h new file mode 100644 index 0000000000..32592bab12 --- /dev/null +++ b/src/gallium/drivers/trace/tr_dump.h @@ -0,0 +1,177 @@ +/************************************************************************** + * + * 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. + * + **************************************************************************/ + +/** + * @file + * Trace data dumping primitives. + */ + +#ifndef TR_DUMP_H +#define TR_DUMP_H + + +#include "pipe/p_compiler.h" + + +struct pipe_buffer; +struct pipe_texture; +struct pipe_surface; +struct pipe_transfer; + +/* + * Call before use. + */ +void trace_dump_init(void); + +/* + * Low level dumping controls. + * + * Opening the trace file and checking if that is opened. + */ +boolean trace_dump_trace_begin(void); +boolean trace_dump_trace_enabled(void); +void trace_dump_trace_end(void); + +/* + * Lock and unlock the call mutex. + * + * It used by the none locked version of dumping control + * and begin/end call dump functions. + * + * Begin takes the lock while end unlocks it. Use the _locked + * version to avoid locking/unlocking it. + */ +void trace_dump_call_lock(void); +void trace_dump_call_unlock(void); + +/* + * High level dumping control. + */ +void trace_dumping_start_locked(void); +void trace_dumping_stop_locked(void); +boolean trace_dumping_enabled_locked(void); +void trace_dumping_start(void); +void trace_dumping_stop(void); +boolean trace_dumping_enabled(void); + +void trace_dump_call_begin_locked(const char *klass, const char *method); +void trace_dump_call_end_locked(void); +void trace_dump_call_begin(const char *klass, const char *method); +void trace_dump_call_end(void); + +void trace_dump_arg_begin(const char *name); +void trace_dump_arg_end(void); +void trace_dump_ret_begin(void); +void trace_dump_ret_end(void); +void trace_dump_bool(int value); +void trace_dump_int(long long int value); +void trace_dump_uint(long long unsigned value); +void trace_dump_float(double value); +void trace_dump_bytes(const void *data, size_t size); +void trace_dump_string(const char *str); +void trace_dump_enum(const char *value); +void trace_dump_array_begin(void); +void trace_dump_array_end(void); +void trace_dump_elem_begin(void); +void trace_dump_elem_end(void); +void trace_dump_struct_begin(const char *name); +void trace_dump_struct_end(void); +void trace_dump_member_begin(const char *name); +void trace_dump_member_end(void); +void trace_dump_null(void); +void trace_dump_ptr(const void *value); +/* will turn a wrapped object into the real one and dump ptr */ +void trace_dump_buffer_ptr(struct pipe_buffer *_buffer); +void trace_dump_texture_ptr(struct pipe_texture *_texture); +void trace_dump_surface_ptr(struct pipe_surface *_surface); +void trace_dump_transfer_ptr(struct pipe_transfer *_transfer); + +/* + * Code saving macros. + */ + +#define trace_dump_arg(_type, _arg) \ + do { \ + trace_dump_arg_begin(#_arg); \ + trace_dump_##_type(_arg); \ + trace_dump_arg_end(); \ + } while(0) + +#define trace_dump_ret(_type, _arg) \ + do { \ + trace_dump_ret_begin(); \ + trace_dump_##_type(_arg); \ + trace_dump_ret_end(); \ + } while(0) + +#define trace_dump_array(_type, _obj, _size) \ + do { \ + size_t idx; \ + trace_dump_array_begin(); \ + for(idx = 0; idx < (_size); ++idx) { \ + trace_dump_elem_begin(); \ + trace_dump_##_type((_obj)[idx]); \ + trace_dump_elem_end(); \ + } \ + trace_dump_array_end(); \ + } while(0) + +#define trace_dump_struct_array(_type, _obj, _size) \ + do { \ + size_t idx; \ + trace_dump_array_begin(); \ + for(idx = 0; idx < (_size); ++idx) { \ + trace_dump_elem_begin(); \ + trace_dump_##_type(&(_obj)[idx]); \ + trace_dump_elem_end(); \ + } \ + trace_dump_array_end(); \ + } while(0) + +#define trace_dump_member(_type, _obj, _member) \ + do { \ + trace_dump_member_begin(#_member); \ + trace_dump_##_type((_obj)->_member); \ + trace_dump_member_end(); \ + } while(0) + +#define trace_dump_arg_array(_type, _arg, _size) \ + do { \ + trace_dump_arg_begin(#_arg); \ + trace_dump_array(_type, _arg, _size); \ + trace_dump_arg_end(); \ + } while(0) + +#define trace_dump_member_array(_type, _obj, _member) \ + do { \ + trace_dump_member_begin(#_member); \ + trace_dump_array(_type, (_obj)->_member, sizeof((_obj)->_member)/sizeof((_obj)->_member[0])); \ + trace_dump_member_end(); \ + } while(0) + + +#endif /* TR_DUMP_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 new file mode 100644 index 0000000000..26f1c04594 --- /dev/null +++ b/src/gallium/drivers/trace/tr_screen.c @@ -0,0 +1,958 @@ +/************************************************************************** + * + * 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 "util/u_memory.h" +#include "util/u_simple_list.h" + +#include "tr_buffer.h" +#include "tr_dump.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) +{ + struct trace_screen *tr_scr = trace_screen(_screen); + struct pipe_screen *screen = tr_scr->screen; + const char *result; + + trace_dump_call_begin("pipe_screen", "get_name"); + + trace_dump_arg(ptr, screen); + + result = screen->get_name(screen); + + trace_dump_ret(string, result); + + trace_dump_call_end(); + + return result; +} + + +static const char * +trace_screen_get_vendor(struct pipe_screen *_screen) +{ + struct trace_screen *tr_scr = trace_screen(_screen); + struct pipe_screen *screen = tr_scr->screen; + const char *result; + + trace_dump_call_begin("pipe_screen", "get_vendor"); + + trace_dump_arg(ptr, screen); + + result = screen->get_vendor(screen); + + trace_dump_ret(string, result); + + trace_dump_call_end(); + + return result; +} + + +static int +trace_screen_get_param(struct pipe_screen *_screen, + int param) +{ + struct trace_screen *tr_scr = trace_screen(_screen); + struct pipe_screen *screen = tr_scr->screen; + int result; + + trace_dump_call_begin("pipe_screen", "get_param"); + + trace_dump_arg(ptr, screen); + trace_dump_arg(int, param); + + result = screen->get_param(screen, param); + + trace_dump_ret(int, result); + + trace_dump_call_end(); + + return result; +} + + +static float +trace_screen_get_paramf(struct pipe_screen *_screen, + int param) +{ + struct trace_screen *tr_scr = trace_screen(_screen); + struct pipe_screen *screen = tr_scr->screen; + float result; + + trace_dump_call_begin("pipe_screen", "get_paramf"); + + trace_dump_arg(ptr, screen); + trace_dump_arg(int, param); + + result = screen->get_paramf(screen, param); + + trace_dump_ret(float, result); + + trace_dump_call_end(); + + return result; +} + + +static boolean +trace_screen_is_format_supported(struct pipe_screen *_screen, + enum pipe_format format, + enum pipe_texture_target target, + unsigned tex_usage, + unsigned geom_flags) +{ + struct trace_screen *tr_scr = trace_screen(_screen); + struct pipe_screen *screen = tr_scr->screen; + boolean result; + + trace_dump_call_begin("pipe_screen", "is_format_supported"); + + trace_dump_arg(ptr, screen); + trace_dump_arg(format, format); + trace_dump_arg(int, target); + trace_dump_arg(uint, tex_usage); + trace_dump_arg(uint, geom_flags); + + result = screen->is_format_supported(screen, format, target, tex_usage, geom_flags); + + trace_dump_ret(bool, result); + + trace_dump_call_end(); + + return result; +} + + +static void +trace_screen_flush_frontbuffer(struct pipe_screen *_screen, + struct pipe_surface *_surface, + void *context_private) +{ + struct trace_screen *tr_scr = trace_screen(_screen); + struct trace_surface *tr_surf = trace_surface(_surface); + struct pipe_screen *screen = tr_scr->screen; + struct pipe_surface *surface = tr_surf->surface; + + trace_dump_call_begin("pipe_screen", "flush_frontbuffer"); + + trace_dump_arg(ptr, screen); + trace_dump_arg(ptr, surface); + /* XXX: hide, as there is nothing we can do with this + trace_dump_arg(ptr, context_private); + */ + + screen->flush_frontbuffer(screen, surface, context_private); + + trace_dump_call_end(); +} + + +/******************************************************************** + * texture + */ + + +static struct pipe_texture * +trace_screen_texture_create(struct pipe_screen *_screen, + const struct pipe_texture *templat) +{ + struct trace_screen *tr_scr = trace_screen(_screen); + struct pipe_screen *screen = tr_scr->screen; + struct pipe_texture *result; + + trace_dump_call_begin("pipe_screen", "texture_create"); + + trace_dump_arg(ptr, screen); + trace_dump_arg(template, templat); + + result = screen->texture_create(screen, templat); + + trace_dump_ret(ptr, result); + + trace_dump_call_end(); + + result = trace_texture_create(tr_scr, result); + + return result; +} + + +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 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; + + trace_dump_call_begin("pipe_screen", "texture_blanket"); + + trace_dump_arg(ptr, screen); + trace_dump_arg(template, templat); + trace_dump_arg(uint, pitch); + trace_dump_arg(ptr, buffer); + + result = screen->texture_blanket(screen, templat, ppitch, buffer); + + trace_dump_ret(ptr, result); + + trace_dump_call_end(); + + result = trace_texture_create(tr_scr, result); + + return result; +} + + +static void +trace_screen_texture_destroy(struct pipe_texture *_texture) +{ + struct trace_screen *tr_scr = trace_screen(_texture->screen); + struct trace_texture *tr_tex = trace_texture(_texture); + struct pipe_screen *screen = tr_scr->screen; + struct pipe_texture *texture = tr_tex->texture; + + assert(texture->screen == screen); + + trace_dump_call_begin("pipe_screen", "texture_destroy"); + + trace_dump_arg(ptr, screen); + trace_dump_arg(ptr, texture); + + trace_dump_call_end(); + + trace_texture_destroy(tr_tex); +} + + +/******************************************************************** + * surface + */ + + +static struct pipe_surface * +trace_screen_get_tex_surface(struct pipe_screen *_screen, + struct pipe_texture *_texture, + unsigned face, unsigned level, + unsigned zslice, + unsigned usage) +{ + struct trace_screen *tr_scr = trace_screen(_screen); + struct trace_texture *tr_tex = trace_texture(_texture); + struct pipe_screen *screen = tr_scr->screen; + struct pipe_texture *texture = tr_tex->texture; + struct pipe_surface *result = NULL; + + assert(texture->screen == screen); + + trace_dump_call_begin("pipe_screen", "get_tex_surface"); + + trace_dump_arg(ptr, screen); + trace_dump_arg(ptr, texture); + trace_dump_arg(uint, face); + trace_dump_arg(uint, level); + trace_dump_arg(uint, zslice); + trace_dump_arg(uint, usage); + + result = screen->get_tex_surface(screen, texture, face, level, zslice, usage); + + trace_dump_ret(ptr, result); + + trace_dump_call_end(); + + result = trace_surface_create(tr_tex, result); + + return result; +} + + +static void +trace_screen_tex_surface_destroy(struct pipe_surface *_surface) +{ + struct trace_screen *tr_scr = trace_screen(_surface->texture->screen); + struct trace_surface *tr_surf = trace_surface(_surface); + struct pipe_screen *screen = tr_scr->screen; + struct pipe_surface *surface = tr_surf->surface; + + trace_dump_call_begin("pipe_screen", "tex_surface_destroy"); + + trace_dump_arg(ptr, screen); + trace_dump_arg(ptr, surface); + + trace_dump_call_end(); + + trace_surface_destroy(tr_surf); +} + + +/******************************************************************** + * transfer + */ + + +static struct pipe_transfer * +trace_screen_get_tex_transfer(struct pipe_screen *_screen, + struct pipe_texture *_texture, + unsigned face, unsigned level, + unsigned zslice, + enum pipe_transfer_usage usage, + unsigned x, unsigned y, unsigned w, unsigned h) +{ + struct trace_screen *tr_scr = trace_screen(_screen); + struct trace_texture *tr_tex = trace_texture(_texture); + struct pipe_screen *screen = tr_scr->screen; + struct pipe_texture *texture = tr_tex->texture; + struct pipe_transfer *result = NULL; + + assert(texture->screen == screen); + + trace_dump_call_begin("pipe_screen", "get_tex_transfer"); + + trace_dump_arg(ptr, screen); + trace_dump_arg(ptr, texture); + trace_dump_arg(uint, face); + trace_dump_arg(uint, level); + trace_dump_arg(uint, zslice); + trace_dump_arg(uint, usage); + + trace_dump_arg(uint, x); + trace_dump_arg(uint, y); + trace_dump_arg(uint, w); + trace_dump_arg(uint, h); + + result = screen->get_tex_transfer(screen, texture, face, level, zslice, usage, + x, y, w, h); + + trace_dump_ret(ptr, result); + + trace_dump_call_end(); + + result = trace_transfer_create(tr_tex, result); + + return result; +} + + +static void +trace_screen_tex_transfer_destroy(struct pipe_transfer *_transfer) +{ + struct trace_screen *tr_scr = trace_screen(_transfer->texture->screen); + struct trace_transfer *tr_trans = trace_transfer(_transfer); + struct pipe_screen *screen = tr_scr->screen; + struct pipe_transfer *transfer = tr_trans->transfer; + + trace_dump_call_begin("pipe_screen", "tex_transfer_destroy"); + + trace_dump_arg(ptr, screen); + trace_dump_arg(ptr, transfer); + + trace_dump_call_end(); + + trace_transfer_destroy(tr_trans); +} + + +static void * +trace_screen_transfer_map(struct pipe_screen *_screen, + struct pipe_transfer *_transfer) +{ + struct trace_screen *tr_scr = trace_screen(_screen); + struct trace_transfer *tr_trans = trace_transfer(_transfer); + struct pipe_screen *screen = tr_scr->screen; + struct pipe_transfer *transfer = tr_trans->transfer; + void *map; + + map = screen->transfer_map(screen, transfer); + if(map) { + if(transfer->usage != PIPE_TRANSFER_READ) { + assert(!tr_trans->map); + tr_trans->map = map; + } + } + + return map; +} + + +static void +trace_screen_transfer_unmap(struct pipe_screen *_screen, + struct pipe_transfer *_transfer) +{ + struct trace_screen *tr_scr = trace_screen(_screen); + struct trace_transfer *tr_trans = trace_transfer(_transfer); + struct pipe_screen *screen = tr_scr->screen; + struct pipe_transfer *transfer = tr_trans->transfer; + + if(tr_trans->map) { + size_t size = transfer->nblocksy * transfer->stride; + + trace_dump_call_begin("pipe_screen", "transfer_write"); + + trace_dump_arg(ptr, screen); + + trace_dump_arg(ptr, transfer); + + trace_dump_arg_begin("stride"); + trace_dump_uint(transfer->stride); + trace_dump_arg_end(); + + trace_dump_arg_begin("data"); + trace_dump_bytes(tr_trans->map, size); + trace_dump_arg_end(); + + trace_dump_arg_begin("size"); + trace_dump_uint(size); + trace_dump_arg_end(); + + trace_dump_call_end(); + + tr_trans->map = NULL; + } + + screen->transfer_unmap(screen, transfer); +} + + +/******************************************************************** + * buffer + */ + + +static struct pipe_buffer * +trace_screen_surface_buffer_create(struct pipe_screen *_screen, + unsigned width, unsigned height, + enum pipe_format format, + unsigned usage, + unsigned tex_usage, + unsigned *pstride) +{ + struct trace_screen *tr_scr = trace_screen(_screen); + struct pipe_screen *screen = tr_scr->screen; + unsigned stride; + struct pipe_buffer *result; + + trace_dump_call_begin("pipe_screen", "surface_buffer_create"); + + trace_dump_arg(ptr, screen); + trace_dump_arg(uint, width); + trace_dump_arg(uint, height); + trace_dump_arg(format, format); + trace_dump_arg(uint, usage); + trace_dump_arg(uint, tex_usage); + + result = screen->surface_buffer_create(screen, + width, height, + format, + usage, + tex_usage, + pstride); + + stride = *pstride; + + trace_dump_arg(uint, stride); + + trace_dump_ret(ptr, result); + + trace_dump_call_end(); + + return trace_buffer_create(tr_scr, result); +} + + +static struct pipe_buffer * +trace_screen_buffer_create(struct pipe_screen *_screen, + unsigned alignment, + unsigned usage, + unsigned size) +{ + struct trace_screen *tr_scr = trace_screen(_screen); + struct pipe_screen *screen = tr_scr->screen; + struct pipe_buffer *result; + + trace_dump_call_begin("pipe_screen", "buffer_create"); + + trace_dump_arg(ptr, screen); + trace_dump_arg(uint, alignment); + trace_dump_arg(uint, usage); + trace_dump_arg(uint, size); + + result = screen->buffer_create(screen, alignment, usage, size); + + trace_dump_ret(ptr, result); + + trace_dump_call_end(); + + /* Zero the buffer to avoid dumping uninitialized memory */ + if(result->usage & PIPE_BUFFER_USAGE_CPU_WRITE) { + void *map; + map = pipe_buffer_map(screen, result, PIPE_BUFFER_USAGE_CPU_WRITE); + if(map) { + memset(map, 0, result->size); + screen->buffer_unmap(screen, result); + } + } + + return trace_buffer_create(tr_scr, result); +} + + +static struct pipe_buffer * +trace_screen_user_buffer_create(struct pipe_screen *_screen, + void *data, + unsigned size) +{ + struct trace_screen *tr_scr = trace_screen(_screen); + struct pipe_screen *screen = tr_scr->screen; + struct pipe_buffer *result; + + trace_dump_call_begin("pipe_screen", "user_buffer_create"); + + trace_dump_arg(ptr, screen); + trace_dump_arg_begin("data"); + trace_dump_bytes(data, size); + trace_dump_arg_end(); + trace_dump_arg(uint, size); + + result = screen->user_buffer_create(screen, data, size); + + trace_dump_ret(ptr, result); + + trace_dump_call_end(); + + if(result) { + assert(!(result->usage & TRACE_BUFFER_USAGE_USER)); + result->usage |= TRACE_BUFFER_USAGE_USER; + } + + return trace_buffer_create(tr_scr, result); +} + + +/** + * This function is used to track if data has been changed on a user buffer + * without map/unmap being called. + */ +void +trace_screen_user_buffer_update(struct pipe_screen *_screen, + struct pipe_buffer *_buffer) +{ +#if 0 + struct trace_screen *tr_scr = trace_screen(_screen); + struct pipe_screen *screen = tr_scr->screen; + const void *map; + + if(buffer && buffer->usage & TRACE_BUFFER_USAGE_USER) { + map = screen->buffer_map(screen, buffer, PIPE_BUFFER_USAGE_CPU_READ); + if(map) { + trace_dump_call_begin("pipe_winsys", "buffer_write"); + + trace_dump_arg(ptr, screen); + + trace_dump_arg(ptr, buffer); + + trace_dump_arg_begin("data"); + trace_dump_bytes(map, buffer->size); + trace_dump_arg_end(); + + trace_dump_arg_begin("size"); + trace_dump_uint(buffer->size); + trace_dump_arg_end(); + + trace_dump_call_end(); + + screen->buffer_unmap(screen, buffer); + } + } +#endif +} + + +static void * +trace_screen_buffer_map(struct pipe_screen *_screen, + struct pipe_buffer *_buffer, + unsigned usage) +{ + 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; + void *map; + + assert(screen->buffer_map); + map = screen->buffer_map(screen, buffer, usage); + if(map) { + if(usage & PIPE_BUFFER_USAGE_CPU_WRITE) { + tr_buf->map = map; + } + } + + return map; +} + + +static void * +trace_screen_buffer_map_range(struct pipe_screen *_screen, + struct pipe_buffer *_buffer, + unsigned offset, + unsigned length, + unsigned usage) +{ + 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; + void *map; + + assert(screen->buffer_map_range); + map = screen->buffer_map_range(screen, buffer, offset, length, usage); + if(map) { + if(usage & PIPE_BUFFER_USAGE_CPU_WRITE) { + tr_buf->map = map; + } + } + + return map; +} + + +static void +buffer_write(struct pipe_screen *screen, + struct pipe_buffer *buffer, + unsigned offset, + const char *map, + unsigned size) +{ + assert(map); + + trace_dump_call_begin("pipe_screen", "buffer_write"); + + trace_dump_arg(ptr, screen); + + trace_dump_arg(ptr, buffer); + + trace_dump_arg(uint, offset); + + trace_dump_arg_begin("data"); + trace_dump_bytes(map + offset, size); + trace_dump_arg_end(); + + trace_dump_arg(uint, size); + + trace_dump_call_end(); + +} + + +static void +trace_screen_buffer_flush_mapped_range(struct pipe_screen *_screen, + struct pipe_buffer *_buffer, + unsigned offset, + unsigned length) +{ + 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; + + assert(tr_buf->map); + buffer_write(screen, buffer, offset, tr_buf->map, length); + tr_buf->range_flushed = TRUE; + screen->buffer_flush_mapped_range(screen, buffer, offset, length); +} + + +static void +trace_screen_buffer_unmap(struct pipe_screen *_screen, + 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; + + if (tr_buf->map && !tr_buf->range_flushed) + buffer_write(screen, buffer, 0, tr_buf->map, buffer->size); + tr_buf->map = NULL; + tr_buf->range_flushed = FALSE; + screen->buffer_unmap(screen, buffer); +} + + +static void +trace_screen_buffer_destroy(struct pipe_buffer *_buffer) +{ + struct trace_screen *tr_scr = trace_screen(_buffer->screen); + struct trace_buffer *tr_buf = trace_buffer(_buffer); + struct pipe_screen *screen = tr_scr->screen; + struct pipe_buffer *buffer = tr_buf->buffer; + + trace_dump_call_begin("pipe_screen", "buffer_destroy"); + + trace_dump_arg(ptr, screen); + trace_dump_arg(ptr, buffer); + + trace_dump_call_end(); + + trace_buffer_destroy(tr_scr, _buffer); +} + + +/******************************************************************** + * fence + */ + + +static void +trace_screen_fence_reference(struct pipe_screen *_screen, + struct pipe_fence_handle **pdst, + struct pipe_fence_handle *src) +{ + struct trace_screen *tr_scr = trace_screen(_screen); + struct pipe_screen *screen = tr_scr->screen; + struct pipe_fence_handle *dst; + + assert(pdst); + dst = *pdst; + + trace_dump_call_begin("pipe_screen", "fence_reference"); + + trace_dump_arg(ptr, screen); + trace_dump_arg(ptr, dst); + trace_dump_arg(ptr, src); + + screen->fence_reference(screen, pdst, src); + + trace_dump_call_end(); +} + + +static int +trace_screen_fence_signalled(struct pipe_screen *_screen, + struct pipe_fence_handle *fence, + unsigned flags) +{ + struct trace_screen *tr_scr = trace_screen(_screen); + struct pipe_screen *screen = tr_scr->screen; + int result; + + trace_dump_call_begin("pipe_screen", "fence_signalled"); + + trace_dump_arg(ptr, screen); + trace_dump_arg(ptr, fence); + trace_dump_arg(uint, flags); + + result = screen->fence_signalled(screen, fence, flags); + + trace_dump_ret(int, result); + + trace_dump_call_end(); + + return result; +} + + +static int +trace_screen_fence_finish(struct pipe_screen *_screen, + struct pipe_fence_handle *fence, + unsigned flags) +{ + struct trace_screen *tr_scr = trace_screen(_screen); + struct pipe_screen *screen = tr_scr->screen; + int result; + + trace_dump_call_begin("pipe_screen", "fence_finish"); + + trace_dump_arg(ptr, screen); + trace_dump_arg(ptr, fence); + trace_dump_arg(uint, flags); + + result = screen->fence_finish(screen, fence, flags); + + trace_dump_ret(int, result); + + trace_dump_call_end(); + + return result; +} + + +/******************************************************************** + * screen + */ + +static void +trace_screen_destroy(struct pipe_screen *_screen) +{ + struct trace_screen *tr_scr = trace_screen(_screen); + struct pipe_screen *screen = tr_scr->screen; + + trace_dump_call_begin("pipe_screen", "destroy"); + trace_dump_arg(ptr, 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) +{ + struct trace_screen *tr_scr; + struct pipe_winsys *winsys; + + if(!screen) + goto error1; + + if (!trace_enabled()) + goto error1; + + trace_dump_call_begin("", "pipe_screen_create"); + + tr_scr = CALLOC_STRUCT(trace_screen); + if(!tr_scr) + goto error2; + +#if 0 + winsys = trace_winsys_create(screen->winsys); + if(!winsys) + goto error3; +#else + winsys = screen->winsys; +#endif + pipe_mutex_init(tr_scr->list_mutex); + make_empty_list(&tr_scr->buffers); + make_empty_list(&tr_scr->contexts); + make_empty_list(&tr_scr->textures); + make_empty_list(&tr_scr->surfaces); + make_empty_list(&tr_scr->transfers); + + tr_scr->base.winsys = winsys; + tr_scr->base.destroy = trace_screen_destroy; + tr_scr->base.get_name = trace_screen_get_name; + tr_scr->base.get_vendor = trace_screen_get_vendor; + tr_scr->base.get_param = trace_screen_get_param; + tr_scr->base.get_paramf = trace_screen_get_paramf; + tr_scr->base.is_format_supported = trace_screen_is_format_supported; + tr_scr->base.texture_create = trace_screen_texture_create; + tr_scr->base.texture_blanket = trace_screen_texture_blanket; + tr_scr->base.texture_destroy = trace_screen_texture_destroy; + tr_scr->base.get_tex_surface = trace_screen_get_tex_surface; + tr_scr->base.tex_surface_destroy = trace_screen_tex_surface_destroy; + tr_scr->base.get_tex_transfer = trace_screen_get_tex_transfer; + tr_scr->base.tex_transfer_destroy = trace_screen_tex_transfer_destroy; + tr_scr->base.transfer_map = trace_screen_transfer_map; + tr_scr->base.transfer_unmap = trace_screen_transfer_unmap; + tr_scr->base.buffer_create = trace_screen_buffer_create; + tr_scr->base.user_buffer_create = trace_screen_user_buffer_create; + tr_scr->base.surface_buffer_create = trace_screen_surface_buffer_create; + if (screen->buffer_map) + tr_scr->base.buffer_map = trace_screen_buffer_map; + if (screen->buffer_map_range) + tr_scr->base.buffer_map_range = trace_screen_buffer_map_range; + if (screen->buffer_flush_mapped_range) + tr_scr->base.buffer_flush_mapped_range = trace_screen_buffer_flush_mapped_range; + if (screen->buffer_unmap) + tr_scr->base.buffer_unmap = trace_screen_buffer_unmap; + tr_scr->base.buffer_destroy = trace_screen_buffer_destroy; + tr_scr->base.fence_reference = trace_screen_fence_reference; + tr_scr->base.fence_signalled = trace_screen_fence_signalled; + tr_scr->base.fence_finish = trace_screen_fence_finish; + tr_scr->base.flush_frontbuffer = trace_screen_flush_frontbuffer; + tr_scr->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 +error3: + FREE(tr_scr); +#endif +error2: + trace_dump_ret(ptr, screen); + trace_dump_call_end(); + trace_dump_trace_end(); +error1: + return screen; +} + + +struct trace_screen * +trace_screen(struct pipe_screen *screen) +{ + assert(screen); + assert(screen->destroy == trace_screen_destroy); + return (struct trace_screen *)screen; +} diff --git a/src/gallium/drivers/trace/tr_screen.h b/src/gallium/drivers/trace/tr_screen.h new file mode 100644 index 0000000000..dba8cd7c65 --- /dev/null +++ b/src/gallium/drivers/trace/tr_screen.h @@ -0,0 +1,130 @@ +/************************************************************************** + * + * 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_SCREEN_H_ +#define TR_SCREEN_H_ + + +#include "pipe/p_screen.h" +#include "pipe/p_thread.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +struct tr_list { + struct tr_list *next; + struct tr_list *prev; +}; + +/** + * It often happens that new data is written directly to the user buffers + * without mapping/unmapping. This flag marks user buffers, so that their + * contents can be dumpped before being used by the pipe context. + */ +#define TRACE_BUFFER_USAGE_USER (1 << 31) + + +struct trace_screen +{ + struct pipe_screen base; + + struct pipe_screen *screen; + + /* remote debugger */ + struct trace_rbug *rbug; + + pipe_mutex list_mutex; + int num_buffers; + int num_contexts; + int num_textures; + int num_surfaces; + int num_transfers; + struct tr_list buffers; + struct tr_list contexts; + struct tr_list textures; + struct tr_list surfaces; + struct tr_list transfers; +}; + + +/* + * 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); + +#define trace_screen_add_to_list(tr_scr, name, obj) \ + do { \ + pipe_mutex_lock(tr_scr->list_mutex); \ + insert_at_head(&tr_scr->name, &obj->list); \ + tr_scr->num_##name++; \ + pipe_mutex_unlock(tr_scr->list_mutex); \ + } while (0) + +#define trace_screen_remove_from_list(tr_scr, name, obj) \ + do { \ + pipe_mutex_lock(tr_scr->list_mutex); \ + remove_from_list(&obj->list); \ + tr_scr->num_##name--; \ + pipe_mutex_unlock(tr_scr->list_mutex); \ + } while (0) + + +#ifdef __cplusplus +} +#endif + +#endif /* TR_SCREEN_H_ */ diff --git a/src/gallium/drivers/trace/tr_state.c b/src/gallium/drivers/trace/tr_state.c new file mode 100644 index 0000000000..d8c11640bf --- /dev/null +++ b/src/gallium/drivers/trace/tr_state.c @@ -0,0 +1,66 @@ +/* + * 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 + * 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 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 "tr_state.h" + +#include "util/u_memory.h" +#include "util/u_simple_list.h" + +#include "tgsi/tgsi_parse.h" + +struct trace_shader * trace_shader_create(struct trace_context *tr_ctx, + const struct pipe_shader_state *state, + void *result, + enum trace_shader_type type) +{ + struct trace_shader *tr_shdr = CALLOC_STRUCT(trace_shader); + + tr_shdr->state = result; + tr_shdr->type = type; + tr_shdr->tokens = tgsi_dup_tokens(state->tokens); + + /* works on context as well */ + trace_screen_add_to_list(tr_ctx, shaders, tr_shdr); + + return tr_shdr; +} + +void trace_shader_destroy(struct trace_context *tr_ctx, + struct trace_shader *tr_shdr) +{ + trace_screen_remove_from_list(tr_ctx, shaders, tr_shdr); + + 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); + } + + 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 new file mode 100644 index 0000000000..1c16042ee5 --- /dev/null +++ b/src/gallium/drivers/trace/tr_state.h @@ -0,0 +1,68 @@ +/* + * 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 + * 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 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. + */ + +#ifndef TR_STATE_H_ +#define TR_STATE_H_ + +#include "tr_context.h" + +struct tgsi_token; + +enum trace_shader_type { + TRACE_SHADER_FRAGMENT = 0, + TRACE_SHADER_VERTEX = 1, + TRACE_SHADER_GEOMETRY = 2, +}; + +struct trace_shader +{ + struct tr_list list; + + enum trace_shader_type type; + + void *state; + void *replaced; + + struct tgsi_token *tokens; + struct tgsi_token *replaced_tokens; + + boolean disabled; +}; + + +static INLINE struct trace_shader * +trace_shader(void *state) +{ + return (struct trace_shader *)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 diff --git a/src/gallium/drivers/trace/tr_texture.c b/src/gallium/drivers/trace/tr_texture.c new file mode 100644 index 0000000000..1f25fe38d4 --- /dev/null +++ b/src/gallium/drivers/trace/tr_texture.c @@ -0,0 +1,170 @@ +/************************************************************************** + * + * 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 "util/u_hash_table.h" +#include "util/u_memory.h" +#include "util/u_simple_list.h" + +#include "tr_screen.h" +#include "tr_texture.h" + + +struct pipe_texture * +trace_texture_create(struct trace_screen *tr_scr, + struct pipe_texture *texture) +{ + struct trace_texture *tr_tex; + + if(!texture) + goto error; + + assert(texture->screen == tr_scr->screen); + + tr_tex = CALLOC_STRUCT(trace_texture); + if(!tr_tex) + goto error; + + memcpy(&tr_tex->base, texture, sizeof(struct pipe_texture)); + + pipe_reference_init(&tr_tex->base.reference, 1); + tr_tex->base.screen = &tr_scr->base; + tr_tex->texture = texture; + + trace_screen_add_to_list(tr_scr, textures, tr_tex); + + return &tr_tex->base; + +error: + pipe_texture_reference(&texture, NULL); + return NULL; +} + + +void +trace_texture_destroy(struct trace_texture *tr_tex) +{ + struct trace_screen *tr_scr = trace_screen(tr_tex->base.screen); + + trace_screen_remove_from_list(tr_scr, textures, tr_tex); + + pipe_texture_reference(&tr_tex->texture, NULL); + FREE(tr_tex); +} + + +struct pipe_surface * +trace_surface_create(struct trace_texture *tr_tex, + struct pipe_surface *surface) +{ + struct trace_screen *tr_scr = trace_screen(tr_tex->base.screen); + struct trace_surface *tr_surf; + + if(!surface) + goto error; + + assert(surface->texture == tr_tex->texture); + + tr_surf = CALLOC_STRUCT(trace_surface); + if(!tr_surf) + goto error; + + memcpy(&tr_surf->base, surface, sizeof(struct pipe_surface)); + + pipe_reference_init(&tr_surf->base.reference, 1); + tr_surf->base.texture = NULL; + pipe_texture_reference(&tr_surf->base.texture, &tr_tex->base); + tr_surf->surface = surface; + + trace_screen_add_to_list(tr_scr, surfaces, tr_surf); + + return &tr_surf->base; + +error: + pipe_surface_reference(&surface, NULL); + return NULL; +} + + +void +trace_surface_destroy(struct trace_surface *tr_surf) +{ + struct trace_screen *tr_scr = trace_screen(tr_surf->base.texture->screen); + + trace_screen_remove_from_list(tr_scr, surfaces, tr_surf); + + pipe_texture_reference(&tr_surf->base.texture, NULL); + pipe_surface_reference(&tr_surf->surface, NULL); + FREE(tr_surf); +} + + +struct pipe_transfer * +trace_transfer_create(struct trace_texture *tr_tex, + struct pipe_transfer *transfer) +{ + struct trace_screen *tr_scr = trace_screen(tr_tex->base.screen); + struct trace_transfer *tr_trans; + + if(!transfer) + goto error; + + assert(transfer->texture == tr_tex->texture); + + tr_trans = CALLOC_STRUCT(trace_transfer); + if(!tr_trans) + goto error; + + memcpy(&tr_trans->base, transfer, sizeof(struct pipe_transfer)); + + tr_trans->base.texture = NULL; + pipe_texture_reference(&tr_trans->base.texture, &tr_tex->base); + tr_trans->transfer = transfer; + assert(tr_trans->base.texture == &tr_tex->base); + + trace_screen_add_to_list(tr_scr, transfers, tr_trans); + + return &tr_trans->base; + +error: + transfer->texture->screen->tex_transfer_destroy(transfer); + return NULL; +} + + +void +trace_transfer_destroy(struct trace_transfer *tr_trans) +{ + struct trace_screen *tr_scr = trace_screen(tr_trans->base.texture->screen); + struct pipe_screen *screen = tr_trans->transfer->texture->screen; + + trace_screen_remove_from_list(tr_scr, transfers, tr_trans); + + pipe_texture_reference(&tr_trans->base.texture, NULL); + screen->tex_transfer_destroy(tr_trans->transfer); + FREE(tr_trans); +} + diff --git a/src/gallium/drivers/trace/tr_texture.h b/src/gallium/drivers/trace/tr_texture.h new file mode 100644 index 0000000000..395e523e73 --- /dev/null +++ b/src/gallium/drivers/trace/tr_texture.h @@ -0,0 +1,122 @@ +/************************************************************************** + * + * 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_TEXTURE_H_ +#define TR_TEXTURE_H_ + + +#include "pipe/p_compiler.h" +#include "pipe/p_state.h" + +#include "tr_screen.h" + + +struct trace_texture +{ + struct pipe_texture base; + + struct pipe_texture *texture; + + struct tr_list list; +}; + + +struct trace_surface +{ + struct pipe_surface base; + + struct pipe_surface *surface; + + struct tr_list list; +}; + + +struct trace_transfer +{ + struct pipe_transfer base; + + struct pipe_transfer *transfer; + + struct tr_list list; + + void *map; +}; + + +static INLINE struct trace_texture * +trace_texture(struct pipe_texture *texture) +{ + if(!texture) + return NULL; + (void)trace_screen(texture->screen); + return (struct trace_texture *)texture; +} + + +static INLINE struct trace_surface * +trace_surface(struct pipe_surface *surface) +{ + if(!surface) + return NULL; + (void)trace_texture(surface->texture); + return (struct trace_surface *)surface; +} + + +static INLINE struct trace_transfer * +trace_transfer(struct pipe_transfer *transfer) +{ + if(!transfer) + return NULL; + (void)trace_texture(transfer->texture); + return (struct trace_transfer *)transfer; +} + + +struct pipe_texture * +trace_texture_create(struct trace_screen *tr_scr, + struct pipe_texture *texture); + +void +trace_texture_destroy(struct trace_texture *tr_tex); + +struct pipe_surface * +trace_surface_create(struct trace_texture *tr_tex, + struct pipe_surface *surface); + +void +trace_surface_destroy(struct trace_surface *tr_surf); + +struct pipe_transfer * +trace_transfer_create(struct trace_texture *tr_tex, + struct pipe_transfer *transfer); + +void +trace_transfer_destroy(struct trace_transfer *tr_trans); + + +#endif /* TR_TEXTURE_H_ */ diff --git a/src/gallium/drivers/trace/trace.xsl b/src/gallium/drivers/trace/trace.xsl new file mode 100644 index 0000000000..7be95e0e75 --- /dev/null +++ b/src/gallium/drivers/trace/trace.xsl @@ -0,0 +1,188 @@ +<?xml version="1.0"?> + +<!-- + +Copyright 2008 Tungsten Graphics, Inc. + +This program is free software: you can redistribute it and/or modify it +under the terms of the GNU Lesser General Public License as published +by the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. + +!--> + +<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> + + <xsl:output method="html" /> + + <xsl:strip-space elements="*" /> + + <xsl:template match="/trace"> + <html> + <head> + <title>Gallium Trace</title> + </head> + <style> + body { + font-family: verdana, sans-serif; + font-size: 11px; + font-weight: normal; + text-align : left; + } + + .fun { + font-weight: bold; + } + + .var { + font-style: italic; + } + + .typ { + display: none; + } + + .lit { + color: #0000ff; + } + + .ptr { + color: #008000; + } + </style> + <body> + <ol class="calls"> + <xsl:apply-templates/> + </ol> + </body> + </html> + </xsl:template> + + <xsl:template match="call"> + <li> + <xsl:attribute name="value"> + <xsl:apply-templates select="@no"/> + </xsl:attribute> + <span class="fun"> + <xsl:value-of select="@class"/> + <xsl:text>::</xsl:text> + <xsl:value-of select="@method"/> + </span> + <xsl:text>(</xsl:text> + <xsl:apply-templates select="arg"/> + <xsl:text>)</xsl:text> + <xsl:apply-templates select="ret"/> + </li> + </xsl:template> + + <xsl:template match="arg|member"> + <xsl:apply-templates select="@name"/> + <xsl:text> = </xsl:text> + <xsl:apply-templates /> + <xsl:if test="position() != last()"> + <xsl:text>, </xsl:text> + </xsl:if> + </xsl:template> + + <xsl:template match="ret"> + <xsl:text> = </xsl:text> + <xsl:apply-templates /> + </xsl:template> + + <xsl:template match="bool|int|uint|float|enum"> + <span class="lit"> + <xsl:value-of select="text()"/> + </span> + </xsl:template> + + <xsl:template match="bytes"> + <span class="lit"> + <xsl:text>...</xsl:text> + </span> + </xsl:template> + + <xsl:template match="string"> + <span class="lit"> + <xsl:text>"</xsl:text> + <xsl:call-template name="break"> + <xsl:with-param name="text" select="text()"/> + </xsl:call-template> + <xsl:text>"</xsl:text> + </span> + </xsl:template> + + <xsl:template match="array|struct"> + <xsl:text>{</xsl:text> + <xsl:apply-templates /> + <xsl:text>}</xsl:text> + </xsl:template> + + <xsl:template match="elem"> + <xsl:apply-templates /> + <xsl:if test="position() != last()"> + <xsl:text>, </xsl:text> + </xsl:if> + </xsl:template> + + <xsl:template match="null"> + <span class="ptr"> + <xsl:text>NULL</xsl:text> + </span> + </xsl:template> + + <xsl:template match="ptr"> + <span class="ptr"> + <xsl:value-of select="text()"/> + </span> + </xsl:template> + + <xsl:template match="@name"> + <span class="var"> + <xsl:value-of select="."/> + </span> + </xsl:template> + + <xsl:template name="break"> + <xsl:param name="text" select="."/> + <xsl:choose> + <xsl:when test="contains($text, '
')"> + <xsl:value-of select="substring-before($text, '
')"/> + <br/> + <xsl:call-template name="break"> + <xsl:with-param name="text" select="substring-after($text, '
')"/> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="$text"/> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <xsl:template name="replace"> + <xsl:param name="text"/> + <xsl:param name="from"/> + <xsl:param name="to"/> + <xsl:choose> + <xsl:when test="contains($text,$from)"> + <xsl:value-of select="concat(substring-before($text,$from),$to)"/> + <xsl:call-template name="replace"> + <xsl:with-param name="text" select="substring-after($text,$from)"/> + <xsl:with-param name="from" select="$from"/> + <xsl:with-param name="to" select="$to"/> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="$text"/> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + +</xsl:transform> |