diff options
Diffstat (limited to 'src/gallium/drivers/r300')
44 files changed, 3452 insertions, 2284 deletions
diff --git a/src/gallium/drivers/r300/Makefile b/src/gallium/drivers/r300/Makefile index 69e4724790a..afddcb161fa 100644 --- a/src/gallium/drivers/r300/Makefile +++ b/src/gallium/drivers/r300/Makefile @@ -4,10 +4,8 @@ include $(TOP)/configs/current LIBNAME = r300 C_SOURCES = \ - r3xx_fs.c \ - r5xx_fs.c \ + r300_blit.c \ r300_chipset.c \ - r300_clear.c \ r300_context.c \ r300_debug.c \ r300_emit.c \ @@ -20,12 +18,12 @@ C_SOURCES = \ r300_state_derived.c \ r300_state_invariant.c \ r300_vs.c \ - r300_surface.c \ r300_texture.c \ r300_tgsi_to_rc.c LIBRARY_INCLUDES = \ - -I$(TOP)/src/mesa/drivers/dri/r300/compiler + -I$(TOP)/src/mesa/drivers/dri/r300/compiler \ + -I$(TOP)/src/gallium/winsys/drm/radeon/core COMPILER_ARCHIVE = $(TOP)/src/mesa/drivers/dri/r300/compiler/libr300compiler.a @@ -37,4 +35,4 @@ include ../../Makefile.template .PHONY : $(COMPILER_ARCHIVE) $(COMPILER_ARCHIVE): - cd $(TOP)/src/mesa/drivers/dri/r300/compiler; make + $(MAKE) -C $(TOP)/src/mesa/drivers/dri/r300/compiler diff --git a/src/gallium/drivers/r300/SConscript b/src/gallium/drivers/r300/SConscript index b4c8ba2015a..183aa17f9b3 100644 --- a/src/gallium/drivers/r300/SConscript +++ b/src/gallium/drivers/r300/SConscript @@ -4,15 +4,18 @@ r300compiler = SConscript('#/src/mesa/drivers/dri/r300/compiler/SConscript') env = env.Clone() # add the paths for r300compiler -env.Append(CPPPATH = ['#/src/mesa/drivers/dri/r300/compiler', '#/include', '#/src/mesa']) +env.Append(CPPPATH = [ + '#/src/mesa/drivers/dri/r300/compiler', + '#/src/gallium/winsys/drm/radeon/core', + '#/include', + '#/src/mesa', +]) r300 = env.ConvenienceLibrary( target = 'r300', source = [ - 'r3xx_fs.c', - 'r5xx_fs.c', + 'r300_blit.c', 'r300_chipset.c', - 'r300_clear.c', 'r300_context.c', 'r300_debug.c', 'r300_emit.c', @@ -25,7 +28,6 @@ r300 = env.ConvenienceLibrary( 'r300_state_derived.c', 'r300_state_invariant.c', 'r300_vs.c', - 'r300_surface.c', 'r300_texture.c', 'r300_tgsi_to_rc.c', ] + r300compiler) + r300compiler diff --git a/src/gallium/drivers/r300/r300_blit.c b/src/gallium/drivers/r300/r300_blit.c new file mode 100644 index 00000000000..ffe066d5369 --- /dev/null +++ b/src/gallium/drivers/r300/r300_blit.c @@ -0,0 +1,130 @@ +/* + * Copyright 2009 Marek Olšák <[email protected]> + * + * 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_blit.h" +#include "r300_context.h" + +#include "util/u_rect.h" + +static void r300_blitter_save_states(struct r300_context* r300) +{ + util_blitter_save_blend(r300->blitter, r300->blend_state); + util_blitter_save_depth_stencil_alpha(r300->blitter, r300->dsa_state); + util_blitter_save_rasterizer(r300->blitter, r300->rs_state); + util_blitter_save_fragment_shader(r300->blitter, r300->fs); + util_blitter_save_vertex_shader(r300->blitter, r300->vs); +} + +/* Clear currently bound buffers. */ +void r300_clear(struct pipe_context* pipe, + unsigned buffers, + const float* rgba, + double depth, + unsigned stencil) +{ + /* XXX Implement fastfill. + * + * If fastfill is enabled, a few facts should be considered: + * + * 1) Zbuffer must be micro-tiled and whole microtiles must be + * written. + * + * 2) ZB_DEPTHCLEARVALUE is used to clear a zbuffer and Z Mask must be + * equal to 0. + * + * 3) RB3D_COLOR_CLEAR_VALUE is used to clear a colorbuffer and + * RB3D_COLOR_CHANNEL_MASK must be equal to 0. + * + * 4) ZB_CB_CLEAR can be used to make the ZB units help in clearing + * the colorbuffer. The color clear value is supplied through both + * RB3D_COLOR_CLEAR_VALUE and ZB_DEPTHCLEARVALUE, and the colorbuffer + * must be set in ZB_DEPTHOFFSET and ZB_DEPTHPITCH in addition to + * RB3D_COLOROFFSET and RB3D_COLORPITCH. It's obvious that the zbuffer + * will not be cleared and multiple render targets cannot be cleared + * this way either. + * + * 5) For 16-bit integer buffering, compression causes a hung with one or + * two samples and should not be used. + * + * 6) 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?) + * + * - Marek + */ + + struct r300_context* r300 = r300_context(pipe); + + r300_blitter_save_states(r300); + + util_blitter_clear(r300->blitter, + r300->framebuffer_state.width, + r300->framebuffer_state.height, + r300->framebuffer_state.nr_cbufs, + buffers, rgba, depth, stencil); +} + +/* Copy a block of pixels from one surface to another. */ +void r300_surface_copy(struct pipe_context* pipe, + struct pipe_surface* dst, + unsigned dstx, unsigned dsty, + struct pipe_surface* src, + unsigned srcx, unsigned srcy, + unsigned width, unsigned height) +{ + struct r300_context* r300 = r300_context(pipe); + + /* 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->framebuffer_state); + + util_blitter_save_fragment_sampler_states( + r300->blitter, r300->sampler_count, (void**)r300->sampler_states); + + util_blitter_save_fragment_sampler_textures( + r300->blitter, r300->texture_count, + (struct pipe_texture**)r300->textures); + + /* Do a copy */ + util_blitter_copy(r300->blitter, + dst, dstx, dsty, src, srcx, srcy, width, height, TRUE); +} + +/* Fill a region of a surface with a constant value. */ +void r300_surface_fill(struct pipe_context* pipe, + struct pipe_surface* dst, + unsigned dstx, unsigned dsty, + unsigned width, unsigned height, + unsigned value) +{ + struct r300_context* r300 = r300_context(pipe); + + r300_blitter_save_states(r300); + util_blitter_save_framebuffer(r300->blitter, &r300->framebuffer_state); + + util_blitter_fill(r300->blitter, + dst, dstx, dsty, width, height, value); +} diff --git a/src/gallium/drivers/r300/r300_clear.h b/src/gallium/drivers/r300/r300_blit.h index cd5900565e8..029e4f98e7d 100644 --- a/src/gallium/drivers/r300/r300_clear.h +++ b/src/gallium/drivers/r300/r300_blit.h @@ -1,5 +1,5 @@ /* - * Copyright 2008 Corbin Simpson <[email protected]> + * Copyright 2008 Marek Olšák <[email protected]> * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -20,12 +20,11 @@ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE * USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#ifndef R300_CLEAR_H -#define R300_CLEAR_H +#ifndef R300_BLIT_H +#define R300_BLIT_H -#include "util/u_clear.h" - -#include "r300_context.h" +struct pipe_context; +struct pipe_surface; void r300_clear(struct pipe_context* pipe, unsigned buffers, @@ -33,4 +32,17 @@ void r300_clear(struct pipe_context* pipe, double depth, unsigned stencil); -#endif /* R300_CLEAR_H */ +void r300_surface_copy(struct pipe_context* pipe, + struct pipe_surface* dst, + unsigned dstx, unsigned dsty, + struct pipe_surface* src, + unsigned srcx, unsigned srcy, + unsigned width, unsigned height); + +void r300_surface_fill(struct pipe_context* pipe, + struct pipe_surface* dst, + unsigned dstx, unsigned dsty, + unsigned width, unsigned height, + unsigned value); + +#endif /* R300_BLIT_H */ diff --git a/src/gallium/drivers/r300/r300_chipset.c b/src/gallium/drivers/r300/r300_chipset.c index d138866d33c..51fdb82ff34 100644 --- a/src/gallium/drivers/r300/r300_chipset.c +++ b/src/gallium/drivers/r300/r300_chipset.c @@ -21,6 +21,7 @@ * USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "r300_chipset.h" + #include "util/u_debug.h" /* r300_chipset: A file all to itself for deducing the various properties of @@ -31,7 +32,7 @@ void r300_parse_chipset(struct r300_capabilities* caps) { /* Reasonable defaults */ caps->num_vert_fpus = 4; - caps->has_tcl = getenv("RADEON_NO_TCL") ? FALSE : TRUE; + caps->has_tcl = debug_get_bool_option("RADEON_NO_TCL", FALSE) ? FALSE : TRUE; caps->is_r500 = FALSE; caps->high_second_pipe = FALSE; diff --git a/src/gallium/drivers/r300/r300_chipset.h b/src/gallium/drivers/r300/r300_chipset.h index 322d4a57e41..0633a8b8a72 100644 --- a/src/gallium/drivers/r300/r300_chipset.h +++ b/src/gallium/drivers/r300/r300_chipset.h @@ -33,9 +33,11 @@ struct r300_capabilities { /* Chipset family */ int family; /* The number of vertex floating-point units */ - int num_vert_fpus; + unsigned num_vert_fpus; /* The number of fragment pipes */ - int num_frag_pipes; + unsigned num_frag_pipes; + /* The number of z pipes */ + unsigned num_z_pipes; /* Whether or not TCL is physically present */ boolean has_tcl; /* Whether or not this is an RV515 or newer; R500s have many differences diff --git a/src/gallium/drivers/r300/r300_clear.c b/src/gallium/drivers/r300/r300_clear.c deleted file mode 100644 index 8b9cb819ae6..00000000000 --- a/src/gallium/drivers/r300/r300_clear.c +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2008 Corbin Simpson <[email protected]> - * - * 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_clear.h" - -/* Clears currently bound buffers. */ -void r300_clear(struct pipe_context* pipe, - unsigned buffers, - const float* rgba, - double depth, - unsigned stencil) -{ - /* XXX we can and should do one clear if both color and zs are set */ - util_clear(pipe, &r300_context(pipe)->framebuffer_state, - buffers, rgba, depth, stencil); -} diff --git a/src/gallium/drivers/r300/r300_context.c b/src/gallium/drivers/r300/r300_context.c index 9cc455135db..d5c2d63d393 100644 --- a/src/gallium/drivers/r300/r300_context.c +++ b/src/gallium/drivers/r300/r300_context.c @@ -20,178 +20,167 @@ * 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_flush.h" -#include "r300_state_invariant.h" - -static boolean r300_draw_range_elements(struct pipe_context* pipe, - struct pipe_buffer* indexBuffer, - unsigned indexSize, - unsigned minIndex, - unsigned maxIndex, - unsigned mode, - unsigned start, - unsigned count) -{ - struct r300_context* r300 = r300_context(pipe); - int i; - - for (i = 0; i < r300->vertex_buffer_count; i++) { - void* buf = pipe_buffer_map(pipe->screen, - r300->vertex_buffers[i].buffer, - PIPE_BUFFER_USAGE_CPU_READ); - draw_set_mapped_vertex_buffer(r300->draw, i, buf); - } - - if (indexBuffer) { - void* indices = pipe_buffer_map(pipe->screen, indexBuffer, - PIPE_BUFFER_USAGE_CPU_READ); - draw_set_mapped_element_buffer_range(r300->draw, indexSize, - minIndex, maxIndex, indices); - } else { - draw_set_mapped_element_buffer(r300->draw, 0, NULL); - } - - draw_set_mapped_constant_buffer(r300->draw, - r300->shader_constants[PIPE_SHADER_VERTEX].constants, - r300->shader_constants[PIPE_SHADER_VERTEX].count * - (sizeof(float) * 4)); - - draw_arrays(r300->draw, mode, start, count); +#include "draw/draw_context.h" - for (i = 0; i < r300->vertex_buffer_count; i++) { - pipe_buffer_unmap(pipe->screen, r300->vertex_buffers[i].buffer); - draw_set_mapped_vertex_buffer(r300->draw, i, NULL); - } +#include "tgsi/tgsi_scan.h" - if (indexBuffer) { - pipe_buffer_unmap(pipe->screen, indexBuffer); - draw_set_mapped_element_buffer_range(r300->draw, 0, start, - start + count - 1, NULL); - } +#include "util/u_hash_table.h" +#include "util/u_memory.h" +#include "util/u_simple_list.h" - return TRUE; -} +#include "r300_blit.h" +#include "r300_context.h" +#include "r300_flush.h" +#include "r300_query.h" +#include "r300_render.h" +#include "r300_screen.h" +#include "r300_state_derived.h" +#include "r300_state_invariant.h" +#include "r300_texture.h" +#include "r300_winsys.h" -static boolean r300_draw_elements(struct pipe_context* pipe, - struct pipe_buffer* indexBuffer, - unsigned indexSize, unsigned mode, - unsigned start, unsigned count) +static enum pipe_error r300_clear_hash_table(void* key, void* value, + void* data) { - return r300_draw_range_elements(pipe, indexBuffer, indexSize, 0, ~0, - mode, start, count); + FREE(key); + FREE(value); + return PIPE_OK; } -static boolean r300_draw_arrays(struct pipe_context* pipe, unsigned mode, - unsigned start, unsigned count) +static void r300_destroy_context(struct pipe_context* context) { - return r300_draw_elements(pipe, NULL, 0, mode, start, count); -} - -static void r300_destroy_context(struct pipe_context* context) { struct r300_context* r300 = r300_context(context); struct r300_query* query, * temp; + util_blitter_destroy(r300->blitter); + + util_hash_table_foreach(r300->shader_hash_table, r300_clear_hash_table, + NULL); + util_hash_table_destroy(r300->shader_hash_table); + draw_destroy(r300->draw); /* Free the OQ BO. */ context->screen->buffer_destroy(r300->oqbo); /* If there are any queries pending or not destroyed, remove them now. */ - if (r300->query_list) { - foreach_s(query, temp, r300->query_list) { - remove_from_list(query); - FREE(query); - } + foreach_s(query, temp, &r300->query_list) { + remove_from_list(query); + FREE(query); } FREE(r300->blend_color_state); FREE(r300->rs_block); FREE(r300->scissor_state); + FREE(r300->vertex_info); FREE(r300->viewport_state); FREE(r300); } static unsigned int -r300_is_texture_referenced( struct pipe_context *pipe, - struct pipe_texture *texture, - unsigned face, unsigned level) +r300_is_texture_referenced(struct pipe_context *pipe, + struct pipe_texture *texture, + unsigned face, unsigned level) { - /** - * FIXME: Optimize. - */ + struct pipe_buffer* buf = 0; - return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE; + r300_get_texture_buffer(texture, &buf, NULL); + + return pipe->is_buffer_referenced(pipe, buf); } static unsigned int -r300_is_buffer_referenced( struct pipe_context *pipe, - struct pipe_buffer *buf) +r300_is_buffer_referenced(struct pipe_context *pipe, + struct pipe_buffer *buf) +{ + /* This only checks to see whether actual hardware buffers are + * referenced. Since we use managed BOs and transfers, it's actually not + * possible for pipe_buffers to ever reference the actual hardware, so + * buffers are never referenced. */ + return 0; +} + +static void r300_flush_cb(void *data) { - /** - * FIXME: Optimize. - */ + struct r300_context* const cs_context_copy = data; - return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE; + cs_context_copy->context.flush(&cs_context_copy->context, 0, NULL); } struct pipe_context* r300_create_context(struct pipe_screen* screen, - struct r300_winsys* r300_winsys) + struct radeon_winsys* radeon_winsys) { struct r300_context* r300 = CALLOC_STRUCT(r300_context); + struct r300_screen* r300screen = r300_screen(screen); if (!r300) return NULL; - r300->winsys = r300_winsys; + r300->winsys = radeon_winsys; - r300->context.winsys = (struct pipe_winsys*)r300_winsys; - r300->context.screen = r300_screen(screen); + r300->context.winsys = (struct pipe_winsys*)radeon_winsys; + r300->context.screen = screen; r300_init_debug(r300); r300->context.destroy = r300_destroy_context; r300->context.clear = r300_clear; + r300->context.surface_copy = r300_surface_copy; + r300->context.surface_fill = r300_surface_fill; - r300->context.draw_arrays = r300_draw_arrays; - r300->context.draw_elements = r300_draw_elements; - r300->context.draw_range_elements = r300_draw_range_elements; + if (r300screen->caps->has_tcl) { + r300->context.draw_arrays = r300_draw_arrays; + r300->context.draw_elements = r300_draw_elements; + r300->context.draw_range_elements = r300_draw_range_elements; + } else { + r300->context.draw_arrays = r300_swtcl_draw_arrays; + r300->context.draw_elements = r300_draw_elements; + r300->context.draw_range_elements = r300_swtcl_draw_range_elements; + + /* Create a Draw. This is used for SW TCL. */ + r300->draw = draw_create(); + /* Enable our renderer. */ + draw_set_rasterize_stage(r300->draw, r300_draw_stage(r300)); + /* Enable Draw's clipping. */ + draw_set_driver_clipping(r300->draw, FALSE); + /* Force Draw to never do viewport transform, since we can do + * transform in hardware, always. */ + draw_set_viewport_state(r300->draw, &r300_viewport_identity); + } r300->context.is_texture_referenced = r300_is_texture_referenced; r300->context.is_buffer_referenced = r300_is_buffer_referenced; + r300->shader_hash_table = util_hash_table_create(r300_shader_key_hash, + r300_shader_key_compare); + r300->blend_color_state = CALLOC_STRUCT(r300_blend_color_state); r300->rs_block = CALLOC_STRUCT(r300_rs_block); r300->scissor_state = CALLOC_STRUCT(r300_scissor_state); + r300->vertex_info = CALLOC_STRUCT(r300_vertex_info); r300->viewport_state = CALLOC_STRUCT(r300_viewport_state); - /* Create a Draw. This is used for vert collation and SW TCL. */ - r300->draw = draw_create(); - /* Enable our renderer. */ - draw_set_rasterize_stage(r300->draw, r300_draw_stage(r300)); - /* Disable Draw's clipping if TCL is present. */ - draw_set_driver_clipping(r300->draw, r300_screen(screen)->caps->has_tcl); - /* Force Draw to never do viewport transform, since (again) we can do - * transform in hardware, always. */ - draw_set_viewport_state(r300->draw, &r300_viewport_identity); - /* Open up the OQ BO. */ r300->oqbo = screen->buffer_create(screen, 4096, PIPE_BUFFER_USAGE_VERTEX, 4096); + make_empty_list(&r300->query_list); r300_init_flush_functions(r300); r300_init_query_functions(r300); - r300_init_surface_functions(r300); + /* r300_init_surface_functions(r300); */ r300_init_state_functions(r300); r300_emit_invariant_state(r300); + + r300->winsys->set_flush_cb(r300->winsys, r300_flush_cb, r300); r300->dirty_state = R300_NEW_KITCHEN_SINK; r300->dirty_hw++; + r300->blitter = util_blitter_create(&r300->context); + return &r300->context; } diff --git a/src/gallium/drivers/r300/r300_context.h b/src/gallium/drivers/r300/r300_context.h index 52b1c9a6b26..232530b7dc4 100644 --- a/src/gallium/drivers/r300/r300_context.h +++ b/src/gallium/drivers/r300/r300_context.h @@ -23,20 +23,12 @@ #ifndef R300_CONTEXT_H #define R300_CONTEXT_H -#include "draw/draw_context.h" #include "draw/draw_vertex.h" -#include "pipe/p_context.h" - -#include "tgsi/tgsi_scan.h" +#include "util/u_blitter.h" -#include "util/u_memory.h" -#include "util/u_simple_list.h" - -#include "r300_clear.h" -#include "r300_query.h" -#include "r300_screen.h" -#include "r300_winsys.h" +#include "pipe/p_context.h" +#include "pipe/p_inlines.h" struct r300_fragment_shader; struct r300_vertex_shader; @@ -44,6 +36,7 @@ struct r300_vertex_shader; 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 */ }; @@ -62,7 +55,6 @@ struct r300_dsa_state { 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 z_buffer_top; /* R300_ZB_ZTOP: 0x4f14 */ uint32_t stencil_ref_bf; /* R500_ZB_STENCILREFMASK_BF: 0x4fd4 */ }; @@ -88,6 +80,7 @@ struct r300_rs_state { uint32_t line_stipple_config; /* R300_GA_LINE_STIPPLE_CONFIG: 0x4328 */ uint32_t line_stipple_value; /* R300_GA_LINE_STIPPLE_VALUE: 0x4260 */ uint32_t color_control; /* R300_GA_COLOR_CONTROL: 0x4278 */ + uint32_t polygon_mode; /* R300_GA_POLY_MODE: 0x4288 */ }; struct r300_rs_block { @@ -98,14 +91,28 @@ struct r300_rs_block { }; struct r300_sampler_state { + struct pipe_sampler_state state; + uint32_t filter0; /* R300_TX_FILTER0: 0x4400 */ uint32_t filter1; /* R300_TX_FILTER1: 0x4440 */ uint32_t border_color; /* R300_TX_BORDER_COLOR: 0x45c0 */ + + /* Min/max LOD must be clamped to [0, last_level], thus + * it's dependent on a currently bound texture */ + unsigned min_lod, max_lod; +}; + +struct r300_scissor_regs { + uint32_t top_left; /* R300_SC_SCISSORS_TL: 0x43e0 */ + uint32_t bottom_right; /* R300_SC_SCISSORS_BR: 0x43e4 */ + + /* Whether everything is culled by scissoring. */ + boolean empty_area; }; struct r300_scissor_state { - uint32_t scissor_top_left; /* R300_SC_SCISSORS_TL: 0x43e0 */ - uint32_t scissor_bottom_right; /* R300_SC_SCISSORS_BR: 0x43e4 */ + struct r300_scissor_regs framebuffer; + struct r300_scissor_regs scissor; }; struct r300_texture_state { @@ -124,13 +131,17 @@ struct r300_viewport_state { uint32_t vte_control; /* R300_VAP_VTE_CNTL: 0x20b0 */ }; +struct r300_ztop_state { + uint32_t z_buffer_top; /* R300_ZB_ZTOP: 0x4f14 */ +}; + #define R300_NEW_BLEND 0x00000001 #define R300_NEW_BLEND_COLOR 0x00000002 #define R300_NEW_CLIP 0x00000004 -#define R300_NEW_CONSTANTS 0x00000008 -#define R300_NEW_DSA 0x00000010 -#define R300_NEW_FRAMEBUFFERS 0x00000020 -#define R300_NEW_FRAGMENT_SHADER 0x00000040 +#define R300_NEW_DSA 0x00000008 +#define R300_NEW_FRAMEBUFFERS 0x00000010 +#define R300_NEW_FRAGMENT_SHADER 0x00000020 +#define R300_NEW_FRAGMENT_SHADER_CONSTANTS 0x00000040 #define R300_NEW_RASTERIZER 0x00000080 #define R300_NEW_RS_BLOCK 0x00000100 #define R300_NEW_SAMPLER 0x00000200 @@ -140,8 +151,10 @@ struct r300_viewport_state { #define R300_ANY_NEW_TEXTURES 0x03fc0000 #define R300_NEW_VERTEX_FORMAT 0x04000000 #define R300_NEW_VERTEX_SHADER 0x08000000 -#define R300_NEW_VIEWPORT 0x10000000 -#define R300_NEW_KITCHEN_SINK 0x1fffffff +#define R300_NEW_VERTEX_SHADER_CONSTANTS 0x10000000 +#define R300_NEW_VIEWPORT 0x20000000 +#define R300_NEW_QUERY 0x40000000 +#define R300_NEW_KITCHEN_SINK 0x7fffffff /* The next several objects are not pure Radeon state; they inherit from * various Gallium classes. */ @@ -172,6 +185,10 @@ struct r300_query { unsigned int count; /* The offset of this query into the query buffer, in bytes. */ unsigned offset; + /* if we've flushed the query */ + boolean flushed; + /* if begin has been emitted */ + boolean begin_emitted; /* Linked list members. */ struct r300_query* prev; struct r300_query* next; @@ -184,6 +201,12 @@ struct r300_texture { /* Offsets into the buffer. */ unsigned offset[PIPE_MAX_TEXTURE_LEVELS]; + /* A pitch for each mip-level */ + unsigned pitch[PIPE_MAX_TEXTURE_LEVELS]; + + /* Size of one zslice or face based on the texture target */ + unsigned layer_size[PIPE_MAX_TEXTURE_LEVELS]; + /** * If non-zero, override the natural texture layout with * a custom stride (in bytes). @@ -197,6 +220,11 @@ struct r300_texture { /* Total size of this texture, in bytes. */ unsigned size; + /* Whether this texture has non-power-of-two dimensions. + * It can be either a regular texture or a rectangle one. + */ + boolean is_npot; + /* Pipe buffer backing this texture. */ struct pipe_buffer* buffer; @@ -204,18 +232,14 @@ struct r300_texture { struct r300_texture_state state; }; -struct r300_vertex_format { +struct r300_vertex_info { /* Parent class */ struct vertex_info vinfo; + /* R300_VAP_PROG_STREAK_CNTL_[0-7] */ uint32_t vap_prog_stream_cntl[8]; /* R300_VAP_PROG_STREAK_CNTL_EXT_[0-7] */ uint32_t vap_prog_stream_cntl_ext[8]; - /* Map of vertex attributes into PVS memory for HW TCL, - * or GA memory for SW TCL. */ - int vs_tab[16]; - /* Map of rasterizer attributes from GB through RS to US. */ - int fs_tab[16]; }; extern struct pipe_viewport_state r300_viewport_identity; @@ -225,9 +249,11 @@ struct r300_context { struct pipe_context context; /* The interface to the windowing system, etc. */ - struct r300_winsys* winsys; + struct radeon_winsys* winsys; /* Draw module. Used mostly for SW TCL. */ struct draw_context* draw; + /* Accelerated blit support. */ + struct blitter_context* blitter; /* Vertex buffer for rendering. */ struct pipe_buffer* vbo; @@ -237,7 +263,14 @@ struct r300_context { /* Occlusion query buffer. */ struct pipe_buffer* oqbo; /* Query list. */ - struct r300_query* query_list; + struct r300_query *query_current; + struct r300_query query_list; + + /* Shader hash table. Used to store vertex formatting information, which + * depends on the combination of both currently loaded shaders. */ + struct util_hash_table* shader_hash_table; + /* Vertex formatting information. */ + struct r300_vertex_info* vertex_info; /* Various CSO state objects. */ /* Blend state. */ @@ -266,15 +299,20 @@ struct r300_context { /* Texture states. */ struct r300_texture* textures[8]; int texture_count; - /* Vertex buffers for Gallium. */ - struct pipe_vertex_buffer vertex_buffers[PIPE_MAX_ATTRIBS]; - int vertex_buffer_count; - /* Vertex information. */ - struct r300_vertex_format vertex_info; /* Vertex shader. */ struct r300_vertex_shader* vs; /* Viewport state. */ struct r300_viewport_state* viewport_state; + /* ZTOP state. */ + struct r300_ztop_state ztop_state; + + /* Vertex buffers for Gallium. */ + struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS]; + int vertex_buffer_count; + /* Vertex elements for Gallium. */ + struct pipe_vertex_element vertex_element[PIPE_MAX_ATTRIBS]; + int vertex_element_count; + /* Bitmask of dirty state objects. */ uint32_t dirty_state; /* Flag indicating whether or not the HW is dirty. */ @@ -312,11 +350,13 @@ void r300_init_surface_functions(struct r300_context* r300); #define DBG_VP 0x0000004 #define DBG_CS 0x0000008 #define DBG_DRAW 0x0000010 +#define DBG_TEX 0x0000020 +#define DBG_FALL 0x0000040 /*@}*/ static INLINE boolean DBG_ON(struct r300_context * ctx, unsigned flags) { - return (ctx->debug & flags) ? true : false; + return (ctx->debug & flags) ? TRUE : FALSE; } static INLINE void DBG(struct r300_context * ctx, unsigned flags, const char * fmt, ...) diff --git a/src/gallium/drivers/r300/r300_cs.h b/src/gallium/drivers/r300/r300_cs.h index 883f0a02dc5..d142fee0502 100644 --- a/src/gallium/drivers/r300/r300_cs.h +++ b/src/gallium/drivers/r300/r300_cs.h @@ -26,7 +26,8 @@ #include "util/u_math.h" #include "r300_reg.h" -#include "r300_winsys.h" + +#include "radeon_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 @@ -34,8 +35,8 @@ #define MAX_CS_SIZE 64 * 1024 / 4 -#define VERY_VERBOSE_CS 0 -#define VERY_VERBOSE_REGISTERS 0 +#define VERY_VERBOSE_CS 1 +#define VERY_VERBOSE_REGISTERS 1 /* XXX stolen from radeon_drm.h */ #define RADEON_GEM_DOMAIN_CPU 0x1 @@ -50,11 +51,11 @@ #define CS_LOCALS(context) \ struct r300_context* const cs_context_copy = (context); \ - struct r300_winsys* cs_winsys = cs_context_copy->winsys; \ + struct radeon_winsys* cs_winsys = cs_context_copy->winsys; \ int cs_count = 0; #define CHECK_CS(size) \ - cs_winsys->check_cs(cs_winsys, (size)) + assert(cs_winsys->check_cs(cs_winsys, (size))) #define BEGIN_CS(size) do { \ CHECK_CS(size); \ @@ -114,6 +115,15 @@ cs_count -= 3; \ } while (0) +#define OUT_CS_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); \ + assert(bo); \ + cs_winsys->write_cs_reloc(cs_winsys, bo, rd, wd, flags); \ + cs_count -= 2; \ +} 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__, \ diff --git a/src/gallium/drivers/r300/r300_debug.c b/src/gallium/drivers/r300/r300_debug.c index 85d69c07479..2a6ed54ac9b 100644 --- a/src/gallium/drivers/r300/r300_debug.c +++ b/src/gallium/drivers/r300/r300_debug.c @@ -37,6 +37,8 @@ static struct debug_option debug_options[] = { { "vp", DBG_VP, "Vertex program handling" }, { "cs", DBG_CS, "Command submissions" }, { "draw", DBG_DRAW, "Draw and emit" }, + { "tex", DBG_TEX, "Textures" }, + { "fall", DBG_FALL, "Fallbacks" }, { "all", ~0, "Convenience option that enables all debug flags" }, @@ -47,7 +49,7 @@ static struct debug_option debug_options[] = { void r300_init_debug(struct r300_context * ctx) { const char * options = debug_get_option("RADEON_DEBUG", 0); - boolean printhint = false; + boolean printhint = FALSE; size_t length; struct debug_option * opt; @@ -69,14 +71,14 @@ void r300_init_debug(struct r300_context * ctx) if (!opt->name) { debug_printf("Unknown debug option: %s\n", options); - printhint = true; + printhint = TRUE; } options += length; } if (!ctx->debug) - printhint = true; + printhint = TRUE; } if (printhint || ctx->debug & DBG_HELP) { diff --git a/src/gallium/drivers/r300/r300_emit.c b/src/gallium/drivers/r300/r300_emit.c index 77ce431cdc3..f8bfa714fef 100644 --- a/src/gallium/drivers/r300/r300_emit.c +++ b/src/gallium/drivers/r300/r300_emit.c @@ -1,5 +1,6 @@ /* * Copyright 2008 Corbin Simpson <[email protected]> + * Copyright 2009 Marek Olšák <[email protected]> * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -22,20 +23,35 @@ /* r300_emit: Functions for emitting state. */ -#include "r300_emit.h" +#include "util/u_format.h" +#include "util/u_math.h" +#include "r300_context.h" +#include "r300_cs.h" +#include "r300_emit.h" #include "r300_fs.h" +#include "r300_screen.h" #include "r300_state_derived.h" +#include "r300_state_inlines.h" +#include "r300_texture.h" #include "r300_vs.h" void r300_emit_blend_state(struct r300_context* r300, struct r300_blend_state* blend) { CS_LOCALS(r300); - BEGIN_CS(7); - OUT_CS_REG_SEQ(R300_RB3D_CBLEND, 2); - OUT_CS(blend->blend_control); - OUT_CS(blend->alpha_blend_control); + BEGIN_CS(8); + OUT_CS_REG_SEQ(R300_RB3D_CBLEND, 3); + if (r300->framebuffer_state.nr_cbufs) { + OUT_CS(blend->blend_control); + OUT_CS(blend->alpha_blend_control); + OUT_CS(blend->color_channel_mask); + } else { + OUT_CS(0); + OUT_CS(0); + OUT_CS(0); + /* XXX also disable fastfill here once it's supported */ + } OUT_CS_REG(R300_RB3D_ROPCNTL, blend->rop); OUT_CS_REG(R300_RB3D_DITHER_CTL, blend->dither); END_CS; @@ -96,19 +112,30 @@ void r300_emit_dsa_state(struct r300_context* r300, struct r300_screen* r300screen = r300_screen(r300->context.screen); CS_LOCALS(r300); - BEGIN_CS(r300screen->caps->is_r500 ? 8 : 8); + BEGIN_CS(r300screen->caps->is_r500 ? 10 : 8); OUT_CS_REG(R300_FG_ALPHA_FUNC, dsa->alpha_function); - /* XXX figure out the r300 counterpart for this */ - if (r300screen->caps->is_r500) { - /* OUT_CS_REG(R500_FG_ALPHA_VALUE, dsa->alpha_reference); */ - } + + /* not needed since we use the 8bit alpha ref */ + /*if (r300screen->caps->is_r500) { + OUT_CS_REG(R500_FG_ALPHA_VALUE, dsa->alpha_reference); + }*/ + OUT_CS_REG_SEQ(R300_ZB_CNTL, 3); - OUT_CS(dsa->z_buffer_control); - OUT_CS(dsa->z_stencil_control); + + if (r300->framebuffer_state.zsbuf) { + OUT_CS(dsa->z_buffer_control); + OUT_CS(dsa->z_stencil_control); + } else { + OUT_CS(0); + OUT_CS(0); + } + OUT_CS(dsa->stencil_ref_mask); - OUT_CS_REG(R300_ZB_ZTOP, dsa->z_buffer_top); + OUT_CS_REG(R300_ZB_ZTOP, r300->ztop_state.z_buffer_top); + + /* XXX it seems r3xx doesn't support STENCILREFMASK_BF */ if (r300screen->caps->is_r500) { - /* OUT_CS_REG(R500_ZB_STENCILREFMASK_BF, dsa->stencil_ref_bf); */ + OUT_CS_REG(R500_ZB_STENCILREFMASK_BF, dsa->stencil_ref_bf); } END_CS; } @@ -118,7 +145,9 @@ static const float * get_shader_constant( struct rc_constant * constant, struct r300_constant_buffer * externals) { - static const float zero[4] = { 0.0, 0.0, 0.0, 0.0 }; + static float vec[4] = { 0.0, 0.0, 0.0, 1.0 }; + struct pipe_texture *tex; + switch(constant->Type) { case RC_CONSTANT_EXTERNAL: return externals->constants[constant->u.External]; @@ -126,11 +155,60 @@ static const float * get_shader_constant( case RC_CONSTANT_IMMEDIATE: return constant->u.Immediate; + case RC_CONSTANT_STATE: + switch (constant->u.State[0]) { + /* Factor for converting rectangle coords to + * normalized coords. Should only show up on non-r500. */ + case RC_STATE_R300_TEXRECT_FACTOR: + tex = &r300->textures[constant->u.State[1]]->tex; + vec[0] = 1.0 / tex->width0; + vec[1] = 1.0 / tex->height0; + break; + + /* Texture compare-fail value. */ + /* XXX Since Gallium doesn't support GL_ARB_shadow_ambient, + * this is always (0,0,0,0). */ + case RC_STATE_SHADOW_AMBIENT: + vec[3] = 0; + break; + + case RC_STATE_R300_VIEWPORT_SCALE: + if (r300->rs_state->enable_vte) { + vec[0] = r300->viewport_state->xscale; + vec[1] = r300->viewport_state->yscale; + vec[2] = r300->viewport_state->zscale; + } else { + vec[0] = 1; + vec[1] = 1; + vec[2] = 1; + } + break; + + case RC_STATE_R300_VIEWPORT_OFFSET: + if (r300->rs_state->enable_vte) { + vec[0] = r300->viewport_state->xoffset; + vec[1] = r300->viewport_state->yoffset; + vec[2] = r300->viewport_state->zoffset; + } else { + /* Zeros. */ + } + break; + + default: + debug_printf("r300: Implementation error: " + "Unknown RC_CONSTANT type %d\n", constant->u.State[0]); + } + break; + default: - debug_printf("r300: Implementation error: Unhandled constant type %i\n", - constant->Type); - return zero; + debug_printf("r300: Implementation error: " + "Unhandled constant type %d\n", constant->Type); } + + /* This should either be (0, 0, 0, 1), which should be a relatively safe + * RGBA or STRQ value, or it could be one of the RC_CONSTANT_STATE + * state factors. */ + return vec; } /* Convert a normal single-precision float into the 7.16 format @@ -168,18 +246,15 @@ static uint32_t pack_float24(float f) } void r300_emit_fragment_program_code(struct r300_context* r300, - struct rX00_fragment_program_code* generic_code, - struct r300_constant_buffer* externals) + struct rX00_fragment_program_code* generic_code) { struct r300_fragment_program_code * code = &generic_code->code.r300; - struct rc_constant_list * constants = &generic_code->constants; int i; CS_LOCALS(r300); BEGIN_CS(15 + code->alu.length * 4 + - (code->tex.length ? (1 + code->tex.length) : 0) + - (constants->Count ? (1 + constants->Count * 4) : 0)); + (code->tex.length ? (1 + code->tex.length) : 0)); OUT_CS_REG(R300_US_CONFIG, code->config); OUT_CS_REG(R300_US_PIXSIZE, code->pixsize); @@ -211,33 +286,58 @@ void r300_emit_fragment_program_code(struct r300_context* r300, OUT_CS(code->tex.inst[i]); } - if (constants->Count) { - OUT_CS_ONE_REG(R300_PFS_PARAM_0_X, constants->Count * 4); - for(i = 0; i < constants->Count; ++i) { - const float * data = get_shader_constant(r300, &constants->Constants[i], externals); - OUT_CS(pack_float24(data[0])); - OUT_CS(pack_float24(data[1])); - OUT_CS(pack_float24(data[2])); - OUT_CS(pack_float24(data[3])); - } + END_CS; +} + +void r300_emit_fs_constant_buffer(struct r300_context* r300, + struct rc_constant_list* constants) +{ + int i; + CS_LOCALS(r300); + + if (constants->Count == 0) + return; + + BEGIN_CS(constants->Count * 4 + 1); + OUT_CS_REG_SEQ(R300_PFS_PARAM_0_X, constants->Count * 4); + for(i = 0; i < constants->Count; ++i) { + const float * data = get_shader_constant(r300, + &constants->Constants[i], + &r300->shader_constants[PIPE_SHADER_FRAGMENT]); + OUT_CS(pack_float24(data[0])); + OUT_CS(pack_float24(data[1])); + OUT_CS(pack_float24(data[2])); + OUT_CS(pack_float24(data[3])); } + END_CS; +} +static void r300_emit_fragment_depth_config(struct r300_context* r300, + struct r300_fragment_shader* fs) +{ + CS_LOCALS(r300); + + BEGIN_CS(4); + if (r300_fragment_shader_writes_depth(fs)) { + OUT_CS_REG(R300_FG_DEPTH_SRC, R300_FG_DEPTH_SRC_SHADER); + OUT_CS_REG(R300_US_W_FMT, R300_W_FMT_W24 | R300_W_SRC_US); + } else { + OUT_CS_REG(R300_FG_DEPTH_SRC, R300_FG_DEPTH_SRC_SCAN); + OUT_CS_REG(R300_US_W_FMT, R300_W_FMT_W0 | R300_W_SRC_US); + } END_CS; } void r500_emit_fragment_program_code(struct r300_context* r300, - struct rX00_fragment_program_code* generic_code, - struct r300_constant_buffer* externals) + struct rX00_fragment_program_code* generic_code) { struct r500_fragment_program_code * code = &generic_code->code.r500; - struct rc_constant_list * constants = &generic_code->constants; int i; CS_LOCALS(r300); BEGIN_CS(13 + - ((code->inst_end + 1) * 6) + - (constants->Count ? (3 + (constants->Count * 4)) : 0)); - OUT_CS_REG(R500_US_CONFIG, 0); + ((code->inst_end + 1) * 6)); + 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)); @@ -256,18 +356,30 @@ void r500_emit_fragment_program_code(struct r300_context* r300, OUT_CS(code->inst[i].inst5); } - if (constants->Count) { - OUT_CS_REG(R500_GA_US_VECTOR_INDEX, R500_GA_US_VECTOR_INDEX_TYPE_CONST); - OUT_CS_ONE_REG(R500_GA_US_VECTOR_DATA, constants->Count * 4); - for (i = 0; i < constants->Count; i++) { - const float * data = get_shader_constant(r300, &constants->Constants[i], externals); - OUT_CS_32F(data[0]); - OUT_CS_32F(data[1]); - OUT_CS_32F(data[2]); - OUT_CS_32F(data[3]); - } - } + END_CS; +} + +void r500_emit_fs_constant_buffer(struct r300_context* r300, + struct rc_constant_list* constants) +{ + int i; + CS_LOCALS(r300); + + if (constants->Count == 0) + return; + BEGIN_CS(constants->Count * 4 + 3); + OUT_CS_REG(R500_GA_US_VECTOR_INDEX, R500_GA_US_VECTOR_INDEX_TYPE_CONST); + OUT_CS_ONE_REG(R500_GA_US_VECTOR_DATA, constants->Count * 4); + for (i = 0; i < constants->Count; i++) { + const float * data = get_shader_constant(r300, + &constants->Constants[i], + &r300->shader_constants[PIPE_SHADER_FRAGMENT]); + OUT_CS_32F(data[0]); + OUT_CS_32F(data[1]); + OUT_CS_32F(data[2]); + OUT_CS_32F(data[3]); + } END_CS; } @@ -275,76 +387,98 @@ void r300_emit_fb_state(struct r300_context* r300, struct pipe_framebuffer_state* fb) { struct r300_texture* tex; - unsigned pixpitch; + struct pipe_surface* surf; int i; CS_LOCALS(r300); - BEGIN_CS((10 * fb->nr_cbufs) + (fb->zsbuf ? 10 : 0) + 4); + /* Shouldn't fail unless there is a bug in the state tracker. */ + assert(fb->nr_cbufs <= 4); + + BEGIN_CS((10 * fb->nr_cbufs) + (2 * (4 - fb->nr_cbufs)) + + (fb->zsbuf ? 10 : 0) + 6); + + /* 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. */ + OUT_CS_REG(R300_RB3D_CCTL, R300_RB3D_CCTL_NUM_MULTIWRITES(fb->nr_cbufs)); + + /* Set up colorbuffers. */ for (i = 0; i < fb->nr_cbufs; i++) { - tex = (struct r300_texture*)fb->cbufs[i]->texture; + surf = fb->cbufs[i]; + tex = (struct r300_texture*)surf->texture; assert(tex && tex->buffer && "cbuf is marked, but NULL!"); - pixpitch = r300_texture_get_stride(tex, 0) / tex->tex.block.size; OUT_CS_REG_SEQ(R300_RB3D_COLOROFFSET0 + (4 * i), 1); - OUT_CS_RELOC(tex->buffer, 0, 0, RADEON_GEM_DOMAIN_VRAM, 0); + OUT_CS_RELOC(tex->buffer, surf->offset, 0, RADEON_GEM_DOMAIN_VRAM, 0); OUT_CS_REG_SEQ(R300_RB3D_COLORPITCH0 + (4 * i), 1); - OUT_CS_RELOC(tex->buffer, pixpitch | + OUT_CS_RELOC(tex->buffer, tex->pitch[surf->level] | r300_translate_colorformat(tex->tex.format), 0, RADEON_GEM_DOMAIN_VRAM, 0); OUT_CS_REG(R300_US_OUT_FMT_0 + (4 * i), - r300_translate_out_fmt(fb->cbufs[i]->format)); + r300_translate_out_fmt(surf->format)); + } + + /* Disable unused colorbuffers. */ + for (; i < 4; i++) { + OUT_CS_REG(R300_US_OUT_FMT_0 + (4 * i), R300_US_OUT_FMT_UNUSED); } + /* Set up a zbuffer. */ if (fb->zsbuf) { - tex = (struct r300_texture*)fb->zsbuf->texture; + surf = fb->zsbuf; + tex = (struct r300_texture*)surf->texture; assert(tex && tex->buffer && "zsbuf is marked, but NULL!"); - pixpitch = r300_texture_get_stride(tex, 0) / tex->tex.block.size; OUT_CS_REG_SEQ(R300_ZB_DEPTHOFFSET, 1); - OUT_CS_RELOC(tex->buffer, 0, 0, RADEON_GEM_DOMAIN_VRAM, 0); + OUT_CS_RELOC(tex->buffer, surf->offset, 0, RADEON_GEM_DOMAIN_VRAM, 0); OUT_CS_REG(R300_ZB_FORMAT, r300_translate_zsformat(tex->tex.format)); OUT_CS_REG_SEQ(R300_ZB_DEPTHPITCH, 1); - OUT_CS_RELOC(tex->buffer, pixpitch, 0, RADEON_GEM_DOMAIN_VRAM, 0); + OUT_CS_RELOC(tex->buffer, tex->pitch[surf->level], 0, + RADEON_GEM_DOMAIN_VRAM, 0); } - 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); END_CS; } -void r300_emit_query_begin(struct r300_context* r300, - struct r300_query* query) +static void r300_emit_query_start(struct r300_context *r300) { + struct r300_capabilities *caps = r300_screen(r300->context.screen)->caps; + struct r300_query *query = r300->query_current; CS_LOCALS(r300); - /* XXX This will almost certainly not return good results - * for overlapping queries. */ - BEGIN_CS(2); + if (!query) + return; + + BEGIN_CS(4); + if (caps->family == CHIP_FAMILY_RV530) { + OUT_CS_REG(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_ALL); + } else { + OUT_CS_REG(R300_SU_REG_DEST, R300_RASTER_PIPE_SELECT_ALL); + } OUT_CS_REG(R300_ZB_ZPASS_DATA, 0); END_CS; + query->begin_emitted = TRUE; } -void r300_emit_query_end(struct r300_context* r300, - struct r300_query* query) + +static void r300_emit_query_finish(struct r300_context *r300, + struct r300_query *query) { struct r300_capabilities* caps = r300_screen(r300->context.screen)->caps; CS_LOCALS(r300); - if (!r300->winsys->add_buffer(r300->winsys, r300->oqbo, - 0, RADEON_GEM_DOMAIN_GTT)) { - debug_printf("r300: There wasn't room for the OQ buffer!?" - " Oh noes!\n"); - } - assert(caps->num_frag_pipes); + BEGIN_CS(6 * caps->num_frag_pipes + 2); /* I'm not so sure I like this switch, but it's hard to be elegant * when there's so many special cases... @@ -381,7 +515,7 @@ void r300_emit_query_end(struct r300_context* r300, OUT_CS_REG_SEQ(R300_ZB_ZPASS_ADDR, 1); OUT_CS_RELOC(r300->oqbo, query->offset + (sizeof(uint32_t) * 0), 0, RADEON_GEM_DOMAIN_GTT, 0); - break; + break; default: debug_printf("r300: Implementation error: Chipset reports %d" " pixel pipes!\n", caps->num_frag_pipes); @@ -391,14 +525,62 @@ void r300_emit_query_end(struct r300_context* r300, /* And, finally, reset it to normal... */ OUT_CS_REG(R300_SU_REG_DEST, 0xF); END_CS; +} + +static void rv530_emit_query_single(struct r300_context *r300, + struct r300_query *query) +{ + 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_RELOC(r300->oqbo, query->offset, 0, RADEON_GEM_DOMAIN_GTT, 0); + OUT_CS_REG(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_ALL); + END_CS; +} + +static void rv530_emit_query_double(struct r300_context *r300, + struct r300_query *query) +{ + 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_RELOC(r300->oqbo, query->offset, 0, RADEON_GEM_DOMAIN_GTT, 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_RELOC(r300->oqbo, query->offset + sizeof(uint32_t), 0, RADEON_GEM_DOMAIN_GTT, 0); + OUT_CS_REG(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_ALL); + END_CS; +} + +void r300_emit_query_end(struct r300_context* r300) +{ + struct r300_capabilities *caps = r300_screen(r300->context.screen)->caps; + struct r300_query *query = r300->query_current; + + if (!query) + return; + + if (query->begin_emitted == FALSE) + return; + + if (caps->family == CHIP_FAMILY_RV530) { + if (caps->num_z_pipes == 2) + rv530_emit_query_double(r300, query); + else + rv530_emit_query_single(r300, query); + } else + r300_emit_query_finish(r300, query); } void r300_emit_rs_state(struct r300_context* r300, struct r300_rs_state* rs) { CS_LOCALS(r300); - BEGIN_CS(20); + BEGIN_CS(22); OUT_CS_REG(R300_VAP_CNTL_STATUS, rs->vap_control_status); OUT_CS_REG(R300_GA_POINT_SIZE, rs->point_size); OUT_CS_REG_SEQ(R300_GA_POINT_MINMAX, 2); @@ -414,6 +596,7 @@ void r300_emit_rs_state(struct r300_context* r300, struct r300_rs_state* rs) 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_COLOR_CONTROL, rs->color_control); + OUT_CS_REG(R300_GA_POLY_MODE, rs->polygon_mode); END_CS; } @@ -424,6 +607,8 @@ void r300_emit_rs_block_state(struct r300_context* r300, struct r300_screen* r300screen = r300_screen(r300->context.screen); CS_LOCALS(r300); + DBG(r300, DBG_DRAW, "r300: RS emit:\n"); + BEGIN_CS(21); if (r300screen->caps->is_r500) { OUT_CS_REG_SEQ(R500_RS_IP_0, 8); @@ -432,7 +617,7 @@ void r300_emit_rs_block_state(struct r300_context* r300, } for (i = 0; i < 8; i++) { OUT_CS(rs->ip[i]); - /* debug_printf("ip %d: 0x%08x\n", i, rs->ip[i]); */ + DBG(r300, DBG_DRAW, " : ip %d: 0x%08x\n", i, rs->ip[i]); } OUT_CS_REG_SEQ(R300_RS_COUNT, 2); @@ -446,40 +631,67 @@ void r300_emit_rs_block_state(struct r300_context* r300, } for (i = 0; i < 8; i++) { OUT_CS(rs->inst[i]); - /* debug_printf("inst %d: 0x%08x\n", i, rs->inst[i]); */ + DBG(r300, DBG_DRAW, " : inst %d: 0x%08x\n", i, rs->inst[i]); } - /* debug_printf("count: 0x%08x inst_count: 0x%08x\n", rs->count, - * rs->inst_count); */ + DBG(r300, DBG_DRAW, " : count: 0x%08x inst_count: 0x%08x\n", + rs->count, rs->inst_count); END_CS; } -void r300_emit_scissor_state(struct r300_context* r300, - struct r300_scissor_state* scissor) +static void r300_emit_scissor_regs(struct r300_context* r300, + struct r300_scissor_regs* scissor) { CS_LOCALS(r300); BEGIN_CS(3); OUT_CS_REG_SEQ(R300_SC_SCISSORS_TL, 2); - OUT_CS(scissor->scissor_top_left); - OUT_CS(scissor->scissor_bottom_right); + OUT_CS(scissor->top_left); + OUT_CS(scissor->bottom_right); END_CS; } +void r300_emit_scissor_state(struct r300_context* r300, + struct r300_scissor_state* scissor) +{ + if (r300->rs_state->rs.scissor) { + r300_emit_scissor_regs(r300, &scissor->scissor); + } else { + r300_emit_scissor_regs(r300, &scissor->framebuffer); + } +} + void r300_emit_texture(struct r300_context* r300, struct r300_sampler_state* sampler, struct r300_texture* tex, unsigned offset) { + uint32_t filter0 = sampler->filter0; + uint32_t format0 = tex->state.format0; + unsigned min_level, max_level; CS_LOCALS(r300); + /* to emulate 1D textures through 2D ones correctly */ + if (tex->tex.target == PIPE_TEXTURE_1D) { + filter0 &= ~R300_TX_WRAP_T_MASK; + filter0 |= R300_TX_WRAP_T(R300_TX_CLAMP_TO_EDGE); + } + + /* determine min/max levels */ + /* the MAX_MIP level is the largest (finest) one */ + max_level = MIN2(sampler->max_lod, tex->tex.last_level); + min_level = MIN2(sampler->min_lod, max_level); + format0 |= R300_TX_NUM_LEVELS(max_level); + filter0 |= R300_TX_MAX_MIP_LEVEL(min_level); + BEGIN_CS(16); - OUT_CS_REG(R300_TX_FILTER0_0 + (offset * 4), sampler->filter0); + OUT_CS_REG(R300_TX_FILTER0_0 + (offset * 4), filter0 | + (offset << 28)); OUT_CS_REG(R300_TX_FILTER1_0 + (offset * 4), sampler->filter1); OUT_CS_REG(R300_TX_BORDER_COLOR_0 + (offset * 4), sampler->border_color); - OUT_CS_REG(R300_TX_FORMAT0_0 + (offset * 4), tex->state.format0); + OUT_CS_REG(R300_TX_FORMAT0_0 + (offset * 4), format0); OUT_CS_REG(R300_TX_FORMAT1_0 + (offset * 4), tex->state.format1); OUT_CS_REG(R300_TX_FORMAT2_0 + (offset * 4), tex->state.format2); OUT_CS_REG_SEQ(R300_TX_OFFSET_0 + (offset * 4), 1); @@ -488,13 +700,76 @@ void r300_emit_texture(struct r300_context* r300, END_CS; } -void r300_emit_vertex_buffer(struct r300_context* r300) +static boolean r300_validate_aos(struct r300_context *r300) +{ + struct pipe_vertex_buffer *vbuf = r300->vertex_buffer; + struct pipe_vertex_element *velem = r300->vertex_element; + int i; + + /* Check if formats and strides are aligned to the size of DWORD. */ + for (i = 0; i < r300->vertex_element_count; i++) { + if (vbuf[velem[i].vertex_buffer_index].stride % 4 != 0 || + util_format_get_blocksize(velem[i].src_format) % 4 != 0) { + return FALSE; + } + } + return TRUE; +} + +void r300_emit_aos(struct r300_context* r300, unsigned offset) +{ + struct pipe_vertex_buffer *vb1, *vb2, *vbuf = r300->vertex_buffer; + struct pipe_vertex_element *velem = r300->vertex_element; + int i; + unsigned size1, size2, aos_count = r300->vertex_element_count; + unsigned packet_size = (aos_count * 3 + 1) / 2; + CS_LOCALS(r300); + + /* XXX Move this checking to a more approriate place. */ + if (!r300_validate_aos(r300)) { + /* XXX We should fallback using Draw. */ + assert(0); + } + + BEGIN_CS(2 + packet_size + aos_count * 2); + OUT_CS_PKT3(R300_PACKET3_3D_LOAD_VBPNTR, packet_size); + OUT_CS(aos_count); + + 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); + + OUT_CS(R300_VBPNTR_SIZE0(size1) | R300_VBPNTR_STRIDE0(vb1->stride) | + R300_VBPNTR_SIZE1(size2) | R300_VBPNTR_STRIDE1(vb2->stride)); + OUT_CS(vb1->buffer_offset + velem[i].src_offset + offset * vb1->stride); + OUT_CS(vb2->buffer_offset + velem[i+1].src_offset + offset * vb2->stride); + } + + if (aos_count & 1) { + vb1 = &vbuf[velem[i].vertex_buffer_index]; + size1 = util_format_get_blocksize(velem[i].src_format); + + OUT_CS(R300_VBPNTR_SIZE0(size1) | R300_VBPNTR_STRIDE0(vb1->stride)); + OUT_CS(vb1->buffer_offset + velem[i].src_offset + offset * vb1->stride); + } + + for (i = 0; i < aos_count; i++) { + OUT_CS_RELOC_NO_OFFSET(vbuf[velem[i].vertex_buffer_index].buffer, + RADEON_GEM_DOMAIN_GTT, 0, 0); + } + END_CS; +} + +#if 0 +void r300_emit_draw_packet(struct r300_context* r300) { CS_LOCALS(r300); DBG(r300, DBG_DRAW, "r300: Preparing vertex buffer %p for render, " "vertex size %d\n", r300->vbo, - r300->vertex_info.vinfo.size); + r300->vertex_info->vinfo.size); /* Set the pointer to our vertex buffer. The emitted values are this: * PACKET3 [3D_LOAD_VBPNTR] * COUNT [1] @@ -505,54 +780,66 @@ void r300_emit_vertex_buffer(struct r300_context* r300) BEGIN_CS(7); OUT_CS_PKT3(R300_PACKET3_3D_LOAD_VBPNTR, 3); OUT_CS(1); - OUT_CS(r300->vertex_info.vinfo.size | - (r300->vertex_info.vinfo.size << 8)); + OUT_CS(r300->vertex_info->vinfo.size | + (r300->vertex_info->vinfo.size << 8)); OUT_CS(r300->vbo_offset); OUT_CS_RELOC(r300->vbo, 0, RADEON_GEM_DOMAIN_GTT, 0, 0); END_CS; } +#endif void r300_emit_vertex_format_state(struct r300_context* r300) { int i; CS_LOCALS(r300); + DBG(r300, DBG_DRAW, "r300: VAP/PSC emit:\n"); + BEGIN_CS(26); - OUT_CS_REG(R300_VAP_VTX_SIZE, r300->vertex_info.vinfo.size); + OUT_CS_REG(R300_VAP_VTX_SIZE, r300->vertex_info->vinfo.size); OUT_CS_REG_SEQ(R300_VAP_VTX_STATE_CNTL, 2); - OUT_CS(r300->vertex_info.vinfo.hwfmt[0]); - OUT_CS(r300->vertex_info.vinfo.hwfmt[1]); + OUT_CS(r300->vertex_info->vinfo.hwfmt[0]); + OUT_CS(r300->vertex_info->vinfo.hwfmt[1]); OUT_CS_REG_SEQ(R300_VAP_OUTPUT_VTX_FMT_0, 2); - OUT_CS(r300->vertex_info.vinfo.hwfmt[2]); - OUT_CS(r300->vertex_info.vinfo.hwfmt[3]); - /* for (i = 0; i < 4; i++) { - * debug_printf("hwfmt%d: 0x%08x\n", i, - * r300->vertex_info.vinfo.hwfmt[i]); - * } */ + OUT_CS(r300->vertex_info->vinfo.hwfmt[2]); + OUT_CS(r300->vertex_info->vinfo.hwfmt[3]); + for (i = 0; i < 4; i++) { + DBG(r300, DBG_DRAW, " : hwfmt%d: 0x%08x\n", i, + r300->vertex_info->vinfo.hwfmt[i]); + } OUT_CS_REG_SEQ(R300_VAP_PROG_STREAM_CNTL_0, 8); for (i = 0; i < 8; i++) { - OUT_CS(r300->vertex_info.vap_prog_stream_cntl[i]); - /* debug_printf("prog_stream_cntl%d: 0x%08x\n", i, - * r300->vertex_info.vap_prog_stream_cntl[i]); */ + OUT_CS(r300->vertex_info->vap_prog_stream_cntl[i]); + DBG(r300, DBG_DRAW, " : prog_stream_cntl%d: 0x%08x\n", i, + r300->vertex_info->vap_prog_stream_cntl[i]); } OUT_CS_REG_SEQ(R300_VAP_PROG_STREAM_CNTL_EXT_0, 8); for (i = 0; i < 8; i++) { - OUT_CS(r300->vertex_info.vap_prog_stream_cntl_ext[i]); - /* debug_printf("prog_stream_cntl_ext%d: 0x%08x\n", i, - * r300->vertex_info.vap_prog_stream_cntl_ext[i]); */ + OUT_CS(r300->vertex_info->vap_prog_stream_cntl_ext[i]); + DBG(r300, DBG_DRAW, " : prog_stream_cntl_ext%d: 0x%08x\n", i, + r300->vertex_info->vap_prog_stream_cntl_ext[i]); } END_CS; } + void r300_emit_vertex_program_code(struct r300_context* r300, - struct r300_vertex_program_code* code, - struct r300_constant_buffer* constants) + struct r300_vertex_program_code* code) { int i; struct r300_screen* r300screen = r300_screen(r300->context.screen); unsigned instruction_count = code->length / 4; + + int vtx_mem_size = r300screen->caps->is_r500 ? 128 : 72; + int input_count = MAX2(util_bitcount(code->InputsRead), 1); + int output_count = MAX2(util_bitcount(code->OutputsWritten), 1); + int temp_count = MAX2(code->num_temporaries, 1); + int pvs_num_slots = MIN3(vtx_mem_size / input_count, + vtx_mem_size / output_count, 10); + int pvs_num_controllers = MIN2(vtx_mem_size / temp_count, 6); + CS_LOCALS(r300); if (!r300screen->caps->has_tcl) { @@ -561,17 +848,11 @@ void r300_emit_vertex_program_code(struct r300_context* r300, return; } - if (code->constants.Count) { - BEGIN_CS(14 + code->length + (code->constants.Count * 4)); - } else { - BEGIN_CS(11 + code->length); - } - + BEGIN_CS(9 + code->length); /* R300_VAP_PVS_CODE_CNTL_0 * R300_VAP_PVS_CONST_CNTL * R300_VAP_PVS_CODE_CNTL_1 - * See the r5xx docs for instructions on how to use these. - * XXX these could be optimized to select better values... */ + * See the r5xx docs for instructions on how to use these. */ OUT_CS_REG_SEQ(R300_VAP_PVS_CODE_CNTL_0, 3); OUT_CS(R300_PVS_FIRST_INST(0) | R300_PVS_XYZW_VALID_INST(instruction_count - 1) | @@ -584,32 +865,51 @@ void r300_emit_vertex_program_code(struct r300_context* r300, for (i = 0; i < code->length; i++) OUT_CS(code->body.d[i]); - if (code->constants.Count) { - OUT_CS_REG(R300_VAP_PVS_VECTOR_INDX_REG, - (r300screen->caps->is_r500 ? - R500_PVS_CONST_START : R300_PVS_CONST_START)); - OUT_CS_ONE_REG(R300_VAP_PVS_UPLOAD_DATA, code->constants.Count * 4); - for (i = 0; i < code->constants.Count; i++) { - const float * data = get_shader_constant(r300, &code->constants.Constants[i], constants); - OUT_CS_32F(data[0]); - OUT_CS_32F(data[1]); - OUT_CS_32F(data[2]); - OUT_CS_32F(data[3]); - } - } - - OUT_CS_REG(R300_VAP_CNTL, R300_PVS_NUM_SLOTS(10) | - R300_PVS_NUM_CNTLRS(5) | + OUT_CS_REG(R300_VAP_CNTL, R300_PVS_NUM_SLOTS(pvs_num_slots) | + R300_PVS_NUM_CNTLRS(pvs_num_controllers) | R300_PVS_NUM_FPUS(r300screen->caps->num_vert_fpus) | - R300_PVS_VF_MAX_VTX_NUM(12)); - OUT_CS_REG(R300_VAP_PVS_STATE_FLUSH_REG, 0x0); + R300_PVS_VF_MAX_VTX_NUM(12) | + (r300screen->caps->is_r500 ? R500_TCL_STATE_OPTIMIZATION : 0)); END_CS; } void r300_emit_vertex_shader(struct r300_context* r300, struct r300_vertex_shader* vs) { - r300_emit_vertex_program_code(r300, &vs->code, &r300->shader_constants[PIPE_SHADER_VERTEX]); + r300_emit_vertex_program_code(r300, &vs->code); +} + +void r300_emit_vs_constant_buffer(struct r300_context* r300, + struct rc_constant_list* constants) +{ + int i; + struct r300_screen* r300screen = r300_screen(r300->context.screen); + CS_LOCALS(r300); + + if (!r300screen->caps->has_tcl) { + debug_printf("r300: Implementation error: emit_vertex_shader called," + " but has_tcl is FALSE!\n"); + return; + } + + if (constants->Count == 0) + return; + + BEGIN_CS(constants->Count * 4 + 3); + OUT_CS_REG(R300_VAP_PVS_VECTOR_INDX_REG, + (r300screen->caps->is_r500 ? + R500_PVS_CONST_START : R300_PVS_CONST_START)); + OUT_CS_ONE_REG(R300_VAP_PVS_UPLOAD_DATA, constants->Count * 4); + for (i = 0; i < constants->Count; i++) { + const float * data = get_shader_constant(r300, + &constants->Constants[i], + &r300->shader_constants[PIPE_SHADER_VERTEX]); + OUT_CS_32F(data[0]); + OUT_CS_32F(data[1]); + OUT_CS_32F(data[2]); + OUT_CS_32F(data[3]); + } + END_CS; } void r300_emit_viewport_state(struct r300_context* r300, @@ -634,13 +934,42 @@ void r300_emit_viewport_state(struct r300_context* r300, END_CS; } +void r300_emit_texture_count(struct r300_context* r300) +{ + uint32_t tx_enable = 0; + int i; + CS_LOCALS(r300); + + /* Notice that texture_count and sampler_count are just sizes + * of the respective arrays. We still have to check for the individual + * elements. */ + for (i = 0; i < MIN2(r300->sampler_count, r300->texture_count); i++) { + if (r300->textures[i]) { + tx_enable |= 1 << i; + } + } + + BEGIN_CS(2); + OUT_CS_REG(R300_TX_ENABLE, tx_enable); + END_CS; + +} + void r300_flush_textures(struct r300_context* r300) { CS_LOCALS(r300); - BEGIN_CS(4); + BEGIN_CS(2); OUT_CS_REG(R300_TX_INVALTAGS, 0); - OUT_CS_REG(R300_TX_ENABLE, (1 << r300->texture_count) - 1); + END_CS; +} + +static void r300_flush_pvs(struct r300_context* r300) +{ + CS_LOCALS(r300); + + BEGIN_CS(2); + OUT_CS_REG(R300_VAP_PVS_STATE_FLUSH_REG, 0x0); END_CS; } @@ -656,9 +985,17 @@ void r300_emit_dirty_state(struct r300_context* r300) return; } - r300_update_derived_state(r300); + /* Check size of CS. */ + /* Make sure we have at least 8*1024 spare dwords. */ + /* XXX It would be nice to know the number of dwords we really need to + * XXX emit. */ + if (!r300->winsys->check_cs(r300->winsys, 8*1024)) { + r300->context.flush(&r300->context, 0, NULL); + } + + /* Clean out BOs. */ + r300->winsys->reset_bos(r300->winsys); - /* XXX check size */ validate: /* Color buffers... */ for (i = 0; i < r300->framebuffer_state.nr_cbufs; i++) { @@ -683,7 +1020,8 @@ validate: /* ...textures... */ for (i = 0; i < r300->texture_count; i++) { tex = r300->textures[i]; - assert(tex && tex->buffer && "texture is marked, but NULL!"); + if (!tex) + continue; if (!r300->winsys->add_buffer(r300->winsys, tex->buffer, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0)) { r300->context.flush(&r300->context, 0, NULL); @@ -704,7 +1042,7 @@ validate: goto validate; } } else { - debug_printf("No VBO while emitting dirty state!\n"); + /* debug_printf("No VBO while emitting dirty state!\n"); */ } if (!r300->winsys->validate(r300->winsys)) { r300->context.flush(&r300->context, 0, NULL); @@ -717,6 +1055,11 @@ validate: goto validate; } + if (r300->dirty_state & R300_NEW_QUERY) { + r300_emit_query_start(r300); + r300->dirty_state &= ~R300_NEW_QUERY; + } + if (r300->dirty_state & R300_NEW_BLEND) { r300_emit_blend_state(r300, r300->blend_state); r300->dirty_state &= ~R300_NEW_BLEND; @@ -738,14 +1081,26 @@ validate: } if (r300->dirty_state & R300_NEW_FRAGMENT_SHADER) { + r300_emit_fragment_depth_config(r300, r300->fs); if (r300screen->caps->is_r500) { - r500_emit_fragment_program_code(r300, &r300->fs->code, &r300->shader_constants[PIPE_SHADER_FRAGMENT]); + r500_emit_fragment_program_code(r300, &r300->fs->shader->code); } else { - r300_emit_fragment_program_code(r300, &r300->fs->code, &r300->shader_constants[PIPE_SHADER_FRAGMENT]); + r300_emit_fragment_program_code(r300, &r300->fs->shader->code); } r300->dirty_state &= ~R300_NEW_FRAGMENT_SHADER; } + if (r300->dirty_state & R300_NEW_FRAGMENT_SHADER_CONSTANTS) { + if (r300screen->caps->is_r500) { + r500_emit_fs_constant_buffer(r300, + &r300->fs->shader->code.constants); + } else { + r300_emit_fs_constant_buffer(r300, + &r300->fs->shader->code.constants); + } + r300->dirty_state &= ~R300_NEW_FRAGMENT_SHADER_CONSTANTS; + } + if (r300->dirty_state & R300_NEW_FRAMEBUFFERS) { r300_emit_fb_state(r300, &r300->framebuffer_state); r300->dirty_state &= ~R300_NEW_FRAMEBUFFERS; @@ -769,13 +1124,16 @@ validate: /* Samplers and textures are tracked separately but emitted together. */ if (r300->dirty_state & (R300_ANY_NEW_SAMPLERS | R300_ANY_NEW_TEXTURES)) { + r300_emit_texture_count(r300); + for (i = 0; i < MIN2(r300->sampler_count, r300->texture_count); i++) { - if (r300->dirty_state & - ((R300_NEW_SAMPLER << i) | (R300_NEW_TEXTURE << i))) { - r300_emit_texture(r300, - r300->sampler_states[i], - r300->textures[i], - i); + if (r300->dirty_state & + ((R300_NEW_SAMPLER << i) | (R300_NEW_TEXTURE << i))) { + if (r300->textures[i]) + r300_emit_texture(r300, + r300->sampler_states[i], + r300->textures[i], + i); r300->dirty_state &= ~((R300_NEW_SAMPLER << i) | (R300_NEW_TEXTURE << i)); dirty_tex++; @@ -798,17 +1156,26 @@ validate: r300->dirty_state &= ~R300_NEW_VERTEX_FORMAT; } + if (r300->dirty_state & (R300_NEW_VERTEX_SHADER | R300_NEW_VERTEX_SHADER_CONSTANTS)) { + r300_flush_pvs(r300); + } + if (r300->dirty_state & R300_NEW_VERTEX_SHADER) { r300_emit_vertex_shader(r300, r300->vs); r300->dirty_state &= ~R300_NEW_VERTEX_SHADER; } + if (r300->dirty_state & R300_NEW_VERTEX_SHADER_CONSTANTS) { + r300_emit_vs_constant_buffer(r300, &r300->vs->code.constants); + r300->dirty_state &= ~R300_NEW_VERTEX_SHADER_CONSTANTS; + } + /* XXX assert(r300->dirty_state == 0); */ /* Finally, emit the VBO. */ - r300_emit_vertex_buffer(r300); + /* r300_emit_vertex_buffer(r300); */ r300->dirty_hw++; } diff --git a/src/gallium/drivers/r300/r300_emit.h b/src/gallium/drivers/r300/r300_emit.h index c4002b8e5d0..3797d3d332a 100644 --- a/src/gallium/drivers/r300/r300_emit.h +++ b/src/gallium/drivers/r300/r300_emit.h @@ -23,16 +23,14 @@ #ifndef R300_EMIT_H #define R300_EMIT_H -#include "util/u_math.h" - #include "r300_context.h" -#include "r300_cs.h" -#include "r300_screen.h" -#include "r300_state_inlines.h" +#include "radeon_code.h" struct rX00_fragment_program_code; struct r300_vertex_program_code; +void r300_emit_aos(struct r300_context* r300, unsigned offset); + void r300_emit_blend_state(struct r300_context* r300, struct r300_blend_state* blend); @@ -46,20 +44,24 @@ void r300_emit_dsa_state(struct r300_context* r300, struct r300_dsa_state* dsa); void r300_emit_fragment_program_code(struct r300_context* r300, - struct rX00_fragment_program_code* generic_code, - struct r300_constant_buffer* externals); + struct rX00_fragment_program_code* generic_code); + +void r300_emit_fs_constant_buffer(struct r300_context* r300, + struct rc_constant_list* constants); void r500_emit_fragment_program_code(struct r300_context* r300, - struct rX00_fragment_program_code* generic_code, - struct r300_constant_buffer* externals); + struct rX00_fragment_program_code* generic_code); + +void r500_emit_fs_constant_buffer(struct r300_context* r300, + struct rc_constant_list* constants); void r300_emit_fb_state(struct r300_context* r300, struct pipe_framebuffer_state* fb); void r300_emit_query_begin(struct r300_context* r300, struct r300_query* query); -void r300_emit_query_end(struct r300_context* r300, - struct r300_query* query); + +void r300_emit_query_end(struct r300_context* r300); void r300_emit_rs_state(struct r300_context* r300, struct r300_rs_state* rs); @@ -79,8 +81,10 @@ void r300_emit_vertex_buffer(struct r300_context* r300); void r300_emit_vertex_format_state(struct r300_context* r300); void r300_emit_vertex_program_code(struct r300_context* r300, - struct r300_vertex_program_code* code, - struct r300_constant_buffer* constants); + struct r300_vertex_program_code* code); + +void r300_emit_vs_constant_buffer(struct r300_context* r300, + struct rc_constant_list* constants); void r300_emit_vertex_shader(struct r300_context* r300, struct r300_vertex_shader* vs); @@ -88,6 +92,8 @@ void r300_emit_vertex_shader(struct r300_context* r300, void r300_emit_viewport_state(struct r300_context* r300, struct r300_viewport_state* viewport); +void r300_emit_texture_count(struct r300_context* r300); + void r300_flush_textures(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 0dff1c6f4fb..14a08241fc4 100644 --- a/src/gallium/drivers/r300/r300_flush.c +++ b/src/gallium/drivers/r300/r300_flush.c @@ -20,29 +20,48 @@ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE * USE OR OTHER DEALINGS IN THE SOFTWARE. */ +#include "draw/draw_context.h" +#include "draw/draw_private.h" + +#include "util/u_simple_list.h" + +#include "r300_context.h" +#include "r300_cs.h" +#include "r300_emit.h" #include "r300_flush.h" +#include "r300_state_invariant.h" static void r300_flush(struct pipe_context* pipe, unsigned flags, struct pipe_fence_handle** fence) { - struct r300_context* r300 = r300_context(pipe); - CS_LOCALS(r300); + struct r300_context *r300 = r300_context(pipe); + struct r300_query *query; + CS_LOCALS(r300); /* 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. */ - if (!r300->draw->flushing) { + * within Draw. This feels kludgy, but it might be the best thing. + * + * Of course, the best thing is to kill Draw with fire. :3 */ + if (r300->draw && !r300->draw->flushing) { draw_flush(r300->draw); } + r300_emit_query_end(r300); + if (r300->dirty_hw) { FLUSH_CS; r300_emit_invariant_state(r300); r300->dirty_state = R300_NEW_KITCHEN_SINK; r300->dirty_hw = 0; } + /* reset flushed query */ + foreach(query, &r300->query_list) { + query->flushed = TRUE; + } } + void r300_init_flush_functions(struct r300_context* r300) { r300->context.flush = r300_flush; diff --git a/src/gallium/drivers/r300/r300_flush.h b/src/gallium/drivers/r300/r300_flush.h index 9a83d89daab..0e9e6106bb7 100644 --- a/src/gallium/drivers/r300/r300_flush.h +++ b/src/gallium/drivers/r300/r300_flush.h @@ -23,13 +23,6 @@ #ifndef R300_FLUSH_H #define R300_FLUSH_H -#include "draw/draw_private.h" - -#include "pipe/p_context.h" - -#include "r300_context.h" -#include "r300_cs.h" - void r300_init_flush_functions(struct r300_context* r300); #endif /* R300_FLUSH_H */ diff --git a/src/gallium/drivers/r300/r300_fs.c b/src/gallium/drivers/r300/r300_fs.c index 546ad545a53..60ea9c171d5 100644 --- a/src/gallium/drivers/r300/r300_fs.c +++ b/src/gallium/drivers/r300/r300_fs.c @@ -1,6 +1,7 @@ /* * Copyright 2008 Corbin Simpson <[email protected]> * Joakim Sindholt <[email protected]> + * Copyright 2009 Marek Olšák <[email protected]> * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -21,12 +22,58 @@ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE * USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#include "r300_fs.h" +#include "util/u_math.h" +#include "util/u_memory.h" + +#include "tgsi/tgsi_dump.h" +#include "r300_context.h" +#include "r300_screen.h" +#include "r300_fs.h" #include "r300_tgsi_to_rc.h" +#include "radeon_code.h" #include "radeon_compiler.h" +/* Convert info about FS input semantics to r300_shader_semantics. */ +void r300_shader_read_fs_inputs(struct tgsi_shader_info* info, + struct r300_shader_semantics* fs_inputs) +{ + int i; + unsigned index; + + r300_shader_semantics_reset(fs_inputs); + + for (i = 0; i < info->num_inputs; i++) { + index = info->input_semantic_index[i]; + + switch (info->input_semantic_name[i]) { + case TGSI_SEMANTIC_COLOR: + assert(index <= ATTR_COLOR_COUNT); + fs_inputs->color[index] = i; + break; + + case TGSI_SEMANTIC_GENERIC: + assert(index <= ATTR_GENERIC_COUNT); + fs_inputs->generic[index] = i; + break; + + case TGSI_SEMANTIC_FOG: + assert(index == 0); + fs_inputs->fog = i; + break; + + case TGSI_SEMANTIC_POSITION: + assert(index == 0); + fs_inputs->wpos = i; + break; + + default: + assert(0); + } + } +} + static void find_output_registers(struct r300_fragment_program_compiler * compiler, struct r300_fragment_shader * fs) { @@ -54,61 +101,69 @@ static void allocate_hardware_inputs( void (*allocate)(void * data, unsigned input, unsigned hwreg), void * mydata) { - struct tgsi_shader_info* info = &((struct r300_fragment_shader*)c->UserData)->info; - int total_colors = 0; - int colors = 0; - int total_generic = 0; - int generic = 0; - int i; - - for (i = 0; i < info->num_inputs; i++) { - switch (info->input_semantic_name[i]) { - case TGSI_SEMANTIC_COLOR: - total_colors++; - break; - case TGSI_SEMANTIC_FOG: - case TGSI_SEMANTIC_GENERIC: - total_generic++; - break; + struct r300_shader_semantics* inputs = + (struct r300_shader_semantics*)c->UserData; + int i, reg = 0; + + /* Allocate input registers. */ + for (i = 0; i < ATTR_COLOR_COUNT; i++) { + if (inputs->color[i] != ATTR_UNUSED) { + allocate(mydata, inputs->color[i], reg++); + } + } + for (i = 0; i < ATTR_GENERIC_COUNT; i++) { + if (inputs->generic[i] != ATTR_UNUSED) { + allocate(mydata, inputs->generic[i], reg++); } } + if (inputs->fog != ATTR_UNUSED) { + allocate(mydata, inputs->fog, reg++); + } + if (inputs->wpos != ATTR_UNUSED) { + allocate(mydata, inputs->wpos, reg++); + } +} - for(i = 0; i < info->num_inputs; i++) { - switch (info->input_semantic_name[i]) { - case TGSI_SEMANTIC_COLOR: - allocate(mydata, i, colors); - colors++; - break; - case TGSI_SEMANTIC_FOG: - case TGSI_SEMANTIC_GENERIC: - allocate(mydata, i, total_colors + generic); - generic++; - break; +static void get_compare_state( + struct r300_context* r300, + struct r300_fragment_program_external_state* state, + unsigned shadow_samplers) +{ + memset(state, 0, sizeof(*state)); + + for (int i = 0; i < r300->sampler_count; i++) { + struct r300_sampler_state* s = r300->sampler_states[i]; + + if (s && s->state.compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) { + /* XXX Gallium doesn't provide us with any information regarding + * this mode, so we are screwed. I'm setting 0 = LUMINANCE. */ + state->unit[i].depth_texture_mode = 0; + + /* Fortunately, no need to translate this. */ + state->unit[i].texture_compare_func = s->state.compare_func; } } } -void r300_translate_fragment_shader(struct r300_context* r300, - struct r300_fragment_shader* fs) +static void r300_translate_fragment_shader( + struct r300_context* r300, + struct r300_fragment_shader_code* shader) { + struct r300_fragment_shader* fs = r300->fs; struct r300_fragment_program_compiler compiler; struct tgsi_to_rc ttr; + int wpos = fs->inputs.wpos; + /* Setup the compiler. */ memset(&compiler, 0, sizeof(compiler)); rc_init(&compiler.Base); compiler.Base.Debug = DBG_ON(r300, DBG_FP); - compiler.code = &fs->code; + compiler.code = &shader->code; + compiler.state = shader->compare_state; compiler.is_r500 = r300_screen(r300->context.screen)->caps->is_r500; compiler.AllocateHwInputs = &allocate_hardware_inputs; - compiler.UserData = fs; - - /* TODO: Program compilation depends on texture compare modes, - * which are sampler state. Therefore, programs need to be recompiled - * depending on this state as in the classic Mesa driver. - * - * This is not yet handled correctly. - */ + compiler.UserData = &fs->inputs; find_output_registers(&compiler, fs); @@ -123,20 +178,76 @@ void r300_translate_fragment_shader(struct r300_context* r300, r300_tgsi_to_rc(&ttr, fs->state.tokens); + fs->shadow_samplers = compiler.Base.Program.ShadowSamplers; + + /** + * Transform the program to support WPOS. + * + * Introduce a small fragment at the start of the program that will be + * the only code that directly reads the WPOS input. + * All other code pieces that reference that input will be rewritten + * to read from a newly allocated temporary. */ + if (wpos != ATTR_UNUSED) { + /* Moving the input to some other reg is not really necessary. */ + rc_transform_fragment_wpos(&compiler.Base, wpos, wpos, TRUE); + } + /* Invoke the compiler */ r3xx_compile_fragment_program(&compiler); if (compiler.Base.Error) { - /* Todo: Fallback to software rendering gracefully? */ - fprintf(stderr, "r300 FP: Compiler error: %s\n", compiler.Base.ErrorMsg); - - if (compiler.is_r500) { - memcpy(compiler.code, &r5xx_passthrough_fragment_shader, sizeof(r5xx_passthrough_fragment_shader)); - } else { - memcpy(compiler.code, &r3xx_passthrough_fragment_shader, sizeof(r3xx_passthrough_fragment_shader)); - } + /* XXX failover maybe? */ + DBG(r300, DBG_FP, "r300: Error compiling fragment program: %s\n", + compiler.Base.ErrorMsg); + assert(0); } /* And, finally... */ rc_destroy(&compiler.Base); - fs->translated = TRUE; +} + +boolean r300_pick_fragment_shader(struct r300_context* r300) +{ + struct r300_fragment_shader* fs = r300->fs; + struct r300_fragment_program_external_state state; + struct r300_fragment_shader_code* ptr; + + if (!fs->first) { + /* Build the fragment shader for the first time. */ + fs->first = fs->shader = CALLOC_STRUCT(r300_fragment_shader_code); + + /* BTW shadow samplers will be known after the first translation, + * therefore we set ~0, which means it should look at all sampler + * states. This choice doesn't have any impact on the correctness. */ + get_compare_state(r300, &fs->shader->compare_state, ~0); + r300_translate_fragment_shader(r300, fs->shader); + return TRUE; + + } else if (fs->shadow_samplers) { + get_compare_state(r300, &state, fs->shadow_samplers); + + /* Check if the currently-bound shader has been compiled + * with the texture-compare state we need. */ + if (memcmp(&fs->shader->compare_state, &state, sizeof(state)) != 0) { + /* Search for the right shader. */ + ptr = fs->first; + while (ptr) { + if (memcmp(&ptr->compare_state, &state, sizeof(state)) == 0) { + fs->shader = ptr; + return TRUE; + } + ptr = ptr->next; + } + + /* Not found, gotta compile a new one. */ + ptr = CALLOC_STRUCT(r300_fragment_shader_code); + ptr->next = fs->first; + fs->first = fs->shader = ptr; + + ptr->compare_state = state; + r300_translate_fragment_shader(r300, ptr); + return TRUE; + } + } + + return FALSE; } diff --git a/src/gallium/drivers/r300/r300_fs.h b/src/gallium/drivers/r300/r300_fs.h index 967e9f697e9..40ce874353c 100644 --- a/src/gallium/drivers/r300/r300_fs.h +++ b/src/gallium/drivers/r300/r300_fs.h @@ -1,6 +1,7 @@ /* * Copyright 2008 Corbin Simpson <[email protected]> * Joakim Sindholt <[email protected]> + * Copyright 2009 Marek Olšák <[email protected]> * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -24,28 +25,47 @@ #ifndef R300_FS_H #define R300_FS_H -#include "tgsi/tgsi_dump.h" +#include "pipe/p_state.h" +#include "tgsi/tgsi_scan.h" +#include "radeon_code.h" +#include "r300_shader_semantics.h" -#include "r300_context.h" -#include "r3xx_fs.h" -#include "r5xx_fs.h" +struct r300_fragment_shader_code { + struct r300_fragment_program_external_state compare_state; + struct rX00_fragment_program_code code; -#include "radeon_code.h" + struct r300_fragment_shader_code* next; +}; struct r300_fragment_shader { /* Parent class */ struct pipe_shader_state state; + struct tgsi_shader_info info; + struct r300_shader_semantics inputs; - /* Has this shader been translated yet? */ - boolean translated; + /* Bits 0-15: TRUE if it's a shadow sampler, FALSE otherwise. */ + unsigned shadow_samplers; - /* Compiled code */ - struct rX00_fragment_program_code code; + /* Currently-bound fragment shader. */ + struct r300_fragment_shader_code* shader; + + /* List of the same shaders compiled with different texture-compare + * states. */ + struct r300_fragment_shader_code* first; }; +void r300_shader_read_fs_inputs(struct tgsi_shader_info* info, + struct r300_shader_semantics* fs_inputs); + +/* Return TRUE if the shader was switched and should be re-emitted. */ +boolean r300_pick_fragment_shader(struct r300_context* r300); -void r300_translate_fragment_shader(struct r300_context* r300, - struct r300_fragment_shader* fs); +static INLINE boolean r300_fragment_shader_writes_depth(struct r300_fragment_shader *fs) +{ + if (!fs) + return FALSE; + return (fs->shader->code.writes_depth) ? TRUE : FALSE; +} #endif /* R300_FS_H */ diff --git a/src/gallium/drivers/r300/r300_query.c b/src/gallium/drivers/r300/r300_query.c index 2880d34877f..ca00b043c51 100644 --- a/src/gallium/drivers/r300/r300_query.c +++ b/src/gallium/drivers/r300/r300_query.c @@ -20,17 +20,23 @@ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE * USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#include "r300_query.h" +#include "util/u_memory.h" +#include "util/u_simple_list.h" +#include "r300_context.h" +#include "r300_screen.h" +#include "r300_cs.h" #include "r300_emit.h" +#include "r300_query.h" +#include "r300_reg.h" -static struct pipe_query* r300_create_query(struct pipe_context* pipe, +static struct pipe_query *r300_create_query(struct pipe_context *pipe, unsigned query_type) { - struct r300_context* r300 = r300_context(pipe); - struct r300_screen* r300screen = r300_screen(r300->context.screen); - unsigned query_size = r300screen->caps->num_frag_pipes * 4; - struct r300_query* q, * qptr; + struct r300_context *r300 = r300_context(pipe); + struct r300_screen *r300screen = r300_screen(r300->context.screen); + unsigned query_size; + struct r300_query *q, *qptr; q = CALLOC_STRUCT(r300_query); @@ -39,13 +45,16 @@ static struct pipe_query* r300_create_query(struct pipe_context* pipe, q->active = FALSE; - if (!r300->query_list) { - r300->query_list = q; - } else if (!is_empty_list(r300->query_list)) { - qptr = last_elem(r300->query_list); + if (r300screen->caps->family == CHIP_FAMILY_RV530) + query_size = r300screen->caps->num_z_pipes * sizeof(uint32_t); + else + query_size = r300screen->caps->num_frag_pipes * sizeof(uint32_t); + + 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); } + insert_at_tail(&r300->query_list, q); /* XXX */ if (q->offset >= 4096) { @@ -71,24 +80,26 @@ static void r300_begin_query(struct pipe_context* pipe, struct r300_context* r300 = r300_context(pipe); struct r300_query* q = (struct r300_query*)query; + assert(r300->query_current == NULL); + map = pipe->screen->buffer_map(pipe->screen, r300->oqbo, PIPE_BUFFER_USAGE_CPU_WRITE); map += q->offset / 4; - *map = ~0; + *map = ~0U; pipe->screen->buffer_unmap(pipe->screen, r300->oqbo); - r300_emit_dirty_state(r300); - r300_emit_query_begin(r300, q); + q->flushed = FALSE; + r300->query_current = q; + r300->dirty_state |= R300_NEW_QUERY; } static void r300_end_query(struct pipe_context* pipe, - struct pipe_query* query) + struct pipe_query* query) { struct r300_context* r300 = r300_context(pipe); - struct r300_query* q = (struct r300_query*)query; - r300_emit_dirty_state(r300); - r300_emit_query_end(r300, q); + r300_emit_query_end(r300); + r300->query_current = NULL; } static boolean r300_get_query_result(struct pipe_context* pipe, @@ -98,28 +109,36 @@ static boolean r300_get_query_result(struct pipe_context* pipe, { struct r300_context* r300 = r300_context(pipe); struct r300_screen* r300screen = r300_screen(r300->context.screen); - struct r300_query* q = (struct r300_query*)query; + struct r300_query *q = (struct r300_query*)query; unsigned flags = PIPE_BUFFER_USAGE_CPU_READ; uint32_t* map; - uint32_t temp; - unsigned i; + uint32_t temp = 0; + unsigned i, num_results; - if (wait) { + if (q->flushed == FALSE) pipe->flush(pipe, 0, NULL); - } else { + if (!wait) { flags |= PIPE_BUFFER_USAGE_DONTBLOCK; } map = pipe->screen->buffer_map(pipe->screen, r300->oqbo, flags); + if (!map) + return FALSE; map += q->offset / 4; - for (i = 0; i < r300screen->caps->num_frag_pipes; i++) { - if (*map == ~0) { + + 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) { debug_printf("r300: Despite waiting, OQ results haven't" " come in yet.\n"); } - temp = ~0; + temp = ~0U; break; } temp += *map; @@ -127,7 +146,7 @@ static boolean r300_get_query_result(struct pipe_context* pipe, } pipe->screen->buffer_unmap(pipe->screen, r300->oqbo); - if (temp == ~0) { + if (temp == ~0U) { /* Our results haven't been written yet... */ return FALSE; } diff --git a/src/gallium/drivers/r300/r300_query.h b/src/gallium/drivers/r300/r300_query.h index 4f50e8f8440..48876da3123 100644 --- a/src/gallium/drivers/r300/r300_query.h +++ b/src/gallium/drivers/r300/r300_query.h @@ -23,10 +23,6 @@ #ifndef R300_QUERY_H #define R300_QUERY_H -#include "r300_context.h" -#include "r300_cs.h" -#include "r300_reg.h" - struct r300_context; static INLINE struct r300_query* r300_query(struct pipe_query* q) diff --git a/src/gallium/drivers/r300/r300_reg.h b/src/gallium/drivers/r300/r300_reg.h index 3abff5db622..034bfc15cf9 100644 --- a/src/gallium/drivers/r300/r300_reg.h +++ b/src/gallium/drivers/r300/r300_reg.h @@ -348,6 +348,27 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. # define R300_WRITE_ENA_W 8 # define R300_SWIZZLE1_SHIFT 16 +# define R300_VAP_SWIZZLE_X001 \ + ((R300_SWIZZLE_SELECT_X << R300_SWIZZLE_SELECT_X_SHIFT) | \ + (R300_SWIZZLE_SELECT_FP_ZERO << R300_SWIZZLE_SELECT_Y_SHIFT) | \ + (R300_SWIZZLE_SELECT_FP_ZERO << R300_SWIZZLE_SELECT_Z_SHIFT) | \ + (R300_SWIZZLE_SELECT_FP_ONE << R300_SWIZZLE_SELECT_W_SHIFT) | \ + (0xf << R300_WRITE_ENA_SHIFT)) + +# define R300_VAP_SWIZZLE_XY01 \ + ((R300_SWIZZLE_SELECT_X << R300_SWIZZLE_SELECT_X_SHIFT) | \ + (R300_SWIZZLE_SELECT_Y << R300_SWIZZLE_SELECT_Y_SHIFT) | \ + (R300_SWIZZLE_SELECT_FP_ZERO << R300_SWIZZLE_SELECT_Z_SHIFT) | \ + (R300_SWIZZLE_SELECT_FP_ONE << R300_SWIZZLE_SELECT_W_SHIFT) | \ + (0xf << R300_WRITE_ENA_SHIFT)) + +# define R300_VAP_SWIZZLE_XYZ1 \ + ((R300_SWIZZLE_SELECT_X << R300_SWIZZLE_SELECT_X_SHIFT) | \ + (R300_SWIZZLE_SELECT_Y << R300_SWIZZLE_SELECT_Y_SHIFT) | \ + (R300_SWIZZLE_SELECT_Z << R300_SWIZZLE_SELECT_Z_SHIFT) | \ + (R300_SWIZZLE_SELECT_FP_ONE << R300_SWIZZLE_SELECT_W_SHIFT) | \ + (0xf << R300_WRITE_ENA_SHIFT)) + # define R300_VAP_SWIZZLE_XYZW \ ((R300_SWIZZLE_SELECT_X << R300_SWIZZLE_SELECT_X_SHIFT) | \ (R300_SWIZZLE_SELECT_Y << R300_SWIZZLE_SELECT_Y_SHIFT) | \ @@ -640,20 +661,20 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. # define R300_GB_SUPER_TILE_B (1 << 15) # define R300_GB_SUBPIXEL_1_12 (0 << 16) # define R300_GB_SUBPIXEL_1_16 (1 << 16) -# define GB_TILE_CONFIG_QUADS_PER_RAS_4 (0 << 17) -# define GB_TILE_CONFIG_QUADS_PER_RAS_8 (1 << 17) -# define GB_TILE_CONFIG_QUADS_PER_RAS_16 (2 << 17) -# define GB_TILE_CONFIG_QUADS_PER_RAS_32 (3 << 17) -# define GB_TILE_CONFIG_BB_SCAN_INTERCEPT (0 << 19) -# define GB_TILE_CONFIG_BB_SCAN_BOUND_BOX (1 << 19) -# define GB_TILE_CONFIG_ALT_SCAN_EN_LR (0 << 20) -# define GB_TILE_CONFIG_ALT_SCAN_EN_LRL (1 << 20) -# define GB_TILE_CONFIG_ALT_OFFSET (0 << 21) -# define GB_TILE_CONFIG_SUBPRECISION (0 << 22) -# define GB_TILE_CONFIG_ALT_TILING_DEF (0 << 23) -# define GB_TILE_CONFIG_ALT_TILING_3_2 (1 << 23) -# define GB_TILE_CONFIG_Z_EXTENDED_24_1 (0 << 24) -# define GB_TILE_CONFIG_Z_EXTENDED_S25_1 (1 << 24) +# define R300_GB_TILE_CONFIG_QUADS_PER_RAS_4 (0 << 17) +# define R300_GB_TILE_CONFIG_QUADS_PER_RAS_8 (1 << 17) +# define R300_GB_TILE_CONFIG_QUADS_PER_RAS_16 (2 << 17) +# define R300_GB_TILE_CONFIG_QUADS_PER_RAS_32 (3 << 17) +# define R300_GB_TILE_CONFIG_BB_SCAN_INTERCEPT (0 << 19) +# define R300_GB_TILE_CONFIG_BB_SCAN_BOUND_BOX (1 << 19) +# define R300_GB_TILE_CONFIG_ALT_SCAN_EN_LR (0 << 20) +# define R300_GB_TILE_CONFIG_ALT_SCAN_EN_LRL (1 << 20) +# define R300_GB_TILE_CONFIG_ALT_OFFSET (0 << 21) +# define R300_GB_TILE_CONFIG_SUBPRECISION (0 << 22) +# define R300_GB_TILE_CONFIG_ALT_TILING_DEF (0 << 23) +# define R300_GB_TILE_CONFIG_ALT_TILING_3_2 (1 << 23) +# define R300_GB_TILE_CONFIG_Z_EXTENDED_24_1 (0 << 24) +# define R300_GB_TILE_CONFIG_Z_EXTENDED_S25_1 (1 << 24) /* Specifies the sizes of the various FIFO`s in the sc/rs/us. This register must be the first one written */ #define R300_GB_FIFO_SIZE 0x4024 @@ -679,9 +700,9 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. # define R300_OFIFO_HIGHWATER_SHIFT 22 /* two bits only */ # define R300_CUBE_FIFO_HIGHWATER_COL_SHIFT 24 -#define GB_Z_PEQ_CONFIG 0x4028 -# define GB_Z_PEQ_CONFIG_Z_PEQ_SIZE_4_4 (0 << 0) -# define GB_Z_PEQ_CONFIG_Z_PEQ_SIZE_8_8 (1 << 0) +#define R300_GB_Z_PEQ_CONFIG 0x4028 +# define R300_GB_Z_PEQ_CONFIG_Z_PEQ_SIZE_4_4 (0 << 0) +# define R300_GB_Z_PEQ_CONFIG_Z_PEQ_SIZE_8_8 (1 << 0) /* Specifies various polygon specific selects (fog, depth, perspective). */ #define R300_GB_SELECT 0x401c @@ -704,39 +725,39 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. /* Specifies the graphics pipeline configuration for antialiasing. */ #define R300_GB_AA_CONFIG 0x4020 -# define GB_AA_CONFIG_AA_DISABLE (0 << 0) -# define GB_AA_CONFIG_AA_ENABLE (1 << 0) -# define GB_AA_CONFIG_NUM_AA_SUBSAMPLES_2 (0 << 1) -# define GB_AA_CONFIG_NUM_AA_SUBSAMPLES_3 (1 << 1) -# define GB_AA_CONFIG_NUM_AA_SUBSAMPLES_4 (2 << 1) -# define GB_AA_CONFIG_NUM_AA_SUBSAMPLES_6 (3 << 1) +# define R300_GB_AA_CONFIG_AA_DISABLE (0 << 0) +# define R300_GB_AA_CONFIG_AA_ENABLE (1 << 0) +# define R300_GB_AA_CONFIG_NUM_AA_SUBSAMPLES_2 (0 << 1) +# define R300_GB_AA_CONFIG_NUM_AA_SUBSAMPLES_3 (1 << 1) +# define R300_GB_AA_CONFIG_NUM_AA_SUBSAMPLES_4 (2 << 1) +# define R300_GB_AA_CONFIG_NUM_AA_SUBSAMPLES_6 (3 << 1) /* Selects which of 4 pipes are active. */ -#define GB_PIPE_SELECT 0x402c -# define GB_PIPE_SELECT_PIPE0_ID_SHIFT 0 -# define GB_PIPE_SELECT_PIPE1_ID_SHIFT 2 -# define GB_PIPE_SELECT_PIPE2_ID_SHIFT 4 -# define GB_PIPE_SELECT_PIPE3_ID_SHIFT 6 -# define GB_PIPE_SELECT_PIPE_MASK_SHIFT 8 -# define GB_PIPE_SELECT_MAX_PIPE 12 -# define GB_PIPE_SELECT_BAD_PIPES 14 -# define GB_PIPE_SELECT_CONFIG_PIPES 18 +#define R300_GB_PIPE_SELECT 0x402c +# define R300_GB_PIPE_SELECT_PIPE0_ID_SHIFT 0 +# define R300_GB_PIPE_SELECT_PIPE1_ID_SHIFT 2 +# define R300_GB_PIPE_SELECT_PIPE2_ID_SHIFT 4 +# define R300_GB_PIPE_SELECT_PIPE3_ID_SHIFT 6 +# define R300_GB_PIPE_SELECT_PIPE_MASK_SHIFT 8 +# define R300_GB_PIPE_SELECT_MAX_PIPE 12 +# define R300_GB_PIPE_SELECT_BAD_PIPES 14 +# define R300_GB_PIPE_SELECT_CONFIG_PIPES 18 /* Specifies the sizes of the various FIFO`s in the sc/rs. */ -#define GB_FIFO_SIZE1 0x4070 +#define R300_GB_FIFO_SIZE1 0x4070 /* High water mark for SC input fifo */ -# define GB_FIFO_SIZE1_SC_HIGHWATER_IFIFO_SHIFT 0 -# define GB_FIFO_SIZE1_SC_HIGHWATER_IFIFO_MASK 0x0000003f +# define R300_GB_FIFO_SIZE1_SC_HIGHWATER_IFIFO_SHIFT 0 +# define R300_GB_FIFO_SIZE1_SC_HIGHWATER_IFIFO_MASK 0x0000003f /* High water mark for SC input fifo (B) */ -# define GB_FIFO_SIZE1_SC_HIGHWATER_BFIFO_SHIFT 6 -# define GB_FIFO_SIZE1_SC_HIGHWATER_BFIFO_MASK 0x00000fc0 +# define R300_GB_FIFO_SIZE1_SC_HIGHWATER_BFIFO_SHIFT 6 +# define R300_GB_FIFO_SIZE1_SC_HIGHWATER_BFIFO_MASK 0x00000fc0 /* High water mark for RS colors' fifo */ -# define GB_FIFO_SIZE1_SC_HIGHWATER_COL_SHIFT 12 -# define GB_FIFO_SIZE1_SC_HIGHWATER_COL_MASK 0x0003f000 +# define R300_GB_FIFO_SIZE1_SC_HIGHWATER_COL_SHIFT 12 +# define R300_GB_FIFO_SIZE1_SC_HIGHWATER_COL_MASK 0x0003f000 /* High water mark for RS textures' fifo */ -# define GB_FIFO_SIZE1_SC_HIGHWATER_TEX_SHIFT 18 -# define GB_FIFO_SIZE1_SC_HIGHWATER_TEX_MASK 0x00fc0000 +# define R300_GB_FIFO_SIZE1_SC_HIGHWATER_TEX_SHIFT 18 +# define R300_GB_FIFO_SIZE1_SC_HIGHWATER_TEX_MASK 0x00fc0000 /* This table specifies the source location and format for up to 16 texture * addresses (i[0]:i[15]) and four colors (c[0]:c[3]) @@ -841,10 +862,10 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. # define R300_POINTSIZE_X_MASK 0xffff0000 # define R300_POINTSIZE_MAX (R300_POINTSIZE_Y_MASK / 6) -/* Blue fill color */ +/* Red fill color */ #define R500_GA_FILL_R 0x4220 -/* Blue fill color */ +/* Green fill color */ #define R500_GA_FILL_G 0x4224 /* Blue fill color */ @@ -1172,6 +1193,13 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. /* SU Depth Offset value */ #define R300_SU_DEPTH_OFFSET 0x42c4 +#define R300_SU_REG_DEST 0x42c8 +# define R300_RASTER_PIPE_SELECT_0 (1 << 0) +# define R300_RASTER_PIPE_SELECT_1 (1 << 1) +# define R300_RASTER_PIPE_SELECT_2 (1 << 2) +# define R300_RASTER_PIPE_SELECT_3 (1 << 3) +# define R300_RASTER_PIPE_SELECT_ALL 0xf + /* BEGIN: Rasterization / Interpolators - many guesses */ @@ -1265,7 +1293,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. # define R500_RS_INST_TEX_ID(x) ((x) << 0) #define R500_RS_INST_TEX_CN_WRITE (1 << 4) #define R500_RS_INST_TEX_ADDR_SHIFT 5 -# define R500_RS_INST_TEX_ADDR(x) ((x) << 0) +# define R500_RS_INST_TEX_ADDR(x) ((x) << 5) #define R500_RS_INST_COL_ID_SHIFT 12 # define R500_RS_INST_COL_ID(x) ((x) << 12) #define R500_RS_INST_COL_CN_NO_WRITE (0 << 16) @@ -1435,6 +1463,8 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. # define R300_TX_MIN_FILTER_MIP_NEAREST (1 << 13) # define R300_TX_MIN_FILTER_MIP_LINEAR (2 << 13) # define R300_TX_MIN_FILTER_MIP_MASK (3 << 13) +# define R300_TX_MAX_MIP_LEVEL_SHIFT 17 +# define R300_TX_MAX_MIP_LEVEL_MASK (0xf << 17) # define R300_TX_MAX_ANISO_1_TO_1 (0 << 21) # define R300_TX_MAX_ANISO_2_TO_1 (1 << 21) # define R300_TX_MAX_ANISO_4_TO_1 (2 << 21) @@ -1443,6 +1473,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. # define R300_TX_MAX_ANISO_MASK (7 << 21) # define R300_TX_WRAP_S(x) ((x) << 0) # define R300_TX_WRAP_T(x) ((x) << 3) +# define R300_TX_MAX_MIP_LEVEL(x) ((x) << 17) #define R300_TX_FILTER1_0 0x4440 # define R300_CHROMA_KEY_MODE_DISABLE 0 @@ -1472,8 +1503,6 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. # define R300_TX_HEIGHTMASK_MASK (2047 << 11) # define R300_TX_DEPTHMASK_SHIFT 22 # define R300_TX_DEPTHMASK_MASK (0xf << 22) -# define R300_TX_MAX_MIP_LEVEL_SHIFT 26 -# define R300_TX_MAX_MIP_LEVEL_MASK (0xf << 26) # define R300_TX_SIZE_PROJECTED (1 << 30) # define R300_TX_PITCH_EN (1 << 31) # define R300_TX_WIDTH(x) ((x) << 0) @@ -1856,6 +1885,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. # define R300_RGB_ADDR0(x) ((x) << 0) # define R300_RGB_ADDR1(x) ((x) << 6) # define R300_RGB_ADDR2(x) ((x) << 12) +# define R300_RGB_TARGET(x) ((x) << 29) #define R300_US_ALU_ALPHA_ADDR_0 0x47C0 # define R300_ALU_SRC0A_SHIFT 0 @@ -1873,9 +1903,10 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. # define R300_ALU_DSTA_REG (1 << 23) # define R300_ALU_DSTA_OUTPUT (1 << 24) # define R300_ALU_DSTA_DEPTH (1 << 27) -# define R300_ALPHA_ADDR0(x) ((x) << 0) -# define R300_ALPHA_ADDR1(x) ((x) << 6) -# define R300_ALPHA_ADDR2(x) ((x) << 12) +# define R300_ALPHA_ADDR0(x) ((x) << 0) +# define R300_ALPHA_ADDR1(x) ((x) << 6) +# define R300_ALPHA_ADDR2(x) ((x) << 12) +# define R300_ALPHA_TARGET(x) ((x) << 25) #define R300_US_ALU_RGB_INST_0 0x48C0 # define R300_ALU_ARGC_SRC0C_XYZ 0 @@ -2095,6 +2126,10 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #define R500_FG_ALPHA_VALUE 0x4be0 # define R500_FG_ALPHA_VALUE_MASK 0x0000ffff +#define RV530_FG_ZBREG_DEST 0x4be8 +# define RV530_FG_ZBREG_DEST_PIPE_SELECT_0 (1 << 0) +# define RV530_FG_ZBREG_DEST_PIPE_SELECT_1 (1 << 1) +# define RV530_FG_ZBREG_DEST_PIPE_SELECT_ALL (3 << 0) /* gap */ /* Fragment program parameters in 7.16 floating point */ @@ -2110,6 +2145,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. /* Unpipelined. */ #define R300_RB3D_CCTL 0x4e00 +# define R300_RB3D_CCTL_NUM_MULTIWRITES(x) (MAX2(((x)-1), 0) << 5) # define R300_RB3D_CCTL_NUM_MULTIWRITES_1_BUFFER (0 << 5) # define R300_RB3D_CCTL_NUM_MULTIWRITES_2_BUFFERS (1 << 5) # define R300_RB3D_CCTL_NUM_MULTIWRITES_3_BUFFERS (2 << 5) @@ -2150,6 +2186,8 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. # define R300_DISCARD_SRC_PIXELS_SRC_ALPHA_1 (4 << 3) # define R300_DISCARD_SRC_PIXELS_SRC_COLOR_1 (5 << 3) # define R300_DISCARD_SRC_PIXELS_SRC_ALPHA_COLOR_1 (6 << 3) +# define R500_SRC_ALPHA_0_NO_READ (1 << 30) +# define R500_SRC_ALPHA_1_NO_READ (1 << 31) /* the following are shared between CBLEND and ABLEND */ # define R300_FCN_MASK (3 << 12) @@ -2384,6 +2422,8 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. # define R300_Z_WRITE_ENABLE (1 << 2) # define R300_Z_SIGNED_COMPARE (1 << 3) # define R300_STENCIL_FRONT_BACK (1 << 4) +# define R500_STENCIL_ZSIGNED_MAGNITUDE (1 << 5) +# define R500_STENCIL_REFMASK_FRONT_BACK (1 << 6) #define R300_ZB_ZSTENCILCNTL 0x4f04 /* functions */ @@ -2600,7 +2640,7 @@ enum { VE_COND_MUX_GTE = 25, VE_SET_GREATER_THAN = 26, VE_SET_EQUAL = 27, - VE_SET_NOT_EQUAL = 28, + VE_SET_NOT_EQUAL = 28 }; enum { @@ -2634,20 +2674,20 @@ enum { ME_PRED_SET_CLR = 25, ME_PRED_SET_INV = 26, ME_PRED_SET_POP = 27, - ME_PRED_SET_RESTORE = 28, + ME_PRED_SET_RESTORE = 28 }; enum { /* R3XX */ PVS_MACRO_OP_2CLK_MADD = 0, - PVS_MACRO_OP_2CLK_M2X_ADD = 1, + PVS_MACRO_OP_2CLK_M2X_ADD = 1 }; enum { PVS_SRC_REG_TEMPORARY = 0, /* Intermediate Storage */ PVS_SRC_REG_INPUT = 1, /* Input Vertex Storage */ PVS_SRC_REG_CONSTANT = 2, /* Constant State Storage */ - PVS_SRC_REG_ALT_TEMPORARY = 3, /* Alternate Intermediate Storage */ + PVS_SRC_REG_ALT_TEMPORARY = 3 /* Alternate Intermediate Storage */ }; enum { @@ -2656,7 +2696,7 @@ enum { PVS_DST_REG_OUT = 2, /* Output Memory. Used for all outputs */ PVS_DST_REG_OUT_REPL_X = 3, /* Output Memory & Replicate X to all channels */ PVS_DST_REG_ALT_TEMPORARY = 4, /* Alternate Intermediate Storage */ - PVS_DST_REG_INPUT = 5, /* Output Memory & Replicate X to all channels */ + PVS_DST_REG_INPUT = 5 /* Output Memory & Replicate X to all channels */ }; enum { @@ -2665,7 +2705,7 @@ enum { PVS_SRC_SELECT_Z = 2, /* Select Z Component */ PVS_SRC_SELECT_W = 3, /* Select W Component */ PVS_SRC_SELECT_FORCE_0 = 4, /* Force Component to 0.0 */ - PVS_SRC_SELECT_FORCE_1 = 5, /* Force Component to 1.0 */ + PVS_SRC_SELECT_FORCE_1 = 5 /* Force Component to 1.0 */ }; /* PVS Opcode & Destination Operand Description */ @@ -2704,7 +2744,7 @@ enum { PVS_DST_ADDR_SEL_MASK = 0x3, PVS_DST_ADDR_SEL_SHIFT = 29, PVS_DST_ADDR_MODE_0_MASK = 0x1, - PVS_DST_ADDR_MODE_0_SHIFT = 31, + PVS_DST_ADDR_MODE_0_SHIFT = 31 }; /* PVS Source Operand Description */ @@ -2739,7 +2779,7 @@ enum { PVS_SRC_ADDR_SEL_MASK = 0x3, PVS_SRC_ADDR_SEL_SHIFT = 29, PVS_SRC_ADDR_MODE_1_MASK = 0x0, - PVS_SRC_ADDR_MODE_1_SHIFT = 32, + PVS_SRC_ADDR_MODE_1_SHIFT = 32 }; /*\}*/ @@ -3256,6 +3296,11 @@ enum { */ #define R300_PACKET3_3D_LOAD_VBPNTR 0x00002F00 +# define R300_VBPNTR_SIZE0(x) ((x) >> 2) +# define R300_VBPNTR_STRIDE0(x) (((x) >> 2) << 8) +# define R300_VBPNTR_SIZE1(x) (((x) >> 2) << 16) +# define R300_VBPNTR_STRIDE1(x) (((x) >> 2) << 24) + #define R300_PACKET3_INDX_BUFFER 0x00003300 # define R300_INDX_BUFFER_DST_SHIFT 0 # define R300_INDX_BUFFER_SKIP_SHIFT 16 @@ -3313,10 +3358,6 @@ enum { #define R200_3D_DRAW_IMMD_2 0xC0003500 -/* XXX Oh look, stuff not brought over from docs yet */ - -#define R300_SU_REG_DEST 0x42C8 - #endif /* _R300_REG_H */ /* *INDENT-ON* */ diff --git a/src/gallium/drivers/r300/r300_render.c b/src/gallium/drivers/r300/r300_render.c index ca44e0f6615..a4ac9ad9a7b 100644 --- a/src/gallium/drivers/r300/r300_render.c +++ b/src/gallium/drivers/r300/r300_render.c @@ -20,19 +20,389 @@ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE * USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#include "draw/draw_pipe.h" +/* r300_render: Vertex and index buffer primitive emission. Contains both + * HW TCL fastpath rendering, and SW TCL Draw-assisted rendering. */ + +#include "draw/draw_context.h" #include "draw/draw_vbuf.h" + +#include "pipe/p_inlines.h" + #include "util/u_memory.h" +#include "util/u_prim.h" #include "r300_cs.h" #include "r300_context.h" #include "r300_emit.h" #include "r300_reg.h" +#include "r300_render.h" #include "r300_state_derived.h" /* r300_render: Vertex and index buffer primitive emission. */ #define R300_MAX_VBO_SIZE (1024 * 1024) +uint32_t r300_translate_primitive(unsigned prim) +{ + switch (prim) { + case PIPE_PRIM_POINTS: + return R300_VAP_VF_CNTL__PRIM_POINTS; + case PIPE_PRIM_LINES: + return R300_VAP_VF_CNTL__PRIM_LINES; + case PIPE_PRIM_LINE_LOOP: + return R300_VAP_VF_CNTL__PRIM_LINE_LOOP; + case PIPE_PRIM_LINE_STRIP: + return R300_VAP_VF_CNTL__PRIM_LINE_STRIP; + case PIPE_PRIM_TRIANGLES: + return R300_VAP_VF_CNTL__PRIM_TRIANGLES; + case PIPE_PRIM_TRIANGLE_STRIP: + return R300_VAP_VF_CNTL__PRIM_TRIANGLE_STRIP; + case PIPE_PRIM_TRIANGLE_FAN: + return R300_VAP_VF_CNTL__PRIM_TRIANGLE_FAN; + case PIPE_PRIM_QUADS: + return R300_VAP_VF_CNTL__PRIM_QUADS; + case PIPE_PRIM_QUAD_STRIP: + return R300_VAP_VF_CNTL__PRIM_QUAD_STRIP; + case PIPE_PRIM_POLYGON: + return R300_VAP_VF_CNTL__PRIM_POLYGON; + default: + return 0; + } +} + +static boolean r300_nothing_to_draw(struct r300_context *r300) +{ + return r300->rs_state->rs.scissor && + r300->scissor_state->scissor.empty_area; +} + +static uint32_t r300_provoking_vertex_fixes(struct r300_context *r300, + unsigned mode) +{ + uint32_t color_control = r300->rs_state->color_control; + + /* By default (see r300_state.c:r300_create_rs_state) color_control is + * initialized to provoking the first vertex. + * + * Triangle fans must be reduced to the second vertex, not the first, in + * Gallium flatshade-first mode, as per the GL spec. + * (http://www.opengl.org/registry/specs/ARB/provoking_vertex.txt) + * + * Quads never provoke correctly in flatshade-first mode. The first + * vertex is never considered as provoking, so only the second, third, + * and fourth vertices can be selected, and both "third" and "last" modes + * select the fourth vertex. This is probably due to D3D lacking quads. + * + * Similarly, polygons reduce to the first, not the last, vertex, when in + * "last" mode, and all other modes start from the second vertex. + * + * ~ C. + */ + + if (r300->rs_state->rs.flatshade_first) { + switch (mode) { + case PIPE_PRIM_TRIANGLE_FAN: + color_control |= R300_GA_COLOR_CONTROL_PROVOKING_VERTEX_SECOND; + break; + case PIPE_PRIM_QUADS: + case PIPE_PRIM_QUAD_STRIP: + case PIPE_PRIM_POLYGON: + color_control |= R300_GA_COLOR_CONTROL_PROVOKING_VERTEX_LAST; + break; + default: + color_control |= R300_GA_COLOR_CONTROL_PROVOKING_VERTEX_FIRST; + break; + } + } else { + color_control |= R300_GA_COLOR_CONTROL_PROVOKING_VERTEX_LAST; + } + + return color_control; +} + +static void r300_emit_draw_arrays(struct r300_context *r300, + unsigned mode, + unsigned count) +{ + CS_LOCALS(r300); + + BEGIN_CS(8); + OUT_CS_REG(R300_GA_COLOR_CONTROL, + r300_provoking_vertex_fixes(r300, mode)); + OUT_CS_REG(R300_VAP_VF_MIN_VTX_INDX, 0); + OUT_CS_REG(R300_VAP_VF_MAX_VTX_INDX, count - 1); + OUT_CS_PKT3(R300_PACKET3_3D_DRAW_VBUF_2, 0); + OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_LIST | (count << 16) | + r300_translate_primitive(mode)); + END_CS; +} + +static void r300_emit_draw_elements(struct r300_context *r300, + struct pipe_buffer* indexBuffer, + unsigned indexSize, + unsigned minIndex, + unsigned maxIndex, + unsigned mode, + unsigned start, + unsigned count) +{ + uint32_t count_dwords; + uint32_t offset_dwords = indexSize * start / sizeof(uint32_t); + CS_LOCALS(r300); + + /* XXX most of these are stupid */ + assert(indexSize == 4 || indexSize == 2); + assert((start * indexSize) % 4 == 0); + assert(offset_dwords == 0); + + BEGIN_CS(14); + OUT_CS_REG(R300_GA_COLOR_CONTROL, + r300_provoking_vertex_fixes(r300, mode)); + OUT_CS_REG(R300_VAP_VF_MIN_VTX_INDX, minIndex); + OUT_CS_REG(R300_VAP_VF_MAX_VTX_INDX, maxIndex); + OUT_CS_PKT3(R300_PACKET3_3D_DRAW_INDX_2, 0); + if (indexSize == 4) { + count_dwords = count + start; + OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (count << 16) | + R300_VAP_VF_CNTL__INDEX_SIZE_32bit | + r300_translate_primitive(mode)); + } else { + count_dwords = (count + start + 1) / 2; + OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (count << 16) | + r300_translate_primitive(mode)); + } + + /* INDX_BUFFER is a truly special packet3. + * Unlike most other packet3, where the offset is after the count, + * the order is reversed, so the relocation ends up carrying the + * size of the indexbuf instead of the offset. + * + * XXX Fix offset + */ + OUT_CS_PKT3(R300_PACKET3_INDX_BUFFER, 2); + OUT_CS(R300_INDX_BUFFER_ONE_REG_WR | (R300_VAP_PORT_IDX0 >> 2) | + (0 << R300_INDX_BUFFER_SKIP_SHIFT)); + OUT_CS(offset_dwords); + OUT_CS_RELOC(indexBuffer, count_dwords, + RADEON_GEM_DOMAIN_GTT, 0, 0); + + END_CS; +} + + +static boolean r300_setup_vertex_buffers(struct r300_context *r300) +{ + struct pipe_vertex_buffer *vbuf = r300->vertex_buffer; + struct pipe_vertex_element *velem = r300->vertex_element; + +validate: + for (int i = 0; i < r300->vertex_element_count; i++) { + if (!r300->winsys->add_buffer(r300->winsys, + vbuf[velem[i].vertex_buffer_index].buffer, + RADEON_GEM_DOMAIN_GTT, 0)) { + r300->context.flush(&r300->context, 0, NULL); + goto validate; + } + } + + if (!r300->winsys->validate(r300->winsys)) { + r300->context.flush(&r300->context, 0, NULL); + return r300->winsys->validate(r300->winsys); + } + + return TRUE; +} + +/* This is the fast-path drawing & emission for HW TCL. */ +void r300_draw_range_elements(struct pipe_context* pipe, + struct pipe_buffer* indexBuffer, + unsigned indexSize, + unsigned minIndex, + unsigned maxIndex, + unsigned mode, + unsigned start, + unsigned count) +{ + struct r300_context* r300 = r300_context(pipe); + + if (!u_trim_pipe_prim(mode, &count)) { + return; + } + + if (count > 65535) { + /* XXX: use aux/indices functions to split this into smaller + * primitives. + */ + return; + } + + if (r300_nothing_to_draw(r300)) { + return; + } + + r300_update_derived_state(r300); + + if (!r300_setup_vertex_buffers(r300)) { + return; + } + + if (!r300->winsys->add_buffer(r300->winsys, indexBuffer, + RADEON_GEM_DOMAIN_GTT, 0)) { + return; + } + + if (!r300->winsys->validate(r300->winsys)) { + return; + } + + r300_emit_dirty_state(r300); + + r300_emit_aos(r300, 0); + + r300_emit_draw_elements(r300, indexBuffer, indexSize, minIndex, maxIndex, + mode, start, count); +} + +/* Simple helpers for context setup. Should probably be moved to util. */ +void r300_draw_elements(struct pipe_context* pipe, + struct pipe_buffer* indexBuffer, + unsigned indexSize, unsigned mode, + unsigned start, unsigned count) +{ + pipe->draw_range_elements(pipe, indexBuffer, indexSize, 0, ~0, + mode, start, count); +} + +void r300_draw_arrays(struct pipe_context* pipe, unsigned mode, + unsigned start, unsigned count) +{ + struct r300_context* r300 = r300_context(pipe); + + if (!u_trim_pipe_prim(mode, &count)) { + return; + } + + if (count > 65535) { + /* XXX: driver needs to handle this -- use the functions in + * aux/indices to split this into several smaller primitives. + */ + return; + } + + if (r300_nothing_to_draw(r300)) { + return; + } + + r300_update_derived_state(r300); + + if (!r300_setup_vertex_buffers(r300)) { + return; + } + + r300_emit_dirty_state(r300); + + r300_emit_aos(r300, start); + + r300_emit_draw_arrays(r300, mode, count); +} + +/**************************************************************************** + * The rest of this file is for SW TCL rendering only. Please be polite and * + * keep these functions separated so that they are easier to locate. ~C. * + ***************************************************************************/ + +/* SW TCL arrays, using Draw. */ +void r300_swtcl_draw_arrays(struct pipe_context* pipe, + unsigned mode, + unsigned start, + unsigned count) +{ + struct r300_context* r300 = r300_context(pipe); + int i; + + if (!u_trim_pipe_prim(mode, &count)) { + return; + } + + if (r300_nothing_to_draw(r300)) { + return; + } + + for (i = 0; i < r300->vertex_buffer_count; i++) { + void* buf = pipe_buffer_map(pipe->screen, + r300->vertex_buffer[i].buffer, + PIPE_BUFFER_USAGE_CPU_READ); + draw_set_mapped_vertex_buffer(r300->draw, i, buf); + } + + draw_set_mapped_element_buffer(r300->draw, 0, NULL); + + draw_set_mapped_constant_buffer(r300->draw, + PIPE_SHADER_VERTEX, + r300->shader_constants[PIPE_SHADER_VERTEX].constants, + r300->shader_constants[PIPE_SHADER_VERTEX].count * + (sizeof(float) * 4)); + + draw_arrays(r300->draw, mode, start, count); + + for (i = 0; i < r300->vertex_buffer_count; i++) { + pipe_buffer_unmap(pipe->screen, r300->vertex_buffer[i].buffer); + draw_set_mapped_vertex_buffer(r300->draw, i, NULL); + } +} + +/* SW TCL elements, using Draw. */ +void r300_swtcl_draw_range_elements(struct pipe_context* pipe, + struct pipe_buffer* indexBuffer, + unsigned indexSize, + unsigned minIndex, + unsigned maxIndex, + unsigned mode, + unsigned start, + unsigned count) +{ + struct r300_context* r300 = r300_context(pipe); + int i; + void* indices; + + if (!u_trim_pipe_prim(mode, &count)) { + return; + } + + if (r300_nothing_to_draw(r300)) { + return; + } + + for (i = 0; i < r300->vertex_buffer_count; i++) { + void* buf = pipe_buffer_map(pipe->screen, + r300->vertex_buffer[i].buffer, + PIPE_BUFFER_USAGE_CPU_READ); + draw_set_mapped_vertex_buffer(r300->draw, i, buf); + } + + indices = pipe_buffer_map(pipe->screen, indexBuffer, + PIPE_BUFFER_USAGE_CPU_READ); + draw_set_mapped_element_buffer_range(r300->draw, indexSize, + minIndex, maxIndex, indices); + + draw_set_mapped_constant_buffer(r300->draw, + PIPE_SHADER_VERTEX, + r300->shader_constants[PIPE_SHADER_VERTEX].constants, + r300->shader_constants[PIPE_SHADER_VERTEX].count * + (sizeof(float) * 4)); + + draw_arrays(r300->draw, mode, start, count); + + for (i = 0; i < r300->vertex_buffer_count; i++) { + pipe_buffer_unmap(pipe->screen, r300->vertex_buffer[i].buffer); + draw_set_mapped_vertex_buffer(r300->draw, i, NULL); + } + + pipe_buffer_unmap(pipe->screen, indexBuffer); + draw_set_mapped_element_buffer_range(r300->draw, 0, start, + start + count - 1, NULL); +} + +/* Object for rendering using Draw. */ struct r300_render { /* Parent class */ struct vbuf_render base; @@ -67,7 +437,7 @@ r300_render_get_vertex_info(struct vbuf_render* render) r300_update_derived_state(r300); - return &r300->vertex_info.vinfo; + return &r300->vertex_info->vinfo; } static boolean r300_render_allocate_vertices(struct vbuf_render* render, @@ -105,7 +475,7 @@ static void* r300_render_map_vertices(struct vbuf_render* render) r300render->vbo_ptr = pipe_buffer_map(screen, r300render->vbo, PIPE_BUFFER_USAGE_CPU_WRITE); - return (r300render->vbo_ptr + r300render->vbo_offset); + return ((uint8_t*)r300render->vbo_ptr + r300render->vbo_offset); } static void r300_render_unmap_vertices(struct vbuf_render* render, @@ -127,7 +497,6 @@ static void r300_render_unmap_vertices(struct vbuf_render* render, static void r300_render_release_vertices(struct vbuf_render* render) { struct r300_render* r300render = r300_render(render); - struct r300_context* r300 = r300render->r300; r300render->vbo_offset += r300render->vbo_max_used; r300render->vbo_max_used = 0; @@ -137,56 +506,13 @@ static boolean r300_render_set_primitive(struct vbuf_render* render, unsigned prim) { struct r300_render* r300render = r300_render(render); - r300render->prim = prim; - switch (prim) { - case PIPE_PRIM_POINTS: - r300render->hwprim = R300_VAP_VF_CNTL__PRIM_POINTS; - break; - case PIPE_PRIM_LINES: - r300render->hwprim = R300_VAP_VF_CNTL__PRIM_LINES; - break; - case PIPE_PRIM_LINE_LOOP: - r300render->hwprim = R300_VAP_VF_CNTL__PRIM_LINE_LOOP; - break; - case PIPE_PRIM_LINE_STRIP: - r300render->hwprim = R300_VAP_VF_CNTL__PRIM_LINE_STRIP; - break; - case PIPE_PRIM_TRIANGLES: - r300render->hwprim = R300_VAP_VF_CNTL__PRIM_TRIANGLES; - break; - case PIPE_PRIM_TRIANGLE_STRIP: - r300render->hwprim = R300_VAP_VF_CNTL__PRIM_TRIANGLE_STRIP; - break; - case PIPE_PRIM_TRIANGLE_FAN: - r300render->hwprim = R300_VAP_VF_CNTL__PRIM_TRIANGLE_FAN; - break; - case PIPE_PRIM_QUADS: - r300render->hwprim = R300_VAP_VF_CNTL__PRIM_QUADS; - break; - case PIPE_PRIM_QUAD_STRIP: - r300render->hwprim = R300_VAP_VF_CNTL__PRIM_QUAD_STRIP; - break; - case PIPE_PRIM_POLYGON: - r300render->hwprim = R300_VAP_VF_CNTL__PRIM_POLYGON; - break; - default: - return FALSE; - break; - } + r300render->prim = prim; + r300render->hwprim = r300_translate_primitive(prim); return TRUE; } -static void r300_prepare_render(struct r300_render* render, unsigned count) -{ - struct r300_context* r300 = render->r300; - - CS_LOCALS(r300); - - r300_emit_dirty_state(r300); -} - static void r300_render_draw_arrays(struct vbuf_render* render, unsigned start, unsigned count) @@ -196,7 +522,7 @@ static void r300_render_draw_arrays(struct vbuf_render* render, CS_LOCALS(r300); - r300_prepare_render(r300render, count); + r300_emit_dirty_state(r300); DBG(r300, DBG_DRAW, "r300: Doing vbuf render, count %d\n", count); @@ -213,15 +539,11 @@ static void r300_render_draw(struct vbuf_render* render, { struct r300_render* r300render = r300_render(render); struct r300_context* r300 = r300render->r300; - struct pipe_screen* screen = r300->context.screen; - struct pipe_buffer* index_buffer; - void* index_map; int i; - uint32_t index; CS_LOCALS(r300); - r300_prepare_render(r300render, count); + r300_emit_dirty_state(r300); BEGIN_CS(2 + (count+1)/2); OUT_CS_PKT3(R300_PACKET3_3D_DRAW_INDX_2, (count+1)/2); diff --git a/src/gallium/drivers/r300/r300_render.h b/src/gallium/drivers/r300/r300_render.h new file mode 100644 index 00000000000..27b5e6a9630 --- /dev/null +++ b/src/gallium/drivers/r300/r300_render.h @@ -0,0 +1,59 @@ +/* + * Copyright 2009 Corbin Simpson <[email protected]> + * + * 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_RENDER_H +#define R300_RENDER_H + +uint32_t r300_translate_primitive(unsigned prim); + +void r300_draw_range_elements(struct pipe_context* pipe, + struct pipe_buffer* indexBuffer, + unsigned indexSize, + unsigned minIndex, + unsigned maxIndex, + unsigned mode, + unsigned start, + unsigned count); + +void r300_draw_elements(struct pipe_context* pipe, + struct pipe_buffer* indexBuffer, + unsigned indexSize, unsigned mode, + unsigned start, unsigned count); + +void r300_draw_arrays(struct pipe_context* pipe, unsigned mode, + unsigned start, unsigned count); + +void r300_swtcl_draw_arrays(struct pipe_context* pipe, + unsigned mode, + unsigned start, + unsigned count); + +void r300_swtcl_draw_range_elements(struct pipe_context* pipe, + struct pipe_buffer* indexBuffer, + unsigned indexSize, + unsigned minIndex, + unsigned maxIndex, + unsigned mode, + unsigned start, + unsigned count); + +#endif /* R300_RENDER_H */ diff --git a/src/gallium/drivers/r300/r300_screen.c b/src/gallium/drivers/r300/r300_screen.c index 81d01b1320c..287664b1d20 100644 --- a/src/gallium/drivers/r300/r300_screen.c +++ b/src/gallium/drivers/r300/r300_screen.c @@ -20,7 +20,16 @@ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE * USE OR OTHER DEALINGS IN THE SOFTWARE. */ +#include "pipe/p_inlines.h" +#include "util/u_format.h" +#include "util/u_memory.h" +#include "util/u_simple_screen.h" + +#include "r300_context.h" #include "r300_screen.h" +#include "r300_texture.h" + +#include "radeon_winsys.h" /* Return the identifier behind whom the brave coders responsible for this * amalgamation of code, sweat, and duct tape, routinely obscure their names. @@ -73,14 +82,14 @@ static int r300_get_param(struct pipe_screen* pscreen, int param) struct r300_screen* r300screen = r300_screen(pscreen); switch (param) { - /* XXX cases marked "IN THEORY" are possible on the hardware, - * but haven't been implemented yet. */ case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS: + case PIPE_CAP_MAX_COMBINED_SAMPLERS: /* XXX I'm told this goes up to 16 */ return 8; case PIPE_CAP_NPOT_TEXTURES: - /* IN THEORY */ - return 0; + /* XXX enable now to get GL2.1 API, + * figure out later how to emulate this */ + return 1; case PIPE_CAP_TWO_SIDED_STENCIL: if (r300screen->caps->is_r500) { return 1; @@ -88,16 +97,26 @@ static int r300_get_param(struct pipe_screen* pscreen, int param) return 0; } case PIPE_CAP_GLSL: - if (r300screen->caps->is_r500) { - return 1; - } else { - return 0; - } + /* I'll be frank. This is a lie. + * + * We don't truly support GLSL on any of this driver's chipsets. + * To be fair, no chipset supports the full GLSL specification + * to the best of our knowledge, but some of the less esoteric + * features are still missing here. + * + * Rather than cripple ourselves intentionally, I'm going to set + * this flag, and as Gallium's interface continues to change, I + * hope that this single monolithic GLSL enable can slowly get + * split down into many different pieces and the state tracker + * will handle fallbacks transparently, like it should. + * + * ~ C. + */ + return 1; case PIPE_CAP_ANISOTROPIC_FILTER: return 1; case PIPE_CAP_POINT_SPRITE: - /* IN THEORY */ - return 0; + return 1; case PIPE_CAP_MAX_RENDER_TARGETS: return 4; case PIPE_CAP_OCCLUSION_QUERY: @@ -105,32 +124,13 @@ static int r300_get_param(struct pipe_screen* pscreen, int param) case PIPE_CAP_TEXTURE_SHADOW_MAP: return 1; case PIPE_CAP_MAX_TEXTURE_2D_LEVELS: - if (r300screen->caps->is_r500) { - /* 13 == 4096x4096 */ - return 13; - } else { - /* 12 == 2048x2048 */ - return 12; - } case PIPE_CAP_MAX_TEXTURE_3D_LEVELS: - /* So, technically, the limit is the same as above, but some math - * shows why this is silly. Assuming RGBA, 4cpp, we can see that - * 4096*4096*4096 = 64.0 GiB exactly, so it's not exactly - * practical. However, if at some point a game really wants this, - * then we can remove or raise this limit. */ - if (r300screen->caps->is_r500) { - /* 9 == 256x256x256 */ - return 9; - } else { - /* 8 == 128*128*128 */ - return 8; - } case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS: if (r300screen->caps->is_r500) { - /* 13 == 4096x4096 */ + /* 13 == 4096 */ return 13; } else { - /* 12 == 2048x2048 */ + /* 12 == 2048 */ return 12; } case PIPE_CAP_TEXTURE_MIRROR_CLAMP: @@ -138,13 +138,17 @@ static int r300_get_param(struct pipe_screen* pscreen, int param) case PIPE_CAP_TEXTURE_MIRROR_REPEAT: return 1; case PIPE_CAP_MAX_VERTEX_TEXTURE_UNITS: - /* XXX guessing (what a terrible guess) */ - return 2; + return 0; case PIPE_CAP_TGSI_CONT_SUPPORTED: - /* XXX */ return 0; case PIPE_CAP_BLEND_EQUATION_SEPARATE: return 1; + case PIPE_CAP_SM3: + if (r300screen->caps->is_r500) { + return 1; + } else { + return 0; + } default: debug_printf("r300: Implementation error: Bad param %d\n", param); @@ -179,19 +183,22 @@ static float r300_get_paramf(struct pipe_screen* pscreen, int param) } } -static boolean check_tex_2d_format(enum pipe_format format, uint32_t usage, - boolean is_r500) +static boolean check_tex_format(enum pipe_format format, uint32_t usage, + boolean is_r500) { + uint32_t retval = 0; + switch (format) { /* Supported formats. */ /* Colorbuffer */ case PIPE_FORMAT_A4R4G4B4_UNORM: case PIPE_FORMAT_R5G6B5_UNORM: case PIPE_FORMAT_A1R5G5B5_UNORM: - return usage & + retval = usage & (PIPE_TEXTURE_USAGE_RENDER_TARGET | PIPE_TEXTURE_USAGE_DISPLAY_TARGET | PIPE_TEXTURE_USAGE_PRIMARY); + break; /* Texture */ case PIPE_FORMAT_A8R8G8B8_SRGB: @@ -201,7 +208,10 @@ static boolean check_tex_2d_format(enum pipe_format format, uint32_t usage, case PIPE_FORMAT_DXT3_RGBA: case PIPE_FORMAT_DXT5_RGBA: case PIPE_FORMAT_YCBCR: - return usage & PIPE_TEXTURE_USAGE_SAMPLER; + case PIPE_FORMAT_L8_UNORM: + case PIPE_FORMAT_A8L8_UNORM: + retval = usage & PIPE_TEXTURE_USAGE_SAMPLER; + break; /* Colorbuffer or texture */ case PIPE_FORMAT_A8R8G8B8_UNORM: @@ -209,25 +219,32 @@ static boolean check_tex_2d_format(enum pipe_format format, uint32_t usage, case PIPE_FORMAT_R8G8B8A8_UNORM: case PIPE_FORMAT_R8G8B8X8_UNORM: case PIPE_FORMAT_I8_UNORM: - return usage & + retval = usage & (PIPE_TEXTURE_USAGE_RENDER_TARGET | PIPE_TEXTURE_USAGE_DISPLAY_TARGET | PIPE_TEXTURE_USAGE_PRIMARY | PIPE_TEXTURE_USAGE_SAMPLER); + break; - /* Z buffer */ + /* Z buffer or texture */ case PIPE_FORMAT_Z16_UNORM: - return usage & PIPE_TEXTURE_USAGE_DEPTH_STENCIL; + retval = usage & + (PIPE_TEXTURE_USAGE_DEPTH_STENCIL | + PIPE_TEXTURE_USAGE_SAMPLER); + break; + /* 24bit Z buffer can only be used as a texture on R500. */ + case PIPE_FORMAT_Z24X8_UNORM: /* Z buffer with stencil or texture */ case PIPE_FORMAT_Z24S8_UNORM: - return usage & + retval = usage & (PIPE_TEXTURE_USAGE_DEPTH_STENCIL | - PIPE_TEXTURE_USAGE_SAMPLER); + (is_r500 ? PIPE_TEXTURE_USAGE_SAMPLER : 0)); + break; /* Definitely unsupported formats. */ /* Non-usable Z buffer/stencil formats. */ - case PIPE_FORMAT_Z24X8_UNORM: + case PIPE_FORMAT_Z32_UNORM: case PIPE_FORMAT_S8Z24_UNORM: case PIPE_FORMAT_X8Z24_UNORM: debug_printf("r300: Note: Got unsupported format: %s in %s\n", @@ -237,7 +254,6 @@ static boolean check_tex_2d_format(enum pipe_format format, uint32_t usage, /* XXX These don't even exist case PIPE_FORMAT_A32R32G32B32: case PIPE_FORMAT_A16R16G16B16: */ - /* XXX Insert YUV422 packed VYUY and YVYU here */ /* XXX What the deuce is UV88? (r3xx accel page 14) debug_printf("r300: Warning: Got unimplemented format: %s in %s\n", pf_name(format), __FUNCTION__); @@ -261,10 +277,15 @@ static boolean check_tex_2d_format(enum pipe_format format, uint32_t usage, break; } - return FALSE; + /* If usage was a mask that contained multiple bits, and not all of them + * are supported, this will catch that and return FALSE. + * e.g. usage = 2 | 4; retval = 4; (retval >= usage) == FALSE + * + * This also returns FALSE for any unknown formats. + */ + return (retval >= usage); } -/* XXX moar targets */ static boolean r300_is_format_supported(struct pipe_screen* pscreen, enum pipe_format format, enum pipe_texture_target target, @@ -272,15 +293,13 @@ static boolean r300_is_format_supported(struct pipe_screen* pscreen, unsigned geom_flags) { switch (target) { + case PIPE_TEXTURE_1D: /* handle 1D textures as 2D ones */ case PIPE_TEXTURE_2D: - return check_tex_2d_format(format, tex_usage, - r300_screen(pscreen)->caps->is_r500); - case PIPE_TEXTURE_1D: case PIPE_TEXTURE_3D: case PIPE_TEXTURE_CUBE: - debug_printf("r300: Implementation error: Unsupported format " - "target: %d\n", target); - break; + return check_tex_format(format, tex_usage, + r300_screen(pscreen)->caps->is_r500); + default: debug_printf("r300: Fatal: This is not a format target: %d\n", target); @@ -300,36 +319,25 @@ r300_get_tex_transfer(struct pipe_screen *screen, { struct r300_texture *tex = (struct r300_texture *)texture; struct r300_transfer *trans; - unsigned offset; /* in bytes */ + unsigned offset; - /* XXX Add support for these things */ - if (texture->target == PIPE_TEXTURE_CUBE) { - debug_printf("PIPE_TEXTURE_CUBE is not yet supported.\n"); - /* offset = tex->image_offset[level][face]; */ - } - else if (texture->target == PIPE_TEXTURE_3D) { - debug_printf("PIPE_TEXTURE_3D is not yet supported.\n"); - /* offset = tex->image_offset[level][zslice]; */ - } - else { - offset = tex->offset[level]; - assert(face == 0); - assert(zslice == 0); - } + offset = r300_texture_get_offset(tex, level, zslice, face); /* in bytes */ trans = CALLOC_STRUCT(r300_transfer); if (trans) { pipe_texture_reference(&trans->transfer.texture, texture); - trans->transfer.format = texture->format; trans->transfer.x = x; trans->transfer.y = y; trans->transfer.width = w; trans->transfer.height = h; - trans->transfer.block = texture->block; - trans->transfer.nblocksx = texture->nblocksx[level]; - trans->transfer.nblocksy = texture->nblocksy[level]; trans->transfer.stride = r300_texture_get_stride(tex, level); trans->transfer.usage = usage; + + /* XXX not sure whether it's required to set these two, + the driver doesn't use them */ + trans->transfer.zslice = zslice; + trans->transfer.face = face; + trans->offset = offset; } return &trans->transfer; @@ -347,6 +355,7 @@ static void* r300_transfer_map(struct pipe_screen* screen, { struct r300_texture* tex = (struct r300_texture*)transfer->texture; char* map; + enum pipe_format format = tex->tex.format; map = pipe_buffer_map(screen, tex->buffer, pipe_transfer_buffer_flags(transfer)); @@ -356,8 +365,8 @@ static void* r300_transfer_map(struct pipe_screen* screen, } return map + r300_transfer(transfer)->offset + - transfer->y / transfer->block.height * transfer->stride + - transfer->x / transfer->block.width * transfer->block.size; + transfer->y / util_format_get_blockheight(format) * transfer->stride + + transfer->x / util_format_get_blockwidth(format) * util_format_get_blocksize(format); } static void r300_transfer_unmap(struct pipe_screen* screen, @@ -375,7 +384,7 @@ static void r300_destroy_screen(struct pipe_screen* pscreen) FREE(r300screen); } -struct pipe_screen* r300_create_screen(struct r300_winsys* r300_winsys) +struct pipe_screen* r300_create_screen(struct radeon_winsys* radeon_winsys) { struct r300_screen* r300screen = CALLOC_STRUCT(r300_screen); struct r300_capabilities* caps = CALLOC_STRUCT(r300_capabilities); @@ -383,13 +392,14 @@ struct pipe_screen* r300_create_screen(struct r300_winsys* r300_winsys) if (!r300screen || !caps) return NULL; - caps->pci_id = r300_winsys->pci_id; - caps->num_frag_pipes = r300_winsys->gb_pipes; + caps->pci_id = radeon_winsys->pci_id; + caps->num_frag_pipes = radeon_winsys->gb_pipes; + caps->num_z_pipes = radeon_winsys->z_pipes; r300_parse_chipset(caps); r300screen->caps = caps; - r300screen->screen.winsys = (struct pipe_winsys*)r300_winsys; + r300screen->screen.winsys = (struct pipe_winsys*)radeon_winsys; r300screen->screen.destroy = r300_destroy_screen; r300screen->screen.get_name = r300_get_name; r300screen->screen.get_vendor = r300_get_vendor; diff --git a/src/gallium/drivers/r300/r300_screen.h b/src/gallium/drivers/r300/r300_screen.h index 2a0e41fbc3b..2217988addd 100644 --- a/src/gallium/drivers/r300/r300_screen.h +++ b/src/gallium/drivers/r300/r300_screen.h @@ -23,14 +23,11 @@ #ifndef R300_SCREEN_H #define R300_SCREEN_H -#include "pipe/p_inlines.h" #include "pipe/p_screen.h" -#include "util/u_memory.h" -#include "util/u_simple_screen.h" #include "r300_chipset.h" -#include "r300_texture.h" -#include "r300_winsys.h" + +struct radeon_winsys; struct r300_screen { /* Parent class */ @@ -61,6 +58,6 @@ r300_transfer(struct pipe_transfer* transfer) } /* Creates a new r300 screen. */ -struct pipe_screen* r300_create_screen(struct r300_winsys* r300_winsys); +struct pipe_screen* r300_create_screen(struct radeon_winsys* radeon_winsys); #endif /* R300_SCREEN_H */ diff --git a/src/gallium/drivers/r300/r300_shader_inlines.h b/src/gallium/drivers/r300/r300_shader_inlines.h deleted file mode 100644 index a04f45b03e2..00000000000 --- a/src/gallium/drivers/r300/r300_shader_inlines.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2009 Corbin Simpson <[email protected]> - * Joakim Sindholt <[email protected]> - * - * 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_SHADER_INLINES_H -#define R300_SHADER_INLINES_H - -/* TGSI constants. TGSI is like XML: If it can't solve your problems, you're - * not using enough of it. */ -static const struct tgsi_full_src_register r300_constant_zero = { - .SrcRegister.Extended = TRUE, - .SrcRegister.File = TGSI_FILE_NULL, - .SrcRegisterExtSwz.ExtSwizzleX = TGSI_EXTSWIZZLE_ZERO, - .SrcRegisterExtSwz.ExtSwizzleY = TGSI_EXTSWIZZLE_ZERO, - .SrcRegisterExtSwz.ExtSwizzleZ = TGSI_EXTSWIZZLE_ZERO, - .SrcRegisterExtSwz.ExtSwizzleW = TGSI_EXTSWIZZLE_ZERO, -}; - -static const struct tgsi_full_src_register r300_constant_one = { - .SrcRegister.Extended = TRUE, - .SrcRegister.File = TGSI_FILE_NULL, - .SrcRegisterExtSwz.ExtSwizzleX = TGSI_EXTSWIZZLE_ONE, - .SrcRegisterExtSwz.ExtSwizzleY = TGSI_EXTSWIZZLE_ONE, - .SrcRegisterExtSwz.ExtSwizzleZ = TGSI_EXTSWIZZLE_ONE, - .SrcRegisterExtSwz.ExtSwizzleW = TGSI_EXTSWIZZLE_ONE, -}; - -#endif /* R300_SHADER_INLINES_H */ diff --git a/src/gallium/drivers/r300/r300_shader_semantics.h b/src/gallium/drivers/r300/r300_shader_semantics.h new file mode 100644 index 00000000000..6796841b29b --- /dev/null +++ b/src/gallium/drivers/r300/r300_shader_semantics.h @@ -0,0 +1,66 @@ +/* + * Copyright 2009 Marek Olšák <[email protected]> + * + * 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_SHADER_SEMANTICS_H +#define R300_SHADER_SEMANTICS_H + +#define ATTR_UNUSED (-1) +#define ATTR_COLOR_COUNT 2 +#define ATTR_GENERIC_COUNT 16 + +/* This structure contains information about what attributes are written by VS + * or read by FS. (but not both) It's much easier to work with than + * tgsi_shader_info. + * + * The variables contain indices to tgsi_shader_info semantics and those + * indices are nothing else than input/output register numbers. */ +struct r300_shader_semantics { + int pos; + int psize; + int color[ATTR_COLOR_COUNT]; + int bcolor[ATTR_COLOR_COUNT]; + int generic[ATTR_GENERIC_COUNT]; + int fog; + int wpos; +}; + +static INLINE void r300_shader_semantics_reset( + struct r300_shader_semantics* info) +{ + int i; + + info->pos = ATTR_UNUSED; + info->psize = ATTR_UNUSED; + info->fog = ATTR_UNUSED; + info->wpos = ATTR_UNUSED; + + for (i = 0; i < ATTR_COLOR_COUNT; i++) { + info->color[i] = ATTR_UNUSED; + info->bcolor[i] = ATTR_UNUSED; + } + + for (i = 0; i < ATTR_GENERIC_COUNT; i++) { + info->generic[i] = ATTR_UNUSED; + } +} + +#endif diff --git a/src/gallium/drivers/r300/r300_state.c b/src/gallium/drivers/r300/r300_state.c index 88cb9af6fb7..a145a7f18a5 100644 --- a/src/gallium/drivers/r300/r300_state.c +++ b/src/gallium/drivers/r300/r300_state.c @@ -1,5 +1,6 @@ /* * Copyright 2008 Corbin Simpson <[email protected]> + * Copyright 2009 Marek Olšák <[email protected]> * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -20,8 +21,10 @@ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE * USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#include "util/u_debug.h" +#include "draw/draw_context.h" + #include "util/u_math.h" +#include "util/u_memory.h" #include "util/u_pack_color.h" #include "tgsi/tgsi_parse.h" @@ -31,6 +34,7 @@ #include "r300_context.h" #include "r300_reg.h" +#include "r300_screen.h" #include "r300_state_inlines.h" #include "r300_fs.h" #include "r300_vs.h" @@ -38,6 +42,120 @@ /* r300_state: Functions used to intialize state context by translating * Gallium state objects into semi-native r300 state objects. */ +static boolean blend_discard_if_src_alpha_0(unsigned srcRGB, unsigned srcA, + unsigned dstRGB, unsigned dstA) +{ + /* If the blend equation is ADD or REVERSE_SUBTRACT, + * SRC_ALPHA == 0, and the following state is set, the colorbuffer + * will not be changed. + * Notice that the dst factors are the src factors inverted. */ + return (srcRGB == PIPE_BLENDFACTOR_SRC_ALPHA || + srcRGB == PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE || + srcRGB == PIPE_BLENDFACTOR_ZERO) && + (srcA == PIPE_BLENDFACTOR_SRC_COLOR || + srcA == PIPE_BLENDFACTOR_SRC_ALPHA || + srcA == PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE || + srcA == PIPE_BLENDFACTOR_ZERO) && + (dstRGB == PIPE_BLENDFACTOR_INV_SRC_ALPHA || + dstRGB == PIPE_BLENDFACTOR_ONE) && + (dstA == PIPE_BLENDFACTOR_INV_SRC_COLOR || + dstA == PIPE_BLENDFACTOR_INV_SRC_ALPHA || + dstA == PIPE_BLENDFACTOR_ONE); +} + +static boolean blend_discard_if_src_alpha_1(unsigned srcRGB, unsigned srcA, + unsigned dstRGB, unsigned dstA) +{ + /* If the blend equation is ADD or REVERSE_SUBTRACT, + * SRC_ALPHA == 1, and the following state is set, the colorbuffer + * will not be changed. + * Notice that the dst factors are the src factors inverted. */ + return (srcRGB == PIPE_BLENDFACTOR_INV_SRC_ALPHA || + srcRGB == PIPE_BLENDFACTOR_ZERO) && + (srcA == PIPE_BLENDFACTOR_INV_SRC_COLOR || + srcA == PIPE_BLENDFACTOR_INV_SRC_ALPHA || + srcA == PIPE_BLENDFACTOR_ZERO) && + (dstRGB == PIPE_BLENDFACTOR_SRC_ALPHA || + dstRGB == PIPE_BLENDFACTOR_ONE) && + (dstA == PIPE_BLENDFACTOR_SRC_COLOR || + dstA == PIPE_BLENDFACTOR_SRC_ALPHA || + dstA == PIPE_BLENDFACTOR_ONE); +} + +static boolean blend_discard_if_src_color_0(unsigned srcRGB, unsigned srcA, + unsigned dstRGB, unsigned dstA) +{ + /* If the blend equation is ADD or REVERSE_SUBTRACT, + * SRC_COLOR == (0,0,0), and the following state is set, the colorbuffer + * will not be changed. + * Notice that the dst factors are the src factors inverted. */ + return (srcRGB == PIPE_BLENDFACTOR_SRC_COLOR || + srcRGB == PIPE_BLENDFACTOR_ZERO) && + (srcA == PIPE_BLENDFACTOR_ZERO) && + (dstRGB == PIPE_BLENDFACTOR_INV_SRC_COLOR || + dstRGB == PIPE_BLENDFACTOR_ONE) && + (dstA == PIPE_BLENDFACTOR_ONE); +} + +static boolean blend_discard_if_src_color_1(unsigned srcRGB, unsigned srcA, + unsigned dstRGB, unsigned dstA) +{ + /* If the blend equation is ADD or REVERSE_SUBTRACT, + * SRC_COLOR == (1,1,1), and the following state is set, the colorbuffer + * will not be changed. + * Notice that the dst factors are the src factors inverted. */ + return (srcRGB == PIPE_BLENDFACTOR_INV_SRC_COLOR || + srcRGB == PIPE_BLENDFACTOR_ZERO) && + (srcA == PIPE_BLENDFACTOR_ZERO) && + (dstRGB == PIPE_BLENDFACTOR_SRC_COLOR || + dstRGB == PIPE_BLENDFACTOR_ONE) && + (dstA == PIPE_BLENDFACTOR_ONE); +} + +static boolean blend_discard_if_src_alpha_color_0(unsigned srcRGB, unsigned srcA, + unsigned dstRGB, unsigned dstA) +{ + /* If the blend equation is ADD or REVERSE_SUBTRACT, + * SRC_ALPHA_COLOR == (0,0,0,0), and the following state is set, + * the colorbuffer will not be changed. + * Notice that the dst factors are the src factors inverted. */ + return (srcRGB == PIPE_BLENDFACTOR_SRC_COLOR || + srcRGB == PIPE_BLENDFACTOR_SRC_ALPHA || + srcRGB == PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE || + srcRGB == PIPE_BLENDFACTOR_ZERO) && + (srcA == PIPE_BLENDFACTOR_SRC_COLOR || + srcA == PIPE_BLENDFACTOR_SRC_ALPHA || + srcA == PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE || + srcA == PIPE_BLENDFACTOR_ZERO) && + (dstRGB == PIPE_BLENDFACTOR_INV_SRC_COLOR || + dstRGB == PIPE_BLENDFACTOR_INV_SRC_ALPHA || + dstRGB == PIPE_BLENDFACTOR_ONE) && + (dstA == PIPE_BLENDFACTOR_INV_SRC_COLOR || + dstA == PIPE_BLENDFACTOR_INV_SRC_ALPHA || + dstA == PIPE_BLENDFACTOR_ONE); +} + +static boolean blend_discard_if_src_alpha_color_1(unsigned srcRGB, unsigned srcA, + unsigned dstRGB, unsigned dstA) +{ + /* If the blend equation is ADD or REVERSE_SUBTRACT, + * SRC_ALPHA_COLOR == (1,1,1,1), and the following state is set, + * the colorbuffer will not be changed. + * Notice that the dst factors are the src factors inverted. */ + return (srcRGB == PIPE_BLENDFACTOR_INV_SRC_COLOR || + srcRGB == PIPE_BLENDFACTOR_INV_SRC_ALPHA || + srcRGB == PIPE_BLENDFACTOR_ZERO) && + (srcA == PIPE_BLENDFACTOR_INV_SRC_COLOR || + srcA == PIPE_BLENDFACTOR_INV_SRC_ALPHA || + srcA == PIPE_BLENDFACTOR_ZERO) && + (dstRGB == PIPE_BLENDFACTOR_SRC_COLOR || + dstRGB == PIPE_BLENDFACTOR_SRC_ALPHA || + dstRGB == PIPE_BLENDFACTOR_ONE) && + (dstA == PIPE_BLENDFACTOR_SRC_COLOR || + dstA == PIPE_BLENDFACTOR_SRC_ALPHA || + dstA == PIPE_BLENDFACTOR_ONE); +} + /* Create a new blend state based on the CSO blend state. * * This encompasses alpha blending, logic/raster ops, and blend dithering. */ @@ -46,23 +164,123 @@ static void* r300_create_blend_state(struct pipe_context* pipe, { struct r300_blend_state* blend = CALLOC_STRUCT(r300_blend_state); - if (state->blend_enable) { - /* XXX for now, always do separate alpha... - * is it faster to do it with one reg? */ + if (state->blend_enable) + { + unsigned eqRGB = state->rgb_func; + unsigned srcRGB = state->rgb_src_factor; + unsigned dstRGB = state->rgb_dst_factor; + + unsigned eqA = state->alpha_func; + unsigned srcA = state->alpha_src_factor; + unsigned dstA = state->alpha_dst_factor; + + /* 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 | - R300_SEPARATE_ALPHA_ENABLE | - R300_READ_ENABLE | - r300_translate_blend_function(state->rgb_func) | - (r300_translate_blend_factor(state->rgb_src_factor) << - R300_SRC_BLEND_SHIFT) | - (r300_translate_blend_factor(state->rgb_dst_factor) << - R300_DST_BLEND_SHIFT); - blend->alpha_blend_control = - r300_translate_blend_function(state->alpha_func) | - (r300_translate_blend_factor(state->alpha_src_factor) << - R300_SRC_BLEND_SHIFT) | - (r300_translate_blend_factor(state->alpha_dst_factor) << - R300_DST_BLEND_SHIFT); + r300_translate_blend_function(eqRGB) | + ( r300_translate_blend_factor(srcRGB) << R300_SRC_BLEND_SHIFT) | + ( r300_translate_blend_factor(dstRGB) << R300_DST_BLEND_SHIFT); + + /* Optimization: some operations do not require the destination color. + * + * When SRC_ALPHA_SATURATE is used, colorbuffer reads must be enabled, + * otherwise blending gives incorrect results. It seems to be + * a hardware bug. */ + if (eqRGB == PIPE_BLEND_MIN || eqA == PIPE_BLEND_MIN || + eqRGB == PIPE_BLEND_MAX || eqA == PIPE_BLEND_MAX || + dstRGB != PIPE_BLENDFACTOR_ZERO || + dstA != PIPE_BLENDFACTOR_ZERO || + srcRGB == PIPE_BLENDFACTOR_DST_COLOR || + srcRGB == PIPE_BLENDFACTOR_DST_ALPHA || + srcRGB == PIPE_BLENDFACTOR_INV_DST_COLOR || + srcRGB == PIPE_BLENDFACTOR_INV_DST_ALPHA || + srcA == PIPE_BLENDFACTOR_DST_COLOR || + srcA == PIPE_BLENDFACTOR_DST_ALPHA || + srcA == PIPE_BLENDFACTOR_INV_DST_COLOR || + srcA == PIPE_BLENDFACTOR_INV_DST_ALPHA || + srcRGB == PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE) { + /* Enable reading from the colorbuffer. */ + blend->blend_control |= R300_READ_ENABLE; + + if (r300_screen(r300_context(pipe)->context.screen)->caps->is_r500) { + /* Optimization: Depending on incoming pixels, we can + * conditionally disable the reading in hardware... */ + if (eqRGB != PIPE_BLEND_MIN && eqA != PIPE_BLEND_MIN && + eqRGB != PIPE_BLEND_MAX && eqA != PIPE_BLEND_MAX) { + /* Disable reading if SRC_ALPHA == 0. */ + if ((dstRGB == PIPE_BLENDFACTOR_SRC_ALPHA || + dstRGB == PIPE_BLENDFACTOR_ZERO) && + (dstA == PIPE_BLENDFACTOR_SRC_COLOR || + dstA == PIPE_BLENDFACTOR_SRC_ALPHA || + dstA == PIPE_BLENDFACTOR_ZERO)) { + blend->blend_control |= R500_SRC_ALPHA_0_NO_READ; + } + + /* Disable reading if SRC_ALPHA == 1. */ + if ((dstRGB == PIPE_BLENDFACTOR_INV_SRC_ALPHA || + dstRGB == PIPE_BLENDFACTOR_ZERO) && + (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; + } + } + } + } + + /* Optimization: discard pixels which don't change the colorbuffer. + * + * The code below is non-trivial and some math is involved. + * + * Discarding pixels must be disabled when FP16 AA is enabled. + * This is a hardware bug. Also, this implementation wouldn't work + * with FP blending enabled and equation clamping disabled. + * + * Equations other than ADD are rarely used and therefore won't be + * optimized. */ + if ((eqRGB == PIPE_BLEND_ADD || eqRGB == PIPE_BLEND_REVERSE_SUBTRACT) && + (eqA == PIPE_BLEND_ADD || eqA == PIPE_BLEND_REVERSE_SUBTRACT)) { + /* ADD: X+Y + * REVERSE_SUBTRACT: Y-X + * + * The idea is: + * If X = src*srcFactor = 0 and Y = dst*dstFactor = 1, + * then CB will not be changed. + * + * Given the srcFactor and dstFactor variables, we can derive + * what src and dst should be equal to and discard appropriate + * pixels. + */ + if (blend_discard_if_src_alpha_0(srcRGB, srcA, dstRGB, dstA)) { + blend->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; + } else if (blend_discard_if_src_color_0(srcRGB, srcA, + dstRGB, dstA)) { + blend->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; + } else if (blend_discard_if_src_alpha_color_0(srcRGB, srcA, + dstRGB, dstA)) { + blend->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 |= + 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 = + r300_translate_blend_function(eqA) | + (r300_translate_blend_factor(srcA) << R300_SRC_BLEND_SHIFT) | + (r300_translate_blend_factor(dstA) << R300_DST_BLEND_SHIFT); + } } /* PIPE_LOGICOP_* don't need to be translated, fortunately. */ @@ -71,6 +289,20 @@ static void* r300_create_blend_state(struct pipe_context* pipe, (state->logicop_func) << R300_RB3D_ROPCNTL_ROP_SHIFT; } + /* Color Channel Mask */ + if (state->colormask & PIPE_MASK_R) { + blend->color_channel_mask |= RB3D_COLOR_CHANNEL_MASK_RED_MASK0; + } + if (state->colormask & PIPE_MASK_G) { + blend->color_channel_mask |= RB3D_COLOR_CHANNEL_MASK_GREEN_MASK0; + } + if (state->colormask & PIPE_MASK_B) { + blend->color_channel_mask |= RB3D_COLOR_CHANNEL_MASK_BLUE_MASK0; + } + if (state->colormask & PIPE_MASK_A) { + blend->color_channel_mask |= RB3D_COLOR_CHANNEL_MASK_ALPHA_MASK0; + } + if (state->dither) { blend->dither = R300_RB3D_DITHER_CTL_DITHER_MODE_LUT | R300_RB3D_DITHER_CTL_ALPHA_DITHER_MODE_LUT; @@ -96,25 +328,30 @@ static void r300_delete_blend_state(struct pipe_context* pipe, FREE(state); } +/* Convert float to 10bit integer */ +static unsigned float_to_fixed10(float f) +{ + return CLAMP((unsigned)(f * 1023.9f), 0, 1023); +} + /* Set blend color. * Setup both R300 and R500 registers, figure out later which one to write. */ static void r300_set_blend_color(struct pipe_context* pipe, const struct pipe_blend_color* color) { struct r300_context* r300 = r300_context(pipe); - ubyte ur, ug, ub, ua; - - ur = float_to_ubyte(color->color[0]); - ug = float_to_ubyte(color->color[1]); - ub = float_to_ubyte(color->color[2]); - ua = float_to_ubyte(color->color[3]); + union util_color uc; - util_pack_color(color->color, PIPE_FORMAT_A8R8G8B8_UNORM, - &r300->blend_color_state->blend_color); + util_pack_color(color->color, PIPE_FORMAT_A8R8G8B8_UNORM, &uc); + r300->blend_color_state->blend_color = uc.ui; - /* XXX this is wrong */ - r300->blend_color_state->blend_color_red_alpha = ur | (ua << 16); - r300->blend_color_state->blend_color_green_blue = ub | (ug << 16); + /* XXX if FP16 blending is enabled, we should use the FP16 format */ + r300->blend_color_state->blend_color_red_alpha = + float_to_fixed10(color->color[0]) | + (float_to_fixed10(color->color[3]) << 16); + r300->blend_color_state->blend_color_green_blue = + float_to_fixed10(color->color[2]) | + (float_to_fixed10(color->color[1]) << 16); r300->dirty_state |= R300_NEW_BLEND_COLOR; } @@ -133,31 +370,6 @@ static void r300_set_clip_state(struct pipe_context* pipe, } } -static void - r300_set_constant_buffer(struct pipe_context* pipe, - uint shader, uint index, - const struct pipe_constant_buffer* buffer) -{ - struct r300_context* r300 = r300_context(pipe); - - /* This entire chunk of code seems ever-so-slightly baked. - * It's as if I've got pipe_buffer* matryoshkas... */ - if (buffer && buffer->buffer && buffer->buffer->size) { - void* map = pipe->winsys->buffer_map(pipe->winsys, buffer->buffer, - PIPE_BUFFER_USAGE_CPU_READ); - memcpy(r300->shader_constants[shader].constants, - map, buffer->buffer->size); - pipe->winsys->buffer_unmap(pipe->winsys, buffer->buffer); - - r300->shader_constants[shader].count = - buffer->buffer->size / (sizeof(float) * 4); - } else { - r300->shader_constants[shader].count = 0; - } - - r300->dirty_state |= R300_NEW_CONSTANTS; -} - /* Create a new depth, stencil, and alpha state based on the CSO dsa state. * * This contains the depth buffer, stencil buffer, alpha test, and such. @@ -167,6 +379,8 @@ static void* r300_create_dsa_state(struct pipe_context* pipe, const struct pipe_depth_stencil_alpha_state* state) { + struct r300_capabilities *caps = + r300_screen(r300_context(pipe)->context.screen)->caps; struct r300_dsa_state* dsa = CALLOC_STRUCT(r300_dsa_state); /* Depth test setup. */ @@ -211,9 +425,16 @@ static void* (r300_translate_stencil_op(state->stencil[1].zfail_op) << R300_S_BACK_ZFAIL_OP_SHIFT); - dsa->stencil_ref_bf = (state->stencil[1].ref_value) | - (state->stencil[1].valuemask << R300_STENCILMASK_SHIFT) | - (state->stencil[1].writemask << R300_STENCILWRITEMASK_SHIFT); + /* XXX it seems r3xx doesn't support STENCILREFMASK_BF */ + if (caps->is_r500) + { + dsa->z_buffer_control |= R500_STENCIL_REFMASK_FRONT_BACK; + dsa->stencil_ref_bf = (state->stencil[1].ref_value) | + (state->stencil[1].valuemask << + R300_STENCILMASK_SHIFT) | + (state->stencil[1].writemask << + R300_STENCILWRITEMASK_SHIFT); + } } } @@ -222,11 +443,13 @@ static void* dsa->alpha_function = r300_translate_alpha_function(state->alpha.func) | R300_FG_ALPHA_FUNC_ENABLE; - dsa->alpha_reference = CLAMP(state->alpha.ref_value * 1023.0f, - 0, 1023); - } else { - /* XXX need to fix this to be dynamically set - dsa->z_buffer_top = R300_ZTOP_ENABLE; */ + + /* XXX figure out why emitting 10bit alpha ref causes CS to dump */ + /* always use 8bit alpha ref */ + dsa->alpha_function |= float_to_ubyte(state->alpha.ref_value); + + if (caps->is_r500) + dsa->alpha_function |= R500_FG_ALPHA_FUNC_8BIT; } return (void*)dsa; @@ -249,11 +472,29 @@ static void r300_delete_dsa_state(struct pipe_context* pipe, FREE(state); } -static void r300_set_edgeflags(struct pipe_context* pipe, - const unsigned* bitfield) +static void r300_set_scissor_regs(const struct pipe_scissor_state* state, + struct r300_scissor_regs *scissor, + boolean is_r500) { - /* XXX you know it's bad when i915 has this blank too */ - /* XXX and even worse, I have no idea WTF the bitfield is */ + if (is_r500) { + scissor->top_left = + (state->minx << R300_SCISSORS_X_SHIFT) | + (state->miny << R300_SCISSORS_Y_SHIFT); + scissor->bottom_right = + ((state->maxx - 1) << R300_SCISSORS_X_SHIFT) | + ((state->maxy - 1) << R300_SCISSORS_Y_SHIFT); + } else { + /* Offset of 1440 in non-R500 chipsets. */ + scissor->top_left = + ((state->minx + 1440) << R300_SCISSORS_X_SHIFT) | + ((state->miny + 1440) << R300_SCISSORS_Y_SHIFT); + scissor->bottom_right = + (((state->maxx - 1) + 1440) << R300_SCISSORS_X_SHIFT) | + (((state->maxy - 1) + 1440) << R300_SCISSORS_Y_SHIFT); + } + + scissor->empty_area = state->minx >= state->maxx || + state->miny >= state->maxy; } static void @@ -261,12 +502,27 @@ static void const struct pipe_framebuffer_state* state) { struct r300_context* r300 = r300_context(pipe); + struct pipe_scissor_state scissor; - draw_flush(r300->draw); + if (r300->draw) { + draw_flush(r300->draw); + } r300->framebuffer_state = *state; + scissor.minx = scissor.miny = 0; + scissor.maxx = state->width; + scissor.maxy = state->height; + r300_set_scissor_regs(&scissor, &r300->scissor_state->framebuffer, + r300_screen(r300->context.screen)->caps->is_r500); + + /* Don't rely on the order of states being set for the first time. */ + if (!r300->rs_state || !r300->rs_state->rs.scissor) { + r300->dirty_state |= R300_NEW_SCISSOR; + } r300->dirty_state |= R300_NEW_FRAMEBUFFERS; + r300->dirty_state |= R300_NEW_BLEND; + r300->dirty_state |= R300_NEW_DSA; } /* Create fragment shader state. */ @@ -282,6 +538,7 @@ static void* r300_create_fs_state(struct pipe_context* pipe, fs->state.tokens = tgsi_dup_tokens(shader->tokens); tgsi_scan_shader(shader->tokens, &fs->info); + r300_shader_read_fs_inputs(&fs->info, &fs->inputs); return (void*)fs; } @@ -295,21 +552,31 @@ static void r300_bind_fs_state(struct pipe_context* pipe, void* shader) if (fs == NULL) { r300->fs = NULL; return; - } else if (!fs->translated) { - r300_translate_fragment_shader(r300, fs); } r300->fs = fs; + r300_pick_fragment_shader(r300); - r300->dirty_state |= R300_NEW_FRAGMENT_SHADER; + if (r300->vs && r300_vertex_shader_setup_wpos(r300)) { + r300->dirty_state |= R300_NEW_VERTEX_FORMAT; + } + + r300->dirty_state |= R300_NEW_FRAGMENT_SHADER | R300_NEW_FRAGMENT_SHADER_CONSTANTS; } /* Delete fragment shader state. */ static void r300_delete_fs_state(struct pipe_context* pipe, void* shader) { struct r300_fragment_shader* fs = (struct r300_fragment_shader*)shader; - rc_constants_destroy(&fs->code.constants); - FREE(fs->state.tokens); + struct r300_fragment_shader_code *tmp, *ptr = fs->first; + + while (ptr) { + tmp = ptr; + ptr = ptr->next; + rc_constants_destroy(&tmp->code.constants); + FREE(tmp); + } + FREE((void*)fs->state.tokens); FREE(shader); } @@ -347,8 +614,6 @@ static void* r300_create_rs_state(struct pipe_context* pipe, if (state->bypass_vs_clip_and_viewport || !r300_screen(pipe->screen)->caps->has_tcl) { rs->vap_control_status |= R300_VAP_TCL_BYPASS; - } else { - rs->rs.bypass_vs_clip_and_viewport = TRUE; } rs->point_size = pack_float_16_6x(state->point_size) | @@ -363,25 +628,52 @@ static void* r300_create_rs_state(struct pipe_context* pipe, rs->line_control = pack_float_16_6x(state->line_width) | R300_GA_LINE_CNTL_END_TYPE_COMP; + /* XXX I think there is something wrong with the polygon mode, + * XXX re-test when r300g is in a better shape */ + + /* Enable polygon mode */ + if (state->fill_cw != PIPE_POLYGON_MODE_FILL || + state->fill_ccw != PIPE_POLYGON_MODE_FILL) { + rs->polygon_mode = R300_GA_POLY_MODE_DUAL; + } + /* Radeons don't think in "CW/CCW", they think in "front/back". */ if (state->front_winding == PIPE_WINDING_CW) { rs->cull_mode = R300_FRONT_FACE_CW; + /* Polygon offset */ if (state->offset_cw) { rs->polygon_offset_enable |= R300_FRONT_ENABLE; } if (state->offset_ccw) { rs->polygon_offset_enable |= R300_BACK_ENABLE; } + + /* Polygon mode */ + if (rs->polygon_mode) { + rs->polygon_mode |= + r300_translate_polygon_mode_front(state->fill_cw); + rs->polygon_mode |= + r300_translate_polygon_mode_back(state->fill_ccw); + } } else { rs->cull_mode = R300_FRONT_FACE_CCW; + /* Polygon offset */ if (state->offset_ccw) { rs->polygon_offset_enable |= R300_FRONT_ENABLE; } if (state->offset_cw) { rs->polygon_offset_enable |= R300_BACK_ENABLE; } + + /* Polygon mode */ + if (rs->polygon_mode) { + rs->polygon_mode |= + r300_translate_polygon_mode_front(state->fill_ccw); + rs->polygon_mode |= + r300_translate_polygon_mode_back(state->fill_cw); + } } if (state->front_winding & state->cull_mode) { rs->cull_mode |= R300_CULL_FRONT; @@ -412,10 +704,6 @@ static void* r300_create_rs_state(struct pipe_context* pipe, rs->color_control = R300_SHADE_MODEL_SMOOTH; } - if (!state->flatshade_first) { - rs->color_control |= R300_GA_COLOR_CONTROL_PROVOKING_VERTEX_LAST; - } - return (void*)rs; } @@ -425,14 +713,20 @@ static void r300_bind_rs_state(struct pipe_context* pipe, void* state) struct r300_context* r300 = r300_context(pipe); struct r300_rs_state* rs = (struct r300_rs_state*)state; - draw_flush(r300->draw); - draw_set_rasterizer_state(r300->draw, &rs->rs); + if (r300->draw) { + draw_flush(r300->draw); + draw_set_rasterizer_state(r300->draw, &rs->rs); + } r300->rs_state = rs; + /* XXX Clean these up when we move to atom emits */ r300->dirty_state |= R300_NEW_RASTERIZER; r300->dirty_state |= R300_NEW_RS_BLOCK; r300->dirty_state |= R300_NEW_SCISSOR; r300->dirty_state |= R300_NEW_VIEWPORT; + if (r300->fs && r300->fs->inputs.wpos != ATTR_UNUSED) { + r300->dirty_state |= R300_NEW_FRAGMENT_SHADER_CONSTANTS; + } } /* Free rasterizer state. */ @@ -448,6 +742,9 @@ static void* struct r300_context* r300 = r300_context(pipe); struct r300_sampler_state* sampler = CALLOC_STRUCT(r300_sampler_state); int lod_bias; + union util_color uc; + + sampler->state = *state; sampler->filter0 |= (r300_translate_wrap(state->wrap_s) << R300_TX_WRAP_S_SHIFT) | @@ -456,7 +753,13 @@ static void* sampler->filter0 |= r300_translate_tex_filters(state->min_img_filter, state->mag_img_filter, - state->min_mip_filter); + state->min_mip_filter, + state->max_anisotropy > 1.0); + + /* Unfortunately, r300-r500 don't support floating-point mipmap lods. */ + /* We must pass these to the emit function to clamp them properly. */ + sampler->min_lod = MAX2((unsigned)state->min_lod, 0); + sampler->max_lod = MAX2((unsigned)ceilf(state->max_lod), 0); lod_bias = CLAMP((int)(state->lod_bias * 32), -(1 << 9), (1 << 9) - 1); @@ -464,8 +767,8 @@ static void* sampler->filter1 |= r300_anisotropy(state->max_anisotropy); - util_pack_color(state->border_color, PIPE_FORMAT_A8R8G8B8_UNORM, - &sampler->border_color); + util_pack_color(state->border_color, PIPE_FORMAT_A8R8G8B8_UNORM, &uc); + sampler->border_color = uc.ui; /* R500-specific fixups and optimizations */ if (r300_screen(r300->context.screen)->caps->is_r500) { @@ -494,6 +797,20 @@ static void r300_bind_sampler_states(struct pipe_context* pipe, } r300->sampler_count = count; + + /* Pick a fragment shader based on the texture compare state. */ + if (r300->fs && (r300->dirty_state & R300_ANY_NEW_SAMPLERS)) { + if (r300_pick_fragment_shader(r300)) { + r300->dirty_state |= R300_NEW_FRAGMENT_SHADER | + R300_NEW_FRAGMENT_SHADER_CONSTANTS; + } + } +} + +static void r300_lacks_vertex_textures(struct pipe_context* pipe, + unsigned count, + void** states) +{ } static void r300_delete_sampler_state(struct pipe_context* pipe, void* state) @@ -506,18 +823,26 @@ static void r300_set_sampler_textures(struct pipe_context* pipe, struct pipe_texture** texture) { struct r300_context* r300 = r300_context(pipe); + boolean is_r500 = r300_screen(r300->context.screen)->caps->is_r500; int i; /* XXX magic num */ if (count > 8) { return; } - + for (i = 0; i < count; i++) { if (r300->textures[i] != (struct r300_texture*)texture[i]) { pipe_texture_reference((struct pipe_texture**)&r300->textures[i], texture[i]); r300->dirty_state |= (R300_NEW_TEXTURE << i); + + /* R300-specific - set the texrect factor in a fragment shader */ + if (!is_r500 && r300->textures[i]->is_npot) { + /* XXX It would be nice to re-emit just 1 constant, + * XXX not all of them */ + r300->dirty_state |= R300_NEW_FRAGMENT_SHADER_CONSTANTS; + } } } @@ -537,24 +862,13 @@ static void r300_set_scissor_state(struct pipe_context* pipe, { struct r300_context* r300 = r300_context(pipe); - if (r300_screen(r300->context.screen)->caps->is_r500) { - r300->scissor_state->scissor_top_left = - (state->minx << R300_SCISSORS_X_SHIFT) | - (state->miny << R300_SCISSORS_Y_SHIFT); - r300->scissor_state->scissor_bottom_right = - ((state->maxx - 1) << R300_SCISSORS_X_SHIFT) | - ((state->maxy - 1) << R300_SCISSORS_Y_SHIFT); - } else { - /* Offset of 1440 in non-R500 chipsets. */ - r300->scissor_state->scissor_top_left = - ((state->minx + 1440) << R300_SCISSORS_X_SHIFT) | - ((state->miny + 1440) << R300_SCISSORS_Y_SHIFT); - r300->scissor_state->scissor_bottom_right = - (((state->maxx - 1) + 1440) << R300_SCISSORS_X_SHIFT) | - (((state->maxy - 1) + 1440) << R300_SCISSORS_Y_SHIFT); - } + r300_set_scissor_regs(state, &r300->scissor_state->scissor, + r300_screen(r300->context.screen)->caps->is_r500); - r300->dirty_state |= R300_NEW_SCISSOR; + /* Don't rely on the order of states being set for the first time. */ + if (!r300->rs_state || r300->rs_state->rs.scissor) { + r300->dirty_state |= R300_NEW_SCISSOR; + } } static void r300_set_viewport_state(struct pipe_context* pipe, @@ -566,17 +880,14 @@ static void r300_set_viewport_state(struct pipe_context* pipe, r300->viewport_state->vte_control = R300_VTX_W0_FMT; if (state->scale[0] != 1.0f) { - assert(state->scale[0] != 0.0f); r300->viewport_state->xscale = state->scale[0]; r300->viewport_state->vte_control |= R300_VPORT_X_SCALE_ENA; } if (state->scale[1] != 1.0f) { - assert(state->scale[1] != 0.0f); r300->viewport_state->yscale = state->scale[1]; r300->viewport_state->vte_control |= R300_VPORT_Y_SCALE_ENA; } if (state->scale[2] != 1.0f) { - assert(state->scale[2] != 0.0f); r300->viewport_state->zscale = state->scale[2]; r300->viewport_state->vte_control |= R300_VPORT_Z_SCALE_ENA; } @@ -594,6 +905,9 @@ static void r300_set_viewport_state(struct pipe_context* pipe, } r300->dirty_state |= R300_NEW_VIEWPORT; + if (r300->fs && r300->fs->inputs.wpos != ATTR_UNUSED) { + r300->dirty_state |= R300_NEW_FRAGMENT_SHADER_CONSTANTS; + } } static void r300_set_vertex_buffers(struct pipe_context* pipe, @@ -602,13 +916,16 @@ static void r300_set_vertex_buffers(struct pipe_context* pipe, { struct r300_context* r300 = r300_context(pipe); - memcpy(r300->vertex_buffers, buffers, + memcpy(r300->vertex_buffer, buffers, sizeof(struct pipe_vertex_buffer) * count); - r300->vertex_buffer_count = count; - draw_flush(r300->draw); - draw_set_vertex_buffers(r300->draw, count, buffers); + if (r300->draw) { + draw_flush(r300->draw); + draw_set_vertex_buffers(r300->draw, count, buffers); + } + + r300->dirty_state |= R300_NEW_VERTEX_FORMAT; } static void r300_set_vertex_elements(struct pipe_context* pipe, @@ -617,8 +934,15 @@ static void r300_set_vertex_elements(struct pipe_context* pipe, { struct r300_context* r300 = r300_context(pipe); - draw_flush(r300->draw); - draw_set_vertex_elements(r300->draw, count, elements); + memcpy(r300->vertex_element, + elements, + sizeof(struct pipe_vertex_element) * count); + r300->vertex_element_count = count; + + if (r300->draw) { + draw_flush(r300->draw); + draw_set_vertex_elements(r300->draw, count, elements); + } } static void* r300_create_vs_state(struct pipe_context* pipe, @@ -634,9 +958,6 @@ static void* r300_create_vs_state(struct pipe_context* pipe, tgsi_scan_shader(shader->tokens, &vs->info); - /* Appease Draw. */ - vs->draw = draw_create_vertex_shader(r300->draw, shader); - return (void*)vs; } else { return draw_create_vertex_shader(r300->draw, shader); @@ -647,8 +968,6 @@ static void r300_bind_vs_state(struct pipe_context* pipe, void* shader) { struct r300_context* r300 = r300_context(pipe); - draw_flush(r300->draw); - if (r300_screen(pipe->screen)->caps->has_tcl) { struct r300_vertex_shader* vs = (struct r300_vertex_shader*)shader; @@ -659,10 +978,16 @@ static void r300_bind_vs_state(struct pipe_context* pipe, void* shader) r300_translate_vertex_shader(r300, vs); } - draw_bind_vertex_shader(r300->draw, vs->draw); r300->vs = vs; - r300->dirty_state |= R300_NEW_VERTEX_SHADER; + if (r300->fs) { + r300_vertex_shader_setup_wpos(r300); + } + + r300->dirty_state |= + R300_NEW_VERTEX_SHADER | R300_NEW_VERTEX_SHADER_CONSTANTS | + R300_NEW_VERTEX_FORMAT; } else { + draw_flush(r300->draw); draw_bind_vertex_shader(r300->draw, (struct draw_vertex_shader*)shader); } @@ -676,8 +1001,7 @@ static void r300_delete_vs_state(struct pipe_context* pipe, void* shader) struct r300_vertex_shader* vs = (struct r300_vertex_shader*)shader; rc_constants_destroy(&vs->code.constants); - draw_delete_vertex_shader(r300->draw, vs->draw); - FREE(vs->state.tokens); + FREE((void*)vs->state.tokens); FREE(shader); } else { draw_delete_vertex_shader(r300->draw, @@ -685,6 +1009,31 @@ static void r300_delete_vs_state(struct pipe_context* pipe, void* shader) } } +static void r300_set_constant_buffer(struct pipe_context *pipe, + uint shader, uint index, + const struct pipe_constant_buffer *buf) +{ + struct r300_context* r300 = r300_context(pipe); + void *mapped; + + if (buf == NULL || buf->buffer->size == 0 || + (mapped = pipe_buffer_map(pipe->screen, buf->buffer, PIPE_BUFFER_USAGE_CPU_READ)) == NULL) + { + r300->shader_constants[shader].count = 0; + return; + } + + assert((buf->buffer->size % 4 * sizeof(float)) == 0); + memcpy(r300->shader_constants[shader].constants, mapped, buf->buffer->size); + r300->shader_constants[shader].count = buf->buffer->size / (4 * sizeof(float)); + pipe_buffer_unmap(pipe->screen, buf->buffer); + + if (shader == PIPE_SHADER_VERTEX) + r300->dirty_state |= R300_NEW_VERTEX_SHADER_CONSTANTS; + else if (shader == PIPE_SHADER_FRAGMENT) + r300->dirty_state |= R300_NEW_FRAGMENT_SHADER_CONSTANTS; +} + void r300_init_state_functions(struct r300_context* r300) { r300->context.create_blend_state = r300_create_blend_state; @@ -701,8 +1050,6 @@ void r300_init_state_functions(struct r300_context* r300) r300->context.bind_depth_stencil_alpha_state = r300_bind_dsa_state; r300->context.delete_depth_stencil_alpha_state = r300_delete_dsa_state; - r300->context.set_edgeflags = r300_set_edgeflags; - r300->context.set_framebuffer_state = r300_set_framebuffer_state; r300->context.create_fs_state = r300_create_fs_state; @@ -716,10 +1063,11 @@ void r300_init_state_functions(struct r300_context* r300) r300->context.delete_rasterizer_state = r300_delete_rs_state; r300->context.create_sampler_state = r300_create_sampler_state; - r300->context.bind_sampler_states = r300_bind_sampler_states; + r300->context.bind_fragment_sampler_states = r300_bind_sampler_states; + r300->context.bind_vertex_sampler_states = r300_lacks_vertex_textures; r300->context.delete_sampler_state = r300_delete_sampler_state; - r300->context.set_sampler_textures = r300_set_sampler_textures; + r300->context.set_fragment_sampler_textures = r300_set_sampler_textures; r300->context.set_scissor_state = r300_set_scissor_state; diff --git a/src/gallium/drivers/r300/r300_state_derived.c b/src/gallium/drivers/r300/r300_state_derived.c index 02b7ab91076..22660a52d9a 100644 --- a/src/gallium/drivers/r300/r300_state_derived.c +++ b/src/gallium/drivers/r300/r300_state_derived.c @@ -1,5 +1,6 @@ /* * Copyright 2008 Corbin Simpson <[email protected]> + * Copyright 2009 Marek Olšák <[email protected]> * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -20,439 +21,540 @@ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE * USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#include "r300_state_derived.h" +#include "draw/draw_context.h" + +#include "util/u_math.h" +#include "util/u_memory.h" +#include "r300_context.h" #include "r300_fs.h" +#include "r300_screen.h" +#include "r300_shader_semantics.h" +#include "r300_state_derived.h" #include "r300_state_inlines.h" #include "r300_vs.h" /* r300_state_derived: Various bits of state which are dependent upon * currently bound CSO data. */ -/* Set up the vs_tab and routes. */ -static void r300_vs_tab_routes(struct r300_context* r300, - struct r300_vertex_format* vformat) +struct r300_shader_key { + struct r300_vertex_shader* vs; + struct r300_fragment_shader* fs; +}; + +struct r300_shader_derived_value { + struct r300_vertex_format* vformat; + struct r300_rs_block* rs_block; +}; + +unsigned r300_shader_key_hash(void* key) { + struct r300_shader_key* shader_key = (struct r300_shader_key*)key; + unsigned vs = (intptr_t)shader_key->vs; + unsigned fs = (intptr_t)shader_key->fs; + + return (vs << 16) | (fs & 0xffff); +} + +int r300_shader_key_compare(void* key1, void* key2) { + struct r300_shader_key* shader_key1 = (struct r300_shader_key*)key1; + struct r300_shader_key* shader_key2 = (struct r300_shader_key*)key2; + + return (shader_key1->vs == shader_key2->vs) && + (shader_key1->fs == shader_key2->fs); +} + +static void r300_draw_emit_attrib(struct r300_context* r300, + enum attrib_emit emit, + enum interp_mode interp, + int index) { - struct r300_screen* r300screen = r300_screen(r300->context.screen); - struct vertex_info* vinfo = &vformat->vinfo; - int* tab = vformat->vs_tab; - boolean pos = FALSE, psize = FALSE, fog = FALSE; - int i, texs = 0, cols = 0; - struct tgsi_shader_info* info; + struct tgsi_shader_info* info = &r300->vs->info; + int output; - if (r300screen->caps->has_tcl) { - /* Use vertex shader to determine required routes. */ - info = &r300->vs->info; + output = draw_find_shader_output(r300->draw, + info->output_semantic_name[index], + info->output_semantic_index[index]); + draw_emit_vertex_attr(&r300->vertex_info->vinfo, emit, interp, output); +} + +static void r300_draw_emit_all_attribs(struct r300_context* r300) +{ + struct r300_shader_semantics* vs_outputs = &r300->vs->outputs; + int i, gen_count; + + /* Position. */ + if (vs_outputs->pos != ATTR_UNUSED) { + r300_draw_emit_attrib(r300, EMIT_4F, INTERP_PERSPECTIVE, + vs_outputs->pos); } else { - /* Use fragment shader to determine required routes. */ - info = &r300->fs->info; + assert(0); } - assert(info->num_inputs <= 16); - - if (!r300screen->caps->has_tcl || !r300->rs_state->enable_vte) - { - for (i = 0; i < info->num_inputs; i++) { - switch (r300->vs->code.inputs[i]) { - case TGSI_SEMANTIC_POSITION: - pos = TRUE; - tab[i] = 0; - break; - case TGSI_SEMANTIC_COLOR: - tab[i] = 2 + cols; - cols++; - break; - case TGSI_SEMANTIC_PSIZE: - assert(psize == FALSE); - psize = TRUE; - tab[i] = 15; - break; - case TGSI_SEMANTIC_FOG: - assert(fog == FALSE); - fog = TRUE; - /* Fall through */ - case TGSI_SEMANTIC_GENERIC: - tab[i] = 6 + texs; - texs++; - break; - default: - debug_printf("r300: Unknown vertex input %d\n", - info->input_semantic_name[i]); - break; - } - } + /* Point size. */ + if (vs_outputs->psize != ATTR_UNUSED) { + r300_draw_emit_attrib(r300, EMIT_1F_PSIZE, INTERP_POS, + vs_outputs->psize); } - else - { - /* Just copy vert attribs over as-is. */ - for (i = 0; i < info->num_inputs; i++) { - tab[i] = i; - } - for (i = 0; i < info->num_outputs; i++) { - switch (info->output_semantic_name[i]) { - case TGSI_SEMANTIC_POSITION: - pos = TRUE; - break; - case TGSI_SEMANTIC_COLOR: - cols++; - break; - case TGSI_SEMANTIC_PSIZE: - psize = TRUE; - break; - case TGSI_SEMANTIC_FOG: - fog = TRUE; - /* Fall through */ - case TGSI_SEMANTIC_GENERIC: - texs++; - break; - default: - debug_printf("r300: Unknown vertex output %d\n", - info->output_semantic_name[i]); - break; - } + /* Colors. */ + for (i = 0; i < ATTR_COLOR_COUNT; i++) { + if (vs_outputs->color[i] != ATTR_UNUSED) { + r300_draw_emit_attrib(r300, EMIT_4F, INTERP_LINEAR, + vs_outputs->color[i]); } } - /* XXX magic */ - assert(texs <= 8); + /* XXX Back-face colors. */ - /* Do the actual vertex_info setup. - * - * vertex_info has four uints of hardware-specific data in it. - * vinfo.hwfmt[0] is R300_VAP_VTX_STATE_CNTL - * vinfo.hwfmt[1] is R300_VAP_VSM_VTX_ASSM - * vinfo.hwfmt[2] is R300_VAP_OUTPUT_VTX_FMT_0 - * vinfo.hwfmt[3] is R300_VAP_OUTPUT_VTX_FMT_1 */ - - vinfo->hwfmt[0] = 0x5555; /* XXX this is classic Mesa bonghits */ - - /* We need to add vertex position attribute only for SW TCL case, - * for HW TCL case it could be generated by vertex shader */ - if (!pos && !r300screen->caps->has_tcl) { - debug_printf("r300: Forcing vertex position attribute emit...\n"); - /* Make room for the position attribute - * at the beginning of the tab. */ - for (i = 15; i > 0; i--) { - tab[i] = tab[i-1]; + /* Texture coordinates. */ + gen_count = 0; + for (i = 0; i < ATTR_GENERIC_COUNT; i++) { + if (vs_outputs->generic[i] != ATTR_UNUSED) { + r300_draw_emit_attrib(r300, EMIT_4F, INTERP_PERSPECTIVE, + vs_outputs->generic[i]); + gen_count++; } - tab[0] = 0; - } - draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_PERSPECTIVE, - draw_find_vs_output(r300->draw, TGSI_SEMANTIC_POSITION, 0)); - vinfo->hwfmt[1] |= R300_INPUT_CNTL_POS; - vinfo->hwfmt[2] |= R300_VAP_OUTPUT_VTX_FMT_0__POS_PRESENT; - - if (psize) { - draw_emit_vertex_attr(vinfo, EMIT_1F_PSIZE, INTERP_POS, - draw_find_vs_output(r300->draw, TGSI_SEMANTIC_PSIZE, 0)); - vinfo->hwfmt[2] |= R300_VAP_OUTPUT_VTX_FMT_0__PT_SIZE_PRESENT; } - for (i = 0; i < cols; i++) { - draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_LINEAR, - draw_find_vs_output(r300->draw, TGSI_SEMANTIC_COLOR, i)); - vinfo->hwfmt[1] |= R300_INPUT_CNTL_COLOR; - vinfo->hwfmt[2] |= (R300_VAP_OUTPUT_VTX_FMT_0__COLOR_0_PRESENT << i); + /* Fog coordinates. */ + if (vs_outputs->fog != ATTR_UNUSED) { + r300_draw_emit_attrib(r300, EMIT_4F, INTERP_PERSPECTIVE, + vs_outputs->fog); + gen_count++; } - /* Init i right here, increment it if fog is enabled. - * This gets around a double-increment problem. */ - i = 0; + /* XXX magic */ + assert(gen_count <= 8); +} - if (fog) { - i++; - draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_PERSPECTIVE, - draw_find_vs_output(r300->draw, TGSI_SEMANTIC_FOG, 0)); - vinfo->hwfmt[1] |= (R300_INPUT_CNTL_TC0 << i); - vinfo->hwfmt[3] |= (4 << (3 * i)); +/* Update the PSC tables. */ +static void r300_vertex_psc(struct r300_context* r300) +{ + struct r300_vertex_info *vformat = r300->vertex_info; + uint16_t type, swizzle; + enum pipe_format format; + unsigned i; + int identity[16] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; + int* stream_tab; + + /* If TCL is bypassed, map vertex streams to equivalent VS output + * locations. */ + if (r300->rs_state->enable_vte) { + stream_tab = identity; + } else { + stream_tab = r300->vs->stream_loc_notcl; } - for (; i < texs; i++) { - draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_PERSPECTIVE, - draw_find_vs_output(r300->draw, TGSI_SEMANTIC_GENERIC, i)); - vinfo->hwfmt[1] |= (R300_INPUT_CNTL_TC0 << i); - vinfo->hwfmt[3] |= (4 << (3 * i)); - } + /* Vertex shaders have no semantics on their inputs, + * so PSC should just route stuff based on the vertex elements, + * and not on attrib information. */ + DBG(r300, DBG_DRAW, "r300: vs expects %d attribs, routing %d elements" + " in psc\n", + r300->vs->info.num_inputs, + r300->vertex_element_count); - /* Handle the case where the vertex shader will be generating some of - * the attribs based on its inputs. */ - if (r300screen->caps->has_tcl && - info->num_inputs < info->num_outputs) { - vinfo->num_attribs = info->num_inputs; + for (i = 0; i < r300->vertex_element_count; i++) { + format = r300->vertex_element[i].src_format; + + type = r300_translate_vertex_data_type(format) | + (stream_tab[i] << R300_DST_VEC_LOC_SHIFT); + swizzle = r300_translate_vertex_data_swizzle(format); + + if (i & 1) { + vformat->vap_prog_stream_cntl[i >> 1] |= type << 16; + vformat->vap_prog_stream_cntl_ext[i >> 1] |= swizzle << 16; + } else { + vformat->vap_prog_stream_cntl[i >> 1] |= type; + vformat->vap_prog_stream_cntl_ext[i >> 1] |= swizzle; + } } - draw_compute_vertex_size(vinfo); + assert(i <= 15); + + /* Set the last vector in the PSC. */ + if (i) { + i -= 1; + } + vformat->vap_prog_stream_cntl[i >> 1] |= + (R300_LAST_VEC << (i & 1 ? 16 : 0)); } -/* Update the PSC tables. */ -static void r300_vertex_psc(struct r300_context* r300, - struct r300_vertex_format* vformat) +/* Update the PSC tables for SW TCL, using Draw. */ +static void r300_swtcl_vertex_psc(struct r300_context* r300) { - struct r300_screen* r300screen = r300_screen(r300->context.screen); + struct r300_vertex_info *vformat = r300->vertex_info; struct vertex_info* vinfo = &vformat->vinfo; - int* tab = vformat->vs_tab; - uint32_t temp; - int i, attrib_count; - - /* Vertex shaders have no semantics on their inputs, - * so PSC should just route stuff based on their info, - * and not on attrib information. */ - if (r300screen->caps->has_tcl) { - attrib_count = r300->vs->info.num_inputs; - DBG(r300, DBG_DRAW, "r300: routing %d attribs in psc for vs\n", - attrib_count); - } else { - attrib_count = vinfo->num_attribs; - DBG(r300, DBG_DRAW, "r300: attrib count: %d\n", attrib_count); - for (i = 0; i < attrib_count; i++) { - DBG(r300, DBG_DRAW, "r300: attrib: offset %d, interp %d, size %d," - " tab %d\n", vinfo->attrib[i].src_index, - vinfo->attrib[i].interp_mode, vinfo->attrib[i].emit, - tab[i]); - } + uint16_t type, swizzle; + enum pipe_format format; + unsigned i, attrib_count; + int* vs_output_tab = r300->vs->stream_loc_notcl; + + /* For each Draw attribute, route it to the fragment shader according + * to the vs_output_tab. */ + attrib_count = vinfo->num_attribs; + DBG(r300, DBG_DRAW, "r300: attrib count: %d\n", attrib_count); + for (i = 0; i < attrib_count; i++) { + DBG(r300, DBG_DRAW, "r300: attrib: offset %d, interp %d, size %d," + " vs_output_tab %d\n", vinfo->attrib[i].src_index, + vinfo->attrib[i].interp_mode, vinfo->attrib[i].emit, + vs_output_tab[i]); } for (i = 0; i < attrib_count; i++) { - /* Make sure we have a proper destination for our attribute */ - assert(tab[i] != -1); + /* Make sure we have a proper destination for our attribute. */ + assert(vs_output_tab[i] != -1); - /* Add the attribute to the PSC table. */ - temp = r300screen->caps->has_tcl ? - R300_DATA_TYPE_FLOAT_4 : - translate_vertex_data_type(vinfo->attrib[i].emit); - temp |= tab[i] << R300_DST_VEC_LOC_SHIFT; + format = draw_translate_vinfo_format(vinfo->attrib[i].emit); - if (i & 1) { - vformat->vap_prog_stream_cntl[i >> 1] &= 0x0000ffff; - vformat->vap_prog_stream_cntl[i >> 1] |= temp << 16; + /* Obtain the type of data in this attribute. */ + type = r300_translate_vertex_data_type(format) | + vs_output_tab[i] << R300_DST_VEC_LOC_SHIFT; - vformat->vap_prog_stream_cntl_ext[i >> 1] |= - (R300_VAP_SWIZZLE_XYZW << 16); - } else { - vformat->vap_prog_stream_cntl[i >> 1] &= 0xffff0000; - vformat->vap_prog_stream_cntl[i >> 1] |= temp << 0; + /* Obtain the swizzle for this attribute. Note that the default + * swizzle in the hardware is not XYZW! */ + swizzle = r300_translate_vertex_data_swizzle(format); - vformat->vap_prog_stream_cntl_ext[i >> 1] |= - (R300_VAP_SWIZZLE_XYZW << 0); + /* Add the attribute to the PSC table. */ + if (i & 1) { + vformat->vap_prog_stream_cntl[i >> 1] |= type << 16; + vformat->vap_prog_stream_cntl_ext[i >> 1] |= swizzle << 16; + } else { + vformat->vap_prog_stream_cntl[i >> 1] |= type; + vformat->vap_prog_stream_cntl_ext[i >> 1] |= swizzle; } } /* Set the last vector in the PSC. */ - i--; + if (i) { + i -= 1; + } vformat->vap_prog_stream_cntl[i >> 1] |= (R300_LAST_VEC << (i & 1 ? 16 : 0)); } -/* Update the vertex format. */ -static void r300_update_vertex_format(struct r300_context* r300) +static void r300_rs_col(struct r300_rs_block* rs, int id, int ptr, + boolean swizzle_0001) { - struct r300_vertex_format vformat; - int i; - - memset(&vformat, 0, sizeof(struct r300_vertex_format)); - for (i = 0; i < 16; i++) { - vformat.vs_tab[i] = -1; - vformat.fs_tab[i] = -1; + rs->ip[id] |= R300_RS_COL_PTR(ptr); + if (swizzle_0001) { + rs->ip[id] |= R300_RS_COL_FMT(R300_RS_COL_FMT_0001); + } else { + rs->ip[id] |= R300_RS_COL_FMT(R300_RS_COL_FMT_RGBA); } + rs->inst[id] |= R300_RS_INST_COL_ID(id); +} - r300_vs_tab_routes(r300, &vformat); - - r300_vertex_psc(r300, &vformat); +static void r300_rs_col_write(struct r300_rs_block* rs, int id, int fp_offset) +{ + rs->inst[id] |= R300_RS_INST_COL_CN_WRITE | + R300_RS_INST_COL_ADDR(fp_offset); +} - if (memcmp(&r300->vertex_info, &vformat, - sizeof(struct r300_vertex_format))) { - memcpy(&r300->vertex_info, &vformat, - sizeof(struct r300_vertex_format)); - r300->dirty_state |= R300_NEW_VERTEX_FORMAT; +static void r300_rs_tex(struct r300_rs_block* rs, int id, int ptr, + boolean swizzle_X001) +{ + if (swizzle_X001) { + rs->ip[id] |= R300_RS_TEX_PTR(ptr*4) | + R300_RS_SEL_S(R300_RS_SEL_C0) | + R300_RS_SEL_T(R300_RS_SEL_K0) | + R300_RS_SEL_R(R300_RS_SEL_K0) | + R300_RS_SEL_Q(R300_RS_SEL_K1); + } else { + rs->ip[id] |= R300_RS_TEX_PTR(ptr*4) | + R300_RS_SEL_S(R300_RS_SEL_C0) | + R300_RS_SEL_T(R300_RS_SEL_C1) | + R300_RS_SEL_R(R300_RS_SEL_C2) | + R300_RS_SEL_Q(R300_RS_SEL_C3); } + rs->inst[id] |= R300_RS_INST_TEX_ID(id); } -/* Set up the mappings from GB to US, for RS block. */ -static void r300_update_fs_tab(struct r300_context* r300) +static void r300_rs_tex_write(struct r300_rs_block* rs, int id, int fp_offset) { - struct r300_vertex_format* vformat = &r300->vertex_info; - struct tgsi_shader_info* info = &r300->fs->info; - int i, cols = 0, texs = 0, cols_emitted = 0; - int* tab = vformat->fs_tab; + rs->inst[id] |= R300_RS_INST_TEX_CN_WRITE | + R300_RS_INST_TEX_ADDR(fp_offset); +} - for (i = 0; i < 16; i++) { - tab[i] = -1; +static void r500_rs_col(struct r300_rs_block* rs, int id, int ptr, + boolean swizzle_0001) +{ + rs->ip[id] |= R500_RS_COL_PTR(ptr); + if (swizzle_0001) { + rs->ip[id] |= R500_RS_COL_FMT(R300_RS_COL_FMT_0001); + } else { + rs->ip[id] |= R500_RS_COL_FMT(R300_RS_COL_FMT_RGBA); } + rs->inst[id] |= R500_RS_INST_COL_ID(id); +} - assert(info->num_inputs <= 16); - for (i = 0; i < info->num_inputs; i++) { - switch (info->input_semantic_name[i]) { - case TGSI_SEMANTIC_COLOR: - tab[i] = INTERP_LINEAR; - cols++; - break; - case TGSI_SEMANTIC_POSITION: - case TGSI_SEMANTIC_PSIZE: - debug_printf("r300: Implementation error: Can't use " - "pos attribs in fragshader yet!\n"); - /* Pass through for now */ - case TGSI_SEMANTIC_FOG: - case TGSI_SEMANTIC_GENERIC: - tab[i] = INTERP_PERSPECTIVE; - break; - default: - debug_printf("r300: Unknown vertex input %d\n", - info->input_semantic_name[i]); - break; - } - } +static void r500_rs_col_write(struct r300_rs_block* rs, int id, int fp_offset) +{ + rs->inst[id] |= R500_RS_INST_COL_CN_WRITE | + R500_RS_INST_COL_ADDR(fp_offset); +} - /* Now that we know where everything is... */ - DBG(r300, DBG_DRAW, "r300: fp input count: %d\n", info->num_inputs); - for (i = 0; i < info->num_inputs; i++) { - switch (tab[i]) { - case INTERP_LINEAR: - DBG(r300, DBG_DRAW, "r300: attrib: " - "stack offset %d, color, tab %d\n", - i, cols_emitted); - tab[i] = cols_emitted; - cols_emitted++; - break; - case INTERP_PERSPECTIVE: - DBG(r300, DBG_DRAW, "r300: attrib: " - "stack offset %d, texcoord, tab %d\n", - i, cols + texs); - tab[i] = cols + texs; - texs++; - break; - case -1: - debug_printf("r300: Implementation error: Bad fp interp!\n"); - default: - break; - } +static void r500_rs_tex(struct r300_rs_block* rs, int id, int ptr, + boolean swizzle_X001) +{ + int rs_tex_comp = ptr*4; + + if (swizzle_X001) { + rs->ip[id] |= R500_RS_SEL_S(rs_tex_comp) | + R500_RS_SEL_T(R500_RS_IP_PTR_K0) | + R500_RS_SEL_R(R500_RS_IP_PTR_K0) | + R500_RS_SEL_Q(R500_RS_IP_PTR_K1); + } else { + rs->ip[id] |= R500_RS_SEL_S(rs_tex_comp) | + R500_RS_SEL_T(rs_tex_comp + 1) | + R500_RS_SEL_R(rs_tex_comp + 2) | + R500_RS_SEL_Q(rs_tex_comp + 3); } + rs->inst[id] |= R500_RS_INST_TEX_ID(id); +} +static void r500_rs_tex_write(struct r300_rs_block* rs, int id, int fp_offset) +{ + rs->inst[id] |= R500_RS_INST_TEX_CN_WRITE | + R500_RS_INST_TEX_ADDR(fp_offset); } -/* Set up the RS block. This is the part of the chipset that actually does - * the rasterization of vertices into fragments. This is also the part of the - * chipset that locks up if any part of it is even slightly wrong. */ -static void r300_update_rs_block(struct r300_context* r300) +/* Set up the RS block. + * + * This is the part of the chipset that actually does the rasterization + * of vertices into fragments. This is also the part of the chipset that + * locks up if any part of it is even slightly wrong. */ +static void r300_update_rs_block(struct r300_context* r300, + struct r300_shader_semantics* vs_outputs, + struct r300_shader_semantics* fs_inputs) { struct r300_rs_block* rs = r300->rs_block; - struct tgsi_shader_info* info = &r300->fs->info; - int* tab = r300->vertex_info.fs_tab; - int col_count = 0, fp_offset = 0, i, tex_count = 0; - int rs_tex_comp = 0; - memset(rs, 0, sizeof(struct r300_rs_block)); + int i, col_count = 0, tex_count = 0, fp_offset = 0; + void (*rX00_rs_col)(struct r300_rs_block*, int, int, boolean); + void (*rX00_rs_col_write)(struct r300_rs_block*, int, int); + void (*rX00_rs_tex)(struct r300_rs_block*, int, int, boolean); + void (*rX00_rs_tex_write)(struct r300_rs_block*, int, int); + boolean any_bcolor_used = vs_outputs->bcolor[0] != ATTR_UNUSED || + vs_outputs->bcolor[1] != ATTR_UNUSED; if (r300_screen(r300->context.screen)->caps->is_r500) { - for (i = 0; i < info->num_inputs; i++) { - assert(tab[i] != -1); - switch (info->input_semantic_name[i]) { - case TGSI_SEMANTIC_COLOR: - rs->ip[col_count] |= - R500_RS_COL_PTR(col_count) | - R500_RS_COL_FMT(R300_RS_COL_FMT_RGBA); - col_count++; - break; - case TGSI_SEMANTIC_GENERIC: - rs->ip[tex_count] |= - R500_RS_SEL_S(rs_tex_comp) | - R500_RS_SEL_T(rs_tex_comp + 1) | - R500_RS_SEL_R(rs_tex_comp + 2) | - R500_RS_SEL_Q(rs_tex_comp + 3); - tex_count++; - rs_tex_comp += 4; - break; - default: - break; - } - } + rX00_rs_col = r500_rs_col; + rX00_rs_col_write = r500_rs_col_write; + rX00_rs_tex = r500_rs_tex; + rX00_rs_tex_write = r500_rs_tex_write; + } else { + rX00_rs_col = r300_rs_col; + rX00_rs_col_write = r300_rs_col_write; + rX00_rs_tex = r300_rs_tex; + rX00_rs_tex_write = r300_rs_tex_write; + } - /* Rasterize at least one color, or bad things happen. */ - if ((col_count == 0) && (tex_count == 0)) { - rs->ip[0] |= R500_RS_COL_FMT(R300_RS_COL_FMT_0001); + /* Rasterize colors. */ + for (i = 0; i < ATTR_COLOR_COUNT; i++) { + if (vs_outputs->color[i] != ATTR_UNUSED || any_bcolor_used) { + /* Always rasterize if it's written by the VS, + * otherwise it locks up. */ + rX00_rs_col(rs, col_count, i, FALSE); + + /* Write it to the FS input register if it's used by the FS. */ + if (fs_inputs->color[i] != ATTR_UNUSED) { + rX00_rs_col_write(rs, col_count, fp_offset); + fp_offset++; + } col_count++; + } else { + /* Skip the FS input register, leave it uninitialized. */ + /* If we try to set it to (0,0,0,1), it will lock up. */ + if (fs_inputs->color[i] != ATTR_UNUSED) { + fp_offset++; + } } + } - for (i = 0; i < tex_count; i++) { - rs->inst[i] |= R500_RS_INST_TEX_ID(i) | - R500_RS_INST_TEX_CN_WRITE | R500_RS_INST_TEX_ADDR(fp_offset); - fp_offset++; + /* Rasterize texture coordinates. */ + for (i = 0; i < ATTR_GENERIC_COUNT; i++) { + if (vs_outputs->generic[i] != ATTR_UNUSED) { + /* Always rasterize if it's written by the VS, + * otherwise it locks up. */ + rX00_rs_tex(rs, tex_count, tex_count, FALSE); + + /* Write it to the FS input register if it's used by the FS. */ + if (fs_inputs->generic[i] != ATTR_UNUSED) { + rX00_rs_tex_write(rs, tex_count, fp_offset); + fp_offset++; + } + tex_count++; + } else { + /* Skip the FS input register, leave it uninitialized. */ + /* If we try to set it to (0,0,0,1), it will lock up. */ + if (fs_inputs->generic[i] != ATTR_UNUSED) { + fp_offset++; + } } + } - for (i = 0; i < col_count; i++) { - rs->inst[i] |= R500_RS_INST_COL_ID(i) | - R500_RS_INST_COL_CN_WRITE | R500_RS_INST_COL_ADDR(fp_offset); + /* Rasterize fog coordinates. */ + if (vs_outputs->fog != ATTR_UNUSED) { + /* Always rasterize if it's written by the VS, + * otherwise it locks up. */ + rX00_rs_tex(rs, tex_count, tex_count, TRUE); + + /* Write it to the FS input register if it's used by the FS. */ + if (fs_inputs->fog != ATTR_UNUSED) { + rX00_rs_tex_write(rs, tex_count, fp_offset); fp_offset++; } + tex_count++; } else { - for (i = 0; i < info->num_inputs; i++) { - assert(tab[i] != -1); - switch (info->input_semantic_name[i]) { - case TGSI_SEMANTIC_COLOR: - rs->ip[col_count] |= - R300_RS_COL_PTR(col_count) | - R300_RS_COL_FMT(R300_RS_COL_FMT_RGBA); - col_count++; - break; - case TGSI_SEMANTIC_GENERIC: - rs->ip[tex_count] |= - R300_RS_TEX_PTR(rs_tex_comp) | - R300_RS_SEL_S(R300_RS_SEL_C0) | - R300_RS_SEL_T(R300_RS_SEL_C1) | - R300_RS_SEL_R(R300_RS_SEL_C2) | - R300_RS_SEL_Q(R300_RS_SEL_C3); - tex_count++; - rs_tex_comp+=4; - break; - default: - break; - } + /* Skip the FS input register, leave it uninitialized. */ + /* If we try to set it to (0,0,0,1), it will lock up. */ + if (fs_inputs->fog != ATTR_UNUSED) { + fp_offset++; } + } - if (col_count == 0) { - rs->ip[0] |= R300_RS_COL_FMT(R300_RS_COL_FMT_0001); - } + /* Rasterize WPOS. */ + /* If the FS doesn't need it, it's not written by the VS. */ + if (fs_inputs->wpos != ATTR_UNUSED) { + rX00_rs_tex(rs, tex_count, tex_count, FALSE); + rX00_rs_tex_write(rs, tex_count, fp_offset); - if (tex_count == 0) { - rs->ip[0] |= - R300_RS_SEL_S(R300_RS_SEL_K0) | - R300_RS_SEL_T(R300_RS_SEL_K0) | - R300_RS_SEL_R(R300_RS_SEL_K0) | - R300_RS_SEL_Q(R300_RS_SEL_K1); - } + fp_offset++; + tex_count++; + } - /* Rasterize at least one color, or bad things happen. */ - if ((col_count == 0) && (tex_count == 0)) { - col_count++; - } + /* Rasterize at least one color, or bad things happen. */ + if (col_count == 0 && tex_count == 0) { + rX00_rs_col(rs, 0, 0, TRUE); + col_count++; + } - for (i = 0; i < tex_count; i++) { - rs->inst[i] |= R300_RS_INST_TEX_ID(i) | - R300_RS_INST_TEX_CN_WRITE | R300_RS_INST_TEX_ADDR(fp_offset); - fp_offset++; - } + rs->count = (tex_count*4) | (col_count << R300_IC_COUNT_SHIFT) | + R300_HIRES_EN; - for (i = 0; i < col_count; i++) { - rs->inst[i] |= R300_RS_INST_COL_ID(i) | - R300_RS_INST_COL_CN_WRITE | R300_RS_INST_COL_ADDR(fp_offset); - fp_offset++; - } + rs->inst_count = MAX3(col_count - 1, tex_count - 1, 0); +} + +/* Update the vertex format. */ +static void r300_update_derived_shader_state(struct r300_context* r300) +{ + struct r300_screen* r300screen = r300_screen(r300->context.screen); + + /* + struct r300_shader_key* key; + struct r300_shader_derived_value* value; + key = CALLOC_STRUCT(r300_shader_key); + key->vs = r300->vs; + key->fs = r300->fs; + + value = (struct r300_shader_derived_value*) + util_hash_table_get(r300->shader_hash_table, (void*)key); + if (value) { + //vformat = value->vformat; + rs_block = value->rs_block; + + FREE(key); + } else { + rs_block = CALLOC_STRUCT(r300_rs_block); + value = CALLOC_STRUCT(r300_shader_derived_value); + + r300_update_rs_block(r300, rs_block); + + //value->vformat = vformat; + value->rs_block = rs_block; + util_hash_table_set(r300->shader_hash_table, + (void*)key, (void*)value); + } */ + + /* Reset structures */ + memset(r300->rs_block, 0, sizeof(struct r300_rs_block)); + memset(r300->vertex_info, 0, sizeof(struct r300_vertex_info)); + memcpy(r300->vertex_info->vinfo.hwfmt, r300->vs->hwfmt, sizeof(uint)*4); + + r300_update_rs_block(r300, &r300->vs->outputs, &r300->fs->inputs); + + if (r300screen->caps->has_tcl) { + r300_vertex_psc(r300); + } else { + r300_draw_emit_all_attribs(r300); + draw_compute_vertex_size(&r300->vertex_info->vinfo); + r300_swtcl_vertex_psc(r300); } - rs->count = (rs_tex_comp) | (col_count << R300_IC_COUNT_SHIFT) | - R300_HIRES_EN; + r300->dirty_state |= R300_NEW_RS_BLOCK; +} + +static boolean r300_dsa_writes_depth_stencil(struct r300_dsa_state* dsa) +{ + /* We are interested only in the cases when a new depth or stencil value + * can be written and changed. */ + + /* 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)); +} + +static boolean r300_dsa_alpha_test_enabled(struct r300_dsa_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; +} - rs->inst_count = MAX2(MAX2(col_count - 1, tex_count - 1), 0); +static void r300_update_ztop(struct r300_context* r300) +{ + r300->ztop_state.z_buffer_top = R300_ZTOP_ENABLE; + + /* This is important enough that I felt it warranted a comment. + * + * According to the docs, these are the conditions where ZTOP must be + * disabled: + * 1) Alpha testing enabled + * 2) Texture kill instructions in fragment shader + * 3) Chroma key culling enabled + * 4) W-buffering enabled + * + * The docs claim that for the first three cases, if no ZS writes happen, + * then ZTOP can be used. + * + * (3) will never apply since we do not support chroma-keyed operations. + * (4) will need to be re-examined (and this comment updated) if/when + * Hyper-Z becomes supported. + * + * Additionally, the following conditions require disabled ZTOP: + * 5) Depth writes in fragment shader + * 6) Outstanding occlusion queries + * + * ~C. + */ + + /* ZS writes */ + if (r300_dsa_writes_depth_stencil(r300->dsa_state) && + (r300_dsa_alpha_test_enabled(r300->dsa_state) || /* (1) */ + r300->fs->info.uses_kill)) { /* (2) */ + r300->ztop_state.z_buffer_top = R300_ZTOP_DISABLE; + } else if (r300_fragment_shader_writes_depth(r300->fs)) { /* (5) */ + r300->ztop_state.z_buffer_top = R300_ZTOP_DISABLE; + } else if (r300->query_current) { /* (6) */ + r300->ztop_state.z_buffer_top = R300_ZTOP_DISABLE; + } } void r300_update_derived_state(struct r300_context* r300) { if (r300->dirty_state & - (R300_NEW_FRAGMENT_SHADER | R300_NEW_VERTEX_SHADER)) { - r300_update_vertex_format(r300); + (R300_NEW_FRAGMENT_SHADER | R300_NEW_VERTEX_SHADER | + R300_NEW_VERTEX_FORMAT)) { + r300_update_derived_shader_state(r300); } - if (r300->dirty_state & R300_NEW_VERTEX_FORMAT) { - r300_update_fs_tab(r300); - r300_update_rs_block(r300); + if (r300->dirty_state & + (R300_NEW_DSA | R300_NEW_FRAGMENT_SHADER | R300_NEW_QUERY)) { + r300_update_ztop(r300); } } diff --git a/src/gallium/drivers/r300/r300_state_derived.h b/src/gallium/drivers/r300/r300_state_derived.h index 71a4a47b003..05ad535e2de 100644 --- a/src/gallium/drivers/r300/r300_state_derived.h +++ b/src/gallium/drivers/r300/r300_state_derived.h @@ -25,6 +25,10 @@ struct r300_context; +unsigned r300_shader_key_hash(void* key); + +int r300_shader_key_compare(void* key1, void* key2); + void r300_update_derived_state(struct r300_context* r300); #endif /* R300_STATE_DERIVED_H */ diff --git a/src/gallium/drivers/r300/r300_state_inlines.h b/src/gallium/drivers/r300/r300_state_inlines.h index 88eb66b79e7..35be00e1b01 100644 --- a/src/gallium/drivers/r300/r300_state_inlines.h +++ b/src/gallium/drivers/r300/r300_state_inlines.h @@ -24,8 +24,12 @@ #ifndef R300_STATE_INLINES_H #define R300_STATE_INLINES_H +#include "draw/draw_vertex.h" + #include "pipe/p_format.h" +#include "util/u_format.h" + #include "r300_reg.h" /* Some maths. These should probably find their way to u_math, if needed. */ @@ -51,6 +55,7 @@ static INLINE uint32_t r300_translate_blend_function(int blend_func) return R300_COMB_FCN_MAX; default: debug_printf("r300: Unknown blend function %d\n", blend_func); + assert(0); break; } return 0; @@ -98,6 +103,7 @@ static INLINE uint32_t r300_translate_blend_factor(int blend_fact) case PIPE_BLENDFACTOR_INV_SRC1_ALPHA: */ default: debug_printf("r300: Unknown blend factor %d\n", blend_fact); + assert(0); break; } return 0; @@ -127,6 +133,7 @@ static INLINE uint32_t r300_translate_depth_stencil_function(int zs_func) default: debug_printf("r300: Unknown depth/stencil function %d\n", zs_func); + assert(0); break; } return 0; @@ -153,6 +160,7 @@ static INLINE uint32_t r300_translate_stencil_op(int s_op) return R300_ZS_INVERT; default: debug_printf("r300: Unknown stencil op %d", s_op); + assert(0); break; } return 0; @@ -179,11 +187,48 @@ static INLINE uint32_t r300_translate_alpha_function(int alpha_func) return R300_FG_ALPHA_FUNC_ALWAYS; default: debug_printf("r300: Unknown alpha function %d", alpha_func); + assert(0); break; } return 0; } +static INLINE uint32_t +r300_translate_polygon_mode_front(unsigned mode) { + switch (mode) + { + case PIPE_POLYGON_MODE_FILL: + return R300_GA_POLY_MODE_FRONT_PTYPE_TRI; + case PIPE_POLYGON_MODE_LINE: + return R300_GA_POLY_MODE_FRONT_PTYPE_LINE; + case PIPE_POLYGON_MODE_POINT: + return R300_GA_POLY_MODE_FRONT_PTYPE_POINT; + + default: + debug_printf("r300: Bad polygon mode %i in %s\n", mode, + __FUNCTION__); + return R300_GA_POLY_MODE_FRONT_PTYPE_TRI; + } +} + +static INLINE uint32_t +r300_translate_polygon_mode_back(unsigned mode) { + switch (mode) + { + case PIPE_POLYGON_MODE_FILL: + return R300_GA_POLY_MODE_BACK_PTYPE_TRI; + case PIPE_POLYGON_MODE_LINE: + return R300_GA_POLY_MODE_BACK_PTYPE_LINE; + case PIPE_POLYGON_MODE_POINT: + return R300_GA_POLY_MODE_BACK_PTYPE_POINT; + + default: + debug_printf("r300: Bad polygon mode %i in %s\n", mode, + __FUNCTION__); + return R300_GA_POLY_MODE_BACK_PTYPE_TRI; + } +} + /* Texture sampler state. */ static INLINE uint32_t r300_translate_wrap(int wrap) @@ -207,40 +252,42 @@ static INLINE uint32_t r300_translate_wrap(int wrap) return R300_TX_CLAMP_TO_EDGE | R300_TX_MIRRORED; default: debug_printf("r300: Unknown texture wrap %d", wrap); + assert(0); return 0; } } -static INLINE uint32_t r300_translate_tex_filters(int min, int mag, int mip) +static INLINE uint32_t r300_translate_tex_filters(int min, int mag, int mip, + int is_anisotropic) { uint32_t retval = 0; - switch (min) { + if (is_anisotropic) + retval |= R300_TX_MIN_FILTER_ANISO | R300_TX_MAG_FILTER_ANISO; + else { + switch (min) { case PIPE_TEX_FILTER_NEAREST: retval |= R300_TX_MIN_FILTER_NEAREST; break; case PIPE_TEX_FILTER_LINEAR: retval |= R300_TX_MIN_FILTER_LINEAR; break; - case PIPE_TEX_FILTER_ANISO: - retval |= R300_TX_MIN_FILTER_ANISO; - break; default: debug_printf("r300: Unknown texture filter %d\n", min); + assert(0); break; - } - switch (mag) { + } + switch (mag) { case PIPE_TEX_FILTER_NEAREST: retval |= R300_TX_MAG_FILTER_NEAREST; break; case PIPE_TEX_FILTER_LINEAR: retval |= R300_TX_MAG_FILTER_LINEAR; break; - case PIPE_TEX_FILTER_ANISO: - retval |= R300_TX_MAG_FILTER_ANISO; - break; default: debug_printf("r300: Unknown texture filter %d\n", mag); + assert(0); break; + } } switch (mip) { case PIPE_TEX_MIPFILTER_NONE: @@ -254,6 +301,7 @@ static INLINE uint32_t r300_translate_tex_filters(int min, int mag, int mip) break; default: debug_printf("r300: Unknown texture filter %d\n", mip); + assert(0); break; } @@ -277,6 +325,8 @@ static INLINE uint32_t r300_anisotropy(float max_aniso) /* Buffer formats. */ +/* Colorbuffer formats. This is the unswizzled format of the RB3D block's + * output. For the swizzling of the targets, check the shader's format. */ static INLINE uint32_t r300_translate_colorformat(enum pipe_format format) { switch (format) { @@ -295,7 +345,6 @@ static INLINE uint32_t r300_translate_colorformat(enum pipe_format format) case PIPE_FORMAT_X8R8G8B8_UNORM: case PIPE_FORMAT_R8G8B8A8_UNORM: case PIPE_FORMAT_R8G8B8X8_UNORM: - case PIPE_FORMAT_Z24S8_UNORM: return R300_COLOR_FORMAT_ARGB8888; /* XXX Not in pipe_format case PIPE_FORMAT_A32R32G32B32: @@ -312,17 +361,21 @@ static INLINE uint32_t r300_translate_colorformat(enum pipe_format format) debug_printf("r300: Implementation error: " "Got unsupported color format %s in %s\n", pf_name(format), __FUNCTION__); + assert(0); break; } return 0; } +/* Depthbuffer and stencilbuffer. Thankfully, we only support two flavors. */ static INLINE uint32_t r300_translate_zsformat(enum pipe_format format) { switch (format) { /* 16-bit depth, no stencil */ case PIPE_FORMAT_Z16_UNORM: return R300_DEPTHFORMAT_16BIT_INT_Z; + /* 24-bit depth, ignored stencil */ + case PIPE_FORMAT_Z24X8_UNORM: /* 24-bit depth, 8-bit stencil */ case PIPE_FORMAT_Z24S8_UNORM: return R300_DEPTHFORMAT_24BIT_INT_Z_8BIT_STENCIL; @@ -330,18 +383,22 @@ static INLINE uint32_t r300_translate_zsformat(enum pipe_format format) debug_printf("r300: Implementation error: " "Got unsupported ZS format %s in %s\n", pf_name(format), __FUNCTION__); + assert(0); break; } return 0; } -/* Translate pipe_format into US_OUT_FMT. +/* Shader output formats. This is essentially the swizzle from the shader + * to the RB3D block. + * * Note that formats are stored from C3 to C0. */ static INLINE uint32_t r300_translate_out_fmt(enum pipe_format format) { switch (format) { case PIPE_FORMAT_A8R8G8B8_UNORM: case PIPE_FORMAT_X8R8G8B8_UNORM: + /* XXX */ case PIPE_FORMAT_Z24S8_UNORM: return R300_US_OUT_FMT_C4_8 | R300_C0_SEL_B | R300_C1_SEL_G | @@ -355,6 +412,7 @@ static INLINE uint32_t r300_translate_out_fmt(enum pipe_format format) debug_printf("r300: Implementation error: " "Got unsupported output format %s in %s\n", pf_name(format), __FUNCTION__); + assert(0); return R300_US_OUT_FMT_UNUSED; } return 0; @@ -381,32 +439,119 @@ static INLINE uint32_t r300_translate_gb_pipes(int pipe_count) return 0; } -static INLINE uint32_t translate_vertex_data_type(int type) { - switch (type) { - case EMIT_1F: - case EMIT_1F_PSIZE: - return R300_DATA_TYPE_FLOAT_1; - break; - case EMIT_2F: - return R300_DATA_TYPE_FLOAT_2; - break; - case EMIT_3F: - return R300_DATA_TYPE_FLOAT_3; - break; - case EMIT_4F: - return R300_DATA_TYPE_FLOAT_4; +/* Utility function to count the number of components in RGBAZS formats. + * XXX should go to util or p_format.h */ +static INLINE unsigned pf_component_count(enum pipe_format format) { + unsigned count = 0; + + if (util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_RGB, 0)) { + count++; + } + if (util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_RGB, 1)) { + count++; + } + if (util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_RGB, 2)) { + count++; + } + if (util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_RGB, 3)) { + count++; + } + if (util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_ZS, 0)) { + count++; + } + if (util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_ZS, 1)) { + count++; + } + + return count; +} + +/* Translate pipe_formats into PSC vertex types. */ +static INLINE uint16_t +r300_translate_vertex_data_type(enum pipe_format format) { + uint32_t result = 0; + const struct util_format_description *desc; + unsigned components = pf_component_count(format); + + desc = util_format_description(format); + + if (desc->layout != UTIL_FORMAT_LAYOUT_ARITH && + desc->layout != UTIL_FORMAT_LAYOUT_ARRAY) { + debug_printf("r300: Bad format %s in %s:%d\n", pf_name(format), + __FUNCTION__, __LINE__); + assert(0); + } + + switch (desc->channel[0].type) { + /* Half-floats, floats, doubles */ + case UTIL_FORMAT_TYPE_FLOAT: + switch (util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_RGB, 0)) { + case 32: + result = R300_DATA_TYPE_FLOAT_1 + (components - 1); + break; + default: + debug_printf("r300: Bad format %s in %s:%d\n", + pf_name(format), __FUNCTION__, __LINE__); + assert(0); + } break; - case EMIT_4UB: - return R300_DATA_TYPE_BYTE; + /* Unsigned ints */ + case UTIL_FORMAT_TYPE_UNSIGNED: + /* Signed ints */ + case UTIL_FORMAT_TYPE_SIGNED: + switch (util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_RGB, 0)) { + case 8: + result = R300_DATA_TYPE_BYTE; + break; + case 16: + if (components > 2) { + result = R300_DATA_TYPE_SHORT_4; + } else { + result = R300_DATA_TYPE_SHORT_2; + } + break; + default: + debug_printf("r300: Bad format %s in %s:%d\n", + pf_name(format), __FUNCTION__, __LINE__); + debug_printf("r300: util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_RGB, 0) == %d\n", + util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_RGB, 0)); + assert(0); + } break; default: - debug_printf("r300: Implementation error: " - "Bad vertex data type!\n"); + debug_printf("r300: Bad format %s in %s:%d\n", + pf_name(format), __FUNCTION__, __LINE__); assert(0); - break; } - return 0; + if (desc->channel[0].type == UTIL_FORMAT_TYPE_SIGNED) { + result |= R300_SIGNED; + } + if (desc->channel[0].normalized) { + result |= R300_NORMALIZE; + } + + return result; +} + +static INLINE uint16_t +r300_translate_vertex_data_swizzle(enum pipe_format format) { + const struct util_format_description *desc = util_format_description(format); + + assert(format); + + if (desc->layout != UTIL_FORMAT_LAYOUT_ARITH && + desc->layout != UTIL_FORMAT_LAYOUT_ARRAY) { + debug_printf("r300: Bad format %s in %s:%d\n", + pf_name(format), __FUNCTION__, __LINE__); + return 0; + } + + return ((desc->swizzle[0] << R300_SWIZZLE_SELECT_X_SHIFT) | + (desc->swizzle[1] << R300_SWIZZLE_SELECT_Y_SHIFT) | + (desc->swizzle[2] << R300_SWIZZLE_SELECT_Z_SHIFT) | + (desc->swizzle[3] << R300_SWIZZLE_SELECT_W_SHIFT) | + (0xf << R300_WRITE_ENA_SHIFT)); } #endif /* R300_STATE_INLINES_H */ diff --git a/src/gallium/drivers/r300/r300_state_invariant.c b/src/gallium/drivers/r300/r300_state_invariant.c index 3865730d635..f25f3ca217d 100644 --- a/src/gallium/drivers/r300/r300_state_invariant.c +++ b/src/gallium/drivers/r300/r300_state_invariant.c @@ -21,9 +21,12 @@ * 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" - struct pipe_viewport_state r300_viewport_identity = { .scale = {1.0, 1.0, 1.0, 1.0}, .translate = {0.0, 0.0, 0.0, 0.0}, @@ -40,7 +43,7 @@ void r300_emit_invariant_state(struct r300_context* r300) struct r300_capabilities* caps = r300_screen(r300->context.screen)->caps; CS_LOCALS(r300); - BEGIN_CS(24 + (caps->has_tcl ? 2: 0)); + BEGIN_CS(16 + (caps->has_tcl ? 2: 0)); /*** Graphics Backend (GB) ***/ /* Various GB enables */ @@ -63,13 +66,8 @@ void r300_emit_invariant_state(struct r300_context* r300) 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); - OUT_CS_REG(R300_FG_DEPTH_SRC, 0x0); - OUT_CS_REG(R300_US_W_FMT, 0x0); /*** VAP ***/ - /* Max and min vertex index clamp. */ - OUT_CS_REG(R300_VAP_VF_MIN_VTX_INDX, 0x0); - OUT_CS_REG(R300_VAP_VF_MAX_VTX_INDX, 0xffffff); /* Sign/normalize control */ OUT_CS_REG(R300_VAP_PSC_SGN_NORM_CNTL, R300_SGN_NORM_NO_ZERO); /* TCL-only stuff */ @@ -81,15 +79,11 @@ void r300_emit_invariant_state(struct r300_context* r300) END_CS; /* XXX unsorted stuff from surface_fill */ - BEGIN_CS(64 + (caps->has_tcl ? 5 : 0) + (caps->is_r500 ? 4 : 0)); - /* Flush PVS. */ - OUT_CS_REG(R300_VAP_PVS_STATE_FLUSH_REG, 0x0); + BEGIN_CS(44 + (caps->has_tcl ? 7 : 0) + (caps->is_r500 ? 4 : 0)); - OUT_CS_REG(R300_SE_VTE_CNTL, R300_VPORT_X_SCALE_ENA | - R300_VPORT_X_OFFSET_ENA | R300_VPORT_Y_SCALE_ENA | - R300_VPORT_Y_OFFSET_ENA | R300_VPORT_Z_SCALE_ENA | - R300_VPORT_Z_OFFSET_ENA | R300_VTX_W0_FMT); if (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); @@ -111,7 +105,6 @@ void r300_emit_invariant_state(struct r300_context* r300) /* 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_POLY_MODE, 0x00000000); OUT_CS_REG(R300_GA_ROUND_MODE, 0x00000001); OUT_CS_REG(R300_GA_OFFSET, 0x00000000); OUT_CS_REG(R300_GA_FOG_SCALE, 0x3DBF1412); @@ -121,22 +114,15 @@ void r300_emit_invariant_state(struct r300_context* r300) 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_CCTL, 0x00000000); - OUT_CS_REG(RB3D_COLOR_CHANNEL_MASK, 0x0000000F); OUT_CS_REG(R300_RB3D_AARESOLVE_CTL, 0x00000000); if (caps->is_r500) { - OUT_CS_REG(R500_RB3D_DISCARD_SRC_PIXEL_LTE_THRESHOLD, 0x00000000); - OUT_CS_REG(R500_RB3D_DISCARD_SRC_PIXEL_GTE_THRESHOLD, 0xFFFFFFFF); + 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_FORMAT, 0x00000002); - OUT_CS_REG(R300_ZB_ZCACHE_CTLSTAT, 0x00000003); 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); - OUT_CS_REG(R300_VAP_VTX_STATE_CNTL, 0x1); - OUT_CS_REG(R300_VAP_VSM_VTX_ASSM, 0x405); - OUT_CS_REG(R300_SE_VTE_CNTL, 0x0000043F); /* XXX */ OUT_CS_REG(R300_SC_CLIP_RULE, 0xaaaa); diff --git a/src/gallium/drivers/r300/r300_state_invariant.h b/src/gallium/drivers/r300/r300_state_invariant.h index 5bea6779fe5..05cff0d6dfe 100644 --- a/src/gallium/drivers/r300/r300_state_invariant.h +++ b/src/gallium/drivers/r300/r300_state_invariant.h @@ -23,11 +23,7 @@ #ifndef R300_STATE_INVARIANT_H #define R300_STATE_INVARIANT_H -#include "r300_chipset.h" -#include "r300_context.h" -#include "r300_cs.h" -#include "r300_reg.h" -#include "r300_state_inlines.h" +struct r300_context; void r300_emit_invariant_state(struct r300_context* r300); diff --git a/src/gallium/drivers/r300/r300_surface.c b/src/gallium/drivers/r300/r300_surface.c deleted file mode 100644 index cc6288cb519..00000000000 --- a/src/gallium/drivers/r300/r300_surface.c +++ /dev/null @@ -1,372 +0,0 @@ -/* - * Copyright 2008 Corbin Simpson <[email protected]> - * Joakim Sindholt <[email protected]> - * - * 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_surface.h" - -static void r300_surface_setup(struct r300_context* r300, - struct r300_texture* dest, - unsigned x, unsigned y, - unsigned w, unsigned h) -{ - struct r300_capabilities* caps = r300_screen(r300->context.screen)->caps; - unsigned pixpitch = r300_texture_get_stride(dest, 0) / dest->tex.block.size; - CS_LOCALS(r300); - - r300_emit_blend_state(r300, &blend_clear_state); - r300_emit_blend_color_state(r300, &blend_color_clear_state); - r300_emit_dsa_state(r300, &dsa_clear_state); - r300_emit_rs_state(r300, &rs_clear_state); - - BEGIN_CS(26); - - /* Viewport setup */ - OUT_CS_REG_SEQ(R300_SE_VPORT_XSCALE, 6); - OUT_CS_32F((float)w); - OUT_CS_32F((float)x); - OUT_CS_32F((float)h); - OUT_CS_32F((float)y); - OUT_CS_32F(1.0); - OUT_CS_32F(0.0); - - OUT_CS_REG(R300_VAP_VTE_CNTL, R300_VPORT_X_SCALE_ENA | - R300_VPORT_X_OFFSET_ENA | - R300_VPORT_Y_SCALE_ENA | - R300_VPORT_Y_OFFSET_ENA | - R300_VTX_XY_FMT | R300_VTX_Z_FMT); - - /* Pixel scissors. */ - OUT_CS_REG_SEQ(R300_SC_SCISSORS_TL, 2); - if (caps->is_r500) { - OUT_CS((x << R300_SCISSORS_X_SHIFT) | (y << R300_SCISSORS_Y_SHIFT)); - OUT_CS(((w - 1) << R300_SCISSORS_X_SHIFT) | ((h - 1) << R300_SCISSORS_Y_SHIFT)); - } else { - /* Non-R500 chipsets have an offset of 1440 in their scissors. */ - OUT_CS(((x + 1440) << R300_SCISSORS_X_SHIFT) | - ((y + 1440) << R300_SCISSORS_Y_SHIFT)); - OUT_CS((((w - 1) + 1440) << R300_SCISSORS_X_SHIFT) | - (((h - 1) + 1440) << R300_SCISSORS_Y_SHIFT)); - } - - /* Flush colorbuffer and blend caches. */ - OUT_CS_REG(R300_RB3D_DSTCACHE_CTLSTAT, - R300_RB3D_DSTCACHE_CTLSTAT_DC_FLUSH_FLUSH_DIRTY_3D | - R300_RB3D_DSTCACHE_CTLSTAT_DC_FINISH_SIGNAL); - OUT_CS_REG(R300_ZB_ZCACHE_CTLSTAT, - R300_ZB_ZCACHE_CTLSTAT_ZC_FLUSH_FLUSH_AND_FREE | - R300_ZB_ZCACHE_CTLSTAT_ZC_FREE_FREE); - - /* Setup colorbuffer. */ - OUT_CS_REG_SEQ(R300_RB3D_COLOROFFSET0, 1); - OUT_CS_RELOC(dest->buffer, 0, 0, RADEON_GEM_DOMAIN_VRAM, 0); - OUT_CS_REG_SEQ(R300_RB3D_COLORPITCH0, 1); - OUT_CS_RELOC(dest->buffer, pixpitch | - r300_translate_colorformat(dest->tex.format), 0, - RADEON_GEM_DOMAIN_VRAM, 0); - OUT_CS_REG(RB3D_COLOR_CHANNEL_MASK, 0xf); - - END_CS; -} - -/* Provides pipe_context's "surface_fill". Commonly used for clearing - * buffers. */ -static void r300_surface_fill(struct pipe_context* pipe, - struct pipe_surface* dest, - unsigned x, unsigned y, - unsigned w, unsigned h, - unsigned color) -{ - int i; - float r, g, b, a, depth; - struct r300_context* r300 = r300_context(pipe); - struct r300_capabilities* caps = r300_screen(pipe->screen)->caps; - struct r300_texture* tex = (struct r300_texture*)dest->texture; - unsigned pixpitch = r300_texture_get_stride(tex, 0) / tex->tex.block.size; - boolean invalid = FALSE; - CS_LOCALS(r300); - - a = (float)((color >> 24) & 0xff) / 255.0f; - r = (float)((color >> 16) & 0xff) / 255.0f; - g = (float)((color >> 8) & 0xff) / 255.0f; - b = (float)((color >> 0) & 0xff) / 255.0f; - debug_printf("r300: Filling surface %p at (%d,%d)," - " dimensions %dx%d (pixel pitch %d), color 0x%x\n", - dest, x, y, w, h, pixpitch, color); - - /* Fallback? */ - if (FALSE) { -fallback: - debug_printf("r300: Falling back on surface clear..."); - util_surface_fill(pipe, dest, x, y, w, h, color); - return; - } - - /* Make sure our target BO is okay. */ -validate: - if (!r300->winsys->add_buffer(r300->winsys, tex->buffer, - 0, RADEON_GEM_DOMAIN_VRAM)) { - r300->context.flush(&r300->context, 0, NULL); - goto validate; - } - if (!r300->winsys->validate(r300->winsys)) { - r300->context.flush(&r300->context, 0, NULL); - if (invalid) { - debug_printf("r300: Stuck in validation loop, gonna fallback."); - goto fallback; - } - invalid = TRUE; - goto validate; - } - - r300_surface_setup(r300, tex, x, y, w, h); - - /* Vertex shader setup */ - if (caps->has_tcl) { - r300_emit_vertex_program_code(r300, &r300_passthrough_vertex_shader, 0); - } else { - BEGIN_CS(4); - OUT_CS_REG(R300_VAP_CNTL_STATUS, -#ifdef PIPE_ARCH_BIG_ENDIAN - R300_VC_32BIT_SWAP | -#endif - R300_VAP_TCL_BYPASS); - OUT_CS_REG(R300_VAP_CNTL, R300_PVS_NUM_SLOTS(5) | - R300_PVS_NUM_CNTLRS(5) | - R300_PVS_NUM_FPUS(caps->num_vert_fpus) | - R300_PVS_VF_MAX_VTX_NUM(12)); - END_CS; - } - - /* Fragment shader setup */ - if (caps->is_r500) { - r500_emit_fragment_program_code(r300, &r5xx_passthrough_fragment_shader, 0); - r300_emit_rs_block_state(r300, &r5xx_rs_block_clear_state); - } else { - r300_emit_fragment_program_code(r300, &r3xx_passthrough_fragment_shader, 0); - r300_emit_rs_block_state(r300, &r3xx_rs_block_clear_state); - } - - BEGIN_CS(26); - - /* VAP stream control, mapping from input memory to PVS/RS memory */ - if (caps->has_tcl) { - OUT_CS_REG(R300_VAP_PROG_STREAM_CNTL_0, - (R300_DATA_TYPE_FLOAT_4 << R300_DATA_TYPE_0_SHIFT) | - ((R300_LAST_VEC | (1 << R300_DST_VEC_LOC_SHIFT) | - R300_DATA_TYPE_FLOAT_4) << R300_DATA_TYPE_1_SHIFT)); - } else { - OUT_CS_REG(R300_VAP_PROG_STREAM_CNTL_0, - (R300_DATA_TYPE_FLOAT_4 << R300_DATA_TYPE_0_SHIFT) | - ((R300_LAST_VEC | (2 << R300_DST_VEC_LOC_SHIFT) | - R300_DATA_TYPE_FLOAT_4) << R300_DATA_TYPE_1_SHIFT)); - } - OUT_CS_REG(R300_VAP_PROG_STREAM_CNTL_EXT_0, - (R300_VAP_SWIZZLE_XYZW << R300_SWIZZLE0_SHIFT) | - (R300_VAP_SWIZZLE_XYZW << R300_SWIZZLE1_SHIFT)); - - /* VAP format controls */ - OUT_CS_REG(R300_VAP_OUTPUT_VTX_FMT_0, - R300_VAP_OUTPUT_VTX_FMT_0__POS_PRESENT | - R300_VAP_OUTPUT_VTX_FMT_0__COLOR_0_PRESENT); - OUT_CS_REG(R300_VAP_OUTPUT_VTX_FMT_1, 0x0); - - /* Disable textures */ - OUT_CS_REG(R300_TX_ENABLE, 0x0); - - /* The size of the point we're about to draw, in sixths of pixels */ - OUT_CS_REG(R300_GA_POINT_SIZE, - ((h * 6) & R300_POINTSIZE_Y_MASK) | - ((w * 6) << R300_POINTSIZE_X_SHIFT)); - - /* Vertex size. */ - OUT_CS_REG(R300_VAP_VTX_SIZE, 0x8); - - /* Packet3 with our point vertex */ - OUT_CS_PKT3(R200_3D_DRAW_IMMD_2, 8); - OUT_CS(R300_PRIM_TYPE_POINT | R300_PRIM_WALK_RING | - (1 << R300_PRIM_NUM_VERTICES_SHIFT)); - /* Position */ - OUT_CS_32F(0.5); - OUT_CS_32F(0.5); - OUT_CS_32F(1.0); - OUT_CS_32F(1.0); - /* Color */ - OUT_CS_32F(r); - OUT_CS_32F(g); - OUT_CS_32F(b); - OUT_CS_32F(a); - - OUT_CS_REG(R300_RB3D_DSTCACHE_CTLSTAT, 0xA); - - END_CS; - - r300->dirty_hw++; -} - -static void r300_surface_copy(struct pipe_context* pipe, - struct pipe_surface* dest, - unsigned destx, unsigned desty, - struct pipe_surface* src, - unsigned srcx, unsigned srcy, - unsigned w, unsigned h) -{ - struct r300_context* r300 = r300_context(pipe); - struct r300_capabilities* caps = r300_screen(pipe->screen)->caps; - struct r300_texture* srctex = (struct r300_texture*)src->texture; - struct r300_texture* desttex = (struct r300_texture*)dest->texture; - unsigned pixpitch = r300_texture_get_stride(srctex, 0) / srctex->tex.block.size; - boolean invalid = FALSE; - float fsrcx = srcx, fsrcy = srcy, fdestx = destx, fdesty = desty; - CS_LOCALS(r300); - - debug_printf("r300: Copying surface %p at (%d,%d) to %p at (%d, %d)," - " dimensions %dx%d (pixel pitch %d)\n", - src, srcx, srcy, dest, destx, desty, w, h, pixpitch); - - if ((srctex->buffer == desttex->buffer) && - ((destx < srcx + w) || (srcx < destx + w)) && - ((desty < srcy + h) || (srcy < desty + h))) { -fallback: - debug_printf("r300: Falling back on surface_copy\n"); - util_surface_copy(pipe, FALSE, dest, destx, desty, src, - srcx, srcy, w, h); - } - - /* Add our target BOs to the list. */ -validate: - if (!r300->winsys->add_buffer(r300->winsys, srctex->buffer, - RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0)) { - r300->context.flush(&r300->context, 0, NULL); - goto validate; - } - if (!r300->winsys->add_buffer(r300->winsys, desttex->buffer, - 0, RADEON_GEM_DOMAIN_VRAM)) { - r300->context.flush(&r300->context, 0, NULL); - goto validate; - } - if (!r300->winsys->validate(r300->winsys)) { - r300->context.flush(&r300->context, 0, NULL); - if (invalid) { - debug_printf("r300: Stuck in validation loop, gonna fallback."); - goto fallback; - } - invalid = TRUE; - goto validate; - } - - r300_surface_setup(r300, desttex, destx, desty, w, h); - - /* Setup the texture. */ - r300_emit_texture(r300, &r300_sampler_copy_state, srctex, 0); - - /* Flush and enable. */ - r300_flush_textures(r300); - - /* Vertex shader setup */ - if (caps->has_tcl) { - r300_emit_vertex_program_code(r300, &r300_passthrough_vertex_shader, 0); - } else { - BEGIN_CS(4); - OUT_CS_REG(R300_VAP_CNTL_STATUS, -#ifdef PIPE_ARCH_BIG_ENDIAN - R300_VC_32BIT_SWAP | -#endif - R300_VAP_TCL_BYPASS); - OUT_CS_REG(R300_VAP_CNTL, R300_PVS_NUM_SLOTS(5) | - R300_PVS_NUM_CNTLRS(5) | - R300_PVS_NUM_FPUS(caps->num_vert_fpus) | - R300_PVS_VF_MAX_VTX_NUM(12)); - END_CS; - } - - /* Fragment shader setup */ - if (caps->is_r500) { - r500_emit_fragment_program_code(r300, &r5xx_texture_fragment_shader, 0); - r300_emit_rs_block_state(r300, &r5xx_rs_block_copy_state); - } else { - r300_emit_fragment_program_code(r300, &r3xx_texture_fragment_shader, 0); - r300_emit_rs_block_state(r300, &r3xx_rs_block_copy_state); - } - - BEGIN_CS(30); - /* VAP stream control, mapping from input memory to PVS/RS memory */ - if (caps->has_tcl) { - OUT_CS_REG(R300_VAP_PROG_STREAM_CNTL_0, - (R300_DATA_TYPE_FLOAT_2 << R300_DATA_TYPE_0_SHIFT) | - ((R300_LAST_VEC | (1 << R300_DST_VEC_LOC_SHIFT) | - R300_DATA_TYPE_FLOAT_2) << R300_DATA_TYPE_1_SHIFT)); - } else { - OUT_CS_REG(R300_VAP_PROG_STREAM_CNTL_0, - (R300_DATA_TYPE_FLOAT_2 << R300_DATA_TYPE_0_SHIFT) | - ((R300_LAST_VEC | (6 << R300_DST_VEC_LOC_SHIFT) | - R300_DATA_TYPE_FLOAT_2) << R300_DATA_TYPE_1_SHIFT)); - } - OUT_CS_REG(R300_VAP_PROG_STREAM_CNTL_EXT_0, - (R300_VAP_SWIZZLE_XYZW << R300_SWIZZLE0_SHIFT) | - (R300_VAP_SWIZZLE_XYZW << R300_SWIZZLE1_SHIFT)); - - /* VAP format controls */ - OUT_CS_REG(R300_VAP_OUTPUT_VTX_FMT_0, - R300_VAP_OUTPUT_VTX_FMT_0__POS_PRESENT); - /* Two components of texture 0 */ - OUT_CS_REG(R300_VAP_OUTPUT_VTX_FMT_1, 0x2); - - /* Vertex size. */ - OUT_CS_REG(R300_VAP_VTX_SIZE, 0x4); - - /* Packet3 with our texcoords */ - OUT_CS_PKT3(R200_3D_DRAW_IMMD_2, 16); - OUT_CS(R300_PRIM_TYPE_QUADS | R300_PRIM_WALK_RING | - (4 << R300_PRIM_NUM_VERTICES_SHIFT)); - /* (x , y ) */ - OUT_CS_32F(fdestx / dest->width); - OUT_CS_32F(fdesty / dest->height); - OUT_CS_32F(fsrcx / src->width); - OUT_CS_32F(fsrcy / src->height); - /* (x , y + h) */ - OUT_CS_32F(fdestx / dest->width); - OUT_CS_32F((fdesty + h) / dest->height); - OUT_CS_32F(fsrcx / src->width); - OUT_CS_32F((fsrcy + h) / src->height); - /* (x + w, y + h) */ - OUT_CS_32F((fdestx + w) / dest->width); - OUT_CS_32F((fdesty + h) / dest->height); - OUT_CS_32F((fsrcx + w) / src->width); - OUT_CS_32F((fsrcy + h) / src->height); - /* (x + w, y ) */ - OUT_CS_32F((fdestx + w) / dest->width); - OUT_CS_32F(fdesty / dest->height); - OUT_CS_32F((fsrcx + w) / src->width); - OUT_CS_32F(fsrcy / src->height); - - OUT_CS_REG(R300_RB3D_DSTCACHE_CTLSTAT, 0xA); - - END_CS; - - r300->dirty_hw++; -} - -void r300_init_surface_functions(struct r300_context* r300) -{ - r300->context.surface_fill = r300_surface_fill; - r300->context.surface_copy = r300_surface_copy; -} diff --git a/src/gallium/drivers/r300/r300_surface.h b/src/gallium/drivers/r300/r300_surface.h deleted file mode 100644 index f9e98b2ec9c..00000000000 --- a/src/gallium/drivers/r300/r300_surface.h +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright 2008 Corbin Simpson <[email protected]> - * - * 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_SURFACE_H -#define R300_SURFACE_H - -#include "pipe/p_context.h" -#include "pipe/p_screen.h" - -#include "util/u_rect.h" - -#include "r300_context.h" -#include "r300_cs.h" -#include "r300_emit.h" -#include "r300_fs.h" -#include "r300_vs.h" -#include "r300_state_inlines.h" - -static struct r300_blend_state blend_clear_state = { - .blend_control = 0x0, - .alpha_blend_control = 0x0, - .rop = 0x0, - .dither = 0x0, -}; - -static struct r300_blend_color_state blend_color_clear_state = { - .blend_color = 0x0, - .blend_color_red_alpha = 0x0, - .blend_color_green_blue = 0x0, -}; - -static struct r300_dsa_state dsa_clear_state = { - .alpha_function = 0x0, - .alpha_reference = 0x0, - .z_buffer_control = 0x0, - .z_stencil_control = 0x0, - .stencil_ref_mask = R300_STENCILWRITEMASK_MASK, - .z_buffer_top = R300_ZTOP_ENABLE, - .stencil_ref_bf = 0x0, -}; - -static struct r300_rs_state rs_clear_state = { - .point_minmax = 0x36000006, - .line_control = 0x00030006, - .depth_scale_front = 0x0, - .depth_offset_front = 0x0, - .depth_scale_back = 0x0, - .depth_offset_back = 0x0, - .polygon_offset_enable = 0x0, - .cull_mode = 0x0, - .line_stipple_config = 0x3BAAAAAB, - .line_stipple_value = 0x0, - .color_control = R300_SHADE_MODEL_FLAT, -}; - -static struct r300_rs_block r3xx_rs_block_clear_state = { - .ip[0] = R500_RS_SEL_S(R300_RS_SEL_C0) | - R500_RS_SEL_T(R300_RS_SEL_C0) | - R500_RS_SEL_R(R300_RS_SEL_C0) | - R500_RS_SEL_Q(R300_RS_SEL_K1), - .inst[0] = R300_RS_INST_COL_CN_WRITE, - .count = R300_IT_COUNT(0) | R300_IC_COUNT(1) | R300_HIRES_EN, - .inst_count = 0, -}; - -static struct r300_rs_block r5xx_rs_block_clear_state = { - .ip[0] = R500_RS_SEL_S(R500_RS_IP_PTR_K0) | - R500_RS_SEL_T(R500_RS_IP_PTR_K0) | - R500_RS_SEL_R(R500_RS_IP_PTR_K0) | - R500_RS_SEL_Q(R500_RS_IP_PTR_K1), - .inst[0] = R500_RS_INST_COL_CN_WRITE, - .count = R300_IT_COUNT(0) | R300_IC_COUNT(1) | R300_HIRES_EN, - .inst_count = 0, -}; - -/* The following state is used for surface_copy only. */ - -static struct r300_rs_block r3xx_rs_block_copy_state = { - .ip[0] = R500_RS_SEL_S(R300_RS_SEL_K0) | - R500_RS_SEL_T(R300_RS_SEL_K0) | - R500_RS_SEL_R(R300_RS_SEL_K0) | - R500_RS_SEL_Q(R300_RS_SEL_K1), - .inst[0] = R300_RS_INST_COL_CN_WRITE, - .count = R300_IT_COUNT(2) | R300_IC_COUNT(0) | R300_HIRES_EN, - .inst_count = R300_RS_TX_OFFSET(0), -}; - -static struct r300_rs_block r5xx_rs_block_copy_state = { - .ip[0] = R500_RS_SEL_S(0) | - R500_RS_SEL_T(1) | - R500_RS_SEL_R(R500_RS_IP_PTR_K0) | - R500_RS_SEL_Q(R500_RS_IP_PTR_K1), - .inst[0] = R500_RS_INST_TEX_CN_WRITE, - .count = R300_IT_COUNT(2) | R300_IC_COUNT(0) | R300_HIRES_EN, - .inst_count = R300_RS_TX_OFFSET(0), -}; - -static struct r300_sampler_state r300_sampler_copy_state = { - .filter0 = R300_TX_WRAP_S(R300_TX_CLAMP) | - R300_TX_WRAP_T(R300_TX_CLAMP) | - R300_TX_MAG_FILTER_NEAREST | - R300_TX_MIN_FILTER_NEAREST, -}; - -#endif /* R300_SURFACE_H */ diff --git a/src/gallium/drivers/r300/r300_texture.c b/src/gallium/drivers/r300/r300_texture.c index ce60ded7caf..9a96206a4dc 100644 --- a/src/gallium/drivers/r300/r300_texture.c +++ b/src/gallium/drivers/r300/r300_texture.c @@ -20,41 +20,75 @@ * 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_math.h" +#include "util/u_memory.h" + +#include "r300_context.h" #include "r300_texture.h" +#include "r300_screen.h" -static void r300_setup_texture_state(struct r300_texture* tex) +static void r300_setup_texture_state(struct r300_texture* tex, boolean is_r500) { struct r300_texture_state* state = &tex->state; struct pipe_texture *pt = &tex->tex; - state->format0 = R300_TX_WIDTH((pt->width[0] - 1) & 0x7ff) | - R300_TX_HEIGHT((pt->height[0] - 1) & 0x7ff) | - R300_TX_DEPTH(util_logbase2(pt->depth[0]) & 0xf) | - R300_TX_NUM_LEVELS(pt->last_level) | - R300_TX_PITCH_EN; + state->format0 = R300_TX_WIDTH((pt->width0 - 1) & 0x7ff) | + R300_TX_HEIGHT((pt->height0 - 1) & 0x7ff); + + if (tex->is_npot) { + /* rectangles love this */ + state->format0 |= R300_TX_PITCH_EN; + state->format2 = (tex->pitch[0] - 1) & 0x1fff; + } else { + /* power of two textures (3D, mipmaps, and no pitch) */ + state->format0 |= R300_TX_DEPTH(util_logbase2(pt->depth0) & 0xf); + } - /* XXX */ state->format1 = r300_translate_texformat(pt->format); if (pt->target == PIPE_TEXTURE_CUBE) { - state->format1 |= R300_TX_FORMAT_CUBIC_MAP; + state->format1 |= R300_TX_FORMAT_CUBIC_MAP; } if (pt->target == PIPE_TEXTURE_3D) { - state->format1 |= R300_TX_FORMAT_3D; + state->format1 |= R300_TX_FORMAT_3D; } - state->format2 = (r300_texture_get_stride(tex, 0) / pt->block.size) - 1; - - /* Assume (somewhat foolishly) that oversized textures will - * not be permitted by the state tracker. */ - if (pt->width[0] > 2048) { - state->format2 |= R500_TXWIDTH_BIT11; - } - if (pt->height[0] > 2048) { - state->format2 |= R500_TXHEIGHT_BIT11; + /* large textures on r500 */ + if (is_r500) + { + if (pt->width0 > 2048) { + state->format2 |= R500_TXWIDTH_BIT11; + } + if (pt->height0 > 2048) { + state->format2 |= R500_TXHEIGHT_BIT11; + } } + assert(is_r500 || (pt->width0 <= 2048 && pt->height0 <= 2048)); debug_printf("r300: Set texture state (%dx%d, %d levels)\n", - pt->width[0], pt->height[0], pt->last_level); + pt->width0, pt->height0, pt->last_level); +} + +unsigned r300_texture_get_offset(struct r300_texture* tex, unsigned level, + unsigned zslice, unsigned face) +{ + unsigned offset = tex->offset[level]; + + switch (tex->tex.target) { + case PIPE_TEXTURE_3D: + assert(face == 0); + return offset + zslice * tex->layer_size[level]; + + case PIPE_TEXTURE_CUBE: + assert(zslice == 0); + return offset + face * tex->layer_size[level]; + + default: + assert(zslice == 0 && face == 0); + return offset; + } } /** @@ -67,47 +101,49 @@ unsigned r300_texture_get_stride(struct r300_texture* tex, unsigned level) return tex->stride_override; if (level > tex->tex.last_level) { - debug_printf("%s: level (%u) > last_level (%u)\n", __FUNCTION__, level, tex->tex.last_level); + debug_printf("%s: level (%u) > last_level (%u)\n", __FUNCTION__, + level, tex->tex.last_level); return 0; } - return align(pf_get_stride(&tex->tex.block, tex->tex.width[level]), 32); + return align(util_format_get_stride(tex->tex.format, u_minify(tex->tex.width0, level)), 32); } static void r300_setup_miptree(struct r300_texture* tex) { struct pipe_texture* base = &tex->tex; - int stride, size; + int stride, size, layer_size; int i; for (i = 0; i <= base->last_level; i++) { - if (i > 0) { - base->width[i] = minify(base->width[i-1]); - base->height[i] = minify(base->height[i-1]); - base->depth[i] = minify(base->depth[i-1]); - } + unsigned nblocksy = util_format_get_nblocksy(base->format, u_minify(base->height0, i)); - base->nblocksx[i] = pf_get_nblocksx(&base->block, base->width[i]); - base->nblocksy[i] = pf_get_nblocksy(&base->block, base->height[i]); - - /* Radeons enjoy things in multiples of 64. - * - * XXX - * POT, uncompressed, unmippmapped textures can be aligned to 32, - * instead of 64. */ stride = r300_texture_get_stride(tex, i); - size = stride * base->nblocksy[i] * base->depth[i]; + layer_size = stride * nblocksy; + + if (base->target == PIPE_TEXTURE_CUBE) + size = layer_size * 6; + else + size = layer_size * u_minify(base->depth0, i); tex->offset[i] = align(tex->size, 32); tex->size = tex->offset[i] + size; + tex->layer_size[i] = layer_size; + tex->pitch[i] = stride / util_format_get_blocksize(base->format); debug_printf("r300: Texture miptree: Level %d " "(%dx%dx%d px, pitch %d bytes)\n", - i, base->width[i], base->height[i], base->depth[i], - stride); + i, u_minify(base->width0, i), u_minify(base->height0, i), + u_minify(base->depth0, i), stride); } } +static void r300_setup_flags(struct r300_texture* tex) +{ + tex->is_npot = !util_is_power_of_two(tex->tex.width0) || + !util_is_power_of_two(tex->tex.height0); +} + /* Create a new texture. */ static struct pipe_texture* r300_texture_create(struct pipe_screen* screen, @@ -123,9 +159,9 @@ static struct pipe_texture* pipe_reference_init(&tex->tex.reference, 1); tex->tex.screen = screen; + r300_setup_flags(tex); r300_setup_miptree(tex); - - r300_setup_texture_state(tex); + r300_setup_texture_state(tex, r300_screen(screen)->caps->is_r500); tex->buffer = screen->buffer_create(screen, 1024, PIPE_BUFFER_USAGE_PIXEL, @@ -159,17 +195,20 @@ static struct pipe_surface* r300_get_tex_surface(struct pipe_screen* screen, struct pipe_surface* surface = CALLOC_STRUCT(pipe_surface); unsigned offset; - /* XXX this is certainly dependent on tex target */ - offset = tex->offset[level]; + offset = r300_texture_get_offset(tex, level, zslice, face); if (surface) { pipe_reference_init(&surface->reference, 1); pipe_texture_reference(&surface->texture, texture); surface->format = texture->format; - surface->width = texture->width[level]; - surface->height = texture->height[level]; + 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; } return surface; @@ -189,10 +228,10 @@ static struct pipe_texture* { struct r300_texture* tex; - /* XXX we should start doing mips now... */ + /* Support only 2D textures without mipmaps */ if (base->target != PIPE_TEXTURE_2D || - base->last_level != 0 || - base->depth[0] != 1) { + base->depth0 != 1 || + base->last_level != 0) { return NULL; } @@ -206,15 +245,64 @@ static struct pipe_texture* tex->tex.screen = screen; tex->stride_override = *stride; + tex->pitch[0] = *stride / util_format_get_blocksize(base->format); - /* XXX */ - r300_setup_texture_state(tex); + r300_setup_flags(tex); + r300_setup_texture_state(tex, r300_screen(screen)->caps->is_r500); pipe_buffer_reference(&tex->buffer, buffer); return (struct pipe_texture*)tex; } +static struct pipe_video_surface * +r300_video_surface_create(struct pipe_screen *screen, + enum pipe_video_chroma_format chroma_format, + unsigned width, unsigned height) +{ + struct r300_video_surface *r300_vsfc; + struct pipe_texture template; + + assert(screen); + assert(width && height); + + r300_vsfc = CALLOC_STRUCT(r300_video_surface); + if (!r300_vsfc) + return NULL; + + pipe_reference_init(&r300_vsfc->base.reference, 1); + r300_vsfc->base.screen = screen; + r300_vsfc->base.chroma_format = chroma_format; + r300_vsfc->base.width = width; + r300_vsfc->base.height = height; + + memset(&template, 0, sizeof(struct pipe_texture)); + template.target = PIPE_TEXTURE_2D; + template.format = PIPE_FORMAT_X8R8G8B8_UNORM; + template.last_level = 0; + template.width0 = util_next_power_of_two(width); + template.height0 = util_next_power_of_two(height); + template.depth0 = 1; + template.tex_usage = PIPE_TEXTURE_USAGE_SAMPLER | + PIPE_TEXTURE_USAGE_RENDER_TARGET; + + r300_vsfc->tex = screen->texture_create(screen, &template); + if (!r300_vsfc->tex) + { + FREE(r300_vsfc); + return NULL; + } + + return &r300_vsfc->base; +} + +static void r300_video_surface_destroy(struct pipe_video_surface *vsfc) +{ + struct r300_video_surface *r300_vsfc = r300_video_surface(vsfc); + pipe_texture_reference(&r300_vsfc->tex, NULL); + FREE(r300_vsfc); +} + void r300_init_screen_texture_functions(struct pipe_screen* screen) { screen->texture_create = r300_texture_create; @@ -222,6 +310,9 @@ void r300_init_screen_texture_functions(struct pipe_screen* screen) screen->get_tex_surface = r300_get_tex_surface; screen->tex_surface_destroy = r300_tex_surface_destroy; screen->texture_blanket = r300_texture_blanket; + + screen->video_surface_create = r300_video_surface_create; + screen->video_surface_destroy= r300_video_surface_destroy; } boolean r300_get_texture_buffer(struct pipe_texture* texture, diff --git a/src/gallium/drivers/r300/r300_texture.h b/src/gallium/drivers/r300/r300_texture.h index bd87790bc34..55ceb1a5136 100644 --- a/src/gallium/drivers/r300/r300_texture.h +++ b/src/gallium/drivers/r300/r300_texture.h @@ -23,11 +23,8 @@ #ifndef R300_TEXTURE_H #define R300_TEXTURE_H -#include "pipe/p_screen.h" +#include "pipe/p_video_state.h" -#include "util/u_math.h" - -#include "r300_context.h" #include "r300_reg.h" struct r300_texture; @@ -36,6 +33,9 @@ void r300_init_screen_texture_functions(struct pipe_screen* screen); unsigned r300_texture_get_stride(struct r300_texture* tex, unsigned level); +unsigned r300_texture_get_offset(struct r300_texture* tex, unsigned level, + unsigned zslice, unsigned face); + /* Note the signature of R300_EASY_TX_FORMAT(A, R, G, B, FORMAT)... */ static INLINE uint32_t r300_translate_texformat(enum pipe_format format) { @@ -43,6 +43,19 @@ static INLINE uint32_t r300_translate_texformat(enum pipe_format format) /* X8 */ case PIPE_FORMAT_I8_UNORM: return R300_EASY_TX_FORMAT(X, X, X, X, X8); + case PIPE_FORMAT_L8_UNORM: + return R300_EASY_TX_FORMAT(X, X, X, ONE, X8); + /* X16 */ + case PIPE_FORMAT_R16_UNORM: + return R300_EASY_TX_FORMAT(X, X, X, X, X16); + case PIPE_FORMAT_R16_SNORM: + return R300_EASY_TX_FORMAT(X, X, X, X, X16) | + R300_TX_FORMAT_SIGNED; + case PIPE_FORMAT_Z16_UNORM: + return R300_EASY_TX_FORMAT(X, X, X, X, X16); + /* Y8X8 */ + case PIPE_FORMAT_A8L8_UNORM: + return R300_EASY_TX_FORMAT(X, X, X, Y, Y8X8); /* W8Z8Y8X8 */ case PIPE_FORMAT_A8R8G8B8_UNORM: return R300_EASY_TX_FORMAT(X, Y, Z, W, W8Z8Y8X8); @@ -75,12 +88,9 @@ static INLINE uint32_t r300_translate_texformat(enum pipe_format format) R300_TX_FORMAT_YUV_TO_RGB; /* W24_FP */ case PIPE_FORMAT_Z24S8_UNORM: + case PIPE_FORMAT_Z24X8_UNORM: return R300_EASY_TX_FORMAT(X, X, X, X, W24_FP); - /* Z5_Y6_X5 */ - case PIPE_FORMAT_R16_SNORM: - return R300_EASY_TX_FORMAT(X, X, X, X, Z5Y6X5); - case PIPE_FORMAT_Z16_UNORM: - return R300_EASY_TX_FORMAT(X, X, X, X, X16); + default: debug_printf("r300: Implementation error: " "Got unsupported texture format %s in %s\n", @@ -91,6 +101,18 @@ static INLINE uint32_t r300_translate_texformat(enum pipe_format format) return 0; } +struct r300_video_surface +{ + struct pipe_video_surface base; + struct pipe_texture *tex; +}; + +static INLINE struct r300_video_surface * +r300_video_surface(struct pipe_video_surface *pvs) +{ + return (struct r300_video_surface *)pvs; +} + #ifndef R300_WINSYS_H boolean r300_get_texture_buffer(struct pipe_texture* texture, diff --git a/src/gallium/drivers/r300/r300_tgsi_to_rc.c b/src/gallium/drivers/r300/r300_tgsi_to_rc.c index 74d4fb50876..a792c2cf989 100644 --- a/src/gallium/drivers/r300/r300_tgsi_to_rc.c +++ b/src/gallium/drivers/r300/r300_tgsi_to_rc.c @@ -120,7 +120,7 @@ static unsigned translate_opcode(unsigned opcode) /* case TGSI_OPCODE_NOT: return RC_OPCODE_NOT; */ /* case TGSI_OPCODE_TRUNC: return RC_OPCODE_TRUNC; */ /* case TGSI_OPCODE_SHL: return RC_OPCODE_SHL; */ - /* case TGSI_OPCODE_SHR: return RC_OPCODE_SHR; */ + /* case TGSI_OPCODE_ISHR: return RC_OPCODE_SHR; */ /* case TGSI_OPCODE_AND: return RC_OPCODE_AND; */ /* case TGSI_OPCODE_OR: return RC_OPCODE_OR; */ /* case TGSI_OPCODE_MOD: return RC_OPCODE_MOD; */ @@ -135,10 +135,6 @@ static unsigned translate_opcode(unsigned opcode) /* case TGSI_OPCODE_BGNSUB: return RC_OPCODE_BGNSUB; */ /* case TGSI_OPCODE_ENDLOOP2: return RC_OPCODE_ENDLOOP2; */ /* case TGSI_OPCODE_ENDSUB: return RC_OPCODE_ENDSUB; */ - /* case TGSI_OPCODE_NOISE1: return RC_OPCODE_NOISE1; */ - /* case TGSI_OPCODE_NOISE2: return RC_OPCODE_NOISE2; */ - /* case TGSI_OPCODE_NOISE3: return RC_OPCODE_NOISE3; */ - /* case TGSI_OPCODE_NOISE4: return RC_OPCODE_NOISE4; */ case TGSI_OPCODE_NOP: return RC_OPCODE_NOP; /* gap */ /* case TGSI_OPCODE_NRM4: return RC_OPCODE_NRM4; */ @@ -146,7 +142,6 @@ static unsigned translate_opcode(unsigned opcode) /* case TGSI_OPCODE_IFC: return RC_OPCODE_IFC; */ /* case TGSI_OPCODE_BREAKC: return RC_OPCODE_BREAKC; */ case TGSI_OPCODE_KIL: return RC_OPCODE_KIL; - case TGSI_OPCODE_SWZ: return RC_OPCODE_SWZ; } fprintf(stderr, "Unknown opcode: %i\n", opcode); @@ -195,10 +190,10 @@ static void transform_dstreg( struct rc_dst_register * dst, struct tgsi_full_dst_register * src) { - dst->File = translate_register_file(src->DstRegister.File); - dst->Index = translate_register_index(ttr, src->DstRegister.File, src->DstRegister.Index); - dst->WriteMask = src->DstRegister.WriteMask; - dst->RelAddr = src->DstRegister.Indirect; + dst->File = translate_register_file(src->Register.File); + dst->Index = translate_register_index(ttr, src->Register.File, src->Register.Index); + dst->WriteMask = src->Register.WriteMask; + dst->RelAddr = src->Register.Indirect; } static void transform_srcreg( @@ -206,23 +201,19 @@ static void transform_srcreg( struct rc_src_register * dst, struct tgsi_full_src_register * src) { - dst->File = translate_register_file(src->SrcRegister.File); - dst->Index = translate_register_index(ttr, src->SrcRegister.File, src->SrcRegister.Index); - dst->RelAddr = src->SrcRegister.Indirect; - dst->Swizzle = tgsi_util_get_full_src_register_extswizzle(src, 0); - dst->Swizzle |= tgsi_util_get_full_src_register_extswizzle(src, 1) << 3; - dst->Swizzle |= tgsi_util_get_full_src_register_extswizzle(src, 2) << 6; - dst->Swizzle |= tgsi_util_get_full_src_register_extswizzle(src, 3) << 9; - dst->Abs = src->SrcRegisterExtMod.Absolute; - dst->Negate = - src->SrcRegisterExtSwz.NegateX | - (src->SrcRegisterExtSwz.NegateY << 1) | - (src->SrcRegisterExtSwz.NegateZ << 2) | - (src->SrcRegisterExtSwz.NegateW << 3); - dst->Negate ^= src->SrcRegister.Negate ? RC_MASK_XYZW : 0; + dst->File = translate_register_file(src->Register.File); + dst->Index = translate_register_index(ttr, src->Register.File, src->Register.Index); + dst->RelAddr = src->Register.Indirect; + dst->Swizzle = tgsi_util_get_full_src_register_swizzle(src, 0); + dst->Swizzle |= tgsi_util_get_full_src_register_swizzle(src, 1) << 3; + dst->Swizzle |= tgsi_util_get_full_src_register_swizzle(src, 2) << 6; + dst->Swizzle |= tgsi_util_get_full_src_register_swizzle(src, 3) << 9; + dst->Abs = src->Register.Absolute; + dst->Negate = src->Register.Negate ? RC_MASK_XYZW : 0; } -static void transform_texture(struct rc_instruction * dst, struct tgsi_instruction_ext_texture src) +static void transform_texture(struct rc_instruction * dst, struct tgsi_instruction_texture src, + uint32_t *shadowSamplers) { switch(src.Texture) { case TGSI_TEXTURE_1D: @@ -243,14 +234,17 @@ static void transform_texture(struct rc_instruction * dst, struct tgsi_instructi case TGSI_TEXTURE_SHADOW1D: dst->U.I.TexSrcTarget = RC_TEXTURE_1D; dst->U.I.TexShadow = 1; + *shadowSamplers |= 1 << dst->U.I.TexSrcUnit; break; case TGSI_TEXTURE_SHADOW2D: dst->U.I.TexSrcTarget = RC_TEXTURE_2D; dst->U.I.TexShadow = 1; + *shadowSamplers |= 1 << dst->U.I.TexSrcUnit; break; case TGSI_TEXTURE_SHADOWRECT: dst->U.I.TexSrcTarget = RC_TEXTURE_RECT; dst->U.I.TexShadow = 1; + *shadowSamplers |= 1 << dst->U.I.TexSrcUnit; break; } } @@ -268,17 +262,19 @@ static void transform_instruction(struct tgsi_to_rc * ttr, struct tgsi_full_inst dst->U.I.SaturateMode = translate_saturate(src->Instruction.Saturate); if (src->Instruction.NumDstRegs) - transform_dstreg(ttr, &dst->U.I.DstReg, &src->FullDstRegisters[0]); + transform_dstreg(ttr, &dst->U.I.DstReg, &src->Dst[0]); for(i = 0; i < src->Instruction.NumSrcRegs; ++i) { - if (src->FullSrcRegisters[i].SrcRegister.File == TGSI_FILE_SAMPLER) - dst->U.I.TexSrcUnit = src->FullSrcRegisters[i].SrcRegister.Index; + if (src->Src[i].Register.File == TGSI_FILE_SAMPLER) + dst->U.I.TexSrcUnit = src->Src[i].Register.Index; else - transform_srcreg(ttr, &dst->U.I.SrcReg[i], &src->FullSrcRegisters[i]); + transform_srcreg(ttr, &dst->U.I.SrcReg[i], &src->Src[i]); } /* Texturing. */ - transform_texture(dst, src->InstructionExtTexture); + if (src->Instruction.Texture) + transform_texture(dst, src->Texture, + &ttr->compiler->Program.ShadowSamplers); } static void handle_immediate(struct tgsi_to_rc * ttr, struct tgsi_full_immediate * imm) diff --git a/src/gallium/drivers/r300/r300_vs.c b/src/gallium/drivers/r300/r300_vs.c index 8460cfaf518..68aef70872e 100644 --- a/src/gallium/drivers/r300/r300_vs.c +++ b/src/gallium/drivers/r300/r300_vs.c @@ -1,5 +1,6 @@ /* * Copyright 2009 Corbin Simpson <[email protected]> + * Copyright 2009 Marek Olšák <[email protected]> * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -21,91 +22,296 @@ * USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "r300_vs.h" +#include "r300_fs.h" #include "r300_context.h" +#include "r300_screen.h" #include "r300_tgsi_to_rc.h" +#include "r300_reg.h" #include "tgsi/tgsi_dump.h" #include "tgsi/tgsi_parse.h" #include "radeon_compiler.h" +#include "util/u_math.h" -static void set_vertex_inputs_outputs(struct r300_vertex_program_compiler * c) +/* Convert info about VS output semantics into r300_shader_semantics. */ +static void r300_shader_read_vs_outputs( + struct tgsi_shader_info* info, + struct r300_shader_semantics* vs_outputs) { - struct r300_vertex_shader * vs = c->UserData; - struct tgsi_shader_info* info = &vs->info; - struct tgsi_parse_context parser; - struct tgsi_full_declaration * decl; - boolean pointsize = false; - int out_colors = 0; - int colors = 0; - int out_generic = 0; - int generic = 0; int i; + unsigned index; - /* Fill in the input mapping */ - for (i = 0; i < info->num_inputs; i++) - c->code->inputs[i] = i; + r300_shader_semantics_reset(vs_outputs); - /* Fill in the output mapping */ for (i = 0; i < info->num_outputs; i++) { + index = info->output_semantic_index[i]; + switch (info->output_semantic_name[i]) { + case TGSI_SEMANTIC_POSITION: + assert(index == 0); + vs_outputs->pos = i; + break; + case TGSI_SEMANTIC_PSIZE: - pointsize = true; + assert(index == 0); + vs_outputs->psize = i; break; + case TGSI_SEMANTIC_COLOR: - out_colors++; + assert(index <= ATTR_COLOR_COUNT); + vs_outputs->color[index] = i; break; - case TGSI_SEMANTIC_FOG: + + case TGSI_SEMANTIC_BCOLOR: + assert(index <= ATTR_COLOR_COUNT); + vs_outputs->bcolor[index] = i; + break; + case TGSI_SEMANTIC_GENERIC: - out_generic++; + assert(index <= ATTR_GENERIC_COUNT); + vs_outputs->generic[index] = i; + break; + + case TGSI_SEMANTIC_FOG: + assert(index == 0); + vs_outputs->fog = i; break; + + case TGSI_SEMANTIC_EDGEFLAG: + assert(index == 0); + fprintf(stderr, "r300 VP: cannot handle edgeflag output\n"); + assert(0); + break; + default: + assert(0); } } +} - tgsi_parse_init(&parser, vs->state.tokens); +static void r300_shader_vap_output_fmt(struct r300_vertex_shader* vs) +{ + struct r300_shader_semantics* vs_outputs = &vs->outputs; + uint32_t* hwfmt = vs->hwfmt; + int i, gen_count; + boolean any_bcolor_used = vs_outputs->bcolor[0] != ATTR_UNUSED || + vs_outputs->bcolor[1] != ATTR_UNUSED; + + /* Do the actual vertex_info setup. + * + * vertex_info has four uints of hardware-specific data in it. + * vinfo.hwfmt[0] is R300_VAP_VTX_STATE_CNTL + * vinfo.hwfmt[1] is R300_VAP_VSM_VTX_ASSM + * vinfo.hwfmt[2] is R300_VAP_OUTPUT_VTX_FMT_0 + * vinfo.hwfmt[3] is R300_VAP_OUTPUT_VTX_FMT_1 */ + + hwfmt[0] = 0x5555; /* XXX this is classic Mesa bonghits */ + + /* Position. */ + if (vs_outputs->pos != ATTR_UNUSED) { + hwfmt[1] |= R300_INPUT_CNTL_POS; + hwfmt[2] |= R300_VAP_OUTPUT_VTX_FMT_0__POS_PRESENT; + } else { + assert(0); + } - while (!tgsi_parse_end_of_tokens(&parser)) { - tgsi_parse_token(&parser); + /* Point size. */ + if (vs_outputs->psize != ATTR_UNUSED) { + hwfmt[2] |= R300_VAP_OUTPUT_VTX_FMT_0__PT_SIZE_PRESENT; + } - if (parser.FullToken.Token.Type != TGSI_TOKEN_TYPE_DECLARATION) - continue; + /* Colors. */ + for (i = 0; i < ATTR_COLOR_COUNT; i++) { + if (vs_outputs->color[i] != ATTR_UNUSED || any_bcolor_used) { + hwfmt[1] |= R300_INPUT_CNTL_COLOR; + hwfmt[2] |= R300_VAP_OUTPUT_VTX_FMT_0__COLOR_0_PRESENT << i; + } + } - decl = &parser.FullToken.FullDeclaration; + /* Back-face colors. */ + if (any_bcolor_used) { + for (i = 0; i < ATTR_COLOR_COUNT; i++) { + hwfmt[1] |= R300_INPUT_CNTL_COLOR; + hwfmt[2] |= R300_VAP_OUTPUT_VTX_FMT_0__COLOR_0_PRESENT << (2+i); + } + } - if (decl->Declaration.File != TGSI_FILE_OUTPUT) - continue; + /* Texture coordinates. */ + gen_count = 0; + for (i = 0; i < ATTR_GENERIC_COUNT; i++) { + if (vs_outputs->generic[i] != ATTR_UNUSED) { + hwfmt[1] |= (R300_INPUT_CNTL_TC0 << gen_count); + hwfmt[3] |= (4 << (3 * gen_count)); + gen_count++; + } + } - switch (decl->Semantic.SemanticName) { - case TGSI_SEMANTIC_POSITION: - c->code->outputs[decl->DeclarationRange.First] = 0; - break; - case TGSI_SEMANTIC_PSIZE: - c->code->outputs[decl->DeclarationRange.First] = 1; - break; - case TGSI_SEMANTIC_COLOR: - c->code->outputs[decl->DeclarationRange.First] = 1 + - (pointsize ? 1 : 0) + - colors++; - break; - case TGSI_SEMANTIC_FOG: - case TGSI_SEMANTIC_GENERIC: - c->code->outputs[decl->DeclarationRange.First] = 1 + - (pointsize ? 1 : 0) + - out_colors + - generic++; - break; - default: - debug_printf("r300: vs: Bad semantic declaration %d\n", - decl->Semantic.SemanticName); - break; + /* Fog coordinates. */ + if (vs_outputs->fog != ATTR_UNUSED) { + hwfmt[1] |= (R300_INPUT_CNTL_TC0 << gen_count); + hwfmt[3] |= (4 << (3 * gen_count)); + gen_count++; + } + + /* XXX magic */ + assert(gen_count <= 8); + + /* WPOS. */ + vs->wpos_tex_output = gen_count; +} + +/* Sets up stream mapping to equivalent VS outputs if TCL is bypassed + * or isn't present. */ +static void r300_stream_locations_notcl( + struct r300_shader_semantics* vs_outputs, + int* stream_loc) +{ + int i, tabi = 0, gen_count; + boolean any_bcolor_used = vs_outputs->bcolor[0] != ATTR_UNUSED || + vs_outputs->bcolor[1] != ATTR_UNUSED; + + /* Position. */ + stream_loc[tabi++] = 0; + + /* Point size. */ + if (vs_outputs->psize != ATTR_UNUSED) { + stream_loc[tabi++] = 1; + } + + /* Colors. */ + for (i = 0; i < ATTR_COLOR_COUNT; i++) { + if (vs_outputs->color[i] != ATTR_UNUSED || any_bcolor_used) { + stream_loc[tabi++] = 2 + i; + } + } + + /* Back-face colors. */ + if (any_bcolor_used) { + for (i = 0; i < ATTR_COLOR_COUNT; i++) { + stream_loc[tabi++] = 4 + i; } } - tgsi_parse_free(&parser); + /* Texture coordinates. */ + gen_count = 0; + for (i = 0; i < ATTR_GENERIC_COUNT; i++) { + if (vs_outputs->generic[i] != ATTR_UNUSED) { + assert(tabi < 16); + stream_loc[tabi++] = 6 + gen_count; + gen_count++; + } + } + + /* Fog coordinates. */ + if (vs_outputs->fog != ATTR_UNUSED) { + assert(tabi < 16); + stream_loc[tabi++] = 6 + gen_count; + gen_count++; + } + + /* WPOS. */ + if (vs_outputs->wpos != ATTR_UNUSED) { + assert(tabi < 16); + stream_loc[tabi++] = 6 + gen_count; + gen_count++; + } + + for (; tabi < 16;) { + stream_loc[tabi++] = -1; + } } +static void set_vertex_inputs_outputs(struct r300_vertex_program_compiler * c) +{ + struct r300_vertex_shader * vs = c->UserData; + struct r300_shader_semantics* outputs = &vs->outputs; + struct tgsi_shader_info* info = &vs->info; + int i, reg = 0; + boolean any_bcolor_used = outputs->bcolor[0] != ATTR_UNUSED || + outputs->bcolor[1] != ATTR_UNUSED; + + /* Fill in the input mapping */ + for (i = 0; i < info->num_inputs; i++) + c->code->inputs[i] = i; + + /* Position. */ + if (outputs->pos != ATTR_UNUSED) { + c->code->outputs[outputs->pos] = reg++; + } else { + assert(0); + } + + /* Point size. */ + if (outputs->psize != ATTR_UNUSED) { + c->code->outputs[outputs->psize] = reg++; + } + + /* If we're writing back facing colors we need to send + * four colors to make front/back face colors selection work. + * If the vertex program doesn't write all 4 colors, lets + * pretend it does by skipping output index reg so the colors + * get written into appropriate output vectors. + */ + + /* Colors. */ + for (i = 0; i < ATTR_COLOR_COUNT; i++) { + if (outputs->color[i] != ATTR_UNUSED) { + c->code->outputs[outputs->color[i]] = reg++; + } else if (any_bcolor_used) { + reg++; + } + } + + /* Back-face colors. */ + for (i = 0; i < ATTR_COLOR_COUNT; i++) { + if (outputs->bcolor[i] != ATTR_UNUSED) { + c->code->outputs[outputs->bcolor[i]] = reg++; + } else if (any_bcolor_used) { + reg++; + } + } + + /* Texture coordinates. */ + for (i = 0; i < ATTR_GENERIC_COUNT; i++) { + if (outputs->generic[i] != ATTR_UNUSED) { + c->code->outputs[outputs->generic[i]] = reg++; + } + } + + /* Fog coordinates. */ + if (outputs->fog != ATTR_UNUSED) { + c->code->outputs[outputs->fog] = reg++; + } + + /* WPOS. */ + if (outputs->wpos != ATTR_UNUSED) { + c->code->outputs[outputs->wpos] = reg++; + } +} + +static void r300_insert_wpos(struct r300_vertex_program_compiler* c, + struct r300_shader_semantics* outputs) +{ + int i, lastOutput = 0; + + /* Find the max output index. */ + lastOutput = MAX2(lastOutput, outputs->psize); + for (i = 0; i < ATTR_COLOR_COUNT; i++) { + lastOutput = MAX2(lastOutput, outputs->color[i]); + lastOutput = MAX2(lastOutput, outputs->bcolor[i]); + } + for (i = 0; i < ATTR_GENERIC_COUNT; i++) { + lastOutput = MAX2(lastOutput, outputs->generic[i]); + } + lastOutput = MAX2(lastOutput, outputs->fog); + + /* Set WPOS after the last output. */ + lastOutput++; + rc_copy_output(&c->Base, 0, lastOutput); /* out[lastOutput] = out[0]; */ + outputs->wpos = lastOutput; +} void r300_translate_vertex_shader(struct r300_context* r300, struct r300_vertex_shader* vs) @@ -113,6 +319,9 @@ void r300_translate_vertex_shader(struct r300_context* r300, struct r300_vertex_program_compiler compiler; struct tgsi_to_rc ttr; + /* Initialize. */ + r300_shader_read_vs_outputs(&vs->info, &vs->outputs); + /* Setup the compiler */ rc_init(&compiler.Base); @@ -131,13 +340,19 @@ void r300_translate_vertex_shader(struct r300_context* r300, r300_tgsi_to_rc(&ttr, vs->state.tokens); - compiler.RequiredOutputs = ~(~0 << vs->info.num_outputs); + compiler.RequiredOutputs = ~(~0 << (vs->info.num_outputs+1)); compiler.SetHwInputOutput = &set_vertex_inputs_outputs; + /* Insert the WPOS output. */ + r300_insert_wpos(&compiler, &vs->outputs); + + r300_shader_vap_output_fmt(vs); + r300_stream_locations_notcl(&vs->outputs, vs->stream_loc_notcl); + /* Invoke the compiler */ r3xx_compile_vertex_program(&compiler); if (compiler.Base.Error) { - /* Todo: Fail gracefully */ + /* XXX We should fallback using Draw. */ fprintf(stderr, "r300 VP: Compiler error\n"); abort(); } @@ -147,88 +362,29 @@ void r300_translate_vertex_shader(struct r300_context* r300, vs->translated = TRUE; } - -/* XXX get these to r300_reg */ -#define R300_PVS_DST_OPCODE(x) ((x) << 0) -# define R300_VE_DOT_PRODUCT 1 -# define R300_VE_MULTIPLY 2 -# define R300_VE_ADD 3 -# define R300_VE_MAXIMUM 7 -# define R300_VE_SET_LESS_THAN 10 -#define R300_PVS_DST_MATH_INST (1 << 6) -# define R300_ME_RECIP_DX 6 -#define R300_PVS_DST_MACRO_INST (1 << 7) -# define R300_PVS_MACRO_OP_2CLK_MADD 0 -#define R300_PVS_DST_REG_TYPE(x) ((x) << 8) -# define R300_PVS_DST_REG_TEMPORARY 0 -# define R300_PVS_DST_REG_A0 1 -# define R300_PVS_DST_REG_OUT 2 -# define R300_PVS_DST_REG_OUT_REPL_X 3 -# define R300_PVS_DST_REG_ALT_TEMPORARY 4 -# define R300_PVS_DST_REG_INPUT 5 -#define R300_PVS_DST_OFFSET(x) ((x) << 13) -#define R300_PVS_DST_WE(x) ((x) << 20) -#define R300_PVS_DST_WE_XYZW (0xf << 20) - -#define R300_PVS_SRC_REG_TYPE(x) ((x) << 0) -# define R300_PVS_SRC_REG_TEMPORARY 0 -# define R300_PVS_SRC_REG_INPUT 1 -# define R300_PVS_SRC_REG_CONSTANT 2 -# define R300_PVS_SRC_REG_ALT_TEMPORARY 3 -#define R300_PVS_SRC_OFFSET(x) ((x) << 5) -#define R300_PVS_SRC_SWIZZLE(x) ((x) << 13) -# define R300_PVS_SRC_SELECT_X 0 -# define R300_PVS_SRC_SELECT_Y 1 -# define R300_PVS_SRC_SELECT_Z 2 -# define R300_PVS_SRC_SELECT_W 3 -# define R300_PVS_SRC_SELECT_FORCE_0 4 -# define R300_PVS_SRC_SELECT_FORCE_1 5 -# define R300_PVS_SRC_SWIZZLE_XYZW \ - ((R300_PVS_SRC_SELECT_X | (R300_PVS_SRC_SELECT_Y << 3) | \ - (R300_PVS_SRC_SELECT_Z << 6) | (R300_PVS_SRC_SELECT_W << 9)) << 13) -# define R300_PVS_SRC_SWIZZLE_ZERO \ - ((R300_PVS_SRC_SELECT_FORCE_0 | (R300_PVS_SRC_SELECT_FORCE_0 << 3) | \ - (R300_PVS_SRC_SELECT_FORCE_0 << 6) | \ - (R300_PVS_SRC_SELECT_FORCE_0 << 9)) << 13) -# define R300_PVS_SRC_SWIZZLE_ONE \ - ((R300_PVS_SRC_SELECT_FORCE_1 | (R300_PVS_SRC_SELECT_FORCE_1 << 3) | \ - (R300_PVS_SRC_SELECT_FORCE_1 << 6) | \ - (R300_PVS_SRC_SELECT_FORCE_1 << 9)) << 13) -#define R300_PVS_MODIFIER_X (1 << 25) -#define R300_PVS_MODIFIER_Y (1 << 26) -#define R300_PVS_MODIFIER_Z (1 << 27) -#define R300_PVS_MODIFIER_W (1 << 28) -#define R300_PVS_NEGATE_XYZW \ - (R300_PVS_MODIFIER_X | R300_PVS_MODIFIER_Y | \ - R300_PVS_MODIFIER_Z | R300_PVS_MODIFIER_W) - -struct r300_vertex_program_code r300_passthrough_vertex_shader = { - .length = 8, /* two instructions */ - - /* MOV out[0], in[0] */ - .body.d[0] = R300_PVS_DST_OPCODE(R300_VE_ADD) | - R300_PVS_DST_REG_TYPE(R300_PVS_DST_REG_OUT) | - R300_PVS_DST_OFFSET(0) | R300_PVS_DST_WE_XYZW, - .body.d[1] = R300_PVS_SRC_REG_TYPE(R300_PVS_SRC_REG_INPUT) | - R300_PVS_SRC_OFFSET(0) | R300_PVS_SRC_SWIZZLE_XYZW, - .body.d[2] = R300_PVS_SRC_SWIZZLE_ZERO, - .body.d[3] = 0x0, - - /* MOV out[1], in[1] */ - .body.d[4] = R300_PVS_DST_OPCODE(R300_VE_ADD) | - R300_PVS_DST_REG_TYPE(R300_PVS_DST_REG_OUT) | - R300_PVS_DST_OFFSET(1) | R300_PVS_DST_WE_XYZW, - .body.d[5] = R300_PVS_SRC_REG_TYPE(R300_PVS_SRC_REG_INPUT) | - R300_PVS_SRC_OFFSET(1) | R300_PVS_SRC_SWIZZLE_XYZW, - .body.d[6] = R300_PVS_SRC_SWIZZLE_ZERO, - .body.d[7] = 0x0, - - .inputs[0] = 0, - .inputs[1] = 1, - .outputs[0] = 0, - .outputs[1] = 1, - - .InputsRead = 3, - .OutputsWritten = 3 -}; - +boolean r300_vertex_shader_setup_wpos(struct r300_context* r300) +{ + struct r300_vertex_shader* vs = r300->vs; + int tex_output = r300->vs->wpos_tex_output; + uint32_t tex_fmt = R300_INPUT_CNTL_TC0 << tex_output; + uint32_t* hwfmt = vs->hwfmt; + + if (r300->fs->inputs.wpos != ATTR_UNUSED) { + /* Enable WPOS in VAP. */ + if (!(hwfmt[1] & tex_fmt)) { + hwfmt[1] |= tex_fmt; + hwfmt[3] |= (4 << (3 * tex_output)); + + assert(tex_output < 8); + return TRUE; + } + } else { + /* Disable WPOS in VAP. */ + if (hwfmt[1] & tex_fmt) { + hwfmt[1] &= ~tex_fmt; + hwfmt[3] &= ~(4 << (3 * tex_output)); + return TRUE; + } + } + return FALSE; +} diff --git a/src/gallium/drivers/r300/r300_vs.h b/src/gallium/drivers/r300/r300_vs.h index 2a4ce315e32..18cfeee3cd4 100644 --- a/src/gallium/drivers/r300/r300_vs.h +++ b/src/gallium/drivers/r300/r300_vs.h @@ -1,5 +1,6 @@ /* * Copyright 2009 Corbin Simpson <[email protected]> + * Copyright 2009 Marek Olšák <[email protected]> * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -25,18 +26,25 @@ #include "pipe/p_state.h" #include "tgsi/tgsi_scan.h" - #include "radeon_code.h" +#include "r300_shader_semantics.h" + struct r300_context; struct r300_vertex_shader { /* Parent class */ struct pipe_shader_state state; + struct tgsi_shader_info info; + struct r300_shader_semantics outputs; + uint hwfmt[4]; + + /* Stream locations for SWTCL or if TCL is bypassed. */ + int stream_loc_notcl[16]; - /* Fallback shader, because Draw has issues */ - struct draw_vertex_shader* draw; + /* Output stream location for WPOS. */ + int wpos_tex_output; /* Has this shader been translated yet? */ boolean translated; @@ -45,10 +53,10 @@ struct r300_vertex_shader { struct r300_vertex_program_code code; }; - -extern struct r300_vertex_program_code r300_passthrough_vertex_shader; - void r300_translate_vertex_shader(struct r300_context* r300, struct r300_vertex_shader* vs); +/* Return TRUE if VAP (hwfmt) needs to be re-emitted. */ +boolean r300_vertex_shader_setup_wpos(struct r300_context* r300); + #endif /* R300_VS_H */ diff --git a/src/gallium/drivers/r300/r300_winsys.h b/src/gallium/drivers/r300/r300_winsys.h index f18ad75a47d..1ae6de70fee 100644 --- a/src/gallium/drivers/r300/r300_winsys.h +++ b/src/gallium/drivers/r300/r300_winsys.h @@ -35,67 +35,10 @@ extern "C" { #include "pipe/p_state.h" #include "pipe/internal/p_winsys_screen.h" -struct r300_winsys { - /* Parent class */ - struct pipe_winsys base; - - /* Opaque Radeon-specific winsys object. */ - void* radeon_winsys; - - /* PCI ID */ - uint32_t pci_id; - - /* GB pipe count */ - uint32_t gb_pipes; - - /* GART size. */ - uint32_t gart_size; - - /* VRAM size. */ - uint32_t vram_size; - - /* Add a pipe_buffer to the list of buffer objects to validate. */ - boolean (*add_buffer)(struct r300_winsys* winsys, - struct pipe_buffer* pbuffer, - uint32_t rd, - uint32_t wd); - - /* Revalidate all currently setup pipe_buffers. - * Returns TRUE if a flush is required. */ - boolean (*validate)(struct r300_winsys* winsys); - - /* Check to see if there's room for commands. */ - boolean (*check_cs)(struct r300_winsys* winsys, int size); - - /* Start a command emit. */ - void (*begin_cs)(struct r300_winsys* winsys, - int size, - const char* file, - const char* function, - int line); - - /* Write a dword to the command buffer. */ - void (*write_cs_dword)(struct r300_winsys* winsys, uint32_t dword); - - /* Write a relocated dword to the command buffer. */ - void (*write_cs_reloc)(struct r300_winsys* winsys, - struct pipe_buffer* bo, - uint32_t rd, - uint32_t wd, - uint32_t flags); - - /* Finish a command emit. */ - void (*end_cs)(struct r300_winsys* winsys, - const char* file, - const char* function, - int line); - - /* Flush the CS. */ - void (*flush_cs)(struct r300_winsys* winsys); -}; +#include "radeon_winsys.h" struct pipe_context* r300_create_context(struct pipe_screen* screen, - struct r300_winsys* r300_winsys); + struct radeon_winsys* radeon_winsys); boolean r300_get_texture_buffer(struct pipe_texture* texture, struct pipe_buffer** buffer, diff --git a/src/gallium/drivers/r300/r3xx_fs.c b/src/gallium/drivers/r300/r3xx_fs.c deleted file mode 100644 index c1c1194d58e..00000000000 --- a/src/gallium/drivers/r300/r3xx_fs.c +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2008 Corbin Simpson <[email protected]> - * Joakim Sindholt <[email protected]> - * - * 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 "r3xx_fs.h" - -#include "r300_reg.h" - -struct rX00_fragment_program_code r3xx_passthrough_fragment_shader = { - .code.r300.alu.length = 1, - .code.r300.tex.length = 0, - - .code.r300.config = 0, - .code.r300.pixsize = 0, - .code.r300.code_offset = 0, - .code.r300.code_addr[3] = R300_RGBA_OUT, - - .code.r300.alu.inst[0].rgb_inst = R300_RGB_SWIZA(R300_ALU_ARGC_SRC0C_XYZ) | - R300_RGB_SWIZB(R300_ALU_ARGC_SRC0C_XYZ) | - R300_RGB_SWIZC(R300_ALU_ARGC_ZERO) | - R300_ALU_OUTC_CMP, - .code.r300.alu.inst[0].rgb_addr = R300_RGB_ADDR0(0) | R300_RGB_ADDR1(0) | - R300_RGB_ADDR2(0) | R300_ALU_DSTC_OUTPUT_XYZ, - .code.r300.alu.inst[0].alpha_inst = R300_ALPHA_SWIZA(R300_ALU_ARGA_SRC0A) | - R300_ALPHA_SWIZB(R300_ALU_ARGA_SRC0A) | - R300_ALPHA_SWIZC(R300_ALU_ARGA_ZERO) | - R300_ALU_OUTA_CMP, - .code.r300.alu.inst[0].alpha_addr = R300_ALPHA_ADDR0(0) | - R300_ALPHA_ADDR1(0) | R300_ALPHA_ADDR2(0) | R300_ALU_DSTA_OUTPUT, -}; - -struct rX00_fragment_program_code r3xx_texture_fragment_shader = { - .code.r300.alu.length = 1, - .code.r300.tex.length = 1, - - .code.r300.config = R300_PFS_CNTL_FIRST_NODE_HAS_TEX, - .code.r300.pixsize = 0, - .code.r300.code_offset = 0, - .code.r300.code_addr[3] = R300_RGBA_OUT, - - .code.r300.tex.inst[0] = R300_TEX_OP_LD << R300_TEX_INST_SHIFT, - - .code.r300.alu.inst[0].rgb_inst = R300_RGB_SWIZA(R300_ALU_ARGC_SRC0C_XYZ) | - R300_RGB_SWIZB(R300_ALU_ARGC_SRC0C_XYZ) | - R300_RGB_SWIZC(R300_ALU_ARGC_ZERO) | - R300_ALU_OUTC_CMP, - .code.r300.alu.inst[0].rgb_addr = R300_RGB_ADDR0(0) | R300_RGB_ADDR1(0) | - R300_RGB_ADDR2(0) | R300_ALU_DSTC_OUTPUT_XYZ, - .code.r300.alu.inst[0].alpha_inst = R300_ALPHA_SWIZA(R300_ALU_ARGA_SRC0A) | - R300_ALPHA_SWIZB(R300_ALU_ARGA_SRC0A) | - R300_ALPHA_SWIZC(R300_ALU_ARGA_ZERO) | - R300_ALU_OUTA_CMP, - .code.r300.alu.inst[0].alpha_addr = R300_ALPHA_ADDR0(0) | - R300_ALPHA_ADDR1(0) | R300_ALPHA_ADDR2(0) | R300_ALU_DSTA_OUTPUT, -}; diff --git a/src/gallium/drivers/r300/r3xx_fs.h b/src/gallium/drivers/r300/r3xx_fs.h deleted file mode 100644 index 51cd245724d..00000000000 --- a/src/gallium/drivers/r300/r3xx_fs.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2008 Corbin Simpson <[email protected]> - * Joakim Sindholt <[email protected]> - * - * 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 R3XX_FS_H -#define R3XX_FS_H - -#include "radeon_code.h" - -struct rX00_fragment_program_code r3xx_passthrough_fragment_shader; -struct rX00_fragment_program_code r3xx_texture_fragment_shader; - -#endif /* R3XX_FS_H */ diff --git a/src/gallium/drivers/r300/r5xx_fs.c b/src/gallium/drivers/r300/r5xx_fs.c deleted file mode 100644 index f072deab0d9..00000000000 --- a/src/gallium/drivers/r300/r5xx_fs.c +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright 2008 Corbin Simpson <[email protected]> - * Joakim Sindholt <[email protected]> - * - * 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 "r5xx_fs.h" - -#include "r300_reg.h" - -/* XXX this all should find its way back to r300_reg */ -/* Swizzle tools */ -#define R500_SWIZZLE_ZERO 4 -#define R500_SWIZZLE_HALF 5 -#define R500_SWIZZLE_ONE 6 -#define R500_SWIZ_RGB_ZERO ((4 << 0) | (4 << 3) | (4 << 6)) -#define R500_SWIZ_RGB_ONE ((6 << 0) | (6 << 3) | (6 << 6)) -#define R500_SWIZ_RGB_RGB ((0 << 0) | (1 << 3) | (2 << 6)) -#define R500_SWIZ_MOD_NEG 1 -#define R500_SWIZ_MOD_ABS 2 -#define R500_SWIZ_MOD_NEG_ABS 3 -/* Swizzles for inst2 */ -#define R500_SWIZ_TEX_STRQ(x) ((x) << 8) -#define R500_SWIZ_TEX_RGBA(x) ((x) << 24) -/* Swizzles for inst3 */ -#define R500_SWIZ_RGB_A(x) ((x) << 2) -#define R500_SWIZ_RGB_B(x) ((x) << 15) -/* Swizzles for inst4 */ -#define R500_SWIZ_ALPHA_A(x) ((x) << 14) -#define R500_SWIZ_ALPHA_B(x) ((x) << 21) -/* Swizzle for inst5 */ -#define R500_SWIZ_RGBA_C(x) ((x) << 14) -#define R500_SWIZ_ALPHA_C(x) ((x) << 27) -/* Writemasks */ -#define R500_TEX_WMASK(x) ((x) << 11) -#define R500_ALU_WMASK(x) ((x) << 11) -#define R500_ALU_OMASK(x) ((x) << 15) -#define R500_W_OMASK (1 << 31) - -struct rX00_fragment_program_code r5xx_passthrough_fragment_shader = { - .code.r500.max_temp_idx = 0, - .code.r500.inst_end = 0, - - .code.r500.inst[0].inst0 = R500_INST_TYPE_OUT | - R500_INST_TEX_SEM_WAIT | R500_INST_LAST | - R500_INST_RGB_OMASK_RGB | R500_INST_ALPHA_OMASK | - R500_INST_RGB_CLAMP | R500_INST_ALPHA_CLAMP, - .code.r500.inst[0].inst1 = - R500_RGB_ADDR0(0) | R500_RGB_ADDR1(0) | R500_RGB_ADDR1_CONST | - R500_RGB_ADDR2(0) | R500_RGB_ADDR2_CONST, - .code.r500.inst[0].inst2 = - R500_ALPHA_ADDR0(0) | R500_ALPHA_ADDR1(0) | R500_ALPHA_ADDR1_CONST | - R500_ALPHA_ADDR2(0) | R500_ALPHA_ADDR2_CONST, - .code.r500.inst[0].inst3 = - R500_ALU_RGB_SEL_A_SRC0 | R500_ALU_RGB_R_SWIZ_A_R | - R500_ALU_RGB_G_SWIZ_A_G | R500_ALU_RGB_B_SWIZ_A_B | - R500_ALU_RGB_SEL_B_SRC0 | R500_ALU_RGB_R_SWIZ_B_R | - R500_ALU_RGB_B_SWIZ_B_G | R500_ALU_RGB_G_SWIZ_B_B, - .code.r500.inst[0].inst4 = - R500_ALPHA_OP_CMP | R500_ALPHA_SWIZ_A_A | R500_ALPHA_SWIZ_B_A, - .code.r500.inst[0].inst5 = - R500_ALU_RGBA_OP_CMP | R500_ALU_RGBA_R_SWIZ_0 | - R500_ALU_RGBA_G_SWIZ_0 | R500_ALU_RGBA_B_SWIZ_0 | - R500_ALU_RGBA_A_SWIZ_0, -}; - -struct rX00_fragment_program_code r5xx_texture_fragment_shader = { - .code.r500.max_temp_idx = 0, - .code.r500.inst_end = 1, - - .code.r500.inst[0].inst0 = R500_INST_TYPE_TEX | - R500_INST_TEX_SEM_WAIT | - R500_INST_RGB_WMASK_RGB | R500_INST_ALPHA_WMASK | - R500_INST_RGB_CLAMP | R500_INST_ALPHA_CLAMP, - .code.r500.inst[0].inst1 = R500_TEX_ID(0) | R500_TEX_INST_LD | - R500_TEX_SEM_ACQUIRE | R500_TEX_IGNORE_UNCOVERED, - .code.r500.inst[0].inst2 = R500_TEX_SRC_ADDR(0) | - R500_TEX_SRC_S_SWIZ_R | R500_TEX_SRC_T_SWIZ_G | - R500_TEX_SRC_R_SWIZ_B | R500_TEX_SRC_Q_SWIZ_A | - R500_TEX_DST_ADDR(0) | - R500_TEX_DST_R_SWIZ_R | R500_TEX_DST_G_SWIZ_G | - R500_TEX_DST_B_SWIZ_B | R500_TEX_DST_A_SWIZ_A, - .code.r500.inst[0].inst3 = 0x0, - .code.r500.inst[0].inst4 = 0x0, - .code.r500.inst[0].inst5 = 0x0, - - .code.r500.inst[1].inst0 = R500_INST_TYPE_OUT | - R500_INST_TEX_SEM_WAIT | R500_INST_LAST | - R500_INST_RGB_OMASK_RGB | R500_INST_ALPHA_OMASK | - R500_INST_RGB_CLAMP | R500_INST_ALPHA_CLAMP, - .code.r500.inst[1].inst1 = - R500_RGB_ADDR0(0) | R500_RGB_ADDR1(0) | R500_RGB_ADDR1_CONST | - R500_RGB_ADDR2(0) | R500_RGB_ADDR2_CONST, - .code.r500.inst[1].inst2 = - R500_ALPHA_ADDR0(0) | R500_ALPHA_ADDR1(0) | R500_ALPHA_ADDR1_CONST | - R500_ALPHA_ADDR2(0) | R500_ALPHA_ADDR2_CONST, - .code.r500.inst[1].inst3 = - R500_ALU_RGB_SEL_A_SRC0 | R500_ALU_RGB_R_SWIZ_A_R | - R500_ALU_RGB_G_SWIZ_A_G | R500_ALU_RGB_B_SWIZ_A_B | - R500_ALU_RGB_SEL_B_SRC0 | R500_ALU_RGB_R_SWIZ_B_R | - R500_ALU_RGB_B_SWIZ_B_G | R500_ALU_RGB_G_SWIZ_B_B, - .code.r500.inst[1].inst4 = - R500_ALPHA_OP_CMP | R500_ALPHA_SWIZ_A_A | R500_ALPHA_SWIZ_B_A, - .code.r500.inst[1].inst5 = - R500_ALU_RGBA_OP_CMP | R500_ALU_RGBA_R_SWIZ_0 | - R500_ALU_RGBA_G_SWIZ_0 | R500_ALU_RGBA_B_SWIZ_0 | - R500_ALU_RGBA_A_SWIZ_0, -}; diff --git a/src/gallium/drivers/r300/r5xx_fs.h b/src/gallium/drivers/r300/r5xx_fs.h deleted file mode 100644 index a4addde32b2..00000000000 --- a/src/gallium/drivers/r300/r5xx_fs.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2008 Corbin Simpson <[email protected]> - * Joakim Sindholt <[email protected]> - * - * 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 R5XX_FS_H -#define R5XX_FS_H - -#include "radeon_code.h" - -struct rX00_fragment_program_code r5xx_passthrough_fragment_shader; -struct rX00_fragment_program_code r5xx_texture_fragment_shader; - -#endif /* R5XX_FS_H */ |