blob: d4f82eaa27e0f22f68d156c675ac81812b345202 [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 Craik2af46352012-11-26 18:30:17 -080024#include <SkXfermode.h>
25
Chris Craik0776a602013-02-14 15:36:01 -080026#include <private/hwui/DrawGlInfo.h>
27
Chris Craik2af46352012-11-26 18:30:17 -080028#include "OpenGLRenderer.h"
Romain Guy3b748a42013-04-17 18:54:38 -070029#include "AssetAtlas.h"
Chris Craikc3566d02013-02-04 16:16:33 -080030#include "DeferredDisplayList.h"
Chris Craik2af46352012-11-26 18:30:17 -080031#include "DisplayListRenderer.h"
Romain Guy3b748a42013-04-17 18:54:38 -070032#include "UvMapper.h"
Chris Craik2af46352012-11-26 18:30:17 -080033#include "utils/LinearAllocator.h"
34
35#define CRASH() do { \
Romain Guy5216c3b2013-06-14 16:31:37 -070036 *(int *)(uintptr_t) 0xbbadbeef = 0; \
Chris Craik2af46352012-11-26 18:30:17 -080037 ((void(*)())0)(); /* More reliable, but doesn't say BBADBEEF */ \
38} while(false)
39
Chris Craik2af46352012-11-26 18:30:17 -080040// Use OP_LOG for logging with arglist, OP_LOGS if just printing char*
Chris Craik28ce94a2013-05-31 11:38:03 -070041#define OP_LOGS(s) OP_LOG("%s", (s))
Chris Craik3dc553b2013-02-04 12:45:13 -080042#define OP_LOG(s, ...) ALOGD( "%*s" s, level * 2, "", __VA_ARGS__ )
Chris Craik2af46352012-11-26 18:30:17 -080043
Chris Craik2af46352012-11-26 18:30:17 -080044namespace android {
45namespace uirenderer {
46
47/**
48 * Structure for storing canvas operations when they are recorded into a DisplayList, so that they
49 * may be replayed to an OpenGLRenderer.
50 *
51 * To avoid individual memory allocations, DisplayListOps may only be allocated into a
52 * LinearAllocator's managed memory buffers. Each pointer held by a DisplayListOp is either a
53 * pointer into memory also allocated in the LinearAllocator (mostly for text and float buffers) or
54 * references a externally refcounted object (Sk... and Skia... objects). ~DisplayListOp() is
55 * never called as LinearAllocators are simply discarded, so no memory management should be done in
56 * this class.
57 */
58class DisplayListOp {
59public:
60 // These objects should always be allocated with a LinearAllocator, and never destroyed/deleted.
61 // standard new() intentionally not implemented, and delete/deconstructor should never be used.
62 virtual ~DisplayListOp() { CRASH(); }
63 static void operator delete(void* ptr) { CRASH(); }
64 /** static void* operator new(size_t size); PURPOSELY OMITTED **/
65 static void* operator new(size_t size, LinearAllocator& allocator) {
66 return allocator.alloc(size);
67 }
68
69 enum OpLogFlag {
70 kOpLogFlag_Recurse = 0x1,
71 kOpLogFlag_JSON = 0x2 // TODO: add?
72 };
73
Chet Haasedd671592013-04-19 14:54:34 -070074 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
75 bool useQuickReject) = 0;
Chris Craikc3566d02013-02-04 16:16:33 -080076
Chet Haasedd671592013-04-19 14:54:34 -070077 virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level,
78 bool useQuickReject) = 0;
Chris Craikff785832013-03-08 13:12:16 -080079
Chris Craikc5493fb2013-06-19 16:58:58 -070080 virtual void output(int level, uint32_t logFlags = 0) const = 0;
Chris Craik2af46352012-11-26 18:30:17 -080081
82 // NOTE: it would be nice to declare constants and overriding the implementation in each op to
83 // point at the constants, but that seems to require a .cpp file
84 virtual const char* name() = 0;
85};
86
87class StateOp : public DisplayListOp {
88public:
89 StateOp() {};
90
91 virtual ~StateOp() {}
92
Chet Haasedd671592013-04-19 14:54:34 -070093 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
94 bool useQuickReject) {
Chris Craikff785832013-03-08 13:12:16 -080095 // default behavior only affects immediate, deferrable state, issue directly to renderer
96 applyState(deferStruct.mRenderer, saveCount);
97 }
98
Chris Craikc3566d02013-02-04 16:16:33 -080099 /**
100 * State operations are applied directly to the renderer, but can cause the deferred drawing op
101 * list to flush
102 */
Chet Haasedd671592013-04-19 14:54:34 -0700103 virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level,
104 bool useQuickReject) {
Chris Craikff785832013-03-08 13:12:16 -0800105 applyState(replayStruct.mRenderer, saveCount);
Chris Craikc3566d02013-02-04 16:16:33 -0800106 }
107
Chris Craik7273daa2013-03-28 11:25:24 -0700108 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const = 0;
Chris Craik2af46352012-11-26 18:30:17 -0800109};
110
111class DrawOp : public DisplayListOp {
Chris Craik527a3aa2013-03-04 10:19:31 -0800112friend class MergingDrawBatch;
Chris Craik2af46352012-11-26 18:30:17 -0800113public:
Chris Craikd218a922014-01-02 17:13:34 -0800114 DrawOp(const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -0800115 : mPaint(paint), mQuickRejected(false) {}
116
Chet Haasedd671592013-04-19 14:54:34 -0700117 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
118 bool useQuickReject) {
119 if (mQuickRejected && CC_LIKELY(useQuickReject)) {
Chris Craikff785832013-03-08 13:12:16 -0800120 return;
Chris Craikc3566d02013-02-04 16:16:33 -0800121 }
122
Chris Craikff785832013-03-08 13:12:16 -0800123 deferStruct.mDeferredList.addDrawOp(deferStruct.mRenderer, this);
Chris Craikc3566d02013-02-04 16:16:33 -0800124 }
125
Chet Haasedd671592013-04-19 14:54:34 -0700126 virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level,
127 bool useQuickReject) {
128 if (mQuickRejected && CC_LIKELY(useQuickReject)) {
Chris Craikff785832013-03-08 13:12:16 -0800129 return;
130 }
131
Chris Craik527a3aa2013-03-04 10:19:31 -0800132 replayStruct.mDrawGlStatus |= applyDraw(replayStruct.mRenderer, replayStruct.mDirty);
Chris Craikff785832013-03-08 13:12:16 -0800133 }
134
Chris Craik527a3aa2013-03-04 10:19:31 -0800135 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) = 0;
Chris Craik2af46352012-11-26 18:30:17 -0800136
Chris Craik527a3aa2013-03-04 10:19:31 -0800137 /**
138 * Draw multiple instances of an operation, must be overidden for operations that merge
139 *
140 * Currently guarantees certain similarities between ops (see MergingDrawBatch::canMergeWith),
141 * and pure translation transformations. Other guarantees of similarity should be enforced by
142 * reducing which operations are tagged as mergeable.
143 */
144 virtual status_t multiDraw(OpenGLRenderer& renderer, Rect& dirty,
Chris Craikc1c5f082013-09-11 16:23:37 -0700145 const Vector<OpStatePair>& ops, const Rect& bounds) {
Chris Craik527a3aa2013-03-04 10:19:31 -0800146 status_t status = DrawGlInfo::kStatusDone;
147 for (unsigned int i = 0; i < ops.size(); i++) {
Chris Craikc1c5f082013-09-11 16:23:37 -0700148 renderer.restoreDisplayState(*(ops[i].state), true);
149 status |= ops[i].op->applyDraw(renderer, dirty);
Chris Craik527a3aa2013-03-04 10:19:31 -0800150 }
151 return status;
152 }
153
Chris Craik28ce94a2013-05-31 11:38:03 -0700154 /**
Chris Craik527a3aa2013-03-04 10:19:31 -0800155 * When this method is invoked the state field is initialized to have the
156 * final rendering state. We can thus use it to process data as it will be
157 * used at draw time.
158 *
159 * Additionally, this method allows subclasses to provide defer-time preferences for batching
160 * and merging.
161 *
Chris Craik28ce94a2013-05-31 11:38:03 -0700162 * if a subclass can set deferInfo.mergeable to true, it should implement multiDraw()
Chris Craik527a3aa2013-03-04 10:19:31 -0800163 */
Chris Craikc1c5f082013-09-11 16:23:37 -0700164 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
165 const DeferredDisplayState& state) {}
Romain Guy0f667532013-03-01 14:31:04 -0800166
Chris Craik5e49b302013-07-30 19:05:20 -0700167 /**
168 * Query the conservative, local bounds (unmapped) bounds of the op.
169 *
170 * returns true if bounds exist
171 */
Chris Craikc1c5f082013-09-11 16:23:37 -0700172 virtual bool getLocalBounds(const DrawModifiers& drawModifiers, Rect& localBounds) {
173 return false;
174 }
Chris Craik2af46352012-11-26 18:30:17 -0800175
176 // TODO: better refine localbounds usage
177 void setQuickRejected(bool quickRejected) { mQuickRejected = quickRejected; }
178 bool getQuickRejected() { return mQuickRejected; }
179
Chris Craikc1c5f082013-09-11 16:23:37 -0700180 inline int getPaintAlpha() const {
Chris Craik527a3aa2013-03-04 10:19:31 -0800181 return OpenGLRenderer::getAlphaDirect(mPaint);
Chris Craikc3566d02013-02-04 16:16:33 -0800182 }
183
Chris Craik527a3aa2013-03-04 10:19:31 -0800184 inline float strokeWidthOutset() {
Chris Craikf0a59072013-11-19 18:00:46 -0800185 // since anything AA stroke with less than 1.0 pixel width is drawn with an alpha-reduced
186 // 1.0 stroke, treat 1.0 as minimum.
187
188 // TODO: it would be nice if this could take scale into account, but scale isn't stable
189 // since higher levels of the view hierarchy can change scale out from underneath it.
190 return fmaxf(mPaint->getStrokeWidth(), 1) * 0.5f;
Chris Craike7c69c62013-04-03 09:55:48 -0700191 }
Chris Craikc3566d02013-02-04 16:16:33 -0800192
Chris Craik2af46352012-11-26 18:30:17 -0800193protected:
Chris Craikd218a922014-01-02 17:13:34 -0800194 const SkPaint* getPaint(OpenGLRenderer& renderer) {
Chris Craika08f95c2013-03-15 17:24:33 -0700195 return renderer.filterPaint(mPaint);
Chris Craik2af46352012-11-26 18:30:17 -0800196 }
197
Chris Craik28ce94a2013-05-31 11:38:03 -0700198 // Helper method for determining op opaqueness. Assumes op fills its bounds in local
199 // coordinates, and that paint's alpha is used
Chris Craikc1c5f082013-09-11 16:23:37 -0700200 inline bool isOpaqueOverBounds(const DeferredDisplayState& state) {
Chris Craik28ce94a2013-05-31 11:38:03 -0700201 // ensure that local bounds cover mapped bounds
202 if (!state.mMatrix.isSimple()) return false;
203
204 // check state/paint for transparency
205 if (state.mDrawModifiers.mShader ||
206 state.mAlpha != 1.0f ||
207 (mPaint && mPaint->getAlpha() != 0xFF)) return false;
208
209 SkXfermode::Mode mode = OpenGLRenderer::getXfermodeDirect(mPaint);
210 return (mode == SkXfermode::kSrcOver_Mode ||
211 mode == SkXfermode::kSrc_Mode);
212
213 }
214
Chris Craikd218a922014-01-02 17:13:34 -0800215 const SkPaint* mPaint; // should be accessed via getPaint() when applying
Chris Craik2af46352012-11-26 18:30:17 -0800216 bool mQuickRejected;
217};
218
219class DrawBoundedOp : public DrawOp {
220public:
Chris Craikd218a922014-01-02 17:13:34 -0800221 DrawBoundedOp(float left, float top, float right, float bottom, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -0800222 : DrawOp(paint), mLocalBounds(left, top, right, bottom) {}
223
Chris Craikd218a922014-01-02 17:13:34 -0800224 DrawBoundedOp(const Rect& localBounds, const SkPaint* paint)
Chris Craik41541822013-05-03 16:35:54 -0700225 : DrawOp(paint), mLocalBounds(localBounds) {}
226
Chris Craik5d116762013-02-19 17:49:31 -0800227 // Calculates bounds as smallest rect encompassing all points
228 // NOTE: requires at least 1 vertex, and doesn't account for stroke size (should be handled in
229 // subclass' constructor)
Chris Craikd218a922014-01-02 17:13:34 -0800230 DrawBoundedOp(const float* points, int count, const SkPaint* paint)
Chris Craik5d116762013-02-19 17:49:31 -0800231 : DrawOp(paint), mLocalBounds(points[0], points[1], points[0], points[1]) {
232 for (int i = 2; i < count; i += 2) {
233 mLocalBounds.left = fminf(mLocalBounds.left, points[i]);
234 mLocalBounds.right = fmaxf(mLocalBounds.right, points[i]);
235 mLocalBounds.top = fminf(mLocalBounds.top, points[i + 1]);
236 mLocalBounds.bottom = fmaxf(mLocalBounds.bottom, points[i + 1]);
237 }
238 }
239
240 // default empty constructor for bounds, to be overridden in child constructor body
Chris Craikd218a922014-01-02 17:13:34 -0800241 DrawBoundedOp(const SkPaint* paint): DrawOp(paint) { }
Chris Craik2af46352012-11-26 18:30:17 -0800242
Chris Craikc1c5f082013-09-11 16:23:37 -0700243 bool getLocalBounds(const DrawModifiers& drawModifiers, Rect& localBounds) {
Chris Craik2af46352012-11-26 18:30:17 -0800244 localBounds.set(mLocalBounds);
Chris Craikc1c5f082013-09-11 16:23:37 -0700245 if (drawModifiers.mHasShadow) {
246 // TODO: inspect paint's looper directly
Romain Guy9b5a1a22013-08-09 14:06:29 -0700247 Rect shadow(mLocalBounds);
Chris Craikc1c5f082013-09-11 16:23:37 -0700248 shadow.translate(drawModifiers.mShadowDx, drawModifiers.mShadowDy);
249 shadow.outset(drawModifiers.mShadowRadius);
Romain Guy9b5a1a22013-08-09 14:06:29 -0700250 localBounds.unionWith(shadow);
251 }
Chris Craik2af46352012-11-26 18:30:17 -0800252 return true;
253 }
254
255protected:
256 Rect mLocalBounds; // displayed area in LOCAL coord. doesn't incorporate stroke, so check paint
257};
258
259///////////////////////////////////////////////////////////////////////////////
260// STATE OPERATIONS - these may affect the state of the canvas/renderer, but do
261// not directly draw or alter output
262///////////////////////////////////////////////////////////////////////////////
263
264class SaveOp : public StateOp {
265public:
266 SaveOp(int flags)
267 : mFlags(flags) {}
268
Chet Haasedd671592013-04-19 14:54:34 -0700269 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
270 bool useQuickReject) {
Chris Craikff785832013-03-08 13:12:16 -0800271 int newSaveCount = deferStruct.mRenderer.save(mFlags);
272 deferStruct.mDeferredList.addSave(deferStruct.mRenderer, this, newSaveCount);
273 }
274
Chris Craik7273daa2013-03-28 11:25:24 -0700275 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800276 renderer.save(mFlags);
277 }
278
Chris Craikc5493fb2013-06-19 16:58:58 -0700279 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800280 OP_LOG("Save flags %x", mFlags);
281 }
282
283 virtual const char* name() { return "Save"; }
284
Chris Craikff785832013-03-08 13:12:16 -0800285 int getFlags() const { return mFlags; }
Chris Craik2af46352012-11-26 18:30:17 -0800286private:
Chris Craikff785832013-03-08 13:12:16 -0800287 SaveOp() {}
288 DisplayListOp* reinit(int flags) {
289 mFlags = flags;
290 return this;
291 }
292
Chris Craik2af46352012-11-26 18:30:17 -0800293 int mFlags;
294};
295
296class RestoreToCountOp : public StateOp {
297public:
298 RestoreToCountOp(int count)
299 : mCount(count) {}
300
Chet Haasedd671592013-04-19 14:54:34 -0700301 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
302 bool useQuickReject) {
Chris Craik7273daa2013-03-28 11:25:24 -0700303 deferStruct.mDeferredList.addRestoreToCount(deferStruct.mRenderer,
304 this, saveCount + mCount);
Chris Craikff785832013-03-08 13:12:16 -0800305 deferStruct.mRenderer.restoreToCount(saveCount + mCount);
Chris Craik2af46352012-11-26 18:30:17 -0800306 }
307
Chris Craik7273daa2013-03-28 11:25:24 -0700308 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craikff785832013-03-08 13:12:16 -0800309 renderer.restoreToCount(saveCount + mCount);
310 }
311
Chris Craikc5493fb2013-06-19 16:58:58 -0700312 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800313 OP_LOG("Restore to count %d", mCount);
314 }
315
316 virtual const char* name() { return "RestoreToCount"; }
317
318private:
Chris Craikff785832013-03-08 13:12:16 -0800319 RestoreToCountOp() {}
320 DisplayListOp* reinit(int count) {
321 mCount = count;
322 return this;
323 }
324
Chris Craik2af46352012-11-26 18:30:17 -0800325 int mCount;
326};
327
328class SaveLayerOp : public StateOp {
329public:
Derek Sollenbergerd44fbe52014-02-05 16:47:00 -0500330 SaveLayerOp(float left, float top, float right, float bottom, int alpha, int flags)
331 : mArea(left, top, right, bottom), mPaint(&mCachedPaint), mFlags(flags) {
332 mCachedPaint.setAlpha(alpha);
333 }
334
335 SaveLayerOp(float left, float top, float right, float bottom, const SkPaint* paint, int flags)
336 : mArea(left, top, right, bottom), mPaint(paint), mFlags(flags) {}
Chris Craikff785832013-03-08 13:12:16 -0800337
Chet Haasedd671592013-04-19 14:54:34 -0700338 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
339 bool useQuickReject) {
Chris Craikff785832013-03-08 13:12:16 -0800340 // NOTE: don't bother with actual saveLayer, instead issuing it at flush time
Chris Craikd90144d2013-03-19 15:03:48 -0700341 int newSaveCount = deferStruct.mRenderer.getSaveCount();
Chris Craikff785832013-03-08 13:12:16 -0800342 deferStruct.mDeferredList.addSaveLayer(deferStruct.mRenderer, this, newSaveCount);
Chris Craikd90144d2013-03-19 15:03:48 -0700343
344 // NOTE: don't issue full saveLayer, since that has side effects/is costly. instead just
345 // setup the snapshot for deferral, and re-issue the op at flush time
346 deferStruct.mRenderer.saveLayerDeferred(mArea.left, mArea.top, mArea.right, mArea.bottom,
Derek Sollenbergerd44fbe52014-02-05 16:47:00 -0500347 mPaint, mFlags);
Chris Craikff785832013-03-08 13:12:16 -0800348 }
Chris Craik2af46352012-11-26 18:30:17 -0800349
Chris Craik7273daa2013-03-28 11:25:24 -0700350 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Derek Sollenbergerd44fbe52014-02-05 16:47:00 -0500351 renderer.saveLayer(mArea.left, mArea.top, mArea.right, mArea.bottom, mPaint, mFlags);
Chris Craik2af46352012-11-26 18:30:17 -0800352 }
353
Chris Craikc5493fb2013-06-19 16:58:58 -0700354 virtual void output(int level, uint32_t logFlags) const {
Chris Craikff785832013-03-08 13:12:16 -0800355 OP_LOG("SaveLayer%s of area " RECT_STRING,
356 (isSaveLayerAlpha() ? "Alpha" : ""),RECT_ARGS(mArea));
Chris Craik2af46352012-11-26 18:30:17 -0800357 }
358
Chris Craikff785832013-03-08 13:12:16 -0800359 virtual const char* name() { return isSaveLayerAlpha() ? "SaveLayerAlpha" : "SaveLayer"; }
360
361 int getFlags() { return mFlags; }
Chris Craik2af46352012-11-26 18:30:17 -0800362
363private:
Derek Sollenbergerd44fbe52014-02-05 16:47:00 -0500364 bool isSaveLayerAlpha() const {
365 SkXfermode::Mode mode = OpenGLRenderer::getXfermodeDirect(mPaint);
366 int alpha = OpenGLRenderer::getAlphaDirect(mPaint);
367 return alpha < 255 && mode == SkXfermode::kSrcOver_Mode;
Chris Craik2af46352012-11-26 18:30:17 -0800368 }
369
Chris Craik2af46352012-11-26 18:30:17 -0800370 Rect mArea;
Derek Sollenbergerd44fbe52014-02-05 16:47:00 -0500371 const SkPaint* mPaint;
372 SkPaint mCachedPaint;
Chris Craik2af46352012-11-26 18:30:17 -0800373 int mFlags;
374};
375
376class TranslateOp : public StateOp {
377public:
378 TranslateOp(float dx, float dy)
379 : mDx(dx), mDy(dy) {}
380
Chris Craik7273daa2013-03-28 11:25:24 -0700381 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800382 renderer.translate(mDx, mDy);
383 }
384
Chris Craikc5493fb2013-06-19 16:58:58 -0700385 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800386 OP_LOG("Translate by %f %f", mDx, mDy);
387 }
388
389 virtual const char* name() { return "Translate"; }
390
391private:
392 float mDx;
393 float mDy;
394};
395
396class RotateOp : public StateOp {
397public:
398 RotateOp(float degrees)
399 : mDegrees(degrees) {}
400
Chris Craik7273daa2013-03-28 11:25:24 -0700401 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800402 renderer.rotate(mDegrees);
403 }
404
Chris Craikc5493fb2013-06-19 16:58:58 -0700405 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800406 OP_LOG("Rotate by %f degrees", mDegrees);
407 }
408
409 virtual const char* name() { return "Rotate"; }
410
411private:
412 float mDegrees;
413};
414
415class ScaleOp : public StateOp {
416public:
417 ScaleOp(float sx, float sy)
418 : mSx(sx), mSy(sy) {}
419
Chris Craik7273daa2013-03-28 11:25:24 -0700420 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800421 renderer.scale(mSx, mSy);
422 }
423
Chris Craikc5493fb2013-06-19 16:58:58 -0700424 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800425 OP_LOG("Scale by %f %f", mSx, mSy);
426 }
427
428 virtual const char* name() { return "Scale"; }
429
430private:
431 float mSx;
432 float mSy;
433};
434
435class SkewOp : public StateOp {
436public:
437 SkewOp(float sx, float sy)
438 : mSx(sx), mSy(sy) {}
439
Chris Craik7273daa2013-03-28 11:25:24 -0700440 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800441 renderer.skew(mSx, mSy);
442 }
443
Chris Craikc5493fb2013-06-19 16:58:58 -0700444 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800445 OP_LOG("Skew by %f %f", mSx, mSy);
446 }
447
448 virtual const char* name() { return "Skew"; }
449
450private:
451 float mSx;
452 float mSy;
453};
454
455class SetMatrixOp : public StateOp {
456public:
Chris Craikd218a922014-01-02 17:13:34 -0800457 SetMatrixOp(const SkMatrix* matrix)
Chris Craik2af46352012-11-26 18:30:17 -0800458 : mMatrix(matrix) {}
459
Chris Craik7273daa2013-03-28 11:25:24 -0700460 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800461 renderer.setMatrix(mMatrix);
462 }
463
Chris Craikc5493fb2013-06-19 16:58:58 -0700464 virtual void output(int level, uint32_t logFlags) const {
Romain Guy4e7b7722013-07-16 13:47:01 -0700465 if (mMatrix) {
Chris Craik629f6772014-02-05 13:00:24 -0800466 OP_LOG("SetMatrix " SK_MATRIX_STRING, SK_MATRIX_ARGS(mMatrix));
Romain Guy4e7b7722013-07-16 13:47:01 -0700467 } else {
468 OP_LOGS("SetMatrix (reset)");
469 }
Chris Craik2af46352012-11-26 18:30:17 -0800470 }
471
472 virtual const char* name() { return "SetMatrix"; }
473
474private:
Chris Craikd218a922014-01-02 17:13:34 -0800475 const SkMatrix* mMatrix;
Chris Craik2af46352012-11-26 18:30:17 -0800476};
477
478class ConcatMatrixOp : public StateOp {
479public:
Chris Craikd218a922014-01-02 17:13:34 -0800480 ConcatMatrixOp(const SkMatrix* matrix)
Chris Craik2af46352012-11-26 18:30:17 -0800481 : mMatrix(matrix) {}
482
Chris Craik7273daa2013-03-28 11:25:24 -0700483 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800484 renderer.concatMatrix(mMatrix);
485 }
486
Chris Craikc5493fb2013-06-19 16:58:58 -0700487 virtual void output(int level, uint32_t logFlags) const {
Chris Craik629f6772014-02-05 13:00:24 -0800488 OP_LOG("ConcatMatrix " SK_MATRIX_STRING, SK_MATRIX_ARGS(mMatrix));
Chris Craik2af46352012-11-26 18:30:17 -0800489 }
490
491 virtual const char* name() { return "ConcatMatrix"; }
492
493private:
Chris Craikd218a922014-01-02 17:13:34 -0800494 const SkMatrix* mMatrix;
Chris Craik2af46352012-11-26 18:30:17 -0800495};
496
Chris Craikff785832013-03-08 13:12:16 -0800497class ClipOp : public StateOp {
498public:
499 ClipOp(SkRegion::Op op) : mOp(op) {}
500
Chet Haasedd671592013-04-19 14:54:34 -0700501 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
502 bool useQuickReject) {
Chris Craikff785832013-03-08 13:12:16 -0800503 // NOTE: must defer op BEFORE applying state, since it may read clip
504 deferStruct.mDeferredList.addClip(deferStruct.mRenderer, this);
505
506 // TODO: Can we avoid applying complex clips at defer time?
507 applyState(deferStruct.mRenderer, saveCount);
508 }
509
510 bool canCauseComplexClip() {
511 return ((mOp != SkRegion::kIntersect_Op) && (mOp != SkRegion::kReplace_Op)) || !isRect();
512 }
513
514protected:
515 ClipOp() {}
516 virtual bool isRect() { return false; }
517
518 SkRegion::Op mOp;
519};
520
521class ClipRectOp : public ClipOp {
Chris Craik2af46352012-11-26 18:30:17 -0800522public:
523 ClipRectOp(float left, float top, float right, float bottom, SkRegion::Op op)
Chris Craikff785832013-03-08 13:12:16 -0800524 : ClipOp(op), mArea(left, top, right, bottom) {}
Chris Craik2af46352012-11-26 18:30:17 -0800525
Chris Craik7273daa2013-03-28 11:25:24 -0700526 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800527 renderer.clipRect(mArea.left, mArea.top, mArea.right, mArea.bottom, mOp);
528 }
529
Chris Craikc5493fb2013-06-19 16:58:58 -0700530 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800531 OP_LOG("ClipRect " RECT_STRING, RECT_ARGS(mArea));
532 }
533
534 virtual const char* name() { return "ClipRect"; }
535
Chris Craikff785832013-03-08 13:12:16 -0800536protected:
537 virtual bool isRect() { return true; }
Chris Craikb98a0162013-02-21 11:30:22 -0800538
Chris Craik2af46352012-11-26 18:30:17 -0800539private:
Chris Craikff785832013-03-08 13:12:16 -0800540 ClipRectOp() {}
541 DisplayListOp* reinit(float left, float top, float right, float bottom, SkRegion::Op op) {
542 mOp = op;
543 mArea.set(left, top, right, bottom);
544 return this;
Chris Craikb98a0162013-02-21 11:30:22 -0800545 }
Chris Craikff785832013-03-08 13:12:16 -0800546
Chris Craik2af46352012-11-26 18:30:17 -0800547 Rect mArea;
Chris Craik2af46352012-11-26 18:30:17 -0800548};
549
Chris Craikff785832013-03-08 13:12:16 -0800550class ClipPathOp : public ClipOp {
Chris Craik2af46352012-11-26 18:30:17 -0800551public:
Chris Craikd218a922014-01-02 17:13:34 -0800552 ClipPathOp(const SkPath* path, SkRegion::Op op)
Chris Craikff785832013-03-08 13:12:16 -0800553 : ClipOp(op), mPath(path) {}
Chris Craik2af46352012-11-26 18:30:17 -0800554
Chris Craik7273daa2013-03-28 11:25:24 -0700555 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800556 renderer.clipPath(mPath, mOp);
557 }
558
Chris Craikc5493fb2013-06-19 16:58:58 -0700559 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800560 SkRect bounds = mPath->getBounds();
561 OP_LOG("ClipPath bounds " RECT_STRING,
562 bounds.left(), bounds.top(), bounds.right(), bounds.bottom());
563 }
564
565 virtual const char* name() { return "ClipPath"; }
566
567private:
Chris Craikd218a922014-01-02 17:13:34 -0800568 const SkPath* mPath;
Chris Craik2af46352012-11-26 18:30:17 -0800569};
570
Chris Craikff785832013-03-08 13:12:16 -0800571class ClipRegionOp : public ClipOp {
Chris Craik2af46352012-11-26 18:30:17 -0800572public:
Chris Craikd218a922014-01-02 17:13:34 -0800573 ClipRegionOp(const SkRegion* region, SkRegion::Op op)
Chris Craikff785832013-03-08 13:12:16 -0800574 : ClipOp(op), mRegion(region) {}
Chris Craik2af46352012-11-26 18:30:17 -0800575
Chris Craik7273daa2013-03-28 11:25:24 -0700576 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800577 renderer.clipRegion(mRegion, mOp);
578 }
579
Chris Craikc5493fb2013-06-19 16:58:58 -0700580 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800581 SkIRect bounds = mRegion->getBounds();
582 OP_LOG("ClipRegion bounds %d %d %d %d",
583 bounds.left(), bounds.top(), bounds.right(), bounds.bottom());
584 }
585
586 virtual const char* name() { return "ClipRegion"; }
587
588private:
Chris Craikd218a922014-01-02 17:13:34 -0800589 const SkRegion* mRegion;
Chris Craik2af46352012-11-26 18:30:17 -0800590};
591
592class ResetShaderOp : public StateOp {
593public:
Chris Craik7273daa2013-03-28 11:25:24 -0700594 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800595 renderer.resetShader();
596 }
597
Chris Craikc5493fb2013-06-19 16:58:58 -0700598 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800599 OP_LOGS("ResetShader");
600 }
601
602 virtual const char* name() { return "ResetShader"; }
603};
604
605class SetupShaderOp : public StateOp {
606public:
607 SetupShaderOp(SkiaShader* shader)
608 : mShader(shader) {}
Chris Craik7273daa2013-03-28 11:25:24 -0700609 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800610 renderer.setupShader(mShader);
611 }
612
Chris Craikc5493fb2013-06-19 16:58:58 -0700613 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800614 OP_LOG("SetupShader, shader %p", mShader);
615 }
616
617 virtual const char* name() { return "SetupShader"; }
618
619private:
620 SkiaShader* mShader;
621};
622
623class ResetColorFilterOp : public StateOp {
624public:
Chris Craik7273daa2013-03-28 11:25:24 -0700625 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800626 renderer.resetColorFilter();
627 }
628
Chris Craikc5493fb2013-06-19 16:58:58 -0700629 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800630 OP_LOGS("ResetColorFilter");
631 }
632
633 virtual const char* name() { return "ResetColorFilter"; }
634};
635
636class SetupColorFilterOp : public StateOp {
637public:
638 SetupColorFilterOp(SkiaColorFilter* colorFilter)
639 : mColorFilter(colorFilter) {}
640
Chris Craik7273daa2013-03-28 11:25:24 -0700641 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800642 renderer.setupColorFilter(mColorFilter);
643 }
644
Chris Craikc5493fb2013-06-19 16:58:58 -0700645 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800646 OP_LOG("SetupColorFilter, filter %p", mColorFilter);
647 }
648
649 virtual const char* name() { return "SetupColorFilter"; }
650
651private:
652 SkiaColorFilter* mColorFilter;
653};
654
655class ResetShadowOp : public StateOp {
656public:
Chris Craik7273daa2013-03-28 11:25:24 -0700657 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800658 renderer.resetShadow();
659 }
660
Chris Craikc5493fb2013-06-19 16:58:58 -0700661 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800662 OP_LOGS("ResetShadow");
663 }
664
665 virtual const char* name() { return "ResetShadow"; }
666};
667
668class SetupShadowOp : public StateOp {
669public:
670 SetupShadowOp(float radius, float dx, float dy, int color)
671 : mRadius(radius), mDx(dx), mDy(dy), mColor(color) {}
672
Chris Craik7273daa2013-03-28 11:25:24 -0700673 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800674 renderer.setupShadow(mRadius, mDx, mDy, mColor);
675 }
676
Chris Craikc5493fb2013-06-19 16:58:58 -0700677 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800678 OP_LOG("SetupShadow, radius %f, %f, %f, color %#x", mRadius, mDx, mDy, mColor);
679 }
680
681 virtual const char* name() { return "SetupShadow"; }
682
683private:
684 float mRadius;
685 float mDx;
686 float mDy;
687 int mColor;
688};
689
690class ResetPaintFilterOp : public StateOp {
691public:
Chris Craik7273daa2013-03-28 11:25:24 -0700692 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800693 renderer.resetPaintFilter();
694 }
695
Chris Craikc5493fb2013-06-19 16:58:58 -0700696 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800697 OP_LOGS("ResetPaintFilter");
698 }
699
700 virtual const char* name() { return "ResetPaintFilter"; }
701};
702
703class SetupPaintFilterOp : public StateOp {
704public:
705 SetupPaintFilterOp(int clearBits, int setBits)
706 : mClearBits(clearBits), mSetBits(setBits) {}
707
Chris Craik7273daa2013-03-28 11:25:24 -0700708 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800709 renderer.setupPaintFilter(mClearBits, mSetBits);
710 }
711
Chris Craikc5493fb2013-06-19 16:58:58 -0700712 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800713 OP_LOG("SetupPaintFilter, clear %#x, set %#x", mClearBits, mSetBits);
714 }
715
716 virtual const char* name() { return "SetupPaintFilter"; }
717
718private:
719 int mClearBits;
720 int mSetBits;
721};
722
Chris Craik2af46352012-11-26 18:30:17 -0800723///////////////////////////////////////////////////////////////////////////////
724// DRAW OPERATIONS - these are operations that can draw to the canvas's device
725///////////////////////////////////////////////////////////////////////////////
726
727class DrawBitmapOp : public DrawBoundedOp {
728public:
Chris Craikd218a922014-01-02 17:13:34 -0800729 DrawBitmapOp(const SkBitmap* bitmap, float left, float top, const SkPaint* paint)
Romain Guy3b748a42013-04-17 18:54:38 -0700730 : DrawBoundedOp(left, top, left + bitmap->width(), top + bitmap->height(), paint),
Romain Guy55b6f952013-06-27 15:27:09 -0700731 mBitmap(bitmap), mAtlas(Caches::getInstance().assetAtlas) {
732 mEntry = mAtlas.getEntry(bitmap);
733 if (mEntry) {
734 mEntryGenerationId = mAtlas.getGenerationId();
735 mUvMapper = mEntry->uvMapper;
736 }
Romain Guy3b748a42013-04-17 18:54:38 -0700737 }
Chris Craik2af46352012-11-26 18:30:17 -0800738
Chris Craik527a3aa2013-03-04 10:19:31 -0800739 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craika08f95c2013-03-15 17:24:33 -0700740 return renderer.drawBitmap(mBitmap, mLocalBounds.left, mLocalBounds.top,
741 getPaint(renderer));
Chris Craik2af46352012-11-26 18:30:17 -0800742 }
743
Romain Guy55b6f952013-06-27 15:27:09 -0700744 AssetAtlas::Entry* getAtlasEntry() {
745 // The atlas entry is stale, let's get a new one
746 if (mEntry && mEntryGenerationId != mAtlas.getGenerationId()) {
747 mEntryGenerationId = mAtlas.getGenerationId();
748 mEntry = mAtlas.getEntry(mBitmap);
749 mUvMapper = mEntry->uvMapper;
750 }
751 return mEntry;
752 }
753
Chris Craik527a3aa2013-03-04 10:19:31 -0800754#define SET_TEXTURE(ptr, posRect, offsetRect, texCoordsRect, xDim, yDim) \
755 TextureVertex::set(ptr++, posRect.xDim - offsetRect.left, posRect.yDim - offsetRect.top, \
756 texCoordsRect.xDim, texCoordsRect.yDim)
757
Romain Guy03c00b52013-06-20 18:30:28 -0700758 /**
759 * This multi-draw operation builds a mesh on the stack by generating a quad
760 * for each bitmap in the batch. This method is also responsible for dirtying
761 * the current layer, if any.
762 */
Chris Craik527a3aa2013-03-04 10:19:31 -0800763 virtual status_t multiDraw(OpenGLRenderer& renderer, Rect& dirty,
Chris Craikc1c5f082013-09-11 16:23:37 -0700764 const Vector<OpStatePair>& ops, const Rect& bounds) {
765 const DeferredDisplayState& firstState = *(ops[0].state);
766 renderer.restoreDisplayState(firstState, true); // restore all but the clip
767
Chris Craik527a3aa2013-03-04 10:19:31 -0800768 TextureVertex vertices[6 * ops.size()];
769 TextureVertex* vertex = &vertices[0];
770
Romain Guy03c00b52013-06-20 18:30:28 -0700771 const bool hasLayer = renderer.hasLayer();
Chris Craik996fe652013-09-20 17:13:18 -0700772 bool pureTranslate = true;
Romain Guy2db5e992013-05-21 15:29:59 -0700773
Romain Guy3b748a42013-04-17 18:54:38 -0700774 // TODO: manually handle rect clip for bitmaps by adjusting texCoords per op,
775 // and allowing them to be merged in getBatchId()
Chris Craik527a3aa2013-03-04 10:19:31 -0800776 for (unsigned int i = 0; i < ops.size(); i++) {
Chris Craikc1c5f082013-09-11 16:23:37 -0700777 const DeferredDisplayState& state = *(ops[i].state);
778 const Rect& opBounds = state.mBounds;
Romain Guy2db5e992013-05-21 15:29:59 -0700779 // When we reach multiDraw(), the matrix can be either
780 // pureTranslate or simple (translate and/or scale).
781 // If the matrix is not pureTranslate, then we have a scale
Chris Craik996fe652013-09-20 17:13:18 -0700782 pureTranslate &= state.mMatrix.isPureTranslate();
Romain Guy3b748a42013-04-17 18:54:38 -0700783
784 Rect texCoords(0, 0, 1, 1);
Chris Craikc1c5f082013-09-11 16:23:37 -0700785 ((DrawBitmapOp*) ops[i].op)->mUvMapper.map(texCoords);
Romain Guy3b748a42013-04-17 18:54:38 -0700786
Chris Craik527a3aa2013-03-04 10:19:31 -0800787 SET_TEXTURE(vertex, opBounds, bounds, texCoords, left, top);
788 SET_TEXTURE(vertex, opBounds, bounds, texCoords, right, top);
789 SET_TEXTURE(vertex, opBounds, bounds, texCoords, left, bottom);
790
791 SET_TEXTURE(vertex, opBounds, bounds, texCoords, left, bottom);
792 SET_TEXTURE(vertex, opBounds, bounds, texCoords, right, top);
793 SET_TEXTURE(vertex, opBounds, bounds, texCoords, right, bottom);
Romain Guy03c00b52013-06-20 18:30:28 -0700794
795 if (hasLayer) {
Chris Craikc1c5f082013-09-11 16:23:37 -0700796 renderer.dirtyLayer(opBounds.left, opBounds.top, opBounds.right, opBounds.bottom);
Romain Guy03c00b52013-06-20 18:30:28 -0700797 }
Chris Craik527a3aa2013-03-04 10:19:31 -0800798 }
799
Romain Guy55b6f952013-06-27 15:27:09 -0700800 return renderer.drawBitmaps(mBitmap, mEntry, ops.size(), &vertices[0],
Chris Craik996fe652013-09-20 17:13:18 -0700801 pureTranslate, bounds, mPaint);
Chris Craik527a3aa2013-03-04 10:19:31 -0800802 }
803
Chris Craikc5493fb2013-06-19 16:58:58 -0700804 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800805 OP_LOG("Draw bitmap %p at %f %f", mBitmap, mLocalBounds.left, mLocalBounds.top);
806 }
807
808 virtual const char* name() { return "DrawBitmap"; }
Chris Craik527a3aa2013-03-04 10:19:31 -0800809
Chris Craikc1c5f082013-09-11 16:23:37 -0700810 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
811 const DeferredDisplayState& state) {
Chris Craik28ce94a2013-05-31 11:38:03 -0700812 deferInfo.batchId = DeferredDisplayList::kOpBatch_Bitmap;
Chris Craikd965bc52013-09-16 14:47:13 -0700813 deferInfo.mergeId = getAtlasEntry() ?
814 (mergeid_t) mEntry->getMergeId() : (mergeid_t) mBitmap;
Romain Guy2db5e992013-05-21 15:29:59 -0700815
Chris Craikd965bc52013-09-16 14:47:13 -0700816 // Don't merge non-simply transformed or neg scale ops, SET_TEXTURE doesn't handle rotation
Chris Craik28ce94a2013-05-31 11:38:03 -0700817 // Don't merge A8 bitmaps - the paint's color isn't compared by mergeId, or in
818 // MergingDrawBatch::canMergeWith()
819 // TODO: support clipped bitmaps by handling them in SET_TEXTURE
Chris Craikd965bc52013-09-16 14:47:13 -0700820 deferInfo.mergeable = state.mMatrix.isSimple() && state.mMatrix.positiveScale() &&
821 !state.mClipSideFlags &&
Chris Craik28ce94a2013-05-31 11:38:03 -0700822 OpenGLRenderer::getXfermodeDirect(mPaint) == SkXfermode::kSrcOver_Mode &&
823 (mBitmap->getConfig() != SkBitmap::kA8_Config);
Chris Craikc3566d02013-02-04 16:16:33 -0800824 }
Chris Craik2af46352012-11-26 18:30:17 -0800825
Chris Craik527a3aa2013-03-04 10:19:31 -0800826 const SkBitmap* bitmap() { return mBitmap; }
Chris Craik2af46352012-11-26 18:30:17 -0800827protected:
Chris Craikd218a922014-01-02 17:13:34 -0800828 const SkBitmap* mBitmap;
Romain Guy55b6f952013-06-27 15:27:09 -0700829 const AssetAtlas& mAtlas;
830 uint32_t mEntryGenerationId;
831 AssetAtlas::Entry* mEntry;
Romain Guy3b748a42013-04-17 18:54:38 -0700832 UvMapper mUvMapper;
Chris Craik2af46352012-11-26 18:30:17 -0800833};
834
835class DrawBitmapMatrixOp : public DrawBoundedOp {
836public:
Chris Craikd218a922014-01-02 17:13:34 -0800837 DrawBitmapMatrixOp(const SkBitmap* bitmap, const SkMatrix* matrix, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -0800838 : DrawBoundedOp(paint), mBitmap(bitmap), mMatrix(matrix) {
839 mLocalBounds.set(0, 0, bitmap->width(), bitmap->height());
840 const mat4 transform(*matrix);
841 transform.mapRect(mLocalBounds);
842 }
843
Chris Craik527a3aa2013-03-04 10:19:31 -0800844 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -0800845 return renderer.drawBitmap(mBitmap, mMatrix, getPaint(renderer));
846 }
847
Chris Craikc5493fb2013-06-19 16:58:58 -0700848 virtual void output(int level, uint32_t logFlags) const {
Chris Craik629f6772014-02-05 13:00:24 -0800849 OP_LOG("Draw bitmap %p matrix " SK_MATRIX_STRING, mBitmap, SK_MATRIX_ARGS(mMatrix));
Chris Craik2af46352012-11-26 18:30:17 -0800850 }
851
Chris Craik527a3aa2013-03-04 10:19:31 -0800852 virtual const char* name() { return "DrawBitmapMatrix"; }
853
Chris Craikc1c5f082013-09-11 16:23:37 -0700854 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
855 const DeferredDisplayState& state) {
Chris Craik28ce94a2013-05-31 11:38:03 -0700856 deferInfo.batchId = DeferredDisplayList::kOpBatch_Bitmap;
Chris Craikc3566d02013-02-04 16:16:33 -0800857 }
Chris Craik2af46352012-11-26 18:30:17 -0800858
859private:
Chris Craikd218a922014-01-02 17:13:34 -0800860 const SkBitmap* mBitmap;
861 const SkMatrix* mMatrix;
Chris Craik2af46352012-11-26 18:30:17 -0800862};
863
864class DrawBitmapRectOp : public DrawBoundedOp {
865public:
Chris Craikd218a922014-01-02 17:13:34 -0800866 DrawBitmapRectOp(const SkBitmap* bitmap,
867 float srcLeft, float srcTop, float srcRight, float srcBottom,
868 float dstLeft, float dstTop, float dstRight, float dstBottom, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -0800869 : DrawBoundedOp(dstLeft, dstTop, dstRight, dstBottom, paint),
870 mBitmap(bitmap), mSrc(srcLeft, srcTop, srcRight, srcBottom) {}
871
Chris Craik527a3aa2013-03-04 10:19:31 -0800872 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -0800873 return renderer.drawBitmap(mBitmap, mSrc.left, mSrc.top, mSrc.right, mSrc.bottom,
874 mLocalBounds.left, mLocalBounds.top, mLocalBounds.right, mLocalBounds.bottom,
875 getPaint(renderer));
876 }
877
Chris Craikc5493fb2013-06-19 16:58:58 -0700878 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800879 OP_LOG("Draw bitmap %p src="RECT_STRING", dst="RECT_STRING,
880 mBitmap, RECT_ARGS(mSrc), RECT_ARGS(mLocalBounds));
881 }
882
883 virtual const char* name() { return "DrawBitmapRect"; }
Chris Craik527a3aa2013-03-04 10:19:31 -0800884
Chris Craikc1c5f082013-09-11 16:23:37 -0700885 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
886 const DeferredDisplayState& state) {
Chris Craik28ce94a2013-05-31 11:38:03 -0700887 deferInfo.batchId = DeferredDisplayList::kOpBatch_Bitmap;
Chris Craikc3566d02013-02-04 16:16:33 -0800888 }
Chris Craik2af46352012-11-26 18:30:17 -0800889
890private:
Chris Craikd218a922014-01-02 17:13:34 -0800891 const SkBitmap* mBitmap;
Chris Craik2af46352012-11-26 18:30:17 -0800892 Rect mSrc;
893};
894
895class DrawBitmapDataOp : public DrawBitmapOp {
896public:
Chris Craikd218a922014-01-02 17:13:34 -0800897 DrawBitmapDataOp(const SkBitmap* bitmap, float left, float top, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -0800898 : DrawBitmapOp(bitmap, left, top, paint) {}
899
Chris Craik527a3aa2013-03-04 10:19:31 -0800900 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -0800901 return renderer.drawBitmapData(mBitmap, mLocalBounds.left,
902 mLocalBounds.top, getPaint(renderer));
903 }
904
Chris Craikc5493fb2013-06-19 16:58:58 -0700905 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800906 OP_LOG("Draw bitmap %p", mBitmap);
907 }
908
909 virtual const char* name() { return "DrawBitmapData"; }
Chris Craik527a3aa2013-03-04 10:19:31 -0800910
Chris Craikc1c5f082013-09-11 16:23:37 -0700911 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
912 const DeferredDisplayState& state) {
Chris Craik28ce94a2013-05-31 11:38:03 -0700913 deferInfo.batchId = DeferredDisplayList::kOpBatch_Bitmap;
Chris Craikc3566d02013-02-04 16:16:33 -0800914 }
Chris Craik2af46352012-11-26 18:30:17 -0800915};
916
Chris Craik5d116762013-02-19 17:49:31 -0800917class DrawBitmapMeshOp : public DrawBoundedOp {
Chris Craik2af46352012-11-26 18:30:17 -0800918public:
Chris Craikd218a922014-01-02 17:13:34 -0800919 DrawBitmapMeshOp(const SkBitmap* bitmap, int meshWidth, int meshHeight,
920 const float* vertices, const int* colors, const SkPaint* paint)
Chris Craik5d116762013-02-19 17:49:31 -0800921 : DrawBoundedOp(vertices, 2 * (meshWidth + 1) * (meshHeight + 1), paint),
922 mBitmap(bitmap), mMeshWidth(meshWidth), mMeshHeight(meshHeight),
Chris Craik2af46352012-11-26 18:30:17 -0800923 mVertices(vertices), mColors(colors) {}
924
Chris Craik527a3aa2013-03-04 10:19:31 -0800925 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -0800926 return renderer.drawBitmapMesh(mBitmap, mMeshWidth, mMeshHeight,
927 mVertices, mColors, getPaint(renderer));
928 }
929
Chris Craikc5493fb2013-06-19 16:58:58 -0700930 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800931 OP_LOG("Draw bitmap %p mesh %d x %d", mBitmap, mMeshWidth, mMeshHeight);
932 }
933
934 virtual const char* name() { return "DrawBitmapMesh"; }
Chris Craik527a3aa2013-03-04 10:19:31 -0800935
Chris Craikc1c5f082013-09-11 16:23:37 -0700936 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
937 const DeferredDisplayState& state) {
Chris Craik28ce94a2013-05-31 11:38:03 -0700938 deferInfo.batchId = DeferredDisplayList::kOpBatch_Bitmap;
Chris Craikc3566d02013-02-04 16:16:33 -0800939 }
Chris Craik2af46352012-11-26 18:30:17 -0800940
941private:
Chris Craikd218a922014-01-02 17:13:34 -0800942 const SkBitmap* mBitmap;
Chris Craik2af46352012-11-26 18:30:17 -0800943 int mMeshWidth;
944 int mMeshHeight;
Chris Craikd218a922014-01-02 17:13:34 -0800945 const float* mVertices;
946 const int* mColors;
Chris Craik2af46352012-11-26 18:30:17 -0800947};
948
949class DrawPatchOp : public DrawBoundedOp {
950public:
Chris Craikd218a922014-01-02 17:13:34 -0800951 DrawPatchOp(const SkBitmap* bitmap, const Res_png_9patch* patch,
952 float left, float top, float right, float bottom, const SkPaint* paint)
Romain Guy03c00b52013-06-20 18:30:28 -0700953 : DrawBoundedOp(left, top, right, bottom, paint),
Romain Guy55b6f952013-06-27 15:27:09 -0700954 mBitmap(bitmap), mPatch(patch), mGenerationId(0), mMesh(NULL),
955 mAtlas(Caches::getInstance().assetAtlas) {
956 mEntry = mAtlas.getEntry(bitmap);
957 if (mEntry) {
958 mEntryGenerationId = mAtlas.getGenerationId();
959 }
Romain Guy3b748a42013-04-17 18:54:38 -0700960 };
Chris Craik2af46352012-11-26 18:30:17 -0800961
Romain Guy55b6f952013-06-27 15:27:09 -0700962 AssetAtlas::Entry* getAtlasEntry() {
963 // The atlas entry is stale, let's get a new one
964 if (mEntry && mEntryGenerationId != mAtlas.getGenerationId()) {
965 mEntryGenerationId = mAtlas.getGenerationId();
966 mEntry = mAtlas.getEntry(mBitmap);
967 }
968 return mEntry;
969 }
970
Romain Guy03c00b52013-06-20 18:30:28 -0700971 const Patch* getMesh(OpenGLRenderer& renderer) {
Romain Guy4c2547f2013-06-11 16:19:24 -0700972 if (!mMesh || renderer.getCaches().patchCache.getGenerationId() != mGenerationId) {
973 PatchCache& cache = renderer.getCaches().patchCache;
Romain Guy55b6f952013-06-27 15:27:09 -0700974 mMesh = cache.get(getAtlasEntry(), mBitmap->width(), mBitmap->height(),
Romain Guy03c00b52013-06-20 18:30:28 -0700975 mLocalBounds.getWidth(), mLocalBounds.getHeight(), mPatch);
Romain Guy4c2547f2013-06-11 16:19:24 -0700976 mGenerationId = cache.getGenerationId();
977 }
Romain Guy03c00b52013-06-20 18:30:28 -0700978 return mMesh;
979 }
980
981 /**
982 * This multi-draw operation builds an indexed mesh on the stack by copying
983 * and transforming the vertices of each 9-patch in the batch. This method
984 * is also responsible for dirtying the current layer, if any.
985 */
986 virtual status_t multiDraw(OpenGLRenderer& renderer, Rect& dirty,
Chris Craikc1c5f082013-09-11 16:23:37 -0700987 const Vector<OpStatePair>& ops, const Rect& bounds) {
988 const DeferredDisplayState& firstState = *(ops[0].state);
989 renderer.restoreDisplayState(firstState, true); // restore all but the clip
Romain Guy03c00b52013-06-20 18:30:28 -0700990
991 // Batches will usually contain a small number of items so it's
992 // worth performing a first iteration to count the exact number
993 // of vertices we need in the new mesh
994 uint32_t totalVertices = 0;
995 for (unsigned int i = 0; i < ops.size(); i++) {
Chris Craikc1c5f082013-09-11 16:23:37 -0700996 totalVertices += ((DrawPatchOp*) ops[i].op)->getMesh(renderer)->verticesCount;
Romain Guy03c00b52013-06-20 18:30:28 -0700997 }
998
999 const bool hasLayer = renderer.hasLayer();
1000
1001 uint32_t indexCount = 0;
1002
1003 TextureVertex vertices[totalVertices];
1004 TextureVertex* vertex = &vertices[0];
1005
1006 // Create a mesh that contains the transformed vertices for all the
1007 // 9-patch objects that are part of the batch. Note that onDefer()
1008 // enforces ops drawn by this function to have a pure translate or
1009 // identity matrix
1010 for (unsigned int i = 0; i < ops.size(); i++) {
Chris Craikc1c5f082013-09-11 16:23:37 -07001011 DrawPatchOp* patchOp = (DrawPatchOp*) ops[i].op;
1012 const DeferredDisplayState* state = ops[i].state;
Romain Guy03c00b52013-06-20 18:30:28 -07001013 const Patch* opMesh = patchOp->getMesh(renderer);
1014 uint32_t vertexCount = opMesh->verticesCount;
1015 if (vertexCount == 0) continue;
1016
1017 // We use the bounds to know where to translate our vertices
1018 // Using patchOp->state.mBounds wouldn't work because these
1019 // bounds are clipped
Chris Craikc1c5f082013-09-11 16:23:37 -07001020 const float tx = (int) floorf(state->mMatrix.getTranslateX() +
Romain Guy03c00b52013-06-20 18:30:28 -07001021 patchOp->mLocalBounds.left + 0.5f);
Chris Craikc1c5f082013-09-11 16:23:37 -07001022 const float ty = (int) floorf(state->mMatrix.getTranslateY() +
Romain Guy03c00b52013-06-20 18:30:28 -07001023 patchOp->mLocalBounds.top + 0.5f);
1024
1025 // Copy & transform all the vertices for the current operation
1026 TextureVertex* opVertices = opMesh->vertices;
1027 for (uint32_t j = 0; j < vertexCount; j++, opVertices++) {
1028 TextureVertex::set(vertex++,
Romain Guy3380cfd2013-08-15 16:57:57 -07001029 opVertices->x + tx, opVertices->y + ty,
1030 opVertices->u, opVertices->v);
Romain Guy03c00b52013-06-20 18:30:28 -07001031 }
1032
1033 // Dirty the current layer if possible. When the 9-patch does not
1034 // contain empty quads we can take a shortcut and simply set the
1035 // dirty rect to the object's bounds.
1036 if (hasLayer) {
1037 if (!opMesh->hasEmptyQuads) {
1038 renderer.dirtyLayer(tx, ty,
1039 tx + patchOp->mLocalBounds.getWidth(),
1040 ty + patchOp->mLocalBounds.getHeight());
1041 } else {
1042 const size_t count = opMesh->quads.size();
1043 for (size_t i = 0; i < count; i++) {
1044 const Rect& quadBounds = opMesh->quads[i];
1045 const float x = tx + quadBounds.left;
1046 const float y = ty + quadBounds.top;
1047 renderer.dirtyLayer(x, y,
1048 x + quadBounds.getWidth(), y + quadBounds.getHeight());
1049 }
1050 }
1051 }
1052
1053 indexCount += opMesh->indexCount;
1054 }
1055
Romain Guy55b6f952013-06-27 15:27:09 -07001056 return renderer.drawPatches(mBitmap, getAtlasEntry(),
1057 &vertices[0], indexCount, getPaint(renderer));
Romain Guy03c00b52013-06-20 18:30:28 -07001058 }
1059
1060 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Romain Guy4c2547f2013-06-11 16:19:24 -07001061 // We're not calling the public variant of drawPatch() here
1062 // This method won't perform the quickReject() since we've already done it at this point
Romain Guy55b6f952013-06-27 15:27:09 -07001063 return renderer.drawPatch(mBitmap, getMesh(renderer), getAtlasEntry(),
Romain Guy03c00b52013-06-20 18:30:28 -07001064 mLocalBounds.left, mLocalBounds.top, mLocalBounds.right, mLocalBounds.bottom,
1065 getPaint(renderer));
Chris Craik2af46352012-11-26 18:30:17 -08001066 }
1067
Chris Craikc5493fb2013-06-19 16:58:58 -07001068 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001069 OP_LOG("Draw patch "RECT_STRING, RECT_ARGS(mLocalBounds));
1070 }
1071
1072 virtual const char* name() { return "DrawPatch"; }
Chris Craik527a3aa2013-03-04 10:19:31 -08001073
Chris Craikc1c5f082013-09-11 16:23:37 -07001074 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
1075 const DeferredDisplayState& state) {
Chris Craik28ce94a2013-05-31 11:38:03 -07001076 deferInfo.batchId = DeferredDisplayList::kOpBatch_Patch;
Romain Guy7f6d6b02013-08-06 13:49:28 -07001077 deferInfo.mergeId = getAtlasEntry() ? (mergeid_t) mEntry->getMergeId() : (mergeid_t) mBitmap;
Romain Guy03c00b52013-06-20 18:30:28 -07001078 deferInfo.mergeable = state.mMatrix.isPureTranslate() &&
1079 OpenGLRenderer::getXfermodeDirect(mPaint) == SkXfermode::kSrcOver_Mode;
Chris Craikc1c5f082013-09-11 16:23:37 -07001080 deferInfo.opaqueOverBounds = isOpaqueOverBounds(state) && mBitmap->isOpaque();
Chris Craikc3566d02013-02-04 16:16:33 -08001081 }
Chris Craik2af46352012-11-26 18:30:17 -08001082
1083private:
Chris Craikd218a922014-01-02 17:13:34 -08001084 const SkBitmap* mBitmap;
1085 const Res_png_9patch* mPatch;
Romain Guy4c2547f2013-06-11 16:19:24 -07001086
Romain Guy4c2547f2013-06-11 16:19:24 -07001087 uint32_t mGenerationId;
1088 const Patch* mMesh;
Romain Guy03c00b52013-06-20 18:30:28 -07001089
Romain Guy55b6f952013-06-27 15:27:09 -07001090 const AssetAtlas& mAtlas;
1091 uint32_t mEntryGenerationId;
Romain Guy3b748a42013-04-17 18:54:38 -07001092 AssetAtlas::Entry* mEntry;
Chris Craik2af46352012-11-26 18:30:17 -08001093};
1094
1095class DrawColorOp : public DrawOp {
1096public:
1097 DrawColorOp(int color, SkXfermode::Mode mode)
Chris Craikf57776b2013-10-25 18:30:17 -07001098 : DrawOp(NULL), mColor(color), mMode(mode) {};
Chris Craik2af46352012-11-26 18:30:17 -08001099
Chris Craik527a3aa2013-03-04 10:19:31 -08001100 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001101 return renderer.drawColor(mColor, mMode);
1102 }
1103
Chris Craikc5493fb2013-06-19 16:58:58 -07001104 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001105 OP_LOG("Draw color %#x, mode %d", mColor, mMode);
1106 }
1107
1108 virtual const char* name() { return "DrawColor"; }
1109
1110private:
1111 int mColor;
1112 SkXfermode::Mode mMode;
1113};
1114
1115class DrawStrokableOp : public DrawBoundedOp {
1116public:
Chris Craikd218a922014-01-02 17:13:34 -08001117 DrawStrokableOp(float left, float top, float right, float bottom, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001118 : DrawBoundedOp(left, top, right, bottom, paint) {};
1119
Chris Craikc1c5f082013-09-11 16:23:37 -07001120 bool getLocalBounds(const DrawModifiers& drawModifiers, Rect& localBounds) {
Chris Craikc3566d02013-02-04 16:16:33 -08001121 localBounds.set(mLocalBounds);
Chris Craik2af46352012-11-26 18:30:17 -08001122 if (mPaint && mPaint->getStyle() != SkPaint::kFill_Style) {
Chris Craikc3566d02013-02-04 16:16:33 -08001123 localBounds.outset(strokeWidthOutset());
Chris Craik2af46352012-11-26 18:30:17 -08001124 }
1125 return true;
1126 }
Chris Craikc3566d02013-02-04 16:16:33 -08001127
Chris Craikc1c5f082013-09-11 16:23:37 -07001128 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
1129 const DeferredDisplayState& state) {
Chris Craikc3566d02013-02-04 16:16:33 -08001130 if (mPaint->getPathEffect()) {
Chris Craik28ce94a2013-05-31 11:38:03 -07001131 deferInfo.batchId = DeferredDisplayList::kOpBatch_AlphaMaskTexture;
Chris Craik527a3aa2013-03-04 10:19:31 -08001132 } else {
Chris Craik28ce94a2013-05-31 11:38:03 -07001133 deferInfo.batchId = mPaint->isAntiAlias() ?
Chris Craik527a3aa2013-03-04 10:19:31 -08001134 DeferredDisplayList::kOpBatch_AlphaVertices :
1135 DeferredDisplayList::kOpBatch_Vertices;
Chris Craikc3566d02013-02-04 16:16:33 -08001136 }
Chris Craikc3566d02013-02-04 16:16:33 -08001137 }
Chris Craik2af46352012-11-26 18:30:17 -08001138};
1139
1140class DrawRectOp : public DrawStrokableOp {
1141public:
Chris Craikd218a922014-01-02 17:13:34 -08001142 DrawRectOp(float left, float top, float right, float bottom, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001143 : DrawStrokableOp(left, top, right, bottom, paint) {}
1144
Chris Craik527a3aa2013-03-04 10:19:31 -08001145 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001146 return renderer.drawRect(mLocalBounds.left, mLocalBounds.top,
1147 mLocalBounds.right, mLocalBounds.bottom, getPaint(renderer));
1148 }
1149
Chris Craikc5493fb2013-06-19 16:58:58 -07001150 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001151 OP_LOG("Draw Rect "RECT_STRING, RECT_ARGS(mLocalBounds));
1152 }
1153
Chris Craikc1c5f082013-09-11 16:23:37 -07001154 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
1155 const DeferredDisplayState& state) {
1156 DrawStrokableOp::onDefer(renderer, deferInfo, state);
1157 deferInfo.opaqueOverBounds = isOpaqueOverBounds(state) &&
Chris Craik28ce94a2013-05-31 11:38:03 -07001158 mPaint->getStyle() == SkPaint::kFill_Style;
1159 }
1160
Chris Craik2af46352012-11-26 18:30:17 -08001161 virtual const char* name() { return "DrawRect"; }
1162};
1163
Chris Craik5d116762013-02-19 17:49:31 -08001164class DrawRectsOp : public DrawBoundedOp {
Chris Craik2af46352012-11-26 18:30:17 -08001165public:
Chris Craikd218a922014-01-02 17:13:34 -08001166 DrawRectsOp(const float* rects, int count, const SkPaint* paint)
Chris Craik5d116762013-02-19 17:49:31 -08001167 : DrawBoundedOp(rects, count, paint),
1168 mRects(rects), mCount(count) {}
Chris Craik2af46352012-11-26 18:30:17 -08001169
Chris Craik527a3aa2013-03-04 10:19:31 -08001170 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001171 return renderer.drawRects(mRects, mCount, getPaint(renderer));
1172 }
1173
Chris Craikc5493fb2013-06-19 16:58:58 -07001174 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001175 OP_LOG("Draw Rects count %d", mCount);
1176 }
1177
1178 virtual const char* name() { return "DrawRects"; }
1179
Chris Craikc1c5f082013-09-11 16:23:37 -07001180 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
1181 const DeferredDisplayState& state) {
Chris Craik28ce94a2013-05-31 11:38:03 -07001182 deferInfo.batchId = DeferredDisplayList::kOpBatch_Vertices;
Chris Craikc3566d02013-02-04 16:16:33 -08001183 }
1184
Chris Craik2af46352012-11-26 18:30:17 -08001185private:
1186 const float* mRects;
1187 int mCount;
1188};
1189
1190class DrawRoundRectOp : public DrawStrokableOp {
1191public:
1192 DrawRoundRectOp(float left, float top, float right, float bottom,
Chris Craikd218a922014-01-02 17:13:34 -08001193 float rx, float ry, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001194 : DrawStrokableOp(left, top, right, bottom, paint), mRx(rx), mRy(ry) {}
1195
Chris Craik527a3aa2013-03-04 10:19:31 -08001196 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001197 return renderer.drawRoundRect(mLocalBounds.left, mLocalBounds.top,
1198 mLocalBounds.right, mLocalBounds.bottom, mRx, mRy, getPaint(renderer));
1199 }
1200
Chris Craikc5493fb2013-06-19 16:58:58 -07001201 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001202 OP_LOG("Draw RoundRect "RECT_STRING", rx %f, ry %f", RECT_ARGS(mLocalBounds), mRx, mRy);
1203 }
1204
1205 virtual const char* name() { return "DrawRoundRect"; }
1206
1207private:
1208 float mRx;
1209 float mRy;
1210};
1211
1212class DrawCircleOp : public DrawStrokableOp {
1213public:
Chris Craikd218a922014-01-02 17:13:34 -08001214 DrawCircleOp(float x, float y, float radius, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001215 : DrawStrokableOp(x - radius, y - radius, x + radius, y + radius, paint),
1216 mX(x), mY(y), mRadius(radius) {}
1217
Chris Craik527a3aa2013-03-04 10:19:31 -08001218 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001219 return renderer.drawCircle(mX, mY, mRadius, getPaint(renderer));
1220 }
1221
Chris Craikc5493fb2013-06-19 16:58:58 -07001222 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001223 OP_LOG("Draw Circle x %f, y %f, r %f", mX, mY, mRadius);
1224 }
1225
1226 virtual const char* name() { return "DrawCircle"; }
1227
1228private:
1229 float mX;
1230 float mY;
1231 float mRadius;
1232};
1233
1234class DrawOvalOp : public DrawStrokableOp {
1235public:
Chris Craikd218a922014-01-02 17:13:34 -08001236 DrawOvalOp(float left, float top, float right, float bottom, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001237 : DrawStrokableOp(left, top, right, bottom, paint) {}
1238
Chris Craik527a3aa2013-03-04 10:19:31 -08001239 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001240 return renderer.drawOval(mLocalBounds.left, mLocalBounds.top,
1241 mLocalBounds.right, mLocalBounds.bottom, getPaint(renderer));
1242 }
1243
Chris Craikc5493fb2013-06-19 16:58:58 -07001244 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001245 OP_LOG("Draw Oval "RECT_STRING, RECT_ARGS(mLocalBounds));
1246 }
1247
1248 virtual const char* name() { return "DrawOval"; }
1249};
1250
1251class DrawArcOp : public DrawStrokableOp {
1252public:
1253 DrawArcOp(float left, float top, float right, float bottom,
Chris Craikd218a922014-01-02 17:13:34 -08001254 float startAngle, float sweepAngle, bool useCenter, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001255 : DrawStrokableOp(left, top, right, bottom, paint),
1256 mStartAngle(startAngle), mSweepAngle(sweepAngle), mUseCenter(useCenter) {}
1257
Chris Craik527a3aa2013-03-04 10:19:31 -08001258 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001259 return renderer.drawArc(mLocalBounds.left, mLocalBounds.top,
1260 mLocalBounds.right, mLocalBounds.bottom,
1261 mStartAngle, mSweepAngle, mUseCenter, getPaint(renderer));
1262 }
1263
Chris Craikc5493fb2013-06-19 16:58:58 -07001264 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001265 OP_LOG("Draw Arc "RECT_STRING", start %f, sweep %f, useCenter %d",
1266 RECT_ARGS(mLocalBounds), mStartAngle, mSweepAngle, mUseCenter);
1267 }
1268
1269 virtual const char* name() { return "DrawArc"; }
1270
1271private:
1272 float mStartAngle;
1273 float mSweepAngle;
1274 bool mUseCenter;
1275};
1276
1277class DrawPathOp : public DrawBoundedOp {
1278public:
Chris Craikd218a922014-01-02 17:13:34 -08001279 DrawPathOp(const SkPath* path, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001280 : DrawBoundedOp(paint), mPath(path) {
1281 float left, top, offset;
1282 uint32_t width, height;
Romain Guyca89e2a2013-03-08 17:44:20 -08001283 PathCache::computePathBounds(path, paint, left, top, offset, width, height);
Chris Craik2af46352012-11-26 18:30:17 -08001284 left -= offset;
1285 top -= offset;
1286 mLocalBounds.set(left, top, left + width, top + height);
1287 }
1288
Chris Craik527a3aa2013-03-04 10:19:31 -08001289 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001290 return renderer.drawPath(mPath, getPaint(renderer));
1291 }
1292
Chris Craikc1c5f082013-09-11 16:23:37 -07001293 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
1294 const DeferredDisplayState& state) {
Chris Craikd218a922014-01-02 17:13:34 -08001295 const SkPaint* paint = getPaint(renderer);
Romain Guyca89e2a2013-03-08 17:44:20 -08001296 renderer.getCaches().pathCache.precache(mPath, paint);
Chris Craik527a3aa2013-03-04 10:19:31 -08001297
Chris Craik28ce94a2013-05-31 11:38:03 -07001298 deferInfo.batchId = DeferredDisplayList::kOpBatch_AlphaMaskTexture;
Romain Guyca89e2a2013-03-08 17:44:20 -08001299 }
1300
Chris Craikc5493fb2013-06-19 16:58:58 -07001301 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001302 OP_LOG("Draw Path %p in "RECT_STRING, mPath, RECT_ARGS(mLocalBounds));
1303 }
1304
1305 virtual const char* name() { return "DrawPath"; }
1306
1307private:
Chris Craikd218a922014-01-02 17:13:34 -08001308 const SkPath* mPath;
Chris Craik2af46352012-11-26 18:30:17 -08001309};
1310
Chris Craikc3566d02013-02-04 16:16:33 -08001311class DrawLinesOp : public DrawBoundedOp {
Chris Craik2af46352012-11-26 18:30:17 -08001312public:
Chris Craikd218a922014-01-02 17:13:34 -08001313 DrawLinesOp(const float* points, int count, const SkPaint* paint)
Chris Craik5d116762013-02-19 17:49:31 -08001314 : DrawBoundedOp(points, count, paint),
1315 mPoints(points), mCount(count) {
Chris Craikc3566d02013-02-04 16:16:33 -08001316 mLocalBounds.outset(strokeWidthOutset());
Chris Craik2af46352012-11-26 18:30:17 -08001317 }
1318
Chris Craik527a3aa2013-03-04 10:19:31 -08001319 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001320 return renderer.drawLines(mPoints, mCount, getPaint(renderer));
1321 }
1322
Chris Craikc5493fb2013-06-19 16:58:58 -07001323 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001324 OP_LOG("Draw Lines count %d", mCount);
1325 }
1326
1327 virtual const char* name() { return "DrawLines"; }
1328
Chris Craikc1c5f082013-09-11 16:23:37 -07001329 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
1330 const DeferredDisplayState& state) {
Chris Craik28ce94a2013-05-31 11:38:03 -07001331 deferInfo.batchId = mPaint->isAntiAlias() ?
Chris Craikc3566d02013-02-04 16:16:33 -08001332 DeferredDisplayList::kOpBatch_AlphaVertices :
1333 DeferredDisplayList::kOpBatch_Vertices;
1334 }
1335
Chris Craik2af46352012-11-26 18:30:17 -08001336protected:
Chris Craikd218a922014-01-02 17:13:34 -08001337 const float* mPoints;
Chris Craik2af46352012-11-26 18:30:17 -08001338 int mCount;
1339};
1340
1341class DrawPointsOp : public DrawLinesOp {
1342public:
Chris Craikd218a922014-01-02 17:13:34 -08001343 DrawPointsOp(const float* points, int count, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001344 : DrawLinesOp(points, count, paint) {}
1345
Chris Craik527a3aa2013-03-04 10:19:31 -08001346 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001347 return renderer.drawPoints(mPoints, mCount, getPaint(renderer));
1348 }
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 Points count %d", mCount);
1352 }
1353
1354 virtual const char* name() { return "DrawPoints"; }
1355};
1356
1357class DrawSomeTextOp : public DrawOp {
1358public:
Chris Craikd218a922014-01-02 17:13:34 -08001359 DrawSomeTextOp(const char* text, int bytesCount, int count, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001360 : DrawOp(paint), mText(text), mBytesCount(bytesCount), mCount(count) {};
1361
Chris Craikc5493fb2013-06-19 16:58:58 -07001362 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001363 OP_LOG("Draw some text, %d bytes", mBytesCount);
1364 }
Chris Craikc3566d02013-02-04 16:16:33 -08001365
Chris Craikc1c5f082013-09-11 16:23:37 -07001366 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
1367 const DeferredDisplayState& state) {
Chris Craikd218a922014-01-02 17:13:34 -08001368 const SkPaint* paint = getPaint(renderer);
Romain Guy0f667532013-03-01 14:31:04 -08001369 FontRenderer& fontRenderer = renderer.getCaches().fontRenderer->getFontRenderer(paint);
1370 fontRenderer.precache(paint, mText, mCount, mat4::identity());
Romain Guy0f667532013-03-01 14:31:04 -08001371
Chris Craik28ce94a2013-05-31 11:38:03 -07001372 deferInfo.batchId = mPaint->getColor() == 0xff000000 ?
Chris Craikc3566d02013-02-04 16:16:33 -08001373 DeferredDisplayList::kOpBatch_Text :
1374 DeferredDisplayList::kOpBatch_ColorText;
1375 }
Chris Craik527a3aa2013-03-04 10:19:31 -08001376
Chris Craik2af46352012-11-26 18:30:17 -08001377protected:
1378 const char* mText;
1379 int mBytesCount;
1380 int mCount;
1381};
1382
1383class DrawTextOnPathOp : public DrawSomeTextOp {
1384public:
1385 DrawTextOnPathOp(const char* text, int bytesCount, int count,
Chris Craikd218a922014-01-02 17:13:34 -08001386 const SkPath* path, float hOffset, float vOffset, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001387 : DrawSomeTextOp(text, bytesCount, count, paint),
1388 mPath(path), mHOffset(hOffset), mVOffset(vOffset) {
1389 /* TODO: inherit from DrawBounded and init mLocalBounds */
1390 }
1391
Chris Craik527a3aa2013-03-04 10:19:31 -08001392 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001393 return renderer.drawTextOnPath(mText, mBytesCount, mCount, mPath,
1394 mHOffset, mVOffset, getPaint(renderer));
1395 }
1396
1397 virtual const char* name() { return "DrawTextOnPath"; }
1398
1399private:
Chris Craikd218a922014-01-02 17:13:34 -08001400 const SkPath* mPath;
Chris Craik2af46352012-11-26 18:30:17 -08001401 float mHOffset;
1402 float mVOffset;
1403};
1404
1405class DrawPosTextOp : public DrawSomeTextOp {
1406public:
1407 DrawPosTextOp(const char* text, int bytesCount, int count,
Chris Craikd218a922014-01-02 17:13:34 -08001408 const float* positions, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001409 : DrawSomeTextOp(text, bytesCount, count, paint), mPositions(positions) {
1410 /* TODO: inherit from DrawBounded and init mLocalBounds */
1411 }
1412
Chris Craik527a3aa2013-03-04 10:19:31 -08001413 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001414 return renderer.drawPosText(mText, mBytesCount, mCount, mPositions, getPaint(renderer));
1415 }
1416
1417 virtual const char* name() { return "DrawPosText"; }
1418
1419private:
1420 const float* mPositions;
1421};
1422
1423class DrawTextOp : public DrawBoundedOp {
1424public:
1425 DrawTextOp(const char* text, int bytesCount, int count, float x, float y,
Chris Craikd218a922014-01-02 17:13:34 -08001426 const float* positions, const SkPaint* paint, float totalAdvance, const Rect& bounds)
Chris Craik41541822013-05-03 16:35:54 -07001427 : DrawBoundedOp(bounds, paint), mText(text), mBytesCount(bytesCount), mCount(count),
1428 mX(x), mY(y), mPositions(positions), mTotalAdvance(totalAdvance) {
Romain Guybd3055f2013-03-13 16:14:47 -07001429 memset(&mPrecacheTransform.data[0], 0xff, 16 * sizeof(float));
Chris Craik2af46352012-11-26 18:30:17 -08001430 }
1431
Chris Craikc1c5f082013-09-11 16:23:37 -07001432 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
1433 const DeferredDisplayState& state) {
Chris Craikd218a922014-01-02 17:13:34 -08001434 const SkPaint* paint = getPaint(renderer);
Romain Guy0f667532013-03-01 14:31:04 -08001435 FontRenderer& fontRenderer = renderer.getCaches().fontRenderer->getFontRenderer(paint);
Romain Guybd3055f2013-03-13 16:14:47 -07001436 const mat4& transform = renderer.findBestFontTransform(state.mMatrix);
1437 if (mPrecacheTransform != transform) {
1438 fontRenderer.precache(paint, mText, mCount, transform);
1439 mPrecacheTransform = transform;
1440 }
Chris Craik28ce94a2013-05-31 11:38:03 -07001441 deferInfo.batchId = mPaint->getColor() == 0xff000000 ?
Chris Craik527a3aa2013-03-04 10:19:31 -08001442 DeferredDisplayList::kOpBatch_Text :
1443 DeferredDisplayList::kOpBatch_ColorText;
1444
Chris Craik28ce94a2013-05-31 11:38:03 -07001445 deferInfo.mergeId = (mergeid_t)mPaint->getColor();
Chris Craik527a3aa2013-03-04 10:19:31 -08001446
1447 // don't merge decorated text - the decorations won't draw in order
1448 bool noDecorations = !(mPaint->getFlags() & (SkPaint::kUnderlineText_Flag |
1449 SkPaint::kStrikeThruText_Flag));
Chris Craik28ce94a2013-05-31 11:38:03 -07001450 deferInfo.mergeable = state.mMatrix.isPureTranslate() && noDecorations &&
1451 OpenGLRenderer::getXfermodeDirect(mPaint) == SkXfermode::kSrcOver_Mode;
Romain Guy0f667532013-03-01 14:31:04 -08001452 }
1453
Chris Craik527a3aa2013-03-04 10:19:31 -08001454 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Romain Guy9b5a1a22013-08-09 14:06:29 -07001455 Rect bounds;
Chris Craikc1c5f082013-09-11 16:23:37 -07001456 getLocalBounds(renderer.getDrawModifiers(), bounds);
Chris Craik2af46352012-11-26 18:30:17 -08001457 return renderer.drawText(mText, mBytesCount, mCount, mX, mY,
Romain Guy9b5a1a22013-08-09 14:06:29 -07001458 mPositions, getPaint(renderer), mTotalAdvance, bounds);
Chris Craik2af46352012-11-26 18:30:17 -08001459 }
1460
Chris Craik527a3aa2013-03-04 10:19:31 -08001461 virtual status_t multiDraw(OpenGLRenderer& renderer, Rect& dirty,
Chris Craikc1c5f082013-09-11 16:23:37 -07001462 const Vector<OpStatePair>& ops, const Rect& bounds) {
Chris Craik527a3aa2013-03-04 10:19:31 -08001463 status_t status = DrawGlInfo::kStatusDone;
Chris Craik527a3aa2013-03-04 10:19:31 -08001464 for (unsigned int i = 0; i < ops.size(); i++) {
Chris Craikc1c5f082013-09-11 16:23:37 -07001465 const DeferredDisplayState& state = *(ops[i].state);
Chris Craik527a3aa2013-03-04 10:19:31 -08001466 DrawOpMode drawOpMode = (i == ops.size() - 1) ? kDrawOpMode_Flush : kDrawOpMode_Defer;
Chris Craikc1c5f082013-09-11 16:23:37 -07001467 renderer.restoreDisplayState(state, true); // restore all but the clip
Chris Craik527a3aa2013-03-04 10:19:31 -08001468
Chris Craikc1c5f082013-09-11 16:23:37 -07001469 DrawTextOp& op = *((DrawTextOp*)ops[i].op);
Romain Guy9b5a1a22013-08-09 14:06:29 -07001470 // quickReject() will not occure in drawText() so we can use mLocalBounds
1471 // directly, we do not need to account for shadow by calling getLocalBounds()
Chris Craik527a3aa2013-03-04 10:19:31 -08001472 status |= renderer.drawText(op.mText, op.mBytesCount, op.mCount, op.mX, op.mY,
Chris Craik41541822013-05-03 16:35:54 -07001473 op.mPositions, op.getPaint(renderer), op.mTotalAdvance, op.mLocalBounds,
1474 drawOpMode);
Chris Craik527a3aa2013-03-04 10:19:31 -08001475 }
1476 return status;
1477 }
1478
Chris Craikc5493fb2013-06-19 16:58:58 -07001479 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001480 OP_LOG("Draw Text of count %d, bytes %d", mCount, mBytesCount);
1481 }
1482
1483 virtual const char* name() { return "DrawText"; }
1484
1485private:
1486 const char* mText;
1487 int mBytesCount;
1488 int mCount;
1489 float mX;
1490 float mY;
1491 const float* mPositions;
Chris Craik41541822013-05-03 16:35:54 -07001492 float mTotalAdvance;
Romain Guybd3055f2013-03-13 16:14:47 -07001493 mat4 mPrecacheTransform;
Chris Craik2af46352012-11-26 18:30:17 -08001494};
1495
1496///////////////////////////////////////////////////////////////////////////////
1497// SPECIAL DRAW OPERATIONS
1498///////////////////////////////////////////////////////////////////////////////
1499
1500class DrawFunctorOp : public DrawOp {
1501public:
1502 DrawFunctorOp(Functor* functor)
Chris Craikf57776b2013-10-25 18:30:17 -07001503 : DrawOp(NULL), mFunctor(functor) {}
Chris Craik2af46352012-11-26 18:30:17 -08001504
Chris Craik527a3aa2013-03-04 10:19:31 -08001505 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001506 renderer.startMark("GL functor");
1507 status_t ret = renderer.callDrawGLFunction(mFunctor, dirty);
1508 renderer.endMark();
1509 return ret;
1510 }
1511
Chris Craikc5493fb2013-06-19 16:58:58 -07001512 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001513 OP_LOG("Draw Functor %p", mFunctor);
1514 }
1515
1516 virtual const char* name() { return "DrawFunctor"; }
1517
1518private:
1519 Functor* mFunctor;
1520};
1521
Chris Craik5d116762013-02-19 17:49:31 -08001522class DrawDisplayListOp : public DrawBoundedOp {
Chris Craikf57776b2013-10-25 18:30:17 -07001523 friend class DisplayList; // grant DisplayList access to info of child
Chris Craik2af46352012-11-26 18:30:17 -08001524public:
Chris Craikf57776b2013-10-25 18:30:17 -07001525 DrawDisplayListOp(DisplayList* displayList, int flags, const mat4& transformFromParent)
Chris Craik5d116762013-02-19 17:49:31 -08001526 : DrawBoundedOp(0, 0, displayList->getWidth(), displayList->getHeight(), 0),
Chris Craikf57776b2013-10-25 18:30:17 -07001527 mDisplayList(displayList), mFlags(flags), mTransformFromParent(transformFromParent) {}
Chris Craikc3566d02013-02-04 16:16:33 -08001528
Chet Haasedd671592013-04-19 14:54:34 -07001529 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
1530 bool useQuickReject) {
Chris Craikf57776b2013-10-25 18:30:17 -07001531 if (mDisplayList && mDisplayList->isRenderable() && !mSkipInOrderDraw) {
Chris Craikff785832013-03-08 13:12:16 -08001532 mDisplayList->defer(deferStruct, level + 1);
Chris Craikc3566d02013-02-04 16:16:33 -08001533 }
Chris Craikc3566d02013-02-04 16:16:33 -08001534 }
Chet Haasedd671592013-04-19 14:54:34 -07001535 virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level,
1536 bool useQuickReject) {
Chris Craikf57776b2013-10-25 18:30:17 -07001537 if (mDisplayList && mDisplayList->isRenderable() && !mSkipInOrderDraw) {
Chris Craikff785832013-03-08 13:12:16 -08001538 mDisplayList->replay(replayStruct, level + 1);
1539 }
1540 }
Chris Craik2af46352012-11-26 18:30:17 -08001541
Chris Craika08f95c2013-03-15 17:24:33 -07001542 // NOT USED since replay() is overridden
Chris Craik527a3aa2013-03-04 10:19:31 -08001543 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craika08f95c2013-03-15 17:24:33 -07001544 return DrawGlInfo::kStatusDone;
1545 }
Chris Craikff785832013-03-08 13:12:16 -08001546
Chris Craikc5493fb2013-06-19 16:58:58 -07001547 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001548 OP_LOG("Draw Display List %p, flags %#x", mDisplayList, mFlags);
Chris Craikff785832013-03-08 13:12:16 -08001549 if (mDisplayList && (logFlags & kOpLogFlag_Recurse)) {
Chris Craik2af46352012-11-26 18:30:17 -08001550 mDisplayList->output(level + 1);
1551 }
1552 }
1553
1554 virtual const char* name() { return "DrawDisplayList"; }
1555
1556private:
1557 DisplayList* mDisplayList;
Chris Craikf57776b2013-10-25 18:30:17 -07001558 const int mFlags;
1559
1560 ///////////////////////////
1561 // Properties below are used by DisplayList::computeOrderingImpl() and iterate()
1562 ///////////////////////////
1563 /**
1564 * Records transform vs parent, used for computing total transform without rerunning DL contents
1565 */
1566 const mat4 mTransformFromParent;
1567
1568 /**
Chris Craikf533e942014-01-14 22:35:37 -08001569 * Holds the transformation between the 3d root OR projection surface ViewGroup and this
1570 * DisplayList drawing instance. Represents any translations / transformations done within the
1571 * drawing of the compositing ancestor ViewGroup's draw, before the draw of the View represented
1572 * by this DisplayList draw instance.
Chris Craikf57776b2013-10-25 18:30:17 -07001573 *
1574 * Note: doesn't include any transformation recorded within the DisplayList and its properties.
1575 */
Chris Craikf533e942014-01-14 22:35:37 -08001576 mat4 mTransformFromCompositingAncestor;
Chris Craikf57776b2013-10-25 18:30:17 -07001577 bool mSkipInOrderDraw;
1578};
1579
1580/**
1581 * Not a canvas operation, used only by 3d / z ordering logic in DisplayList::iterate()
1582 */
1583class DrawShadowOp : public DrawOp {
1584public:
Chris Craika2fe7af2014-01-28 17:25:06 -08001585 DrawShadowOp(const mat4& transform, float alpha, const SkPath* outline,
1586 float fallbackWidth, float fallbackHeight)
1587 : DrawOp(NULL), mTransform(transform), mAlpha(alpha), mOutline(outline),
1588 mFallbackWidth(fallbackWidth), mFallbackHeight(fallbackHeight) {}
Chris Craikf57776b2013-10-25 18:30:17 -07001589
1590 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craika2fe7af2014-01-28 17:25:06 -08001591 if (!mOutline->isEmpty()) {
1592 return renderer.drawShadow(mTransform, mAlpha, mOutline);
1593 }
1594
1595 SkPath fakeOutline;
1596 fakeOutline.addRect(0, 0, mFallbackWidth, mFallbackHeight);
1597 return renderer.drawShadow(mTransform, mAlpha, &fakeOutline);
Chris Craikf57776b2013-10-25 18:30:17 -07001598 }
1599
1600 virtual void output(int level, uint32_t logFlags) const {
Chris Craika2fe7af2014-01-28 17:25:06 -08001601 OP_LOG("DrawShadow of outline %p", mOutline);
Chris Craikf57776b2013-10-25 18:30:17 -07001602 }
1603
1604 virtual const char* name() { return "DrawShadow"; }
1605
1606private:
Chris Craika2fe7af2014-01-28 17:25:06 -08001607 const mat4 mTransform;
1608 const float mAlpha;
1609 const SkPath* mOutline;
1610 const float mFallbackWidth;
1611 const float mFallbackHeight;
Chris Craik2af46352012-11-26 18:30:17 -08001612};
1613
1614class DrawLayerOp : public DrawOp {
1615public:
Chris Craika08f95c2013-03-15 17:24:33 -07001616 DrawLayerOp(Layer* layer, float x, float y)
Chris Craikf57776b2013-10-25 18:30:17 -07001617 : DrawOp(NULL), mLayer(layer), mX(x), mY(y) {}
Chris Craik2af46352012-11-26 18:30:17 -08001618
Chris Craik527a3aa2013-03-04 10:19:31 -08001619 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craika08f95c2013-03-15 17:24:33 -07001620 return renderer.drawLayer(mLayer, mX, mY);
Chris Craik2af46352012-11-26 18:30:17 -08001621 }
1622
Chris Craikc5493fb2013-06-19 16:58:58 -07001623 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001624 OP_LOG("Draw Layer %p at %f %f", mLayer, mX, mY);
1625 }
1626
1627 virtual const char* name() { return "DrawLayer"; }
1628
1629private:
1630 Layer* mLayer;
1631 float mX;
1632 float mY;
1633};
1634
1635}; // namespace uirenderer
1636}; // namespace android
1637
1638#endif // ANDROID_HWUI_DISPLAY_OPERATION_H