Commit 7440d469 authored by Vladimir Levin's avatar Vladimir Levin Committed by Commit Bot

Plumb PaintImage into PaintShaders.

This patch plumbs PaintImage into PaintShaders instead of SkImage.
With the patch to not construct SkPaint and instead using PaintFlags,
it becomes possible to introspect the flags to pull off PaintImage used
to construct it.

R=khushalsagar@chromium.org, chrishtr@chromium.org

Change-Id: Ia01ce40b1586b90172421ba99009baeb604fd937
Reviewed-on: https://chromium-review.googlesource.com/576868Reviewed-by: default avatarKhushal <khushalsagar@chromium.org>
Reviewed-by: default avatardanakj <danakj@chromium.org>
Reviewed-by: default avatarChris Harrelson <chrishtr@chromium.org>
Commit-Queue: Vladimir Levin <vmpstr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#488812}
parent b2724284
......@@ -579,8 +579,8 @@ TEST_F(DiscardableImageMapTest, GetDiscardableImagesInShader) {
std::max(y * 0.5f, kMinScale));
PaintFlags flags;
flags.setShader(PaintShader::MakeImage(
discardable_image[y][x], SkShader::kClamp_TileMode,
SkShader::kClamp_TileMode, &scale));
PaintImage(y * 4 + x, discardable_image[y][x]),
SkShader::kClamp_TileMode, SkShader::kClamp_TileMode, &scale));
content_layer_client.add_draw_rect(
gfx::Rect(x * 512 + 6, y * 512 + 6, 500, 500), flags);
}
......
......@@ -42,4 +42,10 @@ PaintImage::Id PaintImage::GetNextId() {
return s_next_id_.GetNext();
}
PaintImage PaintImage::CloneWithSkImage(sk_sp<SkImage> new_image) const {
PaintImage result(*this);
result.sk_image_ = std::move(new_image);
return result;
}
} // namespace cc
......@@ -64,6 +64,11 @@ class CC_PAINT_EXPORT PaintImage {
size_t frame_count() const { return frame_count_; }
bool is_multipart() const { return is_multipart_; }
// Returns a PaintImage that has the same fields as this PaintImage, except
// with a replaced sk_image_. This can be used to swap out a specific SkImage
// in an otherwise unchanged PaintImage.
PaintImage CloneWithSkImage(sk_sp<SkImage> new_image) const;
private:
Id id_ = kUnknownStableId;
sk_sp<SkImage> sk_image_;
......
......@@ -475,7 +475,8 @@ TEST(PaintOpBufferTest, DiscardableImagesTracking_DrawImageRect) {
TEST(PaintOpBufferTest, DiscardableImagesTracking_OpWithFlags) {
PaintOpBuffer buffer;
PaintFlags flags;
sk_sp<SkImage> image = CreateDiscardableImage(gfx::Size(100, 100));
auto image = PaintImage(PaintImage::GetNextId(),
CreateDiscardableImage(gfx::Size(100, 100)));
flags.setShader(PaintShader::MakeImage(std::move(image),
SkShader::kClamp_TileMode,
SkShader::kClamp_TileMode, nullptr));
......
......@@ -11,7 +11,7 @@
namespace cc {
sk_sp<PaintShader> PaintShader::MakeColor(SkColor color) {
sk_sp<PaintShader> shader(new PaintShader(kColor));
sk_sp<PaintShader> shader(new PaintShader(Type::kColor));
// Just one color. Store it in the fallback color. Easy.
shader->fallback_color_ = color;
......@@ -27,7 +27,7 @@ sk_sp<PaintShader> PaintShader::MakeLinearGradient(const SkPoint points[],
uint32_t flags,
const SkMatrix* local_matrix,
SkColor fallback_color) {
sk_sp<PaintShader> shader(new PaintShader(kLinearGradient));
sk_sp<PaintShader> shader(new PaintShader(Type::kLinearGradient));
// There are always two points, the start and the end.
shader->start_point_ = points[0];
......@@ -48,7 +48,7 @@ sk_sp<PaintShader> PaintShader::MakeRadialGradient(const SkPoint& center,
uint32_t flags,
const SkMatrix* local_matrix,
SkColor fallback_color) {
sk_sp<PaintShader> shader(new PaintShader(kRadialGradient));
sk_sp<PaintShader> shader(new PaintShader(Type::kRadialGradient));
shader->center_ = center;
shader->start_radius_ = shader->end_radius_ = radius;
......@@ -71,7 +71,7 @@ sk_sp<PaintShader> PaintShader::MakeTwoPointConicalGradient(
uint32_t flags,
const SkMatrix* local_matrix,
SkColor fallback_color) {
sk_sp<PaintShader> shader(new PaintShader(kTwoPointConicalGradient));
sk_sp<PaintShader> shader(new PaintShader(Type::kTwoPointConicalGradient));
shader->start_point_ = start;
shader->end_point_ = end;
......@@ -92,7 +92,7 @@ sk_sp<PaintShader> PaintShader::MakeSweepGradient(SkScalar cx,
uint32_t flags,
const SkMatrix* local_matrix,
SkColor fallback_color) {
sk_sp<PaintShader> shader(new PaintShader(kSweepGradient));
sk_sp<PaintShader> shader(new PaintShader(Type::kSweepGradient));
shader->center_ = SkPoint::Make(cx, cy);
shader->SetColorsAndPositions(colors, pos, color_count);
......@@ -103,27 +103,30 @@ sk_sp<PaintShader> PaintShader::MakeSweepGradient(SkScalar cx,
return shader;
}
sk_sp<PaintShader> PaintShader::MakeImage(sk_sp<const SkImage> image,
sk_sp<PaintShader> PaintShader::MakeImage(const PaintImage& image,
SkShader::TileMode tx,
SkShader::TileMode ty,
const SkMatrix* local_matrix) {
sk_sp<PaintShader> shader(new PaintShader(kImage));
sk_sp<PaintShader> shader(new PaintShader(Type::kImage));
shader->image_ = std::move(image);
shader->image_ = image;
shader->SetMatrixAndTiling(local_matrix, tx, ty);
return shader;
}
sk_sp<PaintShader> PaintShader::MakePaintRecord(sk_sp<PaintRecord> record,
const SkRect& tile,
SkShader::TileMode tx,
SkShader::TileMode ty,
const SkMatrix* local_matrix) {
sk_sp<PaintShader> shader(new PaintShader(kPaintRecord));
sk_sp<PaintShader> PaintShader::MakePaintRecord(
sk_sp<PaintRecord> record,
const SkRect& tile,
SkShader::TileMode tx,
SkShader::TileMode ty,
const SkMatrix* local_matrix,
ScalingBehavior scaling_behavior) {
sk_sp<PaintShader> shader(new PaintShader(Type::kPaintRecord));
shader->record_ = std::move(record);
shader->tile_ = tile;
shader->scaling_behavior_ = scaling_behavior;
shader->SetMatrixAndTiling(local_matrix, tx, ty);
return shader;
......@@ -137,10 +140,10 @@ sk_sp<SkShader> PaintShader::GetSkShader() const {
return cached_shader_;
switch (shader_type_) {
case kColor:
case Type::kColor:
// This will be handled by the fallback check below.
break;
case kLinearGradient: {
case Type::kLinearGradient: {
SkPoint points[2] = {start_point_, end_point_};
cached_shader_ = SkGradientShader::MakeLinear(
points, colors_.data(),
......@@ -149,37 +152,56 @@ sk_sp<SkShader> PaintShader::GetSkShader() const {
local_matrix_ ? &*local_matrix_ : nullptr);
break;
}
case kRadialGradient:
case Type::kRadialGradient:
cached_shader_ = SkGradientShader::MakeRadial(
center_, start_radius_, colors_.data(),
positions_.empty() ? nullptr : positions_.data(),
static_cast<int>(colors_.size()), tx_, flags_,
local_matrix_ ? &*local_matrix_ : nullptr);
break;
case kTwoPointConicalGradient:
case Type::kTwoPointConicalGradient:
cached_shader_ = SkGradientShader::MakeTwoPointConical(
start_point_, start_radius_, end_point_, end_radius_, colors_.data(),
positions_.empty() ? nullptr : positions_.data(),
static_cast<int>(colors_.size()), tx_, flags_,
local_matrix_ ? &*local_matrix_ : nullptr);
break;
case kSweepGradient:
case Type::kSweepGradient:
cached_shader_ = SkGradientShader::MakeSweep(
center_.x(), center_.y(), colors_.data(),
positions_.empty() ? nullptr : positions_.data(),
static_cast<int>(colors_.size()), flags_,
local_matrix_ ? &*local_matrix_ : nullptr);
break;
case kImage:
cached_shader_ = image_->makeShader(
case Type::kImage:
cached_shader_ = image_.sk_image()->makeShader(
tx_, ty_, local_matrix_ ? &*local_matrix_ : nullptr);
break;
case kPaintRecord:
cached_shader_ = SkShader::MakePictureShader(
ToSkPicture(record_, tile_), tx_, ty_,
local_matrix_ ? &*local_matrix_ : nullptr, nullptr);
case Type::kPaintRecord: {
auto picture = ToSkPicture(record_, tile_);
switch (scaling_behavior_) {
// For raster scale, we create a picture shader directly.
case ScalingBehavior::kRasterAtScale:
cached_shader_ = SkShader::MakePictureShader(
std::move(picture), tx_, ty_,
local_matrix_ ? &*local_matrix_ : nullptr, nullptr);
break;
// For fixed scale, we create an image shader with and image backed by
// the picture.
case ScalingBehavior::kFixedScale: {
auto image = SkImage::MakeFromPicture(
std::move(picture), SkISize::Make(tile_.width(), tile_.height()),
nullptr, nullptr, SkImage::BitDepth::kU8,
SkColorSpace::MakeSRGB());
cached_shader_ = image->makeShader(
tx_, ty_, local_matrix_ ? &*local_matrix_ : nullptr);
break;
}
}
break;
case kShaderCount:
}
case Type::kShaderCount:
NOTREACHED();
break;
}
......
......@@ -10,6 +10,7 @@
#include "base/optional.h"
#include "cc/paint/paint_export.h"
#include "cc/paint/paint_image.h"
#include "third_party/skia/include/core/SkImage.h"
#include "third_party/skia/include/core/SkScalar.h"
#include "third_party/skia/include/core/SkShader.h"
......@@ -21,6 +22,22 @@ using PaintRecord = PaintOpBuffer;
class CC_PAINT_EXPORT PaintShader : public SkRefCnt {
public:
enum class Type {
kColor,
kLinearGradient,
kRadialGradient,
kTwoPointConicalGradient,
kSweepGradient,
kImage,
kPaintRecord,
kShaderCount
};
// Scaling behavior dictates how a PaintRecord shader will behave. Use
// RasterAtScale to create a picture shader. Use FixedScale to create an image
// shader that is backed by the paint record.
enum class ScalingBehavior { kRasterAtScale, kFixedScale };
static sk_sp<PaintShader> MakeColor(SkColor color);
static sk_sp<PaintShader> MakeLinearGradient(
......@@ -67,39 +84,35 @@ class CC_PAINT_EXPORT PaintShader : public SkRefCnt {
const SkMatrix* local_matrix = nullptr,
SkColor fallback_color = SK_ColorTRANSPARENT);
static sk_sp<PaintShader> MakeImage(sk_sp<const SkImage> image,
static sk_sp<PaintShader> MakeImage(const PaintImage& image,
SkShader::TileMode tx,
SkShader::TileMode ty,
const SkMatrix* local_matrix);
static sk_sp<PaintShader> MakePaintRecord(sk_sp<PaintRecord> record,
const SkRect& tile,
SkShader::TileMode tx,
SkShader::TileMode ty,
const SkMatrix* local_matrix);
static sk_sp<PaintShader> MakePaintRecord(
sk_sp<PaintRecord> record,
const SkRect& tile,
SkShader::TileMode tx,
SkShader::TileMode ty,
const SkMatrix* local_matrix,
ScalingBehavior scaling_behavior = ScalingBehavior::kRasterAtScale);
~PaintShader() override;
SkMatrix GetLocalMatrix() const {
return local_matrix_ ? *local_matrix_ : SkMatrix::I();
}
Type shader_type() const { return shader_type_; }
const PaintImage& paint_image() {
DCHECK_EQ(Type::kImage, shader_type_);
return image_;
}
bool IsOpaque() const;
private:
friend class PaintFlags;
enum Type {
kColor,
kLinearGradient,
kRadialGradient,
kTwoPointConicalGradient,
kSweepGradient,
kImage,
kPaintRecord,
kShaderCount
};
explicit PaintShader(Type type);
sk_sp<SkShader> GetSkShader() const;
......@@ -112,7 +125,7 @@ class CC_PAINT_EXPORT PaintShader : public SkRefCnt {
SkShader::TileMode ty);
void SetFlagsAndFallback(uint32_t flags, SkColor fallback_color);
Type shader_type_ = kShaderCount;
Type shader_type_ = Type::kShaderCount;
uint32_t flags_ = 0;
SkScalar end_radius_ = 0;
......@@ -120,6 +133,7 @@ class CC_PAINT_EXPORT PaintShader : public SkRefCnt {
SkShader::TileMode tx_ = SkShader::kClamp_TileMode;
SkShader::TileMode ty_ = SkShader::kClamp_TileMode;
SkColor fallback_color_ = SK_ColorTRANSPARENT;
ScalingBehavior scaling_behavior_ = ScalingBehavior::kRasterAtScale;
base::Optional<SkMatrix> local_matrix_;
SkPoint center_ = SkPoint::Make(0, 0);
......@@ -128,7 +142,7 @@ class CC_PAINT_EXPORT PaintShader : public SkRefCnt {
SkPoint start_point_ = SkPoint::Make(0, 0);
SkPoint end_point_ = SkPoint::Make(0, 0);
sk_sp<const SkImage> image_;
PaintImage image_;
sk_sp<PaintRecord> record_;
std::vector<SkColor> colors_;
......
......@@ -123,9 +123,7 @@ PaintImage DragImage::ResizeAndOrientImage(
canvas->concat(AffineTransformToSkMatrix(transform));
canvas->drawImage(image.sk_image(), 0, 0, &paint);
return PaintImage(image.stable_id(), surface->makeImageSnapshot(),
image.animation_type(), image.completion_state(),
image.frame_count());
return image.CloneWithSkImage(surface->makeImageSnapshot());
}
FloatSize DragImage::ClampedImageScale(const IntSize& image_size,
......
......@@ -241,7 +241,7 @@ sk_sp<PaintShader> CreatePatternShader(const PaintImage& image,
SkShader::TileMode tmx,
SkShader::TileMode tmy) {
if (spacing.IsZero()) {
return PaintShader::MakeImage(image.sk_image(), tmx, tmy, &shader_matrix);
return PaintShader::MakeImage(image, tmx, tmy, &shader_matrix);
}
// Arbitrary tiling is currently only supported for SkPictureShader, so we use
......@@ -363,13 +363,13 @@ PaintImage Image::PaintImageForCurrentFrame() {
bool Image::ApplyShader(PaintFlags& flags, const SkMatrix& local_matrix) {
// Default shader impl: attempt to build a shader based on the current frame
// SkImage.
sk_sp<SkImage> image = ImageForCurrentFrame();
PaintImage image = PaintImageForCurrentFrame();
if (!image)
return false;
flags.setShader(
PaintShader::MakeImage(std::move(image), SkShader::kRepeat_TileMode,
SkShader::kRepeat_TileMode, &local_matrix));
flags.setShader(PaintShader::MakeImage(image, SkShader::kRepeat_TileMode,
SkShader::kRepeat_TileMode,
&local_matrix));
if (!flags.HasShader())
return false;
......
......@@ -5,10 +5,10 @@
#include "platform/graphics/ImagePattern.h"
#include "platform/graphics/Image.h"
#include "platform/graphics/paint/PaintRecorder.h"
#include "platform/graphics/paint/PaintShader.h"
#include "platform/graphics/skia/SkiaUtils.h"
#include "third_party/skia/include/core/SkImage.h"
#include "third_party/skia/include/core/SkPictureRecorder.h"
#include "third_party/skia/include/core/SkSurface.h"
namespace blink {
......@@ -19,7 +19,7 @@ PassRefPtr<ImagePattern> ImagePattern::Create(PassRefPtr<Image> image,
}
ImagePattern::ImagePattern(PassRefPtr<Image> image, RepeatMode repeat_mode)
: Pattern(repeat_mode), tile_image_(image->ImageForCurrentFrame()) {
: Pattern(repeat_mode), tile_image_(image->PaintImageForCurrentFrame()) {
previous_local_matrix_.setIdentity();
}
......@@ -54,32 +54,29 @@ sk_sp<PaintShader> ImagePattern::CreateShader(const SkMatrix& local_matrix) {
// Create a transparent image 2 pixels wider and/or taller than the
// original, then copy the orignal into the middle of it.
const SkISize tile_size =
SkISize::Make(tile_image_->width() + 2 * border_pixel_x,
tile_image_->height() + 2 * border_pixel_y);
SkPictureRecorder recorder;
recorder.beginRecording(tile_size.width(), tile_size.height());
const SkRect tile_bounds =
SkRect::MakeWH(tile_image_.sk_image()->width() + 2 * border_pixel_x,
tile_image_.sk_image()->height() + 2 * border_pixel_y);
PaintRecorder recorder;
auto* canvas = recorder.beginRecording(tile_bounds);
SkPaint paint;
PaintFlags paint;
paint.setBlendMode(SkBlendMode::kSrc);
recorder.getRecordingCanvas()->drawImage(tile_image_, border_pixel_x,
border_pixel_y, &paint);
// Note: we use a picture *image* (as opposed to a picture *shader*) to
// lock-in the resolution (for 1px padding in particular).
sk_sp<SkImage> tile_image = SkImage::MakeFromPicture(
recorder.finishRecordingAsPicture(), tile_size, nullptr, nullptr,
SkImage::BitDepth::kU8, SkColorSpace::MakeSRGB());
canvas->drawImage(tile_image_, border_pixel_x, border_pixel_y, &paint);
previous_local_matrix_ = local_matrix;
SkMatrix adjusted_matrix(local_matrix);
adjusted_matrix.postTranslate(-border_pixel_x, -border_pixel_y);
return PaintShader::MakeImage(std::move(tile_image), tile_mode_x, tile_mode_y,
&adjusted_matrix);
// Note: we specify kFixedScale to lock-in the resolution (for 1px padding in
// particular).
return PaintShader::MakePaintRecord(
recorder.finishRecordingAsPicture(), tile_bounds, tile_mode_x,
tile_mode_y, &adjusted_matrix, PaintShader::ScalingBehavior::kFixedScale);
}
bool ImagePattern::IsTextureBacked() const {
return tile_image_ && tile_image_->isTextureBacked();
return tile_image_.sk_image() && tile_image_.sk_image()->isTextureBacked();
}
} // namespace blink
......@@ -6,8 +6,7 @@
#define ImagePattern_h
#include "platform/graphics/Pattern.h"
class SkImage;
#include "platform/graphics/paint/PaintImage.h"
namespace blink {
......@@ -27,7 +26,7 @@ class PLATFORM_EXPORT ImagePattern final : public Pattern {
ImagePattern(PassRefPtr<Image>, RepeatMode);
SkMatrix previous_local_matrix_;
sk_sp<SkImage> tile_image_;
PaintImage tile_image_;
};
} // namespace blink
......
......@@ -38,8 +38,9 @@ sk_sp<cc::PaintShader> CreateImageRepShaderForScale(
shader_scale.setScaleY(local_matrix.getScaleY() / scale);
return cc::PaintShader::MakeImage(
SkImage::MakeFromBitmap(image_rep.sk_bitmap()), tile_mode, tile_mode,
&shader_scale);
cc::PaintImage(cc::PaintImage::kNonLazyStableId,
SkImage::MakeFromBitmap(image_rep.sk_bitmap())),
tile_mode, tile_mode, &shader_scale);
}
sk_sp<cc::PaintShader> CreateGradientShader(int start_point,
......
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