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