X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fdrivers%2Fllvmpipe%2Flp_setup_line.c;h=018130c31924a8bdb1be2e59a716b7cce59db133;hb=e26a978773ba8fbff04cd2ab3342fcb02e90c06e;hp=3b16163ba593a930796ed028dd5ef08346551515;hpb=d6b3a193d4d525c5048ebf793e6a63fd98f92d64;p=mesa.git diff --git a/src/gallium/drivers/llvmpipe/lp_setup_line.c b/src/gallium/drivers/llvmpipe/lp_setup_line.c index 3b16163ba59..018130c3192 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup_line.c +++ b/src/gallium/drivers/llvmpipe/lp_setup_line.c @@ -1,6 +1,6 @@ /************************************************************************** * - * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. + * Copyright 2007 VMware, Inc. * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a @@ -18,7 +18,7 @@ * 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 + * IN NO EVENT SHALL VMWARE 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. @@ -233,7 +233,7 @@ static void setup_line_coefficients( struct lp_setup_context *setup, -static INLINE int subpixel_snap( float a ) +static inline int subpixel_snap( float a ) { return util_iround(FIXED_ONE * a); } @@ -262,14 +262,14 @@ print_line(struct lp_setup_context *setup, } -static INLINE boolean sign(float x){ +static inline boolean sign(float x){ return x >= 0; } /* Used on positive floats only: */ -static INLINE float fracf(float f) +static inline float fracf(float f) { return f - floorf(f); } @@ -294,7 +294,7 @@ try_setup_line( struct lp_setup_context *setup, int y[4]; int i; int nr_planes = 4; - unsigned scissor_index = 0; + unsigned viewport_index = 0; unsigned layer = 0; /* linewidth should be interpreted as integer */ @@ -311,6 +311,7 @@ try_setup_line( struct lp_setup_context *setup, float y2diff; float dx, dy; float area; + const float (*pv)[4]; boolean draw_start; boolean draw_end; @@ -320,19 +321,18 @@ try_setup_line( struct lp_setup_context *setup, if (0) print_line(setup, v1, v2); - if (setup->scissor_test) { - nr_planes = 8; - if (setup->viewport_index_slot > 0) { - unsigned *udata = (unsigned*)v1[setup->viewport_index_slot]; - scissor_index = lp_clamp_scissor_idx(*udata); - } + if (setup->flatshade_first) { + pv = v1; } else { - nr_planes = 4; + pv = v2; + } + if (setup->viewport_index_slot > 0) { + unsigned *udata = (unsigned*)pv[setup->viewport_index_slot]; + viewport_index = lp_clamp_viewport_idx(*udata); } - if (setup->layer_slot > 0) { - layer = *(unsigned*)v1[setup->layer_slot]; + layer = *(unsigned*)pv[setup->layer_slot]; layer = MIN2(layer, scene->fb_max_layer); } @@ -553,7 +553,7 @@ try_setup_line( struct lp_setup_context *setup, * up needing a bottom-left fill convention, which requires * slightly different rounding. */ - int adj = (setup->pixel_offset != 0) ? 1 : 0; + int adj = (setup->bottom_edge_rule != 0) ? 1 : 0; bbox.x0 = (MIN4(x[0], x[1], x[2], x[3]) + (FIXED_ONE-1)) >> FIXED_ORDER; bbox.x1 = (MAX4(x[0], x[1], x[2], x[3]) + (FIXED_ONE-1)) >> FIXED_ORDER; @@ -573,7 +573,7 @@ try_setup_line( struct lp_setup_context *setup, return TRUE; } - if (!u_rect_test_intersection(&setup->draw_regions[scissor_index], &bbox)) { + if (!u_rect_test_intersection(&setup->draw_regions[viewport_index], &bbox)) { if (0) debug_printf("offscreen\n"); LP_COUNT(nr_culled_tris); return TRUE; @@ -584,6 +584,18 @@ try_setup_line( struct lp_setup_context *setup, bbox.x0 = MAX2(bbox.x0, 0); bbox.y0 = MAX2(bbox.y0, 0); + nr_planes = 4; + /* + * Determine how many scissor planes we need, that is drop scissor + * edges if the bounding box of the tri is fully inside that edge. + */ + if (setup->scissor_test) { + /* why not just use draw_regions */ + boolean s_planes[4]; + scissor_planes_needed(s_planes, &bbox, &setup->scissors[viewport_index]); + nr_planes += s_planes[0] + s_planes[1] + s_planes[2] + s_planes[3]; + } + line = lp_setup_alloc_triangle(scene, key->num_inputs, nr_planes, @@ -600,7 +612,8 @@ try_setup_line( struct lp_setup_context *setup, LP_COUNT(nr_tris); - if (lp_context->active_statistics_queries) { + if (lp_context->active_statistics_queries && + !llvmpipe_rasterization_disabled(lp_context)) { lp_context->pipeline_statistics.c_primitives++; } @@ -622,7 +635,6 @@ try_setup_line( struct lp_setup_context *setup, } else { line->inputs.frontfacing = TRUE; } - /* Setup parameter interpolants: */ @@ -635,20 +647,27 @@ try_setup_line( struct lp_setup_context *setup, line->inputs.disable = FALSE; line->inputs.opaque = FALSE; line->inputs.layer = layer; - + line->inputs.viewport_index = viewport_index; + + /* + * XXX: this code is mostly identical to the one in lp_setup_tri, except it + * uses 4 planes instead of 3. Could share the code (including the sse + * assembly, in fact we'd get the 4th plane for free). + * The only difference apart from storing the 4th plane would be some + * different shuffle for calculating dcdx/dcdy. + */ for (i = 0; i < 4; i++) { - /* half-edge constants, will be interated over the whole render + /* half-edge constants, will be iterated over the whole render * target. */ - plane[i].c = plane[i].dcdx * x[i] - plane[i].dcdy * y[i]; + plane[i].c = IMUL64(plane[i].dcdx, x[i]) - IMUL64(plane[i].dcdy, y[i]); - - /* correct for top-left vs. bottom-left fill convention. - */ + /* correct for top-left vs. bottom-left fill convention. + */ if (plane[i].dcdx < 0) { /* both fill conventions want this - adjust for left edges */ - plane[i].c++; + plane[i].c++; } else if (plane[i].dcdx == 0) { if (setup->pixel_offset == 0) { @@ -694,33 +713,49 @@ try_setup_line( struct lp_setup_context *setup, * Note that otherwise, the scissor planes only vary in 'C' value, * and even then only on state-changes. Could alternatively store * these planes elsewhere. + * (Or only store the c value together with a bit indicating which + * scissor edge this is, so rasterization would treat them differently + * (easier to evaluate) to ordinary planes.) */ - if (nr_planes == 8) { - const struct u_rect *scissor = - &setup->scissors[scissor_index]; - - plane[4].dcdx = -1; - plane[4].dcdy = 0; - plane[4].c = 1-scissor->x0; - plane[4].eo = 1; - - plane[5].dcdx = 1; - plane[5].dcdy = 0; - plane[5].c = scissor->x1+1; - plane[5].eo = 0; - - plane[6].dcdx = 0; - plane[6].dcdy = 1; - plane[6].c = 1-scissor->y0; - plane[6].eo = 1; - - plane[7].dcdx = 0; - plane[7].dcdy = -1; - plane[7].c = scissor->y1+1; - plane[7].eo = 0; + if (nr_planes > 4) { + /* why not just use draw_regions */ + const struct u_rect *scissor = &setup->scissors[viewport_index]; + struct lp_rast_plane *plane_s = &plane[4]; + boolean s_planes[4]; + scissor_planes_needed(s_planes, &bbox, scissor); + + if (s_planes[0]) { + plane_s->dcdx = -1 << 8; + plane_s->dcdy = 0; + plane_s->c = (1-scissor->x0) << 8; + plane_s->eo = 1 << 8; + plane_s++; + } + if (s_planes[1]) { + plane_s->dcdx = 1 << 8; + plane_s->dcdy = 0; + plane_s->c = (scissor->x1+1) << 8; + plane_s->eo = 0 << 8; + plane_s++; + } + if (s_planes[2]) { + plane_s->dcdx = 0; + plane_s->dcdy = 1 << 8; + plane_s->c = (1-scissor->y0) << 8; + plane_s->eo = 1 << 8; + plane_s++; + } + if (s_planes[3]) { + plane_s->dcdx = 0; + plane_s->dcdy = -1 << 8; + plane_s->c = (scissor->y1+1) << 8; + plane_s->eo = 0; + plane_s++; + } + assert(plane_s == &plane[nr_planes]); } - return lp_setup_bin_triangle(setup, line, &bbox, nr_planes, scissor_index); + return lp_setup_bin_triangle(setup, line, &bbox, nr_planes, viewport_index); }