blob: e42a9e424d2a34591d9cf201be456bcbc5a174fb [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"
37
Chris Craik2af46352012-11-26 18:30:17 -080038// Use OP_LOG for logging with arglist, OP_LOGS if just printing char*
Chris Craik28ce94a2013-05-31 11:38:03 -070039#define OP_LOGS(s) OP_LOG("%s", (s))
Chris Craik3dc553b2013-02-04 12:45:13 -080040#define OP_LOG(s, ...) ALOGD( "%*s" s, level * 2, "", __VA_ARGS__ )
Chris Craik2af46352012-11-26 18:30:17 -080041
Chris Craik2af46352012-11-26 18:30:17 -080042namespace android {
43namespace uirenderer {
44
45/**
46 * Structure for storing canvas operations when they are recorded into a DisplayList, so that they
47 * may be replayed to an OpenGLRenderer.
48 *
49 * To avoid individual memory allocations, DisplayListOps may only be allocated into a
50 * LinearAllocator's managed memory buffers. Each pointer held by a DisplayListOp is either a
51 * pointer into memory also allocated in the LinearAllocator (mostly for text and float buffers) or
52 * references a externally refcounted object (Sk... and Skia... objects). ~DisplayListOp() is
53 * never called as LinearAllocators are simply discarded, so no memory management should be done in
54 * this class.
55 */
56class DisplayListOp {
57public:
58 // These objects should always be allocated with a LinearAllocator, and never destroyed/deleted.
59 // standard new() intentionally not implemented, and delete/deconstructor should never be used.
Chris Craik51d6a3d2014-12-22 17:16:56 -080060 virtual ~DisplayListOp() { LOG_ALWAYS_FATAL("Destructor not supported"); }
61 static void operator delete(void* ptr) { LOG_ALWAYS_FATAL("delete not supported"); }
62 static void* operator new(size_t size) = delete; /** PURPOSELY OMITTED **/
Chris Craik2af46352012-11-26 18:30:17 -080063 static void* operator new(size_t size, LinearAllocator& allocator) {
64 return allocator.alloc(size);
65 }
66
67 enum OpLogFlag {
68 kOpLogFlag_Recurse = 0x1,
69 kOpLogFlag_JSON = 0x2 // TODO: add?
70 };
71
Chet Haasedd671592013-04-19 14:54:34 -070072 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
73 bool useQuickReject) = 0;
Chris Craikc3566d02013-02-04 16:16:33 -080074
Chet Haasedd671592013-04-19 14:54:34 -070075 virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level,
76 bool useQuickReject) = 0;
Chris Craikff785832013-03-08 13:12:16 -080077
Chris Craikc5493fb2013-06-19 16:58:58 -070078 virtual void output(int level, uint32_t logFlags = 0) const = 0;
Chris Craik2af46352012-11-26 18:30:17 -080079
80 // NOTE: it would be nice to declare constants and overriding the implementation in each op to
81 // point at the constants, but that seems to require a .cpp file
82 virtual const char* name() = 0;
83};
84
85class StateOp : public DisplayListOp {
86public:
Andreas Gampe64bb4132014-11-22 00:35:09 +000087 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
88 bool useQuickReject) {
Chris Craikff785832013-03-08 13:12:16 -080089 // default behavior only affects immediate, deferrable state, issue directly to renderer
90 applyState(deferStruct.mRenderer, saveCount);
91 }
92
Chris Craikc3566d02013-02-04 16:16:33 -080093 /**
94 * State operations are applied directly to the renderer, but can cause the deferred drawing op
95 * list to flush
96 */
Andreas Gampe64bb4132014-11-22 00:35:09 +000097 virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level,
98 bool useQuickReject) {
Chris Craikff785832013-03-08 13:12:16 -080099 applyState(replayStruct.mRenderer, saveCount);
Chris Craikc3566d02013-02-04 16:16:33 -0800100 }
101
Chris Craik7273daa2013-03-28 11:25:24 -0700102 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const = 0;
Chris Craik2af46352012-11-26 18:30:17 -0800103};
104
105class DrawOp : public DisplayListOp {
Chris Craik527a3aa2013-03-04 10:19:31 -0800106friend class MergingDrawBatch;
Chris Craik2af46352012-11-26 18:30:17 -0800107public:
Chris Craikd218a922014-01-02 17:13:34 -0800108 DrawOp(const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -0800109 : mPaint(paint), mQuickRejected(false) {}
110
Andreas Gampe64bb4132014-11-22 00:35:09 +0000111 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
Chet Haasedd671592013-04-19 14:54:34 -0700112 bool useQuickReject) {
113 if (mQuickRejected && CC_LIKELY(useQuickReject)) {
Chris Craikff785832013-03-08 13:12:16 -0800114 return;
Chris Craikc3566d02013-02-04 16:16:33 -0800115 }
116
Chris Craikff785832013-03-08 13:12:16 -0800117 deferStruct.mDeferredList.addDrawOp(deferStruct.mRenderer, this);
Chris Craikc3566d02013-02-04 16:16:33 -0800118 }
119
Andreas Gampe64bb4132014-11-22 00:35:09 +0000120 virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level,
Chet Haasedd671592013-04-19 14:54:34 -0700121 bool useQuickReject) {
122 if (mQuickRejected && CC_LIKELY(useQuickReject)) {
Chris Craikff785832013-03-08 13:12:16 -0800123 return;
124 }
125
Tom Hudson107843d2014-09-08 11:26:26 -0400126 applyDraw(replayStruct.mRenderer, replayStruct.mDirty);
Chris Craikff785832013-03-08 13:12:16 -0800127 }
128
Tom Hudson107843d2014-09-08 11:26:26 -0400129 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) = 0;
Chris Craik2af46352012-11-26 18:30:17 -0800130
Chris Craik527a3aa2013-03-04 10:19:31 -0800131 /**
132 * Draw multiple instances of an operation, must be overidden for operations that merge
133 *
134 * Currently guarantees certain similarities between ops (see MergingDrawBatch::canMergeWith),
135 * and pure translation transformations. Other guarantees of similarity should be enforced by
136 * reducing which operations are tagged as mergeable.
137 */
Tom Hudson107843d2014-09-08 11:26:26 -0400138 virtual void multiDraw(OpenGLRenderer& renderer, Rect& dirty,
Andreas Gampe64bb4132014-11-22 00:35:09 +0000139 const Vector<OpStatePair>& ops, const Rect& bounds) {
Chris Craik527a3aa2013-03-04 10:19:31 -0800140 for (unsigned int i = 0; i < ops.size(); i++) {
Chris Craikc1c5f082013-09-11 16:23:37 -0700141 renderer.restoreDisplayState(*(ops[i].state), true);
Tom Hudson107843d2014-09-08 11:26:26 -0400142 ops[i].op->applyDraw(renderer, dirty);
Chris Craik527a3aa2013-03-04 10:19:31 -0800143 }
Chris Craik527a3aa2013-03-04 10:19:31 -0800144 }
145
Chris Craik28ce94a2013-05-31 11:38:03 -0700146 /**
Chris Craik527a3aa2013-03-04 10:19:31 -0800147 * When this method is invoked the state field is initialized to have the
148 * final rendering state. We can thus use it to process data as it will be
149 * used at draw time.
150 *
151 * Additionally, this method allows subclasses to provide defer-time preferences for batching
152 * and merging.
153 *
Chris Craik28ce94a2013-05-31 11:38:03 -0700154 * if a subclass can set deferInfo.mergeable to true, it should implement multiDraw()
Chris Craik527a3aa2013-03-04 10:19:31 -0800155 */
Andreas Gampe64bb4132014-11-22 00:35:09 +0000156 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
157 const DeferredDisplayState& state) {}
Romain Guy0f6675332013-03-01 14:31:04 -0800158
Chris Craik5e49b302013-07-30 19:05:20 -0700159 /**
160 * Query the conservative, local bounds (unmapped) bounds of the op.
161 *
162 * returns true if bounds exist
163 */
Andreas Gampe64bb4132014-11-22 00:35:09 +0000164 virtual bool getLocalBounds(Rect& localBounds) {
Chris Craikc1c5f082013-09-11 16:23:37 -0700165 return false;
166 }
Chris Craik2af46352012-11-26 18:30:17 -0800167
168 // TODO: better refine localbounds usage
169 void setQuickRejected(bool quickRejected) { mQuickRejected = quickRejected; }
170 bool getQuickRejected() { return mQuickRejected; }
171
Chris Craikc1c5f082013-09-11 16:23:37 -0700172 inline int getPaintAlpha() const {
Chris Craik527a3aa2013-03-04 10:19:31 -0800173 return OpenGLRenderer::getAlphaDirect(mPaint);
Chris Craikc3566d02013-02-04 16:16:33 -0800174 }
175
Derek Sollenbergerc29a0a42014-03-31 13:52:39 -0400176 virtual bool hasTextShadow() const {
177 return false;
178 }
179
Chris Craik527a3aa2013-03-04 10:19:31 -0800180 inline float strokeWidthOutset() {
Chris Craikf0a59072013-11-19 18:00:46 -0800181 // since anything AA stroke with less than 1.0 pixel width is drawn with an alpha-reduced
182 // 1.0 stroke, treat 1.0 as minimum.
183
184 // TODO: it would be nice if this could take scale into account, but scale isn't stable
185 // since higher levels of the view hierarchy can change scale out from underneath it.
186 return fmaxf(mPaint->getStrokeWidth(), 1) * 0.5f;
Chris Craike7c69c62013-04-03 09:55:48 -0700187 }
Chris Craikc3566d02013-02-04 16:16:33 -0800188
Chris Craik2af46352012-11-26 18:30:17 -0800189protected:
Chris Craik28ce94a2013-05-31 11:38:03 -0700190 // Helper method for determining op opaqueness. Assumes op fills its bounds in local
191 // coordinates, and that paint's alpha is used
Chris Craikc1c5f082013-09-11 16:23:37 -0700192 inline bool isOpaqueOverBounds(const DeferredDisplayState& state) {
Chris Craik28ce94a2013-05-31 11:38:03 -0700193 // ensure that local bounds cover mapped bounds
194 if (!state.mMatrix.isSimple()) return false;
195
Chris Craik2262abb2014-08-18 19:55:36 -0700196 if (state.mRoundRectClipState) return false;
197
Chris Craik28ce94a2013-05-31 11:38:03 -0700198 // check state/paint for transparency
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400199 if (mPaint) {
Chris Craikc5b5f052014-10-01 16:40:16 -0700200 if (mPaint->getAlpha() != 0xFF) {
201 return false;
202 }
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400203 if (mPaint->getShader() && !mPaint->getShader()->isOpaque()) {
204 return false;
205 }
Chris Craikc5b5f052014-10-01 16:40:16 -0700206 if (Renderer::isBlendedColorFilter(mPaint->getColorFilter())) {
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400207 return false;
208 }
209 }
210
211 if (state.mAlpha != 1.0f) return false;
Chris Craik28ce94a2013-05-31 11:38:03 -0700212
213 SkXfermode::Mode mode = OpenGLRenderer::getXfermodeDirect(mPaint);
214 return (mode == SkXfermode::kSrcOver_Mode ||
215 mode == SkXfermode::kSrc_Mode);
216
217 }
218
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -0400219 const SkPaint* mPaint;
Chris Craik2af46352012-11-26 18:30:17 -0800220 bool mQuickRejected;
221};
222
223class DrawBoundedOp : public DrawOp {
224public:
Chris Craikd218a922014-01-02 17:13:34 -0800225 DrawBoundedOp(float left, float top, float right, float bottom, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -0800226 : DrawOp(paint), mLocalBounds(left, top, right, bottom) {}
227
Chris Craikd218a922014-01-02 17:13:34 -0800228 DrawBoundedOp(const Rect& localBounds, const SkPaint* paint)
Chris Craik41541822013-05-03 16:35:54 -0700229 : DrawOp(paint), mLocalBounds(localBounds) {}
230
Chris Craik5d116762013-02-19 17:49:31 -0800231 // Calculates bounds as smallest rect encompassing all points
232 // NOTE: requires at least 1 vertex, and doesn't account for stroke size (should be handled in
233 // subclass' constructor)
Chris Craikd218a922014-01-02 17:13:34 -0800234 DrawBoundedOp(const float* points, int count, const SkPaint* paint)
Chris Craik5d116762013-02-19 17:49:31 -0800235 : DrawOp(paint), mLocalBounds(points[0], points[1], points[0], points[1]) {
236 for (int i = 2; i < count; i += 2) {
237 mLocalBounds.left = fminf(mLocalBounds.left, points[i]);
238 mLocalBounds.right = fmaxf(mLocalBounds.right, points[i]);
239 mLocalBounds.top = fminf(mLocalBounds.top, points[i + 1]);
240 mLocalBounds.bottom = fmaxf(mLocalBounds.bottom, points[i + 1]);
241 }
242 }
243
244 // default empty constructor for bounds, to be overridden in child constructor body
Chris Craikd218a922014-01-02 17:13:34 -0800245 DrawBoundedOp(const SkPaint* paint): DrawOp(paint) { }
Chris Craik2af46352012-11-26 18:30:17 -0800246
John Reckca1b3b82014-06-27 07:21:36 -0700247 virtual bool getLocalBounds(Rect& localBounds) {
Chris Craik2af46352012-11-26 18:30:17 -0800248 localBounds.set(mLocalBounds);
Derek Sollenbergerc29a0a42014-03-31 13:52:39 -0400249 OpenGLRenderer::TextShadow textShadow;
250 if (OpenGLRenderer::getTextShadow(mPaint, &textShadow)) {
Romain Guy9b5a1a22013-08-09 14:06:29 -0700251 Rect shadow(mLocalBounds);
Derek Sollenbergerc29a0a42014-03-31 13:52:39 -0400252 shadow.translate(textShadow.dx, textShadow.dx);
253 shadow.outset(textShadow.radius);
Romain Guy9b5a1a22013-08-09 14:06:29 -0700254 localBounds.unionWith(shadow);
255 }
Chris Craik2af46352012-11-26 18:30:17 -0800256 return true;
257 }
258
259protected:
260 Rect mLocalBounds; // displayed area in LOCAL coord. doesn't incorporate stroke, so check paint
261};
262
263///////////////////////////////////////////////////////////////////////////////
264// STATE OPERATIONS - these may affect the state of the canvas/renderer, but do
265// not directly draw or alter output
266///////////////////////////////////////////////////////////////////////////////
267
268class SaveOp : public StateOp {
269public:
270 SaveOp(int flags)
271 : mFlags(flags) {}
272
Andreas Gampe64bb4132014-11-22 00:35:09 +0000273 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
274 bool useQuickReject) {
Chris Craikff785832013-03-08 13:12:16 -0800275 int newSaveCount = deferStruct.mRenderer.save(mFlags);
276 deferStruct.mDeferredList.addSave(deferStruct.mRenderer, this, newSaveCount);
277 }
278
Andreas Gampe64bb4132014-11-22 00:35:09 +0000279 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800280 renderer.save(mFlags);
281 }
282
Andreas Gampe64bb4132014-11-22 00:35:09 +0000283 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800284 OP_LOG("Save flags %x", mFlags);
285 }
286
287 virtual const char* name() { return "Save"; }
288
Chris Craikff785832013-03-08 13:12:16 -0800289 int getFlags() const { return mFlags; }
Chris Craik2af46352012-11-26 18:30:17 -0800290private:
291 int mFlags;
292};
293
294class RestoreToCountOp : public StateOp {
295public:
296 RestoreToCountOp(int count)
297 : mCount(count) {}
298
Andreas Gampe64bb4132014-11-22 00:35:09 +0000299 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
300 bool useQuickReject) {
Chris Craik7273daa2013-03-28 11:25:24 -0700301 deferStruct.mDeferredList.addRestoreToCount(deferStruct.mRenderer,
302 this, saveCount + mCount);
Chris Craikff785832013-03-08 13:12:16 -0800303 deferStruct.mRenderer.restoreToCount(saveCount + mCount);
Chris Craik2af46352012-11-26 18:30:17 -0800304 }
305
Chris Craik7273daa2013-03-28 11:25:24 -0700306 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craikff785832013-03-08 13:12:16 -0800307 renderer.restoreToCount(saveCount + mCount);
308 }
309
Andreas Gampe64bb4132014-11-22 00:35:09 +0000310 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800311 OP_LOG("Restore to count %d", mCount);
312 }
313
314 virtual const char* name() { return "RestoreToCount"; }
315
316private:
317 int mCount;
318};
319
320class SaveLayerOp : public StateOp {
321public:
Derek Sollenbergerd44fbe52014-02-05 16:47:00 -0500322 SaveLayerOp(float left, float top, float right, float bottom, int alpha, int flags)
Chris Craik3f0854292014-04-15 16:18:08 -0700323 : mArea(left, top, right, bottom)
324 , mPaint(&mCachedPaint)
325 , mFlags(flags)
326 , mConvexMask(NULL) {
Derek Sollenbergerd44fbe52014-02-05 16:47:00 -0500327 mCachedPaint.setAlpha(alpha);
328 }
329
330 SaveLayerOp(float left, float top, float right, float bottom, const SkPaint* paint, int flags)
Chris Craik3f0854292014-04-15 16:18:08 -0700331 : mArea(left, top, right, bottom)
332 , mPaint(paint)
333 , mFlags(flags)
334 , mConvexMask(NULL)
335 {}
Chris Craikff785832013-03-08 13:12:16 -0800336
Andreas Gampe64bb4132014-11-22 00:35:09 +0000337 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
338 bool useQuickReject) {
Chris Craikff785832013-03-08 13:12:16 -0800339 // NOTE: don't bother with actual saveLayer, instead issuing it at flush time
Chris Craikd90144d2013-03-19 15:03:48 -0700340 int newSaveCount = deferStruct.mRenderer.getSaveCount();
Chris Craikff785832013-03-08 13:12:16 -0800341 deferStruct.mDeferredList.addSaveLayer(deferStruct.mRenderer, this, newSaveCount);
Chris Craikd90144d2013-03-19 15:03:48 -0700342
343 // NOTE: don't issue full saveLayer, since that has side effects/is costly. instead just
344 // setup the snapshot for deferral, and re-issue the op at flush time
345 deferStruct.mRenderer.saveLayerDeferred(mArea.left, mArea.top, mArea.right, mArea.bottom,
Derek Sollenbergerd44fbe52014-02-05 16:47:00 -0500346 mPaint, mFlags);
Chris Craikff785832013-03-08 13:12:16 -0800347 }
Chris Craik2af46352012-11-26 18:30:17 -0800348
Andreas Gampe64bb4132014-11-22 00:35:09 +0000349 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik3f0854292014-04-15 16:18:08 -0700350 renderer.saveLayer(mArea.left, mArea.top, mArea.right, mArea.bottom,
351 mPaint, mFlags, mConvexMask);
Chris Craik2af46352012-11-26 18:30:17 -0800352 }
353
Andreas Gampe64bb4132014-11-22 00:35:09 +0000354 virtual void output(int level, uint32_t logFlags) const {
Chris Craikff785832013-03-08 13:12:16 -0800355 OP_LOG("SaveLayer%s of area " RECT_STRING,
356 (isSaveLayerAlpha() ? "Alpha" : ""),RECT_ARGS(mArea));
Chris Craik2af46352012-11-26 18:30:17 -0800357 }
358
Chris Craikff785832013-03-08 13:12:16 -0800359 virtual const char* name() { return isSaveLayerAlpha() ? "SaveLayerAlpha" : "SaveLayer"; }
360
361 int getFlags() { return mFlags; }
Chris Craik2af46352012-11-26 18:30:17 -0800362
Chris Craik3f0854292014-04-15 16:18:08 -0700363 // Called to make SaveLayerOp clip to the provided mask when drawing back/restored
364 void setMask(const SkPath* convexMask) {
365 mConvexMask = convexMask;
366 }
367
Chris Craik2af46352012-11-26 18:30:17 -0800368private:
Derek Sollenbergerd44fbe52014-02-05 16:47:00 -0500369 bool isSaveLayerAlpha() const {
370 SkXfermode::Mode mode = OpenGLRenderer::getXfermodeDirect(mPaint);
371 int alpha = OpenGLRenderer::getAlphaDirect(mPaint);
372 return alpha < 255 && mode == SkXfermode::kSrcOver_Mode;
Chris Craik2af46352012-11-26 18:30:17 -0800373 }
374
Chris Craik2af46352012-11-26 18:30:17 -0800375 Rect mArea;
Derek Sollenbergerd44fbe52014-02-05 16:47:00 -0500376 const SkPaint* mPaint;
377 SkPaint mCachedPaint;
Chris Craik2af46352012-11-26 18:30:17 -0800378 int mFlags;
Chris Craik3f0854292014-04-15 16:18:08 -0700379
380 // Convex path, points at data in RenderNode, valid for the duration of the frame only
381 // Only used for masking the SaveLayer which wraps projected RenderNodes
382 const SkPath* mConvexMask;
Chris Craik2af46352012-11-26 18:30:17 -0800383};
384
385class TranslateOp : public StateOp {
386public:
387 TranslateOp(float dx, float dy)
388 : mDx(dx), mDy(dy) {}
389
Andreas Gampe64bb4132014-11-22 00:35:09 +0000390 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800391 renderer.translate(mDx, mDy);
392 }
393
Andreas Gampe64bb4132014-11-22 00:35:09 +0000394 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800395 OP_LOG("Translate by %f %f", mDx, mDy);
396 }
397
398 virtual const char* name() { return "Translate"; }
399
400private:
401 float mDx;
402 float mDy;
403};
404
405class RotateOp : public StateOp {
406public:
407 RotateOp(float degrees)
408 : mDegrees(degrees) {}
409
Andreas Gampe64bb4132014-11-22 00:35:09 +0000410 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800411 renderer.rotate(mDegrees);
412 }
413
Andreas Gampe64bb4132014-11-22 00:35:09 +0000414 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800415 OP_LOG("Rotate by %f degrees", mDegrees);
416 }
417
418 virtual const char* name() { return "Rotate"; }
419
420private:
421 float mDegrees;
422};
423
424class ScaleOp : public StateOp {
425public:
426 ScaleOp(float sx, float sy)
427 : mSx(sx), mSy(sy) {}
428
Andreas Gampe64bb4132014-11-22 00:35:09 +0000429 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800430 renderer.scale(mSx, mSy);
431 }
432
Andreas Gampe64bb4132014-11-22 00:35:09 +0000433 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800434 OP_LOG("Scale by %f %f", mSx, mSy);
435 }
436
437 virtual const char* name() { return "Scale"; }
438
439private:
440 float mSx;
441 float mSy;
442};
443
444class SkewOp : public StateOp {
445public:
446 SkewOp(float sx, float sy)
447 : mSx(sx), mSy(sy) {}
448
Andreas Gampe64bb4132014-11-22 00:35:09 +0000449 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800450 renderer.skew(mSx, mSy);
451 }
452
Andreas Gampe64bb4132014-11-22 00:35:09 +0000453 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800454 OP_LOG("Skew by %f %f", mSx, mSy);
455 }
456
457 virtual const char* name() { return "Skew"; }
458
459private:
460 float mSx;
461 float mSy;
462};
463
464class SetMatrixOp : public StateOp {
465public:
Derek Sollenberger13908822013-12-10 12:28:58 -0500466 SetMatrixOp(const SkMatrix& matrix)
Chris Craik2af46352012-11-26 18:30:17 -0800467 : mMatrix(matrix) {}
468
Andreas Gampe64bb4132014-11-22 00:35:09 +0000469 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800470 renderer.setMatrix(mMatrix);
471 }
472
Andreas Gampe64bb4132014-11-22 00:35:09 +0000473 virtual void output(int level, uint32_t logFlags) const {
Derek Sollenberger13908822013-12-10 12:28:58 -0500474 if (mMatrix.isIdentity()) {
Romain Guy4e7b7722013-07-16 13:47:01 -0700475 OP_LOGS("SetMatrix (reset)");
Derek Sollenberger13908822013-12-10 12:28:58 -0500476 } else {
477 OP_LOG("SetMatrix " SK_MATRIX_STRING, SK_MATRIX_ARGS(&mMatrix));
Romain Guy4e7b7722013-07-16 13:47:01 -0700478 }
Chris Craik2af46352012-11-26 18:30:17 -0800479 }
480
481 virtual const char* name() { return "SetMatrix"; }
482
483private:
Derek Sollenberger13908822013-12-10 12:28:58 -0500484 const SkMatrix mMatrix;
Chris Craik2af46352012-11-26 18:30:17 -0800485};
486
487class ConcatMatrixOp : public StateOp {
488public:
Derek Sollenberger13908822013-12-10 12:28:58 -0500489 ConcatMatrixOp(const SkMatrix& matrix)
Chris Craik2af46352012-11-26 18:30:17 -0800490 : mMatrix(matrix) {}
491
Andreas Gampe64bb4132014-11-22 00:35:09 +0000492 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800493 renderer.concatMatrix(mMatrix);
494 }
495
Andreas Gampe64bb4132014-11-22 00:35:09 +0000496 virtual void output(int level, uint32_t logFlags) const {
Derek Sollenberger13908822013-12-10 12:28:58 -0500497 OP_LOG("ConcatMatrix " SK_MATRIX_STRING, SK_MATRIX_ARGS(&mMatrix));
Chris Craik2af46352012-11-26 18:30:17 -0800498 }
499
500 virtual const char* name() { return "ConcatMatrix"; }
501
502private:
Derek Sollenberger13908822013-12-10 12:28:58 -0500503 const SkMatrix mMatrix;
Chris Craik2af46352012-11-26 18:30:17 -0800504};
505
Chris Craikff785832013-03-08 13:12:16 -0800506class ClipOp : public StateOp {
507public:
508 ClipOp(SkRegion::Op op) : mOp(op) {}
509
Andreas Gampe64bb4132014-11-22 00:35:09 +0000510 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
511 bool useQuickReject) {
Chris Craikff785832013-03-08 13:12:16 -0800512 // NOTE: must defer op BEFORE applying state, since it may read clip
513 deferStruct.mDeferredList.addClip(deferStruct.mRenderer, this);
514
515 // TODO: Can we avoid applying complex clips at defer time?
516 applyState(deferStruct.mRenderer, saveCount);
517 }
518
519 bool canCauseComplexClip() {
520 return ((mOp != SkRegion::kIntersect_Op) && (mOp != SkRegion::kReplace_Op)) || !isRect();
521 }
522
523protected:
Chris Craikff785832013-03-08 13:12:16 -0800524 virtual bool isRect() { return false; }
525
526 SkRegion::Op mOp;
527};
528
529class ClipRectOp : public ClipOp {
Chris Craik2af46352012-11-26 18:30:17 -0800530public:
531 ClipRectOp(float left, float top, float right, float bottom, SkRegion::Op op)
Chris Craikff785832013-03-08 13:12:16 -0800532 : ClipOp(op), mArea(left, top, right, bottom) {}
Chris Craik2af46352012-11-26 18:30:17 -0800533
Andreas Gampe64bb4132014-11-22 00:35:09 +0000534 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800535 renderer.clipRect(mArea.left, mArea.top, mArea.right, mArea.bottom, mOp);
536 }
537
Andreas Gampe64bb4132014-11-22 00:35:09 +0000538 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800539 OP_LOG("ClipRect " RECT_STRING, RECT_ARGS(mArea));
540 }
541
542 virtual const char* name() { return "ClipRect"; }
543
Chris Craikff785832013-03-08 13:12:16 -0800544protected:
545 virtual bool isRect() { return true; }
Chris Craikb98a0162013-02-21 11:30:22 -0800546
Chris Craik2af46352012-11-26 18:30:17 -0800547private:
548 Rect mArea;
Chris Craik2af46352012-11-26 18:30:17 -0800549};
550
Chris Craikff785832013-03-08 13:12:16 -0800551class ClipPathOp : public ClipOp {
Chris Craik2af46352012-11-26 18:30:17 -0800552public:
Chris Craikd218a922014-01-02 17:13:34 -0800553 ClipPathOp(const SkPath* path, SkRegion::Op op)
Chris Craikff785832013-03-08 13:12:16 -0800554 : ClipOp(op), mPath(path) {}
Chris Craik2af46352012-11-26 18:30:17 -0800555
Andreas Gampe64bb4132014-11-22 00:35:09 +0000556 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800557 renderer.clipPath(mPath, mOp);
558 }
559
Andreas Gampe64bb4132014-11-22 00:35:09 +0000560 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800561 SkRect bounds = mPath->getBounds();
562 OP_LOG("ClipPath bounds " RECT_STRING,
563 bounds.left(), bounds.top(), bounds.right(), bounds.bottom());
564 }
565
566 virtual const char* name() { return "ClipPath"; }
567
568private:
Chris Craikd218a922014-01-02 17:13:34 -0800569 const SkPath* mPath;
Chris Craik2af46352012-11-26 18:30:17 -0800570};
571
Chris Craikff785832013-03-08 13:12:16 -0800572class ClipRegionOp : public ClipOp {
Chris Craik2af46352012-11-26 18:30:17 -0800573public:
Chris Craikd218a922014-01-02 17:13:34 -0800574 ClipRegionOp(const SkRegion* region, SkRegion::Op op)
Chris Craikff785832013-03-08 13:12:16 -0800575 : ClipOp(op), mRegion(region) {}
Chris Craik2af46352012-11-26 18:30:17 -0800576
Andreas Gampe64bb4132014-11-22 00:35:09 +0000577 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800578 renderer.clipRegion(mRegion, mOp);
579 }
580
Andreas Gampe64bb4132014-11-22 00:35:09 +0000581 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800582 SkIRect bounds = mRegion->getBounds();
583 OP_LOG("ClipRegion bounds %d %d %d %d",
584 bounds.left(), bounds.top(), bounds.right(), bounds.bottom());
585 }
586
587 virtual const char* name() { return "ClipRegion"; }
588
589private:
Chris Craikd218a922014-01-02 17:13:34 -0800590 const SkRegion* mRegion;
Chris Craik2af46352012-11-26 18:30:17 -0800591};
592
Chris Craik2af46352012-11-26 18:30:17 -0800593///////////////////////////////////////////////////////////////////////////////
594// DRAW OPERATIONS - these are operations that can draw to the canvas's device
595///////////////////////////////////////////////////////////////////////////////
596
597class DrawBitmapOp : public DrawBoundedOp {
598public:
Chris Craik79647502014-08-06 13:42:24 -0700599 DrawBitmapOp(const SkBitmap* bitmap, const SkPaint* paint)
600 : DrawBoundedOp(0, 0, bitmap->width(), bitmap->height(), paint)
601 , mBitmap(bitmap)
John Reckebd52612014-12-10 16:47:36 -0800602 , mEntryValid(false), mEntry(NULL) {
Romain Guy3b748a42013-04-17 18:54:38 -0700603 }
Chris Craik2af46352012-11-26 18:30:17 -0800604
Andreas Gampe64bb4132014-11-22 00:35:09 +0000605 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Tom Hudson107843d2014-09-08 11:26:26 -0400606 renderer.drawBitmap(mBitmap, mPaint);
Chris Craik2af46352012-11-26 18:30:17 -0800607 }
608
John Reckebd52612014-12-10 16:47:36 -0800609 AssetAtlas::Entry* getAtlasEntry(OpenGLRenderer& renderer) {
610 if (!mEntryValid) {
611 mEntryValid = true;
612 mEntry = renderer.renderState().assetAtlas().getEntry(mBitmap);
Romain Guy55b6f952013-06-27 15:27:09 -0700613 }
614 return mEntry;
615 }
616
Chris Craik527a3aa2013-03-04 10:19:31 -0800617#define SET_TEXTURE(ptr, posRect, offsetRect, texCoordsRect, xDim, yDim) \
618 TextureVertex::set(ptr++, posRect.xDim - offsetRect.left, posRect.yDim - offsetRect.top, \
619 texCoordsRect.xDim, texCoordsRect.yDim)
620
Romain Guy03c00b52013-06-20 18:30:28 -0700621 /**
622 * This multi-draw operation builds a mesh on the stack by generating a quad
623 * for each bitmap in the batch. This method is also responsible for dirtying
624 * the current layer, if any.
625 */
Andreas Gampe64bb4132014-11-22 00:35:09 +0000626 virtual void multiDraw(OpenGLRenderer& renderer, Rect& dirty,
Chris Craikc1c5f082013-09-11 16:23:37 -0700627 const Vector<OpStatePair>& ops, const Rect& bounds) {
628 const DeferredDisplayState& firstState = *(ops[0].state);
629 renderer.restoreDisplayState(firstState, true); // restore all but the clip
630
Chris Craik527a3aa2013-03-04 10:19:31 -0800631 TextureVertex vertices[6 * ops.size()];
632 TextureVertex* vertex = &vertices[0];
633
Romain Guy03c00b52013-06-20 18:30:28 -0700634 const bool hasLayer = renderer.hasLayer();
Chris Craik996fe652013-09-20 17:13:18 -0700635 bool pureTranslate = true;
Romain Guy2db5e992013-05-21 15:29:59 -0700636
Romain Guy3b748a42013-04-17 18:54:38 -0700637 // TODO: manually handle rect clip for bitmaps by adjusting texCoords per op,
638 // and allowing them to be merged in getBatchId()
Chris Craik527a3aa2013-03-04 10:19:31 -0800639 for (unsigned int i = 0; i < ops.size(); i++) {
Chris Craikc1c5f082013-09-11 16:23:37 -0700640 const DeferredDisplayState& state = *(ops[i].state);
641 const Rect& opBounds = state.mBounds;
Romain Guy2db5e992013-05-21 15:29:59 -0700642 // When we reach multiDraw(), the matrix can be either
643 // pureTranslate or simple (translate and/or scale).
644 // If the matrix is not pureTranslate, then we have a scale
Chris Craik996fe652013-09-20 17:13:18 -0700645 pureTranslate &= state.mMatrix.isPureTranslate();
Romain Guy3b748a42013-04-17 18:54:38 -0700646
647 Rect texCoords(0, 0, 1, 1);
John Reckebd52612014-12-10 16:47:36 -0800648 ((DrawBitmapOp*) ops[i].op)->uvMap(renderer, texCoords);
Romain Guy3b748a42013-04-17 18:54:38 -0700649
Chris Craik527a3aa2013-03-04 10:19:31 -0800650 SET_TEXTURE(vertex, opBounds, bounds, texCoords, left, top);
651 SET_TEXTURE(vertex, opBounds, bounds, texCoords, right, top);
652 SET_TEXTURE(vertex, opBounds, bounds, texCoords, left, bottom);
653
654 SET_TEXTURE(vertex, opBounds, bounds, texCoords, left, bottom);
655 SET_TEXTURE(vertex, opBounds, bounds, texCoords, right, top);
656 SET_TEXTURE(vertex, opBounds, bounds, texCoords, right, bottom);
Romain Guy03c00b52013-06-20 18:30:28 -0700657
658 if (hasLayer) {
Chris Craikc1c5f082013-09-11 16:23:37 -0700659 renderer.dirtyLayer(opBounds.left, opBounds.top, opBounds.right, opBounds.bottom);
Romain Guy03c00b52013-06-20 18:30:28 -0700660 }
Chris Craik527a3aa2013-03-04 10:19:31 -0800661 }
662
Tom Hudson107843d2014-09-08 11:26:26 -0400663 renderer.drawBitmaps(mBitmap, mEntry, ops.size(), &vertices[0],
Chris Craik996fe652013-09-20 17:13:18 -0700664 pureTranslate, bounds, mPaint);
Chris Craik527a3aa2013-03-04 10:19:31 -0800665 }
666
Andreas Gampe64bb4132014-11-22 00:35:09 +0000667 virtual void output(int level, uint32_t logFlags) const {
John Reckdad7d84c2014-12-09 12:33:26 -0800668 OP_LOG("Draw bitmap %p at %f %f%s", mBitmap, mLocalBounds.left, mLocalBounds.top,
669 mEntry ? " using AssetAtlas" : "");
Chris Craik2af46352012-11-26 18:30:17 -0800670 }
671
672 virtual const char* name() { return "DrawBitmap"; }
Chris Craik527a3aa2013-03-04 10:19:31 -0800673
Andreas Gampe64bb4132014-11-22 00:35:09 +0000674 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
Chris Craikc1c5f082013-09-11 16:23:37 -0700675 const DeferredDisplayState& state) {
Chris Craik28ce94a2013-05-31 11:38:03 -0700676 deferInfo.batchId = DeferredDisplayList::kOpBatch_Bitmap;
John Reckebd52612014-12-10 16:47:36 -0800677 deferInfo.mergeId = getAtlasEntry(renderer) ?
Chris Craikd965bc52013-09-16 14:47:13 -0700678 (mergeid_t) mEntry->getMergeId() : (mergeid_t) mBitmap;
Romain Guy2db5e992013-05-21 15:29:59 -0700679
Chris Craikd965bc52013-09-16 14:47:13 -0700680 // Don't merge non-simply transformed or neg scale ops, SET_TEXTURE doesn't handle rotation
Chris Craik28ce94a2013-05-31 11:38:03 -0700681 // Don't merge A8 bitmaps - the paint's color isn't compared by mergeId, or in
682 // MergingDrawBatch::canMergeWith()
683 // TODO: support clipped bitmaps by handling them in SET_TEXTURE
Chris Craikd965bc52013-09-16 14:47:13 -0700684 deferInfo.mergeable = state.mMatrix.isSimple() && state.mMatrix.positiveScale() &&
685 !state.mClipSideFlags &&
Chris Craik28ce94a2013-05-31 11:38:03 -0700686 OpenGLRenderer::getXfermodeDirect(mPaint) == SkXfermode::kSrcOver_Mode &&
Mike Reed1103b322014-07-08 12:36:44 -0400687 (mBitmap->colorType() != kAlpha_8_SkColorType);
Chris Craikc3566d02013-02-04 16:16:33 -0800688 }
Chris Craik2af46352012-11-26 18:30:17 -0800689
John Reckebd52612014-12-10 16:47:36 -0800690 void uvMap(OpenGLRenderer& renderer, Rect& texCoords) {
691 if (getAtlasEntry(renderer)) {
692 mEntry->uvMapper.map(texCoords);
693 }
694 }
695
Chris Craik527a3aa2013-03-04 10:19:31 -0800696 const SkBitmap* bitmap() { return mBitmap; }
Chris Craik2af46352012-11-26 18:30:17 -0800697protected:
Chris Craikd218a922014-01-02 17:13:34 -0800698 const SkBitmap* mBitmap;
John Reckebd52612014-12-10 16:47:36 -0800699 bool mEntryValid;
Romain Guy55b6f952013-06-27 15:27:09 -0700700 AssetAtlas::Entry* mEntry;
Chris Craik2af46352012-11-26 18:30:17 -0800701};
702
Chris Craik2af46352012-11-26 18:30:17 -0800703class DrawBitmapRectOp : public DrawBoundedOp {
704public:
Chris Craikd218a922014-01-02 17:13:34 -0800705 DrawBitmapRectOp(const SkBitmap* bitmap,
706 float srcLeft, float srcTop, float srcRight, float srcBottom,
707 float dstLeft, float dstTop, float dstRight, float dstBottom, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -0800708 : DrawBoundedOp(dstLeft, dstTop, dstRight, dstBottom, paint),
709 mBitmap(bitmap), mSrc(srcLeft, srcTop, srcRight, srcBottom) {}
710
Andreas Gampe64bb4132014-11-22 00:35:09 +0000711 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Tom Hudson107843d2014-09-08 11:26:26 -0400712 renderer.drawBitmap(mBitmap, mSrc.left, mSrc.top, mSrc.right, mSrc.bottom,
Chris Craik2af46352012-11-26 18:30:17 -0800713 mLocalBounds.left, mLocalBounds.top, mLocalBounds.right, mLocalBounds.bottom,
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -0400714 mPaint);
Chris Craik2af46352012-11-26 18:30:17 -0800715 }
716
Andreas Gampe64bb4132014-11-22 00:35:09 +0000717 virtual void output(int level, uint32_t logFlags) const {
John Reckce444ca2014-06-02 15:12:36 -0700718 OP_LOG("Draw bitmap %p src=" RECT_STRING ", dst=" RECT_STRING,
Chris Craik2af46352012-11-26 18:30:17 -0800719 mBitmap, RECT_ARGS(mSrc), RECT_ARGS(mLocalBounds));
720 }
721
722 virtual const char* name() { return "DrawBitmapRect"; }
Chris Craik527a3aa2013-03-04 10:19:31 -0800723
Andreas Gampe64bb4132014-11-22 00:35:09 +0000724 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
725 const DeferredDisplayState& state) {
Chris Craik28ce94a2013-05-31 11:38:03 -0700726 deferInfo.batchId = DeferredDisplayList::kOpBatch_Bitmap;
Chris Craikc3566d02013-02-04 16:16:33 -0800727 }
Chris Craik2af46352012-11-26 18:30:17 -0800728
729private:
Chris Craikd218a922014-01-02 17:13:34 -0800730 const SkBitmap* mBitmap;
Chris Craik2af46352012-11-26 18:30:17 -0800731 Rect mSrc;
732};
733
734class DrawBitmapDataOp : public DrawBitmapOp {
735public:
Chris Craik79647502014-08-06 13:42:24 -0700736 DrawBitmapDataOp(const SkBitmap* bitmap, const SkPaint* paint)
737 : DrawBitmapOp(bitmap, paint) {}
Chris Craik2af46352012-11-26 18:30:17 -0800738
Andreas Gampe64bb4132014-11-22 00:35:09 +0000739 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Tom Hudson107843d2014-09-08 11:26:26 -0400740 renderer.drawBitmapData(mBitmap, mPaint);
Chris Craik2af46352012-11-26 18:30:17 -0800741 }
742
Andreas Gampe64bb4132014-11-22 00:35:09 +0000743 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800744 OP_LOG("Draw bitmap %p", mBitmap);
745 }
746
747 virtual const char* name() { return "DrawBitmapData"; }
Chris Craik527a3aa2013-03-04 10:19:31 -0800748
Andreas Gampe64bb4132014-11-22 00:35:09 +0000749 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
750 const DeferredDisplayState& state) {
Chris Craik28ce94a2013-05-31 11:38:03 -0700751 deferInfo.batchId = DeferredDisplayList::kOpBatch_Bitmap;
Chris Craikc3566d02013-02-04 16:16:33 -0800752 }
Chris Craik2af46352012-11-26 18:30:17 -0800753};
754
Chris Craik5d116762013-02-19 17:49:31 -0800755class DrawBitmapMeshOp : public DrawBoundedOp {
Chris Craik2af46352012-11-26 18:30:17 -0800756public:
Chris Craikd218a922014-01-02 17:13:34 -0800757 DrawBitmapMeshOp(const SkBitmap* bitmap, int meshWidth, int meshHeight,
758 const float* vertices, const int* colors, const SkPaint* paint)
Chris Craik5d116762013-02-19 17:49:31 -0800759 : DrawBoundedOp(vertices, 2 * (meshWidth + 1) * (meshHeight + 1), paint),
760 mBitmap(bitmap), mMeshWidth(meshWidth), mMeshHeight(meshHeight),
Chris Craik2af46352012-11-26 18:30:17 -0800761 mVertices(vertices), mColors(colors) {}
762
Andreas Gampe64bb4132014-11-22 00:35:09 +0000763 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Tom Hudson107843d2014-09-08 11:26:26 -0400764 renderer.drawBitmapMesh(mBitmap, mMeshWidth, mMeshHeight,
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -0400765 mVertices, mColors, mPaint);
Chris Craik2af46352012-11-26 18:30:17 -0800766 }
767
Andreas Gampe64bb4132014-11-22 00:35:09 +0000768 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800769 OP_LOG("Draw bitmap %p mesh %d x %d", mBitmap, mMeshWidth, mMeshHeight);
770 }
771
772 virtual const char* name() { return "DrawBitmapMesh"; }
Chris Craik527a3aa2013-03-04 10:19:31 -0800773
Andreas Gampe64bb4132014-11-22 00:35:09 +0000774 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
775 const DeferredDisplayState& state) {
Chris Craik28ce94a2013-05-31 11:38:03 -0700776 deferInfo.batchId = DeferredDisplayList::kOpBatch_Bitmap;
Chris Craikc3566d02013-02-04 16:16:33 -0800777 }
Chris Craik2af46352012-11-26 18:30:17 -0800778
779private:
Chris Craikd218a922014-01-02 17:13:34 -0800780 const SkBitmap* mBitmap;
Chris Craik2af46352012-11-26 18:30:17 -0800781 int mMeshWidth;
782 int mMeshHeight;
Chris Craikd218a922014-01-02 17:13:34 -0800783 const float* mVertices;
784 const int* mColors;
Chris Craik2af46352012-11-26 18:30:17 -0800785};
786
787class DrawPatchOp : public DrawBoundedOp {
788public:
Chris Craikd218a922014-01-02 17:13:34 -0800789 DrawPatchOp(const SkBitmap* bitmap, const Res_png_9patch* patch,
790 float left, float top, float right, float bottom, const SkPaint* paint)
Romain Guy03c00b52013-06-20 18:30:28 -0700791 : DrawBoundedOp(left, top, right, bottom, paint),
Romain Guy55b6f952013-06-27 15:27:09 -0700792 mBitmap(bitmap), mPatch(patch), mGenerationId(0), mMesh(NULL),
John Reckebd52612014-12-10 16:47:36 -0800793 mEntryValid(false), mEntry(NULL) {
Romain Guy3b748a42013-04-17 18:54:38 -0700794 };
Chris Craik2af46352012-11-26 18:30:17 -0800795
John Reckebd52612014-12-10 16:47:36 -0800796 AssetAtlas::Entry* getAtlasEntry(OpenGLRenderer& renderer) {
797 if (!mEntryValid) {
798 mEntryValid = true;
799 mEntry = renderer.renderState().assetAtlas().getEntry(mBitmap);
Romain Guy55b6f952013-06-27 15:27:09 -0700800 }
801 return mEntry;
802 }
803
Romain Guy03c00b52013-06-20 18:30:28 -0700804 const Patch* getMesh(OpenGLRenderer& renderer) {
Romain Guy4c2547f2013-06-11 16:19:24 -0700805 if (!mMesh || renderer.getCaches().patchCache.getGenerationId() != mGenerationId) {
806 PatchCache& cache = renderer.getCaches().patchCache;
John Reckebd52612014-12-10 16:47:36 -0800807 mMesh = cache.get(getAtlasEntry(renderer), mBitmap->width(), mBitmap->height(),
Romain Guy03c00b52013-06-20 18:30:28 -0700808 mLocalBounds.getWidth(), mLocalBounds.getHeight(), mPatch);
Romain Guy4c2547f2013-06-11 16:19:24 -0700809 mGenerationId = cache.getGenerationId();
810 }
Romain Guy03c00b52013-06-20 18:30:28 -0700811 return mMesh;
812 }
813
814 /**
815 * This multi-draw operation builds an indexed mesh on the stack by copying
816 * and transforming the vertices of each 9-patch in the batch. This method
817 * is also responsible for dirtying the current layer, if any.
818 */
Andreas Gampe64bb4132014-11-22 00:35:09 +0000819 virtual void multiDraw(OpenGLRenderer& renderer, Rect& dirty,
820 const Vector<OpStatePair>& ops, const Rect& bounds) {
Chris Craikc1c5f082013-09-11 16:23:37 -0700821 const DeferredDisplayState& firstState = *(ops[0].state);
822 renderer.restoreDisplayState(firstState, true); // restore all but the clip
Romain Guy03c00b52013-06-20 18:30:28 -0700823
824 // Batches will usually contain a small number of items so it's
825 // worth performing a first iteration to count the exact number
826 // of vertices we need in the new mesh
827 uint32_t totalVertices = 0;
828 for (unsigned int i = 0; i < ops.size(); i++) {
Chris Craikc1c5f082013-09-11 16:23:37 -0700829 totalVertices += ((DrawPatchOp*) ops[i].op)->getMesh(renderer)->verticesCount;
Romain Guy03c00b52013-06-20 18:30:28 -0700830 }
831
832 const bool hasLayer = renderer.hasLayer();
833
834 uint32_t indexCount = 0;
835
836 TextureVertex vertices[totalVertices];
837 TextureVertex* vertex = &vertices[0];
838
839 // Create a mesh that contains the transformed vertices for all the
840 // 9-patch objects that are part of the batch. Note that onDefer()
841 // enforces ops drawn by this function to have a pure translate or
842 // identity matrix
843 for (unsigned int i = 0; i < ops.size(); i++) {
Chris Craikc1c5f082013-09-11 16:23:37 -0700844 DrawPatchOp* patchOp = (DrawPatchOp*) ops[i].op;
845 const DeferredDisplayState* state = ops[i].state;
Romain Guy03c00b52013-06-20 18:30:28 -0700846 const Patch* opMesh = patchOp->getMesh(renderer);
847 uint32_t vertexCount = opMesh->verticesCount;
848 if (vertexCount == 0) continue;
849
850 // We use the bounds to know where to translate our vertices
851 // Using patchOp->state.mBounds wouldn't work because these
852 // bounds are clipped
Chris Craikc1c5f082013-09-11 16:23:37 -0700853 const float tx = (int) floorf(state->mMatrix.getTranslateX() +
Romain Guy03c00b52013-06-20 18:30:28 -0700854 patchOp->mLocalBounds.left + 0.5f);
Chris Craikc1c5f082013-09-11 16:23:37 -0700855 const float ty = (int) floorf(state->mMatrix.getTranslateY() +
Romain Guy03c00b52013-06-20 18:30:28 -0700856 patchOp->mLocalBounds.top + 0.5f);
857
858 // Copy & transform all the vertices for the current operation
Chris Craik51d6a3d2014-12-22 17:16:56 -0800859 TextureVertex* opVertices = opMesh->vertices.get();
Romain Guy03c00b52013-06-20 18:30:28 -0700860 for (uint32_t j = 0; j < vertexCount; j++, opVertices++) {
861 TextureVertex::set(vertex++,
Romain Guy3380cfd2013-08-15 16:57:57 -0700862 opVertices->x + tx, opVertices->y + ty,
863 opVertices->u, opVertices->v);
Romain Guy03c00b52013-06-20 18:30:28 -0700864 }
865
866 // Dirty the current layer if possible. When the 9-patch does not
867 // contain empty quads we can take a shortcut and simply set the
868 // dirty rect to the object's bounds.
869 if (hasLayer) {
870 if (!opMesh->hasEmptyQuads) {
871 renderer.dirtyLayer(tx, ty,
872 tx + patchOp->mLocalBounds.getWidth(),
873 ty + patchOp->mLocalBounds.getHeight());
874 } else {
875 const size_t count = opMesh->quads.size();
876 for (size_t i = 0; i < count; i++) {
877 const Rect& quadBounds = opMesh->quads[i];
878 const float x = tx + quadBounds.left;
879 const float y = ty + quadBounds.top;
880 renderer.dirtyLayer(x, y,
881 x + quadBounds.getWidth(), y + quadBounds.getHeight());
882 }
883 }
884 }
885
886 indexCount += opMesh->indexCount;
887 }
888
Yohann Roussel59cf7342014-12-11 11:10:50 +0100889 renderer.drawPatches(mBitmap, getAtlasEntry(renderer),
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -0400890 &vertices[0], indexCount, mPaint);
Romain Guy03c00b52013-06-20 18:30:28 -0700891 }
892
Andreas Gampe64bb4132014-11-22 00:35:09 +0000893 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Romain Guy4c2547f2013-06-11 16:19:24 -0700894 // We're not calling the public variant of drawPatch() here
895 // This method won't perform the quickReject() since we've already done it at this point
Yohann Roussel59cf7342014-12-11 11:10:50 +0100896 renderer.drawPatch(mBitmap, getMesh(renderer), getAtlasEntry(renderer),
Romain Guy03c00b52013-06-20 18:30:28 -0700897 mLocalBounds.left, mLocalBounds.top, mLocalBounds.right, mLocalBounds.bottom,
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -0400898 mPaint);
Chris Craik2af46352012-11-26 18:30:17 -0800899 }
900
Andreas Gampe64bb4132014-11-22 00:35:09 +0000901 virtual void output(int level, uint32_t logFlags) const {
John Reckdad7d84c2014-12-09 12:33:26 -0800902 OP_LOG("Draw patch " RECT_STRING "%s", RECT_ARGS(mLocalBounds),
903 mEntry ? " with AssetAtlas" : "");
Chris Craik2af46352012-11-26 18:30:17 -0800904 }
905
906 virtual const char* name() { return "DrawPatch"; }
Chris Craik527a3aa2013-03-04 10:19:31 -0800907
Andreas Gampe64bb4132014-11-22 00:35:09 +0000908 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
Chris Craikc1c5f082013-09-11 16:23:37 -0700909 const DeferredDisplayState& state) {
Chris Craik28ce94a2013-05-31 11:38:03 -0700910 deferInfo.batchId = DeferredDisplayList::kOpBatch_Patch;
John Reckebd52612014-12-10 16:47:36 -0800911 deferInfo.mergeId = getAtlasEntry(renderer) ? (mergeid_t) mEntry->getMergeId() : (mergeid_t) mBitmap;
Romain Guy03c00b52013-06-20 18:30:28 -0700912 deferInfo.mergeable = state.mMatrix.isPureTranslate() &&
913 OpenGLRenderer::getXfermodeDirect(mPaint) == SkXfermode::kSrcOver_Mode;
Chris Craikc1c5f082013-09-11 16:23:37 -0700914 deferInfo.opaqueOverBounds = isOpaqueOverBounds(state) && mBitmap->isOpaque();
Chris Craikc3566d02013-02-04 16:16:33 -0800915 }
Chris Craik2af46352012-11-26 18:30:17 -0800916
917private:
Chris Craikd218a922014-01-02 17:13:34 -0800918 const SkBitmap* mBitmap;
919 const Res_png_9patch* mPatch;
Romain Guy4c2547f2013-06-11 16:19:24 -0700920
Romain Guy4c2547f2013-06-11 16:19:24 -0700921 uint32_t mGenerationId;
922 const Patch* mMesh;
Romain Guy03c00b52013-06-20 18:30:28 -0700923
John Reckebd52612014-12-10 16:47:36 -0800924 bool mEntryValid;
Romain Guy3b748a42013-04-17 18:54:38 -0700925 AssetAtlas::Entry* mEntry;
Chris Craik2af46352012-11-26 18:30:17 -0800926};
927
928class DrawColorOp : public DrawOp {
929public:
930 DrawColorOp(int color, SkXfermode::Mode mode)
Chris Craikf57776b2013-10-25 18:30:17 -0700931 : DrawOp(NULL), mColor(color), mMode(mode) {};
Chris Craik2af46352012-11-26 18:30:17 -0800932
Andreas Gampe64bb4132014-11-22 00:35:09 +0000933 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Tom Hudson107843d2014-09-08 11:26:26 -0400934 renderer.drawColor(mColor, mMode);
Chris Craik2af46352012-11-26 18:30:17 -0800935 }
936
Andreas Gampe64bb4132014-11-22 00:35:09 +0000937 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800938 OP_LOG("Draw color %#x, mode %d", mColor, mMode);
939 }
940
941 virtual const char* name() { return "DrawColor"; }
942
943private:
944 int mColor;
945 SkXfermode::Mode mMode;
946};
947
948class DrawStrokableOp : public DrawBoundedOp {
949public:
Chris Craikd218a922014-01-02 17:13:34 -0800950 DrawStrokableOp(float left, float top, float right, float bottom, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -0800951 : DrawBoundedOp(left, top, right, bottom, paint) {};
Chris Craik947eabf2014-08-19 10:21:12 -0700952 DrawStrokableOp(const Rect& localBounds, const SkPaint* paint)
953 : DrawBoundedOp(localBounds, paint) {};
Chris Craik2af46352012-11-26 18:30:17 -0800954
John Reckca1b3b82014-06-27 07:21:36 -0700955 virtual bool getLocalBounds(Rect& localBounds) {
Chris Craikc3566d02013-02-04 16:16:33 -0800956 localBounds.set(mLocalBounds);
Chris Craik2af46352012-11-26 18:30:17 -0800957 if (mPaint && mPaint->getStyle() != SkPaint::kFill_Style) {
Chris Craikc3566d02013-02-04 16:16:33 -0800958 localBounds.outset(strokeWidthOutset());
Chris Craik2af46352012-11-26 18:30:17 -0800959 }
960 return true;
961 }
Chris Craikc3566d02013-02-04 16:16:33 -0800962
Andreas Gampe64bb4132014-11-22 00:35:09 +0000963 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
964 const DeferredDisplayState& state) {
Chris Craikc3566d02013-02-04 16:16:33 -0800965 if (mPaint->getPathEffect()) {
Chris Craik28ce94a2013-05-31 11:38:03 -0700966 deferInfo.batchId = DeferredDisplayList::kOpBatch_AlphaMaskTexture;
Chris Craik527a3aa2013-03-04 10:19:31 -0800967 } else {
Chris Craik28ce94a2013-05-31 11:38:03 -0700968 deferInfo.batchId = mPaint->isAntiAlias() ?
Chris Craik527a3aa2013-03-04 10:19:31 -0800969 DeferredDisplayList::kOpBatch_AlphaVertices :
970 DeferredDisplayList::kOpBatch_Vertices;
Chris Craikc3566d02013-02-04 16:16:33 -0800971 }
Chris Craikc3566d02013-02-04 16:16:33 -0800972 }
Chris Craik2af46352012-11-26 18:30:17 -0800973};
974
975class DrawRectOp : public DrawStrokableOp {
976public:
Chris Craikd218a922014-01-02 17:13:34 -0800977 DrawRectOp(float left, float top, float right, float bottom, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -0800978 : DrawStrokableOp(left, top, right, bottom, paint) {}
979
Andreas Gampe64bb4132014-11-22 00:35:09 +0000980 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Tom Hudson107843d2014-09-08 11:26:26 -0400981 renderer.drawRect(mLocalBounds.left, mLocalBounds.top,
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -0400982 mLocalBounds.right, mLocalBounds.bottom, mPaint);
Chris Craik2af46352012-11-26 18:30:17 -0800983 }
984
Andreas Gampe64bb4132014-11-22 00:35:09 +0000985 virtual void output(int level, uint32_t logFlags) const {
John Reckce444ca2014-06-02 15:12:36 -0700986 OP_LOG("Draw Rect " RECT_STRING, RECT_ARGS(mLocalBounds));
Chris Craik2af46352012-11-26 18:30:17 -0800987 }
988
Chris Craikc1c5f082013-09-11 16:23:37 -0700989 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
990 const DeferredDisplayState& state) {
991 DrawStrokableOp::onDefer(renderer, deferInfo, state);
992 deferInfo.opaqueOverBounds = isOpaqueOverBounds(state) &&
Chris Craik28ce94a2013-05-31 11:38:03 -0700993 mPaint->getStyle() == SkPaint::kFill_Style;
994 }
995
Chris Craik2af46352012-11-26 18:30:17 -0800996 virtual const char* name() { return "DrawRect"; }
997};
998
Chris Craik5d116762013-02-19 17:49:31 -0800999class DrawRectsOp : public DrawBoundedOp {
Chris Craik2af46352012-11-26 18:30:17 -08001000public:
Chris Craikd218a922014-01-02 17:13:34 -08001001 DrawRectsOp(const float* rects, int count, const SkPaint* paint)
Chris Craik5d116762013-02-19 17:49:31 -08001002 : DrawBoundedOp(rects, count, paint),
1003 mRects(rects), mCount(count) {}
Chris Craik2af46352012-11-26 18:30:17 -08001004
Andreas Gampe64bb4132014-11-22 00:35:09 +00001005 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Tom Hudson107843d2014-09-08 11:26:26 -04001006 renderer.drawRects(mRects, mCount, mPaint);
Chris Craik2af46352012-11-26 18:30:17 -08001007 }
1008
Andreas Gampe64bb4132014-11-22 00:35:09 +00001009 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001010 OP_LOG("Draw Rects count %d", mCount);
1011 }
1012
1013 virtual const char* name() { return "DrawRects"; }
1014
Andreas Gampe64bb4132014-11-22 00:35:09 +00001015 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
1016 const DeferredDisplayState& state) {
Chris Craik28ce94a2013-05-31 11:38:03 -07001017 deferInfo.batchId = DeferredDisplayList::kOpBatch_Vertices;
Chris Craikc3566d02013-02-04 16:16:33 -08001018 }
1019
Chris Craik2af46352012-11-26 18:30:17 -08001020private:
1021 const float* mRects;
1022 int mCount;
1023};
1024
1025class DrawRoundRectOp : public DrawStrokableOp {
1026public:
1027 DrawRoundRectOp(float left, float top, float right, float bottom,
Chris Craikd218a922014-01-02 17:13:34 -08001028 float rx, float ry, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001029 : DrawStrokableOp(left, top, right, bottom, paint), mRx(rx), mRy(ry) {}
1030
Andreas Gampe64bb4132014-11-22 00:35:09 +00001031 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Tom Hudson107843d2014-09-08 11:26:26 -04001032 renderer.drawRoundRect(mLocalBounds.left, mLocalBounds.top,
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -04001033 mLocalBounds.right, mLocalBounds.bottom, mRx, mRy, mPaint);
Chris Craik2af46352012-11-26 18:30:17 -08001034 }
1035
Andreas Gampe64bb4132014-11-22 00:35:09 +00001036 virtual void output(int level, uint32_t logFlags) const {
John Reckce444ca2014-06-02 15:12:36 -07001037 OP_LOG("Draw RoundRect " RECT_STRING ", rx %f, ry %f", RECT_ARGS(mLocalBounds), mRx, mRy);
Chris Craik2af46352012-11-26 18:30:17 -08001038 }
1039
Chris Craik05f3d6e2014-06-02 16:27:04 -07001040 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
1041 const DeferredDisplayState& state) {
1042 DrawStrokableOp::onDefer(renderer, deferInfo, state);
1043 if (!mPaint->getPathEffect()) {
Chris Craik6ac174b2014-06-17 13:47:05 -07001044 renderer.getCaches().tessellationCache.precacheRoundRect(state.mMatrix, *mPaint,
1045 mLocalBounds.getWidth(), mLocalBounds.getHeight(), mRx, mRy);
Chris Craik05f3d6e2014-06-02 16:27:04 -07001046 }
1047 }
1048
Chris Craik2af46352012-11-26 18:30:17 -08001049 virtual const char* name() { return "DrawRoundRect"; }
1050
1051private:
1052 float mRx;
1053 float mRy;
1054};
1055
Jorim Jaggi072707d2014-09-15 17:20:08 +02001056class DrawRoundRectPropsOp : public DrawOp {
1057public:
1058 DrawRoundRectPropsOp(float* left, float* top, float* right, float* bottom,
1059 float *rx, float *ry, const SkPaint* paint)
1060 : DrawOp(paint), mLeft(left), mTop(top), mRight(right), mBottom(bottom),
1061 mRx(rx), mRy(ry) {}
1062
Andreas Gampe64bb4132014-11-22 00:35:09 +00001063 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Tom Hudson107843d2014-09-08 11:26:26 -04001064 renderer.drawRoundRect(*mLeft, *mTop, *mRight, *mBottom,
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -04001065 *mRx, *mRy, mPaint);
Jorim Jaggi072707d2014-09-15 17:20:08 +02001066 }
1067
Andreas Gampe64bb4132014-11-22 00:35:09 +00001068 virtual void output(int level, uint32_t logFlags) const {
Jorim Jaggi072707d2014-09-15 17:20:08 +02001069 OP_LOG("Draw RoundRect Props " RECT_STRING ", rx %f, ry %f",
1070 *mLeft, *mTop, *mRight, *mBottom, *mRx, *mRy);
1071 }
1072
1073 virtual const char* name() { return "DrawRoundRectProps"; }
1074
1075private:
1076 float* mLeft;
1077 float* mTop;
1078 float* mRight;
1079 float* mBottom;
1080 float* mRx;
1081 float* mRy;
1082};
1083
Chris Craik2af46352012-11-26 18:30:17 -08001084class DrawCircleOp : public DrawStrokableOp {
1085public:
Chris Craikd218a922014-01-02 17:13:34 -08001086 DrawCircleOp(float x, float y, float radius, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001087 : DrawStrokableOp(x - radius, y - radius, x + radius, y + radius, paint),
1088 mX(x), mY(y), mRadius(radius) {}
1089
Andreas Gampe64bb4132014-11-22 00:35:09 +00001090 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Tom Hudson107843d2014-09-08 11:26:26 -04001091 renderer.drawCircle(mX, mY, mRadius, mPaint);
Chris Craik2af46352012-11-26 18:30:17 -08001092 }
1093
Andreas Gampe64bb4132014-11-22 00:35:09 +00001094 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001095 OP_LOG("Draw Circle x %f, y %f, r %f", mX, mY, mRadius);
1096 }
1097
1098 virtual const char* name() { return "DrawCircle"; }
1099
1100private:
1101 float mX;
1102 float mY;
1103 float mRadius;
1104};
1105
John Reck52244ff2014-05-01 21:27:37 -07001106class DrawCirclePropsOp : public DrawOp {
1107public:
1108 DrawCirclePropsOp(float* x, float* y, float* radius, const SkPaint* paint)
1109 : DrawOp(paint), mX(x), mY(y), mRadius(radius) {}
1110
Andreas Gampe64bb4132014-11-22 00:35:09 +00001111 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Tom Hudson107843d2014-09-08 11:26:26 -04001112 renderer.drawCircle(*mX, *mY, *mRadius, mPaint);
John Reck52244ff2014-05-01 21:27:37 -07001113 }
1114
Andreas Gampe64bb4132014-11-22 00:35:09 +00001115 virtual void output(int level, uint32_t logFlags) const {
John Reck52244ff2014-05-01 21:27:37 -07001116 OP_LOG("Draw Circle Props x %p, y %p, r %p", mX, mY, mRadius);
1117 }
1118
1119 virtual const char* name() { return "DrawCircleProps"; }
1120
1121private:
1122 float* mX;
1123 float* mY;
1124 float* mRadius;
1125};
1126
Chris Craik2af46352012-11-26 18:30:17 -08001127class DrawOvalOp : public DrawStrokableOp {
1128public:
Chris Craikd218a922014-01-02 17:13:34 -08001129 DrawOvalOp(float left, float top, float right, float bottom, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001130 : DrawStrokableOp(left, top, right, bottom, paint) {}
1131
Andreas Gampe64bb4132014-11-22 00:35:09 +00001132 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Tom Hudson107843d2014-09-08 11:26:26 -04001133 renderer.drawOval(mLocalBounds.left, mLocalBounds.top,
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -04001134 mLocalBounds.right, mLocalBounds.bottom, mPaint);
Chris Craik2af46352012-11-26 18:30:17 -08001135 }
1136
Andreas Gampe64bb4132014-11-22 00:35:09 +00001137 virtual void output(int level, uint32_t logFlags) const {
John Reckce444ca2014-06-02 15:12:36 -07001138 OP_LOG("Draw Oval " RECT_STRING, RECT_ARGS(mLocalBounds));
Chris Craik2af46352012-11-26 18:30:17 -08001139 }
1140
1141 virtual const char* name() { return "DrawOval"; }
1142};
1143
1144class DrawArcOp : public DrawStrokableOp {
1145public:
1146 DrawArcOp(float left, float top, float right, float bottom,
Chris Craikd218a922014-01-02 17:13:34 -08001147 float startAngle, float sweepAngle, bool useCenter, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001148 : DrawStrokableOp(left, top, right, bottom, paint),
1149 mStartAngle(startAngle), mSweepAngle(sweepAngle), mUseCenter(useCenter) {}
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.drawArc(mLocalBounds.left, mLocalBounds.top,
Chris Craik2af46352012-11-26 18:30:17 -08001153 mLocalBounds.right, mLocalBounds.bottom,
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -04001154 mStartAngle, mSweepAngle, mUseCenter, mPaint);
Chris Craik2af46352012-11-26 18:30:17 -08001155 }
1156
Andreas Gampe64bb4132014-11-22 00:35:09 +00001157 virtual void output(int level, uint32_t logFlags) const {
John Reckce444ca2014-06-02 15:12:36 -07001158 OP_LOG("Draw Arc " RECT_STRING ", start %f, sweep %f, useCenter %d",
Chris Craik2af46352012-11-26 18:30:17 -08001159 RECT_ARGS(mLocalBounds), mStartAngle, mSweepAngle, mUseCenter);
1160 }
1161
1162 virtual const char* name() { return "DrawArc"; }
1163
1164private:
1165 float mStartAngle;
1166 float mSweepAngle;
1167 bool mUseCenter;
1168};
1169
1170class DrawPathOp : public DrawBoundedOp {
1171public:
Chris Craikd218a922014-01-02 17:13:34 -08001172 DrawPathOp(const SkPath* path, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001173 : DrawBoundedOp(paint), mPath(path) {
1174 float left, top, offset;
1175 uint32_t width, height;
Romain Guyca89e2a2013-03-08 17:44:20 -08001176 PathCache::computePathBounds(path, paint, left, top, offset, width, height);
Chris Craik2af46352012-11-26 18:30:17 -08001177 left -= offset;
1178 top -= offset;
1179 mLocalBounds.set(left, top, left + width, top + height);
1180 }
1181
Andreas Gampe64bb4132014-11-22 00:35:09 +00001182 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Tom Hudson107843d2014-09-08 11:26:26 -04001183 renderer.drawPath(mPath, mPaint);
Chris Craik2af46352012-11-26 18:30:17 -08001184 }
1185
Chris Craikc1c5f082013-09-11 16:23:37 -07001186 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
Andreas Gampe64bb4132014-11-22 00:35:09 +00001187 const DeferredDisplayState& state) {
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -04001188 renderer.getCaches().pathCache.precache(mPath, mPaint);
Chris Craik527a3aa2013-03-04 10:19:31 -08001189
Chris Craik28ce94a2013-05-31 11:38:03 -07001190 deferInfo.batchId = DeferredDisplayList::kOpBatch_AlphaMaskTexture;
Romain Guyca89e2a2013-03-08 17:44:20 -08001191 }
1192
Andreas Gampe64bb4132014-11-22 00:35:09 +00001193 virtual void output(int level, uint32_t logFlags) const {
John Reckce444ca2014-06-02 15:12:36 -07001194 OP_LOG("Draw Path %p in " RECT_STRING, mPath, RECT_ARGS(mLocalBounds));
Chris Craik2af46352012-11-26 18:30:17 -08001195 }
1196
1197 virtual const char* name() { return "DrawPath"; }
1198
1199private:
Chris Craikd218a922014-01-02 17:13:34 -08001200 const SkPath* mPath;
Chris Craik2af46352012-11-26 18:30:17 -08001201};
1202
Chris Craikc3566d02013-02-04 16:16:33 -08001203class DrawLinesOp : public DrawBoundedOp {
Chris Craik2af46352012-11-26 18:30:17 -08001204public:
Chris Craikd218a922014-01-02 17:13:34 -08001205 DrawLinesOp(const float* points, int count, const SkPaint* paint)
Chris Craik5d116762013-02-19 17:49:31 -08001206 : DrawBoundedOp(points, count, paint),
1207 mPoints(points), mCount(count) {
Chris Craikc3566d02013-02-04 16:16:33 -08001208 mLocalBounds.outset(strokeWidthOutset());
Chris Craik2af46352012-11-26 18:30:17 -08001209 }
1210
Andreas Gampe64bb4132014-11-22 00:35:09 +00001211 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Tom Hudson107843d2014-09-08 11:26:26 -04001212 renderer.drawLines(mPoints, mCount, mPaint);
Chris Craik2af46352012-11-26 18:30:17 -08001213 }
1214
Andreas Gampe64bb4132014-11-22 00:35:09 +00001215 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001216 OP_LOG("Draw Lines count %d", mCount);
1217 }
1218
1219 virtual const char* name() { return "DrawLines"; }
1220
Andreas Gampe64bb4132014-11-22 00:35:09 +00001221 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
1222 const DeferredDisplayState& state) {
Chris Craik28ce94a2013-05-31 11:38:03 -07001223 deferInfo.batchId = mPaint->isAntiAlias() ?
Chris Craikc3566d02013-02-04 16:16:33 -08001224 DeferredDisplayList::kOpBatch_AlphaVertices :
1225 DeferredDisplayList::kOpBatch_Vertices;
1226 }
1227
Chris Craik2af46352012-11-26 18:30:17 -08001228protected:
Chris Craikd218a922014-01-02 17:13:34 -08001229 const float* mPoints;
Chris Craik2af46352012-11-26 18:30:17 -08001230 int mCount;
1231};
1232
1233class DrawPointsOp : public DrawLinesOp {
1234public:
Chris Craikd218a922014-01-02 17:13:34 -08001235 DrawPointsOp(const float* points, int count, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001236 : DrawLinesOp(points, count, paint) {}
1237
Andreas Gampe64bb4132014-11-22 00:35:09 +00001238 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Tom Hudson107843d2014-09-08 11:26:26 -04001239 renderer.drawPoints(mPoints, mCount, mPaint);
Chris Craik2af46352012-11-26 18:30:17 -08001240 }
1241
Andreas Gampe64bb4132014-11-22 00:35:09 +00001242 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001243 OP_LOG("Draw Points count %d", mCount);
1244 }
1245
1246 virtual const char* name() { return "DrawPoints"; }
1247};
1248
1249class DrawSomeTextOp : public DrawOp {
1250public:
Chris Craikd218a922014-01-02 17:13:34 -08001251 DrawSomeTextOp(const char* text, int bytesCount, int count, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001252 : DrawOp(paint), mText(text), mBytesCount(bytesCount), mCount(count) {};
1253
Andreas Gampe64bb4132014-11-22 00:35:09 +00001254 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001255 OP_LOG("Draw some text, %d bytes", mBytesCount);
1256 }
Chris Craikc3566d02013-02-04 16:16:33 -08001257
Derek Sollenbergerc29a0a42014-03-31 13:52:39 -04001258 virtual bool hasTextShadow() const {
1259 return OpenGLRenderer::hasTextShadow(mPaint);
1260 }
1261
Chris Craikc1c5f082013-09-11 16:23:37 -07001262 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
Andreas Gampe64bb4132014-11-22 00:35:09 +00001263 const DeferredDisplayState& state) {
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -04001264 FontRenderer& fontRenderer = renderer.getCaches().fontRenderer->getFontRenderer(mPaint);
1265 fontRenderer.precache(mPaint, mText, mCount, SkMatrix::I());
Romain Guy0f6675332013-03-01 14:31:04 -08001266
Chris Craik98d608d2014-07-17 12:25:11 -07001267 deferInfo.batchId = mPaint->getColor() == SK_ColorBLACK ?
Chris Craikc3566d02013-02-04 16:16:33 -08001268 DeferredDisplayList::kOpBatch_Text :
1269 DeferredDisplayList::kOpBatch_ColorText;
1270 }
Chris Craik527a3aa2013-03-04 10:19:31 -08001271
Chris Craik2af46352012-11-26 18:30:17 -08001272protected:
1273 const char* mText;
1274 int mBytesCount;
1275 int mCount;
1276};
1277
1278class DrawTextOnPathOp : public DrawSomeTextOp {
1279public:
1280 DrawTextOnPathOp(const char* text, int bytesCount, int count,
Chris Craikd218a922014-01-02 17:13:34 -08001281 const SkPath* path, float hOffset, float vOffset, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001282 : DrawSomeTextOp(text, bytesCount, count, paint),
1283 mPath(path), mHOffset(hOffset), mVOffset(vOffset) {
1284 /* TODO: inherit from DrawBounded and init mLocalBounds */
1285 }
1286
Andreas Gampe64bb4132014-11-22 00:35:09 +00001287 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Tom Hudson107843d2014-09-08 11:26:26 -04001288 renderer.drawTextOnPath(mText, mBytesCount, mCount, mPath,
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -04001289 mHOffset, mVOffset, mPaint);
Chris Craik2af46352012-11-26 18:30:17 -08001290 }
1291
1292 virtual const char* name() { return "DrawTextOnPath"; }
1293
1294private:
Chris Craikd218a922014-01-02 17:13:34 -08001295 const SkPath* mPath;
Chris Craik2af46352012-11-26 18:30:17 -08001296 float mHOffset;
1297 float mVOffset;
1298};
1299
1300class DrawPosTextOp : public DrawSomeTextOp {
1301public:
1302 DrawPosTextOp(const char* text, int bytesCount, int count,
Chris Craikd218a922014-01-02 17:13:34 -08001303 const float* positions, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001304 : DrawSomeTextOp(text, bytesCount, count, paint), mPositions(positions) {
1305 /* TODO: inherit from DrawBounded and init mLocalBounds */
1306 }
1307
Andreas Gampe64bb4132014-11-22 00:35:09 +00001308 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Tom Hudson107843d2014-09-08 11:26:26 -04001309 renderer.drawPosText(mText, mBytesCount, mCount, mPositions, mPaint);
Chris Craik2af46352012-11-26 18:30:17 -08001310 }
1311
1312 virtual const char* name() { return "DrawPosText"; }
1313
1314private:
1315 const float* mPositions;
1316};
1317
Chris Craik947eabf2014-08-19 10:21:12 -07001318class DrawTextOp : public DrawStrokableOp {
Chris Craik2af46352012-11-26 18:30:17 -08001319public:
1320 DrawTextOp(const char* text, int bytesCount, int count, float x, float y,
Chris Craikd218a922014-01-02 17:13:34 -08001321 const float* positions, const SkPaint* paint, float totalAdvance, const Rect& bounds)
Chris Craik947eabf2014-08-19 10:21:12 -07001322 : DrawStrokableOp(bounds, paint), mText(text), mBytesCount(bytesCount), mCount(count),
Chris Craik41541822013-05-03 16:35:54 -07001323 mX(x), mY(y), mPositions(positions), mTotalAdvance(totalAdvance) {
Chris Craik59744b72014-07-01 17:56:52 -07001324 mPrecacheTransform = SkMatrix::InvalidMatrix();
Chris Craik2af46352012-11-26 18:30:17 -08001325 }
1326
Chris Craikc1c5f082013-09-11 16:23:37 -07001327 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
1328 const DeferredDisplayState& state) {
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -04001329 FontRenderer& fontRenderer = renderer.getCaches().fontRenderer->getFontRenderer(mPaint);
Chris Craik59744b72014-07-01 17:56:52 -07001330 SkMatrix transform;
1331 renderer.findBestFontTransform(state.mMatrix, &transform);
Romain Guybd3055f2013-03-13 16:14:47 -07001332 if (mPrecacheTransform != transform) {
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -04001333 fontRenderer.precache(mPaint, mText, mCount, transform);
Romain Guybd3055f2013-03-13 16:14:47 -07001334 mPrecacheTransform = transform;
1335 }
Chris Craik98d608d2014-07-17 12:25:11 -07001336 deferInfo.batchId = mPaint->getColor() == SK_ColorBLACK ?
Chris Craik527a3aa2013-03-04 10:19:31 -08001337 DeferredDisplayList::kOpBatch_Text :
1338 DeferredDisplayList::kOpBatch_ColorText;
1339
Kévin PETIT73fc5582014-02-13 11:03:40 +00001340 deferInfo.mergeId = reinterpret_cast<mergeid_t>(mPaint->getColor());
Chris Craik527a3aa2013-03-04 10:19:31 -08001341
1342 // don't merge decorated text - the decorations won't draw in order
Chris Craik98d608d2014-07-17 12:25:11 -07001343 bool hasDecorations = mPaint->getFlags()
1344 & (SkPaint::kUnderlineText_Flag | SkPaint::kStrikeThruText_Flag);
1345
1346 deferInfo.mergeable = state.mMatrix.isPureTranslate()
1347 && !hasDecorations
1348 && OpenGLRenderer::getXfermodeDirect(mPaint) == SkXfermode::kSrcOver_Mode;
Romain Guy0f6675332013-03-01 14:31:04 -08001349 }
1350
Andreas Gampe64bb4132014-11-22 00:35:09 +00001351 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Romain Guy9b5a1a22013-08-09 14:06:29 -07001352 Rect bounds;
John Reck3b202512014-06-23 13:13:08 -07001353 getLocalBounds(bounds);
Tom Hudson107843d2014-09-08 11:26:26 -04001354 renderer.drawText(mText, mBytesCount, mCount, mX, mY,
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -04001355 mPositions, mPaint, mTotalAdvance, bounds);
Chris Craik2af46352012-11-26 18:30:17 -08001356 }
1357
Andreas Gampe64bb4132014-11-22 00:35:09 +00001358 virtual void multiDraw(OpenGLRenderer& renderer, Rect& dirty,
1359 const Vector<OpStatePair>& ops, const Rect& bounds) {
Chris Craik527a3aa2013-03-04 10:19:31 -08001360 for (unsigned int i = 0; i < ops.size(); i++) {
Chris Craikc1c5f082013-09-11 16:23:37 -07001361 const DeferredDisplayState& state = *(ops[i].state);
Chris Craik527a3aa2013-03-04 10:19:31 -08001362 DrawOpMode drawOpMode = (i == ops.size() - 1) ? kDrawOpMode_Flush : kDrawOpMode_Defer;
Chris Craikc1c5f082013-09-11 16:23:37 -07001363 renderer.restoreDisplayState(state, true); // restore all but the clip
Chris Craik527a3aa2013-03-04 10:19:31 -08001364
Chris Craikc1c5f082013-09-11 16:23:37 -07001365 DrawTextOp& op = *((DrawTextOp*)ops[i].op);
Romain Guy9b5a1a22013-08-09 14:06:29 -07001366 // quickReject() will not occure in drawText() so we can use mLocalBounds
1367 // directly, we do not need to account for shadow by calling getLocalBounds()
Tom Hudson107843d2014-09-08 11:26:26 -04001368 renderer.drawText(op.mText, op.mBytesCount, op.mCount, op.mX, op.mY,
Derek Sollenberger09c2d4f2014-10-15 09:21:10 -04001369 op.mPositions, op.mPaint, op.mTotalAdvance, op.mLocalBounds,
Chris Craik41541822013-05-03 16:35:54 -07001370 drawOpMode);
Chris Craik527a3aa2013-03-04 10:19:31 -08001371 }
Chris Craik527a3aa2013-03-04 10:19:31 -08001372 }
1373
Andreas Gampe64bb4132014-11-22 00:35:09 +00001374 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001375 OP_LOG("Draw Text of count %d, bytes %d", mCount, mBytesCount);
1376 }
1377
1378 virtual const char* name() { return "DrawText"; }
1379
1380private:
1381 const char* mText;
1382 int mBytesCount;
1383 int mCount;
1384 float mX;
1385 float mY;
1386 const float* mPositions;
Chris Craik41541822013-05-03 16:35:54 -07001387 float mTotalAdvance;
Chris Craik59744b72014-07-01 17:56:52 -07001388 SkMatrix mPrecacheTransform;
Chris Craik2af46352012-11-26 18:30:17 -08001389};
1390
1391///////////////////////////////////////////////////////////////////////////////
1392// SPECIAL DRAW OPERATIONS
1393///////////////////////////////////////////////////////////////////////////////
1394
1395class DrawFunctorOp : public DrawOp {
1396public:
1397 DrawFunctorOp(Functor* functor)
Chris Craikf57776b2013-10-25 18:30:17 -07001398 : DrawOp(NULL), mFunctor(functor) {}
Chris Craik2af46352012-11-26 18:30:17 -08001399
Tom Hudson107843d2014-09-08 11:26:26 -04001400 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001401 renderer.startMark("GL functor");
Tom Hudson107843d2014-09-08 11:26:26 -04001402 renderer.callDrawGLFunction(mFunctor, dirty);
Chris Craik2af46352012-11-26 18:30:17 -08001403 renderer.endMark();
Chris Craik2af46352012-11-26 18:30:17 -08001404 }
1405
Andreas Gampe64bb4132014-11-22 00:35:09 +00001406 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001407 OP_LOG("Draw Functor %p", mFunctor);
1408 }
1409
1410 virtual const char* name() { return "DrawFunctor"; }
1411
1412private:
1413 Functor* mFunctor;
1414};
1415
Chris Craika7090e02014-06-20 16:01:00 -07001416class DrawRenderNodeOp : public DrawBoundedOp {
1417 friend class RenderNode; // grant RenderNode access to info of child
Chris Craik8afd0f22014-08-21 17:41:57 -07001418 friend class DisplayListData; // grant DisplayListData access to info of child
Chris Craik2af46352012-11-26 18:30:17 -08001419public:
Chris Craika7090e02014-06-20 16:01:00 -07001420 DrawRenderNodeOp(RenderNode* renderNode, int flags, const mat4& transformFromParent)
1421 : DrawBoundedOp(0, 0, renderNode->getWidth(), renderNode->getHeight(), 0),
1422 mRenderNode(renderNode), mFlags(flags), mTransformFromParent(transformFromParent) {}
Chris Craikc3566d02013-02-04 16:16:33 -08001423
Andreas Gampe64bb4132014-11-22 00:35:09 +00001424 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
1425 bool useQuickReject) {
Chris Craik8afd0f22014-08-21 17:41:57 -07001426 if (mRenderNode->isRenderable() && !mSkipInOrderDraw) {
Chris Craika7090e02014-06-20 16:01:00 -07001427 mRenderNode->defer(deferStruct, level + 1);
Chris Craikc3566d02013-02-04 16:16:33 -08001428 }
Chris Craikc3566d02013-02-04 16:16:33 -08001429 }
Chris Craik8afd0f22014-08-21 17:41:57 -07001430
Andreas Gampe64bb4132014-11-22 00:35:09 +00001431 virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level,
1432 bool useQuickReject) {
Chris Craik8afd0f22014-08-21 17:41:57 -07001433 if (mRenderNode->isRenderable() && !mSkipInOrderDraw) {
Chris Craika7090e02014-06-20 16:01:00 -07001434 mRenderNode->replay(replayStruct, level + 1);
Chris Craikff785832013-03-08 13:12:16 -08001435 }
1436 }
Chris Craik2af46352012-11-26 18:30:17 -08001437
Andreas Gampe64bb4132014-11-22 00:35:09 +00001438 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik80d49022014-06-20 15:03:43 -07001439 LOG_ALWAYS_FATAL("should not be called, because replay() is overridden");
Chris Craika08f95c2013-03-15 17:24:33 -07001440 }
Chris Craikff785832013-03-08 13:12:16 -08001441
Chris Craikc5493fb2013-06-19 16:58:58 -07001442 virtual void output(int level, uint32_t logFlags) const {
Chris Craik8afd0f22014-08-21 17:41:57 -07001443 OP_LOG("Draw RenderNode %p %s, flags %#x", mRenderNode, mRenderNode->getName(), mFlags);
Chris Craika7090e02014-06-20 16:01:00 -07001444 if (mRenderNode && (logFlags & kOpLogFlag_Recurse)) {
1445 mRenderNode->output(level + 1);
Chris Craik2af46352012-11-26 18:30:17 -08001446 }
1447 }
1448
Chris Craika7090e02014-06-20 16:01:00 -07001449 virtual const char* name() { return "DrawRenderNode"; }
Chris Craik2af46352012-11-26 18:30:17 -08001450
Chris Craika7090e02014-06-20 16:01:00 -07001451 RenderNode* renderNode() { return mRenderNode; }
John Reck087bc0c2014-04-04 16:20:08 -07001452
Chris Craik2af46352012-11-26 18:30:17 -08001453private:
Chris Craika7090e02014-06-20 16:01:00 -07001454 RenderNode* mRenderNode;
Chris Craikf57776b2013-10-25 18:30:17 -07001455 const int mFlags;
1456
1457 ///////////////////////////
Chris Craika7090e02014-06-20 16:01:00 -07001458 // Properties below are used by RenderNode::computeOrderingImpl() and issueOperations()
Chris Craikf57776b2013-10-25 18:30:17 -07001459 ///////////////////////////
1460 /**
1461 * Records transform vs parent, used for computing total transform without rerunning DL contents
1462 */
1463 const mat4 mTransformFromParent;
1464
1465 /**
Chris Craika7090e02014-06-20 16:01:00 -07001466 * Holds the transformation between the projection surface ViewGroup and this RenderNode
Chris Craikb79a3e32014-03-11 12:20:17 -07001467 * drawing instance. Represents any translations / transformations done within the drawing of
1468 * the compositing ancestor ViewGroup's draw, before the draw of the View represented by this
1469 * DisplayList draw instance.
Chris Craikf57776b2013-10-25 18:30:17 -07001470 *
Chris Craika7090e02014-06-20 16:01:00 -07001471 * Note: doesn't include transformation within the RenderNode, or its properties.
Chris Craikf57776b2013-10-25 18:30:17 -07001472 */
Chris Craikf533e942014-01-14 22:35:37 -08001473 mat4 mTransformFromCompositingAncestor;
Chris Craikf57776b2013-10-25 18:30:17 -07001474 bool mSkipInOrderDraw;
1475};
1476
1477/**
Chris Craik024433f2014-03-26 13:19:14 -07001478 * Not a canvas operation, used only by 3d / z ordering logic in RenderNode::iterate()
Chris Craikf57776b2013-10-25 18:30:17 -07001479 */
1480class DrawShadowOp : public DrawOp {
1481public:
Chris Craik024433f2014-03-26 13:19:14 -07001482 DrawShadowOp(const mat4& transformXY, const mat4& transformZ,
Chris Craik74669862014-08-07 17:27:30 -07001483 float casterAlpha, const SkPath* casterOutline)
1484 : DrawOp(NULL)
1485 , mTransformXY(transformXY)
1486 , mTransformZ(transformZ)
1487 , mCasterAlpha(casterAlpha)
1488 , mCasterOutline(casterOutline) {
Chris Craik61317322014-05-21 13:03:52 -07001489 }
Chris Craikf57776b2013-10-25 18:30:17 -07001490
Andreas Gampe64bb4132014-11-22 00:35:09 +00001491 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
Chris Craik05f3d6e2014-06-02 16:27:04 -07001492 const DeferredDisplayState& state) {
1493 renderer.getCaches().tessellationCache.precacheShadows(&state.mMatrix,
Chris Craik74669862014-08-07 17:27:30 -07001494 renderer.getLocalClipBounds(), isCasterOpaque(), mCasterOutline,
Chris Craik05f3d6e2014-06-02 16:27:04 -07001495 &mTransformXY, &mTransformZ, renderer.getLightCenter(), renderer.getLightRadius());
1496 }
1497
Andreas Gampe64bb4132014-11-22 00:35:09 +00001498 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik05f3d6e2014-06-02 16:27:04 -07001499 TessellationCache::vertexBuffer_pair_t buffers;
Chris Craikc3e75f92014-08-27 15:34:52 -07001500 Matrix4 drawTransform(*(renderer.currentTransform()));
Chris Craik05f3d6e2014-06-02 16:27:04 -07001501 renderer.getCaches().tessellationCache.getShadowBuffers(&drawTransform,
Chris Craik74669862014-08-07 17:27:30 -07001502 renderer.getLocalClipBounds(), isCasterOpaque(), mCasterOutline,
Chris Craik05f3d6e2014-06-02 16:27:04 -07001503 &mTransformXY, &mTransformZ, renderer.getLightCenter(), renderer.getLightRadius(),
1504 buffers);
1505
Tom Hudson107843d2014-09-08 11:26:26 -04001506 renderer.drawShadow(mCasterAlpha, buffers.first, buffers.second);
Chris Craikf57776b2013-10-25 18:30:17 -07001507 }
1508
Andreas Gampe64bb4132014-11-22 00:35:09 +00001509 virtual void output(int level, uint32_t logFlags) const {
Chris Craik61317322014-05-21 13:03:52 -07001510 OP_LOGS("DrawShadow");
Chris Craikf57776b2013-10-25 18:30:17 -07001511 }
1512
1513 virtual const char* name() { return "DrawShadow"; }
1514
1515private:
Chris Craikaf4d04c2014-07-29 12:50:14 -07001516 bool isCasterOpaque() { return mCasterAlpha >= 1.0f; }
Chris Craik05f3d6e2014-06-02 16:27:04 -07001517
Chris Craikb79a3e32014-03-11 12:20:17 -07001518 const mat4 mTransformXY;
1519 const mat4 mTransformZ;
Chris Craik024433f2014-03-26 13:19:14 -07001520 const float mCasterAlpha;
Chris Craik74669862014-08-07 17:27:30 -07001521 const SkPath* mCasterOutline;
Chris Craik2af46352012-11-26 18:30:17 -08001522};
1523
1524class DrawLayerOp : public DrawOp {
1525public:
Chris Craika08f95c2013-03-15 17:24:33 -07001526 DrawLayerOp(Layer* layer, float x, float y)
Chris Craikf57776b2013-10-25 18:30:17 -07001527 : DrawOp(NULL), mLayer(layer), mX(x), mY(y) {}
Chris Craik2af46352012-11-26 18:30:17 -08001528
Andreas Gampe64bb4132014-11-22 00:35:09 +00001529 virtual void applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Tom Hudson107843d2014-09-08 11:26:26 -04001530 renderer.drawLayer(mLayer, mX, mY);
Chris Craik2af46352012-11-26 18:30:17 -08001531 }
1532
Andreas Gampe64bb4132014-11-22 00:35:09 +00001533 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001534 OP_LOG("Draw Layer %p at %f %f", mLayer, mX, mY);
1535 }
1536
1537 virtual const char* name() { return "DrawLayer"; }
1538
1539private:
1540 Layer* mLayer;
1541 float mX;
1542 float mY;
1543};
1544
1545}; // namespace uirenderer
1546}; // namespace android
1547
1548#endif // ANDROID_HWUI_DISPLAY_OPERATION_H