diff options
author | Neil Roberts <[email protected]> | 2020-06-22 14:26:02 +0200 |
---|---|---|
committer | Marge Bot <[email protected]> | 2020-07-06 21:59:16 +0000 |
commit | ee4d51f8b2de004b04d02c7edf66ca0608adf16f (patch) | |
tree | 7b3a32fcd42b915bcd32bc94e1f093cd32a552af /src/gallium/drivers | |
parent | 207da33a86d1a2b45995a7fd123afb761b1d841f (diff) |
v3d: Add a lowering pass for line smoothing
When line smoothing is enabled, the driver now increases the width of
the line so that it can add some semi-transparent pixels to either side
of the line. A lowering pass is added which modifies the alpha component
of every write to fragment output 0 so that if the fragment is outside
the width of the line then the alpha is reduced. It additionally
discards fragments that are completely invisible. It might seem bad to
use discard on a tiled renderer but the assumption is that any bad
effects from using discard will also happen anyway because of enabling
alpha blending.
v2: Disable the line smoothing pass entirely when the framebuffer
contains an integer colour output or one with no alpha channel.
Calculate the coverage once upfront and store in a global variable
instead of calculating each time an output write is modified. Also
do the conditional discard once upfront.
v3: Don’t check whether the output buffer has an alpha channel. Only
look at output 0. Use aa_line_width intrinsic instead of calculating
the real line width in the shader. Clamp the coverage as part of the
global variable, not per output write.
Reviewed-by: Eric Anholt <[email protected]>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5624>
Diffstat (limited to 'src/gallium/drivers')
-rw-r--r-- | src/gallium/drivers/v3d/v3d_context.c | 45 | ||||
-rw-r--r-- | src/gallium/drivers/v3d/v3d_context.h | 4 | ||||
-rw-r--r-- | src/gallium/drivers/v3d/v3d_program.c | 2 | ||||
-rw-r--r-- | src/gallium/drivers/v3d/v3d_uniforms.c | 5 | ||||
-rw-r--r-- | src/gallium/drivers/v3d/v3dx_emit.c | 2 |
5 files changed, 56 insertions, 2 deletions
diff --git a/src/gallium/drivers/v3d/v3d_context.c b/src/gallium/drivers/v3d/v3d_context.c index f3dc3a92fec..185bdc687b4 100644 --- a/src/gallium/drivers/v3d/v3d_context.c +++ b/src/gallium/drivers/v3d/v3d_context.c @@ -149,6 +149,51 @@ v3d_update_primitive_counters(struct v3d_context *v3d) } } +bool +v3d_line_smoothing_enabled(struct v3d_context *v3d) +{ + if (!v3d->rasterizer->base.line_smooth) + return false; + + /* According to the OpenGL docs, line smoothing shouldn’t be applied + * when multisampling + */ + if (v3d->job->msaa || v3d->rasterizer->base.multisample) + return false; + + if (v3d->framebuffer.nr_cbufs <= 0) + return false; + + struct pipe_surface *cbuf = v3d->framebuffer.cbufs[0]; + if (!cbuf) + return false; + + /* Modifying the alpha for pure integer formats probably + * doesn’t make sense because we don’t know how the application + * uses the alpha value. + */ + if (util_format_is_pure_integer(cbuf->format)) + return false; + + return true; +} + +float +v3d_get_real_line_width(struct v3d_context *v3d) +{ + float width = v3d->rasterizer->base.line_width; + + if (v3d_line_smoothing_enabled(v3d)) { + /* If line smoothing is enabled then we want to add some extra + * pixels to the width in order to have some semi-transparent + * edges. + */ + width = floorf(M_SQRT2 * width) + 3; + } + + return width; +} + static void v3d_context_destroy(struct pipe_context *pctx) { diff --git a/src/gallium/drivers/v3d/v3d_context.h b/src/gallium/drivers/v3d/v3d_context.h index 55bc96bed9d..74df773ca9a 100644 --- a/src/gallium/drivers/v3d/v3d_context.h +++ b/src/gallium/drivers/v3d/v3d_context.h @@ -699,6 +699,10 @@ struct v3d_fence *v3d_fence_create(struct v3d_context *v3d); void v3d_update_primitive_counters(struct v3d_context *v3d); +bool v3d_line_smoothing_enabled(struct v3d_context *v3d); + +float v3d_get_real_line_width(struct v3d_context *v3d); + #ifdef v3dX # include "v3dx_context.h" #else diff --git a/src/gallium/drivers/v3d/v3d_program.c b/src/gallium/drivers/v3d/v3d_program.c index 2415b279754..07a596d3eaf 100644 --- a/src/gallium/drivers/v3d/v3d_program.c +++ b/src/gallium/drivers/v3d/v3d_program.c @@ -541,6 +541,8 @@ v3d_update_compiled_fs(struct v3d_context *v3d, uint8_t prim_mode) key->is_points = (prim_mode == PIPE_PRIM_POINTS); key->is_lines = (prim_mode >= PIPE_PRIM_LINES && prim_mode <= PIPE_PRIM_LINE_STRIP); + key->line_smoothing = (key->is_lines && + v3d_line_smoothing_enabled(v3d)); key->clamp_color = v3d->rasterizer->base.clamp_fragment_color; if (v3d->blend->base.logicop_enable) { key->logicop_func = v3d->blend->base.logicop_func; diff --git a/src/gallium/drivers/v3d/v3d_uniforms.c b/src/gallium/drivers/v3d/v3d_uniforms.c index 64fde274a99..37fb98daa57 100644 --- a/src/gallium/drivers/v3d/v3d_uniforms.c +++ b/src/gallium/drivers/v3d/v3d_uniforms.c @@ -313,11 +313,14 @@ v3d_write_uniforms(struct v3d_context *v3d, struct v3d_job *job, break; case QUNIFORM_LINE_WIDTH: - case QUNIFORM_AA_LINE_WIDTH: cl_aligned_f(&uniforms, v3d->rasterizer->base.line_width); break; + case QUNIFORM_AA_LINE_WIDTH: + cl_aligned_f(&uniforms, v3d_get_real_line_width(v3d)); + break; + case QUNIFORM_UBO_ADDR: { uint32_t unit = v3d_unit_data_get_unit(data); /* Constant buffer 0 may be a system memory pointer, diff --git a/src/gallium/drivers/v3d/v3dx_emit.c b/src/gallium/drivers/v3d/v3dx_emit.c index bcad6cddac6..2dad2e0e246 100644 --- a/src/gallium/drivers/v3d/v3dx_emit.c +++ b/src/gallium/drivers/v3d/v3dx_emit.c @@ -551,7 +551,7 @@ v3dX(emit_state)(struct pipe_context *pctx) } cl_emit(&job->bcl, LINE_WIDTH, line_width) { - line_width.line_width = v3d->rasterizer->base.line_width; + line_width.line_width = v3d_get_real_line_width(v3d); } } |