This is an alternative to the draw module's polygon stipple stage.
The softpipe implementation here is just a test. The advantange of
using the new polygon stipple utility module (with other drivers)
is we can avoid software vertex processing in the draw module and
get much better performance.
Polygon stipple doesn't require special vertex processing like
the other draw module stage.
return;
#if 0
- softpipe_update_derived(softpipe); /* not needed?? */
+ softpipe_update_derived(softpipe, PIPE_PRIM_TRIANGLES); /* not needed?? */
#endif
if (buffers & PIPE_CLEAR_COLOR) {
#include "pipe/p_defines.h"
#include "util/u_math.h"
#include "util/u_memory.h"
+#include "util/u_pstipple.h"
#include "util/u_inlines.h"
#include "tgsi/tgsi_exec.h"
#include "sp_clear.h"
struct softpipe_context *softpipe = softpipe_context( pipe );
uint i;
+#if DO_PSTIPPLE_IN_HELPER_MODULE
+ if (softpipe->pstipple.sampler)
+ pipe->delete_sampler_state(pipe, softpipe->pstipple.sampler);
+
+ pipe_resource_reference(&softpipe->pstipple.texture, NULL);
+ pipe_sampler_view_reference(&softpipe->pstipple.sampler_view, NULL);
+#endif
+
if (softpipe->draw)
draw_destroy( softpipe->draw );
sp_init_surface_functions(softpipe);
+#if DO_PSTIPPLE_IN_HELPER_MODULE
+ /* create the polgon stipple sampler */
+ softpipe->pstipple.sampler = util_pstipple_create_sampler(&softpipe->pipe);
+#endif
+
return &softpipe->pipe;
fail:
#include "sp_quad_pipe.h"
-/** Do polygon stipple in the driver here, or in the draw module? */
-#define DO_PSTIPPLE_IN_DRAW_MODULE 1
+/** Do polygon stipple in the draw module? */
+#define DO_PSTIPPLE_IN_DRAW_MODULE 0
+
+/** Do polygon stipple with the util module? */
+#define DO_PSTIPPLE_IN_HELPER_MODULE 1
struct softpipe_vbuf_render;
struct pipe_query *render_cond_query;
uint render_cond_mode;
+ /** Polygon stipple items */
+ struct {
+ struct pipe_resource *texture;
+ struct pipe_sampler_state *sampler;
+ struct pipe_sampler_view *sampler_view;
+ } pstipple;
+
/** Software quad rendering pipeline */
struct {
struct quad_stage *shade;
sp->reduced_api_prim = u_reduced_prim(mode);
if (sp->dirty) {
- softpipe_update_derived(sp);
+ softpipe_update_derived(sp, sp->reduced_api_prim);
}
softpipe_map_transfers(sp);
sp->reduced_api_prim = u_reduced_prim(info->mode);
if (sp->dirty) {
- softpipe_update_derived(sp);
+ softpipe_update_derived(sp, sp->reduced_api_prim);
}
softpipe_map_transfers(sp);
insert_stage_at_head( sp, sp->quad.shade );
}
-#if !DO_PSTIPPLE_IN_DRAW_MODULE
+#if !DO_PSTIPPLE_IN_DRAW_MODULE && !DO_PSTIPPLE_IN_HELPER_MODULE
if (sp->rasterizer->poly_stipple_enable)
insert_stage_at_head( sp, sp->quad.pstipple );
#endif
struct softpipe_context *sp = setup->softpipe;
if (sp->dirty) {
- softpipe_update_derived(sp);
+ softpipe_update_derived(sp, sp->reduced_api_prim);
}
/* Note: nr_attrs is only used for debugging (vertex printing) */
struct sp_fragment_shader_variant_key
{
- int foo; /* XXX temporary */
+ boolean polygon_stipple;
};
struct sp_fragment_shader_variant_key key;
struct tgsi_shader_info info;
+ unsigned stipple_sampler_unit;
+
/* See comments about this elsewhere */
#if 0
struct draw_fragment_shader *draw_shader;
const struct pipe_framebuffer_state *);
void
-softpipe_update_derived(struct softpipe_context *softpipe);
+softpipe_update_derived(struct softpipe_context *softpipe, unsigned prim);
void
softpipe_draw_vbo(struct pipe_context *pipe,
softpipe_get_vbuf_vertex_info(struct softpipe_context *softpipe);
+struct sp_fragment_shader_variant *
+softpipe_find_fs_variant(struct softpipe_context *softpipe,
+ struct sp_fragment_shader *fs,
+ const struct sp_fragment_shader_variant_key *key);
+
+
struct sp_fragment_shader_variant *
softpipe_find_fs_variant(struct softpipe_context *softpipe,
struct sp_fragment_shader *fs,
*
**************************************************************************/
+#include "util/u_inlines.h"
#include "util/u_math.h"
#include "util/u_memory.h"
+#include "util/u_pstipple.h"
#include "pipe/p_shader_tokens.h"
#include "draw/draw_context.h"
#include "draw/draw_vertex.h"
static void
-update_fragment_shader(struct softpipe_context *softpipe)
+update_fragment_shader(struct softpipe_context *softpipe, unsigned prim)
{
struct sp_fragment_shader_variant_key key;
memset(&key, 0, sizeof(key));
+ if (prim == PIPE_PRIM_TRIANGLES)
+ key.polygon_stipple = softpipe->rasterizer->poly_stipple_enable;
+
if (softpipe->fs) {
softpipe->fs_variant = softpipe_find_fs_variant(softpipe,
softpipe->fs, &key);
}
+/**
+ * This should be called when the polygon stipple pattern changes.
+ * We create a new texture from the stipple pattern and create a new
+ * sampler view.
+ */
+static void
+update_polygon_stipple_pattern(struct softpipe_context *softpipe)
+{
+ struct pipe_resource *tex;
+ struct pipe_sampler_view *view;
+
+ tex = util_pstipple_create_stipple_texture(&softpipe->pipe,
+ softpipe->poly_stipple.stipple);
+ pipe_resource_reference(&softpipe->pstipple.texture, tex);
+
+ view = util_pstipple_create_sampler_view(&softpipe->pipe, tex);
+ pipe_sampler_view_reference(&softpipe->pstipple.sampler_view, view);
+}
+
+
+/**
+ * Should be called when polygon stipple is enabled/disabled or when
+ * the fragment shader changes.
+ * We add/update the fragment sampler and sampler views to sample from
+ * the polygon stipple texture. The texture unit that we use depends on
+ * the fragment shader (we need to use a unit not otherwise used by the
+ * shader).
+ */
+static void
+update_polygon_stipple_enable(struct softpipe_context *softpipe, unsigned prim)
+{
+ if (prim == PIPE_PRIM_TRIANGLES &&
+ softpipe->fs_variant->key.polygon_stipple) {
+ const unsigned unit = softpipe->fs_variant->stipple_sampler_unit;
+
+ assert(unit >= softpipe->num_fragment_samplers);
+
+ /* sampler state */
+ softpipe->fragment_samplers[unit] = softpipe->pstipple.sampler;
+
+ /* sampler view */
+ pipe_sampler_view_reference(&softpipe->fragment_sampler_views[unit],
+ softpipe->pstipple.sampler_view);
+
+ sp_tex_tile_cache_set_sampler_view(softpipe->fragment_tex_cache[unit],
+ softpipe->pstipple.sampler_view);
+
+ softpipe->dirty |= SP_NEW_SAMPLER;
+ }
+}
+
+
/* Hopefully this will remain quite simple, otherwise need to pull in
* something like the state tracker mechanism.
*/
void
-softpipe_update_derived(struct softpipe_context *softpipe)
+softpipe_update_derived(struct softpipe_context *softpipe, unsigned prim)
{
struct softpipe_screen *sp_screen = softpipe_screen(softpipe->pipe.screen);
softpipe->tex_timestamp = sp_screen->timestamp;
softpipe->dirty |= SP_NEW_TEXTURE;
}
-
+
+#if DO_PSTIPPLE_IN_HELPER_MODULE
+ if (softpipe->dirty & SP_NEW_STIPPLE)
+ /* before updating samplers! */
+ update_polygon_stipple_pattern(softpipe);
+#endif
+
if (softpipe->dirty & (SP_NEW_RASTERIZER |
SP_NEW_FS))
- update_fragment_shader(softpipe);
+ update_fragment_shader(softpipe, prim);
+
+#if DO_PSTIPPLE_IN_HELPER_MODULE
+ if (softpipe->dirty & (SP_NEW_RASTERIZER |
+ SP_NEW_STIPPLE |
+ SP_NEW_FS))
+ update_polygon_stipple_enable(softpipe, prim);
+#endif
if (softpipe->dirty & (SP_NEW_SAMPLER |
SP_NEW_TEXTURE |
#include "pipe/p_defines.h"
#include "util/u_memory.h"
#include "util/u_inlines.h"
+#include "util/u_pstipple.h"
#include "draw/draw_context.h"
#include "draw/draw_vs.h"
#include "draw/draw_gs.h"
const struct sp_fragment_shader_variant_key *key)
{
struct sp_fragment_shader_variant *var;
- struct pipe_shader_state *curfs = &fs->shader;
+ struct pipe_shader_state *stipple_fs = NULL, *curfs = &fs->shader;
+ unsigned unit = 0;
+
+ if (key->polygon_stipple) {
+ /* get new shader that implements polygon stippling */
+ stipple_fs = util_pstipple_create_fragment_shader(&softpipe->pipe,
+ curfs, &unit);
+ curfs = stipple_fs;
+ }
/* codegen, create variant object */
var = softpipe_create_fs_variant_sse(softpipe, curfs);
if (var) {
var->key = *key;
var->tokens = tgsi_dup_tokens(curfs->tokens);
+ var->stipple_sampler_unit = unit;
tgsi_scan_shader(var->tokens, &var->info);
fs->variants = var;
}
+ if (stipple_fs) {
+ free((void *) stipple_fs->tokens);
+ free(stipple_fs);
+ }
+
return var;
}