diff options
Diffstat (limited to 'src/gallium/drivers/r300')
-rw-r--r-- | src/gallium/drivers/r300/Makefile | 2 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_blit.c | 10 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_context.c | 70 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_context.h | 81 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_emit.c | 384 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_emit.h | 54 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_fs.c | 7 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_render.c | 114 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_state.c | 109 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_state_derived.c | 126 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_state_inlines.h | 6 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_state_invariant.c | 3 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_state_invariant.h | 3 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_texture.c | 18 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_vs.c | 4 |
15 files changed, 542 insertions, 449 deletions
diff --git a/src/gallium/drivers/r300/Makefile b/src/gallium/drivers/r300/Makefile index afddcb161f..1f69daec81 100644 --- a/src/gallium/drivers/r300/Makefile +++ b/src/gallium/drivers/r300/Makefile @@ -32,7 +32,5 @@ EXTRA_OBJECTS = \ include ../../Makefile.template -.PHONY : $(COMPILER_ARCHIVE) - $(COMPILER_ARCHIVE): $(MAKE) -C $(TOP)/src/mesa/drivers/dri/r300/compiler diff --git a/src/gallium/drivers/r300/r300_blit.c b/src/gallium/drivers/r300/r300_blit.c index ec7414dc36..8acb1098b9 100644 --- a/src/gallium/drivers/r300/r300_blit.c +++ b/src/gallium/drivers/r300/r300_blit.c @@ -33,7 +33,7 @@ static void r300_blitter_save_states(struct r300_context* r300) util_blitter_save_stencil_ref(r300->blitter, &(r300->stencil_ref)); util_blitter_save_rasterizer(r300->blitter, r300->rs_state.state); util_blitter_save_fragment_shader(r300->blitter, r300->fs); - util_blitter_save_vertex_shader(r300->blitter, r300->vs); + util_blitter_save_vertex_shader(r300->blitter, r300->vs_state.state); util_blitter_save_viewport(r300->blitter, &r300->viewport); util_blitter_save_clip(r300->blitter, &r300->clip); } @@ -100,6 +100,8 @@ static void r300_hw_copy(struct pipe_context* pipe, unsigned width, unsigned height) { struct r300_context* r300 = r300_context(pipe); + struct r300_textures_state* state = + (struct r300_textures_state*)r300->textures_state.state; /* Yeah we have to save all those states to ensure this blitter operation * is really transparent. The states will be restored by the blitter once @@ -108,11 +110,11 @@ static void r300_hw_copy(struct pipe_context* pipe, util_blitter_save_framebuffer(r300->blitter, r300->fb_state.state); util_blitter_save_fragment_sampler_states( - r300->blitter, r300->sampler_count, (void**)r300->sampler_states); + r300->blitter, state->sampler_count, (void**)state->sampler_states); util_blitter_save_fragment_sampler_textures( - r300->blitter, r300->texture_count, - (struct pipe_texture**)r300->textures); + r300->blitter, state->texture_count, + (struct pipe_texture**)state->textures); /* Do a copy */ util_blitter_copy(r300->blitter, diff --git a/src/gallium/drivers/r300/r300_context.c b/src/gallium/drivers/r300/r300_context.c index f631b4ed27..86b98a4ba5 100644 --- a/src/gallium/drivers/r300/r300_context.c +++ b/src/gallium/drivers/r300/r300_context.c @@ -59,7 +59,9 @@ static void r300_destroy_context(struct pipe_context* context) FREE(r300->fb_state.state); FREE(r300->rs_block_state.state); FREE(r300->scissor_state.state); - FREE(r300->vertex_format_state.state); + FREE(r300->textures_state.state); + FREE(r300->vertex_stream_state.state); + FREE(r300->vap_output_state.state); FREE(r300->viewport_state.state); FREE(r300->ztop_state.state); FREE(r300); @@ -96,39 +98,55 @@ static void r300_flush_cb(void *data) } #define R300_INIT_ATOM(atomname, atomsize) \ - r300->atomname##_state.name = #atomname; \ - r300->atomname##_state.state = NULL; \ - r300->atomname##_state.size = atomsize; \ - r300->atomname##_state.emit = r300_emit_##atomname##_state; \ - r300->atomname##_state.dirty = FALSE; \ - insert_at_tail(&r300->atom_list, &r300->atomname##_state); + r300->atomname.name = #atomname; \ + r300->atomname.state = NULL; \ + r300->atomname.size = atomsize; \ + r300->atomname.emit = r300_emit_##atomname; \ + r300->atomname.dirty = FALSE; \ + insert_at_tail(&r300->atom_list, &r300->atomname); static void r300_setup_atoms(struct r300_context* r300) { + boolean is_r500 = r300_screen(r300->context.screen)->caps->is_r500; + boolean has_tcl = r300_screen(r300->context.screen)->caps->has_tcl; + /* Create the actual atom list. * * Each atom is examined and emitted in the order it appears here, which * can affect performance and conformance if not handled with care. * - * Some atoms never change size, others change every emit. This is just - * an upper bound on each atom, to keep the emission machinery from - * underallocating space. */ + * Some atoms never change size, others change every emit - those have + * the size of 0 here. */ make_empty_list(&r300->atom_list); - R300_INIT_ATOM(invariant, 71); - R300_INIT_ATOM(ztop, 2); - R300_INIT_ATOM(blend, 8); - R300_INIT_ATOM(blend_color, 3); - R300_INIT_ATOM(clip, 29); - R300_INIT_ATOM(dsa, 8); - R300_INIT_ATOM(fb, 56); - R300_INIT_ATOM(rs, 25); - R300_INIT_ATOM(scissor, 3); - R300_INIT_ATOM(viewport, 9); - R300_INIT_ATOM(rs_block, 21); - R300_INIT_ATOM(vertex_format, 26); + R300_INIT_ATOM(invariant_state, 71); + R300_INIT_ATOM(ztop_state, 2); + R300_INIT_ATOM(blend_state, 8); + R300_INIT_ATOM(blend_color_state, is_r500 ? 3 : 2); + R300_INIT_ATOM(clip_state, has_tcl ? 5 + (6 * 4) : 2); + R300_INIT_ATOM(dsa_state, is_r500 ? 8 : 6); + R300_INIT_ATOM(fb_state, 0); + R300_INIT_ATOM(rs_state, 0); + R300_INIT_ATOM(scissor_state, 3); + R300_INIT_ATOM(viewport_state, 9); + R300_INIT_ATOM(rs_block_state, 0); + R300_INIT_ATOM(vertex_stream_state, 0); + R300_INIT_ATOM(vap_output_state, 6); + R300_INIT_ATOM(pvs_flush, 2); + R300_INIT_ATOM(vs_state, 0); + R300_INIT_ATOM(texture_cache_inval, 2); + R300_INIT_ATOM(textures_state, 0); /* Some non-CSO atoms need explicit space to store the state locally. */ + r300->blend_color_state.state = CALLOC_STRUCT(r300_blend_color_state); + r300->clip_state.state = CALLOC_STRUCT(pipe_clip_state); r300->fb_state.state = CALLOC_STRUCT(pipe_framebuffer_state); + r300->rs_block_state.state = CALLOC_STRUCT(r300_rs_block); + r300->scissor_state.state = CALLOC_STRUCT(pipe_scissor_state); + r300->textures_state.state = CALLOC_STRUCT(r300_textures_state); + r300->vertex_stream_state.state = CALLOC_STRUCT(r300_vertex_stream_state); + r300->vap_output_state.state = CALLOC_STRUCT(r300_vap_output_state); + r300->viewport_state.state = CALLOC_STRUCT(r300_viewport_state); + r300->ztop_state.state = CALLOC_STRUCT(r300_ztop_state); } struct pipe_context* r300_create_context(struct pipe_screen* screen, @@ -178,14 +196,6 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen, r300_setup_atoms(r300); - r300->blend_color_state.state = CALLOC_STRUCT(r300_blend_color_state); - r300->clip_state.state = CALLOC_STRUCT(pipe_clip_state); - r300->rs_block_state.state = CALLOC_STRUCT(r300_rs_block); - r300->scissor_state.state = CALLOC_STRUCT(pipe_scissor_state); - r300->vertex_format_state.state = CALLOC_STRUCT(r300_vertex_info); - r300->viewport_state.state = CALLOC_STRUCT(r300_viewport_state); - r300->ztop_state.state = CALLOC_STRUCT(r300_ztop_state); - /* Open up the OQ BO. */ r300->oqbo = screen->buffer_create(screen, 4096, PIPE_BUFFER_USAGE_VERTEX, 4096); diff --git a/src/gallium/drivers/r300/r300_context.h b/src/gallium/drivers/r300/r300_context.h index 97100c08cc..0d1518a05b 100644 --- a/src/gallium/drivers/r300/r300_context.h +++ b/src/gallium/drivers/r300/r300_context.h @@ -45,7 +45,7 @@ struct r300_atom { /* Opaque state. */ void* state; /* Emit the state to the context. */ - void (*emit)(struct r300_context*, void*); + void (*emit)(struct r300_context*, unsigned, void*); /* Upper bound on number of dwords to emit. */ unsigned size; /* Whether this atom should be emitted. */ @@ -86,7 +86,6 @@ struct r300_rs_state { uint32_t vap_control_status; /* R300_VAP_CNTL_STATUS: 0x2140 */ uint32_t antialiasing_config; /* R300_GB_AA_CONFIG: 0x4020 */ uint32_t point_size; /* R300_GA_POINT_SIZE: 0x421c */ - uint32_t point_minmax; /* R300_GA_POINT_MINMAX: 0x4230 */ uint32_t line_control; /* R300_GA_LINE_CNTL: 0x4234 */ float depth_scale; /* R300_SU_POLY_OFFSET_FRONT_SCALE: 0x42a4 */ /* R300_SU_POLY_OFFSET_BACK_SCALE: 0x42ac */ @@ -119,7 +118,7 @@ struct r300_sampler_state { unsigned min_lod, max_lod; }; -struct r300_texture_state { +struct r300_texture_format_state { uint32_t format0; /* R300_TX_FORMAT0: 0x4480 */ uint32_t format1; /* R300_TX_FORMAT1: 0x44c0 */ uint32_t format2; /* R300_TX_FORMAT2: 0x4500 */ @@ -135,6 +134,40 @@ struct r300_texture_fb_state { uint32_t zb_format; /* R300_ZB_FORMAT */ }; +struct r300_textures_state { + /* Textures. */ + struct r300_texture *textures[8]; + int texture_count; + /* Sampler states. */ + struct r300_sampler_state *sampler_states[8]; + int sampler_count; + + /* These is the merge of the texture and sampler states. */ + unsigned count; + uint32_t tx_enable; /* R300_TX_ENABLE: 0x4101 */ + struct r300_texture_sampler_state { + uint32_t format[3]; /* R300_TX_FORMAT[0-2] */ + uint32_t filter[2]; /* R300_TX_FILTER[0-1] */ + uint32_t border_color; /* R300_TX_BORDER_COLOR: 0x45c0 */ + uint32_t tile_config; /* R300_TX_OFFSET (subset thereof) */ + } regs[8]; +}; + +struct r300_vertex_stream_state { + /* 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]; + + unsigned count; +}; + +struct r300_vap_output_state { + uint32_t vap_vtx_state_cntl; /* R300_VAP_VTX_STATE_CNTL: 0x2180 */ + uint32_t vap_vsm_vtx_assm; /* R300_VAP_VSM_VTX_ASSM: 0x2184 */ + uint32_t vap_out_vtx_fmt[2]; /* R300_VAP_OUTPUT_VTX_FMT_[0-1]: 0x2090 */ +}; + struct r300_viewport_state { float xscale; /* R300_VAP_VPORT_XSCALE: 0x2098 */ float xoffset; /* R300_VAP_VPORT_XOFFSET: 0x209c */ @@ -151,11 +184,6 @@ struct r300_ztop_state { #define R300_NEW_FRAGMENT_SHADER 0x00000020 #define R300_NEW_FRAGMENT_SHADER_CONSTANTS 0x00000040 -#define R300_NEW_SAMPLER 0x00000200 -#define R300_ANY_NEW_SAMPLERS 0x0001fe00 -#define R300_NEW_TEXTURE 0x00040000 -#define R300_ANY_NEW_TEXTURES 0x03fc0000 -#define R300_NEW_VERTEX_SHADER 0x08000000 #define R300_NEW_VERTEX_SHADER_CONSTANTS 0x10000000 #define R300_NEW_QUERY 0x40000000 #define R300_NEW_KITCHEN_SINK 0x7fffffff @@ -241,23 +269,13 @@ struct r300_texture { struct pipe_buffer* buffer; /* Registers carrying texture format data. */ - struct r300_texture_state state; + struct r300_texture_format_state state; struct r300_texture_fb_state fb_state; /* Buffer tiling */ enum r300_buffer_tiling microtile, macrotile; }; -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]; -}; - extern struct pipe_viewport_state r300_viewport_identity; struct r300_context { @@ -282,9 +300,6 @@ struct r300_context { struct r300_query *query_current; struct r300_query query_list; - /* Vertex formatting information. */ - struct r300_atom vertex_format_state; - /* Various CSO state objects. */ /* Beginning of atom list. */ struct r300_atom atom_list; @@ -306,20 +321,24 @@ struct r300_context { struct r300_atom rs_state; /* RS block state. */ struct r300_atom rs_block_state; - /* Sampler states. */ - struct r300_sampler_state* sampler_states[8]; - int sampler_count; /* Scissor state. */ struct r300_atom scissor_state; - /* Texture states. */ - struct r300_texture* textures[8]; - int texture_count; + /* Textures state. */ + struct r300_atom textures_state; + /* Vertex stream formatting state. */ + struct r300_atom vertex_stream_state; + /* VAP (vertex shader) output mapping state. */ + struct r300_atom vap_output_state; /* Vertex shader. */ - struct r300_vertex_shader* vs; + struct r300_atom vs_state; /* Viewport state. */ struct r300_atom viewport_state; /* ZTOP state. */ struct r300_atom ztop_state; + /* PVS flush. */ + struct r300_atom pvs_flush; + /* Texture cache invalidate. */ + struct r300_atom texture_cache_inval; /* Invariant state. This must be emitted to get the engine started. */ struct r300_atom invariant_state; @@ -327,10 +346,14 @@ struct r300_context { /* Vertex buffers for Gallium. */ struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS]; int vertex_buffer_count; + int vertex_buffer_max_index; /* Vertex elements for Gallium. */ struct pipe_vertex_element vertex_element[PIPE_MAX_ATTRIBS]; int vertex_element_count; + /* Vertex info for Draw. */ + struct vertex_info vertex_info; + struct pipe_stencil_ref stencil_ref; struct pipe_clip_state clip; diff --git a/src/gallium/drivers/r300/r300_emit.c b/src/gallium/drivers/r300/r300_emit.c index 37ebe6c49d..addb28bded 100644 --- a/src/gallium/drivers/r300/r300_emit.c +++ b/src/gallium/drivers/r300/r300_emit.c @@ -34,14 +34,15 @@ #include "r300_screen.h" #include "r300_vs.h" -void r300_emit_blend_state(struct r300_context* r300, void* state) +void r300_emit_blend_state(struct r300_context* r300, + unsigned size, void* state) { struct r300_blend_state* blend = (struct r300_blend_state*)state; struct pipe_framebuffer_state* fb = (struct pipe_framebuffer_state*)r300->fb_state.state; CS_LOCALS(r300); - BEGIN_CS(8); + BEGIN_CS(size); OUT_CS_REG(R300_RB3D_ROPCNTL, blend->rop); OUT_CS_REG_SEQ(R300_RB3D_CBLEND, 3); if (fb->nr_cbufs) { @@ -58,26 +59,28 @@ void r300_emit_blend_state(struct r300_context* r300, void* state) END_CS; } -void r300_emit_blend_color_state(struct r300_context* r300, void* state) +void r300_emit_blend_color_state(struct r300_context* r300, + unsigned size, void* state) { struct r300_blend_color_state* bc = (struct r300_blend_color_state*)state; struct r300_screen* r300screen = r300_screen(r300->context.screen); CS_LOCALS(r300); if (r300screen->caps->is_r500) { - BEGIN_CS(3); + BEGIN_CS(size); OUT_CS_REG_SEQ(R500_RB3D_CONSTANT_COLOR_AR, 2); OUT_CS(bc->blend_color_red_alpha); OUT_CS(bc->blend_color_green_blue); END_CS; } else { - BEGIN_CS(2); + BEGIN_CS(size); OUT_CS_REG(R300_RB3D_BLEND_COLOR, bc->blend_color); END_CS; } } -void r300_emit_clip_state(struct r300_context* r300, void* state) +void r300_emit_clip_state(struct r300_context* r300, + unsigned size, void* state) { struct pipe_clip_state* clip = (struct pipe_clip_state*)state; int i; @@ -85,7 +88,7 @@ void r300_emit_clip_state(struct r300_context* r300, void* state) CS_LOCALS(r300); if (r300screen->caps->has_tcl) { - BEGIN_CS(5 + (6 * 4)); + BEGIN_CS(size); OUT_CS_REG(R300_VAP_PVS_VECTOR_INDX_REG, (r300screen->caps->is_r500 ? R500_PVS_UCP_START : R300_PVS_UCP_START)); @@ -100,14 +103,14 @@ void r300_emit_clip_state(struct r300_context* r300, void* state) R300_PS_UCP_MODE_CLIP_AS_TRIFAN); END_CS; } else { - BEGIN_CS(2); + BEGIN_CS(size); OUT_CS_REG(R300_VAP_CLIP_CNTL, R300_CLIP_DISABLE); END_CS; } } -void r300_emit_dsa_state(struct r300_context* r300, void* state) +void r300_emit_dsa_state(struct r300_context* r300, unsigned size, void* state) { struct r300_dsa_state* dsa = (struct r300_dsa_state*)state; struct r300_screen* r300screen = r300_screen(r300->context.screen); @@ -116,7 +119,7 @@ void r300_emit_dsa_state(struct r300_context* r300, void* state) struct pipe_stencil_ref stencil_ref = r300->stencil_ref; CS_LOCALS(r300); - BEGIN_CS(r300screen->caps->is_r500 ? 8 : 6); + BEGIN_CS(size); OUT_CS_REG(R300_FG_ALPHA_FUNC, dsa->alpha_function); OUT_CS_REG_SEQ(R300_ZB_CNTL, 3); @@ -143,6 +146,8 @@ static const float * get_shader_constant( { struct r300_viewport_state* viewport = (struct r300_viewport_state*)r300->viewport_state.state; + struct r300_textures_state* texstate = + (struct r300_textures_state*)r300->textures_state.state; static float vec[4] = { 0.0, 0.0, 0.0, 1.0 }; struct pipe_texture *tex; @@ -158,7 +163,7 @@ static const float * get_shader_constant( /* 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; + tex = &texstate->textures[constant->u.State[1]]->tex; vec[0] = 1.0 / tex->width0; vec[1] = 1.0 / tex->height0; break; @@ -370,7 +375,7 @@ void r500_emit_fs_constant_buffer(struct r300_context* r300, END_CS; } -void r300_emit_fb_state(struct r300_context* r300, void* state) +void r300_emit_fb_state(struct r300_context* r300, unsigned size, void* state) { struct pipe_framebuffer_state* fb = (struct pipe_framebuffer_state*)state; struct r300_screen* r300screen = r300_screen(r300->context.screen); @@ -379,7 +384,7 @@ void r300_emit_fb_state(struct r300_context* r300, void* state) int i; CS_LOCALS(r300); - BEGIN_CS((10 * fb->nr_cbufs) + (fb->zsbuf ? 10 : 0) + 6); + BEGIN_CS(size); /* Flush and free renderbuffer caches. */ OUT_CS_REG(R300_RB3D_DSTCACHE_CTLSTAT, @@ -418,6 +423,9 @@ void r300_emit_fb_state(struct r300_context* r300, void* state) OUT_CS_REG(R300_US_OUT_FMT_0 + (4 * i), tex->fb_state.us_out_fmt); } + for (; i < 4; i++) { + OUT_CS_REG(R300_US_OUT_FMT_0 + (4 * i), R300_US_OUT_FMT_UNUSED); + } /* Set up a zbuffer. */ if (fb->zsbuf) { @@ -435,6 +443,8 @@ void r300_emit_fb_state(struct r300_context* r300, void* state) 0, RADEON_GEM_DOMAIN_VRAM, 0); } + OUT_CS_REG(R300_GA_POINT_MINMAX, + (MAX2(fb->width, fb->height) * 6) << R300_GA_POINT_MINMAX_MAX_SHIFT); END_CS; } @@ -564,21 +574,19 @@ void r300_emit_query_end(struct r300_context* r300) r300_emit_query_finish(r300, query); } -void r300_emit_rs_state(struct r300_context* r300, void* state) +void r300_emit_rs_state(struct r300_context* r300, unsigned size, void* state) { struct r300_rs_state* rs = (struct r300_rs_state*)state; float scale, offset; CS_LOCALS(r300); - BEGIN_CS(18 + (rs->polygon_offset_enable ? 5 : 0)); + BEGIN_CS(size); OUT_CS_REG(R300_VAP_CNTL_STATUS, rs->vap_control_status); OUT_CS_REG(R300_GB_AA_CONFIG, rs->antialiasing_config); OUT_CS_REG(R300_GA_POINT_SIZE, rs->point_size); - OUT_CS_REG_SEQ(R300_GA_POINT_MINMAX, 2); - OUT_CS(rs->point_minmax); - OUT_CS(rs->line_control); + OUT_CS_REG(R300_GA_LINE_CNTL, rs->line_control); if (rs->polygon_offset_enable) { scale = rs->depth_scale * 12; @@ -609,7 +617,8 @@ void r300_emit_rs_state(struct r300_context* r300, void* state) END_CS; } -void r300_emit_rs_block_state(struct r300_context* r300, void* state) +void r300_emit_rs_block_state(struct r300_context* r300, + unsigned size, void* state) { struct r300_rs_block* rs = (struct r300_rs_block*)state; unsigned i; @@ -620,7 +629,7 @@ void r300_emit_rs_block_state(struct r300_context* r300, void* state) DBG(r300, DBG_DRAW, "r300: RS emit:\n"); - BEGIN_CS(5 + count*2); + BEGIN_CS(size); if (r300screen->caps->is_r500) { OUT_CS_REG_SEQ(R500_RS_IP_0, count); } else { @@ -651,7 +660,8 @@ void r300_emit_rs_block_state(struct r300_context* r300, void* state) END_CS; } -void r300_emit_scissor_state(struct r300_context* r300, void* state) +void r300_emit_scissor_state(struct r300_context* r300, + unsigned size, void* state) { unsigned minx, miny, maxx, maxy; uint32_t top_left, bottom_right; @@ -705,56 +715,42 @@ void r300_emit_scissor_state(struct r300_context* r300, void* state) (((maxy - 1) + 1440) << R300_SCISSORS_Y_SHIFT); } - BEGIN_CS(3); + BEGIN_CS(size); OUT_CS_REG_SEQ(R300_SC_SCISSORS_TL, 2); OUT_CS(top_left); OUT_CS(bottom_right); END_CS; } -void r300_emit_texture(struct r300_context* r300, - struct r300_sampler_state* sampler, - struct r300_texture* tex, - unsigned offset) +void r300_emit_textures_state(struct r300_context *r300, + unsigned size, void *state) { - uint32_t filter0 = sampler->filter0; - uint32_t format0 = tex->state.format0; - unsigned min_level, max_level; + struct r300_textures_state *allstate = (struct r300_textures_state*)state; + struct r300_texture_sampler_state *texstate; + unsigned i; 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); - } + BEGIN_CS(size); + OUT_CS_REG(R300_TX_ENABLE, allstate->tx_enable); - if (tex->is_npot) { - /* NPOT textures don't support mip filter, unfortunately. - * This prevents incorrect rendering. */ - filter0 &= ~R300_TX_MIN_FILTER_MIP_MASK; - } else { - /* 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); - } + for (i = 0; i < allstate->count; i++) { + if ((1 << i) & allstate->tx_enable) { + texstate = &allstate->regs[i]; - BEGIN_CS(16); - 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), 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); - OUT_CS_RELOC(tex->buffer, - R300_TXO_MACRO_TILE(tex->macrotile) | - R300_TXO_MICRO_TILE(tex->microtile), - RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0, 0); + OUT_CS_REG(R300_TX_FILTER0_0 + (i * 4), texstate->filter[0]); + OUT_CS_REG(R300_TX_FILTER1_0 + (i * 4), texstate->filter[1]); + OUT_CS_REG(R300_TX_BORDER_COLOR_0 + (i * 4), + texstate->border_color); + + OUT_CS_REG(R300_TX_FORMAT0_0 + (i * 4), texstate->format[0]); + OUT_CS_REG(R300_TX_FORMAT1_0 + (i * 4), texstate->format[1]); + OUT_CS_REG(R300_TX_FORMAT2_0 + (i * 4), texstate->format[2]); + + OUT_CS_REG_SEQ(R300_TX_OFFSET_0 + (i * 4), 1); + OUT_CS_RELOC(allstate->textures[i]->buffer, texstate->tile_config, + RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0, 0); + } + } END_CS; } @@ -798,58 +794,76 @@ void r300_emit_aos(struct r300_context* r300, unsigned offset) END_CS; } -void r300_emit_vertex_format_state(struct r300_context* r300, void* state) +void r300_emit_vertex_stream_state(struct r300_context* r300, + unsigned size, void* state) { - struct r300_vertex_info* vertex_info = (struct r300_vertex_info*)state; + struct r300_vertex_stream_state *streams = + (struct r300_vertex_stream_state*)state; unsigned i; CS_LOCALS(r300); - DBG(r300, DBG_DRAW, "r300: VAP/PSC emit:\n"); - - BEGIN_CS(26); - OUT_CS_REG(R300_VAP_VTX_SIZE, vertex_info->vinfo.size); + DBG(r300, DBG_DRAW, "r300: PSC emit:\n"); - OUT_CS_REG_SEQ(R300_VAP_VTX_STATE_CNTL, 2); - OUT_CS(vertex_info->vinfo.hwfmt[0]); - OUT_CS(vertex_info->vinfo.hwfmt[1]); - OUT_CS_REG_SEQ(R300_VAP_OUTPUT_VTX_FMT_0, 2); - OUT_CS(vertex_info->vinfo.hwfmt[2]); - OUT_CS(vertex_info->vinfo.hwfmt[3]); - for (i = 0; i < 4; i++) { - DBG(r300, DBG_DRAW, " : hwfmt%d: 0x%08x\n", i, - vertex_info->vinfo.hwfmt[i]); - } - - OUT_CS_REG_SEQ(R300_VAP_PROG_STREAM_CNTL_0, 8); - for (i = 0; i < 8; i++) { - OUT_CS(vertex_info->vap_prog_stream_cntl[i]); + BEGIN_CS(size); + OUT_CS_REG_SEQ(R300_VAP_PROG_STREAM_CNTL_0, streams->count); + for (i = 0; i < streams->count; i++) { + OUT_CS(streams->vap_prog_stream_cntl[i]); DBG(r300, DBG_DRAW, " : prog_stream_cntl%d: 0x%08x\n", i, - vertex_info->vap_prog_stream_cntl[i]); + streams->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(vertex_info->vap_prog_stream_cntl_ext[i]); + OUT_CS_REG_SEQ(R300_VAP_PROG_STREAM_CNTL_EXT_0, streams->count); + for (i = 0; i < streams->count; i++) { + OUT_CS(streams->vap_prog_stream_cntl_ext[i]); DBG(r300, DBG_DRAW, " : prog_stream_cntl_ext%d: 0x%08x\n", i, - vertex_info->vap_prog_stream_cntl_ext[i]); + streams->vap_prog_stream_cntl_ext[i]); } END_CS; } +void r300_emit_vap_output_state(struct r300_context* r300, + unsigned size, void* state) +{ + struct r300_vap_output_state *vap_out_state = + (struct r300_vap_output_state*)state; + CS_LOCALS(r300); + + DBG(r300, DBG_DRAW, "r300: VAP emit:\n"); + + BEGIN_CS(size); + OUT_CS_REG_SEQ(R300_VAP_VTX_STATE_CNTL, 2); + OUT_CS(vap_out_state->vap_vtx_state_cntl); + OUT_CS(vap_out_state->vap_vsm_vtx_assm); + OUT_CS_REG_SEQ(R300_VAP_OUTPUT_VTX_FMT_0, 2); + OUT_CS(vap_out_state->vap_out_vtx_fmt[0]); + OUT_CS(vap_out_state->vap_out_vtx_fmt[1]); + END_CS; +} -void r300_emit_vertex_program_code(struct r300_context* r300, - struct r300_vertex_program_code* code) +void r300_emit_pvs_flush(struct r300_context* r300, unsigned size, void* state) { - int i; + CS_LOCALS(r300); + + BEGIN_CS(size); + OUT_CS_REG(R300_VAP_PVS_STATE_FLUSH_REG, 0x0); + END_CS; +} + +void r300_emit_vs_state(struct r300_context* r300, unsigned size, void* state) +{ + struct r300_vertex_shader* vs = (struct r300_vertex_shader*)state; + struct r300_vertex_program_code* code = &vs->code; struct r300_screen* r300screen = r300_screen(r300->context.screen); unsigned instruction_count = code->length / 4; + unsigned i; - 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); + unsigned vtx_mem_size = r300screen->caps->is_r500 ? 128 : 72; + unsigned input_count = MAX2(util_bitcount(code->InputsRead), 1); + unsigned output_count = MAX2(util_bitcount(code->OutputsWritten), 1); + unsigned temp_count = MAX2(code->num_temporaries, 1); + + unsigned pvs_num_slots = MIN3(vtx_mem_size / input_count, + vtx_mem_size / output_count, 10); + unsigned pvs_num_controllers = MIN2(vtx_mem_size / temp_count, 6); CS_LOCALS(r300); @@ -859,7 +873,7 @@ void r300_emit_vertex_program_code(struct r300_context* r300, return; } - BEGIN_CS(9 + code->length); + BEGIN_CS(size); /* R300_VAP_PVS_CODE_CNTL_0 * R300_VAP_PVS_CONST_CNTL * R300_VAP_PVS_CODE_CNTL_1 @@ -873,8 +887,9 @@ void r300_emit_vertex_program_code(struct r300_context* r300, OUT_CS_REG(R300_VAP_PVS_VECTOR_INDX_REG, 0); OUT_CS_ONE_REG(R300_VAP_PVS_UPLOAD_DATA, code->length); - for (i = 0; i < code->length; i++) + for (i = 0; i < code->length; i++) { OUT_CS(code->body.d[i]); + } OUT_CS_REG(R300_VAP_CNTL, R300_PVS_NUM_SLOTS(pvs_num_slots) | R300_PVS_NUM_CNTLRS(pvs_num_controllers) | @@ -884,12 +899,6 @@ void r300_emit_vertex_program_code(struct r300_context* r300, END_CS; } -void r300_emit_vertex_shader(struct r300_context* r300, - struct r300_vertex_shader* vs) -{ - r300_emit_vertex_program_code(r300, &vs->code); -} - void r300_emit_vs_constant_buffer(struct r300_context* r300, struct rc_constant_list* constants) { @@ -923,77 +932,56 @@ void r300_emit_vs_constant_buffer(struct r300_context* r300, END_CS; } -void r300_emit_viewport_state(struct r300_context* r300, void* state) +void r300_emit_viewport_state(struct r300_context* r300, + unsigned size, void* state) { struct r300_viewport_state* viewport = (struct r300_viewport_state*)state; CS_LOCALS(r300); - BEGIN_CS(9); - OUT_CS_REG_SEQ(R300_SE_VPORT_XSCALE, 6); - OUT_CS_32F(viewport->xscale); - OUT_CS_32F(viewport->xoffset); - OUT_CS_32F(viewport->yscale); - OUT_CS_32F(viewport->yoffset); - OUT_CS_32F(viewport->zscale); - OUT_CS_32F(viewport->zoffset); - OUT_CS_REG(R300_VAP_VTE_CNTL, viewport->vte_control); - 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; - + BEGIN_CS(size); + OUT_CS_REG_SEQ(R300_SE_VPORT_XSCALE, 6); + OUT_CS_32F(viewport->xscale); + OUT_CS_32F(viewport->xoffset); + OUT_CS_32F(viewport->yscale); + OUT_CS_32F(viewport->yoffset); + OUT_CS_32F(viewport->zscale); + OUT_CS_32F(viewport->zoffset); + OUT_CS_REG(R300_VAP_VTE_CNTL, viewport->vte_control); + END_CS; } -void r300_emit_ztop_state(struct r300_context* r300, void* state) +void r300_emit_ztop_state(struct r300_context* r300, + unsigned size, void* state) { struct r300_ztop_state* ztop = (struct r300_ztop_state*)state; CS_LOCALS(r300); - BEGIN_CS(2); + BEGIN_CS(size); OUT_CS_REG(R300_ZB_ZTOP, ztop->z_buffer_top); END_CS; } -void r300_flush_textures(struct r300_context* r300) +void r300_emit_texture_cache_inval(struct r300_context* r300, unsigned size, void* state) { CS_LOCALS(r300); - BEGIN_CS(2); + BEGIN_CS(size); OUT_CS_REG(R300_TX_INVALTAGS, 0); 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; -} - -void r300_emit_buffer_validate(struct r300_context *r300) +void r300_emit_buffer_validate(struct r300_context *r300, + boolean do_validate_vertex_buffers, + struct pipe_buffer *index_buffer) { struct pipe_framebuffer_state* fb = (struct pipe_framebuffer_state*)r300->fb_state.state; + struct r300_textures_state *texstate = + (struct r300_textures_state*)r300->textures_state.state; struct r300_texture* tex; + struct pipe_vertex_buffer *vbuf = r300->vertex_buffer; + struct pipe_vertex_element *velem = r300->vertex_element; + struct pipe_buffer *pbuf; unsigned i; boolean invalid = FALSE; @@ -1022,9 +1010,9 @@ validate: } } /* ...textures... */ - for (i = 0; i < r300->texture_count; i++) { - tex = r300->textures[i]; - if (!tex) + for (i = 0; i < texstate->count; i++) { + tex = texstate->textures[i]; + if (!tex || !texstate->sampler_states[i]) continue; if (!r300->winsys->add_buffer(r300->winsys, tex->buffer, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0)) { @@ -1040,16 +1028,35 @@ validate: goto validate; } } - /* ...and vertex buffer. */ + /* ...vertex buffer for SWTCL path... */ if (r300->vbo) { if (!r300->winsys->add_buffer(r300->winsys, r300->vbo, RADEON_GEM_DOMAIN_GTT, 0)) { r300->context.flush(&r300->context, 0, NULL); goto validate; } - } else { - /* debug_printf("No VBO while emitting dirty state!\n"); */ } + /* ...vertex buffers for HWTCL path... */ + if (do_validate_vertex_buffers) { + for (i = 0; i < r300->vertex_element_count; i++) { + pbuf = vbuf[velem[i].vertex_buffer_index].buffer; + + if (!r300->winsys->add_buffer(r300->winsys, pbuf, + RADEON_GEM_DOMAIN_GTT, 0)) { + r300->context.flush(&r300->context, 0, NULL); + goto validate; + } + } + } + /* ...and index buffer for HWTCL path. */ + if (index_buffer) { + if (!r300->winsys->add_buffer(r300->winsys, 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); if (invalid) { @@ -1062,16 +1069,10 @@ validate: } } -/* Emit all dirty state. */ -void r300_emit_dirty_state(struct r300_context* r300) +unsigned r300_get_num_dirty_dwords(struct r300_context *r300) { - struct r300_screen* r300screen = r300_screen(r300->context.screen); struct r300_atom* atom; - unsigned i, dwords = 1024; - int dirty_tex = 0; - - /* Check the required number of dwords against the space remaining in the - * current CS object. If we need more, then flush. */ + unsigned dwords = 0; foreach(atom, &r300->atom_list) { if (atom->dirty || atom->always_dirty) { @@ -1079,12 +1080,17 @@ void r300_emit_dirty_state(struct r300_context* r300) } } - /* Make sure we have at least 2*1024 spare dwords. */ - /* XXX It would be nice to know the number of dwords we really need to - * XXX emit. */ - while (!r300->winsys->check_cs(r300->winsys, dwords)) { - r300->context.flush(&r300->context, 0, NULL); - } + /* XXX This is the compensation for the non-atomized states. */ + dwords += 1024; + + return dwords; +} + +/* Emit all dirty state. */ +void r300_emit_dirty_state(struct r300_context* r300) +{ + struct r300_screen* r300screen = r300_screen(r300->context.screen); + struct r300_atom* atom; if (r300->dirty_state & R300_NEW_QUERY) { r300_emit_query_start(r300); @@ -1093,7 +1099,7 @@ void r300_emit_dirty_state(struct r300_context* r300) foreach(atom, &r300->atom_list) { if (atom->dirty || atom->always_dirty) { - atom->emit(r300, atom->state); + atom->emit(r300, atom->size, atom->state); atom->dirty = FALSE; } } @@ -1119,43 +1125,9 @@ void r300_emit_dirty_state(struct r300_context* r300) r300->dirty_state &= ~R300_NEW_FRAGMENT_SHADER_CONSTANTS; } - /* 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))) { - if (r300->textures[i]) { - r300_emit_texture(r300, - r300->sampler_states[i], - r300->textures[i], - i); - dirty_tex |= r300->dirty_state & (R300_NEW_TEXTURE << i); - } - r300->dirty_state &= - ~((R300_NEW_SAMPLER << i) | (R300_NEW_TEXTURE << i)); - } - } - r300->dirty_state &= ~(R300_ANY_NEW_SAMPLERS | R300_ANY_NEW_TEXTURES); - } - - if (dirty_tex) { - r300_flush_textures(r300); - } - - 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); + struct r300_vertex_shader* vs = r300->vs_state.state; + r300_emit_vs_constant_buffer(r300, &vs->code.constants); r300->dirty_state &= ~R300_NEW_VERTEX_SHADER_CONSTANTS; } diff --git a/src/gallium/drivers/r300/r300_emit.h b/src/gallium/drivers/r300/r300_emit.h index 6b96d9b57c..449e640a88 100644 --- a/src/gallium/drivers/r300/r300_emit.h +++ b/src/gallium/drivers/r300/r300_emit.h @@ -31,13 +31,17 @@ struct r300_vertex_program_code; void r300_emit_aos(struct r300_context* r300, unsigned offset); -void r300_emit_blend_state(struct r300_context* r300, void* state); +void r300_emit_blend_state(struct r300_context* r300, + unsigned size, void* state); -void r300_emit_blend_color_state(struct r300_context* r300, void* state); +void r300_emit_blend_color_state(struct r300_context* r300, + unsigned size, void* state); -void r300_emit_clip_state(struct r300_context* r300, void* state); +void r300_emit_clip_state(struct r300_context* r300, + unsigned size, void* state); -void r300_emit_dsa_state(struct r300_context* r300, void* state); +void r300_emit_dsa_state(struct r300_context* r300, + unsigned size, void* state); void r300_emit_fragment_program_code(struct r300_context* r300, struct rX00_fragment_program_code* generic_code); @@ -51,48 +55,54 @@ void r500_emit_fragment_program_code(struct r300_context* r300, void r500_emit_fs_constant_buffer(struct r300_context* r300, struct rc_constant_list* constants); -void r300_emit_fb_state(struct r300_context* r300, void* state); +void r300_emit_fb_state(struct r300_context* r300, unsigned size, void* state); void r300_emit_query_begin(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, void* state); +void r300_emit_rs_state(struct r300_context* r300, unsigned size, void* state); -void r300_emit_rs_block_state(struct r300_context* r300, void* state); +void r300_emit_rs_block_state(struct r300_context* r300, + unsigned size, void* state); -void r300_emit_scissor_state(struct r300_context* r300, void* state); +void r300_emit_scissor_state(struct r300_context* r300, + unsigned size, void* state); -void r300_emit_texture(struct r300_context* r300, - struct r300_sampler_state* sampler, - struct r300_texture* tex, - unsigned offset); +void r300_emit_textures_state(struct r300_context *r300, + unsigned size, void *state); void r300_emit_vertex_buffer(struct r300_context* r300); -void r300_emit_vertex_format_state(struct r300_context* r300, void* state); +void r300_emit_vertex_stream_state(struct r300_context* r300, + unsigned size, void* state); -void r300_emit_vertex_program_code(struct r300_context* r300, - struct r300_vertex_program_code* code); +void r300_emit_vap_output_state(struct r300_context* r300, + unsigned size, void* state); 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); +void r300_emit_vs_state(struct r300_context* r300, unsigned size, void* state); -void r300_emit_viewport_state(struct r300_context* r300, void* state); +void r300_emit_viewport_state(struct r300_context* r300, + unsigned size, void* state); -void r300_emit_texture_count(struct r300_context* r300); +void r300_emit_ztop_state(struct r300_context* r300, + unsigned size, void* state); -void r300_emit_ztop_state(struct r300_context* r300, void* state); +void r300_emit_pvs_flush(struct r300_context* r300, unsigned size, void* state); -void r300_flush_textures(struct r300_context* r300); +void r300_emit_texture_cache_inval(struct r300_context* r300, unsigned size, void* state); + +unsigned r300_get_num_dirty_dwords(struct r300_context *r300); /* Emit all dirty state. */ void r300_emit_dirty_state(struct r300_context* r300); -void r300_emit_buffer_validate(struct r300_context *r300); +void r300_emit_buffer_validate(struct r300_context *r300, + boolean do_validate_vertex_buffers, + struct pipe_buffer *index_buffer); #endif /* R300_EMIT_H */ diff --git a/src/gallium/drivers/r300/r300_fs.c b/src/gallium/drivers/r300/r300_fs.c index ae4c62b2f1..3c2625269b 100644 --- a/src/gallium/drivers/r300/r300_fs.c +++ b/src/gallium/drivers/r300/r300_fs.c @@ -133,10 +133,13 @@ static void get_compare_state( struct r300_fragment_program_external_state* state, unsigned shadow_samplers) { + struct r300_textures_state *texstate = + (struct r300_textures_state*)r300->textures_state.state; + memset(state, 0, sizeof(*state)); - for (int i = 0; i < r300->sampler_count; i++) { - struct r300_sampler_state* s = r300->sampler_states[i]; + for (int i = 0; i < texstate->sampler_count; i++) { + struct r300_sampler_state* s = texstate->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 diff --git a/src/gallium/drivers/r300/r300_render.c b/src/gallium/drivers/r300/r300_render.c index 754eb4dc76..770a92be74 100644 --- a/src/gallium/drivers/r300/r300_render.c +++ b/src/gallium/drivers/r300/r300_render.c @@ -118,6 +118,18 @@ static uint32_t r300_provoking_vertex_fixes(struct r300_context *r300, return color_control; } +/* Check if the requested number of dwords is available in the CS and + * if not, flush. Return TRUE if the flush occured. */ +static boolean r300_reserve_cs_space(struct r300_context *r300, + unsigned dwords) +{ + if (!r300->winsys->check_cs(r300->winsys, dwords)) { + r300->context.flush(&r300->context, 0, NULL); + return TRUE; + } + return FALSE; +} + static boolean immd_is_good_idea(struct r300_context *r300, unsigned count) { @@ -132,7 +144,7 @@ static void r300_emit_draw_arrays_immediate(struct r300_context *r300, struct pipe_vertex_element* velem; struct pipe_vertex_buffer* vbuf; unsigned vertex_element_count = r300->vertex_element_count; - unsigned i, v, vbi, dw, elem_offset; + unsigned i, v, vbi, dw, elem_offset, dwords; /* Size of the vertex, in dwords. */ unsigned vertex_size = 0; @@ -171,9 +183,13 @@ static void r300_emit_draw_arrays_immediate(struct r300_context *r300, } } + dwords = 10 + count * vertex_size; + + r300_reserve_cs_space(r300, r300_get_num_dirty_dwords(r300) + dwords); + r300_emit_buffer_validate(r300, FALSE, 0); r300_emit_dirty_state(r300); - BEGIN_CS(10 + count * vertex_size); + BEGIN_CS(dwords); OUT_CS_REG(R300_GA_COLOR_CONTROL, r300_provoking_vertex_fixes(r300, mode)); OUT_CS_REG(R300_VAP_VTX_SIZE, vertex_size); @@ -258,11 +274,6 @@ static void r300_emit_draw_elements(struct r300_context *r300, assert((start * indexSize) % 4 == 0); - /* XXX Non-zero offset locks up. */ - if (offset_dwords != 0) { - return; - } - if (alt_num_verts) { assert(count < (1 << 24)); BEGIN_CS(16); @@ -276,13 +287,13 @@ static void r300_emit_draw_elements(struct r300_context *r300, 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; + count_dwords = count; OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (count << 16) | R300_VAP_VF_CNTL__INDEX_SIZE_32bit | r300_translate_primitive(mode) | (alt_num_verts ? R500_VAP_VF_CNTL__USE_ALT_NUM_VERTS : 0)); } else { - count_dwords = (count + start + 1) / 2; + count_dwords = (count + 1) / 2; OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (count << 16) | r300_translate_primitive(mode) | (alt_num_verts ? R500_VAP_VF_CNTL__USE_ALT_NUM_VERTS : 0)); @@ -303,31 +314,6 @@ static void r300_emit_draw_elements(struct r300_context *r300, 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; - struct pipe_buffer *pbuf; - -validate: - for (int i = 0; i < r300->vertex_element_count; i++) { - pbuf = vbuf[velem[i].vertex_buffer_index].buffer; - - if (!r300->winsys->add_buffer(r300->winsys, pbuf, - 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; -} - static void r300_shorten_ubyte_elts(struct r300_context* r300, struct pipe_buffer** elts, unsigned count) @@ -383,30 +369,17 @@ void r300_draw_range_elements(struct pipe_context* pipe, return; } - r300_update_derived_state(r300); - - r300_emit_buffer_validate(r300); - - if (!r300_setup_vertex_buffers(r300)) { - return; - } - if (indexSize == 1) { r300_shorten_ubyte_elts(r300, &indexBuffer, count); indexSize = 2; } - if (!r300->winsys->add_buffer(r300->winsys, indexBuffer, - RADEON_GEM_DOMAIN_GTT, 0)) { - goto cleanup; - } - - if (!r300->winsys->validate(r300->winsys)) { - goto cleanup; - } + r300_update_derived_state(r300); + /* 128 dwords for emit_aos and emit_draw_elements */ + r300_reserve_cs_space(r300, r300_get_num_dirty_dwords(r300) + 128); + r300_emit_buffer_validate(r300, TRUE, indexBuffer); r300_emit_dirty_state(r300); - r300_emit_aos(r300, 0); if (alt_num_verts || count <= 65535) { @@ -420,10 +393,16 @@ void r300_draw_range_elements(struct pipe_context* pipe, start += short_count; count -= short_count; + + /* 16 spare dwords are enough for emit_draw_elements. */ + if (count && r300_reserve_cs_space(r300, 16)) { + r300_emit_buffer_validate(r300, TRUE, indexBuffer); + r300_emit_dirty_state(r300); + r300_emit_aos(r300, 0); + } } while (count); } -cleanup: if (indexBuffer != orgIndexBuffer) { pipe->screen->buffer_destroy(indexBuffer); } @@ -435,8 +414,11 @@ void r300_draw_elements(struct pipe_context* pipe, unsigned indexSize, unsigned mode, unsigned start, unsigned count) { - pipe->draw_range_elements(pipe, indexBuffer, indexSize, 0, ~0, - mode, start, count); + struct r300_context *r300 = r300_context(pipe); + + pipe->draw_range_elements(pipe, indexBuffer, indexSize, 0, + r300->vertex_buffer_max_index, + mode, start, count); } void r300_draw_arrays(struct pipe_context* pipe, unsigned mode, @@ -457,15 +439,13 @@ void r300_draw_arrays(struct pipe_context* pipe, unsigned mode, r300_update_derived_state(r300); - r300_emit_buffer_validate(r300); - if (immd_is_good_idea(r300, count)) { r300_emit_draw_arrays_immediate(r300, mode, start, count); } else { - if (!r300_setup_vertex_buffers(r300)) { - return; - } - + /* Make sure there are at least 128 spare dwords in the command buffer. + * (most of it being consumed by emit_aos) */ + r300_reserve_cs_space(r300, r300_get_num_dirty_dwords(r300) + 128); + r300_emit_buffer_validate(r300, TRUE, 0); r300_emit_dirty_state(r300); if (alt_num_verts || count <= 65535) { @@ -479,6 +459,13 @@ void r300_draw_arrays(struct pipe_context* pipe, unsigned mode, start += short_count; count -= short_count; + + /* Again, we emit both AOS and draw_arrays so there should be + * at least 128 spare dwords. */ + if (count && r300_reserve_cs_space(r300, 128)) { + r300_emit_buffer_validate(r300, TRUE, 0); + r300_emit_dirty_state(r300); + } } while (count); } } @@ -610,7 +597,7 @@ r300_render_get_vertex_info(struct vbuf_render* render) r300_update_derived_state(r300); - return (struct vertex_info*)r300->vertex_format_state.state; + return &r300->vertex_info; } static boolean r300_render_allocate_vertices(struct vbuf_render* render, @@ -695,6 +682,7 @@ static void r300_render_draw_arrays(struct vbuf_render* render, CS_LOCALS(r300); + r300_reserve_cs_space(r300, r300_get_num_dirty_dwords(r300) + 2); r300_emit_dirty_state(r300); DBG(r300, DBG_DRAW, "r300: Doing vbuf render, count %d\n", count); @@ -713,12 +701,14 @@ static void r300_render_draw(struct vbuf_render* render, struct r300_render* r300render = r300_render(render); struct r300_context* r300 = r300render->r300; int i; + unsigned dwords = 2 + (count+1)/2; CS_LOCALS(r300); + r300_reserve_cs_space(r300, r300_get_num_dirty_dwords(r300) + dwords); r300_emit_dirty_state(r300); - BEGIN_CS(2 + (count+1)/2); + BEGIN_CS(dwords); OUT_CS_PKT3(R300_PACKET3_3D_DRAW_INDX_2, (count+1)/2); OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (count << 16) | r300render->hwprim); diff --git a/src/gallium/drivers/r300/r300_state.c b/src/gallium/drivers/r300/r300_state.c index ebb859138f..b732380a14 100644 --- a/src/gallium/drivers/r300/r300_state.c +++ b/src/gallium/drivers/r300/r300_state.c @@ -600,7 +600,8 @@ static void memcpy(r300->fb_state.state, state, sizeof(struct pipe_framebuffer_state)); - r300->fb_state.size = (10 * state->nr_cbufs) + (state->zsbuf ? 10 : 0) + 6; + r300->fb_state.size = (10 * state->nr_cbufs) + (2 * (4 - state->nr_cbufs)) + + (state->zsbuf ? 10 : 0) + 8; r300_fb_update_tiling_flags(r300, r300->fb_state.state, state); @@ -660,8 +661,10 @@ static void r300_bind_fs_state(struct pipe_context* pipe, void* shader) r300->fs = fs; r300_pick_fragment_shader(r300); - if (r300->vs && r300_vertex_shader_setup_wpos(r300)) { - r300->vertex_format_state.dirty = TRUE; + r300->rs_block_state.dirty = TRUE; /* Will be updated before the emission. */ + + if (r300->vs_state.state && r300_vertex_shader_setup_wpos(r300)) { + r300->vap_output_state.dirty = TRUE; } r300->dirty_state |= R300_NEW_FRAGMENT_SHADER | R300_NEW_FRAGMENT_SHADER_CONSTANTS; @@ -720,22 +723,6 @@ static void* r300_create_rs_state(struct pipe_context* pipe, rs->point_size = pack_float_16_6x(state->point_size) | (pack_float_16_6x(state->point_size) << R300_POINTSIZE_X_SHIFT); - /* Point minimum and maximum sizes. This register has to be emitted, - * and it'd be a step backwards to put it in invariant state. */ - if (r300screen->caps->is_r500) { - rs->point_minmax = - ((int)(0.0 * 6.0) << R300_GA_POINT_MINMAX_MIN_SHIFT) | - ((int)(4096.0 * 6.0) << R300_GA_POINT_MINMAX_MAX_SHIFT); - } else if (r300screen->caps->is_r400) { - rs->point_minmax = - ((int)(0.0 * 6.0) << R300_GA_POINT_MINMAX_MIN_SHIFT) | - ((int)(4021.0 * 6.0) << R300_GA_POINT_MINMAX_MAX_SHIFT); - } else { - rs->point_minmax = - ((int)(0.0 * 6.0) << R300_GA_POINT_MINMAX_MIN_SHIFT) | - ((int)(2560.0 * 6.0) << R300_GA_POINT_MINMAX_MAX_SHIFT); - } - rs->line_control = pack_float_16_6x(state->line_width) | R300_GA_LINE_CNTL_END_TYPE_COMP; @@ -826,12 +813,13 @@ static void r300_bind_rs_state(struct pipe_context* pipe, void* state) if (rs) { r300->polygon_offset_enabled = rs->rs.offset_cw || rs->rs.offset_ccw; + r300->rs_state.dirty = TRUE; } else { r300->polygon_offset_enabled = FALSE; } r300->rs_state.state = rs; - r300->rs_state.dirty = TRUE; + r300->rs_state.size = 17 + (r300->polygon_offset_enabled ? 5 : 0); /* XXX Why is this still needed, dammit!? */ r300->scissor_state.dirty = TRUE; r300->viewport_state.dirty = TRUE; @@ -870,7 +858,7 @@ static void* state->max_anisotropy > 0); /* Unfortunately, r300-r500 don't support floating-point mipmap lods. */ - /* We must pass these to the emit function to clamp them properly. */ + /* We must pass these to the merge function to clamp them properly. */ sampler->min_lod = MAX2((unsigned)state->min_lod, 0); sampler->max_lod = MAX2((unsigned)ceilf(state->max_lod), 0); @@ -896,23 +884,20 @@ static void r300_bind_sampler_states(struct pipe_context* pipe, void** states) { struct r300_context* r300 = r300_context(pipe); - int i; + struct r300_textures_state* state = + (struct r300_textures_state*)r300->textures_state.state; if (count > 8) { return; } - for (i = 0; i < count; i++) { - if (r300->sampler_states[i] != states[i]) { - r300->sampler_states[i] = (struct r300_sampler_state*)states[i]; - r300->dirty_state |= (R300_NEW_SAMPLER << i); - } - } + memcpy(state->sampler_states, states, sizeof(void*) * count); + state->sampler_count = count; - r300->sampler_count = count; + r300->textures_state.dirty = TRUE; /* Pick a fragment shader based on the texture compare state. */ - if (r300->fs && (r300->dirty_state & R300_ANY_NEW_SAMPLERS)) { + if (r300->fs && count) { if (r300_pick_fragment_shader(r300)) { r300->dirty_state |= R300_NEW_FRAGMENT_SHADER | R300_NEW_FRAGMENT_SHADER_CONSTANTS; @@ -936,22 +921,25 @@ static void r300_set_sampler_textures(struct pipe_context* pipe, struct pipe_texture** texture) { struct r300_context* r300 = r300_context(pipe); + struct r300_textures_state* state = + (struct r300_textures_state*)r300->textures_state.state; + unsigned i; boolean is_r500 = r300_screen(r300->context.screen)->caps->is_r500; - int i; + boolean dirty_tex = FALSE; /* 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); + if (state->textures[i] != (struct r300_texture*)texture[i]) { + pipe_texture_reference((struct pipe_texture**)&state->textures[i], + texture[i]); + dirty_tex = TRUE; - /* R300-specific - set the texrect factor in a fragment shader */ - if (!is_r500 && r300->textures[i]->is_npot) { + /* R300-specific - set the texrect factor in the fragment shader */ + if (!is_r500 && state->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; @@ -960,14 +948,19 @@ static void r300_set_sampler_textures(struct pipe_context* pipe, } for (i = count; i < 8; i++) { - if (r300->textures[i]) { - pipe_texture_reference((struct pipe_texture**)&r300->textures[i], + if (state->textures[i]) { + pipe_texture_reference((struct pipe_texture**)&state->textures[i], NULL); - r300->dirty_state |= (R300_NEW_TEXTURE << i); } } - r300->texture_count = count; + state->texture_count = count; + + r300->textures_state.dirty = TRUE; + + if (dirty_tex) { + r300->texture_cache_inval.dirty = TRUE; + } } static void r300_set_scissor_state(struct pipe_context* pipe, @@ -1029,17 +1022,24 @@ static void r300_set_vertex_buffers(struct pipe_context* pipe, const struct pipe_vertex_buffer* buffers) { struct r300_context* r300 = r300_context(pipe); + unsigned i, max_index = ~0; memcpy(r300->vertex_buffer, buffers, sizeof(struct pipe_vertex_buffer) * count); + + for (i = 0; i < count; i++) { + max_index = MIN2(buffers[i].max_index, max_index); + } + r300->vertex_buffer_count = count; + r300->vertex_buffer_max_index = max_index; if (r300->draw) { draw_flush(r300->draw); draw_set_vertex_buffers(r300->draw, count, buffers); + } else { + r300->vertex_stream_state.dirty = TRUE; } - - r300->vertex_format_state.dirty = TRUE; } static boolean r300_validate_aos(struct r300_context *r300) @@ -1108,21 +1108,26 @@ static void r300_bind_vs_state(struct pipe_context* pipe, void* shader) struct r300_vertex_shader* vs = (struct r300_vertex_shader*)shader; if (vs == NULL) { - r300->vs = NULL; + r300->vs_state.state = NULL; return; } else if (!vs->translated) { r300_translate_vertex_shader(r300, vs); } - r300->vs = vs; + r300->vs_state.state = vs; + r300->vs_state.size = vs->code.length + 9; + r300->vs_state.dirty = TRUE; + + r300->rs_block_state.dirty = TRUE; /* Will be updated before the emission. */ + r300->vap_output_state.dirty = TRUE; + r300->vertex_stream_state.dirty = TRUE; /* XXX needed for TCL bypass */ + r300->pvs_flush.dirty = TRUE; + if (r300->fs) { r300_vertex_shader_setup_wpos(r300); } - r300->vertex_format_state.dirty = TRUE; - - r300->dirty_state |= - R300_NEW_VERTEX_SHADER | R300_NEW_VERTEX_SHADER_CONSTANTS; + r300->dirty_state |= R300_NEW_VERTEX_SHADER_CONSTANTS; } else { draw_flush(r300->draw); draw_bind_vertex_shader(r300->draw, @@ -1194,8 +1199,10 @@ static void r300_set_constant_buffer(struct pipe_context *pipe, r300->shader_constants[shader].count = buf->size / (4 * sizeof(float)); pipe_buffer_unmap(pipe->screen, buf); - if (shader == PIPE_SHADER_VERTEX) + if (shader == PIPE_SHADER_VERTEX) { r300->dirty_state |= R300_NEW_VERTEX_SHADER_CONSTANTS; + r300->pvs_flush.dirty = TRUE; + } else if (shader == PIPE_SHADER_FRAGMENT) r300->dirty_state |= R300_NEW_FRAGMENT_SHADER_CONSTANTS; } diff --git a/src/gallium/drivers/r300/r300_state_derived.c b/src/gallium/drivers/r300/r300_state_derived.c index 778eaaacd9..9c8e907fdf 100644 --- a/src/gallium/drivers/r300/r300_state_derived.c +++ b/src/gallium/drivers/r300/r300_state_derived.c @@ -42,20 +42,20 @@ static void r300_draw_emit_attrib(struct r300_context* r300, enum interp_mode interp, int index) { - struct tgsi_shader_info* info = &r300->vs->info; + struct r300_vertex_shader* vs = r300->vs_state.state; + struct tgsi_shader_info* info = &vs->info; int output; output = draw_find_shader_output(r300->draw, info->output_semantic_name[index], info->output_semantic_index[index]); - draw_emit_vertex_attr( - (struct vertex_info*)r300->vertex_format_state.state, - emit, interp, output); + draw_emit_vertex_attr(&r300->vertex_info, emit, interp, output); } static void r300_draw_emit_all_attribs(struct r300_context* r300) { - struct r300_shader_semantics* vs_outputs = &r300->vs->outputs; + struct r300_vertex_shader* vs = r300->vs_state.state; + struct r300_shader_semantics* vs_outputs = &vs->outputs; int i, gen_count; /* Position. */ @@ -104,16 +104,21 @@ static void r300_draw_emit_all_attribs(struct r300_context* r300) } /* Update the PSC tables. */ +/* XXX move this function into r300_state.c after TCL-bypass gets removed + * XXX because this one is dependent only on vertex elements. */ static void r300_vertex_psc(struct r300_context* r300) { - struct r300_vertex_info *vformat = - (struct r300_vertex_info*)r300->vertex_format_state.state; + struct r300_vertex_shader* vs = r300->vs_state.state; + struct r300_vertex_stream_state *vformat = + (struct r300_vertex_stream_state*)r300->vertex_stream_state.state; 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; + memset(vformat, 0, sizeof(struct r300_vertex_stream_state)); + stream_tab = identity; /* Vertex shaders have no semantics on their inputs, @@ -121,7 +126,7 @@ static void r300_vertex_psc(struct r300_context* r300) * 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, + vs->info.num_inputs, r300->vertex_element_count); for (i = 0; i < r300->vertex_element_count; i++) { @@ -148,18 +153,24 @@ static void r300_vertex_psc(struct r300_context* r300) } vformat->vap_prog_stream_cntl[i >> 1] |= (R300_LAST_VEC << (i & 1 ? 16 : 0)); + + vformat->count = (i >> 1) + 1; + r300->vertex_stream_state.size = (1 + vformat->count) * 2; } /* Update the PSC tables for SW TCL, using Draw. */ static void r300_swtcl_vertex_psc(struct r300_context* r300) { - struct r300_vertex_info *vformat = - (struct r300_vertex_info*)r300->vertex_format_state.state; - struct vertex_info* vinfo = &vformat->vinfo; + struct r300_vertex_shader* vs = r300->vs_state.state; + struct r300_vertex_stream_state *vformat = + (struct r300_vertex_stream_state*)r300->vertex_stream_state.state; + struct vertex_info* vinfo = &r300->vertex_info; uint16_t type, swizzle; enum pipe_format format; unsigned i, attrib_count; - int* vs_output_tab = r300->vs->stream_loc_notcl; + int* vs_output_tab = vs->stream_loc_notcl; + + memset(vformat, 0, sizeof(struct r300_vertex_stream_state)); /* For each Draw attribute, route it to the fragment shader according * to the vs_output_tab. */ @@ -202,6 +213,9 @@ static void r300_swtcl_vertex_psc(struct r300_context* r300) } vformat->vap_prog_stream_cntl[i >> 1] |= (R300_LAST_VEC << (i & 1 ? 16 : 0)); + + vformat->count = (i >> 1) + 1; + r300->vertex_stream_state.size = (1 + vformat->count) * 2; } static void r300_rs_col(struct r300_rs_block* rs, int id, int ptr, @@ -410,31 +424,29 @@ static void r300_update_rs_block(struct r300_context* r300, /* Now, after all that, see if we actually need to update the state. */ if (memcmp(r300->rs_block_state.state, &rs, sizeof(struct r300_rs_block))) { memcpy(r300->rs_block_state.state, &rs, sizeof(struct r300_rs_block)); - r300->rs_block_state.size = 5 + count; - r300->rs_block_state.dirty = TRUE; + r300->rs_block_state.size = 5 + count*2; } } /* Update the shader-dependant states. */ static void r300_update_derived_shader_state(struct r300_context* r300) { + struct r300_vertex_shader* vs = r300->vs_state.state; struct r300_screen* r300screen = r300_screen(r300->context.screen); - struct r300_vertex_info *vformat = - (struct r300_vertex_info*)r300->vertex_format_state.state; - struct vertex_info* vinfo = &vformat->vinfo; + struct r300_vap_output_state *vap_out = + (struct r300_vap_output_state*)r300->vap_output_state.state; - /* Mmm, delicious hax */ - memset(r300->vertex_format_state.state, 0, sizeof(struct r300_vertex_info)); - memcpy(vinfo->hwfmt, r300->vs->hwfmt, sizeof(uint)*4); + /* XXX Mmm, delicious hax */ + memset(&r300->vertex_info, 0, sizeof(struct vertex_info)); + memcpy(vap_out, vs->hwfmt, sizeof(uint)*4); - r300_update_rs_block(r300, &r300->vs->outputs, &r300->fs->inputs); + r300_update_rs_block(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( - (struct vertex_info*)r300->vertex_format_state.state); + draw_compute_vertex_size(&r300->vertex_info); r300_swtcl_vertex_psc(r300); } } @@ -510,14 +522,74 @@ static void r300_update_ztop(struct r300_context* r300) r300->ztop_state.dirty = TRUE; } +static void r300_merge_textures_and_samplers(struct r300_context* r300) +{ + struct r300_textures_state *state = + (struct r300_textures_state*)r300->textures_state.state; + struct r300_texture_sampler_state *texstate; + struct r300_sampler_state *sampler; + struct r300_texture *tex; + unsigned min_level, max_level, i, size; + unsigned count = MIN2(state->texture_count, state->sampler_count); + + state->tx_enable = 0; + size = 2; + + for (i = 0; i < count; i++) { + if (state->textures[i] && state->sampler_states[i]) { + state->tx_enable |= 1 << i; + + tex = state->textures[i]; + sampler = state->sampler_states[i]; + + texstate = &state->regs[i]; + memcpy(texstate->format, &tex->state, sizeof(uint32_t)*3); + texstate->filter[0] = sampler->filter0; + texstate->filter[1] = sampler->filter1; + texstate->border_color = sampler->border_color; + texstate->tile_config = R300_TXO_MACRO_TILE(tex->macrotile) | + R300_TXO_MICRO_TILE(tex->microtile); + + /* to emulate 1D textures through 2D ones correctly */ + if (tex->tex.target == PIPE_TEXTURE_1D) { + texstate->filter[0] &= ~R300_TX_WRAP_T_MASK; + texstate->filter[0] |= R300_TX_WRAP_T(R300_TX_CLAMP_TO_EDGE); + } + + if (tex->is_npot) { + /* NPOT textures don't support mip filter, unfortunately. + * This prevents incorrect rendering. */ + texstate->filter[0] &= ~R300_TX_MIN_FILTER_MIP_MASK; + } else { + /* 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); + texstate->format[0] |= R300_TX_NUM_LEVELS(max_level); + texstate->filter[0] |= R300_TX_MAX_MIP_LEVEL(min_level); + } + + texstate->filter[0] |= i << 28; + + size += 16; + state->count = i+1; + } + } + + r300->textures_state.size = size; +} + void r300_update_derived_state(struct r300_context* r300) { - /* XXX */ - if (r300->dirty_state & - (R300_NEW_FRAGMENT_SHADER | R300_NEW_VERTEX_SHADER) || - r300->vertex_format_state.dirty || r300->rs_state.dirty) { + if (r300->rs_block_state.dirty || + r300->vertex_stream_state.dirty || /* XXX put updating this state out of this file */ + r300->rs_state.dirty) { /* XXX and remove this one (tcl_bypass dependency) */ r300_update_derived_shader_state(r300); } + if (r300->textures_state.dirty) { + r300_merge_textures_and_samplers(r300); + } + r300_update_ztop(r300); } diff --git a/src/gallium/drivers/r300/r300_state_inlines.h b/src/gallium/drivers/r300/r300_state_inlines.h index 0e1cb328d1..2f3a56e1fb 100644 --- a/src/gallium/drivers/r300/r300_state_inlines.h +++ b/src/gallium/drivers/r300/r300_state_inlines.h @@ -384,8 +384,7 @@ r300_translate_vertex_data_type(enum pipe_format format) { desc = util_format_description(format); - if (desc->layout != UTIL_FORMAT_LAYOUT_ARITH && - desc->layout != UTIL_FORMAT_LAYOUT_ARRAY) { + if (desc->layout != UTIL_FORMAT_LAYOUT_PLAIN) { debug_printf("r300: Bad format %s in %s:%d\n", util_format_name(format), __FUNCTION__, __LINE__); assert(0); @@ -458,8 +457,7 @@ r300_translate_vertex_data_swizzle(enum pipe_format format) { assert(format); - if (desc->layout != UTIL_FORMAT_LAYOUT_ARITH && - desc->layout != UTIL_FORMAT_LAYOUT_ARRAY) { + if (desc->layout != UTIL_FORMAT_LAYOUT_PLAIN) { debug_printf("r300: Bad format %s in %s:%d\n", util_format_name(format), __FUNCTION__, __LINE__); return 0; diff --git a/src/gallium/drivers/r300/r300_state_invariant.c b/src/gallium/drivers/r300/r300_state_invariant.c index 97927acf1b..4a2c68269b 100644 --- a/src/gallium/drivers/r300/r300_state_invariant.c +++ b/src/gallium/drivers/r300/r300_state_invariant.c @@ -38,7 +38,8 @@ struct pipe_viewport_state r300_viewport_identity = { * * Note that eventually this should be empty, but it's useful for development * and general unduplication of code. */ -void r300_emit_invariant_state(struct r300_context* r300, void* state) +void r300_emit_invariant_state(struct r300_context* r300, + unsigned size, void* state) { struct r300_capabilities* caps = r300_screen(r300->context.screen)->caps; CS_LOCALS(r300); diff --git a/src/gallium/drivers/r300/r300_state_invariant.h b/src/gallium/drivers/r300/r300_state_invariant.h index 5d1a963654..83d031c7fe 100644 --- a/src/gallium/drivers/r300/r300_state_invariant.h +++ b/src/gallium/drivers/r300/r300_state_invariant.h @@ -25,6 +25,7 @@ struct r300_context; -void r300_emit_invariant_state(struct r300_context* r300, void* state); +void r300_emit_invariant_state(struct r300_context* r300, + unsigned size, void* state); #endif /* R300_STATE_INVARIANT_H */ diff --git a/src/gallium/drivers/r300/r300_texture.c b/src/gallium/drivers/r300/r300_texture.c index ed2be06254..2246c75056 100644 --- a/src/gallium/drivers/r300/r300_texture.c +++ b/src/gallium/drivers/r300/r300_texture.c @@ -70,6 +70,12 @@ static uint32_t r300_translate_texformat(enum pipe_format format) R300_TX_FORMAT_B_SHIFT, R300_TX_FORMAT_A_SHIFT }; + const uint32_t swizzle[4] = { + R300_TX_FORMAT_X, + R300_TX_FORMAT_Y, + R300_TX_FORMAT_Z, + R300_TX_FORMAT_W + }; const uint32_t sign_bit[4] = { R300_TX_FORMAT_SIGNED_X, R300_TX_FORMAT_SIGNED_Y, @@ -119,16 +125,16 @@ static uint32_t r300_translate_texformat(enum pipe_format format) switch (desc->swizzle[i]) { case UTIL_FORMAT_SWIZZLE_X: case UTIL_FORMAT_SWIZZLE_NONE: - result |= R300_TX_FORMAT_X << swizzle_shift[i]; + result |= swizzle[0] << swizzle_shift[i]; break; case UTIL_FORMAT_SWIZZLE_Y: - result |= R300_TX_FORMAT_Y << swizzle_shift[i]; + result |= swizzle[1] << swizzle_shift[i]; break; case UTIL_FORMAT_SWIZZLE_Z: - result |= R300_TX_FORMAT_Z << swizzle_shift[i]; + result |= swizzle[2] << swizzle_shift[i]; break; case UTIL_FORMAT_SWIZZLE_W: - result |= R300_TX_FORMAT_W << swizzle_shift[i]; + result |= swizzle[3] << swizzle_shift[i]; break; case UTIL_FORMAT_SWIZZLE_0: result |= R300_TX_FORMAT_ZERO << swizzle_shift[i]; @@ -142,7 +148,7 @@ static uint32_t r300_translate_texformat(enum pipe_format format) } /* Compressed formats. */ - if (desc->layout == UTIL_FORMAT_LAYOUT_DXT) { + if (desc->layout == UTIL_FORMAT_LAYOUT_COMPRESSED) { switch (format) { case PIPE_FORMAT_DXT1_RGB: case PIPE_FORMAT_DXT1_RGBA: @@ -499,7 +505,7 @@ boolean r300_is_sampler_format_supported(enum pipe_format format) static void r300_setup_texture_state(struct r300_screen* screen, struct r300_texture* tex) { - struct r300_texture_state* state = &tex->state; + struct r300_texture_format_state* state = &tex->state; struct pipe_texture *pt = &tex->tex; unsigned i; boolean is_r500 = screen->caps->is_r500; diff --git a/src/gallium/drivers/r300/r300_vs.c b/src/gallium/drivers/r300/r300_vs.c index a6786c321c..60a04bbfed 100644 --- a/src/gallium/drivers/r300/r300_vs.c +++ b/src/gallium/drivers/r300/r300_vs.c @@ -368,8 +368,8 @@ void r300_translate_vertex_shader(struct r300_context* r300, 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; + struct r300_vertex_shader* vs = r300->vs_state.state; + int tex_output = vs->wpos_tex_output; uint32_t tex_fmt = R300_INPUT_CNTL_TC0 << tex_output; uint32_t* hwfmt = vs->hwfmt; |