diff options
author | Ben Skeggs <[email protected]> | 2008-03-25 12:14:49 +1100 |
---|---|---|
committer | Ben Skeggs <[email protected]> | 2008-03-25 12:14:49 +1100 |
commit | 9e1f7b2c57154704d5881362a44da703b7a4a00f (patch) | |
tree | 9cd0ca55f1eb9a0908ae76f65cfda107a7aec0ca /src | |
parent | 601b018a9a6143c634239d5bb51616724c2e593d (diff) | |
parent | 4654803e2595ea041ea83baf5e13e6c68890e9a7 (diff) |
Merge remote branch 'upstream/gallium-0.1' into nouveau-gallium-0.1
Diffstat (limited to 'src')
37 files changed, 1890 insertions, 245 deletions
diff --git a/src/gallium/auxiliary/cso_cache/cso_cache.c b/src/gallium/auxiliary/cso_cache/cso_cache.c index a2764b4265c..18acab09674 100644 --- a/src/gallium/auxiliary/cso_cache/cso_cache.c +++ b/src/gallium/auxiliary/cso_cache/cso_cache.c @@ -29,6 +29,7 @@ */ #include "pipe/p_util.h" +#include "pipe/p_debug.h" #include "cso_cache.h" #include "cso_hash.h" @@ -131,75 +132,77 @@ static int _cso_size_for_type(enum cso_cache_type type) static void delete_blend_state(void *state, void *data) { struct cso_blend *cso = (struct cso_blend *)state; - if (cso->delete_state && cso->data != &cso->state) + if (cso->delete_state) cso->delete_state(cso->context, cso->data); + FREE(state); } static void delete_depth_stencil_state(void *state, void *data) { struct cso_depth_stencil_alpha *cso = (struct cso_depth_stencil_alpha *)state; - if (cso->delete_state && cso->data != &cso->state) + if (cso->delete_state) cso->delete_state(cso->context, cso->data); + FREE(state); } static void delete_sampler_state(void *state, void *data) { struct cso_sampler *cso = (struct cso_sampler *)state; - if (cso->delete_state && cso->data != &cso->state) + if (cso->delete_state) cso->delete_state(cso->context, cso->data); + FREE(state); } static void delete_rasterizer_state(void *state, void *data) { struct cso_rasterizer *cso = (struct cso_rasterizer *)state; - if (cso->delete_state && cso->data != &cso->state) + if (cso->delete_state) cso->delete_state(cso->context, cso->data); + FREE(state); } static void delete_fs_state(void *state, void *data) { struct cso_fragment_shader *cso = (struct cso_fragment_shader *)state; - if (cso->delete_state && cso->data != &cso->state) + if (cso->delete_state) cso->delete_state(cso->context, cso->data); + FREE(state); } static void delete_vs_state(void *state, void *data) { struct cso_vertex_shader *cso = (struct cso_vertex_shader *)state; - if (cso->delete_state && cso->data != &cso->state) + if (cso->delete_state) cso->delete_state(cso->context, cso->data); + FREE(state); } static INLINE void delete_cso(void *state, enum cso_cache_type type) { switch (type) { - case CSO_BLEND: { + case CSO_BLEND: delete_blend_state(state, 0); - } break; - case CSO_SAMPLER: { + case CSO_SAMPLER: delete_sampler_state(state, 0); - } break; - case CSO_DEPTH_STENCIL_ALPHA: { + case CSO_DEPTH_STENCIL_ALPHA: delete_depth_stencil_state(state, 0); - } break; - case CSO_RASTERIZER: { + case CSO_RASTERIZER: delete_rasterizer_state(state, 0); - } break; - case CSO_FRAGMENT_SHADER: { + case CSO_FRAGMENT_SHADER: delete_fs_state(state, 0); - } break; - case CSO_VERTEX_SHADER: { + case CSO_VERTEX_SHADER: delete_vs_state(state, 0); - } break; + default: + assert(0); + FREE(state); } - FREE(state); } static INLINE void sanitize_hash(struct cso_hash *hash, enum cso_cache_type type, diff --git a/src/gallium/auxiliary/draw/Makefile b/src/gallium/auxiliary/draw/Makefile index 21e9f737b77..0c7ce5da5ba 100644 --- a/src/gallium/auxiliary/draw/Makefile +++ b/src/gallium/auxiliary/draw/Makefile @@ -16,6 +16,10 @@ C_SOURCES = \ draw_flatshade.c \ draw_offset.c \ draw_passthrough.c \ + draw_pt.c \ + draw_pt_vcache.c \ + draw_pt_fetch_emit.c \ + draw_pt_elts.c \ draw_prim.c \ draw_pstipple.c \ draw_stipple.c \ diff --git a/src/gallium/auxiliary/draw/SConscript b/src/gallium/auxiliary/draw/SConscript index d7fb86d992c..9b3e7247c54 100644 --- a/src/gallium/auxiliary/draw/SConscript +++ b/src/gallium/auxiliary/draw/SConscript @@ -14,7 +14,11 @@ draw = env.ConvenienceLibrary( 'draw_debug.c', 'draw_flatshade.c', 'draw_offset.c', - 'draw_passthrough.c', + 'draw_passthrough.c', # going away soon + 'draw_pt.c', + 'draw_pt_vcache.c', + 'draw_pt_fetch_emit.c', + 'draw_pt_elts.c', 'draw_prim.c', 'draw_pstipple.c', 'draw_stipple.c', diff --git a/src/gallium/auxiliary/draw/draw_aaline.c b/src/gallium/auxiliary/draw/draw_aaline.c index 6742f7f4b96..cc1873abada 100644 --- a/src/gallium/auxiliary/draw/draw_aaline.c +++ b/src/gallium/auxiliary/draw/draw_aaline.c @@ -621,7 +621,7 @@ aaline_first_line(struct draw_stage *stage, struct prim_header *header) bind_aaline_fragment_shader(aaline); aaline->state.sampler[num] = aaline->sampler_cso; - aaline->state.texture[num] = aaline->texture; + pipe_texture_reference(&aaline->state.texture[num], aaline->texture); aaline->driver_bind_sampler_states(pipe, num + 1, aaline->state.sampler); aaline->driver_set_sampler_textures(pipe, num + 1, aaline->state.texture); @@ -769,9 +769,14 @@ aaline_set_sampler_textures(struct pipe_context *pipe, unsigned num, struct pipe_texture **texture) { struct aaline_stage *aaline = aaline_stage_from_pipe(pipe); + uint i; + /* save current */ - memcpy(aaline->state.texture, texture, num * sizeof(struct pipe_texture *)); + for (i = 0; i < num; i++) { + pipe_texture_reference(&aaline->state.texture[i], texture[i]); + } aaline->num_textures = num; + /* pass-through */ aaline->driver_set_sampler_textures(aaline->pipe, num, texture); } diff --git a/src/gallium/auxiliary/draw/draw_context.c b/src/gallium/auxiliary/draw/draw_context.c index 41da93cdf83..903cc267662 100644 --- a/src/gallium/auxiliary/draw/draw_context.c +++ b/src/gallium/auxiliary/draw/draw_context.c @@ -37,10 +37,11 @@ #include "draw_vbuf.h" - struct draw_context *draw_create( void ) { struct draw_context *draw = CALLOC_STRUCT( draw_context ); + if (draw == NULL) + goto fail; #if defined(__i386__) || defined(__386__) draw->use_sse = GETENV( "GALLIUM_NOSSE" ) == NULL; @@ -61,6 +62,19 @@ struct draw_context *draw_create( void ) draw->pipeline.validate = draw_validate_stage( draw ); draw->pipeline.first = draw->pipeline.validate; + if (!draw->pipeline.wide_line || + !draw->pipeline.wide_point || + !draw->pipeline.stipple || + !draw->pipeline.unfilled || + !draw->pipeline.twoside || + !draw->pipeline.offset || + !draw->pipeline.clip || + !draw->pipeline.flatshade || + !draw->pipeline.cull || + !draw->pipeline.validate) + goto fail; + + ASSIGN_4V( draw->plane[0], -1, 0, 0, 1 ); ASSIGN_4V( draw->plane[1], 1, 0, 0, 1 ); ASSIGN_4V( draw->plane[2], 0, -1, 0, 1 ); @@ -75,6 +89,8 @@ struct draw_context *draw_create( void ) uint i; const unsigned size = (MAX_VERTEX_SIZE + 0x0f) & ~0x0f; char *tmp = align_malloc(Elements(draw->vs.queue) * size, 16); + if (!tmp) + goto fail; for (i = 0; i < Elements(draw->vs.queue); i++) draw->vs.queue[i].vertex = (struct vertex_header *)(tmp + i * size); @@ -93,22 +109,42 @@ struct draw_context *draw_create( void ) draw_vertex_cache_invalidate( draw ); draw_set_mapped_element_buffer( draw, 0, NULL ); + if (!draw_pt_init( draw )) + goto fail; + return draw; + +fail: + draw_destroy( draw ); + return NULL; } void draw_destroy( struct draw_context *draw ) { - draw->pipeline.wide_line->destroy( draw->pipeline.wide_line ); - draw->pipeline.wide_point->destroy( draw->pipeline.wide_point ); - draw->pipeline.stipple->destroy( draw->pipeline.stipple ); - draw->pipeline.unfilled->destroy( draw->pipeline.unfilled ); - draw->pipeline.twoside->destroy( draw->pipeline.twoside ); - draw->pipeline.offset->destroy( draw->pipeline.offset ); - draw->pipeline.clip->destroy( draw->pipeline.clip ); - draw->pipeline.flatshade->destroy( draw->pipeline.flatshade ); - draw->pipeline.cull->destroy( draw->pipeline.cull ); - draw->pipeline.validate->destroy( draw->pipeline.validate ); + if (!draw) + return; + + if (draw->pipeline.wide_line) + draw->pipeline.wide_line->destroy( draw->pipeline.wide_line ); + if (draw->pipeline.wide_point) + draw->pipeline.wide_point->destroy( draw->pipeline.wide_point ); + if (draw->pipeline.stipple) + draw->pipeline.stipple->destroy( draw->pipeline.stipple ); + if (draw->pipeline.unfilled) + draw->pipeline.unfilled->destroy( draw->pipeline.unfilled ); + if (draw->pipeline.twoside) + draw->pipeline.twoside->destroy( draw->pipeline.twoside ); + if (draw->pipeline.offset) + draw->pipeline.offset->destroy( draw->pipeline.offset ); + if (draw->pipeline.clip) + draw->pipeline.clip->destroy( draw->pipeline.clip ); + if (draw->pipeline.flatshade) + draw->pipeline.flatshade->destroy( draw->pipeline.flatshade ); + if (draw->pipeline.cull) + draw->pipeline.cull->destroy( draw->pipeline.cull ); + if (draw->pipeline.validate) + draw->pipeline.validate->destroy( draw->pipeline.validate ); if (draw->pipeline.aaline) draw->pipeline.aaline->destroy( draw->pipeline.aaline ); if (draw->pipeline.aapoint) @@ -117,8 +153,11 @@ void draw_destroy( struct draw_context *draw ) draw->pipeline.pstipple->destroy( draw->pipeline.pstipple ); if (draw->pipeline.rasterize) draw->pipeline.rasterize->destroy( draw->pipeline.rasterize ); + tgsi_exec_machine_free_data(&draw->machine); - align_free( draw->vs.queue[0].vertex ); /* Frees all the vertices. */ + + if (draw->vs.queue[0].vertex) + align_free( draw->vs.queue[0].vertex ); /* Frees all the vertices. */ /* Not so fast -- we're just borrowing this at the moment. * @@ -126,6 +165,8 @@ void draw_destroy( struct draw_context *draw ) draw->render->destroy( draw->render ); */ + draw_pt_destroy( draw ); + FREE( draw ); } diff --git a/src/gallium/auxiliary/draw/draw_passthrough.c b/src/gallium/auxiliary/draw/draw_passthrough.c index fdec6a591b8..dd00894c5bd 100644 --- a/src/gallium/auxiliary/draw/draw_passthrough.c +++ b/src/gallium/auxiliary/draw/draw_passthrough.c @@ -125,9 +125,9 @@ fetch_store_general( struct draw_context *draw, case PIPE_FORMAT_B8G8R8A8_UNORM: { ubyte *ub = (ubyte *) from; - attrib[0] = UBYTE_TO_FLOAT(ub[0]); + attrib[2] = UBYTE_TO_FLOAT(ub[0]); attrib[1] = UBYTE_TO_FLOAT(ub[1]); - attrib[2] = UBYTE_TO_FLOAT(ub[2]); + attrib[0] = UBYTE_TO_FLOAT(ub[2]); attrib[3] = UBYTE_TO_FLOAT(ub[3]); } break; diff --git a/src/gallium/auxiliary/draw/draw_prim.c b/src/gallium/auxiliary/draw/draw_prim.c index cb0277fb6c9..4fe0ddc02a7 100644 --- a/src/gallium/auxiliary/draw/draw_prim.c +++ b/src/gallium/auxiliary/draw/draw_prim.c @@ -526,7 +526,7 @@ draw_arrays(struct draw_context *draw, unsigned prim, /* drawing done here: */ if (!draw->rasterizer->bypass_vs || - !draw_passthrough_arrays(draw, prim, start, count)) { + !draw_pt_arrays(draw, prim, start, count)) { /* we have to run the whole pipeline */ draw_prim(draw, prim, start, count); } diff --git a/src/gallium/auxiliary/draw/draw_private.h b/src/gallium/auxiliary/draw/draw_private.h index 1c65c3d1b2a..0c5afcacfae 100644 --- a/src/gallium/auxiliary/draw/draw_private.h +++ b/src/gallium/auxiliary/draw/draw_private.h @@ -53,6 +53,9 @@ struct pipe_context; struct gallivm_prog; struct gallivm_cpu_engine; +struct draw_pt_middle_end; +struct draw_pt_front_end; + /** * Basic vertex info. * Carry some useful information around with the vertices in the prim pipe. @@ -203,8 +206,21 @@ struct draw_context /* Support prototype passthrough path: */ struct { - unsigned prim; - unsigned hw_vertex_size; + unsigned prim; /* XXX: to be removed */ + unsigned hw_vertex_size; /* XXX: to be removed */ + + struct { + struct draw_pt_middle_end *fetch_emit; + struct draw_pt_middle_end *fetch_shade_emit; + struct draw_pt_middle_end *fetch_shade_cliptest_pipeline_or_emit; + } middle; + + struct { + struct draw_pt_front_end *noop; + struct draw_pt_front_end *split_arrays; + struct draw_pt_front_end *vcache; + } front; + } pt; @@ -351,7 +367,18 @@ extern void draw_update_vertex_fetch( struct draw_context *draw ); extern boolean draw_need_pipeline(const struct draw_context *draw); -/* Prototype/hack +/* Passthrough mode (second attempt): + */ +boolean draw_pt_init( struct draw_context *draw ); +void draw_pt_destroy( struct draw_context *draw ); +boolean draw_pt_arrays( struct draw_context *draw, + unsigned prim, + unsigned start, + unsigned count ); + + + +/* Prototype/hack (DEPRECATED) */ boolean draw_passthrough_arrays(struct draw_context *draw, diff --git a/src/gallium/auxiliary/draw/draw_pstipple.c b/src/gallium/auxiliary/draw/draw_pstipple.c index bd8d3a76ae5..9cec9866408 100644 --- a/src/gallium/auxiliary/draw/draw_pstipple.c +++ b/src/gallium/auxiliary/draw/draw_pstipple.c @@ -56,6 +56,7 @@ struct pstip_fragment_shader struct pipe_shader_state state; void *driver_fs; void *pstip_fs; + uint sampler_unit; }; @@ -67,7 +68,6 @@ struct pstip_stage struct draw_stage stage; void *sampler_cso; - uint sampler_unit; struct pipe_texture *texture; uint num_samplers; uint num_textures; @@ -329,7 +329,7 @@ generate_pstip_fs(struct pstip_stage *pstip) tgsi_dump(pstip_fs.tokens, 0); #endif - pstip->sampler_unit = transform.maxSampler + 1; + pstip->fs->sampler_unit = transform.maxSampler + 1; pstip->fs->pstip_fs = pstip->driver_create_fs_state(pstip->pipe, &pstip_fs); } @@ -398,6 +398,7 @@ pstip_create_texture(struct pstip_stage *pstip) texTemp.cpp = 1; pstip->texture = screen->texture_create(screen, &texTemp); + assert(pstip->texture->refcount == 1); //pstip_update_texture(pstip); } @@ -488,11 +489,14 @@ pstip_first_tri(struct draw_stage *stage, struct prim_header *header) /* how many samplers? */ /* we'll use sampler/texture[pstip->sampler_unit] for the stipple */ num_samplers = MAX2(pstip->num_textures, pstip->num_samplers); - num_samplers = MAX2(num_samplers, pstip->sampler_unit + 1); + num_samplers = MAX2(num_samplers, pstip->fs->sampler_unit + 1); /* plug in our sampler, texture */ - pstip->state.samplers[pstip->sampler_unit] = pstip->sampler_cso; - pstip->state.textures[pstip->sampler_unit] = pstip->texture; + pstip->state.samplers[pstip->fs->sampler_unit] = pstip->sampler_cso; + pipe_texture_reference(&pstip->state.textures[pstip->fs->sampler_unit], + pstip->texture); + + assert(num_samplers <= PIPE_MAX_SAMPLERS); pstip->driver_bind_sampler_states(pipe, num_samplers, pstip->state.samplers); pstip->driver_set_sampler_textures(pipe, num_samplers, pstip->state.textures); @@ -624,8 +628,14 @@ pstip_bind_sampler_states(struct pipe_context *pipe, unsigned num, void **sampler) { struct pstip_stage *pstip = pstip_stage_from_pipe(pipe); + uint i; + /* save current */ memcpy(pstip->state.samplers, sampler, num * sizeof(void *)); + for (i = num; i < PIPE_MAX_SAMPLERS; i++) { + pstip->state.samplers[i] = NULL; + } + pstip->num_samplers = num; /* pass-through */ pstip->driver_bind_sampler_states(pstip->pipe, num, sampler); @@ -637,9 +647,18 @@ pstip_set_sampler_textures(struct pipe_context *pipe, unsigned num, struct pipe_texture **texture) { struct pstip_stage *pstip = pstip_stage_from_pipe(pipe); + uint i; + /* save current */ - memcpy(pstip->state.textures, texture, num * sizeof(struct pipe_texture *)); + for (i = 0; i < num; i++) { + pipe_texture_reference(&pstip->state.textures[i], texture[i]); + } + for (; i < PIPE_MAX_SAMPLERS; i++) { + pipe_texture_reference(&pstip->state.textures[i], NULL); + } + pstip->num_textures = num; + /* pass-through */ pstip->driver_set_sampler_textures(pstip->pipe, num, texture); } diff --git a/src/gallium/auxiliary/draw/draw_pt.c b/src/gallium/auxiliary/draw/draw_pt.c new file mode 100644 index 00000000000..d7169f78f44 --- /dev/null +++ b/src/gallium/auxiliary/draw/draw_pt.c @@ -0,0 +1,206 @@ +/************************************************************************** + * + * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. + * 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. + * + **************************************************************************/ + + /* + * Authors: + * Keith Whitwell <[email protected]> + */ + +#include "pipe/p_util.h" +#include "draw/draw_context.h" +#include "draw/draw_private.h" +#include "draw/draw_pt.h" + + +static boolean too_many_verts( struct draw_context *draw, + unsigned verts ) +{ + return verts < 1024; +} + +static boolean too_many_elts( struct draw_context *draw, + unsigned elts ) +{ + return elts < (16 * 1024); +} + + +boolean +draw_pt_arrays(struct draw_context *draw, + unsigned prim, + unsigned start, + unsigned count) +{ + const boolean pipeline = draw_need_pipeline(draw); + const boolean cliptest = !draw->rasterizer->bypass_clipping; + const boolean shading = !draw->rasterizer->bypass_vs; + struct draw_pt_front_end *frontend = NULL; + struct draw_pt_middle_end *middle = NULL; + + + /* Overall we do: + * - frontend -- prepare fetch_elts, draw_elts - eg vcache + * - middle -- fetch, shade, cliptest, viewport + * - pipeline -- the prim pipeline: clipping, wide lines, etc + * - backend -- the vbuf_render provided by the driver. + */ + + +#if 0 + if (!cliptest && !pipeline && !shading) { + /* This is the 'passthrough' path: + */ + /* Fetch user verts, emit hw verts: + */ + middle = draw->pt.middle.fetch_emit; + } + else if (!cliptest && !pipeline) { + /* Fetch user verts, run vertex shader, emit hw verts: + */ + middle = draw->pt.middle.fetch_shade_emit; + } + else if (!pipeline) { + /* Even though !pipeline, we have to run it to get clipping. We + * do know that the pipeline is just the clipping operation, but + * that probably doesn't help much. + * + * This is going to be the most important path for a lot of + * swtnl cards. + */ + /* Fetch user verts, + * run vertex shader, + * cliptest and viewport trasform + * if no clipped vertices, + * emit hw verts + * else + * run pipline + */ + middle = draw->pt.middle.fetch_shade_cliptest_pipeline_or_emit; + } + else if (!cliptest) { + /* Fetch user verts, run vertex shader, run pipeline: + */ + middle = draw->pt.middle.fetch_shade_pipeline; + } + else { + /* This is what we're currently always doing: + */ + /* Fetch user verts, run vertex shader, cliptest, run pipeline: + */ + middle = draw->pt.middle.fetch_shade_cliptest_pipeline; + } +#else + if (cliptest || pipeline || shading) + return FALSE; + + middle = draw->pt.middle.fetch_emit; +#endif + + + /* If !pipeline, need to make sure we respect the driver's limited + * capabilites to receive blocks of vertex data and elements. + */ +#if 0 + if (!pipeline) { + unsigned vertex_mode = passthrough; + unsigned nr_verts = count_vertices( draw, start, count ); + unsigned hw_prim = prim; + + if (is_elts(draw)) { + frontend = draw->pt.front.vcache; + hw_prim = reduced_prim(prim); + } + + if (too_many_verts(nr_verts)) { + /* if (is_verts(draw) && can_split(prim)) { + draw = draw_arrays_split; + } + else */ { + frontend = draw->pt.front.vcache; + hw_prim = reduced_prim(prim); + } + } + + if (too_many_elts(count)) { + + /* if (is_elts(draw) && can_split(prim)) { + draw = draw_elts_split; + } + else */ { + frontend = draw->pt.front.vcache; + hw_prim = reduced_prim(prim); + } + } + + if (!good_prim(hw_prim)) { + draw = draw->pt.front.vcache; + } + } +#else + frontend = draw->pt.front.vcache; +#endif + + frontend->prepare( frontend, middle ); + + frontend->run( frontend, + prim, + draw_pt_elt_func( draw ), + draw_pt_elt_ptr( draw, start ), + count ); + + frontend->finish( frontend ); + + return TRUE; +} + + +boolean draw_pt_init( struct draw_context *draw ) +{ + draw->pt.middle.fetch_emit = draw_pt_fetch_emit( draw ); + if (!draw->pt.middle.fetch_emit) + return FALSE; + + draw->pt.front.vcache = draw_pt_vcache(); + if (!draw->pt.front.vcache) + return FALSE; + + return TRUE; +} + + +void draw_pt_destroy( struct draw_context *draw ) +{ + if (draw->pt.middle.fetch_emit) { + draw->pt.middle.fetch_emit->destroy( draw->pt.middle.fetch_emit ); + draw->pt.middle.fetch_emit = NULL; + } + + if (draw->pt.front.vcache) { + draw->pt.front.vcache->destroy( draw->pt.front.vcache ); + draw->pt.front.vcache = NULL; + } +} diff --git a/src/gallium/auxiliary/draw/draw_pt.h b/src/gallium/auxiliary/draw/draw_pt.h new file mode 100644 index 00000000000..439fa4c8813 --- /dev/null +++ b/src/gallium/auxiliary/draw/draw_pt.h @@ -0,0 +1,118 @@ +/************************************************************************** + * + * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. + * 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. + * + **************************************************************************/ + + /* + * Authors: + * Keith Whitwell <[email protected]> + */ + +#ifndef DRAW_PT_H +#define DRAW_PT_H + +#include "pipe/p_compiler.h" + +typedef unsigned (*pt_elt_func)( const void *elts, unsigned idx ); + +struct draw_pt_middle_end; +struct draw_context; + +/* The "front end" - prepare sets of fetch, draw elements for the + * middle end. + * + * Currenly one version of this: + * - vcache - catchall implementation, decomposes to TRI/LINE/POINT prims + * Later: + * - varray, varray_split + * - velement, velement_split + * + * Currenly only using the vcache version. + */ +struct draw_pt_front_end { + void (*prepare)( struct draw_pt_front_end *, + struct draw_pt_middle_end * ); + + void (*run)( struct draw_pt_front_end *, + unsigned prim, + pt_elt_func elt_func, + const void *elt_ptr, + unsigned count ); + + void (*finish)( struct draw_pt_front_end * ); + void (*destroy)( struct draw_pt_front_end * ); +}; + + +/* The "middle end" - prepares actual hardware vertices for the + * hardware backend. + * + * Currently two versions of this: + * - fetch, vertex shade, cliptest, prim-pipeline + * - fetch, emit (ie passthrough) + * Later: + * - fetch, vertex shade, cliptest, maybe-pipeline, maybe-emit + * - fetch, vertex shade, emit + * + * Currenly only using the passthrough version. + */ +struct draw_pt_middle_end { + void (*prepare)( struct draw_pt_middle_end * ); + + void (*run)( struct draw_pt_middle_end *, + unsigned prim, + const unsigned *fetch_elts, + unsigned fetch_count, + const ushort *draw_elts, + unsigned draw_count ); + + void (*finish)( struct draw_pt_middle_end * ); + void (*destroy)( struct draw_pt_middle_end * ); +}; + + +/* The "back end" - supplied by the driver, defined in draw_vbuf.h. + * + * Not sure whether to wrap the prim pipeline up as an alternate + * backend. Would be a win for everything except pure passthrough + * mode... + */ +struct vbuf_render; + + +/* Helper functions. + */ +pt_elt_func draw_pt_elt_func( struct draw_context *draw ); +const void *draw_pt_elt_ptr( struct draw_context *draw, + unsigned start ); + +/* Implementations: + */ +struct draw_pt_front_end *draw_pt_vcache( void ); +struct draw_pt_middle_end *draw_pt_fetch_emit( struct draw_context *draw ); + + + +#endif diff --git a/src/gallium/auxiliary/draw/draw_pt_elts.c b/src/gallium/auxiliary/draw/draw_pt_elts.c new file mode 100644 index 00000000000..d49770e7b2d --- /dev/null +++ b/src/gallium/auxiliary/draw/draw_pt_elts.c @@ -0,0 +1,88 @@ +/************************************************************************** + * + * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. + * 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. + * + **************************************************************************/ + + /* + * Authors: + * Keith Whitwell <[email protected]> + */ + +#include "draw/draw_pt.h" +#include "draw/draw_private.h" + +/* Neat get_elt func that also works for varrays drawing by encoding + * the start value into a pointer. + */ + +static unsigned elt_uint( const void *elts, unsigned idx ) +{ + return *(((const uint *)elts) + idx); +} + +static unsigned elt_ushort( const void *elts, unsigned idx ) +{ + return *(((const ushort *)elts) + idx); +} + +static unsigned elt_ubyte( const void *elts, unsigned idx ) +{ + return *(((const ubyte *)elts) + idx); +} + +static unsigned elt_vert( const void *elts, unsigned idx ) +{ + return (const ubyte *)elts - (const ubyte *)NULL + idx; +} + +pt_elt_func draw_pt_elt_func( struct draw_context *draw ) +{ + switch (draw->user.eltSize) { + case 0: return elt_vert; + case 1: return elt_ubyte; + case 2: return elt_ushort; + case 4: return elt_uint; + default: return NULL; + } +} + +const void *draw_pt_elt_ptr( struct draw_context *draw, + unsigned start ) +{ + const char *elts = draw->user.elts; + + switch (draw->user.eltSize) { + case 0: + return (const void *)(((const ubyte *)NULL) + start); + case 1: + return (const void *)(((const ubyte *)elts) + start); + case 2: + return (const void *)(((const ushort *)elts) + start); + case 4: + return (const void *)(((const uint *)elts) + start); + default: + return NULL; + } +} diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c b/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c new file mode 100644 index 00000000000..64ef83d8001 --- /dev/null +++ b/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c @@ -0,0 +1,364 @@ +/************************************************************************** + * + * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. + * 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. + * + **************************************************************************/ + + /* + * Authors: + * Keith Whitwell <[email protected]> + */ + +#include "pipe/p_util.h" +#include "draw/draw_context.h" +#include "draw/draw_private.h" +#include "draw/draw_vbuf.h" +#include "draw/draw_vertex.h" +#include "draw/draw_pt.h" + +/* The simplest 'middle end' in the new vertex code. + * + * The responsibilities of a middle end are to: + * - perform vertex fetch using + * - draw vertex element/buffer state + * - a list of fetch indices we received as an input + * - run the vertex shader + * - cliptest, + * - clip coord calculation + * - viewport transformation + * - if necessary, run the primitive pipeline, passing it: + * - a linear array of vertex_header vertices constructed here + * - a set of draw indices we received as an input + * - otherwise, drive the hw backend, + * - allocate space for hardware format vertices + * - translate the vertex-shader output vertices to hw format + * - calling the backend draw functions. + * + * For convenience, we provide a helper function to drive the hardware + * backend given similar inputs to those required to run the pipeline. + * + * In the case of passthrough mode, many of these actions are disabled + * or noops, so we end up doing: + * + * - perform vertex fetch + * - drive the hw backend + * + * IE, basically just vertex fetch to post-vs-format vertices, + * followed by a call to the backend helper function. + */ + + +struct fetch_emit_middle_end { + struct draw_pt_middle_end base; + struct draw_context *draw; + + struct { + const ubyte *ptr; + unsigned pitch; + void (*fetch)( const void *from, float *attrib); + void (*emit)( const float *attrib, float **out ); + } fetch[PIPE_ATTRIB_MAX]; + + unsigned nr_fetch; + unsigned hw_vertex_size; +}; + + +static void fetch_B8G8R8A8_UNORM( const void *from, + float *attrib ) +{ + ubyte *ub = (ubyte *) from; + attrib[2] = UBYTE_TO_FLOAT(ub[0]); + attrib[1] = UBYTE_TO_FLOAT(ub[1]); + attrib[0] = UBYTE_TO_FLOAT(ub[2]); + attrib[3] = UBYTE_TO_FLOAT(ub[3]); +} + +static void fetch_R32G32B32A32_FLOAT( const void *from, + float *attrib ) +{ + float *f = (float *) from; + attrib[0] = f[0]; + attrib[1] = f[1]; + attrib[2] = f[2]; + attrib[3] = f[3]; +} + +static void fetch_R32G32B32_FLOAT( const void *from, + float *attrib ) +{ + float *f = (float *) from; + attrib[0] = f[0]; + attrib[1] = f[1]; + attrib[2] = f[2]; + attrib[3] = 1.0; +} + +static void fetch_R32G32_FLOAT( const void *from, + float *attrib ) +{ + float *f = (float *) from; + attrib[0] = f[0]; + attrib[1] = f[1]; + attrib[2] = 0.0; + attrib[3] = 1.0; +} + +static void fetch_R32_FLOAT( const void *from, + float *attrib ) +{ + float *f = (float *) from; + attrib[0] = f[0]; + attrib[1] = 0.0; + attrib[2] = 0.0; + attrib[3] = 1.0; +} + + +static void emit_R32_FLOAT( const float *attrib, + float **out ) +{ + (*out)[0] = attrib[0]; + (*out) += 1; +} + +static void emit_R32G32_FLOAT( const float *attrib, + float **out ) +{ + (*out)[0] = attrib[0]; + (*out)[1] = attrib[1]; + (*out) += 2; +} + +static void emit_R32G32B32_FLOAT( const float *attrib, + float **out ) +{ + (*out)[0] = attrib[0]; + (*out)[1] = attrib[1]; + (*out)[2] = attrib[2]; + (*out) += 3; +} + +static void emit_R32G32B32A32_FLOAT( const float *attrib, + float **out ) +{ + (*out)[0] = attrib[0]; + (*out)[1] = attrib[1]; + (*out)[2] = attrib[2]; + (*out)[3] = attrib[3]; + (*out) += 4; +} + + +/** + * General-purpose fetch from user's vertex arrays, emit to driver's + * vertex buffer. + * + * XXX this is totally temporary. + */ +static void +fetch_store_general( struct fetch_emit_middle_end *feme, + void *out_ptr, + const unsigned *fetch_elts, + unsigned count ) +{ + float *out = (float *)out_ptr; + struct vbuf_render *render = feme->draw->render; + uint i, j; + + for (i = 0; i < count; i++) { + unsigned elt = fetch_elts[i]; + + for (j = 0; j < feme->nr_fetch; j++) { + float attrib[4]; + const ubyte *from = (feme->fetch[j].ptr + + feme->fetch[j].pitch * elt); + + feme->fetch[j].fetch( from, attrib ); + feme->fetch[j].emit( attrib, &out ); + } + } +} + + + +static void fetch_emit_prepare( struct draw_pt_middle_end *middle ) +{ + static const float zero = 0; + struct fetch_emit_middle_end *feme = (struct fetch_emit_middle_end *)middle; + struct draw_context *draw = feme->draw; + const struct vertex_info *vinfo = draw->render->get_vertex_info(draw->render); + unsigned nr_attrs = vinfo->num_attribs; + unsigned i; + + for (i = 0; i < nr_attrs; i++) { + unsigned src_element = vinfo->src_index[i]; + unsigned src_buffer = draw->vertex_element[src_element].vertex_buffer_index; + + feme->fetch[i].ptr = ((const ubyte *)draw->user.vbuffer[src_buffer] + + draw->vertex_buffer[src_buffer].buffer_offset + + draw->vertex_element[src_element].src_offset); + + feme->fetch[i].pitch = draw->vertex_buffer[src_buffer].pitch; + + switch (draw->vertex_element[src_element].src_format) { + case PIPE_FORMAT_B8G8R8A8_UNORM: + feme->fetch[i].fetch = fetch_B8G8R8A8_UNORM; + break; + case PIPE_FORMAT_R32G32B32A32_FLOAT: + feme->fetch[i].fetch = fetch_R32G32B32A32_FLOAT; + break; + case PIPE_FORMAT_R32G32B32_FLOAT: + feme->fetch[i].fetch = fetch_R32G32B32_FLOAT; + break; + case PIPE_FORMAT_R32G32_FLOAT: + feme->fetch[i].fetch = fetch_R32G32_FLOAT; + break; + case PIPE_FORMAT_R32_FLOAT: + feme->fetch[i].fetch = fetch_R32_FLOAT; + break; + default: + assert(0); + feme->fetch[i].fetch = NULL; + break; + } + + switch (vinfo->emit[i]) { + case EMIT_4F: + feme->fetch[i].emit = emit_R32G32B32A32_FLOAT; + break; + case EMIT_3F: + feme->fetch[i].emit = emit_R32G32B32_FLOAT; + break; + case EMIT_2F: + feme->fetch[i].emit = emit_R32G32_FLOAT; + break; + case EMIT_1F: + feme->fetch[i].emit = emit_R32_FLOAT; + break; + case EMIT_HEADER: + feme->fetch[i].ptr = (const ubyte *)&zero; + feme->fetch[i].pitch = 0; + feme->fetch[i].fetch = fetch_R32_FLOAT; + feme->fetch[i].emit = emit_R32_FLOAT; + break; + case EMIT_1F_PSIZE: + feme->fetch[i].ptr = (const ubyte *)&feme->draw->rasterizer->point_size; + feme->fetch[i].pitch = 0; + feme->fetch[i].fetch = fetch_R32_FLOAT; + feme->fetch[i].emit = emit_R32_FLOAT; + default: + assert(0); + feme->fetch[i].emit = NULL; + break; + } + } + + feme->nr_fetch = nr_attrs; + feme->hw_vertex_size = vinfo->size * 4; +} + + + + + +static void fetch_emit_run( struct draw_pt_middle_end *middle, + unsigned prim, + const unsigned *fetch_elts, + unsigned fetch_count, + const ushort *draw_elts, + unsigned draw_count ) +{ + struct fetch_emit_middle_end *feme = (struct fetch_emit_middle_end *)middle; + struct draw_context *draw = feme->draw; + void *hw_verts; + boolean ok; + + ok = draw->render->set_primitive( draw->render, + prim ); + if (!ok) { + assert(0); + return; + } + + + hw_verts = draw->render->allocate_vertices( draw->render, + (ushort)feme->hw_vertex_size, + (ushort)fetch_count ); + if (!hw_verts) { + assert(0); + return; + } + + + /* Single routine to fetch vertices and emit HW verts. + */ + fetch_store_general( feme, + hw_verts, + fetch_elts, + fetch_count ); + + /* XXX: Draw arrays path to avoid re-emitting index list again and + * again. + */ + draw->render->draw( draw->render, + draw_elts, + draw_count ); + + /* Done -- that was easy, wasn't it: + */ + draw->render->release_vertices( draw->render, + hw_verts, + feme->hw_vertex_size, + fetch_count ); + +} + + + +static void fetch_emit_finish( struct draw_pt_middle_end *middle ) +{ + /* nothing to do */ +} + +static void fetch_emit_destroy( struct draw_pt_middle_end *middle ) +{ + FREE(middle); +} + + +struct draw_pt_middle_end *draw_pt_fetch_emit( struct draw_context *draw ) +{ + struct fetch_emit_middle_end *fetch_emit = CALLOC_STRUCT( fetch_emit_middle_end ); + + fetch_emit->base.prepare = fetch_emit_prepare; + fetch_emit->base.run = fetch_emit_run; + fetch_emit->base.finish = fetch_emit_finish; + fetch_emit->base.destroy = fetch_emit_destroy; + + fetch_emit->draw = draw; + + return &fetch_emit->base; +} + diff --git a/src/gallium/auxiliary/draw/draw_pt_vcache.c b/src/gallium/auxiliary/draw/draw_pt_vcache.c new file mode 100644 index 00000000000..98c22eb4d4a --- /dev/null +++ b/src/gallium/auxiliary/draw/draw_pt_vcache.c @@ -0,0 +1,337 @@ +/************************************************************************** + * + * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. + * 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. + * + **************************************************************************/ + + /* + * Authors: + * Keith Whitwell <[email protected]> + */ + +#include "pipe/p_util.h" +#include "draw/draw_context.h" +#include "draw/draw_private.h" +//#include "draw/draw_vbuf.h" +//#include "draw/draw_vertex.h" +#include "draw/draw_pt.h" + + +#define CACHE_MAX 32 +#define FETCH_MAX 128 +#define DRAW_MAX (16*1024) + +struct vcache_frontend { + struct draw_pt_front_end base; + + unsigned in[CACHE_MAX]; + ushort out[CACHE_MAX]; + + ushort draw_elts[DRAW_MAX]; + unsigned fetch_elts[FETCH_MAX]; + + unsigned draw_count; + unsigned fetch_count; + + pt_elt_func elt_func; + const void *elt_ptr; + + struct draw_pt_middle_end *middle; + unsigned output_prim; +}; + +static void vcache_flush( struct vcache_frontend *vcache ) +{ +#if 0 + /* Should always be true if output_prim == input_prim, otherwise + * not so much... + */ + unsigned i; + for (i = 0; i < vcache->draw_count; i++) { + assert( vcache->fetch_elts[vcache->draw_elts[i]] == + vcache->elt_func(vcache->elt_ptr, i) ); + } +#endif + + if (vcache->draw_count) { + vcache->middle->run( vcache->middle, + vcache->output_prim, + vcache->fetch_elts, + vcache->fetch_count, + vcache->draw_elts, + vcache->draw_count ); + } + + memset(vcache->in, ~0, sizeof(vcache->in)); + vcache->fetch_count = 0; + vcache->draw_count = 0; +} + +static void vcache_check_flush( struct vcache_frontend *vcache ) +{ + if ( vcache->draw_count + 6 >= DRAW_MAX || + vcache->fetch_count + 4 >= FETCH_MAX ) + { + vcache_flush( vcache ); + } +} + + +static void vcache_elt( struct vcache_frontend *vcache, + unsigned felt ) +{ + unsigned idx = felt % CACHE_MAX; + + if (vcache->in[idx] != felt) { + assert(vcache->fetch_count < FETCH_MAX); + + vcache->in[idx] = felt; + vcache->out[idx] = vcache->fetch_count; + vcache->fetch_elts[vcache->fetch_count++] = felt; + } + + vcache->draw_elts[vcache->draw_count++] = vcache->out[idx]; +} + +static void vcache_triangle( struct vcache_frontend *vcache, + unsigned i0, + unsigned i1, + unsigned i2 ) +{ + /* TODO: encode edgeflags in draw_elts */ + vcache_elt(vcache, i0); + vcache_elt(vcache, i1); + vcache_elt(vcache, i2); + vcache_check_flush(vcache); +} + +static void vcache_line( struct vcache_frontend *vcache, + boolean reset, + unsigned i0, + unsigned i1 ) +{ + /* TODO: encode reset-line-stipple in draw_elts */ + (void) reset; + vcache_elt(vcache, i0); + vcache_elt(vcache, i1); + vcache_check_flush(vcache); +} + + +static void vcache_point( struct vcache_frontend *vcache, + unsigned i0 ) +{ + vcache_elt(vcache, i0); + vcache_check_flush(vcache); +} + +static void vcache_quad( struct vcache_frontend *vcache, + unsigned i0, + unsigned i1, + unsigned i2, + unsigned i3 ) +{ + vcache_triangle( vcache, i0, i1, i3 ); + vcache_triangle( vcache, i1, i2, i3 ); +} + + +static void vcache_prepare( struct draw_pt_front_end *frontend, + struct draw_pt_middle_end *middle ) +{ + struct vcache_frontend *vcache = (struct vcache_frontend *)frontend; + vcache->middle = middle; + middle->prepare( middle ); +} + +static unsigned reduced_prim[PIPE_PRIM_POLYGON + 1] = { + PIPE_PRIM_POINTS, + PIPE_PRIM_LINES, + PIPE_PRIM_LINES, + PIPE_PRIM_LINES, + PIPE_PRIM_TRIANGLES, + PIPE_PRIM_TRIANGLES, + PIPE_PRIM_TRIANGLES, + PIPE_PRIM_TRIANGLES, + PIPE_PRIM_TRIANGLES, + PIPE_PRIM_TRIANGLES +}; + + +static void vcache_run( struct draw_pt_front_end *frontend, + unsigned prim, + pt_elt_func get_elt, + const void *elts, + unsigned count ) +{ + struct vcache_frontend *vcache = (struct vcache_frontend *)frontend; + unsigned i; + + /* These are for validation only: + */ + vcache->elt_func = get_elt; + vcache->elt_ptr = elts; + vcache->output_prim = reduced_prim[prim]; + + switch (prim) { + case PIPE_PRIM_POINTS: + for (i = 0; i < count; i ++) { + vcache_point( vcache, + get_elt(elts, i) ); + } + break; + + case PIPE_PRIM_LINES: + for (i = 0; i+1 < count; i += 2) { + vcache_line( vcache, + TRUE, + get_elt(elts, i + 0), + get_elt(elts, i + 1)); + } + break; + + case PIPE_PRIM_LINE_LOOP: + if (count >= 2) { + for (i = 1; i < count; i++) { + vcache_line( vcache, + i == 1, /* XXX: only if vb not split */ + get_elt(elts, i - 1), + get_elt(elts, i) ); + } + + vcache_line( vcache, + 0, + get_elt(elts, count - 1), + get_elt(elts, 0) ); + } + break; + + case PIPE_PRIM_LINE_STRIP: + for (i = 1; i < count; i++) { + vcache_line( vcache, + i == 1, + get_elt(elts, i - 1), + get_elt(elts, i) ); + } + break; + + case PIPE_PRIM_TRIANGLES: + for (i = 0; i+2 < count; i += 3) { + vcache_triangle( vcache, + get_elt(elts, i + 0), + get_elt(elts, i + 1), + get_elt(elts, i + 2) ); + } + break; + + case PIPE_PRIM_TRIANGLE_STRIP: + for (i = 0; i+2 < count; i++) { + if (i & 1) { + vcache_triangle( vcache, + get_elt(elts, i + 1), + get_elt(elts, i + 0), + get_elt(elts, i + 2) ); + } + else { + vcache_triangle( vcache, + get_elt(elts, i + 0), + get_elt(elts, i + 1), + get_elt(elts, i + 2) ); + } + } + break; + + case PIPE_PRIM_TRIANGLE_FAN: + for (i = 0; i+2 < count; i++) { + vcache_triangle( vcache, + get_elt(elts, 0), + get_elt(elts, i + 1), + get_elt(elts, i + 2) ); + } + break; + + + case PIPE_PRIM_QUADS: + for (i = 0; i+3 < count; i += 4) { + vcache_quad( vcache, + get_elt(elts, i + 0), + get_elt(elts, i + 1), + get_elt(elts, i + 2), + get_elt(elts, i + 3)); + } + break; + + case PIPE_PRIM_QUAD_STRIP: + for (i = 0; i+3 < count; i += 2) { + vcache_quad( vcache, + get_elt(elts, i + 2), + get_elt(elts, i + 0), + get_elt(elts, i + 1), + get_elt(elts, i + 3)); + } + break; + + case PIPE_PRIM_POLYGON: + for (i = 0; i+2 < count; i++) { + vcache_triangle( vcache, + get_elt(elts, i + 1), + get_elt(elts, i + 2), + get_elt(elts, 0)); + } + break; + + default: + assert(0); + break; + } + + vcache_flush( vcache ); +} + +static void vcache_finish( struct draw_pt_front_end *frontend ) +{ + struct vcache_frontend *vcache = (struct vcache_frontend *)frontend; + vcache->middle->finish( vcache->middle ); + vcache->middle = NULL; +} + +static void vcache_destroy( struct draw_pt_front_end *frontend ) +{ + FREE(frontend); +} + + +struct draw_pt_front_end *draw_pt_vcache( void ) +{ + struct vcache_frontend *vcache = CALLOC_STRUCT( vcache_frontend ); + + vcache->base.prepare = vcache_prepare; + vcache->base.run = vcache_run; + vcache->base.finish = vcache_finish; + vcache->base.destroy = vcache_destroy; + + memset(vcache->in, ~0, sizeof(vcache->in)); + + return &vcache->base; +} diff --git a/src/gallium/auxiliary/draw/draw_validate.c b/src/gallium/auxiliary/draw/draw_validate.c index 33e55595081..70b477ba5cc 100644 --- a/src/gallium/auxiliary/draw/draw_validate.c +++ b/src/gallium/auxiliary/draw/draw_validate.c @@ -34,20 +34,14 @@ /** - * Check if we need any special pipeline stages, or whether prims/verts - * can go through untouched. + * Check if we need any special pipeline stages, or whether + * prims/verts can go through untouched. Don't test for bypass + * clipping or vs modes, this function is just about the primitive + * pipeline stages. */ boolean draw_need_pipeline(const struct draw_context *draw) { - /* clipping */ - if (!draw->rasterizer->bypass_clipping) - return TRUE; - - /* vertex shader */ - if (!draw->rasterizer->bypass_vs) - return TRUE; - /* line stipple */ if (draw->rasterizer->line_stipple_enable && draw->line_stipple) return TRUE; @@ -72,6 +66,11 @@ draw_need_pipeline(const struct draw_context *draw) if (draw->rasterizer->poly_stipple_enable && draw->pipeline.pstipple) return TRUE; + /* unfilled polygons */ + if (draw->rasterizer->fill_cw != PIPE_POLYGON_MODE_FILL || + draw->rasterizer->fill_ccw != PIPE_POLYGON_MODE_FILL) + return TRUE; + /* polygon offset */ if (draw->rasterizer->offset_cw || draw->rasterizer->offset_ccw) return TRUE; @@ -84,9 +83,14 @@ draw_need_pipeline(const struct draw_context *draw) if (draw->rasterizer->light_twoside) return TRUE; - /* polygon cull */ + /* polygon cull - this is difficult - hardware can cull just fine + * most of the time (though sometimes CULL_NEITHER is unsupported. + * + * Generally this isn't a reason to require the pipeline, though. + * if (draw->rasterizer->cull_mode) return TRUE; + */ return FALSE; } diff --git a/src/gallium/auxiliary/draw/draw_vs_exec.c b/src/gallium/auxiliary/draw/draw_vs_exec.c index 364693e0b49..4e2fa727070 100644 --- a/src/gallium/auxiliary/draw/draw_vs_exec.c +++ b/src/gallium/auxiliary/draw/draw_vs_exec.c @@ -38,6 +38,8 @@ #include "draw_context.h" #include "draw_vs.h" +#include "tgsi/util/tgsi_parse.h" + static INLINE unsigned compute_clipmask(const float *clip, /*const*/ float plane[][4], unsigned nr) @@ -187,6 +189,7 @@ vs_exec_run( struct draw_vertex_shader *shader, static void vs_exec_delete( struct draw_vertex_shader *dvs ) { + FREE((void*) dvs->state.tokens); FREE( dvs ); } @@ -196,11 +199,13 @@ draw_create_vs_exec(struct draw_context *draw, const struct pipe_shader_state *state) { struct draw_vertex_shader *vs = CALLOC_STRUCT( draw_vertex_shader ); + uint nt = tgsi_num_tokens(state->tokens); if (vs == NULL) return NULL; - vs->state = *state; + /* we make a private copy of the tokens */ + vs->state.tokens = mem_dup(state->tokens, nt * sizeof(state->tokens[0])); vs->prepare = vs_exec_prepare; vs->run = vs_exec_run; vs->delete = vs_exec_delete; diff --git a/src/gallium/auxiliary/draw/draw_vs_llvm.c b/src/gallium/auxiliary/draw/draw_vs_llvm.c index 53c260be53a..bd983f2ddfa 100644 --- a/src/gallium/auxiliary/draw/draw_vs_llvm.c +++ b/src/gallium/auxiliary/draw/draw_vs_llvm.c @@ -38,6 +38,8 @@ #include "draw_context.h" #include "draw_vs.h" +#include "tgsi/util/tgsi_parse.h" + #ifdef MESA_LLVM #include "gallivm/gallivm.h" @@ -186,6 +188,7 @@ vs_llvm_delete( struct draw_vertex_shader *base ) /* Do something to free compiled shader: */ + FREE( (void*) shader->base.state.tokens ); FREE( shader ); } @@ -197,12 +200,14 @@ draw_create_vs_llvm(struct draw_context *draw, const struct pipe_shader_state *templ) { struct draw_llvm_vertex_shader *vs; + uint nt = tgsi_num_tokens(templ->tokens); vs = CALLOC_STRUCT( draw_llvm_vertex_shader ); if (vs == NULL) return NULL; - vs->base.state = templ; + /* we make a private copy of the tokens */ + vs->base.state.tokens = mem_dup(templ->tokens, nt * sizeof(templ->tokens[0])); vs->base.prepare = vs_llvm_prepare; vs->base.run = vs_llvm_run; vs->base.delete = vs_llvm_delete; diff --git a/src/gallium/auxiliary/draw/draw_vs_sse.c b/src/gallium/auxiliary/draw/draw_vs_sse.c index 5ee2adb3447..a4503c143ed 100644 --- a/src/gallium/auxiliary/draw/draw_vs_sse.c +++ b/src/gallium/auxiliary/draw/draw_vs_sse.c @@ -43,6 +43,7 @@ #include "rtasm/rtasm_x86sse.h" #include "tgsi/exec/tgsi_sse2.h" +#include "tgsi/util/tgsi_parse.h" typedef void (XSTDCALL *codegen_function) ( @@ -204,6 +205,7 @@ vs_sse_delete( struct draw_vertex_shader *base ) x86_release_func( &shader->sse2_program ); + FREE( (void*) shader->base.state.tokens ); FREE( shader ); } @@ -213,6 +215,7 @@ draw_create_vs_sse(struct draw_context *draw, const struct pipe_shader_state *templ) { struct draw_sse_vertex_shader *vs; + uint nt = tgsi_num_tokens(templ->tokens); if (!draw->use_sse) return NULL; @@ -221,7 +224,8 @@ draw_create_vs_sse(struct draw_context *draw, if (vs == NULL) return NULL; - vs->base.state = *templ; + /* we make a private copy of the tokens */ + vs->base.state.tokens = mem_dup(templ->tokens, nt * sizeof(templ->tokens[0])); vs->base.prepare = vs_sse_prepare; vs->base.run = vs_sse_run; vs->base.delete = vs_sse_delete; diff --git a/src/gallium/auxiliary/tgsi/util/tgsi_parse.c b/src/gallium/auxiliary/tgsi/util/tgsi_parse.c index bf6b89ce564..c3526cb71ff 100644 --- a/src/gallium/auxiliary/tgsi/util/tgsi_parse.c +++ b/src/gallium/auxiliary/tgsi/util/tgsi_parse.c @@ -317,3 +317,16 @@ tgsi_parse_token( } } + +unsigned +tgsi_num_tokens(const struct tgsi_token *tokens) +{ + struct tgsi_parse_context ctx; + if (tgsi_parse_init(&ctx, tokens) == TGSI_PARSE_OK) { + unsigned len = (ctx.FullHeader.Header.HeaderSize + + ctx.FullHeader.Header.BodySize + + 1); + return len; + } + return 0; +} diff --git a/src/gallium/auxiliary/tgsi/util/tgsi_parse.h b/src/gallium/auxiliary/tgsi/util/tgsi_parse.h index 40083728d64..a98e88e3437 100644 --- a/src/gallium/auxiliary/tgsi/util/tgsi_parse.h +++ b/src/gallium/auxiliary/tgsi/util/tgsi_parse.h @@ -113,6 +113,10 @@ void tgsi_parse_token( struct tgsi_parse_context *ctx ); +unsigned +tgsi_num_tokens(const struct tgsi_token *tokens); + + #if defined __cplusplus } #endif diff --git a/src/gallium/auxiliary/util/SConscript b/src/gallium/auxiliary/util/SConscript index b44f2d5e398..9b3929eb2d3 100644 --- a/src/gallium/auxiliary/util/SConscript +++ b/src/gallium/auxiliary/util/SConscript @@ -4,6 +4,7 @@ util = env.ConvenienceLibrary( target = 'util', source = [ 'p_debug.c', + 'p_debug_mem.c', 'p_tile.c', 'p_util.c', 'u_blit.c', diff --git a/src/gallium/auxiliary/util/p_debug.c b/src/gallium/auxiliary/util/p_debug.c index c51e9e6a692..cc036dabf82 100644 --- a/src/gallium/auxiliary/util/p_debug.c +++ b/src/gallium/auxiliary/util/p_debug.c @@ -58,7 +58,7 @@ int rpl_snprintf(char *str, size_t size, const char *format, ...); #endif -void debug_vprintf(const char *format, va_list ap) +void _debug_vprintf(const char *format, va_list ap) { #ifdef WIN32 #ifndef WINCE @@ -76,15 +76,7 @@ void debug_vprintf(const char *format, va_list ap) } -void debug_printf(const char *format, ...) -{ - va_list ap; - va_start(ap, format); - debug_vprintf(format, ap); - va_end(ap); -} - - +#ifdef DEBUG void debug_print_blob( const char *name, const void *blob, unsigned size ) @@ -99,12 +91,10 @@ void debug_print_blob( const char *name, debug_printf("%d:\t%08x\n", i, ublob[i]); } } +#endif -/* TODO: implement a debug_abort that calls EngBugCheckEx on WIN32 */ - - -static INLINE void debug_break(void) +void _debug_break(void) { #if (defined(__i386__) || defined(__386__)) && defined(__GNUC__) __asm("int3"); @@ -117,6 +107,150 @@ static INLINE void debug_break(void) #endif } + +#ifdef WIN32 +static const char * +find(const char *start, const char *end, char c) +{ + const char *p; + for(p = start; !end || p != end; ++p) { + if(*p == c) + return p; + if(*p < 32) + break; + } + return NULL; +} + +static int +compare(const char *start, const char *end, const char *s) +{ + const char *p, *q; + for(p = start, q = s; p != end && *q != '\0'; ++p, ++q) { + if(*p != *q) + return 0; + } + return p == end && *q == '\0'; +} + +static void +copy(char *dst, const char *start, const char *end, size_t n) +{ + const char *p; + char *q; + for(p = start, q = dst, n = n - 1; p != end && n; ++p, ++q, --n) + *q = *p; + *q = '\0'; +} +#endif + + +const char * +debug_get_option(const char *name, const char *dfault) +{ + const char *result; +#ifdef WIN32 + ULONG_PTR iFile = 0; + const void *pMap = NULL; + const char *sol, *eol, *sep; + static char output[1024]; + + pMap = EngMapFile(L"\\??\\c:\\gallium.cfg", 0, &iFile); + if(!pMap) + result = dfault; + else { + sol = (const char *)pMap; + while(1) { + /* TODO: handle LF line endings */ + eol = find(sol, NULL, '\r'); + if(!eol || eol == sol) + break; + sep = find(sol, eol, '='); + if(!sep) + break; + if(compare(sol, sep, name)) { + copy(output, sep + 1, eol, sizeof(output)); + result = output; + break; + } + sol = eol + 2; + } + EngUnmapFile(iFile); + } +#else + + result = getenv(name); + if(!result) + result = dfault; +#endif + + if(result) + debug_printf("%s: %s = %s\n", __FUNCTION__, name, result); + else + debug_printf("%s: %s = (null)\n", __FUNCTION__, name); + + return result; +} + +boolean +debug_get_bool_option(const char *name, boolean dfault) +{ + const char *str = debug_get_option(name, NULL); + boolean result; + + if(str == NULL) + result = dfault; + else if(!strcmp(str, "no")) + result = FALSE; + else if(!strcmp(str, "0")) + result = FALSE; + else if(!strcmp(str, "f")) + result = FALSE; + else if(!strcmp(str, "false")) + result = FALSE; + else + result = TRUE; + + debug_printf("%s: %s = %s\n", __FUNCTION__, name, result ? "TRUE" : "FALSE"); + + return result; +} + + +long +debug_get_num_option(const char *name, long dfault) +{ + /* FIXME */ + return dfault; +} + + +unsigned long +debug_get_flags_option(const char *name, + const struct debug_named_value *flags, + unsigned long dfault) +{ + unsigned long result; + const char *str; + + str = debug_get_option(name, NULL); + if(!str) + result = dfault; + else { + result = 0; + while( flags->name ) { + if (!strcmp(str, "all") || strstr(str, flags->name )) + result |= flags->value; + ++flags; + } + } + + debug_printf("%s: %s = 0x%lx\n", __FUNCTION__, name, result); + + return result; +} + + #if defined(WIN32) ULONG_PTR debug_config_file = 0; void *mapped_config_file = 0; @@ -126,7 +260,7 @@ enum { }; /* Check for aborts enabled. */ -static unsigned abort_en() +static unsigned abort_en(void) { if (!mapped_config_file) { @@ -149,59 +283,28 @@ static unsigned abort_en() return ((((char *)mapped_config_file)[0]) - 0x30) & eAssertAbortEn; } #else /* WIN32 */ -static unsigned abort_en() +static unsigned abort_en(void) { return !GETENV("GALLIUM_ABORT_ON_ASSERT"); } #endif -void debug_assert_fail(const char *expr, const char *file, unsigned line) +void _debug_assert_fail(const char *expr, + const char *file, + unsigned line, + const char *function) { - debug_printf("%s:%i: Assertion `%s' failed.\n", file, line, expr); + _debug_printf("%s:%u:%s: Assertion `%s' failed.\n", file, line, function, expr); if (abort_en()) { debug_break(); } else { - debug_printf("continuing...\n"); + _debug_printf("continuing...\n"); } } -#define DEBUG_MASK_TABLE_SIZE 256 - - -/** - * Mask hash table. - * - * For now we just take the lower bits of the key, and do no attempt to solve - * collisions. Use a proper hash table when we have dozens of drivers. - */ -static uint32_t debug_mask_table[DEBUG_MASK_TABLE_SIZE]; - - -void debug_mask_set(uint32_t uuid, uint32_t mask) -{ - unsigned hash = uuid & (DEBUG_MASK_TABLE_SIZE - 1); - debug_mask_table[hash] = mask; -} - - -uint32_t debug_mask_get(uint32_t uuid) -{ - unsigned hash = uuid & (DEBUG_MASK_TABLE_SIZE - 1); - return debug_mask_table[hash]; -} - - -void debug_mask_vprintf(uint32_t uuid, uint32_t what, const char *format, va_list ap) -{ - uint32_t mask = debug_mask_get(uuid); - if(mask & what) - debug_vprintf(format, ap); -} - - const char * debug_dump_enum(const struct debug_named_value *names, unsigned long value) @@ -214,7 +317,7 @@ debug_dump_enum(const struct debug_named_value *names, ++names; } - snprintf(rest, sizeof(rest), "0x%08x", value); + snprintf(rest, sizeof(rest), "0x%08lx", value); return rest; } @@ -247,7 +350,7 @@ debug_dump_flags(const struct debug_named_value *names, else first = 0; - snprintf(rest, sizeof(rest), "0x%08x", value); + snprintf(rest, sizeof(rest), "0x%08lx", value); strncat(output, rest, sizeof(output)); } diff --git a/src/gallium/auxiliary/util/p_debug_mem.c b/src/gallium/auxiliary/util/p_debug_mem.c new file mode 100644 index 00000000000..c160afe5b7f --- /dev/null +++ b/src/gallium/auxiliary/util/p_debug_mem.c @@ -0,0 +1,172 @@ +/************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * 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. + * + **************************************************************************/ + +/** + * @file + * Memory debugging. + * + * @author José Fonseca <[email protected]> + */ + +#ifdef WIN32 +#include <windows.h> +#include <winddi.h> +#else +#include <stdio.h> +#include <stdlib.h> +#endif + +#include "pipe/p_debug.h" +#include "util/u_double_list.h" + + +#define DEBUG_MEMORY_MAGIC 0x6e34090aU + + +#if defined(WIN32) && !defined(WINCE) +#define real_malloc(_size) EngAllocMem(0, _size, 'D3AG') +#define real_free(_ptr) EngFreeMem(_ptr) +#else +#define real_malloc(_size) malloc(_size) +#define real_free(_ptr) free(_ptr) +#endif + + +struct debug_memory_header +{ + struct list_head head; + + unsigned long no; + const char *file; + unsigned line; + const char *function; + size_t size; + unsigned magic; +}; + +static struct list_head list = { &list, &list }; + +static unsigned long start_no = 0; +static unsigned long end_no = 0; + + +void * +debug_malloc(const char *file, unsigned line, const char *function, + size_t size) +{ + struct debug_memory_header *hdr; + + hdr = real_malloc(sizeof(*hdr) + size); + if(!hdr) + return NULL; + + hdr->no = end_no++; + hdr->file = file; + hdr->line = line; + hdr->function = function; + hdr->size = size; + hdr->magic = DEBUG_MEMORY_MAGIC; + + LIST_ADDTAIL(&hdr->head, &list); + + return (void *)((char *)hdr + sizeof(*hdr)); +} + +void +debug_free(const char *file, unsigned line, const char *function, + void *ptr) +{ + struct debug_memory_header *hdr; + + if(!ptr) + return; + + hdr = (struct debug_memory_header *)((char *)ptr - sizeof(*hdr)); + if(hdr->magic != DEBUG_MEMORY_MAGIC) { + debug_printf("%s:%u:%s: freeing bad or corrupted memory %p\n", + file, line, function, + ptr); + debug_assert(0); + return; + } + + LIST_DEL(&hdr->head); + hdr->magic = 0; + + real_free(hdr); +} + +void * +debug_calloc(const char *file, unsigned line, const char *function, + size_t count, size_t size ) +{ + void *ptr = debug_malloc( file, line, function, count * size ); + if( ptr ) + memset( ptr, 0, count * size ); + return ptr; +} + +void * +debug_realloc(const char *file, unsigned line, const char *function, + void *old_ptr, size_t old_size, size_t new_size ) +{ + void *new_ptr = NULL; + + if (new_size != 0) { + new_ptr = debug_malloc( file, line, function, new_size ); + + if( new_ptr && old_ptr ) + memcpy( new_ptr, old_ptr, old_size ); + } + + debug_free( file, line, function, old_ptr ); + return new_ptr; +} + +void +debug_memory_reset(void) +{ + start_no = end_no; +} + +void +debug_memory_report(void) +{ + struct list_head *entry; + + entry = list.prev; + for (; entry != &list; entry = entry->prev) { + struct debug_memory_header *hdr; + void *ptr; + hdr = LIST_ENTRY(struct debug_memory_header, entry, head); + ptr = (void *)((char *)hdr + sizeof(*hdr)); + if(hdr->no >= start_no) + debug_printf("%s:%u:%s: %u bytes at %p not freed\n", + hdr->file, hdr->line, hdr->function, + hdr->size, ptr); + } +} diff --git a/src/gallium/auxiliary/util/u_gen_mipmap.c b/src/gallium/auxiliary/util/u_gen_mipmap.c index cf02f00b1b7..e129c062be6 100644 --- a/src/gallium/auxiliary/util/u_gen_mipmap.c +++ b/src/gallium/auxiliary/util/u_gen_mipmap.c @@ -719,8 +719,6 @@ util_create_gen_mipmap(struct pipe_context *pipe, ctx->sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; ctx->sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE; ctx->sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST; - ctx->sampler.min_img_filter = PIPE_TEX_FILTER_LINEAR; - ctx->sampler.mag_img_filter = PIPE_TEX_FILTER_LINEAR; ctx->sampler.normalized_coords = 1; @@ -774,23 +772,23 @@ set_vertex_data(struct gen_mipmap_state *ctx, float width, float height) { void *buf; - ctx->vertices[0][0][0] = 0.0f; /*x*/ - ctx->vertices[0][0][1] = 0.0f; /*y*/ + ctx->vertices[0][0][0] = -0.5f; /*x*/ + ctx->vertices[0][0][1] = -0.5f; /*y*/ ctx->vertices[0][1][0] = 0.0f; /*s*/ ctx->vertices[0][1][1] = 0.0f; /*t*/ - ctx->vertices[1][0][0] = width; /*x*/ - ctx->vertices[1][0][1] = 0.0f; /*y*/ + ctx->vertices[1][0][0] = width - 0.5f; /*x*/ + ctx->vertices[1][0][1] = -0.5f; /*y*/ ctx->vertices[1][1][0] = 1.0f; /*s*/ ctx->vertices[1][1][1] = 0.0f; /*t*/ - ctx->vertices[2][0][0] = width; - ctx->vertices[2][0][1] = height; + ctx->vertices[2][0][0] = width - 0.5f; + ctx->vertices[2][0][1] = height - 0.5f; ctx->vertices[2][1][0] = 1.0f; ctx->vertices[2][1][1] = 1.0f; - ctx->vertices[3][0][0] = 0.0f; - ctx->vertices[3][0][1] = height; + ctx->vertices[3][0][0] = -0.5f; + ctx->vertices[3][0][1] = height - 0.5f; ctx->vertices[3][1][0] = 0.0f; ctx->vertices[3][1][1] = 1.0f; @@ -849,11 +847,13 @@ simple_viewport(struct pipe_context *pipe, uint width, uint height) * \param face which cube face to generate mipmaps for (0 for non-cube maps) * \param baseLevel the first mipmap level to use as a src * \param lastLevel the last mipmap level to generate + * \param filter the minification filter used to generate mipmap levels with + * \param filter one of PIPE_TEX_FILTER_LINEAR, PIPE_TEX_FILTER_NEAREST */ void util_gen_mipmap(struct gen_mipmap_state *ctx, struct pipe_texture *pt, - uint face, uint baseLevel, uint lastLevel) + uint face, uint baseLevel, uint lastLevel, uint filter) { struct pipe_context *pipe = ctx->pipe; struct pipe_screen *screen = pipe->screen; @@ -890,6 +890,10 @@ util_gen_mipmap(struct gen_mipmap_state *ctx, memset(&fb, 0, sizeof(fb)); fb.num_cbufs = 1; + /* set min/mag to same filter for faster sw speed */ + ctx->sampler.mag_img_filter = filter; + ctx->sampler.min_img_filter = filter; + /* * XXX for small mipmap levels, it may be faster to use the software * fallback path... diff --git a/src/gallium/auxiliary/util/u_gen_mipmap.h b/src/gallium/auxiliary/util/u_gen_mipmap.h index eeabf3bf075..bd9af54fb74 100644 --- a/src/gallium/auxiliary/util/u_gen_mipmap.h +++ b/src/gallium/auxiliary/util/u_gen_mipmap.h @@ -50,7 +50,6 @@ util_destroy_gen_mipmap(struct gen_mipmap_state *ctx); extern void util_gen_mipmap(struct gen_mipmap_state *ctx, struct pipe_texture *pt, - uint face, uint baseLevel, uint lastLevel); - + uint face, uint baseLevel, uint lastLevel, uint filter); #endif diff --git a/src/gallium/drivers/softpipe/sp_winsys.h b/src/gallium/drivers/softpipe/sp_winsys.h index fc372dba27b..291825dfe22 100644 --- a/src/gallium/drivers/softpipe/sp_winsys.h +++ b/src/gallium/drivers/softpipe/sp_winsys.h @@ -37,6 +37,12 @@ #include "pipe/p_compiler.h" /* for boolean */ + +#ifdef __cplusplus +extern "C" { +#endif + + enum pipe_format; struct softpipe_winsys { @@ -60,4 +66,8 @@ struct pipe_screen * softpipe_create_screen(struct pipe_winsys *); +#ifdef __cplusplus +} +#endif + #endif /* SP_WINSYS_H */ diff --git a/src/gallium/include/pipe/p_debug.h b/src/gallium/include/pipe/p_debug.h index 14f8056924d..577cdaebcdf 100644 --- a/src/gallium/include/pipe/p_debug.h +++ b/src/gallium/include/pipe/p_debug.h @@ -60,43 +60,102 @@ extern "C" { #endif +void _debug_vprintf(const char *format, va_list ap); + + +static INLINE void +_debug_printf(const char *format, ...) +{ + va_list ap; + va_start(ap, format); + _debug_vprintf(format, ap); + va_end(ap); +} + + /** * Print debug messages. * - * A debug message will be printed regardless of the DEBUG/NDEBUG macros. - * * The actual channel used to output debug message is platform specific. To * avoid misformating or truncation, follow these rules of thumb: * - output whole lines * - avoid outputing large strings (512 bytes is the current maximum length * that is guaranteed to be printed in all platforms) */ -void debug_printf(const char *format, ...); +static INLINE void +debug_printf(const char *format, ...) +{ +#ifdef DEBUG + va_list ap; + va_start(ap, format); + _debug_vprintf(format, ap); + va_end(ap); +#endif +} -/* Dump a blob in hex to the same place that debug_printf sends its - * messages: +#ifdef DEBUG +#define debug_vprintf(_format, _ap) _debug_vprintf(_format, _ap) +#else +#define debug_vprintf(_format, _ap) ((void)0) +#endif + + +/** + * Dump a blob in hex to the same place that debug_printf sends its + * messages. */ +#ifdef DEBUG void debug_print_blob( const char *name, const void *blob, unsigned size ); +#else +#define debug_print_blob(_name, _blob, _size) ((void)0) +#endif + + +void _debug_break(void); + /** - * @sa debug_printf + * Hard-coded breakpoint. */ -void debug_vprintf(const char *format, va_list ap); +#ifdef DEBUG +#if (defined(__i386__) || defined(__386__)) && defined(__GNUC__) +#define debug_break() __asm("int3") +#elif (defined(__i386__) || defined(__386__)) && defined(__MSC__) +#define debug_break() _asm {int 3} +#else +#define debug_break() _debug_break() +#endif +#else /* !DEBUG */ +#define debug_break() ((void)0) +#endif /* !DEBUG */ -void debug_assert_fail(const char *expr, const char *file, unsigned line); +long +debug_get_num_option(const char *name, long dfault); -/** Assert macro */ +void _debug_assert_fail(const char *expr, + const char *file, + unsigned line, + const char *function); + + +/** + * Assert macro + * + * Do not expect that the assert call terminates -- errors must be handled + * regardless of assert behavior. + */ #ifdef DEBUG -#define debug_assert(expr) ((expr) ? (void)0 : debug_assert_fail(#expr, __FILE__, __LINE__)) +#define debug_assert(expr) ((expr) ? (void)0 : _debug_assert_fail(#expr, __FILE__, __LINE__, __FUNCTION__)) #else #define debug_assert(expr) ((void)0) #endif +/** Override standard assert macro */ #ifdef assert #undef assert #endif @@ -104,72 +163,35 @@ void debug_assert_fail(const char *expr, const char *file, unsigned line); /** - * Set a channel's debug mask. - * - * uuid is just a random 32 bit integer that uniquely identifies the debugging - * channel. - * - * @note Due to current implementation issues, make sure the lower 8 bits of - * UUID are unique. + * Output the current function name. */ -void debug_mask_set(uint32_t uuid, uint32_t mask); - - -uint32_t debug_mask_get(uint32_t uuid); +#ifdef DEBUG +#define debug_checkpoint() \ + _debug_printf("%s\n", __FUNCTION__) +#else +#define debug_checkpoint() \ + ((void)0) +#endif /** - * Conditional debug output. - * - * This is just a generalization of the debug filtering mechanism used - * throughout Gallium. - * - * You use this function as: - * - * @code - * #define MYDRIVER_UUID 0x12345678 // random 32 bit identifier - * - * static void inline - * mydriver_debug(uint32_t what, const char *format, ...) - * { - * #ifdef DEBUG - * va_list ap; - * va_start(ap, format); - * debug_mask_vprintf(MYDRIVER_UUID, what, format, ap); - * va_end(ap); - * #endif - * } - * - * ... - * - * debug_mask_set(MYDRIVER_UUID, - * MYDRIVER_DEBUG_THIS | - * MYDRIVER_DEBUG_THAT | - * ... ); - * - * ... - * - * mydriver_debug(MYDRIVER_DEBUG_THIS, - * "this and this happened\n"); - * - * mydriver_debug(MYDRIVER_DEBUG_THAT, - * "that = %f\n", that); - * ... - * @endcode - * - * You can also define several variants of mydriver_debug, with hardcoded what. - * Note that although macros with variable number of arguments would accomplish - * more in less code, they are not portable. + * Output the full source code position. */ -void debug_mask_vprintf(uint32_t uuid, - uint32_t what, - const char *format, - va_list ap); +#ifdef DEBUG +#define debug_checkpoint_full() \ + _debug_printf("%s:%u:%s", __FILE__, __LINE__, __FUNCTION__) +#else +#define debug_checkpoint_full() \ + ((void)0) +#endif +/** + * Output a warning message. Muted on release version. + */ #ifdef DEBUG #define debug_warning(__msg) \ - debug_printf("%s:%i:warning: %s\n", __FILE__, __LINE__, (__msg)) + _debug_printf("%s:%u:%s: warning: %s\n", __FILE__, __LINE__, __FUNCTION__, (__msg)) #else #define debug_warning(__msg) \ ((void)0) @@ -177,6 +199,18 @@ void debug_mask_vprintf(uint32_t uuid, /** + * Output an error message. Not muted on release version. + */ +#ifdef DEBUG +#define debug_error(__msg) \ + _debug_printf("%s:%u:%s: error: %s\n", __FILE__, __LINE__, __FUNCTION__, (__msg)) +#else +#define debug_error(__msg) \ + _debug_printf("error: %s\n", __msg)) +#endif + + +/** * Used by debug_dump_enum and debug_dump_flags to describe symbols. */ struct debug_named_value @@ -225,6 +259,56 @@ debug_dump_flags(const struct debug_named_value *names, unsigned long value); +/** + * Get option. + * + * It is an alias for getenv on Linux. + * + * On Windows it reads C:\gallium.cfg, which is a text file with CR+LF line + * endings with one option per line as + * + * NAME=value + * + * This file must be terminated with an extra empty line. + */ +const char * +debug_get_option(const char *name, const char *dfault); + +boolean +debug_get_bool_option(const char *name, boolean dfault); + +long +debug_get_unsigned_option(const char *name, long dfault); + +unsigned long +debug_get_flags_option(const char *name, + const struct debug_named_value *flags, + unsigned long dfault); + + +void * +debug_malloc(const char *file, unsigned line, const char *function, + size_t size); + +void +debug_free(const char *file, unsigned line, const char *function, + void *ptr); + +void * +debug_calloc(const char *file, unsigned line, const char *function, + size_t count, size_t size ); + +void * +debug_realloc(const char *file, unsigned line, const char *function, + void *old_ptr, size_t old_size, size_t new_size ); + +void +debug_memory_reset(void); + +void +debug_memory_report(void); + + #ifdef __cplusplus } #endif diff --git a/src/gallium/include/pipe/p_util.h b/src/gallium/include/pipe/p_util.h index c2e0f8c6a5d..505626c60b5 100644 --- a/src/gallium/include/pipe/p_util.h +++ b/src/gallium/include/pipe/p_util.h @@ -39,6 +39,22 @@ extern "C" { #endif +#if defined(WIN32) && defined(DEBUG) /* memory debugging */ + +#include "p_debug.h" + +#define MALLOC( _size ) \ + debug_malloc( __FILE__, __LINE__, __FUNCTION__, _size ) +#define CALLOC( _count, _size ) \ + debug_calloc(__FILE__, __LINE__, __FUNCTION__, _count, _size ) +#define FREE( _ptr ) \ + debug_free( __FILE__, __LINE__, __FUNCTION__, _ptr ) +#define REALLOC( _ptr, _old_size, _size ) \ + debug_realloc( __FILE__, __LINE__, __FUNCTION__, _ptr, _old_size, _size ) +#define GETENV( X ) NULL + +#else + #ifdef WIN32 void * __stdcall @@ -91,10 +107,10 @@ REALLOC( void *old_ptr, unsigned old_size, unsigned new_size ) void *new_ptr = NULL; if (new_size != 0) { + unsigned copy_size = old_size < new_size ? old_size : new_size; new_ptr = MALLOC( new_size ); - - if( new_ptr && old_ptr ) { - memcpy( new_ptr, old_ptr, old_size ); + if (new_ptr && old_ptr && copy_size) { + memcpy( new_ptr, old_ptr, copy_size ); } } @@ -104,7 +120,7 @@ REALLOC( void *old_ptr, unsigned old_size, unsigned new_size ) #define GETENV( X ) NULL -#else /* WIN32 */ +#else /* !WIN32 */ #define MALLOC( SIZE ) malloc( SIZE ) @@ -116,7 +132,8 @@ REALLOC( void *old_ptr, unsigned old_size, unsigned new_size ) #define GETENV( X ) getenv( X ) -#endif /* WIN32 */ +#endif /* !WIN32 */ +#endif /* !DEBUG */ #define MALLOC_STRUCT(T) (struct T *) MALLOC(sizeof(struct T)) @@ -184,7 +201,7 @@ mem_dup(const void *src, uint size) #define MIN2( A, B ) ( (A)<(B) ? (A) : (B) ) #define MAX2( A, B ) ( (A)>(B) ? (A) : (B) ) -#define Elements(x) sizeof(x)/sizeof(*(x)) +#define Elements(x) (sizeof(x)/sizeof((x)[0])) #define Offset(TYPE, MEMBER) ((unsigned)&(((TYPE *)NULL)->MEMBER)) /** diff --git a/src/mesa/state_tracker/st_atom_texture.c b/src/mesa/state_tracker/st_atom_texture.c index 9aef30f4566..e1528c4d7b9 100644 --- a/src/mesa/state_tracker/st_atom_texture.c +++ b/src/mesa/state_tracker/st_atom_texture.c @@ -56,28 +56,27 @@ update_textures(struct st_context *st) for (unit = 0; unit < st->ctx->Const.MaxTextureCoordUnits; unit++) { const GLuint su = fprog->Base.SamplerUnits[unit]; - struct gl_texture_object *texObj = st->ctx->Texture.Unit[su]._Current; - struct st_texture_object *stObj = st_texture_object(texObj); - struct pipe_texture *pt; + struct pipe_texture *pt = NULL; - if (texObj) { - GLboolean flush, retval; + if (fprog->Base.SamplersUsed & (1 << su)) { + struct gl_texture_object *texObj = st->ctx->Texture.Unit[su]._Current; + struct st_texture_object *stObj = st_texture_object(texObj); - retval = st_finalize_texture(st->ctx, st->pipe, texObj, &flush); - if (!retval) { - /* out of mem */ - continue; + if (texObj) { + GLboolean flush, retval; + + retval = st_finalize_texture(st->ctx, st->pipe, texObj, &flush); + if (!retval) { + /* out of mem */ + continue; + } + + st->state.num_textures = unit + 1; } - st->state.num_textures = unit + 1; + pt = st_get_stobj_texture(stObj); } - /* XXX: need to ensure that textures are unbound/removed from - * this table before being deleted, otherwise the pointer - * comparison below could fail. - */ - - pt = st_get_stobj_texture(stObj); pipe_texture_reference(&st->state.sampler_texture[unit], pt); } diff --git a/src/mesa/state_tracker/st_cb_bitmap.c b/src/mesa/state_tracker/st_cb_bitmap.c index acc22d4323c..6e594398743 100644 --- a/src/mesa/state_tracker/st_cb_bitmap.c +++ b/src/mesa/state_tracker/st_cb_bitmap.c @@ -44,6 +44,7 @@ #include "st_atom_constbuf.h" #include "st_program.h" #include "st_cb_bitmap.h" +#include "st_cb_program.h" #include "st_mesa_to_tgsi.h" #include "st_texture.h" #include "pipe/p_context.h" @@ -406,7 +407,7 @@ draw_bitmap_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z, assert(height <= maxSize); cso_save_rasterizer(cso); - //cso_save_viewport(cso); + cso_save_samplers(cso); /* rasterizer state: just scissor */ { @@ -457,11 +458,9 @@ draw_bitmap_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z, /* restore state */ cso_restore_rasterizer(cso); cso_restore_samplers(cso); - //cso_restore_viewport(cso); /* shaders don't go through cso yet */ pipe->bind_fs_state(pipe, st->fp->driver_shader); pipe->bind_vs_state(pipe, st->vp->driver_shader); - pipe->set_sampler_textures(pipe, ctx->st->state.num_textures, ctx->st->state.sampler_texture); } @@ -513,7 +512,13 @@ st_destroy_bitmap(struct st_context *st) { struct pipe_context *pipe = st->pipe; - /* XXX free frag shader state */ + if (st->bitmap.combined_prog) { + st_delete_program(st->ctx, &st->bitmap.combined_prog->Base.Base); + } + + if (st->bitmap.program) { + st_delete_program(st->ctx, &st->bitmap.program->Base.Base); + } if (st->bitmap.vs) { pipe->delete_vs_state(pipe, st->bitmap.vs); diff --git a/src/mesa/state_tracker/st_cb_drawpixels.c b/src/mesa/state_tracker/st_cb_drawpixels.c index 2ebaf8a2c31..0a2d37c1178 100644 --- a/src/mesa/state_tracker/st_cb_drawpixels.c +++ b/src/mesa/state_tracker/st_cb_drawpixels.c @@ -523,6 +523,7 @@ draw_textured_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z, cso_save_rasterizer(cso); cso_save_viewport(cso); + cso_save_samplers(cso); /* rasterizer state: just scissor */ { @@ -596,13 +597,11 @@ draw_textured_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z, /* restore state */ cso_restore_rasterizer(cso); cso_restore_viewport(cso); + cso_restore_samplers(cso); /* shaders don't go through cso yet */ pipe->bind_fs_state(pipe, st->fp->driver_shader); pipe->bind_vs_state(pipe, st->vp->driver_shader); - cso_set_rasterizer(cso, &st->state.rasterizer); - cso_set_samplers(cso, PIPE_MAX_SAMPLERS, - (const struct pipe_sampler_state **) st->state.sampler_list); pipe->set_sampler_textures(pipe, ctx->st->state.num_textures, ctx->st->state.sampler_texture); } diff --git a/src/mesa/state_tracker/st_cb_program.c b/src/mesa/state_tracker/st_cb_program.c index a739fcd3362..003ec0d2b79 100644 --- a/src/mesa/state_tracker/st_cb_program.c +++ b/src/mesa/state_tracker/st_cb_program.c @@ -45,6 +45,7 @@ #include "st_context.h" #include "st_program.h" #include "st_atom_shader.h" +#include "st_cb_program.h" static GLuint SerialNo = 1; @@ -122,8 +123,8 @@ static struct gl_program *st_new_program( GLcontext *ctx, } -static void st_delete_program( GLcontext *ctx, - struct gl_program *prog ) +void +st_delete_program(GLcontext *ctx, struct gl_program *prog) { struct st_context *st = st_context(ctx); struct pipe_context *pipe = st->pipe; diff --git a/src/mesa/state_tracker/st_cb_program.h b/src/mesa/state_tracker/st_cb_program.h index 45dc753dffe..0de96f2fd22 100644 --- a/src/mesa/state_tracker/st_cb_program.h +++ b/src/mesa/state_tracker/st_cb_program.h @@ -32,5 +32,8 @@ extern void st_init_program_functions(struct dd_function_table *functions); +extern void +st_delete_program(GLcontext *ctx, struct gl_program *prog); + #endif diff --git a/src/mesa/state_tracker/st_cb_texture.c b/src/mesa/state_tracker/st_cb_texture.c index a6c1a353552..d0bc234f365 100644 --- a/src/mesa/state_tracker/st_cb_texture.c +++ b/src/mesa/state_tracker/st_cb_texture.c @@ -265,19 +265,17 @@ guess_and_alloc_texture(struct st_context *st, { GLuint firstLevel; GLuint lastLevel; - GLuint width = stImage->base.Width; - GLuint height = stImage->base.Height; - GLuint depth = stImage->base.Depth; + GLuint width = stImage->base.Width2; /* size w/out border */ + GLuint height = stImage->base.Height2; + GLuint depth = stImage->base.Depth2; GLuint i, comp_byte = 0; DBG("%s\n", __FUNCTION__); assert(!stObj->pt); - if (stImage->base.Border) - return; - - if (stImage->level > stObj->base.BaseLevel && + if (stObj->pt && + stImage->level > stObj->base.BaseLevel && (stImage->base.Width == 1 || (stObj->base.Target != GL_TEXTURE_1D && stImage->base.Height == 1) || @@ -297,7 +295,8 @@ guess_and_alloc_texture(struct st_context *st, /* Figure out image dimensions at start level. */ for (i = stImage->level; i > firstLevel; i--) { - width <<= 1; + if (width != 1) + width <<= 1; if (height != 1) height <<= 1; if (depth != 1) @@ -1448,9 +1447,9 @@ st_finalize_texture(GLcontext *ctx, stObj->pt->format != st_mesa_format_to_pipe_format(firstImage->base.TexFormat->MesaFormat) || stObj->pt->last_level != stObj->lastLevel || - stObj->pt->width[0] != firstImage->base.Width || - stObj->pt->height[0] != firstImage->base.Height || - stObj->pt->depth[0] != firstImage->base.Depth || + stObj->pt->width[0] != firstImage->base.Width2 || + stObj->pt->height[0] != firstImage->base.Height2 || + stObj->pt->depth[0] != firstImage->base.Depth2 || stObj->pt->cpp != cpp || stObj->pt->compressed != firstImage->base.IsCompressed)) { pipe_texture_release(&stObj->pt); @@ -1464,9 +1463,9 @@ st_finalize_texture(GLcontext *ctx, gl_target_to_pipe(stObj->base.Target), st_mesa_format_to_pipe_format(firstImage->base.TexFormat->MesaFormat), stObj->lastLevel, - firstImage->base.Width, - firstImage->base.Height, - firstImage->base.Depth, + firstImage->base.Width2, + firstImage->base.Height2, + firstImage->base.Depth2, comp_byte); if (!stObj->pt) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage"); diff --git a/src/mesa/state_tracker/st_context.c b/src/mesa/state_tracker/st_context.c index d9e87229764..7c183865753 100644 --- a/src/mesa/state_tracker/st_context.c +++ b/src/mesa/state_tracker/st_context.c @@ -42,6 +42,7 @@ #include "st_cb_drawpixels.h" #include "st_cb_fbo.h" #include "st_cb_feedback.h" +#include "st_cb_program.h" #include "st_cb_queryobj.h" #include "st_cb_rasterpos.h" #include "st_cb_readpixels.h" diff --git a/src/mesa/state_tracker/st_gen_mipmap.c b/src/mesa/state_tracker/st_gen_mipmap.c index 61e1d9621c1..a9319112276 100644 --- a/src/mesa/state_tracker/st_gen_mipmap.c +++ b/src/mesa/state_tracker/st_gen_mipmap.c @@ -92,7 +92,8 @@ st_render_mipmap(struct st_context *st, return FALSE; } - util_gen_mipmap(st->gen_mipmap, pt, face, baseLevel, lastLevel); + util_gen_mipmap(st->gen_mipmap, pt, face, baseLevel, lastLevel, + PIPE_TEX_FILTER_LINEAR); /* shaders don't go through CSO yet */ if (st->fp) diff --git a/src/mesa/state_tracker/st_program.h b/src/mesa/state_tracker/st_program.h index 9ef2a07eaac..63d6590540c 100644 --- a/src/mesa/state_tracker/st_program.h +++ b/src/mesa/state_tracker/st_program.h @@ -97,10 +97,6 @@ struct st_vertex_program }; -extern void -st_init_program_functions(struct dd_function_table *functions); - - static inline struct st_fragment_program * st_fragment_program( struct gl_fragment_program *fp ) { |