From 78ea9cee0d7fd424238ec25f9939d2c955694c0a Mon Sep 17 00:00:00 2001 From: Brian Date: Fri, 27 Jul 2007 10:10:49 -0600 Subject: Implement point/line quad clipping. Not quite as efficient as it probably could be, but sufficient for now. --- src/mesa/pipe/softpipe/sp_prim_setup.c | 89 ++++++++++++++++++++++++++-------- 1 file changed, 70 insertions(+), 19 deletions(-) (limited to 'src/mesa/pipe') diff --git a/src/mesa/pipe/softpipe/sp_prim_setup.c b/src/mesa/pipe/softpipe/sp_prim_setup.c index bb37bb9a8b..8f4fa41f44 100644 --- a/src/mesa/pipe/softpipe/sp_prim_setup.c +++ b/src/mesa/pipe/softpipe/sp_prim_setup.c @@ -43,18 +43,6 @@ #include "sp_prim_setup.h" - -/** - * Emit/render a quad. - * This passes the quad to the first stage of per-fragment operations. - */ -static INLINE void -quad_emit(struct softpipe_context *sp, struct quad_header *quad) -{ - sp->quad.first->run(sp->quad.first, quad); -} - - /** * Triangle edge info */ @@ -103,6 +91,8 @@ struct setup_stage { GLuint y_flags; GLuint mask; /**< mask of MASK_BOTTOM/TOP_LEFT/RIGHT bits */ } span; + + struct pipe_scissor_state scissor; }; @@ -116,6 +106,46 @@ static inline struct setup_stage *setup_stage( struct draw_stage *stage ) } +/** + * Clip setup->quad against the scissor/surface bounds. + */ +static INLINE void +quad_clip(struct setup_stage *setup) +{ + if (setup->quad.x0 >= setup->scissor.maxx || + setup->quad.y0 >= setup->scissor.maxy || + setup->quad.x0 + 1 < setup->scissor.minx || + setup->quad.y0 + 1 < setup->scissor.miny) { + /* totally clipped */ + setup->quad.mask = 0x0; + return; + } + if (setup->quad.x0 < setup->scissor.minx) + setup->quad.mask &= (MASK_BOTTOM_RIGHT | MASK_TOP_RIGHT); + if (setup->quad.y0 < setup->scissor.miny) + setup->quad.mask &= (MASK_TOP_LEFT | MASK_TOP_RIGHT); + if (setup->quad.x0 == setup->scissor.maxx - 1) + setup->quad.mask &= (MASK_BOTTOM_LEFT | MASK_TOP_LEFT); + if (setup->quad.y0 == setup->scissor.maxy - 1) + setup->quad.mask &= (MASK_BOTTOM_LEFT | MASK_BOTTOM_RIGHT); +} + + +/** + * Emit/render a quad. + * This passes the quad to the first stage of per-fragment operations. + */ +static INLINE void +quad_emit(struct setup_stage *setup) +{ + quad_clip(setup); + if (setup->quad.mask) { + struct softpipe_context *sp = setup->softpipe; + sp->quad.first->run(sp->quad.first, &setup->quad); + } +} + + /** * Given an X or Y coordinate, return the block/quad coordinate that it * belongs to. @@ -137,7 +167,7 @@ static void run_shader_block( struct setup_stage *setup, setup->quad.y0 = y; setup->quad.mask = mask; - quad_emit(setup->softpipe, &setup->quad); + quad_emit(setup); } @@ -694,8 +724,8 @@ plot(struct setup_stage *setup, GLint x, GLint y) { /* flush prev quad, start new quad */ - if (setup->quad.x0 != -1) - quad_emit(setup->softpipe, &setup->quad); + if (setup->quad.x0 != -1) + quad_emit(setup); setup->quad.x0 = quadX; setup->quad.y0 = quadY; @@ -832,7 +862,7 @@ setup_line(struct draw_stage *stage, struct prim_header *prim) /* draw final quad */ if (setup->quad.mask) { - quad_emit(setup->softpipe, &setup->quad); + quad_emit(setup); } } @@ -889,7 +919,7 @@ setup_point(struct draw_stage *stage, struct prim_header *prim) setup->quad.x0 = x - ix; setup->quad.y0 = y - iy; setup->quad.mask = (1 << ix) << (2 * iy); - quad_emit(setup->softpipe, &setup->quad); + quad_emit(setup); } else { const GLint ixmin = block((GLint) (x - halfSize)); @@ -951,7 +981,7 @@ setup_point(struct draw_stage *stage, struct prim_header *prim) if (setup->quad.mask) { setup->quad.x0 = ix; setup->quad.y0 = iy; - quad_emit( setup->softpipe, &setup->quad ); + quad_emit(setup); } } } @@ -985,7 +1015,7 @@ setup_point(struct draw_stage *stage, struct prim_header *prim) if (setup->quad.mask) { setup->quad.x0 = ix; setup->quad.y0 = iy; - quad_emit( setup->softpipe, &setup->quad ); + quad_emit(setup); } } } @@ -1001,6 +1031,27 @@ static void setup_begin( struct draw_stage *stage ) setup->quad.nr_attrs = setup->softpipe->nr_frag_attrs; + /* compute scissor/drawing bounds. + * XXX we should probably move this into the sp_state_derived.c file + * and only compute when scissor or setup state changes. + */ + { + const struct softpipe_context *sp = setup->softpipe; + const struct pipe_surface *surf = sp->cbuf; + if (sp->setup.scissor) { + setup->scissor.minx = MAX2(sp->scissor.minx, 0); + setup->scissor.miny = MAX2(sp->scissor.miny, 0); + setup->scissor.maxx = MIN2(sp->scissor.maxx, surf->width - 1); + setup->scissor.maxy = MIN2(sp->scissor.maxy, surf->height - 1); + } + else { + setup->scissor.minx = 0; + setup->scissor.miny = 0; + setup->scissor.maxx = surf->width - 1; + setup->scissor.maxy = surf->height - 1; + } + } + /* * XXX this is where we might map() the renderbuffers to begin * s/w rendering. -- cgit v1.2.3