blob: 516e6199bd279776f83e13d58faf02ad71909506 [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"
Doris Liu14b56a52016-02-26 11:36:03 -080031#include "VectorDrawable.h"
Chris Craik2af46352012-11-26 18:30:17 -080032
Chris Craikdf72b632015-06-30 17:56:13 -070033#include <algorithm>
34
Chris Craik65fe5ee2015-01-26 18:06:29 -080035#include <SkColor.h>
36#include <SkPath.h>
37#include <SkPathOps.h>
38#include <SkXfermode.h>
39
40#include <private/hwui/DrawGlInfo.h>
41
Chris Craik2af46352012-11-26 18:30:17 -080042// Use OP_LOG for logging with arglist, OP_LOGS if just printing char*
Chris Craik28ce94a2013-05-31 11:38:03 -070043#define OP_LOGS(s) OP_LOG("%s", (s))
Chris Craik3dc553b2013-02-04 12:45:13 -080044#define OP_LOG(s, ...) ALOGD( "%*s" s, level * 2, "", __VA_ARGS__ )
Chris Craik2af46352012-11-26 18:30:17 -080045
Chris Craik2af46352012-11-26 18:30:17 -080046namespace android {
47namespace uirenderer {
48
49/**
50 * Structure for storing canvas operations when they are recorded into a DisplayList, so that they
51 * may be replayed to an OpenGLRenderer.
52 *
53 * To avoid individual memory allocations, DisplayListOps may only be allocated into a
54 * LinearAllocator's managed memory buffers. Each pointer held by a DisplayListOp is either a
55 * pointer into memory also allocated in the LinearAllocator (mostly for text and float buffers) or
56 * references a externally refcounted object (Sk... and Skia... objects). ~DisplayListOp() is
57 * never called as LinearAllocators are simply discarded, so no memory management should be done in
58 * this class.
59 */
60class DisplayListOp {
61public:
62 // These objects should always be allocated with a LinearAllocator, and never destroyed/deleted.
63 // standard new() intentionally not implemented, and delete/deconstructor should never be used.
Chris Craik51d6a3d2014-12-22 17:16:56 -080064 virtual ~DisplayListOp() { LOG_ALWAYS_FATAL("Destructor not supported"); }
65 static void operator delete(void* ptr) { LOG_ALWAYS_FATAL("delete not supported"); }
66 static void* operator new(size_t size) = delete; /** PURPOSELY OMITTED **/
Chris Craik2af46352012-11-26 18:30:17 -080067 static void* operator new(size_t size, LinearAllocator& allocator) {
John Reck7df9ff22016-02-10 16:08:08 -080068 // FIXME: Quick hack to keep old pipeline working, delete this when
69 // we no longer need to support HWUI_NEWOPS := false
70 return allocator.alloc<char>(size);
Chris Craik2af46352012-11-26 18:30:17 -080071 }
72
73 enum OpLogFlag {
74 kOpLogFlag_Recurse = 0x1,
75 kOpLogFlag_JSON = 0x2 // TODO: add?
76 };
77
Chet Haasedd671592013-04-19 14:54:34 -070078 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
79 bool useQuickReject) = 0;
Chris Craikc3566d02013-02-04 16:16:33 -080080
Chet Haasedd671592013-04-19 14:54:34 -070081 virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level,
82 bool useQuickReject) = 0;
Chris Craikff785832013-03-08 13:12:16 -080083
Chris Craikc5493fb2013-06-19 16:58:58 -070084 virtual void output(int level, uint32_t logFlags = 0) const = 0;
Chris Craik2af46352012-11-26 18:30:17 -080085
86 // NOTE: it would be nice to declare constants and overriding the implementation in each op to
87 // point at the constants, but that seems to require a .cpp file
88 virtual const char* name() = 0;
89};
90
91class StateOp : public DisplayListOp {
92public:
Andreas Gampe64bb4132014-11-22 00:35:09 +000093 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
Chris Craikd41c4d82015-01-05 15:51:13 -080094 bool useQuickReject) override {
Chris Craikff785832013-03-08 13:12:16 -080095 // default behavior only affects immediate, deferrable state, issue directly to renderer
96 applyState(deferStruct.mRenderer, saveCount);
97 }
98
Chris Craikc3566d02013-02-04 16:16:33 -080099 /**
100 * State operations are applied directly to the renderer, but can cause the deferred drawing op
101 * list to flush
102 */
Andreas Gampe64bb4132014-11-22 00:35:09 +0000103 virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level,
Chris Craikd41c4d82015-01-05 15:51:13 -0800104 bool useQuickReject) override {
Chris Craikff785832013-03-08 13:12:16 -0800105 applyState(replayStruct.mRenderer, saveCount);
Chris Craikc3566d02013-02-04 16:16:33 -0800106 }
107
Chris Craik7273daa2013-03-28 11:25:24 -0700108 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const = 0;
Chris Craik2af46352012-11-26 18:30:17 -0800109};
110
111class DrawOp : public DisplayListOp {
Chris Craik527a3aa2013-03-04 10:19:31 -0800112friend class MergingDrawBatch;
Chris Craik2af46352012-11-26 18:30:17 -0800113public:
Chris Craikd218a922014-01-02 17:13:34 -0800114 DrawOp(const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -0800115 : mPaint(paint), mQuickRejected(false) {}
116
Andreas Gampe64bb4132014-11-22 00:35:09 +0000117 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
Chris Craikd41c4d82015-01-05 15:51:13 -0800118 bool useQuickReject) override {
Chet Haasedd671592013-04-19 14:54:34 -0700119 if (mQuickRejected && CC_LIKELY(useQuickReject)) {
Chris Craikff785832013-03-08 13:12:16 -0800120 return;
Chris Craikc3566d02013-02-04 16:16:33 -0800121 }
122
Chris Craikff785832013-03-08 13:12:16 -0800123 deferStruct.mDeferredList.addDrawOp(deferStruct.mRenderer, this);
Chris Craikc3566d02013-02-04 16:16:33 -0800124 }
125
Andreas Gampe64bb4132014-11-22 00:35:09 +0000126 virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level,
Chris Craikd41c4d82015-01-05 15:51:13 -0800127 bool useQuickReject) override {
Chet Haasedd671592013-04-19 14:54:34 -0700128 if (mQuickRejected && CC_LIKELY(useQuickReject)) {
Chris Craikff785832013-03-08 13:12:16 -0800129 return;
130 }
131
Tom Hudson107843d2014-09-08 11:26:26 -0400132 applyDraw(replayStruct.mRenderer, replayStruct.mDirty);
Chris Craikff785832013-03-08 13:12:16 -0800133 }
134
Tom Hudson107843d2014-09-08 11:26:26 -0400135 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) = 0;
Chris Craik2af46352012-11-26 18:30:17 -0800136
Chris Craik527a3aa2013-03-04 10:19:31 -0800137 /**
138 * Draw multiple instances of an operation, must be overidden for operations that merge
139 *
140 * Currently guarantees certain similarities between ops (see MergingDrawBatch::canMergeWith),
141 * and pure translation transformations. Other guarantees of similarity should be enforced by
142 * reducing which operations are tagged as mergeable.
143 */
Tom Hudson107843d2014-09-08 11:26:26 -0400144 virtual void multiDraw(OpenGLRenderer& renderer, Rect& dirty,
John Reck272a6852015-07-29 16:48:58 -0700145 const std::vector<OpStatePair>& ops, const Rect& bounds) {
Chris Craik527a3aa2013-03-04 10:19:31 -0800146 for (unsigned int i = 0; i < ops.size(); i++) {
Chris Craikc1c5f082013-09-11 16:23:37 -0700147 renderer.restoreDisplayState(*(ops[i].state), true);
Tom Hudson107843d2014-09-08 11:26:26 -0400148 ops[i].op->applyDraw(renderer, dirty);
Chris Craik527a3aa2013-03-04 10:19:31 -0800149 }
Chris Craik527a3aa2013-03-04 10:19:31 -0800150 }
151
Chris Craik28ce94a2013-05-31 11:38:03 -0700152 /**
Chris Craik527a3aa2013-03-04 10:19:31 -0800153 * When this method is invoked the state field is initialized to have the
154 * final rendering state. We can thus use it to process data as it will be
155 * used at draw time.
156 *
157 * Additionally, this method allows subclasses to provide defer-time preferences for batching
158 * and merging.
159 *
Chris Craik28ce94a2013-05-31 11:38:03 -0700160 * if a subclass can set deferInfo.mergeable to true, it should implement multiDraw()
Chris Craik527a3aa2013-03-04 10:19:31 -0800161 */
Andreas Gampe64bb4132014-11-22 00:35:09 +0000162 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
163 const DeferredDisplayState& state) {}
Romain Guy0f667532013-03-01 14:31:04 -0800164
Chris Craik5e49b302013-07-30 19:05:20 -0700165 /**
166 * Query the conservative, local bounds (unmapped) bounds of the op.
167 *
168 * returns true if bounds exist
169 */
Andreas Gampe64bb4132014-11-22 00:35:09 +0000170 virtual bool getLocalBounds(Rect& localBounds) {
Chris Craikc1c5f082013-09-11 16:23:37 -0700171 return false;
172 }
Chris Craik2af46352012-11-26 18:30:17 -0800173
174 // TODO: better refine localbounds usage
175 void setQuickRejected(bool quickRejected) { mQuickRejected = quickRejected; }
176 bool getQuickRejected() { return mQuickRejected; }
177
Derek Sollenbergerc29a0a42014-03-31 13:52:39 -0400178 virtual bool hasTextShadow() const {
179 return false;
180 }
181
Chris Craik527a3aa2013-03-04 10:19:31 -0800182 inline float strokeWidthOutset() {
Chris Craikf0a59072013-11-19 18:00:46 -0800183 // since anything AA stroke with less than 1.0 pixel width is drawn with an alpha-reduced
184 // 1.0 stroke, treat 1.0 as minimum.
185
186 // TODO: it would be nice if this could take scale into account, but scale isn't stable
187 // since higher levels of the view hierarchy can change scale out from underneath it.
Chris Craikdf72b632015-06-30 17:56:13 -0700188 return std::max(mPaint->getStrokeWidth(), 1.0f) * 0.5f;
Chris Craike7c69c62013-04-03 09:55:48 -0700189 }
Chris Craikc3566d02013-02-04 16:16:33 -0800190
Chris Craik2af46352012-11-26 18:30:17 -0800191protected:
Chris Craik28ce94a2013-05-31 11:38:03 -0700192 // Helper method for determining op opaqueness. Assumes op fills its bounds in local
193 // coordinates, and that paint's alpha is used
Chris Craikc1c5f082013-09-11 16:23:37 -0700194 inline bool isOpaqueOverBounds(const DeferredDisplayState& state) {
Chris Craik28ce94a2013-05-31 11:38:03 -0700195 // ensure that local bounds cover mapped bounds
196 if (!state.mMatrix.isSimple()) return false;
197
Chris Craik2262abb2014-08-18 19:55:36 -0700198 if (state.mRoundRectClipState) return false;
199
Chris Craik28ce94a2013-05-31 11:38:03 -0700200 // check state/paint for transparency
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400201 if (mPaint) {
Chris Craikc5b5f052014-10-01 16:40:16 -0700202 if (mPaint->getAlpha() != 0xFF) {
203 return false;
204 }
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400205 if (mPaint->getShader() && !mPaint->getShader()->isOpaque()) {
206 return false;
207 }
Tom Hudson8dfaa492014-12-09 15:03:44 -0500208 if (PaintUtils::isBlendedColorFilter(mPaint->getColorFilter())) {
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400209 return false;
210 }
211 }
212
213 if (state.mAlpha != 1.0f) return false;
Chris Craik28ce94a2013-05-31 11:38:03 -0700214
Chris Craikbf6f0f22015-10-01 12:36:07 -0700215 SkXfermode::Mode mode = PaintUtils::getXfermodeDirect(mPaint);
Chris Craik28ce94a2013-05-31 11:38:03 -0700216 return (mode == SkXfermode::kSrcOver_Mode ||
217 mode == SkXfermode::kSrc_Mode);
218
219 }
220
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -0400221 const SkPaint* mPaint;
Chris Craik2af46352012-11-26 18:30:17 -0800222 bool mQuickRejected;
223};
224
225class DrawBoundedOp : public DrawOp {
226public:
Chris Craikd218a922014-01-02 17:13:34 -0800227 DrawBoundedOp(float left, float top, float right, float bottom, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -0800228 : DrawOp(paint), mLocalBounds(left, top, right, bottom) {}
229
Chris Craikd218a922014-01-02 17:13:34 -0800230 DrawBoundedOp(const Rect& localBounds, const SkPaint* paint)
Chris Craik41541822013-05-03 16:35:54 -0700231 : DrawOp(paint), mLocalBounds(localBounds) {}
232
Chris Craik5d116762013-02-19 17:49:31 -0800233 // Calculates bounds as smallest rect encompassing all points
234 // NOTE: requires at least 1 vertex, and doesn't account for stroke size (should be handled in
235 // subclass' constructor)
Chris Craikd218a922014-01-02 17:13:34 -0800236 DrawBoundedOp(const float* points, int count, const SkPaint* paint)
Chris Craik5d116762013-02-19 17:49:31 -0800237 : DrawOp(paint), mLocalBounds(points[0], points[1], points[0], points[1]) {
238 for (int i = 2; i < count; i += 2) {
Chris Craikdf72b632015-06-30 17:56:13 -0700239 mLocalBounds.left = std::min(mLocalBounds.left, points[i]);
240 mLocalBounds.right = std::max(mLocalBounds.right, points[i]);
241 mLocalBounds.top = std::min(mLocalBounds.top, points[i + 1]);
242 mLocalBounds.bottom = std::max(mLocalBounds.bottom, points[i + 1]);
Chris Craik5d116762013-02-19 17:49:31 -0800243 }
244 }
245
246 // default empty constructor for bounds, to be overridden in child constructor body
Chris Craikd218a922014-01-02 17:13:34 -0800247 DrawBoundedOp(const SkPaint* paint): DrawOp(paint) { }
Chris Craik2af46352012-11-26 18:30:17 -0800248
Chris Craikd41c4d82015-01-05 15:51:13 -0800249 virtual bool getLocalBounds(Rect& localBounds) override {
Chris Craik2af46352012-11-26 18:30:17 -0800250 localBounds.set(mLocalBounds);
Chris Craikbf6f0f22015-10-01 12:36:07 -0700251 PaintUtils::TextShadow textShadow;
252 if (PaintUtils::getTextShadow(mPaint, &textShadow)) {
Romain Guy9b5a1a22013-08-09 14:06:29 -0700253 Rect shadow(mLocalBounds);
Derek Sollenbergerc29a0a42014-03-31 13:52:39 -0400254 shadow.translate(textShadow.dx, textShadow.dx);
255 shadow.outset(textShadow.radius);
Romain Guy9b5a1a22013-08-09 14:06:29 -0700256 localBounds.unionWith(shadow);
257 }
Chris Craik2af46352012-11-26 18:30:17 -0800258 return true;
259 }
260
261protected:
262 Rect mLocalBounds; // displayed area in LOCAL coord. doesn't incorporate stroke, so check paint
263};
264
265///////////////////////////////////////////////////////////////////////////////
266// STATE OPERATIONS - these may affect the state of the canvas/renderer, but do
267// not directly draw or alter output
268///////////////////////////////////////////////////////////////////////////////
269
270class SaveOp : public StateOp {
271public:
272 SaveOp(int flags)
273 : mFlags(flags) {}
274
Andreas Gampe64bb4132014-11-22 00:35:09 +0000275 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
Chris Craikd41c4d82015-01-05 15:51:13 -0800276 bool useQuickReject) override {
Chris Craikff785832013-03-08 13:12:16 -0800277 int newSaveCount = deferStruct.mRenderer.save(mFlags);
278 deferStruct.mDeferredList.addSave(deferStruct.mRenderer, this, newSaveCount);
279 }
280
Chris Craikd41c4d82015-01-05 15:51:13 -0800281 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const override {
Chris Craik2af46352012-11-26 18:30:17 -0800282 renderer.save(mFlags);
283 }
284
Chris Craikd41c4d82015-01-05 15:51:13 -0800285 virtual void output(int level, uint32_t logFlags) const override {
Chris Craik2af46352012-11-26 18:30:17 -0800286 OP_LOG("Save flags %x", mFlags);
287 }
288
Chris Craikd41c4d82015-01-05 15:51:13 -0800289 virtual const char* name() override { return "Save"; }
Chris Craik2af46352012-11-26 18:30:17 -0800290
Chris Craikff785832013-03-08 13:12:16 -0800291 int getFlags() const { return mFlags; }
Chris Craik2af46352012-11-26 18:30:17 -0800292private:
293 int mFlags;
294};
295
296class RestoreToCountOp : public StateOp {
297public:
298 RestoreToCountOp(int count)
299 : mCount(count) {}
300
Andreas Gampe64bb4132014-11-22 00:35:09 +0000301 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
Chris Craikd41c4d82015-01-05 15:51:13 -0800302 bool useQuickReject) override {
Chris Craik7273daa2013-03-28 11:25:24 -0700303 deferStruct.mDeferredList.addRestoreToCount(deferStruct.mRenderer,
304 this, saveCount + mCount);
Chris Craikff785832013-03-08 13:12:16 -0800305 deferStruct.mRenderer.restoreToCount(saveCount + mCount);
Chris Craik2af46352012-11-26 18:30:17 -0800306 }
307
Chris Craikd41c4d82015-01-05 15:51:13 -0800308 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const override {
Chris Craikff785832013-03-08 13:12:16 -0800309 renderer.restoreToCount(saveCount + mCount);
310 }
311
Chris Craikd41c4d82015-01-05 15:51:13 -0800312 virtual void output(int level, uint32_t logFlags) const override {
Chris Craik2af46352012-11-26 18:30:17 -0800313 OP_LOG("Restore to count %d", mCount);
314 }
315
Chris Craikd41c4d82015-01-05 15:51:13 -0800316 virtual const char* name() override { return "RestoreToCount"; }
Chris Craik2af46352012-11-26 18:30:17 -0800317
318private:
319 int mCount;
320};
321
322class SaveLayerOp : public StateOp {
323public:
Derek Sollenbergerd44fbe52014-02-05 16:47:00 -0500324 SaveLayerOp(float left, float top, float right, float bottom, int alpha, int flags)
Chris Craik3f0854292014-04-15 16:18:08 -0700325 : mArea(left, top, right, bottom)
326 , mPaint(&mCachedPaint)
327 , mFlags(flags)
Chris Craikd41c4d82015-01-05 15:51:13 -0800328 , mConvexMask(nullptr) {
Derek Sollenbergerd44fbe52014-02-05 16:47:00 -0500329 mCachedPaint.setAlpha(alpha);
330 }
331
332 SaveLayerOp(float left, float top, float right, float bottom, const SkPaint* paint, int flags)
Chris Craik3f0854292014-04-15 16:18:08 -0700333 : mArea(left, top, right, bottom)
334 , mPaint(paint)
335 , mFlags(flags)
Chris Craikd41c4d82015-01-05 15:51:13 -0800336 , mConvexMask(nullptr)
Chris Craik3f0854292014-04-15 16:18:08 -0700337 {}
Chris Craikff785832013-03-08 13:12:16 -0800338
Andreas Gampe64bb4132014-11-22 00:35:09 +0000339 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
Chris Craikd41c4d82015-01-05 15:51:13 -0800340 bool useQuickReject) override {
Chris Craikff785832013-03-08 13:12:16 -0800341 // NOTE: don't bother with actual saveLayer, instead issuing it at flush time
Chris Craikd90144d2013-03-19 15:03:48 -0700342 int newSaveCount = deferStruct.mRenderer.getSaveCount();
Chris Craikff785832013-03-08 13:12:16 -0800343 deferStruct.mDeferredList.addSaveLayer(deferStruct.mRenderer, this, newSaveCount);
Chris Craikd90144d2013-03-19 15:03:48 -0700344
345 // NOTE: don't issue full saveLayer, since that has side effects/is costly. instead just
346 // setup the snapshot for deferral, and re-issue the op at flush time
347 deferStruct.mRenderer.saveLayerDeferred(mArea.left, mArea.top, mArea.right, mArea.bottom,
Derek Sollenbergerd44fbe52014-02-05 16:47:00 -0500348 mPaint, mFlags);
Chris Craikff785832013-03-08 13:12:16 -0800349 }
Chris Craik2af46352012-11-26 18:30:17 -0800350
Chris Craikd41c4d82015-01-05 15:51:13 -0800351 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const override {
Chris Craik3f0854292014-04-15 16:18:08 -0700352 renderer.saveLayer(mArea.left, mArea.top, mArea.right, mArea.bottom,
353 mPaint, mFlags, mConvexMask);
Chris Craik2af46352012-11-26 18:30:17 -0800354 }
355
Chris Craikd41c4d82015-01-05 15:51:13 -0800356 virtual void output(int level, uint32_t logFlags) const override {
Chris Craikff785832013-03-08 13:12:16 -0800357 OP_LOG("SaveLayer%s of area " RECT_STRING,
358 (isSaveLayerAlpha() ? "Alpha" : ""),RECT_ARGS(mArea));
Chris Craik2af46352012-11-26 18:30:17 -0800359 }
360
Chris Craikd41c4d82015-01-05 15:51:13 -0800361 virtual const char* name() override {
362 return isSaveLayerAlpha() ? "SaveLayerAlpha" : "SaveLayer";
363 }
Chris Craikff785832013-03-08 13:12:16 -0800364
365 int getFlags() { return mFlags; }
Chris Craik2af46352012-11-26 18:30:17 -0800366
Chris Craik3f0854292014-04-15 16:18:08 -0700367 // Called to make SaveLayerOp clip to the provided mask when drawing back/restored
368 void setMask(const SkPath* convexMask) {
369 mConvexMask = convexMask;
370 }
371
Chris Craik2af46352012-11-26 18:30:17 -0800372private:
Derek Sollenbergerd44fbe52014-02-05 16:47:00 -0500373 bool isSaveLayerAlpha() const {
Chris Craikbf6f0f22015-10-01 12:36:07 -0700374 SkXfermode::Mode mode = PaintUtils::getXfermodeDirect(mPaint);
375 int alpha = PaintUtils::getAlphaDirect(mPaint);
Derek Sollenbergerd44fbe52014-02-05 16:47:00 -0500376 return alpha < 255 && mode == SkXfermode::kSrcOver_Mode;
Chris Craik2af46352012-11-26 18:30:17 -0800377 }
378
Chris Craik2af46352012-11-26 18:30:17 -0800379 Rect mArea;
Derek Sollenbergerd44fbe52014-02-05 16:47:00 -0500380 const SkPaint* mPaint;
381 SkPaint mCachedPaint;
Chris Craik2af46352012-11-26 18:30:17 -0800382 int mFlags;
Chris Craik3f0854292014-04-15 16:18:08 -0700383
384 // Convex path, points at data in RenderNode, valid for the duration of the frame only
385 // Only used for masking the SaveLayer which wraps projected RenderNodes
386 const SkPath* mConvexMask;
Chris Craik2af46352012-11-26 18:30:17 -0800387};
388
389class TranslateOp : public StateOp {
390public:
391 TranslateOp(float dx, float dy)
392 : mDx(dx), mDy(dy) {}
393
Chris Craikd41c4d82015-01-05 15:51:13 -0800394 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const override {
Chris Craik2af46352012-11-26 18:30:17 -0800395 renderer.translate(mDx, mDy);
396 }
397
Chris Craikd41c4d82015-01-05 15:51:13 -0800398 virtual void output(int level, uint32_t logFlags) const override {
Chris Craik2af46352012-11-26 18:30:17 -0800399 OP_LOG("Translate by %f %f", mDx, mDy);
400 }
401
Chris Craikd41c4d82015-01-05 15:51:13 -0800402 virtual const char* name() override { return "Translate"; }
Chris Craik2af46352012-11-26 18:30:17 -0800403
404private:
405 float mDx;
406 float mDy;
407};
408
409class RotateOp : public StateOp {
410public:
411 RotateOp(float degrees)
412 : mDegrees(degrees) {}
413
Chris Craikd41c4d82015-01-05 15:51:13 -0800414 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const override {
Chris Craik2af46352012-11-26 18:30:17 -0800415 renderer.rotate(mDegrees);
416 }
417
Chris Craikd41c4d82015-01-05 15:51:13 -0800418 virtual void output(int level, uint32_t logFlags) const override {
Chris Craik2af46352012-11-26 18:30:17 -0800419 OP_LOG("Rotate by %f degrees", mDegrees);
420 }
421
Chris Craikd41c4d82015-01-05 15:51:13 -0800422 virtual const char* name() override { return "Rotate"; }
Chris Craik2af46352012-11-26 18:30:17 -0800423
424private:
425 float mDegrees;
426};
427
428class ScaleOp : public StateOp {
429public:
430 ScaleOp(float sx, float sy)
431 : mSx(sx), mSy(sy) {}
432
Chris Craikd41c4d82015-01-05 15:51:13 -0800433 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const override {
Chris Craik2af46352012-11-26 18:30:17 -0800434 renderer.scale(mSx, mSy);
435 }
436
Chris Craikd41c4d82015-01-05 15:51:13 -0800437 virtual void output(int level, uint32_t logFlags) const override {
Chris Craik2af46352012-11-26 18:30:17 -0800438 OP_LOG("Scale by %f %f", mSx, mSy);
439 }
440
Chris Craikd41c4d82015-01-05 15:51:13 -0800441 virtual const char* name() override { return "Scale"; }
Chris Craik2af46352012-11-26 18:30:17 -0800442
443private:
444 float mSx;
445 float mSy;
446};
447
448class SkewOp : public StateOp {
449public:
450 SkewOp(float sx, float sy)
451 : mSx(sx), mSy(sy) {}
452
Chris Craikd41c4d82015-01-05 15:51:13 -0800453 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const override {
Chris Craik2af46352012-11-26 18:30:17 -0800454 renderer.skew(mSx, mSy);
455 }
456
Chris Craikd41c4d82015-01-05 15:51:13 -0800457 virtual void output(int level, uint32_t logFlags) const override {
Chris Craik2af46352012-11-26 18:30:17 -0800458 OP_LOG("Skew by %f %f", mSx, mSy);
459 }
460
Chris Craikd41c4d82015-01-05 15:51:13 -0800461 virtual const char* name() override { return "Skew"; }
Chris Craik2af46352012-11-26 18:30:17 -0800462
463private:
464 float mSx;
465 float mSy;
466};
467
468class SetMatrixOp : public StateOp {
469public:
Derek Sollenberger13908822013-12-10 12:28:58 -0500470 SetMatrixOp(const SkMatrix& matrix)
Chris Craik2af46352012-11-26 18:30:17 -0800471 : mMatrix(matrix) {}
472
Chris Craikd41c4d82015-01-05 15:51:13 -0800473 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const override {
Chris Craik6daa13c2015-08-19 13:32:12 -0700474 // Setting a matrix on a Canvas isn't equivalent to setting a total matrix on the scene.
475 // Set a canvas-relative matrix on the renderer instead.
476 renderer.setLocalMatrix(mMatrix);
Chris Craik2af46352012-11-26 18:30:17 -0800477 }
478
Chris Craikd41c4d82015-01-05 15:51:13 -0800479 virtual void output(int level, uint32_t logFlags) const override {
Derek Sollenberger13908822013-12-10 12:28:58 -0500480 if (mMatrix.isIdentity()) {
Romain Guy4e7b7722013-07-16 13:47:01 -0700481 OP_LOGS("SetMatrix (reset)");
Derek Sollenberger13908822013-12-10 12:28:58 -0500482 } else {
483 OP_LOG("SetMatrix " SK_MATRIX_STRING, SK_MATRIX_ARGS(&mMatrix));
Romain Guy4e7b7722013-07-16 13:47:01 -0700484 }
Chris Craik2af46352012-11-26 18:30:17 -0800485 }
486
Chris Craikd41c4d82015-01-05 15:51:13 -0800487 virtual const char* name() override { return "SetMatrix"; }
Chris Craik2af46352012-11-26 18:30:17 -0800488
489private:
Derek Sollenberger13908822013-12-10 12:28:58 -0500490 const SkMatrix mMatrix;
Chris Craik2af46352012-11-26 18:30:17 -0800491};
492
493class ConcatMatrixOp : public StateOp {
494public:
Derek Sollenberger13908822013-12-10 12:28:58 -0500495 ConcatMatrixOp(const SkMatrix& matrix)
Chris Craik2af46352012-11-26 18:30:17 -0800496 : mMatrix(matrix) {}
497
Chris Craikd41c4d82015-01-05 15:51:13 -0800498 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const override {
Chris Craik2af46352012-11-26 18:30:17 -0800499 renderer.concatMatrix(mMatrix);
500 }
501
Chris Craikd41c4d82015-01-05 15:51:13 -0800502 virtual void output(int level, uint32_t logFlags) const override {
Derek Sollenberger13908822013-12-10 12:28:58 -0500503 OP_LOG("ConcatMatrix " SK_MATRIX_STRING, SK_MATRIX_ARGS(&mMatrix));
Chris Craik2af46352012-11-26 18:30:17 -0800504 }
505
Chris Craikd41c4d82015-01-05 15:51:13 -0800506 virtual const char* name() override { return "ConcatMatrix"; }
Chris Craik2af46352012-11-26 18:30:17 -0800507
508private:
Derek Sollenberger13908822013-12-10 12:28:58 -0500509 const SkMatrix mMatrix;
Chris Craik2af46352012-11-26 18:30:17 -0800510};
511
Chris Craikff785832013-03-08 13:12:16 -0800512class ClipOp : public StateOp {
513public:
514 ClipOp(SkRegion::Op op) : mOp(op) {}
515
Andreas Gampe64bb4132014-11-22 00:35:09 +0000516 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
Chris Craikd41c4d82015-01-05 15:51:13 -0800517 bool useQuickReject) override {
Chris Craikff785832013-03-08 13:12:16 -0800518 // NOTE: must defer op BEFORE applying state, since it may read clip
519 deferStruct.mDeferredList.addClip(deferStruct.mRenderer, this);
520
521 // TODO: Can we avoid applying complex clips at defer time?
522 applyState(deferStruct.mRenderer, saveCount);
523 }
524
525 bool canCauseComplexClip() {
526 return ((mOp != SkRegion::kIntersect_Op) && (mOp != SkRegion::kReplace_Op)) || !isRect();
527 }
528
529protected:
Chris Craikff785832013-03-08 13:12:16 -0800530 virtual bool isRect() { return false; }
531
532 SkRegion::Op mOp;
533};
534
535class ClipRectOp : public ClipOp {
Chris Craik2af46352012-11-26 18:30:17 -0800536public:
537 ClipRectOp(float left, float top, float right, float bottom, SkRegion::Op op)
Chris Craikff785832013-03-08 13:12:16 -0800538 : ClipOp(op), mArea(left, top, right, bottom) {}
Chris Craik2af46352012-11-26 18:30:17 -0800539
Chris Craikd41c4d82015-01-05 15:51:13 -0800540 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const override {
Chris Craik2af46352012-11-26 18:30:17 -0800541 renderer.clipRect(mArea.left, mArea.top, mArea.right, mArea.bottom, mOp);
542 }
543
Chris Craikd41c4d82015-01-05 15:51:13 -0800544 virtual void output(int level, uint32_t logFlags) const override {
Chris Craik2af46352012-11-26 18:30:17 -0800545 OP_LOG("ClipRect " RECT_STRING, RECT_ARGS(mArea));
546 }
547
Chris Craikd41c4d82015-01-05 15:51:13 -0800548 virtual const char* name() override { return "ClipRect"; }
Chris Craik2af46352012-11-26 18:30:17 -0800549
Chris Craikff785832013-03-08 13:12:16 -0800550protected:
Chris Craikd41c4d82015-01-05 15:51:13 -0800551 virtual bool isRect() override { return true; }
Chris Craikb98a0162013-02-21 11:30:22 -0800552
Chris Craik2af46352012-11-26 18:30:17 -0800553private:
554 Rect mArea;
Chris Craik2af46352012-11-26 18:30:17 -0800555};
556
Chris Craikff785832013-03-08 13:12:16 -0800557class ClipPathOp : public ClipOp {
Chris Craik2af46352012-11-26 18:30:17 -0800558public:
Chris Craikd218a922014-01-02 17:13:34 -0800559 ClipPathOp(const SkPath* path, SkRegion::Op op)
Chris Craikff785832013-03-08 13:12:16 -0800560 : ClipOp(op), mPath(path) {}
Chris Craik2af46352012-11-26 18:30:17 -0800561
Chris Craikd41c4d82015-01-05 15:51:13 -0800562 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const override {
Chris Craik2af46352012-11-26 18:30:17 -0800563 renderer.clipPath(mPath, mOp);
564 }
565
Chris Craikd41c4d82015-01-05 15:51:13 -0800566 virtual void output(int level, uint32_t logFlags) const override {
Chris Craik2af46352012-11-26 18:30:17 -0800567 SkRect bounds = mPath->getBounds();
568 OP_LOG("ClipPath bounds " RECT_STRING,
569 bounds.left(), bounds.top(), bounds.right(), bounds.bottom());
570 }
571
Chris Craikd41c4d82015-01-05 15:51:13 -0800572 virtual const char* name() override { return "ClipPath"; }
Chris Craik2af46352012-11-26 18:30:17 -0800573
574private:
Chris Craikd218a922014-01-02 17:13:34 -0800575 const SkPath* mPath;
Chris Craik2af46352012-11-26 18:30:17 -0800576};
577
Chris Craikff785832013-03-08 13:12:16 -0800578class ClipRegionOp : public ClipOp {
Chris Craik2af46352012-11-26 18:30:17 -0800579public:
Chris Craikd218a922014-01-02 17:13:34 -0800580 ClipRegionOp(const SkRegion* region, SkRegion::Op op)
Chris Craikff785832013-03-08 13:12:16 -0800581 : ClipOp(op), mRegion(region) {}
Chris Craik2af46352012-11-26 18:30:17 -0800582
Chris Craikd41c4d82015-01-05 15:51:13 -0800583 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const override {
Chris Craik2af46352012-11-26 18:30:17 -0800584 renderer.clipRegion(mRegion, mOp);
585 }
586
Chris Craikd41c4d82015-01-05 15:51:13 -0800587 virtual void output(int level, uint32_t logFlags) const override {
Chris Craik2af46352012-11-26 18:30:17 -0800588 SkIRect bounds = mRegion->getBounds();
589 OP_LOG("ClipRegion bounds %d %d %d %d",
590 bounds.left(), bounds.top(), bounds.right(), bounds.bottom());
591 }
592
Chris Craikd41c4d82015-01-05 15:51:13 -0800593 virtual const char* name() override { return "ClipRegion"; }
Chris Craik2af46352012-11-26 18:30:17 -0800594
595private:
Chris Craikd218a922014-01-02 17:13:34 -0800596 const SkRegion* mRegion;
Chris Craik2af46352012-11-26 18:30:17 -0800597};
598
Chris Craik2af46352012-11-26 18:30:17 -0800599///////////////////////////////////////////////////////////////////////////////
600// DRAW OPERATIONS - these are operations that can draw to the canvas's device
601///////////////////////////////////////////////////////////////////////////////
602
603class DrawBitmapOp : public DrawBoundedOp {
604public:
Chris Craik79647502014-08-06 13:42:24 -0700605 DrawBitmapOp(const SkBitmap* bitmap, const SkPaint* paint)
606 : DrawBoundedOp(0, 0, bitmap->width(), bitmap->height(), paint)
607 , mBitmap(bitmap)
Chris Craikd41c4d82015-01-05 15:51:13 -0800608 , mEntryValid(false), mEntry(nullptr) {
Romain Guy3b748a42013-04-17 18:54:38 -0700609 }
Chris Craik2af46352012-11-26 18:30:17 -0800610
Chris Craikd41c4d82015-01-05 15:51:13 -0800611 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
Tom Hudson107843d2014-09-08 11:26:26 -0400612 renderer.drawBitmap(mBitmap, mPaint);
Chris Craik2af46352012-11-26 18:30:17 -0800613 }
614
John Reckebd52612014-12-10 16:47:36 -0800615 AssetAtlas::Entry* getAtlasEntry(OpenGLRenderer& renderer) {
616 if (!mEntryValid) {
617 mEntryValid = true;
Chris Craik15c3f192015-12-03 12:16:56 -0800618 mEntry = renderer.renderState().assetAtlas().getEntry(mBitmap->pixelRef());
Romain Guy55b6f952013-06-27 15:27:09 -0700619 }
620 return mEntry;
621 }
622
Chris Craik527a3aa2013-03-04 10:19:31 -0800623#define SET_TEXTURE(ptr, posRect, offsetRect, texCoordsRect, xDim, yDim) \
624 TextureVertex::set(ptr++, posRect.xDim - offsetRect.left, posRect.yDim - offsetRect.top, \
625 texCoordsRect.xDim, texCoordsRect.yDim)
626
Romain Guy03c00b52013-06-20 18:30:28 -0700627 /**
628 * This multi-draw operation builds a mesh on the stack by generating a quad
629 * for each bitmap in the batch. This method is also responsible for dirtying
630 * the current layer, if any.
631 */
Andreas Gampe64bb4132014-11-22 00:35:09 +0000632 virtual void multiDraw(OpenGLRenderer& renderer, Rect& dirty,
John Reck272a6852015-07-29 16:48:58 -0700633 const std::vector<OpStatePair>& ops, const Rect& bounds) override {
Chris Craikc1c5f082013-09-11 16:23:37 -0700634 const DeferredDisplayState& firstState = *(ops[0].state);
635 renderer.restoreDisplayState(firstState, true); // restore all but the clip
636
Chris Craik527a3aa2013-03-04 10:19:31 -0800637 TextureVertex vertices[6 * ops.size()];
638 TextureVertex* vertex = &vertices[0];
639
Romain Guy03c00b52013-06-20 18:30:28 -0700640 const bool hasLayer = renderer.hasLayer();
Chris Craik996fe652013-09-20 17:13:18 -0700641 bool pureTranslate = true;
Romain Guy2db5e992013-05-21 15:29:59 -0700642
Romain Guy3b748a42013-04-17 18:54:38 -0700643 // TODO: manually handle rect clip for bitmaps by adjusting texCoords per op,
644 // and allowing them to be merged in getBatchId()
Chris Craik527a3aa2013-03-04 10:19:31 -0800645 for (unsigned int i = 0; i < ops.size(); i++) {
Chris Craikc1c5f082013-09-11 16:23:37 -0700646 const DeferredDisplayState& state = *(ops[i].state);
647 const Rect& opBounds = state.mBounds;
Romain Guy2db5e992013-05-21 15:29:59 -0700648 // When we reach multiDraw(), the matrix can be either
649 // pureTranslate or simple (translate and/or scale).
650 // If the matrix is not pureTranslate, then we have a scale
Chris Craik996fe652013-09-20 17:13:18 -0700651 pureTranslate &= state.mMatrix.isPureTranslate();
Romain Guy3b748a42013-04-17 18:54:38 -0700652
653 Rect texCoords(0, 0, 1, 1);
John Reckebd52612014-12-10 16:47:36 -0800654 ((DrawBitmapOp*) ops[i].op)->uvMap(renderer, texCoords);
Romain Guy3b748a42013-04-17 18:54:38 -0700655
Chris Craik527a3aa2013-03-04 10:19:31 -0800656 SET_TEXTURE(vertex, opBounds, bounds, texCoords, left, top);
657 SET_TEXTURE(vertex, opBounds, bounds, texCoords, right, top);
658 SET_TEXTURE(vertex, opBounds, bounds, texCoords, left, bottom);
659
660 SET_TEXTURE(vertex, opBounds, bounds, texCoords, left, bottom);
661 SET_TEXTURE(vertex, opBounds, bounds, texCoords, right, top);
662 SET_TEXTURE(vertex, opBounds, bounds, texCoords, right, bottom);
Romain Guy03c00b52013-06-20 18:30:28 -0700663
664 if (hasLayer) {
Chris Craikc1c5f082013-09-11 16:23:37 -0700665 renderer.dirtyLayer(opBounds.left, opBounds.top, opBounds.right, opBounds.bottom);
Romain Guy03c00b52013-06-20 18:30:28 -0700666 }
Chris Craik527a3aa2013-03-04 10:19:31 -0800667 }
668
Tom Hudson107843d2014-09-08 11:26:26 -0400669 renderer.drawBitmaps(mBitmap, mEntry, ops.size(), &vertices[0],
Chris Craik996fe652013-09-20 17:13:18 -0700670 pureTranslate, bounds, mPaint);
Chris Craik527a3aa2013-03-04 10:19:31 -0800671 }
672
Chris Craikd41c4d82015-01-05 15:51:13 -0800673 virtual void output(int level, uint32_t logFlags) const override {
Chris Craik0519c812015-02-11 13:17:06 -0800674 OP_LOG("Draw bitmap %p of size %dx%d%s",
675 mBitmap, mBitmap->width(), mBitmap->height(),
John Reckdad7d84c2014-12-09 12:33:26 -0800676 mEntry ? " using AssetAtlas" : "");
Chris Craik2af46352012-11-26 18:30:17 -0800677 }
678
Chris Craikd41c4d82015-01-05 15:51:13 -0800679 virtual const char* name() override { return "DrawBitmap"; }
Chris Craik527a3aa2013-03-04 10:19:31 -0800680
Andreas Gampe64bb4132014-11-22 00:35:09 +0000681 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
Chris Craikd41c4d82015-01-05 15:51:13 -0800682 const DeferredDisplayState& state) override {
Chris Craik28ce94a2013-05-31 11:38:03 -0700683 deferInfo.batchId = DeferredDisplayList::kOpBatch_Bitmap;
John Reckebd52612014-12-10 16:47:36 -0800684 deferInfo.mergeId = getAtlasEntry(renderer) ?
Chris Craikd965bc52013-09-16 14:47:13 -0700685 (mergeid_t) mEntry->getMergeId() : (mergeid_t) mBitmap;
Romain Guy2db5e992013-05-21 15:29:59 -0700686
Chris Craikd965bc52013-09-16 14:47:13 -0700687 // Don't merge non-simply transformed or neg scale ops, SET_TEXTURE doesn't handle rotation
Chris Craik28ce94a2013-05-31 11:38:03 -0700688 // Don't merge A8 bitmaps - the paint's color isn't compared by mergeId, or in
689 // MergingDrawBatch::canMergeWith()
690 // TODO: support clipped bitmaps by handling them in SET_TEXTURE
Chris Craikd965bc52013-09-16 14:47:13 -0700691 deferInfo.mergeable = state.mMatrix.isSimple() && state.mMatrix.positiveScale() &&
692 !state.mClipSideFlags &&
Chris Craikbf6f0f22015-10-01 12:36:07 -0700693 PaintUtils::getXfermodeDirect(mPaint) == SkXfermode::kSrcOver_Mode &&
Mike Reed1103b322014-07-08 12:36:44 -0400694 (mBitmap->colorType() != kAlpha_8_SkColorType);
Chris Craikc3566d02013-02-04 16:16:33 -0800695 }
Chris Craik2af46352012-11-26 18:30:17 -0800696
John Reckebd52612014-12-10 16:47:36 -0800697 void uvMap(OpenGLRenderer& renderer, Rect& texCoords) {
698 if (getAtlasEntry(renderer)) {
699 mEntry->uvMapper.map(texCoords);
700 }
701 }
702
Chris Craik527a3aa2013-03-04 10:19:31 -0800703 const SkBitmap* bitmap() { return mBitmap; }
Chris Craik2af46352012-11-26 18:30:17 -0800704protected:
Chris Craikd218a922014-01-02 17:13:34 -0800705 const SkBitmap* mBitmap;
John Reckebd52612014-12-10 16:47:36 -0800706 bool mEntryValid;
Romain Guy55b6f952013-06-27 15:27:09 -0700707 AssetAtlas::Entry* mEntry;
Chris Craik2af46352012-11-26 18:30:17 -0800708};
709
Chris Craik2af46352012-11-26 18:30:17 -0800710class DrawBitmapRectOp : public DrawBoundedOp {
711public:
Chris Craikd218a922014-01-02 17:13:34 -0800712 DrawBitmapRectOp(const SkBitmap* bitmap,
713 float srcLeft, float srcTop, float srcRight, float srcBottom,
714 float dstLeft, float dstTop, float dstRight, float dstBottom, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -0800715 : DrawBoundedOp(dstLeft, dstTop, dstRight, dstBottom, paint),
716 mBitmap(bitmap), mSrc(srcLeft, srcTop, srcRight, srcBottom) {}
717
Chris Craikd41c4d82015-01-05 15:51:13 -0800718 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
Chris Craik14100ac2015-02-24 13:46:29 -0800719 renderer.drawBitmap(mBitmap, mSrc, mLocalBounds, mPaint);
Chris Craik2af46352012-11-26 18:30:17 -0800720 }
721
Chris Craikd41c4d82015-01-05 15:51:13 -0800722 virtual void output(int level, uint32_t logFlags) const override {
John Reckce444ca2014-06-02 15:12:36 -0700723 OP_LOG("Draw bitmap %p src=" RECT_STRING ", dst=" RECT_STRING,
Chris Craik2af46352012-11-26 18:30:17 -0800724 mBitmap, RECT_ARGS(mSrc), RECT_ARGS(mLocalBounds));
725 }
726
Chris Craikd41c4d82015-01-05 15:51:13 -0800727 virtual const char* name() override { return "DrawBitmapRect"; }
Chris Craik527a3aa2013-03-04 10:19:31 -0800728
Andreas Gampe64bb4132014-11-22 00:35:09 +0000729 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
Chris Craikd41c4d82015-01-05 15:51:13 -0800730 const DeferredDisplayState& state) override {
Chris Craik28ce94a2013-05-31 11:38:03 -0700731 deferInfo.batchId = DeferredDisplayList::kOpBatch_Bitmap;
Chris Craikc3566d02013-02-04 16:16:33 -0800732 }
Chris Craik2af46352012-11-26 18:30:17 -0800733
734private:
Chris Craikd218a922014-01-02 17:13:34 -0800735 const SkBitmap* mBitmap;
Chris Craik2af46352012-11-26 18:30:17 -0800736 Rect mSrc;
737};
738
Chris Craik5d116762013-02-19 17:49:31 -0800739class DrawBitmapMeshOp : public DrawBoundedOp {
Chris Craik2af46352012-11-26 18:30:17 -0800740public:
Chris Craikd218a922014-01-02 17:13:34 -0800741 DrawBitmapMeshOp(const SkBitmap* bitmap, int meshWidth, int meshHeight,
742 const float* vertices, const int* colors, const SkPaint* paint)
Chris Craik5d116762013-02-19 17:49:31 -0800743 : DrawBoundedOp(vertices, 2 * (meshWidth + 1) * (meshHeight + 1), paint),
744 mBitmap(bitmap), mMeshWidth(meshWidth), mMeshHeight(meshHeight),
Chris Craik2af46352012-11-26 18:30:17 -0800745 mVertices(vertices), mColors(colors) {}
746
Chris Craikd41c4d82015-01-05 15:51:13 -0800747 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
Tom Hudson107843d2014-09-08 11:26:26 -0400748 renderer.drawBitmapMesh(mBitmap, mMeshWidth, mMeshHeight,
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -0400749 mVertices, mColors, mPaint);
Chris Craik2af46352012-11-26 18:30:17 -0800750 }
751
Chris Craikd41c4d82015-01-05 15:51:13 -0800752 virtual void output(int level, uint32_t logFlags) const override {
Chris Craik2af46352012-11-26 18:30:17 -0800753 OP_LOG("Draw bitmap %p mesh %d x %d", mBitmap, mMeshWidth, mMeshHeight);
754 }
755
Chris Craikd41c4d82015-01-05 15:51:13 -0800756 virtual const char* name() override { return "DrawBitmapMesh"; }
Chris Craik527a3aa2013-03-04 10:19:31 -0800757
Andreas Gampe64bb4132014-11-22 00:35:09 +0000758 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
Chris Craikd41c4d82015-01-05 15:51:13 -0800759 const DeferredDisplayState& state) override {
Chris Craik28ce94a2013-05-31 11:38:03 -0700760 deferInfo.batchId = DeferredDisplayList::kOpBatch_Bitmap;
Chris Craikc3566d02013-02-04 16:16:33 -0800761 }
Chris Craik2af46352012-11-26 18:30:17 -0800762
763private:
Chris Craikd218a922014-01-02 17:13:34 -0800764 const SkBitmap* mBitmap;
Chris Craik2af46352012-11-26 18:30:17 -0800765 int mMeshWidth;
766 int mMeshHeight;
Chris Craikd218a922014-01-02 17:13:34 -0800767 const float* mVertices;
768 const int* mColors;
Chris Craik2af46352012-11-26 18:30:17 -0800769};
770
771class DrawPatchOp : public DrawBoundedOp {
772public:
Chris Craikd218a922014-01-02 17:13:34 -0800773 DrawPatchOp(const SkBitmap* bitmap, const Res_png_9patch* patch,
774 float left, float top, float right, float bottom, const SkPaint* paint)
Romain Guy03c00b52013-06-20 18:30:28 -0700775 : DrawBoundedOp(left, top, right, bottom, paint),
Chris Craikd41c4d82015-01-05 15:51:13 -0800776 mBitmap(bitmap), mPatch(patch), mGenerationId(0), mMesh(nullptr),
777 mEntryValid(false), mEntry(nullptr) {
Romain Guy3b748a42013-04-17 18:54:38 -0700778 };
Chris Craik2af46352012-11-26 18:30:17 -0800779
John Reckebd52612014-12-10 16:47:36 -0800780 AssetAtlas::Entry* getAtlasEntry(OpenGLRenderer& renderer) {
781 if (!mEntryValid) {
782 mEntryValid = true;
Chris Craik15c3f192015-12-03 12:16:56 -0800783 mEntry = renderer.renderState().assetAtlas().getEntry(mBitmap->pixelRef());
Romain Guy55b6f952013-06-27 15:27:09 -0700784 }
785 return mEntry;
786 }
787
Romain Guy03c00b52013-06-20 18:30:28 -0700788 const Patch* getMesh(OpenGLRenderer& renderer) {
Romain Guy4c2547f2013-06-11 16:19:24 -0700789 if (!mMesh || renderer.getCaches().patchCache.getGenerationId() != mGenerationId) {
790 PatchCache& cache = renderer.getCaches().patchCache;
John Reckebd52612014-12-10 16:47:36 -0800791 mMesh = cache.get(getAtlasEntry(renderer), mBitmap->width(), mBitmap->height(),
Romain Guy03c00b52013-06-20 18:30:28 -0700792 mLocalBounds.getWidth(), mLocalBounds.getHeight(), mPatch);
Romain Guy4c2547f2013-06-11 16:19:24 -0700793 mGenerationId = cache.getGenerationId();
794 }
Romain Guy03c00b52013-06-20 18:30:28 -0700795 return mMesh;
796 }
797
798 /**
799 * This multi-draw operation builds an indexed mesh on the stack by copying
800 * and transforming the vertices of each 9-patch in the batch. This method
801 * is also responsible for dirtying the current layer, if any.
802 */
Andreas Gampe64bb4132014-11-22 00:35:09 +0000803 virtual void multiDraw(OpenGLRenderer& renderer, Rect& dirty,
John Reck272a6852015-07-29 16:48:58 -0700804 const std::vector<OpStatePair>& ops, const Rect& bounds) override {
Chris Craikc1c5f082013-09-11 16:23:37 -0700805 const DeferredDisplayState& firstState = *(ops[0].state);
806 renderer.restoreDisplayState(firstState, true); // restore all but the clip
Romain Guy03c00b52013-06-20 18:30:28 -0700807
808 // Batches will usually contain a small number of items so it's
809 // worth performing a first iteration to count the exact number
810 // of vertices we need in the new mesh
811 uint32_t totalVertices = 0;
812 for (unsigned int i = 0; i < ops.size(); i++) {
Chris Craikc1c5f082013-09-11 16:23:37 -0700813 totalVertices += ((DrawPatchOp*) ops[i].op)->getMesh(renderer)->verticesCount;
Romain Guy03c00b52013-06-20 18:30:28 -0700814 }
815
816 const bool hasLayer = renderer.hasLayer();
817
818 uint32_t indexCount = 0;
819
820 TextureVertex vertices[totalVertices];
821 TextureVertex* vertex = &vertices[0];
822
823 // Create a mesh that contains the transformed vertices for all the
824 // 9-patch objects that are part of the batch. Note that onDefer()
825 // enforces ops drawn by this function to have a pure translate or
826 // identity matrix
827 for (unsigned int i = 0; i < ops.size(); i++) {
Chris Craikc1c5f082013-09-11 16:23:37 -0700828 DrawPatchOp* patchOp = (DrawPatchOp*) ops[i].op;
829 const DeferredDisplayState* state = ops[i].state;
Romain Guy03c00b52013-06-20 18:30:28 -0700830 const Patch* opMesh = patchOp->getMesh(renderer);
831 uint32_t vertexCount = opMesh->verticesCount;
832 if (vertexCount == 0) continue;
833
834 // We use the bounds to know where to translate our vertices
835 // Using patchOp->state.mBounds wouldn't work because these
836 // bounds are clipped
Chris Craikc1c5f082013-09-11 16:23:37 -0700837 const float tx = (int) floorf(state->mMatrix.getTranslateX() +
Romain Guy03c00b52013-06-20 18:30:28 -0700838 patchOp->mLocalBounds.left + 0.5f);
Chris Craikc1c5f082013-09-11 16:23:37 -0700839 const float ty = (int) floorf(state->mMatrix.getTranslateY() +
Romain Guy03c00b52013-06-20 18:30:28 -0700840 patchOp->mLocalBounds.top + 0.5f);
841
842 // Copy & transform all the vertices for the current operation
Chris Craik51d6a3d2014-12-22 17:16:56 -0800843 TextureVertex* opVertices = opMesh->vertices.get();
Romain Guy03c00b52013-06-20 18:30:28 -0700844 for (uint32_t j = 0; j < vertexCount; j++, opVertices++) {
845 TextureVertex::set(vertex++,
Romain Guy3380cfd2013-08-15 16:57:57 -0700846 opVertices->x + tx, opVertices->y + ty,
847 opVertices->u, opVertices->v);
Romain Guy03c00b52013-06-20 18:30:28 -0700848 }
849
850 // Dirty the current layer if possible. When the 9-patch does not
851 // contain empty quads we can take a shortcut and simply set the
852 // dirty rect to the object's bounds.
853 if (hasLayer) {
854 if (!opMesh->hasEmptyQuads) {
855 renderer.dirtyLayer(tx, ty,
856 tx + patchOp->mLocalBounds.getWidth(),
857 ty + patchOp->mLocalBounds.getHeight());
858 } else {
859 const size_t count = opMesh->quads.size();
860 for (size_t i = 0; i < count; i++) {
861 const Rect& quadBounds = opMesh->quads[i];
862 const float x = tx + quadBounds.left;
863 const float y = ty + quadBounds.top;
864 renderer.dirtyLayer(x, y,
865 x + quadBounds.getWidth(), y + quadBounds.getHeight());
866 }
867 }
868 }
869
870 indexCount += opMesh->indexCount;
871 }
872
Yohann Roussel59cf7342014-12-11 11:10:50 +0100873 renderer.drawPatches(mBitmap, getAtlasEntry(renderer),
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -0400874 &vertices[0], indexCount, mPaint);
Romain Guy03c00b52013-06-20 18:30:28 -0700875 }
876
Chris Craikd41c4d82015-01-05 15:51:13 -0800877 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
Romain Guy4c2547f2013-06-11 16:19:24 -0700878 // We're not calling the public variant of drawPatch() here
879 // This method won't perform the quickReject() since we've already done it at this point
Yohann Roussel59cf7342014-12-11 11:10:50 +0100880 renderer.drawPatch(mBitmap, getMesh(renderer), getAtlasEntry(renderer),
Romain Guy03c00b52013-06-20 18:30:28 -0700881 mLocalBounds.left, mLocalBounds.top, mLocalBounds.right, mLocalBounds.bottom,
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -0400882 mPaint);
Chris Craik2af46352012-11-26 18:30:17 -0800883 }
884
Chris Craikd41c4d82015-01-05 15:51:13 -0800885 virtual void output(int level, uint32_t logFlags) const override {
John Reckdad7d84c2014-12-09 12:33:26 -0800886 OP_LOG("Draw patch " RECT_STRING "%s", RECT_ARGS(mLocalBounds),
887 mEntry ? " with AssetAtlas" : "");
Chris Craik2af46352012-11-26 18:30:17 -0800888 }
889
Chris Craikd41c4d82015-01-05 15:51:13 -0800890 virtual const char* name() override { return "DrawPatch"; }
Chris Craik527a3aa2013-03-04 10:19:31 -0800891
Andreas Gampe64bb4132014-11-22 00:35:09 +0000892 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
Chris Craikd41c4d82015-01-05 15:51:13 -0800893 const DeferredDisplayState& state) override {
Chris Craik28ce94a2013-05-31 11:38:03 -0700894 deferInfo.batchId = DeferredDisplayList::kOpBatch_Patch;
John Reckebd52612014-12-10 16:47:36 -0800895 deferInfo.mergeId = getAtlasEntry(renderer) ? (mergeid_t) mEntry->getMergeId() : (mergeid_t) mBitmap;
Romain Guy03c00b52013-06-20 18:30:28 -0700896 deferInfo.mergeable = state.mMatrix.isPureTranslate() &&
Chris Craikbf6f0f22015-10-01 12:36:07 -0700897 PaintUtils::getXfermodeDirect(mPaint) == SkXfermode::kSrcOver_Mode;
Chris Craikc1c5f082013-09-11 16:23:37 -0700898 deferInfo.opaqueOverBounds = isOpaqueOverBounds(state) && mBitmap->isOpaque();
Chris Craikc3566d02013-02-04 16:16:33 -0800899 }
Chris Craik2af46352012-11-26 18:30:17 -0800900
901private:
Chris Craikd218a922014-01-02 17:13:34 -0800902 const SkBitmap* mBitmap;
903 const Res_png_9patch* mPatch;
Romain Guy4c2547f2013-06-11 16:19:24 -0700904
Romain Guy4c2547f2013-06-11 16:19:24 -0700905 uint32_t mGenerationId;
906 const Patch* mMesh;
Romain Guy03c00b52013-06-20 18:30:28 -0700907
John Reckebd52612014-12-10 16:47:36 -0800908 bool mEntryValid;
Romain Guy3b748a42013-04-17 18:54:38 -0700909 AssetAtlas::Entry* mEntry;
Chris Craik2af46352012-11-26 18:30:17 -0800910};
911
912class DrawColorOp : public DrawOp {
913public:
914 DrawColorOp(int color, SkXfermode::Mode mode)
Chris Craikd41c4d82015-01-05 15:51:13 -0800915 : DrawOp(nullptr), mColor(color), mMode(mode) {};
Chris Craik2af46352012-11-26 18:30:17 -0800916
Chris Craikd41c4d82015-01-05 15:51:13 -0800917 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
Tom Hudson107843d2014-09-08 11:26:26 -0400918 renderer.drawColor(mColor, mMode);
Chris Craik2af46352012-11-26 18:30:17 -0800919 }
920
Chris Craikd41c4d82015-01-05 15:51:13 -0800921 virtual void output(int level, uint32_t logFlags) const override {
Chris Craik2af46352012-11-26 18:30:17 -0800922 OP_LOG("Draw color %#x, mode %d", mColor, mMode);
923 }
924
Chris Craikd41c4d82015-01-05 15:51:13 -0800925 virtual const char* name() override { return "DrawColor"; }
Chris Craik2af46352012-11-26 18:30:17 -0800926
927private:
928 int mColor;
929 SkXfermode::Mode mMode;
930};
931
932class DrawStrokableOp : public DrawBoundedOp {
933public:
Chris Craikd218a922014-01-02 17:13:34 -0800934 DrawStrokableOp(float left, float top, float right, float bottom, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -0800935 : DrawBoundedOp(left, top, right, bottom, paint) {};
Chris Craik947eabf2014-08-19 10:21:12 -0700936 DrawStrokableOp(const Rect& localBounds, const SkPaint* paint)
937 : DrawBoundedOp(localBounds, paint) {};
Chris Craik2af46352012-11-26 18:30:17 -0800938
Chris Craikd41c4d82015-01-05 15:51:13 -0800939 virtual bool getLocalBounds(Rect& localBounds) override {
Chris Craikc3566d02013-02-04 16:16:33 -0800940 localBounds.set(mLocalBounds);
Chris Craik2af46352012-11-26 18:30:17 -0800941 if (mPaint && mPaint->getStyle() != SkPaint::kFill_Style) {
Chris Craikc3566d02013-02-04 16:16:33 -0800942 localBounds.outset(strokeWidthOutset());
Chris Craik2af46352012-11-26 18:30:17 -0800943 }
944 return true;
945 }
Chris Craikc3566d02013-02-04 16:16:33 -0800946
Andreas Gampe64bb4132014-11-22 00:35:09 +0000947 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
Chris Craikd41c4d82015-01-05 15:51:13 -0800948 const DeferredDisplayState& state) override {
Chris Craikc3566d02013-02-04 16:16:33 -0800949 if (mPaint->getPathEffect()) {
Chris Craik28ce94a2013-05-31 11:38:03 -0700950 deferInfo.batchId = DeferredDisplayList::kOpBatch_AlphaMaskTexture;
Chris Craik527a3aa2013-03-04 10:19:31 -0800951 } else {
Chris Craik28ce94a2013-05-31 11:38:03 -0700952 deferInfo.batchId = mPaint->isAntiAlias() ?
Chris Craik527a3aa2013-03-04 10:19:31 -0800953 DeferredDisplayList::kOpBatch_AlphaVertices :
954 DeferredDisplayList::kOpBatch_Vertices;
Chris Craikc3566d02013-02-04 16:16:33 -0800955 }
Chris Craikc3566d02013-02-04 16:16:33 -0800956 }
Chris Craik2af46352012-11-26 18:30:17 -0800957};
958
959class DrawRectOp : public DrawStrokableOp {
960public:
Chris Craikd218a922014-01-02 17:13:34 -0800961 DrawRectOp(float left, float top, float right, float bottom, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -0800962 : DrawStrokableOp(left, top, right, bottom, paint) {}
963
Chris Craikd41c4d82015-01-05 15:51:13 -0800964 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
Tom Hudson107843d2014-09-08 11:26:26 -0400965 renderer.drawRect(mLocalBounds.left, mLocalBounds.top,
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -0400966 mLocalBounds.right, mLocalBounds.bottom, mPaint);
Chris Craik2af46352012-11-26 18:30:17 -0800967 }
968
Chris Craikd41c4d82015-01-05 15:51:13 -0800969 virtual void output(int level, uint32_t logFlags) const override {
John Reckce444ca2014-06-02 15:12:36 -0700970 OP_LOG("Draw Rect " RECT_STRING, RECT_ARGS(mLocalBounds));
Chris Craik2af46352012-11-26 18:30:17 -0800971 }
972
Chris Craikc1c5f082013-09-11 16:23:37 -0700973 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
Chris Craikd41c4d82015-01-05 15:51:13 -0800974 const DeferredDisplayState& state) override {
Chris Craikc1c5f082013-09-11 16:23:37 -0700975 DrawStrokableOp::onDefer(renderer, deferInfo, state);
976 deferInfo.opaqueOverBounds = isOpaqueOverBounds(state) &&
Chris Craik28ce94a2013-05-31 11:38:03 -0700977 mPaint->getStyle() == SkPaint::kFill_Style;
978 }
979
Chris Craikd41c4d82015-01-05 15:51:13 -0800980 virtual const char* name() override { return "DrawRect"; }
Chris Craik2af46352012-11-26 18:30:17 -0800981};
982
Chris Craik5d116762013-02-19 17:49:31 -0800983class DrawRectsOp : public DrawBoundedOp {
Chris Craik2af46352012-11-26 18:30:17 -0800984public:
Chris Craikd218a922014-01-02 17:13:34 -0800985 DrawRectsOp(const float* rects, int count, const SkPaint* paint)
Chris Craik5d116762013-02-19 17:49:31 -0800986 : DrawBoundedOp(rects, count, paint),
987 mRects(rects), mCount(count) {}
Chris Craik2af46352012-11-26 18:30:17 -0800988
Chris Craikd41c4d82015-01-05 15:51:13 -0800989 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
Tom Hudson107843d2014-09-08 11:26:26 -0400990 renderer.drawRects(mRects, mCount, mPaint);
Chris Craik2af46352012-11-26 18:30:17 -0800991 }
992
Chris Craikd41c4d82015-01-05 15:51:13 -0800993 virtual void output(int level, uint32_t logFlags) const override {
Chris Craik2af46352012-11-26 18:30:17 -0800994 OP_LOG("Draw Rects count %d", mCount);
995 }
996
Chris Craikd41c4d82015-01-05 15:51:13 -0800997 virtual const char* name() override { return "DrawRects"; }
Chris Craik2af46352012-11-26 18:30:17 -0800998
Andreas Gampe64bb4132014-11-22 00:35:09 +0000999 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
Chris Craikd41c4d82015-01-05 15:51:13 -08001000 const DeferredDisplayState& state) override {
Chris Craik28ce94a2013-05-31 11:38:03 -07001001 deferInfo.batchId = DeferredDisplayList::kOpBatch_Vertices;
Chris Craikc3566d02013-02-04 16:16:33 -08001002 }
1003
Chris Craik2af46352012-11-26 18:30:17 -08001004private:
1005 const float* mRects;
1006 int mCount;
1007};
1008
1009class DrawRoundRectOp : public DrawStrokableOp {
1010public:
1011 DrawRoundRectOp(float left, float top, float right, float bottom,
Chris Craikd218a922014-01-02 17:13:34 -08001012 float rx, float ry, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001013 : DrawStrokableOp(left, top, right, bottom, paint), mRx(rx), mRy(ry) {}
1014
Chris Craikd41c4d82015-01-05 15:51:13 -08001015 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
Tom Hudson107843d2014-09-08 11:26:26 -04001016 renderer.drawRoundRect(mLocalBounds.left, mLocalBounds.top,
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -04001017 mLocalBounds.right, mLocalBounds.bottom, mRx, mRy, mPaint);
Chris Craik2af46352012-11-26 18:30:17 -08001018 }
1019
Chris Craikd41c4d82015-01-05 15:51:13 -08001020 virtual void output(int level, uint32_t logFlags) const override {
John Reckce444ca2014-06-02 15:12:36 -07001021 OP_LOG("Draw RoundRect " RECT_STRING ", rx %f, ry %f", RECT_ARGS(mLocalBounds), mRx, mRy);
Chris Craik2af46352012-11-26 18:30:17 -08001022 }
1023
Chris Craik05f3d6e2014-06-02 16:27:04 -07001024 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
Chris Craikd41c4d82015-01-05 15:51:13 -08001025 const DeferredDisplayState& state) override {
Chris Craik05f3d6e2014-06-02 16:27:04 -07001026 DrawStrokableOp::onDefer(renderer, deferInfo, state);
1027 if (!mPaint->getPathEffect()) {
Chris Craik6ac174b2014-06-17 13:47:05 -07001028 renderer.getCaches().tessellationCache.precacheRoundRect(state.mMatrix, *mPaint,
1029 mLocalBounds.getWidth(), mLocalBounds.getHeight(), mRx, mRy);
Chris Craik05f3d6e2014-06-02 16:27:04 -07001030 }
1031 }
1032
Chris Craikd41c4d82015-01-05 15:51:13 -08001033 virtual const char* name() override { return "DrawRoundRect"; }
Chris Craik2af46352012-11-26 18:30:17 -08001034
1035private:
1036 float mRx;
1037 float mRy;
1038};
1039
Jorim Jaggi072707d2014-09-15 17:20:08 +02001040class DrawRoundRectPropsOp : public DrawOp {
1041public:
1042 DrawRoundRectPropsOp(float* left, float* top, float* right, float* bottom,
1043 float *rx, float *ry, const SkPaint* paint)
1044 : DrawOp(paint), mLeft(left), mTop(top), mRight(right), mBottom(bottom),
1045 mRx(rx), mRy(ry) {}
1046
Chris Craikd41c4d82015-01-05 15:51:13 -08001047 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
Tom Hudson107843d2014-09-08 11:26:26 -04001048 renderer.drawRoundRect(*mLeft, *mTop, *mRight, *mBottom,
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -04001049 *mRx, *mRy, mPaint);
Jorim Jaggi072707d2014-09-15 17:20:08 +02001050 }
1051
Chris Craikd41c4d82015-01-05 15:51:13 -08001052 virtual void output(int level, uint32_t logFlags) const override {
Jorim Jaggi072707d2014-09-15 17:20:08 +02001053 OP_LOG("Draw RoundRect Props " RECT_STRING ", rx %f, ry %f",
1054 *mLeft, *mTop, *mRight, *mBottom, *mRx, *mRy);
1055 }
1056
Chris Craikd41c4d82015-01-05 15:51:13 -08001057 virtual const char* name() override { return "DrawRoundRectProps"; }
Jorim Jaggi072707d2014-09-15 17:20:08 +02001058
1059private:
1060 float* mLeft;
1061 float* mTop;
1062 float* mRight;
1063 float* mBottom;
1064 float* mRx;
1065 float* mRy;
1066};
1067
Chris Craik2af46352012-11-26 18:30:17 -08001068class DrawCircleOp : public DrawStrokableOp {
1069public:
Chris Craikd218a922014-01-02 17:13:34 -08001070 DrawCircleOp(float x, float y, float radius, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001071 : DrawStrokableOp(x - radius, y - radius, x + radius, y + radius, paint),
1072 mX(x), mY(y), mRadius(radius) {}
1073
Chris Craikd41c4d82015-01-05 15:51:13 -08001074 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
Tom Hudson107843d2014-09-08 11:26:26 -04001075 renderer.drawCircle(mX, mY, mRadius, mPaint);
Chris Craik2af46352012-11-26 18:30:17 -08001076 }
1077
Chris Craikd41c4d82015-01-05 15:51:13 -08001078 virtual void output(int level, uint32_t logFlags) const override {
Chris Craik2af46352012-11-26 18:30:17 -08001079 OP_LOG("Draw Circle x %f, y %f, r %f", mX, mY, mRadius);
1080 }
1081
Chris Craikd41c4d82015-01-05 15:51:13 -08001082 virtual const char* name() override { return "DrawCircle"; }
Chris Craik2af46352012-11-26 18:30:17 -08001083
1084private:
1085 float mX;
1086 float mY;
1087 float mRadius;
1088};
1089
John Reck52244ff2014-05-01 21:27:37 -07001090class DrawCirclePropsOp : public DrawOp {
1091public:
1092 DrawCirclePropsOp(float* x, float* y, float* radius, const SkPaint* paint)
1093 : DrawOp(paint), mX(x), mY(y), mRadius(radius) {}
1094
Chris Craikd41c4d82015-01-05 15:51:13 -08001095 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
Tom Hudson107843d2014-09-08 11:26:26 -04001096 renderer.drawCircle(*mX, *mY, *mRadius, mPaint);
John Reck52244ff2014-05-01 21:27:37 -07001097 }
1098
Chris Craikd41c4d82015-01-05 15:51:13 -08001099 virtual void output(int level, uint32_t logFlags) const override {
John Reck52244ff2014-05-01 21:27:37 -07001100 OP_LOG("Draw Circle Props x %p, y %p, r %p", mX, mY, mRadius);
1101 }
1102
Chris Craikd41c4d82015-01-05 15:51:13 -08001103 virtual const char* name() override { return "DrawCircleProps"; }
John Reck52244ff2014-05-01 21:27:37 -07001104
1105private:
1106 float* mX;
1107 float* mY;
1108 float* mRadius;
1109};
1110
Doris Liu14b56a52016-02-26 11:36:03 -08001111class DrawVectorDrawableOp : public DrawOp {
1112public:
1113 DrawVectorDrawableOp(VectorDrawableRoot* tree)
1114 : DrawOp(nullptr), mTree(tree) {}
1115
1116 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
1117 const SkBitmap& bitmap = mTree->getBitmapUpdateIfDirty();
1118 SkPaint* paint = mTree->getPaint();
1119 const SkRect bounds = mTree->getBounds();
1120 renderer.drawBitmap(&bitmap, Rect(0, 0, bitmap.width(), bitmap.height()),
1121 bounds, paint);
1122 }
1123
1124 virtual void output(int level, uint32_t logFlags) const override {
1125 OP_LOG("Draw Vector Drawable %p", mTree);
1126 }
1127
1128 virtual const char* name() override { return "DrawVectorDrawable"; }
1129
1130private:
1131 VectorDrawableRoot* mTree;
1132
1133};
1134
Chris Craik2af46352012-11-26 18:30:17 -08001135class DrawOvalOp : public DrawStrokableOp {
1136public:
Chris Craikd218a922014-01-02 17:13:34 -08001137 DrawOvalOp(float left, float top, float right, float bottom, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001138 : DrawStrokableOp(left, top, right, bottom, paint) {}
1139
Chris Craikd41c4d82015-01-05 15:51:13 -08001140 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
Tom Hudson107843d2014-09-08 11:26:26 -04001141 renderer.drawOval(mLocalBounds.left, mLocalBounds.top,
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -04001142 mLocalBounds.right, mLocalBounds.bottom, mPaint);
Chris Craik2af46352012-11-26 18:30:17 -08001143 }
1144
Chris Craikd41c4d82015-01-05 15:51:13 -08001145 virtual void output(int level, uint32_t logFlags) const override {
John Reckce444ca2014-06-02 15:12:36 -07001146 OP_LOG("Draw Oval " RECT_STRING, RECT_ARGS(mLocalBounds));
Chris Craik2af46352012-11-26 18:30:17 -08001147 }
1148
Chris Craikd41c4d82015-01-05 15:51:13 -08001149 virtual const char* name() override { return "DrawOval"; }
Chris Craik2af46352012-11-26 18:30:17 -08001150};
1151
1152class DrawArcOp : public DrawStrokableOp {
1153public:
1154 DrawArcOp(float left, float top, float right, float bottom,
Chris Craikd218a922014-01-02 17:13:34 -08001155 float startAngle, float sweepAngle, bool useCenter, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001156 : DrawStrokableOp(left, top, right, bottom, paint),
1157 mStartAngle(startAngle), mSweepAngle(sweepAngle), mUseCenter(useCenter) {}
1158
Chris Craikd41c4d82015-01-05 15:51:13 -08001159 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
Tom Hudson107843d2014-09-08 11:26:26 -04001160 renderer.drawArc(mLocalBounds.left, mLocalBounds.top,
Chris Craik2af46352012-11-26 18:30:17 -08001161 mLocalBounds.right, mLocalBounds.bottom,
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -04001162 mStartAngle, mSweepAngle, mUseCenter, mPaint);
Chris Craik2af46352012-11-26 18:30:17 -08001163 }
1164
Chris Craikd41c4d82015-01-05 15:51:13 -08001165 virtual void output(int level, uint32_t logFlags) const override {
John Reckce444ca2014-06-02 15:12:36 -07001166 OP_LOG("Draw Arc " RECT_STRING ", start %f, sweep %f, useCenter %d",
Chris Craik2af46352012-11-26 18:30:17 -08001167 RECT_ARGS(mLocalBounds), mStartAngle, mSweepAngle, mUseCenter);
1168 }
1169
Chris Craikd41c4d82015-01-05 15:51:13 -08001170 virtual const char* name() override { return "DrawArc"; }
Chris Craik2af46352012-11-26 18:30:17 -08001171
1172private:
1173 float mStartAngle;
1174 float mSweepAngle;
1175 bool mUseCenter;
1176};
1177
1178class DrawPathOp : public DrawBoundedOp {
1179public:
Chris Craikd218a922014-01-02 17:13:34 -08001180 DrawPathOp(const SkPath* path, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001181 : DrawBoundedOp(paint), mPath(path) {
1182 float left, top, offset;
1183 uint32_t width, height;
Romain Guyca89e2a2013-03-08 17:44:20 -08001184 PathCache::computePathBounds(path, paint, left, top, offset, width, height);
Chris Craik2af46352012-11-26 18:30:17 -08001185 left -= offset;
1186 top -= offset;
1187 mLocalBounds.set(left, top, left + width, top + height);
1188 }
1189
Chris Craikd41c4d82015-01-05 15:51:13 -08001190 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
Tom Hudson107843d2014-09-08 11:26:26 -04001191 renderer.drawPath(mPath, mPaint);
Chris Craik2af46352012-11-26 18:30:17 -08001192 }
1193
Chris Craikc1c5f082013-09-11 16:23:37 -07001194 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
Chris Craikd41c4d82015-01-05 15:51:13 -08001195 const DeferredDisplayState& state) override {
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -04001196 renderer.getCaches().pathCache.precache(mPath, mPaint);
Chris Craik527a3aa2013-03-04 10:19:31 -08001197
Chris Craik28ce94a2013-05-31 11:38:03 -07001198 deferInfo.batchId = DeferredDisplayList::kOpBatch_AlphaMaskTexture;
Romain Guyca89e2a2013-03-08 17:44:20 -08001199 }
1200
Chris Craikd41c4d82015-01-05 15:51:13 -08001201 virtual void output(int level, uint32_t logFlags) const override {
John Reckce444ca2014-06-02 15:12:36 -07001202 OP_LOG("Draw Path %p in " RECT_STRING, mPath, RECT_ARGS(mLocalBounds));
Chris Craik2af46352012-11-26 18:30:17 -08001203 }
1204
Chris Craikd41c4d82015-01-05 15:51:13 -08001205 virtual const char* name() override { return "DrawPath"; }
Chris Craik2af46352012-11-26 18:30:17 -08001206
1207private:
Chris Craikd218a922014-01-02 17:13:34 -08001208 const SkPath* mPath;
Chris Craik2af46352012-11-26 18:30:17 -08001209};
1210
Chris Craikc3566d02013-02-04 16:16:33 -08001211class DrawLinesOp : public DrawBoundedOp {
Chris Craik2af46352012-11-26 18:30:17 -08001212public:
Chris Craikd218a922014-01-02 17:13:34 -08001213 DrawLinesOp(const float* points, int count, const SkPaint* paint)
Chris Craik5d116762013-02-19 17:49:31 -08001214 : DrawBoundedOp(points, count, paint),
1215 mPoints(points), mCount(count) {
Chris Craikc3566d02013-02-04 16:16:33 -08001216 mLocalBounds.outset(strokeWidthOutset());
Chris Craik2af46352012-11-26 18:30:17 -08001217 }
1218
Chris Craikd41c4d82015-01-05 15:51:13 -08001219 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
Tom Hudson107843d2014-09-08 11:26:26 -04001220 renderer.drawLines(mPoints, mCount, mPaint);
Chris Craik2af46352012-11-26 18:30:17 -08001221 }
1222
Chris Craikd41c4d82015-01-05 15:51:13 -08001223 virtual void output(int level, uint32_t logFlags) const override {
Chris Craik2af46352012-11-26 18:30:17 -08001224 OP_LOG("Draw Lines count %d", mCount);
1225 }
1226
Chris Craikd41c4d82015-01-05 15:51:13 -08001227 virtual const char* name() override { return "DrawLines"; }
Chris Craik2af46352012-11-26 18:30:17 -08001228
Andreas Gampe64bb4132014-11-22 00:35:09 +00001229 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
Chris Craikd41c4d82015-01-05 15:51:13 -08001230 const DeferredDisplayState& state) override {
Chris Craik28ce94a2013-05-31 11:38:03 -07001231 deferInfo.batchId = mPaint->isAntiAlias() ?
Chris Craikc3566d02013-02-04 16:16:33 -08001232 DeferredDisplayList::kOpBatch_AlphaVertices :
1233 DeferredDisplayList::kOpBatch_Vertices;
1234 }
1235
Chris Craik2af46352012-11-26 18:30:17 -08001236protected:
Chris Craikd218a922014-01-02 17:13:34 -08001237 const float* mPoints;
Chris Craik2af46352012-11-26 18:30:17 -08001238 int mCount;
1239};
1240
1241class DrawPointsOp : public DrawLinesOp {
1242public:
Chris Craikd218a922014-01-02 17:13:34 -08001243 DrawPointsOp(const float* points, int count, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001244 : DrawLinesOp(points, count, paint) {}
1245
Chris Craikd41c4d82015-01-05 15:51:13 -08001246 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
Tom Hudson107843d2014-09-08 11:26:26 -04001247 renderer.drawPoints(mPoints, mCount, mPaint);
Chris Craik2af46352012-11-26 18:30:17 -08001248 }
1249
Chris Craikd41c4d82015-01-05 15:51:13 -08001250 virtual void output(int level, uint32_t logFlags) const override {
Chris Craik2af46352012-11-26 18:30:17 -08001251 OP_LOG("Draw Points count %d", mCount);
1252 }
1253
Chris Craikd41c4d82015-01-05 15:51:13 -08001254 virtual const char* name() override { return "DrawPoints"; }
Chris Craik2af46352012-11-26 18:30:17 -08001255};
1256
1257class DrawSomeTextOp : public DrawOp {
1258public:
Chris Craike8c3c812016-02-05 20:10:50 -08001259 DrawSomeTextOp(const glyph_t* text, int bytesCount, int count, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001260 : DrawOp(paint), mText(text), mBytesCount(bytesCount), mCount(count) {};
1261
Chris Craikd41c4d82015-01-05 15:51:13 -08001262 virtual void output(int level, uint32_t logFlags) const override {
Chris Craik2af46352012-11-26 18:30:17 -08001263 OP_LOG("Draw some text, %d bytes", mBytesCount);
1264 }
Chris Craikc3566d02013-02-04 16:16:33 -08001265
Chris Craikd41c4d82015-01-05 15:51:13 -08001266 virtual bool hasTextShadow() const override {
Chris Craikbf6f0f22015-10-01 12:36:07 -07001267 return PaintUtils::hasTextShadow(mPaint);
Derek Sollenbergerc29a0a42014-03-31 13:52:39 -04001268 }
1269
Chris Craikc1c5f082013-09-11 16:23:37 -07001270 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
Chris Craikd41c4d82015-01-05 15:51:13 -08001271 const DeferredDisplayState& state) override {
Chris Craikc08820f2015-09-22 14:22:29 -07001272 FontRenderer& fontRenderer = renderer.getCaches().fontRenderer.getFontRenderer();
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -04001273 fontRenderer.precache(mPaint, mText, mCount, SkMatrix::I());
Romain Guy0f667532013-03-01 14:31:04 -08001274
Chris Craik98d608d2014-07-17 12:25:11 -07001275 deferInfo.batchId = mPaint->getColor() == SK_ColorBLACK ?
Chris Craikc3566d02013-02-04 16:16:33 -08001276 DeferredDisplayList::kOpBatch_Text :
1277 DeferredDisplayList::kOpBatch_ColorText;
1278 }
Chris Craik527a3aa2013-03-04 10:19:31 -08001279
Chris Craik2af46352012-11-26 18:30:17 -08001280protected:
Chris Craike8c3c812016-02-05 20:10:50 -08001281 const glyph_t* mText;
Chris Craik2af46352012-11-26 18:30:17 -08001282 int mBytesCount;
1283 int mCount;
1284};
1285
1286class DrawTextOnPathOp : public DrawSomeTextOp {
1287public:
Chris Craike8c3c812016-02-05 20:10:50 -08001288 DrawTextOnPathOp(const glyph_t* text, int bytesCount, int count,
Chris Craikd218a922014-01-02 17:13:34 -08001289 const SkPath* path, float hOffset, float vOffset, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001290 : DrawSomeTextOp(text, bytesCount, count, paint),
1291 mPath(path), mHOffset(hOffset), mVOffset(vOffset) {
1292 /* TODO: inherit from DrawBounded and init mLocalBounds */
1293 }
1294
Chris Craikd41c4d82015-01-05 15:51:13 -08001295 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
Tom Hudson107843d2014-09-08 11:26:26 -04001296 renderer.drawTextOnPath(mText, mBytesCount, mCount, mPath,
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -04001297 mHOffset, mVOffset, mPaint);
Chris Craik2af46352012-11-26 18:30:17 -08001298 }
1299
Chris Craikd41c4d82015-01-05 15:51:13 -08001300 virtual const char* name() override { return "DrawTextOnPath"; }
Chris Craik2af46352012-11-26 18:30:17 -08001301
1302private:
Chris Craikd218a922014-01-02 17:13:34 -08001303 const SkPath* mPath;
Chris Craik2af46352012-11-26 18:30:17 -08001304 float mHOffset;
1305 float mVOffset;
1306};
1307
Chris Craik947eabf2014-08-19 10:21:12 -07001308class DrawTextOp : public DrawStrokableOp {
Chris Craik2af46352012-11-26 18:30:17 -08001309public:
Chris Craike8c3c812016-02-05 20:10:50 -08001310 DrawTextOp(const glyph_t* text, int bytesCount, int count, float x, float y,
Chris Craikd218a922014-01-02 17:13:34 -08001311 const float* positions, const SkPaint* paint, float totalAdvance, const Rect& bounds)
Chris Craik947eabf2014-08-19 10:21:12 -07001312 : DrawStrokableOp(bounds, paint), mText(text), mBytesCount(bytesCount), mCount(count),
Chris Craik41541822013-05-03 16:35:54 -07001313 mX(x), mY(y), mPositions(positions), mTotalAdvance(totalAdvance) {
Chris Craik59744b72014-07-01 17:56:52 -07001314 mPrecacheTransform = SkMatrix::InvalidMatrix();
Chris Craik2af46352012-11-26 18:30:17 -08001315 }
1316
Chris Craikc1c5f082013-09-11 16:23:37 -07001317 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
Chris Craikd41c4d82015-01-05 15:51:13 -08001318 const DeferredDisplayState& state) override {
Chris Craikc08820f2015-09-22 14:22:29 -07001319 FontRenderer& fontRenderer = renderer.getCaches().fontRenderer.getFontRenderer();
Chris Craik59744b72014-07-01 17:56:52 -07001320 SkMatrix transform;
1321 renderer.findBestFontTransform(state.mMatrix, &transform);
Romain Guybd3055f2013-03-13 16:14:47 -07001322 if (mPrecacheTransform != transform) {
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -04001323 fontRenderer.precache(mPaint, mText, mCount, transform);
Romain Guybd3055f2013-03-13 16:14:47 -07001324 mPrecacheTransform = transform;
1325 }
Chris Craik98d608d2014-07-17 12:25:11 -07001326 deferInfo.batchId = mPaint->getColor() == SK_ColorBLACK ?
Chris Craik527a3aa2013-03-04 10:19:31 -08001327 DeferredDisplayList::kOpBatch_Text :
1328 DeferredDisplayList::kOpBatch_ColorText;
1329
Kévin PETIT73fc5582014-02-13 11:03:40 +00001330 deferInfo.mergeId = reinterpret_cast<mergeid_t>(mPaint->getColor());
Chris Craik527a3aa2013-03-04 10:19:31 -08001331
1332 // don't merge decorated text - the decorations won't draw in order
Chris Craik98d608d2014-07-17 12:25:11 -07001333 bool hasDecorations = mPaint->getFlags()
1334 & (SkPaint::kUnderlineText_Flag | SkPaint::kStrikeThruText_Flag);
1335
1336 deferInfo.mergeable = state.mMatrix.isPureTranslate()
1337 && !hasDecorations
Chris Craikbf6f0f22015-10-01 12:36:07 -07001338 && PaintUtils::getXfermodeDirect(mPaint) == SkXfermode::kSrcOver_Mode;
Romain Guy0f667532013-03-01 14:31:04 -08001339 }
1340
Chris Craikd41c4d82015-01-05 15:51:13 -08001341 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
Romain Guy9b5a1a22013-08-09 14:06:29 -07001342 Rect bounds;
John Reck3b202512014-06-23 13:13:08 -07001343 getLocalBounds(bounds);
Tom Hudson107843d2014-09-08 11:26:26 -04001344 renderer.drawText(mText, mBytesCount, mCount, mX, mY,
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -04001345 mPositions, mPaint, mTotalAdvance, bounds);
Chris Craik2af46352012-11-26 18:30:17 -08001346 }
1347
Andreas Gampe64bb4132014-11-22 00:35:09 +00001348 virtual void multiDraw(OpenGLRenderer& renderer, Rect& dirty,
John Reck272a6852015-07-29 16:48:58 -07001349 const std::vector<OpStatePair>& ops, const Rect& bounds) override {
Chris Craik527a3aa2013-03-04 10:19:31 -08001350 for (unsigned int i = 0; i < ops.size(); i++) {
Chris Craikc1c5f082013-09-11 16:23:37 -07001351 const DeferredDisplayState& state = *(ops[i].state);
Chris Craik03ae2722015-02-25 11:01:09 -08001352 DrawOpMode drawOpMode = (i == ops.size() - 1) ? DrawOpMode::kFlush : DrawOpMode::kDefer;
Chris Craikc1c5f082013-09-11 16:23:37 -07001353 renderer.restoreDisplayState(state, true); // restore all but the clip
Chris Craik527a3aa2013-03-04 10:19:31 -08001354
Chris Craikc1c5f082013-09-11 16:23:37 -07001355 DrawTextOp& op = *((DrawTextOp*)ops[i].op);
Romain Guy9b5a1a22013-08-09 14:06:29 -07001356 // quickReject() will not occure in drawText() so we can use mLocalBounds
1357 // directly, we do not need to account for shadow by calling getLocalBounds()
Tom Hudson107843d2014-09-08 11:26:26 -04001358 renderer.drawText(op.mText, op.mBytesCount, op.mCount, op.mX, op.mY,
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -04001359 op.mPositions, op.mPaint, op.mTotalAdvance, op.mLocalBounds,
Chris Craik41541822013-05-03 16:35:54 -07001360 drawOpMode);
Chris Craik527a3aa2013-03-04 10:19:31 -08001361 }
Chris Craik527a3aa2013-03-04 10:19:31 -08001362 }
1363
Chris Craikd41c4d82015-01-05 15:51:13 -08001364 virtual void output(int level, uint32_t logFlags) const override {
Chris Craik2af46352012-11-26 18:30:17 -08001365 OP_LOG("Draw Text of count %d, bytes %d", mCount, mBytesCount);
1366 }
1367
Chris Craikd41c4d82015-01-05 15:51:13 -08001368 virtual const char* name() override { return "DrawText"; }
Chris Craik2af46352012-11-26 18:30:17 -08001369
1370private:
Chris Craike8c3c812016-02-05 20:10:50 -08001371 const glyph_t* mText;
Chris Craik2af46352012-11-26 18:30:17 -08001372 int mBytesCount;
1373 int mCount;
1374 float mX;
1375 float mY;
1376 const float* mPositions;
Chris Craik41541822013-05-03 16:35:54 -07001377 float mTotalAdvance;
Chris Craik59744b72014-07-01 17:56:52 -07001378 SkMatrix mPrecacheTransform;
Chris Craik2af46352012-11-26 18:30:17 -08001379};
1380
1381///////////////////////////////////////////////////////////////////////////////
1382// SPECIAL DRAW OPERATIONS
1383///////////////////////////////////////////////////////////////////////////////
1384
1385class DrawFunctorOp : public DrawOp {
1386public:
1387 DrawFunctorOp(Functor* functor)
Chris Craikd41c4d82015-01-05 15:51:13 -08001388 : DrawOp(nullptr), mFunctor(functor) {}
Chris Craik2af46352012-11-26 18:30:17 -08001389
Chris Craikd41c4d82015-01-05 15:51:13 -08001390 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
Chris Craik2af46352012-11-26 18:30:17 -08001391 renderer.startMark("GL functor");
Tom Hudson107843d2014-09-08 11:26:26 -04001392 renderer.callDrawGLFunction(mFunctor, dirty);
Chris Craik2af46352012-11-26 18:30:17 -08001393 renderer.endMark();
Chris Craik2af46352012-11-26 18:30:17 -08001394 }
1395
Chris Craikd41c4d82015-01-05 15:51:13 -08001396 virtual void output(int level, uint32_t logFlags) const override {
Chris Craik2af46352012-11-26 18:30:17 -08001397 OP_LOG("Draw Functor %p", mFunctor);
1398 }
1399
Chris Craikd41c4d82015-01-05 15:51:13 -08001400 virtual const char* name() override { return "DrawFunctor"; }
Chris Craik2af46352012-11-26 18:30:17 -08001401
1402private:
1403 Functor* mFunctor;
1404};
1405
Chris Craika7090e02014-06-20 16:01:00 -07001406class DrawRenderNodeOp : public DrawBoundedOp {
1407 friend class RenderNode; // grant RenderNode access to info of child
Chris Craik003cc3d2015-10-16 10:24:55 -07001408 friend class DisplayList; // grant DisplayList access to info of child
Chris Craikb565df12015-10-05 13:00:52 -07001409 friend class DisplayListCanvas;
Chris Craik161f54b2015-11-05 11:08:52 -08001410 friend class TestUtils;
Chris Craik2af46352012-11-26 18:30:17 -08001411public:
Chris Craika766cb22015-06-08 16:49:43 -07001412 DrawRenderNodeOp(RenderNode* renderNode, const mat4& transformFromParent, bool clipIsSimple)
Chris Craik54fa17f2015-11-25 14:14:53 -08001413 : DrawBoundedOp(0, 0,
1414 renderNode->stagingProperties().getWidth(),
1415 renderNode->stagingProperties().getHeight(),
1416 nullptr)
Chris Craikb565df12015-10-05 13:00:52 -07001417 , renderNode(renderNode)
Chris Craika766cb22015-06-08 16:49:43 -07001418 , mRecordedWithPotentialStencilClip(!clipIsSimple || !transformFromParent.isSimple())
Chris Craik8d1f2122015-11-24 16:40:09 -08001419 , localMatrix(transformFromParent)
1420 , skipInOrderDraw(false) {}
Chris Craikc3566d02013-02-04 16:16:33 -08001421
Andreas Gampe64bb4132014-11-22 00:35:09 +00001422 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
Chris Craikd41c4d82015-01-05 15:51:13 -08001423 bool useQuickReject) override {
Chris Craik8d1f2122015-11-24 16:40:09 -08001424 if (renderNode->isRenderable() && !skipInOrderDraw) {
Chris Craikb565df12015-10-05 13:00:52 -07001425 renderNode->defer(deferStruct, level + 1);
Chris Craikc3566d02013-02-04 16:16:33 -08001426 }
Chris Craikc3566d02013-02-04 16:16:33 -08001427 }
Chris Craik8afd0f22014-08-21 17:41:57 -07001428
Andreas Gampe64bb4132014-11-22 00:35:09 +00001429 virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level,
Chris Craikd41c4d82015-01-05 15:51:13 -08001430 bool useQuickReject) override {
Chris Craik8d1f2122015-11-24 16:40:09 -08001431 if (renderNode->isRenderable() && !skipInOrderDraw) {
Chris Craikb565df12015-10-05 13:00:52 -07001432 renderNode->replay(replayStruct, level + 1);
Chris Craikff785832013-03-08 13:12:16 -08001433 }
1434 }
Chris Craik2af46352012-11-26 18:30:17 -08001435
Chris Craikd41c4d82015-01-05 15:51:13 -08001436 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
Chris Craik80d49022014-06-20 15:03:43 -07001437 LOG_ALWAYS_FATAL("should not be called, because replay() is overridden");
Chris Craika08f95c2013-03-15 17:24:33 -07001438 }
Chris Craikff785832013-03-08 13:12:16 -08001439
Chris Craikd41c4d82015-01-05 15:51:13 -08001440 virtual void output(int level, uint32_t logFlags) const override {
Chris Craikb565df12015-10-05 13:00:52 -07001441 OP_LOG("Draw RenderNode %p %s", renderNode, renderNode->getName());
1442 if (renderNode && (logFlags & kOpLogFlag_Recurse)) {
1443 renderNode->output(level + 1);
Chris Craik2af46352012-11-26 18:30:17 -08001444 }
1445 }
1446
Chris Craikd41c4d82015-01-05 15:51:13 -08001447 virtual const char* name() override { return "DrawRenderNode"; }
Chris Craik2af46352012-11-26 18:30:17 -08001448
1449private:
Chris Craikb565df12015-10-05 13:00:52 -07001450 RenderNode* renderNode;
Chris Craikf57776b2013-10-25 18:30:17 -07001451
Chris Craika766cb22015-06-08 16:49:43 -07001452 /**
1453 * This RenderNode was drawn into a DisplayList with the canvas in a state that will likely
1454 * require rendering with stencil clipping. Either:
1455 *
1456 * 1) A path clip or rotated rect clip was in effect on the canvas at record time
1457 * 2) The RenderNode was recorded with a non-simple canvas transform (e.g. rotation)
1458 *
1459 * Note: even if this is false, non-rect clipping may still be applied applied either due to
1460 * property-driven rotation (either in this RenderNode, or any ancestor), or record time
1461 * clipping in an ancestor. These are handled in RenderNode::prepareTreeImpl since they are
1462 * dynamic (relative to a static DisplayList of a parent), and don't affect this flag.
1463 */
1464 bool mRecordedWithPotentialStencilClip;
1465
Chris Craikf57776b2013-10-25 18:30:17 -07001466 ///////////////////////////
Chris Craika7090e02014-06-20 16:01:00 -07001467 // Properties below are used by RenderNode::computeOrderingImpl() and issueOperations()
Chris Craikf57776b2013-10-25 18:30:17 -07001468 ///////////////////////////
1469 /**
1470 * Records transform vs parent, used for computing total transform without rerunning DL contents
1471 */
Chris Craik8d1f2122015-11-24 16:40:09 -08001472 const mat4 localMatrix;
Chris Craikf57776b2013-10-25 18:30:17 -07001473
1474 /**
Chris Craika7090e02014-06-20 16:01:00 -07001475 * Holds the transformation between the projection surface ViewGroup and this RenderNode
Chris Craikb79a3e32014-03-11 12:20:17 -07001476 * drawing instance. Represents any translations / transformations done within the drawing of
1477 * the compositing ancestor ViewGroup's draw, before the draw of the View represented by this
1478 * DisplayList draw instance.
Chris Craikf57776b2013-10-25 18:30:17 -07001479 *
Chris Craika7090e02014-06-20 16:01:00 -07001480 * Note: doesn't include transformation within the RenderNode, or its properties.
Chris Craikf57776b2013-10-25 18:30:17 -07001481 */
Chris Craik8d1f2122015-11-24 16:40:09 -08001482 mat4 transformFromCompositingAncestor;
1483 bool skipInOrderDraw;
Chris Craikf57776b2013-10-25 18:30:17 -07001484};
1485
1486/**
Chris Craik024433f2014-03-26 13:19:14 -07001487 * Not a canvas operation, used only by 3d / z ordering logic in RenderNode::iterate()
Chris Craikf57776b2013-10-25 18:30:17 -07001488 */
1489class DrawShadowOp : public DrawOp {
1490public:
Chris Craik024433f2014-03-26 13:19:14 -07001491 DrawShadowOp(const mat4& transformXY, const mat4& transformZ,
Chris Craik74669862014-08-07 17:27:30 -07001492 float casterAlpha, const SkPath* casterOutline)
Chris Craikd41c4d82015-01-05 15:51:13 -08001493 : DrawOp(nullptr)
Chris Craik74669862014-08-07 17:27:30 -07001494 , mTransformXY(transformXY)
1495 , mTransformZ(transformZ)
1496 , mCasterAlpha(casterAlpha)
1497 , mCasterOutline(casterOutline) {
Chris Craik61317322014-05-21 13:03:52 -07001498 }
Chris Craikf57776b2013-10-25 18:30:17 -07001499
Andreas Gampe64bb4132014-11-22 00:35:09 +00001500 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
Chris Craikd41c4d82015-01-05 15:51:13 -08001501 const DeferredDisplayState& state) override {
Chris Craik05f3d6e2014-06-02 16:27:04 -07001502 renderer.getCaches().tessellationCache.precacheShadows(&state.mMatrix,
Chris Craik74669862014-08-07 17:27:30 -07001503 renderer.getLocalClipBounds(), isCasterOpaque(), mCasterOutline,
Chris Craik05f3d6e2014-06-02 16:27:04 -07001504 &mTransformXY, &mTransformZ, renderer.getLightCenter(), renderer.getLightRadius());
1505 }
1506
Chris Craikd41c4d82015-01-05 15:51:13 -08001507 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
Chris Craik05f3d6e2014-06-02 16:27:04 -07001508 TessellationCache::vertexBuffer_pair_t buffers;
Chris Craikc3e75f92014-08-27 15:34:52 -07001509 Matrix4 drawTransform(*(renderer.currentTransform()));
Chris Craik05f3d6e2014-06-02 16:27:04 -07001510 renderer.getCaches().tessellationCache.getShadowBuffers(&drawTransform,
Chris Craik74669862014-08-07 17:27:30 -07001511 renderer.getLocalClipBounds(), isCasterOpaque(), mCasterOutline,
Chris Craik05f3d6e2014-06-02 16:27:04 -07001512 &mTransformXY, &mTransformZ, renderer.getLightCenter(), renderer.getLightRadius(),
1513 buffers);
1514
Tom Hudson107843d2014-09-08 11:26:26 -04001515 renderer.drawShadow(mCasterAlpha, buffers.first, buffers.second);
Chris Craikf57776b2013-10-25 18:30:17 -07001516 }
1517
Chris Craikd41c4d82015-01-05 15:51:13 -08001518 virtual void output(int level, uint32_t logFlags) const override {
Chris Craik61317322014-05-21 13:03:52 -07001519 OP_LOGS("DrawShadow");
Chris Craikf57776b2013-10-25 18:30:17 -07001520 }
1521
Chris Craikd41c4d82015-01-05 15:51:13 -08001522 virtual const char* name() override { return "DrawShadow"; }
Chris Craikf57776b2013-10-25 18:30:17 -07001523
1524private:
Chris Craikaf4d04c2014-07-29 12:50:14 -07001525 bool isCasterOpaque() { return mCasterAlpha >= 1.0f; }
Chris Craik05f3d6e2014-06-02 16:27:04 -07001526
Chris Craikb79a3e32014-03-11 12:20:17 -07001527 const mat4 mTransformXY;
1528 const mat4 mTransformZ;
Chris Craik024433f2014-03-26 13:19:14 -07001529 const float mCasterAlpha;
Chris Craik74669862014-08-07 17:27:30 -07001530 const SkPath* mCasterOutline;
Chris Craik2af46352012-11-26 18:30:17 -08001531};
1532
1533class DrawLayerOp : public DrawOp {
1534public:
Chris Craik3aadd602015-08-20 12:41:40 -07001535 DrawLayerOp(Layer* layer)
1536 : DrawOp(nullptr), mLayer(layer) {}
Chris Craik2af46352012-11-26 18:30:17 -08001537
Chris Craikd41c4d82015-01-05 15:51:13 -08001538 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
Chris Craik3aadd602015-08-20 12:41:40 -07001539 renderer.drawLayer(mLayer);
Chris Craik2af46352012-11-26 18:30:17 -08001540 }
1541
Chris Craikd41c4d82015-01-05 15:51:13 -08001542 virtual void output(int level, uint32_t logFlags) const override {
Chris Craik3aadd602015-08-20 12:41:40 -07001543 OP_LOG("Draw Layer %p", mLayer);
Chris Craik2af46352012-11-26 18:30:17 -08001544 }
1545
Chris Craikd41c4d82015-01-05 15:51:13 -08001546 virtual const char* name() override { return "DrawLayer"; }
Chris Craik2af46352012-11-26 18:30:17 -08001547
1548private:
1549 Layer* mLayer;
Chris Craik2af46352012-11-26 18:30:17 -08001550};
1551
1552}; // namespace uirenderer
1553}; // namespace android
1554
1555#endif // ANDROID_HWUI_DISPLAY_OPERATION_H