diff options
Diffstat (limited to 'lib/mesa/src/gallium/drivers/llvmpipe/lp_setup.c')
-rw-r--r-- | lib/mesa/src/gallium/drivers/llvmpipe/lp_setup.c | 199 |
1 files changed, 185 insertions, 14 deletions
diff --git a/lib/mesa/src/gallium/drivers/llvmpipe/lp_setup.c b/lib/mesa/src/gallium/drivers/llvmpipe/lp_setup.c index 43177745a..50f3cea7b 100644 --- a/lib/mesa/src/gallium/drivers/llvmpipe/lp_setup.c +++ b/lib/mesa/src/gallium/drivers/llvmpipe/lp_setup.c @@ -39,6 +39,7 @@ #include "util/u_inlines.h" #include "util/u_memory.h" #include "util/u_pack_color.h" +#include "util/u_cpu_detect.h" #include "util/u_viewport.h" #include "draw/draw_pipe.h" #include "util/os_time.h" @@ -53,6 +54,7 @@ #include "lp_setup_context.h" #include "lp_screen.h" #include "lp_state.h" +#include "lp_jit.h" #include "frontend/sw_winsys.h" #include "draw/draw_context.h" @@ -84,6 +86,7 @@ lp_setup_get_empty_scene(struct lp_setup_context *setup) lp_scene_begin_binning(setup->scene, &setup->fb); + setup->scene->permit_linear_rasterizer = setup->permit_linear_rasterizer; } @@ -98,6 +101,20 @@ first_triangle( struct lp_setup_context *setup, setup->triangle( setup, v0, v1, v2 ); } +static boolean +first_rectangle( struct lp_setup_context *setup, + const float (*v0)[4], + const float (*v1)[4], + const float (*v2)[4], + const float (*v3)[4], + const float (*v4)[4], + const float (*v5)[4]) +{ + assert(setup->state == SETUP_ACTIVE); + lp_setup_choose_rect( setup ); + return setup->rect( setup, v0, v1, v2, v3, v4, v5 ); +} + static void first_line( struct lp_setup_context *setup, const float (*v0)[4], @@ -117,7 +134,8 @@ first_point( struct lp_setup_context *setup, setup->point( setup, v0 ); } -void lp_setup_reset( struct lp_setup_context *setup ) +void +lp_setup_reset( struct lp_setup_context *setup ) { unsigned i; @@ -145,6 +163,7 @@ void lp_setup_reset( struct lp_setup_context *setup ) setup->line = first_line; setup->point = first_point; setup->triangle = first_triangle; + setup->rect = first_rectangle; } @@ -576,6 +595,7 @@ lp_setup_set_triangle_state( struct lp_setup_context *setup, setup->ccw_is_frontface = ccw_is_frontface; setup->cullmode = cull_mode; setup->triangle = first_triangle; + setup->rect = first_rectangle; setup->multisample = multisample; setup->pixel_offset = half_pixel_center ? 0.5f : 0.0f; setup->bottom_edge_rule = bottom_edge_rule; @@ -588,26 +608,32 @@ lp_setup_set_triangle_state( struct lp_setup_context *setup, void lp_setup_set_line_state( struct lp_setup_context *setup, - float line_width) + float line_width, + boolean line_rectangular) { LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); setup->line_width = line_width; + setup->rectangular_lines = line_rectangular; } void lp_setup_set_point_state( struct lp_setup_context *setup, float point_size, + boolean point_tri_clip, boolean point_size_per_vertex, uint sprite_coord_enable, - uint sprite_coord_origin) + uint sprite_coord_origin, + boolean point_quad_rasterization) { LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); setup->point_size = point_size; setup->sprite_coord_enable = sprite_coord_enable; setup->sprite_coord_origin = sprite_coord_origin; + setup->point_tri_clip = point_tri_clip; setup->point_size_per_vertex = point_size_per_vertex; + setup->legacy_points = !point_quad_rasterization; } void @@ -706,7 +732,11 @@ lp_setup_set_fs_images(struct lp_setup_context *setup, if (llvmpipe_resource_is_texture(res)) { uint32_t mip_offset = lp_res->mip_offsets[image->u.tex.level]; + const uint32_t bw = util_format_get_blockwidth(image->resource->format); + const uint32_t bh = util_format_get_blockheight(image->resource->format); + jit_image->width = DIV_ROUND_UP(jit_image->width, bw); + jit_image->height = DIV_ROUND_UP(jit_image->height, bh); jit_image->width = u_minify(jit_image->width, image->u.tex.level); jit_image->height = u_minify(jit_image->height, image->u.tex.level); @@ -829,6 +859,7 @@ lp_setup_set_rasterizer_discard(struct lp_setup_context *setup, setup->line = first_line; setup->point = first_point; setup->triangle = first_triangle; + setup->rect = first_rectangle; } } @@ -842,6 +873,24 @@ lp_setup_set_vertex_info(struct lp_setup_context *setup, } +void +lp_setup_set_linear_mode( struct lp_setup_context *setup, + boolean mode ) +{ + /* The linear rasterizer requires sse2 both at compile and runtime, + * in particular for the code in lp_rast_linear_fallback.c. This + * is more than ten-year-old technology, so it's a reasonable + * baseline. + */ +#if defined(PIPE_ARCH_SSE) + setup->permit_linear_rasterizer = (mode && + util_get_cpu_caps()->has_sse2); +#else + setup->permit_linear_rasterizer = FALSE; +#endif +} + + /** * Called during state validation when LP_NEW_VIEWPORT is set. */ @@ -851,6 +900,7 @@ lp_setup_set_viewports(struct lp_setup_context *setup, const struct pipe_viewport_state *viewports) { struct llvmpipe_context *lp = llvmpipe_context(setup->pipe); + float half_height, x0, y0; unsigned i; LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); @@ -859,6 +909,26 @@ lp_setup_set_viewports(struct lp_setup_context *setup, assert(viewports); /* + * Linear rasterizer path for scissor/viewport intersection. + * + * Calculate "scissor" rect from the (first) viewport. + * Just like stored scissor rects need inclusive coords. + * For rounding, assume half pixel center (d3d9 should not end up + * with fractional viewports) - quite obviously for msaa we'd need + * fractional values here (and elsewhere for the point bounding box). + * + * See: lp_setup.c::try_update_scene_state + */ + half_height = fabsf(viewports[0].scale[1]); + x0 = viewports[0].translate[0] - viewports[0].scale[0]; + y0 = viewports[0].translate[1] - half_height; + setup->vpwh.x0 = (int)(x0 + 0.5f); + setup->vpwh.x1 = (int)(viewports[0].scale[0] * 2.0f + x0 - 0.5f); + setup->vpwh.y0 = (int)(y0 + 0.5f); + setup->vpwh.y1 = (int)(half_height * 2.0f + y0 - 0.5f); + setup->dirty |= LP_SETUP_NEW_SCISSOR; + + /* * For use in lp_state_fs.c, propagate the viewport values for all viewports. */ for (i = 0; i < num_viewports; i++) { @@ -878,7 +948,7 @@ lp_setup_set_viewports(struct lp_setup_context *setup, /** - * Called during state validation when LP_NEW_SAMPLER_VIEW is set. + * Called directly by llvmpipe_set_sampler_views */ void lp_setup_set_fragment_sampler_views(struct lp_setup_context *setup, @@ -896,6 +966,12 @@ lp_setup_set_fragment_sampler_views(struct lp_setup_context *setup, for (i = 0; i < max_tex_num; i++) { struct pipe_sampler_view *view = i < num ? views[i] : NULL; + /* We are going to overwrite/unref the current texture further below. If + * set, make sure to unmap its resource to avoid leaking previous + * mapping. */ + if (setup->fs.current_tex[i]) + llvmpipe_resource_unmap(setup->fs.current_tex[i], 0, 0); + if (view) { struct pipe_resource *res = view->texture; struct llvmpipe_resource *lp_tex = llvmpipe_resource(res); @@ -1000,13 +1076,7 @@ lp_setup_set_fragment_sampler_views(struct lp_setup_context *setup, } else { /* display target texture/surface */ - /* - * XXX: Where should this be unmapped? - */ - struct llvmpipe_screen *screen = llvmpipe_screen(res->screen); - struct sw_winsys *winsys = screen->winsys; - jit_tex->base = winsys->displaytarget_map(winsys, lp_tex->dt, - PIPE_MAP_READ); + jit_tex->base = llvmpipe_resource_map(res, 0, 0, LP_TEX_USAGE_READ); jit_tex->row_stride[0] = lp_tex->row_stride[0]; jit_tex->img_stride[0] = lp_tex->img_stride[0]; jit_tex->mip_offsets[0] = 0; @@ -1028,7 +1098,6 @@ lp_setup_set_fragment_sampler_views(struct lp_setup_context *setup, setup->dirty |= LP_SETUP_NEW_FS; } - /** * Called during state validation when LP_NEW_SAMPLER is set. */ @@ -1053,6 +1122,7 @@ lp_setup_set_fragment_sampler_state(struct lp_setup_context *setup, jit_sam->min_lod = sampler->min_lod; jit_sam->max_lod = sampler->max_lod; jit_sam->lod_bias = sampler->lod_bias; + jit_sam->max_aniso = sampler->max_anisotropy; COPY_4V(jit_sam->border_color, sampler->border_color.f); } } @@ -1061,6 +1131,8 @@ lp_setup_set_fragment_sampler_state(struct lp_setup_context *setup, } + + /** * Is the given texture referenced by any scene? * Note: we have to check all scenes including any scenes currently @@ -1289,6 +1361,7 @@ try_update_scene_state( struct lp_setup_context *setup ) memcpy(&stored->jit_context, &setup->fs.current.jit_context, sizeof setup->fs.current.jit_context); + stored->jit_context.aniso_filter_table = lp_build_sample_aniso_filter_table(); stored->variant = setup->fs.current.variant; if (!lp_scene_add_frag_shader_reference(scene, @@ -1314,6 +1387,7 @@ try_update_scene_state( struct lp_setup_context *setup ) if (setup->dirty & LP_SETUP_NEW_SCISSOR) { unsigned i; + for (i = 0; i < PIPE_MAX_VIEWPORTS; ++i) { setup->draw_regions[i] = setup->framebuffer; if (setup->scissor_test) { @@ -1321,6 +1395,35 @@ try_update_scene_state( struct lp_setup_context *setup ) &setup->draw_regions[i]); } } + if (setup->permit_linear_rasterizer) { + /* NOTE: this only takes first vp into account. */ + boolean need_vp_scissoring = !!memcmp(&setup->vpwh, &setup->framebuffer, + sizeof(setup->framebuffer)); + assert(setup->viewport_index_slot < 0); + if (need_vp_scissoring) { + u_rect_possible_intersection(&setup->vpwh, + &setup->draw_regions[0]); + } + } + else if (setup->point_tri_clip) { + /* + * for d3d-style point clipping, we're going to need + * the fake vp scissor too. Hence do the intersection with vp, + * but don't indicate this. As above this will only work for first vp + * which should be ok because we instruct draw to only skip point + * clipping when there's only one viewport (this works because d3d10 + * points are always single pixel). + * (Also note that if we have permit_linear_rasterizer this will + * cause large points to always get vp scissored, regardless the + * point_tri_clip setting.) + */ + boolean need_vp_scissoring = !!memcmp(&setup->vpwh, &setup->framebuffer, + sizeof(setup->framebuffer)); + if (need_vp_scissoring) { + u_rect_possible_intersection(&setup->vpwh, + &setup->draw_regions[0]); + } + } } setup->dirty = 0; @@ -1417,7 +1520,10 @@ lp_setup_destroy( struct lp_setup_context *setup ) util_unreference_framebuffer_state(&setup->fb); for (i = 0; i < ARRAY_SIZE(setup->fs.current_tex); i++) { - pipe_resource_reference(&setup->fs.current_tex[i], NULL); + struct pipe_resource **res_ptr = &setup->fs.current_tex[i]; + if (*res_ptr) + llvmpipe_resource_unmap(*res_ptr, 0, 0); + pipe_resource_reference(res_ptr, NULL); } for (i = 0; i < ARRAY_SIZE(setup->constants); i++) { @@ -1650,4 +1756,69 @@ lp_setup_flush_and_restart(struct lp_setup_context *setup) return TRUE; } - +void +lp_setup_add_scissor_planes(const struct u_rect *scissor, + struct lp_rast_plane *plane_s, + boolean s_planes[4], bool multisample) +{ + /* + * When rasterizing scissored tris, use the intersection of the + * triangle bounding box and the scissor rect to generate the + * scissor planes. + * + * This permits us to cut off the triangle "tails" that are present + * in the intermediate recursive levels caused when two of the + * triangles edges don't diverge quickly enough to trivially reject + * exterior blocks from the triangle. + * + * It's not really clear if it's worth worrying about these tails, + * but since we generate the planes for each scissored tri, it's + * free to trim them in this case. + * + * 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.) + */ + int adj = multisample ? 127 : 0; + if (s_planes[0]) { + int x0 = scissor->x0 - 1; + plane_s->dcdx = ~0U << 8; + plane_s->dcdy = 0; + plane_s->c = x0 << 8; + plane_s->c += adj; + plane_s->c = -plane_s->c; /* flip sign */ + plane_s->eo = 1 << 8; + plane_s++; + } + if (s_planes[1]) { + int x1 = scissor->x1; + plane_s->dcdx = 1 << 8; + plane_s->dcdy = 0; + plane_s->c = x1 << 8; + plane_s->c += 127 + adj; + plane_s->eo = 0 << 8; + plane_s++; + } + if (s_planes[2]) { + int y0 = scissor->y0 - 1; + plane_s->dcdx = 0; + plane_s->dcdy = 1 << 8; + plane_s->c = y0 << 8; + plane_s->c += adj; + plane_s->c = -plane_s->c; /* flip sign */ + plane_s->eo = 1 << 8; + plane_s++; + } + if (s_planes[3]) { + int y1 = scissor->y1; + plane_s->dcdx = 0; + plane_s->dcdy = ~0U << 8; + plane_s->c = y1 << 8; + plane_s->c += 127 + adj; + plane_s->eo = 0; + plane_s++; + } +} |