diff options
Diffstat (limited to 'src/gallium/drivers/r300')
-rw-r--r-- | src/gallium/drivers/r300/r300_context.c | 16 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_context.h | 20 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_debug.c | 82 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_emit.c | 27 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_flush.c | 42 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_query.c | 18 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_render.c | 37 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_screen.c | 1 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_screen.h | 30 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_state.c | 84 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_state_derived.c | 15 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_vs.c | 20 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_vs.h | 6 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_winsys.h | 9 |
14 files changed, 303 insertions, 104 deletions
diff --git a/src/gallium/drivers/r300/r300_context.c b/src/gallium/drivers/r300/r300_context.c index 0444fdac7d..9837deaa5e 100644 --- a/src/gallium/drivers/r300/r300_context.c +++ b/src/gallium/drivers/r300/r300_context.c @@ -80,6 +80,9 @@ static void r300_destroy_context(struct pipe_context* context) FREE(r300->ztop_state.state); FREE(r300->fs_constants.state); FREE(r300->vs_constants.state); + if (!r300->screen->caps.has_tcl) { + FREE(r300->vertex_stream_state.state); + } FREE(r300); } @@ -151,6 +154,16 @@ static void r300_setup_atoms(struct r300_context* r300) r300->ztop_state.state = CALLOC_STRUCT(r300_ztop_state); r300->fs_constants.state = CALLOC_STRUCT(r300_constant_buffer); r300->vs_constants.state = CALLOC_STRUCT(r300_constant_buffer); + if (!r300->screen->caps.has_tcl) { + r300->vertex_stream_state.state = CALLOC_STRUCT(r300_vertex_stream_state); + } + + /* Some non-CSO atoms don't use the state pointer. */ + r300->invariant_state.allow_null_state = TRUE; + r300->fs_rc_constant_state.allow_null_state = TRUE; + r300->pvs_flush.allow_null_state = TRUE; + r300->query_start.allow_null_state = TRUE; + r300->texture_cache_inval.allow_null_state = TRUE; } struct pipe_context* r300_create_context(struct pipe_screen* screen, @@ -201,6 +214,9 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen, draw_set_rasterize_stage(r300->draw, r300_draw_stage(r300)); /* Enable Draw's clipping. */ draw_set_driver_clipping(r300->draw, FALSE); + /* Disable converting points/lines to triangles. */ + draw_wide_line_threshold(r300->draw, 10000000.f); + draw_wide_point_threshold(r300->draw, 10000000.f); } r300_setup_atoms(r300); diff --git a/src/gallium/drivers/r300/r300_context.h b/src/gallium/drivers/r300/r300_context.h index 5ad448978b..e44906d009 100644 --- a/src/gallium/drivers/r300/r300_context.h +++ b/src/gallium/drivers/r300/r300_context.h @@ -55,6 +55,8 @@ struct r300_atom { unsigned size; /* Whether this atom should be emitted. */ boolean dirty; + /* Whether this atom may be emitted with state == NULL. */ + boolean allow_null_state; }; struct r300_blend_state { @@ -88,8 +90,10 @@ struct r300_dsa_state { }; struct r300_rs_state { - /* Draw-specific rasterizer state */ + /* Original rasterizer state. */ struct pipe_rasterizer_state rs; + /* Draw-specific rasterizer state. */ + struct pipe_rasterizer_state rs_draw; uint32_t vap_control_status; /* R300_VAP_CNTL_STATUS: 0x2140 */ uint32_t antialiasing_config; /* R300_GB_AA_CONFIG: 0x4020 */ @@ -235,10 +239,6 @@ struct r300_constant_buffer { struct r300_query { /* The kind of query. Currently only OQ is supported. */ unsigned type; - /* Whether this query is currently active. Only active queries will - * get emitted into the command stream, and only active queries get - * tallied. */ - boolean active; /* The current count of this query. Required to be at least 32 bits. */ unsigned int count; /* The offset of this query into the query buffer, in bytes. */ @@ -304,16 +304,6 @@ struct r300_texture { 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]; -}; - struct r300_vertex_element_state { unsigned count; struct pipe_vertex_element velem[PIPE_MAX_ATTRIBS]; diff --git a/src/gallium/drivers/r300/r300_debug.c b/src/gallium/drivers/r300/r300_debug.c index 8eb321fa08..85a1aa7b06 100644 --- a/src/gallium/drivers/r300/r300_debug.c +++ b/src/gallium/drivers/r300/r300_debug.c @@ -40,6 +40,7 @@ static struct debug_option debug_options[] = { { "texalloc", DBG_TEXALLOC, "Texture allocation (for debugging)" }, { "fall", DBG_FALL, "Fallbacks (for debugging)" }, { "rs", DBG_RS, "Rasterizer (for debugging)" }, + { "fb", DBG_FB, "Framebuffer (for debugging)" }, { "anisohq", DBG_ANISOHQ, "High quality anisotropic filtering (for benchmarking)" }, { "notiling", DBG_NO_TILING, "Disable tiling (for benchmarking)" }, { "noimmd", DBG_NO_IMMD, "Disable immediate mode (for benchmarking)" }, @@ -97,3 +98,84 @@ void r300_init_debug(struct r300_screen * screen) } } } + +void r500_dump_rs_block(struct r300_rs_block *rs) +{ + unsigned count, ip, it_count, ic_count, i, j; + unsigned tex_ptr; + unsigned col_ptr, col_fmt; + + count = rs->inst_count & 0xf; + count++; + + it_count = rs->count & 0x7f; + ic_count = (rs->count >> 7) & 0xf; + + fprintf(stderr, "RS Block: %d texcoords (linear), %d colors (perspective)\n", + it_count, ic_count); + fprintf(stderr, "%d instructions\n", count); + + for (i = 0; i < count; i++) { + if (rs->inst[i] & 0x10) { + ip = rs->inst[i] & 0xf; + fprintf(stderr, "texture: ip %d to psf %d\n", + ip, (rs->inst[i] >> 5) & 0x7f); + + tex_ptr = rs->ip[ip] & 0xffffff; + fprintf(stderr, " : "); + + j = 3; + do { + if (tex_ptr & 0x3f == 63) { + fprintf(stderr, "1.0"); + } else if (tex_ptr & 0x3f == 62) { + fprintf(stderr, "0.0"); + } else { + fprintf(stderr, "[%d]", tex_ptr & 0x3f); + } + } while (j-- && fprintf(stderr, "/")); + fprintf(stderr, "\n"); + } + + if (rs->inst[i] & 0x10000) { + ip = (rs->inst[i] >> 12) & 0xf; + fprintf(stderr, "color: ip %d to psf %d\n", + ip, (rs->inst[i] >> 18) & 0x7f); + + col_ptr = (rs->ip[ip] >> 24) & 0x7; + col_fmt = (rs->ip[ip] >> 27) & 0xf; + fprintf(stderr, " : offset %d ", col_ptr); + + switch (col_fmt) { + case 0: + fprintf(stderr, "(R/G/B/A)"); + break; + case 1: + fprintf(stderr, "(R/G/B/0)"); + break; + case 2: + fprintf(stderr, "(R/G/B/1)"); + break; + case 4: + fprintf(stderr, "(0/0/0/A)"); + break; + case 5: + fprintf(stderr, "(0/0/0/0)"); + break; + case 6: + fprintf(stderr, "(0/0/0/1)"); + break; + case 8: + fprintf(stderr, "(1/1/1/A)"); + break; + case 9: + fprintf(stderr, "(1/1/1/0)"); + break; + case 10: + fprintf(stderr, "(1/1/1/1)"); + break; + } + fprintf(stderr, "\n"); + } + } +} diff --git a/src/gallium/drivers/r300/r300_emit.c b/src/gallium/drivers/r300/r300_emit.c index 568109cf96..7f7f2929cc 100644 --- a/src/gallium/drivers/r300/r300_emit.c +++ b/src/gallium/drivers/r300/r300_emit.c @@ -548,8 +548,8 @@ void r300_emit_query_start(struct r300_context *r300, unsigned size, void*state) } -static void r300_emit_query_finish(struct r300_context *r300, - struct r300_query *query) +static void r300_emit_query_end_frag_pipes(struct r300_context *r300, + struct r300_query *query) { struct r300_capabilities* caps = &r300->screen->caps; CS_LOCALS(r300); @@ -604,8 +604,8 @@ static void r300_emit_query_finish(struct r300_context *r300, END_CS; } -static void rv530_emit_query_single(struct r300_context *r300, - struct r300_query *query) +static void rv530_emit_query_end_single_z(struct r300_context *r300, + struct r300_query *query) { CS_LOCALS(r300); @@ -617,8 +617,8 @@ static void rv530_emit_query_single(struct r300_context *r300, END_CS; } -static void rv530_emit_query_double(struct r300_context *r300, - struct r300_query *query) +static void rv530_emit_query_end_double_z(struct r300_context *r300, + struct r300_query *query) { CS_LOCALS(r300); @@ -646,11 +646,13 @@ void r300_emit_query_end(struct r300_context* r300) if (caps->family == CHIP_FAMILY_RV530) { if (caps->num_z_pipes == 2) - rv530_emit_query_double(r300, query); + rv530_emit_query_end_double_z(r300, query); else - rv530_emit_query_single(r300, query); + rv530_emit_query_end_single_z(r300, query); } else - r300_emit_query_finish(r300, query); + r300_emit_query_end_frag_pipes(r300, query); + + query->begin_emitted = FALSE; } void r300_emit_rs_state(struct r300_context* r300, unsigned size, void* state) @@ -714,6 +716,10 @@ void r300_emit_rs_block_state(struct r300_context* r300, unsigned count = (rs->inst_count & R300_RS_INST_COUNT_MASK) + 1; CS_LOCALS(r300); + if (SCREEN_DBG_ON(r300->screen, DBG_DRAW)) { + r500_dump_rs_block(rs); + } + DBG(r300, DBG_DRAW, "r300: RS emit:\n"); BEGIN_CS(size); @@ -1094,7 +1100,8 @@ validate: } } /* ...occlusion query buffer... */ - if (r300->query_start.dirty) { + if (r300->query_start.dirty || + (r300->query_current && r300->query_current->begin_emitted)) { if (!r300_add_buffer(r300->rws, r300->oqbo, 0, RADEON_GEM_DOMAIN_GTT)) { r300->context.flush(&r300->context, 0, NULL); diff --git a/src/gallium/drivers/r300/r300_flush.c b/src/gallium/drivers/r300/r300_flush.c index e78c6a3624..d6876c1903 100644 --- a/src/gallium/drivers/r300/r300_flush.c +++ b/src/gallium/drivers/r300/r300_flush.c @@ -1,5 +1,6 @@ /* * Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com> + * Copyright 2010 Marek Olšák <maraeo@gmail.com> * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -37,6 +38,8 @@ static void r300_flush(struct pipe_context* pipe, struct r300_context *r300 = r300_context(pipe); struct r300_query *query; struct r300_atom *atom; + struct pipe_framebuffer_state *fb; + unsigned i; CS_LOCALS(r300); (void) cs_count; @@ -48,15 +51,15 @@ static void r300_flush(struct pipe_context* pipe, draw_flush(r300->draw); } - r300_emit_query_end(r300); - if (r300->dirty_hw) { + r300_emit_query_end(r300); + FLUSH_CS; r300->dirty_hw = 0; /* New kitchen sink, baby. */ foreach(atom, &r300->atom_list) { - if (atom->state) { + if (atom->state || atom->allow_null_state) { atom->dirty = TRUE; } } @@ -72,6 +75,39 @@ static void r300_flush(struct pipe_context* pipe, foreach(query, &r300->query_list) { query->flushed = TRUE; } + + /* XXX + * + * This is a preliminary implementation of glFinish. Note that st/mesa + * uses a non-null fence when glFinish is called and then waits for + * the fence. Instead of returning the actual fence, we do the sync + * directly. + * + * The ideal implementation should use something like EmitIrqLocked and + * WaitIrq, or better, real fences. + * + * This feature degrades performance to the level of r300c for games that + * use glFinish a lot, even openarena does. Ideally we wouldn't need + * glFinish at all if we had proper throttling in swapbuffers so that + * the CPU wouldn't outrun the GPU by several frames, so this is basically + * a temporary fix for the input lag. Once swap&sync works with DRI2, + * I'll be happy to remove this code. + * + * - M. */ + if (fence && r300->fb_state.state) { + fb = r300->fb_state.state; + + for (i = 0; i < fb->nr_cbufs; i++) { + if (fb->cbufs[i]->texture) { + r300->rws->buffer_wait(r300->rws, + r300_texture(fb->cbufs[i]->texture)->buffer); + } + if (fb->zsbuf) { + r300->rws->buffer_wait(r300->rws, + r300_texture(fb->zsbuf->texture)->buffer); + } + } + } } void r300_init_flush_functions(struct r300_context* r300) diff --git a/src/gallium/drivers/r300/r300_query.c b/src/gallium/drivers/r300/r300_query.c index 5c27796e89..6acbac2219 100644 --- a/src/gallium/drivers/r300/r300_query.c +++ b/src/gallium/drivers/r300/r300_query.c @@ -43,8 +43,6 @@ static struct pipe_query *r300_create_query(struct pipe_context *pipe, q->type = query_type; assert(q->type == PIPE_QUERY_OCCLUSION_COUNTER); - q->active = FALSE; - if (r300screen->caps.family == CHIP_FAMILY_RV530) query_size = r300screen->caps.num_z_pipes * sizeof(uint32_t); else @@ -59,6 +57,7 @@ static struct pipe_query *r300_create_query(struct pipe_context *pipe, /* XXX */ if (q->offset >= 4096) { q->offset = 0; + fprintf(stderr, "r300: Rewinding OQBO...\n"); } return (struct pipe_query*)q; @@ -80,7 +79,12 @@ static void r300_begin_query(struct pipe_context* pipe, struct r300_context* r300 = r300_context(pipe); struct r300_query* q = (struct r300_query*)query; - assert(r300->query_current == NULL); + if (r300->query_current != NULL) { + fprintf(stderr, "r300: begin_query: " + "Some other query has already been started.\n"); + assert(0); + return; + } pipe_buffer_write(pipe, r300->oqbo, @@ -97,10 +101,14 @@ static void r300_end_query(struct pipe_context* pipe, struct pipe_query* query) { struct r300_context* r300 = r300_context(pipe); - struct r300_query* q = (struct r300_query*)query; + + if ((struct r300_query*)query != r300->query_current) { + fprintf(stderr, "r300: end_query: Got invalid query.\n"); + assert(0); + return; + } r300_emit_query_end(r300); - q->begin_emitted = false; r300->query_current = NULL; } diff --git a/src/gallium/drivers/r300/r300_render.c b/src/gallium/drivers/r300/r300_render.c index 8795410efd..e1f61982be 100644 --- a/src/gallium/drivers/r300/r300_render.c +++ b/src/gallium/drivers/r300/r300_render.c @@ -735,6 +735,8 @@ void r300_swtcl_draw_arrays(struct pipe_context* pipe, return; } + r300_update_derived_state(r300); + for (i = 0; i < r300->vertex_buffer_count; i++) { void* buf = pipe_buffer_map(pipe, r300->vertex_buffer[i].buffer, @@ -747,6 +749,10 @@ void r300_swtcl_draw_arrays(struct pipe_context* pipe, draw_arrays(r300->draw, mode, start, count); + /* XXX Not sure whether this is the best fix. + * It prevents CS from being rejected and weird assertion failures. */ + draw_flush(r300->draw); + for (i = 0; i < r300->vertex_buffer_count; i++) { pipe_buffer_unmap(pipe, r300->vertex_buffer[i].buffer, vb_transfer[i]); @@ -779,6 +785,8 @@ void r300_swtcl_draw_range_elements(struct pipe_context* pipe, return; } + r300_update_derived_state(r300); + for (i = 0; i < r300->vertex_buffer_count; i++) { void* buf = pipe_buffer_map(pipe, r300->vertex_buffer[i].buffer, @@ -794,6 +802,10 @@ void r300_swtcl_draw_range_elements(struct pipe_context* pipe, draw_arrays(r300->draw, mode, start, count); + /* XXX Not sure whether this is the best fix. + * It prevents CS from being rejected and weird assertion failures. */ + draw_flush(r300->draw); + for (i = 0; i < r300->vertex_buffer_count; i++) { pipe_buffer_unmap(pipe, r300->vertex_buffer[i].buffer, vb_transfer[i]); @@ -827,7 +839,7 @@ struct r300_render { size_t vbo_max_used; void * vbo_ptr; - struct pipe_transfer *vbo_transfer; + struct pipe_transfer *vbo_transfer; }; static INLINE struct r300_render* @@ -842,8 +854,6 @@ r300_render_get_vertex_info(struct vbuf_render* render) struct r300_render* r300render = r300_render(render); struct r300_context* r300 = r300render->r300; - r300_update_derived_state(r300); - return &r300->vertex_info; } @@ -891,10 +901,6 @@ static void r300_render_unmap_vertices(struct vbuf_render* render, { struct r300_render* r300render = r300_render(render); struct pipe_context* context = &r300render->r300->context; - CS_LOCALS(r300render->r300); - BEGIN_CS(2); - OUT_CS_REG(R300_VAP_VF_MAX_VTX_INDX, max); - END_CS; r300render->vbo_max_used = MAX2(r300render->vbo_max_used, r300render->vertex_size * (max + 1)); @@ -928,10 +934,13 @@ static void r500_render_draw_arrays(struct vbuf_render* render, struct r300_context* r300 = r300render->r300; uint8_t* ptr; unsigned i; + unsigned dwords = 6; CS_LOCALS(r300); - r300_prepare_for_rendering(r300, PREP_FIRST_DRAW, NULL, 2, 0, 0); + (void) i; (void) ptr; + + r300_prepare_for_rendering(r300, PREP_FIRST_DRAW, NULL, dwords, 0, 0); DBG(r300, DBG_DRAW, "r300: Doing vbuf render, count %d\n", count); @@ -952,7 +961,10 @@ static void r500_render_draw_arrays(struct vbuf_render* render, r300render->vbo_transfer); */ - BEGIN_CS(2); + BEGIN_CS(dwords); + OUT_CS_REG(R300_GA_COLOR_CONTROL, + r300_provoking_vertex_fixes(r300, r300render->prim)); + OUT_CS_REG(R300_VAP_VF_MAX_VTX_INDX, count - 1); OUT_CS_PKT3(R300_PACKET3_3D_DRAW_VBUF_2, 0); OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_LIST | (count << 16) | r300render->hwprim); @@ -966,13 +978,18 @@ static void r500_render_draw_elements(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; + unsigned dwords = 6 + (count+1)/2; + unsigned max_index = (r300render->vbo_size - r300render->vbo_offset) / + (r300render->r300->vertex_info.size * 4) - 1; CS_LOCALS(r300); r300_prepare_for_rendering(r300, PREP_FIRST_DRAW, NULL, dwords, 0, 0); BEGIN_CS(dwords); + OUT_CS_REG(R300_GA_COLOR_CONTROL, + r300_provoking_vertex_fixes(r300, r300render->prim)); + OUT_CS_REG(R300_VAP_VF_MAX_VTX_INDX, max_index); 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_screen.c b/src/gallium/drivers/r300/r300_screen.c index 8399f5df8e..640b3d3468 100644 --- a/src/gallium/drivers/r300/r300_screen.c +++ b/src/gallium/drivers/r300/r300_screen.c @@ -115,6 +115,7 @@ static int r300_get_param(struct pipe_screen* pscreen, enum pipe_cap param) return 1; /* Unsupported features (boolean caps). */ + case PIPE_CAP_TIMER_QUERY: case PIPE_CAP_DUAL_SOURCE_BLEND: case PIPE_CAP_TGSI_CONT_SUPPORTED: case PIPE_CAP_INDEP_BLEND_ENABLE: diff --git a/src/gallium/drivers/r300/r300_screen.h b/src/gallium/drivers/r300/r300_screen.h index d58aa138a7..29492024fe 100644 --- a/src/gallium/drivers/r300/r300_screen.h +++ b/src/gallium/drivers/r300/r300_screen.h @@ -61,19 +61,23 @@ static INLINE struct r300_screen* r300_screen(struct pipe_screen* screen) { * those changes. */ /*@{*/ -#define DBG_HELP 0x0000001 -#define DBG_FP 0x0000002 -#define DBG_VP 0x0000004 -#define DBG_CS 0x0000008 -#define DBG_DRAW 0x0000010 -#define DBG_TEX 0x0000020 -#define DBG_FALL 0x0000040 -#define DBG_ANISOHQ 0x0000080 -#define DBG_NO_TILING 0x0000100 -#define DBG_NO_IMMD 0x0000200 -#define DBG_STATS 0x0000400 -#define DBG_RS 0x0000800 -#define DBG_TEXALLOC 0x0001000 +#define DBG_HELP (1 << 0) +/* Logging. */ +#define DBG_FP (1 << 1) +#define DBG_VP (1 << 2) +#define DBG_CS (1 << 3) +#define DBG_DRAW (1 << 4) +#define DBG_TEX (1 << 5) +#define DBG_TEXALLOC (1 << 6) +#define DBG_RS (1 << 7) +#define DBG_FALL (1 << 8) +#define DBG_FB (1 << 9) +/* Features. */ +#define DBG_ANISOHQ (1 << 16) +#define DBG_NO_TILING (1 << 17) +#define DBG_NO_IMMD (1 << 18) +/* Statistics. */ +#define DBG_STATS (1 << 24) /*@}*/ static INLINE boolean SCREEN_DBG_ON(struct r300_screen * screen, unsigned flags) diff --git a/src/gallium/drivers/r300/r300_state.c b/src/gallium/drivers/r300/r300_state.c index 006a34119b..11c10e2f2a 100644 --- a/src/gallium/drivers/r300/r300_state.c +++ b/src/gallium/drivers/r300/r300_state.c @@ -566,13 +566,35 @@ static void r300_fb_set_tiling_flags(struct r300_context *r300, } } +static void r300_print_fb_surf_info(struct pipe_surface *surf, unsigned index, + const char *binding) +{ + struct pipe_resource *tex = surf->texture; + struct r300_texture *rtex = r300_texture(tex); + + fprintf(stderr, + "r300: %s[%i] Dim: %ix%i, Offset: %i, ZSlice: %i, " + "Face: %i, Level: %i, Format: %s\n" + + "r300: TEX: Macro: %s, Micro: %s, Pitch: %i, " + "Dim: %ix%ix%i, LastLevel: %i, Format: %s\n", + + binding, index, surf->width, surf->height, surf->offset, + surf->zslice, surf->face, surf->level, + util_format_short_name(surf->format), + + rtex->macrotile ? "YES" : " NO", rtex->microtile ? "YES" : " NO", + rtex->hwpitch[0], tex->width0, tex->height0, tex->depth0, + tex->last_level, util_format_short_name(tex->format)); +} + static void r300_set_framebuffer_state(struct pipe_context* pipe, const struct pipe_framebuffer_state* state) { struct r300_context* r300 = r300_context(pipe); struct pipe_framebuffer_state *old_state = r300->fb_state.state; - unsigned max_width, max_height; + unsigned max_width, max_height, i; uint32_t zbuffer_bpp = 0; if (state->nr_cbufs > 4) { @@ -634,6 +656,16 @@ static void r300->rs_state.dirty = TRUE; } } + + if (DBG_ON(r300, DBG_FB)) { + fprintf(stderr, "r300: set_framebuffer_state:\n"); + for (i = 0; i < state->nr_cbufs; i++) { + r300_print_fb_surf_info(state->cbufs[i], i, "CB"); + } + if (state->zsbuf) { + r300_print_fb_surf_info(state->zsbuf, 0, "ZB"); + } + } } /* Create fragment shader state. */ @@ -724,8 +756,12 @@ static void* r300_create_rs_state(struct pipe_context* pipe, int i; float psiz; - /* Copy rasterizer state for Draw. */ + /* Copy rasterizer state. */ rs->rs = *state; + rs->rs_draw = *state; + + /* Override some states for Draw. */ + rs->rs_draw.sprite_coord_enable = 0; /* We can do this in HW. */ #ifdef PIPE_ARCH_LITTLE_ENDIAN rs->vap_control_status = R300_VC_NO_SWAP; @@ -856,9 +892,9 @@ static void r300_bind_rs_state(struct pipe_context* pipe, void* state) int last_sprite_coord_enable = r300->sprite_coord_enable; boolean last_two_sided_color = r300->two_sided_color; - if (r300->draw) { + if (r300->draw && rs) { draw_flush(r300->draw); - draw_set_rasterizer_state(r300->draw, &rs->rs, state); + draw_set_rasterizer_state(r300->draw, &rs->rs_draw, state); } if (rs) { @@ -1200,7 +1236,7 @@ static void r300_set_vertex_buffers(struct pipe_context* pipe, } } -/* Update the PSC tables. */ +/* Initialize the PSC tables. */ static void r300_vertex_psc(struct r300_vertex_element_state *velems) { struct r300_vertex_stream_state *vstream = &velems->vertex_stream; @@ -1339,7 +1375,6 @@ static void* r300_create_vertex_elements_state(struct pipe_context* pipe, abort(); } } - } } return velems; @@ -1360,6 +1395,7 @@ static void r300_bind_vertex_elements_state(struct pipe_context *pipe, if (r300->draw) { draw_flush(r300->draw); draw_set_vertex_elements(r300->draw, velems->count, velems->velem); + return; } UPDATE_STATE(&velems->vertex_stream, r300->vertex_stream_state); @@ -1382,8 +1418,10 @@ static void* r300_create_vs_state(struct pipe_context* pipe, vs->state = *shader; vs->state.tokens = tgsi_dup_tokens(shader->tokens); + r300_init_vs_outputs(vs); + if (r300->screen->caps.has_tcl) { - r300_translate_vertex_shader(r300, vs, vs->state.tokens); + r300_translate_vertex_shader(r300, vs); } else { vs->draw_vs = draw_create_vertex_shader(r300->draw, shader); } @@ -1453,7 +1491,7 @@ static void r300_set_constant_buffer(struct pipe_context *pipe, struct r300_constant_buffer *cbuf; struct pipe_transfer *tr; void *mapped; - int max_size = 0; + int max_size = 0, max_size_bytes = 0, clamped_size = 0; switch (shader) { case PIPE_SHADER_VERTEX: @@ -1472,6 +1510,7 @@ static void r300_set_constant_buffer(struct pipe_context *pipe, assert(0); return; } + max_size_bytes = max_size * 4 * sizeof(float); if (buf == NULL || buf->width0 == 0 || (mapped = pipe_buffer_map(pipe, buf, PIPE_TRANSFER_READ, &tr)) == NULL) @@ -1480,19 +1519,21 @@ static void r300_set_constant_buffer(struct pipe_context *pipe, return; } - assert((buf->width0 % 4 * sizeof(float)) == 0); + if (shader == PIPE_SHADER_FRAGMENT || + (shader == PIPE_SHADER_VERTEX && r300->screen->caps.has_tcl)) { + assert((buf->width0 % (4 * sizeof(float))) == 0); - /* Check the size of the constant buffer. */ - /* XXX Subtract immediates and RC_STATE_* variables. */ - if (buf->width0 > (sizeof(float) * 4 * max_size)) { - fprintf(stderr, "r300: Max size of the constant buffer is " - "%i*4 floats.\n", max_size); - abort(); - } + /* Check the size of the constant buffer. */ + /* XXX Subtract immediates and RC_STATE_* variables. */ + if (buf->width0 > max_size_bytes) { + fprintf(stderr, "r300: Max size of the constant buffer is " + "%i*4 floats.\n", max_size); + } + clamped_size = MIN2(buf->width0, max_size_bytes); - memcpy(cbuf->constants, mapped, buf->width0); - cbuf->count = buf->width0 / (4 * sizeof(float)); - pipe_buffer_unmap(pipe, buf, tr); + memcpy(cbuf->constants, mapped, clamped_size); + cbuf->count = clamped_size / (4 * sizeof(float)); + } if (shader == PIPE_SHADER_VERTEX) { if (r300->screen->caps.has_tcl) { @@ -1502,12 +1543,13 @@ static void r300_set_constant_buffer(struct pipe_context *pipe, r300->pvs_flush.dirty = TRUE; } else if (r300->draw) { draw_set_mapped_constant_buffer(r300->draw, PIPE_SHADER_VERTEX, - 0, cbuf->constants, - buf->width0); + 0, mapped, buf->width0); } } else if (shader == PIPE_SHADER_FRAGMENT) { r300->fs_constants.dirty = TRUE; } + + pipe_buffer_unmap(pipe, buf, tr); } void r300_init_state_functions(struct r300_context* r300) diff --git a/src/gallium/drivers/r300/r300_state_derived.c b/src/gallium/drivers/r300/r300_state_derived.c index c738899827..7583862a1a 100644 --- a/src/gallium/drivers/r300/r300_state_derived.c +++ b/src/gallium/drivers/r300/r300_state_derived.c @@ -116,13 +116,12 @@ static void r300_draw_emit_all_attribs(struct r300_context* r300) static void r300_swtcl_vertex_psc(struct r300_context *r300) { struct r300_vertex_stream_state *vstream = r300->vertex_stream_state.state; - struct vertex_info* vinfo = &r300->vertex_info; + struct vertex_info *vinfo = &r300->vertex_info; uint16_t type, swizzle; enum pipe_format format; unsigned i, attrib_count; int* vs_output_tab = r300->stream_loc_notcl; - /* XXX hax */ memset(vstream, 0, sizeof(struct r300_vertex_stream_state)); /* For each Draw attribute, route it to the fragment shader according @@ -615,13 +614,13 @@ void r300_update_derived_state(struct r300_context* r300) if (r300->rs_block_state.dirty) { r300_update_rs_block(r300); - } - if (r300->draw) { - memset(&r300->vertex_info, 0, sizeof(struct vertex_info)); - r300_draw_emit_all_attribs(r300); - draw_compute_vertex_size(&r300->vertex_info); - r300_swtcl_vertex_psc(r300); + if (r300->draw) { + memset(&r300->vertex_info, 0, sizeof(struct vertex_info)); + r300_draw_emit_all_attribs(r300); + draw_compute_vertex_size(&r300->vertex_info); + r300_swtcl_vertex_psc(r300); + } } r300_update_hyperz_state(r300); diff --git a/src/gallium/drivers/r300/r300_vs.c b/src/gallium/drivers/r300/r300_vs.c index f3186431e1..59f89b3482 100644 --- a/src/gallium/drivers/r300/r300_vs.c +++ b/src/gallium/drivers/r300/r300_vs.c @@ -181,21 +181,23 @@ static void r300_dummy_vertex_shader( state.tokens = ureg_finalize(ureg); shader->dummy = TRUE; - r300_translate_vertex_shader(r300, shader, state.tokens); + r300_translate_vertex_shader(r300, shader); ureg_destroy(ureg); } -void r300_translate_vertex_shader(struct r300_context* r300, - struct r300_vertex_shader* vs, - const struct tgsi_token *tokens) +void r300_init_vs_outputs(struct r300_vertex_shader *vs) +{ + tgsi_scan_shader(vs->state.tokens, &vs->info); + r300_shader_read_vs_outputs(&vs->info, &vs->outputs); +} + +void r300_translate_vertex_shader(struct r300_context *r300, + struct r300_vertex_shader *vs) { struct r300_vertex_program_compiler compiler; struct tgsi_to_rc ttr; - tgsi_scan_shader(tokens, &vs->info); - r300_shader_read_vs_outputs(&vs->info, &vs->outputs); - /* Setup the compiler */ rc_init(&compiler.Base); @@ -205,7 +207,7 @@ void r300_translate_vertex_shader(struct r300_context* r300, if (compiler.Base.Debug) { debug_printf("r300: Initial vertex program\n"); - tgsi_dump(tokens, 0); + tgsi_dump(vs->state.tokens, 0); } /* Translate TGSI to our internal representation */ @@ -213,7 +215,7 @@ void r300_translate_vertex_shader(struct r300_context* r300, ttr.info = &vs->info; ttr.use_half_swizzles = FALSE; - r300_tgsi_to_rc(&ttr, tokens); + r300_tgsi_to_rc(&ttr, vs->state.tokens); compiler.RequiredOutputs = ~(~0 << (vs->info.num_outputs + 1)); compiler.SetHwInputOutput = &set_vertex_inputs_outputs; diff --git a/src/gallium/drivers/r300/r300_vs.h b/src/gallium/drivers/r300/r300_vs.h index 57b3fbca0b..31890d78ca 100644 --- a/src/gallium/drivers/r300/r300_vs.h +++ b/src/gallium/drivers/r300/r300_vs.h @@ -56,8 +56,8 @@ struct r300_vertex_shader { void *draw_vs; }; -void r300_translate_vertex_shader(struct r300_context* r300, - struct r300_vertex_shader* vs, - const struct tgsi_token *tokens); +void r300_init_vs_outputs(struct r300_vertex_shader *vs); +void r300_translate_vertex_shader(struct r300_context *r300, + struct r300_vertex_shader *vs); #endif /* R300_VS_H */ diff --git a/src/gallium/drivers/r300/r300_winsys.h b/src/gallium/drivers/r300/r300_winsys.h index 1642981eaa..3d0413f90a 100644 --- a/src/gallium/drivers/r300/r300_winsys.h +++ b/src/gallium/drivers/r300/r300_winsys.h @@ -87,13 +87,8 @@ struct r300_winsys_screen { struct r300_winsys_buffer **pdst, struct r300_winsys_buffer *src); - boolean (*buffer_references)(struct r300_winsys_buffer *a, - struct r300_winsys_buffer *b); - - void (*buffer_flush_range)(struct r300_winsys_screen *rws, - struct r300_winsys_buffer *buf, - unsigned offset, - unsigned length); + void (*buffer_wait)(struct r300_winsys_screen *rws, + struct r300_winsys_buffer *buf); /* Add a pipe_resource to the list of buffer objects to validate. */ boolean (*add_buffer)(struct r300_winsys_screen *winsys, |