blob: 173f3948dd0e791584f31818454aa3815d343879 [file] [log] [blame]
John Reck013127b2020-10-29 20:53:51 -04001/*
2 * Copyright (C) 2020 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#pragma once
18
19#include <SkAndroidFrameworkUtils.h>
20#include <SkCanvas.h>
21#include <SkPath.h>
Nader Jawadfb1e7f12020-11-06 22:49:42 -080022#include <SkRegion.h>
23#include <SkVertices.h>
Nader Jawadda9248c2020-11-09 17:27:36 -080024#include <SkImage.h>
25#include <SkPicture.h>
Derek Sollenbergerdf301aa2020-12-17 11:06:03 -050026#include <SkRuntimeEffect.h>
John Reck013127b2020-10-29 20:53:51 -040027
John Reck064650b2021-01-19 21:29:24 -050028#include <log/log.h>
29
30#include "hwui/Bitmap.h"
31#include "CanvasProperty.h"
John Reck013127b2020-10-29 20:53:51 -040032#include "CanvasOpTypes.h"
Nader Jawad55f19762020-11-25 15:30:20 -080033#include "Layer.h"
John Reck064650b2021-01-19 21:29:24 -050034#include "Points.h"
35#include "RenderNode.h"
John Reck013127b2020-10-29 20:53:51 -040036
37#include <experimental/type_traits>
Nader Jawadda9248c2020-11-09 17:27:36 -080038#include <utility>
John Reck013127b2020-10-29 20:53:51 -040039
40namespace android::uirenderer {
41
42template <CanvasOpType T>
43struct CanvasOp;
44
45struct CanvasOpTraits {
46 CanvasOpTraits() = delete;
47
48 template<class T>
49 using draw_t = decltype(std::integral_constant<void (T::*)(SkCanvas*) const, &T::draw>{});
50
51 template <class T>
52 static constexpr bool can_draw = std::experimental::is_detected_v<draw_t, T>;
53};
54
55#define ASSERT_DRAWABLE() private: constexpr void _check_drawable() \
56 { static_assert(CanvasOpTraits::can_draw<std::decay_t<decltype(*this)>>); }
57
58// ----------------------------------------------
59// State Ops
60// ---------------------------------------------
61
62template <>
63struct CanvasOp<CanvasOpType::Save> {
64 void draw(SkCanvas* canvas) const { canvas->save(); }
65 ASSERT_DRAWABLE()
66};
67
68template <>
69struct CanvasOp<CanvasOpType::SaveLayer> {
70 SkCanvas::SaveLayerRec saveLayerRec;
71 void draw(SkCanvas* canvas) const { canvas->saveLayer(saveLayerRec); }
72 ASSERT_DRAWABLE()
73};
74
75template <>
76struct CanvasOp<CanvasOpType::SaveBehind> {
77 SkRect bounds;
78 void draw(SkCanvas* canvas) const { SkAndroidFrameworkUtils::SaveBehind(canvas, &bounds); }
79 ASSERT_DRAWABLE()
80};
81
82template <>
83struct CanvasOp<CanvasOpType::Restore> {
84 void draw(SkCanvas* canvas) const { canvas->restore(); }
85 ASSERT_DRAWABLE()
86};
87
88template <>
89struct CanvasOp<CanvasOpType::BeginZ> {
90};
91template <>
92struct CanvasOp<CanvasOpType::EndZ> {};
93
94// ----------------------------------------------
95// Clip Ops
96// ---------------------------------------------
97
98template <>
99struct CanvasOp<CanvasOpType::ClipRect> {
100 SkRect rect;
101 SkClipOp clipOp;
102 void draw(SkCanvas* canvas) const { canvas->clipRect(rect, clipOp); }
103 ASSERT_DRAWABLE()
104};
105
106template <>
107struct CanvasOp<CanvasOpType::ClipPath> {
108 SkPath path;
109 SkClipOp op;
110 void draw(SkCanvas* canvas) const { canvas->clipPath(path, op, true); }
111 ASSERT_DRAWABLE()
112};
113
114// ----------------------------------------------
115// Drawing Ops
116// ---------------------------------------------
117
Nader Jawadde3ce842020-11-06 16:54:48 -0800118template<>
119struct CanvasOp<CanvasOpType::DrawRoundRectProperty> {
120 sp<uirenderer::CanvasPropertyPrimitive> left;
121 sp<uirenderer::CanvasPropertyPrimitive> top;
122 sp<uirenderer::CanvasPropertyPrimitive> right;
123 sp<uirenderer::CanvasPropertyPrimitive> bottom;
124 sp<uirenderer::CanvasPropertyPrimitive> rx;
125 sp<uirenderer::CanvasPropertyPrimitive> ry;
126 sp<uirenderer::CanvasPropertyPaint> paint;
127
128 void draw(SkCanvas* canvas) const {
129 SkRect rect = SkRect::MakeLTRB(left->value, top->value, right->value, bottom->value);
130 canvas->drawRoundRect(rect, rx->value, ry->value, paint->value);
131 }
132 ASSERT_DRAWABLE()
133};
134
135template<>
136struct CanvasOp<CanvasOpType::DrawCircleProperty> {
137 sp<uirenderer::CanvasPropertyPrimitive> x;
138 sp<uirenderer::CanvasPropertyPrimitive> y;
139 sp<uirenderer::CanvasPropertyPrimitive> radius;
140 sp<uirenderer::CanvasPropertyPaint> paint;
141
142 void draw(SkCanvas* canvas) const {
143 canvas->drawCircle(x->value, y->value, radius->value, paint->value);
144 }
145 ASSERT_DRAWABLE()
146};
147
Derek Sollenbergerdf301aa2020-12-17 11:06:03 -0500148template<>
149struct CanvasOp<CanvasOpType::DrawRippleProperty> {
150 sp<uirenderer::CanvasPropertyPrimitive> x;
151 sp<uirenderer::CanvasPropertyPrimitive> y;
152 sp<uirenderer::CanvasPropertyPrimitive> radius;
153 sp<uirenderer::CanvasPropertyPaint> paint;
154 sp<uirenderer::CanvasPropertyPrimitive> progress;
Lucas Dupin6d1601a2021-04-15 08:39:50 -0700155 sp<uirenderer::CanvasPropertyPrimitive> turbulencePhase;
Derek Sollenbergerdf301aa2020-12-17 11:06:03 -0500156 sk_sp<SkRuntimeEffect> effect;
157
Lucas Dupin6d1601a2021-04-15 08:39:50 -0700158 const float PI = 3.1415926535897932384626;
159 const float PI_ROTATE_RIGHT = PI * 0.0078125;
160 const float PI_ROTATE_LEFT = PI * -0.0078125;
161 const float SCALE = 1.5;
162 const float CIRCLE_X_1 = 0.01 * cos(SCALE * 0.55);
163 const float CIRCLE_Y_1 = 0.01 * sin(SCALE * 0.55);
164 const float CIRCLE_X_2 = -0.0066 * cos(SCALE * 0.45);
165 const float CIRCLE_Y_2 = -0.0066 * sin(SCALE * 0.45);
166 const float CIRCLE_X_3 = -0.0066 * cos(SCALE * 0.35);
167 const float CIRCLE_Y_3 = -0.0066 * sin(SCALE * 0.35);
168
Derek Sollenbergerdf301aa2020-12-17 11:06:03 -0500169 void draw(SkCanvas* canvas) const {
170 SkRuntimeShaderBuilder runtimeEffectBuilder(effect);
171
Lucas Dupin6d1601a2021-04-15 08:39:50 -0700172 setUniform2f(runtimeEffectBuilder, "in_origin", x->value, y->value);
173 setUniform(runtimeEffectBuilder, "in_radius", radius);
174 setUniform(runtimeEffectBuilder, "in_progress", progress);
175 setUniform(runtimeEffectBuilder, "in_turbulencePhase", turbulencePhase);
Derek Sollenbergerdf301aa2020-12-17 11:06:03 -0500176
Lucas Dupin6d1601a2021-04-15 08:39:50 -0700177 //
178 // Keep in sync with:
179 // frameworks/base/graphics/java/android/graphics/drawable/RippleShader.java
180 //
181 const float turbulence = turbulencePhase->value;
182 setUniform2f(runtimeEffectBuilder, "in_tCircle1", SCALE * 0.5 + (turbulence * CIRCLE_X_1),
183 SCALE * 0.5 + (turbulence * CIRCLE_Y_1));
184 setUniform2f(runtimeEffectBuilder, "in_tCircle2", SCALE * 0.2 + (turbulence * CIRCLE_X_2),
185 SCALE * 0.2 + (turbulence * CIRCLE_Y_2));
186 setUniform2f(runtimeEffectBuilder, "in_tCircle3", SCALE + (turbulence * CIRCLE_X_3),
187 SCALE + (turbulence * CIRCLE_Y_3));
188 const float rotation1 = turbulence * PI_ROTATE_RIGHT + 1.7 * PI;
189 setUniform2f(runtimeEffectBuilder, "in_tRotation1", cos(rotation1), sin(rotation1));
190 const float rotation2 = turbulence * PI_ROTATE_LEFT + 2 * PI;
191 setUniform2f(runtimeEffectBuilder, "in_tRotation2", cos(rotation2), sin(rotation2));
192 const float rotation3 = turbulence * PI_ROTATE_RIGHT + 2.75 * PI;
193 setUniform2f(runtimeEffectBuilder, "in_tRotation3", cos(rotation3), sin(rotation3));
Derek Sollenbergerdf301aa2020-12-17 11:06:03 -0500194
195 SkPaint paintMod = paint->value;
196 paintMod.setShader(runtimeEffectBuilder.makeShader(nullptr, false));
197 canvas->drawCircle(x->value, y->value, radius->value, paintMod);
198 }
Lucas Dupin6d1601a2021-04-15 08:39:50 -0700199
200 void setUniform(SkRuntimeShaderBuilder& effect, std::string name,
201 sp<uirenderer::CanvasPropertyPrimitive> property) const {
202 SkRuntimeShaderBuilder::BuilderUniform uniform = effect.uniform(name.c_str());
203 if (uniform.fVar != nullptr) {
204 uniform = property->value;
205 }
206 }
207
208 void setUniform2f(SkRuntimeShaderBuilder effect, std::string name, float a, float b) const {
209 SkRuntimeShaderBuilder::BuilderUniform uniform = effect.uniform(name.c_str());
210 if (uniform.fVar != nullptr) {
211 uniform = SkV2{a, b};
212 }
213 }
214
Derek Sollenbergerdf301aa2020-12-17 11:06:03 -0500215 ASSERT_DRAWABLE()
216};
217
John Reck013127b2020-10-29 20:53:51 -0400218template <>
219struct CanvasOp<CanvasOpType::DrawColor> {
220 SkColor4f color;
221 SkBlendMode mode;
222 void draw(SkCanvas* canvas) const { canvas->drawColor(color, mode); }
223 ASSERT_DRAWABLE()
224};
225
226template <>
Nader Jawadd5c2b6d2020-11-05 19:12:29 -0800227struct CanvasOp<CanvasOpType::DrawPaint> {
228 SkPaint paint;
229 void draw(SkCanvas* canvas) const { canvas->drawPaint(paint); }
230 ASSERT_DRAWABLE()
231};
232
233template <>
Nader Jawadfb1e7f12020-11-06 22:49:42 -0800234struct CanvasOp<CanvasOpType::DrawPoint> {
235 float x;
236 float y;
237 SkPaint paint;
238 void draw(SkCanvas* canvas) const { canvas->drawPoint(x, y, paint); }
239 ASSERT_DRAWABLE()
240};
241
242template <>
Nader Jawad4285c8a2020-11-06 22:49:42 -0800243struct CanvasOp<CanvasOpType::DrawPoints> {
244 size_t count;
245 SkPaint paint;
246 sk_sp<Points> points;
247 void draw(SkCanvas* canvas) const {
248 canvas->drawPoints(
249 SkCanvas::kPoints_PointMode,
250 count,
251 points->data(),
252 paint
253 );
254 }
255 ASSERT_DRAWABLE()
256};
257
258template <>
John Reck013127b2020-10-29 20:53:51 -0400259struct CanvasOp<CanvasOpType::DrawRect> {
260 SkRect rect;
261 SkPaint paint;
262 void draw(SkCanvas* canvas) const { canvas->drawRect(rect, paint); }
263 ASSERT_DRAWABLE()
264};
265
Nader Jawadfb1e7f12020-11-06 22:49:42 -0800266template <>
267struct CanvasOp<CanvasOpType::DrawRegion> {
268 SkRegion region;
269 SkPaint paint;
270 void draw(SkCanvas* canvas) const { canvas->drawRegion(region, paint); }
271 ASSERT_DRAWABLE()
272};
273
Nader Jawadd5c2b6d2020-11-05 19:12:29 -0800274template<>
275struct CanvasOp<CanvasOpType::DrawRoundRect> {
276 SkRect rect;
277 SkScalar rx;
278 SkScalar ry;
279 SkPaint paint;
280 void draw(SkCanvas* canvas) const {
281 canvas->drawRoundRect(rect, rx, ry, paint);
282 }
283 ASSERT_DRAWABLE()
284};
285
286template<>
Nader Jawadfb1e7f12020-11-06 22:49:42 -0800287struct CanvasOp<CanvasOpType::DrawDoubleRoundRect> {
288 SkRRect outer;
289 SkRRect inner;
290 SkPaint paint;
291 void draw(SkCanvas* canvas) const {
292 canvas->drawDRRect(outer, inner, paint);
293 }
294 ASSERT_DRAWABLE()
295};
296
297template<>
Nader Jawadd5c2b6d2020-11-05 19:12:29 -0800298struct CanvasOp<CanvasOpType::DrawCircle> {
299 SkScalar cx;
300 SkScalar cy;
301 SkScalar radius;
302 SkPaint paint;
303 void draw(SkCanvas* canvas) const {
304 canvas->drawCircle(cx, cy, radius, paint);
305 }
306 ASSERT_DRAWABLE()
307};
308
309template<>
310struct CanvasOp<CanvasOpType::DrawOval> {
311 SkRect oval;
312 SkPaint paint;
313 void draw(SkCanvas* canvas) const {
314 canvas->drawOval(oval, paint);
315 }
316 ASSERT_DRAWABLE()
317};
318
319template<>
320struct CanvasOp<CanvasOpType::DrawArc> {
321 SkRect oval;
322 SkScalar startAngle;
323 SkScalar sweepAngle;
324 bool useCenter;
325 SkPaint paint;
326
327 void draw(SkCanvas* canvas) const {
328 canvas->drawArc(oval, startAngle, sweepAngle, useCenter, paint);
329 }
330 ASSERT_DRAWABLE()
331};
John Reck013127b2020-10-29 20:53:51 -0400332
Nader Jawadfb1e7f12020-11-06 22:49:42 -0800333template<>
334struct CanvasOp<CanvasOpType::DrawPath> {
335 SkPath path;
336 SkPaint paint;
337
338 void draw(SkCanvas* canvas) const { canvas->drawPath(path, paint); }
339 ASSERT_DRAWABLE()
340};
341
342template<>
343struct CanvasOp<CanvasOpType::DrawLine> {
344 float startX;
345 float startY;
346 float endX;
347 float endY;
348 SkPaint paint;
349
350 void draw(SkCanvas* canvas) const {
351 canvas->drawLine(startX, startY, endX, endY, paint);
352 }
353 ASSERT_DRAWABLE()
354};
355
356template<>
Nader Jawad4285c8a2020-11-06 22:49:42 -0800357struct CanvasOp<CanvasOpType::DrawLines> {
358 size_t count;
359 SkPaint paint;
360 sk_sp<Points> points;
361 void draw(SkCanvas* canvas) const {
362 canvas->drawPoints(
363 SkCanvas::kLines_PointMode,
364 count,
365 points->data(),
366 paint
367 );
368 }
369 ASSERT_DRAWABLE()
370};
371
372template<>
Nader Jawadfb1e7f12020-11-06 22:49:42 -0800373struct CanvasOp<CanvasOpType::DrawVertices> {
374 sk_sp<SkVertices> vertices;
375 SkBlendMode mode;
376 SkPaint paint;
377 void draw(SkCanvas* canvas) const {
378 canvas->drawVertices(vertices, mode, paint);
379 }
380 ASSERT_DRAWABLE()
381};
382
Nader Jawadda9248c2020-11-09 17:27:36 -0800383template<>
384struct CanvasOp<CanvasOpType::DrawImage> {
385
John Reckb5eeb182020-12-09 13:45:39 -0500386 CanvasOp(
Nader Jawadda9248c2020-11-09 17:27:36 -0800387 const sk_sp<Bitmap>& bitmap,
388 float left,
389 float top,
Mike Reed7994a312021-01-28 18:06:26 -0500390 SkFilterMode filter,
Nader Jawadda9248c2020-11-09 17:27:36 -0800391 SkPaint paint
392 ) : left(left),
393 top(top),
Mike Reed7994a312021-01-28 18:06:26 -0500394 filter(filter),
Nader Jawadda9248c2020-11-09 17:27:36 -0800395 paint(std::move(paint)),
396 bitmap(bitmap),
397 image(bitmap->makeImage()) { }
398
399 float left;
400 float top;
Mike Reed7994a312021-01-28 18:06:26 -0500401 SkFilterMode filter;
Nader Jawadda9248c2020-11-09 17:27:36 -0800402 SkPaint paint;
403 sk_sp<Bitmap> bitmap;
404 sk_sp<SkImage> image;
405
406 void draw(SkCanvas* canvas) const {
Mike Reed7994a312021-01-28 18:06:26 -0500407 canvas->drawImage(image, left, top, SkSamplingOptions(filter), &paint);
Nader Jawadda9248c2020-11-09 17:27:36 -0800408 }
409 ASSERT_DRAWABLE()
410};
411
412template<>
413struct CanvasOp<CanvasOpType::DrawImageRect> {
414
John Reckb5eeb182020-12-09 13:45:39 -0500415 CanvasOp(
Nader Jawadda9248c2020-11-09 17:27:36 -0800416 const sk_sp<Bitmap>& bitmap,
417 SkRect src,
418 SkRect dst,
Mike Reed7994a312021-01-28 18:06:26 -0500419 SkFilterMode filter,
Nader Jawadda9248c2020-11-09 17:27:36 -0800420 SkPaint paint
421 ) : src(src),
422 dst(dst),
Mike Reed7994a312021-01-28 18:06:26 -0500423 filter(filter),
Nader Jawadda9248c2020-11-09 17:27:36 -0800424 paint(std::move(paint)),
425 bitmap(bitmap),
426 image(bitmap->makeImage()) { }
427
428 SkRect src;
429 SkRect dst;
Mike Reed7994a312021-01-28 18:06:26 -0500430 SkFilterMode filter;
Nader Jawadda9248c2020-11-09 17:27:36 -0800431 SkPaint paint;
432 sk_sp<Bitmap> bitmap;
433 sk_sp<SkImage> image;
434
435 void draw(SkCanvas* canvas) const {
436 canvas->drawImageRect(image,
437 src,
438 dst,
Mike Reed7994a312021-01-28 18:06:26 -0500439 SkSamplingOptions(filter),
Nader Jawadda9248c2020-11-09 17:27:36 -0800440 &paint,
441 SkCanvas::kFast_SrcRectConstraint
442 );
443 }
444 ASSERT_DRAWABLE()
445};
446
447template<>
448struct CanvasOp<CanvasOpType::DrawImageLattice> {
449
John Reckb5eeb182020-12-09 13:45:39 -0500450 CanvasOp(
Nader Jawadda9248c2020-11-09 17:27:36 -0800451 const sk_sp<Bitmap>& bitmap,
452 SkRect dst,
453 SkCanvas::Lattice lattice,
Mike Reed1b3dcfc2021-01-26 20:31:20 -0500454 SkFilterMode filter,
Nader Jawadda9248c2020-11-09 17:27:36 -0800455 SkPaint paint
456 ): dst(dst),
457 lattice(lattice),
Mike Reed1b3dcfc2021-01-26 20:31:20 -0500458 filter(filter),
Nader Jawadda9248c2020-11-09 17:27:36 -0800459 bitmap(bitmap),
460 image(bitmap->makeImage()),
461 paint(std::move(paint)) {}
462
463 SkRect dst;
464 SkCanvas::Lattice lattice;
Mike Reed1b3dcfc2021-01-26 20:31:20 -0500465 SkFilterMode filter;
Nader Jawadda9248c2020-11-09 17:27:36 -0800466 const sk_sp<Bitmap> bitmap;
467 const sk_sp<SkImage> image;
468
469 SkPaint paint;
470 void draw(SkCanvas* canvas) const {
Mike Reed1b3dcfc2021-01-26 20:31:20 -0500471 canvas->drawImageLattice(image.get(), lattice, dst, filter, &paint);
Nader Jawadda9248c2020-11-09 17:27:36 -0800472 }
473 ASSERT_DRAWABLE()
474};
475
476template<>
477struct CanvasOp<CanvasOpType::DrawPicture> {
478 sk_sp<SkPicture> picture;
479 void draw(SkCanvas* canvas) const {
480 picture->playback(canvas);
481 }
482};
483
Nader Jawad55f19762020-11-25 15:30:20 -0800484template<>
485struct CanvasOp<CanvasOpType::DrawLayer> {
486 sp<Layer> layer;
487};
488
John Reck064650b2021-01-19 21:29:24 -0500489template<>
490struct CanvasOp<CanvasOpType::DrawRenderNode> {
491 sp<RenderNode> renderNode;
492};
493
John Reck013127b2020-10-29 20:53:51 -0400494// cleanup our macros
495#undef ASSERT_DRAWABLE
496
Nader Jawadfb1e7f12020-11-06 22:49:42 -0800497} // namespace android::uirenderer