diff options
Diffstat (limited to 'src/gallium/auxiliary/driver_trace')
-rw-r--r-- | src/gallium/auxiliary/driver_trace/README | 55 | ||||
-rw-r--r-- | src/gallium/auxiliary/driver_trace/tr_context.c | 1948 | ||||
-rw-r--r-- | src/gallium/auxiliary/driver_trace/tr_context.h | 77 | ||||
-rw-r--r-- | src/gallium/auxiliary/driver_trace/tr_dump.c | 599 | ||||
-rw-r--r-- | src/gallium/auxiliary/driver_trace/tr_dump.h | 190 | ||||
-rw-r--r-- | src/gallium/auxiliary/driver_trace/tr_dump_defines.h | 58 | ||||
-rw-r--r-- | src/gallium/auxiliary/driver_trace/tr_dump_state.c | 961 | ||||
-rw-r--r-- | src/gallium/auxiliary/driver_trace/tr_dump_state.h | 94 | ||||
-rw-r--r-- | src/gallium/auxiliary/driver_trace/tr_public.h | 50 | ||||
-rw-r--r-- | src/gallium/auxiliary/driver_trace/tr_screen.c | 684 | ||||
-rw-r--r-- | src/gallium/auxiliary/driver_trace/tr_screen.h | 65 | ||||
-rw-r--r-- | src/gallium/auxiliary/driver_trace/tr_texture.c | 119 | ||||
-rw-r--r-- | src/gallium/auxiliary/driver_trace/tr_texture.h | 122 | ||||
-rw-r--r-- | src/gallium/auxiliary/driver_trace/trace.xsl | 196 |
14 files changed, 5218 insertions, 0 deletions
diff --git a/src/gallium/auxiliary/driver_trace/README b/src/gallium/auxiliary/driver_trace/README new file mode 100644 index 00000000000..fbad26c4498 --- /dev/null +++ b/src/gallium/auxiliary/driver_trace/README @@ -0,0 +1,55 @@ + TRACE PIPE DRIVER + + += About = + +This directory contains a Gallium3D trace debugger pipe driver. +It can traces all incoming calls. + + += Usage = + +== Tracing == + +For tracing then do + + GALLIUM_TRACE=tri.trace 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. + +For long traces you can use the + + src/gallium/tools/trace/dump.py tri.trace | less -R + + +== Remote debugging == + +For remote debugging see: + + src/gallium/auxiliary/driver_rbug/README + + += Integrating = + +You can integrate the trace pipe driver either inside the state tracker or the +target. The procedure on both cases is the same. Let's assume you have a +pipe_screen obtained by the usual means (variable and function names are just +for illustration purposes): + + real_screen = real_screen_create(...); + +The trace screen is then created by doing + + trace_screen = trace_screen_create(real_screen); + +You can then simply use trace_screen instead of real_screen. + +You can create as many contexts you wish from trace_screen::context_create they +are automatically wrapped by trace_screen. + + +-- +Jose Fonseca <[email protected]> +Jakob Bornecrantz <[email protected]> diff --git a/src/gallium/auxiliary/driver_trace/tr_context.c b/src/gallium/auxiliary/driver_trace/tr_context.c new file mode 100644 index 00000000000..6d918d42a38 --- /dev/null +++ b/src/gallium/auxiliary/driver_trace/tr_context.c @@ -0,0 +1,1948 @@ +/************************************************************************** + * + * Copyright 2008 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 "util/u_inlines.h" +#include "util/u_memory.h" +#include "util/simple_list.h" + +#include "pipe/p_format.h" +#include "pipe/p_screen.h" + +#include "tr_dump.h" +#include "tr_dump_defines.h" +#include "tr_dump_state.h" +#include "tr_public.h" +#include "tr_screen.h" +#include "tr_texture.h" +#include "tr_context.h" + + +struct trace_query +{ + unsigned type; + + struct pipe_query *query; +}; + + +static inline struct trace_query * +trace_query(struct pipe_query *query) +{ + return (struct trace_query *)query; +} + + +static inline struct pipe_query * +trace_query_unwrap(struct pipe_query *query) +{ + if (query) { + return trace_query(query)->query; + } else { + return NULL; + } +} + + +static inline struct pipe_surface * +trace_surface_unwrap(struct trace_context *tr_ctx, + struct pipe_surface *surface) +{ + 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); + return tr_surf->surface; +} + + +static void +trace_context_draw_vbo(struct pipe_context *_pipe, + const struct pipe_draw_info *info) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct pipe_context *pipe = tr_ctx->pipe; + + trace_dump_call_begin("pipe_context", "draw_vbo"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(draw_info, info); + + trace_dump_trace_flush(); + + pipe->draw_vbo(pipe, info); + + trace_dump_call_end(); +} + + +static struct pipe_query * +trace_context_create_query(struct pipe_context *_pipe, + unsigned query_type, + unsigned index) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct pipe_context *pipe = tr_ctx->pipe; + struct pipe_query *query; + + trace_dump_call_begin("pipe_context", "create_query"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(query_type, query_type); + trace_dump_arg(int, index); + + query = pipe->create_query(pipe, query_type, index); + + trace_dump_ret(ptr, query); + + trace_dump_call_end(); + + /* Wrap query object. */ + if (query) { + struct trace_query *tr_query = CALLOC_STRUCT(trace_query); + if (tr_query) { + tr_query->type = query_type; + tr_query->query = query; + query = (struct pipe_query *)tr_query; + } else { + pipe->destroy_query(pipe, query); + query = NULL; + } + } + + return query; +} + + +static 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; + struct trace_query *tr_query = trace_query(_query); + struct pipe_query *query = tr_query->query; + + FREE(tr_query); + + 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 boolean +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; + boolean ret; + + query = trace_query_unwrap(query); + + trace_dump_call_begin("pipe_context", "begin_query"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(ptr, query); + + ret = pipe->begin_query(pipe, query); + + trace_dump_call_end(); + return ret; +} + + +static bool +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; + bool ret; + + query = trace_query_unwrap(query); + + trace_dump_call_begin("pipe_context", "end_query"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(ptr, query); + + ret = pipe->end_query(pipe, query); + + trace_dump_call_end(); + return ret; +} + + +static boolean +trace_context_get_query_result(struct pipe_context *_pipe, + struct pipe_query *_query, + boolean wait, + union pipe_query_result *result) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct pipe_context *pipe = tr_ctx->pipe; + struct trace_query *tr_query = trace_query(_query); + struct pipe_query *query = tr_query->query; + boolean ret; + + trace_dump_call_begin("pipe_context", "get_query_result"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(ptr, query); + + ret = pipe->get_query_result(pipe, query, wait, result); + + trace_dump_arg_begin("result"); + if (ret) { + trace_dump_query_result(tr_query->type, result); + } else { + trace_dump_null(); + } + trace_dump_arg_end(); + + trace_dump_ret(bool, ret); + + trace_dump_call_end(); + + return ret; +} + + +static void +trace_context_set_active_query_state(struct pipe_context *_pipe, + boolean enable) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct pipe_context *pipe = tr_ctx->pipe; + + trace_dump_call_begin("pipe_context", "set_active_query_state"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(bool, enable); + + pipe->set_active_query_state(pipe, enable); + + trace_dump_call_end(); +} + + +static 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 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 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 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 void +trace_context_bind_sampler_states(struct pipe_context *_pipe, + enum pipe_shader_type shader, + unsigned start, + unsigned num_states, + void **states) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct pipe_context *pipe = tr_ctx->pipe; + + /* remove this when we have pipe->bind_sampler_states(..., start, ...) */ + assert(start == 0); + + trace_dump_call_begin("pipe_context", "bind_sampler_states"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(uint, shader); + trace_dump_arg(uint, start); + trace_dump_arg(uint, num_states); + trace_dump_arg_array(ptr, states, num_states); + + pipe->bind_sampler_states(pipe, shader, start, num_states, states); + + trace_dump_call_end(); +} + + +static 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 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 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 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 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 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 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(); +} + + +#define TRACE_SHADER_STATE(shader_type) \ + static void * \ + trace_context_create_##shader_type##_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_" #shader_type "_state"); \ + trace_dump_arg(ptr, pipe); \ + trace_dump_arg(shader_state, state); \ + result = pipe->create_##shader_type##_state(pipe, state); \ + trace_dump_ret(ptr, result); \ + trace_dump_call_end(); \ + return result; \ + } \ + \ + static void \ + trace_context_bind_##shader_type##_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_" #shader_type "_state"); \ + trace_dump_arg(ptr, pipe); \ + trace_dump_arg(ptr, state); \ + pipe->bind_##shader_type##_state(pipe, state); \ + trace_dump_call_end(); \ + } \ + \ + static void \ + trace_context_delete_##shader_type##_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_" #shader_type "_state"); \ + trace_dump_arg(ptr, pipe); \ + trace_dump_arg(ptr, state); \ + pipe->delete_##shader_type##_state(pipe, state); \ + trace_dump_call_end(); \ + } + +TRACE_SHADER_STATE(fs) +TRACE_SHADER_STATE(vs) +TRACE_SHADER_STATE(gs) +TRACE_SHADER_STATE(tcs) +TRACE_SHADER_STATE(tes) + +#undef TRACE_SHADER_STATE + + +static inline void * +trace_context_create_compute_state(struct pipe_context *_pipe, + const struct pipe_compute_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_compute_state"); + trace_dump_arg(ptr, pipe); + trace_dump_arg(compute_state, state); + result = pipe->create_compute_state(pipe, state); + trace_dump_ret(ptr, result); + trace_dump_call_end(); + return result; +} + +static inline void +trace_context_bind_compute_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_compute_state"); + trace_dump_arg(ptr, pipe); + trace_dump_arg(ptr, state); + pipe->bind_compute_state(pipe, state); + trace_dump_call_end(); +} + +static inline void +trace_context_delete_compute_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_compute_state"); + trace_dump_arg(ptr, pipe); + trace_dump_arg(ptr, state); + pipe->delete_compute_state(pipe, state); + trace_dump_call_end(); +} + +static void * +trace_context_create_vertex_elements_state(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; + void * result; + + trace_dump_call_begin("pipe_context", "create_vertex_elements_state"); + + 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(); + + result = pipe->create_vertex_elements_state(pipe, num_elements, elements); + + trace_dump_ret(ptr, result); + + trace_dump_call_end(); + + return result; +} + + +static void +trace_context_bind_vertex_elements_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_vertex_elements_state"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(ptr, state); + + pipe->bind_vertex_elements_state(pipe, state); + + trace_dump_call_end(); +} + + +static void +trace_context_delete_vertex_elements_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_vertex_elements_state"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(ptr, state); + + pipe->delete_vertex_elements_state(pipe, state); + + trace_dump_call_end(); +} + + +static 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 void +trace_context_set_stencil_ref(struct pipe_context *_pipe, + const struct pipe_stencil_ref *state) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct pipe_context *pipe = tr_ctx->pipe; + + trace_dump_call_begin("pipe_context", "set_stencil_ref"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(stencil_ref, state); + + pipe->set_stencil_ref(pipe, state); + + trace_dump_call_end(); +} + + +static 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 void +trace_context_set_sample_mask(struct pipe_context *_pipe, + unsigned sample_mask) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct pipe_context *pipe = tr_ctx->pipe; + + trace_dump_call_begin("pipe_context", "set_sample_mask"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(uint, sample_mask); + + pipe->set_sample_mask(pipe, sample_mask); + + trace_dump_call_end(); +} + +static void +trace_context_set_constant_buffer(struct pipe_context *_pipe, + enum pipe_shader_type shader, uint index, + const struct pipe_constant_buffer *constant_buffer) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct pipe_context *pipe = tr_ctx->pipe; + + 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, constant_buffer); + + pipe->set_constant_buffer(pipe, shader, index, constant_buffer); + + trace_dump_call_end(); +} + + +static 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; + + + /* 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 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 void +trace_context_set_scissor_states(struct pipe_context *_pipe, + unsigned start_slot, + unsigned num_scissors, + const struct pipe_scissor_state *states) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct pipe_context *pipe = tr_ctx->pipe; + + trace_dump_call_begin("pipe_context", "set_scissor_states"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(uint, start_slot); + trace_dump_arg(uint, num_scissors); + trace_dump_arg(scissor_state, states); + + pipe->set_scissor_states(pipe, start_slot, num_scissors, states); + + trace_dump_call_end(); +} + + +static void +trace_context_set_viewport_states(struct pipe_context *_pipe, + unsigned start_slot, + unsigned num_viewports, + const struct pipe_viewport_state *states) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct pipe_context *pipe = tr_ctx->pipe; + + trace_dump_call_begin("pipe_context", "set_viewport_states"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(uint, start_slot); + trace_dump_arg(uint, num_viewports); + trace_dump_arg(viewport_state, states); + + pipe->set_viewport_states(pipe, start_slot, num_viewports, states); + + trace_dump_call_end(); +} + + +static struct pipe_sampler_view * +trace_context_create_sampler_view(struct pipe_context *_pipe, + struct pipe_resource *resource, + const struct pipe_sampler_view *templ) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct pipe_context *pipe = tr_ctx->pipe; + struct pipe_sampler_view *result; + struct trace_sampler_view *tr_view; + + trace_dump_call_begin("pipe_context", "create_sampler_view"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(ptr, resource); + + trace_dump_arg_begin("templ"); + trace_dump_sampler_view_template(templ, resource->target); + trace_dump_arg_end(); + + result = pipe->create_sampler_view(pipe, resource, templ); + + trace_dump_ret(ptr, result); + + trace_dump_call_end(); + + /* + * Wrap pipe_sampler_view + */ + tr_view = CALLOC_STRUCT(trace_sampler_view); + tr_view->base = *templ; + tr_view->base.reference.count = 1; + tr_view->base.texture = NULL; + pipe_resource_reference(&tr_view->base.texture, resource); + tr_view->base.context = _pipe; + tr_view->sampler_view = result; + result = &tr_view->base; + + return result; +} + + +static void +trace_context_sampler_view_destroy(struct pipe_context *_pipe, + struct pipe_sampler_view *_view) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct trace_sampler_view *tr_view = trace_sampler_view(_view); + struct pipe_context *pipe = tr_ctx->pipe; + struct pipe_sampler_view *view = tr_view->sampler_view; + + assert(_view->context == _pipe); + + trace_dump_call_begin("pipe_context", "sampler_view_destroy"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(ptr, view); + + pipe_sampler_view_reference(&tr_view->sampler_view, NULL); + + trace_dump_call_end(); + + pipe_resource_reference(&_view->texture, NULL); + FREE(_view); +} + +/******************************************************************** + * surface + */ + + +static struct pipe_surface * +trace_context_create_surface(struct pipe_context *_pipe, + struct pipe_resource *resource, + const struct pipe_surface *surf_tmpl) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct pipe_context *pipe = tr_ctx->pipe; + struct pipe_surface *result = NULL; + + trace_dump_call_begin("pipe_context", "create_surface"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(ptr, resource); + + trace_dump_arg_begin("surf_tmpl"); + trace_dump_surface_template(surf_tmpl, resource->target); + trace_dump_arg_end(); + + + result = pipe->create_surface(pipe, resource, surf_tmpl); + + trace_dump_ret(ptr, result); + + trace_dump_call_end(); + + result = trace_surf_create(tr_ctx, resource, result); + + return result; +} + + +static void +trace_context_surface_destroy(struct pipe_context *_pipe, + struct pipe_surface *_surface) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct pipe_context *pipe = tr_ctx->pipe; + struct trace_surface *tr_surf = trace_surface(_surface); + struct pipe_surface *surface = tr_surf->surface; + + trace_dump_call_begin("pipe_context", "surface_destroy"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(ptr, surface); + + trace_dump_call_end(); + + trace_surf_destroy(tr_surf); +} + + +static void +trace_context_set_sampler_views(struct pipe_context *_pipe, + enum pipe_shader_type shader, + unsigned start, + unsigned num, + struct pipe_sampler_view **views) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct trace_sampler_view *tr_view; + struct pipe_context *pipe = tr_ctx->pipe; + struct pipe_sampler_view *unwrapped_views[PIPE_MAX_SHADER_SAMPLER_VIEWS]; + unsigned i; + + /* remove this when we have pipe->set_sampler_views(..., start, ...) */ + assert(start == 0); + + for (i = 0; i < num; ++i) { + tr_view = trace_sampler_view(views[i]); + unwrapped_views[i] = tr_view ? tr_view->sampler_view : NULL; + } + views = unwrapped_views; + + trace_dump_call_begin("pipe_context", "set_sampler_views"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(uint, shader); + trace_dump_arg(uint, start); + trace_dump_arg(uint, num); + trace_dump_arg_array(ptr, views, num); + + pipe->set_sampler_views(pipe, shader, start, num, views); + + trace_dump_call_end(); +} + + +static void +trace_context_set_vertex_buffers(struct pipe_context *_pipe, + unsigned start_slot, unsigned num_buffers, + const struct pipe_vertex_buffer *buffers) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct pipe_context *pipe = tr_ctx->pipe; + + trace_dump_call_begin("pipe_context", "set_vertex_buffers"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(uint, start_slot); + trace_dump_arg(uint, num_buffers); + + trace_dump_arg_begin("buffers"); + trace_dump_struct_array(vertex_buffer, buffers, num_buffers); + trace_dump_arg_end(); + + pipe->set_vertex_buffers(pipe, start_slot, num_buffers, buffers); + + trace_dump_call_end(); +} + + +static struct pipe_stream_output_target * +trace_context_create_stream_output_target(struct pipe_context *_pipe, + struct pipe_resource *res, + unsigned buffer_offset, + unsigned buffer_size) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct pipe_context *pipe = tr_ctx->pipe; + struct pipe_stream_output_target *result; + + trace_dump_call_begin("pipe_context", "create_stream_output_target"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(ptr, res); + trace_dump_arg(uint, buffer_offset); + trace_dump_arg(uint, buffer_size); + + result = pipe->create_stream_output_target(pipe, + res, buffer_offset, buffer_size); + + trace_dump_ret(ptr, result); + + trace_dump_call_end(); + + return result; +} + + +static void +trace_context_stream_output_target_destroy( + struct pipe_context *_pipe, + struct pipe_stream_output_target *target) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct pipe_context *pipe = tr_ctx->pipe; + + trace_dump_call_begin("pipe_context", "stream_output_target_destroy"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(ptr, target); + + pipe->stream_output_target_destroy(pipe, target); + + trace_dump_call_end(); +} + + +static void +trace_context_set_stream_output_targets(struct pipe_context *_pipe, + unsigned num_targets, + struct pipe_stream_output_target **tgs, + const unsigned *offsets) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct pipe_context *pipe = tr_ctx->pipe; + + trace_dump_call_begin("pipe_context", "set_stream_output_targets"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(uint, num_targets); + trace_dump_arg_array(ptr, tgs, num_targets); + trace_dump_arg_array(uint, offsets, num_targets); + + pipe->set_stream_output_targets(pipe, num_targets, tgs, offsets); + + trace_dump_call_end(); +} + + +static void +trace_context_resource_copy_region(struct pipe_context *_pipe, + struct pipe_resource *dst, + unsigned dst_level, + unsigned dstx, unsigned dsty, unsigned dstz, + struct pipe_resource *src, + unsigned src_level, + const struct pipe_box *src_box) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct pipe_context *pipe = tr_ctx->pipe; + + trace_dump_call_begin("pipe_context", "resource_copy_region"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(ptr, dst); + trace_dump_arg(uint, dst_level); + trace_dump_arg(uint, dstx); + trace_dump_arg(uint, dsty); + trace_dump_arg(uint, dstz); + trace_dump_arg(ptr, src); + trace_dump_arg(uint, src_level); + trace_dump_arg(box, src_box); + + pipe->resource_copy_region(pipe, + dst, dst_level, dstx, dsty, dstz, + src, src_level, src_box); + + trace_dump_call_end(); +} + + +static void +trace_context_blit(struct pipe_context *_pipe, + const struct pipe_blit_info *_info) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct pipe_context *pipe = tr_ctx->pipe; + struct pipe_blit_info info = *_info; + + trace_dump_call_begin("pipe_context", "blit"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(blit_info, _info); + + pipe->blit(pipe, &info); + + trace_dump_call_end(); +} + + +static void +trace_context_flush_resource(struct pipe_context *_pipe, + struct pipe_resource *resource) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct pipe_context *pipe = tr_ctx->pipe; + + trace_dump_call_begin("pipe_context", "flush_resource"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(ptr, resource); + + pipe->flush_resource(pipe, resource); + + trace_dump_call_end(); +} + + +static void +trace_context_clear(struct pipe_context *_pipe, + unsigned buffers, + const union pipe_color_union *color, + 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_begin("color"); + if (color) + trace_dump_array(float, color->f, 4); + else + trace_dump_null(); + trace_dump_arg_end(); + trace_dump_arg(float, depth); + trace_dump_arg(uint, stencil); + + pipe->clear(pipe, buffers, color, depth, stencil); + + trace_dump_call_end(); +} + + +static void +trace_context_clear_render_target(struct pipe_context *_pipe, + struct pipe_surface *dst, + const union pipe_color_union *color, + unsigned dstx, unsigned dsty, + unsigned width, unsigned height, + bool render_condition_enabled) +{ + 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", "clear_render_target"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(ptr, dst); + trace_dump_arg_array(float, color->f, 4); + trace_dump_arg(uint, dstx); + trace_dump_arg(uint, dsty); + trace_dump_arg(uint, width); + trace_dump_arg(uint, height); + trace_dump_arg(bool, render_condition_enabled); + + pipe->clear_render_target(pipe, dst, color, dstx, dsty, width, height, + render_condition_enabled); + + trace_dump_call_end(); +} + +static void +trace_context_clear_depth_stencil(struct pipe_context *_pipe, + struct pipe_surface *dst, + unsigned clear_flags, + double depth, + unsigned stencil, + unsigned dstx, unsigned dsty, + unsigned width, unsigned height, + bool render_condition_enabled) +{ + 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", "clear_depth_stencil"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(ptr, dst); + trace_dump_arg(uint, clear_flags); + trace_dump_arg(float, depth); + trace_dump_arg(uint, stencil); + trace_dump_arg(uint, dstx); + trace_dump_arg(uint, dsty); + trace_dump_arg(uint, width); + trace_dump_arg(uint, height); + trace_dump_arg(bool, render_condition_enabled); + + pipe->clear_depth_stencil(pipe, dst, clear_flags, depth, stencil, + dstx, dsty, width, height, + render_condition_enabled); + + trace_dump_call_end(); +} + +static inline void +trace_context_clear_texture(struct pipe_context *_pipe, + struct pipe_resource *res, + unsigned level, + const struct pipe_box *box, + const void *data) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct pipe_context *pipe = tr_ctx->pipe; + + + trace_dump_call_begin("pipe_context", "clear_texture"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(ptr, res); + trace_dump_arg(uint, level); + trace_dump_arg_begin("box"); + trace_dump_box(box); + trace_dump_arg_end(); + trace_dump_arg(ptr, data); + + pipe->clear_texture(pipe, res, level, box, data); + + trace_dump_call_end(); +} + +static void +trace_context_flush(struct pipe_context *_pipe, + struct pipe_fence_handle **fence, + unsigned flags) +{ + 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, fence, flags); + + if (fence) + trace_dump_ret(ptr, *fence); + + trace_dump_call_end(); +} + + +static inline boolean +trace_context_generate_mipmap(struct pipe_context *_pipe, + struct pipe_resource *res, + enum pipe_format format, + unsigned base_level, + unsigned last_level, + unsigned first_layer, + unsigned last_layer) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct pipe_context *pipe = tr_ctx->pipe; + boolean ret; + + trace_dump_call_begin("pipe_context", "generate_mipmap"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(ptr, res); + + trace_dump_arg(format, format); + trace_dump_arg(uint, base_level); + trace_dump_arg(uint, last_level); + trace_dump_arg(uint, first_layer); + trace_dump_arg(uint, last_layer); + + ret = pipe->generate_mipmap(pipe, res, format, base_level, last_level, + first_layer, last_layer); + + trace_dump_ret(bool, ret); + trace_dump_call_end(); + + return ret; +} + + +static void +trace_context_destroy(struct pipe_context *_pipe) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct pipe_context *pipe = tr_ctx->pipe; + + trace_dump_call_begin("pipe_context", "destroy"); + trace_dump_arg(ptr, pipe); + trace_dump_call_end(); + + pipe->destroy(pipe); + + FREE(tr_ctx); +} + + +/******************************************************************** + * transfer + */ + + +static void * +trace_context_transfer_map(struct pipe_context *_context, + struct pipe_resource *resource, + unsigned level, + unsigned usage, + const struct pipe_box *box, + struct pipe_transfer **transfer) +{ + struct trace_context *tr_context = trace_context(_context); + struct pipe_context *context = tr_context->pipe; + struct pipe_transfer *result = NULL; + void *map; + + /* + * Map and transfers can't be serialized so we convert all write transfers + * to texture/buffer_subdata and ignore read transfers. + */ + + map = context->transfer_map(context, resource, level, usage, box, &result); + if (!map) + return NULL; + + *transfer = trace_transfer_create(tr_context, resource, result); + + if (map) { + if (usage & PIPE_TRANSFER_WRITE) { + trace_transfer(*transfer)->map = map; + } + } + + return *transfer ? map : NULL; +} + +static void +trace_context_transfer_flush_region( struct pipe_context *_context, + struct pipe_transfer *_transfer, + const struct pipe_box *box) +{ + struct trace_context *tr_context = trace_context(_context); + struct trace_transfer *tr_transfer = trace_transfer(_transfer); + struct pipe_context *context = tr_context->pipe; + struct pipe_transfer *transfer = tr_transfer->transfer; + + context->transfer_flush_region(context, transfer, box); +} + +static void +trace_context_transfer_unmap(struct pipe_context *_context, + struct pipe_transfer *_transfer) +{ + struct trace_context *tr_ctx = trace_context(_context); + struct trace_transfer *tr_trans = trace_transfer(_transfer); + struct pipe_context *context = tr_ctx->pipe; + struct pipe_transfer *transfer = tr_trans->transfer; + + if (tr_trans->map) { + /* + * Fake a texture/buffer_subdata + */ + + struct pipe_resource *resource = transfer->resource; + unsigned level = transfer->level; + unsigned usage = transfer->usage; + const struct pipe_box *box = &transfer->box; + unsigned stride = transfer->stride; + unsigned layer_stride = transfer->layer_stride; + + if (resource->target == PIPE_BUFFER) + trace_dump_call_begin("pipe_context", "buffer_subdata"); + else + trace_dump_call_begin("pipe_context", "texture_subdata"); + + trace_dump_arg(ptr, context); + trace_dump_arg(ptr, resource); + trace_dump_arg(uint, level); + trace_dump_arg(uint, usage); + trace_dump_arg(box, box); + + trace_dump_arg_begin("data"); + trace_dump_box_bytes(tr_trans->map, + resource, + box, + stride, + layer_stride); + trace_dump_arg_end(); + + trace_dump_arg(uint, stride); + trace_dump_arg(uint, layer_stride); + + trace_dump_call_end(); + + tr_trans->map = NULL; + } + + context->transfer_unmap(context, transfer); + trace_transfer_destroy(tr_ctx, tr_trans); +} + + +static void +trace_context_buffer_subdata(struct pipe_context *_context, + struct pipe_resource *resource, + unsigned usage, unsigned offset, + unsigned size, const void *data) +{ + struct trace_context *tr_context = trace_context(_context); + struct pipe_context *context = tr_context->pipe; + struct pipe_box box; + + trace_dump_call_begin("pipe_context", "buffer_subdata"); + + trace_dump_arg(ptr, context); + trace_dump_arg(ptr, resource); + trace_dump_arg(uint, usage); + trace_dump_arg(uint, offset); + trace_dump_arg(uint, size); + + trace_dump_arg_begin("data"); + u_box_1d(offset, size, &box); + trace_dump_box_bytes(data, resource, &box, 0, 0); + trace_dump_arg_end(); + + trace_dump_call_end(); + + context->buffer_subdata(context, resource, usage, offset, size, data); +} + + +static void +trace_context_texture_subdata(struct pipe_context *_context, + struct pipe_resource *resource, + unsigned level, + unsigned usage, + const struct pipe_box *box, + const void *data, + unsigned stride, + unsigned layer_stride) +{ + struct trace_context *tr_context = trace_context(_context); + struct pipe_context *context = tr_context->pipe; + + trace_dump_call_begin("pipe_context", "texture_subdata"); + + trace_dump_arg(ptr, context); + trace_dump_arg(ptr, resource); + trace_dump_arg(uint, level); + trace_dump_arg(uint, usage); + trace_dump_arg(box, box); + + trace_dump_arg_begin("data"); + trace_dump_box_bytes(data, + resource, + box, + stride, + layer_stride); + trace_dump_arg_end(); + + trace_dump_arg(uint, stride); + trace_dump_arg(uint, layer_stride); + + trace_dump_call_end(); + + context->texture_subdata(context, resource, level, usage, box, + data, stride, layer_stride); +} + +static void +trace_context_invalidate_resource(struct pipe_context *_context, + struct pipe_resource *resource) +{ + struct trace_context *tr_context = trace_context(_context); + struct pipe_context *context = tr_context->pipe; + + trace_dump_call_begin("pipe_context", "invalidate_resource"); + + trace_dump_arg(ptr, context); + trace_dump_arg(ptr, resource); + + trace_dump_call_end(); + + context->invalidate_resource(context, resource); +} + +static void +trace_context_render_condition(struct pipe_context *_context, + struct pipe_query *query, + boolean condition, + enum pipe_render_cond_flag mode) +{ + struct trace_context *tr_context = trace_context(_context); + struct pipe_context *context = tr_context->pipe; + + query = trace_query_unwrap(query); + + trace_dump_call_begin("pipe_context", "render_condition"); + + trace_dump_arg(ptr, context); + trace_dump_arg(ptr, query); + trace_dump_arg(bool, condition); + trace_dump_arg(uint, mode); + + trace_dump_call_end(); + + context->render_condition(context, query, condition, mode); +} + + +static void +trace_context_texture_barrier(struct pipe_context *_context, unsigned flags) +{ + struct trace_context *tr_context = trace_context(_context); + struct pipe_context *context = tr_context->pipe; + + trace_dump_call_begin("pipe_context", "texture_barrier"); + + trace_dump_arg(ptr, context); + trace_dump_arg(uint, flags); + + trace_dump_call_end(); + + context->texture_barrier(context, flags); +} + + +static void +trace_context_memory_barrier(struct pipe_context *_context, + unsigned flags) +{ + struct trace_context *tr_context = trace_context(_context); + struct pipe_context *context = tr_context->pipe; + + trace_dump_call_begin("pipe_context", "memory_barrier"); + trace_dump_arg(ptr, context); + trace_dump_arg(uint, flags); + trace_dump_call_end(); + + context->memory_barrier(context, flags); +} + + +static bool +trace_context_resource_commit(struct pipe_context *_context, + struct pipe_resource *resource, + unsigned level, struct pipe_box *box, bool commit) +{ + struct trace_context *tr_context = trace_context(_context); + struct pipe_context *context = tr_context->pipe; + + trace_dump_call_begin("pipe_context", "resource_commit"); + trace_dump_arg(ptr, context); + trace_dump_arg(ptr, resource); + trace_dump_arg(uint, level); + trace_dump_arg(box, box); + trace_dump_arg(bool, commit); + trace_dump_call_end(); + + return context->resource_commit(context, resource, level, box, commit); +} + +static void +trace_context_set_tess_state(struct pipe_context *_context, + const float default_outer_level[4], + const float default_inner_level[2]) +{ + struct trace_context *tr_context = trace_context(_context); + struct pipe_context *context = tr_context->pipe; + + trace_dump_call_begin("pipe_context", "set_tess_state"); + trace_dump_arg(ptr, context); + trace_dump_arg_array(float, default_outer_level, 4); + trace_dump_arg_array(float, default_inner_level, 2); + trace_dump_call_end(); + + context->set_tess_state(context, default_outer_level, default_inner_level); +} + + +static void trace_context_set_shader_buffers(struct pipe_context *_context, + enum pipe_shader_type shader, + unsigned start, unsigned nr, + const struct pipe_shader_buffer *buffers) +{ + struct trace_context *tr_context = trace_context(_context); + struct pipe_context *context = tr_context->pipe; + + trace_dump_call_begin("pipe_context", "set_shader_buffers"); + trace_dump_arg(ptr, context); + trace_dump_arg(uint, shader); + trace_dump_arg(uint, start); + trace_dump_arg_begin("buffers"); + trace_dump_struct_array(shader_buffer, buffers, nr); + trace_dump_arg_end(); + trace_dump_call_end(); + + context->set_shader_buffers(context, shader, start, nr, buffers); +} + +static void trace_context_set_shader_images(struct pipe_context *_context, + enum pipe_shader_type shader, + unsigned start, unsigned nr, + const struct pipe_image_view *images) +{ + struct trace_context *tr_context = trace_context(_context); + struct pipe_context *context = tr_context->pipe; + + trace_dump_call_begin("pipe_context", "set_shader_images"); + trace_dump_arg(ptr, context); + trace_dump_arg(uint, shader); + trace_dump_arg(uint, start); + trace_dump_arg_begin("images"); + trace_dump_struct_array(image_view, images, nr); + trace_dump_arg_end(); + trace_dump_call_end(); + + context->set_shader_images(context, shader, start, nr, images); +} + +static void trace_context_launch_grid(struct pipe_context *_pipe, + const struct pipe_grid_info *info) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct pipe_context *pipe = tr_ctx->pipe; + + trace_dump_call_begin("pipe_context", "launch_grid"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(grid_info, info); + + trace_dump_trace_flush(); + + pipe->launch_grid(pipe, info); + + trace_dump_call_end(); +} + +static uint64_t trace_context_create_texture_handle(struct pipe_context *_pipe, + struct pipe_sampler_view *view, + const struct pipe_sampler_state *state) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct pipe_context *pipe = tr_ctx->pipe; + uint64_t handle; + + trace_dump_call_begin("pipe_context", "create_texture_handle"); + trace_dump_arg(ptr, pipe); + trace_dump_arg(ptr, view); + trace_dump_arg_begin("state"); + trace_dump_arg(sampler_state, state); + trace_dump_arg_end(); + + handle = pipe->create_texture_handle(pipe, view, state); + + trace_dump_ret(uint, handle); + trace_dump_call_end(); + + return handle; +} + +static void trace_context_delete_texture_handle(struct pipe_context *_pipe, + uint64_t handle) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct pipe_context *pipe = tr_ctx->pipe; + + trace_dump_call_begin("pipe_context", "delete_texture_handle"); + trace_dump_arg(ptr, pipe); + trace_dump_arg(uint, handle); + trace_dump_call_end(); + + pipe->delete_texture_handle(pipe, handle); +} + +static void trace_context_make_texture_handle_resident(struct pipe_context *_pipe, + uint64_t handle, + bool resident) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct pipe_context *pipe = tr_ctx->pipe; + + trace_dump_call_begin("pipe_context", "make_texture_handle_resident"); + trace_dump_arg(ptr, pipe); + trace_dump_arg(uint, handle); + trace_dump_arg(bool, resident); + trace_dump_call_end(); + + pipe->make_texture_handle_resident(pipe, handle, resident); +} + +static uint64_t trace_context_create_image_handle(struct pipe_context *_pipe, + const struct pipe_image_view *image) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct pipe_context *pipe = tr_ctx->pipe; + uint64_t handle; + + trace_dump_call_begin("pipe_context", "create_image_handle"); + trace_dump_arg(ptr, pipe); + trace_dump_arg_begin("image"); + trace_dump_image_view(image); + trace_dump_arg_end(); + + handle = pipe->create_image_handle(pipe, image); + + trace_dump_ret(uint, handle); + trace_dump_call_end(); + + return handle; +} + +static void trace_context_delete_image_handle(struct pipe_context *_pipe, + uint64_t handle) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct pipe_context *pipe = tr_ctx->pipe; + + trace_dump_call_begin("pipe_context", "delete_image_handle"); + trace_dump_arg(ptr, pipe); + trace_dump_arg(uint, handle); + trace_dump_call_end(); + + pipe->delete_image_handle(pipe, handle); +} + +static void trace_context_make_image_handle_resident(struct pipe_context *_pipe, + uint64_t handle, + unsigned access, + bool resident) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct pipe_context *pipe = tr_ctx->pipe; + + trace_dump_call_begin("pipe_context", "make_image_handle_resident"); + trace_dump_arg(ptr, pipe); + trace_dump_arg(uint, handle); + trace_dump_arg(uint, access); + trace_dump_arg(bool, resident); + trace_dump_call_end(); + + pipe->make_image_handle_resident(pipe, handle, access, resident); +} + +struct pipe_context * +trace_context_create(struct trace_screen *tr_scr, + struct pipe_context *pipe) +{ + struct trace_context *tr_ctx; + + if (!pipe) + goto error1; + + if (!trace_enabled()) + goto error1; + + tr_ctx = CALLOC_STRUCT(trace_context); + if (!tr_ctx) + goto error1; + + tr_ctx->base.priv = pipe->priv; /* expose wrapped priv data */ + tr_ctx->base.screen = &tr_scr->base; + tr_ctx->base.stream_uploader = pipe->stream_uploader; + tr_ctx->base.const_uploader = pipe->const_uploader; + + tr_ctx->base.destroy = trace_context_destroy; + +#define TR_CTX_INIT(_member) \ + tr_ctx->base . _member = pipe -> _member ? trace_context_ ## _member : NULL + + TR_CTX_INIT(draw_vbo); + TR_CTX_INIT(render_condition); + TR_CTX_INIT(create_query); + TR_CTX_INIT(destroy_query); + TR_CTX_INIT(begin_query); + TR_CTX_INIT(end_query); + TR_CTX_INIT(get_query_result); + TR_CTX_INIT(set_active_query_state); + TR_CTX_INIT(create_blend_state); + TR_CTX_INIT(bind_blend_state); + TR_CTX_INIT(delete_blend_state); + TR_CTX_INIT(create_sampler_state); + TR_CTX_INIT(bind_sampler_states); + TR_CTX_INIT(delete_sampler_state); + TR_CTX_INIT(create_rasterizer_state); + TR_CTX_INIT(bind_rasterizer_state); + TR_CTX_INIT(delete_rasterizer_state); + TR_CTX_INIT(create_depth_stencil_alpha_state); + TR_CTX_INIT(bind_depth_stencil_alpha_state); + TR_CTX_INIT(delete_depth_stencil_alpha_state); + TR_CTX_INIT(create_fs_state); + TR_CTX_INIT(bind_fs_state); + TR_CTX_INIT(delete_fs_state); + TR_CTX_INIT(create_vs_state); + TR_CTX_INIT(bind_vs_state); + TR_CTX_INIT(delete_vs_state); + TR_CTX_INIT(create_gs_state); + TR_CTX_INIT(bind_gs_state); + TR_CTX_INIT(delete_gs_state); + TR_CTX_INIT(create_tcs_state); + TR_CTX_INIT(bind_tcs_state); + TR_CTX_INIT(delete_tcs_state); + TR_CTX_INIT(create_tes_state); + TR_CTX_INIT(bind_tes_state); + TR_CTX_INIT(delete_tes_state); + TR_CTX_INIT(create_compute_state); + TR_CTX_INIT(bind_compute_state); + TR_CTX_INIT(delete_compute_state); + TR_CTX_INIT(create_vertex_elements_state); + TR_CTX_INIT(bind_vertex_elements_state); + TR_CTX_INIT(delete_vertex_elements_state); + TR_CTX_INIT(set_blend_color); + TR_CTX_INIT(set_stencil_ref); + TR_CTX_INIT(set_clip_state); + TR_CTX_INIT(set_sample_mask); + TR_CTX_INIT(set_constant_buffer); + TR_CTX_INIT(set_framebuffer_state); + TR_CTX_INIT(set_polygon_stipple); + TR_CTX_INIT(set_scissor_states); + TR_CTX_INIT(set_viewport_states); + TR_CTX_INIT(set_sampler_views); + TR_CTX_INIT(create_sampler_view); + TR_CTX_INIT(sampler_view_destroy); + TR_CTX_INIT(create_surface); + TR_CTX_INIT(surface_destroy); + TR_CTX_INIT(set_vertex_buffers); + TR_CTX_INIT(create_stream_output_target); + TR_CTX_INIT(stream_output_target_destroy); + TR_CTX_INIT(set_stream_output_targets); + TR_CTX_INIT(resource_copy_region); + TR_CTX_INIT(blit); + TR_CTX_INIT(flush_resource); + TR_CTX_INIT(clear); + TR_CTX_INIT(clear_render_target); + TR_CTX_INIT(clear_depth_stencil); + TR_CTX_INIT(clear_texture); + TR_CTX_INIT(flush); + TR_CTX_INIT(generate_mipmap); + TR_CTX_INIT(texture_barrier); + TR_CTX_INIT(memory_barrier); + TR_CTX_INIT(resource_commit); + TR_CTX_INIT(set_tess_state); + TR_CTX_INIT(set_shader_buffers); + TR_CTX_INIT(launch_grid); + TR_CTX_INIT(set_shader_images); + TR_CTX_INIT(create_texture_handle); + TR_CTX_INIT(delete_texture_handle); + TR_CTX_INIT(make_texture_handle_resident); + TR_CTX_INIT(create_image_handle); + TR_CTX_INIT(delete_image_handle); + TR_CTX_INIT(make_image_handle_resident); + + TR_CTX_INIT(transfer_map); + TR_CTX_INIT(transfer_unmap); + TR_CTX_INIT(transfer_flush_region); + TR_CTX_INIT(buffer_subdata); + TR_CTX_INIT(texture_subdata); + TR_CTX_INIT(invalidate_resource); + +#undef TR_CTX_INIT + + tr_ctx->pipe = pipe; + + return &tr_ctx->base; + +error1: + return pipe; +} + + +/** + * Sanity checker: check that the given context really is a + * trace context (and not the wrapped driver's context). + */ +void +trace_context_check(const struct pipe_context *pipe) +{ + MAYBE_UNUSED struct trace_context *tr_ctx = (struct trace_context *) pipe; + assert(tr_ctx->base.destroy == trace_context_destroy); +} diff --git a/src/gallium/auxiliary/driver_trace/tr_context.h b/src/gallium/auxiliary/driver_trace/tr_context.h new file mode 100644 index 00000000000..ad57d9d5243 --- /dev/null +++ b/src/gallium/auxiliary/driver_trace/tr_context.h @@ -0,0 +1,77 @@ +/************************************************************************** + * + * Copyright 2008 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_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_screen; + +struct trace_context +{ + struct pipe_context base; + + struct pipe_context *pipe; +}; + + +void +trace_context_check(const struct pipe_context *pipe); + + +static inline struct trace_context * +trace_context(struct pipe_context *pipe) +{ + assert(pipe); +#ifdef DEBUG + trace_context_check(pipe); +#endif + return (struct trace_context *)pipe; +} + + +struct pipe_context * +trace_context_create(struct trace_screen *tr_scr, + struct pipe_context *pipe); + + +#ifdef __cplusplus +} +#endif + +#endif /* TR_CONTEXT_H_ */ diff --git a/src/gallium/auxiliary/driver_trace/tr_dump.c b/src/gallium/auxiliary/driver_trace/tr_dump.c new file mode 100644 index 00000000000..49349496ac6 --- /dev/null +++ b/src/gallium/auxiliary/driver_trace/tr_dump.c @@ -0,0 +1,599 @@ +/************************************************************************** + * + * Copyright 2008 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. + * + **************************************************************************/ + + +/** + * @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 <[email protected]> + */ + +#include "pipe/p_config.h" + +#include <stdio.h> +#include <stdlib.h> + +#include "pipe/p_compiler.h" +#include "os/os_thread.h" +#include "util/os_time.h" +#include "util/u_debug.h" +#include "util/u_memory.h" +#include "util/u_string.h" +#include "util/u_math.h" +#include "util/u_format.h" + +#include "tr_dump.h" +#include "tr_screen.h" +#include "tr_texture.h" + + +static boolean close_stream = FALSE; +static FILE *stream = NULL; +static mtx_t call_mutex = _MTX_INITIALIZER_NP; +static long unsigned call_no = 0; +static boolean dumping = FALSE; + + +static inline void +trace_dump_write(const char *buf, size_t size) +{ + if (stream) { + fwrite(buf, size, 1, stream); + } +} + + +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_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_end(const char *name) +{ + trace_dump_writes("</"); + trace_dump_writes(name); + trace_dump_writes(">"); +} + +void +trace_dump_trace_flush(void) +{ + if (stream) { + fflush(stream); + } +} + +static void +trace_dump_trace_close(void) +{ + if (stream) { + trace_dump_writes("</trace>\n"); + if (close_stream) { + fclose(stream); + close_stream = FALSE; + stream = NULL; + } + call_no = 0; + } +} + + +static void +trace_dump_call_time(int64_t time) +{ + if (stream) { + trace_dump_indent(2); + trace_dump_tag_begin("time"); + trace_dump_int(time); + trace_dump_tag_end("time"); + trace_dump_newline(); + } +} + + +boolean +trace_dump_trace_begin(void) +{ + const char *filename; + + filename = debug_get_option("GALLIUM_TRACE", NULL); + if (!filename) + return FALSE; + + if (!stream) { + + if (strcmp(filename, "stderr") == 0) { + close_stream = FALSE; + stream = stderr; + } + else if (strcmp(filename, "stdout") == 0) { + close_stream = FALSE; + stream = stdout; + } + else { + close_stream = TRUE; + stream = fopen(filename, "wt"); + 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"); + + /* Many applications don't exit cleanly, others may create and destroy a + * screen multiple times, so we only write </trace> tag and close at exit + * time. + */ + atexit(trace_dump_trace_close); + } + + return TRUE; +} + +boolean trace_dump_trace_enabled(void) +{ + return stream ? TRUE : FALSE; +} + +/* + * Call lock + */ + +void trace_dump_call_lock(void) +{ + mtx_lock(&call_mutex); +} + +void trace_dump_call_unlock(void) +{ + mtx_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) +{ + mtx_lock(&call_mutex); + trace_dumping_start_locked(); + mtx_unlock(&call_mutex); +} + +void trace_dumping_stop(void) +{ + mtx_lock(&call_mutex); + trace_dumping_stop_locked(); + mtx_unlock(&call_mutex); +} + +boolean trace_dumping_enabled(void) +{ + boolean ret; + mtx_lock(&call_mutex); + ret = trace_dumping_enabled_locked(); + mtx_unlock(&call_mutex); + return ret; +} + +/* + * Dump functions + */ + +static int64_t call_start_time = 0; + +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(); + + call_start_time = os_time_get(); +} + +void trace_dump_call_end_locked(void) +{ + int64_t call_end_time; + + if (!dumping) + return; + + call_end_time = os_time_get(); + + trace_dump_call_time(call_end_time - call_start_time); + trace_dump_indent(1); + trace_dump_tag_end("call"); + trace_dump_newline(); + fflush(stream); +} + +void trace_dump_call_begin(const char *klass, const char *method) +{ + mtx_lock(&call_mutex); + trace_dump_call_begin_locked(klass, method); +} + +void trace_dump_call_end(void) +{ + trace_dump_call_end_locked(); + mtx_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_box_bytes(const void *data, + struct pipe_resource *resource, + const struct pipe_box *box, + unsigned stride, + unsigned slice_stride) +{ + enum pipe_format format = resource->format; + size_t size; + + assert(box->height > 0); + assert(box->depth > 0); + + size = util_format_get_nblocksx(format, box->width ) * util_format_get_blocksize(format) + + (util_format_get_nblocksy(format, box->height) - 1) * stride + + (box->depth - 1) * slice_stride; + + /* + * Only dump buffer transfers to avoid huge files. + * TODO: Make this run-time configurable + */ + if (resource->target != PIPE_BUFFER) { + size = 0; + } + + trace_dump_bytes(data, size); +} + +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_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/auxiliary/driver_trace/tr_dump.h b/src/gallium/auxiliary/driver_trace/tr_dump.h new file mode 100644 index 00000000000..7a268e31c46 --- /dev/null +++ b/src/gallium/auxiliary/driver_trace/tr_dump.h @@ -0,0 +1,190 @@ +/************************************************************************** + * + * Copyright 2008 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. + * + **************************************************************************/ + +/** + * @file + * Trace data dumping primitives. + */ + +#ifndef TR_DUMP_H +#define TR_DUMP_H + + +#include "pipe/p_compiler.h" +#include "pipe/p_format.h" + +struct pipe_resource; +struct pipe_surface; +struct pipe_transfer; +struct pipe_box; + +/* + * 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_flush(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_box_bytes(const void *data, + struct pipe_resource *resource, + const struct pipe_box *box, + unsigned stride, + unsigned slice_stride); +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_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_arg_struct(_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 { \ + if (_obj) { \ + 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(); \ + } else { \ + trace_dump_null(); \ + } \ + } while(0) + +#define trace_dump_struct_array(_type, _obj, _size) \ + do { \ + if (_obj) { \ + 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(); \ + } else { \ + trace_dump_null(); \ + } \ + } 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/auxiliary/driver_trace/tr_dump_defines.h b/src/gallium/auxiliary/driver_trace/tr_dump_defines.h new file mode 100644 index 00000000000..7f969a30333 --- /dev/null +++ b/src/gallium/auxiliary/driver_trace/tr_dump_defines.h @@ -0,0 +1,58 @@ +/************************************************************************** + * + * Copyright 2013 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_DUMP_DEFINES_H_ +#define TR_DUMP_DEFINES_H_ + +#include "pipe/p_compiler.h" +#include "util/u_format.h" +#include "util/u_dump.h" +#include "tr_dump.h" + + +static inline void +trace_dump_format(enum pipe_format format) +{ + if (!trace_dumping_enabled_locked()) + return; + + trace_dump_enum(util_format_name(format)); +} + + +static inline void +trace_dump_query_type(unsigned value) +{ + if (!trace_dumping_enabled_locked()) + return; + + trace_dump_enum(util_str_query_type(value, FALSE)); +} + + + +#endif /* TR_DUMP_DEFINES_H_ */ diff --git a/src/gallium/auxiliary/driver_trace/tr_dump_state.c b/src/gallium/auxiliary/driver_trace/tr_dump_state.c new file mode 100644 index 00000000000..e7e32237c4c --- /dev/null +++ b/src/gallium/auxiliary/driver_trace/tr_dump_state.c @@ -0,0 +1,961 @@ +/************************************************************************** + * + * Copyright 2008 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 "pipe/p_compiler.h" +#include "util/u_memory.h" +#include "util/u_format.h" +#include "tgsi/tgsi_dump.h" + +#include "tr_dump.h" +#include "tr_dump_defines.h" +#include "tr_dump_state.h" + + +void trace_dump_resource_template(const struct pipe_resource *templat) +{ + if (!trace_dumping_enabled_locked()) + return; + + if (!templat) { + trace_dump_null(); + return; + } + + trace_dump_struct_begin("pipe_resource"); + + trace_dump_member(int, templat, target); + trace_dump_member(format, templat, format); + + trace_dump_member_begin("width"); + trace_dump_uint(templat->width0); + trace_dump_member_end(); + + trace_dump_member_begin("height"); + trace_dump_uint(templat->height0); + trace_dump_member_end(); + + trace_dump_member_begin("depth"); + trace_dump_uint(templat->depth0); + trace_dump_member_end(); + + trace_dump_member_begin("array_size"); + trace_dump_uint(templat->array_size); + trace_dump_member_end(); + + trace_dump_member(uint, templat, last_level); + trace_dump_member(uint, templat, nr_samples); + trace_dump_member(uint, templat, usage); + trace_dump_member(uint, templat, bind); + trace_dump_member(uint, templat, flags); + + trace_dump_struct_end(); +} + + +void trace_dump_box(const struct pipe_box *box) +{ + if (!trace_dumping_enabled_locked()) + return; + + if (!box) { + trace_dump_null(); + return; + } + + trace_dump_struct_begin("pipe_box"); + + trace_dump_member(int, box, x); + trace_dump_member(int, box, y); + trace_dump_member(int, box, z); + trace_dump_member(int, box, width); + trace_dump_member(int, box, height); + trace_dump_member(int, box, depth); + + 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(bool, state, clamp_vertex_color); + trace_dump_member(bool, state, clamp_fragment_color); + trace_dump_member(uint, state, front_ccw); + trace_dump_member(uint, state, cull_face); + trace_dump_member(uint, state, fill_front); + trace_dump_member(uint, state, fill_back); + trace_dump_member(bool, state, offset_point); + trace_dump_member(bool, state, offset_line); + trace_dump_member(bool, state, offset_tri); + 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, sprite_coord_mode); + trace_dump_member(bool, state, point_quad_rasterization); + 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(bool, state, line_last_pixel); + + trace_dump_member(bool, state, flatshade_first); + + trace_dump_member(bool, state, half_pixel_center); + trace_dump_member(bool, state, bottom_edge_rule); + + trace_dump_member(bool, state, rasterizer_discard); + + trace_dump_member(bool, state, depth_clip); + + trace_dump_member(bool, state, clip_halfz); + + trace_dump_member(uint, state, clip_plane_enable); + + trace_dump_member(uint, state, line_stipple_factor); + trace_dump_member(uint, state, line_stipple_pattern); + + trace_dump_member(uint, state, sprite_coord_enable); + + trace_dump_member(float, state, line_width); + trace_dump_member(float, state, point_size); + trace_dump_member(float, state, offset_units); + trace_dump_member(float, state, offset_scale); + trace_dump_member(float, state, offset_clamp); + + 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, + ARRAY_SIZE(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_struct_end(); +} + + +void trace_dump_shader_state(const struct pipe_shader_state *state) +{ + unsigned i; + + if (!trace_dumping_enabled_locked()) + return; + + if (!state) { + trace_dump_null(); + return; + } + + + trace_dump_struct_begin("pipe_shader_state"); + + trace_dump_member_begin("tokens"); + if (state->tokens) { + static char str[64 * 1024]; + tgsi_dump_str(state->tokens, 0, str, sizeof(str)); + trace_dump_string(str); + } else { + trace_dump_null(); + } + trace_dump_member_end(); + + trace_dump_member_begin("stream_output"); + trace_dump_struct_begin("pipe_stream_output_info"); + trace_dump_member(uint, &state->stream_output, num_outputs); + trace_dump_member_array(uint, &state->stream_output, stride); + trace_dump_member_begin("output"); + trace_dump_array_begin(); + for(i = 0; i < state->stream_output.num_outputs; ++i) { + trace_dump_elem_begin(); + trace_dump_struct_begin(""); /* anonymous */ + trace_dump_member(uint, &state->stream_output.output[i], register_index); + trace_dump_member(uint, &state->stream_output.output[i], start_component); + trace_dump_member(uint, &state->stream_output.output[i], num_components); + trace_dump_member(uint, &state->stream_output.output[i], output_buffer); + trace_dump_member(uint, &state->stream_output.output[i], dst_offset); + trace_dump_member(uint, &state->stream_output.output[i], stream); + trace_dump_struct_end(); + trace_dump_elem_end(); + } + trace_dump_array_end(); + trace_dump_member_end(); // output + trace_dump_struct_end(); + trace_dump_member_end(); // stream_output + + trace_dump_struct_end(); +} + + +void trace_dump_compute_state(const struct pipe_compute_state *state) +{ + if (!trace_dumping_enabled_locked()) + return; + + if (!state) { + trace_dump_null(); + return; + } + + trace_dump_struct_begin("pipe_compute_state"); + + trace_dump_member(uint, state, ir_type); + + trace_dump_member_begin("prog"); + if (state->prog && state->ir_type == PIPE_SHADER_IR_TGSI) { + static char str[64 * 1024]; + tgsi_dump_str(state->prog, 0, str, sizeof(str)); + trace_dump_string(str); + } else { + trace_dump_null(); + } + trace_dump_member_end(); + + trace_dump_member(uint, state, req_local_mem); + trace_dump_member(uint, state, req_private_mem); + trace_dump_member(uint, state, req_input_mem); + + 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 < ARRAY_SIZE(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], 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(); +} + +static void trace_dump_rt_blend_state(const struct pipe_rt_blend_state *state) +{ + trace_dump_struct_begin("pipe_rt_blend_state"); + + trace_dump_member(uint, 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(uint, state, colormask); + + trace_dump_struct_end(); +} + +void trace_dump_blend_state(const struct pipe_blend_state *state) +{ + unsigned valid_entries = 1; + + if (!trace_dumping_enabled_locked()) + return; + + if (!state) { + trace_dump_null(); + return; + } + + trace_dump_struct_begin("pipe_blend_state"); + + trace_dump_member(bool, state, dither); + + trace_dump_member(bool, state, logicop_enable); + trace_dump_member(uint, state, logicop_func); + + trace_dump_member(bool, state, independent_blend_enable); + + trace_dump_member_begin("rt"); + if (state->independent_blend_enable) + valid_entries = PIPE_MAX_COLOR_BUFS; + trace_dump_struct_array(rt_blend_state, state->rt, valid_entries); + trace_dump_member_end(); + + 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_stencil_ref(const struct pipe_stencil_ref *state) +{ + if (!trace_dumping_enabled_locked()) + return; + + if (!state) { + trace_dump_null(); + return; + } + + trace_dump_struct_begin("pipe_stencil_ref"); + + trace_dump_member_array(uint, state, ref_value); + + 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, samples); + trace_dump_member(uint, state, layers); + 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(uint, state, compare_mode); + trace_dump_member(uint, state, compare_func); + trace_dump_member(bool, state, normalized_coords); + trace_dump_member(uint, state, max_anisotropy); + trace_dump_member(bool, state, seamless_cube_map); + 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.f); + + trace_dump_struct_end(); +} + + +void trace_dump_sampler_view_template(const struct pipe_sampler_view *state, + enum pipe_texture_target target) +{ + if (!trace_dumping_enabled_locked()) + return; + + if (!state) { + trace_dump_null(); + return; + } + + trace_dump_struct_begin("pipe_sampler_view"); + + trace_dump_member(format, state, format); + + trace_dump_member_begin("u"); + trace_dump_struct_begin(""); /* anonymous */ + if (target == PIPE_BUFFER) { + trace_dump_member_begin("buf"); + trace_dump_struct_begin(""); /* anonymous */ + trace_dump_member(uint, &state->u.buf, offset); + trace_dump_member(uint, &state->u.buf, size); + trace_dump_struct_end(); /* anonymous */ + trace_dump_member_end(); /* buf */ + } else { + trace_dump_member_begin("tex"); + trace_dump_struct_begin(""); /* anonymous */ + trace_dump_member(uint, &state->u.tex, first_layer); + trace_dump_member(uint, &state->u.tex, last_layer); + trace_dump_member(uint, &state->u.tex, first_level); + trace_dump_member(uint, &state->u.tex, last_level); + trace_dump_struct_end(); /* anonymous */ + trace_dump_member_end(); /* tex */ + } + trace_dump_struct_end(); /* anonymous */ + trace_dump_member_end(); /* u */ + + trace_dump_member(uint, state, swizzle_r); + trace_dump_member(uint, state, swizzle_g); + trace_dump_member(uint, state, swizzle_b); + trace_dump_member(uint, state, swizzle_a); + + trace_dump_struct_end(); +} + + +void trace_dump_surface_template(const struct pipe_surface *state, + enum pipe_texture_target target) +{ + if (!trace_dumping_enabled_locked()) + return; + + if (!state) { + trace_dump_null(); + return; + } + + trace_dump_struct_begin("pipe_surface"); + + trace_dump_member(format, state, format); + trace_dump_member(uint, state, width); + trace_dump_member(uint, state, height); + + trace_dump_member_begin("u"); + trace_dump_struct_begin(""); /* anonymous */ + if (target == PIPE_BUFFER) { + trace_dump_member_begin("buf"); + trace_dump_struct_begin(""); /* anonymous */ + trace_dump_member(uint, &state->u.buf, first_element); + trace_dump_member(uint, &state->u.buf, last_element); + trace_dump_struct_end(); /* anonymous */ + trace_dump_member_end(); /* buf */ + } else { + trace_dump_member_begin("tex"); + trace_dump_struct_begin(""); /* anonymous */ + trace_dump_member(uint, &state->u.tex, level); + trace_dump_member(uint, &state->u.tex, first_layer); + trace_dump_member(uint, &state->u.tex, last_layer); + trace_dump_struct_end(); /* anonymous */ + trace_dump_member_end(); /* tex */ + } + trace_dump_struct_end(); /* anonymous */ + trace_dump_member_end(); /* u */ + + 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(uint, state, box.x); + trace_dump_member(uint, state, box.y); + trace_dump_member(uint, state, box.z); + trace_dump_member(uint, state, box.width); + trace_dump_member(uint, state, box.height); + trace_dump_member(uint, state, box.depth); + + trace_dump_member(uint, state, stride); + trace_dump_member(uint, state, layer_stride); + trace_dump_member(uint, state, usage); + + trace_dump_member(ptr, state, resource); + + 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(bool, state, is_user_buffer); + trace_dump_member(uint, state, buffer_offset); + trace_dump_member(ptr, state, buffer.resource); + + 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(format, state, src_format); + + 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(ptr, state, buffer); + trace_dump_member(uint, state, buffer_offset); + trace_dump_member(uint, state, buffer_size); + trace_dump_struct_end(); +} + + +void trace_dump_shader_buffer(const struct pipe_shader_buffer *state) +{ + if (!trace_dumping_enabled_locked()) + return; + + if(!state) { + trace_dump_null(); + return; + } + + trace_dump_struct_begin("pipe_shader_buffer"); + trace_dump_member(ptr, state, buffer); + trace_dump_member(uint, state, buffer_offset); + trace_dump_member(uint, state, buffer_size); + trace_dump_struct_end(); +} + + +void trace_dump_image_view(const struct pipe_image_view *state) +{ + if (!trace_dumping_enabled_locked()) + return; + + if(!state) { + trace_dump_null(); + return; + } + + trace_dump_struct_begin("pipe_image_view"); + trace_dump_member(ptr, state, resource); + trace_dump_member(uint, state, format); + trace_dump_member(uint, state, access); + + trace_dump_member_begin("u"); + trace_dump_struct_begin(""); /* anonymous */ + if (state->resource->target == PIPE_BUFFER) { + trace_dump_member_begin("buf"); + trace_dump_struct_begin(""); /* anonymous */ + trace_dump_member(uint, &state->u.buf, offset); + trace_dump_member(uint, &state->u.buf, size); + trace_dump_struct_end(); /* anonymous */ + trace_dump_member_end(); /* buf */ + } else { + trace_dump_member_begin("tex"); + trace_dump_struct_begin(""); /* anonymous */ + trace_dump_member(uint, &state->u.tex, first_layer); + trace_dump_member(uint, &state->u.tex, last_layer); + trace_dump_member(uint, &state->u.tex, level); + trace_dump_struct_end(); /* anonymous */ + trace_dump_member_end(); /* tex */ + } + trace_dump_struct_end(); /* anonymous */ + trace_dump_member_end(); /* u */ + + trace_dump_struct_end(); +} + + +void trace_dump_draw_info(const struct pipe_draw_info *state) +{ + if (!trace_dumping_enabled_locked()) + return; + + if (!state) { + trace_dump_null(); + return; + } + + trace_dump_struct_begin("pipe_draw_info"); + + trace_dump_member(uint, state, index_size); + trace_dump_member(uint, state, has_user_indices); + + trace_dump_member(uint, state, mode); + trace_dump_member(uint, state, start); + trace_dump_member(uint, state, count); + + trace_dump_member(uint, state, start_instance); + trace_dump_member(uint, state, instance_count); + + trace_dump_member(uint, state, vertices_per_patch); + + trace_dump_member(int, state, index_bias); + trace_dump_member(uint, state, min_index); + trace_dump_member(uint, state, max_index); + + trace_dump_member(bool, state, primitive_restart); + trace_dump_member(uint, state, restart_index); + + trace_dump_member(ptr, state, index.resource); + trace_dump_member(ptr, state, count_from_stream_output); + + if (!state->indirect) { + trace_dump_member(ptr, state, indirect); + } else { + trace_dump_member(uint, state, indirect->offset); + trace_dump_member(uint, state, indirect->stride); + trace_dump_member(uint, state, indirect->draw_count); + trace_dump_member(uint, state, indirect->indirect_draw_count_offset); + trace_dump_member(ptr, state, indirect->buffer); + trace_dump_member(ptr, state, indirect->indirect_draw_count); + } + + trace_dump_struct_end(); +} + +void trace_dump_blit_info(const struct pipe_blit_info *info) +{ + char mask[7]; + + if (!trace_dumping_enabled_locked()) + return; + + if (!info) { + trace_dump_null(); + return; + } + + trace_dump_struct_begin("pipe_blit_info"); + + trace_dump_member_begin("dst"); + trace_dump_struct_begin("dst"); + trace_dump_member(ptr, &info->dst, resource); + trace_dump_member(uint, &info->dst, level); + trace_dump_member(format, &info->dst, format); + trace_dump_member_begin("box"); + trace_dump_box(&info->dst.box); + trace_dump_member_end(); + trace_dump_struct_end(); + trace_dump_member_end(); + + trace_dump_member_begin("src"); + trace_dump_struct_begin("src"); + trace_dump_member(ptr, &info->src, resource); + trace_dump_member(uint, &info->src, level); + trace_dump_member(format, &info->src, format); + trace_dump_member_begin("box"); + trace_dump_box(&info->src.box); + trace_dump_member_end(); + trace_dump_struct_end(); + trace_dump_member_end(); + + mask[0] = (info->mask & PIPE_MASK_R) ? 'R' : '-'; + mask[1] = (info->mask & PIPE_MASK_G) ? 'G' : '-'; + mask[2] = (info->mask & PIPE_MASK_B) ? 'B' : '-'; + mask[3] = (info->mask & PIPE_MASK_A) ? 'A' : '-'; + mask[4] = (info->mask & PIPE_MASK_Z) ? 'Z' : '-'; + mask[5] = (info->mask & PIPE_MASK_S) ? 'S' : '-'; + mask[6] = 0; + + trace_dump_member_begin("mask"); + trace_dump_string(mask); + trace_dump_member_end(); + trace_dump_member(uint, info, filter); + + trace_dump_member(bool, info, scissor_enable); + trace_dump_member_begin("scissor"); + trace_dump_scissor_state(&info->scissor); + trace_dump_member_end(); + + trace_dump_struct_end(); +} + +void +trace_dump_query_result(unsigned query_type, + const union pipe_query_result *result) +{ + if (!trace_dumping_enabled_locked()) + return; + + if (!result) { + trace_dump_null(); + return; + } + + switch (query_type) { + case PIPE_QUERY_OCCLUSION_PREDICATE: + case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE: + case PIPE_QUERY_SO_OVERFLOW_PREDICATE: + case PIPE_QUERY_SO_OVERFLOW_ANY_PREDICATE: + case PIPE_QUERY_GPU_FINISHED: + trace_dump_bool(result->b); + break; + + case PIPE_QUERY_OCCLUSION_COUNTER: + case PIPE_QUERY_TIMESTAMP: + case PIPE_QUERY_TIME_ELAPSED: + case PIPE_QUERY_PRIMITIVES_GENERATED: + case PIPE_QUERY_PRIMITIVES_EMITTED: + trace_dump_uint(result->u64); + break; + + case PIPE_QUERY_SO_STATISTICS: + trace_dump_struct_begin("pipe_query_data_so_statistics"); + trace_dump_member(uint, &result->so_statistics, num_primitives_written); + trace_dump_member(uint, &result->so_statistics, primitives_storage_needed); + trace_dump_struct_end(); + break; + + case PIPE_QUERY_TIMESTAMP_DISJOINT: + trace_dump_struct_begin("pipe_query_data_timestamp_disjoint"); + trace_dump_member(uint, &result->timestamp_disjoint, frequency); + trace_dump_member(bool, &result->timestamp_disjoint, disjoint); + trace_dump_struct_end(); + break; + + case PIPE_QUERY_PIPELINE_STATISTICS: + trace_dump_struct_begin("pipe_query_data_pipeline_statistics"); + trace_dump_member(uint, &result->pipeline_statistics, ia_vertices); + trace_dump_member(uint, &result->pipeline_statistics, ia_primitives); + trace_dump_member(uint, &result->pipeline_statistics, vs_invocations); + trace_dump_member(uint, &result->pipeline_statistics, gs_invocations); + trace_dump_member(uint, &result->pipeline_statistics, gs_primitives); + trace_dump_member(uint, &result->pipeline_statistics, c_invocations); + trace_dump_member(uint, &result->pipeline_statistics, c_primitives); + trace_dump_member(uint, &result->pipeline_statistics, ps_invocations); + trace_dump_member(uint, &result->pipeline_statistics, hs_invocations); + trace_dump_member(uint, &result->pipeline_statistics, ds_invocations); + trace_dump_member(uint, &result->pipeline_statistics, cs_invocations); + trace_dump_struct_end(); + break; + + default: + assert(query_type >= PIPE_QUERY_DRIVER_SPECIFIC); + trace_dump_uint(result->u64); + break; + } +} + +void trace_dump_grid_info(const struct pipe_grid_info *state) +{ + if (!trace_dumping_enabled_locked()) + return; + + if (!state) { + trace_dump_null(); + return; + } + + trace_dump_struct_begin("pipe_grid_info"); + + trace_dump_member(uint, state, pc); + trace_dump_member(ptr, state, input); + + trace_dump_member_begin("block"); + trace_dump_array(uint, state->block, ARRAY_SIZE(state->block)); + trace_dump_member_end(); + + trace_dump_member_begin("grid"); + trace_dump_array(uint, state->grid, ARRAY_SIZE(state->grid)); + trace_dump_member_end(); + + trace_dump_member(ptr, state, indirect); + trace_dump_member(uint, state, indirect_offset); + + trace_dump_struct_end(); +} + diff --git a/src/gallium/auxiliary/driver_trace/tr_dump_state.h b/src/gallium/auxiliary/driver_trace/tr_dump_state.h new file mode 100644 index 00000000000..baff0252f9b --- /dev/null +++ b/src/gallium/auxiliary/driver_trace/tr_dump_state.h @@ -0,0 +1,94 @@ +/************************************************************************** + * + * Copyright 2008 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_DUMP_STATE_H_ +#define TR_DUMP_STATE_H_ + +#include "pipe/p_state.h" +#include "pipe/p_shader_tokens.h" + + +void trace_dump_resource_template(const struct pipe_resource *templat); + +void trace_dump_box(const struct pipe_box *box); + +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_token(const struct tgsi_token *token); + +void trace_dump_shader_state(const struct pipe_shader_state *state); + +void trace_dump_compute_state(const struct pipe_compute_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_stencil_ref(const struct pipe_stencil_ref *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_sampler_view_template(const struct pipe_sampler_view *view, + enum pipe_texture_target target); + +void trace_dump_surface_template(const struct pipe_surface *state, + enum pipe_texture_target target); + +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); + +void trace_dump_constant_buffer(const struct pipe_constant_buffer *state); + +void trace_dump_shader_buffer(const struct pipe_shader_buffer *buffer); + +void trace_dump_draw_info(const struct pipe_draw_info *state); + +void trace_dump_blit_info(const struct pipe_blit_info *); + +void trace_dump_query_result(unsigned query_type, + const union pipe_query_result *result); + +void trace_dump_grid_info(const struct pipe_grid_info *state); + +void trace_dump_image_view(const struct pipe_image_view *view); + +#endif /* TR_STATE_H */ diff --git a/src/gallium/auxiliary/driver_trace/tr_public.h b/src/gallium/auxiliary/driver_trace/tr_public.h new file mode 100644 index 00000000000..b03133f8d97 --- /dev/null +++ b/src/gallium/auxiliary/driver_trace/tr_public.h @@ -0,0 +1,50 @@ +/************************************************************************** + * + * Copyright 2010 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 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 + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + **************************************************************************/ + +#ifndef TR_PUBLIC_H +#define TR_PUBLIC_H + +#include "pipe/p_compiler.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct pipe_screen; +struct pipe_context; + +struct pipe_screen * +trace_screen_create(struct pipe_screen *screen); + +boolean +trace_enabled(void); + +#ifdef __cplusplus +} +#endif + +#endif /* TR_PUBLIC_H */ diff --git a/src/gallium/auxiliary/driver_trace/tr_screen.c b/src/gallium/auxiliary/driver_trace/tr_screen.c new file mode 100644 index 00000000000..d5a81249b51 --- /dev/null +++ b/src/gallium/auxiliary/driver_trace/tr_screen.c @@ -0,0 +1,684 @@ +/************************************************************************** + * + * Copyright 2008 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 "util/u_format.h" +#include "util/u_memory.h" +#include "util/simple_list.h" + +#include "tr_dump.h" +#include "tr_dump_defines.h" +#include "tr_dump_state.h" +#include "tr_texture.h" +#include "tr_context.h" +#include "tr_screen.h" +#include "tr_public.h" + + +static boolean trace = 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 const char * +trace_screen_get_device_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_device_vendor"); + + trace_dump_arg(ptr, screen); + + result = screen->get_device_vendor(screen); + + trace_dump_ret(string, result); + + trace_dump_call_end(); + + return result; +} + + +static struct disk_cache * +trace_screen_get_disk_shader_cache(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", "get_disk_shader_cache"); + + trace_dump_arg(ptr, screen); + + struct disk_cache *result = screen->get_disk_shader_cache(screen); + + trace_dump_ret(ptr, result); + + trace_dump_call_end(); + + return result; +} + + +static int +trace_screen_get_param(struct pipe_screen *_screen, + enum pipe_cap 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 int +trace_screen_get_shader_param(struct pipe_screen *_screen, + enum pipe_shader_type shader, + enum pipe_shader_cap 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_shader_param"); + + trace_dump_arg(ptr, screen); + trace_dump_arg(uint, shader); + trace_dump_arg(int, param); + + result = screen->get_shader_param(screen, shader, param); + + trace_dump_ret(int, result); + + trace_dump_call_end(); + + return result; +} + + +static float +trace_screen_get_paramf(struct pipe_screen *_screen, + enum pipe_capf 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 int +trace_screen_get_compute_param(struct pipe_screen *_screen, + enum pipe_shader_ir ir_type, + enum pipe_compute_cap param, void *data) +{ + struct trace_screen *tr_scr = trace_screen(_screen); + struct pipe_screen *screen = tr_scr->screen; + int result; + + trace_dump_call_begin("pipe_screen", "get_compute_param"); + + trace_dump_arg(ptr, screen); + trace_dump_arg(int, ir_type); + trace_dump_arg(int, param); + trace_dump_arg(ptr, data); + + result = screen->get_compute_param(screen, ir_type, param, data); + + trace_dump_ret(int, 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 sample_count, + unsigned tex_usage) +{ + 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, sample_count); + trace_dump_arg(uint, tex_usage); + + result = screen->is_format_supported(screen, format, target, sample_count, + tex_usage); + + trace_dump_ret(bool, result); + + trace_dump_call_end(); + + return result; +} + + +static struct pipe_context * +trace_screen_context_create(struct pipe_screen *_screen, void *priv, + unsigned flags) +{ + struct trace_screen *tr_scr = trace_screen(_screen); + struct pipe_screen *screen = tr_scr->screen; + struct pipe_context *result; + + trace_dump_call_begin("pipe_screen", "context_create"); + + trace_dump_arg(ptr, screen); + trace_dump_arg(ptr, priv); + trace_dump_arg(uint, flags); + + result = screen->context_create(screen, priv, flags); + + trace_dump_ret(ptr, result); + + trace_dump_call_end(); + + result = trace_context_create(tr_scr, result); + + return result; +} + + +static void +trace_screen_flush_frontbuffer(struct pipe_screen *_screen, + struct pipe_resource *resource, + unsigned level, unsigned layer, + void *context_private, + struct pipe_box *sub_box) +{ + struct trace_screen *tr_scr = trace_screen(_screen); + struct pipe_screen *screen = tr_scr->screen; + + trace_dump_call_begin("pipe_screen", "flush_frontbuffer"); + + trace_dump_arg(ptr, screen); + trace_dump_arg(ptr, resource); + trace_dump_arg(uint, level); + trace_dump_arg(uint, layer); + /* XXX: hide, as there is nothing we can do with this + trace_dump_arg(ptr, context_private); + */ + + screen->flush_frontbuffer(screen, resource, level, layer, context_private, sub_box); + + trace_dump_call_end(); +} + + +static void +trace_screen_get_driver_uuid(struct pipe_screen *_screen, char *uuid) +{ + struct pipe_screen *screen = trace_screen(_screen)->screen; + + trace_dump_call_begin("pipe_screen", "get_driver_uuid"); + trace_dump_arg(ptr, screen); + + screen->get_driver_uuid(screen, uuid); + + trace_dump_ret(string, uuid); + trace_dump_call_end(); +} + +static void +trace_screen_get_device_uuid(struct pipe_screen *_screen, char *uuid) +{ + struct pipe_screen *screen = trace_screen(_screen)->screen; + + trace_dump_call_begin("pipe_screen", "get_device_uuid"); + trace_dump_arg(ptr, screen); + + screen->get_device_uuid(screen, uuid); + + trace_dump_ret(string, uuid); + trace_dump_call_end(); +} + + +/******************************************************************** + * texture + */ + + +static struct pipe_resource * +trace_screen_resource_create(struct pipe_screen *_screen, + const struct pipe_resource *templat) +{ + struct trace_screen *tr_scr = trace_screen(_screen); + struct pipe_screen *screen = tr_scr->screen; + struct pipe_resource *result; + + trace_dump_call_begin("pipe_screen", "resource_create"); + + trace_dump_arg(ptr, screen); + trace_dump_arg(resource_template, templat); + + result = screen->resource_create(screen, templat); + + trace_dump_ret(ptr, result); + + trace_dump_call_end(); + + if (result) + result->screen = _screen; + return result; +} + +static struct pipe_resource * +trace_screen_resource_from_handle(struct pipe_screen *_screen, + const struct pipe_resource *templ, + struct winsys_handle *handle, + unsigned usage) +{ + struct trace_screen *tr_screen = trace_screen(_screen); + struct pipe_screen *screen = tr_screen->screen; + struct pipe_resource *result; + + /* TODO trace call */ + + result = screen->resource_from_handle(screen, templ, handle, usage); + + if (result) + result->screen = _screen; + return result; +} + +static bool +trace_screen_check_resource_capability(struct pipe_screen *_screen, + struct pipe_resource *resource, + unsigned bind) +{ + struct pipe_screen *screen = trace_screen(_screen)->screen; + + return screen->check_resource_capability(screen, resource, bind); +} + +static boolean +trace_screen_resource_get_handle(struct pipe_screen *_screen, + struct pipe_context *_pipe, + struct pipe_resource *resource, + struct winsys_handle *handle, + unsigned usage) +{ + struct trace_screen *tr_screen = trace_screen(_screen); + struct trace_context *tr_pipe = _pipe ? trace_context(_pipe) : NULL; + struct pipe_screen *screen = tr_screen->screen; + + /* TODO trace call */ + + return screen->resource_get_handle(screen, tr_pipe ? tr_pipe->pipe : NULL, + resource, handle, usage); +} + +static struct pipe_resource * +trace_screen_resource_from_memobj(struct pipe_screen *_screen, + const struct pipe_resource *templ, + struct pipe_memory_object *memobj, + uint64_t offset) +{ + struct pipe_screen *screen = trace_screen(_screen)->screen; + + trace_dump_call_begin("pipe_screen", "resource_from_memobj"); + trace_dump_arg(ptr, screen); + trace_dump_arg(resource_template, templ); + trace_dump_arg(ptr, memobj); + trace_dump_arg(uint, offset); + + struct pipe_resource *res = + screen->resource_from_memobj(screen, templ, memobj, offset); + + if (!res) + return NULL; + res->screen = _screen; + + trace_dump_ret(ptr, res); + trace_dump_call_end(); + return res; +} + +static void +trace_screen_resource_changed(struct pipe_screen *_screen, + struct pipe_resource *resource) +{ + struct trace_screen *tr_scr = trace_screen(_screen); + struct pipe_screen *screen = tr_scr->screen; + + trace_dump_call_begin("pipe_screen", "resource_changed"); + + trace_dump_arg(ptr, screen); + trace_dump_arg(ptr, resource); + + screen->resource_changed(screen, resource); + + trace_dump_call_end(); +} + +static void +trace_screen_resource_destroy(struct pipe_screen *_screen, + struct pipe_resource *resource) +{ + struct trace_screen *tr_scr = trace_screen(_screen); + struct pipe_screen *screen = tr_scr->screen; + + /* Don't trace this, because due to the lack of pipe_resource wrapping, + * we can get this call from inside of driver calls, which would try + * to lock an already-locked mutex. + */ + screen->resource_destroy(screen, resource); +} + + +/******************************************************************** + * 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 boolean +trace_screen_fence_finish(struct pipe_screen *_screen, + struct pipe_context *_ctx, + struct pipe_fence_handle *fence, + uint64_t timeout) +{ + struct trace_screen *tr_scr = trace_screen(_screen); + struct pipe_screen *screen = tr_scr->screen; + struct pipe_context *ctx = _ctx ? trace_context(_ctx)->pipe : NULL; + int result; + + trace_dump_call_begin("pipe_screen", "fence_finish"); + + trace_dump_arg(ptr, screen); + trace_dump_arg(ptr, ctx); + trace_dump_arg(ptr, fence); + trace_dump_arg(uint, timeout); + + result = screen->fence_finish(screen, ctx, fence, timeout); + + trace_dump_ret(bool, result); + + trace_dump_call_end(); + + return result; +} + + +/******************************************************************** + * memobj + */ + +static struct pipe_memory_object * +trace_screen_memobj_create_from_handle(struct pipe_screen *_screen, + struct winsys_handle *handle, + bool dedicated) +{ + struct pipe_screen *screen = trace_screen(_screen)->screen; + + trace_dump_call_begin("pipe_screen", "memobj_create_from_handle"); + trace_dump_arg(ptr, screen); + trace_dump_arg(ptr, handle); + trace_dump_arg(bool, dedicated); + + struct pipe_memory_object *res = + screen->memobj_create_from_handle(screen, handle, dedicated); + + trace_dump_ret(ptr, res); + trace_dump_call_end(); + + return res; +} + +static void +trace_screen_memobj_destroy(struct pipe_screen *_screen, + struct pipe_memory_object *memobj) +{ + struct pipe_screen *screen = trace_screen(_screen)->screen; + + trace_dump_call_begin("pipe_screen", "memobj_destroy"); + trace_dump_arg(ptr, screen); + trace_dump_arg(ptr, memobj); + trace_dump_call_end(); + + screen->memobj_destroy(screen, memobj); +} + + +/******************************************************************** + * screen + */ + +static uint64_t +trace_screen_get_timestamp(struct pipe_screen *_screen) +{ + struct trace_screen *tr_scr = trace_screen(_screen); + struct pipe_screen *screen = tr_scr->screen; + uint64_t result; + + trace_dump_call_begin("pipe_screen", "get_timestamp"); + trace_dump_arg(ptr, screen); + + result = screen->get_timestamp(screen); + + trace_dump_ret(uint, result); + trace_dump_call_end(); + + return result; +} + +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(); + + screen->destroy(screen); + + FREE(tr_scr); +} + +boolean +trace_enabled(void) +{ + static boolean firstrun = TRUE; + + if (!firstrun) + return trace; + firstrun = FALSE; + + if(trace_dump_trace_begin()) { + trace_dumping_start(); + trace = TRUE; + } + + return trace; +} + +struct pipe_screen * +trace_screen_create(struct pipe_screen *screen) +{ + struct trace_screen *tr_scr; + + if (!trace_enabled()) + goto error1; + + trace_dump_call_begin("", "pipe_screen_create"); + + tr_scr = CALLOC_STRUCT(trace_screen); + if (!tr_scr) + goto error2; + +#define SCR_INIT(_member) \ + tr_scr->base._member = screen->_member ? trace_screen_##_member : NULL + + 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_device_vendor = trace_screen_get_device_vendor; + SCR_INIT(get_disk_shader_cache); + tr_scr->base.get_param = trace_screen_get_param; + tr_scr->base.get_shader_param = trace_screen_get_shader_param; + tr_scr->base.get_paramf = trace_screen_get_paramf; + tr_scr->base.get_compute_param = trace_screen_get_compute_param; + tr_scr->base.is_format_supported = trace_screen_is_format_supported; + assert(screen->context_create); + tr_scr->base.context_create = trace_screen_context_create; + tr_scr->base.resource_create = trace_screen_resource_create; + tr_scr->base.resource_from_handle = trace_screen_resource_from_handle; + SCR_INIT(check_resource_capability); + tr_scr->base.resource_get_handle = trace_screen_resource_get_handle; + SCR_INIT(resource_from_memobj); + SCR_INIT(resource_changed); + tr_scr->base.resource_destroy = trace_screen_resource_destroy; + tr_scr->base.fence_reference = trace_screen_fence_reference; + tr_scr->base.fence_finish = trace_screen_fence_finish; + SCR_INIT(memobj_create_from_handle); + SCR_INIT(memobj_destroy); + tr_scr->base.flush_frontbuffer = trace_screen_flush_frontbuffer; + tr_scr->base.get_timestamp = trace_screen_get_timestamp; + SCR_INIT(get_driver_uuid); + SCR_INIT(get_device_uuid); + + tr_scr->screen = screen; + + trace_dump_ret(ptr, screen); + trace_dump_call_end(); + + return &tr_scr->base; + +error2: + trace_dump_ret(ptr, screen); + trace_dump_call_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/auxiliary/driver_trace/tr_screen.h b/src/gallium/auxiliary/driver_trace/tr_screen.h new file mode 100644 index 00000000000..65ea4fb6a43 --- /dev/null +++ b/src/gallium/auxiliary/driver_trace/tr_screen.h @@ -0,0 +1,65 @@ +/************************************************************************** + * + * Copyright 2008 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_SCREEN_H_ +#define TR_SCREEN_H_ + + +#include "pipe/p_screen.h" +#include "os/os_thread.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * 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 dumped before being used by the pipe context. + */ +#define TRACE_FLAG_USER_BUFFER (1 << 31) + + +struct trace_screen +{ + struct pipe_screen base; + + struct pipe_screen *screen; +}; + + +struct trace_screen * +trace_screen(struct pipe_screen *screen); + + +#ifdef __cplusplus +} +#endif + +#endif /* TR_SCREEN_H_ */ diff --git a/src/gallium/auxiliary/driver_trace/tr_texture.c b/src/gallium/auxiliary/driver_trace/tr_texture.c new file mode 100644 index 00000000000..fe0c7b52c9b --- /dev/null +++ b/src/gallium/auxiliary/driver_trace/tr_texture.c @@ -0,0 +1,119 @@ +/************************************************************************** + * + * Copyright 2008 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 "util/u_inlines.h" +#include "util/u_hash_table.h" +#include "util/u_memory.h" +#include "util/simple_list.h" + +#include "tr_screen.h" +#include "tr_context.h" +#include "tr_texture.h" + + +struct pipe_surface * +trace_surf_create(struct trace_context *tr_ctx, + struct pipe_resource *res, + struct pipe_surface *surface) +{ + struct trace_surface *tr_surf; + + if (!surface) + goto error; + + assert(surface->texture == res); + + tr_surf = CALLOC_STRUCT(trace_surface); + if (!tr_surf) + goto error; + + memcpy(&tr_surf->base, surface, sizeof(struct pipe_surface)); + tr_surf->base.context = &tr_ctx->base; + + pipe_reference_init(&tr_surf->base.reference, 1); + tr_surf->base.texture = NULL; + pipe_resource_reference(&tr_surf->base.texture, res); + tr_surf->surface = surface; + + return &tr_surf->base; + +error: + pipe_surface_reference(&surface, NULL); + return NULL; +} + + +void +trace_surf_destroy(struct trace_surface *tr_surf) +{ + trace_context_check(tr_surf->base.context); + pipe_resource_reference(&tr_surf->base.texture, NULL); + pipe_surface_reference(&tr_surf->surface, NULL); + FREE(tr_surf); +} + + +struct pipe_transfer * +trace_transfer_create(struct trace_context *tr_ctx, + struct pipe_resource *res, + struct pipe_transfer *transfer) +{ + struct trace_transfer *tr_trans; + + if (!transfer) + goto error; + + assert(transfer->resource == res); + + tr_trans = CALLOC_STRUCT(trace_transfer); + if (!tr_trans) + goto error; + + memcpy(&tr_trans->base, transfer, sizeof(struct pipe_transfer)); + + tr_trans->base.resource = NULL; + tr_trans->transfer = transfer; + + pipe_resource_reference(&tr_trans->base.resource, res); + assert(tr_trans->base.resource == res); + + return &tr_trans->base; + +error: + tr_ctx->pipe->transfer_unmap(tr_ctx->pipe, transfer); + return NULL; +} + + +void +trace_transfer_destroy(struct trace_context *tr_context, + struct trace_transfer *tr_trans) +{ + pipe_resource_reference(&tr_trans->base.resource, NULL); + FREE(tr_trans); +} + diff --git a/src/gallium/auxiliary/driver_trace/tr_texture.h b/src/gallium/auxiliary/driver_trace/tr_texture.h new file mode 100644 index 00000000000..e5dfc53fdb0 --- /dev/null +++ b/src/gallium/auxiliary/driver_trace/tr_texture.h @@ -0,0 +1,122 @@ +/************************************************************************** + * + * Copyright 2008 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_TEXTURE_H_ +#define TR_TEXTURE_H_ + + +#include "pipe/p_compiler.h" +#include "pipe/p_state.h" + +#include "tr_screen.h" + +struct trace_context; + + +struct tr_list +{ + struct tr_list *next; + struct tr_list *prev; +}; + +struct trace_surface +{ + struct pipe_surface base; + + struct pipe_surface *surface; + + struct tr_list list; +}; + + +struct trace_sampler_view +{ + struct pipe_sampler_view base; + + struct pipe_sampler_view *sampler_view; +}; + + +struct trace_transfer +{ + struct pipe_transfer base; + + struct pipe_transfer *transfer; + struct pipe_context *pipe; + + struct tr_list list; + + void *map; +}; + + +static inline struct trace_surface * +trace_surface(struct pipe_surface *surface) +{ + if (!surface) + return NULL; + return (struct trace_surface *)surface; +} + + +static inline struct trace_sampler_view * +trace_sampler_view(struct pipe_sampler_view *sampler_view) +{ + if (!sampler_view) + return NULL; + return (struct trace_sampler_view *)sampler_view; +} + + +static inline struct trace_transfer * +trace_transfer(struct pipe_transfer *transfer) +{ + if (!transfer) + return NULL; + return (struct trace_transfer *)transfer; +} + + +struct pipe_surface * +trace_surf_create(struct trace_context *tr_ctx, + struct pipe_resource *tr_res, + struct pipe_surface *surface); + +void +trace_surf_destroy(struct trace_surface *tr_surf); + +struct pipe_transfer * +trace_transfer_create(struct trace_context *tr_ctx, + struct pipe_resource *tr_res, + struct pipe_transfer *transfer); + +void +trace_transfer_destroy(struct trace_context *tr_ctx, + struct trace_transfer *tr_trans); + + +#endif /* TR_TEXTURE_H_ */ diff --git a/src/gallium/auxiliary/driver_trace/trace.xsl b/src/gallium/auxiliary/driver_trace/trace.xsl new file mode 100644 index 00000000000..12458ae3287 --- /dev/null +++ b/src/gallium/auxiliary/driver_trace/trace.xsl @@ -0,0 +1,196 @@ +<?xml version="1.0"?> + +<!-- + +Copyright 2008 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. + +!--> + +<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> |