Commit 3475495d authored by kylechar's avatar kylechar Committed by Chromium LUCI CQ

Fix nearest-neighbor scaling and renderpass bypass

There is a bug where SkiaRenderer doesn't handle the nearest_neighbor
flag set on quads correctly. If the quad is in a render pass that is
bypassed then SkiaRenderer will draw the quad directly using a higher
filter quality than nearest-neighbor.

There can actually be two different scaling operations, one when the
quad is copied into the render pass with nearest-neighbour scaling and
the second when the render pass is copied into the framebuffer (or other
another render pass) most likely with bilinear interpolation. If there
are two scaling operations at different qualities, it's not going to be
possible to bypass the render pass without changing the resulting
pixels. To simplify things, don't bypass a render pass where the only
quad specifies nearest-neighbour scaling.

Bug: 1155338
Change-Id: If476bfb2ce027772aaa6a153ba108d341c354423
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2577706Reviewed-by: default avatarMichael Ludwig <michaelludwig@google.com>
Commit-Queue: kylechar <kylechar@chromium.org>
Cr-Commit-Position: refs/heads/master@{#835190}
parent ed4e5169
......@@ -280,27 +280,28 @@ bool IsAAForcedOff(const DrawQuad* quad) {
}
}
SkFilterQuality GetFilterQuality(const DrawQuad* quad) {
bool nearest_neighbor;
bool UseNearestNeighborSampling(const DrawQuad* quad) {
switch (quad->material) {
case DrawQuad::Material::kPictureContent:
nearest_neighbor = PictureDrawQuad::MaterialCast(quad)->nearest_neighbor;
break;
return PictureDrawQuad::MaterialCast(quad)->nearest_neighbor;
case DrawQuad::Material::kTextureContent:
nearest_neighbor = TextureDrawQuad::MaterialCast(quad)->nearest_neighbor;
break;
return TextureDrawQuad::MaterialCast(quad)->nearest_neighbor;
case DrawQuad::Material::kTiledContent:
nearest_neighbor = TileDrawQuad::MaterialCast(quad)->nearest_neighbor;
break;
return TileDrawQuad::MaterialCast(quad)->nearest_neighbor;
default:
// Other quad types do not expose filter quality, so default to bilinear
// TODO(penghuang): figure out how to set correct filter quality for YUV
// and video stream quads.
nearest_neighbor = false;
break;
// Other quad types do not expose nearest_neighbor.
return false;
}
}
SkFilterQuality GetFilterQuality(const DrawQuad* quad) {
if (UseNearestNeighborSampling(quad))
return kNone_SkFilterQuality;
return nearest_neighbor ? kNone_SkFilterQuality : kLow_SkFilterQuality;
// Default to bilinear if the quad doesn't specify nearest_neighbor.
// TODO(penghuang): figure out how to set correct filter quality for YUV and
// video stream quads.
return kLow_SkFilterQuality;
}
// Returns kFast if sampling outside of vis_tex_coords due to AA or bilerp will
......@@ -1332,6 +1333,12 @@ const DrawQuad* SkiaRenderer::CanPassBeDrawnDirectly(
quad->material == DrawQuad::Material::kPictureContent)
return nullptr;
// If the quad specifies nearest-neighbor scaling then there could be two
// scaling operations at different quality levels. This requires drawing to an
// intermediate render pass. See https://crbug.com/1155338.
if (UseNearestNeighborSampling(quad))
return nullptr;
if (quad->material == DrawQuad::Material::kTextureContent) {
// Per-vertex opacities complicate bypassing the RP and alpha blending the
// texture with image filters, so punt under that rare circumstance.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment