blob: 1b5af497ffaddbc050870bdcc9777844c19c0e6d [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 Craik98d608d2014-07-17 12:25:11 -070020#include <SkColor.h>
Chris Craik8c271ca2014-03-25 10:33:01 -070021#include <SkPath.h>
22#include <SkPathOps.h>
Chris Craik2af46352012-11-26 18:30:17 -080023#include <SkXfermode.h>
24
Chris Craik0776a602013-02-14 15:36:01 -080025#include <private/hwui/DrawGlInfo.h>
26
Chris Craik2af46352012-11-26 18:30:17 -080027#include "OpenGLRenderer.h"
Romain Guy3b748a42013-04-17 18:54:38 -070028#include "AssetAtlas.h"
Chris Craikc3566d02013-02-04 16:16:33 -080029#include "DeferredDisplayList.h"
Chris Craik2af46352012-11-26 18:30:17 -080030#include "DisplayListRenderer.h"
Tom Hudson2dc236b2014-10-15 15:46:42 -040031#include "GammaFontRenderer.h"
32#include "Patch.h"
33#include "RenderNode.h"
John Reckebd52612014-12-10 16:47:36 -080034#include "RenderState.h"
Romain Guy3b748a42013-04-17 18:54:38 -070035#include "UvMapper.h"
Chris Craik2af46352012-11-26 18:30:17 -080036#include "utils/LinearAllocator.h"
Tom Hudson8dfaa492014-12-09 15:03:44 -050037#include "utils/PaintUtils.h"
Chris Craik2af46352012-11-26 18:30:17 -080038
Chris Craik2af46352012-11-26 18:30:17 -080039// Use OP_LOG for logging with arglist, OP_LOGS if just printing char*
Chris Craik28ce94a2013-05-31 11:38:03 -070040#define OP_LOGS(s) OP_LOG("%s", (s))
Chris Craik3dc553b2013-02-04 12:45:13 -080041#define OP_LOG(s, ...) ALOGD( "%*s" s, level * 2, "", __VA_ARGS__ )
Chris Craik2af46352012-11-26 18:30:17 -080042
Chris Craik2af46352012-11-26 18:30:17 -080043namespace android {
44namespace uirenderer {
45
46/**
47 * Structure for storing canvas operations when they are recorded into a DisplayList, so that they
48 * may be replayed to an OpenGLRenderer.
49 *
50 * To avoid individual memory allocations, DisplayListOps may only be allocated into a
51 * LinearAllocator's managed memory buffers. Each pointer held by a DisplayListOp is either a
52 * pointer into memory also allocated in the LinearAllocator (mostly for text and float buffers) or
53 * references a externally refcounted object (Sk... and Skia... objects). ~DisplayListOp() is
54 * never called as LinearAllocators are simply discarded, so no memory management should be done in
55 * this class.
56 */
57class DisplayListOp {
58public:
59 // These objects should always be allocated with a LinearAllocator, and never destroyed/deleted.
60 // standard new() intentionally not implemented, and delete/deconstructor should never be used.
Chris Craik51d6a3d2014-12-22 17:16:56 -080061 virtual ~DisplayListOp() { LOG_ALWAYS_FATAL("Destructor not supported"); }
62 static void operator delete(void* ptr) { LOG_ALWAYS_FATAL("delete not supported"); }
63 static void* operator new(size_t size) = delete; /** PURPOSELY OMITTED **/
Chris Craik2af46352012-11-26 18:30:17 -080064 static void* operator new(size_t size, LinearAllocator& allocator) {
65 return allocator.alloc(size);
66 }
67
68 enum OpLogFlag {
69 kOpLogFlag_Recurse = 0x1,
70 kOpLogFlag_JSON = 0x2 // TODO: add?
71 };
72
Chet Haasedd671592013-04-19 14:54:34 -070073 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
74 bool useQuickReject) = 0;
Chris Craikc3566d02013-02-04 16:16:33 -080075
Chet Haasedd671592013-04-19 14:54:34 -070076 virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level,
77 bool useQuickReject) = 0;
Chris Craikff785832013-03-08 13:12:16 -080078
Chris Craikc5493fb2013-06-19 16:58:58 -070079 virtual void output(int level, uint32_t logFlags = 0) const = 0;
Chris Craik2af46352012-11-26 18:30:17 -080080
81 // NOTE: it would be nice to declare constants and overriding the implementation in each op to
82 // point at the constants, but that seems to require a .cpp file
83 virtual const char* name() = 0;
84};
85
86class StateOp : public DisplayListOp {
87public:
Andreas Gampe64bb4132014-11-22 00:35:09 +000088 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
Chris Craikd41c4d82015-01-05 15:51:13 -080089 bool useQuickReject) override {
Chris Craikff785832013-03-08 13:12:16 -080090 // default behavior only affects immediate, deferrable state, issue directly to renderer
91 applyState(deferStruct.mRenderer, saveCount);
92 }
93
Chris Craikc3566d02013-02-04 16:16:33 -080094 /**
95 * State operations are applied directly to the renderer, but can cause the deferred drawing op
96 * list to flush
97 */
Andreas Gampe64bb4132014-11-22 00:35:09 +000098 virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level,
Chris Craikd41c4d82015-01-05 15:51:13 -080099 bool useQuickReject) override {
Chris Craikff785832013-03-08 13:12:16 -0800100 applyState(replayStruct.mRenderer, saveCount);
Chris Craikc3566d02013-02-04 16:16:33 -0800101 }
102
Chris Craik7273daa2013-03-28 11:25:24 -0700103 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const = 0;
Chris Craik2af46352012-11-26 18:30:17 -0800104};
105
106class DrawOp : public DisplayListOp {
Chris Craik527a3aa2013-03-04 10:19:31 -0800107friend class MergingDrawBatch;
Chris Craik2af46352012-11-26 18:30:17 -0800108public:
Chris Craikd218a922014-01-02 17:13:34 -0800109 DrawOp(const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -0800110 : mPaint(paint), mQuickRejected(false) {}
111
Andreas Gampe64bb4132014-11-22 00:35:09 +0000112 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
Chris Craikd41c4d82015-01-05 15:51:13 -0800113 bool useQuickReject) override {
Chet Haasedd671592013-04-19 14:54:34 -0700114 if (mQuickRejected && CC_LIKELY(useQuickReject)) {
Chris Craikff785832013-03-08 13:12:16 -0800115 return;
Chris Craikc3566d02013-02-04 16:16:33 -0800116 }
117
Chris Craikff785832013-03-08 13:12:16 -0800118 deferStruct.mDeferredList.addDrawOp(deferStruct.mRenderer, this);
Chris Craikc3566d02013-02-04 16:16:33 -0800119 }
120
Andreas Gampe64bb4132014-11-22 00:35:09 +0000121 virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level,
Chris Craikd41c4d82015-01-05 15:51:13 -0800122 bool useQuickReject) override {
Chet Haasedd671592013-04-19 14:54:34 -0700123 if (mQuickRejected && CC_LIKELY(useQuickReject)) {
Chris Craikff785832013-03-08 13:12:16 -0800124 return;
125 }
126
Tom Hudson107843d2014-09-08 11:26:26 -0400127 applyDraw(replayStruct.mRenderer, replayStruct.mDirty);
Chris Craikff785832013-03-08 13:12:16 -0800128 }
129
Tom Hudson107843d2014-09-08 11:26:26 -0400130 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) = 0;
Chris Craik2af46352012-11-26 18:30:17 -0800131
Chris Craik527a3aa2013-03-04 10:19:31 -0800132 /**
133 * Draw multiple instances of an operation, must be overidden for operations that merge
134 *
135 * Currently guarantees certain similarities between ops (see MergingDrawBatch::canMergeWith),
136 * and pure translation transformations. Other guarantees of similarity should be enforced by
137 * reducing which operations are tagged as mergeable.
138 */
Tom Hudson107843d2014-09-08 11:26:26 -0400139 virtual void multiDraw(OpenGLRenderer& renderer, Rect& dirty,
Andreas Gampe64bb4132014-11-22 00:35:09 +0000140 const Vector<OpStatePair>& ops, const Rect& bounds) {
Chris Craik527a3aa2013-03-04 10:19:31 -0800141 for (unsigned int i = 0; i < ops.size(); i++) {
Chris Craikc1c5f082013-09-11 16:23:37 -0700142 renderer.restoreDisplayState(*(ops[i].state), true);
Tom Hudson107843d2014-09-08 11:26:26 -0400143 ops[i].op->applyDraw(renderer, dirty);
Chris Craik527a3aa2013-03-04 10:19:31 -0800144 }
Chris Craik527a3aa2013-03-04 10:19:31 -0800145 }
146
Chris Craik28ce94a2013-05-31 11:38:03 -0700147 /**
Chris Craik527a3aa2013-03-04 10:19:31 -0800148 * When this method is invoked the state field is initialized to have the
149 * final rendering state. We can thus use it to process data as it will be
150 * used at draw time.
151 *
152 * Additionally, this method allows subclasses to provide defer-time preferences for batching
153 * and merging.
154 *
Chris Craik28ce94a2013-05-31 11:38:03 -0700155 * if a subclass can set deferInfo.mergeable to true, it should implement multiDraw()
Chris Craik527a3aa2013-03-04 10:19:31 -0800156 */
Andreas Gampe64bb4132014-11-22 00:35:09 +0000157 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
158 const DeferredDisplayState& state) {}
Romain Guy0f6675332013-03-01 14:31:04 -0800159
Chris Craik5e49b302013-07-30 19:05:20 -0700160 /**
161 * Query the conservative, local bounds (unmapped) bounds of the op.
162 *
163 * returns true if bounds exist
164 */
Andreas Gampe64bb4132014-11-22 00:35:09 +0000165 virtual bool getLocalBounds(Rect& localBounds) {
Chris Craikc1c5f082013-09-11 16:23:37 -0700166 return false;
167 }
Chris Craik2af46352012-11-26 18:30:17 -0800168
169 // TODO: better refine localbounds usage
170 void setQuickRejected(bool quickRejected) { mQuickRejected = quickRejected; }
171 bool getQuickRejected() { return mQuickRejected; }
172
Chris Craikc1c5f082013-09-11 16:23:37 -0700173 inline int getPaintAlpha() const {
Chris Craik527a3aa2013-03-04 10:19:31 -0800174 return OpenGLRenderer::getAlphaDirect(mPaint);
Chris Craikc3566d02013-02-04 16:16:33 -0800175 }
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.
187 return fmaxf(mPaint->getStrokeWidth(), 1) * 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
214 SkXfermode::Mode mode = OpenGLRenderer::getXfermodeDirect(mPaint);
215 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) {
238 mLocalBounds.left = fminf(mLocalBounds.left, points[i]);
239 mLocalBounds.right = fmaxf(mLocalBounds.right, points[i]);
240 mLocalBounds.top = fminf(mLocalBounds.top, points[i + 1]);
241 mLocalBounds.bottom = fmaxf(mLocalBounds.bottom, points[i + 1]);
242 }
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);
Derek Sollenbergerc29a0a42014-03-31 13:52:39 -0400250 OpenGLRenderer::TextShadow textShadow;
251 if (OpenGLRenderer::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 {
373 SkXfermode::Mode mode = OpenGLRenderer::getXfermodeDirect(mPaint);
374 int alpha = OpenGLRenderer::getAlphaDirect(mPaint);
375 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 Craik2af46352012-11-26 18:30:17 -0800473 renderer.setMatrix(mMatrix);
474 }
475
Chris Craikd41c4d82015-01-05 15:51:13 -0800476 virtual void output(int level, uint32_t logFlags) const override {
Derek Sollenberger13908822013-12-10 12:28:58 -0500477 if (mMatrix.isIdentity()) {
Romain Guy4e7b7722013-07-16 13:47:01 -0700478 OP_LOGS("SetMatrix (reset)");
Derek Sollenberger13908822013-12-10 12:28:58 -0500479 } else {
480 OP_LOG("SetMatrix " SK_MATRIX_STRING, SK_MATRIX_ARGS(&mMatrix));
Romain Guy4e7b7722013-07-16 13:47:01 -0700481 }
Chris Craik2af46352012-11-26 18:30:17 -0800482 }
483
Chris Craikd41c4d82015-01-05 15:51:13 -0800484 virtual const char* name() override { return "SetMatrix"; }
Chris Craik2af46352012-11-26 18:30:17 -0800485
486private:
Derek Sollenberger13908822013-12-10 12:28:58 -0500487 const SkMatrix mMatrix;
Chris Craik2af46352012-11-26 18:30:17 -0800488};
489
490class ConcatMatrixOp : public StateOp {
491public:
Derek Sollenberger13908822013-12-10 12:28:58 -0500492 ConcatMatrixOp(const SkMatrix& matrix)
Chris Craik2af46352012-11-26 18:30:17 -0800493 : mMatrix(matrix) {}
494
Chris Craikd41c4d82015-01-05 15:51:13 -0800495 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const override {
Chris Craik2af46352012-11-26 18:30:17 -0800496 renderer.concatMatrix(mMatrix);
497 }
498
Chris Craikd41c4d82015-01-05 15:51:13 -0800499 virtual void output(int level, uint32_t logFlags) const override {
Derek Sollenberger13908822013-12-10 12:28:58 -0500500 OP_LOG("ConcatMatrix " SK_MATRIX_STRING, SK_MATRIX_ARGS(&mMatrix));
Chris Craik2af46352012-11-26 18:30:17 -0800501 }
502
Chris Craikd41c4d82015-01-05 15:51:13 -0800503 virtual const char* name() override { return "ConcatMatrix"; }
Chris Craik2af46352012-11-26 18:30:17 -0800504
505private:
Derek Sollenberger13908822013-12-10 12:28:58 -0500506 const SkMatrix mMatrix;
Chris Craik2af46352012-11-26 18:30:17 -0800507};
508
Chris Craikff785832013-03-08 13:12:16 -0800509class ClipOp : public StateOp {
510public:
511 ClipOp(SkRegion::Op op) : mOp(op) {}
512
Andreas Gampe64bb4132014-11-22 00:35:09 +0000513 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
Chris Craikd41c4d82015-01-05 15:51:13 -0800514 bool useQuickReject) override {
Chris Craikff785832013-03-08 13:12:16 -0800515 // NOTE: must defer op BEFORE applying state, since it may read clip
516 deferStruct.mDeferredList.addClip(deferStruct.mRenderer, this);
517
518 // TODO: Can we avoid applying complex clips at defer time?
519 applyState(deferStruct.mRenderer, saveCount);
520 }
521
522 bool canCauseComplexClip() {
523 return ((mOp != SkRegion::kIntersect_Op) && (mOp != SkRegion::kReplace_Op)) || !isRect();
524 }
525
526protected:
Chris Craikff785832013-03-08 13:12:16 -0800527 virtual bool isRect() { return false; }
528
529 SkRegion::Op mOp;
530};
531
532class ClipRectOp : public ClipOp {
Chris Craik2af46352012-11-26 18:30:17 -0800533public:
534 ClipRectOp(float left, float top, float right, float bottom, SkRegion::Op op)
Chris Craikff785832013-03-08 13:12:16 -0800535 : ClipOp(op), mArea(left, top, right, bottom) {}
Chris Craik2af46352012-11-26 18:30:17 -0800536
Chris Craikd41c4d82015-01-05 15:51:13 -0800537 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const override {
Chris Craik2af46352012-11-26 18:30:17 -0800538 renderer.clipRect(mArea.left, mArea.top, mArea.right, mArea.bottom, mOp);
539 }
540
Chris Craikd41c4d82015-01-05 15:51:13 -0800541 virtual void output(int level, uint32_t logFlags) const override {
Chris Craik2af46352012-11-26 18:30:17 -0800542 OP_LOG("ClipRect " RECT_STRING, RECT_ARGS(mArea));
543 }
544
Chris Craikd41c4d82015-01-05 15:51:13 -0800545 virtual const char* name() override { return "ClipRect"; }
Chris Craik2af46352012-11-26 18:30:17 -0800546
Chris Craikff785832013-03-08 13:12:16 -0800547protected:
Chris Craikd41c4d82015-01-05 15:51:13 -0800548 virtual bool isRect() override { return true; }
Chris Craikb98a0162013-02-21 11:30:22 -0800549
Chris Craik2af46352012-11-26 18:30:17 -0800550private:
551 Rect mArea;
Chris Craik2af46352012-11-26 18:30:17 -0800552};
553
Chris Craikff785832013-03-08 13:12:16 -0800554class ClipPathOp : public ClipOp {
Chris Craik2af46352012-11-26 18:30:17 -0800555public:
Chris Craikd218a922014-01-02 17:13:34 -0800556 ClipPathOp(const SkPath* path, SkRegion::Op op)
Chris Craikff785832013-03-08 13:12:16 -0800557 : ClipOp(op), mPath(path) {}
Chris Craik2af46352012-11-26 18:30:17 -0800558
Chris Craikd41c4d82015-01-05 15:51:13 -0800559 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const override {
Chris Craik2af46352012-11-26 18:30:17 -0800560 renderer.clipPath(mPath, mOp);
561 }
562
Chris Craikd41c4d82015-01-05 15:51:13 -0800563 virtual void output(int level, uint32_t logFlags) const override {
Chris Craik2af46352012-11-26 18:30:17 -0800564 SkRect bounds = mPath->getBounds();
565 OP_LOG("ClipPath bounds " RECT_STRING,
566 bounds.left(), bounds.top(), bounds.right(), bounds.bottom());
567 }
568
Chris Craikd41c4d82015-01-05 15:51:13 -0800569 virtual const char* name() override { return "ClipPath"; }
Chris Craik2af46352012-11-26 18:30:17 -0800570
571private:
Chris Craikd218a922014-01-02 17:13:34 -0800572 const SkPath* mPath;
Chris Craik2af46352012-11-26 18:30:17 -0800573};
574
Chris Craikff785832013-03-08 13:12:16 -0800575class ClipRegionOp : public ClipOp {
Chris Craik2af46352012-11-26 18:30:17 -0800576public:
Chris Craikd218a922014-01-02 17:13:34 -0800577 ClipRegionOp(const SkRegion* region, SkRegion::Op op)
Chris Craikff785832013-03-08 13:12:16 -0800578 : ClipOp(op), mRegion(region) {}
Chris Craik2af46352012-11-26 18:30:17 -0800579
Chris Craikd41c4d82015-01-05 15:51:13 -0800580 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const override {
Chris Craik2af46352012-11-26 18:30:17 -0800581 renderer.clipRegion(mRegion, mOp);
582 }
583
Chris Craikd41c4d82015-01-05 15:51:13 -0800584 virtual void output(int level, uint32_t logFlags) const override {
Chris Craik2af46352012-11-26 18:30:17 -0800585 SkIRect bounds = mRegion->getBounds();
586 OP_LOG("ClipRegion bounds %d %d %d %d",
587 bounds.left(), bounds.top(), bounds.right(), bounds.bottom());
588 }
589
Chris Craikd41c4d82015-01-05 15:51:13 -0800590 virtual const char* name() override { return "ClipRegion"; }
Chris Craik2af46352012-11-26 18:30:17 -0800591
592private:
Chris Craikd218a922014-01-02 17:13:34 -0800593 const SkRegion* mRegion;
Chris Craik2af46352012-11-26 18:30:17 -0800594};
595
Chris Craik2af46352012-11-26 18:30:17 -0800596///////////////////////////////////////////////////////////////////////////////
597// DRAW OPERATIONS - these are operations that can draw to the canvas's device
598///////////////////////////////////////////////////////////////////////////////
599
600class DrawBitmapOp : public DrawBoundedOp {
601public:
Chris Craik79647502014-08-06 13:42:24 -0700602 DrawBitmapOp(const SkBitmap* bitmap, const SkPaint* paint)
603 : DrawBoundedOp(0, 0, bitmap->width(), bitmap->height(), paint)
604 , mBitmap(bitmap)
Chris Craikd41c4d82015-01-05 15:51:13 -0800605 , mEntryValid(false), mEntry(nullptr) {
Romain Guy3b748a42013-04-17 18:54:38 -0700606 }
Chris Craik2af46352012-11-26 18:30:17 -0800607
Chris Craikd41c4d82015-01-05 15:51:13 -0800608 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
Tom Hudson107843d2014-09-08 11:26:26 -0400609 renderer.drawBitmap(mBitmap, mPaint);
Chris Craik2af46352012-11-26 18:30:17 -0800610 }
611
John Reckebd52612014-12-10 16:47:36 -0800612 AssetAtlas::Entry* getAtlasEntry(OpenGLRenderer& renderer) {
613 if (!mEntryValid) {
614 mEntryValid = true;
615 mEntry = renderer.renderState().assetAtlas().getEntry(mBitmap);
Romain Guy55b6f952013-06-27 15:27:09 -0700616 }
617 return mEntry;
618 }
619
Chris Craik527a3aa2013-03-04 10:19:31 -0800620#define SET_TEXTURE(ptr, posRect, offsetRect, texCoordsRect, xDim, yDim) \
621 TextureVertex::set(ptr++, posRect.xDim - offsetRect.left, posRect.yDim - offsetRect.top, \
622 texCoordsRect.xDim, texCoordsRect.yDim)
623
Romain Guy03c00b52013-06-20 18:30:28 -0700624 /**
625 * This multi-draw operation builds a mesh on the stack by generating a quad
626 * for each bitmap in the batch. This method is also responsible for dirtying
627 * the current layer, if any.
628 */
Andreas Gampe64bb4132014-11-22 00:35:09 +0000629 virtual void multiDraw(OpenGLRenderer& renderer, Rect& dirty,
Chris Craikd41c4d82015-01-05 15:51:13 -0800630 const Vector<OpStatePair>& ops, const Rect& bounds) override {
Chris Craikc1c5f082013-09-11 16:23:37 -0700631 const DeferredDisplayState& firstState = *(ops[0].state);
632 renderer.restoreDisplayState(firstState, true); // restore all but the clip
633
Chris Craik527a3aa2013-03-04 10:19:31 -0800634 TextureVertex vertices[6 * ops.size()];
635 TextureVertex* vertex = &vertices[0];
636
Romain Guy03c00b52013-06-20 18:30:28 -0700637 const bool hasLayer = renderer.hasLayer();
Chris Craik996fe652013-09-20 17:13:18 -0700638 bool pureTranslate = true;
Romain Guy2db5e992013-05-21 15:29:59 -0700639
Romain Guy3b748a42013-04-17 18:54:38 -0700640 // TODO: manually handle rect clip for bitmaps by adjusting texCoords per op,
641 // and allowing them to be merged in getBatchId()
Chris Craik527a3aa2013-03-04 10:19:31 -0800642 for (unsigned int i = 0; i < ops.size(); i++) {
Chris Craikc1c5f082013-09-11 16:23:37 -0700643 const DeferredDisplayState& state = *(ops[i].state);
644 const Rect& opBounds = state.mBounds;
Romain Guy2db5e992013-05-21 15:29:59 -0700645 // When we reach multiDraw(), the matrix can be either
646 // pureTranslate or simple (translate and/or scale).
647 // If the matrix is not pureTranslate, then we have a scale
Chris Craik996fe652013-09-20 17:13:18 -0700648 pureTranslate &= state.mMatrix.isPureTranslate();
Romain Guy3b748a42013-04-17 18:54:38 -0700649
650 Rect texCoords(0, 0, 1, 1);
John Reckebd52612014-12-10 16:47:36 -0800651 ((DrawBitmapOp*) ops[i].op)->uvMap(renderer, texCoords);
Romain Guy3b748a42013-04-17 18:54:38 -0700652
Chris Craik527a3aa2013-03-04 10:19:31 -0800653 SET_TEXTURE(vertex, opBounds, bounds, texCoords, left, top);
654 SET_TEXTURE(vertex, opBounds, bounds, texCoords, right, top);
655 SET_TEXTURE(vertex, opBounds, bounds, texCoords, left, bottom);
656
657 SET_TEXTURE(vertex, opBounds, bounds, texCoords, left, bottom);
658 SET_TEXTURE(vertex, opBounds, bounds, texCoords, right, top);
659 SET_TEXTURE(vertex, opBounds, bounds, texCoords, right, bottom);
Romain Guy03c00b52013-06-20 18:30:28 -0700660
661 if (hasLayer) {
Chris Craikc1c5f082013-09-11 16:23:37 -0700662 renderer.dirtyLayer(opBounds.left, opBounds.top, opBounds.right, opBounds.bottom);
Romain Guy03c00b52013-06-20 18:30:28 -0700663 }
Chris Craik527a3aa2013-03-04 10:19:31 -0800664 }
665
Tom Hudson107843d2014-09-08 11:26:26 -0400666 renderer.drawBitmaps(mBitmap, mEntry, ops.size(), &vertices[0],
Chris Craik996fe652013-09-20 17:13:18 -0700667 pureTranslate, bounds, mPaint);
Chris Craik527a3aa2013-03-04 10:19:31 -0800668 }
669
Chris Craikd41c4d82015-01-05 15:51:13 -0800670 virtual void output(int level, uint32_t logFlags) const override {
John Reckdad7d84c2014-12-09 12:33:26 -0800671 OP_LOG("Draw bitmap %p at %f %f%s", mBitmap, mLocalBounds.left, mLocalBounds.top,
672 mEntry ? " using AssetAtlas" : "");
Chris Craik2af46352012-11-26 18:30:17 -0800673 }
674
Chris Craikd41c4d82015-01-05 15:51:13 -0800675 virtual const char* name() override { return "DrawBitmap"; }
Chris Craik527a3aa2013-03-04 10:19:31 -0800676
Andreas Gampe64bb4132014-11-22 00:35:09 +0000677 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
Chris Craikd41c4d82015-01-05 15:51:13 -0800678 const DeferredDisplayState& state) override {
Chris Craik28ce94a2013-05-31 11:38:03 -0700679 deferInfo.batchId = DeferredDisplayList::kOpBatch_Bitmap;
John Reckebd52612014-12-10 16:47:36 -0800680 deferInfo.mergeId = getAtlasEntry(renderer) ?
Chris Craikd965bc52013-09-16 14:47:13 -0700681 (mergeid_t) mEntry->getMergeId() : (mergeid_t) mBitmap;
Romain Guy2db5e992013-05-21 15:29:59 -0700682
Chris Craikd965bc52013-09-16 14:47:13 -0700683 // Don't merge non-simply transformed or neg scale ops, SET_TEXTURE doesn't handle rotation
Chris Craik28ce94a2013-05-31 11:38:03 -0700684 // Don't merge A8 bitmaps - the paint's color isn't compared by mergeId, or in
685 // MergingDrawBatch::canMergeWith()
686 // TODO: support clipped bitmaps by handling them in SET_TEXTURE
Chris Craikd965bc52013-09-16 14:47:13 -0700687 deferInfo.mergeable = state.mMatrix.isSimple() && state.mMatrix.positiveScale() &&
688 !state.mClipSideFlags &&
Chris Craik28ce94a2013-05-31 11:38:03 -0700689 OpenGLRenderer::getXfermodeDirect(mPaint) == SkXfermode::kSrcOver_Mode &&
Mike Reed1103b322014-07-08 12:36:44 -0400690 (mBitmap->colorType() != kAlpha_8_SkColorType);
Chris Craikc3566d02013-02-04 16:16:33 -0800691 }
Chris Craik2af46352012-11-26 18:30:17 -0800692
John Reckebd52612014-12-10 16:47:36 -0800693 void uvMap(OpenGLRenderer& renderer, Rect& texCoords) {
694 if (getAtlasEntry(renderer)) {
695 mEntry->uvMapper.map(texCoords);
696 }
697 }
698
Chris Craik527a3aa2013-03-04 10:19:31 -0800699 const SkBitmap* bitmap() { return mBitmap; }
Chris Craik2af46352012-11-26 18:30:17 -0800700protected:
Chris Craikd218a922014-01-02 17:13:34 -0800701 const SkBitmap* mBitmap;
John Reckebd52612014-12-10 16:47:36 -0800702 bool mEntryValid;
Romain Guy55b6f952013-06-27 15:27:09 -0700703 AssetAtlas::Entry* mEntry;
Chris Craik2af46352012-11-26 18:30:17 -0800704};
705
Chris Craik2af46352012-11-26 18:30:17 -0800706class DrawBitmapRectOp : public DrawBoundedOp {
707public:
Chris Craikd218a922014-01-02 17:13:34 -0800708 DrawBitmapRectOp(const SkBitmap* bitmap,
709 float srcLeft, float srcTop, float srcRight, float srcBottom,
710 float dstLeft, float dstTop, float dstRight, float dstBottom, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -0800711 : DrawBoundedOp(dstLeft, dstTop, dstRight, dstBottom, paint),
712 mBitmap(bitmap), mSrc(srcLeft, srcTop, srcRight, srcBottom) {}
713
Chris Craikd41c4d82015-01-05 15:51:13 -0800714 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
Tom Hudson107843d2014-09-08 11:26:26 -0400715 renderer.drawBitmap(mBitmap, mSrc.left, mSrc.top, mSrc.right, mSrc.bottom,
Chris Craik2af46352012-11-26 18:30:17 -0800716 mLocalBounds.left, mLocalBounds.top, mLocalBounds.right, mLocalBounds.bottom,
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -0400717 mPaint);
Chris Craik2af46352012-11-26 18:30:17 -0800718 }
719
Chris Craikd41c4d82015-01-05 15:51:13 -0800720 virtual void output(int level, uint32_t logFlags) const override {
John Reckce444ca2014-06-02 15:12:36 -0700721 OP_LOG("Draw bitmap %p src=" RECT_STRING ", dst=" RECT_STRING,
Chris Craik2af46352012-11-26 18:30:17 -0800722 mBitmap, RECT_ARGS(mSrc), RECT_ARGS(mLocalBounds));
723 }
724
Chris Craikd41c4d82015-01-05 15:51:13 -0800725 virtual const char* name() override { return "DrawBitmapRect"; }
Chris Craik527a3aa2013-03-04 10:19:31 -0800726
Andreas Gampe64bb4132014-11-22 00:35:09 +0000727 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
Chris Craikd41c4d82015-01-05 15:51:13 -0800728 const DeferredDisplayState& state) override {
Chris Craik28ce94a2013-05-31 11:38:03 -0700729 deferInfo.batchId = DeferredDisplayList::kOpBatch_Bitmap;
Chris Craikc3566d02013-02-04 16:16:33 -0800730 }
Chris Craik2af46352012-11-26 18:30:17 -0800731
732private:
Chris Craikd218a922014-01-02 17:13:34 -0800733 const SkBitmap* mBitmap;
Chris Craik2af46352012-11-26 18:30:17 -0800734 Rect mSrc;
735};
736
737class DrawBitmapDataOp : public DrawBitmapOp {
738public:
Chris Craik79647502014-08-06 13:42:24 -0700739 DrawBitmapDataOp(const SkBitmap* bitmap, const SkPaint* paint)
740 : DrawBitmapOp(bitmap, paint) {}
Chris Craik2af46352012-11-26 18:30:17 -0800741
Chris Craikd41c4d82015-01-05 15:51:13 -0800742 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
Tom Hudson107843d2014-09-08 11:26:26 -0400743 renderer.drawBitmapData(mBitmap, mPaint);
Chris Craik2af46352012-11-26 18:30:17 -0800744 }
745
Chris Craikd41c4d82015-01-05 15:51:13 -0800746 virtual void output(int level, uint32_t logFlags) const override {
Chris Craik2af46352012-11-26 18:30:17 -0800747 OP_LOG("Draw bitmap %p", mBitmap);
748 }
749
Chris Craikd41c4d82015-01-05 15:51:13 -0800750 virtual const char* name() override { return "DrawBitmapData"; }
Chris Craik527a3aa2013-03-04 10:19:31 -0800751
Andreas Gampe64bb4132014-11-22 00:35:09 +0000752 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
Chris Craikd41c4d82015-01-05 15:51:13 -0800753 const DeferredDisplayState& state) override {
Chris Craik28ce94a2013-05-31 11:38:03 -0700754 deferInfo.batchId = DeferredDisplayList::kOpBatch_Bitmap;
Chris Craikc3566d02013-02-04 16:16:33 -0800755 }
Chris Craik2af46352012-11-26 18:30:17 -0800756};
757
Chris Craik5d116762013-02-19 17:49:31 -0800758class DrawBitmapMeshOp : public DrawBoundedOp {
Chris Craik2af46352012-11-26 18:30:17 -0800759public:
Chris Craikd218a922014-01-02 17:13:34 -0800760 DrawBitmapMeshOp(const SkBitmap* bitmap, int meshWidth, int meshHeight,
761 const float* vertices, const int* colors, const SkPaint* paint)
Chris Craik5d116762013-02-19 17:49:31 -0800762 : DrawBoundedOp(vertices, 2 * (meshWidth + 1) * (meshHeight + 1), paint),
763 mBitmap(bitmap), mMeshWidth(meshWidth), mMeshHeight(meshHeight),
Chris Craik2af46352012-11-26 18:30:17 -0800764 mVertices(vertices), mColors(colors) {}
765
Chris Craikd41c4d82015-01-05 15:51:13 -0800766 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
Tom Hudson107843d2014-09-08 11:26:26 -0400767 renderer.drawBitmapMesh(mBitmap, mMeshWidth, mMeshHeight,
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -0400768 mVertices, mColors, mPaint);
Chris Craik2af46352012-11-26 18:30:17 -0800769 }
770
Chris Craikd41c4d82015-01-05 15:51:13 -0800771 virtual void output(int level, uint32_t logFlags) const override {
Chris Craik2af46352012-11-26 18:30:17 -0800772 OP_LOG("Draw bitmap %p mesh %d x %d", mBitmap, mMeshWidth, mMeshHeight);
773 }
774
Chris Craikd41c4d82015-01-05 15:51:13 -0800775 virtual const char* name() override { return "DrawBitmapMesh"; }
Chris Craik527a3aa2013-03-04 10:19:31 -0800776
Andreas Gampe64bb4132014-11-22 00:35:09 +0000777 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
Chris Craikd41c4d82015-01-05 15:51:13 -0800778 const DeferredDisplayState& state) override {
Chris Craik28ce94a2013-05-31 11:38:03 -0700779 deferInfo.batchId = DeferredDisplayList::kOpBatch_Bitmap;
Chris Craikc3566d02013-02-04 16:16:33 -0800780 }
Chris Craik2af46352012-11-26 18:30:17 -0800781
782private:
Chris Craikd218a922014-01-02 17:13:34 -0800783 const SkBitmap* mBitmap;
Chris Craik2af46352012-11-26 18:30:17 -0800784 int mMeshWidth;
785 int mMeshHeight;
Chris Craikd218a922014-01-02 17:13:34 -0800786 const float* mVertices;
787 const int* mColors;
Chris Craik2af46352012-11-26 18:30:17 -0800788};
789
790class DrawPatchOp : public DrawBoundedOp {
791public:
Chris Craikd218a922014-01-02 17:13:34 -0800792 DrawPatchOp(const SkBitmap* bitmap, const Res_png_9patch* patch,
793 float left, float top, float right, float bottom, const SkPaint* paint)
Romain Guy03c00b52013-06-20 18:30:28 -0700794 : DrawBoundedOp(left, top, right, bottom, paint),
Chris Craikd41c4d82015-01-05 15:51:13 -0800795 mBitmap(bitmap), mPatch(patch), mGenerationId(0), mMesh(nullptr),
796 mEntryValid(false), mEntry(nullptr) {
Romain Guy3b748a42013-04-17 18:54:38 -0700797 };
Chris Craik2af46352012-11-26 18:30:17 -0800798
John Reckebd52612014-12-10 16:47:36 -0800799 AssetAtlas::Entry* getAtlasEntry(OpenGLRenderer& renderer) {
800 if (!mEntryValid) {
801 mEntryValid = true;
802 mEntry = renderer.renderState().assetAtlas().getEntry(mBitmap);
Romain Guy55b6f952013-06-27 15:27:09 -0700803 }
804 return mEntry;
805 }
806
Romain Guy03c00b52013-06-20 18:30:28 -0700807 const Patch* getMesh(OpenGLRenderer& renderer) {
Romain Guy4c2547f2013-06-11 16:19:24 -0700808 if (!mMesh || renderer.getCaches().patchCache.getGenerationId() != mGenerationId) {
809 PatchCache& cache = renderer.getCaches().patchCache;
John Reckebd52612014-12-10 16:47:36 -0800810 mMesh = cache.get(getAtlasEntry(renderer), mBitmap->width(), mBitmap->height(),
Romain Guy03c00b52013-06-20 18:30:28 -0700811 mLocalBounds.getWidth(), mLocalBounds.getHeight(), mPatch);
Romain Guy4c2547f2013-06-11 16:19:24 -0700812 mGenerationId = cache.getGenerationId();
813 }
Romain Guy03c00b52013-06-20 18:30:28 -0700814 return mMesh;
815 }
816
817 /**
818 * This multi-draw operation builds an indexed mesh on the stack by copying
819 * and transforming the vertices of each 9-patch in the batch. This method
820 * is also responsible for dirtying the current layer, if any.
821 */
Andreas Gampe64bb4132014-11-22 00:35:09 +0000822 virtual void multiDraw(OpenGLRenderer& renderer, Rect& dirty,
Chris Craikd41c4d82015-01-05 15:51:13 -0800823 const Vector<OpStatePair>& ops, const Rect& bounds) override {
Chris Craikc1c5f082013-09-11 16:23:37 -0700824 const DeferredDisplayState& firstState = *(ops[0].state);
825 renderer.restoreDisplayState(firstState, true); // restore all but the clip
Romain Guy03c00b52013-06-20 18:30:28 -0700826
827 // Batches will usually contain a small number of items so it's
828 // worth performing a first iteration to count the exact number
829 // of vertices we need in the new mesh
830 uint32_t totalVertices = 0;
831 for (unsigned int i = 0; i < ops.size(); i++) {
Chris Craikc1c5f082013-09-11 16:23:37 -0700832 totalVertices += ((DrawPatchOp*) ops[i].op)->getMesh(renderer)->verticesCount;
Romain Guy03c00b52013-06-20 18:30:28 -0700833 }
834
835 const bool hasLayer = renderer.hasLayer();
836
837 uint32_t indexCount = 0;
838
839 TextureVertex vertices[totalVertices];
840 TextureVertex* vertex = &vertices[0];
841
842 // Create a mesh that contains the transformed vertices for all the
843 // 9-patch objects that are part of the batch. Note that onDefer()
844 // enforces ops drawn by this function to have a pure translate or
845 // identity matrix
846 for (unsigned int i = 0; i < ops.size(); i++) {
Chris Craikc1c5f082013-09-11 16:23:37 -0700847 DrawPatchOp* patchOp = (DrawPatchOp*) ops[i].op;
848 const DeferredDisplayState* state = ops[i].state;
Romain Guy03c00b52013-06-20 18:30:28 -0700849 const Patch* opMesh = patchOp->getMesh(renderer);
850 uint32_t vertexCount = opMesh->verticesCount;
851 if (vertexCount == 0) continue;
852
853 // We use the bounds to know where to translate our vertices
854 // Using patchOp->state.mBounds wouldn't work because these
855 // bounds are clipped
Chris Craikc1c5f082013-09-11 16:23:37 -0700856 const float tx = (int) floorf(state->mMatrix.getTranslateX() +
Romain Guy03c00b52013-06-20 18:30:28 -0700857 patchOp->mLocalBounds.left + 0.5f);
Chris Craikc1c5f082013-09-11 16:23:37 -0700858 const float ty = (int) floorf(state->mMatrix.getTranslateY() +
Romain Guy03c00b52013-06-20 18:30:28 -0700859 patchOp->mLocalBounds.top + 0.5f);
860
861 // Copy & transform all the vertices for the current operation
Chris Craik51d6a3d2014-12-22 17:16:56 -0800862 TextureVertex* opVertices = opMesh->vertices.get();
Romain Guy03c00b52013-06-20 18:30:28 -0700863 for (uint32_t j = 0; j < vertexCount; j++, opVertices++) {
864 TextureVertex::set(vertex++,
Romain Guy3380cfd2013-08-15 16:57:57 -0700865 opVertices->x + tx, opVertices->y + ty,
866 opVertices->u, opVertices->v);
Romain Guy03c00b52013-06-20 18:30:28 -0700867 }
868
869 // Dirty the current layer if possible. When the 9-patch does not
870 // contain empty quads we can take a shortcut and simply set the
871 // dirty rect to the object's bounds.
872 if (hasLayer) {
873 if (!opMesh->hasEmptyQuads) {
874 renderer.dirtyLayer(tx, ty,
875 tx + patchOp->mLocalBounds.getWidth(),
876 ty + patchOp->mLocalBounds.getHeight());
877 } else {
878 const size_t count = opMesh->quads.size();
879 for (size_t i = 0; i < count; i++) {
880 const Rect& quadBounds = opMesh->quads[i];
881 const float x = tx + quadBounds.left;
882 const float y = ty + quadBounds.top;
883 renderer.dirtyLayer(x, y,
884 x + quadBounds.getWidth(), y + quadBounds.getHeight());
885 }
886 }
887 }
888
889 indexCount += opMesh->indexCount;
890 }
891
Yohann Roussel59cf7342014-12-11 11:10:50 +0100892 renderer.drawPatches(mBitmap, getAtlasEntry(renderer),
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -0400893 &vertices[0], indexCount, mPaint);
Romain Guy03c00b52013-06-20 18:30:28 -0700894 }
895
Chris Craikd41c4d82015-01-05 15:51:13 -0800896 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
Romain Guy4c2547f2013-06-11 16:19:24 -0700897 // We're not calling the public variant of drawPatch() here
898 // This method won't perform the quickReject() since we've already done it at this point
Yohann Roussel59cf7342014-12-11 11:10:50 +0100899 renderer.drawPatch(mBitmap, getMesh(renderer), getAtlasEntry(renderer),
Romain Guy03c00b52013-06-20 18:30:28 -0700900 mLocalBounds.left, mLocalBounds.top, mLocalBounds.right, mLocalBounds.bottom,
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -0400901 mPaint);
Chris Craik2af46352012-11-26 18:30:17 -0800902 }
903
Chris Craikd41c4d82015-01-05 15:51:13 -0800904 virtual void output(int level, uint32_t logFlags) const override {
John Reckdad7d84c2014-12-09 12:33:26 -0800905 OP_LOG("Draw patch " RECT_STRING "%s", RECT_ARGS(mLocalBounds),
906 mEntry ? " with AssetAtlas" : "");
Chris Craik2af46352012-11-26 18:30:17 -0800907 }
908
Chris Craikd41c4d82015-01-05 15:51:13 -0800909 virtual const char* name() override { return "DrawPatch"; }
Chris Craik527a3aa2013-03-04 10:19:31 -0800910
Andreas Gampe64bb4132014-11-22 00:35:09 +0000911 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
Chris Craikd41c4d82015-01-05 15:51:13 -0800912 const DeferredDisplayState& state) override {
Chris Craik28ce94a2013-05-31 11:38:03 -0700913 deferInfo.batchId = DeferredDisplayList::kOpBatch_Patch;
John Reckebd52612014-12-10 16:47:36 -0800914 deferInfo.mergeId = getAtlasEntry(renderer) ? (mergeid_t) mEntry->getMergeId() : (mergeid_t) mBitmap;
Romain Guy03c00b52013-06-20 18:30:28 -0700915 deferInfo.mergeable = state.mMatrix.isPureTranslate() &&
916 OpenGLRenderer::getXfermodeDirect(mPaint) == SkXfermode::kSrcOver_Mode;
Chris Craikc1c5f082013-09-11 16:23:37 -0700917 deferInfo.opaqueOverBounds = isOpaqueOverBounds(state) && mBitmap->isOpaque();
Chris Craikc3566d02013-02-04 16:16:33 -0800918 }
Chris Craik2af46352012-11-26 18:30:17 -0800919
920private:
Chris Craikd218a922014-01-02 17:13:34 -0800921 const SkBitmap* mBitmap;
922 const Res_png_9patch* mPatch;
Romain Guy4c2547f2013-06-11 16:19:24 -0700923
Romain Guy4c2547f2013-06-11 16:19:24 -0700924 uint32_t mGenerationId;
925 const Patch* mMesh;
Romain Guy03c00b52013-06-20 18:30:28 -0700926
John Reckebd52612014-12-10 16:47:36 -0800927 bool mEntryValid;
Romain Guy3b748a42013-04-17 18:54:38 -0700928 AssetAtlas::Entry* mEntry;
Chris Craik2af46352012-11-26 18:30:17 -0800929};
930
931class DrawColorOp : public DrawOp {
932public:
933 DrawColorOp(int color, SkXfermode::Mode mode)
Chris Craikd41c4d82015-01-05 15:51:13 -0800934 : DrawOp(nullptr), mColor(color), mMode(mode) {};
Chris Craik2af46352012-11-26 18:30:17 -0800935
Chris Craikd41c4d82015-01-05 15:51:13 -0800936 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
Tom Hudson107843d2014-09-08 11:26:26 -0400937 renderer.drawColor(mColor, mMode);
Chris Craik2af46352012-11-26 18:30:17 -0800938 }
939
Chris Craikd41c4d82015-01-05 15:51:13 -0800940 virtual void output(int level, uint32_t logFlags) const override {
Chris Craik2af46352012-11-26 18:30:17 -0800941 OP_LOG("Draw color %#x, mode %d", mColor, mMode);
942 }
943
Chris Craikd41c4d82015-01-05 15:51:13 -0800944 virtual const char* name() override { return "DrawColor"; }
Chris Craik2af46352012-11-26 18:30:17 -0800945
946private:
947 int mColor;
948 SkXfermode::Mode mMode;
949};
950
951class DrawStrokableOp : public DrawBoundedOp {
952public:
Chris Craikd218a922014-01-02 17:13:34 -0800953 DrawStrokableOp(float left, float top, float right, float bottom, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -0800954 : DrawBoundedOp(left, top, right, bottom, paint) {};
Chris Craik947eabf2014-08-19 10:21:12 -0700955 DrawStrokableOp(const Rect& localBounds, const SkPaint* paint)
956 : DrawBoundedOp(localBounds, paint) {};
Chris Craik2af46352012-11-26 18:30:17 -0800957
Chris Craikd41c4d82015-01-05 15:51:13 -0800958 virtual bool getLocalBounds(Rect& localBounds) override {
Chris Craikc3566d02013-02-04 16:16:33 -0800959 localBounds.set(mLocalBounds);
Chris Craik2af46352012-11-26 18:30:17 -0800960 if (mPaint && mPaint->getStyle() != SkPaint::kFill_Style) {
Chris Craikc3566d02013-02-04 16:16:33 -0800961 localBounds.outset(strokeWidthOutset());
Chris Craik2af46352012-11-26 18:30:17 -0800962 }
963 return true;
964 }
Chris Craikc3566d02013-02-04 16:16:33 -0800965
Andreas Gampe64bb4132014-11-22 00:35:09 +0000966 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
Chris Craikd41c4d82015-01-05 15:51:13 -0800967 const DeferredDisplayState& state) override {
Chris Craikc3566d02013-02-04 16:16:33 -0800968 if (mPaint->getPathEffect()) {
Chris Craik28ce94a2013-05-31 11:38:03 -0700969 deferInfo.batchId = DeferredDisplayList::kOpBatch_AlphaMaskTexture;
Chris Craik527a3aa2013-03-04 10:19:31 -0800970 } else {
Chris Craik28ce94a2013-05-31 11:38:03 -0700971 deferInfo.batchId = mPaint->isAntiAlias() ?
Chris Craik527a3aa2013-03-04 10:19:31 -0800972 DeferredDisplayList::kOpBatch_AlphaVertices :
973 DeferredDisplayList::kOpBatch_Vertices;
Chris Craikc3566d02013-02-04 16:16:33 -0800974 }
Chris Craikc3566d02013-02-04 16:16:33 -0800975 }
Chris Craik2af46352012-11-26 18:30:17 -0800976};
977
978class DrawRectOp : public DrawStrokableOp {
979public:
Chris Craikd218a922014-01-02 17:13:34 -0800980 DrawRectOp(float left, float top, float right, float bottom, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -0800981 : DrawStrokableOp(left, top, right, bottom, paint) {}
982
Chris Craikd41c4d82015-01-05 15:51:13 -0800983 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
Tom Hudson107843d2014-09-08 11:26:26 -0400984 renderer.drawRect(mLocalBounds.left, mLocalBounds.top,
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -0400985 mLocalBounds.right, mLocalBounds.bottom, mPaint);
Chris Craik2af46352012-11-26 18:30:17 -0800986 }
987
Chris Craikd41c4d82015-01-05 15:51:13 -0800988 virtual void output(int level, uint32_t logFlags) const override {
John Reckce444ca2014-06-02 15:12:36 -0700989 OP_LOG("Draw Rect " RECT_STRING, RECT_ARGS(mLocalBounds));
Chris Craik2af46352012-11-26 18:30:17 -0800990 }
991
Chris Craikc1c5f082013-09-11 16:23:37 -0700992 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
Chris Craikd41c4d82015-01-05 15:51:13 -0800993 const DeferredDisplayState& state) override {
Chris Craikc1c5f082013-09-11 16:23:37 -0700994 DrawStrokableOp::onDefer(renderer, deferInfo, state);
995 deferInfo.opaqueOverBounds = isOpaqueOverBounds(state) &&
Chris Craik28ce94a2013-05-31 11:38:03 -0700996 mPaint->getStyle() == SkPaint::kFill_Style;
997 }
998
Chris Craikd41c4d82015-01-05 15:51:13 -0800999 virtual const char* name() override { return "DrawRect"; }
Chris Craik2af46352012-11-26 18:30:17 -08001000};
1001
Chris Craik5d116762013-02-19 17:49:31 -08001002class DrawRectsOp : public DrawBoundedOp {
Chris Craik2af46352012-11-26 18:30:17 -08001003public:
Chris Craikd218a922014-01-02 17:13:34 -08001004 DrawRectsOp(const float* rects, int count, const SkPaint* paint)
Chris Craik5d116762013-02-19 17:49:31 -08001005 : DrawBoundedOp(rects, count, paint),
1006 mRects(rects), mCount(count) {}
Chris Craik2af46352012-11-26 18:30:17 -08001007
Chris Craikd41c4d82015-01-05 15:51:13 -08001008 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
Tom Hudson107843d2014-09-08 11:26:26 -04001009 renderer.drawRects(mRects, mCount, mPaint);
Chris Craik2af46352012-11-26 18:30:17 -08001010 }
1011
Chris Craikd41c4d82015-01-05 15:51:13 -08001012 virtual void output(int level, uint32_t logFlags) const override {
Chris Craik2af46352012-11-26 18:30:17 -08001013 OP_LOG("Draw Rects count %d", mCount);
1014 }
1015
Chris Craikd41c4d82015-01-05 15:51:13 -08001016 virtual const char* name() override { return "DrawRects"; }
Chris Craik2af46352012-11-26 18:30:17 -08001017
Andreas Gampe64bb4132014-11-22 00:35:09 +00001018 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
Chris Craikd41c4d82015-01-05 15:51:13 -08001019 const DeferredDisplayState& state) override {
Chris Craik28ce94a2013-05-31 11:38:03 -07001020 deferInfo.batchId = DeferredDisplayList::kOpBatch_Vertices;
Chris Craikc3566d02013-02-04 16:16:33 -08001021 }
1022
Chris Craik2af46352012-11-26 18:30:17 -08001023private:
1024 const float* mRects;
1025 int mCount;
1026};
1027
1028class DrawRoundRectOp : public DrawStrokableOp {
1029public:
1030 DrawRoundRectOp(float left, float top, float right, float bottom,
Chris Craikd218a922014-01-02 17:13:34 -08001031 float rx, float ry, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001032 : DrawStrokableOp(left, top, right, bottom, paint), mRx(rx), mRy(ry) {}
1033
Chris Craikd41c4d82015-01-05 15:51:13 -08001034 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
Tom Hudson107843d2014-09-08 11:26:26 -04001035 renderer.drawRoundRect(mLocalBounds.left, mLocalBounds.top,
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -04001036 mLocalBounds.right, mLocalBounds.bottom, mRx, mRy, mPaint);
Chris Craik2af46352012-11-26 18:30:17 -08001037 }
1038
Chris Craikd41c4d82015-01-05 15:51:13 -08001039 virtual void output(int level, uint32_t logFlags) const override {
John Reckce444ca2014-06-02 15:12:36 -07001040 OP_LOG("Draw RoundRect " RECT_STRING ", rx %f, ry %f", RECT_ARGS(mLocalBounds), mRx, mRy);
Chris Craik2af46352012-11-26 18:30:17 -08001041 }
1042
Chris Craik05f3d6e2014-06-02 16:27:04 -07001043 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
Chris Craikd41c4d82015-01-05 15:51:13 -08001044 const DeferredDisplayState& state) override {
Chris Craik05f3d6e2014-06-02 16:27:04 -07001045 DrawStrokableOp::onDefer(renderer, deferInfo, state);
1046 if (!mPaint->getPathEffect()) {
Chris Craik6ac174b2014-06-17 13:47:05 -07001047 renderer.getCaches().tessellationCache.precacheRoundRect(state.mMatrix, *mPaint,
1048 mLocalBounds.getWidth(), mLocalBounds.getHeight(), mRx, mRy);
Chris Craik05f3d6e2014-06-02 16:27:04 -07001049 }
1050 }
1051
Chris Craikd41c4d82015-01-05 15:51:13 -08001052 virtual const char* name() override { return "DrawRoundRect"; }
Chris Craik2af46352012-11-26 18:30:17 -08001053
1054private:
1055 float mRx;
1056 float mRy;
1057};
1058
Jorim Jaggi072707d2014-09-15 17:20:08 +02001059class DrawRoundRectPropsOp : public DrawOp {
1060public:
1061 DrawRoundRectPropsOp(float* left, float* top, float* right, float* bottom,
1062 float *rx, float *ry, const SkPaint* paint)
1063 : DrawOp(paint), mLeft(left), mTop(top), mRight(right), mBottom(bottom),
1064 mRx(rx), mRy(ry) {}
1065
Chris Craikd41c4d82015-01-05 15:51:13 -08001066 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
Tom Hudson107843d2014-09-08 11:26:26 -04001067 renderer.drawRoundRect(*mLeft, *mTop, *mRight, *mBottom,
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -04001068 *mRx, *mRy, mPaint);
Jorim Jaggi072707d2014-09-15 17:20:08 +02001069 }
1070
Chris Craikd41c4d82015-01-05 15:51:13 -08001071 virtual void output(int level, uint32_t logFlags) const override {
Jorim Jaggi072707d2014-09-15 17:20:08 +02001072 OP_LOG("Draw RoundRect Props " RECT_STRING ", rx %f, ry %f",
1073 *mLeft, *mTop, *mRight, *mBottom, *mRx, *mRy);
1074 }
1075
Chris Craikd41c4d82015-01-05 15:51:13 -08001076 virtual const char* name() override { return "DrawRoundRectProps"; }
Jorim Jaggi072707d2014-09-15 17:20:08 +02001077
1078private:
1079 float* mLeft;
1080 float* mTop;
1081 float* mRight;
1082 float* mBottom;
1083 float* mRx;
1084 float* mRy;
1085};
1086
Chris Craik2af46352012-11-26 18:30:17 -08001087class DrawCircleOp : public DrawStrokableOp {
1088public:
Chris Craikd218a922014-01-02 17:13:34 -08001089 DrawCircleOp(float x, float y, float radius, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001090 : DrawStrokableOp(x - radius, y - radius, x + radius, y + radius, paint),
1091 mX(x), mY(y), mRadius(radius) {}
1092
Chris Craikd41c4d82015-01-05 15:51:13 -08001093 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
Tom Hudson107843d2014-09-08 11:26:26 -04001094 renderer.drawCircle(mX, mY, mRadius, mPaint);
Chris Craik2af46352012-11-26 18:30:17 -08001095 }
1096
Chris Craikd41c4d82015-01-05 15:51:13 -08001097 virtual void output(int level, uint32_t logFlags) const override {
Chris Craik2af46352012-11-26 18:30:17 -08001098 OP_LOG("Draw Circle x %f, y %f, r %f", mX, mY, mRadius);
1099 }
1100
Chris Craikd41c4d82015-01-05 15:51:13 -08001101 virtual const char* name() override { return "DrawCircle"; }
Chris Craik2af46352012-11-26 18:30:17 -08001102
1103private:
1104 float mX;
1105 float mY;
1106 float mRadius;
1107};
1108
John Reck52244ff2014-05-01 21:27:37 -07001109class DrawCirclePropsOp : public DrawOp {
1110public:
1111 DrawCirclePropsOp(float* x, float* y, float* radius, const SkPaint* paint)
1112 : DrawOp(paint), mX(x), mY(y), mRadius(radius) {}
1113
Chris Craikd41c4d82015-01-05 15:51:13 -08001114 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
Tom Hudson107843d2014-09-08 11:26:26 -04001115 renderer.drawCircle(*mX, *mY, *mRadius, mPaint);
John Reck52244ff2014-05-01 21:27:37 -07001116 }
1117
Chris Craikd41c4d82015-01-05 15:51:13 -08001118 virtual void output(int level, uint32_t logFlags) const override {
John Reck52244ff2014-05-01 21:27:37 -07001119 OP_LOG("Draw Circle Props x %p, y %p, r %p", mX, mY, mRadius);
1120 }
1121
Chris Craikd41c4d82015-01-05 15:51:13 -08001122 virtual const char* name() override { return "DrawCircleProps"; }
John Reck52244ff2014-05-01 21:27:37 -07001123
1124private:
1125 float* mX;
1126 float* mY;
1127 float* mRadius;
1128};
1129
Chris Craik2af46352012-11-26 18:30:17 -08001130class DrawOvalOp : public DrawStrokableOp {
1131public:
Chris Craikd218a922014-01-02 17:13:34 -08001132 DrawOvalOp(float left, float top, float right, float bottom, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001133 : DrawStrokableOp(left, top, right, bottom, paint) {}
1134
Chris Craikd41c4d82015-01-05 15:51:13 -08001135 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
Tom Hudson107843d2014-09-08 11:26:26 -04001136 renderer.drawOval(mLocalBounds.left, mLocalBounds.top,
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -04001137 mLocalBounds.right, mLocalBounds.bottom, 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 Oval " RECT_STRING, RECT_ARGS(mLocalBounds));
Chris Craik2af46352012-11-26 18:30:17 -08001142 }
1143
Chris Craikd41c4d82015-01-05 15:51:13 -08001144 virtual const char* name() override { return "DrawOval"; }
Chris Craik2af46352012-11-26 18:30:17 -08001145};
1146
1147class DrawArcOp : public DrawStrokableOp {
1148public:
1149 DrawArcOp(float left, float top, float right, float bottom,
Chris Craikd218a922014-01-02 17:13:34 -08001150 float startAngle, float sweepAngle, bool useCenter, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001151 : DrawStrokableOp(left, top, right, bottom, paint),
1152 mStartAngle(startAngle), mSweepAngle(sweepAngle), mUseCenter(useCenter) {}
1153
Chris Craikd41c4d82015-01-05 15:51:13 -08001154 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
Tom Hudson107843d2014-09-08 11:26:26 -04001155 renderer.drawArc(mLocalBounds.left, mLocalBounds.top,
Chris Craik2af46352012-11-26 18:30:17 -08001156 mLocalBounds.right, mLocalBounds.bottom,
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -04001157 mStartAngle, mSweepAngle, mUseCenter, mPaint);
Chris Craik2af46352012-11-26 18:30:17 -08001158 }
1159
Chris Craikd41c4d82015-01-05 15:51:13 -08001160 virtual void output(int level, uint32_t logFlags) const override {
John Reckce444ca2014-06-02 15:12:36 -07001161 OP_LOG("Draw Arc " RECT_STRING ", start %f, sweep %f, useCenter %d",
Chris Craik2af46352012-11-26 18:30:17 -08001162 RECT_ARGS(mLocalBounds), mStartAngle, mSweepAngle, mUseCenter);
1163 }
1164
Chris Craikd41c4d82015-01-05 15:51:13 -08001165 virtual const char* name() override { return "DrawArc"; }
Chris Craik2af46352012-11-26 18:30:17 -08001166
1167private:
1168 float mStartAngle;
1169 float mSweepAngle;
1170 bool mUseCenter;
1171};
1172
1173class DrawPathOp : public DrawBoundedOp {
1174public:
Chris Craikd218a922014-01-02 17:13:34 -08001175 DrawPathOp(const SkPath* path, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001176 : DrawBoundedOp(paint), mPath(path) {
1177 float left, top, offset;
1178 uint32_t width, height;
Romain Guyca89e2a2013-03-08 17:44:20 -08001179 PathCache::computePathBounds(path, paint, left, top, offset, width, height);
Chris Craik2af46352012-11-26 18:30:17 -08001180 left -= offset;
1181 top -= offset;
1182 mLocalBounds.set(left, top, left + width, top + height);
1183 }
1184
Chris Craikd41c4d82015-01-05 15:51:13 -08001185 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
Tom Hudson107843d2014-09-08 11:26:26 -04001186 renderer.drawPath(mPath, mPaint);
Chris Craik2af46352012-11-26 18:30:17 -08001187 }
1188
Chris Craikc1c5f082013-09-11 16:23:37 -07001189 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
Chris Craikd41c4d82015-01-05 15:51:13 -08001190 const DeferredDisplayState& state) override {
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -04001191 renderer.getCaches().pathCache.precache(mPath, mPaint);
Chris Craik527a3aa2013-03-04 10:19:31 -08001192
Chris Craik28ce94a2013-05-31 11:38:03 -07001193 deferInfo.batchId = DeferredDisplayList::kOpBatch_AlphaMaskTexture;
Romain Guyca89e2a2013-03-08 17:44:20 -08001194 }
1195
Chris Craikd41c4d82015-01-05 15:51:13 -08001196 virtual void output(int level, uint32_t logFlags) const override {
John Reckce444ca2014-06-02 15:12:36 -07001197 OP_LOG("Draw Path %p in " RECT_STRING, mPath, RECT_ARGS(mLocalBounds));
Chris Craik2af46352012-11-26 18:30:17 -08001198 }
1199
Chris Craikd41c4d82015-01-05 15:51:13 -08001200 virtual const char* name() override { return "DrawPath"; }
Chris Craik2af46352012-11-26 18:30:17 -08001201
1202private:
Chris Craikd218a922014-01-02 17:13:34 -08001203 const SkPath* mPath;
Chris Craik2af46352012-11-26 18:30:17 -08001204};
1205
Chris Craikc3566d02013-02-04 16:16:33 -08001206class DrawLinesOp : public DrawBoundedOp {
Chris Craik2af46352012-11-26 18:30:17 -08001207public:
Chris Craikd218a922014-01-02 17:13:34 -08001208 DrawLinesOp(const float* points, int count, const SkPaint* paint)
Chris Craik5d116762013-02-19 17:49:31 -08001209 : DrawBoundedOp(points, count, paint),
1210 mPoints(points), mCount(count) {
Chris Craikc3566d02013-02-04 16:16:33 -08001211 mLocalBounds.outset(strokeWidthOutset());
Chris Craik2af46352012-11-26 18:30:17 -08001212 }
1213
Chris Craikd41c4d82015-01-05 15:51:13 -08001214 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
Tom Hudson107843d2014-09-08 11:26:26 -04001215 renderer.drawLines(mPoints, mCount, mPaint);
Chris Craik2af46352012-11-26 18:30:17 -08001216 }
1217
Chris Craikd41c4d82015-01-05 15:51:13 -08001218 virtual void output(int level, uint32_t logFlags) const override {
Chris Craik2af46352012-11-26 18:30:17 -08001219 OP_LOG("Draw Lines count %d", mCount);
1220 }
1221
Chris Craikd41c4d82015-01-05 15:51:13 -08001222 virtual const char* name() override { return "DrawLines"; }
Chris Craik2af46352012-11-26 18:30:17 -08001223
Andreas Gampe64bb4132014-11-22 00:35:09 +00001224 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
Chris Craikd41c4d82015-01-05 15:51:13 -08001225 const DeferredDisplayState& state) override {
Chris Craik28ce94a2013-05-31 11:38:03 -07001226 deferInfo.batchId = mPaint->isAntiAlias() ?
Chris Craikc3566d02013-02-04 16:16:33 -08001227 DeferredDisplayList::kOpBatch_AlphaVertices :
1228 DeferredDisplayList::kOpBatch_Vertices;
1229 }
1230
Chris Craik2af46352012-11-26 18:30:17 -08001231protected:
Chris Craikd218a922014-01-02 17:13:34 -08001232 const float* mPoints;
Chris Craik2af46352012-11-26 18:30:17 -08001233 int mCount;
1234};
1235
1236class DrawPointsOp : public DrawLinesOp {
1237public:
Chris Craikd218a922014-01-02 17:13:34 -08001238 DrawPointsOp(const float* points, int count, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001239 : DrawLinesOp(points, count, paint) {}
1240
Chris Craikd41c4d82015-01-05 15:51:13 -08001241 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
Tom Hudson107843d2014-09-08 11:26:26 -04001242 renderer.drawPoints(mPoints, mCount, mPaint);
Chris Craik2af46352012-11-26 18:30:17 -08001243 }
1244
Chris Craikd41c4d82015-01-05 15:51:13 -08001245 virtual void output(int level, uint32_t logFlags) const override {
Chris Craik2af46352012-11-26 18:30:17 -08001246 OP_LOG("Draw Points count %d", mCount);
1247 }
1248
Chris Craikd41c4d82015-01-05 15:51:13 -08001249 virtual const char* name() override { return "DrawPoints"; }
Chris Craik2af46352012-11-26 18:30:17 -08001250};
1251
1252class DrawSomeTextOp : public DrawOp {
1253public:
Chris Craikd218a922014-01-02 17:13:34 -08001254 DrawSomeTextOp(const char* text, int bytesCount, int count, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001255 : DrawOp(paint), mText(text), mBytesCount(bytesCount), mCount(count) {};
1256
Chris Craikd41c4d82015-01-05 15:51:13 -08001257 virtual void output(int level, uint32_t logFlags) const override {
Chris Craik2af46352012-11-26 18:30:17 -08001258 OP_LOG("Draw some text, %d bytes", mBytesCount);
1259 }
Chris Craikc3566d02013-02-04 16:16:33 -08001260
Chris Craikd41c4d82015-01-05 15:51:13 -08001261 virtual bool hasTextShadow() const override {
Derek Sollenbergerc29a0a42014-03-31 13:52:39 -04001262 return OpenGLRenderer::hasTextShadow(mPaint);
1263 }
1264
Chris Craikc1c5f082013-09-11 16:23:37 -07001265 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
Chris Craikd41c4d82015-01-05 15:51:13 -08001266 const DeferredDisplayState& state) override {
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -04001267 FontRenderer& fontRenderer = renderer.getCaches().fontRenderer->getFontRenderer(mPaint);
1268 fontRenderer.precache(mPaint, mText, mCount, SkMatrix::I());
Romain Guy0f6675332013-03-01 14:31:04 -08001269
Chris Craik98d608d2014-07-17 12:25:11 -07001270 deferInfo.batchId = mPaint->getColor() == SK_ColorBLACK ?
Chris Craikc3566d02013-02-04 16:16:33 -08001271 DeferredDisplayList::kOpBatch_Text :
1272 DeferredDisplayList::kOpBatch_ColorText;
1273 }
Chris Craik527a3aa2013-03-04 10:19:31 -08001274
Chris Craik2af46352012-11-26 18:30:17 -08001275protected:
1276 const char* mText;
1277 int mBytesCount;
1278 int mCount;
1279};
1280
1281class DrawTextOnPathOp : public DrawSomeTextOp {
1282public:
1283 DrawTextOnPathOp(const char* text, int bytesCount, int count,
Chris Craikd218a922014-01-02 17:13:34 -08001284 const SkPath* path, float hOffset, float vOffset, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001285 : DrawSomeTextOp(text, bytesCount, count, paint),
1286 mPath(path), mHOffset(hOffset), mVOffset(vOffset) {
1287 /* TODO: inherit from DrawBounded and init mLocalBounds */
1288 }
1289
Chris Craikd41c4d82015-01-05 15:51:13 -08001290 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
Tom Hudson107843d2014-09-08 11:26:26 -04001291 renderer.drawTextOnPath(mText, mBytesCount, mCount, mPath,
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -04001292 mHOffset, mVOffset, mPaint);
Chris Craik2af46352012-11-26 18:30:17 -08001293 }
1294
Chris Craikd41c4d82015-01-05 15:51:13 -08001295 virtual const char* name() override { return "DrawTextOnPath"; }
Chris Craik2af46352012-11-26 18:30:17 -08001296
1297private:
Chris Craikd218a922014-01-02 17:13:34 -08001298 const SkPath* mPath;
Chris Craik2af46352012-11-26 18:30:17 -08001299 float mHOffset;
1300 float mVOffset;
1301};
1302
1303class DrawPosTextOp : public DrawSomeTextOp {
1304public:
1305 DrawPosTextOp(const char* text, int bytesCount, int count,
Chris Craikd218a922014-01-02 17:13:34 -08001306 const float* positions, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001307 : DrawSomeTextOp(text, bytesCount, count, paint), mPositions(positions) {
1308 /* TODO: inherit from DrawBounded and init mLocalBounds */
1309 }
1310
Chris Craikd41c4d82015-01-05 15:51:13 -08001311 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
Tom Hudson107843d2014-09-08 11:26:26 -04001312 renderer.drawPosText(mText, mBytesCount, mCount, mPositions, mPaint);
Chris Craik2af46352012-11-26 18:30:17 -08001313 }
1314
Chris Craikd41c4d82015-01-05 15:51:13 -08001315 virtual const char* name() override { return "DrawPosText"; }
Chris Craik2af46352012-11-26 18:30:17 -08001316
1317private:
1318 const float* mPositions;
1319};
1320
Chris Craik947eabf2014-08-19 10:21:12 -07001321class DrawTextOp : public DrawStrokableOp {
Chris Craik2af46352012-11-26 18:30:17 -08001322public:
1323 DrawTextOp(const char* text, int bytesCount, int count, float x, float y,
Chris Craikd218a922014-01-02 17:13:34 -08001324 const float* positions, const SkPaint* paint, float totalAdvance, const Rect& bounds)
Chris Craik947eabf2014-08-19 10:21:12 -07001325 : DrawStrokableOp(bounds, paint), mText(text), mBytesCount(bytesCount), mCount(count),
Chris Craik41541822013-05-03 16:35:54 -07001326 mX(x), mY(y), mPositions(positions), mTotalAdvance(totalAdvance) {
Chris Craik59744b72014-07-01 17:56:52 -07001327 mPrecacheTransform = SkMatrix::InvalidMatrix();
Chris Craik2af46352012-11-26 18:30:17 -08001328 }
1329
Chris Craikc1c5f082013-09-11 16:23:37 -07001330 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
Chris Craikd41c4d82015-01-05 15:51:13 -08001331 const DeferredDisplayState& state) override {
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -04001332 FontRenderer& fontRenderer = renderer.getCaches().fontRenderer->getFontRenderer(mPaint);
Chris Craik59744b72014-07-01 17:56:52 -07001333 SkMatrix transform;
1334 renderer.findBestFontTransform(state.mMatrix, &transform);
Romain Guybd3055f2013-03-13 16:14:47 -07001335 if (mPrecacheTransform != transform) {
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -04001336 fontRenderer.precache(mPaint, mText, mCount, transform);
Romain Guybd3055f2013-03-13 16:14:47 -07001337 mPrecacheTransform = transform;
1338 }
Chris Craik98d608d2014-07-17 12:25:11 -07001339 deferInfo.batchId = mPaint->getColor() == SK_ColorBLACK ?
Chris Craik527a3aa2013-03-04 10:19:31 -08001340 DeferredDisplayList::kOpBatch_Text :
1341 DeferredDisplayList::kOpBatch_ColorText;
1342
Kévin PETIT73fc5582014-02-13 11:03:40 +00001343 deferInfo.mergeId = reinterpret_cast<mergeid_t>(mPaint->getColor());
Chris Craik527a3aa2013-03-04 10:19:31 -08001344
1345 // don't merge decorated text - the decorations won't draw in order
Chris Craik98d608d2014-07-17 12:25:11 -07001346 bool hasDecorations = mPaint->getFlags()
1347 & (SkPaint::kUnderlineText_Flag | SkPaint::kStrikeThruText_Flag);
1348
1349 deferInfo.mergeable = state.mMatrix.isPureTranslate()
1350 && !hasDecorations
1351 && OpenGLRenderer::getXfermodeDirect(mPaint) == SkXfermode::kSrcOver_Mode;
Romain Guy0f6675332013-03-01 14:31:04 -08001352 }
1353
Chris Craikd41c4d82015-01-05 15:51:13 -08001354 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
Romain Guy9b5a1a22013-08-09 14:06:29 -07001355 Rect bounds;
John Reck3b202512014-06-23 13:13:08 -07001356 getLocalBounds(bounds);
Tom Hudson107843d2014-09-08 11:26:26 -04001357 renderer.drawText(mText, mBytesCount, mCount, mX, mY,
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -04001358 mPositions, mPaint, mTotalAdvance, bounds);
Chris Craik2af46352012-11-26 18:30:17 -08001359 }
1360
Andreas Gampe64bb4132014-11-22 00:35:09 +00001361 virtual void multiDraw(OpenGLRenderer& renderer, Rect& dirty,
Chris Craikd41c4d82015-01-05 15:51:13 -08001362 const Vector<OpStatePair>& ops, const Rect& bounds) override {
Chris Craik527a3aa2013-03-04 10:19:31 -08001363 for (unsigned int i = 0; i < ops.size(); i++) {
Chris Craikc1c5f082013-09-11 16:23:37 -07001364 const DeferredDisplayState& state = *(ops[i].state);
Chris Craik527a3aa2013-03-04 10:19:31 -08001365 DrawOpMode drawOpMode = (i == ops.size() - 1) ? kDrawOpMode_Flush : kDrawOpMode_Defer;
Chris Craikc1c5f082013-09-11 16:23:37 -07001366 renderer.restoreDisplayState(state, true); // restore all but the clip
Chris Craik527a3aa2013-03-04 10:19:31 -08001367
Chris Craikc1c5f082013-09-11 16:23:37 -07001368 DrawTextOp& op = *((DrawTextOp*)ops[i].op);
Romain Guy9b5a1a22013-08-09 14:06:29 -07001369 // quickReject() will not occure in drawText() so we can use mLocalBounds
1370 // directly, we do not need to account for shadow by calling getLocalBounds()
Tom Hudson107843d2014-09-08 11:26:26 -04001371 renderer.drawText(op.mText, op.mBytesCount, op.mCount, op.mX, op.mY,
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -04001372 op.mPositions, op.mPaint, op.mTotalAdvance, op.mLocalBounds,
Chris Craik41541822013-05-03 16:35:54 -07001373 drawOpMode);
Chris Craik527a3aa2013-03-04 10:19:31 -08001374 }
Chris Craik527a3aa2013-03-04 10:19:31 -08001375 }
1376
Chris Craikd41c4d82015-01-05 15:51:13 -08001377 virtual void output(int level, uint32_t logFlags) const override {
Chris Craik2af46352012-11-26 18:30:17 -08001378 OP_LOG("Draw Text of count %d, bytes %d", mCount, mBytesCount);
1379 }
1380
Chris Craikd41c4d82015-01-05 15:51:13 -08001381 virtual const char* name() override { return "DrawText"; }
Chris Craik2af46352012-11-26 18:30:17 -08001382
1383private:
1384 const char* mText;
1385 int mBytesCount;
1386 int mCount;
1387 float mX;
1388 float mY;
1389 const float* mPositions;
Chris Craik41541822013-05-03 16:35:54 -07001390 float mTotalAdvance;
Chris Craik59744b72014-07-01 17:56:52 -07001391 SkMatrix mPrecacheTransform;
Chris Craik2af46352012-11-26 18:30:17 -08001392};
1393
1394///////////////////////////////////////////////////////////////////////////////
1395// SPECIAL DRAW OPERATIONS
1396///////////////////////////////////////////////////////////////////////////////
1397
1398class DrawFunctorOp : public DrawOp {
1399public:
1400 DrawFunctorOp(Functor* functor)
Chris Craikd41c4d82015-01-05 15:51:13 -08001401 : DrawOp(nullptr), mFunctor(functor) {}
Chris Craik2af46352012-11-26 18:30:17 -08001402
Chris Craikd41c4d82015-01-05 15:51:13 -08001403 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
Chris Craik2af46352012-11-26 18:30:17 -08001404 renderer.startMark("GL functor");
Tom Hudson107843d2014-09-08 11:26:26 -04001405 renderer.callDrawGLFunction(mFunctor, dirty);
Chris Craik2af46352012-11-26 18:30:17 -08001406 renderer.endMark();
Chris Craik2af46352012-11-26 18:30:17 -08001407 }
1408
Chris Craikd41c4d82015-01-05 15:51:13 -08001409 virtual void output(int level, uint32_t logFlags) const override {
Chris Craik2af46352012-11-26 18:30:17 -08001410 OP_LOG("Draw Functor %p", mFunctor);
1411 }
1412
Chris Craikd41c4d82015-01-05 15:51:13 -08001413 virtual const char* name() override { return "DrawFunctor"; }
Chris Craik2af46352012-11-26 18:30:17 -08001414
1415private:
1416 Functor* mFunctor;
1417};
1418
Chris Craika7090e02014-06-20 16:01:00 -07001419class DrawRenderNodeOp : public DrawBoundedOp {
1420 friend class RenderNode; // grant RenderNode access to info of child
Chris Craik8afd0f22014-08-21 17:41:57 -07001421 friend class DisplayListData; // grant DisplayListData access to info of child
Chris Craik2af46352012-11-26 18:30:17 -08001422public:
Chris Craika7090e02014-06-20 16:01:00 -07001423 DrawRenderNodeOp(RenderNode* renderNode, int flags, const mat4& transformFromParent)
Chris Craikd41c4d82015-01-05 15:51:13 -08001424 : DrawBoundedOp(0, 0, renderNode->getWidth(), renderNode->getHeight(), nullptr),
Chris Craika7090e02014-06-20 16:01:00 -07001425 mRenderNode(renderNode), mFlags(flags), mTransformFromParent(transformFromParent) {}
Chris Craikc3566d02013-02-04 16:16:33 -08001426
Andreas Gampe64bb4132014-11-22 00:35:09 +00001427 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
Chris Craikd41c4d82015-01-05 15:51:13 -08001428 bool useQuickReject) override {
Chris Craik8afd0f22014-08-21 17:41:57 -07001429 if (mRenderNode->isRenderable() && !mSkipInOrderDraw) {
Chris Craika7090e02014-06-20 16:01:00 -07001430 mRenderNode->defer(deferStruct, level + 1);
Chris Craikc3566d02013-02-04 16:16:33 -08001431 }
Chris Craikc3566d02013-02-04 16:16:33 -08001432 }
Chris Craik8afd0f22014-08-21 17:41:57 -07001433
Andreas Gampe64bb4132014-11-22 00:35:09 +00001434 virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level,
Chris Craikd41c4d82015-01-05 15:51:13 -08001435 bool useQuickReject) override {
Chris Craik8afd0f22014-08-21 17:41:57 -07001436 if (mRenderNode->isRenderable() && !mSkipInOrderDraw) {
Chris Craika7090e02014-06-20 16:01:00 -07001437 mRenderNode->replay(replayStruct, level + 1);
Chris Craikff785832013-03-08 13:12:16 -08001438 }
1439 }
Chris Craik2af46352012-11-26 18:30:17 -08001440
Chris Craikd41c4d82015-01-05 15:51:13 -08001441 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
Chris Craik80d49022014-06-20 15:03:43 -07001442 LOG_ALWAYS_FATAL("should not be called, because replay() is overridden");
Chris Craika08f95c2013-03-15 17:24:33 -07001443 }
Chris Craikff785832013-03-08 13:12:16 -08001444
Chris Craikd41c4d82015-01-05 15:51:13 -08001445 virtual void output(int level, uint32_t logFlags) const override {
Chris Craik8afd0f22014-08-21 17:41:57 -07001446 OP_LOG("Draw RenderNode %p %s, flags %#x", mRenderNode, mRenderNode->getName(), mFlags);
Chris Craika7090e02014-06-20 16:01:00 -07001447 if (mRenderNode && (logFlags & kOpLogFlag_Recurse)) {
1448 mRenderNode->output(level + 1);
Chris Craik2af46352012-11-26 18:30:17 -08001449 }
1450 }
1451
Chris Craikd41c4d82015-01-05 15:51:13 -08001452 virtual const char* name() override { return "DrawRenderNode"; }
Chris Craik2af46352012-11-26 18:30:17 -08001453
Chris Craika7090e02014-06-20 16:01:00 -07001454 RenderNode* renderNode() { return mRenderNode; }
John Reck087bc0c2014-04-04 16:20:08 -07001455
Chris Craik2af46352012-11-26 18:30:17 -08001456private:
Chris Craika7090e02014-06-20 16:01:00 -07001457 RenderNode* mRenderNode;
Chris Craikf57776b2013-10-25 18:30:17 -07001458 const int mFlags;
1459
1460 ///////////////////////////
Chris Craika7090e02014-06-20 16:01:00 -07001461 // Properties below are used by RenderNode::computeOrderingImpl() and issueOperations()
Chris Craikf57776b2013-10-25 18:30:17 -07001462 ///////////////////////////
1463 /**
1464 * Records transform vs parent, used for computing total transform without rerunning DL contents
1465 */
1466 const mat4 mTransformFromParent;
1467
1468 /**
Chris Craika7090e02014-06-20 16:01:00 -07001469 * Holds the transformation between the projection surface ViewGroup and this RenderNode
Chris Craikb79a3e32014-03-11 12:20:17 -07001470 * drawing instance. Represents any translations / transformations done within the drawing of
1471 * the compositing ancestor ViewGroup's draw, before the draw of the View represented by this
1472 * DisplayList draw instance.
Chris Craikf57776b2013-10-25 18:30:17 -07001473 *
Chris Craika7090e02014-06-20 16:01:00 -07001474 * Note: doesn't include transformation within the RenderNode, or its properties.
Chris Craikf57776b2013-10-25 18:30:17 -07001475 */
Chris Craikf533e942014-01-14 22:35:37 -08001476 mat4 mTransformFromCompositingAncestor;
Chris Craikf57776b2013-10-25 18:30:17 -07001477 bool mSkipInOrderDraw;
1478};
1479
1480/**
Chris Craik024433f2014-03-26 13:19:14 -07001481 * Not a canvas operation, used only by 3d / z ordering logic in RenderNode::iterate()
Chris Craikf57776b2013-10-25 18:30:17 -07001482 */
1483class DrawShadowOp : public DrawOp {
1484public:
Chris Craik024433f2014-03-26 13:19:14 -07001485 DrawShadowOp(const mat4& transformXY, const mat4& transformZ,
Chris Craik74669862014-08-07 17:27:30 -07001486 float casterAlpha, const SkPath* casterOutline)
Chris Craikd41c4d82015-01-05 15:51:13 -08001487 : DrawOp(nullptr)
Chris Craik74669862014-08-07 17:27:30 -07001488 , mTransformXY(transformXY)
1489 , mTransformZ(transformZ)
1490 , mCasterAlpha(casterAlpha)
1491 , mCasterOutline(casterOutline) {
Chris Craik61317322014-05-21 13:03:52 -07001492 }
Chris Craikf57776b2013-10-25 18:30:17 -07001493
Andreas Gampe64bb4132014-11-22 00:35:09 +00001494 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
Chris Craikd41c4d82015-01-05 15:51:13 -08001495 const DeferredDisplayState& state) override {
Chris Craik05f3d6e2014-06-02 16:27:04 -07001496 renderer.getCaches().tessellationCache.precacheShadows(&state.mMatrix,
Chris Craik74669862014-08-07 17:27:30 -07001497 renderer.getLocalClipBounds(), isCasterOpaque(), mCasterOutline,
Chris Craik05f3d6e2014-06-02 16:27:04 -07001498 &mTransformXY, &mTransformZ, renderer.getLightCenter(), renderer.getLightRadius());
1499 }
1500
Chris Craikd41c4d82015-01-05 15:51:13 -08001501 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
Chris Craik05f3d6e2014-06-02 16:27:04 -07001502 TessellationCache::vertexBuffer_pair_t buffers;
Chris Craikc3e75f92014-08-27 15:34:52 -07001503 Matrix4 drawTransform(*(renderer.currentTransform()));
Chris Craik05f3d6e2014-06-02 16:27:04 -07001504 renderer.getCaches().tessellationCache.getShadowBuffers(&drawTransform,
Chris Craik74669862014-08-07 17:27:30 -07001505 renderer.getLocalClipBounds(), isCasterOpaque(), mCasterOutline,
Chris Craik05f3d6e2014-06-02 16:27:04 -07001506 &mTransformXY, &mTransformZ, renderer.getLightCenter(), renderer.getLightRadius(),
1507 buffers);
1508
Tom Hudson107843d2014-09-08 11:26:26 -04001509 renderer.drawShadow(mCasterAlpha, buffers.first, buffers.second);
Chris Craikf57776b2013-10-25 18:30:17 -07001510 }
1511
Chris Craikd41c4d82015-01-05 15:51:13 -08001512 virtual void output(int level, uint32_t logFlags) const override {
Chris Craik61317322014-05-21 13:03:52 -07001513 OP_LOGS("DrawShadow");
Chris Craikf57776b2013-10-25 18:30:17 -07001514 }
1515
Chris Craikd41c4d82015-01-05 15:51:13 -08001516 virtual const char* name() override { return "DrawShadow"; }
Chris Craikf57776b2013-10-25 18:30:17 -07001517
1518private:
Chris Craikaf4d04c2014-07-29 12:50:14 -07001519 bool isCasterOpaque() { return mCasterAlpha >= 1.0f; }
Chris Craik05f3d6e2014-06-02 16:27:04 -07001520
Chris Craikb79a3e32014-03-11 12:20:17 -07001521 const mat4 mTransformXY;
1522 const mat4 mTransformZ;
Chris Craik024433f2014-03-26 13:19:14 -07001523 const float mCasterAlpha;
Chris Craik74669862014-08-07 17:27:30 -07001524 const SkPath* mCasterOutline;
Chris Craik2af46352012-11-26 18:30:17 -08001525};
1526
1527class DrawLayerOp : public DrawOp {
1528public:
Chris Craika08f95c2013-03-15 17:24:33 -07001529 DrawLayerOp(Layer* layer, float x, float y)
Chris Craikd41c4d82015-01-05 15:51:13 -08001530 : DrawOp(nullptr), mLayer(layer), mX(x), mY(y) {}
Chris Craik2af46352012-11-26 18:30:17 -08001531
Chris Craikd41c4d82015-01-05 15:51:13 -08001532 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) override {
Tom Hudson107843d2014-09-08 11:26:26 -04001533 renderer.drawLayer(mLayer, mX, mY);
Chris Craik2af46352012-11-26 18:30:17 -08001534 }
1535
Chris Craikd41c4d82015-01-05 15:51:13 -08001536 virtual void output(int level, uint32_t logFlags) const override {
Chris Craik2af46352012-11-26 18:30:17 -08001537 OP_LOG("Draw Layer %p at %f %f", mLayer, mX, mY);
1538 }
1539
Chris Craikd41c4d82015-01-05 15:51:13 -08001540 virtual const char* name() override { return "DrawLayer"; }
Chris Craik2af46352012-11-26 18:30:17 -08001541
1542private:
1543 Layer* mLayer;
1544 float mX;
1545 float mY;
1546};
1547
1548}; // namespace uirenderer
1549}; // namespace android
1550
1551#endif // ANDROID_HWUI_DISPLAY_OPERATION_H