blob: 233f3f0a31b8a14816668280a85eb7ea253d94e2 [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 Craik8c271ca2014-03-25 10:33:01 -070024#include <SkPath.h>
25#include <SkPathOps.h>
Chris Craik2af46352012-11-26 18:30:17 -080026#include <SkXfermode.h>
27
Chris Craik0776a602013-02-14 15:36:01 -080028#include <private/hwui/DrawGlInfo.h>
29
Chris Craik2af46352012-11-26 18:30:17 -080030#include "OpenGLRenderer.h"
Romain Guy3b748a42013-04-17 18:54:38 -070031#include "AssetAtlas.h"
Chris Craikc3566d02013-02-04 16:16:33 -080032#include "DeferredDisplayList.h"
Chris Craik2af46352012-11-26 18:30:17 -080033#include "DisplayListRenderer.h"
Romain Guy3b748a42013-04-17 18:54:38 -070034#include "UvMapper.h"
Chris Craik2af46352012-11-26 18:30:17 -080035#include "utils/LinearAllocator.h"
36
37#define CRASH() do { \
Romain Guy5216c3b2013-06-14 16:31:37 -070038 *(int *)(uintptr_t) 0xbbadbeef = 0; \
Chris Craik2af46352012-11-26 18:30:17 -080039 ((void(*)())0)(); /* More reliable, but doesn't say BBADBEEF */ \
40} while(false)
41
Chris Craik2af46352012-11-26 18:30:17 -080042// Use OP_LOG for logging with arglist, OP_LOGS if just printing char*
Chris Craik28ce94a2013-05-31 11:38:03 -070043#define OP_LOGS(s) OP_LOG("%s", (s))
Chris Craik3dc553b2013-02-04 12:45:13 -080044#define OP_LOG(s, ...) ALOGD( "%*s" s, level * 2, "", __VA_ARGS__ )
Chris Craik2af46352012-11-26 18:30:17 -080045
Chris Craik2af46352012-11-26 18:30:17 -080046namespace android {
47namespace uirenderer {
48
49/**
50 * Structure for storing canvas operations when they are recorded into a DisplayList, so that they
51 * may be replayed to an OpenGLRenderer.
52 *
53 * To avoid individual memory allocations, DisplayListOps may only be allocated into a
54 * LinearAllocator's managed memory buffers. Each pointer held by a DisplayListOp is either a
55 * pointer into memory also allocated in the LinearAllocator (mostly for text and float buffers) or
56 * references a externally refcounted object (Sk... and Skia... objects). ~DisplayListOp() is
57 * never called as LinearAllocators are simply discarded, so no memory management should be done in
58 * this class.
59 */
60class DisplayListOp {
61public:
62 // These objects should always be allocated with a LinearAllocator, and never destroyed/deleted.
63 // standard new() intentionally not implemented, and delete/deconstructor should never be used.
64 virtual ~DisplayListOp() { CRASH(); }
65 static void operator delete(void* ptr) { CRASH(); }
66 /** static void* operator new(size_t size); PURPOSELY OMITTED **/
67 static void* operator new(size_t size, LinearAllocator& allocator) {
68 return allocator.alloc(size);
69 }
70
71 enum OpLogFlag {
72 kOpLogFlag_Recurse = 0x1,
73 kOpLogFlag_JSON = 0x2 // TODO: add?
74 };
75
Chet Haasedd671592013-04-19 14:54:34 -070076 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
77 bool useQuickReject) = 0;
Chris Craikc3566d02013-02-04 16:16:33 -080078
Chet Haasedd671592013-04-19 14:54:34 -070079 virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level,
80 bool useQuickReject) = 0;
Chris Craikff785832013-03-08 13:12:16 -080081
Chris Craikc5493fb2013-06-19 16:58:58 -070082 virtual void output(int level, uint32_t logFlags = 0) const = 0;
Chris Craik2af46352012-11-26 18:30:17 -080083
84 // NOTE: it would be nice to declare constants and overriding the implementation in each op to
85 // point at the constants, but that seems to require a .cpp file
86 virtual const char* name() = 0;
87};
88
89class StateOp : public DisplayListOp {
90public:
91 StateOp() {};
92
93 virtual ~StateOp() {}
94
Chet Haasedd671592013-04-19 14:54:34 -070095 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
96 bool useQuickReject) {
Chris Craikff785832013-03-08 13:12:16 -080097 // default behavior only affects immediate, deferrable state, issue directly to renderer
98 applyState(deferStruct.mRenderer, saveCount);
99 }
100
Chris Craikc3566d02013-02-04 16:16:33 -0800101 /**
102 * State operations are applied directly to the renderer, but can cause the deferred drawing op
103 * list to flush
104 */
Chet Haasedd671592013-04-19 14:54:34 -0700105 virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level,
106 bool useQuickReject) {
Chris Craikff785832013-03-08 13:12:16 -0800107 applyState(replayStruct.mRenderer, saveCount);
Chris Craikc3566d02013-02-04 16:16:33 -0800108 }
109
Chris Craik7273daa2013-03-28 11:25:24 -0700110 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const = 0;
Chris Craik2af46352012-11-26 18:30:17 -0800111};
112
113class DrawOp : public DisplayListOp {
Chris Craik527a3aa2013-03-04 10:19:31 -0800114friend class MergingDrawBatch;
Chris Craik2af46352012-11-26 18:30:17 -0800115public:
Chris Craikd218a922014-01-02 17:13:34 -0800116 DrawOp(const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -0800117 : mPaint(paint), mQuickRejected(false) {}
118
Chet Haasedd671592013-04-19 14:54:34 -0700119 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
120 bool useQuickReject) {
121 if (mQuickRejected && CC_LIKELY(useQuickReject)) {
Chris Craikff785832013-03-08 13:12:16 -0800122 return;
Chris Craikc3566d02013-02-04 16:16:33 -0800123 }
124
Chris Craikff785832013-03-08 13:12:16 -0800125 deferStruct.mDeferredList.addDrawOp(deferStruct.mRenderer, this);
Chris Craikc3566d02013-02-04 16:16:33 -0800126 }
127
Chet Haasedd671592013-04-19 14:54:34 -0700128 virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level,
129 bool useQuickReject) {
130 if (mQuickRejected && CC_LIKELY(useQuickReject)) {
Chris Craikff785832013-03-08 13:12:16 -0800131 return;
132 }
133
Chris Craik527a3aa2013-03-04 10:19:31 -0800134 replayStruct.mDrawGlStatus |= applyDraw(replayStruct.mRenderer, replayStruct.mDirty);
Chris Craikff785832013-03-08 13:12:16 -0800135 }
136
Chris Craik527a3aa2013-03-04 10:19:31 -0800137 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) = 0;
Chris Craik2af46352012-11-26 18:30:17 -0800138
Chris Craik527a3aa2013-03-04 10:19:31 -0800139 /**
140 * Draw multiple instances of an operation, must be overidden for operations that merge
141 *
142 * Currently guarantees certain similarities between ops (see MergingDrawBatch::canMergeWith),
143 * and pure translation transformations. Other guarantees of similarity should be enforced by
144 * reducing which operations are tagged as mergeable.
145 */
146 virtual status_t multiDraw(OpenGLRenderer& renderer, Rect& dirty,
Chris Craikc1c5f082013-09-11 16:23:37 -0700147 const Vector<OpStatePair>& ops, const Rect& bounds) {
Chris Craik527a3aa2013-03-04 10:19:31 -0800148 status_t status = DrawGlInfo::kStatusDone;
149 for (unsigned int i = 0; i < ops.size(); i++) {
Chris Craikc1c5f082013-09-11 16:23:37 -0700150 renderer.restoreDisplayState(*(ops[i].state), true);
151 status |= ops[i].op->applyDraw(renderer, dirty);
Chris Craik527a3aa2013-03-04 10:19:31 -0800152 }
153 return status;
154 }
155
Chris Craik28ce94a2013-05-31 11:38:03 -0700156 /**
Chris Craik527a3aa2013-03-04 10:19:31 -0800157 * When this method is invoked the state field is initialized to have the
158 * final rendering state. We can thus use it to process data as it will be
159 * used at draw time.
160 *
161 * Additionally, this method allows subclasses to provide defer-time preferences for batching
162 * and merging.
163 *
Chris Craik28ce94a2013-05-31 11:38:03 -0700164 * if a subclass can set deferInfo.mergeable to true, it should implement multiDraw()
Chris Craik527a3aa2013-03-04 10:19:31 -0800165 */
Chris Craikc1c5f082013-09-11 16:23:37 -0700166 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
167 const DeferredDisplayState& state) {}
Romain Guy0f667532013-03-01 14:31:04 -0800168
Chris Craik5e49b302013-07-30 19:05:20 -0700169 /**
170 * Query the conservative, local bounds (unmapped) bounds of the op.
171 *
172 * returns true if bounds exist
173 */
Chris Craikc1c5f082013-09-11 16:23:37 -0700174 virtual bool getLocalBounds(const DrawModifiers& drawModifiers, Rect& localBounds) {
175 return false;
176 }
Chris Craik2af46352012-11-26 18:30:17 -0800177
178 // TODO: better refine localbounds usage
179 void setQuickRejected(bool quickRejected) { mQuickRejected = quickRejected; }
180 bool getQuickRejected() { return mQuickRejected; }
181
Chris Craikc1c5f082013-09-11 16:23:37 -0700182 inline int getPaintAlpha() const {
Chris Craik527a3aa2013-03-04 10:19:31 -0800183 return OpenGLRenderer::getAlphaDirect(mPaint);
Chris Craikc3566d02013-02-04 16:16:33 -0800184 }
185
Derek Sollenbergerc29a0a42014-03-31 13:52:39 -0400186 virtual bool hasTextShadow() const {
187 return false;
188 }
189
Chris Craik527a3aa2013-03-04 10:19:31 -0800190 inline float strokeWidthOutset() {
Chris Craikf0a59072013-11-19 18:00:46 -0800191 // since anything AA stroke with less than 1.0 pixel width is drawn with an alpha-reduced
192 // 1.0 stroke, treat 1.0 as minimum.
193
194 // TODO: it would be nice if this could take scale into account, but scale isn't stable
195 // since higher levels of the view hierarchy can change scale out from underneath it.
196 return fmaxf(mPaint->getStrokeWidth(), 1) * 0.5f;
Chris Craike7c69c62013-04-03 09:55:48 -0700197 }
Chris Craikc3566d02013-02-04 16:16:33 -0800198
Chris Craik2af46352012-11-26 18:30:17 -0800199protected:
Chris Craikd218a922014-01-02 17:13:34 -0800200 const SkPaint* getPaint(OpenGLRenderer& renderer) {
Chris Craika08f95c2013-03-15 17:24:33 -0700201 return renderer.filterPaint(mPaint);
Chris Craik2af46352012-11-26 18:30:17 -0800202 }
203
Chris Craik28ce94a2013-05-31 11:38:03 -0700204 // Helper method for determining op opaqueness. Assumes op fills its bounds in local
205 // coordinates, and that paint's alpha is used
Chris Craikc1c5f082013-09-11 16:23:37 -0700206 inline bool isOpaqueOverBounds(const DeferredDisplayState& state) {
Chris Craik28ce94a2013-05-31 11:38:03 -0700207 // ensure that local bounds cover mapped bounds
208 if (!state.mMatrix.isSimple()) return false;
209
210 // check state/paint for transparency
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400211 if (mPaint) {
212 if (mPaint->getShader() && !mPaint->getShader()->isOpaque()) {
213 return false;
214 }
215 if (mPaint->getAlpha() != 0xFF) {
216 return false;
217 }
218 }
219
220 if (state.mAlpha != 1.0f) return false;
Chris Craik28ce94a2013-05-31 11:38:03 -0700221
222 SkXfermode::Mode mode = OpenGLRenderer::getXfermodeDirect(mPaint);
223 return (mode == SkXfermode::kSrcOver_Mode ||
224 mode == SkXfermode::kSrc_Mode);
225
226 }
227
Chris Craikd218a922014-01-02 17:13:34 -0800228 const SkPaint* mPaint; // should be accessed via getPaint() when applying
Chris Craik2af46352012-11-26 18:30:17 -0800229 bool mQuickRejected;
230};
231
232class DrawBoundedOp : public DrawOp {
233public:
Chris Craikd218a922014-01-02 17:13:34 -0800234 DrawBoundedOp(float left, float top, float right, float bottom, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -0800235 : DrawOp(paint), mLocalBounds(left, top, right, bottom) {}
236
Chris Craikd218a922014-01-02 17:13:34 -0800237 DrawBoundedOp(const Rect& localBounds, const SkPaint* paint)
Chris Craik41541822013-05-03 16:35:54 -0700238 : DrawOp(paint), mLocalBounds(localBounds) {}
239
Chris Craik5d116762013-02-19 17:49:31 -0800240 // Calculates bounds as smallest rect encompassing all points
241 // NOTE: requires at least 1 vertex, and doesn't account for stroke size (should be handled in
242 // subclass' constructor)
Chris Craikd218a922014-01-02 17:13:34 -0800243 DrawBoundedOp(const float* points, int count, const SkPaint* paint)
Chris Craik5d116762013-02-19 17:49:31 -0800244 : DrawOp(paint), mLocalBounds(points[0], points[1], points[0], points[1]) {
245 for (int i = 2; i < count; i += 2) {
246 mLocalBounds.left = fminf(mLocalBounds.left, points[i]);
247 mLocalBounds.right = fmaxf(mLocalBounds.right, points[i]);
248 mLocalBounds.top = fminf(mLocalBounds.top, points[i + 1]);
249 mLocalBounds.bottom = fmaxf(mLocalBounds.bottom, points[i + 1]);
250 }
251 }
252
253 // default empty constructor for bounds, to be overridden in child constructor body
Chris Craikd218a922014-01-02 17:13:34 -0800254 DrawBoundedOp(const SkPaint* paint): DrawOp(paint) { }
Chris Craik2af46352012-11-26 18:30:17 -0800255
Chris Craikc1c5f082013-09-11 16:23:37 -0700256 bool getLocalBounds(const DrawModifiers& drawModifiers, Rect& localBounds) {
Chris Craik2af46352012-11-26 18:30:17 -0800257 localBounds.set(mLocalBounds);
Derek Sollenbergerc29a0a42014-03-31 13:52:39 -0400258 OpenGLRenderer::TextShadow textShadow;
259 if (OpenGLRenderer::getTextShadow(mPaint, &textShadow)) {
Romain Guy9b5a1a22013-08-09 14:06:29 -0700260 Rect shadow(mLocalBounds);
Derek Sollenbergerc29a0a42014-03-31 13:52:39 -0400261 shadow.translate(textShadow.dx, textShadow.dx);
262 shadow.outset(textShadow.radius);
Romain Guy9b5a1a22013-08-09 14:06:29 -0700263 localBounds.unionWith(shadow);
264 }
Chris Craik2af46352012-11-26 18:30:17 -0800265 return true;
266 }
267
268protected:
269 Rect mLocalBounds; // displayed area in LOCAL coord. doesn't incorporate stroke, so check paint
270};
271
272///////////////////////////////////////////////////////////////////////////////
273// STATE OPERATIONS - these may affect the state of the canvas/renderer, but do
274// not directly draw or alter output
275///////////////////////////////////////////////////////////////////////////////
276
277class SaveOp : public StateOp {
278public:
279 SaveOp(int flags)
280 : mFlags(flags) {}
281
Chet Haasedd671592013-04-19 14:54:34 -0700282 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
283 bool useQuickReject) {
Chris Craikff785832013-03-08 13:12:16 -0800284 int newSaveCount = deferStruct.mRenderer.save(mFlags);
285 deferStruct.mDeferredList.addSave(deferStruct.mRenderer, this, newSaveCount);
286 }
287
Chris Craik7273daa2013-03-28 11:25:24 -0700288 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800289 renderer.save(mFlags);
290 }
291
Chris Craikc5493fb2013-06-19 16:58:58 -0700292 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800293 OP_LOG("Save flags %x", mFlags);
294 }
295
296 virtual const char* name() { return "Save"; }
297
Chris Craikff785832013-03-08 13:12:16 -0800298 int getFlags() const { return mFlags; }
Chris Craik2af46352012-11-26 18:30:17 -0800299private:
300 int mFlags;
301};
302
303class RestoreToCountOp : public StateOp {
304public:
305 RestoreToCountOp(int count)
306 : mCount(count) {}
307
Chet Haasedd671592013-04-19 14:54:34 -0700308 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
309 bool useQuickReject) {
Chris Craik7273daa2013-03-28 11:25:24 -0700310 deferStruct.mDeferredList.addRestoreToCount(deferStruct.mRenderer,
311 this, saveCount + mCount);
Chris Craikff785832013-03-08 13:12:16 -0800312 deferStruct.mRenderer.restoreToCount(saveCount + mCount);
Chris Craik2af46352012-11-26 18:30:17 -0800313 }
314
Chris Craik7273daa2013-03-28 11:25:24 -0700315 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craikff785832013-03-08 13:12:16 -0800316 renderer.restoreToCount(saveCount + mCount);
317 }
318
Chris Craikc5493fb2013-06-19 16:58:58 -0700319 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800320 OP_LOG("Restore to count %d", mCount);
321 }
322
323 virtual const char* name() { return "RestoreToCount"; }
324
325private:
326 int mCount;
327};
328
329class SaveLayerOp : public StateOp {
330public:
Derek Sollenbergerd44fbe52014-02-05 16:47:00 -0500331 SaveLayerOp(float left, float top, float right, float bottom, int alpha, int flags)
Chris Craik3f085422014-04-15 16:18:08 -0700332 : mArea(left, top, right, bottom)
333 , mPaint(&mCachedPaint)
334 , mFlags(flags)
335 , mConvexMask(NULL) {
Derek Sollenbergerd44fbe52014-02-05 16:47:00 -0500336 mCachedPaint.setAlpha(alpha);
337 }
338
339 SaveLayerOp(float left, float top, float right, float bottom, const SkPaint* paint, int flags)
Chris Craik3f085422014-04-15 16:18:08 -0700340 : mArea(left, top, right, bottom)
341 , mPaint(paint)
342 , mFlags(flags)
343 , mConvexMask(NULL)
344 {}
Chris Craikff785832013-03-08 13:12:16 -0800345
Chet Haasedd671592013-04-19 14:54:34 -0700346 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
347 bool useQuickReject) {
Chris Craikff785832013-03-08 13:12:16 -0800348 // NOTE: don't bother with actual saveLayer, instead issuing it at flush time
Chris Craikd90144d2013-03-19 15:03:48 -0700349 int newSaveCount = deferStruct.mRenderer.getSaveCount();
Chris Craikff785832013-03-08 13:12:16 -0800350 deferStruct.mDeferredList.addSaveLayer(deferStruct.mRenderer, this, newSaveCount);
Chris Craikd90144d2013-03-19 15:03:48 -0700351
352 // NOTE: don't issue full saveLayer, since that has side effects/is costly. instead just
353 // setup the snapshot for deferral, and re-issue the op at flush time
354 deferStruct.mRenderer.saveLayerDeferred(mArea.left, mArea.top, mArea.right, mArea.bottom,
Derek Sollenbergerd44fbe52014-02-05 16:47:00 -0500355 mPaint, mFlags);
Chris Craikff785832013-03-08 13:12:16 -0800356 }
Chris Craik2af46352012-11-26 18:30:17 -0800357
Chris Craik7273daa2013-03-28 11:25:24 -0700358 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik3f085422014-04-15 16:18:08 -0700359 renderer.saveLayer(mArea.left, mArea.top, mArea.right, mArea.bottom,
360 mPaint, mFlags, mConvexMask);
Chris Craik2af46352012-11-26 18:30:17 -0800361 }
362
Chris Craikc5493fb2013-06-19 16:58:58 -0700363 virtual void output(int level, uint32_t logFlags) const {
Chris Craikff785832013-03-08 13:12:16 -0800364 OP_LOG("SaveLayer%s of area " RECT_STRING,
365 (isSaveLayerAlpha() ? "Alpha" : ""),RECT_ARGS(mArea));
Chris Craik2af46352012-11-26 18:30:17 -0800366 }
367
Chris Craikff785832013-03-08 13:12:16 -0800368 virtual const char* name() { return isSaveLayerAlpha() ? "SaveLayerAlpha" : "SaveLayer"; }
369
370 int getFlags() { return mFlags; }
Chris Craik2af46352012-11-26 18:30:17 -0800371
Chris Craik3f085422014-04-15 16:18:08 -0700372 // Called to make SaveLayerOp clip to the provided mask when drawing back/restored
373 void setMask(const SkPath* convexMask) {
374 mConvexMask = convexMask;
375 }
376
Chris Craik2af46352012-11-26 18:30:17 -0800377private:
Derek Sollenbergerd44fbe52014-02-05 16:47:00 -0500378 bool isSaveLayerAlpha() const {
379 SkXfermode::Mode mode = OpenGLRenderer::getXfermodeDirect(mPaint);
380 int alpha = OpenGLRenderer::getAlphaDirect(mPaint);
381 return alpha < 255 && mode == SkXfermode::kSrcOver_Mode;
Chris Craik2af46352012-11-26 18:30:17 -0800382 }
383
Chris Craik2af46352012-11-26 18:30:17 -0800384 Rect mArea;
Derek Sollenbergerd44fbe52014-02-05 16:47:00 -0500385 const SkPaint* mPaint;
386 SkPaint mCachedPaint;
Chris Craik2af46352012-11-26 18:30:17 -0800387 int mFlags;
Chris Craik3f085422014-04-15 16:18:08 -0700388
389 // Convex path, points at data in RenderNode, valid for the duration of the frame only
390 // Only used for masking the SaveLayer which wraps projected RenderNodes
391 const SkPath* mConvexMask;
Chris Craik2af46352012-11-26 18:30:17 -0800392};
393
394class TranslateOp : public StateOp {
395public:
396 TranslateOp(float dx, float dy)
397 : mDx(dx), mDy(dy) {}
398
Chris Craik7273daa2013-03-28 11:25:24 -0700399 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800400 renderer.translate(mDx, mDy);
401 }
402
Chris Craikc5493fb2013-06-19 16:58:58 -0700403 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800404 OP_LOG("Translate by %f %f", mDx, mDy);
405 }
406
407 virtual const char* name() { return "Translate"; }
408
409private:
410 float mDx;
411 float mDy;
412};
413
414class RotateOp : public StateOp {
415public:
416 RotateOp(float degrees)
417 : mDegrees(degrees) {}
418
Chris Craik7273daa2013-03-28 11:25:24 -0700419 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800420 renderer.rotate(mDegrees);
421 }
422
Chris Craikc5493fb2013-06-19 16:58:58 -0700423 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800424 OP_LOG("Rotate by %f degrees", mDegrees);
425 }
426
427 virtual const char* name() { return "Rotate"; }
428
429private:
430 float mDegrees;
431};
432
433class ScaleOp : public StateOp {
434public:
435 ScaleOp(float sx, float sy)
436 : mSx(sx), mSy(sy) {}
437
Chris Craik7273daa2013-03-28 11:25:24 -0700438 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800439 renderer.scale(mSx, mSy);
440 }
441
Chris Craikc5493fb2013-06-19 16:58:58 -0700442 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800443 OP_LOG("Scale by %f %f", mSx, mSy);
444 }
445
446 virtual const char* name() { return "Scale"; }
447
448private:
449 float mSx;
450 float mSy;
451};
452
453class SkewOp : public StateOp {
454public:
455 SkewOp(float sx, float sy)
456 : mSx(sx), mSy(sy) {}
457
Chris Craik7273daa2013-03-28 11:25:24 -0700458 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800459 renderer.skew(mSx, mSy);
460 }
461
Chris Craikc5493fb2013-06-19 16:58:58 -0700462 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800463 OP_LOG("Skew by %f %f", mSx, mSy);
464 }
465
466 virtual const char* name() { return "Skew"; }
467
468private:
469 float mSx;
470 float mSy;
471};
472
473class SetMatrixOp : public StateOp {
474public:
Derek Sollenberger13908822013-12-10 12:28:58 -0500475 SetMatrixOp(const SkMatrix& matrix)
Chris Craik2af46352012-11-26 18:30:17 -0800476 : mMatrix(matrix) {}
477
Chris Craik7273daa2013-03-28 11:25:24 -0700478 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800479 renderer.setMatrix(mMatrix);
480 }
481
Chris Craikc5493fb2013-06-19 16:58:58 -0700482 virtual void output(int level, uint32_t logFlags) const {
Derek Sollenberger13908822013-12-10 12:28:58 -0500483 if (mMatrix.isIdentity()) {
Romain Guy4e7b7722013-07-16 13:47:01 -0700484 OP_LOGS("SetMatrix (reset)");
Derek Sollenberger13908822013-12-10 12:28:58 -0500485 } else {
486 OP_LOG("SetMatrix " SK_MATRIX_STRING, SK_MATRIX_ARGS(&mMatrix));
Romain Guy4e7b7722013-07-16 13:47:01 -0700487 }
Chris Craik2af46352012-11-26 18:30:17 -0800488 }
489
490 virtual const char* name() { return "SetMatrix"; }
491
492private:
Derek Sollenberger13908822013-12-10 12:28:58 -0500493 const SkMatrix mMatrix;
Chris Craik2af46352012-11-26 18:30:17 -0800494};
495
496class ConcatMatrixOp : public StateOp {
497public:
Derek Sollenberger13908822013-12-10 12:28:58 -0500498 ConcatMatrixOp(const SkMatrix& matrix)
Chris Craik2af46352012-11-26 18:30:17 -0800499 : mMatrix(matrix) {}
500
Chris Craik7273daa2013-03-28 11:25:24 -0700501 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800502 renderer.concatMatrix(mMatrix);
503 }
504
Chris Craikc5493fb2013-06-19 16:58:58 -0700505 virtual void output(int level, uint32_t logFlags) const {
Derek Sollenberger13908822013-12-10 12:28:58 -0500506 OP_LOG("ConcatMatrix " SK_MATRIX_STRING, SK_MATRIX_ARGS(&mMatrix));
Chris Craik2af46352012-11-26 18:30:17 -0800507 }
508
509 virtual const char* name() { return "ConcatMatrix"; }
510
511private:
Derek Sollenberger13908822013-12-10 12:28:58 -0500512 const SkMatrix mMatrix;
Chris Craik2af46352012-11-26 18:30:17 -0800513};
514
Chris Craikff785832013-03-08 13:12:16 -0800515class ClipOp : public StateOp {
516public:
517 ClipOp(SkRegion::Op op) : mOp(op) {}
518
Chet Haasedd671592013-04-19 14:54:34 -0700519 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
520 bool useQuickReject) {
Chris Craikff785832013-03-08 13:12:16 -0800521 // NOTE: must defer op BEFORE applying state, since it may read clip
522 deferStruct.mDeferredList.addClip(deferStruct.mRenderer, this);
523
524 // TODO: Can we avoid applying complex clips at defer time?
525 applyState(deferStruct.mRenderer, saveCount);
526 }
527
528 bool canCauseComplexClip() {
529 return ((mOp != SkRegion::kIntersect_Op) && (mOp != SkRegion::kReplace_Op)) || !isRect();
530 }
531
532protected:
Chris Craikff785832013-03-08 13:12:16 -0800533 virtual bool isRect() { return false; }
534
535 SkRegion::Op mOp;
536};
537
538class ClipRectOp : public ClipOp {
Chris Craik2af46352012-11-26 18:30:17 -0800539public:
540 ClipRectOp(float left, float top, float right, float bottom, SkRegion::Op op)
Chris Craikff785832013-03-08 13:12:16 -0800541 : ClipOp(op), mArea(left, top, right, bottom) {}
Chris Craik2af46352012-11-26 18:30:17 -0800542
Chris Craik7273daa2013-03-28 11:25:24 -0700543 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800544 renderer.clipRect(mArea.left, mArea.top, mArea.right, mArea.bottom, mOp);
545 }
546
Chris Craikc5493fb2013-06-19 16:58:58 -0700547 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800548 OP_LOG("ClipRect " RECT_STRING, RECT_ARGS(mArea));
549 }
550
551 virtual const char* name() { return "ClipRect"; }
552
Chris Craikff785832013-03-08 13:12:16 -0800553protected:
554 virtual bool isRect() { return true; }
Chris Craikb98a0162013-02-21 11:30:22 -0800555
Chris Craik2af46352012-11-26 18:30:17 -0800556private:
557 Rect mArea;
Chris Craik2af46352012-11-26 18:30:17 -0800558};
559
Chris Craikff785832013-03-08 13:12:16 -0800560class ClipPathOp : public ClipOp {
Chris Craik2af46352012-11-26 18:30:17 -0800561public:
Chris Craikd218a922014-01-02 17:13:34 -0800562 ClipPathOp(const SkPath* path, SkRegion::Op op)
Chris Craikff785832013-03-08 13:12:16 -0800563 : ClipOp(op), mPath(path) {}
Chris Craik2af46352012-11-26 18:30:17 -0800564
Chris Craik7273daa2013-03-28 11:25:24 -0700565 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800566 renderer.clipPath(mPath, mOp);
567 }
568
Chris Craikc5493fb2013-06-19 16:58:58 -0700569 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800570 SkRect bounds = mPath->getBounds();
571 OP_LOG("ClipPath bounds " RECT_STRING,
572 bounds.left(), bounds.top(), bounds.right(), bounds.bottom());
573 }
574
575 virtual const char* name() { return "ClipPath"; }
576
577private:
Chris Craikd218a922014-01-02 17:13:34 -0800578 const SkPath* mPath;
Chris Craik2af46352012-11-26 18:30:17 -0800579};
580
Chris Craikff785832013-03-08 13:12:16 -0800581class ClipRegionOp : public ClipOp {
Chris Craik2af46352012-11-26 18:30:17 -0800582public:
Chris Craikd218a922014-01-02 17:13:34 -0800583 ClipRegionOp(const SkRegion* region, SkRegion::Op op)
Chris Craikff785832013-03-08 13:12:16 -0800584 : ClipOp(op), mRegion(region) {}
Chris Craik2af46352012-11-26 18:30:17 -0800585
Chris Craik7273daa2013-03-28 11:25:24 -0700586 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800587 renderer.clipRegion(mRegion, mOp);
588 }
589
Chris Craikc5493fb2013-06-19 16:58:58 -0700590 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800591 SkIRect bounds = mRegion->getBounds();
592 OP_LOG("ClipRegion bounds %d %d %d %d",
593 bounds.left(), bounds.top(), bounds.right(), bounds.bottom());
594 }
595
596 virtual const char* name() { return "ClipRegion"; }
597
598private:
Chris Craikd218a922014-01-02 17:13:34 -0800599 const SkRegion* mRegion;
Chris Craik2af46352012-11-26 18:30:17 -0800600};
601
Chris Craik2af46352012-11-26 18:30:17 -0800602class ResetPaintFilterOp : public StateOp {
603public:
Chris Craik7273daa2013-03-28 11:25:24 -0700604 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800605 renderer.resetPaintFilter();
606 }
607
Chris Craikc5493fb2013-06-19 16:58:58 -0700608 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800609 OP_LOGS("ResetPaintFilter");
610 }
611
612 virtual const char* name() { return "ResetPaintFilter"; }
613};
614
615class SetupPaintFilterOp : public StateOp {
616public:
617 SetupPaintFilterOp(int clearBits, int setBits)
618 : mClearBits(clearBits), mSetBits(setBits) {}
619
Chris Craik7273daa2013-03-28 11:25:24 -0700620 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800621 renderer.setupPaintFilter(mClearBits, mSetBits);
622 }
623
Chris Craikc5493fb2013-06-19 16:58:58 -0700624 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800625 OP_LOG("SetupPaintFilter, clear %#x, set %#x", mClearBits, mSetBits);
626 }
627
628 virtual const char* name() { return "SetupPaintFilter"; }
629
630private:
631 int mClearBits;
632 int mSetBits;
633};
634
Chris Craik2af46352012-11-26 18:30:17 -0800635///////////////////////////////////////////////////////////////////////////////
636// DRAW OPERATIONS - these are operations that can draw to the canvas's device
637///////////////////////////////////////////////////////////////////////////////
638
639class DrawBitmapOp : public DrawBoundedOp {
640public:
Chris Craikd218a922014-01-02 17:13:34 -0800641 DrawBitmapOp(const SkBitmap* bitmap, float left, float top, const SkPaint* paint)
Romain Guy3b748a42013-04-17 18:54:38 -0700642 : DrawBoundedOp(left, top, left + bitmap->width(), top + bitmap->height(), paint),
Romain Guy55b6f952013-06-27 15:27:09 -0700643 mBitmap(bitmap), mAtlas(Caches::getInstance().assetAtlas) {
644 mEntry = mAtlas.getEntry(bitmap);
645 if (mEntry) {
646 mEntryGenerationId = mAtlas.getGenerationId();
647 mUvMapper = mEntry->uvMapper;
648 }
Romain Guy3b748a42013-04-17 18:54:38 -0700649 }
Chris Craik2af46352012-11-26 18:30:17 -0800650
Chris Craik527a3aa2013-03-04 10:19:31 -0800651 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craika08f95c2013-03-15 17:24:33 -0700652 return renderer.drawBitmap(mBitmap, mLocalBounds.left, mLocalBounds.top,
653 getPaint(renderer));
Chris Craik2af46352012-11-26 18:30:17 -0800654 }
655
Romain Guy55b6f952013-06-27 15:27:09 -0700656 AssetAtlas::Entry* getAtlasEntry() {
657 // The atlas entry is stale, let's get a new one
658 if (mEntry && mEntryGenerationId != mAtlas.getGenerationId()) {
659 mEntryGenerationId = mAtlas.getGenerationId();
660 mEntry = mAtlas.getEntry(mBitmap);
661 mUvMapper = mEntry->uvMapper;
662 }
663 return mEntry;
664 }
665
Chris Craik527a3aa2013-03-04 10:19:31 -0800666#define SET_TEXTURE(ptr, posRect, offsetRect, texCoordsRect, xDim, yDim) \
667 TextureVertex::set(ptr++, posRect.xDim - offsetRect.left, posRect.yDim - offsetRect.top, \
668 texCoordsRect.xDim, texCoordsRect.yDim)
669
Romain Guy03c00b52013-06-20 18:30:28 -0700670 /**
671 * This multi-draw operation builds a mesh on the stack by generating a quad
672 * for each bitmap in the batch. This method is also responsible for dirtying
673 * the current layer, if any.
674 */
Chris Craik527a3aa2013-03-04 10:19:31 -0800675 virtual status_t multiDraw(OpenGLRenderer& renderer, Rect& dirty,
Chris Craikc1c5f082013-09-11 16:23:37 -0700676 const Vector<OpStatePair>& ops, const Rect& bounds) {
677 const DeferredDisplayState& firstState = *(ops[0].state);
678 renderer.restoreDisplayState(firstState, true); // restore all but the clip
679
Chris Craik527a3aa2013-03-04 10:19:31 -0800680 TextureVertex vertices[6 * ops.size()];
681 TextureVertex* vertex = &vertices[0];
682
Romain Guy03c00b52013-06-20 18:30:28 -0700683 const bool hasLayer = renderer.hasLayer();
Chris Craik996fe652013-09-20 17:13:18 -0700684 bool pureTranslate = true;
Romain Guy2db5e992013-05-21 15:29:59 -0700685
Romain Guy3b748a42013-04-17 18:54:38 -0700686 // TODO: manually handle rect clip for bitmaps by adjusting texCoords per op,
687 // and allowing them to be merged in getBatchId()
Chris Craik527a3aa2013-03-04 10:19:31 -0800688 for (unsigned int i = 0; i < ops.size(); i++) {
Chris Craikc1c5f082013-09-11 16:23:37 -0700689 const DeferredDisplayState& state = *(ops[i].state);
690 const Rect& opBounds = state.mBounds;
Romain Guy2db5e992013-05-21 15:29:59 -0700691 // When we reach multiDraw(), the matrix can be either
692 // pureTranslate or simple (translate and/or scale).
693 // If the matrix is not pureTranslate, then we have a scale
Chris Craik996fe652013-09-20 17:13:18 -0700694 pureTranslate &= state.mMatrix.isPureTranslate();
Romain Guy3b748a42013-04-17 18:54:38 -0700695
696 Rect texCoords(0, 0, 1, 1);
Chris Craikc1c5f082013-09-11 16:23:37 -0700697 ((DrawBitmapOp*) ops[i].op)->mUvMapper.map(texCoords);
Romain Guy3b748a42013-04-17 18:54:38 -0700698
Chris Craik527a3aa2013-03-04 10:19:31 -0800699 SET_TEXTURE(vertex, opBounds, bounds, texCoords, left, top);
700 SET_TEXTURE(vertex, opBounds, bounds, texCoords, right, top);
701 SET_TEXTURE(vertex, opBounds, bounds, texCoords, left, bottom);
702
703 SET_TEXTURE(vertex, opBounds, bounds, texCoords, left, bottom);
704 SET_TEXTURE(vertex, opBounds, bounds, texCoords, right, top);
705 SET_TEXTURE(vertex, opBounds, bounds, texCoords, right, bottom);
Romain Guy03c00b52013-06-20 18:30:28 -0700706
707 if (hasLayer) {
Chris Craikc1c5f082013-09-11 16:23:37 -0700708 renderer.dirtyLayer(opBounds.left, opBounds.top, opBounds.right, opBounds.bottom);
Romain Guy03c00b52013-06-20 18:30:28 -0700709 }
Chris Craik527a3aa2013-03-04 10:19:31 -0800710 }
711
Romain Guy55b6f952013-06-27 15:27:09 -0700712 return renderer.drawBitmaps(mBitmap, mEntry, ops.size(), &vertices[0],
Chris Craik996fe652013-09-20 17:13:18 -0700713 pureTranslate, bounds, mPaint);
Chris Craik527a3aa2013-03-04 10:19:31 -0800714 }
715
Chris Craikc5493fb2013-06-19 16:58:58 -0700716 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800717 OP_LOG("Draw bitmap %p at %f %f", mBitmap, mLocalBounds.left, mLocalBounds.top);
718 }
719
720 virtual const char* name() { return "DrawBitmap"; }
Chris Craik527a3aa2013-03-04 10:19:31 -0800721
Chris Craikc1c5f082013-09-11 16:23:37 -0700722 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
723 const DeferredDisplayState& state) {
Chris Craik28ce94a2013-05-31 11:38:03 -0700724 deferInfo.batchId = DeferredDisplayList::kOpBatch_Bitmap;
Chris Craikd965bc52013-09-16 14:47:13 -0700725 deferInfo.mergeId = getAtlasEntry() ?
726 (mergeid_t) mEntry->getMergeId() : (mergeid_t) mBitmap;
Romain Guy2db5e992013-05-21 15:29:59 -0700727
Chris Craikd965bc52013-09-16 14:47:13 -0700728 // Don't merge non-simply transformed or neg scale ops, SET_TEXTURE doesn't handle rotation
Chris Craik28ce94a2013-05-31 11:38:03 -0700729 // Don't merge A8 bitmaps - the paint's color isn't compared by mergeId, or in
730 // MergingDrawBatch::canMergeWith()
731 // TODO: support clipped bitmaps by handling them in SET_TEXTURE
Chris Craikd965bc52013-09-16 14:47:13 -0700732 deferInfo.mergeable = state.mMatrix.isSimple() && state.mMatrix.positiveScale() &&
733 !state.mClipSideFlags &&
Chris Craik28ce94a2013-05-31 11:38:03 -0700734 OpenGLRenderer::getXfermodeDirect(mPaint) == SkXfermode::kSrcOver_Mode &&
Chris Craik67862522014-02-28 12:26:34 -0800735 (mBitmap->config() != SkBitmap::kA8_Config);
Chris Craikc3566d02013-02-04 16:16:33 -0800736 }
Chris Craik2af46352012-11-26 18:30:17 -0800737
Chris Craik527a3aa2013-03-04 10:19:31 -0800738 const SkBitmap* bitmap() { return mBitmap; }
Chris Craik2af46352012-11-26 18:30:17 -0800739protected:
Chris Craikd218a922014-01-02 17:13:34 -0800740 const SkBitmap* mBitmap;
Romain Guy55b6f952013-06-27 15:27:09 -0700741 const AssetAtlas& mAtlas;
742 uint32_t mEntryGenerationId;
743 AssetAtlas::Entry* mEntry;
Romain Guy3b748a42013-04-17 18:54:38 -0700744 UvMapper mUvMapper;
Chris Craik2af46352012-11-26 18:30:17 -0800745};
746
747class DrawBitmapMatrixOp : public DrawBoundedOp {
748public:
Derek Sollenberger13908822013-12-10 12:28:58 -0500749 DrawBitmapMatrixOp(const SkBitmap* bitmap, const SkMatrix& matrix, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -0800750 : DrawBoundedOp(paint), mBitmap(bitmap), mMatrix(matrix) {
751 mLocalBounds.set(0, 0, bitmap->width(), bitmap->height());
Derek Sollenberger13908822013-12-10 12:28:58 -0500752 const mat4 transform(matrix);
Chris Craik2af46352012-11-26 18:30:17 -0800753 transform.mapRect(mLocalBounds);
754 }
755
Chris Craik527a3aa2013-03-04 10:19:31 -0800756 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -0800757 return renderer.drawBitmap(mBitmap, mMatrix, getPaint(renderer));
758 }
759
Chris Craikc5493fb2013-06-19 16:58:58 -0700760 virtual void output(int level, uint32_t logFlags) const {
Derek Sollenberger13908822013-12-10 12:28:58 -0500761 OP_LOG("Draw bitmap %p matrix " SK_MATRIX_STRING, mBitmap, SK_MATRIX_ARGS(&mMatrix));
Chris Craik2af46352012-11-26 18:30:17 -0800762 }
763
Chris Craik527a3aa2013-03-04 10:19:31 -0800764 virtual const char* name() { return "DrawBitmapMatrix"; }
765
Chris Craikc1c5f082013-09-11 16:23:37 -0700766 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
767 const DeferredDisplayState& state) {
Chris Craik28ce94a2013-05-31 11:38:03 -0700768 deferInfo.batchId = DeferredDisplayList::kOpBatch_Bitmap;
Chris Craikc3566d02013-02-04 16:16:33 -0800769 }
Chris Craik2af46352012-11-26 18:30:17 -0800770
771private:
Chris Craikd218a922014-01-02 17:13:34 -0800772 const SkBitmap* mBitmap;
Derek Sollenberger13908822013-12-10 12:28:58 -0500773 const SkMatrix mMatrix;
Chris Craik2af46352012-11-26 18:30:17 -0800774};
775
776class DrawBitmapRectOp : public DrawBoundedOp {
777public:
Chris Craikd218a922014-01-02 17:13:34 -0800778 DrawBitmapRectOp(const SkBitmap* bitmap,
779 float srcLeft, float srcTop, float srcRight, float srcBottom,
780 float dstLeft, float dstTop, float dstRight, float dstBottom, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -0800781 : DrawBoundedOp(dstLeft, dstTop, dstRight, dstBottom, paint),
782 mBitmap(bitmap), mSrc(srcLeft, srcTop, srcRight, srcBottom) {}
783
Chris Craik527a3aa2013-03-04 10:19:31 -0800784 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -0800785 return renderer.drawBitmap(mBitmap, mSrc.left, mSrc.top, mSrc.right, mSrc.bottom,
786 mLocalBounds.left, mLocalBounds.top, mLocalBounds.right, mLocalBounds.bottom,
787 getPaint(renderer));
788 }
789
Chris Craikc5493fb2013-06-19 16:58:58 -0700790 virtual void output(int level, uint32_t logFlags) const {
John Reckce444ca2014-06-02 15:12:36 -0700791 OP_LOG("Draw bitmap %p src=" RECT_STRING ", dst=" RECT_STRING,
Chris Craik2af46352012-11-26 18:30:17 -0800792 mBitmap, RECT_ARGS(mSrc), RECT_ARGS(mLocalBounds));
793 }
794
795 virtual const char* name() { return "DrawBitmapRect"; }
Chris Craik527a3aa2013-03-04 10:19:31 -0800796
Chris Craikc1c5f082013-09-11 16:23:37 -0700797 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
798 const DeferredDisplayState& state) {
Chris Craik28ce94a2013-05-31 11:38:03 -0700799 deferInfo.batchId = DeferredDisplayList::kOpBatch_Bitmap;
Chris Craikc3566d02013-02-04 16:16:33 -0800800 }
Chris Craik2af46352012-11-26 18:30:17 -0800801
802private:
Chris Craikd218a922014-01-02 17:13:34 -0800803 const SkBitmap* mBitmap;
Chris Craik2af46352012-11-26 18:30:17 -0800804 Rect mSrc;
805};
806
807class DrawBitmapDataOp : public DrawBitmapOp {
808public:
Chris Craikd218a922014-01-02 17:13:34 -0800809 DrawBitmapDataOp(const SkBitmap* bitmap, float left, float top, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -0800810 : DrawBitmapOp(bitmap, left, top, paint) {}
811
Chris Craik527a3aa2013-03-04 10:19:31 -0800812 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -0800813 return renderer.drawBitmapData(mBitmap, mLocalBounds.left,
814 mLocalBounds.top, getPaint(renderer));
815 }
816
Chris Craikc5493fb2013-06-19 16:58:58 -0700817 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800818 OP_LOG("Draw bitmap %p", mBitmap);
819 }
820
821 virtual const char* name() { return "DrawBitmapData"; }
Chris Craik527a3aa2013-03-04 10:19:31 -0800822
Chris Craikc1c5f082013-09-11 16:23:37 -0700823 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
824 const DeferredDisplayState& state) {
Chris Craik28ce94a2013-05-31 11:38:03 -0700825 deferInfo.batchId = DeferredDisplayList::kOpBatch_Bitmap;
Chris Craikc3566d02013-02-04 16:16:33 -0800826 }
Chris Craik2af46352012-11-26 18:30:17 -0800827};
828
Chris Craik5d116762013-02-19 17:49:31 -0800829class DrawBitmapMeshOp : public DrawBoundedOp {
Chris Craik2af46352012-11-26 18:30:17 -0800830public:
Chris Craikd218a922014-01-02 17:13:34 -0800831 DrawBitmapMeshOp(const SkBitmap* bitmap, int meshWidth, int meshHeight,
832 const float* vertices, const int* colors, const SkPaint* paint)
Chris Craik5d116762013-02-19 17:49:31 -0800833 : DrawBoundedOp(vertices, 2 * (meshWidth + 1) * (meshHeight + 1), paint),
834 mBitmap(bitmap), mMeshWidth(meshWidth), mMeshHeight(meshHeight),
Chris Craik2af46352012-11-26 18:30:17 -0800835 mVertices(vertices), mColors(colors) {}
836
Chris Craik527a3aa2013-03-04 10:19:31 -0800837 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -0800838 return renderer.drawBitmapMesh(mBitmap, mMeshWidth, mMeshHeight,
839 mVertices, mColors, getPaint(renderer));
840 }
841
Chris Craikc5493fb2013-06-19 16:58:58 -0700842 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800843 OP_LOG("Draw bitmap %p mesh %d x %d", mBitmap, mMeshWidth, mMeshHeight);
844 }
845
846 virtual const char* name() { return "DrawBitmapMesh"; }
Chris Craik527a3aa2013-03-04 10:19:31 -0800847
Chris Craikc1c5f082013-09-11 16:23:37 -0700848 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
849 const DeferredDisplayState& state) {
Chris Craik28ce94a2013-05-31 11:38:03 -0700850 deferInfo.batchId = DeferredDisplayList::kOpBatch_Bitmap;
Chris Craikc3566d02013-02-04 16:16:33 -0800851 }
Chris Craik2af46352012-11-26 18:30:17 -0800852
853private:
Chris Craikd218a922014-01-02 17:13:34 -0800854 const SkBitmap* mBitmap;
Chris Craik2af46352012-11-26 18:30:17 -0800855 int mMeshWidth;
856 int mMeshHeight;
Chris Craikd218a922014-01-02 17:13:34 -0800857 const float* mVertices;
858 const int* mColors;
Chris Craik2af46352012-11-26 18:30:17 -0800859};
860
861class DrawPatchOp : public DrawBoundedOp {
862public:
Chris Craikd218a922014-01-02 17:13:34 -0800863 DrawPatchOp(const SkBitmap* bitmap, const Res_png_9patch* patch,
864 float left, float top, float right, float bottom, const SkPaint* paint)
Romain Guy03c00b52013-06-20 18:30:28 -0700865 : DrawBoundedOp(left, top, right, bottom, paint),
Romain Guy55b6f952013-06-27 15:27:09 -0700866 mBitmap(bitmap), mPatch(patch), mGenerationId(0), mMesh(NULL),
867 mAtlas(Caches::getInstance().assetAtlas) {
868 mEntry = mAtlas.getEntry(bitmap);
869 if (mEntry) {
870 mEntryGenerationId = mAtlas.getGenerationId();
871 }
Romain Guy3b748a42013-04-17 18:54:38 -0700872 };
Chris Craik2af46352012-11-26 18:30:17 -0800873
Romain Guy55b6f952013-06-27 15:27:09 -0700874 AssetAtlas::Entry* getAtlasEntry() {
875 // The atlas entry is stale, let's get a new one
876 if (mEntry && mEntryGenerationId != mAtlas.getGenerationId()) {
877 mEntryGenerationId = mAtlas.getGenerationId();
878 mEntry = mAtlas.getEntry(mBitmap);
879 }
880 return mEntry;
881 }
882
Romain Guy03c00b52013-06-20 18:30:28 -0700883 const Patch* getMesh(OpenGLRenderer& renderer) {
Romain Guy4c2547f2013-06-11 16:19:24 -0700884 if (!mMesh || renderer.getCaches().patchCache.getGenerationId() != mGenerationId) {
885 PatchCache& cache = renderer.getCaches().patchCache;
Romain Guy55b6f952013-06-27 15:27:09 -0700886 mMesh = cache.get(getAtlasEntry(), mBitmap->width(), mBitmap->height(),
Romain Guy03c00b52013-06-20 18:30:28 -0700887 mLocalBounds.getWidth(), mLocalBounds.getHeight(), mPatch);
Romain Guy4c2547f2013-06-11 16:19:24 -0700888 mGenerationId = cache.getGenerationId();
889 }
Romain Guy03c00b52013-06-20 18:30:28 -0700890 return mMesh;
891 }
892
893 /**
894 * This multi-draw operation builds an indexed mesh on the stack by copying
895 * and transforming the vertices of each 9-patch in the batch. This method
896 * is also responsible for dirtying the current layer, if any.
897 */
898 virtual status_t multiDraw(OpenGLRenderer& renderer, Rect& dirty,
Chris Craikc1c5f082013-09-11 16:23:37 -0700899 const Vector<OpStatePair>& ops, const Rect& bounds) {
900 const DeferredDisplayState& firstState = *(ops[0].state);
901 renderer.restoreDisplayState(firstState, true); // restore all but the clip
Romain Guy03c00b52013-06-20 18:30:28 -0700902
903 // Batches will usually contain a small number of items so it's
904 // worth performing a first iteration to count the exact number
905 // of vertices we need in the new mesh
906 uint32_t totalVertices = 0;
907 for (unsigned int i = 0; i < ops.size(); i++) {
Chris Craikc1c5f082013-09-11 16:23:37 -0700908 totalVertices += ((DrawPatchOp*) ops[i].op)->getMesh(renderer)->verticesCount;
Romain Guy03c00b52013-06-20 18:30:28 -0700909 }
910
911 const bool hasLayer = renderer.hasLayer();
912
913 uint32_t indexCount = 0;
914
915 TextureVertex vertices[totalVertices];
916 TextureVertex* vertex = &vertices[0];
917
918 // Create a mesh that contains the transformed vertices for all the
919 // 9-patch objects that are part of the batch. Note that onDefer()
920 // enforces ops drawn by this function to have a pure translate or
921 // identity matrix
922 for (unsigned int i = 0; i < ops.size(); i++) {
Chris Craikc1c5f082013-09-11 16:23:37 -0700923 DrawPatchOp* patchOp = (DrawPatchOp*) ops[i].op;
924 const DeferredDisplayState* state = ops[i].state;
Romain Guy03c00b52013-06-20 18:30:28 -0700925 const Patch* opMesh = patchOp->getMesh(renderer);
926 uint32_t vertexCount = opMesh->verticesCount;
927 if (vertexCount == 0) continue;
928
929 // We use the bounds to know where to translate our vertices
930 // Using patchOp->state.mBounds wouldn't work because these
931 // bounds are clipped
Chris Craikc1c5f082013-09-11 16:23:37 -0700932 const float tx = (int) floorf(state->mMatrix.getTranslateX() +
Romain Guy03c00b52013-06-20 18:30:28 -0700933 patchOp->mLocalBounds.left + 0.5f);
Chris Craikc1c5f082013-09-11 16:23:37 -0700934 const float ty = (int) floorf(state->mMatrix.getTranslateY() +
Romain Guy03c00b52013-06-20 18:30:28 -0700935 patchOp->mLocalBounds.top + 0.5f);
936
937 // Copy & transform all the vertices for the current operation
938 TextureVertex* opVertices = opMesh->vertices;
939 for (uint32_t j = 0; j < vertexCount; j++, opVertices++) {
940 TextureVertex::set(vertex++,
Romain Guy3380cfd2013-08-15 16:57:57 -0700941 opVertices->x + tx, opVertices->y + ty,
942 opVertices->u, opVertices->v);
Romain Guy03c00b52013-06-20 18:30:28 -0700943 }
944
945 // Dirty the current layer if possible. When the 9-patch does not
946 // contain empty quads we can take a shortcut and simply set the
947 // dirty rect to the object's bounds.
948 if (hasLayer) {
949 if (!opMesh->hasEmptyQuads) {
950 renderer.dirtyLayer(tx, ty,
951 tx + patchOp->mLocalBounds.getWidth(),
952 ty + patchOp->mLocalBounds.getHeight());
953 } else {
954 const size_t count = opMesh->quads.size();
955 for (size_t i = 0; i < count; i++) {
956 const Rect& quadBounds = opMesh->quads[i];
957 const float x = tx + quadBounds.left;
958 const float y = ty + quadBounds.top;
959 renderer.dirtyLayer(x, y,
960 x + quadBounds.getWidth(), y + quadBounds.getHeight());
961 }
962 }
963 }
964
965 indexCount += opMesh->indexCount;
966 }
967
Romain Guy55b6f952013-06-27 15:27:09 -0700968 return renderer.drawPatches(mBitmap, getAtlasEntry(),
969 &vertices[0], indexCount, getPaint(renderer));
Romain Guy03c00b52013-06-20 18:30:28 -0700970 }
971
972 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Romain Guy4c2547f2013-06-11 16:19:24 -0700973 // We're not calling the public variant of drawPatch() here
974 // This method won't perform the quickReject() since we've already done it at this point
Romain Guy55b6f952013-06-27 15:27:09 -0700975 return renderer.drawPatch(mBitmap, getMesh(renderer), getAtlasEntry(),
Romain Guy03c00b52013-06-20 18:30:28 -0700976 mLocalBounds.left, mLocalBounds.top, mLocalBounds.right, mLocalBounds.bottom,
977 getPaint(renderer));
Chris Craik2af46352012-11-26 18:30:17 -0800978 }
979
Chris Craikc5493fb2013-06-19 16:58:58 -0700980 virtual void output(int level, uint32_t logFlags) const {
John Reckce444ca2014-06-02 15:12:36 -0700981 OP_LOG("Draw patch " RECT_STRING, RECT_ARGS(mLocalBounds));
Chris Craik2af46352012-11-26 18:30:17 -0800982 }
983
984 virtual const char* name() { return "DrawPatch"; }
Chris Craik527a3aa2013-03-04 10:19:31 -0800985
Chris Craikc1c5f082013-09-11 16:23:37 -0700986 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
987 const DeferredDisplayState& state) {
Chris Craik28ce94a2013-05-31 11:38:03 -0700988 deferInfo.batchId = DeferredDisplayList::kOpBatch_Patch;
Romain Guy7f6d6b02013-08-06 13:49:28 -0700989 deferInfo.mergeId = getAtlasEntry() ? (mergeid_t) mEntry->getMergeId() : (mergeid_t) mBitmap;
Romain Guy03c00b52013-06-20 18:30:28 -0700990 deferInfo.mergeable = state.mMatrix.isPureTranslate() &&
991 OpenGLRenderer::getXfermodeDirect(mPaint) == SkXfermode::kSrcOver_Mode;
Chris Craikc1c5f082013-09-11 16:23:37 -0700992 deferInfo.opaqueOverBounds = isOpaqueOverBounds(state) && mBitmap->isOpaque();
Chris Craikc3566d02013-02-04 16:16:33 -0800993 }
Chris Craik2af46352012-11-26 18:30:17 -0800994
995private:
Chris Craikd218a922014-01-02 17:13:34 -0800996 const SkBitmap* mBitmap;
997 const Res_png_9patch* mPatch;
Romain Guy4c2547f2013-06-11 16:19:24 -0700998
Romain Guy4c2547f2013-06-11 16:19:24 -0700999 uint32_t mGenerationId;
1000 const Patch* mMesh;
Romain Guy03c00b52013-06-20 18:30:28 -07001001
Romain Guy55b6f952013-06-27 15:27:09 -07001002 const AssetAtlas& mAtlas;
1003 uint32_t mEntryGenerationId;
Romain Guy3b748a42013-04-17 18:54:38 -07001004 AssetAtlas::Entry* mEntry;
Chris Craik2af46352012-11-26 18:30:17 -08001005};
1006
1007class DrawColorOp : public DrawOp {
1008public:
1009 DrawColorOp(int color, SkXfermode::Mode mode)
Chris Craikf57776b2013-10-25 18:30:17 -07001010 : DrawOp(NULL), mColor(color), mMode(mode) {};
Chris Craik2af46352012-11-26 18:30:17 -08001011
Chris Craik527a3aa2013-03-04 10:19:31 -08001012 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001013 return renderer.drawColor(mColor, mMode);
1014 }
1015
Chris Craikc5493fb2013-06-19 16:58:58 -07001016 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001017 OP_LOG("Draw color %#x, mode %d", mColor, mMode);
1018 }
1019
1020 virtual const char* name() { return "DrawColor"; }
1021
1022private:
1023 int mColor;
1024 SkXfermode::Mode mMode;
1025};
1026
1027class DrawStrokableOp : public DrawBoundedOp {
1028public:
Chris Craikd218a922014-01-02 17:13:34 -08001029 DrawStrokableOp(float left, float top, float right, float bottom, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001030 : DrawBoundedOp(left, top, right, bottom, paint) {};
1031
Chris Craikc1c5f082013-09-11 16:23:37 -07001032 bool getLocalBounds(const DrawModifiers& drawModifiers, Rect& localBounds) {
Chris Craikc3566d02013-02-04 16:16:33 -08001033 localBounds.set(mLocalBounds);
Chris Craik2af46352012-11-26 18:30:17 -08001034 if (mPaint && mPaint->getStyle() != SkPaint::kFill_Style) {
Chris Craikc3566d02013-02-04 16:16:33 -08001035 localBounds.outset(strokeWidthOutset());
Chris Craik2af46352012-11-26 18:30:17 -08001036 }
1037 return true;
1038 }
Chris Craikc3566d02013-02-04 16:16:33 -08001039
Chris Craikc1c5f082013-09-11 16:23:37 -07001040 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
1041 const DeferredDisplayState& state) {
Chris Craikc3566d02013-02-04 16:16:33 -08001042 if (mPaint->getPathEffect()) {
Chris Craik28ce94a2013-05-31 11:38:03 -07001043 deferInfo.batchId = DeferredDisplayList::kOpBatch_AlphaMaskTexture;
Chris Craik527a3aa2013-03-04 10:19:31 -08001044 } else {
Chris Craik28ce94a2013-05-31 11:38:03 -07001045 deferInfo.batchId = mPaint->isAntiAlias() ?
Chris Craik527a3aa2013-03-04 10:19:31 -08001046 DeferredDisplayList::kOpBatch_AlphaVertices :
1047 DeferredDisplayList::kOpBatch_Vertices;
Chris Craikc3566d02013-02-04 16:16:33 -08001048 }
Chris Craikc3566d02013-02-04 16:16:33 -08001049 }
Chris Craik2af46352012-11-26 18:30:17 -08001050};
1051
1052class DrawRectOp : public DrawStrokableOp {
1053public:
Chris Craikd218a922014-01-02 17:13:34 -08001054 DrawRectOp(float left, float top, float right, float bottom, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001055 : DrawStrokableOp(left, top, right, bottom, paint) {}
1056
Chris Craik527a3aa2013-03-04 10:19:31 -08001057 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001058 return renderer.drawRect(mLocalBounds.left, mLocalBounds.top,
1059 mLocalBounds.right, mLocalBounds.bottom, getPaint(renderer));
1060 }
1061
Chris Craikc5493fb2013-06-19 16:58:58 -07001062 virtual void output(int level, uint32_t logFlags) const {
John Reckce444ca2014-06-02 15:12:36 -07001063 OP_LOG("Draw Rect " RECT_STRING, RECT_ARGS(mLocalBounds));
Chris Craik2af46352012-11-26 18:30:17 -08001064 }
1065
Chris Craikc1c5f082013-09-11 16:23:37 -07001066 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
1067 const DeferredDisplayState& state) {
1068 DrawStrokableOp::onDefer(renderer, deferInfo, state);
1069 deferInfo.opaqueOverBounds = isOpaqueOverBounds(state) &&
Chris Craik28ce94a2013-05-31 11:38:03 -07001070 mPaint->getStyle() == SkPaint::kFill_Style;
1071 }
1072
Chris Craik2af46352012-11-26 18:30:17 -08001073 virtual const char* name() { return "DrawRect"; }
1074};
1075
Chris Craik5d116762013-02-19 17:49:31 -08001076class DrawRectsOp : public DrawBoundedOp {
Chris Craik2af46352012-11-26 18:30:17 -08001077public:
Chris Craikd218a922014-01-02 17:13:34 -08001078 DrawRectsOp(const float* rects, int count, const SkPaint* paint)
Chris Craik5d116762013-02-19 17:49:31 -08001079 : DrawBoundedOp(rects, count, paint),
1080 mRects(rects), mCount(count) {}
Chris Craik2af46352012-11-26 18:30:17 -08001081
Chris Craik527a3aa2013-03-04 10:19:31 -08001082 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001083 return renderer.drawRects(mRects, mCount, getPaint(renderer));
1084 }
1085
Chris Craikc5493fb2013-06-19 16:58:58 -07001086 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001087 OP_LOG("Draw Rects count %d", mCount);
1088 }
1089
1090 virtual const char* name() { return "DrawRects"; }
1091
Chris Craikc1c5f082013-09-11 16:23:37 -07001092 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
1093 const DeferredDisplayState& state) {
Chris Craik28ce94a2013-05-31 11:38:03 -07001094 deferInfo.batchId = DeferredDisplayList::kOpBatch_Vertices;
Chris Craikc3566d02013-02-04 16:16:33 -08001095 }
1096
Chris Craik2af46352012-11-26 18:30:17 -08001097private:
1098 const float* mRects;
1099 int mCount;
1100};
1101
1102class DrawRoundRectOp : public DrawStrokableOp {
1103public:
1104 DrawRoundRectOp(float left, float top, float right, float bottom,
Chris Craikd218a922014-01-02 17:13:34 -08001105 float rx, float ry, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001106 : DrawStrokableOp(left, top, right, bottom, paint), mRx(rx), mRy(ry) {}
1107
Chris Craik527a3aa2013-03-04 10:19:31 -08001108 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001109 return renderer.drawRoundRect(mLocalBounds.left, mLocalBounds.top,
1110 mLocalBounds.right, mLocalBounds.bottom, mRx, mRy, getPaint(renderer));
1111 }
1112
Chris Craikc5493fb2013-06-19 16:58:58 -07001113 virtual void output(int level, uint32_t logFlags) const {
John Reckce444ca2014-06-02 15:12:36 -07001114 OP_LOG("Draw RoundRect " RECT_STRING ", rx %f, ry %f", RECT_ARGS(mLocalBounds), mRx, mRy);
Chris Craik2af46352012-11-26 18:30:17 -08001115 }
1116
Chris Craik05f3d6e2014-06-02 16:27:04 -07001117 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
1118 const DeferredDisplayState& state) {
1119 DrawStrokableOp::onDefer(renderer, deferInfo, state);
1120 if (!mPaint->getPathEffect()) {
1121 renderer.getCaches().tessellationCache.precacheRoundRect(state.mMatrix,
1122 mLocalBounds.getWidth(), mLocalBounds.getHeight(), mRx, mRy, mPaint);
1123 }
1124 }
1125
Chris Craik2af46352012-11-26 18:30:17 -08001126 virtual const char* name() { return "DrawRoundRect"; }
1127
1128private:
1129 float mRx;
1130 float mRy;
1131};
1132
1133class DrawCircleOp : public DrawStrokableOp {
1134public:
Chris Craikd218a922014-01-02 17:13:34 -08001135 DrawCircleOp(float x, float y, float radius, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001136 : DrawStrokableOp(x - radius, y - radius, x + radius, y + radius, paint),
1137 mX(x), mY(y), mRadius(radius) {}
1138
Chris Craik527a3aa2013-03-04 10:19:31 -08001139 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001140 return renderer.drawCircle(mX, mY, mRadius, getPaint(renderer));
1141 }
1142
Chris Craikc5493fb2013-06-19 16:58:58 -07001143 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001144 OP_LOG("Draw Circle x %f, y %f, r %f", mX, mY, mRadius);
1145 }
1146
1147 virtual const char* name() { return "DrawCircle"; }
1148
1149private:
1150 float mX;
1151 float mY;
1152 float mRadius;
1153};
1154
John Reck52244ff2014-05-01 21:27:37 -07001155class DrawCirclePropsOp : public DrawOp {
1156public:
1157 DrawCirclePropsOp(float* x, float* y, float* radius, const SkPaint* paint)
1158 : DrawOp(paint), mX(x), mY(y), mRadius(radius) {}
1159
1160 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
1161 return renderer.drawCircle(*mX, *mY, *mRadius, getPaint(renderer));
1162 }
1163
1164 virtual void output(int level, uint32_t logFlags) const {
1165 OP_LOG("Draw Circle Props x %p, y %p, r %p", mX, mY, mRadius);
1166 }
1167
1168 virtual const char* name() { return "DrawCircleProps"; }
1169
1170private:
1171 float* mX;
1172 float* mY;
1173 float* mRadius;
1174};
1175
Chris Craik2af46352012-11-26 18:30:17 -08001176class DrawOvalOp : public DrawStrokableOp {
1177public:
Chris Craikd218a922014-01-02 17:13:34 -08001178 DrawOvalOp(float left, float top, float right, float bottom, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001179 : DrawStrokableOp(left, top, right, bottom, paint) {}
1180
Chris Craik527a3aa2013-03-04 10:19:31 -08001181 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001182 return renderer.drawOval(mLocalBounds.left, mLocalBounds.top,
1183 mLocalBounds.right, mLocalBounds.bottom, getPaint(renderer));
1184 }
1185
Chris Craikc5493fb2013-06-19 16:58:58 -07001186 virtual void output(int level, uint32_t logFlags) const {
John Reckce444ca2014-06-02 15:12:36 -07001187 OP_LOG("Draw Oval " RECT_STRING, RECT_ARGS(mLocalBounds));
Chris Craik2af46352012-11-26 18:30:17 -08001188 }
1189
1190 virtual const char* name() { return "DrawOval"; }
1191};
1192
1193class DrawArcOp : public DrawStrokableOp {
1194public:
1195 DrawArcOp(float left, float top, float right, float bottom,
Chris Craikd218a922014-01-02 17:13:34 -08001196 float startAngle, float sweepAngle, bool useCenter, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001197 : DrawStrokableOp(left, top, right, bottom, paint),
1198 mStartAngle(startAngle), mSweepAngle(sweepAngle), mUseCenter(useCenter) {}
1199
Chris Craik527a3aa2013-03-04 10:19:31 -08001200 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001201 return renderer.drawArc(mLocalBounds.left, mLocalBounds.top,
1202 mLocalBounds.right, mLocalBounds.bottom,
1203 mStartAngle, mSweepAngle, mUseCenter, getPaint(renderer));
1204 }
1205
Chris Craikc5493fb2013-06-19 16:58:58 -07001206 virtual void output(int level, uint32_t logFlags) const {
John Reckce444ca2014-06-02 15:12:36 -07001207 OP_LOG("Draw Arc " RECT_STRING ", start %f, sweep %f, useCenter %d",
Chris Craik2af46352012-11-26 18:30:17 -08001208 RECT_ARGS(mLocalBounds), mStartAngle, mSweepAngle, mUseCenter);
1209 }
1210
1211 virtual const char* name() { return "DrawArc"; }
1212
1213private:
1214 float mStartAngle;
1215 float mSweepAngle;
1216 bool mUseCenter;
1217};
1218
1219class DrawPathOp : public DrawBoundedOp {
1220public:
Chris Craikd218a922014-01-02 17:13:34 -08001221 DrawPathOp(const SkPath* path, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001222 : DrawBoundedOp(paint), mPath(path) {
1223 float left, top, offset;
1224 uint32_t width, height;
Romain Guyca89e2a2013-03-08 17:44:20 -08001225 PathCache::computePathBounds(path, paint, left, top, offset, width, height);
Chris Craik2af46352012-11-26 18:30:17 -08001226 left -= offset;
1227 top -= offset;
1228 mLocalBounds.set(left, top, left + width, top + height);
1229 }
1230
Chris Craik527a3aa2013-03-04 10:19:31 -08001231 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001232 return renderer.drawPath(mPath, getPaint(renderer));
1233 }
1234
Chris Craikc1c5f082013-09-11 16:23:37 -07001235 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
1236 const DeferredDisplayState& state) {
Chris Craikd218a922014-01-02 17:13:34 -08001237 const SkPaint* paint = getPaint(renderer);
Romain Guyca89e2a2013-03-08 17:44:20 -08001238 renderer.getCaches().pathCache.precache(mPath, paint);
Chris Craik527a3aa2013-03-04 10:19:31 -08001239
Chris Craik28ce94a2013-05-31 11:38:03 -07001240 deferInfo.batchId = DeferredDisplayList::kOpBatch_AlphaMaskTexture;
Romain Guyca89e2a2013-03-08 17:44:20 -08001241 }
1242
Chris Craikc5493fb2013-06-19 16:58:58 -07001243 virtual void output(int level, uint32_t logFlags) const {
John Reckce444ca2014-06-02 15:12:36 -07001244 OP_LOG("Draw Path %p in " RECT_STRING, mPath, RECT_ARGS(mLocalBounds));
Chris Craik2af46352012-11-26 18:30:17 -08001245 }
1246
1247 virtual const char* name() { return "DrawPath"; }
1248
1249private:
Chris Craikd218a922014-01-02 17:13:34 -08001250 const SkPath* mPath;
Chris Craik2af46352012-11-26 18:30:17 -08001251};
1252
Chris Craikc3566d02013-02-04 16:16:33 -08001253class DrawLinesOp : public DrawBoundedOp {
Chris Craik2af46352012-11-26 18:30:17 -08001254public:
Chris Craikd218a922014-01-02 17:13:34 -08001255 DrawLinesOp(const float* points, int count, const SkPaint* paint)
Chris Craik5d116762013-02-19 17:49:31 -08001256 : DrawBoundedOp(points, count, paint),
1257 mPoints(points), mCount(count) {
Chris Craikc3566d02013-02-04 16:16:33 -08001258 mLocalBounds.outset(strokeWidthOutset());
Chris Craik2af46352012-11-26 18:30:17 -08001259 }
1260
Chris Craik527a3aa2013-03-04 10:19:31 -08001261 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001262 return renderer.drawLines(mPoints, mCount, getPaint(renderer));
1263 }
1264
Chris Craikc5493fb2013-06-19 16:58:58 -07001265 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001266 OP_LOG("Draw Lines count %d", mCount);
1267 }
1268
1269 virtual const char* name() { return "DrawLines"; }
1270
Chris Craikc1c5f082013-09-11 16:23:37 -07001271 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
1272 const DeferredDisplayState& state) {
Chris Craik28ce94a2013-05-31 11:38:03 -07001273 deferInfo.batchId = mPaint->isAntiAlias() ?
Chris Craikc3566d02013-02-04 16:16:33 -08001274 DeferredDisplayList::kOpBatch_AlphaVertices :
1275 DeferredDisplayList::kOpBatch_Vertices;
1276 }
1277
Chris Craik2af46352012-11-26 18:30:17 -08001278protected:
Chris Craikd218a922014-01-02 17:13:34 -08001279 const float* mPoints;
Chris Craik2af46352012-11-26 18:30:17 -08001280 int mCount;
1281};
1282
1283class DrawPointsOp : public DrawLinesOp {
1284public:
Chris Craikd218a922014-01-02 17:13:34 -08001285 DrawPointsOp(const float* points, int count, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001286 : DrawLinesOp(points, count, paint) {}
1287
Chris Craik527a3aa2013-03-04 10:19:31 -08001288 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001289 return renderer.drawPoints(mPoints, mCount, getPaint(renderer));
1290 }
1291
Chris Craikc5493fb2013-06-19 16:58:58 -07001292 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001293 OP_LOG("Draw Points count %d", mCount);
1294 }
1295
1296 virtual const char* name() { return "DrawPoints"; }
1297};
1298
1299class DrawSomeTextOp : public DrawOp {
1300public:
Chris Craikd218a922014-01-02 17:13:34 -08001301 DrawSomeTextOp(const char* text, int bytesCount, int count, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001302 : DrawOp(paint), mText(text), mBytesCount(bytesCount), mCount(count) {};
1303
Chris Craikc5493fb2013-06-19 16:58:58 -07001304 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001305 OP_LOG("Draw some text, %d bytes", mBytesCount);
1306 }
Chris Craikc3566d02013-02-04 16:16:33 -08001307
Derek Sollenbergerc29a0a42014-03-31 13:52:39 -04001308 virtual bool hasTextShadow() const {
1309 return OpenGLRenderer::hasTextShadow(mPaint);
1310 }
1311
Chris Craikc1c5f082013-09-11 16:23:37 -07001312 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
1313 const DeferredDisplayState& state) {
Chris Craikd218a922014-01-02 17:13:34 -08001314 const SkPaint* paint = getPaint(renderer);
Romain Guy0f667532013-03-01 14:31:04 -08001315 FontRenderer& fontRenderer = renderer.getCaches().fontRenderer->getFontRenderer(paint);
1316 fontRenderer.precache(paint, mText, mCount, mat4::identity());
Romain Guy0f667532013-03-01 14:31:04 -08001317
Chris Craik28ce94a2013-05-31 11:38:03 -07001318 deferInfo.batchId = mPaint->getColor() == 0xff000000 ?
Chris Craikc3566d02013-02-04 16:16:33 -08001319 DeferredDisplayList::kOpBatch_Text :
1320 DeferredDisplayList::kOpBatch_ColorText;
1321 }
Chris Craik527a3aa2013-03-04 10:19:31 -08001322
Chris Craik2af46352012-11-26 18:30:17 -08001323protected:
1324 const char* mText;
1325 int mBytesCount;
1326 int mCount;
1327};
1328
1329class DrawTextOnPathOp : public DrawSomeTextOp {
1330public:
1331 DrawTextOnPathOp(const char* text, int bytesCount, int count,
Chris Craikd218a922014-01-02 17:13:34 -08001332 const SkPath* path, float hOffset, float vOffset, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001333 : DrawSomeTextOp(text, bytesCount, count, paint),
1334 mPath(path), mHOffset(hOffset), mVOffset(vOffset) {
1335 /* TODO: inherit from DrawBounded and init mLocalBounds */
1336 }
1337
Chris Craik527a3aa2013-03-04 10:19:31 -08001338 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001339 return renderer.drawTextOnPath(mText, mBytesCount, mCount, mPath,
1340 mHOffset, mVOffset, getPaint(renderer));
1341 }
1342
1343 virtual const char* name() { return "DrawTextOnPath"; }
1344
1345private:
Chris Craikd218a922014-01-02 17:13:34 -08001346 const SkPath* mPath;
Chris Craik2af46352012-11-26 18:30:17 -08001347 float mHOffset;
1348 float mVOffset;
1349};
1350
1351class DrawPosTextOp : public DrawSomeTextOp {
1352public:
1353 DrawPosTextOp(const char* text, int bytesCount, int count,
Chris Craikd218a922014-01-02 17:13:34 -08001354 const float* positions, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001355 : DrawSomeTextOp(text, bytesCount, count, paint), mPositions(positions) {
1356 /* TODO: inherit from DrawBounded and init mLocalBounds */
1357 }
1358
Chris Craik527a3aa2013-03-04 10:19:31 -08001359 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001360 return renderer.drawPosText(mText, mBytesCount, mCount, mPositions, getPaint(renderer));
1361 }
1362
1363 virtual const char* name() { return "DrawPosText"; }
1364
1365private:
1366 const float* mPositions;
1367};
1368
1369class DrawTextOp : public DrawBoundedOp {
1370public:
1371 DrawTextOp(const char* text, int bytesCount, int count, float x, float y,
Chris Craikd218a922014-01-02 17:13:34 -08001372 const float* positions, const SkPaint* paint, float totalAdvance, const Rect& bounds)
Chris Craik41541822013-05-03 16:35:54 -07001373 : DrawBoundedOp(bounds, paint), mText(text), mBytesCount(bytesCount), mCount(count),
1374 mX(x), mY(y), mPositions(positions), mTotalAdvance(totalAdvance) {
Romain Guybd3055f2013-03-13 16:14:47 -07001375 memset(&mPrecacheTransform.data[0], 0xff, 16 * sizeof(float));
Chris Craik2af46352012-11-26 18:30:17 -08001376 }
1377
Chris Craikc1c5f082013-09-11 16:23:37 -07001378 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
1379 const DeferredDisplayState& state) {
Chris Craikd218a922014-01-02 17:13:34 -08001380 const SkPaint* paint = getPaint(renderer);
Romain Guy0f667532013-03-01 14:31:04 -08001381 FontRenderer& fontRenderer = renderer.getCaches().fontRenderer->getFontRenderer(paint);
Romain Guybd3055f2013-03-13 16:14:47 -07001382 const mat4& transform = renderer.findBestFontTransform(state.mMatrix);
1383 if (mPrecacheTransform != transform) {
1384 fontRenderer.precache(paint, mText, mCount, transform);
1385 mPrecacheTransform = transform;
1386 }
Chris Craik28ce94a2013-05-31 11:38:03 -07001387 deferInfo.batchId = mPaint->getColor() == 0xff000000 ?
Chris Craik527a3aa2013-03-04 10:19:31 -08001388 DeferredDisplayList::kOpBatch_Text :
1389 DeferredDisplayList::kOpBatch_ColorText;
1390
Kévin PETIT73fc5582014-02-13 11:03:40 +00001391 deferInfo.mergeId = reinterpret_cast<mergeid_t>(mPaint->getColor());
Chris Craik527a3aa2013-03-04 10:19:31 -08001392
1393 // don't merge decorated text - the decorations won't draw in order
1394 bool noDecorations = !(mPaint->getFlags() & (SkPaint::kUnderlineText_Flag |
1395 SkPaint::kStrikeThruText_Flag));
Chris Craik28ce94a2013-05-31 11:38:03 -07001396 deferInfo.mergeable = state.mMatrix.isPureTranslate() && noDecorations &&
1397 OpenGLRenderer::getXfermodeDirect(mPaint) == SkXfermode::kSrcOver_Mode;
Romain Guy0f667532013-03-01 14:31:04 -08001398 }
1399
Chris Craik527a3aa2013-03-04 10:19:31 -08001400 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Romain Guy9b5a1a22013-08-09 14:06:29 -07001401 Rect bounds;
Chris Craikc1c5f082013-09-11 16:23:37 -07001402 getLocalBounds(renderer.getDrawModifiers(), bounds);
Chris Craik2af46352012-11-26 18:30:17 -08001403 return renderer.drawText(mText, mBytesCount, mCount, mX, mY,
Romain Guy9b5a1a22013-08-09 14:06:29 -07001404 mPositions, getPaint(renderer), mTotalAdvance, bounds);
Chris Craik2af46352012-11-26 18:30:17 -08001405 }
1406
Chris Craik527a3aa2013-03-04 10:19:31 -08001407 virtual status_t multiDraw(OpenGLRenderer& renderer, Rect& dirty,
Chris Craikc1c5f082013-09-11 16:23:37 -07001408 const Vector<OpStatePair>& ops, const Rect& bounds) {
Chris Craik527a3aa2013-03-04 10:19:31 -08001409 status_t status = DrawGlInfo::kStatusDone;
Chris Craik527a3aa2013-03-04 10:19:31 -08001410 for (unsigned int i = 0; i < ops.size(); i++) {
Chris Craikc1c5f082013-09-11 16:23:37 -07001411 const DeferredDisplayState& state = *(ops[i].state);
Chris Craik527a3aa2013-03-04 10:19:31 -08001412 DrawOpMode drawOpMode = (i == ops.size() - 1) ? kDrawOpMode_Flush : kDrawOpMode_Defer;
Chris Craikc1c5f082013-09-11 16:23:37 -07001413 renderer.restoreDisplayState(state, true); // restore all but the clip
Chris Craik527a3aa2013-03-04 10:19:31 -08001414
Chris Craikc1c5f082013-09-11 16:23:37 -07001415 DrawTextOp& op = *((DrawTextOp*)ops[i].op);
Romain Guy9b5a1a22013-08-09 14:06:29 -07001416 // quickReject() will not occure in drawText() so we can use mLocalBounds
1417 // directly, we do not need to account for shadow by calling getLocalBounds()
Chris Craik527a3aa2013-03-04 10:19:31 -08001418 status |= renderer.drawText(op.mText, op.mBytesCount, op.mCount, op.mX, op.mY,
Chris Craik41541822013-05-03 16:35:54 -07001419 op.mPositions, op.getPaint(renderer), op.mTotalAdvance, op.mLocalBounds,
1420 drawOpMode);
Chris Craik527a3aa2013-03-04 10:19:31 -08001421 }
1422 return status;
1423 }
1424
Chris Craikc5493fb2013-06-19 16:58:58 -07001425 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001426 OP_LOG("Draw Text of count %d, bytes %d", mCount, mBytesCount);
1427 }
1428
1429 virtual const char* name() { return "DrawText"; }
1430
1431private:
1432 const char* mText;
1433 int mBytesCount;
1434 int mCount;
1435 float mX;
1436 float mY;
1437 const float* mPositions;
Chris Craik41541822013-05-03 16:35:54 -07001438 float mTotalAdvance;
Romain Guybd3055f2013-03-13 16:14:47 -07001439 mat4 mPrecacheTransform;
Chris Craik2af46352012-11-26 18:30:17 -08001440};
1441
1442///////////////////////////////////////////////////////////////////////////////
1443// SPECIAL DRAW OPERATIONS
1444///////////////////////////////////////////////////////////////////////////////
1445
1446class DrawFunctorOp : public DrawOp {
1447public:
1448 DrawFunctorOp(Functor* functor)
Chris Craikf57776b2013-10-25 18:30:17 -07001449 : DrawOp(NULL), mFunctor(functor) {}
Chris Craik2af46352012-11-26 18:30:17 -08001450
Chris Craik527a3aa2013-03-04 10:19:31 -08001451 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001452 renderer.startMark("GL functor");
1453 status_t ret = renderer.callDrawGLFunction(mFunctor, dirty);
1454 renderer.endMark();
1455 return ret;
1456 }
1457
Chris Craikc5493fb2013-06-19 16:58:58 -07001458 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001459 OP_LOG("Draw Functor %p", mFunctor);
1460 }
1461
1462 virtual const char* name() { return "DrawFunctor"; }
1463
1464private:
1465 Functor* mFunctor;
1466};
1467
Chris Craik5d116762013-02-19 17:49:31 -08001468class DrawDisplayListOp : public DrawBoundedOp {
John Recke18264b2014-03-12 13:56:30 -07001469 friend class RenderNode; // grant DisplayList access to info of child
Chris Craik2af46352012-11-26 18:30:17 -08001470public:
John Recke18264b2014-03-12 13:56:30 -07001471 DrawDisplayListOp(RenderNode* displayList, int flags, const mat4& transformFromParent)
Chris Craik5d116762013-02-19 17:49:31 -08001472 : DrawBoundedOp(0, 0, displayList->getWidth(), displayList->getHeight(), 0),
Chris Craikf57776b2013-10-25 18:30:17 -07001473 mDisplayList(displayList), mFlags(flags), mTransformFromParent(transformFromParent) {}
Chris Craikc3566d02013-02-04 16:16:33 -08001474
Chet Haasedd671592013-04-19 14:54:34 -07001475 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
1476 bool useQuickReject) {
Chris Craikf57776b2013-10-25 18:30:17 -07001477 if (mDisplayList && mDisplayList->isRenderable() && !mSkipInOrderDraw) {
Chris Craikb265e2c2014-03-27 15:50:09 -07001478 mDisplayList->deferNodeInParent(deferStruct, level + 1);
Chris Craikc3566d02013-02-04 16:16:33 -08001479 }
Chris Craikc3566d02013-02-04 16:16:33 -08001480 }
Chet Haasedd671592013-04-19 14:54:34 -07001481 virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level,
1482 bool useQuickReject) {
Chris Craikf57776b2013-10-25 18:30:17 -07001483 if (mDisplayList && mDisplayList->isRenderable() && !mSkipInOrderDraw) {
Chris Craikb265e2c2014-03-27 15:50:09 -07001484 mDisplayList->replayNodeInParent(replayStruct, level + 1);
Chris Craikff785832013-03-08 13:12:16 -08001485 }
1486 }
Chris Craik2af46352012-11-26 18:30:17 -08001487
Chris Craika08f95c2013-03-15 17:24:33 -07001488 // NOT USED since replay() is overridden
Chris Craik527a3aa2013-03-04 10:19:31 -08001489 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craika08f95c2013-03-15 17:24:33 -07001490 return DrawGlInfo::kStatusDone;
1491 }
Chris Craikff785832013-03-08 13:12:16 -08001492
Chris Craikc5493fb2013-06-19 16:58:58 -07001493 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001494 OP_LOG("Draw Display List %p, flags %#x", mDisplayList, mFlags);
Chris Craikff785832013-03-08 13:12:16 -08001495 if (mDisplayList && (logFlags & kOpLogFlag_Recurse)) {
Chris Craik2af46352012-11-26 18:30:17 -08001496 mDisplayList->output(level + 1);
1497 }
1498 }
1499
1500 virtual const char* name() { return "DrawDisplayList"; }
1501
John Reck087bc0c2014-04-04 16:20:08 -07001502 RenderNode* renderNode() { return mDisplayList; }
1503
Chris Craik2af46352012-11-26 18:30:17 -08001504private:
John Recke18264b2014-03-12 13:56:30 -07001505 RenderNode* mDisplayList;
Chris Craikf57776b2013-10-25 18:30:17 -07001506 const int mFlags;
1507
1508 ///////////////////////////
1509 // Properties below are used by DisplayList::computeOrderingImpl() and iterate()
1510 ///////////////////////////
1511 /**
1512 * Records transform vs parent, used for computing total transform without rerunning DL contents
1513 */
1514 const mat4 mTransformFromParent;
1515
1516 /**
Chris Craikb79a3e32014-03-11 12:20:17 -07001517 * Holds the transformation between the projection surface ViewGroup and this DisplayList
1518 * drawing instance. Represents any translations / transformations done within the drawing of
1519 * the compositing ancestor ViewGroup's draw, before the draw of the View represented by this
1520 * DisplayList draw instance.
Chris Craikf57776b2013-10-25 18:30:17 -07001521 *
1522 * Note: doesn't include any transformation recorded within the DisplayList and its properties.
1523 */
Chris Craikf533e942014-01-14 22:35:37 -08001524 mat4 mTransformFromCompositingAncestor;
Chris Craikf57776b2013-10-25 18:30:17 -07001525 bool mSkipInOrderDraw;
1526};
1527
1528/**
Chris Craik024433f2014-03-26 13:19:14 -07001529 * Not a canvas operation, used only by 3d / z ordering logic in RenderNode::iterate()
Chris Craikf57776b2013-10-25 18:30:17 -07001530 */
1531class DrawShadowOp : public DrawOp {
1532public:
Chris Craik024433f2014-03-26 13:19:14 -07001533 DrawShadowOp(const mat4& transformXY, const mat4& transformZ,
1534 float casterAlpha, bool casterUnclipped,
Chris Craik61317322014-05-21 13:03:52 -07001535 const SkPath* casterOutline, const SkPath* revealClip)
Chris Craik024433f2014-03-26 13:19:14 -07001536 : DrawOp(NULL), mTransformXY(transformXY), mTransformZ(transformZ),
Chris Craik61317322014-05-21 13:03:52 -07001537 mCasterAlpha(casterAlpha), mCasterUnclipped(casterUnclipped) {
1538 mOutline = *casterOutline;
1539 if (revealClip) {
1540 // intersect the outline with the convex reveal clip
1541 Op(mOutline, *revealClip, kIntersect_PathOp, &mOutline);
1542 }
1543 }
Chris Craikf57776b2013-10-25 18:30:17 -07001544
Chris Craik05f3d6e2014-06-02 16:27:04 -07001545 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
1546 const DeferredDisplayState& state) {
1547 renderer.getCaches().tessellationCache.precacheShadows(&state.mMatrix,
1548 renderer.getLocalClipBounds(), isCasterOpaque(), &mOutline,
1549 &mTransformXY, &mTransformZ, renderer.getLightCenter(), renderer.getLightRadius());
1550 }
1551
Chris Craikf57776b2013-10-25 18:30:17 -07001552 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik05f3d6e2014-06-02 16:27:04 -07001553 TessellationCache::vertexBuffer_pair_t buffers;
1554 Matrix4 drawTransform;
1555 renderer.getMatrix(&drawTransform);
1556 renderer.getCaches().tessellationCache.getShadowBuffers(&drawTransform,
1557 renderer.getLocalClipBounds(), isCasterOpaque(), &mOutline,
1558 &mTransformXY, &mTransformZ, renderer.getLightCenter(), renderer.getLightRadius(),
1559 buffers);
1560
1561 return renderer.drawShadow(mCasterAlpha, buffers.first, buffers.second);
Chris Craikf57776b2013-10-25 18:30:17 -07001562 }
1563
1564 virtual void output(int level, uint32_t logFlags) const {
Chris Craik61317322014-05-21 13:03:52 -07001565 OP_LOGS("DrawShadow");
Chris Craikf57776b2013-10-25 18:30:17 -07001566 }
1567
1568 virtual const char* name() { return "DrawShadow"; }
1569
1570private:
Chris Craik05f3d6e2014-06-02 16:27:04 -07001571 bool isCasterOpaque() { return mCasterAlpha >= 1.0f && mCasterUnclipped; }
1572
Chris Craikb79a3e32014-03-11 12:20:17 -07001573 const mat4 mTransformXY;
1574 const mat4 mTransformZ;
Chris Craik024433f2014-03-26 13:19:14 -07001575 const float mCasterAlpha;
1576 const bool mCasterUnclipped;
Chris Craik61317322014-05-21 13:03:52 -07001577 SkPath mOutline;
Chris Craik2af46352012-11-26 18:30:17 -08001578};
1579
1580class DrawLayerOp : public DrawOp {
1581public:
Chris Craika08f95c2013-03-15 17:24:33 -07001582 DrawLayerOp(Layer* layer, float x, float y)
Chris Craikf57776b2013-10-25 18:30:17 -07001583 : DrawOp(NULL), mLayer(layer), mX(x), mY(y) {}
Chris Craik2af46352012-11-26 18:30:17 -08001584
Chris Craik527a3aa2013-03-04 10:19:31 -08001585 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craika08f95c2013-03-15 17:24:33 -07001586 return renderer.drawLayer(mLayer, mX, mY);
Chris Craik2af46352012-11-26 18:30:17 -08001587 }
1588
Chris Craikc5493fb2013-06-19 16:58:58 -07001589 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001590 OP_LOG("Draw Layer %p at %f %f", mLayer, mX, mY);
1591 }
1592
1593 virtual const char* name() { return "DrawLayer"; }
1594
1595private:
1596 Layer* mLayer;
1597 float mX;
1598 float mY;
1599};
1600
1601}; // namespace uirenderer
1602}; // namespace android
1603
1604#endif // ANDROID_HWUI_DISPLAY_OPERATION_H