X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;ds=sidebyside;f=src%2Fgallium%2Fauxiliary%2Fdraw%2Fdraw_context.c;h=8f1189a6bda4834eeb66e32548f1b953b28a7462;hb=b4b1dcb2c152519648a52ce415dc702d8c0bc7a6;hp=d64b82b026193be8ac085f316c67519a4e18ce2e;hpb=e96f4e3b853ff5fe4d927c69695c0b5f1966d448;p=mesa.git diff --git a/src/gallium/auxiliary/draw/draw_context.c b/src/gallium/auxiliary/draw/draw_context.c index d64b82b0261..8f1189a6bda 100644 --- a/src/gallium/auxiliary/draw/draw_context.c +++ b/src/gallium/auxiliary/draw/draw_context.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. @@ -27,7 +27,7 @@ /* * Authors: - * Keith Whitwell + * Keith Whitwell */ @@ -37,7 +37,11 @@ #include "util/u_cpu_detect.h" #include "util/u_inlines.h" #include "util/u_helpers.h" +#include "util/u_prim.h" +#include "util/u_format.h" #include "draw_context.h" +#include "draw_pipe.h" +#include "draw_prim_assembler.h" #include "draw_vs.h" #include "draw_gs.h" @@ -49,20 +53,13 @@ boolean draw_get_option_use_llvm(void) { - static boolean first = TRUE; - static boolean value; - if (first) { - first = FALSE; - value = debug_get_bool_option("DRAW_USE_LLVM", TRUE); - -#ifdef PIPE_ARCH_X86 - util_cpu_detect(); - /* require SSE2 due to LLVM PR6960. */ - if (!util_cpu_caps.has_sse2) - value = FALSE; -#endif - } - return value; + return debug_get_bool_option("DRAW_USE_LLVM", TRUE); +} +#else +boolean +draw_get_option_use_llvm(void) +{ + return FALSE; } #endif @@ -71,17 +68,19 @@ draw_get_option_use_llvm(void) * Create new draw module context with gallivm state for LLVM JIT. */ static struct draw_context * -draw_create_context(struct pipe_context *pipe, boolean try_llvm) +draw_create_context(struct pipe_context *pipe, void *context, + boolean try_llvm) { struct draw_context *draw = CALLOC_STRUCT( draw_context ); - if (draw == NULL) + if (!draw) goto err_out; + /* we need correct cpu caps for disabling denorms in draw_vbo() */ + util_cpu_detect(); + #if HAVE_LLVM if (try_llvm && draw_get_option_use_llvm()) { - draw->llvm = draw_llvm_create(draw); - if (!draw->llvm) - goto err_destroy; + draw->llvm = draw_llvm_create(draw, (LLVMContextRef)context); } #endif @@ -90,6 +89,10 @@ draw_create_context(struct pipe_context *pipe, boolean try_llvm) if (!draw_init(draw)) goto err_destroy; + draw->ia = draw_prim_assembler_create(draw); + if (!draw->ia) + goto err_destroy; + return draw; err_destroy: @@ -105,17 +108,26 @@ err_out: struct draw_context * draw_create(struct pipe_context *pipe) { - return draw_create_context(pipe, TRUE); + return draw_create_context(pipe, NULL, TRUE); } +#if HAVE_LLVM +struct draw_context * +draw_create_with_llvm_context(struct pipe_context *pipe, + void *context) +{ + return draw_create_context(pipe, context, TRUE); +} +#endif + /** * Create a new draw context, without LLVM JIT. */ struct draw_context * draw_create_no_llvm(struct pipe_context *pipe) { - return draw_create_context(pipe, FALSE); + return draw_create_context(pipe, NULL, FALSE); } @@ -137,6 +149,7 @@ boolean draw_init(struct draw_context *draw) draw->clip_z = TRUE; draw->pt.user.planes = (float (*) [DRAW_TOTAL_CLIP_PLANES][4]) &(draw->plane[0]); + draw->pt.user.eltMax = ~0; if (!draw_pipeline_init( draw )) return FALSE; @@ -153,9 +166,25 @@ boolean draw_init(struct draw_context *draw) draw->quads_always_flatshade_last = !draw->pipe->screen->get_param( draw->pipe->screen, PIPE_CAP_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION); + draw->floating_point_depth = false; + return TRUE; } +/* + * Called whenever we're starting to draw a new instance. + * Some internal structures don't want to have to reset internal + * members on each invocation (because their state might have to persist + * between multiple primitive restart rendering call) but might have to + * for each new instance. + * This is particularly the case for primitive id's in geometry shader. + */ +void draw_new_instance(struct draw_context *draw) +{ + draw_geometry_shader_new_instance(draw->gs.geometry_shader); + draw_prim_assembler_new_instance(draw->ia); +} + void draw_destroy( struct draw_context *draw ) { @@ -187,6 +216,7 @@ void draw_destroy( struct draw_context *draw ) draw->render->destroy( draw->render ); */ + draw_prim_assembler_destroy(draw->ia); draw_pipeline_destroy( draw ); draw_pt_destroy( draw ); draw_vs_destroy( draw ); @@ -208,29 +238,65 @@ void draw_flush( struct draw_context *draw ) /** - * Specify the Minimum Resolvable Depth factor for polygon offset. + * Specify the depth stencil format for the draw pipeline. This function + * determines the Minimum Resolvable Depth factor for polygon offset. * This factor potentially depends on the number of Z buffer bits, * the rasterization algorithm and the arithmetic performed on Z - * values between vertex shading and rasterization. It will vary - * from one driver to another. + * values between vertex shading and rasterization. */ -void draw_set_mrd(struct draw_context *draw, double mrd) +void draw_set_zs_format(struct draw_context *draw, enum pipe_format format) { - draw->mrd = mrd; + const struct util_format_description *desc = util_format_description(format); + + draw->floating_point_depth = + (util_get_depth_format_type(desc) == UTIL_FORMAT_TYPE_FLOAT); + + draw->mrd = util_get_depth_format_mrd(desc); } -static void update_clip_flags( struct draw_context *draw ) +static bool +draw_is_vs_window_space(struct draw_context *draw) { - draw->clip_xy = !draw->driver.bypass_clip_xy; + if (draw->vs.vertex_shader) { + struct tgsi_shader_info *info = &draw->vs.vertex_shader->info; + + return info->properties[TGSI_PROPERTY_VS_WINDOW_SPACE_POSITION] != 0; + } + return false; +} + + +void +draw_update_clip_flags(struct draw_context *draw) +{ + bool window_space = draw_is_vs_window_space(draw); + + draw->clip_xy = !draw->driver.bypass_clip_xy && !window_space; draw->guard_band_xy = (!draw->driver.bypass_clip_xy && draw->driver.guard_band_xy); draw->clip_z = (!draw->driver.bypass_clip_z && - draw->rasterizer && draw->rasterizer->depth_clip); + draw->rasterizer && draw->rasterizer->depth_clip) && + !window_space; draw->clip_user = draw->rasterizer && - draw->rasterizer->clip_plane_enable != 0; + draw->rasterizer->clip_plane_enable != 0 && + !window_space; + draw->guard_band_points_xy = draw->guard_band_xy || + (draw->driver.bypass_clip_points && + (draw->rasterizer && + draw->rasterizer->point_tri_clip)); } + +void +draw_update_viewport_flags(struct draw_context *draw) +{ + bool window_space = draw_is_vs_window_space(draw); + + draw->bypass_viewport = window_space || draw->identity_viewport; +} + + /** * Register new primitive rasterization/rendering state. * This causes the drawing pipeline to be rebuilt. @@ -244,7 +310,7 @@ void draw_set_rasterizer_state( struct draw_context *draw, draw->rasterizer = raster; draw->rast_handle = rast_handle; - update_clip_flags(draw); + draw_update_clip_flags(draw); } } @@ -254,18 +320,24 @@ void draw_set_rasterizer_state( struct draw_context *draw, * Some hardware can turn off clipping altogether - in particular any * hardware with a TNL unit can do its own clipping, even if it is * relying on the draw module for some other reason. + * Setting bypass_clip_points to achieve d3d-style point clipping (the driver + * will need to do the "vp scissoring") _requires_ the driver to implement + * wide points / point sprites itself (points will still be clipped if rasterizer + * point_tri_clip isn't set). Only relevant if bypass_clip_xy isn't set. */ void draw_set_driver_clipping( struct draw_context *draw, boolean bypass_clip_xy, boolean bypass_clip_z, - boolean guard_band_xy) + boolean guard_band_xy, + boolean bypass_clip_points) { draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE ); draw->driver.bypass_clip_xy = bypass_clip_xy; draw->driver.bypass_clip_z = bypass_clip_z; draw->driver.guard_band_xy = guard_band_xy; - update_clip_flags(draw); + draw->driver.bypass_clip_points = bypass_clip_points; + draw_update_clip_flags(draw); } @@ -298,21 +370,28 @@ void draw_set_clip_state( struct draw_context *draw, /** * Set the draw module's viewport state. */ -void draw_set_viewport_state( struct draw_context *draw, - const struct pipe_viewport_state *viewport ) +void draw_set_viewport_states( struct draw_context *draw, + unsigned start_slot, + unsigned num_viewports, + const struct pipe_viewport_state *vps ) { + const struct pipe_viewport_state *viewport = vps; draw_do_flush(draw, DRAW_FLUSH_PARAMETER_CHANGE); - draw->viewport = *viewport; /* struct copy */ - draw->identity_viewport = (viewport->scale[0] == 1.0f && - viewport->scale[1] == 1.0f && - viewport->scale[2] == 1.0f && - viewport->scale[3] == 1.0f && - viewport->translate[0] == 0.0f && - viewport->translate[1] == 0.0f && - viewport->translate[2] == 0.0f && - viewport->translate[3] == 0.0f); - draw_vs_set_viewport( draw, viewport ); + debug_assert(start_slot < PIPE_MAX_VIEWPORTS); + debug_assert((start_slot + num_viewports) <= PIPE_MAX_VIEWPORTS); + + memcpy(draw->viewports + start_slot, vps, + sizeof(struct pipe_viewport_state) * num_viewports); + + draw->identity_viewport = (num_viewports == 1) && + (viewport->scale[0] == 1.0f && + viewport->scale[1] == 1.0f && + viewport->scale[2] == 1.0f && + viewport->translate[0] == 0.0f && + viewport->translate[1] == 0.0f && + viewport->translate[2] == 0.0f); + draw_update_viewport_flags(draw); } @@ -351,15 +430,17 @@ draw_set_vertex_elements(struct draw_context *draw, */ void draw_set_mapped_vertex_buffer(struct draw_context *draw, - unsigned attr, const void *buffer) + unsigned attr, const void *buffer, + size_t size) { - draw->pt.user.vbuffer[attr] = buffer; + draw->pt.user.vbuffer[attr].map = buffer; + draw->pt.user.vbuffer[attr].size = size; } void draw_set_mapped_constant_buffer(struct draw_context *draw, - unsigned shader_type, + enum pipe_shader_type shader_type, unsigned slot, const void *buffer, unsigned size ) @@ -468,14 +549,14 @@ draw_alloc_extra_vertex_attrib(struct draw_context *draw, uint n; slot = draw_find_shader_output(draw, semantic_name, semantic_index); - if (slot > 0) { + if (slot >= 0) { return slot; } num_outputs = draw_current_shader_outputs(draw); n = draw->extra_shader_outputs.num; - assert(n < Elements(draw->extra_shader_outputs.semantic_name)); + assert(n < ARRAY_SIZE(draw->extra_shader_outputs.semantic_name)); draw->extra_shader_outputs.semantic_name[n] = semantic_name; draw->extra_shader_outputs.semantic_index[n] = semantic_index; @@ -512,6 +593,28 @@ draw_get_shader_info(const struct draw_context *draw) } } +/** + * Prepare outputs slots from the draw module + * + * Certain parts of the draw module can emit additional + * outputs that can be quite useful to the backends, a good + * example of it is the process of decomposing primitives + * into wireframes (aka. lines) which normally would lose + * the face-side information, but using this method we can + * inject another shader output which passes the original + * face side information to the backend. + */ +void +draw_prepare_shader_outputs(struct draw_context *draw) +{ + draw_remove_extra_vertex_attribs(draw); + draw_prim_assembler_prepare_outputs(draw->ia); + draw_unfilled_prepare_outputs(draw, draw->pipeline.unfilled); + if (draw->pipeline.aapoint) + draw_aapoint_prepare_outputs(draw, draw->pipeline.aapoint); + if (draw->pipeline.aaline) + draw_aaline_prepare_outputs(draw, draw->pipeline.aaline); +} /** * Ask the draw module for the location/slot of the given vertex attribute in @@ -524,9 +627,10 @@ draw_get_shader_info(const struct draw_context *draw) * attributes (such as texcoords for AA lines). The driver can call this * function to find those attributes. * - * Zero is returned if the attribute is not found since this is - * a don't care / undefined situtation. Returning -1 would be a bit more - * work for the drivers. + * -1 is returned if the attribute is not found since this is + * an undefined situation. Note, that zero is valid and can + * be used by any of the attributes, because position is not + * required to be attribute 0 or even at all present. */ int draw_find_shader_output(const struct draw_context *draw, @@ -549,7 +653,7 @@ draw_find_shader_output(const struct draw_context *draw, } } - return 0; + return -1; } @@ -575,6 +679,40 @@ draw_num_shader_outputs(const struct draw_context *draw) } +/** + * Return total number of the vertex shader outputs. This function + * also counts any extra vertex output attributes that may + * be filled in by some draw stages (such as AA point, AA line, + * front face). + */ +uint +draw_total_vs_outputs(const struct draw_context *draw) +{ + const struct tgsi_shader_info *info = &draw->vs.vertex_shader->info; + + return info->num_outputs + draw->extra_shader_outputs.num; +} + +/** + * Return total number of the geometry shader outputs. This function + * also counts any extra geometry output attributes that may + * be filled in by some draw stages (such as AA point, AA line, front + * face). + */ +uint +draw_total_gs_outputs(const struct draw_context *draw) +{ + const struct tgsi_shader_info *info; + + if (!draw->gs.geometry_shader) + return 0; + + info = &draw->gs.geometry_shader->info; + + return info->num_outputs + draw->extra_shader_outputs.num; +} + + /** * Provide TGSI sampler objects for vertex/geometry shaders that use * texture fetches. This state only needs to be set once per context. @@ -582,7 +720,7 @@ draw_num_shader_outputs(const struct draw_context *draw) */ void draw_texture_sampler(struct draw_context *draw, - uint shader, + enum pipe_shader_type shader, struct tgsi_sampler *sampler) { if (shader == PIPE_SHADER_VERTEX) { @@ -593,7 +731,41 @@ draw_texture_sampler(struct draw_context *draw, } } +/** + * Provide TGSI image objects for vertex/geometry shaders that use + * texture fetches. This state only needs to be set once per context. + * This might only be used by software drivers for the time being. + */ +void +draw_image(struct draw_context *draw, + enum pipe_shader_type shader, + struct tgsi_image *image) +{ + if (shader == PIPE_SHADER_VERTEX) { + draw->vs.tgsi.image = image; + } else { + debug_assert(shader == PIPE_SHADER_GEOMETRY); + draw->gs.tgsi.image = image; + } +} +/** + * Provide TGSI buffer objects for vertex/geometry shaders that use + * load/store/atomic ops. This state only needs to be set once per context. + * This might only be used by software drivers for the time being. + */ +void +draw_buffer(struct draw_context *draw, + enum pipe_shader_type shader, + struct tgsi_buffer *buffer) +{ + if (shader == PIPE_SHADER_VERTEX) { + draw->vs.tgsi.buffer = buffer; + } else { + debug_assert(shader == PIPE_SHADER_GEOMETRY); + draw->gs.tgsi.buffer = buffer; + } +} void draw_set_render( struct draw_context *draw, @@ -612,7 +784,8 @@ void draw_set_render( struct draw_context *draw, */ void draw_set_indexes(struct draw_context *draw, - const void *elements, unsigned elem_size) + const void *elements, unsigned elem_size, + unsigned elem_buffer_space) { assert(elem_size == 0 || elem_size == 1 || @@ -620,6 +793,10 @@ draw_set_indexes(struct draw_context *draw, elem_size == 4); draw->pt.user.elts = elements; draw->pt.user.eltSizeIB = elem_size; + if (elem_size) + draw->pt.user.eltMax = elem_buffer_space / elem_size; + else + draw->pt.user.eltMax = 0; } @@ -672,18 +849,67 @@ draw_current_shader_position_output(const struct draw_context *draw) /** * Return the index of the shader output which will contain the - * vertex position. + * viewport index. + */ +uint +draw_current_shader_viewport_index_output(const struct draw_context *draw) +{ + if (draw->gs.geometry_shader) + return draw->gs.geometry_shader->viewport_index_output; + return draw->vs.vertex_shader->viewport_index_output; +} + +/** + * Returns true if there's a geometry shader bound and the geometry + * shader writes out a viewport index. + */ +boolean +draw_current_shader_uses_viewport_index(const struct draw_context *draw) +{ + if (draw->gs.geometry_shader) + return draw->gs.geometry_shader->info.writes_viewport_index; + return draw->vs.vertex_shader->info.writes_viewport_index; +} + + +/** + * Return the index of the shader output which will contain the + * clip vertex position. + * Note we don't support clipvertex output in the gs. For clipping + * to work correctly hence we return ordinary position output instead. */ uint draw_current_shader_clipvertex_output(const struct draw_context *draw) { + if (draw->gs.geometry_shader) + return draw->gs.position_output; return draw->vs.clipvertex_output; } uint -draw_current_shader_clipdistance_output(const struct draw_context *draw, int index) +draw_current_shader_ccdistance_output(const struct draw_context *draw, int index) { - return draw->vs.clipdistance_output[index]; + debug_assert(index < PIPE_MAX_CLIP_OR_CULL_DISTANCE_ELEMENT_COUNT); + if (draw->gs.geometry_shader) + return draw->gs.geometry_shader->ccdistance_output[index]; + return draw->vs.ccdistance_output[index]; +} + + +uint +draw_current_shader_num_written_clipdistances(const struct draw_context *draw) +{ + if (draw->gs.geometry_shader) + return draw->gs.geometry_shader->info.num_written_clipdistance; + return draw->vs.vertex_shader->info.num_written_clipdistance; +} + +uint +draw_current_shader_num_written_culldistances(const struct draw_context *draw) +{ + if (draw->gs.geometry_shader) + return draw->gs.geometry_shader->info.num_written_culldistance; + return draw->vs.vertex_shader->info.num_written_culldistance; } /** @@ -711,7 +937,9 @@ draw_get_rasterizer_no_cull( struct draw_context *draw, rast.scissor = scissor; rast.flatshade = flatshade; rast.front_ccw = 1; - rast.gl_rasterization_rules = draw->rasterizer->gl_rasterization_rules; + rast.half_pixel_center = draw->rasterizer->half_pixel_center; + rast.bottom_edge_rule = draw->rasterizer->bottom_edge_rule; + rast.clip_halfz = draw->rasterizer->clip_halfz; draw->rasterizer_no_cull[scissor][flatshade] = pipe->create_rasterizer_state(pipe, &rast); @@ -734,25 +962,9 @@ draw_set_mapped_so_targets(struct draw_context *draw, draw->so.num_targets = num_targets; } -void -draw_set_mapped_so_buffers(struct draw_context *draw, - void *buffers[PIPE_MAX_SO_BUFFERS], - unsigned num_buffers) -{ -} - -void -draw_set_so_state(struct draw_context *draw, - struct pipe_stream_output_info *state) -{ - memcpy(&draw->so.state, - state, - sizeof(struct pipe_stream_output_info)); -} - void draw_set_sampler_views(struct draw_context *draw, - unsigned shader_stage, + enum pipe_shader_type shader_stage, struct pipe_sampler_view **views, unsigned num) { @@ -773,7 +985,7 @@ draw_set_sampler_views(struct draw_context *draw, void draw_set_samplers(struct draw_context *draw, - unsigned shader_stage, + enum pipe_shader_type shader_stage, struct pipe_sampler_state **samplers, unsigned num) { @@ -792,14 +1004,14 @@ draw_set_samplers(struct draw_context *draw, draw->num_samplers[shader_stage] = num; #ifdef HAVE_LLVM - if (draw->llvm && shader_stage == PIPE_SHADER_VERTEX) - draw_llvm_set_sampler_state(draw); + if (draw->llvm) + draw_llvm_set_sampler_state(draw, shader_stage); #endif } void draw_set_mapped_texture(struct draw_context *draw, - unsigned shader_stage, + enum pipe_shader_type shader_stage, unsigned sview_idx, uint32_t width, uint32_t height, uint32_t depth, uint32_t first_level, uint32_t last_level, @@ -824,7 +1036,8 @@ draw_set_mapped_texture(struct draw_context *draw, * different ways of setting textures, and drivers typically only support one. */ int -draw_get_shader_param_no_llvm(unsigned shader, enum pipe_shader_cap param) +draw_get_shader_param_no_llvm(enum pipe_shader_type shader, + enum pipe_shader_cap param) { switch(shader) { case PIPE_SHADER_VERTEX: @@ -838,9 +1051,11 @@ draw_get_shader_param_no_llvm(unsigned shader, enum pipe_shader_cap param) /** * XXX: Results for PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS because there are two * different ways of setting textures, and drivers typically only support one. + * Drivers requesting a draw context explicitly without llvm must call + * draw_get_shader_param_no_llvm instead. */ int -draw_get_shader_param(unsigned shader, enum pipe_shader_cap param) +draw_get_shader_param(enum pipe_shader_type shader, enum pipe_shader_cap param) { #ifdef HAVE_LLVM @@ -858,3 +1073,66 @@ draw_get_shader_param(unsigned shader, enum pipe_shader_cap param) return draw_get_shader_param_no_llvm(shader, param); } +/** + * Enables or disables collection of statistics. + * + * Draw module is capable of generating statistics for the vertex + * processing pipeline. Collection of that data isn't free and so + * it's disabled by default. The users of the module can enable + * (or disable) this functionality through this function. + * The actual data will be emitted through the VBUF interface, + * the 'pipeline_statistics' callback to be exact. + */ +void +draw_collect_pipeline_statistics(struct draw_context *draw, + boolean enable) +{ + draw->collect_statistics = enable; +} + +/** + * Computes clipper invocation statistics. + * + * Figures out how many primitives would have been + * sent to the clipper given the specified + * prim info data. + */ +void +draw_stats_clipper_primitives(struct draw_context *draw, + const struct draw_prim_info *prim_info) +{ + if (draw->collect_statistics) { + unsigned i; + for (i = 0; i < prim_info->primitive_count; i++) { + draw->statistics.c_invocations += + u_decomposed_prims_for_vertices(prim_info->prim, + prim_info->primitive_lengths[i]); + } + } +} + + +/** + * Returns true if the draw module will inject the frontface + * info into the outputs. + * + * Given the specified primitive and rasterizer state + * the function will figure out if the draw module + * will inject the front-face information into shader + * outputs. This is done to preserve the front-facing + * info when decomposing primitives into wireframes. + */ +boolean +draw_will_inject_frontface(const struct draw_context *draw) +{ + unsigned reduced_prim = u_reduced_prim(draw->pt.prim); + const struct pipe_rasterizer_state *rast = draw->rasterizer; + + if (reduced_prim != PIPE_PRIM_TRIANGLES) { + return FALSE; + } + + return (rast && + (rast->fill_front != PIPE_POLYGON_MODE_FILL || + rast->fill_back != PIPE_POLYGON_MODE_FILL)); +}