blob: 762716379b73549b00dff10857ed9bcff69020ae [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
Romain Guy7031ff62013-02-22 11:48:16 -080020#ifndef LOG_TAG
21 #define LOG_TAG "OpenGLRenderer"
22#endif
23
Chris Craik98d608d2014-07-17 12:25:11 -070024#include <SkColor.h>
Chris Craik8c271ca2014-03-25 10:33:01 -070025#include <SkPath.h>
26#include <SkPathOps.h>
Chris Craik2af46352012-11-26 18:30:17 -080027#include <SkXfermode.h>
28
Chris Craik0776a602013-02-14 15:36:01 -080029#include <private/hwui/DrawGlInfo.h>
30
Chris Craik2af46352012-11-26 18:30:17 -080031#include "OpenGLRenderer.h"
Romain Guy3b748a42013-04-17 18:54:38 -070032#include "AssetAtlas.h"
Chris Craikc3566d02013-02-04 16:16:33 -080033#include "DeferredDisplayList.h"
Chris Craik2af46352012-11-26 18:30:17 -080034#include "DisplayListRenderer.h"
Tom Hudson2dc236b2014-10-15 15:46:42 -040035#include "GammaFontRenderer.h"
36#include "Patch.h"
37#include "RenderNode.h"
Romain Guy3b748a42013-04-17 18:54:38 -070038#include "UvMapper.h"
Chris Craik2af46352012-11-26 18:30:17 -080039#include "utils/LinearAllocator.h"
40
41#define CRASH() do { \
Romain Guy5216c3b2013-06-14 16:31:37 -070042 *(int *)(uintptr_t) 0xbbadbeef = 0; \
Chris Craik2af46352012-11-26 18:30:17 -080043 ((void(*)())0)(); /* More reliable, but doesn't say BBADBEEF */ \
44} while(false)
45
Chris Craik2af46352012-11-26 18:30:17 -080046// Use OP_LOG for logging with arglist, OP_LOGS if just printing char*
Chris Craik28ce94a2013-05-31 11:38:03 -070047#define OP_LOGS(s) OP_LOG("%s", (s))
Chris Craik3dc553b2013-02-04 12:45:13 -080048#define OP_LOG(s, ...) ALOGD( "%*s" s, level * 2, "", __VA_ARGS__ )
Chris Craik2af46352012-11-26 18:30:17 -080049
Chris Craik2af46352012-11-26 18:30:17 -080050namespace android {
51namespace uirenderer {
52
53/**
54 * Structure for storing canvas operations when they are recorded into a DisplayList, so that they
55 * may be replayed to an OpenGLRenderer.
56 *
57 * To avoid individual memory allocations, DisplayListOps may only be allocated into a
58 * LinearAllocator's managed memory buffers. Each pointer held by a DisplayListOp is either a
59 * pointer into memory also allocated in the LinearAllocator (mostly for text and float buffers) or
60 * references a externally refcounted object (Sk... and Skia... objects). ~DisplayListOp() is
61 * never called as LinearAllocators are simply discarded, so no memory management should be done in
62 * this class.
63 */
64class DisplayListOp {
65public:
66 // These objects should always be allocated with a LinearAllocator, and never destroyed/deleted.
67 // standard new() intentionally not implemented, and delete/deconstructor should never be used.
68 virtual ~DisplayListOp() { CRASH(); }
Andreas Gampe64bb4132014-11-22 00:35:09 +000069 static void operator delete(void* ptr) { CRASH(); }
Chris Craik2af46352012-11-26 18:30:17 -080070 /** static void* operator new(size_t size); PURPOSELY OMITTED **/
71 static void* operator new(size_t size, LinearAllocator& allocator) {
72 return allocator.alloc(size);
73 }
74
75 enum OpLogFlag {
76 kOpLogFlag_Recurse = 0x1,
77 kOpLogFlag_JSON = 0x2 // TODO: add?
78 };
79
Chet Haasedd671592013-04-19 14:54:34 -070080 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
81 bool useQuickReject) = 0;
Chris Craikc3566d02013-02-04 16:16:33 -080082
Chet Haasedd671592013-04-19 14:54:34 -070083 virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level,
84 bool useQuickReject) = 0;
Chris Craikff785832013-03-08 13:12:16 -080085
Chris Craikc5493fb2013-06-19 16:58:58 -070086 virtual void output(int level, uint32_t logFlags = 0) const = 0;
Chris Craik2af46352012-11-26 18:30:17 -080087
88 // NOTE: it would be nice to declare constants and overriding the implementation in each op to
89 // point at the constants, but that seems to require a .cpp file
90 virtual const char* name() = 0;
91};
92
93class StateOp : public DisplayListOp {
94public:
95 StateOp() {};
96
97 virtual ~StateOp() {}
98
Andreas Gampe64bb4132014-11-22 00:35:09 +000099 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
100 bool useQuickReject) {
Chris Craikff785832013-03-08 13:12:16 -0800101 // default behavior only affects immediate, deferrable state, issue directly to renderer
102 applyState(deferStruct.mRenderer, saveCount);
103 }
104
Chris Craikc3566d02013-02-04 16:16:33 -0800105 /**
106 * State operations are applied directly to the renderer, but can cause the deferred drawing op
107 * list to flush
108 */
Andreas Gampe64bb4132014-11-22 00:35:09 +0000109 virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level,
110 bool useQuickReject) {
Chris Craikff785832013-03-08 13:12:16 -0800111 applyState(replayStruct.mRenderer, saveCount);
Chris Craikc3566d02013-02-04 16:16:33 -0800112 }
113
Chris Craik7273daa2013-03-28 11:25:24 -0700114 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const = 0;
Chris Craik2af46352012-11-26 18:30:17 -0800115};
116
117class DrawOp : public DisplayListOp {
Chris Craik527a3aa2013-03-04 10:19:31 -0800118friend class MergingDrawBatch;
Chris Craik2af46352012-11-26 18:30:17 -0800119public:
Chris Craikd218a922014-01-02 17:13:34 -0800120 DrawOp(const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -0800121 : mPaint(paint), mQuickRejected(false) {}
122
Andreas Gampe64bb4132014-11-22 00:35:09 +0000123 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
Chet Haasedd671592013-04-19 14:54:34 -0700124 bool useQuickReject) {
125 if (mQuickRejected && CC_LIKELY(useQuickReject)) {
Chris Craikff785832013-03-08 13:12:16 -0800126 return;
Chris Craikc3566d02013-02-04 16:16:33 -0800127 }
128
Chris Craikff785832013-03-08 13:12:16 -0800129 deferStruct.mDeferredList.addDrawOp(deferStruct.mRenderer, this);
Chris Craikc3566d02013-02-04 16:16:33 -0800130 }
131
Andreas Gampe64bb4132014-11-22 00:35:09 +0000132 virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level,
Chet Haasedd671592013-04-19 14:54:34 -0700133 bool useQuickReject) {
134 if (mQuickRejected && CC_LIKELY(useQuickReject)) {
Chris Craikff785832013-03-08 13:12:16 -0800135 return;
136 }
137
Tom Hudson107843d2014-09-08 11:26:26 -0400138 applyDraw(replayStruct.mRenderer, replayStruct.mDirty);
Chris Craikff785832013-03-08 13:12:16 -0800139 }
140
Tom Hudson107843d2014-09-08 11:26:26 -0400141 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) = 0;
Chris Craik2af46352012-11-26 18:30:17 -0800142
Chris Craik527a3aa2013-03-04 10:19:31 -0800143 /**
144 * Draw multiple instances of an operation, must be overidden for operations that merge
145 *
146 * Currently guarantees certain similarities between ops (see MergingDrawBatch::canMergeWith),
147 * and pure translation transformations. Other guarantees of similarity should be enforced by
148 * reducing which operations are tagged as mergeable.
149 */
Tom Hudson107843d2014-09-08 11:26:26 -0400150 virtual void multiDraw(OpenGLRenderer& renderer, Rect& dirty,
Andreas Gampe64bb4132014-11-22 00:35:09 +0000151 const Vector<OpStatePair>& ops, const Rect& bounds) {
Chris Craik527a3aa2013-03-04 10:19:31 -0800152 for (unsigned int i = 0; i < ops.size(); i++) {
Chris Craikc1c5f082013-09-11 16:23:37 -0700153 renderer.restoreDisplayState(*(ops[i].state), true);
Tom Hudson107843d2014-09-08 11:26:26 -0400154 ops[i].op->applyDraw(renderer, dirty);
Chris Craik527a3aa2013-03-04 10:19:31 -0800155 }
Chris Craik527a3aa2013-03-04 10:19:31 -0800156 }
157
Chris Craik28ce94a2013-05-31 11:38:03 -0700158 /**
Chris Craik527a3aa2013-03-04 10:19:31 -0800159 * When this method is invoked the state field is initialized to have the
160 * final rendering state. We can thus use it to process data as it will be
161 * used at draw time.
162 *
163 * Additionally, this method allows subclasses to provide defer-time preferences for batching
164 * and merging.
165 *
Chris Craik28ce94a2013-05-31 11:38:03 -0700166 * if a subclass can set deferInfo.mergeable to true, it should implement multiDraw()
Chris Craik527a3aa2013-03-04 10:19:31 -0800167 */
Andreas Gampe64bb4132014-11-22 00:35:09 +0000168 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
169 const DeferredDisplayState& state) {}
Romain Guy0f6675332013-03-01 14:31:04 -0800170
Chris Craik5e49b302013-07-30 19:05:20 -0700171 /**
172 * Query the conservative, local bounds (unmapped) bounds of the op.
173 *
174 * returns true if bounds exist
175 */
Andreas Gampe64bb4132014-11-22 00:35:09 +0000176 virtual bool getLocalBounds(Rect& localBounds) {
Chris Craikc1c5f082013-09-11 16:23:37 -0700177 return false;
178 }
Chris Craik2af46352012-11-26 18:30:17 -0800179
180 // TODO: better refine localbounds usage
181 void setQuickRejected(bool quickRejected) { mQuickRejected = quickRejected; }
182 bool getQuickRejected() { return mQuickRejected; }
183
Chris Craikc1c5f082013-09-11 16:23:37 -0700184 inline int getPaintAlpha() const {
Chris Craik527a3aa2013-03-04 10:19:31 -0800185 return OpenGLRenderer::getAlphaDirect(mPaint);
Chris Craikc3566d02013-02-04 16:16:33 -0800186 }
187
Derek Sollenbergerc29a0a42014-03-31 13:52:39 -0400188 virtual bool hasTextShadow() const {
189 return false;
190 }
191
Chris Craik527a3aa2013-03-04 10:19:31 -0800192 inline float strokeWidthOutset() {
Chris Craikf0a59072013-11-19 18:00:46 -0800193 // since anything AA stroke with less than 1.0 pixel width is drawn with an alpha-reduced
194 // 1.0 stroke, treat 1.0 as minimum.
195
196 // TODO: it would be nice if this could take scale into account, but scale isn't stable
197 // since higher levels of the view hierarchy can change scale out from underneath it.
198 return fmaxf(mPaint->getStrokeWidth(), 1) * 0.5f;
Chris Craike7c69c62013-04-03 09:55:48 -0700199 }
Chris Craikc3566d02013-02-04 16:16:33 -0800200
Chris Craik2af46352012-11-26 18:30:17 -0800201protected:
Chris Craik28ce94a2013-05-31 11:38:03 -0700202 // Helper method for determining op opaqueness. Assumes op fills its bounds in local
203 // coordinates, and that paint's alpha is used
Chris Craikc1c5f082013-09-11 16:23:37 -0700204 inline bool isOpaqueOverBounds(const DeferredDisplayState& state) {
Chris Craik28ce94a2013-05-31 11:38:03 -0700205 // ensure that local bounds cover mapped bounds
206 if (!state.mMatrix.isSimple()) return false;
207
Chris Craik2262abb2014-08-18 19:55:36 -0700208 if (state.mRoundRectClipState) return false;
209
Chris Craik28ce94a2013-05-31 11:38:03 -0700210 // check state/paint for transparency
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400211 if (mPaint) {
Chris Craikc5b5f052014-10-01 16:40:16 -0700212 if (mPaint->getAlpha() != 0xFF) {
213 return false;
214 }
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400215 if (mPaint->getShader() && !mPaint->getShader()->isOpaque()) {
216 return false;
217 }
Chris Craikc5b5f052014-10-01 16:40:16 -0700218 if (Renderer::isBlendedColorFilter(mPaint->getColorFilter())) {
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400219 return false;
220 }
221 }
222
223 if (state.mAlpha != 1.0f) return false;
Chris Craik28ce94a2013-05-31 11:38:03 -0700224
225 SkXfermode::Mode mode = OpenGLRenderer::getXfermodeDirect(mPaint);
226 return (mode == SkXfermode::kSrcOver_Mode ||
227 mode == SkXfermode::kSrc_Mode);
228
229 }
230
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -0400231 const SkPaint* mPaint;
Chris Craik2af46352012-11-26 18:30:17 -0800232 bool mQuickRejected;
233};
234
235class DrawBoundedOp : public DrawOp {
236public:
Chris Craikd218a922014-01-02 17:13:34 -0800237 DrawBoundedOp(float left, float top, float right, float bottom, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -0800238 : DrawOp(paint), mLocalBounds(left, top, right, bottom) {}
239
Chris Craikd218a922014-01-02 17:13:34 -0800240 DrawBoundedOp(const Rect& localBounds, const SkPaint* paint)
Chris Craik41541822013-05-03 16:35:54 -0700241 : DrawOp(paint), mLocalBounds(localBounds) {}
242
Chris Craik5d116762013-02-19 17:49:31 -0800243 // Calculates bounds as smallest rect encompassing all points
244 // NOTE: requires at least 1 vertex, and doesn't account for stroke size (should be handled in
245 // subclass' constructor)
Chris Craikd218a922014-01-02 17:13:34 -0800246 DrawBoundedOp(const float* points, int count, const SkPaint* paint)
Chris Craik5d116762013-02-19 17:49:31 -0800247 : DrawOp(paint), mLocalBounds(points[0], points[1], points[0], points[1]) {
248 for (int i = 2; i < count; i += 2) {
249 mLocalBounds.left = fminf(mLocalBounds.left, points[i]);
250 mLocalBounds.right = fmaxf(mLocalBounds.right, points[i]);
251 mLocalBounds.top = fminf(mLocalBounds.top, points[i + 1]);
252 mLocalBounds.bottom = fmaxf(mLocalBounds.bottom, points[i + 1]);
253 }
254 }
255
256 // default empty constructor for bounds, to be overridden in child constructor body
Chris Craikd218a922014-01-02 17:13:34 -0800257 DrawBoundedOp(const SkPaint* paint): DrawOp(paint) { }
Chris Craik2af46352012-11-26 18:30:17 -0800258
John Reckca1b3b82014-06-27 07:21:36 -0700259 virtual bool getLocalBounds(Rect& localBounds) {
Chris Craik2af46352012-11-26 18:30:17 -0800260 localBounds.set(mLocalBounds);
Derek Sollenbergerc29a0a42014-03-31 13:52:39 -0400261 OpenGLRenderer::TextShadow textShadow;
262 if (OpenGLRenderer::getTextShadow(mPaint, &textShadow)) {
Romain Guy9b5a1a22013-08-09 14:06:29 -0700263 Rect shadow(mLocalBounds);
Derek Sollenbergerc29a0a42014-03-31 13:52:39 -0400264 shadow.translate(textShadow.dx, textShadow.dx);
265 shadow.outset(textShadow.radius);
Romain Guy9b5a1a22013-08-09 14:06:29 -0700266 localBounds.unionWith(shadow);
267 }
Chris Craik2af46352012-11-26 18:30:17 -0800268 return true;
269 }
270
271protected:
272 Rect mLocalBounds; // displayed area in LOCAL coord. doesn't incorporate stroke, so check paint
273};
274
275///////////////////////////////////////////////////////////////////////////////
276// STATE OPERATIONS - these may affect the state of the canvas/renderer, but do
277// not directly draw or alter output
278///////////////////////////////////////////////////////////////////////////////
279
280class SaveOp : public StateOp {
281public:
282 SaveOp(int flags)
283 : mFlags(flags) {}
284
Andreas Gampe64bb4132014-11-22 00:35:09 +0000285 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
286 bool useQuickReject) {
Chris Craikff785832013-03-08 13:12:16 -0800287 int newSaveCount = deferStruct.mRenderer.save(mFlags);
288 deferStruct.mDeferredList.addSave(deferStruct.mRenderer, this, newSaveCount);
289 }
290
Andreas Gampe64bb4132014-11-22 00:35:09 +0000291 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800292 renderer.save(mFlags);
293 }
294
Andreas Gampe64bb4132014-11-22 00:35:09 +0000295 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800296 OP_LOG("Save flags %x", mFlags);
297 }
298
299 virtual const char* name() { return "Save"; }
300
Chris Craikff785832013-03-08 13:12:16 -0800301 int getFlags() const { return mFlags; }
Chris Craik2af46352012-11-26 18:30:17 -0800302private:
303 int mFlags;
304};
305
306class RestoreToCountOp : public StateOp {
307public:
308 RestoreToCountOp(int count)
309 : mCount(count) {}
310
Andreas Gampe64bb4132014-11-22 00:35:09 +0000311 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
312 bool useQuickReject) {
Chris Craik7273daa2013-03-28 11:25:24 -0700313 deferStruct.mDeferredList.addRestoreToCount(deferStruct.mRenderer,
314 this, saveCount + mCount);
Chris Craikff785832013-03-08 13:12:16 -0800315 deferStruct.mRenderer.restoreToCount(saveCount + mCount);
Chris Craik2af46352012-11-26 18:30:17 -0800316 }
317
Chris Craik7273daa2013-03-28 11:25:24 -0700318 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craikff785832013-03-08 13:12:16 -0800319 renderer.restoreToCount(saveCount + mCount);
320 }
321
Andreas Gampe64bb4132014-11-22 00:35:09 +0000322 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800323 OP_LOG("Restore to count %d", mCount);
324 }
325
326 virtual const char* name() { return "RestoreToCount"; }
327
328private:
329 int mCount;
330};
331
332class SaveLayerOp : public StateOp {
333public:
Derek Sollenbergerd44fbe52014-02-05 16:47:00 -0500334 SaveLayerOp(float left, float top, float right, float bottom, int alpha, int flags)
Chris Craik3f0854292014-04-15 16:18:08 -0700335 : mArea(left, top, right, bottom)
336 , mPaint(&mCachedPaint)
337 , mFlags(flags)
338 , mConvexMask(NULL) {
Derek Sollenbergerd44fbe52014-02-05 16:47:00 -0500339 mCachedPaint.setAlpha(alpha);
340 }
341
342 SaveLayerOp(float left, float top, float right, float bottom, const SkPaint* paint, int flags)
Chris Craik3f0854292014-04-15 16:18:08 -0700343 : mArea(left, top, right, bottom)
344 , mPaint(paint)
345 , mFlags(flags)
346 , mConvexMask(NULL)
347 {}
Chris Craikff785832013-03-08 13:12:16 -0800348
Andreas Gampe64bb4132014-11-22 00:35:09 +0000349 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
350 bool useQuickReject) {
Chris Craikff785832013-03-08 13:12:16 -0800351 // NOTE: don't bother with actual saveLayer, instead issuing it at flush time
Chris Craikd90144d2013-03-19 15:03:48 -0700352 int newSaveCount = deferStruct.mRenderer.getSaveCount();
Chris Craikff785832013-03-08 13:12:16 -0800353 deferStruct.mDeferredList.addSaveLayer(deferStruct.mRenderer, this, newSaveCount);
Chris Craikd90144d2013-03-19 15:03:48 -0700354
355 // NOTE: don't issue full saveLayer, since that has side effects/is costly. instead just
356 // setup the snapshot for deferral, and re-issue the op at flush time
357 deferStruct.mRenderer.saveLayerDeferred(mArea.left, mArea.top, mArea.right, mArea.bottom,
Derek Sollenbergerd44fbe52014-02-05 16:47:00 -0500358 mPaint, mFlags);
Chris Craikff785832013-03-08 13:12:16 -0800359 }
Chris Craik2af46352012-11-26 18:30:17 -0800360
Andreas Gampe64bb4132014-11-22 00:35:09 +0000361 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik3f0854292014-04-15 16:18:08 -0700362 renderer.saveLayer(mArea.left, mArea.top, mArea.right, mArea.bottom,
363 mPaint, mFlags, mConvexMask);
Chris Craik2af46352012-11-26 18:30:17 -0800364 }
365
Andreas Gampe64bb4132014-11-22 00:35:09 +0000366 virtual void output(int level, uint32_t logFlags) const {
Chris Craikff785832013-03-08 13:12:16 -0800367 OP_LOG("SaveLayer%s of area " RECT_STRING,
368 (isSaveLayerAlpha() ? "Alpha" : ""),RECT_ARGS(mArea));
Chris Craik2af46352012-11-26 18:30:17 -0800369 }
370
Chris Craikff785832013-03-08 13:12:16 -0800371 virtual const char* name() { return isSaveLayerAlpha() ? "SaveLayerAlpha" : "SaveLayer"; }
372
373 int getFlags() { return mFlags; }
Chris Craik2af46352012-11-26 18:30:17 -0800374
Chris Craik3f0854292014-04-15 16:18:08 -0700375 // Called to make SaveLayerOp clip to the provided mask when drawing back/restored
376 void setMask(const SkPath* convexMask) {
377 mConvexMask = convexMask;
378 }
379
Chris Craik2af46352012-11-26 18:30:17 -0800380private:
Derek Sollenbergerd44fbe52014-02-05 16:47:00 -0500381 bool isSaveLayerAlpha() const {
382 SkXfermode::Mode mode = OpenGLRenderer::getXfermodeDirect(mPaint);
383 int alpha = OpenGLRenderer::getAlphaDirect(mPaint);
384 return alpha < 255 && mode == SkXfermode::kSrcOver_Mode;
Chris Craik2af46352012-11-26 18:30:17 -0800385 }
386
Chris Craik2af46352012-11-26 18:30:17 -0800387 Rect mArea;
Derek Sollenbergerd44fbe52014-02-05 16:47:00 -0500388 const SkPaint* mPaint;
389 SkPaint mCachedPaint;
Chris Craik2af46352012-11-26 18:30:17 -0800390 int mFlags;
Chris Craik3f0854292014-04-15 16:18:08 -0700391
392 // Convex path, points at data in RenderNode, valid for the duration of the frame only
393 // Only used for masking the SaveLayer which wraps projected RenderNodes
394 const SkPath* mConvexMask;
Chris Craik2af46352012-11-26 18:30:17 -0800395};
396
397class TranslateOp : public StateOp {
398public:
399 TranslateOp(float dx, float dy)
400 : mDx(dx), mDy(dy) {}
401
Andreas Gampe64bb4132014-11-22 00:35:09 +0000402 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800403 renderer.translate(mDx, mDy);
404 }
405
Andreas Gampe64bb4132014-11-22 00:35:09 +0000406 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800407 OP_LOG("Translate by %f %f", mDx, mDy);
408 }
409
410 virtual const char* name() { return "Translate"; }
411
412private:
413 float mDx;
414 float mDy;
415};
416
417class RotateOp : public StateOp {
418public:
419 RotateOp(float degrees)
420 : mDegrees(degrees) {}
421
Andreas Gampe64bb4132014-11-22 00:35:09 +0000422 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800423 renderer.rotate(mDegrees);
424 }
425
Andreas Gampe64bb4132014-11-22 00:35:09 +0000426 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800427 OP_LOG("Rotate by %f degrees", mDegrees);
428 }
429
430 virtual const char* name() { return "Rotate"; }
431
432private:
433 float mDegrees;
434};
435
436class ScaleOp : public StateOp {
437public:
438 ScaleOp(float sx, float sy)
439 : mSx(sx), mSy(sy) {}
440
Andreas Gampe64bb4132014-11-22 00:35:09 +0000441 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800442 renderer.scale(mSx, mSy);
443 }
444
Andreas Gampe64bb4132014-11-22 00:35:09 +0000445 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800446 OP_LOG("Scale by %f %f", mSx, mSy);
447 }
448
449 virtual const char* name() { return "Scale"; }
450
451private:
452 float mSx;
453 float mSy;
454};
455
456class SkewOp : public StateOp {
457public:
458 SkewOp(float sx, float sy)
459 : mSx(sx), mSy(sy) {}
460
Andreas Gampe64bb4132014-11-22 00:35:09 +0000461 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800462 renderer.skew(mSx, mSy);
463 }
464
Andreas Gampe64bb4132014-11-22 00:35:09 +0000465 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800466 OP_LOG("Skew by %f %f", mSx, mSy);
467 }
468
469 virtual const char* name() { return "Skew"; }
470
471private:
472 float mSx;
473 float mSy;
474};
475
476class SetMatrixOp : public StateOp {
477public:
Derek Sollenberger13908822013-12-10 12:28:58 -0500478 SetMatrixOp(const SkMatrix& matrix)
Chris Craik2af46352012-11-26 18:30:17 -0800479 : mMatrix(matrix) {}
480
Andreas Gampe64bb4132014-11-22 00:35:09 +0000481 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800482 renderer.setMatrix(mMatrix);
483 }
484
Andreas Gampe64bb4132014-11-22 00:35:09 +0000485 virtual void output(int level, uint32_t logFlags) const {
Derek Sollenberger13908822013-12-10 12:28:58 -0500486 if (mMatrix.isIdentity()) {
Romain Guy4e7b7722013-07-16 13:47:01 -0700487 OP_LOGS("SetMatrix (reset)");
Derek Sollenberger13908822013-12-10 12:28:58 -0500488 } else {
489 OP_LOG("SetMatrix " SK_MATRIX_STRING, SK_MATRIX_ARGS(&mMatrix));
Romain Guy4e7b7722013-07-16 13:47:01 -0700490 }
Chris Craik2af46352012-11-26 18:30:17 -0800491 }
492
493 virtual const char* name() { return "SetMatrix"; }
494
495private:
Derek Sollenberger13908822013-12-10 12:28:58 -0500496 const SkMatrix mMatrix;
Chris Craik2af46352012-11-26 18:30:17 -0800497};
498
499class ConcatMatrixOp : public StateOp {
500public:
Derek Sollenberger13908822013-12-10 12:28:58 -0500501 ConcatMatrixOp(const SkMatrix& matrix)
Chris Craik2af46352012-11-26 18:30:17 -0800502 : mMatrix(matrix) {}
503
Andreas Gampe64bb4132014-11-22 00:35:09 +0000504 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800505 renderer.concatMatrix(mMatrix);
506 }
507
Andreas Gampe64bb4132014-11-22 00:35:09 +0000508 virtual void output(int level, uint32_t logFlags) const {
Derek Sollenberger13908822013-12-10 12:28:58 -0500509 OP_LOG("ConcatMatrix " SK_MATRIX_STRING, SK_MATRIX_ARGS(&mMatrix));
Chris Craik2af46352012-11-26 18:30:17 -0800510 }
511
512 virtual const char* name() { return "ConcatMatrix"; }
513
514private:
Derek Sollenberger13908822013-12-10 12:28:58 -0500515 const SkMatrix mMatrix;
Chris Craik2af46352012-11-26 18:30:17 -0800516};
517
Chris Craikff785832013-03-08 13:12:16 -0800518class ClipOp : public StateOp {
519public:
520 ClipOp(SkRegion::Op op) : mOp(op) {}
521
Andreas Gampe64bb4132014-11-22 00:35:09 +0000522 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
523 bool useQuickReject) {
Chris Craikff785832013-03-08 13:12:16 -0800524 // NOTE: must defer op BEFORE applying state, since it may read clip
525 deferStruct.mDeferredList.addClip(deferStruct.mRenderer, this);
526
527 // TODO: Can we avoid applying complex clips at defer time?
528 applyState(deferStruct.mRenderer, saveCount);
529 }
530
531 bool canCauseComplexClip() {
532 return ((mOp != SkRegion::kIntersect_Op) && (mOp != SkRegion::kReplace_Op)) || !isRect();
533 }
534
535protected:
Chris Craikff785832013-03-08 13:12:16 -0800536 virtual bool isRect() { return false; }
537
538 SkRegion::Op mOp;
539};
540
541class ClipRectOp : public ClipOp {
Chris Craik2af46352012-11-26 18:30:17 -0800542public:
543 ClipRectOp(float left, float top, float right, float bottom, SkRegion::Op op)
Chris Craikff785832013-03-08 13:12:16 -0800544 : ClipOp(op), mArea(left, top, right, bottom) {}
Chris Craik2af46352012-11-26 18:30:17 -0800545
Andreas Gampe64bb4132014-11-22 00:35:09 +0000546 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800547 renderer.clipRect(mArea.left, mArea.top, mArea.right, mArea.bottom, mOp);
548 }
549
Andreas Gampe64bb4132014-11-22 00:35:09 +0000550 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800551 OP_LOG("ClipRect " RECT_STRING, RECT_ARGS(mArea));
552 }
553
554 virtual const char* name() { return "ClipRect"; }
555
Chris Craikff785832013-03-08 13:12:16 -0800556protected:
557 virtual bool isRect() { return true; }
Chris Craikb98a0162013-02-21 11:30:22 -0800558
Chris Craik2af46352012-11-26 18:30:17 -0800559private:
560 Rect mArea;
Chris Craik2af46352012-11-26 18:30:17 -0800561};
562
Chris Craikff785832013-03-08 13:12:16 -0800563class ClipPathOp : public ClipOp {
Chris Craik2af46352012-11-26 18:30:17 -0800564public:
Chris Craikd218a922014-01-02 17:13:34 -0800565 ClipPathOp(const SkPath* path, SkRegion::Op op)
Chris Craikff785832013-03-08 13:12:16 -0800566 : ClipOp(op), mPath(path) {}
Chris Craik2af46352012-11-26 18:30:17 -0800567
Andreas Gampe64bb4132014-11-22 00:35:09 +0000568 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800569 renderer.clipPath(mPath, mOp);
570 }
571
Andreas Gampe64bb4132014-11-22 00:35:09 +0000572 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800573 SkRect bounds = mPath->getBounds();
574 OP_LOG("ClipPath bounds " RECT_STRING,
575 bounds.left(), bounds.top(), bounds.right(), bounds.bottom());
576 }
577
578 virtual const char* name() { return "ClipPath"; }
579
580private:
Chris Craikd218a922014-01-02 17:13:34 -0800581 const SkPath* mPath;
Chris Craik2af46352012-11-26 18:30:17 -0800582};
583
Chris Craikff785832013-03-08 13:12:16 -0800584class ClipRegionOp : public ClipOp {
Chris Craik2af46352012-11-26 18:30:17 -0800585public:
Chris Craikd218a922014-01-02 17:13:34 -0800586 ClipRegionOp(const SkRegion* region, SkRegion::Op op)
Chris Craikff785832013-03-08 13:12:16 -0800587 : ClipOp(op), mRegion(region) {}
Chris Craik2af46352012-11-26 18:30:17 -0800588
Andreas Gampe64bb4132014-11-22 00:35:09 +0000589 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800590 renderer.clipRegion(mRegion, mOp);
591 }
592
Andreas Gampe64bb4132014-11-22 00:35:09 +0000593 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800594 SkIRect bounds = mRegion->getBounds();
595 OP_LOG("ClipRegion bounds %d %d %d %d",
596 bounds.left(), bounds.top(), bounds.right(), bounds.bottom());
597 }
598
599 virtual const char* name() { return "ClipRegion"; }
600
601private:
Chris Craikd218a922014-01-02 17:13:34 -0800602 const SkRegion* mRegion;
Chris Craik2af46352012-11-26 18:30:17 -0800603};
604
Chris Craik2af46352012-11-26 18:30:17 -0800605///////////////////////////////////////////////////////////////////////////////
606// DRAW OPERATIONS - these are operations that can draw to the canvas's device
607///////////////////////////////////////////////////////////////////////////////
608
609class DrawBitmapOp : public DrawBoundedOp {
610public:
Chris Craik79647502014-08-06 13:42:24 -0700611 DrawBitmapOp(const SkBitmap* bitmap, const SkPaint* paint)
612 : DrawBoundedOp(0, 0, bitmap->width(), bitmap->height(), paint)
613 , mBitmap(bitmap)
614 , mAtlas(Caches::getInstance().assetAtlas) {
Romain Guy55b6f952013-06-27 15:27:09 -0700615 mEntry = mAtlas.getEntry(bitmap);
616 if (mEntry) {
617 mEntryGenerationId = mAtlas.getGenerationId();
618 mUvMapper = mEntry->uvMapper;
619 }
Romain Guy3b748a42013-04-17 18:54:38 -0700620 }
Chris Craik2af46352012-11-26 18:30:17 -0800621
Andreas Gampe64bb4132014-11-22 00:35:09 +0000622 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Tom Hudson107843d2014-09-08 11:26:26 -0400623 renderer.drawBitmap(mBitmap, mPaint);
Chris Craik2af46352012-11-26 18:30:17 -0800624 }
625
Romain Guy55b6f952013-06-27 15:27:09 -0700626 AssetAtlas::Entry* getAtlasEntry() {
627 // The atlas entry is stale, let's get a new one
628 if (mEntry && mEntryGenerationId != mAtlas.getGenerationId()) {
629 mEntryGenerationId = mAtlas.getGenerationId();
630 mEntry = mAtlas.getEntry(mBitmap);
631 mUvMapper = mEntry->uvMapper;
632 }
633 return mEntry;
634 }
635
Chris Craik527a3aa2013-03-04 10:19:31 -0800636#define SET_TEXTURE(ptr, posRect, offsetRect, texCoordsRect, xDim, yDim) \
637 TextureVertex::set(ptr++, posRect.xDim - offsetRect.left, posRect.yDim - offsetRect.top, \
638 texCoordsRect.xDim, texCoordsRect.yDim)
639
Romain Guy03c00b52013-06-20 18:30:28 -0700640 /**
641 * This multi-draw operation builds a mesh on the stack by generating a quad
642 * for each bitmap in the batch. This method is also responsible for dirtying
643 * the current layer, if any.
644 */
Andreas Gampe64bb4132014-11-22 00:35:09 +0000645 virtual void multiDraw(OpenGLRenderer& renderer, Rect& dirty,
Chris Craikc1c5f082013-09-11 16:23:37 -0700646 const Vector<OpStatePair>& ops, const Rect& bounds) {
647 const DeferredDisplayState& firstState = *(ops[0].state);
648 renderer.restoreDisplayState(firstState, true); // restore all but the clip
649
Chris Craik527a3aa2013-03-04 10:19:31 -0800650 TextureVertex vertices[6 * ops.size()];
651 TextureVertex* vertex = &vertices[0];
652
Romain Guy03c00b52013-06-20 18:30:28 -0700653 const bool hasLayer = renderer.hasLayer();
Chris Craik996fe652013-09-20 17:13:18 -0700654 bool pureTranslate = true;
Romain Guy2db5e992013-05-21 15:29:59 -0700655
Romain Guy3b748a42013-04-17 18:54:38 -0700656 // TODO: manually handle rect clip for bitmaps by adjusting texCoords per op,
657 // and allowing them to be merged in getBatchId()
Chris Craik527a3aa2013-03-04 10:19:31 -0800658 for (unsigned int i = 0; i < ops.size(); i++) {
Chris Craikc1c5f082013-09-11 16:23:37 -0700659 const DeferredDisplayState& state = *(ops[i].state);
660 const Rect& opBounds = state.mBounds;
Romain Guy2db5e992013-05-21 15:29:59 -0700661 // When we reach multiDraw(), the matrix can be either
662 // pureTranslate or simple (translate and/or scale).
663 // If the matrix is not pureTranslate, then we have a scale
Chris Craik996fe652013-09-20 17:13:18 -0700664 pureTranslate &= state.mMatrix.isPureTranslate();
Romain Guy3b748a42013-04-17 18:54:38 -0700665
666 Rect texCoords(0, 0, 1, 1);
Chris Craikc1c5f082013-09-11 16:23:37 -0700667 ((DrawBitmapOp*) ops[i].op)->mUvMapper.map(texCoords);
Romain Guy3b748a42013-04-17 18:54:38 -0700668
Chris Craik527a3aa2013-03-04 10:19:31 -0800669 SET_TEXTURE(vertex, opBounds, bounds, texCoords, left, top);
670 SET_TEXTURE(vertex, opBounds, bounds, texCoords, right, top);
671 SET_TEXTURE(vertex, opBounds, bounds, texCoords, left, bottom);
672
673 SET_TEXTURE(vertex, opBounds, bounds, texCoords, left, bottom);
674 SET_TEXTURE(vertex, opBounds, bounds, texCoords, right, top);
675 SET_TEXTURE(vertex, opBounds, bounds, texCoords, right, bottom);
Romain Guy03c00b52013-06-20 18:30:28 -0700676
677 if (hasLayer) {
Chris Craikc1c5f082013-09-11 16:23:37 -0700678 renderer.dirtyLayer(opBounds.left, opBounds.top, opBounds.right, opBounds.bottom);
Romain Guy03c00b52013-06-20 18:30:28 -0700679 }
Chris Craik527a3aa2013-03-04 10:19:31 -0800680 }
681
Tom Hudson107843d2014-09-08 11:26:26 -0400682 renderer.drawBitmaps(mBitmap, mEntry, ops.size(), &vertices[0],
Chris Craik996fe652013-09-20 17:13:18 -0700683 pureTranslate, bounds, mPaint);
Chris Craik527a3aa2013-03-04 10:19:31 -0800684 }
685
Andreas Gampe64bb4132014-11-22 00:35:09 +0000686 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800687 OP_LOG("Draw bitmap %p at %f %f", mBitmap, mLocalBounds.left, mLocalBounds.top);
688 }
689
690 virtual const char* name() { return "DrawBitmap"; }
Chris Craik527a3aa2013-03-04 10:19:31 -0800691
Andreas Gampe64bb4132014-11-22 00:35:09 +0000692 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
Chris Craikc1c5f082013-09-11 16:23:37 -0700693 const DeferredDisplayState& state) {
Chris Craik28ce94a2013-05-31 11:38:03 -0700694 deferInfo.batchId = DeferredDisplayList::kOpBatch_Bitmap;
Chris Craikd965bc52013-09-16 14:47:13 -0700695 deferInfo.mergeId = getAtlasEntry() ?
696 (mergeid_t) mEntry->getMergeId() : (mergeid_t) mBitmap;
Romain Guy2db5e992013-05-21 15:29:59 -0700697
Chris Craikd965bc52013-09-16 14:47:13 -0700698 // Don't merge non-simply transformed or neg scale ops, SET_TEXTURE doesn't handle rotation
Chris Craik28ce94a2013-05-31 11:38:03 -0700699 // Don't merge A8 bitmaps - the paint's color isn't compared by mergeId, or in
700 // MergingDrawBatch::canMergeWith()
701 // TODO: support clipped bitmaps by handling them in SET_TEXTURE
Chris Craikd965bc52013-09-16 14:47:13 -0700702 deferInfo.mergeable = state.mMatrix.isSimple() && state.mMatrix.positiveScale() &&
703 !state.mClipSideFlags &&
Chris Craik28ce94a2013-05-31 11:38:03 -0700704 OpenGLRenderer::getXfermodeDirect(mPaint) == SkXfermode::kSrcOver_Mode &&
Mike Reed1103b322014-07-08 12:36:44 -0400705 (mBitmap->colorType() != kAlpha_8_SkColorType);
Chris Craikc3566d02013-02-04 16:16:33 -0800706 }
Chris Craik2af46352012-11-26 18:30:17 -0800707
Chris Craik527a3aa2013-03-04 10:19:31 -0800708 const SkBitmap* bitmap() { return mBitmap; }
Chris Craik2af46352012-11-26 18:30:17 -0800709protected:
Chris Craikd218a922014-01-02 17:13:34 -0800710 const SkBitmap* mBitmap;
Romain Guy55b6f952013-06-27 15:27:09 -0700711 const AssetAtlas& mAtlas;
712 uint32_t mEntryGenerationId;
713 AssetAtlas::Entry* mEntry;
Romain Guy3b748a42013-04-17 18:54:38 -0700714 UvMapper mUvMapper;
Chris Craik2af46352012-11-26 18:30:17 -0800715};
716
Chris Craik2af46352012-11-26 18:30:17 -0800717class DrawBitmapRectOp : public DrawBoundedOp {
718public:
Chris Craikd218a922014-01-02 17:13:34 -0800719 DrawBitmapRectOp(const SkBitmap* bitmap,
720 float srcLeft, float srcTop, float srcRight, float srcBottom,
721 float dstLeft, float dstTop, float dstRight, float dstBottom, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -0800722 : DrawBoundedOp(dstLeft, dstTop, dstRight, dstBottom, paint),
723 mBitmap(bitmap), mSrc(srcLeft, srcTop, srcRight, srcBottom) {}
724
Andreas Gampe64bb4132014-11-22 00:35:09 +0000725 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Tom Hudson107843d2014-09-08 11:26:26 -0400726 renderer.drawBitmap(mBitmap, mSrc.left, mSrc.top, mSrc.right, mSrc.bottom,
Chris Craik2af46352012-11-26 18:30:17 -0800727 mLocalBounds.left, mLocalBounds.top, mLocalBounds.right, mLocalBounds.bottom,
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -0400728 mPaint);
Chris Craik2af46352012-11-26 18:30:17 -0800729 }
730
Andreas Gampe64bb4132014-11-22 00:35:09 +0000731 virtual void output(int level, uint32_t logFlags) const {
John Reckce444ca2014-06-02 15:12:36 -0700732 OP_LOG("Draw bitmap %p src=" RECT_STRING ", dst=" RECT_STRING,
Chris Craik2af46352012-11-26 18:30:17 -0800733 mBitmap, RECT_ARGS(mSrc), RECT_ARGS(mLocalBounds));
734 }
735
736 virtual const char* name() { return "DrawBitmapRect"; }
Chris Craik527a3aa2013-03-04 10:19:31 -0800737
Andreas Gampe64bb4132014-11-22 00:35:09 +0000738 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
739 const DeferredDisplayState& state) {
Chris Craik28ce94a2013-05-31 11:38:03 -0700740 deferInfo.batchId = DeferredDisplayList::kOpBatch_Bitmap;
Chris Craikc3566d02013-02-04 16:16:33 -0800741 }
Chris Craik2af46352012-11-26 18:30:17 -0800742
743private:
Chris Craikd218a922014-01-02 17:13:34 -0800744 const SkBitmap* mBitmap;
Chris Craik2af46352012-11-26 18:30:17 -0800745 Rect mSrc;
746};
747
748class DrawBitmapDataOp : public DrawBitmapOp {
749public:
Chris Craik79647502014-08-06 13:42:24 -0700750 DrawBitmapDataOp(const SkBitmap* bitmap, const SkPaint* paint)
751 : DrawBitmapOp(bitmap, paint) {}
Chris Craik2af46352012-11-26 18:30:17 -0800752
Andreas Gampe64bb4132014-11-22 00:35:09 +0000753 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Tom Hudson107843d2014-09-08 11:26:26 -0400754 renderer.drawBitmapData(mBitmap, mPaint);
Chris Craik2af46352012-11-26 18:30:17 -0800755 }
756
Andreas Gampe64bb4132014-11-22 00:35:09 +0000757 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800758 OP_LOG("Draw bitmap %p", mBitmap);
759 }
760
761 virtual const char* name() { return "DrawBitmapData"; }
Chris Craik527a3aa2013-03-04 10:19:31 -0800762
Andreas Gampe64bb4132014-11-22 00:35:09 +0000763 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
764 const DeferredDisplayState& state) {
Chris Craik28ce94a2013-05-31 11:38:03 -0700765 deferInfo.batchId = DeferredDisplayList::kOpBatch_Bitmap;
Chris Craikc3566d02013-02-04 16:16:33 -0800766 }
Chris Craik2af46352012-11-26 18:30:17 -0800767};
768
Chris Craik5d116762013-02-19 17:49:31 -0800769class DrawBitmapMeshOp : public DrawBoundedOp {
Chris Craik2af46352012-11-26 18:30:17 -0800770public:
Chris Craikd218a922014-01-02 17:13:34 -0800771 DrawBitmapMeshOp(const SkBitmap* bitmap, int meshWidth, int meshHeight,
772 const float* vertices, const int* colors, const SkPaint* paint)
Chris Craik5d116762013-02-19 17:49:31 -0800773 : DrawBoundedOp(vertices, 2 * (meshWidth + 1) * (meshHeight + 1), paint),
774 mBitmap(bitmap), mMeshWidth(meshWidth), mMeshHeight(meshHeight),
Chris Craik2af46352012-11-26 18:30:17 -0800775 mVertices(vertices), mColors(colors) {}
776
Andreas Gampe64bb4132014-11-22 00:35:09 +0000777 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Tom Hudson107843d2014-09-08 11:26:26 -0400778 renderer.drawBitmapMesh(mBitmap, mMeshWidth, mMeshHeight,
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -0400779 mVertices, mColors, mPaint);
Chris Craik2af46352012-11-26 18:30:17 -0800780 }
781
Andreas Gampe64bb4132014-11-22 00:35:09 +0000782 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800783 OP_LOG("Draw bitmap %p mesh %d x %d", mBitmap, mMeshWidth, mMeshHeight);
784 }
785
786 virtual const char* name() { return "DrawBitmapMesh"; }
Chris Craik527a3aa2013-03-04 10:19:31 -0800787
Andreas Gampe64bb4132014-11-22 00:35:09 +0000788 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
789 const DeferredDisplayState& state) {
Chris Craik28ce94a2013-05-31 11:38:03 -0700790 deferInfo.batchId = DeferredDisplayList::kOpBatch_Bitmap;
Chris Craikc3566d02013-02-04 16:16:33 -0800791 }
Chris Craik2af46352012-11-26 18:30:17 -0800792
793private:
Chris Craikd218a922014-01-02 17:13:34 -0800794 const SkBitmap* mBitmap;
Chris Craik2af46352012-11-26 18:30:17 -0800795 int mMeshWidth;
796 int mMeshHeight;
Chris Craikd218a922014-01-02 17:13:34 -0800797 const float* mVertices;
798 const int* mColors;
Chris Craik2af46352012-11-26 18:30:17 -0800799};
800
801class DrawPatchOp : public DrawBoundedOp {
802public:
Chris Craikd218a922014-01-02 17:13:34 -0800803 DrawPatchOp(const SkBitmap* bitmap, const Res_png_9patch* patch,
804 float left, float top, float right, float bottom, const SkPaint* paint)
Romain Guy03c00b52013-06-20 18:30:28 -0700805 : DrawBoundedOp(left, top, right, bottom, paint),
Romain Guy55b6f952013-06-27 15:27:09 -0700806 mBitmap(bitmap), mPatch(patch), mGenerationId(0), mMesh(NULL),
807 mAtlas(Caches::getInstance().assetAtlas) {
808 mEntry = mAtlas.getEntry(bitmap);
809 if (mEntry) {
810 mEntryGenerationId = mAtlas.getGenerationId();
811 }
Romain Guy3b748a42013-04-17 18:54:38 -0700812 };
Chris Craik2af46352012-11-26 18:30:17 -0800813
Romain Guy55b6f952013-06-27 15:27:09 -0700814 AssetAtlas::Entry* getAtlasEntry() {
815 // The atlas entry is stale, let's get a new one
816 if (mEntry && mEntryGenerationId != mAtlas.getGenerationId()) {
817 mEntryGenerationId = mAtlas.getGenerationId();
818 mEntry = mAtlas.getEntry(mBitmap);
819 }
820 return mEntry;
821 }
822
Romain Guy03c00b52013-06-20 18:30:28 -0700823 const Patch* getMesh(OpenGLRenderer& renderer) {
Romain Guy4c2547f2013-06-11 16:19:24 -0700824 if (!mMesh || renderer.getCaches().patchCache.getGenerationId() != mGenerationId) {
825 PatchCache& cache = renderer.getCaches().patchCache;
Romain Guy55b6f952013-06-27 15:27:09 -0700826 mMesh = cache.get(getAtlasEntry(), mBitmap->width(), mBitmap->height(),
Romain Guy03c00b52013-06-20 18:30:28 -0700827 mLocalBounds.getWidth(), mLocalBounds.getHeight(), mPatch);
Romain Guy4c2547f2013-06-11 16:19:24 -0700828 mGenerationId = cache.getGenerationId();
829 }
Romain Guy03c00b52013-06-20 18:30:28 -0700830 return mMesh;
831 }
832
833 /**
834 * This multi-draw operation builds an indexed mesh on the stack by copying
835 * and transforming the vertices of each 9-patch in the batch. This method
836 * is also responsible for dirtying the current layer, if any.
837 */
Andreas Gampe64bb4132014-11-22 00:35:09 +0000838 virtual void multiDraw(OpenGLRenderer& renderer, Rect& dirty,
839 const Vector<OpStatePair>& ops, const Rect& bounds) {
Chris Craikc1c5f082013-09-11 16:23:37 -0700840 const DeferredDisplayState& firstState = *(ops[0].state);
841 renderer.restoreDisplayState(firstState, true); // restore all but the clip
Romain Guy03c00b52013-06-20 18:30:28 -0700842
843 // Batches will usually contain a small number of items so it's
844 // worth performing a first iteration to count the exact number
845 // of vertices we need in the new mesh
846 uint32_t totalVertices = 0;
847 for (unsigned int i = 0; i < ops.size(); i++) {
Chris Craikc1c5f082013-09-11 16:23:37 -0700848 totalVertices += ((DrawPatchOp*) ops[i].op)->getMesh(renderer)->verticesCount;
Romain Guy03c00b52013-06-20 18:30:28 -0700849 }
850
851 const bool hasLayer = renderer.hasLayer();
852
853 uint32_t indexCount = 0;
854
855 TextureVertex vertices[totalVertices];
856 TextureVertex* vertex = &vertices[0];
857
858 // Create a mesh that contains the transformed vertices for all the
859 // 9-patch objects that are part of the batch. Note that onDefer()
860 // enforces ops drawn by this function to have a pure translate or
861 // identity matrix
862 for (unsigned int i = 0; i < ops.size(); i++) {
Chris Craikc1c5f082013-09-11 16:23:37 -0700863 DrawPatchOp* patchOp = (DrawPatchOp*) ops[i].op;
864 const DeferredDisplayState* state = ops[i].state;
Romain Guy03c00b52013-06-20 18:30:28 -0700865 const Patch* opMesh = patchOp->getMesh(renderer);
866 uint32_t vertexCount = opMesh->verticesCount;
867 if (vertexCount == 0) continue;
868
869 // We use the bounds to know where to translate our vertices
870 // Using patchOp->state.mBounds wouldn't work because these
871 // bounds are clipped
Chris Craikc1c5f082013-09-11 16:23:37 -0700872 const float tx = (int) floorf(state->mMatrix.getTranslateX() +
Romain Guy03c00b52013-06-20 18:30:28 -0700873 patchOp->mLocalBounds.left + 0.5f);
Chris Craikc1c5f082013-09-11 16:23:37 -0700874 const float ty = (int) floorf(state->mMatrix.getTranslateY() +
Romain Guy03c00b52013-06-20 18:30:28 -0700875 patchOp->mLocalBounds.top + 0.5f);
876
877 // Copy & transform all the vertices for the current operation
878 TextureVertex* opVertices = opMesh->vertices;
879 for (uint32_t j = 0; j < vertexCount; j++, opVertices++) {
880 TextureVertex::set(vertex++,
Romain Guy3380cfd2013-08-15 16:57:57 -0700881 opVertices->x + tx, opVertices->y + ty,
882 opVertices->u, opVertices->v);
Romain Guy03c00b52013-06-20 18:30:28 -0700883 }
884
885 // Dirty the current layer if possible. When the 9-patch does not
886 // contain empty quads we can take a shortcut and simply set the
887 // dirty rect to the object's bounds.
888 if (hasLayer) {
889 if (!opMesh->hasEmptyQuads) {
890 renderer.dirtyLayer(tx, ty,
891 tx + patchOp->mLocalBounds.getWidth(),
892 ty + patchOp->mLocalBounds.getHeight());
893 } else {
894 const size_t count = opMesh->quads.size();
895 for (size_t i = 0; i < count; i++) {
896 const Rect& quadBounds = opMesh->quads[i];
897 const float x = tx + quadBounds.left;
898 const float y = ty + quadBounds.top;
899 renderer.dirtyLayer(x, y,
900 x + quadBounds.getWidth(), y + quadBounds.getHeight());
901 }
902 }
903 }
904
905 indexCount += opMesh->indexCount;
906 }
907
Tom Hudson107843d2014-09-08 11:26:26 -0400908 renderer.drawPatches(mBitmap, getAtlasEntry(),
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -0400909 &vertices[0], indexCount, mPaint);
Romain Guy03c00b52013-06-20 18:30:28 -0700910 }
911
Andreas Gampe64bb4132014-11-22 00:35:09 +0000912 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Romain Guy4c2547f2013-06-11 16:19:24 -0700913 // We're not calling the public variant of drawPatch() here
914 // This method won't perform the quickReject() since we've already done it at this point
Tom Hudson107843d2014-09-08 11:26:26 -0400915 renderer.drawPatch(mBitmap, getMesh(renderer), getAtlasEntry(),
Romain Guy03c00b52013-06-20 18:30:28 -0700916 mLocalBounds.left, mLocalBounds.top, mLocalBounds.right, mLocalBounds.bottom,
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -0400917 mPaint);
Chris Craik2af46352012-11-26 18:30:17 -0800918 }
919
Andreas Gampe64bb4132014-11-22 00:35:09 +0000920 virtual void output(int level, uint32_t logFlags) const {
John Reckce444ca2014-06-02 15:12:36 -0700921 OP_LOG("Draw patch " RECT_STRING, RECT_ARGS(mLocalBounds));
Chris Craik2af46352012-11-26 18:30:17 -0800922 }
923
924 virtual const char* name() { return "DrawPatch"; }
Chris Craik527a3aa2013-03-04 10:19:31 -0800925
Andreas Gampe64bb4132014-11-22 00:35:09 +0000926 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
Chris Craikc1c5f082013-09-11 16:23:37 -0700927 const DeferredDisplayState& state) {
Chris Craik28ce94a2013-05-31 11:38:03 -0700928 deferInfo.batchId = DeferredDisplayList::kOpBatch_Patch;
Romain Guy7f6d6b02013-08-06 13:49:28 -0700929 deferInfo.mergeId = getAtlasEntry() ? (mergeid_t) mEntry->getMergeId() : (mergeid_t) mBitmap;
Romain Guy03c00b52013-06-20 18:30:28 -0700930 deferInfo.mergeable = state.mMatrix.isPureTranslate() &&
931 OpenGLRenderer::getXfermodeDirect(mPaint) == SkXfermode::kSrcOver_Mode;
Chris Craikc1c5f082013-09-11 16:23:37 -0700932 deferInfo.opaqueOverBounds = isOpaqueOverBounds(state) && mBitmap->isOpaque();
Chris Craikc3566d02013-02-04 16:16:33 -0800933 }
Chris Craik2af46352012-11-26 18:30:17 -0800934
935private:
Chris Craikd218a922014-01-02 17:13:34 -0800936 const SkBitmap* mBitmap;
937 const Res_png_9patch* mPatch;
Romain Guy4c2547f2013-06-11 16:19:24 -0700938
Romain Guy4c2547f2013-06-11 16:19:24 -0700939 uint32_t mGenerationId;
940 const Patch* mMesh;
Romain Guy03c00b52013-06-20 18:30:28 -0700941
Romain Guy55b6f952013-06-27 15:27:09 -0700942 const AssetAtlas& mAtlas;
943 uint32_t mEntryGenerationId;
Romain Guy3b748a42013-04-17 18:54:38 -0700944 AssetAtlas::Entry* mEntry;
Chris Craik2af46352012-11-26 18:30:17 -0800945};
946
947class DrawColorOp : public DrawOp {
948public:
949 DrawColorOp(int color, SkXfermode::Mode mode)
Chris Craikf57776b2013-10-25 18:30:17 -0700950 : DrawOp(NULL), mColor(color), mMode(mode) {};
Chris Craik2af46352012-11-26 18:30:17 -0800951
Andreas Gampe64bb4132014-11-22 00:35:09 +0000952 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Tom Hudson107843d2014-09-08 11:26:26 -0400953 renderer.drawColor(mColor, mMode);
Chris Craik2af46352012-11-26 18:30:17 -0800954 }
955
Andreas Gampe64bb4132014-11-22 00:35:09 +0000956 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800957 OP_LOG("Draw color %#x, mode %d", mColor, mMode);
958 }
959
960 virtual const char* name() { return "DrawColor"; }
961
962private:
963 int mColor;
964 SkXfermode::Mode mMode;
965};
966
967class DrawStrokableOp : public DrawBoundedOp {
968public:
Chris Craikd218a922014-01-02 17:13:34 -0800969 DrawStrokableOp(float left, float top, float right, float bottom, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -0800970 : DrawBoundedOp(left, top, right, bottom, paint) {};
Chris Craik947eabf2014-08-19 10:21:12 -0700971 DrawStrokableOp(const Rect& localBounds, const SkPaint* paint)
972 : DrawBoundedOp(localBounds, paint) {};
Chris Craik2af46352012-11-26 18:30:17 -0800973
John Reckca1b3b82014-06-27 07:21:36 -0700974 virtual bool getLocalBounds(Rect& localBounds) {
Chris Craikc3566d02013-02-04 16:16:33 -0800975 localBounds.set(mLocalBounds);
Chris Craik2af46352012-11-26 18:30:17 -0800976 if (mPaint && mPaint->getStyle() != SkPaint::kFill_Style) {
Chris Craikc3566d02013-02-04 16:16:33 -0800977 localBounds.outset(strokeWidthOutset());
Chris Craik2af46352012-11-26 18:30:17 -0800978 }
979 return true;
980 }
Chris Craikc3566d02013-02-04 16:16:33 -0800981
Andreas Gampe64bb4132014-11-22 00:35:09 +0000982 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
983 const DeferredDisplayState& state) {
Chris Craikc3566d02013-02-04 16:16:33 -0800984 if (mPaint->getPathEffect()) {
Chris Craik28ce94a2013-05-31 11:38:03 -0700985 deferInfo.batchId = DeferredDisplayList::kOpBatch_AlphaMaskTexture;
Chris Craik527a3aa2013-03-04 10:19:31 -0800986 } else {
Chris Craik28ce94a2013-05-31 11:38:03 -0700987 deferInfo.batchId = mPaint->isAntiAlias() ?
Chris Craik527a3aa2013-03-04 10:19:31 -0800988 DeferredDisplayList::kOpBatch_AlphaVertices :
989 DeferredDisplayList::kOpBatch_Vertices;
Chris Craikc3566d02013-02-04 16:16:33 -0800990 }
Chris Craikc3566d02013-02-04 16:16:33 -0800991 }
Chris Craik2af46352012-11-26 18:30:17 -0800992};
993
994class DrawRectOp : public DrawStrokableOp {
995public:
Chris Craikd218a922014-01-02 17:13:34 -0800996 DrawRectOp(float left, float top, float right, float bottom, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -0800997 : DrawStrokableOp(left, top, right, bottom, paint) {}
998
Andreas Gampe64bb4132014-11-22 00:35:09 +0000999 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Tom Hudson107843d2014-09-08 11:26:26 -04001000 renderer.drawRect(mLocalBounds.left, mLocalBounds.top,
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -04001001 mLocalBounds.right, mLocalBounds.bottom, mPaint);
Chris Craik2af46352012-11-26 18:30:17 -08001002 }
1003
Andreas Gampe64bb4132014-11-22 00:35:09 +00001004 virtual void output(int level, uint32_t logFlags) const {
John Reckce444ca2014-06-02 15:12:36 -07001005 OP_LOG("Draw Rect " RECT_STRING, RECT_ARGS(mLocalBounds));
Chris Craik2af46352012-11-26 18:30:17 -08001006 }
1007
Chris Craikc1c5f082013-09-11 16:23:37 -07001008 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
1009 const DeferredDisplayState& state) {
1010 DrawStrokableOp::onDefer(renderer, deferInfo, state);
1011 deferInfo.opaqueOverBounds = isOpaqueOverBounds(state) &&
Chris Craik28ce94a2013-05-31 11:38:03 -07001012 mPaint->getStyle() == SkPaint::kFill_Style;
1013 }
1014
Chris Craik2af46352012-11-26 18:30:17 -08001015 virtual const char* name() { return "DrawRect"; }
1016};
1017
Chris Craik5d116762013-02-19 17:49:31 -08001018class DrawRectsOp : public DrawBoundedOp {
Chris Craik2af46352012-11-26 18:30:17 -08001019public:
Chris Craikd218a922014-01-02 17:13:34 -08001020 DrawRectsOp(const float* rects, int count, const SkPaint* paint)
Chris Craik5d116762013-02-19 17:49:31 -08001021 : DrawBoundedOp(rects, count, paint),
1022 mRects(rects), mCount(count) {}
Chris Craik2af46352012-11-26 18:30:17 -08001023
Andreas Gampe64bb4132014-11-22 00:35:09 +00001024 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Tom Hudson107843d2014-09-08 11:26:26 -04001025 renderer.drawRects(mRects, mCount, mPaint);
Chris Craik2af46352012-11-26 18:30:17 -08001026 }
1027
Andreas Gampe64bb4132014-11-22 00:35:09 +00001028 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001029 OP_LOG("Draw Rects count %d", mCount);
1030 }
1031
1032 virtual const char* name() { return "DrawRects"; }
1033
Andreas Gampe64bb4132014-11-22 00:35:09 +00001034 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
1035 const DeferredDisplayState& state) {
Chris Craik28ce94a2013-05-31 11:38:03 -07001036 deferInfo.batchId = DeferredDisplayList::kOpBatch_Vertices;
Chris Craikc3566d02013-02-04 16:16:33 -08001037 }
1038
Chris Craik2af46352012-11-26 18:30:17 -08001039private:
1040 const float* mRects;
1041 int mCount;
1042};
1043
1044class DrawRoundRectOp : public DrawStrokableOp {
1045public:
1046 DrawRoundRectOp(float left, float top, float right, float bottom,
Chris Craikd218a922014-01-02 17:13:34 -08001047 float rx, float ry, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001048 : DrawStrokableOp(left, top, right, bottom, paint), mRx(rx), mRy(ry) {}
1049
Andreas Gampe64bb4132014-11-22 00:35:09 +00001050 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Tom Hudson107843d2014-09-08 11:26:26 -04001051 renderer.drawRoundRect(mLocalBounds.left, mLocalBounds.top,
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -04001052 mLocalBounds.right, mLocalBounds.bottom, mRx, mRy, mPaint);
Chris Craik2af46352012-11-26 18:30:17 -08001053 }
1054
Andreas Gampe64bb4132014-11-22 00:35:09 +00001055 virtual void output(int level, uint32_t logFlags) const {
John Reckce444ca2014-06-02 15:12:36 -07001056 OP_LOG("Draw RoundRect " RECT_STRING ", rx %f, ry %f", RECT_ARGS(mLocalBounds), mRx, mRy);
Chris Craik2af46352012-11-26 18:30:17 -08001057 }
1058
Chris Craik05f3d6e2014-06-02 16:27:04 -07001059 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
1060 const DeferredDisplayState& state) {
1061 DrawStrokableOp::onDefer(renderer, deferInfo, state);
1062 if (!mPaint->getPathEffect()) {
Chris Craik6ac174b2014-06-17 13:47:05 -07001063 renderer.getCaches().tessellationCache.precacheRoundRect(state.mMatrix, *mPaint,
1064 mLocalBounds.getWidth(), mLocalBounds.getHeight(), mRx, mRy);
Chris Craik05f3d6e2014-06-02 16:27:04 -07001065 }
1066 }
1067
Chris Craik2af46352012-11-26 18:30:17 -08001068 virtual const char* name() { return "DrawRoundRect"; }
1069
1070private:
1071 float mRx;
1072 float mRy;
1073};
1074
Jorim Jaggi072707d2014-09-15 17:20:08 +02001075class DrawRoundRectPropsOp : public DrawOp {
1076public:
1077 DrawRoundRectPropsOp(float* left, float* top, float* right, float* bottom,
1078 float *rx, float *ry, const SkPaint* paint)
1079 : DrawOp(paint), mLeft(left), mTop(top), mRight(right), mBottom(bottom),
1080 mRx(rx), mRy(ry) {}
1081
Andreas Gampe64bb4132014-11-22 00:35:09 +00001082 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Tom Hudson107843d2014-09-08 11:26:26 -04001083 renderer.drawRoundRect(*mLeft, *mTop, *mRight, *mBottom,
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -04001084 *mRx, *mRy, mPaint);
Jorim Jaggi072707d2014-09-15 17:20:08 +02001085 }
1086
Andreas Gampe64bb4132014-11-22 00:35:09 +00001087 virtual void output(int level, uint32_t logFlags) const {
Jorim Jaggi072707d2014-09-15 17:20:08 +02001088 OP_LOG("Draw RoundRect Props " RECT_STRING ", rx %f, ry %f",
1089 *mLeft, *mTop, *mRight, *mBottom, *mRx, *mRy);
1090 }
1091
1092 virtual const char* name() { return "DrawRoundRectProps"; }
1093
1094private:
1095 float* mLeft;
1096 float* mTop;
1097 float* mRight;
1098 float* mBottom;
1099 float* mRx;
1100 float* mRy;
1101};
1102
Chris Craik2af46352012-11-26 18:30:17 -08001103class DrawCircleOp : public DrawStrokableOp {
1104public:
Chris Craikd218a922014-01-02 17:13:34 -08001105 DrawCircleOp(float x, float y, float radius, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001106 : DrawStrokableOp(x - radius, y - radius, x + radius, y + radius, paint),
1107 mX(x), mY(y), mRadius(radius) {}
1108
Andreas Gampe64bb4132014-11-22 00:35:09 +00001109 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Tom Hudson107843d2014-09-08 11:26:26 -04001110 renderer.drawCircle(mX, mY, mRadius, mPaint);
Chris Craik2af46352012-11-26 18:30:17 -08001111 }
1112
Andreas Gampe64bb4132014-11-22 00:35:09 +00001113 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001114 OP_LOG("Draw Circle x %f, y %f, r %f", mX, mY, mRadius);
1115 }
1116
1117 virtual const char* name() { return "DrawCircle"; }
1118
1119private:
1120 float mX;
1121 float mY;
1122 float mRadius;
1123};
1124
John Reck52244ff2014-05-01 21:27:37 -07001125class DrawCirclePropsOp : public DrawOp {
1126public:
1127 DrawCirclePropsOp(float* x, float* y, float* radius, const SkPaint* paint)
1128 : DrawOp(paint), mX(x), mY(y), mRadius(radius) {}
1129
Andreas Gampe64bb4132014-11-22 00:35:09 +00001130 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Tom Hudson107843d2014-09-08 11:26:26 -04001131 renderer.drawCircle(*mX, *mY, *mRadius, mPaint);
John Reck52244ff2014-05-01 21:27:37 -07001132 }
1133
Andreas Gampe64bb4132014-11-22 00:35:09 +00001134 virtual void output(int level, uint32_t logFlags) const {
John Reck52244ff2014-05-01 21:27:37 -07001135 OP_LOG("Draw Circle Props x %p, y %p, r %p", mX, mY, mRadius);
1136 }
1137
1138 virtual const char* name() { return "DrawCircleProps"; }
1139
1140private:
1141 float* mX;
1142 float* mY;
1143 float* mRadius;
1144};
1145
Chris Craik2af46352012-11-26 18:30:17 -08001146class DrawOvalOp : public DrawStrokableOp {
1147public:
Chris Craikd218a922014-01-02 17:13:34 -08001148 DrawOvalOp(float left, float top, float right, float bottom, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001149 : DrawStrokableOp(left, top, right, bottom, paint) {}
1150
Andreas Gampe64bb4132014-11-22 00:35:09 +00001151 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Tom Hudson107843d2014-09-08 11:26:26 -04001152 renderer.drawOval(mLocalBounds.left, mLocalBounds.top,
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -04001153 mLocalBounds.right, mLocalBounds.bottom, mPaint);
Chris Craik2af46352012-11-26 18:30:17 -08001154 }
1155
Andreas Gampe64bb4132014-11-22 00:35:09 +00001156 virtual void output(int level, uint32_t logFlags) const {
John Reckce444ca2014-06-02 15:12:36 -07001157 OP_LOG("Draw Oval " RECT_STRING, RECT_ARGS(mLocalBounds));
Chris Craik2af46352012-11-26 18:30:17 -08001158 }
1159
1160 virtual const char* name() { return "DrawOval"; }
1161};
1162
1163class DrawArcOp : public DrawStrokableOp {
1164public:
1165 DrawArcOp(float left, float top, float right, float bottom,
Chris Craikd218a922014-01-02 17:13:34 -08001166 float startAngle, float sweepAngle, bool useCenter, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001167 : DrawStrokableOp(left, top, right, bottom, paint),
1168 mStartAngle(startAngle), mSweepAngle(sweepAngle), mUseCenter(useCenter) {}
1169
Andreas Gampe64bb4132014-11-22 00:35:09 +00001170 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Tom Hudson107843d2014-09-08 11:26:26 -04001171 renderer.drawArc(mLocalBounds.left, mLocalBounds.top,
Chris Craik2af46352012-11-26 18:30:17 -08001172 mLocalBounds.right, mLocalBounds.bottom,
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -04001173 mStartAngle, mSweepAngle, mUseCenter, mPaint);
Chris Craik2af46352012-11-26 18:30:17 -08001174 }
1175
Andreas Gampe64bb4132014-11-22 00:35:09 +00001176 virtual void output(int level, uint32_t logFlags) const {
John Reckce444ca2014-06-02 15:12:36 -07001177 OP_LOG("Draw Arc " RECT_STRING ", start %f, sweep %f, useCenter %d",
Chris Craik2af46352012-11-26 18:30:17 -08001178 RECT_ARGS(mLocalBounds), mStartAngle, mSweepAngle, mUseCenter);
1179 }
1180
1181 virtual const char* name() { return "DrawArc"; }
1182
1183private:
1184 float mStartAngle;
1185 float mSweepAngle;
1186 bool mUseCenter;
1187};
1188
1189class DrawPathOp : public DrawBoundedOp {
1190public:
Chris Craikd218a922014-01-02 17:13:34 -08001191 DrawPathOp(const SkPath* path, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001192 : DrawBoundedOp(paint), mPath(path) {
1193 float left, top, offset;
1194 uint32_t width, height;
Romain Guyca89e2a2013-03-08 17:44:20 -08001195 PathCache::computePathBounds(path, paint, left, top, offset, width, height);
Chris Craik2af46352012-11-26 18:30:17 -08001196 left -= offset;
1197 top -= offset;
1198 mLocalBounds.set(left, top, left + width, top + height);
1199 }
1200
Andreas Gampe64bb4132014-11-22 00:35:09 +00001201 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Tom Hudson107843d2014-09-08 11:26:26 -04001202 renderer.drawPath(mPath, mPaint);
Chris Craik2af46352012-11-26 18:30:17 -08001203 }
1204
Chris Craikc1c5f082013-09-11 16:23:37 -07001205 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
Andreas Gampe64bb4132014-11-22 00:35:09 +00001206 const DeferredDisplayState& state) {
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -04001207 renderer.getCaches().pathCache.precache(mPath, mPaint);
Chris Craik527a3aa2013-03-04 10:19:31 -08001208
Chris Craik28ce94a2013-05-31 11:38:03 -07001209 deferInfo.batchId = DeferredDisplayList::kOpBatch_AlphaMaskTexture;
Romain Guyca89e2a2013-03-08 17:44:20 -08001210 }
1211
Andreas Gampe64bb4132014-11-22 00:35:09 +00001212 virtual void output(int level, uint32_t logFlags) const {
John Reckce444ca2014-06-02 15:12:36 -07001213 OP_LOG("Draw Path %p in " RECT_STRING, mPath, RECT_ARGS(mLocalBounds));
Chris Craik2af46352012-11-26 18:30:17 -08001214 }
1215
1216 virtual const char* name() { return "DrawPath"; }
1217
1218private:
Chris Craikd218a922014-01-02 17:13:34 -08001219 const SkPath* mPath;
Chris Craik2af46352012-11-26 18:30:17 -08001220};
1221
Chris Craikc3566d02013-02-04 16:16:33 -08001222class DrawLinesOp : public DrawBoundedOp {
Chris Craik2af46352012-11-26 18:30:17 -08001223public:
Chris Craikd218a922014-01-02 17:13:34 -08001224 DrawLinesOp(const float* points, int count, const SkPaint* paint)
Chris Craik5d116762013-02-19 17:49:31 -08001225 : DrawBoundedOp(points, count, paint),
1226 mPoints(points), mCount(count) {
Chris Craikc3566d02013-02-04 16:16:33 -08001227 mLocalBounds.outset(strokeWidthOutset());
Chris Craik2af46352012-11-26 18:30:17 -08001228 }
1229
Andreas Gampe64bb4132014-11-22 00:35:09 +00001230 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Tom Hudson107843d2014-09-08 11:26:26 -04001231 renderer.drawLines(mPoints, mCount, mPaint);
Chris Craik2af46352012-11-26 18:30:17 -08001232 }
1233
Andreas Gampe64bb4132014-11-22 00:35:09 +00001234 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001235 OP_LOG("Draw Lines count %d", mCount);
1236 }
1237
1238 virtual const char* name() { return "DrawLines"; }
1239
Andreas Gampe64bb4132014-11-22 00:35:09 +00001240 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
1241 const DeferredDisplayState& state) {
Chris Craik28ce94a2013-05-31 11:38:03 -07001242 deferInfo.batchId = mPaint->isAntiAlias() ?
Chris Craikc3566d02013-02-04 16:16:33 -08001243 DeferredDisplayList::kOpBatch_AlphaVertices :
1244 DeferredDisplayList::kOpBatch_Vertices;
1245 }
1246
Chris Craik2af46352012-11-26 18:30:17 -08001247protected:
Chris Craikd218a922014-01-02 17:13:34 -08001248 const float* mPoints;
Chris Craik2af46352012-11-26 18:30:17 -08001249 int mCount;
1250};
1251
1252class DrawPointsOp : public DrawLinesOp {
1253public:
Chris Craikd218a922014-01-02 17:13:34 -08001254 DrawPointsOp(const float* points, int count, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001255 : DrawLinesOp(points, count, paint) {}
1256
Andreas Gampe64bb4132014-11-22 00:35:09 +00001257 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Tom Hudson107843d2014-09-08 11:26:26 -04001258 renderer.drawPoints(mPoints, mCount, mPaint);
Chris Craik2af46352012-11-26 18:30:17 -08001259 }
1260
Andreas Gampe64bb4132014-11-22 00:35:09 +00001261 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001262 OP_LOG("Draw Points count %d", mCount);
1263 }
1264
1265 virtual const char* name() { return "DrawPoints"; }
1266};
1267
1268class DrawSomeTextOp : public DrawOp {
1269public:
Chris Craikd218a922014-01-02 17:13:34 -08001270 DrawSomeTextOp(const char* text, int bytesCount, int count, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001271 : DrawOp(paint), mText(text), mBytesCount(bytesCount), mCount(count) {};
1272
Andreas Gampe64bb4132014-11-22 00:35:09 +00001273 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001274 OP_LOG("Draw some text, %d bytes", mBytesCount);
1275 }
Chris Craikc3566d02013-02-04 16:16:33 -08001276
Derek Sollenbergerc29a0a42014-03-31 13:52:39 -04001277 virtual bool hasTextShadow() const {
1278 return OpenGLRenderer::hasTextShadow(mPaint);
1279 }
1280
Chris Craikc1c5f082013-09-11 16:23:37 -07001281 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
Andreas Gampe64bb4132014-11-22 00:35:09 +00001282 const DeferredDisplayState& state) {
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -04001283 FontRenderer& fontRenderer = renderer.getCaches().fontRenderer->getFontRenderer(mPaint);
1284 fontRenderer.precache(mPaint, mText, mCount, SkMatrix::I());
Romain Guy0f6675332013-03-01 14:31:04 -08001285
Chris Craik98d608d2014-07-17 12:25:11 -07001286 deferInfo.batchId = mPaint->getColor() == SK_ColorBLACK ?
Chris Craikc3566d02013-02-04 16:16:33 -08001287 DeferredDisplayList::kOpBatch_Text :
1288 DeferredDisplayList::kOpBatch_ColorText;
1289 }
Chris Craik527a3aa2013-03-04 10:19:31 -08001290
Chris Craik2af46352012-11-26 18:30:17 -08001291protected:
1292 const char* mText;
1293 int mBytesCount;
1294 int mCount;
1295};
1296
1297class DrawTextOnPathOp : public DrawSomeTextOp {
1298public:
1299 DrawTextOnPathOp(const char* text, int bytesCount, int count,
Chris Craikd218a922014-01-02 17:13:34 -08001300 const SkPath* path, float hOffset, float vOffset, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001301 : DrawSomeTextOp(text, bytesCount, count, paint),
1302 mPath(path), mHOffset(hOffset), mVOffset(vOffset) {
1303 /* TODO: inherit from DrawBounded and init mLocalBounds */
1304 }
1305
Andreas Gampe64bb4132014-11-22 00:35:09 +00001306 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Tom Hudson107843d2014-09-08 11:26:26 -04001307 renderer.drawTextOnPath(mText, mBytesCount, mCount, mPath,
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -04001308 mHOffset, mVOffset, mPaint);
Chris Craik2af46352012-11-26 18:30:17 -08001309 }
1310
1311 virtual const char* name() { return "DrawTextOnPath"; }
1312
1313private:
Chris Craikd218a922014-01-02 17:13:34 -08001314 const SkPath* mPath;
Chris Craik2af46352012-11-26 18:30:17 -08001315 float mHOffset;
1316 float mVOffset;
1317};
1318
1319class DrawPosTextOp : public DrawSomeTextOp {
1320public:
1321 DrawPosTextOp(const char* text, int bytesCount, int count,
Chris Craikd218a922014-01-02 17:13:34 -08001322 const float* positions, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001323 : DrawSomeTextOp(text, bytesCount, count, paint), mPositions(positions) {
1324 /* TODO: inherit from DrawBounded and init mLocalBounds */
1325 }
1326
Andreas Gampe64bb4132014-11-22 00:35:09 +00001327 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Tom Hudson107843d2014-09-08 11:26:26 -04001328 renderer.drawPosText(mText, mBytesCount, mCount, mPositions, mPaint);
Chris Craik2af46352012-11-26 18:30:17 -08001329 }
1330
1331 virtual const char* name() { return "DrawPosText"; }
1332
1333private:
1334 const float* mPositions;
1335};
1336
Chris Craik947eabf2014-08-19 10:21:12 -07001337class DrawTextOp : public DrawStrokableOp {
Chris Craik2af46352012-11-26 18:30:17 -08001338public:
1339 DrawTextOp(const char* text, int bytesCount, int count, float x, float y,
Chris Craikd218a922014-01-02 17:13:34 -08001340 const float* positions, const SkPaint* paint, float totalAdvance, const Rect& bounds)
Chris Craik947eabf2014-08-19 10:21:12 -07001341 : DrawStrokableOp(bounds, paint), mText(text), mBytesCount(bytesCount), mCount(count),
Chris Craik41541822013-05-03 16:35:54 -07001342 mX(x), mY(y), mPositions(positions), mTotalAdvance(totalAdvance) {
Chris Craik59744b72014-07-01 17:56:52 -07001343 mPrecacheTransform = SkMatrix::InvalidMatrix();
Chris Craik2af46352012-11-26 18:30:17 -08001344 }
1345
Chris Craikc1c5f082013-09-11 16:23:37 -07001346 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
1347 const DeferredDisplayState& state) {
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -04001348 FontRenderer& fontRenderer = renderer.getCaches().fontRenderer->getFontRenderer(mPaint);
Chris Craik59744b72014-07-01 17:56:52 -07001349 SkMatrix transform;
1350 renderer.findBestFontTransform(state.mMatrix, &transform);
Romain Guybd3055f2013-03-13 16:14:47 -07001351 if (mPrecacheTransform != transform) {
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -04001352 fontRenderer.precache(mPaint, mText, mCount, transform);
Romain Guybd3055f2013-03-13 16:14:47 -07001353 mPrecacheTransform = transform;
1354 }
Chris Craik98d608d2014-07-17 12:25:11 -07001355 deferInfo.batchId = mPaint->getColor() == SK_ColorBLACK ?
Chris Craik527a3aa2013-03-04 10:19:31 -08001356 DeferredDisplayList::kOpBatch_Text :
1357 DeferredDisplayList::kOpBatch_ColorText;
1358
Kévin PETIT73fc5582014-02-13 11:03:40 +00001359 deferInfo.mergeId = reinterpret_cast<mergeid_t>(mPaint->getColor());
Chris Craik527a3aa2013-03-04 10:19:31 -08001360
1361 // don't merge decorated text - the decorations won't draw in order
Chris Craik98d608d2014-07-17 12:25:11 -07001362 bool hasDecorations = mPaint->getFlags()
1363 & (SkPaint::kUnderlineText_Flag | SkPaint::kStrikeThruText_Flag);
1364
1365 deferInfo.mergeable = state.mMatrix.isPureTranslate()
1366 && !hasDecorations
1367 && OpenGLRenderer::getXfermodeDirect(mPaint) == SkXfermode::kSrcOver_Mode;
Romain Guy0f6675332013-03-01 14:31:04 -08001368 }
1369
Andreas Gampe64bb4132014-11-22 00:35:09 +00001370 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Romain Guy9b5a1a22013-08-09 14:06:29 -07001371 Rect bounds;
John Reck3b202512014-06-23 13:13:08 -07001372 getLocalBounds(bounds);
Tom Hudson107843d2014-09-08 11:26:26 -04001373 renderer.drawText(mText, mBytesCount, mCount, mX, mY,
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -04001374 mPositions, mPaint, mTotalAdvance, bounds);
Chris Craik2af46352012-11-26 18:30:17 -08001375 }
1376
Andreas Gampe64bb4132014-11-22 00:35:09 +00001377 virtual void multiDraw(OpenGLRenderer& renderer, Rect& dirty,
1378 const Vector<OpStatePair>& ops, const Rect& bounds) {
Chris Craik527a3aa2013-03-04 10:19:31 -08001379 for (unsigned int i = 0; i < ops.size(); i++) {
Chris Craikc1c5f082013-09-11 16:23:37 -07001380 const DeferredDisplayState& state = *(ops[i].state);
Chris Craik527a3aa2013-03-04 10:19:31 -08001381 DrawOpMode drawOpMode = (i == ops.size() - 1) ? kDrawOpMode_Flush : kDrawOpMode_Defer;
Chris Craikc1c5f082013-09-11 16:23:37 -07001382 renderer.restoreDisplayState(state, true); // restore all but the clip
Chris Craik527a3aa2013-03-04 10:19:31 -08001383
Chris Craikc1c5f082013-09-11 16:23:37 -07001384 DrawTextOp& op = *((DrawTextOp*)ops[i].op);
Romain Guy9b5a1a22013-08-09 14:06:29 -07001385 // quickReject() will not occure in drawText() so we can use mLocalBounds
1386 // directly, we do not need to account for shadow by calling getLocalBounds()
Tom Hudson107843d2014-09-08 11:26:26 -04001387 renderer.drawText(op.mText, op.mBytesCount, op.mCount, op.mX, op.mY,
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -04001388 op.mPositions, op.mPaint, op.mTotalAdvance, op.mLocalBounds,
Chris Craik41541822013-05-03 16:35:54 -07001389 drawOpMode);
Chris Craik527a3aa2013-03-04 10:19:31 -08001390 }
Chris Craik527a3aa2013-03-04 10:19:31 -08001391 }
1392
Andreas Gampe64bb4132014-11-22 00:35:09 +00001393 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001394 OP_LOG("Draw Text of count %d, bytes %d", mCount, mBytesCount);
1395 }
1396
1397 virtual const char* name() { return "DrawText"; }
1398
1399private:
1400 const char* mText;
1401 int mBytesCount;
1402 int mCount;
1403 float mX;
1404 float mY;
1405 const float* mPositions;
Chris Craik41541822013-05-03 16:35:54 -07001406 float mTotalAdvance;
Chris Craik59744b72014-07-01 17:56:52 -07001407 SkMatrix mPrecacheTransform;
Chris Craik2af46352012-11-26 18:30:17 -08001408};
1409
1410///////////////////////////////////////////////////////////////////////////////
1411// SPECIAL DRAW OPERATIONS
1412///////////////////////////////////////////////////////////////////////////////
1413
1414class DrawFunctorOp : public DrawOp {
1415public:
1416 DrawFunctorOp(Functor* functor)
Chris Craikf57776b2013-10-25 18:30:17 -07001417 : DrawOp(NULL), mFunctor(functor) {}
Chris Craik2af46352012-11-26 18:30:17 -08001418
Tom Hudson107843d2014-09-08 11:26:26 -04001419 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001420 renderer.startMark("GL functor");
Tom Hudson107843d2014-09-08 11:26:26 -04001421 renderer.callDrawGLFunction(mFunctor, dirty);
Chris Craik2af46352012-11-26 18:30:17 -08001422 renderer.endMark();
Chris Craik2af46352012-11-26 18:30:17 -08001423 }
1424
Andreas Gampe64bb4132014-11-22 00:35:09 +00001425 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001426 OP_LOG("Draw Functor %p", mFunctor);
1427 }
1428
1429 virtual const char* name() { return "DrawFunctor"; }
1430
1431private:
1432 Functor* mFunctor;
1433};
1434
Chris Craika7090e02014-06-20 16:01:00 -07001435class DrawRenderNodeOp : public DrawBoundedOp {
1436 friend class RenderNode; // grant RenderNode access to info of child
Chris Craik8afd0f22014-08-21 17:41:57 -07001437 friend class DisplayListData; // grant DisplayListData access to info of child
Chris Craik2af46352012-11-26 18:30:17 -08001438public:
Chris Craika7090e02014-06-20 16:01:00 -07001439 DrawRenderNodeOp(RenderNode* renderNode, int flags, const mat4& transformFromParent)
1440 : DrawBoundedOp(0, 0, renderNode->getWidth(), renderNode->getHeight(), 0),
1441 mRenderNode(renderNode), mFlags(flags), mTransformFromParent(transformFromParent) {}
Chris Craikc3566d02013-02-04 16:16:33 -08001442
Andreas Gampe64bb4132014-11-22 00:35:09 +00001443 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
1444 bool useQuickReject) {
Chris Craik8afd0f22014-08-21 17:41:57 -07001445 if (mRenderNode->isRenderable() && !mSkipInOrderDraw) {
Chris Craika7090e02014-06-20 16:01:00 -07001446 mRenderNode->defer(deferStruct, level + 1);
Chris Craikc3566d02013-02-04 16:16:33 -08001447 }
Chris Craikc3566d02013-02-04 16:16:33 -08001448 }
Chris Craik8afd0f22014-08-21 17:41:57 -07001449
Andreas Gampe64bb4132014-11-22 00:35:09 +00001450 virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level,
1451 bool useQuickReject) {
Chris Craik8afd0f22014-08-21 17:41:57 -07001452 if (mRenderNode->isRenderable() && !mSkipInOrderDraw) {
Chris Craika7090e02014-06-20 16:01:00 -07001453 mRenderNode->replay(replayStruct, level + 1);
Chris Craikff785832013-03-08 13:12:16 -08001454 }
1455 }
Chris Craik2af46352012-11-26 18:30:17 -08001456
Andreas Gampe64bb4132014-11-22 00:35:09 +00001457 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik80d49022014-06-20 15:03:43 -07001458 LOG_ALWAYS_FATAL("should not be called, because replay() is overridden");
Chris Craika08f95c2013-03-15 17:24:33 -07001459 }
Chris Craikff785832013-03-08 13:12:16 -08001460
Chris Craikc5493fb2013-06-19 16:58:58 -07001461 virtual void output(int level, uint32_t logFlags) const {
Chris Craik8afd0f22014-08-21 17:41:57 -07001462 OP_LOG("Draw RenderNode %p %s, flags %#x", mRenderNode, mRenderNode->getName(), mFlags);
Chris Craika7090e02014-06-20 16:01:00 -07001463 if (mRenderNode && (logFlags & kOpLogFlag_Recurse)) {
1464 mRenderNode->output(level + 1);
Chris Craik2af46352012-11-26 18:30:17 -08001465 }
1466 }
1467
Chris Craika7090e02014-06-20 16:01:00 -07001468 virtual const char* name() { return "DrawRenderNode"; }
Chris Craik2af46352012-11-26 18:30:17 -08001469
Chris Craika7090e02014-06-20 16:01:00 -07001470 RenderNode* renderNode() { return mRenderNode; }
John Reck087bc0c2014-04-04 16:20:08 -07001471
Chris Craik2af46352012-11-26 18:30:17 -08001472private:
Chris Craika7090e02014-06-20 16:01:00 -07001473 RenderNode* mRenderNode;
Chris Craikf57776b2013-10-25 18:30:17 -07001474 const int mFlags;
1475
1476 ///////////////////////////
Chris Craika7090e02014-06-20 16:01:00 -07001477 // Properties below are used by RenderNode::computeOrderingImpl() and issueOperations()
Chris Craikf57776b2013-10-25 18:30:17 -07001478 ///////////////////////////
1479 /**
1480 * Records transform vs parent, used for computing total transform without rerunning DL contents
1481 */
1482 const mat4 mTransformFromParent;
1483
1484 /**
Chris Craika7090e02014-06-20 16:01:00 -07001485 * Holds the transformation between the projection surface ViewGroup and this RenderNode
Chris Craikb79a3e32014-03-11 12:20:17 -07001486 * drawing instance. Represents any translations / transformations done within the drawing of
1487 * the compositing ancestor ViewGroup's draw, before the draw of the View represented by this
1488 * DisplayList draw instance.
Chris Craikf57776b2013-10-25 18:30:17 -07001489 *
Chris Craika7090e02014-06-20 16:01:00 -07001490 * Note: doesn't include transformation within the RenderNode, or its properties.
Chris Craikf57776b2013-10-25 18:30:17 -07001491 */
Chris Craikf533e942014-01-14 22:35:37 -08001492 mat4 mTransformFromCompositingAncestor;
Chris Craikf57776b2013-10-25 18:30:17 -07001493 bool mSkipInOrderDraw;
1494};
1495
1496/**
Chris Craik024433f2014-03-26 13:19:14 -07001497 * Not a canvas operation, used only by 3d / z ordering logic in RenderNode::iterate()
Chris Craikf57776b2013-10-25 18:30:17 -07001498 */
1499class DrawShadowOp : public DrawOp {
1500public:
Chris Craik024433f2014-03-26 13:19:14 -07001501 DrawShadowOp(const mat4& transformXY, const mat4& transformZ,
Chris Craik74669862014-08-07 17:27:30 -07001502 float casterAlpha, const SkPath* casterOutline)
1503 : DrawOp(NULL)
1504 , mTransformXY(transformXY)
1505 , mTransformZ(transformZ)
1506 , mCasterAlpha(casterAlpha)
1507 , mCasterOutline(casterOutline) {
Chris Craik61317322014-05-21 13:03:52 -07001508 }
Chris Craikf57776b2013-10-25 18:30:17 -07001509
Andreas Gampe64bb4132014-11-22 00:35:09 +00001510 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
Chris Craik05f3d6e2014-06-02 16:27:04 -07001511 const DeferredDisplayState& state) {
1512 renderer.getCaches().tessellationCache.precacheShadows(&state.mMatrix,
Chris Craik74669862014-08-07 17:27:30 -07001513 renderer.getLocalClipBounds(), isCasterOpaque(), mCasterOutline,
Chris Craik05f3d6e2014-06-02 16:27:04 -07001514 &mTransformXY, &mTransformZ, renderer.getLightCenter(), renderer.getLightRadius());
1515 }
1516
Andreas Gampe64bb4132014-11-22 00:35:09 +00001517 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik05f3d6e2014-06-02 16:27:04 -07001518 TessellationCache::vertexBuffer_pair_t buffers;
Chris Craikc3e75f92014-08-27 15:34:52 -07001519 Matrix4 drawTransform(*(renderer.currentTransform()));
Chris Craik05f3d6e2014-06-02 16:27:04 -07001520 renderer.getCaches().tessellationCache.getShadowBuffers(&drawTransform,
Chris Craik74669862014-08-07 17:27:30 -07001521 renderer.getLocalClipBounds(), isCasterOpaque(), mCasterOutline,
Chris Craik05f3d6e2014-06-02 16:27:04 -07001522 &mTransformXY, &mTransformZ, renderer.getLightCenter(), renderer.getLightRadius(),
1523 buffers);
1524
Tom Hudson107843d2014-09-08 11:26:26 -04001525 renderer.drawShadow(mCasterAlpha, buffers.first, buffers.second);
Chris Craikf57776b2013-10-25 18:30:17 -07001526 }
1527
Andreas Gampe64bb4132014-11-22 00:35:09 +00001528 virtual void output(int level, uint32_t logFlags) const {
Chris Craik61317322014-05-21 13:03:52 -07001529 OP_LOGS("DrawShadow");
Chris Craikf57776b2013-10-25 18:30:17 -07001530 }
1531
1532 virtual const char* name() { return "DrawShadow"; }
1533
1534private:
Chris Craikaf4d04c2014-07-29 12:50:14 -07001535 bool isCasterOpaque() { return mCasterAlpha >= 1.0f; }
Chris Craik05f3d6e2014-06-02 16:27:04 -07001536
Chris Craikb79a3e32014-03-11 12:20:17 -07001537 const mat4 mTransformXY;
1538 const mat4 mTransformZ;
Chris Craik024433f2014-03-26 13:19:14 -07001539 const float mCasterAlpha;
Chris Craik74669862014-08-07 17:27:30 -07001540 const SkPath* mCasterOutline;
Chris Craik2af46352012-11-26 18:30:17 -08001541};
1542
1543class DrawLayerOp : public DrawOp {
1544public:
Chris Craika08f95c2013-03-15 17:24:33 -07001545 DrawLayerOp(Layer* layer, float x, float y)
Chris Craikf57776b2013-10-25 18:30:17 -07001546 : DrawOp(NULL), mLayer(layer), mX(x), mY(y) {}
Chris Craik2af46352012-11-26 18:30:17 -08001547
Andreas Gampe64bb4132014-11-22 00:35:09 +00001548 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Tom Hudson107843d2014-09-08 11:26:26 -04001549 renderer.drawLayer(mLayer, mX, mY);
Chris Craik2af46352012-11-26 18:30:17 -08001550 }
1551
Andreas Gampe64bb4132014-11-22 00:35:09 +00001552 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001553 OP_LOG("Draw Layer %p at %f %f", mLayer, mX, mY);
1554 }
1555
1556 virtual const char* name() { return "DrawLayer"; }
1557
1558private:
1559 Layer* mLayer;
1560 float mX;
1561 float mY;
1562};
1563
1564}; // namespace uirenderer
1565}; // namespace android
1566
1567#endif // ANDROID_HWUI_DISPLAY_OPERATION_H