vmpstr | 7b99c958 | 2017-06-08 21:39:45 | [diff] [blame] | 1 | // Copyright 2017 The Chromium Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #include "cc/paint/paint_shader.h" |
| 6 | |
Adrienne Walker | 90b79a2 | 2018-05-08 21:40:42 | [diff] [blame] | 7 | #include "base/atomic_sequence_num.h" |
Khushal | 67c8c74 | 2018-05-16 18:05:05 | [diff] [blame] | 8 | #include "cc/paint/paint_image_builder.h" |
Khushal | 252af33 | 2018-02-14 05:03:09 | [diff] [blame] | 9 | #include "cc/paint/paint_op_writer.h" |
vmpstr | 7b99c958 | 2017-06-08 21:39:45 | [diff] [blame] | 10 | #include "cc/paint/paint_record.h" |
Khushal | 7ae9c79 | 2017-10-05 22:26:32 | [diff] [blame] | 11 | #include "third_party/skia/include/core/SkPictureRecorder.h" |
vmpstr | 7b99c958 | 2017-06-08 21:39:45 | [diff] [blame] | 12 | #include "third_party/skia/include/effects/SkGradientShader.h" |
| 13 | |
| 14 | namespace cc { |
Khushal | 7ae9c79 | 2017-10-05 22:26:32 | [diff] [blame] | 15 | namespace { |
Lei Zhang | 868717c | 2018-05-09 04:33:56 | [diff] [blame] | 16 | base::AtomicSequenceNumber g_next_shader_id; |
Khushal | 7ae9c79 | 2017-10-05 22:26:32 | [diff] [blame] | 17 | |
| 18 | sk_sp<SkPicture> ToSkPicture(sk_sp<PaintRecord> record, |
| 19 | const SkRect& bounds, |
Khushal | 9fd411f | 2018-01-20 02:09:51 | [diff] [blame] | 20 | const gfx::SizeF* raster_scale, |
Khushal | 7ae9c79 | 2017-10-05 22:26:32 | [diff] [blame] | 21 | ImageProvider* image_provider) { |
| 22 | SkPictureRecorder recorder; |
Adrienne Walker | c4bdc13e | 2018-06-27 00:56:30 | [diff] [blame] | 23 | SkCanvas* canvas = |
| 24 | recorder.beginRecording(SkRect::MakeWH(bounds.width(), bounds.height())); |
| 25 | canvas->translate(-bounds.fLeft, -bounds.fTop); |
Khushal | 9fd411f | 2018-01-20 02:09:51 | [diff] [blame] | 26 | if (raster_scale) |
| 27 | canvas->scale(raster_scale->width(), raster_scale->height()); |
Wei Li | 2a9bfe4 | 2018-01-13 05:42:56 | [diff] [blame] | 28 | record->Playback(canvas, PlaybackParams(image_provider)); |
Khushal | 7ae9c79 | 2017-10-05 22:26:32 | [diff] [blame] | 29 | return recorder.finishRecordingAsPicture(); |
| 30 | } |
| 31 | |
Khushal | 67c8c74 | 2018-05-16 18:05:05 | [diff] [blame] | 32 | bool CompareMatrices(const SkMatrix& a, |
| 33 | const SkMatrix& b, |
| 34 | bool ignore_scaling_differences) { |
| 35 | if (!ignore_scaling_differences) |
| 36 | return PaintOp::AreSkMatricesEqual(a, b); |
| 37 | |
| 38 | SkSize scale; |
| 39 | SkMatrix a_without_scale; |
| 40 | SkMatrix b_without_scale; |
Khushal | 67c8c74 | 2018-05-16 18:05:05 | [diff] [blame] | 41 | |
Khushal | ceacc10a | 2018-06-01 17:53:53 | [diff] [blame] | 42 | const bool decomposes = a.decomposeScale(&scale, &a_without_scale); |
| 43 | if (decomposes != b.decomposeScale(&scale, &b_without_scale)) |
| 44 | return false; |
| 45 | |
| 46 | if (!decomposes) |
| 47 | return true; |
Khushal | 67c8c74 | 2018-05-16 18:05:05 | [diff] [blame] | 48 | return PaintOp::AreSkMatricesEqual(a_without_scale, b_without_scale); |
| 49 | } |
| 50 | |
Khushal | 515436e2 | 2019-04-05 05:03:51 | [diff] [blame] | 51 | SkRect AdjustForMaxTextureSize(SkRect tile, int max_texture_size) { |
| 52 | if (max_texture_size == 0) |
| 53 | return tile; |
| 54 | |
| 55 | if (tile.width() < max_texture_size && tile.height() < max_texture_size) |
| 56 | return tile; |
| 57 | |
| 58 | float down_scale = max_texture_size / std::max(tile.width(), tile.height()); |
| 59 | tile = SkRect::MakeXYWH(tile.x(), tile.y(), |
| 60 | SkScalarFloorToScalar(tile.width() * down_scale), |
| 61 | SkScalarFloorToScalar(tile.height() * down_scale)); |
| 62 | return tile; |
| 63 | } |
| 64 | |
Khushal | 7ae9c79 | 2017-10-05 22:26:32 | [diff] [blame] | 65 | } // namespace |
vmpstr | 7b99c958 | 2017-06-08 21:39:45 | [diff] [blame] | 66 | |
Adrienne Walker | 90b79a2 | 2018-05-08 21:40:42 | [diff] [blame] | 67 | const PaintShader::RecordShaderId PaintShader::kInvalidRecordShaderId = -1; |
| 68 | |
Florin Malita | c677eac | 2018-11-08 18:51:18 | [diff] [blame] | 69 | sk_sp<PaintShader> PaintShader::MakeEmpty() { |
| 70 | sk_sp<PaintShader> shader(new PaintShader(Type::kEmpty)); |
| 71 | |
| 72 | shader->CreateSkShader(); |
| 73 | return shader; |
| 74 | } |
| 75 | |
Adrienne Walker | 8d85c9d7 | 2017-07-07 23:16:46 | [diff] [blame] | 76 | sk_sp<PaintShader> PaintShader::MakeColor(SkColor color) { |
Vladimir Levin | 7440d46 | 2017-07-21 23:53:51 | [diff] [blame] | 77 | sk_sp<PaintShader> shader(new PaintShader(Type::kColor)); |
Vladimir Levin | 4ca1c84 | 2017-07-10 22:09:31 | [diff] [blame] | 78 | |
| 79 | // Just one color. Store it in the fallback color. Easy. |
| 80 | shader->fallback_color_ = color; |
| 81 | |
Khushal | a866a80 | 2017-10-05 18:21:00 | [diff] [blame] | 82 | shader->CreateSkShader(); |
Vladimir Levin | 4ca1c84 | 2017-07-10 22:09:31 | [diff] [blame] | 83 | return shader; |
vmpstr | 7b99c958 | 2017-06-08 21:39:45 | [diff] [blame] | 84 | } |
| 85 | |
Adrienne Walker | 8d85c9d7 | 2017-07-07 23:16:46 | [diff] [blame] | 86 | sk_sp<PaintShader> PaintShader::MakeLinearGradient(const SkPoint points[], |
| 87 | const SkColor colors[], |
| 88 | const SkScalar pos[], |
| 89 | int count, |
Mike Reed | 500aabf | 2019-04-04 12:50:32 | [diff] [blame] | 90 | SkTileMode mode, |
Adrienne Walker | 8d85c9d7 | 2017-07-07 23:16:46 | [diff] [blame] | 91 | uint32_t flags, |
| 92 | const SkMatrix* local_matrix, |
| 93 | SkColor fallback_color) { |
Vladimir Levin | 7440d46 | 2017-07-21 23:53:51 | [diff] [blame] | 94 | sk_sp<PaintShader> shader(new PaintShader(Type::kLinearGradient)); |
Vladimir Levin | 4ca1c84 | 2017-07-10 22:09:31 | [diff] [blame] | 95 | |
| 96 | // There are always two points, the start and the end. |
| 97 | shader->start_point_ = points[0]; |
| 98 | shader->end_point_ = points[1]; |
| 99 | shader->SetColorsAndPositions(colors, pos, count); |
| 100 | shader->SetMatrixAndTiling(local_matrix, mode, mode); |
| 101 | shader->SetFlagsAndFallback(flags, fallback_color); |
| 102 | |
Khushal | a866a80 | 2017-10-05 18:21:00 | [diff] [blame] | 103 | shader->CreateSkShader(); |
Vladimir Levin | 4ca1c84 | 2017-07-10 22:09:31 | [diff] [blame] | 104 | return shader; |
vmpstr | 7b99c958 | 2017-06-08 21:39:45 | [diff] [blame] | 105 | } |
| 106 | |
Adrienne Walker | 8d85c9d7 | 2017-07-07 23:16:46 | [diff] [blame] | 107 | sk_sp<PaintShader> PaintShader::MakeRadialGradient(const SkPoint& center, |
| 108 | SkScalar radius, |
| 109 | const SkColor colors[], |
| 110 | const SkScalar pos[], |
Vladimir Levin | 4ca1c84 | 2017-07-10 22:09:31 | [diff] [blame] | 111 | int count, |
Mike Reed | 500aabf | 2019-04-04 12:50:32 | [diff] [blame] | 112 | SkTileMode mode, |
Adrienne Walker | 8d85c9d7 | 2017-07-07 23:16:46 | [diff] [blame] | 113 | uint32_t flags, |
| 114 | const SkMatrix* local_matrix, |
| 115 | SkColor fallback_color) { |
Vladimir Levin | 7440d46 | 2017-07-21 23:53:51 | [diff] [blame] | 116 | sk_sp<PaintShader> shader(new PaintShader(Type::kRadialGradient)); |
Vladimir Levin | 4ca1c84 | 2017-07-10 22:09:31 | [diff] [blame] | 117 | |
| 118 | shader->center_ = center; |
| 119 | shader->start_radius_ = shader->end_radius_ = radius; |
| 120 | shader->SetColorsAndPositions(colors, pos, count); |
| 121 | shader->SetMatrixAndTiling(local_matrix, mode, mode); |
| 122 | shader->SetFlagsAndFallback(flags, fallback_color); |
| 123 | |
Khushal | a866a80 | 2017-10-05 18:21:00 | [diff] [blame] | 124 | shader->CreateSkShader(); |
Vladimir Levin | 4ca1c84 | 2017-07-10 22:09:31 | [diff] [blame] | 125 | return shader; |
vmpstr | 7b99c958 | 2017-06-08 21:39:45 | [diff] [blame] | 126 | } |
| 127 | |
Adrienne Walker | 8d85c9d7 | 2017-07-07 23:16:46 | [diff] [blame] | 128 | sk_sp<PaintShader> PaintShader::MakeTwoPointConicalGradient( |
vmpstr | 7b99c958 | 2017-06-08 21:39:45 | [diff] [blame] | 129 | const SkPoint& start, |
| 130 | SkScalar start_radius, |
| 131 | const SkPoint& end, |
| 132 | SkScalar end_radius, |
| 133 | const SkColor colors[], |
| 134 | const SkScalar pos[], |
Vladimir Levin | 4ca1c84 | 2017-07-10 22:09:31 | [diff] [blame] | 135 | int count, |
Mike Reed | 500aabf | 2019-04-04 12:50:32 | [diff] [blame] | 136 | SkTileMode mode, |
vmpstr | 7b99c958 | 2017-06-08 21:39:45 | [diff] [blame] | 137 | uint32_t flags, |
| 138 | const SkMatrix* local_matrix, |
| 139 | SkColor fallback_color) { |
Vladimir Levin | 7440d46 | 2017-07-21 23:53:51 | [diff] [blame] | 140 | sk_sp<PaintShader> shader(new PaintShader(Type::kTwoPointConicalGradient)); |
Vladimir Levin | 4ca1c84 | 2017-07-10 22:09:31 | [diff] [blame] | 141 | |
| 142 | shader->start_point_ = start; |
| 143 | shader->end_point_ = end; |
| 144 | shader->start_radius_ = start_radius; |
| 145 | shader->end_radius_ = end_radius; |
| 146 | shader->SetColorsAndPositions(colors, pos, count); |
| 147 | shader->SetMatrixAndTiling(local_matrix, mode, mode); |
| 148 | shader->SetFlagsAndFallback(flags, fallback_color); |
| 149 | |
Khushal | a866a80 | 2017-10-05 18:21:00 | [diff] [blame] | 150 | shader->CreateSkShader(); |
Vladimir Levin | 4ca1c84 | 2017-07-10 22:09:31 | [diff] [blame] | 151 | return shader; |
vmpstr | 7b99c958 | 2017-06-08 21:39:45 | [diff] [blame] | 152 | } |
| 153 | |
Adrienne Walker | 8d85c9d7 | 2017-07-07 23:16:46 | [diff] [blame] | 154 | sk_sp<PaintShader> PaintShader::MakeSweepGradient(SkScalar cx, |
| 155 | SkScalar cy, |
| 156 | const SkColor colors[], |
| 157 | const SkScalar pos[], |
| 158 | int color_count, |
Mike Reed | 500aabf | 2019-04-04 12:50:32 | [diff] [blame] | 159 | SkTileMode mode, |
Florin Malita | 0786698 | 2017-08-07 21:11:50 | [diff] [blame] | 160 | SkScalar start_degrees, |
| 161 | SkScalar end_degrees, |
Adrienne Walker | 8d85c9d7 | 2017-07-07 23:16:46 | [diff] [blame] | 162 | uint32_t flags, |
| 163 | const SkMatrix* local_matrix, |
| 164 | SkColor fallback_color) { |
Vladimir Levin | 7440d46 | 2017-07-21 23:53:51 | [diff] [blame] | 165 | sk_sp<PaintShader> shader(new PaintShader(Type::kSweepGradient)); |
Vladimir Levin | 4ca1c84 | 2017-07-10 22:09:31 | [diff] [blame] | 166 | |
| 167 | shader->center_ = SkPoint::Make(cx, cy); |
Florin Malita | 0786698 | 2017-08-07 21:11:50 | [diff] [blame] | 168 | shader->start_degrees_ = start_degrees; |
| 169 | shader->end_degrees_ = end_degrees; |
Vladimir Levin | 4ca1c84 | 2017-07-10 22:09:31 | [diff] [blame] | 170 | shader->SetColorsAndPositions(colors, pos, color_count); |
Florin Malita | 0786698 | 2017-08-07 21:11:50 | [diff] [blame] | 171 | shader->SetMatrixAndTiling(local_matrix, mode, mode); |
Vladimir Levin | 4ca1c84 | 2017-07-10 22:09:31 | [diff] [blame] | 172 | shader->SetFlagsAndFallback(flags, fallback_color); |
| 173 | |
Khushal | a866a80 | 2017-10-05 18:21:00 | [diff] [blame] | 174 | shader->CreateSkShader(); |
Vladimir Levin | 4ca1c84 | 2017-07-10 22:09:31 | [diff] [blame] | 175 | return shader; |
vmpstr | 7b99c958 | 2017-06-08 21:39:45 | [diff] [blame] | 176 | } |
| 177 | |
Vladimir Levin | 7440d46 | 2017-07-21 23:53:51 | [diff] [blame] | 178 | sk_sp<PaintShader> PaintShader::MakeImage(const PaintImage& image, |
Mike Reed | 500aabf | 2019-04-04 12:50:32 | [diff] [blame] | 179 | SkTileMode tx, |
| 180 | SkTileMode ty, |
Xida Chen | 0481c52 | 2019-08-07 00:54:46 | [diff] [blame] | 181 | const SkMatrix* local_matrix, |
| 182 | const SkRect* tile_rect) { |
Vladimir Levin | 7440d46 | 2017-07-21 23:53:51 | [diff] [blame] | 183 | sk_sp<PaintShader> shader(new PaintShader(Type::kImage)); |
Vladimir Levin | 4ca1c84 | 2017-07-10 22:09:31 | [diff] [blame] | 184 | |
Vladimir Levin | 7440d46 | 2017-07-21 23:53:51 | [diff] [blame] | 185 | shader->image_ = image; |
Vladimir Levin | 4ca1c84 | 2017-07-10 22:09:31 | [diff] [blame] | 186 | shader->SetMatrixAndTiling(local_matrix, tx, ty); |
Xida Chen | 0481c52 | 2019-08-07 00:54:46 | [diff] [blame] | 187 | if (tile_rect) { |
| 188 | DCHECK(image.IsPaintWorklet()); |
| 189 | shader->tile_ = *tile_rect; |
| 190 | } |
Vladimir Levin | 4ca1c84 | 2017-07-10 22:09:31 | [diff] [blame] | 191 | |
Khushal | a866a80 | 2017-10-05 18:21:00 | [diff] [blame] | 192 | shader->CreateSkShader(); |
Vladimir Levin | 4ca1c84 | 2017-07-10 22:09:31 | [diff] [blame] | 193 | return shader; |
vmpstr | 7b99c958 | 2017-06-08 21:39:45 | [diff] [blame] | 194 | } |
| 195 | |
Vladimir Levin | 7440d46 | 2017-07-21 23:53:51 | [diff] [blame] | 196 | sk_sp<PaintShader> PaintShader::MakePaintRecord( |
| 197 | sk_sp<PaintRecord> record, |
| 198 | const SkRect& tile, |
Mike Reed | 500aabf | 2019-04-04 12:50:32 | [diff] [blame] | 199 | SkTileMode tx, |
| 200 | SkTileMode ty, |
Vladimir Levin | 7440d46 | 2017-07-21 23:53:51 | [diff] [blame] | 201 | const SkMatrix* local_matrix, |
| 202 | ScalingBehavior scaling_behavior) { |
| 203 | sk_sp<PaintShader> shader(new PaintShader(Type::kPaintRecord)); |
Vladimir Levin | 4ca1c84 | 2017-07-10 22:09:31 | [diff] [blame] | 204 | |
| 205 | shader->record_ = std::move(record); |
Lei Zhang | 868717c | 2018-05-09 04:33:56 | [diff] [blame] | 206 | shader->id_ = g_next_shader_id.GetNext(); |
Vladimir Levin | 4ca1c84 | 2017-07-10 22:09:31 | [diff] [blame] | 207 | shader->tile_ = tile; |
Vladimir Levin | 7440d46 | 2017-07-21 23:53:51 | [diff] [blame] | 208 | shader->scaling_behavior_ = scaling_behavior; |
Vladimir Levin | 4ca1c84 | 2017-07-10 22:09:31 | [diff] [blame] | 209 | shader->SetMatrixAndTiling(local_matrix, tx, ty); |
| 210 | |
Khushal | a866a80 | 2017-10-05 18:21:00 | [diff] [blame] | 211 | shader->CreateSkShader(); |
Vladimir Levin | 4ca1c84 | 2017-07-10 22:09:31 | [diff] [blame] | 212 | return shader; |
vmpstr | 7b99c958 | 2017-06-08 21:39:45 | [diff] [blame] | 213 | } |
| 214 | |
Khushal | 252af33 | 2018-02-14 05:03:09 | [diff] [blame] | 215 | // static |
| 216 | size_t PaintShader::GetSerializedSize(const PaintShader* shader) { |
| 217 | size_t bool_size = sizeof(bool); |
| 218 | if (!shader) |
| 219 | return bool_size; |
| 220 | |
| 221 | return bool_size + sizeof(shader->shader_type_) + sizeof(shader->flags_) + |
| 222 | sizeof(shader->end_radius_) + sizeof(shader->start_radius_) + |
| 223 | sizeof(shader->tx_) + sizeof(shader->ty_) + |
| 224 | sizeof(shader->fallback_color_) + sizeof(shader->scaling_behavior_) + |
| 225 | bool_size + sizeof(*shader->local_matrix_) + sizeof(shader->center_) + |
| 226 | sizeof(shader->tile_) + sizeof(shader->start_point_) + |
| 227 | sizeof(shader->end_point_) + sizeof(shader->start_degrees_) + |
| 228 | sizeof(shader->end_degrees_) + |
| 229 | PaintOpWriter::GetImageSize(shader->image_) + |
| 230 | PaintOpWriter::GetImageSize(shader->image_) + bool_size + |
Adrienne Walker | 90b79a2 | 2018-05-08 21:40:42 | [diff] [blame] | 231 | sizeof(shader->id_) + |
Khushal | 252af33 | 2018-02-14 05:03:09 | [diff] [blame] | 232 | PaintOpWriter::GetRecordSize(shader->record_.get()) + |
| 233 | sizeof(shader->colors_.size()) + |
| 234 | shader->colors_.size() * sizeof(SkColor) + |
| 235 | sizeof(shader->positions_.size()) + |
| 236 | shader->positions_.size() * sizeof(SkScalar); |
| 237 | } |
| 238 | |
Vladimir Levin | 4ca1c84 | 2017-07-10 22:09:31 | [diff] [blame] | 239 | PaintShader::PaintShader(Type type) : shader_type_(type) {} |
Adrienne Walker | 8d85c9d7 | 2017-07-07 23:16:46 | [diff] [blame] | 240 | PaintShader::~PaintShader() = default; |
vmpstr | 7b99c958 | 2017-06-08 21:39:45 | [diff] [blame] | 241 | |
Khushal | 0c568dc | 2018-03-21 01:46:07 | [diff] [blame] | 242 | bool PaintShader::has_discardable_images() const { |
Khushal | bd34e88 | 2018-10-22 20:46:08 | [diff] [blame] | 243 | return (image_ && !image_.IsTextureBacked()) || |
Khushal | 0c568dc | 2018-03-21 01:46:07 | [diff] [blame] | 244 | (record_ && record_->HasDiscardableImages()); |
| 245 | } |
| 246 | |
Khushal | 7ae9c79 | 2017-10-05 22:26:32 | [diff] [blame] | 247 | bool PaintShader::GetRasterizationTileRect(const SkMatrix& ctm, |
| 248 | SkRect* tile_rect) const { |
| 249 | DCHECK_EQ(shader_type_, Type::kPaintRecord); |
| 250 | |
| 251 | // If we are using a fixed scale, the record is rasterized with the original |
| 252 | // tile size and scaling is applied to the generated output. |
| 253 | if (scaling_behavior_ == ScalingBehavior::kFixedScale) { |
| 254 | *tile_rect = tile_; |
| 255 | return true; |
| 256 | } |
| 257 | |
| 258 | SkMatrix matrix = ctm; |
| 259 | if (local_matrix_.has_value()) |
| 260 | matrix.preConcat(local_matrix_.value()); |
| 261 | |
| 262 | SkSize scale; |
| 263 | if (!matrix.decomposeScale(&scale)) { |
| 264 | // Decomposition failed, use an approximation. |
| 265 | scale.set(SkScalarSqrt(matrix.getScaleX() * matrix.getScaleX() + |
| 266 | matrix.getSkewX() * matrix.getSkewX()), |
| 267 | SkScalarSqrt(matrix.getScaleY() * matrix.getScaleY() + |
| 268 | matrix.getSkewY() * matrix.getSkewY())); |
| 269 | } |
Adrienne Walker | c4bdc13e | 2018-06-27 00:56:30 | [diff] [blame] | 270 | |
| 271 | SkScalar tile_area = |
| 272 | tile_.width() * tile_.height() * scale.width() * scale.height(); |
Khushal | 7ae9c79 | 2017-10-05 22:26:32 | [diff] [blame] | 273 | |
| 274 | // Clamp the tile size to about 4M pixels. |
| 275 | // TODO(khushalsagar): We need to consider the max texture size as well. |
| 276 | static const SkScalar kMaxTileArea = 2048 * 2048; |
Khushal | 7ae9c79 | 2017-10-05 22:26:32 | [diff] [blame] | 277 | if (tile_area > kMaxTileArea) { |
| 278 | SkScalar clamp_scale = SkScalarSqrt(kMaxTileArea / tile_area); |
Adrienne Walker | c4bdc13e | 2018-06-27 00:56:30 | [diff] [blame] | 279 | scale.set(clamp_scale, clamp_scale); |
Khushal | 7ae9c79 | 2017-10-05 22:26:32 | [diff] [blame] | 280 | } |
| 281 | |
Adrienne Walker | c4bdc13e | 2018-06-27 00:56:30 | [diff] [blame] | 282 | *tile_rect = SkRect::MakeXYWH( |
| 283 | tile_.fLeft * scale.width(), tile_.fTop * scale.height(), |
| 284 | SkScalarCeilToInt(SkScalarAbs(scale.width() * tile_.width())), |
| 285 | SkScalarCeilToInt(SkScalarAbs(scale.height() * tile_.height()))); |
| 286 | |
| 287 | if (tile_rect->isEmpty()) |
Khushal | 7ae9c79 | 2017-10-05 22:26:32 | [diff] [blame] | 288 | return false; |
| 289 | |
Khushal | 7ae9c79 | 2017-10-05 22:26:32 | [diff] [blame] | 290 | return true; |
| 291 | } |
| 292 | |
Khushal | 67c8c74 | 2018-05-16 18:05:05 | [diff] [blame] | 293 | sk_sp<PaintShader> PaintShader::CreateScaledPaintRecord( |
Khushal | 7ae9c79 | 2017-10-05 22:26:32 | [diff] [blame] | 294 | const SkMatrix& ctm, |
Khushal | 515436e2 | 2019-04-05 05:03:51 | [diff] [blame] | 295 | int max_texture_size, |
Khushal | 67c8c74 | 2018-05-16 18:05:05 | [diff] [blame] | 296 | gfx::SizeF* raster_scale) const { |
Khushal | 7ae9c79 | 2017-10-05 22:26:32 | [diff] [blame] | 297 | DCHECK_EQ(shader_type_, Type::kPaintRecord); |
| 298 | |
Adrienne Walker | 13de7e3 | 2018-10-23 17:46:58 | [diff] [blame] | 299 | // If this is already fixed scale, then this is already good to go. |
| 300 | if (scaling_behavior_ == ScalingBehavior::kFixedScale) { |
| 301 | *raster_scale = gfx::SizeF(1.f, 1.f); |
| 302 | return sk_ref_sp<PaintShader>(this); |
| 303 | } |
| 304 | |
Khushal | 7ae9c79 | 2017-10-05 22:26:32 | [diff] [blame] | 305 | // For creating a decoded PaintRecord shader, we need to do the following: |
| 306 | // 1) Figure out the scale at which the record should be rasterization given |
| 307 | // the ctm and local_matrix on the shader. |
| 308 | // 2) Transform this record to an SkPicture with this scale and replace |
| 309 | // encoded images in this record with decodes from the ImageProvider. This |
| 310 | // is done by setting the raster_matrix_ for this shader to be used |
| 311 | // in GetSkShader. |
| 312 | // 3) Since the SkShader will use a scaled SkPicture, we use a kFixedScale for |
| 313 | // the decoded shader which creates an SkPicture backed SkImage for |
| 314 | // creating the decoded SkShader. |
| 315 | // Note that the scaling logic here is replicated from |
| 316 | // SkPictureShader::refBitmapShader. |
| 317 | SkRect tile_rect; |
| 318 | if (!GetRasterizationTileRect(ctm, &tile_rect)) |
| 319 | return nullptr; |
Khushal | 515436e2 | 2019-04-05 05:03:51 | [diff] [blame] | 320 | tile_rect = AdjustForMaxTextureSize(tile_rect, max_texture_size); |
Khushal | 7ae9c79 | 2017-10-05 22:26:32 | [diff] [blame] | 321 | |
| 322 | sk_sp<PaintShader> shader(new PaintShader(Type::kPaintRecord)); |
| 323 | shader->record_ = record_; |
Adrienne Walker | 90b79a2 | 2018-05-08 21:40:42 | [diff] [blame] | 324 | shader->id_ = id_; |
Khushal | 7ae9c79 | 2017-10-05 22:26:32 | [diff] [blame] | 325 | shader->tile_ = tile_rect; |
| 326 | // Use a fixed scale since we have already scaled the tile rect and fixed the |
| 327 | // raster scale. |
| 328 | shader->scaling_behavior_ = ScalingBehavior::kFixedScale; |
| 329 | shader->tx_ = tx_; |
| 330 | shader->ty_ = ty_; |
| 331 | |
Khushal | 67c8c74 | 2018-05-16 18:05:05 | [diff] [blame] | 332 | *raster_scale = |
Khushal | 9fd411f | 2018-01-20 02:09:51 | [diff] [blame] | 333 | gfx::SizeF(SkIntToScalar(tile_rect.width()) / tile_.width(), |
| 334 | SkIntToScalar(tile_rect.height()) / tile_.height()); |
Khushal | 7ae9c79 | 2017-10-05 22:26:32 | [diff] [blame] | 335 | shader->local_matrix_ = GetLocalMatrix(); |
Khushal | 67c8c74 | 2018-05-16 18:05:05 | [diff] [blame] | 336 | shader->local_matrix_->preScale(1 / raster_scale->width(), |
| 337 | 1 / raster_scale->height()); |
Khushal | 7ae9c79 | 2017-10-05 22:26:32 | [diff] [blame] | 338 | |
Khushal | 7ae9c79 | 2017-10-05 22:26:32 | [diff] [blame] | 339 | return shader; |
| 340 | } |
| 341 | |
Xida Chen | 044ad8a | 2019-12-17 16:41:22 | [diff] [blame] | 342 | sk_sp<PaintShader> PaintShader::CreatePaintWorkletRecord( |
| 343 | ImageProvider* image_provider) const { |
| 344 | DCHECK_EQ(shader_type_, Type::kImage); |
| 345 | DCHECK(image_ && image_.IsPaintWorklet()); |
| 346 | |
| 347 | ImageProvider::ScopedResult result = |
| 348 | image_provider->GetRasterContent(DrawImage(image_)); |
| 349 | if (!result || !result.paint_record()) |
| 350 | return nullptr; |
| 351 | SkMatrix local_matrix = GetLocalMatrix(); |
| 352 | return PaintShader::MakePaintRecord( |
| 353 | sk_ref_sp<PaintRecord>(result.paint_record()), tile_, tx_, ty_, |
| 354 | &local_matrix); |
| 355 | } |
| 356 | |
Khushal | 67c8c74 | 2018-05-16 18:05:05 | [diff] [blame] | 357 | sk_sp<PaintShader> PaintShader::CreateDecodedImage( |
| 358 | const SkMatrix& ctm, |
| 359 | SkFilterQuality quality, |
| 360 | ImageProvider* image_provider, |
| 361 | uint32_t* transfer_cache_entry_id, |
Eric Karl | 4c5bf9d | 2018-07-13 08:26:44 | [diff] [blame] | 362 | SkFilterQuality* raster_quality, |
| 363 | bool* needs_mips) const { |
Khushal | 67c8c74 | 2018-05-16 18:05:05 | [diff] [blame] | 364 | DCHECK_EQ(shader_type_, Type::kImage); |
| 365 | if (!image_) |
| 366 | return nullptr; |
| 367 | |
| 368 | SkMatrix total_image_matrix = GetLocalMatrix(); |
| 369 | total_image_matrix.preConcat(ctm); |
| 370 | SkRect src_rect = SkRect::MakeIWH(image_.width(), image_.height()); |
| 371 | SkIRect int_src_rect; |
| 372 | src_rect.roundOut(&int_src_rect); |
| 373 | DrawImage draw_image(image_, int_src_rect, quality, total_image_matrix); |
Xida Chen | 2d4a118 | 2019-02-08 15:48:49 | [diff] [blame] | 374 | auto decoded_draw_image = image_provider->GetRasterContent(draw_image); |
Khushal | 67c8c74 | 2018-05-16 18:05:05 | [diff] [blame] | 375 | if (!decoded_draw_image) |
| 376 | return nullptr; |
| 377 | |
| 378 | auto decoded_image = decoded_draw_image.decoded_image(); |
| 379 | SkMatrix final_matrix = GetLocalMatrix(); |
| 380 | bool need_scale = !decoded_image.is_scale_adjustment_identity(); |
| 381 | if (need_scale) { |
| 382 | final_matrix.preScale(1.f / decoded_image.scale_adjustment().width(), |
| 383 | 1.f / decoded_image.scale_adjustment().height()); |
| 384 | } |
| 385 | |
| 386 | PaintImage decoded_paint_image; |
| 387 | if (decoded_image.transfer_cache_entry_id()) { |
| 388 | decoded_paint_image = image_; |
| 389 | *transfer_cache_entry_id = *decoded_image.transfer_cache_entry_id(); |
| 390 | } else { |
| 391 | DCHECK(decoded_image.image()); |
| 392 | |
| 393 | sk_sp<SkImage> sk_image = |
| 394 | sk_ref_sp<SkImage>(const_cast<SkImage*>(decoded_image.image().get())); |
| 395 | decoded_paint_image = |
| 396 | PaintImageBuilder::WithDefault() |
| 397 | .set_id(image_.stable_id()) |
| 398 | .set_image(std::move(sk_image), image_.content_id()) |
| 399 | .TakePaintImage(); |
| 400 | } |
| 401 | |
| 402 | // TODO(khushalsagar): Remove filter quality from DecodedDrawImage. All we |
| 403 | // want to do is cap the filter quality used, but Gpu and Sw cache have |
| 404 | // different behaviour. D: |
| 405 | *raster_quality = decoded_image.filter_quality(); |
Eric Karl | 4c5bf9d | 2018-07-13 08:26:44 | [diff] [blame] | 406 | *needs_mips = decoded_image.transfer_cache_entry_needs_mips(); |
Khushal | 67c8c74 | 2018-05-16 18:05:05 | [diff] [blame] | 407 | return PaintShader::MakeImage(decoded_paint_image, tx_, ty_, &final_matrix); |
| 408 | } |
| 409 | |
Vladimir Levin | 4ca1c84 | 2017-07-10 22:09:31 | [diff] [blame] | 410 | sk_sp<SkShader> PaintShader::GetSkShader() const { |
Khushal | a866a80 | 2017-10-05 18:21:00 | [diff] [blame] | 411 | return cached_shader_; |
| 412 | } |
| 413 | |
Khushal | 67c8c74 | 2018-05-16 18:05:05 | [diff] [blame] | 414 | void PaintShader::CreateSkShader(const gfx::SizeF* raster_scale, |
| 415 | ImageProvider* image_provider) { |
Khushal | a866a80 | 2017-10-05 18:21:00 | [diff] [blame] | 416 | DCHECK(!cached_shader_); |
Vladimir Levin | 4ca1c84 | 2017-07-10 22:09:31 | [diff] [blame] | 417 | |
| 418 | switch (shader_type_) { |
Florin Malita | c677eac | 2018-11-08 18:51:18 | [diff] [blame] | 419 | case Type::kEmpty: |
Mike Reed | a1a4e0b | 2019-04-10 17:54:16 | [diff] [blame] | 420 | cached_shader_ = SkShaders::Empty(); |
Florin Malita | c677eac | 2018-11-08 18:51:18 | [diff] [blame] | 421 | break; |
Vladimir Levin | 7440d46 | 2017-07-21 23:53:51 | [diff] [blame] | 422 | case Type::kColor: |
Vladimir Levin | 4ca1c84 | 2017-07-10 22:09:31 | [diff] [blame] | 423 | // This will be handled by the fallback check below. |
| 424 | break; |
Vladimir Levin | 7440d46 | 2017-07-21 23:53:51 | [diff] [blame] | 425 | case Type::kLinearGradient: { |
Vladimir Levin | 4ca1c84 | 2017-07-10 22:09:31 | [diff] [blame] | 426 | SkPoint points[2] = {start_point_, end_point_}; |
| 427 | cached_shader_ = SkGradientShader::MakeLinear( |
| 428 | points, colors_.data(), |
| 429 | positions_.empty() ? nullptr : positions_.data(), |
| 430 | static_cast<int>(colors_.size()), tx_, flags_, |
Philip Rogers | 3f67719f | 2018-03-09 02:16:44 | [diff] [blame] | 431 | base::OptionalOrNullptr(local_matrix_)); |
Vladimir Levin | 4ca1c84 | 2017-07-10 22:09:31 | [diff] [blame] | 432 | break; |
| 433 | } |
Vladimir Levin | 7440d46 | 2017-07-21 23:53:51 | [diff] [blame] | 434 | case Type::kRadialGradient: |
Vladimir Levin | 4ca1c84 | 2017-07-10 22:09:31 | [diff] [blame] | 435 | cached_shader_ = SkGradientShader::MakeRadial( |
| 436 | center_, start_radius_, colors_.data(), |
| 437 | positions_.empty() ? nullptr : positions_.data(), |
| 438 | static_cast<int>(colors_.size()), tx_, flags_, |
Philip Rogers | 3f67719f | 2018-03-09 02:16:44 | [diff] [blame] | 439 | base::OptionalOrNullptr(local_matrix_)); |
Vladimir Levin | 4ca1c84 | 2017-07-10 22:09:31 | [diff] [blame] | 440 | break; |
Vladimir Levin | 7440d46 | 2017-07-21 23:53:51 | [diff] [blame] | 441 | case Type::kTwoPointConicalGradient: |
Vladimir Levin | 4ca1c84 | 2017-07-10 22:09:31 | [diff] [blame] | 442 | cached_shader_ = SkGradientShader::MakeTwoPointConical( |
| 443 | start_point_, start_radius_, end_point_, end_radius_, colors_.data(), |
| 444 | positions_.empty() ? nullptr : positions_.data(), |
| 445 | static_cast<int>(colors_.size()), tx_, flags_, |
Philip Rogers | 3f67719f | 2018-03-09 02:16:44 | [diff] [blame] | 446 | base::OptionalOrNullptr(local_matrix_)); |
Vladimir Levin | 4ca1c84 | 2017-07-10 22:09:31 | [diff] [blame] | 447 | break; |
Vladimir Levin | 7440d46 | 2017-07-21 23:53:51 | [diff] [blame] | 448 | case Type::kSweepGradient: |
Vladimir Levin | 4ca1c84 | 2017-07-10 22:09:31 | [diff] [blame] | 449 | cached_shader_ = SkGradientShader::MakeSweep( |
| 450 | center_.x(), center_.y(), colors_.data(), |
| 451 | positions_.empty() ? nullptr : positions_.data(), |
Florin Malita | 0786698 | 2017-08-07 21:11:50 | [diff] [blame] | 452 | static_cast<int>(colors_.size()), tx_, start_degrees_, end_degrees_, |
Philip Rogers | 3f67719f | 2018-03-09 02:16:44 | [diff] [blame] | 453 | flags_, base::OptionalOrNullptr(local_matrix_)); |
Vladimir Levin | 4ca1c84 | 2017-07-10 22:09:31 | [diff] [blame] | 454 | break; |
Vladimir Levin | 7440d46 | 2017-07-21 23:53:51 | [diff] [blame] | 455 | case Type::kImage: |
Xida Chen | 0481c52 | 2019-08-07 00:54:46 | [diff] [blame] | 456 | if (image_ && !image_.IsPaintWorklet()) { |
Vladimir Levin | dd4145d | 2018-01-13 04:25:30 | [diff] [blame] | 457 | cached_shader_ = image_.GetSkImage()->makeShader( |
Philip Rogers | 3f67719f | 2018-03-09 02:16:44 | [diff] [blame] | 458 | tx_, ty_, base::OptionalOrNullptr(local_matrix_)); |
Vladimir Levin | dd4145d | 2018-01-13 04:25:30 | [diff] [blame] | 459 | } |
Vladimir Levin | 4ca1c84 | 2017-07-10 22:09:31 | [diff] [blame] | 460 | break; |
Vladimir Levin | 7440d46 | 2017-07-21 23:53:51 | [diff] [blame] | 461 | case Type::kPaintRecord: { |
Khushal | 7ae9c79 | 2017-10-05 22:26:32 | [diff] [blame] | 462 | // Create a recording at the desired scale if this record has images which |
| 463 | // have been decoded before raster. |
Khushal | 67c8c74 | 2018-05-16 18:05:05 | [diff] [blame] | 464 | auto picture = ToSkPicture(record_, tile_, raster_scale, image_provider); |
Vladimir Levin | 7440d46 | 2017-07-21 23:53:51 | [diff] [blame] | 465 | |
| 466 | switch (scaling_behavior_) { |
| 467 | // For raster scale, we create a picture shader directly. |
| 468 | case ScalingBehavior::kRasterAtScale: |
Mike Reed | 500aabf | 2019-04-04 12:50:32 | [diff] [blame] | 469 | cached_shader_ = picture->makeShader( |
| 470 | tx_, ty_, base::OptionalOrNullptr(local_matrix_), nullptr); |
Vladimir Levin | 7440d46 | 2017-07-21 23:53:51 | [diff] [blame] | 471 | break; |
Khushal | 7ae9c79 | 2017-10-05 22:26:32 | [diff] [blame] | 472 | // For fixed scale, we create an image shader with an image backed by |
Vladimir Levin | 7440d46 | 2017-07-21 23:53:51 | [diff] [blame] | 473 | // the picture. |
| 474 | case ScalingBehavior::kFixedScale: { |
| 475 | auto image = SkImage::MakeFromPicture( |
| 476 | std::move(picture), SkISize::Make(tile_.width(), tile_.height()), |
| 477 | nullptr, nullptr, SkImage::BitDepth::kU8, |
| 478 | SkColorSpace::MakeSRGB()); |
| 479 | cached_shader_ = image->makeShader( |
Philip Rogers | 3f67719f | 2018-03-09 02:16:44 | [diff] [blame] | 480 | tx_, ty_, base::OptionalOrNullptr(local_matrix_)); |
Vladimir Levin | 7440d46 | 2017-07-21 23:53:51 | [diff] [blame] | 481 | break; |
| 482 | } |
| 483 | } |
Vladimir Levin | 4ca1c84 | 2017-07-10 22:09:31 | [diff] [blame] | 484 | break; |
Vladimir Levin | 7440d46 | 2017-07-21 23:53:51 | [diff] [blame] | 485 | } |
| 486 | case Type::kShaderCount: |
Vladimir Levin | 4ca1c84 | 2017-07-10 22:09:31 | [diff] [blame] | 487 | NOTREACHED(); |
| 488 | break; |
| 489 | } |
| 490 | |
| 491 | // If we didn't create a shader for whatever reason, create a fallback color |
| 492 | // one. |
| 493 | if (!cached_shader_) |
Mike Reed | a1a4e0b | 2019-04-10 17:54:16 | [diff] [blame] | 494 | cached_shader_ = SkShaders::Color(fallback_color_); |
Vladimir Levin | 4ca1c84 | 2017-07-10 22:09:31 | [diff] [blame] | 495 | } |
| 496 | |
| 497 | void PaintShader::SetColorsAndPositions(const SkColor* colors, |
| 498 | const SkScalar* positions, |
| 499 | int count) { |
Vladimir Levin | 1ec7cdb6 | 2017-08-30 02:21:48 | [diff] [blame] | 500 | #if DCHECK_IS_ON() |
| 501 | static const int kMaxShaderColorsSupported = 10000; |
Vladimir Levin | 4ca1c84 | 2017-07-10 22:09:31 | [diff] [blame] | 502 | DCHECK_GE(count, 2); |
Vladimir Levin | 1ec7cdb6 | 2017-08-30 02:21:48 | [diff] [blame] | 503 | DCHECK_LE(count, kMaxShaderColorsSupported); |
| 504 | #endif |
Vladimir Levin | 4ca1c84 | 2017-07-10 22:09:31 | [diff] [blame] | 505 | colors_.assign(colors, colors + count); |
| 506 | if (positions) |
| 507 | positions_.assign(positions, positions + count); |
| 508 | } |
| 509 | |
| 510 | void PaintShader::SetMatrixAndTiling(const SkMatrix* matrix, |
Mike Reed | 500aabf | 2019-04-04 12:50:32 | [diff] [blame] | 511 | SkTileMode tx, |
| 512 | SkTileMode ty) { |
Vladimir Levin | 4ca1c84 | 2017-07-10 22:09:31 | [diff] [blame] | 513 | if (matrix) |
| 514 | local_matrix_ = *matrix; |
| 515 | tx_ = tx; |
| 516 | ty_ = ty; |
| 517 | } |
| 518 | |
| 519 | void PaintShader::SetFlagsAndFallback(uint32_t flags, SkColor fallback_color) { |
| 520 | flags_ = flags; |
| 521 | fallback_color_ = fallback_color; |
| 522 | } |
| 523 | |
Adrienne Walker | dab4962 | 2017-07-21 00:07:44 | [diff] [blame] | 524 | bool PaintShader::IsOpaque() const { |
| 525 | // TODO(enne): don't create a shader to answer this. |
| 526 | return GetSkShader()->isOpaque(); |
| 527 | } |
| 528 | |
Vladimir Levin | 2f5940a | 2017-08-11 18:01:05 | [diff] [blame] | 529 | bool PaintShader::IsValid() const { |
| 530 | // If we managed to create a shader already, then we should be valid. |
| 531 | if (cached_shader_) |
| 532 | return true; |
| 533 | |
| 534 | switch (shader_type_) { |
Florin Malita | c677eac | 2018-11-08 18:51:18 | [diff] [blame] | 535 | case Type::kEmpty: |
Vladimir Levin | 2f5940a | 2017-08-11 18:01:05 | [diff] [blame] | 536 | case Type::kColor: |
| 537 | return true; |
Vladimir Levin | 3b05219 | 2017-09-08 01:51:00 | [diff] [blame] | 538 | case Type::kSweepGradient: |
| 539 | if (!std::isfinite(start_degrees_) || !std::isfinite(end_degrees_) || |
| 540 | start_degrees_ >= end_degrees_) { |
| 541 | return false; |
| 542 | } |
Nico Weber | 38a94195 | 2018-01-26 17:56:35 | [diff] [blame] | 543 | FALLTHROUGH; |
Vladimir Levin | 2f5940a | 2017-08-11 18:01:05 | [diff] [blame] | 544 | case Type::kLinearGradient: |
| 545 | case Type::kRadialGradient: |
| 546 | case Type::kTwoPointConicalGradient: |
Vladimir Levin | 2f5940a | 2017-08-11 18:01:05 | [diff] [blame] | 547 | return colors_.size() >= 2 && |
| 548 | (positions_.empty() || positions_.size() == colors_.size()); |
| 549 | case Type::kImage: |
Vladimir Levin | dd4145d | 2018-01-13 04:25:30 | [diff] [blame] | 550 | // We may not be able to decode the image, in which case it would be |
| 551 | // false, but that would still make a valid shader. |
| 552 | return true; |
Vladimir Levin | 2f5940a | 2017-08-11 18:01:05 | [diff] [blame] | 553 | case Type::kPaintRecord: |
| 554 | return !!record_; |
| 555 | case Type::kShaderCount: |
| 556 | return false; |
| 557 | } |
| 558 | return false; |
| 559 | } |
| 560 | |
Adrienne Walker | 6ac3063 | 2017-11-18 01:52:07 | [diff] [blame] | 561 | bool PaintShader::operator==(const PaintShader& other) const { |
| 562 | if (shader_type_ != other.shader_type_) |
| 563 | return false; |
Adrienne Walker | e1bef6c | 2017-11-30 00:46:35 | [diff] [blame] | 564 | |
Khushal | 67c8c74 | 2018-05-16 18:05:05 | [diff] [blame] | 565 | // Record and image shaders are scaled during serialization. |
| 566 | const bool ignore_scaling_differences = |
| 567 | shader_type_ == PaintShader::Type::kPaintRecord || |
| 568 | shader_type_ == PaintShader::Type::kImage; |
| 569 | |
Adrienne Walker | e1bef6c | 2017-11-30 00:46:35 | [diff] [blame] | 570 | // Variables that all shaders use. |
Khushal | 67c8c74 | 2018-05-16 18:05:05 | [diff] [blame] | 571 | const SkMatrix& local_matrix = local_matrix_ ? *local_matrix_ : SkMatrix::I(); |
| 572 | const SkMatrix& other_local_matrix = |
| 573 | other.local_matrix_ ? *other.local_matrix_ : SkMatrix::I(); |
| 574 | if (!CompareMatrices(local_matrix, other_local_matrix, |
| 575 | ignore_scaling_differences)) { |
| 576 | return false; |
Adrienne Walker | 6ac3063 | 2017-11-18 01:52:07 | [diff] [blame] | 577 | } |
Khushal | 67c8c74 | 2018-05-16 18:05:05 | [diff] [blame] | 578 | |
Adrienne Walker | e1bef6c | 2017-11-30 00:46:35 | [diff] [blame] | 579 | if (fallback_color_ != other.fallback_color_) |
Adrienne Walker | 6ac3063 | 2017-11-18 01:52:07 | [diff] [blame] | 580 | return false; |
Adrienne Walker | e1bef6c | 2017-11-30 00:46:35 | [diff] [blame] | 581 | if (flags_ != other.flags_) |
Adrienne Walker | 6ac3063 | 2017-11-18 01:52:07 | [diff] [blame] | 582 | return false; |
Adrienne Walker | e1bef6c | 2017-11-30 00:46:35 | [diff] [blame] | 583 | if (tx_ != other.tx_) |
Adrienne Walker | 6ac3063 | 2017-11-18 01:52:07 | [diff] [blame] | 584 | return false; |
Adrienne Walker | e1bef6c | 2017-11-30 00:46:35 | [diff] [blame] | 585 | if (ty_ != other.ty_) |
Adrienne Walker | 6ac3063 | 2017-11-18 01:52:07 | [diff] [blame] | 586 | return false; |
Khushal | 67c8c74 | 2018-05-16 18:05:05 | [diff] [blame] | 587 | |
| 588 | if (!ignore_scaling_differences && |
| 589 | scaling_behavior_ != other.scaling_behavior_) |
Adrienne Walker | 6ac3063 | 2017-11-18 01:52:07 | [diff] [blame] | 590 | return false; |
| 591 | |
Adrienne Walker | e1bef6c | 2017-11-30 00:46:35 | [diff] [blame] | 592 | // Variables that only some shaders use. |
| 593 | switch (shader_type_) { |
Florin Malita | c677eac | 2018-11-08 18:51:18 | [diff] [blame] | 594 | case Type::kEmpty: |
Adrienne Walker | e1bef6c | 2017-11-30 00:46:35 | [diff] [blame] | 595 | case Type::kColor: |
| 596 | break; |
| 597 | case Type::kSweepGradient: |
| 598 | if (!PaintOp::AreEqualEvenIfNaN(start_degrees_, other.start_degrees_)) |
| 599 | return false; |
| 600 | if (!PaintOp::AreEqualEvenIfNaN(end_degrees_, other.end_degrees_)) |
| 601 | return false; |
Nico Weber | 38a94195 | 2018-01-26 17:56:35 | [diff] [blame] | 602 | FALLTHROUGH; |
Adrienne Walker | e1bef6c | 2017-11-30 00:46:35 | [diff] [blame] | 603 | case Type::kLinearGradient: |
| 604 | case Type::kRadialGradient: |
| 605 | case Type::kTwoPointConicalGradient: |
| 606 | if (!PaintOp::AreEqualEvenIfNaN(start_radius_, other.start_radius_)) |
| 607 | return false; |
| 608 | if (!PaintOp::AreEqualEvenIfNaN(end_radius_, other.end_radius_)) |
| 609 | return false; |
| 610 | if (!PaintOp::AreSkPointsEqual(center_, other.center_)) |
| 611 | return false; |
| 612 | if (!PaintOp::AreSkPointsEqual(start_point_, other.start_point_)) |
| 613 | return false; |
| 614 | if (!PaintOp::AreSkPointsEqual(end_point_, other.end_point_)) |
| 615 | return false; |
| 616 | if (colors_ != other.colors_) |
| 617 | return false; |
| 618 | if (positions_.size() != other.positions_.size()) |
| 619 | return false; |
| 620 | for (size_t i = 0; i < positions_.size(); ++i) { |
| 621 | if (!PaintOp::AreEqualEvenIfNaN(positions_[i], other.positions_[i])) |
| 622 | return false; |
| 623 | } |
| 624 | break; |
| 625 | case Type::kImage: |
| 626 | // TODO(enne): add comparison of images once those are serialized. |
| 627 | break; |
| 628 | case Type::kPaintRecord: |
Vladimir Levin | bd083f78 | 2018-01-12 23:26:09 | [diff] [blame] | 629 | // If we have a record but not other.record, or vice versa, then shaders |
| 630 | // aren't the same. |
| 631 | if (!record_ != !other.record_) |
| 632 | return false; |
Khushal | 67c8c74 | 2018-05-16 18:05:05 | [diff] [blame] | 633 | // tile_ and record_ intentionally omitted since they are modified on the |
| 634 | // serialized shader based on the ctm. |
Adrienne Walker | e1bef6c | 2017-11-30 00:46:35 | [diff] [blame] | 635 | break; |
| 636 | case Type::kShaderCount: |
| 637 | break; |
| 638 | } |
Adrienne Walker | 6ac3063 | 2017-11-18 01:52:07 | [diff] [blame] | 639 | |
Adrienne Walker | 6ac3063 | 2017-11-18 01:52:07 | [diff] [blame] | 640 | return true; |
| 641 | } |
| 642 | |
vmpstr | 7b99c958 | 2017-06-08 21:39:45 | [diff] [blame] | 643 | } // namespace cc |