blob: ce92beb898ba2e27f6a0c84509d967395e86e4af [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 Guy0f6675332013-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
Chris Craik527a3aa2013-03-04 10:19:31 -0800186 inline float strokeWidthOutset() {
Chris Craikf0a59072013-11-19 18:00:46 -0800187 // since anything AA stroke with less than 1.0 pixel width is drawn with an alpha-reduced
188 // 1.0 stroke, treat 1.0 as minimum.
189
190 // TODO: it would be nice if this could take scale into account, but scale isn't stable
191 // since higher levels of the view hierarchy can change scale out from underneath it.
192 return fmaxf(mPaint->getStrokeWidth(), 1) * 0.5f;
Chris Craike7c69c62013-04-03 09:55:48 -0700193 }
Chris Craikc3566d02013-02-04 16:16:33 -0800194
Chris Craik2af46352012-11-26 18:30:17 -0800195protected:
Chris Craikd218a922014-01-02 17:13:34 -0800196 const SkPaint* getPaint(OpenGLRenderer& renderer) {
Chris Craika08f95c2013-03-15 17:24:33 -0700197 return renderer.filterPaint(mPaint);
Chris Craik2af46352012-11-26 18:30:17 -0800198 }
199
Chris Craik28ce94a2013-05-31 11:38:03 -0700200 // Helper method for determining op opaqueness. Assumes op fills its bounds in local
201 // coordinates, and that paint's alpha is used
Chris Craikc1c5f082013-09-11 16:23:37 -0700202 inline bool isOpaqueOverBounds(const DeferredDisplayState& state) {
Chris Craik28ce94a2013-05-31 11:38:03 -0700203 // ensure that local bounds cover mapped bounds
204 if (!state.mMatrix.isSimple()) return false;
205
206 // check state/paint for transparency
207 if (state.mDrawModifiers.mShader ||
208 state.mAlpha != 1.0f ||
209 (mPaint && mPaint->getAlpha() != 0xFF)) return false;
210
211 SkXfermode::Mode mode = OpenGLRenderer::getXfermodeDirect(mPaint);
212 return (mode == SkXfermode::kSrcOver_Mode ||
213 mode == SkXfermode::kSrc_Mode);
214
215 }
216
Chris Craikd218a922014-01-02 17:13:34 -0800217 const SkPaint* mPaint; // should be accessed via getPaint() when applying
Chris Craik2af46352012-11-26 18:30:17 -0800218 bool mQuickRejected;
219};
220
221class DrawBoundedOp : public DrawOp {
222public:
Chris Craikd218a922014-01-02 17:13:34 -0800223 DrawBoundedOp(float left, float top, float right, float bottom, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -0800224 : DrawOp(paint), mLocalBounds(left, top, right, bottom) {}
225
Chris Craikd218a922014-01-02 17:13:34 -0800226 DrawBoundedOp(const Rect& localBounds, const SkPaint* paint)
Chris Craik41541822013-05-03 16:35:54 -0700227 : DrawOp(paint), mLocalBounds(localBounds) {}
228
Chris Craik5d116762013-02-19 17:49:31 -0800229 // Calculates bounds as smallest rect encompassing all points
230 // NOTE: requires at least 1 vertex, and doesn't account for stroke size (should be handled in
231 // subclass' constructor)
Chris Craikd218a922014-01-02 17:13:34 -0800232 DrawBoundedOp(const float* points, int count, const SkPaint* paint)
Chris Craik5d116762013-02-19 17:49:31 -0800233 : DrawOp(paint), mLocalBounds(points[0], points[1], points[0], points[1]) {
234 for (int i = 2; i < count; i += 2) {
235 mLocalBounds.left = fminf(mLocalBounds.left, points[i]);
236 mLocalBounds.right = fmaxf(mLocalBounds.right, points[i]);
237 mLocalBounds.top = fminf(mLocalBounds.top, points[i + 1]);
238 mLocalBounds.bottom = fmaxf(mLocalBounds.bottom, points[i + 1]);
239 }
240 }
241
242 // default empty constructor for bounds, to be overridden in child constructor body
Chris Craikd218a922014-01-02 17:13:34 -0800243 DrawBoundedOp(const SkPaint* paint): DrawOp(paint) { }
Chris Craik2af46352012-11-26 18:30:17 -0800244
Chris Craikc1c5f082013-09-11 16:23:37 -0700245 bool getLocalBounds(const DrawModifiers& drawModifiers, Rect& localBounds) {
Chris Craik2af46352012-11-26 18:30:17 -0800246 localBounds.set(mLocalBounds);
Chris Craikc1c5f082013-09-11 16:23:37 -0700247 if (drawModifiers.mHasShadow) {
248 // TODO: inspect paint's looper directly
Romain Guy9b5a1a22013-08-09 14:06:29 -0700249 Rect shadow(mLocalBounds);
Chris Craikc1c5f082013-09-11 16:23:37 -0700250 shadow.translate(drawModifiers.mShadowDx, drawModifiers.mShadowDy);
251 shadow.outset(drawModifiers.mShadowRadius);
Romain Guy9b5a1a22013-08-09 14:06:29 -0700252 localBounds.unionWith(shadow);
253 }
Chris Craik2af46352012-11-26 18:30:17 -0800254 return true;
255 }
256
257protected:
258 Rect mLocalBounds; // displayed area in LOCAL coord. doesn't incorporate stroke, so check paint
259};
260
261///////////////////////////////////////////////////////////////////////////////
262// STATE OPERATIONS - these may affect the state of the canvas/renderer, but do
263// not directly draw or alter output
264///////////////////////////////////////////////////////////////////////////////
265
266class SaveOp : public StateOp {
267public:
268 SaveOp(int flags)
269 : mFlags(flags) {}
270
Chet Haasedd671592013-04-19 14:54:34 -0700271 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
272 bool useQuickReject) {
Chris Craikff785832013-03-08 13:12:16 -0800273 int newSaveCount = deferStruct.mRenderer.save(mFlags);
274 deferStruct.mDeferredList.addSave(deferStruct.mRenderer, this, newSaveCount);
275 }
276
Chris Craik7273daa2013-03-28 11:25:24 -0700277 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800278 renderer.save(mFlags);
279 }
280
Chris Craikc5493fb2013-06-19 16:58:58 -0700281 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800282 OP_LOG("Save flags %x", mFlags);
283 }
284
285 virtual const char* name() { return "Save"; }
286
Chris Craikff785832013-03-08 13:12:16 -0800287 int getFlags() const { return mFlags; }
Chris Craik2af46352012-11-26 18:30:17 -0800288private:
289 int mFlags;
290};
291
292class RestoreToCountOp : public StateOp {
293public:
294 RestoreToCountOp(int count)
295 : mCount(count) {}
296
Chet Haasedd671592013-04-19 14:54:34 -0700297 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
298 bool useQuickReject) {
Chris Craik7273daa2013-03-28 11:25:24 -0700299 deferStruct.mDeferredList.addRestoreToCount(deferStruct.mRenderer,
300 this, saveCount + mCount);
Chris Craikff785832013-03-08 13:12:16 -0800301 deferStruct.mRenderer.restoreToCount(saveCount + mCount);
Chris Craik2af46352012-11-26 18:30:17 -0800302 }
303
Chris Craik7273daa2013-03-28 11:25:24 -0700304 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craikff785832013-03-08 13:12:16 -0800305 renderer.restoreToCount(saveCount + mCount);
306 }
307
Chris Craikc5493fb2013-06-19 16:58:58 -0700308 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800309 OP_LOG("Restore to count %d", mCount);
310 }
311
312 virtual const char* name() { return "RestoreToCount"; }
313
314private:
315 int mCount;
316};
317
318class SaveLayerOp : public StateOp {
319public:
Derek Sollenbergerd44fbe52014-02-05 16:47:00 -0500320 SaveLayerOp(float left, float top, float right, float bottom, int alpha, int flags)
Chris Craik3f0854292014-04-15 16:18:08 -0700321 : mArea(left, top, right, bottom)
322 , mPaint(&mCachedPaint)
323 , mFlags(flags)
324 , mConvexMask(NULL) {
Derek Sollenbergerd44fbe52014-02-05 16:47:00 -0500325 mCachedPaint.setAlpha(alpha);
326 }
327
328 SaveLayerOp(float left, float top, float right, float bottom, const SkPaint* paint, int flags)
Chris Craik3f0854292014-04-15 16:18:08 -0700329 : mArea(left, top, right, bottom)
330 , mPaint(paint)
331 , mFlags(flags)
332 , mConvexMask(NULL)
333 {}
Chris Craikff785832013-03-08 13:12:16 -0800334
Chet Haasedd671592013-04-19 14:54:34 -0700335 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
336 bool useQuickReject) {
Chris Craikff785832013-03-08 13:12:16 -0800337 // NOTE: don't bother with actual saveLayer, instead issuing it at flush time
Chris Craikd90144d2013-03-19 15:03:48 -0700338 int newSaveCount = deferStruct.mRenderer.getSaveCount();
Chris Craikff785832013-03-08 13:12:16 -0800339 deferStruct.mDeferredList.addSaveLayer(deferStruct.mRenderer, this, newSaveCount);
Chris Craikd90144d2013-03-19 15:03:48 -0700340
341 // NOTE: don't issue full saveLayer, since that has side effects/is costly. instead just
342 // setup the snapshot for deferral, and re-issue the op at flush time
343 deferStruct.mRenderer.saveLayerDeferred(mArea.left, mArea.top, mArea.right, mArea.bottom,
Derek Sollenbergerd44fbe52014-02-05 16:47:00 -0500344 mPaint, mFlags);
Chris Craikff785832013-03-08 13:12:16 -0800345 }
Chris Craik2af46352012-11-26 18:30:17 -0800346
Chris Craik7273daa2013-03-28 11:25:24 -0700347 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik3f0854292014-04-15 16:18:08 -0700348 renderer.saveLayer(mArea.left, mArea.top, mArea.right, mArea.bottom,
349 mPaint, mFlags, mConvexMask);
Chris Craik2af46352012-11-26 18:30:17 -0800350 }
351
Chris Craikc5493fb2013-06-19 16:58:58 -0700352 virtual void output(int level, uint32_t logFlags) const {
Chris Craikff785832013-03-08 13:12:16 -0800353 OP_LOG("SaveLayer%s of area " RECT_STRING,
354 (isSaveLayerAlpha() ? "Alpha" : ""),RECT_ARGS(mArea));
Chris Craik2af46352012-11-26 18:30:17 -0800355 }
356
Chris Craikff785832013-03-08 13:12:16 -0800357 virtual const char* name() { return isSaveLayerAlpha() ? "SaveLayerAlpha" : "SaveLayer"; }
358
359 int getFlags() { return mFlags; }
Chris Craik2af46352012-11-26 18:30:17 -0800360
Chris Craik3f0854292014-04-15 16:18:08 -0700361 // Called to make SaveLayerOp clip to the provided mask when drawing back/restored
362 void setMask(const SkPath* convexMask) {
363 mConvexMask = convexMask;
364 }
365
Chris Craik2af46352012-11-26 18:30:17 -0800366private:
Derek Sollenbergerd44fbe52014-02-05 16:47:00 -0500367 bool isSaveLayerAlpha() const {
368 SkXfermode::Mode mode = OpenGLRenderer::getXfermodeDirect(mPaint);
369 int alpha = OpenGLRenderer::getAlphaDirect(mPaint);
370 return alpha < 255 && mode == SkXfermode::kSrcOver_Mode;
Chris Craik2af46352012-11-26 18:30:17 -0800371 }
372
Chris Craik2af46352012-11-26 18:30:17 -0800373 Rect mArea;
Derek Sollenbergerd44fbe52014-02-05 16:47:00 -0500374 const SkPaint* mPaint;
375 SkPaint mCachedPaint;
Chris Craik2af46352012-11-26 18:30:17 -0800376 int mFlags;
Chris Craik3f0854292014-04-15 16:18:08 -0700377
378 // Convex path, points at data in RenderNode, valid for the duration of the frame only
379 // Only used for masking the SaveLayer which wraps projected RenderNodes
380 const SkPath* mConvexMask;
Chris Craik2af46352012-11-26 18:30:17 -0800381};
382
383class TranslateOp : public StateOp {
384public:
385 TranslateOp(float dx, float dy)
386 : mDx(dx), mDy(dy) {}
387
Chris Craik7273daa2013-03-28 11:25:24 -0700388 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800389 renderer.translate(mDx, mDy);
390 }
391
Chris Craikc5493fb2013-06-19 16:58:58 -0700392 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800393 OP_LOG("Translate by %f %f", mDx, mDy);
394 }
395
396 virtual const char* name() { return "Translate"; }
397
398private:
399 float mDx;
400 float mDy;
401};
402
403class RotateOp : public StateOp {
404public:
405 RotateOp(float degrees)
406 : mDegrees(degrees) {}
407
Chris Craik7273daa2013-03-28 11:25:24 -0700408 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800409 renderer.rotate(mDegrees);
410 }
411
Chris Craikc5493fb2013-06-19 16:58:58 -0700412 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800413 OP_LOG("Rotate by %f degrees", mDegrees);
414 }
415
416 virtual const char* name() { return "Rotate"; }
417
418private:
419 float mDegrees;
420};
421
422class ScaleOp : public StateOp {
423public:
424 ScaleOp(float sx, float sy)
425 : mSx(sx), mSy(sy) {}
426
Chris Craik7273daa2013-03-28 11:25:24 -0700427 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800428 renderer.scale(mSx, mSy);
429 }
430
Chris Craikc5493fb2013-06-19 16:58:58 -0700431 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800432 OP_LOG("Scale by %f %f", mSx, mSy);
433 }
434
435 virtual const char* name() { return "Scale"; }
436
437private:
438 float mSx;
439 float mSy;
440};
441
442class SkewOp : public StateOp {
443public:
444 SkewOp(float sx, float sy)
445 : mSx(sx), mSy(sy) {}
446
Chris Craik7273daa2013-03-28 11:25:24 -0700447 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800448 renderer.skew(mSx, mSy);
449 }
450
Chris Craikc5493fb2013-06-19 16:58:58 -0700451 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800452 OP_LOG("Skew by %f %f", mSx, mSy);
453 }
454
455 virtual const char* name() { return "Skew"; }
456
457private:
458 float mSx;
459 float mSy;
460};
461
462class SetMatrixOp : public StateOp {
463public:
Chris Craikd218a922014-01-02 17:13:34 -0800464 SetMatrixOp(const SkMatrix* matrix)
Chris Craik2af46352012-11-26 18:30:17 -0800465 : mMatrix(matrix) {}
466
Chris Craik7273daa2013-03-28 11:25:24 -0700467 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800468 renderer.setMatrix(mMatrix);
469 }
470
Chris Craikc5493fb2013-06-19 16:58:58 -0700471 virtual void output(int level, uint32_t logFlags) const {
Romain Guy4e7b7722013-07-16 13:47:01 -0700472 if (mMatrix) {
Chris Craik629f6772014-02-05 13:00:24 -0800473 OP_LOG("SetMatrix " SK_MATRIX_STRING, SK_MATRIX_ARGS(mMatrix));
Romain Guy4e7b7722013-07-16 13:47:01 -0700474 } else {
475 OP_LOGS("SetMatrix (reset)");
476 }
Chris Craik2af46352012-11-26 18:30:17 -0800477 }
478
479 virtual const char* name() { return "SetMatrix"; }
480
481private:
Chris Craikd218a922014-01-02 17:13:34 -0800482 const SkMatrix* mMatrix;
Chris Craik2af46352012-11-26 18:30:17 -0800483};
484
485class ConcatMatrixOp : public StateOp {
486public:
Chris Craikd218a922014-01-02 17:13:34 -0800487 ConcatMatrixOp(const SkMatrix* matrix)
Chris Craik2af46352012-11-26 18:30:17 -0800488 : mMatrix(matrix) {}
489
Chris Craik7273daa2013-03-28 11:25:24 -0700490 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800491 renderer.concatMatrix(mMatrix);
492 }
493
Chris Craikc5493fb2013-06-19 16:58:58 -0700494 virtual void output(int level, uint32_t logFlags) const {
Chris Craik629f6772014-02-05 13:00:24 -0800495 OP_LOG("ConcatMatrix " SK_MATRIX_STRING, SK_MATRIX_ARGS(mMatrix));
Chris Craik2af46352012-11-26 18:30:17 -0800496 }
497
498 virtual const char* name() { return "ConcatMatrix"; }
499
500private:
Chris Craikd218a922014-01-02 17:13:34 -0800501 const SkMatrix* mMatrix;
Chris Craik2af46352012-11-26 18:30:17 -0800502};
503
Chris Craikff785832013-03-08 13:12:16 -0800504class ClipOp : public StateOp {
505public:
506 ClipOp(SkRegion::Op op) : mOp(op) {}
507
Chet Haasedd671592013-04-19 14:54:34 -0700508 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
509 bool useQuickReject) {
Chris Craikff785832013-03-08 13:12:16 -0800510 // NOTE: must defer op BEFORE applying state, since it may read clip
511 deferStruct.mDeferredList.addClip(deferStruct.mRenderer, this);
512
513 // TODO: Can we avoid applying complex clips at defer time?
514 applyState(deferStruct.mRenderer, saveCount);
515 }
516
517 bool canCauseComplexClip() {
518 return ((mOp != SkRegion::kIntersect_Op) && (mOp != SkRegion::kReplace_Op)) || !isRect();
519 }
520
521protected:
Chris Craikff785832013-03-08 13:12:16 -0800522 virtual bool isRect() { return false; }
523
524 SkRegion::Op mOp;
525};
526
527class ClipRectOp : public ClipOp {
Chris Craik2af46352012-11-26 18:30:17 -0800528public:
529 ClipRectOp(float left, float top, float right, float bottom, SkRegion::Op op)
Chris Craikff785832013-03-08 13:12:16 -0800530 : ClipOp(op), mArea(left, top, right, bottom) {}
Chris Craik2af46352012-11-26 18:30:17 -0800531
Chris Craik7273daa2013-03-28 11:25:24 -0700532 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800533 renderer.clipRect(mArea.left, mArea.top, mArea.right, mArea.bottom, mOp);
534 }
535
Chris Craikc5493fb2013-06-19 16:58:58 -0700536 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800537 OP_LOG("ClipRect " RECT_STRING, RECT_ARGS(mArea));
538 }
539
540 virtual const char* name() { return "ClipRect"; }
541
Chris Craikff785832013-03-08 13:12:16 -0800542protected:
543 virtual bool isRect() { return true; }
Chris Craikb98a0162013-02-21 11:30:22 -0800544
Chris Craik2af46352012-11-26 18:30:17 -0800545private:
546 Rect mArea;
Chris Craik2af46352012-11-26 18:30:17 -0800547};
548
Chris Craikff785832013-03-08 13:12:16 -0800549class ClipPathOp : public ClipOp {
Chris Craik2af46352012-11-26 18:30:17 -0800550public:
Chris Craikd218a922014-01-02 17:13:34 -0800551 ClipPathOp(const SkPath* path, SkRegion::Op op)
Chris Craikff785832013-03-08 13:12:16 -0800552 : ClipOp(op), mPath(path) {}
Chris Craik2af46352012-11-26 18:30:17 -0800553
Chris Craik7273daa2013-03-28 11:25:24 -0700554 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800555 renderer.clipPath(mPath, mOp);
556 }
557
Chris Craikc5493fb2013-06-19 16:58:58 -0700558 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800559 SkRect bounds = mPath->getBounds();
560 OP_LOG("ClipPath bounds " RECT_STRING,
561 bounds.left(), bounds.top(), bounds.right(), bounds.bottom());
562 }
563
564 virtual const char* name() { return "ClipPath"; }
565
566private:
Chris Craikd218a922014-01-02 17:13:34 -0800567 const SkPath* mPath;
Chris Craik2af46352012-11-26 18:30:17 -0800568};
569
Chris Craikff785832013-03-08 13:12:16 -0800570class ClipRegionOp : public ClipOp {
Chris Craik2af46352012-11-26 18:30:17 -0800571public:
Chris Craikd218a922014-01-02 17:13:34 -0800572 ClipRegionOp(const SkRegion* region, SkRegion::Op op)
Chris Craikff785832013-03-08 13:12:16 -0800573 : ClipOp(op), mRegion(region) {}
Chris Craik2af46352012-11-26 18:30:17 -0800574
Chris Craik7273daa2013-03-28 11:25:24 -0700575 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800576 renderer.clipRegion(mRegion, mOp);
577 }
578
Chris Craikc5493fb2013-06-19 16:58:58 -0700579 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800580 SkIRect bounds = mRegion->getBounds();
581 OP_LOG("ClipRegion bounds %d %d %d %d",
582 bounds.left(), bounds.top(), bounds.right(), bounds.bottom());
583 }
584
585 virtual const char* name() { return "ClipRegion"; }
586
587private:
Chris Craikd218a922014-01-02 17:13:34 -0800588 const SkRegion* mRegion;
Chris Craik2af46352012-11-26 18:30:17 -0800589};
590
591class ResetShaderOp : public StateOp {
592public:
Chris Craik7273daa2013-03-28 11:25:24 -0700593 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800594 renderer.resetShader();
595 }
596
Chris Craikc5493fb2013-06-19 16:58:58 -0700597 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800598 OP_LOGS("ResetShader");
599 }
600
601 virtual const char* name() { return "ResetShader"; }
602};
603
604class SetupShaderOp : public StateOp {
605public:
606 SetupShaderOp(SkiaShader* shader)
607 : mShader(shader) {}
Chris Craik7273daa2013-03-28 11:25:24 -0700608 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800609 renderer.setupShader(mShader);
610 }
611
Chris Craikc5493fb2013-06-19 16:58:58 -0700612 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800613 OP_LOG("SetupShader, shader %p", mShader);
614 }
615
616 virtual const char* name() { return "SetupShader"; }
617
618private:
619 SkiaShader* mShader;
620};
621
Chris Craik2af46352012-11-26 18:30:17 -0800622class ResetShadowOp : public StateOp {
623public:
Chris Craik7273daa2013-03-28 11:25:24 -0700624 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800625 renderer.resetShadow();
626 }
627
Chris Craikc5493fb2013-06-19 16:58:58 -0700628 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800629 OP_LOGS("ResetShadow");
630 }
631
632 virtual const char* name() { return "ResetShadow"; }
633};
634
635class SetupShadowOp : public StateOp {
636public:
637 SetupShadowOp(float radius, float dx, float dy, int color)
638 : mRadius(radius), mDx(dx), mDy(dy), mColor(color) {}
639
Chris Craik7273daa2013-03-28 11:25:24 -0700640 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800641 renderer.setupShadow(mRadius, mDx, mDy, mColor);
642 }
643
Chris Craikc5493fb2013-06-19 16:58:58 -0700644 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800645 OP_LOG("SetupShadow, radius %f, %f, %f, color %#x", mRadius, mDx, mDy, mColor);
646 }
647
648 virtual const char* name() { return "SetupShadow"; }
649
650private:
651 float mRadius;
652 float mDx;
653 float mDy;
654 int mColor;
655};
656
657class ResetPaintFilterOp : public StateOp {
658public:
Chris Craik7273daa2013-03-28 11:25:24 -0700659 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800660 renderer.resetPaintFilter();
661 }
662
Chris Craikc5493fb2013-06-19 16:58:58 -0700663 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800664 OP_LOGS("ResetPaintFilter");
665 }
666
667 virtual const char* name() { return "ResetPaintFilter"; }
668};
669
670class SetupPaintFilterOp : public StateOp {
671public:
672 SetupPaintFilterOp(int clearBits, int setBits)
673 : mClearBits(clearBits), mSetBits(setBits) {}
674
Chris Craik7273daa2013-03-28 11:25:24 -0700675 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800676 renderer.setupPaintFilter(mClearBits, mSetBits);
677 }
678
Chris Craikc5493fb2013-06-19 16:58:58 -0700679 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800680 OP_LOG("SetupPaintFilter, clear %#x, set %#x", mClearBits, mSetBits);
681 }
682
683 virtual const char* name() { return "SetupPaintFilter"; }
684
685private:
686 int mClearBits;
687 int mSetBits;
688};
689
Chris Craik2af46352012-11-26 18:30:17 -0800690///////////////////////////////////////////////////////////////////////////////
691// DRAW OPERATIONS - these are operations that can draw to the canvas's device
692///////////////////////////////////////////////////////////////////////////////
693
694class DrawBitmapOp : public DrawBoundedOp {
695public:
Chris Craikd218a922014-01-02 17:13:34 -0800696 DrawBitmapOp(const SkBitmap* bitmap, float left, float top, const SkPaint* paint)
Romain Guy3b748a42013-04-17 18:54:38 -0700697 : DrawBoundedOp(left, top, left + bitmap->width(), top + bitmap->height(), paint),
Romain Guy55b6f952013-06-27 15:27:09 -0700698 mBitmap(bitmap), mAtlas(Caches::getInstance().assetAtlas) {
699 mEntry = mAtlas.getEntry(bitmap);
700 if (mEntry) {
701 mEntryGenerationId = mAtlas.getGenerationId();
702 mUvMapper = mEntry->uvMapper;
703 }
Romain Guy3b748a42013-04-17 18:54:38 -0700704 }
Chris Craik2af46352012-11-26 18:30:17 -0800705
Chris Craik527a3aa2013-03-04 10:19:31 -0800706 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craika08f95c2013-03-15 17:24:33 -0700707 return renderer.drawBitmap(mBitmap, mLocalBounds.left, mLocalBounds.top,
708 getPaint(renderer));
Chris Craik2af46352012-11-26 18:30:17 -0800709 }
710
Romain Guy55b6f952013-06-27 15:27:09 -0700711 AssetAtlas::Entry* getAtlasEntry() {
712 // The atlas entry is stale, let's get a new one
713 if (mEntry && mEntryGenerationId != mAtlas.getGenerationId()) {
714 mEntryGenerationId = mAtlas.getGenerationId();
715 mEntry = mAtlas.getEntry(mBitmap);
716 mUvMapper = mEntry->uvMapper;
717 }
718 return mEntry;
719 }
720
Chris Craik527a3aa2013-03-04 10:19:31 -0800721#define SET_TEXTURE(ptr, posRect, offsetRect, texCoordsRect, xDim, yDim) \
722 TextureVertex::set(ptr++, posRect.xDim - offsetRect.left, posRect.yDim - offsetRect.top, \
723 texCoordsRect.xDim, texCoordsRect.yDim)
724
Romain Guy03c00b52013-06-20 18:30:28 -0700725 /**
726 * This multi-draw operation builds a mesh on the stack by generating a quad
727 * for each bitmap in the batch. This method is also responsible for dirtying
728 * the current layer, if any.
729 */
Chris Craik527a3aa2013-03-04 10:19:31 -0800730 virtual status_t multiDraw(OpenGLRenderer& renderer, Rect& dirty,
Chris Craikc1c5f082013-09-11 16:23:37 -0700731 const Vector<OpStatePair>& ops, const Rect& bounds) {
732 const DeferredDisplayState& firstState = *(ops[0].state);
733 renderer.restoreDisplayState(firstState, true); // restore all but the clip
734
Chris Craik527a3aa2013-03-04 10:19:31 -0800735 TextureVertex vertices[6 * ops.size()];
736 TextureVertex* vertex = &vertices[0];
737
Romain Guy03c00b52013-06-20 18:30:28 -0700738 const bool hasLayer = renderer.hasLayer();
Chris Craik996fe652013-09-20 17:13:18 -0700739 bool pureTranslate = true;
Romain Guy2db5e992013-05-21 15:29:59 -0700740
Romain Guy3b748a42013-04-17 18:54:38 -0700741 // TODO: manually handle rect clip for bitmaps by adjusting texCoords per op,
742 // and allowing them to be merged in getBatchId()
Chris Craik527a3aa2013-03-04 10:19:31 -0800743 for (unsigned int i = 0; i < ops.size(); i++) {
Chris Craikc1c5f082013-09-11 16:23:37 -0700744 const DeferredDisplayState& state = *(ops[i].state);
745 const Rect& opBounds = state.mBounds;
Romain Guy2db5e992013-05-21 15:29:59 -0700746 // When we reach multiDraw(), the matrix can be either
747 // pureTranslate or simple (translate and/or scale).
748 // If the matrix is not pureTranslate, then we have a scale
Chris Craik996fe652013-09-20 17:13:18 -0700749 pureTranslate &= state.mMatrix.isPureTranslate();
Romain Guy3b748a42013-04-17 18:54:38 -0700750
751 Rect texCoords(0, 0, 1, 1);
Chris Craikc1c5f082013-09-11 16:23:37 -0700752 ((DrawBitmapOp*) ops[i].op)->mUvMapper.map(texCoords);
Romain Guy3b748a42013-04-17 18:54:38 -0700753
Chris Craik527a3aa2013-03-04 10:19:31 -0800754 SET_TEXTURE(vertex, opBounds, bounds, texCoords, left, top);
755 SET_TEXTURE(vertex, opBounds, bounds, texCoords, right, top);
756 SET_TEXTURE(vertex, opBounds, bounds, texCoords, left, bottom);
757
758 SET_TEXTURE(vertex, opBounds, bounds, texCoords, left, bottom);
759 SET_TEXTURE(vertex, opBounds, bounds, texCoords, right, top);
760 SET_TEXTURE(vertex, opBounds, bounds, texCoords, right, bottom);
Romain Guy03c00b52013-06-20 18:30:28 -0700761
762 if (hasLayer) {
Chris Craikc1c5f082013-09-11 16:23:37 -0700763 renderer.dirtyLayer(opBounds.left, opBounds.top, opBounds.right, opBounds.bottom);
Romain Guy03c00b52013-06-20 18:30:28 -0700764 }
Chris Craik527a3aa2013-03-04 10:19:31 -0800765 }
766
Romain Guy55b6f952013-06-27 15:27:09 -0700767 return renderer.drawBitmaps(mBitmap, mEntry, ops.size(), &vertices[0],
Chris Craik996fe652013-09-20 17:13:18 -0700768 pureTranslate, bounds, mPaint);
Chris Craik527a3aa2013-03-04 10:19:31 -0800769 }
770
Chris Craikc5493fb2013-06-19 16:58:58 -0700771 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800772 OP_LOG("Draw bitmap %p at %f %f", mBitmap, mLocalBounds.left, mLocalBounds.top);
773 }
774
775 virtual const char* name() { return "DrawBitmap"; }
Chris Craik527a3aa2013-03-04 10:19:31 -0800776
Chris Craikc1c5f082013-09-11 16:23:37 -0700777 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
778 const DeferredDisplayState& state) {
Chris Craik28ce94a2013-05-31 11:38:03 -0700779 deferInfo.batchId = DeferredDisplayList::kOpBatch_Bitmap;
Chris Craikd965bc52013-09-16 14:47:13 -0700780 deferInfo.mergeId = getAtlasEntry() ?
781 (mergeid_t) mEntry->getMergeId() : (mergeid_t) mBitmap;
Romain Guy2db5e992013-05-21 15:29:59 -0700782
Chris Craikd965bc52013-09-16 14:47:13 -0700783 // Don't merge non-simply transformed or neg scale ops, SET_TEXTURE doesn't handle rotation
Chris Craik28ce94a2013-05-31 11:38:03 -0700784 // Don't merge A8 bitmaps - the paint's color isn't compared by mergeId, or in
785 // MergingDrawBatch::canMergeWith()
786 // TODO: support clipped bitmaps by handling them in SET_TEXTURE
Chris Craikd965bc52013-09-16 14:47:13 -0700787 deferInfo.mergeable = state.mMatrix.isSimple() && state.mMatrix.positiveScale() &&
788 !state.mClipSideFlags &&
Chris Craik28ce94a2013-05-31 11:38:03 -0700789 OpenGLRenderer::getXfermodeDirect(mPaint) == SkXfermode::kSrcOver_Mode &&
Chris Craik678625242014-02-28 12:26:34 -0800790 (mBitmap->config() != SkBitmap::kA8_Config);
Chris Craikc3566d02013-02-04 16:16:33 -0800791 }
Chris Craik2af46352012-11-26 18:30:17 -0800792
Chris Craik527a3aa2013-03-04 10:19:31 -0800793 const SkBitmap* bitmap() { return mBitmap; }
Chris Craik2af46352012-11-26 18:30:17 -0800794protected:
Chris Craikd218a922014-01-02 17:13:34 -0800795 const SkBitmap* mBitmap;
Romain Guy55b6f952013-06-27 15:27:09 -0700796 const AssetAtlas& mAtlas;
797 uint32_t mEntryGenerationId;
798 AssetAtlas::Entry* mEntry;
Romain Guy3b748a42013-04-17 18:54:38 -0700799 UvMapper mUvMapper;
Chris Craik2af46352012-11-26 18:30:17 -0800800};
801
802class DrawBitmapMatrixOp : public DrawBoundedOp {
803public:
Chris Craikd218a922014-01-02 17:13:34 -0800804 DrawBitmapMatrixOp(const SkBitmap* bitmap, const SkMatrix* matrix, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -0800805 : DrawBoundedOp(paint), mBitmap(bitmap), mMatrix(matrix) {
806 mLocalBounds.set(0, 0, bitmap->width(), bitmap->height());
807 const mat4 transform(*matrix);
808 transform.mapRect(mLocalBounds);
809 }
810
Chris Craik527a3aa2013-03-04 10:19:31 -0800811 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -0800812 return renderer.drawBitmap(mBitmap, mMatrix, getPaint(renderer));
813 }
814
Chris Craikc5493fb2013-06-19 16:58:58 -0700815 virtual void output(int level, uint32_t logFlags) const {
Chris Craik629f6772014-02-05 13:00:24 -0800816 OP_LOG("Draw bitmap %p matrix " SK_MATRIX_STRING, mBitmap, SK_MATRIX_ARGS(mMatrix));
Chris Craik2af46352012-11-26 18:30:17 -0800817 }
818
Chris Craik527a3aa2013-03-04 10:19:31 -0800819 virtual const char* name() { return "DrawBitmapMatrix"; }
820
Chris Craikc1c5f082013-09-11 16:23:37 -0700821 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
822 const DeferredDisplayState& state) {
Chris Craik28ce94a2013-05-31 11:38:03 -0700823 deferInfo.batchId = DeferredDisplayList::kOpBatch_Bitmap;
Chris Craikc3566d02013-02-04 16:16:33 -0800824 }
Chris Craik2af46352012-11-26 18:30:17 -0800825
826private:
Chris Craikd218a922014-01-02 17:13:34 -0800827 const SkBitmap* mBitmap;
828 const SkMatrix* mMatrix;
Chris Craik2af46352012-11-26 18:30:17 -0800829};
830
831class DrawBitmapRectOp : public DrawBoundedOp {
832public:
Chris Craikd218a922014-01-02 17:13:34 -0800833 DrawBitmapRectOp(const SkBitmap* bitmap,
834 float srcLeft, float srcTop, float srcRight, float srcBottom,
835 float dstLeft, float dstTop, float dstRight, float dstBottom, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -0800836 : DrawBoundedOp(dstLeft, dstTop, dstRight, dstBottom, paint),
837 mBitmap(bitmap), mSrc(srcLeft, srcTop, srcRight, srcBottom) {}
838
Chris Craik527a3aa2013-03-04 10:19:31 -0800839 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -0800840 return renderer.drawBitmap(mBitmap, mSrc.left, mSrc.top, mSrc.right, mSrc.bottom,
841 mLocalBounds.left, mLocalBounds.top, mLocalBounds.right, mLocalBounds.bottom,
842 getPaint(renderer));
843 }
844
Chris Craikc5493fb2013-06-19 16:58:58 -0700845 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800846 OP_LOG("Draw bitmap %p src="RECT_STRING", dst="RECT_STRING,
847 mBitmap, RECT_ARGS(mSrc), RECT_ARGS(mLocalBounds));
848 }
849
850 virtual const char* name() { return "DrawBitmapRect"; }
Chris Craik527a3aa2013-03-04 10:19:31 -0800851
Chris Craikc1c5f082013-09-11 16:23:37 -0700852 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
853 const DeferredDisplayState& state) {
Chris Craik28ce94a2013-05-31 11:38:03 -0700854 deferInfo.batchId = DeferredDisplayList::kOpBatch_Bitmap;
Chris Craikc3566d02013-02-04 16:16:33 -0800855 }
Chris Craik2af46352012-11-26 18:30:17 -0800856
857private:
Chris Craikd218a922014-01-02 17:13:34 -0800858 const SkBitmap* mBitmap;
Chris Craik2af46352012-11-26 18:30:17 -0800859 Rect mSrc;
860};
861
862class DrawBitmapDataOp : public DrawBitmapOp {
863public:
Chris Craikd218a922014-01-02 17:13:34 -0800864 DrawBitmapDataOp(const SkBitmap* bitmap, float left, float top, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -0800865 : DrawBitmapOp(bitmap, left, top, paint) {}
866
Chris Craik527a3aa2013-03-04 10:19:31 -0800867 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -0800868 return renderer.drawBitmapData(mBitmap, mLocalBounds.left,
869 mLocalBounds.top, getPaint(renderer));
870 }
871
Chris Craikc5493fb2013-06-19 16:58:58 -0700872 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800873 OP_LOG("Draw bitmap %p", mBitmap);
874 }
875
876 virtual const char* name() { return "DrawBitmapData"; }
Chris Craik527a3aa2013-03-04 10:19:31 -0800877
Chris Craikc1c5f082013-09-11 16:23:37 -0700878 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
879 const DeferredDisplayState& state) {
Chris Craik28ce94a2013-05-31 11:38:03 -0700880 deferInfo.batchId = DeferredDisplayList::kOpBatch_Bitmap;
Chris Craikc3566d02013-02-04 16:16:33 -0800881 }
Chris Craik2af46352012-11-26 18:30:17 -0800882};
883
Chris Craik5d116762013-02-19 17:49:31 -0800884class DrawBitmapMeshOp : public DrawBoundedOp {
Chris Craik2af46352012-11-26 18:30:17 -0800885public:
Chris Craikd218a922014-01-02 17:13:34 -0800886 DrawBitmapMeshOp(const SkBitmap* bitmap, int meshWidth, int meshHeight,
887 const float* vertices, const int* colors, const SkPaint* paint)
Chris Craik5d116762013-02-19 17:49:31 -0800888 : DrawBoundedOp(vertices, 2 * (meshWidth + 1) * (meshHeight + 1), paint),
889 mBitmap(bitmap), mMeshWidth(meshWidth), mMeshHeight(meshHeight),
Chris Craik2af46352012-11-26 18:30:17 -0800890 mVertices(vertices), mColors(colors) {}
891
Chris Craik527a3aa2013-03-04 10:19:31 -0800892 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -0800893 return renderer.drawBitmapMesh(mBitmap, mMeshWidth, mMeshHeight,
894 mVertices, mColors, getPaint(renderer));
895 }
896
Chris Craikc5493fb2013-06-19 16:58:58 -0700897 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800898 OP_LOG("Draw bitmap %p mesh %d x %d", mBitmap, mMeshWidth, mMeshHeight);
899 }
900
901 virtual const char* name() { return "DrawBitmapMesh"; }
Chris Craik527a3aa2013-03-04 10:19:31 -0800902
Chris Craikc1c5f082013-09-11 16:23:37 -0700903 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
904 const DeferredDisplayState& state) {
Chris Craik28ce94a2013-05-31 11:38:03 -0700905 deferInfo.batchId = DeferredDisplayList::kOpBatch_Bitmap;
Chris Craikc3566d02013-02-04 16:16:33 -0800906 }
Chris Craik2af46352012-11-26 18:30:17 -0800907
908private:
Chris Craikd218a922014-01-02 17:13:34 -0800909 const SkBitmap* mBitmap;
Chris Craik2af46352012-11-26 18:30:17 -0800910 int mMeshWidth;
911 int mMeshHeight;
Chris Craikd218a922014-01-02 17:13:34 -0800912 const float* mVertices;
913 const int* mColors;
Chris Craik2af46352012-11-26 18:30:17 -0800914};
915
916class DrawPatchOp : public DrawBoundedOp {
917public:
Chris Craikd218a922014-01-02 17:13:34 -0800918 DrawPatchOp(const SkBitmap* bitmap, const Res_png_9patch* patch,
919 float left, float top, float right, float bottom, const SkPaint* paint)
Romain Guy03c00b52013-06-20 18:30:28 -0700920 : DrawBoundedOp(left, top, right, bottom, paint),
Romain Guy55b6f952013-06-27 15:27:09 -0700921 mBitmap(bitmap), mPatch(patch), mGenerationId(0), mMesh(NULL),
922 mAtlas(Caches::getInstance().assetAtlas) {
923 mEntry = mAtlas.getEntry(bitmap);
924 if (mEntry) {
925 mEntryGenerationId = mAtlas.getGenerationId();
926 }
Romain Guy3b748a42013-04-17 18:54:38 -0700927 };
Chris Craik2af46352012-11-26 18:30:17 -0800928
Romain Guy55b6f952013-06-27 15:27:09 -0700929 AssetAtlas::Entry* getAtlasEntry() {
930 // The atlas entry is stale, let's get a new one
931 if (mEntry && mEntryGenerationId != mAtlas.getGenerationId()) {
932 mEntryGenerationId = mAtlas.getGenerationId();
933 mEntry = mAtlas.getEntry(mBitmap);
934 }
935 return mEntry;
936 }
937
Romain Guy03c00b52013-06-20 18:30:28 -0700938 const Patch* getMesh(OpenGLRenderer& renderer) {
Romain Guy4c2547f2013-06-11 16:19:24 -0700939 if (!mMesh || renderer.getCaches().patchCache.getGenerationId() != mGenerationId) {
940 PatchCache& cache = renderer.getCaches().patchCache;
Romain Guy55b6f952013-06-27 15:27:09 -0700941 mMesh = cache.get(getAtlasEntry(), mBitmap->width(), mBitmap->height(),
Romain Guy03c00b52013-06-20 18:30:28 -0700942 mLocalBounds.getWidth(), mLocalBounds.getHeight(), mPatch);
Romain Guy4c2547f2013-06-11 16:19:24 -0700943 mGenerationId = cache.getGenerationId();
944 }
Romain Guy03c00b52013-06-20 18:30:28 -0700945 return mMesh;
946 }
947
948 /**
949 * This multi-draw operation builds an indexed mesh on the stack by copying
950 * and transforming the vertices of each 9-patch in the batch. This method
951 * is also responsible for dirtying the current layer, if any.
952 */
953 virtual status_t multiDraw(OpenGLRenderer& renderer, Rect& dirty,
Chris Craikc1c5f082013-09-11 16:23:37 -0700954 const Vector<OpStatePair>& ops, const Rect& bounds) {
955 const DeferredDisplayState& firstState = *(ops[0].state);
956 renderer.restoreDisplayState(firstState, true); // restore all but the clip
Romain Guy03c00b52013-06-20 18:30:28 -0700957
958 // Batches will usually contain a small number of items so it's
959 // worth performing a first iteration to count the exact number
960 // of vertices we need in the new mesh
961 uint32_t totalVertices = 0;
962 for (unsigned int i = 0; i < ops.size(); i++) {
Chris Craikc1c5f082013-09-11 16:23:37 -0700963 totalVertices += ((DrawPatchOp*) ops[i].op)->getMesh(renderer)->verticesCount;
Romain Guy03c00b52013-06-20 18:30:28 -0700964 }
965
966 const bool hasLayer = renderer.hasLayer();
967
968 uint32_t indexCount = 0;
969
970 TextureVertex vertices[totalVertices];
971 TextureVertex* vertex = &vertices[0];
972
973 // Create a mesh that contains the transformed vertices for all the
974 // 9-patch objects that are part of the batch. Note that onDefer()
975 // enforces ops drawn by this function to have a pure translate or
976 // identity matrix
977 for (unsigned int i = 0; i < ops.size(); i++) {
Chris Craikc1c5f082013-09-11 16:23:37 -0700978 DrawPatchOp* patchOp = (DrawPatchOp*) ops[i].op;
979 const DeferredDisplayState* state = ops[i].state;
Romain Guy03c00b52013-06-20 18:30:28 -0700980 const Patch* opMesh = patchOp->getMesh(renderer);
981 uint32_t vertexCount = opMesh->verticesCount;
982 if (vertexCount == 0) continue;
983
984 // We use the bounds to know where to translate our vertices
985 // Using patchOp->state.mBounds wouldn't work because these
986 // bounds are clipped
Chris Craikc1c5f082013-09-11 16:23:37 -0700987 const float tx = (int) floorf(state->mMatrix.getTranslateX() +
Romain Guy03c00b52013-06-20 18:30:28 -0700988 patchOp->mLocalBounds.left + 0.5f);
Chris Craikc1c5f082013-09-11 16:23:37 -0700989 const float ty = (int) floorf(state->mMatrix.getTranslateY() +
Romain Guy03c00b52013-06-20 18:30:28 -0700990 patchOp->mLocalBounds.top + 0.5f);
991
992 // Copy & transform all the vertices for the current operation
993 TextureVertex* opVertices = opMesh->vertices;
994 for (uint32_t j = 0; j < vertexCount; j++, opVertices++) {
995 TextureVertex::set(vertex++,
Romain Guy3380cfd2013-08-15 16:57:57 -0700996 opVertices->x + tx, opVertices->y + ty,
997 opVertices->u, opVertices->v);
Romain Guy03c00b52013-06-20 18:30:28 -0700998 }
999
1000 // Dirty the current layer if possible. When the 9-patch does not
1001 // contain empty quads we can take a shortcut and simply set the
1002 // dirty rect to the object's bounds.
1003 if (hasLayer) {
1004 if (!opMesh->hasEmptyQuads) {
1005 renderer.dirtyLayer(tx, ty,
1006 tx + patchOp->mLocalBounds.getWidth(),
1007 ty + patchOp->mLocalBounds.getHeight());
1008 } else {
1009 const size_t count = opMesh->quads.size();
1010 for (size_t i = 0; i < count; i++) {
1011 const Rect& quadBounds = opMesh->quads[i];
1012 const float x = tx + quadBounds.left;
1013 const float y = ty + quadBounds.top;
1014 renderer.dirtyLayer(x, y,
1015 x + quadBounds.getWidth(), y + quadBounds.getHeight());
1016 }
1017 }
1018 }
1019
1020 indexCount += opMesh->indexCount;
1021 }
1022
Romain Guy55b6f952013-06-27 15:27:09 -07001023 return renderer.drawPatches(mBitmap, getAtlasEntry(),
1024 &vertices[0], indexCount, getPaint(renderer));
Romain Guy03c00b52013-06-20 18:30:28 -07001025 }
1026
1027 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Romain Guy4c2547f2013-06-11 16:19:24 -07001028 // We're not calling the public variant of drawPatch() here
1029 // This method won't perform the quickReject() since we've already done it at this point
Romain Guy55b6f952013-06-27 15:27:09 -07001030 return renderer.drawPatch(mBitmap, getMesh(renderer), getAtlasEntry(),
Romain Guy03c00b52013-06-20 18:30:28 -07001031 mLocalBounds.left, mLocalBounds.top, mLocalBounds.right, mLocalBounds.bottom,
1032 getPaint(renderer));
Chris Craik2af46352012-11-26 18:30:17 -08001033 }
1034
Chris Craikc5493fb2013-06-19 16:58:58 -07001035 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001036 OP_LOG("Draw patch "RECT_STRING, RECT_ARGS(mLocalBounds));
1037 }
1038
1039 virtual const char* name() { return "DrawPatch"; }
Chris Craik527a3aa2013-03-04 10:19:31 -08001040
Chris Craikc1c5f082013-09-11 16:23:37 -07001041 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
1042 const DeferredDisplayState& state) {
Chris Craik28ce94a2013-05-31 11:38:03 -07001043 deferInfo.batchId = DeferredDisplayList::kOpBatch_Patch;
Romain Guy7f6d6b02013-08-06 13:49:28 -07001044 deferInfo.mergeId = getAtlasEntry() ? (mergeid_t) mEntry->getMergeId() : (mergeid_t) mBitmap;
Romain Guy03c00b52013-06-20 18:30:28 -07001045 deferInfo.mergeable = state.mMatrix.isPureTranslate() &&
1046 OpenGLRenderer::getXfermodeDirect(mPaint) == SkXfermode::kSrcOver_Mode;
Chris Craikc1c5f082013-09-11 16:23:37 -07001047 deferInfo.opaqueOverBounds = isOpaqueOverBounds(state) && mBitmap->isOpaque();
Chris Craikc3566d02013-02-04 16:16:33 -08001048 }
Chris Craik2af46352012-11-26 18:30:17 -08001049
1050private:
Chris Craikd218a922014-01-02 17:13:34 -08001051 const SkBitmap* mBitmap;
1052 const Res_png_9patch* mPatch;
Romain Guy4c2547f2013-06-11 16:19:24 -07001053
Romain Guy4c2547f2013-06-11 16:19:24 -07001054 uint32_t mGenerationId;
1055 const Patch* mMesh;
Romain Guy03c00b52013-06-20 18:30:28 -07001056
Romain Guy55b6f952013-06-27 15:27:09 -07001057 const AssetAtlas& mAtlas;
1058 uint32_t mEntryGenerationId;
Romain Guy3b748a42013-04-17 18:54:38 -07001059 AssetAtlas::Entry* mEntry;
Chris Craik2af46352012-11-26 18:30:17 -08001060};
1061
1062class DrawColorOp : public DrawOp {
1063public:
1064 DrawColorOp(int color, SkXfermode::Mode mode)
Chris Craikf57776b2013-10-25 18:30:17 -07001065 : DrawOp(NULL), mColor(color), mMode(mode) {};
Chris Craik2af46352012-11-26 18:30:17 -08001066
Chris Craik527a3aa2013-03-04 10:19:31 -08001067 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001068 return renderer.drawColor(mColor, mMode);
1069 }
1070
Chris Craikc5493fb2013-06-19 16:58:58 -07001071 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001072 OP_LOG("Draw color %#x, mode %d", mColor, mMode);
1073 }
1074
1075 virtual const char* name() { return "DrawColor"; }
1076
1077private:
1078 int mColor;
1079 SkXfermode::Mode mMode;
1080};
1081
1082class DrawStrokableOp : public DrawBoundedOp {
1083public:
Chris Craikd218a922014-01-02 17:13:34 -08001084 DrawStrokableOp(float left, float top, float right, float bottom, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001085 : DrawBoundedOp(left, top, right, bottom, paint) {};
1086
Chris Craikc1c5f082013-09-11 16:23:37 -07001087 bool getLocalBounds(const DrawModifiers& drawModifiers, Rect& localBounds) {
Chris Craikc3566d02013-02-04 16:16:33 -08001088 localBounds.set(mLocalBounds);
Chris Craik2af46352012-11-26 18:30:17 -08001089 if (mPaint && mPaint->getStyle() != SkPaint::kFill_Style) {
Chris Craikc3566d02013-02-04 16:16:33 -08001090 localBounds.outset(strokeWidthOutset());
Chris Craik2af46352012-11-26 18:30:17 -08001091 }
1092 return true;
1093 }
Chris Craikc3566d02013-02-04 16:16:33 -08001094
Chris Craikc1c5f082013-09-11 16:23:37 -07001095 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
1096 const DeferredDisplayState& state) {
Chris Craikc3566d02013-02-04 16:16:33 -08001097 if (mPaint->getPathEffect()) {
Chris Craik28ce94a2013-05-31 11:38:03 -07001098 deferInfo.batchId = DeferredDisplayList::kOpBatch_AlphaMaskTexture;
Chris Craik527a3aa2013-03-04 10:19:31 -08001099 } else {
Chris Craik28ce94a2013-05-31 11:38:03 -07001100 deferInfo.batchId = mPaint->isAntiAlias() ?
Chris Craik527a3aa2013-03-04 10:19:31 -08001101 DeferredDisplayList::kOpBatch_AlphaVertices :
1102 DeferredDisplayList::kOpBatch_Vertices;
Chris Craikc3566d02013-02-04 16:16:33 -08001103 }
Chris Craikc3566d02013-02-04 16:16:33 -08001104 }
Chris Craik2af46352012-11-26 18:30:17 -08001105};
1106
1107class DrawRectOp : public DrawStrokableOp {
1108public:
Chris Craikd218a922014-01-02 17:13:34 -08001109 DrawRectOp(float left, float top, float right, float bottom, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001110 : DrawStrokableOp(left, top, right, bottom, paint) {}
1111
Chris Craik527a3aa2013-03-04 10:19:31 -08001112 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001113 return renderer.drawRect(mLocalBounds.left, mLocalBounds.top,
1114 mLocalBounds.right, mLocalBounds.bottom, getPaint(renderer));
1115 }
1116
Chris Craikc5493fb2013-06-19 16:58:58 -07001117 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001118 OP_LOG("Draw Rect "RECT_STRING, RECT_ARGS(mLocalBounds));
1119 }
1120
Chris Craikc1c5f082013-09-11 16:23:37 -07001121 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
1122 const DeferredDisplayState& state) {
1123 DrawStrokableOp::onDefer(renderer, deferInfo, state);
1124 deferInfo.opaqueOverBounds = isOpaqueOverBounds(state) &&
Chris Craik28ce94a2013-05-31 11:38:03 -07001125 mPaint->getStyle() == SkPaint::kFill_Style;
1126 }
1127
Chris Craik2af46352012-11-26 18:30:17 -08001128 virtual const char* name() { return "DrawRect"; }
1129};
1130
Chris Craik5d116762013-02-19 17:49:31 -08001131class DrawRectsOp : public DrawBoundedOp {
Chris Craik2af46352012-11-26 18:30:17 -08001132public:
Chris Craikd218a922014-01-02 17:13:34 -08001133 DrawRectsOp(const float* rects, int count, const SkPaint* paint)
Chris Craik5d116762013-02-19 17:49:31 -08001134 : DrawBoundedOp(rects, count, paint),
1135 mRects(rects), mCount(count) {}
Chris Craik2af46352012-11-26 18:30:17 -08001136
Chris Craik527a3aa2013-03-04 10:19:31 -08001137 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001138 return renderer.drawRects(mRects, mCount, getPaint(renderer));
1139 }
1140
Chris Craikc5493fb2013-06-19 16:58:58 -07001141 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001142 OP_LOG("Draw Rects count %d", mCount);
1143 }
1144
1145 virtual const char* name() { return "DrawRects"; }
1146
Chris Craikc1c5f082013-09-11 16:23:37 -07001147 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
1148 const DeferredDisplayState& state) {
Chris Craik28ce94a2013-05-31 11:38:03 -07001149 deferInfo.batchId = DeferredDisplayList::kOpBatch_Vertices;
Chris Craikc3566d02013-02-04 16:16:33 -08001150 }
1151
Chris Craik2af46352012-11-26 18:30:17 -08001152private:
1153 const float* mRects;
1154 int mCount;
1155};
1156
1157class DrawRoundRectOp : public DrawStrokableOp {
1158public:
1159 DrawRoundRectOp(float left, float top, float right, float bottom,
Chris Craikd218a922014-01-02 17:13:34 -08001160 float rx, float ry, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001161 : DrawStrokableOp(left, top, right, bottom, paint), mRx(rx), mRy(ry) {}
1162
Chris Craik527a3aa2013-03-04 10:19:31 -08001163 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001164 return renderer.drawRoundRect(mLocalBounds.left, mLocalBounds.top,
1165 mLocalBounds.right, mLocalBounds.bottom, mRx, mRy, getPaint(renderer));
1166 }
1167
Chris Craikc5493fb2013-06-19 16:58:58 -07001168 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001169 OP_LOG("Draw RoundRect "RECT_STRING", rx %f, ry %f", RECT_ARGS(mLocalBounds), mRx, mRy);
1170 }
1171
1172 virtual const char* name() { return "DrawRoundRect"; }
1173
1174private:
1175 float mRx;
1176 float mRy;
1177};
1178
1179class DrawCircleOp : public DrawStrokableOp {
1180public:
Chris Craikd218a922014-01-02 17:13:34 -08001181 DrawCircleOp(float x, float y, float radius, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001182 : DrawStrokableOp(x - radius, y - radius, x + radius, y + radius, paint),
1183 mX(x), mY(y), mRadius(radius) {}
1184
Chris Craik527a3aa2013-03-04 10:19:31 -08001185 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001186 return renderer.drawCircle(mX, mY, mRadius, getPaint(renderer));
1187 }
1188
Chris Craikc5493fb2013-06-19 16:58:58 -07001189 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001190 OP_LOG("Draw Circle x %f, y %f, r %f", mX, mY, mRadius);
1191 }
1192
1193 virtual const char* name() { return "DrawCircle"; }
1194
1195private:
1196 float mX;
1197 float mY;
1198 float mRadius;
1199};
1200
John Reck52244ff2014-05-01 21:27:37 -07001201class DrawCirclePropsOp : public DrawOp {
1202public:
1203 DrawCirclePropsOp(float* x, float* y, float* radius, const SkPaint* paint)
1204 : DrawOp(paint), mX(x), mY(y), mRadius(radius) {}
1205
1206 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
1207 return renderer.drawCircle(*mX, *mY, *mRadius, getPaint(renderer));
1208 }
1209
1210 virtual void output(int level, uint32_t logFlags) const {
1211 OP_LOG("Draw Circle Props x %p, y %p, r %p", mX, mY, mRadius);
1212 }
1213
1214 virtual const char* name() { return "DrawCircleProps"; }
1215
1216private:
1217 float* mX;
1218 float* mY;
1219 float* mRadius;
1220};
1221
Chris Craik2af46352012-11-26 18:30:17 -08001222class DrawOvalOp : public DrawStrokableOp {
1223public:
Chris Craikd218a922014-01-02 17:13:34 -08001224 DrawOvalOp(float left, float top, float right, float bottom, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001225 : DrawStrokableOp(left, top, right, bottom, paint) {}
1226
Chris Craik527a3aa2013-03-04 10:19:31 -08001227 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001228 return renderer.drawOval(mLocalBounds.left, mLocalBounds.top,
1229 mLocalBounds.right, mLocalBounds.bottom, getPaint(renderer));
1230 }
1231
Chris Craikc5493fb2013-06-19 16:58:58 -07001232 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001233 OP_LOG("Draw Oval "RECT_STRING, RECT_ARGS(mLocalBounds));
1234 }
1235
1236 virtual const char* name() { return "DrawOval"; }
1237};
1238
1239class DrawArcOp : public DrawStrokableOp {
1240public:
1241 DrawArcOp(float left, float top, float right, float bottom,
Chris Craikd218a922014-01-02 17:13:34 -08001242 float startAngle, float sweepAngle, bool useCenter, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001243 : DrawStrokableOp(left, top, right, bottom, paint),
1244 mStartAngle(startAngle), mSweepAngle(sweepAngle), mUseCenter(useCenter) {}
1245
Chris Craik527a3aa2013-03-04 10:19:31 -08001246 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001247 return renderer.drawArc(mLocalBounds.left, mLocalBounds.top,
1248 mLocalBounds.right, mLocalBounds.bottom,
1249 mStartAngle, mSweepAngle, mUseCenter, getPaint(renderer));
1250 }
1251
Chris Craikc5493fb2013-06-19 16:58:58 -07001252 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001253 OP_LOG("Draw Arc "RECT_STRING", start %f, sweep %f, useCenter %d",
1254 RECT_ARGS(mLocalBounds), mStartAngle, mSweepAngle, mUseCenter);
1255 }
1256
1257 virtual const char* name() { return "DrawArc"; }
1258
1259private:
1260 float mStartAngle;
1261 float mSweepAngle;
1262 bool mUseCenter;
1263};
1264
1265class DrawPathOp : public DrawBoundedOp {
1266public:
Chris Craikd218a922014-01-02 17:13:34 -08001267 DrawPathOp(const SkPath* path, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001268 : DrawBoundedOp(paint), mPath(path) {
1269 float left, top, offset;
1270 uint32_t width, height;
Romain Guyca89e2a2013-03-08 17:44:20 -08001271 PathCache::computePathBounds(path, paint, left, top, offset, width, height);
Chris Craik2af46352012-11-26 18:30:17 -08001272 left -= offset;
1273 top -= offset;
1274 mLocalBounds.set(left, top, left + width, top + height);
1275 }
1276
Chris Craik527a3aa2013-03-04 10:19:31 -08001277 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001278 return renderer.drawPath(mPath, getPaint(renderer));
1279 }
1280
Chris Craikc1c5f082013-09-11 16:23:37 -07001281 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
1282 const DeferredDisplayState& state) {
Chris Craikd218a922014-01-02 17:13:34 -08001283 const SkPaint* paint = getPaint(renderer);
Romain Guyca89e2a2013-03-08 17:44:20 -08001284 renderer.getCaches().pathCache.precache(mPath, paint);
Chris Craik527a3aa2013-03-04 10:19:31 -08001285
Chris Craik28ce94a2013-05-31 11:38:03 -07001286 deferInfo.batchId = DeferredDisplayList::kOpBatch_AlphaMaskTexture;
Romain Guyca89e2a2013-03-08 17:44:20 -08001287 }
1288
Chris Craikc5493fb2013-06-19 16:58:58 -07001289 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001290 OP_LOG("Draw Path %p in "RECT_STRING, mPath, RECT_ARGS(mLocalBounds));
1291 }
1292
1293 virtual const char* name() { return "DrawPath"; }
1294
1295private:
Chris Craikd218a922014-01-02 17:13:34 -08001296 const SkPath* mPath;
Chris Craik2af46352012-11-26 18:30:17 -08001297};
1298
Chris Craikc3566d02013-02-04 16:16:33 -08001299class DrawLinesOp : public DrawBoundedOp {
Chris Craik2af46352012-11-26 18:30:17 -08001300public:
Chris Craikd218a922014-01-02 17:13:34 -08001301 DrawLinesOp(const float* points, int count, const SkPaint* paint)
Chris Craik5d116762013-02-19 17:49:31 -08001302 : DrawBoundedOp(points, count, paint),
1303 mPoints(points), mCount(count) {
Chris Craikc3566d02013-02-04 16:16:33 -08001304 mLocalBounds.outset(strokeWidthOutset());
Chris Craik2af46352012-11-26 18:30:17 -08001305 }
1306
Chris Craik527a3aa2013-03-04 10:19:31 -08001307 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001308 return renderer.drawLines(mPoints, mCount, getPaint(renderer));
1309 }
1310
Chris Craikc5493fb2013-06-19 16:58:58 -07001311 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001312 OP_LOG("Draw Lines count %d", mCount);
1313 }
1314
1315 virtual const char* name() { return "DrawLines"; }
1316
Chris Craikc1c5f082013-09-11 16:23:37 -07001317 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
1318 const DeferredDisplayState& state) {
Chris Craik28ce94a2013-05-31 11:38:03 -07001319 deferInfo.batchId = mPaint->isAntiAlias() ?
Chris Craikc3566d02013-02-04 16:16:33 -08001320 DeferredDisplayList::kOpBatch_AlphaVertices :
1321 DeferredDisplayList::kOpBatch_Vertices;
1322 }
1323
Chris Craik2af46352012-11-26 18:30:17 -08001324protected:
Chris Craikd218a922014-01-02 17:13:34 -08001325 const float* mPoints;
Chris Craik2af46352012-11-26 18:30:17 -08001326 int mCount;
1327};
1328
1329class DrawPointsOp : public DrawLinesOp {
1330public:
Chris Craikd218a922014-01-02 17:13:34 -08001331 DrawPointsOp(const float* points, int count, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001332 : DrawLinesOp(points, count, paint) {}
1333
Chris Craik527a3aa2013-03-04 10:19:31 -08001334 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001335 return renderer.drawPoints(mPoints, mCount, getPaint(renderer));
1336 }
1337
Chris Craikc5493fb2013-06-19 16:58:58 -07001338 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001339 OP_LOG("Draw Points count %d", mCount);
1340 }
1341
1342 virtual const char* name() { return "DrawPoints"; }
1343};
1344
1345class DrawSomeTextOp : public DrawOp {
1346public:
Chris Craikd218a922014-01-02 17:13:34 -08001347 DrawSomeTextOp(const char* text, int bytesCount, int count, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001348 : DrawOp(paint), mText(text), mBytesCount(bytesCount), mCount(count) {};
1349
Chris Craikc5493fb2013-06-19 16:58:58 -07001350 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001351 OP_LOG("Draw some text, %d bytes", mBytesCount);
1352 }
Chris Craikc3566d02013-02-04 16:16:33 -08001353
Chris Craikc1c5f082013-09-11 16:23:37 -07001354 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
1355 const DeferredDisplayState& state) {
Chris Craikd218a922014-01-02 17:13:34 -08001356 const SkPaint* paint = getPaint(renderer);
Romain Guy0f6675332013-03-01 14:31:04 -08001357 FontRenderer& fontRenderer = renderer.getCaches().fontRenderer->getFontRenderer(paint);
1358 fontRenderer.precache(paint, mText, mCount, mat4::identity());
Romain Guy0f6675332013-03-01 14:31:04 -08001359
Chris Craik28ce94a2013-05-31 11:38:03 -07001360 deferInfo.batchId = mPaint->getColor() == 0xff000000 ?
Chris Craikc3566d02013-02-04 16:16:33 -08001361 DeferredDisplayList::kOpBatch_Text :
1362 DeferredDisplayList::kOpBatch_ColorText;
1363 }
Chris Craik527a3aa2013-03-04 10:19:31 -08001364
Chris Craik2af46352012-11-26 18:30:17 -08001365protected:
1366 const char* mText;
1367 int mBytesCount;
1368 int mCount;
1369};
1370
1371class DrawTextOnPathOp : public DrawSomeTextOp {
1372public:
1373 DrawTextOnPathOp(const char* text, int bytesCount, int count,
Chris Craikd218a922014-01-02 17:13:34 -08001374 const SkPath* path, float hOffset, float vOffset, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001375 : DrawSomeTextOp(text, bytesCount, count, paint),
1376 mPath(path), mHOffset(hOffset), mVOffset(vOffset) {
1377 /* TODO: inherit from DrawBounded and init mLocalBounds */
1378 }
1379
Chris Craik527a3aa2013-03-04 10:19:31 -08001380 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001381 return renderer.drawTextOnPath(mText, mBytesCount, mCount, mPath,
1382 mHOffset, mVOffset, getPaint(renderer));
1383 }
1384
1385 virtual const char* name() { return "DrawTextOnPath"; }
1386
1387private:
Chris Craikd218a922014-01-02 17:13:34 -08001388 const SkPath* mPath;
Chris Craik2af46352012-11-26 18:30:17 -08001389 float mHOffset;
1390 float mVOffset;
1391};
1392
1393class DrawPosTextOp : public DrawSomeTextOp {
1394public:
1395 DrawPosTextOp(const char* text, int bytesCount, int count,
Chris Craikd218a922014-01-02 17:13:34 -08001396 const float* positions, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001397 : DrawSomeTextOp(text, bytesCount, count, paint), mPositions(positions) {
1398 /* TODO: inherit from DrawBounded and init mLocalBounds */
1399 }
1400
Chris Craik527a3aa2013-03-04 10:19:31 -08001401 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001402 return renderer.drawPosText(mText, mBytesCount, mCount, mPositions, getPaint(renderer));
1403 }
1404
1405 virtual const char* name() { return "DrawPosText"; }
1406
1407private:
1408 const float* mPositions;
1409};
1410
1411class DrawTextOp : public DrawBoundedOp {
1412public:
1413 DrawTextOp(const char* text, int bytesCount, int count, float x, float y,
Chris Craikd218a922014-01-02 17:13:34 -08001414 const float* positions, const SkPaint* paint, float totalAdvance, const Rect& bounds)
Chris Craik41541822013-05-03 16:35:54 -07001415 : DrawBoundedOp(bounds, paint), mText(text), mBytesCount(bytesCount), mCount(count),
1416 mX(x), mY(y), mPositions(positions), mTotalAdvance(totalAdvance) {
Romain Guybd3055f2013-03-13 16:14:47 -07001417 memset(&mPrecacheTransform.data[0], 0xff, 16 * sizeof(float));
Chris Craik2af46352012-11-26 18:30:17 -08001418 }
1419
Chris Craikc1c5f082013-09-11 16:23:37 -07001420 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
1421 const DeferredDisplayState& state) {
Chris Craikd218a922014-01-02 17:13:34 -08001422 const SkPaint* paint = getPaint(renderer);
Romain Guy0f6675332013-03-01 14:31:04 -08001423 FontRenderer& fontRenderer = renderer.getCaches().fontRenderer->getFontRenderer(paint);
Romain Guybd3055f2013-03-13 16:14:47 -07001424 const mat4& transform = renderer.findBestFontTransform(state.mMatrix);
1425 if (mPrecacheTransform != transform) {
1426 fontRenderer.precache(paint, mText, mCount, transform);
1427 mPrecacheTransform = transform;
1428 }
Chris Craik28ce94a2013-05-31 11:38:03 -07001429 deferInfo.batchId = mPaint->getColor() == 0xff000000 ?
Chris Craik527a3aa2013-03-04 10:19:31 -08001430 DeferredDisplayList::kOpBatch_Text :
1431 DeferredDisplayList::kOpBatch_ColorText;
1432
Kévin PETIT73fc5582014-02-13 11:03:40 +00001433 deferInfo.mergeId = reinterpret_cast<mergeid_t>(mPaint->getColor());
Chris Craik527a3aa2013-03-04 10:19:31 -08001434
1435 // don't merge decorated text - the decorations won't draw in order
1436 bool noDecorations = !(mPaint->getFlags() & (SkPaint::kUnderlineText_Flag |
1437 SkPaint::kStrikeThruText_Flag));
Chris Craik28ce94a2013-05-31 11:38:03 -07001438 deferInfo.mergeable = state.mMatrix.isPureTranslate() && noDecorations &&
1439 OpenGLRenderer::getXfermodeDirect(mPaint) == SkXfermode::kSrcOver_Mode;
Romain Guy0f6675332013-03-01 14:31:04 -08001440 }
1441
Chris Craik527a3aa2013-03-04 10:19:31 -08001442 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Romain Guy9b5a1a22013-08-09 14:06:29 -07001443 Rect bounds;
Chris Craikc1c5f082013-09-11 16:23:37 -07001444 getLocalBounds(renderer.getDrawModifiers(), bounds);
Chris Craik2af46352012-11-26 18:30:17 -08001445 return renderer.drawText(mText, mBytesCount, mCount, mX, mY,
Romain Guy9b5a1a22013-08-09 14:06:29 -07001446 mPositions, getPaint(renderer), mTotalAdvance, bounds);
Chris Craik2af46352012-11-26 18:30:17 -08001447 }
1448
Chris Craik527a3aa2013-03-04 10:19:31 -08001449 virtual status_t multiDraw(OpenGLRenderer& renderer, Rect& dirty,
Chris Craikc1c5f082013-09-11 16:23:37 -07001450 const Vector<OpStatePair>& ops, const Rect& bounds) {
Chris Craik527a3aa2013-03-04 10:19:31 -08001451 status_t status = DrawGlInfo::kStatusDone;
Chris Craik527a3aa2013-03-04 10:19:31 -08001452 for (unsigned int i = 0; i < ops.size(); i++) {
Chris Craikc1c5f082013-09-11 16:23:37 -07001453 const DeferredDisplayState& state = *(ops[i].state);
Chris Craik527a3aa2013-03-04 10:19:31 -08001454 DrawOpMode drawOpMode = (i == ops.size() - 1) ? kDrawOpMode_Flush : kDrawOpMode_Defer;
Chris Craikc1c5f082013-09-11 16:23:37 -07001455 renderer.restoreDisplayState(state, true); // restore all but the clip
Chris Craik527a3aa2013-03-04 10:19:31 -08001456
Chris Craikc1c5f082013-09-11 16:23:37 -07001457 DrawTextOp& op = *((DrawTextOp*)ops[i].op);
Romain Guy9b5a1a22013-08-09 14:06:29 -07001458 // quickReject() will not occure in drawText() so we can use mLocalBounds
1459 // directly, we do not need to account for shadow by calling getLocalBounds()
Chris Craik527a3aa2013-03-04 10:19:31 -08001460 status |= renderer.drawText(op.mText, op.mBytesCount, op.mCount, op.mX, op.mY,
Chris Craik41541822013-05-03 16:35:54 -07001461 op.mPositions, op.getPaint(renderer), op.mTotalAdvance, op.mLocalBounds,
1462 drawOpMode);
Chris Craik527a3aa2013-03-04 10:19:31 -08001463 }
1464 return status;
1465 }
1466
Chris Craikc5493fb2013-06-19 16:58:58 -07001467 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001468 OP_LOG("Draw Text of count %d, bytes %d", mCount, mBytesCount);
1469 }
1470
1471 virtual const char* name() { return "DrawText"; }
1472
1473private:
1474 const char* mText;
1475 int mBytesCount;
1476 int mCount;
1477 float mX;
1478 float mY;
1479 const float* mPositions;
Chris Craik41541822013-05-03 16:35:54 -07001480 float mTotalAdvance;
Romain Guybd3055f2013-03-13 16:14:47 -07001481 mat4 mPrecacheTransform;
Chris Craik2af46352012-11-26 18:30:17 -08001482};
1483
1484///////////////////////////////////////////////////////////////////////////////
1485// SPECIAL DRAW OPERATIONS
1486///////////////////////////////////////////////////////////////////////////////
1487
1488class DrawFunctorOp : public DrawOp {
1489public:
1490 DrawFunctorOp(Functor* functor)
Chris Craikf57776b2013-10-25 18:30:17 -07001491 : DrawOp(NULL), mFunctor(functor) {}
Chris Craik2af46352012-11-26 18:30:17 -08001492
Chris Craik527a3aa2013-03-04 10:19:31 -08001493 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001494 renderer.startMark("GL functor");
1495 status_t ret = renderer.callDrawGLFunction(mFunctor, dirty);
1496 renderer.endMark();
1497 return ret;
1498 }
1499
Chris Craikc5493fb2013-06-19 16:58:58 -07001500 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001501 OP_LOG("Draw Functor %p", mFunctor);
1502 }
1503
1504 virtual const char* name() { return "DrawFunctor"; }
1505
1506private:
1507 Functor* mFunctor;
1508};
1509
Chris Craik5d116762013-02-19 17:49:31 -08001510class DrawDisplayListOp : public DrawBoundedOp {
John Recke18264b2014-03-12 13:56:30 -07001511 friend class RenderNode; // grant DisplayList access to info of child
Chris Craik2af46352012-11-26 18:30:17 -08001512public:
John Recke18264b2014-03-12 13:56:30 -07001513 DrawDisplayListOp(RenderNode* displayList, int flags, const mat4& transformFromParent)
Chris Craik5d116762013-02-19 17:49:31 -08001514 : DrawBoundedOp(0, 0, displayList->getWidth(), displayList->getHeight(), 0),
Chris Craikf57776b2013-10-25 18:30:17 -07001515 mDisplayList(displayList), mFlags(flags), mTransformFromParent(transformFromParent) {}
Chris Craikc3566d02013-02-04 16:16:33 -08001516
Chet Haasedd671592013-04-19 14:54:34 -07001517 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
1518 bool useQuickReject) {
Chris Craikf57776b2013-10-25 18:30:17 -07001519 if (mDisplayList && mDisplayList->isRenderable() && !mSkipInOrderDraw) {
Chris Craikb265e2c2014-03-27 15:50:09 -07001520 mDisplayList->deferNodeInParent(deferStruct, level + 1);
Chris Craikc3566d02013-02-04 16:16:33 -08001521 }
Chris Craikc3566d02013-02-04 16:16:33 -08001522 }
Chet Haasedd671592013-04-19 14:54:34 -07001523 virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level,
1524 bool useQuickReject) {
Chris Craikf57776b2013-10-25 18:30:17 -07001525 if (mDisplayList && mDisplayList->isRenderable() && !mSkipInOrderDraw) {
Chris Craikb265e2c2014-03-27 15:50:09 -07001526 mDisplayList->replayNodeInParent(replayStruct, level + 1);
Chris Craikff785832013-03-08 13:12:16 -08001527 }
1528 }
Chris Craik2af46352012-11-26 18:30:17 -08001529
Chris Craika08f95c2013-03-15 17:24:33 -07001530 // NOT USED since replay() is overridden
Chris Craik527a3aa2013-03-04 10:19:31 -08001531 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craika08f95c2013-03-15 17:24:33 -07001532 return DrawGlInfo::kStatusDone;
1533 }
Chris Craikff785832013-03-08 13:12:16 -08001534
Chris Craikc5493fb2013-06-19 16:58:58 -07001535 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001536 OP_LOG("Draw Display List %p, flags %#x", mDisplayList, mFlags);
Chris Craikff785832013-03-08 13:12:16 -08001537 if (mDisplayList && (logFlags & kOpLogFlag_Recurse)) {
Chris Craik2af46352012-11-26 18:30:17 -08001538 mDisplayList->output(level + 1);
1539 }
1540 }
1541
1542 virtual const char* name() { return "DrawDisplayList"; }
1543
John Reck087bc0c2014-04-04 16:20:08 -07001544 RenderNode* renderNode() { return mDisplayList; }
1545
Chris Craik2af46352012-11-26 18:30:17 -08001546private:
John Recke18264b2014-03-12 13:56:30 -07001547 RenderNode* mDisplayList;
Chris Craikf57776b2013-10-25 18:30:17 -07001548 const int mFlags;
1549
1550 ///////////////////////////
1551 // Properties below are used by DisplayList::computeOrderingImpl() and iterate()
1552 ///////////////////////////
1553 /**
1554 * Records transform vs parent, used for computing total transform without rerunning DL contents
1555 */
1556 const mat4 mTransformFromParent;
1557
1558 /**
Chris Craikb79a3e32014-03-11 12:20:17 -07001559 * Holds the transformation between the projection surface ViewGroup and this DisplayList
1560 * drawing instance. Represents any translations / transformations done within the drawing of
1561 * the compositing ancestor ViewGroup's draw, before the draw of the View represented by this
1562 * DisplayList draw instance.
Chris Craikf57776b2013-10-25 18:30:17 -07001563 *
1564 * Note: doesn't include any transformation recorded within the DisplayList and its properties.
1565 */
Chris Craikf533e942014-01-14 22:35:37 -08001566 mat4 mTransformFromCompositingAncestor;
Chris Craikf57776b2013-10-25 18:30:17 -07001567 bool mSkipInOrderDraw;
1568};
1569
1570/**
Chris Craik024433f2014-03-26 13:19:14 -07001571 * Not a canvas operation, used only by 3d / z ordering logic in RenderNode::iterate()
Chris Craikf57776b2013-10-25 18:30:17 -07001572 */
1573class DrawShadowOp : public DrawOp {
1574public:
Chris Craik024433f2014-03-26 13:19:14 -07001575 DrawShadowOp(const mat4& transformXY, const mat4& transformZ,
1576 float casterAlpha, bool casterUnclipped,
Chris Craik8c271ca2014-03-25 10:33:01 -07001577 float fallbackWidth, float fallbackHeight,
1578 const SkPath* outline, const SkPath* revealClip)
Chris Craik024433f2014-03-26 13:19:14 -07001579 : DrawOp(NULL), mTransformXY(transformXY), mTransformZ(transformZ),
1580 mCasterAlpha(casterAlpha), mCasterUnclipped(casterUnclipped),
Chris Craik8c271ca2014-03-25 10:33:01 -07001581 mFallbackWidth(fallbackWidth), mFallbackHeight(fallbackHeight),
1582 mOutline(outline), mRevealClip(revealClip) {}
Chris Craikf57776b2013-10-25 18:30:17 -07001583
1584 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik8c271ca2014-03-25 10:33:01 -07001585 SkPath casterPerimeter;
1586 if (!mOutline || mOutline->isEmpty()) {
1587 casterPerimeter.addRect(0, 0, mFallbackWidth, mFallbackHeight);
1588 } else {
1589 casterPerimeter = *mOutline;
Chris Craika2fe7af2014-01-28 17:25:06 -08001590 }
1591
Chris Craik8c271ca2014-03-25 10:33:01 -07001592 if (mRevealClip) {
1593 // intersect the outline with the convex reveal clip
1594 Op(casterPerimeter, *mRevealClip, kIntersect_PathOp, &casterPerimeter);
1595 }
1596
Chris Craik024433f2014-03-26 13:19:14 -07001597 return renderer.drawShadow(mTransformXY, mTransformZ,
1598 mCasterAlpha, mCasterUnclipped, &casterPerimeter);
Chris Craikf57776b2013-10-25 18:30:17 -07001599 }
1600
1601 virtual void output(int level, uint32_t logFlags) const {
Chris Craika2fe7af2014-01-28 17:25:06 -08001602 OP_LOG("DrawShadow of outline %p", mOutline);
Chris Craikf57776b2013-10-25 18:30:17 -07001603 }
1604
1605 virtual const char* name() { return "DrawShadow"; }
1606
1607private:
Chris Craikb79a3e32014-03-11 12:20:17 -07001608 const mat4 mTransformXY;
1609 const mat4 mTransformZ;
Chris Craik024433f2014-03-26 13:19:14 -07001610 const float mCasterAlpha;
1611 const bool mCasterUnclipped;
Chris Craika2fe7af2014-01-28 17:25:06 -08001612 const float mFallbackWidth;
1613 const float mFallbackHeight;
Chris Craik8c271ca2014-03-25 10:33:01 -07001614
1615 // these point at convex SkPaths owned by RenderProperties, or null
1616 const SkPath* mOutline;
1617 const SkPath* mRevealClip;
Chris Craik2af46352012-11-26 18:30:17 -08001618};
1619
1620class DrawLayerOp : public DrawOp {
1621public:
Chris Craika08f95c2013-03-15 17:24:33 -07001622 DrawLayerOp(Layer* layer, float x, float y)
Chris Craikf57776b2013-10-25 18:30:17 -07001623 : DrawOp(NULL), mLayer(layer), mX(x), mY(y) {}
Chris Craik2af46352012-11-26 18:30:17 -08001624
Chris Craik527a3aa2013-03-04 10:19:31 -08001625 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craika08f95c2013-03-15 17:24:33 -07001626 return renderer.drawLayer(mLayer, mX, mY);
Chris Craik2af46352012-11-26 18:30:17 -08001627 }
1628
Chris Craikc5493fb2013-06-19 16:58:58 -07001629 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001630 OP_LOG("Draw Layer %p at %f %f", mLayer, mX, mY);
1631 }
1632
1633 virtual const char* name() { return "DrawLayer"; }
1634
1635private:
1636 Layer* mLayer;
1637 float mX;
1638 float mY;
1639};
1640
1641}; // namespace uirenderer
1642}; // namespace android
1643
1644#endif // ANDROID_HWUI_DISPLAY_OPERATION_H