Commit 0a4d08b8 authored by Michael Ludwig's avatar Michael Ludwig Committed by Commit Bot

Allow arbitrary DrawQuad types to be drawn directly

This does not actually change the current logic of
what DrawQuads are drawn directly by skia_renderer
or gl_renderer. It just makes it possible at the
direct_renderer level for subclasses to have more
flexibility in how they bypass RenderPasses.

Bug: 1013735
Change-Id: I4a82155b57ce58a40ca68ccc2b05875e84d625e9
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1860103Reviewed-by: default avatarweiliangc <weiliangc@chromium.org>
Commit-Queue: Michael Ludwig <michaelludwig@google.com>
Cr-Commit-Position: refs/heads/master@{#706149}
parent e41bbad7
......@@ -196,65 +196,7 @@ gfx::Rect DirectRenderer::MoveFromDrawToWindowSpace(
return window_rect;
}
// static
const TileDrawQuad* DirectRenderer::CanPassBeDrawnDirectly(
const RenderPass* pass,
DisplayResourceProvider* const resource_provider) {
#if defined(OS_MACOSX)
// On Macs, this path can sometimes lead to all black output.
// TODO(enne): investigate this and remove this hack.
return nullptr;
#endif
// Can only collapse a single tile quad.
if (pass->quad_list.size() != 1)
return nullptr;
// If we need copy requests, then render pass has to exist.
if (!pass->copy_requests.empty())
return nullptr;
const DrawQuad* quad = *pass->quad_list.BackToFrontBegin();
// Hack: this could be supported by concatenating transforms, but
// in practice if there is one quad, it is at the origin of the render pass
// and has the same size as the pass.
if (!quad->shared_quad_state->quad_to_target_transform.IsIdentity() ||
quad->rect != pass->output_rect)
return nullptr;
// The quad is expected to be the entire layer so that AA edges are correct.
if (quad->shared_quad_state->quad_layer_rect != quad->rect)
return nullptr;
if (quad->material != DrawQuad::Material::kTiledContent)
return nullptr;
// TODO(chrishtr): support could be added for opacity, but care needs
// to be taken to make sure it is correct w.r.t. non-commutative filters etc.
if (quad->shared_quad_state->opacity != 1.0f)
return nullptr;
if (quad->shared_quad_state->blend_mode != SkBlendMode::kSrcOver)
return nullptr;
const TileDrawQuad* tile_quad = TileDrawQuad::MaterialCast(quad);
// Hack: this could be supported by passing in a subrectangle to draw
// render pass, although in practice if there is only one quad there
// will be no border texels on the input.
if (tile_quad->tex_coord_rect != gfx::RectF(tile_quad->rect))
return nullptr;
// Tile quad features not supported in render pass shaders.
if (tile_quad->nearest_neighbor)
return nullptr;
// BUG=skia:3868, Skia currently doesn't support texture rectangle inputs.
// See also the DCHECKs about GL_TEXTURE_2D in DrawRenderPassQuad.
GLenum target =
resource_provider->GetResourceTextureTarget(tile_quad->resource_id());
if (target != GL_TEXTURE_2D)
return nullptr;
return tile_quad;
}
const TileDrawQuad* DirectRenderer::CanPassBeDrawnDirectly(
const RenderPass* pass) {
const DrawQuad* DirectRenderer::CanPassBeDrawnDirectly(const RenderPass* pass) {
return nullptr;
}
......@@ -268,17 +210,19 @@ void DirectRenderer::SetVisible(bool visible) {
void DirectRenderer::DecideRenderPassAllocationsForFrame(
const RenderPassList& render_passes_in_draw_order) {
render_pass_bypass_quads_.clear();
DCHECK(render_pass_bypass_quads_.empty());
auto& root_render_pass = render_passes_in_draw_order.back();
base::flat_map<RenderPassId, RenderPassRequirements> render_passes_in_frame;
for (const auto& pass : render_passes_in_draw_order) {
if (pass != root_render_pass) {
if (const TileDrawQuad* tile_quad = CanPassBeDrawnDirectly(pass.get())) {
// If there's a copy request, we need an explicit renderpass backing so
// only try to draw directly if there are no copy requests.
if (pass != root_render_pass && pass->copy_requests.empty()) {
if (const DrawQuad* quad = CanPassBeDrawnDirectly(pass.get())) {
// If the render pass is drawn directly, it will not be drawn from as
// a render pass so it's not added to the map.
render_pass_bypass_quads_[pass->id] = *tile_quad;
render_pass_bypass_quads_[pass->id] = quad;
continue;
}
}
......@@ -458,6 +402,7 @@ void DirectRenderer::DrawFrame(RenderPassList* render_passes_in_draw_order,
render_pass_filters_.clear();
render_pass_backdrop_filters_.clear();
render_pass_backdrop_filter_bounds_.clear();
render_pass_bypass_quads_.clear();
current_frame_valid_ = false;
}
......
......@@ -206,10 +206,7 @@ class VIZ_SERVICE_EXPORT DirectRenderer {
// If a pass contains a single tile draw quad and can be drawn without
// a render pass (e.g. applying a filter directly to the tile quad)
// return that quad, otherwise return null.
static const TileDrawQuad* CanPassBeDrawnDirectly(
const RenderPass* pass,
DisplayResourceProvider* const resource_provider);
virtual const TileDrawQuad* CanPassBeDrawnDirectly(const RenderPass* pass);
virtual const DrawQuad* CanPassBeDrawnDirectly(const RenderPass* pass);
virtual void FinishDrawingQuadList() {}
virtual bool FlippedFramebuffer() const = 0;
virtual void EnsureScissorTestEnabled() = 0;
......@@ -250,8 +247,10 @@ class VIZ_SERVICE_EXPORT DirectRenderer {
int frames_since_using_dc_layers_ = 0;
// A map from RenderPass id to the single quad present in and replacing the
// RenderPass.
base::flat_map<RenderPassId, TileDrawQuad> render_pass_bypass_quads_;
// RenderPass. The DrawQuads are owned by their RenderPasses, which outlive
// the drawn frame, so it is safe to store these pointers until the end of
// DrawFrame().
base::flat_map<RenderPassId, const DrawQuad*> render_pass_bypass_quads_;
// A map from RenderPass id to the filters used when drawing the RenderPass.
base::flat_map<RenderPassId, cc::FilterOperations*> render_pass_filters_;
......
......@@ -1036,8 +1036,55 @@ sk_sp<SkImage> GLRenderer::ApplyBackdropFilters(
return FinalizeImage(surface);
}
const TileDrawQuad* GLRenderer::CanPassBeDrawnDirectly(const RenderPass* pass) {
return DirectRenderer::CanPassBeDrawnDirectly(pass, resource_provider_);
const DrawQuad* GLRenderer::CanPassBeDrawnDirectly(const RenderPass* pass) {
#if defined(OS_MACOSX)
// On Macs, this path can sometimes lead to all black output.
// TODO(enne): investigate this and remove this hack.
return nullptr;
#endif
// Can only collapse a single tile quad.
if (pass->quad_list.size() != 1)
return nullptr;
const DrawQuad* quad = *pass->quad_list.BackToFrontBegin();
// Hack: this could be supported by concatenating transforms, but
// in practice if there is one quad, it is at the origin of the render pass
// and has the same size as the pass.
if (!quad->shared_quad_state->quad_to_target_transform.IsIdentity() ||
quad->rect != pass->output_rect)
return nullptr;
// The quad is expected to be the entire layer so that AA edges are correct.
if (quad->shared_quad_state->quad_layer_rect != quad->rect)
return nullptr;
if (quad->material != DrawQuad::Material::kTiledContent)
return nullptr;
// TODO(chrishtr): support could be added for opacity, but care needs
// to be taken to make sure it is correct w.r.t. non-commutative filters etc.
if (quad->shared_quad_state->opacity != 1.0f)
return nullptr;
if (quad->shared_quad_state->blend_mode != SkBlendMode::kSrcOver)
return nullptr;
const TileDrawQuad* tile_quad = TileDrawQuad::MaterialCast(quad);
// Hack: this could be supported by passing in a subrectangle to draw
// render pass, although in practice if there is only one quad there
// will be no border texels on the input.
if (tile_quad->tex_coord_rect != gfx::RectF(tile_quad->rect))
return nullptr;
// Tile quad features not supported in render pass shaders.
if (tile_quad->nearest_neighbor)
return nullptr;
// BUG=skia:3868, Skia currently doesn't support texture rectangle inputs.
// See also the DCHECKs about GL_TEXTURE_2D in DrawRenderPassQuad.
GLenum target =
resource_provider_->GetResourceTextureTarget(tile_quad->resource_id());
if (target != GL_TEXTURE_2D)
return nullptr;
return tile_quad;
}
void GLRenderer::DrawRenderPassQuad(const RenderPassDrawQuad* quad,
......@@ -1050,7 +1097,8 @@ void GLRenderer::DrawRenderPassQuad(const RenderPassDrawQuad* quad,
params.projection_matrix = current_frame()->projection_matrix;
params.tex_coord_rect = quad->tex_coord_rect;
if (bypass != render_pass_bypass_quads_.end()) {
TileDrawQuad* tile_quad = &bypass->second;
DCHECK(bypass->second->material == DrawQuad::Material::kTiledContent);
const TileDrawQuad* tile_quad = TileDrawQuad::MaterialCast(bypass->second);
// The projection matrix used by GLRenderer has a flip. As tile texture
// inputs are oriented opposite to framebuffer outputs, don't flip via
// texture coords and let the projection matrix naturallyd o it.
......
......@@ -230,7 +230,8 @@ class VIZ_SERVICE_EXPORT GLRenderer : public DirectRenderer {
const base::Optional<gfx::RRectF>& backdrop_filter_bounds,
const gfx::Transform& backdrop_filter_bounds_transform);
const TileDrawQuad* CanPassBeDrawnDirectly(const RenderPass* pass) override;
// gl_renderer can bypass TileDrawQuads that fill the RenderPass
const DrawQuad* CanPassBeDrawnDirectly(const RenderPass* pass) override;
void DrawRenderPassQuad(const RenderPassDrawQuad* quadi,
const gfx::QuadF* clip_region);
......
......@@ -1737,9 +1737,48 @@ SkiaRenderer::DrawRPDQParams SkiaRenderer::CalculateRPDQParams(
return rpdq_params;
}
const TileDrawQuad* SkiaRenderer::CanPassBeDrawnDirectly(
const RenderPass* pass) {
return DirectRenderer::CanPassBeDrawnDirectly(pass, resource_provider_);
const DrawQuad* SkiaRenderer::CanPassBeDrawnDirectly(const RenderPass* pass) {
// TODO(michaelludwig) - For now, this only supports layer-filling
// TileDrawQuads to match legacy bypass behavior. It will be updated to
// select more quad material types as their corresponding DrawXQuad()
// functions are updated to accept DrawRPDQParams as well.
// Can only collapse a single tile quad.
if (pass->quad_list.size() != 1)
return nullptr;
// If it there are supposed to be mipmaps, the renderpass must exist
if (pass->generate_mipmap)
return nullptr;
const DrawQuad* quad = *pass->quad_list.BackToFrontBegin();
// Hack: this could be supported by concatenating transforms, but
// in practice if there is one quad, it is at the origin of the render pass
// and has the same size as the pass.
if (!quad->shared_quad_state->quad_to_target_transform.IsIdentity() ||
quad->rect != pass->output_rect)
return nullptr;
// The quad is expected to be the entire layer so that AA edges are correct.
if (quad->shared_quad_state->quad_layer_rect != quad->rect)
return nullptr;
if (quad->material != DrawQuad::Material::kTiledContent)
return nullptr;
// TODO(chrishtr): support could be added for opacity, but care needs
// to be taken to make sure it is correct w.r.t. non-commutative filters etc.
if (quad->shared_quad_state->opacity != 1.0f)
return nullptr;
if (quad->shared_quad_state->blend_mode != SkBlendMode::kSrcOver)
return nullptr;
const TileDrawQuad* tile_quad = TileDrawQuad::MaterialCast(quad);
// Hack: this could be supported by passing in a subrectangle to draw
// render pass, although in practice if there is only one quad there
// will be no border texels on the input.
if (tile_quad->tex_coord_rect != gfx::RectF(tile_quad->rect))
return nullptr;
return tile_quad;
}
void SkiaRenderer::DrawRenderPassQuad(const RenderPassDrawQuad* quad,
......@@ -1747,7 +1786,8 @@ void SkiaRenderer::DrawRenderPassQuad(const RenderPassDrawQuad* quad,
auto bypass = render_pass_bypass_quads_.find(quad->render_pass_id);
// When Render Pass has a single quad inside we would draw that directly.
if (bypass != render_pass_bypass_quads_.end()) {
TileDrawQuad* tile_quad = &bypass->second;
DCHECK(bypass->second->material == DrawQuad::Material::kTiledContent);
const TileDrawQuad* tile_quad = TileDrawQuad::MaterialCast(bypass->second);
ScopedSkImageBuilder builder(this, tile_quad->resource_id(),
tile_quad->is_premultiplied
? kPremul_SkAlphaType
......
......@@ -163,7 +163,9 @@ class VIZ_SERVICE_EXPORT SkiaRenderer : public DirectRenderer {
// Schedule overlay candidates for presentation at next SwapBuffers().
void ScheduleDCLayers();
const TileDrawQuad* CanPassBeDrawnDirectly(const RenderPass* pass) override;
// skia_renderer can draw most single-quad passes directly, regardless of
// blend mode or image filtering.
const DrawQuad* CanPassBeDrawnDirectly(const RenderPass* pass) override;
// Get corresponding GrContext. Returns nullptr when there is no GrContext.
// TODO(weiliangc): This currently only returns nullptr. If SKPRecord isn't
......
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