blob: 0c4c2ea81de40a6e2ab0a5c9ccc6cfc02454e73c [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "cc/blink/web_display_item_list_impl.h"
#include <stddef.h>
#include <stdint.h>
#include <vector>
#include "cc/paint/paint_filter.h"
#include "cc/paint/paint_op_buffer.h"
#include "cc/paint/render_surface_filters.h"
#include "third_party/WebKit/public/platform/WebFloatRect.h"
#include "third_party/WebKit/public/platform/WebRect.h"
#include "third_party/skia/include/core/SkColorFilter.h"
#include "third_party/skia/include/core/SkMatrix44.h"
#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/gfx/geometry/safe_integer_conversions.h"
#include "ui/gfx/skia_util.h"
#include "ui/gfx/transform.h"
namespace cc_blink {
namespace {
} // namespace
WebDisplayItemListImpl::WebDisplayItemListImpl()
: display_item_list_(base::MakeRefCounted<cc::DisplayItemList>()) {}
WebDisplayItemListImpl::WebDisplayItemListImpl(
cc::DisplayItemList* display_list)
: display_item_list_(display_list) {
}
WebDisplayItemListImpl::~WebDisplayItemListImpl() = default;
void WebDisplayItemListImpl::AppendDrawingItem(
const blink::WebRect& visual_rect,
sk_sp<const cc::PaintOpBuffer> record) {
display_item_list_->StartPaint();
display_item_list_->push<cc::DrawRecordOp>(std::move(record));
display_item_list_->EndPaintOfUnpaired(visual_rect);
}
void WebDisplayItemListImpl::AppendClipItem(
const blink::WebRect& clip_rect,
const blink::WebVector<SkRRect>& rounded_clip_rects) {
bool antialias = true;
display_item_list_->StartPaint();
display_item_list_->push<cc::SaveOp>();
display_item_list_->push<cc::ClipRectOp>(gfx::RectToSkRect(clip_rect),
SkClipOp::kIntersect, antialias);
for (const SkRRect& rrect : rounded_clip_rects) {
if (rrect.isRect()) {
display_item_list_->push<cc::ClipRectOp>(rrect.rect(),
SkClipOp::kIntersect, antialias);
} else {
display_item_list_->push<cc::ClipRRectOp>(rrect, SkClipOp::kIntersect,
antialias);
}
}
display_item_list_->EndPaintOfPairedBegin();
}
void WebDisplayItemListImpl::AppendEndClipItem() {
AppendRestore();
}
void WebDisplayItemListImpl::AppendClipPathItem(const SkPath& clip_path,
bool antialias) {
display_item_list_->StartPaint();
display_item_list_->push<cc::SaveOp>();
display_item_list_->push<cc::ClipPathOp>(clip_path, SkClipOp::kIntersect,
antialias);
display_item_list_->EndPaintOfPairedBegin();
}
void WebDisplayItemListImpl::AppendEndClipPathItem() {
AppendRestore();
}
void WebDisplayItemListImpl::AppendFloatClipItem(
const blink::WebFloatRect& clip_rect) {
bool antialias = false;
display_item_list_->StartPaint();
display_item_list_->push<cc::SaveOp>();
display_item_list_->push<cc::ClipRectOp>(gfx::RectFToSkRect(clip_rect),
SkClipOp::kIntersect, antialias);
display_item_list_->EndPaintOfPairedBegin();
}
void WebDisplayItemListImpl::AppendEndFloatClipItem() {
AppendRestore();
}
void WebDisplayItemListImpl::AppendTransformItem(const SkMatrix44& matrix) {
display_item_list_->StartPaint();
display_item_list_->push<cc::SaveOp>();
if (!matrix.isIdentity())
display_item_list_->push<cc::ConcatOp>(static_cast<SkMatrix>(matrix));
display_item_list_->EndPaintOfPairedBegin();
}
void WebDisplayItemListImpl::AppendEndTransformItem() {
AppendRestore();
}
void WebDisplayItemListImpl::AppendCompositingItem(
float opacity,
SkBlendMode xfermode,
SkRect* bounds,
SkColorFilter* color_filter) {
DCHECK_GE(opacity, 0.f);
DCHECK_LE(opacity, 1.f);
// TODO(ajuma): This should really be rounding instead of flooring the alpha
// value, but that breaks slimming paint reftests.
auto alpha = static_cast<uint8_t>(gfx::ToFlooredInt(255 * opacity));
if (xfermode == SkBlendMode::kSrcOver && !color_filter) {
display_item_list_->StartPaint();
display_item_list_->push<cc::SaveLayerAlphaOp>(bounds, alpha, false);
if (bounds) {
display_item_list_->push<cc::ClipRectOp>(*bounds, SkClipOp::kIntersect,
false);
}
display_item_list_->EndPaintOfPairedBegin();
return;
}
cc::PaintFlags flags;
flags.setBlendMode(xfermode);
flags.setAlpha(alpha);
flags.setColorFilter(sk_ref_sp(color_filter));
display_item_list_->StartPaint();
display_item_list_->push<cc::SaveLayerOp>(bounds, &flags);
if (bounds) {
display_item_list_->push<cc::ClipRectOp>(*bounds, SkClipOp::kIntersect,
false);
}
display_item_list_->EndPaintOfPairedBegin();
}
void WebDisplayItemListImpl::AppendEndCompositingItem() {
AppendRestore();
}
void WebDisplayItemListImpl::AppendFilterItem(
const cc::FilterOperations& filters,
const blink::WebFloatRect& filter_bounds,
const blink::WebFloatPoint& origin) {
display_item_list_->StartPaint();
// TODO(danakj): Skip the save+translate+restore if the origin is 0,0. This
// should be easier to do when this code is part of the blink DisplayItem
// which can keep related state.
display_item_list_->push<cc::SaveOp>();
display_item_list_->push<cc::TranslateOp>(origin.x, origin.y);
cc::PaintFlags flags;
flags.setImageFilter(cc::RenderSurfaceFilters::BuildImageFilter(
filters, gfx::SizeF(filter_bounds.width, filter_bounds.height)));
SkRect layer_bounds = gfx::RectFToSkRect(filter_bounds);
layer_bounds.offset(-origin.x, -origin.y);
display_item_list_->push<cc::SaveLayerOp>(&layer_bounds, &flags);
display_item_list_->push<cc::TranslateOp>(-origin.x, -origin.y);
display_item_list_->EndPaintOfPairedBegin(
gfx::ToEnclosingRect(filter_bounds));
}
void WebDisplayItemListImpl::AppendEndFilterItem() {
display_item_list_->StartPaint();
display_item_list_->push<cc::RestoreOp>(); // For SaveLayerOp.
display_item_list_->push<cc::RestoreOp>(); // For SaveOp.
display_item_list_->EndPaintOfPairedEnd();
}
void WebDisplayItemListImpl::AppendScrollItem(
const blink::WebSize& scroll_offset,
ScrollContainerId) {
display_item_list_->StartPaint();
display_item_list_->push<cc::SaveOp>();
display_item_list_->push<cc::TranslateOp>(
static_cast<float>(-scroll_offset.width),
static_cast<float>(-scroll_offset.height));
display_item_list_->EndPaintOfPairedBegin();
}
void WebDisplayItemListImpl::AppendEndScrollItem() {
AppendRestore();
}
void WebDisplayItemListImpl::AppendRestore() {
display_item_list_->StartPaint();
display_item_list_->push<cc::RestoreOp>();
display_item_list_->EndPaintOfPairedEnd();
}
cc::DisplayItemList* WebDisplayItemListImpl::GetCcDisplayItemList() {
return display_item_list_.get();
}
} // namespace cc_blink