summaryrefslogtreecommitdiff
path: root/src/gallium/drivers/r300
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/drivers/r300')
-rw-r--r--src/gallium/drivers/r300/Makefile2
-rw-r--r--src/gallium/drivers/r300/r300_blit.c10
-rw-r--r--src/gallium/drivers/r300/r300_context.c70
-rw-r--r--src/gallium/drivers/r300/r300_context.h81
-rw-r--r--src/gallium/drivers/r300/r300_emit.c384
-rw-r--r--src/gallium/drivers/r300/r300_emit.h54
-rw-r--r--src/gallium/drivers/r300/r300_fs.c7
-rw-r--r--src/gallium/drivers/r300/r300_render.c114
-rw-r--r--src/gallium/drivers/r300/r300_state.c109
-rw-r--r--src/gallium/drivers/r300/r300_state_derived.c126
-rw-r--r--src/gallium/drivers/r300/r300_state_inlines.h6
-rw-r--r--src/gallium/drivers/r300/r300_state_invariant.c3
-rw-r--r--src/gallium/drivers/r300/r300_state_invariant.h3
-rw-r--r--src/gallium/drivers/r300/r300_texture.c18
-rw-r--r--src/gallium/drivers/r300/r300_vs.c4
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;