diff options
Diffstat (limited to 'src/gallium/drivers/r300')
35 files changed, 2182 insertions, 1181 deletions
diff --git a/src/gallium/drivers/r300/Makefile b/src/gallium/drivers/r300/Makefile index a6529b2060..5a8e00f15a 100644 --- a/src/gallium/drivers/r300/Makefile +++ b/src/gallium/drivers/r300/Makefile @@ -13,6 +13,7 @@ C_SOURCES = \ r300_fs.c \ r300_query.c \ r300_render.c \ + r300_resource.c \ r300_screen.c \ r300_screen_buffer.c \ r300_state.c \ diff --git a/src/gallium/drivers/r300/SConscript b/src/gallium/drivers/r300/SConscript index 221878c1c0..08aec427a1 100644 --- a/src/gallium/drivers/r300/SConscript +++ b/src/gallium/drivers/r300/SConscript @@ -23,6 +23,7 @@ r300 = env.ConvenienceLibrary( 'r300_fs.c', 'r300_query.c', 'r300_render.c', + 'r300_resource.c', 'r300_screen.c', 'r300_screen_buffer.c', 'r300_state.c', diff --git a/src/gallium/drivers/r300/r300_blit.c b/src/gallium/drivers/r300/r300_blit.c index bcdf950df9..322eaa83bd 100644 --- a/src/gallium/drivers/r300/r300_blit.c +++ b/src/gallium/drivers/r300/r300_blit.c @@ -32,7 +32,7 @@ static void r300_blitter_save_states(struct r300_context* r300) util_blitter_save_depth_stencil_alpha(r300->blitter, r300->dsa_state.state); 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_fragment_shader(r300->blitter, r300->fs.state); util_blitter_save_vertex_shader(r300->blitter, r300->vs_state.state); util_blitter_save_viewport(r300->blitter, &r300->viewport); util_blitter_save_clip(r300->blitter, &r300->clip); @@ -111,11 +111,12 @@ 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, state->sampler_count, (void**)state->sampler_states); + r300->blitter, state->sampler_state_count, + (void**)state->sampler_states); util_blitter_save_fragment_sampler_views( - r300->blitter, state->texture_count, - state->fragment_sampler_views); + r300->blitter, state->sampler_view_count, + (struct pipe_sampler_view**)state->sampler_views); /* Do a copy */ util_blitter_copy(r300->blitter, @@ -137,8 +138,8 @@ void r300_surface_copy(struct pipe_context* pipe, if (!pipe->screen->is_format_supported(pipe->screen, old_format, src->texture->target, - PIPE_TEXTURE_USAGE_RENDER_TARGET | - PIPE_TEXTURE_USAGE_SAMPLER, 0)) { + PIPE_BIND_RENDER_TARGET | + PIPE_BIND_SAMPLER_VIEW, 0)) { switch (util_format_get_blocksize(old_format)) { case 1: new_format = PIPE_FORMAT_I8_UNORM; diff --git a/src/gallium/drivers/r300/r300_chipset.c b/src/gallium/drivers/r300/r300_chipset.c index 4171986263..9b2163e44c 100644 --- a/src/gallium/drivers/r300/r300_chipset.c +++ b/src/gallium/drivers/r300/r300_chipset.c @@ -34,12 +34,12 @@ void r300_parse_chipset(struct r300_capabilities* caps) { /* Reasonable defaults */ caps->num_vert_fpus = 4; + caps->num_tex_units = 16; caps->has_tcl = debug_get_bool_option("RADEON_NO_TCL", FALSE) ? FALSE : TRUE; caps->is_r400 = FALSE; caps->is_r500 = FALSE; caps->high_second_pipe = FALSE; - /* Note: These are not ordered by PCI ID. I leave that task to GCC, * which will perform the ordering while collating jump tables. Instead, * I've tried to group them according to capabilities and age. */ diff --git a/src/gallium/drivers/r300/r300_chipset.h b/src/gallium/drivers/r300/r300_chipset.h index 2808486492..ff957b7c29 100644 --- a/src/gallium/drivers/r300/r300_chipset.h +++ b/src/gallium/drivers/r300/r300_chipset.h @@ -38,6 +38,8 @@ struct r300_capabilities { unsigned num_frag_pipes; /* The number of z pipes */ unsigned num_z_pipes; + /* The number of texture units. */ + unsigned num_tex_units; /* Whether or not TCL is physically present */ boolean has_tcl; /* Whether or not this is R400. The differences compared to their R3xx diff --git a/src/gallium/drivers/r300/r300_context.c b/src/gallium/drivers/r300/r300_context.c index 4b470b2c6a..06af2c2fd8 100644 --- a/src/gallium/drivers/r300/r300_context.c +++ b/src/gallium/drivers/r300/r300_context.c @@ -35,7 +35,6 @@ #include "r300_screen.h" #include "r300_screen_buffer.h" #include "r300_state_invariant.h" -#include "r300_transfer.h" #include "r300_winsys.h" static void r300_destroy_context(struct pipe_context* context) @@ -47,7 +46,7 @@ static void r300_destroy_context(struct pipe_context* context) draw_destroy(r300->draw); /* Free the OQ BO. */ - context->screen->buffer_destroy(r300->oqbo); + context->screen->resource_destroy(context->screen, r300->oqbo); /* If there are any queries pending or not destroyed, remove them now. */ foreach_s(query, temp, &r300->query_list) { @@ -67,28 +66,11 @@ static void r300_destroy_context(struct pipe_context* context) FREE(r300->vap_output_state.state); FREE(r300->viewport_state.state); FREE(r300->ztop_state.state); + FREE(r300->fs_constants.state); + FREE(r300->vs_constants.state); FREE(r300); } -static unsigned int -r300_is_texture_referenced(struct pipe_context *context, - struct pipe_texture *texture, - unsigned face, unsigned level) -{ - struct r300_context* r300 = r300_context(context); - struct r300_texture* tex = (struct r300_texture*)texture; - - return r300->rws->is_buffer_referenced(r300->rws, tex->buffer); -} - -static unsigned int -r300_is_buffer_referenced(struct pipe_context *context, - struct pipe_buffer *buf) -{ - struct r300_context* r300 = r300_context(context); - - return r300_buffer_is_referenced(r300, buf); -} static void r300_flush_cb(void *data) { @@ -107,8 +89,8 @@ static void r300_flush_cb(void *data) 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; + boolean is_r500 = r300->screen->caps.is_r500; + boolean has_tcl = r300->screen->caps.has_tcl; /* Create the actual atom list. * @@ -119,6 +101,7 @@ static void r300_setup_atoms(struct r300_context* r300) * the size of 0 here. */ make_empty_list(&r300->atom_list); R300_INIT_ATOM(invariant_state, 71); + R300_INIT_ATOM(query_start, 4); R300_INIT_ATOM(ztop_state, 2); R300_INIT_ATOM(blend_state, 8); R300_INIT_ATOM(blend_color_state, is_r500 ? 3 : 2); @@ -133,8 +116,19 @@ static void r300_setup_atoms(struct r300_context* r300) R300_INIT_ATOM(vap_output_state, 6); R300_INIT_ATOM(pvs_flush, 2); R300_INIT_ATOM(vs_state, 0); + R300_INIT_ATOM(vs_constants, 0); R300_INIT_ATOM(texture_cache_inval, 2); R300_INIT_ATOM(textures_state, 0); + R300_INIT_ATOM(fs, 0); + R300_INIT_ATOM(fs_rc_constant_state, 0); + R300_INIT_ATOM(fs_constants, 0); + + /* Replace emission functions for r500. */ + if (r300->screen->caps.is_r500) { + r300->fs.emit = r500_emit_fs; + r300->fs_rc_constant_state.emit = r500_emit_fs_rc_constant_state; + r300->fs_constants.emit = r500_emit_fs_constants; + } /* Some non-CSO atoms need explicit space to store the state locally. */ r300->blend_color_state.state = CALLOC_STRUCT(r300_blend_color_state); @@ -146,6 +140,8 @@ static void r300_setup_atoms(struct r300_context* r300) 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); + r300->fs_constants.state = CALLOC_STRUCT(r300_constant_buffer); + r300->vs_constants.state = CALLOC_STRUCT(r300_constant_buffer); } struct pipe_context* r300_create_context(struct pipe_screen* screen, @@ -159,6 +155,7 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen, return NULL; r300->rws = rws; + r300->screen = r300screen; r300->context.winsys = (struct pipe_winsys*)rws; r300->context.screen = screen; @@ -170,10 +167,20 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen, r300->context.surface_copy = r300_surface_copy; r300->context.surface_fill = r300_surface_fill; - if (r300screen->caps->has_tcl) { + if (r300screen->caps.has_tcl) { r300->context.draw_arrays = r300_draw_arrays; r300->context.draw_elements = r300_draw_elements; r300->context.draw_range_elements = r300_draw_range_elements; + + if (r300screen->caps.is_r500) { + r300->emit_draw_arrays_immediate = r500_emit_draw_arrays_immediate; + r300->emit_draw_arrays = r500_emit_draw_arrays; + r300->emit_draw_elements = r500_emit_draw_elements; + } else { + r300->emit_draw_arrays_immediate = r300_emit_draw_arrays_immediate; + r300->emit_draw_arrays = r300_emit_draw_arrays; + r300->emit_draw_elements = r300_emit_draw_elements; + } } else { r300->context.draw_arrays = r300_swtcl_draw_arrays; r300->context.draw_elements = r300_draw_elements; @@ -190,23 +197,17 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen, draw_set_viewport_state(r300->draw, &r300_viewport_identity); } - r300->context.is_texture_referenced = r300_is_texture_referenced; - r300->context.is_buffer_referenced = r300_is_buffer_referenced; - r300_setup_atoms(r300); /* Open up the OQ BO. */ - r300->oqbo = screen->buffer_create(screen, 4096, - PIPE_BUFFER_USAGE_PIXEL, 4096); + r300->oqbo = pipe_buffer_create(screen, + R300_BIND_OQBO, 4096); make_empty_list(&r300->query_list); r300_init_flush_functions(r300); - r300_init_query_functions(r300); - - r300_init_transfer_functions(r300); - r300_init_state_functions(r300); + r300_init_resource_functions(r300); r300->invariant_state.dirty = TRUE; @@ -215,16 +216,16 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen, r300->blitter = util_blitter_create(&r300->context); - r300->upload_ib = u_upload_create(screen, + r300->upload_ib = u_upload_create(&r300->context, 32 * 1024, 16, - PIPE_BUFFER_USAGE_INDEX); + PIPE_BIND_INDEX_BUFFER); if (r300->upload_ib == NULL) goto no_upload_ib; - r300->upload_vb = u_upload_create(screen, + r300->upload_vb = u_upload_create(&r300->context, 128 * 1024, 16, - PIPE_BUFFER_USAGE_VERTEX); + PIPE_BIND_VERTEX_BUFFER); if (r300->upload_vb == NULL) goto no_upload_vb; diff --git a/src/gallium/drivers/r300/r300_context.h b/src/gallium/drivers/r300/r300_context.h index 0a82484e89..2e8601b65e 100644 --- a/src/gallium/drivers/r300/r300_context.h +++ b/src/gallium/drivers/r300/r300_context.h @@ -29,6 +29,7 @@ #include "pipe/p_context.h" #include "util/u_inlines.h" +#include "util/u_transfer.h" #include "r300_defines.h" #include "r300_screen.h" @@ -52,8 +53,6 @@ struct r300_atom { unsigned size; /* Whether this atom should be emitted. */ boolean dirty; - /* Another dirty flag that is never automatically cleared. */ - boolean always_dirty; }; struct r300_blend_state { @@ -79,6 +78,11 @@ struct r300_dsa_state { uint32_t z_stencil_control; /* R300_ZB_ZSTENCILCNTL: 0x4f04 */ uint32_t stencil_ref_mask; /* R300_ZB_STENCILREFMASK: 0x4f08 */ uint32_t stencil_ref_bf; /* R500_ZB_STENCILREFMASK_BF: 0x4fd4 */ + + /* Whether a two-sided stencil is enabled. */ + boolean two_sided; + /* Whether a fallback should be used for a two-sided stencil ref value. */ + boolean stencil_ref_bf_fallback; }; struct r300_rs_state { @@ -99,6 +103,17 @@ struct r300_rs_state { uint32_t line_stipple_value; /* R300_GA_LINE_STIPPLE_VALUE: 0x4260 */ uint32_t color_control; /* R300_GA_COLOR_CONTROL: 0x4278 */ uint32_t polygon_mode; /* R300_GA_POLY_MODE: 0x4288 */ + uint32_t clip_rule; /* R300_SC_CLIP_RULE: 0x43D0 */ + + /* Specifies top of Raster pipe specific enable controls, + * i.e. texture coordinates stuffing for points, lines, triangles */ + uint32_t stuffing_enable; /* R300_GB_ENABLE: 0x4008 */ + + /* Point sprites texture coordinates, 0: lower left, 1: upper right */ + float point_texcoord_left; /* R300_GA_POINT_S0: 0x4200 */ + float point_texcoord_bottom; /* R300_GA_POINT_T0: 0x4204 */ + float point_texcoord_right; /* R300_GA_POINT_S1: 0x4208 */ + float point_texcoord_top; /* R300_GA_POINT_T1: 0x420c */ }; struct r300_rs_block { @@ -124,6 +139,15 @@ 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 */ + uint32_t tile_config; /* R300_TX_OFFSET (subset thereof) */ +}; + +struct r300_sampler_view { + struct pipe_sampler_view base; + + /* Copy of r300_texture::texture_format_state with format-specific bits + * added. */ + struct r300_texture_format_state format; }; struct r300_texture_fb_state { @@ -138,21 +162,21 @@ struct r300_texture_fb_state { struct r300_textures_state { /* Textures. */ - struct pipe_sampler_view *fragment_sampler_views[8]; - int texture_count; + struct r300_sampler_view *sampler_views[16]; + int sampler_view_count; /* Sampler states. */ - struct r300_sampler_state *sampler_states[8]; - int sampler_count; + struct r300_sampler_state *sampler_states[16]; + int sampler_state_count; - /* These is the merge of the texture and sampler states. */ + /* This 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] */ + struct r300_texture_format_state format; + uint32_t filter0; /* R300_TX_FILTER0: 0x4400 */ + uint32_t filter1; /* R300_TX_FILTER1: 0x4440 */ uint32_t border_color; /* R300_TX_BORDER_COLOR: 0x45c0 */ - uint32_t tile_config; /* R300_TX_OFFSET (subset thereof) */ - } regs[8]; + } regs[16]; }; struct r300_vertex_stream_state { @@ -223,7 +247,7 @@ struct r300_query { struct r300_texture { /* Parent class */ - struct pipe_texture tex; + struct u_resource b; /* Offsets into the buffer. */ unsigned offset[R300_MAX_TEXTURE_LEVELS]; @@ -250,16 +274,19 @@ struct r300_texture { /* Total size of this texture, in bytes. */ unsigned size; - /* Whether this texture has non-power-of-two dimensions. + /* Whether this texture has non-power-of-two dimensions + * or a user-specified pitch. * It can be either a regular texture or a rectangle one. */ - boolean is_npot; + boolean uses_pitch; /* Pipe buffer backing this texture. */ struct r300_winsys_buffer *buffer; /* Registers carrying texture format data. */ - struct r300_texture_format_state state; + /* Only format-independent bits should be filled in. */ + struct r300_texture_format_state tx_format; + /* All bits should be filled in. */ struct r300_texture_fb_state fb_state; /* Buffer tiling */ @@ -289,20 +316,37 @@ struct r300_context { /* Parent class */ struct pipe_context context; + /* Emission of drawing packets. */ + void (*emit_draw_arrays_immediate)( + struct r300_context *r300, + unsigned mode, unsigned start, unsigned count); + + void (*emit_draw_arrays)( + struct r300_context *r300, + unsigned mode, unsigned count); + + void (*emit_draw_elements)( + struct r300_context *r300, struct pipe_resource* indexBuffer, + unsigned indexSize, unsigned minIndex, unsigned maxIndex, + unsigned mode, unsigned start, unsigned count); + + /* The interface to the windowing system, etc. */ struct r300_winsys_screen *rws; + /* Screen. */ + struct r300_screen *screen; /* Draw module. Used mostly for SW TCL. */ struct draw_context* draw; /* Accelerated blit support. */ struct blitter_context* blitter; /* Vertex buffer for rendering. */ - struct pipe_buffer* vbo; + struct pipe_resource* vbo; /* Offset into the VBO. */ size_t vbo_offset; /* Occlusion query buffer. */ - struct pipe_buffer* oqbo; + struct pipe_resource* oqbo; /* Query list. */ struct r300_query *query_current; struct r300_query query_list; @@ -316,14 +360,18 @@ struct r300_context { struct r300_atom blend_color_state; /* User clip planes. */ struct r300_atom clip_state; - /* Shader constants. */ - struct r300_constant_buffer shader_constants[PIPE_SHADER_TYPES]; /* Depth, stencil, and alpha state. */ struct r300_atom dsa_state; /* Fragment shader. */ - struct r300_fragment_shader* fs; + struct r300_atom fs; + /* Fragment shader RC_CONSTANT_STATE variables. */ + struct r300_atom fs_rc_constant_state; + /* Fragment shader constant buffer. */ + struct r300_atom fs_constants; /* Framebuffer state. */ struct r300_atom fb_state; + /* Occlusion query. */ + struct r300_atom query_start; /* Rasterizer state. */ struct r300_atom rs_state; /* RS block state. */ @@ -338,6 +386,8 @@ struct r300_context { struct r300_atom vap_output_state; /* Vertex shader. */ struct r300_atom vs_state; + /* Vertex shader constant buffer. */ + struct r300_atom vs_constants; /* Viewport state. */ struct r300_atom viewport_state; /* ZTOP state. */ @@ -367,27 +417,40 @@ struct r300_context { struct pipe_viewport_state viewport; - /* Bitmask of dirty state objects. */ - uint32_t dirty_state; /* Flag indicating whether or not the HW is dirty. */ uint32_t dirty_hw; /* Whether polygon offset is enabled. */ boolean polygon_offset_enabled; /* Z buffer bit depth. */ uint32_t zbuffer_bpp; - /* Whether scissor is enabled. */ - boolean scissor_enabled; + /* Whether rendering is conditional and should be skipped. */ + boolean skip_rendering; + /* Whether the two-sided stencil ref value is different for front and + * back faces, and fallback should be used for r3xx-r4xx. */ + boolean stencil_ref_bf_fallback; + /* Point sprites texcoord index, 1 bit per texcoord */ + int sprite_coord_enable; + /* upload managers */ struct u_upload_mgr *upload_vb; struct u_upload_mgr *upload_ib; }; /* Convenience cast wrapper. */ +static INLINE struct r300_texture* r300_texture(struct pipe_resource* tex) +{ + return (struct r300_texture*)tex; +} + static INLINE struct r300_context* r300_context(struct pipe_context* context) { return (struct r300_context*)context; } +static INLINE struct r300_fragment_shader *r300_fs(struct r300_context *r300) +{ + return (struct r300_fragment_shader*)r300->fs.state; +} struct pipe_context* r300_create_context(struct pipe_screen* screen, void *priv); @@ -395,12 +458,11 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen, /* Context initialization. */ struct draw_stage* r300_draw_stage(struct r300_context* r300); void r300_init_state_functions(struct r300_context* r300); -void r300_init_surface_functions(struct r300_context* r300); -void r300_init_tex_functions( struct pipe_context *pipe ); +void r300_init_resource_functions(struct r300_context* r300); static INLINE boolean CTX_DBG_ON(struct r300_context * ctx, unsigned flags) { - return SCREEN_DBG_ON(r300_screen(ctx->context.screen), flags); + return SCREEN_DBG_ON(ctx->screen, flags); } static INLINE void CTX_DBG(struct r300_context * ctx, unsigned flags, diff --git a/src/gallium/drivers/r300/r300_defines.h b/src/gallium/drivers/r300/r300_defines.h index 2e04876de9..8237c999aa 100644 --- a/src/gallium/drivers/r300/r300_defines.h +++ b/src/gallium/drivers/r300/r300_defines.h @@ -28,14 +28,7 @@ #define R300_MAX_TEXTURE_LEVELS 13 #define R300_MAX_DRAW_VBO_SIZE (1024 * 1024) -#define R300_TEXTURE_USAGE_TRANSFER PIPE_TEXTURE_USAGE_CUSTOM - -/* Non-atom dirty state flags. */ -#define R300_NEW_FRAGMENT_SHADER 0x00000020 -#define R300_NEW_FRAGMENT_SHADER_CONSTANTS 0x00000040 -#define R300_NEW_VERTEX_SHADER_CONSTANTS 0x10000000 -#define R300_NEW_QUERY 0x40000000 -#define R300_NEW_KITCHEN_SINK 0x7fffffff +#define R300_RESOURCE_FLAG_TRANSFER PIPE_RESOURCE_FLAG_DRV_PRIV /* Tiling flags. */ enum r300_buffer_tiling { diff --git a/src/gallium/drivers/r300/r300_emit.c b/src/gallium/drivers/r300/r300_emit.c index 15bcf8907f..9c4bcfc49b 100644 --- a/src/gallium/drivers/r300/r300_emit.c +++ b/src/gallium/drivers/r300/r300_emit.c @@ -64,10 +64,9 @@ 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) { + if (r300->screen->caps.is_r500) { BEGIN_CS(size); OUT_CS_REG_SEQ(R500_RB3D_CONSTANT_COLOR_AR, 2); OUT_CS(bc->blend_color_red_alpha); @@ -85,13 +84,12 @@ void r300_emit_clip_state(struct r300_context* r300, { struct pipe_clip_state* clip = (struct pipe_clip_state*)state; int i; - struct r300_screen* r300screen = r300_screen(r300->context.screen); CS_LOCALS(r300); - if (r300screen->caps->has_tcl) { + if (r300->screen->caps.has_tcl) { BEGIN_CS(size); OUT_CS_REG(R300_VAP_PVS_VECTOR_INDX_REG, - (r300screen->caps->is_r500 ? + (r300->screen->caps.is_r500 ? R500_PVS_UCP_START : R300_PVS_UCP_START)); OUT_CS_ONE_REG(R300_VAP_PVS_UPLOAD_DATA, 6 * 4); for (i = 0; i < 6; i++) { @@ -114,7 +112,6 @@ void r300_emit_clip_state(struct r300_context* r300, 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); struct pipe_framebuffer_state* fb = (struct pipe_framebuffer_state*)r300->fb_state.state; struct pipe_stencil_ref stencil_ref = r300->stencil_ref; @@ -134,66 +131,53 @@ void r300_emit_dsa_state(struct r300_context* r300, unsigned size, void* state) OUT_CS(dsa->stencil_ref_mask | stencil_ref.ref_value[0]); - if (r300screen->caps->is_r500) { + if (r300->screen->caps.is_r500) { OUT_CS_REG(R500_ZB_STENCILREFMASK_BF, dsa->stencil_ref_bf | stencil_ref.ref_value[1]); } END_CS; } -static const float * get_shader_constant( +static const float * get_rc_constant_state( struct r300_context * r300, - struct rc_constant * constant, - struct r300_constant_buffer * externals) + struct rc_constant * constant) { struct r300_viewport_state* viewport = r300->viewport_state.state; struct r300_textures_state* texstate = r300->textures_state.state; static float vec[4] = { 0.0, 0.0, 0.0, 1.0 }; - struct pipe_texture *tex; - - switch(constant->Type) { - case RC_CONSTANT_EXTERNAL: - return externals->constants[constant->u.External]; - - case RC_CONSTANT_IMMEDIATE: - return constant->u.Immediate; - - case RC_CONSTANT_STATE: - switch (constant->u.State[0]) { - /* Factor for converting rectangle coords to - * normalized coords. Should only show up on non-r500. */ - case RC_STATE_R300_TEXRECT_FACTOR: - tex = texstate->fragment_sampler_views[constant->u.State[1]]->texture; - vec[0] = 1.0 / tex->width0; - vec[1] = 1.0 / tex->height0; - break; - - /* Texture compare-fail value. Shouldn't ever show up, but if - * it does, we'll be ready. */ - case RC_STATE_SHADOW_AMBIENT: - vec[3] = 0; - break; - - case RC_STATE_R300_VIEWPORT_SCALE: - vec[0] = viewport->xscale; - vec[1] = viewport->yscale; - vec[2] = viewport->zscale; - break; - - case RC_STATE_R300_VIEWPORT_OFFSET: - vec[0] = viewport->xoffset; - vec[1] = viewport->yoffset; - vec[2] = viewport->zoffset; - break; - - default: - fprintf(stderr, "r300: Implementation error: " - "Unknown RC_CONSTANT type %d\n", constant->u.State[0]); - } + struct pipe_resource *tex; + + assert(constant->Type == RC_CONSTANT_STATE); + + switch (constant->u.State[0]) { + /* Factor for converting rectangle coords to + * normalized coords. Should only show up on non-r500. */ + case RC_STATE_R300_TEXRECT_FACTOR: + tex = texstate->sampler_views[constant->u.State[1]]->base.texture; + vec[0] = 1.0 / tex->width0; + vec[1] = 1.0 / tex->height0; + break; + + /* Texture compare-fail value. Shouldn't ever show up, but if + * it does, we'll be ready. */ + case RC_STATE_SHADOW_AMBIENT: + vec[3] = 0; + break; + + case RC_STATE_R300_VIEWPORT_SCALE: + vec[0] = viewport->xscale; + vec[1] = viewport->yscale; + vec[2] = viewport->zscale; + break; + + case RC_STATE_R300_VIEWPORT_OFFSET: + vec[0] = viewport->xoffset; + vec[1] = viewport->yoffset; + vec[2] = viewport->zoffset; break; default: fprintf(stderr, "r300: Implementation error: " - "Unhandled constant type %d\n", constant->Type); + "Unknown RC_CONSTANT type %d\n", constant->u.State[0]); } /* This should either be (0, 0, 0, 1), which should be a relatively safe @@ -236,17 +220,31 @@ static uint32_t pack_float24(float f) return float24; } -void r300_emit_fragment_program_code(struct r300_context* r300, - struct rX00_fragment_program_code* generic_code) +unsigned r300_get_fs_atom_size(struct r300_context *r300) +{ + struct r300_fragment_shader *fs = r300_fs(r300); + unsigned imm_count = fs->shader->immediates_count; + struct r300_fragment_program_code *code = &fs->shader->code.code.r300; + + return 19 + + code->alu.length * 4 + + (code->tex.length ? (1 + code->tex.length) : 0) + + (imm_count ? imm_count * 5 : 0); +} + +void r300_emit_fs(struct r300_context* r300, unsigned size, void *state) { + struct r300_fragment_shader *fs = r300_fs(r300); + struct rX00_fragment_program_code* generic_code = &fs->shader->code; struct r300_fragment_program_code * code = &generic_code->code.r300; - int i; + unsigned i; + unsigned imm_count = fs->shader->immediates_count; + unsigned imm_first = fs->shader->externals_count; + unsigned imm_end = generic_code->constants.Count; + struct rc_constant *constants = generic_code->constants.Constants; CS_LOCALS(r300); - BEGIN_CS(15 + - code->alu.length * 4 + - (code->tex.length ? (1 + code->tex.length) : 0)); - + BEGIN_CS(size); OUT_CS_REG(R300_US_CONFIG, code->config); OUT_CS_REG(R300_US_PIXSIZE, code->pixsize); OUT_CS_REG(R300_US_CODE_OFFSET, code->code_offset); @@ -277,24 +275,43 @@ void r300_emit_fragment_program_code(struct r300_context* r300, OUT_CS(code->tex.inst[i]); } + /* Emit immediates. */ + if (imm_count) { + for(i = imm_first; i < imm_end; ++i) { + if (constants[i].Type == RC_CONSTANT_IMMEDIATE) { + const float *data = constants[i].u.Immediate; + + OUT_CS_REG_SEQ(R300_PFS_PARAM_0_X + i * 16, 4); + OUT_CS(pack_float24(data[0])); + OUT_CS(pack_float24(data[1])); + OUT_CS(pack_float24(data[2])); + OUT_CS(pack_float24(data[3])); + } + } + } + + OUT_CS_REG(R300_FG_DEPTH_SRC, fs->shader->fg_depth_src); + OUT_CS_REG(R300_US_W_FMT, fs->shader->us_out_w); END_CS; } -void r300_emit_fs_constant_buffer(struct r300_context* r300, - struct rc_constant_list* constants) +void r300_emit_fs_constants(struct r300_context* r300, unsigned size, void *state) { - int i; + struct r300_fragment_shader *fs = r300_fs(r300); + struct rc_constant_list *constants = &fs->shader->code.constants; + struct r300_constant_buffer *buf = (struct r300_constant_buffer*)state; + unsigned i, count = fs->shader->externals_count; CS_LOCALS(r300); - if (constants->Count == 0) + if (count == 0) return; - BEGIN_CS(constants->Count * 4 + 1); - OUT_CS_REG_SEQ(R300_PFS_PARAM_0_X, constants->Count * 4); - for(i = 0; i < constants->Count; ++i) { - const float * data = get_shader_constant(r300, - &constants->Constants[i], - &r300->shader_constants[PIPE_SHADER_FRAGMENT]); + BEGIN_CS(size); + OUT_CS_REG_SEQ(R300_PFS_PARAM_0_X, count * 4); + for(i = 0; i < count; ++i) { + const float *data; + assert(constants->Constants[i].Type == RC_CONSTANT_EXTERNAL); + data = buf->constants[i]; OUT_CS(pack_float24(data[0])); OUT_CS(pack_float24(data[1])); OUT_CS(pack_float24(data[2])); @@ -303,31 +320,59 @@ void r300_emit_fs_constant_buffer(struct r300_context* r300, END_CS; } -static void r300_emit_fragment_depth_config(struct r300_context* r300, - struct r300_fragment_shader* fs) +void r300_emit_fs_rc_constant_state(struct r300_context* r300, unsigned size, void *state) { + struct r300_fragment_shader *fs = r300_fs(r300); + struct rc_constant_list *constants = &fs->shader->code.constants; + unsigned i; + unsigned count = fs->shader->rc_state_count; + unsigned first = fs->shader->externals_count; + unsigned end = constants->Count; CS_LOCALS(r300); - BEGIN_CS(4); - if (r300_fragment_shader_writes_depth(fs)) { - OUT_CS_REG(R300_FG_DEPTH_SRC, R300_FG_DEPTH_SRC_SHADER); - OUT_CS_REG(R300_US_W_FMT, R300_W_FMT_W24 | R300_W_SRC_US); - } else { - OUT_CS_REG(R300_FG_DEPTH_SRC, R300_FG_DEPTH_SRC_SCAN); - OUT_CS_REG(R300_US_W_FMT, R300_W_FMT_W0 | R300_W_SRC_US); + if (count == 0) + return; + + BEGIN_CS(size); + for(i = first; i < end; ++i) { + if (constants->Constants[i].Type == RC_CONSTANT_STATE) { + const float *data = + get_rc_constant_state(r300, &constants->Constants[i]); + + OUT_CS_REG_SEQ(R300_PFS_PARAM_0_X + i * 16, 4); + OUT_CS(pack_float24(data[0])); + OUT_CS(pack_float24(data[1])); + OUT_CS(pack_float24(data[2])); + OUT_CS(pack_float24(data[3])); + } } END_CS; } -void r500_emit_fragment_program_code(struct r300_context* r300, - struct rX00_fragment_program_code* generic_code) +unsigned r500_get_fs_atom_size(struct r300_context *r300) +{ + struct r300_fragment_shader *fs = r300_fs(r300); + unsigned imm_count = fs->shader->immediates_count; + struct r500_fragment_program_code *code = &fs->shader->code.code.r500; + + return 17 + + ((code->inst_end + 1) * 6) + + (imm_count ? imm_count * 7 : 0); +} + +void r500_emit_fs(struct r300_context* r300, unsigned size, void *state) { + struct r300_fragment_shader *fs = r300_fs(r300); + struct rX00_fragment_program_code* generic_code = &fs->shader->code; struct r500_fragment_program_code * code = &generic_code->code.r500; - int i; + unsigned i; + unsigned imm_count = fs->shader->immediates_count; + unsigned imm_first = fs->shader->externals_count; + unsigned imm_end = generic_code->constants.Count; + struct rc_constant *constants = generic_code->constants.Constants; CS_LOCALS(r300); - BEGIN_CS(13 + - ((code->inst_end + 1) * 6)); + BEGIN_CS(size); OUT_CS_REG(R500_US_CONFIG, R500_ZERO_TIMES_ANYTHING_EQUALS_ZERO); OUT_CS_REG(R500_US_PIXSIZE, code->max_temp_idx); OUT_CS_REG(R500_US_CODE_RANGE, @@ -347,25 +392,48 @@ void r500_emit_fragment_program_code(struct r300_context* r300, OUT_CS(code->inst[i].inst5); } + /* Emit immediates. */ + if (imm_count) { + for(i = imm_first; i < imm_end; ++i) { + if (constants[i].Type == RC_CONSTANT_IMMEDIATE) { + const float *data = constants[i].u.Immediate; + + OUT_CS_REG(R500_GA_US_VECTOR_INDEX, + R500_GA_US_VECTOR_INDEX_TYPE_CONST | + (i & R500_GA_US_VECTOR_INDEX_MASK)); + OUT_CS_ONE_REG(R500_GA_US_VECTOR_DATA, 4); + OUT_CS_32F(data[0]); + OUT_CS_32F(data[1]); + OUT_CS_32F(data[2]); + OUT_CS_32F(data[3]); + } + } + } + + OUT_CS_REG(R300_FG_DEPTH_SRC, fs->shader->fg_depth_src); + OUT_CS_REG(R300_US_W_FMT, fs->shader->us_out_w); END_CS; } -void r500_emit_fs_constant_buffer(struct r300_context* r300, - struct rc_constant_list* constants) +void r500_emit_fs_constants(struct r300_context* r300, unsigned size, void *state) { - int i; + struct r300_fragment_shader *fs = r300_fs(r300); + struct rc_constant_list *constants = &fs->shader->code.constants; + struct r300_constant_buffer *buf = (struct r300_constant_buffer*)state; + unsigned i, count = fs->shader->externals_count; CS_LOCALS(r300); - if (constants->Count == 0) + if (count == 0) return; - BEGIN_CS(constants->Count * 4 + 3); + BEGIN_CS(size); OUT_CS_REG(R500_GA_US_VECTOR_INDEX, R500_GA_US_VECTOR_INDEX_TYPE_CONST); - OUT_CS_ONE_REG(R500_GA_US_VECTOR_DATA, constants->Count * 4); - for (i = 0; i < constants->Count; i++) { - const float * data = get_shader_constant(r300, - &constants->Constants[i], - &r300->shader_constants[PIPE_SHADER_FRAGMENT]); + OUT_CS_ONE_REG(R500_GA_US_VECTOR_DATA, count * 4); + for(i = 0; i < count; ++i) { + const float *data; + assert(constants->Constants[i].Type == RC_CONSTANT_EXTERNAL); + data = buf->constants[i]; + OUT_CS_32F(data[0]); OUT_CS_32F(data[1]); OUT_CS_32F(data[2]); @@ -374,10 +442,41 @@ void r500_emit_fs_constant_buffer(struct r300_context* r300, END_CS; } +void r500_emit_fs_rc_constant_state(struct r300_context* r300, unsigned size, void *state) +{ + struct r300_fragment_shader *fs = r300_fs(r300); + struct rc_constant_list *constants = &fs->shader->code.constants; + unsigned i; + unsigned count = fs->shader->rc_state_count; + unsigned first = fs->shader->externals_count; + unsigned end = constants->Count; + CS_LOCALS(r300); + + if (count == 0) + return; + + BEGIN_CS(size); + for(i = first; i < end; ++i) { + if (constants->Constants[i].Type == RC_CONSTANT_STATE) { + const float *data = + get_rc_constant_state(r300, &constants->Constants[i]); + + OUT_CS_REG(R500_GA_US_VECTOR_INDEX, + R500_GA_US_VECTOR_INDEX_TYPE_CONST | + (i & R500_GA_US_VECTOR_INDEX_MASK)); + OUT_CS_ONE_REG(R500_GA_US_VECTOR_DATA, 4); + OUT_CS_32F(data[0]); + OUT_CS_32F(data[1]); + OUT_CS_32F(data[2]); + OUT_CS_32F(data[3]); + } + } + END_CS; +} + void r300_emit_fb_state(struct r300_context* r300, unsigned size, void* state) { struct pipe_framebuffer_state* fb = (struct pipe_framebuffer_state*)state; - struct r300_screen* r300screen = r300_screen(r300->context.screen); struct r300_texture* tex; struct pipe_surface* surf; int i; @@ -395,7 +494,7 @@ void r300_emit_fb_state(struct r300_context* r300, unsigned size, void* state) /* Set the number of colorbuffers. */ if (fb->nr_cbufs > 1) { - if (r300screen->caps->is_r500) { + if (r300->screen->caps.is_r500) { OUT_CS_REG(R300_RB3D_CCTL, R300_RB3D_CCTL_NUM_MULTIWRITES(fb->nr_cbufs) | R300_RB3D_CCTL_INDEPENDENT_COLORFORMAT_ENABLE_ENABLE); @@ -410,7 +509,7 @@ void r300_emit_fb_state(struct r300_context* r300, unsigned size, void* state) /* Set up colorbuffers. */ for (i = 0; i < fb->nr_cbufs; i++) { surf = fb->cbufs[i]; - tex = (struct r300_texture*)surf->texture; + tex = r300_texture(surf->texture); assert(tex && tex->buffer && "cbuf is marked, but NULL!"); OUT_CS_REG_SEQ(R300_RB3D_COLOROFFSET0 + (4 * i), 1); @@ -429,7 +528,7 @@ void r300_emit_fb_state(struct r300_context* r300, unsigned size, void* state) /* Set up a zbuffer. */ if (fb->zsbuf) { surf = fb->zsbuf; - tex = (struct r300_texture*)surf->texture; + tex = r300_texture(surf->texture); assert(tex && tex->buffer && "zsbuf is marked, but NULL!"); OUT_CS_REG_SEQ(R300_ZB_DEPTHOFFSET, 1); @@ -442,22 +541,32 @@ void r300_emit_fb_state(struct r300_context* r300, unsigned size, void* state) 0, RADEON_GEM_DOMAIN_VRAM, 0); } + OUT_CS_REG_SEQ(R300_SC_SCISSORS_TL, 2); + if (r300->screen->caps.is_r500) { + OUT_CS(0); + OUT_CS(((fb->width - 1) << R300_SCISSORS_X_SHIFT) | + ((fb->height - 1) << R300_SCISSORS_Y_SHIFT)); + } else { + OUT_CS((1440 << R300_SCISSORS_X_SHIFT) | + (1440 << R300_SCISSORS_Y_SHIFT)); + OUT_CS(((fb->width + 1440-1) << R300_SCISSORS_X_SHIFT) | + ((fb->height + 1440-1) << R300_SCISSORS_Y_SHIFT)); + } OUT_CS_REG(R300_GA_POINT_MINMAX, (MAX2(fb->width, fb->height) * 6) << R300_GA_POINT_MINMAX_MAX_SHIFT); END_CS; } -void r300_emit_query_start(struct r300_context *r300) +void r300_emit_query_start(struct r300_context *r300, unsigned size, void*state) { - struct r300_capabilities *caps = r300_screen(r300->context.screen)->caps; struct r300_query *query = r300->query_current; CS_LOCALS(r300); if (!query) return; - BEGIN_CS(4); - if (caps->family == CHIP_FAMILY_RV530) { + BEGIN_CS(size); + if (r300->screen->caps.family == CHIP_FAMILY_RV530) { OUT_CS_REG(RV530_FG_ZBREG_DEST, RV530_FG_ZBREG_DEST_PIPE_SELECT_ALL); } else { OUT_CS_REG(R300_SU_REG_DEST, R300_RASTER_PIPE_SELECT_ALL); @@ -471,7 +580,7 @@ void r300_emit_query_start(struct r300_context *r300) static void r300_emit_query_finish(struct r300_context *r300, struct r300_query *query) { - struct r300_capabilities* caps = r300_screen(r300->context.screen)->caps; + struct r300_capabilities* caps = &r300->screen->caps; CS_LOCALS(r300); assert(caps->num_frag_pipes); @@ -555,7 +664,7 @@ static void rv530_emit_query_double(struct r300_context *r300, void r300_emit_query_end(struct r300_context* r300) { - struct r300_capabilities *caps = r300_screen(r300->context.screen)->caps; + struct r300_capabilities *caps = &r300->screen->caps; struct r300_query *query = r300->query_current; if (!query) @@ -613,6 +722,13 @@ void r300_emit_rs_state(struct r300_context* r300, unsigned size, void* state) OUT_CS_REG(R300_GA_LINE_STIPPLE_CONFIG, rs->line_stipple_config); OUT_CS_REG(R300_GA_LINE_STIPPLE_VALUE, rs->line_stipple_value); OUT_CS_REG(R300_GA_POLY_MODE, rs->polygon_mode); + OUT_CS_REG(R300_SC_CLIP_RULE, rs->clip_rule); + OUT_CS_REG(R300_GB_ENABLE, rs->stuffing_enable); + OUT_CS_REG_SEQ(R300_GA_POINT_S0, 4); + OUT_CS_32F(rs->point_texcoord_left); + OUT_CS_32F(rs->point_texcoord_bottom); + OUT_CS_32F(rs->point_texcoord_right); + OUT_CS_32F(rs->point_texcoord_top); END_CS; } @@ -621,7 +737,6 @@ void r300_emit_rs_block_state(struct r300_context* r300, { struct r300_rs_block* rs = (struct r300_rs_block*)state; unsigned i; - struct r300_screen* r300screen = r300_screen(r300->context.screen); /* It's the same for both INST and IP tables */ unsigned count = (rs->inst_count & R300_RS_INST_COUNT_MASK) + 1; CS_LOCALS(r300); @@ -629,7 +744,7 @@ void r300_emit_rs_block_state(struct r300_context* r300, DBG(r300, DBG_DRAW, "r300: RS emit:\n"); BEGIN_CS(size); - if (r300screen->caps->is_r500) { + if (r300->screen->caps.is_r500) { OUT_CS_REG_SEQ(R500_RS_IP_0, count); } else { OUT_CS_REG_SEQ(R300_RS_IP_0, count); @@ -643,7 +758,7 @@ void r300_emit_rs_block_state(struct r300_context* r300, OUT_CS(rs->count); OUT_CS(rs->inst_count); - if (r300screen->caps->is_r500) { + if (r300->screen->caps.is_r500) { OUT_CS_REG_SEQ(R500_RS_INST_0, count); } else { OUT_CS_REG_SEQ(R300_RS_INST_0, count); @@ -662,62 +777,22 @@ void r300_emit_rs_block_state(struct r300_context* r300, void r300_emit_scissor_state(struct r300_context* r300, unsigned size, void* state) { - unsigned minx, miny, maxx, maxy; - uint32_t top_left, bottom_right; - struct r300_screen* r300screen = r300_screen(r300->context.screen); struct pipe_scissor_state* scissor = (struct pipe_scissor_state*)state; - struct pipe_framebuffer_state* fb = - (struct pipe_framebuffer_state*)r300->fb_state.state; CS_LOCALS(r300); - minx = miny = 0; - maxx = fb->width; - maxy = fb->height; - - if (r300->scissor_enabled) { - minx = MAX2(minx, scissor->minx); - miny = MAX2(miny, scissor->miny); - maxx = MIN2(maxx, scissor->maxx); - maxy = MIN2(maxy, scissor->maxy); - } - - /* Special case for zero-area scissor. - * - * We can't allow the variables maxx and maxy to be zero because they are - * subtracted from later in the code, which would cause emitting ~0 and - * making the kernel checker angry. - * - * Let's consider we change maxx and maxy to 1, which is effectively - * a one-pixel area. We must then change minx and miny to a number which is - * greater than 1 to get the zero area back. */ - if (!maxx || !maxy) { - minx = 2; - miny = 2; - maxx = 1; - maxy = 1; - } - - if (r300screen->caps->is_r500) { - top_left = - (minx << R300_SCISSORS_X_SHIFT) | - (miny << R300_SCISSORS_Y_SHIFT); - bottom_right = - ((maxx - 1) << R300_SCISSORS_X_SHIFT) | - ((maxy - 1) << R300_SCISSORS_Y_SHIFT); + BEGIN_CS(size); + OUT_CS_REG_SEQ(R300_SC_CLIPRECT_TL_0, 2); + if (r300->screen->caps.is_r500) { + OUT_CS((scissor->minx << R300_CLIPRECT_X_SHIFT) | + (scissor->miny << R300_CLIPRECT_Y_SHIFT)); + OUT_CS(((scissor->maxx - 1) << R300_CLIPRECT_X_SHIFT) | + ((scissor->maxy - 1) << R300_CLIPRECT_Y_SHIFT)); } else { - /* Offset of 1440 in non-R500 chipsets. */ - top_left = - ((minx + 1440) << R300_SCISSORS_X_SHIFT) | - ((miny + 1440) << R300_SCISSORS_Y_SHIFT); - bottom_right = - (((maxx - 1) + 1440) << R300_SCISSORS_X_SHIFT) | - (((maxy - 1) + 1440) << R300_SCISSORS_Y_SHIFT); + OUT_CS(((scissor->minx + 1440) << R300_CLIPRECT_X_SHIFT) | + ((scissor->miny + 1440) << R300_CLIPRECT_Y_SHIFT)); + OUT_CS(((scissor->maxx + 1440-1) << R300_CLIPRECT_X_SHIFT) | + ((scissor->maxy + 1440-1) << R300_CLIPRECT_Y_SHIFT)); } - - BEGIN_CS(size); - OUT_CS_REG_SEQ(R300_SC_SCISSORS_TL, 2); - OUT_CS(top_left); - OUT_CS(bottom_right); END_CS; } @@ -736,18 +811,18 @@ void r300_emit_textures_state(struct r300_context *r300, if ((1 << i) & allstate->tx_enable) { texstate = &allstate->regs[i]; - 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_FILTER0_0 + (i * 4), texstate->filter0); + OUT_CS_REG(R300_TX_FILTER1_0 + (i * 4), texstate->filter1); 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(R300_TX_FORMAT0_0 + (i * 4), texstate->format.format0); + OUT_CS_REG(R300_TX_FORMAT1_0 + (i * 4), texstate->format.format1); + OUT_CS_REG(R300_TX_FORMAT2_0 + (i * 4), texstate->format.format2); OUT_CS_REG_SEQ(R300_TX_OFFSET_0 + (i * 4), 1); - OUT_CS_TEX_RELOC((struct r300_texture *)allstate->fragment_sampler_views[i]->texture, - texstate->tile_config, + OUT_CS_TEX_RELOC(r300_texture(allstate->sampler_views[i]->base.texture), + texstate->format.tile_config, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0, 0); } } @@ -876,11 +951,11 @@ 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); + struct r300_screen* r300screen = r300->screen; unsigned instruction_count = code->length / 4; unsigned i; - unsigned vtx_mem_size = r300screen->caps->is_r500 ? 128 : 72; + 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); @@ -889,6 +964,10 @@ void r300_emit_vs_state(struct r300_context* r300, unsigned size, void* state) vtx_mem_size / output_count, 10); unsigned pvs_num_controllers = MIN2(vtx_mem_size / temp_count, 6); + unsigned imm_first = vs->externals_count; + unsigned imm_end = vs->code.constants.Count; + unsigned imm_count = vs->immediates_count; + CS_LOCALS(r300); BEGIN_CS(size); @@ -911,28 +990,47 @@ void r300_emit_vs_state(struct r300_context* r300, unsigned size, void* state) OUT_CS_REG(R300_VAP_CNTL, R300_PVS_NUM_SLOTS(pvs_num_slots) | R300_PVS_NUM_CNTLRS(pvs_num_controllers) | - R300_PVS_NUM_FPUS(r300screen->caps->num_vert_fpus) | + R300_PVS_NUM_FPUS(r300screen->caps.num_vert_fpus) | R300_PVS_VF_MAX_VTX_NUM(12) | - (r300screen->caps->is_r500 ? R500_TCL_STATE_OPTIMIZATION : 0)); + (r300screen->caps.is_r500 ? R500_TCL_STATE_OPTIMIZATION : 0)); + + /* Emit immediates. */ + if (imm_count) { + OUT_CS_REG(R300_VAP_PVS_VECTOR_INDX_REG, + (r300->screen->caps.is_r500 ? + R500_PVS_CONST_START : R300_PVS_CONST_START) + + imm_first); + OUT_CS_ONE_REG(R300_VAP_PVS_UPLOAD_DATA, imm_count * 4); + for (i = imm_first; i < imm_end; i++) { + const float *data = vs->code.constants.Constants[i].u.Immediate; + OUT_CS_32F(data[0]); + OUT_CS_32F(data[1]); + OUT_CS_32F(data[2]); + OUT_CS_32F(data[3]); + } + } END_CS; } -void r300_emit_vs_constant_buffer(struct r300_context* r300, - struct rc_constant_list* constants) +void r300_emit_vs_constants(struct r300_context* r300, + unsigned size, void *state) { - struct r300_screen* r300screen = r300_screen(r300->context.screen); unsigned i; + unsigned count = + ((struct r300_vertex_shader*)r300->vs_state.state)->externals_count; + struct r300_constant_buffer *buf = (struct r300_constant_buffer*)state; CS_LOCALS(r300); - BEGIN_CS(constants->Count * 4 + 3); + if (!count) + return; + + BEGIN_CS(size); OUT_CS_REG(R300_VAP_PVS_VECTOR_INDX_REG, - (r300screen->caps->is_r500 ? + (r300->screen->caps.is_r500 ? R500_PVS_CONST_START : R300_PVS_CONST_START)); - OUT_CS_ONE_REG(R300_VAP_PVS_UPLOAD_DATA, constants->Count * 4); - for (i = 0; i < constants->Count; i++) { - const float *data = get_shader_constant(r300, - &constants->Constants[i], - &r300->shader_constants[PIPE_SHADER_VERTEX]); + OUT_CS_ONE_REG(R300_VAP_PVS_UPLOAD_DATA, count * 4); + for (i = 0; i < count; i++) { + const float *data = buf->constants[i]; OUT_CS_32F(data[0]); OUT_CS_32F(data[1]); OUT_CS_32F(data[2]); @@ -981,7 +1079,7 @@ void r300_emit_texture_cache_inval(struct r300_context* r300, unsigned size, voi void r300_emit_buffer_validate(struct r300_context *r300, boolean do_validate_vertex_buffers, - struct pipe_buffer *index_buffer) + struct pipe_resource *index_buffer) { struct pipe_framebuffer_state* fb = (struct pipe_framebuffer_state*)r300->fb_state.state; @@ -990,7 +1088,7 @@ void r300_emit_buffer_validate(struct r300_context *r300, struct r300_texture* tex; struct pipe_vertex_buffer *vbuf = r300->vertex_buffer; struct pipe_vertex_element *velem = r300->velems->velem; - struct pipe_buffer *pbuf; + struct pipe_resource *pbuf; unsigned i; boolean invalid = FALSE; @@ -1006,7 +1104,7 @@ void r300_emit_buffer_validate(struct r300_context *r300, validate: /* Color buffers... */ for (i = 0; i < fb->nr_cbufs; i++) { - tex = (struct r300_texture*)fb->cbufs[i]->texture; + tex = r300_texture(fb->cbufs[i]->texture); assert(tex && tex->buffer && "cbuf is marked, but NULL!"); if (!r300_add_texture(r300->rws, tex, 0, RADEON_GEM_DOMAIN_VRAM)) { @@ -1016,7 +1114,7 @@ validate: } /* ...depth buffer... */ if (fb->zsbuf) { - tex = (struct r300_texture*)fb->zsbuf->texture; + tex = r300_texture(fb->zsbuf->texture); assert(tex && tex->buffer && "zsbuf is marked, but NULL!"); if (!r300_add_texture(r300->rws, tex, 0, RADEON_GEM_DOMAIN_VRAM)) { @@ -1030,7 +1128,7 @@ validate: continue; } - tex = (struct r300_texture*)texstate->fragment_sampler_views[i]->texture; + tex = r300_texture(texstate->sampler_views[i]->base.texture); if (!r300_add_texture(r300->rws, tex, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0)) { r300->context.flush(&r300->context, 0, NULL); @@ -1038,7 +1136,7 @@ validate: } } /* ...occlusion query buffer... */ - if (r300->dirty_state & R300_NEW_QUERY) { + if (r300->query_start.dirty) { if (!r300_add_buffer(r300->rws, r300->oqbo, 0, RADEON_GEM_DOMAIN_GTT)) { r300->context.flush(&r300->context, 0, NULL); @@ -1091,70 +1189,29 @@ unsigned r300_get_num_dirty_dwords(struct r300_context *r300) unsigned dwords = 0; foreach(atom, &r300->atom_list) { - if (atom->dirty || atom->always_dirty) { + if (atom->dirty) { dwords += atom->size; } } - /* 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_screen* r300screen = r300->screen; struct r300_atom* atom; - if (r300->dirty_state & R300_NEW_QUERY) { - r300_emit_query_start(r300); - r300->dirty_state &= ~R300_NEW_QUERY; - } - foreach(atom, &r300->atom_list) { - if (atom->dirty || atom->always_dirty) { + if (atom->dirty) { atom->emit(r300, atom->size, atom->state); atom->dirty = FALSE; } } - if (r300->dirty_state & R300_NEW_FRAGMENT_SHADER) { - r300_emit_fragment_depth_config(r300, r300->fs); - if (r300screen->caps->is_r500) { - r500_emit_fragment_program_code(r300, &r300->fs->shader->code); - } else { - r300_emit_fragment_program_code(r300, &r300->fs->shader->code); - } - r300->dirty_state &= ~R300_NEW_FRAGMENT_SHADER; - } - - if (r300->dirty_state & R300_NEW_FRAGMENT_SHADER_CONSTANTS) { - if (r300screen->caps->is_r500) { - r500_emit_fs_constant_buffer(r300, - &r300->fs->shader->code.constants); - } else { - r300_emit_fs_constant_buffer(r300, - &r300->fs->shader->code.constants); - } - r300->dirty_state &= ~R300_NEW_FRAGMENT_SHADER_CONSTANTS; - } - - if (r300->dirty_state & R300_NEW_VERTEX_SHADER_CONSTANTS) { - struct r300_vertex_shader* vs = r300->vs_state.state; - if (vs->code.constants.Count) { - r300_emit_vs_constant_buffer(r300, &vs->code.constants); - } - r300->dirty_state &= ~R300_NEW_VERTEX_SHADER_CONSTANTS; - } - - /* XXX - assert(r300->dirty_state == 0); - */ - /* Emit the VBO for SWTCL. */ - if (!r300screen->caps->has_tcl) { + if (!r300screen->caps.has_tcl) { r300_emit_vertex_buffer(r300); } diff --git a/src/gallium/drivers/r300/r300_emit.h b/src/gallium/drivers/r300/r300_emit.h index 7db2fc6a1a..56f7318cdb 100644 --- a/src/gallium/drivers/r300/r300_emit.h +++ b/src/gallium/drivers/r300/r300_emit.h @@ -43,21 +43,25 @@ void r300_emit_clip_state(struct r300_context* r300, 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); +unsigned r300_get_fs_atom_size(struct r300_context *r300); -void r300_emit_fs_constant_buffer(struct r300_context* r300, - struct rc_constant_list* constants); +void r300_emit_fs(struct r300_context* r300, unsigned size, void *state); -void r500_emit_fragment_program_code(struct r300_context* r300, - struct rX00_fragment_program_code* generic_code); +void r300_emit_fs_constants(struct r300_context* r300, unsigned size, void *state); -void r500_emit_fs_constant_buffer(struct r300_context* r300, - struct rc_constant_list* constants); +void r300_emit_fs_rc_constant_state(struct r300_context* r300, unsigned size, void *state); + +unsigned r500_get_fs_atom_size(struct r300_context *r300); + +void r500_emit_fs(struct r300_context* r300, unsigned size, void *state); + +void r500_emit_fs_constants(struct r300_context* r300, unsigned size, void *state); + +void r500_emit_fs_rc_constant_state(struct r300_context* r300, unsigned size, void *state); void r300_emit_fb_state(struct r300_context* r300, unsigned size, void* state); -void r300_emit_query_start(struct r300_context* r300); +void r300_emit_query_start(struct r300_context *r300, unsigned size, void *state); void r300_emit_query_end(struct r300_context* r300); @@ -80,8 +84,8 @@ void r300_emit_vertex_stream_state(struct r300_context* r300, 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_vs_constants(struct r300_context* r300, + unsigned size, void *state); void r300_emit_vs_state(struct r300_context* r300, unsigned size, void* state); @@ -102,6 +106,6 @@ void r300_emit_dirty_state(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_resource *index_buffer); #endif /* R300_EMIT_H */ diff --git a/src/gallium/drivers/r300/r300_flush.c b/src/gallium/drivers/r300/r300_flush.c index 70de152713..5e61f528b6 100644 --- a/src/gallium/drivers/r300/r300_flush.c +++ b/src/gallium/drivers/r300/r300_flush.c @@ -52,7 +52,6 @@ static void r300_flush(struct pipe_context* pipe, if (r300->dirty_hw) { FLUSH_CS; - r300->dirty_state = R300_NEW_KITCHEN_SINK; r300->dirty_hw = 0; /* New kitchen sink, baby. */ @@ -63,9 +62,9 @@ static void r300_flush(struct pipe_context* pipe, } /* Unmark HWTCL state for SWTCL. */ - if (!r300_screen(pipe->screen)->caps->has_tcl) { + if (!r300->screen->caps.has_tcl) { r300->vs_state.dirty = FALSE; - r300->dirty_state &= ~R300_NEW_VERTEX_SHADER_CONSTANTS; + r300->vs_constants.dirty = FALSE; } } diff --git a/src/gallium/drivers/r300/r300_fs.c b/src/gallium/drivers/r300/r300_fs.c index e23fef8c9f..cf81771bb7 100644 --- a/src/gallium/drivers/r300/r300_fs.c +++ b/src/gallium/drivers/r300/r300_fs.c @@ -26,10 +26,12 @@ #include "util/u_memory.h" #include "tgsi/tgsi_dump.h" +#include "tgsi/tgsi_ureg.h" #include "r300_context.h" #include "r300_screen.h" #include "r300_fs.h" +#include "r300_reg.h" #include "r300_tgsi_to_rc.h" #include "radeon_code.h" @@ -69,26 +71,27 @@ void r300_shader_read_fs_inputs(struct tgsi_shader_info* info, break; default: - assert(0); + fprintf(stderr, "r300: FP: Unknown input semantic: %i\n", + info->input_semantic_name[i]); } } } static void find_output_registers(struct r300_fragment_program_compiler * compiler, - struct r300_fragment_shader * fs) + struct r300_fragment_shader_code *shader) { unsigned i, colorbuf_count = 0; /* Mark the outputs as not present initially */ - compiler->OutputColor[0] = fs->info.num_outputs; - compiler->OutputColor[1] = fs->info.num_outputs; - compiler->OutputColor[2] = fs->info.num_outputs; - compiler->OutputColor[3] = fs->info.num_outputs; - compiler->OutputDepth = fs->info.num_outputs; + compiler->OutputColor[0] = shader->info.num_outputs; + compiler->OutputColor[1] = shader->info.num_outputs; + compiler->OutputColor[2] = shader->info.num_outputs; + compiler->OutputColor[3] = shader->info.num_outputs; + compiler->OutputDepth = shader->info.num_outputs; /* Now see where they really are. */ - for(i = 0; i < fs->info.num_outputs; ++i) { - switch(fs->info.output_semantic_name[i]) { + for(i = 0; i < shader->info.num_outputs; ++i) { + switch(shader->info.output_semantic_name[i]) { case TGSI_SEMANTIC_COLOR: compiler->OutputColor[colorbuf_count] = i; colorbuf_count++; @@ -128,20 +131,21 @@ static void allocate_hardware_inputs( } } -static void get_compare_state( +static void get_external_state( struct r300_context* r300, - struct r300_fragment_program_external_state* state, - unsigned shadow_samplers) + struct r300_fragment_program_external_state* state) { - struct r300_textures_state *texstate = - (struct r300_textures_state*)r300->textures_state.state; - - memset(state, 0, sizeof(*state)); + struct r300_textures_state *texstate = r300->textures_state.state; + unsigned i; - for (int i = 0; i < texstate->sampler_count; i++) { + for (i = 0; i < texstate->sampler_state_count; i++) { struct r300_sampler_state* s = texstate->sampler_states[i]; - if (s && s->state.compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) { + if (!s) { + continue; + } + + if (s->state.compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) { /* XXX Gallium doesn't provide us with any information regarding * this mode, so we are screwed. I'm setting 0 = LUMINANCE. */ state->unit[i].depth_texture_mode = 0; @@ -149,17 +153,89 @@ static void get_compare_state( /* Fortunately, no need to translate this. */ state->unit[i].texture_compare_func = s->state.compare_func; } + + state->unit[i].non_normalized_coords = !s->state.normalized_coords; + + if (texstate->sampler_views[i]) { + struct r300_texture *t; + t = (struct r300_texture*)texstate->sampler_views[i]->base.texture; + + /* XXX this should probably take into account STR, not just S. */ + if (t->uses_pitch) { + switch (s->state.wrap_s) { + case PIPE_TEX_WRAP_REPEAT: + state->unit[i].wrap_mode = RC_WRAP_REPEAT; + /* XXX Enable when REPEAT fallback works. + state->unit[i].fake_npot = TRUE; */ + break; + + case PIPE_TEX_WRAP_CLAMP: + case PIPE_TEX_WRAP_CLAMP_TO_EDGE: + case PIPE_TEX_WRAP_CLAMP_TO_BORDER: + state->unit[i].wrap_mode = RC_WRAP_CLAMP; + break; + + case PIPE_TEX_WRAP_MIRROR_REPEAT: + case PIPE_TEX_WRAP_MIRROR_CLAMP: + case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE: + case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER: + state->unit[i].wrap_mode = RC_WRAP_MIRROR; + state->unit[i].fake_npot = TRUE; + break; + + default: + state->unit[i].wrap_mode = RC_WRAP_NONE; + break; + } + } + } } } static void r300_translate_fragment_shader( struct r300_context* r300, + struct r300_fragment_shader_code* shader, + const struct tgsi_token *tokens); + +static void r300_dummy_fragment_shader( + struct r300_context* r300, struct r300_fragment_shader_code* shader) { - struct r300_fragment_shader* fs = r300->fs; + struct pipe_shader_state state; + struct ureg_program *ureg; + struct ureg_dst out; + struct ureg_src imm; + + /* Make a simple fragment shader which outputs (0, 0, 0, 1) */ + ureg = ureg_create(TGSI_PROCESSOR_FRAGMENT); + out = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0); + imm = ureg_imm4f(ureg, 0, 0, 0, 1); + + ureg_MOV(ureg, out, imm); + ureg_END(ureg); + + state.tokens = ureg_finalize(ureg); + + shader->dummy = TRUE; + r300_translate_fragment_shader(r300, shader, state.tokens); + + ureg_destroy(ureg); +} + +static void r300_translate_fragment_shader( + struct r300_context* r300, + struct r300_fragment_shader_code* shader, + const struct tgsi_token *tokens) +{ struct r300_fragment_program_compiler compiler; struct tgsi_to_rc ttr; - int wpos = fs->inputs.wpos; + int wpos; + unsigned i; + + tgsi_scan_shader(tokens, &shader->info); + r300_shader_read_fs_inputs(&shader->info, &shader->inputs); + + wpos = shader->inputs.wpos; /* Setup the compiler. */ memset(&compiler, 0, sizeof(compiler)); @@ -168,25 +244,24 @@ static void r300_translate_fragment_shader( compiler.code = &shader->code; compiler.state = shader->compare_state; - compiler.is_r500 = r300_screen(r300->context.screen)->caps->is_r500; + compiler.is_r500 = r300->screen->caps.is_r500; + compiler.max_temp_regs = compiler.is_r500 ? 128 : 32; compiler.AllocateHwInputs = &allocate_hardware_inputs; - compiler.UserData = &fs->inputs; + compiler.UserData = &shader->inputs; - find_output_registers(&compiler, fs); + find_output_registers(&compiler, shader); if (compiler.Base.Debug) { debug_printf("r300: Initial fragment program\n"); - tgsi_dump(fs->state.tokens, 0); + tgsi_dump(tokens, 0); } /* Translate TGSI to our internal representation */ ttr.compiler = &compiler.Base; - ttr.info = &fs->info; + ttr.info = &shader->info; ttr.use_half_swizzles = TRUE; - r300_tgsi_to_rc(&ttr, fs->state.tokens); - - fs->shadow_samplers = compiler.Base.Program.ShadowSamplers; + r300_tgsi_to_rc(&ttr, tokens); /** * Transform the program to support WPOS. @@ -202,11 +277,47 @@ static void r300_translate_fragment_shader( /* Invoke the compiler */ r3xx_compile_fragment_program(&compiler); + if (compiler.Base.Error) { - /* XXX failover maybe? */ - fprintf(stderr, "r300 FP: Compiler Error:\n%s", - compiler.Base.ErrorMsg); - abort(); + fprintf(stderr, "r300 FP: Compiler Error:\n%sUsing a dummy shader" + " instead.\n", compiler.Base.ErrorMsg); + + if (shader->dummy) { + fprintf(stderr, "r300 FP: Cannot compile the dummy shader! " + "Giving up...\n"); + abort(); + } + + rc_destroy(&compiler.Base); + r300_dummy_fragment_shader(r300, shader); + return; + } + + /* Initialize numbers of constants for each type. */ + shader->externals_count = ttr.immediate_offset; + shader->immediates_count = 0; + shader->rc_state_count = 0; + + for (i = shader->externals_count; i < shader->code.constants.Count; i++) { + switch (shader->code.constants.Constants[i].Type) { + case RC_CONSTANT_IMMEDIATE: + ++shader->immediates_count; + break; + case RC_CONSTANT_STATE: + ++shader->rc_state_count; + break; + default: + assert(0); + } + } + + /* Setup shader depth output. */ + if (shader->code.writes_depth) { + shader->fg_depth_src = R300_FG_DEPTH_SRC_SHADER; + shader->us_out_w = R300_W_FMT_W24 | R300_W_SRC_US; + } else { + shader->fg_depth_src = R300_FG_DEPTH_SRC_SCAN; + shader->us_out_w = R300_W_FMT_W0 | R300_W_SRC_US; } /* And, finally... */ @@ -215,24 +326,22 @@ static void r300_translate_fragment_shader( boolean r300_pick_fragment_shader(struct r300_context* r300) { - struct r300_fragment_shader* fs = r300->fs; - struct r300_fragment_program_external_state state; + struct r300_fragment_shader* fs = r300_fs(r300); + struct r300_fragment_program_external_state state = {{{ 0 }}}; struct r300_fragment_shader_code* ptr; + get_external_state(r300, &state); + if (!fs->first) { /* Build the fragment shader for the first time. */ fs->first = fs->shader = CALLOC_STRUCT(r300_fragment_shader_code); - /* BTW shadow samplers will be known after the first translation, - * therefore we set ~0, which means it should look at all sampler - * states. This choice doesn't have any impact on the correctness. */ - get_compare_state(r300, &fs->shader->compare_state, ~0); - r300_translate_fragment_shader(r300, fs->shader); + memcpy(&fs->shader->compare_state, &state, + sizeof(struct r300_fragment_program_external_state)); + r300_translate_fragment_shader(r300, fs->shader, fs->state.tokens); return TRUE; - } else if (fs->shadow_samplers) { - get_compare_state(r300, &state, fs->shadow_samplers); - + } else { /* Check if the currently-bound shader has been compiled * with the texture-compare state we need. */ if (memcmp(&fs->shader->compare_state, &state, sizeof(state)) != 0) { @@ -240,8 +349,12 @@ boolean r300_pick_fragment_shader(struct r300_context* r300) ptr = fs->first; while (ptr) { if (memcmp(&ptr->compare_state, &state, sizeof(state)) == 0) { - fs->shader = ptr; - return TRUE; + if (fs->shader != ptr) { + fs->shader = ptr; + return TRUE; + } + /* The currently-bound one is OK. */ + return FALSE; } ptr = ptr->next; } @@ -252,7 +365,7 @@ boolean r300_pick_fragment_shader(struct r300_context* r300) fs->first = fs->shader = ptr; ptr->compare_state = state; - r300_translate_fragment_shader(r300, ptr); + r300_translate_fragment_shader(r300, ptr, fs->state.tokens); return TRUE; } } diff --git a/src/gallium/drivers/r300/r300_fs.h b/src/gallium/drivers/r300/r300_fs.h index 40ce874353..1cc4355359 100644 --- a/src/gallium/drivers/r300/r300_fs.h +++ b/src/gallium/drivers/r300/r300_fs.h @@ -31,6 +31,22 @@ #include "r300_shader_semantics.h" struct r300_fragment_shader_code { + struct tgsi_shader_info info; + struct r300_shader_semantics inputs; + + /* Whether the shader was replaced by a dummy one due to a shader + * compilation failure. */ + boolean dummy; + + /* Numbers of constants for each type. */ + unsigned externals_count; + unsigned immediates_count; + unsigned rc_state_count; + + /* Registers for fragment depth output setup. */ + uint32_t fg_depth_src; /* R300_FG_DEPTH_SRC: 0x4bd8 */ + uint32_t us_out_w; /* R300_US_W_FMT: 0x46b4 */ + struct r300_fragment_program_external_state compare_state; struct rX00_fragment_program_code code; @@ -41,12 +57,6 @@ struct r300_fragment_shader { /* Parent class */ struct pipe_shader_state state; - struct tgsi_shader_info info; - struct r300_shader_semantics inputs; - - /* Bits 0-15: TRUE if it's a shadow sampler, FALSE otherwise. */ - unsigned shadow_samplers; - /* Currently-bound fragment shader. */ struct r300_fragment_shader_code* shader; diff --git a/src/gallium/drivers/r300/r300_query.c b/src/gallium/drivers/r300/r300_query.c index f8b52d593d..398edb9d10 100644 --- a/src/gallium/drivers/r300/r300_query.c +++ b/src/gallium/drivers/r300/r300_query.c @@ -36,7 +36,7 @@ static struct pipe_query *r300_create_query(struct pipe_context *pipe, unsigned query_type) { struct r300_context *r300 = r300_context(pipe); - struct r300_screen *r300screen = r300_screen(r300->context.screen); + struct r300_screen *r300screen = r300->screen; unsigned query_size; struct r300_query *q, *qptr; @@ -47,10 +47,10 @@ static struct pipe_query *r300_create_query(struct pipe_context *pipe, q->active = FALSE; - if (r300screen->caps->family == CHIP_FAMILY_RV530) - query_size = r300screen->caps->num_z_pipes * sizeof(uint32_t); + if (r300screen->caps.family == CHIP_FAMILY_RV530) + query_size = r300screen->caps.num_z_pipes * sizeof(uint32_t); else - query_size = r300screen->caps->num_frag_pipes * sizeof(uint32_t); + query_size = r300screen->caps.num_frag_pipes * sizeof(uint32_t); if (!is_empty_list(&r300->query_list)) { qptr = last_elem(&r300->query_list); @@ -78,21 +78,21 @@ static void r300_destroy_query(struct pipe_context* pipe, static void r300_begin_query(struct pipe_context* pipe, struct pipe_query* query) { - uint32_t* map; + uint32_t value = ~0U; struct r300_context* r300 = r300_context(pipe); struct r300_query* q = (struct r300_query*)query; assert(r300->query_current == NULL); - map = pipe->screen->buffer_map(pipe->screen, r300->oqbo, - PIPE_BUFFER_USAGE_CPU_WRITE); - map += q->offset / 4; - *map = ~0U; - pipe->screen->buffer_unmap(pipe->screen, r300->oqbo); + pipe_buffer_write(pipe, + r300->oqbo, + q->offset, + sizeof value, + &value); q->flushed = FALSE; r300->query_current = q; - r300->dirty_state |= R300_NEW_QUERY; + r300->query_start.dirty = TRUE; } static void r300_end_query(struct pipe_context* pipe, @@ -112,9 +112,10 @@ static boolean r300_get_query_result(struct pipe_context* pipe, uint64_t* result) { struct r300_context* r300 = r300_context(pipe); - struct r300_screen* r300screen = r300_screen(r300->context.screen); + struct r300_screen* r300screen = r300->screen; struct r300_query *q = (struct r300_query*)query; - unsigned flags = PIPE_BUFFER_USAGE_CPU_READ; + struct pipe_transfer *transfer; + unsigned flags = PIPE_TRANSFER_READ; uint32_t* map; uint32_t temp = 0; unsigned i, num_results; @@ -122,18 +123,18 @@ static boolean r300_get_query_result(struct pipe_context* pipe, if (q->flushed == FALSE) pipe->flush(pipe, 0, NULL); if (!wait) { - flags |= PIPE_BUFFER_USAGE_DONTBLOCK; + flags |= PIPE_TRANSFER_DONTBLOCK; } - map = pipe->screen->buffer_map(pipe->screen, r300->oqbo, flags); + map = pipe_buffer_map(pipe, r300->oqbo, flags, &transfer); if (!map) return FALSE; map += q->offset / 4; - if (r300screen->caps->family == CHIP_FAMILY_RV530) - num_results = r300screen->caps->num_z_pipes; + if (r300screen->caps.family == CHIP_FAMILY_RV530) + num_results = r300screen->caps.num_z_pipes; else - num_results = r300screen->caps->num_frag_pipes; + num_results = r300screen->caps.num_frag_pipes; for (i = 0; i < num_results; i++) { if (*map == ~0U) { @@ -148,7 +149,7 @@ static boolean r300_get_query_result(struct pipe_context* pipe, temp += *map; map++; } - pipe->screen->buffer_unmap(pipe->screen, r300->oqbo); + pipe_buffer_unmap(pipe, r300->oqbo, transfer); if (temp == ~0U) { /* Our results haven't been written yet... */ @@ -159,10 +160,33 @@ static boolean r300_get_query_result(struct pipe_context* pipe, return TRUE; } +static void r300_render_condition(struct pipe_context *pipe, + struct pipe_query *query, + uint mode) +{ + struct r300_context *r300 = r300_context(pipe); + uint64_t result; + boolean wait; + + if (query) { + wait = mode == PIPE_RENDER_COND_WAIT || + mode == PIPE_RENDER_COND_BY_REGION_WAIT; + + if (!r300_get_query_result(pipe, query, wait, &result)) { + r300->skip_rendering = FALSE; + } + + r300->skip_rendering = result == 0; + } else { + r300->skip_rendering = FALSE; + } +} + void r300_init_query_functions(struct r300_context* r300) { r300->context.create_query = r300_create_query; r300->context.destroy_query = r300_destroy_query; r300->context.begin_query = r300_begin_query; r300->context.end_query = r300_end_query; r300->context.get_query_result = r300_get_query_result; + r300->context.render_condition = r300_render_condition; } diff --git a/src/gallium/drivers/r300/r300_reg.h b/src/gallium/drivers/r300/r300_reg.h index 0d6b7654f3..239f91443f 100644 --- a/src/gallium/drivers/r300/r300_reg.h +++ b/src/gallium/drivers/r300/r300_reg.h @@ -1543,7 +1543,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. # define R300_TX_FORMAT_DXT1 0xF # define R300_TX_FORMAT_DXT3 0x10 # define R300_TX_FORMAT_DXT5 0x11 -# define R300_TX_FORMAT_Y8 0x12 +# define R300_TX_FORMAT_CxV8U8 0x12 # define R300_TX_FORMAT_AVYU444 0x13 # define R300_TX_FORMAT_VYUY422 0x14 # define R300_TX_FORMAT_YVYU422 0x15 @@ -1740,6 +1740,10 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. # define R300_PFS_CNTL_TEX_OFFSET_MASK (31 << 13) # define R300_PFS_CNTL_TEX_END_SHIFT 18 # define R300_PFS_CNTL_TEX_END_MASK (31 << 18) +# define R400_PFS_CNTL_TEX_OFFSET_MSB_SHIFT 24 +# define R400_PFS_CNTL_TEX_OFFSET_MSB_MASK (0xf << 24) +# define R400_PFS_CNTL_TEX_END_MSB_SHIFT 28 +# define R400_PFS_CNTL_TEX_END_MSB_MASK (0xf << 28) /* gap */ @@ -1764,6 +1768,10 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. # define R300_TEX_SIZE_MASK (31 << 17) # define R300_RGBA_OUT (1 << 22) # define R300_W_OUT (1 << 23) +# define R400_TEX_START_MSB_SHIFT 24 +# define R400_TEX_START_MSG_MASK (0xf << 24) +# define R400_TEX_SIZE_MSB_SHIFT 28 +# define R400_TEX_SIZE_MSG_MASK (0xf << 28) /* TEX * As far as I can tell, texture instructions cannot write into output @@ -1784,6 +1792,8 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. # define R300_TEX_OP_TXP 3 # define R300_TEX_OP_TXB 4 # define R300_TEX_INST_MASK (7 << 15) +# define R400_SRC_ADDR_EXT_BIT (1 << 19) +# define R400_DST_ADDR_EXT_BIT (1 << 20) /* Output format from the unfied shader */ #define R300_US_OUT_FMT_0 0x46A4 @@ -2092,6 +2102,43 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. # define R300_ALU_OUTA_CLAMP (1 << 30) /* END: Fragment program instruction set */ +/* R4xx extended fragment shader registers. */ +#define R400_US_ALU_EXT_ADDR_0 0x4ac0 /* up to 63 (0x4bbc) */ +# define R400_ADDR0_EXT_RGB_MSB_BIT 0x01 +# define R400_ADDR1_EXT_RGB_MSB_BIT 0x02 +# define R400_ADDR2_EXT_RGB_MSB_BIT 0x04 +# define R400_ADDRD_EXT_RGB_MSB_BIT 0x08 +# define R400_ADDR0_EXT_A_MSB_BIT 0x10 +# define R400_ADDR1_EXT_A_MSB_BIT 0x20 +# define R400_ADDR2_EXT_A_MSB_BIT 0x40 +# define R400_ADDRD_EXT_A_MSB_BIT 0x80 +#define R400_US_CODE_BANK 0x46b8 +# define R400_BANK_SHIFT 0 +# define R400_BANK_MASK 0xf +# define R400_R390_MODE_ENABLE (1 << 4) +#define R400_US_CODE_EXT 0x46bc +# define R400_ALU_OFFSET_MSB_SHIFT 0 +# define R400_ALU_OFFSET_MSB_MASK (0x7 << 0) +# define R400_ALU_SIZE_MSB_SHIFT 3 +# define R400_ALU_SIZE_MSB_MASK (0x7 << 3) +# define R400_ALU_START0_MSB_SHIFT 6 +# define R400_ALU_START0_MSB_MASK (0x7 << 6) +# define R400_ALU_SIZE0_MSB_SHIFT 9 +# define R400_ALU_SIZE0_MSB_MASK (0x7 << 9) +# define R400_ALU_START1_MSB_SHIFT 12 +# define R400_ALU_START1_MSB_MASK (0x7 << 12) +# define R400_ALU_SIZE1_MSB_SHIFT 15 +# define R400_ALU_SIZE1_MSB_MASK (0x7 << 15) +# define R400_ALU_START2_MSB_SHIFT 18 +# define R400_ALU_START2_MSB_MASK (0x7 << 18) +# define R400_ALU_SIZE2_MSB_SHIFT 21 +# define R400_ALU_SIZE2_MSB_MASK (0x7 << 21) +# define R400_ALU_START3_MSB_SHIFT 24 +# define R400_ALU_START3_MSB_MASK (0x7 << 24) +# define R400_ALU_SIZE3_MSB_SHIFT 27 +# define R400_ALU_SIZE3_MSB_MASK (0x7 << 27) +/* END: R4xx extended fragment shader registers. */ + /* Fog: Fog Blending Enable */ #define R300_FG_FOG_BLEND 0x4bc0 # define R300_FG_FOG_BLEND_DISABLE (0 << 0) @@ -3290,7 +3337,6 @@ enum { # define R300_W_SRC_US (0 << 2) # define R300_W_SRC_RAS (1 << 2) - /* Draw a primitive from vertex data in arrays loaded via 3D_LOAD_VBPNTR. * Two parameter dwords: * 0. VAP_VTX_FMT: The first parameter is not written to hardware diff --git a/src/gallium/drivers/r300/r300_render.c b/src/gallium/drivers/r300/r300_render.c index 1fb7eac2b3..751a7e6d5b 100644 --- a/src/gallium/drivers/r300/r300_render.c +++ b/src/gallium/drivers/r300/r300_render.c @@ -152,7 +152,9 @@ static boolean immd_is_good_idea(struct r300_context *r300, if (!checked[vbi]) { vbuf = &r300->vertex_buffer[vbi]; - if (r300_buffer_is_referenced(r300, vbuf->buffer)) { + if (r300->context.is_resource_referenced(&r300->context, + vbuf->buffer, + 0, 0)) { /* It's a very bad idea to map it... */ return FALSE; } @@ -162,10 +164,15 @@ static boolean immd_is_good_idea(struct r300_context *r300, return TRUE; } -static void r300_emit_draw_arrays_immediate(struct r300_context *r300, - unsigned mode, - unsigned start, - unsigned count) +/***************************************************************************** + * The emission of draw packets for r500. Older GPUs may use these functions * + * after resolving fallback issues (e.g. stencil ref two-sided). * + ****************************************************************************/ + +void r500_emit_draw_arrays_immediate(struct r300_context *r300, + unsigned mode, + unsigned start, + unsigned count) { struct pipe_vertex_element* velem; struct pipe_vertex_buffer* vbuf; @@ -187,6 +194,7 @@ static void r300_emit_draw_arrays_immediate(struct r300_context *r300, /* Mapped vertex buffers. */ uint32_t* map[PIPE_MAX_ATTRIBS] = {0}; + struct pipe_transfer* transfer[PIPE_MAX_ATTRIBS] = {NULL}; CS_LOCALS(r300); @@ -201,9 +209,10 @@ static void r300_emit_draw_arrays_immediate(struct r300_context *r300, /* Map the buffer. */ if (!map[vbi]) { vbuf = &r300->vertex_buffer[vbi]; - map[vbi] = (uint32_t*)pipe_buffer_map(r300->context.screen, + map[vbi] = (uint32_t*)pipe_buffer_map(&r300->context, vbuf->buffer, - PIPE_BUFFER_USAGE_CPU_READ); + PIPE_TRANSFER_READ, + &transfer[vbi]); map[vbi] += vbuf->buffer_offset / 4; stride[vbi] = vbuf->stride / 4; } @@ -246,15 +255,15 @@ static void r300_emit_draw_arrays_immediate(struct r300_context *r300, if (map[vbi]) { vbuf = &r300->vertex_buffer[vbi]; - pipe_buffer_unmap(r300->context.screen, vbuf->buffer); + pipe_buffer_unmap(&r300->context, vbuf->buffer, transfer[vbi]); map[vbi] = NULL; } } } -static void r300_emit_draw_arrays(struct r300_context *r300, - unsigned mode, - unsigned count) +void r500_emit_draw_arrays(struct r300_context *r300, + unsigned mode, + unsigned count) { #if defined(ENABLE_ALT_NUM_VERTS) boolean alt_num_verts = count > 65535; @@ -264,7 +273,11 @@ static void r300_emit_draw_arrays(struct r300_context *r300, CS_LOCALS(r300); if (alt_num_verts) { - assert(count < (1 << 24)); + if (count >= (1 << 24)) { + fprintf(stderr, "r300: Got a huge number of vertices: %i, " + "refusing to render.\n", count); + return; + } BEGIN_CS(9); OUT_CS_REG(R500_VAP_ALT_NUM_VERTICES, count); } else { @@ -282,14 +295,14 @@ static void r300_emit_draw_arrays(struct r300_context *r300, END_CS; } -static void r300_emit_draw_elements(struct r300_context *r300, - struct pipe_buffer* indexBuffer, - unsigned indexSize, - unsigned minIndex, - unsigned maxIndex, - unsigned mode, - unsigned start, - unsigned count) +void r500_emit_draw_elements(struct r300_context *r300, + struct pipe_resource* indexBuffer, + unsigned indexSize, + unsigned minIndex, + unsigned maxIndex, + unsigned mode, + unsigned start, + unsigned count) { uint32_t count_dwords; uint32_t offset_dwords = indexSize * start / sizeof(uint32_t); @@ -300,7 +313,11 @@ static void r300_emit_draw_elements(struct r300_context *r300, #endif CS_LOCALS(r300); - assert(count < (1 << 24)); + if (count >= (1 << 24)) { + fprintf(stderr, "r300: Got a huge number of vertices: %i, " + "refusing to render.\n", count); + return; + } maxIndex = MIN2(maxIndex, r300->vertex_buffer_max_index); @@ -347,25 +364,123 @@ static void r300_emit_draw_elements(struct r300_context *r300, END_CS; } +/***************************************************************************** + * The emission of draw packets for r300 which take care of the two-sided * + * stencil ref fallback and call r500's functions. * + ****************************************************************************/ + +/* Set drawing for front faces. */ +static void r300_begin_stencil_ref_fallback(struct r300_context *r300) +{ + struct r300_rs_state *rs = (struct r300_rs_state*)r300->rs_state.state; + CS_LOCALS(r300); + + BEGIN_CS(2); + OUT_CS_REG(R300_SU_CULL_MODE, rs->cull_mode | R300_CULL_BACK); + END_CS; +} + +/* Set drawing for back faces. */ +static void r300_switch_stencil_ref_side(struct r300_context *r300) +{ + struct r300_rs_state *rs = (struct r300_rs_state*)r300->rs_state.state; + struct r300_dsa_state *dsa = (struct r300_dsa_state*)r300->dsa_state.state; + CS_LOCALS(r300); + + BEGIN_CS(4); + OUT_CS_REG(R300_SU_CULL_MODE, rs->cull_mode | R300_CULL_FRONT); + OUT_CS_REG(R300_ZB_STENCILREFMASK, + dsa->stencil_ref_bf | r300->stencil_ref.ref_value[1]); + END_CS; +} + +/* Restore the original state. */ +static void r300_end_stencil_ref_fallback(struct r300_context *r300) +{ + struct r300_rs_state *rs = (struct r300_rs_state*)r300->rs_state.state; + struct r300_dsa_state *dsa = (struct r300_dsa_state*)r300->dsa_state.state; + CS_LOCALS(r300); + + BEGIN_CS(4); + OUT_CS_REG(R300_SU_CULL_MODE, rs->cull_mode); + OUT_CS_REG(R300_ZB_STENCILREFMASK, + dsa->stencil_ref_mask | r300->stencil_ref.ref_value[0]); + END_CS; +} + +void r300_emit_draw_arrays_immediate(struct r300_context *r300, + unsigned mode, + unsigned start, + unsigned count) +{ + if (!r300->stencil_ref_bf_fallback) { + r500_emit_draw_arrays_immediate(r300, mode, start, count); + } else { + r300_begin_stencil_ref_fallback(r300); + r500_emit_draw_arrays_immediate(r300, mode, start, count); + r300_switch_stencil_ref_side(r300); + r500_emit_draw_arrays_immediate(r300, mode, start, count); + r300_end_stencil_ref_fallback(r300); + } +} + +void r300_emit_draw_arrays(struct r300_context *r300, + unsigned mode, + unsigned count) +{ + if (!r300->stencil_ref_bf_fallback) { + r500_emit_draw_arrays(r300, mode, count); + } else { + r300_begin_stencil_ref_fallback(r300); + r500_emit_draw_arrays(r300, mode, count); + r300_switch_stencil_ref_side(r300); + r500_emit_draw_arrays(r300, mode, count); + r300_end_stencil_ref_fallback(r300); + } +} + +void r300_emit_draw_elements(struct r300_context *r300, + struct pipe_resource* indexBuffer, + unsigned indexSize, + unsigned minIndex, + unsigned maxIndex, + unsigned mode, + unsigned start, + unsigned count) +{ + if (!r300->stencil_ref_bf_fallback) { + r500_emit_draw_elements(r300, indexBuffer, indexSize, minIndex, + maxIndex, mode, start, count); + } else { + r300_begin_stencil_ref_fallback(r300); + r500_emit_draw_elements(r300, indexBuffer, indexSize, minIndex, + maxIndex, mode, start, count); + r300_switch_stencil_ref_side(r300); + r500_emit_draw_elements(r300, indexBuffer, indexSize, minIndex, + maxIndex, mode, start, count); + r300_end_stencil_ref_fallback(r300); + } +} + static void r300_shorten_ubyte_elts(struct r300_context* r300, - struct pipe_buffer** elts, + struct pipe_resource** elts, unsigned start, unsigned count) { + struct pipe_context* context = &r300->context; struct pipe_screen* screen = r300->context.screen; - struct pipe_buffer* new_elts; + struct pipe_resource* new_elts; unsigned char *in_map; unsigned short *out_map; + struct pipe_transfer *src_transfer, *dst_transfer; unsigned i; - new_elts = screen->buffer_create(screen, 32, - PIPE_BUFFER_USAGE_INDEX | - PIPE_BUFFER_USAGE_CPU_WRITE | - PIPE_BUFFER_USAGE_GPU_READ, - 2 * count); + new_elts = pipe_buffer_create(screen, + PIPE_BIND_INDEX_BUFFER, + 2 * count); - in_map = pipe_buffer_map(screen, *elts, PIPE_BUFFER_USAGE_CPU_READ); - out_map = pipe_buffer_map(screen, new_elts, PIPE_BUFFER_USAGE_CPU_WRITE); + in_map = pipe_buffer_map(context, *elts, PIPE_TRANSFER_READ, &src_transfer); + out_map = pipe_buffer_map(context, new_elts, PIPE_TRANSFER_WRITE, &dst_transfer); in_map += start; @@ -375,41 +490,43 @@ static void r300_shorten_ubyte_elts(struct r300_context* r300, out_map++; } - pipe_buffer_unmap(screen, *elts); - pipe_buffer_unmap(screen, new_elts); + pipe_buffer_unmap(context, *elts, src_transfer); + pipe_buffer_unmap(context, new_elts, dst_transfer); *elts = new_elts; } static void r300_align_ushort_elts(struct r300_context *r300, - struct pipe_buffer **elts, + struct pipe_resource **elts, unsigned start, unsigned count) { - struct pipe_screen* screen = r300->context.screen; - struct pipe_buffer* new_elts; + struct pipe_context* context = &r300->context; + struct pipe_transfer *in_transfer = NULL; + struct pipe_transfer *out_transfer = NULL; + struct pipe_resource* new_elts; unsigned short *in_map; unsigned short *out_map; - new_elts = screen->buffer_create(screen, 32, - PIPE_BUFFER_USAGE_INDEX | - PIPE_BUFFER_USAGE_CPU_WRITE | - PIPE_BUFFER_USAGE_GPU_READ, - 2 * count); + new_elts = pipe_buffer_create(context->screen, + PIPE_BIND_INDEX_BUFFER, + 2 * count); - in_map = pipe_buffer_map(screen, *elts, PIPE_BUFFER_USAGE_CPU_READ); - out_map = pipe_buffer_map(screen, new_elts, PIPE_BUFFER_USAGE_CPU_WRITE); + in_map = pipe_buffer_map(context, *elts, + PIPE_TRANSFER_READ, &in_transfer); + out_map = pipe_buffer_map(context, new_elts, + PIPE_TRANSFER_WRITE, &out_transfer); memcpy(out_map, in_map+start, 2 * count); - pipe_buffer_unmap(screen, *elts); - pipe_buffer_unmap(screen, new_elts); + pipe_buffer_unmap(context, *elts, in_transfer); + pipe_buffer_unmap(context, new_elts, out_transfer); *elts = new_elts; } /* This is the fast-path drawing & emission for HW TCL. */ void r300_draw_range_elements(struct pipe_context* pipe, - struct pipe_buffer* indexBuffer, + struct pipe_resource* indexBuffer, unsigned indexSize, unsigned minIndex, unsigned maxIndex, @@ -418,15 +535,19 @@ void r300_draw_range_elements(struct pipe_context* pipe, unsigned count) { struct r300_context* r300 = r300_context(pipe); - struct pipe_buffer* orgIndexBuffer = indexBuffer; + struct pipe_resource* orgIndexBuffer = indexBuffer; #if defined(ENABLE_ALT_NUM_VERTS) - boolean alt_num_verts = r300_screen(pipe->screen)->caps->is_r500 && + boolean alt_num_verts = r300->screen->caps.is_r500 && count > 65536; #else boolean alt_num_verts = FALSE; #endif unsigned short_count; + if (r300->skip_rendering) { + return; + } + if (!u_trim_pipe_prim(mode, &count)) { return; } @@ -453,13 +574,13 @@ void r300_draw_range_elements(struct pipe_context* pipe, u_upload_flush(r300->upload_vb); u_upload_flush(r300->upload_ib); if (alt_num_verts || count <= 65535) { - r300_emit_draw_elements(r300, indexBuffer, indexSize, minIndex, - maxIndex, mode, start, count); + r300->emit_draw_elements(r300, indexBuffer, indexSize, minIndex, + maxIndex, mode, start, count); } else { do { short_count = MIN2(count, 65534); - r300_emit_draw_elements(r300, indexBuffer, indexSize, minIndex, - maxIndex, mode, start, short_count); + r300->emit_draw_elements(r300, indexBuffer, indexSize, minIndex, + maxIndex, mode, start, short_count); start += short_count; count -= short_count; @@ -474,13 +595,13 @@ void r300_draw_range_elements(struct pipe_context* pipe, } if (indexBuffer != orgIndexBuffer) { - pipe_buffer_reference( &indexBuffer, NULL ); + pipe_resource_reference( &indexBuffer, NULL ); } } /* Simple helpers for context setup. Should probably be moved to util. */ void r300_draw_elements(struct pipe_context* pipe, - struct pipe_buffer* indexBuffer, + struct pipe_resource* indexBuffer, unsigned indexSize, unsigned mode, unsigned start, unsigned count) { @@ -496,13 +617,17 @@ void r300_draw_arrays(struct pipe_context* pipe, unsigned mode, { struct r300_context* r300 = r300_context(pipe); #if defined(ENABLE_ALT_NUM_VERTS) - boolean alt_num_verts = r300_screen(pipe->screen)->caps->is_r500 && + boolean alt_num_verts = r300->screen->caps.is_r500 && count > 65536; #else boolean alt_num_verts = FALSE; #endif unsigned short_count; + if (r300->skip_rendering) { + return; + } + if (!u_trim_pipe_prim(mode, &count)) { return; } @@ -510,7 +635,7 @@ void r300_draw_arrays(struct pipe_context* pipe, unsigned mode, r300_update_derived_state(r300); if (immd_is_good_idea(r300, count)) { - r300_emit_draw_arrays_immediate(r300, mode, start, count); + r300->emit_draw_arrays_immediate(r300, mode, start, count); } else { /* Make sure there are at least 128 spare dwords in the command buffer. * (most of it being consumed by emit_aos) */ @@ -520,12 +645,12 @@ void r300_draw_arrays(struct pipe_context* pipe, unsigned mode, if (alt_num_verts || count <= 65535) { r300_emit_aos(r300, start); - r300_emit_draw_arrays(r300, mode, count); + r300->emit_draw_arrays(r300, mode, count); } else { do { short_count = MIN2(count, 65535); r300_emit_aos(r300, start); - r300_emit_draw_arrays(r300, mode, short_count); + r300->emit_draw_arrays(r300, mode, short_count); start += short_count; count -= short_count; @@ -554,16 +679,22 @@ void r300_swtcl_draw_arrays(struct pipe_context* pipe, unsigned count) { struct r300_context* r300 = r300_context(pipe); + struct pipe_transfer *vb_transfer[PIPE_MAX_ATTRIBS]; int i; + if (r300->skip_rendering) { + return; + } + if (!u_trim_pipe_prim(mode, &count)) { return; } for (i = 0; i < r300->vertex_buffer_count; i++) { - void* buf = pipe_buffer_map(pipe->screen, + void* buf = pipe_buffer_map(pipe, r300->vertex_buffer[i].buffer, - PIPE_BUFFER_USAGE_CPU_READ); + PIPE_TRANSFER_READ, + &vb_transfer[i]); draw_set_mapped_vertex_buffer(r300->draw, i, buf); } @@ -572,14 +703,15 @@ void r300_swtcl_draw_arrays(struct pipe_context* pipe, draw_arrays(r300->draw, mode, start, count); for (i = 0; i < r300->vertex_buffer_count; i++) { - pipe_buffer_unmap(pipe->screen, r300->vertex_buffer[i].buffer); + pipe_buffer_unmap(pipe, r300->vertex_buffer[i].buffer, + vb_transfer[i]); draw_set_mapped_vertex_buffer(r300->draw, i, NULL); } } /* SW TCL elements, using Draw. */ void r300_swtcl_draw_range_elements(struct pipe_context* pipe, - struct pipe_buffer* indexBuffer, + struct pipe_resource* indexBuffer, unsigned indexSize, unsigned minIndex, unsigned maxIndex, @@ -588,33 +720,42 @@ void r300_swtcl_draw_range_elements(struct pipe_context* pipe, unsigned count) { struct r300_context* r300 = r300_context(pipe); + struct pipe_transfer *vb_transfer[PIPE_MAX_ATTRIBS]; + struct pipe_transfer *ib_transfer; int i; void* indices; + if (r300->skip_rendering) { + return; + } + if (!u_trim_pipe_prim(mode, &count)) { return; } for (i = 0; i < r300->vertex_buffer_count; i++) { - void* buf = pipe_buffer_map(pipe->screen, + void* buf = pipe_buffer_map(pipe, r300->vertex_buffer[i].buffer, - PIPE_BUFFER_USAGE_CPU_READ); + PIPE_TRANSFER_READ, + &vb_transfer[i]); draw_set_mapped_vertex_buffer(r300->draw, i, buf); } - indices = pipe_buffer_map(pipe->screen, indexBuffer, - PIPE_BUFFER_USAGE_CPU_READ); + indices = pipe_buffer_map(pipe, indexBuffer, + PIPE_TRANSFER_READ, &ib_transfer); draw_set_mapped_element_buffer_range(r300->draw, indexSize, minIndex, maxIndex, indices); draw_arrays(r300->draw, mode, start, count); for (i = 0; i < r300->vertex_buffer_count; i++) { - pipe_buffer_unmap(pipe->screen, r300->vertex_buffer[i].buffer); + pipe_buffer_unmap(pipe, r300->vertex_buffer[i].buffer, + vb_transfer[i]); draw_set_mapped_vertex_buffer(r300->draw, i, NULL); } - pipe_buffer_unmap(pipe->screen, indexBuffer); + pipe_buffer_unmap(pipe, indexBuffer, + ib_transfer); draw_set_mapped_element_buffer_range(r300->draw, 0, start, start + count - 1, NULL); } @@ -633,11 +774,13 @@ struct r300_render { unsigned hwprim; /* VBO */ - struct pipe_buffer* vbo; + struct pipe_resource* vbo; size_t vbo_size; size_t vbo_offset; size_t vbo_max_used; void * vbo_ptr; + + struct pipe_transfer *vbo_transfer; }; static INLINE struct r300_render* @@ -668,10 +811,9 @@ static boolean r300_render_allocate_vertices(struct vbuf_render* render, if (size + r300render->vbo_offset > r300render->vbo_size) { - pipe_buffer_reference(&r300->vbo, NULL); + pipe_resource_reference(&r300->vbo, NULL); r300render->vbo = pipe_buffer_create(screen, - 64, - PIPE_BUFFER_USAGE_VERTEX, + PIPE_BIND_VERTEX_BUFFER, R300_MAX_DRAW_VBO_SIZE); r300render->vbo_offset = 0; r300render->vbo_size = R300_MAX_DRAW_VBO_SIZE; @@ -687,10 +829,11 @@ static boolean r300_render_allocate_vertices(struct vbuf_render* render, static void* r300_render_map_vertices(struct vbuf_render* render) { struct r300_render* r300render = r300_render(render); - struct pipe_screen* screen = r300render->r300->context.screen; - r300render->vbo_ptr = pipe_buffer_map(screen, r300render->vbo, - PIPE_BUFFER_USAGE_CPU_WRITE); + r300render->vbo_ptr = pipe_buffer_map(&r300render->r300->context, + r300render->vbo, + PIPE_TRANSFER_WRITE, + &r300render->vbo_transfer); return ((uint8_t*)r300render->vbo_ptr + r300render->vbo_offset); } @@ -700,7 +843,7 @@ static void r300_render_unmap_vertices(struct vbuf_render* render, ushort max) { struct r300_render* r300render = r300_render(render); - struct pipe_screen* screen = r300render->r300->context.screen; + struct pipe_context* context = &r300render->r300->context; CS_LOCALS(r300render->r300); BEGIN_CS(2); OUT_CS_REG(R300_VAP_VF_MAX_VTX_INDX, max); @@ -708,7 +851,7 @@ static void r300_render_unmap_vertices(struct vbuf_render* render, r300render->vbo_max_used = MAX2(r300render->vbo_max_used, r300render->vertex_size * (max + 1)); - pipe_buffer_unmap(screen, r300render->vbo); + pipe_buffer_unmap(context, r300render->vbo, r300render->vbo_transfer); } static void r300_render_release_vertices(struct vbuf_render* render) @@ -730,9 +873,9 @@ static boolean r300_render_set_primitive(struct vbuf_render* render, return TRUE; } -static void r300_render_draw_arrays(struct vbuf_render* render, - unsigned start, - unsigned count) +static void r500_render_draw_arrays(struct vbuf_render* render, + unsigned start, + unsigned count) { struct r300_render* r300render = r300_render(render); struct r300_context* r300 = r300render->r300; @@ -752,9 +895,9 @@ static void r300_render_draw_arrays(struct vbuf_render* render, END_CS; } -static void r300_render_draw(struct vbuf_render* render, - const ushort* indices, - uint count) +static void r500_render_draw(struct vbuf_render* render, + const ushort* indices, + uint count) { struct r300_render* r300render = r300_render(render); struct r300_context* r300 = r300render->r300; @@ -780,6 +923,40 @@ static void r300_render_draw(struct vbuf_render* render, END_CS; } +static void r300_render_draw_arrays(struct vbuf_render* render, + unsigned start, + unsigned count) +{ + struct r300_context* r300 = r300_render(render)->r300; + + if (!r300->stencil_ref_bf_fallback) { + r500_render_draw_arrays(render, start, count); + } else { + r300_begin_stencil_ref_fallback(r300); + r500_render_draw_arrays(render, start, count); + r300_switch_stencil_ref_side(r300); + r500_render_draw_arrays(render, start, count); + r300_end_stencil_ref_fallback(r300); + } +} + +static void r300_render_draw(struct vbuf_render* render, + const ushort* indices, + uint count) +{ + struct r300_context* r300 = r300_render(render)->r300; + + if (!r300->stencil_ref_bf_fallback) { + r500_render_draw(render, indices, count); + } else { + r300_begin_stencil_ref_fallback(r300); + r500_render_draw(render, indices, count); + r300_switch_stencil_ref_side(r300); + r500_render_draw(render, indices, count); + r300_end_stencil_ref_fallback(r300); + } +} + static void r300_render_destroy(struct vbuf_render* render) { FREE(render); @@ -800,8 +977,13 @@ static struct vbuf_render* r300_render_create(struct r300_context* r300) r300render->base.map_vertices = r300_render_map_vertices; r300render->base.unmap_vertices = r300_render_unmap_vertices; r300render->base.set_primitive = r300_render_set_primitive; - r300render->base.draw = r300_render_draw; - r300render->base.draw_arrays = r300_render_draw_arrays; + if (r300->screen->caps.is_r500) { + r300render->base.draw = r500_render_draw; + r300render->base.draw_arrays = r500_render_draw_arrays; + } else { + r300render->base.draw = r300_render_draw; + r300render->base.draw_arrays = r300_render_draw_arrays; + } r300render->base.release_vertices = r300_render_release_vertices; r300render->base.destroy = r300_render_destroy; diff --git a/src/gallium/drivers/r300/r300_render.h b/src/gallium/drivers/r300/r300_render.h index 27b5e6a963..b8307c84d3 100644 --- a/src/gallium/drivers/r300/r300_render.h +++ b/src/gallium/drivers/r300/r300_render.h @@ -25,8 +25,44 @@ uint32_t r300_translate_primitive(unsigned prim); +void r500_emit_draw_arrays_immediate(struct r300_context *r300, + unsigned mode, + unsigned start, + unsigned count); + +void r500_emit_draw_arrays(struct r300_context *r300, + unsigned mode, + unsigned count); + +void r500_emit_draw_elements(struct r300_context *r300, + struct pipe_resource* indexBuffer, + unsigned indexSize, + unsigned minIndex, + unsigned maxIndex, + unsigned mode, + unsigned start, + unsigned count); + +void r300_emit_draw_arrays_immediate(struct r300_context *r300, + unsigned mode, + unsigned start, + unsigned count); + +void r300_emit_draw_arrays(struct r300_context *r300, + unsigned mode, + unsigned count); + +void r300_emit_draw_elements(struct r300_context *r300, + struct pipe_resource* indexBuffer, + unsigned indexSize, + unsigned minIndex, + unsigned maxIndex, + unsigned mode, + unsigned start, + unsigned count); + void r300_draw_range_elements(struct pipe_context* pipe, - struct pipe_buffer* indexBuffer, + struct pipe_resource* indexBuffer, unsigned indexSize, unsigned minIndex, unsigned maxIndex, @@ -35,7 +71,7 @@ void r300_draw_range_elements(struct pipe_context* pipe, unsigned count); void r300_draw_elements(struct pipe_context* pipe, - struct pipe_buffer* indexBuffer, + struct pipe_resource* indexBuffer, unsigned indexSize, unsigned mode, unsigned start, unsigned count); @@ -48,7 +84,7 @@ void r300_swtcl_draw_arrays(struct pipe_context* pipe, unsigned count); void r300_swtcl_draw_range_elements(struct pipe_context* pipe, - struct pipe_buffer* indexBuffer, + struct pipe_resource* indexBuffer, unsigned indexSize, unsigned minIndex, unsigned maxIndex, diff --git a/src/gallium/drivers/r300/r300_resource.c b/src/gallium/drivers/r300/r300_resource.c new file mode 100644 index 0000000000..0469b21b75 --- /dev/null +++ b/src/gallium/drivers/r300/r300_resource.c @@ -0,0 +1,90 @@ +/* + * Copyright 2010 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Dave Airlie + */ +#include <stdio.h> + +#include "util/u_inlines.h" +#include "util/u_format.h" +#include "util/u_memory.h" +#include "util/u_upload_mgr.h" +#include "util/u_math.h" + +#include "r300_context.h" +#include "r300_texture.h" +#include "r300_screen.h" +#include "r300_screen_buffer.h" + +#include "r300_winsys.h" + + + + +static struct pipe_resource * +r300_resource_create(struct pipe_screen *screen, + const struct pipe_resource *template) +{ + if (template->target == PIPE_BUFFER) + return r300_buffer_create(screen, template); + else + return r300_texture_create(screen, template); + +} + +static struct pipe_resource * +r300_resource_from_handle(struct pipe_screen * screen, + const struct pipe_resource *template, + struct winsys_handle *whandle) +{ + if (template->target == PIPE_BUFFER) + return NULL; + else + return r300_texture_from_handle(screen, template, whandle); +} + + + +void +r300_init_resource_functions(struct r300_context *r300) +{ + r300->context.get_transfer = u_get_transfer_vtbl; + r300->context.transfer_map = u_transfer_map_vtbl; + r300->context.transfer_flush_region = u_transfer_flush_region_vtbl; + r300->context.transfer_unmap = u_transfer_unmap_vtbl; + r300->context.transfer_destroy = u_transfer_destroy_vtbl; + r300->context.transfer_inline_write = u_transfer_inline_write_vtbl; + r300->context.is_resource_referenced = u_is_resource_referenced_vtbl; +} + +void +r300_init_screen_resource_functions(struct r300_screen *r300screen) +{ + r300screen->screen.resource_create = r300_resource_create; + r300screen->screen.resource_from_handle = r300_resource_from_handle; + r300screen->screen.resource_get_handle = u_resource_get_handle_vtbl; + r300screen->screen.resource_destroy = u_resource_destroy_vtbl; + r300screen->screen.user_buffer_create = r300_user_buffer_create; + + r300screen->screen.get_tex_surface = r300_get_tex_surface; + r300screen->screen.tex_surface_destroy = r300_tex_surface_destroy; +} diff --git a/src/gallium/drivers/r300/r300_screen.c b/src/gallium/drivers/r300/r300_screen.c index 50e5e9307e..8fc1d5aa00 100644 --- a/src/gallium/drivers/r300/r300_screen.c +++ b/src/gallium/drivers/r300/r300_screen.c @@ -72,7 +72,7 @@ static const char* r300_get_name(struct pipe_screen* pscreen) { struct r300_screen* r300screen = r300_screen(pscreen); - return chip_families[r300screen->caps->family]; + return chip_families[r300screen->caps.family]; } static int r300_get_param(struct pipe_screen* pscreen, int param) @@ -82,18 +82,13 @@ static int r300_get_param(struct pipe_screen* pscreen, int param) switch (param) { case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS: case PIPE_CAP_MAX_COMBINED_SAMPLERS: - /* XXX I'm told this goes up to 16 */ - return 8; + return r300screen->caps.num_tex_units; case PIPE_CAP_NPOT_TEXTURES: /* XXX enable now to get GL2.1 API, * figure out later how to emulate this */ return 1; case PIPE_CAP_TWO_SIDED_STENCIL: - if (r300screen->caps->is_r500) { - return 1; - } else { - return 0; - } + return 1; case PIPE_CAP_GLSL: /* I'll be frank. This is a lie. * @@ -126,7 +121,7 @@ static int r300_get_param(struct pipe_screen* pscreen, int param) case PIPE_CAP_MAX_TEXTURE_2D_LEVELS: case PIPE_CAP_MAX_TEXTURE_3D_LEVELS: case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS: - if (r300screen->caps->is_r500) { + if (r300screen->caps.is_r500) { /* 13 == 4096 */ return 13; } else { @@ -144,7 +139,7 @@ static int r300_get_param(struct pipe_screen* pscreen, int param) case PIPE_CAP_BLEND_EQUATION_SEPARATE: return 1; case PIPE_CAP_SM3: - if (r300screen->caps->is_r500) { + if (r300screen->caps.is_r500) { return 1; } else { return 0; @@ -181,9 +176,9 @@ static float r300_get_paramf(struct pipe_screen* pscreen, int param) case PIPE_CAP_MAX_POINT_WIDTH_AA: /* The maximum dimensions of the colorbuffer are our practical * rendering limits. 2048 pixels should be enough for anybody. */ - if (r300screen->caps->is_r500) { + if (r300screen->caps.is_r500) { return 4096.0f; - } else if (r300screen->caps->is_r400) { + } else if (r300screen->caps.is_r400) { return 4021.0f; } else { return 2560.0f; @@ -206,11 +201,14 @@ static boolean r300_is_format_supported(struct pipe_screen* screen, unsigned geom_flags) { uint32_t retval = 0; - boolean is_r500 = r300_screen(screen)->caps->is_r500; - boolean is_r400 = r300_screen(screen)->caps->is_r400; + boolean is_r500 = r300_screen(screen)->caps.is_r500; + boolean is_r400 = r300_screen(screen)->caps.is_r400; boolean is_z24 = format == PIPE_FORMAT_X8Z24_UNORM || format == PIPE_FORMAT_S8_USCALED_Z24_UNORM; - boolean is_color2101010 = format == PIPE_FORMAT_R10G10B10A2_UNORM; + boolean is_color2101010 = format == PIPE_FORMAT_R10G10B10A2_UNORM || + format == PIPE_FORMAT_R10G10B10X2_SNORM || + format == PIPE_FORMAT_B10G10R10A2_UNORM || + format == PIPE_FORMAT_R10SG10SB10SA2U_NORM; boolean is_ati1n = format == PIPE_FORMAT_RGTC1_UNORM || format == PIPE_FORMAT_RGTC1_SNORM; boolean is_ati2n = format == PIPE_FORMAT_RGTC2_UNORM || @@ -223,7 +221,7 @@ static boolean r300_is_format_supported(struct pipe_screen* screen, } /* Check sampler format support. */ - if ((usage & PIPE_TEXTURE_USAGE_SAMPLER) && + if ((usage & PIPE_BIND_SAMPLER_VIEW) && /* Z24 cannot be sampled from on non-r5xx. */ (is_r500 || !is_z24) && /* ATI1N is r5xx-only. */ @@ -231,28 +229,28 @@ static boolean r300_is_format_supported(struct pipe_screen* screen, /* ATI2N is supported on r4xx-r5xx. */ (is_r400 || is_r500 || !is_ati2n) && r300_is_sampler_format_supported(format)) { - retval |= PIPE_TEXTURE_USAGE_SAMPLER; + retval |= PIPE_BIND_SAMPLER_VIEW; } /* Check colorbuffer format support. */ - if ((usage & (PIPE_TEXTURE_USAGE_RENDER_TARGET | - PIPE_TEXTURE_USAGE_DISPLAY_TARGET | - PIPE_TEXTURE_USAGE_SCANOUT | - PIPE_TEXTURE_USAGE_SHARED)) && + if ((usage & (PIPE_BIND_RENDER_TARGET | + PIPE_BIND_DISPLAY_TARGET | + PIPE_BIND_SCANOUT | + PIPE_BIND_SHARED)) && /* 2101010 cannot be rendered to on non-r5xx. */ (is_r500 || !is_color2101010) && r300_is_colorbuffer_format_supported(format)) { retval |= usage & - (PIPE_TEXTURE_USAGE_RENDER_TARGET | - PIPE_TEXTURE_USAGE_DISPLAY_TARGET | - PIPE_TEXTURE_USAGE_SCANOUT | - PIPE_TEXTURE_USAGE_SHARED); + (PIPE_BIND_RENDER_TARGET | + PIPE_BIND_DISPLAY_TARGET | + PIPE_BIND_SCANOUT | + PIPE_BIND_SHARED); } /* Check depth-stencil format support. */ - if (usage & PIPE_TEXTURE_USAGE_DEPTH_STENCIL && + if (usage & PIPE_BIND_DEPTH_STENCIL && r300_is_zs_format_supported(format)) { - retval |= PIPE_TEXTURE_USAGE_DEPTH_STENCIL; + retval |= PIPE_BIND_DEPTH_STENCIL; } return retval == usage; @@ -266,29 +264,45 @@ static void r300_destroy_screen(struct pipe_screen* pscreen) if (rws) rws->destroy(rws); - FREE(r300screen->caps); FREE(r300screen); } +static void r300_fence_reference(struct pipe_screen *screen, + struct pipe_fence_handle **ptr, + struct pipe_fence_handle *fence) +{ +} + +static int r300_fence_signalled(struct pipe_screen *screen, + struct pipe_fence_handle *fence, + unsigned flags) +{ + return 0; +} + +static int r300_fence_finish(struct pipe_screen *screen, + struct pipe_fence_handle *fence, + unsigned flags) +{ + return 0; +} + struct pipe_screen* r300_create_screen(struct r300_winsys_screen *rws) { struct r300_screen *r300screen = CALLOC_STRUCT(r300_screen); - struct r300_capabilities *caps = CALLOC_STRUCT(r300_capabilities); - if (!r300screen || !caps) { + if (!r300screen) { FREE(r300screen); - FREE(caps); return NULL; } - caps->pci_id = rws->get_value(rws, R300_VID_PCI_ID); - caps->num_frag_pipes = rws->get_value(rws, R300_VID_GB_PIPES); - caps->num_z_pipes = rws->get_value(rws, R300_VID_Z_PIPES); + r300screen->caps.pci_id = rws->get_value(rws, R300_VID_PCI_ID); + r300screen->caps.num_frag_pipes = rws->get_value(rws, R300_VID_GB_PIPES); + r300screen->caps.num_z_pipes = rws->get_value(rws, R300_VID_Z_PIPES); r300_init_debug(r300screen); - r300_parse_chipset(caps); + r300_parse_chipset(&r300screen->caps); - r300screen->caps = caps; r300screen->rws = rws; r300screen->screen.winsys = (struct pipe_winsys*)rws; r300screen->screen.destroy = r300_destroy_screen; @@ -299,9 +313,12 @@ struct pipe_screen* r300_create_screen(struct r300_winsys_screen *rws) r300screen->screen.is_format_supported = r300_is_format_supported; r300screen->screen.context_create = r300_create_context; - r300_init_screen_texture_functions(&r300screen->screen); + r300screen->screen.fence_reference = r300_fence_reference; + r300screen->screen.fence_signalled = r300_fence_signalled; + r300screen->screen.fence_finish = r300_fence_finish; + + r300_init_screen_resource_functions(r300screen); - r300_screen_init_buffer_functions(r300screen); return &r300screen->screen; } diff --git a/src/gallium/drivers/r300/r300_screen.h b/src/gallium/drivers/r300/r300_screen.h index 1cf8b7452d..2f951c7097 100644 --- a/src/gallium/drivers/r300/r300_screen.h +++ b/src/gallium/drivers/r300/r300_screen.h @@ -37,7 +37,7 @@ struct r300_screen { struct r300_winsys_screen *rws; /* Chipset capabilities */ - struct r300_capabilities* caps; + struct r300_capabilities caps; /** Combination of DBG_xxx flags */ unsigned debug; @@ -89,5 +89,7 @@ static INLINE void SCREEN_DBG(struct r300_screen * screen, unsigned flags, void r300_init_debug(struct r300_screen* ctx); +void r300_init_screen_resource_functions(struct r300_screen *r300screen); + #endif /* R300_SCREEN_H */ diff --git a/src/gallium/drivers/r300/r300_screen_buffer.c b/src/gallium/drivers/r300/r300_screen_buffer.c index a1cd48ee73..cb47ba1688 100644 --- a/src/gallium/drivers/r300/r300_screen_buffer.c +++ b/src/gallium/drivers/r300/r300_screen_buffer.c @@ -34,23 +34,31 @@ #include "r300_winsys.h" -boolean r300_buffer_is_referenced(struct r300_context *r300, - struct pipe_buffer *buf) +static unsigned r300_buffer_is_referenced(struct pipe_context *context, + struct pipe_resource *buf, + unsigned face, unsigned level) { + struct r300_context *r300 = r300_context(context); struct r300_buffer *rbuf = r300_buffer(buf); + if (r300_buffer_is_user_buffer(buf)) - return FALSE; + return PIPE_UNREFERENCED; + + if (r300->rws->is_buffer_referenced(r300->rws, rbuf->buf)) + return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE; - return r300->rws->is_buffer_referenced(r300->rws, rbuf->buf); - + return PIPE_UNREFERENCED; } + +/* External helper, not required to implent u_resource_vtbl: + */ int r300_upload_index_buffer(struct r300_context *r300, - struct pipe_buffer **index_buffer, + struct pipe_resource **index_buffer, unsigned index_size, unsigned start, unsigned count) { - struct pipe_buffer *upload_buffer = NULL; + struct pipe_resource *upload_buffer = NULL; unsigned index_offset = start * index_size; int ret = 0; @@ -68,10 +76,12 @@ int r300_upload_index_buffer(struct r300_context *r300, } done: // if (upload_buffer) - // pipe_buffer_reference(&upload_buffer, NULL); + // pipe_resource_reference(&upload_buffer, NULL); return ret; } +/* External helper, not required to implent u_resource_vtbl: + */ int r300_upload_user_buffers(struct r300_context *r300) { enum pipe_error ret = PIPE_OK; @@ -82,9 +92,9 @@ int r300_upload_user_buffers(struct r300_context *r300) for (i = 0; i < nr; i++) { if (r300_buffer_is_user_buffer(r300->vertex_buffer[i].buffer)) { - struct pipe_buffer *upload_buffer = NULL; + struct pipe_resource *upload_buffer = NULL; unsigned offset = 0; /*r300->vertex_buffer[i].buffer_offset * 4;*/ - unsigned size = r300->vertex_buffer[i].buffer->size; + unsigned size = r300->vertex_buffer[i].buffer->width0; unsigned upload_offset; ret = u_upload_buffer(r300->upload_vb, offset, size, @@ -93,7 +103,7 @@ int r300_upload_user_buffers(struct r300_context *r300) if (ret) return ret; - pipe_buffer_reference(&r300->vertex_buffer[i].buffer, NULL); + pipe_resource_reference(&r300->vertex_buffer[i].buffer, NULL); r300->vertex_buffer[i].buffer = upload_buffer; r300->vertex_buffer[i].buffer_offset = upload_offset; } @@ -125,70 +135,11 @@ static void r300_winsys_buffer_destroy(struct r300_screen *r300screen, } } -static struct pipe_buffer *r300_buffer_create(struct pipe_screen *screen, - unsigned alignment, - unsigned usage, - unsigned size) -{ - struct r300_screen *r300screen = r300_screen(screen); - struct r300_buffer *rbuf; - - rbuf = CALLOC_STRUCT(r300_buffer); - if (!rbuf) - goto error1; - - rbuf->magic = R300_BUFFER_MAGIC; - - pipe_reference_init(&rbuf->base.reference, 1); - rbuf->base.screen = screen; - rbuf->base.alignment = alignment; - rbuf->base.usage = usage; - rbuf->base.size = size; - rbuf->buf = r300_winsys_buffer_create(r300screen, - alignment, - usage, - size); - - if (!rbuf->buf) - goto error2; - - return &rbuf->base; -error2: - FREE(rbuf); -error1: - return NULL; -} - - -static struct pipe_buffer *r300_user_buffer_create(struct pipe_screen *screen, - void *ptr, - unsigned bytes) +static void r300_buffer_destroy(struct pipe_screen *screen, + struct pipe_resource *buf) { - struct r300_buffer *rbuf; - - rbuf = CALLOC_STRUCT(r300_buffer); - if (!rbuf) - goto no_rbuf; - - rbuf->magic = R300_BUFFER_MAGIC; - - pipe_reference_init(&rbuf->base.reference, 1); - rbuf->base.screen = screen; - rbuf->base.alignment = 1; - rbuf->base.usage = 0; - rbuf->base.size = bytes; - - rbuf->user_buffer = ptr; - return &rbuf->base; - -no_rbuf: - return NULL; -} - -static void r300_buffer_destroy(struct pipe_buffer *buf) -{ - struct r300_screen *r300screen = r300_screen(buf->screen); + struct r300_screen *r300screen = r300_screen(screen); struct r300_buffer *rbuf = r300_buffer(buf); r300_winsys_buffer_destroy(r300screen, rbuf); @@ -197,7 +148,7 @@ static void r300_buffer_destroy(struct pipe_buffer *buf) static void * r300_buffer_map_range(struct pipe_screen *screen, - struct pipe_buffer *buf, + struct pipe_resource *buf, unsigned offset, unsigned length, unsigned usage ) { @@ -211,11 +162,12 @@ r300_buffer_map_range(struct pipe_screen *screen, if (rbuf->user_buffer) return rbuf->user_buffer; - if (rbuf->base.usage & PIPE_BUFFER_USAGE_CONSTANT) + if (rbuf->b.b.bind & PIPE_BIND_CONSTANT_BUFFER) { goto just_map; + } /* check if the mapping is to a range we already flushed */ - if (usage & PIPE_BUFFER_USAGE_DISCARD) { + if (usage & PIPE_TRANSFER_DISCARD) { for (i = 0; i < rbuf->num_ranges; i++) { if ((offset >= rbuf->ranges[i].start) && @@ -229,9 +181,9 @@ r300_buffer_map_range(struct pipe_screen *screen, rbuf->num_ranges = 0; rbuf->map = NULL; rbuf->buf = r300_winsys_buffer_create(r300screen, - rbuf->base.alignment, - rbuf->base.usage, - rbuf->base.size); + 16, + rbuf->b.b.bind, /* XXX */ + rbuf->b.b.width0); break; } } @@ -244,7 +196,7 @@ just_map: static void r300_buffer_flush_mapped_range( struct pipe_screen *screen, - struct pipe_buffer *buf, + struct pipe_resource *buf, unsigned offset, unsigned length ) { @@ -254,7 +206,7 @@ r300_buffer_flush_mapped_range( struct pipe_screen *screen, if (rbuf->user_buffer) return; - if (rbuf->base.usage & PIPE_BUFFER_USAGE_CONSTANT) + if (rbuf->b.b.bind & PIPE_BIND_CONSTANT_BUFFER) return; /* mark the range as used */ @@ -271,44 +223,152 @@ r300_buffer_flush_mapped_range( struct pipe_screen *screen, rbuf->num_ranges++; } -static void * -r300_buffer_map(struct pipe_screen *screen, - struct pipe_buffer *buf, - unsigned usage) + +static void +r300_buffer_unmap(struct pipe_screen *screen, + struct pipe_resource *buf) { struct r300_screen *r300screen = r300_screen(screen); struct r300_winsys_screen *rws = r300screen->rws; struct r300_buffer *rbuf = r300_buffer(buf); - void *map; - if (rbuf->user_buffer) - return rbuf->user_buffer; + if (rbuf->buf) { + rws->buffer_unmap(rws, rbuf->buf); + } +} - map = rws->buffer_map(rws, rbuf->buf, usage); - return map; + + +/* As a first step, keep the original code intact, implement buffer + * transfers in terms of the old map/unmap functions. + * + * Utility functions for transfer create/destroy are hooked in and + * just record the arguments to those functions. + */ +static void * +r300_buffer_transfer_map( struct pipe_context *pipe, + struct pipe_transfer *transfer ) +{ + uint8_t *map = r300_buffer_map_range( pipe->screen, + transfer->resource, + transfer->box.x, + transfer->box.width, + transfer->usage ); + if (map == NULL) + return NULL; + + /* map_buffer() returned a pointer to the beginning of the buffer, + * but transfers are expected to return a pointer to just the + * region specified in the box. + */ + return map + transfer->box.x; } -static void -r300_buffer_unmap(struct pipe_screen *screen, - struct pipe_buffer *buf) + + +static void r300_buffer_transfer_flush_region( struct pipe_context *pipe, + struct pipe_transfer *transfer, + const struct pipe_box *box) +{ + assert(box->x + box->width <= transfer->box.width); + + r300_buffer_flush_mapped_range(pipe->screen, + transfer->resource, + transfer->box.x + box->x, + box->width); +} + +static void r300_buffer_transfer_unmap( struct pipe_context *pipe, + struct pipe_transfer *transfer ) +{ + r300_buffer_unmap(pipe->screen, + transfer->resource); +} + + + + +struct u_resource_vtbl r300_buffer_vtbl = +{ + u_default_resource_get_handle, /* get_handle */ + r300_buffer_destroy, /* resource_destroy */ + r300_buffer_is_referenced, /* is_buffer_referenced */ + u_default_get_transfer, /* get_transfer */ + u_default_transfer_destroy, /* transfer_destroy */ + r300_buffer_transfer_map, /* transfer_map */ + r300_buffer_transfer_flush_region, /* transfer_flush_region */ + r300_buffer_transfer_unmap, /* transfer_unmap */ + u_default_transfer_inline_write /* transfer_inline_write */ +}; + + + + +struct pipe_resource *r300_buffer_create(struct pipe_screen *screen, + const struct pipe_resource *template) { struct r300_screen *r300screen = r300_screen(screen); - struct r300_winsys_screen *rws = r300screen->rws; - struct r300_buffer *rbuf = r300_buffer(buf); + struct r300_buffer *rbuf; + unsigned alignment = 16; - if (rbuf->buf) { - rws->buffer_unmap(rws, rbuf->buf); - } + rbuf = CALLOC_STRUCT(r300_buffer); + if (!rbuf) + goto error1; + + rbuf->magic = R300_BUFFER_MAGIC; + + rbuf->b.b = *template; + rbuf->b.vtbl = &r300_buffer_vtbl; + pipe_reference_init(&rbuf->b.b.reference, 1); + rbuf->b.b.screen = screen; + + if (rbuf->b.b.bind & R300_BIND_OQBO) + alignment = 4096; + + rbuf->buf = r300_winsys_buffer_create(r300screen, + alignment, + rbuf->b.b.bind, + rbuf->b.b.width0); + + if (!rbuf->buf) + goto error2; + + return &rbuf->b.b; +error2: + FREE(rbuf); +error1: + return NULL; } -void r300_screen_init_buffer_functions(struct r300_screen *r300screen) + +struct pipe_resource *r300_user_buffer_create(struct pipe_screen *screen, + void *ptr, + unsigned bytes, + unsigned bind) { - r300screen->screen.buffer_create = r300_buffer_create; - r300screen->screen.user_buffer_create = r300_user_buffer_create; - r300screen->screen.buffer_map = r300_buffer_map; - r300screen->screen.buffer_map_range = r300_buffer_map_range; - r300screen->screen.buffer_flush_mapped_range = r300_buffer_flush_mapped_range; - r300screen->screen.buffer_unmap = r300_buffer_unmap; - r300screen->screen.buffer_destroy = r300_buffer_destroy; + struct r300_buffer *rbuf; + + rbuf = CALLOC_STRUCT(r300_buffer); + if (!rbuf) + goto no_rbuf; + + rbuf->magic = R300_BUFFER_MAGIC; + + pipe_reference_init(&rbuf->b.b.reference, 1); + rbuf->b.vtbl = &r300_buffer_vtbl; + rbuf->b.b.screen = screen; + rbuf->b.b.format = PIPE_FORMAT_R8_UNORM; + rbuf->b.b._usage = PIPE_USAGE_IMMUTABLE; + rbuf->b.b.bind = bind; + rbuf->b.b.width0 = bytes; + rbuf->b.b.height0 = 1; + rbuf->b.b.depth0 = 1; + + rbuf->user_buffer = ptr; + return &rbuf->b.b; + +no_rbuf: + return NULL; } + diff --git a/src/gallium/drivers/r300/r300_screen_buffer.h b/src/gallium/drivers/r300/r300_screen_buffer.h index 0cf349c25c..93009ea02f 100644 --- a/src/gallium/drivers/r300/r300_screen_buffer.h +++ b/src/gallium/drivers/r300/r300_screen_buffer.h @@ -3,6 +3,7 @@ #include <stdio.h> #include "pipe/p_compiler.h" #include "pipe/p_state.h" +#include "util/u_transfer.h" #include "r300_screen.h" #include "r300_winsys.h" @@ -18,7 +19,7 @@ struct r300_buffer_range { struct r300_buffer { - struct pipe_buffer base; + struct u_resource b; uint32_t magic; @@ -32,7 +33,7 @@ struct r300_buffer }; static INLINE struct r300_buffer * -r300_buffer(struct pipe_buffer *buffer) +r300_buffer(struct pipe_resource *buffer) { if (buffer) { assert(((struct r300_buffer *)buffer)->magic == R300_BUFFER_MAGIC); @@ -42,13 +43,13 @@ r300_buffer(struct pipe_buffer *buffer) } static INLINE boolean -r300_buffer_is_user_buffer(struct pipe_buffer *buffer) +r300_buffer_is_user_buffer(struct pipe_resource *buffer) { return r300_buffer(buffer)->user_buffer ? true : false; } static INLINE boolean r300_add_buffer(struct r300_winsys_screen *rws, - struct pipe_buffer *buffer, + struct pipe_resource *buffer, int rd, int wr) { struct r300_buffer *buf = r300_buffer(buffer); @@ -67,7 +68,6 @@ static INLINE boolean r300_add_texture(struct r300_winsys_screen *rws, return rws->add_buffer(rws, tex->buffer, rd, wr); } -void r300_screen_init_buffer_functions(struct r300_screen *r300screen); static INLINE void r300_buffer_write_reloc(struct r300_winsys_screen *rws, struct r300_buffer *buf, @@ -89,11 +89,18 @@ static INLINE void r300_texture_write_reloc(struct r300_winsys_screen *rws, int r300_upload_user_buffers(struct r300_context *r300); int r300_upload_index_buffer(struct r300_context *r300, - struct pipe_buffer **index_buffer, + struct pipe_resource **index_buffer, unsigned index_size, unsigned start, unsigned count); -boolean r300_buffer_is_referenced(struct r300_context *r300, - struct pipe_buffer *buf); + +struct pipe_resource *r300_buffer_create(struct pipe_screen *screen, + const struct pipe_resource *template); + +struct pipe_resource *r300_user_buffer_create(struct pipe_screen *screen, + void *ptr, + unsigned bytes, + unsigned usage); + #endif diff --git a/src/gallium/drivers/r300/r300_state.c b/src/gallium/drivers/r300/r300_state.c index 39e05583dd..371e52d208 100644 --- a/src/gallium/drivers/r300/r300_state.c +++ b/src/gallium/drivers/r300/r300_state.c @@ -32,11 +32,14 @@ #include "pipe/p_config.h" #include "r300_context.h" +#include "r300_emit.h" #include "r300_reg.h" #include "r300_screen.h" #include "r300_screen_buffer.h" +#include "r300_state.h" #include "r300_state_inlines.h" #include "r300_fs.h" +#include "r300_texture.h" #include "r300_vs.h" #include "r300_winsys.h" @@ -219,7 +222,7 @@ static void* r300_create_blend_state(struct pipe_context* pipe, /* Enable reading from the colorbuffer. */ blend->blend_control |= R300_READ_ENABLE; - if (r300_screen(r300_context(pipe)->context.screen)->caps->is_r500) { + if (r300screen->caps.is_r500) { /* Optimization: Depending on incoming pixels, we can * conditionally disable the reading in hardware... */ if (eqRGB != PIPE_BLEND_MIN && eqA != PIPE_BLEND_MIN && @@ -308,7 +311,7 @@ static void* r300_create_blend_state(struct pipe_context* pipe, /* Color channel masks for all MRTs. */ blend->color_channel_mask = bgra_cmask(state->rt[0].colormask); - if (r300screen->caps->is_r500 && state->independent_blend_enable) { + if (r300screen->caps.is_r500 && state->independent_blend_enable) { if (state->rt[1].blend_enable) { blend->color_channel_mask |= bgra_cmask(state->rt[1].colormask) << 4; } @@ -320,10 +323,17 @@ static void* r300_create_blend_state(struct pipe_context* pipe, } } + /* Neither fglrx nor classic r300 ever set this, regardless of dithering + * state. Since it's an optional implementation detail, we can leave it + * out and never dither. + * + * This could be revisited if we ever get quality or conformance hints. + * if (state->dither) { blend->dither = R300_RB3D_DITHER_CTL_DITHER_MODE_LUT | - R300_RB3D_DITHER_CTL_ALPHA_DITHER_MODE_LUT; + R300_RB3D_DITHER_CTL_ALPHA_DITHER_MODE_LUT; } + */ return (void*)blend; } @@ -356,7 +366,6 @@ static void r300_set_blend_color(struct pipe_context* pipe, const struct pipe_blend_color* color) { struct r300_context* r300 = r300_context(pipe); - struct r300_screen* r300screen = r300_screen(pipe->screen); struct r300_blend_color_state* state = (struct r300_blend_color_state*)r300->blend_color_state.state; union util_color uc; @@ -372,7 +381,7 @@ static void r300_set_blend_color(struct pipe_context* pipe, float_to_fixed10(color->color[2]) | (float_to_fixed10(color->color[1]) << 16); - r300->blend_color_state.size = r300screen->caps->is_r500 ? 3 : 2; + r300->blend_color_state.size = r300->screen->caps.is_r500 ? 3 : 2; r300->blend_color_state.dirty = TRUE; } @@ -383,7 +392,7 @@ static void r300_set_clip_state(struct pipe_context* pipe, r300->clip = *state; - if (r300_screen(pipe->screen)->caps->has_tcl) { + if (r300->screen->caps.has_tcl) { memcpy(r300->clip_state.state, state, sizeof(struct pipe_clip_state)); r300->clip_state.size = 29; } else { @@ -404,8 +413,7 @@ static void* r300_create_dsa_state(struct pipe_context* pipe, const struct pipe_depth_stencil_alpha_state* state) { - struct r300_capabilities *caps = - r300_screen(r300_context(pipe)->context.screen)->caps; + struct r300_capabilities *caps = &r300_screen(pipe->screen)->caps; struct r300_dsa_state* dsa = CALLOC_STRUCT(r300_dsa_state); /* Depth test setup. */ @@ -439,6 +447,8 @@ static void* (state->stencil[0].writemask << R300_STENCILWRITEMASK_SHIFT); if (state->stencil[1].enabled) { + dsa->two_sided = TRUE; + dsa->z_buffer_control |= R300_STENCIL_FRONT_BACK; dsa->z_stencil_control |= (r300_translate_depth_stencil_function(state->stencil[1].func) << @@ -450,14 +460,16 @@ static void* (r300_translate_stencil_op(state->stencil[1].zfail_op) << R300_S_BACK_ZFAIL_OP_SHIFT); - if (caps->is_r500) - { + dsa->stencil_ref_bf = + (state->stencil[1].valuemask << R300_STENCILMASK_SHIFT) | + (state->stencil[1].writemask << R300_STENCILWRITEMASK_SHIFT); + + if (caps->is_r500) { dsa->z_buffer_control |= R500_STENCIL_REFMASK_FRONT_BACK; - dsa->stencil_ref_bf = - (state->stencil[1].valuemask << - R300_STENCILMASK_SHIFT) | - (state->stencil[1].writemask << - R300_STENCILWRITEMASK_SHIFT); + } else { + dsa->stencil_ref_bf_fallback = + (state->stencil[0].valuemask != state->stencil[1].valuemask || + state->stencil[0].writemask != state->stencil[1].writemask); } } } @@ -478,13 +490,33 @@ static void* return (void*)dsa; } +static void r300_update_stencil_ref_fallback_status(struct r300_context *r300) +{ + struct r300_dsa_state *dsa = (struct r300_dsa_state*)r300->dsa_state.state; + + if (r300->screen->caps.is_r500) { + return; + } + + r300->stencil_ref_bf_fallback = + dsa->stencil_ref_bf_fallback || + (dsa->two_sided && + r300->stencil_ref.ref_value[0] != r300->stencil_ref.ref_value[1]); +} + /* Bind DSA state. */ static void r300_bind_dsa_state(struct pipe_context* pipe, void* state) { struct r300_context* r300 = r300_context(pipe); + if (!state) { + return; + } + UPDATE_STATE(state, r300->dsa_state); + + r300_update_stencil_ref_fallback_status(r300); } /* Free DSA state. */ @@ -498,8 +530,11 @@ static void r300_set_stencil_ref(struct pipe_context* pipe, const struct pipe_stencil_ref* sr) { struct r300_context* r300 = r300_context(pipe); + r300->stencil_ref = *sr; r300->dsa_state.dirty = TRUE; + + r300_update_stencil_ref_fallback_status(r300); } /* This switcheroo is needed just because of goddamned MACRO_SWITCH. */ @@ -522,7 +557,7 @@ static void r300_fb_update_tiling_flags(struct r300_context *r300, continue; } - tex = (struct r300_texture*)old_state->cbufs[i]->texture; + tex = r300_texture(old_state->cbufs[i]->texture); if (tex) { r300->rws->buffer_set_tiling(r300->rws, tex->buffer, @@ -534,7 +569,7 @@ static void r300_fb_update_tiling_flags(struct r300_context *r300, if (old_state->zsbuf && (!new_state->zsbuf || old_state->zsbuf->texture != new_state->zsbuf->texture)) { - tex = (struct r300_texture*)old_state->zsbuf->texture; + tex = r300_texture(old_state->zsbuf->texture); if (tex) { r300->rws->buffer_set_tiling(r300->rws, tex->buffer, @@ -546,7 +581,7 @@ static void r300_fb_update_tiling_flags(struct r300_context *r300, /* Set tiling flags for new surfaces. */ for (i = 0; i < new_state->nr_cbufs; i++) { - tex = (struct r300_texture*)new_state->cbufs[i]->texture; + tex = r300_texture(new_state->cbufs[i]->texture); level = new_state->cbufs[i]->level; r300->rws->buffer_set_tiling(r300->rws, tex->buffer, @@ -555,7 +590,7 @@ static void r300_fb_update_tiling_flags(struct r300_context *r300, tex->mip_macrotile[level]); } if (new_state->zsbuf) { - tex = (struct r300_texture*)new_state->zsbuf->texture; + tex = r300_texture(new_state->zsbuf->texture); level = new_state->zsbuf->level; r300->rws->buffer_set_tiling(r300->rws, tex->buffer, @@ -570,7 +605,6 @@ static void const struct pipe_framebuffer_state* state) { struct r300_context* r300 = r300_context(pipe); - struct r300_screen* r300screen = r300_screen(pipe->screen); struct pipe_framebuffer_state *old_state = r300->fb_state.state; unsigned max_width, max_height; uint32_t zbuffer_bpp = 0; @@ -581,9 +615,9 @@ static void return; } - if (r300screen->caps->is_r500) { + if (r300->screen->caps.is_r500) { max_width = max_height = 4096; - } else if (r300screen->caps->is_r400) { + } else if (r300->screen->caps.is_r400) { max_width = max_height = 4021; } else { max_width = max_height = 2560; @@ -609,16 +643,13 @@ static void if (!!old_state->zsbuf != !!state->zsbuf) { r300->dsa_state.dirty = TRUE; } - if (!r300->scissor_enabled) { - r300->scissor_state.dirty = TRUE; - } r300_fb_update_tiling_flags(r300, r300->fb_state.state, state); memcpy(r300->fb_state.state, state, sizeof(struct pipe_framebuffer_state)); r300->fb_state.size = (10 * state->nr_cbufs) + (2 * (4 - state->nr_cbufs)) + - (state->zsbuf ? 10 : 0) + 8; + (state->zsbuf ? 10 : 0) + 11; /* Polygon offset depends on the zbuffer bit depth. */ if (state->zsbuf && r300->polygon_offset_enabled) { @@ -650,12 +681,28 @@ static void* r300_create_fs_state(struct pipe_context* pipe, fs->state = *shader; fs->state.tokens = tgsi_dup_tokens(shader->tokens); - tgsi_scan_shader(shader->tokens, &fs->info); - r300_shader_read_fs_inputs(&fs->info, &fs->inputs); - return (void*)fs; } +void r300_mark_fs_code_dirty(struct r300_context *r300) +{ + struct r300_fragment_shader* fs = r300_fs(r300); + + r300->fs.dirty = TRUE; + r300->fs_rc_constant_state.dirty = TRUE; + r300->fs_constants.dirty = TRUE; + + if (r300->screen->caps.is_r500) { + r300->fs.size = r500_get_fs_atom_size(r300); + r300->fs_rc_constant_state.size = fs->shader->rc_state_count * 7; + r300->fs_constants.size = fs->shader->externals_count * 4 + 3; + } else { + r300->fs.size = r300_get_fs_atom_size(r300); + r300->fs_rc_constant_state.size = fs->shader->rc_state_count * 5; + r300->fs_constants.size = fs->shader->externals_count * 4 + 1; + } +} + /* Bind fragment shader state. */ static void r300_bind_fs_state(struct pipe_context* pipe, void* shader) { @@ -663,20 +710,19 @@ static void r300_bind_fs_state(struct pipe_context* pipe, void* shader) struct r300_fragment_shader* fs = (struct r300_fragment_shader*)shader; if (fs == NULL) { - r300->fs = NULL; + r300->fs.state = NULL; return; } - r300->fs = fs; + r300->fs.state = fs; r300_pick_fragment_shader(r300); + r300_mark_fs_code_dirty(r300); 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; } /* Delete fragment shader state. */ @@ -711,8 +757,8 @@ static void r300_set_polygon_stipple(struct pipe_context* pipe, static void* r300_create_rs_state(struct pipe_context* pipe, const struct pipe_rasterizer_state* state) { - struct r300_screen* r300screen = r300_screen(pipe->screen); struct r300_rs_state* rs = CALLOC_STRUCT(r300_rs_state); + int i; /* Copy rasterizer state for Draw. */ rs->rs = *state; @@ -724,7 +770,7 @@ static void* r300_create_rs_state(struct pipe_context* pipe, #endif /* If no TCL engine is present, turn off the HW TCL. */ - if (!r300screen->caps->has_tcl) { + if (!r300_screen(pipe->screen)->caps.has_tcl) { rs->vap_control_status |= R300_VAP_TCL_BYPASS; } @@ -805,6 +851,32 @@ static void* r300_create_rs_state(struct pipe_context* pipe, rs->color_control = R300_SHADE_MODEL_SMOOTH; } + rs->clip_rule = state->scissor ? 0xAAAA : 0xFFFF; + + /* Point sprites */ + if (state->sprite_coord_enable) { + rs->stuffing_enable = R300_GB_POINT_STUFF_ENABLE; + for (i = 0; i < 8; i++) { + if (state->sprite_coord_enable & (1 << i)) + rs->stuffing_enable |= + R300_GB_TEX_STR << (R300_GB_TEX0_SOURCE_SHIFT + (i*2)); + } + + rs->point_texcoord_left = 0.0f; + rs->point_texcoord_right = 1.0f; + + switch (state->sprite_coord_mode) { + case PIPE_SPRITE_COORD_UPPER_LEFT: + rs->point_texcoord_top = 0.0f; + rs->point_texcoord_bottom = 1.0f; + break; + case PIPE_SPRITE_COORD_LOWER_LEFT: + rs->point_texcoord_top = 1.0f; + rs->point_texcoord_bottom = 0.0f; + break; + } + } + return (void*)rs; } @@ -813,7 +885,7 @@ static void r300_bind_rs_state(struct pipe_context* pipe, void* state) { struct r300_context* r300 = r300_context(pipe); struct r300_rs_state* rs = (struct r300_rs_state*)state; - boolean scissor_was_enabled = r300->scissor_enabled; + int last_sprite_coord_enable = r300->sprite_coord_enable; if (r300->draw) { draw_flush(r300->draw); @@ -822,17 +894,17 @@ 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->scissor_enabled = rs->rs.scissor; + r300->sprite_coord_enable = rs->rs.sprite_coord_enable; } else { r300->polygon_offset_enabled = FALSE; - r300->scissor_enabled = FALSE; + r300->sprite_coord_enable = 0; } UPDATE_STATE(state, r300->rs_state); - r300->rs_state.size = 17 + (r300->polygon_offset_enabled ? 5 : 0); + r300->rs_state.size = 26 + (r300->polygon_offset_enabled ? 5 : 0); - if (scissor_was_enabled != r300->scissor_enabled) { - r300->scissor_state.dirty = TRUE; + if (last_sprite_coord_enable != r300->sprite_coord_enable) { + r300->rs_block_state.dirty = TRUE; } } @@ -848,7 +920,7 @@ static void* { struct r300_context* r300 = r300_context(pipe); struct r300_sampler_state* sampler = CALLOC_STRUCT(r300_sampler_state); - boolean is_r500 = r300_screen(pipe->screen)->caps->is_r500; + boolean is_r500 = r300->screen->caps.is_r500; int lod_bias; union util_color uc; @@ -887,7 +959,7 @@ static void* sampler->border_color = uc.ui; /* R500-specific fixups and optimizations */ - if (r300_screen(r300->context.screen)->caps->is_r500) { + if (r300->screen->caps.is_r500) { sampler->filter1 |= R500_BORDER_FIX; } @@ -901,23 +973,16 @@ static void r300_bind_sampler_states(struct pipe_context* pipe, struct r300_context* r300 = r300_context(pipe); struct r300_textures_state* state = (struct r300_textures_state*)r300->textures_state.state; + unsigned tex_units = r300->screen->caps.num_tex_units; - if (count > 8) { + if (count > tex_units) { return; } memcpy(state->sampler_states, states, sizeof(void*) * count); - state->sampler_count = count; + state->sampler_state_count = count; r300->textures_state.dirty = TRUE; - - /* Pick a fragment shader based on the texture compare state. */ - if (r300->fs && count) { - if (r300_pick_fragment_shader(r300)) { - r300->dirty_state |= R300_NEW_FRAGMENT_SHADER | - R300_NEW_FRAGMENT_SHADER_CONSTANTS; - } - } } static void r300_lacks_vertex_textures(struct pipe_context* pipe, @@ -940,18 +1005,18 @@ static void r300_set_fragment_sampler_views(struct pipe_context* pipe, (struct r300_textures_state*)r300->textures_state.state; struct r300_texture *texture; unsigned i; - boolean is_r500 = r300_screen(r300->context.screen)->caps->is_r500; + unsigned tex_units = r300->screen->caps.num_tex_units; boolean dirty_tex = FALSE; - /* XXX magic num */ - if (count > 8) { + if (count > tex_units) { return; } for (i = 0; i < count; i++) { - if (state->fragment_sampler_views[i] != views[i]) { - pipe_sampler_view_reference(&state->fragment_sampler_views[i], - views[i]); + if (&state->sampler_views[i]->base != views[i]) { + pipe_sampler_view_reference( + (struct pipe_sampler_view**)&state->sampler_views[i], + views[i]); if (!views[i]) { continue; @@ -960,24 +1025,24 @@ static void r300_set_fragment_sampler_views(struct pipe_context* pipe, /* A new sampler view (= texture)... */ dirty_tex = TRUE; - /* R300-specific - set the texrect factor in the fragment shader */ - texture = (struct r300_texture *)views[i]->texture; - if (!is_r500 && texture->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; + /* Set the texrect factor in the fragment shader. + * Needed for RECT and NPOT fallback. */ + texture = r300_texture(views[i]->texture); + if (texture->uses_pitch) { + r300->fs_rc_constant_state.dirty = TRUE; } } } - for (i = count; i < 8; i++) { - if (state->fragment_sampler_views[i]) { - pipe_sampler_view_reference(&state->fragment_sampler_views[i], - NULL); + for (i = count; i < tex_units; i++) { + if (state->sampler_views[i]) { + pipe_sampler_view_reference( + (struct pipe_sampler_view**)&state->sampler_views[i], + NULL); } } - state->texture_count = count; + state->sampler_view_count = count; r300->textures_state.dirty = TRUE; @@ -988,27 +1053,43 @@ static void r300_set_fragment_sampler_views(struct pipe_context* pipe, static struct pipe_sampler_view * r300_create_sampler_view(struct pipe_context *pipe, - struct pipe_texture *texture, + struct pipe_resource *texture, const struct pipe_sampler_view *templ) { - struct pipe_sampler_view *view = CALLOC_STRUCT(pipe_sampler_view); - - if (view) { - *view = *templ; - view->reference.count = 1; - view->texture = NULL; - pipe_texture_reference(&view->texture, texture); - view->context = pipe; - } + struct r300_sampler_view *view = CALLOC_STRUCT(r300_sampler_view); + struct r300_texture *tex = r300_texture(texture); + unsigned char swizzle[4]; + + if (view) { + view->base = *templ; + view->base.reference.count = 1; + view->base.context = pipe; + view->base.texture = NULL; + pipe_resource_reference(&view->base.texture, texture); + + swizzle[0] = templ->swizzle_r; + swizzle[1] = templ->swizzle_g; + swizzle[2] = templ->swizzle_b; + swizzle[3] = templ->swizzle_a; + + /* XXX Enable swizzles when they become supported. Now we get RGBA + * everywhere. And do testing! */ + view->format = tex->tx_format; + view->format.format1 |= r300_translate_texformat(templ->format, + 0); /*swizzle);*/ + if (r300_screen(pipe->screen)->caps.is_r500) { + view->format.format2 |= r500_tx_format_msb_bit(templ->format); + } + } - return view; + return (struct pipe_sampler_view*)view; } static void r300_sampler_view_destroy(struct pipe_context *pipe, struct pipe_sampler_view *view) { - pipe_texture_reference(&view->texture, NULL); + pipe_resource_reference(&view->texture, NULL); FREE(view); } @@ -1020,9 +1101,7 @@ static void r300_set_scissor_state(struct pipe_context* pipe, memcpy(r300->scissor_state.state, state, sizeof(struct pipe_scissor_state)); - if (r300->scissor_enabled) { - r300->scissor_state.dirty = TRUE; - } + r300->scissor_state.dirty = TRUE; } static void r300_set_viewport_state(struct pipe_context* pipe, @@ -1063,8 +1142,8 @@ static void r300_set_viewport_state(struct pipe_context* pipe, } r300->viewport_state.dirty = TRUE; - if (r300->fs && r300->fs->inputs.wpos != ATTR_UNUSED) { - r300->dirty_state |= R300_NEW_FRAGMENT_SHADER_CONSTANTS; + if (r300->fs.state && r300_fs(r300)->shader->inputs.wpos != ATTR_UNUSED) { + r300->fs_rc_constant_state.dirty = TRUE; } } @@ -1088,10 +1167,9 @@ static void r300_set_vertex_buffers(struct pipe_context* pipe, if (buffers[i].buffer) { if (buffers[i].stride % 4 != 0) { // XXX Shouldn't we align the buffer? - fprintf(stderr, "r300_set_vertex_buffers: " + fprintf(stderr, "r300: set_vertex_buffers: " "Unaligned buffer stride %i isn't supported.\n", buffers[i].stride); - assert(0); abort(); } } @@ -1102,7 +1180,7 @@ static void r300_set_vertex_buffers(struct pipe_context* pipe, vbo = (struct pipe_vertex_buffer*)&buffers[i]; /* Reference our buffer. */ - pipe_buffer_reference(&r300->vertex_buffer[i].buffer, vbo->buffer); + pipe_resource_reference(&r300->vertex_buffer[i].buffer, vbo->buffer); /* Skip NULL buffers */ if (!buffers[i].buffer) { @@ -1115,8 +1193,13 @@ static void r300_set_vertex_buffers(struct pipe_context* pipe, if (vbo->max_index == ~0) { /* Bogus value from broken state tracker; hax it. */ + /* TODO - more hax - fixes doom3 from almos on irc */ + if (!vbo->stride) { + fprintf(stderr, "r300: got a VBO with stride 0 fixing up to stide 4\n"); + vbo->stride = 4; + } vbo->max_index = - (vbo->buffer->size - vbo->buffer_offset) / vbo->stride; + (vbo->buffer->width0 - vbo->buffer_offset) / vbo->stride; } max_index = MIN2(vbo->max_index, max_index); @@ -1124,7 +1207,7 @@ static void r300_set_vertex_buffers(struct pipe_context* pipe, for (; i < r300->vertex_buffer_count; i++) { /* Dereference any old buffers. */ - pipe_buffer_reference(&r300->vertex_buffer[i].buffer, NULL); + pipe_resource_reference(&r300->vertex_buffer[i].buffer, NULL); } memcpy(r300->vertex_buffer, buffers, @@ -1148,7 +1231,11 @@ static void r300_vertex_psc(struct r300_vertex_element_state *velems) enum pipe_format format; unsigned i; - assert(velems->count <= 16); + if (velems->count > 16) { + fprintf(stderr, "r300: More than 16 vertex elements are not supported," + " requested %i, using 16.\n", velems->count); + velems->count = 16; + } /* Vertex shaders have no semantics on their inputs, * so PSC should just route stuff based on the vertex elements, @@ -1183,7 +1270,6 @@ static void* r300_create_vertex_elements_state(struct pipe_context* pipe, unsigned count, const struct pipe_vertex_element* attribs) { - struct r300_screen* r300screen = r300_screen(pipe->screen); struct r300_vertex_element_state *velems; unsigned i, size; @@ -1193,7 +1279,7 @@ static void* r300_create_vertex_elements_state(struct pipe_context* pipe, velems->count = count; memcpy(velems->velem, attribs, sizeof(struct pipe_vertex_element) * count); - if (r300screen->caps->has_tcl) { + if (r300_screen(pipe->screen)->caps.has_tcl) { /* Check if the format is aligned to the size of DWORD. */ for (i = 0; i < count; i++) { size = util_format_get_blocksize(attribs[i].src_format); @@ -1246,10 +1332,13 @@ static void* r300_create_vs_state(struct pipe_context* pipe, struct r300_context* r300 = r300_context(pipe); struct r300_vertex_shader* vs = CALLOC_STRUCT(r300_vertex_shader); - r300_vertex_shader_common_init(vs, shader); - if (r300_screen(pipe->screen)->caps->has_tcl) { - r300_translate_vertex_shader(r300, vs); + /* Copy state directly into shader. */ + vs->state = *shader; + vs->state.tokens = tgsi_dup_tokens(shader->tokens); + + if (r300->screen->caps.has_tcl) { + r300_translate_vertex_shader(r300, vs, vs->state.tokens); } else { vs->draw_vs = draw_create_vertex_shader(r300->draw, shader); } @@ -1272,7 +1361,7 @@ static void r300_bind_vs_state(struct pipe_context* pipe, void* shader) r300->vs_state.state = vs; // VS output mapping for HWTCL or stream mapping for SWTCL to the RS block - if (r300->fs) { + if (r300->fs.state) { r300_vertex_shader_setup_wpos(r300); } memcpy(r300->vap_output_state.state, &vs->vap_out, @@ -1282,13 +1371,20 @@ static void r300_bind_vs_state(struct pipe_context* pipe, void* shader) /* The majority of the RS block bits is dependent on the vertex shader. */ r300->rs_block_state.dirty = TRUE; /* Will be updated before the emission. */ - if (r300_screen(pipe->screen)->caps->has_tcl) { + if (r300->screen->caps.has_tcl) { r300->vs_state.dirty = TRUE; - r300->vs_state.size = vs->code.length + 9; + r300->vs_state.size = + vs->code.length + 9 + + (vs->immediates_count ? vs->immediates_count * 4 + 3 : 0); - r300->pvs_flush.dirty = TRUE; + if (vs->externals_count) { + r300->vs_constants.dirty = TRUE; + r300->vs_constants.size = vs->externals_count * 4 + 3; + } else { + r300->vs_constants.size = 0; + } - r300->dirty_state |= R300_NEW_VERTEX_SHADER_CONSTANTS; + r300->pvs_flush.dirty = TRUE; } else { draw_flush(r300->draw); draw_bind_vertex_shader(r300->draw, @@ -1301,7 +1397,7 @@ static void r300_delete_vs_state(struct pipe_context* pipe, void* shader) struct r300_context* r300 = r300_context(pipe); struct r300_vertex_shader* vs = (struct r300_vertex_shader*)shader; - if (r300_screen(pipe->screen)->caps->has_tcl) { + if (r300->screen->caps.has_tcl) { rc_constants_destroy(&vs->code.constants); } else { draw_delete_vertex_shader(r300->draw, @@ -1314,63 +1410,66 @@ static void r300_delete_vs_state(struct pipe_context* pipe, void* shader) static void r300_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index, - struct pipe_buffer *buf) + struct pipe_resource *buf) { struct r300_context* r300 = r300_context(pipe); - struct r300_screen *r300screen = r300_screen(pipe->screen); + struct r300_constant_buffer *cbuf; + struct pipe_transfer *tr; void *mapped; int max_size = 0; - if (buf == NULL || buf->size == 0 || - (mapped = pipe_buffer_map(pipe->screen, buf, PIPE_BUFFER_USAGE_CPU_READ)) == NULL) - { - r300->shader_constants[shader].count = 0; - return; - } - - assert((buf->size % 4 * sizeof(float)) == 0); - - /* Check the size of the constant buffer. */ switch (shader) { case PIPE_SHADER_VERTEX: + cbuf = (struct r300_constant_buffer*)r300->vs_constants.state; max_size = 256; break; case PIPE_SHADER_FRAGMENT: - if (r300screen->caps->is_r500) { + cbuf = (struct r300_constant_buffer*)r300->fs_constants.state; + if (r300->screen->caps.is_r500) { max_size = 256; - /* XXX Implement emission of r400's extended constant buffer. */ - /*} else if (r300screen->caps->is_r400) { - max_size = 64;*/ } else { max_size = 32; } break; default: assert(0); + return; + } + + if (buf == NULL || buf->width0 == 0 || + (mapped = pipe_buffer_map(pipe, buf, PIPE_TRANSFER_READ, &tr)) == NULL) + { + cbuf->count = 0; + return; } + assert((buf->width0 % 4 * sizeof(float)) == 0); + + /* Check the size of the constant buffer. */ /* XXX Subtract immediates and RC_STATE_* variables. */ - if (buf->size > (sizeof(float) * 4 * max_size)) { + 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(); } - memcpy(r300->shader_constants[shader].constants, mapped, buf->size); - r300->shader_constants[shader].count = buf->size / (4 * sizeof(float)); - pipe_buffer_unmap(pipe->screen, buf); + memcpy(cbuf->constants, mapped, buf->width0); + cbuf->count = buf->width0 / (4 * sizeof(float)); + pipe_buffer_unmap(pipe, buf, tr); if (shader == PIPE_SHADER_VERTEX) { - if (r300screen->caps->has_tcl) { - r300->dirty_state |= R300_NEW_VERTEX_SHADER_CONSTANTS; + if (r300->screen->caps.has_tcl) { + if (r300->vs_constants.size) { + r300->vs_constants.dirty = TRUE; + } r300->pvs_flush.dirty = TRUE; } else if (r300->draw) { draw_set_mapped_constant_buffer(r300->draw, PIPE_SHADER_VERTEX, - 0, r300->shader_constants[PIPE_SHADER_VERTEX].constants, - buf->size); + 0, cbuf->constants, + buf->width0); } } else if (shader == PIPE_SHADER_FRAGMENT) { - r300->dirty_state |= R300_NEW_FRAGMENT_SHADER_CONSTANTS; + r300->fs_constants.dirty = TRUE; } } diff --git a/src/gallium/drivers/r300/r300_state.h b/src/gallium/drivers/r300/r300_state.h new file mode 100644 index 0000000000..1d557506cf --- /dev/null +++ b/src/gallium/drivers/r300/r300_state.h @@ -0,0 +1,30 @@ +/* + * Copyright 2008 Marek Olšák <maraeo@gmail.com> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef R300_STATE_H +#define R300_STATE_H + +struct r300_context; + +void r300_mark_fs_code_dirty(struct r300_context *r300); + +#endif /* R300_STATE_H */ diff --git a/src/gallium/drivers/r300/r300_state_derived.c b/src/gallium/drivers/r300/r300_state_derived.c index bc5431c802..a36cff98c3 100644 --- a/src/gallium/drivers/r300/r300_state_derived.c +++ b/src/gallium/drivers/r300/r300_state_derived.c @@ -30,6 +30,7 @@ #include "r300_fs.h" #include "r300_screen.h" #include "r300_shader_semantics.h" +#include "r300_state.h" #include "r300_state_derived.h" #include "r300_state_inlines.h" #include "r300_vs.h" @@ -37,6 +38,12 @@ /* r300_state_derived: Various bits of state which are dependent upon * currently bound CSO data. */ +enum r300_rs_swizzle { + SWIZ_XYZW = 0, + SWIZ_X001, + SWIZ_XY01, +}; + static void r300_draw_emit_attrib(struct r300_context* r300, enum attrib_emit emit, enum interp_mode interp, @@ -83,8 +90,10 @@ static void r300_draw_emit_all_attribs(struct r300_context* r300) /* XXX Back-face colors. */ /* Texture coordinates. */ + /* Only 8 generic vertex attributes can be used. If there are more, + * they won't be rasterized. */ gen_count = 0; - for (i = 0; i < ATTR_GENERIC_COUNT; i++) { + for (i = 0; i < ATTR_GENERIC_COUNT && gen_count < 8; i++) { if (vs_outputs->generic[i] != ATTR_UNUSED) { r300_draw_emit_attrib(r300, EMIT_4F, INTERP_PERSPECTIVE, vs_outputs->generic[i]); @@ -93,14 +102,11 @@ static void r300_draw_emit_all_attribs(struct r300_context* r300) } /* Fog coordinates. */ - if (vs_outputs->fog != ATTR_UNUSED) { + if (gen_count < 8 && vs_outputs->fog != ATTR_UNUSED) { r300_draw_emit_attrib(r300, EMIT_4F, INTERP_PERSPECTIVE, vs_outputs->fog); gen_count++; } - - /* XXX magic */ - assert(gen_count <= 8); } /* Update the PSC tables for SW TCL, using Draw. */ @@ -181,14 +187,20 @@ static void r300_rs_col_write(struct r300_rs_block* rs, int id, int fp_offset) } static void r300_rs_tex(struct r300_rs_block* rs, int id, int ptr, - boolean swizzle_X001) + enum r300_rs_swizzle swiz) { - if (swizzle_X001) { + if (swiz == SWIZ_X001) { rs->ip[id] |= R300_RS_TEX_PTR(ptr*4) | R300_RS_SEL_S(R300_RS_SEL_C0) | R300_RS_SEL_T(R300_RS_SEL_K0) | R300_RS_SEL_R(R300_RS_SEL_K0) | R300_RS_SEL_Q(R300_RS_SEL_K1); + } else if (swiz == SWIZ_XY01) { + rs->ip[id] |= R300_RS_TEX_PTR(ptr*4) | + R300_RS_SEL_S(R300_RS_SEL_C0) | + R300_RS_SEL_T(R300_RS_SEL_C1) | + R300_RS_SEL_R(R300_RS_SEL_K0) | + R300_RS_SEL_Q(R300_RS_SEL_K1); } else { rs->ip[id] |= R300_RS_TEX_PTR(ptr*4) | R300_RS_SEL_S(R300_RS_SEL_C0) | @@ -224,15 +236,20 @@ static void r500_rs_col_write(struct r300_rs_block* rs, int id, int fp_offset) } static void r500_rs_tex(struct r300_rs_block* rs, int id, int ptr, - boolean swizzle_X001) + enum r300_rs_swizzle swiz) { int rs_tex_comp = ptr*4; - if (swizzle_X001) { + if (swiz == SWIZ_X001) { rs->ip[id] |= R500_RS_SEL_S(rs_tex_comp) | R500_RS_SEL_T(R500_RS_IP_PTR_K0) | R500_RS_SEL_R(R500_RS_IP_PTR_K0) | R500_RS_SEL_Q(R500_RS_IP_PTR_K1); + } else if (swiz == SWIZ_XY01) { + rs->ip[id] |= R500_RS_SEL_S(rs_tex_comp) | + R500_RS_SEL_T(rs_tex_comp + 1) | + R500_RS_SEL_R(R500_RS_IP_PTR_K0) | + R500_RS_SEL_Q(R500_RS_IP_PTR_K1); } else { rs->ip[id] |= R500_RS_SEL_S(rs_tex_comp) | R500_RS_SEL_T(rs_tex_comp + 1) | @@ -261,12 +278,12 @@ static void r300_update_rs_block(struct r300_context* r300, int i, col_count = 0, tex_count = 0, fp_offset = 0, count; void (*rX00_rs_col)(struct r300_rs_block*, int, int, boolean); void (*rX00_rs_col_write)(struct r300_rs_block*, int, int); - void (*rX00_rs_tex)(struct r300_rs_block*, int, int, boolean); + void (*rX00_rs_tex)(struct r300_rs_block*, int, int, enum r300_rs_swizzle); void (*rX00_rs_tex_write)(struct r300_rs_block*, int, int); boolean any_bcolor_used = vs_outputs->bcolor[0] != ATTR_UNUSED || vs_outputs->bcolor[1] != ATTR_UNUSED; - if (r300_screen(r300->context.screen)->caps->is_r500) { + if (r300->screen->caps.is_r500) { rX00_rs_col = r500_rs_col; rX00_rs_col_write = r500_rs_col_write; rX00_rs_tex = r500_rs_tex; @@ -303,14 +320,19 @@ static void r300_update_rs_block(struct r300_context* r300, /* Rasterize texture coordinates. */ for (i = 0; i < ATTR_GENERIC_COUNT; i++) { - if (vs_outputs->generic[i] != ATTR_UNUSED) { + bool sprite_coord = !!(r300->sprite_coord_enable & (1 << i)); + + if (vs_outputs->generic[i] != ATTR_UNUSED || sprite_coord) { /* Always rasterize if it's written by the VS, * otherwise it locks up. */ - rX00_rs_tex(&rs, tex_count, tex_count, FALSE); + rX00_rs_tex(&rs, tex_count, tex_count, + sprite_coord ? SWIZ_XY01 : SWIZ_XYZW); /* Write it to the FS input register if it's used by the FS. */ if (fs_inputs->generic[i] != ATTR_UNUSED) { rX00_rs_tex_write(&rs, tex_count, fp_offset); + if (sprite_coord) + debug_printf("r300: SpriteCoord (generic index %i) is being written to reg %i\n", i, fp_offset); fp_offset++; } tex_count++; @@ -327,7 +349,7 @@ static void r300_update_rs_block(struct r300_context* r300, if (vs_outputs->fog != ATTR_UNUSED) { /* Always rasterize if it's written by the VS, * otherwise it locks up. */ - rX00_rs_tex(&rs, tex_count, tex_count, TRUE); + rX00_rs_tex(&rs, tex_count, tex_count, SWIZ_X001); /* Write it to the FS input register if it's used by the FS. */ if (fs_inputs->fog != ATTR_UNUSED) { @@ -345,8 +367,8 @@ static void r300_update_rs_block(struct r300_context* r300, /* Rasterize WPOS. */ /* If the FS doesn't need it, it's not written by the VS. */ - if (fs_inputs->wpos != ATTR_UNUSED) { - rX00_rs_tex(&rs, tex_count, tex_count, FALSE); + if (vs_outputs->wpos != ATTR_UNUSED && fs_inputs->wpos != ATTR_UNUSED) { + rX00_rs_tex(&rs, tex_count, tex_count, SWIZ_XYZW); rX00_rs_tex_write(&rs, tex_count, fp_offset); fp_offset++; @@ -377,7 +399,7 @@ static void r300_update_derived_shader_state(struct r300_context* r300) { struct r300_vertex_shader* vs = r300->vs_state.state; - r300_update_rs_block(r300, &vs->outputs, &r300->fs->inputs); + r300_update_rs_block(r300, &vs->outputs, &r300_fs(r300)->shader->inputs); } static boolean r300_dsa_writes_depth_stencil(struct r300_dsa_state* dsa) @@ -437,12 +459,12 @@ static void r300_update_ztop(struct r300_context* r300) /* ZS writes */ if (r300_dsa_writes_depth_stencil(r300->dsa_state.state) && - (r300_dsa_alpha_test_enabled(r300->dsa_state.state) ||/* (1) */ - r300->fs->info.uses_kill)) { /* (2) */ + (r300_dsa_alpha_test_enabled(r300->dsa_state.state) || /* (1) */ + r300_fs(r300)->shader->info.uses_kill)) { /* (2) */ ztop_state->z_buffer_top = R300_ZTOP_DISABLE; - } else if (r300_fragment_shader_writes_depth(r300->fs)) { /* (5) */ + } else if (r300_fragment_shader_writes_depth(r300_fs(r300))) { /* (5) */ ztop_state->z_buffer_top = R300_ZTOP_DISABLE; - } else if (r300->query_current) { /* (6) */ + } else if (r300->query_current) { /* (6) */ ztop_state->z_buffer_top = R300_ZTOP_DISABLE; } else { ztop_state->z_buffer_top = R300_ZTOP_ENABLE; @@ -457,55 +479,71 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300) (struct r300_textures_state*)r300->textures_state.state; struct r300_texture_sampler_state *texstate; struct r300_sampler_state *sampler; - struct pipe_sampler_view *view; + struct r300_sampler_view *view; struct r300_texture *tex; unsigned min_level, max_level, i, size; - unsigned count = MIN2(state->texture_count, state->sampler_count); + unsigned count = MIN2(state->sampler_view_count, + state->sampler_state_count); state->tx_enable = 0; state->count = 0; size = 2; for (i = 0; i < count; i++) { - if (state->fragment_sampler_views[i] && state->sampler_states[i]) { + if (state->sampler_views[i] && state->sampler_states[i]) { state->tx_enable |= 1 << i; - view = state->fragment_sampler_views[i]; - tex = (struct r300_texture *)view->texture; + view = state->sampler_views[i]; + tex = r300_texture(view->base.texture); sampler = state->sampler_states[i]; - assert(view->format == tex->tex.format); - texstate = &state->regs[i]; - memcpy(texstate->format, &tex->state, sizeof(uint32_t)*3); - texstate->filter[0] = sampler->filter0; - texstate->filter[1] = sampler->filter1; + texstate->format = view->format; + texstate->filter0 = sampler->filter0; + texstate->filter1 = 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->b.b.target == PIPE_TEXTURE_1D) { + texstate->filter0 &= ~R300_TX_WRAP_T_MASK; + texstate->filter0 |= R300_TX_WRAP_T(R300_TX_CLAMP_TO_EDGE); } - if (tex->is_npot) { + if (tex->uses_pitch) { /* NPOT textures don't support mip filter, unfortunately. * This prevents incorrect rendering. */ - texstate->filter[0] &= ~R300_TX_MIN_FILTER_MIP_MASK; + texstate->filter0 &= ~R300_TX_MIN_FILTER_MIP_MASK; + + /* Set repeat or mirrored-repeat to clamp-to-edge. */ + /* Wrap S. */ + if ((texstate->filter0 & R300_TX_WRAP_S_MASK) == + R300_TX_WRAP_S(R300_TX_REPEAT) || + (texstate->filter0 & R300_TX_WRAP_S_MASK) == + R300_TX_WRAP_S(R300_TX_MIRRORED)) { + texstate->filter0 &= ~R300_TX_WRAP_S_MASK; + texstate->filter0 |= R300_TX_WRAP_S(R300_TX_CLAMP_TO_EDGE); + } + + /* Wrap T. */ + if ((texstate->filter0 & R300_TX_WRAP_T_MASK) == + R300_TX_WRAP_T(R300_TX_REPEAT) || + (texstate->filter0 & R300_TX_WRAP_T_MASK) == + R300_TX_WRAP_T(R300_TX_MIRRORED)) { + texstate->filter0 &= ~R300_TX_WRAP_T_MASK; + texstate->filter0 |= R300_TX_WRAP_T(R300_TX_CLAMP_TO_EDGE); + } } else { /* determine min/max levels */ /* the MAX_MIP level is the largest (finest) one */ - max_level = MIN3(sampler->max_lod + view->first_level, - tex->tex.last_level, view->last_level); - min_level = MIN2(sampler->min_lod + view->first_level, + max_level = MIN3(sampler->max_lod + view->base.first_level, + tex->b.b.last_level, view->base.last_level); + min_level = MIN2(sampler->min_lod + view->base.first_level, max_level); - texstate->format[0] |= R300_TX_NUM_LEVELS(max_level); - texstate->filter[0] |= R300_TX_MAX_MIP_LEVEL(min_level); + texstate->format.format0 |= R300_TX_NUM_LEVELS(max_level); + texstate->filter0 |= R300_TX_MAX_MIP_LEVEL(min_level); } - texstate->filter[0] |= i << 28; + texstate->filter0 |= i << 28; size += 16; state->count = i+1; @@ -513,18 +551,26 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300) } r300->textures_state.size = size; + + /* Pick a fragment shader based on either the texture compare state + * or the uses_pitch flag. */ + if (r300->fs.state && count) { + if (r300_pick_fragment_shader(r300)) { + r300_mark_fs_code_dirty(r300); + } + } } void r300_update_derived_state(struct r300_context* r300) { - if (r300->rs_block_state.dirty) { - r300_update_derived_shader_state(r300); - } - if (r300->textures_state.dirty) { r300_merge_textures_and_samplers(r300); } + if (r300->rs_block_state.dirty) { + r300_update_derived_shader_state(r300); + } + if (r300->draw) { memset(&r300->vertex_info, 0, sizeof(struct vertex_info)); r300_draw_emit_all_attribs(r300); diff --git a/src/gallium/drivers/r300/r300_state_inlines.h b/src/gallium/drivers/r300/r300_state_inlines.h index 8a690039b6..044d70cbe8 100644 --- a/src/gallium/drivers/r300/r300_state_inlines.h +++ b/src/gallium/drivers/r300/r300_state_inlines.h @@ -338,7 +338,7 @@ static INLINE uint32_t r500_anisotropy(unsigned max_aniso) // Map the range [0, 15] to [0, 63]. return R500_TX_MAX_ANISO(MIN2((unsigned)(max_aniso*4.2001), 63)) | - R500_TX_ANISO_HIGH_QUALITY;; + R500_TX_ANISO_HIGH_QUALITY; } /* Non-CSO state. (For now.) */ diff --git a/src/gallium/drivers/r300/r300_state_invariant.c b/src/gallium/drivers/r300/r300_state_invariant.c index 88ae75bb81..ffb175febf 100644 --- a/src/gallium/drivers/r300/r300_state_invariant.c +++ b/src/gallium/drivers/r300/r300_state_invariant.c @@ -41,16 +41,12 @@ struct pipe_viewport_state r300_viewport_identity = { void r300_emit_invariant_state(struct r300_context* r300, unsigned size, void* state) { - struct r300_capabilities* caps = r300_screen(r300->context.screen)->caps; + struct r300_capabilities* caps = &r300_screen(r300->context.screen)->caps; CS_LOCALS(r300); - BEGIN_CS(14 + (caps->has_tcl ? 2: 0)); + BEGIN_CS(12 + (caps->has_tcl ? 2: 0)); /*** Graphics Backend (GB) ***/ - /* Various GB enables */ - OUT_CS_REG(R300_GB_ENABLE, R300_GB_POINT_STUFF_ENABLE | - R300_GB_LINE_STUFF_ENABLE | - R300_GB_TRIANGLE_STUFF_ENABLE); /* Subpixel multisampling for AA * These are commented out because glisse's CS checker doesn't like them. * I presume these will be re-enabled later. @@ -78,7 +74,7 @@ void r300_emit_invariant_state(struct r300_context* r300, END_CS; /* XXX unsorted stuff from surface_fill */ - BEGIN_CS(44 + (caps->has_tcl ? 7 : 0) + + BEGIN_CS(38 + (caps->has_tcl ? 7 : 0) + (caps->family >= CHIP_FAMILY_RV350 ? 4 : 0)); if (caps->has_tcl) { @@ -90,11 +86,6 @@ void r300_emit_invariant_state(struct r300_context* r300, OUT_CS_32F(1.0); OUT_CS_32F(1.0); } - /* XXX point tex stuffing */ - OUT_CS_REG_SEQ(R300_GA_POINT_S0, 1); - OUT_CS_32F(0.0); - OUT_CS_REG_SEQ(R300_GA_POINT_S1, 1); - OUT_CS_32F(1.0); /* XXX line tex stuffing */ OUT_CS_REG_SEQ(R300_GA_LINE_S0, 1); OUT_CS_32F(0.0); @@ -125,9 +116,5 @@ void r300_emit_invariant_state(struct r300_context* r300, OUT_CS_REG(R300_ZB_DEPTHCLEARVALUE, 0x00000000); OUT_CS_REG(R300_ZB_HIZ_OFFSET, 0x00000000); OUT_CS_REG(R300_ZB_HIZ_PITCH, 0x00000000); - - /* XXX */ - OUT_CS_REG(R300_SC_CLIP_RULE, 0xFFFF); - END_CS; } diff --git a/src/gallium/drivers/r300/r300_texture.c b/src/gallium/drivers/r300/r300_texture.c index e7bac615df..4439e35d67 100644 --- a/src/gallium/drivers/r300/r300_texture.c +++ b/src/gallium/drivers/r300/r300_texture.c @@ -28,7 +28,9 @@ #include "util/u_memory.h" #include "r300_context.h" +#include "r300_reg.h" #include "r300_texture.h" +#include "r300_transfer.h" #include "r300_screen.h" #include "r300_winsys.h" @@ -71,7 +73,8 @@ static boolean r300_format_is_plain(enum pipe_format format) * * The FORMAT specifies how the texture sampler will treat the texture, and * makes available X, Y, Z, W, ZERO, and ONE for swizzling. */ -static uint32_t r300_translate_texformat(enum pipe_format format) +uint32_t r300_translate_texformat(enum pipe_format format, + const unsigned char *swizzle) { uint32_t result = 0; const struct util_format_description *desc; @@ -83,7 +86,7 @@ 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] = { + const uint32_t swizzle_bit[4] = { R300_TX_FORMAT_X, R300_TX_FORMAT_Y, R300_TX_FORMAT_Z, @@ -130,24 +133,50 @@ static uint32_t r300_translate_texformat(enum pipe_format format) result |= R300_TX_FORMAT_GAMMA; break; - default:; + default: + switch (format) { + /* Same as YUV but without the YUR->RGB conversion. */ + case PIPE_FORMAT_R8G8_B8G8_UNORM: + return R300_EASY_TX_FORMAT(X, Y, Z, ONE, YVYU422) | result; + case PIPE_FORMAT_G8R8_G8B8_UNORM: + return R300_EASY_TX_FORMAT(X, Y, Z, ONE, VYUY422) | result; + default:; + } } /* Add swizzle. */ + if (!swizzle) { + swizzle = desc->swizzle; + } /*else { + if (swizzle[0] != desc->swizzle[0] || + swizzle[1] != desc->swizzle[1] || + swizzle[2] != desc->swizzle[2] || + swizzle[3] != desc->swizzle[3]) + { + const char n[6] = "RGBA01"; + fprintf(stderr, "Got different swizzling! Format: %c%c%c%c, " + "View: %c%c%c%c\n", + n[desc->swizzle[0]], n[desc->swizzle[1]], + n[desc->swizzle[2]], n[desc->swizzle[3]], + n[swizzle[0]], n[swizzle[1]], n[swizzle[2]], + n[swizzle[3]]); + } + }*/ + for (i = 0; i < 4; i++) { - switch (desc->swizzle[i]) { + switch (swizzle[i]) { case UTIL_FORMAT_SWIZZLE_X: case UTIL_FORMAT_SWIZZLE_NONE: - result |= swizzle[0] << swizzle_shift[i]; + result |= swizzle_bit[0] << swizzle_shift[i]; break; case UTIL_FORMAT_SWIZZLE_Y: - result |= swizzle[1] << swizzle_shift[i]; + result |= swizzle_bit[1] << swizzle_shift[i]; break; case UTIL_FORMAT_SWIZZLE_Z: - result |= swizzle[2] << swizzle_shift[i]; + result |= swizzle_bit[2] << swizzle_shift[i]; break; case UTIL_FORMAT_SWIZZLE_W: - result |= swizzle[3] << swizzle_shift[i]; + result |= swizzle_bit[3] << swizzle_shift[i]; break; case UTIL_FORMAT_SWIZZLE_0: result |= R300_TX_FORMAT_ZERO << swizzle_shift[i]; @@ -186,6 +215,13 @@ static uint32_t r300_translate_texformat(enum pipe_format format) } } + /* This is truly a special format. + * It stores R8G8 and B is computed using sqrt(1 - R^2 - G^2) + * in the sampler unit. Also known as D3DFMT_CxV8U8. */ + if (format == PIPE_FORMAT_R8G8Bx_SNORM) { + return R300_TX_FORMAT_CxV8U8 | result; + } + /* RGTC formats. */ if (desc->layout == UTIL_FORMAT_LAYOUT_RGTC) { switch (format) { @@ -310,7 +346,7 @@ static uint32_t r300_translate_texformat(enum pipe_format format) return ~0; /* Unsupported/unknown. */ } -static uint32_t r500_tx_format_msb_bit(enum pipe_format format) +uint32_t r500_tx_format_msb_bit(enum pipe_format format) { switch (format) { case PIPE_FORMAT_RGTC1_UNORM: @@ -339,10 +375,13 @@ static uint32_t r300_translate_colorformat(enum pipe_format format) /* 16-bit buffers. */ case PIPE_FORMAT_B5G6R5_UNORM: return R300_COLOR_FORMAT_RGB565; + case PIPE_FORMAT_B5G5R5A1_UNORM: case PIPE_FORMAT_B5G5R5X1_UNORM: return R300_COLOR_FORMAT_ARGB1555; + case PIPE_FORMAT_B4G4R4A4_UNORM: + case PIPE_FORMAT_B4G4R4X4_UNORM: return R300_COLOR_FORMAT_ARGB4444; /* 32-bit buffers. */ @@ -353,9 +392,14 @@ static uint32_t r300_translate_colorformat(enum pipe_format format) case PIPE_FORMAT_A8B8G8R8_UNORM: case PIPE_FORMAT_R8G8B8A8_SNORM: case PIPE_FORMAT_X8B8G8R8_UNORM: + case PIPE_FORMAT_R8G8B8X8_UNORM: case PIPE_FORMAT_R8SG8SB8UX8U_NORM: return R300_COLOR_FORMAT_ARGB8888; + case PIPE_FORMAT_R10G10B10A2_UNORM: + case PIPE_FORMAT_R10G10B10X2_SNORM: + case PIPE_FORMAT_B10G10R10A2_UNORM: + case PIPE_FORMAT_R10SG10SB10SA2U_NORM: return R500_COLOR_FORMAT_ARGB2101010; /* R5xx-only? */ /* 64-bit buffers. */ @@ -457,8 +501,10 @@ static uint32_t r300_translate_out_fmt(enum pipe_format format) case PIPE_FORMAT_B5G5R5A1_UNORM: case PIPE_FORMAT_B5G5R5X1_UNORM: case PIPE_FORMAT_B4G4R4A4_UNORM: + case PIPE_FORMAT_B4G4R4X4_UNORM: case PIPE_FORMAT_B8G8R8A8_UNORM: case PIPE_FORMAT_B8G8R8X8_UNORM: + case PIPE_FORMAT_B10G10R10A2_UNORM: return modifier | R300_C0_SEL_B | R300_C1_SEL_G | R300_C2_SEL_R | R300_C3_SEL_A; @@ -478,9 +524,12 @@ static uint32_t r300_translate_out_fmt(enum pipe_format format) R300_C2_SEL_G | R300_C3_SEL_R; /* RGBA outputs. */ + case PIPE_FORMAT_R8G8B8X8_UNORM: case PIPE_FORMAT_R8G8B8A8_SNORM: case PIPE_FORMAT_R8SG8SB8UX8U_NORM: case PIPE_FORMAT_R10G10B10A2_UNORM: + case PIPE_FORMAT_R10G10B10X2_SNORM: + case PIPE_FORMAT_R10SG10SB10SA2U_NORM: case PIPE_FORMAT_R16G16B16A16_UNORM: case PIPE_FORMAT_R16G16B16A16_SNORM: //case PIPE_FORMAT_R16G16B16A16_FLOAT: /* not in pipe_format */ @@ -507,75 +556,83 @@ boolean r300_is_zs_format_supported(enum pipe_format format) boolean r300_is_sampler_format_supported(enum pipe_format format) { - return r300_translate_texformat(format) != ~0; + return r300_translate_texformat(format, 0) != ~0; } -static void r300_setup_texture_state(struct r300_screen* screen, struct r300_texture* tex) +static void r300_texture_setup_immutable_state(struct r300_screen* screen, + struct r300_texture* tex) { - struct r300_texture_format_state* state = &tex->state; - struct pipe_texture *pt = &tex->tex; - unsigned i; - boolean is_r500 = screen->caps->is_r500; + struct r300_texture_format_state* f = &tex->tx_format; + struct pipe_resource *pt = &tex->b.b; + boolean is_r500 = screen->caps.is_r500; /* Set sampler state. */ - state->format0 = R300_TX_WIDTH((pt->width0 - 1) & 0x7ff) | - R300_TX_HEIGHT((pt->height0 - 1) & 0x7ff); + f->format0 = R300_TX_WIDTH((pt->width0 - 1) & 0x7ff) | + R300_TX_HEIGHT((pt->height0 - 1) & 0x7ff); - if (tex->is_npot) { + if (tex->uses_pitch) { /* rectangles love this */ - state->format0 |= R300_TX_PITCH_EN; - state->format2 = (tex->pitch[0] - 1) & 0x1fff; + f->format0 |= R300_TX_PITCH_EN; + f->format2 = (tex->pitch[0] - 1) & 0x1fff; } else { /* power of two textures (3D, mipmaps, and no pitch) */ - state->format0 |= R300_TX_DEPTH(util_logbase2(pt->depth0) & 0xf); + f->format0 |= R300_TX_DEPTH(util_logbase2(pt->depth0) & 0xf); } - state->format1 = r300_translate_texformat(pt->format); + f->format1 = 0; if (pt->target == PIPE_TEXTURE_CUBE) { - state->format1 |= R300_TX_FORMAT_CUBIC_MAP; + f->format1 |= R300_TX_FORMAT_CUBIC_MAP; } if (pt->target == PIPE_TEXTURE_3D) { - state->format1 |= R300_TX_FORMAT_3D; + f->format1 |= R300_TX_FORMAT_3D; } /* large textures on r500 */ if (is_r500) { if (pt->width0 > 2048) { - state->format2 |= R500_TXWIDTH_BIT11; + f->format2 |= R500_TXWIDTH_BIT11; } if (pt->height0 > 2048) { - state->format2 |= R500_TXHEIGHT_BIT11; + f->format2 |= R500_TXHEIGHT_BIT11; } - state->format2 |= r500_tx_format_msb_bit(pt->format); } + f->tile_config = R300_TXO_MACRO_TILE(tex->macrotile) | + R300_TXO_MICRO_TILE(tex->microtile); + SCREEN_DBG(screen, DBG_TEX, "r300: Set texture state (%dx%d, %d levels)\n", pt->width0, pt->height0, pt->last_level); +} + +static void r300_texture_setup_fb_state(struct r300_screen* screen, + struct r300_texture* tex) +{ + unsigned i; /* Set framebuffer state. */ - if (util_format_is_depth_or_stencil(tex->tex.format)) { - for (i = 0; i <= tex->tex.last_level; i++) { + if (util_format_is_depth_or_stencil(tex->b.b.format)) { + for (i = 0; i <= tex->b.b.last_level; i++) { tex->fb_state.depthpitch[i] = tex->pitch[i] | R300_DEPTHMACROTILE(tex->mip_macrotile[i]) | R300_DEPTHMICROTILE(tex->microtile); } - tex->fb_state.zb_format = r300_translate_zsformat(tex->tex.format); + tex->fb_state.zb_format = r300_translate_zsformat(tex->b.b.format); } else { - for (i = 0; i <= tex->tex.last_level; i++) { + for (i = 0; i <= tex->b.b.last_level; i++) { tex->fb_state.colorpitch[i] = tex->pitch[i] | - r300_translate_colorformat(tex->tex.format) | + r300_translate_colorformat(tex->b.b.format) | R300_COLOR_TILE(tex->mip_macrotile[i]) | R300_COLOR_MICROTILE(tex->microtile); } - tex->fb_state.us_out_fmt = r300_translate_out_fmt(tex->tex.format); + tex->fb_state.us_out_fmt = r300_translate_out_fmt(tex->b.b.format); } } void r300_texture_reinterpret_format(struct pipe_screen *screen, - struct pipe_texture *tex, + struct pipe_resource *tex, enum pipe_format new_format) { struct r300_screen *r300screen = r300_screen(screen); @@ -585,7 +642,7 @@ void r300_texture_reinterpret_format(struct pipe_screen *screen, tex->format = new_format; - r300_setup_texture_state(r300_screen(screen), (struct r300_texture*)tex); + r300_texture_setup_fb_state(r300_screen(screen), r300_texture(tex)); } unsigned r300_texture_get_offset(struct r300_texture* tex, unsigned level, @@ -593,7 +650,7 @@ unsigned r300_texture_get_offset(struct r300_texture* tex, unsigned level, { unsigned offset = tex->offset[level]; - switch (tex->tex.target) { + switch (tex->b.b.target) { case PIPE_TEXTURE_3D: assert(face == 0); return offset + zslice * tex->layer_size[level]; @@ -617,7 +674,7 @@ static unsigned r300_texture_get_tile_size(struct r300_texture* tex, { unsigned pixsize, tile_size; - pixsize = util_format_get_blocksize(tex->tex.format); + pixsize = util_format_get_blocksize(tex->b.b.format); tile_size = microblock_table[util_logbase2(pixsize)][tex->microtile][dim]; if (macrotile) { @@ -638,9 +695,9 @@ static boolean r300_texture_macro_switch(struct r300_texture *tex, tile = r300_texture_get_tile_size(tex, dim, TRUE); if (dim == TILE_WIDTH) { - texdim = u_minify(tex->tex.width0, level); + texdim = u_minify(tex->b.b.width0, level); } else { - texdim = u_minify(tex->tex.height0, level); + texdim = u_minify(tex->b.b.height0, level); } /* See TX_FILTER1_n.MACRO_SWITCH. */ @@ -664,22 +721,22 @@ unsigned r300_texture_get_stride(struct r300_screen* screen, return tex->stride_override; /* Check the level. */ - if (level > tex->tex.last_level) { + if (level > tex->b.b.last_level) { SCREEN_DBG(screen, DBG_TEX, "%s: level (%u) > last_level (%u)\n", - __FUNCTION__, level, tex->tex.last_level); + __FUNCTION__, level, tex->b.b.last_level); return 0; } - width = u_minify(tex->tex.width0, level); + width = u_minify(tex->b.b.width0, level); - if (r300_format_is_plain(tex->tex.format)) { + if (r300_format_is_plain(tex->b.b.format)) { tile_width = r300_texture_get_tile_size(tex, TILE_WIDTH, tex->mip_macrotile[level]); width = align(width, tile_width); - return util_format_get_stride(tex->tex.format, width); + return util_format_get_stride(tex->b.b.format, width); } else { - return align(util_format_get_stride(tex->tex.format, width), 32); + return align(util_format_get_stride(tex->b.b.format, width), 32); } } @@ -688,23 +745,49 @@ static unsigned r300_texture_get_nblocksy(struct r300_texture* tex, { unsigned height, tile_height; - height = u_minify(tex->tex.height0, level); + height = u_minify(tex->b.b.height0, level); - if (r300_format_is_plain(tex->tex.format)) { + if (r300_format_is_plain(tex->b.b.format)) { tile_height = r300_texture_get_tile_size(tex, TILE_HEIGHT, tex->mip_macrotile[level]); height = align(height, tile_height); + + /* This is needed for the kernel checker, unfortunately. */ + height = util_next_power_of_two(height); } - return util_format_get_nblocksy(tex->tex.format, height); + return util_format_get_nblocksy(tex->b.b.format, height); +} + +static void r300_texture_3d_fix_mipmapping(struct r300_screen *screen, + struct r300_texture *tex) +{ + /* The kernels <= 2.6.34-rc3 compute the size of mipmapped 3D textures + * incorrectly. This is a workaround to prevent CS from being rejected. */ + + unsigned i, size; + + if (screen->rws->get_value(screen->rws, R300_VID_TEX3D_MIP_BUG) && + tex->b.b.target == PIPE_TEXTURE_3D && + tex->b.b.last_level > 0) { + size = 0; + + for (i = 0; i <= tex->b.b.last_level; i++) { + size += r300_texture_get_stride(screen, tex, i) * + r300_texture_get_nblocksy(tex, i); + } + + size *= tex->b.b.depth0; + tex->size = size; + } } static void r300_setup_miptree(struct r300_screen* screen, struct r300_texture* tex) { - struct pipe_texture* base = &tex->tex; + struct pipe_resource* base = &tex->b.b; unsigned stride, size, layer_size, nblocksy, i; - boolean rv350_mode = screen->caps->family >= CHIP_FAMILY_RV350; + boolean rv350_mode = screen->caps.family >= CHIP_FAMILY_RV350; SCREEN_DBG(screen, DBG_TEX, "r300: Making miptree for texture, format %s\n", util_format_name(base->format)); @@ -741,23 +824,24 @@ static void r300_setup_miptree(struct r300_screen* screen, static void r300_setup_flags(struct r300_texture* tex) { - tex->is_npot = !util_is_power_of_two(tex->tex.width0) || - !util_is_power_of_two(tex->tex.height0); + tex->uses_pitch = !util_is_power_of_two(tex->b.b.width0) || + !util_is_power_of_two(tex->b.b.height0) || + tex->stride_override; } static void r300_setup_tiling(struct pipe_screen *screen, struct r300_texture *tex) { struct r300_winsys_screen *rws = (struct r300_winsys_screen *)screen->winsys; - enum pipe_format format = tex->tex.format; - boolean rv350_mode = r300_screen(screen)->caps->family >= CHIP_FAMILY_RV350; + enum pipe_format format = tex->b.b.format; + boolean rv350_mode = r300_screen(screen)->caps.family >= CHIP_FAMILY_RV350; if (!r300_format_is_plain(format)) { return; } - if (tex->tex.width0 == 1 || - tex->tex.height0 == 1) { + if (tex->b.b.width0 == 1 || + tex->b.b.height0 == 1) { return; } @@ -783,9 +867,72 @@ static void r300_setup_tiling(struct pipe_screen *screen, } } +static unsigned r300_texture_is_referenced(struct pipe_context *context, + struct pipe_resource *texture, + unsigned face, unsigned level) +{ + struct r300_context *r300 = r300_context(context); + struct r300_texture *rtex = (struct r300_texture *)texture; + + if (r300->rws->is_buffer_referenced(r300->rws, rtex->buffer)) + return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE; + + return PIPE_UNREFERENCED; +} + +static void r300_texture_destroy(struct pipe_screen *screen, + struct pipe_resource* texture) +{ + struct r300_texture* tex = (struct r300_texture*)texture; + struct r300_winsys_screen *rws = (struct r300_winsys_screen *)texture->screen->winsys; + + rws->buffer_reference(rws, &tex->buffer, NULL); + FREE(tex); +} + + + + +static boolean + r300_texture_get_handle(struct pipe_screen* screen, + struct pipe_resource *texture, + struct winsys_handle *whandle) +{ + struct r300_winsys_screen *rws = (struct r300_winsys_screen *)screen->winsys; + struct r300_texture* tex = (struct r300_texture*)texture; + unsigned stride; + + if (!tex) { + return FALSE; + } + + stride = r300_texture_get_stride(r300_screen(screen), tex, 0); + + rws->buffer_get_handle(rws, tex->buffer, stride, whandle); + + return TRUE; +} + + + +struct u_resource_vtbl r300_texture_vtbl = +{ + r300_texture_get_handle, /* get_handle */ + r300_texture_destroy, /* resource_destroy */ + r300_texture_is_referenced, /* is_resource_referenced */ + r300_texture_get_transfer, /* get_transfer */ + r300_texture_transfer_destroy, /* transfer_destroy */ + r300_texture_transfer_map, /* transfer_map */ + u_default_transfer_flush_region, /* transfer_flush_region */ + r300_texture_transfer_unmap, /* transfer_unmap */ + u_default_transfer_inline_write /* transfer_inline_write */ +}; + + + /* Create a new texture. */ -static struct pipe_texture* r300_texture_create(struct pipe_screen* screen, - const struct pipe_texture* template) +struct pipe_resource* r300_texture_create(struct pipe_screen* screen, + const struct pipe_resource* base) { struct r300_texture* tex = CALLOC_STRUCT(r300_texture); struct r300_screen* rscreen = r300_screen(screen); @@ -795,19 +942,23 @@ static struct pipe_texture* r300_texture_create(struct pipe_screen* screen, return NULL; } - tex->tex = *template; - pipe_reference_init(&tex->tex.reference, 1); - tex->tex.screen = screen; + tex->b.b = *base; + tex->b.vtbl = &r300_texture_vtbl; + pipe_reference_init(&tex->b.b.reference, 1); + tex->b.b.screen = screen; r300_setup_flags(tex); - if (!(template->tex_usage & R300_TEXTURE_USAGE_TRANSFER)) { + if (!(base->flags & R300_RESOURCE_FLAG_TRANSFER) && + !(base->bind & PIPE_BIND_SCANOUT)) { r300_setup_tiling(screen, tex); } r300_setup_miptree(rscreen, tex); - r300_setup_texture_state(rscreen, tex); + r300_texture_3d_fix_mipmapping(rscreen, tex); + r300_texture_setup_immutable_state(rscreen, tex); + r300_texture_setup_fb_state(rscreen, tex); tex->buffer = rws->buffer_create(rws, 2048, - PIPE_BUFFER_USAGE_PIXEL, + PIPE_BIND_SAMPLER_VIEW, /* XXX */ tex->size); rws->buffer_set_tiling(rws, tex->buffer, tex->pitch[0], @@ -819,26 +970,21 @@ static struct pipe_texture* r300_texture_create(struct pipe_screen* screen, return NULL; } - return (struct pipe_texture*)tex; + return (struct pipe_resource*)tex; } -static void r300_texture_destroy(struct pipe_texture* texture) -{ - struct r300_texture* tex = (struct r300_texture*)texture; - struct r300_winsys_screen *rws = (struct r300_winsys_screen *)texture->screen->winsys; - rws->buffer_reference(rws, &tex->buffer, NULL); - FREE(tex); -} -static struct pipe_surface* r300_get_tex_surface(struct pipe_screen* screen, - struct pipe_texture* texture, - unsigned face, - unsigned level, - unsigned zslice, - unsigned flags) +/* Not required to implement u_resource_vtbl, consider moving to another file: + */ +struct pipe_surface* r300_get_tex_surface(struct pipe_screen* screen, + struct pipe_resource* texture, + unsigned face, + unsigned level, + unsigned zslice, + unsigned flags) { - struct r300_texture* tex = (struct r300_texture*)texture; + struct r300_texture* tex = r300_texture(texture); struct pipe_surface* surface = CALLOC_STRUCT(pipe_surface); unsigned offset; @@ -846,7 +992,7 @@ static struct pipe_surface* r300_get_tex_surface(struct pipe_screen* screen, if (surface) { pipe_reference_init(&surface->reference, 1); - pipe_texture_reference(&surface->texture, texture); + pipe_resource_reference(&surface->texture, texture); surface->format = texture->format; surface->width = u_minify(texture->width0, level); surface->height = u_minify(texture->height0, level); @@ -861,23 +1007,25 @@ static struct pipe_surface* r300_get_tex_surface(struct pipe_screen* screen, return surface; } -static void r300_tex_surface_destroy(struct pipe_surface* s) +/* Not required to implement u_resource_vtbl, consider moving to another file: + */ +void r300_tex_surface_destroy(struct pipe_surface* s) { - pipe_texture_reference(&s->texture, NULL); + pipe_resource_reference(&s->texture, NULL); FREE(s); } - -static struct pipe_texture* - r300_texture_from_handle(struct pipe_screen* screen, - const struct pipe_texture* base, - struct winsys_handle *whandle) +struct pipe_resource* +r300_texture_from_handle(struct pipe_screen* screen, + const struct pipe_resource* base, + struct winsys_handle *whandle) { struct r300_winsys_screen *rws = (struct r300_winsys_screen*)screen->winsys; struct r300_screen* rscreen = r300_screen(screen); struct r300_winsys_buffer *buffer; struct r300_texture* tex; unsigned stride; + boolean override_zb_flags; /* Support only 2D textures without mipmaps */ if (base->target != PIPE_TEXTURE_2D || @@ -896,122 +1044,51 @@ static struct pipe_texture* return NULL; } - tex->tex = *base; - pipe_reference_init(&tex->tex.reference, 1); - tex->tex.screen = screen; + tex->b.b = *base; + tex->b.vtbl = &r300_texture_vtbl; + pipe_reference_init(&tex->b.b.reference, 1); + tex->b.b.screen = screen; tex->stride_override = stride; - tex->pitch[0] = stride / util_format_get_blocksize(base->format); - - r300_setup_flags(tex); - r300_setup_texture_state(rscreen, tex); /* one ref already taken */ tex->buffer = buffer; - return (struct pipe_texture*)tex; -} - -static boolean - r300_texture_get_handle(struct pipe_screen* screen, - struct pipe_texture *texture, - struct winsys_handle *whandle) -{ - struct r300_winsys_screen *rws = (struct r300_winsys_screen *)screen->winsys; - struct r300_texture* tex = (struct r300_texture*)texture; - unsigned stride; - - if (!tex) { - return FALSE; - } - - stride = r300_texture_get_stride(r300_screen(screen), tex, 0); - - rws->buffer_get_handle(rws, tex->buffer, stride, whandle); - - return TRUE; -} - -static struct pipe_video_surface * -r300_video_surface_create(struct pipe_screen *screen, - enum pipe_video_chroma_format chroma_format, - unsigned width, unsigned height) -{ - struct r300_video_surface *r300_vsfc; - struct pipe_texture template; - - assert(screen); - assert(width && height); - - r300_vsfc = CALLOC_STRUCT(r300_video_surface); - if (!r300_vsfc) - return NULL; - - pipe_reference_init(&r300_vsfc->base.reference, 1); - r300_vsfc->base.screen = screen; - r300_vsfc->base.chroma_format = chroma_format; - r300_vsfc->base.width = width; - r300_vsfc->base.height = height; - - memset(&template, 0, sizeof(struct pipe_texture)); - template.target = PIPE_TEXTURE_2D; - template.format = PIPE_FORMAT_B8G8R8X8_UNORM; - template.last_level = 0; - template.width0 = util_next_power_of_two(width); - template.height0 = util_next_power_of_two(height); - template.depth0 = 1; - template.tex_usage = PIPE_TEXTURE_USAGE_SAMPLER | - PIPE_TEXTURE_USAGE_RENDER_TARGET; - - r300_vsfc->tex = screen->texture_create(screen, &template); - if (!r300_vsfc->tex) - { - FREE(r300_vsfc); - return NULL; - } - - return &r300_vsfc->base; -} + rws->buffer_get_tiling(rws, buffer, &tex->microtile, &tex->macrotile); + r300_setup_flags(tex); -static void r300_video_surface_destroy(struct pipe_video_surface *vsfc) -{ - struct r300_video_surface *r300_vsfc = r300_video_surface(vsfc); - pipe_texture_reference(&r300_vsfc->tex, NULL); - FREE(r300_vsfc); -} + /* Enforce microtiled zbuffer. */ + override_zb_flags = util_format_is_depth_or_stencil(base->format) && + tex->microtile == R300_BUFFER_LINEAR; -void r300_init_screen_texture_functions(struct pipe_screen* screen) -{ - screen->texture_create = r300_texture_create; - screen->texture_from_handle = r300_texture_from_handle; - screen->texture_get_handle = r300_texture_get_handle; - screen->texture_destroy = r300_texture_destroy; - screen->get_tex_surface = r300_get_tex_surface; - screen->tex_surface_destroy = r300_tex_surface_destroy; - - screen->video_surface_create = r300_video_surface_create; - screen->video_surface_destroy= r300_video_surface_destroy; -} + if (override_zb_flags) { + switch (util_format_get_blocksize(base->format)) { + case 4: + tex->microtile = R300_BUFFER_TILED; + break; -boolean r300_get_texture_buffer(struct pipe_screen* screen, - struct pipe_texture* texture, - struct r300_winsys_buffer** buffer, - unsigned* stride) -{ - struct r300_texture* tex = (struct r300_texture*)texture; - struct r300_winsys_screen *rws = (struct r300_winsys_screen *)screen->winsys; - struct r300_winsys_buffer *buf; + case 2: + if (rws->get_value(rws, R300_VID_SQUARE_TILING_SUPPORT)) { + tex->microtile = R300_BUFFER_SQUARETILED; + break; + } + /* Pass through. */ - if (!tex) { - return FALSE; + default: + override_zb_flags = FALSE; + } } - rws->buffer_reference(rws, &buf, tex->buffer); - - if (stride) { - *stride = r300_texture_get_stride(r300_screen(screen), tex, 0); + r300_setup_miptree(rscreen, tex); + r300_texture_setup_immutable_state(rscreen, tex); + r300_texture_setup_fb_state(rscreen, tex); + + if (override_zb_flags) { + rws->buffer_set_tiling(rws, tex->buffer, + tex->pitch[0], + tex->microtile, + tex->macrotile); } - - *buffer = buf; - return TRUE; + return (struct pipe_resource*)tex; } + diff --git a/src/gallium/drivers/r300/r300_texture.h b/src/gallium/drivers/r300/r300_texture.h index 60c7fa8342..7b8b40551d 100644 --- a/src/gallium/drivers/r300/r300_texture.h +++ b/src/gallium/drivers/r300/r300_texture.h @@ -23,14 +23,14 @@ #ifndef R300_TEXTURE_H #define R300_TEXTURE_H -#include "pipe/p_video_state.h" #include "util/u_format.h" -#include "r300_reg.h" - struct r300_texture; -void r300_init_screen_texture_functions(struct pipe_screen* screen); +uint32_t r300_translate_texformat(enum pipe_format format, + const unsigned char *swizzle); + +uint32_t r500_tx_format_msb_bit(enum pipe_format format); unsigned r300_texture_get_stride(struct r300_screen* screen, struct r300_texture* tex, unsigned level); @@ -39,7 +39,7 @@ unsigned r300_texture_get_offset(struct r300_texture* tex, unsigned level, unsigned zslice, unsigned face); void r300_texture_reinterpret_format(struct pipe_screen *screen, - struct pipe_texture *tex, + struct pipe_resource *tex, enum pipe_format new_format); boolean r300_is_colorbuffer_format_supported(enum pipe_format format); @@ -48,23 +48,24 @@ boolean r300_is_zs_format_supported(enum pipe_format format); boolean r300_is_sampler_format_supported(enum pipe_format format); -struct r300_video_surface -{ - struct pipe_video_surface base; - struct pipe_texture *tex; -}; - -static INLINE struct r300_video_surface * -r300_video_surface(struct pipe_video_surface *pvs) -{ - return (struct r300_video_surface *)pvs; -} - -/* Used internally for texture_is_referenced() - */ -boolean r300_get_texture_buffer(struct pipe_screen* screen, - struct pipe_texture *texture, - struct r300_winsys_buffer** buffer, - unsigned* stride); + +struct pipe_resource* +r300_texture_from_handle(struct pipe_screen* screen, + const struct pipe_resource* base, + struct winsys_handle *whandle); + +struct pipe_resource* +r300_texture_create(struct pipe_screen* screen, + const struct pipe_resource* template); + + +struct pipe_surface* r300_get_tex_surface(struct pipe_screen* screen, + struct pipe_resource* texture, + unsigned face, + unsigned level, + unsigned zslice, + unsigned flags); + +void r300_tex_surface_destroy(struct pipe_surface* s); #endif /* R300_TEXTURE_H */ diff --git a/src/gallium/drivers/r300/r300_tgsi_to_rc.c b/src/gallium/drivers/r300/r300_tgsi_to_rc.c index 3b3802ee2b..21a1c45982 100644 --- a/src/gallium/drivers/r300/r300_tgsi_to_rc.c +++ b/src/gallium/drivers/r300/r300_tgsi_to_rc.c @@ -383,4 +383,3 @@ void r300_tgsi_to_rc(struct tgsi_to_rc * ttr, rc_calculate_inputs_outputs(ttr->compiler); } - diff --git a/src/gallium/drivers/r300/r300_transfer.c b/src/gallium/drivers/r300/r300_transfer.c index 987a040698..e4df750455 100644 --- a/src/gallium/drivers/r300/r300_transfer.c +++ b/src/gallium/drivers/r300/r300_transfer.c @@ -38,9 +38,6 @@ struct r300_transfer { /* Pipe context. */ struct pipe_context *ctx; - /* Parameters of get_tex_transfer. */ - unsigned x, y, level, zslice, face; - /* Offset from start of buffer. */ unsigned offset; @@ -48,7 +45,7 @@ struct r300_transfer { struct r300_texture *detiled_texture; /* Transfer and format flags. */ - unsigned buffer_usage, render_target_usage; + unsigned render_target_usage; }; /* Convenience cast wrapper. */ @@ -64,22 +61,22 @@ static void r300_copy_from_tiled_texture(struct pipe_context *ctx, { struct pipe_screen *screen = ctx->screen; struct pipe_transfer *transfer = (struct pipe_transfer*)r300transfer; - struct pipe_texture *tex = transfer->texture; + struct pipe_resource *tex = transfer->resource; struct pipe_surface *src, *dst; - src = screen->get_tex_surface(screen, tex, r300transfer->face, - r300transfer->level, r300transfer->zslice, - PIPE_BUFFER_USAGE_GPU_READ | - PIPE_BUFFER_USAGE_PIXEL); + src = screen->get_tex_surface(screen, tex, + transfer->sr.face, + transfer->sr.level, + transfer->box.z, + PIPE_BIND_BLIT_SOURCE); - dst = screen->get_tex_surface(screen, &r300transfer->detiled_texture->tex, + dst = screen->get_tex_surface(screen, &r300transfer->detiled_texture->b.b, 0, 0, 0, - PIPE_BUFFER_USAGE_GPU_WRITE | - PIPE_BUFFER_USAGE_PIXEL | - r300transfer->buffer_usage); + PIPE_BIND_BLIT_DESTINATION); - ctx->surface_copy(ctx, dst, 0, 0, src, r300transfer->x, r300transfer->y, - transfer->width, transfer->height); + ctx->surface_copy(ctx, dst, 0, 0, src, + transfer->box.x, transfer->box.y, + transfer->box.width, transfer->box.height); pipe_surface_reference(&src, NULL); pipe_surface_reference(&dst, NULL); @@ -91,26 +88,28 @@ static void r300_copy_into_tiled_texture(struct pipe_context *ctx, { struct pipe_screen *screen = ctx->screen; struct pipe_transfer *transfer = (struct pipe_transfer*)r300transfer; - struct pipe_texture *tex = transfer->texture; + struct pipe_resource *tex = transfer->resource; struct pipe_surface *src, *dst; - src = screen->get_tex_surface(screen, &r300transfer->detiled_texture->tex, + src = screen->get_tex_surface(screen, &r300transfer->detiled_texture->b.b, 0, 0, 0, - PIPE_BUFFER_USAGE_GPU_READ | - PIPE_BUFFER_USAGE_PIXEL); + PIPE_BIND_BLIT_SOURCE); - dst = screen->get_tex_surface(screen, tex, r300transfer->face, - r300transfer->level, r300transfer->zslice, - PIPE_BUFFER_USAGE_GPU_WRITE | - PIPE_BUFFER_USAGE_PIXEL); + dst = screen->get_tex_surface(screen, tex, + transfer->sr.face, + transfer->sr.level, + transfer->box.z, + PIPE_BIND_BLIT_DESTINATION); /* XXX this flush prevents the following DRM error from occuring: * [drm:radeon_cs_ioctl] *ERROR* Failed to parse relocation ! * Reproducible with perf/copytex. */ ctx->flush(ctx, 0, NULL); - ctx->surface_copy(ctx, dst, r300transfer->x, r300transfer->y, src, 0, 0, - transfer->width, transfer->height); + ctx->surface_copy(ctx, dst, + transfer->box.x, transfer->box.y, + src, 0, 0, + transfer->box.width, transfer->box.height); /* XXX this flush fixes a few piglit tests (e.g. glean/pixelFormats). */ ctx->flush(ctx, 0, NULL); @@ -119,72 +118,72 @@ static void r300_copy_into_tiled_texture(struct pipe_context *ctx, pipe_surface_reference(&dst, NULL); } -static struct pipe_transfer* -r300_get_tex_transfer(struct pipe_context *ctx, - struct pipe_texture *texture, - unsigned face, unsigned level, unsigned zslice, - enum pipe_transfer_usage usage, unsigned x, unsigned y, - unsigned w, unsigned h) +struct pipe_transfer* +r300_texture_get_transfer(struct pipe_context *ctx, + struct pipe_resource *texture, + struct pipe_subresource sr, + unsigned usage, + const struct pipe_box *box) { - struct r300_texture *tex = (struct r300_texture *)texture; + struct r300_texture *tex = r300_texture(texture); struct r300_screen *r300screen = r300_screen(ctx->screen); struct r300_transfer *trans; - struct pipe_texture template; + struct pipe_resource base; trans = CALLOC_STRUCT(r300_transfer); if (trans) { /* Initialize the transfer object. */ - pipe_texture_reference(&trans->transfer.texture, texture); + pipe_resource_reference(&trans->transfer.resource, texture); + trans->transfer.sr = sr; trans->transfer.usage = usage; - trans->transfer.width = w; - trans->transfer.height = h; + trans->transfer.box = *box; trans->ctx = ctx; - trans->x = x; - trans->y = y; - trans->level = level; - trans->zslice = zslice; - trans->face = face; /* If the texture is tiled, we must create a temporary detiled texture * for this transfer. */ if (tex->microtile || tex->macrotile) { - trans->buffer_usage = pipe_transfer_buffer_flags(&trans->transfer); trans->render_target_usage = util_format_is_depth_or_stencil(texture->format) ? - PIPE_TEXTURE_USAGE_DEPTH_STENCIL : - PIPE_TEXTURE_USAGE_RENDER_TARGET; - - template.target = PIPE_TEXTURE_2D; - template.format = texture->format; - template.width0 = w; - template.height0 = h; - template.depth0 = 0; - template.last_level = 0; - template.nr_samples = 0; - template.tex_usage = PIPE_TEXTURE_USAGE_DYNAMIC | - R300_TEXTURE_USAGE_TRANSFER; + PIPE_BIND_DEPTH_STENCIL : + PIPE_BIND_RENDER_TARGET; + + base.target = PIPE_TEXTURE_2D; + base.format = texture->format; + base.width0 = box->width; + base.height0 = box->height; + base.depth0 = 0; + base.last_level = 0; + base.nr_samples = 0; + base._usage = PIPE_USAGE_DYNAMIC; + base.bind = 0; + base.flags = R300_RESOURCE_FLAG_TRANSFER; /* For texture reading, the temporary (detiled) texture is used as * a render target when blitting from a tiled texture. */ if (usage & PIPE_TRANSFER_READ) { - template.tex_usage |= trans->render_target_usage; + base.bind |= trans->render_target_usage; } /* For texture writing, the temporary texture is used as a sampler * when blitting into a tiled texture. */ if (usage & PIPE_TRANSFER_WRITE) { - template.tex_usage |= PIPE_TEXTURE_USAGE_SAMPLER; + base.bind |= PIPE_BIND_SAMPLER_VIEW; } /* Create the temporary texture. */ - trans->detiled_texture = (struct r300_texture*) - ctx->screen->texture_create(ctx->screen, - &template); + trans->detiled_texture = r300_texture( + ctx->screen->resource_create(ctx->screen, + &base)); assert(!trans->detiled_texture->microtile && !trans->detiled_texture->macrotile); /* Set the stride. - * Parameters x, y, level, zslice, and face remain zero. */ + * + * Even though we are using an internal texture for this, + * the transfer sr, box and usage parameters still reflect + * the arguments received to get_transfer. We just do the + * right thing internally. + */ trans->transfer.stride = r300_texture_get_stride(r300screen, trans->detiled_texture, 0); @@ -194,21 +193,16 @@ r300_get_tex_transfer(struct pipe_context *ctx, r300_copy_from_tiled_texture(ctx, trans); } } else { - trans->transfer.x = x; - trans->transfer.y = y; trans->transfer.stride = - r300_texture_get_stride(r300screen, tex, level); - trans->transfer.level = level; - trans->transfer.zslice = zslice; - trans->transfer.face = face; - trans->offset = r300_texture_get_offset(tex, level, zslice, face); + r300_texture_get_stride(r300screen, tex, sr.level); + trans->offset = r300_texture_get_offset(tex, sr.level, box->z, sr.face); } } return &trans->transfer; } -static void r300_tex_transfer_destroy(struct pipe_context *ctx, - struct pipe_transfer *trans) +void r300_texture_transfer_destroy(struct pipe_context *ctx, + struct pipe_transfer *trans) { struct r300_transfer *r300transfer = r300_transfer(trans); @@ -217,49 +211,49 @@ static void r300_tex_transfer_destroy(struct pipe_context *ctx, r300_copy_into_tiled_texture(r300transfer->ctx, r300transfer); } - pipe_texture_reference( - (struct pipe_texture**)&r300transfer->detiled_texture, NULL); + pipe_resource_reference( + (struct pipe_resource**)&r300transfer->detiled_texture, NULL); } - pipe_texture_reference(&trans->texture, NULL); + pipe_resource_reference(&trans->resource, NULL); FREE(trans); } -static void* r300_transfer_map(struct pipe_context *ctx, - struct pipe_transfer *transfer) +void* r300_texture_transfer_map(struct pipe_context *ctx, + struct pipe_transfer *transfer) { struct r300_winsys_screen *rws = (struct r300_winsys_screen *)ctx->winsys; struct r300_transfer *r300transfer = r300_transfer(transfer); - struct r300_texture *tex = (struct r300_texture*)transfer->texture; + struct r300_texture *tex = r300_texture(transfer->resource); char *map; - enum pipe_format format = tex->tex.format; + enum pipe_format format = tex->b.b.format; if (r300transfer->detiled_texture) { /* The detiled texture is of the same size as the region being mapped * (no offset needed). */ return rws->buffer_map(rws, r300transfer->detiled_texture->buffer, - pipe_transfer_buffer_flags(transfer)); + transfer->usage); } else { /* Tiling is disabled. */ map = rws->buffer_map(rws, tex->buffer, - pipe_transfer_buffer_flags(transfer)); + transfer->usage); if (!map) { return NULL; } return map + r300_transfer(transfer)->offset + - transfer->y / util_format_get_blockheight(format) * transfer->stride + - transfer->x / util_format_get_blockwidth(format) * util_format_get_blocksize(format); + transfer->box.y / util_format_get_blockheight(format) * transfer->stride + + transfer->box.x / util_format_get_blockwidth(format) * util_format_get_blocksize(format); } } -static void r300_transfer_unmap(struct pipe_context *ctx, - struct pipe_transfer *transfer) +void r300_texture_transfer_unmap(struct pipe_context *ctx, + struct pipe_transfer *transfer) { struct r300_winsys_screen *rws = (struct r300_winsys_screen *)ctx->winsys; struct r300_transfer *r300transfer = r300_transfer(transfer); - struct r300_texture *tex = (struct r300_texture*)transfer->texture; + struct r300_texture *tex = r300_texture(transfer->resource); if (r300transfer->detiled_texture) { rws->buffer_unmap(rws, r300transfer->detiled_texture->buffer); @@ -268,13 +262,3 @@ static void r300_transfer_unmap(struct pipe_context *ctx, } } - -void r300_init_transfer_functions( struct r300_context *r300ctx ) -{ - struct pipe_context *ctx = &r300ctx->context; - - ctx->get_tex_transfer = r300_get_tex_transfer; - ctx->tex_transfer_destroy = r300_tex_transfer_destroy; - ctx->transfer_map = r300_transfer_map; - ctx->transfer_unmap = r300_transfer_unmap; -} diff --git a/src/gallium/drivers/r300/r300_transfer.h b/src/gallium/drivers/r300/r300_transfer.h index 79baf6d048..d72e54e5ed 100644 --- a/src/gallium/drivers/r300/r300_transfer.h +++ b/src/gallium/drivers/r300/r300_transfer.h @@ -28,6 +28,24 @@ struct r300_context; -void r300_init_transfer_functions(struct r300_context *r300ctx); +struct pipe_transfer* +r300_texture_get_transfer(struct pipe_context *ctx, + struct pipe_resource *texture, + struct pipe_subresource sr, + unsigned usage, + const struct pipe_box *box); + +void +r300_texture_transfer_destroy(struct pipe_context *ctx, + struct pipe_transfer *trans); + +void* +r300_texture_transfer_map(struct pipe_context *ctx, + struct pipe_transfer *transfer); + +void +r300_texture_transfer_unmap(struct pipe_context *ctx, + struct pipe_transfer *transfer); + #endif diff --git a/src/gallium/drivers/r300/r300_vs.c b/src/gallium/drivers/r300/r300_vs.c index d5690caa68..bfab9c3b01 100644 --- a/src/gallium/drivers/r300/r300_vs.c +++ b/src/gallium/drivers/r300/r300_vs.c @@ -31,6 +31,7 @@ #include "tgsi/tgsi_dump.h" #include "tgsi/tgsi_parse.h" +#include "tgsi/tgsi_ureg.h" #include "radeon_compiler.h" @@ -80,11 +81,12 @@ static void r300_shader_read_vs_outputs( case TGSI_SEMANTIC_EDGEFLAG: assert(index == 0); - fprintf(stderr, "r300 VP: cannot handle edgeflag output\n"); - assert(0); + fprintf(stderr, "r300 VP: cannot handle edgeflag output.\n"); break; + default: - assert(0); + fprintf(stderr, "r300 VP: unknown vertex output semantic: %i.\n", + info->output_semantic_name[i]); } } @@ -148,35 +150,32 @@ static void r300_init_vs_output_mapping(struct r300_vertex_shader* vs) /* Texture coordinates. */ gen_count = 0; - for (i = 0; i < ATTR_GENERIC_COUNT; i++) { + for (i = 0; i < ATTR_GENERIC_COUNT && gen_count < 8; i++) { if (vs_outputs->generic[i] != ATTR_UNUSED) { vap_out->vap_vsm_vtx_assm |= (R300_INPUT_CNTL_TC0 << gen_count); vap_out->vap_out_vtx_fmt[1] |= (4 << (3 * gen_count)); - assert(tabi < 16); stream_loc[tabi++] = 6 + gen_count; gen_count++; } } /* Fog coordinates. */ - if (vs_outputs->fog != ATTR_UNUSED) { + if (gen_count < 8 && vs_outputs->fog != ATTR_UNUSED) { vap_out->vap_vsm_vtx_assm |= (R300_INPUT_CNTL_TC0 << gen_count); vap_out->vap_out_vtx_fmt[1] |= (4 << (3 * gen_count)); - assert(tabi < 16); stream_loc[tabi++] = 6 + gen_count; gen_count++; } - /* XXX magic */ - assert(gen_count <= 8); - /* WPOS. */ - vs->wpos_tex_output = gen_count; - - assert(tabi < 16); - stream_loc[tabi++] = 6 + gen_count; + if (gen_count < 8) { + vs->wpos_tex_output = gen_count; + stream_loc[tabi++] = 6 + gen_count; + } else { + vs_outputs->wpos = ATTR_UNUSED; + } for (; tabi < 16;) { stream_loc[tabi++] = -1; @@ -252,24 +251,43 @@ static void set_vertex_inputs_outputs(struct r300_vertex_program_compiler * c) } } -void r300_vertex_shader_common_init(struct r300_vertex_shader *vs, - const struct pipe_shader_state *shader) +static void r300_dummy_vertex_shader( + struct r300_context* r300, + struct r300_vertex_shader* shader) { - /* Copy state directly into shader. */ - vs->state = *shader; - vs->state.tokens = tgsi_dup_tokens(shader->tokens); - tgsi_scan_shader(shader->tokens, &vs->info); + struct pipe_shader_state state; + struct ureg_program *ureg; + struct ureg_dst dst; + struct ureg_src imm; - r300_shader_read_vs_outputs(&vs->info, &vs->outputs); - r300_init_vs_output_mapping(vs); + /* Make a simple vertex shader which outputs (0, 0, 0, 1), + * effectively rendering nothing. */ + ureg = ureg_create(TGSI_PROCESSOR_VERTEX); + dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0); + imm = ureg_imm4f(ureg, 0, 0, 0, 1); + + ureg_MOV(ureg, dst, imm); + ureg_END(ureg); + + state.tokens = ureg_finalize(ureg); + + shader->dummy = TRUE; + r300_translate_vertex_shader(r300, shader, state.tokens); + + ureg_destroy(ureg); } void r300_translate_vertex_shader(struct r300_context* r300, - struct r300_vertex_shader* vs) + struct r300_vertex_shader* vs, + const struct tgsi_token *tokens) { 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); + r300_init_vs_output_mapping(vs); + /* Setup the compiler */ rc_init(&compiler.Base); @@ -279,7 +297,7 @@ void r300_translate_vertex_shader(struct r300_context* r300, if (compiler.Base.Debug) { debug_printf("r300: Initial vertex program\n"); - tgsi_dump(vs->state.tokens, 0); + tgsi_dump(tokens, 0); } /* Translate TGSI to our internal representation */ @@ -287,22 +305,41 @@ void r300_translate_vertex_shader(struct r300_context* r300, ttr.info = &vs->info; ttr.use_half_swizzles = FALSE; - r300_tgsi_to_rc(&ttr, vs->state.tokens); + r300_tgsi_to_rc(&ttr, tokens); + + compiler.RequiredOutputs = + ~(~0 << (vs->info.num_outputs + + (vs->outputs.wpos != ATTR_UNUSED ? 1 : 0))); - compiler.RequiredOutputs = ~(~0 << (vs->info.num_outputs+1)); compiler.SetHwInputOutput = &set_vertex_inputs_outputs; /* Insert the WPOS output. */ - rc_copy_output(&compiler.Base, 0, vs->outputs.wpos); + if (vs->outputs.wpos != ATTR_UNUSED) { + rc_copy_output(&compiler.Base, 0, vs->outputs.wpos); + } /* Invoke the compiler */ r3xx_compile_vertex_program(&compiler); if (compiler.Base.Error) { /* XXX We should fallback using Draw. */ - fprintf(stderr, "r300 VP: Compiler error:\n%s", compiler.Base.ErrorMsg); - abort(); + fprintf(stderr, "r300 VP: Compiler error:\n%sUsing a dummy shader" + " instead.\n", compiler.Base.ErrorMsg); + + if (vs->dummy) { + fprintf(stderr, "r300 VP: Cannot compile the dummy shader! " + "Giving up...\n"); + abort(); + } + + rc_destroy(&compiler.Base); + r300_dummy_vertex_shader(r300, vs); + return; } + /* Initialize numbers of constants for each type. */ + vs->externals_count = ttr.immediate_offset; + vs->immediates_count = vs->code.constants.Count - vs->externals_count; + /* And, finally... */ rc_destroy(&compiler.Base); } @@ -314,13 +351,15 @@ boolean r300_vertex_shader_setup_wpos(struct r300_context* r300) int tex_output = vs->wpos_tex_output; uint32_t tex_fmt = R300_INPUT_CNTL_TC0 << tex_output; - if (r300->fs->inputs.wpos != ATTR_UNUSED) { + if (vs->outputs.wpos == ATTR_UNUSED) { + return FALSE; + } + + if (r300_fs(r300)->shader->inputs.wpos != ATTR_UNUSED) { /* Enable WPOS in VAP. */ if (!(vap_out->vap_vsm_vtx_assm & tex_fmt)) { vap_out->vap_vsm_vtx_assm |= tex_fmt; vap_out->vap_out_vtx_fmt[1] |= (4 << (3 * tex_output)); - - assert(tex_output < 8); return TRUE; } } else { diff --git a/src/gallium/drivers/r300/r300_vs.h b/src/gallium/drivers/r300/r300_vs.h index f6f0b86b68..56bcc3b70b 100644 --- a/src/gallium/drivers/r300/r300_vs.h +++ b/src/gallium/drivers/r300/r300_vs.h @@ -41,6 +41,14 @@ struct r300_vertex_shader { struct r300_shader_semantics outputs; struct r300_vap_output_state vap_out; + /* Whether the shader was replaced by a dummy one due to a shader + * compilation failure. */ + boolean dummy; + + /* Numbers of constants for each type. */ + unsigned externals_count; + unsigned immediates_count; + /* Stream locations for SWTCL or if TCL is bypassed. */ int stream_loc_notcl[16]; @@ -55,11 +63,9 @@ struct r300_vertex_shader { void *draw_vs; }; -void r300_vertex_shader_common_init(struct r300_vertex_shader *vs, - const struct pipe_shader_state *shader); - void r300_translate_vertex_shader(struct r300_context* r300, - struct r300_vertex_shader* vs); + struct r300_vertex_shader* vs, + const struct tgsi_token *tokens); /* Return TRUE if VAP (hwfmt) needs to be re-emitted. */ boolean r300_vertex_shader_setup_wpos(struct r300_context* r300); diff --git a/src/gallium/drivers/r300/r300_winsys.h b/src/gallium/drivers/r300/r300_winsys.h index acfa5dbeb9..5ac997c868 100644 --- a/src/gallium/drivers/r300/r300_winsys.h +++ b/src/gallium/drivers/r300/r300_winsys.h @@ -39,17 +39,19 @@ struct pipe_screen* r300_create_screen(struct r300_winsys_screen *rws); struct r300_winsys_buffer; +/* XXX: this is just a bandaid on larger problems in + * r300_screen_buffer.h which doesn't seem to be fully ported to + * gallium-resources. + */ +#define R300_BIND_OQBO (1<<21) -boolean r300_get_texture_buffer(struct pipe_screen* screen, - struct pipe_texture* texture, - struct r300_winsys_buffer** buffer, - unsigned *stride); enum r300_value_id { R300_VID_PCI_ID, R300_VID_GB_PIPES, R300_VID_Z_PIPES, - R300_VID_SQUARE_TILING_SUPPORT + R300_VID_SQUARE_TILING_SUPPORT, + R300_VID_TEX3D_MIP_BUG, }; struct r300_winsys_screen { @@ -100,7 +102,7 @@ struct r300_winsys_screen { unsigned offset, unsigned length); - /* Add a pipe_buffer to the list of buffer objects to validate. */ + /* Add a pipe_resource to the list of buffer objects to validate. */ boolean (*add_buffer)(struct r300_winsys_screen *winsys, struct r300_winsys_buffer *buf, uint32_t rd, @@ -146,6 +148,11 @@ struct r300_winsys_screen { void (*reset_bos)(struct r300_winsys_screen *winsys); + void (*buffer_get_tiling)(struct r300_winsys_screen *winsys, + struct r300_winsys_buffer *buffer, + enum r300_buffer_tiling *microtiled, + enum r300_buffer_tiling *macrotiled); + void (*buffer_set_tiling)(struct r300_winsys_screen *winsys, struct r300_winsys_buffer *buffer, uint32_t pitch, |