blob: 881851009b6eedd42fa2d4b010220cc0680b56ff [file] [log] [blame]
Chris Craik2af46352012-11-26 18:30:17 -08001/*
Romain Guy7031ff62013-02-22 11:48:16 -08002 * Copyright (C) 2013 The Android Open Source Project
Chris Craik2af46352012-11-26 18:30:17 -08003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef ANDROID_HWUI_DISPLAY_OPERATION_H
18#define ANDROID_HWUI_DISPLAY_OPERATION_H
19
Romain Guy7031ff62013-02-22 11:48:16 -080020#ifndef LOG_TAG
21 #define LOG_TAG "OpenGLRenderer"
22#endif
23
Chris Craik98d608d2014-07-17 12:25:11 -070024#include <SkColor.h>
Chris Craik8c271ca2014-03-25 10:33:01 -070025#include <SkPath.h>
26#include <SkPathOps.h>
Chris Craik2af46352012-11-26 18:30:17 -080027#include <SkXfermode.h>
28
Chris Craik0776a602013-02-14 15:36:01 -080029#include <private/hwui/DrawGlInfo.h>
30
Chris Craik2af46352012-11-26 18:30:17 -080031#include "OpenGLRenderer.h"
Romain Guy3b748a42013-04-17 18:54:38 -070032#include "AssetAtlas.h"
Chris Craikc3566d02013-02-04 16:16:33 -080033#include "DeferredDisplayList.h"
Chris Craik2af46352012-11-26 18:30:17 -080034#include "DisplayListRenderer.h"
Romain Guy3b748a42013-04-17 18:54:38 -070035#include "UvMapper.h"
Chris Craik2af46352012-11-26 18:30:17 -080036#include "utils/LinearAllocator.h"
37
38#define CRASH() do { \
Romain Guy5216c3b2013-06-14 16:31:37 -070039 *(int *)(uintptr_t) 0xbbadbeef = 0; \
Chris Craik2af46352012-11-26 18:30:17 -080040 ((void(*)())0)(); /* More reliable, but doesn't say BBADBEEF */ \
41} while(false)
42
Chris Craik2af46352012-11-26 18:30:17 -080043// Use OP_LOG for logging with arglist, OP_LOGS if just printing char*
Chris Craik28ce94a2013-05-31 11:38:03 -070044#define OP_LOGS(s) OP_LOG("%s", (s))
Chris Craik3dc553b2013-02-04 12:45:13 -080045#define OP_LOG(s, ...) ALOGD( "%*s" s, level * 2, "", __VA_ARGS__ )
Chris Craik2af46352012-11-26 18:30:17 -080046
Chris Craik2af46352012-11-26 18:30:17 -080047namespace android {
48namespace uirenderer {
49
50/**
51 * Structure for storing canvas operations when they are recorded into a DisplayList, so that they
52 * may be replayed to an OpenGLRenderer.
53 *
54 * To avoid individual memory allocations, DisplayListOps may only be allocated into a
55 * LinearAllocator's managed memory buffers. Each pointer held by a DisplayListOp is either a
56 * pointer into memory also allocated in the LinearAllocator (mostly for text and float buffers) or
57 * references a externally refcounted object (Sk... and Skia... objects). ~DisplayListOp() is
58 * never called as LinearAllocators are simply discarded, so no memory management should be done in
59 * this class.
60 */
61class DisplayListOp {
62public:
63 // These objects should always be allocated with a LinearAllocator, and never destroyed/deleted.
64 // standard new() intentionally not implemented, and delete/deconstructor should never be used.
65 virtual ~DisplayListOp() { CRASH(); }
66 static void operator delete(void* ptr) { CRASH(); }
67 /** static void* operator new(size_t size); PURPOSELY OMITTED **/
68 static void* operator new(size_t size, LinearAllocator& allocator) {
69 return allocator.alloc(size);
70 }
71
72 enum OpLogFlag {
73 kOpLogFlag_Recurse = 0x1,
74 kOpLogFlag_JSON = 0x2 // TODO: add?
75 };
76
Chet Haasedd671592013-04-19 14:54:34 -070077 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
78 bool useQuickReject) = 0;
Chris Craikc3566d02013-02-04 16:16:33 -080079
Chet Haasedd671592013-04-19 14:54:34 -070080 virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level,
81 bool useQuickReject) = 0;
Chris Craikff785832013-03-08 13:12:16 -080082
Chris Craikc5493fb2013-06-19 16:58:58 -070083 virtual void output(int level, uint32_t logFlags = 0) const = 0;
Chris Craik2af46352012-11-26 18:30:17 -080084
85 // NOTE: it would be nice to declare constants and overriding the implementation in each op to
86 // point at the constants, but that seems to require a .cpp file
87 virtual const char* name() = 0;
88};
89
90class StateOp : public DisplayListOp {
91public:
92 StateOp() {};
93
94 virtual ~StateOp() {}
95
Chet Haasedd671592013-04-19 14:54:34 -070096 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
97 bool useQuickReject) {
Chris Craikff785832013-03-08 13:12:16 -080098 // default behavior only affects immediate, deferrable state, issue directly to renderer
99 applyState(deferStruct.mRenderer, saveCount);
100 }
101
Chris Craikc3566d02013-02-04 16:16:33 -0800102 /**
103 * State operations are applied directly to the renderer, but can cause the deferred drawing op
104 * list to flush
105 */
Chet Haasedd671592013-04-19 14:54:34 -0700106 virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level,
107 bool useQuickReject) {
Chris Craikff785832013-03-08 13:12:16 -0800108 applyState(replayStruct.mRenderer, saveCount);
Chris Craikc3566d02013-02-04 16:16:33 -0800109 }
110
Chris Craik7273daa2013-03-28 11:25:24 -0700111 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const = 0;
Chris Craik2af46352012-11-26 18:30:17 -0800112};
113
114class DrawOp : public DisplayListOp {
Chris Craik527a3aa2013-03-04 10:19:31 -0800115friend class MergingDrawBatch;
Chris Craik2af46352012-11-26 18:30:17 -0800116public:
Chris Craikd218a922014-01-02 17:13:34 -0800117 DrawOp(const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -0800118 : mPaint(paint), mQuickRejected(false) {}
119
Chet Haasedd671592013-04-19 14:54:34 -0700120 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
121 bool useQuickReject) {
122 if (mQuickRejected && CC_LIKELY(useQuickReject)) {
Chris Craikff785832013-03-08 13:12:16 -0800123 return;
Chris Craikc3566d02013-02-04 16:16:33 -0800124 }
125
Chris Craikff785832013-03-08 13:12:16 -0800126 deferStruct.mDeferredList.addDrawOp(deferStruct.mRenderer, this);
Chris Craikc3566d02013-02-04 16:16:33 -0800127 }
128
Chet Haasedd671592013-04-19 14:54:34 -0700129 virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level,
130 bool useQuickReject) {
131 if (mQuickRejected && CC_LIKELY(useQuickReject)) {
Chris Craikff785832013-03-08 13:12:16 -0800132 return;
133 }
134
Chris Craik527a3aa2013-03-04 10:19:31 -0800135 replayStruct.mDrawGlStatus |= applyDraw(replayStruct.mRenderer, replayStruct.mDirty);
Chris Craikff785832013-03-08 13:12:16 -0800136 }
137
Chris Craik527a3aa2013-03-04 10:19:31 -0800138 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) = 0;
Chris Craik2af46352012-11-26 18:30:17 -0800139
Chris Craik527a3aa2013-03-04 10:19:31 -0800140 /**
141 * Draw multiple instances of an operation, must be overidden for operations that merge
142 *
143 * Currently guarantees certain similarities between ops (see MergingDrawBatch::canMergeWith),
144 * and pure translation transformations. Other guarantees of similarity should be enforced by
145 * reducing which operations are tagged as mergeable.
146 */
147 virtual status_t multiDraw(OpenGLRenderer& renderer, Rect& dirty,
Chris Craikc1c5f082013-09-11 16:23:37 -0700148 const Vector<OpStatePair>& ops, const Rect& bounds) {
Chris Craik527a3aa2013-03-04 10:19:31 -0800149 status_t status = DrawGlInfo::kStatusDone;
150 for (unsigned int i = 0; i < ops.size(); i++) {
Chris Craikc1c5f082013-09-11 16:23:37 -0700151 renderer.restoreDisplayState(*(ops[i].state), true);
152 status |= ops[i].op->applyDraw(renderer, dirty);
Chris Craik527a3aa2013-03-04 10:19:31 -0800153 }
154 return status;
155 }
156
Chris Craik28ce94a2013-05-31 11:38:03 -0700157 /**
Chris Craik527a3aa2013-03-04 10:19:31 -0800158 * When this method is invoked the state field is initialized to have the
159 * final rendering state. We can thus use it to process data as it will be
160 * used at draw time.
161 *
162 * Additionally, this method allows subclasses to provide defer-time preferences for batching
163 * and merging.
164 *
Chris Craik28ce94a2013-05-31 11:38:03 -0700165 * if a subclass can set deferInfo.mergeable to true, it should implement multiDraw()
Chris Craik527a3aa2013-03-04 10:19:31 -0800166 */
Chris Craikc1c5f082013-09-11 16:23:37 -0700167 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
168 const DeferredDisplayState& state) {}
Romain Guy0f667532013-03-01 14:31:04 -0800169
Chris Craik5e49b302013-07-30 19:05:20 -0700170 /**
171 * Query the conservative, local bounds (unmapped) bounds of the op.
172 *
173 * returns true if bounds exist
174 */
John Reck3b202512014-06-23 13:13:08 -0700175 virtual bool getLocalBounds(Rect& localBounds) {
Chris Craikc1c5f082013-09-11 16:23:37 -0700176 return false;
177 }
Chris Craik2af46352012-11-26 18:30:17 -0800178
179 // TODO: better refine localbounds usage
180 void setQuickRejected(bool quickRejected) { mQuickRejected = quickRejected; }
181 bool getQuickRejected() { return mQuickRejected; }
182
Chris Craikc1c5f082013-09-11 16:23:37 -0700183 inline int getPaintAlpha() const {
Chris Craik527a3aa2013-03-04 10:19:31 -0800184 return OpenGLRenderer::getAlphaDirect(mPaint);
Chris Craikc3566d02013-02-04 16:16:33 -0800185 }
186
Derek Sollenbergerc29a0a42014-03-31 13:52:39 -0400187 virtual bool hasTextShadow() const {
188 return false;
189 }
190
Chris Craik527a3aa2013-03-04 10:19:31 -0800191 inline float strokeWidthOutset() {
Chris Craikf0a59072013-11-19 18:00:46 -0800192 // since anything AA stroke with less than 1.0 pixel width is drawn with an alpha-reduced
193 // 1.0 stroke, treat 1.0 as minimum.
194
195 // TODO: it would be nice if this could take scale into account, but scale isn't stable
196 // since higher levels of the view hierarchy can change scale out from underneath it.
197 return fmaxf(mPaint->getStrokeWidth(), 1) * 0.5f;
Chris Craike7c69c62013-04-03 09:55:48 -0700198 }
Chris Craikc3566d02013-02-04 16:16:33 -0800199
Chris Craik2af46352012-11-26 18:30:17 -0800200protected:
Chris Craikd218a922014-01-02 17:13:34 -0800201 const SkPaint* getPaint(OpenGLRenderer& renderer) {
Chris Craika08f95c2013-03-15 17:24:33 -0700202 return renderer.filterPaint(mPaint);
Chris Craik2af46352012-11-26 18:30:17 -0800203 }
204
Chris Craik28ce94a2013-05-31 11:38:03 -0700205 // Helper method for determining op opaqueness. Assumes op fills its bounds in local
206 // coordinates, and that paint's alpha is used
Chris Craikc1c5f082013-09-11 16:23:37 -0700207 inline bool isOpaqueOverBounds(const DeferredDisplayState& state) {
Chris Craik28ce94a2013-05-31 11:38:03 -0700208 // ensure that local bounds cover mapped bounds
209 if (!state.mMatrix.isSimple()) return false;
210
Chris Craik2262abb2014-08-18 19:55:36 -0700211 if (state.mRoundRectClipState) return false;
212
Chris Craik28ce94a2013-05-31 11:38:03 -0700213 // check state/paint for transparency
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400214 if (mPaint) {
215 if (mPaint->getShader() && !mPaint->getShader()->isOpaque()) {
216 return false;
217 }
218 if (mPaint->getAlpha() != 0xFF) {
219 return false;
220 }
221 }
222
223 if (state.mAlpha != 1.0f) return false;
Chris Craik28ce94a2013-05-31 11:38:03 -0700224
225 SkXfermode::Mode mode = OpenGLRenderer::getXfermodeDirect(mPaint);
226 return (mode == SkXfermode::kSrcOver_Mode ||
227 mode == SkXfermode::kSrc_Mode);
228
229 }
230
Chris Craikd218a922014-01-02 17:13:34 -0800231 const SkPaint* mPaint; // should be accessed via getPaint() when applying
Chris Craik2af46352012-11-26 18:30:17 -0800232 bool mQuickRejected;
233};
234
235class DrawBoundedOp : public DrawOp {
236public:
Chris Craikd218a922014-01-02 17:13:34 -0800237 DrawBoundedOp(float left, float top, float right, float bottom, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -0800238 : DrawOp(paint), mLocalBounds(left, top, right, bottom) {}
239
Chris Craikd218a922014-01-02 17:13:34 -0800240 DrawBoundedOp(const Rect& localBounds, const SkPaint* paint)
Chris Craik41541822013-05-03 16:35:54 -0700241 : DrawOp(paint), mLocalBounds(localBounds) {}
242
Chris Craik5d116762013-02-19 17:49:31 -0800243 // Calculates bounds as smallest rect encompassing all points
244 // NOTE: requires at least 1 vertex, and doesn't account for stroke size (should be handled in
245 // subclass' constructor)
Chris Craikd218a922014-01-02 17:13:34 -0800246 DrawBoundedOp(const float* points, int count, const SkPaint* paint)
Chris Craik5d116762013-02-19 17:49:31 -0800247 : DrawOp(paint), mLocalBounds(points[0], points[1], points[0], points[1]) {
248 for (int i = 2; i < count; i += 2) {
249 mLocalBounds.left = fminf(mLocalBounds.left, points[i]);
250 mLocalBounds.right = fmaxf(mLocalBounds.right, points[i]);
251 mLocalBounds.top = fminf(mLocalBounds.top, points[i + 1]);
252 mLocalBounds.bottom = fmaxf(mLocalBounds.bottom, points[i + 1]);
253 }
254 }
255
256 // default empty constructor for bounds, to be overridden in child constructor body
Chris Craikd218a922014-01-02 17:13:34 -0800257 DrawBoundedOp(const SkPaint* paint): DrawOp(paint) { }
Chris Craik2af46352012-11-26 18:30:17 -0800258
John Reckca1b3b82014-06-27 07:21:36 -0700259 virtual bool getLocalBounds(Rect& localBounds) {
Chris Craik2af46352012-11-26 18:30:17 -0800260 localBounds.set(mLocalBounds);
Derek Sollenbergerc29a0a42014-03-31 13:52:39 -0400261 OpenGLRenderer::TextShadow textShadow;
262 if (OpenGLRenderer::getTextShadow(mPaint, &textShadow)) {
Romain Guy9b5a1a22013-08-09 14:06:29 -0700263 Rect shadow(mLocalBounds);
Derek Sollenbergerc29a0a42014-03-31 13:52:39 -0400264 shadow.translate(textShadow.dx, textShadow.dx);
265 shadow.outset(textShadow.radius);
Romain Guy9b5a1a22013-08-09 14:06:29 -0700266 localBounds.unionWith(shadow);
267 }
Chris Craik2af46352012-11-26 18:30:17 -0800268 return true;
269 }
270
271protected:
272 Rect mLocalBounds; // displayed area in LOCAL coord. doesn't incorporate stroke, so check paint
273};
274
275///////////////////////////////////////////////////////////////////////////////
276// STATE OPERATIONS - these may affect the state of the canvas/renderer, but do
277// not directly draw or alter output
278///////////////////////////////////////////////////////////////////////////////
279
280class SaveOp : public StateOp {
281public:
282 SaveOp(int flags)
283 : mFlags(flags) {}
284
Chet Haasedd671592013-04-19 14:54:34 -0700285 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
286 bool useQuickReject) {
Chris Craikff785832013-03-08 13:12:16 -0800287 int newSaveCount = deferStruct.mRenderer.save(mFlags);
288 deferStruct.mDeferredList.addSave(deferStruct.mRenderer, this, newSaveCount);
289 }
290
Chris Craik7273daa2013-03-28 11:25:24 -0700291 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800292 renderer.save(mFlags);
293 }
294
Chris Craikc5493fb2013-06-19 16:58:58 -0700295 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800296 OP_LOG("Save flags %x", mFlags);
297 }
298
299 virtual const char* name() { return "Save"; }
300
Chris Craikff785832013-03-08 13:12:16 -0800301 int getFlags() const { return mFlags; }
Chris Craik2af46352012-11-26 18:30:17 -0800302private:
303 int mFlags;
304};
305
306class RestoreToCountOp : public StateOp {
307public:
308 RestoreToCountOp(int count)
309 : mCount(count) {}
310
Chet Haasedd671592013-04-19 14:54:34 -0700311 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
312 bool useQuickReject) {
Chris Craik7273daa2013-03-28 11:25:24 -0700313 deferStruct.mDeferredList.addRestoreToCount(deferStruct.mRenderer,
314 this, saveCount + mCount);
Chris Craikff785832013-03-08 13:12:16 -0800315 deferStruct.mRenderer.restoreToCount(saveCount + mCount);
Chris Craik2af46352012-11-26 18:30:17 -0800316 }
317
Chris Craik7273daa2013-03-28 11:25:24 -0700318 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craikff785832013-03-08 13:12:16 -0800319 renderer.restoreToCount(saveCount + mCount);
320 }
321
Chris Craikc5493fb2013-06-19 16:58:58 -0700322 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800323 OP_LOG("Restore to count %d", mCount);
324 }
325
326 virtual const char* name() { return "RestoreToCount"; }
327
328private:
329 int mCount;
330};
331
332class SaveLayerOp : public StateOp {
333public:
Derek Sollenbergerd44fbe52014-02-05 16:47:00 -0500334 SaveLayerOp(float left, float top, float right, float bottom, int alpha, int flags)
Chris Craik3f0854292014-04-15 16:18:08 -0700335 : mArea(left, top, right, bottom)
336 , mPaint(&mCachedPaint)
337 , mFlags(flags)
338 , mConvexMask(NULL) {
Derek Sollenbergerd44fbe52014-02-05 16:47:00 -0500339 mCachedPaint.setAlpha(alpha);
340 }
341
342 SaveLayerOp(float left, float top, float right, float bottom, const SkPaint* paint, int flags)
Chris Craik3f0854292014-04-15 16:18:08 -0700343 : mArea(left, top, right, bottom)
344 , mPaint(paint)
345 , mFlags(flags)
346 , mConvexMask(NULL)
347 {}
Chris Craikff785832013-03-08 13:12:16 -0800348
Chet Haasedd671592013-04-19 14:54:34 -0700349 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
350 bool useQuickReject) {
Chris Craikff785832013-03-08 13:12:16 -0800351 // NOTE: don't bother with actual saveLayer, instead issuing it at flush time
Chris Craikd90144d2013-03-19 15:03:48 -0700352 int newSaveCount = deferStruct.mRenderer.getSaveCount();
Chris Craikff785832013-03-08 13:12:16 -0800353 deferStruct.mDeferredList.addSaveLayer(deferStruct.mRenderer, this, newSaveCount);
Chris Craikd90144d2013-03-19 15:03:48 -0700354
355 // NOTE: don't issue full saveLayer, since that has side effects/is costly. instead just
356 // setup the snapshot for deferral, and re-issue the op at flush time
357 deferStruct.mRenderer.saveLayerDeferred(mArea.left, mArea.top, mArea.right, mArea.bottom,
Derek Sollenbergerd44fbe52014-02-05 16:47:00 -0500358 mPaint, mFlags);
Chris Craikff785832013-03-08 13:12:16 -0800359 }
Chris Craik2af46352012-11-26 18:30:17 -0800360
Chris Craik7273daa2013-03-28 11:25:24 -0700361 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik3f0854292014-04-15 16:18:08 -0700362 renderer.saveLayer(mArea.left, mArea.top, mArea.right, mArea.bottom,
363 mPaint, mFlags, mConvexMask);
Chris Craik2af46352012-11-26 18:30:17 -0800364 }
365
Chris Craikc5493fb2013-06-19 16:58:58 -0700366 virtual void output(int level, uint32_t logFlags) const {
Chris Craikff785832013-03-08 13:12:16 -0800367 OP_LOG("SaveLayer%s of area " RECT_STRING,
368 (isSaveLayerAlpha() ? "Alpha" : ""),RECT_ARGS(mArea));
Chris Craik2af46352012-11-26 18:30:17 -0800369 }
370
Chris Craikff785832013-03-08 13:12:16 -0800371 virtual const char* name() { return isSaveLayerAlpha() ? "SaveLayerAlpha" : "SaveLayer"; }
372
373 int getFlags() { return mFlags; }
Chris Craik2af46352012-11-26 18:30:17 -0800374
Chris Craik3f0854292014-04-15 16:18:08 -0700375 // Called to make SaveLayerOp clip to the provided mask when drawing back/restored
376 void setMask(const SkPath* convexMask) {
377 mConvexMask = convexMask;
378 }
379
Chris Craik2af46352012-11-26 18:30:17 -0800380private:
Derek Sollenbergerd44fbe52014-02-05 16:47:00 -0500381 bool isSaveLayerAlpha() const {
382 SkXfermode::Mode mode = OpenGLRenderer::getXfermodeDirect(mPaint);
383 int alpha = OpenGLRenderer::getAlphaDirect(mPaint);
384 return alpha < 255 && mode == SkXfermode::kSrcOver_Mode;
Chris Craik2af46352012-11-26 18:30:17 -0800385 }
386
Chris Craik2af46352012-11-26 18:30:17 -0800387 Rect mArea;
Derek Sollenbergerd44fbe52014-02-05 16:47:00 -0500388 const SkPaint* mPaint;
389 SkPaint mCachedPaint;
Chris Craik2af46352012-11-26 18:30:17 -0800390 int mFlags;
Chris Craik3f0854292014-04-15 16:18:08 -0700391
392 // Convex path, points at data in RenderNode, valid for the duration of the frame only
393 // Only used for masking the SaveLayer which wraps projected RenderNodes
394 const SkPath* mConvexMask;
Chris Craik2af46352012-11-26 18:30:17 -0800395};
396
397class TranslateOp : public StateOp {
398public:
399 TranslateOp(float dx, float dy)
400 : mDx(dx), mDy(dy) {}
401
Chris Craik7273daa2013-03-28 11:25:24 -0700402 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800403 renderer.translate(mDx, mDy);
404 }
405
Chris Craikc5493fb2013-06-19 16:58:58 -0700406 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800407 OP_LOG("Translate by %f %f", mDx, mDy);
408 }
409
410 virtual const char* name() { return "Translate"; }
411
412private:
413 float mDx;
414 float mDy;
415};
416
417class RotateOp : public StateOp {
418public:
419 RotateOp(float degrees)
420 : mDegrees(degrees) {}
421
Chris Craik7273daa2013-03-28 11:25:24 -0700422 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800423 renderer.rotate(mDegrees);
424 }
425
Chris Craikc5493fb2013-06-19 16:58:58 -0700426 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800427 OP_LOG("Rotate by %f degrees", mDegrees);
428 }
429
430 virtual const char* name() { return "Rotate"; }
431
432private:
433 float mDegrees;
434};
435
436class ScaleOp : public StateOp {
437public:
438 ScaleOp(float sx, float sy)
439 : mSx(sx), mSy(sy) {}
440
Chris Craik7273daa2013-03-28 11:25:24 -0700441 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800442 renderer.scale(mSx, mSy);
443 }
444
Chris Craikc5493fb2013-06-19 16:58:58 -0700445 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800446 OP_LOG("Scale by %f %f", mSx, mSy);
447 }
448
449 virtual const char* name() { return "Scale"; }
450
451private:
452 float mSx;
453 float mSy;
454};
455
456class SkewOp : public StateOp {
457public:
458 SkewOp(float sx, float sy)
459 : mSx(sx), mSy(sy) {}
460
Chris Craik7273daa2013-03-28 11:25:24 -0700461 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800462 renderer.skew(mSx, mSy);
463 }
464
Chris Craikc5493fb2013-06-19 16:58:58 -0700465 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800466 OP_LOG("Skew by %f %f", mSx, mSy);
467 }
468
469 virtual const char* name() { return "Skew"; }
470
471private:
472 float mSx;
473 float mSy;
474};
475
476class SetMatrixOp : public StateOp {
477public:
Derek Sollenberger13908822013-12-10 12:28:58 -0500478 SetMatrixOp(const SkMatrix& matrix)
Chris Craik2af46352012-11-26 18:30:17 -0800479 : mMatrix(matrix) {}
480
Chris Craik7273daa2013-03-28 11:25:24 -0700481 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800482 renderer.setMatrix(mMatrix);
483 }
484
Chris Craikc5493fb2013-06-19 16:58:58 -0700485 virtual void output(int level, uint32_t logFlags) const {
Derek Sollenberger13908822013-12-10 12:28:58 -0500486 if (mMatrix.isIdentity()) {
Romain Guy4e7b7722013-07-16 13:47:01 -0700487 OP_LOGS("SetMatrix (reset)");
Derek Sollenberger13908822013-12-10 12:28:58 -0500488 } else {
489 OP_LOG("SetMatrix " SK_MATRIX_STRING, SK_MATRIX_ARGS(&mMatrix));
Romain Guy4e7b7722013-07-16 13:47:01 -0700490 }
Chris Craik2af46352012-11-26 18:30:17 -0800491 }
492
493 virtual const char* name() { return "SetMatrix"; }
494
495private:
Derek Sollenberger13908822013-12-10 12:28:58 -0500496 const SkMatrix mMatrix;
Chris Craik2af46352012-11-26 18:30:17 -0800497};
498
499class ConcatMatrixOp : public StateOp {
500public:
Derek Sollenberger13908822013-12-10 12:28:58 -0500501 ConcatMatrixOp(const SkMatrix& matrix)
Chris Craik2af46352012-11-26 18:30:17 -0800502 : mMatrix(matrix) {}
503
Chris Craik7273daa2013-03-28 11:25:24 -0700504 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800505 renderer.concatMatrix(mMatrix);
506 }
507
Chris Craikc5493fb2013-06-19 16:58:58 -0700508 virtual void output(int level, uint32_t logFlags) const {
Derek Sollenberger13908822013-12-10 12:28:58 -0500509 OP_LOG("ConcatMatrix " SK_MATRIX_STRING, SK_MATRIX_ARGS(&mMatrix));
Chris Craik2af46352012-11-26 18:30:17 -0800510 }
511
512 virtual const char* name() { return "ConcatMatrix"; }
513
514private:
Derek Sollenberger13908822013-12-10 12:28:58 -0500515 const SkMatrix mMatrix;
Chris Craik2af46352012-11-26 18:30:17 -0800516};
517
Chris Craikff785832013-03-08 13:12:16 -0800518class ClipOp : public StateOp {
519public:
520 ClipOp(SkRegion::Op op) : mOp(op) {}
521
Chet Haasedd671592013-04-19 14:54:34 -0700522 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
523 bool useQuickReject) {
Chris Craikff785832013-03-08 13:12:16 -0800524 // NOTE: must defer op BEFORE applying state, since it may read clip
525 deferStruct.mDeferredList.addClip(deferStruct.mRenderer, this);
526
527 // TODO: Can we avoid applying complex clips at defer time?
528 applyState(deferStruct.mRenderer, saveCount);
529 }
530
531 bool canCauseComplexClip() {
532 return ((mOp != SkRegion::kIntersect_Op) && (mOp != SkRegion::kReplace_Op)) || !isRect();
533 }
534
535protected:
Chris Craikff785832013-03-08 13:12:16 -0800536 virtual bool isRect() { return false; }
537
538 SkRegion::Op mOp;
539};
540
541class ClipRectOp : public ClipOp {
Chris Craik2af46352012-11-26 18:30:17 -0800542public:
543 ClipRectOp(float left, float top, float right, float bottom, SkRegion::Op op)
Chris Craikff785832013-03-08 13:12:16 -0800544 : ClipOp(op), mArea(left, top, right, bottom) {}
Chris Craik2af46352012-11-26 18:30:17 -0800545
Chris Craik7273daa2013-03-28 11:25:24 -0700546 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800547 renderer.clipRect(mArea.left, mArea.top, mArea.right, mArea.bottom, mOp);
548 }
549
Chris Craikc5493fb2013-06-19 16:58:58 -0700550 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800551 OP_LOG("ClipRect " RECT_STRING, RECT_ARGS(mArea));
552 }
553
554 virtual const char* name() { return "ClipRect"; }
555
Chris Craikff785832013-03-08 13:12:16 -0800556protected:
557 virtual bool isRect() { return true; }
Chris Craikb98a0162013-02-21 11:30:22 -0800558
Chris Craik2af46352012-11-26 18:30:17 -0800559private:
560 Rect mArea;
Chris Craik2af46352012-11-26 18:30:17 -0800561};
562
Chris Craikff785832013-03-08 13:12:16 -0800563class ClipPathOp : public ClipOp {
Chris Craik2af46352012-11-26 18:30:17 -0800564public:
Chris Craikd218a922014-01-02 17:13:34 -0800565 ClipPathOp(const SkPath* path, SkRegion::Op op)
Chris Craikff785832013-03-08 13:12:16 -0800566 : ClipOp(op), mPath(path) {}
Chris Craik2af46352012-11-26 18:30:17 -0800567
Chris Craik7273daa2013-03-28 11:25:24 -0700568 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800569 renderer.clipPath(mPath, mOp);
570 }
571
Chris Craikc5493fb2013-06-19 16:58:58 -0700572 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800573 SkRect bounds = mPath->getBounds();
574 OP_LOG("ClipPath bounds " RECT_STRING,
575 bounds.left(), bounds.top(), bounds.right(), bounds.bottom());
576 }
577
578 virtual const char* name() { return "ClipPath"; }
579
580private:
Chris Craikd218a922014-01-02 17:13:34 -0800581 const SkPath* mPath;
Chris Craik2af46352012-11-26 18:30:17 -0800582};
583
Chris Craikff785832013-03-08 13:12:16 -0800584class ClipRegionOp : public ClipOp {
Chris Craik2af46352012-11-26 18:30:17 -0800585public:
Chris Craikd218a922014-01-02 17:13:34 -0800586 ClipRegionOp(const SkRegion* region, SkRegion::Op op)
Chris Craikff785832013-03-08 13:12:16 -0800587 : ClipOp(op), mRegion(region) {}
Chris Craik2af46352012-11-26 18:30:17 -0800588
Chris Craik7273daa2013-03-28 11:25:24 -0700589 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800590 renderer.clipRegion(mRegion, mOp);
591 }
592
Chris Craikc5493fb2013-06-19 16:58:58 -0700593 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800594 SkIRect bounds = mRegion->getBounds();
595 OP_LOG("ClipRegion bounds %d %d %d %d",
596 bounds.left(), bounds.top(), bounds.right(), bounds.bottom());
597 }
598
599 virtual const char* name() { return "ClipRegion"; }
600
601private:
Chris Craikd218a922014-01-02 17:13:34 -0800602 const SkRegion* mRegion;
Chris Craik2af46352012-11-26 18:30:17 -0800603};
604
Chris Craik2af46352012-11-26 18:30:17 -0800605class ResetPaintFilterOp : public StateOp {
606public:
Chris Craik7273daa2013-03-28 11:25:24 -0700607 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800608 renderer.resetPaintFilter();
609 }
610
Chris Craikc5493fb2013-06-19 16:58:58 -0700611 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800612 OP_LOGS("ResetPaintFilter");
613 }
614
615 virtual const char* name() { return "ResetPaintFilter"; }
616};
617
618class SetupPaintFilterOp : public StateOp {
619public:
620 SetupPaintFilterOp(int clearBits, int setBits)
621 : mClearBits(clearBits), mSetBits(setBits) {}
622
Chris Craik7273daa2013-03-28 11:25:24 -0700623 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800624 renderer.setupPaintFilter(mClearBits, mSetBits);
625 }
626
Chris Craikc5493fb2013-06-19 16:58:58 -0700627 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800628 OP_LOG("SetupPaintFilter, clear %#x, set %#x", mClearBits, mSetBits);
629 }
630
631 virtual const char* name() { return "SetupPaintFilter"; }
632
633private:
634 int mClearBits;
635 int mSetBits;
636};
637
Chris Craik2af46352012-11-26 18:30:17 -0800638///////////////////////////////////////////////////////////////////////////////
639// DRAW OPERATIONS - these are operations that can draw to the canvas's device
640///////////////////////////////////////////////////////////////////////////////
641
642class DrawBitmapOp : public DrawBoundedOp {
643public:
Chris Craik79647502014-08-06 13:42:24 -0700644 DrawBitmapOp(const SkBitmap* bitmap, const SkPaint* paint)
645 : DrawBoundedOp(0, 0, bitmap->width(), bitmap->height(), paint)
646 , mBitmap(bitmap)
647 , mAtlas(Caches::getInstance().assetAtlas) {
Romain Guy55b6f952013-06-27 15:27:09 -0700648 mEntry = mAtlas.getEntry(bitmap);
649 if (mEntry) {
650 mEntryGenerationId = mAtlas.getGenerationId();
651 mUvMapper = mEntry->uvMapper;
652 }
Romain Guy3b748a42013-04-17 18:54:38 -0700653 }
Chris Craik2af46352012-11-26 18:30:17 -0800654
Chris Craik527a3aa2013-03-04 10:19:31 -0800655 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik79647502014-08-06 13:42:24 -0700656 return renderer.drawBitmap(mBitmap, getPaint(renderer));
Chris Craik2af46352012-11-26 18:30:17 -0800657 }
658
Romain Guy55b6f952013-06-27 15:27:09 -0700659 AssetAtlas::Entry* getAtlasEntry() {
660 // The atlas entry is stale, let's get a new one
661 if (mEntry && mEntryGenerationId != mAtlas.getGenerationId()) {
662 mEntryGenerationId = mAtlas.getGenerationId();
663 mEntry = mAtlas.getEntry(mBitmap);
664 mUvMapper = mEntry->uvMapper;
665 }
666 return mEntry;
667 }
668
Chris Craik527a3aa2013-03-04 10:19:31 -0800669#define SET_TEXTURE(ptr, posRect, offsetRect, texCoordsRect, xDim, yDim) \
670 TextureVertex::set(ptr++, posRect.xDim - offsetRect.left, posRect.yDim - offsetRect.top, \
671 texCoordsRect.xDim, texCoordsRect.yDim)
672
Romain Guy03c00b52013-06-20 18:30:28 -0700673 /**
674 * This multi-draw operation builds a mesh on the stack by generating a quad
675 * for each bitmap in the batch. This method is also responsible for dirtying
676 * the current layer, if any.
677 */
Chris Craik527a3aa2013-03-04 10:19:31 -0800678 virtual status_t multiDraw(OpenGLRenderer& renderer, Rect& dirty,
Chris Craikc1c5f082013-09-11 16:23:37 -0700679 const Vector<OpStatePair>& ops, const Rect& bounds) {
680 const DeferredDisplayState& firstState = *(ops[0].state);
681 renderer.restoreDisplayState(firstState, true); // restore all but the clip
682
Chris Craik527a3aa2013-03-04 10:19:31 -0800683 TextureVertex vertices[6 * ops.size()];
684 TextureVertex* vertex = &vertices[0];
685
Romain Guy03c00b52013-06-20 18:30:28 -0700686 const bool hasLayer = renderer.hasLayer();
Chris Craik996fe652013-09-20 17:13:18 -0700687 bool pureTranslate = true;
Romain Guy2db5e992013-05-21 15:29:59 -0700688
Romain Guy3b748a42013-04-17 18:54:38 -0700689 // TODO: manually handle rect clip for bitmaps by adjusting texCoords per op,
690 // and allowing them to be merged in getBatchId()
Chris Craik527a3aa2013-03-04 10:19:31 -0800691 for (unsigned int i = 0; i < ops.size(); i++) {
Chris Craikc1c5f082013-09-11 16:23:37 -0700692 const DeferredDisplayState& state = *(ops[i].state);
693 const Rect& opBounds = state.mBounds;
Romain Guy2db5e992013-05-21 15:29:59 -0700694 // When we reach multiDraw(), the matrix can be either
695 // pureTranslate or simple (translate and/or scale).
696 // If the matrix is not pureTranslate, then we have a scale
Chris Craik996fe652013-09-20 17:13:18 -0700697 pureTranslate &= state.mMatrix.isPureTranslate();
Romain Guy3b748a42013-04-17 18:54:38 -0700698
699 Rect texCoords(0, 0, 1, 1);
Chris Craikc1c5f082013-09-11 16:23:37 -0700700 ((DrawBitmapOp*) ops[i].op)->mUvMapper.map(texCoords);
Romain Guy3b748a42013-04-17 18:54:38 -0700701
Chris Craik527a3aa2013-03-04 10:19:31 -0800702 SET_TEXTURE(vertex, opBounds, bounds, texCoords, left, top);
703 SET_TEXTURE(vertex, opBounds, bounds, texCoords, right, top);
704 SET_TEXTURE(vertex, opBounds, bounds, texCoords, left, bottom);
705
706 SET_TEXTURE(vertex, opBounds, bounds, texCoords, left, bottom);
707 SET_TEXTURE(vertex, opBounds, bounds, texCoords, right, top);
708 SET_TEXTURE(vertex, opBounds, bounds, texCoords, right, bottom);
Romain Guy03c00b52013-06-20 18:30:28 -0700709
710 if (hasLayer) {
Chris Craikc1c5f082013-09-11 16:23:37 -0700711 renderer.dirtyLayer(opBounds.left, opBounds.top, opBounds.right, opBounds.bottom);
Romain Guy03c00b52013-06-20 18:30:28 -0700712 }
Chris Craik527a3aa2013-03-04 10:19:31 -0800713 }
714
Romain Guy55b6f952013-06-27 15:27:09 -0700715 return renderer.drawBitmaps(mBitmap, mEntry, ops.size(), &vertices[0],
Chris Craik996fe652013-09-20 17:13:18 -0700716 pureTranslate, bounds, mPaint);
Chris Craik527a3aa2013-03-04 10:19:31 -0800717 }
718
Chris Craikc5493fb2013-06-19 16:58:58 -0700719 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800720 OP_LOG("Draw bitmap %p at %f %f", mBitmap, mLocalBounds.left, mLocalBounds.top);
721 }
722
723 virtual const char* name() { return "DrawBitmap"; }
Chris Craik527a3aa2013-03-04 10:19:31 -0800724
Chris Craikc1c5f082013-09-11 16:23:37 -0700725 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
726 const DeferredDisplayState& state) {
Chris Craik28ce94a2013-05-31 11:38:03 -0700727 deferInfo.batchId = DeferredDisplayList::kOpBatch_Bitmap;
Chris Craikd965bc52013-09-16 14:47:13 -0700728 deferInfo.mergeId = getAtlasEntry() ?
729 (mergeid_t) mEntry->getMergeId() : (mergeid_t) mBitmap;
Romain Guy2db5e992013-05-21 15:29:59 -0700730
Chris Craikd965bc52013-09-16 14:47:13 -0700731 // Don't merge non-simply transformed or neg scale ops, SET_TEXTURE doesn't handle rotation
Chris Craik28ce94a2013-05-31 11:38:03 -0700732 // Don't merge A8 bitmaps - the paint's color isn't compared by mergeId, or in
733 // MergingDrawBatch::canMergeWith()
734 // TODO: support clipped bitmaps by handling them in SET_TEXTURE
Chris Craikd965bc52013-09-16 14:47:13 -0700735 deferInfo.mergeable = state.mMatrix.isSimple() && state.mMatrix.positiveScale() &&
736 !state.mClipSideFlags &&
Chris Craik28ce94a2013-05-31 11:38:03 -0700737 OpenGLRenderer::getXfermodeDirect(mPaint) == SkXfermode::kSrcOver_Mode &&
Mike Reed1103b322014-07-08 12:36:44 -0400738 (mBitmap->colorType() != kAlpha_8_SkColorType);
Chris Craikc3566d02013-02-04 16:16:33 -0800739 }
Chris Craik2af46352012-11-26 18:30:17 -0800740
Chris Craik527a3aa2013-03-04 10:19:31 -0800741 const SkBitmap* bitmap() { return mBitmap; }
Chris Craik2af46352012-11-26 18:30:17 -0800742protected:
Chris Craikd218a922014-01-02 17:13:34 -0800743 const SkBitmap* mBitmap;
Romain Guy55b6f952013-06-27 15:27:09 -0700744 const AssetAtlas& mAtlas;
745 uint32_t mEntryGenerationId;
746 AssetAtlas::Entry* mEntry;
Romain Guy3b748a42013-04-17 18:54:38 -0700747 UvMapper mUvMapper;
Chris Craik2af46352012-11-26 18:30:17 -0800748};
749
Chris Craik2af46352012-11-26 18:30:17 -0800750class DrawBitmapRectOp : public DrawBoundedOp {
751public:
Chris Craikd218a922014-01-02 17:13:34 -0800752 DrawBitmapRectOp(const SkBitmap* bitmap,
753 float srcLeft, float srcTop, float srcRight, float srcBottom,
754 float dstLeft, float dstTop, float dstRight, float dstBottom, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -0800755 : DrawBoundedOp(dstLeft, dstTop, dstRight, dstBottom, paint),
756 mBitmap(bitmap), mSrc(srcLeft, srcTop, srcRight, srcBottom) {}
757
Chris Craik527a3aa2013-03-04 10:19:31 -0800758 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -0800759 return renderer.drawBitmap(mBitmap, mSrc.left, mSrc.top, mSrc.right, mSrc.bottom,
760 mLocalBounds.left, mLocalBounds.top, mLocalBounds.right, mLocalBounds.bottom,
761 getPaint(renderer));
762 }
763
Chris Craikc5493fb2013-06-19 16:58:58 -0700764 virtual void output(int level, uint32_t logFlags) const {
John Reckce444ca2014-06-02 15:12:36 -0700765 OP_LOG("Draw bitmap %p src=" RECT_STRING ", dst=" RECT_STRING,
Chris Craik2af46352012-11-26 18:30:17 -0800766 mBitmap, RECT_ARGS(mSrc), RECT_ARGS(mLocalBounds));
767 }
768
769 virtual const char* name() { return "DrawBitmapRect"; }
Chris Craik527a3aa2013-03-04 10:19:31 -0800770
Chris Craikc1c5f082013-09-11 16:23:37 -0700771 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
772 const DeferredDisplayState& state) {
Chris Craik28ce94a2013-05-31 11:38:03 -0700773 deferInfo.batchId = DeferredDisplayList::kOpBatch_Bitmap;
Chris Craikc3566d02013-02-04 16:16:33 -0800774 }
Chris Craik2af46352012-11-26 18:30:17 -0800775
776private:
Chris Craikd218a922014-01-02 17:13:34 -0800777 const SkBitmap* mBitmap;
Chris Craik2af46352012-11-26 18:30:17 -0800778 Rect mSrc;
779};
780
781class DrawBitmapDataOp : public DrawBitmapOp {
782public:
Chris Craik79647502014-08-06 13:42:24 -0700783 DrawBitmapDataOp(const SkBitmap* bitmap, const SkPaint* paint)
784 : DrawBitmapOp(bitmap, paint) {}
Chris Craik2af46352012-11-26 18:30:17 -0800785
Chris Craik527a3aa2013-03-04 10:19:31 -0800786 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik79647502014-08-06 13:42:24 -0700787 return renderer.drawBitmapData(mBitmap, getPaint(renderer));
Chris Craik2af46352012-11-26 18:30:17 -0800788 }
789
Chris Craikc5493fb2013-06-19 16:58:58 -0700790 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800791 OP_LOG("Draw bitmap %p", mBitmap);
792 }
793
794 virtual const char* name() { return "DrawBitmapData"; }
Chris Craik527a3aa2013-03-04 10:19:31 -0800795
Chris Craikc1c5f082013-09-11 16:23:37 -0700796 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
797 const DeferredDisplayState& state) {
Chris Craik28ce94a2013-05-31 11:38:03 -0700798 deferInfo.batchId = DeferredDisplayList::kOpBatch_Bitmap;
Chris Craikc3566d02013-02-04 16:16:33 -0800799 }
Chris Craik2af46352012-11-26 18:30:17 -0800800};
801
Chris Craik5d116762013-02-19 17:49:31 -0800802class DrawBitmapMeshOp : public DrawBoundedOp {
Chris Craik2af46352012-11-26 18:30:17 -0800803public:
Chris Craikd218a922014-01-02 17:13:34 -0800804 DrawBitmapMeshOp(const SkBitmap* bitmap, int meshWidth, int meshHeight,
805 const float* vertices, const int* colors, const SkPaint* paint)
Chris Craik5d116762013-02-19 17:49:31 -0800806 : DrawBoundedOp(vertices, 2 * (meshWidth + 1) * (meshHeight + 1), paint),
807 mBitmap(bitmap), mMeshWidth(meshWidth), mMeshHeight(meshHeight),
Chris Craik2af46352012-11-26 18:30:17 -0800808 mVertices(vertices), mColors(colors) {}
809
Chris Craik527a3aa2013-03-04 10:19:31 -0800810 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -0800811 return renderer.drawBitmapMesh(mBitmap, mMeshWidth, mMeshHeight,
812 mVertices, mColors, getPaint(renderer));
813 }
814
Chris Craikc5493fb2013-06-19 16:58:58 -0700815 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800816 OP_LOG("Draw bitmap %p mesh %d x %d", mBitmap, mMeshWidth, mMeshHeight);
817 }
818
819 virtual const char* name() { return "DrawBitmapMesh"; }
Chris Craik527a3aa2013-03-04 10:19:31 -0800820
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;
Chris Craik2af46352012-11-26 18:30:17 -0800828 int mMeshWidth;
829 int mMeshHeight;
Chris Craikd218a922014-01-02 17:13:34 -0800830 const float* mVertices;
831 const int* mColors;
Chris Craik2af46352012-11-26 18:30:17 -0800832};
833
834class DrawPatchOp : public DrawBoundedOp {
835public:
Chris Craikd218a922014-01-02 17:13:34 -0800836 DrawPatchOp(const SkBitmap* bitmap, const Res_png_9patch* patch,
837 float left, float top, float right, float bottom, const SkPaint* paint)
Romain Guy03c00b52013-06-20 18:30:28 -0700838 : DrawBoundedOp(left, top, right, bottom, paint),
Romain Guy55b6f952013-06-27 15:27:09 -0700839 mBitmap(bitmap), mPatch(patch), mGenerationId(0), mMesh(NULL),
840 mAtlas(Caches::getInstance().assetAtlas) {
841 mEntry = mAtlas.getEntry(bitmap);
842 if (mEntry) {
843 mEntryGenerationId = mAtlas.getGenerationId();
844 }
Romain Guy3b748a42013-04-17 18:54:38 -0700845 };
Chris Craik2af46352012-11-26 18:30:17 -0800846
Romain Guy55b6f952013-06-27 15:27:09 -0700847 AssetAtlas::Entry* getAtlasEntry() {
848 // The atlas entry is stale, let's get a new one
849 if (mEntry && mEntryGenerationId != mAtlas.getGenerationId()) {
850 mEntryGenerationId = mAtlas.getGenerationId();
851 mEntry = mAtlas.getEntry(mBitmap);
852 }
853 return mEntry;
854 }
855
Romain Guy03c00b52013-06-20 18:30:28 -0700856 const Patch* getMesh(OpenGLRenderer& renderer) {
Romain Guy4c2547f2013-06-11 16:19:24 -0700857 if (!mMesh || renderer.getCaches().patchCache.getGenerationId() != mGenerationId) {
858 PatchCache& cache = renderer.getCaches().patchCache;
Romain Guy55b6f952013-06-27 15:27:09 -0700859 mMesh = cache.get(getAtlasEntry(), mBitmap->width(), mBitmap->height(),
Romain Guy03c00b52013-06-20 18:30:28 -0700860 mLocalBounds.getWidth(), mLocalBounds.getHeight(), mPatch);
Romain Guy4c2547f2013-06-11 16:19:24 -0700861 mGenerationId = cache.getGenerationId();
862 }
Romain Guy03c00b52013-06-20 18:30:28 -0700863 return mMesh;
864 }
865
866 /**
867 * This multi-draw operation builds an indexed mesh on the stack by copying
868 * and transforming the vertices of each 9-patch in the batch. This method
869 * is also responsible for dirtying the current layer, if any.
870 */
871 virtual status_t multiDraw(OpenGLRenderer& renderer, Rect& dirty,
Chris Craikc1c5f082013-09-11 16:23:37 -0700872 const Vector<OpStatePair>& ops, const Rect& bounds) {
873 const DeferredDisplayState& firstState = *(ops[0].state);
874 renderer.restoreDisplayState(firstState, true); // restore all but the clip
Romain Guy03c00b52013-06-20 18:30:28 -0700875
876 // Batches will usually contain a small number of items so it's
877 // worth performing a first iteration to count the exact number
878 // of vertices we need in the new mesh
879 uint32_t totalVertices = 0;
880 for (unsigned int i = 0; i < ops.size(); i++) {
Chris Craikc1c5f082013-09-11 16:23:37 -0700881 totalVertices += ((DrawPatchOp*) ops[i].op)->getMesh(renderer)->verticesCount;
Romain Guy03c00b52013-06-20 18:30:28 -0700882 }
883
884 const bool hasLayer = renderer.hasLayer();
885
886 uint32_t indexCount = 0;
887
888 TextureVertex vertices[totalVertices];
889 TextureVertex* vertex = &vertices[0];
890
891 // Create a mesh that contains the transformed vertices for all the
892 // 9-patch objects that are part of the batch. Note that onDefer()
893 // enforces ops drawn by this function to have a pure translate or
894 // identity matrix
895 for (unsigned int i = 0; i < ops.size(); i++) {
Chris Craikc1c5f082013-09-11 16:23:37 -0700896 DrawPatchOp* patchOp = (DrawPatchOp*) ops[i].op;
897 const DeferredDisplayState* state = ops[i].state;
Romain Guy03c00b52013-06-20 18:30:28 -0700898 const Patch* opMesh = patchOp->getMesh(renderer);
899 uint32_t vertexCount = opMesh->verticesCount;
900 if (vertexCount == 0) continue;
901
902 // We use the bounds to know where to translate our vertices
903 // Using patchOp->state.mBounds wouldn't work because these
904 // bounds are clipped
Chris Craikc1c5f082013-09-11 16:23:37 -0700905 const float tx = (int) floorf(state->mMatrix.getTranslateX() +
Romain Guy03c00b52013-06-20 18:30:28 -0700906 patchOp->mLocalBounds.left + 0.5f);
Chris Craikc1c5f082013-09-11 16:23:37 -0700907 const float ty = (int) floorf(state->mMatrix.getTranslateY() +
Romain Guy03c00b52013-06-20 18:30:28 -0700908 patchOp->mLocalBounds.top + 0.5f);
909
910 // Copy & transform all the vertices for the current operation
911 TextureVertex* opVertices = opMesh->vertices;
912 for (uint32_t j = 0; j < vertexCount; j++, opVertices++) {
913 TextureVertex::set(vertex++,
Romain Guy3380cfd2013-08-15 16:57:57 -0700914 opVertices->x + tx, opVertices->y + ty,
915 opVertices->u, opVertices->v);
Romain Guy03c00b52013-06-20 18:30:28 -0700916 }
917
918 // Dirty the current layer if possible. When the 9-patch does not
919 // contain empty quads we can take a shortcut and simply set the
920 // dirty rect to the object's bounds.
921 if (hasLayer) {
922 if (!opMesh->hasEmptyQuads) {
923 renderer.dirtyLayer(tx, ty,
924 tx + patchOp->mLocalBounds.getWidth(),
925 ty + patchOp->mLocalBounds.getHeight());
926 } else {
927 const size_t count = opMesh->quads.size();
928 for (size_t i = 0; i < count; i++) {
929 const Rect& quadBounds = opMesh->quads[i];
930 const float x = tx + quadBounds.left;
931 const float y = ty + quadBounds.top;
932 renderer.dirtyLayer(x, y,
933 x + quadBounds.getWidth(), y + quadBounds.getHeight());
934 }
935 }
936 }
937
938 indexCount += opMesh->indexCount;
939 }
940
Romain Guy55b6f952013-06-27 15:27:09 -0700941 return renderer.drawPatches(mBitmap, getAtlasEntry(),
942 &vertices[0], indexCount, getPaint(renderer));
Romain Guy03c00b52013-06-20 18:30:28 -0700943 }
944
945 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Romain Guy4c2547f2013-06-11 16:19:24 -0700946 // We're not calling the public variant of drawPatch() here
947 // This method won't perform the quickReject() since we've already done it at this point
Romain Guy55b6f952013-06-27 15:27:09 -0700948 return renderer.drawPatch(mBitmap, getMesh(renderer), getAtlasEntry(),
Romain Guy03c00b52013-06-20 18:30:28 -0700949 mLocalBounds.left, mLocalBounds.top, mLocalBounds.right, mLocalBounds.bottom,
950 getPaint(renderer));
Chris Craik2af46352012-11-26 18:30:17 -0800951 }
952
Chris Craikc5493fb2013-06-19 16:58:58 -0700953 virtual void output(int level, uint32_t logFlags) const {
John Reckce444ca2014-06-02 15:12:36 -0700954 OP_LOG("Draw patch " RECT_STRING, RECT_ARGS(mLocalBounds));
Chris Craik2af46352012-11-26 18:30:17 -0800955 }
956
957 virtual const char* name() { return "DrawPatch"; }
Chris Craik527a3aa2013-03-04 10:19:31 -0800958
Chris Craikc1c5f082013-09-11 16:23:37 -0700959 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
960 const DeferredDisplayState& state) {
Chris Craik28ce94a2013-05-31 11:38:03 -0700961 deferInfo.batchId = DeferredDisplayList::kOpBatch_Patch;
Romain Guy7f6d6b02013-08-06 13:49:28 -0700962 deferInfo.mergeId = getAtlasEntry() ? (mergeid_t) mEntry->getMergeId() : (mergeid_t) mBitmap;
Romain Guy03c00b52013-06-20 18:30:28 -0700963 deferInfo.mergeable = state.mMatrix.isPureTranslate() &&
964 OpenGLRenderer::getXfermodeDirect(mPaint) == SkXfermode::kSrcOver_Mode;
Chris Craikc1c5f082013-09-11 16:23:37 -0700965 deferInfo.opaqueOverBounds = isOpaqueOverBounds(state) && mBitmap->isOpaque();
Chris Craikc3566d02013-02-04 16:16:33 -0800966 }
Chris Craik2af46352012-11-26 18:30:17 -0800967
968private:
Chris Craikd218a922014-01-02 17:13:34 -0800969 const SkBitmap* mBitmap;
970 const Res_png_9patch* mPatch;
Romain Guy4c2547f2013-06-11 16:19:24 -0700971
Romain Guy4c2547f2013-06-11 16:19:24 -0700972 uint32_t mGenerationId;
973 const Patch* mMesh;
Romain Guy03c00b52013-06-20 18:30:28 -0700974
Romain Guy55b6f952013-06-27 15:27:09 -0700975 const AssetAtlas& mAtlas;
976 uint32_t mEntryGenerationId;
Romain Guy3b748a42013-04-17 18:54:38 -0700977 AssetAtlas::Entry* mEntry;
Chris Craik2af46352012-11-26 18:30:17 -0800978};
979
980class DrawColorOp : public DrawOp {
981public:
982 DrawColorOp(int color, SkXfermode::Mode mode)
Chris Craikf57776b2013-10-25 18:30:17 -0700983 : DrawOp(NULL), mColor(color), mMode(mode) {};
Chris Craik2af46352012-11-26 18:30:17 -0800984
Chris Craik527a3aa2013-03-04 10:19:31 -0800985 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -0800986 return renderer.drawColor(mColor, mMode);
987 }
988
Chris Craikc5493fb2013-06-19 16:58:58 -0700989 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800990 OP_LOG("Draw color %#x, mode %d", mColor, mMode);
991 }
992
993 virtual const char* name() { return "DrawColor"; }
994
995private:
996 int mColor;
997 SkXfermode::Mode mMode;
998};
999
1000class DrawStrokableOp : public DrawBoundedOp {
1001public:
Chris Craikd218a922014-01-02 17:13:34 -08001002 DrawStrokableOp(float left, float top, float right, float bottom, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001003 : DrawBoundedOp(left, top, right, bottom, paint) {};
Chris Craik947eabf2014-08-19 10:21:12 -07001004 DrawStrokableOp(const Rect& localBounds, const SkPaint* paint)
1005 : DrawBoundedOp(localBounds, paint) {};
Chris Craik2af46352012-11-26 18:30:17 -08001006
John Reckca1b3b82014-06-27 07:21:36 -07001007 virtual bool getLocalBounds(Rect& localBounds) {
Chris Craikc3566d02013-02-04 16:16:33 -08001008 localBounds.set(mLocalBounds);
Chris Craik2af46352012-11-26 18:30:17 -08001009 if (mPaint && mPaint->getStyle() != SkPaint::kFill_Style) {
Chris Craikc3566d02013-02-04 16:16:33 -08001010 localBounds.outset(strokeWidthOutset());
Chris Craik2af46352012-11-26 18:30:17 -08001011 }
1012 return true;
1013 }
Chris Craikc3566d02013-02-04 16:16:33 -08001014
Chris Craikc1c5f082013-09-11 16:23:37 -07001015 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
1016 const DeferredDisplayState& state) {
Chris Craikc3566d02013-02-04 16:16:33 -08001017 if (mPaint->getPathEffect()) {
Chris Craik28ce94a2013-05-31 11:38:03 -07001018 deferInfo.batchId = DeferredDisplayList::kOpBatch_AlphaMaskTexture;
Chris Craik527a3aa2013-03-04 10:19:31 -08001019 } else {
Chris Craik28ce94a2013-05-31 11:38:03 -07001020 deferInfo.batchId = mPaint->isAntiAlias() ?
Chris Craik527a3aa2013-03-04 10:19:31 -08001021 DeferredDisplayList::kOpBatch_AlphaVertices :
1022 DeferredDisplayList::kOpBatch_Vertices;
Chris Craikc3566d02013-02-04 16:16:33 -08001023 }
Chris Craikc3566d02013-02-04 16:16:33 -08001024 }
Chris Craik2af46352012-11-26 18:30:17 -08001025};
1026
1027class DrawRectOp : public DrawStrokableOp {
1028public:
Chris Craikd218a922014-01-02 17:13:34 -08001029 DrawRectOp(float left, float top, float right, float bottom, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001030 : DrawStrokableOp(left, top, right, bottom, paint) {}
1031
Chris Craik527a3aa2013-03-04 10:19:31 -08001032 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001033 return renderer.drawRect(mLocalBounds.left, mLocalBounds.top,
1034 mLocalBounds.right, mLocalBounds.bottom, getPaint(renderer));
1035 }
1036
Chris Craikc5493fb2013-06-19 16:58:58 -07001037 virtual void output(int level, uint32_t logFlags) const {
John Reckce444ca2014-06-02 15:12:36 -07001038 OP_LOG("Draw Rect " RECT_STRING, RECT_ARGS(mLocalBounds));
Chris Craik2af46352012-11-26 18:30:17 -08001039 }
1040
Chris Craikc1c5f082013-09-11 16:23:37 -07001041 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
1042 const DeferredDisplayState& state) {
1043 DrawStrokableOp::onDefer(renderer, deferInfo, state);
1044 deferInfo.opaqueOverBounds = isOpaqueOverBounds(state) &&
Chris Craik28ce94a2013-05-31 11:38:03 -07001045 mPaint->getStyle() == SkPaint::kFill_Style;
1046 }
1047
Chris Craik2af46352012-11-26 18:30:17 -08001048 virtual const char* name() { return "DrawRect"; }
1049};
1050
Chris Craik5d116762013-02-19 17:49:31 -08001051class DrawRectsOp : public DrawBoundedOp {
Chris Craik2af46352012-11-26 18:30:17 -08001052public:
Chris Craikd218a922014-01-02 17:13:34 -08001053 DrawRectsOp(const float* rects, int count, const SkPaint* paint)
Chris Craik5d116762013-02-19 17:49:31 -08001054 : DrawBoundedOp(rects, count, paint),
1055 mRects(rects), mCount(count) {}
Chris Craik2af46352012-11-26 18:30:17 -08001056
Chris Craik527a3aa2013-03-04 10:19:31 -08001057 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001058 return renderer.drawRects(mRects, mCount, getPaint(renderer));
1059 }
1060
Chris Craikc5493fb2013-06-19 16:58:58 -07001061 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001062 OP_LOG("Draw Rects count %d", mCount);
1063 }
1064
1065 virtual const char* name() { return "DrawRects"; }
1066
Chris Craikc1c5f082013-09-11 16:23:37 -07001067 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
1068 const DeferredDisplayState& state) {
Chris Craik28ce94a2013-05-31 11:38:03 -07001069 deferInfo.batchId = DeferredDisplayList::kOpBatch_Vertices;
Chris Craikc3566d02013-02-04 16:16:33 -08001070 }
1071
Chris Craik2af46352012-11-26 18:30:17 -08001072private:
1073 const float* mRects;
1074 int mCount;
1075};
1076
1077class DrawRoundRectOp : public DrawStrokableOp {
1078public:
1079 DrawRoundRectOp(float left, float top, float right, float bottom,
Chris Craikd218a922014-01-02 17:13:34 -08001080 float rx, float ry, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001081 : DrawStrokableOp(left, top, right, bottom, paint), mRx(rx), mRy(ry) {}
1082
Chris Craik527a3aa2013-03-04 10:19:31 -08001083 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001084 return renderer.drawRoundRect(mLocalBounds.left, mLocalBounds.top,
1085 mLocalBounds.right, mLocalBounds.bottom, mRx, mRy, getPaint(renderer));
1086 }
1087
Chris Craikc5493fb2013-06-19 16:58:58 -07001088 virtual void output(int level, uint32_t logFlags) const {
John Reckce444ca2014-06-02 15:12:36 -07001089 OP_LOG("Draw RoundRect " RECT_STRING ", rx %f, ry %f", RECT_ARGS(mLocalBounds), mRx, mRy);
Chris Craik2af46352012-11-26 18:30:17 -08001090 }
1091
Chris Craik05f3d6e2014-06-02 16:27:04 -07001092 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
1093 const DeferredDisplayState& state) {
1094 DrawStrokableOp::onDefer(renderer, deferInfo, state);
1095 if (!mPaint->getPathEffect()) {
Chris Craik6ac174b2014-06-17 13:47:05 -07001096 renderer.getCaches().tessellationCache.precacheRoundRect(state.mMatrix, *mPaint,
1097 mLocalBounds.getWidth(), mLocalBounds.getHeight(), mRx, mRy);
Chris Craik05f3d6e2014-06-02 16:27:04 -07001098 }
1099 }
1100
Chris Craik2af46352012-11-26 18:30:17 -08001101 virtual const char* name() { return "DrawRoundRect"; }
1102
1103private:
1104 float mRx;
1105 float mRy;
1106};
1107
1108class DrawCircleOp : public DrawStrokableOp {
1109public:
Chris Craikd218a922014-01-02 17:13:34 -08001110 DrawCircleOp(float x, float y, float radius, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001111 : DrawStrokableOp(x - radius, y - radius, x + radius, y + radius, paint),
1112 mX(x), mY(y), mRadius(radius) {}
1113
Chris Craik527a3aa2013-03-04 10:19:31 -08001114 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001115 return renderer.drawCircle(mX, mY, mRadius, getPaint(renderer));
1116 }
1117
Chris Craikc5493fb2013-06-19 16:58:58 -07001118 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001119 OP_LOG("Draw Circle x %f, y %f, r %f", mX, mY, mRadius);
1120 }
1121
1122 virtual const char* name() { return "DrawCircle"; }
1123
1124private:
1125 float mX;
1126 float mY;
1127 float mRadius;
1128};
1129
John Reck52244ff2014-05-01 21:27:37 -07001130class DrawCirclePropsOp : public DrawOp {
1131public:
1132 DrawCirclePropsOp(float* x, float* y, float* radius, const SkPaint* paint)
1133 : DrawOp(paint), mX(x), mY(y), mRadius(radius) {}
1134
1135 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
1136 return renderer.drawCircle(*mX, *mY, *mRadius, getPaint(renderer));
1137 }
1138
1139 virtual void output(int level, uint32_t logFlags) const {
1140 OP_LOG("Draw Circle Props x %p, y %p, r %p", mX, mY, mRadius);
1141 }
1142
1143 virtual const char* name() { return "DrawCircleProps"; }
1144
1145private:
1146 float* mX;
1147 float* mY;
1148 float* mRadius;
1149};
1150
Chris Craik2af46352012-11-26 18:30:17 -08001151class DrawOvalOp : public DrawStrokableOp {
1152public:
Chris Craikd218a922014-01-02 17:13:34 -08001153 DrawOvalOp(float left, float top, float right, float bottom, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001154 : DrawStrokableOp(left, top, right, bottom, paint) {}
1155
Chris Craik527a3aa2013-03-04 10:19:31 -08001156 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001157 return renderer.drawOval(mLocalBounds.left, mLocalBounds.top,
1158 mLocalBounds.right, mLocalBounds.bottom, getPaint(renderer));
1159 }
1160
Chris Craikc5493fb2013-06-19 16:58:58 -07001161 virtual void output(int level, uint32_t logFlags) const {
John Reckce444ca2014-06-02 15:12:36 -07001162 OP_LOG("Draw Oval " RECT_STRING, RECT_ARGS(mLocalBounds));
Chris Craik2af46352012-11-26 18:30:17 -08001163 }
1164
1165 virtual const char* name() { return "DrawOval"; }
1166};
1167
1168class DrawArcOp : public DrawStrokableOp {
1169public:
1170 DrawArcOp(float left, float top, float right, float bottom,
Chris Craikd218a922014-01-02 17:13:34 -08001171 float startAngle, float sweepAngle, bool useCenter, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001172 : DrawStrokableOp(left, top, right, bottom, paint),
1173 mStartAngle(startAngle), mSweepAngle(sweepAngle), mUseCenter(useCenter) {}
1174
Chris Craik527a3aa2013-03-04 10:19:31 -08001175 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001176 return renderer.drawArc(mLocalBounds.left, mLocalBounds.top,
1177 mLocalBounds.right, mLocalBounds.bottom,
1178 mStartAngle, mSweepAngle, mUseCenter, getPaint(renderer));
1179 }
1180
Chris Craikc5493fb2013-06-19 16:58:58 -07001181 virtual void output(int level, uint32_t logFlags) const {
John Reckce444ca2014-06-02 15:12:36 -07001182 OP_LOG("Draw Arc " RECT_STRING ", start %f, sweep %f, useCenter %d",
Chris Craik2af46352012-11-26 18:30:17 -08001183 RECT_ARGS(mLocalBounds), mStartAngle, mSweepAngle, mUseCenter);
1184 }
1185
1186 virtual const char* name() { return "DrawArc"; }
1187
1188private:
1189 float mStartAngle;
1190 float mSweepAngle;
1191 bool mUseCenter;
1192};
1193
1194class DrawPathOp : public DrawBoundedOp {
1195public:
Chris Craikd218a922014-01-02 17:13:34 -08001196 DrawPathOp(const SkPath* path, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001197 : DrawBoundedOp(paint), mPath(path) {
1198 float left, top, offset;
1199 uint32_t width, height;
Romain Guyca89e2a2013-03-08 17:44:20 -08001200 PathCache::computePathBounds(path, paint, left, top, offset, width, height);
Chris Craik2af46352012-11-26 18:30:17 -08001201 left -= offset;
1202 top -= offset;
1203 mLocalBounds.set(left, top, left + width, top + height);
1204 }
1205
Chris Craik527a3aa2013-03-04 10:19:31 -08001206 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001207 return renderer.drawPath(mPath, getPaint(renderer));
1208 }
1209
Chris Craikc1c5f082013-09-11 16:23:37 -07001210 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
1211 const DeferredDisplayState& state) {
Chris Craikd218a922014-01-02 17:13:34 -08001212 const SkPaint* paint = getPaint(renderer);
Romain Guyca89e2a2013-03-08 17:44:20 -08001213 renderer.getCaches().pathCache.precache(mPath, paint);
Chris Craik527a3aa2013-03-04 10:19:31 -08001214
Chris Craik28ce94a2013-05-31 11:38:03 -07001215 deferInfo.batchId = DeferredDisplayList::kOpBatch_AlphaMaskTexture;
Romain Guyca89e2a2013-03-08 17:44:20 -08001216 }
1217
Chris Craikc5493fb2013-06-19 16:58:58 -07001218 virtual void output(int level, uint32_t logFlags) const {
John Reckce444ca2014-06-02 15:12:36 -07001219 OP_LOG("Draw Path %p in " RECT_STRING, mPath, RECT_ARGS(mLocalBounds));
Chris Craik2af46352012-11-26 18:30:17 -08001220 }
1221
1222 virtual const char* name() { return "DrawPath"; }
1223
1224private:
Chris Craikd218a922014-01-02 17:13:34 -08001225 const SkPath* mPath;
Chris Craik2af46352012-11-26 18:30:17 -08001226};
1227
Chris Craikc3566d02013-02-04 16:16:33 -08001228class DrawLinesOp : public DrawBoundedOp {
Chris Craik2af46352012-11-26 18:30:17 -08001229public:
Chris Craikd218a922014-01-02 17:13:34 -08001230 DrawLinesOp(const float* points, int count, const SkPaint* paint)
Chris Craik5d116762013-02-19 17:49:31 -08001231 : DrawBoundedOp(points, count, paint),
1232 mPoints(points), mCount(count) {
Chris Craikc3566d02013-02-04 16:16:33 -08001233 mLocalBounds.outset(strokeWidthOutset());
Chris Craik2af46352012-11-26 18:30:17 -08001234 }
1235
Chris Craik527a3aa2013-03-04 10:19:31 -08001236 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001237 return renderer.drawLines(mPoints, mCount, getPaint(renderer));
1238 }
1239
Chris Craikc5493fb2013-06-19 16:58:58 -07001240 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001241 OP_LOG("Draw Lines count %d", mCount);
1242 }
1243
1244 virtual const char* name() { return "DrawLines"; }
1245
Chris Craikc1c5f082013-09-11 16:23:37 -07001246 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
1247 const DeferredDisplayState& state) {
Chris Craik28ce94a2013-05-31 11:38:03 -07001248 deferInfo.batchId = mPaint->isAntiAlias() ?
Chris Craikc3566d02013-02-04 16:16:33 -08001249 DeferredDisplayList::kOpBatch_AlphaVertices :
1250 DeferredDisplayList::kOpBatch_Vertices;
1251 }
1252
Chris Craik2af46352012-11-26 18:30:17 -08001253protected:
Chris Craikd218a922014-01-02 17:13:34 -08001254 const float* mPoints;
Chris Craik2af46352012-11-26 18:30:17 -08001255 int mCount;
1256};
1257
1258class DrawPointsOp : public DrawLinesOp {
1259public:
Chris Craikd218a922014-01-02 17:13:34 -08001260 DrawPointsOp(const float* points, int count, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001261 : DrawLinesOp(points, count, paint) {}
1262
Chris Craik527a3aa2013-03-04 10:19:31 -08001263 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001264 return renderer.drawPoints(mPoints, mCount, getPaint(renderer));
1265 }
1266
Chris Craikc5493fb2013-06-19 16:58:58 -07001267 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001268 OP_LOG("Draw Points count %d", mCount);
1269 }
1270
1271 virtual const char* name() { return "DrawPoints"; }
1272};
1273
1274class DrawSomeTextOp : public DrawOp {
1275public:
Chris Craikd218a922014-01-02 17:13:34 -08001276 DrawSomeTextOp(const char* text, int bytesCount, int count, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001277 : DrawOp(paint), mText(text), mBytesCount(bytesCount), mCount(count) {};
1278
Chris Craikc5493fb2013-06-19 16:58:58 -07001279 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001280 OP_LOG("Draw some text, %d bytes", mBytesCount);
1281 }
Chris Craikc3566d02013-02-04 16:16:33 -08001282
Derek Sollenbergerc29a0a42014-03-31 13:52:39 -04001283 virtual bool hasTextShadow() const {
1284 return OpenGLRenderer::hasTextShadow(mPaint);
1285 }
1286
Chris Craikc1c5f082013-09-11 16:23:37 -07001287 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
1288 const DeferredDisplayState& state) {
Chris Craikd218a922014-01-02 17:13:34 -08001289 const SkPaint* paint = getPaint(renderer);
Romain Guy0f667532013-03-01 14:31:04 -08001290 FontRenderer& fontRenderer = renderer.getCaches().fontRenderer->getFontRenderer(paint);
Chris Craik59744b72014-07-01 17:56:52 -07001291 fontRenderer.precache(paint, mText, mCount, SkMatrix::I());
Romain Guy0f667532013-03-01 14:31:04 -08001292
Chris Craik98d608d2014-07-17 12:25:11 -07001293 deferInfo.batchId = mPaint->getColor() == SK_ColorBLACK ?
Chris Craikc3566d02013-02-04 16:16:33 -08001294 DeferredDisplayList::kOpBatch_Text :
1295 DeferredDisplayList::kOpBatch_ColorText;
1296 }
Chris Craik527a3aa2013-03-04 10:19:31 -08001297
Chris Craik2af46352012-11-26 18:30:17 -08001298protected:
1299 const char* mText;
1300 int mBytesCount;
1301 int mCount;
1302};
1303
1304class DrawTextOnPathOp : public DrawSomeTextOp {
1305public:
1306 DrawTextOnPathOp(const char* text, int bytesCount, int count,
Chris Craikd218a922014-01-02 17:13:34 -08001307 const SkPath* path, float hOffset, float vOffset, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001308 : DrawSomeTextOp(text, bytesCount, count, paint),
1309 mPath(path), mHOffset(hOffset), mVOffset(vOffset) {
1310 /* TODO: inherit from DrawBounded and init mLocalBounds */
1311 }
1312
Chris Craik527a3aa2013-03-04 10:19:31 -08001313 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001314 return renderer.drawTextOnPath(mText, mBytesCount, mCount, mPath,
1315 mHOffset, mVOffset, getPaint(renderer));
1316 }
1317
1318 virtual const char* name() { return "DrawTextOnPath"; }
1319
1320private:
Chris Craikd218a922014-01-02 17:13:34 -08001321 const SkPath* mPath;
Chris Craik2af46352012-11-26 18:30:17 -08001322 float mHOffset;
1323 float mVOffset;
1324};
1325
1326class DrawPosTextOp : public DrawSomeTextOp {
1327public:
1328 DrawPosTextOp(const char* text, int bytesCount, int count,
Chris Craikd218a922014-01-02 17:13:34 -08001329 const float* positions, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001330 : DrawSomeTextOp(text, bytesCount, count, paint), mPositions(positions) {
1331 /* TODO: inherit from DrawBounded and init mLocalBounds */
1332 }
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.drawPosText(mText, mBytesCount, mCount, mPositions, getPaint(renderer));
1336 }
1337
1338 virtual const char* name() { return "DrawPosText"; }
1339
1340private:
1341 const float* mPositions;
1342};
1343
Chris Craik947eabf2014-08-19 10:21:12 -07001344class DrawTextOp : public DrawStrokableOp {
Chris Craik2af46352012-11-26 18:30:17 -08001345public:
1346 DrawTextOp(const char* text, int bytesCount, int count, float x, float y,
Chris Craikd218a922014-01-02 17:13:34 -08001347 const float* positions, const SkPaint* paint, float totalAdvance, const Rect& bounds)
Chris Craik947eabf2014-08-19 10:21:12 -07001348 : DrawStrokableOp(bounds, paint), mText(text), mBytesCount(bytesCount), mCount(count),
Chris Craik41541822013-05-03 16:35:54 -07001349 mX(x), mY(y), mPositions(positions), mTotalAdvance(totalAdvance) {
Chris Craik59744b72014-07-01 17:56:52 -07001350 mPrecacheTransform = SkMatrix::InvalidMatrix();
Chris Craik2af46352012-11-26 18:30:17 -08001351 }
1352
Chris Craikc1c5f082013-09-11 16:23:37 -07001353 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
1354 const DeferredDisplayState& state) {
Chris Craikd218a922014-01-02 17:13:34 -08001355 const SkPaint* paint = getPaint(renderer);
Romain Guy0f667532013-03-01 14:31:04 -08001356 FontRenderer& fontRenderer = renderer.getCaches().fontRenderer->getFontRenderer(paint);
Chris Craik59744b72014-07-01 17:56:52 -07001357 SkMatrix transform;
1358 renderer.findBestFontTransform(state.mMatrix, &transform);
Romain Guybd3055f2013-03-13 16:14:47 -07001359 if (mPrecacheTransform != transform) {
1360 fontRenderer.precache(paint, mText, mCount, transform);
1361 mPrecacheTransform = transform;
1362 }
Chris Craik98d608d2014-07-17 12:25:11 -07001363 deferInfo.batchId = mPaint->getColor() == SK_ColorBLACK ?
Chris Craik527a3aa2013-03-04 10:19:31 -08001364 DeferredDisplayList::kOpBatch_Text :
1365 DeferredDisplayList::kOpBatch_ColorText;
1366
Kévin PETIT73fc5582014-02-13 11:03:40 +00001367 deferInfo.mergeId = reinterpret_cast<mergeid_t>(mPaint->getColor());
Chris Craik527a3aa2013-03-04 10:19:31 -08001368
1369 // don't merge decorated text - the decorations won't draw in order
Chris Craik98d608d2014-07-17 12:25:11 -07001370 bool hasDecorations = mPaint->getFlags()
1371 & (SkPaint::kUnderlineText_Flag | SkPaint::kStrikeThruText_Flag);
1372
1373 deferInfo.mergeable = state.mMatrix.isPureTranslate()
1374 && !hasDecorations
1375 && OpenGLRenderer::getXfermodeDirect(mPaint) == SkXfermode::kSrcOver_Mode;
Romain Guy0f667532013-03-01 14:31:04 -08001376 }
1377
Chris Craik527a3aa2013-03-04 10:19:31 -08001378 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Romain Guy9b5a1a22013-08-09 14:06:29 -07001379 Rect bounds;
John Reck3b202512014-06-23 13:13:08 -07001380 getLocalBounds(bounds);
Chris Craik2af46352012-11-26 18:30:17 -08001381 return renderer.drawText(mText, mBytesCount, mCount, mX, mY,
Romain Guy9b5a1a22013-08-09 14:06:29 -07001382 mPositions, getPaint(renderer), mTotalAdvance, bounds);
Chris Craik2af46352012-11-26 18:30:17 -08001383 }
1384
Chris Craik527a3aa2013-03-04 10:19:31 -08001385 virtual status_t multiDraw(OpenGLRenderer& renderer, Rect& dirty,
Chris Craikc1c5f082013-09-11 16:23:37 -07001386 const Vector<OpStatePair>& ops, const Rect& bounds) {
Chris Craik527a3aa2013-03-04 10:19:31 -08001387 status_t status = DrawGlInfo::kStatusDone;
Chris Craik527a3aa2013-03-04 10:19:31 -08001388 for (unsigned int i = 0; i < ops.size(); i++) {
Chris Craikc1c5f082013-09-11 16:23:37 -07001389 const DeferredDisplayState& state = *(ops[i].state);
Chris Craik527a3aa2013-03-04 10:19:31 -08001390 DrawOpMode drawOpMode = (i == ops.size() - 1) ? kDrawOpMode_Flush : kDrawOpMode_Defer;
Chris Craikc1c5f082013-09-11 16:23:37 -07001391 renderer.restoreDisplayState(state, true); // restore all but the clip
Chris Craik527a3aa2013-03-04 10:19:31 -08001392
Chris Craikc1c5f082013-09-11 16:23:37 -07001393 DrawTextOp& op = *((DrawTextOp*)ops[i].op);
Romain Guy9b5a1a22013-08-09 14:06:29 -07001394 // quickReject() will not occure in drawText() so we can use mLocalBounds
1395 // directly, we do not need to account for shadow by calling getLocalBounds()
Chris Craik527a3aa2013-03-04 10:19:31 -08001396 status |= renderer.drawText(op.mText, op.mBytesCount, op.mCount, op.mX, op.mY,
Chris Craik41541822013-05-03 16:35:54 -07001397 op.mPositions, op.getPaint(renderer), op.mTotalAdvance, op.mLocalBounds,
1398 drawOpMode);
Chris Craik527a3aa2013-03-04 10:19:31 -08001399 }
1400 return status;
1401 }
1402
Chris Craikc5493fb2013-06-19 16:58:58 -07001403 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001404 OP_LOG("Draw Text of count %d, bytes %d", mCount, mBytesCount);
1405 }
1406
1407 virtual const char* name() { return "DrawText"; }
1408
1409private:
1410 const char* mText;
1411 int mBytesCount;
1412 int mCount;
1413 float mX;
1414 float mY;
1415 const float* mPositions;
Chris Craik41541822013-05-03 16:35:54 -07001416 float mTotalAdvance;
Chris Craik59744b72014-07-01 17:56:52 -07001417 SkMatrix mPrecacheTransform;
Chris Craik2af46352012-11-26 18:30:17 -08001418};
1419
1420///////////////////////////////////////////////////////////////////////////////
1421// SPECIAL DRAW OPERATIONS
1422///////////////////////////////////////////////////////////////////////////////
1423
1424class DrawFunctorOp : public DrawOp {
1425public:
1426 DrawFunctorOp(Functor* functor)
Chris Craikf57776b2013-10-25 18:30:17 -07001427 : DrawOp(NULL), mFunctor(functor) {}
Chris Craik2af46352012-11-26 18:30:17 -08001428
Chris Craik527a3aa2013-03-04 10:19:31 -08001429 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001430 renderer.startMark("GL functor");
1431 status_t ret = renderer.callDrawGLFunction(mFunctor, dirty);
1432 renderer.endMark();
1433 return ret;
1434 }
1435
Chris Craikc5493fb2013-06-19 16:58:58 -07001436 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001437 OP_LOG("Draw Functor %p", mFunctor);
1438 }
1439
1440 virtual const char* name() { return "DrawFunctor"; }
1441
1442private:
1443 Functor* mFunctor;
1444};
1445
Chris Craika7090e02014-06-20 16:01:00 -07001446class DrawRenderNodeOp : public DrawBoundedOp {
1447 friend class RenderNode; // grant RenderNode access to info of child
Chris Craik8afd0f22014-08-21 17:41:57 -07001448 friend class DisplayListData; // grant DisplayListData access to info of child
Chris Craik2af46352012-11-26 18:30:17 -08001449public:
Chris Craika7090e02014-06-20 16:01:00 -07001450 DrawRenderNodeOp(RenderNode* renderNode, int flags, const mat4& transformFromParent)
1451 : DrawBoundedOp(0, 0, renderNode->getWidth(), renderNode->getHeight(), 0),
1452 mRenderNode(renderNode), mFlags(flags), mTransformFromParent(transformFromParent) {}
Chris Craikc3566d02013-02-04 16:16:33 -08001453
Chet Haasedd671592013-04-19 14:54:34 -07001454 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
1455 bool useQuickReject) {
Chris Craik8afd0f22014-08-21 17:41:57 -07001456 if (mRenderNode->isRenderable() && !mSkipInOrderDraw) {
Chris Craika7090e02014-06-20 16:01:00 -07001457 mRenderNode->defer(deferStruct, level + 1);
Chris Craikc3566d02013-02-04 16:16:33 -08001458 }
Chris Craikc3566d02013-02-04 16:16:33 -08001459 }
Chris Craik8afd0f22014-08-21 17:41:57 -07001460
Chet Haasedd671592013-04-19 14:54:34 -07001461 virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level,
1462 bool useQuickReject) {
Chris Craik8afd0f22014-08-21 17:41:57 -07001463 if (mRenderNode->isRenderable() && !mSkipInOrderDraw) {
Chris Craika7090e02014-06-20 16:01:00 -07001464 mRenderNode->replay(replayStruct, level + 1);
Chris Craikff785832013-03-08 13:12:16 -08001465 }
1466 }
Chris Craik2af46352012-11-26 18:30:17 -08001467
Chris Craik527a3aa2013-03-04 10:19:31 -08001468 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik80d49022014-06-20 15:03:43 -07001469 LOG_ALWAYS_FATAL("should not be called, because replay() is overridden");
1470 return 0;
Chris Craika08f95c2013-03-15 17:24:33 -07001471 }
Chris Craikff785832013-03-08 13:12:16 -08001472
Chris Craikc5493fb2013-06-19 16:58:58 -07001473 virtual void output(int level, uint32_t logFlags) const {
Chris Craik8afd0f22014-08-21 17:41:57 -07001474 OP_LOG("Draw RenderNode %p %s, flags %#x", mRenderNode, mRenderNode->getName(), mFlags);
Chris Craika7090e02014-06-20 16:01:00 -07001475 if (mRenderNode && (logFlags & kOpLogFlag_Recurse)) {
1476 mRenderNode->output(level + 1);
Chris Craik2af46352012-11-26 18:30:17 -08001477 }
1478 }
1479
Chris Craika7090e02014-06-20 16:01:00 -07001480 virtual const char* name() { return "DrawRenderNode"; }
Chris Craik2af46352012-11-26 18:30:17 -08001481
Chris Craika7090e02014-06-20 16:01:00 -07001482 RenderNode* renderNode() { return mRenderNode; }
John Reck087bc0c2014-04-04 16:20:08 -07001483
Chris Craik2af46352012-11-26 18:30:17 -08001484private:
Chris Craika7090e02014-06-20 16:01:00 -07001485 RenderNode* mRenderNode;
Chris Craikf57776b2013-10-25 18:30:17 -07001486 const int mFlags;
1487
1488 ///////////////////////////
Chris Craika7090e02014-06-20 16:01:00 -07001489 // Properties below are used by RenderNode::computeOrderingImpl() and issueOperations()
Chris Craikf57776b2013-10-25 18:30:17 -07001490 ///////////////////////////
1491 /**
1492 * Records transform vs parent, used for computing total transform without rerunning DL contents
1493 */
1494 const mat4 mTransformFromParent;
1495
1496 /**
Chris Craika7090e02014-06-20 16:01:00 -07001497 * Holds the transformation between the projection surface ViewGroup and this RenderNode
Chris Craikb79a3e32014-03-11 12:20:17 -07001498 * drawing instance. Represents any translations / transformations done within the drawing of
1499 * the compositing ancestor ViewGroup's draw, before the draw of the View represented by this
1500 * DisplayList draw instance.
Chris Craikf57776b2013-10-25 18:30:17 -07001501 *
Chris Craika7090e02014-06-20 16:01:00 -07001502 * Note: doesn't include transformation within the RenderNode, or its properties.
Chris Craikf57776b2013-10-25 18:30:17 -07001503 */
Chris Craikf533e942014-01-14 22:35:37 -08001504 mat4 mTransformFromCompositingAncestor;
Chris Craikf57776b2013-10-25 18:30:17 -07001505 bool mSkipInOrderDraw;
1506};
1507
1508/**
Chris Craik024433f2014-03-26 13:19:14 -07001509 * Not a canvas operation, used only by 3d / z ordering logic in RenderNode::iterate()
Chris Craikf57776b2013-10-25 18:30:17 -07001510 */
1511class DrawShadowOp : public DrawOp {
1512public:
Chris Craik024433f2014-03-26 13:19:14 -07001513 DrawShadowOp(const mat4& transformXY, const mat4& transformZ,
Chris Craik74669862014-08-07 17:27:30 -07001514 float casterAlpha, const SkPath* casterOutline)
1515 : DrawOp(NULL)
1516 , mTransformXY(transformXY)
1517 , mTransformZ(transformZ)
1518 , mCasterAlpha(casterAlpha)
1519 , mCasterOutline(casterOutline) {
Chris Craik61317322014-05-21 13:03:52 -07001520 }
Chris Craikf57776b2013-10-25 18:30:17 -07001521
Chris Craik05f3d6e2014-06-02 16:27:04 -07001522 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
1523 const DeferredDisplayState& state) {
1524 renderer.getCaches().tessellationCache.precacheShadows(&state.mMatrix,
Chris Craik74669862014-08-07 17:27:30 -07001525 renderer.getLocalClipBounds(), isCasterOpaque(), mCasterOutline,
Chris Craik05f3d6e2014-06-02 16:27:04 -07001526 &mTransformXY, &mTransformZ, renderer.getLightCenter(), renderer.getLightRadius());
1527 }
1528
Chris Craikf57776b2013-10-25 18:30:17 -07001529 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik05f3d6e2014-06-02 16:27:04 -07001530 TessellationCache::vertexBuffer_pair_t buffers;
1531 Matrix4 drawTransform;
1532 renderer.getMatrix(&drawTransform);
1533 renderer.getCaches().tessellationCache.getShadowBuffers(&drawTransform,
Chris Craik74669862014-08-07 17:27:30 -07001534 renderer.getLocalClipBounds(), isCasterOpaque(), mCasterOutline,
Chris Craik05f3d6e2014-06-02 16:27:04 -07001535 &mTransformXY, &mTransformZ, renderer.getLightCenter(), renderer.getLightRadius(),
1536 buffers);
1537
1538 return renderer.drawShadow(mCasterAlpha, buffers.first, buffers.second);
Chris Craikf57776b2013-10-25 18:30:17 -07001539 }
1540
1541 virtual void output(int level, uint32_t logFlags) const {
Chris Craik61317322014-05-21 13:03:52 -07001542 OP_LOGS("DrawShadow");
Chris Craikf57776b2013-10-25 18:30:17 -07001543 }
1544
1545 virtual const char* name() { return "DrawShadow"; }
1546
1547private:
Chris Craikaf4d04c2014-07-29 12:50:14 -07001548 bool isCasterOpaque() { return mCasterAlpha >= 1.0f; }
Chris Craik05f3d6e2014-06-02 16:27:04 -07001549
Chris Craikb79a3e32014-03-11 12:20:17 -07001550 const mat4 mTransformXY;
1551 const mat4 mTransformZ;
Chris Craik024433f2014-03-26 13:19:14 -07001552 const float mCasterAlpha;
Chris Craik74669862014-08-07 17:27:30 -07001553 const SkPath* mCasterOutline;
Chris Craik2af46352012-11-26 18:30:17 -08001554};
1555
1556class DrawLayerOp : public DrawOp {
1557public:
Chris Craika08f95c2013-03-15 17:24:33 -07001558 DrawLayerOp(Layer* layer, float x, float y)
Chris Craikf57776b2013-10-25 18:30:17 -07001559 : DrawOp(NULL), mLayer(layer), mX(x), mY(y) {}
Chris Craik2af46352012-11-26 18:30:17 -08001560
Chris Craik527a3aa2013-03-04 10:19:31 -08001561 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craika08f95c2013-03-15 17:24:33 -07001562 return renderer.drawLayer(mLayer, mX, mY);
Chris Craik2af46352012-11-26 18:30:17 -08001563 }
1564
Chris Craikc5493fb2013-06-19 16:58:58 -07001565 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001566 OP_LOG("Draw Layer %p at %f %f", mLayer, mX, mY);
1567 }
1568
1569 virtual const char* name() { return "DrawLayer"; }
1570
1571private:
1572 Layer* mLayer;
1573 float mX;
1574 float mY;
1575};
1576
1577}; // namespace uirenderer
1578}; // namespace android
1579
1580#endif // ANDROID_HWUI_DISPLAY_OPERATION_H