blob: 90417884616bcf608adf173559387fa1399bf89b [file] [log] [blame]
// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/viz/common/quads/render_pass_internal.h"
#include <stddef.h>
#include "base/trace_event/traced_value.h"
#include "cc/base/math_util.h"
#include "components/viz/common/frame_sinks/copy_output_request.h"
#include "components/viz/common/quads/solid_color_draw_quad.h"
#include "components/viz/common/traced_value.h"
namespace viz {
namespace {
const size_t kDefaultNumSharedQuadStatesToReserve = 32;
const size_t kDefaultNumQuadsToReserve = 128;
} // namespace
RenderPassInternal::RenderPassInternal()
: RenderPassInternal(kDefaultNumSharedQuadStatesToReserve,
kDefaultNumQuadsToReserve) {}
// Each layer usually produces one shared quad state, so the number of layers
// is a good hint for what to reserve here.
RenderPassInternal::RenderPassInternal(size_t num_layers)
: RenderPassInternal(num_layers, kDefaultNumQuadsToReserve) {}
RenderPassInternal::RenderPassInternal(size_t shared_quad_state_list_size,
size_t quad_list_size)
: quad_list(quad_list_size),
shared_quad_state_list(alignof(SharedQuadState),
sizeof(SharedQuadState),
shared_quad_state_list_size) {}
RenderPassInternal::~RenderPassInternal() = default;
SharedQuadState* RenderPassInternal::CreateAndAppendSharedQuadState() {
return shared_quad_state_list.AllocateAndConstruct<SharedQuadState>();
}
void RenderPassInternal::ReplaceExistingQuadWithSolidColor(
QuadList::Iterator at,
SkColor4f color,
SkBlendMode blend_mode) {
const SharedQuadState* shared_quad_state = at->shared_quad_state;
if (shared_quad_state->are_contents_opaque ||
shared_quad_state->blend_mode != blend_mode) {
auto* new_shared_quad_state =
shared_quad_state_list.AllocateAndCopyFrom(shared_quad_state);
new_shared_quad_state->are_contents_opaque = false;
new_shared_quad_state->blend_mode = blend_mode;
shared_quad_state = new_shared_quad_state;
}
const gfx::Rect rect = at->rect;
// TODO(crbug.com/40219248) This function should be called with an SkColor4f
quad_list.ReplaceExistingElement<SolidColorDrawQuad>(at)->SetAll(
shared_quad_state, rect, /*visible_rect=*/rect,
/*needs_blending=*/false, color,
/*force_anti_aliasing_off=*/true);
}
void RenderPassInternal::ReplaceExistingQuadWithHolePunch(
QuadList::Iterator quad,
bool* quad_was_opaque) {
// If the `quad` is translucent and uses SrcOver blend mode, we can achieve
// the same result as compositing with `quad` on top, if we replace `quad`
// with a solid color quad with DstOut blend mode, and rely on SrcOver
// blending of the root surface with video on bottom. Essentially,
//
// SrcOver_quad(V, B, V_alpha) = SrcOver_premul(DstOut(BLACK, B, V_alpha), V)
// where
// V is the video quad
// B is the background
// SrcOver_quad uses opacity of source quad (V_alpha)
// SrcOver_premul uses alpha channel and assumes premultipled alpha
//
// This also applies to quads with a mask filter for rounded corners.
if (quad->ShouldDrawWithBlending() &&
quad->shared_quad_state->blend_mode == SkBlendMode::kSrcOver) {
ReplaceExistingQuadWithSolidColor(quad, SkColors::kBlack,
SkBlendMode::kDstOut);
if (quad_was_opaque) {
*quad_was_opaque = false;
}
} else {
// When the opacity == 1.0, drawing with transparent will be done without
// blending and will have the proper effect of completely clearing the
// layer.
ReplaceExistingQuadWithSolidColor(quad, SkColors::kTransparent,
SkBlendMode::kSrcOver);
if (quad_was_opaque) {
*quad_was_opaque = true;
}
}
}
void RenderPassInternal::AsValueInto(
base::trace_event::TracedValue* value) const {
cc::MathUtil::AddToTracedValue("output_rect", output_rect, value);
cc::MathUtil::AddToTracedValue("damage_rect", damage_rect, value);
value->SetBoolean("has_transparent_background", has_transparent_background);
value->SetBoolean("cache_render_pass", cache_render_pass);
value->SetBoolean("has_damage_from_contributing_content",
has_damage_from_contributing_content);
value->SetBoolean("generate_mipmap", generate_mipmap);
value->SetInteger("copy_requests",
base::saturated_cast<int>(copy_requests.size()));
value->BeginArray("filters");
filters.AsValueInto(value);
value->EndArray();
value->BeginArray("backdrop_filters");
backdrop_filters.AsValueInto(value);
value->EndArray();
if (backdrop_filter_bounds.has_value()) {
cc::MathUtil::AddToTracedValue("backdrop_filter_bounds",
*backdrop_filter_bounds, value);
}
value->BeginArray("shared_quad_state_list");
for (auto* shared_quad_state : shared_quad_state_list) {
value->BeginDictionary();
shared_quad_state->AsValueInto(value);
value->EndDictionary();
}
value->EndArray();
value->BeginArray("quad_list");
for (auto* quad : quad_list) {
value->BeginDictionary();
quad->AsValueInto(value);
value->EndDictionary();
}
value->EndArray();
}
} // namespace viz