blob: a0cce98c8d576b16fbd008086d8d3049b3a49e92 [file] [log] [blame]
Stan Iliev021693b2016-10-17 16:26:15 -04001/*
2 * Copyright (C) 2016 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#include "SkiaRecordingCanvas.h"
18
19#include "Layer.h"
20#include "RenderNode.h"
21#include "LayerDrawable.h"
22#include "NinePatchUtils.h"
23#include "pipeline/skia/AnimatedDrawables.h"
Leon Scroggins IIIee708fa2016-12-12 15:31:39 -050024#include <SkImagePriv.h>
Stan Iliev021693b2016-10-17 16:26:15 -040025
26namespace android {
27namespace uirenderer {
28namespace skiapipeline {
29
30// ----------------------------------------------------------------------------
31// Recording Canvas Setup
32// ----------------------------------------------------------------------------
33
34void SkiaRecordingCanvas::initDisplayList(uirenderer::RenderNode* renderNode, int width,
35 int height) {
Stan Iliev021693b2016-10-17 16:26:15 -040036 mCurrentBarrier = nullptr;
37 SkASSERT(mDisplayList.get() == nullptr);
38
39 if (renderNode) {
40 mDisplayList = renderNode->detachAvailableList();
41 }
Derek Sollenbergerea1fe9b2017-03-01 13:02:43 -050042 if (!mDisplayList) {
43 mDisplayList.reset(new SkiaDisplayList());
Stan Iliev021693b2016-10-17 16:26:15 -040044 }
45
Derek Sollenbergerea1fe9b2017-03-01 13:02:43 -050046 mDisplayList->attachRecorder(&mRecorder, SkIRect::MakeWH(width, height));
Stan Iliev021693b2016-10-17 16:26:15 -040047 SkiaCanvas::reset(&mRecorder);
48}
49
50uirenderer::DisplayList* SkiaRecordingCanvas::finishRecording() {
51 // close any existing chunks if necessary
52 insertReorderBarrier(false);
53 mRecorder.restoreToCount(1);
54 return mDisplayList.release();
55}
56
57// ----------------------------------------------------------------------------
58// Recording Canvas draw operations: View System
59// ----------------------------------------------------------------------------
60
61void SkiaRecordingCanvas::drawRoundRect(uirenderer::CanvasPropertyPrimitive* left,
62 uirenderer::CanvasPropertyPrimitive* top, uirenderer::CanvasPropertyPrimitive* right,
63 uirenderer::CanvasPropertyPrimitive* bottom, uirenderer::CanvasPropertyPrimitive* rx,
64 uirenderer::CanvasPropertyPrimitive* ry, uirenderer::CanvasPropertyPaint* paint) {
Stan Ilievf7aa6cd2017-03-29 18:25:12 -040065 // Destructor of drawables created with allocateDrawable, will be invoked by ~LinearAllocator.
Stan Iliev021693b2016-10-17 16:26:15 -040066 drawDrawable(mDisplayList->allocateDrawable<AnimatedRoundRect>(left, top, right, bottom,
67 rx, ry, paint));
68}
69
70void SkiaRecordingCanvas::drawCircle(uirenderer::CanvasPropertyPrimitive* x,
71 uirenderer::CanvasPropertyPrimitive* y, uirenderer::CanvasPropertyPrimitive* radius,
72 uirenderer::CanvasPropertyPaint* paint) {
73 drawDrawable(mDisplayList->allocateDrawable<AnimatedCircle>(x, y, radius, paint));
74}
75
76void SkiaRecordingCanvas::insertReorderBarrier(bool enableReorder) {
Stan Iliev021693b2016-10-17 16:26:15 -040077 if (nullptr != mCurrentBarrier) {
78 // finish off the existing chunk
79 SkDrawable* drawable =
80 mDisplayList->allocateDrawable<EndReorderBarrierDrawable>(
81 mCurrentBarrier);
82 mCurrentBarrier = nullptr;
83 drawDrawable(drawable);
84 }
Stan Iliev88e08912016-11-22 18:19:29 -050085 if (enableReorder) {
86 mCurrentBarrier = (StartReorderBarrierDrawable*)
87 mDisplayList->allocateDrawable<StartReorderBarrierDrawable>(
88 mDisplayList.get());
89 drawDrawable(mCurrentBarrier);
90 }
Stan Iliev021693b2016-10-17 16:26:15 -040091}
92
93void SkiaRecordingCanvas::drawLayer(uirenderer::DeferredLayerUpdater* layerUpdater) {
94 if (layerUpdater != nullptr && layerUpdater->backingLayer() != nullptr) {
95 uirenderer::Layer* layer = layerUpdater->backingLayer();
Stan Ilievf7aa6cd2017-03-29 18:25:12 -040096 // Create a ref-counted drawable, which is kept alive by sk_sp in SkLiteDL.
Stan Iliev021693b2016-10-17 16:26:15 -040097 sk_sp<SkDrawable> drawable(new LayerDrawable(layer));
98 drawDrawable(drawable.get());
99 }
100}
101
102void SkiaRecordingCanvas::drawRenderNode(uirenderer::RenderNode* renderNode) {
Stan Ilievf7aa6cd2017-03-29 18:25:12 -0400103 // Record the child node. Drawable dtor will be invoked when mChildNodes deque is cleared.
Stan Iliev2f06e8a2016-11-02 15:29:03 -0400104 mDisplayList->mChildNodes.emplace_back(renderNode, asSkCanvas(), true, mCurrentBarrier);
Stan Ilievdb45a4b2016-11-08 14:18:31 -0500105 auto& renderNodeDrawable = mDisplayList->mChildNodes.back();
106 drawDrawable(&renderNodeDrawable);
Stan Iliev021693b2016-10-17 16:26:15 -0400107
108 // use staging property, since recording on UI thread
109 if (renderNode->stagingProperties().isProjectionReceiver()) {
Stan Ilievdb45a4b2016-11-08 14:18:31 -0500110 mDisplayList->mProjectionReceiver = &renderNodeDrawable;
Stan Iliev021693b2016-10-17 16:26:15 -0400111 // set projectionReceiveIndex so that RenderNode.hasProjectionReceiver returns true
112 mDisplayList->projectionReceiveIndex = mDisplayList->mChildNodes.size() - 1;
113 }
114}
115
116void SkiaRecordingCanvas::callDrawGLFunction(Functor* functor,
117 uirenderer::GlFunctorLifecycleListener* listener) {
Stan Ilievf7aa6cd2017-03-29 18:25:12 -0400118 // Drawable dtor will be invoked when mChildFunctors deque is cleared.
Stan Iliev021693b2016-10-17 16:26:15 -0400119 mDisplayList->mChildFunctors.emplace_back(functor, listener, asSkCanvas());
120 drawDrawable(&mDisplayList->mChildFunctors.back());
121}
122
123class VectorDrawable : public SkDrawable {
124 public:
125 VectorDrawable(VectorDrawableRoot* tree) : mRoot(tree) {}
126
127 protected:
128 virtual SkRect onGetBounds() override {
129 return SkRect::MakeLargest();
130 }
131 virtual void onDraw(SkCanvas* canvas) override {
Stan Iliev23c38a92017-03-23 00:12:50 -0400132 mRoot->draw(canvas);
Stan Iliev021693b2016-10-17 16:26:15 -0400133 }
134
135 private:
136 sp<VectorDrawableRoot> mRoot;
137};
138
139void SkiaRecordingCanvas::drawVectorDrawable(VectorDrawableRoot* tree) {
140 drawDrawable(mDisplayList->allocateDrawable<VectorDrawable>(tree));
141 mDisplayList->mVectorDrawables.push_back(tree);
142}
143
144// ----------------------------------------------------------------------------
145// Recording Canvas draw operations: Bitmaps
146// ----------------------------------------------------------------------------
147
148inline static const SkPaint* nonAAPaint(const SkPaint* origPaint, SkPaint* tmpPaint) {
149 if (origPaint && origPaint->isAntiAlias()) {
150 *tmpPaint = *origPaint;
151 tmpPaint->setAntiAlias(false);
152 return tmpPaint;
153 } else {
154 return origPaint;
155 }
156}
157
158void SkiaRecordingCanvas::drawBitmap(Bitmap& bitmap, float left, float top, const SkPaint* paint) {
Stan Iliev7bc3bc62017-05-24 13:28:36 -0400159 sk_sp<SkImage> image = bitmap.makeImage();
Stan Iliev021693b2016-10-17 16:26:15 -0400160 SkPaint tmpPaint;
161 mRecorder.drawImage(image, left, top, nonAAPaint(paint, &tmpPaint));
Stan Iliev0cc4e362017-05-18 14:21:23 -0400162 // if image->unique() is true, then mRecorder.drawImage failed for some reason. It also means
163 // it is not safe to store a raw SkImage pointer, because the image object will be destroyed
164 // when this function ends.
Stan Iliev7bc3bc62017-05-24 13:28:36 -0400165 if (!bitmap.isImmutable() && image.get() && !image->unique()) {
Stan Iliev0cc4e362017-05-18 14:21:23 -0400166 mDisplayList->mMutableImages.push_back(image.get());
167 }
Stan Iliev021693b2016-10-17 16:26:15 -0400168}
169
170void SkiaRecordingCanvas::drawBitmap(Bitmap& hwuiBitmap, const SkMatrix& matrix,
171 const SkPaint* paint) {
Stan Iliev021693b2016-10-17 16:26:15 -0400172 SkAutoCanvasRestore acr(&mRecorder, true);
173 concat(matrix);
Stan Iliev7bc3bc62017-05-24 13:28:36 -0400174 sk_sp<SkImage> image = hwuiBitmap.makeImage();
Stan Iliev021693b2016-10-17 16:26:15 -0400175 SkPaint tmpPaint;
176 mRecorder.drawImage(image, 0, 0, nonAAPaint(paint, &tmpPaint));
Stan Iliev7bc3bc62017-05-24 13:28:36 -0400177 if (!hwuiBitmap.isImmutable() && image.get() && !image->unique()) {
Stan Iliev0cc4e362017-05-18 14:21:23 -0400178 mDisplayList->mMutableImages.push_back(image.get());
179 }
Stan Iliev021693b2016-10-17 16:26:15 -0400180}
181
182void SkiaRecordingCanvas::drawBitmap(Bitmap& hwuiBitmap, float srcLeft, float srcTop,
183 float srcRight, float srcBottom, float dstLeft, float dstTop, float dstRight,
184 float dstBottom, const SkPaint* paint) {
Stan Iliev021693b2016-10-17 16:26:15 -0400185 SkRect srcRect = SkRect::MakeLTRB(srcLeft, srcTop, srcRight, srcBottom);
186 SkRect dstRect = SkRect::MakeLTRB(dstLeft, dstTop, dstRight, dstBottom);
Stan Iliev7bc3bc62017-05-24 13:28:36 -0400187 sk_sp<SkImage> image = hwuiBitmap.makeImage();
Stan Iliev021693b2016-10-17 16:26:15 -0400188 SkPaint tmpPaint;
189 mRecorder.drawImageRect(image, srcRect, dstRect, nonAAPaint(paint, &tmpPaint));
Stan Iliev7bc3bc62017-05-24 13:28:36 -0400190 if (!hwuiBitmap.isImmutable() && image.get() && !image->unique() && !srcRect.isEmpty()
Stan Iliev0cc4e362017-05-18 14:21:23 -0400191 && !dstRect.isEmpty()) {
192 mDisplayList->mMutableImages.push_back(image.get());
193 }
Stan Iliev021693b2016-10-17 16:26:15 -0400194}
195
196void SkiaRecordingCanvas::drawNinePatch(Bitmap& hwuiBitmap, const Res_png_9patch& chunk,
197 float dstLeft, float dstTop, float dstRight, float dstBottom, const SkPaint* paint) {
Stan Iliev021693b2016-10-17 16:26:15 -0400198 SkCanvas::Lattice lattice;
Stan Iliev7bc3bc62017-05-24 13:28:36 -0400199 NinePatchUtils::SetLatticeDivs(&lattice, chunk, hwuiBitmap.width(), hwuiBitmap.height());
Stan Iliev021693b2016-10-17 16:26:15 -0400200
201 lattice.fFlags = nullptr;
202 int numFlags = 0;
203 if (chunk.numColors > 0 && chunk.numColors == NinePatchUtils::NumDistinctRects(lattice)) {
204 // We can expect the framework to give us a color for every distinct rect.
205 // Skia requires placeholder flags for degenerate rects.
206 numFlags = (lattice.fXCount + 1) * (lattice.fYCount + 1);
207 }
208
209 SkAutoSTMalloc<25, SkCanvas::Lattice::Flags> flags(numFlags);
210 if (numFlags > 0) {
211 NinePatchUtils::SetLatticeFlags(&lattice, flags.get(), numFlags, chunk);
212 }
213
214 lattice.fBounds = nullptr;
215 SkRect dst = SkRect::MakeLTRB(dstLeft, dstTop, dstRight, dstBottom);
Stan Iliev7bc3bc62017-05-24 13:28:36 -0400216 sk_sp<SkImage> image = hwuiBitmap.makeImage();
Stan Iliev021693b2016-10-17 16:26:15 -0400217
218 SkPaint tmpPaint;
219 mRecorder.drawImageLattice(image.get(), lattice, dst, nonAAPaint(paint, &tmpPaint));
Stan Iliev7bc3bc62017-05-24 13:28:36 -0400220 if (!hwuiBitmap.isImmutable() && image.get() && !image->unique() && !dst.isEmpty()) {
Stan Iliev0cc4e362017-05-18 14:21:23 -0400221 mDisplayList->mMutableImages.push_back(image.get());
222 }
Stan Iliev021693b2016-10-17 16:26:15 -0400223}
224
225}; // namespace skiapipeline
226}; // namespace uirenderer
227}; // namespace android