diff options
Diffstat (limited to 'src/gallium/drivers')
114 files changed, 5856 insertions, 2008 deletions
diff --git a/src/gallium/drivers/galahad/Makefile b/src/gallium/drivers/galahad/Makefile new file mode 100644 index 0000000000..e9c4f7e28c --- /dev/null +++ b/src/gallium/drivers/galahad/Makefile @@ -0,0 +1,11 @@ +TOP = ../../../.. +include $(TOP)/configs/current + +LIBNAME = galahad + +C_SOURCES = \ + glhd_objects.c \ + glhd_context.c \ + glhd_screen.c + +include ../../Makefile.template diff --git a/src/gallium/drivers/galahad/SConscript b/src/gallium/drivers/galahad/SConscript new file mode 100644 index 0000000000..ca6213cfff --- /dev/null +++ b/src/gallium/drivers/galahad/SConscript @@ -0,0 +1,13 @@ +Import('*') + +env = env.Clone() + +identity = env.ConvenienceLibrary( + target = 'identity', + source = [ + 'glhd_context.c', + 'glhd_objects.c', + 'glhd_screen.c', + ]) + +Export('identity') diff --git a/src/gallium/drivers/galahad/glhd_context.c b/src/gallium/drivers/galahad/glhd_context.c new file mode 100644 index 0000000000..ab6f17b3ab --- /dev/null +++ b/src/gallium/drivers/galahad/glhd_context.c @@ -0,0 +1,997 @@ +/************************************************************************** + * + * Copyright 2009 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + + +#include "pipe/p_context.h" + +#include "util/u_format.h" +#include "util/u_memory.h" +#include "util/u_inlines.h" + +#include "glhd_context.h" +#include "glhd_objects.h" + + +static void +galahad_destroy(struct pipe_context *_pipe) +{ + struct galahad_context *glhd_pipe = galahad_context(_pipe); + struct pipe_context *pipe = glhd_pipe->pipe; + + pipe->destroy(pipe); + + FREE(glhd_pipe); +} + +static void +galahad_draw_arrays(struct pipe_context *_pipe, + unsigned prim, + unsigned start, + unsigned count) +{ + struct galahad_context *glhd_pipe = galahad_context(_pipe); + struct pipe_context *pipe = glhd_pipe->pipe; + + pipe->draw_arrays(pipe, + prim, + start, + count); +} + +static void +galahad_draw_elements(struct pipe_context *_pipe, + struct pipe_resource *_indexResource, + unsigned indexSize, + int indexBias, + unsigned prim, + unsigned start, + unsigned count) +{ + struct galahad_context *glhd_pipe = galahad_context(_pipe); + struct galahad_resource *glhd_resource = galahad_resource(_indexResource); + struct pipe_context *pipe = glhd_pipe->pipe; + struct pipe_resource *indexResource = glhd_resource->resource; + + pipe->draw_elements(pipe, + indexResource, + indexSize, + indexBias, + prim, + start, + count); +} + +static void +galahad_draw_range_elements(struct pipe_context *_pipe, + struct pipe_resource *_indexResource, + unsigned indexSize, + int indexBias, + unsigned minIndex, + unsigned maxIndex, + unsigned mode, + unsigned start, + unsigned count) +{ + struct galahad_context *glhd_pipe = galahad_context(_pipe); + struct galahad_resource *glhd_resource = galahad_resource(_indexResource); + struct pipe_context *pipe = glhd_pipe->pipe; + struct pipe_resource *indexResource = glhd_resource->resource; + + pipe->draw_range_elements(pipe, + indexResource, + indexSize, + indexBias, + minIndex, + maxIndex, + mode, + start, + count); +} + +static struct pipe_query * +galahad_create_query(struct pipe_context *_pipe, + unsigned query_type) +{ + struct galahad_context *glhd_pipe = galahad_context(_pipe); + struct pipe_context *pipe = glhd_pipe->pipe; + + if (query_type == PIPE_QUERY_OCCLUSION_COUNTER && + !pipe->screen->get_param(pipe->screen, PIPE_CAP_OCCLUSION_QUERY)) { + glhd_error("Occlusion query requested but not supported"); + } + + if (query_type == PIPE_QUERY_TIME_ELAPSED && + !pipe->screen->get_param(pipe->screen, PIPE_CAP_TIMER_QUERY)) { + glhd_error("Timer query requested but not supported"); + } + + return pipe->create_query(pipe, + query_type); +} + +static void +galahad_destroy_query(struct pipe_context *_pipe, + struct pipe_query *query) +{ + struct galahad_context *glhd_pipe = galahad_context(_pipe); + struct pipe_context *pipe = glhd_pipe->pipe; + + pipe->destroy_query(pipe, + query); +} + +static void +galahad_begin_query(struct pipe_context *_pipe, + struct pipe_query *query) +{ + struct galahad_context *glhd_pipe = galahad_context(_pipe); + struct pipe_context *pipe = glhd_pipe->pipe; + + pipe->begin_query(pipe, + query); +} + +static void +galahad_end_query(struct pipe_context *_pipe, + struct pipe_query *query) +{ + struct galahad_context *glhd_pipe = galahad_context(_pipe); + struct pipe_context *pipe = glhd_pipe->pipe; + + pipe->end_query(pipe, + query); +} + +static boolean +galahad_get_query_result(struct pipe_context *_pipe, + struct pipe_query *query, + boolean wait, + void *result) +{ + struct galahad_context *glhd_pipe = galahad_context(_pipe); + struct pipe_context *pipe = glhd_pipe->pipe; + + return pipe->get_query_result(pipe, + query, + wait, + result); +} + +static void * +galahad_create_blend_state(struct pipe_context *_pipe, + const struct pipe_blend_state *blend) +{ + struct galahad_context *glhd_pipe = galahad_context(_pipe); + struct pipe_context *pipe = glhd_pipe->pipe; + + if (blend->logicop_enable) { + if (blend->rt[0].blend_enable) { + glhd_warn("Blending enabled for render target 0, but logicops " + "are enabled"); + } + } + + return pipe->create_blend_state(pipe, + blend); +} + +static void +galahad_bind_blend_state(struct pipe_context *_pipe, + void *blend) +{ + struct galahad_context *glhd_pipe = galahad_context(_pipe); + struct pipe_context *pipe = glhd_pipe->pipe; + + pipe->bind_blend_state(pipe, + blend); +} + +static void +galahad_delete_blend_state(struct pipe_context *_pipe, + void *blend) +{ + struct galahad_context *glhd_pipe = galahad_context(_pipe); + struct pipe_context *pipe = glhd_pipe->pipe; + + pipe->delete_blend_state(pipe, + blend); +} + +static void * +galahad_create_sampler_state(struct pipe_context *_pipe, + const struct pipe_sampler_state *sampler) +{ + struct galahad_context *glhd_pipe = galahad_context(_pipe); + struct pipe_context *pipe = glhd_pipe->pipe; + + return pipe->create_sampler_state(pipe, + sampler); +} + +static void +galahad_bind_fragment_sampler_states(struct pipe_context *_pipe, + unsigned num_samplers, + void **samplers) +{ + struct galahad_context *glhd_pipe = galahad_context(_pipe); + struct pipe_context *pipe = glhd_pipe->pipe; + + pipe->bind_fragment_sampler_states(pipe, + num_samplers, + samplers); +} + +static void +galahad_bind_vertex_sampler_states(struct pipe_context *_pipe, + unsigned num_samplers, + void **samplers) +{ + struct galahad_context *glhd_pipe = galahad_context(_pipe); + struct pipe_context *pipe = glhd_pipe->pipe; + + pipe->bind_vertex_sampler_states(pipe, + num_samplers, + samplers); +} + +static void +galahad_delete_sampler_state(struct pipe_context *_pipe, + void *sampler) +{ + struct galahad_context *glhd_pipe = galahad_context(_pipe); + struct pipe_context *pipe = glhd_pipe->pipe; + + pipe->delete_sampler_state(pipe, + sampler); +} + +static void * +galahad_create_rasterizer_state(struct pipe_context *_pipe, + const struct pipe_rasterizer_state *rasterizer) +{ + struct galahad_context *glhd_pipe = galahad_context(_pipe); + struct pipe_context *pipe = glhd_pipe->pipe; + + if (rasterizer->point_quad_rasterization) { + if (rasterizer->point_smooth) { + glhd_warn("Point smoothing requested but ignored"); + } + } else { + if (rasterizer->sprite_coord_enable) { + glhd_warn("Point sprites requested but ignored"); + } + } + + return pipe->create_rasterizer_state(pipe, + rasterizer); +} + +static void +galahad_bind_rasterizer_state(struct pipe_context *_pipe, + void *rasterizer) +{ + struct galahad_context *glhd_pipe = galahad_context(_pipe); + struct pipe_context *pipe = glhd_pipe->pipe; + + pipe->bind_rasterizer_state(pipe, + rasterizer); +} + +static void +galahad_delete_rasterizer_state(struct pipe_context *_pipe, + void *rasterizer) +{ + struct galahad_context *glhd_pipe = galahad_context(_pipe); + struct pipe_context *pipe = glhd_pipe->pipe; + + pipe->delete_rasterizer_state(pipe, + rasterizer); +} + +static void * +galahad_create_depth_stencil_alpha_state(struct pipe_context *_pipe, + const struct pipe_depth_stencil_alpha_state *depth_stencil_alpha) +{ + struct galahad_context *glhd_pipe = galahad_context(_pipe); + struct pipe_context *pipe = glhd_pipe->pipe; + + return pipe->create_depth_stencil_alpha_state(pipe, + depth_stencil_alpha); +} + +static void +galahad_bind_depth_stencil_alpha_state(struct pipe_context *_pipe, + void *depth_stencil_alpha) +{ + struct galahad_context *glhd_pipe = galahad_context(_pipe); + struct pipe_context *pipe = glhd_pipe->pipe; + + pipe->bind_depth_stencil_alpha_state(pipe, + depth_stencil_alpha); +} + +static void +galahad_delete_depth_stencil_alpha_state(struct pipe_context *_pipe, + void *depth_stencil_alpha) +{ + struct galahad_context *glhd_pipe = galahad_context(_pipe); + struct pipe_context *pipe = glhd_pipe->pipe; + + pipe->delete_depth_stencil_alpha_state(pipe, + depth_stencil_alpha); +} + +static void * +galahad_create_fs_state(struct pipe_context *_pipe, + const struct pipe_shader_state *fs) +{ + struct galahad_context *glhd_pipe = galahad_context(_pipe); + struct pipe_context *pipe = glhd_pipe->pipe; + + return pipe->create_fs_state(pipe, + fs); +} + +static void +galahad_bind_fs_state(struct pipe_context *_pipe, + void *fs) +{ + struct galahad_context *glhd_pipe = galahad_context(_pipe); + struct pipe_context *pipe = glhd_pipe->pipe; + + pipe->bind_fs_state(pipe, + fs); +} + +static void +galahad_delete_fs_state(struct pipe_context *_pipe, + void *fs) +{ + struct galahad_context *glhd_pipe = galahad_context(_pipe); + struct pipe_context *pipe = glhd_pipe->pipe; + + pipe->delete_fs_state(pipe, + fs); +} + +static void * +galahad_create_vs_state(struct pipe_context *_pipe, + const struct pipe_shader_state *vs) +{ + struct galahad_context *glhd_pipe = galahad_context(_pipe); + struct pipe_context *pipe = glhd_pipe->pipe; + + return pipe->create_vs_state(pipe, + vs); +} + +static void +galahad_bind_vs_state(struct pipe_context *_pipe, + void *vs) +{ + struct galahad_context *glhd_pipe = galahad_context(_pipe); + struct pipe_context *pipe = glhd_pipe->pipe; + + pipe->bind_vs_state(pipe, + vs); +} + +static void +galahad_delete_vs_state(struct pipe_context *_pipe, + void *vs) +{ + struct galahad_context *glhd_pipe = galahad_context(_pipe); + struct pipe_context *pipe = glhd_pipe->pipe; + + pipe->delete_vs_state(pipe, + vs); +} + + +static void * +galahad_create_vertex_elements_state(struct pipe_context *_pipe, + unsigned num_elements, + const struct pipe_vertex_element *vertex_elements) +{ + struct galahad_context *glhd_pipe = galahad_context(_pipe); + struct pipe_context *pipe = glhd_pipe->pipe; + + return pipe->create_vertex_elements_state(pipe, + num_elements, + vertex_elements); +} + +static void +galahad_bind_vertex_elements_state(struct pipe_context *_pipe, + void *velems) +{ + struct galahad_context *glhd_pipe = galahad_context(_pipe); + struct pipe_context *pipe = glhd_pipe->pipe; + + pipe->bind_vertex_elements_state(pipe, + velems); +} + +static void +galahad_delete_vertex_elements_state(struct pipe_context *_pipe, + void *velems) +{ + struct galahad_context *glhd_pipe = galahad_context(_pipe); + struct pipe_context *pipe = glhd_pipe->pipe; + + pipe->delete_vertex_elements_state(pipe, + velems); +} + +static void +galahad_set_blend_color(struct pipe_context *_pipe, + const struct pipe_blend_color *blend_color) +{ + struct galahad_context *glhd_pipe = galahad_context(_pipe); + struct pipe_context *pipe = glhd_pipe->pipe; + + pipe->set_blend_color(pipe, + blend_color); +} + +static void +galahad_set_stencil_ref(struct pipe_context *_pipe, + const struct pipe_stencil_ref *stencil_ref) +{ + struct galahad_context *glhd_pipe = galahad_context(_pipe); + struct pipe_context *pipe = glhd_pipe->pipe; + + pipe->set_stencil_ref(pipe, + stencil_ref); +} + +static void +galahad_set_clip_state(struct pipe_context *_pipe, + const struct pipe_clip_state *clip) +{ + struct galahad_context *glhd_pipe = galahad_context(_pipe); + struct pipe_context *pipe = glhd_pipe->pipe; + + pipe->set_clip_state(pipe, + clip); +} + +static void +galahad_set_sample_mask(struct pipe_context *_pipe, + unsigned sample_mask) +{ + struct galahad_context *glhd_pipe = galahad_context(_pipe); + struct pipe_context *pipe = glhd_pipe->pipe; + + pipe->set_sample_mask(pipe, + sample_mask); +} + +static void +galahad_set_constant_buffer(struct pipe_context *_pipe, + uint shader, + uint index, + struct pipe_resource *_resource) +{ + struct galahad_context *glhd_pipe = galahad_context(_pipe); + struct pipe_context *pipe = glhd_pipe->pipe; + struct pipe_resource *unwrapped_resource; + struct pipe_resource *resource = NULL; + + /* XXX hmm? unwrap the input state */ + if (_resource) { + unwrapped_resource = galahad_resource_unwrap(_resource); + resource = unwrapped_resource; + } + + pipe->set_constant_buffer(pipe, + shader, + index, + resource); +} + +static void +galahad_set_framebuffer_state(struct pipe_context *_pipe, + const struct pipe_framebuffer_state *_state) +{ + struct galahad_context *glhd_pipe = galahad_context(_pipe); + struct pipe_context *pipe = glhd_pipe->pipe; + struct pipe_framebuffer_state unwrapped_state; + struct pipe_framebuffer_state *state = NULL; + unsigned i; + + if (_state->nr_cbufs > PIPE_MAX_COLOR_BUFS) { + glhd_error("%d render targets bound, but only %d are permitted by API", + _state->nr_cbufs, PIPE_MAX_COLOR_BUFS); + } else if (_state->nr_cbufs > + pipe->screen->get_param(pipe->screen, PIPE_CAP_MAX_RENDER_TARGETS)) { + glhd_warn("%d render targets bound, but only %d are supported", + _state->nr_cbufs, + pipe->screen->get_param(pipe->screen, PIPE_CAP_MAX_RENDER_TARGETS)); + } + + /* unwrap the input state */ + if (_state) { + memcpy(&unwrapped_state, _state, sizeof(unwrapped_state)); + for(i = 0; i < _state->nr_cbufs; i++) + unwrapped_state.cbufs[i] = galahad_surface_unwrap(_state->cbufs[i]); + for (; i < PIPE_MAX_COLOR_BUFS; i++) + unwrapped_state.cbufs[i] = NULL; + unwrapped_state.zsbuf = galahad_surface_unwrap(_state->zsbuf); + state = &unwrapped_state; + } + + pipe->set_framebuffer_state(pipe, + state); +} + +static void +galahad_set_polygon_stipple(struct pipe_context *_pipe, + const struct pipe_poly_stipple *poly_stipple) +{ + struct galahad_context *glhd_pipe = galahad_context(_pipe); + struct pipe_context *pipe = glhd_pipe->pipe; + + pipe->set_polygon_stipple(pipe, + poly_stipple); +} + +static void +galahad_set_scissor_state(struct pipe_context *_pipe, + const struct pipe_scissor_state *scissor) +{ + struct galahad_context *glhd_pipe = galahad_context(_pipe); + struct pipe_context *pipe = glhd_pipe->pipe; + + pipe->set_scissor_state(pipe, + scissor); +} + +static void +galahad_set_viewport_state(struct pipe_context *_pipe, + const struct pipe_viewport_state *viewport) +{ + struct galahad_context *glhd_pipe = galahad_context(_pipe); + struct pipe_context *pipe = glhd_pipe->pipe; + + pipe->set_viewport_state(pipe, + viewport); +} + +static void +galahad_set_fragment_sampler_views(struct pipe_context *_pipe, + unsigned num, + struct pipe_sampler_view **_views) +{ + struct galahad_context *glhd_pipe = galahad_context(_pipe); + struct pipe_context *pipe = glhd_pipe->pipe; + struct pipe_sampler_view *unwrapped_views[PIPE_MAX_SAMPLERS]; + struct pipe_sampler_view **views = NULL; + unsigned i; + + if (_views) { + for (i = 0; i < num; i++) + unwrapped_views[i] = galahad_sampler_view_unwrap(_views[i]); + for (; i < PIPE_MAX_SAMPLERS; i++) + unwrapped_views[i] = NULL; + + views = unwrapped_views; + } + + pipe->set_fragment_sampler_views(pipe, num, views); +} + +static void +galahad_set_vertex_sampler_views(struct pipe_context *_pipe, + unsigned num, + struct pipe_sampler_view **_views) +{ + struct galahad_context *glhd_pipe = galahad_context(_pipe); + struct pipe_context *pipe = glhd_pipe->pipe; + struct pipe_sampler_view *unwrapped_views[PIPE_MAX_VERTEX_SAMPLERS]; + struct pipe_sampler_view **views = NULL; + unsigned i; + + if (_views) { + for (i = 0; i < num; i++) + unwrapped_views[i] = galahad_sampler_view_unwrap(_views[i]); + for (; i < PIPE_MAX_VERTEX_SAMPLERS; i++) + unwrapped_views[i] = NULL; + + views = unwrapped_views; + } + + pipe->set_vertex_sampler_views(pipe, num, views); +} + +static void +galahad_set_vertex_buffers(struct pipe_context *_pipe, + unsigned num_buffers, + const struct pipe_vertex_buffer *_buffers) +{ + struct galahad_context *glhd_pipe = galahad_context(_pipe); + struct pipe_context *pipe = glhd_pipe->pipe; + struct pipe_vertex_buffer unwrapped_buffers[PIPE_MAX_SHADER_INPUTS]; + struct pipe_vertex_buffer *buffers = NULL; + unsigned i; + + if (num_buffers) { + memcpy(unwrapped_buffers, _buffers, num_buffers * sizeof(*_buffers)); + for (i = 0; i < num_buffers; i++) + unwrapped_buffers[i].buffer = galahad_resource_unwrap(_buffers[i].buffer); + buffers = unwrapped_buffers; + } + + pipe->set_vertex_buffers(pipe, + num_buffers, + buffers); +} +static void +galahad_resource_copy_region(struct pipe_context *_pipe, + struct pipe_resource *_dst, + struct pipe_subresource subdst, + unsigned dstx, + unsigned dsty, + unsigned dstz, + struct pipe_resource *_src, + struct pipe_subresource subsrc, + unsigned srcx, + unsigned srcy, + unsigned srcz, + unsigned width, + unsigned height) +{ + struct galahad_context *glhd_pipe = galahad_context(_pipe); + struct galahad_resource *glhd_resource_dst = galahad_resource(_dst); + struct galahad_resource *glhd_resource_src = galahad_resource(_src); + struct pipe_context *pipe = glhd_pipe->pipe; + struct pipe_resource *dst = glhd_resource_dst->resource; + struct pipe_resource *src = glhd_resource_src->resource; + + if (_dst->format != _src->format) { + glhd_warn("Format mismatch: Source is %s, destination is %s", + util_format_short_name(_src->format), + util_format_short_name(_dst->format)); + } + + pipe->resource_copy_region(pipe, + dst, + subdst, + dstx, + dsty, + dstz, + src, + subsrc, + srcx, + srcy, + srcz, + width, + height); +} + +static void +galahad_clear(struct pipe_context *_pipe, + unsigned buffers, + const float *rgba, + double depth, + unsigned stencil) +{ + struct galahad_context *glhd_pipe = galahad_context(_pipe); + struct pipe_context *pipe = glhd_pipe->pipe; + + pipe->clear(pipe, + buffers, + rgba, + depth, + stencil); +} + +static void +galahad_clear_render_target(struct pipe_context *_pipe, + struct pipe_surface *_dst, + const float *rgba, + unsigned dstx, unsigned dsty, + unsigned width, unsigned height) +{ + struct galahad_context *glhd_pipe = galahad_context(_pipe); + struct galahad_surface *glhd_surface_dst = galahad_surface(_dst); + struct pipe_context *pipe = glhd_pipe->pipe; + struct pipe_surface *dst = glhd_surface_dst->surface; + + pipe->clear_render_target(pipe, + dst, + rgba, + dstx, + dsty, + width, + height); +} +static void +galahad_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) +{ + struct galahad_context *glhd_pipe = galahad_context(_pipe); + struct galahad_surface *glhd_surface_dst = galahad_surface(_dst); + struct pipe_context *pipe = glhd_pipe->pipe; + struct pipe_surface *dst = glhd_surface_dst->surface; + + pipe->clear_depth_stencil(pipe, + dst, + clear_flags, + depth, + stencil, + dstx, + dsty, + width, + height); + +} + +static void +galahad_flush(struct pipe_context *_pipe, + unsigned flags, + struct pipe_fence_handle **fence) +{ + struct galahad_context *glhd_pipe = galahad_context(_pipe); + struct pipe_context *pipe = glhd_pipe->pipe; + + pipe->flush(pipe, + flags, + fence); +} + +static unsigned int +galahad_is_resource_referenced(struct pipe_context *_pipe, + struct pipe_resource *_resource, + unsigned face, + unsigned level) +{ + struct galahad_context *glhd_pipe = galahad_context(_pipe); + struct galahad_resource *glhd_resource = galahad_resource(_resource); + struct pipe_context *pipe = glhd_pipe->pipe; + struct pipe_resource *resource = glhd_resource->resource; + + return pipe->is_resource_referenced(pipe, + resource, + face, + level); +} + +static struct pipe_sampler_view * +galahad_context_create_sampler_view(struct pipe_context *_pipe, + struct pipe_resource *_resource, + const struct pipe_sampler_view *templ) +{ + struct galahad_context *glhd_context = galahad_context(_pipe); + struct galahad_resource *glhd_resource = galahad_resource(_resource); + struct pipe_context *pipe = glhd_context->pipe; + struct pipe_resource *resource = glhd_resource->resource; + struct pipe_sampler_view *result; + + result = pipe->create_sampler_view(pipe, + resource, + templ); + + if (result) + return galahad_sampler_view_create(glhd_context, glhd_resource, result); + return NULL; +} + +static void +galahad_context_sampler_view_destroy(struct pipe_context *_pipe, + struct pipe_sampler_view *_view) +{ + galahad_sampler_view_destroy(galahad_context(_pipe), + galahad_sampler_view(_view)); +} + +static struct pipe_transfer * +galahad_context_get_transfer(struct pipe_context *_context, + struct pipe_resource *_resource, + struct pipe_subresource sr, + unsigned usage, + const struct pipe_box *box) +{ + struct galahad_context *glhd_context = galahad_context(_context); + struct galahad_resource *glhd_resource = galahad_resource(_resource); + struct pipe_context *context = glhd_context->pipe; + struct pipe_resource *resource = glhd_resource->resource; + struct pipe_transfer *result; + + result = context->get_transfer(context, + resource, + sr, + usage, + box); + + if (result) + return galahad_transfer_create(glhd_context, glhd_resource, result); + return NULL; +} + +static void +galahad_context_transfer_destroy(struct pipe_context *_pipe, + struct pipe_transfer *_transfer) +{ + galahad_transfer_destroy(galahad_context(_pipe), + galahad_transfer(_transfer)); +} + +static void * +galahad_context_transfer_map(struct pipe_context *_context, + struct pipe_transfer *_transfer) +{ + struct galahad_context *glhd_context = galahad_context(_context); + struct galahad_transfer *glhd_transfer = galahad_transfer(_transfer); + struct pipe_context *context = glhd_context->pipe; + struct pipe_transfer *transfer = glhd_transfer->transfer; + + return context->transfer_map(context, + transfer); +} + + + +static void +galahad_context_transfer_flush_region(struct pipe_context *_context, + struct pipe_transfer *_transfer, + const struct pipe_box *box) +{ + struct galahad_context *glhd_context = galahad_context(_context); + struct galahad_transfer *glhd_transfer = galahad_transfer(_transfer); + struct pipe_context *context = glhd_context->pipe; + struct pipe_transfer *transfer = glhd_transfer->transfer; + + context->transfer_flush_region(context, + transfer, + box); +} + + +static void +galahad_context_transfer_unmap(struct pipe_context *_context, + struct pipe_transfer *_transfer) +{ + struct galahad_context *glhd_context = galahad_context(_context); + struct galahad_transfer *glhd_transfer = galahad_transfer(_transfer); + struct pipe_context *context = glhd_context->pipe; + struct pipe_transfer *transfer = glhd_transfer->transfer; + + context->transfer_unmap(context, + transfer); +} + + +static void +galahad_context_transfer_inline_write(struct pipe_context *_context, + struct pipe_resource *_resource, + struct pipe_subresource sr, + unsigned usage, + const struct pipe_box *box, + const void *data, + unsigned stride, + unsigned slice_stride) +{ + struct galahad_context *glhd_context = galahad_context(_context); + struct galahad_resource *glhd_resource = galahad_resource(_resource); + struct pipe_context *context = glhd_context->pipe; + struct pipe_resource *resource = glhd_resource->resource; + + context->transfer_inline_write(context, + resource, + sr, + usage, + box, + data, + stride, + slice_stride); +} + + +struct pipe_context * +galahad_context_create(struct pipe_screen *_screen, struct pipe_context *pipe) +{ + struct galahad_context *glhd_pipe; + (void)galahad_screen(_screen); + + glhd_pipe = CALLOC_STRUCT(galahad_context); + if (!glhd_pipe) { + return NULL; + } + + glhd_pipe->base.winsys = NULL; + glhd_pipe->base.screen = _screen; + glhd_pipe->base.priv = pipe->priv; /* expose wrapped data */ + glhd_pipe->base.draw = NULL; + + glhd_pipe->base.destroy = galahad_destroy; + glhd_pipe->base.draw_arrays = galahad_draw_arrays; + glhd_pipe->base.draw_elements = galahad_draw_elements; + glhd_pipe->base.draw_range_elements = galahad_draw_range_elements; + glhd_pipe->base.create_query = galahad_create_query; + glhd_pipe->base.destroy_query = galahad_destroy_query; + glhd_pipe->base.begin_query = galahad_begin_query; + glhd_pipe->base.end_query = galahad_end_query; + glhd_pipe->base.get_query_result = galahad_get_query_result; + glhd_pipe->base.create_blend_state = galahad_create_blend_state; + glhd_pipe->base.bind_blend_state = galahad_bind_blend_state; + glhd_pipe->base.delete_blend_state = galahad_delete_blend_state; + glhd_pipe->base.create_sampler_state = galahad_create_sampler_state; + glhd_pipe->base.bind_fragment_sampler_states = galahad_bind_fragment_sampler_states; + glhd_pipe->base.bind_vertex_sampler_states = galahad_bind_vertex_sampler_states; + glhd_pipe->base.delete_sampler_state = galahad_delete_sampler_state; + glhd_pipe->base.create_rasterizer_state = galahad_create_rasterizer_state; + glhd_pipe->base.bind_rasterizer_state = galahad_bind_rasterizer_state; + glhd_pipe->base.delete_rasterizer_state = galahad_delete_rasterizer_state; + glhd_pipe->base.create_depth_stencil_alpha_state = galahad_create_depth_stencil_alpha_state; + glhd_pipe->base.bind_depth_stencil_alpha_state = galahad_bind_depth_stencil_alpha_state; + glhd_pipe->base.delete_depth_stencil_alpha_state = galahad_delete_depth_stencil_alpha_state; + glhd_pipe->base.create_fs_state = galahad_create_fs_state; + glhd_pipe->base.bind_fs_state = galahad_bind_fs_state; + glhd_pipe->base.delete_fs_state = galahad_delete_fs_state; + glhd_pipe->base.create_vs_state = galahad_create_vs_state; + glhd_pipe->base.bind_vs_state = galahad_bind_vs_state; + glhd_pipe->base.delete_vs_state = galahad_delete_vs_state; + glhd_pipe->base.create_vertex_elements_state = galahad_create_vertex_elements_state; + glhd_pipe->base.bind_vertex_elements_state = galahad_bind_vertex_elements_state; + glhd_pipe->base.delete_vertex_elements_state = galahad_delete_vertex_elements_state; + glhd_pipe->base.set_blend_color = galahad_set_blend_color; + glhd_pipe->base.set_stencil_ref = galahad_set_stencil_ref; + glhd_pipe->base.set_clip_state = galahad_set_clip_state; + glhd_pipe->base.set_sample_mask = galahad_set_sample_mask; + glhd_pipe->base.set_constant_buffer = galahad_set_constant_buffer; + glhd_pipe->base.set_framebuffer_state = galahad_set_framebuffer_state; + glhd_pipe->base.set_polygon_stipple = galahad_set_polygon_stipple; + glhd_pipe->base.set_scissor_state = galahad_set_scissor_state; + glhd_pipe->base.set_viewport_state = galahad_set_viewport_state; + glhd_pipe->base.set_fragment_sampler_views = galahad_set_fragment_sampler_views; + glhd_pipe->base.set_vertex_sampler_views = galahad_set_vertex_sampler_views; + glhd_pipe->base.set_vertex_buffers = galahad_set_vertex_buffers; + glhd_pipe->base.resource_copy_region = galahad_resource_copy_region; + glhd_pipe->base.clear = galahad_clear; + glhd_pipe->base.clear_render_target = galahad_clear_render_target; + glhd_pipe->base.clear_depth_stencil = galahad_clear_depth_stencil; + glhd_pipe->base.flush = galahad_flush; + glhd_pipe->base.is_resource_referenced = galahad_is_resource_referenced; + glhd_pipe->base.create_sampler_view = galahad_context_create_sampler_view; + glhd_pipe->base.sampler_view_destroy = galahad_context_sampler_view_destroy; + glhd_pipe->base.get_transfer = galahad_context_get_transfer; + glhd_pipe->base.transfer_destroy = galahad_context_transfer_destroy; + glhd_pipe->base.transfer_map = galahad_context_transfer_map; + glhd_pipe->base.transfer_unmap = galahad_context_transfer_unmap; + glhd_pipe->base.transfer_flush_region = galahad_context_transfer_flush_region; + glhd_pipe->base.transfer_inline_write = galahad_context_transfer_inline_write; + + glhd_pipe->pipe = pipe; + + return &glhd_pipe->base; +} diff --git a/src/gallium/drivers/galahad/glhd_context.h b/src/gallium/drivers/galahad/glhd_context.h new file mode 100644 index 0000000000..4e71753ac3 --- /dev/null +++ b/src/gallium/drivers/galahad/glhd_context.h @@ -0,0 +1,64 @@ +/************************************************************************** + * + * Copyright 2009 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef GLHD_CONTEXT_H +#define GLHD_CONTEXT_H + +#include <stdio.h> + +#include "pipe/p_state.h" +#include "pipe/p_context.h" + + +struct galahad_context { + struct pipe_context base; /**< base class */ + + struct pipe_context *pipe; +}; + + +struct pipe_context * +galahad_context_create(struct pipe_screen *screen, struct pipe_context *pipe); + + +static INLINE struct galahad_context * +galahad_context(struct pipe_context *pipe) +{ + return (struct galahad_context *)pipe; +} + +#define glhd_warn(...) \ +do { \ + fprintf(stderr, "galahad: %s: ", __FUNCTION__); \ + fprintf(stderr, __VA_ARGS__); \ + fprintf(stderr, "\n"); \ +} while (0) + +#define glhd_error(...) \ + glhd_warn(__VA_ARGS__); + +#endif /* GLHD_CONTEXT_H */ diff --git a/src/gallium/drivers/galahad/glhd_drm.h b/src/gallium/drivers/galahad/glhd_drm.h new file mode 100644 index 0000000000..613ac24946 --- /dev/null +++ b/src/gallium/drivers/galahad/glhd_drm.h @@ -0,0 +1,35 @@ +/************************************************************************** + * + * Copyright 2009 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef GLHD_DRM_H +#define GLHD_DRM_H + +struct drm_api; + +struct drm_api* galahad_drm_create(struct drm_api *api); + +#endif /* GLHD_DRM_H */ diff --git a/src/gallium/drivers/galahad/glhd_objects.c b/src/gallium/drivers/galahad/glhd_objects.c new file mode 100644 index 0000000000..6c5a21ae70 --- /dev/null +++ b/src/gallium/drivers/galahad/glhd_objects.c @@ -0,0 +1,187 @@ +/************************************************************************** + * + * Copyright 2009 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "util/u_inlines.h" +#include "util/u_memory.h" + +#include "glhd_screen.h" +#include "glhd_objects.h" +#include "glhd_context.h" + + + +struct pipe_resource * +galahad_resource_create(struct galahad_screen *glhd_screen, + struct pipe_resource *resource) +{ + struct galahad_resource *glhd_resource; + + if(!resource) + goto error; + + assert(resource->screen == glhd_screen->screen); + + glhd_resource = CALLOC_STRUCT(galahad_resource); + if(!glhd_resource) + goto error; + + memcpy(&glhd_resource->base, resource, sizeof(struct pipe_resource)); + + pipe_reference_init(&glhd_resource->base.reference, 1); + glhd_resource->base.screen = &glhd_screen->base; + glhd_resource->resource = resource; + + return &glhd_resource->base; + +error: + pipe_resource_reference(&resource, NULL); + return NULL; +} + +void +galahad_resource_destroy(struct galahad_resource *glhd_resource) +{ + pipe_resource_reference(&glhd_resource->resource, NULL); + FREE(glhd_resource); +} + + +struct pipe_surface * +galahad_surface_create(struct galahad_resource *glhd_resource, + struct pipe_surface *surface) +{ + struct galahad_surface *glhd_surface; + + if(!surface) + goto error; + + assert(surface->texture == glhd_resource->resource); + + glhd_surface = CALLOC_STRUCT(galahad_surface); + if(!glhd_surface) + goto error; + + memcpy(&glhd_surface->base, surface, sizeof(struct pipe_surface)); + + pipe_reference_init(&glhd_surface->base.reference, 1); + glhd_surface->base.texture = NULL; + pipe_resource_reference(&glhd_surface->base.texture, &glhd_resource->base); + glhd_surface->surface = surface; + + return &glhd_surface->base; + +error: + pipe_surface_reference(&surface, NULL); + return NULL; +} + +void +galahad_surface_destroy(struct galahad_surface *glhd_surface) +{ + pipe_resource_reference(&glhd_surface->base.texture, NULL); + pipe_surface_reference(&glhd_surface->surface, NULL); + FREE(glhd_surface); +} + + +struct pipe_sampler_view * +galahad_sampler_view_create(struct galahad_context *glhd_context, + struct galahad_resource *glhd_resource, + struct pipe_sampler_view *view) +{ + struct galahad_sampler_view *glhd_view; + + if (!view) + goto error; + + assert(view->texture == glhd_resource->resource); + + glhd_view = CALLOC_STRUCT(galahad_sampler_view); + + glhd_view->base = *view; + glhd_view->base.reference.count = 1; + glhd_view->base.texture = NULL; + pipe_resource_reference(&glhd_view->base.texture, glhd_resource->resource); + glhd_view->base.context = glhd_context->pipe; + glhd_view->sampler_view = view; + + return &glhd_view->base; +error: + return NULL; +} + +void +galahad_sampler_view_destroy(struct galahad_context *glhd_context, + struct galahad_sampler_view *glhd_view) +{ + pipe_resource_reference(&glhd_view->base.texture, NULL); + glhd_context->pipe->sampler_view_destroy(glhd_context->pipe, + glhd_view->sampler_view); + FREE(glhd_view); +} + + +struct pipe_transfer * +galahad_transfer_create(struct galahad_context *glhd_context, + struct galahad_resource *glhd_resource, + struct pipe_transfer *transfer) +{ + struct galahad_transfer *glhd_transfer; + + if(!transfer) + goto error; + + assert(transfer->resource == glhd_resource->resource); + + glhd_transfer = CALLOC_STRUCT(galahad_transfer); + if(!glhd_transfer) + goto error; + + memcpy(&glhd_transfer->base, transfer, sizeof(struct pipe_transfer)); + + glhd_transfer->base.resource = NULL; + glhd_transfer->transfer = transfer; + + pipe_resource_reference(&glhd_transfer->base.resource, &glhd_resource->base); + assert(glhd_transfer->base.resource == &glhd_resource->base); + + return &glhd_transfer->base; + +error: + glhd_context->pipe->transfer_destroy(glhd_context->pipe, transfer); + return NULL; +} + +void +galahad_transfer_destroy(struct galahad_context *glhd_context, + struct galahad_transfer *glhd_transfer) +{ + pipe_resource_reference(&glhd_transfer->base.resource, NULL); + glhd_context->pipe->transfer_destroy(glhd_context->pipe, + glhd_transfer->transfer); + FREE(glhd_transfer); +} diff --git a/src/gallium/drivers/galahad/glhd_objects.h b/src/gallium/drivers/galahad/glhd_objects.h new file mode 100644 index 0000000000..935803915d --- /dev/null +++ b/src/gallium/drivers/galahad/glhd_objects.h @@ -0,0 +1,175 @@ +/************************************************************************** + * + * Copyright 2009 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef GLHD_OBJECTS_H +#define GLHD_OBJECTS_H + + +#include "pipe/p_compiler.h" +#include "pipe/p_state.h" + +#include "glhd_screen.h" + +struct galahad_context; + + +struct galahad_resource +{ + struct pipe_resource base; + + struct pipe_resource *resource; +}; + + +struct galahad_sampler_view +{ + struct pipe_sampler_view base; + + struct pipe_sampler_view *sampler_view; +}; + + +struct galahad_surface +{ + struct pipe_surface base; + + struct pipe_surface *surface; +}; + + +struct galahad_transfer +{ + struct pipe_transfer base; + + struct pipe_transfer *transfer; +}; + + +static INLINE struct galahad_resource * +galahad_resource(struct pipe_resource *_resource) +{ + if(!_resource) + return NULL; + (void)galahad_screen(_resource->screen); + return (struct galahad_resource *)_resource; +} + +static INLINE struct galahad_sampler_view * +galahad_sampler_view(struct pipe_sampler_view *_sampler_view) +{ + if (!_sampler_view) { + return NULL; + } + return (struct galahad_sampler_view *)_sampler_view; +} + +static INLINE struct galahad_surface * +galahad_surface(struct pipe_surface *_surface) +{ + if(!_surface) + return NULL; + (void)galahad_resource(_surface->texture); + return (struct galahad_surface *)_surface; +} + +static INLINE struct galahad_transfer * +galahad_transfer(struct pipe_transfer *_transfer) +{ + if(!_transfer) + return NULL; + (void)galahad_resource(_transfer->resource); + return (struct galahad_transfer *)_transfer; +} + +static INLINE struct pipe_resource * +galahad_resource_unwrap(struct pipe_resource *_resource) +{ + if(!_resource) + return NULL; + return galahad_resource(_resource)->resource; +} + +static INLINE struct pipe_sampler_view * +galahad_sampler_view_unwrap(struct pipe_sampler_view *_sampler_view) +{ + if (!_sampler_view) { + return NULL; + } + return galahad_sampler_view(_sampler_view)->sampler_view; +} + +static INLINE struct pipe_surface * +galahad_surface_unwrap(struct pipe_surface *_surface) +{ + if(!_surface) + return NULL; + return galahad_surface(_surface)->surface; +} + +static INLINE struct pipe_transfer * +galahad_transfer_unwrap(struct pipe_transfer *_transfer) +{ + if(!_transfer) + return NULL; + return galahad_transfer(_transfer)->transfer; +} + + +struct pipe_resource * +galahad_resource_create(struct galahad_screen *glhd_screen, + struct pipe_resource *resource); + +void +galahad_resource_destroy(struct galahad_resource *glhd_resource); + +struct pipe_surface * +galahad_surface_create(struct galahad_resource *glhd_resource, + struct pipe_surface *surface); + +void +galahad_surface_destroy(struct galahad_surface *glhd_surface); + +struct pipe_sampler_view * +galahad_sampler_view_create(struct galahad_context *glhd_context, + struct galahad_resource *glhd_resource, + struct pipe_sampler_view *view); + +void +galahad_sampler_view_destroy(struct galahad_context *glhd_context, + struct galahad_sampler_view *glhd_sampler_view); + +struct pipe_transfer * +galahad_transfer_create(struct galahad_context *glhd_context, + struct galahad_resource *glhd_resource, + struct pipe_transfer *transfer); + +void +galahad_transfer_destroy(struct galahad_context *glhd_context, + struct galahad_transfer *glhd_transfer); + + +#endif /* GLHD_OBJECTS_H */ diff --git a/src/gallium/drivers/galahad/glhd_public.h b/src/gallium/drivers/galahad/glhd_public.h new file mode 100644 index 0000000000..77a380196a --- /dev/null +++ b/src/gallium/drivers/galahad/glhd_public.h @@ -0,0 +1,37 @@ +/************************************************************************** + * + * Copyright 2009 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef GLHD_PUBLIC_H +#define GLHD_PUBLIC_H + +struct pipe_screen; +struct pipe_context; + +struct pipe_screen * +galahad_screen_create(struct pipe_screen *screen); + +#endif /* GLHD_PUBLIC_H */ diff --git a/src/gallium/drivers/galahad/glhd_screen.c b/src/gallium/drivers/galahad/glhd_screen.c new file mode 100644 index 0000000000..bcc37cb633 --- /dev/null +++ b/src/gallium/drivers/galahad/glhd_screen.c @@ -0,0 +1,330 @@ +/************************************************************************** + * + * Copyright 2009 VMware, Inc. + * 2010 Corbin Simpson <MostAwesomeDude@gmail.com> + * 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 "glhd_public.h" +#include "glhd_screen.h" +#include "glhd_context.h" +#include "glhd_objects.h" + + +static void +galahad_screen_destroy(struct pipe_screen *_screen) +{ + struct galahad_screen *glhd_screen = galahad_screen(_screen); + struct pipe_screen *screen = glhd_screen->screen; + + screen->destroy(screen); + + FREE(glhd_screen); +} + +static const char * +galahad_screen_get_name(struct pipe_screen *_screen) +{ + struct galahad_screen *glhd_screen = galahad_screen(_screen); + struct pipe_screen *screen = glhd_screen->screen; + + return screen->get_name(screen); +} + +static const char * +galahad_screen_get_vendor(struct pipe_screen *_screen) +{ + struct galahad_screen *glhd_screen = galahad_screen(_screen); + struct pipe_screen *screen = glhd_screen->screen; + + return screen->get_vendor(screen); +} + +static int +galahad_screen_get_param(struct pipe_screen *_screen, + enum pipe_cap param) +{ + struct galahad_screen *glhd_screen = galahad_screen(_screen); + struct pipe_screen *screen = glhd_screen->screen; + + return screen->get_param(screen, + param); +} + +static float +galahad_screen_get_paramf(struct pipe_screen *_screen, + enum pipe_cap param) +{ + struct galahad_screen *glhd_screen = galahad_screen(_screen); + struct pipe_screen *screen = glhd_screen->screen; + + return screen->get_paramf(screen, + param); +} + +static boolean +galahad_screen_is_format_supported(struct pipe_screen *_screen, + enum pipe_format format, + enum pipe_texture_target target, + unsigned sample_count, + unsigned tex_usage, + unsigned geom_flags) +{ + struct galahad_screen *glhd_screen = galahad_screen(_screen); + struct pipe_screen *screen = glhd_screen->screen; + + if (target >= PIPE_MAX_TEXTURE_TYPES) { + glhd_warn("Received bogus texture target %d", target); + } + + return screen->is_format_supported(screen, + format, + target, + sample_count, + tex_usage, + geom_flags); +} + +static struct pipe_context * +galahad_screen_context_create(struct pipe_screen *_screen, + void *priv) +{ + struct galahad_screen *glhd_screen = galahad_screen(_screen); + struct pipe_screen *screen = glhd_screen->screen; + struct pipe_context *result; + + result = screen->context_create(screen, priv); + if (result) + return galahad_context_create(_screen, result); + return NULL; +} + +static struct pipe_resource * +galahad_screen_resource_create(struct pipe_screen *_screen, + const struct pipe_resource *templat) +{ + struct galahad_screen *glhd_screen = galahad_screen(_screen); + struct pipe_screen *screen = glhd_screen->screen; + struct pipe_resource *result; + + result = screen->resource_create(screen, + templat); + + if (result) + return galahad_resource_create(glhd_screen, result); + return NULL; +} + +static struct pipe_resource * +galahad_screen_resource_from_handle(struct pipe_screen *_screen, + const struct pipe_resource *templ, + struct winsys_handle *handle) +{ + struct galahad_screen *glhd_screen = galahad_screen(_screen); + struct pipe_screen *screen = glhd_screen->screen; + struct pipe_resource *result; + + /* TODO trace call */ + + result = screen->resource_from_handle(screen, templ, handle); + + result = galahad_resource_create(galahad_screen(_screen), result); + + return result; +} + +static boolean +galahad_screen_resource_get_handle(struct pipe_screen *_screen, + struct pipe_resource *_resource, + struct winsys_handle *handle) +{ + struct galahad_screen *glhd_screen = galahad_screen(_screen); + struct galahad_resource *glhd_resource = galahad_resource(_resource); + struct pipe_screen *screen = glhd_screen->screen; + struct pipe_resource *resource = glhd_resource->resource; + + /* TODO trace call */ + + return screen->resource_get_handle(screen, resource, handle); +} + + + +static void +galahad_screen_resource_destroy(struct pipe_screen *screen, + struct pipe_resource *_resource) +{ + galahad_resource_destroy(galahad_resource(_resource)); +} + +static struct pipe_surface * +galahad_screen_get_tex_surface(struct pipe_screen *_screen, + struct pipe_resource *_resource, + unsigned face, + unsigned level, + unsigned zslice, + unsigned usage) +{ + struct galahad_screen *glhd_screen = galahad_screen(_screen); + struct galahad_resource *glhd_resource = galahad_resource(_resource); + struct pipe_screen *screen = glhd_screen->screen; + struct pipe_resource *resource = glhd_resource->resource; + struct pipe_surface *result; + + result = screen->get_tex_surface(screen, + resource, + face, + level, + zslice, + usage); + + if (result) + return galahad_surface_create(glhd_resource, result); + return NULL; +} + +static void +galahad_screen_tex_surface_destroy(struct pipe_surface *_surface) +{ + galahad_surface_destroy(galahad_surface(_surface)); +} + + + +static struct pipe_resource * +galahad_screen_user_buffer_create(struct pipe_screen *_screen, + void *ptr, + unsigned bytes, + unsigned usage) +{ + struct galahad_screen *glhd_screen = galahad_screen(_screen); + struct pipe_screen *screen = glhd_screen->screen; + struct pipe_resource *result; + + result = screen->user_buffer_create(screen, + ptr, + bytes, + usage); + + if (result) + return galahad_resource_create(glhd_screen, result); + return NULL; +} + + + +static void +galahad_screen_flush_frontbuffer(struct pipe_screen *_screen, + struct pipe_surface *_surface, + void *context_private) +{ + struct galahad_screen *glhd_screen = galahad_screen(_screen); + struct galahad_surface *glhd_surface = galahad_surface(_surface); + struct pipe_screen *screen = glhd_screen->screen; + struct pipe_surface *surface = glhd_surface->surface; + + screen->flush_frontbuffer(screen, + surface, + context_private); +} + +static void +galahad_screen_fence_reference(struct pipe_screen *_screen, + struct pipe_fence_handle **ptr, + struct pipe_fence_handle *fence) +{ + struct galahad_screen *glhd_screen = galahad_screen(_screen); + struct pipe_screen *screen = glhd_screen->screen; + + screen->fence_reference(screen, + ptr, + fence); +} + +static int +galahad_screen_fence_signalled(struct pipe_screen *_screen, + struct pipe_fence_handle *fence, + unsigned flags) +{ + struct galahad_screen *glhd_screen = galahad_screen(_screen); + struct pipe_screen *screen = glhd_screen->screen; + + return screen->fence_signalled(screen, + fence, + flags); +} + +static int +galahad_screen_fence_finish(struct pipe_screen *_screen, + struct pipe_fence_handle *fence, + unsigned flags) +{ + struct galahad_screen *glhd_screen = galahad_screen(_screen); + struct pipe_screen *screen = glhd_screen->screen; + + return screen->fence_finish(screen, + fence, + flags); +} + +struct pipe_screen * +galahad_screen_create(struct pipe_screen *screen) +{ + struct galahad_screen *glhd_screen; + + glhd_screen = CALLOC_STRUCT(galahad_screen); + if (!glhd_screen) { + return NULL; + } + + glhd_screen->base.winsys = NULL; + + glhd_screen->base.destroy = galahad_screen_destroy; + glhd_screen->base.get_name = galahad_screen_get_name; + glhd_screen->base.get_vendor = galahad_screen_get_vendor; + glhd_screen->base.get_param = galahad_screen_get_param; + glhd_screen->base.get_paramf = galahad_screen_get_paramf; + glhd_screen->base.is_format_supported = galahad_screen_is_format_supported; + glhd_screen->base.context_create = galahad_screen_context_create; + glhd_screen->base.resource_create = galahad_screen_resource_create; + glhd_screen->base.resource_from_handle = galahad_screen_resource_from_handle; + glhd_screen->base.resource_get_handle = galahad_screen_resource_get_handle; + glhd_screen->base.resource_destroy = galahad_screen_resource_destroy; + glhd_screen->base.get_tex_surface = galahad_screen_get_tex_surface; + glhd_screen->base.tex_surface_destroy = galahad_screen_tex_surface_destroy; + glhd_screen->base.user_buffer_create = galahad_screen_user_buffer_create; + glhd_screen->base.flush_frontbuffer = galahad_screen_flush_frontbuffer; + glhd_screen->base.fence_reference = galahad_screen_fence_reference; + glhd_screen->base.fence_signalled = galahad_screen_fence_signalled; + glhd_screen->base.fence_finish = galahad_screen_fence_finish; + + glhd_screen->screen = screen; + + return &glhd_screen->base; +} diff --git a/src/gallium/drivers/galahad/glhd_screen.h b/src/gallium/drivers/galahad/glhd_screen.h new file mode 100644 index 0000000000..7862f4af2b --- /dev/null +++ b/src/gallium/drivers/galahad/glhd_screen.h @@ -0,0 +1,48 @@ +/************************************************************************** + * + * Copyright 2009 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef GLHD_SCREEN_H +#define GLHD_SCREEN_H + +#include "pipe/p_screen.h" +#include "pipe/p_defines.h" + + +struct galahad_screen { + struct pipe_screen base; + + struct pipe_screen *screen; +}; + + +static INLINE struct galahad_screen * +galahad_screen(struct pipe_screen *screen) +{ + return (struct galahad_screen *)screen; +} + +#endif /* GLHD_SCREEN_H */ diff --git a/src/gallium/drivers/i915/SConscript b/src/gallium/drivers/i915/SConscript index 7b69681096..d6e7a8dbd3 100644 --- a/src/gallium/drivers/i915/SConscript +++ b/src/gallium/drivers/i915/SConscript @@ -2,6 +2,10 @@ Import('*') env = env.Clone() +if msvc: + print 'warning: not building i915g' + Return() + i915 = env.ConvenienceLibrary( target = 'i915', source = [ diff --git a/src/gallium/drivers/i915/i915_blit.c b/src/gallium/drivers/i915/i915_blit.c index c5b5979bf9..0a1b3e0d66 100644 --- a/src/gallium/drivers/i915/i915_blit.c +++ b/src/gallium/drivers/i915/i915_blit.c @@ -31,7 +31,6 @@ #include "i915_batch.h" #include "i915_debug.h" -#define FILE_DEBUG_FLAG DEBUG_BLIT void i915_fill_blit(struct i915_context *i915, @@ -47,10 +46,8 @@ i915_fill_blit(struct i915_context *i915, unsigned BR13, CMD; - I915_DBG(i915, - "%s dst:buf(%p)/%d+%d %d,%d sz:%dx%d\n", - __FUNCTION__, - dst_buffer, dst_pitch, dst_offset, x, y, w, h); + I915_DBG(DBG_BLIT, "%s dst:buf(%p)/%d+%d %d,%d sz:%dx%d\n", + __FUNCTION__, dst_buffer, dst_pitch, dst_offset, x, y, w, h); switch (cpp) { case 1: @@ -100,11 +97,11 @@ i915_copy_blit(struct i915_context *i915, int dst_x2 = dst_x + w; - I915_DBG(i915, - "%s src:buf(%p)/%d+%d %d,%d dst:buf(%p)/%d+%d %d,%d sz:%dx%d\n", - __FUNCTION__, - src_buffer, src_pitch, src_offset, src_x, src_y, - dst_buffer, dst_pitch, dst_offset, dst_x, dst_y, w, h); + I915_DBG(DBG_BLIT, + "%s src:buf(%p)/%d+%d %d,%d dst:buf(%p)/%d+%d %d,%d sz:%dx%d\n", + __FUNCTION__, + src_buffer, src_pitch, src_offset, src_x, src_y, + dst_buffer, dst_pitch, dst_offset, dst_x, dst_y, w, h); switch (cpp) { case 1: diff --git a/src/gallium/drivers/i915/i915_context.h b/src/gallium/drivers/i915/i915_context.h index acc0ffe037..ac02ab2332 100644 --- a/src/gallium/drivers/i915/i915_context.h +++ b/src/gallium/drivers/i915/i915_context.h @@ -237,8 +237,6 @@ struct i915_context struct i915_state current; unsigned hardware_dirty; - - unsigned debug; }; /* A flag for each state_tracker state object: diff --git a/src/gallium/drivers/i915/i915_debug.c b/src/gallium/drivers/i915/i915_debug.c index 663fac3055..57d3390dea 100644 --- a/src/gallium/drivers/i915/i915_debug.c +++ b/src/gallium/drivers/i915/i915_debug.c @@ -27,11 +27,37 @@ #include "i915_reg.h" #include "i915_context.h" +#include "i915_screen.h" #include "i915_debug.h" +#include "i915_debug_private.h" #include "i915_batch.h" #include "util/u_debug.h" + +static const struct debug_named_value debug_options[] = { + {"blit", DBG_BLIT, "Print when using the 2d blitter"}, + {"emit", DBG_EMIT, "State emit information"}, + {"atoms", DBG_ATOMS, "Print dirty state atoms"}, + {"flush", DBG_FLUSH, "Flushing information"}, + {"texture", DBG_TEXTURE, "Texture information"}, + {"constants", DBG_CONSTANTS, "Constant buffers"}, + DEBUG_NAMED_VALUE_END +}; + +unsigned i915_debug = 0; + +void i915_debug_init(struct i915_screen *screen) +{ + i915_debug = debug_get_flags_option("I915_DEBUG", debug_options, 0); +} + + + +/*********************************************************************** + * Batchbuffer dumping + */ + static void PRINTF( struct debug_stream *stream, @@ -896,3 +922,66 @@ i915_dump_batchbuffer( struct i915_winsys_batchbuffer *batch ) } + +/*********************************************************************** + * Dirty state atom dumping + */ + +void +i915_dump_dirty(struct i915_context *i915, const char *func) +{ + struct { + unsigned dirty; + const char *name; + } l[] = { + {I915_NEW_VIEWPORT, "viewport"}, + {I915_NEW_RASTERIZER, "rasterizer"}, + {I915_NEW_FS, "fs"}, + {I915_NEW_BLEND, "blend"}, + {I915_NEW_CLIP, "clip"}, + {I915_NEW_SCISSOR, "scissor"}, + {I915_NEW_STIPPLE, "stipple"}, + {I915_NEW_FRAMEBUFFER, "framebuffer"}, + {I915_NEW_ALPHA_TEST, "alpha_test"}, + {I915_NEW_DEPTH_STENCIL, "depth_stencil"}, + {I915_NEW_SAMPLER, "sampler"}, + {I915_NEW_SAMPLER_VIEW, "sampler_view"}, + {I915_NEW_CONSTANTS, "constants"}, + {I915_NEW_VBO, "vbo"}, + {I915_NEW_VS, "vs"}, + {0, NULL}, + }; + int i; + + debug_printf("%s: ", func); + for (i = 0; l[i].name; i++) + if (i915->dirty & l[i].dirty) + debug_printf("%s ", l[i].name); + debug_printf("\n"); +} + +void +i915_dump_hardware_dirty(struct i915_context *i915, const char *func) +{ + struct { + unsigned dirty; + const char *name; + } l[] = { + {I915_HW_STATIC, "static"}, + {I915_HW_DYNAMIC, "dynamic"}, + {I915_HW_SAMPLER, "sampler"}, + {I915_HW_MAP, "map"}, + {I915_HW_PROGRAM, "program"}, + {I915_HW_CONSTANTS, "constants"}, + {I915_HW_IMMEDIATE, "immediate"}, + {I915_HW_INVARIENT, "invarient"}, + {0, NULL}, + }; + int i; + + debug_printf("%s: ", func); + for (i = 0; l[i].name; i++) + if (i915->hardware_dirty & l[i].dirty) + debug_printf("%s ", l[i].name); + debug_printf("\n"); +} diff --git a/src/gallium/drivers/i915/i915_debug.h b/src/gallium/drivers/i915/i915_debug.h index 67b8d9c2f6..8aa09f9c1f 100644 --- a/src/gallium/drivers/i915/i915_debug.h +++ b/src/gallium/drivers/i915/i915_debug.h @@ -26,89 +26,51 @@ **************************************************************************/ /* Authors: Keith Whitwell <keith@tungstengraphics.com> + * Jakob Bornecrantz <wallbraker@gmail.com> */ #ifndef I915_DEBUG_H #define I915_DEBUG_H -#include <stdarg.h> +#include "util/u_debug.h" +struct i915_screen; struct i915_context; +struct i915_winsys_batchbuffer; -struct debug_stream -{ - unsigned offset; /* current gtt offset */ - char *ptr; /* pointer to gtt offset zero */ - char *end; /* pointer to gtt offset zero */ - unsigned print_addresses; -}; - - -/* Internal functions - */ -void i915_disassemble_program(struct debug_stream *stream, - const unsigned *program, unsigned sz); - -void i915_print_ureg(const char *msg, unsigned ureg); - - -#define DEBUG_BATCH 0x1 -#define DEBUG_BLIT 0x2 -#define DEBUG_BUFFER 0x4 -#define DEBUG_CONSTANTS 0x8 -#define DEBUG_CONTEXT 0x10 -#define DEBUG_DRAW 0x20 -#define DEBUG_DYNAMIC 0x40 -#define DEBUG_FLUSH 0x80 -#define DEBUG_MAP 0x100 -#define DEBUG_PROGRAM 0x200 -#define DEBUG_REGIONS 0x400 -#define DEBUG_SAMPLER 0x800 -#define DEBUG_STATIC 0x1000 -#define DEBUG_SURFACE 0x2000 -#define DEBUG_WINSYS 0x4000 - -#include "pipe/p_compiler.h" +#define DBG_BLIT 0x1 +#define DBG_EMIT 0x2 +#define DBG_ATOMS 0x4 +#define DBG_FLUSH 0x8 +#define DBG_TEXTURE 0x10 +#define DBG_CONSTANTS 0x20 -#if defined(DEBUG) && defined(FILE_DEBUG_FLAG) +extern unsigned i915_debug; -#include "util/u_simple_screen.h" +static INLINE boolean +I915_DBG_ON(unsigned flags) +{ + return i915_debug & flags; +} static INLINE void -I915_DBG( - struct i915_context *i915, - const char *fmt, - ... ) +I915_DBG(unsigned flags, const char *fmt, ...) { - if ((i915)->debug & FILE_DEBUG_FLAG) { + if (I915_DBG_ON(flags)) { va_list args; - va_start( args, fmt ); - debug_vprintf( fmt, args ); - va_end( args ); + va_start(args, fmt); + debug_vprintf(fmt, args); + va_end(args); } } -#else - -static INLINE void -I915_DBG( - struct i915_context *i915, - const char *fmt, - ... ) -{ - (void) i915; - (void) fmt; -} - -#endif - - -struct i915_winsys_batchbuffer; +void i915_debug_init(struct i915_screen *i915); -void i915_dump_batchbuffer( struct i915_winsys_batchbuffer *i915 ); +void i915_dump_batchbuffer(struct i915_winsys_batchbuffer *i915); -void i915_debug_init( struct i915_context *i915 ); +void i915_dump_dirty(struct i915_context *i915, const char *func); +void i915_dump_hardware_dirty(struct i915_context *i915, const char *func); #endif diff --git a/src/gallium/drivers/i915/i915_debug_fp.c b/src/gallium/drivers/i915/i915_debug_fp.c index f41c51f299..50f49c540f 100644 --- a/src/gallium/drivers/i915/i915_debug_fp.c +++ b/src/gallium/drivers/i915/i915_debug_fp.c @@ -28,6 +28,7 @@ #include "i915_reg.h" #include "i915_debug.h" +#include "i915_debug_private.h" #include "util/u_debug.h" diff --git a/src/gallium/drivers/i915/i915_debug_private.h b/src/gallium/drivers/i915/i915_debug_private.h new file mode 100644 index 0000000000..b3668d0848 --- /dev/null +++ b/src/gallium/drivers/i915/i915_debug_private.h @@ -0,0 +1,45 @@ +/************************************************************************** + * + * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +/* Authors: Keith Whitwell <keith@tungstengraphics.com> + */ + +#ifndef I915_DEBUG_PRIVATE_H +#define I915_DEBUG_PRIVATE_H + +struct debug_stream +{ + unsigned offset; /* current gtt offset */ + char *ptr; /* pointer to gtt offset zero */ + char *end; /* pointer to gtt offset zero */ + unsigned print_addresses; +}; + +void i915_disassemble_program(struct debug_stream *stream, + const unsigned *program, unsigned sz); + +#endif diff --git a/src/gallium/drivers/i915/i915_flush.c b/src/gallium/drivers/i915/i915_flush.c index 1582168eba..967146479d 100644 --- a/src/gallium/drivers/i915/i915_flush.c +++ b/src/gallium/drivers/i915/i915_flush.c @@ -35,6 +35,7 @@ #include "i915_context.h" #include "i915_reg.h" #include "i915_batch.h" +#include "i915_debug.h" static void i915_flush( struct pipe_context *pipe, @@ -76,9 +77,9 @@ static void i915_flush( struct pipe_context *pipe, */ FLUSH_BATCH(fence); i915->vbo_flushed = 1; -} - + I915_DBG(DBG_FLUSH, "%s: #####\n", __FUNCTION__); +} void i915_init_flush_functions( struct i915_context *i915 ) { diff --git a/src/gallium/drivers/i915/i915_prim_vbuf.c b/src/gallium/drivers/i915/i915_prim_vbuf.c index f8665acbe1..bd046bd905 100644 --- a/src/gallium/drivers/i915/i915_prim_vbuf.c +++ b/src/gallium/drivers/i915/i915_prim_vbuf.c @@ -52,8 +52,7 @@ #include "i915_state.h" -#undef VBUF_USE_FIFO -#undef VBUF_MAP_BUFFER +#define VBUF_MAP_BUFFER /** * Primitive renderer for i915. @@ -79,23 +78,18 @@ struct i915_vbuf_render { struct i915_winsys_buffer *vbo; size_t vbo_size; /**< current size of allocated buffer */ size_t vbo_alloc_size; /**< minimum buffer size to allocate */ - size_t vbo_offset; + size_t vbo_hw_offset; /**< offset that we program the hardware with */ + size_t vbo_sw_offset; /**< offset that we work with */ + size_t vbo_index; /**< index offset to be added to all indices */ void *vbo_ptr; size_t vbo_max_used; + size_t vbo_max_index; /**< index offset to be added to all indices */ #ifndef VBUF_MAP_BUFFER size_t map_used_start; size_t map_used_end; size_t map_size; #endif - -#ifdef VBUF_USE_FIFO - /* Stuff for the pool */ - struct util_fifo *pool_fifo; - unsigned pool_used; - unsigned pool_buffer_size; - boolean pool_not_used; -#endif }; @@ -109,6 +103,35 @@ i915_vbuf_render(struct vbuf_render *render) return (struct i915_vbuf_render *)render; } +/** + * If vbo state differs between renderer and context + * push state to the context. This function pushes + * hw_offset to i915->vbo_offset and vbo to i915->vbo. + * + * Side effects: + * May updates context vbo_offset and vbo fields. + */ +static void +i915_vbuf_update_vbo_state(struct vbuf_render *render) +{ + struct i915_vbuf_render *i915_render = i915_vbuf_render(render); + struct i915_context *i915 = i915_render->i915; + + if (i915->vbo != i915_render->vbo || + i915->vbo_offset != i915_render->vbo_hw_offset) { + i915->vbo = i915_render->vbo; + i915->vbo_offset = i915_render->vbo_hw_offset; + i915->dirty |= I915_NEW_VBO; + } +} + +/** + * Callback exported to the draw module. + * Returns the current vertex_info. + * + * Side effects: + * If state is dirty update derived state. + */ static const struct vertex_info * i915_vbuf_render_get_vertex_info(struct vbuf_render *render) { @@ -123,12 +146,18 @@ i915_vbuf_render_get_vertex_info(struct vbuf_render *render) return &i915->current.vertex_info; } +/** + * Reserve space in the vbo for vertices. + * + * Side effects: + * None. + */ static boolean i915_vbuf_render_reserve(struct i915_vbuf_render *i915_render, size_t size) { struct i915_context *i915 = i915_render->i915; - if (i915_render->vbo_size < size + i915_render->vbo_offset) + if (i915_render->vbo_size < size + i915_render->vbo_sw_offset) return FALSE; if (i915->vbo_flushed) @@ -137,28 +166,28 @@ i915_vbuf_render_reserve(struct i915_vbuf_render *i915_render, size_t size) return TRUE; } +/** + * Allocate a new vbo buffer should there not be enough space for + * the requested number of vertices by the draw module. + * + * Side effects: + * Updates hw_offset, sw_offset, index and allocates a new buffer. + */ static void i915_vbuf_render_new_buf(struct i915_vbuf_render *i915_render, size_t size) { struct i915_context *i915 = i915_render->i915; struct i915_winsys *iws = i915->iws; - if (i915_render->vbo) { -#ifdef VBUF_USE_FIFO - if (i915_render->pool_not_used) - iws->buffer_destroy(iws, i915_render->vbo); - else - u_fifo_add(i915_render->pool_fifo, i915_render->vbo); - i915_render->vbo = NULL; -#else + if (i915_render->vbo) iws->buffer_destroy(iws, i915_render->vbo); -#endif - } i915->vbo_flushed = 0; i915_render->vbo_size = MAX2(size, i915_render->vbo_alloc_size); - i915_render->vbo_offset = 0; + i915_render->vbo_hw_offset = 0; + i915_render->vbo_sw_offset = 0; + i915_render->vbo_index = 0; #ifndef VBUF_MAP_BUFFER if (i915_render->vbo_size > i915_render->map_size) { @@ -168,52 +197,51 @@ i915_vbuf_render_new_buf(struct i915_vbuf_render *i915_render, size_t size) } #endif -#ifdef VBUF_USE_FIFO - if (i915_render->vbo_size != i915_render->pool_buffer_size) { - i915_render->pool_not_used = TRUE; - i915_render->vbo = iws->buffer_create(iws, i915_render->vbo_size, 64, - I915_NEW_VERTEX); - } else { - i915_render->pool_not_used = FALSE; - - if (i915_render->pool_used >= 2) { - FLUSH_BATCH(NULL); - i915->vbo_flushed = 0; - i915_render->pool_used = 0; - } - u_fifo_pop(i915_render->pool_fifo, (void**)&i915_render->vbo); - } -#else i915_render->vbo = iws->buffer_create(iws, i915_render->vbo_size, 64, I915_NEW_VERTEX); -#endif } +/** + * Callback exported to the draw module. + * + * Side effects: + * Updates hw_offset, sw_offset, index and may allocate + * a new buffer. Also updates may update the vbo state + * on the i915 context. + */ static boolean i915_vbuf_render_allocate_vertices(struct vbuf_render *render, ushort vertex_size, ushort nr_vertices) { struct i915_vbuf_render *i915_render = i915_vbuf_render(render); - struct i915_context *i915 = i915_render->i915; size_t size = (size_t)vertex_size * (size_t)nr_vertices; + size_t offset; - /* FIXME: handle failure */ - assert(!i915->vbo); + /* + * Align sw_offset with first multiple of vertex size from hw_offset. + * Set index to be the multiples from from hw_offset to sw_offset. + * i915_vbuf_render_new_buf will reset index, sw_offset, hw_offset + * when it allocates a new buffer this is correct. + */ + { + offset = i915_render->vbo_sw_offset - i915_render->vbo_hw_offset; + offset = util_align_npot(offset, vertex_size); + i915_render->vbo_sw_offset = i915_render->vbo_hw_offset + offset; + i915_render->vbo_index = offset / vertex_size; + } - if (!i915_vbuf_render_reserve(i915_render, size)) { -#ifdef VBUF_USE_FIFO - /* incase we flushed reset the number of pool buffers used */ - if (i915->vbo_flushed) - i915_render->pool_used = 0; -#endif + if (!i915_vbuf_render_reserve(i915_render, size)) i915_vbuf_render_new_buf(i915_render, size); - } + + /* + * If a new buffer has been alocated sw_offset, + * hw_offset & index will be reset by new_buf + */ i915_render->vertex_size = vertex_size; - i915->vbo = i915_render->vbo; - i915->vbo_offset = i915_render->vbo_offset; - i915->dirty |= I915_NEW_VBO; + + i915_vbuf_update_vbo_state(render); if (!i915_render->vbo) return FALSE; @@ -232,7 +260,7 @@ i915_vbuf_render_map_vertices(struct vbuf_render *render) #ifdef VBUF_MAP_BUFFER i915_render->vbo_ptr = iws->buffer_map(iws, i915_render->vbo, TRUE); - return (unsigned char *)i915_render->vbo_ptr + i915_render->vbo_offset; + return (unsigned char *)i915_render->vbo_ptr + i915_render->vbo_sw_offset; #else (void)iws; return (unsigned char *)i915_render->vbo_ptr; @@ -248,6 +276,7 @@ i915_vbuf_render_unmap_vertices(struct vbuf_render *render, struct i915_context *i915 = i915_render->i915; struct i915_winsys *iws = i915->iws; + i915_render->vbo_max_index = max_index; i915_render->vbo_max_used = MAX2(i915_render->vbo_max_used, i915_render->vertex_size * (max_index + 1)); #ifdef VBUF_MAP_BUFFER iws->buffer_unmap(iws, i915_render->vbo); @@ -255,13 +284,36 @@ i915_vbuf_render_unmap_vertices(struct vbuf_render *render, i915_render->map_used_start = i915_render->vertex_size * min_index; i915_render->map_used_end = i915_render->vertex_size * (max_index + 1); iws->buffer_write(iws, i915_render->vbo, - i915_render->map_used_start + i915_render->vbo_offset, + i915_render->map_used_start + i915_render->vbo_sw_offset, i915_render->map_used_end - i915_render->map_used_start, (unsigned char *)i915_render->vbo_ptr + i915_render->map_used_start); #endif } +/** + * Ensure that the given max_index given is not larger ushort max. + * If it is larger then ushort max it advanced the hw_offset to the + * same position in the vbo as sw_offset and set index to zero. + * + * Side effects: + * On failure update hw_offset and index. + */ +static void +i915_vbuf_ensure_index_bounds(struct vbuf_render *render, + unsigned max_index) +{ + struct i915_vbuf_render *i915_render = i915_vbuf_render(render); + + if (max_index + i915_render->vbo_index < ((1 << 17) - 1)) + return; + + i915_render->vbo_hw_offset = i915_render->vbo_sw_offset; + i915_render->vbo_index = 0; + + i915_vbuf_update_vbo_state(render); +} + static boolean i915_vbuf_render_set_primitive(struct vbuf_render *render, unsigned prim) @@ -327,7 +379,9 @@ draw_arrays_generate_indices(struct vbuf_render *render, struct i915_vbuf_render *i915_render = i915_vbuf_render(render); struct i915_context *i915 = i915_render->i915; unsigned i; - unsigned end = start + nr; + unsigned end = start + nr + i915_render->vbo_index; + start += i915_render->vbo_index; + switch(type) { case 0: for (i = start; i+1 < end; i += 2) @@ -391,16 +445,18 @@ draw_arrays_fallback(struct vbuf_render *render, struct i915_context *i915 = i915_render->i915; unsigned nr_indices; + nr_indices = draw_arrays_calc_nr_indices(nr, i915_render->fallback); + if (!nr_indices) + return; + + i915_vbuf_ensure_index_bounds(render, start + nr_indices); + if (i915->dirty) i915_update_derived(i915); if (i915->hardware_dirty) i915_emit_hardware_state(i915); - nr_indices = draw_arrays_calc_nr_indices(nr, i915_render->fallback); - if (!nr_indices) - return; - if (!BEGIN_BATCH(1 + (nr_indices + 1)/2, 1)) { FLUSH_BATCH(NULL); @@ -415,6 +471,7 @@ draw_arrays_fallback(struct vbuf_render *render, goto out; } } + OUT_BATCH(_3DPRIMITIVE | PRIM_INDIRECT | i915_render->hwprim | @@ -440,6 +497,9 @@ i915_vbuf_render_draw_arrays(struct vbuf_render *render, return; } + i915_vbuf_ensure_index_bounds(render, start + nr); + start += i915_render->vbo_index; + if (i915->dirty) i915_update_derived(i915); @@ -485,35 +545,36 @@ draw_generate_indices(struct vbuf_render *render, struct i915_vbuf_render *i915_render = i915_vbuf_render(render); struct i915_context *i915 = i915_render->i915; unsigned i; + unsigned o = i915_render->vbo_index; switch(type) { case 0: for (i = 0; i + 1 < nr_indices; i += 2) { - OUT_BATCH(indices[i] | indices[i+1] << 16); + OUT_BATCH((o+indices[i]) | (o+indices[i+1]) << 16); } if (i < nr_indices) { - OUT_BATCH(indices[i]); + OUT_BATCH((o+indices[i])); } break; case PIPE_PRIM_LINE_LOOP: if (nr_indices >= 2) { for (i = 1; i < nr_indices; i++) - OUT_BATCH(indices[i-1] | indices[i] << 16); - OUT_BATCH(indices[i-1] | indices[0] << 16); + OUT_BATCH((o+indices[i-1]) | (o+indices[i]) << 16); + OUT_BATCH((o+indices[i-1]) | (o+indices[0]) << 16); } break; case PIPE_PRIM_QUADS: for (i = 0; i + 3 < nr_indices; i += 4) { - OUT_BATCH(indices[i+0] | indices[i+1] << 16); - OUT_BATCH(indices[i+3] | indices[i+1] << 16); - OUT_BATCH(indices[i+2] | indices[i+3] << 16); + OUT_BATCH((o+indices[i+0]) | (o+indices[i+1]) << 16); + OUT_BATCH((o+indices[i+3]) | (o+indices[i+1]) << 16); + OUT_BATCH((o+indices[i+2]) | (o+indices[i+3]) << 16); } break; case PIPE_PRIM_QUAD_STRIP: for (i = 0; i + 3 < nr_indices; i += 2) { - OUT_BATCH(indices[i+0] | indices[i+1] << 16); - OUT_BATCH(indices[i+3] | indices[i+2] << 16); - OUT_BATCH(indices[i+0] | indices[i+3] << 16); + OUT_BATCH((o+indices[i+0]) | (o+indices[i+1]) << 16); + OUT_BATCH((o+indices[i+3]) | (o+indices[i+2]) << 16); + OUT_BATCH((o+indices[i+0]) | (o+indices[i+3]) << 16); } break; default: @@ -558,6 +619,8 @@ i915_vbuf_render_draw_elements(struct vbuf_render *render, if (!nr_indices) return; + i915_vbuf_ensure_index_bounds(render, i915_render->vbo_max_index); + if (i915->dirty) i915_update_derived(i915); @@ -597,14 +660,15 @@ static void i915_vbuf_render_release_vertices(struct vbuf_render *render) { struct i915_vbuf_render *i915_render = i915_vbuf_render(render); - struct i915_context *i915 = i915_render->i915; - - assert(i915->vbo); - i915_render->vbo_offset += i915_render->vbo_max_used; + i915_render->vbo_sw_offset += i915_render->vbo_max_used; i915_render->vbo_max_used = 0; - i915->vbo = NULL; - i915->dirty |= I915_NEW_VBO; + + /* + * Micro optimization, by calling update here we the offset change + * will be picked up on the next pipe_context::draw_*. + */ + i915_vbuf_update_vbo_state(render); } static void @@ -652,7 +716,8 @@ i915_vbuf_render_create(struct i915_context *i915) i915_render->vbo = NULL; i915_render->vbo_ptr = NULL; i915_render->vbo_size = 0; - i915_render->vbo_offset = 0; + i915_render->vbo_hw_offset = 0; + i915_render->vbo_sw_offset = 0; i915_render->vbo_alloc_size = i915_render->base.max_vertex_buffer_bytes * 4; #ifdef VBUF_USE_POOL diff --git a/src/gallium/drivers/i915/i915_screen.c b/src/gallium/drivers/i915/i915_screen.c index bb0b85d74c..77345d5f71 100644 --- a/src/gallium/drivers/i915/i915_screen.c +++ b/src/gallium/drivers/i915/i915_screen.c @@ -31,6 +31,7 @@ #include "util/u_string.h" #include "i915_reg.h" +#include "i915_debug.h" #include "i915_context.h" #include "i915_screen.h" #include "i915_surface.h" @@ -331,5 +332,7 @@ i915_screen_create(struct i915_winsys *iws) i915_init_screen_resource_functions(is); i915_init_screen_surface_functions(is); + i915_debug_init(is); + return &is->base; } diff --git a/src/gallium/drivers/i915/i915_state.h b/src/gallium/drivers/i915/i915_state.h index 86c6b0027d..7795046f06 100644 --- a/src/gallium/drivers/i915/i915_state.h +++ b/src/gallium/drivers/i915/i915_state.h @@ -35,16 +35,21 @@ struct i915_context; struct i915_tracked_state { + const char *name; + void (*update)(struct i915_context *); unsigned dirty; - void (*update)( struct i915_context * ); }; -void i915_update_immediate( struct i915_context *i915 ); -void i915_update_dynamic( struct i915_context *i915 ); -void i915_update_derived( struct i915_context *i915 ); -void i915_update_samplers( struct i915_context *i915 ); -void i915_update_textures(struct i915_context *i915); +extern struct i915_tracked_state i915_update_vertex_layout; -void i915_emit_hardware_state( struct i915_context *i915 ); +extern struct i915_tracked_state i915_hw_samplers; +extern struct i915_tracked_state i915_hw_sampler_views; +extern struct i915_tracked_state i915_hw_immediate; +extern struct i915_tracked_state i915_hw_dynamic; +extern struct i915_tracked_state i915_hw_fs; +extern struct i915_tracked_state i915_hw_framebuffer; + +void i915_update_derived(struct i915_context *i915); +void i915_emit_hardware_state(struct i915_context *i915); #endif diff --git a/src/gallium/drivers/i915/i915_state_derived.c b/src/gallium/drivers/i915/i915_state_derived.c index 4da46772b5..c059540357 100644 --- a/src/gallium/drivers/i915/i915_state_derived.c +++ b/src/gallium/drivers/i915/i915_state_derived.c @@ -32,15 +32,16 @@ #include "draw/draw_vertex.h" #include "i915_context.h" #include "i915_state.h" +#include "i915_debug.h" #include "i915_reg.h" -/** +/*********************************************************************** * Determine the hardware vertex layout. * Depends on vertex/fragment shader state. */ -static void calculate_vertex_layout( struct i915_context *i915 ) +static void calculate_vertex_layout(struct i915_context *i915) { const struct i915_fragment_shader *fs = i915->fs; const enum interp_mode colorInterp = i915->rasterizer->color_interp; @@ -146,37 +147,71 @@ static void calculate_vertex_layout( struct i915_context *i915 ) } } +struct i915_tracked_state i915_update_vertex_layout = { + "vertex_layout", + calculate_vertex_layout, + I915_NEW_RASTERIZER | I915_NEW_FS | I915_NEW_VS +}; -/* Hopefully this will remain quite simple, otherwise need to pull in - * something like the state tracker mechanism. +/*********************************************************************** + * Update fragment state */ -void i915_update_derived( struct i915_context *i915 ) +static void update_fs(struct i915_context *i915) { - if (i915->dirty & (I915_NEW_RASTERIZER | I915_NEW_FS | I915_NEW_VS)) - calculate_vertex_layout( i915 ); - - if (i915->dirty & (I915_NEW_SAMPLER | I915_NEW_SAMPLER_VIEW)) - i915_update_samplers(i915); - - if (i915->dirty & I915_NEW_SAMPLER_VIEW) - i915_update_textures(i915); + i915->hardware_dirty |= I915_HW_PROGRAM; /* XXX right? */ +} - if (i915->dirty) - i915_update_immediate( i915 ); +struct i915_tracked_state i915_hw_fs = { + "fs", + update_fs, + I915_NEW_FS +}; - if (i915->dirty) - i915_update_dynamic( i915 ); - if (i915->dirty & I915_NEW_FS) { - i915->hardware_dirty |= I915_HW_PROGRAM; /* XXX right? */ - } +/*********************************************************************** + * Update framebuffer state + */ +static void update_framebuffer(struct i915_context *i915) +{ /* HW emit currently references framebuffer state directly: */ - if (i915->dirty & I915_NEW_FRAMEBUFFER) - i915->hardware_dirty |= I915_HW_STATIC; + i915->hardware_dirty |= I915_HW_STATIC; +} + +struct i915_tracked_state i915_hw_framebuffer = { + "framebuffer", + update_framebuffer, + I915_NEW_FRAMEBUFFER +}; + + + +/*********************************************************************** + */ +static struct i915_tracked_state *atoms[] = { + &i915_update_vertex_layout, + &i915_hw_samplers, + &i915_hw_sampler_views, + &i915_hw_immediate, + &i915_hw_dynamic, + &i915_hw_fs, + &i915_hw_framebuffer, + NULL, +}; + +void i915_update_derived(struct i915_context *i915) +{ + int i; + + if (I915_DBG_ON(DBG_ATOMS)) + i915_dump_dirty(i915, __FUNCTION__); + + for (i = 0; atoms[i]; i++) + if (atoms[i]->dirty & i915->dirty) + atoms[i]->update(i915); i915->dirty = 0; } diff --git a/src/gallium/drivers/i915/i915_state_dynamic.c b/src/gallium/drivers/i915/i915_state_dynamic.c index 9c6723b391..d964483ac7 100644 --- a/src/gallium/drivers/i915/i915_state_dynamic.c +++ b/src/gallium/drivers/i915/i915_state_dynamic.c @@ -1,8 +1,8 @@ /************************************************************************** - * + * * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. * All Rights Reserved. - * + * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including @@ -10,11 +10,11 @@ * 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. @@ -22,7 +22,7 @@ * 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 "i915_batch.h" @@ -34,10 +34,9 @@ #include "util/u_memory.h" #include "util/u_pack_color.h" -#define FILE_DEBUG_FLAG DEBUG_STATE /* State that we have chosen to store in the DYNAMIC segment of the - * i915 indirect state mechanism. + * i915 indirect state mechanism. * * Can't cache these in the way we do the static state, as there is no * start/size in the command packet, instead an 'end' value that gets @@ -47,10 +46,10 @@ * (active) state every time a 4kb boundary is crossed. */ -static INLINE void set_dynamic_indirect( struct i915_context *i915, - unsigned offset, - const unsigned *src, - unsigned dwords ) +static INLINE void set_dynamic_indirect(struct i915_context *i915, + unsigned offset, + const unsigned *src, + unsigned dwords) { unsigned i; @@ -61,38 +60,41 @@ static INLINE void set_dynamic_indirect( struct i915_context *i915, } + /*********************************************************************** - * Modes4: stencil masks and logicop + * Modes4: stencil masks and logicop */ -static void upload_MODES4( struct i915_context *i915 ) +static void upload_MODES4(struct i915_context *i915) { unsigned modes4 = 0; - /* I915_NEW_STENCIL */ + /* I915_NEW_STENCIL + */ modes4 |= i915->depth_stencil->stencil_modes4; - /* I915_NEW_BLEND */ + + /* I915_NEW_BLEND + */ modes4 |= i915->blend->modes4; - /* Always, so that we know when state is in-active: + /* Always, so that we know when state is in-active: */ - set_dynamic_indirect( i915, - I915_DYNAMIC_MODES4, - &modes4, - 1 ); + set_dynamic_indirect(i915, + I915_DYNAMIC_MODES4, + &modes4, + 1); } const struct i915_tracked_state i915_upload_MODES4 = { - I915_NEW_BLEND | I915_NEW_DEPTH_STENCIL, - upload_MODES4 + "MODES4", + upload_MODES4, + I915_NEW_BLEND | I915_NEW_DEPTH_STENCIL }; - /*********************************************************************** */ - -static void upload_BFO( struct i915_context *i915 ) +static void upload_BFO(struct i915_context *i915) { unsigned bfo[2]; bfo[0] = i915->depth_stencil->bfo[0]; @@ -101,88 +103,89 @@ static void upload_BFO( struct i915_context *i915 ) if (bfo[0] & BFO_ENABLE_STENCIL_REF) { bfo[0] |= i915->stencil_ref.ref_value[1] << BFO_STENCIL_REF_SHIFT; } - set_dynamic_indirect( i915, - I915_DYNAMIC_BFO_0, - &(bfo[0]), - 2 ); + + set_dynamic_indirect(i915, + I915_DYNAMIC_BFO_0, + &(bfo[0]), + 2); } const struct i915_tracked_state i915_upload_BFO = { - I915_NEW_DEPTH_STENCIL, - upload_BFO + "BFO", + upload_BFO, + I915_NEW_DEPTH_STENCIL }; + /*********************************************************************** */ - - -static void upload_BLENDCOLOR( struct i915_context *i915 ) +static void upload_BLENDCOLOR(struct i915_context *i915) { unsigned bc[2]; - memset( bc, 0, sizeof(bc) ); + memset(bc, 0, sizeof(bc)); - /* I915_NEW_BLEND {_COLOR} + /* I915_NEW_BLEND */ { const float *color = i915->blend_color.color; bc[0] = _3DSTATE_CONST_BLEND_COLOR_CMD; - bc[1] = pack_ui32_float4( color[0], - color[1], - color[2], - color[3] ); + bc[1] = pack_ui32_float4(color[0], + color[1], + color[2], + color[3]); } - set_dynamic_indirect( i915, - I915_DYNAMIC_BC_0, - bc, - 2 ); + set_dynamic_indirect(i915, + I915_DYNAMIC_BC_0, + bc, + 2); } const struct i915_tracked_state i915_upload_BLENDCOLOR = { - I915_NEW_BLEND, - upload_BLENDCOLOR + "BLENDCOLOR", + upload_BLENDCOLOR, + I915_NEW_BLEND }; -/*********************************************************************** - */ -static void upload_IAB( struct i915_context *i915 ) +/*********************************************************************** + */ +static void upload_IAB(struct i915_context *i915) { unsigned iab = i915->blend->iab; - - set_dynamic_indirect( i915, - I915_DYNAMIC_IAB, - &iab, - 1 ); + set_dynamic_indirect(i915, + I915_DYNAMIC_IAB, + &iab, + 1); } const struct i915_tracked_state i915_upload_IAB = { - I915_NEW_BLEND, - upload_IAB + "IAB", + upload_IAB, + I915_NEW_BLEND }; + /*********************************************************************** */ - - - -static void upload_DEPTHSCALE( struct i915_context *i915 ) +static void upload_DEPTHSCALE(struct i915_context *i915) { - set_dynamic_indirect( i915, - I915_DYNAMIC_DEPTHSCALE_0, - &(i915->rasterizer->ds[0].u), - 2 ); + set_dynamic_indirect(i915, + I915_DYNAMIC_DEPTHSCALE_0, + &(i915->rasterizer->ds[0].u), + 2); } const struct i915_tracked_state i915_upload_DEPTHSCALE = { - I915_NEW_RASTERIZER, - upload_DEPTHSCALE + "DEPTHSCALE", + upload_DEPTHSCALE, + I915_NEW_RASTERIZER }; @@ -196,10 +199,9 @@ const struct i915_tracked_state i915_upload_DEPTHSCALE = { * XXX: does stipple pattern need to be adjusted according to * the window position? * - * XXX: possibly need workaround for conform paths test. + * XXX: possibly need workaround for conform paths test. */ - -static void upload_STIPPLE( struct i915_context *i915 ) +static void upload_STIPPLE(struct i915_context *i915) { unsigned st[2]; @@ -210,7 +212,6 @@ static void upload_STIPPLE( struct i915_context *i915 ) */ st[1] |= i915->rasterizer->st; - /* I915_NEW_STIPPLE */ { @@ -225,73 +226,75 @@ static void upload_STIPPLE( struct i915_context *i915 ) /* Not sure what to do about fallbacks, so for now just dont: */ st[1] |= ((p[0] << 0) | - (p[1] << 4) | - (p[2] << 8) | - (p[3] << 12)); + (p[1] << 4) | + (p[2] << 8) | + (p[3] << 12)); } - - set_dynamic_indirect( i915, - I915_DYNAMIC_STP_0, - &st[0], - 2 ); + set_dynamic_indirect(i915, + I915_DYNAMIC_STP_0, + &st[0], + 2); } - const struct i915_tracked_state i915_upload_STIPPLE = { - I915_NEW_RASTERIZER | I915_NEW_STIPPLE, - upload_STIPPLE + "STIPPLE", + upload_STIPPLE, + I915_NEW_RASTERIZER | I915_NEW_STIPPLE }; /*********************************************************************** - * Scissor. + * Scissor enable */ static void upload_SCISSOR_ENABLE( struct i915_context *i915 ) { - set_dynamic_indirect( i915, - I915_DYNAMIC_SC_ENA_0, - &(i915->rasterizer->sc[0]), - 1 ); + set_dynamic_indirect(i915, + I915_DYNAMIC_SC_ENA_0, + &(i915->rasterizer->sc[0]), + 1); } const struct i915_tracked_state i915_upload_SCISSOR_ENABLE = { - I915_NEW_RASTERIZER, - upload_SCISSOR_ENABLE + "SCISSOR ENABLE", + upload_SCISSOR_ENABLE, + I915_NEW_RASTERIZER }; -static void upload_SCISSOR_RECT( struct i915_context *i915 ) +/*********************************************************************** + * Scissor rect + */ +static void upload_SCISSOR_RECT(struct i915_context *i915) { unsigned x1 = i915->scissor.minx; unsigned y1 = i915->scissor.miny; unsigned x2 = i915->scissor.maxx; unsigned y2 = i915->scissor.maxy; unsigned sc[3]; - + sc[0] = _3DSTATE_SCISSOR_RECT_0_CMD; sc[1] = (y1 << 16) | (x1 & 0xffff); sc[2] = (y2 << 16) | (x2 & 0xffff); - set_dynamic_indirect( i915, - I915_DYNAMIC_SC_RECT_0, - &sc[0], - 3 ); + set_dynamic_indirect(i915, + I915_DYNAMIC_SC_RECT_0, + &sc[0], + 3); } - const struct i915_tracked_state i915_upload_SCISSOR_RECT = { - I915_NEW_SCISSOR, - upload_SCISSOR_RECT + "SCISSOR RECT", + upload_SCISSOR_RECT, + I915_NEW_SCISSOR }; - - - +/*********************************************************************** + */ static const struct i915_tracked_state *atoms[] = { &i915_upload_MODES4, &i915_upload_BFO, @@ -306,12 +309,17 @@ static const struct i915_tracked_state *atoms[] = { /* These will be dynamic indirect state commands, but for now just end * up on the batch buffer with everything else. */ -void i915_update_dynamic( struct i915_context *i915 ) +static void update_dynamic(struct i915_context *i915) { int i; for (i = 0; i < Elements(atoms); i++) if (i915->dirty & atoms[i]->dirty) - atoms[i]->update( i915 ); + atoms[i]->update(i915); } +struct i915_tracked_state i915_hw_dynamic = { + "dynamic", + update_dynamic, + ~0 /* all state atoms, becuase we do internal checking */ +}; diff --git a/src/gallium/drivers/i915/i915_state_emit.c b/src/gallium/drivers/i915/i915_state_emit.c index 22082fece8..bbf9ff51f5 100644 --- a/src/gallium/drivers/i915/i915_state_emit.c +++ b/src/gallium/drivers/i915/i915_state_emit.c @@ -29,6 +29,7 @@ #include "i915_reg.h" #include "i915_context.h" #include "i915_batch.h" +#include "i915_debug.h" #include "i915_reg.h" #include "i915_resource.h" @@ -111,15 +112,20 @@ i915_emit_hardware_state(struct i915_context *i915 ) 3 ) * 3/2; /* plus 50% margin */ -#if 0 - debug_printf("i915_emit_hardware_state: %d dwords, %d relocs\n", dwords, relocs); -#endif - + uintptr_t save_ptr; + size_t save_relocs; + + if (I915_DBG_ON(DBG_ATOMS)) + i915_dump_hardware_dirty(i915, __FUNCTION__); + if(!BEGIN_BATCH(dwords, relocs)) { FLUSH_BATCH(NULL); assert(BEGIN_BATCH(dwords, relocs)); } + save_ptr = (uintptr_t)i915->batch->ptr; + save_relocs = i915->batch->relocs; + /* 14 dwords, 0 relocs */ if (i915->hardware_dirty & I915_HW_INVARIENT) { @@ -399,6 +405,9 @@ i915_emit_hardware_state(struct i915_context *i915 ) OUT_BATCH(0); } + I915_DBG(DBG_EMIT, "%s: used %d dwords, %d relocs\n", __FUNCTION__, + ((uintptr_t)i915->batch->ptr - save_ptr) / 4, + i915->batch->relocs - save_relocs); i915->hardware_dirty = 0; } diff --git a/src/gallium/drivers/i915/i915_state_immediate.c b/src/gallium/drivers/i915/i915_state_immediate.c index 8cec699285..f9ade7077f 100644 --- a/src/gallium/drivers/i915/i915_state_immediate.c +++ b/src/gallium/drivers/i915/i915_state_immediate.c @@ -1,8 +1,8 @@ /************************************************************************** - * + * * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. * All Rights Reserved. - * + * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including @@ -10,11 +10,11 @@ * 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. @@ -22,13 +22,13 @@ * 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. - * + * **************************************************************************/ /* * Authors: * Keith Whitwell <keith@tungstengraphics.com> */ - + #include "i915_state_inlines.h" #include "i915_context.h" #include "i915_state.h" @@ -46,30 +46,31 @@ /*********************************************************************** - * S0,S1: Vertex buffer state. + * S0,S1: Vertex buffer state. */ static void upload_S0S1(struct i915_context *i915) { unsigned LIS0, LIS1; - /* I915_NEW_VBO */ - /* TODO: re-use vertex buffers here? */ + /* I915_NEW_VBO + */ LIS0 = i915->vbo_offset; - /* I915_NEW_VERTEX_SIZE -- do this where the vertex size is calculated! + /* I915_NEW_VERTEX_SIZE */ + /* XXX do this where the vertex size is calculated! */ { unsigned vertex_size = i915->current.vertex_info.size; LIS1 = ((vertex_size << 24) | - (vertex_size << 16)); + (vertex_size << 16)); } - /* I915_NEW_VBO */ - /* TODO: use a vertex generation number to track vbo changes */ + /* I915_NEW_VBO + */ if (1 || i915->current.immediate[I915_IMMEDIATE_S0] != LIS0 || - i915->current.immediate[I915_IMMEDIATE_S1] != LIS1) + i915->current.immediate[I915_IMMEDIATE_S1] != LIS1) { i915->current.immediate[I915_IMMEDIATE_S0] = LIS0; i915->current.immediate[I915_IMMEDIATE_S1] = LIS1; @@ -78,13 +79,13 @@ static void upload_S0S1(struct i915_context *i915) } const struct i915_tracked_state i915_upload_S0S1 = { - I915_NEW_VBO | I915_NEW_VERTEX_FORMAT, - upload_S0S1 + "imm S0 S1", + upload_S0S1, + I915_NEW_VBO | I915_NEW_VERTEX_FORMAT }; - /*********************************************************************** * S4: Vertex format, rasterization state */ @@ -92,7 +93,8 @@ static void upload_S2S4(struct i915_context *i915) { unsigned LIS2, LIS4; - /* I915_NEW_VERTEX_FORMAT */ + /* I915_NEW_VERTEX_FORMAT + */ { LIS2 = i915->current.vertex_info.hwfmt[1]; LIS4 = i915->current.vertex_info.hwfmt[0]; @@ -113,35 +115,38 @@ static void upload_S2S4(struct i915_context *i915) } } - const struct i915_tracked_state i915_upload_S2S4 = { - I915_NEW_RASTERIZER | I915_NEW_VERTEX_FORMAT, - upload_S2S4 + "imm S2 S4", + upload_S2S4, + I915_NEW_RASTERIZER | I915_NEW_VERTEX_FORMAT }; /*********************************************************************** - * */ -static void upload_S5( struct i915_context *i915 ) +static void upload_S5(struct i915_context *i915) { unsigned LIS5 = 0; + /* I915_NEW_DEPTH_STENCIL + */ LIS5 |= i915->depth_stencil->stencil_LIS5; /* hope it's safe to set stencil ref value even if stencil test is disabled? */ LIS5 |= i915->stencil_ref.ref_value[0] << S5_STENCIL_REF_SHIFT; + /* I915_NEW_BLEND + */ LIS5 |= i915->blend->LIS5; #if 0 - /* I915_NEW_RASTERIZER */ + /* I915_NEW_RASTERIZER + */ if (i915->state.Polygon->OffsetFill) { LIS5 |= S5_GLOBAL_DEPTH_OFFSET_ENABLE; } #endif - if (LIS5 != i915->current.immediate[I915_IMMEDIATE_S5]) { i915->current.immediate[I915_IMMEDIATE_S5] = LIS5; i915->hardware_dirty |= I915_HW_IMMEDIATE; @@ -149,14 +154,16 @@ static void upload_S5( struct i915_context *i915 ) } const struct i915_tracked_state i915_upload_S5 = { - (I915_NEW_DEPTH_STENCIL | I915_NEW_BLEND | I915_NEW_RASTERIZER), - upload_S5 + "imm S5", + upload_S5, + I915_NEW_DEPTH_STENCIL | I915_NEW_BLEND | I915_NEW_RASTERIZER }; + /*********************************************************************** */ -static void upload_S6( struct i915_context *i915 ) +static void upload_S6(struct i915_context *i915) { unsigned LIS6 = (2 << S6_TRISTRIP_PV_SHIFT); @@ -180,14 +187,16 @@ static void upload_S6( struct i915_context *i915 ) } const struct i915_tracked_state i915_upload_S6 = { - I915_NEW_BLEND | I915_NEW_DEPTH_STENCIL | I915_NEW_FRAMEBUFFER, - upload_S6 + "imm s6", + upload_S6, + I915_NEW_BLEND | I915_NEW_DEPTH_STENCIL | I915_NEW_FRAMEBUFFER }; + /*********************************************************************** */ -static void upload_S7( struct i915_context *i915 ) +static void upload_S7(struct i915_context *i915) { unsigned LIS7; @@ -202,11 +211,15 @@ static void upload_S7( struct i915_context *i915 ) } const struct i915_tracked_state i915_upload_S7 = { - I915_NEW_RASTERIZER, - upload_S7 + "imm S7", + upload_S7, + I915_NEW_RASTERIZER }; + +/*********************************************************************** + */ static const struct i915_tracked_state *atoms[] = { &i915_upload_S0S1, &i915_upload_S2S4, @@ -215,13 +228,17 @@ static const struct i915_tracked_state *atoms[] = { &i915_upload_S7 }; -/* - */ -void i915_update_immediate( struct i915_context *i915 ) +static void update_immediate(struct i915_context *i915) { int i; for (i = 0; i < Elements(atoms); i++) if (i915->dirty & atoms[i]->dirty) - atoms[i]->update( i915 ); + atoms[i]->update(i915); } + +struct i915_tracked_state i915_hw_immediate = { + "immediate", + update_immediate, + ~0 /* all state atoms, becuase we do internal checking */ +}; diff --git a/src/gallium/drivers/i915/i915_state_sampler.c b/src/gallium/drivers/i915/i915_state_sampler.c index 77b9bccbb7..941259eb76 100644 --- a/src/gallium/drivers/i915/i915_state_sampler.c +++ b/src/gallium/drivers/i915/i915_state_sampler.c @@ -53,17 +53,23 @@ * * So we need to update the map state when we change samplers and * we need to be change the sampler state when map state is changed. - * The first part is done by calling i915_update_texture in - * i915_update_samplers and the second part is done else where in - * code tracking the state changes. + * The first part is done by calling update_texture in update_samplers + * and the second part is done else where in code tracking the state + * changes. + */ + +static void update_texture(struct i915_context *i915, + uint unit, + const struct i915_texture *tex, + const struct i915_sampler_state *sampler, + uint state[6]); + + + +/*********************************************************************** + * Samplers */ -static void -i915_update_texture(struct i915_context *i915, - uint unit, - const struct i915_texture *tex, - const struct i915_sampler_state *sampler, - uint state[6]); /** * Compute i915 texture sampling state. * @@ -74,16 +80,13 @@ i915_update_texture(struct i915_context *i915, */ static void update_sampler(struct i915_context *i915, uint unit, - const struct i915_sampler_state *sampler, - const struct i915_texture *tex, - unsigned state[3] ) + const struct i915_sampler_state *sampler, + const struct i915_texture *tex, + unsigned state[3]) { const struct pipe_resource *pt = &tex->b.b; unsigned minlod, lastlod; - /* Need to do this after updating the maps, which call the - * intel_finalize_mipmap_tree and hence can update firstLevel: - */ state[0] = sampler->state[0]; state[1] = sampler->state[1]; state[2] = sampler->state[2]; @@ -118,7 +121,7 @@ static void update_sampler(struct i915_context *i915, wr == PIPE_TEX_WRAP_CLAMP_TO_BORDER)) { if (i915->conformance_mode > 0) { assert(0); - /* sampler->fallback = true; */ + /* sampler->fallback = true; */ /* TODO */ } } @@ -137,8 +140,7 @@ static void update_sampler(struct i915_context *i915, state[1] |= (unit << SS3_TEXTUREMAP_INDEX_SHIFT); } - -void i915_update_samplers( struct i915_context *i915 ) +static void update_samplers(struct i915_context *i915) { uint unit; @@ -152,29 +154,38 @@ void i915_update_samplers( struct i915_context *i915 ) if (i915->fragment_sampler_views[unit]) { struct i915_texture *texture = i915_texture(i915->fragment_sampler_views[unit]->texture); - update_sampler( i915, - unit, - i915->sampler[unit], /* sampler state */ - texture, /* texture */ - i915->current.sampler[unit] /* the result */ - ); - i915_update_texture( i915, - unit, - texture, /* texture */ - i915->sampler[unit], /* sampler state */ - i915->current.texbuffer[unit] ); - - i915->current.sampler_enable_nr++; - i915->current.sampler_enable_flags |= (1 << unit); + update_sampler(i915, + unit, + i915->sampler[unit], /* sampler state */ + texture, /* texture */ + i915->current.sampler[unit]); /* the result */ + update_texture(i915, + unit, + texture, /* texture */ + i915->sampler[unit], /* sampler state */ + i915->current.texbuffer[unit]); /* the result */ + + i915->current.sampler_enable_nr++; + i915->current.sampler_enable_flags |= (1 << unit); } } i915->hardware_dirty |= I915_HW_SAMPLER | I915_HW_MAP; } +struct i915_tracked_state i915_hw_samplers = { + "sampler_views", + update_samplers, + I915_NEW_SAMPLER | I915_NEW_SAMPLER_VIEW +}; -static uint -translate_texture_format(enum pipe_format pipeFormat) + + +/*********************************************************************** + * Sampler views + */ + +static uint translate_texture_format(enum pipe_format pipeFormat) { switch (pipeFormat) { case PIPE_FORMAT_L8_UNORM: @@ -226,19 +237,17 @@ translate_texture_format(enum pipe_format pipeFormat) return (MAPSURF_32BIT | MT_32BIT_xI824); default: debug_printf("i915: translate_texture_format() bad image format %x\n", - pipeFormat); + pipeFormat); assert(0); return 0; } } - -static void -i915_update_texture(struct i915_context *i915, - uint unit, - const struct i915_texture *tex, - const struct i915_sampler_state *sampler, - uint state[6]) +static void update_texture(struct i915_context *i915, + uint unit, + const struct i915_texture *tex, + const struct i915_sampler_state *sampler, + uint state[6]) { const struct pipe_resource *pt = &tex->b.b; uint format, pitch; @@ -287,9 +296,7 @@ i915_update_texture(struct i915_context *i915, | ((depth - 1) << MS4_VOLUME_DEPTH_SHIFT)); } - -void -i915_update_textures(struct i915_context *i915) +static void update_textures(struct i915_context *i915) { uint unit; @@ -300,13 +307,19 @@ i915_update_textures(struct i915_context *i915) if (i915->fragment_sampler_views[unit]) { struct i915_texture *texture = i915_texture(i915->fragment_sampler_views[unit]->texture); - i915_update_texture( i915, - unit, - texture, /* texture */ - i915->sampler[unit], /* sampler state */ - i915->current.texbuffer[unit] ); + update_texture(i915, + unit, + texture, /* texture */ + i915->sampler[unit], /* sampler state */ + i915->current.texbuffer[unit]); } } i915->hardware_dirty |= I915_HW_MAP; } + +struct i915_tracked_state i915_hw_sampler_views = { + "sampler_views", + update_textures, + I915_NEW_SAMPLER_VIEW +}; diff --git a/src/gallium/drivers/i965/SConscript b/src/gallium/drivers/i965/SConscript index 019af682f6..119f914a16 100644 --- a/src/gallium/drivers/i965/SConscript +++ b/src/gallium/drivers/i965/SConscript @@ -2,6 +2,10 @@ Import('*') env = env.Clone() +if msvc: + print 'warning: not building i965g' + Return(); + i965 = env.ConvenienceLibrary( target = 'i965', source = [ diff --git a/src/gallium/drivers/i965/brw_disasm.c b/src/gallium/drivers/i965/brw_disasm.c index 4c8579365d..28c83515ba 100644 --- a/src/gallium/drivers/i965/brw_disasm.c +++ b/src/gallium/drivers/i965/brw_disasm.c @@ -239,7 +239,7 @@ char *imm_encoding[8] = { [2] = "UW", [3] = "W", [5] = "VF", - [5] = "V", + [6] = "V", [7] = "F" }; diff --git a/src/gallium/drivers/i965/brw_pipe_query.c b/src/gallium/drivers/i965/brw_pipe_query.c index 2eb862635c..0745254c3c 100644 --- a/src/gallium/drivers/i965/brw_pipe_query.c +++ b/src/gallium/drivers/i965/brw_pipe_query.c @@ -50,10 +50,11 @@ static boolean brw_query_get_result(struct pipe_context *pipe, struct pipe_query *q, boolean wait, - uint64_t *result) + void *vresult) { struct brw_context *brw = brw_context(pipe); struct brw_query_object *query = (struct brw_query_object *)q; + uint64_t *result = (uint64_t*)vresult; /* Map and count the pixels from the current query BO */ if (query->bo) { diff --git a/src/gallium/drivers/identity/id_context.c b/src/gallium/drivers/identity/id_context.c index 898e0b3af8..67be895b38 100644 --- a/src/gallium/drivers/identity/id_context.c +++ b/src/gallium/drivers/identity/id_context.c @@ -158,7 +158,7 @@ static boolean identity_get_query_result(struct pipe_context *_pipe, struct pipe_query *query, boolean wait, - uint64_t *result) + void *result) { struct identity_context *id_pipe = identity_context(_pipe); struct pipe_context *pipe = id_pipe->pipe; diff --git a/src/gallium/drivers/identity/id_objects.c b/src/gallium/drivers/identity/id_objects.c index ca4743f9ef..593928f399 100644 --- a/src/gallium/drivers/identity/id_objects.c +++ b/src/gallium/drivers/identity/id_objects.c @@ -120,13 +120,14 @@ identity_sampler_view_create(struct identity_context *id_context, assert(view->texture == id_resource->resource); - id_view = MALLOC(sizeof(struct identity_sampler_view)); + id_view = CALLOC_STRUCT(identity_sampler_view); id_view->base = *view; id_view->base.reference.count = 1; id_view->base.texture = NULL; pipe_resource_reference(&id_view->base.texture, id_resource->resource); id_view->base.context = id_context->pipe; + id_view->sampler_view = view; return &id_view->base; error: @@ -180,8 +181,8 @@ identity_transfer_destroy(struct identity_context *id_context, struct identity_transfer *id_transfer) { pipe_resource_reference(&id_transfer->base.resource, NULL); - id_transfer->pipe->transfer_destroy(id_context->pipe, - id_transfer->transfer); + id_context->pipe->transfer_destroy(id_context->pipe, + id_transfer->transfer); FREE(id_transfer); } diff --git a/src/gallium/drivers/identity/id_objects.h b/src/gallium/drivers/identity/id_objects.h index 5eea10b0b5..e8deabf4fc 100644 --- a/src/gallium/drivers/identity/id_objects.h +++ b/src/gallium/drivers/identity/id_objects.h @@ -65,7 +65,6 @@ struct identity_transfer { struct pipe_transfer base; - struct pipe_context *pipe; struct pipe_transfer *transfer; }; diff --git a/src/gallium/drivers/llvmpipe/.gitignore b/src/gallium/drivers/llvmpipe/.gitignore index a1b6f56e0d..4e0d4c3fc0 100644 --- a/src/gallium/drivers/llvmpipe/.gitignore +++ b/src/gallium/drivers/llvmpipe/.gitignore @@ -3,3 +3,4 @@ lp_test_blend lp_test_conv lp_test_format lp_test_printf +lp_test_sincos diff --git a/src/gallium/drivers/llvmpipe/Makefile b/src/gallium/drivers/llvmpipe/Makefile index 213e4c4a99..ee28179c30 100644 --- a/src/gallium/drivers/llvmpipe/Makefile +++ b/src/gallium/drivers/llvmpipe/Makefile @@ -34,8 +34,10 @@ C_SOURCES = \ lp_state_clip.c \ lp_state_derived.c \ lp_state_fs.c \ + lp_state_gs.c \ lp_state_rasterizer.c \ lp_state_sampler.c \ + lp_state_so.c \ lp_state_surface.c \ lp_state_vertex.c \ lp_state_vs.c \ diff --git a/src/gallium/drivers/llvmpipe/SConscript b/src/gallium/drivers/llvmpipe/SConscript index a0646692e7..a1ef71da89 100644 --- a/src/gallium/drivers/llvmpipe/SConscript +++ b/src/gallium/drivers/llvmpipe/SConscript @@ -57,6 +57,7 @@ llvmpipe = env.ConvenienceLibrary( 'lp_state_gs.c', 'lp_state_rasterizer.c', 'lp_state_sampler.c', + 'lp_state_so.c', 'lp_state_surface.c', 'lp_state_vertex.c', 'lp_state_vs.c', diff --git a/src/gallium/drivers/llvmpipe/lp_context.c b/src/gallium/drivers/llvmpipe/lp_context.c index 9e88a6e09f..3db4f12ebb 100644 --- a/src/gallium/drivers/llvmpipe/lp_context.c +++ b/src/gallium/drivers/llvmpipe/lp_context.c @@ -36,6 +36,7 @@ #include "util/u_inlines.h" #include "util/u_math.h" #include "util/u_memory.h" +#include "util/u_simple_list.h" #include "lp_clear.h" #include "lp_context.h" #include "lp_flush.h" @@ -94,6 +95,8 @@ llvmpipe_create_context( struct pipe_screen *screen, void *priv ) memset(llvmpipe, 0, sizeof *llvmpipe); + make_empty_list(&llvmpipe->fs_variants_list); + llvmpipe->pipe.winsys = screen->winsys; llvmpipe->pipe.screen = screen; llvmpipe->pipe.priv = priv; @@ -110,6 +113,7 @@ llvmpipe_create_context( struct pipe_screen *screen, void *priv ) llvmpipe_init_sampler_funcs(llvmpipe); llvmpipe_init_query_funcs( llvmpipe ); llvmpipe_init_vertex_funcs(llvmpipe); + llvmpipe_init_so_funcs(llvmpipe); llvmpipe_init_fs_funcs(llvmpipe); llvmpipe_init_vs_funcs(llvmpipe); llvmpipe_init_gs_funcs(llvmpipe); diff --git a/src/gallium/drivers/llvmpipe/lp_context.h b/src/gallium/drivers/llvmpipe/lp_context.h index cb04d4a4d5..986e604ce7 100644 --- a/src/gallium/drivers/llvmpipe/lp_context.h +++ b/src/gallium/drivers/llvmpipe/lp_context.h @@ -38,6 +38,7 @@ #include "lp_tex_sample.h" #include "lp_jit.h" #include "lp_setup.h" +#include "lp_state_fs.h" struct llvmpipe_vbuf_render; @@ -62,6 +63,7 @@ struct llvmpipe_context { const struct lp_vertex_shader *vs; const struct lp_geometry_shader *gs; const struct lp_velems_state *velems; + const struct lp_so_state *so; /** Other rendering state */ struct pipe_blend_color blend_color; @@ -75,6 +77,12 @@ struct llvmpipe_context { struct pipe_sampler_view *vertex_sampler_views[PIPE_MAX_VERTEX_SAMPLERS]; struct pipe_viewport_state viewport; struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS]; + struct { + struct llvmpipe_resource *buffer[PIPE_MAX_SO_BUFFERS]; + int offset[PIPE_MAX_SO_BUFFERS]; + int so_count[PIPE_MAX_SO_BUFFERS]; + int num_buffers; + } so_target; unsigned num_samplers; unsigned num_fragment_sampler_views; @@ -105,6 +113,8 @@ struct llvmpipe_context { unsigned tex_timestamp; boolean no_rast; + struct lp_fs_variant_list_item fs_variants_list; + unsigned nr_fs_variants; }; diff --git a/src/gallium/drivers/llvmpipe/lp_limits.h b/src/gallium/drivers/llvmpipe/lp_limits.h index 4102a9df67..d1c431475d 100644 --- a/src/gallium/drivers/llvmpipe/lp_limits.h +++ b/src/gallium/drivers/llvmpipe/lp_limits.h @@ -66,5 +66,10 @@ */ #define LP_MAX_SCENE_SIZE (512 * 1024 * 1024) +/** + * Max number of shader variants (for all shaders combined, + * per context) that will be kept around. + */ +#define LP_MAX_SHADER_VARIANTS 1024 #endif /* LP_LIMITS_H */ diff --git a/src/gallium/drivers/llvmpipe/lp_query.c b/src/gallium/drivers/llvmpipe/lp_query.c index c486442286..c902c04684 100644 --- a/src/gallium/drivers/llvmpipe/lp_query.c +++ b/src/gallium/drivers/llvmpipe/lp_query.c @@ -76,10 +76,11 @@ static boolean llvmpipe_get_query_result(struct pipe_context *pipe, struct pipe_query *q, boolean wait, - uint64_t *result ) + void *vresult) { struct llvmpipe_context *llvmpipe = llvmpipe_context( pipe ); struct llvmpipe_query *pq = llvmpipe_query(q); + uint64_t *result = (uint64_t *)vresult; if (!pq->done) { lp_setup_flush(llvmpipe->setup, 0); diff --git a/src/gallium/drivers/llvmpipe/lp_rast.c b/src/gallium/drivers/llvmpipe/lp_rast.c index 50e44dcb2b..1fadb9cca1 100644 --- a/src/gallium/drivers/llvmpipe/lp_rast.c +++ b/src/gallium/drivers/llvmpipe/lp_rast.c @@ -627,7 +627,7 @@ void lp_rast_begin_query(struct lp_rasterizer_task *task, const union lp_rast_cmd_arg arg) { - /* Reset the the per-task counter */ + /* Reset the per-task counter */ task->vis_counter = 0; } diff --git a/src/gallium/drivers/llvmpipe/lp_setup.c b/src/gallium/drivers/llvmpipe/lp_setup.c index b6db66fe64..9e319fd9f0 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup.c +++ b/src/gallium/drivers/llvmpipe/lp_setup.c @@ -297,6 +297,11 @@ lp_setup_bind_framebuffer( struct lp_setup_context *setup, */ set_scene_state( setup, SETUP_FLUSHED ); + /* + * Ensure the old scene is not reused. + */ + assert(!setup->scene); + /* Set new state. This will be picked up later when we next need a * scene. */ @@ -326,7 +331,7 @@ lp_setup_clear( struct lp_setup_context *setup, if (flags & PIPE_CLEAR_DEPTHSTENCIL) { if (setup->fb.zsbuf && - ((setup->clear.flags & PIPE_CLEAR_DEPTHSTENCIL) != PIPE_CLEAR_DEPTHSTENCIL) && + ((flags & PIPE_CLEAR_DEPTHSTENCIL) != PIPE_CLEAR_DEPTHSTENCIL) && util_format_is_depth_and_stencil(setup->fb.zsbuf->format)) full_zs_clear = FALSE; @@ -933,6 +938,8 @@ lp_setup_begin_query(struct lp_setup_context *setup, memset(pq->count, 0, sizeof(pq->count)); /* reset all counters */ + set_scene_state( setup, SETUP_ACTIVE ); + cmd_arg.query_obj = pq; lp_scene_bin_everywhere(scene, lp_rast_begin_query, cmd_arg); pq->binned = TRUE; @@ -948,6 +955,8 @@ lp_setup_end_query(struct lp_setup_context *setup, struct llvmpipe_query *pq) struct lp_scene * scene = lp_setup_get_current_scene(setup); union lp_rast_cmd_arg cmd_arg; + set_scene_state( setup, SETUP_ACTIVE ); + cmd_arg.query_obj = pq; lp_scene_bin_everywhere(scene, lp_rast_end_query, cmd_arg); } diff --git a/src/gallium/drivers/llvmpipe/lp_setup_vbuf.c b/src/gallium/drivers/llvmpipe/lp_setup_vbuf.c index f6a424f25a..e53a62cb72 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup_vbuf.c +++ b/src/gallium/drivers/llvmpipe/lp_setup_vbuf.c @@ -60,10 +60,6 @@ static const struct vertex_info * lp_setup_get_vertex_info(struct vbuf_render *vbr) { struct lp_setup_context *setup = lp_setup_context(vbr); - - /* vertex size/info depends on the latest state */ - lp_setup_update_state(setup); - return setup->vertex_info; } diff --git a/src/gallium/drivers/llvmpipe/lp_state.h b/src/gallium/drivers/llvmpipe/lp_state.h index 3f7a85b682..05d1b93794 100644 --- a/src/gallium/drivers/llvmpipe/lp_state.h +++ b/src/gallium/drivers/llvmpipe/lp_state.h @@ -54,6 +54,9 @@ #define LP_NEW_QUERY 0x4000 #define LP_NEW_BLEND_COLOR 0x8000 #define LP_NEW_GS 0x10000 +#define LP_NEW_SO 0x20000 +#define LP_NEW_SO_BUFFERS 0x40000 + struct vertex_info; @@ -82,6 +85,10 @@ struct lp_velems_state struct pipe_vertex_element velem[PIPE_MAX_ATTRIBS]; }; +struct lp_so_state { + struct pipe_stream_output_state base; +}; + void llvmpipe_set_framebuffer_state(struct pipe_context *, @@ -120,5 +127,9 @@ llvmpipe_init_gs_funcs(struct llvmpipe_context *llvmpipe); void llvmpipe_init_rasterizer_funcs(struct llvmpipe_context *llvmpipe); +void +llvmpipe_init_so_funcs(struct llvmpipe_context *llvmpipe); + + #endif diff --git a/src/gallium/drivers/llvmpipe/lp_state_fs.c b/src/gallium/drivers/llvmpipe/lp_state_fs.c index 2619e043fd..65115052cd 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_fs.c +++ b/src/gallium/drivers/llvmpipe/lp_state_fs.c @@ -68,6 +68,7 @@ #include "util/u_format.h" #include "util/u_dump.h" #include "util/u_string.h" +#include "util/u_simple_list.h" #include "os/os_time.h" #include "pipe/p_shader_tokens.h" #include "draw/draw_context.h" @@ -95,6 +96,7 @@ #include "lp_setup.h" #include "lp_state.h" #include "lp_tex_sample.h" +#include "lp_flush.h" #include <llvm-c/Analysis.h> @@ -936,7 +938,10 @@ generate_variant(struct llvmpipe_context *lp, if(!variant) return NULL; - variant->no = shader->variant_no++; + variant->shader = shader; + variant->list_item_global.base = variant; + variant->list_item_local.base = variant; + variant->no = shader->variants_created++; memcpy(&variant->key, key, sizeof *key); @@ -962,10 +967,6 @@ generate_variant(struct llvmpipe_context *lp, !shader->info.uses_kill ? TRUE : FALSE; - /* insert new variant into linked list */ - variant->next = shader->variants; - shader->variants = variant; - return variant; } @@ -981,6 +982,7 @@ llvmpipe_create_fs_state(struct pipe_context *pipe, return NULL; shader->no = fs_no++; + make_empty_list(&shader->variants); /* get/save the summary info for this shader */ tgsi_scan_shader(templ->tokens, &shader->info); @@ -1024,14 +1026,40 @@ llvmpipe_bind_fs_state(struct pipe_context *pipe, void *fs) llvmpipe->dirty |= LP_NEW_FS; } +static void +remove_shader_variant(struct llvmpipe_context *lp, + struct lp_fragment_shader_variant *variant) +{ + struct llvmpipe_screen *screen = llvmpipe_screen(lp->pipe.screen); + unsigned i; + + if (gallivm_debug & GALLIVM_DEBUG_IR) { + debug_printf("llvmpipe: del fs #%u var #%u v created #%u v cached #%u v total cached #%u\n", + variant->shader->no, variant->no, variant->shader->variants_created, + variant->shader->variants_cached, lp->nr_fs_variants); + } + for (i = 0; i < Elements(variant->function); i++) { + if (variant->function[i]) { + if (variant->jit_function[i]) + LLVMFreeMachineCodeForFunction(screen->engine, + variant->function[i]); + LLVMDeleteFunction(variant->function[i]); + } + } + remove_from_list(&variant->list_item_local); + variant->shader->variants_cached--; + remove_from_list(&variant->list_item_global); + lp->nr_fs_variants--; + FREE(variant); +} static void llvmpipe_delete_fs_state(struct pipe_context *pipe, void *fs) { struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe); - struct llvmpipe_screen *screen = llvmpipe_screen(pipe->screen); + struct pipe_fence_handle *fence = NULL; struct lp_fragment_shader *shader = fs; - struct lp_fragment_shader_variant *variant; + struct lp_fs_variant_list_item *li; assert(fs != llvmpipe->fs); (void) llvmpipe; @@ -1039,29 +1067,24 @@ llvmpipe_delete_fs_state(struct pipe_context *pipe, void *fs) /* * XXX: we need to flush the context until we have some sort of reference * counting in fragment shaders as they may still be binned + * Flushing alone might not sufficient we need to wait on it too. */ - draw_flush(llvmpipe->draw); - lp_setup_flush(llvmpipe->setup, 0); - - variant = shader->variants; - while(variant) { - struct lp_fragment_shader_variant *next = variant->next; - unsigned i; - for (i = 0; i < Elements(variant->function); i++) { - if (variant->function[i]) { - if (variant->jit_function[i]) - LLVMFreeMachineCodeForFunction(screen->engine, - variant->function[i]); - LLVMDeleteFunction(variant->function[i]); - } - } + llvmpipe_flush(pipe, 0, &fence); - FREE(variant); + if (fence) { + pipe->screen->fence_finish(pipe->screen, fence, 0); + pipe->screen->fence_reference(pipe->screen, &fence, NULL); + } - variant = next; + li = first_elem(&shader->variants); + while(!at_end(&shader->variants, li)) { + struct lp_fs_variant_list_item *next = next_elem(li); + remove_shader_variant(llvmpipe, li->base); + li = next; } + assert(shader->variants_cached == 0); FREE((void *) shader->base.tokens); FREE(shader); } @@ -1088,9 +1111,10 @@ llvmpipe_set_constant_buffer(struct pipe_context *pipe, /* note: reference counting */ pipe_resource_reference(&llvmpipe->constants[shader][index], constants); - if(shader == PIPE_SHADER_VERTEX) { - draw_set_mapped_constant_buffer(llvmpipe->draw, PIPE_SHADER_VERTEX, index, - data, size); + if(shader == PIPE_SHADER_VERTEX || + shader == PIPE_SHADER_GEOMETRY) { + draw_set_mapped_constant_buffer(llvmpipe->draw, shader, + index, data, size); } llvmpipe->dirty |= LP_NEW_CONSTANTS; @@ -1215,7 +1239,6 @@ make_variant_key(struct llvmpipe_context *lp, lp_sampler_static_state(&key->sampler[i], lp->fragment_sampler_views[i], lp->sampler[i]); } - /** * Update fragment state. This is called just prior to drawing * something when some fragment-related state has changed. @@ -1225,21 +1248,47 @@ llvmpipe_update_fs(struct llvmpipe_context *lp) { struct lp_fragment_shader *shader = lp->fs; struct lp_fragment_shader_variant_key key; - struct lp_fragment_shader_variant *variant; + struct lp_fragment_shader_variant *variant = NULL; + struct lp_fs_variant_list_item *li; make_variant_key(lp, shader, &key); - variant = shader->variants; - while(variant) { - if(memcmp(&variant->key, &key, sizeof key) == 0) + li = first_elem(&shader->variants); + while(!at_end(&shader->variants, li)) { + if(memcmp(&li->base->key, &key, sizeof key) == 0) { + variant = li->base; break; - - variant = variant->next; + } + li = next_elem(li); } - if (!variant) { + if (variant) { + move_to_head(&lp->fs_variants_list, &variant->list_item_global); + } + else { int64_t t0, t1; int64_t dt; + unsigned i; + if (lp->nr_fs_variants >= LP_MAX_SHADER_VARIANTS) { + struct pipe_context *pipe = &lp->pipe; + struct pipe_fence_handle *fence = NULL; + + /* + * XXX: we need to flush the context until we have some sort of reference + * counting in fragment shaders as they may still be binned + * Flushing alone might not be sufficient we need to wait on it too. + */ + llvmpipe_flush(pipe, 0, &fence); + + if (fence) { + pipe->screen->fence_finish(pipe->screen, fence, 0); + pipe->screen->fence_reference(pipe->screen, &fence, NULL); + } + for (i = 0; i < LP_MAX_SHADER_VARIANTS / 4; i++) { + struct lp_fs_variant_list_item *item = last_elem(&lp->fs_variants_list); + remove_shader_variant(lp, item->base); + } + } t0 = os_time_get(); variant = generate_variant(lp, shader, &key); @@ -1248,6 +1297,13 @@ llvmpipe_update_fs(struct llvmpipe_context *lp) dt = t1 - t0; LP_COUNT_ADD(llvm_compile_time, dt); LP_COUNT_ADD(nr_llvm_compiles, 2); /* emit vs. omit in/out test */ + + if (variant) { + insert_at_head(&shader->variants, &variant->list_item_local); + insert_at_head(&lp->fs_variants_list, &variant->list_item_global); + lp->nr_fs_variants++; + shader->variants_cached++; + } } lp_setup_set_fs_variant(lp->setup, variant); diff --git a/src/gallium/drivers/llvmpipe/lp_state_fs.h b/src/gallium/drivers/llvmpipe/lp_state_fs.h index 64ead2a997..593cd4de6b 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_fs.h +++ b/src/gallium/drivers/llvmpipe/lp_state_fs.h @@ -64,6 +64,11 @@ struct lp_fragment_shader_variant_key struct lp_sampler_static_state sampler[PIPE_MAX_SAMPLERS]; }; +struct lp_fs_variant_list_item +{ + struct lp_fragment_shader_variant *base; + struct lp_fs_variant_list_item *next, *prev; +}; struct lp_fragment_shader_variant { @@ -75,7 +80,8 @@ struct lp_fragment_shader_variant lp_jit_frag_func jit_function[2]; - struct lp_fragment_shader_variant *next; + struct lp_fs_variant_list_item list_item_global, list_item_local; + struct lp_fragment_shader *shader; /* For debugging/profiling purposes */ unsigned no; @@ -89,11 +95,12 @@ struct lp_fragment_shader struct tgsi_shader_info info; - struct lp_fragment_shader_variant *variants; + struct lp_fs_variant_list_item variants; /* For debugging/profiling purposes */ unsigned no; - unsigned variant_no; + unsigned variants_created; + unsigned variants_cached; }; diff --git a/src/gallium/drivers/llvmpipe/lp_state_gs.c b/src/gallium/drivers/llvmpipe/lp_state_gs.c index e5eeb88e2b..1ba6f10821 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_gs.c +++ b/src/gallium/drivers/llvmpipe/lp_state_gs.c @@ -33,7 +33,6 @@ #include "util/u_memory.h" #include "util/u_inlines.h" #include "draw/draw_context.h" -#include "draw/draw_vs.h" #include "tgsi/tgsi_dump.h" #include "tgsi/tgsi_scan.h" #include "tgsi/tgsi_parse.h" diff --git a/src/gallium/drivers/llvmpipe/lp_state_sampler.c b/src/gallium/drivers/llvmpipe/lp_state_sampler.c index 55d43368a3..e94065fb6a 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_sampler.c +++ b/src/gallium/drivers/llvmpipe/lp_state_sampler.c @@ -105,6 +105,13 @@ llvmpipe_bind_vertex_sampler_states(struct pipe_context *pipe, static void +llvmpipe_bind_geometry_sampler_states(struct pipe_context *pipe, + unsigned num, void **sampler) +{ + /* XXX: implementation missing */ +} + +static void llvmpipe_set_fragment_sampler_views(struct pipe_context *pipe, unsigned num, struct pipe_sampler_view **views) @@ -163,6 +170,14 @@ llvmpipe_set_vertex_sampler_views(struct pipe_context *pipe, } +static void +llvmpipe_set_geometry_sampler_views(struct pipe_context *pipe, + unsigned num, + struct pipe_sampler_view **views) +{ + /*XXX: implementation missing */ +} + static struct pipe_sampler_view * llvmpipe_create_sampler_view(struct pipe_context *pipe, struct pipe_resource *texture, @@ -206,8 +221,10 @@ llvmpipe_init_sampler_funcs(struct llvmpipe_context *llvmpipe) llvmpipe->pipe.bind_fragment_sampler_states = llvmpipe_bind_sampler_states; llvmpipe->pipe.bind_vertex_sampler_states = llvmpipe_bind_vertex_sampler_states; + llvmpipe->pipe.bind_geometry_sampler_states = llvmpipe_bind_geometry_sampler_states; llvmpipe->pipe.set_fragment_sampler_views = llvmpipe_set_fragment_sampler_views; llvmpipe->pipe.set_vertex_sampler_views = llvmpipe_set_vertex_sampler_views; + llvmpipe->pipe.set_geometry_sampler_views = llvmpipe_set_geometry_sampler_views; llvmpipe->pipe.create_sampler_view = llvmpipe_create_sampler_view; llvmpipe->pipe.sampler_view_destroy = llvmpipe_sampler_view_destroy; llvmpipe->pipe.delete_sampler_state = llvmpipe_delete_sampler_state; diff --git a/src/gallium/drivers/llvmpipe/lp_state_so.c b/src/gallium/drivers/llvmpipe/lp_state_so.c new file mode 100644 index 0000000000..30b17c9881 --- /dev/null +++ b/src/gallium/drivers/llvmpipe/lp_state_so.c @@ -0,0 +1,137 @@ +/************************************************************************** + * + * 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 "lp_context.h" +#include "lp_state.h" +#include "lp_texture.h" + +#include "util/u_memory.h" +#include "draw/draw_context.h" + + +static void * +llvmpipe_create_stream_output_state(struct pipe_context *pipe, + const struct pipe_stream_output_state *templ) +{ + struct lp_so_state *so; + so = (struct lp_so_state *) CALLOC_STRUCT(lp_so_state); + + if (so) { + so->base.num_outputs = templ->num_outputs; + so->base.stride = templ->stride; + memcpy(so->base.output_buffer, + templ->output_buffer, + sizeof(int) * templ->num_outputs); + memcpy(so->base.register_index, + templ->register_index, + sizeof(int) * templ->num_outputs); + memcpy(so->base.register_mask, + templ->register_mask, + sizeof(ubyte) * templ->num_outputs); + } + return so; +} + +static void +llvmpipe_bind_stream_output_state(struct pipe_context *pipe, + void *so) +{ + struct llvmpipe_context *lp = llvmpipe_context(pipe); + struct lp_so_state *lp_so = (struct lp_so_state *) so; + + lp->so = lp_so; + + lp->dirty |= LP_NEW_SO; + + if (lp_so) + draw_set_so_state(lp->draw, &lp_so->base); +} + +static void +llvmpipe_delete_stream_output_state(struct pipe_context *pipe, void *so) +{ + FREE( so ); +} + +static void +llvmpipe_set_stream_output_buffers(struct pipe_context *pipe, + struct pipe_resource **buffers, + int *offsets, + int num_buffers) +{ + struct llvmpipe_context *lp = llvmpipe_context(pipe); + int i; + void *map_buffers[PIPE_MAX_SO_BUFFERS]; + + assert(num_buffers <= PIPE_MAX_SO_BUFFERS); + if (num_buffers > PIPE_MAX_SO_BUFFERS) + num_buffers = PIPE_MAX_SO_BUFFERS; + + lp->dirty |= LP_NEW_SO_BUFFERS; + + for (i = 0; i < num_buffers; ++i) { + void *mapped; + struct llvmpipe_resource *res = llvmpipe_resource(buffers[i]); + + if (!res) { + /* the whole call is invalid, bail out */ + lp->so_target.num_buffers = 0; + draw_set_mapped_so_buffers(lp->draw, 0, 0); + return; + } + + lp->so_target.buffer[i] = res; + lp->so_target.offset[i] = offsets[i]; + lp->so_target.so_count[i] = 0; + + mapped = res->data; + if (offsets[i] >= 0) + map_buffers[i] = ((char*)mapped) + offsets[i]; + else { + /* this is a buffer append */ + assert(!"appending not implemented"); + map_buffers[i] = mapped; + } + } + lp->so_target.num_buffers = num_buffers; + + draw_set_mapped_so_buffers(lp->draw, map_buffers, num_buffers); +} + +void +llvmpipe_init_so_funcs(struct llvmpipe_context *llvmpipe) +{ + llvmpipe->pipe.create_stream_output_state = + llvmpipe_create_stream_output_state; + llvmpipe->pipe.bind_stream_output_state = + llvmpipe_bind_stream_output_state; + llvmpipe->pipe.delete_stream_output_state = + llvmpipe_delete_stream_output_state; + + llvmpipe->pipe.set_stream_output_buffers = + llvmpipe_set_stream_output_buffers; +} diff --git a/src/gallium/drivers/llvmpipe/lp_surface.c b/src/gallium/drivers/llvmpipe/lp_surface.c index 4f409f9b63..f0cbbe8c56 100644 --- a/src/gallium/drivers/llvmpipe/lp_surface.c +++ b/src/gallium/drivers/llvmpipe/lp_surface.c @@ -67,14 +67,14 @@ lp_resource_copy(struct pipe_context *pipe, dst, subdst.face, subdst.level, 0, /* flush_flags */ FALSE, /* read_only */ - FALSE, /* cpu_access */ + TRUE, /* cpu_access */ FALSE); /* do_not_block */ llvmpipe_flush_resource(pipe, src, subsrc.face, subsrc.level, 0, /* flush_flags */ TRUE, /* read_only */ - FALSE, /* cpu_access */ + TRUE, /* cpu_access */ FALSE); /* do_not_block */ /* @@ -106,19 +106,27 @@ lp_resource_copy(struct pipe_context *pipe, unsigned x, y; enum lp_texture_usage usage; - /* XXX for the tiles which are completely contained by the - * dest rectangle, we could set the usage mode to WRITE_ALL. - * Just test for the case of replacing the whole dest region for now. - */ - if (width == dst_tex->base.width0 && height == dst_tex->base.height0) - usage = LP_TEX_USAGE_WRITE_ALL; - else - usage = LP_TEX_USAGE_READ_WRITE; - adjust_to_tile_bounds(dstx, dsty, width, height, &tx, &ty, &tw, &th); for (y = 0; y < th; y += TILE_SIZE) { + boolean contained_y = ty + y >= dsty && + ty + y + TILE_SIZE <= dsty + height ? + TRUE : FALSE; + for (x = 0; x < tw; x += TILE_SIZE) { + boolean contained_x = tx + x >= dstx && + tx + x + TILE_SIZE <= dstx + width ? + TRUE : FALSE; + + /* + * Set the usage mode to WRITE_ALL for the tiles which are + * completely contained by the dest rectangle. + */ + if (contained_y && contained_x) + usage = LP_TEX_USAGE_WRITE_ALL; + else + usage = LP_TEX_USAGE_READ_WRITE; + (void) llvmpipe_get_texture_tile_linear(dst_tex, subdst.face, subdst.level, usage, @@ -153,4 +161,6 @@ void llvmpipe_init_surface_functions(struct llvmpipe_context *lp) { lp->pipe.resource_copy_region = lp_resource_copy; + lp->pipe.clear_render_target = util_clear_render_target; + lp->pipe.clear_depth_stencil = util_clear_depth_stencil; } diff --git a/src/gallium/drivers/nv50/nv50_program.c b/src/gallium/drivers/nv50/nv50_program.c index 97f938e698..8cb1639013 100644 --- a/src/gallium/drivers/nv50/nv50_program.c +++ b/src/gallium/drivers/nv50/nv50_program.c @@ -3924,7 +3924,7 @@ ctor_nv50_pc(struct nv50_pc *pc, struct nv50_program *p) case TGSI_PROPERTY_GS_OUTPUT_PRIM: p->cfg.prim_type = nv50_map_gs_output_prim(data[0]); break; - case TGSI_PROPERTY_GS_MAX_VERTICES: + case TGSI_PROPERTY_GS_MAX_OUTPUT_VERTICES: p->cfg.vert_count = data[0]; break; default: diff --git a/src/gallium/drivers/nv50/nv50_query.c b/src/gallium/drivers/nv50/nv50_query.c index 57b16a355d..53f94820ce 100644 --- a/src/gallium/drivers/nv50/nv50_query.c +++ b/src/gallium/drivers/nv50/nv50_query.c @@ -106,8 +106,9 @@ nv50_query_end(struct pipe_context *pipe, struct pipe_query *pq) static boolean nv50_query_result(struct pipe_context *pipe, struct pipe_query *pq, - boolean wait, uint64_t *result) + boolean wait, void *vresult) { + uint64_t *result = (uint64_t*)vresult; struct nv50_query *q = nv50_query(pq); int ret; diff --git a/src/gallium/drivers/nv50/nv50_surface.c b/src/gallium/drivers/nv50/nv50_surface.c index 814921f764..3e61203adf 100644 --- a/src/gallium/drivers/nv50/nv50_surface.c +++ b/src/gallium/drivers/nv50/nv50_surface.c @@ -115,7 +115,6 @@ nv50_surface_set(struct nv50_screen *screen, struct pipe_surface *ps, int dst) } if (!bo->tile_flags) { - MARK_RING (chan, 9, 2); /* flush on lack of space or relocs */ BEGIN_RING(chan, eng2d, mthd, 2); OUT_RING (chan, format); OUT_RING (chan, 1); @@ -126,7 +125,6 @@ nv50_surface_set(struct nv50_screen *screen, struct pipe_surface *ps, int dst) OUT_RELOCh(chan, bo, ps->offset, flags); OUT_RELOCl(chan, bo, ps->offset, flags); } else { - MARK_RING (chan, 11, 2); /* flush on lack of space or relocs */ BEGIN_RING(chan, eng2d, mthd, 5); OUT_RING (chan, format); OUT_RING (chan, 0); @@ -162,7 +160,9 @@ nv50_surface_do_copy(struct nv50_screen *screen, struct pipe_surface *dst, struct nouveau_grobj *eng2d = screen->eng2d; int ret; - WAIT_RING (chan, 32); + ret = MARK_RING(chan, 2*16 + 32, 4); + if (ret) + return ret; ret = nv50_surface_set(screen, dst, 1); if (ret) @@ -209,7 +209,7 @@ nv50_surface_copy(struct pipe_context *pipe, (nv50_2d_format_faithful(src->format) && nv50_2d_format_faithful(dest->format))); - ps_src = nv50_miptree_surface_new(pipe->screen, dest, subsrc.face, + ps_src = nv50_miptree_surface_new(pipe->screen, src, subsrc.face, subsrc.level, srcz, 0 /* bind flags */); ps_dst = nv50_miptree_surface_new(pipe->screen, dest, subdst.face, subdst.level, destz, 0 /* bindflags */); @@ -241,7 +241,9 @@ nv50_clear_render_target(struct pipe_context *pipe, if (format < 0) return; - WAIT_RING (chan, 32); + ret = MARK_RING (chan, 16 + 32, 2); + if (ret) + return; ret = nv50_surface_set(screen, dst, 1); if (ret) diff --git a/src/gallium/drivers/nvfx/nvfx_query.c b/src/gallium/drivers/nvfx/nvfx_query.c index 1b20b5245d..1dab20c41a 100644 --- a/src/gallium/drivers/nvfx/nvfx_query.c +++ b/src/gallium/drivers/nvfx/nvfx_query.c @@ -96,8 +96,9 @@ nvfx_query_end(struct pipe_context *pipe, struct pipe_query *pq) static boolean nvfx_query_result(struct pipe_context *pipe, struct pipe_query *pq, - boolean wait, uint64_t *result) + boolean wait, void *vresult) { + uint64_t *result = (uint64_t *)vresult; struct nvfx_context *nvfx = nvfx_context(pipe); struct nvfx_query *q = nvfx_query(pq); diff --git a/src/gallium/drivers/nvfx/nvfx_surface.c b/src/gallium/drivers/nvfx/nvfx_surface.c index 44e1af2e6a..a605d2b754 100644 --- a/src/gallium/drivers/nvfx/nvfx_surface.c +++ b/src/gallium/drivers/nvfx/nvfx_surface.c @@ -44,7 +44,7 @@ nvfx_surface_copy(struct pipe_context *pipe, struct nv04_surface_2d *eng2d = nvfx->screen->eng2d; struct pipe_surface *ps_dst, *ps_src; - ps_src = nvfx_miptree_surface_new(pipe->screen, dest, subsrc.face, + ps_src = nvfx_miptree_surface_new(pipe->screen, src, subsrc.face, subsrc.level, srcz, 0 /* bind flags */); ps_dst = nvfx_miptree_surface_new(pipe->screen, dest, subdst.face, subdst.level, destz, 0 /* bindflags */); diff --git a/src/gallium/drivers/r300/Makefile b/src/gallium/drivers/r300/Makefile index 6bb82e5ed0..13152635a6 100644 --- a/src/gallium/drivers/r300/Makefile +++ b/src/gallium/drivers/r300/Makefile @@ -14,12 +14,13 @@ C_SOURCES = \ r300_hyperz.c \ r300_query.c \ r300_render.c \ + r300_render_stencilref.c \ + r300_render_translate.c \ r300_resource.c \ r300_screen.c \ r300_screen_buffer.c \ r300_state.c \ r300_state_derived.c \ - r300_state_invariant.c \ r300_vs.c \ r300_vs_draw.c \ r300_texture.c \ diff --git a/src/gallium/drivers/r300/SConscript b/src/gallium/drivers/r300/SConscript index eb3e1d365e..552ed4e5be 100644 --- a/src/gallium/drivers/r300/SConscript +++ b/src/gallium/drivers/r300/SConscript @@ -24,12 +24,13 @@ r300 = env.ConvenienceLibrary( 'r300_hyperz.c', 'r300_query.c', 'r300_render.c', + 'r300_render_stencilref.c', + 'r300_render_translate.c', 'r300_resource.c', 'r300_screen.c', 'r300_screen_buffer.c', 'r300_state.c', 'r300_state_derived.c', - 'r300_state_invariant.c', 'r300_vs.c', 'r300_vs_draw.c', 'r300_texture.c', diff --git a/src/gallium/drivers/r300/r300_blit.c b/src/gallium/drivers/r300/r300_blit.c index 49ec51fd13..97d53a14f8 100644 --- a/src/gallium/drivers/r300/r300_blit.c +++ b/src/gallium/drivers/r300/r300_blit.c @@ -25,8 +25,23 @@ #include "util/u_format.h" -static void r300_blitter_save_states(struct r300_context* r300) +enum r300_blitter_op /* bitmask */ { + R300_CLEAR = 1, + R300_CLEAR_SURFACE = 2, + R300_COPY = 4 +}; + +static void r300_blitter_begin(struct r300_context* r300, enum r300_blitter_op op) +{ + if (r300->query_current) { + r300->blitter_saved_query = r300->query_current; + r300_stop_query(r300); + } + + /* Yeah we have to save all those states to ensure the blitter operation + * is really transparent. The states will be restored by the blitter once + * copying is done. */ util_blitter_save_blend(r300->blitter, r300->blend_state.state); util_blitter_save_depth_stencil_alpha(r300->blitter, r300->dsa_state.state); util_blitter_save_stencil_ref(r300->blitter, &(r300->stencil_ref)); @@ -34,11 +49,34 @@ static void r300_blitter_save_states(struct r300_context* r300) util_blitter_save_fragment_shader(r300->blitter, r300->fs.state); util_blitter_save_vertex_shader(r300->blitter, r300->vs_state.state); util_blitter_save_viewport(r300->blitter, &r300->viewport); - util_blitter_save_clip(r300->blitter, &r300->clip); + util_blitter_save_clip(r300->blitter, (struct pipe_clip_state*)r300->clip_state.state); util_blitter_save_vertex_elements(r300->blitter, r300->velems); - /* XXX this crashes the driver util_blitter_save_vertex_buffers(r300->blitter, r300->vertex_buffer_count, - r300->vertex_buffer); */ + r300->vertex_buffer); + + if (op & (R300_CLEAR_SURFACE | R300_COPY)) + util_blitter_save_framebuffer(r300->blitter, r300->fb_state.state); + + if (op & R300_COPY) { + struct r300_textures_state* state = + (struct r300_textures_state*)r300->textures_state.state; + + util_blitter_save_fragment_sampler_states( + r300->blitter, state->sampler_state_count, + (void**)state->sampler_states); + + util_blitter_save_fragment_sampler_views( + r300->blitter, state->sampler_view_count, + (struct pipe_sampler_view**)state->sampler_views); + } +} + +static void r300_blitter_end(struct r300_context *r300) +{ + if (r300->blitter_saved_query) { + r300_resume_query(r300, r300->blitter_saved_query); + r300->blitter_saved_query = NULL; + } } /* Clear currently bound buffers. */ @@ -48,24 +86,37 @@ static void r300_clear(struct pipe_context* pipe, double depth, unsigned stencil) { - /* XXX Implement fastfill. + /* My notes about fastfill: + * + * 1) Only the zbuffer is cleared. + * + * 2) The zbuffer must be micro-tiled and whole microtiles must be + * written. If microtiling is disabled, it locks up. * - * If fastfill is enabled, a few facts should be considered: + * 3) There is Z Mask RAM which contains a compressed zbuffer and + * it interacts with fastfill. We should figure out how to use it + * to get more performance. + * This is what we know about the Z Mask: * - * 1) Zbuffer must be micro-tiled and whole microtiles must be - * written. + * Each dword of the Z Mask contains compression information + * for 16 4x4 pixel blocks, that is 2 bits for each block. + * On chips with 2 Z pipes, every other dword maps to a different + * pipe. * - * 2) ZB_DEPTHCLEARVALUE is used to clear a zbuffer and Z Mask must be - * equal to 0. + * 4) ZB_DEPTHCLEARVALUE is used to clear the zbuffer and the Z Mask must + * be equal to 0. (clear the Z Mask RAM with zeros) * - * 3) For 16-bit integer buffering, compression causes a hung with one or + * 5) For 16-bit zbuffer, compression causes a hung with one or * two samples and should not be used. * - * 4) Fastfill must not be used if reading of compressed Z data is disabled + * 6) FORCE_COMPRESSED_STENCIL_VALUE should be enabled for stencil clears + * to avoid needless decompression. + * + * 7) Fastfill must not be used if reading of compressed Z data is disabled * and writing of compressed Z data is enabled (RD/WR_COMP_ENABLE), * i.e. it cannot be used to compress the zbuffer. - * (what the hell does that mean and how does it fit in clearing - * the buffers?) + * + * 8) ZB_CB_CLEAR does not interact with fastfill in any way. * * - Marek */ @@ -74,13 +125,45 @@ static void r300_clear(struct pipe_context* pipe, struct pipe_framebuffer_state* fb = (struct pipe_framebuffer_state*)r300->fb_state.state; - r300_blitter_save_states(r300); - + r300_blitter_begin(r300, R300_CLEAR); util_blitter_clear(r300->blitter, fb->width, fb->height, fb->nr_cbufs, buffers, rgba, depth, stencil); + r300_blitter_end(r300); +} + +/* Clear a region of a color surface to a constant value. */ +static void r300_clear_render_target(struct pipe_context *pipe, + struct pipe_surface *dst, + const float *rgba, + unsigned dstx, unsigned dsty, + unsigned width, unsigned height) +{ + struct r300_context *r300 = r300_context(pipe); + + r300_blitter_begin(r300, R300_CLEAR_SURFACE); + util_blitter_clear_render_target(r300->blitter, dst, rgba, + dstx, dsty, width, height); + r300_blitter_end(r300); +} + +/* Clear a region of a depth stencil surface. */ +static void r300_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) +{ + struct r300_context *r300 = r300_context(pipe); + + r300_blitter_begin(r300, R300_CLEAR_SURFACE); + util_blitter_clear_depth_stencil(r300->blitter, dst, clear_flags, depth, stencil, + dstx, dsty, width, height); + r300_blitter_end(r300); } /* Copy a block of pixels from one surface to another using HW. */ @@ -94,27 +177,12 @@ static void r300_hw_copy_region(struct pipe_context* pipe, unsigned width, unsigned height) { struct r300_context* r300 = r300_context(pipe); - struct r300_textures_state* state = - (struct r300_textures_state*)r300->textures_state.state; - /* Yeah we have to save all those states to ensure this blitter operation - * is really transparent. The states will be restored by the blitter once - * copying is done. */ - r300_blitter_save_states(r300); - util_blitter_save_framebuffer(r300->blitter, r300->fb_state.state); - - util_blitter_save_fragment_sampler_states( - r300->blitter, state->sampler_state_count, - (void**)state->sampler_states); - - util_blitter_save_fragment_sampler_views( - r300->blitter, state->sampler_view_count, - (struct pipe_sampler_view**)state->sampler_views); - - /* Do a copy */ + r300_blitter_begin(r300, R300_COPY); util_blitter_copy_region(r300->blitter, dst, subdst, dstx, dsty, dstz, src, subsrc, srcx, srcy, srcz, width, height, TRUE); + r300_blitter_end(r300); } /* Copy a block of pixels from one surface to another. */ @@ -130,14 +198,6 @@ static void r300_resource_copy_region(struct pipe_context *pipe, enum pipe_format old_format = dst->format; enum pipe_format new_format = old_format; - if (dst->format != src->format) { - debug_printf("r300: Implementation error: Format mismatch in %s\n" - " : src: %s dst: %s\n", __FUNCTION__, - util_format_short_name(src->format), - util_format_short_name(dst->format)); - debug_assert(0); - } - if (!pipe->screen->is_format_supported(pipe->screen, old_format, src->target, src->nr_samples, @@ -188,40 +248,6 @@ static void r300_resource_copy_region(struct pipe_context *pipe, } } -/* Clear a region of a color surface to a constant value. */ -static void r300_clear_render_target(struct pipe_context *pipe, - struct pipe_surface *dst, - const float *rgba, - unsigned dstx, unsigned dsty, - unsigned width, unsigned height) -{ - struct r300_context *r300 = r300_context(pipe); - - r300_blitter_save_states(r300); - util_blitter_save_framebuffer(r300->blitter, r300->fb_state.state); - - util_blitter_clear_render_target(r300->blitter, dst, rgba, - dstx, dsty, width, height); -} - -/* Clear a region of a depth stencil surface. */ -static void r300_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) -{ - struct r300_context *r300 = r300_context(pipe); - - r300_blitter_save_states(r300); - util_blitter_save_framebuffer(r300->blitter, r300->fb_state.state); - - util_blitter_clear_depth_stencil(r300->blitter, dst, clear_flags, depth, stencil, - dstx, dsty, width, height); -} - void r300_init_blit_functions(struct r300_context *r300) { r300->context.clear = r300_clear; diff --git a/src/gallium/drivers/r300/r300_cb.h b/src/gallium/drivers/r300/r300_cb.h new file mode 100644 index 0000000000..61b28330b0 --- /dev/null +++ b/src/gallium/drivers/r300/r300_cb.h @@ -0,0 +1,142 @@ +/* + * Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com> + * Copyright 2010 Marek Olšák <maraeo@gmail.com> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +/** + * This file contains macros for building command buffers in memory. + * + * Use NEW_CB for buffers with a varying size and it will also allocate + * the buffer. + * Use BEGIN_CB for arrays with a static size. + * + * Example: + * + * uint32_t cb[3]; + * CB_LOCALS; + * + * BEGIN_CB(cb, 3); + * OUT_CB_REG_SEQ(R500_RB3D_CONSTANT_COLOR_AR, 2); + * OUT_CB(blend_color_red_alpha); + * OUT_CB(blend_color_green_blue); + * END_CB; + * + * And later: + * + * CS_LOCALS; + * WRITE_CS_TABLE(cb, 3); + * + * Or using a little slower variant: + * + * CS_LOCALS; + * BEGIN_CS(cb, 3); + * OUT_CS_TABLE(cb, 3); + * END_CS; + */ + +#ifndef R300_CB_H +#define R300_CB_H + +#include "r300_reg.h" + +/* Yes, I know macros are ugly. However, they are much prettier than the code + * that they neatly hide away, and don't have the cost of function setup, so + * we're going to use them. */ + +#ifdef DEBUG +#define CB_DEBUG(x) x +#else +#define CB_DEBUG(x) +#endif + + +/** + * Command buffer setup. + */ + +#define CB_LOCALS \ + CB_DEBUG(int cs_count = 0;) \ + uint32_t *cs_ptr = NULL; \ + CB_DEBUG((void) cs_count;) (void) cs_ptr; + +#define NEW_CB(ptr, size) do { \ + assert(sizeof(*ptr) == sizeof(uint32_t)); \ + cs_ptr = (ptr) = (uint32_t*)malloc((size) * sizeof(uint32_t)); \ + CB_DEBUG(cs_count = size;) \ +} while (0) + +#define BEGIN_CB(ptr, size) do { \ + assert(sizeof(*ptr) == sizeof(uint32_t)); \ + cs_ptr = ptr; \ + CB_DEBUG(cs_count = size;) \ +} while (0) + +#define BEGIN_CS_AS_CB(r300, size) \ + BEGIN_CB(r300->rws->get_cs_pointer(r300->rws, size), size) + +#define END_CB do { \ + CB_DEBUG(if (cs_count != 0) \ + debug_printf("r300: Warning: cs_count off by %d at (%s, %s:%i)\n", \ + cs_count, __FUNCTION__, __FILE__, __LINE__);) \ +} while (0) + + +/** + * Storing pure DWORDs. + */ + +#define OUT_CB(value) do { \ + *cs_ptr = (value); \ + cs_ptr++; \ + CB_DEBUG(cs_count--;) \ +} while (0) + +#define OUT_CB_TABLE(values, count) do { \ + memcpy(cs_ptr, values, count * sizeof(uint32_t)); \ + cs_ptr += count; \ + CB_DEBUG(cs_count -= count;) \ +} while (0) + +#define OUT_CB_32F(value) \ + OUT_CB(fui(value)); + +#define OUT_CB_REG(register, value) do { \ + assert(register); \ + OUT_CB(CP_PACKET0(register, 0)); \ + OUT_CB(value); \ +} while (0) + +/* Note: This expects count to be the number of registers, + * not the actual packet0 count! */ +#define OUT_CB_REG_SEQ(register, count) do { \ + assert(register); \ + OUT_CB(CP_PACKET0(register, (count) - 1)); \ +} while (0) + +#define OUT_CB_ONE_REG(register, count) do { \ + assert(register); \ + OUT_CB(CP_PACKET0(register, (count) - 1) | RADEON_ONE_REG_WR); \ +} while (0) + +#define OUT_CB_PKT3(op, count) \ + OUT_CB(CP_PACKET3(op, count)) + +#endif /* R300_CB_H */ diff --git a/src/gallium/drivers/r300/r300_chipset.c b/src/gallium/drivers/r300/r300_chipset.c index e6dca66d4a..21f3b9d261 100644 --- a/src/gallium/drivers/r300/r300_chipset.c +++ b/src/gallium/drivers/r300/r300_chipset.c @@ -36,6 +36,7 @@ void r300_parse_chipset(struct r300_capabilities* caps) caps->num_vert_fpus = 2; caps->num_tex_units = 16; caps->has_tcl = debug_get_bool_option("RADEON_NO_TCL", FALSE) ? FALSE : TRUE; + caps->has_hiz = TRUE; caps->is_r400 = FALSE; caps->is_r500 = FALSE; caps->high_second_pipe = FALSE; @@ -76,6 +77,7 @@ void r300_parse_chipset(struct r300_capabilities* caps) case 0x4E54: case 0x4E56: caps->family = CHIP_FAMILY_RV350; + caps->has_hiz = FALSE; caps->high_second_pipe = TRUE; break; @@ -106,6 +108,7 @@ void r300_parse_chipset(struct r300_capabilities* caps) case 0x5B64: case 0x5B65: caps->family = CHIP_FAMILY_RV370; + caps->has_hiz = FALSE; caps->high_second_pipe = TRUE; break; @@ -201,24 +204,28 @@ void r300_parse_chipset(struct r300_capabilities* caps) case 0x5954: case 0x5955: caps->family = CHIP_FAMILY_RS480; + caps->has_hiz = FALSE; caps->has_tcl = FALSE; break; case 0x5974: case 0x5975: caps->family = CHIP_FAMILY_RS482; + caps->has_hiz = FALSE; caps->has_tcl = FALSE; break; case 0x5A41: case 0x5A42: caps->family = CHIP_FAMILY_RS400; + caps->has_hiz = FALSE; caps->has_tcl = FALSE; break; case 0x5A61: case 0x5A62: caps->family = CHIP_FAMILY_RC410; + caps->has_hiz = FALSE; caps->has_tcl = FALSE; break; diff --git a/src/gallium/drivers/r300/r300_chipset.h b/src/gallium/drivers/r300/r300_chipset.h index ab649c3857..65750f54e7 100644 --- a/src/gallium/drivers/r300/r300_chipset.h +++ b/src/gallium/drivers/r300/r300_chipset.h @@ -42,6 +42,8 @@ struct r300_capabilities { unsigned num_tex_units; /* Whether or not TCL is physically present */ boolean has_tcl; + /* Some chipsets do not have HiZ RAM. */ + boolean has_hiz; /* Whether or not this is RV350 or newer, including all r400 and r500 * chipsets. The differences compared to the oldest r300 chips are: * - Blend LTE/GTE thresholds diff --git a/src/gallium/drivers/r300/r300_context.c b/src/gallium/drivers/r300/r300_context.c index 88ce186798..df2874d5bf 100644 --- a/src/gallium/drivers/r300/r300_context.c +++ b/src/gallium/drivers/r300/r300_context.c @@ -23,22 +23,64 @@ #include "draw/draw_context.h" #include "util/u_memory.h" +#include "util/u_sampler.h" #include "util/u_simple_list.h" #include "util/u_upload_mgr.h" +#include "r300_cb.h" #include "r300_context.h" #include "r300_emit.h" #include "r300_screen.h" #include "r300_screen_buffer.h" -#include "r300_state_invariant.h" #include "r300_winsys.h" #include <inttypes.h> +static void r300_release_referenced_objects(struct r300_context *r300) +{ + struct pipe_framebuffer_state *fb = + (struct pipe_framebuffer_state*)r300->fb_state.state; + struct r300_textures_state *textures = + (struct r300_textures_state*)r300->textures_state.state; + struct r300_query *query, *temp; + unsigned i; + + /* Framebuffer state. */ + for (i = 0; i < fb->nr_cbufs; i++) { + pipe_surface_reference(&fb->cbufs[i], NULL); + } + pipe_surface_reference(&fb->zsbuf, NULL); + + /* Textures. */ + for (i = 0; i < textures->sampler_view_count; i++) + pipe_sampler_view_reference( + (struct pipe_sampler_view**)&textures->sampler_views[i], NULL); + + /* The special dummy texture for texkill. */ + if (r300->texkill_sampler) { + pipe_sampler_view_reference( + (struct pipe_sampler_view**)&r300->texkill_sampler, + NULL); + } + + /* The SWTCL VBO. */ + pipe_resource_reference(&r300->vbo, NULL); + + /* Vertex buffers. */ + for (i = 0; i < r300->vertex_buffer_count; i++) { + pipe_resource_reference(&r300->vertex_buffer[i].buffer, NULL); + } + + /* If there are any queries pending or not destroyed, remove them now. */ + foreach_s(query, temp, &r300->query_list) { + remove_from_list(query); + FREE(query); + } +} + static void r300_destroy_context(struct pipe_context* context) { struct r300_context* r300 = r300_context(context); - struct r300_query* query, * temp; struct r300_atom *atom; util_blitter_destroy(r300->blitter); @@ -54,24 +96,24 @@ static void r300_destroy_context(struct pipe_context* context) } } - /* Free the OQ BO. */ - context->screen->resource_destroy(context->screen, r300->oqbo); - - /* If there are any queries pending or not destroyed, remove them now. */ - foreach_s(query, temp, &r300->query_list) { - remove_from_list(query); - FREE(query); - } - u_upload_destroy(r300->upload_vb); u_upload_destroy(r300->upload_ib); + translate_cache_destroy(r300->tran.translate_cache); + + r300_release_referenced_objects(r300); + + FREE(r300->aa_state.state); FREE(r300->blend_color_state.state); FREE(r300->clip_state.state); FREE(r300->fb_state.state); + FREE(r300->gpu_flush.state); + FREE(r300->hyperz_state.state); + FREE(r300->invariant_state.state); FREE(r300->rs_block_state.state); FREE(r300->scissor_state.state); FREE(r300->textures_state.state); + FREE(r300->vap_invariant_state.state); FREE(r300->viewport_state.state); FREE(r300->ztop_state.state); FREE(r300->fs_constants.state); @@ -99,8 +141,10 @@ static void r300_flush_cb(void *data) static void r300_setup_atoms(struct r300_context* r300) { + boolean is_rv350 = r300->screen->caps.is_rv350; boolean is_r500 = r300->screen->caps.is_r500; boolean has_tcl = r300->screen->caps.has_tcl; + boolean drm_2_3_0 = r300->rws->get_value(r300->rws, R300_VID_DRM_2_3_0); /* Create the actual atom list. * @@ -108,44 +152,75 @@ static void r300_setup_atoms(struct r300_context* r300) * can affect performance and conformance if not handled with care. * * Some atoms never change size, others change every emit - those have - * the size of 0 here. */ + * the size of 0 here. + * + * NOTE: The framebuffer state is split into these atoms: + * - gpu_flush (unpipelined regs) + * - aa_state (unpipelined regs) + * - fb_state (unpipelined regs) + * - hyperz_state (unpipelined regs followed by pipelined ones) + * - fb_state_pipelined (pipelined regs) + * The motivation behind this is to be able to emit a strict + * subset of the regs, and to have reasonable register ordering. */ make_empty_list(&r300->atom_list); - R300_INIT_ATOM(invariant_state, 71); - R300_INIT_ATOM(query_start, 4); + /* SC, GB (unpipelined), RB3D (unpipelined), ZB (unpipelined). */ + R300_INIT_ATOM(gpu_flush, 9); + R300_INIT_ATOM(aa_state, 4); + R300_INIT_ATOM(fb_state, 0); + /* ZB (unpipelined), SC. */ + R300_INIT_ATOM(hyperz_state, 6); R300_INIT_ATOM(ztop_state, 2); + /* ZB, FG. */ + R300_INIT_ATOM(dsa_state, is_r500 ? 8 : 6); + /* RB3D. */ R300_INIT_ATOM(blend_state, 8); R300_INIT_ATOM(blend_color_state, is_r500 ? 3 : 2); - R300_INIT_ATOM(clip_state, has_tcl ? 5 + (6 * 4) : 2); - R300_INIT_ATOM(dsa_state, is_r500 ? 8 : 6); - R300_INIT_ATOM(fb_state, 0); - R300_INIT_ATOM(rs_state, 0); + /* SC. */ R300_INIT_ATOM(scissor_state, 3); + /* GB, FG, GA, SU, SC, RB3D. */ + R300_INIT_ATOM(invariant_state, 16 + (is_rv350 ? 4 : 0)); + /* VAP. */ R300_INIT_ATOM(viewport_state, 9); - R300_INIT_ATOM(rs_block_state, 0); - R300_INIT_ATOM(vertex_stream_state, 0); R300_INIT_ATOM(pvs_flush, 2); + R300_INIT_ATOM(vap_invariant_state, 9); + R300_INIT_ATOM(vertex_stream_state, 0); R300_INIT_ATOM(vs_state, 0); R300_INIT_ATOM(vs_constants, 0); - R300_INIT_ATOM(texture_cache_inval, 2); - R300_INIT_ATOM(textures_state, 0); + R300_INIT_ATOM(clip_state, has_tcl ? 5 + (6 * 4) : 2); + /* VAP, RS, GA, GB, SU, SC. */ + R300_INIT_ATOM(rs_block_state, 0); + R300_INIT_ATOM(rs_state, 0); + /* SC, US. */ + R300_INIT_ATOM(fb_state_pipelined, 5 + (drm_2_3_0 ? 3 : 0)); + /* US. */ R300_INIT_ATOM(fs, 0); R300_INIT_ATOM(fs_rc_constant_state, 0); R300_INIT_ATOM(fs_constants, 0); + /* TX. */ + R300_INIT_ATOM(texture_cache_inval, 2); + R300_INIT_ATOM(textures_state, 0); + /* ZB (unpipelined), SU. */ + R300_INIT_ATOM(query_start, 4); /* Replace emission functions for r500. */ - if (r300->screen->caps.is_r500) { + if (is_r500) { r300->fs.emit = r500_emit_fs; r300->fs_rc_constant_state.emit = r500_emit_fs_rc_constant_state; r300->fs_constants.emit = r500_emit_fs_constants; } /* Some non-CSO atoms need explicit space to store the state locally. */ + r300->aa_state.state = CALLOC_STRUCT(r300_aa_state); r300->blend_color_state.state = CALLOC_STRUCT(r300_blend_color_state); - r300->clip_state.state = CALLOC_STRUCT(pipe_clip_state); + r300->clip_state.state = CALLOC_STRUCT(r300_clip_state); r300->fb_state.state = CALLOC_STRUCT(pipe_framebuffer_state); + r300->gpu_flush.state = CALLOC_STRUCT(pipe_framebuffer_state); + r300->hyperz_state.state = CALLOC_STRUCT(r300_hyperz_state); + r300->invariant_state.state = CALLOC_STRUCT(r300_invariant_state); r300->rs_block_state.state = CALLOC_STRUCT(r300_rs_block); r300->scissor_state.state = CALLOC_STRUCT(pipe_scissor_state); r300->textures_state.state = CALLOC_STRUCT(r300_textures_state); + r300->vap_invariant_state.state = CALLOC_STRUCT(r300_vap_invariant_state); r300->viewport_state.state = CALLOC_STRUCT(r300_viewport_state); r300->ztop_state.state = CALLOC_STRUCT(r300_ztop_state); r300->fs_constants.state = CALLOC_STRUCT(r300_constant_buffer); @@ -155,11 +230,112 @@ static void r300_setup_atoms(struct r300_context* r300) } /* Some non-CSO atoms don't use the state pointer. */ - r300->invariant_state.allow_null_state = TRUE; + r300->fb_state_pipelined.allow_null_state = TRUE; r300->fs_rc_constant_state.allow_null_state = TRUE; r300->pvs_flush.allow_null_state = TRUE; r300->query_start.allow_null_state = TRUE; r300->texture_cache_inval.allow_null_state = TRUE; + + /* Some states must be marked dirty here to properly set up + * hardware in the first command stream. */ + r300->invariant_state.dirty = TRUE; + r300->pvs_flush.dirty = TRUE; + r300->vap_invariant_state.dirty = TRUE; + r300->texture_cache_inval.dirty = TRUE; + r300->textures_state.dirty = TRUE; +} + +/* Not every state tracker calls every driver function before the first draw + * call and we must initialize the command buffers somehow. */ +static void r300_init_states(struct pipe_context *pipe) +{ + struct r300_context *r300 = r300_context(pipe); + struct pipe_blend_color bc = {{0}}; + struct pipe_clip_state cs = {{{0}}}; + struct pipe_scissor_state ss = {0}; + struct r300_clip_state *clip = + (struct r300_clip_state*)r300->clip_state.state; + struct r300_gpu_flush *gpuflush = + (struct r300_gpu_flush*)r300->gpu_flush.state; + struct r300_vap_invariant_state *vap_invariant = + (struct r300_vap_invariant_state*)r300->vap_invariant_state.state; + struct r300_invariant_state *invariant = + (struct r300_invariant_state*)r300->invariant_state.state; + struct r300_hyperz_state *hyperz = + (struct r300_hyperz_state*)r300->hyperz_state.state; + CB_LOCALS; + + pipe->set_blend_color(pipe, &bc); + pipe->set_scissor_state(pipe, &ss); + + /* Initialize the clip state. */ + if (r300_context(pipe)->screen->caps.has_tcl) { + pipe->set_clip_state(pipe, &cs); + } else { + BEGIN_CB(clip->cb, 2); + OUT_CB_REG(R300_VAP_CLIP_CNTL, R300_CLIP_DISABLE); + END_CB; + } + + /* Initialize the GPU flush. */ + { + BEGIN_CB(gpuflush->cb_flush_clean, 6); + + /* Flush and free renderbuffer caches. */ + OUT_CB_REG(R300_RB3D_DSTCACHE_CTLSTAT, + R300_RB3D_DSTCACHE_CTLSTAT_DC_FREE_FREE_3D_TAGS | + R300_RB3D_DSTCACHE_CTLSTAT_DC_FLUSH_FLUSH_DIRTY_3D); + OUT_CB_REG(R300_ZB_ZCACHE_CTLSTAT, + R300_ZB_ZCACHE_CTLSTAT_ZC_FLUSH_FLUSH_AND_FREE | + R300_ZB_ZCACHE_CTLSTAT_ZC_FREE_FREE); + + /* Wait until the GPU is idle. + * This fixes random pixels sometimes appearing probably caused + * by incomplete rendering. */ + OUT_CB_REG(RADEON_WAIT_UNTIL, RADEON_WAIT_3D_IDLECLEAN); + END_CB; + } + + /* Initialize the VAP invariant state. */ + { + BEGIN_CB(vap_invariant->cb, 9); + OUT_CB_REG(VAP_PVS_VTX_TIMEOUT_REG, 0xffff); + OUT_CB_REG_SEQ(R300_VAP_GB_VERT_CLIP_ADJ, 4); + OUT_CB_32F(1.0); + OUT_CB_32F(1.0); + OUT_CB_32F(1.0); + OUT_CB_32F(1.0); + OUT_CB_REG(R300_VAP_PSC_SGN_NORM_CNTL, R300_SGN_NORM_NO_ZERO); + END_CB; + } + + /* Initialize the invariant state. */ + { + BEGIN_CB(invariant->cb, r300->invariant_state.size); + OUT_CB_REG(R300_GB_SELECT, 0); + OUT_CB_REG(R300_FG_FOG_BLEND, 0); + OUT_CB_REG(R300_GA_ROUND_MODE, 1); + OUT_CB_REG(R300_GA_OFFSET, 0); + OUT_CB_REG(R300_SU_TEX_WRAP, 0); + OUT_CB_REG(R300_SU_DEPTH_SCALE, 0x4B7FFFFF); + OUT_CB_REG(R300_SU_DEPTH_OFFSET, 0); + OUT_CB_REG(R300_SC_EDGERULE, 0x2DA49525); + + if (r300->screen->caps.is_rv350) { + OUT_CB_REG(R500_RB3D_DISCARD_SRC_PIXEL_LTE_THRESHOLD, 0x01010101); + OUT_CB_REG(R500_RB3D_DISCARD_SRC_PIXEL_GTE_THRESHOLD, 0xFEFEFEFE); + } + END_CB; + } + + /* Initialize the hyperz state. */ + { + BEGIN_CB(&hyperz->cb_begin, 6); + OUT_CB_REG(R300_ZB_BW_CNTL, 0); + OUT_CB_REG(R300_ZB_DEPTHCLEARVALUE, 0); + OUT_CB_REG(R300_SC_HYPERZ, 0x1C); + END_CB; + } } struct pipe_context* r300_create_context(struct pipe_screen* screen, @@ -195,9 +371,6 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen, r300_setup_atoms(r300); - /* Open up the OQ BO. */ - r300->oqbo = pipe_buffer_create(screen, - R300_BIND_OQBO, 4096); make_empty_list(&r300->query_list); r300_init_blit_functions(r300); @@ -207,8 +380,6 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen, r300_init_state_functions(r300); r300_init_resource_functions(r300); - r300->invariant_state.dirty = TRUE; - rws->set_flush_cb(r300->rws, r300_flush_cb, r300); r300->dirty_hw++; @@ -227,6 +398,34 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen, if (r300->upload_vb == NULL) goto no_upload_vb; + r300->tran.translate_cache = translate_cache_create(); + + r300_init_states(&r300->context); + + /* The KIL opcode needs the first texture unit to be enabled + * on r3xx-r4xx. In order to calm down the CS checker, we bind this + * dummy texture there. */ + if (!r300->screen->caps.is_r500) { + struct pipe_resource *tex; + struct pipe_resource rtempl = {{0}}; + struct pipe_sampler_view vtempl = {{0}}; + + rtempl.target = PIPE_TEXTURE_2D; + rtempl.format = PIPE_FORMAT_I8_UNORM; + rtempl.bind = PIPE_BIND_SAMPLER_VIEW; + rtempl.width0 = 1; + rtempl.height0 = 1; + rtempl.depth0 = 1; + tex = screen->resource_create(screen, &rtempl); + + u_sampler_view_default_template(&vtempl, tex, tex->format); + + r300->texkill_sampler = (struct r300_sampler_view*) + r300->context.create_sampler_view(&r300->context, tex, &vtempl); + + pipe_resource_reference(&tex, NULL); + } + return &r300->context; no_upload_ib: @@ -238,10 +437,7 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen, boolean r300_check_cs(struct r300_context *r300, unsigned size) { - struct r300_cs_info cs_info; - - r300->rws->get_cs_info(r300->rws, &cs_info); - return size <= cs_info.free; + return size <= r300->rws->get_cs_free_dwords(r300->rws); } void r300_finish(struct r300_context *r300) diff --git a/src/gallium/drivers/r300/r300_context.h b/src/gallium/drivers/r300/r300_context.h index 48ec52d26c..50dcd0fc67 100644 --- a/src/gallium/drivers/r300/r300_context.h +++ b/src/gallium/drivers/r300/r300_context.h @@ -31,6 +31,8 @@ #include "util/u_inlines.h" #include "util/u_transfer.h" +#include "translate/translate_cache.h" + #include "r300_defines.h" #include "r300_screen.h" @@ -59,68 +61,83 @@ struct r300_atom { boolean allow_null_state; }; +struct r300_aa_state { + struct r300_surface *dest; + + uint32_t aa_config; + uint32_t aaresolve_ctl; +}; + struct r300_blend_state { - uint32_t blend_control; /* R300_RB3D_CBLEND: 0x4e04 */ - uint32_t alpha_blend_control; /* R300_RB3D_ABLEND: 0x4e08 */ - uint32_t color_channel_mask; /* R300_RB3D_COLOR_CHANNEL_MASK: 0x4e0c */ - uint32_t rop; /* R300_RB3D_ROPCNTL: 0x4e18 */ - uint32_t dither; /* R300_RB3D_DITHER_CTL: 0x4e50 */ + uint32_t cb[8]; + uint32_t cb_no_readwrite[8]; }; struct r300_blend_color_state { - /* RV515 and earlier */ - uint32_t blend_color; /* R300_RB3D_BLEND_COLOR: 0x4e10 */ - /* R520 and newer */ - uint32_t blend_color_red_alpha; /* R500_RB3D_CONSTANT_COLOR_AR: 0x4ef8 */ - uint32_t blend_color_green_blue; /* R500_RB3D_CONSTANT_COLOR_GB: 0x4efc */ + uint32_t cb[3]; +}; + +struct r300_clip_state { + struct pipe_clip_state clip; + + uint32_t cb[29]; }; struct r300_dsa_state { + struct pipe_depth_stencil_alpha_state dsa; + + /* This is actually a command buffer with named dwords. */ + uint32_t cb_begin; uint32_t alpha_function; /* R300_FG_ALPHA_FUNC: 0x4bd4 */ - uint32_t alpha_reference; /* R500_FG_ALPHA_VALUE: 0x4be0 */ + uint32_t cb_reg_seq; uint32_t z_buffer_control; /* R300_ZB_CNTL: 0x4f00 */ uint32_t z_stencil_control; /* R300_ZB_ZSTENCILCNTL: 0x4f04 */ uint32_t stencil_ref_mask; /* R300_ZB_STENCILREFMASK: 0x4f08 */ + uint32_t cb_reg; uint32_t stencil_ref_bf; /* R500_ZB_STENCILREFMASK_BF: 0x4fd4 */ + /* The second command buffer disables zbuffer reads and writes. */ + uint32_t cb_no_readwrite[8]; + /* Whether a two-sided stencil is enabled. */ boolean two_sided; /* Whether a fallback should be used for a two-sided stencil ref value. */ boolean two_sided_stencil_ref; }; +struct r300_hyperz_state { + /* This is actually a command buffer with named dwords. */ + uint32_t cb_begin; + uint32_t zb_bw_cntl; /* R300_ZB_BW_CNTL */ + uint32_t cb_reg1; + uint32_t zb_depthclearvalue; /* R300_ZB_DEPTHCLEARVALUE */ + uint32_t cb_reg2; + uint32_t sc_hyperz; /* R300_SC_HYPERZ */ +}; + +struct r300_gpu_flush { + uint32_t cb_flush_clean[6]; +}; + struct r300_rs_state { /* Original rasterizer state. */ struct pipe_rasterizer_state rs; /* Draw-specific rasterizer state. */ struct pipe_rasterizer_state rs_draw; - uint32_t vap_control_status; /* R300_VAP_CNTL_STATUS: 0x2140 */ - uint32_t antialiasing_config; /* R300_GB_AA_CONFIG: 0x4020 */ - uint32_t point_size; /* R300_GA_POINT_SIZE: 0x421c */ - uint32_t point_minmax; /* R300_GA_POINT_MINMAX: 0x4230 */ - uint32_t line_control; /* R300_GA_LINE_CNTL: 0x4234 */ - float depth_scale; /* R300_SU_POLY_OFFSET_FRONT_SCALE: 0x42a4 */ - /* R300_SU_POLY_OFFSET_BACK_SCALE: 0x42ac */ - float depth_offset; /* R300_SU_POLY_OFFSET_FRONT_OFFSET: 0x42a8 */ - /* R300_SU_POLY_OFFSET_BACK_OFFSET: 0x42b0 */ - uint32_t polygon_offset_enable; /* R300_SU_POLY_OFFSET_ENABLE: 0x42b4 */ - uint32_t cull_mode; /* R300_SU_CULL_MODE: 0x42b8 */ - uint32_t line_stipple_config; /* R300_GA_LINE_STIPPLE_CONFIG: 0x4328 */ - uint32_t line_stipple_value; /* R300_GA_LINE_STIPPLE_VALUE: 0x4260 */ + /* Command buffers. */ + uint32_t cb_main[25]; + uint32_t cb_poly_offset_zb16[5]; + uint32_t cb_poly_offset_zb24[5]; + + /* The index to cb_main where the cull_mode register value resides. */ + unsigned cull_mode_index; + + /* Whether polygon offset is enabled. */ + boolean polygon_offset_enable; + + /* This is emitted in the draw function. */ uint32_t color_control; /* R300_GA_COLOR_CONTROL: 0x4278 */ - uint32_t polygon_mode; /* R300_GA_POLY_MODE: 0x4288 */ - uint32_t clip_rule; /* R300_SC_CLIP_RULE: 0x43D0 */ - - /* Specifies top of Raster pipe specific enable controls, - * i.e. texture coordinates stuffing for points, lines, triangles */ - uint32_t stuffing_enable; /* R300_GB_ENABLE: 0x4008 */ - - /* Point sprites texture coordinates, 0: lower left, 1: upper right */ - float point_texcoord_left; /* R300_GA_POINT_S0: 0x4200 */ - float point_texcoord_bottom; /* R300_GA_POINT_T0: 0x4204 */ - float point_texcoord_right; /* R300_GA_POINT_S1: 0x4208 */ - float point_texcoord_top; /* R300_GA_POINT_T1: 0x420c */ }; struct r300_rs_block { @@ -163,16 +180,14 @@ struct r300_sampler_view { /* Copy of r300_texture::texture_format_state with format-specific bits * added. */ struct r300_texture_format_state format; + + /* The texture cache region for this texture. */ + uint32_t texcache_region; }; struct r300_texture_fb_state { - /* Colorbuffer. */ - uint32_t colorpitch[R300_MAX_TEXTURE_LEVELS]; /* R300_RB3D_COLORPITCH[0-3]*/ - uint32_t us_out_fmt; /* R300_US_OUT_FMT[0-3] */ - - /* Zbuffer. */ - uint32_t depthpitch[R300_MAX_TEXTURE_LEVELS]; /* R300_RB3D_DEPTHPITCH */ - uint32_t zb_format; /* R300_ZB_FORMAT */ + uint32_t pitch[R300_MAX_TEXTURE_LEVELS]; /* COLORPITCH or DEPTHPITCH. */ + uint32_t format; /* US_OUT_FMT or R300_ZB_FORMAT */ }; struct r300_texture_sampler_state { @@ -205,6 +220,14 @@ struct r300_vertex_stream_state { unsigned count; }; +struct r300_invariant_state { + uint32_t cb[20]; +}; + +struct r300_vap_invariant_state { + uint32_t cb[9]; +}; + struct r300_viewport_state { float xscale; /* R300_VAP_VPORT_XSCALE: 0x2098 */ float xoffset; /* R300_VAP_VPORT_XOFFSET: 0x209c */ @@ -224,7 +247,7 @@ struct r300_ztop_state { struct r300_constant_buffer { /* Buffer of constants */ - float constants[256][4]; + uint32_t constants[256][4]; /* Total number of constants */ unsigned count; }; @@ -239,14 +262,23 @@ struct r300_constant_buffer { struct r300_query { /* The kind of query. Currently only OQ is supported. */ unsigned type; - /* The current count of this query. Required to be at least 32 bits. */ - unsigned int count; - /* The offset of this query into the query buffer, in bytes. */ - unsigned offset; + /* The number of pipes where query results are stored. */ + unsigned num_pipes; + /* How many results have been written, in dwords. It's incremented + * after end_query and flush. */ + unsigned num_results; /* if we've flushed the query */ boolean flushed; /* if begin has been emitted */ boolean begin_emitted; + + /* The buffer where query results are stored. */ + struct r300_winsys_buffer *buffer; + /* The size of the buffer. */ + unsigned buffer_size; + /* The domain of the buffer. */ + enum r300_buffer_domain domain; + /* Linked list members. */ struct r300_query* prev; struct r300_query* next; @@ -268,6 +300,19 @@ struct r300_fence { boolean signalled; }; +struct r300_surface { + struct pipe_surface base; + + /* Winsys buffer backing the texture. */ + struct r300_winsys_buffer *buffer; + + enum r300_buffer_domain domain; + + uint32_t offset; + uint32_t pitch; /* COLORPITCH or DEPTHPITCH. */ + uint32_t format; /* US_OUT_FMT or R300_ZB_FORMAT. */ +}; + struct r300_texture { /* Parent class */ struct u_resource b; @@ -326,9 +371,34 @@ struct r300_vertex_element_state { unsigned count; struct pipe_vertex_element velem[PIPE_MAX_ATTRIBS]; + /* If (velem[i].src_format != hw_format[i]), the vertex buffer + * referenced by this vertex element cannot be used for rendering and + * its vertex data must be translated to hw_format[i]. */ + enum pipe_format hw_format[PIPE_MAX_ATTRIBS]; + unsigned hw_format_size[PIPE_MAX_ATTRIBS]; + + /* The size of the vertex, in dwords. */ + unsigned vertex_size_dwords; + + /* This might mean two things: + * - src_format != hw_format, as discussed above. + * - src_offset % 4 != 0. */ + boolean incompatible_layout; + struct r300_vertex_stream_state vertex_stream; }; +struct r300_translate_context { + /* Translate cache for incompatible vertex offset/stride/format fallback. */ + struct translate_cache *translate_cache; + + /* The vertex buffer slot containing the translated buffer. */ + unsigned vb_slot; + + /* Saved and new vertex element state. */ + void *saved_velems, *new_velems; +}; + struct r300_context { /* Parent class */ struct pipe_context context; @@ -343,21 +413,30 @@ struct r300_context { struct blitter_context* blitter; /* Stencil two-sided reference value fallback. */ struct r300_stencilref_context *stencilref_fallback; + /* For translating vertex buffers having incompatible vertex layout. */ + struct r300_translate_context tran; /* Vertex buffer for rendering. */ struct pipe_resource* vbo; + /* The KIL opcode needs the first texture unit to be enabled + * on r3xx-r4xx. In order to calm down the CS checker, we bind this + * dummy texture there. */ + struct r300_sampler_view *texkill_sampler; /* Offset into the VBO. */ size_t vbo_offset; - /* Occlusion query buffer. */ - struct pipe_resource* oqbo; - /* Query list. */ + /* The currently active query. */ struct r300_query *query_current; + /* The saved query for blitter operations. */ + struct r300_query *blitter_saved_query; + /* Query list. */ struct r300_query query_list; /* Various CSO state objects. */ /* Beginning of atom list. */ struct r300_atom atom_list; + /* Anti-aliasing (MSAA) state. */ + struct r300_atom aa_state; /* Blend state. */ struct r300_atom blend_state; /* Blend color state. */ @@ -374,6 +453,10 @@ struct r300_context { struct r300_atom fs_constants; /* Framebuffer state. */ struct r300_atom fb_state; + /* Framebuffer state (pipelined regs). */ + struct r300_atom fb_state_pipelined; + /* HyperZ state (various SC/ZB bits). */ + struct r300_atom hyperz_state; /* Occlusion query. */ struct r300_atom query_start; /* Rasterizer state. */ @@ -396,8 +479,12 @@ struct r300_context { struct r300_atom ztop_state; /* PVS flush. */ struct r300_atom pvs_flush; + /* VAP invariant state. */ + struct r300_atom vap_invariant_state; /* Texture cache invalidate. */ struct r300_atom texture_cache_inval; + /* GPU flush. */ + struct r300_atom gpu_flush; /* Invariant state. This must be emitted to get the engine started. */ struct r300_atom invariant_state; @@ -414,9 +501,6 @@ struct r300_context { struct vertex_info vertex_info; struct pipe_stencil_ref stencil_ref; - - struct pipe_clip_state clip; - struct pipe_viewport_state viewport; /* Stream locations for SWTCL. */ @@ -434,6 +518,8 @@ struct r300_context { int sprite_coord_enable; /* Whether two-sided color selection is enabled (AKA light_twoside). */ boolean two_sided_color; + /* Incompatible vertex buffer layout? (misaligned stride or buffer_offset) */ + boolean incompatible_vb_layout; /* upload managers */ struct u_upload_mgr *upload_vb; @@ -449,6 +535,11 @@ static INLINE struct r300_query* r300_query(struct pipe_query* q) return (struct r300_query*)q; } +static INLINE struct r300_surface* r300_surface(struct pipe_surface* surf) +{ + return (struct r300_surface*)surf; +} + static INLINE struct r300_texture* r300_texture(struct pipe_resource* tex) { return (struct r300_texture*)tex; @@ -467,6 +558,9 @@ static INLINE struct r300_fragment_shader *r300_fs(struct r300_context *r300) struct pipe_context* r300_create_context(struct pipe_screen* screen, void *priv); +boolean r300_check_cs(struct r300_context *r300, unsigned size); +void r300_finish(struct r300_context *r300); + /* Context initialization. */ struct draw_stage* r300_draw_stage(struct r300_context* r300); void r300_init_blit_functions(struct r300_context *r300); @@ -476,10 +570,29 @@ void r300_init_render_functions(struct r300_context *r300); void r300_init_state_functions(struct r300_context* r300); void r300_init_resource_functions(struct r300_context* r300); -boolean r300_check_cs(struct r300_context *r300, unsigned size); -void r300_finish(struct r300_context *r300); +/* r300_query.c */ +void r300_resume_query(struct r300_context *r300, + struct r300_query *query); +void r300_stop_query(struct r300_context *r300); + +/* r300_render_translate.c */ +void r300_begin_vertex_translate(struct r300_context *r300); +void r300_end_vertex_translate(struct r300_context *r300); +void r300_translate_index_buffer(struct r300_context *r300, + struct pipe_resource **index_buffer, + unsigned *index_size, unsigned index_offset, + unsigned *start, unsigned count); + +/* r300_render_stencilref.c */ +void r300_plug_in_stencil_ref_fallback(struct r300_context *r300); + +/* r300_state.c */ +void r300_mark_fs_code_dirty(struct r300_context *r300); + +/* r300_debug.c */ void r500_dump_rs_block(struct r300_rs_block *rs); + static INLINE boolean CTX_DBG_ON(struct r300_context * ctx, unsigned flags) { return SCREEN_DBG_ON(ctx->screen, flags); diff --git a/src/gallium/drivers/r300/r300_cs.h b/src/gallium/drivers/r300/r300_cs.h index 9c8c273902..1db7da642b 100644 --- a/src/gallium/drivers/r300/r300_cs.h +++ b/src/gallium/drivers/r300/r300_cs.h @@ -20,171 +20,133 @@ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE * USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/** + * This file contains macros for immediate command submission. + */ + #ifndef R300_CS_H #define R300_CS_H -#include "util/u_math.h" - #include "r300_reg.h" +#include "r300_context.h" #include "r300_winsys.h" /* Yes, I know macros are ugly. However, they are much prettier than the code * that they neatly hide away, and don't have the cost of function setup,so * we're going to use them. */ -#define MAX_CS_SIZE 64 * 1024 / 4 - -#define VERY_VERBOSE_CS 1 -#define VERY_VERBOSE_REGISTERS 1 +#ifdef DEBUG +#define CS_DEBUG(x) x +#else +#define CS_DEBUG(x) +#endif -/* XXX stolen from radeon_reg.h */ -#define RADEON_CP_PACKET0 0x0 - -#define CP_PACKET0(register, count) \ - (RADEON_CP_PACKET0 | ((count) << 16) | ((register) >> 2)) +/** + * Command submission setup. + */ #define CS_LOCALS(context) \ struct r300_context* const cs_context_copy = (context); \ struct r300_winsys_screen *cs_winsys = cs_context_copy->rws; \ - int cs_count = 0; (void) cs_count; - -#define CHECK_CS(size) \ - assert(r300_check_cs(cs_context_copy, (size))) + CS_DEBUG(int cs_count = 0; (void) cs_count;) #define BEGIN_CS(size) do { \ - CHECK_CS(size); \ - if (VERY_VERBOSE_CS) { \ - DBG(cs_context_copy, DBG_CS, "r300: BEGIN_CS, count %d, in %s (%s:%d)\n", \ - size, __FUNCTION__, __FILE__, __LINE__); \ - } \ - cs_winsys->begin_cs(cs_winsys, (size), \ - __FILE__, __FUNCTION__, __LINE__); \ - cs_count = size; \ + assert(r300_check_cs(cs_context_copy, (size))); \ + CS_DEBUG(cs_count = size;) \ +} while (0) + +#ifdef DEBUG +#define END_CS do { \ + if (cs_count != 0) \ + debug_printf("r300: Warning: cs_count off by %d at (%s, %s:%i)\n", \ + cs_count, __FUNCTION__, __FILE__, __LINE__); \ + cs_count = 0; \ } while (0) +#else +#define END_CS +#endif + +/** + * Writing pure DWORDs. + */ #define OUT_CS(value) do { \ - if (VERY_VERBOSE_CS || VERY_VERBOSE_REGISTERS) { \ - DBG(cs_context_copy, DBG_CS, "r300: writing %08x\n", value); \ - } \ cs_winsys->write_cs_dword(cs_winsys, (value)); \ - cs_count--; \ + CS_DEBUG(cs_count--;) \ } while (0) #define OUT_CS_32F(value) do { \ - if (VERY_VERBOSE_CS || VERY_VERBOSE_REGISTERS) { \ - DBG(cs_context_copy, DBG_CS, "r300: writing %f\n", value); \ - } \ cs_winsys->write_cs_dword(cs_winsys, fui(value)); \ - cs_count--; \ + CS_DEBUG(cs_count--;) \ } while (0) #define OUT_CS_REG(register, value) do { \ - if (VERY_VERBOSE_REGISTERS) \ - DBG(cs_context_copy, DBG_CS, "r300: writing 0x%08X to register 0x%04X\n", \ - value, register); \ assert(register); \ cs_winsys->write_cs_dword(cs_winsys, CP_PACKET0(register, 0)); \ cs_winsys->write_cs_dword(cs_winsys, value); \ - cs_count -= 2; \ + CS_DEBUG(cs_count -= 2;) \ } while (0) /* Note: This expects count to be the number of registers, * not the actual packet0 count! */ #define OUT_CS_REG_SEQ(register, count) do { \ - if (VERY_VERBOSE_REGISTERS) \ - DBG(cs_context_copy, DBG_CS, "r300: writing register sequence of %d to 0x%04X\n", \ - count, register); \ assert(register); \ cs_winsys->write_cs_dword(cs_winsys, CP_PACKET0((register), ((count) - 1))); \ - cs_count--; \ + CS_DEBUG(cs_count--;) \ } while (0) #define OUT_CS_TABLE(values, count) do { \ - if (VERY_VERBOSE_REGISTERS) \ - DBG(cs_context_copy, DBG_CS, "r300: writing table of %d dwords\n", count); \ cs_winsys->write_cs_table(cs_winsys, values, count); \ - cs_count -= count; \ + CS_DEBUG(cs_count -= count;) \ } while (0) -#define OUT_CS_BUF_RELOC(bo, offset, rd, wd, flags) do { \ - DBG(cs_context_copy, DBG_CS, "r300: writing relocation for buffer %p, offset %d, " \ - "domains (%d, %d, %d)\n", \ - bo, offset, rd, wd, flags); \ - assert(bo); \ - cs_winsys->write_cs_dword(cs_winsys, offset); \ - r300_buffer_write_reloc(cs_winsys, r300_buffer(bo), rd, wd, flags); \ - cs_count -= 3; \ +#define OUT_CS_ONE_REG(register, count) do { \ + assert(register); \ + cs_winsys->write_cs_dword(cs_winsys, CP_PACKET0((register), ((count) - 1)) | RADEON_ONE_REG_WR); \ + CS_DEBUG(cs_count--;) \ } while (0) - -#define OUT_CS_TEX_RELOC(tex, offset, rd, wd, flags) do { \ - DBG(cs_context_copy, DBG_CS, "r300: writing relocation for texture %p, offset %d, " \ - "domains (%d, %d, %d)\n", \ - tex, offset, rd, wd, flags); \ - assert(tex); \ - cs_winsys->write_cs_dword(cs_winsys, offset); \ - r300_texture_write_reloc(cs_winsys, tex, rd, wd, flags); \ - cs_count -= 3; \ +#define OUT_CS_PKT3(op, count) do { \ + cs_winsys->write_cs_dword(cs_winsys, CP_PACKET3(op, count)); \ + CS_DEBUG(cs_count--;) \ } while (0) -#define OUT_CS_BUF_RELOC_NO_OFFSET(bo, rd, wd, flags) do { \ - DBG(cs_context_copy, DBG_CS, "r300: writing relocation for buffer %p, " \ - "domains (%d, %d, %d)\n", \ - bo, rd, wd, flags); \ +/** + * Writing relocations. + */ + +#define OUT_CS_RELOC(bo, offset, rd, wd, flags) do { \ assert(bo); \ - r300_buffer_write_reloc(cs_winsys, r300_buffer(bo), rd, wd, flags); \ - cs_count -= 2; \ + cs_winsys->write_cs_dword(cs_winsys, offset); \ + cs_winsys->write_cs_reloc(cs_winsys, bo, rd, wd, flags); \ + CS_DEBUG(cs_count -= 3;) \ } while (0) -#define END_CS do { \ - if (VERY_VERBOSE_CS) { \ - DBG(cs_context_copy, DBG_CS, "r300: END_CS in %s (%s:%d)\n", __FUNCTION__, \ - __FILE__, __LINE__); \ - } \ - if (cs_count != 0) \ - debug_printf("r300: Warning: cs_count off by %d\n", cs_count); \ - cs_winsys->end_cs(cs_winsys, __FILE__, __FUNCTION__, __LINE__); \ +#define OUT_CS_BUF_RELOC(bo, offset, rd, wd, flags) do { \ + assert(bo); \ + OUT_CS_RELOC(r300_buffer(bo)->buf, offset, rd, wd, flags); \ } while (0) -#define FLUSH_CS do { \ - if (VERY_VERBOSE_CS) { \ - DBG(cs_context_copy, DBG_CS, "r300: FLUSH_CS in %s (%s:%d)\n\n", __FUNCTION__, \ - __FILE__, __LINE__); \ - } \ - if (SCREEN_DBG_ON(r300->screen, DBG_STATS)) { \ - r300->flush_counter++; \ - } \ - cs_winsys->flush_cs(cs_winsys); \ +#define OUT_CS_TEX_RELOC(tex, offset, rd, wd, flags) do { \ + assert(tex); \ + OUT_CS_RELOC(tex->buffer, offset, rd, wd, flags); \ } while (0) -#define RADEON_ONE_REG_WR (1 << 15) - -#define OUT_CS_ONE_REG(register, count) do { \ - if (VERY_VERBOSE_REGISTERS) \ - DBG(cs_context_copy, DBG_CS, "r300: writing data sequence of %d to 0x%04X\n", \ - count, register); \ - assert(register); \ - cs_winsys->write_cs_dword(cs_winsys, CP_PACKET0((register), ((count) - 1)) | RADEON_ONE_REG_WR); \ - cs_count--; \ +#define OUT_CS_BUF_RELOC_NO_OFFSET(bo, rd, wd, flags) do { \ + assert(bo); \ + cs_winsys->write_cs_reloc(cs_winsys, r300_buffer(bo)->buf, rd, wd, flags); \ + CS_DEBUG(cs_count -= 2;) \ } while (0) -#define CP_PACKET3(op, count) \ - (RADEON_CP_PACKET3 | (op) | ((count) << 16)) -#define OUT_CS_PKT3(op, count) do { \ - cs_winsys->write_cs_dword(cs_winsys, CP_PACKET3(op, count)); \ - cs_count--; \ -} while (0) +/** + * Command buffer emission. + */ -#define OUT_CS_INDEX_RELOC(bo, offset, count, rd, wd, flags) do { \ - DBG(cs_context_copy, DBG_CS, "r300: writing relocation for index buffer %p," \ - "offset %d\n", bo, offset); \ - assert(bo); \ - cs_winsys->write_cs_dword(cs_winsys, offset); \ - cs_winsys->write_cs_dword(cs_winsys, count); \ - cs_winsys->write_cs_reloc(cs_winsys, bo, rd, wd, flags); \ - cs_count -= 4; \ +#define WRITE_CS_TABLE(values, count) do { \ + CS_DEBUG(assert(cs_count == 0);) \ + cs_winsys->write_cs_table(cs_winsys, values, count); \ } while (0) #endif /* R300_CS_H */ diff --git a/src/gallium/drivers/r300/r300_debug.c b/src/gallium/drivers/r300/r300_debug.c index 297791f3ff..a6cd86e392 100644 --- a/src/gallium/drivers/r300/r300_debug.c +++ b/src/gallium/drivers/r300/r300_debug.c @@ -29,7 +29,6 @@ static const struct debug_named_value debug_options[] = { { "fp", DBG_FP, "Fragment program handling (for debugging)" }, { "vp", DBG_VP, "Vertex program handling (for debugging)" }, - { "cs", DBG_CS, "Command submissions (for debugging)" }, { "draw", DBG_DRAW, "Draw and emit (for debugging)" }, { "tex", DBG_TEX, "Textures (for debugging)" }, { "texalloc", DBG_TEXALLOC, "Texture allocation (for debugging)" }, @@ -39,6 +38,7 @@ static const struct debug_named_value debug_options[] = { { "anisohq", DBG_ANISOHQ, "High quality anisotropic filtering (for benchmarking)" }, { "notiling", DBG_NO_TILING, "Disable tiling (for benchmarking)" }, { "noimmd", DBG_NO_IMMD, "Disable immediate mode (for benchmarking)" }, + { "fakeocc", DBG_FAKE_OCC, "Use fake occlusion queries (for lulz)" }, { "stats", DBG_STATS, "Gather statistics (for lulz)" }, /* must be last */ diff --git a/src/gallium/drivers/r300/r300_defines.h b/src/gallium/drivers/r300/r300_defines.h index 83c9ec7e39..d510d80a7b 100644 --- a/src/gallium/drivers/r300/r300_defines.h +++ b/src/gallium/drivers/r300/r300_defines.h @@ -30,13 +30,7 @@ #define R300_RESOURCE_FLAG_TRANSFER PIPE_RESOURCE_FLAG_DRV_PRIV -#define R300_INVALID_FORMAT (~0) - -/* XXX: this is just a bandaid on larger problems in - * r300_screen_buffer.h which doesn't seem to be fully ported to - * gallium-resources. - */ -#define R300_BIND_OQBO (1<<21) +#define R300_INVALID_FORMAT 0xffff /* Tiling flags. */ enum r300_buffer_tiling { diff --git a/src/gallium/drivers/r300/r300_emit.c b/src/gallium/drivers/r300/r300_emit.c index c329c0f30f..014b382edf 100644 --- a/src/gallium/drivers/r300/r300_emit.c +++ b/src/gallium/drivers/r300/r300_emit.c @@ -43,21 +43,11 @@ void r300_emit_blend_state(struct r300_context* r300, (struct pipe_framebuffer_state*)r300->fb_state.state; CS_LOCALS(r300); - BEGIN_CS(size); - OUT_CS_REG(R300_RB3D_ROPCNTL, blend->rop); - OUT_CS_REG_SEQ(R300_RB3D_CBLEND, 3); if (fb->nr_cbufs) { - OUT_CS(blend->blend_control); - OUT_CS(blend->alpha_blend_control); - OUT_CS(blend->color_channel_mask); + WRITE_CS_TABLE(blend->cb, size); } else { - OUT_CS(0); - OUT_CS(0); - OUT_CS(0); - /* XXX also disable fastfill here once it's supported */ + WRITE_CS_TABLE(blend->cb_no_readwrite, size); } - OUT_CS_REG(R300_RB3D_DITHER_CTL, blend->dither); - END_CS; } void r300_emit_blend_color_state(struct r300_context* r300, @@ -66,40 +56,16 @@ void r300_emit_blend_color_state(struct r300_context* r300, struct r300_blend_color_state* bc = (struct r300_blend_color_state*)state; CS_LOCALS(r300); - if (r300->screen->caps.is_r500) { - BEGIN_CS(size); - OUT_CS_REG_SEQ(R500_RB3D_CONSTANT_COLOR_AR, 2); - OUT_CS(bc->blend_color_red_alpha); - OUT_CS(bc->blend_color_green_blue); - END_CS; - } else { - BEGIN_CS(size); - OUT_CS_REG(R300_RB3D_BLEND_COLOR, bc->blend_color); - END_CS; - } + WRITE_CS_TABLE(bc->cb, size); } void r300_emit_clip_state(struct r300_context* r300, unsigned size, void* state) { - struct pipe_clip_state* clip = (struct pipe_clip_state*)state; + struct r300_clip_state* clip = (struct r300_clip_state*)state; CS_LOCALS(r300); - if (r300->screen->caps.has_tcl) { - BEGIN_CS(size); - OUT_CS_REG(R300_VAP_PVS_VECTOR_INDX_REG, - (r300->screen->caps.is_r500 ? - R500_PVS_UCP_START : R300_PVS_UCP_START)); - OUT_CS_ONE_REG(R300_VAP_PVS_UPLOAD_DATA, 6 * 4); - OUT_CS_TABLE(clip->ucp, 6 * 4); - OUT_CS_REG(R300_VAP_CLIP_CNTL, ((1 << clip->nr) - 1) | - R300_PS_UCP_MODE_CLIP_AS_TRIFAN); - END_CS; - } else { - BEGIN_CS(size); - OUT_CS_REG(R300_VAP_CLIP_CNTL, R300_CLIP_DISABLE); - END_CS; - } + WRITE_CS_TABLE(clip->cb, size); } void r300_emit_dsa_state(struct r300_context* r300, unsigned size, void* state) @@ -107,27 +73,13 @@ void r300_emit_dsa_state(struct r300_context* r300, unsigned size, void* state) struct r300_dsa_state* dsa = (struct r300_dsa_state*)state; struct pipe_framebuffer_state* fb = (struct pipe_framebuffer_state*)r300->fb_state.state; - struct pipe_stencil_ref stencil_ref = r300->stencil_ref; CS_LOCALS(r300); - BEGIN_CS(size); - OUT_CS_REG(R300_FG_ALPHA_FUNC, dsa->alpha_function); - OUT_CS_REG_SEQ(R300_ZB_CNTL, 3); - if (fb->zsbuf) { - OUT_CS(dsa->z_buffer_control); - OUT_CS(dsa->z_stencil_control); + WRITE_CS_TABLE(&dsa->cb_begin, size); } else { - OUT_CS(0); - OUT_CS(0); + WRITE_CS_TABLE(dsa->cb_no_readwrite, size); } - - OUT_CS(dsa->stencil_ref_mask | stencil_ref.ref_value[0]); - - if (r300->screen->caps.is_r500) { - OUT_CS_REG(R500_ZB_STENCILREFMASK_BF, dsa->stencil_ref_bf | stencil_ref.ref_value[1]); - } - END_CS; } static const float * get_rc_constant_state( @@ -175,7 +127,7 @@ static const float * get_rc_constant_state( /* Convert a normal single-precision float into the 7.16 format * used by the R300 fragment shader. */ -static uint32_t pack_float24(float f) +uint32_t pack_float24(float f) { union { float fl; @@ -206,101 +158,27 @@ static uint32_t pack_float24(float f) return float24; } -unsigned r300_get_fs_atom_size(struct r300_context *r300) -{ - struct r300_fragment_shader *fs = r300_fs(r300); - unsigned imm_count = fs->shader->immediates_count; - struct r300_fragment_program_code *code = &fs->shader->code.code.r300; - - return 19 + - code->alu.length * 4 + - (code->tex.length ? (1 + code->tex.length) : 0) + - (imm_count ? imm_count * 5 : 0); -} - void r300_emit_fs(struct r300_context* r300, unsigned size, void *state) { struct r300_fragment_shader *fs = r300_fs(r300); - struct rX00_fragment_program_code* generic_code = &fs->shader->code; - struct r300_fragment_program_code * code = &generic_code->code.r300; - unsigned i; - unsigned imm_count = fs->shader->immediates_count; - unsigned imm_first = fs->shader->externals_count; - unsigned imm_end = generic_code->constants.Count; - struct rc_constant *constants = generic_code->constants.Constants; CS_LOCALS(r300); - BEGIN_CS(size); - OUT_CS_REG(R300_US_CONFIG, code->config); - OUT_CS_REG(R300_US_PIXSIZE, code->pixsize); - OUT_CS_REG(R300_US_CODE_OFFSET, code->code_offset); - - OUT_CS_REG_SEQ(R300_US_CODE_ADDR_0, 4); - OUT_CS_TABLE(code->code_addr, 4); - - OUT_CS_REG_SEQ(R300_US_ALU_RGB_INST_0, code->alu.length); - for (i = 0; i < code->alu.length; i++) - OUT_CS(code->alu.inst[i].rgb_inst); - - OUT_CS_REG_SEQ(R300_US_ALU_RGB_ADDR_0, code->alu.length); - for (i = 0; i < code->alu.length; i++) - OUT_CS(code->alu.inst[i].rgb_addr); - - OUT_CS_REG_SEQ(R300_US_ALU_ALPHA_INST_0, code->alu.length); - for (i = 0; i < code->alu.length; i++) - OUT_CS(code->alu.inst[i].alpha_inst); - - OUT_CS_REG_SEQ(R300_US_ALU_ALPHA_ADDR_0, code->alu.length); - for (i = 0; i < code->alu.length; i++) - OUT_CS(code->alu.inst[i].alpha_addr); - - if (code->tex.length) { - OUT_CS_REG_SEQ(R300_US_TEX_INST_0, code->tex.length); - OUT_CS_TABLE(code->tex.inst, code->tex.length); - } - - /* Emit immediates. */ - if (imm_count) { - for(i = imm_first; i < imm_end; ++i) { - if (constants[i].Type == RC_CONSTANT_IMMEDIATE) { - const float *data = constants[i].u.Immediate; - - OUT_CS_REG_SEQ(R300_PFS_PARAM_0_X + i * 16, 4); - OUT_CS(pack_float24(data[0])); - OUT_CS(pack_float24(data[1])); - OUT_CS(pack_float24(data[2])); - OUT_CS(pack_float24(data[3])); - } - } - } - - OUT_CS_REG(R300_FG_DEPTH_SRC, fs->shader->fg_depth_src); - OUT_CS_REG(R300_US_W_FMT, fs->shader->us_out_w); - END_CS; + WRITE_CS_TABLE(fs->shader->cb_code, fs->shader->cb_code_size); } void r300_emit_fs_constants(struct r300_context* r300, unsigned size, void *state) { struct r300_fragment_shader *fs = r300_fs(r300); - struct rc_constant_list *constants = &fs->shader->code.constants; struct r300_constant_buffer *buf = (struct r300_constant_buffer*)state; - unsigned i, count = fs->shader->externals_count; + unsigned count = fs->shader->externals_count * 4; CS_LOCALS(r300); if (count == 0) return; BEGIN_CS(size); - OUT_CS_REG_SEQ(R300_PFS_PARAM_0_X, count * 4); - for(i = 0; i < count; ++i) { - const float *data; - assert(constants->Constants[i].Type == RC_CONSTANT_EXTERNAL); - data = buf->constants[i]; - OUT_CS(pack_float24(data[0])); - OUT_CS(pack_float24(data[1])); - OUT_CS(pack_float24(data[2])); - OUT_CS(pack_float24(data[3])); - } + OUT_CS_REG_SEQ(R300_PFS_PARAM_0_X, count); + OUT_CS_TABLE(buf->constants, count); END_CS; } @@ -312,6 +190,8 @@ void r300_emit_fs_rc_constant_state(struct r300_context* r300, unsigned size, vo unsigned count = fs->shader->rc_state_count; unsigned first = fs->shader->externals_count; unsigned end = constants->Count; + uint32_t cdata[4]; + unsigned j; CS_LOCALS(r300); if (count == 0) @@ -323,85 +203,29 @@ void r300_emit_fs_rc_constant_state(struct r300_context* r300, unsigned size, vo const float *data = get_rc_constant_state(r300, &constants->Constants[i]); + for (j = 0; j < 4; j++) + cdata[j] = pack_float24(data[j]); + OUT_CS_REG_SEQ(R300_PFS_PARAM_0_X + i * 16, 4); - OUT_CS(pack_float24(data[0])); - OUT_CS(pack_float24(data[1])); - OUT_CS(pack_float24(data[2])); - OUT_CS(pack_float24(data[3])); + OUT_CS_TABLE(cdata, 4); } } END_CS; } -unsigned r500_get_fs_atom_size(struct r300_context *r300) -{ - struct r300_fragment_shader *fs = r300_fs(r300); - unsigned imm_count = fs->shader->immediates_count; - struct r500_fragment_program_code *code = &fs->shader->code.code.r500; - - return 17 + - ((code->inst_end + 1) * 6) + - (imm_count ? imm_count * 7 : 0); -} - void r500_emit_fs(struct r300_context* r300, unsigned size, void *state) { struct r300_fragment_shader *fs = r300_fs(r300); - struct rX00_fragment_program_code* generic_code = &fs->shader->code; - struct r500_fragment_program_code * code = &generic_code->code.r500; - unsigned i; - unsigned imm_count = fs->shader->immediates_count; - unsigned imm_first = fs->shader->externals_count; - unsigned imm_end = generic_code->constants.Count; - struct rc_constant *constants = generic_code->constants.Constants; CS_LOCALS(r300); - BEGIN_CS(size); - OUT_CS_REG(R500_US_CONFIG, R500_ZERO_TIMES_ANYTHING_EQUALS_ZERO); - OUT_CS_REG(R500_US_PIXSIZE, code->max_temp_idx); - OUT_CS_REG(R500_US_CODE_RANGE, - R500_US_CODE_RANGE_ADDR(0) | R500_US_CODE_RANGE_SIZE(code->inst_end)); - OUT_CS_REG(R500_US_CODE_OFFSET, 0); - OUT_CS_REG(R500_US_CODE_ADDR, - R500_US_CODE_START_ADDR(0) | R500_US_CODE_END_ADDR(code->inst_end)); - - OUT_CS_REG(R500_GA_US_VECTOR_INDEX, R500_GA_US_VECTOR_INDEX_TYPE_INSTR); - OUT_CS_ONE_REG(R500_GA_US_VECTOR_DATA, (code->inst_end + 1) * 6); - for (i = 0; i <= code->inst_end; i++) { - OUT_CS(code->inst[i].inst0); - OUT_CS(code->inst[i].inst1); - OUT_CS(code->inst[i].inst2); - OUT_CS(code->inst[i].inst3); - OUT_CS(code->inst[i].inst4); - OUT_CS(code->inst[i].inst5); - } - - /* Emit immediates. */ - if (imm_count) { - for(i = imm_first; i < imm_end; ++i) { - if (constants[i].Type == RC_CONSTANT_IMMEDIATE) { - const float *data = constants[i].u.Immediate; - - OUT_CS_REG(R500_GA_US_VECTOR_INDEX, - R500_GA_US_VECTOR_INDEX_TYPE_CONST | - (i & R500_GA_US_VECTOR_INDEX_MASK)); - OUT_CS_ONE_REG(R500_GA_US_VECTOR_DATA, 4); - OUT_CS_TABLE(data, 4); - } - } - } - - OUT_CS_REG(R300_FG_DEPTH_SRC, fs->shader->fg_depth_src); - OUT_CS_REG(R300_US_W_FMT, fs->shader->us_out_w); - END_CS; + WRITE_CS_TABLE(fs->shader->cb_code, fs->shader->cb_code_size); } void r500_emit_fs_constants(struct r300_context* r300, unsigned size, void *state) { struct r300_fragment_shader *fs = r300_fs(r300); - struct rc_constant_list *constants = &fs->shader->code.constants; struct r300_constant_buffer *buf = (struct r300_constant_buffer*)state; - unsigned i, count = fs->shader->externals_count; + unsigned count = fs->shader->externals_count * 4; CS_LOCALS(r300); if (count == 0) @@ -409,11 +233,8 @@ void r500_emit_fs_constants(struct r300_context* r300, unsigned size, void *stat BEGIN_CS(size); OUT_CS_REG(R500_GA_US_VECTOR_INDEX, R500_GA_US_VECTOR_INDEX_TYPE_CONST); - OUT_CS_ONE_REG(R500_GA_US_VECTOR_DATA, count * 4); - for(i = 0; i < count; ++i) { - assert(constants->Constants[i].Type == RC_CONSTANT_EXTERNAL); - } - OUT_CS_TABLE(buf->constants, count * 4); + OUT_CS_ONE_REG(R500_GA_US_VECTOR_DATA, count); + OUT_CS_TABLE(buf->constants, count); END_CS; } @@ -446,83 +267,170 @@ void r500_emit_fs_rc_constant_state(struct r300_context* r300, unsigned size, vo END_CS; } +void r300_emit_gpu_flush(struct r300_context *r300, unsigned size, void *state) +{ + struct r300_gpu_flush *gpuflush = (struct r300_gpu_flush*)state; + struct pipe_framebuffer_state* fb = + (struct pipe_framebuffer_state*)r300->fb_state.state; + CS_LOCALS(r300); + + BEGIN_CS(size); + + /* Set up scissors. + * By writing to the SC registers, SC & US assert idle. */ + OUT_CS_REG_SEQ(R300_SC_SCISSORS_TL, 2); + if (r300->screen->caps.is_r500) { + OUT_CS(0); + OUT_CS(((fb->width - 1) << R300_SCISSORS_X_SHIFT) | + ((fb->height - 1) << R300_SCISSORS_Y_SHIFT)); + } else { + OUT_CS((1440 << R300_SCISSORS_X_SHIFT) | + (1440 << R300_SCISSORS_Y_SHIFT)); + OUT_CS(((fb->width + 1440-1) << R300_SCISSORS_X_SHIFT) | + ((fb->height + 1440-1) << R300_SCISSORS_Y_SHIFT)); + } + + /* Flush CB & ZB caches and wait until the 3D engine is idle and clean. */ + OUT_CS_TABLE(gpuflush->cb_flush_clean, 6); + END_CS; +} + +void r300_emit_aa_state(struct r300_context *r300, unsigned size, void *state) +{ + struct r300_aa_state *aa = (struct r300_aa_state*)state; + CS_LOCALS(r300); + + BEGIN_CS(size); + OUT_CS_REG(R300_GB_AA_CONFIG, aa->aa_config); + + if (aa->dest) { + OUT_CS_REG_SEQ(R300_RB3D_AARESOLVE_OFFSET, 1); + OUT_CS_RELOC(aa->dest->buffer, aa->dest->offset, 0, aa->dest->domain, 0); + + OUT_CS_REG_SEQ(R300_RB3D_AARESOLVE_PITCH, 1); + OUT_CS_RELOC(aa->dest->buffer, aa->dest->pitch, 0, aa->dest->domain, 0); + } + + OUT_CS_REG(R300_RB3D_AARESOLVE_CTL, aa->aaresolve_ctl); + END_CS; +} + void r300_emit_fb_state(struct r300_context* r300, unsigned size, void* state) { struct pipe_framebuffer_state* fb = (struct pipe_framebuffer_state*)state; - struct r300_texture* tex; - struct pipe_surface* surf; - int i; + struct r300_surface* surf; + unsigned i; CS_LOCALS(r300); BEGIN_CS(size); - /* Flush and free renderbuffer caches. */ - OUT_CS_REG(R300_RB3D_DSTCACHE_CTLSTAT, - R300_RB3D_DSTCACHE_CTLSTAT_DC_FREE_FREE_3D_TAGS | - R300_RB3D_DSTCACHE_CTLSTAT_DC_FLUSH_FLUSH_DIRTY_3D); - OUT_CS_REG(R300_ZB_ZCACHE_CTLSTAT, - R300_ZB_ZCACHE_CTLSTAT_ZC_FLUSH_FLUSH_AND_FREE | - R300_ZB_ZCACHE_CTLSTAT_ZC_FREE_FREE); - - /* Set the number of colorbuffers. */ - if (fb->nr_cbufs > 1) { - if (r300->screen->caps.is_r500) { - OUT_CS_REG(R300_RB3D_CCTL, - R300_RB3D_CCTL_NUM_MULTIWRITES(fb->nr_cbufs) | - R300_RB3D_CCTL_INDEPENDENT_COLORFORMAT_ENABLE_ENABLE); - } else { - OUT_CS_REG(R300_RB3D_CCTL, - R300_RB3D_CCTL_NUM_MULTIWRITES(fb->nr_cbufs)); - } + /* NUM_MULTIWRITES replicates COLOR[0] to all colorbuffers, which is not + * what we usually want. */ + if (r300->screen->caps.is_r500) { + OUT_CS_REG(R300_RB3D_CCTL, + R300_RB3D_CCTL_INDEPENDENT_COLORFORMAT_ENABLE_ENABLE); } else { - OUT_CS_REG(R300_RB3D_CCTL, 0x0); + OUT_CS_REG(R300_RB3D_CCTL, 0); } /* Set up colorbuffers. */ for (i = 0; i < fb->nr_cbufs; i++) { - surf = fb->cbufs[i]; - tex = r300_texture(surf->texture); - assert(tex && tex->buffer && "cbuf is marked, but NULL!"); + surf = r300_surface(fb->cbufs[i]); OUT_CS_REG_SEQ(R300_RB3D_COLOROFFSET0 + (4 * i), 1); - OUT_CS_TEX_RELOC(tex, surf->offset, 0, tex->domain, 0); + OUT_CS_RELOC(surf->buffer, surf->offset, 0, surf->domain, 0); OUT_CS_REG_SEQ(R300_RB3D_COLORPITCH0 + (4 * i), 1); - OUT_CS_TEX_RELOC(tex, tex->fb_state.colorpitch[surf->level], - 0, tex->domain, 0); - - OUT_CS_REG(R300_US_OUT_FMT_0 + (4 * i), tex->fb_state.us_out_fmt); - } - for (; i < 4; i++) { - OUT_CS_REG(R300_US_OUT_FMT_0 + (4 * i), R300_US_OUT_FMT_UNUSED); + OUT_CS_RELOC(surf->buffer, surf->pitch, 0, surf->domain, 0); } /* Set up a zbuffer. */ if (fb->zsbuf) { - surf = fb->zsbuf; - tex = r300_texture(surf->texture); - assert(tex && tex->buffer && "zsbuf is marked, but NULL!"); + surf = r300_surface(fb->zsbuf); - OUT_CS_REG_SEQ(R300_ZB_DEPTHOFFSET, 1); - OUT_CS_TEX_RELOC(tex, surf->offset, 0, tex->domain, 0); + OUT_CS_REG(R300_ZB_FORMAT, surf->format); - OUT_CS_REG(R300_ZB_FORMAT, tex->fb_state.zb_format); + OUT_CS_REG_SEQ(R300_ZB_DEPTHOFFSET, 1); + OUT_CS_RELOC(surf->buffer, surf->offset, 0, surf->domain, 0); OUT_CS_REG_SEQ(R300_ZB_DEPTHPITCH, 1); - OUT_CS_TEX_RELOC(tex, tex->fb_state.depthpitch[surf->level], - 0, tex->domain, 0); + OUT_CS_RELOC(surf->buffer, surf->pitch, 0, surf->domain, 0); + + /* HiZ RAM. */ + if (r300->screen->caps.has_hiz) { + OUT_CS_REG(R300_ZB_HIZ_OFFSET, 0); + OUT_CS_REG(R300_ZB_HIZ_PITCH, 0); + } + + /* Z Mask RAM. (compressed zbuffer) */ + OUT_CS_REG(R300_ZB_ZMASK_OFFSET, 0); + OUT_CS_REG(R300_ZB_ZMASK_PITCH, 0); } - OUT_CS_REG_SEQ(R300_SC_SCISSORS_TL, 2); - if (r300->screen->caps.is_r500) { - OUT_CS(0); - OUT_CS(((fb->width - 1) << R300_SCISSORS_X_SHIFT) | - ((fb->height - 1) << R300_SCISSORS_Y_SHIFT)); - } else { - OUT_CS((1440 << R300_SCISSORS_X_SHIFT) | - (1440 << R300_SCISSORS_Y_SHIFT)); - OUT_CS(((fb->width + 1440-1) << R300_SCISSORS_X_SHIFT) | - ((fb->height + 1440-1) << R300_SCISSORS_Y_SHIFT)); + END_CS; +} + +void r300_emit_hyperz_state(struct r300_context *r300, + unsigned size, void *state) +{ + CS_LOCALS(r300); + WRITE_CS_TABLE(state, size); +} + +void r300_emit_fb_state_pipelined(struct r300_context *r300, + unsigned size, void *state) +{ + struct pipe_framebuffer_state* fb = + (struct pipe_framebuffer_state*)r300->fb_state.state; + unsigned i; + CS_LOCALS(r300); + + BEGIN_CS(size); + + /* Colorbuffer format in the US block. + * (must be written after unpipelined regs) */ + OUT_CS_REG_SEQ(R300_US_OUT_FMT_0, 4); + for (i = 0; i < fb->nr_cbufs; i++) { + OUT_CS(r300_surface(fb->cbufs[i])->format); + } + for (; i < 4; i++) { + OUT_CS(R300_US_OUT_FMT_UNUSED); + } + + /* Multisampling. Depends on framebuffer sample count. + * These are pipelined regs and as such cannot be moved + * to the AA state. */ + if (r300->rws->get_value(r300->rws, R300_VID_DRM_2_3_0)) { + unsigned mspos0 = 0x66666666; + unsigned mspos1 = 0x6666666; + + if (fb->nr_cbufs && fb->cbufs[0]->texture->nr_samples > 1) { + /* Subsample placement. These may not be optimal. */ + switch (fb->cbufs[0]->texture->nr_samples) { + case 2: + mspos0 = 0x33996633; + mspos1 = 0x6666663; + break; + case 3: + mspos0 = 0x33936933; + mspos1 = 0x6666663; + break; + case 4: + mspos0 = 0x33939933; + mspos1 = 0x3966663; + break; + case 6: + mspos0 = 0x22a2aa22; + mspos1 = 0x2a65672; + break; + default: + debug_printf("r300: Bad number of multisamples!\n"); + } + } + + OUT_CS_REG_SEQ(R300_GB_MSPOS0, 2); + OUT_CS(mspos0); + OUT_CS(mspos1); } END_CS; } @@ -544,13 +452,14 @@ void r300_emit_query_start(struct r300_context *r300, unsigned size, void*state) OUT_CS_REG(R300_ZB_ZPASS_DATA, 0); END_CS; query->begin_emitted = TRUE; + query->flushed = FALSE; } - static void r300_emit_query_end_frag_pipes(struct r300_context *r300, struct r300_query *query) { struct r300_capabilities* caps = &r300->screen->caps; + struct r300_winsys_buffer *buf = r300->query_current->buffer; CS_LOCALS(r300); assert(caps->num_frag_pipes); @@ -569,28 +478,28 @@ static void r300_emit_query_end_frag_pipes(struct r300_context *r300, /* pipe 3 only */ OUT_CS_REG(R300_SU_REG_DEST, 1 << 3); OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1); - OUT_CS_BUF_RELOC(r300->oqbo, query->offset + (sizeof(uint32_t) * 3), - 0, r300_buffer(r300->oqbo)->domain, 0); + OUT_CS_RELOC(buf, (query->num_results + 3) * 4, + 0, query->domain, 0); case 3: /* pipe 2 only */ OUT_CS_REG(R300_SU_REG_DEST, 1 << 2); OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1); - OUT_CS_BUF_RELOC(r300->oqbo, query->offset + (sizeof(uint32_t) * 2), - 0, r300_buffer(r300->oqbo)->domain, 0); + OUT_CS_RELOC(buf, (query->num_results + 2) * 4, + 0, query->domain, 0); case 2: /* pipe 1 only */ /* As mentioned above, accomodate RV380 and older. */ OUT_CS_REG(R300_SU_REG_DEST, 1 << (caps->high_second_pipe ? 3 : 1)); OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1); - OUT_CS_BUF_RELOC(r300->oqbo, query->offset + (sizeof(uint32_t) * 1), - 0, r300_buffer(r300->oqbo)->domain, 0); + OUT_CS_RELOC(buf, (query->num_results + 1) * 4, + 0, query->domain, 0); case 1: /* pipe 0 only */ OUT_CS_REG(R300_SU_REG_DEST, 1 << 0); OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1); - OUT_CS_BUF_RELOC(r300->oqbo, query->offset + (sizeof(uint32_t) * 0), - 0, r300_buffer(r300->oqbo)->domain, 0); + OUT_CS_RELOC(buf, (query->num_results + 0) * 4, + 0, query->domain, 0); break; default: fprintf(stderr, "r300: Implementation error: Chipset reports %d" @@ -606,12 +515,13 @@ static void r300_emit_query_end_frag_pipes(struct r300_context *r300, static void rv530_emit_query_end_single_z(struct r300_context *r300, struct r300_query *query) { + struct r300_winsys_buffer *buf = r300->query_current->buffer; CS_LOCALS(r300); BEGIN_CS(8); OUT_CS_REG(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_0); OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1); - OUT_CS_BUF_RELOC(r300->oqbo, query->offset, 0, r300_buffer(r300->oqbo)->domain, 0); + OUT_CS_RELOC(buf, query->num_results * 4, 0, query->domain, 0); OUT_CS_REG(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_ALL); END_CS; } @@ -619,15 +529,16 @@ static void rv530_emit_query_end_single_z(struct r300_context *r300, static void rv530_emit_query_end_double_z(struct r300_context *r300, struct r300_query *query) { + struct r300_winsys_buffer *buf = r300->query_current->buffer; CS_LOCALS(r300); BEGIN_CS(14); OUT_CS_REG(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_0); OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1); - OUT_CS_BUF_RELOC(r300->oqbo, query->offset, 0, r300_buffer(r300->oqbo)->domain, 0); + OUT_CS_RELOC(buf, (query->num_results + 0) * 4, 0, query->domain, 0); OUT_CS_REG(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_1); OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1); - OUT_CS_BUF_RELOC(r300->oqbo, query->offset + sizeof(uint32_t), 0, r300_buffer(r300->oqbo)->domain, 0); + OUT_CS_RELOC(buf, (query->num_results + 1) * 4, 0, query->domain, 0); OUT_CS_REG(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_ALL); END_CS; } @@ -652,57 +563,36 @@ void r300_emit_query_end(struct r300_context* r300) r300_emit_query_end_frag_pipes(r300, query); query->begin_emitted = FALSE; + query->num_results += query->num_pipes; + + /* XXX grab all the results and reset the counter. */ + if (query->num_results >= query->buffer_size / 4 - 4) { + query->num_results = (query->buffer_size / 4) / 2; + fprintf(stderr, "r300: Rewinding OQBO...\n"); + } +} + +void r300_emit_invariant_state(struct r300_context *r300, + unsigned size, void *state) +{ + CS_LOCALS(r300); + WRITE_CS_TABLE(state, size); } void r300_emit_rs_state(struct r300_context* r300, unsigned size, void* state) { - struct r300_rs_state* rs = (struct r300_rs_state*)state; - float scale, offset; + struct r300_rs_state* rs = state; CS_LOCALS(r300); BEGIN_CS(size); - OUT_CS_REG(R300_VAP_CNTL_STATUS, rs->vap_control_status); - - OUT_CS_REG(R300_GB_AA_CONFIG, rs->antialiasing_config); - - OUT_CS_REG(R300_GA_POINT_SIZE, rs->point_size); - OUT_CS_REG_SEQ(R300_GA_POINT_MINMAX, 2); - OUT_CS(rs->point_minmax); - OUT_CS(rs->line_control); - + OUT_CS_TABLE(rs->cb_main, 25); if (rs->polygon_offset_enable) { - scale = rs->depth_scale * 12; - offset = rs->depth_offset; - - switch (r300->zbuffer_bpp) { - case 16: - offset *= 4; - break; - case 24: - offset *= 2; - break; + if (r300->zbuffer_bpp == 16) { + OUT_CS_TABLE(rs->cb_poly_offset_zb16, 5); + } else { + OUT_CS_TABLE(rs->cb_poly_offset_zb24, 5); } - - OUT_CS_REG_SEQ(R300_SU_POLY_OFFSET_FRONT_SCALE, 4); - OUT_CS_32F(scale); - OUT_CS_32F(offset); - OUT_CS_32F(scale); - OUT_CS_32F(offset); } - - OUT_CS_REG_SEQ(R300_SU_POLY_OFFSET_ENABLE, 2); - OUT_CS(rs->polygon_offset_enable); - OUT_CS(rs->cull_mode); - OUT_CS_REG(R300_GA_LINE_STIPPLE_CONFIG, rs->line_stipple_config); - OUT_CS_REG(R300_GA_LINE_STIPPLE_VALUE, rs->line_stipple_value); - OUT_CS_REG(R300_GA_POLY_MODE, rs->polygon_mode); - OUT_CS_REG(R300_SC_CLIP_RULE, rs->clip_rule); - OUT_CS_REG(R300_GB_ENABLE, rs->stuffing_enable); - OUT_CS_REG_SEQ(R300_GA_POINT_S0, 4); - OUT_CS_32F(rs->point_texcoord_left); - OUT_CS_32F(rs->point_texcoord_bottom); - OUT_CS_32F(rs->point_texcoord_right); - OUT_CS_32F(rs->point_texcoord_top); END_CS; } @@ -717,9 +607,18 @@ void r300_emit_rs_block_state(struct r300_context* r300, if (SCREEN_DBG_ON(r300->screen, DBG_DRAW)) { r500_dump_rs_block(rs); - } - DBG(r300, DBG_DRAW, "r300: RS emit:\n"); + fprintf(stderr, "r300: RS emit:\n"); + + for (i = 0; i < count; i++) + fprintf(stderr, " : ip %d: 0x%08x\n", i, rs->ip[i]); + + for (i = 0; i < count; i++) + fprintf(stderr, " : inst %d: 0x%08x\n", i, rs->inst[i]); + + fprintf(stderr, " : count: 0x%08x inst_count: 0x%08x\n", + rs->count, rs->inst_count); + } BEGIN_CS(size); OUT_CS_REG_SEQ(R300_VAP_VTX_STATE_CNTL, 2); @@ -735,9 +634,6 @@ void r300_emit_rs_block_state(struct r300_context* r300, OUT_CS_REG_SEQ(R300_RS_IP_0, count); } OUT_CS_TABLE(rs->ip, count); - for (i = 0; i < count; i++) { - DBG(r300, DBG_DRAW, " : ip %d: 0x%08x\n", i, rs->ip[i]); - } OUT_CS_REG_SEQ(R300_RS_COUNT, 2); OUT_CS(rs->count); @@ -749,13 +645,6 @@ void r300_emit_rs_block_state(struct r300_context* r300, OUT_CS_REG_SEQ(R300_RS_INST_0, count); } OUT_CS_TABLE(rs->inst, count); - for (i = 0; i < count; i++) { - DBG(r300, DBG_DRAW, " : inst %d: 0x%08x\n", i, rs->inst[i]); - } - - DBG(r300, DBG_DRAW, " : count: 0x%08x inst_count: 0x%08x\n", - rs->count, rs->inst_count); - END_CS; } @@ -821,19 +710,11 @@ void r300_emit_aos(struct r300_context* r300, int offset, boolean indexed) struct pipe_vertex_element *velem = r300->velems->velem; struct r300_buffer *buf; int i; + unsigned *hw_format_size = r300->velems->hw_format_size; unsigned size1, size2, aos_count = r300->velems->count; unsigned packet_size = (aos_count * 3 + 1) / 2; CS_LOCALS(r300); - for (i = 0; i < aos_count; i++) { - if ((vbuf[velem[i].vertex_buffer_index].buffer_offset + velem[i].src_offset) % 4 != 0) { - /* XXX We must align the buffer. */ - assert(0); - fprintf(stderr, "r300: Unaligned vertex buffer offsets aren't supported, aborting..\n"); - abort(); - } - } - BEGIN_CS(2 + packet_size + aos_count * 2); OUT_CS_PKT3(R300_PACKET3_3D_LOAD_VBPNTR, packet_size); OUT_CS(aos_count | (!indexed ? R300_VC_FORCE_PREFETCH : 0)); @@ -841,8 +722,8 @@ void r300_emit_aos(struct r300_context* r300, int offset, boolean indexed) for (i = 0; i < aos_count - 1; i += 2) { vb1 = &vbuf[velem[i].vertex_buffer_index]; vb2 = &vbuf[velem[i+1].vertex_buffer_index]; - size1 = util_format_get_blocksize(velem[i].src_format); - size2 = util_format_get_blocksize(velem[i+1].src_format); + size1 = hw_format_size[i]; + size2 = hw_format_size[i+1]; OUT_CS(R300_VBPNTR_SIZE0(size1) | R300_VBPNTR_STRIDE0(vb1->stride) | R300_VBPNTR_SIZE1(size2) | R300_VBPNTR_STRIDE1(vb2->stride)); @@ -852,7 +733,7 @@ void r300_emit_aos(struct r300_context* r300, int offset, boolean indexed) if (aos_count & 1) { vb1 = &vbuf[velem[i].vertex_buffer_index]; - size1 = util_format_get_blocksize(velem[i].src_format); + size1 = hw_format_size[i]; OUT_CS(R300_VBPNTR_SIZE0(size1) | R300_VBPNTR_STRIDE0(vb1->stride)); OUT_CS(vb1->buffer_offset + velem[i].src_offset + offset * vb1->stride); @@ -897,21 +778,25 @@ void r300_emit_vertex_stream_state(struct r300_context* r300, unsigned i; CS_LOCALS(r300); - DBG(r300, DBG_DRAW, "r300: PSC emit:\n"); + if (DBG_ON(r300, DBG_DRAW)) { + fprintf(stderr, "r300: PSC emit:\n"); + + for (i = 0; i < streams->count; i++) { + fprintf(stderr, " : prog_stream_cntl%d: 0x%08x\n", i, + streams->vap_prog_stream_cntl[i]); + } + + for (i = 0; i < streams->count; i++) { + fprintf(stderr, " : prog_stream_cntl_ext%d: 0x%08x\n", i, + streams->vap_prog_stream_cntl_ext[i]); + } + } BEGIN_CS(size); OUT_CS_REG_SEQ(R300_VAP_PROG_STREAM_CNTL_0, streams->count); OUT_CS_TABLE(streams->vap_prog_stream_cntl, streams->count); - for (i = 0; i < streams->count; i++) { - DBG(r300, DBG_DRAW, " : prog_stream_cntl%d: 0x%08x\n", i, - streams->vap_prog_stream_cntl[i]); - } OUT_CS_REG_SEQ(R300_VAP_PROG_STREAM_CNTL_EXT_0, streams->count); OUT_CS_TABLE(streams->vap_prog_stream_cntl_ext, streams->count); - for (i = 0; i < streams->count; i++) { - DBG(r300, DBG_DRAW, " : prog_stream_cntl_ext%d: 0x%08x\n", i, - streams->vap_prog_stream_cntl_ext[i]); - } END_CS; } @@ -924,6 +809,13 @@ void r300_emit_pvs_flush(struct r300_context* r300, unsigned size, void* state) END_CS; } +void r300_emit_vap_invariant_state(struct r300_context *r300, + unsigned size, void *state) +{ + CS_LOCALS(r300); + WRITE_CS_TABLE(state, size); +} + void r300_emit_vs_state(struct r300_context* r300, unsigned size, void* state) { struct r300_vertex_shader* vs = (struct r300_vertex_shader*)state; @@ -948,6 +840,7 @@ void r300_emit_vs_state(struct r300_context* r300, unsigned size, void* state) CS_LOCALS(r300); BEGIN_CS(size); + /* R300_VAP_PVS_CODE_CNTL_0 * R300_VAP_PVS_CONST_CNTL * R300_VAP_PVS_CODE_CNTL_1 @@ -1012,12 +905,7 @@ void r300_emit_viewport_state(struct r300_context* r300, BEGIN_CS(size); OUT_CS_REG_SEQ(R300_SE_VPORT_XSCALE, 6); - OUT_CS_32F(viewport->xscale); - OUT_CS_32F(viewport->xoffset); - OUT_CS_32F(viewport->yscale); - OUT_CS_32F(viewport->yoffset); - OUT_CS_32F(viewport->zscale); - OUT_CS_32F(viewport->zoffset); + OUT_CS_TABLE(&viewport->xscale, 6); OUT_CS_REG(R300_VAP_VTE_CNTL, viewport->vte_control); END_CS; } @@ -1099,10 +987,9 @@ validate: } } /* ...occlusion query buffer... */ - if (r300->query_start.dirty || - (r300->query_current && r300->query_current->begin_emitted)) { - if (!r300_add_buffer(r300->rws, r300->oqbo, - 0, r300_buffer(r300->oqbo)->domain)) { + if (r300->query_current) { + if (!r300->rws->add_buffer(r300->rws, r300->query_current->buffer, + 0, r300->query_current->domain)) { r300->context.flush(&r300->context, 0, NULL); goto validate; } diff --git a/src/gallium/drivers/r300/r300_emit.h b/src/gallium/drivers/r300/r300_emit.h index 9066088342..586ccda620 100644 --- a/src/gallium/drivers/r300/r300_emit.h +++ b/src/gallium/drivers/r300/r300_emit.h @@ -29,6 +29,8 @@ struct rX00_fragment_program_code; struct r300_vertex_program_code; +uint32_t pack_float24(float f); + void r300_emit_aos(struct r300_context* r300, int offset, boolean indexed); void r300_emit_blend_state(struct r300_context* r300, @@ -43,16 +45,12 @@ void r300_emit_clip_state(struct r300_context* r300, void r300_emit_dsa_state(struct r300_context* r300, unsigned size, void* state); -unsigned r300_get_fs_atom_size(struct r300_context *r300); - void r300_emit_fs(struct r300_context* r300, unsigned size, void *state); void r300_emit_fs_constants(struct r300_context* r300, unsigned size, void *state); void r300_emit_fs_rc_constant_state(struct r300_context* r300, unsigned size, void *state); -unsigned r500_get_fs_atom_size(struct r300_context *r300); - void r500_emit_fs(struct r300_context* r300, unsigned size, void *state); void r500_emit_fs_constants(struct r300_context* r300, unsigned size, void *state); @@ -61,6 +59,16 @@ void r500_emit_fs_rc_constant_state(struct r300_context* r300, unsigned size, vo void r300_emit_fb_state(struct r300_context* r300, unsigned size, void* state); +void r300_emit_fb_state_pipelined(struct r300_context *r300, + unsigned size, void *state); + +void r300_emit_gpu_flush(struct r300_context *r300, unsigned size, void *state); + +void r300_emit_hyperz_state(struct r300_context *r300, + unsigned size, void *state); + +void r300_emit_aa_state(struct r300_context *r300, unsigned size, void *state); + void r300_emit_query_start(struct r300_context *r300, unsigned size, void *state); void r300_emit_query_end(struct r300_context* r300); @@ -78,6 +86,9 @@ void r300_emit_textures_state(struct r300_context *r300, void r300_emit_aos_swtcl(struct r300_context *r300, boolean indexed); +void r300_emit_vap_invariant_state(struct r300_context *r300, + unsigned size, void *state); + void r300_emit_vertex_stream_state(struct r300_context* r300, unsigned size, void* state); @@ -96,6 +107,9 @@ void r300_emit_pvs_flush(struct r300_context* r300, unsigned size, void* state); void r300_emit_texture_cache_inval(struct r300_context* r300, unsigned size, void* state); +void r300_emit_invariant_state(struct r300_context *r300, + unsigned size, void *state); + unsigned r300_get_num_dirty_dwords(struct r300_context *r300); /* Emit all dirty state. */ diff --git a/src/gallium/drivers/r300/r300_flush.c b/src/gallium/drivers/r300/r300_flush.c index 360b19a0c1..ba840bfff8 100644 --- a/src/gallium/drivers/r300/r300_flush.c +++ b/src/gallium/drivers/r300/r300_flush.c @@ -39,8 +39,6 @@ static void r300_flush(struct pipe_context* pipe, struct r300_atom *atom; struct r300_fence **rfence = (struct r300_fence**)fence; - CS_LOCALS(r300); - (void) cs_count; /* We probably need to flush Draw, but we may have been called from * within Draw. This feels kludgy, but it might be the best thing. * @@ -52,7 +50,10 @@ static void r300_flush(struct pipe_context* pipe, if (r300->dirty_hw) { r300_emit_query_end(r300); - FLUSH_CS; + if (SCREEN_DBG_ON(r300->screen, DBG_STATS)) { + r300->flush_counter++; + } + r300->rws->flush_cs(r300->rws); r300->dirty_hw = 0; /* New kitchen sink, baby. */ diff --git a/src/gallium/drivers/r300/r300_fs.c b/src/gallium/drivers/r300/r300_fs.c index a434808046..424f831731 100644 --- a/src/gallium/drivers/r300/r300_fs.c +++ b/src/gallium/drivers/r300/r300_fs.c @@ -28,7 +28,9 @@ #include "tgsi/tgsi_dump.h" #include "tgsi/tgsi_ureg.h" +#include "r300_cb.h" #include "r300_context.h" +#include "r300_emit.h" #include "r300_screen.h" #include "r300_fs.h" #include "r300_reg.h" @@ -229,6 +231,122 @@ static void r300_dummy_fragment_shader( ureg_destroy(ureg); } +static void r300_emit_fs_code_to_buffer( + struct r300_context *r300, + struct r300_fragment_shader_code *shader) +{ + struct rX00_fragment_program_code *generic_code = &shader->code; + unsigned imm_count = shader->immediates_count; + unsigned imm_first = shader->externals_count; + unsigned imm_end = generic_code->constants.Count; + struct rc_constant *constants = generic_code->constants.Constants; + unsigned i; + CB_LOCALS; + + if (r300->screen->caps.is_r500) { + struct r500_fragment_program_code *code = &generic_code->code.r500; + + shader->cb_code_size = 17 + + ((code->inst_end + 1) * 6) + + imm_count * 7; + + NEW_CB(shader->cb_code, shader->cb_code_size); + OUT_CB_REG(R500_US_CONFIG, R500_ZERO_TIMES_ANYTHING_EQUALS_ZERO); + OUT_CB_REG(R500_US_PIXSIZE, code->max_temp_idx); + OUT_CB_REG(R500_US_CODE_RANGE, + R500_US_CODE_RANGE_ADDR(0) | R500_US_CODE_RANGE_SIZE(code->inst_end)); + OUT_CB_REG(R500_US_CODE_OFFSET, 0); + OUT_CB_REG(R500_US_CODE_ADDR, + R500_US_CODE_START_ADDR(0) | R500_US_CODE_END_ADDR(code->inst_end)); + + OUT_CB_REG(R500_GA_US_VECTOR_INDEX, R500_GA_US_VECTOR_INDEX_TYPE_INSTR); + OUT_CB_ONE_REG(R500_GA_US_VECTOR_DATA, (code->inst_end + 1) * 6); + for (i = 0; i <= code->inst_end; i++) { + OUT_CB(code->inst[i].inst0); + OUT_CB(code->inst[i].inst1); + OUT_CB(code->inst[i].inst2); + OUT_CB(code->inst[i].inst3); + OUT_CB(code->inst[i].inst4); + OUT_CB(code->inst[i].inst5); + } + + /* Emit immediates. */ + if (imm_count) { + for(i = imm_first; i < imm_end; ++i) { + if (constants[i].Type == RC_CONSTANT_IMMEDIATE) { + const float *data = constants[i].u.Immediate; + + OUT_CB_REG(R500_GA_US_VECTOR_INDEX, + R500_GA_US_VECTOR_INDEX_TYPE_CONST | + (i & R500_GA_US_VECTOR_INDEX_MASK)); + OUT_CB_ONE_REG(R500_GA_US_VECTOR_DATA, 4); + OUT_CB_TABLE(data, 4); + } + } + } + } else { /* r300 */ + struct r300_fragment_program_code *code = &generic_code->code.r300; + + shader->cb_code_size = 19 + + (r300->screen->caps.is_r400 ? 2 : 0) + + code->alu.length * 4 + + (code->tex.length ? (1 + code->tex.length) : 0) + + imm_count * 5; + + NEW_CB(shader->cb_code, shader->cb_code_size); + + if (r300->screen->caps.is_r400) + OUT_CB_REG(R400_US_CODE_BANK, 0); + + OUT_CB_REG(R300_US_CONFIG, code->config); + OUT_CB_REG(R300_US_PIXSIZE, code->pixsize); + OUT_CB_REG(R300_US_CODE_OFFSET, code->code_offset); + + OUT_CB_REG_SEQ(R300_US_CODE_ADDR_0, 4); + OUT_CB_TABLE(code->code_addr, 4); + + OUT_CB_REG_SEQ(R300_US_ALU_RGB_INST_0, code->alu.length); + for (i = 0; i < code->alu.length; i++) + OUT_CB(code->alu.inst[i].rgb_inst); + + OUT_CB_REG_SEQ(R300_US_ALU_RGB_ADDR_0, code->alu.length); + for (i = 0; i < code->alu.length; i++) + OUT_CB(code->alu.inst[i].rgb_addr); + + OUT_CB_REG_SEQ(R300_US_ALU_ALPHA_INST_0, code->alu.length); + for (i = 0; i < code->alu.length; i++) + OUT_CB(code->alu.inst[i].alpha_inst); + + OUT_CB_REG_SEQ(R300_US_ALU_ALPHA_ADDR_0, code->alu.length); + for (i = 0; i < code->alu.length; i++) + OUT_CB(code->alu.inst[i].alpha_addr); + + if (code->tex.length) { + OUT_CB_REG_SEQ(R300_US_TEX_INST_0, code->tex.length); + OUT_CB_TABLE(code->tex.inst, code->tex.length); + } + + /* Emit immediates. */ + if (imm_count) { + for(i = imm_first; i < imm_end; ++i) { + if (constants[i].Type == RC_CONSTANT_IMMEDIATE) { + const float *data = constants[i].u.Immediate; + + OUT_CB_REG_SEQ(R300_PFS_PARAM_0_X + i * 16, 4); + OUT_CB(pack_float24(data[0])); + OUT_CB(pack_float24(data[1])); + OUT_CB(pack_float24(data[2])); + OUT_CB(pack_float24(data[3])); + } + } + } + } + + OUT_CB_REG(R300_FG_DEPTH_SRC, shader->fg_depth_src); + OUT_CB_REG(R300_US_W_FMT, shader->us_out_w); + END_CB; +} + static void r300_translate_fragment_shader( struct r300_context* r300, struct r300_fragment_shader_code* shader, @@ -338,6 +456,9 @@ static void r300_translate_fragment_shader( /* And, finally... */ rc_destroy(&compiler.Base); + + /* Build the command buffer. */ + r300_emit_fs_code_to_buffer(r300, shader); } boolean r300_pick_fragment_shader(struct r300_context* r300) diff --git a/src/gallium/drivers/r300/r300_fs.h b/src/gallium/drivers/r300/r300_fs.h index 1cc4355359..51bfa88c5e 100644 --- a/src/gallium/drivers/r300/r300_fs.h +++ b/src/gallium/drivers/r300/r300_fs.h @@ -50,6 +50,9 @@ struct r300_fragment_shader_code { struct r300_fragment_program_external_state compare_state; struct rX00_fragment_program_code code; + unsigned cb_code_size; + uint32_t *cb_code; + struct r300_fragment_shader_code* next; }; diff --git a/src/gallium/drivers/r300/r300_hyperz.c b/src/gallium/drivers/r300/r300_hyperz.c index b41b6b1508..e5c7658952 100644 --- a/src/gallium/drivers/r300/r300_hyperz.c +++ b/src/gallium/drivers/r300/r300_hyperz.c @@ -31,33 +31,46 @@ /* The ZTOP state */ /*****************************************************************************/ -static boolean r300_dsa_writes_depth_stencil(struct r300_dsa_state* dsa) +static boolean r300_dsa_writes_stencil( + struct pipe_stencil_state *s) { - /* We are interested only in the cases when a new depth or stencil value - * can be written and changed. */ + return s->enabled && s->writemask && + (s->fail_op != PIPE_STENCIL_OP_KEEP || + s->zfail_op != PIPE_STENCIL_OP_KEEP || + s->zpass_op != PIPE_STENCIL_OP_KEEP); +} + +static boolean r300_dsa_writes_depth_stencil( + struct pipe_depth_stencil_alpha_state *dsa) +{ + /* We are interested only in the cases when a depth or stencil value + * can be changed. */ + + if (dsa->depth.enabled && dsa->depth.writemask && + dsa->depth.func != PIPE_FUNC_NEVER) + return TRUE; + + if (r300_dsa_writes_stencil(&dsa->stencil[0]) || + r300_dsa_writes_stencil(&dsa->stencil[1])) + return TRUE; - /* We might optionally check for [Z func: never] and inspect the stencil - * state in a similar fashion, but it's not terribly important. */ - return (dsa->z_buffer_control & R300_Z_WRITE_ENABLE) || - (dsa->stencil_ref_mask & R300_STENCILWRITEMASK_MASK) || - ((dsa->z_buffer_control & R500_STENCIL_REFMASK_FRONT_BACK) && - (dsa->stencil_ref_bf & R300_STENCILWRITEMASK_MASK)); + return FALSE; } -static boolean r300_dsa_alpha_test_enabled(struct r300_dsa_state* dsa) +static boolean r300_dsa_alpha_test_enabled( + struct pipe_depth_stencil_alpha_state *dsa) { /* We are interested only in the cases when alpha testing can kill * a fragment. */ - uint32_t af = dsa->alpha_function; - return (af & R300_FG_ALPHA_FUNC_ENABLE) && - (af & R300_FG_ALPHA_FUNC_ALWAYS) != R300_FG_ALPHA_FUNC_ALWAYS; + return dsa->alpha.enabled && dsa->alpha.func != PIPE_FUNC_ALWAYS; } static void r300_update_ztop(struct r300_context* r300) { struct r300_ztop_state* ztop_state = (struct r300_ztop_state*)r300->ztop_state.state; + uint32_t old_ztop = ztop_state->z_buffer_top; /* This is important enough that I felt it warranted a comment. * @@ -99,7 +112,8 @@ static void r300_update_ztop(struct r300_context* r300) ztop_state->z_buffer_top = R300_ZTOP_ENABLE; } - r300->ztop_state.dirty = TRUE; + if (ztop_state->z_buffer_top != old_ztop) + r300->ztop_state.dirty = TRUE; } void r300_update_hyperz_state(struct r300_context* r300) diff --git a/src/gallium/drivers/r300/r300_query.c b/src/gallium/drivers/r300/r300_query.c index 97081c4a00..10086ee925 100644 --- a/src/gallium/drivers/r300/r300_query.c +++ b/src/gallium/drivers/r300/r300_query.c @@ -26,6 +26,7 @@ #include "r300_context.h" #include "r300_screen.h" #include "r300_emit.h" +#include "r300_winsys.h" #include <stdio.h> @@ -34,30 +35,29 @@ static struct pipe_query *r300_create_query(struct pipe_context *pipe, { struct r300_context *r300 = r300_context(pipe); struct r300_screen *r300screen = r300->screen; - unsigned query_size; - struct r300_query *q, *qptr; + struct r300_query *q; + + if (query_type != PIPE_QUERY_OCCLUSION_COUNTER) { + return NULL; + } q = CALLOC_STRUCT(r300_query); + if (!q) + return NULL; q->type = query_type; - assert(q->type == PIPE_QUERY_OCCLUSION_COUNTER); + q->domain = R300_DOMAIN_GTT; + q->buffer_size = 4096; if (r300screen->caps.family == CHIP_FAMILY_RV530) - query_size = r300screen->caps.num_z_pipes * sizeof(uint32_t); + q->num_pipes = r300screen->caps.num_z_pipes; else - query_size = r300screen->caps.num_frag_pipes * sizeof(uint32_t); + q->num_pipes = r300screen->caps.num_frag_pipes; - if (!is_empty_list(&r300->query_list)) { - qptr = last_elem(&r300->query_list); - q->offset = qptr->offset + query_size; - } insert_at_tail(&r300->query_list, q); - /* XXX */ - if (q->offset >= 4096) { - q->offset = 0; - fprintf(stderr, "r300: Rewinding OQBO...\n"); - } + /* Open up the occlusion query buffer. */ + q->buffer = r300->rws->buffer_create(r300->rws, 4096, 0, q->domain, q->buffer_size); return (struct pipe_query*)q; } @@ -65,18 +65,26 @@ static struct pipe_query *r300_create_query(struct pipe_context *pipe, static void r300_destroy_query(struct pipe_context* pipe, struct pipe_query* query) { - struct r300_query* q = (struct r300_query*)query; + struct r300_context *r300 = r300_context(pipe); + struct r300_query* q = r300_query(query); + r300->rws->buffer_reference(r300->rws, &q->buffer, NULL); remove_from_list(q); FREE(query); } +void r300_resume_query(struct r300_context *r300, + struct r300_query *query) +{ + r300->query_current = query; + r300->query_start.dirty = TRUE; +} + static void r300_begin_query(struct pipe_context* pipe, struct pipe_query* query) { - uint32_t value = ~0U; struct r300_context* r300 = r300_context(pipe); - struct r300_query* q = (struct r300_query*)query; + struct r300_query* q = r300_query(query); if (r300->query_current != NULL) { fprintf(stderr, "r300: begin_query: " @@ -85,85 +93,59 @@ static void r300_begin_query(struct pipe_context* pipe, return; } - pipe_buffer_write(pipe, - r300->oqbo, - q->offset, - sizeof value, - &value); + q->num_results = 0; + r300_resume_query(r300, q); +} - q->flushed = FALSE; - r300->query_current = q; - r300->query_start.dirty = TRUE; +void r300_stop_query(struct r300_context *r300) +{ + r300_emit_query_end(r300); + r300->query_current = NULL; } static void r300_end_query(struct pipe_context* pipe, struct pipe_query* query) { struct r300_context* r300 = r300_context(pipe); + struct r300_query *q = r300_query(query); - if ((struct r300_query*)query != r300->query_current) { + if (q != r300->query_current) { fprintf(stderr, "r300: end_query: Got invalid query.\n"); assert(0); return; } - r300_emit_query_end(r300); - r300->query_current = NULL; + r300_stop_query(r300); } static boolean r300_get_query_result(struct pipe_context* pipe, struct pipe_query* query, boolean wait, - uint64_t* result) + void* vresult) { struct r300_context* r300 = r300_context(pipe); - struct r300_screen* r300screen = r300->screen; - struct r300_query *q = (struct r300_query*)query; - struct pipe_transfer *transfer; - unsigned flags = PIPE_TRANSFER_READ; - uint32_t* map; - uint32_t temp = 0; - unsigned i, num_results; - - if (q->flushed == FALSE) + struct r300_query *q = r300_query(query); + unsigned flags, i; + uint32_t temp, *map; + uint64_t *result = (uint64_t*)vresult; + + if (!q->flushed) pipe->flush(pipe, 0, NULL); - if (!wait) { - flags |= PIPE_TRANSFER_DONTBLOCK; - } - map = pipe_buffer_map(pipe, r300->oqbo, flags, &transfer); + flags = PIPE_TRANSFER_READ | (!wait ? PIPE_TRANSFER_DONTBLOCK : 0); + + map = r300->rws->buffer_map(r300->rws, q->buffer, flags); if (!map) return FALSE; - map += q->offset / 4; - if (r300screen->caps.family == CHIP_FAMILY_RV530) - num_results = r300screen->caps.num_z_pipes; - else - num_results = r300screen->caps.num_frag_pipes; - - for (i = 0; i < num_results; i++) { - if (*map == ~0U) { - /* Looks like our results aren't ready yet. */ - if (wait) { - fprintf(stderr, "r300: Despite waiting, OQ results haven't " - "come in yet. This is a driver bug.\n" - "r300: Returning bogus results to avoid " - "a possible infinite loop...\n"); - temp = 987654321; - } else { - temp = ~0U; - } - break; - } + /* Sum up the results. */ + temp = 0; + for (i = 0; i < q->num_results; i++) { temp += *map; map++; } - pipe_buffer_unmap(pipe, r300->oqbo, transfer); - if (temp == ~0U) { - /* Our results haven't been written yet... */ - return FALSE; - } + r300->rws->buffer_unmap(r300->rws, q->buffer); *result = temp; return TRUE; @@ -191,11 +173,61 @@ static void r300_render_condition(struct pipe_context *pipe, } } +/*************************************************************************** + * Fake occlusion queries (for debugging) + ***************************************************************************/ + +static unsigned r300_fake_query; + +static struct pipe_query *r300_fake_create_query(struct pipe_context *pipe, + unsigned query_type) +{ + return (struct pipe_query*)&r300_fake_query; +} + +static void r300_fake_destroy_query(struct pipe_context* pipe, + struct pipe_query* query) +{ +} + +static void r300_fake_begin_query(struct pipe_context* pipe, + struct pipe_query* query) +{ +} + +static void r300_fake_end_query(struct pipe_context* pipe, + struct pipe_query* query) +{ +} + +static boolean r300_fake_get_query_result(struct pipe_context* pipe, + struct pipe_query* query, + boolean wait, void* vresult) +{ + uint64_t *result = (uint64_t*)vresult; + *result = 1000000; + return TRUE; +} + +static void r300_fake_render_condition(struct pipe_context *pipe, + struct pipe_query *query, uint mode) +{ +} + void r300_init_query_functions(struct r300_context* r300) { - r300->context.create_query = r300_create_query; - r300->context.destroy_query = r300_destroy_query; - r300->context.begin_query = r300_begin_query; - r300->context.end_query = r300_end_query; - r300->context.get_query_result = r300_get_query_result; - r300->context.render_condition = r300_render_condition; + if (DBG_ON(r300, DBG_FAKE_OCC)) { + r300->context.create_query = r300_fake_create_query; + r300->context.destroy_query = r300_fake_destroy_query; + r300->context.begin_query = r300_fake_begin_query; + r300->context.end_query = r300_fake_end_query; + r300->context.get_query_result = r300_fake_get_query_result; + r300->context.render_condition = r300_fake_render_condition; + } else { + r300->context.create_query = r300_create_query; + r300->context.destroy_query = r300_destroy_query; + r300->context.begin_query = r300_begin_query; + r300->context.end_query = r300_end_query; + r300->context.get_query_result = r300_get_query_result; + r300->context.render_condition = r300_render_condition; + } } diff --git a/src/gallium/drivers/r300/r300_reg.h b/src/gallium/drivers/r300/r300_reg.h index c4fa19ace5..180560175a 100644 --- a/src/gallium/drivers/r300/r300_reg.h +++ b/src/gallium/drivers/r300/r300_reg.h @@ -1630,6 +1630,40 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. # define R300_TX_FORMAT_GAMMA (1 << 21) # define R300_TX_FORMAT_YUV_TO_RGB (1 << 22) +# define R300_TX_CACHE(x) ((x) << 27) +# define R300_TX_CACHE_WHOLE 0 +/* reserved */ +# define R300_TX_CACHE_HALF_0 2 +# define R300_TX_CACHE_HALF_1 3 +# define R300_TX_CACHE_FOURTH_0 4 +# define R300_TX_CACHE_FOURTH_1 5 +# define R300_TX_CACHE_FOURTH_2 6 +# define R300_TX_CACHE_FOURTH_3 7 +# define R300_TX_CACHE_EIGHTH_0 8 +# define R300_TX_CACHE_EIGHTH_1 9 +# define R300_TX_CACHE_EIGHTH_2 10 +# define R300_TX_CACHE_EIGHTH_3 11 +# define R300_TX_CACHE_EIGHTH_4 12 +# define R300_TX_CACHE_EIGHTH_5 13 +# define R300_TX_CACHE_EIGHTH_6 14 +# define R300_TX_CACHE_EIGHTH_7 15 +# define R300_TX_CACHE_SIXTEENTH_0 16 +# define R300_TX_CACHE_SIXTEENTH_1 17 +# define R300_TX_CACHE_SIXTEENTH_2 18 +# define R300_TX_CACHE_SIXTEENTH_3 19 +# define R300_TX_CACHE_SIXTEENTH_4 20 +# define R300_TX_CACHE_SIXTEENTH_5 21 +# define R300_TX_CACHE_SIXTEENTH_6 22 +# define R300_TX_CACHE_SIXTEENTH_7 23 +# define R300_TX_CACHE_SIXTEENTH_8 24 +# define R300_TX_CACHE_SIXTEENTH_9 25 +# define R300_TX_CACHE_SIXTEENTH_10 26 +# define R300_TX_CACHE_SIXTEENTH_11 27 +# define R300_TX_CACHE_SIXTEENTH_12 28 +# define R300_TX_CACHE_SIXTEENTH_13 29 +# define R300_TX_CACHE_SIXTEENTH_14 30 +# define R300_TX_CACHE_SIXTEENTH_15 31 + #define R300_TX_FORMAT2_0 0x4500 /* obvious missing in gap */ # define R300_TX_PITCHMASK_SHIFT 0 # define R300_TX_PITCHMASK_MASK (2047 << 0) @@ -2639,6 +2673,24 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. /* Z Buffer Clear Value */ #define R300_ZB_DEPTHCLEARVALUE 0x4f28 +/* Z Mask RAM is a Z compression buffer. + * Each dword of the Z Mask contains compression info for 16 4x4 pixel blocks, + * that is 2 bits for each block. + * On chips with 2 Z pipes, every other dword maps to a different pipe. + */ + +/* The dword offset into Z mask RAM (bits 18:4) */ +#define R300_ZB_ZMASK_OFFSET 0x4f30 + +/* Z Mask Pitch. */ +#define R300_ZB_ZMASK_PITCH 0x4f34 + +/* Access to Z Mask RAM in a manner similar to HiZ RAM. + * The indices are autoincrementing. */ +#define R300_ZB_ZMASK_WRINDEX 0x4f38 +#define R300_ZB_ZMASK_DWORD 0x4f3c +#define R300_ZB_ZMASK_RDINDEX 0x4f40 + /* Hierarchical Z Memory Offset */ #define R300_ZB_HIZ_OFFSET 0x4f44 @@ -3437,9 +3489,18 @@ enum { # define RADEON_WAIT_3D_IDLECLEAN (1 << 17) # define RADEON_WAIT_HOST_IDLECLEAN (1 << 18) +#define R200_3D_DRAW_IMMD_2 0xC0003500 + +#define RADEON_CP_PACKET0 0x0 /* XXX stolen from radeon_reg.h */ #define RADEON_CP_PACKET3 0xC0000000 -#define R200_3D_DRAW_IMMD_2 0xC0003500 +#define RADEON_ONE_REG_WR (1 << 15) + +#define CP_PACKET0(register, count) \ + (RADEON_CP_PACKET0 | ((count) << 16) | ((register) >> 2)) + +#define CP_PACKET3(op, count) \ + (RADEON_CP_PACKET3 | (op) | ((count) << 16)) #endif /* _R300_REG_H */ diff --git a/src/gallium/drivers/r300/r300_render.c b/src/gallium/drivers/r300/r300_render.c index 23caaa5473..53728431a6 100644 --- a/src/gallium/drivers/r300/r300_render.c +++ b/src/gallium/drivers/r300/r300_render.c @@ -35,6 +35,7 @@ #include "util/u_prim.h" #include "r300_cs.h" +#include "r300_cb.h" #include "r300_context.h" #include "r300_screen_buffer.h" #include "r300_emit.h" @@ -43,6 +44,8 @@ #include <limits.h> +#define IMMD_DWORDS 32 + static uint32_t r300_translate_primitive(unsigned prim) { switch (prim) { @@ -269,7 +272,7 @@ static boolean immd_is_good_idea(struct r300_context *r300, return FALSE; } - if (count > 10) { + if (count * r300->velems->vertex_size_dwords > IMMD_DWORDS) { return FALSE; } @@ -308,84 +311,75 @@ static void r300_emit_draw_arrays_immediate(struct r300_context *r300, struct pipe_vertex_element* velem; struct pipe_vertex_buffer* vbuf; unsigned vertex_element_count = r300->velems->count; - unsigned i, v, vbi, dw, elem_offset, dwords; + unsigned i, v, vbi, dwords; /* Size of the vertex, in dwords. */ - unsigned vertex_size = 0; - - /* Offsets of the attribute, in dwords, from the start of the vertex. */ - unsigned offset[PIPE_MAX_ATTRIBS]; + unsigned vertex_size = r300->velems->vertex_size_dwords; /* Size of the vertex element, in dwords. */ unsigned size[PIPE_MAX_ATTRIBS]; /* Stride to the same attrib in the next vertex in the vertex buffer, * in dwords. */ - unsigned stride[PIPE_MAX_ATTRIBS] = {0}; + unsigned stride[PIPE_MAX_ATTRIBS]; /* Mapped vertex buffers. */ - uint32_t* map[PIPE_MAX_ATTRIBS] = {0}; - struct pipe_transfer* transfer[PIPE_MAX_ATTRIBS] = {NULL}; + uint32_t* map[PIPE_MAX_ATTRIBS]; + uint32_t* mapelem[PIPE_MAX_ATTRIBS]; + struct pipe_transfer* transfer[PIPE_MAX_ATTRIBS] = {0}; - CS_LOCALS(r300); + CB_LOCALS; /* Calculate the vertex size, offsets, strides etc. and map the buffers. */ for (i = 0; i < vertex_element_count; i++) { velem = &r300->velems->velem[i]; - offset[i] = velem->src_offset / 4; - size[i] = util_format_get_blocksize(velem->src_format) / 4; - vertex_size += size[i]; + size[i] = r300->velems->hw_format_size[i] / 4; vbi = velem->vertex_buffer_index; + vbuf = &r300->vertex_buffer[vbi]; + stride[i] = vbuf->stride / 4; /* Map the buffer. */ - if (!map[vbi]) { - vbuf = &r300->vertex_buffer[vbi]; + if (!transfer[vbi]) { map[vbi] = (uint32_t*)pipe_buffer_map(&r300->context, vbuf->buffer, PIPE_TRANSFER_READ, &transfer[vbi]); - map[vbi] += vbuf->buffer_offset / 4; - stride[vbi] = vbuf->stride / 4; + map[vbi] += (vbuf->buffer_offset / 4) + stride[i] * start; } + mapelem[i] = map[vbi] + (velem->src_offset / 4); } dwords = 9 + count * vertex_size; r300_prepare_for_rendering(r300, PREP_FIRST_DRAW, NULL, dwords, 0, 0, NULL); - BEGIN_CS(dwords); - OUT_CS_REG(R300_GA_COLOR_CONTROL, + BEGIN_CS_AS_CB(r300, dwords); + OUT_CB_REG(R300_GA_COLOR_CONTROL, r300_provoking_vertex_fixes(r300, mode)); - OUT_CS_REG(R300_VAP_VTX_SIZE, vertex_size); - OUT_CS_REG_SEQ(R300_VAP_VF_MAX_VTX_INDX, 2); - OUT_CS(count - 1); - OUT_CS(0); - OUT_CS_PKT3(R300_PACKET3_3D_DRAW_IMMD_2, count * vertex_size); - OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_EMBEDDED | (count << 16) | + OUT_CB_REG(R300_VAP_VTX_SIZE, vertex_size); + OUT_CB_REG_SEQ(R300_VAP_VF_MAX_VTX_INDX, 2); + OUT_CB(count - 1); + OUT_CB(0); + OUT_CB_PKT3(R300_PACKET3_3D_DRAW_IMMD_2, count * vertex_size); + OUT_CB(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_EMBEDDED | (count << 16) | r300_translate_primitive(mode)); /* Emit vertices. */ for (v = 0; v < count; v++) { for (i = 0; i < vertex_element_count; i++) { - velem = &r300->velems->velem[i]; - vbi = velem->vertex_buffer_index; - elem_offset = offset[i] + stride[vbi] * (v + start); - - for (dw = 0; dw < size[i]; dw++) { - OUT_CS(map[vbi][elem_offset + dw]); - } + OUT_CB_TABLE(&mapelem[i][stride[i] * v], size[i]); } } - END_CS; + END_CB; /* Unmap buffers. */ for (i = 0; i < vertex_element_count; i++) { vbi = r300->velems->velem[i].vertex_buffer_index; - if (map[vbi]) { + if (transfer[vbi]) { vbuf = &r300->vertex_buffer[vbi]; pipe_buffer_unmap(&r300->context, vbuf->buffer, transfer[vbi]); - map[vbi] = NULL; + transfer[vbi] = NULL; } } } @@ -482,111 +476,6 @@ static void r300_emit_draw_elements(struct r300_context *r300, END_CS; } -static void r300_shorten_ubyte_elts(struct r300_context* r300, - struct pipe_resource** elts, - int index_bias, - unsigned start, - unsigned count) -{ - struct pipe_context* context = &r300->context; - struct pipe_screen* screen = r300->context.screen; - struct pipe_resource* new_elts; - unsigned char *in_map; - unsigned short *out_map; - struct pipe_transfer *src_transfer, *dst_transfer; - unsigned i; - - new_elts = pipe_buffer_create(screen, - PIPE_BIND_INDEX_BUFFER, - 2 * count); - - in_map = pipe_buffer_map(context, *elts, PIPE_TRANSFER_READ, &src_transfer); - out_map = pipe_buffer_map(context, new_elts, PIPE_TRANSFER_WRITE, &dst_transfer); - - in_map += start; - - for (i = 0; i < count; i++) { - *out_map = (unsigned short)(*in_map + index_bias); - in_map++; - out_map++; - } - - pipe_buffer_unmap(context, *elts, src_transfer); - pipe_buffer_unmap(context, new_elts, dst_transfer); - - *elts = new_elts; -} - -static void r300_rebuild_ushort_elts(struct r300_context *r300, - struct pipe_resource **elts, - int index_bias, - unsigned start, unsigned count) -{ - struct pipe_context *context = &r300->context; - struct pipe_transfer *in_transfer = NULL; - struct pipe_transfer *out_transfer = NULL; - struct pipe_resource *new_elts; - unsigned short *in_map; - unsigned short *out_map; - unsigned i; - - new_elts = pipe_buffer_create(context->screen, - PIPE_BIND_INDEX_BUFFER, - 2 * count); - - in_map = pipe_buffer_map(context, *elts, - PIPE_TRANSFER_READ, &in_transfer); - out_map = pipe_buffer_map(context, new_elts, - PIPE_TRANSFER_WRITE, &out_transfer); - - in_map += start; - for (i = 0; i < count; i++) { - *out_map = (unsigned short)(*in_map + index_bias); - in_map++; - out_map++; - } - - pipe_buffer_unmap(context, *elts, in_transfer); - pipe_buffer_unmap(context, new_elts, out_transfer); - - *elts = new_elts; -} - -static void r300_rebuild_uint_elts(struct r300_context *r300, - struct pipe_resource **elts, - int index_bias, - unsigned start, unsigned count) -{ - struct pipe_context *context = &r300->context; - struct pipe_transfer *in_transfer = NULL; - struct pipe_transfer *out_transfer = NULL; - struct pipe_resource *new_elts; - unsigned int *in_map; - unsigned int *out_map; - unsigned i; - - new_elts = pipe_buffer_create(context->screen, - PIPE_BIND_INDEX_BUFFER, - 2 * count); - - in_map = pipe_buffer_map(context, *elts, - PIPE_TRANSFER_READ, &in_transfer); - out_map = pipe_buffer_map(context, new_elts, - PIPE_TRANSFER_WRITE, &out_transfer); - - in_map += start; - for (i = 0; i < count; i++) { - *out_map = (unsigned int)(*in_map + index_bias); - in_map++; - out_map++; - } - - pipe_buffer_unmap(context, *elts, in_transfer); - pipe_buffer_unmap(context, new_elts, out_transfer); - - *elts = new_elts; -} - /* This is the fast-path drawing & emission for HW TCL. */ static void r300_draw_range_elements(struct pipe_context* pipe, struct pipe_resource* indexBuffer, @@ -605,6 +494,7 @@ static void r300_draw_range_elements(struct pipe_context* pipe, r300->rws->get_value(r300->rws, R300_VID_DRM_2_3_0); unsigned short_count; int buffer_offset = 0, index_offset = 0; /* for index bias emulation */ + boolean translate = FALSE; if (r300->skip_rendering) { return; @@ -614,33 +504,25 @@ static void r300_draw_range_elements(struct pipe_context* pipe, return; } - if (indexBias && !index_bias_supported(r300)) { - r300_split_index_bias(r300, indexBias, &buffer_offset, &index_offset); + /* Index buffer range checking. */ + if ((start + count) * indexSize > indexBuffer->width0) { + fprintf(stderr, "r300: Invalid index buffer range. Skipping rendering.\n"); + return; } - /* Rebuild the index buffer if needed. */ - switch (indexSize) { - case 1: - r300_shorten_ubyte_elts(r300, &indexBuffer, index_offset, start, count); - indexSize = 2; - start = 0; - break; - - case 2: - if (start % 2 != 0 || index_offset) { - r300_rebuild_ushort_elts(r300, &indexBuffer, index_offset, start, count); - start = 0; - } - break; + /* Set up fallback for incompatible vertex layout if needed. */ + if (r300->incompatible_vb_layout || r300->velems->incompatible_layout) { + r300_begin_vertex_translate(r300); + translate = TRUE; + } - case 4: - if (index_offset) { - r300_rebuild_uint_elts(r300, &indexBuffer, index_offset, start, count); - start = 0; - } - break; + if (indexBias && !index_bias_supported(r300)) { + r300_split_index_bias(r300, indexBias, &buffer_offset, &index_offset); } + r300_translate_index_buffer(r300, &indexBuffer, &indexSize, index_offset, + &start, count); + r300_update_derived_state(r300); r300_upload_index_buffer(r300, &indexBuffer, indexSize, start, count); @@ -676,6 +558,10 @@ static void r300_draw_range_elements(struct pipe_context* pipe, if (indexBuffer != orgIndexBuffer) { pipe_resource_reference( &indexBuffer, NULL ); } + + if (translate) { + r300_end_vertex_translate(r300); + } } /* Simple helpers for context setup. Should probably be moved to util. */ @@ -699,6 +585,7 @@ static void r300_draw_arrays(struct pipe_context* pipe, unsigned mode, count > 65536 && r300->rws->get_value(r300->rws, R300_VID_DRM_2_3_0); unsigned short_count; + boolean translate = FALSE; if (r300->skip_rendering) { return; @@ -708,6 +595,12 @@ static void r300_draw_arrays(struct pipe_context* pipe, unsigned mode, return; } + /* Set up fallback for incompatible vertex layout if needed. */ + if (r300->incompatible_vb_layout || r300->velems->incompatible_layout) { + r300_begin_vertex_translate(r300); + translate = TRUE; + } + r300_update_derived_state(r300); if (immd_is_good_idea(r300, count)) { @@ -737,6 +630,10 @@ static void r300_draw_arrays(struct pipe_context* pipe, unsigned mode, } u_upload_flush(r300->upload_vb); } + + if (translate) { + r300_end_vertex_translate(r300); + } } /**************************************************************************** @@ -1016,7 +913,7 @@ static void r300_render_draw_elements(struct vbuf_render* render, unsigned max_index = (r300render->vbo_size - r300render->vbo_offset) / (r300render->r300->vertex_info.size * 4) - 1; unsigned short_count; - struct r300_cs_info cs_info; + unsigned free_dwords; CS_LOCALS(r300); @@ -1029,9 +926,9 @@ static void r300_render_draw_elements(struct vbuf_render* render, NULL, 256, 0, 0, &end_cs_dwords); while (count) { - r300->rws->get_cs_info(r300->rws, &cs_info); + free_dwords = r300->rws->get_cs_free_dwords(r300->rws); - short_count = MIN2(count, (cs_info.free - end_cs_dwords - 6) * 2); + short_count = MIN2(count, (free_dwords - end_cs_dwords - 6) * 2); BEGIN_CS(6 + (short_count+1)/2); OUT_CS_REG(R300_GA_COLOR_CONTROL, @@ -1117,132 +1014,45 @@ struct draw_stage* r300_draw_stage(struct r300_context* r300) } /**************************************************************************** - * Two-sided stencil reference value fallback. It's designed to be as much - * separate from rest of the driver as possible. + * End of SW TCL functions * ***************************************************************************/ -struct r300_stencilref_context { - void (*draw_arrays)(struct pipe_context *pipe, - unsigned mode, unsigned start, unsigned count); - - void (*draw_range_elements)( - struct pipe_context *pipe, struct pipe_resource *indexBuffer, - unsigned indexSize, int indexBias, unsigned minIndex, unsigned maxIndex, - unsigned mode, unsigned start, unsigned count); - - uint32_t rs_cull_mode; - uint32_t zb_stencilrefmask; - ubyte ref_value_front; -}; - -static boolean r300_stencilref_needed(struct r300_context *r300) +static void r300_resource_resolve(struct pipe_context* pipe, + struct pipe_resource* dest, + struct pipe_subresource subdest, + struct pipe_resource* src, + struct pipe_subresource subsrc) { - struct r300_dsa_state *dsa = (struct r300_dsa_state*)r300->dsa_state.state; - - return dsa->two_sided_stencil_ref || - (dsa->two_sided && - r300->stencil_ref.ref_value[0] != r300->stencil_ref.ref_value[1]); -} - -/* Set drawing for front faces. */ -static void r300_stencilref_begin(struct r300_context *r300) -{ - struct r300_stencilref_context *sr = r300->stencilref_fallback; - struct r300_rs_state *rs = (struct r300_rs_state*)r300->rs_state.state; - struct r300_dsa_state *dsa = (struct r300_dsa_state*)r300->dsa_state.state; - - /* Save state. */ - sr->rs_cull_mode = rs->cull_mode; - sr->zb_stencilrefmask = dsa->stencil_ref_mask; - sr->ref_value_front = r300->stencil_ref.ref_value[0]; - - /* We *cull* pixels, therefore no need to mask out the bits. */ - rs->cull_mode |= R300_CULL_BACK; - - r300->rs_state.dirty = TRUE; -} - -/* Set drawing for back faces. */ -static void r300_stencilref_switch_side(struct r300_context *r300) -{ - struct r300_stencilref_context *sr = r300->stencilref_fallback; - struct r300_rs_state *rs = (struct r300_rs_state*)r300->rs_state.state; - struct r300_dsa_state *dsa = (struct r300_dsa_state*)r300->dsa_state.state; - - rs->cull_mode = sr->rs_cull_mode | R300_CULL_FRONT; - dsa->stencil_ref_mask = dsa->stencil_ref_bf; - r300->stencil_ref.ref_value[0] = r300->stencil_ref.ref_value[1]; - - r300->rs_state.dirty = TRUE; - r300->dsa_state.dirty = TRUE; -} - -/* Restore the original state. */ -static void r300_stencilref_end(struct r300_context *r300) -{ - struct r300_stencilref_context *sr = r300->stencilref_fallback; - struct r300_rs_state *rs = (struct r300_rs_state*)r300->rs_state.state; - struct r300_dsa_state *dsa = (struct r300_dsa_state*)r300->dsa_state.state; - - /* Restore state. */ - rs->cull_mode = sr->rs_cull_mode; - dsa->stencil_ref_mask = sr->zb_stencilrefmask; - r300->stencil_ref.ref_value[0] = sr->ref_value_front; - - r300->rs_state.dirty = TRUE; - r300->dsa_state.dirty = TRUE; -} - -static void r300_stencilref_draw_arrays(struct pipe_context *pipe, unsigned mode, - unsigned start, unsigned count) -{ - struct r300_context *r300 = r300_context(pipe); - struct r300_stencilref_context *sr = r300->stencilref_fallback; - - if (!r300_stencilref_needed(r300)) { - sr->draw_arrays(pipe, mode, start, count); - } else { - r300_stencilref_begin(r300); - sr->draw_arrays(pipe, mode, start, count); - r300_stencilref_switch_side(r300); - sr->draw_arrays(pipe, mode, start, count); - r300_stencilref_end(r300); - } -} - -static void r300_stencilref_draw_range_elements( - struct pipe_context *pipe, struct pipe_resource *indexBuffer, - unsigned indexSize, int indexBias, unsigned minIndex, unsigned maxIndex, - unsigned mode, unsigned start, unsigned count) -{ - struct r300_context *r300 = r300_context(pipe); - struct r300_stencilref_context *sr = r300->stencilref_fallback; - - if (!r300_stencilref_needed(r300)) { - sr->draw_range_elements(pipe, indexBuffer, indexSize, indexBias, - minIndex, maxIndex, mode, start, count); - } else { - r300_stencilref_begin(r300); - sr->draw_range_elements(pipe, indexBuffer, indexSize, indexBias, - minIndex, maxIndex, mode, start, count); - r300_stencilref_switch_side(r300); - sr->draw_range_elements(pipe, indexBuffer, indexSize, indexBias, - minIndex, maxIndex, mode, start, count); - r300_stencilref_end(r300); - } -} - -static void r300_plug_in_stencil_ref_fallback(struct r300_context *r300) -{ - r300->stencilref_fallback = CALLOC_STRUCT(r300_stencilref_context); - - /* Save original draw functions. */ - r300->stencilref_fallback->draw_arrays = r300->context.draw_arrays; - r300->stencilref_fallback->draw_range_elements = r300->context.draw_range_elements; - - /* Override the draw functions. */ - r300->context.draw_arrays = r300_stencilref_draw_arrays; - r300->context.draw_range_elements = r300_stencilref_draw_range_elements; + struct r300_context* r300 = r300_context(pipe); + struct r300_aa_state *aa = (struct r300_aa_state*)r300->aa_state.state; + struct pipe_surface* srcsurf = src->screen->get_tex_surface(src->screen, + src, subsrc.face, subsrc.level, 0, 0); + float color[] = {0, 0, 0, 0}; + + DBG(r300, DBG_DRAW, "r300: Resolving resource...\n"); + + /* Enable AA resolve. */ + aa->dest = r300_surface( + dest->screen->get_tex_surface(dest->screen, dest, subdest.face, + subdest.level, 0, 0)); + + aa->aaresolve_ctl = + R300_RB3D_AARESOLVE_CTL_AARESOLVE_MODE_RESOLVE | + R300_RB3D_AARESOLVE_CTL_AARESOLVE_ALPHA_AVERAGE; + r300->aa_state.size = 12; + r300->aa_state.dirty = TRUE; + + /* Resolve the surface. */ + r300->context.clear_render_target(pipe, + srcsurf, color, 0, 0, src->width0, src->height0); + + /* Disable AA resolve. */ + aa->aaresolve_ctl = 0; + r300->aa_state.size = 4; + r300->aa_state.dirty = TRUE; + + pipe_surface_reference((struct pipe_surface**)&srcsurf, NULL); + pipe_surface_reference((struct pipe_surface**)&aa->dest, NULL); } void r300_init_render_functions(struct r300_context *r300) @@ -1259,7 +1069,9 @@ void r300_init_render_functions(struct r300_context *r300) r300->context.draw_range_elements = r300_swtcl_draw_range_elements; } - /* Plug in two-sided stencil reference value fallback if needed. */ + r300->context.resource_resolve = r300_resource_resolve; + + /* Plug in the two-sided stencil reference value fallback if needed. */ if (!r300->screen->caps.is_r500) r300_plug_in_stencil_ref_fallback(r300); } diff --git a/src/gallium/drivers/r300/r300_render_stencilref.c b/src/gallium/drivers/r300/r300_render_stencilref.c new file mode 100644 index 0000000000..9a6b4e12ff --- /dev/null +++ b/src/gallium/drivers/r300/r300_render_stencilref.c @@ -0,0 +1,158 @@ +/* + * Copyright 2010 Marek Olšák <maraeo@gmail.com> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +/** + * The two-sided stencil reference value fallback for r3xx-r4xx chips. + * These chips support two-sided stencil functions but they do not support + * a two-sided reference value. + * + * The functions below split every draw call which uses the two-sided + * reference value into two draw calls -- the first one renders front faces + * and the second renders back faces with the other reference value. + */ + +#include "r300_context.h" +#include "r300_reg.h" + +struct r300_stencilref_context { + void (*draw_arrays)(struct pipe_context *pipe, + unsigned mode, unsigned start, unsigned count); + + void (*draw_range_elements)( + struct pipe_context *pipe, struct pipe_resource *indexBuffer, + unsigned indexSize, int indexBias, unsigned minIndex, unsigned maxIndex, + unsigned mode, unsigned start, unsigned count); + + uint32_t rs_cull_mode; + uint32_t zb_stencilrefmask; + ubyte ref_value_front; +}; + +static boolean r300_stencilref_needed(struct r300_context *r300) +{ + struct r300_dsa_state *dsa = (struct r300_dsa_state*)r300->dsa_state.state; + + return dsa->two_sided_stencil_ref || + (dsa->two_sided && + r300->stencil_ref.ref_value[0] != r300->stencil_ref.ref_value[1]); +} + +/* Set drawing for front faces. */ +static void r300_stencilref_begin(struct r300_context *r300) +{ + struct r300_stencilref_context *sr = r300->stencilref_fallback; + struct r300_rs_state *rs = (struct r300_rs_state*)r300->rs_state.state; + struct r300_dsa_state *dsa = (struct r300_dsa_state*)r300->dsa_state.state; + + /* Save state. */ + sr->rs_cull_mode = rs->cb_main[rs->cull_mode_index]; + sr->zb_stencilrefmask = dsa->stencil_ref_mask; + sr->ref_value_front = r300->stencil_ref.ref_value[0]; + + /* We *cull* pixels, therefore no need to mask out the bits. */ + rs->cb_main[rs->cull_mode_index] |= R300_CULL_BACK; + + r300->rs_state.dirty = TRUE; +} + +/* Set drawing for back faces. */ +static void r300_stencilref_switch_side(struct r300_context *r300) +{ + struct r300_stencilref_context *sr = r300->stencilref_fallback; + struct r300_rs_state *rs = (struct r300_rs_state*)r300->rs_state.state; + struct r300_dsa_state *dsa = (struct r300_dsa_state*)r300->dsa_state.state; + + rs->cb_main[rs->cull_mode_index] = sr->rs_cull_mode | R300_CULL_FRONT; + dsa->stencil_ref_mask = dsa->stencil_ref_bf; + r300->stencil_ref.ref_value[0] = r300->stencil_ref.ref_value[1]; + + r300->rs_state.dirty = TRUE; + r300->dsa_state.dirty = TRUE; +} + +/* Restore the original state. */ +static void r300_stencilref_end(struct r300_context *r300) +{ + struct r300_stencilref_context *sr = r300->stencilref_fallback; + struct r300_rs_state *rs = (struct r300_rs_state*)r300->rs_state.state; + struct r300_dsa_state *dsa = (struct r300_dsa_state*)r300->dsa_state.state; + + /* Restore state. */ + rs->cb_main[rs->cull_mode_index] = sr->rs_cull_mode; + dsa->stencil_ref_mask = sr->zb_stencilrefmask; + r300->stencil_ref.ref_value[0] = sr->ref_value_front; + + r300->rs_state.dirty = TRUE; + r300->dsa_state.dirty = TRUE; +} + +static void r300_stencilref_draw_arrays(struct pipe_context *pipe, unsigned mode, + unsigned start, unsigned count) +{ + struct r300_context *r300 = r300_context(pipe); + struct r300_stencilref_context *sr = r300->stencilref_fallback; + + if (!r300_stencilref_needed(r300)) { + sr->draw_arrays(pipe, mode, start, count); + } else { + r300_stencilref_begin(r300); + sr->draw_arrays(pipe, mode, start, count); + r300_stencilref_switch_side(r300); + sr->draw_arrays(pipe, mode, start, count); + r300_stencilref_end(r300); + } +} + +static void r300_stencilref_draw_range_elements( + struct pipe_context *pipe, struct pipe_resource *indexBuffer, + unsigned indexSize, int indexBias, unsigned minIndex, unsigned maxIndex, + unsigned mode, unsigned start, unsigned count) +{ + struct r300_context *r300 = r300_context(pipe); + struct r300_stencilref_context *sr = r300->stencilref_fallback; + + if (!r300_stencilref_needed(r300)) { + sr->draw_range_elements(pipe, indexBuffer, indexSize, indexBias, + minIndex, maxIndex, mode, start, count); + } else { + r300_stencilref_begin(r300); + sr->draw_range_elements(pipe, indexBuffer, indexSize, indexBias, + minIndex, maxIndex, mode, start, count); + r300_stencilref_switch_side(r300); + sr->draw_range_elements(pipe, indexBuffer, indexSize, indexBias, + minIndex, maxIndex, mode, start, count); + r300_stencilref_end(r300); + } +} + +void r300_plug_in_stencil_ref_fallback(struct r300_context *r300) +{ + r300->stencilref_fallback = CALLOC_STRUCT(r300_stencilref_context); + + /* Save original draw functions. */ + r300->stencilref_fallback->draw_arrays = r300->context.draw_arrays; + r300->stencilref_fallback->draw_range_elements = r300->context.draw_range_elements; + + /* Override the draw functions. */ + r300->context.draw_arrays = r300_stencilref_draw_arrays; + r300->context.draw_range_elements = r300_stencilref_draw_range_elements; +} diff --git a/src/gallium/drivers/r300/r300_render_translate.c b/src/gallium/drivers/r300/r300_render_translate.c new file mode 100644 index 0000000000..0ea11e5bfc --- /dev/null +++ b/src/gallium/drivers/r300/r300_render_translate.c @@ -0,0 +1,322 @@ +/* + * Copyright 2010 Marek Olšák <maraeo@gmail.com> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +/** + * The functions below translate vertex and index buffers to the layout + * compatible with the hardware, so that all vertex and index fetches are + * DWORD-aligned and all used vertex and index formats are supported. + * For indices, an optional index offset is added to each index. + */ + +#include "r300_context.h" +#include "translate/translate.h" + +void r300_begin_vertex_translate(struct r300_context *r300) +{ + struct pipe_context *pipe = &r300->context; + struct translate_key key = {0}; + struct translate_element *te; + unsigned tr_elem_index[PIPE_MAX_ATTRIBS] = {0}; + struct translate *tr; + struct r300_vertex_element_state *ve = r300->velems; + boolean vb_translated[PIPE_MAX_ATTRIBS] = {0}; + void *vb_map[PIPE_MAX_ATTRIBS] = {0}, *out_map; + struct pipe_transfer *vb_transfer[PIPE_MAX_ATTRIBS] = {0}, *out_transfer; + struct pipe_resource *out_buffer; + unsigned i, num_verts; + + /* Initialize the translate key, i.e. the recipe how vertices should be + * translated. */ + for (i = 0; i < ve->count; i++) { + struct pipe_vertex_buffer *vb = + &r300->vertex_buffer[ve->velem[i].vertex_buffer_index]; + enum pipe_format output_format = ve->hw_format[i]; + unsigned output_format_size = ve->hw_format_size[i]; + + /* Check for support. */ + if (ve->velem[i].src_format == ve->hw_format[i] && + (vb->buffer_offset + ve->velem[i].src_offset) % 4 == 0 && + vb->stride % 4 == 0) { + continue; + } + + /* Workaround for translate: output floats instead of halfs. */ + switch (output_format) { + case PIPE_FORMAT_R16_FLOAT: + output_format = PIPE_FORMAT_R32_FLOAT; + output_format_size = 4; + break; + case PIPE_FORMAT_R16G16_FLOAT: + output_format = PIPE_FORMAT_R32G32_FLOAT; + output_format_size = 8; + break; + case PIPE_FORMAT_R16G16B16_FLOAT: + output_format = PIPE_FORMAT_R32G32B32_FLOAT; + output_format_size = 12; + break; + case PIPE_FORMAT_R16G16B16A16_FLOAT: + output_format = PIPE_FORMAT_R32G32B32A32_FLOAT; + output_format_size = 16; + break; + default:; + } + + /* Add this vertex element. */ + te = &key.element[key.nr_elements]; + /*te->type; + te->instance_divisor;*/ + te->input_buffer = ve->velem[i].vertex_buffer_index; + te->input_format = ve->velem[i].src_format; + te->input_offset = vb->buffer_offset + ve->velem[i].src_offset; + te->output_format = output_format; + te->output_offset = key.output_stride; + + key.output_stride += output_format_size; + vb_translated[ve->velem[i].vertex_buffer_index] = TRUE; + tr_elem_index[i] = key.nr_elements; + key.nr_elements++; + } + + /* Get a translate object. */ + tr = translate_cache_find(r300->tran.translate_cache, &key); + + /* Map buffers we want to translate. */ + for (i = 0; i < r300->vertex_buffer_count; i++) { + if (vb_translated[i]) { + struct pipe_vertex_buffer *vb = &r300->vertex_buffer[i]; + + vb_map[i] = pipe_buffer_map(pipe, vb->buffer, + PIPE_TRANSFER_READ, &vb_transfer[i]); + + tr->set_buffer(tr, i, vb_map[i], vb->stride, vb->max_index); + } + } + + /* Create and map the output buffer. */ + num_verts = r300->vertex_buffer_max_index + 1; + + out_buffer = pipe_buffer_create(&r300->screen->screen, + PIPE_BIND_VERTEX_BUFFER, + key.output_stride * num_verts); + + out_map = pipe_buffer_map(pipe, out_buffer, PIPE_TRANSFER_WRITE, + &out_transfer); + + /* Translate. */ + tr->run(tr, 0, num_verts, 0, out_map); + + /* Unmap all buffers. */ + for (i = 0; i < r300->vertex_buffer_count; i++) { + if (vb_translated[i]) { + pipe_buffer_unmap(pipe, r300->vertex_buffer[i].buffer, + vb_transfer[i]); + } + } + + pipe_buffer_unmap(pipe, out_buffer, out_transfer); + + /* Setup the new vertex buffer in the first free slot. */ + for (i = 0; i < PIPE_MAX_ATTRIBS; i++) { + struct pipe_vertex_buffer *vb = &r300->vertex_buffer[i]; + + if (!vb->buffer) { + pipe_resource_reference(&vb->buffer, out_buffer); + vb->buffer_offset = 0; + vb->max_index = num_verts - 1; + vb->stride = key.output_stride; + r300->tran.vb_slot = i; + break; + } + } + + /* Save and replace vertex elements. */ + { + struct pipe_vertex_element new_velems[PIPE_MAX_ATTRIBS]; + + r300->tran.saved_velems = r300->velems; + + for (i = 0; i < ve->count; i++) { + if (vb_translated[ve->velem[i].vertex_buffer_index]) { + te = &key.element[tr_elem_index[i]]; + new_velems[i].instance_divisor = ve->velem[i].instance_divisor; + new_velems[i].src_format = te->output_format; + new_velems[i].src_offset = te->output_offset; + new_velems[i].vertex_buffer_index = r300->tran.vb_slot; + } else { + memcpy(&new_velems[i], &ve->velem[i], + sizeof(struct pipe_vertex_element)); + } + } + + r300->tran.new_velems = + pipe->create_vertex_elements_state(pipe, ve->count, new_velems); + pipe->bind_vertex_elements_state(pipe, r300->tran.new_velems); + } + + pipe_resource_reference(&out_buffer, NULL); +} + +void r300_end_vertex_translate(struct r300_context *r300) +{ + struct pipe_context *pipe = &r300->context; + + /* Restore vertex elements. */ + pipe->bind_vertex_elements_state(pipe, r300->tran.saved_velems); + pipe->delete_vertex_elements_state(pipe, r300->tran.new_velems); + + /* Delete the now-unused VBO. */ + pipe_resource_reference(&r300->vertex_buffer[r300->tran.vb_slot].buffer, + NULL); +} + +static void r300_shorten_ubyte_elts(struct r300_context* r300, + struct pipe_resource** elts, + int index_bias, + unsigned start, + unsigned count) +{ + struct pipe_context* context = &r300->context; + struct pipe_screen* screen = r300->context.screen; + struct pipe_resource* new_elts; + unsigned char *in_map; + unsigned short *out_map; + struct pipe_transfer *src_transfer, *dst_transfer; + unsigned i; + + new_elts = pipe_buffer_create(screen, + PIPE_BIND_INDEX_BUFFER, + 2 * count); + + in_map = pipe_buffer_map(context, *elts, PIPE_TRANSFER_READ, &src_transfer); + out_map = pipe_buffer_map(context, new_elts, PIPE_TRANSFER_WRITE, &dst_transfer); + + in_map += start; + + for (i = 0; i < count; i++) { + *out_map = (unsigned short)(*in_map + index_bias); + in_map++; + out_map++; + } + + pipe_buffer_unmap(context, *elts, src_transfer); + pipe_buffer_unmap(context, new_elts, dst_transfer); + + *elts = new_elts; +} + +static void r300_rebuild_ushort_elts(struct r300_context *r300, + struct pipe_resource **elts, + int index_bias, + unsigned start, unsigned count) +{ + struct pipe_context *context = &r300->context; + struct pipe_transfer *in_transfer = NULL; + struct pipe_transfer *out_transfer = NULL; + struct pipe_resource *new_elts; + unsigned short *in_map; + unsigned short *out_map; + unsigned i; + + new_elts = pipe_buffer_create(context->screen, + PIPE_BIND_INDEX_BUFFER, + 2 * count); + + in_map = pipe_buffer_map(context, *elts, + PIPE_TRANSFER_READ, &in_transfer); + out_map = pipe_buffer_map(context, new_elts, + PIPE_TRANSFER_WRITE, &out_transfer); + + in_map += start; + for (i = 0; i < count; i++) { + *out_map = (unsigned short)(*in_map + index_bias); + in_map++; + out_map++; + } + + pipe_buffer_unmap(context, *elts, in_transfer); + pipe_buffer_unmap(context, new_elts, out_transfer); + + *elts = new_elts; +} + +static void r300_rebuild_uint_elts(struct r300_context *r300, + struct pipe_resource **elts, + int index_bias, + unsigned start, unsigned count) +{ + struct pipe_context *context = &r300->context; + struct pipe_transfer *in_transfer = NULL; + struct pipe_transfer *out_transfer = NULL; + struct pipe_resource *new_elts; + unsigned int *in_map; + unsigned int *out_map; + unsigned i; + + new_elts = pipe_buffer_create(context->screen, + PIPE_BIND_INDEX_BUFFER, + 2 * count); + + in_map = pipe_buffer_map(context, *elts, + PIPE_TRANSFER_READ, &in_transfer); + out_map = pipe_buffer_map(context, new_elts, + PIPE_TRANSFER_WRITE, &out_transfer); + + in_map += start; + for (i = 0; i < count; i++) { + *out_map = (unsigned int)(*in_map + index_bias); + in_map++; + out_map++; + } + + pipe_buffer_unmap(context, *elts, in_transfer); + pipe_buffer_unmap(context, new_elts, out_transfer); + + *elts = new_elts; +} + +void r300_translate_index_buffer(struct r300_context *r300, + struct pipe_resource **index_buffer, + unsigned *index_size, unsigned index_offset, + unsigned *start, unsigned count) +{ + switch (*index_size) { + case 1: + r300_shorten_ubyte_elts(r300, index_buffer, index_offset, *start, count); + *index_size = 2; + *start = 0; + break; + + case 2: + if (*start % 2 != 0 || index_offset) { + r300_rebuild_ushort_elts(r300, index_buffer, index_offset, *start, count); + *start = 0; + } + break; + + case 4: + if (index_offset) { + r300_rebuild_uint_elts(r300, index_buffer, index_offset, *start, count); + *start = 0; + } + break; + } +} diff --git a/src/gallium/drivers/r300/r300_screen.c b/src/gallium/drivers/r300/r300_screen.c index fd522b84e1..5bba55906c 100644 --- a/src/gallium/drivers/r300/r300_screen.c +++ b/src/gallium/drivers/r300/r300_screen.c @@ -270,15 +270,24 @@ static boolean r300_is_format_supported(struct pipe_screen* screen, format == PIPE_FORMAT_R16G16B16_FLOAT || format == PIPE_FORMAT_R16G16B16A16_FLOAT; - if (target >= PIPE_MAX_TEXTURE_TYPES) { - fprintf(stderr, "r300: Implementation error: Received bogus texture " - "target %d in %s\n", target, __FUNCTION__); - return FALSE; + switch (sample_count) { + case 0: + case 1: + break; + case 2: + case 3: + case 4: + case 6: + if (usage != PIPE_BIND_RENDER_TARGET || + !util_format_is_rgba8_variant( + util_format_description(format))) { + return FALSE; + } + break; + default: + return FALSE; } - if (sample_count > 1) - return FALSE; - /* Check sampler format support. */ if ((usage & PIPE_BIND_SAMPLER_VIEW) && /* Z24 cannot be sampled from on non-r5xx. */ @@ -320,6 +329,12 @@ static boolean r300_is_format_supported(struct pipe_screen* screen, retval |= PIPE_BIND_VERTEX_BUFFER; } + /* Transfers are always supported. */ + if (usage & PIPE_BIND_TRANSFER_READ) + retval |= PIPE_BIND_TRANSFER_READ; + if (usage & PIPE_BIND_TRANSFER_WRITE) + retval |= PIPE_BIND_TRANSFER_WRITE; + return retval == usage; } diff --git a/src/gallium/drivers/r300/r300_screen.h b/src/gallium/drivers/r300/r300_screen.h index 29492024fe..29cd5dbe26 100644 --- a/src/gallium/drivers/r300/r300_screen.h +++ b/src/gallium/drivers/r300/r300_screen.h @@ -65,7 +65,7 @@ static INLINE struct r300_screen* r300_screen(struct pipe_screen* screen) { /* Logging. */ #define DBG_FP (1 << 1) #define DBG_VP (1 << 2) -#define DBG_CS (1 << 3) +/* The bit (1 << 3) is unused. */ #define DBG_DRAW (1 << 4) #define DBG_TEX (1 << 5) #define DBG_TEXALLOC (1 << 6) @@ -76,6 +76,7 @@ static INLINE struct r300_screen* r300_screen(struct pipe_screen* screen) { #define DBG_ANISOHQ (1 << 16) #define DBG_NO_TILING (1 << 17) #define DBG_NO_IMMD (1 << 18) +#define DBG_FAKE_OCC (1 << 19) /* Statistics. */ #define DBG_STATS (1 << 24) /*@}*/ diff --git a/src/gallium/drivers/r300/r300_screen_buffer.c b/src/gallium/drivers/r300/r300_screen_buffer.c index 44179f19ed..7959e6a2f9 100644 --- a/src/gallium/drivers/r300/r300_screen_buffer.c +++ b/src/gallium/drivers/r300/r300_screen_buffer.c @@ -93,25 +93,28 @@ int r300_upload_user_buffers(struct r300_context *r300) enum pipe_error ret = PIPE_OK; int i, nr; - nr = r300->vertex_buffer_count; + nr = r300->velems->count; for (i = 0; i < nr; i++) { - if (r300_buffer_is_user_buffer(r300->vertex_buffer[i].buffer)) { - struct pipe_resource *upload_buffer = NULL; - unsigned offset = 0; /*r300->vertex_buffer[i].buffer_offset * 4;*/ - unsigned size = r300->vertex_buffer[i].buffer->width0; - unsigned upload_offset; - ret = u_upload_buffer(r300->upload_vb, - offset, size, - r300->vertex_buffer[i].buffer, - &upload_offset, &upload_buffer); - if (ret) - return ret; - - pipe_resource_reference(&r300->vertex_buffer[i].buffer, NULL); - r300->vertex_buffer[i].buffer = upload_buffer; - r300->vertex_buffer[i].buffer_offset = upload_offset; - } + struct pipe_vertex_buffer *vb = + &r300->vertex_buffer[r300->velems->velem[i].vertex_buffer_index]; + + if (r300_buffer_is_user_buffer(vb->buffer)) { + struct pipe_resource *upload_buffer = NULL; + unsigned offset = 0; /*vb->buffer_offset * 4;*/ + unsigned size = vb->buffer->width0; + unsigned upload_offset; + ret = u_upload_buffer(r300->upload_vb, + offset, size, + vb->buffer, + &upload_offset, &upload_buffer); + if (ret) + return ret; + + pipe_resource_reference(&vb->buffer, NULL); + vb->buffer = upload_buffer; + vb->buffer_offset = upload_offset; + } } return ret; } @@ -261,10 +264,6 @@ struct pipe_resource *r300_buffer_create(struct pipe_screen *screen, rbuf->b.vtbl = &r300_buffer_vtbl; pipe_reference_init(&rbuf->b.b.reference, 1); rbuf->b.b.screen = screen; - - if (rbuf->b.b.bind & R300_BIND_OQBO) - alignment = 4096; - rbuf->domain = R300_DOMAIN_GTT; rbuf->buf = r300screen->rws->buffer_create(r300screen->rws, diff --git a/src/gallium/drivers/r300/r300_screen_buffer.h b/src/gallium/drivers/r300/r300_screen_buffer.h index 87b42b9412..ff35585870 100644 --- a/src/gallium/drivers/r300/r300_screen_buffer.h +++ b/src/gallium/drivers/r300/r300_screen_buffer.h @@ -116,25 +116,4 @@ static INLINE boolean r300_add_texture(struct r300_winsys_screen *rws, return rws->add_buffer(rws, tex->buffer, rd, wr); } -static INLINE void r300_buffer_write_reloc(struct r300_winsys_screen *rws, - struct r300_buffer *buf, - enum r300_buffer_domain rd, - enum r300_buffer_domain wd, - uint32_t flags) -{ - if (!buf->buf) - return; - - rws->write_cs_reloc(rws, buf->buf, rd, wd, flags); -} - -static INLINE void r300_texture_write_reloc(struct r300_winsys_screen *rws, - struct r300_texture *texture, - enum r300_buffer_domain rd, - enum r300_buffer_domain wd, - uint32_t flags) -{ - rws->write_cs_reloc(rws, texture->buffer, rd, wd, flags); -} - #endif diff --git a/src/gallium/drivers/r300/r300_state.c b/src/gallium/drivers/r300/r300_state.c index cfec8ac2b7..15de533778 100644 --- a/src/gallium/drivers/r300/r300_state.c +++ b/src/gallium/drivers/r300/r300_state.c @@ -31,12 +31,12 @@ #include "pipe/p_config.h" +#include "r300_cb.h" #include "r300_context.h" #include "r300_emit.h" #include "r300_reg.h" #include "r300_screen.h" #include "r300_screen_buffer.h" -#include "r300_state.h" #include "r300_state_inlines.h" #include "r300_fs.h" #include "r300_texture.h" @@ -183,6 +183,12 @@ static void* r300_create_blend_state(struct pipe_context* pipe, { struct r300_screen* r300screen = r300_screen(pipe->screen); struct r300_blend_state* blend = CALLOC_STRUCT(r300_blend_state); + uint32_t blend_control = 0; /* R300_RB3D_CBLEND: 0x4e04 */ + uint32_t alpha_blend_control = 0; /* R300_RB3D_ABLEND: 0x4e08 */ + uint32_t color_channel_mask = 0; /* R300_RB3D_COLOR_CHANNEL_MASK: 0x4e0c */ + uint32_t rop = 0; /* R300_RB3D_ROPCNTL: 0x4e18 */ + uint32_t dither = 0; /* R300_RB3D_DITHER_CTL: 0x4e50 */ + CB_LOCALS; if (state->rt[0].blend_enable) { @@ -196,7 +202,7 @@ static void* r300_create_blend_state(struct pipe_context* pipe, /* despite the name, ALPHA_BLEND_ENABLE has nothing to do with alpha, * this is just the crappy D3D naming */ - blend->blend_control = R300_ALPHA_BLEND_ENABLE | + blend_control = R300_ALPHA_BLEND_ENABLE | r300_translate_blend_function(eqRGB) | ( r300_translate_blend_factor(srcRGB) << R300_SRC_BLEND_SHIFT) | ( r300_translate_blend_factor(dstRGB) << R300_DST_BLEND_SHIFT); @@ -220,7 +226,7 @@ static void* r300_create_blend_state(struct pipe_context* pipe, srcA == PIPE_BLENDFACTOR_INV_DST_ALPHA || srcRGB == PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE) { /* Enable reading from the colorbuffer. */ - blend->blend_control |= R300_READ_ENABLE; + blend_control |= R300_READ_ENABLE; if (r300screen->caps.is_r500) { /* Optimization: Depending on incoming pixels, we can @@ -233,7 +239,7 @@ static void* r300_create_blend_state(struct pipe_context* pipe, (dstA == PIPE_BLENDFACTOR_SRC_COLOR || dstA == PIPE_BLENDFACTOR_SRC_ALPHA || dstA == PIPE_BLENDFACTOR_ZERO)) { - blend->blend_control |= R500_SRC_ALPHA_0_NO_READ; + blend_control |= R500_SRC_ALPHA_0_NO_READ; } /* Disable reading if SRC_ALPHA == 1. */ @@ -242,7 +248,7 @@ static void* r300_create_blend_state(struct pipe_context* pipe, (dstA == PIPE_BLENDFACTOR_INV_SRC_COLOR || dstA == PIPE_BLENDFACTOR_INV_SRC_ALPHA || dstA == PIPE_BLENDFACTOR_ZERO)) { - blend->blend_control |= R500_SRC_ALPHA_1_NO_READ; + blend_control |= R500_SRC_ALPHA_1_NO_READ; } } } @@ -272,31 +278,31 @@ static void* r300_create_blend_state(struct pipe_context* pipe, * pixels. */ if (blend_discard_if_src_alpha_0(srcRGB, srcA, dstRGB, dstA)) { - blend->blend_control |= R300_DISCARD_SRC_PIXELS_SRC_ALPHA_0; + blend_control |= R300_DISCARD_SRC_PIXELS_SRC_ALPHA_0; } else if (blend_discard_if_src_alpha_1(srcRGB, srcA, dstRGB, dstA)) { - blend->blend_control |= R300_DISCARD_SRC_PIXELS_SRC_ALPHA_1; + blend_control |= R300_DISCARD_SRC_PIXELS_SRC_ALPHA_1; } else if (blend_discard_if_src_color_0(srcRGB, srcA, dstRGB, dstA)) { - blend->blend_control |= R300_DISCARD_SRC_PIXELS_SRC_COLOR_0; + blend_control |= R300_DISCARD_SRC_PIXELS_SRC_COLOR_0; } else if (blend_discard_if_src_color_1(srcRGB, srcA, dstRGB, dstA)) { - blend->blend_control |= R300_DISCARD_SRC_PIXELS_SRC_COLOR_1; + blend_control |= R300_DISCARD_SRC_PIXELS_SRC_COLOR_1; } else if (blend_discard_if_src_alpha_color_0(srcRGB, srcA, dstRGB, dstA)) { - blend->blend_control |= + blend_control |= R300_DISCARD_SRC_PIXELS_SRC_ALPHA_COLOR_0; } else if (blend_discard_if_src_alpha_color_1(srcRGB, srcA, dstRGB, dstA)) { - blend->blend_control |= + blend_control |= R300_DISCARD_SRC_PIXELS_SRC_ALPHA_COLOR_1; } } /* separate alpha */ if (srcA != srcRGB || dstA != dstRGB || eqA != eqRGB) { - blend->blend_control |= R300_SEPARATE_ALPHA_ENABLE; - blend->alpha_blend_control = + blend_control |= R300_SEPARATE_ALPHA_ENABLE; + alpha_blend_control = r300_translate_blend_function(eqA) | (r300_translate_blend_factor(srcA) << R300_SRC_BLEND_SHIFT) | (r300_translate_blend_factor(dstA) << R300_DST_BLEND_SHIFT); @@ -305,21 +311,21 @@ static void* r300_create_blend_state(struct pipe_context* pipe, /* PIPE_LOGICOP_* don't need to be translated, fortunately. */ if (state->logicop_enable) { - blend->rop = R300_RB3D_ROPCNTL_ROP_ENABLE | + rop = R300_RB3D_ROPCNTL_ROP_ENABLE | (state->logicop_func) << R300_RB3D_ROPCNTL_ROP_SHIFT; } /* Color channel masks for all MRTs. */ - blend->color_channel_mask = bgra_cmask(state->rt[0].colormask); + color_channel_mask = bgra_cmask(state->rt[0].colormask); if (r300screen->caps.is_r500 && state->independent_blend_enable) { if (state->rt[1].blend_enable) { - blend->color_channel_mask |= bgra_cmask(state->rt[1].colormask) << 4; + color_channel_mask |= bgra_cmask(state->rt[1].colormask) << 4; } if (state->rt[2].blend_enable) { - blend->color_channel_mask |= bgra_cmask(state->rt[2].colormask) << 8; + color_channel_mask |= bgra_cmask(state->rt[2].colormask) << 8; } if (state->rt[3].blend_enable) { - blend->color_channel_mask |= bgra_cmask(state->rt[3].colormask) << 12; + color_channel_mask |= bgra_cmask(state->rt[3].colormask) << 12; } } @@ -330,11 +336,31 @@ static void* r300_create_blend_state(struct pipe_context* pipe, * This could be revisited if we ever get quality or conformance hints. * if (state->dither) { - blend->dither = R300_RB3D_DITHER_CTL_DITHER_MODE_LUT | + dither = R300_RB3D_DITHER_CTL_DITHER_MODE_LUT | R300_RB3D_DITHER_CTL_ALPHA_DITHER_MODE_LUT; } */ + /* Build a command buffer. */ + BEGIN_CB(blend->cb, 8); + OUT_CB_REG(R300_RB3D_ROPCNTL, rop); + OUT_CB_REG_SEQ(R300_RB3D_CBLEND, 3); + OUT_CB(blend_control); + OUT_CB(alpha_blend_control); + OUT_CB(color_channel_mask); + OUT_CB_REG(R300_RB3D_DITHER_CTL, dither); + END_CB; + + /* The same as above, but with no colorbuffer reads and writes. */ + BEGIN_CB(blend->cb_no_readwrite, 8); + OUT_CB_REG(R300_RB3D_ROPCNTL, rop); + OUT_CB_REG_SEQ(R300_RB3D_CBLEND, 3); + OUT_CB(0); + OUT_CB(0); + OUT_CB(0); + OUT_CB_REG(R300_RB3D_DITHER_CTL, dither); + END_CB; + return (void*)blend; } @@ -368,20 +394,26 @@ static void r300_set_blend_color(struct pipe_context* pipe, struct r300_context* r300 = r300_context(pipe); struct r300_blend_color_state* state = (struct r300_blend_color_state*)r300->blend_color_state.state; - union util_color uc; + CB_LOCALS; - util_pack_color(color->color, PIPE_FORMAT_B8G8R8A8_UNORM, &uc); - state->blend_color = uc.ui; + if (r300->screen->caps.is_r500) { + /* XXX if FP16 blending is enabled, we should use the FP16 format */ + BEGIN_CB(state->cb, 3); + OUT_CB_REG_SEQ(R500_RB3D_CONSTANT_COLOR_AR, 2); + OUT_CB(float_to_fixed10(color->color[0]) | + (float_to_fixed10(color->color[3]) << 16)); + OUT_CB(float_to_fixed10(color->color[2]) | + (float_to_fixed10(color->color[1]) << 16)); + END_CB; + } else { + union util_color uc; + util_pack_color(color->color, PIPE_FORMAT_B8G8R8A8_UNORM, &uc); - /* XXX if FP16 blending is enabled, we should use the FP16 format */ - state->blend_color_red_alpha = - float_to_fixed10(color->color[0]) | - (float_to_fixed10(color->color[3]) << 16); - state->blend_color_green_blue = - float_to_fixed10(color->color[2]) | - (float_to_fixed10(color->color[1]) << 16); + BEGIN_CB(state->cb, 2); + OUT_CB_REG(R300_RB3D_BLEND_COLOR, uc.ui); + END_CB; + } - r300->blend_color_state.size = r300->screen->caps.is_r500 ? 3 : 2; r300->blend_color_state.dirty = TRUE; } @@ -389,18 +421,27 @@ static void r300_set_clip_state(struct pipe_context* pipe, const struct pipe_clip_state* state) { struct r300_context* r300 = r300_context(pipe); + struct r300_clip_state *clip = + (struct r300_clip_state*)r300->clip_state.state; + CB_LOCALS; - r300->clip = *state; + clip->clip = *state; if (r300->screen->caps.has_tcl) { - memcpy(r300->clip_state.state, state, sizeof(struct pipe_clip_state)); - r300->clip_state.size = 29; + BEGIN_CB(clip->cb, 29); + OUT_CB_REG(R300_VAP_PVS_VECTOR_INDX_REG, + (r300->screen->caps.is_r500 ? + R500_PVS_UCP_START : R300_PVS_UCP_START)); + OUT_CB_ONE_REG(R300_VAP_PVS_UPLOAD_DATA, 6 * 4); + OUT_CB_TABLE(state->ucp, 6 * 4); + OUT_CB_REG(R300_VAP_CLIP_CNTL, ((1 << state->nr) - 1) | + R300_PS_UCP_MODE_CLIP_AS_TRIFAN); + END_CB; r300->clip_state.dirty = TRUE; } else { draw_flush(r300->draw); draw_set_clip_state(r300->draw, state); - r300->clip_state.size = 2; } } @@ -422,6 +463,9 @@ static void* { struct r300_capabilities *caps = &r300_screen(pipe->screen)->caps; struct r300_dsa_state* dsa = CALLOC_STRUCT(r300_dsa_state); + CB_LOCALS; + + dsa->dsa = *state; /* Depth test setup. */ if (state->depth.enabled) { @@ -494,9 +538,43 @@ static void* dsa->alpha_function |= R500_FG_ALPHA_FUNC_8BIT; } + BEGIN_CB(&dsa->cb_begin, 8); + OUT_CB_REG(R300_FG_ALPHA_FUNC, dsa->alpha_function); + OUT_CB_REG_SEQ(R300_ZB_CNTL, 3); + OUT_CB(dsa->z_buffer_control); + OUT_CB(dsa->z_stencil_control); + OUT_CB(dsa->stencil_ref_mask); + OUT_CB_REG(R500_ZB_STENCILREFMASK_BF, dsa->stencil_ref_bf); + END_CB; + + BEGIN_CB(dsa->cb_no_readwrite, 8); + OUT_CB_REG(R300_FG_ALPHA_FUNC, dsa->alpha_function); + OUT_CB_REG_SEQ(R300_ZB_CNTL, 3); + OUT_CB(0); + OUT_CB(0); + OUT_CB(0); + OUT_CB_REG(R500_ZB_STENCILREFMASK_BF, 0); + END_CB; + return (void*)dsa; } +static void r300_dsa_inject_stencilref(struct r300_context *r300) +{ + struct r300_dsa_state *dsa = + (struct r300_dsa_state*)r300->dsa_state.state; + + if (!dsa) + return; + + dsa->stencil_ref_mask = + (dsa->stencil_ref_mask & ~R300_STENCILREF_MASK) | + r300->stencil_ref.ref_value[0]; + dsa->stencil_ref_bf = + (dsa->stencil_ref_bf & ~R300_STENCILREF_MASK) | + r300->stencil_ref.ref_value[1]; +} + /* Bind DSA state. */ static void r300_bind_dsa_state(struct pipe_context* pipe, void* state) @@ -508,6 +586,8 @@ static void r300_bind_dsa_state(struct pipe_context* pipe, } UPDATE_STATE(state, r300->dsa_state); + + r300_dsa_inject_stencilref(r300); } /* Free DSA state. */ @@ -523,6 +603,8 @@ static void r300_set_stencil_ref(struct pipe_context* pipe, struct r300_context* r300 = r300_context(pipe); r300->stencil_ref = *sr; + + r300_dsa_inject_stencilref(r300); r300->dsa_state.dirty = TRUE; } @@ -577,21 +659,34 @@ static void r300_print_fb_surf_info(struct pipe_surface *surf, unsigned index, tex->last_level, util_format_short_name(tex->format)); } +static void copy_framebuffer_state(struct pipe_framebuffer_state *dst, + const struct pipe_framebuffer_state *src) +{ + unsigned i; + + for (i = 0; i < src->nr_cbufs; i++) { + pipe_surface_reference(&dst->cbufs[i], src->cbufs[i]); + } + for (; i < dst->nr_cbufs; i++) { + pipe_surface_reference(&dst->cbufs[i], NULL); + } + pipe_surface_reference(&dst->zsbuf, src->zsbuf); + + dst->nr_cbufs = src->nr_cbufs; + dst->width = src->width; + dst->height = src->height; +} + static void r300_set_framebuffer_state(struct pipe_context* pipe, const struct pipe_framebuffer_state* state) { struct r300_context* r300 = r300_context(pipe); + struct r300_aa_state *aa = (struct r300_aa_state*)r300->aa_state.state; struct pipe_framebuffer_state *old_state = r300->fb_state.state; unsigned max_width, max_height, i; uint32_t zbuffer_bpp = 0; - if (state->nr_cbufs > 4) { - fprintf(stderr, "r300: Implementation error: Too many MRTs in %s, " - "refusing to bind framebuffer state!\n", __FUNCTION__); - return; - } - if (r300->screen->caps.is_r500) { max_width = max_height = 4096; } else if (r300->screen->caps.is_r400) { @@ -610,7 +705,11 @@ static void draw_flush(r300->draw); } + r300->gpu_flush.dirty = TRUE; + r300->aa_state.dirty = TRUE; r300->fb_state.dirty = TRUE; + r300->hyperz_state.dirty = TRUE; + r300->fb_state_pipelined.dirty = TRUE; /* If nr_cbufs is changed from zero to non-zero or vice versa... */ if (!!old_state->nr_cbufs != !!state->nr_cbufs) { @@ -624,10 +723,12 @@ static void /* The tiling flags are dependent on the surface miplevel, unfortunately. */ r300_fb_set_tiling_flags(r300, r300->fb_state.state, state); - memcpy(r300->fb_state.state, state, sizeof(struct pipe_framebuffer_state)); + copy_framebuffer_state(r300->fb_state.state, state); - r300->fb_state.size = (10 * state->nr_cbufs) + (2 * (4 - state->nr_cbufs)) + - (state->zsbuf ? 10 : 0) + 9; + r300->fb_state.size = + 2 + + (8 * state->nr_cbufs) + + (state->zsbuf ? (r300->screen->caps.has_hiz ? 18 : 14) : 0); /* Polygon offset depends on the zbuffer bit depth. */ if (state->zsbuf && r300->polygon_offset_enabled) { @@ -646,6 +747,30 @@ static void } } + /* Set up AA config. */ + if (r300->rws->get_value(r300->rws, R300_VID_DRM_2_3_0)) { + if (state->nr_cbufs && state->cbufs[0]->texture->nr_samples > 1) { + aa->aa_config = R300_GB_AA_CONFIG_AA_ENABLE; + + switch (state->cbufs[0]->texture->nr_samples) { + case 2: + aa->aa_config |= R300_GB_AA_CONFIG_NUM_AA_SUBSAMPLES_2; + break; + case 3: + aa->aa_config |= R300_GB_AA_CONFIG_NUM_AA_SUBSAMPLES_3; + break; + case 4: + aa->aa_config |= R300_GB_AA_CONFIG_NUM_AA_SUBSAMPLES_4; + break; + case 6: + aa->aa_config |= R300_GB_AA_CONFIG_NUM_AA_SUBSAMPLES_6; + break; + } + } else { + aa->aa_config = 0; + } + } + if (DBG_ON(r300, DBG_FB)) { fprintf(stderr, "r300: set_framebuffer_state:\n"); for (i = 0; i < state->nr_cbufs; i++) { @@ -679,13 +804,12 @@ void r300_mark_fs_code_dirty(struct r300_context *r300) r300->fs.dirty = TRUE; r300->fs_rc_constant_state.dirty = TRUE; r300->fs_constants.dirty = TRUE; + r300->fs.size = fs->shader->cb_code_size; if (r300->screen->caps.is_r500) { - r300->fs.size = r500_get_fs_atom_size(r300); r300->fs_rc_constant_state.size = fs->shader->rc_state_count * 7; r300->fs_constants.size = fs->shader->externals_count * 4 + 3; } else { - r300->fs.size = r300_get_fs_atom_size(r300); r300->fs_rc_constant_state.size = fs->shader->rc_state_count * 5; r300->fs_constants.size = fs->shader->externals_count * 4 + 1; } @@ -719,6 +843,7 @@ static void r300_delete_fs_state(struct pipe_context* pipe, void* shader) tmp = ptr; ptr = ptr->next; rc_constants_destroy(&tmp->code.constants); + FREE(tmp->cb_code); FREE(tmp); } FREE((void*)fs->state.tokens); @@ -744,6 +869,27 @@ static void* r300_create_rs_state(struct pipe_context* pipe, struct r300_rs_state* rs = CALLOC_STRUCT(r300_rs_state); int i; float psiz; + uint32_t vap_control_status; /* R300_VAP_CNTL_STATUS: 0x2140 */ + uint32_t point_size; /* R300_GA_POINT_SIZE: 0x421c */ + uint32_t point_minmax; /* R300_GA_POINT_MINMAX: 0x4230 */ + uint32_t line_control; /* R300_GA_LINE_CNTL: 0x4234 */ + uint32_t polygon_offset_enable; /* R300_SU_POLY_OFFSET_ENABLE: 0x42b4 */ + uint32_t cull_mode; /* R300_SU_CULL_MODE: 0x42b8 */ + uint32_t line_stipple_config; /* R300_GA_LINE_STIPPLE_CONFIG: 0x4328 */ + uint32_t line_stipple_value; /* R300_GA_LINE_STIPPLE_VALUE: 0x4260 */ + uint32_t polygon_mode; /* R300_GA_POLY_MODE: 0x4288 */ + uint32_t clip_rule; /* R300_SC_CLIP_RULE: 0x43D0 */ + + /* Specifies top of Raster pipe specific enable controls, + * i.e. texture coordinates stuffing for points, lines, triangles */ + uint32_t stuffing_enable; /* R300_GB_ENABLE: 0x4008 */ + + /* Point sprites texture coordinates, 0: lower left, 1: upper right */ + float point_texcoord_left; /* R300_GA_POINT_S0: 0x4200 */ + float point_texcoord_bottom; /* R300_GA_POINT_T0: 0x4204 */ + float point_texcoord_right; /* R300_GA_POINT_S1: 0x4208 */ + float point_texcoord_top; /* R300_GA_POINT_T1: 0x420c */ + CB_LOCALS; /* Copy rasterizer state. */ rs->rs = *state; @@ -753,18 +899,18 @@ static void* r300_create_rs_state(struct pipe_context* pipe, rs->rs_draw.sprite_coord_enable = 0; /* We can do this in HW. */ #ifdef PIPE_ARCH_LITTLE_ENDIAN - rs->vap_control_status = R300_VC_NO_SWAP; + vap_control_status = R300_VC_NO_SWAP; #else - rs->vap_control_status = R300_VC_32BIT_SWAP; + vap_control_status = R300_VC_32BIT_SWAP; #endif /* If no TCL engine is present, turn off the HW TCL. */ if (!r300_screen(pipe->screen)->caps.has_tcl) { - rs->vap_control_status |= R300_VAP_TCL_BYPASS; + vap_control_status |= R300_VAP_TCL_BYPASS; } /* Point size width and height. */ - rs->point_size = + point_size = pack_float_16_6x(state->point_size) | (pack_float_16_6x(state->point_size) << R300_POINTSIZE_X_SHIFT); @@ -774,68 +920,67 @@ static void* r300_create_rs_state(struct pipe_context* pipe, * Clamp to [0, max FB size] */ psiz = pipe->screen->get_paramf(pipe->screen, PIPE_CAP_MAX_POINT_WIDTH); - rs->point_minmax = + point_minmax = pack_float_16_6x(psiz) << R300_GA_POINT_MINMAX_MAX_SHIFT; } else { /* We cannot disable the point-size vertex output, * so clamp it. */ psiz = state->point_size; - rs->point_minmax = + point_minmax = (pack_float_16_6x(psiz) << R300_GA_POINT_MINMAX_MIN_SHIFT) | (pack_float_16_6x(psiz) << R300_GA_POINT_MINMAX_MAX_SHIFT); } /* Line control. */ - rs->line_control = pack_float_16_6x(state->line_width) | + line_control = pack_float_16_6x(state->line_width) | R300_GA_LINE_CNTL_END_TYPE_COMP; /* Enable polygon mode */ + polygon_mode = 0; if (state->fill_front != PIPE_POLYGON_MODE_FILL || state->fill_back != PIPE_POLYGON_MODE_FILL) { - rs->polygon_mode = R300_GA_POLY_MODE_DUAL; + polygon_mode = R300_GA_POLY_MODE_DUAL; } /* Front face */ if (state->front_ccw) - rs->cull_mode = R300_FRONT_FACE_CCW; + cull_mode = R300_FRONT_FACE_CCW; else - rs->cull_mode = R300_FRONT_FACE_CW; + cull_mode = R300_FRONT_FACE_CW; /* Polygon offset */ + polygon_offset_enable = 0; if (util_get_offset(state, state->fill_front)) { - rs->polygon_offset_enable |= R300_FRONT_ENABLE; + polygon_offset_enable |= R300_FRONT_ENABLE; } if (util_get_offset(state, state->fill_back)) { - rs->polygon_offset_enable |= R300_BACK_ENABLE; + polygon_offset_enable |= R300_BACK_ENABLE; } + rs->polygon_offset_enable = polygon_offset_enable != 0; + /* Polygon mode */ - if (rs->polygon_mode) { - rs->polygon_mode |= + if (polygon_mode) { + polygon_mode |= r300_translate_polygon_mode_front(state->fill_front); - rs->polygon_mode |= + polygon_mode |= r300_translate_polygon_mode_back(state->fill_back); } if (state->cull_face & PIPE_FACE_FRONT) { - rs->cull_mode |= R300_CULL_FRONT; + cull_mode |= R300_CULL_FRONT; } if (state->cull_face & PIPE_FACE_BACK) { - rs->cull_mode |= R300_CULL_BACK; - } - - if (rs->polygon_offset_enable) { - rs->depth_offset = state->offset_units; - rs->depth_scale = state->offset_scale; + cull_mode |= R300_CULL_BACK; } if (state->line_stipple_enable) { - rs->line_stipple_config = + line_stipple_config = R300_GA_LINE_STIPPLE_CONFIG_LINE_RESET_LINE | (fui((float)state->line_stipple_factor) & R300_GA_LINE_STIPPLE_CONFIG_STIPPLE_SCALE_MASK); /* XXX this might need to be scaled up */ - rs->line_stipple_value = state->line_stipple_pattern; + line_stipple_value = state->line_stipple_pattern; } if (state->flatshade) { @@ -844,32 +989,80 @@ static void* r300_create_rs_state(struct pipe_context* pipe, rs->color_control = R300_SHADE_MODEL_SMOOTH; } - rs->clip_rule = state->scissor ? 0xAAAA : 0xFFFF; + clip_rule = state->scissor ? 0xAAAA : 0xFFFF; /* Point sprites */ + stuffing_enable = 0; if (state->sprite_coord_enable) { - rs->stuffing_enable = R300_GB_POINT_STUFF_ENABLE; + stuffing_enable = R300_GB_POINT_STUFF_ENABLE; for (i = 0; i < 8; i++) { if (state->sprite_coord_enable & (1 << i)) - rs->stuffing_enable |= + stuffing_enable |= R300_GB_TEX_STR << (R300_GB_TEX0_SOURCE_SHIFT + (i*2)); } - rs->point_texcoord_left = 0.0f; - rs->point_texcoord_right = 1.0f; + point_texcoord_left = 0.0f; + point_texcoord_right = 1.0f; switch (state->sprite_coord_mode) { case PIPE_SPRITE_COORD_UPPER_LEFT: - rs->point_texcoord_top = 0.0f; - rs->point_texcoord_bottom = 1.0f; + point_texcoord_top = 0.0f; + point_texcoord_bottom = 1.0f; break; case PIPE_SPRITE_COORD_LOWER_LEFT: - rs->point_texcoord_top = 1.0f; - rs->point_texcoord_bottom = 0.0f; + point_texcoord_top = 1.0f; + point_texcoord_bottom = 0.0f; break; } } + /* Build the main command buffer. */ + BEGIN_CB(rs->cb_main, 25); + OUT_CB_REG(R300_VAP_CNTL_STATUS, vap_control_status); + OUT_CB_REG(R300_GA_POINT_SIZE, point_size); + OUT_CB_REG_SEQ(R300_GA_POINT_MINMAX, 2); + OUT_CB(point_minmax); + OUT_CB(line_control); + OUT_CB_REG_SEQ(R300_SU_POLY_OFFSET_ENABLE, 2); + OUT_CB(polygon_offset_enable); + rs->cull_mode_index = 9; + OUT_CB(cull_mode); + OUT_CB_REG(R300_GA_LINE_STIPPLE_CONFIG, line_stipple_config); + OUT_CB_REG(R300_GA_LINE_STIPPLE_VALUE, line_stipple_value); + OUT_CB_REG(R300_GA_POLY_MODE, polygon_mode); + OUT_CB_REG(R300_SC_CLIP_RULE, clip_rule); + OUT_CB_REG(R300_GB_ENABLE, stuffing_enable); + OUT_CB_REG_SEQ(R300_GA_POINT_S0, 4); + OUT_CB_32F(point_texcoord_left); + OUT_CB_32F(point_texcoord_bottom); + OUT_CB_32F(point_texcoord_right); + OUT_CB_32F(point_texcoord_top); + END_CB; + + /* Build the two command buffers for polygon offset setup. */ + if (polygon_offset_enable) { + float scale = state->offset_scale * 12; + float offset = state->offset_units * 4; + + BEGIN_CB(rs->cb_poly_offset_zb16, 5); + OUT_CB_REG_SEQ(R300_SU_POLY_OFFSET_FRONT_SCALE, 4); + OUT_CB_32F(scale); + OUT_CB_32F(offset); + OUT_CB_32F(scale); + OUT_CB_32F(offset); + END_CB; + + offset = state->offset_units * 2; + + BEGIN_CB(rs->cb_poly_offset_zb24, 5); + OUT_CB_REG_SEQ(R300_SU_POLY_OFFSET_FRONT_SCALE, 4); + OUT_CB_32F(scale); + OUT_CB_32F(offset); + OUT_CB_32F(scale); + OUT_CB_32F(offset); + END_CB; + } + return (void*)rs; } @@ -899,7 +1092,7 @@ static void r300_bind_rs_state(struct pipe_context* pipe, void* state) } UPDATE_STATE(state, r300->rs_state); - r300->rs_state.size = 27 + (r300->polygon_offset_enabled ? 5 : 0); + r300->rs_state.size = 25 + (r300->polygon_offset_enabled ? 5 : 0); if (last_sprite_coord_enable != r300->sprite_coord_enable || last_two_sided_color != r300->two_sided_color) { @@ -925,10 +1118,34 @@ static void* sampler->state = *state; + /* r300 doesn't handle CLAMP and MIRROR_CLAMP correctly when either MAG + * or MIN filter is NEAREST. Since texwrap produces same results + * for CLAMP and CLAMP_TO_EDGE, we use them instead. */ + if (sampler->state.min_img_filter == PIPE_TEX_FILTER_NEAREST || + sampler->state.mag_img_filter == PIPE_TEX_FILTER_NEAREST) { + /* Wrap S. */ + if (sampler->state.wrap_s == PIPE_TEX_WRAP_CLAMP) + sampler->state.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + else if (sampler->state.wrap_s == PIPE_TEX_WRAP_MIRROR_CLAMP) + sampler->state.wrap_s = PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE; + + /* Wrap T. */ + if (sampler->state.wrap_t == PIPE_TEX_WRAP_CLAMP) + sampler->state.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + else if (sampler->state.wrap_t == PIPE_TEX_WRAP_MIRROR_CLAMP) + sampler->state.wrap_t = PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE; + + /* Wrap R. */ + if (sampler->state.wrap_r == PIPE_TEX_WRAP_CLAMP) + sampler->state.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + else if (sampler->state.wrap_r == PIPE_TEX_WRAP_MIRROR_CLAMP) + sampler->state.wrap_r = PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE; + } + sampler->filter0 |= - (r300_translate_wrap(state->wrap_s) << R300_TX_WRAP_S_SHIFT) | - (r300_translate_wrap(state->wrap_t) << R300_TX_WRAP_T_SHIFT) | - (r300_translate_wrap(state->wrap_r) << R300_TX_WRAP_R_SHIFT); + (r300_translate_wrap(sampler->state.wrap_s) << R300_TX_WRAP_S_SHIFT) | + (r300_translate_wrap(sampler->state.wrap_t) << R300_TX_WRAP_T_SHIFT) | + (r300_translate_wrap(sampler->state.wrap_r) << R300_TX_WRAP_R_SHIFT); sampler->filter0 |= r300_translate_tex_filters(state->min_img_filter, state->mag_img_filter, @@ -995,6 +1212,31 @@ static void r300_delete_sampler_state(struct pipe_context* pipe, void* state) FREE(state); } +static uint32_t r300_assign_texture_cache_region(unsigned index, unsigned num) +{ + /* This looks like a hack, but I believe it's suppose to work like + * that. To illustrate how this works, let's assume you have 5 textures. + * From docs, 5 and the successive numbers are: + * + * FOURTH_1 = 5 + * FOURTH_2 = 6 + * FOURTH_3 = 7 + * EIGHTH_0 = 8 + * EIGHTH_1 = 9 + * + * First 3 textures will get 3/4 of size of the cache, divived evenly + * between them. The last 1/4 of the cache must be divided between + * the last 2 textures, each will therefore get 1/8 of the cache. + * Why not just to use "5 + texture_index" ? + * + * This simple trick works for all "num" <= 16. + */ + if (num <= 1) + return R300_TX_CACHE(R300_TX_CACHE_WHOLE); + else + return R300_TX_CACHE(num + index); +} + static void r300_set_fragment_sampler_views(struct pipe_context* pipe, unsigned count, struct pipe_sampler_view** views) @@ -1003,7 +1245,7 @@ static void r300_set_fragment_sampler_views(struct pipe_context* pipe, struct r300_textures_state* state = (struct r300_textures_state*)r300->textures_state.state; struct r300_texture *texture; - unsigned i; + unsigned i, real_num_views = 0, view_index = 0; unsigned tex_units = r300->screen->caps.num_tex_units; boolean dirty_tex = FALSE; @@ -1011,6 +1253,12 @@ static void r300_set_fragment_sampler_views(struct pipe_context* pipe, return; } + /* Calculate the real number of views. */ + for (i = 0; i < count; i++) { + if (views[i]) + real_num_views++; + } + for (i = 0; i < count; i++) { if (&state->sampler_views[i]->base != views[i]) { pipe_sampler_view_reference( @@ -1030,6 +1278,10 @@ static void r300_set_fragment_sampler_views(struct pipe_context* pipe, if (texture->uses_pitch) { r300->fs_rc_constant_state.dirty = TRUE; } + + state->sampler_views[i]->texcache_region = + r300_assign_texture_cache_region(view_index, real_num_views); + view_index++; } } @@ -1167,15 +1419,15 @@ static void r300_set_vertex_buffers(struct pipe_context* pipe, if (r300->screen->caps.has_tcl) { /* HW TCL. */ - /* Check if the stride is aligned to the size of DWORD. */ + r300->incompatible_vb_layout = FALSE; + + /* Check if the strides and offsets are aligned to the size of DWORD. */ for (i = 0; i < count; i++) { if (buffers[i].buffer) { - if (buffers[i].stride % 4 != 0) { - // XXX Shouldn't we align the buffer? - fprintf(stderr, "r300: set_vertex_buffers: " - "Unaligned buffer stride %i isn't supported.\n", - buffers[i].stride); - abort(); + if (buffers[i].stride % 4 != 0 || + buffers[i].buffer_offset % 4 != 0) { + r300->incompatible_vb_layout = TRUE; + break; } } } @@ -1248,7 +1500,7 @@ static void r300_vertex_psc(struct r300_vertex_element_state *velems) * so PSC should just route stuff based on the vertex elements, * and not on attrib information. */ for (i = 0; i < velems->count; i++) { - format = velems->velem[i].src_format; + format = velems->hw_format[i]; type = r300_translate_vertex_data_type(format); if (type == R300_INVALID_FORMAT) { @@ -1280,12 +1532,15 @@ static void r300_vertex_psc(struct r300_vertex_element_state *velems) vstream->count = (i >> 1) + 1; } +#define FORMAT_REPLACE(what, withwhat) \ + case PIPE_FORMAT_##what: *format = PIPE_FORMAT_##withwhat; break + static void* r300_create_vertex_elements_state(struct pipe_context* pipe, unsigned count, const struct pipe_vertex_element* attribs) { struct r300_vertex_element_state *velems; - unsigned i, size; + unsigned i; enum pipe_format *format; assert(count <= PIPE_MAX_ATTRIBS); @@ -1295,86 +1550,68 @@ static void* r300_create_vertex_elements_state(struct pipe_context* pipe, memcpy(velems->velem, attribs, sizeof(struct pipe_vertex_element) * count); if (r300_screen(pipe->screen)->caps.has_tcl) { - r300_vertex_psc(velems); - - /* Check if the format is aligned to the size of DWORD. - * We only care about the blocksizes of the formats since - * swizzles are already set up. */ + /* Set the best hw format in case the original format is not + * supported by hw. */ for (i = 0; i < count; i++) { - format = &velems->velem[i].src_format; + velems->hw_format[i] = velems->velem[i].src_format; + format = &velems->hw_format[i]; - /* Replace some formats with their aligned counterparts, - * this is OK because we check for aligned strides too. */ + /* This is basically the list of unsupported formats. + * For now we don't care about the alignment, that's going to + * be sorted out after the PSC setup. */ switch (*format) { - /* Align to RGBA8. */ - case PIPE_FORMAT_R8_UNORM: - case PIPE_FORMAT_R8G8_UNORM: - case PIPE_FORMAT_R8G8B8_UNORM: - *format = PIPE_FORMAT_R8G8B8A8_UNORM; - continue; - case PIPE_FORMAT_R8_SNORM: - case PIPE_FORMAT_R8G8_SNORM: - case PIPE_FORMAT_R8G8B8_SNORM: - *format = PIPE_FORMAT_R8G8B8A8_SNORM; - continue; - case PIPE_FORMAT_R8_USCALED: - case PIPE_FORMAT_R8G8_USCALED: - case PIPE_FORMAT_R8G8B8_USCALED: - *format = PIPE_FORMAT_R8G8B8A8_USCALED; - continue; - case PIPE_FORMAT_R8_SSCALED: - case PIPE_FORMAT_R8G8_SSCALED: - case PIPE_FORMAT_R8G8B8_SSCALED: - *format = PIPE_FORMAT_R8G8B8A8_SSCALED; - continue; - - /* Align to RG16. */ - case PIPE_FORMAT_R16_UNORM: - *format = PIPE_FORMAT_R16G16_UNORM; - continue; - case PIPE_FORMAT_R16_SNORM: - *format = PIPE_FORMAT_R16G16_SNORM; - continue; - case PIPE_FORMAT_R16_USCALED: - *format = PIPE_FORMAT_R16G16_USCALED; - continue; - case PIPE_FORMAT_R16_SSCALED: - *format = PIPE_FORMAT_R16G16_SSCALED; - continue; - case PIPE_FORMAT_R16_FLOAT: - *format = PIPE_FORMAT_R16G16_FLOAT; - continue; - - /* Align to RGBA16. */ - case PIPE_FORMAT_R16G16B16_UNORM: - *format = PIPE_FORMAT_R16G16B16A16_UNORM; - continue; - case PIPE_FORMAT_R16G16B16_SNORM: - *format = PIPE_FORMAT_R16G16B16A16_SNORM; - continue; - case PIPE_FORMAT_R16G16B16_USCALED: - *format = PIPE_FORMAT_R16G16B16A16_USCALED; - continue; - case PIPE_FORMAT_R16G16B16_SSCALED: - *format = PIPE_FORMAT_R16G16B16A16_SSCALED; - continue; - case PIPE_FORMAT_R16G16B16_FLOAT: - *format = PIPE_FORMAT_R16G16B16A16_FLOAT; - continue; + FORMAT_REPLACE(R64_FLOAT, R32_FLOAT); + FORMAT_REPLACE(R64G64_FLOAT, R32G32_FLOAT); + FORMAT_REPLACE(R64G64B64_FLOAT, R32G32B32_FLOAT); + FORMAT_REPLACE(R64G64B64A64_FLOAT, R32G32B32A32_FLOAT); + + FORMAT_REPLACE(R32_UNORM, R32_FLOAT); + FORMAT_REPLACE(R32G32_UNORM, R32G32_FLOAT); + FORMAT_REPLACE(R32G32B32_UNORM, R32G32B32_FLOAT); + FORMAT_REPLACE(R32G32B32A32_UNORM, R32G32B32A32_FLOAT); + + FORMAT_REPLACE(R32_USCALED, R32_FLOAT); + FORMAT_REPLACE(R32G32_USCALED, R32G32_FLOAT); + FORMAT_REPLACE(R32G32B32_USCALED, R32G32B32_FLOAT); + FORMAT_REPLACE(R32G32B32A32_USCALED,R32G32B32A32_FLOAT); + + FORMAT_REPLACE(R32_SNORM, R32_FLOAT); + FORMAT_REPLACE(R32G32_SNORM, R32G32_FLOAT); + FORMAT_REPLACE(R32G32B32_SNORM, R32G32B32_FLOAT); + FORMAT_REPLACE(R32G32B32A32_SNORM, R32G32B32A32_FLOAT); + + FORMAT_REPLACE(R32_SSCALED, R32_FLOAT); + FORMAT_REPLACE(R32G32_SSCALED, R32G32_FLOAT); + FORMAT_REPLACE(R32G32B32_SSCALED, R32G32B32_FLOAT); + FORMAT_REPLACE(R32G32B32A32_SSCALED,R32G32B32A32_FLOAT); + + FORMAT_REPLACE(R32_FIXED, R32_FLOAT); + FORMAT_REPLACE(R32G32_FIXED, R32G32_FLOAT); + FORMAT_REPLACE(R32G32B32_FIXED, R32G32B32_FLOAT); + FORMAT_REPLACE(R32G32B32A32_FIXED, R32G32B32A32_FLOAT); default:; } - size = util_format_get_blocksize(*format); + velems->incompatible_layout = + velems->incompatible_layout || + velems->velem[i].src_format != velems->hw_format[i] || + velems->velem[i].src_offset % 4 != 0; + } - if (size % 4 != 0) { - /* XXX Shouldn't we align the format? */ - fprintf(stderr, "r300_create_vertex_elements_state: " - "Unaligned format %s:%i isn't supported\n", - util_format_short_name(*format), size); - assert(0); - abort(); - } + /* Now setup PSC. + * The unused components will be replaced by (..., 0, 1). */ + r300_vertex_psc(velems); + + /* Align the formats to the size of DWORD. + * We only care about the blocksizes of the formats since + * swizzles are already set up. + * Also compute the vertex size. */ + for (i = 0; i < count; i++) { + /* This is OK because we check for aligned strides too. */ + velems->hw_format_size[i] = + align(util_format_get_blocksize(velems->hw_format[i]), 4); + velems->vertex_size_dwords += velems->hw_format_size[i] / 4; } } } @@ -1412,7 +1649,6 @@ static void* r300_create_vs_state(struct pipe_context* pipe, const struct pipe_shader_state* shader) { struct r300_context* r300 = r300_context(pipe); - struct r300_vertex_shader* vs = CALLOC_STRUCT(r300_vertex_shader); /* Copy state directly into shader. */ @@ -1490,7 +1726,7 @@ static void r300_set_constant_buffer(struct pipe_context *pipe, struct r300_context* r300 = r300_context(pipe); struct r300_constant_buffer *cbuf; struct pipe_transfer *tr; - void *mapped; + float *mapped; int max_size = 0, max_size_bytes = 0, clamped_size = 0; switch (shader) { @@ -1529,10 +1765,20 @@ static void r300_set_constant_buffer(struct pipe_context *pipe, fprintf(stderr, "r300: Max size of the constant buffer is " "%i*4 floats.\n", max_size); } - clamped_size = MIN2(buf->width0, max_size_bytes); - memcpy(cbuf->constants, mapped, clamped_size); + clamped_size = MIN2(buf->width0, max_size_bytes); cbuf->count = clamped_size / (4 * sizeof(float)); + + if (shader == PIPE_SHADER_FRAGMENT && !r300->screen->caps.is_r500) { + unsigned i,j; + + /* Convert constants to float24. */ + for (i = 0; i < cbuf->count; i++) + for (j = 0; j < 4; j++) + cbuf->constants[i][j] = pack_float24(mapped[i*4+j]); + } else { + memcpy(cbuf->constants, mapped, clamped_size); + } } if (shader == PIPE_SHADER_VERTEX) { diff --git a/src/gallium/drivers/r300/r300_state.h b/src/gallium/drivers/r300/r300_state.h deleted file mode 100644 index 1d557506cf..0000000000 --- a/src/gallium/drivers/r300/r300_state.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2008 Marek Olšák <maraeo@gmail.com> - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef R300_STATE_H -#define R300_STATE_H - -struct r300_context; - -void r300_mark_fs_code_dirty(struct r300_context *r300); - -#endif /* R300_STATE_H */ diff --git a/src/gallium/drivers/r300/r300_state_derived.c b/src/gallium/drivers/r300/r300_state_derived.c index cc75fad3bb..3aa8deb63c 100644 --- a/src/gallium/drivers/r300/r300_state_derived.c +++ b/src/gallium/drivers/r300/r300_state_derived.c @@ -31,7 +31,6 @@ #include "r300_hyperz.h" #include "r300_screen.h" #include "r300_shader_semantics.h" -#include "r300_state.h" #include "r300_state_derived.h" #include "r300_state_inlines.h" #include "r300_texture.h" @@ -537,6 +536,10 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300) UTIL_FORMAT_SWIZZLE_X }; + /* The KIL opcode fix, see below. */ + if (!count && !r300->screen->caps.is_r500) + count = 1; + state->tx_enable = 0; state->count = 0; size = 2; @@ -555,6 +558,9 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300) texstate->filter1 = sampler->filter1; texstate->border_color = sampler->border_color; + /* Assign a texture cache region. */ + texstate->format.format1 |= view->texcache_region; + /* If compare mode is disabled, the sampler view swizzles * are stored in the format. * Otherwise, swizzles must be applied after the compare mode @@ -613,6 +619,36 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300) size += 16; state->count = i+1; + } else { + /* For the KIL opcode to work on r3xx-r4xx, the texture unit + * assigned to this opcode (it's always the first one) must be + * enabled. Otherwise the opcode doesn't work. + * + * In order to not depend on the fragment shader, we just make + * the first unit enabled all the time. */ + if (i == 0 && !r300->screen->caps.is_r500) { + pipe_sampler_view_reference( + (struct pipe_sampler_view**)&state->sampler_views[i], + &r300->texkill_sampler->base); + + state->tx_enable |= 1 << i; + + texstate = &state->regs[i]; + + /* Just set some valid state. */ + texstate->format = r300->texkill_sampler->format; + texstate->filter0 = + r300_translate_tex_filters(PIPE_TEX_FILTER_NEAREST, + PIPE_TEX_FILTER_NEAREST, + PIPE_TEX_FILTER_NEAREST, + FALSE); + texstate->filter1 = 0; + texstate->border_color = 0; + + texstate->filter0 |= i << 28; + size += 16; + state->count = i+1; + } } } diff --git a/src/gallium/drivers/r300/r300_state_invariant.c b/src/gallium/drivers/r300/r300_state_invariant.c deleted file mode 100644 index 34d3a169d5..0000000000 --- a/src/gallium/drivers/r300/r300_state_invariant.c +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright 2009 Joakim Sindholt <opensource@zhasha.com> - * Corbin Simpson <MostAwesomeDude@gmail.com> - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "r300_context.h" -#include "r300_cs.h" -#include "r300_reg.h" -#include "r300_screen.h" -#include "r300_state_invariant.h" - -/* Calculate and emit invariant state. This is data that the 3D engine - * will probably want at the beginning of every CS, but it's not currently - * handled by any CSO setup, and in addition it doesn't really change much. - * - * Note that eventually this should be empty, but it's useful for development - * and general unduplication of code. */ -void r300_emit_invariant_state(struct r300_context* r300, - unsigned size, void* state) -{ - CS_LOCALS(r300); - - if (r300->rws->get_value(r300->rws, R300_VID_DRM_2_3_0)) { - /* Subpixel multisampling for AA. */ - BEGIN_CS(4); - OUT_CS_REG(R300_GB_MSPOS0, 0x66666666); - OUT_CS_REG(R300_GB_MSPOS1, 0x6666666); - END_CS; - } - - BEGIN_CS(12 + (r300->screen->caps.has_tcl ? 2 : 0)); - - /*** Graphics Backend (GB) ***/ - /* Source of fog depth */ - OUT_CS_REG(R300_GB_SELECT, R300_GB_FOG_SELECT_1_1_W); - - /*** Fog (FG) ***/ - OUT_CS_REG(R300_FG_FOG_BLEND, 0x0); - OUT_CS_REG(R300_FG_FOG_COLOR_R, 0x0); - OUT_CS_REG(R300_FG_FOG_COLOR_G, 0x0); - OUT_CS_REG(R300_FG_FOG_COLOR_B, 0x0); - - /*** VAP ***/ - /* Sign/normalize control */ - OUT_CS_REG(R300_VAP_PSC_SGN_NORM_CNTL, R300_SGN_NORM_NO_ZERO); - /* TCL-only stuff */ - if (r300->screen->caps.has_tcl) { - /* Amount of time to wait for vertex fetches in PVS */ - OUT_CS_REG(VAP_PVS_VTX_TIMEOUT_REG, 0xffff); - } - - END_CS; - - /* XXX unsorted stuff from surface_fill */ - BEGIN_CS(38 + (r300->screen->caps.has_tcl ? 7 : 0) + - (r300->screen->caps.is_rv350 ? 4 : 0)); - - if (r300->screen->caps.has_tcl) { - /*Flushing PVS is required before the VAP_GB registers can be changed*/ - OUT_CS_REG(R300_VAP_PVS_STATE_FLUSH_REG, 0); - OUT_CS_REG_SEQ(R300_VAP_GB_VERT_CLIP_ADJ, 4); - OUT_CS_32F(1.0); - OUT_CS_32F(1.0); - OUT_CS_32F(1.0); - OUT_CS_32F(1.0); - } - /* XXX line tex stuffing */ - OUT_CS_REG_SEQ(R300_GA_LINE_S0, 1); - OUT_CS_32F(0.0); - OUT_CS_REG_SEQ(R300_GA_LINE_S1, 1); - OUT_CS_32F(1.0); - OUT_CS_REG(R300_GA_TRIANGLE_STIPPLE, 0x5 | - (0x5 << R300_GA_TRIANGLE_STIPPLE_Y_SHIFT_SHIFT)); - /* XXX this big chunk should be refactored into rs_state */ - OUT_CS_REG(R300_GA_SOLID_RG, 0x00000000); - OUT_CS_REG(R300_GA_SOLID_BA, 0x00000000); - OUT_CS_REG(R300_GA_ROUND_MODE, 0x00000001); - OUT_CS_REG(R300_GA_OFFSET, 0x00000000); - OUT_CS_REG(R300_GA_FOG_SCALE, 0x3DBF1412); - OUT_CS_REG(R300_GA_FOG_OFFSET, 0x00000000); - OUT_CS_REG(R300_SU_TEX_WRAP, 0x00000000); - OUT_CS_REG(R300_SU_DEPTH_SCALE, 0x4B7FFFFF); - OUT_CS_REG(R300_SU_DEPTH_OFFSET, 0x00000000); - OUT_CS_REG(R300_SC_HYPERZ, 0x0000001C); - OUT_CS_REG(R300_SC_EDGERULE, 0x2DA49525); - OUT_CS_REG(R300_RB3D_AARESOLVE_CTL, 0x00000000); - - if (r300->screen->caps.is_rv350) { - OUT_CS_REG(R500_RB3D_DISCARD_SRC_PIXEL_LTE_THRESHOLD, 0x01010101); - OUT_CS_REG(R500_RB3D_DISCARD_SRC_PIXEL_GTE_THRESHOLD, 0xFEFEFEFE); - } - - OUT_CS_REG(R300_ZB_BW_CNTL, 0x00000000); - OUT_CS_REG(R300_ZB_DEPTHCLEARVALUE, 0x00000000); - OUT_CS_REG(R300_ZB_HIZ_OFFSET, 0x00000000); - OUT_CS_REG(R300_ZB_HIZ_PITCH, 0x00000000); - END_CS; -} diff --git a/src/gallium/drivers/r300/r300_state_invariant.h b/src/gallium/drivers/r300/r300_state_invariant.h deleted file mode 100644 index 83d031c7fe..0000000000 --- a/src/gallium/drivers/r300/r300_state_invariant.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com> - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef R300_STATE_INVARIANT_H -#define R300_STATE_INVARIANT_H - -struct r300_context; - -void r300_emit_invariant_state(struct r300_context* r300, - unsigned size, void* state); - -#endif /* R300_STATE_INVARIANT_H */ diff --git a/src/gallium/drivers/r300/r300_texture.c b/src/gallium/drivers/r300/r300_texture.c index 5a013e2a25..6206570fca 100644 --- a/src/gallium/drivers/r300/r300_texture.c +++ b/src/gallium/drivers/r300/r300_texture.c @@ -21,30 +21,28 @@ * 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 "util/u_format.h" -#include "util/u_format_s3tc.h" -#include "util/u_math.h" -#include "util/u_memory.h" +/* Always include headers in the reverse order!! ~ M. */ +#include "r300_texture.h" #include "r300_context.h" #include "r300_reg.h" -#include "r300_texture.h" #include "r300_transfer.h" #include "r300_screen.h" #include "r300_winsys.h" -#define TILE_WIDTH 0 -#define TILE_HEIGHT 1 +#include "util/u_format.h" +#include "util/u_format_s3tc.h" +#include "util/u_math.h" +#include "util/u_memory.h" + +#include "pipe/p_screen.h" -static const unsigned microblock_table[5][3][2] = { - /*linear tiled square-tiled */ - {{32, 1}, {8, 4}, {0, 0}}, /* 8 bits per pixel */ - {{16, 1}, {8, 2}, {4, 4}}, /* 16 bits per pixel */ - {{ 8, 1}, {4, 2}, {0, 0}}, /* 32 bits per pixel */ - {{ 4, 1}, {0, 0}, {2, 2}}, /* 64 bits per pixel */ - {{ 2, 1}, {0, 0}, {0, 0}} /* 128 bits per pixel */ +/* XXX NO! just no! */ +#include "state_tracker/drm_driver.h" + +enum r300_dim { + DIM_WIDTH = 0, + DIM_HEIGHT = 1 }; unsigned r300_get_swizzle_combined(const unsigned char *swizzle_format, @@ -596,21 +594,21 @@ static void r300_texture_setup_fb_state(struct r300_screen* screen, /* Set framebuffer state. */ if (util_format_is_depth_or_stencil(tex->b.b.format)) { for (i = 0; i <= tex->b.b.last_level; i++) { - tex->fb_state.depthpitch[i] = + tex->fb_state.pitch[i] = tex->hwpitch[i] | R300_DEPTHMACROTILE(tex->mip_macrotile[i]) | R300_DEPTHMICROTILE(tex->microtile); } - tex->fb_state.zb_format = r300_translate_zsformat(tex->b.b.format); + tex->fb_state.format = r300_translate_zsformat(tex->b.b.format); } else { for (i = 0; i <= tex->b.b.last_level; i++) { - tex->fb_state.colorpitch[i] = + tex->fb_state.pitch[i] = tex->hwpitch[i] | r300_translate_colorformat(tex->b.b.format) | R300_COLOR_TILE(tex->mip_macrotile[i]) | R300_COLOR_MICROTILE(tex->microtile); } - tex->fb_state.us_out_fmt = r300_translate_out_fmt(tex->b.b.format); + tex->fb_state.format = r300_translate_out_fmt(tex->b.b.format); } } @@ -620,8 +618,10 @@ void r300_texture_reinterpret_format(struct pipe_screen *screen, { struct r300_screen *r300screen = r300_screen(screen); - SCREEN_DBG(r300screen, DBG_TEX, "r300: texture_reinterpret_format: %s -> %s\n", - util_format_short_name(tex->format), util_format_short_name(new_format)); + SCREEN_DBG(r300screen, DBG_TEX, + "r300: texture_reinterpret_format: %s -> %s\n", + util_format_short_name(tex->format), + util_format_short_name(new_format)); tex->format = new_format; @@ -648,36 +648,65 @@ unsigned r300_texture_get_offset(struct r300_texture* tex, unsigned level, } } -/** - * Return the width (dim==TILE_WIDTH) or height (dim==TILE_HEIGHT) of one tile - * of the given texture. - */ -static unsigned r300_texture_get_tile_size(struct r300_texture* tex, - int dim, boolean macrotile) +/* Returns the number of pixels that the texture should be aligned to + * in the given dimension. */ +static unsigned r300_get_pixel_alignment(struct r300_texture *tex, + enum r300_buffer_tiling macrotile, + enum r300_dim dim) { - unsigned pixsize, tile_size; - - pixsize = util_format_get_blocksize(tex->b.b.format); - tile_size = microblock_table[util_logbase2(pixsize)][tex->microtile][dim]; - - if (macrotile) { - tile_size *= 8; + static const unsigned table[2][5][3][2] = + { + { + /* Macro: linear linear linear + Micro: linear tiled square-tiled */ + {{ 32, 1}, { 8, 4}, { 0, 0}}, /* 8 bits per pixel */ + {{ 16, 1}, { 8, 2}, { 4, 4}}, /* 16 bits per pixel */ + {{ 8, 1}, { 4, 2}, { 0, 0}}, /* 32 bits per pixel */ + {{ 4, 1}, { 0, 0}, { 2, 2}}, /* 64 bits per pixel */ + {{ 2, 1}, { 0, 0}, { 0, 0}} /* 128 bits per pixel */ + }, + { + /* Macro: tiled tiled tiled + Micro: linear tiled square-tiled */ + {{256, 8}, {64, 32}, { 0, 0}}, /* 8 bits per pixel */ + {{128, 8}, {64, 16}, {32, 32}}, /* 16 bits per pixel */ + {{ 64, 8}, {32, 16}, { 0, 0}}, /* 32 bits per pixel */ + {{ 32, 8}, { 0, 0}, {16, 16}}, /* 64 bits per pixel */ + {{ 16, 8}, { 0, 0}, { 0, 0}} /* 128 bits per pixel */ + } + }; + static const unsigned aa_block[2] = {4, 8}; + unsigned res = 0; + unsigned pixsize = util_format_get_blocksize(tex->b.b.format); + + assert(macrotile <= R300_BUFFER_TILED); + assert(tex->microtile <= R300_BUFFER_SQUARETILED); + assert(pixsize <= 16); + assert(dim <= DIM_HEIGHT); + + if (tex->b.b.nr_samples > 1) { + /* Multisampled textures have their own alignment scheme. */ + if (pixsize == 4) + res = aa_block[dim]; + } else { + /* Standard alignment. */ + res = table[macrotile][util_logbase2(pixsize)][tex->microtile][dim]; } - assert(tile_size); - return tile_size; + assert(res); + return res; } /* Return true if macrotiling should be enabled on the miplevel. */ static boolean r300_texture_macro_switch(struct r300_texture *tex, unsigned level, boolean rv350_mode, - int dim) + enum r300_dim dim) { unsigned tile, texdim; - tile = r300_texture_get_tile_size(tex, dim, TRUE); - if (dim == TILE_WIDTH) { + tile = r300_get_pixel_alignment(tex, R300_BUFFER_TILED, dim); + if (dim == DIM_WIDTH) { texdim = u_minify(tex->b.b.width0, level); } else { texdim = u_minify(tex->b.b.height0, level); @@ -713,8 +742,8 @@ unsigned r300_texture_get_stride(struct r300_screen* screen, width = u_minify(tex->b.b.width0, level); if (util_format_is_plain(tex->b.b.format)) { - tile_width = r300_texture_get_tile_size(tex, TILE_WIDTH, - tex->mip_macrotile[level]); + tile_width = r300_get_pixel_alignment(tex, tex->mip_macrotile[level], + DIM_WIDTH); width = align(width, tile_width); stride = util_format_get_stride(tex->b.b.format, width); @@ -743,8 +772,8 @@ static unsigned r300_texture_get_nblocksy(struct r300_texture* tex, height = u_minify(tex->b.b.height0, level); if (util_format_is_plain(tex->b.b.format)) { - tile_height = r300_texture_get_tile_size(tex, TILE_HEIGHT, - tex->mip_macrotile[level]); + tile_height = r300_get_pixel_alignment(tex, tex->mip_macrotile[level], + DIM_HEIGHT); height = align(height, tile_height); /* This is needed for the kernel checker, unfortunately. */ @@ -784,21 +813,26 @@ static void r300_setup_miptree(struct r300_screen* screen, unsigned stride, size, layer_size, nblocksy, i; boolean rv350_mode = screen->caps.is_rv350; - SCREEN_DBG(screen, DBG_TEXALLOC, "r300: Making miptree for texture, format %s\n", - util_format_short_name(base->format)); + SCREEN_DBG(screen, DBG_TEXALLOC, + "r300: Making miptree for texture, format %s\n", + util_format_short_name(base->format)); for (i = 0; i <= base->last_level; i++) { /* Let's see if this miplevel can be macrotiled. */ tex->mip_macrotile[i] = (tex->macrotile == R300_BUFFER_TILED && - r300_texture_macro_switch(tex, i, rv350_mode, TILE_WIDTH) && - r300_texture_macro_switch(tex, i, rv350_mode, TILE_HEIGHT)) ? + r300_texture_macro_switch(tex, i, rv350_mode, DIM_WIDTH) && + r300_texture_macro_switch(tex, i, rv350_mode, DIM_HEIGHT)) ? R300_BUFFER_TILED : R300_BUFFER_LINEAR; stride = r300_texture_get_stride(screen, tex, i); nblocksy = r300_texture_get_nblocksy(tex, i); layer_size = stride * nblocksy; + if (base->nr_samples) { + layer_size *= base->nr_samples; + } + if (base->target == PIPE_TEXTURE_CUBE) size = layer_size * 6; else @@ -864,8 +898,8 @@ static void r300_setup_tiling(struct pipe_screen *screen, } /* Set macrotiling. */ - if (r300_texture_macro_switch(tex, 0, rv350_mode, TILE_WIDTH) && - r300_texture_macro_switch(tex, 0, rv350_mode, TILE_HEIGHT)) { + if (r300_texture_macro_switch(tex, 0, rv350_mode, DIM_WIDTH) && + r300_texture_macro_switch(tex, 0, rv350_mode, DIM_HEIGHT)) { tex->macrotile = R300_BUFFER_TILED; } } @@ -899,17 +933,14 @@ static boolean r300_texture_get_handle(struct pipe_screen* screen, { struct r300_winsys_screen *rws = (struct r300_winsys_screen *)screen->winsys; struct r300_texture* tex = (struct r300_texture*)texture; - unsigned stride; if (!tex) { return FALSE; } - stride = r300_texture_get_stride(r300_screen(screen), tex, 0); - - rws->buffer_get_handle(rws, tex->buffer, stride, whandle); + whandle->stride = r300_texture_get_stride(r300_screen(screen), tex, 0); - return TRUE; + return rws->buffer_get_handle(rws, tex->buffer, whandle); } struct u_resource_vtbl r300_texture_vtbl = @@ -966,11 +997,12 @@ struct pipe_resource* r300_texture_create(struct pipe_screen* screen, SCREEN_DBG(rscreen, DBG_TEX, "r300: texture_create: Macro: %s, Micro: %s, Pitch: %i, " - "Dim: %ix%ix%i, LastLevel: %i, Format: %s\n", + "Dim: %ix%ix%i, LastLevel: %i, Size: %i, Format: %s\n", tex->macrotile ? "YES" : " NO", tex->microtile ? "YES" : " NO", tex->hwpitch[0], base->width0, base->height0, base->depth0, base->last_level, + tex->size, util_format_short_name(base->format)); tex->domain = base->flags & R300_RESOURCE_FLAG_TRANSFER ? R300_DOMAIN_GTT : @@ -979,16 +1011,16 @@ struct pipe_resource* r300_texture_create(struct pipe_screen* screen, tex->buffer = rws->buffer_create(rws, 2048, base->bind, tex->domain, tex->size); + if (!tex->buffer) { + FREE(tex); + return NULL; + } + rws->buffer_set_tiling(rws, tex->buffer, tex->pitch[0] * util_format_get_blocksize(tex->b.b.format), tex->microtile, tex->macrotile); - if (!tex->buffer) { - FREE(tex); - return NULL; - } - return (struct pipe_resource*)tex; } @@ -1002,26 +1034,27 @@ struct pipe_surface* r300_get_tex_surface(struct pipe_screen* screen, unsigned flags) { struct r300_texture* tex = r300_texture(texture); - struct pipe_surface* surface = CALLOC_STRUCT(pipe_surface); - unsigned offset; - - offset = r300_texture_get_offset(tex, level, zslice, face); + struct r300_surface* surface = CALLOC_STRUCT(r300_surface); if (surface) { - pipe_reference_init(&surface->reference, 1); - pipe_resource_reference(&surface->texture, texture); - surface->format = texture->format; - surface->width = u_minify(texture->width0, level); - surface->height = u_minify(texture->height0, level); - surface->offset = offset; - surface->usage = flags; - surface->zslice = zslice; - surface->texture = texture; - surface->face = face; - surface->level = level; + pipe_reference_init(&surface->base.reference, 1); + pipe_resource_reference(&surface->base.texture, texture); + surface->base.format = texture->format; + surface->base.width = u_minify(texture->width0, level); + surface->base.height = u_minify(texture->height0, level); + surface->base.usage = flags; + surface->base.zslice = zslice; + surface->base.face = face; + surface->base.level = level; + + surface->buffer = tex->buffer; + surface->domain = tex->domain; + surface->offset = r300_texture_get_offset(tex, level, zslice, face); + surface->pitch = tex->fb_state.pitch[level]; + surface->format = tex->fb_state.format; } - return surface; + return &surface->base; } /* Not required to implement u_resource_vtbl, consider moving to another file: @@ -1041,7 +1074,6 @@ r300_texture_from_handle(struct pipe_screen* screen, struct r300_screen* rscreen = r300_screen(screen); struct r300_winsys_buffer *buffer; struct r300_texture* tex; - unsigned stride; boolean override_zb_flags; /* Support only 2D textures without mipmaps */ @@ -1051,7 +1083,8 @@ r300_texture_from_handle(struct pipe_screen* screen, return NULL; } - buffer = rws->buffer_from_handle(rws, screen, whandle, &stride); + /* XXX make the winsys return the stride_override, see i915_resource_texture.c:830 */ + buffer = rws->buffer_from_handle(rws, whandle->handle); if (!buffer) { return NULL; } @@ -1067,7 +1100,7 @@ r300_texture_from_handle(struct pipe_screen* screen, tex->b.b.screen = screen; tex->domain = R300_DOMAIN_VRAM; - tex->stride_override = stride; + tex->stride_override = whandle->stride; /* one ref already taken */ tex->buffer = buffer; @@ -1079,7 +1112,7 @@ r300_texture_from_handle(struct pipe_screen* screen, "Pitch: % 4i, Dim: %ix%i, Format: %s\n", tex->macrotile ? "YES" : " NO", tex->microtile ? "YES" : " NO", - stride / util_format_get_blocksize(base->format), + whandle->stride / util_format_get_blocksize(base->format), base->width0, base->height0, util_format_short_name(base->format)); diff --git a/src/gallium/drivers/r300/r300_texture.h b/src/gallium/drivers/r300/r300_texture.h index ff640c56ee..99e7694254 100644 --- a/src/gallium/drivers/r300/r300_texture.h +++ b/src/gallium/drivers/r300/r300_texture.h @@ -23,8 +23,11 @@ #ifndef R300_TEXTURE_H #define R300_TEXTURE_H -#include "util/u_format.h" +#include "pipe/p_format.h" +struct pipe_screen; +struct pipe_resource; +struct winsys_handle; struct r300_texture; struct r300_screen; diff --git a/src/gallium/drivers/r300/r300_tgsi_to_rc.c b/src/gallium/drivers/r300/r300_tgsi_to_rc.c index 89f39af976..5394e04f72 100644 --- a/src/gallium/drivers/r300/r300_tgsi_to_rc.c +++ b/src/gallium/drivers/r300/r300_tgsi_to_rc.c @@ -105,12 +105,12 @@ static unsigned translate_opcode(unsigned opcode) /* case TGSI_OPCODE_DIV: return RC_OPCODE_DIV; */ /* case TGSI_OPCODE_DP2: return RC_OPCODE_DP2; */ case TGSI_OPCODE_TXL: return RC_OPCODE_TXL; - /* case TGSI_OPCODE_BRK: return RC_OPCODE_BRK; */ + case TGSI_OPCODE_BRK: return RC_OPCODE_BRK; case TGSI_OPCODE_IF: return RC_OPCODE_IF; - /* case TGSI_OPCODE_LOOP: return RC_OPCODE_LOOP; */ + case TGSI_OPCODE_BGNLOOP: return RC_OPCODE_BGNLOOP; case TGSI_OPCODE_ELSE: return RC_OPCODE_ELSE; case TGSI_OPCODE_ENDIF: return RC_OPCODE_ENDIF; - /* case TGSI_OPCODE_ENDLOOP: return RC_OPCODE_ENDLOOP; */ + case TGSI_OPCODE_ENDLOOP: return RC_OPCODE_ENDLOOP; /* case TGSI_OPCODE_PUSHA: return RC_OPCODE_PUSHA; */ /* case TGSI_OPCODE_POPA: return RC_OPCODE_POPA; */ case TGSI_OPCODE_CEIL: return RC_OPCODE_CEIL; diff --git a/src/gallium/drivers/r300/r300_transfer.c b/src/gallium/drivers/r300/r300_transfer.c index 0d88d745c0..02421a58b8 100644 --- a/src/gallium/drivers/r300/r300_transfer.c +++ b/src/gallium/drivers/r300/r300_transfer.c @@ -57,22 +57,11 @@ static void r300_copy_from_tiled_texture(struct pipe_context *ctx, subdst.face = 0; subdst.level = 0; - /* XXX if we don't flush before copying the texture and mapping it, - * we get wrong pixels, i.e. it's like latest draw calls didn't happen, - * including this blit. Tests: e.g. piglit/provoking-vertex - * - * Since the flush immediately before mapping is implicit (the buffer is - * always referenced in resource_copy_region), every read transfer costs - * 2 flushes. That sucks. */ - ctx->flush(ctx, 0, NULL); - ctx->resource_copy_region(ctx, &r300transfer->detiled_texture->b.b, subdst, 0, 0, 0, tex, transfer->sr, transfer->box.x, transfer->box.y, transfer->box.z, transfer->box.width, transfer->box.height); - - /* Flushing after the copy is implicit, issued by winsys. */ } /* Copy a detiled texture to a tiled one. */ @@ -92,7 +81,6 @@ static void r300_copy_into_tiled_texture(struct pipe_context *ctx, 0, 0, 0, transfer->box.width, transfer->box.height); - /* XXX this flush fixes a few piglit tests (e.g. glean/pixelFormats). */ ctx->flush(ctx, 0, NULL); } @@ -107,7 +95,7 @@ r300_texture_get_transfer(struct pipe_context *ctx, struct r300_screen *r300screen = r300_screen(ctx->screen); struct r300_transfer *trans; struct pipe_resource base; - boolean referenced_cs, referenced_hw; + boolean referenced_cs, referenced_hw, blittable; referenced_cs = r300screen->rws->is_buffer_referenced( r300screen->rws, tex->buffer, R300_REF_CS); @@ -118,6 +106,10 @@ r300_texture_get_transfer(struct pipe_context *ctx, r300screen->rws, tex->buffer, R300_REF_HW); } + blittable = ctx->screen->is_format_supported( + ctx->screen, texture->format, texture->target, 0, + PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET, 0); + trans = CALLOC_STRUCT(r300_transfer); if (trans) { /* Initialize the transfer object. */ @@ -130,7 +122,7 @@ r300_texture_get_transfer(struct pipe_context *ctx, * for this transfer. * Also make write transfers pipelined. */ if (tex->microtile || tex->macrotile || - (referenced_hw & !(usage & PIPE_TRANSFER_READ))) { + ((referenced_hw & !(usage & PIPE_TRANSFER_READ)) && blittable)) { base.target = PIPE_TEXTURE_2D; base.format = texture->format; base.width0 = box->width; @@ -158,6 +150,30 @@ r300_texture_get_transfer(struct pipe_context *ctx, ctx->screen->resource_create(ctx->screen, &base)); + if (!trans->detiled_texture) { + /* Oh crap, the thing can't create the texture. + * Let's flush and try again. */ + ctx->flush(ctx, 0, NULL); + + trans->detiled_texture = r300_texture( + ctx->screen->resource_create(ctx->screen, + &base)); + + if (!trans->detiled_texture) { + /* For linear textures, it's safe to fallback to + * an unpipelined transfer. */ + if (!tex->microtile && !tex->macrotile) { + goto unpipelined; + } + + /* Otherwise, go to hell. */ + fprintf(stderr, + "r300: Failed to create a transfer object, praise.\n"); + FREE(trans); + return NULL; + } + } + assert(!trans->detiled_texture->microtile && !trans->detiled_texture->macrotile); @@ -179,16 +195,20 @@ r300_texture_get_transfer(struct pipe_context *ctx, /* Always referenced in the blit. */ ctx->flush(ctx, 0, NULL); } - } else { - trans->transfer.stride = + return &trans->transfer; + } + + unpipelined: + /* Unpipelined transfer. */ + trans->transfer.stride = r300_texture_get_stride(r300screen, tex, sr.level); - trans->offset = r300_texture_get_offset(tex, sr.level, box->z, sr.face); + trans->offset = r300_texture_get_offset(tex, sr.level, box->z, sr.face); - if (referenced_cs && (usage & PIPE_TRANSFER_READ)) - ctx->flush(ctx, PIPE_FLUSH_RENDER_CACHE, NULL); - } + if (referenced_cs && (usage & PIPE_TRANSFER_READ)) + ctx->flush(ctx, PIPE_FLUSH_RENDER_CACHE, NULL); + return &trans->transfer; } - return &trans->transfer; + return NULL; } void r300_texture_transfer_destroy(struct pipe_context *ctx, diff --git a/src/gallium/drivers/r300/r300_winsys.h b/src/gallium/drivers/r300/r300_winsys.h index 8a8888d481..3b5e9eec60 100644 --- a/src/gallium/drivers/r300/r300_winsys.h +++ b/src/gallium/drivers/r300/r300_winsys.h @@ -47,13 +47,6 @@ enum r300_reference_domain { /* bitfield */ R300_REF_HW = 2 }; -struct r300_cs_info { - /* In DWORDs. */ - unsigned used; - unsigned free; - unsigned capacity; -}; - struct r300_winsys_screen { void (*destroy)(struct r300_winsys_screen *ws); @@ -109,16 +102,13 @@ struct r300_winsys_screen { * Returns TRUE if a flush is required. */ boolean (*validate)(struct r300_winsys_screen* winsys); - /* Return current CS info. */ - void (*get_cs_info)(struct r300_winsys_screen *winsys, - struct r300_cs_info *info); + /* Return the number of free dwords in CS. */ + unsigned (*get_cs_free_dwords)(struct r300_winsys_screen *winsys); - /* Start a command emit. */ - void (*begin_cs)(struct r300_winsys_screen* winsys, - int size, - const char* file, - const char* function, - int line); + /* Return the pointer to the first free dword in CS and assume a pipe + * driver wants to fill "count" dwords. */ + uint32_t *(*get_cs_pointer)(struct r300_winsys_screen *winsys, + unsigned count); /* Write a dword to the command buffer. */ void (*write_cs_dword)(struct r300_winsys_screen* winsys, uint32_t dword); @@ -134,12 +124,6 @@ struct r300_winsys_screen { enum r300_buffer_domain wd, uint32_t flags); - /* Finish a command emit. */ - void (*end_cs)(struct r300_winsys_screen* winsys, - const char* file, - const char* function, - int line); - /* Flush the CS. */ void (*flush_cs)(struct r300_winsys_screen* winsys); @@ -164,12 +148,10 @@ struct r300_winsys_screen { enum r300_value_id vid); struct r300_winsys_buffer *(*buffer_from_handle)(struct r300_winsys_screen *winsys, - struct pipe_screen *screen, - struct winsys_handle *whandle, - unsigned *stride); + unsigned handle); + boolean (*buffer_get_handle)(struct r300_winsys_screen *winsys, struct r300_winsys_buffer *buffer, - unsigned stride, struct winsys_handle *whandle); boolean (*is_buffer_referenced)(struct r300_winsys_screen *winsys, diff --git a/src/gallium/drivers/r600/r600_blit.c b/src/gallium/drivers/r600/r600_blit.c index 80c3069cf5..1dcb19babc 100644 --- a/src/gallium/drivers/r600/r600_blit.c +++ b/src/gallium/drivers/r600/r600_blit.c @@ -49,6 +49,9 @@ static void r600_blitter_save_states(struct r600_context *rctx) rctx->vertex_elements); util_blitter_save_viewport(rctx->blitter, &rctx->viewport); + /* XXX util_blitter_save_clip(rctx->blitter, &rctx->clip); */ + util_blitter_save_vertex_buffers(rctx->blitter, rctx->nvertex_buffer, + rctx->vertex_buffer); } static void r600_clear(struct pipe_context *ctx, unsigned buffers, diff --git a/src/gallium/drivers/r600/r600_helper.c b/src/gallium/drivers/r600/r600_helper.c index 9370a5355e..e3175b627a 100644 --- a/src/gallium/drivers/r600/r600_helper.c +++ b/src/gallium/drivers/r600/r600_helper.c @@ -26,7 +26,6 @@ #include <stdio.h> #include <errno.h> #include <util/u_inlines.h> -#include <util/u_format.h> #include "r600_screen.h" #include "r600d.h" diff --git a/src/gallium/drivers/r600/r600_query.c b/src/gallium/drivers/r600/r600_query.c index 24746e7877..9b02ae680e 100644 --- a/src/gallium/drivers/r600/r600_query.c +++ b/src/gallium/drivers/r600/r600_query.c @@ -50,7 +50,7 @@ static void r600_end_query(struct pipe_context *pipe, struct pipe_query *query) static boolean r600_get_query_result(struct pipe_context *pipe, struct pipe_query *query, - boolean wait, uint64_t *result) + boolean wait, void *result) { return TRUE; } diff --git a/src/gallium/drivers/rbug/rbug_context.c b/src/gallium/drivers/rbug/rbug_context.c index 164d811ab4..00b167e256 100644 --- a/src/gallium/drivers/rbug/rbug_context.c +++ b/src/gallium/drivers/rbug/rbug_context.c @@ -241,7 +241,7 @@ static boolean rbug_get_query_result(struct pipe_context *_pipe, struct pipe_query *query, boolean wait, - uint64_t *result) + void *result) { struct rbug_context *rb_pipe = rbug_context(_pipe); struct pipe_context *pipe = rb_pipe->pipe; diff --git a/src/gallium/drivers/softpipe/Makefile b/src/gallium/drivers/softpipe/Makefile index 83f3e4a19b..35d426aa3e 100644 --- a/src/gallium/drivers/softpipe/Makefile +++ b/src/gallium/drivers/softpipe/Makefile @@ -25,6 +25,7 @@ C_SOURCES = \ sp_state_derived.c \ sp_state_fs.c \ sp_state_sampler.c \ + sp_state_so.c \ sp_state_rasterizer.c \ sp_state_surface.c \ sp_state_vertex.c \ diff --git a/src/gallium/drivers/softpipe/SConscript b/src/gallium/drivers/softpipe/SConscript index b80c6dea93..be5917a688 100644 --- a/src/gallium/drivers/softpipe/SConscript +++ b/src/gallium/drivers/softpipe/SConscript @@ -27,6 +27,7 @@ softpipe = env.ConvenienceLibrary( 'sp_state_fs.c', 'sp_state_rasterizer.c', 'sp_state_sampler.c', + 'sp_state_so.c', 'sp_state_surface.c', 'sp_state_vertex.c', 'sp_surface.c', diff --git a/src/gallium/drivers/softpipe/sp_context.c b/src/gallium/drivers/softpipe/sp_context.c index 2f10b46e98..12ef98aac7 100644 --- a/src/gallium/drivers/softpipe/sp_context.c +++ b/src/gallium/drivers/softpipe/sp_context.c @@ -114,6 +114,11 @@ softpipe_destroy( struct pipe_context *pipe ) pipe_sampler_view_reference(&softpipe->vertex_sampler_views[i], NULL); } + for (i = 0; i < PIPE_MAX_GEOMETRY_SAMPLERS; i++) { + sp_destroy_tex_tile_cache(softpipe->geometry_tex_cache[i]); + pipe_sampler_view_reference(&softpipe->geometry_sampler_views[i], NULL); + } + for (i = 0; i < PIPE_SHADER_TYPES; i++) { uint j; @@ -174,7 +179,12 @@ softpipe_is_resource_referenced( struct pipe_context *pipe, softpipe->vertex_tex_cache[i]->texture == texture) return PIPE_REFERENCED_FOR_READ; } - + for (i = 0; i < PIPE_MAX_GEOMETRY_SAMPLERS; i++) { + if (softpipe->geometry_tex_cache[i] && + softpipe->geometry_tex_cache[i]->texture == texture) + return PIPE_REFERENCED_FOR_READ; + } + return PIPE_UNREFERENCED; } @@ -225,6 +235,7 @@ softpipe_create_context( struct pipe_screen *screen, softpipe->pipe.create_sampler_state = softpipe_create_sampler_state; softpipe->pipe.bind_fragment_sampler_states = softpipe_bind_sampler_states; softpipe->pipe.bind_vertex_sampler_states = softpipe_bind_vertex_sampler_states; + softpipe->pipe.bind_geometry_sampler_states = softpipe_bind_geometry_sampler_states; softpipe->pipe.delete_sampler_state = softpipe_delete_sampler_state; softpipe->pipe.create_depth_stencil_alpha_state = softpipe_create_depth_stencil_state; @@ -251,6 +262,10 @@ softpipe_create_context( struct pipe_screen *screen, softpipe->pipe.bind_vertex_elements_state = softpipe_bind_vertex_elements_state; softpipe->pipe.delete_vertex_elements_state = softpipe_delete_vertex_elements_state; + softpipe->pipe.create_stream_output_state = softpipe_create_stream_output_state; + softpipe->pipe.bind_stream_output_state = softpipe_bind_stream_output_state; + softpipe->pipe.delete_stream_output_state = softpipe_delete_stream_output_state; + softpipe->pipe.set_blend_color = softpipe_set_blend_color; softpipe->pipe.set_stencil_ref = softpipe_set_stencil_ref; softpipe->pipe.set_clip_state = softpipe_set_clip_state; @@ -261,10 +276,11 @@ softpipe_create_context( struct pipe_screen *screen, softpipe->pipe.set_scissor_state = softpipe_set_scissor_state; softpipe->pipe.set_fragment_sampler_views = softpipe_set_sampler_views; softpipe->pipe.set_vertex_sampler_views = softpipe_set_vertex_sampler_views; + softpipe->pipe.set_geometry_sampler_views = softpipe_set_geometry_sampler_views; softpipe->pipe.create_sampler_view = softpipe_create_sampler_view; softpipe->pipe.sampler_view_destroy = softpipe_sampler_view_destroy; softpipe->pipe.set_viewport_state = softpipe_set_viewport_state; - + softpipe->pipe.set_stream_output_buffers = softpipe_set_stream_output_buffers; softpipe->pipe.set_vertex_buffers = softpipe_set_vertex_buffers; softpipe->pipe.draw_arrays = softpipe_draw_arrays; @@ -272,6 +288,7 @@ softpipe_create_context( struct pipe_screen *screen, softpipe->pipe.draw_range_elements = softpipe_draw_range_elements; softpipe->pipe.draw_arrays_instanced = softpipe_draw_arrays_instanced; softpipe->pipe.draw_elements_instanced = softpipe_draw_elements_instanced; + softpipe->pipe.draw_stream_output = softpipe_draw_stream_output; softpipe->pipe.clear = softpipe_clear; softpipe->pipe.flush = softpipe_flush; @@ -296,6 +313,9 @@ softpipe_create_context( struct pipe_screen *screen, for (i = 0; i < PIPE_MAX_VERTEX_SAMPLERS; i++) { softpipe->vertex_tex_cache[i] = sp_create_tex_tile_cache( &softpipe->pipe ); } + for (i = 0; i < PIPE_MAX_GEOMETRY_SAMPLERS; i++) { + softpipe->geometry_tex_cache[i] = sp_create_tex_tile_cache( &softpipe->pipe ); + } softpipe->fs_machine = tgsi_exec_machine_create(); @@ -314,10 +334,17 @@ softpipe_create_context( struct pipe_screen *screen, goto fail; draw_texture_samplers(softpipe->draw, + PIPE_SHADER_VERTEX, PIPE_MAX_VERTEX_SAMPLERS, (struct tgsi_sampler **) softpipe->tgsi.vert_samplers_list); + draw_texture_samplers(softpipe->draw, + PIPE_SHADER_GEOMETRY, + PIPE_MAX_GEOMETRY_SAMPLERS, + (struct tgsi_sampler **) + softpipe->tgsi.geom_samplers_list); + if (debug_get_bool_option( "SP_NO_RAST", FALSE )) softpipe->no_rast = TRUE; diff --git a/src/gallium/drivers/softpipe/sp_context.h b/src/gallium/drivers/softpipe/sp_context.h index b3d3fe620f..53115a827d 100644 --- a/src/gallium/drivers/softpipe/sp_context.h +++ b/src/gallium/drivers/softpipe/sp_context.h @@ -50,6 +50,7 @@ struct softpipe_tex_tile_cache; struct sp_fragment_shader; struct sp_vertex_shader; struct sp_velems_state; +struct sp_so_state; struct softpipe_context { @@ -59,12 +60,14 @@ struct softpipe_context { struct pipe_blend_state *blend; struct pipe_sampler_state *sampler[PIPE_MAX_SAMPLERS]; struct pipe_sampler_state *vertex_samplers[PIPE_MAX_VERTEX_SAMPLERS]; + struct pipe_sampler_state *geometry_samplers[PIPE_MAX_GEOMETRY_SAMPLERS]; struct pipe_depth_stencil_alpha_state *depth_stencil; struct pipe_rasterizer_state *rasterizer; struct sp_fragment_shader *fs; struct sp_vertex_shader *vs; struct sp_geometry_shader *gs; struct sp_velems_state *velems; + struct sp_so_state *so; /** Other rendering state */ struct pipe_blend_color blend_color; @@ -76,13 +79,23 @@ struct softpipe_context { struct pipe_scissor_state scissor; struct pipe_sampler_view *sampler_views[PIPE_MAX_SAMPLERS]; struct pipe_sampler_view *vertex_sampler_views[PIPE_MAX_VERTEX_SAMPLERS]; + struct pipe_sampler_view *geometry_sampler_views[PIPE_MAX_GEOMETRY_SAMPLERS]; struct pipe_viewport_state viewport; struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS]; + struct { + struct softpipe_resource *buffer[PIPE_MAX_SO_BUFFERS]; + int offset[PIPE_MAX_SO_BUFFERS]; + int so_count[PIPE_MAX_SO_BUFFERS]; + int num_buffers; + } so_target; + struct pipe_query_data_so_statistics so_stats; unsigned num_samplers; unsigned num_sampler_views; unsigned num_vertex_samplers; unsigned num_vertex_sampler_views; + unsigned num_geometry_samplers; + unsigned num_geometry_sampler_views; unsigned num_vertex_buffers; unsigned dirty; /**< Mask of SP_NEW_x flags */ @@ -139,6 +152,7 @@ struct softpipe_context { /** TGSI exec things */ struct { + struct sp_sampler_varient *geom_samplers_list[PIPE_MAX_GEOMETRY_SAMPLERS]; struct sp_sampler_varient *vert_samplers_list[PIPE_MAX_VERTEX_SAMPLERS]; struct sp_sampler_varient *frag_samplers_list[PIPE_MAX_SAMPLERS]; } tgsi; @@ -160,6 +174,7 @@ struct softpipe_context { unsigned tex_timestamp; struct softpipe_tex_tile_cache *tex_cache[PIPE_MAX_SAMPLERS]; struct softpipe_tex_tile_cache *vertex_tex_cache[PIPE_MAX_VERTEX_SAMPLERS]; + struct softpipe_tex_tile_cache *geometry_tex_cache[PIPE_MAX_GEOMETRY_SAMPLERS]; unsigned use_sse : 1; unsigned dump_fs : 1; diff --git a/src/gallium/drivers/softpipe/sp_draw_arrays.c b/src/gallium/drivers/softpipe/sp_draw_arrays.c index b30036e230..79daa68f3b 100644 --- a/src/gallium/drivers/softpipe/sp_draw_arrays.c +++ b/src/gallium/drivers/softpipe/sp_draw_arrays.c @@ -84,6 +84,57 @@ softpipe_draw_arrays(struct pipe_context *pipe, unsigned mode, 1); } +void +softpipe_draw_stream_output(struct pipe_context *pipe, unsigned mode) +{ + struct softpipe_context *sp = softpipe_context(pipe); + struct draw_context *draw = sp->draw; + const unsigned start = 0; + const unsigned count = sp->so_target.so_count[0]; + void *buf = sp->so_target.buffer[0]->data; + int offset = sp->so_target.offset[0]; + + if (!softpipe_check_render_cond(sp) || + sp->so_target.num_buffers != 1) + return; + + sp->reduced_api_prim = u_reduced_prim(mode); + + if (sp->dirty) { + softpipe_update_derived(sp); + } + + softpipe_map_transfers(sp); + + /* Map so buffers */ + if (offset < 0) /* we were appending so start from beginning */ + offset = 0; + buf = (void*)((int32_t*)buf + offset); + draw_set_mapped_vertex_buffer(draw, 0, buf); + + draw_set_mapped_element_buffer_range(draw, + 0, 0, + start, + start + count - 1, + NULL); + + /* draw! */ + draw_arrays_instanced(draw, mode, start, count, 0, 1); + + /* unmap vertex/index buffers - will cause draw module to flush */ + draw_set_mapped_vertex_buffer(draw, 0, NULL); + + /* + * TODO: Flush only when a user vertex/index buffer is present + * (or even better, modify draw module to do this + * internally when this condition is seen?) + */ + draw_flush(draw); + + /* Note: leave drawing surfaces mapped */ + sp->dirty_render_cache = TRUE; +} + void softpipe_draw_range_elements(struct pipe_context *pipe, diff --git a/src/gallium/drivers/softpipe/sp_flush.c b/src/gallium/drivers/softpipe/sp_flush.c index 5024fc8a81..4a53ef048f 100644 --- a/src/gallium/drivers/softpipe/sp_flush.c +++ b/src/gallium/drivers/softpipe/sp_flush.c @@ -56,6 +56,9 @@ softpipe_flush( struct pipe_context *pipe, for (i = 0; i < softpipe->num_vertex_sampler_views; i++) { sp_flush_tex_tile_cache(softpipe->vertex_tex_cache[i]); } + for (i = 0; i < softpipe->num_geometry_sampler_views; i++) { + sp_flush_tex_tile_cache(softpipe->geometry_tex_cache[i]); + } } if (flags & PIPE_FLUSH_SWAPBUFFERS) { diff --git a/src/gallium/drivers/softpipe/sp_prim_vbuf.c b/src/gallium/drivers/softpipe/sp_prim_vbuf.c index db0d175510..c60249dbfb 100644 --- a/src/gallium/drivers/softpipe/sp_prim_vbuf.c +++ b/src/gallium/drivers/softpipe/sp_prim_vbuf.c @@ -542,6 +542,22 @@ sp_vbuf_draw_arrays(struct vbuf_render *vbr, uint start, uint nr) } } +static void +sp_vbuf_so_info(struct vbuf_render *vbr, uint primitives, uint vertices) +{ + struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr); + struct softpipe_context *softpipe = cvbr->softpipe; + unsigned i; + + for (i = 0; i < softpipe->so_target.num_buffers; ++i) { + softpipe->so_target.so_count[i] += vertices; + } + + softpipe->so_stats.num_primitives_written = primitives; + softpipe->so_stats.primitives_storage_needed = + vertices * 4 /*sizeof(float|int32)*/ * 4 /*x,y,z,w*/; +} + static void sp_vbuf_destroy(struct vbuf_render *vbr) @@ -575,6 +591,7 @@ sp_create_vbuf_backend(struct softpipe_context *sp) cvbr->base.draw_elements = sp_vbuf_draw_elements; cvbr->base.draw_arrays = sp_vbuf_draw_arrays; cvbr->base.release_vertices = sp_vbuf_release_vertices; + cvbr->base.set_stream_output_info = sp_vbuf_so_info; cvbr->base.destroy = sp_vbuf_destroy; cvbr->softpipe = sp; diff --git a/src/gallium/drivers/softpipe/sp_quad_fs.c b/src/gallium/drivers/softpipe/sp_quad_fs.c index 907e94b59b..d240bcbf3b 100644 --- a/src/gallium/drivers/softpipe/sp_quad_fs.c +++ b/src/gallium/drivers/softpipe/sp_quad_fs.c @@ -109,7 +109,7 @@ shade_quads(struct quad_stage *qs, { struct softpipe_context *softpipe = qs->softpipe; struct tgsi_exec_machine *machine = softpipe->fs_machine; - unsigned i, pass = 0; + unsigned i, nr_quads = 0; for (i = 0; i < PIPE_MAX_CONSTANT_BUFFERS; i++) { machine->Consts[i] = softpipe->mapped_constants[PIPE_SHADER_FRAGMENT][i]; @@ -123,11 +123,11 @@ shade_quads(struct quad_stage *qs, if (/*do_coverage*/ 0) coverage_quad( qs, quads[i] ); - quads[pass++] = quads[i]; + quads[nr_quads++] = quads[i]; } - if (pass) - qs->next->run(qs->next, quads, pass); + if (nr_quads) + qs->next->run(qs->next, quads, nr_quads); } diff --git a/src/gallium/drivers/softpipe/sp_query.c b/src/gallium/drivers/softpipe/sp_query.c index b959af63af..4ae69c1c2b 100644 --- a/src/gallium/drivers/softpipe/sp_query.c +++ b/src/gallium/drivers/softpipe/sp_query.c @@ -41,6 +41,7 @@ struct softpipe_query { unsigned type; uint64_t start; uint64_t end; + struct pipe_query_data_so_statistics so; }; @@ -55,7 +56,11 @@ softpipe_create_query(struct pipe_context *pipe, { struct softpipe_query* sq; - assert(type == PIPE_QUERY_OCCLUSION_COUNTER || type == PIPE_QUERY_TIME_ELAPSED); + assert(type == PIPE_QUERY_OCCLUSION_COUNTER || + type == PIPE_QUERY_TIME_ELAPSED || + type == PIPE_QUERY_SO_STATISTICS || + type == PIPE_QUERY_GPU_FINISHED || + type == PIPE_QUERY_TIMESTAMP_DISJOINT); sq = CALLOC_STRUCT( softpipe_query ); sq->type = type; @@ -75,7 +80,7 @@ softpipe_begin_query(struct pipe_context *pipe, struct pipe_query *q) { struct softpipe_context *softpipe = softpipe_context( pipe ); struct softpipe_query *sq = softpipe_query(q); - + switch (sq->type) { case PIPE_QUERY_OCCLUSION_COUNTER: sq->start = softpipe->occlusion_count; @@ -83,6 +88,13 @@ softpipe_begin_query(struct pipe_context *pipe, struct pipe_query *q) case PIPE_QUERY_TIME_ELAPSED: sq->start = 1000*os_time_get(); break; + case PIPE_QUERY_SO_STATISTICS: + sq->so.num_primitives_written = 0; + sq->so.primitives_storage_needed = 0; + break; + case PIPE_QUERY_GPU_FINISHED: + break; + case PIPE_QUERY_TIMESTAMP_DISJOINT: default: assert(0); break; @@ -106,6 +118,15 @@ softpipe_end_query(struct pipe_context *pipe, struct pipe_query *q) case PIPE_QUERY_TIME_ELAPSED: sq->end = 1000*os_time_get(); break; + case PIPE_QUERY_SO_STATISTICS: + sq->so.num_primitives_written = + softpipe->so_stats.num_primitives_written; + sq->so.primitives_storage_needed = + softpipe->so_stats.primitives_storage_needed; + break; + case PIPE_QUERY_GPU_FINISHED: + case PIPE_QUERY_TIMESTAMP_DISJOINT: + break; default: assert(0); break; @@ -118,10 +139,32 @@ static boolean softpipe_get_query_result(struct pipe_context *pipe, struct pipe_query *q, boolean wait, - uint64_t *result ) + void *vresult) { struct softpipe_query *sq = softpipe_query(q); - *result = sq->end - sq->start; + uint64_t *result = (uint64_t*)vresult; + + switch (sq->type) { + case PIPE_QUERY_SO_STATISTICS: + memcpy(vresult, &sq->so, + sizeof(struct pipe_query_data_so_statistics)); + break; + case PIPE_QUERY_GPU_FINISHED: + *result = TRUE; + break; + case PIPE_QUERY_TIMESTAMP_DISJOINT: { + struct pipe_query_data_timestamp_disjoint td; + /*os_get_time is in microseconds*/ + td.frequency = 1000000; + td.disjoint = FALSE; + memcpy(vresult, &sq->so, + sizeof(struct pipe_query_data_timestamp_disjoint)); + } + break; + default: + *result = sq->end - sq->start; + break; + } return TRUE; } diff --git a/src/gallium/drivers/softpipe/sp_screen.c b/src/gallium/drivers/softpipe/sp_screen.c index 8abe7f50e1..fc57d3eb61 100644 --- a/src/gallium/drivers/softpipe/sp_screen.c +++ b/src/gallium/drivers/softpipe/sp_screen.c @@ -115,6 +115,8 @@ softpipe_get_param(struct pipe_screen *screen, enum pipe_cap param) case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER: case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER: return 1; + case PIPE_CAP_STREAM_OUTPUT: + return 1; case PIPE_CAP_MAX_VS_INSTRUCTIONS: case PIPE_CAP_MAX_FS_INSTRUCTIONS: diff --git a/src/gallium/drivers/softpipe/sp_state.h b/src/gallium/drivers/softpipe/sp_state.h index 5b0faabeae..7d6b86dce0 100644 --- a/src/gallium/drivers/softpipe/sp_state.h +++ b/src/gallium/drivers/softpipe/sp_state.h @@ -51,6 +51,8 @@ #define SP_NEW_VS 0x2000 #define SP_NEW_QUERY 0x4000 #define SP_NEW_GS 0x8000 +#define SP_NEW_SO 0x10000 +#define SP_NEW_SO_BUFFERS 0x20000 struct tgsi_sampler; @@ -98,6 +100,7 @@ struct sp_vertex_shader { struct sp_geometry_shader { struct pipe_shader_state shader; struct draw_geometry_shader *draw_data; + int max_sampler; }; struct sp_velems_state { @@ -105,6 +108,10 @@ struct sp_velems_state { struct pipe_vertex_element velem[PIPE_MAX_ATTRIBS]; }; +struct sp_so_state { + struct pipe_stream_output_state base; +}; + void * softpipe_create_blend_state(struct pipe_context *, @@ -122,6 +129,10 @@ void softpipe_bind_vertex_sampler_states(struct pipe_context *, unsigned num_samplers, void **samplers); +void +softpipe_bind_geometry_sampler_states(struct pipe_context *, + unsigned num_samplers, + void **samplers); void softpipe_delete_sampler_state(struct pipe_context *, void *); void * @@ -189,6 +200,11 @@ softpipe_set_vertex_sampler_views(struct pipe_context *, unsigned num, struct pipe_sampler_view **); +void +softpipe_set_geometry_sampler_views(struct pipe_context *, + unsigned num, + struct pipe_sampler_view **); + struct pipe_sampler_view * softpipe_create_sampler_view(struct pipe_context *pipe, struct pipe_resource *texture, @@ -244,6 +260,8 @@ softpipe_draw_elements_instanced(struct pipe_context *pipe, unsigned startInstance, unsigned instanceCount); +void softpipe_draw_stream_output(struct pipe_context *pipe, unsigned mode); + void softpipe_map_transfers(struct softpipe_context *sp); @@ -263,5 +281,20 @@ softpipe_get_vertex_info(struct softpipe_context *softpipe); struct vertex_info * softpipe_get_vbuf_vertex_info(struct softpipe_context *softpipe); +void * +softpipe_create_stream_output_state( + struct pipe_context *pipe, + const struct pipe_stream_output_state *templ); +void +softpipe_bind_stream_output_state(struct pipe_context *pipe, + void *so); +void +softpipe_delete_stream_output_state(struct pipe_context *pipe, void *so); + +void +softpipe_set_stream_output_buffers(struct pipe_context *pipe, + struct pipe_resource **buffers, + int *offsets, + int num_buffers); #endif diff --git a/src/gallium/drivers/softpipe/sp_state_derived.c b/src/gallium/drivers/softpipe/sp_state_derived.c index 4c6d4909f5..3ba4d934fd 100644 --- a/src/gallium/drivers/softpipe/sp_state_derived.c +++ b/src/gallium/drivers/softpipe/sp_state_derived.c @@ -225,6 +225,19 @@ update_tgsi_samplers( struct softpipe_context *softpipe ) } } } + + for (i = 0; i < PIPE_MAX_GEOMETRY_SAMPLERS; i++) { + struct softpipe_tex_tile_cache *tc = softpipe->geometry_tex_cache[i]; + + if (tc->texture) { + struct softpipe_resource *spt = softpipe_resource(tc->texture); + + if (spt->timestamp != tc->timestamp) { + sp_tex_tile_cache_validate_texture(tc); + tc->timestamp = spt->timestamp; + } + } + } } diff --git a/src/gallium/drivers/softpipe/sp_state_fs.c b/src/gallium/drivers/softpipe/sp_state_fs.c index 2fff80c438..3fbf1f2578 100644 --- a/src/gallium/drivers/softpipe/sp_state_fs.c +++ b/src/gallium/drivers/softpipe/sp_state_fs.c @@ -35,6 +35,7 @@ #include "util/u_inlines.h" #include "draw/draw_context.h" #include "draw/draw_vs.h" +#include "draw/draw_gs.h" #include "tgsi/tgsi_dump.h" #include "tgsi/tgsi_exec.h" #include "tgsi/tgsi_scan.h" @@ -223,6 +224,8 @@ softpipe_create_gs_state(struct pipe_context *pipe, if (state->draw_data == NULL) goto fail; + state->max_sampler = state->draw_data->info.file_max[TGSI_FILE_SAMPLER]; + return state; fail: diff --git a/src/gallium/drivers/softpipe/sp_state_sampler.c b/src/gallium/drivers/softpipe/sp_state_sampler.c index 2692f06c92..79d9516ad9 100644 --- a/src/gallium/drivers/softpipe/sp_state_sampler.c +++ b/src/gallium/drivers/softpipe/sp_state_sampler.c @@ -121,6 +121,33 @@ softpipe_bind_vertex_sampler_states(struct pipe_context *pipe, softpipe->dirty |= SP_NEW_SAMPLER; } +void +softpipe_bind_geometry_sampler_states(struct pipe_context *pipe, + unsigned num_samplers, + void **samplers) +{ + struct softpipe_context *softpipe = softpipe_context(pipe); + unsigned i; + + assert(num_samplers <= PIPE_MAX_GEOMETRY_SAMPLERS); + + /* Check for no-op */ + if (num_samplers == softpipe->num_geometry_samplers && + !memcmp(softpipe->geometry_samplers, samplers, num_samplers * sizeof(void *))) + return; + + draw_flush(softpipe->draw); + + for (i = 0; i < num_samplers; ++i) + softpipe->geometry_samplers[i] = samplers[i]; + for (i = num_samplers; i < PIPE_MAX_GEOMETRY_SAMPLERS; ++i) + softpipe->geometry_samplers[i] = NULL; + + softpipe->num_geometry_samplers = num_samplers; + + softpipe->dirty |= SP_NEW_SAMPLER; +} + struct pipe_sampler_view * softpipe_create_sampler_view(struct pipe_context *pipe, @@ -210,6 +237,36 @@ softpipe_set_vertex_sampler_views(struct pipe_context *pipe, softpipe->dirty |= SP_NEW_TEXTURE; } +void +softpipe_set_geometry_sampler_views(struct pipe_context *pipe, + unsigned num, + struct pipe_sampler_view **views) +{ + struct softpipe_context *softpipe = softpipe_context(pipe); + uint i; + + assert(num <= PIPE_MAX_GEOMETRY_SAMPLERS); + + /* Check for no-op */ + if (num == softpipe->num_geometry_sampler_views && + !memcmp(softpipe->geometry_sampler_views, views, num * sizeof(struct pipe_sampler_view *))) { + return; + } + + draw_flush(softpipe->draw); + + for (i = 0; i < PIPE_MAX_GEOMETRY_SAMPLERS; i++) { + struct pipe_sampler_view *view = i < num ? views[i] : NULL; + + pipe_sampler_view_reference(&softpipe->geometry_sampler_views[i], view); + sp_tex_tile_cache_set_sampler_view(softpipe->geometry_tex_cache[i], view); + } + + softpipe->num_geometry_sampler_views = num; + + softpipe->dirty |= SP_NEW_TEXTURE; +} + /** * Find/create an sp_sampler_varient object for sampling the given texture, @@ -293,6 +350,30 @@ softpipe_reset_sampler_varients(struct softpipe_context *softpipe) } } + if (softpipe->gs) { + for (i = 0; i <= softpipe->gs->max_sampler; i++) { + if (softpipe->geometry_samplers[i]) { + struct pipe_resource *texture = NULL; + + if (softpipe->geometry_sampler_views[i]) { + texture = softpipe->geometry_sampler_views[i]->texture; + } + + softpipe->tgsi.geom_samplers_list[i] = + get_sampler_varient( + i, + sp_sampler(softpipe->geometry_samplers[i]), + texture, + TGSI_PROCESSOR_GEOMETRY ); + + sp_sampler_varient_bind_texture( + softpipe->tgsi.geom_samplers_list[i], + softpipe->geometry_tex_cache[i], + texture ); + } + } + } + for (i = 0; i <= softpipe->fs->info.file_max[TGSI_FILE_SAMPLER]; i++) { if (softpipe->sampler[i]) { struct pipe_resource *texture = NULL; diff --git a/src/gallium/drivers/softpipe/sp_state_so.c b/src/gallium/drivers/softpipe/sp_state_so.c new file mode 100644 index 0000000000..cfe23f9e84 --- /dev/null +++ b/src/gallium/drivers/softpipe/sp_state_so.c @@ -0,0 +1,124 @@ +/************************************************************************** + * + * 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 TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "sp_context.h" +#include "sp_state.h" +#include "sp_texture.h" + +#include "util/u_format.h" +#include "util/u_memory.h" +#include "draw/draw_context.h" + + +void * +softpipe_create_stream_output_state(struct pipe_context *pipe, + const struct pipe_stream_output_state *templ) +{ + struct sp_so_state *so; + so = (struct sp_so_state *) CALLOC_STRUCT(sp_so_state); + + if (so) { + so->base.num_outputs = templ->num_outputs; + so->base.stride = templ->stride; + memcpy(so->base.output_buffer, + templ->output_buffer, + sizeof(int) * templ->num_outputs); + memcpy(so->base.register_index, + templ->register_index, + sizeof(int) * templ->num_outputs); + memcpy(so->base.register_mask, + templ->register_mask, + sizeof(ubyte) * templ->num_outputs); + } + return so; +} + +void +softpipe_bind_stream_output_state(struct pipe_context *pipe, + void *so) +{ + struct softpipe_context *softpipe = softpipe_context(pipe); + struct sp_so_state *sp_so = (struct sp_so_state *) so; + + softpipe->so = sp_so; + + softpipe->dirty |= SP_NEW_SO; + + if (sp_so) + draw_set_so_state(softpipe->draw, &sp_so->base); +} + +void +softpipe_delete_stream_output_state(struct pipe_context *pipe, void *so) +{ + FREE( so ); +} + +void +softpipe_set_stream_output_buffers(struct pipe_context *pipe, + struct pipe_resource **buffers, + int *offsets, + int num_buffers) +{ + struct softpipe_context *softpipe = softpipe_context(pipe); + int i; + void *map_buffers[PIPE_MAX_SO_BUFFERS]; + + assert(num_buffers <= PIPE_MAX_SO_BUFFERS); + if (num_buffers > PIPE_MAX_SO_BUFFERS) + num_buffers = PIPE_MAX_SO_BUFFERS; + + softpipe->dirty |= SP_NEW_SO_BUFFERS; + + for (i = 0; i < num_buffers; ++i) { + void *mapped; + struct softpipe_resource *res = softpipe_resource(buffers[i]); + + if (!res) { + /* the whole call is invalid, bail out */ + softpipe->so_target.num_buffers = 0; + draw_set_mapped_so_buffers(softpipe->draw, 0, 0); + return; + } + + softpipe->so_target.buffer[i] = res; + softpipe->so_target.offset[i] = offsets[i]; + softpipe->so_target.so_count[i] = 0; + + mapped = res->data; + if (offsets[i] >= 0) + map_buffers[i] = ((char*)mapped) + offsets[i]; + else { + /* this is a buffer append */ + assert(!"appending not implemented"); + map_buffers[i] = mapped; + } + } + softpipe->so_target.num_buffers = num_buffers; + + draw_set_mapped_so_buffers(softpipe->draw, map_buffers, num_buffers); +} diff --git a/src/gallium/drivers/softpipe/sp_surface.c b/src/gallium/drivers/softpipe/sp_surface.c index 99433f7d1d..55b27e6010 100644 --- a/src/gallium/drivers/softpipe/sp_surface.c +++ b/src/gallium/drivers/softpipe/sp_surface.c @@ -33,4 +33,6 @@ void sp_init_surface_functions(struct softpipe_context *sp) { sp->pipe.resource_copy_region = util_resource_copy_region; + sp->pipe.clear_render_target = util_clear_render_target; + sp->pipe.clear_depth_stencil = util_clear_depth_stencil; } diff --git a/src/gallium/drivers/softpipe/sp_tex_sample.c b/src/gallium/drivers/softpipe/sp_tex_sample.c index ff83c66d8b..cf7ab81405 100644 --- a/src/gallium/drivers/softpipe/sp_tex_sample.c +++ b/src/gallium/drivers/softpipe/sp_tex_sample.c @@ -71,7 +71,7 @@ lerp(float a, float v0, float v1) /** - * Do 2D/biliner interpolation of float values. + * Do 2D/bilinear interpolation of float values. * v00, v10, v01 and v11 are typically four texture samples in a square/box. * a and b are the horizontal and vertical interpolants. * It's important that this function is inlined when compiled with diff --git a/src/gallium/drivers/svga/svga_pipe_query.c b/src/gallium/drivers/svga/svga_pipe_query.c index 96fb4b8e53..579f8034c7 100644 --- a/src/gallium/drivers/svga/svga_pipe_query.c +++ b/src/gallium/drivers/svga/svga_pipe_query.c @@ -63,7 +63,7 @@ svga_query( struct pipe_query *q ) static boolean svga_get_query_result(struct pipe_context *pipe, struct pipe_query *q, boolean wait, - uint64_t *result); + void *result); static struct pipe_query *svga_create_query( struct pipe_context *pipe, unsigned query_type ) @@ -207,13 +207,14 @@ static void svga_end_query(struct pipe_context *pipe, static boolean svga_get_query_result(struct pipe_context *pipe, struct pipe_query *q, boolean wait, - uint64_t *result) + void *vresult) { struct svga_context *svga = svga_context( pipe ); struct svga_screen *svgascreen = svga_screen( pipe->screen ); struct svga_winsys_screen *sws = svgascreen->sws; struct svga_query *sq = svga_query( q ); SVGA3dQueryState state; + uint64_t *result = (uint64_t*)vresult; SVGA_DBG(DEBUG_QUERY, "%s wait: %d\n", __FUNCTION__); diff --git a/src/gallium/drivers/sw/sw.c b/src/gallium/drivers/sw/sw.c index 9f156df45f..6b873ecc1b 100644 --- a/src/gallium/drivers/sw/sw.c +++ b/src/gallium/drivers/sw/sw.c @@ -2,7 +2,6 @@ #include "util/u_debug.h" #include "target-helpers/wrap_screen.h" #include "sw_public.h" -#include "state_tracker/sw_winsys.h" /* Helper function to choose and instantiate one of the software rasterizers: diff --git a/src/gallium/drivers/trace/tr_context.c b/src/gallium/drivers/trace/tr_context.c index 9ca916fe7b..55dd6cf883 100644 --- a/src/gallium/drivers/trace/tr_context.c +++ b/src/gallium/drivers/trace/tr_context.c @@ -248,7 +248,7 @@ static INLINE boolean trace_context_get_query_result(struct pipe_context *_pipe, struct pipe_query *query, boolean wait, - uint64_t *presult) + void *presult) { struct trace_context *tr_ctx = trace_context(_pipe); struct pipe_context *pipe = tr_ctx->pipe; @@ -260,7 +260,7 @@ trace_context_get_query_result(struct pipe_context *_pipe, trace_dump_arg(ptr, pipe); _result = pipe->get_query_result(pipe, query, wait, presult); - result = *presult; + result = *((uint64_t*)presult); trace_dump_arg(uint, result); trace_dump_ret(bool, _result); |