diff options
author | Marek Olšák <[email protected]> | 2018-04-07 14:01:12 -0400 |
---|---|---|
committer | Marek Olšák <[email protected]> | 2018-04-13 14:08:14 -0400 |
commit | 6ff0c6f4ebcb87ea6c6fe5a4ba90b548f666067d (patch) | |
tree | 30926986da28bb0b67b857d8f2cf7eeaa77f8773 /src/gallium/auxiliary/driver_rbug | |
parent | 918b798668c5465d85ca542423e4cf525dc79b31 (diff) |
gallium: move ddebug, noop, rbug, trace to auxiliary to improve build times
which also simplifies the build scripts.
Diffstat (limited to 'src/gallium/auxiliary/driver_rbug')
-rw-r--r-- | src/gallium/auxiliary/driver_rbug/README | 44 | ||||
-rw-r--r-- | src/gallium/auxiliary/driver_rbug/rbug_context.c | 1274 | ||||
-rw-r--r-- | src/gallium/auxiliary/driver_rbug/rbug_context.h | 104 | ||||
-rw-r--r-- | src/gallium/auxiliary/driver_rbug/rbug_core.c | 888 | ||||
-rw-r--r-- | src/gallium/auxiliary/driver_rbug/rbug_objects.c | 250 | ||||
-rw-r--r-- | src/gallium/auxiliary/driver_rbug/rbug_objects.h | 228 | ||||
-rw-r--r-- | src/gallium/auxiliary/driver_rbug/rbug_public.h | 48 | ||||
-rw-r--r-- | src/gallium/auxiliary/driver_rbug/rbug_screen.c | 343 | ||||
-rw-r--r-- | src/gallium/auxiliary/driver_rbug/rbug_screen.h | 100 |
9 files changed, 3279 insertions, 0 deletions
diff --git a/src/gallium/auxiliary/driver_rbug/README b/src/gallium/auxiliary/driver_rbug/README new file mode 100644 index 00000000000..0edf0ad89de --- /dev/null +++ b/src/gallium/auxiliary/driver_rbug/README @@ -0,0 +1,44 @@ + RBUG PIPE DRIVER + + += About = + +This directory contains a Gallium3D remote debugger pipe driver. +It provides remote debugging functionality. + + += Usage = + +Do + + GALLIUM_RBUG=true progs/trivial/tri + +which should open gallium remote debugging session. While the program is running +you can launch the small remote debugging application from progs/rbug. More +information is in that directory. Also for a gui see: + + http://cgit.freedesktop.org/mesa/rbug-gui + + += Integrating = + +You can integrate the rbug 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 rbug screen is then created by doing + + rbug_screen = rbug_screen_create(real_screen); + +You can then simply use rbug_screen instead of real_screen. + +You can create as many contexts you wish from rbug_screen::context_create they +are automatically wrapped by rbug_screen. + + +-- +Jose Fonseca <[email protected]> +Jakob Bornecrantz <[email protected]> diff --git a/src/gallium/auxiliary/driver_rbug/rbug_context.c b/src/gallium/auxiliary/driver_rbug/rbug_context.c new file mode 100644 index 00000000000..e1f3c4f2844 --- /dev/null +++ b/src/gallium/auxiliary/driver_rbug/rbug_context.c @@ -0,0 +1,1274 @@ +/************************************************************************** + * + * 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 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_context.h" +#include "util/u_memory.h" +#include "util/u_inlines.h" +#include "util/simple_list.h" + +#include "rbug/rbug_context.h" + +#include "rbug_context.h" +#include "rbug_objects.h" + + +static void +rbug_destroy(struct pipe_context *_pipe) +{ + struct rbug_screen *rb_screen = rbug_screen(_pipe->screen); + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + + rbug_screen_remove_from_list(rb_screen, contexts, rb_pipe); + + mtx_lock(&rb_pipe->call_mutex); + pipe->destroy(pipe); + rb_pipe->pipe = NULL; + mtx_unlock(&rb_pipe->call_mutex); + + FREE(rb_pipe); +} + +static void +rbug_draw_block_locked(struct rbug_context *rb_pipe, int flag) +{ + + if (rb_pipe->draw_blocker & flag) { + rb_pipe->draw_blocked |= flag; + } else if ((rb_pipe->draw_rule.blocker & flag) && + (rb_pipe->draw_blocker & RBUG_BLOCK_RULE)) { + unsigned k; + boolean block = FALSE; + unsigned sh; + + debug_printf("%s (%p %p) (%p %p) (%p %u) (%p %u)\n", __FUNCTION__, + (void *) rb_pipe->draw_rule.shader[PIPE_SHADER_FRAGMENT], + (void *) rb_pipe->curr.shader[PIPE_SHADER_FRAGMENT], + (void *) rb_pipe->draw_rule.shader[PIPE_SHADER_VERTEX], + (void *) rb_pipe->curr.shader[PIPE_SHADER_VERTEX], + (void *) rb_pipe->draw_rule.surf, 0, + (void *) rb_pipe->draw_rule.texture, 0); + for (sh = 0; sh < PIPE_SHADER_TYPES; sh++) { + if (rb_pipe->draw_rule.shader[sh] && + rb_pipe->draw_rule.shader[sh] == rb_pipe->curr.shader[sh]) + block = TRUE; + } + + if (rb_pipe->draw_rule.surf && + rb_pipe->draw_rule.surf == rb_pipe->curr.zsbuf) + block = TRUE; + if (rb_pipe->draw_rule.surf) + for (k = 0; k < rb_pipe->curr.nr_cbufs; k++) + if (rb_pipe->draw_rule.surf == rb_pipe->curr.cbufs[k]) + block = TRUE; + if (rb_pipe->draw_rule.texture) { + for (sh = 0; sh < ARRAY_SIZE(rb_pipe->curr.num_views); sh++) { + for (k = 0; k < rb_pipe->curr.num_views[sh]; k++) { + if (rb_pipe->draw_rule.texture == rb_pipe->curr.texs[sh][k]) { + block = TRUE; + sh = PIPE_SHADER_TYPES; /* to break out of both loops */ + break; + } + } + } + } + + if (block) + rb_pipe->draw_blocked |= (flag | RBUG_BLOCK_RULE); + } + + if (rb_pipe->draw_blocked) + rbug_notify_draw_blocked(rb_pipe); + + /* wait for rbug to clear the blocked flag */ + while (rb_pipe->draw_blocked & flag) { + rb_pipe->draw_blocked |= flag; + cnd_wait(&rb_pipe->draw_cond, &rb_pipe->draw_mutex); + } + +} + +static void +rbug_draw_vbo(struct pipe_context *_pipe, const struct pipe_draw_info *info) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + + mtx_lock(&rb_pipe->draw_mutex); + rbug_draw_block_locked(rb_pipe, RBUG_BLOCK_BEFORE); + + mtx_lock(&rb_pipe->call_mutex); + /* XXX loop over PIPE_SHADER_x here */ + if (!(rb_pipe->curr.shader[PIPE_SHADER_FRAGMENT] && rb_pipe->curr.shader[PIPE_SHADER_FRAGMENT]->disabled) && + !(rb_pipe->curr.shader[PIPE_SHADER_GEOMETRY] && rb_pipe->curr.shader[PIPE_SHADER_GEOMETRY]->disabled) && + !(rb_pipe->curr.shader[PIPE_SHADER_VERTEX] && rb_pipe->curr.shader[PIPE_SHADER_VERTEX]->disabled)) + pipe->draw_vbo(pipe, info); + mtx_unlock(&rb_pipe->call_mutex); + + rbug_draw_block_locked(rb_pipe, RBUG_BLOCK_AFTER); + mtx_unlock(&rb_pipe->draw_mutex); +} + +static struct pipe_query * +rbug_create_query(struct pipe_context *_pipe, + unsigned query_type, + unsigned index) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + struct pipe_query *query; + + mtx_lock(&rb_pipe->call_mutex); + query = pipe->create_query(pipe, + query_type, + index); + mtx_unlock(&rb_pipe->call_mutex); + return query; +} + +static void +rbug_destroy_query(struct pipe_context *_pipe, + struct pipe_query *query) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + + mtx_lock(&rb_pipe->call_mutex); + pipe->destroy_query(pipe, + query); + mtx_unlock(&rb_pipe->call_mutex); +} + +static boolean +rbug_begin_query(struct pipe_context *_pipe, + struct pipe_query *query) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + boolean ret; + + mtx_lock(&rb_pipe->call_mutex); + ret = pipe->begin_query(pipe, query); + mtx_unlock(&rb_pipe->call_mutex); + return ret; +} + +static bool +rbug_end_query(struct pipe_context *_pipe, + struct pipe_query *query) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + bool ret; + + mtx_lock(&rb_pipe->call_mutex); + ret = pipe->end_query(pipe, + query); + mtx_unlock(&rb_pipe->call_mutex); + + return ret; +} + +static boolean +rbug_get_query_result(struct pipe_context *_pipe, + struct pipe_query *query, + boolean wait, + union pipe_query_result *result) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + boolean ret; + + mtx_lock(&rb_pipe->call_mutex); + ret = pipe->get_query_result(pipe, + query, + wait, + result); + mtx_unlock(&rb_pipe->call_mutex); + + return ret; +} + +static void +rbug_set_active_query_state(struct pipe_context *_pipe, boolean enable) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + + mtx_lock(&rb_pipe->call_mutex); + pipe->set_active_query_state(pipe, enable); + mtx_unlock(&rb_pipe->call_mutex); +} + +static void * +rbug_create_blend_state(struct pipe_context *_pipe, + const struct pipe_blend_state *blend) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + void *ret; + + mtx_lock(&rb_pipe->call_mutex); + ret = pipe->create_blend_state(pipe, + blend); + mtx_unlock(&rb_pipe->call_mutex); + + return ret; +} + +static void +rbug_bind_blend_state(struct pipe_context *_pipe, + void *blend) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + + mtx_lock(&rb_pipe->call_mutex); + pipe->bind_blend_state(pipe, + blend); + mtx_unlock(&rb_pipe->call_mutex); +} + +static void +rbug_delete_blend_state(struct pipe_context *_pipe, + void *blend) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + + mtx_lock(&rb_pipe->call_mutex); + pipe->delete_blend_state(pipe, + blend); + mtx_unlock(&rb_pipe->call_mutex); +} + +static void * +rbug_create_sampler_state(struct pipe_context *_pipe, + const struct pipe_sampler_state *sampler) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + void *ret; + + mtx_lock(&rb_pipe->call_mutex); + ret = pipe->create_sampler_state(pipe, + sampler); + mtx_unlock(&rb_pipe->call_mutex); + + return ret; +} + +static void +rbug_bind_sampler_states(struct pipe_context *_pipe, + enum pipe_shader_type shader, + unsigned start, unsigned count, + void **samplers) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + + mtx_lock(&rb_pipe->call_mutex); + pipe->bind_sampler_states(pipe, shader, start, count, samplers); + mtx_unlock(&rb_pipe->call_mutex); +} + +static void +rbug_delete_sampler_state(struct pipe_context *_pipe, + void *sampler) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + + mtx_lock(&rb_pipe->call_mutex); + pipe->delete_sampler_state(pipe, + sampler); + mtx_unlock(&rb_pipe->call_mutex); +} + +static void * +rbug_create_rasterizer_state(struct pipe_context *_pipe, + const struct pipe_rasterizer_state *rasterizer) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + void *ret; + + mtx_lock(&rb_pipe->call_mutex); + ret = pipe->create_rasterizer_state(pipe, + rasterizer); + mtx_unlock(&rb_pipe->call_mutex); + + return ret; +} + +static void +rbug_bind_rasterizer_state(struct pipe_context *_pipe, + void *rasterizer) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + + mtx_lock(&rb_pipe->call_mutex); + pipe->bind_rasterizer_state(pipe, + rasterizer); + mtx_unlock(&rb_pipe->call_mutex); +} + +static void +rbug_delete_rasterizer_state(struct pipe_context *_pipe, + void *rasterizer) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + + mtx_lock(&rb_pipe->call_mutex); + pipe->delete_rasterizer_state(pipe, + rasterizer); + mtx_unlock(&rb_pipe->call_mutex); +} + +static void * +rbug_create_depth_stencil_alpha_state(struct pipe_context *_pipe, + const struct pipe_depth_stencil_alpha_state *depth_stencil_alpha) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + void *ret; + + mtx_lock(&rb_pipe->call_mutex); + ret = pipe->create_depth_stencil_alpha_state(pipe, + depth_stencil_alpha); + mtx_unlock(&rb_pipe->call_mutex); + + return ret; +} + +static void +rbug_bind_depth_stencil_alpha_state(struct pipe_context *_pipe, + void *depth_stencil_alpha) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + + mtx_lock(&rb_pipe->call_mutex); + pipe->bind_depth_stencil_alpha_state(pipe, + depth_stencil_alpha); + mtx_unlock(&rb_pipe->call_mutex); +} + +static void +rbug_delete_depth_stencil_alpha_state(struct pipe_context *_pipe, + void *depth_stencil_alpha) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + + mtx_lock(&rb_pipe->call_mutex); + pipe->delete_depth_stencil_alpha_state(pipe, + depth_stencil_alpha); + mtx_unlock(&rb_pipe->call_mutex); +} + +static void * +rbug_create_fs_state(struct pipe_context *_pipe, + const struct pipe_shader_state *state) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + void *result; + + mtx_lock(&rb_pipe->call_mutex); + result = pipe->create_fs_state(pipe, state); + mtx_unlock(&rb_pipe->call_mutex); + + if (!result) + return NULL; + + return rbug_shader_create(rb_pipe, state, result, RBUG_SHADER_FRAGMENT); +} + +static void +rbug_bind_fs_state(struct pipe_context *_pipe, + void *_fs) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + void *fs; + + mtx_lock(&rb_pipe->call_mutex); + + fs = rbug_shader_unwrap(_fs); + rb_pipe->curr.shader[PIPE_SHADER_FRAGMENT] = rbug_shader(_fs); + pipe->bind_fs_state(pipe, + fs); + + mtx_unlock(&rb_pipe->call_mutex); +} + +static void +rbug_delete_fs_state(struct pipe_context *_pipe, + void *_fs) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct rbug_shader *rb_shader = rbug_shader(_fs); + + mtx_lock(&rb_pipe->call_mutex); + rbug_shader_destroy(rb_pipe, rb_shader); + mtx_unlock(&rb_pipe->call_mutex); +} + +static void * +rbug_create_vs_state(struct pipe_context *_pipe, + const struct pipe_shader_state *state) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + void *result; + + mtx_lock(&rb_pipe->call_mutex); + result = pipe->create_vs_state(pipe, state); + mtx_unlock(&rb_pipe->call_mutex); + + if (!result) + return NULL; + + return rbug_shader_create(rb_pipe, state, result, RBUG_SHADER_VERTEX); +} + +static void +rbug_bind_vs_state(struct pipe_context *_pipe, + void *_vs) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + void *vs; + + mtx_lock(&rb_pipe->call_mutex); + + vs = rbug_shader_unwrap(_vs); + rb_pipe->curr.shader[PIPE_SHADER_VERTEX] = rbug_shader(_vs); + pipe->bind_vs_state(pipe, + vs); + + mtx_unlock(&rb_pipe->call_mutex); +} + +static void +rbug_delete_vs_state(struct pipe_context *_pipe, + void *_vs) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct rbug_shader *rb_shader = rbug_shader(_vs); + + mtx_unlock(&rb_pipe->call_mutex); + rbug_shader_destroy(rb_pipe, rb_shader); + mtx_unlock(&rb_pipe->call_mutex); +} + +static void * +rbug_create_gs_state(struct pipe_context *_pipe, + const struct pipe_shader_state *state) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + void *result; + + mtx_lock(&rb_pipe->call_mutex); + result = pipe->create_gs_state(pipe, state); + mtx_unlock(&rb_pipe->call_mutex); + + if (!result) + return NULL; + + return rbug_shader_create(rb_pipe, state, result, RBUG_SHADER_GEOM); +} + +static void +rbug_bind_gs_state(struct pipe_context *_pipe, + void *_gs) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + void *gs; + + mtx_lock(&rb_pipe->call_mutex); + + gs = rbug_shader_unwrap(_gs); + rb_pipe->curr.shader[PIPE_SHADER_GEOMETRY] = rbug_shader(_gs); + pipe->bind_gs_state(pipe, + gs); + + mtx_unlock(&rb_pipe->call_mutex); +} + +static void +rbug_delete_gs_state(struct pipe_context *_pipe, + void *_gs) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct rbug_shader *rb_shader = rbug_shader(_gs); + + mtx_lock(&rb_pipe->call_mutex); + rbug_shader_destroy(rb_pipe, rb_shader); + mtx_unlock(&rb_pipe->call_mutex); +} + +static void * +rbug_create_vertex_elements_state(struct pipe_context *_pipe, + unsigned num_elements, + const struct pipe_vertex_element *vertex_elements) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + void *ret; + + mtx_lock(&rb_pipe->call_mutex); + ret = pipe->create_vertex_elements_state(pipe, + num_elements, + vertex_elements); + mtx_unlock(&rb_pipe->call_mutex); + + return ret; +} + +static void +rbug_bind_vertex_elements_state(struct pipe_context *_pipe, + void *velems) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + + mtx_lock(&rb_pipe->call_mutex); + pipe->bind_vertex_elements_state(pipe, + velems); + mtx_unlock(&rb_pipe->call_mutex); +} + +static void +rbug_delete_vertex_elements_state(struct pipe_context *_pipe, + void *velems) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + + mtx_lock(&rb_pipe->call_mutex); + pipe->delete_vertex_elements_state(pipe, + velems); + mtx_unlock(&rb_pipe->call_mutex); +} + +static void +rbug_set_blend_color(struct pipe_context *_pipe, + const struct pipe_blend_color *blend_color) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + + mtx_lock(&rb_pipe->call_mutex); + pipe->set_blend_color(pipe, + blend_color); + mtx_unlock(&rb_pipe->call_mutex); +} + +static void +rbug_set_stencil_ref(struct pipe_context *_pipe, + const struct pipe_stencil_ref *stencil_ref) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + + mtx_lock(&rb_pipe->call_mutex); + pipe->set_stencil_ref(pipe, + stencil_ref); + mtx_unlock(&rb_pipe->call_mutex); +} + +static void +rbug_set_clip_state(struct pipe_context *_pipe, + const struct pipe_clip_state *clip) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + + mtx_lock(&rb_pipe->call_mutex); + pipe->set_clip_state(pipe, + clip); + mtx_unlock(&rb_pipe->call_mutex); +} + +static void +rbug_set_constant_buffer(struct pipe_context *_pipe, + enum pipe_shader_type shader, + uint index, + const struct pipe_constant_buffer *_cb) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + struct pipe_constant_buffer cb; + + /* XXX hmm? unwrap the input state */ + if (_cb) { + cb = *_cb; + cb.buffer = rbug_resource_unwrap(_cb->buffer); + } + + mtx_lock(&rb_pipe->call_mutex); + pipe->set_constant_buffer(pipe, + shader, + index, + _cb ? &cb : NULL); + mtx_unlock(&rb_pipe->call_mutex); +} + +static void +rbug_set_framebuffer_state(struct pipe_context *_pipe, + const struct pipe_framebuffer_state *_state) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + struct pipe_framebuffer_state unwrapped_state; + struct pipe_framebuffer_state *state = NULL; + unsigned i; + + /* must protect curr status */ + mtx_lock(&rb_pipe->call_mutex); + + rb_pipe->curr.nr_cbufs = 0; + memset(rb_pipe->curr.cbufs, 0, sizeof(rb_pipe->curr.cbufs)); + rb_pipe->curr.zsbuf = NULL; + + /* unwrap the input state */ + if (_state) { + memcpy(&unwrapped_state, _state, sizeof(unwrapped_state)); + + rb_pipe->curr.nr_cbufs = _state->nr_cbufs; + for(i = 0; i < _state->nr_cbufs; i++) { + unwrapped_state.cbufs[i] = rbug_surface_unwrap(_state->cbufs[i]); + if (_state->cbufs[i]) + rb_pipe->curr.cbufs[i] = rbug_resource(_state->cbufs[i]->texture); + } + unwrapped_state.zsbuf = rbug_surface_unwrap(_state->zsbuf); + if (_state->zsbuf) + rb_pipe->curr.zsbuf = rbug_resource(_state->zsbuf->texture); + state = &unwrapped_state; + } + + pipe->set_framebuffer_state(pipe, + state); + + mtx_unlock(&rb_pipe->call_mutex); +} + +static void +rbug_set_polygon_stipple(struct pipe_context *_pipe, + const struct pipe_poly_stipple *poly_stipple) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + + mtx_lock(&rb_pipe->call_mutex); + pipe->set_polygon_stipple(pipe, + poly_stipple); + mtx_unlock(&rb_pipe->call_mutex); +} + +static void +rbug_set_scissor_states(struct pipe_context *_pipe, + unsigned start_slot, + unsigned num_scissors, + const struct pipe_scissor_state *scissor) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + + mtx_lock(&rb_pipe->call_mutex); + pipe->set_scissor_states(pipe, start_slot, num_scissors, scissor); + mtx_unlock(&rb_pipe->call_mutex); +} + +static void +rbug_set_viewport_states(struct pipe_context *_pipe, + unsigned start_slot, + unsigned num_viewports, + const struct pipe_viewport_state *viewport) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + + mtx_lock(&rb_pipe->call_mutex); + pipe->set_viewport_states(pipe, start_slot, num_viewports, viewport); + mtx_unlock(&rb_pipe->call_mutex); +} + +static void +rbug_set_sampler_views(struct pipe_context *_pipe, + enum pipe_shader_type shader, + unsigned start, + unsigned num, + struct pipe_sampler_view **_views) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + struct pipe_sampler_view *unwrapped_views[PIPE_MAX_SHADER_SAMPLER_VIEWS]; + struct pipe_sampler_view **views = NULL; + unsigned i; + + assert(start == 0); /* XXX fix */ + + /* must protect curr status */ + mtx_lock(&rb_pipe->call_mutex); + + rb_pipe->curr.num_views[shader] = 0; + memset(rb_pipe->curr.views[shader], 0, sizeof(rb_pipe->curr.views[shader])); + memset(rb_pipe->curr.texs[shader], 0, sizeof(rb_pipe->curr.texs[shader])); + memset(unwrapped_views, 0, sizeof(unwrapped_views)); + + if (_views) { + rb_pipe->curr.num_views[shader] = num; + for (i = 0; i < num; i++) { + rb_pipe->curr.views[shader][i] = rbug_sampler_view(_views[i]); + rb_pipe->curr.texs[shader][i] = rbug_resource(_views[i] ? _views[i]->texture : NULL); + unwrapped_views[i] = rbug_sampler_view_unwrap(_views[i]); + } + views = unwrapped_views; + } + + pipe->set_sampler_views(pipe, shader, start, num, views); + + mtx_unlock(&rb_pipe->call_mutex); +} + +static void +rbug_set_vertex_buffers(struct pipe_context *_pipe, + unsigned start_slot, unsigned num_buffers, + const struct pipe_vertex_buffer *_buffers) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + struct pipe_vertex_buffer unwrapped_buffers[PIPE_MAX_SHADER_INPUTS]; + struct pipe_vertex_buffer *buffers = NULL; + unsigned i; + + mtx_lock(&rb_pipe->call_mutex); + + if (num_buffers && _buffers) { + memcpy(unwrapped_buffers, _buffers, num_buffers * sizeof(*_buffers)); + for (i = 0; i < num_buffers; i++) { + if (!_buffers[i].is_user_buffer) + unwrapped_buffers[i].buffer.resource = + rbug_resource_unwrap(_buffers[i].buffer.resource); + } + buffers = unwrapped_buffers; + } + + pipe->set_vertex_buffers(pipe, start_slot, + num_buffers, + buffers); + + mtx_unlock(&rb_pipe->call_mutex); +} + +static void +rbug_set_sample_mask(struct pipe_context *_pipe, + unsigned sample_mask) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + + mtx_lock(&rb_pipe->call_mutex); + pipe->set_sample_mask(pipe, sample_mask); + mtx_unlock(&rb_pipe->call_mutex); +} + +static struct pipe_stream_output_target * +rbug_create_stream_output_target(struct pipe_context *_pipe, + struct pipe_resource *_res, + unsigned buffer_offset, unsigned buffer_size) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + struct pipe_resource *res = rbug_resource_unwrap(_res); + struct pipe_stream_output_target *target; + + mtx_lock(&rb_pipe->call_mutex); + target = pipe->create_stream_output_target(pipe, res, buffer_offset, + buffer_size); + mtx_unlock(&rb_pipe->call_mutex); + return target; +} + +static void +rbug_stream_output_target_destroy(struct pipe_context *_pipe, + struct pipe_stream_output_target *target) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + + mtx_lock(&rb_pipe->call_mutex); + pipe->stream_output_target_destroy(pipe, target); + mtx_unlock(&rb_pipe->call_mutex); +} + +static void +rbug_set_stream_output_targets(struct pipe_context *_pipe, + unsigned num_targets, + struct pipe_stream_output_target **targets, + const unsigned *offsets) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + + mtx_lock(&rb_pipe->call_mutex); + pipe->set_stream_output_targets(pipe, num_targets, targets, offsets); + mtx_unlock(&rb_pipe->call_mutex); +} + +static void +rbug_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 rbug_context *rb_pipe = rbug_context(_pipe); + struct rbug_resource *rb_resource_dst = rbug_resource(_dst); + struct rbug_resource *rb_resource_src = rbug_resource(_src); + struct pipe_context *pipe = rb_pipe->pipe; + struct pipe_resource *dst = rb_resource_dst->resource; + struct pipe_resource *src = rb_resource_src->resource; + + mtx_lock(&rb_pipe->call_mutex); + pipe->resource_copy_region(pipe, + dst, + dst_level, + dstx, + dsty, + dstz, + src, + src_level, + src_box); + mtx_unlock(&rb_pipe->call_mutex); +} + +static void +rbug_blit(struct pipe_context *_pipe, const struct pipe_blit_info *_blit_info) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct rbug_resource *rb_resource_dst = rbug_resource(_blit_info->dst.resource); + struct rbug_resource *rb_resource_src = rbug_resource(_blit_info->src.resource); + struct pipe_context *pipe = rb_pipe->pipe; + struct pipe_resource *dst = rb_resource_dst->resource; + struct pipe_resource *src = rb_resource_src->resource; + struct pipe_blit_info blit_info; + + blit_info = *_blit_info; + blit_info.dst.resource = dst; + blit_info.src.resource = src; + + mtx_lock(&rb_pipe->call_mutex); + pipe->blit(pipe, &blit_info); + mtx_unlock(&rb_pipe->call_mutex); +} + +static void +rbug_flush_resource(struct pipe_context *_pipe, + struct pipe_resource *_res) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct rbug_resource *rb_resource_res = rbug_resource(_res); + struct pipe_context *pipe = rb_pipe->pipe; + struct pipe_resource *res = rb_resource_res->resource; + + mtx_lock(&rb_pipe->call_mutex); + pipe->flush_resource(pipe, res); + mtx_unlock(&rb_pipe->call_mutex); +} + +static void +rbug_clear(struct pipe_context *_pipe, + unsigned buffers, + const union pipe_color_union *color, + double depth, + unsigned stencil) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + + mtx_lock(&rb_pipe->call_mutex); + pipe->clear(pipe, + buffers, + color, + depth, + stencil); + mtx_unlock(&rb_pipe->call_mutex); +} + +static void +rbug_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 rbug_context *rb_pipe = rbug_context(_pipe); + struct rbug_surface *rb_surface_dst = rbug_surface(_dst); + struct pipe_context *pipe = rb_pipe->pipe; + struct pipe_surface *dst = rb_surface_dst->surface; + + mtx_lock(&rb_pipe->call_mutex); + pipe->clear_render_target(pipe, + dst, + color, + dstx, + dsty, + width, + height, + render_condition_enabled); + mtx_unlock(&rb_pipe->call_mutex); +} + +static void +rbug_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 rbug_context *rb_pipe = rbug_context(_pipe); + struct rbug_surface *rb_surface_dst = rbug_surface(_dst); + struct pipe_context *pipe = rb_pipe->pipe; + struct pipe_surface *dst = rb_surface_dst->surface; + + mtx_lock(&rb_pipe->call_mutex); + pipe->clear_depth_stencil(pipe, + dst, + clear_flags, + depth, + stencil, + dstx, + dsty, + width, + height, + render_condition_enabled); + mtx_unlock(&rb_pipe->call_mutex); +} + +static void +rbug_flush(struct pipe_context *_pipe, + struct pipe_fence_handle **fence, + unsigned flags) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + + mtx_lock(&rb_pipe->call_mutex); + pipe->flush(pipe, fence, flags); + mtx_unlock(&rb_pipe->call_mutex); +} + +static struct pipe_sampler_view * +rbug_context_create_sampler_view(struct pipe_context *_pipe, + struct pipe_resource *_resource, + const struct pipe_sampler_view *templ) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct rbug_resource *rb_resource = rbug_resource(_resource); + struct pipe_context *pipe = rb_pipe->pipe; + struct pipe_resource *resource = rb_resource->resource; + struct pipe_sampler_view *result; + + mtx_lock(&rb_pipe->call_mutex); + result = pipe->create_sampler_view(pipe, + resource, + templ); + mtx_unlock(&rb_pipe->call_mutex); + + if (result) + return rbug_sampler_view_create(rb_pipe, rb_resource, result); + return NULL; +} + +static void +rbug_context_sampler_view_destroy(struct pipe_context *_pipe, + struct pipe_sampler_view *_view) +{ + rbug_sampler_view_destroy(rbug_context(_pipe), + rbug_sampler_view(_view)); +} + +static struct pipe_surface * +rbug_context_create_surface(struct pipe_context *_pipe, + struct pipe_resource *_resource, + const struct pipe_surface *surf_tmpl) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct rbug_resource *rb_resource = rbug_resource(_resource); + struct pipe_context *pipe = rb_pipe->pipe; + struct pipe_resource *resource = rb_resource->resource; + struct pipe_surface *result; + + mtx_lock(&rb_pipe->call_mutex); + result = pipe->create_surface(pipe, + resource, + surf_tmpl); + mtx_unlock(&rb_pipe->call_mutex); + + if (result) + return rbug_surface_create(rb_pipe, rb_resource, result); + return NULL; +} + +static void +rbug_context_surface_destroy(struct pipe_context *_pipe, + struct pipe_surface *_surface) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct rbug_surface *rb_surface = rbug_surface(_surface); + + mtx_lock(&rb_pipe->call_mutex); + rbug_surface_destroy(rb_pipe, + rb_surface); + mtx_unlock(&rb_pipe->call_mutex); +} + + + +static void * +rbug_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 rbug_context *rb_pipe = rbug_context(_context); + struct rbug_resource *rb_resource = rbug_resource(_resource); + struct pipe_context *context = rb_pipe->pipe; + struct pipe_resource *resource = rb_resource->resource; + struct pipe_transfer *result; + void *map; + + mtx_lock(&rb_pipe->call_mutex); + map = context->transfer_map(context, + resource, + level, + usage, + box, &result); + mtx_unlock(&rb_pipe->call_mutex); + + *transfer = rbug_transfer_create(rb_pipe, rb_resource, result); + return *transfer ? map : NULL; +} + +static void +rbug_context_transfer_flush_region(struct pipe_context *_context, + struct pipe_transfer *_transfer, + const struct pipe_box *box) +{ + struct rbug_context *rb_pipe = rbug_context(_context); + struct rbug_transfer *rb_transfer = rbug_transfer(_transfer); + struct pipe_context *context = rb_pipe->pipe; + struct pipe_transfer *transfer = rb_transfer->transfer; + + mtx_lock(&rb_pipe->call_mutex); + context->transfer_flush_region(context, + transfer, + box); + mtx_unlock(&rb_pipe->call_mutex); +} + + +static void +rbug_context_transfer_unmap(struct pipe_context *_context, + struct pipe_transfer *_transfer) +{ + struct rbug_context *rb_pipe = rbug_context(_context); + struct rbug_transfer *rb_transfer = rbug_transfer(_transfer); + struct pipe_context *context = rb_pipe->pipe; + struct pipe_transfer *transfer = rb_transfer->transfer; + + mtx_lock(&rb_pipe->call_mutex); + context->transfer_unmap(context, + transfer); + rbug_transfer_destroy(rb_pipe, + rb_transfer); + mtx_unlock(&rb_pipe->call_mutex); +} + + +static void +rbug_context_buffer_subdata(struct pipe_context *_context, + struct pipe_resource *_resource, + unsigned usage, unsigned offset, + unsigned size, const void *data) +{ + struct rbug_context *rb_pipe = rbug_context(_context); + struct rbug_resource *rb_resource = rbug_resource(_resource); + struct pipe_context *context = rb_pipe->pipe; + struct pipe_resource *resource = rb_resource->resource; + + mtx_lock(&rb_pipe->call_mutex); + context->buffer_subdata(context, resource, usage, offset, size, data); + mtx_unlock(&rb_pipe->call_mutex); +} + + +static void +rbug_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 rbug_context *rb_pipe = rbug_context(_context); + struct rbug_resource *rb_resource = rbug_resource(_resource); + struct pipe_context *context = rb_pipe->pipe; + struct pipe_resource *resource = rb_resource->resource; + + mtx_lock(&rb_pipe->call_mutex); + context->texture_subdata(context, + resource, + level, + usage, + box, + data, + stride, + layer_stride); + mtx_unlock(&rb_pipe->call_mutex); +} + + +struct pipe_context * +rbug_context_create(struct pipe_screen *_screen, struct pipe_context *pipe) +{ + struct rbug_context *rb_pipe; + struct rbug_screen *rb_screen = rbug_screen(_screen); + + if (!rb_screen) + return NULL; + + rb_pipe = CALLOC_STRUCT(rbug_context); + if (!rb_pipe) + return NULL; + + (void) mtx_init(&rb_pipe->draw_mutex, mtx_plain); + cnd_init(&rb_pipe->draw_cond); + (void) mtx_init(&rb_pipe->call_mutex, mtx_plain); + (void) mtx_init(&rb_pipe->list_mutex, mtx_plain); + make_empty_list(&rb_pipe->shaders); + + rb_pipe->base.screen = _screen; + rb_pipe->base.priv = pipe->priv; /* expose wrapped data */ + rb_pipe->base.draw = NULL; + rb_pipe->base.stream_uploader = pipe->stream_uploader; + rb_pipe->base.const_uploader = pipe->const_uploader; + + rb_pipe->base.destroy = rbug_destroy; + rb_pipe->base.draw_vbo = rbug_draw_vbo; + rb_pipe->base.create_query = rbug_create_query; + rb_pipe->base.destroy_query = rbug_destroy_query; + rb_pipe->base.begin_query = rbug_begin_query; + rb_pipe->base.end_query = rbug_end_query; + rb_pipe->base.get_query_result = rbug_get_query_result; + rb_pipe->base.set_active_query_state = rbug_set_active_query_state; + rb_pipe->base.create_blend_state = rbug_create_blend_state; + rb_pipe->base.bind_blend_state = rbug_bind_blend_state; + rb_pipe->base.delete_blend_state = rbug_delete_blend_state; + rb_pipe->base.create_sampler_state = rbug_create_sampler_state; + rb_pipe->base.bind_sampler_states = rbug_bind_sampler_states; + rb_pipe->base.delete_sampler_state = rbug_delete_sampler_state; + rb_pipe->base.create_rasterizer_state = rbug_create_rasterizer_state; + rb_pipe->base.bind_rasterizer_state = rbug_bind_rasterizer_state; + rb_pipe->base.delete_rasterizer_state = rbug_delete_rasterizer_state; + rb_pipe->base.create_depth_stencil_alpha_state = rbug_create_depth_stencil_alpha_state; + rb_pipe->base.bind_depth_stencil_alpha_state = rbug_bind_depth_stencil_alpha_state; + rb_pipe->base.delete_depth_stencil_alpha_state = rbug_delete_depth_stencil_alpha_state; + rb_pipe->base.create_fs_state = rbug_create_fs_state; + rb_pipe->base.bind_fs_state = rbug_bind_fs_state; + rb_pipe->base.delete_fs_state = rbug_delete_fs_state; + rb_pipe->base.create_vs_state = rbug_create_vs_state; + rb_pipe->base.bind_vs_state = rbug_bind_vs_state; + rb_pipe->base.delete_vs_state = rbug_delete_vs_state; + rb_pipe->base.create_gs_state = rbug_create_gs_state; + rb_pipe->base.bind_gs_state = rbug_bind_gs_state; + rb_pipe->base.delete_gs_state = rbug_delete_gs_state; + rb_pipe->base.create_vertex_elements_state = rbug_create_vertex_elements_state; + rb_pipe->base.bind_vertex_elements_state = rbug_bind_vertex_elements_state; + rb_pipe->base.delete_vertex_elements_state = rbug_delete_vertex_elements_state; + rb_pipe->base.set_blend_color = rbug_set_blend_color; + rb_pipe->base.set_stencil_ref = rbug_set_stencil_ref; + rb_pipe->base.set_clip_state = rbug_set_clip_state; + rb_pipe->base.set_constant_buffer = rbug_set_constant_buffer; + rb_pipe->base.set_framebuffer_state = rbug_set_framebuffer_state; + rb_pipe->base.set_polygon_stipple = rbug_set_polygon_stipple; + rb_pipe->base.set_scissor_states = rbug_set_scissor_states; + rb_pipe->base.set_viewport_states = rbug_set_viewport_states; + rb_pipe->base.set_sampler_views = rbug_set_sampler_views; + rb_pipe->base.set_vertex_buffers = rbug_set_vertex_buffers; + rb_pipe->base.set_sample_mask = rbug_set_sample_mask; + rb_pipe->base.create_stream_output_target = rbug_create_stream_output_target; + rb_pipe->base.stream_output_target_destroy = rbug_stream_output_target_destroy; + rb_pipe->base.set_stream_output_targets = rbug_set_stream_output_targets; + rb_pipe->base.resource_copy_region = rbug_resource_copy_region; + rb_pipe->base.blit = rbug_blit; + rb_pipe->base.flush_resource = rbug_flush_resource; + rb_pipe->base.clear = rbug_clear; + rb_pipe->base.clear_render_target = rbug_clear_render_target; + rb_pipe->base.clear_depth_stencil = rbug_clear_depth_stencil; + rb_pipe->base.flush = rbug_flush; + rb_pipe->base.create_sampler_view = rbug_context_create_sampler_view; + rb_pipe->base.sampler_view_destroy = rbug_context_sampler_view_destroy; + rb_pipe->base.create_surface = rbug_context_create_surface; + rb_pipe->base.surface_destroy = rbug_context_surface_destroy; + rb_pipe->base.transfer_map = rbug_context_transfer_map; + rb_pipe->base.transfer_unmap = rbug_context_transfer_unmap; + rb_pipe->base.transfer_flush_region = rbug_context_transfer_flush_region; + rb_pipe->base.buffer_subdata = rbug_context_buffer_subdata; + rb_pipe->base.texture_subdata = rbug_context_texture_subdata; + + rb_pipe->pipe = pipe; + + rbug_screen_add_to_list(rb_screen, contexts, rb_pipe); + + if (debug_get_bool_option("GALLIUM_RBUG_START_BLOCKED", FALSE)) { + rb_pipe->draw_blocked = RBUG_BLOCK_BEFORE; + } + + return &rb_pipe->base; +} diff --git a/src/gallium/auxiliary/driver_rbug/rbug_context.h b/src/gallium/auxiliary/driver_rbug/rbug_context.h new file mode 100644 index 00000000000..e89c6eaac01 --- /dev/null +++ b/src/gallium/auxiliary/driver_rbug/rbug_context.h @@ -0,0 +1,104 @@ +/************************************************************************** + * + * 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 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 RBUG_CONTEXT_H +#define RBUG_CONTEXT_H + +#include "pipe/p_state.h" +#include "pipe/p_context.h" + +#include "rbug_screen.h" + + +struct rbug_context { + struct pipe_context base; /**< base class */ + + struct pipe_context *pipe; + + struct rbug_list list; + + /* call locking */ + mtx_t call_mutex; + + /* current state */ + struct { + struct rbug_shader *shader[PIPE_SHADER_TYPES]; + + struct rbug_sampler_view *views[PIPE_SHADER_TYPES][PIPE_MAX_SHADER_SAMPLER_VIEWS]; + struct rbug_resource *texs[PIPE_SHADER_TYPES][PIPE_MAX_SHADER_SAMPLER_VIEWS]; + unsigned num_views[PIPE_SHADER_TYPES]; + + unsigned nr_cbufs; + struct rbug_resource *cbufs[PIPE_MAX_COLOR_BUFS]; + struct rbug_resource *zsbuf; + } curr; + + /* draw locking */ + mtx_t draw_mutex; + cnd_t draw_cond; + unsigned draw_num_rules; + int draw_blocker; + int draw_blocked; + + struct { + struct rbug_shader *shader[PIPE_SHADER_TYPES]; + + struct rbug_resource *texture; + struct rbug_resource *surf; + + int blocker; + } draw_rule; + + /* list of state objects */ + mtx_t list_mutex; + unsigned num_shaders; + struct rbug_list shaders; +}; + +static inline struct rbug_context * +rbug_context(struct pipe_context *pipe) +{ + return (struct rbug_context *)pipe; +} + + +/********************************************************** + * rbug_context.c + */ + +struct pipe_context * +rbug_context_create(struct pipe_screen *screen, struct pipe_context *pipe); + + +/********************************************************** + * rbug_core.c + */ + +void rbug_notify_draw_blocked(struct rbug_context *rb_context); + + +#endif /* RBUG_CONTEXT_H */ diff --git a/src/gallium/auxiliary/driver_rbug/rbug_core.c b/src/gallium/auxiliary/driver_rbug/rbug_core.c new file mode 100644 index 00000000000..76394039b9b --- /dev/null +++ b/src/gallium/auxiliary/driver_rbug/rbug_core.c @@ -0,0 +1,888 @@ +/************************************************************************** + * + * 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 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 "os/os_thread.h" +#include "util/u_format.h" +#include "util/u_string.h" +#include "util/u_inlines.h" +#include "util/u_memory.h" +#include "util/simple_list.h" +#include "util/u_network.h" +#include "util/os_time.h" + +#include "tgsi/tgsi_parse.h" + +#include "rbug_context.h" +#include "rbug_objects.h" + +#include "rbug/rbug.h" + +#include <errno.h> + +#define U642VOID(x) ((void *)(unsigned long)(x)) +#define VOID2U64(x) ((uint64_t)(unsigned long)(x)) + +#define container_of(ptr, type, field) \ + (type*)((char*)ptr - offsetof(type, field)) + +struct rbug_rbug +{ + struct rbug_screen *rb_screen; + struct rbug_connection *con; + thrd_t thread; + boolean running; +}; + +int +rbug_thread(void *void_rbug); + + +/********************************************************** + * Helper functions + */ + + +static struct rbug_context * +rbug_get_context_locked(struct rbug_screen *rb_screen, rbug_context_t ctx) +{ + struct rbug_context *rb_context = NULL; + struct rbug_list *ptr; + + foreach(ptr, &rb_screen->contexts) { + rb_context = container_of(ptr, struct rbug_context, list); + if (ctx == VOID2U64(rb_context)) + break; + rb_context = NULL; + } + + return rb_context; +} + +static struct rbug_shader * +rbug_get_shader_locked(struct rbug_context *rb_context, rbug_shader_t shdr) +{ + struct rbug_shader *tr_shdr = NULL; + struct rbug_list *ptr; + + foreach(ptr, &rb_context->shaders) { + tr_shdr = container_of(ptr, struct rbug_shader, list); + if (shdr == VOID2U64(tr_shdr)) + break; + tr_shdr = NULL; + } + + return tr_shdr; +} + +static void * +rbug_shader_create_locked(struct pipe_context *pipe, + struct rbug_shader *rb_shader, + struct tgsi_token *tokens) +{ + void *state = NULL; + struct pipe_shader_state pss; + memset(&pss, 0, sizeof(pss)); + pss.tokens = tokens; + + switch(rb_shader->type) { + case RBUG_SHADER_FRAGMENT: + state = pipe->create_fs_state(pipe, &pss); + break; + case RBUG_SHADER_VERTEX: + state = pipe->create_vs_state(pipe, &pss); + break; + case RBUG_SHADER_GEOM: + state = pipe->create_gs_state(pipe, &pss); + break; + default: + assert(0); + break; + } + + return state; +} + +static void +rbug_shader_bind_locked(struct pipe_context *pipe, + struct rbug_shader *rb_shader, + void *state) +{ + switch(rb_shader->type) { + case RBUG_SHADER_FRAGMENT: + pipe->bind_fs_state(pipe, state); + break; + case RBUG_SHADER_VERTEX: + pipe->bind_vs_state(pipe, state); + break; + case RBUG_SHADER_GEOM: + pipe->bind_gs_state(pipe, state); + break; + default: + assert(0); + break; + } +} + +static void +rbug_shader_delete_locked(struct pipe_context *pipe, + struct rbug_shader *rb_shader, + void *state) +{ + switch(rb_shader->type) { + case RBUG_SHADER_FRAGMENT: + pipe->delete_fs_state(pipe, state); + break; + case RBUG_SHADER_VERTEX: + pipe->delete_vs_state(pipe, state); + break; + case RBUG_SHADER_GEOM: + pipe->delete_gs_state(pipe, state); + break; + default: + assert(0); + break; + } +} + +/************************************************ + * Request handler functions + */ + + +static int +rbug_texture_list(struct rbug_rbug *tr_rbug, struct rbug_header *header, uint32_t serial) +{ + struct rbug_screen *rb_screen = tr_rbug->rb_screen; + struct rbug_resource *tr_tex = NULL; + struct rbug_list *ptr; + rbug_texture_t *texs; + int i = 0; + + mtx_lock(&rb_screen->list_mutex); + texs = MALLOC(rb_screen->num_resources * sizeof(rbug_texture_t)); + foreach(ptr, &rb_screen->resources) { + tr_tex = container_of(ptr, struct rbug_resource, list); + texs[i++] = VOID2U64(tr_tex); + } + mtx_unlock(&rb_screen->list_mutex); + + rbug_send_texture_list_reply(tr_rbug->con, serial, texs, i, NULL); + FREE(texs); + + return 0; +} + +static int +rbug_texture_info(struct rbug_rbug *tr_rbug, struct rbug_header *header, uint32_t serial) +{ + struct rbug_screen *rb_screen = tr_rbug->rb_screen; + struct rbug_resource *tr_tex = NULL; + struct rbug_proto_texture_info *gpti = (struct rbug_proto_texture_info *)header; + struct rbug_list *ptr; + struct pipe_resource *t; + uint16_t num_layers; + + mtx_lock(&rb_screen->list_mutex); + foreach(ptr, &rb_screen->resources) { + tr_tex = container_of(ptr, struct rbug_resource, list); + if (gpti->texture == VOID2U64(tr_tex)) + break; + tr_tex = NULL; + } + + if (!tr_tex) { + mtx_unlock(&rb_screen->list_mutex); + return -ESRCH; + } + + t = tr_tex->resource; + num_layers = util_num_layers(t, 0); + + rbug_send_texture_info_reply(tr_rbug->con, serial, + t->target, t->format, + &t->width0, 1, + &t->height0, 1, + &num_layers, 1, + util_format_get_blockwidth(t->format), + util_format_get_blockheight(t->format), + util_format_get_blocksize(t->format), + t->last_level, + t->nr_samples, + t->bind, + NULL); + + mtx_unlock(&rb_screen->list_mutex); + + return 0; +} + +static int +rbug_texture_read(struct rbug_rbug *tr_rbug, struct rbug_header *header, uint32_t serial) +{ + struct rbug_proto_texture_read *gptr = (struct rbug_proto_texture_read *)header; + + struct rbug_screen *rb_screen = tr_rbug->rb_screen; + struct rbug_resource *tr_tex = NULL; + struct rbug_list *ptr; + + struct pipe_context *context = rb_screen->private_context; + struct pipe_resource *tex; + struct pipe_transfer *t; + + void *map; + + mtx_lock(&rb_screen->list_mutex); + foreach(ptr, &rb_screen->resources) { + tr_tex = container_of(ptr, struct rbug_resource, list); + if (gptr->texture == VOID2U64(tr_tex)) + break; + tr_tex = NULL; + } + + if (!tr_tex) { + mtx_unlock(&rb_screen->list_mutex); + return -ESRCH; + } + + tex = tr_tex->resource; + map = pipe_transfer_map(context, tex, + gptr->level, gptr->face + gptr->zslice, + PIPE_TRANSFER_READ, + gptr->x, gptr->y, gptr->w, gptr->h, &t); + + rbug_send_texture_read_reply(tr_rbug->con, serial, + t->resource->format, + util_format_get_blockwidth(t->resource->format), + util_format_get_blockheight(t->resource->format), + util_format_get_blocksize(t->resource->format), + (uint8_t*)map, + t->stride * util_format_get_nblocksy(t->resource->format, + t->box.height), + t->stride, + NULL); + + context->transfer_unmap(context, t); + + mtx_unlock(&rb_screen->list_mutex); + + return 0; +} + +static int +rbug_context_list(struct rbug_rbug *tr_rbug, struct rbug_header *header, uint32_t serial) +{ + struct rbug_screen *rb_screen = tr_rbug->rb_screen; + struct rbug_list *ptr; + struct rbug_context *rb_context = NULL; + rbug_context_t *ctxs; + int i = 0; + + mtx_lock(&rb_screen->list_mutex); + ctxs = MALLOC(rb_screen->num_contexts * sizeof(rbug_context_t)); + foreach(ptr, &rb_screen->contexts) { + rb_context = container_of(ptr, struct rbug_context, list); + ctxs[i++] = VOID2U64(rb_context); + } + mtx_unlock(&rb_screen->list_mutex); + + rbug_send_context_list_reply(tr_rbug->con, serial, ctxs, i, NULL); + FREE(ctxs); + + return 0; +} + +static int +rbug_context_info(struct rbug_rbug *tr_rbug, struct rbug_header *header, uint32_t serial) +{ + struct rbug_proto_context_info *info = (struct rbug_proto_context_info *)header; + + struct rbug_screen *rb_screen = tr_rbug->rb_screen; + struct rbug_context *rb_context = NULL; + rbug_texture_t cbufs[PIPE_MAX_COLOR_BUFS]; + rbug_texture_t texs[PIPE_MAX_SHADER_SAMPLER_VIEWS]; + unsigned i; + + mtx_lock(&rb_screen->list_mutex); + rb_context = rbug_get_context_locked(rb_screen, info->context); + + if (!rb_context) { + mtx_unlock(&rb_screen->list_mutex); + return -ESRCH; + } + + /* protect the pipe context */ + mtx_lock(&rb_context->draw_mutex); + mtx_lock(&rb_context->call_mutex); + + for (i = 0; i < rb_context->curr.nr_cbufs; i++) + cbufs[i] = VOID2U64(rb_context->curr.cbufs[i]); + + /* XXX what about vertex/geometry shader texture views? */ + for (i = 0; i < rb_context->curr.num_views[PIPE_SHADER_FRAGMENT]; i++) + texs[i] = VOID2U64(rb_context->curr.texs[PIPE_SHADER_FRAGMENT][i]); + + rbug_send_context_info_reply(tr_rbug->con, serial, + VOID2U64(rb_context->curr.shader[PIPE_SHADER_VERTEX]), VOID2U64(rb_context->curr.shader[PIPE_SHADER_FRAGMENT]), + texs, rb_context->curr.num_views[PIPE_SHADER_FRAGMENT], + cbufs, rb_context->curr.nr_cbufs, + VOID2U64(rb_context->curr.zsbuf), + rb_context->draw_blocker, rb_context->draw_blocked, NULL); + + mtx_unlock(&rb_context->call_mutex); + mtx_unlock(&rb_context->draw_mutex); + mtx_unlock(&rb_screen->list_mutex); + + return 0; +} + +static int +rbug_context_draw_block(struct rbug_rbug *tr_rbug, struct rbug_header *header, uint32_t serial) +{ + struct rbug_proto_context_draw_block *block = (struct rbug_proto_context_draw_block *)header; + + struct rbug_screen *rb_screen = tr_rbug->rb_screen; + struct rbug_context *rb_context = NULL; + + mtx_lock(&rb_screen->list_mutex); + rb_context = rbug_get_context_locked(rb_screen, block->context); + + if (!rb_context) { + mtx_unlock(&rb_screen->list_mutex); + return -ESRCH; + } + + mtx_lock(&rb_context->draw_mutex); + rb_context->draw_blocker |= block->block; + mtx_unlock(&rb_context->draw_mutex); + + mtx_unlock(&rb_screen->list_mutex); + + return 0; +} + +static int +rbug_context_draw_step(struct rbug_rbug *tr_rbug, struct rbug_header *header, uint32_t serial) +{ + struct rbug_proto_context_draw_step *step = (struct rbug_proto_context_draw_step *)header; + + struct rbug_screen *rb_screen = tr_rbug->rb_screen; + struct rbug_context *rb_context = NULL; + + mtx_lock(&rb_screen->list_mutex); + rb_context = rbug_get_context_locked(rb_screen, step->context); + + if (!rb_context) { + mtx_unlock(&rb_screen->list_mutex); + return -ESRCH; + } + + mtx_lock(&rb_context->draw_mutex); + if (rb_context->draw_blocked & RBUG_BLOCK_RULE) { + if (step->step & RBUG_BLOCK_RULE) + rb_context->draw_blocked &= ~RBUG_BLOCK_MASK; + } else { + rb_context->draw_blocked &= ~step->step; + } + mtx_unlock(&rb_context->draw_mutex); + + cnd_broadcast(&rb_context->draw_cond); + + mtx_unlock(&rb_screen->list_mutex); + + return 0; +} + +static int +rbug_context_draw_unblock(struct rbug_rbug *tr_rbug, struct rbug_header *header, uint32_t serial) +{ + struct rbug_proto_context_draw_unblock *unblock = (struct rbug_proto_context_draw_unblock *)header; + + struct rbug_screen *rb_screen = tr_rbug->rb_screen; + struct rbug_context *rb_context = NULL; + + mtx_lock(&rb_screen->list_mutex); + rb_context = rbug_get_context_locked(rb_screen, unblock->context); + + if (!rb_context) { + mtx_unlock(&rb_screen->list_mutex); + return -ESRCH; + } + + mtx_lock(&rb_context->draw_mutex); + if (rb_context->draw_blocked & RBUG_BLOCK_RULE) { + if (unblock->unblock & RBUG_BLOCK_RULE) + rb_context->draw_blocked &= ~RBUG_BLOCK_MASK; + } else { + rb_context->draw_blocked &= ~unblock->unblock; + } + rb_context->draw_blocker &= ~unblock->unblock; + mtx_unlock(&rb_context->draw_mutex); + + cnd_broadcast(&rb_context->draw_cond); + + mtx_unlock(&rb_screen->list_mutex); + + return 0; +} + +static int +rbug_context_draw_rule(struct rbug_rbug *tr_rbug, struct rbug_header *header, uint32_t serial) +{ + struct rbug_proto_context_draw_rule *rule = (struct rbug_proto_context_draw_rule *)header; + + struct rbug_screen *rb_screen = tr_rbug->rb_screen; + struct rbug_context *rb_context = NULL; + + mtx_lock(&rb_screen->list_mutex); + rb_context = rbug_get_context_locked(rb_screen, rule->context); + + if (!rb_context) { + mtx_unlock(&rb_screen->list_mutex); + return -ESRCH; + } + + mtx_lock(&rb_context->draw_mutex); + rb_context->draw_rule.shader[PIPE_SHADER_VERTEX] = U642VOID(rule->vertex); + rb_context->draw_rule.shader[PIPE_SHADER_FRAGMENT] = U642VOID(rule->fragment); + rb_context->draw_rule.texture = U642VOID(rule->texture); + rb_context->draw_rule.surf = U642VOID(rule->surface); + rb_context->draw_rule.blocker = rule->block; + rb_context->draw_blocker |= RBUG_BLOCK_RULE; + mtx_unlock(&rb_context->draw_mutex); + + cnd_broadcast(&rb_context->draw_cond); + + mtx_unlock(&rb_screen->list_mutex); + + return 0; +} + +static int +rbug_context_flush(struct rbug_rbug *tr_rbug, struct rbug_header *header, uint32_t serial) +{ + struct rbug_proto_context_flush *flush = (struct rbug_proto_context_flush *)header; + + struct rbug_screen *rb_screen = tr_rbug->rb_screen; + struct rbug_context *rb_context = NULL; + + mtx_lock(&rb_screen->list_mutex); + rb_context = rbug_get_context_locked(rb_screen, flush->context); + + if (!rb_context) { + mtx_unlock(&rb_screen->list_mutex); + return -ESRCH; + } + + /* protect the pipe context */ + mtx_lock(&rb_context->call_mutex); + + rb_context->pipe->flush(rb_context->pipe, NULL, 0); + + mtx_unlock(&rb_context->call_mutex); + mtx_unlock(&rb_screen->list_mutex); + + return 0; +} + +static int +rbug_shader_list(struct rbug_rbug *tr_rbug, struct rbug_header *header, uint32_t serial) +{ + struct rbug_proto_shader_list *list = (struct rbug_proto_shader_list *)header; + + struct rbug_screen *rb_screen = tr_rbug->rb_screen; + struct rbug_context *rb_context = NULL; + struct rbug_shader *tr_shdr = NULL; + struct rbug_list *ptr; + rbug_shader_t *shdrs; + int i = 0; + + mtx_lock(&rb_screen->list_mutex); + rb_context = rbug_get_context_locked(rb_screen, list->context); + + if (!rb_context) { + mtx_unlock(&rb_screen->list_mutex); + return -ESRCH; + } + + mtx_lock(&rb_context->list_mutex); + shdrs = MALLOC(rb_context->num_shaders * sizeof(rbug_shader_t)); + foreach(ptr, &rb_context->shaders) { + tr_shdr = container_of(ptr, struct rbug_shader, list); + shdrs[i++] = VOID2U64(tr_shdr); + } + + mtx_unlock(&rb_context->list_mutex); + mtx_unlock(&rb_screen->list_mutex); + + rbug_send_shader_list_reply(tr_rbug->con, serial, shdrs, i, NULL); + FREE(shdrs); + + return 0; +} + +static int +rbug_shader_info(struct rbug_rbug *tr_rbug, struct rbug_header *header, uint32_t serial) +{ + struct rbug_proto_shader_info *info = (struct rbug_proto_shader_info *)header; + + struct rbug_screen *rb_screen = tr_rbug->rb_screen; + struct rbug_context *rb_context = NULL; + struct rbug_shader *tr_shdr = NULL; + unsigned original_len; + unsigned replaced_len; + + mtx_lock(&rb_screen->list_mutex); + rb_context = rbug_get_context_locked(rb_screen, info->context); + + if (!rb_context) { + mtx_unlock(&rb_screen->list_mutex); + return -ESRCH; + } + + mtx_lock(&rb_context->list_mutex); + + tr_shdr = rbug_get_shader_locked(rb_context, info->shader); + + if (!tr_shdr) { + mtx_unlock(&rb_context->list_mutex); + mtx_unlock(&rb_screen->list_mutex); + return -ESRCH; + } + + /* just in case */ + assert(sizeof(struct tgsi_token) == 4); + + original_len = tgsi_num_tokens(tr_shdr->tokens); + if (tr_shdr->replaced_tokens) + replaced_len = tgsi_num_tokens(tr_shdr->replaced_tokens); + else + replaced_len = 0; + + rbug_send_shader_info_reply(tr_rbug->con, serial, + (uint32_t*)tr_shdr->tokens, original_len, + (uint32_t*)tr_shdr->replaced_tokens, replaced_len, + tr_shdr->disabled, + NULL); + + mtx_unlock(&rb_context->list_mutex); + mtx_unlock(&rb_screen->list_mutex); + + return 0; +} + +static int +rbug_shader_disable(struct rbug_rbug *tr_rbug, struct rbug_header *header) +{ + struct rbug_proto_shader_disable *dis = (struct rbug_proto_shader_disable *)header; + + struct rbug_screen *rb_screen = tr_rbug->rb_screen; + struct rbug_context *rb_context = NULL; + struct rbug_shader *tr_shdr = NULL; + + mtx_lock(&rb_screen->list_mutex); + rb_context = rbug_get_context_locked(rb_screen, dis->context); + + if (!rb_context) { + mtx_unlock(&rb_screen->list_mutex); + return -ESRCH; + } + + mtx_lock(&rb_context->list_mutex); + + tr_shdr = rbug_get_shader_locked(rb_context, dis->shader); + + if (!tr_shdr) { + mtx_unlock(&rb_context->list_mutex); + mtx_unlock(&rb_screen->list_mutex); + return -ESRCH; + } + + tr_shdr->disabled = dis->disable; + + mtx_unlock(&rb_context->list_mutex); + mtx_unlock(&rb_screen->list_mutex); + + return 0; +} + +static int +rbug_shader_replace(struct rbug_rbug *tr_rbug, struct rbug_header *header) +{ + struct rbug_proto_shader_replace *rep = (struct rbug_proto_shader_replace *)header; + + struct rbug_screen *rb_screen = tr_rbug->rb_screen; + struct rbug_context *rb_context = NULL; + struct rbug_shader *tr_shdr = NULL; + struct pipe_context *pipe = NULL; + void *state; + + mtx_lock(&rb_screen->list_mutex); + rb_context = rbug_get_context_locked(rb_screen, rep->context); + + if (!rb_context) { + mtx_unlock(&rb_screen->list_mutex); + return -ESRCH; + } + + mtx_lock(&rb_context->list_mutex); + + tr_shdr = rbug_get_shader_locked(rb_context, rep->shader); + + if (!tr_shdr) { + mtx_unlock(&rb_context->list_mutex); + mtx_unlock(&rb_screen->list_mutex); + return -ESRCH; + } + + /* protect the pipe context */ + mtx_lock(&rb_context->call_mutex); + + pipe = rb_context->pipe; + + /* remove old replaced shader */ + if (tr_shdr->replaced_shader) { + /* if this shader is bound rebind the original shader */ + if (rb_context->curr.shader[PIPE_SHADER_FRAGMENT] == tr_shdr || rb_context->curr.shader[PIPE_SHADER_VERTEX] == tr_shdr) + rbug_shader_bind_locked(pipe, tr_shdr, tr_shdr->shader); + + FREE(tr_shdr->replaced_tokens); + rbug_shader_delete_locked(pipe, tr_shdr, tr_shdr->replaced_shader); + tr_shdr->replaced_shader = NULL; + tr_shdr->replaced_tokens = NULL; + } + + /* empty inputs means restore old which we did above */ + if (rep->tokens_len == 0) + goto out; + + tr_shdr->replaced_tokens = tgsi_dup_tokens((struct tgsi_token *)rep->tokens); + if (!tr_shdr->replaced_tokens) + goto err; + + state = rbug_shader_create_locked(pipe, tr_shdr, tr_shdr->replaced_tokens); + if (!state) + goto err; + + /* bind new shader if the shader is currently a bound */ + if (rb_context->curr.shader[PIPE_SHADER_FRAGMENT] == tr_shdr || rb_context->curr.shader[PIPE_SHADER_VERTEX] == tr_shdr) + rbug_shader_bind_locked(pipe, tr_shdr, state); + + /* save state */ + tr_shdr->replaced_shader = state; + +out: + mtx_unlock(&rb_context->call_mutex); + mtx_unlock(&rb_context->list_mutex); + mtx_unlock(&rb_screen->list_mutex); + + return 0; + +err: + FREE(tr_shdr->replaced_tokens); + tr_shdr->replaced_shader = NULL; + tr_shdr->replaced_tokens = NULL; + + mtx_unlock(&rb_context->call_mutex); + mtx_unlock(&rb_context->list_mutex); + mtx_unlock(&rb_screen->list_mutex); + return -EINVAL; +} + +static boolean +rbug_header(struct rbug_rbug *tr_rbug, struct rbug_header *header, uint32_t serial) +{ + int ret = 0; + + switch(header->opcode) { + case RBUG_OP_PING: + rbug_send_ping_reply(tr_rbug->con, serial, NULL); + break; + case RBUG_OP_TEXTURE_LIST: + ret = rbug_texture_list(tr_rbug, header, serial); + break; + case RBUG_OP_TEXTURE_INFO: + ret = rbug_texture_info(tr_rbug, header, serial); + break; + case RBUG_OP_TEXTURE_READ: + ret = rbug_texture_read(tr_rbug, header, serial); + break; + case RBUG_OP_CONTEXT_LIST: + ret = rbug_context_list(tr_rbug, header, serial); + break; + case RBUG_OP_CONTEXT_INFO: + ret = rbug_context_info(tr_rbug, header, serial); + break; + case RBUG_OP_CONTEXT_DRAW_BLOCK: + ret = rbug_context_draw_block(tr_rbug, header, serial); + break; + case RBUG_OP_CONTEXT_DRAW_STEP: + ret = rbug_context_draw_step(tr_rbug, header, serial); + break; + case RBUG_OP_CONTEXT_DRAW_UNBLOCK: + ret = rbug_context_draw_unblock(tr_rbug, header, serial); + break; + case RBUG_OP_CONTEXT_DRAW_RULE: + ret = rbug_context_draw_rule(tr_rbug, header, serial); + break; + case RBUG_OP_CONTEXT_FLUSH: + ret = rbug_context_flush(tr_rbug, header, serial); + break; + case RBUG_OP_SHADER_LIST: + ret = rbug_shader_list(tr_rbug, header, serial); + break; + case RBUG_OP_SHADER_INFO: + ret = rbug_shader_info(tr_rbug, header, serial); + break; + case RBUG_OP_SHADER_DISABLE: + ret = rbug_shader_disable(tr_rbug, header); + break; + case RBUG_OP_SHADER_REPLACE: + ret = rbug_shader_replace(tr_rbug, header); + break; + default: + debug_printf("%s - unsupported opcode %u\n", __FUNCTION__, header->opcode); + ret = -ENOSYS; + break; + } + rbug_free_header(header); + + if (ret) + rbug_send_error_reply(tr_rbug->con, serial, ret, NULL); + + return TRUE; +} + +static void +rbug_con(struct rbug_rbug *tr_rbug) +{ + struct rbug_header *header; + uint32_t serial; + + debug_printf("%s - connection received\n", __FUNCTION__); + + while(tr_rbug->running) { + header = rbug_get_message(tr_rbug->con, &serial); + if (!header) + break; + + if (!rbug_header(tr_rbug, header, serial)) + break; + } + + debug_printf("%s - connection closed\n", __FUNCTION__); + + rbug_disconnect(tr_rbug->con); + tr_rbug->con = NULL; +} + +int +rbug_thread(void *void_tr_rbug) +{ + struct rbug_rbug *tr_rbug = void_tr_rbug; + uint16_t port = 13370; + int s = -1; + int c; + + u_socket_init(); + + for (;port <= 13379 && s < 0; port++) + s = u_socket_listen_on_port(port); + + if (s < 0) { + debug_printf("rbug_rbug - failed to listen\n"); + return 0; + } + + u_socket_block(s, false); + + debug_printf("rbug_rbug - remote debugging listening on port %u\n", --port); + + while(tr_rbug->running) { + os_time_sleep(1); + + c = u_socket_accept(s); + if (c < 0) + continue; + + u_socket_block(c, true); + tr_rbug->con = rbug_from_socket(c); + + rbug_con(tr_rbug); + + u_socket_close(c); + } + + u_socket_close(s); + + u_socket_stop(); + + return 0; +} + +/********************************************************** + * + */ + +struct rbug_rbug * +rbug_start(struct rbug_screen *rb_screen) +{ + struct rbug_rbug *tr_rbug = CALLOC_STRUCT(rbug_rbug); + if (!tr_rbug) + return NULL; + + tr_rbug->rb_screen = rb_screen; + tr_rbug->running = TRUE; + tr_rbug->thread = u_thread_create(rbug_thread, tr_rbug); + + return tr_rbug; +} + +void +rbug_stop(struct rbug_rbug *tr_rbug) +{ + if (!tr_rbug) + return; + + tr_rbug->running = false; + thrd_join(tr_rbug->thread, NULL); + + FREE(tr_rbug); + + return; +} + +void +rbug_notify_draw_blocked(struct rbug_context *rb_context) +{ + struct rbug_screen *rb_screen = rbug_screen(rb_context->base.screen); + struct rbug_rbug *tr_rbug = rb_screen->rbug; + + if (tr_rbug && tr_rbug->con) + rbug_send_context_draw_blocked(tr_rbug->con, + VOID2U64(rb_context), rb_context->draw_blocked, NULL); +} diff --git a/src/gallium/auxiliary/driver_rbug/rbug_objects.c b/src/gallium/auxiliary/driver_rbug/rbug_objects.c new file mode 100644 index 00000000000..2aa4e123f87 --- /dev/null +++ b/src/gallium/auxiliary/driver_rbug/rbug_objects.c @@ -0,0 +1,250 @@ +/************************************************************************** + * + * 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 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 "tgsi/tgsi_parse.h" + +#include "rbug_screen.h" +#include "rbug_objects.h" +#include "rbug_context.h" + + + +struct pipe_resource * +rbug_resource_create(struct rbug_screen *rb_screen, + struct pipe_resource *resource) +{ + struct rbug_resource *rb_resource; + + if (!resource) + goto error; + + assert(resource->screen == rb_screen->screen); + + rb_resource = CALLOC_STRUCT(rbug_resource); + if (!rb_resource) + goto error; + + memcpy(&rb_resource->base, resource, sizeof(struct pipe_resource)); + + pipe_reference_init(&rb_resource->base.reference, 1); + rb_resource->base.screen = &rb_screen->base; + rb_resource->resource = resource; + + if (resource->target != PIPE_BUFFER) + rbug_screen_add_to_list(rb_screen, resources, rb_resource); + + return &rb_resource->base; + +error: + pipe_resource_reference(&resource, NULL); + return NULL; +} + +void +rbug_resource_destroy(struct rbug_resource *rb_resource) +{ + struct rbug_screen *rb_screen = rbug_screen(rb_resource->base.screen); + + if (rb_resource->base.target != PIPE_BUFFER) + rbug_screen_remove_from_list(rb_screen, resources, rb_resource); + + pipe_resource_reference(&rb_resource->resource, NULL); + FREE(rb_resource); +} + + +struct pipe_surface * +rbug_surface_create(struct rbug_context *rb_context, + struct rbug_resource *rb_resource, + struct pipe_surface *surface) +{ + struct rbug_surface *rb_surface; + + if (!surface) + goto error; + + assert(surface->texture == rb_resource->resource); + + rb_surface = CALLOC_STRUCT(rbug_surface); + if (!rb_surface) + goto error; + + memcpy(&rb_surface->base, surface, sizeof(struct pipe_surface)); + + pipe_reference_init(&rb_surface->base.reference, 1); + rb_surface->base.texture = NULL; + rb_surface->base.context = &rb_context->base; + rb_surface->surface = surface; /* we own the surface already */ + pipe_resource_reference(&rb_surface->base.texture, &rb_resource->base); + + return &rb_surface->base; + +error: + pipe_surface_reference(&surface, NULL); + return NULL; +} + +void +rbug_surface_destroy(struct rbug_context *rb_context, + struct rbug_surface *rb_surface) +{ + pipe_resource_reference(&rb_surface->base.texture, NULL); + pipe_surface_reference(&rb_surface->surface, NULL); + FREE(rb_surface); +} + + +struct pipe_sampler_view * +rbug_sampler_view_create(struct rbug_context *rb_context, + struct rbug_resource *rb_resource, + struct pipe_sampler_view *view) +{ + struct rbug_sampler_view *rb_view; + + if (!view) + goto error; + + assert(view->texture == rb_resource->resource); + + rb_view = MALLOC(sizeof(struct rbug_sampler_view)); + + rb_view->base = *view; + rb_view->base.reference.count = 1; + rb_view->base.texture = NULL; + pipe_resource_reference(&rb_view->base.texture, &rb_resource->base); + rb_view->base.context = &rb_context->base; + rb_view->sampler_view = view; + + return &rb_view->base; +error: + return NULL; +} + +void +rbug_sampler_view_destroy(struct rbug_context *rb_context, + struct rbug_sampler_view *rb_view) +{ + pipe_resource_reference(&rb_view->base.texture, NULL); + pipe_sampler_view_reference(&rb_view->sampler_view, NULL); + FREE(rb_view); +} + + +struct pipe_transfer * +rbug_transfer_create(struct rbug_context *rb_context, + struct rbug_resource *rb_resource, + struct pipe_transfer *transfer) +{ + struct rbug_transfer *rb_transfer; + + if (!transfer) + goto error; + + assert(transfer->resource == rb_resource->resource); + + rb_transfer = CALLOC_STRUCT(rbug_transfer); + if (!rb_transfer) + goto error; + + memcpy(&rb_transfer->base, transfer, sizeof(struct pipe_transfer)); + + rb_transfer->base.resource = NULL; + rb_transfer->transfer = transfer; + rb_transfer->pipe = rb_context->pipe; + + pipe_resource_reference(&rb_transfer->base.resource, &rb_resource->base); + assert(rb_transfer->base.resource == &rb_resource->base); + + return &rb_transfer->base; + +error: + rb_context->pipe->transfer_unmap(rb_context->pipe, transfer); + return NULL; +} + +void +rbug_transfer_destroy(struct rbug_context *rb_context, + struct rbug_transfer *rb_transfer) +{ + pipe_resource_reference(&rb_transfer->base.resource, NULL); + FREE(rb_transfer); +} + +void * +rbug_shader_create(struct rbug_context *rb_context, + const struct pipe_shader_state *state, + void *result, enum rbug_shader_type type) +{ + struct rbug_shader *rb_shader = CALLOC_STRUCT(rbug_shader); + + rb_shader->type = type; + rb_shader->shader = result; + rb_shader->tokens = tgsi_dup_tokens(state->tokens); + + /* works on context as well since its just a macro */ + rbug_screen_add_to_list(rb_context, shaders, rb_shader); + + return rb_shader; +} + +void +rbug_shader_destroy(struct rbug_context *rb_context, + struct rbug_shader *rb_shader) +{ + struct pipe_context *pipe = rb_context->pipe; + + /* works on context as well since its just a macro */ + rbug_screen_remove_from_list(rb_context, shaders, rb_shader); + + switch(rb_shader->type) { + case RBUG_SHADER_FRAGMENT: + if (rb_shader->replaced_shader) + pipe->delete_fs_state(pipe, rb_shader->replaced_shader); + pipe->delete_fs_state(pipe, rb_shader->shader); + break; + case RBUG_SHADER_VERTEX: + if (rb_shader->replaced_shader) + pipe->delete_vs_state(pipe, rb_shader->replaced_shader); + pipe->delete_vs_state(pipe, rb_shader->shader); + break; + case RBUG_SHADER_GEOM: + if (rb_shader->replaced_shader) + pipe->delete_gs_state(pipe, rb_shader->replaced_shader); + pipe->delete_gs_state(pipe, rb_shader->shader); + break; + default: + assert(0); + } + + FREE(rb_shader->replaced_tokens); + FREE(rb_shader->tokens); + FREE(rb_shader); +} diff --git a/src/gallium/auxiliary/driver_rbug/rbug_objects.h b/src/gallium/auxiliary/driver_rbug/rbug_objects.h new file mode 100644 index 00000000000..02973e07996 --- /dev/null +++ b/src/gallium/auxiliary/driver_rbug/rbug_objects.h @@ -0,0 +1,228 @@ +/************************************************************************** + * + * 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 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 RBUG_OBJECTS_H +#define RBUG_OBJECTS_H + + +#include "pipe/p_compiler.h" +#include "pipe/p_state.h" + +#include "rbug_screen.h" + +struct rbug_context; + + +struct rbug_resource +{ + struct pipe_resource base; + + struct pipe_resource *resource; + + struct rbug_list list; +}; + + +enum rbug_shader_type +{ + RBUG_SHADER_GEOM, + RBUG_SHADER_VERTEX, + RBUG_SHADER_FRAGMENT, +}; + +struct rbug_shader +{ + struct rbug_list list; + + void *shader; + void *tokens; + void *replaced_shader; + void *replaced_tokens; + + enum rbug_shader_type type; + boolean disabled; +}; + + +struct rbug_sampler_view +{ + struct pipe_sampler_view base; + + struct pipe_sampler_view *sampler_view; +}; + + +struct rbug_surface +{ + struct pipe_surface base; + + struct pipe_surface *surface; +}; + + +struct rbug_transfer +{ + struct pipe_transfer base; + + struct pipe_context *pipe; + struct pipe_transfer *transfer; +}; + + +static inline struct rbug_resource * +rbug_resource(struct pipe_resource *_resource) +{ + if (!_resource) + return NULL; + (void)rbug_screen(_resource->screen); + return (struct rbug_resource *)_resource; +} + +static inline struct rbug_sampler_view * +rbug_sampler_view(struct pipe_sampler_view *_sampler_view) +{ + if (!_sampler_view) + return NULL; + (void)rbug_resource(_sampler_view->texture); + return (struct rbug_sampler_view *)_sampler_view; +} + +static inline struct rbug_surface * +rbug_surface(struct pipe_surface *_surface) +{ + if (!_surface) + return NULL; + (void)rbug_resource(_surface->texture); + return (struct rbug_surface *)_surface; +} + +static inline struct rbug_transfer * +rbug_transfer(struct pipe_transfer *_transfer) +{ + if (!_transfer) + return NULL; + (void)rbug_resource(_transfer->resource); + return (struct rbug_transfer *)_transfer; +} + +static inline struct rbug_shader * +rbug_shader(void *_state) +{ + if (!_state) + return NULL; + return (struct rbug_shader *)_state; +} + +static inline struct pipe_resource * +rbug_resource_unwrap(struct pipe_resource *_resource) +{ + if (!_resource) + return NULL; + return rbug_resource(_resource)->resource; +} + +static inline struct pipe_sampler_view * +rbug_sampler_view_unwrap(struct pipe_sampler_view *_sampler_view) +{ + if (!_sampler_view) + return NULL; + return rbug_sampler_view(_sampler_view)->sampler_view; +} + +static inline struct pipe_surface * +rbug_surface_unwrap(struct pipe_surface *_surface) +{ + if (!_surface) + return NULL; + return rbug_surface(_surface)->surface; +} + +static inline struct pipe_transfer * +rbug_transfer_unwrap(struct pipe_transfer *_transfer) +{ + if (!_transfer) + return NULL; + return rbug_transfer(_transfer)->transfer; +} + +static inline void * +rbug_shader_unwrap(void *_state) +{ + struct rbug_shader *shader; + if (!_state) + return NULL; + + shader = rbug_shader(_state); + return shader->replaced_shader ? shader->replaced_shader : shader->shader; +} + + +struct pipe_resource * +rbug_resource_create(struct rbug_screen *rb_screen, + struct pipe_resource *resource); + +void +rbug_resource_destroy(struct rbug_resource *rb_resource); + +struct pipe_surface * +rbug_surface_create(struct rbug_context *rb_context, + struct rbug_resource *rb_resource, + struct pipe_surface *surface); + +void +rbug_surface_destroy(struct rbug_context *rb_context, + struct rbug_surface *rb_surface); + +struct pipe_sampler_view * +rbug_sampler_view_create(struct rbug_context *rb_context, + struct rbug_resource *rb_resource, + struct pipe_sampler_view *view); + +void +rbug_sampler_view_destroy(struct rbug_context *rb_context, + struct rbug_sampler_view *rb_sampler_view); + +struct pipe_transfer * +rbug_transfer_create(struct rbug_context *rb_context, + struct rbug_resource *rb_resource, + struct pipe_transfer *transfer); + +void +rbug_transfer_destroy(struct rbug_context *rb_context, + struct rbug_transfer *rb_transfer); + +void * +rbug_shader_create(struct rbug_context *rb_context, + const struct pipe_shader_state *state, + void *result, enum rbug_shader_type type); + +void +rbug_shader_destroy(struct rbug_context *rb_context, + struct rbug_shader *rb_shader); + + +#endif /* RBUG_OBJECTS_H */ diff --git a/src/gallium/auxiliary/driver_rbug/rbug_public.h b/src/gallium/auxiliary/driver_rbug/rbug_public.h new file mode 100644 index 00000000000..83f9c94e31f --- /dev/null +++ b/src/gallium/auxiliary/driver_rbug/rbug_public.h @@ -0,0 +1,48 @@ +/************************************************************************** + * + * 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 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 RBUG_PUBLIC_H +#define RBUG_PUBLIC_H + +#ifdef __cplusplus +extern "C" { +#endif + +struct pipe_screen; +struct pipe_context; + +struct pipe_screen * +rbug_screen_create(struct pipe_screen *screen); + +boolean +rbug_enabled(void); + +#ifdef __cplusplus +} +#endif + +#endif /* RBUG_PUBLIC_H */ diff --git a/src/gallium/auxiliary/driver_rbug/rbug_screen.c b/src/gallium/auxiliary/driver_rbug/rbug_screen.c new file mode 100644 index 00000000000..2477edbadf0 --- /dev/null +++ b/src/gallium/auxiliary/driver_rbug/rbug_screen.c @@ -0,0 +1,343 @@ +/************************************************************************** + * + * 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 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_screen.h" +#include "pipe/p_state.h" +#include "util/u_memory.h" +#include "util/u_debug.h" +#include "util/simple_list.h" + +#include "rbug_public.h" +#include "rbug_screen.h" +#include "rbug_context.h" +#include "rbug_objects.h" + +DEBUG_GET_ONCE_BOOL_OPTION(rbug, "GALLIUM_RBUG", FALSE) + +static void +rbug_screen_destroy(struct pipe_screen *_screen) +{ + struct rbug_screen *rb_screen = rbug_screen(_screen); + struct pipe_screen *screen = rb_screen->screen; + + screen->destroy(screen); + + FREE(rb_screen); +} + +static const char * +rbug_screen_get_name(struct pipe_screen *_screen) +{ + struct rbug_screen *rb_screen = rbug_screen(_screen); + struct pipe_screen *screen = rb_screen->screen; + + return screen->get_name(screen); +} + +static const char * +rbug_screen_get_vendor(struct pipe_screen *_screen) +{ + struct rbug_screen *rb_screen = rbug_screen(_screen); + struct pipe_screen *screen = rb_screen->screen; + + return screen->get_vendor(screen); +} + +static const char * +rbug_screen_get_device_vendor(struct pipe_screen *_screen) +{ + struct rbug_screen *rb_screen = rbug_screen(_screen); + struct pipe_screen *screen = rb_screen->screen; + + return screen->get_device_vendor(screen); +} + +static struct disk_cache * +rbug_screen_get_disk_shader_cache(struct pipe_screen *_screen) +{ + struct pipe_screen *screen = rbug_screen(_screen)->screen; + + return screen->get_disk_shader_cache(screen); +} + +static int +rbug_screen_get_param(struct pipe_screen *_screen, + enum pipe_cap param) +{ + struct rbug_screen *rb_screen = rbug_screen(_screen); + struct pipe_screen *screen = rb_screen->screen; + + return screen->get_param(screen, + param); +} + +static int +rbug_screen_get_shader_param(struct pipe_screen *_screen, + enum pipe_shader_type shader, + enum pipe_shader_cap param) +{ + struct rbug_screen *rb_screen = rbug_screen(_screen); + struct pipe_screen *screen = rb_screen->screen; + + return screen->get_shader_param(screen, shader, + param); +} + +static float +rbug_screen_get_paramf(struct pipe_screen *_screen, + enum pipe_capf param) +{ + struct rbug_screen *rb_screen = rbug_screen(_screen); + struct pipe_screen *screen = rb_screen->screen; + + return screen->get_paramf(screen, + param); +} + +static boolean +rbug_screen_is_format_supported(struct pipe_screen *_screen, + enum pipe_format format, + enum pipe_texture_target target, + unsigned sample_count, + unsigned tex_usage) +{ + struct rbug_screen *rb_screen = rbug_screen(_screen); + struct pipe_screen *screen = rb_screen->screen; + + return screen->is_format_supported(screen, + format, + target, + sample_count, + tex_usage); +} + +static struct pipe_context * +rbug_screen_context_create(struct pipe_screen *_screen, + void *priv, unsigned flags) +{ + struct rbug_screen *rb_screen = rbug_screen(_screen); + struct pipe_screen *screen = rb_screen->screen; + struct pipe_context *result; + + result = screen->context_create(screen, priv, flags); + if (result) + return rbug_context_create(_screen, result); + return NULL; +} + +static struct pipe_resource * +rbug_screen_resource_create(struct pipe_screen *_screen, + const struct pipe_resource *templat) +{ + struct rbug_screen *rb_screen = rbug_screen(_screen); + struct pipe_screen *screen = rb_screen->screen; + struct pipe_resource *result; + + result = screen->resource_create(screen, + templat); + + if (result) + return rbug_resource_create(rb_screen, result); + return NULL; +} + +static struct pipe_resource * +rbug_screen_resource_from_handle(struct pipe_screen *_screen, + const struct pipe_resource *templ, + struct winsys_handle *handle, + unsigned usage) +{ + struct rbug_screen *rb_screen = rbug_screen(_screen); + struct pipe_screen *screen = rb_screen->screen; + struct pipe_resource *result; + + result = screen->resource_from_handle(screen, templ, handle, usage); + + result = rbug_resource_create(rbug_screen(_screen), result); + + return result; +} + +static bool +rbug_screen_check_resource_capability(struct pipe_screen *_screen, + struct pipe_resource *_resource, + unsigned bind) +{ + struct rbug_screen *rb_screen = rbug_screen(_screen); + struct rbug_resource *rb_resource = rbug_resource(_resource); + struct pipe_screen *screen = rb_screen->screen; + struct pipe_resource *resource = rb_resource->resource; + + return screen->check_resource_capability(screen, resource, bind); +} + +static boolean +rbug_screen_resource_get_handle(struct pipe_screen *_screen, + struct pipe_context *_pipe, + struct pipe_resource *_resource, + struct winsys_handle *handle, + unsigned usage) +{ + struct rbug_screen *rb_screen = rbug_screen(_screen); + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct rbug_resource *rb_resource = rbug_resource(_resource); + struct pipe_screen *screen = rb_screen->screen; + struct pipe_resource *resource = rb_resource->resource; + + return screen->resource_get_handle(screen, rb_pipe ? rb_pipe->pipe : NULL, + resource, handle, usage); +} + +static void +rbug_screen_resource_changed(struct pipe_screen *_screen, + struct pipe_resource *_resource) +{ + struct rbug_screen *rb_screen = rbug_screen(_screen); + struct rbug_resource *rb_resource = rbug_resource(_resource); + struct pipe_screen *screen = rb_screen->screen; + struct pipe_resource *resource = rb_resource->resource; + + screen->resource_changed(screen, resource); +} + +static void +rbug_screen_resource_destroy(struct pipe_screen *screen, + struct pipe_resource *_resource) +{ + rbug_resource_destroy(rbug_resource(_resource)); +} + +static void +rbug_screen_flush_frontbuffer(struct pipe_screen *_screen, + struct pipe_resource *_resource, + unsigned level, unsigned layer, + void *context_private, struct pipe_box *sub_box) +{ + struct rbug_screen *rb_screen = rbug_screen(_screen); + struct rbug_resource *rb_resource = rbug_resource(_resource); + struct pipe_screen *screen = rb_screen->screen; + struct pipe_resource *resource = rb_resource->resource; + + screen->flush_frontbuffer(screen, + resource, + level, layer, + context_private, sub_box); +} + +static void +rbug_screen_fence_reference(struct pipe_screen *_screen, + struct pipe_fence_handle **ptr, + struct pipe_fence_handle *fence) +{ + struct rbug_screen *rb_screen = rbug_screen(_screen); + struct pipe_screen *screen = rb_screen->screen; + + screen->fence_reference(screen, + ptr, + fence); +} + +static boolean +rbug_screen_fence_finish(struct pipe_screen *_screen, + struct pipe_context *_ctx, + struct pipe_fence_handle *fence, + uint64_t timeout) +{ + struct rbug_screen *rb_screen = rbug_screen(_screen); + struct pipe_screen *screen = rb_screen->screen; + struct pipe_context *ctx = _ctx ? rbug_context(_ctx)->pipe : NULL; + + return screen->fence_finish(screen, ctx, fence, timeout); +} + +boolean +rbug_enabled() +{ + return debug_get_option_rbug(); +} + +struct pipe_screen * +rbug_screen_create(struct pipe_screen *screen) +{ + struct rbug_screen *rb_screen; + + if (!debug_get_option_rbug()) + return screen; + + rb_screen = CALLOC_STRUCT(rbug_screen); + if (!rb_screen) + return screen; + + (void) mtx_init(&rb_screen->list_mutex, mtx_plain); + make_empty_list(&rb_screen->contexts); + make_empty_list(&rb_screen->resources); + make_empty_list(&rb_screen->surfaces); + make_empty_list(&rb_screen->transfers); + +#define SCR_INIT(_member) \ + rb_screen->base._member = screen->_member ? rbug_screen_##_member : NULL + + rb_screen->base.destroy = rbug_screen_destroy; + rb_screen->base.get_name = rbug_screen_get_name; + rb_screen->base.get_vendor = rbug_screen_get_vendor; + SCR_INIT(get_disk_shader_cache); + rb_screen->base.get_device_vendor = rbug_screen_get_device_vendor; + rb_screen->base.get_param = rbug_screen_get_param; + rb_screen->base.get_shader_param = rbug_screen_get_shader_param; + rb_screen->base.get_paramf = rbug_screen_get_paramf; + rb_screen->base.is_format_supported = rbug_screen_is_format_supported; + rb_screen->base.context_create = rbug_screen_context_create; + rb_screen->base.resource_create = rbug_screen_resource_create; + rb_screen->base.resource_from_handle = rbug_screen_resource_from_handle; + SCR_INIT(check_resource_capability); + rb_screen->base.resource_get_handle = rbug_screen_resource_get_handle; + SCR_INIT(resource_changed); + rb_screen->base.resource_destroy = rbug_screen_resource_destroy; + rb_screen->base.flush_frontbuffer = rbug_screen_flush_frontbuffer; + rb_screen->base.fence_reference = rbug_screen_fence_reference; + rb_screen->base.fence_finish = rbug_screen_fence_finish; + + rb_screen->screen = screen; + + rb_screen->private_context = screen->context_create(screen, NULL, 0); + if (!rb_screen->private_context) + goto err_free; + + rb_screen->rbug = rbug_start(rb_screen); + + if (!rb_screen->rbug) + goto err_context; + + return &rb_screen->base; + +err_context: + rb_screen->private_context->destroy(rb_screen->private_context); +err_free: + FREE(rb_screen); + return screen; +} diff --git a/src/gallium/auxiliary/driver_rbug/rbug_screen.h b/src/gallium/auxiliary/driver_rbug/rbug_screen.h new file mode 100644 index 00000000000..1972005753b --- /dev/null +++ b/src/gallium/auxiliary/driver_rbug/rbug_screen.h @@ -0,0 +1,100 @@ +/************************************************************************** + * + * 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 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 RBUG_SCREEN_H +#define RBUG_SCREEN_H + +#include "pipe/p_screen.h" +#include "pipe/p_defines.h" + +#include "os/os_thread.h" + +struct rbug_list { + struct rbug_list *next; + struct rbug_list *prev; +}; + + +struct rbug_screen +{ + struct pipe_screen base; + + struct pipe_screen *screen; + struct pipe_context *private_context; + + /* remote debugger */ + struct rbug_rbug *rbug; + + mtx_t list_mutex; + int num_contexts; + int num_resources; + int num_surfaces; + int num_transfers; + struct rbug_list contexts; + struct rbug_list resources; + struct rbug_list surfaces; + struct rbug_list transfers; +}; + +static inline struct rbug_screen * +rbug_screen(struct pipe_screen *screen) +{ + return (struct rbug_screen *)screen; +} + +#define rbug_screen_add_to_list(scr, name, obj) \ + do { \ + mtx_lock(&scr->list_mutex); \ + insert_at_head(&scr->name, &obj->list); \ + scr->num_##name++; \ + mtx_unlock(&scr->list_mutex); \ + } while (0) + +#define rbug_screen_remove_from_list(scr, name, obj) \ + do { \ + mtx_lock(&scr->list_mutex); \ + remove_from_list(&obj->list); \ + scr->num_##name--; \ + mtx_unlock(&scr->list_mutex); \ + } while (0) + + + +/********************************************************** + * rbug_core.c + */ + +struct rbug_rbug; + +struct rbug_rbug * +rbug_start(struct rbug_screen *rb_screen); + +void +rbug_stop(struct rbug_rbug *rbug); + + +#endif /* RBUG_SCREEN_H */ |