Commit 61152b74 authored by Xu Xing's avatar Xu Xing Committed by Commit Bot

viz: Draw single quad render pass directly

The idea is from:
TODO(weiliangc): GL Renderer has optimization that when Render Pass has a
single quad inside we would draw that directly. We could add similar
optimization here by using the quad's SkImage.

BUG=888930

Cq-Include-Trybots: luci.chromium.try:android_optional_gpu_tests_rel
Change-Id: I42717c8a3fcfd93671db4ccff04acb76c005fa6a
Reviewed-on: https://chromium-review.googlesource.com/1242303Reviewed-by: default avatarenne <enne@chromium.org>
Commit-Queue: Xing Xu <xing.xu@intel.com>
Cr-Commit-Position: refs/heads/master@{#594731}
parent 2d15f116
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include "base/numerics/safe_conversions.h" #include "base/numerics/safe_conversions.h"
#include "base/stl_util.h" #include "base/stl_util.h"
#include "base/trace_event/trace_event.h" #include "base/trace_event/trace_event.h"
#include "build/build_config.h"
#include "cc/base/math_util.h" #include "cc/base/math_util.h"
#include "cc/paint/filter_operations.h" #include "cc/paint/filter_operations.h"
#include "components/viz/common/display/renderer_settings.h" #include "components/viz/common/display/renderer_settings.h"
...@@ -163,6 +164,63 @@ gfx::Rect DirectRenderer::MoveFromDrawToWindowSpace( ...@@ -163,6 +164,63 @@ gfx::Rect DirectRenderer::MoveFromDrawToWindowSpace(
return window_rect; return window_rect;
} }
// static
const TileDrawQuad* DirectRenderer::CanPassBeDrawnDirectly(
const RenderPass* pass,
bool is_using_vulkan,
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::TILED_CONTENT)
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;
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->swizzle_contents || tile_quad->nearest_neighbor)
return nullptr;
if (!is_using_vulkan) {
// 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 TileDrawQuad* DirectRenderer::CanPassBeDrawnDirectly(
const RenderPass* pass) { const RenderPass* pass) {
return nullptr; return nullptr;
......
...@@ -185,6 +185,10 @@ class VIZ_SERVICE_EXPORT DirectRenderer { ...@@ -185,6 +185,10 @@ class VIZ_SERVICE_EXPORT DirectRenderer {
// If a pass contains a single tile draw quad and can be drawn without // 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) // a render pass (e.g. applying a filter directly to the tile quad)
// return that quad, otherwise return null. // return that quad, otherwise return null.
static const TileDrawQuad* CanPassBeDrawnDirectly(
const RenderPass* pass,
bool is_using_vulkan,
DisplayResourceProvider* const resource_provider);
virtual const TileDrawQuad* CanPassBeDrawnDirectly(const RenderPass* pass); virtual const TileDrawQuad* CanPassBeDrawnDirectly(const RenderPass* pass);
virtual void FinishDrawingQuadList() {} virtual void FinishDrawingQuadList() {}
virtual bool FlippedFramebuffer() const = 0; virtual bool FlippedFramebuffer() const = 0;
......
...@@ -870,54 +870,8 @@ sk_sp<SkImage> GLRenderer::ApplyBackgroundFilters( ...@@ -870,54 +870,8 @@ sk_sp<SkImage> GLRenderer::ApplyBackgroundFilters(
} }
const TileDrawQuad* GLRenderer::CanPassBeDrawnDirectly(const RenderPass* pass) { const TileDrawQuad* GLRenderer::CanPassBeDrawnDirectly(const RenderPass* pass) {
#if defined(OS_MACOSX) return DirectRenderer::CanPassBeDrawnDirectly(pass, false,
// On Macs, this path can sometimes lead to all black output. resource_provider_);
// 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::TILED_CONTENT)
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;
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->swizzle_contents || 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, void GLRenderer::DrawRenderPassQuad(const RenderPassDrawQuad* quad,
......
...@@ -776,22 +776,38 @@ bool SkiaRenderer::CalculateRPDQParams(sk_sp<SkImage> content, ...@@ -776,22 +776,38 @@ bool SkiaRenderer::CalculateRPDQParams(sk_sp<SkImage> content,
return true; return true;
} }
void SkiaRenderer::DrawRenderPassQuad(const RenderPassDrawQuad* quad) { const TileDrawQuad* SkiaRenderer::CanPassBeDrawnDirectly(
auto iter = render_pass_backings_.find(quad->render_pass_id); const RenderPass* pass) {
DCHECK(render_pass_backings_.end() != iter); return DirectRenderer::CanPassBeDrawnDirectly(pass, IsUsingVulkan(),
// This function is called after AllocateRenderPassResourceIfNeeded, so there resource_provider_);
// should be backing ready. }
RenderPassBacking& backing = iter->second;
// TODO(weiliangc): GL Renderer has optimization that when Render Pass has a void SkiaRenderer::DrawRenderPassQuad(const RenderPassDrawQuad* quad) {
// single quad inside we would draw that directly. We could add similar auto bypass = render_pass_bypass_quads_.find(quad->render_pass_id);
// optimization here by using the quad's SkImage. // When Render Pass has a single quad inside we would draw that directly.
sk_sp<SkImage> content_image = if (bypass != render_pass_bypass_quads_.end()) {
is_using_ddl() ? skia_output_surface_->MakePromiseSkImageFromRenderPass( TileDrawQuad* tile_quad = &bypass->second;
quad->render_pass_id, backing.size, backing.format, ScopedSkImageBuilder builder(this, tile_quad->resource_id());
backing.mipmap) sk_sp<SkImage> content_image = sk_ref_sp(builder.sk_image());
: backing.render_pass_surface->makeImageSnapshot(); DrawRenderPassQuadInternal(quad, content_image);
} else {
auto iter = render_pass_backings_.find(quad->render_pass_id);
DCHECK(render_pass_backings_.end() != iter);
// This function is called after AllocateRenderPassResourceIfNeeded, so
// there should be backing ready.
RenderPassBacking& backing = iter->second;
sk_sp<SkImage> content_image =
is_using_ddl() ? skia_output_surface_->MakePromiseSkImageFromRenderPass(
quad->render_pass_id, backing.size, backing.format,
backing.mipmap)
: backing.render_pass_surface->makeImageSnapshot();
DrawRenderPassQuadInternal(quad, content_image);
}
}
void SkiaRenderer::DrawRenderPassQuadInternal(const RenderPassDrawQuad* quad,
sk_sp<SkImage> content_image) {
DrawRenderPassDrawQuadParams params; DrawRenderPassDrawQuadParams params;
params.filters = FiltersForPass(quad->render_pass_id); params.filters = FiltersForPass(quad->render_pass_id);
bool can_draw = CalculateRPDQParams(content_image, quad, &params); bool can_draw = CalculateRPDQParams(content_image, quad, &params);
......
...@@ -86,6 +86,9 @@ class VIZ_SERVICE_EXPORT SkiaRenderer : public DirectRenderer { ...@@ -86,6 +86,9 @@ class VIZ_SERVICE_EXPORT SkiaRenderer : public DirectRenderer {
void DrawDebugBorderQuad(const DebugBorderDrawQuad* quad); void DrawDebugBorderQuad(const DebugBorderDrawQuad* quad);
void DrawPictureQuad(const PictureDrawQuad* quad); void DrawPictureQuad(const PictureDrawQuad* quad);
void DrawRenderPassQuad(const RenderPassDrawQuad* quad); void DrawRenderPassQuad(const RenderPassDrawQuad* quad);
void DrawRenderPassQuadInternal(const RenderPassDrawQuad* quad,
sk_sp<SkImage> content_image);
void DrawSolidColorQuad(const SolidColorDrawQuad* quad); void DrawSolidColorQuad(const SolidColorDrawQuad* quad);
void DrawTextureQuad(const TextureDrawQuad* quad); void DrawTextureQuad(const TextureDrawQuad* quad);
void DrawTileQuad(const TileDrawQuad* quad); void DrawTileQuad(const TileDrawQuad* quad);
...@@ -100,6 +103,7 @@ class VIZ_SERVICE_EXPORT SkiaRenderer : public DirectRenderer { ...@@ -100,6 +103,7 @@ class VIZ_SERVICE_EXPORT SkiaRenderer : public DirectRenderer {
bool IsUsingVulkan() const; bool IsUsingVulkan() const;
GrContext* GetGrContext(); GrContext* GetGrContext();
bool is_using_ddl() const { return !!skia_output_surface_; } bool is_using_ddl() const { return !!skia_output_surface_; }
const TileDrawQuad* CanPassBeDrawnDirectly(const RenderPass* pass) override;
// A map from RenderPass id to the texture used to draw the RenderPass from. // A map from RenderPass id to the texture used to draw the RenderPass from.
struct RenderPassBacking { struct RenderPassBacking {
......
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