blob: c6d3db7d9a48e9581fa149076e2fcdede134acf2 [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
211 // check state/paint for transparency
Leon Scroggins IIId1ad5e62014-05-05 12:50:38 -0400212 if (mPaint) {
213 if (mPaint->getShader() && !mPaint->getShader()->isOpaque()) {
214 return false;
215 }
216 if (mPaint->getAlpha() != 0xFF) {
217 return false;
218 }
219 }
220
221 if (state.mAlpha != 1.0f) return false;
Chris Craik28ce94a2013-05-31 11:38:03 -0700222
223 SkXfermode::Mode mode = OpenGLRenderer::getXfermodeDirect(mPaint);
224 return (mode == SkXfermode::kSrcOver_Mode ||
225 mode == SkXfermode::kSrc_Mode);
226
227 }
228
Chris Craikd218a922014-01-02 17:13:34 -0800229 const SkPaint* mPaint; // should be accessed via getPaint() when applying
Chris Craik2af46352012-11-26 18:30:17 -0800230 bool mQuickRejected;
231};
232
233class DrawBoundedOp : public DrawOp {
234public:
Chris Craikd218a922014-01-02 17:13:34 -0800235 DrawBoundedOp(float left, float top, float right, float bottom, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -0800236 : DrawOp(paint), mLocalBounds(left, top, right, bottom) {}
237
Chris Craikd218a922014-01-02 17:13:34 -0800238 DrawBoundedOp(const Rect& localBounds, const SkPaint* paint)
Chris Craik41541822013-05-03 16:35:54 -0700239 : DrawOp(paint), mLocalBounds(localBounds) {}
240
Chris Craik5d116762013-02-19 17:49:31 -0800241 // Calculates bounds as smallest rect encompassing all points
242 // NOTE: requires at least 1 vertex, and doesn't account for stroke size (should be handled in
243 // subclass' constructor)
Chris Craikd218a922014-01-02 17:13:34 -0800244 DrawBoundedOp(const float* points, int count, const SkPaint* paint)
Chris Craik5d116762013-02-19 17:49:31 -0800245 : DrawOp(paint), mLocalBounds(points[0], points[1], points[0], points[1]) {
246 for (int i = 2; i < count; i += 2) {
247 mLocalBounds.left = fminf(mLocalBounds.left, points[i]);
248 mLocalBounds.right = fmaxf(mLocalBounds.right, points[i]);
249 mLocalBounds.top = fminf(mLocalBounds.top, points[i + 1]);
250 mLocalBounds.bottom = fmaxf(mLocalBounds.bottom, points[i + 1]);
251 }
252 }
253
254 // default empty constructor for bounds, to be overridden in child constructor body
Chris Craikd218a922014-01-02 17:13:34 -0800255 DrawBoundedOp(const SkPaint* paint): DrawOp(paint) { }
Chris Craik2af46352012-11-26 18:30:17 -0800256
John Reckca1b3b82014-06-27 07:21:36 -0700257 virtual bool getLocalBounds(Rect& localBounds) {
Chris Craik2af46352012-11-26 18:30:17 -0800258 localBounds.set(mLocalBounds);
Derek Sollenbergerc29a0a42014-03-31 13:52:39 -0400259 OpenGLRenderer::TextShadow textShadow;
260 if (OpenGLRenderer::getTextShadow(mPaint, &textShadow)) {
Romain Guy9b5a1a22013-08-09 14:06:29 -0700261 Rect shadow(mLocalBounds);
Derek Sollenbergerc29a0a42014-03-31 13:52:39 -0400262 shadow.translate(textShadow.dx, textShadow.dx);
263 shadow.outset(textShadow.radius);
Romain Guy9b5a1a22013-08-09 14:06:29 -0700264 localBounds.unionWith(shadow);
265 }
Chris Craik2af46352012-11-26 18:30:17 -0800266 return true;
267 }
268
269protected:
270 Rect mLocalBounds; // displayed area in LOCAL coord. doesn't incorporate stroke, so check paint
271};
272
273///////////////////////////////////////////////////////////////////////////////
274// STATE OPERATIONS - these may affect the state of the canvas/renderer, but do
275// not directly draw or alter output
276///////////////////////////////////////////////////////////////////////////////
277
278class SaveOp : public StateOp {
279public:
280 SaveOp(int flags)
281 : mFlags(flags) {}
282
Chet Haasedd671592013-04-19 14:54:34 -0700283 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
284 bool useQuickReject) {
Chris Craikff785832013-03-08 13:12:16 -0800285 int newSaveCount = deferStruct.mRenderer.save(mFlags);
286 deferStruct.mDeferredList.addSave(deferStruct.mRenderer, this, newSaveCount);
287 }
288
Chris Craik7273daa2013-03-28 11:25:24 -0700289 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800290 renderer.save(mFlags);
291 }
292
Chris Craikc5493fb2013-06-19 16:58:58 -0700293 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800294 OP_LOG("Save flags %x", mFlags);
295 }
296
297 virtual const char* name() { return "Save"; }
298
Chris Craikff785832013-03-08 13:12:16 -0800299 int getFlags() const { return mFlags; }
Chris Craik2af46352012-11-26 18:30:17 -0800300private:
301 int mFlags;
302};
303
304class RestoreToCountOp : public StateOp {
305public:
306 RestoreToCountOp(int count)
307 : mCount(count) {}
308
Chet Haasedd671592013-04-19 14:54:34 -0700309 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
310 bool useQuickReject) {
Chris Craik7273daa2013-03-28 11:25:24 -0700311 deferStruct.mDeferredList.addRestoreToCount(deferStruct.mRenderer,
312 this, saveCount + mCount);
Chris Craikff785832013-03-08 13:12:16 -0800313 deferStruct.mRenderer.restoreToCount(saveCount + mCount);
Chris Craik2af46352012-11-26 18:30:17 -0800314 }
315
Chris Craik7273daa2013-03-28 11:25:24 -0700316 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craikff785832013-03-08 13:12:16 -0800317 renderer.restoreToCount(saveCount + mCount);
318 }
319
Chris Craikc5493fb2013-06-19 16:58:58 -0700320 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800321 OP_LOG("Restore to count %d", mCount);
322 }
323
324 virtual const char* name() { return "RestoreToCount"; }
325
326private:
327 int mCount;
328};
329
330class SaveLayerOp : public StateOp {
331public:
Derek Sollenbergerd44fbe52014-02-05 16:47:00 -0500332 SaveLayerOp(float left, float top, float right, float bottom, int alpha, int flags)
Chris Craik3f085422014-04-15 16:18:08 -0700333 : mArea(left, top, right, bottom)
334 , mPaint(&mCachedPaint)
335 , mFlags(flags)
336 , mConvexMask(NULL) {
Derek Sollenbergerd44fbe52014-02-05 16:47:00 -0500337 mCachedPaint.setAlpha(alpha);
338 }
339
340 SaveLayerOp(float left, float top, float right, float bottom, const SkPaint* paint, int flags)
Chris Craik3f085422014-04-15 16:18:08 -0700341 : mArea(left, top, right, bottom)
342 , mPaint(paint)
343 , mFlags(flags)
344 , mConvexMask(NULL)
345 {}
Chris Craikff785832013-03-08 13:12:16 -0800346
Chet Haasedd671592013-04-19 14:54:34 -0700347 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
348 bool useQuickReject) {
Chris Craikff785832013-03-08 13:12:16 -0800349 // NOTE: don't bother with actual saveLayer, instead issuing it at flush time
Chris Craikd90144d2013-03-19 15:03:48 -0700350 int newSaveCount = deferStruct.mRenderer.getSaveCount();
Chris Craikff785832013-03-08 13:12:16 -0800351 deferStruct.mDeferredList.addSaveLayer(deferStruct.mRenderer, this, newSaveCount);
Chris Craikd90144d2013-03-19 15:03:48 -0700352
353 // NOTE: don't issue full saveLayer, since that has side effects/is costly. instead just
354 // setup the snapshot for deferral, and re-issue the op at flush time
355 deferStruct.mRenderer.saveLayerDeferred(mArea.left, mArea.top, mArea.right, mArea.bottom,
Derek Sollenbergerd44fbe52014-02-05 16:47:00 -0500356 mPaint, mFlags);
Chris Craikff785832013-03-08 13:12:16 -0800357 }
Chris Craik2af46352012-11-26 18:30:17 -0800358
Chris Craik7273daa2013-03-28 11:25:24 -0700359 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik3f085422014-04-15 16:18:08 -0700360 renderer.saveLayer(mArea.left, mArea.top, mArea.right, mArea.bottom,
361 mPaint, mFlags, mConvexMask);
Chris Craik2af46352012-11-26 18:30:17 -0800362 }
363
Chris Craikc5493fb2013-06-19 16:58:58 -0700364 virtual void output(int level, uint32_t logFlags) const {
Chris Craikff785832013-03-08 13:12:16 -0800365 OP_LOG("SaveLayer%s of area " RECT_STRING,
366 (isSaveLayerAlpha() ? "Alpha" : ""),RECT_ARGS(mArea));
Chris Craik2af46352012-11-26 18:30:17 -0800367 }
368
Chris Craikff785832013-03-08 13:12:16 -0800369 virtual const char* name() { return isSaveLayerAlpha() ? "SaveLayerAlpha" : "SaveLayer"; }
370
371 int getFlags() { return mFlags; }
Chris Craik2af46352012-11-26 18:30:17 -0800372
Chris Craik3f085422014-04-15 16:18:08 -0700373 // Called to make SaveLayerOp clip to the provided mask when drawing back/restored
374 void setMask(const SkPath* convexMask) {
375 mConvexMask = convexMask;
376 }
377
Chris Craik2af46352012-11-26 18:30:17 -0800378private:
Derek Sollenbergerd44fbe52014-02-05 16:47:00 -0500379 bool isSaveLayerAlpha() const {
380 SkXfermode::Mode mode = OpenGLRenderer::getXfermodeDirect(mPaint);
381 int alpha = OpenGLRenderer::getAlphaDirect(mPaint);
382 return alpha < 255 && mode == SkXfermode::kSrcOver_Mode;
Chris Craik2af46352012-11-26 18:30:17 -0800383 }
384
Chris Craik2af46352012-11-26 18:30:17 -0800385 Rect mArea;
Derek Sollenbergerd44fbe52014-02-05 16:47:00 -0500386 const SkPaint* mPaint;
387 SkPaint mCachedPaint;
Chris Craik2af46352012-11-26 18:30:17 -0800388 int mFlags;
Chris Craik3f085422014-04-15 16:18:08 -0700389
390 // Convex path, points at data in RenderNode, valid for the duration of the frame only
391 // Only used for masking the SaveLayer which wraps projected RenderNodes
392 const SkPath* mConvexMask;
Chris Craik2af46352012-11-26 18:30:17 -0800393};
394
395class TranslateOp : public StateOp {
396public:
397 TranslateOp(float dx, float dy)
398 : mDx(dx), mDy(dy) {}
399
Chris Craik7273daa2013-03-28 11:25:24 -0700400 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800401 renderer.translate(mDx, mDy);
402 }
403
Chris Craikc5493fb2013-06-19 16:58:58 -0700404 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800405 OP_LOG("Translate by %f %f", mDx, mDy);
406 }
407
408 virtual const char* name() { return "Translate"; }
409
410private:
411 float mDx;
412 float mDy;
413};
414
415class RotateOp : public StateOp {
416public:
417 RotateOp(float degrees)
418 : mDegrees(degrees) {}
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.rotate(mDegrees);
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("Rotate by %f degrees", mDegrees);
426 }
427
428 virtual const char* name() { return "Rotate"; }
429
430private:
431 float mDegrees;
432};
433
434class ScaleOp : public StateOp {
435public:
436 ScaleOp(float sx, float sy)
437 : mSx(sx), mSy(sy) {}
438
Chris Craik7273daa2013-03-28 11:25:24 -0700439 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800440 renderer.scale(mSx, mSy);
441 }
442
Chris Craikc5493fb2013-06-19 16:58:58 -0700443 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800444 OP_LOG("Scale by %f %f", mSx, mSy);
445 }
446
447 virtual const char* name() { return "Scale"; }
448
449private:
450 float mSx;
451 float mSy;
452};
453
454class SkewOp : public StateOp {
455public:
456 SkewOp(float sx, float sy)
457 : mSx(sx), mSy(sy) {}
458
Chris Craik7273daa2013-03-28 11:25:24 -0700459 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800460 renderer.skew(mSx, mSy);
461 }
462
Chris Craikc5493fb2013-06-19 16:58:58 -0700463 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800464 OP_LOG("Skew by %f %f", mSx, mSy);
465 }
466
467 virtual const char* name() { return "Skew"; }
468
469private:
470 float mSx;
471 float mSy;
472};
473
474class SetMatrixOp : public StateOp {
475public:
Derek Sollenberger13908822013-12-10 12:28:58 -0500476 SetMatrixOp(const SkMatrix& matrix)
Chris Craik2af46352012-11-26 18:30:17 -0800477 : mMatrix(matrix) {}
478
Chris Craik7273daa2013-03-28 11:25:24 -0700479 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800480 renderer.setMatrix(mMatrix);
481 }
482
Chris Craikc5493fb2013-06-19 16:58:58 -0700483 virtual void output(int level, uint32_t logFlags) const {
Derek Sollenberger13908822013-12-10 12:28:58 -0500484 if (mMatrix.isIdentity()) {
Romain Guy4e7b7722013-07-16 13:47:01 -0700485 OP_LOGS("SetMatrix (reset)");
Derek Sollenberger13908822013-12-10 12:28:58 -0500486 } else {
487 OP_LOG("SetMatrix " SK_MATRIX_STRING, SK_MATRIX_ARGS(&mMatrix));
Romain Guy4e7b7722013-07-16 13:47:01 -0700488 }
Chris Craik2af46352012-11-26 18:30:17 -0800489 }
490
491 virtual const char* name() { return "SetMatrix"; }
492
493private:
Derek Sollenberger13908822013-12-10 12:28:58 -0500494 const SkMatrix mMatrix;
Chris Craik2af46352012-11-26 18:30:17 -0800495};
496
497class ConcatMatrixOp : public StateOp {
498public:
Derek Sollenberger13908822013-12-10 12:28:58 -0500499 ConcatMatrixOp(const SkMatrix& matrix)
Chris Craik2af46352012-11-26 18:30:17 -0800500 : mMatrix(matrix) {}
501
Chris Craik7273daa2013-03-28 11:25:24 -0700502 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800503 renderer.concatMatrix(mMatrix);
504 }
505
Chris Craikc5493fb2013-06-19 16:58:58 -0700506 virtual void output(int level, uint32_t logFlags) const {
Derek Sollenberger13908822013-12-10 12:28:58 -0500507 OP_LOG("ConcatMatrix " SK_MATRIX_STRING, SK_MATRIX_ARGS(&mMatrix));
Chris Craik2af46352012-11-26 18:30:17 -0800508 }
509
510 virtual const char* name() { return "ConcatMatrix"; }
511
512private:
Derek Sollenberger13908822013-12-10 12:28:58 -0500513 const SkMatrix mMatrix;
Chris Craik2af46352012-11-26 18:30:17 -0800514};
515
Chris Craikff785832013-03-08 13:12:16 -0800516class ClipOp : public StateOp {
517public:
518 ClipOp(SkRegion::Op op) : mOp(op) {}
519
Chet Haasedd671592013-04-19 14:54:34 -0700520 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
521 bool useQuickReject) {
Chris Craikff785832013-03-08 13:12:16 -0800522 // NOTE: must defer op BEFORE applying state, since it may read clip
523 deferStruct.mDeferredList.addClip(deferStruct.mRenderer, this);
524
525 // TODO: Can we avoid applying complex clips at defer time?
526 applyState(deferStruct.mRenderer, saveCount);
527 }
528
529 bool canCauseComplexClip() {
530 return ((mOp != SkRegion::kIntersect_Op) && (mOp != SkRegion::kReplace_Op)) || !isRect();
531 }
532
533protected:
Chris Craikff785832013-03-08 13:12:16 -0800534 virtual bool isRect() { return false; }
535
536 SkRegion::Op mOp;
537};
538
539class ClipRectOp : public ClipOp {
Chris Craik2af46352012-11-26 18:30:17 -0800540public:
541 ClipRectOp(float left, float top, float right, float bottom, SkRegion::Op op)
Chris Craikff785832013-03-08 13:12:16 -0800542 : ClipOp(op), mArea(left, top, right, bottom) {}
Chris Craik2af46352012-11-26 18:30:17 -0800543
Chris Craik7273daa2013-03-28 11:25:24 -0700544 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800545 renderer.clipRect(mArea.left, mArea.top, mArea.right, mArea.bottom, mOp);
546 }
547
Chris Craikc5493fb2013-06-19 16:58:58 -0700548 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800549 OP_LOG("ClipRect " RECT_STRING, RECT_ARGS(mArea));
550 }
551
552 virtual const char* name() { return "ClipRect"; }
553
Chris Craikff785832013-03-08 13:12:16 -0800554protected:
555 virtual bool isRect() { return true; }
Chris Craikb98a0162013-02-21 11:30:22 -0800556
Chris Craik2af46352012-11-26 18:30:17 -0800557private:
558 Rect mArea;
Chris Craik2af46352012-11-26 18:30:17 -0800559};
560
Chris Craikff785832013-03-08 13:12:16 -0800561class ClipPathOp : public ClipOp {
Chris Craik2af46352012-11-26 18:30:17 -0800562public:
Chris Craikd218a922014-01-02 17:13:34 -0800563 ClipPathOp(const SkPath* path, SkRegion::Op op)
Chris Craikff785832013-03-08 13:12:16 -0800564 : ClipOp(op), mPath(path) {}
Chris Craik2af46352012-11-26 18:30:17 -0800565
Chris Craik7273daa2013-03-28 11:25:24 -0700566 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800567 renderer.clipPath(mPath, mOp);
568 }
569
Chris Craikc5493fb2013-06-19 16:58:58 -0700570 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800571 SkRect bounds = mPath->getBounds();
572 OP_LOG("ClipPath bounds " RECT_STRING,
573 bounds.left(), bounds.top(), bounds.right(), bounds.bottom());
574 }
575
576 virtual const char* name() { return "ClipPath"; }
577
578private:
Chris Craikd218a922014-01-02 17:13:34 -0800579 const SkPath* mPath;
Chris Craik2af46352012-11-26 18:30:17 -0800580};
581
Chris Craikff785832013-03-08 13:12:16 -0800582class ClipRegionOp : public ClipOp {
Chris Craik2af46352012-11-26 18:30:17 -0800583public:
Chris Craikd218a922014-01-02 17:13:34 -0800584 ClipRegionOp(const SkRegion* region, SkRegion::Op op)
Chris Craikff785832013-03-08 13:12:16 -0800585 : ClipOp(op), mRegion(region) {}
Chris Craik2af46352012-11-26 18:30:17 -0800586
Chris Craik7273daa2013-03-28 11:25:24 -0700587 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800588 renderer.clipRegion(mRegion, mOp);
589 }
590
Chris Craikc5493fb2013-06-19 16:58:58 -0700591 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800592 SkIRect bounds = mRegion->getBounds();
593 OP_LOG("ClipRegion bounds %d %d %d %d",
594 bounds.left(), bounds.top(), bounds.right(), bounds.bottom());
595 }
596
597 virtual const char* name() { return "ClipRegion"; }
598
599private:
Chris Craikd218a922014-01-02 17:13:34 -0800600 const SkRegion* mRegion;
Chris Craik2af46352012-11-26 18:30:17 -0800601};
602
Chris Craik2af46352012-11-26 18:30:17 -0800603class ResetPaintFilterOp : public StateOp {
604public:
Chris Craik7273daa2013-03-28 11:25:24 -0700605 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800606 renderer.resetPaintFilter();
607 }
608
Chris Craikc5493fb2013-06-19 16:58:58 -0700609 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800610 OP_LOGS("ResetPaintFilter");
611 }
612
613 virtual const char* name() { return "ResetPaintFilter"; }
614};
615
616class SetupPaintFilterOp : public StateOp {
617public:
618 SetupPaintFilterOp(int clearBits, int setBits)
619 : mClearBits(clearBits), mSetBits(setBits) {}
620
Chris Craik7273daa2013-03-28 11:25:24 -0700621 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
Chris Craik2af46352012-11-26 18:30:17 -0800622 renderer.setupPaintFilter(mClearBits, mSetBits);
623 }
624
Chris Craikc5493fb2013-06-19 16:58:58 -0700625 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800626 OP_LOG("SetupPaintFilter, clear %#x, set %#x", mClearBits, mSetBits);
627 }
628
629 virtual const char* name() { return "SetupPaintFilter"; }
630
631private:
632 int mClearBits;
633 int mSetBits;
634};
635
Chris Craik2af46352012-11-26 18:30:17 -0800636///////////////////////////////////////////////////////////////////////////////
637// DRAW OPERATIONS - these are operations that can draw to the canvas's device
638///////////////////////////////////////////////////////////////////////////////
639
640class DrawBitmapOp : public DrawBoundedOp {
641public:
Chris Craik79647502014-08-06 13:42:24 -0700642 DrawBitmapOp(const SkBitmap* bitmap, const SkPaint* paint)
643 : DrawBoundedOp(0, 0, bitmap->width(), bitmap->height(), paint)
644 , mBitmap(bitmap)
645 , mAtlas(Caches::getInstance().assetAtlas) {
Romain Guy55b6f952013-06-27 15:27:09 -0700646 mEntry = mAtlas.getEntry(bitmap);
647 if (mEntry) {
648 mEntryGenerationId = mAtlas.getGenerationId();
649 mUvMapper = mEntry->uvMapper;
650 }
Romain Guy3b748a42013-04-17 18:54:38 -0700651 }
Chris Craik2af46352012-11-26 18:30:17 -0800652
Chris Craik527a3aa2013-03-04 10:19:31 -0800653 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik79647502014-08-06 13:42:24 -0700654 return renderer.drawBitmap(mBitmap, getPaint(renderer));
Chris Craik2af46352012-11-26 18:30:17 -0800655 }
656
Romain Guy55b6f952013-06-27 15:27:09 -0700657 AssetAtlas::Entry* getAtlasEntry() {
658 // The atlas entry is stale, let's get a new one
659 if (mEntry && mEntryGenerationId != mAtlas.getGenerationId()) {
660 mEntryGenerationId = mAtlas.getGenerationId();
661 mEntry = mAtlas.getEntry(mBitmap);
662 mUvMapper = mEntry->uvMapper;
663 }
664 return mEntry;
665 }
666
Chris Craik527a3aa2013-03-04 10:19:31 -0800667#define SET_TEXTURE(ptr, posRect, offsetRect, texCoordsRect, xDim, yDim) \
668 TextureVertex::set(ptr++, posRect.xDim - offsetRect.left, posRect.yDim - offsetRect.top, \
669 texCoordsRect.xDim, texCoordsRect.yDim)
670
Romain Guy03c00b52013-06-20 18:30:28 -0700671 /**
672 * This multi-draw operation builds a mesh on the stack by generating a quad
673 * for each bitmap in the batch. This method is also responsible for dirtying
674 * the current layer, if any.
675 */
Chris Craik527a3aa2013-03-04 10:19:31 -0800676 virtual status_t multiDraw(OpenGLRenderer& renderer, Rect& dirty,
Chris Craikc1c5f082013-09-11 16:23:37 -0700677 const Vector<OpStatePair>& ops, const Rect& bounds) {
678 const DeferredDisplayState& firstState = *(ops[0].state);
679 renderer.restoreDisplayState(firstState, true); // restore all but the clip
680
Chris Craik527a3aa2013-03-04 10:19:31 -0800681 TextureVertex vertices[6 * ops.size()];
682 TextureVertex* vertex = &vertices[0];
683
Romain Guy03c00b52013-06-20 18:30:28 -0700684 const bool hasLayer = renderer.hasLayer();
Chris Craik996fe652013-09-20 17:13:18 -0700685 bool pureTranslate = true;
Romain Guy2db5e992013-05-21 15:29:59 -0700686
Romain Guy3b748a42013-04-17 18:54:38 -0700687 // TODO: manually handle rect clip for bitmaps by adjusting texCoords per op,
688 // and allowing them to be merged in getBatchId()
Chris Craik527a3aa2013-03-04 10:19:31 -0800689 for (unsigned int i = 0; i < ops.size(); i++) {
Chris Craikc1c5f082013-09-11 16:23:37 -0700690 const DeferredDisplayState& state = *(ops[i].state);
691 const Rect& opBounds = state.mBounds;
Romain Guy2db5e992013-05-21 15:29:59 -0700692 // When we reach multiDraw(), the matrix can be either
693 // pureTranslate or simple (translate and/or scale).
694 // If the matrix is not pureTranslate, then we have a scale
Chris Craik996fe652013-09-20 17:13:18 -0700695 pureTranslate &= state.mMatrix.isPureTranslate();
Romain Guy3b748a42013-04-17 18:54:38 -0700696
697 Rect texCoords(0, 0, 1, 1);
Chris Craikc1c5f082013-09-11 16:23:37 -0700698 ((DrawBitmapOp*) ops[i].op)->mUvMapper.map(texCoords);
Romain Guy3b748a42013-04-17 18:54:38 -0700699
Chris Craik527a3aa2013-03-04 10:19:31 -0800700 SET_TEXTURE(vertex, opBounds, bounds, texCoords, left, top);
701 SET_TEXTURE(vertex, opBounds, bounds, texCoords, right, top);
702 SET_TEXTURE(vertex, opBounds, bounds, texCoords, left, bottom);
703
704 SET_TEXTURE(vertex, opBounds, bounds, texCoords, left, bottom);
705 SET_TEXTURE(vertex, opBounds, bounds, texCoords, right, top);
706 SET_TEXTURE(vertex, opBounds, bounds, texCoords, right, bottom);
Romain Guy03c00b52013-06-20 18:30:28 -0700707
708 if (hasLayer) {
Chris Craikc1c5f082013-09-11 16:23:37 -0700709 renderer.dirtyLayer(opBounds.left, opBounds.top, opBounds.right, opBounds.bottom);
Romain Guy03c00b52013-06-20 18:30:28 -0700710 }
Chris Craik527a3aa2013-03-04 10:19:31 -0800711 }
712
Romain Guy55b6f952013-06-27 15:27:09 -0700713 return renderer.drawBitmaps(mBitmap, mEntry, ops.size(), &vertices[0],
Chris Craik996fe652013-09-20 17:13:18 -0700714 pureTranslate, bounds, mPaint);
Chris Craik527a3aa2013-03-04 10:19:31 -0800715 }
716
Chris Craikc5493fb2013-06-19 16:58:58 -0700717 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800718 OP_LOG("Draw bitmap %p at %f %f", mBitmap, mLocalBounds.left, mLocalBounds.top);
719 }
720
721 virtual const char* name() { return "DrawBitmap"; }
Chris Craik527a3aa2013-03-04 10:19:31 -0800722
Chris Craikc1c5f082013-09-11 16:23:37 -0700723 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
724 const DeferredDisplayState& state) {
Chris Craik28ce94a2013-05-31 11:38:03 -0700725 deferInfo.batchId = DeferredDisplayList::kOpBatch_Bitmap;
Chris Craikd965bc52013-09-16 14:47:13 -0700726 deferInfo.mergeId = getAtlasEntry() ?
727 (mergeid_t) mEntry->getMergeId() : (mergeid_t) mBitmap;
Romain Guy2db5e992013-05-21 15:29:59 -0700728
Chris Craikd965bc52013-09-16 14:47:13 -0700729 // Don't merge non-simply transformed or neg scale ops, SET_TEXTURE doesn't handle rotation
Chris Craik28ce94a2013-05-31 11:38:03 -0700730 // Don't merge A8 bitmaps - the paint's color isn't compared by mergeId, or in
731 // MergingDrawBatch::canMergeWith()
732 // TODO: support clipped bitmaps by handling them in SET_TEXTURE
Chris Craikd965bc52013-09-16 14:47:13 -0700733 deferInfo.mergeable = state.mMatrix.isSimple() && state.mMatrix.positiveScale() &&
734 !state.mClipSideFlags &&
Chris Craik28ce94a2013-05-31 11:38:03 -0700735 OpenGLRenderer::getXfermodeDirect(mPaint) == SkXfermode::kSrcOver_Mode &&
Mike Reed1103b322014-07-08 12:36:44 -0400736 (mBitmap->colorType() != kAlpha_8_SkColorType);
Chris Craikc3566d02013-02-04 16:16:33 -0800737 }
Chris Craik2af46352012-11-26 18:30:17 -0800738
Chris Craik527a3aa2013-03-04 10:19:31 -0800739 const SkBitmap* bitmap() { return mBitmap; }
Chris Craik2af46352012-11-26 18:30:17 -0800740protected:
Chris Craikd218a922014-01-02 17:13:34 -0800741 const SkBitmap* mBitmap;
Romain Guy55b6f952013-06-27 15:27:09 -0700742 const AssetAtlas& mAtlas;
743 uint32_t mEntryGenerationId;
744 AssetAtlas::Entry* mEntry;
Romain Guy3b748a42013-04-17 18:54:38 -0700745 UvMapper mUvMapper;
Chris Craik2af46352012-11-26 18:30:17 -0800746};
747
Chris Craik2af46352012-11-26 18:30:17 -0800748class DrawBitmapRectOp : public DrawBoundedOp {
749public:
Chris Craikd218a922014-01-02 17:13:34 -0800750 DrawBitmapRectOp(const SkBitmap* bitmap,
751 float srcLeft, float srcTop, float srcRight, float srcBottom,
752 float dstLeft, float dstTop, float dstRight, float dstBottom, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -0800753 : DrawBoundedOp(dstLeft, dstTop, dstRight, dstBottom, paint),
754 mBitmap(bitmap), mSrc(srcLeft, srcTop, srcRight, srcBottom) {}
755
Chris Craik527a3aa2013-03-04 10:19:31 -0800756 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -0800757 return renderer.drawBitmap(mBitmap, mSrc.left, mSrc.top, mSrc.right, mSrc.bottom,
758 mLocalBounds.left, mLocalBounds.top, mLocalBounds.right, mLocalBounds.bottom,
759 getPaint(renderer));
760 }
761
Chris Craikc5493fb2013-06-19 16:58:58 -0700762 virtual void output(int level, uint32_t logFlags) const {
John Reckce444ca2014-06-02 15:12:36 -0700763 OP_LOG("Draw bitmap %p src=" RECT_STRING ", dst=" RECT_STRING,
Chris Craik2af46352012-11-26 18:30:17 -0800764 mBitmap, RECT_ARGS(mSrc), RECT_ARGS(mLocalBounds));
765 }
766
767 virtual const char* name() { return "DrawBitmapRect"; }
Chris Craik527a3aa2013-03-04 10:19:31 -0800768
Chris Craikc1c5f082013-09-11 16:23:37 -0700769 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
770 const DeferredDisplayState& state) {
Chris Craik28ce94a2013-05-31 11:38:03 -0700771 deferInfo.batchId = DeferredDisplayList::kOpBatch_Bitmap;
Chris Craikc3566d02013-02-04 16:16:33 -0800772 }
Chris Craik2af46352012-11-26 18:30:17 -0800773
774private:
Chris Craikd218a922014-01-02 17:13:34 -0800775 const SkBitmap* mBitmap;
Chris Craik2af46352012-11-26 18:30:17 -0800776 Rect mSrc;
777};
778
779class DrawBitmapDataOp : public DrawBitmapOp {
780public:
Chris Craik79647502014-08-06 13:42:24 -0700781 DrawBitmapDataOp(const SkBitmap* bitmap, const SkPaint* paint)
782 : DrawBitmapOp(bitmap, paint) {}
Chris Craik2af46352012-11-26 18:30:17 -0800783
Chris Craik527a3aa2013-03-04 10:19:31 -0800784 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik79647502014-08-06 13:42:24 -0700785 return renderer.drawBitmapData(mBitmap, getPaint(renderer));
Chris Craik2af46352012-11-26 18:30:17 -0800786 }
787
Chris Craikc5493fb2013-06-19 16:58:58 -0700788 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800789 OP_LOG("Draw bitmap %p", mBitmap);
790 }
791
792 virtual const char* name() { return "DrawBitmapData"; }
Chris Craik527a3aa2013-03-04 10:19:31 -0800793
Chris Craikc1c5f082013-09-11 16:23:37 -0700794 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
795 const DeferredDisplayState& state) {
Chris Craik28ce94a2013-05-31 11:38:03 -0700796 deferInfo.batchId = DeferredDisplayList::kOpBatch_Bitmap;
Chris Craikc3566d02013-02-04 16:16:33 -0800797 }
Chris Craik2af46352012-11-26 18:30:17 -0800798};
799
Chris Craik5d116762013-02-19 17:49:31 -0800800class DrawBitmapMeshOp : public DrawBoundedOp {
Chris Craik2af46352012-11-26 18:30:17 -0800801public:
Chris Craikd218a922014-01-02 17:13:34 -0800802 DrawBitmapMeshOp(const SkBitmap* bitmap, int meshWidth, int meshHeight,
803 const float* vertices, const int* colors, const SkPaint* paint)
Chris Craik5d116762013-02-19 17:49:31 -0800804 : DrawBoundedOp(vertices, 2 * (meshWidth + 1) * (meshHeight + 1), paint),
805 mBitmap(bitmap), mMeshWidth(meshWidth), mMeshHeight(meshHeight),
Chris Craik2af46352012-11-26 18:30:17 -0800806 mVertices(vertices), mColors(colors) {}
807
Chris Craik527a3aa2013-03-04 10:19:31 -0800808 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -0800809 return renderer.drawBitmapMesh(mBitmap, mMeshWidth, mMeshHeight,
810 mVertices, mColors, getPaint(renderer));
811 }
812
Chris Craikc5493fb2013-06-19 16:58:58 -0700813 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800814 OP_LOG("Draw bitmap %p mesh %d x %d", mBitmap, mMeshWidth, mMeshHeight);
815 }
816
817 virtual const char* name() { return "DrawBitmapMesh"; }
Chris Craik527a3aa2013-03-04 10:19:31 -0800818
Chris Craikc1c5f082013-09-11 16:23:37 -0700819 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
820 const DeferredDisplayState& state) {
Chris Craik28ce94a2013-05-31 11:38:03 -0700821 deferInfo.batchId = DeferredDisplayList::kOpBatch_Bitmap;
Chris Craikc3566d02013-02-04 16:16:33 -0800822 }
Chris Craik2af46352012-11-26 18:30:17 -0800823
824private:
Chris Craikd218a922014-01-02 17:13:34 -0800825 const SkBitmap* mBitmap;
Chris Craik2af46352012-11-26 18:30:17 -0800826 int mMeshWidth;
827 int mMeshHeight;
Chris Craikd218a922014-01-02 17:13:34 -0800828 const float* mVertices;
829 const int* mColors;
Chris Craik2af46352012-11-26 18:30:17 -0800830};
831
832class DrawPatchOp : public DrawBoundedOp {
833public:
Chris Craikd218a922014-01-02 17:13:34 -0800834 DrawPatchOp(const SkBitmap* bitmap, const Res_png_9patch* patch,
835 float left, float top, float right, float bottom, const SkPaint* paint)
Romain Guy03c00b52013-06-20 18:30:28 -0700836 : DrawBoundedOp(left, top, right, bottom, paint),
Romain Guy55b6f952013-06-27 15:27:09 -0700837 mBitmap(bitmap), mPatch(patch), mGenerationId(0), mMesh(NULL),
838 mAtlas(Caches::getInstance().assetAtlas) {
839 mEntry = mAtlas.getEntry(bitmap);
840 if (mEntry) {
841 mEntryGenerationId = mAtlas.getGenerationId();
842 }
Romain Guy3b748a42013-04-17 18:54:38 -0700843 };
Chris Craik2af46352012-11-26 18:30:17 -0800844
Romain Guy55b6f952013-06-27 15:27:09 -0700845 AssetAtlas::Entry* getAtlasEntry() {
846 // The atlas entry is stale, let's get a new one
847 if (mEntry && mEntryGenerationId != mAtlas.getGenerationId()) {
848 mEntryGenerationId = mAtlas.getGenerationId();
849 mEntry = mAtlas.getEntry(mBitmap);
850 }
851 return mEntry;
852 }
853
Romain Guy03c00b52013-06-20 18:30:28 -0700854 const Patch* getMesh(OpenGLRenderer& renderer) {
Romain Guy4c2547f2013-06-11 16:19:24 -0700855 if (!mMesh || renderer.getCaches().patchCache.getGenerationId() != mGenerationId) {
856 PatchCache& cache = renderer.getCaches().patchCache;
Romain Guy55b6f952013-06-27 15:27:09 -0700857 mMesh = cache.get(getAtlasEntry(), mBitmap->width(), mBitmap->height(),
Romain Guy03c00b52013-06-20 18:30:28 -0700858 mLocalBounds.getWidth(), mLocalBounds.getHeight(), mPatch);
Romain Guy4c2547f2013-06-11 16:19:24 -0700859 mGenerationId = cache.getGenerationId();
860 }
Romain Guy03c00b52013-06-20 18:30:28 -0700861 return mMesh;
862 }
863
864 /**
865 * This multi-draw operation builds an indexed mesh on the stack by copying
866 * and transforming the vertices of each 9-patch in the batch. This method
867 * is also responsible for dirtying the current layer, if any.
868 */
869 virtual status_t multiDraw(OpenGLRenderer& renderer, Rect& dirty,
Chris Craikc1c5f082013-09-11 16:23:37 -0700870 const Vector<OpStatePair>& ops, const Rect& bounds) {
871 const DeferredDisplayState& firstState = *(ops[0].state);
872 renderer.restoreDisplayState(firstState, true); // restore all but the clip
Romain Guy03c00b52013-06-20 18:30:28 -0700873
874 // Batches will usually contain a small number of items so it's
875 // worth performing a first iteration to count the exact number
876 // of vertices we need in the new mesh
877 uint32_t totalVertices = 0;
878 for (unsigned int i = 0; i < ops.size(); i++) {
Chris Craikc1c5f082013-09-11 16:23:37 -0700879 totalVertices += ((DrawPatchOp*) ops[i].op)->getMesh(renderer)->verticesCount;
Romain Guy03c00b52013-06-20 18:30:28 -0700880 }
881
882 const bool hasLayer = renderer.hasLayer();
883
884 uint32_t indexCount = 0;
885
886 TextureVertex vertices[totalVertices];
887 TextureVertex* vertex = &vertices[0];
888
889 // Create a mesh that contains the transformed vertices for all the
890 // 9-patch objects that are part of the batch. Note that onDefer()
891 // enforces ops drawn by this function to have a pure translate or
892 // identity matrix
893 for (unsigned int i = 0; i < ops.size(); i++) {
Chris Craikc1c5f082013-09-11 16:23:37 -0700894 DrawPatchOp* patchOp = (DrawPatchOp*) ops[i].op;
895 const DeferredDisplayState* state = ops[i].state;
Romain Guy03c00b52013-06-20 18:30:28 -0700896 const Patch* opMesh = patchOp->getMesh(renderer);
897 uint32_t vertexCount = opMesh->verticesCount;
898 if (vertexCount == 0) continue;
899
900 // We use the bounds to know where to translate our vertices
901 // Using patchOp->state.mBounds wouldn't work because these
902 // bounds are clipped
Chris Craikc1c5f082013-09-11 16:23:37 -0700903 const float tx = (int) floorf(state->mMatrix.getTranslateX() +
Romain Guy03c00b52013-06-20 18:30:28 -0700904 patchOp->mLocalBounds.left + 0.5f);
Chris Craikc1c5f082013-09-11 16:23:37 -0700905 const float ty = (int) floorf(state->mMatrix.getTranslateY() +
Romain Guy03c00b52013-06-20 18:30:28 -0700906 patchOp->mLocalBounds.top + 0.5f);
907
908 // Copy & transform all the vertices for the current operation
909 TextureVertex* opVertices = opMesh->vertices;
910 for (uint32_t j = 0; j < vertexCount; j++, opVertices++) {
911 TextureVertex::set(vertex++,
Romain Guy3380cfd2013-08-15 16:57:57 -0700912 opVertices->x + tx, opVertices->y + ty,
913 opVertices->u, opVertices->v);
Romain Guy03c00b52013-06-20 18:30:28 -0700914 }
915
916 // Dirty the current layer if possible. When the 9-patch does not
917 // contain empty quads we can take a shortcut and simply set the
918 // dirty rect to the object's bounds.
919 if (hasLayer) {
920 if (!opMesh->hasEmptyQuads) {
921 renderer.dirtyLayer(tx, ty,
922 tx + patchOp->mLocalBounds.getWidth(),
923 ty + patchOp->mLocalBounds.getHeight());
924 } else {
925 const size_t count = opMesh->quads.size();
926 for (size_t i = 0; i < count; i++) {
927 const Rect& quadBounds = opMesh->quads[i];
928 const float x = tx + quadBounds.left;
929 const float y = ty + quadBounds.top;
930 renderer.dirtyLayer(x, y,
931 x + quadBounds.getWidth(), y + quadBounds.getHeight());
932 }
933 }
934 }
935
936 indexCount += opMesh->indexCount;
937 }
938
Romain Guy55b6f952013-06-27 15:27:09 -0700939 return renderer.drawPatches(mBitmap, getAtlasEntry(),
940 &vertices[0], indexCount, getPaint(renderer));
Romain Guy03c00b52013-06-20 18:30:28 -0700941 }
942
943 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Romain Guy4c2547f2013-06-11 16:19:24 -0700944 // We're not calling the public variant of drawPatch() here
945 // This method won't perform the quickReject() since we've already done it at this point
Romain Guy55b6f952013-06-27 15:27:09 -0700946 return renderer.drawPatch(mBitmap, getMesh(renderer), getAtlasEntry(),
Romain Guy03c00b52013-06-20 18:30:28 -0700947 mLocalBounds.left, mLocalBounds.top, mLocalBounds.right, mLocalBounds.bottom,
948 getPaint(renderer));
Chris Craik2af46352012-11-26 18:30:17 -0800949 }
950
Chris Craikc5493fb2013-06-19 16:58:58 -0700951 virtual void output(int level, uint32_t logFlags) const {
John Reckce444ca2014-06-02 15:12:36 -0700952 OP_LOG("Draw patch " RECT_STRING, RECT_ARGS(mLocalBounds));
Chris Craik2af46352012-11-26 18:30:17 -0800953 }
954
955 virtual const char* name() { return "DrawPatch"; }
Chris Craik527a3aa2013-03-04 10:19:31 -0800956
Chris Craikc1c5f082013-09-11 16:23:37 -0700957 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
958 const DeferredDisplayState& state) {
Chris Craik28ce94a2013-05-31 11:38:03 -0700959 deferInfo.batchId = DeferredDisplayList::kOpBatch_Patch;
Romain Guy7f6d6b02013-08-06 13:49:28 -0700960 deferInfo.mergeId = getAtlasEntry() ? (mergeid_t) mEntry->getMergeId() : (mergeid_t) mBitmap;
Romain Guy03c00b52013-06-20 18:30:28 -0700961 deferInfo.mergeable = state.mMatrix.isPureTranslate() &&
962 OpenGLRenderer::getXfermodeDirect(mPaint) == SkXfermode::kSrcOver_Mode;
Chris Craikc1c5f082013-09-11 16:23:37 -0700963 deferInfo.opaqueOverBounds = isOpaqueOverBounds(state) && mBitmap->isOpaque();
Chris Craikc3566d02013-02-04 16:16:33 -0800964 }
Chris Craik2af46352012-11-26 18:30:17 -0800965
966private:
Chris Craikd218a922014-01-02 17:13:34 -0800967 const SkBitmap* mBitmap;
968 const Res_png_9patch* mPatch;
Romain Guy4c2547f2013-06-11 16:19:24 -0700969
Romain Guy4c2547f2013-06-11 16:19:24 -0700970 uint32_t mGenerationId;
971 const Patch* mMesh;
Romain Guy03c00b52013-06-20 18:30:28 -0700972
Romain Guy55b6f952013-06-27 15:27:09 -0700973 const AssetAtlas& mAtlas;
974 uint32_t mEntryGenerationId;
Romain Guy3b748a42013-04-17 18:54:38 -0700975 AssetAtlas::Entry* mEntry;
Chris Craik2af46352012-11-26 18:30:17 -0800976};
977
978class DrawColorOp : public DrawOp {
979public:
980 DrawColorOp(int color, SkXfermode::Mode mode)
Chris Craikf57776b2013-10-25 18:30:17 -0700981 : DrawOp(NULL), mColor(color), mMode(mode) {};
Chris Craik2af46352012-11-26 18:30:17 -0800982
Chris Craik527a3aa2013-03-04 10:19:31 -0800983 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -0800984 return renderer.drawColor(mColor, mMode);
985 }
986
Chris Craikc5493fb2013-06-19 16:58:58 -0700987 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -0800988 OP_LOG("Draw color %#x, mode %d", mColor, mMode);
989 }
990
991 virtual const char* name() { return "DrawColor"; }
992
993private:
994 int mColor;
995 SkXfermode::Mode mMode;
996};
997
998class DrawStrokableOp : public DrawBoundedOp {
999public:
Chris Craikd218a922014-01-02 17:13:34 -08001000 DrawStrokableOp(float left, float top, float right, float bottom, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001001 : DrawBoundedOp(left, top, right, bottom, paint) {};
1002
John Reckca1b3b82014-06-27 07:21:36 -07001003 virtual bool getLocalBounds(Rect& localBounds) {
Chris Craikc3566d02013-02-04 16:16:33 -08001004 localBounds.set(mLocalBounds);
Chris Craik2af46352012-11-26 18:30:17 -08001005 if (mPaint && mPaint->getStyle() != SkPaint::kFill_Style) {
Chris Craikc3566d02013-02-04 16:16:33 -08001006 localBounds.outset(strokeWidthOutset());
Chris Craik2af46352012-11-26 18:30:17 -08001007 }
1008 return true;
1009 }
Chris Craikc3566d02013-02-04 16:16:33 -08001010
Chris Craikc1c5f082013-09-11 16:23:37 -07001011 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
1012 const DeferredDisplayState& state) {
Chris Craikc3566d02013-02-04 16:16:33 -08001013 if (mPaint->getPathEffect()) {
Chris Craik28ce94a2013-05-31 11:38:03 -07001014 deferInfo.batchId = DeferredDisplayList::kOpBatch_AlphaMaskTexture;
Chris Craik527a3aa2013-03-04 10:19:31 -08001015 } else {
Chris Craik28ce94a2013-05-31 11:38:03 -07001016 deferInfo.batchId = mPaint->isAntiAlias() ?
Chris Craik527a3aa2013-03-04 10:19:31 -08001017 DeferredDisplayList::kOpBatch_AlphaVertices :
1018 DeferredDisplayList::kOpBatch_Vertices;
Chris Craikc3566d02013-02-04 16:16:33 -08001019 }
Chris Craikc3566d02013-02-04 16:16:33 -08001020 }
Chris Craik2af46352012-11-26 18:30:17 -08001021};
1022
1023class DrawRectOp : public DrawStrokableOp {
1024public:
Chris Craikd218a922014-01-02 17:13:34 -08001025 DrawRectOp(float left, float top, float right, float bottom, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001026 : DrawStrokableOp(left, top, right, bottom, paint) {}
1027
Chris Craik527a3aa2013-03-04 10:19:31 -08001028 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001029 return renderer.drawRect(mLocalBounds.left, mLocalBounds.top,
1030 mLocalBounds.right, mLocalBounds.bottom, getPaint(renderer));
1031 }
1032
Chris Craikc5493fb2013-06-19 16:58:58 -07001033 virtual void output(int level, uint32_t logFlags) const {
John Reckce444ca2014-06-02 15:12:36 -07001034 OP_LOG("Draw Rect " RECT_STRING, RECT_ARGS(mLocalBounds));
Chris Craik2af46352012-11-26 18:30:17 -08001035 }
1036
Chris Craikc1c5f082013-09-11 16:23:37 -07001037 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
1038 const DeferredDisplayState& state) {
1039 DrawStrokableOp::onDefer(renderer, deferInfo, state);
1040 deferInfo.opaqueOverBounds = isOpaqueOverBounds(state) &&
Chris Craik28ce94a2013-05-31 11:38:03 -07001041 mPaint->getStyle() == SkPaint::kFill_Style;
1042 }
1043
Chris Craik2af46352012-11-26 18:30:17 -08001044 virtual const char* name() { return "DrawRect"; }
1045};
1046
Chris Craik5d116762013-02-19 17:49:31 -08001047class DrawRectsOp : public DrawBoundedOp {
Chris Craik2af46352012-11-26 18:30:17 -08001048public:
Chris Craikd218a922014-01-02 17:13:34 -08001049 DrawRectsOp(const float* rects, int count, const SkPaint* paint)
Chris Craik5d116762013-02-19 17:49:31 -08001050 : DrawBoundedOp(rects, count, paint),
1051 mRects(rects), mCount(count) {}
Chris Craik2af46352012-11-26 18:30:17 -08001052
Chris Craik527a3aa2013-03-04 10:19:31 -08001053 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001054 return renderer.drawRects(mRects, mCount, getPaint(renderer));
1055 }
1056
Chris Craikc5493fb2013-06-19 16:58:58 -07001057 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001058 OP_LOG("Draw Rects count %d", mCount);
1059 }
1060
1061 virtual const char* name() { return "DrawRects"; }
1062
Chris Craikc1c5f082013-09-11 16:23:37 -07001063 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
1064 const DeferredDisplayState& state) {
Chris Craik28ce94a2013-05-31 11:38:03 -07001065 deferInfo.batchId = DeferredDisplayList::kOpBatch_Vertices;
Chris Craikc3566d02013-02-04 16:16:33 -08001066 }
1067
Chris Craik2af46352012-11-26 18:30:17 -08001068private:
1069 const float* mRects;
1070 int mCount;
1071};
1072
1073class DrawRoundRectOp : public DrawStrokableOp {
1074public:
1075 DrawRoundRectOp(float left, float top, float right, float bottom,
Chris Craikd218a922014-01-02 17:13:34 -08001076 float rx, float ry, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001077 : DrawStrokableOp(left, top, right, bottom, paint), mRx(rx), mRy(ry) {}
1078
Chris Craik527a3aa2013-03-04 10:19:31 -08001079 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001080 return renderer.drawRoundRect(mLocalBounds.left, mLocalBounds.top,
1081 mLocalBounds.right, mLocalBounds.bottom, mRx, mRy, getPaint(renderer));
1082 }
1083
Chris Craikc5493fb2013-06-19 16:58:58 -07001084 virtual void output(int level, uint32_t logFlags) const {
John Reckce444ca2014-06-02 15:12:36 -07001085 OP_LOG("Draw RoundRect " RECT_STRING ", rx %f, ry %f", RECT_ARGS(mLocalBounds), mRx, mRy);
Chris Craik2af46352012-11-26 18:30:17 -08001086 }
1087
Chris Craik05f3d6e2014-06-02 16:27:04 -07001088 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
1089 const DeferredDisplayState& state) {
1090 DrawStrokableOp::onDefer(renderer, deferInfo, state);
1091 if (!mPaint->getPathEffect()) {
Chris Craik6ac174b2014-06-17 13:47:05 -07001092 renderer.getCaches().tessellationCache.precacheRoundRect(state.mMatrix, *mPaint,
1093 mLocalBounds.getWidth(), mLocalBounds.getHeight(), mRx, mRy);
Chris Craik05f3d6e2014-06-02 16:27:04 -07001094 }
1095 }
1096
Chris Craik2af46352012-11-26 18:30:17 -08001097 virtual const char* name() { return "DrawRoundRect"; }
1098
1099private:
1100 float mRx;
1101 float mRy;
1102};
1103
1104class DrawCircleOp : public DrawStrokableOp {
1105public:
Chris Craikd218a922014-01-02 17:13:34 -08001106 DrawCircleOp(float x, float y, float radius, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001107 : DrawStrokableOp(x - radius, y - radius, x + radius, y + radius, paint),
1108 mX(x), mY(y), mRadius(radius) {}
1109
Chris Craik527a3aa2013-03-04 10:19:31 -08001110 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001111 return renderer.drawCircle(mX, mY, mRadius, getPaint(renderer));
1112 }
1113
Chris Craikc5493fb2013-06-19 16:58:58 -07001114 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001115 OP_LOG("Draw Circle x %f, y %f, r %f", mX, mY, mRadius);
1116 }
1117
1118 virtual const char* name() { return "DrawCircle"; }
1119
1120private:
1121 float mX;
1122 float mY;
1123 float mRadius;
1124};
1125
John Reck52244ff2014-05-01 21:27:37 -07001126class DrawCirclePropsOp : public DrawOp {
1127public:
1128 DrawCirclePropsOp(float* x, float* y, float* radius, const SkPaint* paint)
1129 : DrawOp(paint), mX(x), mY(y), mRadius(radius) {}
1130
1131 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
1132 return renderer.drawCircle(*mX, *mY, *mRadius, getPaint(renderer));
1133 }
1134
1135 virtual void output(int level, uint32_t logFlags) const {
1136 OP_LOG("Draw Circle Props x %p, y %p, r %p", mX, mY, mRadius);
1137 }
1138
1139 virtual const char* name() { return "DrawCircleProps"; }
1140
1141private:
1142 float* mX;
1143 float* mY;
1144 float* mRadius;
1145};
1146
Chris Craik2af46352012-11-26 18:30:17 -08001147class DrawOvalOp : public DrawStrokableOp {
1148public:
Chris Craikd218a922014-01-02 17:13:34 -08001149 DrawOvalOp(float left, float top, float right, float bottom, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001150 : DrawStrokableOp(left, top, right, bottom, paint) {}
1151
Chris Craik527a3aa2013-03-04 10:19:31 -08001152 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001153 return renderer.drawOval(mLocalBounds.left, mLocalBounds.top,
1154 mLocalBounds.right, mLocalBounds.bottom, getPaint(renderer));
1155 }
1156
Chris Craikc5493fb2013-06-19 16:58:58 -07001157 virtual void output(int level, uint32_t logFlags) const {
John Reckce444ca2014-06-02 15:12:36 -07001158 OP_LOG("Draw Oval " RECT_STRING, RECT_ARGS(mLocalBounds));
Chris Craik2af46352012-11-26 18:30:17 -08001159 }
1160
1161 virtual const char* name() { return "DrawOval"; }
1162};
1163
1164class DrawArcOp : public DrawStrokableOp {
1165public:
1166 DrawArcOp(float left, float top, float right, float bottom,
Chris Craikd218a922014-01-02 17:13:34 -08001167 float startAngle, float sweepAngle, bool useCenter, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001168 : DrawStrokableOp(left, top, right, bottom, paint),
1169 mStartAngle(startAngle), mSweepAngle(sweepAngle), mUseCenter(useCenter) {}
1170
Chris Craik527a3aa2013-03-04 10:19:31 -08001171 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001172 return renderer.drawArc(mLocalBounds.left, mLocalBounds.top,
1173 mLocalBounds.right, mLocalBounds.bottom,
1174 mStartAngle, mSweepAngle, mUseCenter, getPaint(renderer));
1175 }
1176
Chris Craikc5493fb2013-06-19 16:58:58 -07001177 virtual void output(int level, uint32_t logFlags) const {
John Reckce444ca2014-06-02 15:12:36 -07001178 OP_LOG("Draw Arc " RECT_STRING ", start %f, sweep %f, useCenter %d",
Chris Craik2af46352012-11-26 18:30:17 -08001179 RECT_ARGS(mLocalBounds), mStartAngle, mSweepAngle, mUseCenter);
1180 }
1181
1182 virtual const char* name() { return "DrawArc"; }
1183
1184private:
1185 float mStartAngle;
1186 float mSweepAngle;
1187 bool mUseCenter;
1188};
1189
1190class DrawPathOp : public DrawBoundedOp {
1191public:
Chris Craikd218a922014-01-02 17:13:34 -08001192 DrawPathOp(const SkPath* path, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001193 : DrawBoundedOp(paint), mPath(path) {
1194 float left, top, offset;
1195 uint32_t width, height;
Romain Guyca89e2a2013-03-08 17:44:20 -08001196 PathCache::computePathBounds(path, paint, left, top, offset, width, height);
Chris Craik2af46352012-11-26 18:30:17 -08001197 left -= offset;
1198 top -= offset;
1199 mLocalBounds.set(left, top, left + width, top + height);
1200 }
1201
Chris Craik527a3aa2013-03-04 10:19:31 -08001202 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001203 return renderer.drawPath(mPath, getPaint(renderer));
1204 }
1205
Chris Craikc1c5f082013-09-11 16:23:37 -07001206 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
1207 const DeferredDisplayState& state) {
Chris Craikd218a922014-01-02 17:13:34 -08001208 const SkPaint* paint = getPaint(renderer);
Romain Guyca89e2a2013-03-08 17:44:20 -08001209 renderer.getCaches().pathCache.precache(mPath, paint);
Chris Craik527a3aa2013-03-04 10:19:31 -08001210
Chris Craik28ce94a2013-05-31 11:38:03 -07001211 deferInfo.batchId = DeferredDisplayList::kOpBatch_AlphaMaskTexture;
Romain Guyca89e2a2013-03-08 17:44:20 -08001212 }
1213
Chris Craikc5493fb2013-06-19 16:58:58 -07001214 virtual void output(int level, uint32_t logFlags) const {
John Reckce444ca2014-06-02 15:12:36 -07001215 OP_LOG("Draw Path %p in " RECT_STRING, mPath, RECT_ARGS(mLocalBounds));
Chris Craik2af46352012-11-26 18:30:17 -08001216 }
1217
1218 virtual const char* name() { return "DrawPath"; }
1219
1220private:
Chris Craikd218a922014-01-02 17:13:34 -08001221 const SkPath* mPath;
Chris Craik2af46352012-11-26 18:30:17 -08001222};
1223
Chris Craikc3566d02013-02-04 16:16:33 -08001224class DrawLinesOp : public DrawBoundedOp {
Chris Craik2af46352012-11-26 18:30:17 -08001225public:
Chris Craikd218a922014-01-02 17:13:34 -08001226 DrawLinesOp(const float* points, int count, const SkPaint* paint)
Chris Craik5d116762013-02-19 17:49:31 -08001227 : DrawBoundedOp(points, count, paint),
1228 mPoints(points), mCount(count) {
Chris Craikc3566d02013-02-04 16:16:33 -08001229 mLocalBounds.outset(strokeWidthOutset());
Chris Craik2af46352012-11-26 18:30:17 -08001230 }
1231
Chris Craik527a3aa2013-03-04 10:19:31 -08001232 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001233 return renderer.drawLines(mPoints, mCount, getPaint(renderer));
1234 }
1235
Chris Craikc5493fb2013-06-19 16:58:58 -07001236 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001237 OP_LOG("Draw Lines count %d", mCount);
1238 }
1239
1240 virtual const char* name() { return "DrawLines"; }
1241
Chris Craikc1c5f082013-09-11 16:23:37 -07001242 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
1243 const DeferredDisplayState& state) {
Chris Craik28ce94a2013-05-31 11:38:03 -07001244 deferInfo.batchId = mPaint->isAntiAlias() ?
Chris Craikc3566d02013-02-04 16:16:33 -08001245 DeferredDisplayList::kOpBatch_AlphaVertices :
1246 DeferredDisplayList::kOpBatch_Vertices;
1247 }
1248
Chris Craik2af46352012-11-26 18:30:17 -08001249protected:
Chris Craikd218a922014-01-02 17:13:34 -08001250 const float* mPoints;
Chris Craik2af46352012-11-26 18:30:17 -08001251 int mCount;
1252};
1253
1254class DrawPointsOp : public DrawLinesOp {
1255public:
Chris Craikd218a922014-01-02 17:13:34 -08001256 DrawPointsOp(const float* points, int count, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001257 : DrawLinesOp(points, count, paint) {}
1258
Chris Craik527a3aa2013-03-04 10:19:31 -08001259 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001260 return renderer.drawPoints(mPoints, mCount, getPaint(renderer));
1261 }
1262
Chris Craikc5493fb2013-06-19 16:58:58 -07001263 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001264 OP_LOG("Draw Points count %d", mCount);
1265 }
1266
1267 virtual const char* name() { return "DrawPoints"; }
1268};
1269
1270class DrawSomeTextOp : public DrawOp {
1271public:
Chris Craikd218a922014-01-02 17:13:34 -08001272 DrawSomeTextOp(const char* text, int bytesCount, int count, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001273 : DrawOp(paint), mText(text), mBytesCount(bytesCount), mCount(count) {};
1274
Chris Craikc5493fb2013-06-19 16:58:58 -07001275 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001276 OP_LOG("Draw some text, %d bytes", mBytesCount);
1277 }
Chris Craikc3566d02013-02-04 16:16:33 -08001278
Derek Sollenbergerc29a0a42014-03-31 13:52:39 -04001279 virtual bool hasTextShadow() const {
1280 return OpenGLRenderer::hasTextShadow(mPaint);
1281 }
1282
Chris Craikc1c5f082013-09-11 16:23:37 -07001283 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
1284 const DeferredDisplayState& state) {
Chris Craikd218a922014-01-02 17:13:34 -08001285 const SkPaint* paint = getPaint(renderer);
Romain Guy0f667532013-03-01 14:31:04 -08001286 FontRenderer& fontRenderer = renderer.getCaches().fontRenderer->getFontRenderer(paint);
Chris Craik59744b72014-07-01 17:56:52 -07001287 fontRenderer.precache(paint, mText, mCount, SkMatrix::I());
Romain Guy0f667532013-03-01 14:31:04 -08001288
Chris Craik98d608d2014-07-17 12:25:11 -07001289 deferInfo.batchId = mPaint->getColor() == SK_ColorBLACK ?
Chris Craikc3566d02013-02-04 16:16:33 -08001290 DeferredDisplayList::kOpBatch_Text :
1291 DeferredDisplayList::kOpBatch_ColorText;
1292 }
Chris Craik527a3aa2013-03-04 10:19:31 -08001293
Chris Craik2af46352012-11-26 18:30:17 -08001294protected:
1295 const char* mText;
1296 int mBytesCount;
1297 int mCount;
1298};
1299
1300class DrawTextOnPathOp : public DrawSomeTextOp {
1301public:
1302 DrawTextOnPathOp(const char* text, int bytesCount, int count,
Chris Craikd218a922014-01-02 17:13:34 -08001303 const SkPath* path, float hOffset, float vOffset, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001304 : DrawSomeTextOp(text, bytesCount, count, paint),
1305 mPath(path), mHOffset(hOffset), mVOffset(vOffset) {
1306 /* TODO: inherit from DrawBounded and init mLocalBounds */
1307 }
1308
Chris Craik527a3aa2013-03-04 10:19:31 -08001309 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001310 return renderer.drawTextOnPath(mText, mBytesCount, mCount, mPath,
1311 mHOffset, mVOffset, getPaint(renderer));
1312 }
1313
1314 virtual const char* name() { return "DrawTextOnPath"; }
1315
1316private:
Chris Craikd218a922014-01-02 17:13:34 -08001317 const SkPath* mPath;
Chris Craik2af46352012-11-26 18:30:17 -08001318 float mHOffset;
1319 float mVOffset;
1320};
1321
1322class DrawPosTextOp : public DrawSomeTextOp {
1323public:
1324 DrawPosTextOp(const char* text, int bytesCount, int count,
Chris Craikd218a922014-01-02 17:13:34 -08001325 const float* positions, const SkPaint* paint)
Chris Craik2af46352012-11-26 18:30:17 -08001326 : DrawSomeTextOp(text, bytesCount, count, paint), mPositions(positions) {
1327 /* TODO: inherit from DrawBounded and init mLocalBounds */
1328 }
1329
Chris Craik527a3aa2013-03-04 10:19:31 -08001330 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001331 return renderer.drawPosText(mText, mBytesCount, mCount, mPositions, getPaint(renderer));
1332 }
1333
1334 virtual const char* name() { return "DrawPosText"; }
1335
1336private:
1337 const float* mPositions;
1338};
1339
1340class DrawTextOp : public DrawBoundedOp {
1341public:
1342 DrawTextOp(const char* text, int bytesCount, int count, float x, float y,
Chris Craikd218a922014-01-02 17:13:34 -08001343 const float* positions, const SkPaint* paint, float totalAdvance, const Rect& bounds)
Chris Craik41541822013-05-03 16:35:54 -07001344 : DrawBoundedOp(bounds, paint), mText(text), mBytesCount(bytesCount), mCount(count),
1345 mX(x), mY(y), mPositions(positions), mTotalAdvance(totalAdvance) {
Chris Craik59744b72014-07-01 17:56:52 -07001346 mPrecacheTransform = SkMatrix::InvalidMatrix();
Chris Craik2af46352012-11-26 18:30:17 -08001347 }
1348
Chris Craikc1c5f082013-09-11 16:23:37 -07001349 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
1350 const DeferredDisplayState& state) {
Chris Craikd218a922014-01-02 17:13:34 -08001351 const SkPaint* paint = getPaint(renderer);
Romain Guy0f667532013-03-01 14:31:04 -08001352 FontRenderer& fontRenderer = renderer.getCaches().fontRenderer->getFontRenderer(paint);
Chris Craik59744b72014-07-01 17:56:52 -07001353 SkMatrix transform;
1354 renderer.findBestFontTransform(state.mMatrix, &transform);
Romain Guybd3055f2013-03-13 16:14:47 -07001355 if (mPrecacheTransform != transform) {
1356 fontRenderer.precache(paint, mText, mCount, transform);
1357 mPrecacheTransform = transform;
1358 }
Chris Craik98d608d2014-07-17 12:25:11 -07001359 deferInfo.batchId = mPaint->getColor() == SK_ColorBLACK ?
Chris Craik527a3aa2013-03-04 10:19:31 -08001360 DeferredDisplayList::kOpBatch_Text :
1361 DeferredDisplayList::kOpBatch_ColorText;
1362
Kévin PETIT73fc5582014-02-13 11:03:40 +00001363 deferInfo.mergeId = reinterpret_cast<mergeid_t>(mPaint->getColor());
Chris Craik527a3aa2013-03-04 10:19:31 -08001364
1365 // don't merge decorated text - the decorations won't draw in order
Chris Craik98d608d2014-07-17 12:25:11 -07001366 bool hasDecorations = mPaint->getFlags()
1367 & (SkPaint::kUnderlineText_Flag | SkPaint::kStrikeThruText_Flag);
1368
1369 deferInfo.mergeable = state.mMatrix.isPureTranslate()
1370 && !hasDecorations
1371 && OpenGLRenderer::getXfermodeDirect(mPaint) == SkXfermode::kSrcOver_Mode;
Romain Guy0f667532013-03-01 14:31:04 -08001372 }
1373
Chris Craik527a3aa2013-03-04 10:19:31 -08001374 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Romain Guy9b5a1a22013-08-09 14:06:29 -07001375 Rect bounds;
John Reck3b202512014-06-23 13:13:08 -07001376 getLocalBounds(bounds);
Chris Craik2af46352012-11-26 18:30:17 -08001377 return renderer.drawText(mText, mBytesCount, mCount, mX, mY,
Romain Guy9b5a1a22013-08-09 14:06:29 -07001378 mPositions, getPaint(renderer), mTotalAdvance, bounds);
Chris Craik2af46352012-11-26 18:30:17 -08001379 }
1380
Chris Craik527a3aa2013-03-04 10:19:31 -08001381 virtual status_t multiDraw(OpenGLRenderer& renderer, Rect& dirty,
Chris Craikc1c5f082013-09-11 16:23:37 -07001382 const Vector<OpStatePair>& ops, const Rect& bounds) {
Chris Craik527a3aa2013-03-04 10:19:31 -08001383 status_t status = DrawGlInfo::kStatusDone;
Chris Craik527a3aa2013-03-04 10:19:31 -08001384 for (unsigned int i = 0; i < ops.size(); i++) {
Chris Craikc1c5f082013-09-11 16:23:37 -07001385 const DeferredDisplayState& state = *(ops[i].state);
Chris Craik527a3aa2013-03-04 10:19:31 -08001386 DrawOpMode drawOpMode = (i == ops.size() - 1) ? kDrawOpMode_Flush : kDrawOpMode_Defer;
Chris Craikc1c5f082013-09-11 16:23:37 -07001387 renderer.restoreDisplayState(state, true); // restore all but the clip
Chris Craik527a3aa2013-03-04 10:19:31 -08001388
Chris Craikc1c5f082013-09-11 16:23:37 -07001389 DrawTextOp& op = *((DrawTextOp*)ops[i].op);
Romain Guy9b5a1a22013-08-09 14:06:29 -07001390 // quickReject() will not occure in drawText() so we can use mLocalBounds
1391 // directly, we do not need to account for shadow by calling getLocalBounds()
Chris Craik527a3aa2013-03-04 10:19:31 -08001392 status |= renderer.drawText(op.mText, op.mBytesCount, op.mCount, op.mX, op.mY,
Chris Craik41541822013-05-03 16:35:54 -07001393 op.mPositions, op.getPaint(renderer), op.mTotalAdvance, op.mLocalBounds,
1394 drawOpMode);
Chris Craik527a3aa2013-03-04 10:19:31 -08001395 }
1396 return status;
1397 }
1398
Chris Craikc5493fb2013-06-19 16:58:58 -07001399 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001400 OP_LOG("Draw Text of count %d, bytes %d", mCount, mBytesCount);
1401 }
1402
1403 virtual const char* name() { return "DrawText"; }
1404
1405private:
1406 const char* mText;
1407 int mBytesCount;
1408 int mCount;
1409 float mX;
1410 float mY;
1411 const float* mPositions;
Chris Craik41541822013-05-03 16:35:54 -07001412 float mTotalAdvance;
Chris Craik59744b72014-07-01 17:56:52 -07001413 SkMatrix mPrecacheTransform;
Chris Craik2af46352012-11-26 18:30:17 -08001414};
1415
1416///////////////////////////////////////////////////////////////////////////////
1417// SPECIAL DRAW OPERATIONS
1418///////////////////////////////////////////////////////////////////////////////
1419
1420class DrawFunctorOp : public DrawOp {
1421public:
1422 DrawFunctorOp(Functor* functor)
Chris Craikf57776b2013-10-25 18:30:17 -07001423 : DrawOp(NULL), mFunctor(functor) {}
Chris Craik2af46352012-11-26 18:30:17 -08001424
Chris Craik527a3aa2013-03-04 10:19:31 -08001425 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik2af46352012-11-26 18:30:17 -08001426 renderer.startMark("GL functor");
1427 status_t ret = renderer.callDrawGLFunction(mFunctor, dirty);
1428 renderer.endMark();
1429 return ret;
1430 }
1431
Chris Craikc5493fb2013-06-19 16:58:58 -07001432 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001433 OP_LOG("Draw Functor %p", mFunctor);
1434 }
1435
1436 virtual const char* name() { return "DrawFunctor"; }
1437
1438private:
1439 Functor* mFunctor;
1440};
1441
Chris Craika7090e02014-06-20 16:01:00 -07001442class DrawRenderNodeOp : public DrawBoundedOp {
1443 friend class RenderNode; // grant RenderNode access to info of child
Chris Craik2af46352012-11-26 18:30:17 -08001444public:
Chris Craika7090e02014-06-20 16:01:00 -07001445 DrawRenderNodeOp(RenderNode* renderNode, int flags, const mat4& transformFromParent)
1446 : DrawBoundedOp(0, 0, renderNode->getWidth(), renderNode->getHeight(), 0),
1447 mRenderNode(renderNode), mFlags(flags), mTransformFromParent(transformFromParent) {}
Chris Craikc3566d02013-02-04 16:16:33 -08001448
Chet Haasedd671592013-04-19 14:54:34 -07001449 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
1450 bool useQuickReject) {
Chris Craika7090e02014-06-20 16:01:00 -07001451 if (mRenderNode && mRenderNode->isRenderable() && !mSkipInOrderDraw) {
1452 mRenderNode->defer(deferStruct, level + 1);
Chris Craikc3566d02013-02-04 16:16:33 -08001453 }
Chris Craikc3566d02013-02-04 16:16:33 -08001454 }
Chet Haasedd671592013-04-19 14:54:34 -07001455 virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level,
1456 bool useQuickReject) {
Chris Craika7090e02014-06-20 16:01:00 -07001457 if (mRenderNode && mRenderNode->isRenderable() && !mSkipInOrderDraw) {
1458 mRenderNode->replay(replayStruct, level + 1);
Chris Craikff785832013-03-08 13:12:16 -08001459 }
1460 }
Chris Craik2af46352012-11-26 18:30:17 -08001461
Chris Craik527a3aa2013-03-04 10:19:31 -08001462 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik80d49022014-06-20 15:03:43 -07001463 LOG_ALWAYS_FATAL("should not be called, because replay() is overridden");
1464 return 0;
Chris Craika08f95c2013-03-15 17:24:33 -07001465 }
Chris Craikff785832013-03-08 13:12:16 -08001466
Chris Craikc5493fb2013-06-19 16:58:58 -07001467 virtual void output(int level, uint32_t logFlags) const {
Chris Craika7090e02014-06-20 16:01:00 -07001468 OP_LOG("Draw Display List %p, flags %#x", mRenderNode, mFlags);
1469 if (mRenderNode && (logFlags & kOpLogFlag_Recurse)) {
1470 mRenderNode->output(level + 1);
Chris Craik2af46352012-11-26 18:30:17 -08001471 }
1472 }
1473
Chris Craika7090e02014-06-20 16:01:00 -07001474 virtual const char* name() { return "DrawRenderNode"; }
Chris Craik2af46352012-11-26 18:30:17 -08001475
Chris Craika7090e02014-06-20 16:01:00 -07001476 RenderNode* renderNode() { return mRenderNode; }
John Reck087bc0c2014-04-04 16:20:08 -07001477
Chris Craik2af46352012-11-26 18:30:17 -08001478private:
Chris Craika7090e02014-06-20 16:01:00 -07001479 RenderNode* mRenderNode;
Chris Craikf57776b2013-10-25 18:30:17 -07001480 const int mFlags;
1481
1482 ///////////////////////////
Chris Craika7090e02014-06-20 16:01:00 -07001483 // Properties below are used by RenderNode::computeOrderingImpl() and issueOperations()
Chris Craikf57776b2013-10-25 18:30:17 -07001484 ///////////////////////////
1485 /**
1486 * Records transform vs parent, used for computing total transform without rerunning DL contents
1487 */
1488 const mat4 mTransformFromParent;
1489
1490 /**
Chris Craika7090e02014-06-20 16:01:00 -07001491 * Holds the transformation between the projection surface ViewGroup and this RenderNode
Chris Craikb79a3e32014-03-11 12:20:17 -07001492 * drawing instance. Represents any translations / transformations done within the drawing of
1493 * the compositing ancestor ViewGroup's draw, before the draw of the View represented by this
1494 * DisplayList draw instance.
Chris Craikf57776b2013-10-25 18:30:17 -07001495 *
Chris Craika7090e02014-06-20 16:01:00 -07001496 * Note: doesn't include transformation within the RenderNode, or its properties.
Chris Craikf57776b2013-10-25 18:30:17 -07001497 */
Chris Craikf533e942014-01-14 22:35:37 -08001498 mat4 mTransformFromCompositingAncestor;
Chris Craikf57776b2013-10-25 18:30:17 -07001499 bool mSkipInOrderDraw;
1500};
1501
1502/**
Chris Craik024433f2014-03-26 13:19:14 -07001503 * Not a canvas operation, used only by 3d / z ordering logic in RenderNode::iterate()
Chris Craikf57776b2013-10-25 18:30:17 -07001504 */
1505class DrawShadowOp : public DrawOp {
1506public:
Chris Craik024433f2014-03-26 13:19:14 -07001507 DrawShadowOp(const mat4& transformXY, const mat4& transformZ,
Chris Craik74669862014-08-07 17:27:30 -07001508 float casterAlpha, const SkPath* casterOutline)
1509 : DrawOp(NULL)
1510 , mTransformXY(transformXY)
1511 , mTransformZ(transformZ)
1512 , mCasterAlpha(casterAlpha)
1513 , mCasterOutline(casterOutline) {
Chris Craik61317322014-05-21 13:03:52 -07001514 }
Chris Craikf57776b2013-10-25 18:30:17 -07001515
Chris Craik05f3d6e2014-06-02 16:27:04 -07001516 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
1517 const DeferredDisplayState& state) {
1518 renderer.getCaches().tessellationCache.precacheShadows(&state.mMatrix,
Chris Craik74669862014-08-07 17:27:30 -07001519 renderer.getLocalClipBounds(), isCasterOpaque(), mCasterOutline,
Chris Craik05f3d6e2014-06-02 16:27:04 -07001520 &mTransformXY, &mTransformZ, renderer.getLightCenter(), renderer.getLightRadius());
1521 }
1522
Chris Craikf57776b2013-10-25 18:30:17 -07001523 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craik05f3d6e2014-06-02 16:27:04 -07001524 TessellationCache::vertexBuffer_pair_t buffers;
1525 Matrix4 drawTransform;
1526 renderer.getMatrix(&drawTransform);
1527 renderer.getCaches().tessellationCache.getShadowBuffers(&drawTransform,
Chris Craik74669862014-08-07 17:27:30 -07001528 renderer.getLocalClipBounds(), isCasterOpaque(), mCasterOutline,
Chris Craik05f3d6e2014-06-02 16:27:04 -07001529 &mTransformXY, &mTransformZ, renderer.getLightCenter(), renderer.getLightRadius(),
1530 buffers);
1531
1532 return renderer.drawShadow(mCasterAlpha, buffers.first, buffers.second);
Chris Craikf57776b2013-10-25 18:30:17 -07001533 }
1534
1535 virtual void output(int level, uint32_t logFlags) const {
Chris Craik61317322014-05-21 13:03:52 -07001536 OP_LOGS("DrawShadow");
Chris Craikf57776b2013-10-25 18:30:17 -07001537 }
1538
1539 virtual const char* name() { return "DrawShadow"; }
1540
1541private:
Chris Craikaf4d04c2014-07-29 12:50:14 -07001542 bool isCasterOpaque() { return mCasterAlpha >= 1.0f; }
Chris Craik05f3d6e2014-06-02 16:27:04 -07001543
Chris Craikb79a3e32014-03-11 12:20:17 -07001544 const mat4 mTransformXY;
1545 const mat4 mTransformZ;
Chris Craik024433f2014-03-26 13:19:14 -07001546 const float mCasterAlpha;
Chris Craik74669862014-08-07 17:27:30 -07001547 const SkPath* mCasterOutline;
Chris Craik2af46352012-11-26 18:30:17 -08001548};
1549
1550class DrawLayerOp : public DrawOp {
1551public:
Chris Craika08f95c2013-03-15 17:24:33 -07001552 DrawLayerOp(Layer* layer, float x, float y)
Chris Craikf57776b2013-10-25 18:30:17 -07001553 : DrawOp(NULL), mLayer(layer), mX(x), mY(y) {}
Chris Craik2af46352012-11-26 18:30:17 -08001554
Chris Craik527a3aa2013-03-04 10:19:31 -08001555 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
Chris Craika08f95c2013-03-15 17:24:33 -07001556 return renderer.drawLayer(mLayer, mX, mY);
Chris Craik2af46352012-11-26 18:30:17 -08001557 }
1558
Chris Craikc5493fb2013-06-19 16:58:58 -07001559 virtual void output(int level, uint32_t logFlags) const {
Chris Craik2af46352012-11-26 18:30:17 -08001560 OP_LOG("Draw Layer %p at %f %f", mLayer, mX, mY);
1561 }
1562
1563 virtual const char* name() { return "DrawLayer"; }
1564
1565private:
1566 Layer* mLayer;
1567 float mX;
1568 float mY;
1569};
1570
1571}; // namespace uirenderer
1572}; // namespace android
1573
1574#endif // ANDROID_HWUI_DISPLAY_OPERATION_H