[go: nahoru, domu]

blob: 8b0fbfc46dcfa6da4d9d57cd613d72f9b8051ddd [file] [log] [blame]
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CC_PAINT_PAINT_SHADER_H_
#define CC_PAINT_PAINT_SHADER_H_
#include <memory>
#include <vector>
#include "base/gtest_prod_util.h"
#include "base/types/optional_util.h"
#include "cc/paint/image_analysis_state.h"
#include "cc/paint/paint_export.h"
#include "cc/paint/paint_flags.h"
#include "cc/paint/paint_image.h"
#include "cc/paint/paint_record.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/skia/include/core/SkImage.h"
#include "third_party/skia/include/core/SkScalar.h"
#include "third_party/skia/include/effects/SkGradientShader.h"
#include "ui/gfx/geometry/size_f.h"
class SkShader;
namespace gpu {
struct Mailbox;
}
namespace cc {
class ImageProvider;
class CC_PAINT_EXPORT PaintShader : public SkRefCnt {
public:
enum class Type : uint8_t {
kEmpty,
kColor,
kLinearGradient,
kRadialGradient,
kTwoPointConicalGradient,
kSweepGradient,
kImage,
kPaintRecord,
kShaderCount
};
using RecordShaderId = uint32_t;
static const RecordShaderId kInvalidRecordShaderId;
// 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 : uint8_t { kRasterAtScale, kFixedScale };
static sk_sp<PaintShader> MakeEmpty();
static sk_sp<PaintShader> MakeColor(SkColor4f color);
// TODO(crbug.com/1155544) SkMatrix is deprecated in favor of SkM44.
static sk_sp<PaintShader> MakeLinearGradient(
const SkPoint* points,
const SkColor4f colors[],
const SkScalar* pos,
int count,
SkTileMode mode,
SkGradientShader::Interpolation interpolation = DefaultInterpolation(),
uint32_t flags = 0,
const SkMatrix* local_matrix = nullptr,
SkColor4f fallback_color = SkColors::kTransparent);
static sk_sp<PaintShader> MakeRadialGradient(
const SkPoint& center,
SkScalar radius,
const SkColor4f colors[],
const SkScalar pos[],
int color_count,
SkTileMode mode,
SkGradientShader::Interpolation interpolation = DefaultInterpolation(),
uint32_t flags = 0,
const SkMatrix* local_matrix = nullptr,
SkColor4f fallback_color = SkColors::kTransparent);
static sk_sp<PaintShader> MakeTwoPointConicalGradient(
const SkPoint& start,
SkScalar start_radius,
const SkPoint& end,
SkScalar end_radius,
const SkColor4f colors[],
const SkScalar pos[],
int color_count,
SkTileMode mode,
SkGradientShader::Interpolation interpolation = DefaultInterpolation(),
uint32_t flags = 0,
const SkMatrix* local_matrix = nullptr,
SkColor4f fallback_color = SkColors::kTransparent);
static sk_sp<PaintShader> MakeSweepGradient(
SkScalar cx,
SkScalar cy,
const SkColor4f colors[],
const SkScalar pos[],
int color_count,
SkTileMode mode,
SkScalar start_degrees,
SkScalar end_degrees,
SkGradientShader::Interpolation interpolation = DefaultInterpolation(),
uint32_t flags = 0,
const SkMatrix* local_matrix = nullptr,
SkColor4f fallback_color = SkColors::kTransparent);
// |tile_rect| is not null only if the |image| is paint worklet backed.
static sk_sp<PaintShader> MakeImage(const PaintImage& image,
SkTileMode tx,
SkTileMode ty,
const SkMatrix* local_matrix,
const SkRect* tile_rect = nullptr);
static sk_sp<PaintShader> MakePaintRecord(
PaintRecord record,
const SkRect& tile,
SkTileMode tx,
SkTileMode ty,
const SkMatrix* local_matrix,
ScalingBehavior scaling_behavior = ScalingBehavior::kRasterAtScale);
static size_t GetSerializedSize(const PaintShader* shader);
PaintShader(const PaintShader&) = delete;
~PaintShader() override;
PaintShader& operator=(const PaintShader&) = delete;
void set_has_animated_images(bool has_animated_images) {
image_analysis_state_ = has_animated_images
? ImageAnalysisState::kAnimatedImages
: ImageAnalysisState::kNoAnimatedImages;
}
ImageAnalysisState image_analysis_state() const {
return image_analysis_state_;
}
bool has_discardable_images() const;
SkMatrix GetLocalMatrix() const {
return local_matrix_ ? *local_matrix_ : SkMatrix::I();
}
Type shader_type() const { return shader_type_; }
const PaintImage& paint_image() const {
DCHECK_EQ(Type::kImage, shader_type_);
return image_;
}
const PaintRecord* paint_record() const {
return base::OptionalToPtr(record_);
}
bool GetRasterizationTileRect(const SkMatrix& ctm, SkRect* tile_rect) const {
return GetClampedRasterizationTileRect(ctm, /*max_texture_size=*/0,
tile_rect);
}
SkTileMode tx() const { return tx_; }
SkTileMode ty() const { return ty_; }
SkRect tile() const { return tile_; }
bool IsOpaque() const;
// Returns true if the shader looks like it is valid (ie the members required
// for this shader type all look reasonable. Returns false otherwise. Note
// that this is a best effort function since truly validating whether the
// shader is correct is hard.
bool IsValid() const;
bool EqualsForTesting(const PaintShader& other) const;
RecordShaderId paint_record_shader_id() const {
DCHECK(id_ == kInvalidRecordShaderId || shader_type_ == Type::kPaintRecord);
return id_;
}
private:
friend class PaintFlags;
friend class PaintOpHelper;
friend class PaintOpReader;
friend class PaintOpSerializationTestUtils;
friend class PaintOpWriter;
friend class ScopedRasterFlags;
friend class ShaderPaintFilter;
FRIEND_TEST_ALL_PREFIXES(PaintShaderTest, DecodePaintRecord);
FRIEND_TEST_ALL_PREFIXES(PaintOpBufferTest, PaintRecordShaderSerialization);
FRIEND_TEST_ALL_PREFIXES(PaintOpBufferTest, RecordShadersCached);
static SkGradientShader::Interpolation DefaultInterpolation() {
SkGradientShader::Interpolation default_interpolation;
return default_interpolation;
}
explicit PaintShader(Type type);
bool GetClampedRasterizationTileRect(const SkMatrix& ctm,
int max_texture_size,
SkRect* tile_rect) const;
sk_sp<SkShader> GetSkShader(PaintFlags::FilterQuality quality) const;
// If the type needs a resolve skia object (e.g. SkImage or SkPicture), this
// will create and cache it internally. Most types do not need this, but it
// is safe to call on any type.
void ResolveSkObjects(const gfx::SizeF* raster_scale = nullptr,
ImageProvider* image_provider = nullptr);
// Creates a PaintShader to be rasterized at the given ctm. |raster_scale| is
// set to the scale at which the record should be rasterized when the shader
// is used.
// Note that this does not create a skia backing for the shader.
// Valid only for PaintRecord backed shaders.
sk_sp<PaintShader> CreateScaledPaintRecord(const SkMatrix& ctm,
int max_texture_size,
gfx::SizeF* raster_scale) const;
// Creates a PaintShader with images from |image_provider| to be rasterized
// at the given ctm.
// |transfer_cache_entry_id| is set to the transfer cache id for the image, if
// the decode is backed by the transfer cache.
// |raster_quality| is set to the filter quality the shader should be
// rasterized with.
// Valid only for PaintImage backed shaders.
sk_sp<PaintShader> CreateDecodedImage(
const SkMatrix& ctm,
PaintFlags::FilterQuality requested_quality,
ImageProvider* image_provider,
uint32_t* transfer_cache_entry_id,
PaintFlags::FilterQuality* raster_quality,
bool* needs_mips,
gpu::Mailbox* mailbox) const;
// Creates a paint record shader for worklet-backed images.
sk_sp<PaintShader> CreatePaintWorkletRecord(
ImageProvider* image_provider) const;
void SetColorsAndPositions(const SkColor4f* colors,
const SkScalar* positions,
int count);
void SetMatrixAndTiling(const SkMatrix* matrix, SkTileMode tx, SkTileMode ty);
void SetFlagsAndFallback(uint32_t flags, SkColor4f fallback_color);
void SetGradientInterpolation(SkGradientShader::Interpolation interpolation) {
gradient_interpolation_ = interpolation;
}
Type shader_type_ = Type::kShaderCount;
uint32_t flags_ = 0;
SkScalar end_radius_ = 0;
SkScalar start_radius_ = 0;
SkTileMode tx_ = SkTileMode::kClamp;
SkTileMode ty_ = SkTileMode::kClamp;
SkColor4f fallback_color_ = SkColors::kTransparent;
ScalingBehavior scaling_behavior_ = ScalingBehavior::kRasterAtScale;
absl::optional<SkMatrix> local_matrix_;
SkPoint center_ = SkPoint::Make(0, 0);
SkRect tile_ = SkRect::MakeEmpty();
SkPoint start_point_ = SkPoint::Make(0, 0);
SkPoint end_point_ = SkPoint::Make(0, 0);
SkScalar start_degrees_ = 0;
SkScalar end_degrees_ = 0;
PaintImage image_;
absl::optional<PaintRecord> record_;
RecordShaderId id_ = kInvalidRecordShaderId;
// For decoded PaintRecord shaders, specifies the scale at which the record
// will be rasterized.
absl::optional<gfx::SizeF> tile_scale_;
std::vector<SkColor4f> colors_;
std::vector<SkScalar> positions_;
SkGradientShader::Interpolation gradient_interpolation_;
// Cached intermediates, for Paint objects that may not be thread-safe
sk_sp<SkPicture> sk_cached_picture_;
sk_sp<SkImage> sk_cached_image_;
ImageAnalysisState image_analysis_state_ = ImageAnalysisState::kNoAnalysis;
};
} // namespace cc
#endif // CC_PAINT_PAINT_SHADER_H_