diff options
author | Christian König <[email protected]> | 2010-10-12 23:05:25 +0200 |
---|---|---|
committer | Christian König <[email protected]> | 2010-10-12 23:07:29 +0200 |
commit | 695cc370a280a637f411f5ff3877b3fd1c05e424 (patch) | |
tree | 69ae2a8fbecfa553faba59274688ffe11ee1a612 /src/gallium/drivers/softpipe | |
parent | f3e34ba6fba76870b1c91a27adb706d1b87aeec8 (diff) | |
parent | 48156b87bc9d3e09ec34372d69504a787332ea0b (diff) |
Merge branch 'master' of ssh://git.freedesktop.org/git/mesa/mesa into pipe-video
Conflicts:
configure.ac
src/gallium/drivers/nvfx/Makefile
src/gallium/include/pipe/p_defines.h
src/gallium/include/pipe/p_screen.h
src/gallium/include/state_tracker/dri1_api.h
src/gallium/include/state_tracker/drm_api.h
src/gallium/winsys/nouveau/drm/nouveau_drm_api.c
Diffstat (limited to 'src/gallium/drivers/softpipe')
29 files changed, 1344 insertions, 776 deletions
diff --git a/src/gallium/drivers/softpipe/Makefile b/src/gallium/drivers/softpipe/Makefile index 3111c49a2c2..8876bd16398 100644 --- a/src/gallium/drivers/softpipe/Makefile +++ b/src/gallium/drivers/softpipe/Makefile @@ -23,8 +23,9 @@ C_SOURCES = \ sp_state_blend.c \ sp_state_clip.c \ sp_state_derived.c \ - sp_state_fs.c \ sp_state_sampler.c \ + sp_state_shader.c \ + sp_state_so.c \ sp_state_rasterizer.c \ sp_state_surface.c \ sp_state_vertex.c \ diff --git a/src/gallium/drivers/softpipe/SConscript b/src/gallium/drivers/softpipe/SConscript index c51f449c638..dea7f885e0d 100644 --- a/src/gallium/drivers/softpipe/SConscript +++ b/src/gallium/drivers/softpipe/SConscript @@ -24,9 +24,10 @@ softpipe = env.ConvenienceLibrary( 'sp_state_blend.c', 'sp_state_clip.c', 'sp_state_derived.c', - 'sp_state_fs.c', 'sp_state_rasterizer.c', 'sp_state_sampler.c', + 'sp_state_shader.c', + 'sp_state_so.c', 'sp_state_surface.c', 'sp_state_vertex.c', 'sp_surface.c', diff --git a/src/gallium/drivers/softpipe/sp_context.c b/src/gallium/drivers/softpipe/sp_context.c index f6e2b80d46e..b5d30bc6fc9 100644 --- a/src/gallium/drivers/softpipe/sp_context.c +++ b/src/gallium/drivers/softpipe/sp_context.c @@ -36,6 +36,7 @@ #include "util/u_math.h" #include "util/u_memory.h" #include "util/u_inlines.h" +#include "tgsi/tgsi_exec.h" #include "sp_clear.h" #include "sp_context.h" #include "sp_flush.h" @@ -113,6 +114,11 @@ softpipe_destroy( struct pipe_context *pipe ) pipe_sampler_view_reference(&softpipe->vertex_sampler_views[i], NULL); } + for (i = 0; i < PIPE_MAX_GEOMETRY_SAMPLERS; i++) { + sp_destroy_tex_tile_cache(softpipe->geometry_tex_cache[i]); + pipe_sampler_view_reference(&softpipe->geometry_sampler_views[i], NULL); + } + for (i = 0; i < PIPE_SHADER_TYPES; i++) { uint j; @@ -123,6 +129,8 @@ softpipe_destroy( struct pipe_context *pipe ) } } + tgsi_exec_machine_destroy(softpipe->fs_machine); + FREE( softpipe ); } @@ -171,7 +179,12 @@ softpipe_is_resource_referenced( struct pipe_context *pipe, softpipe->vertex_tex_cache[i]->texture == texture) return PIPE_REFERENCED_FOR_READ; } - + for (i = 0; i < PIPE_MAX_GEOMETRY_SAMPLERS; i++) { + if (softpipe->geometry_tex_cache[i] && + softpipe->geometry_tex_cache[i]->texture == texture) + return PIPE_REFERENCED_FOR_READ; + } + return PIPE_UNREFERENCED; } @@ -215,68 +228,26 @@ softpipe_create_context( struct pipe_screen *screen, softpipe->pipe.priv = priv; /* state setters */ - softpipe->pipe.create_blend_state = softpipe_create_blend_state; - softpipe->pipe.bind_blend_state = softpipe_bind_blend_state; - softpipe->pipe.delete_blend_state = softpipe_delete_blend_state; - - softpipe->pipe.create_sampler_state = softpipe_create_sampler_state; - softpipe->pipe.bind_fragment_sampler_states = softpipe_bind_sampler_states; - softpipe->pipe.bind_vertex_sampler_states = softpipe_bind_vertex_sampler_states; - softpipe->pipe.delete_sampler_state = softpipe_delete_sampler_state; - - softpipe->pipe.create_depth_stencil_alpha_state = softpipe_create_depth_stencil_state; - softpipe->pipe.bind_depth_stencil_alpha_state = softpipe_bind_depth_stencil_state; - softpipe->pipe.delete_depth_stencil_alpha_state = softpipe_delete_depth_stencil_state; - - softpipe->pipe.create_rasterizer_state = softpipe_create_rasterizer_state; - softpipe->pipe.bind_rasterizer_state = softpipe_bind_rasterizer_state; - softpipe->pipe.delete_rasterizer_state = softpipe_delete_rasterizer_state; - - softpipe->pipe.create_fs_state = softpipe_create_fs_state; - softpipe->pipe.bind_fs_state = softpipe_bind_fs_state; - softpipe->pipe.delete_fs_state = softpipe_delete_fs_state; - - softpipe->pipe.create_vs_state = softpipe_create_vs_state; - softpipe->pipe.bind_vs_state = softpipe_bind_vs_state; - softpipe->pipe.delete_vs_state = softpipe_delete_vs_state; - - softpipe->pipe.create_gs_state = softpipe_create_gs_state; - softpipe->pipe.bind_gs_state = softpipe_bind_gs_state; - softpipe->pipe.delete_gs_state = softpipe_delete_gs_state; - - softpipe->pipe.create_vertex_elements_state = softpipe_create_vertex_elements_state; - softpipe->pipe.bind_vertex_elements_state = softpipe_bind_vertex_elements_state; - softpipe->pipe.delete_vertex_elements_state = softpipe_delete_vertex_elements_state; - - softpipe->pipe.set_blend_color = softpipe_set_blend_color; - softpipe->pipe.set_stencil_ref = softpipe_set_stencil_ref; - softpipe->pipe.set_clip_state = softpipe_set_clip_state; - softpipe->pipe.set_constant_buffer = softpipe_set_constant_buffer; + softpipe_init_blend_funcs(&softpipe->pipe); + softpipe_init_clip_funcs(&softpipe->pipe); + softpipe_init_query_funcs( softpipe ); + softpipe_init_rasterizer_funcs(&softpipe->pipe); + softpipe_init_sampler_funcs(&softpipe->pipe); + softpipe_init_shader_funcs(&softpipe->pipe); + softpipe_init_streamout_funcs(&softpipe->pipe); + softpipe_init_texture_funcs( &softpipe->pipe ); + softpipe_init_vertex_funcs(&softpipe->pipe); + softpipe->pipe.set_framebuffer_state = softpipe_set_framebuffer_state; - softpipe->pipe.set_polygon_stipple = softpipe_set_polygon_stipple; - softpipe->pipe.set_scissor_state = softpipe_set_scissor_state; - softpipe->pipe.set_fragment_sampler_views = softpipe_set_sampler_views; - softpipe->pipe.set_vertex_sampler_views = softpipe_set_vertex_sampler_views; - softpipe->pipe.create_sampler_view = softpipe_create_sampler_view; - softpipe->pipe.sampler_view_destroy = softpipe_sampler_view_destroy; - softpipe->pipe.set_viewport_state = softpipe_set_viewport_state; - - softpipe->pipe.set_vertex_buffers = softpipe_set_vertex_buffers; - - softpipe->pipe.draw_arrays = softpipe_draw_arrays; - softpipe->pipe.draw_elements = softpipe_draw_elements; - softpipe->pipe.draw_range_elements = softpipe_draw_range_elements; - softpipe->pipe.draw_arrays_instanced = softpipe_draw_arrays_instanced; - softpipe->pipe.draw_elements_instanced = softpipe_draw_elements_instanced; + + softpipe->pipe.draw_vbo = softpipe_draw_vbo; + softpipe->pipe.draw_stream_output = softpipe_draw_stream_output; softpipe->pipe.clear = softpipe_clear; softpipe->pipe.flush = softpipe_flush; softpipe->pipe.is_resource_referenced = softpipe_is_resource_referenced; - softpipe_init_query_funcs( softpipe ); - softpipe_init_texture_funcs( &softpipe->pipe ); - softpipe->pipe.render_condition = softpipe_render_condition; /* @@ -292,6 +263,11 @@ softpipe_create_context( struct pipe_screen *screen, for (i = 0; i < PIPE_MAX_VERTEX_SAMPLERS; i++) { softpipe->vertex_tex_cache[i] = sp_create_tex_tile_cache( &softpipe->pipe ); } + for (i = 0; i < PIPE_MAX_GEOMETRY_SAMPLERS; i++) { + softpipe->geometry_tex_cache[i] = sp_create_tex_tile_cache( &softpipe->pipe ); + } + + softpipe->fs_machine = tgsi_exec_machine_create(); /* setup quad rendering stages */ softpipe->quad.shade = sp_quad_shade_stage(softpipe); @@ -308,10 +284,17 @@ softpipe_create_context( struct pipe_screen *screen, goto fail; draw_texture_samplers(softpipe->draw, + PIPE_SHADER_VERTEX, PIPE_MAX_VERTEX_SAMPLERS, (struct tgsi_sampler **) softpipe->tgsi.vert_samplers_list); + draw_texture_samplers(softpipe->draw, + PIPE_SHADER_GEOMETRY, + PIPE_MAX_GEOMETRY_SAMPLERS, + (struct tgsi_sampler **) + softpipe->tgsi.geom_samplers_list); + if (debug_get_bool_option( "SP_NO_RAST", FALSE )) softpipe->no_rast = TRUE; diff --git a/src/gallium/drivers/softpipe/sp_context.h b/src/gallium/drivers/softpipe/sp_context.h index 92607874b60..9361a3df09e 100644 --- a/src/gallium/drivers/softpipe/sp_context.h +++ b/src/gallium/drivers/softpipe/sp_context.h @@ -50,6 +50,7 @@ struct softpipe_tex_tile_cache; struct sp_fragment_shader; struct sp_vertex_shader; struct sp_velems_state; +struct sp_so_state; struct softpipe_context { @@ -59,12 +60,14 @@ struct softpipe_context { struct pipe_blend_state *blend; struct pipe_sampler_state *sampler[PIPE_MAX_SAMPLERS]; struct pipe_sampler_state *vertex_samplers[PIPE_MAX_VERTEX_SAMPLERS]; + struct pipe_sampler_state *geometry_samplers[PIPE_MAX_GEOMETRY_SAMPLERS]; struct pipe_depth_stencil_alpha_state *depth_stencil; struct pipe_rasterizer_state *rasterizer; struct sp_fragment_shader *fs; struct sp_vertex_shader *vs; struct sp_geometry_shader *gs; struct sp_velems_state *velems; + struct sp_so_state *so; /** Other rendering state */ struct pipe_blend_color blend_color; @@ -76,13 +79,24 @@ struct softpipe_context { struct pipe_scissor_state scissor; struct pipe_sampler_view *sampler_views[PIPE_MAX_SAMPLERS]; struct pipe_sampler_view *vertex_sampler_views[PIPE_MAX_VERTEX_SAMPLERS]; + struct pipe_sampler_view *geometry_sampler_views[PIPE_MAX_GEOMETRY_SAMPLERS]; struct pipe_viewport_state viewport; struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS]; + struct pipe_index_buffer index_buffer; + struct { + struct softpipe_resource *buffer[PIPE_MAX_SO_BUFFERS]; + int offset[PIPE_MAX_SO_BUFFERS]; + int so_count[PIPE_MAX_SO_BUFFERS]; + int num_buffers; + } so_target; + struct pipe_query_data_so_statistics so_stats; unsigned num_samplers; unsigned num_sampler_views; unsigned num_vertex_samplers; unsigned num_vertex_sampler_views; + unsigned num_geometry_samplers; + unsigned num_geometry_sampler_views; unsigned num_vertex_buffers; unsigned dirty; /**< Mask of SP_NEW_x flags */ @@ -98,6 +112,7 @@ struct softpipe_context { /** Mapped constant buffers */ const void *mapped_constants[PIPE_SHADER_TYPES][PIPE_MAX_CONSTANT_BUFFERS]; + unsigned const_buffer_size[PIPE_SHADER_TYPES][PIPE_MAX_CONSTANT_BUFFERS]; /** Vertex format */ struct vertex_info vertex_info; @@ -109,6 +124,9 @@ struct softpipe_context { /** The reduced version of the primitive supplied by the state tracker */ unsigned reduced_api_prim; + /** Derived information about which winding orders to cull */ + unsigned cull_mode; + /** * The reduced primitive after unfilled triangles, wide-line decomposition, * etc, are taken into account. This is the primitive type that's actually @@ -136,10 +154,13 @@ struct softpipe_context { /** TGSI exec things */ struct { + struct sp_sampler_varient *geom_samplers_list[PIPE_MAX_GEOMETRY_SAMPLERS]; struct sp_sampler_varient *vert_samplers_list[PIPE_MAX_VERTEX_SAMPLERS]; struct sp_sampler_varient *frag_samplers_list[PIPE_MAX_SAMPLERS]; } tgsi; + struct tgsi_exec_machine *fs_machine; + /** The primitive drawing context */ struct draw_context *draw; @@ -155,6 +176,7 @@ struct softpipe_context { unsigned tex_timestamp; struct softpipe_tex_tile_cache *tex_cache[PIPE_MAX_SAMPLERS]; struct softpipe_tex_tile_cache *vertex_tex_cache[PIPE_MAX_VERTEX_SAMPLERS]; + struct softpipe_tex_tile_cache *geometry_tex_cache[PIPE_MAX_GEOMETRY_SAMPLERS]; unsigned use_sse : 1; unsigned dump_fs : 1; diff --git a/src/gallium/drivers/softpipe/sp_draw_arrays.c b/src/gallium/drivers/softpipe/sp_draw_arrays.c index b30036e2303..01b4ca985d0 100644 --- a/src/gallium/drivers/softpipe/sp_draw_arrays.c +++ b/src/gallium/drivers/softpipe/sp_draw_arrays.c @@ -47,152 +47,79 @@ +void +softpipe_draw_stream_output(struct pipe_context *pipe, unsigned mode) +{ + struct softpipe_context *sp = softpipe_context(pipe); + struct draw_context *draw = sp->draw; + const unsigned start = 0; + const unsigned count = sp->so_target.so_count[0]; + void *buf = sp->so_target.buffer[0]->data; + int offset = sp->so_target.offset[0]; -/** - * Draw vertex arrays, with optional indexing. - * Basically, map the vertex buffers (and drawing surfaces), then hand off - * the drawing to the 'draw' module. - */ -static void -softpipe_draw_range_elements_instanced(struct pipe_context *pipe, - struct pipe_resource *indexBuffer, - unsigned indexSize, - int indexBias, - unsigned minIndex, - unsigned maxIndex, - unsigned mode, - unsigned start, - unsigned count, - unsigned startInstance, - unsigned instanceCount); + if (!softpipe_check_render_cond(sp) || + sp->so_target.num_buffers != 1) + return; + sp->reduced_api_prim = u_reduced_prim(mode); -void -softpipe_draw_arrays(struct pipe_context *pipe, unsigned mode, - unsigned start, unsigned count) -{ - softpipe_draw_range_elements_instanced(pipe, - NULL, - 0, - 0, - 0, - 0xffffffff, - mode, - start, - count, - 0, - 1); -} + if (sp->dirty) { + softpipe_update_derived(sp); + } + softpipe_map_transfers(sp); -void -softpipe_draw_range_elements(struct pipe_context *pipe, - struct pipe_resource *indexBuffer, - unsigned indexSize, - int indexBias, - unsigned min_index, - unsigned max_index, - unsigned mode, unsigned start, unsigned count) -{ - softpipe_draw_range_elements_instanced(pipe, - indexBuffer, - indexSize, - indexBias, - min_index, - max_index, - mode, - start, - count, - 0, - 1); -} + /* Map so buffers */ + if (offset < 0) /* we were appending so start from beginning */ + offset = 0; + buf = (void*)((int32_t*)buf + offset); + draw_set_mapped_vertex_buffer(draw, 0, buf); + draw_set_mapped_index_buffer(draw, NULL); -void -softpipe_draw_elements(struct pipe_context *pipe, - struct pipe_resource *indexBuffer, - unsigned indexSize, int indexBias, - unsigned mode, unsigned start, unsigned count) -{ - softpipe_draw_range_elements_instanced(pipe, - indexBuffer, - indexSize, - indexBias, - 0, - 0xffffffff, - mode, - start, - count, - 0, - 1); -} + /* draw! */ + draw_arrays(draw, mode, start, count); -void -softpipe_draw_arrays_instanced(struct pipe_context *pipe, - unsigned mode, - unsigned start, - unsigned count, - unsigned startInstance, - unsigned instanceCount) -{ - softpipe_draw_range_elements_instanced(pipe, - NULL, - 0, - 0, - 0, - 0xffffffff, - mode, - start, - count, - startInstance, - instanceCount); -} + /* unmap vertex/index buffers - will cause draw module to flush */ + draw_set_mapped_vertex_buffer(draw, 0, NULL); -void -softpipe_draw_elements_instanced(struct pipe_context *pipe, - struct pipe_resource *indexBuffer, - unsigned indexSize, - int indexBias, - unsigned mode, - unsigned start, - unsigned count, - unsigned startInstance, - unsigned instanceCount) -{ - softpipe_draw_range_elements_instanced(pipe, - indexBuffer, - indexSize, - indexBias, - 0, - 0xffffffff, - mode, - start, - count, - startInstance, - instanceCount); + /* + * TODO: Flush only when a user vertex/index buffer is present + * (or even better, modify draw module to do this + * internally when this condition is seen?) + */ + draw_flush(draw); + + /* Note: leave drawing surfaces mapped */ + sp->dirty_render_cache = TRUE; } -static void -softpipe_draw_range_elements_instanced(struct pipe_context *pipe, - struct pipe_resource *indexBuffer, - unsigned indexSize, - int indexBias, - unsigned minIndex, - unsigned maxIndex, - unsigned mode, - unsigned start, - unsigned count, - unsigned startInstance, - unsigned instanceCount) + +/** + * This function handles drawing indexed and non-indexed prims, + * instanced and non-instanced drawing, with or without min/max element + * indexes. + * All the other drawing functions are expressed in terms of this + * function. + * + * For non-indexed prims, indexBuffer should be NULL. + * For non-instanced drawing, instanceCount should be 1. + * When the min/max element indexes aren't known, minIndex should be 0 + * and maxIndex should be ~0. + */ +void +softpipe_draw_vbo(struct pipe_context *pipe, + const struct pipe_draw_info *info) { struct softpipe_context *sp = softpipe_context(pipe); struct draw_context *draw = sp->draw; + void *mapped_indices = NULL; unsigned i; if (!softpipe_check_render_cond(sp)) return; - sp->reduced_api_prim = u_reduced_prim(mode); + sp->reduced_api_prim = u_reduced_prim(info->mode); if (sp->dirty) { softpipe_update_derived(sp); @@ -207,32 +134,20 @@ softpipe_draw_range_elements_instanced(struct pipe_context *pipe, } /* Map index buffer, if present */ - if (indexBuffer) { - void *mapped_indexes = softpipe_resource(indexBuffer)->data; - draw_set_mapped_element_buffer_range(draw, - indexSize, - indexBias, - minIndex, - maxIndex, - mapped_indexes); - } else { - /* no index/element buffer */ - draw_set_mapped_element_buffer_range(draw, - 0, 0, - start, - start + count - 1, - NULL); - } + if (info->indexed && sp->index_buffer.buffer) + mapped_indices = softpipe_resource(sp->index_buffer.buffer)->data; + + draw_set_mapped_index_buffer(draw, mapped_indices); /* draw! */ - draw_arrays_instanced(draw, mode, start, count, startInstance, instanceCount); + draw_vbo(draw, info); /* unmap vertex/index buffers - will cause draw module to flush */ for (i = 0; i < sp->num_vertex_buffers; i++) { draw_set_mapped_vertex_buffer(draw, i, NULL); } - if (indexBuffer) { - draw_set_mapped_element_buffer(draw, 0, 0, NULL); + if (mapped_indices) { + draw_set_mapped_index_buffer(draw, NULL); } /* diff --git a/src/gallium/drivers/softpipe/sp_flush.c b/src/gallium/drivers/softpipe/sp_flush.c index 5024fc8a819..1071011db0e 100644 --- a/src/gallium/drivers/softpipe/sp_flush.c +++ b/src/gallium/drivers/softpipe/sp_flush.c @@ -31,6 +31,7 @@ #include "pipe/p_defines.h" +#include "pipe/p_screen.h" #include "draw/draw_context.h" #include "sp_flush.h" #include "sp_context.h" @@ -56,6 +57,9 @@ softpipe_flush( struct pipe_context *pipe, for (i = 0; i < softpipe->num_vertex_sampler_views; i++) { sp_flush_tex_tile_cache(softpipe->vertex_tex_cache[i]); } + for (i = 0; i < softpipe->num_geometry_sampler_views; i++) { + sp_flush_tex_tile_cache(softpipe->geometry_tex_cache[i]); + } } if (flags & PIPE_FLUSH_SWAPBUFFERS) { diff --git a/src/gallium/drivers/softpipe/sp_prim_vbuf.c b/src/gallium/drivers/softpipe/sp_prim_vbuf.c index a58bc107c0a..c60249dbfbc 100644 --- a/src/gallium/drivers/softpipe/sp_prim_vbuf.c +++ b/src/gallium/drivers/softpipe/sp_prim_vbuf.c @@ -158,26 +158,27 @@ static INLINE cptrf4 get_vert( const void *vertex_buffer, * draw elements / indexed primitives */ static void -sp_vbuf_draw(struct vbuf_render *vbr, const ushort *indices, uint nr) +sp_vbuf_draw_elements(struct vbuf_render *vbr, const ushort *indices, uint nr) { struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr); struct softpipe_context *softpipe = cvbr->softpipe; const unsigned stride = softpipe->vertex_info_vbuf.size * sizeof(float); const void *vertex_buffer = cvbr->vertex_buffer; - struct setup_context *setup_ctx = cvbr->setup; + struct setup_context *setup = cvbr->setup; + const boolean flatshade_first = softpipe->rasterizer->flatshade_first; unsigned i; switch (cvbr->prim) { case PIPE_PRIM_POINTS: for (i = 0; i < nr; i++) { - sp_setup_point( setup_ctx, + sp_setup_point( setup, get_vert(vertex_buffer, indices[i-0], stride) ); } break; case PIPE_PRIM_LINES: for (i = 1; i < nr; i += 2) { - sp_setup_line( setup_ctx, + sp_setup_line( setup, get_vert(vertex_buffer, indices[i-1], stride), get_vert(vertex_buffer, indices[i-0], stride) ); } @@ -185,7 +186,7 @@ sp_vbuf_draw(struct vbuf_render *vbr, const ushort *indices, uint nr) case PIPE_PRIM_LINE_STRIP: for (i = 1; i < nr; i ++) { - sp_setup_line( setup_ctx, + sp_setup_line( setup, get_vert(vertex_buffer, indices[i-1], stride), get_vert(vertex_buffer, indices[i-0], stride) ); } @@ -193,48 +194,41 @@ sp_vbuf_draw(struct vbuf_render *vbr, const ushort *indices, uint nr) case PIPE_PRIM_LINE_LOOP: for (i = 1; i < nr; i ++) { - sp_setup_line( setup_ctx, + sp_setup_line( setup, get_vert(vertex_buffer, indices[i-1], stride), get_vert(vertex_buffer, indices[i-0], stride) ); } if (nr) { - sp_setup_line( setup_ctx, + sp_setup_line( setup, get_vert(vertex_buffer, indices[nr-1], stride), get_vert(vertex_buffer, indices[0], stride) ); } break; case PIPE_PRIM_TRIANGLES: - if (softpipe->rasterizer->flatshade_first) { - for (i = 2; i < nr; i += 3) { - sp_setup_tri( setup_ctx, - get_vert(vertex_buffer, indices[i-1], stride), - get_vert(vertex_buffer, indices[i-0], stride), - get_vert(vertex_buffer, indices[i-2], stride) ); - } - } - else { - for (i = 2; i < nr; i += 3) { - sp_setup_tri( setup_ctx, - get_vert(vertex_buffer, indices[i-2], stride), - get_vert(vertex_buffer, indices[i-1], stride), - get_vert(vertex_buffer, indices[i-0], stride) ); - } + for (i = 2; i < nr; i += 3) { + sp_setup_tri( setup, + get_vert(vertex_buffer, indices[i-2], stride), + get_vert(vertex_buffer, indices[i-1], stride), + get_vert(vertex_buffer, indices[i-0], stride) ); } break; case PIPE_PRIM_TRIANGLE_STRIP: - if (softpipe->rasterizer->flatshade_first) { + if (flatshade_first) { for (i = 2; i < nr; i += 1) { - sp_setup_tri( setup_ctx, + /* emit first triangle vertex as first triangle vertex */ + sp_setup_tri( setup, + get_vert(vertex_buffer, indices[i-2], stride), get_vert(vertex_buffer, indices[i+(i&1)-1], stride), - get_vert(vertex_buffer, indices[i-(i&1)], stride), - get_vert(vertex_buffer, indices[i-2], stride) ); + get_vert(vertex_buffer, indices[i-(i&1)], stride) ); + } } else { for (i = 2; i < nr; i += 1) { - sp_setup_tri( setup_ctx, + /* emit last triangle vertex as last triangle vertex */ + sp_setup_tri( setup, get_vert(vertex_buffer, indices[i+(i&1)-2], stride), get_vert(vertex_buffer, indices[i-(i&1)-1], stride), get_vert(vertex_buffer, indices[i-0], stride) ); @@ -243,17 +237,19 @@ sp_vbuf_draw(struct vbuf_render *vbr, const ushort *indices, uint nr) break; case PIPE_PRIM_TRIANGLE_FAN: - if (softpipe->rasterizer->flatshade_first) { + if (flatshade_first) { for (i = 2; i < nr; i += 1) { - sp_setup_tri( setup_ctx, + /* emit first non-spoke vertex as first vertex */ + sp_setup_tri( setup, + get_vert(vertex_buffer, indices[i-1], stride), get_vert(vertex_buffer, indices[i-0], stride), - get_vert(vertex_buffer, indices[0], stride), - get_vert(vertex_buffer, indices[i-1], stride) ); + get_vert(vertex_buffer, indices[0], stride) ); } } else { for (i = 2; i < nr; i += 1) { - sp_setup_tri( setup_ctx, + /* emit last non-spoke vertex as last vertex */ + sp_setup_tri( setup, get_vert(vertex_buffer, indices[0], stride), get_vert(vertex_buffer, indices[i-1], stride), get_vert(vertex_buffer, indices[i-0], stride) ); @@ -262,43 +258,88 @@ sp_vbuf_draw(struct vbuf_render *vbr, const ushort *indices, uint nr) break; case PIPE_PRIM_QUADS: - for (i = 3; i < nr; i += 4) { - sp_setup_tri( setup_ctx, - get_vert(vertex_buffer, indices[i-3], stride), - get_vert(vertex_buffer, indices[i-2], stride), - get_vert(vertex_buffer, indices[i-0], stride) ); + /* GL quads don't follow provoking vertex convention */ + if (flatshade_first) { + /* emit last quad vertex as first triangle vertex */ + for (i = 3; i < nr; i += 4) { + sp_setup_tri( setup, + get_vert(vertex_buffer, indices[i-0], stride), + get_vert(vertex_buffer, indices[i-3], stride), + get_vert(vertex_buffer, indices[i-2], stride) ); - sp_setup_tri( setup_ctx, - get_vert(vertex_buffer, indices[i-2], stride), - get_vert(vertex_buffer, indices[i-1], stride), - get_vert(vertex_buffer, indices[i-0], stride) ); + sp_setup_tri( setup, + get_vert(vertex_buffer, indices[i-0], stride), + get_vert(vertex_buffer, indices[i-2], stride), + get_vert(vertex_buffer, indices[i-1], stride) ); + } + } + else { + /* emit last quad vertex as last triangle vertex */ + for (i = 3; i < nr; i += 4) { + sp_setup_tri( setup, + get_vert(vertex_buffer, indices[i-3], stride), + get_vert(vertex_buffer, indices[i-2], stride), + get_vert(vertex_buffer, indices[i-0], stride) ); + + sp_setup_tri( setup, + get_vert(vertex_buffer, indices[i-2], stride), + get_vert(vertex_buffer, indices[i-1], stride), + get_vert(vertex_buffer, indices[i-0], stride) ); + } } break; case PIPE_PRIM_QUAD_STRIP: - for (i = 3; i < nr; i += 2) { - sp_setup_tri( setup_ctx, - get_vert(vertex_buffer, indices[i-3], stride), - get_vert(vertex_buffer, indices[i-2], stride), - get_vert(vertex_buffer, indices[i-0], stride) ); - sp_setup_tri( setup_ctx, - get_vert(vertex_buffer, indices[i-1], stride), - get_vert(vertex_buffer, indices[i-3], stride), - get_vert(vertex_buffer, indices[i-0], stride) ); + /* GL quad strips don't follow provoking vertex convention */ + if (flatshade_first) { + /* emit last quad vertex as first triangle vertex */ + for (i = 3; i < nr; i += 2) { + sp_setup_tri( setup, + get_vert(vertex_buffer, indices[i-0], stride), + get_vert(vertex_buffer, indices[i-3], stride), + get_vert(vertex_buffer, indices[i-2], stride) ); + sp_setup_tri( setup, + get_vert(vertex_buffer, indices[i-0], stride), + get_vert(vertex_buffer, indices[i-1], stride), + get_vert(vertex_buffer, indices[i-3], stride) ); + } + } + else { + /* emit last quad vertex as last triangle vertex */ + for (i = 3; i < nr; i += 2) { + sp_setup_tri( setup, + get_vert(vertex_buffer, indices[i-3], stride), + get_vert(vertex_buffer, indices[i-2], stride), + get_vert(vertex_buffer, indices[i-0], stride) ); + sp_setup_tri( setup, + get_vert(vertex_buffer, indices[i-1], stride), + get_vert(vertex_buffer, indices[i-3], stride), + get_vert(vertex_buffer, indices[i-0], stride) ); + } } break; case PIPE_PRIM_POLYGON: /* Almost same as tri fan but the _first_ vertex specifies the flat - * shading color. Note that the first polygon vertex is passed as - * the last triangle vertex here. - * flatshade_first state makes no difference. + * shading color. */ - for (i = 2; i < nr; i += 1) { - sp_setup_tri( setup_ctx, - get_vert(vertex_buffer, indices[i-0], stride), - get_vert(vertex_buffer, indices[i-1], stride), - get_vert(vertex_buffer, indices[0], stride) ); + if (flatshade_first) { + /* emit first polygon vertex as first triangle vertex */ + for (i = 2; i < nr; i += 1) { + sp_setup_tri( setup, + get_vert(vertex_buffer, indices[0], stride), + get_vert(vertex_buffer, indices[i-1], stride), + get_vert(vertex_buffer, indices[i-0], stride) ); + } + } + else { + /* emit first polygon vertex as last triangle vertex */ + for (i = 2; i < nr; i += 1) { + sp_setup_tri( setup, + get_vert(vertex_buffer, indices[i-1], stride), + get_vert(vertex_buffer, indices[i-0], stride), + get_vert(vertex_buffer, indices[0], stride) ); + } } break; @@ -317,23 +358,24 @@ sp_vbuf_draw_arrays(struct vbuf_render *vbr, uint start, uint nr) { struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr); struct softpipe_context *softpipe = cvbr->softpipe; - struct setup_context *setup_ctx = cvbr->setup; + struct setup_context *setup = cvbr->setup; const unsigned stride = softpipe->vertex_info_vbuf.size * sizeof(float); const void *vertex_buffer = (void *) get_vert(cvbr->vertex_buffer, start, stride); + const boolean flatshade_first = softpipe->rasterizer->flatshade_first; unsigned i; switch (cvbr->prim) { case PIPE_PRIM_POINTS: for (i = 0; i < nr; i++) { - sp_setup_point( setup_ctx, + sp_setup_point( setup, get_vert(vertex_buffer, i-0, stride) ); } break; case PIPE_PRIM_LINES: for (i = 1; i < nr; i += 2) { - sp_setup_line( setup_ctx, + sp_setup_line( setup, get_vert(vertex_buffer, i-1, stride), get_vert(vertex_buffer, i-0, stride) ); } @@ -341,7 +383,7 @@ sp_vbuf_draw_arrays(struct vbuf_render *vbr, uint start, uint nr) case PIPE_PRIM_LINE_STRIP: for (i = 1; i < nr; i ++) { - sp_setup_line( setup_ctx, + sp_setup_line( setup, get_vert(vertex_buffer, i-1, stride), get_vert(vertex_buffer, i-0, stride) ); } @@ -349,48 +391,40 @@ sp_vbuf_draw_arrays(struct vbuf_render *vbr, uint start, uint nr) case PIPE_PRIM_LINE_LOOP: for (i = 1; i < nr; i ++) { - sp_setup_line( setup_ctx, + sp_setup_line( setup, get_vert(vertex_buffer, i-1, stride), get_vert(vertex_buffer, i-0, stride) ); } if (nr) { - sp_setup_line( setup_ctx, + sp_setup_line( setup, get_vert(vertex_buffer, nr-1, stride), get_vert(vertex_buffer, 0, stride) ); } break; case PIPE_PRIM_TRIANGLES: - if (softpipe->rasterizer->flatshade_first) { - for (i = 2; i < nr; i += 3) { - sp_setup_tri( setup_ctx, - get_vert(vertex_buffer, i-1, stride), - get_vert(vertex_buffer, i-0, stride), - get_vert(vertex_buffer, i-2, stride) ); - } - } - else { - for (i = 2; i < nr; i += 3) { - sp_setup_tri( setup_ctx, - get_vert(vertex_buffer, i-2, stride), - get_vert(vertex_buffer, i-1, stride), - get_vert(vertex_buffer, i-0, stride) ); - } + for (i = 2; i < nr; i += 3) { + sp_setup_tri( setup, + get_vert(vertex_buffer, i-2, stride), + get_vert(vertex_buffer, i-1, stride), + get_vert(vertex_buffer, i-0, stride) ); } break; case PIPE_PRIM_TRIANGLE_STRIP: - if (softpipe->rasterizer->flatshade_first) { + if (flatshade_first) { for (i = 2; i < nr; i++) { - sp_setup_tri( setup_ctx, + /* emit first triangle vertex as first triangle vertex */ + sp_setup_tri( setup, + get_vert(vertex_buffer, i-2, stride), get_vert(vertex_buffer, i+(i&1)-1, stride), - get_vert(vertex_buffer, i-(i&1), stride), - get_vert(vertex_buffer, i-2, stride) ); + get_vert(vertex_buffer, i-(i&1), stride) ); } } else { for (i = 2; i < nr; i++) { - sp_setup_tri( setup_ctx, + /* emit last triangle vertex as last triangle vertex */ + sp_setup_tri( setup, get_vert(vertex_buffer, i+(i&1)-2, stride), get_vert(vertex_buffer, i-(i&1)-1, stride), get_vert(vertex_buffer, i-0, stride) ); @@ -399,17 +433,19 @@ sp_vbuf_draw_arrays(struct vbuf_render *vbr, uint start, uint nr) break; case PIPE_PRIM_TRIANGLE_FAN: - if (softpipe->rasterizer->flatshade_first) { + if (flatshade_first) { for (i = 2; i < nr; i += 1) { - sp_setup_tri( setup_ctx, + /* emit first non-spoke vertex as first vertex */ + sp_setup_tri( setup, + get_vert(vertex_buffer, i-1, stride), get_vert(vertex_buffer, i-0, stride), - get_vert(vertex_buffer, 0, stride), - get_vert(vertex_buffer, i-1, stride) ); + get_vert(vertex_buffer, 0, stride) ); } } else { for (i = 2; i < nr; i += 1) { - sp_setup_tri( setup_ctx, + /* emit last non-spoke vertex as last vertex */ + sp_setup_tri( setup, get_vert(vertex_buffer, 0, stride), get_vert(vertex_buffer, i-1, stride), get_vert(vertex_buffer, i-0, stride) ); @@ -418,42 +454,86 @@ sp_vbuf_draw_arrays(struct vbuf_render *vbr, uint start, uint nr) break; case PIPE_PRIM_QUADS: - for (i = 3; i < nr; i += 4) { - sp_setup_tri( setup_ctx, - get_vert(vertex_buffer, i-3, stride), - get_vert(vertex_buffer, i-2, stride), - get_vert(vertex_buffer, i-0, stride) ); - sp_setup_tri( setup_ctx, - get_vert(vertex_buffer, i-2, stride), - get_vert(vertex_buffer, i-1, stride), - get_vert(vertex_buffer, i-0, stride) ); + /* GL quads don't follow provoking vertex convention */ + if (flatshade_first) { + /* emit last quad vertex as first triangle vertex */ + for (i = 3; i < nr; i += 4) { + sp_setup_tri( setup, + get_vert(vertex_buffer, i-0, stride), + get_vert(vertex_buffer, i-3, stride), + get_vert(vertex_buffer, i-2, stride) ); + sp_setup_tri( setup, + get_vert(vertex_buffer, i-0, stride), + get_vert(vertex_buffer, i-2, stride), + get_vert(vertex_buffer, i-1, stride) ); + } + } + else { + /* emit last quad vertex as last triangle vertex */ + for (i = 3; i < nr; i += 4) { + sp_setup_tri( setup, + get_vert(vertex_buffer, i-3, stride), + get_vert(vertex_buffer, i-2, stride), + get_vert(vertex_buffer, i-0, stride) ); + sp_setup_tri( setup, + get_vert(vertex_buffer, i-2, stride), + get_vert(vertex_buffer, i-1, stride), + get_vert(vertex_buffer, i-0, stride) ); + } } break; case PIPE_PRIM_QUAD_STRIP: - for (i = 3; i < nr; i += 2) { - sp_setup_tri( setup_ctx, - get_vert(vertex_buffer, i-3, stride), - get_vert(vertex_buffer, i-2, stride), - get_vert(vertex_buffer, i-0, stride) ); - sp_setup_tri( setup_ctx, - get_vert(vertex_buffer, i-1, stride), - get_vert(vertex_buffer, i-3, stride), - get_vert(vertex_buffer, i-0, stride) ); + /* GL quad strips don't follow provoking vertex convention */ + if (flatshade_first) { + /* emit last quad vertex as first triangle vertex */ + for (i = 3; i < nr; i += 2) { + sp_setup_tri( setup, + get_vert(vertex_buffer, i-0, stride), + get_vert(vertex_buffer, i-3, stride), + get_vert(vertex_buffer, i-2, stride) ); + sp_setup_tri( setup, + get_vert(vertex_buffer, i-0, stride), + get_vert(vertex_buffer, i-1, stride), + get_vert(vertex_buffer, i-3, stride) ); + } + } + else { + /* emit last quad vertex as last triangle vertex */ + for (i = 3; i < nr; i += 2) { + sp_setup_tri( setup, + get_vert(vertex_buffer, i-3, stride), + get_vert(vertex_buffer, i-2, stride), + get_vert(vertex_buffer, i-0, stride) ); + sp_setup_tri( setup, + get_vert(vertex_buffer, i-1, stride), + get_vert(vertex_buffer, i-3, stride), + get_vert(vertex_buffer, i-0, stride) ); + } } break; case PIPE_PRIM_POLYGON: /* Almost same as tri fan but the _first_ vertex specifies the flat - * shading color. Note that the first polygon vertex is passed as - * the last triangle vertex here. - * flatshade_first state makes no difference. + * shading color. */ - for (i = 2; i < nr; i += 1) { - sp_setup_tri( setup_ctx, - get_vert(vertex_buffer, i-1, stride), - get_vert(vertex_buffer, i-0, stride), - get_vert(vertex_buffer, 0, stride) ); + if (flatshade_first) { + /* emit first polygon vertex as first triangle vertex */ + for (i = 2; i < nr; i += 1) { + sp_setup_tri( setup, + get_vert(vertex_buffer, 0, stride), + get_vert(vertex_buffer, i-1, stride), + get_vert(vertex_buffer, i-0, stride) ); + } + } + else { + /* emit first polygon vertex as last triangle vertex */ + for (i = 2; i < nr; i += 1) { + sp_setup_tri( setup, + get_vert(vertex_buffer, i-1, stride), + get_vert(vertex_buffer, i-0, stride), + get_vert(vertex_buffer, 0, stride) ); + } } break; @@ -462,6 +542,22 @@ sp_vbuf_draw_arrays(struct vbuf_render *vbr, uint start, uint nr) } } +static void +sp_vbuf_so_info(struct vbuf_render *vbr, uint primitives, uint vertices) +{ + struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr); + struct softpipe_context *softpipe = cvbr->softpipe; + unsigned i; + + for (i = 0; i < softpipe->so_target.num_buffers; ++i) { + softpipe->so_target.so_count[i] += vertices; + } + + softpipe->so_stats.num_primitives_written = primitives; + softpipe->so_stats.primitives_storage_needed = + vertices * 4 /*sizeof(float|int32)*/ * 4 /*x,y,z,w*/; +} + static void sp_vbuf_destroy(struct vbuf_render *vbr) @@ -492,9 +588,10 @@ sp_create_vbuf_backend(struct softpipe_context *sp) cvbr->base.map_vertices = sp_vbuf_map_vertices; cvbr->base.unmap_vertices = sp_vbuf_unmap_vertices; cvbr->base.set_primitive = sp_vbuf_set_primitive; - cvbr->base.draw = sp_vbuf_draw; + cvbr->base.draw_elements = sp_vbuf_draw_elements; cvbr->base.draw_arrays = sp_vbuf_draw_arrays; cvbr->base.release_vertices = sp_vbuf_release_vertices; + cvbr->base.set_stream_output_info = sp_vbuf_so_info; cvbr->base.destroy = sp_vbuf_destroy; cvbr->softpipe = sp; diff --git a/src/gallium/drivers/softpipe/sp_quad_blend.c b/src/gallium/drivers/softpipe/sp_quad_blend.c index ead489393ef..6af1b2d0618 100644 --- a/src/gallium/drivers/softpipe/sp_quad_blend.c +++ b/src/gallium/drivers/softpipe/sp_quad_blend.c @@ -33,6 +33,7 @@ #include "pipe/p_defines.h" #include "util/u_math.h" #include "util/u_memory.h" +#include "util/u_format.h" #include "sp_context.h" #include "sp_quad.h" #include "sp_tile_cache.h" @@ -207,7 +208,7 @@ logicop_quad(struct quad_stage *qs, res4[j] = ~0; break; default: - assert(0); + assert(0 && "invalid logicop mode"); } for (j = 0; j < 4; j++) { @@ -220,11 +221,19 @@ logicop_quad(struct quad_stage *qs, +/** + * Do blending for a 2x2 quad for one color buffer. + * \param quadColor the incoming quad colors + * \param dest the destination/framebuffer quad colors + * \param blend_index which set of blending terms to use + * \param has_dst_alpha does the dest color buffer have an alpha channel? + */ static void blend_quad(struct quad_stage *qs, float (*quadColor)[4], float (*dest)[4], - unsigned cbuf) + unsigned blend_index, + boolean has_dst_alpha) { static const float zero[4] = { 0, 0, 0, 0 }; static const float one[4] = { 1, 1, 1, 1 }; @@ -234,7 +243,7 @@ blend_quad(struct quad_stage *qs, /* * Compute src/first term RGB */ - switch (softpipe->blend->rt[cbuf].rgb_src_factor) { + switch (softpipe->blend->rt[blend_index].rgb_src_factor) { case PIPE_BLENDFACTOR_ONE: VEC4_COPY(source[0], quadColor[0]); /* R */ VEC4_COPY(source[1], quadColor[1]); /* G */ @@ -259,24 +268,34 @@ blend_quad(struct quad_stage *qs, VEC4_MUL(source[2], quadColor[2], dest[2]); /* B */ break; case PIPE_BLENDFACTOR_DST_ALPHA: - { - const float *alpha = dest[3]; - VEC4_MUL(source[0], quadColor[0], alpha); /* R */ - VEC4_MUL(source[1], quadColor[1], alpha); /* G */ - VEC4_MUL(source[2], quadColor[2], alpha); /* B */ - } - break; + if (has_dst_alpha) { + const float *alpha = dest[3]; + VEC4_MUL(source[0], quadColor[0], alpha); /* R */ + VEC4_MUL(source[1], quadColor[1], alpha); /* G */ + VEC4_MUL(source[2], quadColor[2], alpha); /* B */ + } + else { + VEC4_COPY(source[0], quadColor[0]); /* R */ + VEC4_COPY(source[1], quadColor[1]); /* G */ + VEC4_COPY(source[2], quadColor[2]); /* B */ + } + break; case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE: - { - const float *alpha = quadColor[3]; - float diff[4], temp[4]; - VEC4_SUB(diff, one, dest[3]); - VEC4_MIN(temp, alpha, diff); - VEC4_MUL(source[0], quadColor[0], temp); /* R */ - VEC4_MUL(source[1], quadColor[1], temp); /* G */ - VEC4_MUL(source[2], quadColor[2], temp); /* B */ - } - break; + if (has_dst_alpha) { + const float *alpha = quadColor[3]; + float diff[4], temp[4]; + VEC4_SUB(diff, one, dest[3]); + VEC4_MIN(temp, alpha, diff); + VEC4_MUL(source[0], quadColor[0], temp); /* R */ + VEC4_MUL(source[1], quadColor[1], temp); /* G */ + VEC4_MUL(source[2], quadColor[2], temp); /* B */ + } + else { + VEC4_COPY(source[0], zero); /* R */ + VEC4_COPY(source[1], zero); /* G */ + VEC4_COPY(source[2], zero); /* B */ + } + break; case PIPE_BLENDFACTOR_CONST_COLOR: { float comp[4]; @@ -329,14 +348,19 @@ blend_quad(struct quad_stage *qs, } break; case PIPE_BLENDFACTOR_INV_DST_ALPHA: - { - float inv_alpha[4]; - VEC4_SUB(inv_alpha, one, dest[3]); - VEC4_MUL(source[0], quadColor[0], inv_alpha); /* R */ - VEC4_MUL(source[1], quadColor[1], inv_alpha); /* G */ - VEC4_MUL(source[2], quadColor[2], inv_alpha); /* B */ - } - break; + if (has_dst_alpha) { + float inv_alpha[4]; + VEC4_SUB(inv_alpha, one, dest[3]); + VEC4_MUL(source[0], quadColor[0], inv_alpha); /* R */ + VEC4_MUL(source[1], quadColor[1], inv_alpha); /* G */ + VEC4_MUL(source[2], quadColor[2], inv_alpha); /* B */ + } + else { + VEC4_COPY(source[0], zero); /* R */ + VEC4_COPY(source[1], zero); /* G */ + VEC4_COPY(source[2], zero); /* B */ + } + break; case PIPE_BLENDFACTOR_INV_DST_COLOR: { float inv_comp[4]; @@ -378,13 +402,13 @@ blend_quad(struct quad_stage *qs, assert(0); /* to do */ break; default: - assert(0); + assert(0 && "invalid rgb src factor"); } /* * Compute src/first term A */ - switch (softpipe->blend->rt[cbuf].alpha_src_factor) { + switch (softpipe->blend->rt[blend_index].alpha_src_factor) { case PIPE_BLENDFACTOR_ONE: VEC4_COPY(source[3], quadColor[3]); /* A */ break; @@ -399,7 +423,10 @@ blend_quad(struct quad_stage *qs, case PIPE_BLENDFACTOR_DST_COLOR: /* fall-through */ case PIPE_BLENDFACTOR_DST_ALPHA: - VEC4_MUL(source[3], quadColor[3], dest[3]); /* A */ + if (has_dst_alpha) + VEC4_MUL(source[3], quadColor[3], dest[3]); /* A */ + else + VEC4_COPY(source[3], quadColor[3]); /* A */ break; case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE: /* multiply alpha by 1.0 */ @@ -429,12 +456,15 @@ blend_quad(struct quad_stage *qs, case PIPE_BLENDFACTOR_INV_DST_COLOR: /* fall-through */ case PIPE_BLENDFACTOR_INV_DST_ALPHA: - { - float inv_alpha[4]; - VEC4_SUB(inv_alpha, one, dest[3]); - VEC4_MUL(source[3], quadColor[3], inv_alpha); /* A */ - } - break; + if (has_dst_alpha) { + float inv_alpha[4]; + VEC4_SUB(inv_alpha, one, dest[3]); + VEC4_MUL(source[3], quadColor[3], inv_alpha); /* A */ + } + else { + VEC4_COPY(source[3], zero); /* A */ + } + break; case PIPE_BLENDFACTOR_INV_CONST_COLOR: /* fall-through */ case PIPE_BLENDFACTOR_INV_CONST_ALPHA: @@ -446,14 +476,14 @@ blend_quad(struct quad_stage *qs, } break; default: - assert(0); + assert(0 && "invalid alpha src factor"); } /* * Compute dest/second term RGB */ - switch (softpipe->blend->rt[cbuf].rgb_dst_factor) { + switch (softpipe->blend->rt[blend_index].rgb_dst_factor) { case PIPE_BLENDFACTOR_ONE: /* dest = dest * 1 NO-OP, leave dest as-is */ break; @@ -468,9 +498,14 @@ blend_quad(struct quad_stage *qs, VEC4_MUL(dest[2], dest[2], quadColor[3]); /* B * A */ break; case PIPE_BLENDFACTOR_DST_ALPHA: - VEC4_MUL(dest[0], dest[0], dest[3]); /* R * A */ - VEC4_MUL(dest[1], dest[1], dest[3]); /* G * A */ - VEC4_MUL(dest[2], dest[2], dest[3]); /* B * A */ + if (has_dst_alpha) { + VEC4_MUL(dest[0], dest[0], dest[3]); /* R * A */ + VEC4_MUL(dest[1], dest[1], dest[3]); /* G * A */ + VEC4_MUL(dest[2], dest[2], dest[3]); /* B * A */ + } + else { + /* dest = dest * 1 NO-OP, leave dest as-is */ + } break; case PIPE_BLENDFACTOR_DST_COLOR: VEC4_MUL(dest[0], dest[0], dest[0]); /* R */ @@ -478,15 +513,20 @@ blend_quad(struct quad_stage *qs, VEC4_MUL(dest[2], dest[2], dest[2]); /* B */ break; case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE: - { - const float *alpha = quadColor[3]; - float diff[4], temp[4]; - VEC4_SUB(diff, one, dest[3]); - VEC4_MIN(temp, alpha, diff); - VEC4_MUL(dest[0], quadColor[0], temp); /* R */ - VEC4_MUL(dest[1], quadColor[1], temp); /* G */ - VEC4_MUL(dest[2], quadColor[2], temp); /* B */ - } + if (has_dst_alpha) { + const float *alpha = quadColor[3]; + float diff[4], temp[4]; + VEC4_SUB(diff, one, dest[3]); + VEC4_MIN(temp, alpha, diff); + VEC4_MUL(dest[0], quadColor[0], temp); /* R */ + VEC4_MUL(dest[1], quadColor[1], temp); /* G */ + VEC4_MUL(dest[2], quadColor[2], temp); /* B */ + } + else { + VEC4_COPY(dest[0], zero); /* R */ + VEC4_COPY(dest[1], zero); /* G */ + VEC4_COPY(dest[2], zero); /* B */ + } break; case PIPE_BLENDFACTOR_CONST_COLOR: { @@ -539,13 +579,18 @@ blend_quad(struct quad_stage *qs, } break; case PIPE_BLENDFACTOR_INV_DST_ALPHA: - { - float inv_comp[4]; - VEC4_SUB(inv_comp, one, dest[3]); /* A */ - VEC4_MUL(dest[0], inv_comp, dest[0]); /* R */ - VEC4_MUL(dest[1], inv_comp, dest[1]); /* G */ - VEC4_MUL(dest[2], inv_comp, dest[2]); /* B */ - } + if (has_dst_alpha) { + float inv_comp[4]; + VEC4_SUB(inv_comp, one, dest[3]); /* A */ + VEC4_MUL(dest[0], inv_comp, dest[0]); /* R */ + VEC4_MUL(dest[1], inv_comp, dest[1]); /* G */ + VEC4_MUL(dest[2], inv_comp, dest[2]); /* B */ + } + else { + VEC4_COPY(dest[0], zero); /* R */ + VEC4_COPY(dest[1], zero); /* G */ + VEC4_COPY(dest[2], zero); /* B */ + } break; case PIPE_BLENDFACTOR_INV_DST_COLOR: { @@ -587,13 +632,13 @@ blend_quad(struct quad_stage *qs, assert(0); break; default: - assert(0); + assert(0 && "invalid rgb dst factor"); } /* * Compute dest/second term A */ - switch (softpipe->blend->rt[cbuf].alpha_dst_factor) { + switch (softpipe->blend->rt[blend_index].alpha_dst_factor) { case PIPE_BLENDFACTOR_ONE: /* dest = dest * 1 NO-OP, leave dest as-is */ break; @@ -605,7 +650,12 @@ blend_quad(struct quad_stage *qs, case PIPE_BLENDFACTOR_DST_COLOR: /* fall-through */ case PIPE_BLENDFACTOR_DST_ALPHA: - VEC4_MUL(dest[3], dest[3], dest[3]); /* A */ + if (has_dst_alpha) { + VEC4_MUL(dest[3], dest[3], dest[3]); /* A */ + } + else { + /* dest = dest * 1 NO-OP, leave dest as-is */ + } break; case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE: /* dest = dest * 1 NO-OP, leave dest as-is */ @@ -634,12 +684,15 @@ blend_quad(struct quad_stage *qs, case PIPE_BLENDFACTOR_INV_DST_COLOR: /* fall-through */ case PIPE_BLENDFACTOR_INV_DST_ALPHA: - { - float inv_comp[4]; - VEC4_SUB(inv_comp, one, dest[3]); /* A */ - VEC4_MUL(dest[3], inv_comp, dest[3]); /* A */ - } - break; + if (has_dst_alpha) { + float inv_comp[4]; + VEC4_SUB(inv_comp, one, dest[3]); /* A */ + VEC4_MUL(dest[3], inv_comp, dest[3]); /* A */ + } + else { + VEC4_COPY(dest[3], zero); /* A */ + } + break; case PIPE_BLENDFACTOR_INV_CONST_COLOR: /* fall-through */ case PIPE_BLENDFACTOR_INV_CONST_ALPHA: @@ -650,13 +703,13 @@ blend_quad(struct quad_stage *qs, } break; default: - assert(0); + assert(0 && "invalid alpha dst factor"); } /* * Combine RGB terms */ - switch (softpipe->blend->rt[cbuf].rgb_func) { + switch (softpipe->blend->rt[blend_index].rgb_func) { case PIPE_BLEND_ADD: VEC4_ADD_SAT(quadColor[0], source[0], dest[0]); /* R */ VEC4_ADD_SAT(quadColor[1], source[1], dest[1]); /* G */ @@ -683,13 +736,13 @@ blend_quad(struct quad_stage *qs, VEC4_MAX(quadColor[2], source[2], dest[2]); /* B */ break; default: - assert(0); + assert(0 && "invalid rgb blend func"); } /* * Combine A terms */ - switch (softpipe->blend->rt[cbuf].alpha_func) { + switch (softpipe->blend->rt[blend_index].alpha_func) { case PIPE_BLEND_ADD: VEC4_ADD_SAT(quadColor[3], source[3], dest[3]); /* A */ break; @@ -706,7 +759,7 @@ blend_quad(struct quad_stage *qs, VEC4_MAX(quadColor[3], source[3], dest[3]); /* A */ break; default: - assert(0); + assert(0 && "invalid alpha blend func"); } } @@ -751,6 +804,8 @@ blend_fallback(struct quad_stage *qs, = sp_get_cached_tile(softpipe->cbuf_cache[cbuf], quads[0]->input.x0, quads[0]->input.y0); + boolean has_dst_alpha + = util_format_has_alpha(softpipe->framebuffer.cbufs[cbuf]->format); uint q, i, j; for (q = 0; q < nr; q++) { @@ -774,7 +829,7 @@ blend_fallback(struct quad_stage *qs, logicop_quad( qs, quadColor, dest ); } else if (blend->rt[blend_buf].blend_enable) { - blend_quad( qs, quadColor, dest, cbuf ); + blend_quad( qs, quadColor, dest, blend_buf, has_dst_alpha ); } if (blend->rt[blend_buf].colormask != 0xf) diff --git a/src/gallium/drivers/softpipe/sp_quad_depth_test.c b/src/gallium/drivers/softpipe/sp_quad_depth_test.c index 72117c233e5..e9b92626176 100644 --- a/src/gallium/drivers/softpipe/sp_quad_depth_test.c +++ b/src/gallium/drivers/softpipe/sp_quad_depth_test.c @@ -82,7 +82,7 @@ get_depth_stencil_values( struct depth_data *data, data->bzzzz[j] = tile->data.depth32[y][x] & 0xffffff; data->stencilVals[j] = tile->data.depth32[y][x] >> 24; } - break; + break; case PIPE_FORMAT_X8Z24_UNORM: case PIPE_FORMAT_S8_USCALED_Z24_UNORM: for (j = 0; j < QUAD_SIZE; j++) { @@ -92,6 +92,14 @@ get_depth_stencil_values( struct depth_data *data, data->stencilVals[j] = tile->data.depth32[y][x] & 0xff; } break; + case PIPE_FORMAT_S8_USCALED: + for (j = 0; j < QUAD_SIZE; j++) { + int x = quad->input.x0 % TILE_SIZE + (j & 1); + int y = quad->input.y0 % TILE_SIZE + (j >> 1); + data->bzzzz[j] = 0; + data->stencilVals[j] = tile->data.stencil8[y][x]; + } + break; default: assert(0); } @@ -227,6 +235,14 @@ write_depth_stencil_values( struct depth_data *data, tile->data.depth32[y][x] = data->bzzzz[j] << 8; } break; + case PIPE_FORMAT_S8_USCALED: + for (j = 0; j < QUAD_SIZE; j++) { + int x = quad->input.x0 % TILE_SIZE + (j & 1); + int y = quad->input.y0 % TILE_SIZE + (j >> 1); + tile->data.stencil8[y][x] = data->stencilVals[j]; + } + break; + default: assert(0); } @@ -661,20 +677,6 @@ static unsigned mask_count[16] = -/** helper to get number of Z buffer bits */ -static unsigned -get_depth_bits(struct quad_stage *qs) -{ - struct pipe_surface *zsurf = qs->softpipe->framebuffer.zsbuf; - if (zsurf) - return util_format_get_component_bits(zsurf->format, - UTIL_FORMAT_COLORSPACE_ZS, 0); - else - return 0; -} - - - /** * General depth/stencil test function. Used when there's no fast-path. */ @@ -693,9 +695,9 @@ depth_test_quads_fallback(struct quad_stage *qs, nr = alpha_test_quads(qs, quads, nr); } - if (get_depth_bits(qs) > 0 && - (qs->softpipe->depth_stencil->depth.enabled || - qs->softpipe->depth_stencil->stencil[0].enabled)) { + if (qs->softpipe->framebuffer.zsbuf && + (qs->softpipe->depth_stencil->depth.enabled || + qs->softpipe->depth_stencil->stencil[0].enabled)) { data.ps = qs->softpipe->framebuffer.zsbuf; data.format = data.ps->format; @@ -794,8 +796,7 @@ choose_depth_test(struct quad_stage *qs, boolean alpha = qs->softpipe->depth_stencil->alpha.enabled; - boolean depth = (get_depth_bits(qs) > 0 && - qs->softpipe->depth_stencil->depth.enabled); + boolean depth = qs->softpipe->depth_stencil->depth.enabled; unsigned depthfunc = qs->softpipe->depth_stencil->depth.func; @@ -805,6 +806,9 @@ choose_depth_test(struct quad_stage *qs, boolean occlusion = qs->softpipe->active_query_count; + if(!qs->softpipe->framebuffer.zsbuf) + depth = depthwrite = stencil = FALSE; + /* default */ qs->run = depth_test_quads_fallback; diff --git a/src/gallium/drivers/softpipe/sp_quad_fs.c b/src/gallium/drivers/softpipe/sp_quad_fs.c index 8ae5a7f028b..90f4787d599 100644 --- a/src/gallium/drivers/softpipe/sp_quad_fs.c +++ b/src/gallium/drivers/softpipe/sp_quad_fs.c @@ -50,8 +50,8 @@ struct quad_shade_stage { struct quad_stage stage; /**< base class */ - struct tgsi_exec_machine *machine; - struct tgsi_exec_vector *inputs, *outputs; + + /* no other fields at this time */ }; @@ -70,9 +70,8 @@ quad_shade_stage(struct quad_stage *qs) static INLINE boolean shade_quad(struct quad_stage *qs, struct quad_header *quad) { - struct quad_shade_stage *qss = quad_shade_stage( qs ); struct softpipe_context *softpipe = qs->softpipe; - struct tgsi_exec_machine *machine = qss->machine; + struct tgsi_exec_machine *machine = softpipe->fs_machine; /* run shader */ return softpipe->fs->run( softpipe->fs, machine, quad ); @@ -108,14 +107,14 @@ shade_quads(struct quad_stage *qs, struct quad_header *quads[], unsigned nr) { - struct quad_shade_stage *qss = quad_shade_stage( qs ); struct softpipe_context *softpipe = qs->softpipe; - struct tgsi_exec_machine *machine = qss->machine; - unsigned i, pass = 0; + struct tgsi_exec_machine *machine = softpipe->fs_machine; + unsigned i, nr_quads = 0; + + tgsi_exec_set_constant_buffers(machine, PIPE_MAX_CONSTANT_BUFFERS, + softpipe->mapped_constants[PIPE_SHADER_FRAGMENT], + softpipe->const_buffer_size[PIPE_SHADER_FRAGMENT]); - for (i = 0; i < PIPE_MAX_CONSTANT_BUFFERS; i++) { - machine->Consts[i] = softpipe->mapped_constants[PIPE_SHADER_FRAGMENT][i]; - } machine->InterpCoefs = quads[0]->coef; for (i = 0; i < nr; i++) { @@ -125,11 +124,11 @@ shade_quads(struct quad_stage *qs, if (/*do_coverage*/ 0) coverage_quad( qs, quads[i] ); - quads[pass++] = quads[i]; + quads[nr_quads++] = quads[i]; } - if (pass) - qs->next->run(qs->next, quads, pass); + if (nr_quads) + qs->next->run(qs->next, quads, nr_quads); } @@ -139,11 +138,10 @@ shade_quads(struct quad_stage *qs, static void shade_begin(struct quad_stage *qs) { - struct quad_shade_stage *qss = quad_shade_stage(qs); struct softpipe_context *softpipe = qs->softpipe; softpipe->fs->prepare( softpipe->fs, - qss->machine, + softpipe->fs_machine, (struct tgsi_sampler **) softpipe->tgsi.frag_samplers_list ); @@ -154,10 +152,6 @@ shade_begin(struct quad_stage *qs) static void shade_destroy(struct quad_stage *qs) { - struct quad_shade_stage *qss = (struct quad_shade_stage *) qs; - - tgsi_exec_machine_destroy(qss->machine); - FREE( qs ); } @@ -174,16 +168,9 @@ sp_quad_shade_stage( struct softpipe_context *softpipe ) qss->stage.run = shade_quads; qss->stage.destroy = shade_destroy; - qss->machine = tgsi_exec_machine_create(); - if (!qss->machine) - goto fail; - return &qss->stage; fail: - if (qss && qss->machine) - tgsi_exec_machine_destroy(qss->machine); - FREE(qss); return NULL; } diff --git a/src/gallium/drivers/softpipe/sp_query.c b/src/gallium/drivers/softpipe/sp_query.c index 4ef5d9f7b1d..4ae69c1c2bd 100644 --- a/src/gallium/drivers/softpipe/sp_query.c +++ b/src/gallium/drivers/softpipe/sp_query.c @@ -30,6 +30,7 @@ */ #include "draw/draw_context.h" +#include "os/os_time.h" #include "pipe/p_defines.h" #include "util/u_memory.h" #include "sp_context.h" @@ -37,8 +38,10 @@ #include "sp_state.h" struct softpipe_query { + unsigned type; uint64_t start; uint64_t end; + struct pipe_query_data_so_statistics so; }; @@ -51,8 +54,17 @@ static struct pipe_query * softpipe_create_query(struct pipe_context *pipe, unsigned type) { - assert(type == PIPE_QUERY_OCCLUSION_COUNTER); - return (struct pipe_query *)CALLOC_STRUCT( softpipe_query ); + struct softpipe_query* sq; + + assert(type == PIPE_QUERY_OCCLUSION_COUNTER || + type == PIPE_QUERY_TIME_ELAPSED || + type == PIPE_QUERY_SO_STATISTICS || + type == PIPE_QUERY_GPU_FINISHED || + type == PIPE_QUERY_TIMESTAMP_DISJOINT); + sq = CALLOC_STRUCT( softpipe_query ); + sq->type = type; + + return (struct pipe_query *)sq; } @@ -68,8 +80,25 @@ softpipe_begin_query(struct pipe_context *pipe, struct pipe_query *q) { struct softpipe_context *softpipe = softpipe_context( pipe ); struct softpipe_query *sq = softpipe_query(q); - - sq->start = softpipe->occlusion_count; + + switch (sq->type) { + case PIPE_QUERY_OCCLUSION_COUNTER: + sq->start = softpipe->occlusion_count; + break; + case PIPE_QUERY_TIME_ELAPSED: + sq->start = 1000*os_time_get(); + break; + case PIPE_QUERY_SO_STATISTICS: + sq->so.num_primitives_written = 0; + sq->so.primitives_storage_needed = 0; + break; + case PIPE_QUERY_GPU_FINISHED: + break; + case PIPE_QUERY_TIMESTAMP_DISJOINT: + default: + assert(0); + break; + } softpipe->active_query_count++; softpipe->dirty |= SP_NEW_QUERY; } @@ -82,7 +111,26 @@ softpipe_end_query(struct pipe_context *pipe, struct pipe_query *q) struct softpipe_query *sq = softpipe_query(q); softpipe->active_query_count--; - sq->end = softpipe->occlusion_count; + switch (sq->type) { + case PIPE_QUERY_OCCLUSION_COUNTER: + sq->end = softpipe->occlusion_count; + break; + case PIPE_QUERY_TIME_ELAPSED: + sq->end = 1000*os_time_get(); + break; + case PIPE_QUERY_SO_STATISTICS: + sq->so.num_primitives_written = + softpipe->so_stats.num_primitives_written; + sq->so.primitives_storage_needed = + softpipe->so_stats.primitives_storage_needed; + break; + case PIPE_QUERY_GPU_FINISHED: + case PIPE_QUERY_TIMESTAMP_DISJOINT: + break; + default: + assert(0); + break; + } softpipe->dirty |= SP_NEW_QUERY; } @@ -91,10 +139,32 @@ static boolean softpipe_get_query_result(struct pipe_context *pipe, struct pipe_query *q, boolean wait, - uint64_t *result ) + void *vresult) { struct softpipe_query *sq = softpipe_query(q); - *result = sq->end - sq->start; + uint64_t *result = (uint64_t*)vresult; + + switch (sq->type) { + case PIPE_QUERY_SO_STATISTICS: + memcpy(vresult, &sq->so, + sizeof(struct pipe_query_data_so_statistics)); + break; + case PIPE_QUERY_GPU_FINISHED: + *result = TRUE; + break; + case PIPE_QUERY_TIMESTAMP_DISJOINT: { + struct pipe_query_data_timestamp_disjoint td; + /*os_get_time is in microseconds*/ + td.frequency = 1000000; + td.disjoint = FALSE; + memcpy(vresult, &sq->so, + sizeof(struct pipe_query_data_timestamp_disjoint)); + } + break; + default: + *result = sq->end - sq->start; + break; + } return TRUE; } diff --git a/src/gallium/drivers/softpipe/sp_screen.c b/src/gallium/drivers/softpipe/sp_screen.c index 00700974c78..25a0a622179 100644 --- a/src/gallium/drivers/softpipe/sp_screen.c +++ b/src/gallium/drivers/softpipe/sp_screen.c @@ -31,8 +31,10 @@ #include "util/u_format_s3tc.h" #include "pipe/p_defines.h" #include "pipe/p_screen.h" +#include "draw/draw_context.h" #include "state_tracker/sw_winsys.h" +#include "tgsi/tgsi_exec.h" #include "sp_texture.h" #include "sp_screen.h" @@ -57,7 +59,7 @@ softpipe_get_name(struct pipe_screen *screen) static int -softpipe_get_param(struct pipe_screen *screen, int param) +softpipe_get_param(struct pipe_screen *screen, enum pipe_cap param) { switch (param) { case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS: @@ -72,6 +74,8 @@ softpipe_get_param(struct pipe_screen *screen, int param) return 1; case PIPE_CAP_GLSL: return 1; + case PIPE_CAP_SM3: + return 1; case PIPE_CAP_ANISOTROPIC_FILTER: return 0; case PIPE_CAP_POINT_SPRITE: @@ -80,26 +84,24 @@ softpipe_get_param(struct pipe_screen *screen, int param) return PIPE_MAX_COLOR_BUFS; case PIPE_CAP_OCCLUSION_QUERY: return 1; + case PIPE_CAP_TIMER_QUERY: + return 1; case PIPE_CAP_TEXTURE_MIRROR_CLAMP: return 1; case PIPE_CAP_TEXTURE_MIRROR_REPEAT: return 1; case PIPE_CAP_TEXTURE_SHADOW_MAP: return 1; + case PIPE_CAP_TEXTURE_SWIZZLE: + return 1; case PIPE_CAP_MAX_TEXTURE_2D_LEVELS: return SP_MAX_TEXTURE_2D_LEVELS; case PIPE_CAP_MAX_TEXTURE_3D_LEVELS: return SP_MAX_TEXTURE_3D_LEVELS; case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS: return SP_MAX_TEXTURE_2D_LEVELS; - case PIPE_CAP_TGSI_CONT_SUPPORTED: - return 1; case PIPE_CAP_BLEND_EQUATION_SEPARATE: return 1; - case PIPE_CAP_MAX_CONST_BUFFERS: - return PIPE_MAX_CONSTANT_BUFFERS; - case PIPE_CAP_MAX_CONST_BUFFER_SIZE: - return 4096 * 4 * sizeof(float); case PIPE_CAP_INDEP_BLEND_ENABLE: return 1; case PIPE_CAP_INDEP_BLEND_FUNC: @@ -109,14 +111,32 @@ softpipe_get_param(struct pipe_screen *screen, int param) case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER: case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER: return 1; + case PIPE_CAP_STREAM_OUTPUT: + return 1; + case PIPE_CAP_DEPTHSTENCIL_CLEAR_SEPARATE: + return 0; default: return 0; } } +static int +softpipe_get_shader_param(struct pipe_screen *screen, unsigned shader, enum pipe_shader_cap param) +{ + switch(shader) + { + case PIPE_SHADER_FRAGMENT: + return tgsi_exec_get_shader_param(param); + case PIPE_SHADER_VERTEX: + case PIPE_SHADER_GEOMETRY: + return draw_get_shader_param(shader, param); + default: + return 0; + } +} static float -softpipe_get_paramf(struct pipe_screen *screen, int param) +softpipe_get_paramf(struct pipe_screen *screen, enum pipe_cap param) { switch (param) { case PIPE_CAP_MAX_LINE_WIDTH: @@ -144,16 +164,19 @@ softpipe_get_paramf(struct pipe_screen *screen, int param) */ static boolean softpipe_is_format_supported( struct pipe_screen *screen, - enum pipe_format format, + enum pipe_format format, enum pipe_texture_target target, + unsigned sample_count, unsigned bind, unsigned geom_flags ) { struct sw_winsys *winsys = softpipe_screen(screen)->winsys; const struct util_format_description *format_desc; - assert(target == PIPE_TEXTURE_1D || + assert(target == PIPE_BUFFER || + target == PIPE_TEXTURE_1D || target == PIPE_TEXTURE_2D || + target == PIPE_TEXTURE_RECT || target == PIPE_TEXTURE_3D || target == PIPE_TEXTURE_CUBE); @@ -161,6 +184,9 @@ softpipe_is_format_supported( struct pipe_screen *screen, if (!format_desc) return FALSE; + if (sample_count > 1) + return FALSE; + if (bind & (PIPE_BIND_DISPLAY_TARGET | PIPE_BIND_SCANOUT | PIPE_BIND_SHARED)) { @@ -271,6 +297,7 @@ softpipe_create_screen(struct sw_winsys *winsys) screen->base.get_name = softpipe_get_name; screen->base.get_vendor = softpipe_get_vendor; screen->base.get_param = softpipe_get_param; + screen->base.get_shader_param = softpipe_get_shader_param; screen->base.get_paramf = softpipe_get_paramf; screen->base.is_format_supported = softpipe_is_format_supported; screen->base.context_create = softpipe_create_context; diff --git a/src/gallium/drivers/softpipe/sp_setup.c b/src/gallium/drivers/softpipe/sp_setup.c index 86354664e4b..5d727dc00df 100644 --- a/src/gallium/drivers/softpipe/sp_setup.c +++ b/src/gallium/drivers/softpipe/sp_setup.c @@ -111,34 +111,13 @@ struct setup_context { uint numFragsWritten; /**< per primitive */ #endif - unsigned winding; /* which winding to cull */ + unsigned cull_face; /* which faces cull */ unsigned nr_vertex_attrs; }; -/** - * Do triangle cull test using tri determinant (sign indicates orientation) - * \return true if triangle is to be culled. - */ -static INLINE boolean -cull_tri(const struct setup_context *setup, float det) -{ - if (det != 0) { - /* if (det < 0 then Z points toward camera and triangle is - * counter-clockwise winding. - */ - unsigned winding = (det < 0) ? PIPE_WINDING_CCW : PIPE_WINDING_CW; - - if ((winding & setup->winding) == 0) - return FALSE; - } - - /* Culled: - */ - return TRUE; -} @@ -304,7 +283,10 @@ setup_sort_vertices(struct setup_context *setup, const float (*v1)[4], const float (*v2)[4]) { - setup->vprovoke = v2; + if (setup->softpipe->rasterizer->flatshade_first) + setup->vprovoke = v0; + else + setup->vprovoke = v2; /* determine bottom to top order of vertices */ { @@ -390,8 +372,16 @@ setup_sort_vertices(struct setup_context *setup, * 0 = front-facing, 1 = back-facing */ setup->facing = - ((det > 0.0) ^ - (setup->softpipe->rasterizer->front_winding == PIPE_WINDING_CW)); + ((det < 0.0) ^ + (setup->softpipe->rasterizer->front_ccw)); + + { + unsigned face = setup->facing == 0 ? PIPE_FACE_FRONT : PIPE_FACE_BACK; + + if (face & setup->cull_face) + return FALSE; + } + /* Prepare pixel offset for rasterisation: * - pixel center (0.5, 0.5) for GL, or @@ -829,11 +819,9 @@ sp_setup_tri(struct setup_context *setup, setup->numFragsWritten = 0; #endif - if (cull_tri( setup, det )) - return; - if (!setup_sort_vertices( setup, det, v0, v1, v2 )) return; + setup_tri_coefficients( setup ); setup_tri_edges( setup ); @@ -1417,14 +1405,14 @@ sp_setup_prepare(struct setup_context *setup) sp->quad.first->begin( sp->quad.first ); if (sp->reduced_api_prim == PIPE_PRIM_TRIANGLES && - sp->rasterizer->fill_cw == PIPE_POLYGON_MODE_FILL && - sp->rasterizer->fill_ccw == PIPE_POLYGON_MODE_FILL) { + sp->rasterizer->fill_front == PIPE_POLYGON_MODE_FILL && + sp->rasterizer->fill_back == PIPE_POLYGON_MODE_FILL) { /* we'll do culling */ - setup->winding = sp->rasterizer->cull_mode; + setup->cull_face = sp->rasterizer->cull_face; } else { /* 'draw' will do culling */ - setup->winding = PIPE_WINDING_NONE; + setup->cull_face = PIPE_FACE_NONE; } } diff --git a/src/gallium/drivers/softpipe/sp_state.h b/src/gallium/drivers/softpipe/sp_state.h index f97fc6eca8f..525bf23734a 100644 --- a/src/gallium/drivers/softpipe/sp_state.h +++ b/src/gallium/drivers/softpipe/sp_state.h @@ -51,6 +51,8 @@ #define SP_NEW_VS 0x2000 #define SP_NEW_QUERY 0x4000 #define SP_NEW_GS 0x8000 +#define SP_NEW_SO 0x10000 +#define SP_NEW_SO_BUFFERS 0x20000 struct tgsi_sampler; @@ -68,6 +70,8 @@ struct sp_fragment_shader { struct tgsi_shader_info info; + struct draw_fragment_shader *draw_shader; + boolean origin_lower_left; /**< fragment shader uses lower left position origin? */ boolean pixel_center_integer; /**< fragment shader uses integer pixel center? */ @@ -98,6 +102,7 @@ struct sp_vertex_shader { struct sp_geometry_shader { struct pipe_shader_state shader; struct draw_geometry_shader *draw_data; + int max_sampler; }; struct sp_velems_state { @@ -105,141 +110,45 @@ struct sp_velems_state { struct pipe_vertex_element velem[PIPE_MAX_ATTRIBS]; }; +struct sp_so_state { + struct pipe_stream_output_state base; +}; -void * -softpipe_create_blend_state(struct pipe_context *, - const struct pipe_blend_state *); -void softpipe_bind_blend_state(struct pipe_context *, - void *); -void softpipe_delete_blend_state(struct pipe_context *, - void *); -void * -softpipe_create_sampler_state(struct pipe_context *, - const struct pipe_sampler_state *); -void softpipe_bind_sampler_states(struct pipe_context *, unsigned, void **); void -softpipe_bind_vertex_sampler_states(struct pipe_context *, - unsigned num_samplers, - void **samplers); -void softpipe_delete_sampler_state(struct pipe_context *, void *); - -void * -softpipe_create_depth_stencil_state(struct pipe_context *, - const struct pipe_depth_stencil_alpha_state *); -void softpipe_bind_depth_stencil_state(struct pipe_context *, void *); -void softpipe_delete_depth_stencil_state(struct pipe_context *, void *); - -void * -softpipe_create_rasterizer_state(struct pipe_context *, - const struct pipe_rasterizer_state *); -void softpipe_bind_rasterizer_state(struct pipe_context *, void *); -void softpipe_delete_rasterizer_state(struct pipe_context *, void *); - -void softpipe_set_framebuffer_state( struct pipe_context *, - const struct pipe_framebuffer_state * ); - -void softpipe_set_blend_color( struct pipe_context *pipe, - const struct pipe_blend_color *blend_color ); - -void softpipe_set_stencil_ref( struct pipe_context *pipe, - const struct pipe_stencil_ref *stencil_ref ); - -void softpipe_set_clip_state( struct pipe_context *, - const struct pipe_clip_state * ); - -void softpipe_set_constant_buffer(struct pipe_context *, - uint shader, uint index, - struct pipe_resource *buf); - -void *softpipe_create_fs_state(struct pipe_context *, - const struct pipe_shader_state *); -void softpipe_bind_fs_state(struct pipe_context *, void *); -void softpipe_delete_fs_state(struct pipe_context *, void *); -void *softpipe_create_vs_state(struct pipe_context *, - const struct pipe_shader_state *); -void softpipe_bind_vs_state(struct pipe_context *, void *); -void softpipe_delete_vs_state(struct pipe_context *, void *); -void *softpipe_create_gs_state(struct pipe_context *, - const struct pipe_shader_state *); -void softpipe_bind_gs_state(struct pipe_context *, void *); -void softpipe_delete_gs_state(struct pipe_context *, void *); - -void *softpipe_create_vertex_elements_state(struct pipe_context *, - unsigned count, - const struct pipe_vertex_element *); -void softpipe_bind_vertex_elements_state(struct pipe_context *, void *); -void softpipe_delete_vertex_elements_state(struct pipe_context *, void *); - -void softpipe_set_polygon_stipple( struct pipe_context *, - const struct pipe_poly_stipple * ); - -void softpipe_set_scissor_state( struct pipe_context *, - const struct pipe_scissor_state * ); - -void softpipe_set_sampler_views( struct pipe_context *, - unsigned num, - struct pipe_sampler_view ** ); +softpipe_init_blend_funcs(struct pipe_context *pipe); void -softpipe_set_vertex_sampler_views(struct pipe_context *, - unsigned num, - struct pipe_sampler_view **); - -struct pipe_sampler_view * -softpipe_create_sampler_view(struct pipe_context *pipe, - struct pipe_resource *texture, - const struct pipe_sampler_view *templ); +softpipe_init_clip_funcs(struct pipe_context *pipe); void -softpipe_sampler_view_destroy(struct pipe_context *pipe, - struct pipe_sampler_view *view); +softpipe_init_sampler_funcs(struct pipe_context *pipe); -void softpipe_set_viewport_state( struct pipe_context *, - const struct pipe_viewport_state * ); - -void softpipe_set_vertex_buffers(struct pipe_context *, - unsigned count, - const struct pipe_vertex_buffer *); +void +softpipe_init_rasterizer_funcs(struct pipe_context *pipe); +void +softpipe_init_shader_funcs(struct pipe_context *pipe); -void softpipe_update_derived( struct softpipe_context *softpipe ); +void +softpipe_init_streamout_funcs(struct pipe_context *pipe); +void +softpipe_init_vertex_funcs(struct pipe_context *pipe); -void softpipe_draw_arrays(struct pipe_context *pipe, unsigned mode, - unsigned start, unsigned count); +void +softpipe_set_framebuffer_state(struct pipe_context *, + const struct pipe_framebuffer_state *); -void softpipe_draw_elements(struct pipe_context *pipe, - struct pipe_resource *indexBuffer, - unsigned indexSize, int indexBias, - unsigned mode, unsigned start, unsigned count); void -softpipe_draw_range_elements(struct pipe_context *pipe, - struct pipe_resource *indexBuffer, - unsigned indexSize, - int indexBias, - unsigned min_index, - unsigned max_index, - unsigned mode, unsigned start, unsigned count); +softpipe_update_derived( struct softpipe_context *softpipe ); void -softpipe_draw_arrays_instanced(struct pipe_context *pipe, - unsigned mode, - unsigned start, - unsigned count, - unsigned startInstance, - unsigned instanceCount); +softpipe_draw_vbo(struct pipe_context *pipe, + const struct pipe_draw_info *info); void -softpipe_draw_elements_instanced(struct pipe_context *pipe, - struct pipe_resource *indexBuffer, - unsigned indexSize, - int indexBias, - unsigned mode, - unsigned start, - unsigned count, - unsigned startInstance, - unsigned instanceCount); +softpipe_draw_stream_output(struct pipe_context *pipe, unsigned mode); void softpipe_map_transfers(struct softpipe_context *sp); diff --git a/src/gallium/drivers/softpipe/sp_state_blend.c b/src/gallium/drivers/softpipe/sp_state_blend.c index c63a49e90b0..12863824b8e 100644 --- a/src/gallium/drivers/softpipe/sp_state_blend.c +++ b/src/gallium/drivers/softpipe/sp_state_blend.c @@ -34,15 +34,17 @@ #include "sp_state.h" -void * +static void * softpipe_create_blend_state(struct pipe_context *pipe, const struct pipe_blend_state *blend) { return mem_dup(blend, sizeof(*blend)); } -void softpipe_bind_blend_state( struct pipe_context *pipe, - void *blend ) + +static void +softpipe_bind_blend_state(struct pipe_context *pipe, + void *blend) { struct softpipe_context *softpipe = softpipe_context(pipe); @@ -53,15 +55,18 @@ void softpipe_bind_blend_state( struct pipe_context *pipe, softpipe->dirty |= SP_NEW_BLEND; } -void softpipe_delete_blend_state(struct pipe_context *pipe, - void *blend) + +static void +softpipe_delete_blend_state(struct pipe_context *pipe, + void *blend) { FREE( blend ); } -void softpipe_set_blend_color( struct pipe_context *pipe, - const struct pipe_blend_color *blend_color ) +static void +softpipe_set_blend_color(struct pipe_context *pipe, + const struct pipe_blend_color *blend_color) { struct softpipe_context *softpipe = softpipe_context(pipe); @@ -73,19 +78,15 @@ void softpipe_set_blend_color( struct pipe_context *pipe, } -/** XXX move someday? Or consolidate all these simple state setters - * into one file. - */ - - -void * +static void * softpipe_create_depth_stencil_state(struct pipe_context *pipe, const struct pipe_depth_stencil_alpha_state *depth_stencil) { return mem_dup(depth_stencil, sizeof(*depth_stencil)); } -void + +static void softpipe_bind_depth_stencil_state(struct pipe_context *pipe, void *depth_stencil) { @@ -96,14 +97,17 @@ softpipe_bind_depth_stencil_state(struct pipe_context *pipe, softpipe->dirty |= SP_NEW_DEPTH_STENCIL_ALPHA; } -void + +static void softpipe_delete_depth_stencil_state(struct pipe_context *pipe, void *depth) { FREE( depth ); } -void softpipe_set_stencil_ref( struct pipe_context *pipe, - const struct pipe_stencil_ref *stencil_ref ) + +static void +softpipe_set_stencil_ref(struct pipe_context *pipe, + const struct pipe_stencil_ref *stencil_ref) { struct softpipe_context *softpipe = softpipe_context(pipe); @@ -111,3 +115,29 @@ void softpipe_set_stencil_ref( struct pipe_context *pipe, softpipe->dirty |= SP_NEW_DEPTH_STENCIL_ALPHA; } + + +static void +softpipe_set_sample_mask(struct pipe_context *pipe, + unsigned sample_mask) +{ +} + + +void +softpipe_init_blend_funcs(struct pipe_context *pipe) +{ + pipe->create_blend_state = softpipe_create_blend_state; + pipe->bind_blend_state = softpipe_bind_blend_state; + pipe->delete_blend_state = softpipe_delete_blend_state; + + pipe->set_blend_color = softpipe_set_blend_color; + + pipe->create_depth_stencil_alpha_state = softpipe_create_depth_stencil_state; + pipe->bind_depth_stencil_alpha_state = softpipe_bind_depth_stencil_state; + pipe->delete_depth_stencil_alpha_state = softpipe_delete_depth_stencil_state; + + pipe->set_stencil_ref = softpipe_set_stencil_ref; + + pipe->set_sample_mask = softpipe_set_sample_mask; +} diff --git a/src/gallium/drivers/softpipe/sp_state_clip.c b/src/gallium/drivers/softpipe/sp_state_clip.c index 4946c776e3e..f3a4c234e27 100644 --- a/src/gallium/drivers/softpipe/sp_state_clip.c +++ b/src/gallium/drivers/softpipe/sp_state_clip.c @@ -32,8 +32,9 @@ #include "draw/draw_context.h" -void softpipe_set_clip_state( struct pipe_context *pipe, - const struct pipe_clip_state *clip ) +static void +softpipe_set_clip_state(struct pipe_context *pipe, + const struct pipe_clip_state *clip) { struct softpipe_context *softpipe = softpipe_context(pipe); @@ -42,8 +43,9 @@ void softpipe_set_clip_state( struct pipe_context *pipe, } -void softpipe_set_viewport_state( struct pipe_context *pipe, - const struct pipe_viewport_state *viewport ) +static void +softpipe_set_viewport_state(struct pipe_context *pipe, + const struct pipe_viewport_state *viewport) { struct softpipe_context *softpipe = softpipe_context(pipe); @@ -55,8 +57,9 @@ void softpipe_set_viewport_state( struct pipe_context *pipe, } -void softpipe_set_scissor_state( struct pipe_context *pipe, - const struct pipe_scissor_state *scissor ) +static void +softpipe_set_scissor_state(struct pipe_context *pipe, + const struct pipe_scissor_state *scissor) { struct softpipe_context *softpipe = softpipe_context(pipe); @@ -67,8 +70,9 @@ void softpipe_set_scissor_state( struct pipe_context *pipe, } -void softpipe_set_polygon_stipple( struct pipe_context *pipe, - const struct pipe_poly_stipple *stipple ) +static void +softpipe_set_polygon_stipple(struct pipe_context *pipe, + const struct pipe_poly_stipple *stipple) { struct softpipe_context *softpipe = softpipe_context(pipe); @@ -77,3 +81,13 @@ void softpipe_set_polygon_stipple( struct pipe_context *pipe, softpipe->poly_stipple = *stipple; /* struct copy */ softpipe->dirty |= SP_NEW_STIPPLE; } + + +void +softpipe_init_clip_funcs(struct pipe_context *pipe) +{ + pipe->set_clip_state = softpipe_set_clip_state; + pipe->set_viewport_state = softpipe_set_viewport_state; + pipe->set_scissor_state = softpipe_set_scissor_state; + pipe->set_polygon_stipple = softpipe_set_polygon_stipple; +} diff --git a/src/gallium/drivers/softpipe/sp_state_derived.c b/src/gallium/drivers/softpipe/sp_state_derived.c index 4c6d4909f5b..3ba4d934fd2 100644 --- a/src/gallium/drivers/softpipe/sp_state_derived.c +++ b/src/gallium/drivers/softpipe/sp_state_derived.c @@ -225,6 +225,19 @@ update_tgsi_samplers( struct softpipe_context *softpipe ) } } } + + for (i = 0; i < PIPE_MAX_GEOMETRY_SAMPLERS; i++) { + struct softpipe_tex_tile_cache *tc = softpipe->geometry_tex_cache[i]; + + if (tc->texture) { + struct softpipe_resource *spt = softpipe_resource(tc->texture); + + if (spt->timestamp != tc->timestamp) { + sp_tex_tile_cache_validate_texture(tc); + tc->timestamp = spt->timestamp; + } + } + } } diff --git a/src/gallium/drivers/softpipe/sp_state_rasterizer.c b/src/gallium/drivers/softpipe/sp_state_rasterizer.c index c9ede09f268..3cd4acd7432 100644 --- a/src/gallium/drivers/softpipe/sp_state_rasterizer.c +++ b/src/gallium/drivers/softpipe/sp_state_rasterizer.c @@ -33,15 +33,17 @@ -void * +static void * softpipe_create_rasterizer_state(struct pipe_context *pipe, const struct pipe_rasterizer_state *rast) { return mem_dup(rast, sizeof(*rast)); } -void softpipe_bind_rasterizer_state(struct pipe_context *pipe, - void *rasterizer) + +static void +softpipe_bind_rasterizer_state(struct pipe_context *pipe, + void *rasterizer) { struct softpipe_context *softpipe = softpipe_context(pipe); @@ -56,10 +58,19 @@ void softpipe_bind_rasterizer_state(struct pipe_context *pipe, softpipe->dirty |= SP_NEW_RASTERIZER; } -void softpipe_delete_rasterizer_state(struct pipe_context *pipe, - void *rasterizer) + +static void +softpipe_delete_rasterizer_state(struct pipe_context *pipe, + void *rasterizer) { FREE( rasterizer ); } +void +softpipe_init_rasterizer_funcs(struct pipe_context *pipe) +{ + pipe->create_rasterizer_state = softpipe_create_rasterizer_state; + pipe->bind_rasterizer_state = softpipe_bind_rasterizer_state; + pipe->delete_rasterizer_state = softpipe_delete_rasterizer_state; +} diff --git a/src/gallium/drivers/softpipe/sp_state_sampler.c b/src/gallium/drivers/softpipe/sp_state_sampler.c index 2692f06c927..b59fbc33ed6 100644 --- a/src/gallium/drivers/softpipe/sp_state_sampler.c +++ b/src/gallium/drivers/softpipe/sp_state_sampler.c @@ -33,7 +33,6 @@ #include "util/u_inlines.h" #include "draw/draw_context.h" -#include "draw/draw_context.h" #include "sp_context.h" #include "sp_state.h" @@ -54,7 +53,7 @@ static struct sp_sampler *sp_sampler( struct pipe_sampler_state *sampler ) } -void * +static void * softpipe_create_sampler_state(struct pipe_context *pipe, const struct pipe_sampler_state *sampler) { @@ -67,7 +66,7 @@ softpipe_create_sampler_state(struct pipe_context *pipe, } -void +static void softpipe_bind_sampler_states(struct pipe_context *pipe, unsigned num, void **sampler) { @@ -94,7 +93,7 @@ softpipe_bind_sampler_states(struct pipe_context *pipe, } -void +static void softpipe_bind_vertex_sampler_states(struct pipe_context *pipe, unsigned num_samplers, void **samplers) @@ -118,11 +117,42 @@ softpipe_bind_vertex_sampler_states(struct pipe_context *pipe, softpipe->num_vertex_samplers = num_samplers; + draw_set_samplers(softpipe->draw, + softpipe->vertex_samplers, + softpipe->num_vertex_samplers); + + softpipe->dirty |= SP_NEW_SAMPLER; +} + +static void +softpipe_bind_geometry_sampler_states(struct pipe_context *pipe, + unsigned num_samplers, + void **samplers) +{ + struct softpipe_context *softpipe = softpipe_context(pipe); + unsigned i; + + assert(num_samplers <= PIPE_MAX_GEOMETRY_SAMPLERS); + + /* Check for no-op */ + if (num_samplers == softpipe->num_geometry_samplers && + !memcmp(softpipe->geometry_samplers, samplers, num_samplers * sizeof(void *))) + return; + + draw_flush(softpipe->draw); + + for (i = 0; i < num_samplers; ++i) + softpipe->geometry_samplers[i] = samplers[i]; + for (i = num_samplers; i < PIPE_MAX_GEOMETRY_SAMPLERS; ++i) + softpipe->geometry_samplers[i] = NULL; + + softpipe->num_geometry_samplers = num_samplers; + softpipe->dirty |= SP_NEW_SAMPLER; } -struct pipe_sampler_view * +static struct pipe_sampler_view * softpipe_create_sampler_view(struct pipe_context *pipe, struct pipe_resource *resource, const struct pipe_sampler_view *templ) @@ -141,7 +171,7 @@ softpipe_create_sampler_view(struct pipe_context *pipe, } -void +static void softpipe_sampler_view_destroy(struct pipe_context *pipe, struct pipe_sampler_view *view) { @@ -150,7 +180,7 @@ softpipe_sampler_view_destroy(struct pipe_context *pipe, } -void +static void softpipe_set_sampler_views(struct pipe_context *pipe, unsigned num, struct pipe_sampler_view **views) @@ -180,7 +210,7 @@ softpipe_set_sampler_views(struct pipe_context *pipe, } -void +static void softpipe_set_vertex_sampler_views(struct pipe_context *pipe, unsigned num, struct pipe_sampler_view **views) @@ -207,6 +237,41 @@ softpipe_set_vertex_sampler_views(struct pipe_context *pipe, softpipe->num_vertex_sampler_views = num; + draw_set_sampler_views(softpipe->draw, + softpipe->vertex_sampler_views, + softpipe->num_vertex_sampler_views); + + softpipe->dirty |= SP_NEW_TEXTURE; +} + + +static void +softpipe_set_geometry_sampler_views(struct pipe_context *pipe, + unsigned num, + struct pipe_sampler_view **views) +{ + struct softpipe_context *softpipe = softpipe_context(pipe); + uint i; + + assert(num <= PIPE_MAX_GEOMETRY_SAMPLERS); + + /* Check for no-op */ + if (num == softpipe->num_geometry_sampler_views && + !memcmp(softpipe->geometry_sampler_views, views, num * sizeof(struct pipe_sampler_view *))) { + return; + } + + draw_flush(softpipe->draw); + + for (i = 0; i < PIPE_MAX_GEOMETRY_SAMPLERS; i++) { + struct pipe_sampler_view *view = i < num ? views[i] : NULL; + + pipe_sampler_view_reference(&softpipe->geometry_sampler_views[i], view); + sp_tex_tile_cache_set_sampler_view(softpipe->geometry_tex_cache[i], view); + } + + softpipe->num_geometry_sampler_views = num; + softpipe->dirty |= SP_NEW_TEXTURE; } @@ -262,8 +327,6 @@ get_sampler_varient( unsigned unit, } - - void softpipe_reset_sampler_varients(struct softpipe_context *softpipe) { @@ -293,6 +356,30 @@ softpipe_reset_sampler_varients(struct softpipe_context *softpipe) } } + if (softpipe->gs) { + for (i = 0; i <= softpipe->gs->max_sampler; i++) { + if (softpipe->geometry_samplers[i]) { + struct pipe_resource *texture = NULL; + + if (softpipe->geometry_sampler_views[i]) { + texture = softpipe->geometry_sampler_views[i]->texture; + } + + softpipe->tgsi.geom_samplers_list[i] = + get_sampler_varient( + i, + sp_sampler(softpipe->geometry_samplers[i]), + texture, + TGSI_PROCESSOR_GEOMETRY ); + + sp_sampler_varient_bind_texture( + softpipe->tgsi.geom_samplers_list[i], + softpipe->geometry_tex_cache[i], + texture ); + } + } + } + for (i = 0; i <= softpipe->fs->info.file_max[TGSI_FILE_SAMPLER]; i++) { if (softpipe->sampler[i]) { struct pipe_resource *texture = NULL; @@ -314,9 +401,7 @@ softpipe_reset_sampler_varients(struct softpipe_context *softpipe) } } - - -void +static void softpipe_delete_sampler_state(struct pipe_context *pipe, void *sampler) { @@ -332,4 +417,20 @@ softpipe_delete_sampler_state(struct pipe_context *pipe, } +void +softpipe_init_sampler_funcs(struct pipe_context *pipe) +{ + pipe->create_sampler_state = softpipe_create_sampler_state; + pipe->bind_fragment_sampler_states = softpipe_bind_sampler_states; + pipe->bind_vertex_sampler_states = softpipe_bind_vertex_sampler_states; + pipe->bind_geometry_sampler_states = softpipe_bind_geometry_sampler_states; + pipe->delete_sampler_state = softpipe_delete_sampler_state; + + pipe->set_fragment_sampler_views = softpipe_set_sampler_views; + pipe->set_vertex_sampler_views = softpipe_set_vertex_sampler_views; + pipe->set_geometry_sampler_views = softpipe_set_geometry_sampler_views; + + pipe->create_sampler_view = softpipe_create_sampler_view; + pipe->sampler_view_destroy = softpipe_sampler_view_destroy; +} diff --git a/src/gallium/drivers/softpipe/sp_state_fs.c b/src/gallium/drivers/softpipe/sp_state_shader.c index 7f072f5a269..7fff338ccea 100644 --- a/src/gallium/drivers/softpipe/sp_state_fs.c +++ b/src/gallium/drivers/softpipe/sp_state_shader.c @@ -35,12 +35,14 @@ #include "util/u_inlines.h" #include "draw/draw_context.h" #include "draw/draw_vs.h" +#include "draw/draw_gs.h" #include "tgsi/tgsi_dump.h" +#include "tgsi/tgsi_exec.h" #include "tgsi/tgsi_scan.h" #include "tgsi/tgsi_parse.h" -void * +static void * softpipe_create_fs_state(struct pipe_context *pipe, const struct pipe_shader_state *templ) { @@ -58,7 +60,15 @@ softpipe_create_fs_state(struct pipe_context *pipe, state = softpipe_create_fs_exec( softpipe, templ ); } - assert(state); + if (!state) + return NULL; + + /* draw's fs state */ + state->draw_shader = draw_create_fragment_shader(softpipe->draw, templ); + if (!state->draw_shader) { + state->delete( state ); + return NULL; + } /* get/save the summary info for this shader */ tgsi_scan_shader(templ->tokens, &state->info); @@ -74,7 +84,7 @@ softpipe_create_fs_state(struct pipe_context *pipe, } -void +static void softpipe_bind_fs_state(struct pipe_context *pipe, void *fs) { struct softpipe_context *softpipe = softpipe_context(pipe); @@ -88,22 +98,35 @@ softpipe_bind_fs_state(struct pipe_context *pipe, void *fs) softpipe->fs = fs; + draw_bind_fragment_shader(softpipe->draw, + (softpipe->fs ? softpipe->fs->draw_shader : NULL)); + softpipe->dirty |= SP_NEW_FS; } -void +static void softpipe_delete_fs_state(struct pipe_context *pipe, void *fs) { + struct softpipe_context *softpipe = softpipe_context(pipe); struct sp_fragment_shader *state = fs; assert(fs != softpipe_context(pipe)->fs); - + + if (softpipe->fs_machine->Tokens == state->shader.tokens) { + /* unbind the shader from the tgsi executor if we're + * deleting it. + */ + tgsi_exec_machine_bind_shader(softpipe->fs_machine, NULL, 0, NULL); + } + + draw_delete_fragment_shader(softpipe->draw, state->draw_shader); + state->delete( state ); } -void * +static void * softpipe_create_vs_state(struct pipe_context *pipe, const struct pipe_shader_state *templ) { @@ -138,7 +161,7 @@ fail: } -void +static void softpipe_bind_vs_state(struct pipe_context *pipe, void *vs) { struct softpipe_context *softpipe = softpipe_context(pipe); @@ -152,7 +175,7 @@ softpipe_bind_vs_state(struct pipe_context *pipe, void *vs) } -void +static void softpipe_delete_vs_state(struct pipe_context *pipe, void *vs) { struct softpipe_context *softpipe = softpipe_context(pipe); @@ -164,33 +187,8 @@ softpipe_delete_vs_state(struct pipe_context *pipe, void *vs) FREE( state ); } -void -softpipe_set_constant_buffer(struct pipe_context *pipe, - uint shader, uint index, - struct pipe_resource *constants) -{ - struct softpipe_context *softpipe = softpipe_context(pipe); - unsigned size = constants ? constants->width0 : 0; - const void *data = constants ? softpipe_resource(constants)->data : NULL; - - assert(shader < PIPE_SHADER_TYPES); - assert(index == 0); - - draw_flush(softpipe->draw); - - /* note: reference counting */ - pipe_resource_reference(&softpipe->constants[shader][index], constants); - - if (shader == PIPE_SHADER_VERTEX || shader == PIPE_SHADER_GEOMETRY) { - draw_set_mapped_constant_buffer(softpipe->draw, shader, index, data, size); - } - softpipe->mapped_constants[shader][index] = data; - softpipe->dirty |= SP_NEW_CONSTANTS; -} - - -void * +static void * softpipe_create_gs_state(struct pipe_context *pipe, const struct pipe_shader_state *templ) { @@ -215,6 +213,8 @@ softpipe_create_gs_state(struct pipe_context *pipe, if (state->draw_data == NULL) goto fail; + state->max_sampler = state->draw_data->info.file_max[TGSI_FILE_SAMPLER]; + return state; fail: @@ -227,7 +227,7 @@ fail: } -void +static void softpipe_bind_gs_state(struct pipe_context *pipe, void *gs) { struct softpipe_context *softpipe = softpipe_context(pipe); @@ -241,7 +241,7 @@ softpipe_bind_gs_state(struct pipe_context *pipe, void *gs) } -void +static void softpipe_delete_gs_state(struct pipe_context *pipe, void *gs) { struct softpipe_context *softpipe = softpipe_context(pipe); @@ -253,3 +253,49 @@ softpipe_delete_gs_state(struct pipe_context *pipe, void *gs) (state) ? state->draw_data : 0); FREE(state); } + + +static void +softpipe_set_constant_buffer(struct pipe_context *pipe, + uint shader, uint index, + struct pipe_resource *constants) +{ + struct softpipe_context *softpipe = softpipe_context(pipe); + unsigned size = constants ? constants->width0 : 0; + const void *data = constants ? softpipe_resource(constants)->data : NULL; + + assert(shader < PIPE_SHADER_TYPES); + + draw_flush(softpipe->draw); + + /* note: reference counting */ + pipe_resource_reference(&softpipe->constants[shader][index], constants); + + if (shader == PIPE_SHADER_VERTEX || shader == PIPE_SHADER_GEOMETRY) { + draw_set_mapped_constant_buffer(softpipe->draw, shader, index, data, size); + } + + softpipe->mapped_constants[shader][index] = data; + softpipe->const_buffer_size[shader][index] = size; + + softpipe->dirty |= SP_NEW_CONSTANTS; +} + + +void +softpipe_init_shader_funcs(struct pipe_context *pipe) +{ + pipe->create_fs_state = softpipe_create_fs_state; + pipe->bind_fs_state = softpipe_bind_fs_state; + pipe->delete_fs_state = softpipe_delete_fs_state; + + pipe->create_vs_state = softpipe_create_vs_state; + pipe->bind_vs_state = softpipe_bind_vs_state; + pipe->delete_vs_state = softpipe_delete_vs_state; + + pipe->create_gs_state = softpipe_create_gs_state; + pipe->bind_gs_state = softpipe_bind_gs_state; + pipe->delete_gs_state = softpipe_delete_gs_state; + + pipe->set_constant_buffer = softpipe_set_constant_buffer; +} diff --git a/src/gallium/drivers/softpipe/sp_state_so.c b/src/gallium/drivers/softpipe/sp_state_so.c new file mode 100644 index 00000000000..ddfa3ef765a --- /dev/null +++ b/src/gallium/drivers/softpipe/sp_state_so.c @@ -0,0 +1,140 @@ +/************************************************************************** + * + * Copyright 2010 VMware, Inc. + * All Rights Reserved. + * + * 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 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 TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "sp_context.h" +#include "sp_state.h" +#include "sp_texture.h" + +#include "util/u_format.h" +#include "util/u_memory.h" +#include "draw/draw_context.h" + + +static void * +softpipe_create_stream_output_state(struct pipe_context *pipe, + const struct pipe_stream_output_state *templ) +{ + struct sp_so_state *so; + so = (struct sp_so_state *) CALLOC_STRUCT(sp_so_state); + + if (so) { + so->base.num_outputs = templ->num_outputs; + so->base.stride = templ->stride; + memcpy(so->base.output_buffer, + templ->output_buffer, + sizeof(int) * templ->num_outputs); + memcpy(so->base.register_index, + templ->register_index, + sizeof(int) * templ->num_outputs); + memcpy(so->base.register_mask, + templ->register_mask, + sizeof(ubyte) * templ->num_outputs); + } + return so; +} + + +static void +softpipe_bind_stream_output_state(struct pipe_context *pipe, + void *so) +{ + struct softpipe_context *softpipe = softpipe_context(pipe); + struct sp_so_state *sp_so = (struct sp_so_state *) so; + + softpipe->so = sp_so; + + softpipe->dirty |= SP_NEW_SO; + + if (sp_so) + draw_set_so_state(softpipe->draw, &sp_so->base); +} + + +static void +softpipe_delete_stream_output_state(struct pipe_context *pipe, void *so) +{ + FREE( so ); +} + + +static void +softpipe_set_stream_output_buffers(struct pipe_context *pipe, + struct pipe_resource **buffers, + int *offsets, + int num_buffers) +{ + struct softpipe_context *softpipe = softpipe_context(pipe); + int i; + void *map_buffers[PIPE_MAX_SO_BUFFERS]; + + assert(num_buffers <= PIPE_MAX_SO_BUFFERS); + if (num_buffers > PIPE_MAX_SO_BUFFERS) + num_buffers = PIPE_MAX_SO_BUFFERS; + + softpipe->dirty |= SP_NEW_SO_BUFFERS; + + for (i = 0; i < num_buffers; ++i) { + void *mapped; + struct softpipe_resource *res = softpipe_resource(buffers[i]); + + if (!res) { + /* the whole call is invalid, bail out */ + softpipe->so_target.num_buffers = 0; + draw_set_mapped_so_buffers(softpipe->draw, 0, 0); + return; + } + + softpipe->so_target.buffer[i] = res; + softpipe->so_target.offset[i] = offsets[i]; + softpipe->so_target.so_count[i] = 0; + + mapped = res->data; + if (offsets[i] >= 0) + map_buffers[i] = ((char*)mapped) + offsets[i]; + else { + /* this is a buffer append */ + assert(!"appending not implemented"); + map_buffers[i] = mapped; + } + } + softpipe->so_target.num_buffers = num_buffers; + + draw_set_mapped_so_buffers(softpipe->draw, map_buffers, num_buffers); +} + + + +void +softpipe_init_streamout_funcs(struct pipe_context *pipe) +{ + pipe->create_stream_output_state = softpipe_create_stream_output_state; + pipe->bind_stream_output_state = softpipe_bind_stream_output_state; + pipe->delete_stream_output_state = softpipe_delete_stream_output_state; + + pipe->set_stream_output_buffers = softpipe_set_stream_output_buffers; +} + diff --git a/src/gallium/drivers/softpipe/sp_state_vertex.c b/src/gallium/drivers/softpipe/sp_state_vertex.c index 462f4d2655e..7d8055f2baf 100644 --- a/src/gallium/drivers/softpipe/sp_state_vertex.c +++ b/src/gallium/drivers/softpipe/sp_state_vertex.c @@ -36,7 +36,7 @@ #include "draw/draw_context.h" -void * +static void * softpipe_create_vertex_elements_state(struct pipe_context *pipe, unsigned count, const struct pipe_vertex_element *attribs) @@ -51,7 +51,8 @@ softpipe_create_vertex_elements_state(struct pipe_context *pipe, return velems; } -void + +static void softpipe_bind_vertex_elements_state(struct pipe_context *pipe, void *velems) { @@ -66,13 +67,15 @@ softpipe_bind_vertex_elements_state(struct pipe_context *pipe, draw_set_vertex_elements(softpipe->draw, sp_velems->count, sp_velems->velem); } -void + +static void softpipe_delete_vertex_elements_state(struct pipe_context *pipe, void *velems) { FREE( velems ); } -void + +static void softpipe_set_vertex_buffers(struct pipe_context *pipe, unsigned count, const struct pipe_vertex_buffer *buffers) @@ -88,3 +91,30 @@ softpipe_set_vertex_buffers(struct pipe_context *pipe, draw_set_vertex_buffers(softpipe->draw, count, buffers); } + + +static void +softpipe_set_index_buffer(struct pipe_context *pipe, + const struct pipe_index_buffer *ib) +{ + struct softpipe_context *softpipe = softpipe_context(pipe); + + if (ib) + memcpy(&softpipe->index_buffer, ib, sizeof(softpipe->index_buffer)); + else + memset(&softpipe->index_buffer, 0, sizeof(softpipe->index_buffer)); + + draw_set_index_buffer(softpipe->draw, ib); +} + + +void +softpipe_init_vertex_funcs(struct pipe_context *pipe) +{ + pipe->create_vertex_elements_state = softpipe_create_vertex_elements_state; + pipe->bind_vertex_elements_state = softpipe_bind_vertex_elements_state; + pipe->delete_vertex_elements_state = softpipe_delete_vertex_elements_state; + + pipe->set_vertex_buffers = softpipe_set_vertex_buffers; + pipe->set_index_buffer = softpipe_set_index_buffer; +} diff --git a/src/gallium/drivers/softpipe/sp_surface.c b/src/gallium/drivers/softpipe/sp_surface.c index b04c2a63ad6..55b27e60100 100644 --- a/src/gallium/drivers/softpipe/sp_surface.c +++ b/src/gallium/drivers/softpipe/sp_surface.c @@ -25,26 +25,14 @@ * **************************************************************************/ -#include "util/u_rect.h" +#include "util/u_surface.h" #include "sp_context.h" #include "sp_surface.h" - -static void -sp_surface_copy(struct pipe_context *pipe, - struct pipe_surface *dest, unsigned destx, unsigned desty, - struct pipe_surface *src, unsigned srcx, unsigned srcy, - unsigned width, unsigned height) -{ - util_surface_copy(pipe, FALSE, - dest, destx, desty, - src, srcx, srcy, - width, height); -} - void sp_init_surface_functions(struct softpipe_context *sp) { - sp->pipe.surface_copy = sp_surface_copy; - sp->pipe.surface_fill = util_surface_fill; + sp->pipe.resource_copy_region = util_resource_copy_region; + sp->pipe.clear_render_target = util_clear_render_target; + sp->pipe.clear_depth_stencil = util_clear_depth_stencil; } diff --git a/src/gallium/drivers/softpipe/sp_tex_sample.c b/src/gallium/drivers/softpipe/sp_tex_sample.c index ff83c66d8b2..088e48f81fe 100644 --- a/src/gallium/drivers/softpipe/sp_tex_sample.c +++ b/src/gallium/drivers/softpipe/sp_tex_sample.c @@ -71,7 +71,7 @@ lerp(float a, float v0, float v1) /** - * Do 2D/biliner interpolation of float values. + * Do 2D/bilinear interpolation of float values. * v00, v10, v01 and v11 are typically four texture samples in a square/box. * a and b are the horizontal and vertical interpolants. * It's important that this function is inlined when compiled with @@ -105,14 +105,14 @@ lerp_3d(float a, float b, float c, /** * Compute coord % size for repeat wrap modes. - * Note that if coord is a signed integer, coord % size doesn't give - * the right value for coord < 0 (in terms of texture repeat). Just - * casting to unsigned fixes that. + * Note that if coord is negative, coord % size doesn't give the right + * value. To avoid that problem we add a large multiple of the size + * (rather than using a conditional). */ static INLINE int repeat(int coord, unsigned size) { - return (int) ((unsigned) coord % size); + return (coord + size * 1024) % size; } @@ -656,7 +656,8 @@ get_texel_2d(const struct sp_sampler_varient *samp, if (x < 0 || x >= (int) u_minify(texture->width0, level) || y < 0 || y >= (int) u_minify(texture->height0, level)) { - return samp->sampler->border_color; + return sp_tex_tile_cache_border_color(samp->cache, + samp->sampler->border_color); } else { return get_texel_2d_no_border( samp, addr, x, y ); @@ -750,7 +751,8 @@ get_texel_3d(const struct sp_sampler_varient *samp, if (x < 0 || x >= (int) u_minify(texture->width0, level) || y < 0 || y >= (int) u_minify(texture->height0, level) || z < 0 || z >= (int) u_minify(texture->depth0, level)) { - return samp->sampler->border_color; + return sp_tex_tile_cache_border_color(samp->cache, + samp->sampler->border_color); } else { return get_texel_3d_no_border( samp, addr, x, y, z ); @@ -1785,6 +1787,7 @@ get_lambda_func(const union sp_sampler_key key) case PIPE_TEXTURE_1D: return compute_lambda_1d; case PIPE_TEXTURE_2D: + case PIPE_TEXTURE_RECT: case PIPE_TEXTURE_CUBE: return compute_lambda_2d; case PIPE_TEXTURE_3D: @@ -1809,6 +1812,7 @@ get_img_filter(const union sp_sampler_key key, return img_filter_1d_linear; break; case PIPE_TEXTURE_2D: + case PIPE_TEXTURE_RECT: /* Try for fast path: */ if (key.bits.is_pot && diff --git a/src/gallium/drivers/softpipe/sp_tex_tile_cache.c b/src/gallium/drivers/softpipe/sp_tex_tile_cache.c index fbce9e042ba..e817c0c8cf5 100644 --- a/src/gallium/drivers/softpipe/sp_tex_tile_cache.c +++ b/src/gallium/drivers/softpipe/sp_tex_tile_cache.c @@ -63,19 +63,21 @@ sp_create_tex_tile_cache( struct pipe_context *pipe ) void sp_destroy_tex_tile_cache(struct softpipe_tex_tile_cache *tc) { - uint pos; + if (tc) { + uint pos; - for (pos = 0; pos < NUM_ENTRIES; pos++) { - /*assert(tc->entries[pos].x < 0);*/ - } - if (tc->transfer) { - tc->pipe->transfer_destroy(tc->pipe, tc->transfer); - } - if (tc->tex_trans) { - tc->pipe->transfer_destroy(tc->pipe, tc->tex_trans); - } + for (pos = 0; pos < NUM_ENTRIES; pos++) { + /*assert(tc->entries[pos].x < 0);*/ + } + if (tc->transfer) { + tc->pipe->transfer_destroy(tc->pipe, tc->transfer); + } + if (tc->tex_trans) { + tc->pipe->transfer_destroy(tc->pipe, tc->tex_trans); + } - FREE( tc ); + FREE( tc ); + } } @@ -115,6 +117,20 @@ sp_tex_tile_cache_validate_texture(struct softpipe_tex_tile_cache *tc) } } +static boolean +sp_tex_tile_is_compat_view(struct softpipe_tex_tile_cache *tc, + struct pipe_sampler_view *view) +{ + if (!view) + return FALSE; + return (tc->texture == view->texture && + tc->format == view->format && + tc->swizzle_r == view->swizzle_r && + tc->swizzle_g == view->swizzle_g && + tc->swizzle_b == view->swizzle_b && + tc->swizzle_a == view->swizzle_a); +} + /** * Specify the sampler view to cache. */ @@ -127,7 +143,7 @@ sp_tex_tile_cache_set_sampler_view(struct softpipe_tex_tile_cache *tc, assert(!tc->transfer); - if (tc->texture != texture) { + if (!sp_tex_tile_is_compat_view(tc, view)) { pipe_resource_reference(&tc->texture, texture); if (tc->tex_trans) { @@ -282,3 +298,23 @@ sp_find_cached_tile_tex(struct softpipe_tex_tile_cache *tc, +/** + * Return the swizzled border color. + */ +const float * +sp_tex_tile_cache_border_color(struct softpipe_tex_tile_cache *tc, + const float border_color[4]) +{ + float rgba01[6]; + + COPY_4V(rgba01, border_color); + rgba01[PIPE_SWIZZLE_ZERO] = 0.0f; + rgba01[PIPE_SWIZZLE_ONE] = 1.0f; + + tc->swz_border_color[0] = rgba01[tc->swizzle_r]; + tc->swz_border_color[1] = rgba01[tc->swizzle_g]; + tc->swz_border_color[2] = rgba01[tc->swizzle_b]; + tc->swz_border_color[3] = rgba01[tc->swizzle_a]; + + return tc->swz_border_color; +} diff --git a/src/gallium/drivers/softpipe/sp_tex_tile_cache.h b/src/gallium/drivers/softpipe/sp_tex_tile_cache.h index 0794ffa0c53..05f25133daa 100644 --- a/src/gallium/drivers/softpipe/sp_tex_tile_cache.h +++ b/src/gallium/drivers/softpipe/sp_tex_tile_cache.h @@ -90,6 +90,8 @@ struct softpipe_tex_tile_cache unsigned format; struct softpipe_tex_cached_tile *last_tile; /**< most recently retrieved tile */ + + float swz_border_color[4]; /**< swizzled border color */ }; @@ -154,7 +156,9 @@ sp_get_cached_tile_tex(struct softpipe_tex_tile_cache *tc, } - +const float * +sp_tex_tile_cache_border_color(struct softpipe_tex_tile_cache *tc, + const float border_color[4]); #endif /* SP_TEX_TILE_CACHE_H */ diff --git a/src/gallium/drivers/softpipe/sp_texture.c b/src/gallium/drivers/softpipe/sp_texture.c index 7aa85559b23..4e6123fbd07 100644 --- a/src/gallium/drivers/softpipe/sp_texture.c +++ b/src/gallium/drivers/softpipe/sp_texture.c @@ -343,11 +343,15 @@ softpipe_get_transfer(struct pipe_context *pipe, if (spt) { struct pipe_transfer *pt = &spt->base; enum pipe_format format = resource->format; + const unsigned hgt = u_minify(spr->base.height0, sr.level); + const unsigned nblocksy = util_format_get_nblocksy(format, hgt); + pipe_resource_reference(&pt->resource, resource); pt->sr = sr; pt->usage = usage; pt->box = *box; pt->stride = spr->stride[sr.level]; + pt->slice_stride = pt->stride * nblocksy; spt->offset = sp_get_tex_image_offset(spr, sr.level, sr.face, box->z); diff --git a/src/gallium/drivers/softpipe/sp_tile_cache.c b/src/gallium/drivers/softpipe/sp_tile_cache.c index f4db6f6ef00..aa76b8aa1ec 100644 --- a/src/gallium/drivers/softpipe/sp_tile_cache.c +++ b/src/gallium/drivers/softpipe/sp_tile_cache.c @@ -38,6 +38,8 @@ #include "util/u_tile.h" #include "sp_tile_cache.h" +static struct softpipe_cached_tile * +sp_alloc_tile(struct softpipe_tile_cache *tc); /** @@ -94,9 +96,19 @@ sp_create_tile_cache( struct pipe_context *pipe ) if (tc) { tc->pipe = pipe; for (pos = 0; pos < NUM_ENTRIES; pos++) { - tc->entries[pos].addr.bits.invalid = 1; + tc->tile_addrs[pos].bits.invalid = 1; + } + tc->last_tile_addr.bits.invalid = 1; + + /* this allocation allows us to guarantee that allocation + * failures are never fatal later + */ + tc->tile = MALLOC_STRUCT( softpipe_cached_tile ); + if (!tc->tile) + { + FREE(tc); + return NULL; } - tc->last_tile = &tc->entries[0]; /* any tile */ /* XXX this code prevents valgrind warnings about use of uninitialized * memory in programs that don't clear the surface before rendering. @@ -115,16 +127,21 @@ sp_create_tile_cache( struct pipe_context *pipe ) void sp_destroy_tile_cache(struct softpipe_tile_cache *tc) { - uint pos; + if (tc) { + uint pos; - for (pos = 0; pos < NUM_ENTRIES; pos++) { - /*assert(tc->entries[pos].x < 0);*/ - } - if (tc->transfer) { - tc->pipe->transfer_destroy(tc->pipe, tc->transfer); - } + for (pos = 0; pos < NUM_ENTRIES; pos++) { + /*assert(tc->entries[pos].x < 0);*/ + FREE( tc->entries[pos] ); + } + FREE( tc->tile ); + + if (tc->transfer) { + tc->pipe->transfer_destroy(tc->pipe, tc->transfer); + } - FREE( tc ); + FREE( tc ); + } } @@ -283,8 +300,15 @@ sp_tile_cache_flush_clear(struct softpipe_tile_cache *tc) uint numCleared = 0; assert(pt->resource); + if (!tc->tile) + tc->tile = sp_alloc_tile(tc); + /* clear the scratch tile to the clear value */ - clear_tile(&tc->tile, pt->resource->format, tc->clear_val); + if (tc->depth_stencil) { + clear_tile(tc->tile, pt->resource->format, tc->clear_val); + } else { + clear_tile_rgba(tc->tile, pt->resource->format, tc->clear_color); + } /* push the tile to all positions marked as clear */ for (y = 0; y < h; y += TILE_SIZE) { @@ -292,11 +316,18 @@ sp_tile_cache_flush_clear(struct softpipe_tile_cache *tc) union tile_address addr = tile_address(x, y); if (is_clear_flag_set(tc->clear_flags, addr)) { - pipe_put_tile_raw(tc->pipe, - pt, - x, y, TILE_SIZE, TILE_SIZE, - tc->tile.data.color32, 0/*STRIDE*/); - + /* write the scratch tile to the surface */ + if (tc->depth_stencil) { + pipe_put_tile_raw(tc->pipe, + pt, + x, y, TILE_SIZE, TILE_SIZE, + tc->tile->data.any, 0/*STRIDE*/); + } + else { + pipe_put_tile_rgba(tc->pipe, pt, + x, y, TILE_SIZE, TILE_SIZE, + (float *) tc->tile->data.color); + } numCleared++; } } @@ -310,6 +341,27 @@ sp_tile_cache_flush_clear(struct softpipe_tile_cache *tc) #endif } +static void +sp_flush_tile(struct softpipe_tile_cache* tc, unsigned pos) +{ + if (!tc->tile_addrs[pos].bits.invalid) { + if (tc->depth_stencil) { + pipe_put_tile_raw(tc->pipe, tc->transfer, + tc->tile_addrs[pos].bits.x * TILE_SIZE, + tc->tile_addrs[pos].bits.y * TILE_SIZE, + TILE_SIZE, TILE_SIZE, + tc->entries[pos]->data.depth32, 0/*STRIDE*/); + } + else { + pipe_put_tile_rgba(tc->pipe, tc->transfer, + tc->tile_addrs[pos].bits.x * TILE_SIZE, + tc->tile_addrs[pos].bits.y * TILE_SIZE, + TILE_SIZE, TILE_SIZE, + (float *) tc->entries[pos]->data.color); + } + tc->tile_addrs[pos].bits.invalid = 1; /* mark as empty */ + } +} /** * Flush the tile cache: write all dirty tiles back to the transfer. @@ -324,28 +376,21 @@ sp_flush_tile_cache(struct softpipe_tile_cache *tc) if (pt) { /* caching a drawing transfer */ for (pos = 0; pos < NUM_ENTRIES; pos++) { - struct softpipe_cached_tile *tile = tc->entries + pos; - if (!tile->addr.bits.invalid) { - if (tc->depth_stencil) { - pipe_put_tile_raw(tc->pipe, pt, - tile->addr.bits.x * TILE_SIZE, - tile->addr.bits.y * TILE_SIZE, - TILE_SIZE, TILE_SIZE, - tile->data.depth32, 0/*STRIDE*/); - } - else { - pipe_put_tile_rgba(tc->pipe, pt, - tile->addr.bits.x * TILE_SIZE, - tile->addr.bits.y * TILE_SIZE, - TILE_SIZE, TILE_SIZE, - (float *) tile->data.color); - } - tile->addr.bits.invalid = 1; /* mark as empty */ - inuse++; + struct softpipe_cached_tile *tile = tc->entries[pos]; + if (!tile) + { + assert(tc->tile_addrs[pos].bits.invalid); + continue; } + + sp_flush_tile(tc, pos); + ++inuse; } sp_tile_cache_flush_clear(tc); + + + tc->last_tile_addr.bits.invalid = 1; } #if 0 @@ -353,6 +398,38 @@ sp_flush_tile_cache(struct softpipe_tile_cache *tc) #endif } +static struct softpipe_cached_tile * +sp_alloc_tile(struct softpipe_tile_cache *tc) +{ + struct softpipe_cached_tile * tile = MALLOC_STRUCT(softpipe_cached_tile); + if (!tile) + { + /* in this case, steal an existing tile */ + if (!tc->tile) + { + unsigned pos; + for (pos = 0; pos < NUM_ENTRIES; ++pos) { + if (!tc->entries[pos]) + continue; + + sp_flush_tile(tc, pos); + tc->tile = tc->entries[pos]; + tc->entries[pos] = NULL; + break; + } + + /* this should never happen */ + if (!tc->tile) + abort(); + } + + tile = tc->tile; + tc->tile = NULL; + + tc->last_tile_addr.bits.invalid = 1; + } + return tile; +} /** * Get a tile from the cache. @@ -367,30 +444,35 @@ sp_find_cached_tile(struct softpipe_tile_cache *tc, /* cache pos/entry: */ const int pos = CACHE_POS(addr.bits.x, addr.bits.y); - struct softpipe_cached_tile *tile = tc->entries + pos; + struct softpipe_cached_tile *tile = tc->entries[pos]; + + if (!tile) { + tile = sp_alloc_tile(tc); + tc->entries[pos] = tile; + } - if (addr.value != tile->addr.value) { + if (addr.value != tc->tile_addrs[pos].value) { assert(pt->resource); - if (tile->addr.bits.invalid == 0) { + if (tc->tile_addrs[pos].bits.invalid == 0) { /* put dirty tile back in framebuffer */ if (tc->depth_stencil) { pipe_put_tile_raw(tc->pipe, pt, - tile->addr.bits.x * TILE_SIZE, - tile->addr.bits.y * TILE_SIZE, + tc->tile_addrs[pos].bits.x * TILE_SIZE, + tc->tile_addrs[pos].bits.y * TILE_SIZE, TILE_SIZE, TILE_SIZE, tile->data.depth32, 0/*STRIDE*/); } else { pipe_put_tile_rgba(tc->pipe, pt, - tile->addr.bits.x * TILE_SIZE, - tile->addr.bits.y * TILE_SIZE, + tc->tile_addrs[pos].bits.x * TILE_SIZE, + tc->tile_addrs[pos].bits.y * TILE_SIZE, TILE_SIZE, TILE_SIZE, (float *) tile->data.color); } } - tile->addr = addr; + tc->tile_addrs[pos] = addr; if (is_clear_flag_set(tc->clear_flags, addr)) { /* don't get tile from framebuffer, just clear it */ @@ -406,15 +488,15 @@ sp_find_cached_tile(struct softpipe_tile_cache *tc, /* get new tile data from transfer */ if (tc->depth_stencil) { pipe_get_tile_raw(tc->pipe, pt, - tile->addr.bits.x * TILE_SIZE, - tile->addr.bits.y * TILE_SIZE, + tc->tile_addrs[pos].bits.x * TILE_SIZE, + tc->tile_addrs[pos].bits.y * TILE_SIZE, TILE_SIZE, TILE_SIZE, tile->data.depth32, 0/*STRIDE*/); } else { pipe_get_tile_rgba(tc->pipe, pt, - tile->addr.bits.x * TILE_SIZE, - tile->addr.bits.y * TILE_SIZE, + tc->tile_addrs[pos].bits.x * TILE_SIZE, + tc->tile_addrs[pos].bits.y * TILE_SIZE, TILE_SIZE, TILE_SIZE, (float *) tile->data.color); } @@ -422,6 +504,7 @@ sp_find_cached_tile(struct softpipe_tile_cache *tc, } tc->last_tile = tile; + tc->last_tile_addr = addr; return tile; } @@ -451,7 +534,7 @@ sp_tile_cache_clear(struct softpipe_tile_cache *tc, const float *rgba, memset(tc->clear_flags, 255, sizeof(tc->clear_flags)); for (pos = 0; pos < NUM_ENTRIES; pos++) { - struct softpipe_cached_tile *tile = tc->entries + pos; - tile->addr.bits.invalid = 1; + tc->tile_addrs[pos].bits.invalid = 1; } + tc->last_tile_addr.bits.invalid = 1; } diff --git a/src/gallium/drivers/softpipe/sp_tile_cache.h b/src/gallium/drivers/softpipe/sp_tile_cache.h index e03d53eb24e..031c7c1ea5c 100644 --- a/src/gallium/drivers/softpipe/sp_tile_cache.h +++ b/src/gallium/drivers/softpipe/sp_tile_cache.h @@ -57,7 +57,6 @@ union tile_address { struct softpipe_cached_tile { - union tile_address addr; union { float color[TILE_SIZE][TILE_SIZE][4]; uint color32[TILE_SIZE][TILE_SIZE]; @@ -83,14 +82,16 @@ struct softpipe_tile_cache struct pipe_transfer *transfer; void *transfer_map; - struct softpipe_cached_tile entries[NUM_ENTRIES]; + union tile_address tile_addrs[NUM_ENTRIES]; + struct softpipe_cached_tile *entries[NUM_ENTRIES]; uint clear_flags[(MAX_WIDTH / TILE_SIZE) * (MAX_HEIGHT / TILE_SIZE) / 32]; float clear_color[4]; /**< for color bufs */ uint clear_val; /**< for z+stencil, or packed color clear value */ boolean depth_stencil; /**< Is the surface a depth/stencil format? */ - struct softpipe_cached_tile tile; /**< scratch tile for clears */ + struct softpipe_cached_tile *tile; /**< scratch tile for clears */ + union tile_address last_tile_addr; struct softpipe_cached_tile *last_tile; /**< most recently retrieved tile */ }; @@ -147,7 +148,7 @@ sp_get_cached_tile(struct softpipe_tile_cache *tc, { union tile_address addr = tile_address( x, y ); - if (tc->last_tile->addr.value == addr.value) + if (tc->last_tile_addr.value == addr.value) return tc->last_tile; return sp_find_cached_tile( tc, addr ); |