• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2013 The Android Open Source Project
3  *
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 
20 #ifndef LOG_TAG
21     #define LOG_TAG "OpenGLRenderer"
22 #endif
23 
24 #include <SkColor.h>
25 #include <SkPath.h>
26 #include <SkPathOps.h>
27 #include <SkXfermode.h>
28 
29 #include <private/hwui/DrawGlInfo.h>
30 
31 #include "OpenGLRenderer.h"
32 #include "AssetAtlas.h"
33 #include "DeferredDisplayList.h"
34 #include "DisplayListRenderer.h"
35 #include "RenderState.h"
36 #include "UvMapper.h"
37 #include "utils/LinearAllocator.h"
38 
39 #define CRASH() do { \
40     *(int *)(uintptr_t) 0xbbadbeef = 0; \
41     ((void(*)())0)(); /* More reliable, but doesn't say BBADBEEF */ \
42 } while(false)
43 
44 // Use OP_LOG for logging with arglist, OP_LOGS if just printing char*
45 #define OP_LOGS(s) OP_LOG("%s", (s))
46 #define OP_LOG(s, ...) ALOGD( "%*s" s, level * 2, "", __VA_ARGS__ )
47 
48 namespace android {
49 namespace uirenderer {
50 
51 /**
52  * Structure for storing canvas operations when they are recorded into a DisplayList, so that they
53  * may be replayed to an OpenGLRenderer.
54  *
55  * To avoid individual memory allocations, DisplayListOps may only be allocated into a
56  * LinearAllocator's managed memory buffers.  Each pointer held by a DisplayListOp is either a
57  * pointer into memory also allocated in the LinearAllocator (mostly for text and float buffers) or
58  * references a externally refcounted object (Sk... and Skia... objects). ~DisplayListOp() is
59  * never called as LinearAllocators are simply discarded, so no memory management should be done in
60  * this class.
61  */
62 class DisplayListOp {
63 public:
64     // These objects should always be allocated with a LinearAllocator, and never destroyed/deleted.
65     // standard new() intentionally not implemented, and delete/deconstructor should never be used.
~DisplayListOp()66     virtual ~DisplayListOp() { CRASH(); }
delete(void * ptr)67     static void operator delete(void* ptr) { CRASH(); }
68     /** static void* operator new(size_t size); PURPOSELY OMITTED **/
new(size_t size,LinearAllocator & allocator)69     static void* operator new(size_t size, LinearAllocator& allocator) {
70         return allocator.alloc(size);
71     }
72 
73     enum OpLogFlag {
74         kOpLogFlag_Recurse = 0x1,
75         kOpLogFlag_JSON = 0x2 // TODO: add?
76     };
77 
78     virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
79             bool useQuickReject) = 0;
80 
81     virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level,
82             bool useQuickReject) = 0;
83 
84     virtual void output(int level, uint32_t logFlags = 0) const = 0;
85 
86     // NOTE: it would be nice to declare constants and overriding the implementation in each op to
87     // point at the constants, but that seems to require a .cpp file
88     virtual const char* name() = 0;
89 };
90 
91 class StateOp : public DisplayListOp {
92 public:
StateOp()93     StateOp() {};
94 
~StateOp()95     virtual ~StateOp() {}
96 
defer(DeferStateStruct & deferStruct,int saveCount,int level,bool useQuickReject)97     virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
98             bool useQuickReject) {
99         // default behavior only affects immediate, deferrable state, issue directly to renderer
100         applyState(deferStruct.mRenderer, saveCount);
101     }
102 
103     /**
104      * State operations are applied directly to the renderer, but can cause the deferred drawing op
105      * list to flush
106      */
replay(ReplayStateStruct & replayStruct,int saveCount,int level,bool useQuickReject)107     virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level,
108             bool useQuickReject) {
109         applyState(replayStruct.mRenderer, saveCount);
110     }
111 
112     virtual void applyState(OpenGLRenderer& renderer, int saveCount) const = 0;
113 };
114 
115 class DrawOp : public DisplayListOp {
116 friend class MergingDrawBatch;
117 public:
DrawOp(const SkPaint * paint)118     DrawOp(const SkPaint* paint)
119             : mPaint(paint), mQuickRejected(false) {}
120 
defer(DeferStateStruct & deferStruct,int saveCount,int level,bool useQuickReject)121     virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
122             bool useQuickReject) {
123         if (mQuickRejected && CC_LIKELY(useQuickReject)) {
124             return;
125         }
126 
127         deferStruct.mDeferredList.addDrawOp(deferStruct.mRenderer, this);
128     }
129 
replay(ReplayStateStruct & replayStruct,int saveCount,int level,bool useQuickReject)130     virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level,
131             bool useQuickReject) {
132         if (mQuickRejected && CC_LIKELY(useQuickReject)) {
133             return;
134         }
135 
136         replayStruct.mDrawGlStatus |= applyDraw(replayStruct.mRenderer, replayStruct.mDirty);
137     }
138 
139     virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) = 0;
140 
141     /**
142      * Draw multiple instances of an operation, must be overidden for operations that merge
143      *
144      * Currently guarantees certain similarities between ops (see MergingDrawBatch::canMergeWith),
145      * and pure translation transformations. Other guarantees of similarity should be enforced by
146      * reducing which operations are tagged as mergeable.
147      */
multiDraw(OpenGLRenderer & renderer,Rect & dirty,const Vector<OpStatePair> & ops,const Rect & bounds)148     virtual status_t multiDraw(OpenGLRenderer& renderer, Rect& dirty,
149             const Vector<OpStatePair>& ops, const Rect& bounds) {
150         status_t status = DrawGlInfo::kStatusDone;
151         for (unsigned int i = 0; i < ops.size(); i++) {
152             renderer.restoreDisplayState(*(ops[i].state), true);
153             status |= ops[i].op->applyDraw(renderer, dirty);
154         }
155         return status;
156     }
157 
158     /**
159      * When this method is invoked the state field is initialized to have the
160      * final rendering state. We can thus use it to process data as it will be
161      * used at draw time.
162      *
163      * Additionally, this method allows subclasses to provide defer-time preferences for batching
164      * and merging.
165      *
166      * if a subclass can set deferInfo.mergeable to true, it should implement multiDraw()
167      */
onDefer(OpenGLRenderer & renderer,DeferInfo & deferInfo,const DeferredDisplayState & state)168     virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
169             const DeferredDisplayState& state) {}
170 
171     /**
172      * Query the conservative, local bounds (unmapped) bounds of the op.
173      *
174      * returns true if bounds exist
175      */
getLocalBounds(Rect & localBounds)176     virtual bool getLocalBounds(Rect& localBounds) {
177         return false;
178     }
179 
180     // TODO: better refine localbounds usage
setQuickRejected(bool quickRejected)181     void setQuickRejected(bool quickRejected) { mQuickRejected = quickRejected; }
getQuickRejected()182     bool getQuickRejected() { return mQuickRejected; }
183 
getPaintAlpha()184     inline int getPaintAlpha() const {
185         return OpenGLRenderer::getAlphaDirect(mPaint);
186     }
187 
hasTextShadow()188     virtual bool hasTextShadow() const {
189         return false;
190     }
191 
strokeWidthOutset()192     inline float strokeWidthOutset() {
193         // since anything AA stroke with less than 1.0 pixel width is drawn with an alpha-reduced
194         // 1.0 stroke, treat 1.0 as minimum.
195 
196         // TODO: it would be nice if this could take scale into account, but scale isn't stable
197         // since higher levels of the view hierarchy can change scale out from underneath it.
198         return fmaxf(mPaint->getStrokeWidth(), 1) * 0.5f;
199     }
200 
201 protected:
getPaint(OpenGLRenderer & renderer)202     const SkPaint* getPaint(OpenGLRenderer& renderer) {
203         return renderer.filterPaint(mPaint);
204     }
205 
206     // Helper method for determining op opaqueness. Assumes op fills its bounds in local
207     // coordinates, and that paint's alpha is used
isOpaqueOverBounds(const DeferredDisplayState & state)208     inline bool isOpaqueOverBounds(const DeferredDisplayState& state) {
209         // ensure that local bounds cover mapped bounds
210         if (!state.mMatrix.isSimple()) return false;
211 
212         if (state.mRoundRectClipState) return false;
213 
214         // check state/paint for transparency
215         if (mPaint) {
216             if (mPaint->getAlpha() != 0xFF) {
217                 return false;
218             }
219             if (mPaint->getShader() && !mPaint->getShader()->isOpaque()) {
220                 return false;
221             }
222             if (Renderer::isBlendedColorFilter(mPaint->getColorFilter())) {
223                 return false;
224             }
225         }
226 
227         if (state.mAlpha != 1.0f) return false;
228 
229         SkXfermode::Mode mode = OpenGLRenderer::getXfermodeDirect(mPaint);
230         return (mode == SkXfermode::kSrcOver_Mode ||
231                 mode == SkXfermode::kSrc_Mode);
232 
233     }
234 
235     const SkPaint* mPaint; // should be accessed via getPaint() when applying
236     bool mQuickRejected;
237 };
238 
239 class DrawBoundedOp : public DrawOp {
240 public:
DrawBoundedOp(float left,float top,float right,float bottom,const SkPaint * paint)241     DrawBoundedOp(float left, float top, float right, float bottom, const SkPaint* paint)
242             : DrawOp(paint), mLocalBounds(left, top, right, bottom) {}
243 
DrawBoundedOp(const Rect & localBounds,const SkPaint * paint)244     DrawBoundedOp(const Rect& localBounds, const SkPaint* paint)
245             : DrawOp(paint), mLocalBounds(localBounds) {}
246 
247     // Calculates bounds as smallest rect encompassing all points
248     // NOTE: requires at least 1 vertex, and doesn't account for stroke size (should be handled in
249     // subclass' constructor)
DrawBoundedOp(const float * points,int count,const SkPaint * paint)250     DrawBoundedOp(const float* points, int count, const SkPaint* paint)
251             : DrawOp(paint), mLocalBounds(points[0], points[1], points[0], points[1]) {
252         for (int i = 2; i < count; i += 2) {
253             mLocalBounds.left = fminf(mLocalBounds.left, points[i]);
254             mLocalBounds.right = fmaxf(mLocalBounds.right, points[i]);
255             mLocalBounds.top = fminf(mLocalBounds.top, points[i + 1]);
256             mLocalBounds.bottom = fmaxf(mLocalBounds.bottom, points[i + 1]);
257         }
258     }
259 
260     // default empty constructor for bounds, to be overridden in child constructor body
DrawBoundedOp(const SkPaint * paint)261     DrawBoundedOp(const SkPaint* paint): DrawOp(paint) { }
262 
getLocalBounds(Rect & localBounds)263     virtual bool getLocalBounds(Rect& localBounds) {
264         localBounds.set(mLocalBounds);
265         OpenGLRenderer::TextShadow textShadow;
266         if (OpenGLRenderer::getTextShadow(mPaint, &textShadow)) {
267             Rect shadow(mLocalBounds);
268             shadow.translate(textShadow.dx, textShadow.dx);
269             shadow.outset(textShadow.radius);
270             localBounds.unionWith(shadow);
271         }
272         return true;
273     }
274 
275 protected:
276     Rect mLocalBounds; // displayed area in LOCAL coord. doesn't incorporate stroke, so check paint
277 };
278 
279 ///////////////////////////////////////////////////////////////////////////////
280 // STATE OPERATIONS - these may affect the state of the canvas/renderer, but do
281 //         not directly draw or alter output
282 ///////////////////////////////////////////////////////////////////////////////
283 
284 class SaveOp : public StateOp {
285 public:
SaveOp(int flags)286     SaveOp(int flags)
287             : mFlags(flags) {}
288 
defer(DeferStateStruct & deferStruct,int saveCount,int level,bool useQuickReject)289     virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
290             bool useQuickReject) {
291         int newSaveCount = deferStruct.mRenderer.save(mFlags);
292         deferStruct.mDeferredList.addSave(deferStruct.mRenderer, this, newSaveCount);
293     }
294 
applyState(OpenGLRenderer & renderer,int saveCount)295     virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
296         renderer.save(mFlags);
297     }
298 
output(int level,uint32_t logFlags)299     virtual void output(int level, uint32_t logFlags) const {
300         OP_LOG("Save flags %x", mFlags);
301     }
302 
name()303     virtual const char* name() { return "Save"; }
304 
getFlags()305     int getFlags() const { return mFlags; }
306 private:
307     int mFlags;
308 };
309 
310 class RestoreToCountOp : public StateOp {
311 public:
RestoreToCountOp(int count)312     RestoreToCountOp(int count)
313             : mCount(count) {}
314 
defer(DeferStateStruct & deferStruct,int saveCount,int level,bool useQuickReject)315     virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
316             bool useQuickReject) {
317         deferStruct.mDeferredList.addRestoreToCount(deferStruct.mRenderer,
318                 this, saveCount + mCount);
319         deferStruct.mRenderer.restoreToCount(saveCount + mCount);
320     }
321 
applyState(OpenGLRenderer & renderer,int saveCount)322     virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
323         renderer.restoreToCount(saveCount + mCount);
324     }
325 
output(int level,uint32_t logFlags)326     virtual void output(int level, uint32_t logFlags) const {
327         OP_LOG("Restore to count %d", mCount);
328     }
329 
name()330     virtual const char* name() { return "RestoreToCount"; }
331 
332 private:
333     int mCount;
334 };
335 
336 class SaveLayerOp : public StateOp {
337 public:
SaveLayerOp(float left,float top,float right,float bottom,int alpha,int flags)338     SaveLayerOp(float left, float top, float right, float bottom, int alpha, int flags)
339             : mArea(left, top, right, bottom)
340             , mPaint(&mCachedPaint)
341             , mFlags(flags)
342             , mConvexMask(NULL) {
343         mCachedPaint.setAlpha(alpha);
344     }
345 
SaveLayerOp(float left,float top,float right,float bottom,const SkPaint * paint,int flags)346     SaveLayerOp(float left, float top, float right, float bottom, const SkPaint* paint, int flags)
347             : mArea(left, top, right, bottom)
348             , mPaint(paint)
349             , mFlags(flags)
350             , mConvexMask(NULL)
351     {}
352 
defer(DeferStateStruct & deferStruct,int saveCount,int level,bool useQuickReject)353     virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
354             bool useQuickReject) {
355         // NOTE: don't bother with actual saveLayer, instead issuing it at flush time
356         int newSaveCount = deferStruct.mRenderer.getSaveCount();
357         deferStruct.mDeferredList.addSaveLayer(deferStruct.mRenderer, this, newSaveCount);
358 
359         // NOTE: don't issue full saveLayer, since that has side effects/is costly. instead just
360         // setup the snapshot for deferral, and re-issue the op at flush time
361         deferStruct.mRenderer.saveLayerDeferred(mArea.left, mArea.top, mArea.right, mArea.bottom,
362                 mPaint, mFlags);
363     }
364 
applyState(OpenGLRenderer & renderer,int saveCount)365     virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
366         renderer.saveLayer(mArea.left, mArea.top, mArea.right, mArea.bottom,
367                 mPaint, mFlags, mConvexMask);
368     }
369 
output(int level,uint32_t logFlags)370     virtual void output(int level, uint32_t logFlags) const {
371         OP_LOG("SaveLayer%s of area " RECT_STRING,
372                 (isSaveLayerAlpha() ? "Alpha" : ""),RECT_ARGS(mArea));
373     }
374 
name()375     virtual const char* name() { return isSaveLayerAlpha() ? "SaveLayerAlpha" : "SaveLayer"; }
376 
getFlags()377     int getFlags() { return mFlags; }
378 
379     // Called to make SaveLayerOp clip to the provided mask when drawing back/restored
setMask(const SkPath * convexMask)380     void setMask(const SkPath* convexMask) {
381         mConvexMask = convexMask;
382     }
383 
384 private:
isSaveLayerAlpha()385     bool isSaveLayerAlpha() const {
386         SkXfermode::Mode mode = OpenGLRenderer::getXfermodeDirect(mPaint);
387         int alpha = OpenGLRenderer::getAlphaDirect(mPaint);
388         return alpha < 255 && mode == SkXfermode::kSrcOver_Mode;
389     }
390 
391     Rect mArea;
392     const SkPaint* mPaint;
393     SkPaint mCachedPaint;
394     int mFlags;
395 
396     // Convex path, points at data in RenderNode, valid for the duration of the frame only
397     // Only used for masking the SaveLayer which wraps projected RenderNodes
398     const SkPath* mConvexMask;
399 };
400 
401 class TranslateOp : public StateOp {
402 public:
TranslateOp(float dx,float dy)403     TranslateOp(float dx, float dy)
404             : mDx(dx), mDy(dy) {}
405 
applyState(OpenGLRenderer & renderer,int saveCount)406     virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
407         renderer.translate(mDx, mDy);
408     }
409 
output(int level,uint32_t logFlags)410     virtual void output(int level, uint32_t logFlags) const {
411         OP_LOG("Translate by %f %f", mDx, mDy);
412     }
413 
name()414     virtual const char* name() { return "Translate"; }
415 
416 private:
417     float mDx;
418     float mDy;
419 };
420 
421 class RotateOp : public StateOp {
422 public:
RotateOp(float degrees)423     RotateOp(float degrees)
424             : mDegrees(degrees) {}
425 
applyState(OpenGLRenderer & renderer,int saveCount)426     virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
427         renderer.rotate(mDegrees);
428     }
429 
output(int level,uint32_t logFlags)430     virtual void output(int level, uint32_t logFlags) const {
431         OP_LOG("Rotate by %f degrees", mDegrees);
432     }
433 
name()434     virtual const char* name() { return "Rotate"; }
435 
436 private:
437     float mDegrees;
438 };
439 
440 class ScaleOp : public StateOp {
441 public:
ScaleOp(float sx,float sy)442     ScaleOp(float sx, float sy)
443             : mSx(sx), mSy(sy) {}
444 
applyState(OpenGLRenderer & renderer,int saveCount)445     virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
446         renderer.scale(mSx, mSy);
447     }
448 
output(int level,uint32_t logFlags)449     virtual void output(int level, uint32_t logFlags) const {
450         OP_LOG("Scale by %f %f", mSx, mSy);
451     }
452 
name()453     virtual const char* name() { return "Scale"; }
454 
455 private:
456     float mSx;
457     float mSy;
458 };
459 
460 class SkewOp : public StateOp {
461 public:
SkewOp(float sx,float sy)462     SkewOp(float sx, float sy)
463             : mSx(sx), mSy(sy) {}
464 
applyState(OpenGLRenderer & renderer,int saveCount)465     virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
466         renderer.skew(mSx, mSy);
467     }
468 
output(int level,uint32_t logFlags)469     virtual void output(int level, uint32_t logFlags) const {
470         OP_LOG("Skew by %f %f", mSx, mSy);
471     }
472 
name()473     virtual const char* name() { return "Skew"; }
474 
475 private:
476     float mSx;
477     float mSy;
478 };
479 
480 class SetMatrixOp : public StateOp {
481 public:
SetMatrixOp(const SkMatrix & matrix)482     SetMatrixOp(const SkMatrix& matrix)
483             : mMatrix(matrix) {}
484 
applyState(OpenGLRenderer & renderer,int saveCount)485     virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
486         renderer.setMatrix(mMatrix);
487     }
488 
output(int level,uint32_t logFlags)489     virtual void output(int level, uint32_t logFlags) const {
490         if (mMatrix.isIdentity()) {
491             OP_LOGS("SetMatrix (reset)");
492         } else {
493             OP_LOG("SetMatrix " SK_MATRIX_STRING, SK_MATRIX_ARGS(&mMatrix));
494         }
495     }
496 
name()497     virtual const char* name() { return "SetMatrix"; }
498 
499 private:
500     const SkMatrix mMatrix;
501 };
502 
503 class ConcatMatrixOp : public StateOp {
504 public:
ConcatMatrixOp(const SkMatrix & matrix)505     ConcatMatrixOp(const SkMatrix& matrix)
506             : mMatrix(matrix) {}
507 
applyState(OpenGLRenderer & renderer,int saveCount)508     virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
509         renderer.concatMatrix(mMatrix);
510     }
511 
output(int level,uint32_t logFlags)512     virtual void output(int level, uint32_t logFlags) const {
513         OP_LOG("ConcatMatrix " SK_MATRIX_STRING, SK_MATRIX_ARGS(&mMatrix));
514     }
515 
name()516     virtual const char* name() { return "ConcatMatrix"; }
517 
518 private:
519     const SkMatrix mMatrix;
520 };
521 
522 class ClipOp : public StateOp {
523 public:
ClipOp(SkRegion::Op op)524     ClipOp(SkRegion::Op op) : mOp(op) {}
525 
defer(DeferStateStruct & deferStruct,int saveCount,int level,bool useQuickReject)526     virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
527             bool useQuickReject) {
528         // NOTE: must defer op BEFORE applying state, since it may read clip
529         deferStruct.mDeferredList.addClip(deferStruct.mRenderer, this);
530 
531         // TODO: Can we avoid applying complex clips at defer time?
532         applyState(deferStruct.mRenderer, saveCount);
533     }
534 
canCauseComplexClip()535     bool canCauseComplexClip() {
536         return ((mOp != SkRegion::kIntersect_Op) && (mOp != SkRegion::kReplace_Op)) || !isRect();
537     }
538 
539 protected:
isRect()540     virtual bool isRect() { return false; }
541 
542     SkRegion::Op mOp;
543 };
544 
545 class ClipRectOp : public ClipOp {
546 public:
ClipRectOp(float left,float top,float right,float bottom,SkRegion::Op op)547     ClipRectOp(float left, float top, float right, float bottom, SkRegion::Op op)
548             : ClipOp(op), mArea(left, top, right, bottom) {}
549 
applyState(OpenGLRenderer & renderer,int saveCount)550     virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
551         renderer.clipRect(mArea.left, mArea.top, mArea.right, mArea.bottom, mOp);
552     }
553 
output(int level,uint32_t logFlags)554     virtual void output(int level, uint32_t logFlags) const {
555         OP_LOG("ClipRect " RECT_STRING, RECT_ARGS(mArea));
556     }
557 
name()558     virtual const char* name() { return "ClipRect"; }
559 
560 protected:
isRect()561     virtual bool isRect() { return true; }
562 
563 private:
564     Rect mArea;
565 };
566 
567 class ClipPathOp : public ClipOp {
568 public:
ClipPathOp(const SkPath * path,SkRegion::Op op)569     ClipPathOp(const SkPath* path, SkRegion::Op op)
570             : ClipOp(op), mPath(path) {}
571 
applyState(OpenGLRenderer & renderer,int saveCount)572     virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
573         renderer.clipPath(mPath, mOp);
574     }
575 
output(int level,uint32_t logFlags)576     virtual void output(int level, uint32_t logFlags) const {
577         SkRect bounds = mPath->getBounds();
578         OP_LOG("ClipPath bounds " RECT_STRING,
579                 bounds.left(), bounds.top(), bounds.right(), bounds.bottom());
580     }
581 
name()582     virtual const char* name() { return "ClipPath"; }
583 
584 private:
585     const SkPath* mPath;
586 };
587 
588 class ClipRegionOp : public ClipOp {
589 public:
ClipRegionOp(const SkRegion * region,SkRegion::Op op)590     ClipRegionOp(const SkRegion* region, SkRegion::Op op)
591             : ClipOp(op), mRegion(region) {}
592 
applyState(OpenGLRenderer & renderer,int saveCount)593     virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
594         renderer.clipRegion(mRegion, mOp);
595     }
596 
output(int level,uint32_t logFlags)597     virtual void output(int level, uint32_t logFlags) const {
598         SkIRect bounds = mRegion->getBounds();
599         OP_LOG("ClipRegion bounds %d %d %d %d",
600                 bounds.left(), bounds.top(), bounds.right(), bounds.bottom());
601     }
602 
name()603     virtual const char* name() { return "ClipRegion"; }
604 
605 private:
606     const SkRegion* mRegion;
607 };
608 
609 class ResetPaintFilterOp : public StateOp {
610 public:
applyState(OpenGLRenderer & renderer,int saveCount)611     virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
612         renderer.resetPaintFilter();
613     }
614 
output(int level,uint32_t logFlags)615     virtual void output(int level, uint32_t logFlags) const {
616         OP_LOGS("ResetPaintFilter");
617     }
618 
name()619     virtual const char* name() { return "ResetPaintFilter"; }
620 };
621 
622 class SetupPaintFilterOp : public StateOp {
623 public:
SetupPaintFilterOp(int clearBits,int setBits)624     SetupPaintFilterOp(int clearBits, int setBits)
625             : mClearBits(clearBits), mSetBits(setBits) {}
626 
applyState(OpenGLRenderer & renderer,int saveCount)627     virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
628         renderer.setupPaintFilter(mClearBits, mSetBits);
629     }
630 
output(int level,uint32_t logFlags)631     virtual void output(int level, uint32_t logFlags) const {
632         OP_LOG("SetupPaintFilter, clear %#x, set %#x", mClearBits, mSetBits);
633     }
634 
name()635     virtual const char* name() { return "SetupPaintFilter"; }
636 
637 private:
638     int mClearBits;
639     int mSetBits;
640 };
641 
642 ///////////////////////////////////////////////////////////////////////////////
643 // DRAW OPERATIONS - these are operations that can draw to the canvas's device
644 ///////////////////////////////////////////////////////////////////////////////
645 
646 class DrawBitmapOp : public DrawBoundedOp {
647 public:
DrawBitmapOp(const SkBitmap * bitmap,const SkPaint * paint)648     DrawBitmapOp(const SkBitmap* bitmap, const SkPaint* paint)
649             : DrawBoundedOp(0, 0, bitmap->width(), bitmap->height(), paint)
650             , mBitmap(bitmap)
651             , mEntryValid(false), mEntry(NULL) {
652     }
653 
applyDraw(OpenGLRenderer & renderer,Rect & dirty)654     virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
655         return renderer.drawBitmap(mBitmap, getPaint(renderer));
656     }
657 
getAtlasEntry(OpenGLRenderer & renderer)658     AssetAtlas::Entry* getAtlasEntry(OpenGLRenderer& renderer) {
659         if (!mEntryValid) {
660             mEntryValid = true;
661             mEntry = renderer.renderState().assetAtlas().getEntry(mBitmap);
662         }
663         return mEntry;
664     }
665 
666 #define SET_TEXTURE(ptr, posRect, offsetRect, texCoordsRect, xDim, yDim) \
667     TextureVertex::set(ptr++, posRect.xDim - offsetRect.left, posRect.yDim - offsetRect.top, \
668             texCoordsRect.xDim, texCoordsRect.yDim)
669 
670     /**
671      * This multi-draw operation builds a mesh on the stack by generating a quad
672      * for each bitmap in the batch. This method is also responsible for dirtying
673      * the current layer, if any.
674      */
multiDraw(OpenGLRenderer & renderer,Rect & dirty,const Vector<OpStatePair> & ops,const Rect & bounds)675     virtual status_t multiDraw(OpenGLRenderer& renderer, Rect& dirty,
676             const Vector<OpStatePair>& ops, const Rect& bounds) {
677         const DeferredDisplayState& firstState = *(ops[0].state);
678         renderer.restoreDisplayState(firstState, true); // restore all but the clip
679 
680         TextureVertex vertices[6 * ops.size()];
681         TextureVertex* vertex = &vertices[0];
682 
683         const bool hasLayer = renderer.hasLayer();
684         bool pureTranslate = true;
685 
686         // TODO: manually handle rect clip for bitmaps by adjusting texCoords per op,
687         // and allowing them to be merged in getBatchId()
688         for (unsigned int i = 0; i < ops.size(); i++) {
689             const DeferredDisplayState& state = *(ops[i].state);
690             const Rect& opBounds = state.mBounds;
691             // When we reach multiDraw(), the matrix can be either
692             // pureTranslate or simple (translate and/or scale).
693             // If the matrix is not pureTranslate, then we have a scale
694             pureTranslate &= state.mMatrix.isPureTranslate();
695 
696             Rect texCoords(0, 0, 1, 1);
697             ((DrawBitmapOp*) ops[i].op)->uvMap(renderer, texCoords);
698 
699             SET_TEXTURE(vertex, opBounds, bounds, texCoords, left, top);
700             SET_TEXTURE(vertex, opBounds, bounds, texCoords, right, top);
701             SET_TEXTURE(vertex, opBounds, bounds, texCoords, left, bottom);
702 
703             SET_TEXTURE(vertex, opBounds, bounds, texCoords, left, bottom);
704             SET_TEXTURE(vertex, opBounds, bounds, texCoords, right, top);
705             SET_TEXTURE(vertex, opBounds, bounds, texCoords, right, bottom);
706 
707             if (hasLayer) {
708                 renderer.dirtyLayer(opBounds.left, opBounds.top, opBounds.right, opBounds.bottom);
709             }
710         }
711 
712         return renderer.drawBitmaps(mBitmap, mEntry, ops.size(), &vertices[0],
713                 pureTranslate, bounds, mPaint);
714     }
715 
output(int level,uint32_t logFlags)716     virtual void output(int level, uint32_t logFlags) const {
717         OP_LOG("Draw bitmap %p at %f %f%s", mBitmap, mLocalBounds.left, mLocalBounds.top,
718                 mEntry ? " using AssetAtlas" : "");
719     }
720 
name()721     virtual const char* name() { return "DrawBitmap"; }
722 
onDefer(OpenGLRenderer & renderer,DeferInfo & deferInfo,const DeferredDisplayState & state)723     virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
724             const DeferredDisplayState& state) {
725         deferInfo.batchId = DeferredDisplayList::kOpBatch_Bitmap;
726         deferInfo.mergeId = getAtlasEntry(renderer) ?
727                 (mergeid_t) mEntry->getMergeId() : (mergeid_t) mBitmap;
728 
729         // Don't merge non-simply transformed or neg scale ops, SET_TEXTURE doesn't handle rotation
730         // 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
733         deferInfo.mergeable = state.mMatrix.isSimple() && state.mMatrix.positiveScale() &&
734                 !state.mClipSideFlags &&
735                 OpenGLRenderer::getXfermodeDirect(mPaint) == SkXfermode::kSrcOver_Mode &&
736                 (mBitmap->colorType() != kAlpha_8_SkColorType);
737     }
738 
uvMap(OpenGLRenderer & renderer,Rect & texCoords)739     void uvMap(OpenGLRenderer& renderer, Rect& texCoords) {
740         if (getAtlasEntry(renderer)) {
741             mEntry->uvMapper.map(texCoords);
742         }
743     }
744 
bitmap()745     const SkBitmap* bitmap() { return mBitmap; }
746 protected:
747     const SkBitmap* mBitmap;
748     bool mEntryValid;
749     AssetAtlas::Entry* mEntry;
750 };
751 
752 class DrawBitmapRectOp : public DrawBoundedOp {
753 public:
DrawBitmapRectOp(const SkBitmap * bitmap,float srcLeft,float srcTop,float srcRight,float srcBottom,float dstLeft,float dstTop,float dstRight,float dstBottom,const SkPaint * paint)754     DrawBitmapRectOp(const SkBitmap* bitmap,
755             float srcLeft, float srcTop, float srcRight, float srcBottom,
756             float dstLeft, float dstTop, float dstRight, float dstBottom, const SkPaint* paint)
757             : DrawBoundedOp(dstLeft, dstTop, dstRight, dstBottom, paint),
758             mBitmap(bitmap), mSrc(srcLeft, srcTop, srcRight, srcBottom) {}
759 
applyDraw(OpenGLRenderer & renderer,Rect & dirty)760     virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
761         return renderer.drawBitmap(mBitmap, mSrc.left, mSrc.top, mSrc.right, mSrc.bottom,
762                 mLocalBounds.left, mLocalBounds.top, mLocalBounds.right, mLocalBounds.bottom,
763                 getPaint(renderer));
764     }
765 
output(int level,uint32_t logFlags)766     virtual void output(int level, uint32_t logFlags) const {
767         OP_LOG("Draw bitmap %p src=" RECT_STRING ", dst=" RECT_STRING,
768                 mBitmap, RECT_ARGS(mSrc), RECT_ARGS(mLocalBounds));
769     }
770 
name()771     virtual const char* name() { return "DrawBitmapRect"; }
772 
onDefer(OpenGLRenderer & renderer,DeferInfo & deferInfo,const DeferredDisplayState & state)773     virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
774             const DeferredDisplayState& state) {
775         deferInfo.batchId = DeferredDisplayList::kOpBatch_Bitmap;
776     }
777 
778 private:
779     const SkBitmap* mBitmap;
780     Rect mSrc;
781 };
782 
783 class DrawBitmapDataOp : public DrawBitmapOp {
784 public:
DrawBitmapDataOp(const SkBitmap * bitmap,const SkPaint * paint)785     DrawBitmapDataOp(const SkBitmap* bitmap, const SkPaint* paint)
786             : DrawBitmapOp(bitmap, paint) {}
787 
applyDraw(OpenGLRenderer & renderer,Rect & dirty)788     virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
789         return renderer.drawBitmapData(mBitmap, getPaint(renderer));
790     }
791 
output(int level,uint32_t logFlags)792     virtual void output(int level, uint32_t logFlags) const {
793         OP_LOG("Draw bitmap %p", mBitmap);
794     }
795 
name()796     virtual const char* name() { return "DrawBitmapData"; }
797 
onDefer(OpenGLRenderer & renderer,DeferInfo & deferInfo,const DeferredDisplayState & state)798     virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
799             const DeferredDisplayState& state) {
800         deferInfo.batchId = DeferredDisplayList::kOpBatch_Bitmap;
801     }
802 };
803 
804 class DrawBitmapMeshOp : public DrawBoundedOp {
805 public:
DrawBitmapMeshOp(const SkBitmap * bitmap,int meshWidth,int meshHeight,const float * vertices,const int * colors,const SkPaint * paint)806     DrawBitmapMeshOp(const SkBitmap* bitmap, int meshWidth, int meshHeight,
807             const float* vertices, const int* colors, const SkPaint* paint)
808             : DrawBoundedOp(vertices, 2 * (meshWidth + 1) * (meshHeight + 1), paint),
809             mBitmap(bitmap), mMeshWidth(meshWidth), mMeshHeight(meshHeight),
810             mVertices(vertices), mColors(colors) {}
811 
applyDraw(OpenGLRenderer & renderer,Rect & dirty)812     virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
813         return renderer.drawBitmapMesh(mBitmap, mMeshWidth, mMeshHeight,
814                 mVertices, mColors, getPaint(renderer));
815     }
816 
output(int level,uint32_t logFlags)817     virtual void output(int level, uint32_t logFlags) const {
818         OP_LOG("Draw bitmap %p mesh %d x %d", mBitmap, mMeshWidth, mMeshHeight);
819     }
820 
name()821     virtual const char* name() { return "DrawBitmapMesh"; }
822 
onDefer(OpenGLRenderer & renderer,DeferInfo & deferInfo,const DeferredDisplayState & state)823     virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
824             const DeferredDisplayState& state) {
825         deferInfo.batchId = DeferredDisplayList::kOpBatch_Bitmap;
826     }
827 
828 private:
829     const SkBitmap* mBitmap;
830     int mMeshWidth;
831     int mMeshHeight;
832     const float* mVertices;
833     const int* mColors;
834 };
835 
836 class DrawPatchOp : public DrawBoundedOp {
837 public:
DrawPatchOp(const SkBitmap * bitmap,const Res_png_9patch * patch,float left,float top,float right,float bottom,const SkPaint * paint)838     DrawPatchOp(const SkBitmap* bitmap, const Res_png_9patch* patch,
839             float left, float top, float right, float bottom, const SkPaint* paint)
840             : DrawBoundedOp(left, top, right, bottom, paint),
841             mBitmap(bitmap), mPatch(patch), mGenerationId(0), mMesh(NULL),
842             mEntryValid(false), mEntry(NULL) {
843     };
844 
getAtlasEntry(OpenGLRenderer & renderer)845     AssetAtlas::Entry* getAtlasEntry(OpenGLRenderer& renderer) {
846         if (!mEntryValid) {
847             mEntryValid = true;
848             mEntry = renderer.renderState().assetAtlas().getEntry(mBitmap);
849         }
850         return mEntry;
851     }
852 
getMesh(OpenGLRenderer & renderer)853     const Patch* getMesh(OpenGLRenderer& renderer) {
854         if (!mMesh || renderer.getCaches().patchCache.getGenerationId() != mGenerationId) {
855             PatchCache& cache = renderer.getCaches().patchCache;
856             mMesh = cache.get(getAtlasEntry(renderer), mBitmap->width(), mBitmap->height(),
857                     mLocalBounds.getWidth(), mLocalBounds.getHeight(), mPatch);
858             mGenerationId = cache.getGenerationId();
859         }
860         return mMesh;
861     }
862 
863     /**
864      * This multi-draw operation builds an indexed mesh on the stack by copying
865      * and transforming the vertices of each 9-patch in the batch. This method
866      * is also responsible for dirtying the current layer, if any.
867      */
multiDraw(OpenGLRenderer & renderer,Rect & dirty,const Vector<OpStatePair> & ops,const Rect & bounds)868     virtual status_t multiDraw(OpenGLRenderer& renderer, Rect& dirty,
869             const Vector<OpStatePair>& ops, const Rect& bounds) {
870         const DeferredDisplayState& firstState = *(ops[0].state);
871         renderer.restoreDisplayState(firstState, true); // restore all but the clip
872 
873         // Batches will usually contain a small number of items so it's
874         // worth performing a first iteration to count the exact number
875         // of vertices we need in the new mesh
876         uint32_t totalVertices = 0;
877         for (unsigned int i = 0; i < ops.size(); i++) {
878             totalVertices += ((DrawPatchOp*) ops[i].op)->getMesh(renderer)->verticesCount;
879         }
880 
881         const bool hasLayer = renderer.hasLayer();
882 
883         uint32_t indexCount = 0;
884 
885         TextureVertex vertices[totalVertices];
886         TextureVertex* vertex = &vertices[0];
887 
888         // Create a mesh that contains the transformed vertices for all the
889         // 9-patch objects that are part of the batch. Note that onDefer()
890         // enforces ops drawn by this function to have a pure translate or
891         // identity matrix
892         for (unsigned int i = 0; i < ops.size(); i++) {
893             DrawPatchOp* patchOp = (DrawPatchOp*) ops[i].op;
894             const DeferredDisplayState* state = ops[i].state;
895             const Patch* opMesh = patchOp->getMesh(renderer);
896             uint32_t vertexCount = opMesh->verticesCount;
897             if (vertexCount == 0) continue;
898 
899             // We use the bounds to know where to translate our vertices
900             // Using patchOp->state.mBounds wouldn't work because these
901             // bounds are clipped
902             const float tx = (int) floorf(state->mMatrix.getTranslateX() +
903                     patchOp->mLocalBounds.left + 0.5f);
904             const float ty = (int) floorf(state->mMatrix.getTranslateY() +
905                     patchOp->mLocalBounds.top + 0.5f);
906 
907             // Copy & transform all the vertices for the current operation
908             TextureVertex* opVertices = opMesh->vertices;
909             for (uint32_t j = 0; j < vertexCount; j++, opVertices++) {
910                 TextureVertex::set(vertex++,
911                         opVertices->x + tx, opVertices->y + ty,
912                         opVertices->u, opVertices->v);
913             }
914 
915             // Dirty the current layer if possible. When the 9-patch does not
916             // contain empty quads we can take a shortcut and simply set the
917             // dirty rect to the object's bounds.
918             if (hasLayer) {
919                 if (!opMesh->hasEmptyQuads) {
920                     renderer.dirtyLayer(tx, ty,
921                             tx + patchOp->mLocalBounds.getWidth(),
922                             ty + patchOp->mLocalBounds.getHeight());
923                 } else {
924                     const size_t count = opMesh->quads.size();
925                     for (size_t i = 0; i < count; i++) {
926                         const Rect& quadBounds = opMesh->quads[i];
927                         const float x = tx + quadBounds.left;
928                         const float y = ty + quadBounds.top;
929                         renderer.dirtyLayer(x, y,
930                                 x + quadBounds.getWidth(), y + quadBounds.getHeight());
931                     }
932                 }
933             }
934 
935             indexCount += opMesh->indexCount;
936         }
937 
938         return renderer.drawPatches(mBitmap, getAtlasEntry(renderer),
939                 &vertices[0], indexCount, getPaint(renderer));
940     }
941 
applyDraw(OpenGLRenderer & renderer,Rect & dirty)942     virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
943         // We're not calling the public variant of drawPatch() here
944         // This method won't perform the quickReject() since we've already done it at this point
945         return renderer.drawPatch(mBitmap, getMesh(renderer), getAtlasEntry(renderer),
946                 mLocalBounds.left, mLocalBounds.top, mLocalBounds.right, mLocalBounds.bottom,
947                 getPaint(renderer));
948     }
949 
output(int level,uint32_t logFlags)950     virtual void output(int level, uint32_t logFlags) const {
951         OP_LOG("Draw patch " RECT_STRING "%s", RECT_ARGS(mLocalBounds),
952                 mEntry ? " with AssetAtlas" : "");
953     }
954 
name()955     virtual const char* name() { return "DrawPatch"; }
956 
onDefer(OpenGLRenderer & renderer,DeferInfo & deferInfo,const DeferredDisplayState & state)957     virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
958             const DeferredDisplayState& state) {
959         deferInfo.batchId = DeferredDisplayList::kOpBatch_Patch;
960         deferInfo.mergeId = getAtlasEntry(renderer) ? (mergeid_t) mEntry->getMergeId() : (mergeid_t) mBitmap;
961         deferInfo.mergeable = state.mMatrix.isPureTranslate() &&
962                 OpenGLRenderer::getXfermodeDirect(mPaint) == SkXfermode::kSrcOver_Mode;
963         deferInfo.opaqueOverBounds = isOpaqueOverBounds(state) && mBitmap->isOpaque();
964     }
965 
966 private:
967     const SkBitmap* mBitmap;
968     const Res_png_9patch* mPatch;
969 
970     uint32_t mGenerationId;
971     const Patch* mMesh;
972 
973     bool mEntryValid;
974     AssetAtlas::Entry* mEntry;
975 };
976 
977 class DrawColorOp : public DrawOp {
978 public:
DrawColorOp(int color,SkXfermode::Mode mode)979     DrawColorOp(int color, SkXfermode::Mode mode)
980             : DrawOp(NULL), mColor(color), mMode(mode) {};
981 
applyDraw(OpenGLRenderer & renderer,Rect & dirty)982     virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
983         return renderer.drawColor(mColor, mMode);
984     }
985 
output(int level,uint32_t logFlags)986     virtual void output(int level, uint32_t logFlags) const {
987         OP_LOG("Draw color %#x, mode %d", mColor, mMode);
988     }
989 
name()990     virtual const char* name() { return "DrawColor"; }
991 
992 private:
993     int mColor;
994     SkXfermode::Mode mMode;
995 };
996 
997 class DrawStrokableOp : public DrawBoundedOp {
998 public:
DrawStrokableOp(float left,float top,float right,float bottom,const SkPaint * paint)999     DrawStrokableOp(float left, float top, float right, float bottom, const SkPaint* paint)
1000             : DrawBoundedOp(left, top, right, bottom, paint) {};
DrawStrokableOp(const Rect & localBounds,const SkPaint * paint)1001     DrawStrokableOp(const Rect& localBounds, const SkPaint* paint)
1002             : DrawBoundedOp(localBounds, paint) {};
1003 
getLocalBounds(Rect & localBounds)1004     virtual bool getLocalBounds(Rect& localBounds) {
1005         localBounds.set(mLocalBounds);
1006         if (mPaint && mPaint->getStyle() != SkPaint::kFill_Style) {
1007             localBounds.outset(strokeWidthOutset());
1008         }
1009         return true;
1010     }
1011 
onDefer(OpenGLRenderer & renderer,DeferInfo & deferInfo,const DeferredDisplayState & state)1012     virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
1013             const DeferredDisplayState& state) {
1014         if (mPaint->getPathEffect()) {
1015             deferInfo.batchId = DeferredDisplayList::kOpBatch_AlphaMaskTexture;
1016         } else {
1017             deferInfo.batchId = mPaint->isAntiAlias() ?
1018                     DeferredDisplayList::kOpBatch_AlphaVertices :
1019                     DeferredDisplayList::kOpBatch_Vertices;
1020         }
1021     }
1022 };
1023 
1024 class DrawRectOp : public DrawStrokableOp {
1025 public:
DrawRectOp(float left,float top,float right,float bottom,const SkPaint * paint)1026     DrawRectOp(float left, float top, float right, float bottom, const SkPaint* paint)
1027             : DrawStrokableOp(left, top, right, bottom, paint) {}
1028 
applyDraw(OpenGLRenderer & renderer,Rect & dirty)1029     virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
1030         return renderer.drawRect(mLocalBounds.left, mLocalBounds.top,
1031                 mLocalBounds.right, mLocalBounds.bottom, getPaint(renderer));
1032     }
1033 
output(int level,uint32_t logFlags)1034     virtual void output(int level, uint32_t logFlags) const {
1035         OP_LOG("Draw Rect " RECT_STRING, RECT_ARGS(mLocalBounds));
1036     }
1037 
onDefer(OpenGLRenderer & renderer,DeferInfo & deferInfo,const DeferredDisplayState & state)1038     virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
1039             const DeferredDisplayState& state) {
1040         DrawStrokableOp::onDefer(renderer, deferInfo, state);
1041         deferInfo.opaqueOverBounds = isOpaqueOverBounds(state) &&
1042                 mPaint->getStyle() == SkPaint::kFill_Style;
1043     }
1044 
name()1045     virtual const char* name() { return "DrawRect"; }
1046 };
1047 
1048 class DrawRectsOp : public DrawBoundedOp {
1049 public:
DrawRectsOp(const float * rects,int count,const SkPaint * paint)1050     DrawRectsOp(const float* rects, int count, const SkPaint* paint)
1051             : DrawBoundedOp(rects, count, paint),
1052             mRects(rects), mCount(count) {}
1053 
applyDraw(OpenGLRenderer & renderer,Rect & dirty)1054     virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
1055         return renderer.drawRects(mRects, mCount, getPaint(renderer));
1056     }
1057 
output(int level,uint32_t logFlags)1058     virtual void output(int level, uint32_t logFlags) const {
1059         OP_LOG("Draw Rects count %d", mCount);
1060     }
1061 
name()1062     virtual const char* name() { return "DrawRects"; }
1063 
onDefer(OpenGLRenderer & renderer,DeferInfo & deferInfo,const DeferredDisplayState & state)1064     virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
1065             const DeferredDisplayState& state) {
1066         deferInfo.batchId = DeferredDisplayList::kOpBatch_Vertices;
1067     }
1068 
1069 private:
1070     const float* mRects;
1071     int mCount;
1072 };
1073 
1074 class DrawRoundRectOp : public DrawStrokableOp {
1075 public:
DrawRoundRectOp(float left,float top,float right,float bottom,float rx,float ry,const SkPaint * paint)1076     DrawRoundRectOp(float left, float top, float right, float bottom,
1077             float rx, float ry, const SkPaint* paint)
1078             : DrawStrokableOp(left, top, right, bottom, paint), mRx(rx), mRy(ry) {}
1079 
applyDraw(OpenGLRenderer & renderer,Rect & dirty)1080     virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
1081         return renderer.drawRoundRect(mLocalBounds.left, mLocalBounds.top,
1082                 mLocalBounds.right, mLocalBounds.bottom, mRx, mRy, getPaint(renderer));
1083     }
1084 
output(int level,uint32_t logFlags)1085     virtual void output(int level, uint32_t logFlags) const {
1086         OP_LOG("Draw RoundRect " RECT_STRING ", rx %f, ry %f", RECT_ARGS(mLocalBounds), mRx, mRy);
1087     }
1088 
onDefer(OpenGLRenderer & renderer,DeferInfo & deferInfo,const DeferredDisplayState & state)1089     virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
1090             const DeferredDisplayState& state) {
1091         DrawStrokableOp::onDefer(renderer, deferInfo, state);
1092         if (!mPaint->getPathEffect()) {
1093             renderer.getCaches().tessellationCache.precacheRoundRect(state.mMatrix, *mPaint,
1094                     mLocalBounds.getWidth(), mLocalBounds.getHeight(), mRx, mRy);
1095         }
1096     }
1097 
name()1098     virtual const char* name() { return "DrawRoundRect"; }
1099 
1100 private:
1101     float mRx;
1102     float mRy;
1103 };
1104 
1105 class DrawRoundRectPropsOp : public DrawOp {
1106 public:
DrawRoundRectPropsOp(float * left,float * top,float * right,float * bottom,float * rx,float * ry,const SkPaint * paint)1107     DrawRoundRectPropsOp(float* left, float* top, float* right, float* bottom,
1108             float *rx, float *ry, const SkPaint* paint)
1109             : DrawOp(paint), mLeft(left), mTop(top), mRight(right), mBottom(bottom),
1110             mRx(rx), mRy(ry) {}
1111 
applyDraw(OpenGLRenderer & renderer,Rect & dirty)1112     virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
1113         return renderer.drawRoundRect(*mLeft, *mTop, *mRight, *mBottom,
1114                 *mRx, *mRy, getPaint(renderer));
1115     }
1116 
output(int level,uint32_t logFlags)1117     virtual void output(int level, uint32_t logFlags) const {
1118         OP_LOG("Draw RoundRect Props " RECT_STRING ", rx %f, ry %f",
1119                 *mLeft, *mTop, *mRight, *mBottom, *mRx, *mRy);
1120     }
1121 
name()1122     virtual const char* name() { return "DrawRoundRectProps"; }
1123 
1124 private:
1125     float* mLeft;
1126     float* mTop;
1127     float* mRight;
1128     float* mBottom;
1129     float* mRx;
1130     float* mRy;
1131 };
1132 
1133 class DrawCircleOp : public DrawStrokableOp {
1134 public:
DrawCircleOp(float x,float y,float radius,const SkPaint * paint)1135     DrawCircleOp(float x, float y, float radius, const SkPaint* paint)
1136             : DrawStrokableOp(x - radius, y - radius, x + radius, y + radius, paint),
1137             mX(x), mY(y), mRadius(radius) {}
1138 
applyDraw(OpenGLRenderer & renderer,Rect & dirty)1139     virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
1140         return renderer.drawCircle(mX, mY, mRadius, getPaint(renderer));
1141     }
1142 
output(int level,uint32_t logFlags)1143     virtual void output(int level, uint32_t logFlags) const {
1144         OP_LOG("Draw Circle x %f, y %f, r %f", mX, mY, mRadius);
1145     }
1146 
name()1147     virtual const char* name() { return "DrawCircle"; }
1148 
1149 private:
1150     float mX;
1151     float mY;
1152     float mRadius;
1153 };
1154 
1155 class DrawCirclePropsOp : public DrawOp {
1156 public:
DrawCirclePropsOp(float * x,float * y,float * radius,const SkPaint * paint)1157     DrawCirclePropsOp(float* x, float* y, float* radius, const SkPaint* paint)
1158             : DrawOp(paint), mX(x), mY(y), mRadius(radius) {}
1159 
applyDraw(OpenGLRenderer & renderer,Rect & dirty)1160     virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
1161         return renderer.drawCircle(*mX, *mY, *mRadius, getPaint(renderer));
1162     }
1163 
output(int level,uint32_t logFlags)1164     virtual void output(int level, uint32_t logFlags) const {
1165         OP_LOG("Draw Circle Props x %p, y %p, r %p", mX, mY, mRadius);
1166     }
1167 
name()1168     virtual const char* name() { return "DrawCircleProps"; }
1169 
1170 private:
1171     float* mX;
1172     float* mY;
1173     float* mRadius;
1174 };
1175 
1176 class DrawOvalOp : public DrawStrokableOp {
1177 public:
DrawOvalOp(float left,float top,float right,float bottom,const SkPaint * paint)1178     DrawOvalOp(float left, float top, float right, float bottom, const SkPaint* paint)
1179             : DrawStrokableOp(left, top, right, bottom, paint) {}
1180 
applyDraw(OpenGLRenderer & renderer,Rect & dirty)1181     virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
1182         return renderer.drawOval(mLocalBounds.left, mLocalBounds.top,
1183                 mLocalBounds.right, mLocalBounds.bottom, getPaint(renderer));
1184     }
1185 
output(int level,uint32_t logFlags)1186     virtual void output(int level, uint32_t logFlags) const {
1187         OP_LOG("Draw Oval " RECT_STRING, RECT_ARGS(mLocalBounds));
1188     }
1189 
name()1190     virtual const char* name() { return "DrawOval"; }
1191 };
1192 
1193 class DrawArcOp : public DrawStrokableOp {
1194 public:
DrawArcOp(float left,float top,float right,float bottom,float startAngle,float sweepAngle,bool useCenter,const SkPaint * paint)1195     DrawArcOp(float left, float top, float right, float bottom,
1196             float startAngle, float sweepAngle, bool useCenter, const SkPaint* paint)
1197             : DrawStrokableOp(left, top, right, bottom, paint),
1198             mStartAngle(startAngle), mSweepAngle(sweepAngle), mUseCenter(useCenter) {}
1199 
applyDraw(OpenGLRenderer & renderer,Rect & dirty)1200     virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
1201         return renderer.drawArc(mLocalBounds.left, mLocalBounds.top,
1202                 mLocalBounds.right, mLocalBounds.bottom,
1203                 mStartAngle, mSweepAngle, mUseCenter, getPaint(renderer));
1204     }
1205 
output(int level,uint32_t logFlags)1206     virtual void output(int level, uint32_t logFlags) const {
1207         OP_LOG("Draw Arc " RECT_STRING ", start %f, sweep %f, useCenter %d",
1208                 RECT_ARGS(mLocalBounds), mStartAngle, mSweepAngle, mUseCenter);
1209     }
1210 
name()1211     virtual const char* name() { return "DrawArc"; }
1212 
1213 private:
1214     float mStartAngle;
1215     float mSweepAngle;
1216     bool mUseCenter;
1217 };
1218 
1219 class DrawPathOp : public DrawBoundedOp {
1220 public:
DrawPathOp(const SkPath * path,const SkPaint * paint)1221     DrawPathOp(const SkPath* path, const SkPaint* paint)
1222             : DrawBoundedOp(paint), mPath(path) {
1223         float left, top, offset;
1224         uint32_t width, height;
1225         PathCache::computePathBounds(path, paint, left, top, offset, width, height);
1226         left -= offset;
1227         top -= offset;
1228         mLocalBounds.set(left, top, left + width, top + height);
1229     }
1230 
applyDraw(OpenGLRenderer & renderer,Rect & dirty)1231     virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
1232         return renderer.drawPath(mPath, getPaint(renderer));
1233     }
1234 
onDefer(OpenGLRenderer & renderer,DeferInfo & deferInfo,const DeferredDisplayState & state)1235     virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
1236             const DeferredDisplayState& state) {
1237         const SkPaint* paint = getPaint(renderer);
1238         renderer.getCaches().pathCache.precache(mPath, paint);
1239 
1240         deferInfo.batchId = DeferredDisplayList::kOpBatch_AlphaMaskTexture;
1241     }
1242 
output(int level,uint32_t logFlags)1243     virtual void output(int level, uint32_t logFlags) const {
1244         OP_LOG("Draw Path %p in " RECT_STRING, mPath, RECT_ARGS(mLocalBounds));
1245     }
1246 
name()1247     virtual const char* name() { return "DrawPath"; }
1248 
1249 private:
1250     const SkPath* mPath;
1251 };
1252 
1253 class DrawLinesOp : public DrawBoundedOp {
1254 public:
DrawLinesOp(const float * points,int count,const SkPaint * paint)1255     DrawLinesOp(const float* points, int count, const SkPaint* paint)
1256             : DrawBoundedOp(points, count, paint),
1257             mPoints(points), mCount(count) {
1258         mLocalBounds.outset(strokeWidthOutset());
1259     }
1260 
applyDraw(OpenGLRenderer & renderer,Rect & dirty)1261     virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
1262         return renderer.drawLines(mPoints, mCount, getPaint(renderer));
1263     }
1264 
output(int level,uint32_t logFlags)1265     virtual void output(int level, uint32_t logFlags) const {
1266         OP_LOG("Draw Lines count %d", mCount);
1267     }
1268 
name()1269     virtual const char* name() { return "DrawLines"; }
1270 
onDefer(OpenGLRenderer & renderer,DeferInfo & deferInfo,const DeferredDisplayState & state)1271     virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
1272             const DeferredDisplayState& state) {
1273         deferInfo.batchId = mPaint->isAntiAlias() ?
1274                 DeferredDisplayList::kOpBatch_AlphaVertices :
1275                 DeferredDisplayList::kOpBatch_Vertices;
1276     }
1277 
1278 protected:
1279     const float* mPoints;
1280     int mCount;
1281 };
1282 
1283 class DrawPointsOp : public DrawLinesOp {
1284 public:
DrawPointsOp(const float * points,int count,const SkPaint * paint)1285     DrawPointsOp(const float* points, int count, const SkPaint* paint)
1286             : DrawLinesOp(points, count, paint) {}
1287 
applyDraw(OpenGLRenderer & renderer,Rect & dirty)1288     virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
1289         return renderer.drawPoints(mPoints, mCount, getPaint(renderer));
1290     }
1291 
output(int level,uint32_t logFlags)1292     virtual void output(int level, uint32_t logFlags) const {
1293         OP_LOG("Draw Points count %d", mCount);
1294     }
1295 
name()1296     virtual const char* name() { return "DrawPoints"; }
1297 };
1298 
1299 class DrawSomeTextOp : public DrawOp {
1300 public:
DrawSomeTextOp(const char * text,int bytesCount,int count,const SkPaint * paint)1301     DrawSomeTextOp(const char* text, int bytesCount, int count, const SkPaint* paint)
1302             : DrawOp(paint), mText(text), mBytesCount(bytesCount), mCount(count) {};
1303 
output(int level,uint32_t logFlags)1304     virtual void output(int level, uint32_t logFlags) const {
1305         OP_LOG("Draw some text, %d bytes", mBytesCount);
1306     }
1307 
hasTextShadow()1308     virtual bool hasTextShadow() const {
1309         return OpenGLRenderer::hasTextShadow(mPaint);
1310     }
1311 
onDefer(OpenGLRenderer & renderer,DeferInfo & deferInfo,const DeferredDisplayState & state)1312     virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
1313             const DeferredDisplayState& state) {
1314         const SkPaint* paint = getPaint(renderer);
1315         FontRenderer& fontRenderer = renderer.getCaches().fontRenderer->getFontRenderer(paint);
1316         fontRenderer.precache(paint, mText, mCount, SkMatrix::I());
1317 
1318         deferInfo.batchId = mPaint->getColor() == SK_ColorBLACK ?
1319                 DeferredDisplayList::kOpBatch_Text :
1320                 DeferredDisplayList::kOpBatch_ColorText;
1321     }
1322 
1323 protected:
1324     const char* mText;
1325     int mBytesCount;
1326     int mCount;
1327 };
1328 
1329 class DrawTextOnPathOp : public DrawSomeTextOp {
1330 public:
DrawTextOnPathOp(const char * text,int bytesCount,int count,const SkPath * path,float hOffset,float vOffset,const SkPaint * paint)1331     DrawTextOnPathOp(const char* text, int bytesCount, int count,
1332             const SkPath* path, float hOffset, float vOffset, const SkPaint* paint)
1333             : DrawSomeTextOp(text, bytesCount, count, paint),
1334             mPath(path), mHOffset(hOffset), mVOffset(vOffset) {
1335         /* TODO: inherit from DrawBounded and init mLocalBounds */
1336     }
1337 
applyDraw(OpenGLRenderer & renderer,Rect & dirty)1338     virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
1339         return renderer.drawTextOnPath(mText, mBytesCount, mCount, mPath,
1340                 mHOffset, mVOffset, getPaint(renderer));
1341     }
1342 
name()1343     virtual const char* name() { return "DrawTextOnPath"; }
1344 
1345 private:
1346     const SkPath* mPath;
1347     float mHOffset;
1348     float mVOffset;
1349 };
1350 
1351 class DrawPosTextOp : public DrawSomeTextOp {
1352 public:
DrawPosTextOp(const char * text,int bytesCount,int count,const float * positions,const SkPaint * paint)1353     DrawPosTextOp(const char* text, int bytesCount, int count,
1354             const float* positions, const SkPaint* paint)
1355             : DrawSomeTextOp(text, bytesCount, count, paint), mPositions(positions) {
1356         /* TODO: inherit from DrawBounded and init mLocalBounds */
1357     }
1358 
applyDraw(OpenGLRenderer & renderer,Rect & dirty)1359     virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
1360         return renderer.drawPosText(mText, mBytesCount, mCount, mPositions, getPaint(renderer));
1361     }
1362 
name()1363     virtual const char* name() { return "DrawPosText"; }
1364 
1365 private:
1366     const float* mPositions;
1367 };
1368 
1369 class DrawTextOp : public DrawStrokableOp {
1370 public:
DrawTextOp(const char * text,int bytesCount,int count,float x,float y,const float * positions,const SkPaint * paint,float totalAdvance,const Rect & bounds)1371     DrawTextOp(const char* text, int bytesCount, int count, float x, float y,
1372             const float* positions, const SkPaint* paint, float totalAdvance, const Rect& bounds)
1373             : DrawStrokableOp(bounds, paint), mText(text), mBytesCount(bytesCount), mCount(count),
1374             mX(x), mY(y), mPositions(positions), mTotalAdvance(totalAdvance) {
1375         mPrecacheTransform = SkMatrix::InvalidMatrix();
1376     }
1377 
onDefer(OpenGLRenderer & renderer,DeferInfo & deferInfo,const DeferredDisplayState & state)1378     virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
1379             const DeferredDisplayState& state) {
1380         const SkPaint* paint = getPaint(renderer);
1381         FontRenderer& fontRenderer = renderer.getCaches().fontRenderer->getFontRenderer(paint);
1382         SkMatrix transform;
1383         renderer.findBestFontTransform(state.mMatrix, &transform);
1384         if (mPrecacheTransform != transform) {
1385             fontRenderer.precache(paint, mText, mCount, transform);
1386             mPrecacheTransform = transform;
1387         }
1388         deferInfo.batchId = mPaint->getColor() == SK_ColorBLACK ?
1389                 DeferredDisplayList::kOpBatch_Text :
1390                 DeferredDisplayList::kOpBatch_ColorText;
1391 
1392         deferInfo.mergeId = reinterpret_cast<mergeid_t>(mPaint->getColor());
1393 
1394         // don't merge decorated text - the decorations won't draw in order
1395         bool hasDecorations = mPaint->getFlags()
1396                 & (SkPaint::kUnderlineText_Flag | SkPaint::kStrikeThruText_Flag);
1397 
1398         deferInfo.mergeable = state.mMatrix.isPureTranslate()
1399                 && !hasDecorations
1400                 && OpenGLRenderer::getXfermodeDirect(mPaint) == SkXfermode::kSrcOver_Mode;
1401     }
1402 
applyDraw(OpenGLRenderer & renderer,Rect & dirty)1403     virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
1404         Rect bounds;
1405         getLocalBounds(bounds);
1406         return renderer.drawText(mText, mBytesCount, mCount, mX, mY,
1407                 mPositions, getPaint(renderer), mTotalAdvance, bounds);
1408     }
1409 
multiDraw(OpenGLRenderer & renderer,Rect & dirty,const Vector<OpStatePair> & ops,const Rect & bounds)1410     virtual status_t multiDraw(OpenGLRenderer& renderer, Rect& dirty,
1411             const Vector<OpStatePair>& ops, const Rect& bounds) {
1412         status_t status = DrawGlInfo::kStatusDone;
1413         for (unsigned int i = 0; i < ops.size(); i++) {
1414             const DeferredDisplayState& state = *(ops[i].state);
1415             DrawOpMode drawOpMode = (i == ops.size() - 1) ? kDrawOpMode_Flush : kDrawOpMode_Defer;
1416             renderer.restoreDisplayState(state, true); // restore all but the clip
1417 
1418             DrawTextOp& op = *((DrawTextOp*)ops[i].op);
1419             // quickReject() will not occure in drawText() so we can use mLocalBounds
1420             // directly, we do not need to account for shadow by calling getLocalBounds()
1421             status |= renderer.drawText(op.mText, op.mBytesCount, op.mCount, op.mX, op.mY,
1422                     op.mPositions, op.getPaint(renderer), op.mTotalAdvance, op.mLocalBounds,
1423                     drawOpMode);
1424         }
1425         return status;
1426     }
1427 
output(int level,uint32_t logFlags)1428     virtual void output(int level, uint32_t logFlags) const {
1429         OP_LOG("Draw Text of count %d, bytes %d", mCount, mBytesCount);
1430     }
1431 
name()1432     virtual const char* name() { return "DrawText"; }
1433 
1434 private:
1435     const char* mText;
1436     int mBytesCount;
1437     int mCount;
1438     float mX;
1439     float mY;
1440     const float* mPositions;
1441     float mTotalAdvance;
1442     SkMatrix mPrecacheTransform;
1443 };
1444 
1445 ///////////////////////////////////////////////////////////////////////////////
1446 // SPECIAL DRAW OPERATIONS
1447 ///////////////////////////////////////////////////////////////////////////////
1448 
1449 class DrawFunctorOp : public DrawOp {
1450 public:
DrawFunctorOp(Functor * functor)1451     DrawFunctorOp(Functor* functor)
1452             : DrawOp(NULL), mFunctor(functor) {}
1453 
applyDraw(OpenGLRenderer & renderer,Rect & dirty)1454     virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
1455         renderer.startMark("GL functor");
1456         status_t ret = renderer.callDrawGLFunction(mFunctor, dirty);
1457         renderer.endMark();
1458         return ret;
1459     }
1460 
output(int level,uint32_t logFlags)1461     virtual void output(int level, uint32_t logFlags) const {
1462         OP_LOG("Draw Functor %p", mFunctor);
1463     }
1464 
name()1465     virtual const char* name() { return "DrawFunctor"; }
1466 
1467 private:
1468     Functor* mFunctor;
1469 };
1470 
1471 class DrawRenderNodeOp : public DrawBoundedOp {
1472     friend class RenderNode; // grant RenderNode access to info of child
1473     friend class DisplayListData; // grant DisplayListData access to info of child
1474 public:
DrawRenderNodeOp(RenderNode * renderNode,int flags,const mat4 & transformFromParent)1475     DrawRenderNodeOp(RenderNode* renderNode, int flags, const mat4& transformFromParent)
1476             : DrawBoundedOp(0, 0, renderNode->getWidth(), renderNode->getHeight(), 0),
1477             mRenderNode(renderNode), mFlags(flags), mTransformFromParent(transformFromParent) {}
1478 
defer(DeferStateStruct & deferStruct,int saveCount,int level,bool useQuickReject)1479     virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
1480             bool useQuickReject) {
1481         if (mRenderNode->isRenderable() && !mSkipInOrderDraw) {
1482             mRenderNode->defer(deferStruct, level + 1);
1483         }
1484     }
1485 
replay(ReplayStateStruct & replayStruct,int saveCount,int level,bool useQuickReject)1486     virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level,
1487             bool useQuickReject) {
1488         if (mRenderNode->isRenderable() && !mSkipInOrderDraw) {
1489             mRenderNode->replay(replayStruct, level + 1);
1490         }
1491     }
1492 
applyDraw(OpenGLRenderer & renderer,Rect & dirty)1493     virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
1494         LOG_ALWAYS_FATAL("should not be called, because replay() is overridden");
1495         return 0;
1496     }
1497 
output(int level,uint32_t logFlags)1498     virtual void output(int level, uint32_t logFlags) const {
1499         OP_LOG("Draw RenderNode %p %s, flags %#x", mRenderNode, mRenderNode->getName(), mFlags);
1500         if (mRenderNode && (logFlags & kOpLogFlag_Recurse)) {
1501             mRenderNode->output(level + 1);
1502         }
1503     }
1504 
name()1505     virtual const char* name() { return "DrawRenderNode"; }
1506 
renderNode()1507     RenderNode* renderNode() { return mRenderNode; }
1508 
1509 private:
1510     RenderNode* mRenderNode;
1511     const int mFlags;
1512 
1513     ///////////////////////////
1514     // Properties below are used by RenderNode::computeOrderingImpl() and issueOperations()
1515     ///////////////////////////
1516     /**
1517      * Records transform vs parent, used for computing total transform without rerunning DL contents
1518      */
1519     const mat4 mTransformFromParent;
1520 
1521     /**
1522      * Holds the transformation between the projection surface ViewGroup and this RenderNode
1523      * drawing instance. Represents any translations / transformations done within the drawing of
1524      * the compositing ancestor ViewGroup's draw, before the draw of the View represented by this
1525      * DisplayList draw instance.
1526      *
1527      * Note: doesn't include transformation within the RenderNode, or its properties.
1528      */
1529     mat4 mTransformFromCompositingAncestor;
1530     bool mSkipInOrderDraw;
1531 };
1532 
1533 /**
1534  * Not a canvas operation, used only by 3d / z ordering logic in RenderNode::iterate()
1535  */
1536 class DrawShadowOp : public DrawOp {
1537 public:
DrawShadowOp(const mat4 & transformXY,const mat4 & transformZ,float casterAlpha,const SkPath * casterOutline)1538     DrawShadowOp(const mat4& transformXY, const mat4& transformZ,
1539             float casterAlpha, const SkPath* casterOutline)
1540         : DrawOp(NULL)
1541         , mTransformXY(transformXY)
1542         , mTransformZ(transformZ)
1543         , mCasterAlpha(casterAlpha)
1544         , mCasterOutline(casterOutline) {
1545     }
1546 
onDefer(OpenGLRenderer & renderer,DeferInfo & deferInfo,const DeferredDisplayState & state)1547     virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
1548             const DeferredDisplayState& state) {
1549         renderer.getCaches().tessellationCache.precacheShadows(&state.mMatrix,
1550                 renderer.getLocalClipBounds(), isCasterOpaque(), mCasterOutline,
1551                 &mTransformXY, &mTransformZ, renderer.getLightCenter(), renderer.getLightRadius());
1552     }
1553 
applyDraw(OpenGLRenderer & renderer,Rect & dirty)1554     virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
1555         TessellationCache::vertexBuffer_pair_t buffers;
1556         Matrix4 drawTransform(*(renderer.currentTransform()));
1557         renderer.getCaches().tessellationCache.getShadowBuffers(&drawTransform,
1558                 renderer.getLocalClipBounds(), isCasterOpaque(), mCasterOutline,
1559                 &mTransformXY, &mTransformZ, renderer.getLightCenter(), renderer.getLightRadius(),
1560                 buffers);
1561 
1562         return renderer.drawShadow(mCasterAlpha, buffers.first, buffers.second);
1563     }
1564 
output(int level,uint32_t logFlags)1565     virtual void output(int level, uint32_t logFlags) const {
1566         OP_LOGS("DrawShadow");
1567     }
1568 
name()1569     virtual const char* name() { return "DrawShadow"; }
1570 
1571 private:
isCasterOpaque()1572     bool isCasterOpaque() { return mCasterAlpha >= 1.0f; }
1573 
1574     const mat4 mTransformXY;
1575     const mat4 mTransformZ;
1576     const float mCasterAlpha;
1577     const SkPath* mCasterOutline;
1578 };
1579 
1580 class DrawLayerOp : public DrawOp {
1581 public:
DrawLayerOp(Layer * layer,float x,float y)1582     DrawLayerOp(Layer* layer, float x, float y)
1583             : DrawOp(NULL), mLayer(layer), mX(x), mY(y) {}
1584 
applyDraw(OpenGLRenderer & renderer,Rect & dirty)1585     virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
1586         return renderer.drawLayer(mLayer, mX, mY);
1587     }
1588 
output(int level,uint32_t logFlags)1589     virtual void output(int level, uint32_t logFlags) const {
1590         OP_LOG("Draw Layer %p at %f %f", mLayer, mX, mY);
1591     }
1592 
name()1593     virtual const char* name() { return "DrawLayer"; }
1594 
1595 private:
1596     Layer* mLayer;
1597     float mX;
1598     float mY;
1599 };
1600 
1601 }; // namespace uirenderer
1602 }; // namespace android
1603 
1604 #endif // ANDROID_HWUI_DISPLAY_OPERATION_H
1605