RecordingCanvas.cpp revision 003cc3dec8e2a92e51086fbcd5ee1bb236efa701
1b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik/*
2b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * Copyright (C) 2015 The Android Open Source Project
3b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik *
4b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * Licensed under the Apache License, Version 2.0 (the "License");
5b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * you may not use this file except in compliance with the License.
6b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * You may obtain a copy of the License at
7b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik *
8b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik *      http://www.apache.org/licenses/LICENSE-2.0
9b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik *
10b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * Unless required by applicable law or agreed to in writing, software
11b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * distributed under the License is distributed on an "AS IS" BASIS,
12b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * See the License for the specific language governing permissions and
14b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * limitations under the License.
15b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik */
16b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
17b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#include "RecordingCanvas.h"
18b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
19b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#include "RecordedOp.h"
20b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#include "RenderNode.h"
21b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
22b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craiknamespace android {
23b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craiknamespace uirenderer {
24b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
25b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris CraikRecordingCanvas::RecordingCanvas(size_t width, size_t height)
26b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        : mState(*this)
27b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        , mResourceCache(ResourceCache::getInstance()) {
28b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    reset(width, height);
29b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
30b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
31b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris CraikRecordingCanvas::~RecordingCanvas() {
32003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik    LOG_ALWAYS_FATAL_IF(mDisplayList,
33b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            "Destroyed a RecordingCanvas during a record!");
34b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
35b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
36b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::reset(int width, int height) {
37003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik    LOG_ALWAYS_FATAL_IF(mDisplayList,
38b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            "prepareDirty called a second time during a recording!");
39003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik    mDisplayList = new DisplayList();
40b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
41b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    mState.initializeSaveStack(width, height, 0, 0, width, height, Vector3());
42b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
43b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    mDeferredBarrierType = kBarrier_InOrder;
44b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    mState.setDirtyClip(false);
45b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    mRestoreSaveCount = -1;
46b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
47b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
48003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris CraikDisplayList* RecordingCanvas::finishRecording() {
49b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    mPaintMap.clear();
50b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    mRegionMap.clear();
51b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    mPathMap.clear();
52003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik    DisplayList* displayList = mDisplayList;
53003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik    mDisplayList = nullptr;
54b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    mSkiaCanvasProxy.reset(nullptr);
55003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik    return displayList;
56b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
57b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
58b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris CraikSkCanvas* RecordingCanvas::asSkCanvas() {
59003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik    LOG_ALWAYS_FATAL_IF(!mDisplayList,
60b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            "attempting to get an SkCanvas when we are not recording!");
61b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    if (!mSkiaCanvasProxy) {
62b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        mSkiaCanvasProxy.reset(new SkiaCanvasProxy(this));
63b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    }
64b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
65b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    // SkCanvas instances default to identity transform, but should inherit
66b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    // the state of this Canvas; if this code was in the SkiaCanvasProxy
67b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    // constructor, we couldn't cache mSkiaCanvasProxy.
68b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    SkMatrix parentTransform;
69b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    getMatrix(&parentTransform);
70b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    mSkiaCanvasProxy.get()->setMatrix(parentTransform);
71b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
72b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    return mSkiaCanvasProxy.get();
73b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
74b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
75b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik// ----------------------------------------------------------------------------
76b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik// android/graphics/Canvas state operations
77b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik// ----------------------------------------------------------------------------
78b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik// Save (layer)
79b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikint RecordingCanvas::save(SkCanvas::SaveFlags flags) {
80b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    return mState.save((int) flags);
81b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
82b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
83b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::RecordingCanvas::restore() {
84b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    if (mRestoreSaveCount < 0) {
85b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        restoreToCount(getSaveCount() - 1);
86b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        return;
87b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    }
88b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
89b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    mRestoreSaveCount--;
90b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    mState.restore();
91b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
92b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
93b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::restoreToCount(int saveCount) {
94b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    mRestoreSaveCount = saveCount;
95b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    mState.restoreToCount(saveCount);
96b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
97b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
98b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikint RecordingCanvas::saveLayer(float left, float top, float right, float bottom, const SkPaint* paint,
99b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        SkCanvas::SaveFlags flags) {
100b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    LOG_ALWAYS_FATAL("TODO");
101b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    return 0;
102b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
103b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
104b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik// Matrix
105b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::rotate(float degrees) {
106b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    if (degrees == 0) return;
107b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
108b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    mState.rotate(degrees);
109b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
110b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
111b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::scale(float sx, float sy) {
112b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    if (sx == 1 && sy == 1) return;
113b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
114b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    mState.scale(sx, sy);
115b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
116b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
117b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::skew(float sx, float sy) {
118b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    mState.skew(sx, sy);
119b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
120b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
121b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::translate(float dx, float dy) {
122b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    if (dx == 0 && dy == 0) return;
123b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
124b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    mState.translate(dx, dy, 0);
125b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
126b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
127b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik// Clip
128b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikbool RecordingCanvas::getClipBounds(SkRect* outRect) const {
129b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    Rect bounds = mState.getLocalClipBounds();
130b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    *outRect = SkRect::MakeLTRB(bounds.left, bounds.top, bounds.right, bounds.bottom);
131b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    return !(outRect->isEmpty());
132b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
133b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikbool RecordingCanvas::quickRejectRect(float left, float top, float right, float bottom) const {
134b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    return mState.quickRejectConservative(left, top, right, bottom);
135b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
136b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikbool RecordingCanvas::quickRejectPath(const SkPath& path) const {
137b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    SkRect bounds = path.getBounds();
138b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    return mState.quickRejectConservative(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
139b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
140b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikbool RecordingCanvas::clipRect(float left, float top, float right, float bottom, SkRegion::Op op) {
141b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    return mState.clipRect(left, top, right, bottom, op);
142b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
143b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikbool RecordingCanvas::clipPath(const SkPath* path, SkRegion::Op op) {
144b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    return mState.clipPath(path, op);
145b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
146b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikbool RecordingCanvas::clipRegion(const SkRegion* region, SkRegion::Op op) {
147b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    return mState.clipRegion(region, op);
148b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
149b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
150b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik// ----------------------------------------------------------------------------
151b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik// android/graphics/Canvas draw operations
152b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik// ----------------------------------------------------------------------------
153b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawColor(int color, SkXfermode::Mode mode) {
154b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    SkPaint paint;
155b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    paint.setColor(color);
156b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    paint.setXfermodeMode(mode);
157b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    drawPaint(paint);
158b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
159b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
160b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawPaint(const SkPaint& paint) {
161b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    // TODO: more efficient recording?
162b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    Matrix4 identity;
163b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    identity.loadIdentity();
164b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
165b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    addOp(new (alloc()) RectOp(
166b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            mState.getRenderTargetClipBounds(),
167b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            identity,
168b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            mState.getRenderTargetClipBounds(),
169b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            refPaint(&paint)));
170b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
171b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
172b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik// Geometry
173b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawPoints(const float* points, int count, const SkPaint& paint) {
174b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    LOG_ALWAYS_FATAL("TODO!");
175b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
176b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawLines(const float* points, int count, const SkPaint& paint) {
177b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    LOG_ALWAYS_FATAL("TODO!");
178b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
179b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawRect(float left, float top, float right, float bottom, const SkPaint& paint) {
180b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    addOp(new (alloc()) RectOp(
181b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            Rect(left, top, right, bottom),
182b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            *(mState.currentSnapshot()->transform),
183b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            mState.getRenderTargetClipBounds(),
184b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            refPaint(&paint)));
185b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
186b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
187b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawSimpleRects(const float* rects, int vertexCount, const SkPaint* paint) {
188b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    if (rects == nullptr) return;
189b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
190003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik    Vertex* rectData = (Vertex*) mDisplayList->allocator.alloc(vertexCount * sizeof(Vertex));
191b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    Vertex* vertex = rectData;
192b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
193b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    float left = FLT_MAX;
194b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    float top = FLT_MAX;
195b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    float right = FLT_MIN;
196b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    float bottom = FLT_MIN;
197b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    for (int index = 0; index < vertexCount; index += 4) {
198b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        float l = rects[index + 0];
199b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        float t = rects[index + 1];
200b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        float r = rects[index + 2];
201b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        float b = rects[index + 3];
202b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
203b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        Vertex::set(vertex++, l, t);
204b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        Vertex::set(vertex++, r, t);
205b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        Vertex::set(vertex++, l, b);
206b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        Vertex::set(vertex++, r, b);
207b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
208b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        left = std::min(left, l);
209b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        top = std::min(top, t);
210b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        right = std::max(right, r);
211b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        bottom = std::max(bottom, b);
212b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    }
213b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    addOp(new (alloc()) SimpleRectsOp(
214b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            Rect(left, top, right, bottom),
215b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            *(mState.currentSnapshot()->transform),
216b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            mState.getRenderTargetClipBounds(),
217b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            refPaint(paint), rectData, vertexCount));
218b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
219b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
220b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawRegion(const SkRegion& region, const SkPaint& paint) {
221b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    if (paint.getStyle() == SkPaint::kFill_Style
222b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            && (!paint.isAntiAlias() || mState.currentTransform()->isSimple())) {
223b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        int count = 0;
224b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        Vector<float> rects;
225b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        SkRegion::Iterator it(region);
226b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        while (!it.done()) {
227b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            const SkIRect& r = it.rect();
228b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            rects.push(r.fLeft);
229b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            rects.push(r.fTop);
230b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            rects.push(r.fRight);
231b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            rects.push(r.fBottom);
232b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            count += 4;
233b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            it.next();
234b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        }
235b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        drawSimpleRects(rects.array(), count, &paint);
236b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    } else {
237b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        SkRegion::Iterator it(region);
238b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        while (!it.done()) {
239b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            const SkIRect& r = it.rect();
240b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            drawRect(r.fLeft, r.fTop, r.fRight, r.fBottom, paint);
241b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            it.next();
242b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        }
243b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    }
244b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
245b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawRoundRect(float left, float top, float right, float bottom,
246b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            float rx, float ry, const SkPaint& paint) {
247b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    LOG_ALWAYS_FATAL("TODO!");
248b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
249b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawCircle(float x, float y, float radius, const SkPaint& paint) {
250b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    LOG_ALWAYS_FATAL("TODO!");
251b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
252b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawOval(float left, float top, float right, float bottom, const SkPaint& paint) {
253b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    LOG_ALWAYS_FATAL("TODO!");
254b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
255b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawArc(float left, float top, float right, float bottom,
256b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            float startAngle, float sweepAngle, bool useCenter, const SkPaint& paint) {
257b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    LOG_ALWAYS_FATAL("TODO!");
258b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
259b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
260b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    LOG_ALWAYS_FATAL("TODO!");
261b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
262b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
263b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik// Bitmap-based
264b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawBitmap(const SkBitmap& bitmap, float left, float top, const SkPaint* paint) {
265b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    save(SkCanvas::kMatrix_SaveFlag);
266b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    translate(left, top);
267b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    drawBitmap(&bitmap, paint);
268b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    restore();
269b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
270b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
271b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawBitmap(const SkBitmap& bitmap, const SkMatrix& matrix,
272b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik                            const SkPaint* paint) {
273b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    if (matrix.isIdentity()) {
274b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        drawBitmap(&bitmap, paint);
275b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    } else if (!(matrix.getType() & ~(SkMatrix::kScale_Mask | SkMatrix::kTranslate_Mask))
276b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            && MathUtils::isPositive(matrix.getScaleX())
277b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            && MathUtils::isPositive(matrix.getScaleY())) {
278b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        // SkMatrix::isScaleTranslate() not available in L
279b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        SkRect src;
280b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        SkRect dst;
281b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        bitmap.getBounds(&src);
282b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        matrix.mapRect(&dst, src);
283b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        drawBitmap(bitmap, src.fLeft, src.fTop, src.fRight, src.fBottom,
284b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik                   dst.fLeft, dst.fTop, dst.fRight, dst.fBottom, paint);
285b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    } else {
286b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        save(SkCanvas::kMatrix_SaveFlag);
287b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        concat(matrix);
288b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        drawBitmap(&bitmap, paint);
289b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        restore();
290b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    }
291b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
292b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawBitmap(const SkBitmap& bitmap, float srcLeft, float srcTop,
293b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            float srcRight, float srcBottom, float dstLeft, float dstTop,
294b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            float dstRight, float dstBottom, const SkPaint* paint) {
295b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    if (srcLeft == 0 && srcTop == 0
296b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            && srcRight == bitmap.width()
297b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            && srcBottom == bitmap.height()
298b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            && (srcBottom - srcTop == dstBottom - dstTop)
299b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            && (srcRight - srcLeft == dstRight - dstLeft)) {
300b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        // transform simple rect to rect drawing case into position bitmap ops, since they merge
301b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        save(SkCanvas::kMatrix_SaveFlag);
302b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        translate(dstLeft, dstTop);
303b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        drawBitmap(&bitmap, paint);
304b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        restore();
305b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    } else {
306b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        LOG_ALWAYS_FATAL("TODO!");
307b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    }
308b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
309b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawBitmapMesh(const SkBitmap& bitmap, int meshWidth, int meshHeight,
310b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            const float* vertices, const int* colors, const SkPaint* paint) {
311b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    LOG_ALWAYS_FATAL("TODO!");
312b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
313b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawNinePatch(const SkBitmap& bitmap, const android::Res_png_9patch& chunk,
314b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            float dstLeft, float dstTop, float dstRight, float dstBottom,
315b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            const SkPaint* paint) {
316b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    LOG_ALWAYS_FATAL("TODO!");
317b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
318b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
319b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik// Text
320b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawText(const uint16_t* glyphs, const float* positions, int count,
321b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            const SkPaint& paint, float x, float y, float boundsLeft, float boundsTop,
322b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            float boundsRight, float boundsBottom, float totalAdvance) {
323b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    LOG_ALWAYS_FATAL("TODO!");
324b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
325b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawPosText(const uint16_t* text, const float* positions, int count,
326b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            int posCount, const SkPaint& paint) {
327b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    LOG_ALWAYS_FATAL("TODO!");
328b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
329b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawTextOnPath(const uint16_t* glyphs, int count, const SkPath& path,
330b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            float hOffset, float vOffset, const SkPaint& paint) {
331b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    LOG_ALWAYS_FATAL("TODO!");
332b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
333b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
334b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawBitmap(const SkBitmap* bitmap, const SkPaint* paint) {
335b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    addOp(new (alloc()) BitmapOp(
336b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            Rect(0, 0, bitmap->width(), bitmap->height()),
337b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            *(mState.currentSnapshot()->transform),
338b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            mState.getRenderTargetClipBounds(),
339b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            refPaint(paint), refBitmap(*bitmap)));
340b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
341b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawRenderNode(RenderNode* renderNode) {
342b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    RenderNodeOp* op = new (alloc()) RenderNodeOp(
343b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            Rect(0, 0, renderNode->getWidth(), renderNode->getHeight()), // are these safe? they're theoretically dynamic
344b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            *(mState.currentSnapshot()->transform),
345b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            mState.getRenderTargetClipBounds(),
346b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            renderNode);
347b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    int opIndex = addOp(op);
348003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik    int childIndex = mDisplayList->addChild(op);
349b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
350b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    // update the chunk's child indices
351003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik    DisplayList::Chunk& chunk = mDisplayList->chunks.back();
352b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    chunk.endChildIndex = childIndex + 1;
353b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
354b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    if (renderNode->stagingProperties().isProjectionReceiver()) {
355b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        // use staging property, since recording on UI thread
356003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik        mDisplayList->projectionReceiveIndex = opIndex;
357b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    }
358b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
359b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
360b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craiksize_t RecordingCanvas::addOp(RecordedOp* op) {
361b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    // TODO: validate if "addDrawOp" quickrejection logic is useful before adding
362003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik    int insertIndex = mDisplayList->ops.size();
363003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik    mDisplayList->ops.push_back(op);
364b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    if (mDeferredBarrierType != kBarrier_None) {
365b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        // op is first in new chunk
366003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik        mDisplayList->chunks.emplace_back();
367003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik        DisplayList::Chunk& newChunk = mDisplayList->chunks.back();
368b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        newChunk.beginOpIndex = insertIndex;
369b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        newChunk.endOpIndex = insertIndex + 1;
370b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        newChunk.reorderChildren = (mDeferredBarrierType == kBarrier_OutOfOrder);
371b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
372003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik        int nextChildIndex = mDisplayList->children().size();
373b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        newChunk.beginChildIndex = newChunk.endChildIndex = nextChildIndex;
374b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        mDeferredBarrierType = kBarrier_None;
375b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    } else {
376b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        // standard case - append to existing chunk
377003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik        mDisplayList->chunks.back().endOpIndex = insertIndex + 1;
378b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    }
379b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    return insertIndex;
380b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
381b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
382b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::refBitmapsInShader(const SkShader* shader) {
383b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    if (!shader) return;
384b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
385b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    // If this paint has an SkShader that has an SkBitmap add
386b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    // it to the bitmap pile
387b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    SkBitmap bitmap;
388b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    SkShader::TileMode xy[2];
389b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    if (shader->asABitmap(&bitmap, nullptr, xy) == SkShader::kDefault_BitmapType) {
390b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        refBitmap(bitmap);
391b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        return;
392b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    }
393b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    SkShader::ComposeRec rec;
394b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    if (shader->asACompose(&rec)) {
395b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        refBitmapsInShader(rec.fShaderA);
396b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        refBitmapsInShader(rec.fShaderB);
397b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        return;
398b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    }
399b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
400b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
401b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}; // namespace uirenderer
402b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}; // namespace android
403