blob: 98315d0a416a6b5bff170572d20cc483ca8bdddf [file] [log] [blame]
Chris Craik2af46352012-11-26 18:30:17 -08001/*
Romain Guy7031ff62013-02-22 11:48:16 -08002 * Copyright (C) 2013 The Android Open Source Project
Chris Craik2af46352012-11-26 18:30:17 -08003 *
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#ifndef ANDROID_HWUI_DISPLAY_OPERATION_H
18#define ANDROID_HWUI_DISPLAY_OPERATION_H
19
Chris Craik2af46352012-11-26 18:30:17 -080020#include "OpenGLRenderer.h"
Romain Guy3b748a42013-04-17 18:54:38 -070021#include "AssetAtlas.h"
Chris Craikc3566d02013-02-04 16:16:33 -080022#include "DeferredDisplayList.h"
Chris Craikdb663fe2015-04-20 13:34:45 -070023#include "DisplayListCanvas.h"
Tom Hudson2dc236b2014-10-15 15:46:42 -040024#include "GammaFontRenderer.h"
25#include "Patch.h"
26#include "RenderNode.h"
Chris Craik65fe5ee2015-01-26 18:06:29 -080027#include "renderstate/RenderState.h"
Romain Guy3b748a42013-04-17 18:54:38 -070028#include "UvMapper.h"
Chris Craik2af46352012-11-26 18:30:17 -080029#include "utils/LinearAllocator.h"
Tom Hudson8dfaa492014-12-09 15:03:44 -050030#include "utils/PaintUtils.h"
Chris Craik2af46352012-11-26 18:30:17 -080031
Chris Craikdf72b632015-06-30 17:56:13 -070032#include <algorithm>
33
Chris Craik65fe5ee2015-01-26 18:06:29 -080034#include <SkColor.h>
35#include <SkPath.h>
36#include <SkPathOps.h>
37#include <SkXfermode.h>
38
39#include <private/hwui/DrawGlInfo.h>
40
Chris Craik2af46352012-11-26 18:30:17 -080041// Use OP_LOG for logging with arglist, OP_LOGS if just printing char*
Chris Craik28ce94a2013-05-31 11:38:03 -070042#define OP_LOGS(s) OP_LOG("%s", (s))
Chris Craik3dc553b2013-02-04 12:45:13 -080043#define OP_LOG(s, ...) ALOGD( "%*s" s, level * 2, "", __VA_ARGS__ )
Chris Craik2af46352012-11-26 18:30:17 -080044
Chris Craik2af46352012-11-26 18:30:17 -080045namespace android {
46namespace uirenderer {
47
48/**
49 * Structure for storing canvas operations when they are recorded into a DisplayList, so that they
50 * may be replayed to an OpenGLRenderer.
51 *
52 * To avoid individual memory allocations, DisplayListOps may only be allocated into a
53 * LinearAllocator's managed memory buffers. Each pointer held by a DisplayListOp is either a
54 * pointer into memory also allocated in the LinearAllocator (mostly for text and float buffers) or
55 * references a externally refcounted object (Sk... and Skia... objects). ~DisplayListOp() is
56 * never called as LinearAllocators are simply discarded, so no memory management should be done in
57 * this class.
58 */
59class DisplayListOp {
60public:
61 // These objects should always be allocated with a LinearAllocator, and never destroyed/deleted.
62 // standard new() intentionally not implemented, and delete/deconstructor should never be used.
Chris Craik51d6a3d2014-12-22 17:16:56 -080063 virtual ~DisplayListOp() { LOG_ALWAYS_FATAL("Destructor not supported"); }
64 static void operator delete(void* ptr) { LOG_ALWAYS_FATAL("delete not supported"); }
65 static void* operator new(size_t size) = delete; /** PURPOSELY OMITTED **/
Chris Craik2af46352012-11-26 18:30:17 -080066 static void* operator new(size_t size, LinearAllocator& allocator) {
John Reck7df9ff22016-02-10 16:08:08 -080067 // FIXME: Quick hack to keep old pipeline working, delete this when
68 // we no longer need to support HWUI_NEWOPS := false
69 return allocator.alloc<char>(size);
Chris Craik2af46352012-11-26 18:30:17 -080070 }
71
72 enum OpLogFlag {
73 kOpLogFlag_Recurse = 0x1,
74 kOpLogFlag_JSON = 0x2 // TODO: add?
75 };
76
Chet Haasedd671592013-04-19 14:54:34 -070077 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
78 bool useQuickReject) = 0;
Chris Craikc3566d02013-02-04 16:16:33 -080079
Chet Haasedd671592013-04-19 14:54:34 -070080 virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level,
81 bool useQuickReject) = 0;
Chris Craikff785832013-03-08 13:12:16 -080082
Chris Craikc5493fb2013-06-19 16:58:58 -070083 virtual void output(int level, uint32_t logFlags = 0) const = 0;
Chris Craik2af46352012-11-26 18:30:17 -080084
85 // NOTE: it would be nice to declare constants and overriding the implementation in each op to
86 // point at the constants, but that seems to require a .cpp file
87 virtual const char* name() = 0;
88};
89
90class StateOp : public DisplayListOp {
91public:
Andreas Gampe64bb4132014-11-22 00:35:09 +000092 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
Chris Craikd41c4d82015-01-05 15:51:13 -080093 bool useQuickReject) override {
Chris Craikff785832013-03-08 13:12:16 -080094 // default behavior only affects immediate, deferrable state, issue directly to renderer
95 applyState(deferStruct.mRenderer, saveCount);
96 }
97
Chris Craikc3566d02013-02-04 16:16:33 -080098 /**
99 * State operations are applied directly to the renderer, but can cause the deferred drawing op
100 * list to flush
101 */
Andreas Gampe64bb4132014-11-22 00:35:09 +0000102 virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level,
Chris Craikd41c4d82015-01-05 15:51:13 -0800103 bool useQuickReject) override {
Chris Craikff785832013-03-08 13:12:16 -0800104 applyState(replayStruct.mRenderer, saveCount);
Chris Craikc3566d02013-02-04 16:16:33 -0800105 }
106
Chris Craik7273daa2013-03-28 11:25:24 -0700107 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const = 0;
Chris Craik2af46352012-11-26 18:30:17 -0800108};
109
110class DrawOp : public DisplayListOp {
Chris Craik527a3aa2013-03-04 10:19:31 -0800111friend class MergingDrawBatch;
Chris Craik2af46352012-11-26 18:30:17 -0800112public:
Chris Craikd218a922014-01-02 17:13:34 -0800113 DrawOp(const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -0800114 : mPaint(paint), mQuickRejected(false) {}
115
Andreas Gampe64bb4132014-11-22 00:35:09 +0000116 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
Chris Craikd41c4d82015-01-05 15:51:13 -0800117 bool useQuickReject) override {
Chet Haasedd671592013-04-19 14:54:34 -0700118 if (mQuickRejected && CC_LIKELY(useQuickReject)) {
Chris Craikff785832013-03-08 13:12:16 -0800119 return;
Chris Craikc3566d02013-02-04 16:16:33 -0800120 }
121
Chris Craikff785832013-03-08 13:12:16 -0800122 deferStruct.mDeferredList.addDrawOp(deferStruct.mRenderer, this);
Chris Craikc3566d02013-02-04 16:16:33 -0800123 }
124
Andreas Gampe64bb4132014-11-22 00:35:09 +0000125 virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level,
Chris Craikd41c4d82015-01-05 15:51:13 -0800126 bool useQuickReject) override {
Chet Haasedd671592013-04-19 14:54:34 -0700127 if (mQuickRejected && CC_LIKELY(useQuickReject)) {
Chris Craikff785832013-03-08 13:12:16 -0800128 return;
129 }
130
Tom Hudson107843d2014-09-08 11:26:26 -0400131 applyDraw(replayStruct.mRenderer, replayStruct.mDirty);
Chris Craikff785832013-03-08 13:12:16 -0800132 }
133
Tom Hudson107843d2014-09-08 11:26:26 -0400134 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) = 0;
Chris Craik2af46352012-11-26 18:30:17 -0800135
Chris Craik527a3aa2013-03-04 10:19:31 -0800136 /**
137 * Draw multiple instances of an operation, must be overidden for operations that merge
138 *
139 * Currently guarantees certain similarities between ops (see MergingDrawBatch::canMergeWith),
140 * and pure translation transformations. Other guarantees of similarity should be enforced by
141 * reducing which operations are tagged as mergeable.
142 */
Tom Hudson107843d2014-09-08 11:26:26 -0400143 virtual void multiDraw(OpenGLRenderer& renderer, Rect& dirty,
John Reck272a6852015-07-29 16:48:58 -0700144 const std::vector<OpStatePair>& ops, const Rect& bounds) {
Chris Craik527a3aa2013-03-04 10:19:31 -0800145 for (unsigned int i = 0; i < ops.size(); i++) {
Chris Craikc1c5f082013-09-11 16:23:37 -0700146 renderer.restoreDisplayState(*(ops[i].state), true);
Tom Hudson107843d2014-09-08 11:26:26 -0400147 ops[i].op->applyDraw(renderer, dirty);
Chris Craik527a3aa2013-03-04 10:19:31 -0800148 }
Chris Craik527a3aa2013-03-04 10:19:31 -0800149 }
150
Chris Craik28ce94a2013-05-31 11:38:03 -0700151 /**
Chris Craik527a3aa2013-03-04 10:19:31 -0800152 * When this method is invoked the state field is initialized to have the
153 * final rendering state. We can thus use it to process data as it will be
154 * used at draw time.
155 *
156 * Additionally, this method allows subclasses to provide defer-time preferences for batching
157 * and merging.
158 *
Chris Craik28ce94a2013-05-31 11:38:03 -0700159 * if a subclass can set deferInfo.mergeable to true, it should implement multiDraw()
Chris Craik527a3aa2013-03-04 10:19:31 -0800160 */
Andreas Gampe64bb4132014-11-22 00:35:09 +0000161 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
162 const DeferredDisplayState& state) {}
Romain Guy0f667532013-03-01 14:31:04 -0800163
Chris Craik5e49b302013-07-30 19:05:20 -0700164 /**
165 * Query the conservative, local bounds (unmapped) bounds of the op.
166 *
167 * returns true if bounds exist
168 */
Andreas Gampe64bb4132014-11-22 00:35:09 +0000169 virtual bool getLocalBounds(Rect& localBounds) {
Chris Craikc1c5f082013-09-11 16:23:37 -0700170 return false;
171 }
Chris Craik2af46352012-11-26 18:30:17 -0800172
173 // TODO: better refine localbounds usage
174 void setQuickRejected(bool quickRejected) { mQuickRejected = quickRejected; }
175 bool getQuickRejected() { return mQuickRejected; }
176
Derek Sollenbergerc29a0a42014-03-31 13:52:39 -0400177 virtual bool hasTextShadow() const {
178 return false;
179 }
180
Chris Craik527a3aa2013-03-04 10:19:31 -0800181 inline float strokeWidthOutset() {
Chris Craikf0a59072013-11-19 18:00:46 -0800182 // since anything AA stroke with less than 1.0 pixel width is drawn with an alpha-reduced
183 // 1.0 stroke, treat 1.0 as minimum.
184
185 // TODO: it would be nice if this could take scale into account, but scale isn't stable
186 // since higher levels of the view hierarchy can change scale out from underneath it.
Chris Craikdf72b632015-06-30 17:56:13 -0700187 return std::max(mPaint->getStrokeWidth(), 1.0f) * 0.5f;
Chris Craike7c69c62013-04-03 09:55:48 -0700188 }
Chris Craikc3566d02013-02-04 16:16:33 -0800189
Chris Craik2af46352012-11-26 18:30:17 -0800190protected:
Chris Craik28ce94a2013-05-31 11:38:03 -0700191 // Helper method for determining op opaqueness. Assumes op fills its bounds in local
192 // coordinates, and that paint's alpha is used
Chris Craikc1c5f082013-09-11 16:23:37 -0700193 inline bool isOpaqueOverBounds(const DeferredDisplayState& state) {
Chris Craik28ce94a2013-05-31 11:38:03 -0700194 // ensure that local bounds cover mapped bounds
195 if (!state.mMatrix.isSimple()) return false;
196
Chris Craik2262abb2014-08-18 19:55:36 -0700197 if (state.mRoundRectClipState) return false;
198
Chris Craik28ce94a2013-05-31 11:38:03 -0700199 // check state/paint for transparency
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400200 if (mPaint) {
Chris Craikc5b5f052014-10-01 16:40:16 -0700201 if (mPaint->getAlpha() != 0xFF) {
202 return false;
203 }
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400204 if (mPaint->getShader() && !mPaint->getShader()->isOpaque()) {
205 return false;
206 }
Tom Hudson8dfaa492014-12-09 15:03:44 -0500207 if (PaintUtils::isBlendedColorFilter(mPaint->getColorFilter())) {
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400208 return false;
209 }
210 }
211
212 if (state.mAlpha != 1.0f) return false;
Chris Craik28ce94a2013-05-31 11:38:03 -0700213
Chris Craikbf6f0f22015-10-01 12:36:07 -0700214 SkXfermode::Mode mode = PaintUtils::getXfermodeDirect(mPaint);
Chris Craik28ce94a2013-05-31 11:38:03 -0700215 return (mode == SkXfermode::kSrcOver_Mode ||
216 mode == SkXfermode::kSrc_Mode);
217
218 }
219
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -0400220 const SkPaint* mPaint;
Chris Craik2af46352012-11-26 18:30:17 -0800221 bool mQuickRejected;
222};
223
224class DrawBoundedOp : public DrawOp {
225public:
Chris Craikd218a922014-01-02 17:13:34 -0800226 DrawBoundedOp(float left, float top, float right, float bottom, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -0800227 : DrawOp(paint), mLocalBounds(left, top, right, bottom) {}
228
Chris Craikd218a922014-01-02 17:13:34 -0800229 DrawBoundedOp(const Rect& localBounds, const SkPaint* paint)
Chris Craik41541822013-05-03 16:35:54 -0700230 : DrawOp(paint), mLocalBounds(localBounds) {}
231
Chris Craik5d116762013-02-19 17:49:31 -0800232 // Calculates bounds as smallest rect encompassing all points
233 // NOTE: requires at least 1 vertex, and doesn't account for stroke size (should be handled in
234 // subclass' constructor)
Chris Craikd218a922014-01-02 17:13:34 -0800235 DrawBoundedOp(const float* points, int count, const SkPaint* paint)
Chris Craik5d116762013-02-19 17:49:31 -0800236 : DrawOp(paint), mLocalBounds(points[0], points[1], points[0], points[1]) {
237 for (int i = 2; i < count; i += 2) {
Chris Craikdf72b632015-06-30 17:56:13 -0700238 mLocalBounds.left = std::min(mLocalBounds.left, points[i]);
239 mLocalBounds.right = std::max(mLocalBounds.right, points[i]);
240 mLocalBounds.top = std::min(mLocalBounds.top, points[i + 1]);
241 mLocalBounds.bottom = std::max(mLocalBounds.bottom, points[i + 1]);
Chris Craik5d116762013-02-19 17:49:31 -0800242 }
243 }
244
245 // default empty constructor for bounds, to be overridden in child constructor body
Chris Craikd218a922014-01-02 17:13:34 -0800246 DrawBoundedOp(const SkPaint* paint): DrawOp(paint) { }
Chris Craik2af46352012-11-26 18:30:17 -0800247
Chris Craikd41c4d82015-01-05 15:51:13 -0800248 virtual bool getLocalBounds(Rect& localBounds) override {
Chris Craik2af46352012-11-26 18:30:17 -0800249 localBounds.set(mLocalBounds);
Chris Craikbf6f0f22015-10-01 12:36:07 -0700250 PaintUtils::TextShadow textShadow;
251 if (PaintUtils::getTextShadow(mPaint, &textShadow)) {
Romain Guy9b5a1a22013-08-09 14:06:29 -0700252 Rect shadow(mLocalBounds);
Derek Sollenbergerc29a0a42014-03-31 13:52:39 -0400253 shadow.translate(textShadow.dx, textShadow.dx);
254 shadow.outset(textShadow.radius);
Romain Guy9b5a1a22013-08-09 14:06:29 -0700255 localBounds.unionWith(shadow);
256 }
Chris Craik2af46352012-11-26 18:30:17 -0800257 return true;
258 }
259
260protected:
261 Rect mLocalBounds; // displayed area in LOCAL coord. doesn't incorporate stroke, so check paint
262};
263
264///////////////////////////////////////////////////////////////////////////////
265// STATE OPERATIONS - these may affect the state of the canvas/renderer, but do
266// not directly draw or alter output
267///////////////////////////////////////////////////////////////////////////////
268
269class SaveOp : public StateOp {
270public:
271 SaveOp(int flags)
272 : mFlags(flags) {}
273
Andreas Gampe64bb4132014-11-22 00:35:09 +0000274 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
Chris Craikd41c4d82015-01-05 15:51:13 -0800275 bool useQuickReject) override {
Chris Craikff785832013-03-08 13:12:16 -0800276 int newSaveCount = deferStruct.mRenderer.save(mFlags);
277 deferStruct.mDeferredList.addSave(deferStruct.mRenderer, this, newSaveCount);
278 }
279
Chris Craikd41c4d82015-01-05 15:51:13 -0800280 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const override {
Chris Craik2af46352012-11-26 18:30:17 -0800281 renderer.save(mFlags);
282 }
283
Chris Craikd41c4d82015-01-05 15:51:13 -0800284 virtual void output(int level, uint32_t logFlags) const override {
Chris Craik2af46352012-11-26 18:30:17 -0800285 OP_LOG("Save flags %x", mFlags);
286 }
287
Chris Craikd41c4d82015-01-05 15:51:13 -0800288 virtual const char* name() override { return "Save"; }
Chris Craik2af46352012-11-26 18:30:17 -0800289
Chris Craikff785832013-03-08 13:12:16 -0800290 int getFlags() const { return mFlags; }
Chris Craik2af46352012-11-26 18:30:17 -0800291private:
292 int mFlags;
293};
294
295class RestoreToCountOp : public StateOp {
296public:
297 RestoreToCountOp(int count)
298 : mCount(count) {}
299
Andreas Gampe64bb4132014-11-22 00:35:09 +0000300 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
Chris Craikd41c4d82015-01-05 15:51:13 -0800301 bool useQuickReject) override {
Chris Craik7273daa2013-03-28 11:25:24 -0700302 deferStruct.mDeferredList.addRestoreToCount(deferStruct.mRenderer,
303 this, saveCount + mCount);
Chris Craikff785832013-03-08 13:12:16 -0800304 deferStruct.mRenderer.restoreToCount(saveCount + mCount);
Chris Craik2af46352012-11-26 18:30:17 -0800305 }
306
Chris Craikd41c4d82015-01-05 15:51:13 -0800307 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const override {
Chris Craikff785832013-03-08 13:12:16 -0800308 renderer.restoreToCount(saveCount + mCount);
309 }
310
Chris Craikd41c4d82015-01-05 15:51:13 -0800311 virtual void output(int level, uint32_t logFlags) const override {
Chris Craik2af46352012-11-26 18:30:17 -0800312 OP_LOG("Restore to count %d", mCount);
313 }
314
Chris Craikd41c4d82015-01-05 15:51:13 -0800315 virtual const char* name() override { return "RestoreToCount"; }
Chris Craik2af46352012-11-26 18:30:17 -0800316
317private:
318 int mCount;
319};
320
321class SaveLayerOp : public StateOp {
322public:
Derek Sollenbergerd44fbe52014-02-05 16:47:00 -0500323 SaveLayerOp(float left, float top, float right, float bottom, int alpha, int flags)
Chris Craik3f0854292014-04-15 16:18:08 -0700324 : mArea(left, top, right, bottom)
325 , mPaint(&mCachedPaint)
326 , mFlags(flags)
Chris Craikd41c4d82015-01-05 15:51:13 -0800327 , mConvexMask(nullptr) {
Derek Sollenbergerd44fbe52014-02-05 16:47:00 -0500328 mCachedPaint.setAlpha(alpha);
329 }
330
331 SaveLayerOp(float left, float top, float right, float bottom, const SkPaint* paint, int flags)
Chris Craik3f0854292014-04-15 16:18:08 -0700332 : mArea(left, top, right, bottom)
333 , mPaint(paint)
334 , mFlags(flags)
Chris Craikd41c4d82015-01-05 15:51:13 -0800335 , mConvexMask(nullptr)
Chris Craik3f0854292014-04-15 16:18:08 -0700336 {}
Chris Craikff785832013-03-08 13:12:16 -0800337
Andreas Gampe64bb4132014-11-22 00:35:09 +0000338 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
Chris Craikd41c4d82015-01-05 15:51:13 -0800339 bool useQuickReject) override {
Chris Craikff785832013-03-08 13:12:16 -0800340 // NOTE: don't bother with actual saveLayer, instead issuing it at flush time
Chris Craikd90144d2013-03-19 15:03:48 -0700341 int newSaveCount = deferStruct.mRenderer.getSaveCount();
Chris Craikff785832013-03-08 13:12:16 -0800342 deferStruct.mDeferredList.addSaveLayer(deferStruct.mRenderer, this, newSaveCount);
Chris Craikd90144d2013-03-19 15:03:48 -0700343
344 // NOTE: don't issue full saveLayer, since that has side effects/is costly. instead just
345 // setup the snapshot for deferral, and re-issue the op at flush time
346 deferStruct.mRenderer.saveLayerDeferred(mArea.left, mArea.top, mArea.right, mArea.bottom,
Derek Sollenbergerd44fbe52014-02-05 16:47:00 -0500347 mPaint, mFlags);
Chris Craikff785832013-03-08 13:12:16 -0800348 }
Chris Craik2af46352012-11-26 18:30:17 -0800349
Chris Craikd41c4d82015-01-05 15:51:13 -0800350 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const override {
Chris Craik3f0854292014-04-15 16:18:08 -0700351 renderer.saveLayer(mArea.left, mArea.top, mArea.right, mArea.bottom,
352 mPaint, mFlags, mConvexMask);
Chris Craik2af46352012-11-26 18:30:17 -0800353 }
354
Chris Craikd41c4d82015-01-05 15:51:13 -0800355 virtual void output(int level, uint32_t logFlags) const override {
Chris Craikff785832013-03-08 13:12:16 -0800356 OP_LOG("SaveLayer%s of area " RECT_STRING,
357 (isSaveLayerAlpha() ? "Alpha" : ""),RECT_ARGS(mArea));
Chris Craik2af46352012-11-26 18:30:17 -0800358 }
359
Chris Craikd41c4d82015-01-05 15:51:13 -0800360 virtual const char* name() override {
361 return isSaveLayerAlpha() ? "SaveLayerAlpha" : "SaveLayer";
362 }
Chris Craikff785832013-03-08 13:12:16 -0800363
364 int getFlags() { return mFlags; }
Chris Craik2af46352012-11-26 18:30:17 -0800365
Chris Craik3f0854292014-04-15 16:18:08 -0700366 // Called to make SaveLayerOp clip to the provided mask when drawing back/restored
367 void setMask(const SkPath* convexMask) {
368 mConvexMask = convexMask;
369 }
370
Chris Craik2af46352012-11-26 18:30:17 -0800371private:
Derek Sollenbergerd44fbe52014-02-05 16:47:00 -0500372 bool isSaveLayerAlpha() const {
Chris Craikbf6f0f22015-10-01 12:36:07 -0700373 SkXfermode::Mode mode = PaintUtils::getXfermodeDirect(mPaint);
374 int alpha = PaintUtils::getAlphaDirect(mPaint);
Derek Sollenbergerd44fbe52014-02-05 16:47:00 -0500375 return alpha < 255 && mode == SkXfermode::kSrcOver_Mode;
Chris Craik2af46352012-11-26 18:30:17 -0800376 }
377
Chris Craik2af46352012-11-26 18:30:17 -0800378 Rect mArea;
Derek Sollenbergerd44fbe52014-02-05 16:47:00 -0500379 const SkPaint* mPaint;
380 SkPaint mCachedPaint;
Chris Craik2af46352012-11-26 18:30:17 -0800381 int mFlags;
Chris Craik3f0854292014-04-15 16:18:08 -0700382
383 // Convex path, points at data in RenderNode, valid for the duration of the frame only
384 // Only used for masking the SaveLayer which wraps projected RenderNodes
385 const SkPath* mConvexMask;
Chris Craik2af46352012-11-26 18:30:17 -0800386};
387
388class TranslateOp : public StateOp {
389public:
390 TranslateOp(float dx, float dy)
391 : mDx(dx), mDy(dy) {}
392
Chris Craikd41c4d82015-01-05 15:51:13 -0800393 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const override {
Chris Craik2af46352012-11-26 18:30:17 -0800394 renderer.translate(mDx, mDy);
395 }
396
Chris Craikd41c4d82015-01-05 15:51:13 -0800397 virtual void output(int level, uint32_t logFlags) const override {
Chris Craik2af46352012-11-26 18:30:17 -0800398 OP_LOG("Translate by %f %f", mDx, mDy);
399 }
400
Chris Craikd41c4d82015-01-05 15:51:13 -0800401 virtual const char* name() override { return "Translate"; }
Chris Craik2af46352012-11-26 18:30:17 -0800402
403private:
404 float mDx;
405 float mDy;
406};
407
408class RotateOp : public StateOp {
409public:
410 RotateOp(float degrees)
411 : mDegrees(degrees) {}
412
Chris Craikd41c4d82015-01-05 15:51:13 -0800413 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const override {
Chris Craik2af46352012-11-26 18:30:17 -0800414 renderer.rotate(mDegrees);
415 }
416
Chris Craikd41c4d82015-01-05 15:51:13 -0800417 virtual void output(int level, uint32_t logFlags) const override {
Chris Craik2af46352012-11-26 18:30:17 -0800418 OP_LOG("Rotate by %f degrees", mDegrees);
419 }
420
Chris Craikd41c4d82015-01-05 15:51:13 -0800421 virtual const char* name() override { return "Rotate"; }
Chris Craik2af46352012-11-26 18:30:17 -0800422
423private:
424 float mDegrees;
425};
426
427class ScaleOp : public StateOp {
428public:
429 ScaleOp(float sx, float sy)
430 : mSx(sx), mSy(sy) {}
431
Chris Craikd41c4d82015-01-05 15:51:13 -0800432 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const override {
Chris Craik2af46352012-11-26 18:30:17 -0800433 renderer.scale(mSx, mSy);
434 }
435
Chris Craikd41c4d82015-01-05 15:51:13 -0800436 virtual void output(int level, uint32_t logFlags) const override {
Chris Craik2af46352012-11-26 18:30:17 -0800437 OP_LOG("Scale by %f %f", mSx, mSy);
438 }
439
Chris Craikd41c4d82015-01-05 15:51:13 -0800440 virtual const char* name() override { return "Scale"; }
Chris Craik2af46352012-11-26 18:30:17 -0800441
442private:
443 float mSx;
444 float mSy;
445};
446
447class SkewOp : public StateOp {
448public:
449 SkewOp(float sx, float sy)
450 : mSx(sx), mSy(sy) {}
451
Chris Craikd41c4d82015-01-05 15:51:13 -0800452 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const override {
Chris Craik2af46352012-11-26 18:30:17 -0800453 renderer.skew(mSx, mSy);
454 }
455
Chris Craikd41c4d82015-01-05 15:51:13 -0800456 virtual void output(int level, uint32_t logFlags) const override {
Chris Craik2af46352012-11-26 18:30:17 -0800457 OP_LOG("Skew by %f %f", mSx, mSy);
458 }
459
Chris Craikd41c4d82015-01-05 15:51:13 -0800460 virtual const char* name() override { return "Skew"; }
Chris Craik2af46352012-11-26 18:30:17 -0800461
462private:
463 float mSx;
464 float mSy;
465};
466
467class SetMatrixOp : public StateOp {
468public:
Derek Sollenberger13908822013-12-10 12:28:58 -0500469 SetMatrixOp(const SkMatrix& matrix)
Chris Craik2af46352012-11-26 18:30:17 -0800470 : mMatrix(matrix) {}
471
Chris Craikd41c4d82015-01-05 15:51:13 -0800472 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const override {
Chris Craik6daa13c2015-08-19 13:32:12 -0700473 // Setting a matrix on a Canvas isn't equivalent to setting a total matrix on the scene.
474 // Set a canvas-relative matrix on the renderer instead.
475 renderer.setLocalMatrix(mMatrix);
Chris Craik2af46352012-11-26 18:30:17 -0800476 }
477
Chris Craikd41c4d82015-01-05 15:51:13 -0800478 virtual void output(int level, uint32_t logFlags) const override {
Derek Sollenberger13908822013-12-10 12:28:58 -0500479 if (mMatrix.isIdentity()) {
Romain Guy4e7b7722013-07-16 13:47:01 -0700480 OP_LOGS("SetMatrix (reset)");
Derek Sollenberger13908822013-12-10 12:28:58 -0500481 } else {
482 OP_LOG("SetMatrix " SK_MATRIX_STRING, SK_MATRIX_ARGS(&mMatrix));
Romain Guy4e7b7722013-07-16 13:47:01 -0700483 }
Chris Craik2af46352012-11-26 18:30:17 -0800484 }
485
Chris Craikd41c4d82015-01-05 15:51:13 -0800486 virtual const char* name() override { return "SetMatrix"; }
Chris Craik2af46352012-11-26 18:30:17 -0800487
488private:
Derek Sollenberger13908822013-12-10 12:28:58 -0500489 const SkMatrix mMatrix;
Chris Craik2af46352012-11-26 18:30:17 -0800490};
491
492class ConcatMatrixOp : public StateOp {
493public:
Derek Sollenberger13908822013-12-10 12:28:58 -0500494 ConcatMatrixOp(const SkMatrix& matrix)
Chris Craik2af46352012-11-26 18:30:17 -0800495 : mMatrix(matrix) {}
496
Chris Craikd41c4d82015-01-05 15:51:13 -0800497 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const override {
Chris Craik2af46352012-11-26 18:30:17 -0800498 renderer.concatMatrix(mMatrix);
499 }
500
Chris Craikd41c4d82015-01-05 15:51:13 -0800501 virtual void output(int level, uint32_t logFlags) const override {
Derek Sollenberger13908822013-12-10 12:28:58 -0500502 OP_LOG("ConcatMatrix " SK_MATRIX_STRING, SK_MATRIX_ARGS(&mMatrix));
Chris Craik2af46352012-11-26 18:30:17 -0800503 }
504
Chris Craikd41c4d82015-01-05 15:51:13 -0800505 virtual const char* name() override { return "ConcatMatrix"; }
Chris Craik2af46352012-11-26 18:30:17 -0800506
507private:
Derek Sollenberger13908822013-12-10 12:28:58 -0500508 const SkMatrix mMatrix;
Chris Craik2af46352012-11-26 18:30:17 -0800509};
510
Chris Craikff785832013-03-08 13:12:16 -0800511class ClipOp : public StateOp {
512public:
513 ClipOp(SkRegion::Op op) : mOp(op) {}
514
Andreas Gampe64bb4132014-11-22 00:35:09 +0000515 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
Chris Craikd41c4d82015-01-05 15:51:13 -0800516 bool useQuickReject) override {
Chris Craikff785832013-03-08 13:12:16 -0800517 // NOTE: must defer op BEFORE applying state, since it may read clip
518 deferStruct.mDeferredList.addClip(deferStruct.mRenderer, this);
519
520 // TODO: Can we avoid applying complex clips at defer time?
521 applyState(deferStruct.mRenderer, saveCount);
522 }
523
524 bool canCauseComplexClip() {
525 return ((mOp != SkRegion::kIntersect_Op) && (mOp != SkRegion::kReplace_Op)) || !isRect();
526 }
527
528protected:
Chris Craikff785832013-03-08 13:12:16 -0800529 virtual bool isRect() { return false; }
530
531 SkRegion::Op mOp;
532};
533
534class ClipRectOp : public ClipOp {
Chris Craik2af46352012-11-26 18:30:17 -0800535public:
536 ClipRectOp(float left, float top, float right, float bottom, SkRegion::Op op)
Chris Craikff785832013-03-08 13:12:16 -0800537 : ClipOp(op), mArea(left, top, right, bottom) {}
Chris Craik2af46352012-11-26 18:30:17 -0800538
Chris Craikd41c4d82015-01-05 15:51:13 -0800539 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const override {
Chris Craik2af46352012-11-26 18:30:17 -0800540 renderer.clipRect(mArea.left, mArea.top, mArea.right, mArea.bottom, mOp);
541 }
542
Chris Craikd41c4d82015-01-05 15:51:13 -0800543 virtual void output(int level, uint32_t logFlags) const override {
Chris Craik2af46352012-11-26 18:30:17 -0800544 OP_LOG("ClipRect " RECT_STRING, RECT_ARGS(mArea));
545 }
546
Chris Craikd41c4d82015-01-05 15:51:13 -0800547 virtual const char* name() override { return "ClipRect"; }
Chris Craik2af46352012-11-26 18:30:17 -0800548
Chris Craikff785832013-03-08 13:12:16 -0800549protected:
Chris Craikd41c4d82015-01-05 15:51:13 -0800550 virtual bool isRect() override { return true; }
Chris Craikb98a0162013-02-21 11:30:22 -0800551
Chris Craik2af46352012-11-26 18:30:17 -0800552private:
553 Rect mArea;
Chris Craik2af46352012-11-26 18:30:17 -0800554};
555
Chris Craikff785832013-03-08 13:12:16 -0800556class ClipPathOp : public ClipOp {
Chris Craik2af46352012-11-26 18:30:17 -0800557public:
Chris Craikd218a922014-01-02 17:13:34 -0800558 ClipPathOp(const SkPath* path, SkRegion::Op op)
Chris Craikff785832013-03-08 13:12:16 -0800559 : ClipOp(op), mPath(path) {}
Chris Craik2af46352012-11-26 18:30:17 -0800560
Chris Craikd41c4d82015-01-05 15:51:13 -0800561 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const override {
Chris Craik2af46352012-11-26 18:30:17 -0800562 renderer.clipPath(mPath, mOp);
563 }
564
Chris Craikd41c4d82015-01-05 15:51:13 -0800565 virtual void output(int level, uint32_t logFlags) const override {
Chris Craik2af46352012-11-26 18:30:17 -0800566 SkRect bounds = mPath->getBounds();
567 OP_LOG("ClipPath bounds " RECT_STRING,
568 bounds.left(), bounds.top(), bounds.right(), bounds.bottom());
569 }
570
Chris Craikd41c4d82015-01-05 15:51:13 -0800571 virtual const char* name() override { return "ClipPath"; }
Chris Craik2af46352012-11-26 18:30:17 -0800572
573private:
Chris Craikd218a922014-01-02 17:13:34 -0800574 const SkPath* mPath;
Chris Craik2af46352012-11-26 18:30:17 -0800575};
576
Chris Craikff785832013-03-08 13:12:16 -0800577class ClipRegionOp : public ClipOp {
Chris Craik2af46352012-11-26 18:30:17 -0800578public:
Chris Craikd218a922014-01-02 17:13:34 -0800579 ClipRegionOp(const SkRegion* region, SkRegion::Op op)
Chris Craikff785832013-03-08 13:12:16 -0800580 : ClipOp(op), mRegion(region) {}
Chris Craik2af46352012-11-26 18:30:17 -0800581
Chris Craikd41c4d82015-01-05 15:51:13 -0800582 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const override {
Chris Craik2af46352012-11-26 18:30:17 -0800583 renderer.clipRegion(mRegion, mOp);
584 }
585
Chris Craikd41c4d82015-01-05 15:51:13 -0800586 virtual void output(int level, uint32_t logFlags) const override {
Chris Craik2af46352012-11-26 18:30:17 -0800587 SkIRect bounds = mRegion->getBounds();
588 OP_LOG("ClipRegion bounds %d %d %d %d",
589 bounds.left(), bounds.top(), bounds.right(), bounds.bottom());
590 }
591
Chris Craikd41c4d82015-01-05 15:51:13 -0800592 virtual const char* name() override { return "ClipRegion"; }
Chris Craik2af46352012-11-26 18:30:17 -0800593
594private:
Chris Craikd218a922014-01-02 17:13:34 -0800595 const SkRegion* mRegion;
Chris Craik2af46352012-11-26 18:30:17 -0800596};
597
Chris Craik2af46352012-11-26 18:30:17 -0800598///////////////////////////////////////////////////////////////////////////////
599// DRAW OPERATIONS - these are operations that can draw to the canvas's device
600///////////////////////////////////////////////////////////////////////////////
601
602class DrawBitmapOp : public DrawBoundedOp {
603public:
Chris Craik79647502014-08-06 13:42:24 -0700604 DrawBitmapOp(const SkBitmap* bitmap, const SkPaint* paint)
605 : DrawBoundedOp(0, 0, bitmap->width(), bitmap->height(), paint)
606 , mBitmap(bitmap)
Chris Craikd41c4d82015-01-05 15:51:13 -0800607 , mEntryValid(false), mEntry(nullptr) {
Romain Guy3b748a42013-04-17 18:54:38 -0700608 }
Chris Craik2af46352012-11-26 18:30:17 -0800609
Chris Craikd41c4d82015-01-05 15:51:13 -0800610 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
Tom Hudson107843d2014-09-08 11:26:26 -0400611 renderer.drawBitmap(mBitmap, mPaint);
Chris Craik2af46352012-11-26 18:30:17 -0800612 }
613
John Reckebd52612014-12-10 16:47:36 -0800614 AssetAtlas::Entry* getAtlasEntry(OpenGLRenderer& renderer) {
615 if (!mEntryValid) {
616 mEntryValid = true;
Chris Craik15c3f192015-12-03 12:16:56 -0800617 mEntry = renderer.renderState().assetAtlas().getEntry(mBitmap->pixelRef());
Romain Guy55b6f952013-06-27 15:27:09 -0700618 }
619 return mEntry;
620 }
621
Chris Craik527a3aa2013-03-04 10:19:31 -0800622#define SET_TEXTURE(ptr, posRect, offsetRect, texCoordsRect, xDim, yDim) \
623 TextureVertex::set(ptr++, posRect.xDim - offsetRect.left, posRect.yDim - offsetRect.top, \
624 texCoordsRect.xDim, texCoordsRect.yDim)
625
Romain Guy03c00b52013-06-20 18:30:28 -0700626 /**
627 * This multi-draw operation builds a mesh on the stack by generating a quad
628 * for each bitmap in the batch. This method is also responsible for dirtying
629 * the current layer, if any.
630 */
Andreas Gampe64bb4132014-11-22 00:35:09 +0000631 virtual void multiDraw(OpenGLRenderer& renderer, Rect& dirty,
John Reck272a6852015-07-29 16:48:58 -0700632 const std::vector<OpStatePair>& ops, const Rect& bounds) override {
Chris Craikc1c5f082013-09-11 16:23:37 -0700633 const DeferredDisplayState& firstState = *(ops[0].state);
634 renderer.restoreDisplayState(firstState, true); // restore all but the clip
635
Chris Craik527a3aa2013-03-04 10:19:31 -0800636 TextureVertex vertices[6 * ops.size()];
637 TextureVertex* vertex = &vertices[0];
638
Romain Guy03c00b52013-06-20 18:30:28 -0700639 const bool hasLayer = renderer.hasLayer();
Chris Craik996fe652013-09-20 17:13:18 -0700640 bool pureTranslate = true;
Romain Guy2db5e992013-05-21 15:29:59 -0700641
Romain Guy3b748a42013-04-17 18:54:38 -0700642 // TODO: manually handle rect clip for bitmaps by adjusting texCoords per op,
643 // and allowing them to be merged in getBatchId()
Chris Craik527a3aa2013-03-04 10:19:31 -0800644 for (unsigned int i = 0; i < ops.size(); i++) {
Chris Craikc1c5f082013-09-11 16:23:37 -0700645 const DeferredDisplayState& state = *(ops[i].state);
646 const Rect& opBounds = state.mBounds;
Romain Guy2db5e992013-05-21 15:29:59 -0700647 // When we reach multiDraw(), the matrix can be either
648 // pureTranslate or simple (translate and/or scale).
649 // If the matrix is not pureTranslate, then we have a scale
Chris Craik996fe652013-09-20 17:13:18 -0700650 pureTranslate &= state.mMatrix.isPureTranslate();
Romain Guy3b748a42013-04-17 18:54:38 -0700651
652 Rect texCoords(0, 0, 1, 1);
John Reckebd52612014-12-10 16:47:36 -0800653 ((DrawBitmapOp*) ops[i].op)->uvMap(renderer, texCoords);
Romain Guy3b748a42013-04-17 18:54:38 -0700654
Chris Craik527a3aa2013-03-04 10:19:31 -0800655 SET_TEXTURE(vertex, opBounds, bounds, texCoords, left, top);
656 SET_TEXTURE(vertex, opBounds, bounds, texCoords, right, top);
657 SET_TEXTURE(vertex, opBounds, bounds, texCoords, left, bottom);
658
659 SET_TEXTURE(vertex, opBounds, bounds, texCoords, left, bottom);
660 SET_TEXTURE(vertex, opBounds, bounds, texCoords, right, top);
661 SET_TEXTURE(vertex, opBounds, bounds, texCoords, right, bottom);
Romain Guy03c00b52013-06-20 18:30:28 -0700662
663 if (hasLayer) {
Chris Craikc1c5f082013-09-11 16:23:37 -0700664 renderer.dirtyLayer(opBounds.left, opBounds.top, opBounds.right, opBounds.bottom);
Romain Guy03c00b52013-06-20 18:30:28 -0700665 }
Chris Craik527a3aa2013-03-04 10:19:31 -0800666 }
667
Tom Hudson107843d2014-09-08 11:26:26 -0400668 renderer.drawBitmaps(mBitmap, mEntry, ops.size(), &vertices[0],
Chris Craik996fe652013-09-20 17:13:18 -0700669 pureTranslate, bounds, mPaint);
Chris Craik527a3aa2013-03-04 10:19:31 -0800670 }
671
Chris Craikd41c4d82015-01-05 15:51:13 -0800672 virtual void output(int level, uint32_t logFlags) const override {
Chris Craik0519c812015-02-11 13:17:06 -0800673 OP_LOG("Draw bitmap %p of size %dx%d%s",
674 mBitmap, mBitmap->width(), mBitmap->height(),
John Reckdad7d84c2014-12-09 12:33:26 -0800675 mEntry ? " using AssetAtlas" : "");
Chris Craik2af46352012-11-26 18:30:17 -0800676 }
677
Chris Craikd41c4d82015-01-05 15:51:13 -0800678 virtual const char* name() override { return "DrawBitmap"; }
Chris Craik527a3aa2013-03-04 10:19:31 -0800679
Andreas Gampe64bb4132014-11-22 00:35:09 +0000680 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
Chris Craikd41c4d82015-01-05 15:51:13 -0800681 const DeferredDisplayState& state) override {
Chris Craik28ce94a2013-05-31 11:38:03 -0700682 deferInfo.batchId = DeferredDisplayList::kOpBatch_Bitmap;
John Reckebd52612014-12-10 16:47:36 -0800683 deferInfo.mergeId = getAtlasEntry(renderer) ?
Chris Craikd965bc52013-09-16 14:47:13 -0700684 (mergeid_t) mEntry->getMergeId() : (mergeid_t) mBitmap;
Romain Guy2db5e992013-05-21 15:29:59 -0700685
Chris Craikd965bc52013-09-16 14:47:13 -0700686 // Don't merge non-simply transformed or neg scale ops, SET_TEXTURE doesn't handle rotation
Chris Craik28ce94a2013-05-31 11:38:03 -0700687 // Don't merge A8 bitmaps - the paint's color isn't compared by mergeId, or in
688 // MergingDrawBatch::canMergeWith()
689 // TODO: support clipped bitmaps by handling them in SET_TEXTURE
Chris Craikd965bc52013-09-16 14:47:13 -0700690 deferInfo.mergeable = state.mMatrix.isSimple() && state.mMatrix.positiveScale() &&
691 !state.mClipSideFlags &&
Chris Craikbf6f0f22015-10-01 12:36:07 -0700692 PaintUtils::getXfermodeDirect(mPaint) == SkXfermode::kSrcOver_Mode &&
Mike Reed1103b322014-07-08 12:36:44 -0400693 (mBitmap->colorType() != kAlpha_8_SkColorType);
Chris Craikc3566d02013-02-04 16:16:33 -0800694 }
Chris Craik2af46352012-11-26 18:30:17 -0800695
John Reckebd52612014-12-10 16:47:36 -0800696 void uvMap(OpenGLRenderer& renderer, Rect& texCoords) {
697 if (getAtlasEntry(renderer)) {
698 mEntry->uvMapper.map(texCoords);
699 }
700 }
701
Chris Craik527a3aa2013-03-04 10:19:31 -0800702 const SkBitmap* bitmap() { return mBitmap; }
Chris Craik2af46352012-11-26 18:30:17 -0800703protected:
Chris Craikd218a922014-01-02 17:13:34 -0800704 const SkBitmap* mBitmap;
John Reckebd52612014-12-10 16:47:36 -0800705 bool mEntryValid;
Romain Guy55b6f952013-06-27 15:27:09 -0700706 AssetAtlas::Entry* mEntry;
Chris Craik2af46352012-11-26 18:30:17 -0800707};
708
Chris Craik2af46352012-11-26 18:30:17 -0800709class DrawBitmapRectOp : public DrawBoundedOp {
710public:
Chris Craikd218a922014-01-02 17:13:34 -0800711 DrawBitmapRectOp(const SkBitmap* bitmap,
712 float srcLeft, float srcTop, float srcRight, float srcBottom,
713 float dstLeft, float dstTop, float dstRight, float dstBottom, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -0800714 : DrawBoundedOp(dstLeft, dstTop, dstRight, dstBottom, paint),
715 mBitmap(bitmap), mSrc(srcLeft, srcTop, srcRight, srcBottom) {}
716
Chris Craikd41c4d82015-01-05 15:51:13 -0800717 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
Chris Craik14100ac2015-02-24 13:46:29 -0800718 renderer.drawBitmap(mBitmap, mSrc, mLocalBounds, mPaint);
Chris Craik2af46352012-11-26 18:30:17 -0800719 }
720
Chris Craikd41c4d82015-01-05 15:51:13 -0800721 virtual void output(int level, uint32_t logFlags) const override {
John Reckce444ca2014-06-02 15:12:36 -0700722 OP_LOG("Draw bitmap %p src=" RECT_STRING ", dst=" RECT_STRING,
Chris Craik2af46352012-11-26 18:30:17 -0800723 mBitmap, RECT_ARGS(mSrc), RECT_ARGS(mLocalBounds));
724 }
725
Chris Craikd41c4d82015-01-05 15:51:13 -0800726 virtual const char* name() override { return "DrawBitmapRect"; }
Chris Craik527a3aa2013-03-04 10:19:31 -0800727
Andreas Gampe64bb4132014-11-22 00:35:09 +0000728 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
Chris Craikd41c4d82015-01-05 15:51:13 -0800729 const DeferredDisplayState& state) override {
Chris Craik28ce94a2013-05-31 11:38:03 -0700730 deferInfo.batchId = DeferredDisplayList::kOpBatch_Bitmap;
Chris Craikc3566d02013-02-04 16:16:33 -0800731 }
Chris Craik2af46352012-11-26 18:30:17 -0800732
733private:
Chris Craikd218a922014-01-02 17:13:34 -0800734 const SkBitmap* mBitmap;
Chris Craik2af46352012-11-26 18:30:17 -0800735 Rect mSrc;
736};
737
Chris Craik5d116762013-02-19 17:49:31 -0800738class DrawBitmapMeshOp : public DrawBoundedOp {
Chris Craik2af46352012-11-26 18:30:17 -0800739public:
Chris Craikd218a922014-01-02 17:13:34 -0800740 DrawBitmapMeshOp(const SkBitmap* bitmap, int meshWidth, int meshHeight,
741 const float* vertices, const int* colors, const SkPaint* paint)
Chris Craik5d116762013-02-19 17:49:31 -0800742 : DrawBoundedOp(vertices, 2 * (meshWidth + 1) * (meshHeight + 1), paint),
743 mBitmap(bitmap), mMeshWidth(meshWidth), mMeshHeight(meshHeight),
Chris Craik2af46352012-11-26 18:30:17 -0800744 mVertices(vertices), mColors(colors) {}
745
Chris Craikd41c4d82015-01-05 15:51:13 -0800746 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
Tom Hudson107843d2014-09-08 11:26:26 -0400747 renderer.drawBitmapMesh(mBitmap, mMeshWidth, mMeshHeight,
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -0400748 mVertices, mColors, mPaint);
Chris Craik2af46352012-11-26 18:30:17 -0800749 }
750
Chris Craikd41c4d82015-01-05 15:51:13 -0800751 virtual void output(int level, uint32_t logFlags) const override {
Chris Craik2af46352012-11-26 18:30:17 -0800752 OP_LOG("Draw bitmap %p mesh %d x %d", mBitmap, mMeshWidth, mMeshHeight);
753 }
754
Chris Craikd41c4d82015-01-05 15:51:13 -0800755 virtual const char* name() override { return "DrawBitmapMesh"; }
Chris Craik527a3aa2013-03-04 10:19:31 -0800756
Andreas Gampe64bb4132014-11-22 00:35:09 +0000757 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
Chris Craikd41c4d82015-01-05 15:51:13 -0800758 const DeferredDisplayState& state) override {
Chris Craik28ce94a2013-05-31 11:38:03 -0700759 deferInfo.batchId = DeferredDisplayList::kOpBatch_Bitmap;
Chris Craikc3566d02013-02-04 16:16:33 -0800760 }
Chris Craik2af46352012-11-26 18:30:17 -0800761
762private:
Chris Craikd218a922014-01-02 17:13:34 -0800763 const SkBitmap* mBitmap;
Chris Craik2af46352012-11-26 18:30:17 -0800764 int mMeshWidth;
765 int mMeshHeight;
Chris Craikd218a922014-01-02 17:13:34 -0800766 const float* mVertices;
767 const int* mColors;
Chris Craik2af46352012-11-26 18:30:17 -0800768};
769
770class DrawPatchOp : public DrawBoundedOp {
771public:
Chris Craikd218a922014-01-02 17:13:34 -0800772 DrawPatchOp(const SkBitmap* bitmap, const Res_png_9patch* patch,
773 float left, float top, float right, float bottom, const SkPaint* paint)
Romain Guy03c00b52013-06-20 18:30:28 -0700774 : DrawBoundedOp(left, top, right, bottom, paint),
Chris Craikd41c4d82015-01-05 15:51:13 -0800775 mBitmap(bitmap), mPatch(patch), mGenerationId(0), mMesh(nullptr),
776 mEntryValid(false), mEntry(nullptr) {
Romain Guy3b748a42013-04-17 18:54:38 -0700777 };
Chris Craik2af46352012-11-26 18:30:17 -0800778
John Reckebd52612014-12-10 16:47:36 -0800779 AssetAtlas::Entry* getAtlasEntry(OpenGLRenderer& renderer) {
780 if (!mEntryValid) {
781 mEntryValid = true;
Chris Craik15c3f192015-12-03 12:16:56 -0800782 mEntry = renderer.renderState().assetAtlas().getEntry(mBitmap->pixelRef());
Romain Guy55b6f952013-06-27 15:27:09 -0700783 }
784 return mEntry;
785 }
786
Romain Guy03c00b52013-06-20 18:30:28 -0700787 const Patch* getMesh(OpenGLRenderer& renderer) {
Romain Guy4c2547f2013-06-11 16:19:24 -0700788 if (!mMesh || renderer.getCaches().patchCache.getGenerationId() != mGenerationId) {
789 PatchCache& cache = renderer.getCaches().patchCache;
John Reckebd52612014-12-10 16:47:36 -0800790 mMesh = cache.get(getAtlasEntry(renderer), mBitmap->width(), mBitmap->height(),
Romain Guy03c00b52013-06-20 18:30:28 -0700791 mLocalBounds.getWidth(), mLocalBounds.getHeight(), mPatch);
Romain Guy4c2547f2013-06-11 16:19:24 -0700792 mGenerationId = cache.getGenerationId();
793 }
Romain Guy03c00b52013-06-20 18:30:28 -0700794 return mMesh;
795 }
796
797 /**
798 * This multi-draw operation builds an indexed mesh on the stack by copying
799 * and transforming the vertices of each 9-patch in the batch. This method
800 * is also responsible for dirtying the current layer, if any.
801 */
Andreas Gampe64bb4132014-11-22 00:35:09 +0000802 virtual void multiDraw(OpenGLRenderer& renderer, Rect& dirty,
John Reck272a6852015-07-29 16:48:58 -0700803 const std::vector<OpStatePair>& ops, const Rect& bounds) override {
Chris Craikc1c5f082013-09-11 16:23:37 -0700804 const DeferredDisplayState& firstState = *(ops[0].state);
805 renderer.restoreDisplayState(firstState, true); // restore all but the clip
Romain Guy03c00b52013-06-20 18:30:28 -0700806
807 // Batches will usually contain a small number of items so it's
808 // worth performing a first iteration to count the exact number
809 // of vertices we need in the new mesh
810 uint32_t totalVertices = 0;
811 for (unsigned int i = 0; i < ops.size(); i++) {
Chris Craikc1c5f082013-09-11 16:23:37 -0700812 totalVertices += ((DrawPatchOp*) ops[i].op)->getMesh(renderer)->verticesCount;
Romain Guy03c00b52013-06-20 18:30:28 -0700813 }
814
815 const bool hasLayer = renderer.hasLayer();
816
817 uint32_t indexCount = 0;
818
819 TextureVertex vertices[totalVertices];
820 TextureVertex* vertex = &vertices[0];
821
822 // Create a mesh that contains the transformed vertices for all the
823 // 9-patch objects that are part of the batch. Note that onDefer()
824 // enforces ops drawn by this function to have a pure translate or
825 // identity matrix
826 for (unsigned int i = 0; i < ops.size(); i++) {
Chris Craikc1c5f082013-09-11 16:23:37 -0700827 DrawPatchOp* patchOp = (DrawPatchOp*) ops[i].op;
828 const DeferredDisplayState* state = ops[i].state;
Romain Guy03c00b52013-06-20 18:30:28 -0700829 const Patch* opMesh = patchOp->getMesh(renderer);
830 uint32_t vertexCount = opMesh->verticesCount;
831 if (vertexCount == 0) continue;
832
833 // We use the bounds to know where to translate our vertices
834 // Using patchOp->state.mBounds wouldn't work because these
835 // bounds are clipped
Chris Craikc1c5f082013-09-11 16:23:37 -0700836 const float tx = (int) floorf(state->mMatrix.getTranslateX() +
Romain Guy03c00b52013-06-20 18:30:28 -0700837 patchOp->mLocalBounds.left + 0.5f);
Chris Craikc1c5f082013-09-11 16:23:37 -0700838 const float ty = (int) floorf(state->mMatrix.getTranslateY() +
Romain Guy03c00b52013-06-20 18:30:28 -0700839 patchOp->mLocalBounds.top + 0.5f);
840
841 // Copy & transform all the vertices for the current operation
Chris Craik51d6a3d2014-12-22 17:16:56 -0800842 TextureVertex* opVertices = opMesh->vertices.get();
Romain Guy03c00b52013-06-20 18:30:28 -0700843 for (uint32_t j = 0; j < vertexCount; j++, opVertices++) {
844 TextureVertex::set(vertex++,
Romain Guy3380cfd2013-08-15 16:57:57 -0700845 opVertices->x + tx, opVertices->y + ty,
846 opVertices->u, opVertices->v);
Romain Guy03c00b52013-06-20 18:30:28 -0700847 }
848
849 // Dirty the current layer if possible. When the 9-patch does not
850 // contain empty quads we can take a shortcut and simply set the
851 // dirty rect to the object's bounds.
852 if (hasLayer) {
853 if (!opMesh->hasEmptyQuads) {
854 renderer.dirtyLayer(tx, ty,
855 tx + patchOp->mLocalBounds.getWidth(),
856 ty + patchOp->mLocalBounds.getHeight());
857 } else {
858 const size_t count = opMesh->quads.size();
859 for (size_t i = 0; i < count; i++) {
860 const Rect& quadBounds = opMesh->quads[i];
861 const float x = tx + quadBounds.left;
862 const float y = ty + quadBounds.top;
863 renderer.dirtyLayer(x, y,
864 x + quadBounds.getWidth(), y + quadBounds.getHeight());
865 }
866 }
867 }
868
869 indexCount += opMesh->indexCount;
870 }
871
Yohann Roussel59cf7342014-12-11 11:10:50 +0100872 renderer.drawPatches(mBitmap, getAtlasEntry(renderer),
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -0400873 &vertices[0], indexCount, mPaint);
Romain Guy03c00b52013-06-20 18:30:28 -0700874 }
875
Chris Craikd41c4d82015-01-05 15:51:13 -0800876 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
Romain Guy4c2547f2013-06-11 16:19:24 -0700877 // We're not calling the public variant of drawPatch() here
878 // This method won't perform the quickReject() since we've already done it at this point
Yohann Roussel59cf7342014-12-11 11:10:50 +0100879 renderer.drawPatch(mBitmap, getMesh(renderer), getAtlasEntry(renderer),
Romain Guy03c00b52013-06-20 18:30:28 -0700880 mLocalBounds.left, mLocalBounds.top, mLocalBounds.right, mLocalBounds.bottom,
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -0400881 mPaint);
Chris Craik2af46352012-11-26 18:30:17 -0800882 }
883
Chris Craikd41c4d82015-01-05 15:51:13 -0800884 virtual void output(int level, uint32_t logFlags) const override {
John Reckdad7d84c2014-12-09 12:33:26 -0800885 OP_LOG("Draw patch " RECT_STRING "%s", RECT_ARGS(mLocalBounds),
886 mEntry ? " with AssetAtlas" : "");
Chris Craik2af46352012-11-26 18:30:17 -0800887 }
888
Chris Craikd41c4d82015-01-05 15:51:13 -0800889 virtual const char* name() override { return "DrawPatch"; }
Chris Craik527a3aa2013-03-04 10:19:31 -0800890
Andreas Gampe64bb4132014-11-22 00:35:09 +0000891 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
Chris Craikd41c4d82015-01-05 15:51:13 -0800892 const DeferredDisplayState& state) override {
Chris Craik28ce94a2013-05-31 11:38:03 -0700893 deferInfo.batchId = DeferredDisplayList::kOpBatch_Patch;
John Reckebd52612014-12-10 16:47:36 -0800894 deferInfo.mergeId = getAtlasEntry(renderer) ? (mergeid_t) mEntry->getMergeId() : (mergeid_t) mBitmap;
Romain Guy03c00b52013-06-20 18:30:28 -0700895 deferInfo.mergeable = state.mMatrix.isPureTranslate() &&
Chris Craikbf6f0f22015-10-01 12:36:07 -0700896 PaintUtils::getXfermodeDirect(mPaint) == SkXfermode::kSrcOver_Mode;
Chris Craikc1c5f082013-09-11 16:23:37 -0700897 deferInfo.opaqueOverBounds = isOpaqueOverBounds(state) && mBitmap->isOpaque();
Chris Craikc3566d02013-02-04 16:16:33 -0800898 }
Chris Craik2af46352012-11-26 18:30:17 -0800899
900private:
Chris Craikd218a922014-01-02 17:13:34 -0800901 const SkBitmap* mBitmap;
902 const Res_png_9patch* mPatch;
Romain Guy4c2547f2013-06-11 16:19:24 -0700903
Romain Guy4c2547f2013-06-11 16:19:24 -0700904 uint32_t mGenerationId;
905 const Patch* mMesh;
Romain Guy03c00b52013-06-20 18:30:28 -0700906
John Reckebd52612014-12-10 16:47:36 -0800907 bool mEntryValid;
Romain Guy3b748a42013-04-17 18:54:38 -0700908 AssetAtlas::Entry* mEntry;
Chris Craik2af46352012-11-26 18:30:17 -0800909};
910
911class DrawColorOp : public DrawOp {
912public:
913 DrawColorOp(int color, SkXfermode::Mode mode)
Chris Craikd41c4d82015-01-05 15:51:13 -0800914 : DrawOp(nullptr), mColor(color), mMode(mode) {};
Chris Craik2af46352012-11-26 18:30:17 -0800915
Chris Craikd41c4d82015-01-05 15:51:13 -0800916 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
Tom Hudson107843d2014-09-08 11:26:26 -0400917 renderer.drawColor(mColor, mMode);
Chris Craik2af46352012-11-26 18:30:17 -0800918 }
919
Chris Craikd41c4d82015-01-05 15:51:13 -0800920 virtual void output(int level, uint32_t logFlags) const override {
Chris Craik2af46352012-11-26 18:30:17 -0800921 OP_LOG("Draw color %#x, mode %d", mColor, mMode);
922 }
923
Chris Craikd41c4d82015-01-05 15:51:13 -0800924 virtual const char* name() override { return "DrawColor"; }
Chris Craik2af46352012-11-26 18:30:17 -0800925
926private:
927 int mColor;
928 SkXfermode::Mode mMode;
929};
930
931class DrawStrokableOp : public DrawBoundedOp {
932public:
Chris Craikd218a922014-01-02 17:13:34 -0800933 DrawStrokableOp(float left, float top, float right, float bottom, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -0800934 : DrawBoundedOp(left, top, right, bottom, paint) {};
Chris Craik947eabf2014-08-19 10:21:12 -0700935 DrawStrokableOp(const Rect& localBounds, const SkPaint* paint)
936 : DrawBoundedOp(localBounds, paint) {};
Chris Craik2af46352012-11-26 18:30:17 -0800937
Chris Craikd41c4d82015-01-05 15:51:13 -0800938 virtual bool getLocalBounds(Rect& localBounds) override {
Chris Craikc3566d02013-02-04 16:16:33 -0800939 localBounds.set(mLocalBounds);
Chris Craik2af46352012-11-26 18:30:17 -0800940 if (mPaint && mPaint->getStyle() != SkPaint::kFill_Style) {
Chris Craikc3566d02013-02-04 16:16:33 -0800941 localBounds.outset(strokeWidthOutset());
Chris Craik2af46352012-11-26 18:30:17 -0800942 }
943 return true;
944 }
Chris Craikc3566d02013-02-04 16:16:33 -0800945
Andreas Gampe64bb4132014-11-22 00:35:09 +0000946 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
Chris Craikd41c4d82015-01-05 15:51:13 -0800947 const DeferredDisplayState& state) override {
Chris Craikc3566d02013-02-04 16:16:33 -0800948 if (mPaint->getPathEffect()) {
Chris Craik28ce94a2013-05-31 11:38:03 -0700949 deferInfo.batchId = DeferredDisplayList::kOpBatch_AlphaMaskTexture;
Chris Craik527a3aa2013-03-04 10:19:31 -0800950 } else {
Chris Craik28ce94a2013-05-31 11:38:03 -0700951 deferInfo.batchId = mPaint->isAntiAlias() ?
Chris Craik527a3aa2013-03-04 10:19:31 -0800952 DeferredDisplayList::kOpBatch_AlphaVertices :
953 DeferredDisplayList::kOpBatch_Vertices;
Chris Craikc3566d02013-02-04 16:16:33 -0800954 }
Chris Craikc3566d02013-02-04 16:16:33 -0800955 }
Chris Craik2af46352012-11-26 18:30:17 -0800956};
957
958class DrawRectOp : public DrawStrokableOp {
959public:
Chris Craikd218a922014-01-02 17:13:34 -0800960 DrawRectOp(float left, float top, float right, float bottom, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -0800961 : DrawStrokableOp(left, top, right, bottom, paint) {}
962
Chris Craikd41c4d82015-01-05 15:51:13 -0800963 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
Tom Hudson107843d2014-09-08 11:26:26 -0400964 renderer.drawRect(mLocalBounds.left, mLocalBounds.top,
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -0400965 mLocalBounds.right, mLocalBounds.bottom, mPaint);
Chris Craik2af46352012-11-26 18:30:17 -0800966 }
967
Chris Craikd41c4d82015-01-05 15:51:13 -0800968 virtual void output(int level, uint32_t logFlags) const override {
John Reckce444ca2014-06-02 15:12:36 -0700969 OP_LOG("Draw Rect " RECT_STRING, RECT_ARGS(mLocalBounds));
Chris Craik2af46352012-11-26 18:30:17 -0800970 }
971
Chris Craikc1c5f082013-09-11 16:23:37 -0700972 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
Chris Craikd41c4d82015-01-05 15:51:13 -0800973 const DeferredDisplayState& state) override {
Chris Craikc1c5f082013-09-11 16:23:37 -0700974 DrawStrokableOp::onDefer(renderer, deferInfo, state);
975 deferInfo.opaqueOverBounds = isOpaqueOverBounds(state) &&
Chris Craik28ce94a2013-05-31 11:38:03 -0700976 mPaint->getStyle() == SkPaint::kFill_Style;
977 }
978
Chris Craikd41c4d82015-01-05 15:51:13 -0800979 virtual const char* name() override { return "DrawRect"; }
Chris Craik2af46352012-11-26 18:30:17 -0800980};
981
Chris Craik5d116762013-02-19 17:49:31 -0800982class DrawRectsOp : public DrawBoundedOp {
Chris Craik2af46352012-11-26 18:30:17 -0800983public:
Chris Craikd218a922014-01-02 17:13:34 -0800984 DrawRectsOp(const float* rects, int count, const SkPaint* paint)
Chris Craik5d116762013-02-19 17:49:31 -0800985 : DrawBoundedOp(rects, count, paint),
986 mRects(rects), mCount(count) {}
Chris Craik2af46352012-11-26 18:30:17 -0800987
Chris Craikd41c4d82015-01-05 15:51:13 -0800988 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
Tom Hudson107843d2014-09-08 11:26:26 -0400989 renderer.drawRects(mRects, mCount, mPaint);
Chris Craik2af46352012-11-26 18:30:17 -0800990 }
991
Chris Craikd41c4d82015-01-05 15:51:13 -0800992 virtual void output(int level, uint32_t logFlags) const override {
Chris Craik2af46352012-11-26 18:30:17 -0800993 OP_LOG("Draw Rects count %d", mCount);
994 }
995
Chris Craikd41c4d82015-01-05 15:51:13 -0800996 virtual const char* name() override { return "DrawRects"; }
Chris Craik2af46352012-11-26 18:30:17 -0800997
Andreas Gampe64bb4132014-11-22 00:35:09 +0000998 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
Chris Craikd41c4d82015-01-05 15:51:13 -0800999 const DeferredDisplayState& state) override {
Chris Craik28ce94a2013-05-31 11:38:03 -07001000 deferInfo.batchId = DeferredDisplayList::kOpBatch_Vertices;
Chris Craikc3566d02013-02-04 16:16:33 -08001001 }
1002
Chris Craik2af46352012-11-26 18:30:17 -08001003private:
1004 const float* mRects;
1005 int mCount;
1006};
1007
1008class DrawRoundRectOp : public DrawStrokableOp {
1009public:
1010 DrawRoundRectOp(float left, float top, float right, float bottom,
Chris Craikd218a922014-01-02 17:13:34 -08001011 float rx, float ry, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001012 : DrawStrokableOp(left, top, right, bottom, paint), mRx(rx), mRy(ry) {}
1013
Chris Craikd41c4d82015-01-05 15:51:13 -08001014 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
Tom Hudson107843d2014-09-08 11:26:26 -04001015 renderer.drawRoundRect(mLocalBounds.left, mLocalBounds.top,
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -04001016 mLocalBounds.right, mLocalBounds.bottom, mRx, mRy, mPaint);
Chris Craik2af46352012-11-26 18:30:17 -08001017 }
1018
Chris Craikd41c4d82015-01-05 15:51:13 -08001019 virtual void output(int level, uint32_t logFlags) const override {
John Reckce444ca2014-06-02 15:12:36 -07001020 OP_LOG("Draw RoundRect " RECT_STRING ", rx %f, ry %f", RECT_ARGS(mLocalBounds), mRx, mRy);
Chris Craik2af46352012-11-26 18:30:17 -08001021 }
1022
Chris Craik05f3d6e2014-06-02 16:27:04 -07001023 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
Chris Craikd41c4d82015-01-05 15:51:13 -08001024 const DeferredDisplayState& state) override {
Chris Craik05f3d6e2014-06-02 16:27:04 -07001025 DrawStrokableOp::onDefer(renderer, deferInfo, state);
1026 if (!mPaint->getPathEffect()) {
Chris Craik6ac174b2014-06-17 13:47:05 -07001027 renderer.getCaches().tessellationCache.precacheRoundRect(state.mMatrix, *mPaint,
1028 mLocalBounds.getWidth(), mLocalBounds.getHeight(), mRx, mRy);
Chris Craik05f3d6e2014-06-02 16:27:04 -07001029 }
1030 }
1031
Chris Craikd41c4d82015-01-05 15:51:13 -08001032 virtual const char* name() override { return "DrawRoundRect"; }
Chris Craik2af46352012-11-26 18:30:17 -08001033
1034private:
1035 float mRx;
1036 float mRy;
1037};
1038
Jorim Jaggi072707d2014-09-15 17:20:08 +02001039class DrawRoundRectPropsOp : public DrawOp {
1040public:
1041 DrawRoundRectPropsOp(float* left, float* top, float* right, float* bottom,
1042 float *rx, float *ry, const SkPaint* paint)
1043 : DrawOp(paint), mLeft(left), mTop(top), mRight(right), mBottom(bottom),
1044 mRx(rx), mRy(ry) {}
1045
Chris Craikd41c4d82015-01-05 15:51:13 -08001046 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
Tom Hudson107843d2014-09-08 11:26:26 -04001047 renderer.drawRoundRect(*mLeft, *mTop, *mRight, *mBottom,
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -04001048 *mRx, *mRy, mPaint);
Jorim Jaggi072707d2014-09-15 17:20:08 +02001049 }
1050
Chris Craikd41c4d82015-01-05 15:51:13 -08001051 virtual void output(int level, uint32_t logFlags) const override {
Jorim Jaggi072707d2014-09-15 17:20:08 +02001052 OP_LOG("Draw RoundRect Props " RECT_STRING ", rx %f, ry %f",
1053 *mLeft, *mTop, *mRight, *mBottom, *mRx, *mRy);
1054 }
1055
Chris Craikd41c4d82015-01-05 15:51:13 -08001056 virtual const char* name() override { return "DrawRoundRectProps"; }
Jorim Jaggi072707d2014-09-15 17:20:08 +02001057
1058private:
1059 float* mLeft;
1060 float* mTop;
1061 float* mRight;
1062 float* mBottom;
1063 float* mRx;
1064 float* mRy;
1065};
1066
Chris Craik2af46352012-11-26 18:30:17 -08001067class DrawCircleOp : public DrawStrokableOp {
1068public:
Chris Craikd218a922014-01-02 17:13:34 -08001069 DrawCircleOp(float x, float y, float radius, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001070 : DrawStrokableOp(x - radius, y - radius, x + radius, y + radius, paint),
1071 mX(x), mY(y), mRadius(radius) {}
1072
Chris Craikd41c4d82015-01-05 15:51:13 -08001073 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
Tom Hudson107843d2014-09-08 11:26:26 -04001074 renderer.drawCircle(mX, mY, mRadius, mPaint);
Chris Craik2af46352012-11-26 18:30:17 -08001075 }
1076
Chris Craikd41c4d82015-01-05 15:51:13 -08001077 virtual void output(int level, uint32_t logFlags) const override {
Chris Craik2af46352012-11-26 18:30:17 -08001078 OP_LOG("Draw Circle x %f, y %f, r %f", mX, mY, mRadius);
1079 }
1080
Chris Craikd41c4d82015-01-05 15:51:13 -08001081 virtual const char* name() override { return "DrawCircle"; }
Chris Craik2af46352012-11-26 18:30:17 -08001082
1083private:
1084 float mX;
1085 float mY;
1086 float mRadius;
1087};
1088
John Reck52244ff2014-05-01 21:27:37 -07001089class DrawCirclePropsOp : public DrawOp {
1090public:
1091 DrawCirclePropsOp(float* x, float* y, float* radius, const SkPaint* paint)
1092 : DrawOp(paint), mX(x), mY(y), mRadius(radius) {}
1093
Chris Craikd41c4d82015-01-05 15:51:13 -08001094 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
Tom Hudson107843d2014-09-08 11:26:26 -04001095 renderer.drawCircle(*mX, *mY, *mRadius, mPaint);
John Reck52244ff2014-05-01 21:27:37 -07001096 }
1097
Chris Craikd41c4d82015-01-05 15:51:13 -08001098 virtual void output(int level, uint32_t logFlags) const override {
John Reck52244ff2014-05-01 21:27:37 -07001099 OP_LOG("Draw Circle Props x %p, y %p, r %p", mX, mY, mRadius);
1100 }
1101
Chris Craikd41c4d82015-01-05 15:51:13 -08001102 virtual const char* name() override { return "DrawCircleProps"; }
John Reck52244ff2014-05-01 21:27:37 -07001103
1104private:
1105 float* mX;
1106 float* mY;
1107 float* mRadius;
1108};
1109
Chris Craik2af46352012-11-26 18:30:17 -08001110class DrawOvalOp : public DrawStrokableOp {
1111public:
Chris Craikd218a922014-01-02 17:13:34 -08001112 DrawOvalOp(float left, float top, float right, float bottom, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001113 : DrawStrokableOp(left, top, right, bottom, paint) {}
1114
Chris Craikd41c4d82015-01-05 15:51:13 -08001115 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
Tom Hudson107843d2014-09-08 11:26:26 -04001116 renderer.drawOval(mLocalBounds.left, mLocalBounds.top,
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -04001117 mLocalBounds.right, mLocalBounds.bottom, mPaint);
Chris Craik2af46352012-11-26 18:30:17 -08001118 }
1119
Chris Craikd41c4d82015-01-05 15:51:13 -08001120 virtual void output(int level, uint32_t logFlags) const override {
John Reckce444ca2014-06-02 15:12:36 -07001121 OP_LOG("Draw Oval " RECT_STRING, RECT_ARGS(mLocalBounds));
Chris Craik2af46352012-11-26 18:30:17 -08001122 }
1123
Chris Craikd41c4d82015-01-05 15:51:13 -08001124 virtual const char* name() override { return "DrawOval"; }
Chris Craik2af46352012-11-26 18:30:17 -08001125};
1126
1127class DrawArcOp : public DrawStrokableOp {
1128public:
1129 DrawArcOp(float left, float top, float right, float bottom,
Chris Craikd218a922014-01-02 17:13:34 -08001130 float startAngle, float sweepAngle, bool useCenter, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001131 : DrawStrokableOp(left, top, right, bottom, paint),
1132 mStartAngle(startAngle), mSweepAngle(sweepAngle), mUseCenter(useCenter) {}
1133
Chris Craikd41c4d82015-01-05 15:51:13 -08001134 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
Tom Hudson107843d2014-09-08 11:26:26 -04001135 renderer.drawArc(mLocalBounds.left, mLocalBounds.top,
Chris Craik2af46352012-11-26 18:30:17 -08001136 mLocalBounds.right, mLocalBounds.bottom,
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -04001137 mStartAngle, mSweepAngle, mUseCenter, mPaint);
Chris Craik2af46352012-11-26 18:30:17 -08001138 }
1139
Chris Craikd41c4d82015-01-05 15:51:13 -08001140 virtual void output(int level, uint32_t logFlags) const override {
John Reckce444ca2014-06-02 15:12:36 -07001141 OP_LOG("Draw Arc " RECT_STRING ", start %f, sweep %f, useCenter %d",
Chris Craik2af46352012-11-26 18:30:17 -08001142 RECT_ARGS(mLocalBounds), mStartAngle, mSweepAngle, mUseCenter);
1143 }
1144
Chris Craikd41c4d82015-01-05 15:51:13 -08001145 virtual const char* name() override { return "DrawArc"; }
Chris Craik2af46352012-11-26 18:30:17 -08001146
1147private:
1148 float mStartAngle;
1149 float mSweepAngle;
1150 bool mUseCenter;
1151};
1152
1153class DrawPathOp : public DrawBoundedOp {
1154public:
Chris Craikd218a922014-01-02 17:13:34 -08001155 DrawPathOp(const SkPath* path, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001156 : DrawBoundedOp(paint), mPath(path) {
1157 float left, top, offset;
1158 uint32_t width, height;
Romain Guyca89e2a2013-03-08 17:44:20 -08001159 PathCache::computePathBounds(path, paint, left, top, offset, width, height);
Chris Craik2af46352012-11-26 18:30:17 -08001160 left -= offset;
1161 top -= offset;
1162 mLocalBounds.set(left, top, left + width, top + height);
1163 }
1164
Chris Craikd41c4d82015-01-05 15:51:13 -08001165 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
Tom Hudson107843d2014-09-08 11:26:26 -04001166 renderer.drawPath(mPath, mPaint);
Chris Craik2af46352012-11-26 18:30:17 -08001167 }
1168
Chris Craikc1c5f082013-09-11 16:23:37 -07001169 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
Chris Craikd41c4d82015-01-05 15:51:13 -08001170 const DeferredDisplayState& state) override {
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -04001171 renderer.getCaches().pathCache.precache(mPath, mPaint);
Chris Craik527a3aa2013-03-04 10:19:31 -08001172
Chris Craik28ce94a2013-05-31 11:38:03 -07001173 deferInfo.batchId = DeferredDisplayList::kOpBatch_AlphaMaskTexture;
Romain Guyca89e2a2013-03-08 17:44:20 -08001174 }
1175
Chris Craikd41c4d82015-01-05 15:51:13 -08001176 virtual void output(int level, uint32_t logFlags) const override {
John Reckce444ca2014-06-02 15:12:36 -07001177 OP_LOG("Draw Path %p in " RECT_STRING, mPath, RECT_ARGS(mLocalBounds));
Chris Craik2af46352012-11-26 18:30:17 -08001178 }
1179
Chris Craikd41c4d82015-01-05 15:51:13 -08001180 virtual const char* name() override { return "DrawPath"; }
Chris Craik2af46352012-11-26 18:30:17 -08001181
1182private:
Chris Craikd218a922014-01-02 17:13:34 -08001183 const SkPath* mPath;
Chris Craik2af46352012-11-26 18:30:17 -08001184};
1185
Chris Craikc3566d02013-02-04 16:16:33 -08001186class DrawLinesOp : public DrawBoundedOp {
Chris Craik2af46352012-11-26 18:30:17 -08001187public:
Chris Craikd218a922014-01-02 17:13:34 -08001188 DrawLinesOp(const float* points, int count, const SkPaint* paint)
Chris Craik5d116762013-02-19 17:49:31 -08001189 : DrawBoundedOp(points, count, paint),
1190 mPoints(points), mCount(count) {
Chris Craikc3566d02013-02-04 16:16:33 -08001191 mLocalBounds.outset(strokeWidthOutset());
Chris Craik2af46352012-11-26 18:30:17 -08001192 }
1193
Chris Craikd41c4d82015-01-05 15:51:13 -08001194 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
Tom Hudson107843d2014-09-08 11:26:26 -04001195 renderer.drawLines(mPoints, mCount, mPaint);
Chris Craik2af46352012-11-26 18:30:17 -08001196 }
1197
Chris Craikd41c4d82015-01-05 15:51:13 -08001198 virtual void output(int level, uint32_t logFlags) const override {
Chris Craik2af46352012-11-26 18:30:17 -08001199 OP_LOG("Draw Lines count %d", mCount);
1200 }
1201
Chris Craikd41c4d82015-01-05 15:51:13 -08001202 virtual const char* name() override { return "DrawLines"; }
Chris Craik2af46352012-11-26 18:30:17 -08001203
Andreas Gampe64bb4132014-11-22 00:35:09 +00001204 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
Chris Craikd41c4d82015-01-05 15:51:13 -08001205 const DeferredDisplayState& state) override {
Chris Craik28ce94a2013-05-31 11:38:03 -07001206 deferInfo.batchId = mPaint->isAntiAlias() ?
Chris Craikc3566d02013-02-04 16:16:33 -08001207 DeferredDisplayList::kOpBatch_AlphaVertices :
1208 DeferredDisplayList::kOpBatch_Vertices;
1209 }
1210
Chris Craik2af46352012-11-26 18:30:17 -08001211protected:
Chris Craikd218a922014-01-02 17:13:34 -08001212 const float* mPoints;
Chris Craik2af46352012-11-26 18:30:17 -08001213 int mCount;
1214};
1215
1216class DrawPointsOp : public DrawLinesOp {
1217public:
Chris Craikd218a922014-01-02 17:13:34 -08001218 DrawPointsOp(const float* points, int count, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001219 : DrawLinesOp(points, count, paint) {}
1220
Chris Craikd41c4d82015-01-05 15:51:13 -08001221 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
Tom Hudson107843d2014-09-08 11:26:26 -04001222 renderer.drawPoints(mPoints, mCount, mPaint);
Chris Craik2af46352012-11-26 18:30:17 -08001223 }
1224
Chris Craikd41c4d82015-01-05 15:51:13 -08001225 virtual void output(int level, uint32_t logFlags) const override {
Chris Craik2af46352012-11-26 18:30:17 -08001226 OP_LOG("Draw Points count %d", mCount);
1227 }
1228
Chris Craikd41c4d82015-01-05 15:51:13 -08001229 virtual const char* name() override { return "DrawPoints"; }
Chris Craik2af46352012-11-26 18:30:17 -08001230};
1231
1232class DrawSomeTextOp : public DrawOp {
1233public:
Chris Craike8c3c812016-02-05 20:10:50 -08001234 DrawSomeTextOp(const glyph_t* text, int bytesCount, int count, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001235 : DrawOp(paint), mText(text), mBytesCount(bytesCount), mCount(count) {};
1236
Chris Craikd41c4d82015-01-05 15:51:13 -08001237 virtual void output(int level, uint32_t logFlags) const override {
Chris Craik2af46352012-11-26 18:30:17 -08001238 OP_LOG("Draw some text, %d bytes", mBytesCount);
1239 }
Chris Craikc3566d02013-02-04 16:16:33 -08001240
Chris Craikd41c4d82015-01-05 15:51:13 -08001241 virtual bool hasTextShadow() const override {
Chris Craikbf6f0f22015-10-01 12:36:07 -07001242 return PaintUtils::hasTextShadow(mPaint);
Derek Sollenbergerc29a0a42014-03-31 13:52:39 -04001243 }
1244
Chris Craikc1c5f082013-09-11 16:23:37 -07001245 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
Chris Craikd41c4d82015-01-05 15:51:13 -08001246 const DeferredDisplayState& state) override {
Chris Craikc08820f2015-09-22 14:22:29 -07001247 FontRenderer& fontRenderer = renderer.getCaches().fontRenderer.getFontRenderer();
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -04001248 fontRenderer.precache(mPaint, mText, mCount, SkMatrix::I());
Romain Guy0f667532013-03-01 14:31:04 -08001249
Chris Craik98d608d2014-07-17 12:25:11 -07001250 deferInfo.batchId = mPaint->getColor() == SK_ColorBLACK ?
Chris Craikc3566d02013-02-04 16:16:33 -08001251 DeferredDisplayList::kOpBatch_Text :
1252 DeferredDisplayList::kOpBatch_ColorText;
1253 }
Chris Craik527a3aa2013-03-04 10:19:31 -08001254
Chris Craik2af46352012-11-26 18:30:17 -08001255protected:
Chris Craike8c3c812016-02-05 20:10:50 -08001256 const glyph_t* mText;
Chris Craik2af46352012-11-26 18:30:17 -08001257 int mBytesCount;
1258 int mCount;
1259};
1260
1261class DrawTextOnPathOp : public DrawSomeTextOp {
1262public:
Chris Craike8c3c812016-02-05 20:10:50 -08001263 DrawTextOnPathOp(const glyph_t* text, int bytesCount, int count,
Chris Craikd218a922014-01-02 17:13:34 -08001264 const SkPath* path, float hOffset, float vOffset, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001265 : DrawSomeTextOp(text, bytesCount, count, paint),
1266 mPath(path), mHOffset(hOffset), mVOffset(vOffset) {
1267 /* TODO: inherit from DrawBounded and init mLocalBounds */
1268 }
1269
Chris Craikd41c4d82015-01-05 15:51:13 -08001270 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
Tom Hudson107843d2014-09-08 11:26:26 -04001271 renderer.drawTextOnPath(mText, mBytesCount, mCount, mPath,
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -04001272 mHOffset, mVOffset, mPaint);
Chris Craik2af46352012-11-26 18:30:17 -08001273 }
1274
Chris Craikd41c4d82015-01-05 15:51:13 -08001275 virtual const char* name() override { return "DrawTextOnPath"; }
Chris Craik2af46352012-11-26 18:30:17 -08001276
1277private:
Chris Craikd218a922014-01-02 17:13:34 -08001278 const SkPath* mPath;
Chris Craik2af46352012-11-26 18:30:17 -08001279 float mHOffset;
1280 float mVOffset;
1281};
1282
Chris Craik947eabf2014-08-19 10:21:12 -07001283class DrawTextOp : public DrawStrokableOp {
Chris Craik2af46352012-11-26 18:30:17 -08001284public:
Chris Craike8c3c812016-02-05 20:10:50 -08001285 DrawTextOp(const glyph_t* text, int bytesCount, int count, float x, float y,
Chris Craikd218a922014-01-02 17:13:34 -08001286 const float* positions, const SkPaint* paint, float totalAdvance, const Rect& bounds)
Chris Craik947eabf2014-08-19 10:21:12 -07001287 : DrawStrokableOp(bounds, paint), mText(text), mBytesCount(bytesCount), mCount(count),
Chris Craik41541822013-05-03 16:35:54 -07001288 mX(x), mY(y), mPositions(positions), mTotalAdvance(totalAdvance) {
Chris Craik59744b72014-07-01 17:56:52 -07001289 mPrecacheTransform = SkMatrix::InvalidMatrix();
Chris Craik2af46352012-11-26 18:30:17 -08001290 }
1291
Chris Craikc1c5f082013-09-11 16:23:37 -07001292 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
Chris Craikd41c4d82015-01-05 15:51:13 -08001293 const DeferredDisplayState& state) override {
Chris Craikc08820f2015-09-22 14:22:29 -07001294 FontRenderer& fontRenderer = renderer.getCaches().fontRenderer.getFontRenderer();
Chris Craik59744b72014-07-01 17:56:52 -07001295 SkMatrix transform;
1296 renderer.findBestFontTransform(state.mMatrix, &transform);
Romain Guybd3055f2013-03-13 16:14:47 -07001297 if (mPrecacheTransform != transform) {
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -04001298 fontRenderer.precache(mPaint, mText, mCount, transform);
Romain Guybd3055f2013-03-13 16:14:47 -07001299 mPrecacheTransform = transform;
1300 }
Chris Craik98d608d2014-07-17 12:25:11 -07001301 deferInfo.batchId = mPaint->getColor() == SK_ColorBLACK ?
Chris Craik527a3aa2013-03-04 10:19:31 -08001302 DeferredDisplayList::kOpBatch_Text :
1303 DeferredDisplayList::kOpBatch_ColorText;
1304
Kévin PETIT73fc5582014-02-13 11:03:40 +00001305 deferInfo.mergeId = reinterpret_cast<mergeid_t>(mPaint->getColor());
Chris Craik527a3aa2013-03-04 10:19:31 -08001306
1307 // don't merge decorated text - the decorations won't draw in order
Chris Craik98d608d2014-07-17 12:25:11 -07001308 bool hasDecorations = mPaint->getFlags()
1309 & (SkPaint::kUnderlineText_Flag | SkPaint::kStrikeThruText_Flag);
1310
1311 deferInfo.mergeable = state.mMatrix.isPureTranslate()
1312 && !hasDecorations
Chris Craikbf6f0f22015-10-01 12:36:07 -07001313 && PaintUtils::getXfermodeDirect(mPaint) == SkXfermode::kSrcOver_Mode;
Romain Guy0f667532013-03-01 14:31:04 -08001314 }
1315
Chris Craikd41c4d82015-01-05 15:51:13 -08001316 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
Romain Guy9b5a1a22013-08-09 14:06:29 -07001317 Rect bounds;
John Reck3b202512014-06-23 13:13:08 -07001318 getLocalBounds(bounds);
Tom Hudson107843d2014-09-08 11:26:26 -04001319 renderer.drawText(mText, mBytesCount, mCount, mX, mY,
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -04001320 mPositions, mPaint, mTotalAdvance, bounds);
Chris Craik2af46352012-11-26 18:30:17 -08001321 }
1322
Andreas Gampe64bb4132014-11-22 00:35:09 +00001323 virtual void multiDraw(OpenGLRenderer& renderer, Rect& dirty,
John Reck272a6852015-07-29 16:48:58 -07001324 const std::vector<OpStatePair>& ops, const Rect& bounds) override {
Chris Craik527a3aa2013-03-04 10:19:31 -08001325 for (unsigned int i = 0; i < ops.size(); i++) {
Chris Craikc1c5f082013-09-11 16:23:37 -07001326 const DeferredDisplayState& state = *(ops[i].state);
Chris Craik03ae2722015-02-25 11:01:09 -08001327 DrawOpMode drawOpMode = (i == ops.size() - 1) ? DrawOpMode::kFlush : DrawOpMode::kDefer;
Chris Craikc1c5f082013-09-11 16:23:37 -07001328 renderer.restoreDisplayState(state, true); // restore all but the clip
Chris Craik527a3aa2013-03-04 10:19:31 -08001329
Chris Craikc1c5f082013-09-11 16:23:37 -07001330 DrawTextOp& op = *((DrawTextOp*)ops[i].op);
Romain Guy9b5a1a22013-08-09 14:06:29 -07001331 // quickReject() will not occure in drawText() so we can use mLocalBounds
1332 // directly, we do not need to account for shadow by calling getLocalBounds()
Tom Hudson107843d2014-09-08 11:26:26 -04001333 renderer.drawText(op.mText, op.mBytesCount, op.mCount, op.mX, op.mY,
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -04001334 op.mPositions, op.mPaint, op.mTotalAdvance, op.mLocalBounds,
Chris Craik41541822013-05-03 16:35:54 -07001335 drawOpMode);
Chris Craik527a3aa2013-03-04 10:19:31 -08001336 }
Chris Craik527a3aa2013-03-04 10:19:31 -08001337 }
1338
Chris Craikd41c4d82015-01-05 15:51:13 -08001339 virtual void output(int level, uint32_t logFlags) const override {
Chris Craik2af46352012-11-26 18:30:17 -08001340 OP_LOG("Draw Text of count %d, bytes %d", mCount, mBytesCount);
1341 }
1342
Chris Craikd41c4d82015-01-05 15:51:13 -08001343 virtual const char* name() override { return "DrawText"; }
Chris Craik2af46352012-11-26 18:30:17 -08001344
1345private:
Chris Craike8c3c812016-02-05 20:10:50 -08001346 const glyph_t* mText;
Chris Craik2af46352012-11-26 18:30:17 -08001347 int mBytesCount;
1348 int mCount;
1349 float mX;
1350 float mY;
1351 const float* mPositions;
Chris Craik41541822013-05-03 16:35:54 -07001352 float mTotalAdvance;
Chris Craik59744b72014-07-01 17:56:52 -07001353 SkMatrix mPrecacheTransform;
Chris Craik2af46352012-11-26 18:30:17 -08001354};
1355
1356///////////////////////////////////////////////////////////////////////////////
1357// SPECIAL DRAW OPERATIONS
1358///////////////////////////////////////////////////////////////////////////////
1359
1360class DrawFunctorOp : public DrawOp {
1361public:
1362 DrawFunctorOp(Functor* functor)
Chris Craikd41c4d82015-01-05 15:51:13 -08001363 : DrawOp(nullptr), mFunctor(functor) {}
Chris Craik2af46352012-11-26 18:30:17 -08001364
Chris Craikd41c4d82015-01-05 15:51:13 -08001365 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
Chris Craik2af46352012-11-26 18:30:17 -08001366 renderer.startMark("GL functor");
Tom Hudson107843d2014-09-08 11:26:26 -04001367 renderer.callDrawGLFunction(mFunctor, dirty);
Chris Craik2af46352012-11-26 18:30:17 -08001368 renderer.endMark();
Chris Craik2af46352012-11-26 18:30:17 -08001369 }
1370
Chris Craikd41c4d82015-01-05 15:51:13 -08001371 virtual void output(int level, uint32_t logFlags) const override {
Chris Craik2af46352012-11-26 18:30:17 -08001372 OP_LOG("Draw Functor %p", mFunctor);
1373 }
1374
Chris Craikd41c4d82015-01-05 15:51:13 -08001375 virtual const char* name() override { return "DrawFunctor"; }
Chris Craik2af46352012-11-26 18:30:17 -08001376
1377private:
1378 Functor* mFunctor;
1379};
1380
Chris Craika7090e02014-06-20 16:01:00 -07001381class DrawRenderNodeOp : public DrawBoundedOp {
1382 friend class RenderNode; // grant RenderNode access to info of child
Chris Craik003cc3d2015-10-16 10:24:55 -07001383 friend class DisplayList; // grant DisplayList access to info of child
Chris Craikb565df12015-10-05 13:00:52 -07001384 friend class DisplayListCanvas;
Chris Craik161f54b2015-11-05 11:08:52 -08001385 friend class TestUtils;
Chris Craik2af46352012-11-26 18:30:17 -08001386public:
Chris Craika766cb22015-06-08 16:49:43 -07001387 DrawRenderNodeOp(RenderNode* renderNode, const mat4& transformFromParent, bool clipIsSimple)
Chris Craik54fa17f2015-11-25 14:14:53 -08001388 : DrawBoundedOp(0, 0,
1389 renderNode->stagingProperties().getWidth(),
1390 renderNode->stagingProperties().getHeight(),
1391 nullptr)
Chris Craikb565df12015-10-05 13:00:52 -07001392 , renderNode(renderNode)
Chris Craika766cb22015-06-08 16:49:43 -07001393 , mRecordedWithPotentialStencilClip(!clipIsSimple || !transformFromParent.isSimple())
Chris Craik8d1f2122015-11-24 16:40:09 -08001394 , localMatrix(transformFromParent)
1395 , skipInOrderDraw(false) {}
Chris Craikc3566d02013-02-04 16:16:33 -08001396
Andreas Gampe64bb4132014-11-22 00:35:09 +00001397 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
Chris Craikd41c4d82015-01-05 15:51:13 -08001398 bool useQuickReject) override {
Chris Craik8d1f2122015-11-24 16:40:09 -08001399 if (renderNode->isRenderable() && !skipInOrderDraw) {
Chris Craikb565df12015-10-05 13:00:52 -07001400 renderNode->defer(deferStruct, level + 1);
Chris Craikc3566d02013-02-04 16:16:33 -08001401 }
Chris Craikc3566d02013-02-04 16:16:33 -08001402 }
Chris Craik8afd0f22014-08-21 17:41:57 -07001403
Andreas Gampe64bb4132014-11-22 00:35:09 +00001404 virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level,
Chris Craikd41c4d82015-01-05 15:51:13 -08001405 bool useQuickReject) override {
Chris Craik8d1f2122015-11-24 16:40:09 -08001406 if (renderNode->isRenderable() && !skipInOrderDraw) {
Chris Craikb565df12015-10-05 13:00:52 -07001407 renderNode->replay(replayStruct, level + 1);
Chris Craikff785832013-03-08 13:12:16 -08001408 }
1409 }
Chris Craik2af46352012-11-26 18:30:17 -08001410
Chris Craikd41c4d82015-01-05 15:51:13 -08001411 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
Chris Craik80d49022014-06-20 15:03:43 -07001412 LOG_ALWAYS_FATAL("should not be called, because replay() is overridden");
Chris Craika08f95c2013-03-15 17:24:33 -07001413 }
Chris Craikff785832013-03-08 13:12:16 -08001414
Chris Craikd41c4d82015-01-05 15:51:13 -08001415 virtual void output(int level, uint32_t logFlags) const override {
Chris Craikb565df12015-10-05 13:00:52 -07001416 OP_LOG("Draw RenderNode %p %s", renderNode, renderNode->getName());
1417 if (renderNode && (logFlags & kOpLogFlag_Recurse)) {
1418 renderNode->output(level + 1);
Chris Craik2af46352012-11-26 18:30:17 -08001419 }
1420 }
1421
Chris Craikd41c4d82015-01-05 15:51:13 -08001422 virtual const char* name() override { return "DrawRenderNode"; }
Chris Craik2af46352012-11-26 18:30:17 -08001423
1424private:
Chris Craikb565df12015-10-05 13:00:52 -07001425 RenderNode* renderNode;
Chris Craikf57776b2013-10-25 18:30:17 -07001426
Chris Craika766cb22015-06-08 16:49:43 -07001427 /**
1428 * This RenderNode was drawn into a DisplayList with the canvas in a state that will likely
1429 * require rendering with stencil clipping. Either:
1430 *
1431 * 1) A path clip or rotated rect clip was in effect on the canvas at record time
1432 * 2) The RenderNode was recorded with a non-simple canvas transform (e.g. rotation)
1433 *
1434 * Note: even if this is false, non-rect clipping may still be applied applied either due to
1435 * property-driven rotation (either in this RenderNode, or any ancestor), or record time
1436 * clipping in an ancestor. These are handled in RenderNode::prepareTreeImpl since they are
1437 * dynamic (relative to a static DisplayList of a parent), and don't affect this flag.
1438 */
1439 bool mRecordedWithPotentialStencilClip;
1440
Chris Craikf57776b2013-10-25 18:30:17 -07001441 ///////////////////////////
Chris Craika7090e02014-06-20 16:01:00 -07001442 // Properties below are used by RenderNode::computeOrderingImpl() and issueOperations()
Chris Craikf57776b2013-10-25 18:30:17 -07001443 ///////////////////////////
1444 /**
1445 * Records transform vs parent, used for computing total transform without rerunning DL contents
1446 */
Chris Craik8d1f2122015-11-24 16:40:09 -08001447 const mat4 localMatrix;
Chris Craikf57776b2013-10-25 18:30:17 -07001448
1449 /**
Chris Craika7090e02014-06-20 16:01:00 -07001450 * Holds the transformation between the projection surface ViewGroup and this RenderNode
Chris Craikb79a3e32014-03-11 12:20:17 -07001451 * drawing instance. Represents any translations / transformations done within the drawing of
1452 * the compositing ancestor ViewGroup's draw, before the draw of the View represented by this
1453 * DisplayList draw instance.
Chris Craikf57776b2013-10-25 18:30:17 -07001454 *
Chris Craika7090e02014-06-20 16:01:00 -07001455 * Note: doesn't include transformation within the RenderNode, or its properties.
Chris Craikf57776b2013-10-25 18:30:17 -07001456 */
Chris Craik8d1f2122015-11-24 16:40:09 -08001457 mat4 transformFromCompositingAncestor;
1458 bool skipInOrderDraw;
Chris Craikf57776b2013-10-25 18:30:17 -07001459};
1460
1461/**
Chris Craik024433f2014-03-26 13:19:14 -07001462 * Not a canvas operation, used only by 3d / z ordering logic in RenderNode::iterate()
Chris Craikf57776b2013-10-25 18:30:17 -07001463 */
1464class DrawShadowOp : public DrawOp {
1465public:
Chris Craik024433f2014-03-26 13:19:14 -07001466 DrawShadowOp(const mat4& transformXY, const mat4& transformZ,
Chris Craik74669862014-08-07 17:27:30 -07001467 float casterAlpha, const SkPath* casterOutline)
Chris Craikd41c4d82015-01-05 15:51:13 -08001468 : DrawOp(nullptr)
Chris Craik74669862014-08-07 17:27:30 -07001469 , mTransformXY(transformXY)
1470 , mTransformZ(transformZ)
1471 , mCasterAlpha(casterAlpha)
1472 , mCasterOutline(casterOutline) {
Chris Craik61317322014-05-21 13:03:52 -07001473 }
Chris Craikf57776b2013-10-25 18:30:17 -07001474
Andreas Gampe64bb4132014-11-22 00:35:09 +00001475 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
Chris Craikd41c4d82015-01-05 15:51:13 -08001476 const DeferredDisplayState& state) override {
Chris Craik05f3d6e2014-06-02 16:27:04 -07001477 renderer.getCaches().tessellationCache.precacheShadows(&state.mMatrix,
Chris Craik74669862014-08-07 17:27:30 -07001478 renderer.getLocalClipBounds(), isCasterOpaque(), mCasterOutline,
Chris Craik05f3d6e2014-06-02 16:27:04 -07001479 &mTransformXY, &mTransformZ, renderer.getLightCenter(), renderer.getLightRadius());
1480 }
1481
Chris Craikd41c4d82015-01-05 15:51:13 -08001482 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
Chris Craik05f3d6e2014-06-02 16:27:04 -07001483 TessellationCache::vertexBuffer_pair_t buffers;
Chris Craikc3e75f92014-08-27 15:34:52 -07001484 Matrix4 drawTransform(*(renderer.currentTransform()));
Chris Craik05f3d6e2014-06-02 16:27:04 -07001485 renderer.getCaches().tessellationCache.getShadowBuffers(&drawTransform,
Chris Craik74669862014-08-07 17:27:30 -07001486 renderer.getLocalClipBounds(), isCasterOpaque(), mCasterOutline,
Chris Craik05f3d6e2014-06-02 16:27:04 -07001487 &mTransformXY, &mTransformZ, renderer.getLightCenter(), renderer.getLightRadius(),
1488 buffers);
1489
Tom Hudson107843d2014-09-08 11:26:26 -04001490 renderer.drawShadow(mCasterAlpha, buffers.first, buffers.second);
Chris Craikf57776b2013-10-25 18:30:17 -07001491 }
1492
Chris Craikd41c4d82015-01-05 15:51:13 -08001493 virtual void output(int level, uint32_t logFlags) const override {
Chris Craik61317322014-05-21 13:03:52 -07001494 OP_LOGS("DrawShadow");
Chris Craikf57776b2013-10-25 18:30:17 -07001495 }
1496
Chris Craikd41c4d82015-01-05 15:51:13 -08001497 virtual const char* name() override { return "DrawShadow"; }
Chris Craikf57776b2013-10-25 18:30:17 -07001498
1499private:
Chris Craikaf4d04c2014-07-29 12:50:14 -07001500 bool isCasterOpaque() { return mCasterAlpha >= 1.0f; }
Chris Craik05f3d6e2014-06-02 16:27:04 -07001501
Chris Craikb79a3e32014-03-11 12:20:17 -07001502 const mat4 mTransformXY;
1503 const mat4 mTransformZ;
Chris Craik024433f2014-03-26 13:19:14 -07001504 const float mCasterAlpha;
Chris Craik74669862014-08-07 17:27:30 -07001505 const SkPath* mCasterOutline;
Chris Craik2af46352012-11-26 18:30:17 -08001506};
1507
1508class DrawLayerOp : public DrawOp {
1509public:
Chris Craik3aadd602015-08-20 12:41:40 -07001510 DrawLayerOp(Layer* layer)
1511 : DrawOp(nullptr), mLayer(layer) {}
Chris Craik2af46352012-11-26 18:30:17 -08001512
Chris Craikd41c4d82015-01-05 15:51:13 -08001513 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
Chris Craik3aadd602015-08-20 12:41:40 -07001514 renderer.drawLayer(mLayer);
Chris Craik2af46352012-11-26 18:30:17 -08001515 }
1516
Chris Craikd41c4d82015-01-05 15:51:13 -08001517 virtual void output(int level, uint32_t logFlags) const override {
Chris Craik3aadd602015-08-20 12:41:40 -07001518 OP_LOG("Draw Layer %p", mLayer);
Chris Craik2af46352012-11-26 18:30:17 -08001519 }
1520
Chris Craikd41c4d82015-01-05 15:51:13 -08001521 virtual const char* name() override { return "DrawLayer"; }
Chris Craik2af46352012-11-26 18:30:17 -08001522
1523private:
1524 Layer* mLayer;
Chris Craik2af46352012-11-26 18:30:17 -08001525};
1526
1527}; // namespace uirenderer
1528}; // namespace android
1529
1530#endif // ANDROID_HWUI_DISPLAY_OPERATION_H